diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk index c8220c56f2..045987fe5a 100644 --- a/deps/uv/config-unix.mk +++ b/deps/uv/config-unix.mk @@ -70,7 +70,7 @@ ifeq (FreeBSD,$(uname_S)) EV_CONFIG=config_freebsd.h EIO_CONFIG=config_freebsd.h CPPFLAGS += -Isrc/ares/config_freebsd -LINKFLAGS+= +LINKFLAGS+=-lkvm OBJS += src/unix/freebsd.o OBJS += src/unix/kqueue.o endif diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 0b1e2e5c9c..cedf529375 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -115,7 +115,8 @@ typedef intptr_t ssize_t; XX( 45, EAISOCKTYPE, "") \ XX( 46, ESHUTDOWN, "") \ XX( 47, EEXIST, "file already exists") \ - XX( 48, ESRCH, "no such process") + XX( 48, ESRCH, "no such process") \ + XX( 49, ENAMETOOLONG, "name too long") #define UV_ERRNO_GEN(val, name, s) UV_##name = val, @@ -653,6 +654,20 @@ UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, const char* interface_addr, uv_membership membership); +/* + * Set IP multicast loop flag. Makes multicast packets loop back to + * local sockets. + * + * Arguments: + * handle UDP handle. Should have been initialized with + * `uv_udp_init`. + * on 1 for on, 0 for off + * + * Returns: + * 0 on success, -1 on error. + */ +UV_EXTERN int uv_udp_set_multicast_loop(uv_udp_t* handle, int on); + /* * Set the multicast ttl * @@ -664,7 +679,7 @@ UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle, * Returns: * 0 on success, -1 on error. */ -int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl); +UV_EXTERN int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl); /* * Set broadcast on or off @@ -677,7 +692,20 @@ int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl); * Returns: * 0 on success, -1 on error. */ -int uv_udp_set_broadcast(uv_udp_t* handle, int on); +UV_EXTERN int uv_udp_set_broadcast(uv_udp_t* handle, int on); + +/* + * Set the time to live + * + * Arguments: + * handle UDP handle. Should have been initialized with + * `uv_udp_init`. + * ttl 1 through 255 + * + * Returns: + * 0 on success, -1 on error. + */ +UV_EXTERN int uv_udp_set_ttl(uv_udp_t* handle, int ttl); /* * Send data. If the socket has not previously been bound with `uv_udp_bind` diff --git a/deps/uv/src/unix/error.c b/deps/uv/src/unix/error.c index e904d39033..80d3270db0 100644 --- a/deps/uv/src/unix/error.c +++ b/deps/uv/src/unix/error.c @@ -71,6 +71,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case EFAULT: return UV_EFAULT; case EMFILE: return UV_EMFILE; case EMSGSIZE: return UV_EMSGSIZE; + case ENAMETOOLONG: return UV_ENAMETOOLONG; case EINVAL: return UV_EINVAL; case ECONNREFUSED: return UV_ECONNREFUSED; case EADDRINUSE: return UV_EADDRINUSE; diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c index 917866f387..9b83d3421f 100644 --- a/deps/uv/src/unix/freebsd.c +++ b/deps/uv/src/unix/freebsd.c @@ -197,10 +197,12 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), multiplier = ((uint64_t)1000L / ticks), cpuspeed, maxcpus, cur = 0; + uv_cpu_info_t* cpu_info; char model[512]; + long* cp_times; int numcpus; size_t size; - uv_cpu_info_t* cpu_info; + int i; size = sizeof(model); if (sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) { @@ -223,20 +225,28 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { free(*cpu_infos); return uv__new_sys_error(errno); } - // kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of ncpu + /* kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of ncpu */ size = sizeof(maxcpus); if (sysctlbyname("kern.smp.maxcpus", &maxcpus, &size, NULL, 0) < 0) { free(*cpu_infos); return uv__new_sys_error(errno); } + size = maxcpus * CPUSTATES * sizeof(long); - long cp_times[size]; + + cp_times = malloc(size); + if (cp_times == NULL) { + free(*cpu_infos); + return uv__new_sys_error(ENOMEM); + } + if (sysctlbyname("kern.cp_times", &cp_times, &size, NULL, 0) < 0) { + free(cp_times); free(*cpu_infos); return uv__new_sys_error(errno); } - for (int i = 0; i < numcpus; i++) { + for (i = 0; i < numcpus; i++) { cpu_info = &(*cpu_infos)[i]; cpu_info->cpu_times.user = (uint64_t)(cp_times[CP_USER+cur]) * multiplier; @@ -251,6 +261,7 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { cur+=CPUSTATES; } + free(cp_times); return uv_ok_; } diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c index 58a6816d8a..cea583355b 100644 --- a/deps/uv/src/unix/kqueue.c +++ b/deps/uv/src/unix/kqueue.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c index ee94ab3ed8..c05dd5df3b 100644 --- a/deps/uv/src/unix/tcp.c +++ b/deps/uv/src/unix/tcp.c @@ -22,6 +22,7 @@ #include "uv.h" #include "internal.h" +#include #include #include diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index 518c1ac514..5c70405042 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -26,6 +26,7 @@ #include #include #include +#include static void uv__udp_run_completed(uv_udp_t* handle); @@ -343,6 +344,14 @@ static int uv__bind(uv_udp_t* handle, goto out; } +#ifdef SO_REUSEPORT /* Apple's version of SO_REUSEADDR... */ + yes = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof yes) == -1) { + uv__set_sys_error(handle->loop, errno); + goto out; + } +#endif + if (flags & UV_UDP_IPV6ONLY) { #ifdef IPV6_V6ONLY yes = 1; @@ -512,27 +521,25 @@ int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, return 0; } -int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { - if (setsockopt(handle->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof ttl) == -1) { - uv__set_sys_error(handle->loop, errno); - return -1; - } - return 0; -} - -int uv_udp_set_broadcast(uv_udp_t* handle, int on) { - if (setsockopt(handle->fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof on) == -1) { - uv__set_sys_error(handle->loop, errno); - return -1; +#define X(name, level, option) \ + int uv_udp_set_##name(uv_udp_t* handle, int flag) { \ + if (setsockopt(handle->fd, level, option, &flag, sizeof(flag))) { \ + uv__set_sys_error(handle->loop, errno); \ + return -1; \ + } \ + return 0; \ } - return 0; -} +X(multicast_loop, IPPROTO_IP, IP_MULTICAST_LOOP) +X(multicast_ttl, IPPROTO_IP, IP_MULTICAST_TTL) +X(broadcast, SOL_SOCKET, SO_BROADCAST) +X(ttl, IPPROTO_IP, IP_TTL) + +#undef X -int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, - int* namelen) { +int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen) { socklen_t socklen; int saved_errno; int rv = 0; diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c index 12ce4d1b5d..59c9ea8346 100644 --- a/deps/uv/src/win/error.c +++ b/deps/uv/src/win/error.c @@ -94,6 +94,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case WSAEMSGSIZE: return UV_EMSGSIZE; case ERROR_NETWORK_UNREACHABLE: return UV_ENETUNREACH; case WSAENETUNREACH: return UV_ENETUNREACH; + case WSAENOBUFS: return UV_ENOBUFS; case ERROR_OUTOFMEMORY: return UV_ENOMEM; case ERROR_NOT_CONNECTED: return UV_ENOTCONN; case WSAENOTCONN: return UV_ENOTCONN; diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index d7087b1f55..6948f7ef1c 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -489,6 +489,103 @@ void fs__readdir(uv_fs_t* req, const wchar_t* path, int flags) { } +#define IS_SLASH(c) \ + ((wchar_t) c == L'/' || (wchar_t) c == L'\\') +#define IS_COLON(c) \ + ((wchar_t) c == L':') +#define IS_LETTER(c) \ + ((((wchar_t) c >= L'a') && ((wchar_t) c <= L'z')) || \ + (((wchar_t) c >= L'A') && ((wchar_t) c <= L'Z'))) +#define IS_QUESTION(c) \ + ((wchar_t) c == L'?') + + +static int uv__count_slash_separated_words(const wchar_t* pos, + const wchar_t* end, + int limit) { + char last_was_slash = 1, count = 0; + + for (; pos < end; pos++) { + if (IS_SLASH(*pos)) { + /* Don't accept double slashes */ + if (last_was_slash) { + return 0; + } else { + last_was_slash = 1; + } + } else { + if (last_was_slash) { + /* Found a new word */ + count++; + if (count > limit) { + return -1; + } + last_was_slash = 0; + } + } + } + + return count; +} + +/* + * Returns true if the given path is a root directory. The following patterns + * are recognized: + * \ + * c:\ (must have trailing slash) + * \\server\share (trailing slash optional) + * \\?\c: (trailing slash optional) + * \\?\UNC\server\share (trailing slash optional) + */ +static int uv__is_root(const wchar_t* path) { + size_t len = wcslen(path); + + /* Test for \ */ + if (len == 0 && IS_SLASH(path[0])) { + return 1; + } + + if (len < 3) { + return 0; + } + + /* Test for c:\ */ + if (IS_LETTER(path[0]) && IS_COLON(path[1]) && IS_SLASH(path[2])) { + return 1; + } + + if (!IS_SLASH(path[0]) || !IS_SLASH(path[1])) { + return 0; + } + + /* Test for \\server\share */ + if (!IS_QUESTION(path[2])) { + return uv__count_slash_separated_words(path + 2, path + len, 2) == 2; + } + + if (!IS_SLASH(path[3])) { + return 0; + } + + if ((len == 6 || len == 7) && + IS_LETTER(path[4]) && IS_COLON(path[5]) && + (len == 6 || IS_SLASH(path[6]))) { + return 1; + } + + /* Test for \\?\UNC\server\share */ + if (len >= 8 && + (path[4] == L'u' || path[4] == L'U') && + (path[5] == L'n' || path[5] == L'N') && + (path[6] == L'c' || path[6] == L'C') && + IS_SLASH(path[7])) { + return uv__count_slash_separated_words(path + 8, path + len, 2) == 2; + } + + return 0; +} + + void fs__stat(uv_fs_t* req, const wchar_t* path) { HANDLE file; WIN32_FIND_DATAW ent; @@ -496,6 +593,30 @@ void fs__stat(uv_fs_t* req, const wchar_t* path) { req->ptr = NULL; + if (uv__is_root(path)) { + /* We can't stat root directories like c:\. _wstati64 can't either, but */ + /* it will make up something reasonable. */ + DWORD drive_type = GetDriveTypeW(path); + if (drive_type == DRIVE_UNKNOWN || drive_type == DRIVE_NO_ROOT_DIR) { + req->last_error = ERROR_PATH_NOT_FOUND; + req->errorno = UV_ENOENT; + req->result = -1; + return; + } + + memset(&req->stat, 0, sizeof req->stat); + + req->stat.st_nlink = 1; + req->stat.st_mode = ((_S_IREAD|_S_IWRITE) + ((_S_IREAD|_S_IWRITE) >> 3) + + ((_S_IREAD|_S_IWRITE) >> 6)) | S_IFDIR; + + req->last_error = ERROR_SUCCESS; + req->errorno = UV_OK; + req->result = 0; + req->ptr = &req->stat; + return; + } + file = FindFirstFileExW(path, FindExInfoStandard, &ent, FindExSearchNameMatch, NULL, 0); @@ -516,7 +637,7 @@ void fs__stat(uv_fs_t* req, const wchar_t* path) { if (result != -1) { req->ptr = &req->stat; } - + SET_REQ_RESULT(req, result); } diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index 73e30f14ef..6a4d39dea0 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -1069,13 +1069,26 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { bg_bright = 0; } else if (arg == 1) { - /* Bright */ + /* Foreground bright on */ fg_bright = 1; + } else if (arg == 2) { + /* Both bright off */ + fg_bright = 0; + bg_bright = 0; + + } else if (arg == 5) { + /* Background bright on */ + bg_bright = 1; + } else if (arg == 21 || arg == 22) { - /* Bright off. */ + /* Foreground bright off */ fg_bright = 0; + } else if (arg == 25) { + /* Background bright off */ + bg_bright = 0; + } else if (arg >= 30 && arg <= 37) { /* Set foreground color */ fg_color = arg - 30; @@ -1091,6 +1104,17 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { } else if (arg == 49) { /* Default background color */ bg_color = 0; + + } else if (arg >= 90 && arg <= 97) { + /* Set bold foreground color */ + fg_bright = 1; + fg_color = arg - 90; + + } else if (arg >= 100 && arg <= 107) { + /* Set bold background color */ + bg_bright = 1; + bg_color = arg - 100; + } } diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c index 1b84ae9e45..08ffd8d12d 100644 --- a/deps/uv/src/win/udp.c +++ b/deps/uv/src/win/udp.c @@ -575,6 +575,12 @@ void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle, } +int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) { + uv__set_artificial_error(handle->loop, UV_ENOSYS); + return -1; +} + + int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { if (setsockopt(handle->socket, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, sizeof ttl) == -1) { @@ -595,3 +601,9 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int on) { return 0; } + + +int uv_udp_set_ttl(uv_udp_t* handle, int ttl) { + uv__set_artificial_error(handle->loop, UV_ENOSYS); + return -1; +} diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 763af8a78d..1601ac442f 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -45,6 +45,7 @@ # define close _close #endif +#define TOO_LONG_NAME_LENGTH 8192 typedef struct { const char* path; @@ -416,6 +417,14 @@ static void open_noent_cb(uv_fs_t* req) { uv_fs_req_cleanup(req); } +static void open_nametoolong_cb(uv_fs_t* req) { + ASSERT(req->fs_type == UV_FS_OPEN); + ASSERT(req->errorno == UV_ENAMETOOLONG); + ASSERT(req->result == -1); + open_cb_count++; + uv_fs_req_cleanup(req); +} + TEST_IMPL(fs_file_noent) { uv_fs_t req; @@ -441,6 +450,31 @@ TEST_IMPL(fs_file_noent) { return 0; } +TEST_IMPL(fs_file_nametoolong) { + uv_fs_t req; + int r; + char name[TOO_LONG_NAME_LENGTH + 1]; + + loop = uv_default_loop(); + + memset(name, 'a', TOO_LONG_NAME_LENGTH); + name[TOO_LONG_NAME_LENGTH] = 0; + + r = uv_fs_open(loop, &req, name, O_RDONLY, 0, NULL); + ASSERT(r == -1); + ASSERT(req.result == -1); + ASSERT(uv_last_error(loop).code == UV_ENAMETOOLONG); + uv_fs_req_cleanup(&req); + + r = uv_fs_open(loop, &req, name, O_RDONLY, 0, open_nametoolong_cb); + ASSERT(r == 0); + + ASSERT(open_cb_count == 0); + uv_run(loop); + ASSERT(open_cb_count == 1); + + return 0; +} static void check_utime(const char* path, double atime, double mtime) { struct stat* s; @@ -1254,6 +1288,22 @@ TEST_IMPL(fs_utime) { } +#ifdef _WIN32 +TEST_IMPL(fs_stat_root) { + int r; + uv_loop_t* loop = uv_default_loop(); + + r = uv_fs_stat(loop, &stat_req, "c:\\", NULL); + ASSERT(r == 0); + + r = uv_fs_stat(loop, &stat_req, "\\\\?\\C:\\", NULL); + ASSERT(r == 0); + + return 0; +} +#endif + + TEST_IMPL(fs_futime) { utime_check_t checkme; const char* path = "test_file"; @@ -1543,4 +1593,4 @@ TEST_IMPL(fs_rename_to_existing_file) { unlink("test_file2"); return 0; -} \ No newline at end of file +} diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 0678372ae4..31dcb0a64c 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -106,6 +106,7 @@ TEST_DECLARE (spawn_and_kill_with_std) TEST_DECLARE (spawn_and_ping) TEST_DECLARE (kill) TEST_DECLARE (fs_file_noent) +TEST_DECLARE (fs_file_nametoolong) TEST_DECLARE (fs_file_async) TEST_DECLARE (fs_file_sync) TEST_DECLARE (fs_async_dir) @@ -143,6 +144,7 @@ TEST_DECLARE (argument_escaping) TEST_DECLARE (environment_creation) TEST_DECLARE (listen_with_simultaneous_accepts) TEST_DECLARE (listen_no_simultaneous_accepts) +TEST_DECLARE (fs_stat_root) #endif HELPER_DECLARE (tcp4_echo_server) HELPER_DECLARE (tcp6_echo_server) @@ -281,9 +283,11 @@ TASK_LIST_START TEST_ENTRY (environment_creation) TEST_ENTRY (listen_with_simultaneous_accepts) TEST_ENTRY (listen_no_simultaneous_accepts) + TEST_ENTRY (fs_stat_root) #endif TEST_ENTRY (fs_file_noent) + TEST_ENTRY (fs_file_nametoolong) TEST_ENTRY (fs_file_async) TEST_ENTRY (fs_file_sync) TEST_ENTRY (fs_async_dir) diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 4f2c225ae6..7a88cfa1ab 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -250,6 +250,11 @@ 'EV_CONFIG_H="config_freebsd.h"', 'EIO_CONFIG_H="config_freebsd.h"', ], + 'direct_dependent_settings': { + 'libraries': [ + '-lkvm', + ], + }, }], [ 'OS=="openbsd"', { 'include_dirs': [ 'src/ares/config_openbsd' ],