[Cmake-commits] CMake branch, master, updated. v3.15.0-rc2-103-gfe11593

Kitware Robot kwrobot at kitware.com
Thu Jun 20 11:43:06 EDT 2019


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, master has been updated
       via  fe11593d3075c6bd7f425c55c7bfbb12b25f8b1f (commit)
       via  d94d54966803c579c0139531bfa1282896572008 (commit)
       via  036752cc0e5f98a611c23c044e3bc1b484b02f53 (commit)
       via  db4667cc727fd7e52f6731642501e680922f72e7 (commit)
       via  cee57246ef03ba5c2a6e67b472d2d1f8946c4f75 (commit)
       via  69b139cfca6c5eef64558070f533b6c898f410e0 (commit)
       via  b4069b04ff63b327ff4881282200c3c73fded34d (commit)
      from  282fa97a45f19356260e73dbe26ae4b1d2501a07 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fe11593d3075c6bd7f425c55c7bfbb12b25f8b1f
commit fe11593d3075c6bd7f425c55c7bfbb12b25f8b1f
Merge: d94d549 db4667c
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jun 20 15:42:40 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Thu Jun 20 11:42:49 2019 -0400

    Merge topic 'update-libuv'
    
    db4667cc72 libuv: fix compilation with macOS 10.10 SDK
    cee57246ef libuv: Add uv__statx() stub to cmake-bootstrap.c
    69b139cfca Merge branch 'upstream-libuv' into update-libuv
    b4069b04ff libuv 2019-06-10 (ee24ce90)
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3457


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d94d54966803c579c0139531bfa1282896572008
commit d94d54966803c579c0139531bfa1282896572008
Merge: 282fa97 036752c
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jun 20 11:42:10 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Jun 20 11:42:10 2019 -0400

    Merge branch 'release-3.15'


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=db4667cc727fd7e52f6731642501e680922f72e7
commit db4667cc727fd7e52f6731642501e680922f72e7
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed Jun 19 06:52:19 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Jun 19 06:57:38 2019 -0400

    libuv: fix compilation with macOS 10.10 SDK
    
    The `F_BARRIERFSYNC` constant was not added until the macOS 10.11 SDK.
    Hard-code its value instead.  This approach is backported from upstream
    libuv PR 2334.

diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c
index 48500ff..3023b1e 100644
--- a/Utilities/cmlibuv/src/unix/fs.c
+++ b/Utilities/cmlibuv/src/unix/fs.c
@@ -168,7 +168,7 @@ static ssize_t uv__fs_fsync(uv_fs_t* req) {
 
   r = fcntl(req->file, F_FULLFSYNC);
   if (r != 0)
-    r = fcntl(req->file, F_BARRIERFSYNC);  /* fsync + barrier */
+    r = fcntl(req->file, 85 /* F_BARRIERFSYNC */);  /* fsync + barrier */
   if (r != 0)
     r = fsync(req->file);
   return r;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cee57246ef03ba5c2a6e67b472d2d1f8946c4f75
commit cee57246ef03ba5c2a6e67b472d2d1f8946c4f75
Author:     Kyle Edwards <kyle.edwards at kitware.com>
AuthorDate: Mon Jun 17 15:48:48 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Jun 18 07:46:08 2019 -0400

    libuv: Add uv__statx() stub to cmake-bootstrap.c

diff --git a/Utilities/cmlibuv/src/unix/cmake-bootstrap.c b/Utilities/cmlibuv/src/unix/cmake-bootstrap.c
index 309ec79..d42ff05 100644
--- a/Utilities/cmlibuv/src/unix/cmake-bootstrap.c
+++ b/Utilities/cmlibuv/src/unix/cmake-bootstrap.c
@@ -137,4 +137,13 @@ int uv__utimesat(int dirfd, const char* path, const struct timespec times[2],
   errno = ENOSYS;
   return -1;
 }
+
+int uv__statx(int dirfd,
+              const char* path,
+              int flags,
+              unsigned int mask,
+              struct uv__statx* statxbuf) {
+  errno = ENOSYS;
+  return -1;
+}
 #endif

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=69b139cfca6c5eef64558070f533b6c898f410e0
commit 69b139cfca6c5eef64558070f533b6c898f410e0
Merge: ab63072 b4069b0
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Jun 18 07:45:53 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Jun 18 07:45:53 2019 -0400

    Merge branch 'upstream-libuv' into update-libuv
    
    * upstream-libuv:
      libuv 2019-06-10 (ee24ce90)

diff --cc Utilities/cmlibuv/include/uv.h
index e6dc736,0000000..eb80bfb
mode 100644,000000..100644
--- a/Utilities/cmlibuv/include/uv.h
+++ b/Utilities/cmlibuv/include/uv.h
@@@ -1,1653 -1,0 +1,1717 @@@
 +/* 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.
 + */
 +
 +/* See https://github.com/libuv/libuv#documentation for documentation. */
 +
 +#ifndef UV_H
 +#define UV_H
 +
 +/* Include KWSys Large File Support configuration. */
 +#include <cmsys/Configure.h>
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +
 +#ifdef _WIN32
 +  /* Windows - set up dll import/export decorators. */
 +# if defined(BUILDING_UV_SHARED)
 +    /* Building shared library. */
 +#   define UV_EXTERN __declspec(dllexport)
 +# elif defined(USING_UV_SHARED)
 +    /* Using shared library. */
 +#   define UV_EXTERN __declspec(dllimport)
 +# else
 +    /* Building static library. */
 +#   define UV_EXTERN /* nothing */
 +# endif
 +#elif __GNUC__ >= 4
 +# define UV_EXTERN __attribute__((visibility("default")))
 +#else
 +# define UV_EXTERN /* nothing */
 +#endif
 +
 +#include "uv/errno.h"
 +#include "uv/version.h"
 +#include <stddef.h>
 +#include <stdio.h>
 +
 +#if defined(_MSC_VER) && _MSC_VER < 1600
 +# include "uv/stdint-msvc2008.h"
 +#else
 +# include <stdint.h>
 +#endif
 +
 +#if defined(_WIN32)
 +# include "uv/win.h"
 +#else
 +# include "uv/unix.h"
 +#endif
 +
 +/* Expand this list if necessary. */
 +#define UV_ERRNO_MAP(XX)                                                      \
 +  XX(E2BIG, "argument list too long")                                         \
 +  XX(EACCES, "permission denied")                                             \
 +  XX(EADDRINUSE, "address already in use")                                    \
 +  XX(EADDRNOTAVAIL, "address not available")                                  \
 +  XX(EAFNOSUPPORT, "address family not supported")                            \
 +  XX(EAGAIN, "resource temporarily unavailable")                              \
 +  XX(EAI_ADDRFAMILY, "address family not supported")                          \
 +  XX(EAI_AGAIN, "temporary failure")                                          \
 +  XX(EAI_BADFLAGS, "bad ai_flags value")                                      \
 +  XX(EAI_BADHINTS, "invalid value for hints")                                 \
 +  XX(EAI_CANCELED, "request canceled")                                        \
 +  XX(EAI_FAIL, "permanent failure")                                           \
 +  XX(EAI_FAMILY, "ai_family not supported")                                   \
 +  XX(EAI_MEMORY, "out of memory")                                             \
 +  XX(EAI_NODATA, "no address")                                                \
 +  XX(EAI_NONAME, "unknown node or service")                                   \
 +  XX(EAI_OVERFLOW, "argument buffer overflow")                                \
 +  XX(EAI_PROTOCOL, "resolved protocol is unknown")                            \
 +  XX(EAI_SERVICE, "service not available for socket type")                    \
 +  XX(EAI_SOCKTYPE, "socket type not supported")                               \
 +  XX(EALREADY, "connection already in progress")                              \
 +  XX(EBADF, "bad file descriptor")                                            \
 +  XX(EBUSY, "resource busy or locked")                                        \
 +  XX(ECANCELED, "operation canceled")                                         \
 +  XX(ECHARSET, "invalid Unicode character")                                   \
 +  XX(ECONNABORTED, "software caused connection abort")                        \
 +  XX(ECONNREFUSED, "connection refused")                                      \
 +  XX(ECONNRESET, "connection reset by peer")                                  \
 +  XX(EDESTADDRREQ, "destination address required")                            \
 +  XX(EEXIST, "file already exists")                                           \
 +  XX(EFAULT, "bad address in system call argument")                           \
 +  XX(EFBIG, "file too large")                                                 \
 +  XX(EHOSTUNREACH, "host is unreachable")                                     \
 +  XX(EINTR, "interrupted system call")                                        \
 +  XX(EINVAL, "invalid argument")                                              \
 +  XX(EIO, "i/o error")                                                        \
 +  XX(EISCONN, "socket is already connected")                                  \
 +  XX(EISDIR, "illegal operation on a directory")                              \
 +  XX(ELOOP, "too many symbolic links encountered")                            \
 +  XX(EMFILE, "too many open files")                                           \
 +  XX(EMSGSIZE, "message too long")                                            \
 +  XX(ENAMETOOLONG, "name too long")                                           \
 +  XX(ENETDOWN, "network is down")                                             \
 +  XX(ENETUNREACH, "network is unreachable")                                   \
 +  XX(ENFILE, "file table overflow")                                           \
 +  XX(ENOBUFS, "no buffer space available")                                    \
 +  XX(ENODEV, "no such device")                                                \
 +  XX(ENOENT, "no such file or directory")                                     \
 +  XX(ENOMEM, "not enough memory")                                             \
 +  XX(ENONET, "machine is not on the network")                                 \
 +  XX(ENOPROTOOPT, "protocol not available")                                   \
 +  XX(ENOSPC, "no space left on device")                                       \
 +  XX(ENOSYS, "function not implemented")                                      \
 +  XX(ENOTCONN, "socket is not connected")                                     \
 +  XX(ENOTDIR, "not a directory")                                              \
 +  XX(ENOTEMPTY, "directory not empty")                                        \
 +  XX(ENOTSOCK, "socket operation on non-socket")                              \
 +  XX(ENOTSUP, "operation not supported on socket")                            \
 +  XX(EPERM, "operation not permitted")                                        \
 +  XX(EPIPE, "broken pipe")                                                    \
 +  XX(EPROTO, "protocol error")                                                \
 +  XX(EPROTONOSUPPORT, "protocol not supported")                               \
 +  XX(EPROTOTYPE, "protocol wrong type for socket")                            \
 +  XX(ERANGE, "result too large")                                              \
 +  XX(EROFS, "read-only file system")                                          \
 +  XX(ESHUTDOWN, "cannot send after transport endpoint shutdown")              \
 +  XX(ESPIPE, "invalid seek")                                                  \
 +  XX(ESRCH, "no such process")                                                \
 +  XX(ETIMEDOUT, "connection timed out")                                       \
 +  XX(ETXTBSY, "text file is busy")                                            \
 +  XX(EXDEV, "cross-device link not permitted")                                \
 +  XX(UNKNOWN, "unknown error")                                                \
 +  XX(EOF, "end of file")                                                      \
 +  XX(ENXIO, "no such device or address")                                      \
 +  XX(EMLINK, "too many links")                                                \
 +  XX(EHOSTDOWN, "host is down")                                               \
 +  XX(EREMOTEIO, "remote I/O error")                                           \
 +  XX(ENOTTY, "inappropriate ioctl for device")                                \
 +  XX(EFTYPE, "inappropriate file type or format")                             \
 +
 +#define UV_HANDLE_TYPE_MAP(XX)                                                \
 +  XX(ASYNC, async)                                                            \
 +  XX(CHECK, check)                                                            \
 +  XX(FS_EVENT, fs_event)                                                      \
 +  XX(FS_POLL, fs_poll)                                                        \
 +  XX(HANDLE, handle)                                                          \
 +  XX(IDLE, idle)                                                              \
 +  XX(NAMED_PIPE, pipe)                                                        \
 +  XX(POLL, poll)                                                              \
 +  XX(PREPARE, prepare)                                                        \
 +  XX(PROCESS, process)                                                        \
 +  XX(STREAM, stream)                                                          \
 +  XX(TCP, tcp)                                                                \
 +  XX(TIMER, timer)                                                            \
 +  XX(TTY, tty)                                                                \
 +  XX(UDP, udp)                                                                \
 +  XX(SIGNAL, signal)                                                          \
 +
 +#define UV_REQ_TYPE_MAP(XX)                                                   \
 +  XX(REQ, req)                                                                \
 +  XX(CONNECT, connect)                                                        \
 +  XX(WRITE, write)                                                            \
 +  XX(SHUTDOWN, shutdown)                                                      \
 +  XX(UDP_SEND, udp_send)                                                      \
 +  XX(FS, fs)                                                                  \
 +  XX(WORK, work)                                                              \
 +  XX(GETADDRINFO, getaddrinfo)                                                \
 +  XX(GETNAMEINFO, getnameinfo)                                                \
 +
 +typedef enum {
 +#define XX(code, _) UV_ ## code = UV__ ## code,
 +  UV_ERRNO_MAP(XX)
 +#undef XX
 +  UV_ERRNO_MAX = UV__EOF - 1
 +} uv_errno_t;
 +
 +typedef enum {
 +  UV_UNKNOWN_HANDLE = 0,
 +#define XX(uc, lc) UV_##uc,
 +  UV_HANDLE_TYPE_MAP(XX)
 +#undef XX
 +  UV_FILE,
 +  UV_HANDLE_TYPE_MAX
 +} uv_handle_type;
 +
 +typedef enum {
 +  UV_UNKNOWN_REQ = 0,
 +#define XX(uc, lc) UV_##uc,
 +  UV_REQ_TYPE_MAP(XX)
 +#undef XX
 +  UV_REQ_TYPE_PRIVATE
 +  UV_REQ_TYPE_MAX
 +} uv_req_type;
 +
 +
 +/* Handle types. */
 +typedef struct uv_loop_s uv_loop_t;
 +typedef struct uv_handle_s uv_handle_t;
++typedef struct uv_dir_s uv_dir_t;
 +typedef struct uv_stream_s uv_stream_t;
 +typedef struct uv_tcp_s uv_tcp_t;
 +typedef struct uv_udp_s uv_udp_t;
 +typedef struct uv_pipe_s uv_pipe_t;
 +typedef struct uv_tty_s uv_tty_t;
 +typedef struct uv_poll_s uv_poll_t;
 +typedef struct uv_timer_s uv_timer_t;
 +typedef struct uv_prepare_s uv_prepare_t;
 +typedef struct uv_check_s uv_check_t;
 +typedef struct uv_idle_s uv_idle_t;
 +typedef struct uv_async_s uv_async_t;
 +typedef struct uv_process_s uv_process_t;
 +typedef struct uv_fs_event_s uv_fs_event_t;
 +typedef struct uv_fs_poll_s uv_fs_poll_t;
 +typedef struct uv_signal_s uv_signal_t;
 +
 +/* Request types. */
 +typedef struct uv_req_s uv_req_t;
 +typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
 +typedef struct uv_getnameinfo_s uv_getnameinfo_t;
 +typedef struct uv_shutdown_s uv_shutdown_t;
 +typedef struct uv_write_s uv_write_t;
 +typedef struct uv_connect_s uv_connect_t;
 +typedef struct uv_udp_send_s uv_udp_send_t;
 +typedef struct uv_fs_s uv_fs_t;
 +typedef struct uv_work_s uv_work_t;
 +
 +/* None of the above. */
 +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 enum {
 +  UV_LOOP_BLOCK_SIGNAL
 +} uv_loop_option;
 +
 +typedef enum {
 +  UV_RUN_DEFAULT = 0,
 +  UV_RUN_ONCE,
 +  UV_RUN_NOWAIT
 +} uv_run_mode;
 +
 +
 +UV_EXTERN unsigned int uv_version(void);
 +UV_EXTERN const char* uv_version_string(void);
 +
 +typedef void* (*uv_malloc_func)(size_t size);
 +typedef void* (*uv_realloc_func)(void* ptr, size_t size);
 +typedef void* (*uv_calloc_func)(size_t count, size_t size);
 +typedef void (*uv_free_func)(void* ptr);
 +
 +UV_EXTERN int uv_replace_allocator(uv_malloc_func malloc_func,
 +                                   uv_realloc_func realloc_func,
 +                                   uv_calloc_func calloc_func,
 +                                   uv_free_func free_func);
 +
 +UV_EXTERN uv_loop_t* uv_default_loop(void);
 +UV_EXTERN int uv_loop_init(uv_loop_t* loop);
 +UV_EXTERN int uv_loop_close(uv_loop_t* loop);
 +/*
 + * NOTE:
 + *  This function is DEPRECATED (to be removed after 0.12), users should
 + *  allocate the loop manually and use uv_loop_init instead.
 + */
 +UV_EXTERN uv_loop_t* uv_loop_new(void);
 +/*
 + * NOTE:
 + *  This function is DEPRECATED (to be removed after 0.12). Users should use
 + *  uv_loop_close and free the memory manually instead.
 + */
 +UV_EXTERN void uv_loop_delete(uv_loop_t*);
 +UV_EXTERN size_t uv_loop_size(void);
 +UV_EXTERN int uv_loop_alive(const uv_loop_t* loop);
 +UV_EXTERN int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...);
 +UV_EXTERN int uv_loop_fork(uv_loop_t* loop);
 +
 +UV_EXTERN int uv_run(uv_loop_t*, uv_run_mode mode);
 +UV_EXTERN void uv_stop(uv_loop_t*);
 +
 +UV_EXTERN void uv_ref(uv_handle_t*);
 +UV_EXTERN void uv_unref(uv_handle_t*);
 +UV_EXTERN int uv_has_ref(const uv_handle_t*);
 +
 +UV_EXTERN void uv_update_time(uv_loop_t*);
 +UV_EXTERN uint64_t uv_now(const uv_loop_t*);
 +
 +UV_EXTERN int uv_backend_fd(const uv_loop_t*);
 +UV_EXTERN int uv_backend_timeout(const uv_loop_t*);
 +
 +typedef void (*uv_alloc_cb)(uv_handle_t* handle,
 +                            size_t suggested_size,
 +                            uv_buf_t* buf);
 +typedef void (*uv_read_cb)(uv_stream_t* stream,
 +                           ssize_t nread,
 +                           const uv_buf_t* buf);
 +typedef void (*uv_write_cb)(uv_write_t* req, int status);
 +typedef void (*uv_connect_cb)(uv_connect_t* req, int status);
 +typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status);
 +typedef void (*uv_connection_cb)(uv_stream_t* server, int status);
 +typedef void (*uv_close_cb)(uv_handle_t* handle);
 +typedef void (*uv_poll_cb)(uv_poll_t* handle, int status, int events);
 +typedef void (*uv_timer_cb)(uv_timer_t* handle);
 +typedef void (*uv_async_cb)(uv_async_t* handle);
 +typedef void (*uv_prepare_cb)(uv_prepare_t* handle);
 +typedef void (*uv_check_cb)(uv_check_t* handle);
 +typedef void (*uv_idle_cb)(uv_idle_t* handle);
 +typedef void (*uv_exit_cb)(uv_process_t*, int64_t exit_status, int term_signal);
 +typedef void (*uv_walk_cb)(uv_handle_t* handle, void* arg);
 +typedef void (*uv_fs_cb)(uv_fs_t* req);
 +typedef void (*uv_work_cb)(uv_work_t* req);
 +typedef void (*uv_after_work_cb)(uv_work_t* req, int status);
 +typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* req,
 +                                  int status,
 +                                  struct addrinfo* res);
 +typedef void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req,
 +                                  int status,
 +                                  const char* hostname,
 +                                  const char* service);
 +
 +typedef struct {
 +  long tv_sec;
 +  long tv_nsec;
 +} uv_timespec_t;
 +
 +
 +typedef struct {
 +  uint64_t st_dev;
 +  uint64_t st_mode;
 +  uint64_t st_nlink;
 +  uint64_t st_uid;
 +  uint64_t st_gid;
 +  uint64_t st_rdev;
 +  uint64_t st_ino;
 +  uint64_t st_size;
 +  uint64_t st_blksize;
 +  uint64_t st_blocks;
 +  uint64_t st_flags;
 +  uint64_t st_gen;
 +  uv_timespec_t st_atim;
 +  uv_timespec_t st_mtim;
 +  uv_timespec_t st_ctim;
 +  uv_timespec_t st_birthtim;
 +} uv_stat_t;
 +
 +
 +typedef void (*uv_fs_event_cb)(uv_fs_event_t* handle,
 +                               const char* filename,
 +                               int events,
 +                               int status);
 +
 +typedef void (*uv_fs_poll_cb)(uv_fs_poll_t* handle,
 +                              int status,
 +                              const uv_stat_t* prev,
 +                              const uv_stat_t* curr);
 +
 +typedef void (*uv_signal_cb)(uv_signal_t* handle, int signum);
 +
 +
 +typedef enum {
 +  UV_LEAVE_GROUP = 0,
 +  UV_JOIN_GROUP
 +} uv_membership;
 +
 +
 +UV_EXTERN int uv_translate_sys_error(int sys_errno);
 +
 +UV_EXTERN const char* uv_strerror(int err);
 +UV_EXTERN char* uv_strerror_r(int err, char* buf, size_t buflen);
 +
 +UV_EXTERN const char* uv_err_name(int err);
 +UV_EXTERN char* uv_err_name_r(int err, char* buf, size_t buflen);
 +
 +
 +#define UV_REQ_FIELDS                                                         \
 +  /* public */                                                                \
 +  void* data;                                                                 \
 +  /* read-only */                                                             \
 +  uv_req_type type;                                                           \
 +  /* private */                                                               \
 +  void* reserved[6];                                                          \
 +  UV_REQ_PRIVATE_FIELDS                                                       \
 +
 +/* Abstract base class of all requests. */
 +struct uv_req_s {
 +  UV_REQ_FIELDS
 +};
 +
 +
 +/* Platform-specific request types. */
 +UV_PRIVATE_REQ_TYPES
 +
 +
 +UV_EXTERN int uv_shutdown(uv_shutdown_t* req,
 +                          uv_stream_t* handle,
 +                          uv_shutdown_cb cb);
 +
 +struct uv_shutdown_s {
 +  UV_REQ_FIELDS
 +  uv_stream_t* handle;
 +  uv_shutdown_cb cb;
 +  UV_SHUTDOWN_PRIVATE_FIELDS
 +};
 +
 +
 +#define UV_HANDLE_FIELDS                                                      \
 +  /* public */                                                                \
 +  void* data;                                                                 \
 +  /* read-only */                                                             \
 +  uv_loop_t* loop;                                                            \
 +  uv_handle_type type;                                                        \
 +  /* private */                                                               \
 +  uv_close_cb close_cb;                                                       \
 +  void* handle_queue[2];                                                      \
 +  union {                                                                     \
 +    int fd;                                                                   \
 +    void* reserved[4];                                                        \
 +  } u;                                                                        \
 +  UV_HANDLE_PRIVATE_FIELDS                                                    \
 +
 +/* The abstract base class of all handles. */
 +struct uv_handle_s {
 +  UV_HANDLE_FIELDS
 +};
 +
 +UV_EXTERN size_t uv_handle_size(uv_handle_type type);
 +UV_EXTERN uv_handle_type uv_handle_get_type(const uv_handle_t* handle);
 +UV_EXTERN const char* uv_handle_type_name(uv_handle_type type);
 +UV_EXTERN void* uv_handle_get_data(const uv_handle_t* handle);
 +UV_EXTERN uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle);
 +UV_EXTERN void uv_handle_set_data(uv_handle_t* handle, void* data);
 +
 +UV_EXTERN size_t uv_req_size(uv_req_type type);
 +UV_EXTERN void* uv_req_get_data(const uv_req_t* req);
 +UV_EXTERN void uv_req_set_data(uv_req_t* req, void* data);
 +UV_EXTERN uv_req_type uv_req_get_type(const uv_req_t* req);
 +UV_EXTERN const char* uv_req_type_name(uv_req_type type);
 +
 +UV_EXTERN int uv_is_active(const uv_handle_t* handle);
 +
 +UV_EXTERN void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg);
 +
 +/* Helpers for ad hoc debugging, no API/ABI stability guaranteed. */
 +UV_EXTERN void uv_print_all_handles(uv_loop_t* loop, FILE* stream);
 +UV_EXTERN void uv_print_active_handles(uv_loop_t* loop, FILE* stream);
 +
 +UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb);
 +
 +UV_EXTERN int uv_send_buffer_size(uv_handle_t* handle, int* value);
 +UV_EXTERN int uv_recv_buffer_size(uv_handle_t* handle, int* value);
 +
 +UV_EXTERN int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd);
 +
 +UV_EXTERN uv_buf_t uv_buf_init(char* base, unsigned int len);
 +
 +
 +#define UV_STREAM_FIELDS                                                      \
 +  /* number of bytes queued for writing */                                    \
 +  size_t write_queue_size;                                                    \
 +  uv_alloc_cb alloc_cb;                                                       \
 +  uv_read_cb read_cb;                                                         \
 +  /* private */                                                               \
 +  UV_STREAM_PRIVATE_FIELDS
 +
 +/*
 + * uv_stream_t is a subclass of uv_handle_t.
 + *
 + * uv_stream is an abstract class.
 + *
 + * uv_stream_t is the parent class of uv_tcp_t, uv_pipe_t and uv_tty_t.
 + */
 +struct uv_stream_s {
 +  UV_HANDLE_FIELDS
 +  UV_STREAM_FIELDS
 +};
 +
 +UV_EXTERN size_t uv_stream_get_write_queue_size(const uv_stream_t* stream);
 +
 +UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);
 +UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client);
 +
 +UV_EXTERN int uv_read_start(uv_stream_t*,
 +                            uv_alloc_cb alloc_cb,
 +                            uv_read_cb read_cb);
 +UV_EXTERN int uv_read_stop(uv_stream_t*);
 +
 +UV_EXTERN int uv_write(uv_write_t* req,
 +                       uv_stream_t* handle,
 +                       const uv_buf_t bufs[],
 +                       unsigned int nbufs,
 +                       uv_write_cb cb);
 +UV_EXTERN int uv_write2(uv_write_t* req,
 +                        uv_stream_t* handle,
 +                        const uv_buf_t bufs[],
 +                        unsigned int nbufs,
 +                        uv_stream_t* send_handle,
 +                        uv_write_cb cb);
 +UV_EXTERN int uv_try_write(uv_stream_t* handle,
 +                           const uv_buf_t bufs[],
 +                           unsigned int nbufs);
 +
 +/* uv_write_t is a subclass of uv_req_t. */
 +struct uv_write_s {
 +  UV_REQ_FIELDS
 +  uv_write_cb cb;
 +  uv_stream_t* send_handle; /* TODO: make private and unix-only in v2.x. */
 +  uv_stream_t* handle;
 +  UV_WRITE_PRIVATE_FIELDS
 +};
 +
 +
 +UV_EXTERN int uv_is_readable(const uv_stream_t* handle);
 +UV_EXTERN int uv_is_writable(const uv_stream_t* handle);
 +
 +UV_EXTERN int uv_stream_set_blocking(uv_stream_t* handle, int blocking);
 +
 +UV_EXTERN int uv_is_closing(const uv_handle_t* handle);
 +
 +
 +/*
 + * uv_tcp_t is a subclass of uv_stream_t.
 + *
 + * Represents a TCP stream or TCP server.
 + */
 +struct uv_tcp_s {
 +  UV_HANDLE_FIELDS
 +  UV_STREAM_FIELDS
 +  UV_TCP_PRIVATE_FIELDS
 +};
 +
 +UV_EXTERN int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle);
 +UV_EXTERN int uv_tcp_init_ex(uv_loop_t*, uv_tcp_t* handle, unsigned int flags);
 +UV_EXTERN int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock);
 +UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable);
 +UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle,
 +                               int enable,
 +                               unsigned int delay);
 +UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable);
 +
 +enum uv_tcp_flags {
 +  /* Used with uv_tcp_bind, when an IPv6 address is used. */
 +  UV_TCP_IPV6ONLY = 1
 +};
 +
 +UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle,
 +                          const struct sockaddr* addr,
 +                          unsigned int flags);
 +UV_EXTERN int uv_tcp_getsockname(const uv_tcp_t* handle,
 +                                 struct sockaddr* name,
 +                                 int* namelen);
 +UV_EXTERN int uv_tcp_getpeername(const uv_tcp_t* handle,
 +                                 struct sockaddr* name,
 +                                 int* namelen);
 +UV_EXTERN int uv_tcp_connect(uv_connect_t* req,
 +                             uv_tcp_t* handle,
 +                             const struct sockaddr* addr,
 +                             uv_connect_cb cb);
 +
 +/* uv_connect_t is a subclass of uv_req_t. */
 +struct uv_connect_s {
 +  UV_REQ_FIELDS
 +  uv_connect_cb cb;
 +  uv_stream_t* handle;
 +  UV_CONNECT_PRIVATE_FIELDS
 +};
 +
 +
 +/*
 + * UDP support.
 + */
 +
 +enum uv_udp_flags {
 +  /* Disables dual stack mode. */
 +  UV_UDP_IPV6ONLY = 1,
 +  /*
 +   * Indicates message was truncated because read buffer was too small. The
 +   * remainder was discarded by the OS. Used in uv_udp_recv_cb.
 +   */
 +  UV_UDP_PARTIAL = 2,
 +  /*
 +   * Indicates if SO_REUSEADDR will be set when binding the handle.
 +   * This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other
 +   * Unix platforms, it sets the SO_REUSEADDR flag.  What that means is that
 +   * multiple threads or processes can bind to the same address without error
 +   * (provided they all set the flag) but only the last one to bind will receive
 +   * any traffic, in effect "stealing" the port from the previous listener.
 +   */
 +  UV_UDP_REUSEADDR = 4
 +};
 +
 +typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status);
 +typedef void (*uv_udp_recv_cb)(uv_udp_t* handle,
 +                               ssize_t nread,
 +                               const uv_buf_t* buf,
 +                               const struct sockaddr* addr,
 +                               unsigned flags);
 +
 +/* uv_udp_t is a subclass of uv_handle_t. */
 +struct uv_udp_s {
 +  UV_HANDLE_FIELDS
 +  /* read-only */
 +  /*
 +   * Number of bytes queued for sending. This field strictly shows how much
 +   * information is currently queued.
 +   */
 +  size_t send_queue_size;
 +  /*
 +   * Number of send requests currently in the queue awaiting to be processed.
 +   */
 +  size_t send_queue_count;
 +  UV_UDP_PRIVATE_FIELDS
 +};
 +
 +/* uv_udp_send_t is a subclass of uv_req_t. */
 +struct uv_udp_send_s {
 +  UV_REQ_FIELDS
 +  uv_udp_t* handle;
 +  uv_udp_send_cb cb;
 +  UV_UDP_SEND_PRIVATE_FIELDS
 +};
 +
 +UV_EXTERN int uv_udp_init(uv_loop_t*, uv_udp_t* handle);
 +UV_EXTERN int uv_udp_init_ex(uv_loop_t*, uv_udp_t* handle, unsigned int flags);
 +UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock);
 +UV_EXTERN int uv_udp_bind(uv_udp_t* handle,
 +                          const struct sockaddr* addr,
 +                          unsigned int flags);
++UV_EXTERN int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr);
 +
++UV_EXTERN int uv_udp_getpeername(const uv_udp_t* handle,
++                                 struct sockaddr* name,
++                                 int* namelen);
 +UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle,
 +                                 struct sockaddr* name,
 +                                 int* namelen);
 +UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle,
 +                                    const char* multicast_addr,
 +                                    const char* interface_addr,
 +                                    uv_membership membership);
 +UV_EXTERN int uv_udp_set_multicast_loop(uv_udp_t* handle, int on);
 +UV_EXTERN int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl);
 +UV_EXTERN int uv_udp_set_multicast_interface(uv_udp_t* handle,
 +                                             const char* interface_addr);
 +UV_EXTERN int uv_udp_set_broadcast(uv_udp_t* handle, int on);
 +UV_EXTERN int uv_udp_set_ttl(uv_udp_t* handle, int ttl);
 +UV_EXTERN int uv_udp_send(uv_udp_send_t* req,
 +                          uv_udp_t* handle,
 +                          const uv_buf_t bufs[],
 +                          unsigned int nbufs,
 +                          const struct sockaddr* addr,
 +                          uv_udp_send_cb send_cb);
 +UV_EXTERN int uv_udp_try_send(uv_udp_t* handle,
 +                              const uv_buf_t bufs[],
 +                              unsigned int nbufs,
 +                              const struct sockaddr* addr);
 +UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle,
 +                                uv_alloc_cb alloc_cb,
 +                                uv_udp_recv_cb recv_cb);
 +UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle);
 +UV_EXTERN size_t uv_udp_get_send_queue_size(const uv_udp_t* handle);
 +UV_EXTERN size_t uv_udp_get_send_queue_count(const uv_udp_t* handle);
 +
 +
 +/*
 + * uv_tty_t is a subclass of uv_stream_t.
 + *
 + * Representing a stream for the console.
 + */
 +struct uv_tty_s {
 +  UV_HANDLE_FIELDS
 +  UV_STREAM_FIELDS
 +  UV_TTY_PRIVATE_FIELDS
 +};
 +
 +typedef enum {
 +  /* Initial/normal terminal mode */
 +  UV_TTY_MODE_NORMAL,
 +  /* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */
 +  UV_TTY_MODE_RAW,
 +  /* Binary-safe I/O mode for IPC (Unix-only) */
 +  UV_TTY_MODE_IO
 +} uv_tty_mode_t;
 +
 +UV_EXTERN int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable);
 +UV_EXTERN int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode);
 +UV_EXTERN int uv_tty_reset_mode(void);
 +UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height);
 +
 +#ifdef __cplusplus
 +extern "C++" {
 +
 +inline int uv_tty_set_mode(uv_tty_t* handle, int mode) {
 +  return uv_tty_set_mode(handle, static_cast<uv_tty_mode_t>(mode));
 +}
 +
 +}
 +#endif
 +
 +UV_EXTERN uv_handle_type uv_guess_handle(uv_file file);
 +
 +/*
 + * uv_pipe_t is a subclass of uv_stream_t.
 + *
 + * Representing a pipe stream or pipe server. On Windows this is a Named
 + * Pipe. On Unix this is a Unix domain socket.
 + */
 +struct uv_pipe_s {
 +  UV_HANDLE_FIELDS
 +  UV_STREAM_FIELDS
 +  int ipc; /* non-zero if this pipe is used for passing handles */
 +  UV_PIPE_PRIVATE_FIELDS
 +};
 +
 +UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc);
 +UV_EXTERN int uv_pipe_open(uv_pipe_t*, uv_file file);
 +UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name);
 +UV_EXTERN void uv_pipe_connect(uv_connect_t* req,
 +                               uv_pipe_t* handle,
 +                               const char* name,
 +                               uv_connect_cb cb);
 +UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle,
 +                                  char* buffer,
 +                                  size_t* size);
 +UV_EXTERN int uv_pipe_getpeername(const uv_pipe_t* handle,
 +                                  char* buffer,
 +                                  size_t* size);
 +UV_EXTERN void uv_pipe_pending_instances(uv_pipe_t* handle, int count);
 +UV_EXTERN int uv_pipe_pending_count(uv_pipe_t* handle);
 +UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle);
 +UV_EXTERN int uv_pipe_chmod(uv_pipe_t* handle, int flags);
 +
 +
 +struct uv_poll_s {
 +  UV_HANDLE_FIELDS
 +  uv_poll_cb poll_cb;
 +  UV_POLL_PRIVATE_FIELDS
 +};
 +
 +enum uv_poll_event {
 +  UV_READABLE = 1,
 +  UV_WRITABLE = 2,
 +  UV_DISCONNECT = 4,
 +  UV_PRIORITIZED = 8
 +};
 +
 +UV_EXTERN int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd);
 +UV_EXTERN int uv_poll_init_socket(uv_loop_t* loop,
 +                                  uv_poll_t* handle,
 +                                  uv_os_sock_t socket);
 +UV_EXTERN int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb);
 +UV_EXTERN int uv_poll_stop(uv_poll_t* handle);
 +
 +
 +struct uv_prepare_s {
 +  UV_HANDLE_FIELDS
 +  UV_PREPARE_PRIVATE_FIELDS
 +};
 +
 +UV_EXTERN int uv_prepare_init(uv_loop_t*, uv_prepare_t* prepare);
 +UV_EXTERN int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb);
 +UV_EXTERN int uv_prepare_stop(uv_prepare_t* prepare);
 +
 +
 +struct uv_check_s {
 +  UV_HANDLE_FIELDS
 +  UV_CHECK_PRIVATE_FIELDS
 +};
 +
 +UV_EXTERN int uv_check_init(uv_loop_t*, uv_check_t* check);
 +UV_EXTERN int uv_check_start(uv_check_t* check, uv_check_cb cb);
 +UV_EXTERN int uv_check_stop(uv_check_t* check);
 +
 +
 +struct uv_idle_s {
 +  UV_HANDLE_FIELDS
 +  UV_IDLE_PRIVATE_FIELDS
 +};
 +
 +UV_EXTERN int uv_idle_init(uv_loop_t*, uv_idle_t* idle);
 +UV_EXTERN int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb);
 +UV_EXTERN int uv_idle_stop(uv_idle_t* idle);
 +
 +
 +struct uv_async_s {
 +  UV_HANDLE_FIELDS
 +  UV_ASYNC_PRIVATE_FIELDS
 +};
 +
 +UV_EXTERN int uv_async_init(uv_loop_t*,
 +                            uv_async_t* async,
 +                            uv_async_cb async_cb);
 +UV_EXTERN int uv_async_send(uv_async_t* async);
 +
 +
 +/*
 + * uv_timer_t is a subclass of uv_handle_t.
 + *
 + * Used to get woken up at a specified time in the future.
 + */
 +struct uv_timer_s {
 +  UV_HANDLE_FIELDS
 +  UV_TIMER_PRIVATE_FIELDS
 +};
 +
 +UV_EXTERN int uv_timer_init(uv_loop_t*, uv_timer_t* handle);
 +UV_EXTERN int uv_timer_start(uv_timer_t* handle,
 +                             uv_timer_cb cb,
 +                             uint64_t timeout,
 +                             uint64_t repeat);
 +UV_EXTERN int uv_timer_stop(uv_timer_t* handle);
 +UV_EXTERN int uv_timer_again(uv_timer_t* handle);
 +UV_EXTERN void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat);
 +UV_EXTERN uint64_t uv_timer_get_repeat(const uv_timer_t* handle);
 +
 +
 +/*
 + * uv_getaddrinfo_t is a subclass of uv_req_t.
 + *
 + * Request object for uv_getaddrinfo.
 + */
 +struct uv_getaddrinfo_s {
 +  UV_REQ_FIELDS
 +  /* read-only */
 +  uv_loop_t* loop;
 +  /* struct addrinfo* addrinfo is marked as private, but it really isn't. */
 +  UV_GETADDRINFO_PRIVATE_FIELDS
 +};
 +
 +
 +UV_EXTERN int uv_getaddrinfo(uv_loop_t* loop,
 +                             uv_getaddrinfo_t* req,
 +                             uv_getaddrinfo_cb getaddrinfo_cb,
 +                             const char* node,
 +                             const char* service,
 +                             const struct addrinfo* hints);
 +UV_EXTERN void uv_freeaddrinfo(struct addrinfo* ai);
 +
 +
 +/*
 +* uv_getnameinfo_t is a subclass of uv_req_t.
 +*
 +* Request object for uv_getnameinfo.
 +*/
 +struct uv_getnameinfo_s {
 +  UV_REQ_FIELDS
 +  /* read-only */
 +  uv_loop_t* loop;
 +  /* host and service are marked as private, but they really aren't. */
 +  UV_GETNAMEINFO_PRIVATE_FIELDS
 +};
 +
 +UV_EXTERN int uv_getnameinfo(uv_loop_t* loop,
 +                             uv_getnameinfo_t* req,
 +                             uv_getnameinfo_cb getnameinfo_cb,
 +                             const struct sockaddr* addr,
 +                             int flags);
 +
 +
 +/* uv_spawn() options. */
 +typedef enum {
 +  UV_IGNORE         = 0x00,
 +  UV_CREATE_PIPE    = 0x01,
 +  UV_INHERIT_FD     = 0x02,
 +  UV_INHERIT_STREAM = 0x04,
 +
 +  /*
 +   * When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE
 +   * determine the direction of flow, from the child process' perspective. Both
 +   * flags may be specified to create a duplex data stream.
 +   */
 +  UV_READABLE_PIPE  = 0x10,
 +  UV_WRITABLE_PIPE  = 0x20,
 +
 +  /*
 +   * Open the child pipe handle in overlapped mode on Windows.
 +   * On Unix it is silently ignored.
 +   */
 +  UV_OVERLAPPED_PIPE = 0x40
 +} uv_stdio_flags;
 +
 +typedef struct uv_stdio_container_s {
 +  uv_stdio_flags flags;
 +
 +  union {
 +    uv_stream_t* stream;
 +    int fd;
 +  } data;
 +} uv_stdio_container_t;
 +
 +typedef struct uv_process_options_s {
 +  uv_exit_cb exit_cb; /* Called after the process exits. */
 +  const char* file;   /* Path to program to execute. */
 +  /*
 +   * Command line arguments. args[0] should be the path to the program. On
 +   * Windows this uses CreateProcess which concatenates the arguments into a
 +   * string this can cause some strange errors. See the note at
 +   * windows_verbatim_arguments.
 +   */
 +  char** args;
 +  /*
 +   * This will be set as the environ variable in the subprocess. If this is
 +   * NULL then the parents environ will be used.
 +   */
 +  char** env;
 +  /*
 +   * If non-null this represents a directory the subprocess should execute
 +   * in. Stands for current working directory.
 +   */
 +  const char* cwd;
 +  /*
 +   * Various flags that control how uv_spawn() behaves. See the definition of
 +   * `enum uv_process_flags` below.
 +   */
 +  unsigned int flags;
 +  /*
 +   * The `stdio` field points to an array of uv_stdio_container_t structs that
 +   * describe the file descriptors that will be made available to the child
 +   * process. The convention is that stdio[0] points to stdin, fd 1 is used for
 +   * stdout, and fd 2 is stderr.
 +   *
 +   * Note that on windows file descriptors greater than 2 are available to the
 +   * child process only if the child processes uses the MSVCRT runtime.
 +   */
 +  int stdio_count;
 +  uv_stdio_container_t* stdio;
 +  /*
 +   * Libuv can change the child process' user/group id. This happens only when
 +   * the appropriate bits are set in the flags fields. This is not supported on
 +   * windows; uv_spawn() will fail and set the error to UV_ENOTSUP.
 +   */
 +  uv_uid_t uid;
 +  uv_gid_t gid;
 +  /*
 +    Libuv can set the child process' CPU affinity mask.  This happens when
 +    `cpumask` is non-NULL.  It must point to an array of char values
 +    of length `cpumask_size`, whose value must be at least that returned by
 +    uv_cpumask_size().  Each byte in the mask can be either zero (false)
 +    or non-zero (true) to indicate whether the corresponding processor at
 +    that index is included.
 +
 +    If enabled on an unsupported platform, uv_spawn() will fail with
 +    UV_ENOTSUP.
 +   */
 +  char* cpumask;
 +  size_t cpumask_size;
 +} uv_process_options_t;
 +
 +/*
 + * These are the flags that can be used for the uv_process_options.flags field.
 + */
 +enum uv_process_flags {
 +  /*
 +   * Set the child process' user id. The user id is supplied in the `uid` field
 +   * of the options struct. This does not work on windows; setting this flag
 +   * will cause uv_spawn() to fail.
 +   */
 +  UV_PROCESS_SETUID = (1 << 0),
 +  /*
 +   * Set the child process' group id. The user id is supplied in the `gid`
 +   * field of the options struct. This does not work on windows; setting this
 +   * flag will cause uv_spawn() to fail.
 +   */
 +  UV_PROCESS_SETGID = (1 << 1),
 +  /*
 +   * Do not wrap any arguments in quotes, or perform any other escaping, when
 +   * converting the argument list into a command line string. This option is
 +   * only meaningful on Windows systems. On Unix it is silently ignored.
 +   */
 +  UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2),
 +  /*
 +   * Spawn the child process in a detached state - this will make it a process
 +   * group leader, and will effectively enable the child to keep running after
 +   * the parent exits.  Note that the child process will still keep the
 +   * parent's event loop alive unless the parent process calls uv_unref() on
 +   * the child's process handle.
 +   */
 +  UV_PROCESS_DETACHED = (1 << 3),
 +  /*
 +   * Hide the subprocess window that would normally be created. This option is
 +   * only meaningful on Windows systems. On Unix it is silently ignored.
 +   */
 +  UV_PROCESS_WINDOWS_HIDE = (1 << 4),
 +  /*
 +   * Hide the subprocess console window that would normally be created. This
 +   * option is only meaningful on Windows systems. On Unix it is silently
 +   * ignored.
 +   */
 +  UV_PROCESS_WINDOWS_HIDE_CONSOLE = (1 << 5),
 +  /*
 +   * Hide the subprocess GUI window that would normally be created. This
 +   * option is only meaningful on Windows systems. On Unix it is silently
 +   * ignored.
 +   */
 +  UV_PROCESS_WINDOWS_HIDE_GUI = (1 << 6)
 +};
 +
 +/*
 + * uv_process_t is a subclass of uv_handle_t.
 + */
 +struct uv_process_s {
 +  UV_HANDLE_FIELDS
 +  uv_exit_cb exit_cb;
 +  int pid;
 +  UV_PROCESS_PRIVATE_FIELDS
 +};
 +
 +UV_EXTERN int uv_spawn(uv_loop_t* loop,
 +                       uv_process_t* handle,
 +                       const uv_process_options_t* options);
 +UV_EXTERN int uv_process_kill(uv_process_t*, int signum);
 +UV_EXTERN int uv_kill(int pid, int signum);
 +UV_EXTERN uv_pid_t uv_process_get_pid(const uv_process_t*);
 +
 +
 +/*
 + * uv_work_t is a subclass of uv_req_t.
 + */
 +struct uv_work_s {
 +  UV_REQ_FIELDS
 +  uv_loop_t* loop;
 +  uv_work_cb work_cb;
 +  uv_after_work_cb after_work_cb;
 +  UV_WORK_PRIVATE_FIELDS
 +};
 +
 +UV_EXTERN int uv_queue_work(uv_loop_t* loop,
 +                            uv_work_t* req,
 +                            uv_work_cb work_cb,
 +                            uv_after_work_cb after_work_cb);
 +
 +UV_EXTERN int uv_cancel(uv_req_t* req);
 +
 +
 +struct uv_cpu_times_s {
 +  uint64_t user;
 +  uint64_t nice;
 +  uint64_t sys;
 +  uint64_t idle;
 +  uint64_t irq;
 +};
 +
 +struct uv_cpu_info_s {
 +  char* model;
 +  int speed;
 +  struct uv_cpu_times_s cpu_times;
 +};
 +
 +struct uv_interface_address_s {
 +  char* name;
 +  char phys_addr[6];
 +  int is_internal;
 +  union {
 +    struct sockaddr_in address4;
 +    struct sockaddr_in6 address6;
 +  } address;
 +  union {
 +    struct sockaddr_in netmask4;
 +    struct sockaddr_in6 netmask6;
 +  } netmask;
 +};
 +
 +struct uv_passwd_s {
 +  char* username;
 +  long uid;
 +  long gid;
 +  char* shell;
 +  char* homedir;
 +};
 +
 +struct uv_utsname_s {
 +  char sysname[256];
 +  char release[256];
 +  char version[256];
 +  char machine[256];
 +  /* This struct does not contain the nodename and domainname fields present in
 +     the utsname type. domainname is a GNU extension. Both fields are referred
 +     to as meaningless in the docs. */
 +};
 +
 +typedef enum {
 +  UV_DIRENT_UNKNOWN,
 +  UV_DIRENT_FILE,
 +  UV_DIRENT_DIR,
 +  UV_DIRENT_LINK,
 +  UV_DIRENT_FIFO,
 +  UV_DIRENT_SOCKET,
 +  UV_DIRENT_CHAR,
 +  UV_DIRENT_BLOCK
 +} uv_dirent_type_t;
 +
 +struct uv_dirent_s {
 +  const char* name;
 +  uv_dirent_type_t type;
 +};
 +
 +UV_EXTERN char** uv_setup_args(int argc, char** argv);
 +UV_EXTERN int uv_get_process_title(char* buffer, size_t size);
 +UV_EXTERN int uv_set_process_title(const char* title);
 +UV_EXTERN int uv_resident_set_memory(size_t* rss);
 +UV_EXTERN int uv_uptime(double* uptime);
 +UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd);
 +UV_EXTERN int uv_open_osfhandle(uv_os_fd_t os_fd);
 +
 +typedef struct {
 +  long tv_sec;
 +  long tv_usec;
 +} uv_timeval_t;
 +
 +typedef struct {
++  int64_t tv_sec;
++  int32_t tv_usec;
++} uv_timeval64_t;
++
++typedef struct {
 +   uv_timeval_t ru_utime; /* user CPU time used */
 +   uv_timeval_t ru_stime; /* system CPU time used */
 +   uint64_t ru_maxrss;    /* maximum resident set size */
 +   uint64_t ru_ixrss;     /* integral shared memory size */
 +   uint64_t ru_idrss;     /* integral unshared data size */
 +   uint64_t ru_isrss;     /* integral unshared stack size */
 +   uint64_t ru_minflt;    /* page reclaims (soft page faults) */
 +   uint64_t ru_majflt;    /* page faults (hard page faults) */
 +   uint64_t ru_nswap;     /* swaps */
 +   uint64_t ru_inblock;   /* block input operations */
 +   uint64_t ru_oublock;   /* block output operations */
 +   uint64_t ru_msgsnd;    /* IPC messages sent */
 +   uint64_t ru_msgrcv;    /* IPC messages received */
 +   uint64_t ru_nsignals;  /* signals received */
 +   uint64_t ru_nvcsw;     /* voluntary context switches */
 +   uint64_t ru_nivcsw;    /* involuntary context switches */
 +} uv_rusage_t;
 +
 +UV_EXTERN int uv_getrusage(uv_rusage_t* rusage);
 +
 +UV_EXTERN int uv_os_homedir(char* buffer, size_t* size);
 +UV_EXTERN int uv_os_tmpdir(char* buffer, size_t* size);
 +UV_EXTERN int uv_os_get_passwd(uv_passwd_t* pwd);
 +UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd);
 +UV_EXTERN uv_pid_t uv_os_getpid(void);
 +UV_EXTERN uv_pid_t uv_os_getppid(void);
 +
 +#define UV_PRIORITY_LOW 19
 +#define UV_PRIORITY_BELOW_NORMAL 10
 +#define UV_PRIORITY_NORMAL 0
 +#define UV_PRIORITY_ABOVE_NORMAL -7
 +#define UV_PRIORITY_HIGH -14
 +#define UV_PRIORITY_HIGHEST -20
 +
 +UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority);
 +UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority);
 +
 +UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
 +UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
 +UV_EXTERN int uv_cpumask_size(void);
 +
 +UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,
 +                                     int* count);
 +UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses,
 +                                           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);
 +
++#ifdef MAXHOSTNAMELEN
++# define UV_MAXHOSTNAMESIZE (MAXHOSTNAMELEN + 1)
++#else
++  /*
++    Fallback for the maximum hostname size, including the null terminator. The
++    Windows gethostname() documentation states that 256 bytes will always be
++    large enough to hold the null-terminated hostname.
++  */
++# define UV_MAXHOSTNAMESIZE 256
++#endif
++
 +UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);
 +
 +UV_EXTERN int uv_os_uname(uv_utsname_t* buffer);
 +
 +
 +typedef enum {
 +  UV_FS_UNKNOWN = -1,
 +  UV_FS_CUSTOM,
 +  UV_FS_OPEN,
 +  UV_FS_CLOSE,
 +  UV_FS_READ,
 +  UV_FS_WRITE,
 +  UV_FS_SENDFILE,
 +  UV_FS_STAT,
 +  UV_FS_LSTAT,
 +  UV_FS_FSTAT,
 +  UV_FS_FTRUNCATE,
 +  UV_FS_UTIME,
 +  UV_FS_FUTIME,
 +  UV_FS_ACCESS,
 +  UV_FS_CHMOD,
 +  UV_FS_FCHMOD,
 +  UV_FS_FSYNC,
 +  UV_FS_FDATASYNC,
 +  UV_FS_UNLINK,
 +  UV_FS_RMDIR,
 +  UV_FS_MKDIR,
 +  UV_FS_MKDTEMP,
 +  UV_FS_RENAME,
 +  UV_FS_SCANDIR,
 +  UV_FS_LINK,
 +  UV_FS_SYMLINK,
 +  UV_FS_READLINK,
 +  UV_FS_CHOWN,
 +  UV_FS_FCHOWN,
 +  UV_FS_REALPATH,
 +  UV_FS_COPYFILE,
-   UV_FS_LCHOWN
++  UV_FS_LCHOWN,
++  UV_FS_OPENDIR,
++  UV_FS_READDIR,
++  UV_FS_CLOSEDIR
 +} uv_fs_type;
 +
++struct uv_dir_s {
++  uv_dirent_t* dirents;
++  size_t nentries;
++  void* reserved[4];
++  UV_DIR_PRIVATE_FIELDS
++};
++
 +/* uv_fs_t is a subclass of uv_req_t. */
 +struct uv_fs_s {
 +  UV_REQ_FIELDS
 +  uv_fs_type fs_type;
 +  uv_loop_t* loop;
 +  uv_fs_cb cb;
 +  ssize_t result;
 +  void* ptr;
 +  const char* path;
 +  uv_stat_t statbuf;  /* Stores the result of uv_fs_stat() and uv_fs_fstat(). */
 +  UV_FS_PRIVATE_FIELDS
 +};
 +
 +UV_EXTERN uv_fs_type uv_fs_get_type(const uv_fs_t*);
 +UV_EXTERN ssize_t uv_fs_get_result(const uv_fs_t*);
 +UV_EXTERN void* uv_fs_get_ptr(const uv_fs_t*);
 +UV_EXTERN const char* uv_fs_get_path(const uv_fs_t*);
 +UV_EXTERN uv_stat_t* uv_fs_get_statbuf(uv_fs_t*);
 +
 +UV_EXTERN void uv_fs_req_cleanup(uv_fs_t* req);
 +UV_EXTERN int uv_fs_close(uv_loop_t* loop,
 +                          uv_fs_t* req,
 +                          uv_file file,
 +                          uv_fs_cb cb);
 +UV_EXTERN int uv_fs_open(uv_loop_t* loop,
 +                         uv_fs_t* req,
 +                         const char* path,
 +                         int flags,
 +                         int mode,
 +                         uv_fs_cb cb);
 +UV_EXTERN int uv_fs_read(uv_loop_t* loop,
 +                         uv_fs_t* req,
 +                         uv_file file,
 +                         const uv_buf_t bufs[],
 +                         unsigned int nbufs,
 +                         int64_t offset,
 +                         uv_fs_cb cb);
 +UV_EXTERN int uv_fs_unlink(uv_loop_t* loop,
 +                           uv_fs_t* req,
 +                           const char* path,
 +                           uv_fs_cb cb);
 +UV_EXTERN int uv_fs_write(uv_loop_t* loop,
 +                          uv_fs_t* req,
 +                          uv_file file,
 +                          const uv_buf_t bufs[],
 +                          unsigned int nbufs,
 +                          int64_t offset,
 +                          uv_fs_cb cb);
 +/*
 + * This flag can be used with uv_fs_copyfile() to return an error if the
 + * destination already exists.
 + */
 +#define UV_FS_COPYFILE_EXCL   0x0001
 +
 +/*
 + * This flag can be used with uv_fs_copyfile() to attempt to create a reflink.
 + * If copy-on-write is not supported, a fallback copy mechanism is used.
 + */
 +#define UV_FS_COPYFILE_FICLONE 0x0002
 +
 +/*
 + * This flag can be used with uv_fs_copyfile() to attempt to create a reflink.
 + * If copy-on-write is not supported, an error is returned.
 + */
 +#define UV_FS_COPYFILE_FICLONE_FORCE 0x0004
 +
 +UV_EXTERN int uv_fs_copyfile(uv_loop_t* loop,
 +                             uv_fs_t* req,
 +                             const char* path,
 +                             const char* new_path,
 +                             int flags,
 +                             uv_fs_cb cb);
 +UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop,
 +                          uv_fs_t* req,
 +                          const char* path,
 +                          int mode,
 +                          uv_fs_cb cb);
 +UV_EXTERN int uv_fs_mkdtemp(uv_loop_t* loop,
 +                            uv_fs_t* req,
 +                            const char* tpl,
 +                            uv_fs_cb cb);
 +UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop,
 +                          uv_fs_t* req,
 +                          const char* path,
 +                          uv_fs_cb cb);
 +UV_EXTERN int uv_fs_scandir(uv_loop_t* loop,
 +                            uv_fs_t* req,
 +                            const char* path,
 +                            int flags,
 +                            uv_fs_cb cb);
 +UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req,
 +                                 uv_dirent_t* ent);
++UV_EXTERN int uv_fs_opendir(uv_loop_t* loop,
++                            uv_fs_t* req,
++                            const char* path,
++                            uv_fs_cb cb);
++UV_EXTERN int uv_fs_readdir(uv_loop_t* loop,
++                            uv_fs_t* req,
++                            uv_dir_t* dir,
++                            uv_fs_cb cb);
++UV_EXTERN int uv_fs_closedir(uv_loop_t* loop,
++                             uv_fs_t* req,
++                             uv_dir_t* dir,
++                             uv_fs_cb cb);
 +UV_EXTERN int uv_fs_stat(uv_loop_t* loop,
 +                         uv_fs_t* req,
 +                         const char* path,
 +                         uv_fs_cb cb);
 +UV_EXTERN int uv_fs_fstat(uv_loop_t* loop,
 +                          uv_fs_t* req,
 +                          uv_file file,
 +                          uv_fs_cb cb);
 +UV_EXTERN int uv_fs_rename(uv_loop_t* loop,
 +                           uv_fs_t* req,
 +                           const char* path,
 +                           const char* new_path,
 +                           uv_fs_cb cb);
 +UV_EXTERN int uv_fs_fsync(uv_loop_t* loop,
 +                          uv_fs_t* req,
 +                          uv_file file,
 +                          uv_fs_cb cb);
 +UV_EXTERN int uv_fs_fdatasync(uv_loop_t* loop,
 +                              uv_fs_t* req,
 +                              uv_file file,
 +                              uv_fs_cb cb);
 +UV_EXTERN int uv_fs_ftruncate(uv_loop_t* loop,
 +                              uv_fs_t* req,
 +                              uv_file file,
 +                              int64_t offset,
 +                              uv_fs_cb cb);
 +UV_EXTERN int uv_fs_sendfile(uv_loop_t* loop,
 +                             uv_fs_t* req,
 +                             uv_file out_fd,
 +                             uv_file in_fd,
 +                             int64_t in_offset,
 +                             size_t length,
 +                             uv_fs_cb cb);
 +UV_EXTERN int uv_fs_access(uv_loop_t* loop,
 +                           uv_fs_t* req,
 +                           const char* path,
 +                           int mode,
 +                           uv_fs_cb cb);
 +UV_EXTERN int uv_fs_chmod(uv_loop_t* loop,
 +                          uv_fs_t* req,
 +                          const char* path,
 +                          int mode,
 +                          uv_fs_cb cb);
 +UV_EXTERN int uv_fs_utime(uv_loop_t* loop,
 +                          uv_fs_t* req,
 +                          const char* path,
 +                          double atime,
 +                          double mtime,
 +                          uv_fs_cb cb);
 +UV_EXTERN int uv_fs_futime(uv_loop_t* loop,
 +                           uv_fs_t* req,
 +                           uv_file file,
 +                           double atime,
 +                           double mtime,
 +                           uv_fs_cb cb);
 +UV_EXTERN int uv_fs_lstat(uv_loop_t* loop,
 +                          uv_fs_t* req,
 +                          const char* path,
 +                          uv_fs_cb cb);
 +UV_EXTERN int uv_fs_link(uv_loop_t* loop,
 +                         uv_fs_t* req,
 +                         const char* path,
 +                         const char* new_path,
 +                         uv_fs_cb cb);
 +
 +/*
 + * This flag can be used with uv_fs_symlink() on Windows to specify whether
 + * path argument points to a directory.
 + */
 +#define UV_FS_SYMLINK_DIR          0x0001
 +
 +/*
 + * This flag can be used with uv_fs_symlink() on Windows to specify whether
 + * the symlink is to be created using junction points.
 + */
 +#define UV_FS_SYMLINK_JUNCTION     0x0002
 +
 +UV_EXTERN int uv_fs_symlink(uv_loop_t* loop,
 +                            uv_fs_t* req,
 +                            const char* path,
 +                            const char* new_path,
 +                            int flags,
 +                            uv_fs_cb cb);
 +UV_EXTERN int uv_fs_readlink(uv_loop_t* loop,
 +                             uv_fs_t* req,
 +                             const char* path,
 +                             uv_fs_cb cb);
 +UV_EXTERN int uv_fs_realpath(uv_loop_t* loop,
 +                             uv_fs_t* req,
 +                             const char* path,
 +                             uv_fs_cb cb);
 +UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop,
 +                           uv_fs_t* req,
 +                           uv_file file,
 +                           int mode,
 +                           uv_fs_cb cb);
 +UV_EXTERN int uv_fs_chown(uv_loop_t* loop,
 +                          uv_fs_t* req,
 +                          const char* path,
 +                          uv_uid_t uid,
 +                          uv_gid_t gid,
 +                          uv_fs_cb cb);
 +UV_EXTERN int uv_fs_fchown(uv_loop_t* loop,
 +                           uv_fs_t* req,
 +                           uv_file file,
 +                           uv_uid_t uid,
 +                           uv_gid_t gid,
 +                           uv_fs_cb cb);
 +UV_EXTERN int uv_fs_lchown(uv_loop_t* loop,
 +                           uv_fs_t* req,
 +                           const char* path,
 +                           uv_uid_t uid,
 +                           uv_gid_t gid,
 +                           uv_fs_cb cb);
 +
 +
 +enum uv_fs_event {
 +  UV_RENAME = 1,
 +  UV_CHANGE = 2
 +};
 +
 +
 +struct uv_fs_event_s {
 +  UV_HANDLE_FIELDS
 +  /* private */
 +  char* path;
 +  UV_FS_EVENT_PRIVATE_FIELDS
 +};
 +
 +
 +/*
 + * uv_fs_stat() based polling file watcher.
 + */
 +struct uv_fs_poll_s {
 +  UV_HANDLE_FIELDS
 +  /* Private, don't touch. */
 +  void* poll_ctx;
 +};
 +
 +UV_EXTERN int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle);
 +UV_EXTERN int uv_fs_poll_start(uv_fs_poll_t* handle,
 +                               uv_fs_poll_cb poll_cb,
 +                               const char* path,
 +                               unsigned int interval);
 +UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle);
 +UV_EXTERN int uv_fs_poll_getpath(uv_fs_poll_t* handle,
 +                                 char* buffer,
 +                                 size_t* size);
 +
 +
 +struct uv_signal_s {
 +  UV_HANDLE_FIELDS
 +  uv_signal_cb signal_cb;
 +  int signum;
 +  UV_SIGNAL_PRIVATE_FIELDS
 +};
 +
 +UV_EXTERN int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle);
 +UV_EXTERN int uv_signal_start(uv_signal_t* handle,
 +                              uv_signal_cb signal_cb,
 +                              int signum);
 +UV_EXTERN int uv_signal_start_oneshot(uv_signal_t* handle,
 +                                      uv_signal_cb signal_cb,
 +                                      int signum);
 +UV_EXTERN int uv_signal_stop(uv_signal_t* handle);
 +
 +UV_EXTERN void uv_loadavg(double avg[3]);
 +
 +
 +/*
 + * Flags to be passed to uv_fs_event_start().
 + */
 +enum uv_fs_event_flags {
 +  /*
 +   * By default, if the fs event watcher is given a directory name, we will
 +   * watch for all events in that directory. This flags overrides this behavior
 +   * and makes fs_event report only changes to the directory entry itself. This
 +   * flag does not affect individual files watched.
 +   * This flag is currently not implemented yet on any backend.
 +   */
 +  UV_FS_EVENT_WATCH_ENTRY = 1,
 +
 +  /*
 +   * By default uv_fs_event will try to use a kernel interface such as inotify
 +   * or kqueue to detect events. This may not work on remote filesystems such
 +   * as NFS mounts. This flag makes fs_event fall back to calling stat() on a
 +   * regular interval.
 +   * This flag is currently not implemented yet on any backend.
 +   */
 +  UV_FS_EVENT_STAT = 2,
 +
 +  /*
 +   * By default, event watcher, when watching directory, is not registering
 +   * (is ignoring) changes in it's subdirectories.
 +   * This flag will override this behaviour on platforms that support it.
 +   */
 +  UV_FS_EVENT_RECURSIVE = 4
 +};
 +
 +
 +UV_EXTERN int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle);
 +UV_EXTERN int uv_fs_event_start(uv_fs_event_t* handle,
 +                                uv_fs_event_cb cb,
 +                                const char* path,
 +                                unsigned int flags);
 +UV_EXTERN int uv_fs_event_stop(uv_fs_event_t* handle);
 +UV_EXTERN int uv_fs_event_getpath(uv_fs_event_t* handle,
 +                                  char* buffer,
 +                                  size_t* size);
 +
 +UV_EXTERN int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr);
 +UV_EXTERN int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr);
 +
 +UV_EXTERN int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size);
 +UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size);
 +
 +UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size);
 +UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst);
 +
 +#if defined(IF_NAMESIZE)
 +# define UV_IF_NAMESIZE (IF_NAMESIZE + 1)
 +#elif defined(IFNAMSIZ)
 +# define UV_IF_NAMESIZE (IFNAMSIZ + 1)
 +#else
 +# define UV_IF_NAMESIZE (16 + 1)
 +#endif
 +
 +UV_EXTERN int uv_if_indextoname(unsigned int ifindex,
 +                                char* buffer,
 +                                size_t* size);
 +UV_EXTERN int uv_if_indextoiid(unsigned int ifindex,
 +                               char* buffer,
 +                               size_t* size);
 +
 +UV_EXTERN int uv_exepath(char* buffer, size_t* size);
 +
 +UV_EXTERN int uv_cwd(char* buffer, size_t* size);
 +
 +UV_EXTERN int uv_chdir(const char* dir);
 +
 +UV_EXTERN uint64_t uv_get_free_memory(void);
 +UV_EXTERN uint64_t uv_get_total_memory(void);
++UV_EXTERN uint64_t uv_get_constrained_memory(void);
 +
 +UV_EXTERN uint64_t uv_hrtime(void);
 +
 +UV_EXTERN void uv_disable_stdio_inheritance(void);
 +
 +UV_EXTERN int uv_dlopen(const char* filename, uv_lib_t* lib);
 +UV_EXTERN void uv_dlclose(uv_lib_t* lib);
 +UV_EXTERN int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr);
 +UV_EXTERN const char* uv_dlerror(const uv_lib_t* lib);
 +
 +UV_EXTERN int uv_mutex_init(uv_mutex_t* handle);
 +UV_EXTERN int uv_mutex_init_recursive(uv_mutex_t* handle);
 +UV_EXTERN void uv_mutex_destroy(uv_mutex_t* handle);
 +UV_EXTERN void uv_mutex_lock(uv_mutex_t* handle);
 +UV_EXTERN int uv_mutex_trylock(uv_mutex_t* handle);
 +UV_EXTERN void uv_mutex_unlock(uv_mutex_t* handle);
 +
 +UV_EXTERN int uv_rwlock_init(uv_rwlock_t* rwlock);
 +UV_EXTERN void uv_rwlock_destroy(uv_rwlock_t* rwlock);
 +UV_EXTERN void uv_rwlock_rdlock(uv_rwlock_t* rwlock);
 +UV_EXTERN int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock);
 +UV_EXTERN void uv_rwlock_rdunlock(uv_rwlock_t* rwlock);
 +UV_EXTERN void uv_rwlock_wrlock(uv_rwlock_t* rwlock);
 +UV_EXTERN int uv_rwlock_trywrlock(uv_rwlock_t* rwlock);
 +UV_EXTERN void uv_rwlock_wrunlock(uv_rwlock_t* rwlock);
 +
 +UV_EXTERN int uv_sem_init(uv_sem_t* sem, unsigned int value);
 +UV_EXTERN void uv_sem_destroy(uv_sem_t* sem);
 +UV_EXTERN void uv_sem_post(uv_sem_t* sem);
 +UV_EXTERN void uv_sem_wait(uv_sem_t* sem);
 +UV_EXTERN int uv_sem_trywait(uv_sem_t* sem);
 +
 +UV_EXTERN int uv_cond_init(uv_cond_t* cond);
 +UV_EXTERN void uv_cond_destroy(uv_cond_t* cond);
 +UV_EXTERN void uv_cond_signal(uv_cond_t* cond);
 +UV_EXTERN void uv_cond_broadcast(uv_cond_t* cond);
 +
 +UV_EXTERN int uv_barrier_init(uv_barrier_t* barrier, unsigned int count);
 +UV_EXTERN void uv_barrier_destroy(uv_barrier_t* barrier);
 +UV_EXTERN int uv_barrier_wait(uv_barrier_t* barrier);
 +
 +UV_EXTERN void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex);
 +UV_EXTERN int uv_cond_timedwait(uv_cond_t* cond,
 +                                uv_mutex_t* mutex,
 +                                uint64_t timeout);
 +
 +UV_EXTERN void uv_once(uv_once_t* guard, void (*callback)(void));
 +
 +UV_EXTERN int uv_key_create(uv_key_t* key);
 +UV_EXTERN void uv_key_delete(uv_key_t* key);
 +UV_EXTERN void* uv_key_get(uv_key_t* key);
 +UV_EXTERN void uv_key_set(uv_key_t* key, void* value);
 +
++UV_EXTERN int uv_gettimeofday(uv_timeval64_t* tv);
++
 +typedef void (*uv_thread_cb)(void* arg);
 +
 +UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg);
++
++typedef enum {
++  UV_THREAD_NO_FLAGS = 0x00,
++  UV_THREAD_HAS_STACK_SIZE = 0x01
++} uv_thread_create_flags;
++
++struct uv_thread_options_s {
++  unsigned int flags;
++  size_t stack_size;
++  /* More fields may be added at any time. */
++};
++
++typedef struct uv_thread_options_s uv_thread_options_t;
++
++UV_EXTERN int uv_thread_create_ex(uv_thread_t* tid,
++                                  const uv_thread_options_t* params,
++                                  uv_thread_cb entry,
++                                  void* arg);
 +UV_EXTERN uv_thread_t uv_thread_self(void);
 +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. */
 +#define XX(_, name) uv_ ## name ## _t name;
 +union uv_any_handle {
 +  UV_HANDLE_TYPE_MAP(XX)
 +};
 +
 +union uv_any_req {
 +  UV_REQ_TYPE_MAP(XX)
 +};
 +#undef XX
 +
 +
 +struct uv_loop_s {
 +  /* User data - use this for whatever. */
 +  void* data;
 +  /* Loop reference counting. */
 +  unsigned int active_handles;
 +  void* handle_queue[2];
 +  union {
 +    void* unused[2];
 +    unsigned int count;
 +  } active_reqs;
 +  /* Internal flag to signal loop stop. */
 +  unsigned int stop_flag;
 +  UV_LOOP_PRIVATE_FIELDS
 +};
 +
 +UV_EXTERN void* uv_loop_get_data(const uv_loop_t*);
 +UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data);
 +
 +/* Don't export the private CPP symbols. */
 +#undef UV_HANDLE_TYPE_PRIVATE
 +#undef UV_REQ_TYPE_PRIVATE
 +#undef UV_REQ_PRIVATE_FIELDS
 +#undef UV_STREAM_PRIVATE_FIELDS
 +#undef UV_TCP_PRIVATE_FIELDS
 +#undef UV_PREPARE_PRIVATE_FIELDS
 +#undef UV_CHECK_PRIVATE_FIELDS
 +#undef UV_IDLE_PRIVATE_FIELDS
 +#undef UV_ASYNC_PRIVATE_FIELDS
 +#undef UV_TIMER_PRIVATE_FIELDS
 +#undef UV_GETADDRINFO_PRIVATE_FIELDS
 +#undef UV_GETNAMEINFO_PRIVATE_FIELDS
 +#undef UV_FS_REQ_PRIVATE_FIELDS
 +#undef UV_WORK_PRIVATE_FIELDS
 +#undef UV_FS_EVENT_PRIVATE_FIELDS
 +#undef UV_SIGNAL_PRIVATE_FIELDS
 +#undef UV_LOOP_PRIVATE_FIELDS
 +#undef UV_LOOP_PRIVATE_PLATFORM_FIELDS
 +#undef UV__ERR
 +
 +#ifdef __cplusplus
 +}
 +#endif
 +#endif /* UV_H */
diff --cc Utilities/cmlibuv/include/uv/unix.h
index 3c1b363,0000000..011abcf
mode 100644,000000..100644
--- a/Utilities/cmlibuv/include/uv/unix.h
+++ b/Utilities/cmlibuv/include/uv/unix.h
@@@ -1,497 -1,0 +1,504 @@@
 +/* 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.
 + */
 +
 +#ifndef UV_UNIX_H
 +#define UV_UNIX_H
 +
 +#include <sys/types.h>
 +#include <sys/stat.h>
 +#include <fcntl.h>
 +#include <dirent.h>
 +
 +#include <sys/socket.h>
 +#include <netinet/in.h>
 +#include <netinet/tcp.h>
 +#include <arpa/inet.h>
- #include <netdb.h>
++#include <netdb.h>  /* MAXHOSTNAMELEN on Solaris */
 +
 +#include <termios.h>
 +#include <pwd.h>
 +
 +#if !defined(__MVS__)
 +#include <semaphore.h>
++#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
 +#endif
 +#include <pthread.h>
 +#include <signal.h>
 +
 +#include "threadpool.h"
 +
 +#ifdef CMAKE_BOOTSTRAP
 +# include "posix.h"
 +#elif defined(__linux__)
 +# include "linux.h"
 +#elif defined (__MVS__)
 +# include "os390.h"
- #elif defined(__PASE__)
- # include "posix.h"
 +#elif defined(_AIX)
 +# include "aix.h"
 +#elif defined(__sun)
 +# include "sunos.h"
 +#elif defined(__APPLE__)
 +# include "darwin.h"
 +#elif defined(__DragonFly__)       || \
 +      defined(__FreeBSD__)         || \
 +      defined(__FreeBSD_kernel__)  || \
 +      defined(__OpenBSD__)         || \
 +      defined(__NetBSD__)
 +# include "bsd.h"
- #elif defined(__CYGWIN__) || defined(__MSYS__)
++#elif defined(__PASE__)   || \
++      defined(__CYGWIN__) || \
++      defined(__MSYS__)   || \
++      defined(__GNU__)
 +# include "posix.h"
- #elif defined(__GNU__)
++#elif defined(__HAIKU__)
 +# include "posix.h"
 +#endif
 +
 +#ifndef NI_MAXHOST
 +# define NI_MAXHOST 1025
 +#endif
 +
 +#ifndef NI_MAXSERV
 +# define NI_MAXSERV 32
 +#endif
 +
 +#ifndef UV_IO_PRIVATE_PLATFORM_FIELDS
 +# define UV_IO_PRIVATE_PLATFORM_FIELDS /* empty */
 +#endif
 +
 +struct uv__io_s;
 +struct uv_loop_s;
 +
 +typedef void (*uv__io_cb)(struct uv_loop_s* loop,
 +                          struct uv__io_s* w,
 +                          unsigned int events);
 +typedef struct uv__io_s uv__io_t;
 +
 +struct uv__io_s {
 +  uv__io_cb cb;
 +  void* pending_queue[2];
 +  void* watcher_queue[2];
 +  unsigned int pevents; /* Pending event mask i.e. mask at next tick. */
 +  unsigned int events;  /* Current event mask. */
 +  int fd;
 +  UV_IO_PRIVATE_PLATFORM_FIELDS
 +};
 +
 +#ifndef UV_PLATFORM_SEM_T
 +# define UV_PLATFORM_SEM_T sem_t
 +#endif
 +
 +#ifndef UV_PLATFORM_LOOP_FIELDS
 +# define UV_PLATFORM_LOOP_FIELDS /* empty */
 +#endif
 +
 +#ifndef UV_PLATFORM_FS_EVENT_FIELDS
 +# define UV_PLATFORM_FS_EVENT_FIELDS /* empty */
 +#endif
 +
 +#ifndef UV_STREAM_PRIVATE_PLATFORM_FIELDS
 +# define UV_STREAM_PRIVATE_PLATFORM_FIELDS /* empty */
 +#endif
 +
 +/* Note: May be cast to struct iovec. See writev(2). */
 +typedef struct uv_buf_t {
 +  char* base;
 +  size_t len;
 +} uv_buf_t;
 +
 +typedef int uv_file;
 +typedef int uv_os_sock_t;
 +typedef int uv_os_fd_t;
 +typedef pid_t uv_pid_t;
 +
 +#ifdef CMAKE_BOOTSTRAP
 +#define UV_ONCE_INIT 0
 +typedef int uv_once_t;
 +typedef int uv_thread_t;
 +typedef int uv_mutex_t;
 +typedef int uv_rwlock_t;
 +typedef int uv_sem_t;
 +typedef int uv_cond_t;
 +typedef int uv_key_t;
 +typedef int uv_barrier_t;
 +#else
 +#define UV_ONCE_INIT PTHREAD_ONCE_INIT
 +
 +typedef pthread_once_t uv_once_t;
 +typedef pthread_t uv_thread_t;
 +typedef pthread_mutex_t uv_mutex_t;
 +typedef pthread_rwlock_t uv_rwlock_t;
 +typedef UV_PLATFORM_SEM_T uv_sem_t;
 +typedef pthread_cond_t uv_cond_t;
 +typedef pthread_key_t uv_key_t;
 +
 +/* Note: guard clauses should match uv_barrier_init's in src/unix/thread.c. */
- #if defined(_AIX) || !defined(PTHREAD_BARRIER_SERIAL_THREAD)
++#if defined(_AIX) || \
++    defined(__OpenBSD__) || \
++    !defined(PTHREAD_BARRIER_SERIAL_THREAD)
 +/* TODO(bnoordhuis) Merge into uv_barrier_t in v2. */
 +struct _uv_barrier {
 +  uv_mutex_t mutex;
 +  uv_cond_t cond;
 +  unsigned threshold;
 +  unsigned in;
 +  unsigned out;
 +};
 +
 +typedef struct {
 +  struct _uv_barrier* b;
 +# if defined(PTHREAD_BARRIER_SERIAL_THREAD)
 +  /* TODO(bnoordhuis) Remove padding in v2. */
 +  char pad[sizeof(pthread_barrier_t) - sizeof(struct _uv_barrier*)];
 +# endif
 +} uv_barrier_t;
 +#else
 +typedef pthread_barrier_t uv_barrier_t;
 +#endif
 +
 +#endif
 +
 +/* Platform-specific definitions for uv_spawn support. */
 +typedef gid_t uv_gid_t;
 +typedef uid_t uv_uid_t;
 +
 +typedef struct dirent uv__dirent_t;
 +
++#define UV_DIR_PRIVATE_FIELDS \
++  DIR* dir;
++
 +#if defined(DT_UNKNOWN)
 +# define HAVE_DIRENT_TYPES
 +# if defined(DT_REG)
 +#  define UV__DT_FILE DT_REG
 +# else
 +#  define UV__DT_FILE -1
 +# endif
 +# if defined(DT_DIR)
 +#  define UV__DT_DIR DT_DIR
 +# else
 +#  define UV__DT_DIR -2
 +# endif
 +# if defined(DT_LNK)
 +#  define UV__DT_LINK DT_LNK
 +# else
 +#  define UV__DT_LINK -3
 +# endif
 +# if defined(DT_FIFO)
 +#  define UV__DT_FIFO DT_FIFO
 +# else
 +#  define UV__DT_FIFO -4
 +# endif
 +# if defined(DT_SOCK)
 +#  define UV__DT_SOCKET DT_SOCK
 +# else
 +#  define UV__DT_SOCKET -5
 +# endif
 +# if defined(DT_CHR)
 +#  define UV__DT_CHAR DT_CHR
 +# else
 +#  define UV__DT_CHAR -6
 +# endif
 +# if defined(DT_BLK)
 +#  define UV__DT_BLOCK DT_BLK
 +# else
 +#  define UV__DT_BLOCK -7
 +# endif
 +#endif
 +
 +/* Platform-specific definitions for uv_dlopen support. */
 +#define UV_DYNAMIC /* empty */
 +
 +typedef struct {
 +  void* handle;
 +  char* errmsg;
 +} uv_lib_t;
 +
 +#define UV_LOOP_PRIVATE_FIELDS                                                \
 +  unsigned long flags;                                                        \
 +  int backend_fd;                                                             \
 +  void* pending_queue[2];                                                     \
 +  void* watcher_queue[2];                                                     \
 +  uv__io_t** watchers;                                                        \
 +  unsigned int nwatchers;                                                     \
 +  unsigned int nfds;                                                          \
 +  void* wq[2];                                                                \
 +  uv_mutex_t wq_mutex;                                                        \
 +  uv_async_t wq_async;                                                        \
 +  uv_rwlock_t cloexec_lock;                                                   \
 +  uv_handle_t* closing_handles;                                               \
 +  void* process_handles[2];                                                   \
 +  void* prepare_handles[2];                                                   \
 +  void* check_handles[2];                                                     \
 +  void* idle_handles[2];                                                      \
 +  void* async_handles[2];                                                     \
 +  void (*async_unused)(void);  /* TODO(bnoordhuis) Remove in libuv v2. */     \
 +  uv__io_t async_io_watcher;                                                  \
 +  int async_wfd;                                                              \
 +  struct {                                                                    \
 +    void* min;                                                                \
 +    unsigned int nelts;                                                       \
 +  } timer_heap;                                                               \
 +  uint64_t timer_counter;                                                     \
 +  uint64_t time;                                                              \
 +  int signal_pipefd[2];                                                       \
 +  uv__io_t signal_io_watcher;                                                 \
 +  uv_signal_t child_watcher;                                                  \
 +  int emfile_fd;                                                              \
 +  UV_PLATFORM_LOOP_FIELDS                                                     \
 +
 +#define UV_REQ_TYPE_PRIVATE /* empty */
 +
 +#define UV_REQ_PRIVATE_FIELDS  /* empty */
 +
 +#define UV_PRIVATE_REQ_TYPES /* empty */
 +
 +#define UV_WRITE_PRIVATE_FIELDS                                               \
 +  void* queue[2];                                                             \
 +  unsigned int write_index;                                                   \
 +  uv_buf_t* bufs;                                                             \
 +  unsigned int nbufs;                                                         \
 +  int error;                                                                  \
 +  uv_buf_t bufsml[4];                                                         \
 +
 +#define UV_CONNECT_PRIVATE_FIELDS                                             \
 +  void* queue[2];                                                             \
 +
 +#define UV_SHUTDOWN_PRIVATE_FIELDS /* empty */
 +
 +#define UV_UDP_SEND_PRIVATE_FIELDS                                            \
 +  void* queue[2];                                                             \
 +  struct sockaddr_storage addr;                                               \
 +  unsigned int nbufs;                                                         \
 +  uv_buf_t* bufs;                                                             \
 +  ssize_t status;                                                             \
 +  uv_udp_send_cb send_cb;                                                     \
 +  uv_buf_t bufsml[4];                                                         \
 +
 +#define UV_HANDLE_PRIVATE_FIELDS                                              \
 +  uv_handle_t* next_closing;                                                  \
 +  unsigned int flags;                                                         \
 +
 +#define UV_STREAM_PRIVATE_FIELDS                                              \
 +  uv_connect_t *connect_req;                                                  \
 +  uv_shutdown_t *shutdown_req;                                                \
 +  uv__io_t io_watcher;                                                        \
 +  void* write_queue[2];                                                       \
 +  void* write_completed_queue[2];                                             \
 +  uv_connection_cb connection_cb;                                             \
 +  int delayed_error;                                                          \
 +  int accepted_fd;                                                            \
 +  void* queued_fds;                                                           \
 +  UV_STREAM_PRIVATE_PLATFORM_FIELDS                                           \
 +
 +#define UV_TCP_PRIVATE_FIELDS /* empty */
 +
 +#define UV_UDP_PRIVATE_FIELDS                                                 \
 +  uv_alloc_cb alloc_cb;                                                       \
 +  uv_udp_recv_cb recv_cb;                                                     \
 +  uv__io_t io_watcher;                                                        \
 +  void* write_queue[2];                                                       \
 +  void* write_completed_queue[2];                                             \
 +
 +#define UV_PIPE_PRIVATE_FIELDS                                                \
 +  const char* pipe_fname; /* strdup'ed */
 +
 +#define UV_POLL_PRIVATE_FIELDS                                                \
 +  uv__io_t io_watcher;
 +
 +#define UV_PREPARE_PRIVATE_FIELDS                                             \
 +  uv_prepare_cb prepare_cb;                                                   \
 +  void* queue[2];                                                             \
 +
 +#define UV_CHECK_PRIVATE_FIELDS                                               \
 +  uv_check_cb check_cb;                                                       \
 +  void* queue[2];                                                             \
 +
 +#define UV_IDLE_PRIVATE_FIELDS                                                \
 +  uv_idle_cb idle_cb;                                                         \
 +  void* queue[2];                                                             \
 +
 +#define UV_ASYNC_PRIVATE_FIELDS                                               \
 +  uv_async_cb async_cb;                                                       \
 +  void* queue[2];                                                             \
 +  int pending;                                                                \
 +
 +#define UV_TIMER_PRIVATE_FIELDS                                               \
 +  uv_timer_cb timer_cb;                                                       \
 +  void* heap_node[3];                                                         \
 +  uint64_t timeout;                                                           \
 +  uint64_t repeat;                                                            \
 +  uint64_t start_id;
 +
 +#define UV_GETADDRINFO_PRIVATE_FIELDS                                         \
 +  struct uv__work work_req;                                                   \
 +  uv_getaddrinfo_cb cb;                                                       \
 +  struct addrinfo* hints;                                                     \
 +  char* hostname;                                                             \
 +  char* service;                                                              \
 +  struct addrinfo* addrinfo;                                                  \
 +  int retcode;
 +
 +#define UV_GETNAMEINFO_PRIVATE_FIELDS                                         \
 +  struct uv__work work_req;                                                   \
 +  uv_getnameinfo_cb getnameinfo_cb;                                           \
 +  struct sockaddr_storage storage;                                            \
 +  int flags;                                                                  \
 +  char host[NI_MAXHOST];                                                      \
 +  char service[NI_MAXSERV];                                                   \
 +  int retcode;
 +
 +#define UV_PROCESS_PRIVATE_FIELDS                                             \
 +  void* queue[2];                                                             \
 +  int status;                                                                 \
 +
 +#define UV_FS_PRIVATE_FIELDS                                                  \
 +  const char *new_path;                                                       \
 +  uv_file file;                                                               \
 +  int flags;                                                                  \
 +  mode_t mode;                                                                \
 +  unsigned int nbufs;                                                         \
 +  uv_buf_t* bufs;                                                             \
 +  off_t off;                                                                  \
 +  uv_uid_t uid;                                                               \
 +  uv_gid_t gid;                                                               \
 +  double atime;                                                               \
 +  double mtime;                                                               \
 +  struct uv__work work_req;                                                   \
 +  uv_buf_t bufsml[4];                                                         \
 +
 +#define UV_WORK_PRIVATE_FIELDS                                                \
 +  struct uv__work work_req;
 +
 +#define UV_TTY_PRIVATE_FIELDS                                                 \
 +  struct termios orig_termios;                                                \
 +  int mode;
 +
 +#define UV_SIGNAL_PRIVATE_FIELDS                                              \
 +  /* RB_ENTRY(uv_signal_s) tree_entry; */                                     \
 +  struct {                                                                    \
 +    struct uv_signal_s* rbe_left;                                             \
 +    struct uv_signal_s* rbe_right;                                            \
 +    struct uv_signal_s* rbe_parent;                                           \
 +    int rbe_color;                                                            \
 +  } tree_entry;                                                               \
 +  /* Use two counters here so we don have to fiddle with atomics. */          \
 +  unsigned int caught_signals;                                                \
 +  unsigned int dispatched_signals;
 +
 +#define UV_FS_EVENT_PRIVATE_FIELDS                                            \
 +  uv_fs_event_cb cb;                                                          \
 +  UV_PLATFORM_FS_EVENT_FIELDS                                                 \
 +
 +/* fs open() flags supported on this platform: */
 +#if defined(O_APPEND)
 +# define UV_FS_O_APPEND       O_APPEND
 +#else
 +# define UV_FS_O_APPEND       0
 +#endif
 +#if defined(O_CREAT)
 +# define UV_FS_O_CREAT        O_CREAT
 +#else
 +# define UV_FS_O_CREAT        0
 +#endif
 +#if defined(O_DIRECT)
 +# define UV_FS_O_DIRECT       O_DIRECT
 +#else
 +# define UV_FS_O_DIRECT       0
 +#endif
 +#if defined(O_DIRECTORY)
 +# define UV_FS_O_DIRECTORY    O_DIRECTORY
 +#else
 +# define UV_FS_O_DIRECTORY    0
 +#endif
 +#if defined(O_DSYNC)
 +# define UV_FS_O_DSYNC        O_DSYNC
 +#else
 +# define UV_FS_O_DSYNC        0
 +#endif
 +#if defined(O_EXCL)
 +# define UV_FS_O_EXCL         O_EXCL
 +#else
 +# define UV_FS_O_EXCL         0
 +#endif
 +#if defined(O_EXLOCK)
 +# define UV_FS_O_EXLOCK       O_EXLOCK
 +#else
 +# define UV_FS_O_EXLOCK       0
 +#endif
 +#if defined(O_NOATIME)
 +# define UV_FS_O_NOATIME      O_NOATIME
 +#else
 +# define UV_FS_O_NOATIME      0
 +#endif
 +#if defined(O_NOCTTY)
 +# define UV_FS_O_NOCTTY       O_NOCTTY
 +#else
 +# define UV_FS_O_NOCTTY       0
 +#endif
 +#if defined(O_NOFOLLOW)
 +# define UV_FS_O_NOFOLLOW     O_NOFOLLOW
 +#else
 +# define UV_FS_O_NOFOLLOW     0
 +#endif
 +#if defined(O_NONBLOCK)
 +# define UV_FS_O_NONBLOCK     O_NONBLOCK
 +#else
 +# define UV_FS_O_NONBLOCK     0
 +#endif
 +#if defined(O_RDONLY)
 +# define UV_FS_O_RDONLY       O_RDONLY
 +#else
 +# define UV_FS_O_RDONLY       0
 +#endif
 +#if defined(O_RDWR)
 +# define UV_FS_O_RDWR         O_RDWR
 +#else
 +# define UV_FS_O_RDWR         0
 +#endif
 +#if defined(O_SYMLINK)
 +# define UV_FS_O_SYMLINK      O_SYMLINK
 +#else
 +# define UV_FS_O_SYMLINK      0
 +#endif
 +#if defined(O_SYNC)
 +# define UV_FS_O_SYNC         O_SYNC
 +#else
 +# define UV_FS_O_SYNC         0
 +#endif
 +#if defined(O_TRUNC)
 +# define UV_FS_O_TRUNC        O_TRUNC
 +#else
 +# define UV_FS_O_TRUNC        0
 +#endif
 +#if defined(O_WRONLY)
 +# define UV_FS_O_WRONLY       O_WRONLY
 +#else
 +# define UV_FS_O_WRONLY       0
 +#endif
 +
 +/* fs open() flags supported on other platforms: */
 +#define UV_FS_O_RANDOM        0
 +#define UV_FS_O_SHORT_LIVED   0
 +#define UV_FS_O_SEQUENTIAL    0
 +#define UV_FS_O_TEMPORARY     0
 +
 +#endif /* UV_UNIX_H */
diff --cc Utilities/cmlibuv/include/uv/win.h
index f3d3809,0000000..7f77cc2
mode 100644,000000..100644
--- a/Utilities/cmlibuv/include/uv/win.h
+++ b/Utilities/cmlibuv/include/uv/win.h
@@@ -1,696 -1,0 +1,701 @@@
 +/* 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.
 + */
 +
 +#ifndef _WIN32_WINNT
 +# define _WIN32_WINNT   0x0600
 +#endif
 +
 +#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
 +typedef intptr_t ssize_t;
 +# define SSIZE_MAX INTPTR_MAX
 +# define _SSIZE_T_
 +# define _SSIZE_T_DEFINED
 +#endif
 +
 +#include <winsock2.h>
 +
 +#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
 +typedef struct pollfd {
 +  SOCKET fd;
 +  short  events;
 +  short  revents;
 +} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD;
 +#endif
 +
 +#ifndef LOCALE_INVARIANT
 +# define LOCALE_INVARIANT 0x007f
 +#endif
 +
 +#include <mswsock.h>
 +#include <ws2tcpip.h>
 +#include <windows.h>
 +
 +#include <process.h>
 +#include <signal.h>
 +#include <fcntl.h>
 +#include <sys/stat.h>
 +
 +#if defined(_MSC_VER) && _MSC_VER < 1600
 +# include "stdint-msvc2008.h"
 +#else
 +# include <stdint.h>
 +#endif
 +
 +#include "tree.h"
 +#include "threadpool.h"
 +
 +#define MAX_PIPENAME_LEN 256
 +
 +#ifndef S_IFLNK
 +# define S_IFLNK 0xA000
 +#endif
 +
 +/* Additional signals supported by uv_signal and or uv_kill. The CRT defines
 + * the following signals already:
 + *
 + *   #define SIGINT           2
 + *   #define SIGILL           4
 + *   #define SIGABRT_COMPAT   6
 + *   #define SIGFPE           8
 + *   #define SIGSEGV         11
 + *   #define SIGTERM         15
 + *   #define SIGBREAK        21
 + *   #define SIGABRT         22
 + *
 + * The additional signals have values that are common on other Unix
 + * variants (Linux and Darwin)
 + */
 +#define SIGHUP                1
 +#define SIGKILL               9
 +#define SIGWINCH             28
 +
 +/* Redefine NSIG to take SIGWINCH into consideration */
 +#if defined(NSIG) && NSIG <= SIGWINCH
 +# undef NSIG
 +#endif
 +#ifndef NSIG
 +# define NSIG SIGWINCH + 1
 +#endif
 +
 +/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many unix-like
 + * platforms. However MinGW doesn't define it, so we do. */
 +#ifndef SIGABRT_COMPAT
 +# define SIGABRT_COMPAT       6
 +#endif
 +
 +/*
 + * Guids and typedefs for winsock extension functions
 + * Mingw32 doesn't have these :-(
 + */
 +#ifndef WSAID_ACCEPTEX
 +# define WSAID_ACCEPTEX                                                       \
 +         {0xb5367df1, 0xcbac, 0x11cf,                                         \
 +         {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
 +#endif
 +
 +#ifndef WSAID_CONNECTEX
 +# define WSAID_CONNECTEX                                                      \
 +         {0x25a207b9, 0xddf3, 0x4660,                                         \
 +         {0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}}
 +#endif
 +
 +#ifndef WSAID_GETACCEPTEXSOCKADDRS
 +# define WSAID_GETACCEPTEXSOCKADDRS                                           \
 +         {0xb5367df2, 0xcbac, 0x11cf,                                         \
 +         {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
 +#endif
 +
 +#ifndef WSAID_DISCONNECTEX
 +# define WSAID_DISCONNECTEX                                                   \
 +         {0x7fda2e11, 0x8630, 0x436f,                                         \
 +         {0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57}}
 +#endif
 +
 +#ifndef WSAID_TRANSMITFILE
 +# define WSAID_TRANSMITFILE                                                   \
 +         {0xb5367df0, 0xcbac, 0x11cf,                                         \
 +         {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
 +#endif
 +
 +#if (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) \
 + || (defined(_MSC_VER) && _MSC_VER < 1500)
 +  typedef BOOL (PASCAL *LPFN_ACCEPTEX)
 +                      (SOCKET sListenSocket,
 +                       SOCKET sAcceptSocket,
 +                       PVOID lpOutputBuffer,
 +                       DWORD dwReceiveDataLength,
 +                       DWORD dwLocalAddressLength,
 +                       DWORD dwRemoteAddressLength,
 +                       LPDWORD lpdwBytesReceived,
 +                       LPOVERLAPPED lpOverlapped);
 +
 +  typedef BOOL (PASCAL *LPFN_CONNECTEX)
 +                      (SOCKET s,
 +                       const struct sockaddr* name,
 +                       int namelen,
 +                       PVOID lpSendBuffer,
 +                       DWORD dwSendDataLength,
 +                       LPDWORD lpdwBytesSent,
 +                       LPOVERLAPPED lpOverlapped);
 +
 +  typedef void (PASCAL *LPFN_GETACCEPTEXSOCKADDRS)
 +                      (PVOID lpOutputBuffer,
 +                       DWORD dwReceiveDataLength,
 +                       DWORD dwLocalAddressLength,
 +                       DWORD dwRemoteAddressLength,
 +                       LPSOCKADDR* LocalSockaddr,
 +                       LPINT LocalSockaddrLength,
 +                       LPSOCKADDR* RemoteSockaddr,
 +                       LPINT RemoteSockaddrLength);
 +
 +  typedef BOOL (PASCAL *LPFN_DISCONNECTEX)
 +                      (SOCKET hSocket,
 +                       LPOVERLAPPED lpOverlapped,
 +                       DWORD dwFlags,
 +                       DWORD reserved);
 +
 +  typedef BOOL (PASCAL *LPFN_TRANSMITFILE)
 +                      (SOCKET hSocket,
 +                       HANDLE hFile,
 +                       DWORD nNumberOfBytesToWrite,
 +                       DWORD nNumberOfBytesPerSend,
 +                       LPOVERLAPPED lpOverlapped,
 +                       LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
 +                       DWORD dwFlags);
 +
 +  typedef PVOID RTL_SRWLOCK;
 +  typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
 +#endif
 +
 +typedef int (WSAAPI* LPFN_WSARECV)
 +            (SOCKET socket,
 +             LPWSABUF buffers,
 +             DWORD buffer_count,
 +             LPDWORD bytes,
 +             LPDWORD flags,
 +             LPWSAOVERLAPPED overlapped,
 +             LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
 +
 +typedef int (WSAAPI* LPFN_WSARECVFROM)
 +            (SOCKET socket,
 +             LPWSABUF buffers,
 +             DWORD buffer_count,
 +             LPDWORD bytes,
 +             LPDWORD flags,
 +             struct sockaddr* addr,
 +             LPINT addr_len,
 +             LPWSAOVERLAPPED overlapped,
 +             LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
 +
 +#ifndef _NTDEF_
 +  typedef LONG NTSTATUS;
 +  typedef NTSTATUS *PNTSTATUS;
 +#endif
 +
 +#ifndef RTL_CONDITION_VARIABLE_INIT
 +  typedef PVOID CONDITION_VARIABLE, *PCONDITION_VARIABLE;
 +#endif
 +
 +typedef struct _AFD_POLL_HANDLE_INFO {
 +  HANDLE Handle;
 +  ULONG Events;
 +  NTSTATUS Status;
 +} AFD_POLL_HANDLE_INFO, *PAFD_POLL_HANDLE_INFO;
 +
 +typedef struct _AFD_POLL_INFO {
 +  LARGE_INTEGER Timeout;
 +  ULONG NumberOfHandles;
 +  ULONG Exclusive;
 +  AFD_POLL_HANDLE_INFO Handles[1];
 +} AFD_POLL_INFO, *PAFD_POLL_INFO;
 +
 +#define UV_MSAFD_PROVIDER_COUNT 3
 +
 +
 +/**
 + * It should be possible to cast uv_buf_t[] to WSABUF[]
 + * see http://msdn.microsoft.com/en-us/library/ms741542(v=vs.85).aspx
 + */
 +typedef struct uv_buf_t {
 +  ULONG len;
 +  char* base;
 +} uv_buf_t;
 +
 +typedef int uv_file;
 +typedef SOCKET uv_os_sock_t;
 +typedef HANDLE uv_os_fd_t;
 +typedef int uv_pid_t;
 +
 +typedef HANDLE uv_thread_t;
 +
 +typedef HANDLE uv_sem_t;
 +
 +typedef CRITICAL_SECTION uv_mutex_t;
 +
 +/* This condition variable implementation is based on the SetEvent solution
 + * (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
 + * We could not use the SignalObjectAndWait solution (section 3.4) because
 + * it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and
 + * uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs.
 + */
 +
 +typedef union {
 +  CONDITION_VARIABLE cond_var;
 +  struct {
 +    unsigned int waiters_count;
 +    CRITICAL_SECTION waiters_count_lock;
 +    HANDLE signal_event;
 +    HANDLE broadcast_event;
 +  } unused_; /* TODO: retained for ABI compatibility; remove me in v2.x. */
 +} uv_cond_t;
 +
 +typedef union {
 +  struct {
 +    unsigned int num_readers_;
 +    CRITICAL_SECTION num_readers_lock_;
 +    HANDLE write_semaphore_;
 +  } state_;
 +  /* TODO: remove me in v2.x. */
 +  struct {
 +    SRWLOCK unused_;
 +  } unused1_;
 +  /* TODO: remove me in v2.x. */
 +  struct {
 +    uv_mutex_t unused1_;
 +    uv_mutex_t unused2_;
 +  } unused2_;
 +} uv_rwlock_t;
 +
 +typedef struct {
 +  unsigned int n;
 +  unsigned int count;
 +  uv_mutex_t mutex;
 +  uv_sem_t turnstile1;
 +  uv_sem_t turnstile2;
 +} uv_barrier_t;
 +
 +typedef struct {
 +  DWORD tls_index;
 +} uv_key_t;
 +
 +#define UV_ONCE_INIT { 0, NULL }
 +
 +typedef struct uv_once_s {
 +  unsigned char ran;
 +  HANDLE event;
 +} uv_once_t;
 +
 +/* Platform-specific definitions for uv_spawn support. */
 +typedef unsigned char uv_uid_t;
 +typedef unsigned char uv_gid_t;
 +
 +typedef struct uv__dirent_s {
 +  int d_type;
 +  char d_name[1];
 +} uv__dirent_t;
 +
++#define UV_DIR_PRIVATE_FIELDS \
++  HANDLE dir_handle;          \
++  WIN32_FIND_DATAW find_data; \
++  BOOL need_find_call;
++
 +#define HAVE_DIRENT_TYPES
 +#define UV__DT_DIR     UV_DIRENT_DIR
 +#define UV__DT_FILE    UV_DIRENT_FILE
 +#define UV__DT_LINK    UV_DIRENT_LINK
 +#define UV__DT_FIFO    UV_DIRENT_FIFO
 +#define UV__DT_SOCKET  UV_DIRENT_SOCKET
 +#define UV__DT_CHAR    UV_DIRENT_CHAR
 +#define UV__DT_BLOCK   UV_DIRENT_BLOCK
 +
 +/* Platform-specific definitions for uv_dlopen support. */
 +#define UV_DYNAMIC FAR WINAPI
 +typedef struct {
 +  HMODULE handle;
 +  char* errmsg;
 +} uv_lib_t;
 +
 +#define UV_LOOP_PRIVATE_FIELDS                                                \
 +    /* The loop's I/O completion port */                                      \
 +  HANDLE iocp;                                                                \
 +  /* The current time according to the event loop. in msecs. */               \
 +  uint64_t time;                                                              \
 +  /* Tail of a single-linked circular queue of pending reqs. If the queue */  \
 +  /* is empty, tail_ is NULL. If there is only one item, */                   \
 +  /* tail_->next_req == tail_ */                                              \
 +  uv_req_t* pending_reqs_tail;                                                \
 +  /* Head of a single-linked list of closed handles */                        \
 +  uv_handle_t* endgame_handles;                                               \
 +  /* TODO(bnoordhuis) Stop heap-allocating |timer_heap| in libuv v2.x. */     \
 +  void* timer_heap;                                                           \
 +    /* Lists of active loop (prepare / check / idle) watchers */              \
 +  uv_prepare_t* prepare_handles;                                              \
 +  uv_check_t* check_handles;                                                  \
 +  uv_idle_t* idle_handles;                                                    \
 +  /* This pointer will refer to the prepare/check/idle handle whose */        \
 +  /* callback is scheduled to be called next. This is needed to allow */      \
 +  /* safe removal from one of the lists above while that list being */        \
 +  /* iterated over. */                                                        \
 +  uv_prepare_t* next_prepare_handle;                                          \
 +  uv_check_t* next_check_handle;                                              \
 +  uv_idle_t* next_idle_handle;                                                \
 +  /* This handle holds the peer sockets for the fast variant of uv_poll_t */  \
 +  SOCKET poll_peer_sockets[UV_MSAFD_PROVIDER_COUNT];                          \
 +  /* Counter to keep track of active tcp streams */                           \
 +  unsigned int active_tcp_streams;                                            \
 +  /* Counter to keep track of active udp streams */                           \
 +  unsigned int active_udp_streams;                                            \
 +  /* Counter to started timer */                                              \
 +  uint64_t timer_counter;                                                     \
 +  /* Threadpool */                                                            \
 +  void* wq[2];                                                                \
 +  uv_mutex_t wq_mutex;                                                        \
 +  uv_async_t wq_async;
 +
 +#define UV_REQ_TYPE_PRIVATE                                                   \
 +  /* TODO: remove the req suffix */                                           \
 +  UV_ACCEPT,                                                                  \
 +  UV_FS_EVENT_REQ,                                                            \
 +  UV_POLL_REQ,                                                                \
 +  UV_PROCESS_EXIT,                                                            \
 +  UV_READ,                                                                    \
 +  UV_UDP_RECV,                                                                \
 +  UV_WAKEUP,                                                                  \
 +  UV_SIGNAL_REQ,
 +
 +#define UV_REQ_PRIVATE_FIELDS                                                 \
 +  union {                                                                     \
 +    /* Used by I/O operations */                                              \
 +    struct {                                                                  \
 +      OVERLAPPED overlapped;                                                  \
 +      size_t queued_bytes;                                                    \
 +    } io;                                                                     \
 +  } u;                                                                        \
 +  struct uv_req_s* next_req;
 +
 +#define UV_WRITE_PRIVATE_FIELDS \
 +  int coalesced;                \
 +  uv_buf_t write_buffer;        \
 +  HANDLE event_handle;          \
 +  HANDLE wait_handle;
 +
 +#define UV_CONNECT_PRIVATE_FIELDS                                             \
 +  /* empty */
 +
 +#define UV_SHUTDOWN_PRIVATE_FIELDS                                            \
 +  /* empty */
 +
 +#define UV_UDP_SEND_PRIVATE_FIELDS                                            \
 +  /* empty */
 +
 +#define UV_PRIVATE_REQ_TYPES                                                  \
 +  typedef struct uv_pipe_accept_s {                                           \
 +    UV_REQ_FIELDS                                                             \
 +    HANDLE pipeHandle;                                                        \
 +    struct uv_pipe_accept_s* next_pending;                                    \
 +  } uv_pipe_accept_t;                                                         \
 +                                                                              \
 +  typedef struct uv_tcp_accept_s {                                            \
 +    UV_REQ_FIELDS                                                             \
 +    SOCKET accept_socket;                                                     \
 +    char accept_buffer[sizeof(struct sockaddr_storage) * 2 + 32];             \
 +    HANDLE event_handle;                                                      \
 +    HANDLE wait_handle;                                                       \
 +    struct uv_tcp_accept_s* next_pending;                                     \
 +  } uv_tcp_accept_t;                                                          \
 +                                                                              \
 +  typedef struct uv_read_s {                                                  \
 +    UV_REQ_FIELDS                                                             \
 +    HANDLE event_handle;                                                      \
 +    HANDLE wait_handle;                                                       \
 +  } uv_read_t;
 +
 +#define uv_stream_connection_fields                                           \
 +  unsigned int write_reqs_pending;                                            \
 +  uv_shutdown_t* shutdown_req;
 +
 +#define uv_stream_server_fields                                               \
 +  uv_connection_cb connection_cb;
 +
 +#define UV_STREAM_PRIVATE_FIELDS                                              \
 +  unsigned int reqs_pending;                                                  \
 +  int activecnt;                                                              \
 +  uv_read_t read_req;                                                         \
 +  union {                                                                     \
 +    struct { uv_stream_connection_fields } conn;                              \
 +    struct { uv_stream_server_fields     } serv;                              \
 +  } stream;
 +
 +#define uv_tcp_server_fields                                                  \
 +  uv_tcp_accept_t* accept_reqs;                                               \
 +  unsigned int processed_accepts;                                             \
 +  uv_tcp_accept_t* pending_accepts;                                           \
 +  LPFN_ACCEPTEX func_acceptex;
 +
 +#define uv_tcp_connection_fields                                              \
 +  uv_buf_t read_buffer;                                                       \
 +  LPFN_CONNECTEX func_connectex;
 +
 +#define UV_TCP_PRIVATE_FIELDS                                                 \
 +  SOCKET socket;                                                              \
 +  int delayed_error;                                                          \
 +  union {                                                                     \
 +    struct { uv_tcp_server_fields } serv;                                     \
 +    struct { uv_tcp_connection_fields } conn;                                 \
 +  } tcp;
 +
 +#define UV_UDP_PRIVATE_FIELDS                                                 \
 +  SOCKET socket;                                                              \
 +  unsigned int reqs_pending;                                                  \
 +  int activecnt;                                                              \
 +  uv_req_t recv_req;                                                          \
 +  uv_buf_t recv_buffer;                                                       \
 +  struct sockaddr_storage recv_from;                                          \
 +  int recv_from_len;                                                          \
 +  uv_udp_recv_cb recv_cb;                                                     \
 +  uv_alloc_cb alloc_cb;                                                       \
 +  LPFN_WSARECV func_wsarecv;                                                  \
 +  LPFN_WSARECVFROM func_wsarecvfrom;
 +
 +#define uv_pipe_server_fields                                                 \
 +  int pending_instances;                                                      \
 +  uv_pipe_accept_t* accept_reqs;                                              \
 +  uv_pipe_accept_t* pending_accepts;
 +
 +#define uv_pipe_connection_fields                                             \
 +  uv_timer_t* eof_timer;                                                      \
 +  uv_write_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \
 +  DWORD ipc_remote_pid;                                                       \
 +  union {                                                                     \
 +    uint32_t payload_remaining;                                               \
 +    uint64_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \
 +  } ipc_data_frame;                                                           \
 +  void* ipc_xfer_queue[2];                                                    \
 +  int ipc_xfer_queue_length;                                                  \
 +  uv_write_t* non_overlapped_writes_tail;                                     \
 +  CRITICAL_SECTION readfile_thread_lock;                                      \
 +  volatile HANDLE readfile_thread_handle;
 +
 +#define UV_PIPE_PRIVATE_FIELDS                                                \
 +  HANDLE handle;                                                              \
 +  WCHAR* name;                                                                \
 +  union {                                                                     \
 +    struct { uv_pipe_server_fields } serv;                                    \
 +    struct { uv_pipe_connection_fields } conn;                                \
 +  } pipe;
 +
 +/* TODO: put the parser states in an union - TTY handles are always half-duplex
 + * so read-state can safely overlap write-state. */
 +#define UV_TTY_PRIVATE_FIELDS                                                 \
 +  HANDLE handle;                                                              \
 +  union {                                                                     \
 +    struct {                                                                  \
 +      /* Used for readable TTY handles */                                     \
 +      /* TODO: remove me in v2.x. */                                          \
 +      HANDLE unused_;                                                         \
 +      uv_buf_t read_line_buffer;                                              \
 +      HANDLE read_raw_wait;                                                   \
 +      /* Fields used for translating win keystrokes into vt100 characters */  \
 +      char last_key[8];                                                       \
 +      unsigned char last_key_offset;                                          \
 +      unsigned char last_key_len;                                             \
 +      WCHAR last_utf16_high_surrogate;                                        \
 +      INPUT_RECORD last_input_record;                                         \
 +    } rd;                                                                     \
 +    struct {                                                                  \
 +      /* Used for writable TTY handles */                                     \
 +      /* utf8-to-utf16 conversion state */                                    \
 +      unsigned int utf8_codepoint;                                            \
 +      unsigned char utf8_bytes_left;                                          \
 +      /* eol conversion state */                                              \
 +      unsigned char previous_eol;                                             \
 +      /* ansi parser state */                                                 \
 +      unsigned char ansi_parser_state;                                        \
 +      unsigned char ansi_csi_argc;                                            \
 +      unsigned short ansi_csi_argv[4];                                        \
 +      COORD saved_position;                                                   \
 +      WORD saved_attributes;                                                  \
 +    } wr;                                                                     \
 +  } tty;
 +
 +#define UV_POLL_PRIVATE_FIELDS                                                \
 +  SOCKET socket;                                                              \
 +  /* Used in fast mode */                                                     \
 +  SOCKET peer_socket;                                                         \
 +  AFD_POLL_INFO afd_poll_info_1;                                              \
 +  AFD_POLL_INFO afd_poll_info_2;                                              \
 +  /* Used in fast and slow mode. */                                           \
 +  uv_req_t poll_req_1;                                                        \
 +  uv_req_t poll_req_2;                                                        \
 +  unsigned char submitted_events_1;                                           \
 +  unsigned char submitted_events_2;                                           \
 +  unsigned char mask_events_1;                                                \
 +  unsigned char mask_events_2;                                                \
 +  unsigned char events;
 +
 +#define UV_TIMER_PRIVATE_FIELDS                                               \
 +  void* heap_node[3];                                                         \
 +  int unused;                                                                 \
 +  uint64_t timeout;                                                           \
 +  uint64_t repeat;                                                            \
 +  uint64_t start_id;                                                          \
 +  uv_timer_cb timer_cb;
 +
 +#define UV_ASYNC_PRIVATE_FIELDS                                               \
 +  struct uv_req_s async_req;                                                  \
 +  uv_async_cb async_cb;                                                       \
 +  /* char to avoid alignment issues */                                        \
 +  char volatile async_sent;
 +
 +#define UV_PREPARE_PRIVATE_FIELDS                                             \
 +  uv_prepare_t* prepare_prev;                                                 \
 +  uv_prepare_t* prepare_next;                                                 \
 +  uv_prepare_cb prepare_cb;
 +
 +#define UV_CHECK_PRIVATE_FIELDS                                               \
 +  uv_check_t* check_prev;                                                     \
 +  uv_check_t* check_next;                                                     \
 +  uv_check_cb check_cb;
 +
 +#define UV_IDLE_PRIVATE_FIELDS                                                \
 +  uv_idle_t* idle_prev;                                                       \
 +  uv_idle_t* idle_next;                                                       \
 +  uv_idle_cb idle_cb;
 +
 +#define UV_HANDLE_PRIVATE_FIELDS                                              \
 +  uv_handle_t* endgame_next;                                                  \
 +  unsigned int flags;
 +
 +#define UV_GETADDRINFO_PRIVATE_FIELDS                                         \
 +  struct uv__work work_req;                                                   \
 +  uv_getaddrinfo_cb getaddrinfo_cb;                                           \
 +  void* alloc;                                                                \
 +  WCHAR* node;                                                                \
 +  WCHAR* service;                                                             \
 +  /* The addrinfoW field is used to store a pointer to the hints, and    */   \
 +  /* later on to store the result of GetAddrInfoW. The final result will */   \
 +  /* be converted to struct addrinfo* and stored in the addrinfo field.  */   \
 +  struct addrinfoW* addrinfow;                                                \
 +  struct addrinfo* addrinfo;                                                  \
 +  int retcode;
 +
 +#define UV_GETNAMEINFO_PRIVATE_FIELDS                                         \
 +  struct uv__work work_req;                                                   \
 +  uv_getnameinfo_cb getnameinfo_cb;                                           \
 +  struct sockaddr_storage storage;                                            \
 +  int flags;                                                                  \
 +  char host[NI_MAXHOST];                                                      \
 +  char service[NI_MAXSERV];                                                   \
 +  int retcode;
 +
 +#define UV_PROCESS_PRIVATE_FIELDS                                             \
 +  struct uv_process_exit_s {                                                  \
 +    UV_REQ_FIELDS                                                             \
 +  } exit_req;                                                                 \
 +  BYTE* child_stdio_buffer;                                                   \
 +  int exit_signal;                                                            \
 +  HANDLE wait_handle;                                                         \
 +  HANDLE process_handle;                                                      \
 +  volatile char exit_cb_pending;
 +
 +#define UV_FS_PRIVATE_FIELDS                                                  \
 +  struct uv__work work_req;                                                   \
 +  int flags;                                                                  \
 +  DWORD sys_errno_;                                                           \
 +  union {                                                                     \
 +    /* TODO: remove me in 0.9. */                                             \
 +    WCHAR* pathw;                                                             \
 +    int fd;                                                                   \
 +  } file;                                                                     \
 +  union {                                                                     \
 +    struct {                                                                  \
 +      int mode;                                                               \
 +      WCHAR* new_pathw;                                                       \
 +      int file_flags;                                                         \
 +      int fd_out;                                                             \
 +      unsigned int nbufs;                                                     \
 +      uv_buf_t* bufs;                                                         \
 +      int64_t offset;                                                         \
 +      uv_buf_t bufsml[4];                                                     \
 +    } info;                                                                   \
 +    struct {                                                                  \
 +      double atime;                                                           \
 +      double mtime;                                                           \
 +    } time;                                                                   \
 +  } fs;
 +
 +#define UV_WORK_PRIVATE_FIELDS                                                \
 +  struct uv__work work_req;
 +
 +#define UV_FS_EVENT_PRIVATE_FIELDS                                            \
 +  struct uv_fs_event_req_s {                                                  \
 +    UV_REQ_FIELDS                                                             \
 +  } req;                                                                      \
 +  HANDLE dir_handle;                                                          \
 +  int req_pending;                                                            \
 +  uv_fs_event_cb cb;                                                          \
 +  WCHAR* filew;                                                               \
 +  WCHAR* short_filew;                                                         \
 +  WCHAR* dirw;                                                                \
 +  char* buffer;
 +
 +#define UV_SIGNAL_PRIVATE_FIELDS                                              \
 +  RB_ENTRY(uv_signal_s) tree_entry;                                           \
 +  struct uv_req_s signal_req;                                                 \
 +  unsigned long pending_signum;
 +
 +#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
 +
 +/* fs open() flags supported on this platform: */
 +#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_RANDOM       _O_RANDOM
 +#define UV_FS_O_RDONLY       _O_RDONLY
 +#define UV_FS_O_RDWR         _O_RDWR
 +#define UV_FS_O_SEQUENTIAL   _O_SEQUENTIAL
 +#define UV_FS_O_SHORT_LIVED  _O_SHORT_LIVED
 +#define UV_FS_O_TEMPORARY    _O_TEMPORARY
 +#define UV_FS_O_TRUNC        _O_TRUNC
 +#define UV_FS_O_WRONLY       _O_WRONLY
 +
 +/* fs open() flags supported on other platforms (or mapped on this platform): */
 +#define UV_FS_O_DIRECT       0x02000000 /* FILE_FLAG_NO_BUFFERING */
 +#define UV_FS_O_DIRECTORY    0
 +#define UV_FS_O_DSYNC        0x04000000 /* FILE_FLAG_WRITE_THROUGH */
 +#define UV_FS_O_EXLOCK       0x10000000 /* EXCLUSIVE SHARING MODE */
 +#define UV_FS_O_NOATIME      0
 +#define UV_FS_O_NOCTTY       0
 +#define UV_FS_O_NOFOLLOW     0
 +#define UV_FS_O_NONBLOCK     0
 +#define UV_FS_O_SYMLINK      0
 +#define UV_FS_O_SYNC         0x08000000 /* FILE_FLAG_WRITE_THROUGH */
diff --cc Utilities/cmlibuv/src/unix/atomic-ops.h
index be741dc,0000000..995aca6
mode 100644,000000..100644
--- a/Utilities/cmlibuv/src/unix/atomic-ops.h
+++ b/Utilities/cmlibuv/src/unix/atomic-ops.h
@@@ -1,100 -1,0 +1,63 @@@
 +/* Copyright (c) 2013, Ben Noordhuis <info at bnoordhuis.nl>
 + *
 + * Permission to use, copy, modify, and/or distribute this software for any
 + * purpose with or without fee is hereby granted, provided that the above
 + * copyright notice and this permission notice appear in all copies.
 + *
 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 + */
 +
 +#ifndef UV_ATOMIC_OPS_H_
 +#define UV_ATOMIC_OPS_H_
 +
 +#include "internal.h"  /* UV_UNUSED */
 +
 +#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
 +#include <atomic.h>
 +#endif
 +
 +UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval));
- UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval));
 +UV_UNUSED(static void cpu_relax(void));
 +
 +/* Prefer hand-rolled assembly over the gcc builtins because the latter also
 + * issue full memory barriers.
 + */
 +UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
 +#if defined(__i386__) || defined(__x86_64__)
 +  int out;
 +  __asm__ __volatile__ ("lock; cmpxchg %2, %1;"
 +                        : "=a" (out), "+m" (*(volatile int*) ptr)
 +                        : "r" (newval), "0" (oldval)
 +                        : "memory");
 +  return out;
 +#elif defined(_AIX) && (defined(__xlC__) || defined(__ibmxl__))
 +  const int out = (*(volatile int*) ptr);
 +  __compare_and_swap(ptr, &oldval, newval);
 +  return out;
 +#elif defined(__MVS__)
 +  unsigned int op4;
 +  if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
 +                (unsigned int*) ptr, *ptr, &op4))
 +    return oldval;
 +  else
 +    return op4;
 +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-   return atomic_cas_uint(ptr, oldval, newval);
- #else
-   return __sync_val_compare_and_swap(ptr, oldval, newval);
- #endif
- }
- 
- UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) {
- #if defined(__i386__) || defined(__x86_64__)
-   long out;
-   __asm__ __volatile__ ("lock; cmpxchg %2, %1;"
-                         : "=a" (out), "+m" (*(volatile long*) ptr)
-                         : "r" (newval), "0" (oldval)
-                         : "memory");
-   return out;
- #elif defined(_AIX) && (defined(__xlC__) || defined(__ibmxl__))
-   const long out = (*(volatile int*) ptr);
- # if defined(__64BIT__)
-   __compare_and_swaplp(ptr, &oldval, newval);
- # else
-   __compare_and_swap(ptr, &oldval, newval);
- # endif /* if defined(__64BIT__) */
-   return out;
- #elif defined (__MVS__)
- #ifdef _LP64
-   unsigned long long op4;
-   if (__plo_CSSTGR(ptr, (unsigned long long*) &oldval, newval,
-                   (unsigned long long*) ptr, *ptr, &op4))
- #else
-   unsigned long op4;
-   if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
-                 (unsigned int*) ptr, *ptr, &op4))
- #endif
-     return oldval;
-   else
-     return op4;
- #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-   return atomic_cas_ulong(ptr, oldval, newval);
++  return atomic_cas_uint((uint_t *)ptr, (uint_t)oldval, (uint_t)newval);
 +#else
 +  return __sync_val_compare_and_swap(ptr, oldval, newval);
 +#endif
 +}
 +
 +UV_UNUSED(static void cpu_relax(void)) {
 +#if defined(__i386__) || defined(__x86_64__)
 +  __asm__ __volatile__ ("rep; nop");  /* a.k.a. PAUSE */
 +#endif
 +}
 +
 +#endif  /* UV_ATOMIC_OPS_H_ */
diff --cc Utilities/cmlibuv/src/unix/core.c
index a8d6adb,0000000..93df7af
mode 100644,000000..100644
--- a/Utilities/cmlibuv/src/unix/core.c
+++ b/Utilities/cmlibuv/src/unix/core.c
@@@ -1,1428 -1,0 +1,1490 @@@
 +/* 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 "internal.h"
 +
 +#include <stddef.h> /* NULL */
 +#include <stdio.h> /* printf */
 +#include <stdlib.h>
 +#include <string.h> /* strerror */
 +#include <errno.h>
 +#include <assert.h>
 +#include <unistd.h>
 +#include <sys/types.h>
 +#include <sys/stat.h>
 +#include <fcntl.h>
 +#include <sys/ioctl.h>
 +#include <sys/socket.h>
 +#include <sys/un.h>
 +#include <netinet/in.h>
 +#include <arpa/inet.h>
 +#include <limits.h> /* INT_MAX, PATH_MAX, IOV_MAX */
 +#include <sys/uio.h> /* writev */
 +#include <sys/resource.h> /* getrusage */
 +#include <pwd.h>
 +#include <sched.h>
 +#include <sys/utsname.h>
++#include <sys/time.h>
 +
 +#ifdef __sun
- # include <netdb.h> /* MAXHOSTNAMELEN on Solaris */
 +# include <sys/filio.h>
 +# include <sys/types.h>
 +# include <sys/wait.h>
 +#endif
 +
 +#ifdef __APPLE__
 +# include <mach-o/dyld.h> /* _NSGetExecutablePath */
 +# include <sys/filio.h>
 +# if defined(O_CLOEXEC)
 +#  define UV__O_CLOEXEC O_CLOEXEC
 +# endif
 +#endif
 +
 +#if defined(__DragonFly__)      || \
 +    defined(__FreeBSD__)        || \
 +    defined(__FreeBSD_kernel__) || \
 +    defined(__NetBSD__)
 +# include <sys/sysctl.h>
 +# include <sys/filio.h>
 +# include <sys/wait.h>
 +# include <sys/param.h>
 +# include <sys/cpuset.h>
 +# define UV__O_CLOEXEC O_CLOEXEC
 +# if defined(__FreeBSD__) && __FreeBSD__ >= 10
 +#  define uv__accept4 accept4
 +# endif
 +# if defined(__NetBSD__)
 +#  define uv__accept4(a, b, c, d) paccept((a), (b), (c), NULL, (d))
 +# endif
 +# if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
 +#  define UV__SOCK_NONBLOCK SOCK_NONBLOCK
 +#  define UV__SOCK_CLOEXEC  SOCK_CLOEXEC
 +# endif
 +# if !defined(F_DUP2FD_CLOEXEC) && defined(_F_DUP2FD_CLOEXEC)
 +#  define F_DUP2FD_CLOEXEC  _F_DUP2FD_CLOEXEC
 +# endif
 +#endif
 +
 +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
 +# include <dlfcn.h>  /* for dlsym */
 +#endif
 +
 +#if defined(__MVS__)
 +#include <sys/ioctl.h>
 +#endif
 +
- #if !defined(__MVS__)
- #include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
- #endif
- 
- /* Fallback for the maximum hostname length */
- #ifndef MAXHOSTNAMELEN
- # define MAXHOSTNAMELEN 256
++#if defined(__linux__)
++#include <sys/syscall.h>
 +#endif
 +
 +static int uv__run_pending(uv_loop_t* loop);
 +
 +/* Verify that uv_buf_t is ABI-compatible with struct iovec. */
 +STATIC_ASSERT(sizeof(uv_buf_t) == sizeof(struct iovec));
 +STATIC_ASSERT(sizeof(&((uv_buf_t*) 0)->base) ==
 +              sizeof(((struct iovec*) 0)->iov_base));
 +STATIC_ASSERT(sizeof(&((uv_buf_t*) 0)->len) ==
 +              sizeof(((struct iovec*) 0)->iov_len));
 +STATIC_ASSERT(offsetof(uv_buf_t, base) == offsetof(struct iovec, iov_base));
 +STATIC_ASSERT(offsetof(uv_buf_t, len) == offsetof(struct iovec, iov_len));
 +
 +
 +uint64_t uv_hrtime(void) {
 +  return uv__hrtime(UV_CLOCK_PRECISE);
 +}
 +
 +
 +void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
 +  assert(!uv__is_closing(handle));
 +
 +  handle->flags |= UV_HANDLE_CLOSING;
 +  handle->close_cb = close_cb;
 +
 +  switch (handle->type) {
 +  case UV_NAMED_PIPE:
 +    uv__pipe_close((uv_pipe_t*)handle);
 +    break;
 +
 +  case UV_TTY:
 +    uv__stream_close((uv_stream_t*)handle);
 +    break;
 +
 +  case UV_TCP:
 +    uv__tcp_close((uv_tcp_t*)handle);
 +    break;
 +
 +  case UV_UDP:
 +    uv__udp_close((uv_udp_t*)handle);
 +    break;
 +
 +  case UV_PREPARE:
 +    uv__prepare_close((uv_prepare_t*)handle);
 +    break;
 +
 +  case UV_CHECK:
 +    uv__check_close((uv_check_t*)handle);
 +    break;
 +
 +  case UV_IDLE:
 +    uv__idle_close((uv_idle_t*)handle);
 +    break;
 +
 +  case UV_ASYNC:
 +    uv__async_close((uv_async_t*)handle);
 +    break;
 +
 +  case UV_TIMER:
 +    uv__timer_close((uv_timer_t*)handle);
 +    break;
 +
 +  case UV_PROCESS:
 +    uv__process_close((uv_process_t*)handle);
 +    break;
 +
 +  case UV_FS_EVENT:
 +    uv__fs_event_close((uv_fs_event_t*)handle);
 +    break;
 +
 +  case UV_POLL:
 +    uv__poll_close((uv_poll_t*)handle);
 +    break;
 +
 +  case UV_FS_POLL:
 +    uv__fs_poll_close((uv_fs_poll_t*)handle);
-     break;
++    /* Poll handles use file system requests, and one of them may still be
++     * running. The poll code will call uv__make_close_pending() for us. */
++    return;
 +
 +  case UV_SIGNAL:
 +    uv__signal_close((uv_signal_t*) handle);
 +    /* Signal handles may not be closed immediately. The signal code will
 +     * itself close uv__make_close_pending whenever appropriate. */
 +    return;
 +
 +  default:
 +    assert(0);
 +  }
 +
 +  uv__make_close_pending(handle);
 +}
 +
 +int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
 +  int r;
 +  int fd;
 +  socklen_t len;
 +
 +  if (handle == NULL || value == NULL)
 +    return UV_EINVAL;
 +
 +  if (handle->type == UV_TCP || handle->type == UV_NAMED_PIPE)
 +    fd = uv__stream_fd((uv_stream_t*) handle);
 +  else if (handle->type == UV_UDP)
 +    fd = ((uv_udp_t *) handle)->io_watcher.fd;
 +  else
 +    return UV_ENOTSUP;
 +
 +  len = sizeof(*value);
 +
 +  if (*value == 0)
 +    r = getsockopt(fd, SOL_SOCKET, optname, value, &len);
 +  else
 +    r = setsockopt(fd, SOL_SOCKET, optname, (const void*) value, len);
 +
 +  if (r < 0)
 +    return UV__ERR(errno);
 +
 +  return 0;
 +}
 +
 +void uv__make_close_pending(uv_handle_t* handle) {
 +  assert(handle->flags & UV_HANDLE_CLOSING);
 +  assert(!(handle->flags & UV_HANDLE_CLOSED));
 +  handle->next_closing = handle->loop->closing_handles;
 +  handle->loop->closing_handles = handle;
 +}
 +
 +int uv__getiovmax(void) {
 +#if defined(IOV_MAX)
 +  return IOV_MAX;
 +#elif defined(_SC_IOV_MAX)
 +  static int iovmax = -1;
 +  if (iovmax == -1) {
 +    iovmax = sysconf(_SC_IOV_MAX);
 +    /* On some embedded devices (arm-linux-uclibc based ip camera),
 +     * sysconf(_SC_IOV_MAX) can not get the correct value. The return
 +     * value is -1 and the errno is EINPROGRESS. Degrade the value to 1.
 +     */
 +    if (iovmax == -1) iovmax = 1;
 +  }
 +  return iovmax;
 +#else
 +  return 1024;
 +#endif
 +}
 +
 +
 +static void uv__finish_close(uv_handle_t* handle) {
 +  /* Note: while the handle is in the UV_HANDLE_CLOSING state now, it's still
 +   * possible for it to be active in the sense that uv__is_active() returns
 +   * true.
 +   *
 +   * A good example is when the user calls uv_shutdown(), immediately followed
 +   * by uv_close(). The handle is considered active at this point because the
 +   * completion of the shutdown req is still pending.
 +   */
 +  assert(handle->flags & UV_HANDLE_CLOSING);
 +  assert(!(handle->flags & UV_HANDLE_CLOSED));
 +  handle->flags |= UV_HANDLE_CLOSED;
 +
 +  switch (handle->type) {
 +    case UV_PREPARE:
 +    case UV_CHECK:
 +    case UV_IDLE:
 +    case UV_ASYNC:
 +    case UV_TIMER:
 +    case UV_PROCESS:
 +    case UV_FS_EVENT:
 +    case UV_FS_POLL:
 +    case UV_POLL:
 +    case UV_SIGNAL:
 +      break;
 +
 +    case UV_NAMED_PIPE:
 +    case UV_TCP:
 +    case UV_TTY:
 +      uv__stream_destroy((uv_stream_t*)handle);
 +      break;
 +
 +    case UV_UDP:
 +      uv__udp_finish_close((uv_udp_t*)handle);
 +      break;
 +
 +    default:
 +      assert(0);
 +      break;
 +  }
 +
 +  uv__handle_unref(handle);
 +  QUEUE_REMOVE(&handle->handle_queue);
 +
 +  if (handle->close_cb) {
 +    handle->close_cb(handle);
 +  }
 +}
 +
 +
 +static void uv__run_closing_handles(uv_loop_t* loop) {
 +  uv_handle_t* p;
 +  uv_handle_t* q;
 +
 +  p = loop->closing_handles;
 +  loop->closing_handles = NULL;
 +
 +  while (p) {
 +    q = p->next_closing;
 +    uv__finish_close(p);
 +    p = q;
 +  }
 +}
 +
 +
 +int uv_is_closing(const uv_handle_t* handle) {
 +  return uv__is_closing(handle);
 +}
 +
 +
 +int uv_backend_fd(const uv_loop_t* loop) {
 +  return loop->backend_fd;
 +}
 +
 +
 +int uv_backend_timeout(const uv_loop_t* loop) {
 +  if (loop->stop_flag != 0)
 +    return 0;
 +
 +  if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
 +    return 0;
 +
 +  if (!QUEUE_EMPTY(&loop->idle_handles))
 +    return 0;
 +
 +  if (!QUEUE_EMPTY(&loop->pending_queue))
 +    return 0;
 +
 +  if (loop->closing_handles)
 +    return 0;
 +
 +  return uv__next_timeout(loop);
 +}
 +
 +
 +static int uv__loop_alive(const uv_loop_t* loop) {
 +  return uv__has_active_handles(loop) ||
 +         uv__has_active_reqs(loop) ||
 +         loop->closing_handles != NULL;
 +}
 +
 +
 +int uv_loop_alive(const uv_loop_t* loop) {
 +    return uv__loop_alive(loop);
 +}
 +
 +
 +int uv_run(uv_loop_t* loop, uv_run_mode mode) {
 +  int timeout;
 +  int r;
 +  int ran_pending;
 +
 +  r = uv__loop_alive(loop);
 +  if (!r)
 +    uv__update_time(loop);
 +
 +  while (r != 0 && loop->stop_flag == 0) {
 +    uv__update_time(loop);
 +    uv__run_timers(loop);
 +    ran_pending = uv__run_pending(loop);
 +    uv__run_idle(loop);
 +    uv__run_prepare(loop);
 +
 +    timeout = 0;
 +    if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
 +      timeout = uv_backend_timeout(loop);
 +
 +    uv__io_poll(loop, timeout);
 +    uv__run_check(loop);
 +    uv__run_closing_handles(loop);
 +
 +    if (mode == UV_RUN_ONCE) {
 +      /* UV_RUN_ONCE implies forward progress: at least one callback must have
 +       * been invoked when it returns. uv__io_poll() can return without doing
 +       * I/O (meaning: no callbacks) when its timeout expires - which means we
 +       * have pending timers that satisfy the forward progress constraint.
 +       *
 +       * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
 +       * the check.
 +       */
 +      uv__update_time(loop);
 +      uv__run_timers(loop);
 +    }
 +
 +    r = uv__loop_alive(loop);
 +    if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
 +      break;
 +  }
 +
 +  /* The if statement lets gcc compile it to a conditional store. Avoids
 +   * dirtying a cache line.
 +   */
 +  if (loop->stop_flag != 0)
 +    loop->stop_flag = 0;
 +
 +  return r;
 +}
 +
 +
 +void uv_update_time(uv_loop_t* loop) {
 +  uv__update_time(loop);
 +}
 +
 +
 +int uv_is_active(const uv_handle_t* handle) {
 +  return uv__is_active(handle);
 +}
 +
 +
 +/* Open a socket in non-blocking close-on-exec mode, atomically if possible. */
 +int uv__socket(int domain, int type, int protocol) {
 +  int sockfd;
 +  int err;
 +
 +#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC)
 +  sockfd = socket(domain, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol);
 +  if (sockfd != -1)
 +    return sockfd;
 +
 +  if (errno != EINVAL)
 +    return UV__ERR(errno);
 +#endif
 +
 +  sockfd = socket(domain, type, protocol);
 +  if (sockfd == -1)
 +    return UV__ERR(errno);
 +
 +  err = uv__nonblock(sockfd, 1);
 +  if (err == 0)
 +    err = uv__cloexec(sockfd, 1);
 +
 +  if (err) {
 +    uv__close(sockfd);
 +    return err;
 +  }
 +
 +#if defined(SO_NOSIGPIPE)
 +  {
 +    int on = 1;
 +    setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));
 +  }
 +#endif
 +
 +  return sockfd;
 +}
 +
 +/* get a file pointer to a file in read-only and close-on-exec mode */
 +FILE* uv__open_file(const char* path) {
 +  int fd;
 +  FILE* fp;
 +
 +  fd = uv__open_cloexec(path, O_RDONLY);
 +  if (fd < 0)
 +    return NULL;
 +
 +   fp = fdopen(fd, "r");
 +   if (fp == NULL)
 +     uv__close(fd);
 +
 +   return fp;
 +}
 +
 +
 +int uv__accept(int sockfd) {
 +  int peerfd;
 +  int err;
 +
 +  assert(sockfd >= 0);
 +
 +  while (1) {
 +#if defined(__linux__)                          || \
 +    (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \
 +    defined(__NetBSD__)
 +    static int no_accept4;
 +
 +    if (no_accept4)
 +      goto skip;
 +
 +    peerfd = uv__accept4(sockfd,
 +                         NULL,
 +                         NULL,
 +                         UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC);
 +    if (peerfd != -1)
 +      return peerfd;
 +
 +    if (errno == EINTR)
 +      continue;
 +
 +    if (errno != ENOSYS)
 +      return UV__ERR(errno);
 +
 +    no_accept4 = 1;
 +skip:
 +#endif
 +
 +    peerfd = accept(sockfd, NULL, NULL);
 +    if (peerfd == -1) {
 +      if (errno == EINTR)
 +        continue;
 +      return UV__ERR(errno);
 +    }
 +
 +    err = uv__cloexec(peerfd, 1);
 +    if (err == 0)
 +      err = uv__nonblock(peerfd, 1);
 +
 +    if (err) {
 +      uv__close(peerfd);
 +      return err;
 +    }
 +
 +    return peerfd;
 +  }
 +}
 +
 +
++/* close() on macos has the "interesting" quirk that it fails with EINTR
++ * without closing the file descriptor when a thread is in the cancel state.
++ * That's why libuv calls close$NOCANCEL() instead.
++ *
++ * glibc on linux has a similar issue: close() is a cancellation point and
++ * will unwind the thread when it's in the cancel state. Work around that
++ * by making the system call directly. Musl libc is unaffected.
++ */
++int uv__close_nocancel(int fd) {
++#if defined(__APPLE__)
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
++#if defined(__LP64__)
++  extern int close$NOCANCEL(int);
++  return close$NOCANCEL(fd);
++#else
++  extern int close$NOCANCEL$UNIX2003(int);
++  return close$NOCANCEL$UNIX2003(fd);
++#endif
++#pragma GCC diagnostic pop
++#elif defined(__linux__)
++  return syscall(SYS_close, fd);
++#else
++  return close(fd);
++#endif
++}
++
++
 +int uv__close_nocheckstdio(int fd) {
 +  int saved_errno;
 +  int rc;
 +
 +  assert(fd > -1);  /* Catch uninitialized io_watcher.fd bugs. */
 +
 +  saved_errno = errno;
-   rc = close(fd);
++  rc = uv__close_nocancel(fd);
 +  if (rc == -1) {
 +    rc = UV__ERR(errno);
 +    if (rc == UV_EINTR || rc == UV__ERR(EINPROGRESS))
 +      rc = 0;    /* The close is in progress, not an error. */
 +    errno = saved_errno;
 +  }
 +
 +  return rc;
 +}
 +
 +
 +int uv__close(int fd) {
 +  assert(fd > STDERR_FILENO);  /* Catch stdio close bugs. */
 +#if defined(__MVS__)
 +  SAVE_ERRNO(epoll_file_close(fd));
 +#endif
 +  return uv__close_nocheckstdio(fd);
 +}
 +
 +
 +int uv__nonblock_ioctl(int fd, int set) {
 +  int r;
 +
 +  do
 +    r = ioctl(fd, FIONBIO, &set);
 +  while (r == -1 && errno == EINTR);
 +
 +  if (r)
 +    return UV__ERR(errno);
 +
 +  return 0;
 +}
 +
 +
- #if !defined(__CYGWIN__) && !defined(__MSYS__)
++#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__HAIKU__)
 +int uv__cloexec_ioctl(int fd, int set) {
 +  int r;
 +
 +  do
 +    r = ioctl(fd, set ? FIOCLEX : FIONCLEX);
 +  while (r == -1 && errno == EINTR);
 +
 +  if (r)
 +    return UV__ERR(errno);
 +
 +  return 0;
 +}
 +#endif
 +
 +
 +int uv__nonblock_fcntl(int fd, int set) {
 +  int flags;
 +  int r;
 +
 +  do
 +    r = fcntl(fd, F_GETFL);
 +  while (r == -1 && errno == EINTR);
 +
 +  if (r == -1)
 +    return UV__ERR(errno);
 +
 +  /* Bail out now if already set/clear. */
 +  if (!!(r & O_NONBLOCK) == !!set)
 +    return 0;
 +
 +  if (set)
 +    flags = r | O_NONBLOCK;
 +  else
 +    flags = r & ~O_NONBLOCK;
 +
 +  do
 +    r = fcntl(fd, F_SETFL, flags);
 +  while (r == -1 && errno == EINTR);
 +
 +  if (r)
 +    return UV__ERR(errno);
 +
 +  return 0;
 +}
 +
 +
 +int uv__cloexec_fcntl(int fd, int set) {
 +  int flags;
 +  int r;
 +
 +  do
 +    r = fcntl(fd, F_GETFD);
 +  while (r == -1 && errno == EINTR);
 +
 +  if (r == -1)
 +    return UV__ERR(errno);
 +
 +  /* Bail out now if already set/clear. */
 +  if (!!(r & FD_CLOEXEC) == !!set)
 +    return 0;
 +
 +  if (set)
 +    flags = r | FD_CLOEXEC;
 +  else
 +    flags = r & ~FD_CLOEXEC;
 +
 +  do
 +    r = fcntl(fd, F_SETFD, flags);
 +  while (r == -1 && errno == EINTR);
 +
 +  if (r)
 +    return UV__ERR(errno);
 +
 +  return 0;
 +}
 +
 +
 +ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
 +  struct cmsghdr* cmsg;
 +  ssize_t rc;
 +  int* pfd;
 +  int* end;
 +#if defined(__linux__)
 +  static int no_msg_cmsg_cloexec;
 +  if (no_msg_cmsg_cloexec == 0) {
 +    rc = recvmsg(fd, msg, flags | 0x40000000);  /* MSG_CMSG_CLOEXEC */
 +    if (rc != -1)
 +      return rc;
 +    if (errno != EINVAL)
 +      return UV__ERR(errno);
 +    rc = recvmsg(fd, msg, flags);
 +    if (rc == -1)
 +      return UV__ERR(errno);
 +    no_msg_cmsg_cloexec = 1;
 +  } else {
 +    rc = recvmsg(fd, msg, flags);
 +  }
 +#else
 +  rc = recvmsg(fd, msg, flags);
 +#endif
 +  if (rc == -1)
 +    return UV__ERR(errno);
 +  if (msg->msg_controllen == 0)
 +    return rc;
 +  for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg))
 +    if (cmsg->cmsg_type == SCM_RIGHTS)
 +      for (pfd = (int*) CMSG_DATA(cmsg),
 +           end = (int*) ((char*) cmsg + cmsg->cmsg_len);
 +           pfd < end;
 +           pfd += 1)
 +        uv__cloexec(*pfd, 1);
 +  return rc;
 +}
 +
 +
 +int uv_cwd(char* buffer, size_t* size) {
 +  if (buffer == NULL || size == NULL)
 +    return UV_EINVAL;
 +
 +  if (getcwd(buffer, *size) == NULL)
 +    return UV__ERR(errno);
 +
 +  *size = strlen(buffer);
 +  if (*size > 1 && buffer[*size - 1] == '/') {
 +    buffer[*size-1] = '\0';
 +    (*size)--;
 +  }
 +
 +  return 0;
 +}
 +
 +
 +int uv_chdir(const char* dir) {
 +  if (chdir(dir))
 +    return UV__ERR(errno);
 +
 +  return 0;
 +}
 +
 +
 +void uv_disable_stdio_inheritance(void) {
 +  int fd;
 +
 +  /* Set the CLOEXEC flag on all open descriptors. Unconditionally try the
 +   * first 16 file descriptors. After that, bail out after the first error.
 +   */
 +  for (fd = 0; ; fd++)
 +    if (uv__cloexec(fd, 1) && fd > 15)
 +      break;
 +}
 +
 +
 +int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
 +  int fd_out;
 +
 +  switch (handle->type) {
 +  case UV_TCP:
 +  case UV_NAMED_PIPE:
 +  case UV_TTY:
 +    fd_out = uv__stream_fd((uv_stream_t*) handle);
 +    break;
 +
 +  case UV_UDP:
 +    fd_out = ((uv_udp_t *) handle)->io_watcher.fd;
 +    break;
 +
 +  case UV_POLL:
 +    fd_out = ((uv_poll_t *) handle)->io_watcher.fd;
 +    break;
 +
 +  default:
 +    return UV_EINVAL;
 +  }
 +
 +  if (uv__is_closing(handle) || fd_out == -1)
 +    return UV_EBADF;
 +
 +  *fd = fd_out;
 +  return 0;
 +}
 +
 +
 +static int uv__run_pending(uv_loop_t* loop) {
 +  QUEUE* q;
 +  QUEUE pq;
 +  uv__io_t* w;
 +
 +  if (QUEUE_EMPTY(&loop->pending_queue))
 +    return 0;
 +
 +  QUEUE_MOVE(&loop->pending_queue, &pq);
 +
 +  while (!QUEUE_EMPTY(&pq)) {
 +    q = QUEUE_HEAD(&pq);
 +    QUEUE_REMOVE(q);
 +    QUEUE_INIT(q);
 +    w = QUEUE_DATA(q, uv__io_t, pending_queue);
 +    w->cb(loop, w, POLLOUT);
 +  }
 +
 +  return 1;
 +}
 +
 +
 +static unsigned int next_power_of_two(unsigned int val) {
 +  val -= 1;
 +  val |= val >> 1;
 +  val |= val >> 2;
 +  val |= val >> 4;
 +  val |= val >> 8;
 +  val |= val >> 16;
 +  val += 1;
 +  return val;
 +}
 +
 +static void maybe_resize(uv_loop_t* loop, unsigned int len) {
 +  uv__io_t** watchers;
 +  void* fake_watcher_list;
 +  void* fake_watcher_count;
 +  unsigned int nwatchers;
 +  unsigned int i;
 +
 +  if (len <= loop->nwatchers)
 +    return;
 +
 +  /* Preserve fake watcher list and count at the end of the watchers */
 +  if (loop->watchers != NULL) {
 +    fake_watcher_list = loop->watchers[loop->nwatchers];
 +    fake_watcher_count = loop->watchers[loop->nwatchers + 1];
 +  } else {
 +    fake_watcher_list = NULL;
 +    fake_watcher_count = NULL;
 +  }
 +
 +  nwatchers = next_power_of_two(len + 2) - 2;
 +  watchers = uv__realloc(loop->watchers,
 +                         (nwatchers + 2) * sizeof(loop->watchers[0]));
 +
 +  if (watchers == NULL)
 +    abort();
 +  for (i = loop->nwatchers; i < nwatchers; i++)
 +    watchers[i] = NULL;
 +  watchers[nwatchers] = fake_watcher_list;
 +  watchers[nwatchers + 1] = fake_watcher_count;
 +
 +  loop->watchers = watchers;
 +  loop->nwatchers = nwatchers;
 +}
 +
 +
 +void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) {
 +  assert(cb != NULL);
 +  assert(fd >= -1);
 +  QUEUE_INIT(&w->pending_queue);
 +  QUEUE_INIT(&w->watcher_queue);
 +  w->cb = cb;
 +  w->fd = fd;
 +  w->events = 0;
 +  w->pevents = 0;
 +
 +#if defined(UV_HAVE_KQUEUE)
 +  w->rcount = 0;
 +  w->wcount = 0;
 +#endif /* defined(UV_HAVE_KQUEUE) */
 +}
 +
 +
 +void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
 +  assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI)));
 +  assert(0 != events);
 +  assert(w->fd >= 0);
 +  assert(w->fd < INT_MAX);
 +
 +  w->pevents |= events;
 +  maybe_resize(loop, w->fd + 1);
 +
 +#if !defined(__sun)
 +  /* The event ports backend needs to rearm all file descriptors on each and
 +   * every tick of the event loop but the other backends allow us to
 +   * short-circuit here if the event mask is unchanged.
 +   */
 +  if (w->events == w->pevents)
 +    return;
 +#endif
 +
 +  if (QUEUE_EMPTY(&w->watcher_queue))
 +    QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
 +
 +  if (loop->watchers[w->fd] == NULL) {
 +    loop->watchers[w->fd] = w;
 +    loop->nfds++;
 +  }
 +}
 +
 +
 +void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
 +  assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI)));
 +  assert(0 != events);
 +
 +  if (w->fd == -1)
 +    return;
 +
 +  assert(w->fd >= 0);
 +
 +  /* Happens when uv__io_stop() is called on a handle that was never started. */
 +  if ((unsigned) w->fd >= loop->nwatchers)
 +    return;
 +
 +  w->pevents &= ~events;
 +
 +  if (w->pevents == 0) {
 +    QUEUE_REMOVE(&w->watcher_queue);
 +    QUEUE_INIT(&w->watcher_queue);
 +
 +    if (loop->watchers[w->fd] != NULL) {
 +      assert(loop->watchers[w->fd] == w);
 +      assert(loop->nfds > 0);
 +      loop->watchers[w->fd] = NULL;
 +      loop->nfds--;
 +      w->events = 0;
 +    }
 +  }
 +  else if (QUEUE_EMPTY(&w->watcher_queue))
 +    QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
 +}
 +
 +
 +void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
 +  uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
 +  QUEUE_REMOVE(&w->pending_queue);
 +
 +  /* Remove stale events for this file descriptor */
-   uv__platform_invalidate_fd(loop, w->fd);
++  if (w->fd != -1)
++    uv__platform_invalidate_fd(loop, w->fd);
 +}
 +
 +
 +void uv__io_feed(uv_loop_t* loop, uv__io_t* w) {
 +  if (QUEUE_EMPTY(&w->pending_queue))
 +    QUEUE_INSERT_TAIL(&loop->pending_queue, &w->pending_queue);
 +}
 +
 +
 +int uv__io_active(const uv__io_t* w, unsigned int events) {
 +  assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI)));
 +  assert(0 != events);
 +  return 0 != (w->pevents & events);
 +}
 +
 +
 +int uv__fd_exists(uv_loop_t* loop, int fd) {
 +  return (unsigned) fd < loop->nwatchers && loop->watchers[fd] != NULL;
 +}
 +
 +
 +int uv_getrusage(uv_rusage_t* rusage) {
 +  struct rusage usage;
 +
 +  if (getrusage(RUSAGE_SELF, &usage))
 +    return UV__ERR(errno);
 +
 +  rusage->ru_utime.tv_sec = usage.ru_utime.tv_sec;
 +  rusage->ru_utime.tv_usec = usage.ru_utime.tv_usec;
 +
 +  rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec;
 +  rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec;
 +
- #if !defined(__MVS__)
++#if !defined(__MVS__) && !defined(__HAIKU__)
 +  rusage->ru_maxrss = usage.ru_maxrss;
 +  rusage->ru_ixrss = usage.ru_ixrss;
 +  rusage->ru_idrss = usage.ru_idrss;
 +  rusage->ru_isrss = usage.ru_isrss;
 +  rusage->ru_minflt = usage.ru_minflt;
 +  rusage->ru_majflt = usage.ru_majflt;
 +  rusage->ru_nswap = usage.ru_nswap;
 +  rusage->ru_inblock = usage.ru_inblock;
 +  rusage->ru_oublock = usage.ru_oublock;
 +  rusage->ru_msgsnd = usage.ru_msgsnd;
 +  rusage->ru_msgrcv = usage.ru_msgrcv;
 +  rusage->ru_nsignals = usage.ru_nsignals;
 +  rusage->ru_nvcsw = usage.ru_nvcsw;
 +  rusage->ru_nivcsw = usage.ru_nivcsw;
 +#endif
 +
 +  return 0;
 +}
 +
 +
 +int uv__open_cloexec(const char* path, int flags) {
 +  int err;
 +  int fd;
 +
 +#if defined(UV__O_CLOEXEC)
 +  static int no_cloexec;
 +
 +  if (!no_cloexec) {
 +    fd = open(path, flags | UV__O_CLOEXEC);
 +    if (fd != -1)
 +      return fd;
 +
 +    if (errno != EINVAL)
 +      return UV__ERR(errno);
 +
 +    /* O_CLOEXEC not supported. */
 +    no_cloexec = 1;
 +  }
 +#endif
 +
 +  fd = open(path, flags);
 +  if (fd == -1)
 +    return UV__ERR(errno);
 +
 +  err = uv__cloexec(fd, 1);
 +  if (err) {
 +    uv__close(fd);
 +    return err;
 +  }
 +
 +  return fd;
 +}
 +
 +
 +int uv__dup2_cloexec(int oldfd, int newfd) {
 +  int r;
 +#if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
 +  r = dup3(oldfd, newfd, O_CLOEXEC);
 +  if (r == -1)
 +    return UV__ERR(errno);
 +  return r;
 +#elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC)
 +  r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd);
 +  if (r != -1)
 +    return r;
 +  if (errno != EINVAL)
 +    return UV__ERR(errno);
 +  /* Fall through. */
 +#elif defined(__linux__)
 +  static int no_dup3;
 +  if (!no_dup3) {
 +    do
 +      r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC);
 +    while (r == -1 && errno == EBUSY);
 +    if (r != -1)
 +      return r;
 +    if (errno != ENOSYS)
 +      return UV__ERR(errno);
 +    /* Fall through. */
 +    no_dup3 = 1;
 +  }
 +#endif
 +  {
 +    int err;
 +    do
 +      r = dup2(oldfd, newfd);
 +#if defined(__linux__)
 +    while (r == -1 && errno == EBUSY);
 +#else
 +    while (0);  /* Never retry. */
 +#endif
 +
 +    if (r == -1)
 +      return UV__ERR(errno);
 +
 +    err = uv__cloexec(newfd, 1);
 +    if (err) {
 +      uv__close(newfd);
 +      return err;
 +    }
 +
 +    return r;
 +  }
 +}
 +
 +
 +int uv_os_homedir(char* buffer, size_t* size) {
 +  uv_passwd_t pwd;
 +  size_t len;
 +  int r;
 +
 +  /* Check if the HOME environment variable is set first. The task of
 +     performing input validation on buffer and size is taken care of by
 +     uv_os_getenv(). */
 +  r = uv_os_getenv("HOME", buffer, size);
 +
 +  if (r != UV_ENOENT)
 +    return r;
 +
 +  /* HOME is not set, so call uv__getpwuid_r() */
 +  r = uv__getpwuid_r(&pwd);
 +
 +  if (r != 0) {
 +    return r;
 +  }
 +
 +  len = strlen(pwd.homedir);
 +
 +  if (len >= *size) {
 +    *size = len + 1;
 +    uv_os_free_passwd(&pwd);
 +    return UV_ENOBUFS;
 +  }
 +
 +  memcpy(buffer, pwd.homedir, len + 1);
 +  *size = len;
 +  uv_os_free_passwd(&pwd);
 +
 +  return 0;
 +}
 +
 +
 +int uv_os_tmpdir(char* buffer, size_t* size) {
 +  const char* buf;
 +  size_t len;
 +
 +  if (buffer == NULL || size == NULL || *size == 0)
 +    return UV_EINVAL;
 +
 +#define CHECK_ENV_VAR(name)                                                   \
 +  do {                                                                        \
 +    buf = getenv(name);                                                       \
 +    if (buf != NULL)                                                          \
 +      goto return_buffer;                                                     \
 +  }                                                                           \
 +  while (0)
 +
 +  /* Check the TMPDIR, TMP, TEMP, and TEMPDIR environment variables in order */
 +  CHECK_ENV_VAR("TMPDIR");
 +  CHECK_ENV_VAR("TMP");
 +  CHECK_ENV_VAR("TEMP");
 +  CHECK_ENV_VAR("TEMPDIR");
 +
 +#undef CHECK_ENV_VAR
 +
 +  /* No temp environment variables defined */
 +  #if defined(__ANDROID__)
 +    buf = "/data/local/tmp";
 +  #else
 +    buf = "/tmp";
 +  #endif
 +
 +return_buffer:
 +  len = strlen(buf);
 +
 +  if (len >= *size) {
 +    *size = len + 1;
 +    return UV_ENOBUFS;
 +  }
 +
 +  /* The returned directory should not have a trailing slash. */
 +  if (len > 1 && buf[len - 1] == '/') {
 +    len--;
 +  }
 +
 +  memcpy(buffer, buf, len + 1);
 +  buffer[len] = '\0';
 +  *size = len;
 +
 +  return 0;
 +}
 +
 +
 +int uv__getpwuid_r(uv_passwd_t* pwd) {
 +  struct passwd pw;
 +  struct passwd* result;
 +  char* buf;
 +  uid_t uid;
 +  size_t bufsize;
 +  size_t name_size;
 +  size_t homedir_size;
 +  size_t shell_size;
 +  long initsize;
 +  int r;
 +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
 +  int (*getpwuid_r)(uid_t, struct passwd*, char*, size_t, struct passwd**);
 +
 +  getpwuid_r = dlsym(RTLD_DEFAULT, "getpwuid_r");
 +  if (getpwuid_r == NULL)
 +    return UV_ENOSYS;
 +#endif
 +
 +  if (pwd == NULL)
 +    return UV_EINVAL;
 +
 +  initsize = sysconf(_SC_GETPW_R_SIZE_MAX);
 +
 +  if (initsize <= 0)
 +    bufsize = 4096;
 +  else
 +    bufsize = (size_t) initsize;
 +
 +  uid = geteuid();
 +  buf = NULL;
 +
 +  for (;;) {
 +    uv__free(buf);
 +    buf = uv__malloc(bufsize);
 +
 +    if (buf == NULL)
 +      return UV_ENOMEM;
 +
 +    r = getpwuid_r(uid, &pw, buf, bufsize, &result);
 +
 +    if (r != ERANGE)
 +      break;
 +
 +    bufsize *= 2;
 +  }
 +
 +  if (r != 0) {
 +    uv__free(buf);
 +    return -r;
 +  }
 +
 +  if (result == NULL) {
 +    uv__free(buf);
 +    return UV_ENOENT;
 +  }
 +
 +  /* Allocate memory for the username, shell, and home directory */
 +  name_size = strlen(pw.pw_name) + 1;
 +  homedir_size = strlen(pw.pw_dir) + 1;
 +  shell_size = strlen(pw.pw_shell) + 1;
 +  pwd->username = uv__malloc(name_size + homedir_size + shell_size);
 +
 +  if (pwd->username == NULL) {
 +    uv__free(buf);
 +    return UV_ENOMEM;
 +  }
 +
 +  /* Copy the username */
 +  memcpy(pwd->username, pw.pw_name, name_size);
 +
 +  /* Copy the home directory */
 +  pwd->homedir = pwd->username + name_size;
 +  memcpy(pwd->homedir, pw.pw_dir, homedir_size);
 +
 +  /* Copy the shell */
 +  pwd->shell = pwd->homedir + homedir_size;
 +  memcpy(pwd->shell, pw.pw_shell, shell_size);
 +
 +  /* Copy the uid and gid */
 +  pwd->uid = pw.pw_uid;
 +  pwd->gid = pw.pw_gid;
 +
 +  uv__free(buf);
 +
 +  return 0;
 +}
 +
 +
 +void uv_os_free_passwd(uv_passwd_t* pwd) {
 +  if (pwd == NULL)
 +    return;
 +
 +  /*
 +    The memory for name, shell, and homedir are allocated in a single
 +    uv__malloc() call. The base of the pointer is stored in pwd->username, so
 +    that is the field that needs to be freed.
 +  */
 +  uv__free(pwd->username);
 +  pwd->username = NULL;
 +  pwd->shell = NULL;
 +  pwd->homedir = NULL;
 +}
 +
 +
 +int uv_os_get_passwd(uv_passwd_t* pwd) {
 +  return uv__getpwuid_r(pwd);
 +}
 +
 +
 +int uv_translate_sys_error(int sys_errno) {
 +  /* If < 0 then it's already a libuv error. */
 +  return sys_errno <= 0 ? sys_errno : -sys_errno;
 +}
 +
 +
 +int uv_os_getenv(const char* name, char* buffer, size_t* size) {
 +  char* var;
 +  size_t len;
 +
 +  if (name == NULL || buffer == NULL || size == NULL || *size == 0)
 +    return UV_EINVAL;
 +
 +  var = getenv(name);
 +
 +  if (var == NULL)
 +    return UV_ENOENT;
 +
 +  len = strlen(var);
 +
 +  if (len >= *size) {
 +    *size = len + 1;
 +    return UV_ENOBUFS;
 +  }
 +
 +  memcpy(buffer, var, len + 1);
 +  *size = len;
 +
 +  return 0;
 +}
 +
 +
 +int uv_os_setenv(const char* name, const char* value) {
 +  if (name == NULL || value == NULL)
 +    return UV_EINVAL;
 +
 +  if (setenv(name, value, 1) != 0)
 +    return UV__ERR(errno);
 +
 +  return 0;
 +}
 +
 +
 +int uv_os_unsetenv(const char* name) {
 +  if (name == NULL)
 +    return UV_EINVAL;
 +
 +  if (unsetenv(name) != 0)
 +    return UV__ERR(errno);
 +
 +  return 0;
 +}
 +
 +
 +int uv_os_gethostname(char* buffer, size_t* size) {
 +  /*
 +    On some platforms, if the input buffer is not large enough, gethostname()
 +    succeeds, but truncates the result. libuv can detect this and return ENOBUFS
 +    instead by creating a large enough buffer and comparing the hostname length
 +    to the size input.
 +  */
-   char buf[MAXHOSTNAMELEN + 1];
++  char buf[UV_MAXHOSTNAMESIZE];
 +  size_t len;
 +
 +  if (buffer == NULL || size == NULL || *size == 0)
 +    return UV_EINVAL;
 +
 +  if (gethostname(buf, sizeof(buf)) != 0)
 +    return UV__ERR(errno);
 +
 +  buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */
 +  len = strlen(buf);
 +
 +  if (len >= *size) {
 +    *size = len + 1;
 +    return UV_ENOBUFS;
 +  }
 +
 +  memcpy(buffer, buf, len + 1);
 +  *size = len;
 +  return 0;
 +}
 +
 +
 +int uv_cpumask_size(void) {
 +#if defined(__linux__) || defined(__FreeBSD__)
 +  return CPU_SETSIZE;
 +#else
 +  return UV_ENOTSUP;
 +#endif
 +}
 +
 +
 +uv_os_fd_t uv_get_osfhandle(int fd) {
 +  return fd;
 +}
 +
 +int uv_open_osfhandle(uv_os_fd_t os_fd) {
 +  return os_fd;
 +}
 +
 +uv_pid_t uv_os_getpid(void) {
 +  return getpid();
 +}
 +
 +
 +uv_pid_t uv_os_getppid(void) {
 +  return getppid();
 +}
 +
 +
 +int uv_os_getpriority(uv_pid_t pid, int* priority) {
 +  int r;
 +
 +  if (priority == NULL)
 +    return UV_EINVAL;
 +
 +  errno = 0;
 +  r = getpriority(PRIO_PROCESS, (int) pid);
 +
 +  if (r == -1 && errno != 0)
 +    return UV__ERR(errno);
 +
 +  *priority = r;
 +  return 0;
 +}
 +
 +
 +int uv_os_setpriority(uv_pid_t pid, int priority) {
 +  if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
 +    return UV_EINVAL;
 +
 +  if (setpriority(PRIO_PROCESS, (int) pid, priority) != 0)
 +    return UV__ERR(errno);
 +
 +  return 0;
 +}
 +
 +
 +int uv_os_uname(uv_utsname_t* buffer) {
 +  struct utsname buf;
 +  int r;
 +
 +  if (buffer == NULL)
 +    return UV_EINVAL;
 +
 +  if (uname(&buf) == -1) {
 +    r = UV__ERR(errno);
 +    goto error;
 +  }
 +
 +  r = uv__strscpy(buffer->sysname, buf.sysname, sizeof(buffer->sysname));
 +  if (r == UV_E2BIG)
 +    goto error;
 +
 +#ifdef _AIX
 +  r = snprintf(buffer->release,
 +               sizeof(buffer->release),
 +               "%s.%s",
 +               buf.version,
 +               buf.release);
 +  if (r >= sizeof(buffer->release)) {
 +    r = UV_E2BIG;
 +    goto error;
 +  }
 +#else
 +  r = uv__strscpy(buffer->release, buf.release, sizeof(buffer->release));
 +  if (r == UV_E2BIG)
 +    goto error;
 +#endif
 +
 +  r = uv__strscpy(buffer->version, buf.version, sizeof(buffer->version));
 +  if (r == UV_E2BIG)
 +    goto error;
 +
 +#if defined(_AIX) || defined(__PASE__)
 +  r = uv__strscpy(buffer->machine, "ppc64", sizeof(buffer->machine));
 +#else
 +  r = uv__strscpy(buffer->machine, buf.machine, sizeof(buffer->machine));
 +#endif
 +
 +  if (r == UV_E2BIG)
 +    goto error;
 +
 +  return 0;
 +
 +error:
 +  buffer->sysname[0] = '\0';
 +  buffer->release[0] = '\0';
 +  buffer->version[0] = '\0';
 +  buffer->machine[0] = '\0';
 +  return r;
 +}
++
++int uv__getsockpeername(const uv_handle_t* handle,
++                        uv__peersockfunc func,
++                        struct sockaddr* name,
++                        int* namelen) {
++  socklen_t socklen;
++  uv_os_fd_t fd;
++  int r;
++
++  r = uv_fileno(handle, &fd);
++  if (r < 0)
++    return r;
++
++  /* sizeof(socklen_t) != sizeof(int) on some systems. */
++  socklen = (socklen_t) *namelen;
++
++  if (func(fd, name, &socklen))
++    return UV__ERR(errno);
++
++  *namelen = (int) socklen;
++  return 0;
++}
++
++int uv_gettimeofday(uv_timeval64_t* tv) {
++  struct timeval time;
++
++  if (tv == NULL)
++    return UV_EINVAL;
++
++  if (gettimeofday(&time, NULL) != 0)
++    return UV__ERR(errno);
++
++  tv->tv_sec = (int64_t) time.tv_sec;
++  tv->tv_usec = (int32_t) time.tv_usec;
++  return 0;
++}
diff --cc Utilities/cmlibuv/src/unix/fs.c
index bffc956,0000000..48500ff
mode 100644,000000..100644
--- a/Utilities/cmlibuv/src/unix/fs.c
+++ b/Utilities/cmlibuv/src/unix/fs.c
@@@ -1,1627 -1,0 +1,1818 @@@
 +/* 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.
 + */
 +
 +/* Caveat emptor: this file deviates from the libuv convention of returning
 + * negated errno codes. Most uv_fs_*() functions map directly to the system
 + * call of the same name. For more complex wrappers, it's easier to just
 + * return -1 with errno set. The dispatcher in uv__fs_work() takes care of
 + * getting the errno to the right place (req->result or as the return value.)
 + */
 +
 +#include "uv.h"
 +#include "internal.h"
 +
 +#include <errno.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <limits.h> /* PATH_MAX */
 +
 +#include <sys/types.h>
 +#include <sys/socket.h>
 +#include <sys/stat.h>
 +#include <sys/time.h>
 +#include <sys/uio.h>
 +#include <pthread.h>
 +#include <unistd.h>
 +#include <fcntl.h>
 +#include <poll.h>
 +
 +#if defined(__DragonFly__)        ||                                      \
 +    defined(__FreeBSD__)          ||                                      \
-     defined(__FreeBSD_kernel_)    ||                                      \
++    defined(__FreeBSD_kernel__)   ||                                      \
 +    defined(__OpenBSD__)          ||                                      \
 +    defined(__NetBSD__)
 +# define HAVE_PREADV 1
 +#else
 +# define HAVE_PREADV 0
 +#endif
 +
 +#if defined(__linux__) || defined(__sun)
 +# include <sys/sendfile.h>
 +#endif
 +
 +#if defined(__APPLE__)
- # include <copyfile.h>
 +# include <sys/sysctl.h>
 +#elif defined(__linux__) && !defined(FICLONE)
 +# include <sys/ioctl.h>
 +# define FICLONE _IOW(0x94, 9, int)
 +#endif
 +
 +#if defined(_AIX) && !defined(_AIX71)
 +# include <utime.h>
 +#endif
 +
 +#if defined(_AIX) && _XOPEN_SOURCE <= 600
 +extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */
 +#endif
 +
 +#define INIT(subtype)                                                         \
 +  do {                                                                        \
 +    if (req == NULL)                                                          \
 +      return UV_EINVAL;                                                       \
 +    UV_REQ_INIT(req, UV_FS);                                                  \
 +    req->fs_type = UV_FS_ ## subtype;                                         \
 +    req->result = 0;                                                          \
 +    req->ptr = NULL;                                                          \
 +    req->loop = loop;                                                         \
 +    req->path = NULL;                                                         \
 +    req->new_path = NULL;                                                     \
 +    req->bufs = NULL;                                                         \
 +    req->cb = cb;                                                             \
 +  }                                                                           \
 +  while (0)
 +
 +#define PATH                                                                  \
 +  do {                                                                        \
 +    assert(path != NULL);                                                     \
 +    if (cb == NULL) {                                                         \
 +      req->path = path;                                                       \
 +    } else {                                                                  \
 +      req->path = uv__strdup(path);                                           \
 +      if (req->path == NULL)                                                  \
 +        return UV_ENOMEM;                                                     \
 +    }                                                                         \
 +  }                                                                           \
 +  while (0)
 +
 +#define PATH2                                                                 \
 +  do {                                                                        \
 +    if (cb == NULL) {                                                         \
 +      req->path = path;                                                       \
 +      req->new_path = new_path;                                               \
 +    } else {                                                                  \
 +      size_t path_len;                                                        \
 +      size_t new_path_len;                                                    \
 +      path_len = strlen(path) + 1;                                            \
 +      new_path_len = strlen(new_path) + 1;                                    \
 +      req->path = uv__malloc(path_len + new_path_len);                        \
 +      if (req->path == NULL)                                                  \
 +        return UV_ENOMEM;                                                     \
 +      req->new_path = req->path + path_len;                                   \
 +      memcpy((void*) req->path, path, path_len);                              \
 +      memcpy((void*) req->new_path, new_path, new_path_len);                  \
 +    }                                                                         \
 +  }                                                                           \
 +  while (0)
 +
 +#define POST                                                                  \
 +  do {                                                                        \
 +    if (cb != NULL) {                                                         \
 +      uv__req_register(loop, req);                                            \
 +      uv__work_submit(loop,                                                   \
 +                      &req->work_req,                                         \
 +                      UV__WORK_FAST_IO,                                       \
 +                      uv__fs_work,                                            \
 +                      uv__fs_done);                                           \
 +      return 0;                                                               \
 +    }                                                                         \
 +    else {                                                                    \
 +      uv__fs_work(&req->work_req);                                            \
 +      return req->result;                                                     \
 +    }                                                                         \
 +  }                                                                           \
 +  while (0)
 +
 +
++static int uv__fs_close(int fd) {
++  int rc;
++
++  rc = uv__close_nocancel(fd);
++  if (rc == -1)
++    if (errno == EINTR || errno == EINPROGRESS)
++      rc = 0;  /* The close is in progress, not an error. */
++
++  return rc;
++}
++
++
 +static ssize_t uv__fs_fsync(uv_fs_t* req) {
 +#if defined(__APPLE__)
 +  /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache
 +   * to the drive platters. This is in contrast to Linux's fdatasync and fsync
 +   * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent
 +   * for flushing buffered data to permanent storage. If F_FULLFSYNC is not
-    * supported by the file system we should fall back to fsync(). This is the
-    * same approach taken by sqlite.
++   * supported by the file system we fall back to F_BARRIERFSYNC or fsync().
++   * This is the same approach taken by sqlite, except sqlite does not issue
++   * an F_BARRIERFSYNC call.
 +   */
 +  int r;
 +
 +  r = fcntl(req->file, F_FULLFSYNC);
 +  if (r != 0)
++    r = fcntl(req->file, F_BARRIERFSYNC);  /* fsync + barrier */
++  if (r != 0)
 +    r = fsync(req->file);
 +  return r;
 +#else
 +  return fsync(req->file);
 +#endif
 +}
 +
 +
 +static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
 +#if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
 +  return fdatasync(req->file);
 +#elif defined(__APPLE__)
 +  /* See the comment in uv__fs_fsync. */
 +  return uv__fs_fsync(req);
 +#else
 +  return fsync(req->file);
 +#endif
 +}
 +
 +
 +static ssize_t uv__fs_futime(uv_fs_t* req) {
 +#if defined(__linux__)                                                        \
-     || defined(_AIX71)
++    || defined(_AIX71)                                                        \
++    || defined(__HAIKU__)
 +  /* utimesat() has nanosecond resolution but we stick to microseconds
 +   * for the sake of consistency with other platforms.
 +   */
 +  struct timespec ts[2];
 +  ts[0].tv_sec  = req->atime;
 +  ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
 +  ts[1].tv_sec  = req->mtime;
 +  ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
 +  return futimens(req->file, ts);
 +#elif defined(__APPLE__)                                                      \
 +    || defined(__DragonFly__)                                                 \
 +    || defined(__FreeBSD__)                                                   \
 +    || defined(__FreeBSD_kernel__)                                            \
 +    || defined(__NetBSD__)                                                    \
 +    || defined(__OpenBSD__)                                                   \
 +    || defined(__sun)
 +  struct timeval tv[2];
 +  tv[0].tv_sec  = req->atime;
 +  tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000;
 +  tv[1].tv_sec  = req->mtime;
 +  tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000;
 +# if defined(__sun)
 +  return futimesat(req->file, NULL, tv);
 +# else
 +  return futimes(req->file, tv);
 +# endif
 +#elif defined(__MVS__)
 +  attrib_t atr;
 +  memset(&atr, 0, sizeof(atr));
 +  atr.att_mtimechg = 1;
 +  atr.att_atimechg = 1;
 +  atr.att_mtime = req->mtime;
 +  atr.att_atime = req->atime;
 +  return __fchattr(req->file, &atr, sizeof(atr));
 +#else
 +  errno = ENOSYS;
 +  return -1;
 +#endif
 +}
 +
 +#if defined(__sun) && (_XOPEN_SOURCE < 600 || defined(CMAKE_BOOTSTRAP))
 +static char* uv__mkdtemp(char *template)
 +{
 +  if (!mktemp(template) || mkdir(template, 0700))
 +    return NULL;
 +  return template;
 +}
 +#else
 +#define uv__mkdtemp mkdtemp
 +#endif
 +
 +static ssize_t uv__fs_mkdtemp(uv_fs_t* req) {
 +  return uv__mkdtemp((char*) req->path) ? 0 : -1;
 +}
 +
 +
 +static ssize_t uv__fs_open(uv_fs_t* req) {
 +  static int no_cloexec_support;
 +  int r;
 +
 +  /* Try O_CLOEXEC before entering locks */
 +  if (no_cloexec_support == 0) {
 +#ifdef O_CLOEXEC
 +    r = open(req->path, req->flags | O_CLOEXEC, req->mode);
 +    if (r >= 0)
 +      return r;
 +    if (errno != EINVAL)
 +      return r;
 +    no_cloexec_support = 1;
 +#endif  /* O_CLOEXEC */
 +  }
 +
 +  if (req->cb != NULL)
 +    uv_rwlock_rdlock(&req->loop->cloexec_lock);
 +
 +  r = open(req->path, req->flags, req->mode);
 +
 +  /* In case of failure `uv__cloexec` will leave error in `errno`,
 +   * so it is enough to just set `r` to `-1`.
 +   */
 +  if (r >= 0 && uv__cloexec(r, 1) != 0) {
 +    r = uv__close(r);
 +    if (r != 0)
 +      abort();
 +    r = -1;
 +  }
 +
 +  if (req->cb != NULL)
 +    uv_rwlock_rdunlock(&req->loop->cloexec_lock);
 +
 +  return r;
 +}
 +
 +
 +static ssize_t uv__fs_read(uv_fs_t* req) {
 +#if defined(__linux__)
 +  static int no_preadv;
 +#endif
 +  unsigned int iovmax;
 +  ssize_t result;
 +
 +  iovmax = uv__getiovmax();
 +  if (req->nbufs > iovmax)
 +    req->nbufs = iovmax;
 +
 +  if (req->off < 0) {
 +    if (req->nbufs == 1)
 +      result = read(req->file, req->bufs[0].base, req->bufs[0].len);
 +    else
 +      result = readv(req->file, (struct iovec*) req->bufs, req->nbufs);
 +  } else {
 +    if (req->nbufs == 1) {
 +      result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
 +      goto done;
 +    }
 +
 +#if HAVE_PREADV
 +    result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
 +#else
 +# if defined(__linux__)
 +    if (no_preadv) retry:
 +# endif
 +    {
 +      result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
 +    }
 +# if defined(__linux__)
 +    else {
 +      result = uv__preadv(req->file,
 +                          (struct iovec*)req->bufs,
 +                          req->nbufs,
 +                          req->off);
 +      if (result == -1 && errno == ENOSYS) {
 +        no_preadv = 1;
 +        goto retry;
 +      }
 +    }
 +# endif
 +#endif
 +  }
 +
 +done:
 +  /* Early cleanup of bufs allocation, since we're done with it. */
 +  if (req->bufs != req->bufsml)
 +    uv__free(req->bufs);
 +
 +  req->bufs = NULL;
 +  req->nbufs = 0;
 +
++#ifdef __PASE__
++  /* PASE returns EOPNOTSUPP when reading a directory, convert to EISDIR */
++  if (result == -1 && errno == EOPNOTSUPP) {
++    struct stat buf;
++    ssize_t rc;
++    rc = fstat(req->file, &buf);
++    if (rc == 0 && S_ISDIR(buf.st_mode)) {
++      errno = EISDIR;
++    }
++  }
++#endif
++
 +  return result;
 +}
 +
 +
 +#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8)
 +#define UV_CONST_DIRENT uv__dirent_t
 +#else
 +#define UV_CONST_DIRENT const uv__dirent_t
 +#endif
 +
 +
 +static int uv__fs_scandir_filter(UV_CONST_DIRENT* dent) {
 +  return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0;
 +}
 +
 +
 +static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) {
 +  return strcmp((*a)->d_name, (*b)->d_name);
 +}
 +
 +
 +static ssize_t uv__fs_scandir(uv_fs_t* req) {
-   uv__dirent_t **dents;
++  uv__dirent_t** dents;
 +  int n;
 +
 +  dents = NULL;
 +  n = scandir(req->path, &dents, uv__fs_scandir_filter, uv__fs_scandir_sort);
 +
 +  /* NOTE: We will use nbufs as an index field */
 +  req->nbufs = 0;
 +
 +  if (n == 0) {
 +    /* OS X still needs to deallocate some memory.
 +     * Memory was allocated using the system allocator, so use free() here.
 +     */
 +    free(dents);
 +    dents = NULL;
 +  } else if (n == -1) {
 +    return n;
 +  }
 +
 +  req->ptr = dents;
 +
 +  return n;
 +}
 +
++static int uv__fs_opendir(uv_fs_t* req) {
++  uv_dir_t* dir;
++
++  dir = uv__malloc(sizeof(*dir));
++  if (dir == NULL)
++    goto error;
++
++  dir->dir = opendir(req->path);
++  if (dir->dir == NULL)
++    goto error;
++
++  req->ptr = dir;
++  return 0;
++
++error:
++  uv__free(dir);
++  req->ptr = NULL;
++  return -1;
++}
++
++static int uv__fs_readdir(uv_fs_t* req) {
++  uv_dir_t* dir;
++  uv_dirent_t* dirent;
++  struct dirent* res;
++  unsigned int dirent_idx;
++  unsigned int i;
++
++  dir = req->ptr;
++  dirent_idx = 0;
++
++  while (dirent_idx < dir->nentries) {
++    /* readdir() returns NULL on end of directory, as well as on error. errno
++       is used to differentiate between the two conditions. */
++    errno = 0;
++    res = readdir(dir->dir);
++
++    if (res == NULL) {
++      if (errno != 0)
++        goto error;
++      break;
++    }
++
++    if (strcmp(res->d_name, ".") == 0 || strcmp(res->d_name, "..") == 0)
++      continue;
++
++    dirent = &dir->dirents[dirent_idx];
++    dirent->name = uv__strdup(res->d_name);
++
++    if (dirent->name == NULL)
++      goto error;
++
++    dirent->type = uv__fs_get_dirent_type(res);
++    ++dirent_idx;
++  }
++
++  return dirent_idx;
++
++error:
++  for (i = 0; i < dirent_idx; ++i) {
++    uv__free((char*) dir->dirents[i].name);
++    dir->dirents[i].name = NULL;
++  }
++
++  return -1;
++}
++
++static int uv__fs_closedir(uv_fs_t* req) {
++  uv_dir_t* dir;
++
++  dir = req->ptr;
++
++  if (dir->dir != NULL) {
++    closedir(dir->dir);
++    dir->dir = NULL;
++  }
++
++  uv__free(req->ptr);
++  req->ptr = NULL;
++  return 0;
++}
++
 +#if defined(_POSIX_PATH_MAX)
 +# define UV__FS_PATH_MAX _POSIX_PATH_MAX
 +#elif defined(PATH_MAX)
 +# define UV__FS_PATH_MAX PATH_MAX
 +#else
 +# define UV__FS_PATH_MAX_FALLBACK 8192
 +# define UV__FS_PATH_MAX UV__FS_PATH_MAX_FALLBACK
 +#endif
 +
 +static ssize_t uv__fs_pathmax_size(const char* path) {
 +  ssize_t pathmax;
 +
 +  pathmax = pathconf(path, _PC_PATH_MAX);
 +
 +  if (pathmax == -1)
 +    pathmax = UV__FS_PATH_MAX;
 +
 +  return pathmax;
 +}
 +
 +static ssize_t uv__fs_readlink(uv_fs_t* req) {
 +  ssize_t maxlen;
 +  ssize_t len;
 +  char* buf;
 +  char* newbuf;
 +
 +#if defined(UV__FS_PATH_MAX_FALLBACK)
 +  /* We may not have a real PATH_MAX.  Read size of link.  */
 +  struct stat st;
 +  int ret;
 +  ret = lstat(req->path, &st);
 +  if (ret != 0)
 +    return -1;
 +  if (!S_ISLNK(st.st_mode)) {
 +    errno = EINVAL;
 +    return -1;
 +  }
 +
 +  maxlen = st.st_size;
 +
 +  /* According to readlink(2) lstat can report st_size == 0
 +     for some symlinks, such as those in /proc or /sys.  */
 +  if (maxlen == 0)
 +    maxlen = uv__fs_pathmax_size(req->path);
 +#else
 +  maxlen = uv__fs_pathmax_size(req->path);
 +#endif
 +
 +  buf = uv__malloc(maxlen);
 +
 +  if (buf == NULL) {
 +    errno = ENOMEM;
 +    return -1;
 +  }
 +
 +#if defined(__MVS__)
 +  len = os390_readlink(req->path, buf, maxlen);
 +#else
 +  len = readlink(req->path, buf, maxlen);
 +#endif
 +
 +  if (len == -1) {
 +    uv__free(buf);
 +    return -1;
 +  }
 +
 +  /* Uncommon case: resize to make room for the trailing nul byte. */
 +  if (len == maxlen) {
 +    newbuf = uv__realloc(buf, len + 1);
 +
 +    if (newbuf == NULL) {
 +      uv__free(buf);
 +      return -1;
 +    }
 +
 +    buf = newbuf;
 +  }
 +
 +  buf[len] = '\0';
 +  req->ptr = buf;
 +
 +  return 0;
 +}
 +
 +static ssize_t uv__fs_realpath(uv_fs_t* req) {
 +  char* buf;
 +
 +#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L
 +  buf = realpath(req->path, NULL);
 +  if (buf == NULL)
 +    return -1;
 +#else
 +  ssize_t len;
 +
 +  len = uv__fs_pathmax_size(req->path);
 +  buf = uv__malloc(len + 1);
 +
 +  if (buf == NULL) {
 +    errno = ENOMEM;
 +    return -1;
 +  }
 +
 +  if (realpath(req->path, buf) == NULL) {
 +    uv__free(buf);
 +    return -1;
 +  }
 +#endif
 +
 +  req->ptr = buf;
 +
 +  return 0;
 +}
 +
 +static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
 +  struct pollfd pfd;
 +  int use_pread;
 +  off_t offset;
 +  ssize_t nsent;
 +  ssize_t nread;
 +  ssize_t nwritten;
 +  size_t buflen;
 +  size_t len;
 +  ssize_t n;
 +  int in_fd;
 +  int out_fd;
 +  char buf[8192];
 +
 +  len = req->bufsml[0].len;
 +  in_fd = req->flags;
 +  out_fd = req->file;
 +  offset = req->off;
 +  use_pread = 1;
 +
 +  /* Here are the rules regarding errors:
 +   *
 +   * 1. Read errors are reported only if nsent==0, otherwise we return nsent.
 +   *    The user needs to know that some data has already been sent, to stop
 +   *    them from sending it twice.
 +   *
 +   * 2. Write errors are always reported. Write errors are bad because they
 +   *    mean data loss: we've read data but now we can't write it out.
 +   *
 +   * We try to use pread() and fall back to regular read() if the source fd
 +   * doesn't support positional reads, for example when it's a pipe fd.
 +   *
 +   * If we get EAGAIN when writing to the target fd, we poll() on it until
 +   * it becomes writable again.
 +   *
 +   * FIXME: If we get a write error when use_pread==1, it should be safe to
 +   *        return the number of sent bytes instead of an error because pread()
 +   *        is, in theory, idempotent. However, special files in /dev or /proc
 +   *        may support pread() but not necessarily return the same data on
 +   *        successive reads.
 +   *
 +   * FIXME: There is no way now to signal that we managed to send *some* data
 +   *        before a write error.
 +   */
 +  for (nsent = 0; (size_t) nsent < len; ) {
 +    buflen = len - nsent;
 +
 +    if (buflen > sizeof(buf))
 +      buflen = sizeof(buf);
 +
 +    do
 +      if (use_pread)
 +        nread = pread(in_fd, buf, buflen, offset);
 +      else
 +        nread = read(in_fd, buf, buflen);
 +    while (nread == -1 && errno == EINTR);
 +
 +    if (nread == 0)
 +      goto out;
 +
 +    if (nread == -1) {
 +      if (use_pread && nsent == 0 && (errno == EIO || errno == ESPIPE)) {
 +        use_pread = 0;
 +        continue;
 +      }
 +
 +      if (nsent == 0)
 +        nsent = -1;
 +
 +      goto out;
 +    }
 +
 +    for (nwritten = 0; nwritten < nread; ) {
 +      do
 +        n = write(out_fd, buf + nwritten, nread - nwritten);
 +      while (n == -1 && errno == EINTR);
 +
 +      if (n != -1) {
 +        nwritten += n;
 +        continue;
 +      }
 +
 +      if (errno != EAGAIN && errno != EWOULDBLOCK) {
 +        nsent = -1;
 +        goto out;
 +      }
 +
 +      pfd.fd = out_fd;
 +      pfd.events = POLLOUT;
 +      pfd.revents = 0;
 +
 +      do
 +        n = poll(&pfd, 1, -1);
 +      while (n == -1 && errno == EINTR);
 +
 +      if (n == -1 || (pfd.revents & ~POLLOUT) != 0) {
 +        errno = EIO;
 +        nsent = -1;
 +        goto out;
 +      }
 +    }
 +
 +    offset += nread;
 +    nsent += nread;
 +  }
 +
 +out:
 +  if (nsent != -1)
 +    req->off = offset;
 +
 +  return nsent;
 +}
 +
 +
 +static ssize_t uv__fs_sendfile(uv_fs_t* req) {
 +  int in_fd;
 +  int out_fd;
 +
 +  in_fd = req->flags;
 +  out_fd = req->file;
 +
 +#if defined(__linux__) || defined(__sun)
 +  {
 +    off_t off;
 +    ssize_t r;
 +
 +    off = req->off;
 +    r = sendfile(out_fd, in_fd, &off, req->bufsml[0].len);
 +
 +    /* sendfile() on SunOS returns EINVAL if the target fd is not a socket but
 +     * it still writes out data. Fortunately, we can detect it by checking if
 +     * the offset has been updated.
 +     */
 +    if (r != -1 || off > req->off) {
 +      r = off - req->off;
 +      req->off = off;
 +      return r;
 +    }
 +
 +    if (errno == EINVAL ||
 +        errno == EIO ||
 +        errno == ENOTSOCK ||
 +        errno == EXDEV) {
 +      errno = 0;
 +      return uv__fs_sendfile_emul(req);
 +    }
 +
 +    return -1;
 +  }
 +#elif defined(__APPLE__)           || \
 +      defined(__DragonFly__)       || \
 +      defined(__FreeBSD__)         || \
 +      defined(__FreeBSD_kernel__)
 +  {
 +    off_t len;
 +    ssize_t r;
 +
 +    /* sendfile() on FreeBSD and Darwin returns EAGAIN if the target fd is in
 +     * non-blocking mode and not all data could be written. If a non-zero
 +     * number of bytes have been sent, we don't consider it an error.
 +     */
 +
 +#if defined(__FreeBSD__) || defined(__DragonFly__)
 +    len = 0;
 +    r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0);
 +#elif defined(__FreeBSD_kernel__)
 +    len = 0;
 +    r = bsd_sendfile(in_fd,
 +                     out_fd,
 +                     req->off,
 +                     req->bufsml[0].len,
 +                     NULL,
 +                     &len,
 +                     0);
 +#else
 +    /* The darwin sendfile takes len as an input for the length to send,
 +     * so make sure to initialize it with the caller's value. */
 +    len = req->bufsml[0].len;
 +    r = sendfile(in_fd, out_fd, req->off, &len, NULL, 0);
 +#endif
 +
 +     /*
 +     * The man page for sendfile(2) on DragonFly states that `len` contains
 +     * a meaningful value ONLY in case of EAGAIN and EINTR.
 +     * Nothing is said about it's value in case of other errors, so better
 +     * not depend on the potential wrong assumption that is was not modified
 +     * by the syscall.
 +     */
 +    if (r == 0 || ((errno == EAGAIN || errno == EINTR) && len != 0)) {
 +      req->off += len;
 +      return (ssize_t) len;
 +    }
 +
 +    if (errno == EINVAL ||
 +        errno == EIO ||
 +        errno == ENOTSOCK ||
 +        errno == EXDEV) {
 +      errno = 0;
 +      return uv__fs_sendfile_emul(req);
 +    }
 +
 +    return -1;
 +  }
 +#else
 +  /* Squelch compiler warnings. */
 +  (void) &in_fd;
 +  (void) &out_fd;
 +
 +  return uv__fs_sendfile_emul(req);
 +#endif
 +}
 +
 +
 +static ssize_t uv__fs_utime(uv_fs_t* req) {
 +#if defined(__linux__)                                                         \
 +    || defined(_AIX71)                                                         \
-     || defined(__sun)
++    || defined(__sun)                                                          \
++    || defined(__HAIKU__)
 +  /* utimesat() has nanosecond resolution but we stick to microseconds
 +   * for the sake of consistency with other platforms.
 +   */
 +  struct timespec ts[2];
 +  ts[0].tv_sec  = req->atime;
 +  ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
 +  ts[1].tv_sec  = req->mtime;
 +  ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
 +  return utimensat(AT_FDCWD, req->path, ts, 0);
 +#elif defined(__APPLE__)                                                      \
 +    || defined(__DragonFly__)                                                 \
 +    || defined(__FreeBSD__)                                                   \
 +    || defined(__FreeBSD_kernel__)                                            \
 +    || defined(__NetBSD__)                                                    \
 +    || defined(__OpenBSD__)
 +  struct timeval tv[2];
 +  tv[0].tv_sec  = req->atime;
 +  tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000;
 +  tv[1].tv_sec  = req->mtime;
 +  tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000;
 +  return utimes(req->path, tv);
 +#elif defined(_AIX)                                                           \
 +    && !defined(_AIX71)
 +  struct utimbuf buf;
 +  buf.actime = req->atime;
 +  buf.modtime = req->mtime;
 +  return utime(req->path, &buf);
 +#elif defined(__MVS__)
 +  attrib_t atr;
 +  memset(&atr, 0, sizeof(atr));
 +  atr.att_mtimechg = 1;
 +  atr.att_atimechg = 1;
 +  atr.att_mtime = req->mtime;
 +  atr.att_atime = req->atime;
 +  return __lchattr((char*) req->path, &atr, sizeof(atr));
 +#else
 +  errno = ENOSYS;
 +  return -1;
 +#endif
 +}
 +
 +
 +static ssize_t uv__fs_write(uv_fs_t* req) {
 +#if defined(__linux__)
 +  static int no_pwritev;
 +#endif
 +  ssize_t r;
 +
 +  /* Serialize writes on OS X, concurrent write() and pwrite() calls result in
 +   * data loss. We can't use a per-file descriptor lock, the descriptor may be
 +   * a dup().
 +   */
 +#if defined(__APPLE__)
 +  static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
 +
 +  if (pthread_mutex_lock(&lock))
 +    abort();
 +#endif
 +
 +  if (req->off < 0) {
 +    if (req->nbufs == 1)
 +      r = write(req->file, req->bufs[0].base, req->bufs[0].len);
 +    else
 +      r = writev(req->file, (struct iovec*) req->bufs, req->nbufs);
 +  } else {
 +    if (req->nbufs == 1) {
 +      r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
 +      goto done;
 +    }
 +#if HAVE_PREADV
 +    r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
 +#else
 +# if defined(__linux__)
 +    if (no_pwritev) retry:
 +# endif
 +    {
 +      r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
 +    }
 +# if defined(__linux__)
 +    else {
 +      r = uv__pwritev(req->file,
 +                      (struct iovec*) req->bufs,
 +                      req->nbufs,
 +                      req->off);
 +      if (r == -1 && errno == ENOSYS) {
 +        no_pwritev = 1;
 +        goto retry;
 +      }
 +    }
 +# endif
 +#endif
 +  }
 +
 +done:
 +#if defined(__APPLE__)
 +  if (pthread_mutex_unlock(&lock))
 +    abort();
 +#endif
 +
 +  return r;
 +}
 +
 +static ssize_t uv__fs_copyfile(uv_fs_t* req) {
- #if defined(__APPLE__) && !TARGET_OS_IPHONE
-   /* On macOS, use the native copyfile(3). */
-   static int can_clone;
-   copyfile_flags_t flags;
-   char buf[64];
-   size_t len;
-   int major;
- 
-   flags = COPYFILE_ALL;
- 
-   if (req->flags & UV_FS_COPYFILE_EXCL)
-     flags |= COPYFILE_EXCL;
- 
-   /* Check OS version. Cloning is only supported on macOS >= 10.12. */
-   if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
-     if (can_clone == 0) {
-       len = sizeof(buf);
-       if (sysctlbyname("kern.osrelease", buf, &len, NULL, 0))
-         return UV__ERR(errno);
- 
-       if (1 != sscanf(buf, "%d", &major))
-         abort();
- 
-       can_clone = -1 + 2 * (major >= 16);  /* macOS >= 10.12 */
-     }
- 
-     if (can_clone < 0)
-       return UV_ENOSYS;
-   }
- 
-   /* copyfile() simply ignores COPYFILE_CLONE if it's not supported. */
-   if (req->flags & UV_FS_COPYFILE_FICLONE)
-     flags |= 1 << 24;  /* COPYFILE_CLONE */
- 
-   if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE)
-     flags |= 1 << 25;  /* COPYFILE_CLONE_FORCE */
- 
-   return copyfile(req->path, req->new_path, NULL, flags);
- #else
 +  uv_fs_t fs_req;
 +  uv_file srcfd;
 +  uv_file dstfd;
 +  struct stat statsbuf;
 +  int dst_flags;
 +  int result;
 +  int err;
 +  size_t bytes_to_send;
 +  int64_t in_offset;
 +
 +  dstfd = -1;
 +  err = 0;
 +
 +  /* Open the source file. */
 +  srcfd = uv_fs_open(NULL, &fs_req, req->path, O_RDONLY, 0, NULL);
 +  uv_fs_req_cleanup(&fs_req);
 +
 +  if (srcfd < 0)
 +    return srcfd;
 +
 +  /* Get the source file's mode. */
 +  if (fstat(srcfd, &statsbuf)) {
 +    err = UV__ERR(errno);
 +    goto out;
 +  }
 +
 +  dst_flags = O_WRONLY | O_CREAT | O_TRUNC;
 +
 +  if (req->flags & UV_FS_COPYFILE_EXCL)
 +    dst_flags |= O_EXCL;
 +
 +  /* Open the destination file. */
 +  dstfd = uv_fs_open(NULL,
 +                     &fs_req,
 +                     req->new_path,
 +                     dst_flags,
 +                     statsbuf.st_mode,
 +                     NULL);
 +  uv_fs_req_cleanup(&fs_req);
 +
 +  if (dstfd < 0) {
 +    err = dstfd;
 +    goto out;
 +  }
 +
 +  if (fchmod(dstfd, statsbuf.st_mode) == -1) {
 +    err = UV__ERR(errno);
 +    goto out;
 +  }
 +
 +#ifdef FICLONE
 +  if (req->flags & UV_FS_COPYFILE_FICLONE ||
 +      req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
 +    if (ioctl(dstfd, FICLONE, srcfd) == -1) {
 +      /* If an error occurred that the sendfile fallback also won't handle, or
 +         this is a force clone then exit. Otherwise, fall through to try using
 +         sendfile(). */
 +      if (errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) {
 +        err = UV__ERR(errno);
 +        goto out;
 +      } else if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
 +        err = UV_ENOTSUP;
 +        goto out;
 +      }
 +    } else {
 +      goto out;
 +    }
 +  }
 +#else
 +  if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
 +    err = UV_ENOSYS;
 +    goto out;
 +  }
 +#endif
 +
 +  bytes_to_send = statsbuf.st_size;
 +  in_offset = 0;
 +  while (bytes_to_send != 0) {
 +    err = uv_fs_sendfile(NULL,
 +                         &fs_req,
 +                         dstfd,
 +                         srcfd,
 +                         in_offset,
 +                         bytes_to_send,
 +                         NULL);
 +    uv_fs_req_cleanup(&fs_req);
 +    if (err < 0)
 +      break;
 +    bytes_to_send -= fs_req.result;
 +    in_offset += fs_req.result;
 +  }
 +
 +out:
 +  if (err < 0)
 +    result = err;
 +  else
 +    result = 0;
 +
 +  /* Close the source file. */
 +  err = uv__close_nocheckstdio(srcfd);
 +
 +  /* Don't overwrite any existing errors. */
 +  if (err != 0 && result == 0)
 +    result = err;
 +
 +  /* Close the destination file if it is open. */
 +  if (dstfd >= 0) {
 +    err = uv__close_nocheckstdio(dstfd);
 +
 +    /* Don't overwrite any existing errors. */
 +    if (err != 0 && result == 0)
 +      result = err;
 +
 +    /* Remove the destination file if something went wrong. */
 +    if (result != 0) {
 +      uv_fs_unlink(NULL, &fs_req, req->new_path, NULL);
 +      /* Ignore the unlink return value, as an error already happened. */
 +      uv_fs_req_cleanup(&fs_req);
 +    }
 +  }
 +
 +  if (result == 0)
 +    return 0;
 +
 +  errno = UV__ERR(result);
 +  return -1;
- #endif
 +}
 +
 +static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
 +  dst->st_dev = src->st_dev;
 +  dst->st_mode = src->st_mode;
 +  dst->st_nlink = src->st_nlink;
 +  dst->st_uid = src->st_uid;
 +  dst->st_gid = src->st_gid;
 +  dst->st_rdev = src->st_rdev;
 +  dst->st_ino = src->st_ino;
 +  dst->st_size = src->st_size;
 +  dst->st_blksize = src->st_blksize;
 +  dst->st_blocks = src->st_blocks;
 +
 +#if defined(__APPLE__)
 +  dst->st_atim.tv_sec = src->st_atimespec.tv_sec;
 +  dst->st_atim.tv_nsec = src->st_atimespec.tv_nsec;
 +  dst->st_mtim.tv_sec = src->st_mtimespec.tv_sec;
 +  dst->st_mtim.tv_nsec = src->st_mtimespec.tv_nsec;
 +  dst->st_ctim.tv_sec = src->st_ctimespec.tv_sec;
 +  dst->st_ctim.tv_nsec = src->st_ctimespec.tv_nsec;
 +  dst->st_birthtim.tv_sec = src->st_birthtimespec.tv_sec;
 +  dst->st_birthtim.tv_nsec = src->st_birthtimespec.tv_nsec;
 +  dst->st_flags = src->st_flags;
 +  dst->st_gen = src->st_gen;
 +#elif defined(__ANDROID__)
 +  dst->st_atim.tv_sec = src->st_atime;
 +  dst->st_atim.tv_nsec = src->st_atimensec;
 +  dst->st_mtim.tv_sec = src->st_mtime;
 +  dst->st_mtim.tv_nsec = src->st_mtimensec;
 +  dst->st_ctim.tv_sec = src->st_ctime;
 +  dst->st_ctim.tv_nsec = src->st_ctimensec;
 +  dst->st_birthtim.tv_sec = src->st_ctime;
 +  dst->st_birthtim.tv_nsec = src->st_ctimensec;
 +  dst->st_flags = 0;
 +  dst->st_gen = 0;
 +#elif !defined(_AIX) && (       \
 +    defined(__DragonFly__)   || \
 +    defined(__FreeBSD__)     || \
 +    defined(__OpenBSD__)     || \
 +    defined(__NetBSD__)      || \
 +    defined(_GNU_SOURCE)     || \
 +    defined(_BSD_SOURCE)     || \
 +    defined(_SVID_SOURCE)    || \
 +    defined(_XOPEN_SOURCE)   || \
 +    defined(_DEFAULT_SOURCE))
 +  dst->st_atim.tv_sec = src->st_atim.tv_sec;
 +  dst->st_atim.tv_nsec = src->st_atim.tv_nsec;
 +  dst->st_mtim.tv_sec = src->st_mtim.tv_sec;
 +  dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec;
 +  dst->st_ctim.tv_sec = src->st_ctim.tv_sec;
 +  dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec;
 +# if defined(__FreeBSD__)    || \
 +     defined(__NetBSD__)
 +  dst->st_birthtim.tv_sec = src->st_birthtim.tv_sec;
 +  dst->st_birthtim.tv_nsec = src->st_birthtim.tv_nsec;
 +  dst->st_flags = src->st_flags;
 +  dst->st_gen = src->st_gen;
 +# else
 +  dst->st_birthtim.tv_sec = src->st_ctim.tv_sec;
 +  dst->st_birthtim.tv_nsec = src->st_ctim.tv_nsec;
 +  dst->st_flags = 0;
 +  dst->st_gen = 0;
 +# endif
 +#else
 +  dst->st_atim.tv_sec = src->st_atime;
 +  dst->st_atim.tv_nsec = 0;
 +  dst->st_mtim.tv_sec = src->st_mtime;
 +  dst->st_mtim.tv_nsec = 0;
 +  dst->st_ctim.tv_sec = src->st_ctime;
 +  dst->st_ctim.tv_nsec = 0;
 +  dst->st_birthtim.tv_sec = src->st_ctime;
 +  dst->st_birthtim.tv_nsec = 0;
 +  dst->st_flags = 0;
 +  dst->st_gen = 0;
 +#endif
 +}
 +
 +
++static int uv__fs_statx(int fd,
++                        const char* path,
++                        int is_fstat,
++                        int is_lstat,
++                        uv_stat_t* buf) {
++  STATIC_ASSERT(UV_ENOSYS != -1);
++#ifdef __linux__
++  static int no_statx;
++  struct uv__statx statxbuf;
++  int dirfd;
++  int flags;
++  int mode;
++  int rc;
++
++  if (no_statx)
++    return UV_ENOSYS;
++
++  dirfd = AT_FDCWD;
++  flags = 0; /* AT_STATX_SYNC_AS_STAT */
++  mode = 0xFFF; /* STATX_BASIC_STATS + STATX_BTIME */
++
++  if (is_fstat) {
++    dirfd = fd;
++    flags |= 0x1000; /* AT_EMPTY_PATH */
++  }
++
++  if (is_lstat)
++    flags |= AT_SYMLINK_NOFOLLOW;
++
++  rc = uv__statx(dirfd, path, flags, mode, &statxbuf);
++
++  if (rc == -1) {
++    /* EPERM happens when a seccomp filter rejects the system call.
++     * Has been observed with libseccomp < 2.3.3 and docker < 18.04.
++     */
++    if (errno != EINVAL && errno != EPERM && errno != ENOSYS)
++      return -1;
++
++    no_statx = 1;
++    return UV_ENOSYS;
++  }
++
++  buf->st_dev = 256 * statxbuf.stx_dev_major + statxbuf.stx_dev_minor;
++  buf->st_mode = statxbuf.stx_mode;
++  buf->st_nlink = statxbuf.stx_nlink;
++  buf->st_uid = statxbuf.stx_uid;
++  buf->st_gid = statxbuf.stx_gid;
++  buf->st_rdev = statxbuf.stx_rdev_major;
++  buf->st_ino = statxbuf.stx_ino;
++  buf->st_size = statxbuf.stx_size;
++  buf->st_blksize = statxbuf.stx_blksize;
++  buf->st_blocks = statxbuf.stx_blocks;
++  buf->st_atim.tv_sec = statxbuf.stx_atime.tv_sec;
++  buf->st_atim.tv_nsec = statxbuf.stx_atime.tv_nsec;
++  buf->st_mtim.tv_sec = statxbuf.stx_mtime.tv_sec;
++  buf->st_mtim.tv_nsec = statxbuf.stx_mtime.tv_nsec;
++  buf->st_ctim.tv_sec = statxbuf.stx_ctime.tv_sec;
++  buf->st_ctim.tv_nsec = statxbuf.stx_ctime.tv_nsec;
++  buf->st_birthtim.tv_sec = statxbuf.stx_btime.tv_sec;
++  buf->st_birthtim.tv_nsec = statxbuf.stx_btime.tv_nsec;
++  buf->st_flags = 0;
++  buf->st_gen = 0;
++
++  return 0;
++#else
++  return UV_ENOSYS;
++#endif /* __linux__ */
++}
++
++
 +static int uv__fs_stat(const char *path, uv_stat_t *buf) {
 +  struct stat pbuf;
 +  int ret;
 +
++  ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 0, buf);
++  if (ret != UV_ENOSYS)
++    return ret;
++
 +  ret = stat(path, &pbuf);
 +  if (ret == 0)
 +    uv__to_stat(&pbuf, buf);
 +
 +  return ret;
 +}
 +
 +
 +static int uv__fs_lstat(const char *path, uv_stat_t *buf) {
 +  struct stat pbuf;
 +  int ret;
 +
++  ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 1, buf);
++  if (ret != UV_ENOSYS)
++    return ret;
++
 +  ret = lstat(path, &pbuf);
 +  if (ret == 0)
 +    uv__to_stat(&pbuf, buf);
 +
 +  return ret;
 +}
 +
 +
 +static int uv__fs_fstat(int fd, uv_stat_t *buf) {
 +  struct stat pbuf;
 +  int ret;
 +
++  ret = uv__fs_statx(fd, "", /* is_fstat */ 1, /* is_lstat */ 0, buf);
++  if (ret != UV_ENOSYS)
++    return ret;
++
 +  ret = fstat(fd, &pbuf);
 +  if (ret == 0)
 +    uv__to_stat(&pbuf, buf);
 +
 +  return ret;
 +}
 +
 +static size_t uv__fs_buf_offset(uv_buf_t* bufs, size_t size) {
 +  size_t offset;
 +  /* Figure out which bufs are done */
 +  for (offset = 0; size > 0 && bufs[offset].len <= size; ++offset)
 +    size -= bufs[offset].len;
 +
 +  /* Fix a partial read/write */
 +  if (size > 0) {
 +    bufs[offset].base += size;
 +    bufs[offset].len -= size;
 +  }
 +  return offset;
 +}
 +
 +static ssize_t uv__fs_write_all(uv_fs_t* req) {
 +  unsigned int iovmax;
 +  unsigned int nbufs;
 +  uv_buf_t* bufs;
 +  ssize_t total;
 +  ssize_t result;
 +
 +  iovmax = uv__getiovmax();
 +  nbufs = req->nbufs;
 +  bufs = req->bufs;
 +  total = 0;
 +
 +  while (nbufs > 0) {
 +    req->nbufs = nbufs;
 +    if (req->nbufs > iovmax)
 +      req->nbufs = iovmax;
 +
 +    do
 +      result = uv__fs_write(req);
 +    while (result < 0 && errno == EINTR);
 +
 +    if (result <= 0) {
 +      if (total == 0)
 +        total = result;
 +      break;
 +    }
 +
 +    if (req->off >= 0)
 +      req->off += result;
 +
 +    req->nbufs = uv__fs_buf_offset(req->bufs, result);
 +    req->bufs += req->nbufs;
 +    nbufs -= req->nbufs;
 +    total += result;
 +  }
 +
 +  if (bufs != req->bufsml)
 +    uv__free(bufs);
 +
 +  req->bufs = NULL;
 +  req->nbufs = 0;
 +
 +  return total;
 +}
 +
 +
 +static void uv__fs_work(struct uv__work* w) {
 +  int retry_on_eintr;
 +  uv_fs_t* req;
 +  ssize_t r;
 +
 +  req = container_of(w, uv_fs_t, work_req);
 +  retry_on_eintr = !(req->fs_type == UV_FS_CLOSE ||
 +                     req->fs_type == UV_FS_READ);
 +
 +  do {
 +    errno = 0;
 +
 +#define X(type, action)                                                       \
 +  case UV_FS_ ## type:                                                        \
 +    r = action;                                                               \
 +    break;
 +
 +    switch (req->fs_type) {
 +    X(ACCESS, access(req->path, req->flags));
 +    X(CHMOD, chmod(req->path, req->mode));
 +    X(CHOWN, chown(req->path, req->uid, req->gid));
-     X(CLOSE, close(req->file));
++    X(CLOSE, uv__fs_close(req->file));
 +    X(COPYFILE, uv__fs_copyfile(req));
 +    X(FCHMOD, fchmod(req->file, req->mode));
 +    X(FCHOWN, fchown(req->file, req->uid, req->gid));
 +    X(LCHOWN, lchown(req->path, req->uid, req->gid));
 +    X(FDATASYNC, uv__fs_fdatasync(req));
 +    X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
 +    X(FSYNC, uv__fs_fsync(req));
 +    X(FTRUNCATE, ftruncate(req->file, req->off));
 +    X(FUTIME, uv__fs_futime(req));
 +    X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
 +    X(LINK, link(req->path, req->new_path));
 +    X(MKDIR, mkdir(req->path, req->mode));
 +    X(MKDTEMP, uv__fs_mkdtemp(req));
 +    X(OPEN, uv__fs_open(req));
 +    X(READ, uv__fs_read(req));
 +    X(SCANDIR, uv__fs_scandir(req));
++    X(OPENDIR, uv__fs_opendir(req));
++    X(READDIR, uv__fs_readdir(req));
++    X(CLOSEDIR, uv__fs_closedir(req));
 +    X(READLINK, uv__fs_readlink(req));
 +    X(REALPATH, uv__fs_realpath(req));
 +    X(RENAME, rename(req->path, req->new_path));
 +    X(RMDIR, rmdir(req->path));
 +    X(SENDFILE, uv__fs_sendfile(req));
 +    X(STAT, uv__fs_stat(req->path, &req->statbuf));
 +    X(SYMLINK, symlink(req->path, req->new_path));
 +    X(UNLINK, unlink(req->path));
 +    X(UTIME, uv__fs_utime(req));
 +    X(WRITE, uv__fs_write_all(req));
 +    default: abort();
 +    }
 +#undef X
 +  } while (r == -1 && errno == EINTR && retry_on_eintr);
 +
 +  if (r == -1)
 +    req->result = UV__ERR(errno);
 +  else
 +    req->result = r;
 +
 +  if (r == 0 && (req->fs_type == UV_FS_STAT ||
 +                 req->fs_type == UV_FS_FSTAT ||
 +                 req->fs_type == UV_FS_LSTAT)) {
 +    req->ptr = &req->statbuf;
 +  }
 +}
 +
 +
 +static void uv__fs_done(struct uv__work* w, int status) {
 +  uv_fs_t* req;
 +
 +  req = container_of(w, uv_fs_t, work_req);
 +  uv__req_unregister(req->loop, req);
 +
 +  if (status == UV_ECANCELED) {
 +    assert(req->result == 0);
 +    req->result = UV_ECANCELED;
 +  }
 +
 +  req->cb(req);
 +}
 +
 +
 +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,
 +                uv_fs_t* req,
 +                const char* path,
 +                int mode,
 +                uv_fs_cb cb) {
 +  INIT(CHMOD);
 +  PATH;
 +  req->mode = mode;
 +  POST;
 +}
 +
 +
 +int uv_fs_chown(uv_loop_t* loop,
 +                uv_fs_t* req,
 +                const char* path,
 +                uv_uid_t uid,
 +                uv_gid_t gid,
 +                uv_fs_cb cb) {
 +  INIT(CHOWN);
 +  PATH;
 +  req->uid = uid;
 +  req->gid = gid;
 +  POST;
 +}
 +
 +
 +int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
 +  INIT(CLOSE);
 +  req->file = file;
 +  POST;
 +}
 +
 +
 +int uv_fs_fchmod(uv_loop_t* loop,
 +                 uv_fs_t* req,
 +                 uv_file file,
 +                 int mode,
 +                 uv_fs_cb cb) {
 +  INIT(FCHMOD);
 +  req->file = file;
 +  req->mode = mode;
 +  POST;
 +}
 +
 +
 +int uv_fs_fchown(uv_loop_t* loop,
 +                 uv_fs_t* req,
 +                 uv_file file,
 +                 uv_uid_t uid,
 +                 uv_gid_t gid,
 +                 uv_fs_cb cb) {
 +  INIT(FCHOWN);
 +  req->file = file;
 +  req->uid = uid;
 +  req->gid = gid;
 +  POST;
 +}
 +
 +
 +int uv_fs_lchown(uv_loop_t* loop,
 +                 uv_fs_t* req,
 +                 const char* path,
 +                 uv_uid_t uid,
 +                 uv_gid_t gid,
 +                 uv_fs_cb cb) {
 +  INIT(LCHOWN);
 +  PATH;
 +  req->uid = uid;
 +  req->gid = gid;
 +  POST;
 +}
 +
 +
 +int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
 +  INIT(FDATASYNC);
 +  req->file = file;
 +  POST;
 +}
 +
 +
 +int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
 +  INIT(FSTAT);
 +  req->file = file;
 +  POST;
 +}
 +
 +
 +int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
 +  INIT(FSYNC);
 +  req->file = file;
 +  POST;
 +}
 +
 +
 +int uv_fs_ftruncate(uv_loop_t* loop,
 +                    uv_fs_t* req,
 +                    uv_file file,
 +                    int64_t off,
 +                    uv_fs_cb cb) {
 +  INIT(FTRUNCATE);
 +  req->file = file;
 +  req->off = off;
 +  POST;
 +}
 +
 +
 +int uv_fs_futime(uv_loop_t* loop,
 +                 uv_fs_t* req,
 +                 uv_file file,
 +                 double atime,
 +                 double mtime,
 +                 uv_fs_cb cb) {
 +  INIT(FUTIME);
 +  req->file = file;
 +  req->atime = atime;
 +  req->mtime = mtime;
 +  POST;
 +}
 +
 +
 +int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
 +  INIT(LSTAT);
 +  PATH;
 +  POST;
 +}
 +
 +
 +int uv_fs_link(uv_loop_t* loop,
 +               uv_fs_t* req,
 +               const char* path,
 +               const char* new_path,
 +               uv_fs_cb cb) {
 +  INIT(LINK);
 +  PATH2;
 +  POST;
 +}
 +
 +
 +int uv_fs_mkdir(uv_loop_t* loop,
 +                uv_fs_t* req,
 +                const char* path,
 +                int mode,
 +                uv_fs_cb cb) {
 +  INIT(MKDIR);
 +  PATH;
 +  req->mode = mode;
 +  POST;
 +}
 +
 +
 +int uv_fs_mkdtemp(uv_loop_t* loop,
 +                  uv_fs_t* req,
 +                  const char* tpl,
 +                  uv_fs_cb cb) {
 +  INIT(MKDTEMP);
 +  req->path = uv__strdup(tpl);
 +  if (req->path == NULL)
 +    return UV_ENOMEM;
 +  POST;
 +}
 +
 +
 +int uv_fs_open(uv_loop_t* loop,
 +               uv_fs_t* req,
 +               const char* path,
 +               int flags,
 +               int mode,
 +               uv_fs_cb cb) {
 +  INIT(OPEN);
 +  PATH;
 +  req->flags = flags;
 +  req->mode = mode;
 +  POST;
 +}
 +
 +
 +int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
 +               uv_file file,
 +               const uv_buf_t bufs[],
 +               unsigned int nbufs,
 +               int64_t off,
 +               uv_fs_cb cb) {
 +  INIT(READ);
 +
 +  if (bufs == NULL || nbufs == 0)
 +    return UV_EINVAL;
 +
 +  req->file = file;
 +
 +  req->nbufs = nbufs;
 +  req->bufs = req->bufsml;
 +  if (nbufs > ARRAY_SIZE(req->bufsml))
 +    req->bufs = uv__malloc(nbufs * sizeof(*bufs));
 +
 +  if (req->bufs == NULL)
 +    return UV_ENOMEM;
 +
 +  memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
 +
 +  req->off = off;
 +  POST;
 +}
 +
 +
 +int uv_fs_scandir(uv_loop_t* loop,
 +                  uv_fs_t* req,
 +                  const char* path,
 +                  int flags,
 +                  uv_fs_cb cb) {
 +  INIT(SCANDIR);
 +  PATH;
 +  req->flags = flags;
 +  POST;
 +}
 +
++int uv_fs_opendir(uv_loop_t* loop,
++                  uv_fs_t* req,
++                  const char* path,
++                  uv_fs_cb cb) {
++  INIT(OPENDIR);
++  PATH;
++  POST;
++}
++
++int uv_fs_readdir(uv_loop_t* loop,
++                  uv_fs_t* req,
++                  uv_dir_t* dir,
++                  uv_fs_cb cb) {
++  INIT(READDIR);
++
++  if (dir == NULL || dir->dir == NULL || dir->dirents == NULL)
++    return UV_EINVAL;
++
++  req->ptr = dir;
++  POST;
++}
++
++int uv_fs_closedir(uv_loop_t* loop,
++                   uv_fs_t* req,
++                   uv_dir_t* dir,
++                   uv_fs_cb cb) {
++  INIT(CLOSEDIR);
++
++  if (dir == NULL)
++    return UV_EINVAL;
++
++  req->ptr = dir;
++  POST;
++}
 +
 +int uv_fs_readlink(uv_loop_t* loop,
 +                   uv_fs_t* req,
 +                   const char* path,
 +                   uv_fs_cb cb) {
 +  INIT(READLINK);
 +  PATH;
 +  POST;
 +}
 +
 +
 +int uv_fs_realpath(uv_loop_t* loop,
 +                  uv_fs_t* req,
 +                  const char * path,
 +                  uv_fs_cb cb) {
 +  INIT(REALPATH);
 +  PATH;
 +  POST;
 +}
 +
 +
 +int uv_fs_rename(uv_loop_t* loop,
 +                 uv_fs_t* req,
 +                 const char* path,
 +                 const char* new_path,
 +                 uv_fs_cb cb) {
 +  INIT(RENAME);
 +  PATH2;
 +  POST;
 +}
 +
 +
 +int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
 +  INIT(RMDIR);
 +  PATH;
 +  POST;
 +}
 +
 +
 +int uv_fs_sendfile(uv_loop_t* loop,
 +                   uv_fs_t* req,
 +                   uv_file out_fd,
 +                   uv_file in_fd,
 +                   int64_t off,
 +                   size_t len,
 +                   uv_fs_cb cb) {
 +  INIT(SENDFILE);
 +  req->flags = in_fd; /* hack */
 +  req->file = out_fd;
 +  req->off = off;
 +  req->bufsml[0].len = len;
 +  POST;
 +}
 +
 +
 +int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
 +  INIT(STAT);
 +  PATH;
 +  POST;
 +}
 +
 +
 +int uv_fs_symlink(uv_loop_t* loop,
 +                  uv_fs_t* req,
 +                  const char* path,
 +                  const char* new_path,
 +                  int flags,
 +                  uv_fs_cb cb) {
 +  INIT(SYMLINK);
 +  PATH2;
 +  req->flags = flags;
 +  POST;
 +}
 +
 +
 +int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
 +  INIT(UNLINK);
 +  PATH;
 +  POST;
 +}
 +
 +
 +int uv_fs_utime(uv_loop_t* loop,
 +                uv_fs_t* req,
 +                const char* path,
 +                double atime,
 +                double mtime,
 +                uv_fs_cb cb) {
 +  INIT(UTIME);
 +  PATH;
 +  req->atime = atime;
 +  req->mtime = mtime;
 +  POST;
 +}
 +
 +
 +int uv_fs_write(uv_loop_t* loop,
 +                uv_fs_t* req,
 +                uv_file file,
 +                const uv_buf_t bufs[],
 +                unsigned int nbufs,
 +                int64_t off,
 +                uv_fs_cb cb) {
 +  INIT(WRITE);
 +
 +  if (bufs == NULL || nbufs == 0)
 +    return UV_EINVAL;
 +
 +  req->file = file;
 +
 +  req->nbufs = nbufs;
 +  req->bufs = req->bufsml;
 +  if (nbufs > ARRAY_SIZE(req->bufsml))
 +    req->bufs = uv__malloc(nbufs * sizeof(*bufs));
 +
 +  if (req->bufs == NULL)
 +    return UV_ENOMEM;
 +
 +  memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
 +
 +  req->off = off;
 +  POST;
 +}
 +
 +
 +void uv_fs_req_cleanup(uv_fs_t* req) {
 +  if (req == NULL)
 +    return;
 +
 +  /* Only necessary for asychronous requests, i.e., requests with a callback.
 +   * Synchronous ones don't copy their arguments and have req->path and
 +   * req->new_path pointing to user-owned memory.  UV_FS_MKDTEMP is the
 +   * exception to the rule, it always allocates memory.
 +   */
 +  if (req->path != NULL && (req->cb != NULL || req->fs_type == UV_FS_MKDTEMP))
 +    uv__free((void*) req->path);  /* Memory is shared with req->new_path. */
 +
 +  req->path = NULL;
 +  req->new_path = NULL;
 +
++  if (req->fs_type == UV_FS_READDIR && req->ptr != NULL)
++    uv__fs_readdir_cleanup(req);
++
 +  if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
 +    uv__fs_scandir_cleanup(req);
 +
 +  if (req->bufs != req->bufsml)
 +    uv__free(req->bufs);
 +  req->bufs = NULL;
 +
-   if (req->ptr != &req->statbuf)
++  if (req->fs_type != UV_FS_OPENDIR && req->ptr != &req->statbuf)
 +    uv__free(req->ptr);
 +  req->ptr = NULL;
 +}
 +
 +
 +int uv_fs_copyfile(uv_loop_t* loop,
 +                   uv_fs_t* req,
 +                   const char* path,
 +                   const char* new_path,
 +                   int flags,
 +                   uv_fs_cb cb) {
 +  INIT(COPYFILE);
 +
 +  if (flags & ~(UV_FS_COPYFILE_EXCL |
 +                UV_FS_COPYFILE_FICLONE |
 +                UV_FS_COPYFILE_FICLONE_FORCE)) {
 +    return UV_EINVAL;
 +  }
 +
 +  PATH2;
 +  req->flags = flags;
 +  POST;
 +}
diff --cc Utilities/cmlibuv/src/unix/haiku.c
index 0000000,7708851..7708851
mode 000000,100644..100644
--- a/Utilities/cmlibuv/src/unix/haiku.c
+++ b/Utilities/cmlibuv/src/unix/haiku.c
diff --cc Utilities/cmlibuv/src/unix/internal.h
index 48fe6e8,0000000..b43c0b1
mode 100644,000000..100644
--- a/Utilities/cmlibuv/src/unix/internal.h
+++ b/Utilities/cmlibuv/src/unix/internal.h
@@@ -1,319 -1,0 +1,326 @@@
 +/* 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.
 + */
 +
 +#ifndef UV_UNIX_INTERNAL_H_
 +#define UV_UNIX_INTERNAL_H_
 +
 +#include "uv-common.h"
 +
 +#include <assert.h>
 +#include <stdlib.h> /* abort */
 +#include <string.h> /* strrchr */
 +#include <fcntl.h>  /* O_CLOEXEC, may be */
 +#include <stdio.h>
 +#include <errno.h>
 +
 +#if defined(__STRICT_ANSI__)
 +# define inline __inline
 +#endif
 +
 +#if defined(__linux__)
 +# include "linux-syscalls.h"
 +#endif /* __linux__ */
 +
 +#if defined(__MVS__)
 +# include "os390-syscalls.h"
 +#endif /* __MVS__ */
 +
 +#if defined(__sun)
 +# include <sys/port.h>
 +# include <port.h>
 +#endif /* __sun */
 +
 +#if defined(_AIX)
 +# define reqevents events
 +# define rtnevents revents
 +# include <sys/poll.h>
 +#else
 +# include <poll.h>
 +#endif /* _AIX */
 +
 +#if defined(__APPLE__) && !TARGET_OS_IPHONE
 +# include <AvailabilityMacros.h>
 +#endif
 +
 +#if defined(CMAKE_BOOTSTRAP)
 +# undef pthread_atfork
 +# define pthread_atfork(prepare, parent, child) \
 +     uv__pthread_atfork(prepare, parent, child)
 +int uv__pthread_atfork(void (*prepare)(void), void (*parent)(void),
 +                       void (*child)(void));
 +# undef pthread_sigmask
 +# define pthread_sigmask(how, set, oldset) \
 +     uv__pthread_sigmask(how, set, oldset)
 +int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
 +#elif defined(__ANDROID__)
 +int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
 +# ifdef pthread_sigmask
 +# undef pthread_sigmask
 +# endif
 +# define pthread_sigmask(how, set, oldset) uv__pthread_sigmask(how, set, oldset)
 +#endif
 +
 +#define ACCESS_ONCE(type, var)                                                \
 +  (*(volatile type*) &(var))
 +
 +#define ROUND_UP(a, b)                                                        \
 +  ((a) % (b) ? ((a) + (b)) - ((a) % (b)) : (a))
 +
 +#define UNREACHABLE()                                                         \
 +  do {                                                                        \
 +    assert(0 && "unreachable code");                                          \
 +    abort();                                                                  \
 +  }                                                                           \
 +  while (0)
 +
 +#define SAVE_ERRNO(block)                                                     \
 +  do {                                                                        \
 +    int _saved_errno = errno;                                                 \
 +    do { block; } while (0);                                                  \
 +    errno = _saved_errno;                                                     \
 +  }                                                                           \
 +  while (0)
 +
 +/* The __clang__ and __INTEL_COMPILER checks are superfluous because they
 + * define __GNUC__. They are here to convey to you, dear reader, that these
 + * macros are enabled when compiling with clang or icc.
 + */
 +#if defined(__clang__) ||                                                     \
 +    defined(__GNUC__) ||                                                      \
-     defined(__INTEL_COMPILER) ||                                              \
-     defined(__SUNPRO_C)
++    defined(__INTEL_COMPILER)
 +# define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration
 +# define UV_UNUSED(declaration)     __attribute__((unused)) declaration
 +#else
 +# define UV_DESTRUCTOR(declaration) declaration
 +# define UV_UNUSED(declaration)     declaration
 +#endif
 +
 +/* Leans on the fact that, on Linux, POLLRDHUP == EPOLLRDHUP. */
 +#ifdef POLLRDHUP
 +# define UV__POLLRDHUP POLLRDHUP
 +#else
 +# define UV__POLLRDHUP 0x2000
 +#endif
 +
 +#ifdef POLLPRI
 +# define UV__POLLPRI POLLPRI
 +#else
 +# define UV__POLLPRI 0
 +#endif
 +
 +#if !defined(O_CLOEXEC) && defined(__FreeBSD__)
 +/*
 + * It may be that we are just missing `__POSIX_VISIBLE >= 200809`.
 + * Try using fixed value const and give up, if it doesn't work
 + */
 +# define O_CLOEXEC 0x00100000
 +#endif
 +
 +typedef struct uv__stream_queued_fds_s uv__stream_queued_fds_t;
 +
 +/* loop flags */
 +enum {
 +  UV_LOOP_BLOCK_SIGPROF = 1
 +};
 +
 +/* flags of excluding ifaddr */
 +enum {
 +  UV__EXCLUDE_IFPHYS,
 +  UV__EXCLUDE_IFADDR
 +};
 +
 +typedef enum {
 +  UV_CLOCK_PRECISE = 0,  /* Use the highest resolution clock available. */
 +  UV_CLOCK_FAST = 1      /* Use the fastest clock with <= 1ms granularity. */
 +} uv_clocktype_t;
 +
 +struct uv__stream_queued_fds_s {
 +  unsigned int size;
 +  unsigned int offset;
 +  int fds[1];
 +};
 +
 +
 +#if defined(_AIX) || \
 +    defined(__APPLE__) || \
 +    defined(__DragonFly__) || \
 +    defined(__FreeBSD__) || \
 +    defined(__FreeBSD_kernel__) || \
 +    defined(__linux__) || \
 +    defined(__OpenBSD__) || \
 +    defined(__NetBSD__)
 +#define uv__cloexec uv__cloexec_ioctl
 +#define uv__nonblock uv__nonblock_ioctl
 +#else
 +#define uv__cloexec uv__cloexec_fcntl
 +#define uv__nonblock uv__nonblock_fcntl
 +#endif
 +
 +/* On Linux, uv__nonblock_fcntl() and uv__nonblock_ioctl() do not commute
 + * when O_NDELAY is not equal to O_NONBLOCK.  Case in point: linux/sparc32
 + * and linux/sparc64, where O_NDELAY is O_NONBLOCK + another bit.
 + *
 + * Libuv uses uv__nonblock_fcntl() directly sometimes so ensure that it
 + * commutes with uv__nonblock().
 + */
 +#if defined(__linux__) && O_NDELAY != O_NONBLOCK
 +#undef uv__nonblock
 +#define uv__nonblock uv__nonblock_fcntl
 +#endif
 +
 +/* core */
 +int uv__cloexec_ioctl(int fd, int set);
 +int uv__cloexec_fcntl(int fd, int set);
 +int uv__nonblock_ioctl(int fd, int set);
 +int uv__nonblock_fcntl(int fd, int set);
 +int uv__close(int fd); /* preserves errno */
 +int uv__close_nocheckstdio(int fd);
++int uv__close_nocancel(int fd);
 +int uv__socket(int domain, int type, int protocol);
 +ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags);
 +void uv__make_close_pending(uv_handle_t* handle);
 +int uv__getiovmax(void);
 +
 +void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd);
 +void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events);
 +void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events);
 +void uv__io_close(uv_loop_t* loop, uv__io_t* w);
 +void uv__io_feed(uv_loop_t* loop, uv__io_t* w);
 +int uv__io_active(const uv__io_t* w, unsigned int events);
 +int uv__io_check_fd(uv_loop_t* loop, int fd);
 +void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */
 +int uv__io_fork(uv_loop_t* loop);
 +int uv__fd_exists(uv_loop_t* loop, int fd);
 +
 +/* async */
 +void uv__async_stop(uv_loop_t* loop);
 +int uv__async_fork(uv_loop_t* loop);
 +
 +
 +/* loop */
 +void uv__run_idle(uv_loop_t* loop);
 +void uv__run_check(uv_loop_t* loop);
 +void uv__run_prepare(uv_loop_t* loop);
 +
 +/* stream */
 +void uv__stream_init(uv_loop_t* loop, uv_stream_t* stream,
 +    uv_handle_type type);
 +int uv__stream_open(uv_stream_t*, int fd, int flags);
 +void uv__stream_destroy(uv_stream_t* stream);
 +#if defined(__APPLE__)
 +int uv__stream_try_select(uv_stream_t* stream, int* fd);
 +#endif /* defined(__APPLE__) */
 +void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events);
 +int uv__accept(int sockfd);
 +int uv__dup2_cloexec(int oldfd, int newfd);
 +int uv__open_cloexec(const char* path, int flags);
 +
 +/* tcp */
 +int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
 +int uv__tcp_nodelay(int fd, int on);
 +int uv__tcp_keepalive(int fd, int on, unsigned int delay);
 +
 +/* pipe */
 +int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
 +
 +/* signal */
 +void uv__signal_close(uv_signal_t* handle);
 +void uv__signal_global_once_init(void);
 +void uv__signal_loop_cleanup(uv_loop_t* loop);
 +int uv__signal_loop_fork(uv_loop_t* loop);
 +
 +/* platform specific */
 +uint64_t uv__hrtime(uv_clocktype_t type);
 +int uv__kqueue_init(uv_loop_t* loop);
 +int uv__platform_loop_init(uv_loop_t* loop);
 +void uv__platform_loop_delete(uv_loop_t* loop);
 +void uv__platform_invalidate_fd(uv_loop_t* loop, int fd);
 +
 +/* various */
 +void uv__async_close(uv_async_t* handle);
 +void uv__check_close(uv_check_t* handle);
 +void uv__fs_event_close(uv_fs_event_t* handle);
 +void uv__idle_close(uv_idle_t* handle);
 +void uv__pipe_close(uv_pipe_t* handle);
 +void uv__poll_close(uv_poll_t* handle);
 +void uv__prepare_close(uv_prepare_t* handle);
 +void uv__process_close(uv_process_t* handle);
 +void uv__stream_close(uv_stream_t* handle);
 +void uv__tcp_close(uv_tcp_t* handle);
 +void uv__udp_close(uv_udp_t* handle);
 +void uv__udp_finish_close(uv_udp_t* handle);
 +uv_handle_type uv__handle_type(int fd);
 +FILE* uv__open_file(const char* path);
 +int uv__getpwuid_r(uv_passwd_t* pwd);
 +
 +
 +#if defined(__APPLE__) && !defined(CMAKE_BOOTSTRAP)
 +int uv___stream_fd(const uv_stream_t* handle);
 +#define uv__stream_fd(handle) (uv___stream_fd((const uv_stream_t*) (handle)))
 +#else
 +#define uv__stream_fd(handle) ((handle)->io_watcher.fd)
 +#endif /* defined(__APPLE__) */
 +
 +#ifdef UV__O_NONBLOCK
 +# define UV__F_NONBLOCK UV__O_NONBLOCK
 +#else
 +# define UV__F_NONBLOCK 1
 +#endif
 +
 +int uv__make_socketpair(int fds[2], int flags);
 +int uv__make_pipe(int fds[2], int flags);
 +
 +#if defined(__APPLE__)
 +
 +int uv__fsevents_init(uv_fs_event_t* handle);
 +int uv__fsevents_close(uv_fs_event_t* handle);
 +void uv__fsevents_loop_delete(uv_loop_t* loop);
 +
 +#endif /* defined(__APPLE__) */
 +
 +UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) {
 +  /* Use a fast time source if available.  We only need millisecond precision.
 +   */
 +  loop->time = uv__hrtime(UV_CLOCK_FAST) / 1000000;
 +}
 +
 +UV_UNUSED(static char* uv__basename_r(const char* path)) {
 +  char* s;
 +
 +  s = strrchr(path, '/');
 +  if (s == NULL)
 +    return (char*) path;
 +
 +  return s + 1;
 +}
 +
 +#if defined(__linux__)
 +int uv__inotify_fork(uv_loop_t* loop, void* old_watchers);
 +#endif
 +
++typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*);
++
++int uv__getsockpeername(const uv_handle_t* handle,
++                        uv__peersockfunc func,
++                        struct sockaddr* name,
++                        int* namelen);
++
 +#endif /* UV_UNIX_INTERNAL_H_ */
diff --cc Utilities/cmlibuv/src/unix/pipe.c
index 9657bc9,0000000..7d97550
mode 100644,000000..100644
--- a/Utilities/cmlibuv/src/unix/pipe.c
+++ b/Utilities/cmlibuv/src/unix/pipe.c
@@@ -1,375 -1,0 +1,375 @@@
 +/* 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 "internal.h"
 +
 +#include <assert.h>
 +#include <errno.h>
 +#include <string.h>
 +#include <sys/un.h>
 +#include <unistd.h>
 +#include <stdlib.h>
 +
 +
 +int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
 +  uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
 +  handle->shutdown_req = NULL;
 +  handle->connect_req = NULL;
 +  handle->pipe_fname = NULL;
 +  handle->ipc = ipc;
 +  return 0;
 +}
 +
 +
 +int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
 +  struct sockaddr_un saddr;
 +  const char* pipe_fname = NULL;
 +  int sockfd = -1;
 +  int err;
 +
 +  /* Already bound? */
 +  if (uv__stream_fd(handle) >= 0)
 +    return UV_EINVAL;
 +
 +  /* Make a copy of the file name, it outlives this function's scope. */
 +  pipe_fname = uv__strdup(name);
 +  if (pipe_fname == NULL)
 +    return UV_ENOMEM;
 +
 +  /* We've got a copy, don't touch the original any more. */
 +  name = NULL;
 +
 +  err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
 +  if (err < 0)
 +    goto err_socket;
 +  sockfd = err;
 +
 +  memset(&saddr, 0, sizeof saddr);
 +  uv__strscpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path));
 +  saddr.sun_family = AF_UNIX;
 +
 +  if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
 +    err = UV__ERR(errno);
 +    /* Convert ENOENT to EACCES for compatibility with Windows. */
 +    if (err == UV_ENOENT)
 +      err = UV_EACCES;
 +
 +    uv__close(sockfd);
 +    goto err_socket;
 +  }
 +
 +  /* Success. */
 +  handle->flags |= UV_HANDLE_BOUND;
 +  handle->pipe_fname = pipe_fname; /* Is a strdup'ed copy. */
 +  handle->io_watcher.fd = sockfd;
 +  return 0;
 +
 +err_socket:
 +  uv__free((void*)pipe_fname);
 +  return err;
 +}
 +
 +
 +int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
 +  if (uv__stream_fd(handle) == -1)
 +    return UV_EINVAL;
 +
 +#if defined(__MVS__)
 +  /* On zOS, backlog=0 has undefined behaviour */
 +  if (backlog == 0)
 +    backlog = 1;
 +  else if (backlog < 0)
 +    backlog = SOMAXCONN;
 +#endif
 +
 +  if (listen(uv__stream_fd(handle), backlog))
 +    return UV__ERR(errno);
 +
 +  handle->connection_cb = cb;
 +  handle->io_watcher.cb = uv__server_io;
 +  uv__io_start(handle->loop, &handle->io_watcher, POLLIN);
 +  return 0;
 +}
 +
 +
 +void uv__pipe_close(uv_pipe_t* handle) {
 +  if (handle->pipe_fname) {
 +    /*
 +     * Unlink the file system entity before closing the file descriptor.
 +     * Doing it the other way around introduces a race where our process
 +     * unlinks a socket with the same name that's just been created by
 +     * another thread or process.
 +     */
 +    unlink(handle->pipe_fname);
 +    uv__free((void*)handle->pipe_fname);
 +    handle->pipe_fname = NULL;
 +  }
 +
 +  uv__stream_close((uv_stream_t*)handle);
 +}
 +
 +
 +int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
 +  int flags;
 +  int mode;
 +  int err;
 +  flags = 0;
 +
 +  if (uv__fd_exists(handle->loop, fd))
 +    return UV_EEXIST;
 +
 +  do
 +    mode = fcntl(fd, F_GETFL);
 +  while (mode == -1 && errno == EINTR);
 +
 +  if (mode == -1)
 +    return UV__ERR(errno); /* according to docs, must be EBADF */
 +
 +  err = uv__nonblock(fd, 1);
 +  if (err)
 +    return err;
 +
 +#if defined(__APPLE__) && !defined(CMAKE_BOOTSTRAP)
 +  err = uv__stream_try_select((uv_stream_t*) handle, &fd);
 +  if (err)
 +    return err;
 +#endif /* defined(__APPLE__) */
 +
 +  mode &= O_ACCMODE;
 +  if (mode != O_WRONLY)
 +    flags |= UV_HANDLE_READABLE;
 +  if (mode != O_RDONLY)
 +    flags |= UV_HANDLE_WRITABLE;
 +
 +  return uv__stream_open((uv_stream_t*)handle, fd, flags);
 +}
 +
 +
 +void uv_pipe_connect(uv_connect_t* req,
 +                    uv_pipe_t* handle,
 +                    const char* name,
 +                    uv_connect_cb cb) {
 +  struct sockaddr_un saddr;
 +  int new_sock;
 +  int err;
 +  int r;
 +
 +  new_sock = (uv__stream_fd(handle) == -1);
 +
 +  if (new_sock) {
 +    err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
 +    if (err < 0)
 +      goto out;
 +    handle->io_watcher.fd = err;
 +  }
 +
 +  memset(&saddr, 0, sizeof saddr);
 +  uv__strscpy(saddr.sun_path, name, sizeof(saddr.sun_path));
 +  saddr.sun_family = AF_UNIX;
 +
 +  do {
 +    r = connect(uv__stream_fd(handle),
 +                (struct sockaddr*)&saddr, sizeof saddr);
 +  }
 +  while (r == -1 && errno == EINTR);
 +
 +  if (r == -1 && errno != EINPROGRESS) {
 +    err = UV__ERR(errno);
 +#if defined(__CYGWIN__) || defined(__MSYS__)
 +    /* EBADF is supposed to mean that the socket fd is bad, but
 +       Cygwin reports EBADF instead of ENOTSOCK when the file is
 +       not a socket.  We do not expect to see a bad fd here
 +       (e.g. due to new_sock), so translate the error.  */
 +    if (err == UV_EBADF)
 +      err = UV_ENOTSOCK;
 +#endif
 +    goto out;
 +  }
 +
 +  err = 0;
 +  if (new_sock) {
 +    err = uv__stream_open((uv_stream_t*)handle,
 +                          uv__stream_fd(handle),
 +                          UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
 +  }
 +
 +  if (err == 0)
-     uv__io_start(handle->loop, &handle->io_watcher, POLLIN | POLLOUT);
++    uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
 +
 +out:
 +  handle->delayed_error = err;
 +  handle->connect_req = req;
 +
 +  uv__req_init(handle->loop, req, UV_CONNECT);
 +  req->handle = (uv_stream_t*)handle;
 +  req->cb = cb;
 +  QUEUE_INIT(&req->queue);
 +
 +  /* Force callback to run on next tick in case of error. */
 +  if (err)
 +    uv__io_feed(handle->loop, &handle->io_watcher);
 +
 +}
 +
 +
- typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*);
- 
- 
 +static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
 +                                    uv__peersockfunc func,
 +                                    char* buffer,
 +                                    size_t* size) {
 +  struct sockaddr_un sa;
 +  socklen_t addrlen;
 +  int err;
 +
 +  addrlen = sizeof(sa);
 +  memset(&sa, 0, addrlen);
-   err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen);
++  err = uv__getsockpeername((const uv_handle_t*) handle,
++                            func,
++                            (struct sockaddr*) &sa,
++                            (int*) &addrlen);
 +  if (err < 0) {
 +    *size = 0;
-     return UV__ERR(errno);
++    return err;
 +  }
 +
 +#if defined(__linux__)
 +  if (sa.sun_path[0] == 0)
 +    /* Linux abstract namespace */
 +    addrlen -= offsetof(struct sockaddr_un, sun_path);
 +  else
 +#endif
 +    addrlen = strlen(sa.sun_path);
 +
 +
 +  if (addrlen >= *size) {
 +    *size = addrlen + 1;
 +    return UV_ENOBUFS;
 +  }
 +
 +  memcpy(buffer, sa.sun_path, addrlen);
 +  *size = addrlen;
 +
 +  /* only null-terminate if it's not an abstract socket */
 +  if (buffer[0] != '\0')
 +    buffer[addrlen] = '\0';
 +
 +  return 0;
 +}
 +
 +
 +int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) {
 +  return uv__pipe_getsockpeername(handle, getsockname, buffer, size);
 +}
 +
 +
 +int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
 +  return uv__pipe_getsockpeername(handle, getpeername, buffer, size);
 +}
 +
 +
 +void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {
 +}
 +
 +
 +int uv_pipe_pending_count(uv_pipe_t* handle) {
 +  uv__stream_queued_fds_t* queued_fds;
 +
 +  if (!handle->ipc)
 +    return 0;
 +
 +  if (handle->accepted_fd == -1)
 +    return 0;
 +
 +  if (handle->queued_fds == NULL)
 +    return 1;
 +
 +  queued_fds = handle->queued_fds;
 +  return queued_fds->offset + 1;
 +}
 +
 +
 +uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
 +  if (!handle->ipc)
 +    return UV_UNKNOWN_HANDLE;
 +
 +  if (handle->accepted_fd == -1)
 +    return UV_UNKNOWN_HANDLE;
 +  else
 +    return uv__handle_type(handle->accepted_fd);
 +}
 +
 +
 +int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
 +  unsigned desired_mode;
 +  struct stat pipe_stat;
 +  char* name_buffer;
 +  size_t name_len;
 +  int r;
 +
 +  if (handle == NULL || uv__stream_fd(handle) == -1)
 +    return UV_EBADF;
 +
 +  if (mode != UV_READABLE &&
 +      mode != UV_WRITABLE &&
 +      mode != (UV_WRITABLE | UV_READABLE))
 +    return UV_EINVAL;
 +
 +  /* Unfortunately fchmod does not work on all platforms, we will use chmod. */
 +  name_len = 0;
 +  r = uv_pipe_getsockname(handle, NULL, &name_len);
 +  if (r != UV_ENOBUFS)
 +    return r;
 +
 +  name_buffer = uv__malloc(name_len);
 +  if (name_buffer == NULL)
 +    return UV_ENOMEM;
 +
 +  r = uv_pipe_getsockname(handle, name_buffer, &name_len);
 +  if (r != 0) {
 +    uv__free(name_buffer);
 +    return r;
 +  }
 +
 +  /* stat must be used as fstat has a bug on Darwin */
 +  if (stat(name_buffer, &pipe_stat) == -1) {
 +    uv__free(name_buffer);
 +    return -errno;
 +  }
 +
 +  desired_mode = 0;
 +  if (mode & UV_READABLE)
 +    desired_mode |= S_IRUSR | S_IRGRP | S_IROTH;
 +  if (mode & UV_WRITABLE)
 +    desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
 +
 +  /* Exit early if pipe already has desired mode. */
 +  if ((pipe_stat.st_mode & desired_mode) == desired_mode) {
 +    uv__free(name_buffer);
 +    return 0;
 +  }
 +
 +  pipe_stat.st_mode |= desired_mode;
 +
 +  r = chmod(name_buffer, pipe_stat.st_mode);
 +  uv__free(name_buffer);
 +
 +  return r != -1 ? 0 : UV__ERR(errno);
 +}
diff --cc Utilities/cmlibuv/src/unix/process.c
index e9579f5,0000000..f4826bf
mode 100644,000000..100644
--- a/Utilities/cmlibuv/src/unix/process.c
+++ b/Utilities/cmlibuv/src/unix/process.c
@@@ -1,651 -1,0 +1,658 @@@
 +/* 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 "internal.h"
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <assert.h>
 +#include <errno.h>
 +
 +#include <sys/types.h>
 +#include <sys/wait.h>
 +#include <unistd.h>
 +#include <fcntl.h>
 +#include <poll.h>
 +#include <sched.h>
 +
 +#if defined(__APPLE__) && !TARGET_OS_IPHONE
 +# include <crt_externs.h>
 +# define environ (*_NSGetEnviron())
 +#else
 +extern char **environ;
 +#endif
 +
 +#if defined(__linux__) || defined(__GLIBC__)
 +# include <grp.h>
 +#endif
 +
 +#ifndef CMAKE_BOOTSTRAP
 +#if defined(__linux__)
 +# define uv__cpu_set_t cpu_set_t
 +#elif defined(__FreeBSD__)
 +# include <sys/param.h>
 +# include <sys/cpuset.h>
 +# include <pthread_np.h>
 +# define uv__cpu_set_t cpuset_t
 +#endif
 +#endif
 +
 +static void uv__chld(uv_signal_t* handle, int signum) {
 +  uv_process_t* process;
 +  uv_loop_t* loop;
 +  int exit_status;
 +  int term_signal;
 +  int status;
 +  pid_t pid;
 +  QUEUE pending;
 +  QUEUE* q;
 +  QUEUE* h;
 +
 +  assert(signum == SIGCHLD);
 +
 +  QUEUE_INIT(&pending);
 +  loop = handle->loop;
 +
 +  h = &loop->process_handles;
 +  q = QUEUE_HEAD(h);
 +  while (q != h) {
 +    process = QUEUE_DATA(q, uv_process_t, queue);
 +    q = QUEUE_NEXT(q);
 +
 +    do
 +      pid = waitpid(process->pid, &status, WNOHANG);
 +    while (pid == -1 && errno == EINTR);
 +
 +    if (pid == 0)
 +      continue;
 +
 +    if (pid == -1) {
 +      if (errno != ECHILD)
 +        abort();
 +      continue;
 +    }
 +
 +    process->status = status;
 +    QUEUE_REMOVE(&process->queue);
 +    QUEUE_INSERT_TAIL(&pending, &process->queue);
 +  }
 +
 +  h = &pending;
 +  q = QUEUE_HEAD(h);
 +  while (q != h) {
 +    process = QUEUE_DATA(q, uv_process_t, queue);
 +    q = QUEUE_NEXT(q);
 +
 +    QUEUE_REMOVE(&process->queue);
 +    QUEUE_INIT(&process->queue);
 +    uv__handle_stop(process);
 +
 +    if (process->exit_cb == NULL)
 +      continue;
 +
 +    exit_status = 0;
 +    if (WIFEXITED(process->status))
 +      exit_status = WEXITSTATUS(process->status);
 +
 +    term_signal = 0;
 +    if (WIFSIGNALED(process->status))
 +      term_signal = WTERMSIG(process->status);
 +
 +    process->exit_cb(process, exit_status, term_signal);
 +  }
 +  assert(QUEUE_EMPTY(&pending));
 +}
 +
 +
 +int uv__make_socketpair(int fds[2], int flags) {
 +#if defined(__linux__)
 +  static int no_cloexec;
 +
 +  if (no_cloexec)
 +    goto skip;
 +
 +  if (socketpair(AF_UNIX, SOCK_STREAM | UV__SOCK_CLOEXEC | flags, 0, fds) == 0)
 +    return 0;
 +
 +  /* Retry on EINVAL, it means SOCK_CLOEXEC is not supported.
 +   * Anything else is a genuine error.
 +   */
 +  if (errno != EINVAL)
 +    return UV__ERR(errno);
 +
 +  no_cloexec = 1;
 +
 +skip:
 +#endif
 +
 +  if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
 +    return UV__ERR(errno);
 +
 +  uv__cloexec(fds[0], 1);
 +  uv__cloexec(fds[1], 1);
 +
 +  if (flags & UV__F_NONBLOCK) {
 +    uv__nonblock(fds[0], 1);
 +    uv__nonblock(fds[1], 1);
 +  }
 +
 +  return 0;
 +}
 +
 +
 +int uv__make_pipe(int fds[2], int flags) {
 +#if defined(__linux__)
 +  static int no_pipe2;
 +
 +  if (no_pipe2)
 +    goto skip;
 +
 +  if (uv__pipe2(fds, flags | UV__O_CLOEXEC) == 0)
 +    return 0;
 +
 +  if (errno != ENOSYS)
 +    return UV__ERR(errno);
 +
 +  no_pipe2 = 1;
 +
 +skip:
 +#endif
 +
 +  if (pipe(fds))
 +    return UV__ERR(errno);
 +
 +  uv__cloexec(fds[0], 1);
 +  uv__cloexec(fds[1], 1);
 +
 +  if (flags & UV__F_NONBLOCK) {
 +    uv__nonblock(fds[0], 1);
 +    uv__nonblock(fds[1], 1);
 +  }
 +
 +  return 0;
 +}
 +
 +
 +/*
 + * Used for initializing stdio streams like options.stdin_stream. Returns
 + * zero on success. See also the cleanup section in uv_spawn().
 + */
 +static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
 +  int mask;
 +  int fd;
 +
 +  mask = UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM;
 +
 +  switch (container->flags & mask) {
 +  case UV_IGNORE:
 +    return 0;
 +
 +  case UV_CREATE_PIPE:
 +    assert(container->data.stream != NULL);
 +    if (container->data.stream->type != UV_NAMED_PIPE)
 +      return UV_EINVAL;
 +    else
 +      return uv__make_socketpair(fds, 0);
 +
 +  case UV_INHERIT_FD:
 +  case UV_INHERIT_STREAM:
 +    if (container->flags & UV_INHERIT_FD)
 +      fd = container->data.fd;
 +    else
 +      fd = uv__stream_fd(container->data.stream);
 +
 +    if (fd == -1)
 +      return UV_EINVAL;
 +
 +    fds[1] = fd;
 +    return 0;
 +
 +  default:
 +    assert(0 && "Unexpected flags");
 +    return UV_EINVAL;
 +  }
 +}
 +
 +
 +static int uv__process_open_stream(uv_stdio_container_t* container,
 +                                   int pipefds[2]) {
 +  int flags;
 +  int err;
 +
 +  if (!(container->flags & UV_CREATE_PIPE) || pipefds[0] < 0)
 +    return 0;
 +
 +  err = uv__close(pipefds[1]);
 +  if (err != 0)
 +    abort();
 +
 +  pipefds[1] = -1;
 +  uv__nonblock(pipefds[0], 1);
 +
 +  flags = 0;
 +  if (container->flags & UV_WRITABLE_PIPE)
 +    flags |= UV_HANDLE_READABLE;
 +  if (container->flags & UV_READABLE_PIPE)
 +    flags |= UV_HANDLE_WRITABLE;
 +
 +  return uv__stream_open(container->data.stream, pipefds[0], flags);
 +}
 +
 +
 +static void uv__process_close_stream(uv_stdio_container_t* container) {
 +  if (!(container->flags & UV_CREATE_PIPE)) return;
 +  uv__stream_close((uv_stream_t*)container->data.stream);
 +}
 +
 +
 +static void uv__write_int(int fd, int val) {
 +  ssize_t n;
 +
 +  do
 +    n = write(fd, &val, sizeof(val));
 +  while (n == -1 && errno == EINTR);
 +
 +  if (n == -1 && errno == EPIPE)
 +    return; /* parent process has quit */
 +
 +  assert(n == sizeof(val));
 +}
 +
 +
 +#if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH))
 +/* execvp is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED, so must be
 + * avoided. Since this isn't called on those targets, the function
 + * doesn't even need to be defined for them.
 + */
 +static void uv__process_child_init(const uv_process_options_t* options,
 +                                   int stdio_count,
 +                                   int (*pipes)[2],
 +                                   int error_fd) {
 +  sigset_t set;
 +  int close_fd;
 +  int use_fd;
 +  int err;
 +  int fd;
 +  int n;
 +#ifndef CMAKE_BOOTSTRAP
 +#if defined(__linux__) || defined(__FreeBSD__)
 +  int r;
 +  int i;
 +  int cpumask_size;
 +  uv__cpu_set_t cpuset;
 +#endif
 +#endif
 +
 +  if (options->flags & UV_PROCESS_DETACHED)
 +    setsid();
 +
 +  /* First duplicate low numbered fds, since it's not safe to duplicate them,
 +   * they could get replaced. Example: swapping stdout and stderr; without
 +   * this fd 2 (stderr) would be duplicated into fd 1, thus making both
 +   * stdout and stderr go to the same fd, which was not the intention. */
 +  for (fd = 0; fd < stdio_count; fd++) {
 +    use_fd = pipes[fd][1];
 +    if (use_fd < 0 || use_fd >= fd)
 +      continue;
 +    pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count);
 +    if (pipes[fd][1] == -1) {
 +      uv__write_int(error_fd, UV__ERR(errno));
 +      _exit(127);
 +    }
 +  }
 +
 +  for (fd = 0; fd < stdio_count; fd++) {
 +    close_fd = pipes[fd][0];
 +    use_fd = pipes[fd][1];
 +
 +    if (use_fd < 0) {
 +      if (fd >= 3)
 +        continue;
 +      else {
 +        /* redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is
 +         * set
 +         */
 +        use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR);
 +        close_fd = use_fd;
 +
 +        if (use_fd < 0) {
 +          uv__write_int(error_fd, UV__ERR(errno));
 +          _exit(127);
 +        }
 +      }
 +    }
 +
 +    if (fd == use_fd)
 +      uv__cloexec_fcntl(use_fd, 0);
 +    else
 +      fd = dup2(use_fd, fd);
 +
 +    if (fd == -1) {
 +      uv__write_int(error_fd, UV__ERR(errno));
 +      _exit(127);
 +    }
 +
 +    if (fd <= 2)
 +      uv__nonblock_fcntl(fd, 0);
 +
 +    if (close_fd >= stdio_count)
 +      uv__close(close_fd);
 +  }
 +
 +  for (fd = 0; fd < stdio_count; fd++) {
 +    use_fd = pipes[fd][1];
 +
 +    if (use_fd >= stdio_count)
 +      uv__close(use_fd);
 +  }
 +
 +  if (options->cwd != NULL && chdir(options->cwd)) {
 +    uv__write_int(error_fd, UV__ERR(errno));
 +    _exit(127);
 +  }
 +
 +  if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) {
 +    /* When dropping privileges from root, the `setgroups` call will
 +     * remove any extraneous groups. If we don't call this, then
 +     * even though our uid has dropped, we may still have groups
 +     * that enable us to do super-user things. This will fail if we
 +     * aren't root, so don't bother checking the return value, this
 +     * is just done as an optimistic privilege dropping function.
 +     */
 +    SAVE_ERRNO(setgroups(0, NULL));
 +  }
 +
 +  if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) {
 +    uv__write_int(error_fd, UV__ERR(errno));
 +    _exit(127);
 +  }
 +
 +  if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) {
 +    uv__write_int(error_fd, UV__ERR(errno));
 +    _exit(127);
 +  }
 +
 +#ifndef CMAKE_BOOTSTRAP
 +#if defined(__linux__) || defined(__FreeBSD__)
 +  if (options->cpumask != NULL) {
 +    cpumask_size = uv_cpumask_size();
 +    assert(options->cpumask_size >= (size_t)cpumask_size);
 +
 +    CPU_ZERO(&cpuset);
 +    for (i = 0; i < cpumask_size; ++i) {
 +      if (options->cpumask[i]) {
 +        CPU_SET(i, &cpuset);
 +      }
 +    }
 +
 +    r = -pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
 +    if (r != 0) {
 +      uv__write_int(error_fd, r);
 +      _exit(127);
 +    }
 +  }
 +#endif
 +#endif
 +
 +  if (options->env != NULL) {
 +    environ = options->env;
 +  }
 +
 +  /* Reset signal disposition.  Use a hard-coded limit because NSIG
 +   * is not fixed on Linux: it's either 32, 34 or 64, depending on
 +   * whether RT signals are enabled.  We are not allowed to touch
 +   * RT signal handlers, glibc uses them internally.
 +   */
 +  for (n = 1; n < 32; n += 1) {
 +    if (n == SIGKILL || n == SIGSTOP)
 +      continue;  /* Can't be changed. */
 +
++#if defined(__HAIKU__)
++    if (n == SIGKILLTHR)
++      continue;  /* Can't be changed. */
++#endif
++
 +    if (SIG_ERR != signal(n, SIG_DFL))
 +      continue;
 +
 +    uv__write_int(error_fd, UV__ERR(errno));
 +    _exit(127);
 +  }
 +
 +  /* Reset signal mask. */
 +  sigemptyset(&set);
 +  err = pthread_sigmask(SIG_SETMASK, &set, NULL);
 +
 +  if (err != 0) {
 +    uv__write_int(error_fd, UV__ERR(err));
 +    _exit(127);
 +  }
 +
 +  execvp(options->file, options->args);
 +  uv__write_int(error_fd, UV__ERR(errno));
 +  _exit(127);
 +}
 +#endif
 +
 +
 +int uv_spawn(uv_loop_t* loop,
 +             uv_process_t* process,
 +             const uv_process_options_t* options) {
 +#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
 +  /* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */
 +  return UV_ENOSYS;
 +#else
 +  int signal_pipe[2] = { -1, -1 };
 +  int pipes_storage[8][2];
 +  int (*pipes)[2];
 +  int stdio_count;
 +  ssize_t r;
 +  pid_t pid;
 +  int err;
 +  int exec_errorno;
 +  int i;
 +  int status;
 +
 +  if (options->cpumask != NULL) {
 +#ifndef CMAKE_BOOTSTRAP
 +#if defined(__linux__) || defined(__FreeBSD__)
 +    if (options->cpumask_size < (size_t)uv_cpumask_size()) {
 +      return UV_EINVAL;
 +    }
 +#else
 +    return UV_ENOTSUP;
 +#endif
 +#else
 +    return UV_ENOTSUP;
 +#endif
 +  }
 +
 +  assert(options->file != NULL);
 +  assert(!(options->flags & ~(UV_PROCESS_DETACHED |
 +                              UV_PROCESS_SETGID |
 +                              UV_PROCESS_SETUID |
 +                              UV_PROCESS_WINDOWS_HIDE |
++                              UV_PROCESS_WINDOWS_HIDE_CONSOLE |
++                              UV_PROCESS_WINDOWS_HIDE_GUI |
 +                              UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
 +
 +  uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
 +  QUEUE_INIT(&process->queue);
 +
 +  stdio_count = options->stdio_count;
 +  if (stdio_count < 3)
 +    stdio_count = 3;
 +
 +  err = UV_ENOMEM;
 +  pipes = pipes_storage;
 +  if (stdio_count > (int) ARRAY_SIZE(pipes_storage))
 +    pipes = uv__malloc(stdio_count * sizeof(*pipes));
 +
 +  if (pipes == NULL)
 +    goto error;
 +
 +  for (i = 0; i < stdio_count; i++) {
 +    pipes[i][0] = -1;
 +    pipes[i][1] = -1;
 +  }
 +
 +  for (i = 0; i < options->stdio_count; i++) {
 +    err = uv__process_init_stdio(options->stdio + i, pipes[i]);
 +    if (err)
 +      goto error;
 +  }
 +
 +  /* This pipe is used by the parent to wait until
 +   * the child has called `execve()`. We need this
 +   * to avoid the following race condition:
 +   *
 +   *    if ((pid = fork()) > 0) {
 +   *      kill(pid, SIGTERM);
 +   *    }
 +   *    else if (pid == 0) {
 +   *      execve("/bin/cat", argp, envp);
 +   *    }
 +   *
 +   * The parent sends a signal immediately after forking.
 +   * Since the child may not have called `execve()` yet,
 +   * there is no telling what process receives the signal,
 +   * our fork or /bin/cat.
 +   *
 +   * To avoid ambiguity, we create a pipe with both ends
 +   * marked close-on-exec. Then, after the call to `fork()`,
 +   * the parent polls the read end until it EOFs or errors with EPIPE.
 +   */
 +  err = uv__make_pipe(signal_pipe, 0);
 +  if (err)
 +    goto error;
 +
 +  uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD);
 +
 +  /* Acquire write lock to prevent opening new fds in worker threads */
 +  uv_rwlock_wrlock(&loop->cloexec_lock);
 +  pid = fork();
 +
 +  if (pid == -1) {
 +    err = UV__ERR(errno);
 +    uv_rwlock_wrunlock(&loop->cloexec_lock);
 +    uv__close(signal_pipe[0]);
 +    uv__close(signal_pipe[1]);
 +    goto error;
 +  }
 +
 +  if (pid == 0) {
 +    uv__process_child_init(options, stdio_count, pipes, signal_pipe[1]);
 +    abort();
 +  }
 +
 +  /* Release lock in parent process */
 +  uv_rwlock_wrunlock(&loop->cloexec_lock);
 +  uv__close(signal_pipe[1]);
 +
 +  process->status = 0;
 +  exec_errorno = 0;
 +  do
 +    r = read(signal_pipe[0], &exec_errorno, sizeof(exec_errorno));
 +  while (r == -1 && errno == EINTR);
 +
 +  if (r == 0)
 +    ; /* okay, EOF */
 +  else if (r == sizeof(exec_errorno)) {
 +    do
 +      err = waitpid(pid, &status, 0); /* okay, read errorno */
 +    while (err == -1 && errno == EINTR);
 +    assert(err == pid);
 +  } else if (r == -1 && errno == EPIPE) {
 +    do
 +      err = waitpid(pid, &status, 0); /* okay, got EPIPE */
 +    while (err == -1 && errno == EINTR);
 +    assert(err == pid);
 +  } else
 +    abort();
 +
 +  uv__close_nocheckstdio(signal_pipe[0]);
 +
 +  for (i = 0; i < options->stdio_count; i++) {
 +    err = uv__process_open_stream(options->stdio + i, pipes[i]);
 +    if (err == 0)
 +      continue;
 +
 +    while (i--)
 +      uv__process_close_stream(options->stdio + i);
 +
 +    goto error;
 +  }
 +
 +  /* Only activate this handle if exec() happened successfully */
 +  if (exec_errorno == 0) {
 +    QUEUE_INSERT_TAIL(&loop->process_handles, &process->queue);
 +    uv__handle_start(process);
 +  }
 +
 +  process->pid = pid;
 +  process->exit_cb = options->exit_cb;
 +
 +  if (pipes != pipes_storage)
 +    uv__free(pipes);
 +
 +  return exec_errorno;
 +
 +error:
 +  if (pipes != NULL) {
 +    for (i = 0; i < stdio_count; i++) {
 +      if (i < options->stdio_count)
 +        if (options->stdio[i].flags & (UV_INHERIT_FD | UV_INHERIT_STREAM))
 +          continue;
 +      if (pipes[i][0] != -1)
 +        uv__close_nocheckstdio(pipes[i][0]);
 +      if (pipes[i][1] != -1)
 +        uv__close_nocheckstdio(pipes[i][1]);
 +    }
 +
 +    if (pipes != pipes_storage)
 +      uv__free(pipes);
 +  }
 +
 +  return err;
 +#endif
 +}
 +
 +
 +int uv_process_kill(uv_process_t* process, int signum) {
 +  return uv_kill(process->pid, signum);
 +}
 +
 +
 +int uv_kill(int pid, int signum) {
 +  if (kill(pid, signum))
 +    return UV__ERR(errno);
 +  else
 +    return 0;
 +}
 +
 +
 +void uv__process_close(uv_process_t* handle) {
 +  QUEUE_REMOVE(&handle->queue);
 +  uv__handle_stop(handle);
 +  if (QUEUE_EMPTY(&handle->loop->process_handles))
 +    uv_signal_stop(&handle->loop->child_watcher);
 +}
diff --cc Utilities/cmlibuv/src/unix/stream.c
index 4b9123f,0000000..8121f64
mode 100644,000000..100644
--- a/Utilities/cmlibuv/src/unix/stream.c
+++ b/Utilities/cmlibuv/src/unix/stream.c
@@@ -1,1688 -1,0 +1,1688 @@@
 +/* 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 "internal.h"
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <assert.h>
 +#include <errno.h>
 +
 +#include <sys/types.h>
 +#include <sys/socket.h>
 +#include <sys/uio.h>
 +#include <sys/un.h>
 +#include <unistd.h>
 +#include <limits.h> /* IOV_MAX */
 +
 +#if defined(__APPLE__)
 +# include <sys/event.h>
 +# include <sys/time.h>
 +# include <sys/select.h>
 +
 +/* Forward declaration */
 +typedef struct uv__stream_select_s uv__stream_select_t;
 +
 +struct uv__stream_select_s {
 +  uv_stream_t* stream;
 +  uv_thread_t thread;
 +  uv_sem_t close_sem;
 +  uv_sem_t async_sem;
 +  uv_async_t async;
 +  int events;
 +  int fake_fd;
 +  int int_fd;
 +  int fd;
 +  fd_set* sread;
 +  size_t sread_sz;
 +  fd_set* swrite;
 +  size_t swrite_sz;
 +};
 +
 +/* Due to a possible kernel bug at least in OS X 10.10 "Yosemite",
 + * EPROTOTYPE can be returned while trying to write to a socket that is
 + * shutting down. If we retry the write, we should get the expected EPIPE
 + * instead.
 + */
 +# define RETRY_ON_WRITE_ERROR(errno) (errno == EINTR || errno == EPROTOTYPE)
 +# define IS_TRANSIENT_WRITE_ERROR(errno, send_handle) \
 +    (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS || \
 +     (errno == EMSGSIZE && send_handle != NULL))
 +#else
 +# define RETRY_ON_WRITE_ERROR(errno) (errno == EINTR)
 +# define IS_TRANSIENT_WRITE_ERROR(errno, send_handle) \
 +    (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
 +#endif /* defined(__APPLE__) */
 +
 +static void uv__stream_connect(uv_stream_t*);
 +static void uv__write(uv_stream_t* stream);
 +static void uv__read(uv_stream_t* stream);
 +static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events);
 +static void uv__write_callbacks(uv_stream_t* stream);
 +static size_t uv__write_req_size(uv_write_t* req);
 +
 +
 +void uv__stream_init(uv_loop_t* loop,
 +                     uv_stream_t* stream,
 +                     uv_handle_type type) {
 +  int err;
 +
 +  uv__handle_init(loop, (uv_handle_t*)stream, type);
 +  stream->read_cb = NULL;
 +  stream->alloc_cb = NULL;
 +  stream->close_cb = NULL;
 +  stream->connection_cb = NULL;
 +  stream->connect_req = NULL;
 +  stream->shutdown_req = NULL;
 +  stream->accepted_fd = -1;
 +  stream->queued_fds = NULL;
 +  stream->delayed_error = 0;
 +  QUEUE_INIT(&stream->write_queue);
 +  QUEUE_INIT(&stream->write_completed_queue);
 +  stream->write_queue_size = 0;
 +
 +  if (loop->emfile_fd == -1) {
 +    err = uv__open_cloexec("/dev/null", O_RDONLY);
 +    if (err < 0)
 +        /* In the rare case that "/dev/null" isn't mounted open "/"
 +         * instead.
 +         */
 +        err = uv__open_cloexec("/", O_RDONLY);
 +    if (err >= 0)
 +      loop->emfile_fd = err;
 +  }
 +
 +#if defined(__APPLE__) && !defined(CMAKE_BOOTSTRAP)
 +  stream->select = NULL;
 +#endif /* defined(__APPLE_) */
 +
 +  uv__io_init(&stream->io_watcher, uv__stream_io, -1);
 +}
 +
 +
 +static void uv__stream_osx_interrupt_select(uv_stream_t* stream) {
 +#if defined(__APPLE__) && !defined(CMAKE_BOOTSTRAP)
 +  /* Notify select() thread about state change */
 +  uv__stream_select_t* s;
 +  int r;
 +
 +  s = stream->select;
 +  if (s == NULL)
 +    return;
 +
 +  /* Interrupt select() loop
 +   * NOTE: fake_fd and int_fd are socketpair(), thus writing to one will
 +   * emit read event on other side
 +   */
 +  do
 +    r = write(s->fake_fd, "x", 1);
 +  while (r == -1 && errno == EINTR);
 +
 +  assert(r == 1);
 +#else  /* !defined(__APPLE__) */
 +  /* No-op on any other platform */
 +#endif  /* !defined(__APPLE__) */
 +}
 +
 +
 +#if defined(__APPLE__) && !defined(CMAKE_BOOTSTRAP)
 +static void uv__stream_osx_select(void* arg) {
 +  uv_stream_t* stream;
 +  uv__stream_select_t* s;
 +  char buf[1024];
 +  int events;
 +  int fd;
 +  int r;
 +  int max_fd;
 +
 +  stream = arg;
 +  s = stream->select;
 +  fd = s->fd;
 +
 +  if (fd > s->int_fd)
 +    max_fd = fd;
 +  else
 +    max_fd = s->int_fd;
 +
 +  while (1) {
 +    /* Terminate on semaphore */
 +    if (uv_sem_trywait(&s->close_sem) == 0)
 +      break;
 +
 +    /* Watch fd using select(2) */
 +    memset(s->sread, 0, s->sread_sz);
 +    memset(s->swrite, 0, s->swrite_sz);
 +
 +    if (uv__io_active(&stream->io_watcher, POLLIN))
 +      FD_SET(fd, s->sread);
 +    if (uv__io_active(&stream->io_watcher, POLLOUT))
 +      FD_SET(fd, s->swrite);
 +    FD_SET(s->int_fd, s->sread);
 +
 +    /* Wait indefinitely for fd events */
 +    r = select(max_fd + 1, s->sread, s->swrite, NULL, NULL);
 +    if (r == -1) {
 +      if (errno == EINTR)
 +        continue;
 +
 +      /* XXX: Possible?! */
 +      abort();
 +    }
 +
 +    /* Ignore timeouts */
 +    if (r == 0)
 +      continue;
 +
 +    /* Empty socketpair's buffer in case of interruption */
 +    if (FD_ISSET(s->int_fd, s->sread))
 +      while (1) {
 +        r = read(s->int_fd, buf, sizeof(buf));
 +
 +        if (r == sizeof(buf))
 +          continue;
 +
 +        if (r != -1)
 +          break;
 +
 +        if (errno == EAGAIN || errno == EWOULDBLOCK)
 +          break;
 +
 +        if (errno == EINTR)
 +          continue;
 +
 +        abort();
 +      }
 +
 +    /* Handle events */
 +    events = 0;
 +    if (FD_ISSET(fd, s->sread))
 +      events |= POLLIN;
 +    if (FD_ISSET(fd, s->swrite))
 +      events |= POLLOUT;
 +
 +    assert(events != 0 || FD_ISSET(s->int_fd, s->sread));
 +    if (events != 0) {
 +      ACCESS_ONCE(int, s->events) = events;
 +
 +      uv_async_send(&s->async);
 +      uv_sem_wait(&s->async_sem);
 +
 +      /* Should be processed at this stage */
 +      assert((s->events == 0) || (stream->flags & UV_HANDLE_CLOSING));
 +    }
 +  }
 +}
 +
 +
 +static void uv__stream_osx_select_cb(uv_async_t* handle) {
 +  uv__stream_select_t* s;
 +  uv_stream_t* stream;
 +  int events;
 +
 +  s = container_of(handle, uv__stream_select_t, async);
 +  stream = s->stream;
 +
 +  /* Get and reset stream's events */
 +  events = s->events;
 +  ACCESS_ONCE(int, s->events) = 0;
 +
 +  assert(events != 0);
 +  assert(events == (events & (POLLIN | POLLOUT)));
 +
 +  /* Invoke callback on event-loop */
 +  if ((events & POLLIN) && uv__io_active(&stream->io_watcher, POLLIN))
 +    uv__stream_io(stream->loop, &stream->io_watcher, POLLIN);
 +
 +  if ((events & POLLOUT) && uv__io_active(&stream->io_watcher, POLLOUT))
 +    uv__stream_io(stream->loop, &stream->io_watcher, POLLOUT);
 +
 +  if (stream->flags & UV_HANDLE_CLOSING)
 +    return;
 +
 +  /* NOTE: It is important to do it here, otherwise `select()` might be called
 +   * before the actual `uv__read()`, leading to the blocking syscall
 +   */
 +  uv_sem_post(&s->async_sem);
 +}
 +
 +
 +static void uv__stream_osx_cb_close(uv_handle_t* async) {
 +  uv__stream_select_t* s;
 +
 +  s = container_of(async, uv__stream_select_t, async);
 +  uv__free(s);
 +}
 +
 +
 +int uv__stream_try_select(uv_stream_t* stream, int* fd) {
 +  /*
 +   * kqueue doesn't work with some files from /dev mount on osx.
 +   * select(2) in separate thread for those fds
 +   */
 +
 +  struct kevent filter[1];
 +  struct kevent events[1];
 +  struct timespec timeout;
 +  uv__stream_select_t* s;
 +  int fds[2];
 +  int err;
 +  int ret;
 +  int kq;
 +  int old_fd;
 +  int max_fd;
 +  size_t sread_sz;
 +  size_t swrite_sz;
 +
 +  kq = kqueue();
 +  if (kq == -1) {
 +    perror("(libuv) kqueue()");
 +    return UV__ERR(errno);
 +  }
 +
 +  EV_SET(&filter[0], *fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
 +
 +  /* Use small timeout, because we only want to capture EINVALs */
 +  timeout.tv_sec = 0;
 +  timeout.tv_nsec = 1;
 +
 +  do
 +    ret = kevent(kq, filter, 1, events, 1, &timeout);
 +  while (ret == -1 && errno == EINTR);
 +
 +  uv__close(kq);
 +
 +  if (ret == -1)
 +    return UV__ERR(errno);
 +
 +  if (ret == 0 || (events[0].flags & EV_ERROR) == 0 || events[0].data != EINVAL)
 +    return 0;
 +
 +  /* At this point we definitely know that this fd won't work with kqueue */
 +
 +  /*
 +   * Create fds for io watcher and to interrupt the select() loop.
 +   * NOTE: do it ahead of malloc below to allocate enough space for fd_sets
 +   */
 +  if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
 +    return UV__ERR(errno);
 +
 +  max_fd = *fd;
 +  if (fds[1] > max_fd)
 +    max_fd = fds[1];
 +
 +  sread_sz = ROUND_UP(max_fd + 1, sizeof(uint32_t) * NBBY) / NBBY;
 +  swrite_sz = sread_sz;
 +
 +  s = uv__malloc(sizeof(*s) + sread_sz + swrite_sz);
 +  if (s == NULL) {
 +    err = UV_ENOMEM;
 +    goto failed_malloc;
 +  }
 +
 +  s->events = 0;
 +  s->fd = *fd;
 +  s->sread = (fd_set*) ((char*) s + sizeof(*s));
 +  s->sread_sz = sread_sz;
 +  s->swrite = (fd_set*) ((char*) s->sread + sread_sz);
 +  s->swrite_sz = swrite_sz;
 +
 +  err = uv_async_init(stream->loop, &s->async, uv__stream_osx_select_cb);
 +  if (err)
 +    goto failed_async_init;
 +
 +  s->async.flags |= UV_HANDLE_INTERNAL;
 +  uv__handle_unref(&s->async);
 +
 +  err = uv_sem_init(&s->close_sem, 0);
 +  if (err != 0)
 +    goto failed_close_sem_init;
 +
 +  err = uv_sem_init(&s->async_sem, 0);
 +  if (err != 0)
 +    goto failed_async_sem_init;
 +
 +  s->fake_fd = fds[0];
 +  s->int_fd = fds[1];
 +
 +  old_fd = *fd;
 +  s->stream = stream;
 +  stream->select = s;
 +  *fd = s->fake_fd;
 +
 +  err = uv_thread_create(&s->thread, uv__stream_osx_select, stream);
 +  if (err != 0)
 +    goto failed_thread_create;
 +
 +  return 0;
 +
 +failed_thread_create:
 +  s->stream = NULL;
 +  stream->select = NULL;
 +  *fd = old_fd;
 +
 +  uv_sem_destroy(&s->async_sem);
 +
 +failed_async_sem_init:
 +  uv_sem_destroy(&s->close_sem);
 +
 +failed_close_sem_init:
 +  uv__close(fds[0]);
 +  uv__close(fds[1]);
 +  uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close);
 +  return err;
 +
 +failed_async_init:
 +  uv__free(s);
 +
 +failed_malloc:
 +  uv__close(fds[0]);
 +  uv__close(fds[1]);
 +
 +  return err;
 +}
 +#endif /* defined(__APPLE__) */
 +
 +
 +int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
 +#if defined(__APPLE__)
 +  int enable;
 +#endif
 +
 +  if (!(stream->io_watcher.fd == -1 || stream->io_watcher.fd == fd))
 +    return UV_EBUSY;
 +
 +  assert(fd >= 0);
 +  stream->flags |= flags;
 +
 +  if (stream->type == UV_TCP) {
 +    if ((stream->flags & UV_HANDLE_TCP_NODELAY) && uv__tcp_nodelay(fd, 1))
 +      return UV__ERR(errno);
 +
 +    /* TODO Use delay the user passed in. */
 +    if ((stream->flags & UV_HANDLE_TCP_KEEPALIVE) &&
 +        uv__tcp_keepalive(fd, 1, 60)) {
 +      return UV__ERR(errno);
 +    }
 +  }
 +
 +#if defined(__APPLE__)
 +  enable = 1;
 +  if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) &&
 +      errno != ENOTSOCK &&
 +      errno != EINVAL) {
 +    return UV__ERR(errno);
 +  }
 +#endif
 +
 +  stream->io_watcher.fd = fd;
 +
 +  return 0;
 +}
 +
 +
 +void uv__stream_flush_write_queue(uv_stream_t* stream, int error) {
 +  uv_write_t* req;
 +  QUEUE* q;
 +  while (!QUEUE_EMPTY(&stream->write_queue)) {
 +    q = QUEUE_HEAD(&stream->write_queue);
 +    QUEUE_REMOVE(q);
 +
 +    req = QUEUE_DATA(q, uv_write_t, queue);
 +    req->error = error;
 +
 +    QUEUE_INSERT_TAIL(&stream->write_completed_queue, &req->queue);
 +  }
 +}
 +
 +
 +void uv__stream_destroy(uv_stream_t* stream) {
 +  assert(!uv__io_active(&stream->io_watcher, POLLIN | POLLOUT));
 +  assert(stream->flags & UV_HANDLE_CLOSED);
 +
 +  if (stream->connect_req) {
 +    uv__req_unregister(stream->loop, stream->connect_req);
 +    stream->connect_req->cb(stream->connect_req, UV_ECANCELED);
 +    stream->connect_req = NULL;
 +  }
 +
 +  uv__stream_flush_write_queue(stream, UV_ECANCELED);
 +  uv__write_callbacks(stream);
 +
 +  if (stream->shutdown_req) {
 +    /* The ECANCELED error code is a lie, the shutdown(2) syscall is a
 +     * fait accompli at this point. Maybe we should revisit this in v0.11.
 +     * A possible reason for leaving it unchanged is that it informs the
 +     * callee that the handle has been destroyed.
 +     */
 +    uv__req_unregister(stream->loop, stream->shutdown_req);
 +    stream->shutdown_req->cb(stream->shutdown_req, UV_ECANCELED);
 +    stream->shutdown_req = NULL;
 +  }
 +
 +  assert(stream->write_queue_size == 0);
 +}
 +
 +
 +/* Implements a best effort approach to mitigating accept() EMFILE errors.
 + * We have a spare file descriptor stashed away that we close to get below
 + * the EMFILE limit. Next, we accept all pending connections and close them
 + * immediately to signal the clients that we're overloaded - and we are, but
 + * we still keep on trucking.
 + *
 + * There is one caveat: it's not reliable in a multi-threaded environment.
 + * The file descriptor limit is per process. Our party trick fails if another
 + * thread opens a file or creates a socket in the time window between us
 + * calling close() and accept().
 + */
 +static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {
 +  int err;
 +  int emfile_fd;
 +
 +  if (loop->emfile_fd == -1)
 +    return UV_EMFILE;
 +
 +  uv__close(loop->emfile_fd);
 +  loop->emfile_fd = -1;
 +
 +  do {
 +    err = uv__accept(accept_fd);
 +    if (err >= 0)
 +      uv__close(err);
 +  } while (err >= 0 || err == UV_EINTR);
 +
 +  emfile_fd = uv__open_cloexec("/", O_RDONLY);
 +  if (emfile_fd >= 0)
 +    loop->emfile_fd = emfile_fd;
 +
 +  return err;
 +}
 +
 +
 +#if defined(UV_HAVE_KQUEUE)
 +# define UV_DEC_BACKLOG(w) w->rcount--;
 +#else
 +# define UV_DEC_BACKLOG(w) /* no-op */
 +#endif /* defined(UV_HAVE_KQUEUE) */
 +
 +
 +void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
 +  uv_stream_t* stream;
 +  int err;
 +
 +  stream = container_of(w, uv_stream_t, io_watcher);
 +  assert(events & POLLIN);
 +  assert(stream->accepted_fd == -1);
 +  assert(!(stream->flags & UV_HANDLE_CLOSING));
 +
 +  uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
 +
 +  /* connection_cb can close the server socket while we're
 +   * in the loop so check it on each iteration.
 +   */
 +  while (uv__stream_fd(stream) != -1) {
 +    assert(stream->accepted_fd == -1);
 +
 +#if defined(UV_HAVE_KQUEUE)
 +    if (w->rcount <= 0)
 +      return;
 +#endif /* defined(UV_HAVE_KQUEUE) */
 +
 +    err = uv__accept(uv__stream_fd(stream));
 +    if (err < 0) {
 +      if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK))
 +        return;  /* Not an error. */
 +
 +      if (err == UV_ECONNABORTED)
 +        continue;  /* Ignore. Nothing we can do about that. */
 +
 +      if (err == UV_EMFILE || err == UV_ENFILE) {
 +        err = uv__emfile_trick(loop, uv__stream_fd(stream));
 +        if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK))
 +          break;
 +      }
 +
 +      stream->connection_cb(stream, err);
 +      continue;
 +    }
 +
 +    UV_DEC_BACKLOG(w)
 +    stream->accepted_fd = err;
 +    stream->connection_cb(stream, 0);
 +
 +    if (stream->accepted_fd != -1) {
 +      /* The user hasn't yet accepted called uv_accept() */
 +      uv__io_stop(loop, &stream->io_watcher, POLLIN);
 +      return;
 +    }
 +
 +    if (stream->type == UV_TCP &&
 +        (stream->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) {
 +      /* Give other processes a chance to accept connections. */
 +      struct timespec timeout = { 0, 1 };
 +      nanosleep(&timeout, NULL);
 +    }
 +  }
 +}
 +
 +
 +#undef UV_DEC_BACKLOG
 +
 +
 +int uv_accept(uv_stream_t* server, uv_stream_t* client) {
 +  int err;
 +
 +  assert(server->loop == client->loop);
 +
 +  if (server->accepted_fd == -1)
 +    return UV_EAGAIN;
 +
 +  switch (client->type) {
 +    case UV_NAMED_PIPE:
 +    case UV_TCP:
 +      err = uv__stream_open(client,
 +                            server->accepted_fd,
 +                            UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
 +      if (err) {
 +        /* TODO handle error */
 +        uv__close(server->accepted_fd);
 +        goto done;
 +      }
 +      break;
 +
 +    case UV_UDP:
 +      err = uv_udp_open((uv_udp_t*) client, server->accepted_fd);
 +      if (err) {
 +        uv__close(server->accepted_fd);
 +        goto done;
 +      }
 +      break;
 +
 +    default:
 +      return UV_EINVAL;
 +  }
 +
 +  client->flags |= UV_HANDLE_BOUND;
 +
 +done:
 +  /* Process queued fds */
 +  if (server->queued_fds != NULL) {
 +    uv__stream_queued_fds_t* queued_fds;
 +
 +    queued_fds = server->queued_fds;
 +
 +    /* Read first */
 +    server->accepted_fd = queued_fds->fds[0];
 +
 +    /* All read, free */
 +    assert(queued_fds->offset > 0);
 +    if (--queued_fds->offset == 0) {
 +      uv__free(queued_fds);
 +      server->queued_fds = NULL;
 +    } else {
 +      /* Shift rest */
 +      memmove(queued_fds->fds,
 +              queued_fds->fds + 1,
 +              queued_fds->offset * sizeof(*queued_fds->fds));
 +    }
 +  } else {
 +    server->accepted_fd = -1;
 +    if (err == 0)
 +      uv__io_start(server->loop, &server->io_watcher, POLLIN);
 +  }
 +  return err;
 +}
 +
 +
 +int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
 +  int err;
 +
 +  switch (stream->type) {
 +  case UV_TCP:
 +    err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb);
 +    break;
 +
 +  case UV_NAMED_PIPE:
 +    err = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb);
 +    break;
 +
 +  default:
 +    err = UV_EINVAL;
 +  }
 +
 +  if (err == 0)
 +    uv__handle_start(stream);
 +
 +  return err;
 +}
 +
 +
 +static void uv__drain(uv_stream_t* stream) {
 +  uv_shutdown_t* req;
 +  int err;
 +
 +  assert(QUEUE_EMPTY(&stream->write_queue));
 +  uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
 +  uv__stream_osx_interrupt_select(stream);
 +
 +  /* Shutdown? */
 +  if ((stream->flags & UV_HANDLE_SHUTTING) &&
 +      !(stream->flags & UV_HANDLE_CLOSING) &&
 +      !(stream->flags & UV_HANDLE_SHUT)) {
 +    assert(stream->shutdown_req);
 +
 +    req = stream->shutdown_req;
 +    stream->shutdown_req = NULL;
 +    stream->flags &= ~UV_HANDLE_SHUTTING;
 +    uv__req_unregister(stream->loop, req);
 +
 +    err = 0;
 +    if (shutdown(uv__stream_fd(stream), SHUT_WR))
 +      err = UV__ERR(errno);
 +
 +    if (err == 0)
 +      stream->flags |= UV_HANDLE_SHUT;
 +
 +    if (req->cb != NULL)
 +      req->cb(req, err);
 +  }
 +}
 +
 +
 +static ssize_t uv__writev(int fd, struct iovec* vec, size_t n) {
 +  if (n == 1)
 +    return write(fd, vec->iov_base, vec->iov_len);
 +  else
 +    return writev(fd, vec, n);
 +}
 +
 +
 +static size_t uv__write_req_size(uv_write_t* req) {
 +  size_t size;
 +
 +  assert(req->bufs != NULL);
 +  size = uv__count_bufs(req->bufs + req->write_index,
 +                        req->nbufs - req->write_index);
 +  assert(req->handle->write_queue_size >= size);
 +
 +  return size;
 +}
 +
 +
 +/* Returns 1 if all write request data has been written, or 0 if there is still
 + * more data to write.
 + *
 + * Note: the return value only says something about the *current* request.
 + * There may still be other write requests sitting in the queue.
 + */
 +static int uv__write_req_update(uv_stream_t* stream,
 +                                uv_write_t* req,
 +                                size_t n) {
 +  uv_buf_t* buf;
 +  size_t len;
 +
 +  assert(n <= stream->write_queue_size);
 +  stream->write_queue_size -= n;
 +
 +  buf = req->bufs + req->write_index;
 +
-   while (n > 0) {
++  do {
 +    len = n < buf->len ? n : buf->len;
 +    buf->base += len;
 +    buf->len -= len;
 +    buf += (buf->len == 0);  /* Advance to next buffer if this one is empty. */
 +    n -= len;
-   }
++  } while (n > 0);
 +
 +  req->write_index = buf - req->bufs;
 +
 +  return req->write_index == req->nbufs;
 +}
 +
 +
 +static void uv__write_req_finish(uv_write_t* req) {
 +  uv_stream_t* stream = req->handle;
 +
 +  /* Pop the req off tcp->write_queue. */
 +  QUEUE_REMOVE(&req->queue);
 +
 +  /* Only free when there was no error. On error, we touch up write_queue_size
 +   * right before making the callback. The reason we don't do that right away
 +   * is that a write_queue_size > 0 is our only way to signal to the user that
 +   * they should stop writing - which they should if we got an error. Something
 +   * to revisit in future revisions of the libuv API.
 +   */
 +  if (req->error == 0) {
 +    if (req->bufs != req->bufsml)
 +      uv__free(req->bufs);
 +    req->bufs = NULL;
 +  }
 +
 +  /* Add it to the write_completed_queue where it will have its
 +   * callback called in the near future.
 +   */
 +  QUEUE_INSERT_TAIL(&stream->write_completed_queue, &req->queue);
 +  uv__io_feed(stream->loop, &stream->io_watcher);
 +}
 +
 +
 +static int uv__handle_fd(uv_handle_t* handle) {
 +  switch (handle->type) {
 +    case UV_NAMED_PIPE:
 +    case UV_TCP:
 +      return ((uv_stream_t*) handle)->io_watcher.fd;
 +
 +    case UV_UDP:
 +      return ((uv_udp_t*) handle)->io_watcher.fd;
 +
 +    default:
 +      return -1;
 +  }
 +}
 +
 +static void uv__write(uv_stream_t* stream) {
 +  struct iovec* iov;
 +  QUEUE* q;
 +  uv_write_t* req;
 +  int iovmax;
 +  int iovcnt;
 +  ssize_t n;
 +  int err;
 +
 +start:
 +
 +  assert(uv__stream_fd(stream) >= 0);
 +
 +  if (QUEUE_EMPTY(&stream->write_queue))
 +    return;
 +
 +  q = QUEUE_HEAD(&stream->write_queue);
 +  req = QUEUE_DATA(q, uv_write_t, queue);
 +  assert(req->handle == stream);
 +
 +  /*
 +   * Cast to iovec. We had to have our own uv_buf_t instead of iovec
 +   * because Windows's WSABUF is not an iovec.
 +   */
 +  assert(sizeof(uv_buf_t) == sizeof(struct iovec));
 +  iov = (struct iovec*) &(req->bufs[req->write_index]);
 +  iovcnt = req->nbufs - req->write_index;
 +
 +  iovmax = uv__getiovmax();
 +
 +  /* Limit iov count to avoid EINVALs from writev() */
 +  if (iovcnt > iovmax)
 +    iovcnt = iovmax;
 +
 +  /*
 +   * Now do the actual writev. Note that we've been updating the pointers
 +   * inside the iov each time we write. So there is no need to offset it.
 +   */
 +
 +  if (req->send_handle) {
 +    int fd_to_send;
 +    struct msghdr msg;
 +    struct cmsghdr *cmsg;
 +    union {
 +      char data[64];
 +      struct cmsghdr alias;
 +    } scratch;
 +
 +    if (uv__is_closing(req->send_handle)) {
 +      err = UV_EBADF;
 +      goto error;
 +    }
 +
 +    fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle);
 +
 +    memset(&scratch, 0, sizeof(scratch));
 +
 +    assert(fd_to_send >= 0);
 +
 +    msg.msg_name = NULL;
 +    msg.msg_namelen = 0;
 +    msg.msg_iov = iov;
 +    msg.msg_iovlen = iovcnt;
 +    msg.msg_flags = 0;
 +
 +    msg.msg_control = &scratch.alias;
 +    msg.msg_controllen = CMSG_SPACE(sizeof(fd_to_send));
 +
 +    cmsg = CMSG_FIRSTHDR(&msg);
 +    cmsg->cmsg_level = SOL_SOCKET;
 +    cmsg->cmsg_type = SCM_RIGHTS;
 +    cmsg->cmsg_len = CMSG_LEN(sizeof(fd_to_send));
 +
 +    /* silence aliasing warning */
 +    {
 +      void* pv = CMSG_DATA(cmsg);
 +      int* pi = pv;
 +      *pi = fd_to_send;
 +    }
 +
 +    do
 +      n = sendmsg(uv__stream_fd(stream), &msg, 0);
 +    while (n == -1 && RETRY_ON_WRITE_ERROR(errno));
 +
 +    /* Ensure the handle isn't sent again in case this is a partial write. */
 +    if (n >= 0)
 +      req->send_handle = NULL;
 +  } else {
 +    do
 +      n = uv__writev(uv__stream_fd(stream), iov, iovcnt);
 +    while (n == -1 && RETRY_ON_WRITE_ERROR(errno));
 +  }
 +
 +  if (n == -1 && !IS_TRANSIENT_WRITE_ERROR(errno, req->send_handle)) {
 +    err = UV__ERR(errno);
 +    goto error;
 +  }
 +
-   if (n > 0 && uv__write_req_update(stream, req, n)) {
++  if (n >= 0 && uv__write_req_update(stream, req, n)) {
 +    uv__write_req_finish(req);
 +    return;  /* TODO(bnoordhuis) Start trying to write the next request. */
 +  }
 +
 +  /* If this is a blocking stream, try again. */
 +  if (stream->flags & UV_HANDLE_BLOCKING_WRITES)
 +    goto start;
 +
 +  /* We're not done. */
 +  uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
 +
 +  /* Notify select() thread about state change */
 +  uv__stream_osx_interrupt_select(stream);
 +
 +  return;
 +
 +error:
 +  req->error = err;
 +  uv__write_req_finish(req);
 +  uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
 +  if (!uv__io_active(&stream->io_watcher, POLLIN))
 +    uv__handle_stop(stream);
 +  uv__stream_osx_interrupt_select(stream);
 +}
 +
 +
 +static void uv__write_callbacks(uv_stream_t* stream) {
 +  uv_write_t* req;
 +  QUEUE* q;
 +  QUEUE pq;
 +
 +  if (QUEUE_EMPTY(&stream->write_completed_queue))
 +    return;
 +
 +  QUEUE_MOVE(&stream->write_completed_queue, &pq);
 +
 +  while (!QUEUE_EMPTY(&pq)) {
 +    /* Pop a req off write_completed_queue. */
 +    q = QUEUE_HEAD(&pq);
 +    req = QUEUE_DATA(q, uv_write_t, queue);
 +    QUEUE_REMOVE(q);
 +    uv__req_unregister(stream->loop, req);
 +
 +    if (req->bufs != NULL) {
 +      stream->write_queue_size -= uv__write_req_size(req);
 +      if (req->bufs != req->bufsml)
 +        uv__free(req->bufs);
 +      req->bufs = NULL;
 +    }
 +
 +    /* NOTE: call callback AFTER freeing the request data. */
 +    if (req->cb)
 +      req->cb(req, req->error);
 +  }
 +}
 +
 +
 +uv_handle_type uv__handle_type(int fd) {
 +  struct sockaddr_storage ss;
 +  socklen_t sslen;
 +  socklen_t len;
 +  int type;
 +
 +  memset(&ss, 0, sizeof(ss));
 +  sslen = sizeof(ss);
 +
 +  if (getsockname(fd, (struct sockaddr*)&ss, &sslen))
 +    return UV_UNKNOWN_HANDLE;
 +
 +  len = sizeof type;
 +
 +  if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len))
 +    return UV_UNKNOWN_HANDLE;
 +
 +  if (type == SOCK_STREAM) {
 +#if defined(_AIX) || defined(__DragonFly__)
 +    /* on AIX/DragonFly the getsockname call returns an empty sa structure
 +     * for sockets of type AF_UNIX.  For all other types it will
 +     * return a properly filled in structure.
 +     */
 +    if (sslen == 0)
 +      return UV_NAMED_PIPE;
 +#endif
 +    switch (ss.ss_family) {
 +      case AF_UNIX:
 +        return UV_NAMED_PIPE;
 +      case AF_INET:
 +      case AF_INET6:
 +        return UV_TCP;
 +      }
 +  }
 +
 +  if (type == SOCK_DGRAM &&
 +      (ss.ss_family == AF_INET || ss.ss_family == AF_INET6))
 +    return UV_UDP;
 +
 +  return UV_UNKNOWN_HANDLE;
 +}
 +
 +
 +static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
 +  stream->flags |= UV_HANDLE_READ_EOF;
 +  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;
 +}
 +
 +
 +static int uv__stream_queue_fd(uv_stream_t* stream, int fd) {
 +  uv__stream_queued_fds_t* queued_fds;
 +  unsigned int queue_size;
 +
 +  queued_fds = stream->queued_fds;
 +  if (queued_fds == NULL) {
 +    queue_size = 8;
 +    queued_fds = uv__malloc((queue_size - 1) * sizeof(*queued_fds->fds) +
 +                            sizeof(*queued_fds));
 +    if (queued_fds == NULL)
 +      return UV_ENOMEM;
 +    queued_fds->size = queue_size;
 +    queued_fds->offset = 0;
 +    stream->queued_fds = queued_fds;
 +
 +    /* Grow */
 +  } else if (queued_fds->size == queued_fds->offset) {
 +    queue_size = queued_fds->size + 8;
 +    queued_fds = uv__realloc(queued_fds,
 +                             (queue_size - 1) * sizeof(*queued_fds->fds) +
 +                              sizeof(*queued_fds));
 +
 +    /*
 +     * Allocation failure, report back.
 +     * NOTE: if it is fatal - sockets will be closed in uv__stream_close
 +     */
 +    if (queued_fds == NULL)
 +      return UV_ENOMEM;
 +    queued_fds->size = queue_size;
 +    stream->queued_fds = queued_fds;
 +  }
 +
 +  /* Put fd in a queue */
 +  queued_fds->fds[queued_fds->offset++] = fd;
 +
 +  return 0;
 +}
 +
 +
 +#define UV__CMSG_FD_COUNT 64
 +#define UV__CMSG_FD_SIZE (UV__CMSG_FD_COUNT * sizeof(int))
 +
 +
 +static int uv__stream_recv_cmsg(uv_stream_t* stream, struct msghdr* msg) {
 +  struct cmsghdr* cmsg;
 +
 +  for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) {
 +    char* start;
 +    char* end;
 +    int err;
 +    void* pv;
 +    int* pi;
 +    unsigned int i;
 +    unsigned int count;
 +
 +    if (cmsg->cmsg_type != SCM_RIGHTS) {
 +      fprintf(stderr, "ignoring non-SCM_RIGHTS ancillary data: %d\n",
 +          cmsg->cmsg_type);
 +      continue;
 +    }
 +
 +    /* silence aliasing warning */
 +    pv = CMSG_DATA(cmsg);
 +    pi = pv;
 +
 +    /* Count available fds */
 +    start = (char*) cmsg;
 +    end = (char*) cmsg + cmsg->cmsg_len;
 +    count = 0;
 +    while (start + CMSG_LEN(count * sizeof(*pi)) < end)
 +      count++;
 +    assert(start + CMSG_LEN(count * sizeof(*pi)) == end);
 +
 +    for (i = 0; i < count; i++) {
 +      /* Already has accepted fd, queue now */
 +      if (stream->accepted_fd != -1) {
 +        err = uv__stream_queue_fd(stream, pi[i]);
 +        if (err != 0) {
 +          /* Close rest */
 +          for (; i < count; i++)
 +            uv__close(pi[i]);
 +          return err;
 +        }
 +      } else {
 +        stream->accepted_fd = pi[i];
 +      }
 +    }
 +  }
 +
 +  return 0;
 +}
 +
 +
 +#ifdef __clang__
 +# pragma clang diagnostic push
 +# pragma clang diagnostic ignored "-Wgnu-folding-constant"
 +# pragma clang diagnostic ignored "-Wvla-extension"
 +#endif
 +
 +static void uv__read(uv_stream_t* stream) {
 +  uv_buf_t buf;
 +  ssize_t nread;
 +  struct msghdr msg;
 +  char cmsg_space[CMSG_SPACE(UV__CMSG_FD_SIZE)];
 +  int count;
 +  int err;
 +  int is_ipc;
 +
 +  stream->flags &= ~UV_HANDLE_READ_PARTIAL;
 +
 +  /* Prevent loop starvation when the data comes in as fast as (or faster than)
 +   * we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O.
 +   */
 +  count = 32;
 +
 +  is_ipc = stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) stream)->ipc;
 +
 +  /* XXX: Maybe instead of having UV_HANDLE_READING we just test if
 +   * tcp->read_cb is NULL or not?
 +   */
 +  while (stream->read_cb
 +      && (stream->flags & UV_HANDLE_READING)
 +      && (count-- > 0)) {
 +    assert(stream->alloc_cb != NULL);
 +
 +    buf = uv_buf_init(NULL, 0);
 +    stream->alloc_cb((uv_handle_t*)stream, 64 * 1024, &buf);
 +    if (buf.base == NULL || buf.len == 0) {
 +      /* User indicates it can't or won't handle the read. */
 +      stream->read_cb(stream, UV_ENOBUFS, &buf);
 +      return;
 +    }
 +
 +    assert(buf.base != NULL);
 +    assert(uv__stream_fd(stream) >= 0);
 +
 +    if (!is_ipc) {
 +      do {
 +        nread = read(uv__stream_fd(stream), buf.base, buf.len);
 +      }
 +      while (nread < 0 && errno == EINTR);
 +    } else {
 +      /* ipc uses recvmsg */
 +      msg.msg_flags = 0;
 +      msg.msg_iov = (struct iovec*) &buf;
 +      msg.msg_iovlen = 1;
 +      msg.msg_name = NULL;
 +      msg.msg_namelen = 0;
 +      /* Set up to receive a descriptor even if one isn't in the message */
 +      msg.msg_controllen = sizeof(cmsg_space);
 +      msg.msg_control = cmsg_space;
 +
 +      do {
 +        nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0);
 +      }
 +      while (nread < 0 && errno == EINTR);
 +    }
 +
 +    if (nread < 0) {
 +      /* Error */
 +      if (errno == EAGAIN || errno == EWOULDBLOCK) {
 +        /* Wait for the next one. */
 +        if (stream->flags & UV_HANDLE_READING) {
 +          uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
 +          uv__stream_osx_interrupt_select(stream);
 +        }
 +        stream->read_cb(stream, 0, &buf);
 +#if defined(__CYGWIN__) || defined(__MSYS__)
 +      } else if (errno == ECONNRESET && stream->type == UV_NAMED_PIPE) {
 +        uv__stream_eof(stream, &buf);
 +        return;
 +#endif
 +      } else {
 +        /* Error. User should call uv_close(). */
 +        stream->read_cb(stream, UV__ERR(errno), &buf);
 +        if (stream->flags & UV_HANDLE_READING) {
 +          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);
 +        }
 +      }
 +      return;
 +    } else if (nread == 0) {
 +      uv__stream_eof(stream, &buf);
 +      return;
 +    } else {
 +      /* Successful read */
 +      ssize_t buflen = buf.len;
 +
 +      if (is_ipc) {
 +        err = uv__stream_recv_cmsg(stream, &msg);
 +        if (err != 0) {
 +          stream->read_cb(stream, err, &buf);
 +          return;
 +        }
 +      }
 +
 +#if defined(__MVS__)
 +      if (is_ipc && msg.msg_controllen > 0) {
 +        uv_buf_t blankbuf;
 +        int nread;
 +        struct iovec *old;
 +
 +        blankbuf.base = 0;
 +        blankbuf.len = 0;
 +        old = msg.msg_iov;
 +        msg.msg_iov = (struct iovec*) &blankbuf;
 +        nread = 0;
 +        do {
 +          nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0);
 +          err = uv__stream_recv_cmsg(stream, &msg);
 +          if (err != 0) {
 +            stream->read_cb(stream, err, &buf);
 +            msg.msg_iov = old;
 +            return;
 +          }
 +        } while (nread == 0 && msg.msg_controllen > 0);
 +        msg.msg_iov = old;
 +      }
 +#endif
 +      stream->read_cb(stream, nread, &buf);
 +
 +      /* Return if we didn't fill the buffer, there is no more data to read. */
 +      if (nread < buflen) {
 +        stream->flags |= UV_HANDLE_READ_PARTIAL;
 +        return;
 +      }
 +    }
 +  }
 +}
 +
 +
 +#ifdef __clang__
 +# pragma clang diagnostic pop
 +#endif
 +
 +#undef UV__CMSG_FD_COUNT
 +#undef UV__CMSG_FD_SIZE
 +
 +
 +int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
 +  assert(stream->type == UV_TCP ||
 +         stream->type == UV_TTY ||
 +         stream->type == UV_NAMED_PIPE);
 +
 +  if (!(stream->flags & UV_HANDLE_WRITABLE) ||
 +      stream->flags & UV_HANDLE_SHUT ||
 +      stream->flags & UV_HANDLE_SHUTTING ||
 +      uv__is_closing(stream)) {
 +    return UV_ENOTCONN;
 +  }
 +
 +  assert(uv__stream_fd(stream) >= 0);
 +
 +  /* Initialize request */
 +  uv__req_init(stream->loop, req, UV_SHUTDOWN);
 +  req->handle = stream;
 +  req->cb = cb;
 +  stream->shutdown_req = req;
 +  stream->flags |= UV_HANDLE_SHUTTING;
 +
 +  uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
 +  uv__stream_osx_interrupt_select(stream);
 +
 +  return 0;
 +}
 +
 +
 +static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
 +  uv_stream_t* stream;
 +
 +  stream = container_of(w, uv_stream_t, io_watcher);
 +
 +  assert(stream->type == UV_TCP ||
 +         stream->type == UV_NAMED_PIPE ||
 +         stream->type == UV_TTY);
 +  assert(!(stream->flags & UV_HANDLE_CLOSING));
 +
 +  if (stream->connect_req) {
 +    uv__stream_connect(stream);
 +    return;
 +  }
 +
 +  assert(uv__stream_fd(stream) >= 0);
 +
 +  /* Ignore POLLHUP here. Even if it's set, there may still be data to read. */
 +  if (events & (POLLIN | POLLERR | POLLHUP))
 +    uv__read(stream);
 +
 +  if (uv__stream_fd(stream) == -1)
 +    return;  /* read_cb closed stream. */
 +
 +  /* Short-circuit iff POLLHUP is set, the user is still interested in read
 +   * events and uv__read() reported a partial read but not EOF. If the EOF
 +   * flag is set, uv__read() called read_cb with err=UV_EOF and we don't
 +   * have to do anything. If the partial read flag is not set, we can't
 +   * report the EOF yet because there is still data to read.
 +   */
 +  if ((events & POLLHUP) &&
 +      (stream->flags & UV_HANDLE_READING) &&
 +      (stream->flags & UV_HANDLE_READ_PARTIAL) &&
 +      !(stream->flags & UV_HANDLE_READ_EOF)) {
 +    uv_buf_t buf = { NULL, 0 };
 +    uv__stream_eof(stream, &buf);
 +  }
 +
 +  if (uv__stream_fd(stream) == -1)
 +    return;  /* read_cb closed stream. */
 +
 +  if (events & (POLLOUT | POLLERR | POLLHUP)) {
 +    uv__write(stream);
 +    uv__write_callbacks(stream);
 +
 +    /* Write queue drained. */
 +    if (QUEUE_EMPTY(&stream->write_queue))
 +      uv__drain(stream);
 +  }
 +}
 +
 +
 +/**
 + * We get called here from directly following a call to connect(2).
 + * In order to determine if we've errored out or succeeded must call
 + * getsockopt.
 + */
 +static void uv__stream_connect(uv_stream_t* stream) {
 +  int error;
 +  uv_connect_t* req = stream->connect_req;
 +  socklen_t errorsize = sizeof(int);
 +
 +  assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE);
 +  assert(req);
 +
 +  if (stream->delayed_error) {
 +    /* To smooth over the differences between unixes errors that
 +     * were reported synchronously on the first connect can be delayed
 +     * until the next tick--which is now.
 +     */
 +    error = stream->delayed_error;
 +    stream->delayed_error = 0;
 +  } else {
 +    /* Normal situation: we need to get the socket error from the kernel. */
 +    assert(uv__stream_fd(stream) >= 0);
 +    getsockopt(uv__stream_fd(stream),
 +               SOL_SOCKET,
 +               SO_ERROR,
 +               &error,
 +               &errorsize);
 +    error = UV__ERR(error);
 +  }
 +
 +  if (error == UV__ERR(EINPROGRESS))
 +    return;
 +
 +  stream->connect_req = NULL;
 +  uv__req_unregister(stream->loop, req);
 +
 +  if (error < 0 || QUEUE_EMPTY(&stream->write_queue)) {
 +    uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
 +  }
 +
 +  if (req->cb)
 +    req->cb(req, error);
 +
 +  if (uv__stream_fd(stream) == -1)
 +    return;
 +
 +  if (error < 0) {
 +    uv__stream_flush_write_queue(stream, UV_ECANCELED);
 +    uv__write_callbacks(stream);
 +  }
 +}
 +
 +
 +int uv_write2(uv_write_t* req,
 +              uv_stream_t* stream,
 +              const uv_buf_t bufs[],
 +              unsigned int nbufs,
 +              uv_stream_t* send_handle,
 +              uv_write_cb cb) {
 +  int empty_queue;
 +
 +  assert(nbufs > 0);
 +  assert((stream->type == UV_TCP ||
 +          stream->type == UV_NAMED_PIPE ||
 +          stream->type == UV_TTY) &&
 +         "uv_write (unix) does not yet support other types of streams");
 +
 +  if (uv__stream_fd(stream) < 0)
 +    return UV_EBADF;
 +
 +  if (!(stream->flags & UV_HANDLE_WRITABLE))
 +    return -EPIPE;
 +
 +  if (send_handle) {
 +    if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc)
 +      return UV_EINVAL;
 +
 +    /* XXX We abuse uv_write2() to send over UDP handles to child processes.
 +     * Don't call uv__stream_fd() on those handles, it's a macro that on OS X
 +     * evaluates to a function that operates on a uv_stream_t with a couple of
 +     * OS X specific fields. On other Unices it does (handle)->io_watcher.fd,
 +     * which works but only by accident.
 +     */
 +    if (uv__handle_fd((uv_handle_t*) send_handle) < 0)
 +      return UV_EBADF;
 +
 +#if defined(__CYGWIN__) || defined(__MSYS__)
 +    /* Cygwin recvmsg always sets msg_controllen to zero, so we cannot send it.
 +       See https://github.com/mirror/newlib-cygwin/blob/86fc4bf0/winsup/cygwin/fhandler_socket.cc#L1736-L1743 */
 +    return UV_ENOSYS;
 +#endif
 +  }
 +
 +  /* It's legal for write_queue_size > 0 even when the write_queue is empty;
 +   * it means there are error-state requests in the write_completed_queue that
 +   * will touch up write_queue_size later, see also uv__write_req_finish().
 +   * We could check that write_queue is empty instead but that implies making
 +   * a write() syscall when we know that the handle is in error mode.
 +   */
 +  empty_queue = (stream->write_queue_size == 0);
 +
 +  /* Initialize the req */
 +  uv__req_init(stream->loop, req, UV_WRITE);
 +  req->cb = cb;
 +  req->handle = stream;
 +  req->error = 0;
 +  req->send_handle = send_handle;
 +  QUEUE_INIT(&req->queue);
 +
 +  req->bufs = req->bufsml;
 +  if (nbufs > ARRAY_SIZE(req->bufsml))
 +    req->bufs = uv__malloc(nbufs * sizeof(bufs[0]));
 +
 +  if (req->bufs == NULL)
 +    return UV_ENOMEM;
 +
 +  memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
 +  req->nbufs = nbufs;
 +  req->write_index = 0;
 +  stream->write_queue_size += uv__count_bufs(bufs, nbufs);
 +
 +  /* Append the request to write_queue. */
 +  QUEUE_INSERT_TAIL(&stream->write_queue, &req->queue);
 +
 +  /* If the queue was empty when this function began, we should attempt to
 +   * do the write immediately. Otherwise start the write_watcher and wait
 +   * for the fd to become writable.
 +   */
 +  if (stream->connect_req) {
 +    /* Still connecting, do nothing. */
 +  }
 +  else if (empty_queue) {
 +    uv__write(stream);
 +  }
 +  else {
 +    /*
 +     * blocking streams should never have anything in the queue.
 +     * if this assert fires then somehow the blocking stream isn't being
 +     * sufficiently flushed in uv__write.
 +     */
 +    assert(!(stream->flags & UV_HANDLE_BLOCKING_WRITES));
 +    uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
 +    uv__stream_osx_interrupt_select(stream);
 +  }
 +
 +  return 0;
 +}
 +
 +
 +/* The buffers to be written must remain valid until the callback is called.
 + * This is not required for the uv_buf_t array.
 + */
 +int uv_write(uv_write_t* req,
 +             uv_stream_t* handle,
 +             const uv_buf_t bufs[],
 +             unsigned int nbufs,
 +             uv_write_cb cb) {
 +  return uv_write2(req, handle, bufs, nbufs, NULL, cb);
 +}
 +
 +
 +void uv_try_write_cb(uv_write_t* req, int status) {
 +  /* Should not be called */
 +  abort();
 +}
 +
 +
 +int uv_try_write(uv_stream_t* stream,
 +                 const uv_buf_t bufs[],
 +                 unsigned int nbufs) {
 +  int r;
 +  int has_pollout;
 +  size_t written;
 +  size_t req_size;
 +  uv_write_t req;
 +
 +  /* Connecting or already writing some data */
 +  if (stream->connect_req != NULL || stream->write_queue_size != 0)
 +    return UV_EAGAIN;
 +
 +  has_pollout = uv__io_active(&stream->io_watcher, POLLOUT);
 +
 +  r = uv_write(&req, stream, bufs, nbufs, uv_try_write_cb);
 +  if (r != 0)
 +    return r;
 +
 +  /* Remove not written bytes from write queue size */
 +  written = uv__count_bufs(bufs, nbufs);
 +  if (req.bufs != NULL)
 +    req_size = uv__write_req_size(&req);
 +  else
 +    req_size = 0;
 +  written -= req_size;
 +  stream->write_queue_size -= req_size;
 +
 +  /* Unqueue request, regardless of immediateness */
 +  QUEUE_REMOVE(&req.queue);
 +  uv__req_unregister(stream->loop, &req);
 +  if (req.bufs != req.bufsml)
 +    uv__free(req.bufs);
 +  req.bufs = NULL;
 +
 +  /* Do not poll for writable, if we wasn't before calling this */
 +  if (!has_pollout) {
 +    uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
 +    uv__stream_osx_interrupt_select(stream);
 +  }
 +
 +  if (written == 0 && req_size != 0)
-     return UV_EAGAIN;
++    return req.error < 0 ? req.error : UV_EAGAIN;
 +  else
 +    return written;
 +}
 +
 +
 +int uv_read_start(uv_stream_t* stream,
 +                  uv_alloc_cb alloc_cb,
 +                  uv_read_cb read_cb) {
 +  assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE ||
 +      stream->type == UV_TTY);
 +
 +  if (stream->flags & UV_HANDLE_CLOSING)
 +    return UV_EINVAL;
 +
 +  if (!(stream->flags & UV_HANDLE_READABLE))
 +    return -ENOTCONN;
 +
 +  /* The UV_HANDLE_READING flag is irrelevant of the state of the tcp - it just
 +   * expresses the desired state of the user.
 +   */
 +  stream->flags |= UV_HANDLE_READING;
 +
 +  /* TODO: try to do the read inline? */
 +  /* TODO: keep track of tcp state. If we've gotten a EOF then we should
 +   * not start the IO watcher.
 +   */
 +  assert(uv__stream_fd(stream) >= 0);
 +  assert(alloc_cb);
 +
 +  stream->read_cb = read_cb;
 +  stream->alloc_cb = alloc_cb;
 +
 +  uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
 +  uv__handle_start(stream);
 +  uv__stream_osx_interrupt_select(stream);
 +
 +  return 0;
 +}
 +
 +
 +int uv_read_stop(uv_stream_t* stream) {
 +  if (!(stream->flags & UV_HANDLE_READING))
 +    return 0;
 +
 +  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 = NULL;
 +  stream->alloc_cb = NULL;
 +  return 0;
 +}
 +
 +
 +int uv_is_readable(const uv_stream_t* stream) {
 +  return !!(stream->flags & UV_HANDLE_READABLE);
 +}
 +
 +
 +int uv_is_writable(const uv_stream_t* stream) {
 +  return !!(stream->flags & UV_HANDLE_WRITABLE);
 +}
 +
 +
 +#if defined(__APPLE__) && !defined(CMAKE_BOOTSTRAP)
 +int uv___stream_fd(const uv_stream_t* handle) {
 +  const uv__stream_select_t* s;
 +
 +  assert(handle->type == UV_TCP ||
 +         handle->type == UV_TTY ||
 +         handle->type == UV_NAMED_PIPE);
 +
 +  s = handle->select;
 +  if (s != NULL)
 +    return s->fd;
 +
 +  return handle->io_watcher.fd;
 +}
 +#endif /* defined(__APPLE__) */
 +
 +
 +void uv__stream_close(uv_stream_t* handle) {
 +  unsigned int i;
 +  uv__stream_queued_fds_t* queued_fds;
 +
 +#if defined(__APPLE__) && !defined(CMAKE_BOOTSTRAP)
 +  /* Terminate select loop first */
 +  if (handle->select != NULL) {
 +    uv__stream_select_t* s;
 +
 +    s = handle->select;
 +
 +    uv_sem_post(&s->close_sem);
 +    uv_sem_post(&s->async_sem);
 +    uv__stream_osx_interrupt_select(handle);
 +    uv_thread_join(&s->thread);
 +    uv_sem_destroy(&s->close_sem);
 +    uv_sem_destroy(&s->async_sem);
 +    uv__close(s->fake_fd);
 +    uv__close(s->int_fd);
 +    uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close);
 +
 +    handle->select = NULL;
 +  }
 +#endif /* defined(__APPLE__) */
 +
 +  uv__io_close(handle->loop, &handle->io_watcher);
 +  uv_read_stop(handle);
 +  uv__handle_stop(handle);
 +  handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
 +
 +  if (handle->io_watcher.fd != -1) {
 +    /* Don't close stdio file descriptors.  Nothing good comes from it. */
 +    if (handle->io_watcher.fd > STDERR_FILENO)
 +      uv__close(handle->io_watcher.fd);
 +    handle->io_watcher.fd = -1;
 +  }
 +
 +  if (handle->accepted_fd != -1) {
 +    uv__close(handle->accepted_fd);
 +    handle->accepted_fd = -1;
 +  }
 +
 +  /* Close all queued fds */
 +  if (handle->queued_fds != NULL) {
 +    queued_fds = handle->queued_fds;
 +    for (i = 0; i < queued_fds->offset; i++)
 +      uv__close(queued_fds->fds[i]);
 +    uv__free(handle->queued_fds);
 +    handle->queued_fds = NULL;
 +  }
 +
 +  assert(!uv__io_active(&handle->io_watcher, POLLIN | POLLOUT));
 +}
 +
 +
 +int uv_stream_set_blocking(uv_stream_t* handle, int blocking) {
 +  /* Don't need to check the file descriptor, uv__nonblock()
 +   * will fail with EBADF if it's not valid.
 +   */
 +  return uv__nonblock(uv__stream_fd(handle), !blocking);
 +}
diff --cc Utilities/cmlibuv/src/unix/sunos.c
index aac6504,0000000..0cd25c1
mode 100644,000000..100644
--- a/Utilities/cmlibuv/src/unix/sunos.c
+++ b/Utilities/cmlibuv/src/unix/sunos.c
@@@ -1,834 -1,0 +1,850 @@@
 +/* 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 "internal.h"
 +
 +#include <stdio.h>
 +#include <stdint.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <assert.h>
 +#include <errno.h>
 +
 +#if !defined(SUNOS_NO_IFADDRS) && _XOPEN_SOURCE < 600
 +#define SUNOS_NO_IFADDRS
 +#endif
 +
 +#ifndef SUNOS_NO_IFADDRS
 +# include <ifaddrs.h>
 +#endif
 +#include <net/if.h>
 +#include <net/if_dl.h>
 +#include <net/if_arp.h>
 +#include <sys/sockio.h>
 +
 +#include <sys/loadavg.h>
 +#include <sys/time.h>
 +#include <unistd.h>
 +#include <kstat.h>
 +#include <fcntl.h>
 +
 +#include <sys/port.h>
 +#include <port.h>
 +
 +#define PORT_FIRED 0x69
 +#define PORT_UNUSED 0x0
 +#define PORT_LOADED 0x99
 +#define PORT_DELETED -1
 +
 +#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64)
 +#define PROCFS_FILE_OFFSET_BITS_HACK 1
 +#undef _FILE_OFFSET_BITS
 +#else
 +#define PROCFS_FILE_OFFSET_BITS_HACK 0
 +#endif
 +
 +#include <procfs.h>
 +
 +#if (PROCFS_FILE_OFFSET_BITS_HACK - 0 == 1)
 +#define _FILE_OFFSET_BITS 64
 +#endif
 +
 +
 +int uv__platform_loop_init(uv_loop_t* loop) {
 +  int err;
 +  int fd;
 +
 +  loop->fs_fd = -1;
 +  loop->backend_fd = -1;
 +
 +  fd = port_create();
 +  if (fd == -1)
 +    return UV__ERR(errno);
 +
 +  err = uv__cloexec(fd, 1);
 +  if (err) {
 +    uv__close(fd);
 +    return err;
 +  }
 +  loop->backend_fd = fd;
 +
 +  return 0;
 +}
 +
 +
 +void uv__platform_loop_delete(uv_loop_t* loop) {
 +  if (loop->fs_fd != -1) {
 +    uv__close(loop->fs_fd);
 +    loop->fs_fd = -1;
 +  }
 +
 +  if (loop->backend_fd != -1) {
 +    uv__close(loop->backend_fd);
 +    loop->backend_fd = -1;
 +  }
 +}
 +
 +
 +int uv__io_fork(uv_loop_t* loop) {
 +#if defined(PORT_SOURCE_FILE)
 +  if (loop->fs_fd != -1) {
 +    /* stop the watcher before we blow away its fileno */
 +    uv__io_stop(loop, &loop->fs_event_watcher, POLLIN);
 +  }
 +#endif
 +  uv__platform_loop_delete(loop);
 +  return uv__platform_loop_init(loop);
 +}
 +
 +
 +void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
 +  struct port_event* events;
 +  uintptr_t i;
 +  uintptr_t nfds;
 +
 +  assert(loop->watchers != NULL);
++  assert(fd >= 0);
 +
 +  events = (struct port_event*) loop->watchers[loop->nwatchers];
 +  nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
 +  if (events == NULL)
 +    return;
 +
 +  /* Invalidate events with same file descriptor */
 +  for (i = 0; i < nfds; i++)
 +    if ((int) events[i].portev_object == fd)
 +      events[i].portev_object = -1;
 +}
 +
 +
 +int uv__io_check_fd(uv_loop_t* loop, int fd) {
 +  if (port_associate(loop->backend_fd, PORT_SOURCE_FD, fd, POLLIN, 0))
 +    return UV__ERR(errno);
 +
-   if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd))
++  if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd)) {
++    perror("(libuv) port_dissociate()");
 +    abort();
++  }
 +
 +  return 0;
 +}
 +
 +
 +void uv__io_poll(uv_loop_t* loop, int timeout) {
 +  struct port_event events[1024];
 +  struct port_event* pe;
 +  struct timespec spec;
 +  QUEUE* q;
 +  uv__io_t* w;
 +  sigset_t* pset;
 +  sigset_t set;
 +  uint64_t base;
 +  uint64_t diff;
 +  unsigned int nfds;
 +  unsigned int i;
 +  int saved_errno;
 +  int have_signals;
 +  int nevents;
 +  int count;
 +  int err;
 +  int fd;
 +
 +  if (loop->nfds == 0) {
 +    assert(QUEUE_EMPTY(&loop->watcher_queue));
 +    return;
 +  }
 +
 +  while (!QUEUE_EMPTY(&loop->watcher_queue)) {
 +    q = QUEUE_HEAD(&loop->watcher_queue);
 +    QUEUE_REMOVE(q);
 +    QUEUE_INIT(q);
 +
 +    w = QUEUE_DATA(q, uv__io_t, watcher_queue);
 +    assert(w->pevents != 0);
 +
-     if (port_associate(loop->backend_fd, PORT_SOURCE_FD, w->fd, w->pevents, 0))
++    if (port_associate(loop->backend_fd,
++                       PORT_SOURCE_FD,
++                       w->fd,
++                       w->pevents,
++                       0)) {
++      perror("(libuv) port_associate()");
 +      abort();
++    }
 +
 +    w->events = w->pevents;
 +  }
 +
 +  pset = NULL;
 +  if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
 +    pset = &set;
 +    sigemptyset(pset);
 +    sigaddset(pset, SIGPROF);
 +  }
 +
 +  assert(timeout >= -1);
 +  base = loop->time;
 +  count = 48; /* Benchmarks suggest this gives the best throughput. */
 +
 +  for (;;) {
 +    if (timeout != -1) {
 +      spec.tv_sec = timeout / 1000;
 +      spec.tv_nsec = (timeout % 1000) * 1000000;
 +    }
 +
 +    /* Work around a kernel bug where nfds is not updated. */
 +    events[0].portev_source = 0;
 +
 +    nfds = 1;
 +    saved_errno = 0;
 +
 +    if (pset != NULL)
 +      pthread_sigmask(SIG_BLOCK, pset, NULL);
 +
 +    err = port_getn(loop->backend_fd,
 +                    events,
 +                    ARRAY_SIZE(events),
 +                    &nfds,
 +                    timeout == -1 ? NULL : &spec);
 +
 +    if (pset != NULL)
 +      pthread_sigmask(SIG_UNBLOCK, pset, NULL);
 +
 +    if (err) {
 +      /* Work around another kernel bug: port_getn() may return events even
 +       * on error.
 +       */
-       if (errno == EINTR || errno == ETIME)
++      if (errno == EINTR || errno == ETIME) {
 +        saved_errno = errno;
-       else
++      } else {
++        perror("(libuv) port_getn()");
 +        abort();
++      }
 +    }
 +
 +    /* Update loop->time unconditionally. It's tempting to skip the update when
 +     * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
 +     * operating system didn't reschedule our process while in the syscall.
 +     */
 +    SAVE_ERRNO(uv__update_time(loop));
 +
 +    if (events[0].portev_source == 0) {
 +      if (timeout == 0)
 +        return;
 +
 +      if (timeout == -1)
 +        continue;
 +
 +      goto update_timeout;
 +    }
 +
 +    if (nfds == 0) {
 +      assert(timeout != -1);
 +      return;
 +    }
 +
 +    have_signals = 0;
 +    nevents = 0;
 +
 +    assert(loop->watchers != NULL);
 +    loop->watchers[loop->nwatchers] = (void*) events;
 +    loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
 +    for (i = 0; i < nfds; i++) {
 +      pe = events + i;
 +      fd = pe->portev_object;
 +
 +      /* Skip invalidated events, see uv__platform_invalidate_fd */
 +      if (fd == -1)
 +        continue;
 +
 +      assert(fd >= 0);
 +      assert((unsigned) fd < loop->nwatchers);
 +
 +      w = loop->watchers[fd];
 +
 +      /* File descriptor that we've stopped watching, ignore. */
 +      if (w == NULL)
 +        continue;
 +
 +      /* Run signal watchers last.  This also affects child process watchers
 +       * because those are implemented in terms of signal watchers.
 +       */
 +      if (w == &loop->signal_io_watcher)
 +        have_signals = 1;
 +      else
 +        w->cb(loop, w, pe->portev_events);
 +
 +      nevents++;
 +
 +      if (w != loop->watchers[fd])
 +        continue;  /* Disabled by callback. */
 +
 +      /* Events Ports operates in oneshot mode, rearm timer on next run. */
 +      if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue))
 +        QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
 +    }
 +
 +    if (have_signals != 0)
 +      loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
 +
 +    loop->watchers[loop->nwatchers] = NULL;
 +    loop->watchers[loop->nwatchers + 1] = NULL;
 +
 +    if (have_signals != 0)
 +      return;  /* Event loop should cycle now so don't poll again. */
 +
 +    if (nevents != 0) {
 +      if (nfds == ARRAY_SIZE(events) && --count != 0) {
 +        /* Poll for more events but don't block this time. */
 +        timeout = 0;
 +        continue;
 +      }
 +      return;
 +    }
 +
 +    if (saved_errno == ETIME) {
 +      assert(timeout != -1);
 +      return;
 +    }
 +
 +    if (timeout == 0)
 +      return;
 +
 +    if (timeout == -1)
 +      continue;
 +
 +update_timeout:
 +    assert(timeout > 0);
 +
 +    diff = loop->time - base;
 +    if (diff >= (uint64_t) timeout)
 +      return;
 +
 +    timeout -= diff;
 +  }
 +}
 +
 +
 +uint64_t uv__hrtime(uv_clocktype_t type) {
 +  return gethrtime();
 +}
 +
 +
 +/*
 + * We could use a static buffer for the path manipulations that we need outside
 + * of the function, but this function could be called by multiple consumers and
 + * we don't want to potentially create a race condition in the use of snprintf.
 + */
 +int uv_exepath(char* buffer, size_t* size) {
 +  ssize_t res;
 +  char buf[128];
 +
 +  if (buffer == NULL || size == NULL || *size == 0)
 +    return UV_EINVAL;
 +
 +  snprintf(buf, sizeof(buf), "/proc/%lu/path/a.out", (unsigned long) getpid());
 +
 +  res = *size - 1;
 +  if (res > 0)
 +    res = readlink(buf, buffer, res);
 +
 +  if (res == -1)
 +    return UV__ERR(errno);
 +
 +  buffer[res] = '\0';
 +  *size = res;
 +  return 0;
 +}
 +
 +
 +uint64_t uv_get_free_memory(void) {
 +  return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES);
 +}
 +
 +
 +uint64_t uv_get_total_memory(void) {
 +  return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES);
 +}
 +
 +
++uint64_t uv_get_constrained_memory(void) {
++  return 0;  /* Memory constraints are unknown. */
++}
++
++
 +void uv_loadavg(double avg[3]) {
 +  (void) getloadavg(avg, 3);
 +}
 +
 +
 +#if defined(PORT_SOURCE_FILE)
 +
 +static int uv__fs_event_rearm(uv_fs_event_t *handle) {
 +  if (handle->fd == -1)
 +    return UV_EBADF;
 +
 +  if (port_associate(handle->loop->fs_fd,
 +                     PORT_SOURCE_FILE,
 +                     (uintptr_t) &handle->fo,
 +                     FILE_ATTRIB | FILE_MODIFIED,
 +                     handle) == -1) {
 +    return UV__ERR(errno);
 +  }
 +  handle->fd = PORT_LOADED;
 +
 +  return 0;
 +}
 +
 +
 +static void uv__fs_event_read(uv_loop_t* loop,
 +                              uv__io_t* w,
 +                              unsigned int revents) {
 +  uv_fs_event_t *handle = NULL;
 +  timespec_t timeout;
 +  port_event_t pe;
 +  int events;
 +  int r;
 +
 +  (void) w;
 +  (void) revents;
 +
 +  do {
 +    uint_t n = 1;
 +
 +    /*
 +     * Note that our use of port_getn() here (and not port_get()) is deliberate:
 +     * there is a bug in event ports (Sun bug 6456558) whereby a zeroed timeout
 +     * causes port_get() to return success instead of ETIME when there aren't
 +     * actually any events (!); by using port_getn() in lieu of port_get(),
 +     * we can at least workaround the bug by checking for zero returned events
 +     * and treating it as we would ETIME.
 +     */
 +    do {
 +      memset(&timeout, 0, sizeof timeout);
 +      r = port_getn(loop->fs_fd, &pe, 1, &n, &timeout);
 +    }
 +    while (r == -1 && errno == EINTR);
 +
 +    if ((r == -1 && errno == ETIME) || n == 0)
 +      break;
 +
 +    handle = (uv_fs_event_t*) pe.portev_user;
 +    assert((r == 0) && "unexpected port_get() error");
 +
 +    events = 0;
 +    if (pe.portev_events & (FILE_ATTRIB | FILE_MODIFIED))
 +      events |= UV_CHANGE;
 +    if (pe.portev_events & ~(FILE_ATTRIB | FILE_MODIFIED))
 +      events |= UV_RENAME;
 +    assert(events != 0);
 +    handle->fd = PORT_FIRED;
 +    handle->cb(handle, NULL, events, 0);
 +
 +    if (handle->fd != PORT_DELETED) {
 +      r = uv__fs_event_rearm(handle);
 +      if (r != 0)
 +        handle->cb(handle, NULL, 0, r);
 +    }
 +  }
 +  while (handle->fd != PORT_DELETED);
 +}
 +
 +
 +int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
 +  uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
 +  return 0;
 +}
 +
 +
 +int uv_fs_event_start(uv_fs_event_t* handle,
 +                      uv_fs_event_cb cb,
 +                      const char* path,
 +                      unsigned int flags) {
 +  int portfd;
 +  int first_run;
 +  int err;
 +
 +  if (uv__is_active(handle))
 +    return UV_EINVAL;
 +
 +  first_run = 0;
 +  if (handle->loop->fs_fd == -1) {
 +    portfd = port_create();
 +    if (portfd == -1)
 +      return UV__ERR(errno);
 +    handle->loop->fs_fd = portfd;
 +    first_run = 1;
 +  }
 +
 +  uv__handle_start(handle);
 +  handle->path = uv__strdup(path);
 +  handle->fd = PORT_UNUSED;
 +  handle->cb = cb;
 +
 +  memset(&handle->fo, 0, sizeof handle->fo);
 +  handle->fo.fo_name = handle->path;
 +  err = uv__fs_event_rearm(handle);
 +  if (err != 0) {
 +    uv_fs_event_stop(handle);
 +    return err;
 +  }
 +
 +  if (first_run) {
 +    uv__io_init(&handle->loop->fs_event_watcher, uv__fs_event_read, portfd);
 +    uv__io_start(handle->loop, &handle->loop->fs_event_watcher, POLLIN);
 +  }
 +
 +  return 0;
 +}
 +
 +
 +int uv_fs_event_stop(uv_fs_event_t* handle) {
 +  if (!uv__is_active(handle))
 +    return 0;
 +
 +  if (handle->fd == PORT_FIRED || handle->fd == PORT_LOADED) {
 +    port_dissociate(handle->loop->fs_fd,
 +                    PORT_SOURCE_FILE,
 +                    (uintptr_t) &handle->fo);
 +  }
 +
 +  handle->fd = PORT_DELETED;
 +  uv__free(handle->path);
 +  handle->path = NULL;
 +  handle->fo.fo_name = NULL;
 +  uv__handle_stop(handle);
 +
 +  return 0;
 +}
 +
 +void uv__fs_event_close(uv_fs_event_t* handle) {
 +  uv_fs_event_stop(handle);
 +}
 +
 +#else /* !defined(PORT_SOURCE_FILE) */
 +
 +int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
 +  return UV_ENOSYS;
 +}
 +
 +
 +int uv_fs_event_start(uv_fs_event_t* handle,
 +                      uv_fs_event_cb cb,
 +                      const char* filename,
 +                      unsigned int flags) {
 +  return UV_ENOSYS;
 +}
 +
 +
 +int uv_fs_event_stop(uv_fs_event_t* handle) {
 +  return UV_ENOSYS;
 +}
 +
 +
 +void uv__fs_event_close(uv_fs_event_t* handle) {
 +  UNREACHABLE();
 +}
 +
 +#endif /* defined(PORT_SOURCE_FILE) */
 +
 +
 +int uv_resident_set_memory(size_t* rss) {
 +  psinfo_t psinfo;
 +  int err;
 +  int fd;
 +
 +  fd = open("/proc/self/psinfo", O_RDONLY);
 +  if (fd == -1)
 +    return UV__ERR(errno);
 +
 +  /* FIXME(bnoordhuis) Handle EINTR. */
 +  err = UV_EINVAL;
 +  if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) {
 +    *rss = (size_t)psinfo.pr_rssize * 1024;
 +    err = 0;
 +  }
 +  uv__close(fd);
 +
 +  return err;
 +}
 +
 +
 +int uv_uptime(double* uptime) {
 +  kstat_ctl_t   *kc;
 +  kstat_t       *ksp;
 +  kstat_named_t *knp;
 +
 +  long hz = sysconf(_SC_CLK_TCK);
 +
 +  kc = kstat_open();
 +  if (kc == NULL)
 +    return UV_EPERM;
 +
 +  ksp = kstat_lookup(kc, (char*) "unix", 0, (char*) "system_misc");
 +  if (kstat_read(kc, ksp, NULL) == -1) {
 +    *uptime = -1;
 +  } else {
 +    knp = (kstat_named_t*)  kstat_data_lookup(ksp, (char*) "clk_intr");
 +    *uptime = knp->value.ul / hz;
 +  }
 +  kstat_close(kc);
 +
 +  return 0;
 +}
 +
 +
 +int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
 +  int           lookup_instance;
 +  kstat_ctl_t   *kc;
 +  kstat_t       *ksp;
 +  kstat_named_t *knp;
 +  uv_cpu_info_t* cpu_info;
 +
 +  kc = kstat_open();
 +  if (kc == NULL)
 +    return UV_EPERM;
 +
 +  /* Get count of cpus */
 +  lookup_instance = 0;
 +  while ((ksp = kstat_lookup(kc, (char*) "cpu_info", lookup_instance, NULL))) {
 +    lookup_instance++;
 +  }
 +
 +  *cpu_infos = uv__malloc(lookup_instance * sizeof(**cpu_infos));
 +  if (!(*cpu_infos)) {
 +    kstat_close(kc);
 +    return UV_ENOMEM;
 +  }
 +
 +  *count = lookup_instance;
 +
 +  cpu_info = *cpu_infos;
 +  lookup_instance = 0;
 +  while ((ksp = kstat_lookup(kc, (char*) "cpu_info", lookup_instance, NULL))) {
 +    if (kstat_read(kc, ksp, NULL) == -1) {
 +      cpu_info->speed = 0;
 +      cpu_info->model = NULL;
 +    } else {
 +      knp = kstat_data_lookup(ksp, (char*) "clock_MHz");
 +      assert(knp->data_type == KSTAT_DATA_INT32 ||
 +             knp->data_type == KSTAT_DATA_INT64);
 +      cpu_info->speed = (knp->data_type == KSTAT_DATA_INT32) ? knp->value.i32
 +                                                             : knp->value.i64;
 +
 +      knp = kstat_data_lookup(ksp, (char*) "brand");
 +      assert(knp->data_type == KSTAT_DATA_STRING);
 +      cpu_info->model = uv__strdup(KSTAT_NAMED_STR_PTR(knp));
 +    }
 +
 +    lookup_instance++;
 +    cpu_info++;
 +  }
 +
 +  cpu_info = *cpu_infos;
 +  lookup_instance = 0;
 +  for (;;) {
 +    ksp = kstat_lookup(kc, (char*) "cpu", lookup_instance, (char*) "sys");
 +
 +    if (ksp == NULL)
 +      break;
 +
 +    if (kstat_read(kc, ksp, NULL) == -1) {
 +      cpu_info->cpu_times.user = 0;
 +      cpu_info->cpu_times.nice = 0;
 +      cpu_info->cpu_times.sys = 0;
 +      cpu_info->cpu_times.idle = 0;
 +      cpu_info->cpu_times.irq = 0;
 +    } else {
 +      knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_user");
 +      assert(knp->data_type == KSTAT_DATA_UINT64);
 +      cpu_info->cpu_times.user = knp->value.ui64;
 +
 +      knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_kernel");
 +      assert(knp->data_type == KSTAT_DATA_UINT64);
 +      cpu_info->cpu_times.sys = knp->value.ui64;
 +
 +      knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_idle");
 +      assert(knp->data_type == KSTAT_DATA_UINT64);
 +      cpu_info->cpu_times.idle = knp->value.ui64;
 +
 +      knp = kstat_data_lookup(ksp, (char*) "intr");
 +      assert(knp->data_type == KSTAT_DATA_UINT64);
 +      cpu_info->cpu_times.irq = knp->value.ui64;
 +      cpu_info->cpu_times.nice = 0;
 +    }
 +
 +    lookup_instance++;
 +    cpu_info++;
 +  }
 +
 +  kstat_close(kc);
 +
 +  return 0;
 +}
 +
 +
 +void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
 +  int i;
 +
 +  for (i = 0; i < count; i++) {
 +    uv__free(cpu_infos[i].model);
 +  }
 +
 +  uv__free(cpu_infos);
 +}
 +
 +#ifdef SUNOS_NO_IFADDRS
 +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
 +  *count = 0;
 +  *addresses = NULL;
 +  return UV_ENOSYS;
 +}
 +#else  /* SUNOS_NO_IFADDRS */
 +/*
 + * Inspired By:
 + * https://blogs.oracle.com/paulie/entry/retrieving_mac_address_in_solaris
 + * http://www.pauliesworld.org/project/getmac.c
 + */
 +static int uv__set_phys_addr(uv_interface_address_t* address,
 +                             struct ifaddrs* ent) {
 +
 +  struct sockaddr_dl* sa_addr;
 +  int sockfd;
 +  size_t i;
 +  struct arpreq arpreq;
 +
 +  /* This appears to only work as root */
 +  sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
 +  memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
 +  for (i = 0; i < sizeof(address->phys_addr); i++) {
 +    /* Check that all bytes of phys_addr are zero. */
 +    if (address->phys_addr[i] != 0)
 +      return 0;
 +  }
 +  memset(&arpreq, 0, sizeof(arpreq));
 +  if (address->address.address4.sin_family == AF_INET) {
 +    struct sockaddr_in* sin = ((struct sockaddr_in*)&arpreq.arp_pa);
 +    sin->sin_addr.s_addr = address->address.address4.sin_addr.s_addr;
 +  } else if (address->address.address4.sin_family == AF_INET6) {
 +    struct sockaddr_in6* sin = ((struct sockaddr_in6*)&arpreq.arp_pa);
 +    memcpy(sin->sin6_addr.s6_addr,
 +           address->address.address6.sin6_addr.s6_addr,
 +           sizeof(address->address.address6.sin6_addr.s6_addr));
 +  } else {
 +    return 0;
 +  }
 +
 +  sockfd = socket(AF_INET, SOCK_DGRAM, 0);
 +  if (sockfd < 0)
 +    return UV__ERR(errno);
 +
 +  if (ioctl(sockfd, SIOCGARP, (char*)&arpreq) == -1) {
 +    uv__close(sockfd);
 +    return UV__ERR(errno);
 +  }
 +  memcpy(address->phys_addr, arpreq.arp_ha.sa_data, sizeof(address->phys_addr));
 +  uv__close(sockfd);
 +  return 0;
 +}
 +
 +
 +static int uv__ifaddr_exclude(struct ifaddrs *ent) {
 +  if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
 +    return 1;
 +  if (ent->ifa_addr == NULL)
 +    return 1;
 +  if (ent->ifa_addr->sa_family != AF_INET &&
 +      ent->ifa_addr->sa_family != AF_INET6)
 +    return 1;
 +  return 0;
 +}
 +
 +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
 +  uv_interface_address_t* address;
 +  struct ifaddrs* addrs;
 +  struct ifaddrs* ent;
 +
 +  *count = 0;
 +  *addresses = NULL;
 +
 +  if (getifaddrs(&addrs))
 +    return UV__ERR(errno);
 +
 +  /* Count the number of interfaces */
 +  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
 +    if (uv__ifaddr_exclude(ent))
 +      continue;
 +    (*count)++;
 +  }
 +
 +  if (*count == 0) {
 +    freeifaddrs(addrs);
 +    return 0;
 +  }
 +
 +  *addresses = uv__malloc(*count * sizeof(**addresses));
 +  if (!(*addresses)) {
 +    freeifaddrs(addrs);
 +    return UV_ENOMEM;
 +  }
 +
 +  address = *addresses;
 +
 +  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
 +    if (uv__ifaddr_exclude(ent))
 +      continue;
 +
 +    address->name = uv__strdup(ent->ifa_name);
 +
 +    if (ent->ifa_addr->sa_family == AF_INET6) {
 +      address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
 +    } else {
 +      address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
 +    }
 +
 +    if (ent->ifa_netmask->sa_family == AF_INET6) {
 +      address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
 +    } else {
 +      address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
 +    }
 +
 +    address->is_internal = !!((ent->ifa_flags & IFF_PRIVATE) ||
 +                           (ent->ifa_flags & IFF_LOOPBACK));
 +
 +    uv__set_phys_addr(address, ent);
 +    address++;
 +  }
 +
 +  freeifaddrs(addrs);
 +
 +  return 0;
 +}
 +#endif  /* SUNOS_NO_IFADDRS */
 +
 +void uv_free_interface_addresses(uv_interface_address_t* addresses,
 +  int count) {
 +  int i;
 +
 +  for (i = 0; i < count; i++) {
 +    uv__free(addresses[i].name);
 +  }
 +
 +  uv__free(addresses);
 +}
diff --cc Utilities/cmlibuv/src/uv-common.c
index 907ebf2,0000000..f4853d6
mode 100644,000000..100644
--- a/Utilities/cmlibuv/src/uv-common.c
+++ b/Utilities/cmlibuv/src/uv-common.c
@@@ -1,696 -1,0 +1,790 @@@
 +/* 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 "uv-common.h"
 +
 +#include <assert.h>
 +#include <errno.h>
 +#include <stdarg.h>
 +#include <stddef.h> /* NULL */
 +#include <stdio.h>
 +#include <stdlib.h> /* malloc */
 +#include <string.h> /* memset */
 +
 +#if defined(_WIN32)
 +# include <malloc.h> /* malloc */
 +#else
 +# include <net/if.h> /* if_nametoindex */
++# include <sys/un.h> /* AF_UNIX, sockaddr_un */
 +#endif
 +
 +
 +typedef struct {
 +  uv_malloc_func local_malloc;
 +  uv_realloc_func local_realloc;
 +  uv_calloc_func local_calloc;
 +  uv_free_func local_free;
 +} uv__allocator_t;
 +
 +static uv__allocator_t uv__allocator = {
 +  malloc,
 +  realloc,
 +  calloc,
 +  free,
 +};
 +
 +char* uv__strdup(const char* s) {
 +  size_t len = strlen(s) + 1;
 +  char* m = uv__malloc(len);
 +  if (m == NULL)
 +    return NULL;
 +  return memcpy(m, s, len);
 +}
 +
 +char* uv__strndup(const char* s, size_t n) {
 +  char* m;
 +  size_t len = strlen(s);
 +  if (n < len)
 +    len = n;
 +  m = uv__malloc(len + 1);
 +  if (m == NULL)
 +    return NULL;
 +  m[len] = '\0';
 +  return memcpy(m, s, len);
 +}
 +
 +void* uv__malloc(size_t size) {
 +  if (size > 0)
 +    return uv__allocator.local_malloc(size);
 +  return NULL;
 +}
 +
 +void uv__free(void* ptr) {
 +  int saved_errno;
 +
 +  /* Libuv expects that free() does not clobber errno.  The system allocator
 +   * honors that assumption but custom allocators may not be so careful.
 +   */
 +  saved_errno = errno;
 +  uv__allocator.local_free(ptr);
 +  errno = saved_errno;
 +}
 +
 +void* uv__calloc(size_t count, size_t size) {
 +  return uv__allocator.local_calloc(count, size);
 +}
 +
 +void* uv__realloc(void* ptr, size_t size) {
 +  if (size > 0)
 +    return uv__allocator.local_realloc(ptr, size);
 +  uv__free(ptr);
 +  return NULL;
 +}
 +
 +int uv_replace_allocator(uv_malloc_func malloc_func,
 +                         uv_realloc_func realloc_func,
 +                         uv_calloc_func calloc_func,
 +                         uv_free_func free_func) {
 +  if (malloc_func == NULL || realloc_func == NULL ||
 +      calloc_func == NULL || free_func == NULL) {
 +    return UV_EINVAL;
 +  }
 +
 +  uv__allocator.local_malloc = malloc_func;
 +  uv__allocator.local_realloc = realloc_func;
 +  uv__allocator.local_calloc = calloc_func;
 +  uv__allocator.local_free = free_func;
 +
 +  return 0;
 +}
 +
 +#define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t);
 +
 +size_t uv_handle_size(uv_handle_type type) {
 +  switch (type) {
 +    UV_HANDLE_TYPE_MAP(XX)
 +    default:
 +      return -1;
 +  }
 +}
 +
 +size_t uv_req_size(uv_req_type type) {
 +  switch(type) {
 +    UV_REQ_TYPE_MAP(XX)
 +    default:
 +      return -1;
 +  }
 +}
 +
 +#undef XX
 +
 +
 +size_t uv_loop_size(void) {
 +  return sizeof(uv_loop_t);
 +}
 +
 +
 +uv_buf_t uv_buf_init(char* base, unsigned int len) {
 +  uv_buf_t buf;
 +  buf.base = base;
 +  buf.len = len;
 +  return buf;
 +}
 +
 +
 +static const char* uv__unknown_err_code(int err) {
 +  char buf[32];
 +  char* copy;
 +
 +  snprintf(buf, sizeof(buf), "Unknown system error %d", err);
 +  copy = uv__strdup(buf);
 +
 +  return copy != NULL ? copy : "Unknown system error";
 +}
 +
 +#define UV_ERR_NAME_GEN_R(name, _) \
 +case UV_## name: \
 +  uv__strscpy(buf, #name, buflen); break;
 +char* uv_err_name_r(int err, char* buf, size_t buflen) {
 +  switch (err) {
 +    UV_ERRNO_MAP(UV_ERR_NAME_GEN_R)
 +    default: snprintf(buf, buflen, "Unknown system error %d", err);
 +  }
 +  return buf;
 +}
 +#undef UV_ERR_NAME_GEN_R
 +
 +
 +#define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name;
 +const char* uv_err_name(int err) {
 +  switch (err) {
 +    UV_ERRNO_MAP(UV_ERR_NAME_GEN)
 +  }
 +  return uv__unknown_err_code(err);
 +}
 +#undef UV_ERR_NAME_GEN
 +
 +
 +#define UV_STRERROR_GEN_R(name, msg) \
 +case UV_ ## name: \
 +  snprintf(buf, buflen, "%s", msg); break;
 +char* uv_strerror_r(int err, char* buf, size_t buflen) {
 +  switch (err) {
 +    UV_ERRNO_MAP(UV_STRERROR_GEN_R)
 +    default: snprintf(buf, buflen, "Unknown system error %d", err);
 +  }
 +  return buf;
 +}
 +#undef UV_STRERROR_GEN_R
 +
 +
 +#define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg;
 +const char* uv_strerror(int err) {
 +  switch (err) {
 +    UV_ERRNO_MAP(UV_STRERROR_GEN)
 +  }
 +  return uv__unknown_err_code(err);
 +}
 +#undef UV_STRERROR_GEN
 +
 +#if !defined(CMAKE_BOOTSTRAP) || defined(_WIN32)
 +
 +int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) {
 +  memset(addr, 0, sizeof(*addr));
 +  addr->sin_family = AF_INET;
 +  addr->sin_port = htons(port);
 +  return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr));
 +}
 +
 +
 +int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) {
 +  char address_part[40];
 +  size_t address_part_size;
 +  const char* zone_index;
 +
 +  memset(addr, 0, sizeof(*addr));
 +  addr->sin6_family = AF_INET6;
 +  addr->sin6_port = htons(port);
++#ifdef SIN6_LEN
++  addr->sin6_len = sizeof(*addr);
++#endif
 +
 +  zone_index = strchr(ip, '%');
 +  if (zone_index != NULL) {
 +    address_part_size = zone_index - ip;
 +    if (address_part_size >= sizeof(address_part))
 +      address_part_size = sizeof(address_part) - 1;
 +
 +    memcpy(address_part, ip, address_part_size);
 +    address_part[address_part_size] = '\0';
 +    ip = address_part;
 +
 +    zone_index++; /* skip '%' */
 +    /* NOTE: unknown interface (id=0) is silently ignored */
 +#ifdef _WIN32
 +    addr->sin6_scope_id = atoi(zone_index);
 +#else
 +    addr->sin6_scope_id = if_nametoindex(zone_index);
 +#endif
 +  }
 +
 +  return uv_inet_pton(AF_INET6, ip, &addr->sin6_addr);
 +}
 +
 +
 +int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) {
 +  return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size);
 +}
 +
 +
 +int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) {
 +  return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size);
 +}
 +
 +
 +int uv_tcp_bind(uv_tcp_t* handle,
 +                const struct sockaddr* addr,
 +                unsigned int flags) {
 +  unsigned int addrlen;
 +
 +  if (handle->type != UV_TCP)
 +    return UV_EINVAL;
 +
 +  if (addr->sa_family == AF_INET)
 +    addrlen = sizeof(struct sockaddr_in);
 +  else if (addr->sa_family == AF_INET6)
 +    addrlen = sizeof(struct sockaddr_in6);
 +  else
 +    return UV_EINVAL;
 +
 +  return uv__tcp_bind(handle, addr, addrlen, flags);
 +}
 +
 +
 +int uv_udp_bind(uv_udp_t* handle,
 +                const struct sockaddr* addr,
 +                unsigned int flags) {
 +  unsigned int addrlen;
 +
 +  if (handle->type != UV_UDP)
 +    return UV_EINVAL;
 +
 +  if (addr->sa_family == AF_INET)
 +    addrlen = sizeof(struct sockaddr_in);
 +  else if (addr->sa_family == AF_INET6)
 +    addrlen = sizeof(struct sockaddr_in6);
 +  else
 +    return UV_EINVAL;
 +
 +  return uv__udp_bind(handle, addr, addrlen, flags);
 +}
 +
 +
 +int uv_tcp_connect(uv_connect_t* req,
 +                   uv_tcp_t* handle,
 +                   const struct sockaddr* addr,
 +                   uv_connect_cb cb) {
 +  unsigned int addrlen;
 +
 +  if (handle->type != UV_TCP)
 +    return UV_EINVAL;
 +
 +  if (addr->sa_family == AF_INET)
 +    addrlen = sizeof(struct sockaddr_in);
 +  else if (addr->sa_family == AF_INET6)
 +    addrlen = sizeof(struct sockaddr_in6);
 +  else
 +    return UV_EINVAL;
 +
 +  return uv__tcp_connect(req, handle, addr, addrlen, cb);
 +}
 +
 +
- int uv_udp_send(uv_udp_send_t* req,
-                 uv_udp_t* handle,
-                 const uv_buf_t bufs[],
-                 unsigned int nbufs,
-                 const struct sockaddr* addr,
-                 uv_udp_send_cb send_cb) {
++int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr) {
 +  unsigned int addrlen;
 +
 +  if (handle->type != UV_UDP)
 +    return UV_EINVAL;
 +
++  /* Disconnect the handle */
++  if (addr == NULL) {
++    if (!(handle->flags & UV_HANDLE_UDP_CONNECTED))
++      return UV_ENOTCONN;
++
++    return uv__udp_disconnect(handle);
++  }
++
 +  if (addr->sa_family == AF_INET)
 +    addrlen = sizeof(struct sockaddr_in);
 +  else if (addr->sa_family == AF_INET6)
 +    addrlen = sizeof(struct sockaddr_in6);
 +  else
 +    return UV_EINVAL;
 +
++  if (handle->flags & UV_HANDLE_UDP_CONNECTED)
++    return UV_EISCONN;
++
++  return uv__udp_connect(handle, addr, addrlen);
++}
++
++
++int uv__udp_is_connected(uv_udp_t* handle) {
++  struct sockaddr_storage addr;
++  int addrlen;
++  if (handle->type != UV_UDP)
++    return 0;
++
++  addrlen = sizeof(addr);
++  if (uv_udp_getpeername(handle, (struct sockaddr*) &addr, &addrlen) != 0)
++    return 0;
++
++  return addrlen > 0;
++}
++
++
++int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) {
++  unsigned int addrlen;
++
++  if (handle->type != UV_UDP)
++    return UV_EINVAL;
++
++  if (addr != NULL && (handle->flags & UV_HANDLE_UDP_CONNECTED))
++    return UV_EISCONN;
++
++  if (addr == NULL && !(handle->flags & UV_HANDLE_UDP_CONNECTED))
++    return UV_EDESTADDRREQ;
++
++  if (addr != NULL) {
++    if (addr->sa_family == AF_INET)
++      addrlen = sizeof(struct sockaddr_in);
++    else if (addr->sa_family == AF_INET6)
++      addrlen = sizeof(struct sockaddr_in6);
++#if defined(AF_UNIX) && !defined(_WIN32)
++    else if (addr->sa_family == AF_UNIX)
++      addrlen = sizeof(struct sockaddr_un);
++#endif
++    else
++      return UV_EINVAL;
++  } else {
++    addrlen = 0;
++  }
++
++  return addrlen;
++}
++
++
++int uv_udp_send(uv_udp_send_t* req,
++                uv_udp_t* handle,
++                const uv_buf_t bufs[],
++                unsigned int nbufs,
++                const struct sockaddr* addr,
++                uv_udp_send_cb send_cb) {
++  int addrlen;
++
++  addrlen = uv__udp_check_before_send(handle, addr);
++  if (addrlen < 0)
++    return addrlen;
++
 +  return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
 +}
 +
 +
 +int uv_udp_try_send(uv_udp_t* handle,
 +                    const uv_buf_t bufs[],
 +                    unsigned int nbufs,
 +                    const struct sockaddr* addr) {
-   unsigned int addrlen;
- 
-   if (handle->type != UV_UDP)
-     return UV_EINVAL;
++  int addrlen;
 +
-   if (addr->sa_family == AF_INET)
-     addrlen = sizeof(struct sockaddr_in);
-   else if (addr->sa_family == AF_INET6)
-     addrlen = sizeof(struct sockaddr_in6);
-   else
-     return UV_EINVAL;
++  addrlen = uv__udp_check_before_send(handle, addr);
++  if (addrlen < 0)
++    return addrlen;
 +
 +  return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen);
 +}
 +
 +
 +int uv_udp_recv_start(uv_udp_t* handle,
 +                      uv_alloc_cb alloc_cb,
 +                      uv_udp_recv_cb recv_cb) {
 +  if (handle->type != UV_UDP || alloc_cb == NULL || recv_cb == NULL)
 +    return UV_EINVAL;
 +  else
 +    return uv__udp_recv_start(handle, alloc_cb, recv_cb);
 +}
 +
 +
 +int uv_udp_recv_stop(uv_udp_t* handle) {
 +  if (handle->type != UV_UDP)
 +    return UV_EINVAL;
 +  else
 +    return uv__udp_recv_stop(handle);
 +}
 +
 +#endif
 +
 +void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
 +  QUEUE queue;
 +  QUEUE* q;
 +  uv_handle_t* h;
 +
 +  QUEUE_MOVE(&loop->handle_queue, &queue);
 +  while (!QUEUE_EMPTY(&queue)) {
 +    q = QUEUE_HEAD(&queue);
 +    h = QUEUE_DATA(q, uv_handle_t, handle_queue);
 +
 +    QUEUE_REMOVE(q);
 +    QUEUE_INSERT_TAIL(&loop->handle_queue, q);
 +
 +    if (h->flags & UV_HANDLE_INTERNAL) continue;
 +    walk_cb(h, arg);
 +  }
 +}
 +
 +
 +static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {
 +  const char* type;
 +  QUEUE* q;
 +  uv_handle_t* h;
 +
 +  if (loop == NULL)
 +    loop = uv_default_loop();
 +
 +  QUEUE_FOREACH(q, &loop->handle_queue) {
 +    h = QUEUE_DATA(q, uv_handle_t, handle_queue);
 +
 +    if (only_active && !uv__is_active(h))
 +      continue;
 +
 +    switch (h->type) {
 +#define X(uc, lc) case UV_##uc: type = #lc; break;
 +      UV_HANDLE_TYPE_MAP(X)
 +#undef X
 +      default: type = "<unknown>";
 +    }
 +
 +    fprintf(stream,
 +            "[%c%c%c] %-8s %p\n",
 +            "R-"[!(h->flags & UV_HANDLE_REF)],
 +            "A-"[!(h->flags & UV_HANDLE_ACTIVE)],
 +            "I-"[!(h->flags & UV_HANDLE_INTERNAL)],
 +            type,
 +            (void*)h);
 +  }
 +}
 +
 +
 +void uv_print_all_handles(uv_loop_t* loop, FILE* stream) {
 +  uv__print_handles(loop, 0, stream);
 +}
 +
 +
 +void uv_print_active_handles(uv_loop_t* loop, FILE* stream) {
 +  uv__print_handles(loop, 1, stream);
 +}
 +
 +
 +void uv_ref(uv_handle_t* handle) {
 +  uv__handle_ref(handle);
 +}
 +
 +
 +void uv_unref(uv_handle_t* handle) {
 +  uv__handle_unref(handle);
 +}
 +
 +
 +int uv_has_ref(const uv_handle_t* handle) {
 +  return uv__has_ref(handle);
 +}
 +
 +
 +void uv_stop(uv_loop_t* loop) {
 +  loop->stop_flag = 1;
 +}
 +
 +
 +uint64_t uv_now(const uv_loop_t* loop) {
 +  return loop->time;
 +}
 +
 +
 +
 +size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs) {
 +  unsigned int i;
 +  size_t bytes;
 +
 +  bytes = 0;
 +  for (i = 0; i < nbufs; i++)
 +    bytes += (size_t) bufs[i].len;
 +
 +  return bytes;
 +}
 +
 +int uv_recv_buffer_size(uv_handle_t* handle, int* value) {
 +  return uv__socket_sockopt(handle, SO_RCVBUF, value);
 +}
 +
 +int uv_send_buffer_size(uv_handle_t* handle, int *value) {
 +  return uv__socket_sockopt(handle, SO_SNDBUF, value);
 +}
 +
 +int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) {
 +  size_t required_len;
 +
 +  if (!uv__is_active(handle)) {
 +    *size = 0;
 +    return UV_EINVAL;
 +  }
 +
 +  required_len = strlen(handle->path);
 +  if (required_len >= *size) {
 +    *size = required_len + 1;
 +    return UV_ENOBUFS;
 +  }
 +
 +  memcpy(buffer, handle->path, required_len);
 +  *size = required_len;
 +  buffer[required_len] = '\0';
 +
 +  return 0;
 +}
 +
 +/* The windows implementation does not have the same structure layout as
 + * the unix implementation (nbufs is not directly inside req but is
 + * contained in a nested union/struct) so this function locates it.
 +*/
 +static unsigned int* uv__get_nbufs(uv_fs_t* req) {
 +#ifdef _WIN32
 +  return &req->fs.info.nbufs;
 +#else
 +  return &req->nbufs;
 +#endif
 +}
 +
 +/* uv_fs_scandir() uses the system allocator to allocate memory on non-Windows
 + * systems. So, the memory should be released using free(). On Windows,
 + * uv__malloc() is used, so use uv__free() to free memory.
 +*/
 +#ifdef _WIN32
 +# define uv__fs_scandir_free uv__free
 +#else
 +# define uv__fs_scandir_free free
 +#endif
 +
 +void uv__fs_scandir_cleanup(uv_fs_t* req) {
 +  uv__dirent_t** dents;
 +
 +  unsigned int* nbufs = uv__get_nbufs(req);
 +
 +  dents = req->ptr;
 +  if (*nbufs > 0 && *nbufs != (unsigned int) req->result)
 +    (*nbufs)--;
 +  for (; *nbufs < (unsigned int) req->result; (*nbufs)++)
 +    uv__fs_scandir_free(dents[*nbufs]);
 +
 +  uv__fs_scandir_free(req->ptr);
 +  req->ptr = NULL;
 +}
 +
 +
 +int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
 +  uv__dirent_t** dents;
 +  uv__dirent_t* dent;
 +  unsigned int* nbufs;
 +
 +  /* Check to see if req passed */
 +  if (req->result < 0)
 +    return req->result;
 +
 +  /* Ptr will be null if req was canceled or no files found */
 +  if (!req->ptr)
 +    return UV_EOF;
 +
 +  nbufs = uv__get_nbufs(req);
 +  assert(nbufs);
 +
 +  dents = req->ptr;
 +
 +  /* Free previous entity */
 +  if (*nbufs > 0)
 +    uv__fs_scandir_free(dents[*nbufs - 1]);
 +
 +  /* End was already reached */
 +  if (*nbufs == (unsigned int) req->result) {
 +    uv__fs_scandir_free(dents);
 +    req->ptr = NULL;
 +    return UV_EOF;
 +  }
 +
 +  dent = dents[(*nbufs)++];
 +
 +  ent->name = dent->d_name;
++  ent->type = uv__fs_get_dirent_type(dent);
++
++  return 0;
++}
++
++uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent) {
++  uv_dirent_type_t type;
++
 +#ifdef HAVE_DIRENT_TYPES
 +  switch (dent->d_type) {
 +    case UV__DT_DIR:
-       ent->type = UV_DIRENT_DIR;
++      type = UV_DIRENT_DIR;
 +      break;
 +    case UV__DT_FILE:
-       ent->type = UV_DIRENT_FILE;
++      type = UV_DIRENT_FILE;
 +      break;
 +    case UV__DT_LINK:
-       ent->type = UV_DIRENT_LINK;
++      type = UV_DIRENT_LINK;
 +      break;
 +    case UV__DT_FIFO:
-       ent->type = UV_DIRENT_FIFO;
++      type = UV_DIRENT_FIFO;
 +      break;
 +    case UV__DT_SOCKET:
-       ent->type = UV_DIRENT_SOCKET;
++      type = UV_DIRENT_SOCKET;
 +      break;
 +    case UV__DT_CHAR:
-       ent->type = UV_DIRENT_CHAR;
++      type = UV_DIRENT_CHAR;
 +      break;
 +    case UV__DT_BLOCK:
-       ent->type = UV_DIRENT_BLOCK;
++      type = UV_DIRENT_BLOCK;
 +      break;
 +    default:
-       ent->type = UV_DIRENT_UNKNOWN;
++      type = UV_DIRENT_UNKNOWN;
 +  }
 +#else
-   ent->type = UV_DIRENT_UNKNOWN;
++  type = UV_DIRENT_UNKNOWN;
 +#endif
 +
-   return 0;
++  return type;
++}
++
++void uv__fs_readdir_cleanup(uv_fs_t* req) {
++  uv_dir_t* dir;
++  uv_dirent_t* dirents;
++  int i;
++
++  if (req->ptr == NULL)
++    return;
++
++  dir = req->ptr;
++  dirents = dir->dirents;
++  req->ptr = NULL;
++
++  if (dirents == NULL)
++    return;
++
++  for (i = 0; i < req->result; ++i) {
++    uv__free((char*) dirents[i].name);
++    dirents[i].name = NULL;
++  }
 +}
 +
 +
 +int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) {
 +  va_list ap;
 +  int err;
 +
 +  va_start(ap, option);
 +  /* Any platform-agnostic options should be handled here. */
 +  err = uv__loop_configure(loop, option, ap);
 +  va_end(ap);
 +
 +  return err;
 +}
 +
 +
 +static uv_loop_t default_loop_struct;
 +static uv_loop_t* default_loop_ptr;
 +
 +
 +uv_loop_t* uv_default_loop(void) {
 +  if (default_loop_ptr != NULL)
 +    return default_loop_ptr;
 +
 +  if (uv_loop_init(&default_loop_struct))
 +    return NULL;
 +
 +  default_loop_ptr = &default_loop_struct;
 +  return default_loop_ptr;
 +}
 +
 +
 +uv_loop_t* uv_loop_new(void) {
 +  uv_loop_t* loop;
 +
 +  loop = uv__malloc(sizeof(*loop));
 +  if (loop == NULL)
 +    return NULL;
 +
 +  if (uv_loop_init(loop)) {
 +    uv__free(loop);
 +    return NULL;
 +  }
 +
 +  return loop;
 +}
 +
 +
 +int uv_loop_close(uv_loop_t* loop) {
 +  QUEUE* q;
 +  uv_handle_t* h;
 +#ifndef NDEBUG
 +  void* saved_data;
 +#endif
 +
 +  if (uv__has_active_reqs(loop))
 +    return UV_EBUSY;
 +
 +  QUEUE_FOREACH(q, &loop->handle_queue) {
 +    h = QUEUE_DATA(q, uv_handle_t, handle_queue);
 +    if (!(h->flags & UV_HANDLE_INTERNAL))
 +      return UV_EBUSY;
 +  }
 +
 +  uv__loop_close(loop);
 +
 +#ifndef NDEBUG
 +  saved_data = loop->data;
 +  memset(loop, -1, sizeof(*loop));
 +  loop->data = saved_data;
 +#endif
 +  if (loop == default_loop_ptr)
 +    default_loop_ptr = NULL;
 +
 +  return 0;
 +}
 +
 +
 +void uv_loop_delete(uv_loop_t* loop) {
 +  uv_loop_t* default_loop;
 +  int err;
 +
 +  default_loop = default_loop_ptr;
 +
 +  err = uv_loop_close(loop);
 +  (void) err;    /* Squelch compiler warnings. */
 +  assert(err == 0);
 +  if (loop != default_loop)
 +    uv__free(loop);
 +}
diff --cc Utilities/cmlibuv/src/win/internal.h
index 206ab5f,0000000..f7d8ccf
mode 100644,000000..100644
--- a/Utilities/cmlibuv/src/win/internal.h
+++ b/Utilities/cmlibuv/src/win/internal.h
@@@ -1,338 -1,0 +1,346 @@@
 +/* 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.
 + */
 +
 +#ifndef UV_WIN_INTERNAL_H_
 +#define UV_WIN_INTERNAL_H_
 +
 +#if defined(_MSC_VER)
 +# pragma warning(push,1)
 +#endif
 +
 +#include "uv.h"
 +#include "../uv-common.h"
 +
 +#include "uv/tree.h"
 +#include "winapi.h"
 +#include "winsock.h"
 +
 +#ifdef _MSC_VER
 +# define INLINE __inline
 +# define UV_THREAD_LOCAL __declspec( thread )
 +#else
 +# define INLINE inline
 +# define UV_THREAD_LOCAL __thread
 +#endif
 +
 +
 +#ifdef _DEBUG
 +
 +extern UV_THREAD_LOCAL int uv__crt_assert_enabled;
 +
 +#define UV_BEGIN_DISABLE_CRT_ASSERT()                           \
 +  {                                                             \
 +    int uv__saved_crt_assert_enabled = uv__crt_assert_enabled;  \
 +    uv__crt_assert_enabled = FALSE;
 +
 +
 +#define UV_END_DISABLE_CRT_ASSERT()                             \
 +    uv__crt_assert_enabled = uv__saved_crt_assert_enabled;      \
 +  }
 +
 +#else
 +#define UV_BEGIN_DISABLE_CRT_ASSERT()
 +#define UV_END_DISABLE_CRT_ASSERT()
 +#endif
 +
 +/*
 + * TCP
 + */
 +
 +typedef enum {
 +  UV__IPC_SOCKET_XFER_NONE = 0,
 +  UV__IPC_SOCKET_XFER_TCP_CONNECTION,
 +  UV__IPC_SOCKET_XFER_TCP_SERVER
 +} uv__ipc_socket_xfer_type_t;
 +
 +typedef struct {
 +  WSAPROTOCOL_INFOW socket_info;
 +  uint32_t delayed_error;
 +} uv__ipc_socket_xfer_info_t;
 +
 +int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);
 +int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client);
 +int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
 +    uv_read_cb read_cb);
 +int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle,
 +    const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);
 +int uv__tcp_try_write(uv_tcp_t* handle, const uv_buf_t bufs[],
 +    unsigned int nbufs);
 +
 +void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req);
 +void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
 +    uv_write_t* req);
 +void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
 +    uv_req_t* req);
 +void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
 +    uv_connect_t* req);
 +
 +void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp);
 +void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);
 +
 +int uv__tcp_xfer_export(uv_tcp_t* handle,
 +                        int pid,
 +                        uv__ipc_socket_xfer_type_t* xfer_type,
 +                        uv__ipc_socket_xfer_info_t* xfer_info);
 +int uv__tcp_xfer_import(uv_tcp_t* tcp,
 +                        uv__ipc_socket_xfer_type_t xfer_type,
 +                        uv__ipc_socket_xfer_info_t* xfer_info);
 +
 +
 +/*
 + * UDP
 + */
 +void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, uv_req_t* req);
 +void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
 +    uv_udp_send_t* req);
 +
 +void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle);
 +void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle);
 +
 +
 +/*
 + * Pipes
 + */
 +int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
 +    char* name, size_t nameSize);
 +
 +int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
 +int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client);
 +int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb,
 +    uv_read_cb read_cb);
 +void uv__pipe_read_stop(uv_pipe_t* handle);
 +int uv__pipe_write(uv_loop_t* loop,
 +                   uv_write_t* req,
 +                   uv_pipe_t* handle,
 +                   const uv_buf_t bufs[],
 +                   size_t nbufs,
 +                   uv_stream_t* send_handle,
 +                   uv_write_cb cb);
 +
 +void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
 +    uv_req_t* req);
 +void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
 +    uv_write_t* req);
 +void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
 +    uv_req_t* raw_req);
 +void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,
 +    uv_connect_t* req);
 +void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
 +    uv_shutdown_t* req);
 +
 +void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle);
 +void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle);
 +void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle);
 +
 +
 +/*
 + * TTY
 + */
 +void uv_console_init(void);
 +
 +int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
 +    uv_read_cb read_cb);
 +int uv_tty_read_stop(uv_tty_t* handle);
 +int uv_tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle,
 +    const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);
 +int uv__tty_try_write(uv_tty_t* handle, const uv_buf_t bufs[],
 +    unsigned int nbufs);
 +void uv_tty_close(uv_tty_t* handle);
 +
 +void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
 +    uv_req_t* req);
 +void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
 +    uv_write_t* req);
 +/*
 + * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working
 + * TODO: find a way to remove it
 + */
 +void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
 +    uv_req_t* raw_req);
 +/*
 + * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working
 + * TODO: find a way to remove it
 + */
 +void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
 +    uv_connect_t* req);
 +
 +void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle);
 +
 +
 +/*
 + * Poll watchers
 + */
 +void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
 +    uv_req_t* req);
 +
 +int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle);
 +void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle);
 +
 +
 +/*
 + * Loop watchers
 + */
 +void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle);
 +
 +void uv_prepare_invoke(uv_loop_t* loop);
 +void uv_check_invoke(uv_loop_t* loop);
 +void uv_idle_invoke(uv_loop_t* loop);
 +
 +void uv__once_init(void);
 +
 +
 +/*
 + * Async watcher
 + */
 +void uv_async_close(uv_loop_t* loop, uv_async_t* handle);
 +void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle);
 +
 +void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
 +    uv_req_t* req);
 +
 +
 +/*
 + * Signal watcher
 + */
 +void uv_signals_init(void);
 +int uv__signal_dispatch(int signum);
 +
 +void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle);
 +void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle);
 +
 +void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle,
 +    uv_req_t* req);
 +
 +
 +/*
 + * Spawn
 + */
 +void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle);
 +void uv_process_close(uv_loop_t* loop, uv_process_t* handle);
 +void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle);
 +
 +
 +/*
 + * Error
 + */
 +int uv_translate_sys_error(int sys_errno);
 +
 +
 +/*
 + * FS
 + */
 +void uv_fs_init(void);
 +
 +
 +/*
 + * FS Event
 + */
 +void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
 +    uv_fs_event_t* handle);
 +void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle);
 +void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle);
 +
 +
 +/*
 + * Stat poller.
 + */
 +void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle);
 +
 +
 +/*
 + * Utilities.
 + */
 +void uv__util_init(void);
 +
 +uint64_t uv__hrtime(double scale);
 +__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
 +int uv__getpwuid_r(uv_passwd_t* pwd);
 +int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
 +int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16);
 +
++typedef int (WINAPI *uv__peersockfunc)(SOCKET, struct sockaddr*, int*);
++
++int uv__getsockpeername(const uv_handle_t* handle,
++                        uv__peersockfunc func,
++                        struct sockaddr* name,
++                        int* namelen,
++                        int delayed_error);
++
 +
 +/*
 + * Process stdio handles.
 + */
 +int uv__stdio_create(uv_loop_t* loop,
 +                     const uv_process_options_t* options,
 +                     BYTE** buffer_ptr);
 +void uv__stdio_destroy(BYTE* buffer);
 +void uv__stdio_noinherit(BYTE* buffer);
 +int uv__stdio_verify(BYTE* buffer, WORD size);
 +WORD uv__stdio_size(BYTE* buffer);
 +HANDLE uv__stdio_handle(BYTE* buffer, int fd);
 +
 +
 +/*
 + * Winapi and ntapi utility functions
 + */
 +void uv_winapi_init(void);
 +
 +
 +/*
 + * Winsock utility functions
 + */
 +void uv_winsock_init(void);
 +
 +int uv_ntstatus_to_winsock_error(NTSTATUS status);
 +
 +BOOL uv_get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target);
 +BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target);
 +
 +int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers,
 +    DWORD buffer_count, DWORD* bytes, DWORD* flags, WSAOVERLAPPED *overlapped,
 +    LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
 +int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
 +    DWORD buffer_count, DWORD* bytes, DWORD* flags, struct sockaddr* addr,
 +    int* addr_len, WSAOVERLAPPED *overlapped,
 +    LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
 +
 +int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
 +    AFD_POLL_INFO* info_out, OVERLAPPED* overlapped);
 +
 +/* Whether there are any non-IFS LSPs stacked on TCP */
 +extern int uv_tcp_non_ifs_lsp_ipv4;
 +extern int uv_tcp_non_ifs_lsp_ipv6;
 +
 +/* Ip address used to bind to any port at any interface */
 +extern struct sockaddr_in uv_addr_ip4_any_;
 +extern struct sockaddr_in6 uv_addr_ip6_any_;
 +
 +/*
 + * Wake all loops with fake message
 + */
 +void uv__wake_all_loops(void);
 +
 +/*
 + * Init system wake-up detection
 + */
 +void uv__init_detect_system_wakeup(void);
 +
 +#endif /* UV_WIN_INTERNAL_H_ */

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b4069b04ff63b327ff4881282200c3c73fded34d
commit b4069b04ff63b327ff4881282200c3c73fded34d
Author:     libuv upstream <libuv at googlegroups.com>
AuthorDate: Mon Jun 10 15:17:21 2019 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Jun 18 07:45:34 2019 -0400

    libuv 2019-06-10 (ee24ce90)
    
    Code extracted from:
    
        https://github.com/libuv/libuv.git
    
    at commit ee24ce900e5714c950b248da2bdd311b01c983be (v1.x).

diff --git a/include/uv.h b/include/uv.h
index a46b229..f97801c 100644
--- a/include/uv.h
+++ b/include/uv.h
@@ -202,6 +202,7 @@ typedef enum {
 /* Handle types. */
 typedef struct uv_loop_s uv_loop_t;
 typedef struct uv_handle_s uv_handle_t;
+typedef struct uv_dir_s uv_dir_t;
 typedef struct uv_stream_s uv_stream_t;
 typedef struct uv_tcp_s uv_tcp_t;
 typedef struct uv_udp_s uv_udp_t;
@@ -630,7 +631,11 @@ UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock);
 UV_EXTERN int uv_udp_bind(uv_udp_t* handle,
                           const struct sockaddr* addr,
                           unsigned int flags);
+UV_EXTERN int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr);
 
+UV_EXTERN int uv_udp_getpeername(const uv_udp_t* handle,
+                                 struct sockaddr* name,
+                                 int* namelen);
 UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle,
                                  struct sockaddr* name,
                                  int* namelen);
@@ -1095,6 +1100,11 @@ typedef struct {
 } uv_timeval_t;
 
 typedef struct {
+  int64_t tv_sec;
+  int32_t tv_usec;
+} uv_timeval64_t;
+
+typedef struct {
    uv_timeval_t ru_utime; /* user CPU time used */
    uv_timeval_t ru_stime; /* system CPU time used */
    uint64_t ru_maxrss;    /* maximum resident set size */
@@ -1144,6 +1154,17 @@ 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);
 
+#ifdef MAXHOSTNAMELEN
+# define UV_MAXHOSTNAMESIZE (MAXHOSTNAMELEN + 1)
+#else
+  /*
+    Fallback for the maximum hostname size, including the null terminator. The
+    Windows gethostname() documentation states that 256 bytes will always be
+    large enough to hold the null-terminated hostname.
+  */
+# define UV_MAXHOSTNAMESIZE 256
+#endif
+
 UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);
 
 UV_EXTERN int uv_os_uname(uv_utsname_t* buffer);
@@ -1181,9 +1202,19 @@ typedef enum {
   UV_FS_FCHOWN,
   UV_FS_REALPATH,
   UV_FS_COPYFILE,
-  UV_FS_LCHOWN
+  UV_FS_LCHOWN,
+  UV_FS_OPENDIR,
+  UV_FS_READDIR,
+  UV_FS_CLOSEDIR
 } uv_fs_type;
 
+struct uv_dir_s {
+  uv_dirent_t* dirents;
+  size_t nentries;
+  void* reserved[4];
+  UV_DIR_PRIVATE_FIELDS
+};
+
 /* uv_fs_t is a subclass of uv_req_t. */
 struct uv_fs_s {
   UV_REQ_FIELDS
@@ -1276,6 +1307,18 @@ UV_EXTERN int uv_fs_scandir(uv_loop_t* loop,
                             uv_fs_cb cb);
 UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req,
                                  uv_dirent_t* ent);
+UV_EXTERN int uv_fs_opendir(uv_loop_t* loop,
+                            uv_fs_t* req,
+                            const char* path,
+                            uv_fs_cb cb);
+UV_EXTERN int uv_fs_readdir(uv_loop_t* loop,
+                            uv_fs_t* req,
+                            uv_dir_t* dir,
+                            uv_fs_cb cb);
+UV_EXTERN int uv_fs_closedir(uv_loop_t* loop,
+                             uv_fs_t* req,
+                             uv_dir_t* dir,
+                             uv_fs_cb cb);
 UV_EXTERN int uv_fs_stat(uv_loop_t* loop,
                          uv_fs_t* req,
                          const char* path,
@@ -1518,6 +1561,7 @@ UV_EXTERN int uv_chdir(const char* dir);
 
 UV_EXTERN uint64_t uv_get_free_memory(void);
 UV_EXTERN uint64_t uv_get_total_memory(void);
+UV_EXTERN uint64_t uv_get_constrained_memory(void);
 
 UV_EXTERN uint64_t uv_hrtime(void);
 
@@ -1571,9 +1615,29 @@ UV_EXTERN void uv_key_delete(uv_key_t* key);
 UV_EXTERN void* uv_key_get(uv_key_t* key);
 UV_EXTERN void uv_key_set(uv_key_t* key, void* value);
 
+UV_EXTERN int uv_gettimeofday(uv_timeval64_t* tv);
+
 typedef void (*uv_thread_cb)(void* arg);
 
 UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg);
+
+typedef enum {
+  UV_THREAD_NO_FLAGS = 0x00,
+  UV_THREAD_HAS_STACK_SIZE = 0x01
+} uv_thread_create_flags;
+
+struct uv_thread_options_s {
+  unsigned int flags;
+  size_t stack_size;
+  /* More fields may be added at any time. */
+};
+
+typedef struct uv_thread_options_s uv_thread_options_t;
+
+UV_EXTERN int uv_thread_create_ex(uv_thread_t* tid,
+                                  const uv_thread_options_t* params,
+                                  uv_thread_cb entry,
+                                  void* arg);
 UV_EXTERN uv_thread_t uv_thread_self(void);
 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);
diff --git a/include/uv/unix.h b/include/uv/unix.h
index 9de9efe..6c93ee9 100644
--- a/include/uv/unix.h
+++ b/include/uv/unix.h
@@ -31,13 +31,14 @@
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <arpa/inet.h>
-#include <netdb.h>
+#include <netdb.h>  /* MAXHOSTNAMELEN on Solaris */
 
 #include <termios.h>
 #include <pwd.h>
 
 #if !defined(__MVS__)
 #include <semaphore.h>
+#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
 #endif
 #include <pthread.h>
 #include <signal.h>
@@ -48,8 +49,6 @@
 # include "uv/linux.h"
 #elif defined (__MVS__)
 # include "uv/os390.h"
-#elif defined(__PASE__)
-# include "uv/posix.h"
 #elif defined(_AIX)
 # include "uv/aix.h"
 #elif defined(__sun)
@@ -62,9 +61,12 @@
       defined(__OpenBSD__)         || \
       defined(__NetBSD__)
 # include "uv/bsd.h"
-#elif defined(__CYGWIN__) || defined(__MSYS__)
+#elif defined(__PASE__)   || \
+      defined(__CYGWIN__) || \
+      defined(__MSYS__)   || \
+      defined(__GNU__)
 # include "uv/posix.h"
-#elif defined(__GNU__)
+#elif defined(__HAIKU__)
 # include "uv/posix.h"
 #endif
 
@@ -136,7 +138,9 @@ typedef pthread_cond_t uv_cond_t;
 typedef pthread_key_t uv_key_t;
 
 /* Note: guard clauses should match uv_barrier_init's in src/unix/thread.c. */
-#if defined(_AIX) || !defined(PTHREAD_BARRIER_SERIAL_THREAD)
+#if defined(_AIX) || \
+    defined(__OpenBSD__) || \
+    !defined(PTHREAD_BARRIER_SERIAL_THREAD)
 /* TODO(bnoordhuis) Merge into uv_barrier_t in v2. */
 struct _uv_barrier {
   uv_mutex_t mutex;
@@ -163,6 +167,9 @@ typedef uid_t uv_uid_t;
 
 typedef struct dirent uv__dirent_t;
 
+#define UV_DIR_PRIVATE_FIELDS \
+  DIR* dir;
+
 #if defined(DT_UNKNOWN)
 # define HAVE_DIRENT_TYPES
 # if defined(DT_REG)
diff --git a/include/uv/version.h b/include/uv/version.h
index abc140a..97f0bc2 100644
--- a/include/uv/version.h
+++ b/include/uv/version.h
@@ -31,7 +31,7 @@
  */
 
 #define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 24
+#define UV_VERSION_MINOR 29
 #define UV_VERSION_PATCH 2
 #define UV_VERSION_IS_RELEASE 0
 #define UV_VERSION_SUFFIX "dev"
diff --git a/include/uv/win.h b/include/uv/win.h
index edd2cc6..acbd958 100644
--- a/include/uv/win.h
+++ b/include/uv/win.h
@@ -301,6 +301,11 @@ typedef struct uv__dirent_s {
   char d_name[1];
 } uv__dirent_t;
 
+#define UV_DIR_PRIVATE_FIELDS \
+  HANDLE dir_handle;          \
+  WIN32_FIND_DATAW find_data; \
+  BOOL need_find_call;
+
 #define HAVE_DIRENT_TYPES
 #define UV__DT_DIR     UV_DIRENT_DIR
 #define UV__DT_FILE    UV_DIRENT_FILE
diff --git a/src/fs-poll.c b/src/fs-poll.c
index 6c82dfc..89864e2 100644
--- a/src/fs-poll.c
+++ b/src/fs-poll.c
@@ -22,12 +22,20 @@
 #include "uv.h"
 #include "uv-common.h"
 
+#ifdef _WIN32
+#include "win/internal.h"
+#include "win/handle-inl.h"
+#define uv__make_close_pending(h) uv_want_endgame((h)->loop, (h))
+#else
+#include "unix/internal.h"
+#endif
+
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
 struct poll_ctx {
-  uv_fs_poll_t* parent_handle; /* NULL if parent has been stopped or closed */
+  uv_fs_poll_t* parent_handle;
   int busy_polling;
   unsigned int interval;
   uint64_t start_time;
@@ -36,6 +44,7 @@ struct poll_ctx {
   uv_timer_t timer_handle;
   uv_fs_t fs_req; /* TODO(bnoordhuis) mark fs_req internal */
   uv_stat_t statbuf;
+  struct poll_ctx* previous; /* context from previous start()..stop() period */
   char path[1]; /* variable length */
 };
 
@@ -49,6 +58,7 @@ static uv_stat_t zero_statbuf;
 
 int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) {
   uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL);
+  handle->poll_ctx = NULL;
   return 0;
 }
 
@@ -62,7 +72,7 @@ int uv_fs_poll_start(uv_fs_poll_t* handle,
   size_t len;
   int err;
 
-  if (uv__is_active(handle))
+  if (uv_is_active((uv_handle_t*)handle))
     return 0;
 
   loop = handle->loop;
@@ -90,6 +100,8 @@ int uv_fs_poll_start(uv_fs_poll_t* handle,
   if (err < 0)
     goto error;
 
+  if (handle->poll_ctx != NULL)
+    ctx->previous = handle->poll_ctx;
   handle->poll_ctx = ctx;
   uv__handle_start(handle);
 
@@ -104,19 +116,17 @@ error:
 int uv_fs_poll_stop(uv_fs_poll_t* handle) {
   struct poll_ctx* ctx;
 
-  if (!uv__is_active(handle))
+  if (!uv_is_active((uv_handle_t*)handle))
     return 0;
 
   ctx = handle->poll_ctx;
   assert(ctx != NULL);
-  assert(ctx->parent_handle != NULL);
-  ctx->parent_handle = NULL;
-  handle->poll_ctx = NULL;
+  assert(ctx->parent_handle == handle);
 
   /* Close the timer if it's active. If it's inactive, there's a stat request
    * in progress and poll_cb will take care of the cleanup.
    */
-  if (uv__is_active(&ctx->timer_handle))
+  if (uv_is_active((uv_handle_t*)&ctx->timer_handle))
     uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
 
   uv__handle_stop(handle);
@@ -129,7 +139,7 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) {
   struct poll_ctx* ctx;
   size_t required_len;
 
-  if (!uv__is_active(handle)) {
+  if (!uv_is_active((uv_handle_t*)handle)) {
     *size = 0;
     return UV_EINVAL;
   }
@@ -153,6 +163,9 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) {
 
 void uv__fs_poll_close(uv_fs_poll_t* handle) {
   uv_fs_poll_stop(handle);
+
+  if (handle->poll_ctx == NULL)
+    uv__make_close_pending((uv_handle_t*)handle);
 }
 
 
@@ -173,14 +186,13 @@ static void poll_cb(uv_fs_t* req) {
   uv_stat_t* statbuf;
   struct poll_ctx* ctx;
   uint64_t interval;
+  uv_fs_poll_t* handle;
 
   ctx = container_of(req, struct poll_ctx, fs_req);
+  handle = ctx->parent_handle;
 
-  if (ctx->parent_handle == NULL) { /* handle has been stopped or closed */
-    uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
-    uv_fs_req_cleanup(req);
-    return;
-  }
+  if (!uv_is_active((uv_handle_t*)handle) || uv__is_closing(handle))
+    goto out;
 
   if (req->result != 0) {
     if (ctx->busy_polling != req->result) {
@@ -205,7 +217,7 @@ static void poll_cb(uv_fs_t* req) {
 out:
   uv_fs_req_cleanup(req);
 
-  if (ctx->parent_handle == NULL) { /* handle has been stopped by callback */
+  if (!uv_is_active((uv_handle_t*)handle) || uv__is_closing(handle)) {
     uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
     return;
   }
@@ -219,8 +231,27 @@ out:
 }
 
 
-static void timer_close_cb(uv_handle_t* handle) {
-  uv__free(container_of(handle, struct poll_ctx, timer_handle));
+static void timer_close_cb(uv_handle_t* timer) {
+  struct poll_ctx* ctx;
+  struct poll_ctx* it;
+  struct poll_ctx* last;
+  uv_fs_poll_t* handle;
+
+  ctx = container_of(timer, struct poll_ctx, timer_handle);
+  handle = ctx->parent_handle;
+  if (ctx == handle->poll_ctx) {
+    handle->poll_ctx = ctx->previous;
+    if (handle->poll_ctx == NULL && uv__is_closing(handle))
+      uv__make_close_pending((uv_handle_t*)handle);
+  } else {
+    for (last = handle->poll_ctx, it = last->previous;
+         it != ctx;
+         last = it, it = it->previous) {
+      assert(last->previous != NULL);
+    }
+    last->previous = ctx->previous;
+  }
+  uv__free(ctx);
 }
 
 
diff --git a/src/threadpool.c b/src/threadpool.c
index 4258933..7aa5755 100644
--- a/src/threadpool.c
+++ b/src/threadpool.c
@@ -27,7 +27,7 @@
 
 #include <stdlib.h>
 
-#define MAX_THREADPOOL_SIZE 128
+#define MAX_THREADPOOL_SIZE 1024
 
 static uv_once_t once = UV_ONCE_INIT;
 static uv_cond_t cond;
diff --git a/src/unix/aix.c b/src/unix/aix.c
index 337e58e..1f36926 100644
--- a/src/unix/aix.c
+++ b/src/unix/aix.c
@@ -344,6 +344,11 @@ uint64_t uv_get_total_memory(void) {
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 void uv_loadavg(double avg[3]) {
   perfstat_cpu_total_t ps_total;
   int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1);
@@ -1041,6 +1046,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
   struct poll_ctl pc;
 
   assert(loop->watchers != NULL);
+  assert(fd >= 0);
 
   events = (struct pollfd*) loop->watchers[loop->nwatchers];
   nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
diff --git a/src/unix/async.c b/src/unix/async.c
index 0b450ae..a5c47bc 100644
--- a/src/unix/async.c
+++ b/src/unix/async.c
@@ -61,14 +61,43 @@ int uv_async_send(uv_async_t* handle) {
   if (ACCESS_ONCE(int, handle->pending) != 0)
     return 0;
 
-  if (cmpxchgi(&handle->pending, 0, 1) == 0)
-    uv__async_send(handle->loop);
+  /* Tell the other thread we're busy with the handle. */
+  if (cmpxchgi(&handle->pending, 0, 1) != 0)
+    return 0;
+
+  /* Wake up the other thread's event loop. */
+  uv__async_send(handle->loop);
+
+  /* Tell the other thread we're done. */
+  if (cmpxchgi(&handle->pending, 1, 2) != 1)
+    abort();
 
   return 0;
 }
 
 
+/* Only call this from the event loop thread. */
+static int uv__async_spin(uv_async_t* handle) {
+  int rc;
+
+  for (;;) {
+    /* rc=0 -- handle is not pending.
+     * rc=1 -- handle is pending, other thread is still working with it.
+     * rc=2 -- handle is pending, other thread is done.
+     */
+    rc = cmpxchgi(&handle->pending, 2, 0);
+
+    if (rc != 1)
+      return rc;
+
+    /* Other thread is busy with this handle, spin until it's done. */
+    cpu_relax();
+  }
+}
+
+
 void uv__async_close(uv_async_t* handle) {
+  uv__async_spin(handle);
   QUEUE_REMOVE(&handle->queue);
   uv__handle_stop(handle);
 }
@@ -109,8 +138,8 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
     QUEUE_REMOVE(q);
     QUEUE_INSERT_TAIL(&loop->async_handles, q);
 
-    if (cmpxchgi(&h->pending, 1, 0) == 0)
-      continue;
+    if (0 == uv__async_spin(h))
+      continue;  /* Not pending. */
 
     if (h->async_cb == NULL)
       continue;
diff --git a/src/unix/atomic-ops.h b/src/unix/atomic-ops.h
index 7cac1f9..541a6c8 100644
--- a/src/unix/atomic-ops.h
+++ b/src/unix/atomic-ops.h
@@ -23,7 +23,6 @@
 #endif
 
 UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval));
-UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval));
 UV_UNUSED(static void cpu_relax(void));
 
 /* Prefer hand-rolled assembly over the gcc builtins because the latter also
@@ -49,43 +48,7 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
   else
     return op4;
 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-  return atomic_cas_uint(ptr, oldval, newval);
-#else
-  return __sync_val_compare_and_swap(ptr, oldval, newval);
-#endif
-}
-
-UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) {
-#if defined(__i386__) || defined(__x86_64__)
-  long out;
-  __asm__ __volatile__ ("lock; cmpxchg %2, %1;"
-                        : "=a" (out), "+m" (*(volatile long*) ptr)
-                        : "r" (newval), "0" (oldval)
-                        : "memory");
-  return out;
-#elif defined(_AIX) && defined(__xlC__)
-  const long out = (*(volatile int*) ptr);
-# if defined(__64BIT__)
-  __compare_and_swaplp(ptr, &oldval, newval);
-# else
-  __compare_and_swap(ptr, &oldval, newval);
-# endif /* if defined(__64BIT__) */
-  return out;
-#elif defined (__MVS__)
-#ifdef _LP64
-  unsigned long long op4;
-  if (__plo_CSSTGR(ptr, (unsigned long long*) &oldval, newval,
-                  (unsigned long long*) ptr, *ptr, &op4))
-#else
-  unsigned long op4;
-  if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
-                (unsigned int*) ptr, *ptr, &op4))
-#endif
-    return oldval;
-  else
-    return op4;
-#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-  return atomic_cas_ulong(ptr, oldval, newval);
+  return atomic_cas_uint((uint_t *)ptr, (uint_t)oldval, (uint_t)newval);
 #else
   return __sync_val_compare_and_swap(ptr, oldval, newval);
 #endif
diff --git a/src/unix/bsd-ifaddrs.c b/src/unix/bsd-ifaddrs.c
index 3c2253f..0d7bbe6 100644
--- a/src/unix/bsd-ifaddrs.c
+++ b/src/unix/bsd-ifaddrs.c
@@ -31,6 +31,10 @@
 #include <net/if_dl.h>
 #endif
 
+#if defined(__HAIKU__)
+#define IFF_RUNNING IFF_LINK
+#endif
+
 static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
   if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
     return 1;
@@ -45,7 +49,8 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
   if (exclude_type == UV__EXCLUDE_IFPHYS)
     return (ent->ifa_addr->sa_family != AF_LINK);
 #endif
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) || \
+    defined(__HAIKU__)
   /*
    * On BSD getifaddrs returns information related to the raw underlying
    * devices.  We're not interested in this information.
@@ -84,7 +89,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
     return 0;
   }
 
-  *addresses = uv__malloc(*count * sizeof(**addresses));
+  /* Make sure the memory is initiallized to zero using calloc() */
+  *addresses = uv__calloc(*count, sizeof(**addresses));
 
   if (*addresses == NULL) {
     freeifaddrs(addrs);
@@ -116,6 +122,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
     address++;
   }
 
+#if !(defined(__CYGWIN__) || defined(__MSYS__))
   /* Fill in physical addresses for each interface */
   for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
     if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
@@ -124,20 +131,15 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
     address = *addresses;
 
     for (i = 0; i < *count; i++) {
-#if defined(__CYGWIN__) || defined(__MSYS__)
-      memset(address->phys_addr, 0, sizeof(address->phys_addr));
-#else
       if (strcmp(address->name, ent->ifa_name) == 0) {
         struct sockaddr_dl* sa_addr;
         sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
         memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
-      } else {
-        memset(address->phys_addr, 0, sizeof(address->phys_addr));
       }
-#endif
       address++;
     }
   }
+#endif
 
   freeifaddrs(addrs);
 
diff --git a/src/unix/core.c b/src/unix/core.c
index cd57ce2..52896f9 100644
--- a/src/unix/core.c
+++ b/src/unix/core.c
@@ -41,9 +41,9 @@
 #include <sys/resource.h> /* getrusage */
 #include <pwd.h>
 #include <sys/utsname.h>
+#include <sys/time.h>
 
 #ifdef __sun
-# include <netdb.h> /* MAXHOSTNAMELEN on Solaris */
 # include <sys/filio.h>
 # include <sys/types.h>
 # include <sys/wait.h>
@@ -88,13 +88,8 @@
 #include <sys/ioctl.h>
 #endif
 
-#if !defined(__MVS__)
-#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
-#endif
-
-/* Fallback for the maximum hostname length */
-#ifndef MAXHOSTNAMELEN
-# define MAXHOSTNAMELEN 256
+#if defined(__linux__)
+#include <sys/syscall.h>
 #endif
 
 static int uv__run_pending(uv_loop_t* loop);
@@ -171,7 +166,9 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
 
   case UV_FS_POLL:
     uv__fs_poll_close((uv_fs_poll_t*)handle);
-    break;
+    /* Poll handles use file system requests, and one of them may still be
+     * running. The poll code will call uv__make_close_pending() for us. */
+    return;
 
   case UV_SIGNAL:
     uv__signal_close((uv_signal_t*) handle);
@@ -517,6 +514,34 @@ skip:
 }
 
 
+/* close() on macos has the "interesting" quirk that it fails with EINTR
+ * without closing the file descriptor when a thread is in the cancel state.
+ * That's why libuv calls close$NOCANCEL() instead.
+ *
+ * glibc on linux has a similar issue: close() is a cancellation point and
+ * will unwind the thread when it's in the cancel state. Work around that
+ * by making the system call directly. Musl libc is unaffected.
+ */
+int uv__close_nocancel(int fd) {
+#if defined(__APPLE__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
+#if defined(__LP64__)
+  extern int close$NOCANCEL(int);
+  return close$NOCANCEL(fd);
+#else
+  extern int close$NOCANCEL$UNIX2003(int);
+  return close$NOCANCEL$UNIX2003(fd);
+#endif
+#pragma GCC diagnostic pop
+#elif defined(__linux__)
+  return syscall(SYS_close, fd);
+#else
+  return close(fd);
+#endif
+}
+
+
 int uv__close_nocheckstdio(int fd) {
   int saved_errno;
   int rc;
@@ -524,7 +549,7 @@ int uv__close_nocheckstdio(int fd) {
   assert(fd > -1);  /* Catch uninitialized io_watcher.fd bugs. */
 
   saved_errno = errno;
-  rc = close(fd);
+  rc = uv__close_nocancel(fd);
   if (rc == -1) {
     rc = UV__ERR(errno);
     if (rc == UV_EINTR || rc == UV__ERR(EINPROGRESS))
@@ -559,7 +584,7 @@ int uv__nonblock_ioctl(int fd, int set) {
 }
 
 
-#if !defined(__CYGWIN__) && !defined(__MSYS__)
+#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__HAIKU__)
 int uv__cloexec_ioctl(int fd, int set) {
   int r;
 
@@ -892,7 +917,8 @@ void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
   QUEUE_REMOVE(&w->pending_queue);
 
   /* Remove stale events for this file descriptor */
-  uv__platform_invalidate_fd(loop, w->fd);
+  if (w->fd != -1)
+    uv__platform_invalidate_fd(loop, w->fd);
 }
 
 
@@ -926,7 +952,7 @@ int uv_getrusage(uv_rusage_t* rusage) {
   rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec;
   rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec;
 
-#if !defined(__MVS__)
+#if !defined(__MVS__) && !defined(__HAIKU__)
   rusage->ru_maxrss = usage.ru_maxrss;
   rusage->ru_ixrss = usage.ru_ixrss;
   rusage->ru_idrss = usage.ru_idrss;
@@ -1291,7 +1317,7 @@ int uv_os_gethostname(char* buffer, size_t* size) {
     instead by creating a large enough buffer and comparing the hostname length
     to the size input.
   */
-  char buf[MAXHOSTNAMELEN + 1];
+  char buf[UV_MAXHOSTNAMESIZE];
   size_t len;
 
   if (buffer == NULL || size == NULL || *size == 0)
@@ -1414,3 +1440,39 @@ error:
   buffer->machine[0] = '\0';
   return r;
 }
+
+int uv__getsockpeername(const uv_handle_t* handle,
+                        uv__peersockfunc func,
+                        struct sockaddr* name,
+                        int* namelen) {
+  socklen_t socklen;
+  uv_os_fd_t fd;
+  int r;
+
+  r = uv_fileno(handle, &fd);
+  if (r < 0)
+    return r;
+
+  /* sizeof(socklen_t) != sizeof(int) on some systems. */
+  socklen = (socklen_t) *namelen;
+
+  if (func(fd, name, &socklen))
+    return UV__ERR(errno);
+
+  *namelen = (int) socklen;
+  return 0;
+}
+
+int uv_gettimeofday(uv_timeval64_t* tv) {
+  struct timeval time;
+
+  if (tv == NULL)
+    return UV_EINVAL;
+
+  if (gettimeofday(&time, NULL) != 0)
+    return UV__ERR(errno);
+
+  tv->tv_sec = (int64_t) time.tv_sec;
+  tv->tv_usec = (int32_t) time.tv_usec;
+  return 0;
+}
diff --git a/src/unix/darwin.c b/src/unix/darwin.c
index 31ad8a9..e4cd8ff 100644
--- a/src/unix/darwin.c
+++ b/src/unix/darwin.c
@@ -117,6 +117,11 @@ uint64_t uv_get_total_memory(void) {
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 void uv_loadavg(double avg[3]) {
   struct loadavg info;
   size_t size = sizeof(info);
diff --git a/src/unix/freebsd.c b/src/unix/freebsd.c
index 0f729cf..7de88d6 100644
--- a/src/unix/freebsd.c
+++ b/src/unix/freebsd.c
@@ -137,6 +137,11 @@ uint64_t uv_get_total_memory(void) {
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 void uv_loadavg(double avg[3]) {
   struct loadavg info;
   size_t size = sizeof(info);
diff --git a/src/unix/fs.c b/src/unix/fs.c
index a0bd70d..0d6bfc6 100644
--- a/src/unix/fs.c
+++ b/src/unix/fs.c
@@ -47,7 +47,7 @@
 
 #if defined(__DragonFly__)        ||                                      \
     defined(__FreeBSD__)          ||                                      \
-    defined(__FreeBSD_kernel_)    ||                                      \
+    defined(__FreeBSD_kernel__)   ||                                      \
     defined(__OpenBSD__)          ||                                      \
     defined(__NetBSD__)
 # define HAVE_PREADV 1
@@ -60,7 +60,6 @@
 #endif
 
 #if defined(__APPLE__)
-# include <copyfile.h>
 # include <sys/sysctl.h>
 #elif defined(__linux__) && !defined(FICLONE)
 # include <sys/ioctl.h>
@@ -143,19 +142,34 @@ extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */
   while (0)
 
 
+static int uv__fs_close(int fd) {
+  int rc;
+
+  rc = uv__close_nocancel(fd);
+  if (rc == -1)
+    if (errno == EINTR || errno == EINPROGRESS)
+      rc = 0;  /* The close is in progress, not an error. */
+
+  return rc;
+}
+
+
 static ssize_t uv__fs_fsync(uv_fs_t* req) {
 #if defined(__APPLE__)
   /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache
    * to the drive platters. This is in contrast to Linux's fdatasync and fsync
    * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent
    * for flushing buffered data to permanent storage. If F_FULLFSYNC is not
-   * supported by the file system we should fall back to fsync(). This is the
-   * same approach taken by sqlite.
+   * supported by the file system we fall back to F_BARRIERFSYNC or fsync().
+   * This is the same approach taken by sqlite, except sqlite does not issue
+   * an F_BARRIERFSYNC call.
    */
   int r;
 
   r = fcntl(req->file, F_FULLFSYNC);
   if (r != 0)
+    r = fcntl(req->file, F_BARRIERFSYNC);  /* fsync + barrier */
+  if (r != 0)
     r = fsync(req->file);
   return r;
 #else
@@ -178,7 +192,8 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
 
 static ssize_t uv__fs_futime(uv_fs_t* req) {
 #if defined(__linux__)                                                        \
-    || defined(_AIX71)
+    || defined(_AIX71)                                                        \
+    || defined(__HAIKU__)
   /* utimesat() has nanosecond resolution but we stick to microseconds
    * for the sake of consistency with other platforms.
    */
@@ -317,6 +332,18 @@ done:
   req->bufs = NULL;
   req->nbufs = 0;
 
+#ifdef __PASE__
+  /* PASE returns EOPNOTSUPP when reading a directory, convert to EISDIR */
+  if (result == -1 && errno == EOPNOTSUPP) {
+    struct stat buf;
+    ssize_t rc;
+    rc = fstat(req->file, &buf);
+    if (rc == 0 && S_ISDIR(buf.st_mode)) {
+      errno = EISDIR;
+    }
+  }
+#endif
+
   return result;
 }
 
@@ -339,7 +366,7 @@ static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) {
 
 
 static ssize_t uv__fs_scandir(uv_fs_t* req) {
-  uv__dirent_t **dents;
+  uv__dirent_t** dents;
   int n;
 
   dents = NULL;
@@ -363,6 +390,87 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) {
   return n;
 }
 
+static int uv__fs_opendir(uv_fs_t* req) {
+  uv_dir_t* dir;
+
+  dir = uv__malloc(sizeof(*dir));
+  if (dir == NULL)
+    goto error;
+
+  dir->dir = opendir(req->path);
+  if (dir->dir == NULL)
+    goto error;
+
+  req->ptr = dir;
+  return 0;
+
+error:
+  uv__free(dir);
+  req->ptr = NULL;
+  return -1;
+}
+
+static int uv__fs_readdir(uv_fs_t* req) {
+  uv_dir_t* dir;
+  uv_dirent_t* dirent;
+  struct dirent* res;
+  unsigned int dirent_idx;
+  unsigned int i;
+
+  dir = req->ptr;
+  dirent_idx = 0;
+
+  while (dirent_idx < dir->nentries) {
+    /* readdir() returns NULL on end of directory, as well as on error. errno
+       is used to differentiate between the two conditions. */
+    errno = 0;
+    res = readdir(dir->dir);
+
+    if (res == NULL) {
+      if (errno != 0)
+        goto error;
+      break;
+    }
+
+    if (strcmp(res->d_name, ".") == 0 || strcmp(res->d_name, "..") == 0)
+      continue;
+
+    dirent = &dir->dirents[dirent_idx];
+    dirent->name = uv__strdup(res->d_name);
+
+    if (dirent->name == NULL)
+      goto error;
+
+    dirent->type = uv__fs_get_dirent_type(res);
+    ++dirent_idx;
+  }
+
+  return dirent_idx;
+
+error:
+  for (i = 0; i < dirent_idx; ++i) {
+    uv__free((char*) dir->dirents[i].name);
+    dir->dirents[i].name = NULL;
+  }
+
+  return -1;
+}
+
+static int uv__fs_closedir(uv_fs_t* req) {
+  uv_dir_t* dir;
+
+  dir = req->ptr;
+
+  if (dir->dir != NULL) {
+    closedir(dir->dir);
+    dir->dir = NULL;
+  }
+
+  uv__free(req->ptr);
+  req->ptr = NULL;
+  return 0;
+}
+
 #if defined(_POSIX_PATH_MAX)
 # define UV__FS_PATH_MAX _POSIX_PATH_MAX
 #elif defined(PATH_MAX)
@@ -692,7 +800,8 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
 static ssize_t uv__fs_utime(uv_fs_t* req) {
 #if defined(__linux__)                                                         \
     || defined(_AIX71)                                                         \
-    || defined(__sun)
+    || defined(__sun)                                                          \
+    || defined(__HAIKU__)
   /* utimesat() has nanosecond resolution but we stick to microseconds
    * for the sake of consistency with other platforms.
    */
@@ -796,45 +905,6 @@ done:
 }
 
 static ssize_t uv__fs_copyfile(uv_fs_t* req) {
-#if defined(__APPLE__) && !TARGET_OS_IPHONE
-  /* On macOS, use the native copyfile(3). */
-  static int can_clone;
-  copyfile_flags_t flags;
-  char buf[64];
-  size_t len;
-  int major;
-
-  flags = COPYFILE_ALL;
-
-  if (req->flags & UV_FS_COPYFILE_EXCL)
-    flags |= COPYFILE_EXCL;
-
-  /* Check OS version. Cloning is only supported on macOS >= 10.12. */
-  if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
-    if (can_clone == 0) {
-      len = sizeof(buf);
-      if (sysctlbyname("kern.osrelease", buf, &len, NULL, 0))
-        return UV__ERR(errno);
-
-      if (1 != sscanf(buf, "%d", &major))
-        abort();
-
-      can_clone = -1 + 2 * (major >= 16);  /* macOS >= 10.12 */
-    }
-
-    if (can_clone < 0)
-      return UV_ENOSYS;
-  }
-
-  /* copyfile() simply ignores COPYFILE_CLONE if it's not supported. */
-  if (req->flags & UV_FS_COPYFILE_FICLONE)
-    flags |= 1 << 24;  /* COPYFILE_CLONE */
-
-  if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE)
-    flags |= 1 << 25;  /* COPYFILE_CLONE_FORCE */
-
-  return copyfile(req->path, req->new_path, NULL, flags);
-#else
   uv_fs_t fs_req;
   uv_file srcfd;
   uv_file dstfd;
@@ -961,7 +1031,6 @@ out:
 
   errno = UV__ERR(result);
   return -1;
-#endif
 }
 
 static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
@@ -1041,10 +1110,84 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
 }
 
 
+static int uv__fs_statx(int fd,
+                        const char* path,
+                        int is_fstat,
+                        int is_lstat,
+                        uv_stat_t* buf) {
+  STATIC_ASSERT(UV_ENOSYS != -1);
+#ifdef __linux__
+  static int no_statx;
+  struct uv__statx statxbuf;
+  int dirfd;
+  int flags;
+  int mode;
+  int rc;
+
+  if (no_statx)
+    return UV_ENOSYS;
+
+  dirfd = AT_FDCWD;
+  flags = 0; /* AT_STATX_SYNC_AS_STAT */
+  mode = 0xFFF; /* STATX_BASIC_STATS + STATX_BTIME */
+
+  if (is_fstat) {
+    dirfd = fd;
+    flags |= 0x1000; /* AT_EMPTY_PATH */
+  }
+
+  if (is_lstat)
+    flags |= AT_SYMLINK_NOFOLLOW;
+
+  rc = uv__statx(dirfd, path, flags, mode, &statxbuf);
+
+  if (rc == -1) {
+    /* EPERM happens when a seccomp filter rejects the system call.
+     * Has been observed with libseccomp < 2.3.3 and docker < 18.04.
+     */
+    if (errno != EINVAL && errno != EPERM && errno != ENOSYS)
+      return -1;
+
+    no_statx = 1;
+    return UV_ENOSYS;
+  }
+
+  buf->st_dev = 256 * statxbuf.stx_dev_major + statxbuf.stx_dev_minor;
+  buf->st_mode = statxbuf.stx_mode;
+  buf->st_nlink = statxbuf.stx_nlink;
+  buf->st_uid = statxbuf.stx_uid;
+  buf->st_gid = statxbuf.stx_gid;
+  buf->st_rdev = statxbuf.stx_rdev_major;
+  buf->st_ino = statxbuf.stx_ino;
+  buf->st_size = statxbuf.stx_size;
+  buf->st_blksize = statxbuf.stx_blksize;
+  buf->st_blocks = statxbuf.stx_blocks;
+  buf->st_atim.tv_sec = statxbuf.stx_atime.tv_sec;
+  buf->st_atim.tv_nsec = statxbuf.stx_atime.tv_nsec;
+  buf->st_mtim.tv_sec = statxbuf.stx_mtime.tv_sec;
+  buf->st_mtim.tv_nsec = statxbuf.stx_mtime.tv_nsec;
+  buf->st_ctim.tv_sec = statxbuf.stx_ctime.tv_sec;
+  buf->st_ctim.tv_nsec = statxbuf.stx_ctime.tv_nsec;
+  buf->st_birthtim.tv_sec = statxbuf.stx_btime.tv_sec;
+  buf->st_birthtim.tv_nsec = statxbuf.stx_btime.tv_nsec;
+  buf->st_flags = 0;
+  buf->st_gen = 0;
+
+  return 0;
+#else
+  return UV_ENOSYS;
+#endif /* __linux__ */
+}
+
+
 static int uv__fs_stat(const char *path, uv_stat_t *buf) {
   struct stat pbuf;
   int ret;
 
+  ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 0, buf);
+  if (ret != UV_ENOSYS)
+    return ret;
+
   ret = stat(path, &pbuf);
   if (ret == 0)
     uv__to_stat(&pbuf, buf);
@@ -1057,6 +1200,10 @@ static int uv__fs_lstat(const char *path, uv_stat_t *buf) {
   struct stat pbuf;
   int ret;
 
+  ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 1, buf);
+  if (ret != UV_ENOSYS)
+    return ret;
+
   ret = lstat(path, &pbuf);
   if (ret == 0)
     uv__to_stat(&pbuf, buf);
@@ -1069,6 +1216,10 @@ static int uv__fs_fstat(int fd, uv_stat_t *buf) {
   struct stat pbuf;
   int ret;
 
+  ret = uv__fs_statx(fd, "", /* is_fstat */ 1, /* is_lstat */ 0, buf);
+  if (ret != UV_ENOSYS)
+    return ret;
+
   ret = fstat(fd, &pbuf);
   if (ret == 0)
     uv__to_stat(&pbuf, buf);
@@ -1157,7 +1308,7 @@ static void uv__fs_work(struct uv__work* w) {
     X(ACCESS, access(req->path, req->flags));
     X(CHMOD, chmod(req->path, req->mode));
     X(CHOWN, chown(req->path, req->uid, req->gid));
-    X(CLOSE, close(req->file));
+    X(CLOSE, uv__fs_close(req->file));
     X(COPYFILE, uv__fs_copyfile(req));
     X(FCHMOD, fchmod(req->file, req->mode));
     X(FCHOWN, fchown(req->file, req->uid, req->gid));
@@ -1174,6 +1325,9 @@ static void uv__fs_work(struct uv__work* w) {
     X(OPEN, uv__fs_open(req));
     X(READ, uv__fs_read(req));
     X(SCANDIR, uv__fs_scandir(req));
+    X(OPENDIR, uv__fs_opendir(req));
+    X(READDIR, uv__fs_readdir(req));
+    X(CLOSEDIR, uv__fs_closedir(req));
     X(READLINK, uv__fs_readlink(req));
     X(REALPATH, uv__fs_realpath(req));
     X(RENAME, rename(req->path, req->new_path));
@@ -1444,6 +1598,40 @@ int uv_fs_scandir(uv_loop_t* loop,
   POST;
 }
 
+int uv_fs_opendir(uv_loop_t* loop,
+                  uv_fs_t* req,
+                  const char* path,
+                  uv_fs_cb cb) {
+  INIT(OPENDIR);
+  PATH;
+  POST;
+}
+
+int uv_fs_readdir(uv_loop_t* loop,
+                  uv_fs_t* req,
+                  uv_dir_t* dir,
+                  uv_fs_cb cb) {
+  INIT(READDIR);
+
+  if (dir == NULL || dir->dir == NULL || dir->dirents == NULL)
+    return UV_EINVAL;
+
+  req->ptr = dir;
+  POST;
+}
+
+int uv_fs_closedir(uv_loop_t* loop,
+                   uv_fs_t* req,
+                   uv_dir_t* dir,
+                   uv_fs_cb cb) {
+  INIT(CLOSEDIR);
+
+  if (dir == NULL)
+    return UV_EINVAL;
+
+  req->ptr = dir;
+  POST;
+}
 
 int uv_fs_readlink(uv_loop_t* loop,
                    uv_fs_t* req,
@@ -1584,6 +1772,9 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
   req->path = NULL;
   req->new_path = NULL;
 
+  if (req->fs_type == UV_FS_READDIR && req->ptr != NULL)
+    uv__fs_readdir_cleanup(req);
+
   if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
     uv__fs_scandir_cleanup(req);
 
@@ -1591,7 +1782,7 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
     uv__free(req->bufs);
   req->bufs = NULL;
 
-  if (req->ptr != &req->statbuf)
+  if (req->fs_type != UV_FS_OPENDIR && req->ptr != &req->statbuf)
     uv__free(req->ptr);
   req->ptr = NULL;
 }
diff --git a/src/unix/fsevents.c b/src/unix/fsevents.c
index c430562..ddacda3 100644
--- a/src/unix/fsevents.c
+++ b/src/unix/fsevents.c
@@ -21,9 +21,10 @@
 #include "uv.h"
 #include "internal.h"
 
-#if TARGET_OS_IPHONE
+#if TARGET_OS_IPHONE || MAC_OS_X_VERSION_MAX_ALLOWED < 1070
 
 /* iOS (currently) doesn't provide the FSEvents-API (nor CoreServices) */
+/* macOS prior to 10.7 doesn't provide the full FSEvents API so use kqueue */
 
 int uv__fsevents_init(uv_fs_event_t* handle) {
   return 0;
diff --git a/src/unix/getaddrinfo.c b/src/unix/getaddrinfo.c
index 6d23fbe..d7ca7d1 100644
--- a/src/unix/getaddrinfo.c
+++ b/src/unix/getaddrinfo.c
@@ -92,7 +92,9 @@ int uv__getaddrinfo_translate_error(int sys_err) {
   }
   assert(!"unknown EAI_* error code");
   abort();
+#ifndef __SUNPRO_C
   return 0;  /* Pacify compiler. */
+#endif
 }
 
 
diff --git a/src/unix/haiku.c b/src/unix/haiku.c
new file mode 100644
index 0000000..7708851
--- /dev/null
+++ b/src/unix/haiku.c
@@ -0,0 +1,176 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <FindDirectory.h> /* find_path() */
+#include <OS.h>
+
+
+void uv_loadavg(double avg[3]) {
+  avg[0] = 0;
+  avg[1] = 0;
+  avg[2] = 0;
+}
+
+
+int uv_exepath(char* buffer, size_t* size) {
+  char abspath[B_PATH_NAME_LENGTH];
+  status_t status;
+  ssize_t abspath_len;
+
+  if (buffer == NULL || size == NULL || *size == 0)
+    return UV_EINVAL;
+
+  status = find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, abspath,
+                     sizeof(abspath));
+  if (status != B_OK)
+    return UV__ERR(status);
+
+  abspath_len = uv__strscpy(buffer, abspath, *size);
+  *size -= 1;
+  if (abspath_len >= 0 && *size > (size_t)abspath_len)
+    *size = (size_t)abspath_len;
+
+  return 0;
+}
+
+
+uint64_t uv_get_free_memory(void) {
+  status_t status;
+  system_info sinfo;
+
+  status = get_system_info(&sinfo);
+  if (status != B_OK)
+    return 0;
+
+  return (sinfo.max_pages - sinfo.used_pages) * B_PAGE_SIZE;
+}
+
+
+uint64_t uv_get_total_memory(void) {
+  status_t status;
+  system_info sinfo;
+
+  status = get_system_info(&sinfo);
+  if (status != B_OK)
+    return 0;
+
+  return sinfo.max_pages * B_PAGE_SIZE;
+}
+
+
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
+int uv_resident_set_memory(size_t* rss) {
+  area_info area;
+  ssize_t cookie;
+  status_t status;
+  thread_info thread;
+
+  status = get_thread_info(find_thread(NULL), &thread);
+  if (status != B_OK)
+    return UV__ERR(status);
+
+  cookie = 0;
+  *rss = 0;
+  while (get_next_area_info(thread.team, &cookie, &area) == B_OK)
+    *rss += area.ram_size;
+
+  return 0;
+}
+
+
+int uv_uptime(double* uptime) {
+  /* system_time() returns time since booting in microseconds */
+  *uptime = (double)system_time() / 1000000;
+  return 0;
+}
+
+
+int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
+  cpu_topology_node_info* topology_infos;
+  int i;
+  status_t status;
+  system_info system;
+  uint32_t topology_count;
+  uint64_t cpuspeed;
+  uv_cpu_info_t* cpu_info;
+
+  if (cpu_infos == NULL || count == NULL)
+    return UV_EINVAL;
+
+  status = get_cpu_topology_info(NULL, &topology_count);
+  if (status != B_OK)
+    return UV__ERR(status);
+
+  topology_infos = uv__malloc(topology_count * sizeof(*topology_infos));
+  if (topology_infos == NULL)
+    return UV_ENOMEM;
+
+  status = get_cpu_topology_info(topology_infos, &topology_count);
+  if (status != B_OK) {
+    uv__free(topology_infos);
+    return UV__ERR(status);
+  }
+
+  cpuspeed = 0;
+  for (i = 0; i < (int)topology_count; i++) {
+    if (topology_infos[i].type == B_TOPOLOGY_CORE) {
+      cpuspeed = topology_infos[i].data.core.default_frequency;
+      break;
+    }
+  }
+
+  uv__free(topology_infos);
+
+  status = get_system_info(&system);
+  if (status != B_OK)
+    return UV__ERR(status);
+
+  *cpu_infos = uv__calloc(system.cpu_count, sizeof(**cpu_infos));
+  if (*cpu_infos == NULL)
+    return UV_ENOMEM;
+
+  /* CPU time and model are not exposed by Haiku. */
+  cpu_info = *cpu_infos;
+  for (i = 0; i < (int)system.cpu_count; i++) {
+    cpu_info->model = uv__strdup("unknown");
+    cpu_info->speed = (int)(cpuspeed / 1000000);
+    cpu_info++;
+  }
+  *count = system.cpu_count;
+
+  return 0;
+}
+
+void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
+  int i;
+
+  for (i = 0; i < count; i++)
+    uv__free(cpu_infos[i].model);
+
+  uv__free(cpu_infos);
+}
diff --git a/src/unix/ibmi.c b/src/unix/ibmi.c
index 13fed6c..c7e1051 100644
--- a/src/unix/ibmi.c
+++ b/src/unix/ibmi.c
@@ -55,19 +55,155 @@
 #include <strings.h>
 #include <sys/vnode.h>
 
+#include <as400_protos.h>
+
+
+typedef struct {
+  int bytes_available;
+  int bytes_returned;
+  char current_date_and_time[8];
+  char system_name[8];
+  char elapsed_time[6];
+  char restricted_state_flag;
+  char reserved;
+  int percent_processing_unit_used;
+  int jobs_in_system;
+  int percent_permanent_addresses;
+  int percent_temporary_addresses;
+  int system_asp;
+  int percent_system_asp_used;
+  int total_auxiliary_storage;
+  int current_unprotected_storage_used;
+  int maximum_unprotected_storage_used;
+  int percent_db_capability;
+  int main_storage_size;
+  int number_of_partitions;
+  int partition_identifier;
+  int reserved1;
+  int current_processing_capacity;
+  char processor_sharing_attribute;
+  char reserved2[3];
+  int number_of_processors;
+  int active_jobs_in_system;
+  int active_threads_in_system;
+  int maximum_jobs_in_system;
+  int percent_temporary_256mb_segments_used;
+  int percent_temporary_4gb_segments_used;
+  int percent_permanent_256mb_segments_used;
+  int percent_permanent_4gb_segments_used;
+  int percent_current_interactive_performance;
+  int percent_uncapped_cpu_capacity_used;
+  int percent_shared_processor_pool_used;
+  long main_storage_size_long;
+} SSTS0200;
+
+
+static int get_ibmi_system_status(SSTS0200* rcvr) {
+  /* rcvrlen is input parameter 2 to QWCRSSTS */
+  unsigned int rcvrlen = sizeof(*rcvr);
+
+  /* format is input parameter 3 to QWCRSSTS ("SSTS0200" in EBCDIC) */
+  unsigned char format[] = {0xE2, 0xE2, 0xE3, 0xE2, 0xF0, 0xF2, 0xF0, 0xF0};
+
+  /* reset_status is input parameter 4 to QWCRSSTS ("*NO       " in EBCDIC) */
+  unsigned char reset_status[] = {
+    0x5C, 0xD5, 0xD6, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
+  };
+
+  /* errcode is input parameter 5 to QWCRSSTS */
+  struct _errcode {
+    int bytes_provided;
+    int bytes_available;
+    char msgid[7];
+  } errcode;
+
+  /* qwcrssts_pointer is the 16-byte tagged system pointer to QWCRSSTS */
+  ILEpointer __attribute__((aligned(16))) qwcrssts_pointer;
+
+  /* qwcrssts_argv is the array of argument pointers to QWCRSSTS */
+  void* qwcrssts_argv[6];
+
+  /* Set the IBM i pointer to the QSYS/QWCRSSTS *PGM object */
+  int rc = _RSLOBJ2(&qwcrssts_pointer, RSLOBJ_TS_PGM, "QWCRSSTS", "QSYS");
+
+  if (rc != 0)
+    return rc;
+
+  /* initialize the QWCRSSTS returned info structure */
+  memset(rcvr, 0, sizeof(*rcvr));
+
+  /* initialize the QWCRSSTS error code structure */
+  memset(&errcode, 0, sizeof(errcode));
+  errcode.bytes_provided = sizeof(errcode);
+
+  /* initialize the array of argument pointers for the QWCRSSTS API */
+  qwcrssts_argv[0] = rcvr;
+  qwcrssts_argv[1] = &rcvrlen;
+  qwcrssts_argv[2] = &format;
+  qwcrssts_argv[3] = &reset_status;
+  qwcrssts_argv[4] = &errcode;
+  qwcrssts_argv[5] = NULL;
+
+  /* Call the IBM i QWCRSSTS API from PASE */
+  rc = _PGMCALL(&qwcrssts_pointer, (void**)&qwcrssts_argv, 0);
+
+  return rc;
+}
+
+
 uint64_t uv_get_free_memory(void) {
-  return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES);
+  SSTS0200 rcvr;
+
+  if (get_ibmi_system_status(&rcvr))
+    return 0;
+
+  /* The amount of main storage, in kilobytes, in the system. */
+  uint64_t main_storage_size = rcvr.main_storage_size;
+
+  /* The current amount of storage in use for temporary objects.
+   * in millions (M) of bytes.
+   */
+  uint64_t current_unprotected_storage_used =
+    rcvr.current_unprotected_storage_used * 1024ULL;
+
+  uint64_t free_storage_size =
+    (main_storage_size - current_unprotected_storage_used) * 1024ULL;
+
+  return free_storage_size < 0 ? 0 : free_storage_size;
 }
 
 
 uint64_t uv_get_total_memory(void) {
-  return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES);
+  SSTS0200 rcvr;
+
+  if (get_ibmi_system_status(&rcvr))
+    return 0;
+
+  return (uint64_t)rcvr.main_storage_size * 1024ULL;
+}
+
+
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
 }
 
 
 void uv_loadavg(double avg[3]) {
+  SSTS0200 rcvr;
+
+  if (get_ibmi_system_status(&rcvr)) {
     avg[0] = avg[1] = avg[2] = 0;
     return;
+  }
+
+  /* The average (in tenths) of the elapsed time during which the processing
+   * units were in use. For example, a value of 411 in binary would be 41.1%.
+   * This percentage could be greater than 100% for an uncapped partition.
+   */
+  double processing_unit_used_percent =
+    rcvr.percent_processing_unit_used / 1000.0;
+
+  avg[0] = avg[1] = avg[2] = processing_unit_used_percent;
 }
 
 
@@ -111,3 +247,4 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
 
   return 0;
 }
+
diff --git a/src/unix/internal.h b/src/unix/internal.h
index c059893..8c8ddc8 100644
--- a/src/unix/internal.h
+++ b/src/unix/internal.h
@@ -95,8 +95,7 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
  */
 #if defined(__clang__) ||                                                     \
     defined(__GNUC__) ||                                                      \
-    defined(__INTEL_COMPILER) ||                                              \
-    defined(__SUNPRO_C)
+    defined(__INTEL_COMPILER)
 # define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration
 # define UV_UNUSED(declaration)     __attribute__((unused)) declaration
 #else
@@ -184,6 +183,7 @@ int uv__nonblock_ioctl(int fd, int set);
 int uv__nonblock_fcntl(int fd, int set);
 int uv__close(int fd); /* preserves errno */
 int uv__close_nocheckstdio(int fd);
+int uv__close_nocancel(int fd);
 int uv__socket(int domain, int type, int protocol);
 ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags);
 void uv__make_close_pending(uv_handle_t* handle);
@@ -306,4 +306,11 @@ UV_UNUSED(static char* uv__basename_r(const char* path)) {
 int uv__inotify_fork(uv_loop_t* loop, void* old_watchers);
 #endif
 
+typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*);
+
+int uv__getsockpeername(const uv_handle_t* handle,
+                        uv__peersockfunc func,
+                        struct sockaddr* name,
+                        int* namelen);
+
 #endif /* UV_UNIX_INTERNAL_H_ */
diff --git a/src/unix/kqueue.c b/src/unix/kqueue.c
index c24f96e..c04e7a4 100644
--- a/src/unix/kqueue.c
+++ b/src/unix/kqueue.c
@@ -59,7 +59,7 @@ int uv__kqueue_init(uv_loop_t* loop) {
 }
 
 
-#if defined(__APPLE__)
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
 static int uv__has_forked_with_cfrunloop;
 #endif
 
@@ -70,7 +70,7 @@ int uv__io_fork(uv_loop_t* loop) {
   if (err)
     return err;
 
-#if defined(__APPLE__)
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
   if (loop->cf_state != NULL) {
     /* We cannot start another CFRunloop and/or thread in the child
        process; CF aborts if you try or if you try to touch the thread
@@ -86,7 +86,7 @@ int uv__io_fork(uv_loop_t* loop) {
     uv__free(loop->cf_state);
     loop->cf_state = NULL;
   }
-#endif
+#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
   return err;
 }
 
@@ -387,6 +387,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
   uintptr_t nfds;
 
   assert(loop->watchers != NULL);
+  assert(fd >= 0);
 
   events = (struct kevent*) loop->watchers[loop->nwatchers];
   nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
@@ -457,7 +458,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
   if (uv__is_active(handle))
     return UV_EINVAL;
 
-#if defined(__APPLE__)
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
   /* Nullify field to perform checks later */
   handle->cf_cb = NULL;
   handle->realpath = NULL;
@@ -481,7 +482,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
     }
     return r;
   }
-#endif /* defined(__APPLE__) */
+#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
 
   /* TODO open asynchronously - but how do we report back errors? */
   fd = open(path, O_RDONLY);
@@ -489,8 +490,11 @@ int uv_fs_event_start(uv_fs_event_t* handle,
     return UV__ERR(errno);
 
   handle->path = uv__strdup(path);
-  if (handle->path == NULL)
+  if (handle->path == NULL) {
+    uv__close_nocheckstdio(fd);
     return UV_ENOMEM;
+  }
+
   handle->cb = cb;
   uv__handle_start(handle);
   uv__io_init(&handle->event_watcher, uv__fs_event, fd);
@@ -509,7 +513,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
 
   uv__handle_stop(handle);
 
-#if defined(__APPLE__)
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
   if (!uv__has_forked_with_cfrunloop)
     r = uv__fsevents_close(handle);
 #endif
diff --git a/src/unix/linux-core.c b/src/unix/linux-core.c
index 3341b94..b539beb 100644
--- a/src/unix/linux-core.c
+++ b/src/unix/linux-core.c
@@ -26,6 +26,7 @@
 #include "uv.h"
 #include "internal.h"
 
+#include <inttypes.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -79,16 +80,20 @@ static int read_times(FILE* statfile_fp,
                       unsigned int numcpus,
                       uv_cpu_info_t* ci);
 static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci);
-static unsigned long read_cpufreq(unsigned int cpunum);
+static uint64_t read_cpufreq(unsigned int cpunum);
 
 
 int uv__platform_loop_init(uv_loop_t* loop) {
   int fd;
 
-  fd = epoll_create1(EPOLL_CLOEXEC);
+  /* It was reported that EPOLL_CLOEXEC is not defined on Android API < 21,
+   * a.k.a. Lollipop. Since EPOLL_CLOEXEC is an alias for O_CLOEXEC on all
+   * architectures, we just use that instead.
+   */
+  fd = epoll_create1(O_CLOEXEC);
 
   /* epoll_create1() can fail either because it's not implemented (old kernel)
-   * or because it doesn't understand the EPOLL_CLOEXEC flag.
+   * or because it doesn't understand the O_CLOEXEC flag.
    */
   if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {
     fd = epoll_create(256);
@@ -141,6 +146,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
   uintptr_t nfds;
 
   assert(loop->watchers != NULL);
+  assert(fd >= 0);
 
   events = (struct epoll_event*) loop->watchers[loop->nwatchers];
   nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
@@ -714,20 +720,20 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
 static int read_times(FILE* statfile_fp,
                       unsigned int numcpus,
                       uv_cpu_info_t* ci) {
-  unsigned long clock_ticks;
   struct uv_cpu_times_s ts;
-  unsigned long user;
-  unsigned long nice;
-  unsigned long sys;
-  unsigned long idle;
-  unsigned long dummy;
-  unsigned long irq;
-  unsigned int num;
-  unsigned int len;
+  uint64_t clock_ticks;
+  uint64_t user;
+  uint64_t nice;
+  uint64_t sys;
+  uint64_t idle;
+  uint64_t dummy;
+  uint64_t irq;
+  uint64_t num;
+  uint64_t len;
   char buf[1024];
 
   clock_ticks = sysconf(_SC_CLK_TCK);
-  assert(clock_ticks != (unsigned long) -1);
+  assert(clock_ticks != (uint64_t) -1);
   assert(clock_ticks != 0);
 
   rewind(statfile_fp);
@@ -760,7 +766,8 @@ static int read_times(FILE* statfile_fp,
      * fields, they're not allowed in C89 mode.
      */
     if (6 != sscanf(buf + len,
-                    "%lu %lu %lu %lu %lu %lu",
+                    "%" PRIu64 " %" PRIu64 " %" PRIu64
+                    "%" PRIu64 " %" PRIu64 " %" PRIu64,
                     &user,
                     &nice,
                     &sys,
@@ -782,8 +789,8 @@ static int read_times(FILE* statfile_fp,
 }
 
 
-static unsigned long read_cpufreq(unsigned int cpunum) {
-  unsigned long val;
+static uint64_t read_cpufreq(unsigned int cpunum) {
+  uint64_t val;
   char buf[1024];
   FILE* fp;
 
@@ -796,7 +803,7 @@ static unsigned long read_cpufreq(unsigned int cpunum) {
   if (fp == NULL)
     return 0;
 
-  if (fscanf(fp, "%lu", &val) != 1)
+  if (fscanf(fp, "%" PRIu64, &val) != 1)
     val = 0;
 
   fclose(fp);
@@ -859,7 +866,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
     return 0;
   }
 
-  *addresses = uv__malloc(*count * sizeof(**addresses));
+  /* Make sure the memory is initiallized to zero using calloc() */
+  *addresses = uv__calloc(*count, sizeof(**addresses));
   if (!(*addresses)) {
     freeifaddrs(addrs);
     return UV_ENOMEM;
@@ -898,11 +906,12 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
     address = *addresses;
 
     for (i = 0; i < (*count); i++) {
-      if (strcmp(address->name, ent->ifa_name) == 0) {
+      size_t namelen = strlen(ent->ifa_name);
+      /* Alias interface share the same physical address */
+      if (strncmp(address->name, ent->ifa_name, namelen) == 0 &&
+          (address->name[namelen] == 0 || address->name[namelen] == ':')) {
         sll = (struct sockaddr_ll*)ent->ifa_addr;
         memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr));
-      } else {
-        memset(address->phys_addr, 0, sizeof(address->phys_addr));
       }
       address++;
     }
@@ -932,3 +941,114 @@ void uv__set_process_title(const char* title) {
   prctl(PR_SET_NAME, title);  /* Only copies first 16 characters. */
 #endif
 }
+
+
+static uint64_t uv__read_proc_meminfo(const char* what) {
+  uint64_t rc;
+  ssize_t n;
+  char* p;
+  int fd;
+  char buf[4096];  /* Large enough to hold all of /proc/meminfo. */
+
+  rc = 0;
+  fd = uv__open_cloexec("/proc/meminfo", O_RDONLY);
+
+  if (fd == -1)
+    return 0;
+
+  n = read(fd, buf, sizeof(buf) - 1);
+
+  if (n <= 0)
+    goto out;
+
+  buf[n] = '\0';
+  p = strstr(buf, what);
+
+  if (p == NULL)
+    goto out;
+
+  p += strlen(what);
+
+  if (1 != sscanf(p, "%" PRIu64 " kB", &rc))
+    goto out;
+
+  rc *= 1024;
+
+out:
+
+  if (uv__close_nocheckstdio(fd))
+    abort();
+
+  return rc;
+}
+
+
+uint64_t uv_get_free_memory(void) {
+  struct sysinfo info;
+  uint64_t rc;
+
+  rc = uv__read_proc_meminfo("MemFree:");
+
+  if (rc != 0)
+    return rc;
+
+  if (0 == sysinfo(&info))
+    return (uint64_t) info.freeram * info.mem_unit;
+
+  return 0;
+}
+
+
+uint64_t uv_get_total_memory(void) {
+  struct sysinfo info;
+  uint64_t rc;
+
+  rc = uv__read_proc_meminfo("MemTotal:");
+
+  if (rc != 0)
+    return rc;
+
+  if (0 == sysinfo(&info))
+    return (uint64_t) info.totalram * info.mem_unit;
+
+  return 0;
+}
+
+
+static uint64_t uv__read_cgroups_uint64(const char* cgroup, const char* param) {
+  char filename[256];
+  uint64_t rc;
+  int fd;
+  ssize_t n;
+  char buf[32];  /* Large enough to hold an encoded uint64_t. */
+
+  snprintf(filename, 256, "/sys/fs/cgroup/%s/%s", cgroup, param);
+
+  rc = 0;
+  fd = uv__open_cloexec(filename, O_RDONLY);
+
+  if (fd < 0)
+    return 0;
+
+  n = read(fd, buf, sizeof(buf) - 1);
+
+  if (n > 0) {
+    buf[n] = '\0';
+    sscanf(buf, "%" PRIu64, &rc);
+  }
+
+  if (uv__close_nocheckstdio(fd))
+    abort();
+
+  return rc;
+}
+
+
+uint64_t uv_get_constrained_memory(void) {
+  /*
+   * This might return 0 if there was a problem getting the memory limit from
+   * cgroups. This is OK because a return value of 0 signifies that the memory
+   * limit is unknown.
+   */
+  return uv__read_cgroups_uint64("memory", "memory.limit_in_bytes");
+}
diff --git a/src/unix/linux-syscalls.c b/src/unix/linux-syscalls.c
index bfd7544..5637cf9 100644
--- a/src/unix/linux-syscalls.c
+++ b/src/unix/linux-syscalls.c
@@ -187,6 +187,21 @@
 # endif
 #endif /* __NR_pwritev */
 
+#ifndef __NR_statx
+# if defined(__x86_64__)
+#  define __NR_statx 332
+# elif defined(__i386__)
+#  define __NR_statx 383
+# elif defined(__aarch64__)
+#  define __NR_statx 397
+# elif defined(__arm__)
+#  define __NR_statx (UV_SYSCALL_BASE + 397)
+# elif defined(__ppc__)
+#  define __NR_statx 383
+# elif defined(__s390__)
+#  define __NR_statx 379
+# endif
+#endif /* __NR_statx */
 
 int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
 #if defined(__i386__)
@@ -336,3 +351,19 @@ int uv__dup3(int oldfd, int newfd, int flags) {
   return errno = ENOSYS, -1;
 #endif
 }
+
+
+int uv__statx(int dirfd,
+              const char* path,
+              int flags,
+              unsigned int mask,
+              struct uv__statx* statxbuf) {
+  /* __NR_statx make Android box killed by SIGSYS.
+   * That looks like a seccomp2 sandbox filter rejecting the system call.
+   */
+#if defined(__NR_statx) && !defined(__ANDROID__)
+  return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf);
+#else
+  return errno = ENOSYS, -1;
+#endif
+}
diff --git a/src/unix/linux-syscalls.h b/src/unix/linux-syscalls.h
index 3dfd329..7e58bfa 100644
--- a/src/unix/linux-syscalls.h
+++ b/src/unix/linux-syscalls.h
@@ -80,6 +80,36 @@
 #define UV__IN_DELETE_SELF    0x400
 #define UV__IN_MOVE_SELF      0x800
 
+struct uv__statx_timestamp {
+  int64_t tv_sec;
+  uint32_t tv_nsec;
+  int32_t unused0;
+};
+
+struct uv__statx {
+  uint32_t stx_mask;
+  uint32_t stx_blksize;
+  uint64_t stx_attributes;
+  uint32_t stx_nlink;
+  uint32_t stx_uid;
+  uint32_t stx_gid;
+  uint16_t stx_mode;
+  uint16_t unused0;
+  uint64_t stx_ino;
+  uint64_t stx_size;
+  uint64_t stx_blocks;
+  uint64_t stx_attributes_mask;
+  struct uv__statx_timestamp stx_atime;
+  struct uv__statx_timestamp stx_btime;
+  struct uv__statx_timestamp stx_ctime;
+  struct uv__statx_timestamp stx_mtime;
+  uint32_t stx_rdev_major;
+  uint32_t stx_rdev_minor;
+  uint32_t stx_dev_major;
+  uint32_t stx_dev_minor;
+  uint64_t unused1[14];
+};
+
 struct uv__inotify_event {
   int32_t wd;
   uint32_t mask;
@@ -113,5 +143,10 @@ int uv__sendmmsg(int fd,
 ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
 ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
 int uv__dup3(int oldfd, int newfd, int flags);
+int uv__statx(int dirfd,
+              const char* path,
+              int flags,
+              unsigned int mask,
+              struct uv__statx* statxbuf);
 
 #endif /* UV_LINUX_SYSCALL_H_ */
diff --git a/src/unix/netbsd.c b/src/unix/netbsd.c
index a2a4e52..c649bb3 100644
--- a/src/unix/netbsd.c
+++ b/src/unix/netbsd.c
@@ -126,6 +126,11 @@ uint64_t uv_get_total_memory(void) {
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 int uv_resident_set_memory(size_t* rss) {
   kvm_t *kd = NULL;
   struct kinfo_proc2 *kinfo = NULL;
diff --git a/src/unix/openbsd.c b/src/unix/openbsd.c
index bffb58b..ffae768 100644
--- a/src/unix/openbsd.c
+++ b/src/unix/openbsd.c
@@ -136,6 +136,11 @@ uint64_t uv_get_total_memory(void) {
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 int uv_resident_set_memory(size_t* rss) {
   struct kinfo_proc kinfo;
   size_t page_size = getpagesize();
diff --git a/src/unix/os390.c b/src/unix/os390.c
index dc146e3..273ded7 100644
--- a/src/unix/os390.c
+++ b/src/unix/os390.c
@@ -356,6 +356,11 @@ uint64_t uv_get_total_memory(void) {
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 int uv_resident_set_memory(size_t* rss) {
   char* ascb;
   char* rax;
@@ -657,6 +662,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
   uintptr_t nfds;
 
   assert(loop->watchers != NULL);
+  assert(fd >= 0);
 
   events = (struct epoll_event*) loop->watchers[loop->nwatchers];
   nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
diff --git a/src/unix/pipe.c b/src/unix/pipe.c
index d3b554c..8347668 100644
--- a/src/unix/pipe.c
+++ b/src/unix/pipe.c
@@ -215,7 +215,7 @@ void uv_pipe_connect(uv_connect_t* req,
   }
 
   if (err == 0)
-    uv__io_start(handle->loop, &handle->io_watcher, POLLIN | POLLOUT);
+    uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
 
 out:
   handle->delayed_error = err;
@@ -233,9 +233,6 @@ out:
 }
 
 
-typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*);
-
-
 static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
                                     uv__peersockfunc func,
                                     char* buffer,
@@ -246,10 +243,13 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
 
   addrlen = sizeof(sa);
   memset(&sa, 0, addrlen);
-  err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen);
+  err = uv__getsockpeername((const uv_handle_t*) handle,
+                            func,
+                            (struct sockaddr*) &sa,
+                            (int*) &addrlen);
   if (err < 0) {
     *size = 0;
-    return UV__ERR(errno);
+    return err;
   }
 
 #if defined(__linux__)
diff --git a/src/unix/posix-poll.c b/src/unix/posix-poll.c
index f3181f9..a3b9f21 100644
--- a/src/unix/posix-poll.c
+++ b/src/unix/posix-poll.c
@@ -298,6 +298,8 @@ update_timeout:
 void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
   size_t i;
 
+  assert(fd >= 0);
+
   if (loop->poll_fds_iterating) {
     /* uv__io_poll is currently iterating.  Just invalidate fd.  */
     for (i = 0; i < loop->poll_fds_used; i++)
diff --git a/src/unix/process.c b/src/unix/process.c
index 101c9c5..e29bf15 100644
--- a/src/unix/process.c
+++ b/src/unix/process.c
@@ -315,7 +315,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
         use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR);
         close_fd = use_fd;
 
-        if (use_fd == -1) {
+        if (use_fd < 0) {
           uv__write_int(error_fd, UV__ERR(errno));
           _exit(127);
         }
@@ -385,6 +385,11 @@ static void uv__process_child_init(const uv_process_options_t* options,
     if (n == SIGKILL || n == SIGSTOP)
       continue;  /* Can't be changed. */
 
+#if defined(__HAIKU__)
+    if (n == SIGKILLTHR)
+      continue;  /* Can't be changed. */
+#endif
+
     if (SIG_ERR != signal(n, SIG_DFL))
       continue;
 
@@ -431,6 +436,8 @@ int uv_spawn(uv_loop_t* loop,
                               UV_PROCESS_SETGID |
                               UV_PROCESS_SETUID |
                               UV_PROCESS_WINDOWS_HIDE |
+                              UV_PROCESS_WINDOWS_HIDE_CONSOLE |
+                              UV_PROCESS_WINDOWS_HIDE_GUI |
                               UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
 
   uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
diff --git a/src/unix/stream.c b/src/unix/stream.c
index a75ba15..17b06a3 100644
--- a/src/unix/stream.c
+++ b/src/unix/stream.c
@@ -745,13 +745,13 @@ static int uv__write_req_update(uv_stream_t* stream,
 
   buf = req->bufs + req->write_index;
 
-  while (n > 0) {
+  do {
     len = n < buf->len ? n : buf->len;
     buf->base += len;
     buf->len -= len;
     buf += (buf->len == 0);  /* Advance to next buffer if this one is empty. */
     n -= len;
-  }
+  } while (n > 0);
 
   req->write_index = buf - req->bufs;
 
@@ -897,7 +897,7 @@ start:
     goto error;
   }
 
-  if (n > 0 && uv__write_req_update(stream, req, n)) {
+  if (n >= 0 && uv__write_req_update(stream, req, n)) {
     uv__write_req_finish(req);
     return;  /* TODO(bnoordhuis) Start trying to write the next request. */
   }
@@ -1541,7 +1541,7 @@ int uv_try_write(uv_stream_t* stream,
   }
 
   if (written == 0 && req_size != 0)
-    return UV_EAGAIN;
+    return req.error < 0 ? req.error : UV_EAGAIN;
   else
     return written;
 }
diff --git a/src/unix/sunos.c b/src/unix/sunos.c
index 2552a01..f323d1d 100644
--- a/src/unix/sunos.c
+++ b/src/unix/sunos.c
@@ -117,6 +117,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
   uintptr_t nfds;
 
   assert(loop->watchers != NULL);
+  assert(fd >= 0);
 
   events = (struct port_event*) loop->watchers[loop->nwatchers];
   nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
@@ -134,8 +135,10 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
   if (port_associate(loop->backend_fd, PORT_SOURCE_FD, fd, POLLIN, 0))
     return UV__ERR(errno);
 
-  if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd))
+  if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd)) {
+    perror("(libuv) port_dissociate()");
     abort();
+  }
 
   return 0;
 }
@@ -173,8 +176,14 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
     w = QUEUE_DATA(q, uv__io_t, watcher_queue);
     assert(w->pevents != 0);
 
-    if (port_associate(loop->backend_fd, PORT_SOURCE_FD, w->fd, w->pevents, 0))
+    if (port_associate(loop->backend_fd,
+                       PORT_SOURCE_FD,
+                       w->fd,
+                       w->pevents,
+                       0)) {
+      perror("(libuv) port_associate()");
       abort();
+    }
 
     w->events = w->pevents;
   }
@@ -218,10 +227,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
       /* Work around another kernel bug: port_getn() may return events even
        * on error.
        */
-      if (errno == EINTR || errno == ETIME)
+      if (errno == EINTR || errno == ETIME) {
         saved_errno = errno;
-      else
+      } else {
+        perror("(libuv) port_getn()");
         abort();
+      }
     }
 
     /* Update loop->time unconditionally. It's tempting to skip the update when
@@ -369,6 +380,11 @@ uint64_t uv_get_total_memory(void) {
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 void uv_loadavg(double avg[3]) {
   (void) getloadavg(avg, 3);
 }
diff --git a/src/unix/tcp.c b/src/unix/tcp.c
index 2982851..8cedcd6 100644
--- a/src/unix/tcp.c
+++ b/src/unix/tcp.c
@@ -82,7 +82,7 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
         handle->flags |= flags;
         return 0;
       }
-      
+
       /* Query to see if tcp socket is bound. */
       slen = sizeof(saddr);
       memset(&saddr, 0, sizeof(saddr));
@@ -235,12 +235,16 @@ int uv__tcp_connect(uv_connect_t* req,
   if (r == -1 && errno != 0) {
     if (errno == EINPROGRESS)
       ; /* not an error */
-    else if (errno == ECONNREFUSED)
-    /* If we get a ECONNREFUSED wait until the next tick to report the
-     * error. Solaris wants to report immediately--other unixes want to
-     * wait.
+    else if (errno == ECONNREFUSED
+#if defined(__OpenBSD__)
+      || errno == EINVAL
+#endif
+      )
+    /* If we get ECONNREFUSED (Solaris) or EINVAL (OpenBSD) wait until the
+     * next tick to report the error. Solaris and OpenBSD wants to report
+     * immediately -- other unixes want to wait.
      */
-      handle->delayed_error = UV__ERR(errno);
+      handle->delayed_error = UV__ERR(ECONNREFUSED);
     else
       return UV__ERR(errno);
   }
@@ -279,44 +283,28 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
 int uv_tcp_getsockname(const uv_tcp_t* handle,
                        struct sockaddr* name,
                        int* namelen) {
-  socklen_t socklen;
 
   if (handle->delayed_error)
     return handle->delayed_error;
 
-  if (uv__stream_fd(handle) < 0)
-    return UV_EINVAL;  /* FIXME(bnoordhuis) UV_EBADF */
-
-  /* sizeof(socklen_t) != sizeof(int) on some systems. */
-  socklen = (socklen_t) *namelen;
-
-  if (getsockname(uv__stream_fd(handle), name, &socklen))
-    return UV__ERR(errno);
-
-  *namelen = (int) socklen;
-  return 0;
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getsockname,
+                             name,
+                             namelen);
 }
 
 
 int uv_tcp_getpeername(const uv_tcp_t* handle,
                        struct sockaddr* name,
                        int* namelen) {
-  socklen_t socklen;
 
   if (handle->delayed_error)
     return handle->delayed_error;
 
-  if (uv__stream_fd(handle) < 0)
-    return UV_EINVAL;  /* FIXME(bnoordhuis) UV_EBADF */
-
-  /* sizeof(socklen_t) != sizeof(int) on some systems. */
-  socklen = (socklen_t) *namelen;
-
-  if (getpeername(uv__stream_fd(handle), name, &socklen))
-    return UV__ERR(errno);
-
-  *namelen = (int) socklen;
-  return 0;
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getpeername,
+                             name,
+                             namelen);
 }
 
 
diff --git a/src/unix/thread.c b/src/unix/thread.c
index 2900470..cd0b7aa 100644
--- a/src/unix/thread.c
+++ b/src/unix/thread.c
@@ -48,8 +48,10 @@
 STATIC_ASSERT(sizeof(uv_barrier_t) == sizeof(pthread_barrier_t));
 #endif
 
-/* Note: guard clauses should match uv_barrier_t's in include/uv/uv-unix.h. */
-#if defined(_AIX) || !defined(PTHREAD_BARRIER_SERIAL_THREAD)
+/* Note: guard clauses should match uv_barrier_t's in include/uv/unix.h. */
+#if defined(_AIX) || \
+    defined(__OpenBSD__) || \
+    !defined(PTHREAD_BARRIER_SERIAL_THREAD)
 int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
   struct _uv_barrier* b;
   int rc;
@@ -176,8 +178,21 @@ static size_t thread_stack_size(void) {
   if (lim.rlim_cur != RLIM_INFINITY) {
     /* pthread_attr_setstacksize() expects page-aligned values. */
     lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize();
-    if (lim.rlim_cur >= PTHREAD_STACK_MIN)
-      return lim.rlim_cur;
+
+    /* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is
+     * too small to safely receive signals on.
+     *
+     * Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has
+     * the largest MINSIGSTKSZ of the architectures that musl supports) so
+     * let's use that as a lower bound.
+     *
+     * We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ
+     * is between 28 and 133 KB when compiling against glibc, depending
+     * on the architecture.
+     */
+    if (lim.rlim_cur >= 8192)
+      if (lim.rlim_cur >= PTHREAD_STACK_MIN)
+        return lim.rlim_cur;
   }
 #endif
 
@@ -192,13 +207,36 @@ static size_t thread_stack_size(void) {
 
 
 int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
+  uv_thread_options_t params;
+  params.flags = UV_THREAD_NO_FLAGS;
+  return uv_thread_create_ex(tid, &params, entry, arg);
+}
+
+int uv_thread_create_ex(uv_thread_t* tid,
+                        const uv_thread_options_t* params,
+                        void (*entry)(void *arg),
+                        void *arg) {
   int err;
-  size_t stack_size;
   pthread_attr_t* attr;
   pthread_attr_t attr_storage;
+  size_t pagesize;
+  size_t stack_size;
+
+  stack_size =
+      params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
 
   attr = NULL;
-  stack_size = thread_stack_size();
+  if (stack_size == 0) {
+    stack_size = thread_stack_size();
+  } else {
+    pagesize = (size_t)getpagesize();
+    /* Round up to the nearest page boundary. */
+    stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
+#ifdef PTHREAD_STACK_MIN
+    if (stack_size < PTHREAD_STACK_MIN)
+      stack_size = PTHREAD_STACK_MIN;
+#endif
+  }
 
   if (stack_size > 0) {
     attr = &attr_storage;
@@ -778,7 +816,9 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
     return UV_ETIMEDOUT;
 
   abort();
+#ifndef __SUNPRO_C
   return UV_EINVAL;  /* Satisfy the compiler. */
+#endif
 }
 
 
diff --git a/src/unix/udp.c b/src/unix/udp.c
index ec337ec..b578e7b 100644
--- a/src/unix/udp.c
+++ b/src/unix/udp.c
@@ -30,6 +30,7 @@
 #if defined(__MVS__)
 #include <xti.h>
 #endif
+#include <sys/un.h>
 
 #if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP)
 # define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
@@ -227,9 +228,22 @@ static void uv__udp_sendmsg(uv_udp_t* handle) {
     assert(req != NULL);
 
     memset(&h, 0, sizeof h);
-    h.msg_name = &req->addr;
-    h.msg_namelen = (req->addr.ss_family == AF_INET6 ?
-      sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
+    if (req->addr.ss_family == AF_UNSPEC) {
+      h.msg_name = NULL;
+      h.msg_namelen = 0;
+    } else {
+      h.msg_name = &req->addr;
+      if (req->addr.ss_family == AF_INET6)
+        h.msg_namelen = sizeof(struct sockaddr_in6);
+      else if (req->addr.ss_family == AF_INET)
+        h.msg_namelen = sizeof(struct sockaddr_in);
+      else if (req->addr.ss_family == AF_UNIX)
+        h.msg_namelen = sizeof(struct sockaddr_un);
+      else {
+        assert(0 && "unsupported address family");
+        abort();
+      }
+    }
     h.msg_iov = (struct iovec*) req->bufs;
     h.msg_iovlen = req->nbufs;
 
@@ -263,16 +277,30 @@ static void uv__udp_sendmsg(uv_udp_t* handle) {
  * are different from the BSDs: it _shares_ the port rather than steal it
  * from the current listener.  While useful, it's not something we can emulate
  * on other platforms so we don't enable it.
+ *
+ * zOS does not support getsockname with SO_REUSEPORT option when using
+ * AF_UNIX.
  */
 static int uv__set_reuse(int fd) {
   int yes;
-
-#if defined(SO_REUSEPORT) && !defined(__linux__)
   yes = 1;
+
+#if defined(SO_REUSEPORT) && defined(__MVS__)
+  struct sockaddr_in sockfd;
+  unsigned int sockfd_len = sizeof(sockfd);
+  if (getsockname(fd, (struct sockaddr*) &sockfd, &sockfd_len) == -1)
+      return UV__ERR(errno);
+  if (sockfd.sin_family == AF_UNIX) {
+    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
+      return UV__ERR(errno);
+  } else {
+    if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
+       return UV__ERR(errno);
+  }
+#elif defined(SO_REUSEPORT) && !defined(__linux__)
   if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
     return UV__ERR(errno);
 #else
-  yes = 1;
   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
     return UV__ERR(errno);
 #endif
@@ -383,6 +411,50 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
 }
 
 
+int uv__udp_connect(uv_udp_t* handle,
+                    const struct sockaddr* addr,
+                    unsigned int addrlen) {
+  int err;
+
+  err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
+  if (err)
+    return err;
+
+  do {
+    errno = 0;
+    err = connect(handle->io_watcher.fd, addr, addrlen);
+  } while (err == -1 && errno == EINTR);
+
+  if (err)
+    return UV__ERR(errno);
+
+  handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
+  return 0;
+}
+
+
+int uv__udp_disconnect(uv_udp_t* handle) {
+    int r;
+    struct sockaddr addr;
+
+    memset(&addr, 0, sizeof(addr));
+
+    addr.sa_family = AF_UNSPEC;
+
+    do {
+      errno = 0;
+      r = connect(handle->io_watcher.fd, &addr, sizeof(addr));
+    } while (r == -1 && errno == EINTR);
+
+    if (r == -1 && errno != EAFNOSUPPORT)
+      return UV__ERR(errno);
+
+    handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
+    return 0;
+}
+
+
 int uv__udp_send(uv_udp_send_t* req,
                  uv_udp_t* handle,
                  const uv_buf_t bufs[],
@@ -395,9 +467,11 @@ int uv__udp_send(uv_udp_send_t* req,
 
   assert(nbufs > 0);
 
-  err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
-  if (err)
-    return err;
+  if (addr) {
+    err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
+    if (err)
+      return err;
+  }
 
   /* It's legal for send_queue_count > 0 even when the write_queue is empty;
    * it means there are error-state requests in the write_completed_queue that
@@ -407,7 +481,10 @@ int uv__udp_send(uv_udp_send_t* req,
 
   uv__req_init(handle->loop, req, UV_UDP_SEND);
   assert(addrlen <= sizeof(req->addr));
-  memcpy(&req->addr, addr, addrlen);
+  if (addr == NULL)
+    req->addr.ss_family = AF_UNSPEC;
+  else
+    memcpy(&req->addr, addr, addrlen);
   req->send_cb = send_cb;
   req->handle = handle;
   req->nbufs = nbufs;
@@ -459,9 +536,13 @@ int uv__udp_try_send(uv_udp_t* handle,
   if (handle->send_queue_count != 0)
     return UV_EAGAIN;
 
-  err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
-  if (err)
-    return err;
+  if (addr) {
+    err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
+    if (err)
+      return err;
+  } else {
+    assert(handle->flags & UV_HANDLE_UDP_CONNECTED);
+  }
 
   memset(&h, 0, sizeof h);
   h.msg_name = (struct sockaddr*) addr;
@@ -608,6 +689,7 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
   uv__io_init(&handle->io_watcher, uv__udp_io, fd);
   QUEUE_INIT(&handle->write_queue);
   QUEUE_INIT(&handle->write_completed_queue);
+
   return 0;
 }
 
@@ -636,6 +718,9 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
     return err;
 
   handle->io_watcher.fd = sock;
+  if (uv__udp_is_connected(handle))
+    handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
   return 0;
 }
 
@@ -743,13 +828,17 @@ int uv_udp_set_ttl(uv_udp_t* handle, int ttl) {
                         IPV6_UNICAST_HOPS,
                         &ttl,
                         sizeof(ttl));
-#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
-          defined(__MVS__) */
+
+#else /* !(defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
+           defined(__MVS__)) */
 
   return uv__setsockopt_maybe_char(handle,
                                    IP_TTL,
                                    IPV6_UNICAST_HOPS,
                                    ttl);
+
+#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
+          defined(__MVS__) */
 }
 
 
@@ -851,23 +940,24 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
   return 0;
 }
 
-
-int uv_udp_getsockname(const uv_udp_t* handle,
+int uv_udp_getpeername(const uv_udp_t* handle,
                        struct sockaddr* name,
                        int* namelen) {
-  socklen_t socklen;
-
-  if (handle->io_watcher.fd == -1)
-    return UV_EINVAL;  /* FIXME(bnoordhuis) UV_EBADF */
 
-  /* sizeof(socklen_t) != sizeof(int) on some systems. */
-  socklen = (socklen_t) *namelen;
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getpeername,
+                             name,
+                             namelen);
+}
 
-  if (getsockname(handle->io_watcher.fd, name, &socklen))
-    return UV__ERR(errno);
+int uv_udp_getsockname(const uv_udp_t* handle,
+                       struct sockaddr* name,
+                       int* namelen) {
 
-  *namelen = (int) socklen;
-  return 0;
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getsockname,
+                             name,
+                             namelen);
 }
 
 
diff --git a/src/uv-common.c b/src/uv-common.c
index 952bde0..066eb31 100644
--- a/src/uv-common.c
+++ b/src/uv-common.c
@@ -34,6 +34,7 @@
 # include <malloc.h> /* malloc */
 #else
 # include <net/if.h> /* if_nametoindex */
+# include <sys/un.h> /* AF_UNIX, sockaddr_un */
 #endif
 
 
@@ -222,6 +223,9 @@ int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) {
   memset(addr, 0, sizeof(*addr));
   addr->sin6_family = AF_INET6;
   addr->sin6_port = htons(port);
+#ifdef SIN6_LEN
+  addr->sin6_len = sizeof(*addr);
+#endif
 
   zone_index = strchr(ip, '%');
   if (zone_index != NULL) {
@@ -314,17 +318,20 @@ int uv_tcp_connect(uv_connect_t* req,
 }
 
 
-int uv_udp_send(uv_udp_send_t* req,
-                uv_udp_t* handle,
-                const uv_buf_t bufs[],
-                unsigned int nbufs,
-                const struct sockaddr* addr,
-                uv_udp_send_cb send_cb) {
+int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr) {
   unsigned int addrlen;
 
   if (handle->type != UV_UDP)
     return UV_EINVAL;
 
+  /* Disconnect the handle */
+  if (addr == NULL) {
+    if (!(handle->flags & UV_HANDLE_UDP_CONNECTED))
+      return UV_ENOTCONN;
+
+    return uv__udp_disconnect(handle);
+  }
+
   if (addr->sa_family == AF_INET)
     addrlen = sizeof(struct sockaddr_in);
   else if (addr->sa_family == AF_INET6)
@@ -332,6 +339,70 @@ int uv_udp_send(uv_udp_send_t* req,
   else
     return UV_EINVAL;
 
+  if (handle->flags & UV_HANDLE_UDP_CONNECTED)
+    return UV_EISCONN;
+
+  return uv__udp_connect(handle, addr, addrlen);
+}
+
+
+int uv__udp_is_connected(uv_udp_t* handle) {
+  struct sockaddr_storage addr;
+  int addrlen;
+  if (handle->type != UV_UDP)
+    return 0;
+
+  addrlen = sizeof(addr);
+  if (uv_udp_getpeername(handle, (struct sockaddr*) &addr, &addrlen) != 0)
+    return 0;
+
+  return addrlen > 0;
+}
+
+
+int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) {
+  unsigned int addrlen;
+
+  if (handle->type != UV_UDP)
+    return UV_EINVAL;
+
+  if (addr != NULL && (handle->flags & UV_HANDLE_UDP_CONNECTED))
+    return UV_EISCONN;
+
+  if (addr == NULL && !(handle->flags & UV_HANDLE_UDP_CONNECTED))
+    return UV_EDESTADDRREQ;
+
+  if (addr != NULL) {
+    if (addr->sa_family == AF_INET)
+      addrlen = sizeof(struct sockaddr_in);
+    else if (addr->sa_family == AF_INET6)
+      addrlen = sizeof(struct sockaddr_in6);
+#if defined(AF_UNIX) && !defined(_WIN32)
+    else if (addr->sa_family == AF_UNIX)
+      addrlen = sizeof(struct sockaddr_un);
+#endif
+    else
+      return UV_EINVAL;
+  } else {
+    addrlen = 0;
+  }
+
+  return addrlen;
+}
+
+
+int uv_udp_send(uv_udp_send_t* req,
+                uv_udp_t* handle,
+                const uv_buf_t bufs[],
+                unsigned int nbufs,
+                const struct sockaddr* addr,
+                uv_udp_send_cb send_cb) {
+  int addrlen;
+
+  addrlen = uv__udp_check_before_send(handle, addr);
+  if (addrlen < 0)
+    return addrlen;
+
   return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
 }
 
@@ -340,17 +411,11 @@ int uv_udp_try_send(uv_udp_t* handle,
                     const uv_buf_t bufs[],
                     unsigned int nbufs,
                     const struct sockaddr* addr) {
-  unsigned int addrlen;
-
-  if (handle->type != UV_UDP)
-    return UV_EINVAL;
+  int addrlen;
 
-  if (addr->sa_family == AF_INET)
-    addrlen = sizeof(struct sockaddr_in);
-  else if (addr->sa_family == AF_INET6)
-    addrlen = sizeof(struct sockaddr_in6);
-  else
-    return UV_EINVAL;
+  addrlen = uv__udp_check_before_send(handle, addr);
+  if (addrlen < 0)
+    return addrlen;
 
   return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen);
 }
@@ -571,37 +636,66 @@ int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
   dent = dents[(*nbufs)++];
 
   ent->name = dent->d_name;
+  ent->type = uv__fs_get_dirent_type(dent);
+
+  return 0;
+}
+
+uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent) {
+  uv_dirent_type_t type;
+
 #ifdef HAVE_DIRENT_TYPES
   switch (dent->d_type) {
     case UV__DT_DIR:
-      ent->type = UV_DIRENT_DIR;
+      type = UV_DIRENT_DIR;
       break;
     case UV__DT_FILE:
-      ent->type = UV_DIRENT_FILE;
+      type = UV_DIRENT_FILE;
       break;
     case UV__DT_LINK:
-      ent->type = UV_DIRENT_LINK;
+      type = UV_DIRENT_LINK;
       break;
     case UV__DT_FIFO:
-      ent->type = UV_DIRENT_FIFO;
+      type = UV_DIRENT_FIFO;
       break;
     case UV__DT_SOCKET:
-      ent->type = UV_DIRENT_SOCKET;
+      type = UV_DIRENT_SOCKET;
       break;
     case UV__DT_CHAR:
-      ent->type = UV_DIRENT_CHAR;
+      type = UV_DIRENT_CHAR;
       break;
     case UV__DT_BLOCK:
-      ent->type = UV_DIRENT_BLOCK;
+      type = UV_DIRENT_BLOCK;
       break;
     default:
-      ent->type = UV_DIRENT_UNKNOWN;
+      type = UV_DIRENT_UNKNOWN;
   }
 #else
-  ent->type = UV_DIRENT_UNKNOWN;
+  type = UV_DIRENT_UNKNOWN;
 #endif
 
-  return 0;
+  return type;
+}
+
+void uv__fs_readdir_cleanup(uv_fs_t* req) {
+  uv_dir_t* dir;
+  uv_dirent_t* dirents;
+  int i;
+
+  if (req->ptr == NULL)
+    return;
+
+  dir = req->ptr;
+  dirents = dir->dirents;
+  req->ptr = NULL;
+
+  if (dirents == NULL)
+    return;
+
+  for (i = 0; i < req->result; ++i) {
+    uv__free((char*) dirents[i].name);
+    dirents[i].name = NULL;
+  }
 }
 
 
diff --git a/src/uv-common.h b/src/uv-common.h
index 15ac4d0..f788161 100644
--- a/src/uv-common.h
+++ b/src/uv-common.h
@@ -103,6 +103,7 @@ enum {
 
   /* Only used by uv_udp_t handles. */
   UV_HANDLE_UDP_PROCESSING              = 0x01000000,
+  UV_HANDLE_UDP_CONNECTED               = 0x02000000,
 
   /* Only used by uv_pipe_t handles. */
   UV_HANDLE_NON_OVERLAPPED_PIPE         = 0x01000000,
@@ -142,6 +143,14 @@ int uv__udp_bind(uv_udp_t* handle,
                  unsigned int  addrlen,
                  unsigned int flags);
 
+int uv__udp_connect(uv_udp_t* handle,
+                    const struct sockaddr* addr,
+                    unsigned int addrlen);
+
+int uv__udp_disconnect(uv_udp_t* handle);
+
+int uv__udp_is_connected(uv_udp_t* handle);
+
 int uv__udp_send(uv_udp_send_t* req,
                  uv_udp_t* handle,
                  const uv_buf_t bufs[],
@@ -184,6 +193,8 @@ size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs);
 int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value);
 
 void uv__fs_scandir_cleanup(uv_fs_t* req);
+void uv__fs_readdir_cleanup(uv_fs_t* req);
+uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent);
 
 int uv__next_timeout(const uv_loop_t* loop);
 void uv__run_timers(uv_loop_t* loop);
diff --git a/src/uv-data-getter-setters.c b/src/uv-data-getter-setters.c
index b7fcd4a..c302566 100644
--- a/src/uv-data-getter-setters.c
+++ b/src/uv-data-getter-setters.c
@@ -36,7 +36,7 @@ const char* uv_req_type_name(uv_req_type type) {
   case UV_REQ_TYPE_MAX:
   case UV_UNKNOWN_REQ:
   default: /* UV_REQ_TYPE_PRIVATE */
-     return NULL;
+    break;
   }
   return NULL;
 }
diff --git a/src/win/core.c b/src/win/core.c
index bf80d77..e9d0a58 100644
--- a/src/win/core.c
+++ b/src/win/core.c
@@ -623,3 +623,30 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
 
   return 0;
 }
+
+int uv_cpumask_size(void) {
+  return (int)(sizeof(DWORD_PTR) * 8);
+}
+
+int uv__getsockpeername(const uv_handle_t* handle,
+                        uv__peersockfunc func,
+                        struct sockaddr* name,
+                        int* namelen,
+                        int delayed_error) {
+
+  int result;
+  uv_os_fd_t fd;
+
+  result = uv_fileno(handle, &fd);
+  if (result != 0)
+    return result;
+
+  if (delayed_error)
+    return uv_translate_sys_error(delayed_error);
+
+  result = func((SOCKET) fd, name, namelen);
+  if (result != 0)
+    return uv_translate_sys_error(WSAGetLastError());
+
+  return 0;
+}
diff --git a/src/win/fs.c b/src/win/fs.c
index 65d936b..9e2f084 100644
--- a/src/win/fs.c
+++ b/src/win/fs.c
@@ -1125,6 +1125,137 @@ cleanup:
     uv__free(dirents);
 }
 
+void fs__opendir(uv_fs_t* req) {
+  WCHAR* pathw;
+  size_t len;
+  const WCHAR* fmt;
+  WCHAR* find_path;
+  uv_dir_t* dir;
+
+  pathw = req->file.pathw;
+  dir = NULL;
+  find_path = NULL;
+
+  /* Figure out whether path is a file or a directory. */
+  if (!(GetFileAttributesW(pathw) & FILE_ATTRIBUTE_DIRECTORY)) {
+    SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY);
+    goto error;
+  }
+
+  dir = uv__malloc(sizeof(*dir));
+  if (dir == NULL) {
+    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
+    goto error;
+  }
+
+  len = wcslen(pathw);
+
+  if (len == 0)
+    fmt = L"./*";
+  else if (IS_SLASH(pathw[len - 1]))
+    fmt = L"%s*";
+  else
+    fmt = L"%s\\*";
+
+  find_path = uv__malloc(sizeof(WCHAR) * (len + 4));
+  if (find_path == NULL) {
+    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
+    goto error;
+  }
+
+  _snwprintf(find_path, len + 3, fmt, pathw);
+  dir->dir_handle = FindFirstFileW(find_path, &dir->find_data);
+  uv__free(find_path);
+  find_path = NULL;
+  if (dir->dir_handle == INVALID_HANDLE_VALUE &&
+      GetLastError() != ERROR_FILE_NOT_FOUND) {
+    SET_REQ_WIN32_ERROR(req, GetLastError());
+    goto error;
+  }
+
+  dir->need_find_call = FALSE;
+  req->ptr = dir;
+  SET_REQ_RESULT(req, 0);
+  return;
+
+error:
+  uv__free(dir);
+  uv__free(find_path);
+  req->ptr = NULL;
+}
+
+void fs__readdir(uv_fs_t* req) {
+  uv_dir_t* dir;
+  uv_dirent_t* dirents;
+  uv__dirent_t dent;
+  unsigned int dirent_idx;
+  PWIN32_FIND_DATAW find_data;
+  unsigned int i;
+  int r;
+
+  req->flags |= UV_FS_FREE_PTR;
+  dir = req->ptr;
+  dirents = dir->dirents;
+  memset(dirents, 0, dir->nentries * sizeof(*dir->dirents));
+  find_data = &dir->find_data;
+  dirent_idx = 0;
+
+  while (dirent_idx < dir->nentries) {
+    if (dir->need_find_call && FindNextFileW(dir->dir_handle, find_data) == 0) {
+      if (GetLastError() == ERROR_NO_MORE_FILES)
+        break;
+      goto error;
+    }
+
+    /* Skip "." and ".." entries. */
+    if (find_data->cFileName[0] == L'.' &&
+        (find_data->cFileName[1] == L'\0' ||
+        (find_data->cFileName[1] == L'.' &&
+        find_data->cFileName[2] == L'\0'))) {
+      dir->need_find_call = TRUE;
+      continue;
+    }
+
+    r = uv__convert_utf16_to_utf8((const WCHAR*) &find_data->cFileName,
+                                  -1,
+                                  (char**) &dirents[dirent_idx].name);
+    if (r != 0)
+      goto error;
+
+    /* Copy file type. */
+    if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
+      dent.d_type = UV__DT_DIR;
+    else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0)
+      dent.d_type = UV__DT_LINK;
+    else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DEVICE) != 0)
+      dent.d_type = UV__DT_CHAR;
+    else
+      dent.d_type = UV__DT_FILE;
+
+    dirents[dirent_idx].type = uv__fs_get_dirent_type(&dent);
+    dir->need_find_call = TRUE;
+    ++dirent_idx;
+  }
+
+  SET_REQ_RESULT(req, dirent_idx);
+  return;
+
+error:
+  SET_REQ_WIN32_ERROR(req, GetLastError());
+  for (i = 0; i < dirent_idx; ++i) {
+    uv__free((char*) dirents[i].name);
+    dirents[i].name = NULL;
+  }
+}
+
+void fs__closedir(uv_fs_t* req) {
+  uv_dir_t* dir;
+
+  dir = req->ptr;
+  FindClose(dir->dir_handle);
+  uv__free(req->ptr);
+  SET_REQ_RESULT(req, 0);
+}
 
 INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf,
     int do_lstat) {
@@ -2039,6 +2170,9 @@ static void uv__fs_work(struct uv__work* w) {
     XX(MKDTEMP, mkdtemp)
     XX(RENAME, rename)
     XX(SCANDIR, scandir)
+    XX(READDIR, readdir)
+    XX(OPENDIR, opendir)
+    XX(CLOSEDIR, closedir)
     XX(LINK, link)
     XX(SYMLINK, symlink)
     XX(READLINK, readlink)
@@ -2080,6 +2214,8 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
   if (req->flags & UV_FS_FREE_PTR) {
     if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
       uv__fs_scandir_cleanup(req);
+    else if (req->fs_type == UV_FS_READDIR)
+      uv__fs_readdir_cleanup(req);
     else
       uv__free(req->ptr);
   }
@@ -2247,6 +2383,45 @@ int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
   POST;
 }
 
+int uv_fs_opendir(uv_loop_t* loop,
+                  uv_fs_t* req,
+                  const char* path,
+                  uv_fs_cb cb) {
+  int err;
+
+  INIT(UV_FS_OPENDIR);
+  err = fs__capture_path(req, path, NULL, cb != NULL);
+  if (err)
+    return uv_translate_sys_error(err);
+  POST;
+}
+
+int uv_fs_readdir(uv_loop_t* loop,
+                  uv_fs_t* req,
+                  uv_dir_t* dir,
+                  uv_fs_cb cb) {
+  INIT(UV_FS_READDIR);
+
+  if (dir == NULL ||
+      dir->dirents == NULL ||
+      dir->dir_handle == INVALID_HANDLE_VALUE) {
+    return UV_EINVAL;
+  }
+
+  req->ptr = dir;
+  POST;
+}
+
+int uv_fs_closedir(uv_loop_t* loop,
+                   uv_fs_t* req,
+                   uv_dir_t* dir,
+                   uv_fs_cb cb) {
+  INIT(UV_FS_CLOSEDIR);
+  if (dir == NULL)
+    return UV_EINVAL;
+  req->ptr = dir;
+  POST;
+}
 
 int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
     const char* new_path, uv_fs_cb cb) {
diff --git a/src/win/handle.c b/src/win/handle.c
index 9d76c3f..61e4df6 100644
--- a/src/win/handle.c
+++ b/src/win/handle.c
@@ -139,7 +139,6 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
     case UV_FS_POLL:
       uv__fs_poll_close((uv_fs_poll_t*) handle);
       uv__handle_closing(handle);
-      uv_want_endgame(loop, handle);
       return;
 
     default:
diff --git a/src/win/internal.h b/src/win/internal.h
index 634b9f7..70ddaa5 100644
--- a/src/win/internal.h
+++ b/src/win/internal.h
@@ -272,6 +272,14 @@ int uv__getpwuid_r(uv_passwd_t* pwd);
 int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
 int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16);
 
+typedef int (WINAPI *uv__peersockfunc)(SOCKET, struct sockaddr*, int*);
+
+int uv__getsockpeername(const uv_handle_t* handle,
+                        uv__peersockfunc func,
+                        struct sockaddr* name,
+                        int* namelen,
+                        int delayed_error);
+
 
 /*
  * Process stdio handles.
diff --git a/src/win/tcp.c b/src/win/tcp.c
index 3ce5548..f2cb527 100644
--- a/src/win/tcp.c
+++ b/src/win/tcp.c
@@ -809,44 +809,24 @@ static int uv_tcp_try_connect(uv_connect_t* req,
 int uv_tcp_getsockname(const uv_tcp_t* handle,
                        struct sockaddr* name,
                        int* namelen) {
-  int result;
-
-  if (handle->socket == INVALID_SOCKET) {
-    return UV_EINVAL;
-  }
-
-  if (handle->delayed_error) {
-    return uv_translate_sys_error(handle->delayed_error);
-  }
-
-  result = getsockname(handle->socket, name, namelen);
-  if (result != 0) {
-    return uv_translate_sys_error(WSAGetLastError());
-  }
 
-  return 0;
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getsockname,
+                             name,
+                             namelen,
+                             handle->delayed_error);
 }
 
 
 int uv_tcp_getpeername(const uv_tcp_t* handle,
                        struct sockaddr* name,
                        int* namelen) {
-  int result;
-
-  if (handle->socket == INVALID_SOCKET) {
-    return UV_EINVAL;
-  }
-
-  if (handle->delayed_error) {
-    return uv_translate_sys_error(handle->delayed_error);
-  }
-
-  result = getpeername(handle->socket, name, namelen);
-  if (result != 0) {
-    return uv_translate_sys_error(WSAGetLastError());
-  }
 
-  return 0;
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getpeername,
+                             name,
+                             namelen,
+                             handle->delayed_error);
 }
 
 
diff --git a/src/win/thread.c b/src/win/thread.c
index fd4b7c9..89c53ad 100644
--- a/src/win/thread.c
+++ b/src/win/thread.c
@@ -112,9 +112,34 @@ static UINT __stdcall uv__thread_start(void* arg) {
 
 
 int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
+  uv_thread_options_t params;
+  params.flags = UV_THREAD_NO_FLAGS;
+  return uv_thread_create_ex(tid, &params, entry, arg);
+}
+
+int uv_thread_create_ex(uv_thread_t* tid,
+                        const uv_thread_options_t* params,
+                        void (*entry)(void *arg),
+                        void *arg) {
   struct thread_ctx* ctx;
   int err;
   HANDLE thread;
+  SYSTEM_INFO sysinfo;
+  size_t stack_size;
+  size_t pagesize;
+
+  stack_size =
+      params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
+
+  if (stack_size != 0) {
+    GetNativeSystemInfo(&sysinfo);
+    pagesize = (size_t)sysinfo.dwPageSize;
+    /* Round up to the nearest page boundary. */
+    stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
+
+    if ((unsigned)stack_size != stack_size)
+      return UV_EINVAL;
+  }
 
   ctx = uv__malloc(sizeof(*ctx));
   if (ctx == NULL)
@@ -126,7 +151,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
   /* Create the thread in suspended state so we have a chance to pass
    * its own creation handle to it */
   thread = (HANDLE) _beginthreadex(NULL,
-                                   0,
+                                   (unsigned)stack_size,
                                    uv__thread_start,
                                    ctx,
                                    CREATE_SUSPENDED,
diff --git a/src/win/tty.c b/src/win/tty.c
index f38e9a8..a98fe26 100644
--- a/src/win/tty.c
+++ b/src/win/tty.c
@@ -736,8 +736,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
       /* Ignore keyup events, unless the left alt key was held and a valid
        * unicode character was emitted. */
       if (!KEV.bKeyDown &&
-          KEV.wVirtualKeyCode != VK_MENU &&
-          KEV.uChar.UnicodeChar != 0) {
+          (KEV.wVirtualKeyCode != VK_MENU ||
+           KEV.uChar.UnicodeChar == 0)) {
         continue;
       }
 
diff --git a/src/win/udp.c b/src/win/udp.c
index 37df849..8aeeab3 100644
--- a/src/win/udp.c
+++ b/src/win/udp.c
@@ -36,22 +36,27 @@ const unsigned int uv_active_udp_streams_threshold = 0;
 
 /* A zero-size buffer for use by uv_udp_read */
 static char uv_zero_[] = "";
-
-int uv_udp_getsockname(const uv_udp_t* handle,
+int uv_udp_getpeername(const uv_udp_t* handle,
                        struct sockaddr* name,
                        int* namelen) {
-  int result;
 
-  if (handle->socket == INVALID_SOCKET) {
-    return UV_EINVAL;
-  }
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getpeername,
+                             name,
+                             namelen,
+                             0);
+}
 
-  result = getsockname(handle->socket, name, namelen);
-  if (result != 0) {
-    return uv_translate_sys_error(WSAGetLastError());
-  }
 
-  return 0;
+int uv_udp_getsockname(const uv_udp_t* handle,
+                       struct sockaddr* name,
+                       int* namelen) {
+
+  return uv__getsockpeername((const uv_handle_t*) handle,
+                             getsockname,
+                             name,
+                             namelen,
+                             0);
 }
 
 
@@ -784,6 +789,18 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
 }
 
 
+int uv__udp_is_bound(uv_udp_t* handle) {
+  struct sockaddr_storage addr;
+  int addrlen;
+
+  addrlen = sizeof(addr);
+  if (uv_udp_getsockname(handle, (struct sockaddr*) &addr, &addrlen) != 0)
+    return 0;
+
+  return addrlen > 0;
+}
+
+
 int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
   WSAPROTOCOL_INFOW protocol_info;
   int opt_len;
@@ -803,7 +820,16 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
                           handle,
                           sock,
                           protocol_info.iAddressFamily);
-  return uv_translate_sys_error(err);
+  if (err)
+    return uv_translate_sys_error(err);
+
+  if (uv__udp_is_bound(handle))
+    handle->flags |= UV_HANDLE_BOUND;
+
+  if (uv__udp_is_connected(handle))
+    handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
+  return 0;
 }
 
 
@@ -880,6 +906,50 @@ int uv__udp_bind(uv_udp_t* handle,
 }
 
 
+int uv__udp_connect(uv_udp_t* handle,
+                    const struct sockaddr* addr,
+                    unsigned int addrlen) {
+  const struct sockaddr* bind_addr;
+  int err;
+
+  if (!(handle->flags & UV_HANDLE_BOUND)) {
+    if (addrlen == sizeof(uv_addr_ip4_any_))
+      bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
+    else if (addrlen == sizeof(uv_addr_ip6_any_))
+      bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
+    else
+      return UV_EINVAL;
+
+    err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
+    if (err)
+      return uv_translate_sys_error(err);
+  }
+
+  err = connect(handle->socket, addr, addrlen);
+  if (err)
+    return uv_translate_sys_error(err);
+
+  handle->flags |= UV_HANDLE_UDP_CONNECTED;
+
+  return 0;
+}
+
+
+int uv__udp_disconnect(uv_udp_t* handle) {
+    int err;
+    struct sockaddr addr;
+
+    memset(&addr, 0, sizeof(addr));
+
+    err = connect(handle->socket, &addr, sizeof(addr));
+    if (err)
+      return uv_translate_sys_error(err);
+
+    handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
+    return 0;
+}
+
+
 /* This function is an egress point, i.e. it returns libuv errors rather than
  * system errors.
  */
@@ -900,6 +970,7 @@ int uv__udp_send(uv_udp_send_t* req,
       bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
     else
       return UV_EINVAL;
+
     err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
     if (err)
       return uv_translate_sys_error(err);
@@ -925,9 +996,11 @@ int uv__udp_try_send(uv_udp_t* handle,
 
   assert(nbufs > 0);
 
-  err = uv__convert_to_localhost_if_unspecified(addr, &converted);
-  if (err)
-    return err;
+  if (addr != NULL) {
+    err = uv__convert_to_localhost_if_unspecified(addr, &converted);
+    if (err)
+      return err;
+  }
 
   /* Already sending a message.*/
   if (handle->send_queue_count != 0)
diff --git a/src/win/util.c b/src/win/util.c
index 9237891..7ca8321 100644
--- a/src/win/util.c
+++ b/src/win/util.c
@@ -59,13 +59,6 @@
 # define UNLEN 256
 #endif
 
-/*
-  Max hostname length. The Windows gethostname() documentation states that 256
-  bytes will always be large enough to hold the null-terminated hostname.
-*/
-#ifndef MAXHOSTNAMELEN
-# define MAXHOSTNAMELEN 256
-#endif
 
 /* Maximum environment variable size, including the terminating null */
 #define MAX_ENV_VAR_LENGTH 32767
@@ -327,6 +320,11 @@ uint64_t uv_get_total_memory(void) {
 }
 
 
+uint64_t uv_get_constrained_memory(void) {
+  return 0;  /* Memory constraints are unknown. */
+}
+
+
 uv_pid_t uv_os_getpid(void) {
   return GetCurrentProcessId();
 }
@@ -684,12 +682,9 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {
                            NULL,
                            (BYTE*)&cpu_brand,
                            &cpu_brand_size);
-    if (err != ERROR_SUCCESS) {
-      RegCloseKey(processor_key);
-      goto error;
-    }
-
     RegCloseKey(processor_key);
+    if (err != ERROR_SUCCESS)
+      goto error;
 
     cpu_info = &cpu_infos[i];
     cpu_info->speed = cpu_speed;
@@ -713,9 +708,11 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {
   return 0;
 
  error:
-  /* This is safe because the cpu_infos array is zeroed on allocation. */
-  for (i = 0; i < cpu_count; i++)
-    uv__free(cpu_infos[i].model);
+  if (cpu_infos != NULL) {
+    /* This is safe because the cpu_infos array is zeroed on allocation. */
+    for (i = 0; i < cpu_count; i++)
+      uv__free(cpu_infos[i].model);
+  }
 
   uv__free(cpu_infos);
   uv__free(sppi);
@@ -1510,7 +1507,7 @@ int uv_os_unsetenv(const char* name) {
 
 
 int uv_os_gethostname(char* buffer, size_t* size) {
-  char buf[MAXHOSTNAMELEN + 1];
+  char buf[UV_MAXHOSTNAMESIZE];
   size_t len;
 
   if (buffer == NULL || size == NULL || *size == 0)
@@ -1634,6 +1631,10 @@ int uv_os_uname(uv_utsname_t* buffer) {
      https://github.com/gagern/gnulib/blob/master/lib/uname.c */
   OSVERSIONINFOW os_info;
   SYSTEM_INFO system_info;
+  HKEY registry_key;
+  WCHAR product_name_w[256];
+  DWORD product_name_w_size;
+  int version_size;
   int processor_level;
   int r;
 
@@ -1658,16 +1659,56 @@ int uv_os_uname(uv_utsname_t* buffer) {
   }
 
   /* Populate the version field. */
-  if (WideCharToMultiByte(CP_UTF8,
-                          0,
-                          os_info.szCSDVersion,
-                          -1,
-                          buffer->version,
-                          sizeof(buffer->version),
-                          NULL,
-                          NULL) == 0) {
-    r = uv_translate_sys_error(GetLastError());
-    goto error;
+  version_size = 0;
+  r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                    L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
+                    0,
+                    KEY_QUERY_VALUE,
+                    &registry_key);
+
+  if (r == ERROR_SUCCESS) {
+    product_name_w_size = sizeof(product_name_w);
+    r = RegGetValueW(registry_key,
+                     NULL,
+                     L"ProductName",
+                     RRF_RT_REG_SZ,
+                     NULL,
+                     (PVOID) product_name_w,
+                     &product_name_w_size);
+    RegCloseKey(registry_key);
+
+    if (r == ERROR_SUCCESS) {
+      version_size = WideCharToMultiByte(CP_UTF8,
+                                         0,
+                                         product_name_w,
+                                         -1,
+                                         buffer->version,
+                                         sizeof(buffer->version),
+                                         NULL,
+                                         NULL);
+      if (version_size == 0) {
+        r = uv_translate_sys_error(GetLastError());
+        goto error;
+      }
+    }
+  }
+
+  /* Append service pack information to the version if present. */
+  if (os_info.szCSDVersion[0] != L'\0') {
+    if (version_size > 0)
+      buffer->version[version_size - 1] = ' ';
+
+    if (WideCharToMultiByte(CP_UTF8,
+                            0,
+                            os_info.szCSDVersion,
+                            -1,
+                            buffer->version + version_size,
+                            sizeof(buffer->version) - version_size,
+                            NULL,
+                            NULL) == 0) {
+      r = uv_translate_sys_error(GetLastError());
+      goto error;
+    }
   }
 
   /* Populate the sysname field. */
@@ -1744,3 +1785,20 @@ error:
   buffer->machine[0] = '\0';
   return r;
 }
+
+int uv_gettimeofday(uv_timeval64_t* tv) {
+  /* Based on https://doxygen.postgresql.org/gettimeofday_8c_source.html */
+  const uint64_t epoch = (uint64_t) 116444736000000000ULL;
+  FILETIME file_time;
+  ULARGE_INTEGER ularge;
+
+  if (tv == NULL)
+    return UV_EINVAL;
+
+  GetSystemTimeAsFileTime(&file_time);
+  ularge.LowPart = file_time.dwLowDateTime;
+  ularge.HighPart = file_time.dwHighDateTime;
+  tv->tv_sec = (int64_t) ((ularge.QuadPart - epoch) / 10000000L);
+  tv->tv_usec = (int32_t) (((ularge.QuadPart - epoch) % 10000000L) / 10);
+  return 0;
+}
diff --git a/src/win/winsock.c b/src/win/winsock.c
index 5e7da2a..5820ba9 100644
--- a/src/win/winsock.c
+++ b/src/win/winsock.c
@@ -87,12 +87,6 @@ void uv_winsock_init(void) {
   WSAPROTOCOL_INFOW protocol_info;
   int opt_len;
 
-  /* Initialize winsock */
-  errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data);
-  if (errorno != 0) {
-    uv_fatal_error(errorno, "WSAStartup");
-  }
-
   /* Set implicit binding address used by connectEx */
   if (uv_ip4_addr("0.0.0.0", 0, &uv_addr_ip4_any_)) {
     abort();
@@ -102,6 +96,15 @@ void uv_winsock_init(void) {
     abort();
   }
 
+  /* Skip initialization in safe mode without network support */
+  if (1 == GetSystemMetrics(SM_CLEANBOOT)) return;
+
+  /* Initialize winsock */
+  errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data);
+  if (errorno != 0) {
+    uv_fatal_error(errorno, "WSAStartup");
+  }
+
   /* Detect non-IFS LSPs */
   dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
 

-----------------------------------------------------------------------

Summary of changes:
 Utilities/cmlibuv/include/uv.h                 |  66 +++++-
 Utilities/cmlibuv/include/uv/unix.h            |  19 +-
 Utilities/cmlibuv/include/uv/version.h         |   2 +-
 Utilities/cmlibuv/include/uv/win.h             |   5 +
 Utilities/cmlibuv/src/fs-poll.c                |  63 ++++--
 Utilities/cmlibuv/src/threadpool.c             |   2 +-
 Utilities/cmlibuv/src/unix/aix.c               |   6 +
 Utilities/cmlibuv/src/unix/async.c             |  37 +++-
 Utilities/cmlibuv/src/unix/atomic-ops.h        |  39 +---
 Utilities/cmlibuv/src/unix/bsd-ifaddrs.c       |  18 +-
 Utilities/cmlibuv/src/unix/cmake-bootstrap.c   |   9 +
 Utilities/cmlibuv/src/unix/core.c              |  90 ++++++--
 Utilities/cmlibuv/src/unix/darwin.c            |   5 +
 Utilities/cmlibuv/src/unix/freebsd.c           |   5 +
 Utilities/cmlibuv/src/unix/fs.c                | 289 ++++++++++++++++++++-----
 Utilities/cmlibuv/src/unix/fsevents.c          |   3 +-
 Utilities/cmlibuv/src/unix/getaddrinfo.c       |   2 +
 Utilities/cmlibuv/src/unix/haiku.c             | 176 +++++++++++++++
 Utilities/cmlibuv/src/unix/ibmi.c              | 141 +++++++++++-
 Utilities/cmlibuv/src/unix/internal.h          |  11 +-
 Utilities/cmlibuv/src/unix/kqueue.c            |  18 +-
 Utilities/cmlibuv/src/unix/linux-core.c        | 162 ++++++++++++--
 Utilities/cmlibuv/src/unix/linux-syscalls.c    |  31 +++
 Utilities/cmlibuv/src/unix/linux-syscalls.h    |  35 +++
 Utilities/cmlibuv/src/unix/netbsd.c            |   5 +
 Utilities/cmlibuv/src/unix/openbsd.c           |   5 +
 Utilities/cmlibuv/src/unix/os390.c             |   6 +
 Utilities/cmlibuv/src/unix/pipe.c              |  12 +-
 Utilities/cmlibuv/src/unix/posix-poll.c        |   2 +
 Utilities/cmlibuv/src/unix/process.c           |   7 +
 Utilities/cmlibuv/src/unix/stream.c            |   8 +-
 Utilities/cmlibuv/src/unix/sunos.c             |  24 +-
 Utilities/cmlibuv/src/unix/tcp.c               |  48 ++--
 Utilities/cmlibuv/src/unix/thread.c            |  52 ++++-
 Utilities/cmlibuv/src/unix/udp.c               | 144 +++++++++---
 Utilities/cmlibuv/src/uv-common.c              | 146 ++++++++++---
 Utilities/cmlibuv/src/uv-common.h              |  11 +
 Utilities/cmlibuv/src/uv-data-getter-setters.c |   2 +-
 Utilities/cmlibuv/src/win/core.c               |  23 ++
 Utilities/cmlibuv/src/win/fs.c                 | 175 +++++++++++++++
 Utilities/cmlibuv/src/win/handle.c             |   1 -
 Utilities/cmlibuv/src/win/internal.h           |   8 +
 Utilities/cmlibuv/src/win/tcp.c                |  40 +---
 Utilities/cmlibuv/src/win/thread.c             |  27 ++-
 Utilities/cmlibuv/src/win/tty.c                |   4 +-
 Utilities/cmlibuv/src/win/udp.c                | 103 +++++++--
 Utilities/cmlibuv/src/win/util.c               | 110 +++++++---
 Utilities/cmlibuv/src/win/winsock.c            |  15 +-
 48 files changed, 1856 insertions(+), 356 deletions(-)
 create mode 100644 Utilities/cmlibuv/src/unix/haiku.c


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list