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