diff options
author | Saúl Ibarra Corretgé <saghul@gmail.com> | 2014-10-21 00:45:30 +0200 |
---|---|---|
committer | Trevor Norris <trev.norris@gmail.com> | 2014-11-05 16:49:57 -0800 |
commit | ce112c27c636ba17129d6061f8db636a80faeb48 (patch) | |
tree | 50e2a8185185b31573fe57b2d33cbf7dfa7529bc /deps/uv/src | |
parent | 28ae70ebad8debd8aa7b521a693aa3de89ad84d6 (diff) | |
download | android-node-v8-ce112c27c636ba17129d6061f8db636a80faeb48.tar.gz android-node-v8-ce112c27c636ba17129d6061f8db636a80faeb48.tar.bz2 android-node-v8-ce112c27c636ba17129d6061f8db636a80faeb48.zip |
deps: update uv to v1.0.0-rc2
PR-URL: https://github.com/joyent/node/pull/8566
Reviewed-by: Fedor Indutny <fedor@indutny.com>
Reviewed-by: Trevor Norris <trev.norris@gmail.com>
Diffstat (limited to 'deps/uv/src')
-rw-r--r-- | deps/uv/src/unix/core.c | 2 | ||||
-rw-r--r-- | deps/uv/src/unix/fs.c | 32 | ||||
-rw-r--r-- | deps/uv/src/unix/thread.c | 5 | ||||
-rw-r--r-- | deps/uv/src/uv-common.c | 10 | ||||
-rw-r--r-- | deps/uv/src/uv-common.h | 2 | ||||
-rw-r--r-- | deps/uv/src/win/fs.c | 68 | ||||
-rw-r--r-- | deps/uv/src/win/poll.c | 2 | ||||
-rw-r--r-- | deps/uv/src/win/thread.c | 5 | ||||
-rw-r--r-- | deps/uv/src/win/util.c | 185 |
9 files changed, 245 insertions, 66 deletions
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 9dcc3935dc..7add085fea 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -637,7 +637,7 @@ int uv_cwd(char* buffer, size_t* size) { if (getcwd(buffer, *size) == NULL) return -errno; - *size = strlen(buffer) + 1; + *size = strlen(buffer); return 0; } diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 9bb7baf774..65fd01230b 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -295,22 +295,21 @@ done: #if defined(__OpenBSD__) || (defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8)) -static int uv__fs_readdir_filter(uv__dirent_t* dent) { +static int uv__fs_scandir_filter(uv__dirent_t* dent) { #else -static int uv__fs_readdir_filter(const uv__dirent_t* dent) { +static int uv__fs_scandir_filter(const uv__dirent_t* dent) { #endif return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0; } -/* This should have been called uv__fs_scandir(). */ -static ssize_t uv__fs_readdir(uv_fs_t* req) { +static ssize_t uv__fs_scandir(uv_fs_t* req) { uv__dirent_t **dents; int saved_errno; int n; dents = NULL; - n = scandir(req->path, &dents, uv__fs_readdir_filter, alphasort); + n = scandir(req->path, &dents, uv__fs_scandir_filter, alphasort); /* NOTE: We will use nbufs as an index field */ req->nbufs = 0; @@ -764,6 +763,7 @@ static void uv__fs_work(struct uv__work* w) { 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)); @@ -779,7 +779,7 @@ static void uv__fs_work(struct uv__work* w) { X(MKDIR, mkdir(req->path, req->mode)); X(MKDTEMP, uv__fs_mkdtemp(req)); X(READ, uv__fs_read(req)); - X(READDIR, uv__fs_readdir(req)); + X(SCANDIR, uv__fs_scandir(req)); X(READLINK, uv__fs_readlink(req)); X(RENAME, rename(req->path, req->new_path)); X(RMDIR, rmdir(req->path)); @@ -854,6 +854,18 @@ static void uv__fs_done(struct uv__work* w, int status) { } +int uv_fs_access(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + int flags, + uv_fs_cb cb) { + INIT(ACCESS); + PATH; + req->flags = flags; + POST; +} + + int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, @@ -1040,12 +1052,12 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, } -int uv_fs_readdir(uv_loop_t* loop, +int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) { - INIT(READDIR); + INIT(SCANDIR); PATH; req->flags = flags; POST; @@ -1167,8 +1179,8 @@ 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); if (req->ptr != &req->statbuf) free(req->ptr); diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index 522426f634..00579cb8f0 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -36,6 +36,11 @@ int uv_thread_join(uv_thread_t *tid) { } +int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) { + return pthread_equal(*t1, *t2); +} + + int uv_mutex_init(uv_mutex_t* mutex) { #if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK) return -pthread_mutex_init(mutex, NULL); diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 13e732dd36..69fc53ae2c 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -306,11 +306,11 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { } -unsigned long uv_thread_self(void) { +uv_thread_t uv_thread_self(void) { #ifdef _WIN32 - return (unsigned long) GetCurrentThreadId(); + return GetCurrentThreadId(); #else - return (unsigned long) pthread_self(); + return pthread_self(); #endif } @@ -437,7 +437,7 @@ int uv_fs_event_getpath(uv_fs_event_t* handle, char* buf, size_t* len) { } -void uv__fs_readdir_cleanup(uv_fs_t* req) { +void uv__fs_scandir_cleanup(uv_fs_t* req) { uv__dirent_t** dents; dents = req->ptr; @@ -448,7 +448,7 @@ void uv__fs_readdir_cleanup(uv_fs_t* req) { } -int uv_fs_readdir_next(uv_fs_t* req, uv_dirent_t* ent) { +int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) { uv__dirent_t** dents; uv__dirent_t* dent; diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index c9bad2f16b..e06606c19b 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -109,7 +109,7 @@ size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs); int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value); -void uv__fs_readdir_cleanup(uv_fs_t* req); +void uv__fs_scandir_cleanup(uv_fs_t* req); #define uv__has_active_reqs(loop) \ (QUEUE_EMPTY(&(loop)->active_reqs) == 0) diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index d3801460e8..11d20f2dbd 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -613,11 +613,6 @@ void fs__write(uv_fs_t* req) { if (offset != -1) { memset(&overlapped, 0, sizeof overlapped); - - offset_.QuadPart = offset; - overlapped.Offset = offset_.LowPart; - overlapped.OffsetHigh = offset_.HighPart; - overlapped_ptr = &overlapped; } else { overlapped_ptr = NULL; @@ -627,6 +622,14 @@ void fs__write(uv_fs_t* req) { bytes = 0; do { DWORD incremental_bytes; + + /* WriteFile() does not advance overlapped as ReadFile() does. */ + if (offset != -1) { + offset_.QuadPart = offset + bytes; + overlapped.Offset = offset_.LowPart; + overlapped.OffsetHigh = offset_.HighPart; + } + result = WriteFile(handle, req->bufs[index].base, req->bufs[index].len, @@ -783,7 +786,7 @@ void fs__mkdtemp(uv_fs_t* req) { } -void fs__readdir(uv_fs_t* req) { +void fs__scandir(uv_fs_t* req) { WCHAR* pathw = req->pathw; size_t len = wcslen(pathw); int result; @@ -1220,6 +1223,25 @@ static void fs__sendfile(uv_fs_t* req) { } +static void fs__access(uv_fs_t* req) { + DWORD attr = GetFileAttributesW(req->pathw); + + if (attr == INVALID_FILE_ATTRIBUTES) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + return; + } + + if ((req->flags & W_OK) && + ((attr & FILE_ATTRIBUTE_READONLY) || + (attr & FILE_ATTRIBUTE_DIRECTORY))) { + SET_REQ_WIN32_ERROR(req, UV_EPERM); + return; + } + + SET_REQ_RESULT(req, 0); +} + + static void fs__chmod(uv_fs_t* req) { int result = _wchmod(req->pathw, req->mode); SET_REQ_RESULT(req, result); @@ -1595,6 +1617,7 @@ static void uv__fs_work(struct uv__work* w) { XX(FTRUNCATE, ftruncate) XX(UTIME, utime) XX(FUTIME, futime) + XX(ACCESS, access) XX(CHMOD, chmod) XX(FCHMOD, fchmod) XX(FSYNC, fsync) @@ -1604,7 +1627,7 @@ static void uv__fs_work(struct uv__work* w) { XX(MKDIR, mkdir) XX(MKDTEMP, mkdtemp) XX(RENAME, rename) - XX(READDIR, readdir) + XX(SCANDIR, scandir) XX(LINK, link) XX(SYMLINK, symlink) XX(READLINK, readlink) @@ -1839,11 +1862,11 @@ int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { } -int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, +int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_READDIR, cb); + uv_fs_req_init(loop, req, UV_FS_SCANDIR, cb); err = fs__capture_path(loop, req, path, NULL, cb != NULL); if (err) { @@ -1856,7 +1879,7 @@ int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, QUEUE_FS_TP_JOB(loop, req); return 0; } else { - fs__readdir(req); + fs__scandir(req); return req->result; } } @@ -2102,6 +2125,31 @@ int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out, } +int uv_fs_access(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + int flags, + uv_fs_cb cb) { + int err; + + uv_fs_req_init(loop, req, UV_FS_ACCESS, cb); + + err = fs__capture_path(loop, req, path, NULL, cb != NULL); + if (err) + return uv_translate_sys_error(err); + + req->flags = flags; + + if (cb) { + QUEUE_FS_TP_JOB(loop, req); + return 0; + } + + fs__access(req); + return req->result; +} + + int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) { int err; diff --git a/deps/uv/src/win/poll.c b/deps/uv/src/win/poll.c index bf3739985a..85c314828b 100644 --- a/deps/uv/src/win/poll.c +++ b/deps/uv/src/win/poll.c @@ -530,7 +530,7 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, SO_PROTOCOL_INFOW, (char*) &protocol_info, &len) != 0) { - return WSAGetLastError(); + return uv_translate_sys_error(WSAGetLastError()); } /* Get the peer socket that is needed to enable fast poll. If the returned */ diff --git a/deps/uv/src/win/thread.c b/deps/uv/src/win/thread.c index ccc5579fa7..5d8d568c01 100644 --- a/deps/uv/src/win/thread.c +++ b/deps/uv/src/win/thread.c @@ -129,6 +129,11 @@ int uv_thread_join(uv_thread_t *tid) { } +int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) { + return *t1 == *t2; +} + + int uv_mutex_init(uv_mutex_t* mutex) { InitializeCriticalSection(mutex); return 0; diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 8d1aefc538..b7dba7bbda 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -206,7 +206,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; + *size = r -1; return UV_ENOBUFS; } @@ -223,7 +223,7 @@ int uv_cwd(char* buffer, size_t* size) { return uv_translate_sys_error(GetLastError()); } - *size = r; + *size = r - 1; return 0; } @@ -778,11 +778,76 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { } +static int is_windows_version_or_greater(DWORD os_major, + DWORD os_minor, + WORD service_pack_major, + WORD service_pack_minor) { + OSVERSIONINFOEX osvi; + DWORDLONG condition_mask = 0; + int op = VER_GREATER_EQUAL; + + /* Initialize the OSVERSIONINFOEX structure. */ + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + osvi.dwMajorVersion = os_major; + osvi.dwMinorVersion = os_minor; + osvi.wServicePackMajor = service_pack_major; + osvi.wServicePackMinor = service_pack_minor; + + /* Initialize the condition mask. */ + VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, op); + VER_SET_CONDITION(condition_mask, VER_MINORVERSION, op); + VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMAJOR, op); + VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMINOR, op); + + /* Perform the test. */ + return (int) VerifyVersionInfo( + &osvi, + VER_MAJORVERSION | VER_MINORVERSION | + VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, + condition_mask); +} + + +static int address_prefix_match(int family, + struct sockaddr* address, + struct sockaddr* prefix_address, + int prefix_len) { + uint8_t* address_data; + uint8_t* prefix_address_data; + int i; + + assert(address->sa_family == family); + assert(prefix_address->sa_family == family); + + if (family == AF_INET6) { + address_data = (uint8_t*) &(((struct sockaddr_in6 *) address)->sin6_addr); + prefix_address_data = + (uint8_t*) &(((struct sockaddr_in6 *) prefix_address)->sin6_addr); + } else { + address_data = (uint8_t*) &(((struct sockaddr_in *) address)->sin_addr); + prefix_address_data = + (uint8_t*) &(((struct sockaddr_in *) prefix_address)->sin_addr); + } + + for (i = 0; i < prefix_len >> 3; i++) { + if (address_data[i] != prefix_address_data[i]) + return 0; + } + + if (prefix_len % 8) + return prefix_address_data[i] == + (address_data[i] & (0xff << (8 - prefix_len % 8))); + + return 1; +} + + int uv_interface_addresses(uv_interface_address_t** addresses_ptr, int* count_ptr) { IP_ADAPTER_ADDRESSES* win_address_buf; ULONG win_address_buf_size; - IP_ADAPTER_ADDRESSES* win_address; + IP_ADAPTER_ADDRESSES* adapter; uv_interface_address_t* uv_address_buf; char* name_buf; @@ -791,6 +856,23 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, int count; + int is_vista_or_greater; + ULONG flags; + + is_vista_or_greater = is_windows_version_or_greater(6, 0, 0, 0); + if (is_vista_or_greater) { + flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER; + } else { + /* We need at least XP SP1. */ + if (!is_windows_version_or_greater(5, 1, 1, 0)) + return UV_ENOTSUP; + + flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX; + } + + /* Fetch the size of the adapters reported by windows, and then get the */ /* list itself. */ win_address_buf_size = 0; @@ -803,7 +885,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, /* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in */ /* win_address_buf_size. */ r = GetAdaptersAddresses(AF_UNSPEC, - GAA_FLAG_INCLUDE_PREFIX, + flags, NULL, win_address_buf, &win_address_buf_size); @@ -862,25 +944,23 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, count = 0; uv_address_buf_size = 0; - for (win_address = win_address_buf; - win_address != NULL; - win_address = win_address->Next) { - /* Use IP_ADAPTER_UNICAST_ADDRESS_XP to retain backwards compatibility */ - /* with Windows XP */ - IP_ADAPTER_UNICAST_ADDRESS_XP* unicast_address; + for (adapter = win_address_buf; + adapter != NULL; + adapter = adapter->Next) { + IP_ADAPTER_UNICAST_ADDRESS* unicast_address; int name_size; /* Interfaces that are not 'up' should not be reported. Also skip */ /* interfaces that have no associated unicast address, as to avoid */ /* allocating space for the name for this interface. */ - if (win_address->OperStatus != IfOperStatusUp || - win_address->FirstUnicastAddress == NULL) + if (adapter->OperStatus != IfOperStatusUp || + adapter->FirstUnicastAddress == NULL) continue; /* Compute the size of the interface name. */ name_size = WideCharToMultiByte(CP_UTF8, 0, - win_address->FriendlyName, + adapter->FriendlyName, -1, NULL, 0, @@ -894,8 +974,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, /* Count the number of addresses associated with this interface, and */ /* compute the size. */ - for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*) - win_address->FirstUnicastAddress; + for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*) + adapter->FirstUnicastAddress; unicast_address != NULL; unicast_address = unicast_address->Next) { count++; @@ -916,16 +996,15 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, name_buf = (char*) (uv_address_buf + count); /* Fill out the output buffer. */ - for (win_address = win_address_buf; - win_address != NULL; - win_address = win_address->Next) { - IP_ADAPTER_UNICAST_ADDRESS_XP* unicast_address; - IP_ADAPTER_PREFIX* prefix; + for (adapter = win_address_buf; + adapter != NULL; + adapter = adapter->Next) { + IP_ADAPTER_UNICAST_ADDRESS* unicast_address; int name_size; size_t max_name_size; - if (win_address->OperStatus != IfOperStatusUp || - win_address->FirstUnicastAddress == NULL) + if (adapter->OperStatus != IfOperStatusUp || + adapter->FirstUnicastAddress == NULL) continue; /* Convert the interface name to UTF8. */ @@ -934,7 +1013,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, max_name_size = INT_MAX; name_size = WideCharToMultiByte(CP_UTF8, 0, - win_address->FriendlyName, + adapter->FriendlyName, -1, name_buf, (int) max_name_size, @@ -946,47 +1025,77 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, return uv_translate_sys_error(GetLastError()); } - prefix = win_address->FirstPrefix; - /* Add an uv_interface_address_t element for every unicast address. */ - /* Walk the prefix list in tandem with the address list. */ - for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*) - win_address->FirstUnicastAddress; - unicast_address != NULL && prefix != NULL; - unicast_address = unicast_address->Next, prefix = prefix->Next) { + for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*) + adapter->FirstUnicastAddress; + unicast_address != NULL; + unicast_address = unicast_address->Next) { struct sockaddr* sa; ULONG prefix_len; sa = unicast_address->Address.lpSockaddr; - prefix_len = prefix->PrefixLength; + + /* XP has no OnLinkPrefixLength field. */ + if (is_vista_or_greater) { + prefix_len = unicast_address->OnLinkPrefixLength; + } else { + /* Prior to Windows Vista the FirstPrefix pointed to the list with + * single prefix for each IP address assigned to the adapter. + * Order of FirstPrefix does not match order of FirstUnicastAddress, + * so we need to find corresponding prefix. + */ + IP_ADAPTER_PREFIX* prefix; + prefix_len = 0; + + for (prefix = adapter->FirstPrefix; prefix; prefix = prefix->Next) { + /* We want the longest matching prefix. */ + if (prefix->Address.lpSockaddr->sa_family != sa->sa_family || + prefix->PrefixLength <= prefix_len) + continue; + + if (address_prefix_match(sa->sa_family, sa, + prefix->Address.lpSockaddr, prefix->PrefixLength)) { + prefix_len = prefix->PrefixLength; + } + } + + /* If there is no matching prefix information, return a single-host + * subnet mask (e.g. 255.255.255.255 for IPv4). + */ + if (!prefix_len) + prefix_len = (sa->sa_family == AF_INET6) ? 128 : 32; + } memset(uv_address, 0, sizeof *uv_address); uv_address->name = name_buf; - if (win_address->PhysicalAddressLength == sizeof(uv_address->phys_addr)) { + if (adapter->PhysicalAddressLength == sizeof(uv_address->phys_addr)) { memcpy(uv_address->phys_addr, - win_address->PhysicalAddress, + adapter->PhysicalAddress, sizeof(uv_address->phys_addr)); } uv_address->is_internal = - (win_address->IfType == IF_TYPE_SOFTWARE_LOOPBACK); + (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK); if (sa->sa_family == AF_INET6) { uv_address->address.address6 = *((struct sockaddr_in6 *) sa); uv_address->netmask.netmask6.sin6_family = AF_INET6; memset(uv_address->netmask.netmask6.sin6_addr.s6_addr, 0xff, prefix_len >> 3); - uv_address->netmask.netmask6.sin6_addr.s6_addr[prefix_len >> 3] = - 0xff << (8 - prefix_len % 8); + /* This check ensures that we don't write past the size of the data. */ + if (prefix_len % 8) { + uv_address->netmask.netmask6.sin6_addr.s6_addr[prefix_len >> 3] = + 0xff << (8 - prefix_len % 8); + } } else { uv_address->address.address4 = *((struct sockaddr_in *) sa); uv_address->netmask.netmask4.sin_family = AF_INET; - uv_address->netmask.netmask4.sin_addr.s_addr = - htonl(0xffffffff << (32 - prefix_len)); + uv_address->netmask.netmask4.sin_addr.s_addr = (prefix_len > 0) ? + htonl(0xffffffff << (32 - prefix_len)) : 0; } uv_address++; |