xref: /netbsd/external/mit/libuv/dist/src/uv-common.c (revision b29f2fbf)
1fbb2e0a3Schristos /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2fbb2e0a3Schristos  *
3fbb2e0a3Schristos  * Permission is hereby granted, free of charge, to any person obtaining a copy
4fbb2e0a3Schristos  * of this software and associated documentation files (the "Software"), to
5fbb2e0a3Schristos  * deal in the Software without restriction, including without limitation the
6fbb2e0a3Schristos  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7fbb2e0a3Schristos  * sell copies of the Software, and to permit persons to whom the Software is
8fbb2e0a3Schristos  * furnished to do so, subject to the following conditions:
9fbb2e0a3Schristos  *
10fbb2e0a3Schristos  * The above copyright notice and this permission notice shall be included in
11fbb2e0a3Schristos  * all copies or substantial portions of the Software.
12fbb2e0a3Schristos  *
13fbb2e0a3Schristos  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14fbb2e0a3Schristos  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15fbb2e0a3Schristos  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16fbb2e0a3Schristos  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17fbb2e0a3Schristos  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18fbb2e0a3Schristos  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19fbb2e0a3Schristos  * IN THE SOFTWARE.
20fbb2e0a3Schristos  */
21fbb2e0a3Schristos 
22fbb2e0a3Schristos #include "uv.h"
23fbb2e0a3Schristos #include "uv-common.h"
24fbb2e0a3Schristos 
25fbb2e0a3Schristos #include <assert.h>
26fbb2e0a3Schristos #include <errno.h>
27fbb2e0a3Schristos #include <stdarg.h>
28fbb2e0a3Schristos #include <stddef.h> /* NULL */
29fbb2e0a3Schristos #include <stdio.h>
30fbb2e0a3Schristos #include <stdlib.h> /* malloc */
31fbb2e0a3Schristos #include <string.h> /* memset */
32fbb2e0a3Schristos 
33fbb2e0a3Schristos #if defined(_WIN32)
34fbb2e0a3Schristos # include <malloc.h> /* malloc */
35fbb2e0a3Schristos #else
36fbb2e0a3Schristos # include <net/if.h> /* if_nametoindex */
37fbb2e0a3Schristos # include <sys/un.h> /* AF_UNIX, sockaddr_un */
38fbb2e0a3Schristos #endif
39fbb2e0a3Schristos 
40fbb2e0a3Schristos 
41fbb2e0a3Schristos typedef struct {
42fbb2e0a3Schristos   uv_malloc_func local_malloc;
43fbb2e0a3Schristos   uv_realloc_func local_realloc;
44fbb2e0a3Schristos   uv_calloc_func local_calloc;
45fbb2e0a3Schristos   uv_free_func local_free;
46fbb2e0a3Schristos } uv__allocator_t;
47fbb2e0a3Schristos 
48fbb2e0a3Schristos static uv__allocator_t uv__allocator = {
49fbb2e0a3Schristos   malloc,
50fbb2e0a3Schristos   realloc,
51fbb2e0a3Schristos   calloc,
52fbb2e0a3Schristos   free,
53fbb2e0a3Schristos };
54fbb2e0a3Schristos 
uv__strdup(const char * s)55fbb2e0a3Schristos char* uv__strdup(const char* s) {
56fbb2e0a3Schristos   size_t len = strlen(s) + 1;
57fbb2e0a3Schristos   char* m = uv__malloc(len);
58fbb2e0a3Schristos   if (m == NULL)
59fbb2e0a3Schristos     return NULL;
60fbb2e0a3Schristos   return memcpy(m, s, len);
61fbb2e0a3Schristos }
62fbb2e0a3Schristos 
uv__strndup(const char * s,size_t n)63fbb2e0a3Schristos char* uv__strndup(const char* s, size_t n) {
64fbb2e0a3Schristos   char* m;
65fbb2e0a3Schristos   size_t len = strlen(s);
66fbb2e0a3Schristos   if (n < len)
67fbb2e0a3Schristos     len = n;
68fbb2e0a3Schristos   m = uv__malloc(len + 1);
69fbb2e0a3Schristos   if (m == NULL)
70fbb2e0a3Schristos     return NULL;
71fbb2e0a3Schristos   m[len] = '\0';
72fbb2e0a3Schristos   return memcpy(m, s, len);
73fbb2e0a3Schristos }
74fbb2e0a3Schristos 
uv__malloc(size_t size)75fbb2e0a3Schristos void* uv__malloc(size_t size) {
76fbb2e0a3Schristos   if (size > 0)
77fbb2e0a3Schristos     return uv__allocator.local_malloc(size);
78fbb2e0a3Schristos   return NULL;
79fbb2e0a3Schristos }
80fbb2e0a3Schristos 
uv__free(void * ptr)81fbb2e0a3Schristos void uv__free(void* ptr) {
82fbb2e0a3Schristos   int saved_errno;
83fbb2e0a3Schristos 
84fbb2e0a3Schristos   /* Libuv expects that free() does not clobber errno.  The system allocator
85fbb2e0a3Schristos    * honors that assumption but custom allocators may not be so careful.
86fbb2e0a3Schristos    */
87fbb2e0a3Schristos   saved_errno = errno;
88fbb2e0a3Schristos   uv__allocator.local_free(ptr);
89fbb2e0a3Schristos   errno = saved_errno;
90fbb2e0a3Schristos }
91fbb2e0a3Schristos 
uv__calloc(size_t count,size_t size)92fbb2e0a3Schristos void* uv__calloc(size_t count, size_t size) {
93fbb2e0a3Schristos   return uv__allocator.local_calloc(count, size);
94fbb2e0a3Schristos }
95fbb2e0a3Schristos 
uv__realloc(void * ptr,size_t size)96fbb2e0a3Schristos void* uv__realloc(void* ptr, size_t size) {
97fbb2e0a3Schristos   if (size > 0)
98fbb2e0a3Schristos     return uv__allocator.local_realloc(ptr, size);
99fbb2e0a3Schristos   uv__free(ptr);
100fbb2e0a3Schristos   return NULL;
101fbb2e0a3Schristos }
102fbb2e0a3Schristos 
uv__reallocf(void * ptr,size_t size)103fbb2e0a3Schristos void* uv__reallocf(void* ptr, size_t size) {
104fbb2e0a3Schristos   void* newptr;
105fbb2e0a3Schristos 
106fbb2e0a3Schristos   newptr = uv__realloc(ptr, size);
107fbb2e0a3Schristos   if (newptr == NULL)
108fbb2e0a3Schristos     if (size > 0)
109fbb2e0a3Schristos       uv__free(ptr);
110fbb2e0a3Schristos 
111fbb2e0a3Schristos   return newptr;
112fbb2e0a3Schristos }
113fbb2e0a3Schristos 
uv_replace_allocator(uv_malloc_func malloc_func,uv_realloc_func realloc_func,uv_calloc_func calloc_func,uv_free_func free_func)114fbb2e0a3Schristos int uv_replace_allocator(uv_malloc_func malloc_func,
115fbb2e0a3Schristos                          uv_realloc_func realloc_func,
116fbb2e0a3Schristos                          uv_calloc_func calloc_func,
117fbb2e0a3Schristos                          uv_free_func free_func) {
118fbb2e0a3Schristos   if (malloc_func == NULL || realloc_func == NULL ||
119fbb2e0a3Schristos       calloc_func == NULL || free_func == NULL) {
120fbb2e0a3Schristos     return UV_EINVAL;
121fbb2e0a3Schristos   }
122fbb2e0a3Schristos 
123fbb2e0a3Schristos   uv__allocator.local_malloc = malloc_func;
124fbb2e0a3Schristos   uv__allocator.local_realloc = realloc_func;
125fbb2e0a3Schristos   uv__allocator.local_calloc = calloc_func;
126fbb2e0a3Schristos   uv__allocator.local_free = free_func;
127fbb2e0a3Schristos 
128fbb2e0a3Schristos   return 0;
129fbb2e0a3Schristos }
130fbb2e0a3Schristos 
131fbb2e0a3Schristos #define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t);
132fbb2e0a3Schristos 
uv_handle_size(uv_handle_type type)133fbb2e0a3Schristos size_t uv_handle_size(uv_handle_type type) {
134fbb2e0a3Schristos   switch (type) {
135fbb2e0a3Schristos     UV_HANDLE_TYPE_MAP(XX)
136fbb2e0a3Schristos     default:
137fbb2e0a3Schristos       return -1;
138fbb2e0a3Schristos   }
139fbb2e0a3Schristos }
140fbb2e0a3Schristos 
uv_req_size(uv_req_type type)141fbb2e0a3Schristos size_t uv_req_size(uv_req_type type) {
142fbb2e0a3Schristos   switch(type) {
143fbb2e0a3Schristos     UV_REQ_TYPE_MAP(XX)
144fbb2e0a3Schristos     default:
145fbb2e0a3Schristos       return -1;
146fbb2e0a3Schristos   }
147fbb2e0a3Schristos }
148fbb2e0a3Schristos 
149fbb2e0a3Schristos #undef XX
150fbb2e0a3Schristos 
151fbb2e0a3Schristos 
uv_loop_size(void)152fbb2e0a3Schristos size_t uv_loop_size(void) {
153fbb2e0a3Schristos   return sizeof(uv_loop_t);
154fbb2e0a3Schristos }
155fbb2e0a3Schristos 
156fbb2e0a3Schristos 
uv_buf_init(char * base,unsigned int len)157fbb2e0a3Schristos uv_buf_t uv_buf_init(char* base, unsigned int len) {
158fbb2e0a3Schristos   uv_buf_t buf;
159fbb2e0a3Schristos   buf.base = base;
160fbb2e0a3Schristos   buf.len = len;
161fbb2e0a3Schristos   return buf;
162fbb2e0a3Schristos }
163fbb2e0a3Schristos 
164fbb2e0a3Schristos 
uv__unknown_err_code(int err)165fbb2e0a3Schristos static const char* uv__unknown_err_code(int err) {
166fbb2e0a3Schristos   char buf[32];
167fbb2e0a3Schristos   char* copy;
168fbb2e0a3Schristos 
169fbb2e0a3Schristos   snprintf(buf, sizeof(buf), "Unknown system error %d", err);
170fbb2e0a3Schristos   copy = uv__strdup(buf);
171fbb2e0a3Schristos 
172fbb2e0a3Schristos   return copy != NULL ? copy : "Unknown system error";
173fbb2e0a3Schristos }
174fbb2e0a3Schristos 
175fbb2e0a3Schristos #define UV_ERR_NAME_GEN_R(name, _) \
176fbb2e0a3Schristos case UV_## name: \
177fbb2e0a3Schristos   uv__strscpy(buf, #name, buflen); break;
uv_err_name_r(int err,char * buf,size_t buflen)178fbb2e0a3Schristos char* uv_err_name_r(int err, char* buf, size_t buflen) {
179fbb2e0a3Schristos   switch (err) {
180fbb2e0a3Schristos     UV_ERRNO_MAP(UV_ERR_NAME_GEN_R)
181fbb2e0a3Schristos     default: snprintf(buf, buflen, "Unknown system error %d", err);
182fbb2e0a3Schristos   }
183fbb2e0a3Schristos   return buf;
184fbb2e0a3Schristos }
185fbb2e0a3Schristos #undef UV_ERR_NAME_GEN_R
186fbb2e0a3Schristos 
187fbb2e0a3Schristos 
188fbb2e0a3Schristos #define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name;
uv_err_name(int err)189fbb2e0a3Schristos const char* uv_err_name(int err) {
190fbb2e0a3Schristos   switch (err) {
191fbb2e0a3Schristos     UV_ERRNO_MAP(UV_ERR_NAME_GEN)
192fbb2e0a3Schristos   }
193fbb2e0a3Schristos   return uv__unknown_err_code(err);
194fbb2e0a3Schristos }
195fbb2e0a3Schristos #undef UV_ERR_NAME_GEN
196fbb2e0a3Schristos 
197fbb2e0a3Schristos 
198fbb2e0a3Schristos #define UV_STRERROR_GEN_R(name, msg) \
199fbb2e0a3Schristos case UV_ ## name: \
200fbb2e0a3Schristos   snprintf(buf, buflen, "%s", msg); break;
uv_strerror_r(int err,char * buf,size_t buflen)201fbb2e0a3Schristos char* uv_strerror_r(int err, char* buf, size_t buflen) {
202fbb2e0a3Schristos   switch (err) {
203fbb2e0a3Schristos     UV_ERRNO_MAP(UV_STRERROR_GEN_R)
204fbb2e0a3Schristos     default: snprintf(buf, buflen, "Unknown system error %d", err);
205fbb2e0a3Schristos   }
206fbb2e0a3Schristos   return buf;
207fbb2e0a3Schristos }
208fbb2e0a3Schristos #undef UV_STRERROR_GEN_R
209fbb2e0a3Schristos 
210fbb2e0a3Schristos 
211fbb2e0a3Schristos #define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg;
uv_strerror(int err)212fbb2e0a3Schristos const char* uv_strerror(int err) {
213fbb2e0a3Schristos   switch (err) {
214fbb2e0a3Schristos     UV_ERRNO_MAP(UV_STRERROR_GEN)
215fbb2e0a3Schristos   }
216fbb2e0a3Schristos   return uv__unknown_err_code(err);
217fbb2e0a3Schristos }
218fbb2e0a3Schristos #undef UV_STRERROR_GEN
219fbb2e0a3Schristos 
220fbb2e0a3Schristos 
uv_ip4_addr(const char * ip,int port,struct sockaddr_in * addr)221fbb2e0a3Schristos int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) {
222fbb2e0a3Schristos   memset(addr, 0, sizeof(*addr));
223fbb2e0a3Schristos   addr->sin_family = AF_INET;
224fbb2e0a3Schristos   addr->sin_port = htons(port);
225fbb2e0a3Schristos #ifdef SIN6_LEN
226fbb2e0a3Schristos   addr->sin_len = sizeof(*addr);
227fbb2e0a3Schristos #endif
228fbb2e0a3Schristos   return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr));
229fbb2e0a3Schristos }
230fbb2e0a3Schristos 
231fbb2e0a3Schristos 
uv_ip6_addr(const char * ip,int port,struct sockaddr_in6 * addr)232fbb2e0a3Schristos int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) {
233fbb2e0a3Schristos   char address_part[40];
234fbb2e0a3Schristos   size_t address_part_size;
235fbb2e0a3Schristos   const char* zone_index;
236fbb2e0a3Schristos 
237fbb2e0a3Schristos   memset(addr, 0, sizeof(*addr));
238fbb2e0a3Schristos   addr->sin6_family = AF_INET6;
239fbb2e0a3Schristos   addr->sin6_port = htons(port);
240fbb2e0a3Schristos #ifdef SIN6_LEN
241fbb2e0a3Schristos   addr->sin6_len = sizeof(*addr);
242fbb2e0a3Schristos #endif
243fbb2e0a3Schristos 
244fbb2e0a3Schristos   zone_index = strchr(ip, '%');
245fbb2e0a3Schristos   if (zone_index != NULL) {
246fbb2e0a3Schristos     address_part_size = zone_index - ip;
247fbb2e0a3Schristos     if (address_part_size >= sizeof(address_part))
248fbb2e0a3Schristos       address_part_size = sizeof(address_part) - 1;
249fbb2e0a3Schristos 
250fbb2e0a3Schristos     memcpy(address_part, ip, address_part_size);
251fbb2e0a3Schristos     address_part[address_part_size] = '\0';
252fbb2e0a3Schristos     ip = address_part;
253fbb2e0a3Schristos 
254fbb2e0a3Schristos     zone_index++; /* skip '%' */
255fbb2e0a3Schristos     /* NOTE: unknown interface (id=0) is silently ignored */
256fbb2e0a3Schristos #ifdef _WIN32
257fbb2e0a3Schristos     addr->sin6_scope_id = atoi(zone_index);
258fbb2e0a3Schristos #else
259fbb2e0a3Schristos     addr->sin6_scope_id = if_nametoindex(zone_index);
260fbb2e0a3Schristos #endif
261fbb2e0a3Schristos   }
262fbb2e0a3Schristos 
263fbb2e0a3Schristos   return uv_inet_pton(AF_INET6, ip, &addr->sin6_addr);
264fbb2e0a3Schristos }
265fbb2e0a3Schristos 
266fbb2e0a3Schristos 
uv_ip4_name(const struct sockaddr_in * src,char * dst,size_t size)267fbb2e0a3Schristos int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) {
268fbb2e0a3Schristos   return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size);
269fbb2e0a3Schristos }
270fbb2e0a3Schristos 
271fbb2e0a3Schristos 
uv_ip6_name(const struct sockaddr_in6 * src,char * dst,size_t size)272fbb2e0a3Schristos int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) {
273fbb2e0a3Schristos   return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size);
274fbb2e0a3Schristos }
275fbb2e0a3Schristos 
276fbb2e0a3Schristos 
uv_ip_name(const struct sockaddr * src,char * dst,size_t size)277*b29f2fbfSchristos int uv_ip_name(const struct sockaddr *src, char *dst, size_t size) {
278*b29f2fbfSchristos   switch (src->sa_family) {
279*b29f2fbfSchristos   case AF_INET:
280*b29f2fbfSchristos     return uv_inet_ntop(AF_INET, &((struct sockaddr_in *)src)->sin_addr,
281*b29f2fbfSchristos                         dst, size);
282*b29f2fbfSchristos   case AF_INET6:
283*b29f2fbfSchristos     return uv_inet_ntop(AF_INET6, &((struct sockaddr_in6 *)src)->sin6_addr,
284*b29f2fbfSchristos                         dst, size);
285*b29f2fbfSchristos   default:
286*b29f2fbfSchristos     return UV_EAFNOSUPPORT;
287*b29f2fbfSchristos   }
288*b29f2fbfSchristos }
289*b29f2fbfSchristos 
290*b29f2fbfSchristos 
uv_tcp_bind(uv_tcp_t * handle,const struct sockaddr * addr,unsigned int flags)291fbb2e0a3Schristos int uv_tcp_bind(uv_tcp_t* handle,
292fbb2e0a3Schristos                 const struct sockaddr* addr,
293fbb2e0a3Schristos                 unsigned int flags) {
294fbb2e0a3Schristos   unsigned int addrlen;
295fbb2e0a3Schristos 
296fbb2e0a3Schristos   if (handle->type != UV_TCP)
297fbb2e0a3Schristos     return UV_EINVAL;
298*b29f2fbfSchristos   if (uv__is_closing(handle)) {
299*b29f2fbfSchristos     return UV_EINVAL;
300*b29f2fbfSchristos   }
301fbb2e0a3Schristos   if (addr->sa_family == AF_INET)
302fbb2e0a3Schristos     addrlen = sizeof(struct sockaddr_in);
303fbb2e0a3Schristos   else if (addr->sa_family == AF_INET6)
304fbb2e0a3Schristos     addrlen = sizeof(struct sockaddr_in6);
305fbb2e0a3Schristos   else
306fbb2e0a3Schristos     return UV_EINVAL;
307fbb2e0a3Schristos 
308fbb2e0a3Schristos   return uv__tcp_bind(handle, addr, addrlen, flags);
309fbb2e0a3Schristos }
310fbb2e0a3Schristos 
311fbb2e0a3Schristos 
uv_udp_init_ex(uv_loop_t * loop,uv_udp_t * handle,unsigned flags)312fbb2e0a3Schristos int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned flags) {
313fbb2e0a3Schristos   unsigned extra_flags;
314fbb2e0a3Schristos   int domain;
315fbb2e0a3Schristos   int rc;
316fbb2e0a3Schristos 
317fbb2e0a3Schristos   /* Use the lower 8 bits for the domain. */
318fbb2e0a3Schristos   domain = flags & 0xFF;
319fbb2e0a3Schristos   if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
320fbb2e0a3Schristos     return UV_EINVAL;
321fbb2e0a3Schristos 
322fbb2e0a3Schristos   /* Use the higher bits for extra flags. */
323fbb2e0a3Schristos   extra_flags = flags & ~0xFF;
324fbb2e0a3Schristos   if (extra_flags & ~UV_UDP_RECVMMSG)
325fbb2e0a3Schristos     return UV_EINVAL;
326fbb2e0a3Schristos 
327fbb2e0a3Schristos   rc = uv__udp_init_ex(loop, handle, flags, domain);
328fbb2e0a3Schristos 
329fbb2e0a3Schristos   if (rc == 0)
330fbb2e0a3Schristos     if (extra_flags & UV_UDP_RECVMMSG)
331fbb2e0a3Schristos       handle->flags |= UV_HANDLE_UDP_RECVMMSG;
332fbb2e0a3Schristos 
333fbb2e0a3Schristos   return rc;
334fbb2e0a3Schristos }
335fbb2e0a3Schristos 
336fbb2e0a3Schristos 
uv_udp_init(uv_loop_t * loop,uv_udp_t * handle)337fbb2e0a3Schristos int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
338fbb2e0a3Schristos   return uv_udp_init_ex(loop, handle, AF_UNSPEC);
339fbb2e0a3Schristos }
340fbb2e0a3Schristos 
341fbb2e0a3Schristos 
uv_udp_bind(uv_udp_t * handle,const struct sockaddr * addr,unsigned int flags)342fbb2e0a3Schristos int uv_udp_bind(uv_udp_t* handle,
343fbb2e0a3Schristos                 const struct sockaddr* addr,
344fbb2e0a3Schristos                 unsigned int flags) {
345fbb2e0a3Schristos   unsigned int addrlen;
346fbb2e0a3Schristos 
347fbb2e0a3Schristos   if (handle->type != UV_UDP)
348fbb2e0a3Schristos     return UV_EINVAL;
349fbb2e0a3Schristos 
350fbb2e0a3Schristos   if (addr->sa_family == AF_INET)
351fbb2e0a3Schristos     addrlen = sizeof(struct sockaddr_in);
352fbb2e0a3Schristos   else if (addr->sa_family == AF_INET6)
353fbb2e0a3Schristos     addrlen = sizeof(struct sockaddr_in6);
354fbb2e0a3Schristos   else
355fbb2e0a3Schristos     return UV_EINVAL;
356fbb2e0a3Schristos 
357fbb2e0a3Schristos   return uv__udp_bind(handle, addr, addrlen, flags);
358fbb2e0a3Schristos }
359fbb2e0a3Schristos 
360fbb2e0a3Schristos 
uv_tcp_connect(uv_connect_t * req,uv_tcp_t * handle,const struct sockaddr * addr,uv_connect_cb cb)361fbb2e0a3Schristos int uv_tcp_connect(uv_connect_t* req,
362fbb2e0a3Schristos                    uv_tcp_t* handle,
363fbb2e0a3Schristos                    const struct sockaddr* addr,
364fbb2e0a3Schristos                    uv_connect_cb cb) {
365fbb2e0a3Schristos   unsigned int addrlen;
366fbb2e0a3Schristos 
367fbb2e0a3Schristos   if (handle->type != UV_TCP)
368fbb2e0a3Schristos     return UV_EINVAL;
369fbb2e0a3Schristos 
370fbb2e0a3Schristos   if (addr->sa_family == AF_INET)
371fbb2e0a3Schristos     addrlen = sizeof(struct sockaddr_in);
372fbb2e0a3Schristos   else if (addr->sa_family == AF_INET6)
373fbb2e0a3Schristos     addrlen = sizeof(struct sockaddr_in6);
374fbb2e0a3Schristos   else
375fbb2e0a3Schristos     return UV_EINVAL;
376fbb2e0a3Schristos 
377fbb2e0a3Schristos   return uv__tcp_connect(req, handle, addr, addrlen, cb);
378fbb2e0a3Schristos }
379fbb2e0a3Schristos 
380fbb2e0a3Schristos 
uv_udp_connect(uv_udp_t * handle,const struct sockaddr * addr)381fbb2e0a3Schristos int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr) {
382fbb2e0a3Schristos   unsigned int addrlen;
383fbb2e0a3Schristos 
384fbb2e0a3Schristos   if (handle->type != UV_UDP)
385fbb2e0a3Schristos     return UV_EINVAL;
386fbb2e0a3Schristos 
387fbb2e0a3Schristos   /* Disconnect the handle */
388fbb2e0a3Schristos   if (addr == NULL) {
389fbb2e0a3Schristos     if (!(handle->flags & UV_HANDLE_UDP_CONNECTED))
390fbb2e0a3Schristos       return UV_ENOTCONN;
391fbb2e0a3Schristos 
392fbb2e0a3Schristos     return uv__udp_disconnect(handle);
393fbb2e0a3Schristos   }
394fbb2e0a3Schristos 
395fbb2e0a3Schristos   if (addr->sa_family == AF_INET)
396fbb2e0a3Schristos     addrlen = sizeof(struct sockaddr_in);
397fbb2e0a3Schristos   else if (addr->sa_family == AF_INET6)
398fbb2e0a3Schristos     addrlen = sizeof(struct sockaddr_in6);
399fbb2e0a3Schristos   else
400fbb2e0a3Schristos     return UV_EINVAL;
401fbb2e0a3Schristos 
402fbb2e0a3Schristos   if (handle->flags & UV_HANDLE_UDP_CONNECTED)
403fbb2e0a3Schristos     return UV_EISCONN;
404fbb2e0a3Schristos 
405fbb2e0a3Schristos   return uv__udp_connect(handle, addr, addrlen);
406fbb2e0a3Schristos }
407fbb2e0a3Schristos 
408fbb2e0a3Schristos 
uv__udp_is_connected(uv_udp_t * handle)409fbb2e0a3Schristos int uv__udp_is_connected(uv_udp_t* handle) {
410fbb2e0a3Schristos   struct sockaddr_storage addr;
411fbb2e0a3Schristos   int addrlen;
412fbb2e0a3Schristos   if (handle->type != UV_UDP)
413fbb2e0a3Schristos     return 0;
414fbb2e0a3Schristos 
415fbb2e0a3Schristos   addrlen = sizeof(addr);
416fbb2e0a3Schristos   if (uv_udp_getpeername(handle, (struct sockaddr*) &addr, &addrlen) != 0)
417fbb2e0a3Schristos     return 0;
418fbb2e0a3Schristos 
419fbb2e0a3Schristos   return addrlen > 0;
420fbb2e0a3Schristos }
421fbb2e0a3Schristos 
422fbb2e0a3Schristos 
uv__udp_check_before_send(uv_udp_t * handle,const struct sockaddr * addr)423fbb2e0a3Schristos int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) {
424fbb2e0a3Schristos   unsigned int addrlen;
425fbb2e0a3Schristos 
426fbb2e0a3Schristos   if (handle->type != UV_UDP)
427fbb2e0a3Schristos     return UV_EINVAL;
428fbb2e0a3Schristos 
429fbb2e0a3Schristos   if (addr != NULL && (handle->flags & UV_HANDLE_UDP_CONNECTED))
430fbb2e0a3Schristos     return UV_EISCONN;
431fbb2e0a3Schristos 
432fbb2e0a3Schristos   if (addr == NULL && !(handle->flags & UV_HANDLE_UDP_CONNECTED))
433fbb2e0a3Schristos     return UV_EDESTADDRREQ;
434fbb2e0a3Schristos 
435fbb2e0a3Schristos   if (addr != NULL) {
436fbb2e0a3Schristos     if (addr->sa_family == AF_INET)
437fbb2e0a3Schristos       addrlen = sizeof(struct sockaddr_in);
438fbb2e0a3Schristos     else if (addr->sa_family == AF_INET6)
439fbb2e0a3Schristos       addrlen = sizeof(struct sockaddr_in6);
440fbb2e0a3Schristos #if defined(AF_UNIX) && !defined(_WIN32)
441fbb2e0a3Schristos     else if (addr->sa_family == AF_UNIX)
442fbb2e0a3Schristos       addrlen = sizeof(struct sockaddr_un);
443fbb2e0a3Schristos #endif
444fbb2e0a3Schristos     else
445fbb2e0a3Schristos       return UV_EINVAL;
446fbb2e0a3Schristos   } else {
447fbb2e0a3Schristos     addrlen = 0;
448fbb2e0a3Schristos   }
449fbb2e0a3Schristos 
450fbb2e0a3Schristos   return addrlen;
451fbb2e0a3Schristos }
452fbb2e0a3Schristos 
453fbb2e0a3Schristos 
uv_udp_send(uv_udp_send_t * req,uv_udp_t * handle,const uv_buf_t bufs[],unsigned int nbufs,const struct sockaddr * addr,uv_udp_send_cb send_cb)454fbb2e0a3Schristos int uv_udp_send(uv_udp_send_t* req,
455fbb2e0a3Schristos                 uv_udp_t* handle,
456fbb2e0a3Schristos                 const uv_buf_t bufs[],
457fbb2e0a3Schristos                 unsigned int nbufs,
458fbb2e0a3Schristos                 const struct sockaddr* addr,
459fbb2e0a3Schristos                 uv_udp_send_cb send_cb) {
460fbb2e0a3Schristos   int addrlen;
461fbb2e0a3Schristos 
462fbb2e0a3Schristos   addrlen = uv__udp_check_before_send(handle, addr);
463fbb2e0a3Schristos   if (addrlen < 0)
464fbb2e0a3Schristos     return addrlen;
465fbb2e0a3Schristos 
466fbb2e0a3Schristos   return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
467fbb2e0a3Schristos }
468fbb2e0a3Schristos 
469fbb2e0a3Schristos 
uv_udp_try_send(uv_udp_t * handle,const uv_buf_t bufs[],unsigned int nbufs,const struct sockaddr * addr)470fbb2e0a3Schristos int uv_udp_try_send(uv_udp_t* handle,
471fbb2e0a3Schristos                     const uv_buf_t bufs[],
472fbb2e0a3Schristos                     unsigned int nbufs,
473fbb2e0a3Schristos                     const struct sockaddr* addr) {
474fbb2e0a3Schristos   int addrlen;
475fbb2e0a3Schristos 
476fbb2e0a3Schristos   addrlen = uv__udp_check_before_send(handle, addr);
477fbb2e0a3Schristos   if (addrlen < 0)
478fbb2e0a3Schristos     return addrlen;
479fbb2e0a3Schristos 
480fbb2e0a3Schristos   return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen);
481fbb2e0a3Schristos }
482fbb2e0a3Schristos 
483fbb2e0a3Schristos 
uv_udp_recv_start(uv_udp_t * handle,uv_alloc_cb alloc_cb,uv_udp_recv_cb recv_cb)484fbb2e0a3Schristos int uv_udp_recv_start(uv_udp_t* handle,
485fbb2e0a3Schristos                       uv_alloc_cb alloc_cb,
486fbb2e0a3Schristos                       uv_udp_recv_cb recv_cb) {
487fbb2e0a3Schristos   if (handle->type != UV_UDP || alloc_cb == NULL || recv_cb == NULL)
488fbb2e0a3Schristos     return UV_EINVAL;
489fbb2e0a3Schristos   else
490fbb2e0a3Schristos     return uv__udp_recv_start(handle, alloc_cb, recv_cb);
491fbb2e0a3Schristos }
492fbb2e0a3Schristos 
493fbb2e0a3Schristos 
uv_udp_recv_stop(uv_udp_t * handle)494fbb2e0a3Schristos int uv_udp_recv_stop(uv_udp_t* handle) {
495fbb2e0a3Schristos   if (handle->type != UV_UDP)
496fbb2e0a3Schristos     return UV_EINVAL;
497fbb2e0a3Schristos   else
498fbb2e0a3Schristos     return uv__udp_recv_stop(handle);
499fbb2e0a3Schristos }
500fbb2e0a3Schristos 
501fbb2e0a3Schristos 
uv_walk(uv_loop_t * loop,uv_walk_cb walk_cb,void * arg)502fbb2e0a3Schristos void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
503fbb2e0a3Schristos   QUEUE queue;
504fbb2e0a3Schristos   QUEUE* q;
505fbb2e0a3Schristos   uv_handle_t* h;
506fbb2e0a3Schristos 
507fbb2e0a3Schristos   QUEUE_MOVE(&loop->handle_queue, &queue);
508fbb2e0a3Schristos   while (!QUEUE_EMPTY(&queue)) {
509fbb2e0a3Schristos     q = QUEUE_HEAD(&queue);
510fbb2e0a3Schristos     h = QUEUE_DATA(q, uv_handle_t, handle_queue);
511fbb2e0a3Schristos 
512fbb2e0a3Schristos     QUEUE_REMOVE(q);
513fbb2e0a3Schristos     QUEUE_INSERT_TAIL(&loop->handle_queue, q);
514fbb2e0a3Schristos 
515fbb2e0a3Schristos     if (h->flags & UV_HANDLE_INTERNAL) continue;
516fbb2e0a3Schristos     walk_cb(h, arg);
517fbb2e0a3Schristos   }
518fbb2e0a3Schristos }
519fbb2e0a3Schristos 
520fbb2e0a3Schristos 
uv__print_handles(uv_loop_t * loop,int only_active,FILE * stream)521fbb2e0a3Schristos static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {
522fbb2e0a3Schristos   const char* type;
523fbb2e0a3Schristos   QUEUE* q;
524fbb2e0a3Schristos   uv_handle_t* h;
525fbb2e0a3Schristos 
526fbb2e0a3Schristos   if (loop == NULL)
527fbb2e0a3Schristos     loop = uv_default_loop();
528fbb2e0a3Schristos 
529fbb2e0a3Schristos   QUEUE_FOREACH(q, &loop->handle_queue) {
530fbb2e0a3Schristos     h = QUEUE_DATA(q, uv_handle_t, handle_queue);
531fbb2e0a3Schristos 
532fbb2e0a3Schristos     if (only_active && !uv__is_active(h))
533fbb2e0a3Schristos       continue;
534fbb2e0a3Schristos 
535fbb2e0a3Schristos     switch (h->type) {
536fbb2e0a3Schristos #define X(uc, lc) case UV_##uc: type = #lc; break;
537fbb2e0a3Schristos       UV_HANDLE_TYPE_MAP(X)
538fbb2e0a3Schristos #undef X
539fbb2e0a3Schristos       default: type = "<unknown>";
540fbb2e0a3Schristos     }
541fbb2e0a3Schristos 
542fbb2e0a3Schristos     fprintf(stream,
543fbb2e0a3Schristos             "[%c%c%c] %-8s %p\n",
544fbb2e0a3Schristos             "R-"[!(h->flags & UV_HANDLE_REF)],
545fbb2e0a3Schristos             "A-"[!(h->flags & UV_HANDLE_ACTIVE)],
546fbb2e0a3Schristos             "I-"[!(h->flags & UV_HANDLE_INTERNAL)],
547fbb2e0a3Schristos             type,
548fbb2e0a3Schristos             (void*)h);
549fbb2e0a3Schristos   }
550fbb2e0a3Schristos }
551fbb2e0a3Schristos 
552fbb2e0a3Schristos 
uv_print_all_handles(uv_loop_t * loop,FILE * stream)553fbb2e0a3Schristos void uv_print_all_handles(uv_loop_t* loop, FILE* stream) {
554fbb2e0a3Schristos   uv__print_handles(loop, 0, stream);
555fbb2e0a3Schristos }
556fbb2e0a3Schristos 
557fbb2e0a3Schristos 
uv_print_active_handles(uv_loop_t * loop,FILE * stream)558fbb2e0a3Schristos void uv_print_active_handles(uv_loop_t* loop, FILE* stream) {
559fbb2e0a3Schristos   uv__print_handles(loop, 1, stream);
560fbb2e0a3Schristos }
561fbb2e0a3Schristos 
562fbb2e0a3Schristos 
uv_ref(uv_handle_t * handle)563fbb2e0a3Schristos void uv_ref(uv_handle_t* handle) {
564fbb2e0a3Schristos   uv__handle_ref(handle);
565fbb2e0a3Schristos }
566fbb2e0a3Schristos 
567fbb2e0a3Schristos 
uv_unref(uv_handle_t * handle)568fbb2e0a3Schristos void uv_unref(uv_handle_t* handle) {
569fbb2e0a3Schristos   uv__handle_unref(handle);
570fbb2e0a3Schristos }
571fbb2e0a3Schristos 
572fbb2e0a3Schristos 
uv_has_ref(const uv_handle_t * handle)573fbb2e0a3Schristos int uv_has_ref(const uv_handle_t* handle) {
574fbb2e0a3Schristos   return uv__has_ref(handle);
575fbb2e0a3Schristos }
576fbb2e0a3Schristos 
577fbb2e0a3Schristos 
uv_stop(uv_loop_t * loop)578fbb2e0a3Schristos void uv_stop(uv_loop_t* loop) {
579fbb2e0a3Schristos   loop->stop_flag = 1;
580fbb2e0a3Schristos }
581fbb2e0a3Schristos 
582fbb2e0a3Schristos 
uv_now(const uv_loop_t * loop)583fbb2e0a3Schristos uint64_t uv_now(const uv_loop_t* loop) {
584fbb2e0a3Schristos   return loop->time;
585fbb2e0a3Schristos }
586fbb2e0a3Schristos 
587fbb2e0a3Schristos 
588fbb2e0a3Schristos 
uv__count_bufs(const uv_buf_t bufs[],unsigned int nbufs)589fbb2e0a3Schristos size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs) {
590fbb2e0a3Schristos   unsigned int i;
591fbb2e0a3Schristos   size_t bytes;
592fbb2e0a3Schristos 
593fbb2e0a3Schristos   bytes = 0;
594fbb2e0a3Schristos   for (i = 0; i < nbufs; i++)
595fbb2e0a3Schristos     bytes += (size_t) bufs[i].len;
596fbb2e0a3Schristos 
597fbb2e0a3Schristos   return bytes;
598fbb2e0a3Schristos }
599fbb2e0a3Schristos 
uv_recv_buffer_size(uv_handle_t * handle,int * value)600fbb2e0a3Schristos int uv_recv_buffer_size(uv_handle_t* handle, int* value) {
601fbb2e0a3Schristos   return uv__socket_sockopt(handle, SO_RCVBUF, value);
602fbb2e0a3Schristos }
603fbb2e0a3Schristos 
uv_send_buffer_size(uv_handle_t * handle,int * value)604fbb2e0a3Schristos int uv_send_buffer_size(uv_handle_t* handle, int *value) {
605fbb2e0a3Schristos   return uv__socket_sockopt(handle, SO_SNDBUF, value);
606fbb2e0a3Schristos }
607fbb2e0a3Schristos 
uv_fs_event_getpath(uv_fs_event_t * handle,char * buffer,size_t * size)608fbb2e0a3Schristos int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) {
609fbb2e0a3Schristos   size_t required_len;
610fbb2e0a3Schristos 
611fbb2e0a3Schristos   if (!uv__is_active(handle)) {
612fbb2e0a3Schristos     *size = 0;
613fbb2e0a3Schristos     return UV_EINVAL;
614fbb2e0a3Schristos   }
615fbb2e0a3Schristos 
616fbb2e0a3Schristos   required_len = strlen(handle->path);
617fbb2e0a3Schristos   if (required_len >= *size) {
618fbb2e0a3Schristos     *size = required_len + 1;
619fbb2e0a3Schristos     return UV_ENOBUFS;
620fbb2e0a3Schristos   }
621fbb2e0a3Schristos 
622fbb2e0a3Schristos   memcpy(buffer, handle->path, required_len);
623fbb2e0a3Schristos   *size = required_len;
624fbb2e0a3Schristos   buffer[required_len] = '\0';
625fbb2e0a3Schristos 
626fbb2e0a3Schristos   return 0;
627fbb2e0a3Schristos }
628fbb2e0a3Schristos 
629fbb2e0a3Schristos /* The windows implementation does not have the same structure layout as
630fbb2e0a3Schristos  * the unix implementation (nbufs is not directly inside req but is
631fbb2e0a3Schristos  * contained in a nested union/struct) so this function locates it.
632fbb2e0a3Schristos */
uv__get_nbufs(uv_fs_t * req)633fbb2e0a3Schristos static unsigned int* uv__get_nbufs(uv_fs_t* req) {
634fbb2e0a3Schristos #ifdef _WIN32
635fbb2e0a3Schristos   return &req->fs.info.nbufs;
636fbb2e0a3Schristos #else
637fbb2e0a3Schristos   return &req->nbufs;
638fbb2e0a3Schristos #endif
639fbb2e0a3Schristos }
640fbb2e0a3Schristos 
641fbb2e0a3Schristos /* uv_fs_scandir() uses the system allocator to allocate memory on non-Windows
642fbb2e0a3Schristos  * systems. So, the memory should be released using free(). On Windows,
643fbb2e0a3Schristos  * uv__malloc() is used, so use uv__free() to free memory.
644fbb2e0a3Schristos */
645fbb2e0a3Schristos #ifdef _WIN32
646fbb2e0a3Schristos # define uv__fs_scandir_free uv__free
647fbb2e0a3Schristos #else
648fbb2e0a3Schristos # define uv__fs_scandir_free free
649fbb2e0a3Schristos #endif
650fbb2e0a3Schristos 
uv__fs_scandir_cleanup(uv_fs_t * req)651fbb2e0a3Schristos void uv__fs_scandir_cleanup(uv_fs_t* req) {
652fbb2e0a3Schristos   uv__dirent_t** dents;
653fbb2e0a3Schristos 
654fbb2e0a3Schristos   unsigned int* nbufs = uv__get_nbufs(req);
655fbb2e0a3Schristos 
656fbb2e0a3Schristos   dents = req->ptr;
657fbb2e0a3Schristos   if (*nbufs > 0 && *nbufs != (unsigned int) req->result)
658fbb2e0a3Schristos     (*nbufs)--;
659fbb2e0a3Schristos   for (; *nbufs < (unsigned int) req->result; (*nbufs)++)
660fbb2e0a3Schristos     uv__fs_scandir_free(dents[*nbufs]);
661fbb2e0a3Schristos 
662fbb2e0a3Schristos   uv__fs_scandir_free(req->ptr);
663fbb2e0a3Schristos   req->ptr = NULL;
664fbb2e0a3Schristos }
665fbb2e0a3Schristos 
666fbb2e0a3Schristos 
uv_fs_scandir_next(uv_fs_t * req,uv_dirent_t * ent)667fbb2e0a3Schristos int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
668fbb2e0a3Schristos   uv__dirent_t** dents;
669fbb2e0a3Schristos   uv__dirent_t* dent;
670fbb2e0a3Schristos   unsigned int* nbufs;
671fbb2e0a3Schristos 
672fbb2e0a3Schristos   /* Check to see if req passed */
673fbb2e0a3Schristos   if (req->result < 0)
674fbb2e0a3Schristos     return req->result;
675fbb2e0a3Schristos 
676fbb2e0a3Schristos   /* Ptr will be null if req was canceled or no files found */
677fbb2e0a3Schristos   if (!req->ptr)
678fbb2e0a3Schristos     return UV_EOF;
679fbb2e0a3Schristos 
680fbb2e0a3Schristos   nbufs = uv__get_nbufs(req);
681fbb2e0a3Schristos   assert(nbufs);
682fbb2e0a3Schristos 
683fbb2e0a3Schristos   dents = req->ptr;
684fbb2e0a3Schristos 
685fbb2e0a3Schristos   /* Free previous entity */
686fbb2e0a3Schristos   if (*nbufs > 0)
687fbb2e0a3Schristos     uv__fs_scandir_free(dents[*nbufs - 1]);
688fbb2e0a3Schristos 
689fbb2e0a3Schristos   /* End was already reached */
690fbb2e0a3Schristos   if (*nbufs == (unsigned int) req->result) {
691fbb2e0a3Schristos     uv__fs_scandir_free(dents);
692fbb2e0a3Schristos     req->ptr = NULL;
693fbb2e0a3Schristos     return UV_EOF;
694fbb2e0a3Schristos   }
695fbb2e0a3Schristos 
696fbb2e0a3Schristos   dent = dents[(*nbufs)++];
697fbb2e0a3Schristos 
698fbb2e0a3Schristos   ent->name = dent->d_name;
699fbb2e0a3Schristos   ent->type = uv__fs_get_dirent_type(dent);
700fbb2e0a3Schristos 
701fbb2e0a3Schristos   return 0;
702fbb2e0a3Schristos }
703fbb2e0a3Schristos 
uv__fs_get_dirent_type(uv__dirent_t * dent)704fbb2e0a3Schristos uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent) {
705fbb2e0a3Schristos   uv_dirent_type_t type;
706fbb2e0a3Schristos 
707fbb2e0a3Schristos #ifdef HAVE_DIRENT_TYPES
708fbb2e0a3Schristos   switch (dent->d_type) {
709fbb2e0a3Schristos     case UV__DT_DIR:
710fbb2e0a3Schristos       type = UV_DIRENT_DIR;
711fbb2e0a3Schristos       break;
712fbb2e0a3Schristos     case UV__DT_FILE:
713fbb2e0a3Schristos       type = UV_DIRENT_FILE;
714fbb2e0a3Schristos       break;
715fbb2e0a3Schristos     case UV__DT_LINK:
716fbb2e0a3Schristos       type = UV_DIRENT_LINK;
717fbb2e0a3Schristos       break;
718fbb2e0a3Schristos     case UV__DT_FIFO:
719fbb2e0a3Schristos       type = UV_DIRENT_FIFO;
720fbb2e0a3Schristos       break;
721fbb2e0a3Schristos     case UV__DT_SOCKET:
722fbb2e0a3Schristos       type = UV_DIRENT_SOCKET;
723fbb2e0a3Schristos       break;
724fbb2e0a3Schristos     case UV__DT_CHAR:
725fbb2e0a3Schristos       type = UV_DIRENT_CHAR;
726fbb2e0a3Schristos       break;
727fbb2e0a3Schristos     case UV__DT_BLOCK:
728fbb2e0a3Schristos       type = UV_DIRENT_BLOCK;
729fbb2e0a3Schristos       break;
730fbb2e0a3Schristos     default:
731fbb2e0a3Schristos       type = UV_DIRENT_UNKNOWN;
732fbb2e0a3Schristos   }
733fbb2e0a3Schristos #else
734fbb2e0a3Schristos   type = UV_DIRENT_UNKNOWN;
735fbb2e0a3Schristos #endif
736fbb2e0a3Schristos 
737fbb2e0a3Schristos   return type;
738fbb2e0a3Schristos }
739fbb2e0a3Schristos 
uv__fs_readdir_cleanup(uv_fs_t * req)740fbb2e0a3Schristos void uv__fs_readdir_cleanup(uv_fs_t* req) {
741fbb2e0a3Schristos   uv_dir_t* dir;
742fbb2e0a3Schristos   uv_dirent_t* dirents;
743fbb2e0a3Schristos   int i;
744fbb2e0a3Schristos 
745fbb2e0a3Schristos   if (req->ptr == NULL)
746fbb2e0a3Schristos     return;
747fbb2e0a3Schristos 
748fbb2e0a3Schristos   dir = req->ptr;
749fbb2e0a3Schristos   dirents = dir->dirents;
750fbb2e0a3Schristos   req->ptr = NULL;
751fbb2e0a3Schristos 
752fbb2e0a3Schristos   if (dirents == NULL)
753fbb2e0a3Schristos     return;
754fbb2e0a3Schristos 
755fbb2e0a3Schristos   for (i = 0; i < req->result; ++i) {
756fbb2e0a3Schristos     uv__free((char*) dirents[i].name);
757fbb2e0a3Schristos     dirents[i].name = NULL;
758fbb2e0a3Schristos   }
759fbb2e0a3Schristos }
760fbb2e0a3Schristos 
761fbb2e0a3Schristos 
uv_loop_configure(uv_loop_t * loop,uv_loop_option option,...)762fbb2e0a3Schristos int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) {
763fbb2e0a3Schristos   va_list ap;
764fbb2e0a3Schristos   int err;
765fbb2e0a3Schristos 
766fbb2e0a3Schristos   va_start(ap, option);
767fbb2e0a3Schristos   /* Any platform-agnostic options should be handled here. */
768fbb2e0a3Schristos   err = uv__loop_configure(loop, option, ap);
769fbb2e0a3Schristos   va_end(ap);
770fbb2e0a3Schristos 
771fbb2e0a3Schristos   return err;
772fbb2e0a3Schristos }
773fbb2e0a3Schristos 
774fbb2e0a3Schristos 
775fbb2e0a3Schristos static uv_loop_t default_loop_struct;
776fbb2e0a3Schristos static uv_loop_t* default_loop_ptr;
777fbb2e0a3Schristos 
778fbb2e0a3Schristos 
uv_default_loop(void)779fbb2e0a3Schristos uv_loop_t* uv_default_loop(void) {
780fbb2e0a3Schristos   if (default_loop_ptr != NULL)
781fbb2e0a3Schristos     return default_loop_ptr;
782fbb2e0a3Schristos 
783fbb2e0a3Schristos   if (uv_loop_init(&default_loop_struct))
784fbb2e0a3Schristos     return NULL;
785fbb2e0a3Schristos 
786fbb2e0a3Schristos   default_loop_ptr = &default_loop_struct;
787fbb2e0a3Schristos   return default_loop_ptr;
788fbb2e0a3Schristos }
789fbb2e0a3Schristos 
790fbb2e0a3Schristos 
uv_loop_new(void)791fbb2e0a3Schristos uv_loop_t* uv_loop_new(void) {
792fbb2e0a3Schristos   uv_loop_t* loop;
793fbb2e0a3Schristos 
794fbb2e0a3Schristos   loop = uv__malloc(sizeof(*loop));
795fbb2e0a3Schristos   if (loop == NULL)
796fbb2e0a3Schristos     return NULL;
797fbb2e0a3Schristos 
798fbb2e0a3Schristos   if (uv_loop_init(loop)) {
799fbb2e0a3Schristos     uv__free(loop);
800fbb2e0a3Schristos     return NULL;
801fbb2e0a3Schristos   }
802fbb2e0a3Schristos 
803fbb2e0a3Schristos   return loop;
804fbb2e0a3Schristos }
805fbb2e0a3Schristos 
806fbb2e0a3Schristos 
uv_loop_close(uv_loop_t * loop)807fbb2e0a3Schristos int uv_loop_close(uv_loop_t* loop) {
808fbb2e0a3Schristos   QUEUE* q;
809fbb2e0a3Schristos   uv_handle_t* h;
810fbb2e0a3Schristos #ifndef NDEBUG
811fbb2e0a3Schristos   void* saved_data;
812fbb2e0a3Schristos #endif
813fbb2e0a3Schristos 
814fbb2e0a3Schristos   if (uv__has_active_reqs(loop))
815fbb2e0a3Schristos     return UV_EBUSY;
816fbb2e0a3Schristos 
817fbb2e0a3Schristos   QUEUE_FOREACH(q, &loop->handle_queue) {
818fbb2e0a3Schristos     h = QUEUE_DATA(q, uv_handle_t, handle_queue);
819fbb2e0a3Schristos     if (!(h->flags & UV_HANDLE_INTERNAL))
820fbb2e0a3Schristos       return UV_EBUSY;
821fbb2e0a3Schristos   }
822fbb2e0a3Schristos 
823fbb2e0a3Schristos   uv__loop_close(loop);
824fbb2e0a3Schristos 
825fbb2e0a3Schristos #ifndef NDEBUG
826fbb2e0a3Schristos   saved_data = loop->data;
827fbb2e0a3Schristos   memset(loop, -1, sizeof(*loop));
828fbb2e0a3Schristos   loop->data = saved_data;
829fbb2e0a3Schristos #endif
830fbb2e0a3Schristos   if (loop == default_loop_ptr)
831fbb2e0a3Schristos     default_loop_ptr = NULL;
832fbb2e0a3Schristos 
833fbb2e0a3Schristos   return 0;
834fbb2e0a3Schristos }
835fbb2e0a3Schristos 
836fbb2e0a3Schristos 
uv_loop_delete(uv_loop_t * loop)837fbb2e0a3Schristos void uv_loop_delete(uv_loop_t* loop) {
838fbb2e0a3Schristos   uv_loop_t* default_loop;
839fbb2e0a3Schristos   int err;
840fbb2e0a3Schristos 
841fbb2e0a3Schristos   default_loop = default_loop_ptr;
842fbb2e0a3Schristos 
843fbb2e0a3Schristos   err = uv_loop_close(loop);
844fbb2e0a3Schristos   (void) err;    /* Squelch compiler warnings. */
845fbb2e0a3Schristos   assert(err == 0);
846fbb2e0a3Schristos   if (loop != default_loop)
847fbb2e0a3Schristos     uv__free(loop);
848fbb2e0a3Schristos }
849fbb2e0a3Schristos 
850fbb2e0a3Schristos 
uv_read_start(uv_stream_t * stream,uv_alloc_cb alloc_cb,uv_read_cb read_cb)851*b29f2fbfSchristos int uv_read_start(uv_stream_t* stream,
852*b29f2fbfSchristos                   uv_alloc_cb alloc_cb,
853*b29f2fbfSchristos                   uv_read_cb read_cb) {
854*b29f2fbfSchristos   if (stream == NULL || alloc_cb == NULL || read_cb == NULL)
855*b29f2fbfSchristos     return UV_EINVAL;
856*b29f2fbfSchristos 
857*b29f2fbfSchristos   if (stream->flags & UV_HANDLE_CLOSING)
858*b29f2fbfSchristos     return UV_EINVAL;
859*b29f2fbfSchristos 
860*b29f2fbfSchristos   if (stream->flags & UV_HANDLE_READING)
861*b29f2fbfSchristos     return UV_EALREADY;
862*b29f2fbfSchristos 
863*b29f2fbfSchristos   if (!(stream->flags & UV_HANDLE_READABLE))
864*b29f2fbfSchristos     return UV_ENOTCONN;
865*b29f2fbfSchristos 
866*b29f2fbfSchristos   return uv__read_start(stream, alloc_cb, read_cb);
867*b29f2fbfSchristos }
868*b29f2fbfSchristos 
869*b29f2fbfSchristos 
uv_os_free_environ(uv_env_item_t * envitems,int count)870fbb2e0a3Schristos void uv_os_free_environ(uv_env_item_t* envitems, int count) {
871fbb2e0a3Schristos   int i;
872fbb2e0a3Schristos 
873fbb2e0a3Schristos   for (i = 0; i < count; i++) {
874fbb2e0a3Schristos     uv__free(envitems[i].name);
875fbb2e0a3Schristos   }
876fbb2e0a3Schristos 
877fbb2e0a3Schristos   uv__free(envitems);
878fbb2e0a3Schristos }
879fbb2e0a3Schristos 
880fbb2e0a3Schristos 
uv_free_cpu_info(uv_cpu_info_t * cpu_infos,int count)881fbb2e0a3Schristos void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
882fbb2e0a3Schristos   int i;
883fbb2e0a3Schristos 
884fbb2e0a3Schristos   for (i = 0; i < count; i++)
885fbb2e0a3Schristos     uv__free(cpu_infos[i].model);
886fbb2e0a3Schristos 
887fbb2e0a3Schristos   uv__free(cpu_infos);
888fbb2e0a3Schristos }
889fbb2e0a3Schristos 
890fbb2e0a3Schristos 
891*b29f2fbfSchristos /* Also covers __clang__ and __INTEL_COMPILER. Disabled on Windows because
892*b29f2fbfSchristos  * threads have already been forcibly terminated by the operating system
893*b29f2fbfSchristos  * by the time destructors run, ergo, it's not safe to try to clean them up.
894*b29f2fbfSchristos  */
895*b29f2fbfSchristos #if defined(__GNUC__) && !defined(_WIN32)
896fbb2e0a3Schristos __attribute__((destructor))
897fbb2e0a3Schristos #endif
uv_library_shutdown(void)898fbb2e0a3Schristos void uv_library_shutdown(void) {
899fbb2e0a3Schristos   static int was_shutdown;
900fbb2e0a3Schristos 
901*b29f2fbfSchristos   if (uv__load_relaxed(&was_shutdown))
902fbb2e0a3Schristos     return;
903fbb2e0a3Schristos 
904fbb2e0a3Schristos   uv__process_title_cleanup();
905fbb2e0a3Schristos   uv__signal_cleanup();
906*b29f2fbfSchristos #ifdef __MVS__
907*b29f2fbfSchristos   /* TODO(itodorov) - zos: revisit when Woz compiler is available. */
908*b29f2fbfSchristos   uv__os390_cleanup();
909*b29f2fbfSchristos #else
910fbb2e0a3Schristos   uv__threadpool_cleanup();
911*b29f2fbfSchristos #endif
912*b29f2fbfSchristos   uv__store_relaxed(&was_shutdown, 1);
913*b29f2fbfSchristos }
914*b29f2fbfSchristos 
915*b29f2fbfSchristos 
uv__metrics_update_idle_time(uv_loop_t * loop)916*b29f2fbfSchristos void uv__metrics_update_idle_time(uv_loop_t* loop) {
917*b29f2fbfSchristos   uv__loop_metrics_t* loop_metrics;
918*b29f2fbfSchristos   uint64_t entry_time;
919*b29f2fbfSchristos   uint64_t exit_time;
920*b29f2fbfSchristos 
921*b29f2fbfSchristos   if (!(uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME))
922*b29f2fbfSchristos     return;
923*b29f2fbfSchristos 
924*b29f2fbfSchristos   loop_metrics = uv__get_loop_metrics(loop);
925*b29f2fbfSchristos 
926*b29f2fbfSchristos   /* The thread running uv__metrics_update_idle_time() is always the same
927*b29f2fbfSchristos    * thread that sets provider_entry_time. So it's unnecessary to lock before
928*b29f2fbfSchristos    * retrieving this value.
929*b29f2fbfSchristos    */
930*b29f2fbfSchristos   if (loop_metrics->provider_entry_time == 0)
931*b29f2fbfSchristos     return;
932*b29f2fbfSchristos 
933*b29f2fbfSchristos   exit_time = uv_hrtime();
934*b29f2fbfSchristos 
935*b29f2fbfSchristos   uv_mutex_lock(&loop_metrics->lock);
936*b29f2fbfSchristos   entry_time = loop_metrics->provider_entry_time;
937*b29f2fbfSchristos   loop_metrics->provider_entry_time = 0;
938*b29f2fbfSchristos   loop_metrics->provider_idle_time += exit_time - entry_time;
939*b29f2fbfSchristos   uv_mutex_unlock(&loop_metrics->lock);
940*b29f2fbfSchristos }
941*b29f2fbfSchristos 
942*b29f2fbfSchristos 
uv__metrics_set_provider_entry_time(uv_loop_t * loop)943*b29f2fbfSchristos void uv__metrics_set_provider_entry_time(uv_loop_t* loop) {
944*b29f2fbfSchristos   uv__loop_metrics_t* loop_metrics;
945*b29f2fbfSchristos   uint64_t now;
946*b29f2fbfSchristos 
947*b29f2fbfSchristos   if (!(uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME))
948*b29f2fbfSchristos     return;
949*b29f2fbfSchristos 
950*b29f2fbfSchristos   now = uv_hrtime();
951*b29f2fbfSchristos   loop_metrics = uv__get_loop_metrics(loop);
952*b29f2fbfSchristos   uv_mutex_lock(&loop_metrics->lock);
953*b29f2fbfSchristos   loop_metrics->provider_entry_time = now;
954*b29f2fbfSchristos   uv_mutex_unlock(&loop_metrics->lock);
955*b29f2fbfSchristos }
956*b29f2fbfSchristos 
957*b29f2fbfSchristos 
uv_metrics_idle_time(uv_loop_t * loop)958*b29f2fbfSchristos uint64_t uv_metrics_idle_time(uv_loop_t* loop) {
959*b29f2fbfSchristos   uv__loop_metrics_t* loop_metrics;
960*b29f2fbfSchristos   uint64_t entry_time;
961*b29f2fbfSchristos   uint64_t idle_time;
962*b29f2fbfSchristos 
963*b29f2fbfSchristos   loop_metrics = uv__get_loop_metrics(loop);
964*b29f2fbfSchristos   uv_mutex_lock(&loop_metrics->lock);
965*b29f2fbfSchristos   idle_time = loop_metrics->provider_idle_time;
966*b29f2fbfSchristos   entry_time = loop_metrics->provider_entry_time;
967*b29f2fbfSchristos   uv_mutex_unlock(&loop_metrics->lock);
968*b29f2fbfSchristos 
969*b29f2fbfSchristos   if (entry_time > 0)
970*b29f2fbfSchristos     idle_time += uv_hrtime() - entry_time;
971*b29f2fbfSchristos   return idle_time;
972fbb2e0a3Schristos }
973