xref: /libuv/src/uv-common.c (revision 56fada47)
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_recv_start(uv_udp_t * handle,uv_alloc_cb alloc_cb,uv_udp_recv_cb recv_cb)517 int uv_udp_recv_start(uv_udp_t* handle,
518                       uv_alloc_cb alloc_cb,
519                       uv_udp_recv_cb recv_cb) {
520   if (handle->type != UV_UDP || alloc_cb == NULL || recv_cb == NULL)
521     return UV_EINVAL;
522   else
523     return uv__udp_recv_start(handle, alloc_cb, recv_cb);
524 }
525 
526 
uv_udp_recv_stop(uv_udp_t * handle)527 int uv_udp_recv_stop(uv_udp_t* handle) {
528   if (handle->type != UV_UDP)
529     return UV_EINVAL;
530   else
531     return uv__udp_recv_stop(handle);
532 }
533 
534 
uv_walk(uv_loop_t * loop,uv_walk_cb walk_cb,void * arg)535 void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
536   struct uv__queue queue;
537   struct uv__queue* q;
538   uv_handle_t* h;
539 
540   uv__queue_move(&loop->handle_queue, &queue);
541   while (!uv__queue_empty(&queue)) {
542     q = uv__queue_head(&queue);
543     h = uv__queue_data(q, uv_handle_t, handle_queue);
544 
545     uv__queue_remove(q);
546     uv__queue_insert_tail(&loop->handle_queue, q);
547 
548     if (h->flags & UV_HANDLE_INTERNAL) continue;
549     walk_cb(h, arg);
550   }
551 }
552 
553 
uv__print_handles(uv_loop_t * loop,int only_active,FILE * stream)554 static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {
555   const char* type;
556   struct uv__queue* q;
557   uv_handle_t* h;
558 
559   if (loop == NULL)
560     loop = uv_default_loop();
561 
562   if (stream == NULL)
563     stream = stderr;
564 
565   uv__queue_foreach(q, &loop->handle_queue) {
566     h = uv__queue_data(q, uv_handle_t, handle_queue);
567 
568     if (only_active && !uv__is_active(h))
569       continue;
570 
571     switch (h->type) {
572 #define X(uc, lc) case UV_##uc: type = #lc; break;
573       UV_HANDLE_TYPE_MAP(X)
574 #undef X
575       default: type = "<unknown>";
576     }
577 
578     fprintf(stream,
579             "[%c%c%c] %-8s %p\n",
580             "R-"[!(h->flags & UV_HANDLE_REF)],
581             "A-"[!(h->flags & UV_HANDLE_ACTIVE)],
582             "I-"[!(h->flags & UV_HANDLE_INTERNAL)],
583             type,
584             (void*)h);
585   }
586 }
587 
588 
uv_print_all_handles(uv_loop_t * loop,FILE * stream)589 void uv_print_all_handles(uv_loop_t* loop, FILE* stream) {
590   uv__print_handles(loop, 0, stream);
591 }
592 
593 
uv_print_active_handles(uv_loop_t * loop,FILE * stream)594 void uv_print_active_handles(uv_loop_t* loop, FILE* stream) {
595   uv__print_handles(loop, 1, stream);
596 }
597 
598 
uv_ref(uv_handle_t * handle)599 void uv_ref(uv_handle_t* handle) {
600   uv__handle_ref(handle);
601 }
602 
603 
uv_unref(uv_handle_t * handle)604 void uv_unref(uv_handle_t* handle) {
605   uv__handle_unref(handle);
606 }
607 
608 
uv_has_ref(const uv_handle_t * handle)609 int uv_has_ref(const uv_handle_t* handle) {
610   return uv__has_ref(handle);
611 }
612 
613 
uv_stop(uv_loop_t * loop)614 void uv_stop(uv_loop_t* loop) {
615   loop->stop_flag = 1;
616 }
617 
618 
uv_now(const uv_loop_t * loop)619 uint64_t uv_now(const uv_loop_t* loop) {
620   return loop->time;
621 }
622 
623 
624 
uv__count_bufs(const uv_buf_t bufs[],unsigned int nbufs)625 size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs) {
626   unsigned int i;
627   size_t bytes;
628 
629   bytes = 0;
630   for (i = 0; i < nbufs; i++)
631     bytes += (size_t) bufs[i].len;
632 
633   return bytes;
634 }
635 
uv_recv_buffer_size(uv_handle_t * handle,int * value)636 int uv_recv_buffer_size(uv_handle_t* handle, int* value) {
637   return uv__socket_sockopt(handle, SO_RCVBUF, value);
638 }
639 
uv_send_buffer_size(uv_handle_t * handle,int * value)640 int uv_send_buffer_size(uv_handle_t* handle, int *value) {
641   return uv__socket_sockopt(handle, SO_SNDBUF, value);
642 }
643 
uv_fs_event_getpath(uv_fs_event_t * handle,char * buffer,size_t * size)644 int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) {
645   size_t required_len;
646 
647   if (!uv__is_active(handle)) {
648     *size = 0;
649     return UV_EINVAL;
650   }
651 
652   required_len = strlen(handle->path);
653   if (required_len >= *size) {
654     *size = required_len + 1;
655     return UV_ENOBUFS;
656   }
657 
658   memcpy(buffer, handle->path, required_len);
659   *size = required_len;
660   buffer[required_len] = '\0';
661 
662   return 0;
663 }
664 
665 /* The windows implementation does not have the same structure layout as
666  * the unix implementation (nbufs is not directly inside req but is
667  * contained in a nested union/struct) so this function locates it.
668 */
uv__get_nbufs(uv_fs_t * req)669 static unsigned int* uv__get_nbufs(uv_fs_t* req) {
670 #ifdef _WIN32
671   return &req->fs.info.nbufs;
672 #else
673   return &req->nbufs;
674 #endif
675 }
676 
677 /* uv_fs_scandir() uses the system allocator to allocate memory on non-Windows
678  * systems. So, the memory should be released using free(). On Windows,
679  * uv__malloc() is used, so use uv__free() to free memory.
680 */
681 #ifdef _WIN32
682 # define uv__fs_scandir_free uv__free
683 #else
684 # define uv__fs_scandir_free free
685 #endif
686 
uv__fs_scandir_cleanup(uv_fs_t * req)687 void uv__fs_scandir_cleanup(uv_fs_t* req) {
688   uv__dirent_t** dents;
689   unsigned int* nbufs;
690   unsigned int i;
691   unsigned int n;
692 
693   if (req->result >= 0) {
694     dents = req->ptr;
695     nbufs = uv__get_nbufs(req);
696 
697     i = 0;
698     if (*nbufs > 0)
699       i = *nbufs - 1;
700 
701     n = (unsigned int) req->result;
702     for (; i < n; i++)
703       uv__fs_scandir_free(dents[i]);
704   }
705 
706   uv__fs_scandir_free(req->ptr);
707   req->ptr = NULL;
708 }
709 
710 
uv_fs_scandir_next(uv_fs_t * req,uv_dirent_t * ent)711 int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
712   uv__dirent_t** dents;
713   uv__dirent_t* dent;
714   unsigned int* nbufs;
715 
716   /* Check to see if req passed */
717   if (req->result < 0)
718     return req->result;
719 
720   /* Ptr will be null if req was canceled or no files found */
721   if (!req->ptr)
722     return UV_EOF;
723 
724   nbufs = uv__get_nbufs(req);
725   assert(nbufs);
726 
727   dents = req->ptr;
728 
729   /* Free previous entity */
730   if (*nbufs > 0)
731     uv__fs_scandir_free(dents[*nbufs - 1]);
732 
733   /* End was already reached */
734   if (*nbufs == (unsigned int) req->result) {
735     uv__fs_scandir_free(dents);
736     req->ptr = NULL;
737     return UV_EOF;
738   }
739 
740   dent = dents[(*nbufs)++];
741 
742   ent->name = dent->d_name;
743   ent->type = uv__fs_get_dirent_type(dent);
744 
745   return 0;
746 }
747 
uv__fs_get_dirent_type(uv__dirent_t * dent)748 uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent) {
749   uv_dirent_type_t type;
750 
751 #ifdef HAVE_DIRENT_TYPES
752   switch (dent->d_type) {
753     case UV__DT_DIR:
754       type = UV_DIRENT_DIR;
755       break;
756     case UV__DT_FILE:
757       type = UV_DIRENT_FILE;
758       break;
759     case UV__DT_LINK:
760       type = UV_DIRENT_LINK;
761       break;
762     case UV__DT_FIFO:
763       type = UV_DIRENT_FIFO;
764       break;
765     case UV__DT_SOCKET:
766       type = UV_DIRENT_SOCKET;
767       break;
768     case UV__DT_CHAR:
769       type = UV_DIRENT_CHAR;
770       break;
771     case UV__DT_BLOCK:
772       type = UV_DIRENT_BLOCK;
773       break;
774     default:
775       type = UV_DIRENT_UNKNOWN;
776   }
777 #else
778   type = UV_DIRENT_UNKNOWN;
779 #endif
780 
781   return type;
782 }
783 
uv__fs_readdir_cleanup(uv_fs_t * req)784 void uv__fs_readdir_cleanup(uv_fs_t* req) {
785   uv_dir_t* dir;
786   uv_dirent_t* dirents;
787   int i;
788 
789   if (req->ptr == NULL)
790     return;
791 
792   dir = req->ptr;
793   dirents = dir->dirents;
794   req->ptr = NULL;
795 
796   if (dirents == NULL)
797     return;
798 
799   for (i = 0; i < req->result; ++i) {
800     uv__free((char*) dirents[i].name);
801     dirents[i].name = NULL;
802   }
803 }
804 
805 
uv_loop_configure(uv_loop_t * loop,uv_loop_option option,...)806 int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) {
807   va_list ap;
808   int err;
809 
810   va_start(ap, option);
811   /* Any platform-agnostic options should be handled here. */
812   err = uv__loop_configure(loop, option, ap);
813   va_end(ap);
814 
815   return err;
816 }
817 
818 
819 static uv_loop_t default_loop_struct;
820 static uv_loop_t* default_loop_ptr;
821 
822 
uv_default_loop(void)823 uv_loop_t* uv_default_loop(void) {
824   if (default_loop_ptr != NULL)
825     return default_loop_ptr;
826 
827   if (uv_loop_init(&default_loop_struct))
828     return NULL;
829 
830   default_loop_ptr = &default_loop_struct;
831   return default_loop_ptr;
832 }
833 
834 
uv_loop_new(void)835 uv_loop_t* uv_loop_new(void) {
836   uv_loop_t* loop;
837 
838   loop = uv__malloc(sizeof(*loop));
839   if (loop == NULL)
840     return NULL;
841 
842   if (uv_loop_init(loop)) {
843     uv__free(loop);
844     return NULL;
845   }
846 
847   return loop;
848 }
849 
850 
uv_loop_close(uv_loop_t * loop)851 int uv_loop_close(uv_loop_t* loop) {
852   struct uv__queue* q;
853   uv_handle_t* h;
854 #ifndef NDEBUG
855   void* saved_data;
856 #endif
857 
858   if (uv__has_active_reqs(loop))
859     return UV_EBUSY;
860 
861   uv__queue_foreach(q, &loop->handle_queue) {
862     h = uv__queue_data(q, uv_handle_t, handle_queue);
863     if (!(h->flags & UV_HANDLE_INTERNAL))
864       return UV_EBUSY;
865   }
866 
867   uv__loop_close(loop);
868 
869 #ifndef NDEBUG
870   saved_data = loop->data;
871   memset(loop, -1, sizeof(*loop));
872   loop->data = saved_data;
873 #endif
874   if (loop == default_loop_ptr)
875     default_loop_ptr = NULL;
876 
877   return 0;
878 }
879 
880 
uv_loop_delete(uv_loop_t * loop)881 void uv_loop_delete(uv_loop_t* loop) {
882   uv_loop_t* default_loop;
883   int err;
884 
885   default_loop = default_loop_ptr;
886 
887   err = uv_loop_close(loop);
888   (void) err;    /* Squelch compiler warnings. */
889   assert(err == 0);
890   if (loop != default_loop)
891     uv__free(loop);
892 }
893 
894 
uv_read_start(uv_stream_t * stream,uv_alloc_cb alloc_cb,uv_read_cb read_cb)895 int uv_read_start(uv_stream_t* stream,
896                   uv_alloc_cb alloc_cb,
897                   uv_read_cb read_cb) {
898   if (stream == NULL || alloc_cb == NULL || read_cb == NULL)
899     return UV_EINVAL;
900 
901   if (stream->flags & UV_HANDLE_CLOSING)
902     return UV_EINVAL;
903 
904   if (stream->flags & UV_HANDLE_READING)
905     return UV_EALREADY;
906 
907   if (!(stream->flags & UV_HANDLE_READABLE))
908     return UV_ENOTCONN;
909 
910   return uv__read_start(stream, alloc_cb, read_cb);
911 }
912 
913 
uv_os_free_environ(uv_env_item_t * envitems,int count)914 void uv_os_free_environ(uv_env_item_t* envitems, int count) {
915   int i;
916 
917   for (i = 0; i < count; i++) {
918     uv__free(envitems[i].name);
919   }
920 
921   uv__free(envitems);
922 }
923 
924 
uv_free_cpu_info(uv_cpu_info_t * cpu_infos,int count)925 void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
926 #ifdef __linux__
927   (void) &count;
928   uv__free(cpu_infos);
929 #else
930   int i;
931 
932   for (i = 0; i < count; i++)
933     uv__free(cpu_infos[i].model);
934 
935   uv__free(cpu_infos);
936 #endif  /* __linux__ */
937 }
938 
939 
940 /* Also covers __clang__ and __INTEL_COMPILER. Disabled on Windows because
941  * threads have already been forcibly terminated by the operating system
942  * by the time destructors run, ergo, it's not safe to try to clean them up.
943  */
944 #if defined(__GNUC__) && !defined(_WIN32)
945 __attribute__((destructor))
946 #endif
uv_library_shutdown(void)947 void uv_library_shutdown(void) {
948   static int was_shutdown;
949 
950   if (uv__exchange_int_relaxed(&was_shutdown, 1))
951     return;
952 
953   uv__process_title_cleanup();
954   uv__signal_cleanup();
955 #ifdef __MVS__
956   /* TODO(itodorov) - zos: revisit when Woz compiler is available. */
957   uv__os390_cleanup();
958 #else
959   uv__threadpool_cleanup();
960 #endif
961 }
962 
963 
uv__metrics_update_idle_time(uv_loop_t * loop)964 void uv__metrics_update_idle_time(uv_loop_t* loop) {
965   uv__loop_metrics_t* loop_metrics;
966   uint64_t entry_time;
967   uint64_t exit_time;
968 
969   if (!(uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME))
970     return;
971 
972   loop_metrics = uv__get_loop_metrics(loop);
973 
974   /* The thread running uv__metrics_update_idle_time() is always the same
975    * thread that sets provider_entry_time. So it's unnecessary to lock before
976    * retrieving this value.
977    */
978   if (loop_metrics->provider_entry_time == 0)
979     return;
980 
981   exit_time = uv_hrtime();
982 
983   uv_mutex_lock(&loop_metrics->lock);
984   entry_time = loop_metrics->provider_entry_time;
985   loop_metrics->provider_entry_time = 0;
986   loop_metrics->provider_idle_time += exit_time - entry_time;
987   uv_mutex_unlock(&loop_metrics->lock);
988 }
989 
990 
uv__metrics_set_provider_entry_time(uv_loop_t * loop)991 void uv__metrics_set_provider_entry_time(uv_loop_t* loop) {
992   uv__loop_metrics_t* loop_metrics;
993   uint64_t now;
994 
995   if (!(uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME))
996     return;
997 
998   now = uv_hrtime();
999   loop_metrics = uv__get_loop_metrics(loop);
1000   uv_mutex_lock(&loop_metrics->lock);
1001   loop_metrics->provider_entry_time = now;
1002   uv_mutex_unlock(&loop_metrics->lock);
1003 }
1004 
1005 
uv_metrics_info(uv_loop_t * loop,uv_metrics_t * metrics)1006 int uv_metrics_info(uv_loop_t* loop, uv_metrics_t* metrics) {
1007   memcpy(metrics,
1008          &uv__get_loop_metrics(loop)->metrics,
1009          sizeof(*metrics));
1010 
1011   return 0;
1012 }
1013 
1014 
uv_metrics_idle_time(uv_loop_t * loop)1015 uint64_t uv_metrics_idle_time(uv_loop_t* loop) {
1016   uv__loop_metrics_t* loop_metrics;
1017   uint64_t entry_time;
1018   uint64_t idle_time;
1019 
1020   loop_metrics = uv__get_loop_metrics(loop);
1021   uv_mutex_lock(&loop_metrics->lock);
1022   idle_time = loop_metrics->provider_idle_time;
1023   entry_time = loop_metrics->provider_entry_time;
1024   uv_mutex_unlock(&loop_metrics->lock);
1025 
1026   if (entry_time > 0)
1027     idle_time += uv_hrtime() - entry_time;
1028   return idle_time;
1029 }
1030