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