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