libuv-svace-build

Форк
0
/
uv-common.c 
1029 строк · 22.8 Кб
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

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

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

75
void* uv__malloc(size_t size) {
76
  if (size > 0)
77
    return uv__allocator.local_malloc(size);
78
  return NULL;
79
}
80

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

92
void* uv__calloc(size_t count, size_t size) {
93
  return uv__allocator.local_calloc(count, size);
94
}
95

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

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

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

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

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

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

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

185
size_t uv_loop_size(void) {
186
  return sizeof(uv_loop_t);
187
}
188

189

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

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;
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;
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;
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;
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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

589
void uv_print_all_handles(uv_loop_t* loop, FILE* stream) {
590
  uv__print_handles(loop, 0, stream);
591
}
592

593

594
void uv_print_active_handles(uv_loop_t* loop, FILE* stream) {
595
  uv__print_handles(loop, 1, stream);
596
}
597

598

599
void uv_ref(uv_handle_t* handle) {
600
  uv__handle_ref(handle);
601
}
602

603

604
void uv_unref(uv_handle_t* handle) {
605
  uv__handle_unref(handle);
606
}
607

608

609
int uv_has_ref(const uv_handle_t* handle) {
610
  return uv__has_ref(handle);
611
}
612

613

614
void uv_stop(uv_loop_t* loop) {
615
  loop->stop_flag = 1;
616
}
617

618

619
uint64_t uv_now(const uv_loop_t* loop) {
620
  return loop->time;
621
}
622

623

624

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

636
int uv_recv_buffer_size(uv_handle_t* handle, int* value) {
637
  return uv__socket_sockopt(handle, SO_RCVBUF, value);
638
}
639

640
int uv_send_buffer_size(uv_handle_t* handle, int *value) {
641
  return uv__socket_sockopt(handle, SO_SNDBUF, value);
642
}
643

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
*/
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

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

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

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

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

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

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

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

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

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

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

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

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
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

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

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

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

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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.