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