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