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 "internal.h" 24 25#include <stdio.h> 26#include <stdint.h> 27#include <stdlib.h> 28#include <string.h> 29#include <assert.h> 30#include <errno.h> 31 32#include <sys/types.h> 33#include <sys/socket.h> 34#include <sys/ioctl.h> 35#include <net/if.h> 36#include <netinet/in.h> 37#include <arpa/inet.h> 38 39#include <sys/time.h> 40#include <unistd.h> 41#include <fcntl.h> 42#include <utmp.h> 43#include <libgen.h> 44 45#include <sys/protosw.h> 46#include <libperfstat.h> 47#include <procinfo.h> 48#include <sys/proc.h> 49#include <sys/procfs.h> 50 51#include <sys/poll.h> 52 53#include <sys/pollset.h> 54#include <ctype.h> 55#ifdef HAVE_SYS_AHAFS_EVPRODS_H 56#include <sys/ahafs_evProds.h> 57#endif 58 59#include <sys/mntctl.h> 60#include <sys/vmount.h> 61#include <limits.h> 62#include <strings.h> 63#include <sys/vnode.h> 64 65#define RDWR_BUF_SIZE 4096 66#define EQ(a,b) (strcmp(a,b) == 0) 67 68char* original_exepath = NULL; 69uv_mutex_t process_title_mutex; 70uv_once_t process_title_mutex_once = UV_ONCE_INIT; 71static void* args_mem = NULL; 72static char** process_argv = NULL; 73static int process_argc = 0; 74static char* process_title_ptr = NULL; 75 76void init_process_title_mutex_once(void) { 77 uv_mutex_init(&process_title_mutex); 78} 79 80 81int uv__platform_loop_init(uv_loop_t* loop) { 82 loop->fs_fd = -1; 83 84 /* Passing maxfd of -1 should mean the limit is determined 85 * by the user's ulimit or the global limit as per the doc */ 86 loop->backend_fd = pollset_create(-1); 87 88 if (loop->backend_fd == -1) 89 return -1; 90 91 return 0; 92} 93 94 95void uv__platform_loop_delete(uv_loop_t* loop) { 96 if (loop->fs_fd != -1) { 97 uv__close(loop->fs_fd); 98 loop->fs_fd = -1; 99 } 100 101 if (loop->backend_fd != -1) { 102 pollset_destroy(loop->backend_fd); 103 loop->backend_fd = -1; 104 } 105} 106 107 108int uv__io_fork(uv_loop_t* loop) { 109 uv__platform_loop_delete(loop); 110 111 return uv__platform_loop_init(loop); 112} 113 114 115int uv__io_check_fd(uv_loop_t* loop, int fd) { 116 struct poll_ctl pc; 117 118 pc.events = POLLIN; 119 pc.cmd = PS_MOD; /* Equivalent to PS_ADD if the fd is not in the pollset. */ 120 pc.fd = fd; 121 122 if (pollset_ctl(loop->backend_fd, &pc, 1)) 123 return UV__ERR(errno); 124 125 pc.cmd = PS_DELETE; 126 if (pollset_ctl(loop->backend_fd, &pc, 1)) 127 abort(); 128 129 return 0; 130} 131 132 133void uv__io_poll(uv_loop_t* loop, int timeout) { 134 uv__loop_internal_fields_t* lfields; 135 struct pollfd events[1024]; 136 struct pollfd pqry; 137 struct pollfd* pe; 138 struct poll_ctl pc; 139 struct uv__queue* q; 140 uv__io_t* w; 141 uint64_t base; 142 uint64_t diff; 143 int have_signals; 144 int nevents; 145 int count; 146 int nfds; 147 int i; 148 int rc; 149 int add_failed; 150 int user_timeout; 151 int reset_timeout; 152 153 if (loop->nfds == 0) { 154 assert(uv__queue_empty(&loop->watcher_queue)); 155 return; 156 } 157 158 lfields = uv__get_internal_fields(loop); 159 160 while (!uv__queue_empty(&loop->watcher_queue)) { 161 q = uv__queue_head(&loop->watcher_queue); 162 uv__queue_remove(q); 163 uv__queue_init(q); 164 165 w = uv__queue_data(q, uv__io_t, watcher_queue); 166 assert(w->pevents != 0); 167 assert(w->fd >= 0); 168 assert(w->fd < (int) loop->nwatchers); 169 170 pc.events = w->pevents; 171 pc.fd = w->fd; 172 173 add_failed = 0; 174 if (w->events == 0) { 175 pc.cmd = PS_ADD; 176 if (pollset_ctl(loop->backend_fd, &pc, 1)) { 177 if (errno != EINVAL) { 178 assert(0 && "Failed to add file descriptor (pc.fd) to pollset"); 179 abort(); 180 } 181 /* Check if the fd is already in the pollset */ 182 pqry.fd = pc.fd; 183 rc = pollset_query(loop->backend_fd, &pqry); 184 switch (rc) { 185 case -1: 186 assert(0 && "Failed to query pollset for file descriptor"); 187 abort(); 188 case 0: 189 assert(0 && "Pollset does not contain file descriptor"); 190 abort(); 191 } 192 /* If we got here then the pollset already contained the file descriptor even though 193 * we didn't think it should. This probably shouldn't happen, but we can continue. */ 194 add_failed = 1; 195 } 196 } 197 if (w->events != 0 || add_failed) { 198 /* Modify, potentially removing events -- need to delete then add. 199 * Could maybe mod if we knew for sure no events are removed, but 200 * content of w->events is handled above as not reliable (falls back) 201 * so may require a pollset_query() which would have to be pretty cheap 202 * compared to a PS_DELETE to be worth optimizing. Alternatively, could 203 * lazily remove events, squelching them in the mean time. */ 204 pc.cmd = PS_DELETE; 205 if (pollset_ctl(loop->backend_fd, &pc, 1)) { 206 assert(0 && "Failed to delete file descriptor (pc.fd) from pollset"); 207 abort(); 208 } 209 pc.cmd = PS_ADD; 210 if (pollset_ctl(loop->backend_fd, &pc, 1)) { 211 assert(0 && "Failed to add file descriptor (pc.fd) to pollset"); 212 abort(); 213 } 214 } 215 216 w->events = w->pevents; 217 } 218 219 assert(timeout >= -1); 220 base = loop->time; 221 count = 48; /* Benchmarks suggest this gives the best throughput. */ 222 223 if (lfields->flags & UV_METRICS_IDLE_TIME) { 224 reset_timeout = 1; 225 user_timeout = timeout; 226 timeout = 0; 227 } else { 228 reset_timeout = 0; 229 } 230 231 for (;;) { 232 /* Only need to set the provider_entry_time if timeout != 0. The function 233 * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. 234 */ 235 if (timeout != 0) 236 uv__metrics_set_provider_entry_time(loop); 237 238 /* Store the current timeout in a location that's globally accessible so 239 * other locations like uv__work_done() can determine whether the queue 240 * of events in the callback were waiting when poll was called. 241 */ 242 lfields->current_timeout = timeout; 243 244 nfds = pollset_poll(loop->backend_fd, 245 events, 246 ARRAY_SIZE(events), 247 timeout); 248 249 /* Update loop->time unconditionally. It's tempting to skip the update when 250 * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the 251 * operating system didn't reschedule our process while in the syscall. 252 */ 253 SAVE_ERRNO(uv__update_time(loop)); 254 255 if (nfds == 0) { 256 if (reset_timeout != 0) { 257 timeout = user_timeout; 258 reset_timeout = 0; 259 if (timeout == -1) 260 continue; 261 if (timeout > 0) 262 goto update_timeout; 263 } 264 265 assert(timeout != -1); 266 return; 267 } 268 269 if (nfds == -1) { 270 if (errno != EINTR) { 271 abort(); 272 } 273 274 if (reset_timeout != 0) { 275 timeout = user_timeout; 276 reset_timeout = 0; 277 } 278 279 if (timeout == -1) 280 continue; 281 282 if (timeout == 0) 283 return; 284 285 /* Interrupted by a signal. Update timeout and poll again. */ 286 goto update_timeout; 287 } 288 289 have_signals = 0; 290 nevents = 0; 291 292 assert(loop->watchers != NULL); 293 loop->watchers[loop->nwatchers] = (void*) events; 294 loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; 295 296 for (i = 0; i < nfds; i++) { 297 pe = events + i; 298 pc.cmd = PS_DELETE; 299 pc.fd = pe->fd; 300 301 /* Skip invalidated events, see uv__platform_invalidate_fd */ 302 if (pc.fd == -1) 303 continue; 304 305 assert(pc.fd >= 0); 306 assert((unsigned) pc.fd < loop->nwatchers); 307 308 w = loop->watchers[pc.fd]; 309 310 if (w == NULL) { 311 /* File descriptor that we've stopped watching, disarm it. 312 * 313 * Ignore all errors because we may be racing with another thread 314 * when the file descriptor is closed. 315 */ 316 pollset_ctl(loop->backend_fd, &pc, 1); 317 continue; 318 } 319 320 /* Run signal watchers last. This also affects child process watchers 321 * because those are implemented in terms of signal watchers. 322 */ 323 if (w == &loop->signal_io_watcher) { 324 have_signals = 1; 325 } else { 326 uv__metrics_update_idle_time(loop); 327 w->cb(loop, w, pe->revents); 328 } 329 330 nevents++; 331 } 332 333 uv__metrics_inc_events(loop, nevents); 334 if (reset_timeout != 0) { 335 timeout = user_timeout; 336 reset_timeout = 0; 337 uv__metrics_inc_events_waiting(loop, nevents); 338 } 339 340 if (have_signals != 0) { 341 uv__metrics_update_idle_time(loop); 342 loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); 343 } 344 345 loop->watchers[loop->nwatchers] = NULL; 346 loop->watchers[loop->nwatchers + 1] = NULL; 347 348 if (have_signals != 0) 349 return; /* Event loop should cycle now so don't poll again. */ 350 351 if (nevents != 0) { 352 if (nfds == ARRAY_SIZE(events) && --count != 0) { 353 /* Poll for more events but don't block this time. */ 354 timeout = 0; 355 continue; 356 } 357 return; 358 } 359 360 if (timeout == 0) 361 return; 362 363 if (timeout == -1) 364 continue; 365 366update_timeout: 367 assert(timeout > 0); 368 369 diff = loop->time - base; 370 if (diff >= (uint64_t) timeout) 371 return; 372 373 timeout -= diff; 374 } 375} 376 377 378uint64_t uv_get_free_memory(void) { 379 perfstat_memory_total_t mem_total; 380 int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1); 381 if (result == -1) { 382 return 0; 383 } 384 return mem_total.real_free * 4096; 385} 386 387 388uint64_t uv_get_total_memory(void) { 389 perfstat_memory_total_t mem_total; 390 int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1); 391 if (result == -1) { 392 return 0; 393 } 394 return mem_total.real_total * 4096; 395} 396 397 398uint64_t uv_get_constrained_memory(void) { 399 return 0; /* Memory constraints are unknown. */ 400} 401 402 403uint64_t uv_get_available_memory(void) { 404 return uv_get_free_memory(); 405} 406 407 408void uv_loadavg(double avg[3]) { 409 perfstat_cpu_total_t ps_total; 410 int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1); 411 if (result == -1) { 412 avg[0] = 0.; avg[1] = 0.; avg[2] = 0.; 413 return; 414 } 415 avg[0] = ps_total.loadavg[0] / (double)(1 << SBITS); 416 avg[1] = ps_total.loadavg[1] / (double)(1 << SBITS); 417 avg[2] = ps_total.loadavg[2] / (double)(1 << SBITS); 418} 419 420 421#ifdef HAVE_SYS_AHAFS_EVPRODS_H 422static char* uv__rawname(const char* cp, char (*dst)[FILENAME_MAX+1]) { 423 char* dp; 424 425 dp = rindex(cp, '/'); 426 if (dp == 0) 427 return 0; 428 429 snprintf(*dst, sizeof(*dst), "%.*s/r%s", (int) (dp - cp), cp, dp + 1); 430 return *dst; 431} 432 433 434/* 435 * Determine whether given pathname is a directory 436 * Returns 0 if the path is a directory, -1 if not 437 * 438 * Note: Opportunity here for more detailed error information but 439 * that requires changing callers of this function as well 440 */ 441static int uv__path_is_a_directory(char* filename) { 442 struct stat statbuf; 443 444 if (uv__stat(filename, &statbuf) < 0) 445 return -1; /* failed: not a directory, assume it is a file */ 446 447 if (statbuf.st_type == VDIR) 448 return 0; 449 450 return -1; 451} 452 453 454/* 455 * Check whether AHAFS is mounted. 456 * Returns 0 if AHAFS is mounted, or an error code < 0 on failure 457 */ 458static int uv__is_ahafs_mounted(void){ 459 char rawbuf[FILENAME_MAX+1]; 460 int rv, i = 2; 461 struct vmount *p; 462 int size_multiplier = 10; 463 size_t siz = sizeof(struct vmount)*size_multiplier; 464 struct vmount *vmt; 465 const char *dev = "/aha"; 466 char *obj, *stub; 467 468 p = uv__malloc(siz); 469 if (p == NULL) 470 return UV__ERR(errno); 471 472 /* Retrieve all mounted filesystems */ 473 rv = mntctl(MCTL_QUERY, siz, (char*)p); 474 if (rv < 0) 475 return UV__ERR(errno); 476 if (rv == 0) { 477 /* buffer was not large enough, reallocate to correct size */ 478 siz = *(int*)p; 479 uv__free(p); 480 p = uv__malloc(siz); 481 if (p == NULL) 482 return UV__ERR(errno); 483 rv = mntctl(MCTL_QUERY, siz, (char*)p); 484 if (rv < 0) 485 return UV__ERR(errno); 486 } 487 488 /* Look for dev in filesystems mount info */ 489 for(vmt = p, i = 0; i < rv; i++) { 490 obj = vmt2dataptr(vmt, VMT_OBJECT); /* device */ 491 stub = vmt2dataptr(vmt, VMT_STUB); /* mount point */ 492 493 if (EQ(obj, dev) || EQ(uv__rawname(obj, &rawbuf), dev) || EQ(stub, dev)) { 494 uv__free(p); /* Found a match */ 495 return 0; 496 } 497 vmt = (struct vmount *) ((char *) vmt + vmt->vmt_length); 498 } 499 500 /* /aha is required for monitoring filesystem changes */ 501 return -1; 502} 503 504/* 505 * Recursive call to mkdir() to create intermediate folders, if any 506 * Returns code from mkdir call 507 */ 508static int uv__makedir_p(const char *dir) { 509 char tmp[256]; 510 char *p = NULL; 511 size_t len; 512 int err; 513 514 /* TODO(bnoordhuis) Check uv__strscpy() return value. */ 515 uv__strscpy(tmp, dir, sizeof(tmp)); 516 len = strlen(tmp); 517 if (tmp[len - 1] == '/') 518 tmp[len - 1] = 0; 519 for (p = tmp + 1; *p; p++) { 520 if (*p == '/') { 521 *p = 0; 522 err = mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 523 if (err != 0 && errno != EEXIST) 524 return err; 525 *p = '/'; 526 } 527 } 528 return mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 529} 530 531/* 532 * Creates necessary subdirectories in the AIX Event Infrastructure 533 * file system for monitoring the object specified. 534 * Returns code from mkdir call 535 */ 536static int uv__make_subdirs_p(const char *filename) { 537 char cmd[2048]; 538 char *p; 539 int rc = 0; 540 541 /* Strip off the monitor file name */ 542 p = strrchr(filename, '/'); 543 544 if (p == NULL) 545 return 0; 546 547 if (uv__path_is_a_directory((char*)filename) == 0) { 548 sprintf(cmd, "/aha/fs/modDir.monFactory"); 549 } else { 550 sprintf(cmd, "/aha/fs/modFile.monFactory"); 551 } 552 553 strncat(cmd, filename, (p - filename)); 554 rc = uv__makedir_p(cmd); 555 556 if (rc == -1 && errno != EEXIST){ 557 return UV__ERR(errno); 558 } 559 560 return rc; 561} 562 563 564/* 565 * Checks if /aha is mounted, then proceeds to set up the monitoring 566 * objects for the specified file. 567 * Returns 0 on success, or an error code < 0 on failure 568 */ 569static int uv__setup_ahafs(const char* filename, int *fd) { 570 int rc = 0; 571 char mon_file_write_string[RDWR_BUF_SIZE]; 572 char mon_file[PATH_MAX]; 573 int file_is_directory = 0; /* -1 == NO, 0 == YES */ 574 575 /* Create monitor file name for object */ 576 file_is_directory = uv__path_is_a_directory((char*)filename); 577 578 if (file_is_directory == 0) 579 sprintf(mon_file, "/aha/fs/modDir.monFactory"); 580 else 581 sprintf(mon_file, "/aha/fs/modFile.monFactory"); 582 583 if ((strlen(mon_file) + strlen(filename) + 5) > PATH_MAX) 584 return UV_ENAMETOOLONG; 585 586 /* Make the necessary subdirectories for the monitor file */ 587 rc = uv__make_subdirs_p(filename); 588 if (rc == -1 && errno != EEXIST) 589 return rc; 590 591 strcat(mon_file, filename); 592 strcat(mon_file, ".mon"); 593 594 *fd = 0; errno = 0; 595 596 /* Open the monitor file, creating it if necessary */ 597 *fd = open(mon_file, O_CREAT|O_RDWR); 598 if (*fd < 0) 599 return UV__ERR(errno); 600 601 /* Write out the monitoring specifications. 602 * In this case, we are monitoring for a state change event type 603 * CHANGED=YES 604 * We will be waiting in select call, rather than a read: 605 * WAIT_TYPE=WAIT_IN_SELECT 606 * We only want minimal information for files: 607 * INFO_LVL=1 608 * For directories, we want more information to track what file 609 * caused the change 610 * INFO_LVL=2 611 */ 612 613 if (file_is_directory == 0) 614 sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=2"); 615 else 616 sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=1"); 617 618 rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1); 619 if (rc < 0 && errno != EBUSY) 620 return UV__ERR(errno); 621 622 return 0; 623} 624 625/* 626 * Skips a specified number of lines in the buffer passed in. 627 * Walks the buffer pointed to by p and attempts to skip n lines. 628 * Returns the total number of lines skipped 629 */ 630static int uv__skip_lines(char **p, int n) { 631 int lines = 0; 632 633 while(n > 0) { 634 *p = strchr(*p, '\n'); 635 if (!p) 636 return lines; 637 638 (*p)++; 639 n--; 640 lines++; 641 } 642 return lines; 643} 644 645 646/* 647 * Parse the event occurrence data to figure out what event just occurred 648 * and take proper action. 649 * 650 * The buf is a pointer to the buffer containing the event occurrence data 651 * Returns 0 on success, -1 if unrecoverable error in parsing 652 * 653 */ 654static int uv__parse_data(char *buf, int *events, uv_fs_event_t* handle) { 655 int evp_rc, i; 656 char *p; 657 char filename[PATH_MAX]; /* To be used when handling directories */ 658 659 p = buf; 660 *events = 0; 661 662 /* Clean the filename buffer*/ 663 for(i = 0; i < PATH_MAX; i++) { 664 filename[i] = 0; 665 } 666 i = 0; 667 668 /* Check for BUF_WRAP */ 669 if (strncmp(buf, "BUF_WRAP", strlen("BUF_WRAP")) == 0) { 670 assert(0 && "Buffer wrap detected, Some event occurrences lost!"); 671 return 0; 672 } 673 674 /* Since we are using the default buffer size (4K), and have specified 675 * INFO_LVL=1, we won't see any EVENT_OVERFLOW conditions. Applications 676 * should check for this keyword if they are using an INFO_LVL of 2 or 677 * higher, and have a buffer size of <= 4K 678 */ 679 680 /* Skip to RC_FROM_EVPROD */ 681 if (uv__skip_lines(&p, 9) != 9) 682 return -1; 683 684 if (sscanf(p, "RC_FROM_EVPROD=%d\nEND_EVENT_DATA", &evp_rc) == 1) { 685 if (uv__path_is_a_directory(handle->path) == 0) { /* Directory */ 686 if (evp_rc == AHAFS_MODDIR_UNMOUNT || evp_rc == AHAFS_MODDIR_REMOVE_SELF) { 687 /* The directory is no longer available for monitoring */ 688 *events = UV_RENAME; 689 handle->dir_filename = NULL; 690 } else { 691 /* A file was added/removed inside the directory */ 692 *events = UV_CHANGE; 693 694 /* Get the EVPROD_INFO */ 695 if (uv__skip_lines(&p, 1) != 1) 696 return -1; 697 698 /* Scan out the name of the file that triggered the event*/ 699 if (sscanf(p, "BEGIN_EVPROD_INFO\n%sEND_EVPROD_INFO", filename) == 1) { 700 handle->dir_filename = uv__strdup((const char*)&filename); 701 } else 702 return -1; 703 } 704 } else { /* Regular File */ 705 if (evp_rc == AHAFS_MODFILE_RENAME) 706 *events = UV_RENAME; 707 else 708 *events = UV_CHANGE; 709 } 710 } 711 else 712 return -1; 713 714 return 0; 715} 716 717 718/* This is the internal callback */ 719static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int fflags) { 720 char result_data[RDWR_BUF_SIZE]; 721 int bytes, rc = 0; 722 uv_fs_event_t* handle; 723 int events = 0; 724 char fname[PATH_MAX]; 725 char *p; 726 727 handle = container_of(event_watch, uv_fs_event_t, event_watcher); 728 729 /* At this point, we assume that polling has been done on the 730 * file descriptor, so we can just read the AHAFS event occurrence 731 * data and parse its results without having to block anything 732 */ 733 bytes = pread(event_watch->fd, result_data, RDWR_BUF_SIZE, 0); 734 735 assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file"); 736 737 /* In file / directory move cases, AIX Event infrastructure 738 * produces a second event with no data. 739 * Ignore it and return gracefully. 740 */ 741 if(bytes == 0) 742 return; 743 744 /* Parse the data */ 745 if(bytes > 0) 746 rc = uv__parse_data(result_data, &events, handle); 747 748 /* Unrecoverable error */ 749 if (rc == -1) 750 return; 751 752 /* For directory changes, the name of the files that triggered the change 753 * are never absolute pathnames 754 */ 755 if (uv__path_is_a_directory(handle->path) == 0) { 756 p = handle->dir_filename; 757 } else { 758 p = strrchr(handle->path, '/'); 759 if (p == NULL) 760 p = handle->path; 761 else 762 p++; 763 } 764 765 /* TODO(bnoordhuis) Check uv__strscpy() return value. */ 766 uv__strscpy(fname, p, sizeof(fname)); 767 768 handle->cb(handle, fname, events, 0); 769} 770#endif 771 772 773int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { 774#ifdef HAVE_SYS_AHAFS_EVPRODS_H 775 uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); 776 return 0; 777#else 778 return UV_ENOSYS; 779#endif 780} 781 782 783int uv_fs_event_start(uv_fs_event_t* handle, 784 uv_fs_event_cb cb, 785 const char* filename, 786 unsigned int flags) { 787#ifdef HAVE_SYS_AHAFS_EVPRODS_H 788 int fd, rc, str_offset = 0; 789 char cwd[PATH_MAX]; 790 char absolute_path[PATH_MAX]; 791 char readlink_cwd[PATH_MAX]; 792 struct timeval zt; 793 fd_set pollfd; 794 795 796 /* Figure out whether filename is absolute or not */ 797 if (filename[0] == '\0') { 798 /* Missing a pathname */ 799 return UV_ENOENT; 800 } 801 else if (filename[0] == '/') { 802 /* We have absolute pathname */ 803 /* TODO(bnoordhuis) Check uv__strscpy() return value. */ 804 uv__strscpy(absolute_path, filename, sizeof(absolute_path)); 805 } else { 806 /* We have a relative pathname, compose the absolute pathname */ 807 snprintf(cwd, sizeof(cwd), "/proc/%lu/cwd", (unsigned long) getpid()); 808 rc = readlink(cwd, readlink_cwd, sizeof(readlink_cwd) - 1); 809 if (rc < 0) 810 return rc; 811 /* readlink does not null terminate our string */ 812 readlink_cwd[rc] = '\0'; 813 814 if (filename[0] == '.' && filename[1] == '/') 815 str_offset = 2; 816 817 snprintf(absolute_path, sizeof(absolute_path), "%s%s", readlink_cwd, 818 filename + str_offset); 819 } 820 821 if (uv__is_ahafs_mounted() < 0) /* /aha checks failed */ 822 return UV_ENOSYS; 823 824 /* Setup ahafs */ 825 rc = uv__setup_ahafs((const char *)absolute_path, &fd); 826 if (rc != 0) 827 return rc; 828 829 /* Setup/Initialize all the libuv routines */ 830 uv__handle_start(handle); 831 uv__io_init(&handle->event_watcher, uv__ahafs_event, fd); 832 handle->path = uv__strdup(filename); 833 handle->cb = cb; 834 handle->dir_filename = NULL; 835 836 uv__io_start(handle->loop, &handle->event_watcher, POLLIN); 837 838 /* AHAFS wants someone to poll for it to start mointoring. 839 * so kick-start it so that we don't miss an event in the 840 * eventuality of an event that occurs in the current loop. */ 841 do { 842 memset(&zt, 0, sizeof(zt)); 843 FD_ZERO(&pollfd); 844 FD_SET(fd, &pollfd); 845 rc = select(fd + 1, &pollfd, NULL, NULL, &zt); 846 } while (rc == -1 && errno == EINTR); 847 return 0; 848#else 849 return UV_ENOSYS; 850#endif 851} 852 853 854int uv_fs_event_stop(uv_fs_event_t* handle) { 855#ifdef HAVE_SYS_AHAFS_EVPRODS_H 856 if (!uv__is_active(handle)) 857 return 0; 858 859 uv__io_close(handle->loop, &handle->event_watcher); 860 uv__handle_stop(handle); 861 862 if (uv__path_is_a_directory(handle->path) == 0) { 863 uv__free(handle->dir_filename); 864 handle->dir_filename = NULL; 865 } 866 867 uv__free(handle->path); 868 handle->path = NULL; 869 uv__close(handle->event_watcher.fd); 870 handle->event_watcher.fd = -1; 871 872 return 0; 873#else 874 return UV_ENOSYS; 875#endif 876} 877 878 879void uv__fs_event_close(uv_fs_event_t* handle) { 880#ifdef HAVE_SYS_AHAFS_EVPRODS_H 881 uv_fs_event_stop(handle); 882#else 883 UNREACHABLE(); 884#endif 885} 886 887 888char** uv_setup_args(int argc, char** argv) { 889 char exepath[UV__PATH_MAX]; 890 char** new_argv; 891 size_t size; 892 char* s; 893 int i; 894 895 if (argc <= 0) 896 return argv; 897 898 /* Save the original pointer to argv. 899 * AIX uses argv to read the process name. 900 * (Not the memory pointed to by argv[0..n] as on Linux.) 901 */ 902 process_argv = argv; 903 process_argc = argc; 904 905 /* Use argv[0] to determine value for uv_exepath(). */ 906 size = sizeof(exepath); 907 if (uv__search_path(argv[0], exepath, &size) == 0) { 908 uv_once(&process_title_mutex_once, init_process_title_mutex_once); 909 uv_mutex_lock(&process_title_mutex); 910 original_exepath = uv__strdup(exepath); 911 uv_mutex_unlock(&process_title_mutex); 912 } 913 914 /* Calculate how much memory we need for the argv strings. */ 915 size = 0; 916 for (i = 0; i < argc; i++) 917 size += strlen(argv[i]) + 1; 918 919 /* Add space for the argv pointers. */ 920 size += (argc + 1) * sizeof(char*); 921 922 new_argv = uv__malloc(size); 923 if (new_argv == NULL) 924 return argv; 925 args_mem = new_argv; 926 927 /* Copy over the strings and set up the pointer table. */ 928 s = (char*) &new_argv[argc + 1]; 929 for (i = 0; i < argc; i++) { 930 size = strlen(argv[i]) + 1; 931 memcpy(s, argv[i], size); 932 new_argv[i] = s; 933 s += size; 934 } 935 new_argv[i] = NULL; 936 937 return new_argv; 938} 939 940 941int uv_set_process_title(const char* title) { 942 char* new_title; 943 944 /* If uv_setup_args wasn't called or failed, we can't continue. */ 945 if (process_argv == NULL || args_mem == NULL) 946 return UV_ENOBUFS; 947 948 /* We cannot free this pointer when libuv shuts down, 949 * the process may still be using it. 950 */ 951 new_title = uv__strdup(title); 952 if (new_title == NULL) 953 return UV_ENOMEM; 954 955 uv_once(&process_title_mutex_once, init_process_title_mutex_once); 956 uv_mutex_lock(&process_title_mutex); 957 958 /* If this is the first time this is set, 959 * don't free and set argv[1] to NULL. 960 */ 961 if (process_title_ptr != NULL) 962 uv__free(process_title_ptr); 963 964 process_title_ptr = new_title; 965 966 process_argv[0] = process_title_ptr; 967 if (process_argc > 1) 968 process_argv[1] = NULL; 969 970 uv_mutex_unlock(&process_title_mutex); 971 972 return 0; 973} 974 975 976int uv_get_process_title(char* buffer, size_t size) { 977 size_t len; 978 if (buffer == NULL || size == 0) 979 return UV_EINVAL; 980 981 /* If uv_setup_args wasn't called, we can't continue. */ 982 if (process_argv == NULL) 983 return UV_ENOBUFS; 984 985 uv_once(&process_title_mutex_once, init_process_title_mutex_once); 986 uv_mutex_lock(&process_title_mutex); 987 988 len = strlen(process_argv[0]); 989 if (size <= len) { 990 uv_mutex_unlock(&process_title_mutex); 991 return UV_ENOBUFS; 992 } 993 994 memcpy(buffer, process_argv[0], len); 995 buffer[len] = '\0'; 996 997 uv_mutex_unlock(&process_title_mutex); 998 999 return 0; 1000} 1001 1002 1003void uv__process_title_cleanup(void) { 1004 uv__free(args_mem); /* Keep valgrind happy. */ 1005 args_mem = NULL; 1006} 1007 1008 1009int uv_resident_set_memory(size_t* rss) { 1010 char pp[64]; 1011 psinfo_t psinfo; 1012 int err; 1013 int fd; 1014 1015 snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid()); 1016 1017 fd = open(pp, O_RDONLY); 1018 if (fd == -1) 1019 return UV__ERR(errno); 1020 1021 /* FIXME(bnoordhuis) Handle EINTR. */ 1022 err = UV_EINVAL; 1023 if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) { 1024 *rss = (size_t)psinfo.pr_rssize * 1024; 1025 err = 0; 1026 } 1027 uv__close(fd); 1028 1029 return err; 1030} 1031 1032 1033int uv_uptime(double* uptime) { 1034 struct utmp *utmp_buf; 1035 size_t entries = 0; 1036 time_t boot_time; 1037 1038 boot_time = 0; 1039 utmpname(UTMP_FILE); 1040 1041 setutent(); 1042 1043 while ((utmp_buf = getutent()) != NULL) { 1044 if (utmp_buf->ut_user[0] && utmp_buf->ut_type == USER_PROCESS) 1045 ++entries; 1046 if (utmp_buf->ut_type == BOOT_TIME) 1047 boot_time = utmp_buf->ut_time; 1048 } 1049 1050 endutent(); 1051 1052 if (boot_time == 0) 1053 return UV_ENOSYS; 1054 1055 *uptime = time(NULL) - boot_time; 1056 return 0; 1057} 1058 1059 1060int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 1061 uv_cpu_info_t* cpu_info; 1062 perfstat_cpu_total_t ps_total; 1063 perfstat_cpu_t* ps_cpus; 1064 perfstat_id_t cpu_id; 1065 int result, ncpus, idx = 0; 1066 1067 result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1); 1068 if (result == -1) { 1069 return UV_ENOSYS; 1070 } 1071 1072 ncpus = result = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0); 1073 if (result == -1) { 1074 return UV_ENOSYS; 1075 } 1076 1077 ps_cpus = (perfstat_cpu_t*) uv__malloc(ncpus * sizeof(perfstat_cpu_t)); 1078 if (!ps_cpus) { 1079 return UV_ENOMEM; 1080 } 1081 1082 /* TODO(bnoordhuis) Check uv__strscpy() return value. */ 1083 uv__strscpy(cpu_id.name, FIRST_CPU, sizeof(cpu_id.name)); 1084 result = perfstat_cpu(&cpu_id, ps_cpus, sizeof(perfstat_cpu_t), ncpus); 1085 if (result == -1) { 1086 uv__free(ps_cpus); 1087 return UV_ENOSYS; 1088 } 1089 1090 *cpu_infos = (uv_cpu_info_t*) uv__malloc(ncpus * sizeof(uv_cpu_info_t)); 1091 if (!*cpu_infos) { 1092 uv__free(ps_cpus); 1093 return UV_ENOMEM; 1094 } 1095 1096 *count = ncpus; 1097 1098 cpu_info = *cpu_infos; 1099 while (idx < ncpus) { 1100 cpu_info->speed = (int)(ps_total.processorHZ / 1000000); 1101 cpu_info->model = uv__strdup(ps_total.description); 1102 cpu_info->cpu_times.user = ps_cpus[idx].user; 1103 cpu_info->cpu_times.sys = ps_cpus[idx].sys; 1104 cpu_info->cpu_times.idle = ps_cpus[idx].idle; 1105 cpu_info->cpu_times.irq = ps_cpus[idx].wait; 1106 cpu_info->cpu_times.nice = 0; 1107 cpu_info++; 1108 idx++; 1109 } 1110 1111 uv__free(ps_cpus); 1112 return 0; 1113} 1114 1115 1116int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { 1117 uv_interface_address_t* address; 1118 int sockfd, sock6fd, inet6, i, r, size = 1; 1119 struct ifconf ifc; 1120 struct ifreq *ifr, *p, flg; 1121 struct in6_ifreq if6; 1122 struct sockaddr_dl* sa_addr; 1123 1124 ifc.ifc_req = NULL; 1125 sock6fd = -1; 1126 r = 0; 1127 *count = 0; 1128 *addresses = NULL; 1129 1130 if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) { 1131 r = UV__ERR(errno); 1132 goto cleanup; 1133 } 1134 1135 if (0 > (sock6fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP))) { 1136 r = UV__ERR(errno); 1137 goto cleanup; 1138 } 1139 1140 if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) { 1141 r = UV__ERR(errno); 1142 goto cleanup; 1143 } 1144 1145 ifc.ifc_req = (struct ifreq*)uv__malloc(size); 1146 if (ifc.ifc_req == NULL) { 1147 r = UV_ENOMEM; 1148 goto cleanup; 1149 } 1150 ifc.ifc_len = size; 1151 if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { 1152 r = UV__ERR(errno); 1153 goto cleanup; 1154 } 1155 1156#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) 1157 1158 /* Count all up and running ipv4/ipv6 addresses */ 1159 ifr = ifc.ifc_req; 1160 while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { 1161 p = ifr; 1162 ifr = (struct ifreq*) 1163 ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); 1164 1165 if (!(p->ifr_addr.sa_family == AF_INET6 || 1166 p->ifr_addr.sa_family == AF_INET)) 1167 continue; 1168 1169 memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); 1170 if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { 1171 r = UV__ERR(errno); 1172 goto cleanup; 1173 } 1174 1175 if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) 1176 continue; 1177 1178 (*count)++; 1179 } 1180 1181 if (*count == 0) 1182 goto cleanup; 1183 1184 /* Alloc the return interface structs */ 1185 *addresses = uv__calloc(*count, sizeof(**addresses)); 1186 if (!(*addresses)) { 1187 r = UV_ENOMEM; 1188 goto cleanup; 1189 } 1190 address = *addresses; 1191 1192 ifr = ifc.ifc_req; 1193 while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { 1194 p = ifr; 1195 ifr = (struct ifreq*) 1196 ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); 1197 1198 if (!(p->ifr_addr.sa_family == AF_INET6 || 1199 p->ifr_addr.sa_family == AF_INET)) 1200 continue; 1201 1202 inet6 = (p->ifr_addr.sa_family == AF_INET6); 1203 1204 memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); 1205 if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) 1206 goto syserror; 1207 1208 if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) 1209 continue; 1210 1211 /* All conditions above must match count loop */ 1212 1213 address->name = uv__strdup(p->ifr_name); 1214 1215 if (inet6) 1216 address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr); 1217 else 1218 address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); 1219 1220 if (inet6) { 1221 memset(&if6, 0, sizeof(if6)); 1222 r = uv__strscpy(if6.ifr_name, p->ifr_name, sizeof(if6.ifr_name)); 1223 if (r == UV_E2BIG) 1224 goto cleanup; 1225 r = 0; 1226 memcpy(&if6.ifr_Addr, &p->ifr_addr, sizeof(if6.ifr_Addr)); 1227 if (ioctl(sock6fd, SIOCGIFNETMASK6, &if6) == -1) 1228 goto syserror; 1229 address->netmask.netmask6 = *((struct sockaddr_in6*) &if6.ifr_Addr); 1230 /* Explicitly set family as the ioctl call appears to return it as 0. */ 1231 address->netmask.netmask6.sin6_family = AF_INET6; 1232 } else { 1233 if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) 1234 goto syserror; 1235 address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr); 1236 /* Explicitly set family as the ioctl call appears to return it as 0. */ 1237 address->netmask.netmask4.sin_family = AF_INET; 1238 } 1239 1240 address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; 1241 1242 address++; 1243 } 1244 1245 /* Fill in physical addresses. */ 1246 ifr = ifc.ifc_req; 1247 while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { 1248 p = ifr; 1249 ifr = (struct ifreq*) 1250 ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); 1251 1252 if (p->ifr_addr.sa_family != AF_LINK) 1253 continue; 1254 1255 address = *addresses; 1256 for (i = 0; i < *count; i++) { 1257 if (strcmp(address->name, p->ifr_name) == 0) { 1258 sa_addr = (struct sockaddr_dl*) &p->ifr_addr; 1259 memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); 1260 } 1261 address++; 1262 } 1263 } 1264 1265#undef ADDR_SIZE 1266 goto cleanup; 1267 1268syserror: 1269 uv_free_interface_addresses(*addresses, *count); 1270 *addresses = NULL; 1271 *count = 0; 1272 r = UV_ENOSYS; 1273 1274cleanup: 1275 if (sockfd != -1) 1276 uv__close(sockfd); 1277 if (sock6fd != -1) 1278 uv__close(sock6fd); 1279 uv__free(ifc.ifc_req); 1280 return r; 1281} 1282 1283 1284void uv_free_interface_addresses(uv_interface_address_t* addresses, 1285 int count) { 1286 int i; 1287 1288 for (i = 0; i < count; ++i) { 1289 uv__free(addresses[i].name); 1290 } 1291 1292 uv__free(addresses); 1293} 1294 1295 1296void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { 1297 struct pollfd* events; 1298 uintptr_t i; 1299 uintptr_t nfds; 1300 struct poll_ctl pc; 1301 1302 assert(loop->watchers != NULL); 1303 assert(fd >= 0); 1304 1305 events = (struct pollfd*) loop->watchers[loop->nwatchers]; 1306 nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; 1307 1308 if (events != NULL) 1309 /* Invalidate events with same file descriptor */ 1310 for (i = 0; i < nfds; i++) 1311 if ((int) events[i].fd == fd) 1312 events[i].fd = -1; 1313 1314 /* Remove the file descriptor from the poll set */ 1315 pc.events = 0; 1316 pc.cmd = PS_DELETE; 1317 pc.fd = fd; 1318 if(loop->backend_fd >= 0) 1319 pollset_ctl(loop->backend_fd, &pc, 1); 1320} 1321