summaryrefslogtreecommitdiff
path: root/deps/uv/src
diff options
context:
space:
mode:
authorSaúl Ibarra Corretgé <saghul@gmail.com>2016-04-01 11:19:19 +0200
committerSaúl Ibarra Corretgé <saghul@gmail.com>2016-04-07 10:48:27 -0300
commitc3cec1eefc9f3b55a3fb7bd623b3d921f493870d (patch)
tree8a4defa8165e15d3d2afd331f2b04c90c70d5bb6 /deps/uv/src
parent71544c5ecae20123a328e08a04b7f1587c4cdbbd (diff)
downloadandroid-node-v8-c3cec1eefc9f3b55a3fb7bd623b3d921f493870d.tar.gz
android-node-v8-c3cec1eefc9f3b55a3fb7bd623b3d921f493870d.tar.bz2
android-node-v8-c3cec1eefc9f3b55a3fb7bd623b3d921f493870d.zip
deps: upgrade libuv to 1.9.0
Fixes: https://github.com/nodejs/node/issues/5737 Fixes: https://github.com/nodejs/node/issues/4643 Fixes: https://github.com/nodejs/node/issues/4291 Fixes: https://github.com/nodejs/node-v0.x-archive/issues/8960 Refs: https://github.com/nodejs/node/pull/3594 PR-URL: https://github.com/nodejs/node/pull/5994 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Johan Bergström <bugs@bergstroem.nu>
Diffstat (limited to 'deps/uv/src')
-rw-r--r--deps/uv/src/fs-poll.c5
-rw-r--r--deps/uv/src/unix/aix.c63
-rw-r--r--deps/uv/src/unix/core.c194
-rw-r--r--deps/uv/src/unix/fs.c17
-rw-r--r--deps/uv/src/unix/internal.h31
-rw-r--r--deps/uv/src/unix/kqueue.c21
-rw-r--r--deps/uv/src/unix/linux-core.c77
-rw-r--r--deps/uv/src/unix/linux-syscalls.h1
-rw-r--r--deps/uv/src/unix/pipe.c11
-rw-r--r--deps/uv/src/unix/poll.c16
-rw-r--r--deps/uv/src/unix/process.c6
-rw-r--r--deps/uv/src/unix/stream.c22
-rw-r--r--deps/uv/src/unix/sunos.c11
-rw-r--r--deps/uv/src/unix/thread.c33
-rw-r--r--deps/uv/src/unix/tty.c36
-rw-r--r--deps/uv/src/uv-common.c5
-rw-r--r--deps/uv/src/win/core.c130
-rw-r--r--deps/uv/src/win/dl.c7
-rw-r--r--deps/uv/src/win/fs-event.c108
-rw-r--r--deps/uv/src/win/fs.c25
-rw-r--r--deps/uv/src/win/getaddrinfo.c61
-rw-r--r--deps/uv/src/win/internal.h3
-rw-r--r--deps/uv/src/win/pipe.c23
-rw-r--r--deps/uv/src/win/poll.c15
-rw-r--r--deps/uv/src/win/timer.c9
-rw-r--r--deps/uv/src/win/tty.c9
-rw-r--r--deps/uv/src/win/util.c254
27 files changed, 888 insertions, 305 deletions
diff --git a/deps/uv/src/fs-poll.c b/deps/uv/src/fs-poll.c
index 44d47b88ed..ee73d5a2e6 100644
--- a/deps/uv/src/fs-poll.c
+++ b/deps/uv/src/fs-poll.c
@@ -138,13 +138,14 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) {
assert(ctx != NULL);
required_len = strlen(ctx->path);
- if (required_len > *size) {
- *size = required_len;
+ if (required_len >= *size) {
+ *size = required_len + 1;
return UV_ENOBUFS;
}
memcpy(buffer, ctx->path, required_len);
*size = required_len;
+ buffer[required_len] = '\0';
return 0;
}
diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c
index c90b7e5cb9..bcaa5ee50b 100644
--- a/deps/uv/src/unix/aix.c
+++ b/deps/uv/src/unix/aix.c
@@ -91,6 +91,24 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
}
+int uv__io_check_fd(uv_loop_t* loop, int fd) {
+ struct poll_ctl pc;
+
+ pc.events = POLLIN;
+ pc.cmd = PS_MOD; /* Equivalent to PS_ADD if the fd is not in the pollset. */
+ pc.fd = fd;
+
+ if (pollset_ctl(loop->backend_fd, &pc, 1))
+ return -errno;
+
+ pc.cmd = PS_DELETE;
+ if (pollset_ctl(loop->backend_fd, &pc, 1))
+ abort();
+
+ return 0;
+}
+
+
void uv__io_poll(uv_loop_t* loop, int timeout) {
struct pollfd events[1024];
struct pollfd pqry;
@@ -506,7 +524,7 @@ static int uv__makedir_p(const char *dir) {
if (*p == '/') {
*p = 0;
err = mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
- if(err != 0)
+ if (err != 0 && errno != EEXIST)
return err;
*p = '/';
}
@@ -707,59 +725,44 @@ static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int
int bytes, rc = 0;
uv_fs_event_t* handle;
int events = 0;
- int i = 0;
char fname[PATH_MAX];
char *p;
handle = container_of(event_watch, uv_fs_event_t, event_watcher);
- /* Clean all the buffers*/
- for(i = 0; i < PATH_MAX; i++) {
- fname[i] = 0;
- }
- i = 0;
-
/* At this point, we assume that polling has been done on the
* file descriptor, so we can just read the AHAFS event occurrence
* data and parse its results without having to block anything
*/
bytes = pread(event_watch->fd, result_data, RDWR_BUF_SIZE, 0);
- assert((bytes <= 0) && "uv__ahafs_event - Error reading monitor file");
+ assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file");
/* Parse the data */
if(bytes > 0)
rc = uv__parse_data(result_data, &events, handle);
+ /* Unrecoverable error */
+ if (rc == -1)
+ return;
+
/* For directory changes, the name of the files that triggered the change
* are never absolute pathnames
*/
if (uv__path_is_a_directory(handle->path) == 0) {
p = handle->dir_filename;
- while(*p != NULL){
- fname[i]= *p;
- i++;
- p++;
- }
} else {
- /* For file changes, figure out whether filename is absolute or not */
- if (handle->path[0] == '/') {
- p = strrchr(handle->path, '/');
+ p = strrchr(handle->path, '/');
+ if (p == NULL)
+ p = handle->path;
+ else
p++;
-
- while(*p != NULL) {
- fname[i]= *p;
- i++;
- p++;
- }
- }
}
+ strncpy(fname, p, sizeof(fname) - 1);
+ /* Just in case */
+ fname[sizeof(fname) - 1] = '\0';
- /* Unrecoverable error */
- if (rc == -1)
- return;
- else /* Call the actual JavaScript callback function */
- handle->cb(handle, (const char*)&fname, events, 0);
+ handle->cb(handle, fname, events, 0);
}
#endif
@@ -839,7 +842,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
/* Setup/Initialize all the libuv routines */
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__ahafs_event, fd);
- handle->path = uv__strdup((const char*)&absolute_path);
+ handle->path = uv__strdup(filename);
handle->cb = cb;
uv__io_start(handle->loop, &handle->event_watcher, UV__POLLIN);
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index cedd86ed34..9aaca84187 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -53,6 +53,9 @@
# include <mach-o/dyld.h> /* _NSGetExecutablePath */
# include <sys/filio.h>
# include <sys/ioctl.h>
+# if defined(O_CLOEXEC)
+# define UV__O_CLOEXEC O_CLOEXEC
+# endif
#endif
#if defined(__FreeBSD__) || defined(__DragonFly__)
@@ -427,6 +430,22 @@ int uv__socket(int domain, int type, int protocol) {
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;
@@ -435,7 +454,7 @@ int uv__accept(int sockfd) {
assert(sockfd >= 0);
while (1) {
-#if defined(__linux__) || __FreeBSD__ >= 10
+#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10)
static int no_accept4;
if (no_accept4)
@@ -479,12 +498,11 @@ skip:
}
-int uv__close(int fd) {
+int uv__close_nocheckstdio(int fd) {
int saved_errno;
int rc;
assert(fd > -1); /* Catch uninitialized io_watcher.fd bugs. */
- assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */
saved_errno = errno;
rc = close(fd);
@@ -499,6 +517,12 @@ int uv__close(int fd) {
}
+int uv__close(int fd) {
+ assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */
+ return uv__close_nocheckstdio(fd);
+}
+
+
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
defined(_AIX) || defined(__DragonFly__)
@@ -809,7 +833,7 @@ 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) {
- assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT)));
+ assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP)));
assert(0 != events);
assert(w->fd >= 0);
assert(w->fd < INT_MAX);
@@ -842,7 +866,7 @@ 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) {
- assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT)));
+ assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP)));
assert(0 != events);
if (w->fd == -1)
@@ -874,7 +898,7 @@ 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) {
- uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT);
+ uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP);
QUEUE_REMOVE(&w->pending_queue);
/* Remove stale events for this file descriptor */
@@ -889,7 +913,7 @@ void uv__io_feed(uv_loop_t* loop, uv__io_t* w) {
int uv__io_active(const uv__io_t* w, unsigned int events) {
- assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT)));
+ assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP)));
assert(0 != events);
return 0 != (w->pevents & events);
}
@@ -930,8 +954,7 @@ int uv__open_cloexec(const char* path, int flags) {
int err;
int fd;
-#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 9) || \
- defined(__DragonFly__)
+#if defined(UV__O_CLOEXEC)
static int no_cloexec;
if (!no_cloexec) {
@@ -1014,17 +1037,10 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
int uv_os_homedir(char* buffer, size_t* size) {
- struct passwd pw;
- struct passwd* result;
+ uv_passwd_t pwd;
char* buf;
- uid_t uid;
- size_t bufsize;
size_t len;
- long initsize;
int r;
-#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
- int (*getpwuid_r)(uid_t, struct passwd*, char*, size_t, struct passwd**);
-#endif
if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL;
@@ -1036,7 +1052,7 @@ int uv_os_homedir(char* buffer, size_t* size) {
len = strlen(buf);
if (len >= *size) {
- *size = len;
+ *size = len + 1;
return -ENOBUFS;
}
@@ -1046,13 +1062,102 @@ int uv_os_homedir(char* buffer, size_t* size) {
return 0;
}
+ /* 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 -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 -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 -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 -ENOSYS;
#endif
- /* HOME is not set, so call getpwuid() */
+ if (pwd == NULL)
+ return -EINVAL;
+
initsize = sysconf(_SC_GETPW_R_SIZE_MAX);
if (initsize <= 0)
@@ -1060,7 +1165,7 @@ int uv_os_homedir(char* buffer, size_t* size) {
else
bufsize = (size_t) initsize;
- uid = getuid();
+ uid = geteuid();
buf = NULL;
for (;;) {
@@ -1088,17 +1193,54 @@ int uv_os_homedir(char* buffer, size_t* size) {
return -ENOENT;
}
- len = strlen(pw.pw_dir);
+ /* 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 (len >= *size) {
- *size = len;
+ if (pwd->username == NULL) {
uv__free(buf);
- return -ENOBUFS;
+ return -ENOMEM;
}
- memcpy(buffer, pw.pw_dir, len + 1);
- *size = len;
+ /* 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);
+}
diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index 57b65be25a..8936ad9d83 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -127,8 +127,8 @@
static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
#if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
return fdatasync(req->file);
-#elif defined(__APPLE__) && defined(F_FULLFSYNC)
- return fcntl(req->file, F_FULLFSYNC);
+#elif defined(__APPLE__) && defined(SYS_fdatasync)
+ return syscall(SYS_fdatasync, req->file);
#else
return fsync(req->file);
#endif
@@ -749,13 +749,13 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
dst->st_gen = src->st_gen;
#elif defined(__ANDROID__)
dst->st_atim.tv_sec = src->st_atime;
- dst->st_atim.tv_nsec = src->st_atime_nsec;
+ dst->st_atim.tv_nsec = src->st_atimensec;
dst->st_mtim.tv_sec = src->st_mtime;
- dst->st_mtim.tv_nsec = src->st_mtime_nsec;
+ dst->st_mtim.tv_nsec = src->st_mtimensec;
dst->st_ctim.tv_sec = src->st_ctime;
- dst->st_ctim.tv_nsec = src->st_ctime_nsec;
+ dst->st_ctim.tv_nsec = src->st_ctimensec;
dst->st_birthtim.tv_sec = src->st_ctime;
- dst->st_birthtim.tv_nsec = src->st_ctime_nsec;
+ dst->st_birthtim.tv_nsec = src->st_ctimensec;
dst->st_flags = 0;
dst->st_gen = 0;
#elif !defined(_AIX) && ( \
@@ -858,9 +858,14 @@ static ssize_t uv__fs_buf_iter(uv_fs_t* req, uv__fs_buf_iter_processor process)
total += result;
}
+ if (errno == EINTR && total == -1)
+ return total;
+
if (bufs != req->bufsml)
uv__free(bufs);
+
req->bufs = NULL;
+ req->nbufs = 0;
return total;
}
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index 741fa57d69..938e76f1d1 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -28,6 +28,7 @@
#include <stdlib.h> /* abort */
#include <string.h> /* strrchr */
#include <fcntl.h> /* O_CLOEXEC, may be */
+#include <stdio.h>
#if defined(__STRICT_ANSI__)
# define inline __inline
@@ -89,17 +90,18 @@
#endif
#if defined(__linux__)
-# define UV__POLLIN UV__EPOLLIN
-# define UV__POLLOUT UV__EPOLLOUT
-# define UV__POLLERR UV__EPOLLERR
-# define UV__POLLHUP UV__EPOLLHUP
+# define UV__POLLIN UV__EPOLLIN
+# define UV__POLLOUT UV__EPOLLOUT
+# define UV__POLLERR UV__EPOLLERR
+# define UV__POLLHUP UV__EPOLLHUP
+# define UV__POLLRDHUP UV__EPOLLRDHUP
#endif
#if defined(__sun) || defined(_AIX)
-# define UV__POLLIN POLLIN
-# define UV__POLLOUT POLLOUT
-# define UV__POLLERR POLLERR
-# define UV__POLLHUP POLLHUP
+# define UV__POLLIN POLLIN
+# define UV__POLLOUT POLLOUT
+# define UV__POLLERR POLLERR
+# define UV__POLLHUP POLLHUP
#endif
#ifndef UV__POLLIN
@@ -118,6 +120,14 @@
# define UV__POLLHUP 8
#endif
+#ifndef UV__POLLRDHUP
+# ifdef POLLRDHUP
+# define UV__POLLRDHUP POLLRDHUP
+# else
+# define UV__POLLRDHUP 0x200
+# endif
+#endif
+
#if !defined(O_CLOEXEC) && defined(__FreeBSD__)
/*
* It may be that we are just missing `__POSIX_VISIBLE >= 200809`.
@@ -167,6 +177,7 @@ struct uv__stream_queued_fds_s {
/* core */
int uv__nonblock(int fd, int set);
int uv__close(int fd);
+int uv__close_nocheckstdio(int fd);
int uv__cloexec(int fd, int set);
int uv__socket(int domain, int type, int protocol);
int uv__dup(int fd);
@@ -180,6 +191,7 @@ 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 */
/* async */
@@ -245,6 +257,9 @@ void uv__timer_close(uv_timer_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__)
int uv___stream_fd(const uv_stream_t* handle);
diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
index 495f20d285..400b4a4b7c 100644
--- a/deps/uv/src/unix/kqueue.c
+++ b/deps/uv/src/unix/kqueue.c
@@ -48,6 +48,24 @@ int uv__kqueue_init(uv_loop_t* loop) {
}
+int uv__io_check_fd(uv_loop_t* loop, int fd) {
+ struct kevent ev;
+ int rc;
+
+ rc = 0;
+ EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
+ if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
+ rc = -errno;
+
+ EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
+ if (rc == 0)
+ if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
+ abort();
+
+ return rc;
+}
+
+
void uv__io_poll(uv_loop_t* loop, int timeout) {
struct kevent events[1024];
struct kevent* ev;
@@ -241,6 +259,9 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (ev->flags & EV_ERROR)
revents |= UV__POLLERR;
+ if ((ev->flags & EV_EOF) && (w->pevents & UV__POLLRDHUP))
+ revents |= UV__POLLRDHUP;
+
if (revents == 0)
continue;
diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c
index 3ff6fb15e9..fb8ac3f237 100644
--- a/deps/uv/src/unix/linux-core.c
+++ b/deps/uv/src/unix/linux-core.c
@@ -39,7 +39,7 @@
#define HAVE_IFADDRS_H 1
#ifdef __UCLIBC__
-# if __UCLIBC_MAJOR__ < 0 || __UCLIBC_MINOR__ < 9 || __UCLIBC_SUBLEVEL__ < 32
+# if __UCLIBC_MAJOR__ < 0 && __UCLIBC_MINOR__ < 9 && __UCLIBC_SUBLEVEL__ < 32
# undef HAVE_IFADDRS_H
# endif
#endif
@@ -52,7 +52,7 @@
# endif
# include <sys/socket.h>
# include <net/ethernet.h>
-# include <linux/if_packet.h>
+# include <netpacket/packet.h>
#endif /* HAVE_IFADDRS_H */
/* Available from 2.6.32 onwards. */
@@ -69,7 +69,7 @@
#endif
static int read_models(unsigned int numcpus, uv_cpu_info_t* ci);
-static int read_times(unsigned int numcpus, uv_cpu_info_t* ci);
+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);
@@ -140,6 +140,26 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
}
+int uv__io_check_fd(uv_loop_t* loop, int fd) {
+ struct uv__epoll_event e;
+ int rc;
+
+ e.events = UV__EPOLLIN;
+ e.data = -1;
+
+ rc = 0;
+ if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_ADD, fd, &e))
+ if (errno != EEXIST)
+ rc = -errno;
+
+ if (rc == 0)
+ if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &e))
+ abort();
+
+ return rc;
+}
+
+
void uv__io_poll(uv_loop_t* loop, int timeout) {
/* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes
* effectively infinite on 32 bits architectures. To avoid blocking
@@ -532,15 +552,42 @@ int uv_uptime(double* uptime) {
}
+static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) {
+ unsigned int num;
+ char buf[1024];
+
+ if (!fgets(buf, sizeof(buf), statfile_fp))
+ abort();
+
+ num = 0;
+ while (fgets(buf, sizeof(buf), statfile_fp)) {
+ if (strncmp(buf, "cpu", 3))
+ break;
+ num++;
+ }
+
+ *numcpus = num;
+ return 0;
+}
+
+
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
unsigned int numcpus;
uv_cpu_info_t* ci;
int err;
+ FILE* statfile_fp;
*cpu_infos = NULL;
*count = 0;
- numcpus = sysconf(_SC_NPROCESSORS_ONLN);
+ statfile_fp = uv__open_file("/proc/stat");
+ if (statfile_fp == NULL)
+ return -errno;
+
+ err = uv__cpu_num(statfile_fp, &numcpus);
+ if (err < 0)
+ return err;
+
assert(numcpus != (unsigned int) -1);
assert(numcpus != 0);
@@ -550,7 +597,11 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
err = read_models(numcpus, ci);
if (err == 0)
- err = read_times(numcpus, ci);
+ err = read_times(statfile_fp, numcpus, ci);
+
+ if (fclose(statfile_fp))
+ if (errno != EINTR && errno != EINPROGRESS)
+ abort();
if (err) {
uv_free_cpu_info(ci, numcpus);
@@ -608,7 +659,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
defined(__i386__) || \
defined(__mips__) || \
defined(__x86_64__)
- fp = fopen("/proc/cpuinfo", "r");
+ fp = uv__open_file("/proc/cpuinfo");
if (fp == NULL)
return -errno;
@@ -676,7 +727,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
}
-static int read_times(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;
@@ -688,22 +739,19 @@ static int read_times(unsigned int numcpus, uv_cpu_info_t* ci) {
unsigned int num;
unsigned int len;
char buf[1024];
- FILE* fp;
clock_ticks = sysconf(_SC_CLK_TCK);
assert(clock_ticks != (unsigned long) -1);
assert(clock_ticks != 0);
- fp = fopen("/proc/stat", "r");
- if (fp == NULL)
- return -errno;
+ rewind(statfile_fp);
- if (!fgets(buf, sizeof(buf), fp))
+ if (!fgets(buf, sizeof(buf), statfile_fp))
abort();
num = 0;
- while (fgets(buf, sizeof(buf), fp)) {
+ while (fgets(buf, sizeof(buf), statfile_fp)) {
if (num >= numcpus)
break;
@@ -742,7 +790,6 @@ static int read_times(unsigned int numcpus, uv_cpu_info_t* ci) {
ts.irq = clock_ticks * irq;
ci[num++].cpu_times = ts;
}
- fclose(fp);
assert(num == numcpus);
return 0;
@@ -759,7 +806,7 @@ static unsigned long read_cpufreq(unsigned int cpunum) {
"/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq",
cpunum);
- fp = fopen(buf, "r");
+ fp = uv__open_file(buf);
if (fp == NULL)
return 0;
diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h
index 96e79439cf..4260df111f 100644
--- a/deps/uv/src/unix/linux-syscalls.h
+++ b/deps/uv/src/unix/linux-syscalls.h
@@ -76,6 +76,7 @@
#define UV__EPOLLOUT 4
#define UV__EPOLLERR 8
#define UV__EPOLLHUP 16
+#define UV__EPOLLRDHUP 0x2000
#define UV__EPOLLONESHOT 0x40000000
#define UV__EPOLLET 0x80000000
diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c
index 7f87a713bf..d4fdfa9d5a 100644
--- a/deps/uv/src/unix/pipe.c
+++ b/deps/uv/src/unix/pipe.c
@@ -200,9 +200,6 @@ out:
if (err)
uv__io_feed(handle->loop, &handle->io_watcher);
- /* Mimic the Windows pipe implementation, always
- * return 0 and let the callback handle errors.
- */
}
@@ -234,14 +231,18 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
addrlen = strlen(sa.sun_path);
- if (addrlen > *size) {
- *size = addrlen;
+ 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;
}
diff --git a/deps/uv/src/unix/poll.c b/deps/uv/src/unix/poll.c
index 37da3b9585..e5efb17160 100644
--- a/deps/uv/src/unix/poll.c
+++ b/deps/uv/src/unix/poll.c
@@ -34,7 +34,7 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
handle = container_of(w, uv_poll_t, io_watcher);
if (events & UV__POLLERR) {
- uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT);
+ uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP);
uv__handle_stop(handle);
handle->poll_cb(handle, -EBADF, 0);
return;
@@ -45,6 +45,8 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
pevents |= UV_READABLE;
if (events & UV__POLLOUT)
pevents |= UV_WRITABLE;
+ if (events & UV__POLLRDHUP)
+ pevents |= UV_DISCONNECT;
handle->poll_cb(handle, 0, pevents);
}
@@ -53,6 +55,10 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
int err;
+ err = uv__io_check_fd(loop, fd);
+ if (err)
+ return err;
+
err = uv__nonblock(fd, 1);
if (err)
return err;
@@ -71,7 +77,9 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
static void uv__poll_stop(uv_poll_t* handle) {
- uv__io_stop(handle->loop, &handle->io_watcher, UV__POLLIN | UV__POLLOUT);
+ uv__io_stop(handle->loop,
+ &handle->io_watcher,
+ UV__POLLIN | UV__POLLOUT | UV__POLLRDHUP);
uv__handle_stop(handle);
}
@@ -86,7 +94,7 @@ int uv_poll_stop(uv_poll_t* handle) {
int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
int events;
- assert((pevents & ~(UV_READABLE | UV_WRITABLE)) == 0);
+ assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
uv__poll_stop(handle);
@@ -99,6 +107,8 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
events |= UV__POLLIN;
if (pevents & UV_WRITABLE)
events |= UV__POLLOUT;
+ if (pevents & UV_DISCONNECT)
+ events |= UV__POLLRDHUP;
uv__io_start(handle->loop, &handle->io_watcher, events);
uv__handle_start(handle);
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
index 571f8cd778..ef10a3422d 100644
--- a/deps/uv/src/unix/process.c
+++ b/deps/uv/src/unix/process.c
@@ -498,7 +498,7 @@ int uv_spawn(uv_loop_t* loop,
} else
abort();
- uv__close(signal_pipe[0]);
+ uv__close_nocheckstdio(signal_pipe[0]);
for (i = 0; i < options->stdio_count; i++) {
err = uv__process_open_stream(options->stdio + i, pipes[i], i == 0);
@@ -530,9 +530,9 @@ error:
if (options->stdio[i].flags & (UV_INHERIT_FD | UV_INHERIT_STREAM))
continue;
if (pipes[i][0] != -1)
- close(pipes[i][0]);
+ uv__close_nocheckstdio(pipes[i][0]);
if (pipes[i][1] != -1)
- close(pipes[i][1]);
+ uv__close_nocheckstdio(pipes[i][1]);
}
uv__free(pipes);
}
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 7d7ab2633b..9043664dfc 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -946,13 +946,14 @@ static void uv__write_callbacks(uv_stream_t* stream) {
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));
- len = sizeof(ss);
+ sslen = sizeof(ss);
- if (getsockname(fd, (struct sockaddr*)&ss, &len))
+ if (getsockname(fd, (struct sockaddr*)&ss, &sslen))
return UV_UNKNOWN_HANDLE;
len = sizeof type;
@@ -961,6 +962,14 @@ uv_handle_type uv__handle_type(int fd) {
return UV_UNKNOWN_HANDLE;
if (type == SOCK_STREAM) {
+#if defined(_AIX)
+ /* on AIX 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;
@@ -1082,6 +1091,11 @@ static int uv__stream_recv_cmsg(uv_stream_t* stream, struct msghdr* msg) {
}
+#ifdef __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wgnu-folding-constant"
+#endif
+
static void uv__read(uv_stream_t* stream) {
uv_buf_t buf;
ssize_t nread;
@@ -1187,6 +1201,10 @@ static void uv__read(uv_stream_t* stream) {
}
+#ifdef __clang__
+# pragma clang diagnostic pop
+#endif
+
#undef UV__CMSG_FD_COUNT
#undef UV__CMSG_FD_SIZE
diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c
index 0c46817b44..9a6cc42b5b 100644
--- a/deps/uv/src/unix/sunos.c
+++ b/deps/uv/src/unix/sunos.c
@@ -116,6 +116,17 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
}
+int uv__io_check_fd(uv_loop_t* loop, int fd) {
+ if (port_associate(loop->backend_fd, PORT_SOURCE_FD, fd, POLLIN, 0))
+ return -errno;
+
+ if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd))
+ abort();
+
+ return 0;
+}
+
+
void uv__io_poll(uv_loop_t* loop, int timeout) {
struct port_event events[1024];
struct port_event* pe;
diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c
index c56a317025..c35bc926bf 100644
--- a/deps/uv/src/unix/thread.c
+++ b/deps/uv/src/unix/thread.c
@@ -27,6 +27,9 @@
#include <errno.h>
#include <sys/time.h>
+#include <sys/resource.h> /* getrlimit() */
+
+#include <limits.h>
#undef NANOSEC
#define NANOSEC ((uint64_t) 1e9)
@@ -55,6 +58,11 @@ static void* uv__thread_start(void *arg)
int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
struct thread_ctx* ctx;
int err;
+ pthread_attr_t* attr;
+#if defined(__APPLE__)
+ pthread_attr_t attr_storage;
+ struct rlimit lim;
+#endif
ctx = uv__malloc(sizeof(*ctx));
if (ctx == NULL)
@@ -63,7 +71,30 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
ctx->entry = entry;
ctx->arg = arg;
- err = pthread_create(tid, NULL, uv__thread_start, ctx);
+ /* On OSX threads other than the main thread are created with a reduced stack
+ * size by default, adjust it to RLIMIT_STACK.
+ */
+#if defined(__APPLE__)
+ if (getrlimit(RLIMIT_STACK, &lim))
+ abort();
+
+ attr = &attr_storage;
+ if (pthread_attr_init(attr))
+ abort();
+
+ if (lim.rlim_cur != RLIM_INFINITY &&
+ lim.rlim_cur >= PTHREAD_STACK_MIN) {
+ if (pthread_attr_setstacksize(attr, lim.rlim_cur))
+ abort();
+ }
+#else
+ attr = NULL;
+#endif
+
+ err = pthread_create(tid, attr, uv__thread_start, ctx);
+
+ if (attr != NULL)
+ pthread_attr_destroy(attr);
if (err)
uv__free(ctx);
diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c
index 7cc5b714ed..32fa37eac9 100644
--- a/deps/uv/src/unix/tty.c
+++ b/deps/uv/src/unix/tty.c
@@ -23,6 +23,7 @@
#include "internal.h"
#include "spinlock.h"
+#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <termios.h>
@@ -33,12 +34,30 @@ static int orig_termios_fd = -1;
static struct termios orig_termios;
static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER;
+static int uv__tty_is_slave(const int fd) {
+ int result;
+#if defined(__linux__) || defined(__FreeBSD__)
+ int dummy;
+
+ result = ioctl(fd, TIOCGPTN, &dummy) != 0;
+#elif defined(__APPLE__)
+ char dummy[256];
+
+ result = ioctl(fd, TIOCPTYGNAME, &dummy) != 0;
+#else
+ /* Fallback to ptsname
+ */
+ result = ptsname(fd) == NULL;
+#endif
+ return result;
+}
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
uv_handle_type type;
int flags;
int newfd;
int r;
+ char path[256];
/* File descriptors that refer to files cannot be monitored with epoll.
* That restriction also applies to character devices like /dev/random
@@ -62,7 +81,15 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
* other processes.
*/
if (type == UV_TTY) {
- r = uv__open_cloexec("/dev/tty", O_RDWR);
+ /* Reopening a pty in master mode won't work either because the reopened
+ * pty will be in slave mode (*BSD) or reopening will allocate a new
+ * master/slave pair (Linux). Therefore check if the fd points to a
+ * slave device.
+ */
+ if (uv__tty_is_slave(fd) && ttyname_r(fd, path, sizeof(path)) == 0)
+ r = uv__open_cloexec(path, O_RDWR);
+ else
+ r = -1;
if (r < 0) {
/* fallback to using blocking writes */
@@ -185,8 +212,13 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
struct winsize ws;
+ int err;
+
+ do
+ err = ioctl(uv__stream_fd(tty), TIOCGWINSZ, &ws);
+ while (err == -1 && errno == EINTR);
- if (ioctl(uv__stream_fd(tty), TIOCGWINSZ, &ws))
+ if (err == -1)
return -errno;
*width = ws.ws_col;
diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c
index 40ed28fec5..6b8c584fbe 100644
--- a/deps/uv/src/uv-common.c
+++ b/deps/uv/src/uv-common.c
@@ -451,13 +451,14 @@ int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) {
}
required_len = strlen(handle->path);
- if (required_len > *size) {
- *size = required_len;
+ 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;
}
diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c
index de0483e102..ba306ebc08 100644
--- a/deps/uv/src/win/core.c
+++ b/deps/uv/src/win/core.c
@@ -256,30 +256,48 @@ static void uv_poll(uv_loop_t* loop, DWORD timeout) {
ULONG_PTR key;
OVERLAPPED* overlapped;
uv_req_t* req;
+ int repeat;
+ uint64_t timeout_time;
- GetQueuedCompletionStatus(loop->iocp,
- &bytes,
- &key,
- &overlapped,
- timeout);
+ timeout_time = loop->time + timeout;
- if (overlapped) {
- /* Package was dequeued */
- req = uv_overlapped_to_req(overlapped);
- uv_insert_pending_req(loop, req);
+ for (repeat = 0; ; repeat++) {
+ GetQueuedCompletionStatus(loop->iocp,
+ &bytes,
+ &key,
+ &overlapped,
+ timeout);
- /* Some time might have passed waiting for I/O,
- * so update the loop time here.
- */
- uv_update_time(loop);
- } else if (GetLastError() != WAIT_TIMEOUT) {
- /* Serious error */
- uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus");
- } else if (timeout > 0) {
- /* GetQueuedCompletionStatus can occasionally return a little early.
- * Make sure that the desired timeout is reflected in the loop time.
- */
- uv__time_forward(loop, timeout);
+ if (overlapped) {
+ /* Package was dequeued */
+ req = uv_overlapped_to_req(overlapped);
+ uv_insert_pending_req(loop, req);
+
+ /* Some time might have passed waiting for I/O,
+ * so update the loop time here.
+ */
+ uv_update_time(loop);
+ } else if (GetLastError() != WAIT_TIMEOUT) {
+ /* Serious error */
+ uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus");
+ } else if (timeout > 0) {
+ /* GetQueuedCompletionStatus can occasionally return a little early.
+ * Make sure that the desired timeout target time is reached.
+ */
+ uv_update_time(loop);
+ if (timeout_time > loop->time) {
+ timeout = (DWORD)(timeout_time - loop->time);
+ /* The first call to GetQueuedCompletionStatus should return very
+ * close to the target time and the second should reach it, but
+ * this is not stated in the documentation. To make sure a busy
+ * loop cannot happen, the timeout is increased exponentially
+ * starting on the third round.
+ */
+ timeout += repeat ? (1 << (repeat - 1)) : 0;
+ continue;
+ }
+ }
+ break;
}
}
@@ -290,33 +308,51 @@ static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) {
OVERLAPPED_ENTRY overlappeds[128];
ULONG count;
ULONG i;
-
- success = pGetQueuedCompletionStatusEx(loop->iocp,
- overlappeds,
- ARRAY_SIZE(overlappeds),
- &count,
- timeout,
- FALSE);
-
- if (success) {
- for (i = 0; i < count; i++) {
- /* Package was dequeued */
- req = uv_overlapped_to_req(overlappeds[i].lpOverlapped);
- uv_insert_pending_req(loop, req);
+ int repeat;
+ uint64_t timeout_time;
+
+ timeout_time = loop->time + timeout;
+
+ for (repeat = 0; ; repeat++) {
+ success = pGetQueuedCompletionStatusEx(loop->iocp,
+ overlappeds,
+ ARRAY_SIZE(overlappeds),
+ &count,
+ timeout,
+ FALSE);
+
+ if (success) {
+ for (i = 0; i < count; i++) {
+ /* Package was dequeued */
+ req = uv_overlapped_to_req(overlappeds[i].lpOverlapped);
+ uv_insert_pending_req(loop, req);
+ }
+
+ /* Some time might have passed waiting for I/O,
+ * so update the loop time here.
+ */
+ uv_update_time(loop);
+ } else if (GetLastError() != WAIT_TIMEOUT) {
+ /* Serious error */
+ uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx");
+ } else if (timeout > 0) {
+ /* GetQueuedCompletionStatus can occasionally return a little early.
+ * Make sure that the desired timeout target time is reached.
+ */
+ uv_update_time(loop);
+ if (timeout_time > loop->time) {
+ timeout = (DWORD)(timeout_time - loop->time);
+ /* The first call to GetQueuedCompletionStatus should return very
+ * close to the target time and the second should reach it, but
+ * this is not stated in the documentation. To make sure a busy
+ * loop cannot happen, the timeout is increased exponentially
+ * starting on the third round.
+ */
+ timeout += repeat ? (1 << (repeat - 1)) : 0;
+ continue;
+ }
}
-
- /* Some time might have passed waiting for I/O,
- * so update the loop time here.
- */
- uv_update_time(loop);
- } else if (GetLastError() != WAIT_TIMEOUT) {
- /* Serious error */
- uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx");
- } else if (timeout > 0) {
- /* GetQueuedCompletionStatus can occasionally return a little early.
- * Make sure that the desired timeout is reflected in the loop time.
- */
- uv__time_forward(loop, timeout);
+ break;
}
}
diff --git a/deps/uv/src/win/dl.c b/deps/uv/src/win/dl.c
index e5f3407f8e..39e400ab2d 100644
--- a/deps/uv/src/win/dl.c
+++ b/deps/uv/src/win/dl.c
@@ -31,7 +31,12 @@ int uv_dlopen(const char* filename, uv_lib_t* lib) {
lib->handle = NULL;
lib->errmsg = NULL;
- if (!uv_utf8_to_utf16(filename, filename_w, ARRAY_SIZE(filename_w))) {
+ if (!MultiByteToWideChar(CP_UTF8,
+ 0,
+ filename,
+ -1,
+ filename_w,
+ ARRAY_SIZE(filename_w))) {
return uv__dlerror(lib, GetLastError());
}
diff --git a/deps/uv/src/win/fs-event.c b/deps/uv/src/win/fs-event.c
index 76ecfebaa2..77c935a2d8 100644
--- a/deps/uv/src/win/fs-event.c
+++ b/deps/uv/src/win/fs-event.c
@@ -63,19 +63,19 @@ static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop,
handle->req_pending = 1;
}
-static int uv_relative_path(const WCHAR* filename,
- const WCHAR* dir,
- WCHAR** relpath) {
- int dirlen = wcslen(dir);
- int filelen = wcslen(filename);
- if (dir[dirlen - 1] == '\\')
+static void uv_relative_path(const WCHAR* filename,
+ const WCHAR* dir,
+ WCHAR** relpath) {
+ size_t dirlen = wcslen(dir);
+ if (dirlen > 0 && dir[dirlen - 1] == '\\')
dirlen--;
- *relpath = uv__malloc((MAX_PATH + 1) * sizeof(WCHAR));
+ size_t filenamelen = wcslen(filename);
+ size_t relpathlen = filenamelen - dirlen - 1;
+ *relpath = uv__malloc((relpathlen + 1) * sizeof(WCHAR));
if (!*relpath)
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
- wcsncpy(*relpath, filename + dirlen + 1, filelen - dirlen - 1);
- (*relpath)[filelen - dirlen - 1] = L'\0';
- return 0;
+ wcsncpy(*relpath, filename + dirlen + 1, relpathlen);
+ (*relpath)[relpathlen] = L'\0';
}
static int uv_split_path(const WCHAR* filename, WCHAR** dir,
@@ -101,12 +101,12 @@ static int uv_split_path(const WCHAR* filename, WCHAR** dir,
*file = wcsdup(filename);
} else {
if (dir) {
- *dir = (WCHAR*)uv__malloc((i + 1) * sizeof(WCHAR));
+ *dir = (WCHAR*)uv__malloc((i + 2) * sizeof(WCHAR));
if (!*dir) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
- wcsncpy(*dir, filename, i);
- (*dir)[i] = L'\0';
+ wcsncpy(*dir, filename, i + 1);
+ (*dir)[i + 1] = L'\0';
}
*file = (WCHAR*)uv__malloc((len - i) * sizeof(WCHAR));
@@ -159,14 +159,20 @@ int uv_fs_event_start(uv_fs_event_t* handle,
uv__handle_start(handle);
/* Convert name to UTF16. */
- name_size = uv_utf8_to_utf16(path, NULL, 0) * sizeof(WCHAR);
+
+ name_size = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0) *
+ sizeof(WCHAR);
pathw = (WCHAR*)uv__malloc(name_size);
if (!pathw) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
- if (!uv_utf8_to_utf16(path, pathw,
- name_size / sizeof(WCHAR))) {
+ if (!MultiByteToWideChar(CP_UTF8,
+ 0,
+ path,
+ -1,
+ pathw,
+ name_size / sizeof(WCHAR))) {
return uv_translate_sys_error(GetLastError());
}
@@ -340,7 +346,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
uv_fs_event_t* handle) {
FILE_NOTIFY_INFORMATION* file_info;
- int err, sizew, size, result;
+ int err, sizew, size;
char* filename = NULL;
WCHAR* filenamew, *long_filenamew = NULL;
DWORD offset = 0;
@@ -425,39 +431,23 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
if (long_filenamew) {
/* Get the file name out of the long path. */
- result = uv_relative_path(long_filenamew,
- handle->dirw,
- &filenamew);
+ uv_relative_path(long_filenamew,
+ handle->dirw,
+ &filenamew);
uv__free(long_filenamew);
-
- if (result == 0) {
- long_filenamew = filenamew;
- sizew = -1;
- } else {
- long_filenamew = NULL;
- }
- }
-
- /*
- * We could not resolve the long form explicitly.
- * We therefore use the name given by ReadDirectoryChangesW.
- * This may be the long form or the 8.3 short name in some cases.
- */
- if (!long_filenamew) {
- filenamew = file_info->FileName;
- sizew = file_info->FileNameLength / sizeof(WCHAR);
- }
- } else {
- /*
- * Removed or renamed events cannot be resolved to the long form.
- * We therefore use the name given by ReadDirectoryChangesW.
- * This may be the long form or the 8.3 short name in some cases.
- */
- if (!long_filenamew) {
- filenamew = file_info->FileName;
- sizew = file_info->FileNameLength / sizeof(WCHAR);
+ long_filenamew = filenamew;
+ sizew = -1;
}
}
+ /*
+ * Removed or renamed events cannot be resolved to the long form.
+ * We therefore use the name given by ReadDirectoryChangesW.
+ * This may be the long form or the 8.3 short name in some cases.
+ */
+ if (!long_filenamew) {
+ filenamew = file_info->FileName;
+ sizew = file_info->FileNameLength / sizeof(WCHAR);
+ }
} else {
/* We already have the long name of the file, so just use it. */
filenamew = handle->filew;
@@ -466,20 +456,28 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
if (filenamew) {
/* Convert the filename to utf8. */
- size = uv_utf16_to_utf8(filenamew,
- sizew,
- NULL,
- 0);
+ size = WideCharToMultiByte(CP_UTF8,
+ 0,
+ filenamew,
+ sizew,
+ NULL,
+ 0,
+ NULL,
+ NULL);
if (size) {
filename = (char*)uv__malloc(size + 1);
if (!filename) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
- size = uv_utf16_to_utf8(filenamew,
- sizew,
- filename,
- size);
+ size = WideCharToMultiByte(CP_UTF8,
+ 0,
+ filenamew,
+ sizew,
+ filename,
+ size,
+ NULL,
+ NULL);
if (size) {
filename[size] = '\0';
} else {
diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c
index a32b0127f7..16e3ae7cf1 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -1717,25 +1717,26 @@ static void fs__readlink(uv_fs_t* req) {
static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
int r;
DWORD w_realpath_len;
- WCHAR* w_realpath_ptr;
- WCHAR* w_finalpath_ptr = NULL;
+ WCHAR* w_realpath_ptr = NULL;
+ WCHAR* w_realpath_buf;
w_realpath_len = pGetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
if (w_realpath_len == 0) {
return -1;
}
- w_realpath_ptr = uv__malloc((w_realpath_len + 1) * sizeof(WCHAR));
- if (w_realpath_ptr == NULL) {
+ w_realpath_buf = uv__malloc((w_realpath_len + 1) * sizeof(WCHAR));
+ if (w_realpath_buf == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return -1;
}
+ w_realpath_ptr = w_realpath_buf;
if (pGetFinalPathNameByHandleW(handle,
w_realpath_ptr,
w_realpath_len,
VOLUME_NAME_DOS) == 0) {
- uv__free(w_realpath_ptr);
+ uv__free(w_realpath_buf);
SetLastError(ERROR_INVALID_HANDLE);
return -1;
}
@@ -1744,20 +1745,22 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
if (wcsncmp(w_realpath_ptr,
UNC_PATH_PREFIX,
UNC_PATH_PREFIX_LEN) == 0) {
- w_finalpath_ptr = w_realpath_ptr + 6;
- *w_finalpath_ptr = L'\\';
+ w_realpath_ptr += 6;
+ *w_realpath_ptr = L'\\';
+ w_realpath_len -= 6;
} else if (wcsncmp(w_realpath_ptr,
LONG_PATH_PREFIX,
LONG_PATH_PREFIX_LEN) == 0) {
- w_finalpath_ptr = w_realpath_ptr + 4;
+ w_realpath_ptr += 4;
+ w_realpath_len -= 4;
} else {
- uv__free(w_realpath_ptr);
+ uv__free(w_realpath_buf);
SetLastError(ERROR_INVALID_HANDLE);
return -1;
}
- r = fs__wide_to_utf8(w_finalpath_ptr, w_realpath_len, realpath_ptr, NULL);
- uv__free(w_realpath_ptr);
+ r = fs__wide_to_utf8(w_realpath_ptr, w_realpath_len, realpath_ptr, NULL);
+ uv__free(w_realpath_buf);
return r;
}
diff --git a/deps/uv/src/win/getaddrinfo.c b/deps/uv/src/win/getaddrinfo.c
index ceed3b7638..744f8e0262 100644
--- a/deps/uv/src/win/getaddrinfo.c
+++ b/deps/uv/src/win/getaddrinfo.c
@@ -126,7 +126,14 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
addrinfo_len += addrinfo_struct_len +
ALIGNED_SIZE(addrinfow_ptr->ai_addrlen);
if (addrinfow_ptr->ai_canonname != NULL) {
- name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, -1, NULL, 0);
+ name_len = WideCharToMultiByte(CP_UTF8,
+ 0,
+ addrinfow_ptr->ai_canonname,
+ -1,
+ NULL,
+ 0,
+ NULL,
+ NULL);
if (name_len == 0) {
req->retcode = uv_translate_sys_error(GetLastError());
goto complete;
@@ -170,16 +177,24 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
/* convert canonical name to UTF-8 */
if (addrinfow_ptr->ai_canonname != NULL) {
- name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname,
- -1,
- NULL,
- 0);
+ name_len = WideCharToMultiByte(CP_UTF8,
+ 0,
+ addrinfow_ptr->ai_canonname,
+ -1,
+ NULL,
+ 0,
+ NULL,
+ NULL);
assert(name_len > 0);
assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len);
- name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname,
- -1,
- cur_ptr,
- name_len);
+ name_len = WideCharToMultiByte(CP_UTF8,
+ 0,
+ addrinfow_ptr->ai_canonname,
+ -1,
+ cur_ptr,
+ name_len,
+ NULL,
+ NULL);
assert(name_len > 0);
addrinfo_ptr->ai_canonname = cur_ptr;
cur_ptr += ALIGNED_SIZE(name_len);
@@ -261,7 +276,8 @@ int uv_getaddrinfo(uv_loop_t* loop,
/* calculate required memory size for all input values */
if (node != NULL) {
- nodesize = ALIGNED_SIZE(uv_utf8_to_utf16(node, NULL, 0) * sizeof(WCHAR));
+ nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, node, -1, NULL, 0) *
+ sizeof(WCHAR));
if (nodesize == 0) {
err = GetLastError();
goto error;
@@ -269,7 +285,12 @@ int uv_getaddrinfo(uv_loop_t* loop,
}
if (service != NULL) {
- servicesize = ALIGNED_SIZE(uv_utf8_to_utf16(service, NULL, 0) *
+ servicesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8,
+ 0,
+ service,
+ -1,
+ NULL,
+ 0) *
sizeof(WCHAR));
if (servicesize == 0) {
err = GetLastError();
@@ -294,9 +315,12 @@ int uv_getaddrinfo(uv_loop_t* loop,
/* the request. */
if (node != NULL) {
req->node = (WCHAR*)alloc_ptr;
- if (uv_utf8_to_utf16(node,
- (WCHAR*) alloc_ptr,
- nodesize / sizeof(WCHAR)) == 0) {
+ if (MultiByteToWideChar(CP_UTF8,
+ 0,
+ node,
+ -1,
+ (WCHAR*) alloc_ptr,
+ nodesize / sizeof(WCHAR)) == 0) {
err = GetLastError();
goto error;
}
@@ -309,9 +333,12 @@ int uv_getaddrinfo(uv_loop_t* loop,
/* in the req. */
if (service != NULL) {
req->service = (WCHAR*)alloc_ptr;
- if (uv_utf8_to_utf16(service,
- (WCHAR*) alloc_ptr,
- servicesize / sizeof(WCHAR)) == 0) {
+ if (MultiByteToWideChar(CP_UTF8,
+ 0,
+ service,
+ -1,
+ (WCHAR*) alloc_ptr,
+ servicesize / sizeof(WCHAR)) == 0) {
err = GetLastError();
goto error;
}
diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h
index 783f21af0f..c724793bf0 100644
--- a/deps/uv/src/win/internal.h
+++ b/deps/uv/src/win/internal.h
@@ -246,7 +246,6 @@ void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle);
void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle);
DWORD uv__next_timeout(const uv_loop_t* loop);
-void uv__time_forward(uv_loop_t* loop, uint64_t msecs);
void uv_process_timers(uv_loop_t* loop);
@@ -329,6 +328,8 @@ uint64_t uv__hrtime(double scale);
int uv_parent_pid();
int uv_current_pid();
__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, char** utf8);
/*
diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c
index bcce80c77e..a784325c58 100644
--- a/deps/uv/src/win/pipe.c
+++ b/deps/uv/src/win/pipe.c
@@ -513,13 +513,18 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
}
/* Convert name to UTF16. */
- nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(WCHAR);
+ nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);
handle->name = (WCHAR*)uv__malloc(nameSize);
if (!handle->name) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
- if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(WCHAR))) {
+ if (!MultiByteToWideChar(CP_UTF8,
+ 0,
+ name,
+ -1,
+ handle->name,
+ nameSize / sizeof(WCHAR))) {
err = GetLastError();
goto error;
}
@@ -627,13 +632,18 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
req->cb = cb;
/* Convert name to UTF16. */
- nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(WCHAR);
+ nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);
handle->name = (WCHAR*)uv__malloc(nameSize);
if (!handle->name) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
- if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(WCHAR))) {
+ if (!MultiByteToWideChar(CP_UTF8,
+ 0,
+ name,
+ -1,
+ handle->name,
+ nameSize / sizeof(WCHAR))) {
err = GetLastError();
goto error;
}
@@ -2038,9 +2048,9 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size)
*size = 0;
err = uv_translate_sys_error(GetLastError());
goto error;
- } else if (pipe_prefix_len + addrlen > *size) {
+ } else if (pipe_prefix_len + addrlen >= *size) {
/* "\\\\.\\pipe" + name */
- *size = pipe_prefix_len + addrlen;
+ *size = pipe_prefix_len + addrlen + 1;
err = UV_ENOBUFS;
goto error;
}
@@ -2062,6 +2072,7 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size)
addrlen += pipe_prefix_len;
*size = addrlen;
+ buffer[addrlen] = '\0';
err = 0;
goto cleanup;
diff --git a/deps/uv/src/win/poll.c b/deps/uv/src/win/poll.c
index ce861d6ffc..d479e521ef 100644
--- a/deps/uv/src/win/poll.c
+++ b/deps/uv/src/win/poll.c
@@ -91,7 +91,11 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
handle->mask_events_1 = handle->events;
handle->mask_events_2 = 0;
} else {
- assert(0);
+ /* Just wait until there's an unsubmitted req. */
+ /* This will happen almost immediately as one of the 2 outstanding */
+ /* requests is about to return. When this happens, */
+ /* uv__fast_poll_process_poll_req will be called, and the pending */
+ /* events, if needed, will be processed in a subsequent request. */
return;
}
@@ -107,6 +111,10 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
if (handle->events & UV_READABLE) {
afd_poll_info->Handles[0].Events |= AFD_POLL_RECEIVE |
AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT;
+ } else {
+ if (handle->events & UV_DISCONNECT) {
+ afd_poll_info->Handles[0].Events |= AFD_POLL_DISCONNECT;
+ }
}
if (handle->events & UV_WRITABLE) {
afd_poll_info->Handles[0].Events |= AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL;
@@ -184,6 +192,9 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
if ((afd_poll_info->Handles[0].Events & (AFD_POLL_RECEIVE |
AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT)) != 0) {
events |= UV_READABLE;
+ if ((afd_poll_info->Handles[0].Events & AFD_POLL_DISCONNECT) != 0) {
+ events |= UV_DISCONNECT;
+ }
}
if ((afd_poll_info->Handles[0].Events & (AFD_POLL_SEND |
AFD_POLL_CONNECT_FAIL)) != 0) {
@@ -218,7 +229,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
assert(handle->type == UV_POLL);
assert(!(handle->flags & UV__HANDLE_CLOSING));
- assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0);
+ assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
handle->events = events;
diff --git a/deps/uv/src/win/timer.c b/deps/uv/src/win/timer.c
index 0da541a2c8..27ca7716af 100644
--- a/deps/uv/src/win/timer.c
+++ b/deps/uv/src/win/timer.c
@@ -34,13 +34,8 @@
void uv_update_time(uv_loop_t* loop) {
uint64_t new_time = uv__hrtime(UV__MILLISEC);
- if (new_time > loop->time) {
- loop->time = new_time;
- }
-}
-
-void uv__time_forward(uv_loop_t* loop, uint64_t msecs) {
- loop->time += msecs;
+ assert(new_time >= loop->time);
+ loop->time = new_time;
}
diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c
index d87cc69909..1b27f60a6f 100644
--- a/deps/uv/src/win/tty.c
+++ b/deps/uv/src/win/tty.c
@@ -292,12 +292,9 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
was_reading = 1;
alloc_cb = tty->alloc_cb;
read_cb = tty->read_cb;
-
- if (was_reading) {
- err = uv_tty_read_stop(tty);
- if (err) {
- return uv_translate_sys_error(err);
- }
+ err = uv_tty_read_stop(tty);
+ if (err) {
+ return uv_translate_sys_error(err);
}
} else {
was_reading = 0;
diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c
index cb24751304..1788b1780e 100644
--- a/deps/uv/src/win/util.c
+++ b/deps/uv/src/win/util.c
@@ -87,30 +87,6 @@ void uv__util_init() {
}
-int uv_utf16_to_utf8(const WCHAR* utf16Buffer, size_t utf16Size,
- char* utf8Buffer, size_t utf8Size) {
- return WideCharToMultiByte(CP_UTF8,
- 0,
- utf16Buffer,
- utf16Size,
- utf8Buffer,
- utf8Size,
- NULL,
- NULL);
-}
-
-
-int uv_utf8_to_utf16(const char* utf8Buffer, WCHAR* utf16Buffer,
- size_t utf16Size) {
- return MultiByteToWideChar(CP_UTF8,
- 0,
- utf8Buffer,
- -1,
- utf16Buffer,
- utf16Size);
-}
-
-
int uv_exepath(char* buffer, size_t* size_ptr) {
int utf8_len, utf16_buffer_len, utf16_len;
WCHAR* utf16_buffer;
@@ -210,7 +186,7 @@ int uv_cwd(char* buffer, size_t* size) {
if (r == 0) {
return uv_translate_sys_error(GetLastError());
} else if (r > (int) *size) {
- *size = r -1;
+ *size = r;
return UV_ENOBUFS;
}
@@ -384,7 +360,7 @@ int uv_set_process_title(const char* title) {
uv__once_init();
/* Find out how big the buffer for the wide-char title must be */
- length = uv_utf8_to_utf16(title, NULL, 0);
+ length = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0);
if (!length) {
err = GetLastError();
goto done;
@@ -396,7 +372,7 @@ int uv_set_process_title(const char* title) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
- length = uv_utf8_to_utf16(title, title_w, length);
+ length = MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w, length);
if (!length) {
err = GetLastError();
goto done;
@@ -434,7 +410,7 @@ static int uv__get_process_title() {
}
/* Find out what the size of the buffer is that we need */
- length = uv_utf16_to_utf8(title_w, -1, NULL, 0);
+ length = WideCharToMultiByte(CP_UTF8, 0, title_w, -1, NULL, 0, NULL, NULL);
if (!length) {
return -1;
}
@@ -446,7 +422,14 @@ static int uv__get_process_title() {
}
/* Do utf16 -> utf8 conversion here */
- if (!uv_utf16_to_utf8(title_w, -1, process_title, length)) {
+ if (!WideCharToMultiByte(CP_UTF8,
+ 0,
+ title_w,
+ -1,
+ process_title,
+ length,
+ NULL,
+ NULL)) {
uv__free(process_title);
return -1;
}
@@ -1169,7 +1152,7 @@ int uv_getrusage(uv_rusage_t *uv_rusage) {
int uv_os_homedir(char* buffer, size_t* size) {
- HANDLE token;
+ uv_passwd_t pwd;
wchar_t path[MAX_PATH];
DWORD bufsize;
size_t len;
@@ -1183,6 +1166,7 @@ int uv_os_homedir(char* buffer, size_t* size) {
if (len == 0) {
r = GetLastError();
+
/* Don't return an error if USERPROFILE was not found */
if (r != ERROR_ENVVAR_NOT_FOUND)
return uv_translate_sys_error(r);
@@ -1190,43 +1174,219 @@ int uv_os_homedir(char* buffer, size_t* size) {
/* This should not be possible */
return UV_EIO;
} else {
- goto convert_buffer;
+ /* Check how much space we need */
+ bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL);
+
+ if (bufsize == 0) {
+ return uv_translate_sys_error(GetLastError());
+ } else if (bufsize > *size) {
+ *size = bufsize;
+ return UV_ENOBUFS;
+ }
+
+ /* Convert to UTF-8 */
+ bufsize = WideCharToMultiByte(CP_UTF8,
+ 0,
+ path,
+ -1,
+ buffer,
+ *size,
+ NULL,
+ NULL);
+
+ if (bufsize == 0)
+ return uv_translate_sys_error(GetLastError());
+
+ *size = bufsize - 1;
+ return 0;
}
- /* USERPROFILE is not set, so call GetUserProfileDirectoryW() */
- if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0)
- return uv_translate_sys_error(GetLastError());
+ /* USERPROFILE is not set, so call uv__getpwuid_r() */
+ r = uv__getpwuid_r(&pwd);
- bufsize = MAX_PATH;
- if (!GetUserProfileDirectoryW(token, path, &bufsize)) {
- r = GetLastError();
- CloseHandle(token);
+ if (r != 0) {
+ return r;
+ }
- /* This should not be possible */
- if (r == ERROR_INSUFFICIENT_BUFFER)
- return UV_EIO;
+ len = strlen(pwd.homedir);
- return uv_translate_sys_error(r);
+ if (len >= *size) {
+ *size = len + 1;
+ uv_os_free_passwd(&pwd);
+ return UV_ENOBUFS;
}
- CloseHandle(token);
+ memcpy(buffer, pwd.homedir, len + 1);
+ *size = len;
+ uv_os_free_passwd(&pwd);
+
+ return 0;
+}
-convert_buffer:
+
+int uv_os_tmpdir(char* buffer, size_t* size) {
+ wchar_t path[MAX_PATH + 1];
+ DWORD bufsize;
+ size_t len;
+
+ if (buffer == NULL || size == NULL || *size == 0)
+ return UV_EINVAL;
+
+ len = GetTempPathW(MAX_PATH + 1, path);
+
+ if (len == 0) {
+ return uv_translate_sys_error(GetLastError());
+ } else if (len > MAX_PATH + 1) {
+ /* This should not be possible */
+ return UV_EIO;
+ }
+
+ /* The returned directory should not have a trailing slash, unless it */
+ /* points at a drive root, like c:\. Remove it if needed.*/
+ if (path[len - 1] == L'\\' &&
+ !(len == 3 && path[1] == L':')) {
+ len--;
+ path[len] = L'\0';
+ }
/* Check how much space we need */
- bufsize = uv_utf16_to_utf8(path, -1, NULL, 0);
+ bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL);
+
if (bufsize == 0) {
return uv_translate_sys_error(GetLastError());
} else if (bufsize > *size) {
- *size = bufsize - 1;
+ *size = bufsize;
return UV_ENOBUFS;
}
/* Convert to UTF-8 */
- bufsize = uv_utf16_to_utf8(path, -1, buffer, *size);
+ bufsize = WideCharToMultiByte(CP_UTF8,
+ 0,
+ path,
+ -1,
+ buffer,
+ *size,
+ NULL,
+ NULL);
+
if (bufsize == 0)
return uv_translate_sys_error(GetLastError());
*size = bufsize - 1;
return 0;
}
+
+
+void uv_os_free_passwd(uv_passwd_t* pwd) {
+ if (pwd == NULL)
+ return;
+
+ uv__free(pwd->username);
+ uv__free(pwd->homedir);
+ pwd->username = NULL;
+ pwd->homedir = NULL;
+}
+
+
+int uv__convert_utf16_to_utf8(const WCHAR* utf16, char** utf8) {
+ DWORD bufsize;
+
+ if (utf16 == NULL)
+ return UV_EINVAL;
+
+ /* Check how much space we need */
+ bufsize = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, NULL, NULL);
+
+ if (bufsize == 0)
+ return uv_translate_sys_error(GetLastError());
+
+ /* Allocate the destination buffer */
+ *utf8 = uv__malloc(bufsize);
+
+ if (*utf8 == NULL)
+ return UV_ENOMEM;
+
+ /* Convert to UTF-8 */
+ bufsize = WideCharToMultiByte(CP_UTF8,
+ 0,
+ utf16,
+ -1,
+ *utf8,
+ bufsize,
+ NULL,
+ NULL);
+
+ if (bufsize == 0) {
+ uv__free(*utf8);
+ return uv_translate_sys_error(GetLastError());
+ }
+
+ return 0;
+}
+
+
+int uv__getpwuid_r(uv_passwd_t* pwd) {
+ HANDLE token;
+ wchar_t username[UNLEN + 1];
+ wchar_t path[MAX_PATH];
+ DWORD bufsize;
+ int r;
+
+ if (pwd == NULL)
+ return UV_EINVAL;
+
+ /* Get the home directory using GetUserProfileDirectoryW() */
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0)
+ return uv_translate_sys_error(GetLastError());
+
+ bufsize = sizeof(path);
+ if (!GetUserProfileDirectoryW(token, path, &bufsize)) {
+ r = GetLastError();
+ CloseHandle(token);
+
+ /* This should not be possible */
+ if (r == ERROR_INSUFFICIENT_BUFFER)
+ return UV_ENOMEM;
+
+ return uv_translate_sys_error(r);
+ }
+
+ CloseHandle(token);
+
+ /* Get the username using GetUserNameW() */
+ bufsize = sizeof(username);
+ if (!GetUserNameW(username, &bufsize)) {
+ r = GetLastError();
+
+ /* This should not be possible */
+ if (r == ERROR_INSUFFICIENT_BUFFER)
+ return UV_ENOMEM;
+
+ return uv_translate_sys_error(r);
+ }
+
+ pwd->homedir = NULL;
+ r = uv__convert_utf16_to_utf8(path, &pwd->homedir);
+
+ if (r != 0)
+ return r;
+
+ pwd->username = NULL;
+ r = uv__convert_utf16_to_utf8(username, &pwd->username);
+
+ if (r != 0) {
+ uv__free(pwd->homedir);
+ return r;
+ }
+
+ pwd->shell = NULL;
+ pwd->uid = -1;
+ pwd->gid = -1;
+
+ return 0;
+}
+
+
+int uv_os_get_passwd(uv_passwd_t* pwd) {
+ return uv__getpwuid_r(pwd);
+}