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