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