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 #define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t);
132 
uv_handle_size(uv_handle_type type)133 size_t uv_handle_size(uv_handle_type type) {
134   switch (type) {
135     UV_HANDLE_TYPE_MAP(XX)
136     default:
137       return -1;
138   }
139 }
140 
uv_req_size(uv_req_type type)141 size_t uv_req_size(uv_req_type type) {
142   switch(type) {
143     UV_REQ_TYPE_MAP(XX)
144     default:
145       return -1;
146   }
147 }
148 
149 #undef XX
150 
151 
uv_loop_size(void)152 size_t uv_loop_size(void) {
153   return sizeof(uv_loop_t);
154 }
155 
156 
uv_buf_init(char * base,unsigned int len)157 uv_buf_t uv_buf_init(char* base, unsigned int len) {
158   uv_buf_t buf;
159   buf.base = base;
160   buf.len = len;
161   return buf;
162 }
163 
164 
uv__unknown_err_code(int err)165 static const char* uv__unknown_err_code(int err) {
166   char buf[32];
167   char* copy;
168 
169   snprintf(buf, sizeof(buf), "Unknown system error %d", err);
170   copy = uv__strdup(buf);
171 
172   return copy != NULL ? copy : "Unknown system error";
173 }
174 
175 #define UV_ERR_NAME_GEN_R(name, _) \
176 case UV_## name: \
177   uv__strscpy(buf, #name, buflen); break;
uv_err_name_r(int err,char * buf,size_t buflen)178 char* uv_err_name_r(int err, char* buf, size_t buflen) {
179   switch (err) {
180     UV_ERRNO_MAP(UV_ERR_NAME_GEN_R)
181     default: snprintf(buf, buflen, "Unknown system error %d", err);
182   }
183   return buf;
184 }
185 #undef UV_ERR_NAME_GEN_R
186 
187 
188 #define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name;
uv_err_name(int err)189 const char* uv_err_name(int err) {
190   switch (err) {
191     UV_ERRNO_MAP(UV_ERR_NAME_GEN)
192   }
193   return uv__unknown_err_code(err);
194 }
195 #undef UV_ERR_NAME_GEN
196 
197 
198 #define UV_STRERROR_GEN_R(name, msg) \
199 case UV_ ## name: \
200   snprintf(buf, buflen, "%s", msg); break;
uv_strerror_r(int err,char * buf,size_t buflen)201 char* uv_strerror_r(int err, char* buf, size_t buflen) {
202   switch (err) {
203     UV_ERRNO_MAP(UV_STRERROR_GEN_R)
204     default: snprintf(buf, buflen, "Unknown system error %d", err);
205   }
206   return buf;
207 }
208 #undef UV_STRERROR_GEN_R
209 
210 
211 #define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg;
uv_strerror(int err)212 const char* uv_strerror(int err) {
213   switch (err) {
214     UV_ERRNO_MAP(UV_STRERROR_GEN)
215   }
216   return uv__unknown_err_code(err);
217 }
218 #undef UV_STRERROR_GEN
219 
220 #if !defined(CMAKE_BOOTSTRAP) || defined(_WIN32)
221 
uv_ip4_addr(const char * ip,int port,struct sockaddr_in * addr)222 int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) {
223   memset(addr, 0, sizeof(*addr));
224   addr->sin_family = AF_INET;
225   addr->sin_port = htons(port);
226 #ifdef SIN6_LEN
227   addr->sin_len = sizeof(*addr);
228 #endif
229   return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr));
230 }
231 
232 
uv_ip6_addr(const char * ip,int port,struct sockaddr_in6 * addr)233 int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) {
234   char address_part[40];
235   size_t address_part_size;
236   const char* zone_index;
237 
238   memset(addr, 0, sizeof(*addr));
239   addr->sin6_family = AF_INET6;
240   addr->sin6_port = htons(port);
241 #ifdef SIN6_LEN
242   addr->sin6_len = sizeof(*addr);
243 #endif
244 
245   zone_index = strchr(ip, '%');
246   if (zone_index != NULL) {
247     address_part_size = zone_index - ip;
248     if (address_part_size >= sizeof(address_part))
249       address_part_size = sizeof(address_part) - 1;
250 
251     memcpy(address_part, ip, address_part_size);
252     address_part[address_part_size] = '\0';
253     ip = address_part;
254 
255     zone_index++; /* skip '%' */
256     /* NOTE: unknown interface (id=0) is silently ignored */
257 #ifdef _WIN32
258     addr->sin6_scope_id = atoi(zone_index);
259 #else
260     addr->sin6_scope_id = if_nametoindex(zone_index);
261 #endif
262   }
263 
264   return uv_inet_pton(AF_INET6, ip, &addr->sin6_addr);
265 }
266 
267 
uv_ip4_name(const struct sockaddr_in * src,char * dst,size_t size)268 int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) {
269   return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size);
270 }
271 
272 
uv_ip6_name(const struct sockaddr_in6 * src,char * dst,size_t size)273 int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) {
274   return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size);
275 }
276 
277 
uv_tcp_bind(uv_tcp_t * handle,const struct sockaddr * addr,unsigned int flags)278 int uv_tcp_bind(uv_tcp_t* handle,
279                 const struct sockaddr* addr,
280                 unsigned int flags) {
281   unsigned int addrlen;
282 
283   if (handle->type != UV_TCP)
284     return UV_EINVAL;
285 
286   if (addr->sa_family == AF_INET)
287     addrlen = sizeof(struct sockaddr_in);
288   else if (addr->sa_family == AF_INET6)
289     addrlen = sizeof(struct sockaddr_in6);
290   else
291     return UV_EINVAL;
292 
293   return uv__tcp_bind(handle, addr, addrlen, flags);
294 }
295 
296 
uv_udp_init_ex(uv_loop_t * loop,uv_udp_t * handle,unsigned flags)297 int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned flags) {
298   unsigned extra_flags;
299   int domain;
300   int rc;
301 
302   /* Use the lower 8 bits for the domain. */
303   domain = flags & 0xFF;
304   if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
305     return UV_EINVAL;
306 
307   /* Use the higher bits for extra flags. */
308   extra_flags = flags & ~0xFF;
309   if (extra_flags & ~UV_UDP_RECVMMSG)
310     return UV_EINVAL;
311 
312   rc = uv__udp_init_ex(loop, handle, flags, domain);
313 
314   if (rc == 0)
315     if (extra_flags & UV_UDP_RECVMMSG)
316       handle->flags |= UV_HANDLE_UDP_RECVMMSG;
317 
318   return rc;
319 }
320 
321 
uv_udp_init(uv_loop_t * loop,uv_udp_t * handle)322 int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
323   return uv_udp_init_ex(loop, handle, AF_UNSPEC);
324 }
325 
326 
uv_udp_bind(uv_udp_t * handle,const struct sockaddr * addr,unsigned int flags)327 int uv_udp_bind(uv_udp_t* handle,
328                 const struct sockaddr* addr,
329                 unsigned int flags) {
330   unsigned int addrlen;
331 
332   if (handle->type != UV_UDP)
333     return UV_EINVAL;
334 
335   if (addr->sa_family == AF_INET)
336     addrlen = sizeof(struct sockaddr_in);
337   else if (addr->sa_family == AF_INET6)
338     addrlen = sizeof(struct sockaddr_in6);
339   else
340     return UV_EINVAL;
341 
342   return uv__udp_bind(handle, addr, addrlen, flags);
343 }
344 
345 
uv_tcp_connect(uv_connect_t * req,uv_tcp_t * handle,const struct sockaddr * addr,uv_connect_cb cb)346 int uv_tcp_connect(uv_connect_t* req,
347                    uv_tcp_t* handle,
348                    const struct sockaddr* addr,
349                    uv_connect_cb cb) {
350   unsigned int addrlen;
351 
352   if (handle->type != UV_TCP)
353     return UV_EINVAL;
354 
355   if (addr->sa_family == AF_INET)
356     addrlen = sizeof(struct sockaddr_in);
357   else if (addr->sa_family == AF_INET6)
358     addrlen = sizeof(struct sockaddr_in6);
359   else
360     return UV_EINVAL;
361 
362   return uv__tcp_connect(req, handle, addr, addrlen, cb);
363 }
364 
365 
uv_udp_connect(uv_udp_t * handle,const struct sockaddr * addr)366 int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr) {
367   unsigned int addrlen;
368 
369   if (handle->type != UV_UDP)
370     return UV_EINVAL;
371 
372   /* Disconnect the handle */
373   if (addr == NULL) {
374     if (!(handle->flags & UV_HANDLE_UDP_CONNECTED))
375       return UV_ENOTCONN;
376 
377     return uv__udp_disconnect(handle);
378   }
379 
380   if (addr->sa_family == AF_INET)
381     addrlen = sizeof(struct sockaddr_in);
382   else if (addr->sa_family == AF_INET6)
383     addrlen = sizeof(struct sockaddr_in6);
384   else
385     return UV_EINVAL;
386 
387   if (handle->flags & UV_HANDLE_UDP_CONNECTED)
388     return UV_EISCONN;
389 
390   return uv__udp_connect(handle, addr, addrlen);
391 }
392 
393 
uv__udp_is_connected(uv_udp_t * handle)394 int uv__udp_is_connected(uv_udp_t* handle) {
395   struct sockaddr_storage addr;
396   int addrlen;
397   if (handle->type != UV_UDP)
398     return 0;
399 
400   addrlen = sizeof(addr);
401   if (uv_udp_getpeername(handle, (struct sockaddr*) &addr, &addrlen) != 0)
402     return 0;
403 
404   return addrlen > 0;
405 }
406 
407 
uv__udp_check_before_send(uv_udp_t * handle,const struct sockaddr * addr)408 int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) {
409   unsigned int addrlen;
410 
411   if (handle->type != UV_UDP)
412     return UV_EINVAL;
413 
414   if (addr != NULL && (handle->flags & UV_HANDLE_UDP_CONNECTED))
415     return UV_EISCONN;
416 
417   if (addr == NULL && !(handle->flags & UV_HANDLE_UDP_CONNECTED))
418     return UV_EDESTADDRREQ;
419 
420   if (addr != NULL) {
421     if (addr->sa_family == AF_INET)
422       addrlen = sizeof(struct sockaddr_in);
423     else if (addr->sa_family == AF_INET6)
424       addrlen = sizeof(struct sockaddr_in6);
425 #if defined(AF_UNIX) && !defined(_WIN32)
426     else if (addr->sa_family == AF_UNIX)
427       addrlen = sizeof(struct sockaddr_un);
428 #endif
429     else
430       return UV_EINVAL;
431   } else {
432     addrlen = 0;
433   }
434 
435   return addrlen;
436 }
437 
438 
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)439 int uv_udp_send(uv_udp_send_t* req,
440                 uv_udp_t* handle,
441                 const uv_buf_t bufs[],
442                 unsigned int nbufs,
443                 const struct sockaddr* addr,
444                 uv_udp_send_cb send_cb) {
445   int addrlen;
446 
447   addrlen = uv__udp_check_before_send(handle, addr);
448   if (addrlen < 0)
449     return addrlen;
450 
451   return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
452 }
453 
454 
uv_udp_try_send(uv_udp_t * handle,const uv_buf_t bufs[],unsigned int nbufs,const struct sockaddr * addr)455 int uv_udp_try_send(uv_udp_t* handle,
456                     const uv_buf_t bufs[],
457                     unsigned int nbufs,
458                     const struct sockaddr* addr) {
459   int addrlen;
460 
461   addrlen = uv__udp_check_before_send(handle, addr);
462   if (addrlen < 0)
463     return addrlen;
464 
465   return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen);
466 }
467 
468 
uv_udp_recv_start(uv_udp_t * handle,uv_alloc_cb alloc_cb,uv_udp_recv_cb recv_cb)469 int uv_udp_recv_start(uv_udp_t* handle,
470                       uv_alloc_cb alloc_cb,
471                       uv_udp_recv_cb recv_cb) {
472   if (handle->type != UV_UDP || alloc_cb == NULL || recv_cb == NULL)
473     return UV_EINVAL;
474   else
475     return uv__udp_recv_start(handle, alloc_cb, recv_cb);
476 }
477 
478 
uv_udp_recv_stop(uv_udp_t * handle)479 int uv_udp_recv_stop(uv_udp_t* handle) {
480   if (handle->type != UV_UDP)
481     return UV_EINVAL;
482   else
483     return uv__udp_recv_stop(handle);
484 }
485 
486 #endif
487 
uv_walk(uv_loop_t * loop,uv_walk_cb walk_cb,void * arg)488 void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
489   QUEUE queue;
490   QUEUE* q;
491   uv_handle_t* h;
492 
493   QUEUE_MOVE(&loop->handle_queue, &queue);
494   while (!QUEUE_EMPTY(&queue)) {
495     q = QUEUE_HEAD(&queue);
496     h = QUEUE_DATA(q, uv_handle_t, handle_queue);
497 
498     QUEUE_REMOVE(q);
499     QUEUE_INSERT_TAIL(&loop->handle_queue, q);
500 
501     if (h->flags & UV_HANDLE_INTERNAL) continue;
502     walk_cb(h, arg);
503   }
504 }
505 
506 
uv__print_handles(uv_loop_t * loop,int only_active,FILE * stream)507 static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {
508   const char* type;
509   QUEUE* q;
510   uv_handle_t* h;
511 
512   if (loop == NULL)
513     loop = uv_default_loop();
514 
515   QUEUE_FOREACH(q, &loop->handle_queue) {
516     h = QUEUE_DATA(q, uv_handle_t, handle_queue);
517 
518     if (only_active && !uv__is_active(h))
519       continue;
520 
521     switch (h->type) {
522 #define X(uc, lc) case UV_##uc: type = #lc; break;
523       UV_HANDLE_TYPE_MAP(X)
524 #undef X
525       default: type = "<unknown>";
526     }
527 
528     fprintf(stream,
529             "[%c%c%c] %-8s %p\n",
530             "R-"[!(h->flags & UV_HANDLE_REF)],
531             "A-"[!(h->flags & UV_HANDLE_ACTIVE)],
532             "I-"[!(h->flags & UV_HANDLE_INTERNAL)],
533             type,
534             (void*)h);
535   }
536 }
537 
538 
uv_print_all_handles(uv_loop_t * loop,FILE * stream)539 void uv_print_all_handles(uv_loop_t* loop, FILE* stream) {
540   uv__print_handles(loop, 0, stream);
541 }
542 
543 
uv_print_active_handles(uv_loop_t * loop,FILE * stream)544 void uv_print_active_handles(uv_loop_t* loop, FILE* stream) {
545   uv__print_handles(loop, 1, stream);
546 }
547 
548 
uv_ref(uv_handle_t * handle)549 void uv_ref(uv_handle_t* handle) {
550   uv__handle_ref(handle);
551 }
552 
553 
uv_unref(uv_handle_t * handle)554 void uv_unref(uv_handle_t* handle) {
555   uv__handle_unref(handle);
556 }
557 
558 
uv_has_ref(const uv_handle_t * handle)559 int uv_has_ref(const uv_handle_t* handle) {
560   return uv__has_ref(handle);
561 }
562 
563 
uv_stop(uv_loop_t * loop)564 void uv_stop(uv_loop_t* loop) {
565   loop->stop_flag = 1;
566 }
567 
568 
uv_now(const uv_loop_t * loop)569 uint64_t uv_now(const uv_loop_t* loop) {
570   return loop->time;
571 }
572 
573 
574 
uv__count_bufs(const uv_buf_t bufs[],unsigned int nbufs)575 size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs) {
576   unsigned int i;
577   size_t bytes;
578 
579   bytes = 0;
580   for (i = 0; i < nbufs; i++)
581     bytes += (size_t) bufs[i].len;
582 
583   return bytes;
584 }
585 
uv_recv_buffer_size(uv_handle_t * handle,int * value)586 int uv_recv_buffer_size(uv_handle_t* handle, int* value) {
587   return uv__socket_sockopt(handle, SO_RCVBUF, value);
588 }
589 
uv_send_buffer_size(uv_handle_t * handle,int * value)590 int uv_send_buffer_size(uv_handle_t* handle, int *value) {
591   return uv__socket_sockopt(handle, SO_SNDBUF, value);
592 }
593 
uv_fs_event_getpath(uv_fs_event_t * handle,char * buffer,size_t * size)594 int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) {
595   size_t required_len;
596 
597   if (!uv__is_active(handle)) {
598     *size = 0;
599     return UV_EINVAL;
600   }
601 
602   required_len = strlen(handle->path);
603   if (required_len >= *size) {
604     *size = required_len + 1;
605     return UV_ENOBUFS;
606   }
607 
608   memcpy(buffer, handle->path, required_len);
609   *size = required_len;
610   buffer[required_len] = '\0';
611 
612   return 0;
613 }
614 
615 /* The windows implementation does not have the same structure layout as
616  * the unix implementation (nbufs is not directly inside req but is
617  * contained in a nested union/struct) so this function locates it.
618 */
uv__get_nbufs(uv_fs_t * req)619 static unsigned int* uv__get_nbufs(uv_fs_t* req) {
620 #ifdef _WIN32
621   return &req->fs.info.nbufs;
622 #else
623   return &req->nbufs;
624 #endif
625 }
626 
627 /* uv_fs_scandir() uses the system allocator to allocate memory on non-Windows
628  * systems. So, the memory should be released using free(). On Windows,
629  * uv__malloc() is used, so use uv__free() to free memory.
630 */
631 #ifdef _WIN32
632 # define uv__fs_scandir_free uv__free
633 #else
634 # define uv__fs_scandir_free free
635 #endif
636 
uv__fs_scandir_cleanup(uv_fs_t * req)637 void uv__fs_scandir_cleanup(uv_fs_t* req) {
638   uv__dirent_t** dents;
639 
640   unsigned int* nbufs = uv__get_nbufs(req);
641 
642   dents = req->ptr;
643   if (*nbufs > 0 && *nbufs != (unsigned int) req->result)
644     (*nbufs)--;
645   for (; *nbufs < (unsigned int) req->result; (*nbufs)++)
646     uv__fs_scandir_free(dents[*nbufs]);
647 
648   uv__fs_scandir_free(req->ptr);
649   req->ptr = NULL;
650 }
651 
652 
uv_fs_scandir_next(uv_fs_t * req,uv_dirent_t * ent)653 int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
654   uv__dirent_t** dents;
655   uv__dirent_t* dent;
656   unsigned int* nbufs;
657 
658   /* Check to see if req passed */
659   if (req->result < 0)
660     return req->result;
661 
662   /* Ptr will be null if req was canceled or no files found */
663   if (!req->ptr)
664     return UV_EOF;
665 
666   nbufs = uv__get_nbufs(req);
667   assert(nbufs);
668 
669   dents = req->ptr;
670 
671   /* Free previous entity */
672   if (*nbufs > 0)
673     uv__fs_scandir_free(dents[*nbufs - 1]);
674 
675   /* End was already reached */
676   if (*nbufs == (unsigned int) req->result) {
677     uv__fs_scandir_free(dents);
678     req->ptr = NULL;
679     return UV_EOF;
680   }
681 
682   dent = dents[(*nbufs)++];
683 
684   ent->name = dent->d_name;
685   ent->type = uv__fs_get_dirent_type(dent);
686 
687   return 0;
688 }
689 
uv__fs_get_dirent_type(uv__dirent_t * dent)690 uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent) {
691   uv_dirent_type_t type;
692 
693 #ifdef HAVE_DIRENT_TYPES
694   switch (dent->d_type) {
695     case UV__DT_DIR:
696       type = UV_DIRENT_DIR;
697       break;
698     case UV__DT_FILE:
699       type = UV_DIRENT_FILE;
700       break;
701     case UV__DT_LINK:
702       type = UV_DIRENT_LINK;
703       break;
704     case UV__DT_FIFO:
705       type = UV_DIRENT_FIFO;
706       break;
707     case UV__DT_SOCKET:
708       type = UV_DIRENT_SOCKET;
709       break;
710     case UV__DT_CHAR:
711       type = UV_DIRENT_CHAR;
712       break;
713     case UV__DT_BLOCK:
714       type = UV_DIRENT_BLOCK;
715       break;
716     default:
717       type = UV_DIRENT_UNKNOWN;
718   }
719 #else
720   type = UV_DIRENT_UNKNOWN;
721 #endif
722 
723   return type;
724 }
725 
uv__fs_readdir_cleanup(uv_fs_t * req)726 void uv__fs_readdir_cleanup(uv_fs_t* req) {
727   uv_dir_t* dir;
728   uv_dirent_t* dirents;
729   int i;
730 
731   if (req->ptr == NULL)
732     return;
733 
734   dir = req->ptr;
735   dirents = dir->dirents;
736   req->ptr = NULL;
737 
738   if (dirents == NULL)
739     return;
740 
741   for (i = 0; i < req->result; ++i) {
742     uv__free((char*) dirents[i].name);
743     dirents[i].name = NULL;
744   }
745 }
746 
747 
uv_loop_configure(uv_loop_t * loop,uv_loop_option option,...)748 int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) {
749   va_list ap;
750   int err;
751 
752   va_start(ap, option);
753   /* Any platform-agnostic options should be handled here. */
754   err = uv__loop_configure(loop, option, ap);
755   va_end(ap);
756 
757   return err;
758 }
759 
760 
761 static uv_loop_t default_loop_struct;
762 static uv_loop_t* default_loop_ptr;
763 
764 
uv_default_loop(void)765 uv_loop_t* uv_default_loop(void) {
766   if (default_loop_ptr != NULL)
767     return default_loop_ptr;
768 
769   if (uv_loop_init(&default_loop_struct))
770     return NULL;
771 
772   default_loop_ptr = &default_loop_struct;
773   return default_loop_ptr;
774 }
775 
776 
uv_loop_new(void)777 uv_loop_t* uv_loop_new(void) {
778   uv_loop_t* loop;
779 
780   loop = uv__malloc(sizeof(*loop));
781   if (loop == NULL)
782     return NULL;
783 
784   if (uv_loop_init(loop)) {
785     uv__free(loop);
786     return NULL;
787   }
788 
789   return loop;
790 }
791 
792 
uv_loop_close(uv_loop_t * loop)793 int uv_loop_close(uv_loop_t* loop) {
794   QUEUE* q;
795   uv_handle_t* h;
796 #ifndef NDEBUG
797   void* saved_data;
798 #endif
799 
800   if (uv__has_active_reqs(loop))
801     return UV_EBUSY;
802 
803   QUEUE_FOREACH(q, &loop->handle_queue) {
804     h = QUEUE_DATA(q, uv_handle_t, handle_queue);
805     if (!(h->flags & UV_HANDLE_INTERNAL))
806       return UV_EBUSY;
807   }
808 
809   uv__loop_close(loop);
810 
811 #ifndef NDEBUG
812   saved_data = loop->data;
813   memset(loop, -1, sizeof(*loop));
814   loop->data = saved_data;
815 #endif
816   if (loop == default_loop_ptr)
817     default_loop_ptr = NULL;
818 
819   return 0;
820 }
821 
822 
uv_loop_delete(uv_loop_t * loop)823 void uv_loop_delete(uv_loop_t* loop) {
824   uv_loop_t* default_loop;
825   int err;
826 
827   default_loop = default_loop_ptr;
828 
829   err = uv_loop_close(loop);
830   (void) err;    /* Squelch compiler warnings. */
831   assert(err == 0);
832   if (loop != default_loop)
833     uv__free(loop);
834 }
835 
836 
uv_os_free_environ(uv_env_item_t * envitems,int count)837 void uv_os_free_environ(uv_env_item_t* envitems, int count) {
838   int i;
839 
840   for (i = 0; i < count; i++) {
841     uv__free(envitems[i].name);
842   }
843 
844   uv__free(envitems);
845 }
846 
847 
uv_free_cpu_info(uv_cpu_info_t * cpu_infos,int count)848 void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
849   int i;
850 
851   for (i = 0; i < count; i++)
852     uv__free(cpu_infos[i].model);
853 
854   uv__free(cpu_infos);
855 }
856 
857 
858 #ifdef __GNUC__  /* Also covers __clang__ and __INTEL_COMPILER. */
859 __attribute__((destructor))
860 #endif
uv_library_shutdown(void)861 void uv_library_shutdown(void) {
862   static int was_shutdown;
863 
864   if (uv__load_relaxed(&was_shutdown))
865     return;
866 
867   uv__process_title_cleanup();
868   uv__signal_cleanup();
869   uv__threadpool_cleanup();
870   uv__store_relaxed(&was_shutdown, 1);
871 }
872 
873 
uv__metrics_update_idle_time(uv_loop_t * loop)874 void uv__metrics_update_idle_time(uv_loop_t* loop) {
875   uv__loop_metrics_t* loop_metrics;
876   uint64_t entry_time;
877   uint64_t exit_time;
878 
879   if (!(uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME))
880     return;
881 
882   loop_metrics = uv__get_loop_metrics(loop);
883 
884   /* The thread running uv__metrics_update_idle_time() is always the same
885    * thread that sets provider_entry_time. So it's unnecessary to lock before
886    * retrieving this value.
887    */
888   if (loop_metrics->provider_entry_time == 0)
889     return;
890 
891   exit_time = uv_hrtime();
892 
893   uv_mutex_lock(&loop_metrics->lock);
894   entry_time = loop_metrics->provider_entry_time;
895   loop_metrics->provider_entry_time = 0;
896   loop_metrics->provider_idle_time += exit_time - entry_time;
897   uv_mutex_unlock(&loop_metrics->lock);
898 }
899 
900 
uv__metrics_set_provider_entry_time(uv_loop_t * loop)901 void uv__metrics_set_provider_entry_time(uv_loop_t* loop) {
902   uv__loop_metrics_t* loop_metrics;
903   uint64_t now;
904 
905   if (!(uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME))
906     return;
907 
908   now = uv_hrtime();
909   loop_metrics = uv__get_loop_metrics(loop);
910   uv_mutex_lock(&loop_metrics->lock);
911   loop_metrics->provider_entry_time = now;
912   uv_mutex_unlock(&loop_metrics->lock);
913 }
914 
915 
uv_metrics_idle_time(uv_loop_t * loop)916 uint64_t uv_metrics_idle_time(uv_loop_t* loop) {
917   uv__loop_metrics_t* loop_metrics;
918   uint64_t entry_time;
919   uint64_t idle_time;
920 
921   loop_metrics = uv__get_loop_metrics(loop);
922   uv_mutex_lock(&loop_metrics->lock);
923   idle_time = loop_metrics->provider_idle_time;
924   entry_time = loop_metrics->provider_entry_time;
925   uv_mutex_unlock(&loop_metrics->lock);
926 
927   if (entry_time > 0)
928     idle_time += uv_hrtime() - entry_time;
929   return idle_time;
930 }
931