diff options
Diffstat (limited to '3rdparty/libuv/src/unix/aix.c')
-rw-r--r-- | 3rdparty/libuv/src/unix/aix.c | 1161 |
1 files changed, 0 insertions, 1161 deletions
diff --git a/3rdparty/libuv/src/unix/aix.c b/3rdparty/libuv/src/unix/aix.c deleted file mode 100644 index bcaa5ee50bc..00000000000 --- a/3rdparty/libuv/src/unix/aix.c +++ /dev/null @@ -1,1161 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <errno.h> - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <net/if.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <sys/time.h> -#include <unistd.h> -#include <fcntl.h> -#include <utmp.h> -#include <libgen.h> - -#include <sys/protosw.h> -#include <libperfstat.h> -#include <procinfo.h> -#include <sys/proc.h> -#include <sys/procfs.h> - -#include <sys/poll.h> - -#include <sys/pollset.h> -#include <ctype.h> -#ifdef HAVE_SYS_AHAFS_EVPRODS_H -#include <sys/ahafs_evProds.h> -#endif - -#include <sys/mntctl.h> -#include <sys/vmount.h> -#include <limits.h> -#include <strings.h> -#include <sys/vnode.h> - -#define RDWR_BUF_SIZE 4096 -#define EQ(a,b) (strcmp(a,b) == 0) - -int uv__platform_loop_init(uv_loop_t* loop) { - loop->fs_fd = -1; - - /* Passing maxfd of -1 should mean the limit is determined - * by the user's ulimit or the global limit as per the doc */ - loop->backend_fd = pollset_create(-1); - - if (loop->backend_fd == -1) - return -1; - - return 0; -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { - if (loop->fs_fd != -1) { - uv__close(loop->fs_fd); - loop->fs_fd = -1; - } - - if (loop->backend_fd != -1) { - pollset_destroy(loop->backend_fd); - loop->backend_fd = -1; - } -} - - -int uv__io_check_fd(uv_loop_t* loop, int fd) { - struct poll_ctl pc; - - pc.events = POLLIN; - pc.cmd = PS_MOD; /* Equivalent to PS_ADD if the fd is not in the pollset. */ - pc.fd = fd; - - if (pollset_ctl(loop->backend_fd, &pc, 1)) - return -errno; - - pc.cmd = PS_DELETE; - if (pollset_ctl(loop->backend_fd, &pc, 1)) - abort(); - - return 0; -} - - -void uv__io_poll(uv_loop_t* loop, int timeout) { - struct pollfd events[1024]; - struct pollfd pqry; - struct pollfd* pe; - struct poll_ctl pc; - QUEUE* q; - uv__io_t* w; - uint64_t base; - uint64_t diff; - int nevents; - int count; - int nfds; - int i; - int rc; - int add_failed; - - if (loop->nfds == 0) { - assert(QUEUE_EMPTY(&loop->watcher_queue)); - return; - } - - while (!QUEUE_EMPTY(&loop->watcher_queue)) { - q = QUEUE_HEAD(&loop->watcher_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - - w = QUEUE_DATA(q, uv__io_t, watcher_queue); - assert(w->pevents != 0); - assert(w->fd >= 0); - assert(w->fd < (int) loop->nwatchers); - - pc.events = w->pevents; - pc.fd = w->fd; - - add_failed = 0; - if (w->events == 0) { - pc.cmd = PS_ADD; - if (pollset_ctl(loop->backend_fd, &pc, 1)) { - if (errno != EINVAL) { - assert(0 && "Failed to add file descriptor (pc.fd) to pollset"); - abort(); - } - /* Check if the fd is already in the pollset */ - pqry.fd = pc.fd; - rc = pollset_query(loop->backend_fd, &pqry); - switch (rc) { - case -1: - assert(0 && "Failed to query pollset for file descriptor"); - abort(); - case 0: - assert(0 && "Pollset does not contain file descriptor"); - abort(); - } - /* If we got here then the pollset already contained the file descriptor even though - * we didn't think it should. This probably shouldn't happen, but we can continue. */ - add_failed = 1; - } - } - if (w->events != 0 || add_failed) { - /* Modify, potentially removing events -- need to delete then add. - * Could maybe mod if we knew for sure no events are removed, but - * content of w->events is handled above as not reliable (falls back) - * so may require a pollset_query() which would have to be pretty cheap - * compared to a PS_DELETE to be worth optimizing. Alternatively, could - * lazily remove events, squelching them in the mean time. */ - pc.cmd = PS_DELETE; - if (pollset_ctl(loop->backend_fd, &pc, 1)) { - assert(0 && "Failed to delete file descriptor (pc.fd) from pollset"); - abort(); - } - pc.cmd = PS_ADD; - if (pollset_ctl(loop->backend_fd, &pc, 1)) { - assert(0 && "Failed to add file descriptor (pc.fd) to pollset"); - abort(); - } - } - - w->events = w->pevents; - } - - assert(timeout >= -1); - base = loop->time; - count = 48; /* Benchmarks suggest this gives the best throughput. */ - - for (;;) { - nfds = pollset_poll(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout); - - /* Update loop->time unconditionally. It's tempting to skip the update when - * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the - * operating system didn't reschedule our process while in the syscall. - */ - SAVE_ERRNO(uv__update_time(loop)); - - if (nfds == 0) { - assert(timeout != -1); - return; - } - - if (nfds == -1) { - if (errno != EINTR) { - abort(); - } - - if (timeout == -1) - continue; - - if (timeout == 0) - return; - - /* Interrupted by a signal. Update timeout and poll again. */ - goto update_timeout; - } - - nevents = 0; - - assert(loop->watchers != NULL); - loop->watchers[loop->nwatchers] = (void*) events; - loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; - - for (i = 0; i < nfds; i++) { - pe = events + i; - pc.cmd = PS_DELETE; - pc.fd = pe->fd; - - /* Skip invalidated events, see uv__platform_invalidate_fd */ - if (pc.fd == -1) - continue; - - assert(pc.fd >= 0); - assert((unsigned) pc.fd < loop->nwatchers); - - w = loop->watchers[pc.fd]; - - if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. - * - * Ignore all errors because we may be racing with another thread - * when the file descriptor is closed. - */ - pollset_ctl(loop->backend_fd, &pc, 1); - continue; - } - - w->cb(loop, w, pe->revents); - nevents++; - } - - loop->watchers[loop->nwatchers] = NULL; - loop->watchers[loop->nwatchers + 1] = NULL; - - if (nevents != 0) { - if (nfds == ARRAY_SIZE(events) && --count != 0) { - /* Poll for more events but don't block this time. */ - timeout = 0; - continue; - } - return; - } - - if (timeout == 0) - return; - - if (timeout == -1) - continue; - -update_timeout: - assert(timeout > 0); - - diff = loop->time - base; - if (diff >= (uint64_t) timeout) - return; - - timeout -= diff; - } -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - uint64_t G = 1000000000; - timebasestruct_t t; - read_wall_time(&t, TIMEBASE_SZ); - time_base_to_time(&t, TIMEBASE_SZ); - return (uint64_t) t.tb_high * G + t.tb_low; -} - - -/* - * We could use a static buffer for the path manipulations that we need outside - * of the function, but this function could be called by multiple consumers and - * we don't want to potentially create a race condition in the use of snprintf. - * There is no direct way of getting the exe path in AIX - either through /procfs - * or through some libc APIs. The below approach is to parse the argv[0]'s pattern - * and use it in conjunction with PATH environment variable to craft one. - */ -int uv_exepath(char* buffer, size_t* size) { - int res; - char args[PATH_MAX]; - char abspath[PATH_MAX]; - size_t abspath_size; - struct procsinfo pi; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - pi.pi_pid = getpid(); - res = getargs(&pi, sizeof(pi), args, sizeof(args)); - if (res < 0) - return -EINVAL; - - /* - * Possibilities for args: - * i) an absolute path such as: /home/user/myprojects/nodejs/node - * ii) a relative path such as: ./node or ../myprojects/nodejs/node - * iii) a bare filename such as "node", after exporting PATH variable - * to its location. - */ - - /* Case i) and ii) absolute or relative paths */ - if (strchr(args, '/') != NULL) { - if (realpath(args, abspath) != abspath) - return -errno; - - abspath_size = strlen(abspath); - - *size -= 1; - if (*size > abspath_size) - *size = abspath_size; - - memcpy(buffer, abspath, *size); - buffer[*size] = '\0'; - - return 0; - } else { - /* Case iii). Search PATH environment variable */ - char trypath[PATH_MAX]; - char *clonedpath = NULL; - char *token = NULL; - char *path = getenv("PATH"); - - if (path == NULL) - return -EINVAL; - - clonedpath = uv__strdup(path); - if (clonedpath == NULL) - return -ENOMEM; - - token = strtok(clonedpath, ":"); - while (token != NULL) { - snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args); - if (realpath(trypath, abspath) == abspath) { - /* Check the match is executable */ - if (access(abspath, X_OK) == 0) { - abspath_size = strlen(abspath); - - *size -= 1; - if (*size > abspath_size) - *size = abspath_size; - - memcpy(buffer, abspath, *size); - buffer[*size] = '\0'; - - uv__free(clonedpath); - return 0; - } - } - token = strtok(NULL, ":"); - } - uv__free(clonedpath); - - /* Out of tokens (path entries), and no match found */ - return -EINVAL; - } -} - - -uint64_t uv_get_free_memory(void) { - perfstat_memory_total_t mem_total; - int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1); - if (result == -1) { - return 0; - } - return mem_total.real_free * 4096; -} - - -uint64_t uv_get_total_memory(void) { - perfstat_memory_total_t mem_total; - int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1); - if (result == -1) { - return 0; - } - return mem_total.real_total * 4096; -} - - -void uv_loadavg(double avg[3]) { - perfstat_cpu_total_t ps_total; - int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1); - if (result == -1) { - avg[0] = 0.; avg[1] = 0.; avg[2] = 0.; - return; - } - avg[0] = ps_total.loadavg[0] / (double)(1 << SBITS); - avg[1] = ps_total.loadavg[1] / (double)(1 << SBITS); - avg[2] = ps_total.loadavg[2] / (double)(1 << SBITS); -} - - -#ifdef HAVE_SYS_AHAFS_EVPRODS_H -static char *uv__rawname(char *cp) { - static char rawbuf[FILENAME_MAX+1]; - char *dp = rindex(cp, '/'); - - if (dp == 0) - return 0; - - *dp = 0; - strcpy(rawbuf, cp); - *dp = '/'; - strcat(rawbuf, "/r"); - strcat(rawbuf, dp+1); - return rawbuf; -} - - -/* - * Determine whether given pathname is a directory - * Returns 0 if the path is a directory, -1 if not - * - * Note: Opportunity here for more detailed error information but - * that requires changing callers of this function as well - */ -static int uv__path_is_a_directory(char* filename) { - struct stat statbuf; - - if (stat(filename, &statbuf) < 0) - return -1; /* failed: not a directory, assume it is a file */ - - if (statbuf.st_type == VDIR) - return 0; - - return -1; -} - - -/* - * Check whether AHAFS is mounted. - * Returns 0 if AHAFS is mounted, or an error code < 0 on failure - */ -static int uv__is_ahafs_mounted(void){ - int rv, i = 2; - struct vmount *p; - int size_multiplier = 10; - size_t siz = sizeof(struct vmount)*size_multiplier; - struct vmount *vmt; - const char *dev = "/aha"; - char *obj, *stub; - - p = uv__malloc(siz); - if (p == NULL) - return -errno; - - /* Retrieve all mounted filesystems */ - rv = mntctl(MCTL_QUERY, siz, (char*)p); - if (rv < 0) - return -errno; - if (rv == 0) { - /* buffer was not large enough, reallocate to correct size */ - siz = *(int*)p; - uv__free(p); - p = uv__malloc(siz); - if (p == NULL) - return -errno; - rv = mntctl(MCTL_QUERY, siz, (char*)p); - if (rv < 0) - return -errno; - } - - /* Look for dev in filesystems mount info */ - for(vmt = p, i = 0; i < rv; i++) { - obj = vmt2dataptr(vmt, VMT_OBJECT); /* device */ - stub = vmt2dataptr(vmt, VMT_STUB); /* mount point */ - - if (EQ(obj, dev) || EQ(uv__rawname(obj), dev) || EQ(stub, dev)) { - uv__free(p); /* Found a match */ - return 0; - } - vmt = (struct vmount *) ((char *) vmt + vmt->vmt_length); - } - - /* /aha is required for monitoring filesystem changes */ - return -1; -} - -/* - * Recursive call to mkdir() to create intermediate folders, if any - * Returns code from mkdir call - */ -static int uv__makedir_p(const char *dir) { - char tmp[256]; - char *p = NULL; - size_t len; - int err; - - snprintf(tmp, sizeof(tmp),"%s",dir); - len = strlen(tmp); - if (tmp[len - 1] == '/') - tmp[len - 1] = 0; - for (p = tmp + 1; *p; p++) { - if (*p == '/') { - *p = 0; - err = mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - if (err != 0 && errno != EEXIST) - return err; - *p = '/'; - } - } - return mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); -} - -/* - * Creates necessary subdirectories in the AIX Event Infrastructure - * file system for monitoring the object specified. - * Returns code from mkdir call - */ -static int uv__make_subdirs_p(const char *filename) { - char cmd[2048]; - char *p; - int rc = 0; - - /* Strip off the monitor file name */ - p = strrchr(filename, '/'); - - if (p == NULL) - return 0; - - if (uv__path_is_a_directory((char*)filename) == 0) { - sprintf(cmd, "/aha/fs/modDir.monFactory"); - } else { - sprintf(cmd, "/aha/fs/modFile.monFactory"); - } - - strncat(cmd, filename, (p - filename)); - rc = uv__makedir_p(cmd); - - if (rc == -1 && errno != EEXIST){ - return -errno; - } - - return rc; -} - - -/* - * Checks if /aha is mounted, then proceeds to set up the monitoring - * objects for the specified file. - * Returns 0 on success, or an error code < 0 on failure - */ -static int uv__setup_ahafs(const char* filename, int *fd) { - int rc = 0; - char mon_file_write_string[RDWR_BUF_SIZE]; - char mon_file[PATH_MAX]; - int file_is_directory = 0; /* -1 == NO, 0 == YES */ - - /* Create monitor file name for object */ - file_is_directory = uv__path_is_a_directory((char*)filename); - - if (file_is_directory == 0) - sprintf(mon_file, "/aha/fs/modDir.monFactory"); - else - sprintf(mon_file, "/aha/fs/modFile.monFactory"); - - if ((strlen(mon_file) + strlen(filename) + 5) > PATH_MAX) - return -ENAMETOOLONG; - - /* Make the necessary subdirectories for the monitor file */ - rc = uv__make_subdirs_p(filename); - if (rc == -1 && errno != EEXIST) - return rc; - - strcat(mon_file, filename); - strcat(mon_file, ".mon"); - - *fd = 0; errno = 0; - - /* Open the monitor file, creating it if necessary */ - *fd = open(mon_file, O_CREAT|O_RDWR); - if (*fd < 0) - return -errno; - - /* Write out the monitoring specifications. - * In this case, we are monitoring for a state change event type - * CHANGED=YES - * We will be waiting in select call, rather than a read: - * WAIT_TYPE=WAIT_IN_SELECT - * We only want minimal information for files: - * INFO_LVL=1 - * For directories, we want more information to track what file - * caused the change - * INFO_LVL=2 - */ - - if (file_is_directory == 0) - sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=2"); - else - sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=1"); - - rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1); - if (rc < 0) - return -errno; - - return 0; -} - -/* - * Skips a specified number of lines in the buffer passed in. - * Walks the buffer pointed to by p and attempts to skip n lines. - * Returns the total number of lines skipped - */ -static int uv__skip_lines(char **p, int n) { - int lines = 0; - - while(n > 0) { - *p = strchr(*p, '\n'); - if (!p) - return lines; - - (*p)++; - n--; - lines++; - } - return lines; -} - - -/* - * Parse the event occurrence data to figure out what event just occurred - * and take proper action. - * - * The buf is a pointer to the buffer containing the event occurrence data - * Returns 0 on success, -1 if unrecoverable error in parsing - * - */ -static int uv__parse_data(char *buf, int *events, uv_fs_event_t* handle) { - int evp_rc, i; - char *p; - char filename[PATH_MAX]; /* To be used when handling directories */ - - p = buf; - *events = 0; - - /* Clean the filename buffer*/ - for(i = 0; i < PATH_MAX; i++) { - filename[i] = 0; - } - i = 0; - - /* Check for BUF_WRAP */ - if (strncmp(buf, "BUF_WRAP", strlen("BUF_WRAP")) == 0) { - assert(0 && "Buffer wrap detected, Some event occurrences lost!"); - return 0; - } - - /* Since we are using the default buffer size (4K), and have specified - * INFO_LVL=1, we won't see any EVENT_OVERFLOW conditions. Applications - * should check for this keyword if they are using an INFO_LVL of 2 or - * higher, and have a buffer size of <= 4K - */ - - /* Skip to RC_FROM_EVPROD */ - if (uv__skip_lines(&p, 9) != 9) - return -1; - - if (sscanf(p, "RC_FROM_EVPROD=%d\nEND_EVENT_DATA", &evp_rc) == 1) { - if (uv__path_is_a_directory(handle->path) == 0) { /* Directory */ - if (evp_rc == AHAFS_MODDIR_UNMOUNT || evp_rc == AHAFS_MODDIR_REMOVE_SELF) { - /* The directory is no longer available for monitoring */ - *events = UV_RENAME; - handle->dir_filename = NULL; - } else { - /* A file was added/removed inside the directory */ - *events = UV_CHANGE; - - /* Get the EVPROD_INFO */ - if (uv__skip_lines(&p, 1) != 1) - return -1; - - /* Scan out the name of the file that triggered the event*/ - if (sscanf(p, "BEGIN_EVPROD_INFO\n%sEND_EVPROD_INFO", filename) == 1) { - handle->dir_filename = uv__strdup((const char*)&filename); - } else - return -1; - } - } else { /* Regular File */ - if (evp_rc == AHAFS_MODFILE_RENAME) - *events = UV_RENAME; - else - *events = UV_CHANGE; - } - } - else - return -1; - - return 0; -} - - -/* This is the internal callback */ -static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int fflags) { - char result_data[RDWR_BUF_SIZE]; - int bytes, rc = 0; - uv_fs_event_t* handle; - int events = 0; - char fname[PATH_MAX]; - char *p; - - handle = container_of(event_watch, uv_fs_event_t, event_watcher); - - /* At this point, we assume that polling has been done on the - * file descriptor, so we can just read the AHAFS event occurrence - * data and parse its results without having to block anything - */ - bytes = pread(event_watch->fd, result_data, RDWR_BUF_SIZE, 0); - - assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file"); - - /* Parse the data */ - if(bytes > 0) - rc = uv__parse_data(result_data, &events, handle); - - /* Unrecoverable error */ - if (rc == -1) - return; - - /* For directory changes, the name of the files that triggered the change - * are never absolute pathnames - */ - if (uv__path_is_a_directory(handle->path) == 0) { - p = handle->dir_filename; - } else { - p = strrchr(handle->path, '/'); - if (p == NULL) - p = handle->path; - else - p++; - } - strncpy(fname, p, sizeof(fname) - 1); - /* Just in case */ - fname[sizeof(fname) - 1] = '\0'; - - handle->cb(handle, fname, events, 0); -} -#endif - - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { -#ifdef HAVE_SYS_AHAFS_EVPRODS_H - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); - return 0; -#else - return -ENOSYS; -#endif -} - - -int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* filename, - unsigned int flags) { -#ifdef HAVE_SYS_AHAFS_EVPRODS_H - int fd, rc, i = 0, res = 0; - char cwd[PATH_MAX]; - char absolute_path[PATH_MAX]; - char fname[PATH_MAX]; - char *p; - - /* Clean all the buffers*/ - for(i = 0; i < PATH_MAX; i++) { - cwd[i] = 0; - absolute_path[i] = 0; - fname[i] = 0; - } - i = 0; - - /* Figure out whether filename is absolute or not */ - if (filename[0] == '/') { - /* We have absolute pathname, create the relative pathname*/ - sprintf(absolute_path, filename); - p = strrchr(filename, '/'); - p++; - } else { - if (filename[0] == '.' && filename[1] == '/') { - /* We have a relative pathname, compose the absolute pathname */ - sprintf(fname, filename); - snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid()); - res = readlink(cwd, absolute_path, sizeof(absolute_path) - 1); - if (res < 0) - return res; - p = strrchr(absolute_path, '/'); - p++; - p++; - } else { - /* We have a relative pathname, compose the absolute pathname */ - sprintf(fname, filename); - snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid()); - res = readlink(cwd, absolute_path, sizeof(absolute_path) - 1); - if (res < 0) - return res; - p = strrchr(absolute_path, '/'); - p++; - } - /* Copy to filename buffer */ - while(filename[i] != NULL) { - *p = filename[i]; - i++; - p++; - } - } - - if (uv__is_ahafs_mounted() < 0) /* /aha checks failed */ - return UV_ENOSYS; - - /* Setup ahafs */ - rc = uv__setup_ahafs((const char *)absolute_path, &fd); - if (rc != 0) - return rc; - - /* Setup/Initialize all the libuv routines */ - uv__handle_start(handle); - uv__io_init(&handle->event_watcher, uv__ahafs_event, fd); - handle->path = uv__strdup(filename); - handle->cb = cb; - - uv__io_start(handle->loop, &handle->event_watcher, UV__POLLIN); - - return 0; -#else - return -ENOSYS; -#endif -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { -#ifdef HAVE_SYS_AHAFS_EVPRODS_H - if (!uv__is_active(handle)) - return 0; - - uv__io_close(handle->loop, &handle->event_watcher); - uv__handle_stop(handle); - - if (uv__path_is_a_directory(handle->path) == 0) { - uv__free(handle->dir_filename); - handle->dir_filename = NULL; - } - - uv__free(handle->path); - handle->path = NULL; - uv__close(handle->event_watcher.fd); - handle->event_watcher.fd = -1; - - return 0; -#else - return -ENOSYS; -#endif -} - - -void uv__fs_event_close(uv_fs_event_t* handle) { -#ifdef HAVE_SYS_AHAFS_EVPRODS_H - uv_fs_event_stop(handle); -#else - UNREACHABLE(); -#endif -} - - -char** uv_setup_args(int argc, char** argv) { - return argv; -} - - -int uv_set_process_title(const char* title) { - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - if (size > 0) { - buffer[0] = '\0'; - } - return 0; -} - - -int uv_resident_set_memory(size_t* rss) { - char pp[64]; - psinfo_t psinfo; - int err; - int fd; - - snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid()); - - fd = open(pp, O_RDONLY); - if (fd == -1) - return -errno; - - /* FIXME(bnoordhuis) Handle EINTR. */ - err = -EINVAL; - if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) { - *rss = (size_t)psinfo.pr_rssize * 1024; - err = 0; - } - uv__close(fd); - - return err; -} - - -int uv_uptime(double* uptime) { - struct utmp *utmp_buf; - size_t entries = 0; - time_t boot_time; - - utmpname(UTMP_FILE); - - setutent(); - - while ((utmp_buf = getutent()) != NULL) { - if (utmp_buf->ut_user[0] && utmp_buf->ut_type == USER_PROCESS) - ++entries; - if (utmp_buf->ut_type == BOOT_TIME) - boot_time = utmp_buf->ut_time; - } - - endutent(); - - if (boot_time == 0) - return -ENOSYS; - - *uptime = time(NULL) - boot_time; - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - uv_cpu_info_t* cpu_info; - perfstat_cpu_total_t ps_total; - perfstat_cpu_t* ps_cpus; - perfstat_id_t cpu_id; - int result, ncpus, idx = 0; - - result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1); - if (result == -1) { - return -ENOSYS; - } - - ncpus = result = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0); - if (result == -1) { - return -ENOSYS; - } - - ps_cpus = (perfstat_cpu_t*) uv__malloc(ncpus * sizeof(perfstat_cpu_t)); - if (!ps_cpus) { - return -ENOMEM; - } - - strcpy(cpu_id.name, FIRST_CPU); - result = perfstat_cpu(&cpu_id, ps_cpus, sizeof(perfstat_cpu_t), ncpus); - if (result == -1) { - uv__free(ps_cpus); - return -ENOSYS; - } - - *cpu_infos = (uv_cpu_info_t*) uv__malloc(ncpus * sizeof(uv_cpu_info_t)); - if (!*cpu_infos) { - uv__free(ps_cpus); - return -ENOMEM; - } - - *count = ncpus; - - cpu_info = *cpu_infos; - while (idx < ncpus) { - cpu_info->speed = (int)(ps_total.processorHZ / 1000000); - cpu_info->model = uv__strdup(ps_total.description); - cpu_info->cpu_times.user = ps_cpus[idx].user; - cpu_info->cpu_times.sys = ps_cpus[idx].sys; - cpu_info->cpu_times.idle = ps_cpus[idx].idle; - cpu_info->cpu_times.irq = ps_cpus[idx].wait; - cpu_info->cpu_times.nice = 0; - cpu_info++; - idx++; - } - - uv__free(ps_cpus); - return 0; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; ++i) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, - int* count) { - uv_interface_address_t* address; - int sockfd, size = 1; - struct ifconf ifc; - struct ifreq *ifr, *p, flg; - - *count = 0; - - if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) { - return -errno; - } - - if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) { - SAVE_ERRNO(uv__close(sockfd)); - return -errno; - } - - ifc.ifc_req = (struct ifreq*)uv__malloc(size); - ifc.ifc_len = size; - if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { - SAVE_ERRNO(uv__close(sockfd)); - return -errno; - } - -#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) - - /* Count all up and running ipv4/ipv6 addresses */ - ifr = ifc.ifc_req; - while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { - p = ifr; - ifr = (struct ifreq*) - ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); - - if (!(p->ifr_addr.sa_family == AF_INET6 || - p->ifr_addr.sa_family == AF_INET)) - continue; - - memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - SAVE_ERRNO(uv__close(sockfd)); - return -errno; - } - - if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) - continue; - - (*count)++; - } - - /* Alloc the return interface structs */ - *addresses = (uv_interface_address_t*) - uv__malloc(*count * sizeof(uv_interface_address_t)); - if (!(*addresses)) { - uv__close(sockfd); - return -ENOMEM; - } - address = *addresses; - - ifr = ifc.ifc_req; - while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { - p = ifr; - ifr = (struct ifreq*) - ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); - - if (!(p->ifr_addr.sa_family == AF_INET6 || - p->ifr_addr.sa_family == AF_INET)) - continue; - - memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - uv__close(sockfd); - return -ENOSYS; - } - - if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) - continue; - - /* All conditions above must match count loop */ - - address->name = uv__strdup(p->ifr_name); - - if (p->ifr_addr.sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); - } - - /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */ - - address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; - - address++; - } - -#undef ADDR_SIZE - - uv__close(sockfd); - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; ++i) { - uv__free(addresses[i].name); - } - - uv__free(addresses); -} - -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { - struct pollfd* events; - uintptr_t i; - uintptr_t nfds; - struct poll_ctl pc; - - assert(loop->watchers != NULL); - - events = (struct pollfd*) loop->watchers[loop->nwatchers]; - nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; - - if (events != NULL) - /* Invalidate events with same file descriptor */ - for (i = 0; i < nfds; i++) - if ((int) events[i].fd == fd) - events[i].fd = -1; - - /* Remove the file descriptor from the poll set */ - pc.events = 0; - pc.cmd = PS_DELETE; - pc.fd = fd; - if(loop->backend_fd >= 0) - pollset_ctl(loop->backend_fd, &pc, 1); -} |