Blame src/unix/aix.c

Packit Service 7c31a4
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit Service 7c31a4
 * of this software and associated documentation files (the "Software"), to
Packit Service 7c31a4
 * deal in the Software without restriction, including without limitation the
Packit Service 7c31a4
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
Packit Service 7c31a4
 * sell copies of the Software, and to permit persons to whom the Software is
Packit Service 7c31a4
 * furnished to do so, subject to the following conditions:
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * The above copyright notice and this permission notice shall be included in
Packit Service 7c31a4
 * all copies or substantial portions of the Software.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit Service 7c31a4
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit Service 7c31a4
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Packit Service 7c31a4
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit Service 7c31a4
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Packit Service 7c31a4
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
Packit Service 7c31a4
 * IN THE SOFTWARE.
Packit Service 7c31a4
 */
Packit Service 7c31a4
Packit Service 7c31a4
#include "uv.h"
Packit Service 7c31a4
#include "internal.h"
Packit Service 7c31a4
Packit Service 7c31a4
#include <stdio.h>
Packit Service 7c31a4
#include <stdint.h>
Packit Service 7c31a4
#include <stdlib.h>
Packit Service 7c31a4
#include <string.h>
Packit Service 7c31a4
#include <assert.h>
Packit Service 7c31a4
#include <errno.h>
Packit Service 7c31a4
Packit Service 7c31a4
#include <sys/types.h>
Packit Service 7c31a4
#include <sys/socket.h>
Packit Service 7c31a4
#include <sys/ioctl.h>
Packit Service 7c31a4
#include <net/if.h>
Packit Service 7c31a4
#include <netinet/in.h>
Packit Service 7c31a4
#include <arpa/inet.h>
Packit Service 7c31a4
Packit Service 7c31a4
#include <sys/time.h>
Packit Service 7c31a4
#include <unistd.h>
Packit Service 7c31a4
#include <fcntl.h>
Packit Service 7c31a4
#include <utmp.h>
Packit Service 7c31a4
#include <libgen.h>
Packit Service 7c31a4
Packit Service 7c31a4
#include <sys/protosw.h>
Packit Service 7c31a4
#include <libperfstat.h>
Packit Service 7c31a4
#include <procinfo.h>
Packit Service 7c31a4
#include <sys/proc.h>
Packit Service 7c31a4
#include <sys/procfs.h>
Packit Service 7c31a4
Packit Service 7c31a4
#include <sys/poll.h>
Packit Service 7c31a4
Packit Service 7c31a4
#include <sys/pollset.h>
Packit Service 7c31a4
#include <ctype.h>
Packit Service 7c31a4
#ifdef HAVE_SYS_AHAFS_EVPRODS_H
Packit Service 7c31a4
#include <sys/ahafs_evProds.h>
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
#include <sys/mntctl.h>
Packit Service 7c31a4
#include <sys/vmount.h>
Packit Service 7c31a4
#include <limits.h>
Packit Service 7c31a4
#include <strings.h>
Packit Service 7c31a4
#include <sys/vnode.h>
Packit Service 7c31a4
Packit Service 7c31a4
#define RDWR_BUF_SIZE   4096
Packit Service 7c31a4
#define EQ(a,b)         (strcmp(a,b) == 0)
Packit Service 7c31a4
Packit Service 7c31a4
static uv_mutex_t process_title_mutex;
Packit Service 7c31a4
static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
Packit Service 7c31a4
static void* args_mem = NULL;
Packit Service 7c31a4
static char** process_argv = NULL;
Packit Service 7c31a4
static int process_argc = 0;
Packit Service 7c31a4
static char* process_title_ptr = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
static void init_process_title_mutex_once(void) {
Packit Service 7c31a4
  uv_mutex_init(&process_title_mutex);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv__platform_loop_init(uv_loop_t* loop) {
Packit Service 7c31a4
  loop->fs_fd = -1;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Passing maxfd of -1 should mean the limit is determined
Packit Service 7c31a4
   * by the user's ulimit or the global limit as per the doc */
Packit Service 7c31a4
  loop->backend_fd = pollset_create(-1);
Packit Service 7c31a4
Packit Service 7c31a4
  if (loop->backend_fd == -1)
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void uv__platform_loop_delete(uv_loop_t* loop) {
Packit Service 7c31a4
  if (loop->fs_fd != -1) {
Packit Service 7c31a4
    uv__close(loop->fs_fd);
Packit Service 7c31a4
    loop->fs_fd = -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (loop->backend_fd != -1) {
Packit Service 7c31a4
    pollset_destroy(loop->backend_fd);
Packit Service 7c31a4
    loop->backend_fd = -1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv__io_fork(uv_loop_t* loop) {
Packit Service 7c31a4
  uv__platform_loop_delete(loop);
Packit Service 7c31a4
Packit Service 7c31a4
  return uv__platform_loop_init(loop);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv__io_check_fd(uv_loop_t* loop, int fd) {
Packit Service 7c31a4
  struct poll_ctl pc;
Packit Service 7c31a4
Packit Service 7c31a4
  pc.events = POLLIN;
Packit Service 7c31a4
  pc.cmd = PS_MOD;  /* Equivalent to PS_ADD if the fd is not in the pollset. */
Packit Service 7c31a4
  pc.fd = fd;
Packit Service 7c31a4
Packit Service 7c31a4
  if (pollset_ctl(loop->backend_fd, &pc, 1))
Packit Service 7c31a4
    return UV__ERR(errno);
Packit Service 7c31a4
Packit Service 7c31a4
  pc.cmd = PS_DELETE;
Packit Service 7c31a4
  if (pollset_ctl(loop->backend_fd, &pc, 1))
Packit Service 7c31a4
    abort();
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void uv__io_poll(uv_loop_t* loop, int timeout) {
Packit Service 7c31a4
  struct pollfd events[1024];
Packit Service 7c31a4
  struct pollfd pqry;
Packit Service 7c31a4
  struct pollfd* pe;
Packit Service 7c31a4
  struct poll_ctl pc;
Packit Service 7c31a4
  QUEUE* q;
Packit Service 7c31a4
  uv__io_t* w;
Packit Service 7c31a4
  uint64_t base;
Packit Service 7c31a4
  uint64_t diff;
Packit Service 7c31a4
  int have_signals;
Packit Service 7c31a4
  int nevents;
Packit Service 7c31a4
  int count;
Packit Service 7c31a4
  int nfds;
Packit Service 7c31a4
  int i;
Packit Service 7c31a4
  int rc;
Packit Service 7c31a4
  int add_failed;
Packit Service 7c31a4
Packit Service 7c31a4
  if (loop->nfds == 0) {
Packit Service 7c31a4
    assert(QUEUE_EMPTY(&loop->watcher_queue));
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  while (!QUEUE_EMPTY(&loop->watcher_queue)) {
Packit Service 7c31a4
    q = QUEUE_HEAD(&loop->watcher_queue);
Packit Service 7c31a4
    QUEUE_REMOVE(q);
Packit Service 7c31a4
    QUEUE_INIT(q);
Packit Service 7c31a4
Packit Service 7c31a4
    w = QUEUE_DATA(q, uv__io_t, watcher_queue);
Packit Service 7c31a4
    assert(w->pevents != 0);
Packit Service 7c31a4
    assert(w->fd >= 0);
Packit Service 7c31a4
    assert(w->fd < (int) loop->nwatchers);
Packit Service 7c31a4
Packit Service 7c31a4
    pc.events = w->pevents;
Packit Service 7c31a4
    pc.fd = w->fd;
Packit Service 7c31a4
Packit Service 7c31a4
    add_failed = 0;
Packit Service 7c31a4
    if (w->events == 0) {
Packit Service 7c31a4
      pc.cmd = PS_ADD;
Packit Service 7c31a4
      if (pollset_ctl(loop->backend_fd, &pc, 1)) {
Packit Service 7c31a4
        if (errno != EINVAL) {
Packit Service 7c31a4
          assert(0 && "Failed to add file descriptor (pc.fd) to pollset");
Packit Service 7c31a4
          abort();
Packit Service 7c31a4
        }
Packit Service 7c31a4
        /* Check if the fd is already in the pollset */
Packit Service 7c31a4
        pqry.fd = pc.fd;
Packit Service 7c31a4
        rc = pollset_query(loop->backend_fd, &pqry);
Packit Service 7c31a4
        switch (rc) {
Packit Service 7c31a4
        case -1:
Packit Service 7c31a4
          assert(0 && "Failed to query pollset for file descriptor");
Packit Service 7c31a4
          abort();
Packit Service 7c31a4
        case 0:
Packit Service 7c31a4
          assert(0 && "Pollset does not contain file descriptor");
Packit Service 7c31a4
          abort();
Packit Service 7c31a4
        }
Packit Service 7c31a4
        /* If we got here then the pollset already contained the file descriptor even though
Packit Service 7c31a4
         * we didn't think it should. This probably shouldn't happen, but we can continue. */
Packit Service 7c31a4
        add_failed = 1;
Packit Service 7c31a4
      }
Packit Service 7c31a4
    }
Packit Service 7c31a4
    if (w->events != 0 || add_failed) {
Packit Service 7c31a4
      /* Modify, potentially removing events -- need to delete then add.
Packit Service 7c31a4
       * Could maybe mod if we knew for sure no events are removed, but
Packit Service 7c31a4
       * content of w->events is handled above as not reliable (falls back)
Packit Service 7c31a4
       * so may require a pollset_query() which would have to be pretty cheap
Packit Service 7c31a4
       * compared to a PS_DELETE to be worth optimizing. Alternatively, could
Packit Service 7c31a4
       * lazily remove events, squelching them in the mean time. */
Packit Service 7c31a4
      pc.cmd = PS_DELETE;
Packit Service 7c31a4
      if (pollset_ctl(loop->backend_fd, &pc, 1)) {
Packit Service 7c31a4
        assert(0 && "Failed to delete file descriptor (pc.fd) from pollset");
Packit Service 7c31a4
        abort();
Packit Service 7c31a4
      }
Packit Service 7c31a4
      pc.cmd = PS_ADD;
Packit Service 7c31a4
      if (pollset_ctl(loop->backend_fd, &pc, 1)) {
Packit Service 7c31a4
        assert(0 && "Failed to add file descriptor (pc.fd) to pollset");
Packit Service 7c31a4
        abort();
Packit Service 7c31a4
      }
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    w->events = w->pevents;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  assert(timeout >= -1);
Packit Service 7c31a4
  base = loop->time;
Packit Service 7c31a4
  count = 48; /* Benchmarks suggest this gives the best throughput. */
Packit Service 7c31a4
Packit Service 7c31a4
  for (;;) {
Packit Service 7c31a4
    nfds = pollset_poll(loop->backend_fd,
Packit Service 7c31a4
                        events,
Packit Service 7c31a4
                        ARRAY_SIZE(events),
Packit Service 7c31a4
                        timeout);
Packit Service 7c31a4
Packit Service 7c31a4
    /* Update loop->time unconditionally. It's tempting to skip the update when
Packit Service 7c31a4
     * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
Packit Service 7c31a4
     * operating system didn't reschedule our process while in the syscall.
Packit Service 7c31a4
     */
Packit Service 7c31a4
    SAVE_ERRNO(uv__update_time(loop));
Packit Service 7c31a4
Packit Service 7c31a4
    if (nfds == 0) {
Packit Service 7c31a4
      assert(timeout != -1);
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    if (nfds == -1) {
Packit Service 7c31a4
      if (errno != EINTR) {
Packit Service 7c31a4
        abort();
Packit Service 7c31a4
      }
Packit Service 7c31a4
Packit Service 7c31a4
      if (timeout == -1)
Packit Service 7c31a4
        continue;
Packit Service 7c31a4
Packit Service 7c31a4
      if (timeout == 0)
Packit Service 7c31a4
        return;
Packit Service 7c31a4
Packit Service 7c31a4
      /* Interrupted by a signal. Update timeout and poll again. */
Packit Service 7c31a4
      goto update_timeout;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    have_signals = 0;
Packit Service 7c31a4
    nevents = 0;
Packit Service 7c31a4
Packit Service 7c31a4
    assert(loop->watchers != NULL);
Packit Service 7c31a4
    loop->watchers[loop->nwatchers] = (void*) events;
Packit Service 7c31a4
    loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
Packit Service 7c31a4
Packit Service 7c31a4
    for (i = 0; i < nfds; i++) {
Packit Service 7c31a4
      pe = events + i;
Packit Service 7c31a4
      pc.cmd = PS_DELETE;
Packit Service 7c31a4
      pc.fd = pe->fd;
Packit Service 7c31a4
Packit Service 7c31a4
      /* Skip invalidated events, see uv__platform_invalidate_fd */
Packit Service 7c31a4
      if (pc.fd == -1)
Packit Service 7c31a4
        continue;
Packit Service 7c31a4
Packit Service 7c31a4
      assert(pc.fd >= 0);
Packit Service 7c31a4
      assert((unsigned) pc.fd < loop->nwatchers);
Packit Service 7c31a4
Packit Service 7c31a4
      w = loop->watchers[pc.fd];
Packit Service 7c31a4
Packit Service 7c31a4
      if (w == NULL) {
Packit Service 7c31a4
        /* File descriptor that we've stopped watching, disarm it.
Packit Service 7c31a4
         *
Packit Service 7c31a4
         * Ignore all errors because we may be racing with another thread
Packit Service 7c31a4
         * when the file descriptor is closed.
Packit Service 7c31a4
         */
Packit Service 7c31a4
        pollset_ctl(loop->backend_fd, &pc, 1);
Packit Service 7c31a4
        continue;
Packit Service 7c31a4
      }
Packit Service 7c31a4
Packit Service 7c31a4
      /* Run signal watchers last.  This also affects child process watchers
Packit Service 7c31a4
       * because those are implemented in terms of signal watchers.
Packit Service 7c31a4
       */
Packit Service 7c31a4
      if (w == &loop->signal_io_watcher)
Packit Service 7c31a4
        have_signals = 1;
Packit Service 7c31a4
      else
Packit Service 7c31a4
        w->cb(loop, w, pe->revents);
Packit Service 7c31a4
Packit Service 7c31a4
      nevents++;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    if (have_signals != 0)
Packit Service 7c31a4
      loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
Packit Service 7c31a4
Packit Service 7c31a4
    loop->watchers[loop->nwatchers] = NULL;
Packit Service 7c31a4
    loop->watchers[loop->nwatchers + 1] = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
    if (have_signals != 0)
Packit Service 7c31a4
      return;  /* Event loop should cycle now so don't poll again. */
Packit Service 7c31a4
Packit Service 7c31a4
    if (nevents != 0) {
Packit Service 7c31a4
      if (nfds == ARRAY_SIZE(events) && --count != 0) {
Packit Service 7c31a4
        /* Poll for more events but don't block this time. */
Packit Service 7c31a4
        timeout = 0;
Packit Service 7c31a4
        continue;
Packit Service 7c31a4
      }
Packit Service 7c31a4
      return;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    if (timeout == 0)
Packit Service 7c31a4
      return;
Packit Service 7c31a4
Packit Service 7c31a4
    if (timeout == -1)
Packit Service 7c31a4
      continue;
Packit Service 7c31a4
Packit Service 7c31a4
update_timeout:
Packit Service 7c31a4
    assert(timeout > 0);
Packit Service 7c31a4
Packit Service 7c31a4
    diff = loop->time - base;
Packit Service 7c31a4
    if (diff >= (uint64_t) timeout)
Packit Service 7c31a4
      return;
Packit Service 7c31a4
Packit Service 7c31a4
    timeout -= diff;
Packit Service 7c31a4
  }
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
uint64_t uv_get_free_memory(void) {
Packit Service 7c31a4
  perfstat_memory_total_t mem_total;
Packit Service 7c31a4
  int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1);
Packit Service 7c31a4
  if (result == -1) {
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  return mem_total.real_free * 4096;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
uint64_t uv_get_total_memory(void) {
Packit Service 7c31a4
  perfstat_memory_total_t mem_total;
Packit Service 7c31a4
  int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1);
Packit Service 7c31a4
  if (result == -1) {
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  return mem_total.real_total * 4096;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
uint64_t uv_get_constrained_memory(void) {
Packit Service 7c31a4
  return 0;  /* Memory constraints are unknown. */
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void uv_loadavg(double avg[3]) {
Packit Service 7c31a4
  perfstat_cpu_total_t ps_total;
Packit Service 7c31a4
  int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1);
Packit Service 7c31a4
  if (result == -1) {
Packit Service 7c31a4
    avg[0] = 0.; avg[1] = 0.; avg[2] = 0.;
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  avg[0] = ps_total.loadavg[0] / (double)(1 << SBITS);
Packit Service 7c31a4
  avg[1] = ps_total.loadavg[1] / (double)(1 << SBITS);
Packit Service 7c31a4
  avg[2] = ps_total.loadavg[2] / (double)(1 << SBITS);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
#ifdef HAVE_SYS_AHAFS_EVPRODS_H
Packit Service 7c31a4
static char* uv__rawname(const char* cp, char (*dst)[FILENAME_MAX+1]) {
Packit Service 7c31a4
  char* dp;
Packit Service 7c31a4
Packit Service 7c31a4
  dp = rindex(cp, '/');
Packit Service 7c31a4
  if (dp == 0)
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
Packit Service 7c31a4
  snprintf(*dst, sizeof(*dst), "%.*s/r%s", (int) (dp - cp), cp, dp + 1);
Packit Service 7c31a4
  return *dst;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
/*
Packit Service 7c31a4
 * Determine whether given pathname is a directory
Packit Service 7c31a4
 * Returns 0 if the path is a directory, -1 if not
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * Note: Opportunity here for more detailed error information but
Packit Service 7c31a4
 *       that requires changing callers of this function as well
Packit Service 7c31a4
 */
Packit Service 7c31a4
static int uv__path_is_a_directory(char* filename) {
Packit Service 7c31a4
  struct stat statbuf;
Packit Service 7c31a4
Packit Service 7c31a4
  if (stat(filename, &statbuf) < 0)
Packit Service 7c31a4
    return -1;  /* failed: not a directory, assume it is a file */
Packit Service 7c31a4
Packit Service 7c31a4
  if (statbuf.st_type == VDIR)
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
Packit Service 7c31a4
  return -1;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
/*
Packit Service 7c31a4
 * Check whether AHAFS is mounted.
Packit Service 7c31a4
 * Returns 0 if AHAFS is mounted, or an error code < 0 on failure
Packit Service 7c31a4
 */
Packit Service 7c31a4
static int uv__is_ahafs_mounted(void){
Packit Service 7c31a4
  char rawbuf[FILENAME_MAX+1];
Packit Service 7c31a4
  int rv, i = 2;
Packit Service 7c31a4
  struct vmount *p;
Packit Service 7c31a4
  int size_multiplier = 10;
Packit Service 7c31a4
  size_t siz = sizeof(struct vmount)*size_multiplier;
Packit Service 7c31a4
  struct vmount *vmt;
Packit Service 7c31a4
  const char *dev = "/aha";
Packit Service 7c31a4
  char *obj, *stub;
Packit Service 7c31a4
Packit Service 7c31a4
  p = uv__malloc(siz);
Packit Service 7c31a4
  if (p == NULL)
Packit Service 7c31a4
    return UV__ERR(errno);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Retrieve all mounted filesystems */
Packit Service 7c31a4
  rv = mntctl(MCTL_QUERY, siz, (char*)p);
Packit Service 7c31a4
  if (rv < 0)
Packit Service 7c31a4
    return UV__ERR(errno);
Packit Service 7c31a4
  if (rv == 0) {
Packit Service 7c31a4
    /* buffer was not large enough, reallocate to correct size */
Packit Service 7c31a4
    siz = *(int*)p;
Packit Service 7c31a4
    uv__free(p);
Packit Service 7c31a4
    p = uv__malloc(siz);
Packit Service 7c31a4
    if (p == NULL)
Packit Service 7c31a4
      return UV__ERR(errno);
Packit Service 7c31a4
    rv = mntctl(MCTL_QUERY, siz, (char*)p);
Packit Service 7c31a4
    if (rv < 0)
Packit Service 7c31a4
      return UV__ERR(errno);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Look for dev in filesystems mount info */
Packit Service 7c31a4
  for(vmt = p, i = 0; i < rv; i++) {
Packit Service 7c31a4
    obj = vmt2dataptr(vmt, VMT_OBJECT);     /* device */
Packit Service 7c31a4
    stub = vmt2dataptr(vmt, VMT_STUB);      /* mount point */
Packit Service 7c31a4
Packit Service 7c31a4
    if (EQ(obj, dev) || EQ(uv__rawname(obj, &rawbuf), dev) || EQ(stub, dev)) {
Packit Service 7c31a4
      uv__free(p);  /* Found a match */
Packit Service 7c31a4
      return 0;
Packit Service 7c31a4
    }
Packit Service 7c31a4
    vmt = (struct vmount *) ((char *) vmt + vmt->vmt_length);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* /aha is required for monitoring filesystem changes */
Packit Service 7c31a4
  return -1;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
/*
Packit Service 7c31a4
 * Recursive call to mkdir() to create intermediate folders, if any
Packit Service 7c31a4
 * Returns code from mkdir call
Packit Service 7c31a4
 */
Packit Service 7c31a4
static int uv__makedir_p(const char *dir) {
Packit Service 7c31a4
  char tmp[256];
Packit Service 7c31a4
  char *p = NULL;
Packit Service 7c31a4
  size_t len;
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
Packit Service 7c31a4
  /* TODO(bnoordhuis) Check uv__strscpy() return value. */
Packit Service 7c31a4
  uv__strscpy(tmp, dir, sizeof(tmp));
Packit Service 7c31a4
  len = strlen(tmp);
Packit Service 7c31a4
  if (tmp[len - 1] == '/')
Packit Service 7c31a4
    tmp[len - 1] = 0;
Packit Service 7c31a4
  for (p = tmp + 1; *p; p++) {
Packit Service 7c31a4
    if (*p == '/') {
Packit Service 7c31a4
      *p = 0;
Packit Service 7c31a4
      err = mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
Packit Service 7c31a4
      if (err != 0 && errno != EEXIST)
Packit Service 7c31a4
        return err;
Packit Service 7c31a4
      *p = '/';
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
  return mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
/*
Packit Service 7c31a4
 * Creates necessary subdirectories in the AIX Event Infrastructure
Packit Service 7c31a4
 * file system for monitoring the object specified.
Packit Service 7c31a4
 * Returns code from mkdir call
Packit Service 7c31a4
 */
Packit Service 7c31a4
static int uv__make_subdirs_p(const char *filename) {
Packit Service 7c31a4
  char cmd[2048];
Packit Service 7c31a4
  char *p;
Packit Service 7c31a4
  int rc = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Strip off the monitor file name */
Packit Service 7c31a4
  p = strrchr(filename, '/');
Packit Service 7c31a4
Packit Service 7c31a4
  if (p == NULL)
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
Packit Service 7c31a4
  if (uv__path_is_a_directory((char*)filename) == 0) {
Packit Service 7c31a4
    sprintf(cmd, "/aha/fs/modDir.monFactory");
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    sprintf(cmd, "/aha/fs/modFile.monFactory");
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  strncat(cmd, filename, (p - filename));
Packit Service 7c31a4
  rc = uv__makedir_p(cmd);
Packit Service 7c31a4
Packit Service 7c31a4
  if (rc == -1 && errno != EEXIST){
Packit Service 7c31a4
    return UV__ERR(errno);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  return rc;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
/*
Packit Service 7c31a4
 * Checks if /aha is mounted, then proceeds to set up the monitoring
Packit Service 7c31a4
 * objects for the specified file.
Packit Service 7c31a4
 * Returns 0 on success, or an error code < 0 on failure
Packit Service 7c31a4
 */
Packit Service 7c31a4
static int uv__setup_ahafs(const char* filename, int *fd) {
Packit Service 7c31a4
  int rc = 0;
Packit Service 7c31a4
  char mon_file_write_string[RDWR_BUF_SIZE];
Packit Service 7c31a4
  char mon_file[PATH_MAX];
Packit Service 7c31a4
  int file_is_directory = 0; /* -1 == NO, 0 == YES  */
Packit Service 7c31a4
Packit Service 7c31a4
  /* Create monitor file name for object */
Packit Service 7c31a4
  file_is_directory = uv__path_is_a_directory((char*)filename);
Packit Service 7c31a4
Packit Service 7c31a4
  if (file_is_directory == 0)
Packit Service 7c31a4
    sprintf(mon_file, "/aha/fs/modDir.monFactory");
Packit Service 7c31a4
  else
Packit Service 7c31a4
    sprintf(mon_file, "/aha/fs/modFile.monFactory");
Packit Service 7c31a4
Packit Service 7c31a4
  if ((strlen(mon_file) + strlen(filename) + 5) > PATH_MAX)
Packit Service 7c31a4
    return UV_ENAMETOOLONG;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Make the necessary subdirectories for the monitor file */
Packit Service 7c31a4
  rc = uv__make_subdirs_p(filename);
Packit Service 7c31a4
  if (rc == -1 && errno != EEXIST)
Packit Service 7c31a4
    return rc;
Packit Service 7c31a4
Packit Service 7c31a4
  strcat(mon_file, filename);
Packit Service 7c31a4
  strcat(mon_file, ".mon");
Packit Service 7c31a4
Packit Service 7c31a4
  *fd = 0; errno = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Open the monitor file, creating it if necessary */
Packit Service 7c31a4
  *fd = open(mon_file, O_CREAT|O_RDWR);
Packit Service 7c31a4
  if (*fd < 0)
Packit Service 7c31a4
    return UV__ERR(errno);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Write out the monitoring specifications.
Packit Service 7c31a4
   * In this case, we are monitoring for a state change event type
Packit Service 7c31a4
   *    CHANGED=YES
Packit Service 7c31a4
   * We will be waiting in select call, rather than a read:
Packit Service 7c31a4
   *    WAIT_TYPE=WAIT_IN_SELECT
Packit Service 7c31a4
   * We only want minimal information for files:
Packit Service 7c31a4
   *      INFO_LVL=1
Packit Service 7c31a4
   * For directories, we want more information to track what file
Packit Service 7c31a4
   * caused the change
Packit Service 7c31a4
   *      INFO_LVL=2
Packit Service 7c31a4
   */
Packit Service 7c31a4
Packit Service 7c31a4
  if (file_is_directory == 0)
Packit Service 7c31a4
    sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=2");
Packit Service 7c31a4
  else
Packit Service 7c31a4
    sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=1");
Packit Service 7c31a4
Packit Service 7c31a4
  rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1);
Packit Service 7c31a4
  if (rc < 0 && errno != EBUSY)
Packit Service 7c31a4
    return UV__ERR(errno);
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
/*
Packit Service 7c31a4
 * Skips a specified number of lines in the buffer passed in.
Packit Service 7c31a4
 * Walks the buffer pointed to by p and attempts to skip n lines.
Packit Service 7c31a4
 * Returns the total number of lines skipped
Packit Service 7c31a4
 */
Packit Service 7c31a4
static int uv__skip_lines(char **p, int n) {
Packit Service 7c31a4
  int lines = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  while(n > 0) {
Packit Service 7c31a4
    *p = strchr(*p, '\n');
Packit Service 7c31a4
    if (!p)
Packit Service 7c31a4
      return lines;
Packit Service 7c31a4
Packit Service 7c31a4
    (*p)++;
Packit Service 7c31a4
    n--;
Packit Service 7c31a4
    lines++;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  return lines;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
/*
Packit Service 7c31a4
 * Parse the event occurrence data to figure out what event just occurred
Packit Service 7c31a4
 * and take proper action.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * The buf is a pointer to the buffer containing the event occurrence data
Packit Service 7c31a4
 * Returns 0 on success, -1 if unrecoverable error in parsing
Packit Service 7c31a4
 *
Packit Service 7c31a4
 */
Packit Service 7c31a4
static int uv__parse_data(char *buf, int *events, uv_fs_event_t* handle) {
Packit Service 7c31a4
  int    evp_rc, i;
Packit Service 7c31a4
  char   *p;
Packit Service 7c31a4
  char   filename[PATH_MAX]; /* To be used when handling directories */
Packit Service 7c31a4
Packit Service 7c31a4
  p = buf;
Packit Service 7c31a4
  *events = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Clean the filename buffer*/
Packit Service 7c31a4
  for(i = 0; i < PATH_MAX; i++) {
Packit Service 7c31a4
    filename[i] = 0;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  i = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Check for BUF_WRAP */
Packit Service 7c31a4
  if (strncmp(buf, "BUF_WRAP", strlen("BUF_WRAP")) == 0) {
Packit Service 7c31a4
    assert(0 && "Buffer wrap detected, Some event occurrences lost!");
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Since we are using the default buffer size (4K), and have specified
Packit Service 7c31a4
   * INFO_LVL=1, we won't see any EVENT_OVERFLOW conditions.  Applications
Packit Service 7c31a4
   * should check for this keyword if they are using an INFO_LVL of 2 or
Packit Service 7c31a4
   * higher, and have a buffer size of <= 4K
Packit Service 7c31a4
   */
Packit Service 7c31a4
Packit Service 7c31a4
  /* Skip to RC_FROM_EVPROD */
Packit Service 7c31a4
  if (uv__skip_lines(&p, 9) != 9)
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
Packit Service 7c31a4
  if (sscanf(p, "RC_FROM_EVPROD=%d\nEND_EVENT_DATA", &evp_rc) == 1) {
Packit Service 7c31a4
    if (uv__path_is_a_directory(handle->path) == 0) { /* Directory */
Packit Service 7c31a4
      if (evp_rc == AHAFS_MODDIR_UNMOUNT || evp_rc == AHAFS_MODDIR_REMOVE_SELF) {
Packit Service 7c31a4
        /* The directory is no longer available for monitoring */
Packit Service 7c31a4
        *events = UV_RENAME;
Packit Service 7c31a4
        handle->dir_filename = NULL;
Packit Service 7c31a4
      } else {
Packit Service 7c31a4
        /* A file was added/removed inside the directory */
Packit Service 7c31a4
        *events = UV_CHANGE;
Packit Service 7c31a4
Packit Service 7c31a4
        /* Get the EVPROD_INFO */
Packit Service 7c31a4
        if (uv__skip_lines(&p, 1) != 1)
Packit Service 7c31a4
          return -1;
Packit Service 7c31a4
Packit Service 7c31a4
        /* Scan out the name of the file that triggered the event*/
Packit Service 7c31a4
        if (sscanf(p, "BEGIN_EVPROD_INFO\n%sEND_EVPROD_INFO", filename) == 1) {
Packit Service 7c31a4
          handle->dir_filename = uv__strdup((const char*)&filename);
Packit Service 7c31a4
        } else
Packit Service 7c31a4
          return -1;
Packit Service 7c31a4
        }
Packit Service 7c31a4
    } else { /* Regular File */
Packit Service 7c31a4
      if (evp_rc == AHAFS_MODFILE_RENAME)
Packit Service 7c31a4
        *events = UV_RENAME;
Packit Service 7c31a4
      else
Packit Service 7c31a4
        *events = UV_CHANGE;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
  else
Packit Service 7c31a4
    return -1;
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
/* This is the internal callback */
Packit Service 7c31a4
static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int fflags) {
Packit Service 7c31a4
  char   result_data[RDWR_BUF_SIZE];
Packit Service 7c31a4
  int bytes, rc = 0;
Packit Service 7c31a4
  uv_fs_event_t* handle;
Packit Service 7c31a4
  int events = 0;
Packit Service 7c31a4
  char fname[PATH_MAX];
Packit Service 7c31a4
  char *p;
Packit Service 7c31a4
Packit Service 7c31a4
  handle = container_of(event_watch, uv_fs_event_t, event_watcher);
Packit Service 7c31a4
Packit Service 7c31a4
  /* At this point, we assume that polling has been done on the
Packit Service 7c31a4
   * file descriptor, so we can just read the AHAFS event occurrence
Packit Service 7c31a4
   * data and parse its results without having to block anything
Packit Service 7c31a4
   */
Packit Service 7c31a4
  bytes = pread(event_watch->fd, result_data, RDWR_BUF_SIZE, 0);
Packit Service 7c31a4
Packit Service 7c31a4
  assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file");
Packit Service 7c31a4
Packit Service 7c31a4
  /* In file / directory move cases, AIX Event infrastructure
Packit Service 7c31a4
   * produces a second event with no data.
Packit Service 7c31a4
   * Ignore it and return gracefully.
Packit Service 7c31a4
   */
Packit Service 7c31a4
  if(bytes == 0)
Packit Service 7c31a4
    return;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Parse the data */
Packit Service 7c31a4
  if(bytes > 0)
Packit Service 7c31a4
    rc = uv__parse_data(result_data, &events, handle);
Packit Service 7c31a4
Packit Service 7c31a4
  /* Unrecoverable error */
Packit Service 7c31a4
  if (rc == -1)
Packit Service 7c31a4
    return;
Packit Service 7c31a4
Packit Service 7c31a4
  /* For directory changes, the name of the files that triggered the change
Packit Service 7c31a4
   * are never absolute pathnames
Packit Service 7c31a4
   */
Packit Service 7c31a4
  if (uv__path_is_a_directory(handle->path) == 0) {
Packit Service 7c31a4
    p = handle->dir_filename;
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    p = strrchr(handle->path, '/');
Packit Service 7c31a4
    if (p == NULL)
Packit Service 7c31a4
      p = handle->path;
Packit Service 7c31a4
    else
Packit Service 7c31a4
      p++;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* TODO(bnoordhuis) Check uv__strscpy() return value. */
Packit Service 7c31a4
  uv__strscpy(fname, p, sizeof(fname));
Packit Service 7c31a4
Packit Service 7c31a4
  handle->cb(handle, fname, events, 0);
Packit Service 7c31a4
}
Packit Service 7c31a4
#endif
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
Packit Service 7c31a4
#ifdef HAVE_SYS_AHAFS_EVPRODS_H
Packit Service 7c31a4
  uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
#else
Packit Service 7c31a4
  return UV_ENOSYS;
Packit Service 7c31a4
#endif
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_event_start(uv_fs_event_t* handle,
Packit Service 7c31a4
                      uv_fs_event_cb cb,
Packit Service 7c31a4
                      const char* filename,
Packit Service 7c31a4
                      unsigned int flags) {
Packit Service 7c31a4
#ifdef HAVE_SYS_AHAFS_EVPRODS_H
Packit Service 7c31a4
  int  fd, rc, str_offset = 0;
Packit Service 7c31a4
  char cwd[PATH_MAX];
Packit Service 7c31a4
  char absolute_path[PATH_MAX];
Packit Service 7c31a4
  char readlink_cwd[PATH_MAX];
Packit Service 7c31a4
  struct timeval zt;
Packit Service 7c31a4
  fd_set pollfd;
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
  /* Figure out whether filename is absolute or not */
Packit Service 7c31a4
  if (filename[0] == '\0') {
Packit Service 7c31a4
    /* Missing a pathname */
Packit Service 7c31a4
    return UV_ENOENT;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  else if (filename[0] == '/') {
Packit Service 7c31a4
    /* We have absolute pathname */
Packit Service 7c31a4
    /* TODO(bnoordhuis) Check uv__strscpy() return value. */
Packit Service 7c31a4
    uv__strscpy(absolute_path, filename, sizeof(absolute_path));
Packit Service 7c31a4
  } else {
Packit Service 7c31a4
    /* We have a relative pathname, compose the absolute pathname */
Packit Service 7c31a4
    snprintf(cwd, sizeof(cwd), "/proc/%lu/cwd", (unsigned long) getpid());
Packit Service 7c31a4
    rc = readlink(cwd, readlink_cwd, sizeof(readlink_cwd) - 1);
Packit Service 7c31a4
    if (rc < 0)
Packit Service 7c31a4
      return rc;
Packit Service 7c31a4
    /* readlink does not null terminate our string */
Packit Service 7c31a4
    readlink_cwd[rc] = '\0';
Packit Service 7c31a4
Packit Service 7c31a4
    if (filename[0] == '.' && filename[1] == '/')
Packit Service 7c31a4
      str_offset = 2;
Packit Service 7c31a4
Packit Service 7c31a4
    snprintf(absolute_path, sizeof(absolute_path), "%s%s", readlink_cwd,
Packit Service 7c31a4
             filename + str_offset);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (uv__is_ahafs_mounted() < 0)  /* /aha checks failed */
Packit Service 7c31a4
    return UV_ENOSYS;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Setup ahafs */
Packit Service 7c31a4
  rc = uv__setup_ahafs((const char *)absolute_path, &fd;;
Packit Service 7c31a4
  if (rc != 0)
Packit Service 7c31a4
    return rc;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Setup/Initialize all the libuv routines */
Packit Service 7c31a4
  uv__handle_start(handle);
Packit Service 7c31a4
  uv__io_init(&handle->event_watcher, uv__ahafs_event, fd);
Packit Service 7c31a4
  handle->path = uv__strdup(filename);
Packit Service 7c31a4
  handle->cb = cb;
Packit Service 7c31a4
  handle->dir_filename = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
  uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
Packit Service 7c31a4
Packit Service 7c31a4
  /* AHAFS wants someone to poll for it to start mointoring.
Packit Service 7c31a4
   *  so kick-start it so that we don't miss an event in the
Packit Service 7c31a4
   *  eventuality of an event that occurs in the current loop. */
Packit Service 7c31a4
  do {
Packit Service 7c31a4
    memset(&zt, 0, sizeof(zt));
Packit Service 7c31a4
    FD_ZERO(&pollfd);
Packit Service 7c31a4
    FD_SET(fd, &pollfd);
Packit Service 7c31a4
    rc = select(fd + 1, &pollfd, NULL, NULL, &zt;;
Packit Service 7c31a4
  } while (rc == -1 && errno == EINTR);
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
#else
Packit Service 7c31a4
  return UV_ENOSYS;
Packit Service 7c31a4
#endif
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_fs_event_stop(uv_fs_event_t* handle) {
Packit Service 7c31a4
#ifdef HAVE_SYS_AHAFS_EVPRODS_H
Packit Service 7c31a4
  if (!uv__is_active(handle))
Packit Service 7c31a4
    return 0;
Packit Service 7c31a4
Packit Service 7c31a4
  uv__io_close(handle->loop, &handle->event_watcher);
Packit Service 7c31a4
  uv__handle_stop(handle);
Packit Service 7c31a4
Packit Service 7c31a4
  if (uv__path_is_a_directory(handle->path) == 0) {
Packit Service 7c31a4
    uv__free(handle->dir_filename);
Packit Service 7c31a4
    handle->dir_filename = NULL;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  uv__free(handle->path);
Packit Service 7c31a4
  handle->path = NULL;
Packit Service 7c31a4
  uv__close(handle->event_watcher.fd);
Packit Service 7c31a4
  handle->event_watcher.fd = -1;
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
#else
Packit Service 7c31a4
  return UV_ENOSYS;
Packit Service 7c31a4
#endif
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void uv__fs_event_close(uv_fs_event_t* handle) {
Packit Service 7c31a4
#ifdef HAVE_SYS_AHAFS_EVPRODS_H
Packit Service 7c31a4
  uv_fs_event_stop(handle);
Packit Service 7c31a4
#else
Packit Service 7c31a4
  UNREACHABLE();
Packit Service 7c31a4
#endif
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
char** uv_setup_args(int argc, char** argv) {
Packit Service 7c31a4
  char** new_argv;
Packit Service 7c31a4
  size_t size;
Packit Service 7c31a4
  char* s;
Packit Service 7c31a4
  int i;
Packit Service 7c31a4
Packit Service 7c31a4
  if (argc <= 0)
Packit Service 7c31a4
    return argv;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Save the original pointer to argv.
Packit Service 7c31a4
   * AIX uses argv to read the process name.
Packit Service 7c31a4
   * (Not the memory pointed to by argv[0..n] as on Linux.)
Packit Service 7c31a4
   */
Packit Service 7c31a4
  process_argv = argv;
Packit Service 7c31a4
  process_argc = argc;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Calculate how much memory we need for the argv strings. */
Packit Service 7c31a4
  size = 0;
Packit Service 7c31a4
  for (i = 0; i < argc; i++)
Packit Service 7c31a4
    size += strlen(argv[i]) + 1;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Add space for the argv pointers. */
Packit Service 7c31a4
  size += (argc + 1) * sizeof(char*);
Packit Service 7c31a4
Packit Service 7c31a4
  new_argv = uv__malloc(size);
Packit Service 7c31a4
  if (new_argv == NULL)
Packit Service 7c31a4
    return argv;
Packit Service 7c31a4
  args_mem = new_argv;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Copy over the strings and set up the pointer table. */
Packit Service 7c31a4
  s = (char*) &new_argv[argc + 1];
Packit Service 7c31a4
  for (i = 0; i < argc; i++) {
Packit Service 7c31a4
    size = strlen(argv[i]) + 1;
Packit Service 7c31a4
    memcpy(s, argv[i], size);
Packit Service 7c31a4
    new_argv[i] = s;
Packit Service 7c31a4
    s += size;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  new_argv[i] = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
  return new_argv;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_set_process_title(const char* title) {
Packit Service 7c31a4
  char* new_title;
Packit Service 7c31a4
Packit Service 7c31a4
  /* We cannot free this pointer when libuv shuts down,
Packit Service 7c31a4
   * the process may still be using it.
Packit Service 7c31a4
   */
Packit Service 7c31a4
  new_title = uv__strdup(title);
Packit Service 7c31a4
  if (new_title == NULL)
Packit Service 7c31a4
    return UV_ENOMEM;
Packit Service 7c31a4
Packit Service 7c31a4
  uv_once(&process_title_mutex_once, init_process_title_mutex_once);
Packit Service 7c31a4
  uv_mutex_lock(&process_title_mutex);
Packit Service 7c31a4
Packit Service 7c31a4
  /* If this is the first time this is set,
Packit Service 7c31a4
   * don't free and set argv[1] to NULL.
Packit Service 7c31a4
   */
Packit Service 7c31a4
  if (process_title_ptr != NULL)
Packit Service 7c31a4
    uv__free(process_title_ptr);
Packit Service 7c31a4
Packit Service 7c31a4
  process_title_ptr = new_title;
Packit Service 7c31a4
Packit Service 7c31a4
  process_argv[0] = process_title_ptr;
Packit Service 7c31a4
  if (process_argc > 1)
Packit Service 7c31a4
     process_argv[1] = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
  uv_mutex_unlock(&process_title_mutex);
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_get_process_title(char* buffer, size_t size) {
Packit Service 7c31a4
  size_t len;
Packit Service 7c31a4
  if (buffer == NULL || size == 0)
Packit Service 7c31a4
    return UV_EINVAL;
Packit Service 7c31a4
Packit Service 7c31a4
  uv_once(&process_title_mutex_once, init_process_title_mutex_once);
Packit Service 7c31a4
  uv_mutex_lock(&process_title_mutex);
Packit Service 7c31a4
Packit Service 7c31a4
  len = strlen(process_argv[0]);
Packit Service 7c31a4
  if (size <= len) {
Packit Service 7c31a4
    uv_mutex_unlock(&process_title_mutex);
Packit Service 7c31a4
    return UV_ENOBUFS;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  memcpy(buffer, process_argv[0], len);
Packit Service 7c31a4
  buffer[len] = '\0';
Packit Service 7c31a4
Packit Service 7c31a4
  uv_mutex_unlock(&process_title_mutex);
Packit Service 7c31a4
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void uv__process_title_cleanup(void) {
Packit Service 7c31a4
  uv__free(args_mem);  /* Keep valgrind happy. */
Packit Service 7c31a4
  args_mem = NULL;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_resident_set_memory(size_t* rss) {
Packit Service 7c31a4
  char pp[64];
Packit Service 7c31a4
  psinfo_t psinfo;
Packit Service 7c31a4
  int err;
Packit Service 7c31a4
  int fd;
Packit Service 7c31a4
Packit Service 7c31a4
  snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid());
Packit Service 7c31a4
Packit Service 7c31a4
  fd = open(pp, O_RDONLY);
Packit Service 7c31a4
  if (fd == -1)
Packit Service 7c31a4
    return UV__ERR(errno);
Packit Service 7c31a4
Packit Service 7c31a4
  /* FIXME(bnoordhuis) Handle EINTR. */
Packit Service 7c31a4
  err = UV_EINVAL;
Packit Service 7c31a4
  if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) {
Packit Service 7c31a4
    *rss = (size_t)psinfo.pr_rssize * 1024;
Packit Service 7c31a4
    err = 0;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  uv__close(fd);
Packit Service 7c31a4
Packit Service 7c31a4
  return err;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_uptime(double* uptime) {
Packit Service 7c31a4
  struct utmp *utmp_buf;
Packit Service 7c31a4
  size_t entries = 0;
Packit Service 7c31a4
  time_t boot_time;
Packit Service 7c31a4
Packit Service 7c31a4
  boot_time = 0;
Packit Service 7c31a4
  utmpname(UTMP_FILE);
Packit Service 7c31a4
Packit Service 7c31a4
  setutent();
Packit Service 7c31a4
Packit Service 7c31a4
  while ((utmp_buf = getutent()) != NULL) {
Packit Service 7c31a4
    if (utmp_buf->ut_user[0] && utmp_buf->ut_type == USER_PROCESS)
Packit Service 7c31a4
      ++entries;
Packit Service 7c31a4
    if (utmp_buf->ut_type == BOOT_TIME)
Packit Service 7c31a4
      boot_time = utmp_buf->ut_time;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  endutent();
Packit Service 7c31a4
Packit Service 7c31a4
  if (boot_time == 0)
Packit Service 7c31a4
    return UV_ENOSYS;
Packit Service 7c31a4
Packit Service 7c31a4
  *uptime = time(NULL) - boot_time;
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
Packit Service 7c31a4
  uv_cpu_info_t* cpu_info;
Packit Service 7c31a4
  perfstat_cpu_total_t ps_total;
Packit Service 7c31a4
  perfstat_cpu_t* ps_cpus;
Packit Service 7c31a4
  perfstat_id_t cpu_id;
Packit Service 7c31a4
  int result, ncpus, idx = 0;
Packit Service 7c31a4
Packit Service 7c31a4
  result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1);
Packit Service 7c31a4
  if (result == -1) {
Packit Service 7c31a4
    return UV_ENOSYS;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  ncpus = result = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0);
Packit Service 7c31a4
  if (result == -1) {
Packit Service 7c31a4
    return UV_ENOSYS;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  ps_cpus = (perfstat_cpu_t*) uv__malloc(ncpus * sizeof(perfstat_cpu_t));
Packit Service 7c31a4
  if (!ps_cpus) {
Packit Service 7c31a4
    return UV_ENOMEM;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* TODO(bnoordhuis) Check uv__strscpy() return value. */
Packit Service 7c31a4
  uv__strscpy(cpu_id.name, FIRST_CPU, sizeof(cpu_id.name));
Packit Service 7c31a4
  result = perfstat_cpu(&cpu_id, ps_cpus, sizeof(perfstat_cpu_t), ncpus);
Packit Service 7c31a4
  if (result == -1) {
Packit Service 7c31a4
    uv__free(ps_cpus);
Packit Service 7c31a4
    return UV_ENOSYS;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  *cpu_infos = (uv_cpu_info_t*) uv__malloc(ncpus * sizeof(uv_cpu_info_t));
Packit Service 7c31a4
  if (!*cpu_infos) {
Packit Service 7c31a4
    uv__free(ps_cpus);
Packit Service 7c31a4
    return UV_ENOMEM;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  *count = ncpus;
Packit Service 7c31a4
Packit Service 7c31a4
  cpu_info = *cpu_infos;
Packit Service 7c31a4
  while (idx < ncpus) {
Packit Service 7c31a4
    cpu_info->speed = (int)(ps_total.processorHZ / 1000000);
Packit Service 7c31a4
    cpu_info->model = uv__strdup(ps_total.description);
Packit Service 7c31a4
    cpu_info->cpu_times.user = ps_cpus[idx].user;
Packit Service 7c31a4
    cpu_info->cpu_times.sys = ps_cpus[idx].sys;
Packit Service 7c31a4
    cpu_info->cpu_times.idle = ps_cpus[idx].idle;
Packit Service 7c31a4
    cpu_info->cpu_times.irq = ps_cpus[idx].wait;
Packit Service 7c31a4
    cpu_info->cpu_times.nice = 0;
Packit Service 7c31a4
    cpu_info++;
Packit Service 7c31a4
    idx++;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  uv__free(ps_cpus);
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
Packit Service 7c31a4
  uv_interface_address_t* address;
Packit Service 7c31a4
  int sockfd, sock6fd, inet6, i, r, size = 1;
Packit Service 7c31a4
  struct ifconf ifc;
Packit Service 7c31a4
  struct ifreq *ifr, *p, flg;
Packit Service 7c31a4
  struct in6_ifreq if6;
Packit Service 7c31a4
  struct sockaddr_dl* sa_addr;
Packit Service 7c31a4
Packit Service 7c31a4
  ifc.ifc_req = NULL;
Packit Service 7c31a4
  sock6fd = -1;
Packit Service 7c31a4
  r = 0;
Packit Service 7c31a4
  *count = 0;
Packit Service 7c31a4
  *addresses = NULL;
Packit Service 7c31a4
Packit Service 7c31a4
  if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
Packit Service 7c31a4
    r = UV__ERR(errno);
Packit Service 7c31a4
    goto cleanup;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (0 > (sock6fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP))) {
Packit Service 7c31a4
    r = UV__ERR(errno);
Packit Service 7c31a4
    goto cleanup;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
Packit Service 7c31a4
    r = UV__ERR(errno);
Packit Service 7c31a4
    goto cleanup;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  ifc.ifc_req = (struct ifreq*)uv__malloc(size);
Packit Service 7c31a4
  if (ifc.ifc_req == NULL) {
Packit Service 7c31a4
    r = UV_ENOMEM;
Packit Service 7c31a4
    goto cleanup;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  ifc.ifc_len = size;
Packit Service 7c31a4
  if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
Packit Service 7c31a4
    r = UV__ERR(errno);
Packit Service 7c31a4
    goto cleanup;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
Packit Service 7c31a4
Packit Service 7c31a4
  /* Count all up and running ipv4/ipv6 addresses */
Packit Service 7c31a4
  ifr = ifc.ifc_req;
Packit Service 7c31a4
  while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
Packit Service 7c31a4
    p = ifr;
Packit Service 7c31a4
    ifr = (struct ifreq*)
Packit Service 7c31a4
      ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
Packit Service 7c31a4
Packit Service 7c31a4
    if (!(p->ifr_addr.sa_family == AF_INET6 ||
Packit Service 7c31a4
          p->ifr_addr.sa_family == AF_INET))
Packit Service 7c31a4
      continue;
Packit Service 7c31a4
Packit Service 7c31a4
    memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
Packit Service 7c31a4
    if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
Packit Service 7c31a4
      r = UV__ERR(errno);
Packit Service 7c31a4
      goto cleanup;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
Packit Service 7c31a4
      continue;
Packit Service 7c31a4
Packit Service 7c31a4
    (*count)++;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (*count == 0)
Packit Service 7c31a4
    goto cleanup;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Alloc the return interface structs */
Packit Service 7c31a4
  *addresses = uv__calloc(*count, sizeof(**addresses));
Packit Service 7c31a4
  if (!(*addresses)) {
Packit Service 7c31a4
    r = UV_ENOMEM;
Packit Service 7c31a4
    goto cleanup;
Packit Service 7c31a4
  }
Packit Service 7c31a4
  address = *addresses;
Packit Service 7c31a4
Packit Service 7c31a4
  ifr = ifc.ifc_req;
Packit Service 7c31a4
  while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
Packit Service 7c31a4
    p = ifr;
Packit Service 7c31a4
    ifr = (struct ifreq*)
Packit Service 7c31a4
      ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
Packit Service 7c31a4
Packit Service 7c31a4
    if (!(p->ifr_addr.sa_family == AF_INET6 ||
Packit Service 7c31a4
          p->ifr_addr.sa_family == AF_INET))
Packit Service 7c31a4
      continue;
Packit Service 7c31a4
Packit Service 7c31a4
    inet6 = (p->ifr_addr.sa_family == AF_INET6);
Packit Service 7c31a4
Packit Service 7c31a4
    memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
Packit Service 7c31a4
    if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1)
Packit Service 7c31a4
      goto syserror;
Packit Service 7c31a4
Packit Service 7c31a4
    if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
Packit Service 7c31a4
      continue;
Packit Service 7c31a4
Packit Service 7c31a4
    /* All conditions above must match count loop */
Packit Service 7c31a4
Packit Service 7c31a4
    address->name = uv__strdup(p->ifr_name);
Packit Service 7c31a4
Packit Service 7c31a4
    if (inet6)
Packit Service 7c31a4
      address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
Packit Service 7c31a4
    else
Packit Service 7c31a4
      address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
Packit Service 7c31a4
Packit Service 7c31a4
    if (inet6) {
Packit Service 7c31a4
      memset(&if6, 0, sizeof(if6));
Packit Service 7c31a4
      r = uv__strscpy(if6.ifr_name, p->ifr_name, sizeof(if6.ifr_name));
Packit Service 7c31a4
      if (r == UV_E2BIG)
Packit Service 7c31a4
        goto cleanup;
Packit Service 7c31a4
      r = 0;
Packit Service 7c31a4
      memcpy(&if6.ifr_Addr, &p->ifr_addr, sizeof(if6.ifr_Addr));
Packit Service 7c31a4
      if (ioctl(sock6fd, SIOCGIFNETMASK6, &if6) == -1)
Packit Service 7c31a4
        goto syserror;
Packit Service 7c31a4
      address->netmask.netmask6 = *((struct sockaddr_in6*) &if6.ifr_Addr);
Packit Service 7c31a4
      /* Explicitly set family as the ioctl call appears to return it as 0. */
Packit Service 7c31a4
      address->netmask.netmask6.sin6_family = AF_INET6;
Packit Service 7c31a4
    } else {
Packit Service 7c31a4
      if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1)
Packit Service 7c31a4
        goto syserror;
Packit Service 7c31a4
      address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr);
Packit Service 7c31a4
      /* Explicitly set family as the ioctl call appears to return it as 0. */
Packit Service 7c31a4
      address->netmask.netmask4.sin_family = AF_INET;
Packit Service 7c31a4
    }
Packit Service 7c31a4
Packit Service 7c31a4
    address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
Packit Service 7c31a4
Packit Service 7c31a4
    address++;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  /* Fill in physical addresses. */
Packit Service 7c31a4
  ifr = ifc.ifc_req;
Packit Service 7c31a4
  while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
Packit Service 7c31a4
    p = ifr;
Packit Service 7c31a4
    ifr = (struct ifreq*)
Packit Service 7c31a4
      ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
Packit Service 7c31a4
Packit Service 7c31a4
    if (p->ifr_addr.sa_family != AF_LINK)
Packit Service 7c31a4
      continue;
Packit Service 7c31a4
Packit Service 7c31a4
    address = *addresses;
Packit Service 7c31a4
    for (i = 0; i < *count; i++) {
Packit Service 7c31a4
      if (strcmp(address->name, p->ifr_name) == 0) {
Packit Service 7c31a4
        sa_addr = (struct sockaddr_dl*) &p->ifr_addr;
Packit Service 7c31a4
        memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
Packit Service 7c31a4
      }
Packit Service 7c31a4
      address++;
Packit Service 7c31a4
    }
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
#undef ADDR_SIZE
Packit Service 7c31a4
  goto cleanup;
Packit Service 7c31a4
Packit Service 7c31a4
syserror:
Packit Service 7c31a4
  uv_free_interface_addresses(*addresses, *count);
Packit Service 7c31a4
  *addresses = NULL;
Packit Service 7c31a4
  *count = 0;
Packit Service 7c31a4
  r = UV_ENOSYS;
Packit Service 7c31a4
Packit Service 7c31a4
cleanup:
Packit Service 7c31a4
  if (sockfd != -1)
Packit Service 7c31a4
    uv__close(sockfd);
Packit Service 7c31a4
  if (sock6fd != -1)
Packit Service 7c31a4
    uv__close(sock6fd);
Packit Service 7c31a4
  uv__free(ifc.ifc_req);
Packit Service 7c31a4
  return r;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void uv_free_interface_addresses(uv_interface_address_t* addresses,
Packit Service 7c31a4
  int count) {
Packit Service 7c31a4
  int i;
Packit Service 7c31a4
Packit Service 7c31a4
  for (i = 0; i < count; ++i) {
Packit Service 7c31a4
    uv__free(addresses[i].name);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  uv__free(addresses);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
Packit Service 7c31a4
  struct pollfd* events;
Packit Service 7c31a4
  uintptr_t i;
Packit Service 7c31a4
  uintptr_t nfds;
Packit Service 7c31a4
  struct poll_ctl pc;
Packit Service 7c31a4
Packit Service 7c31a4
  assert(loop->watchers != NULL);
Packit Service 7c31a4
  assert(fd >= 0);
Packit Service 7c31a4
Packit Service 7c31a4
  events = (struct pollfd*) loop->watchers[loop->nwatchers];
Packit Service 7c31a4
  nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
Packit Service 7c31a4
Packit Service 7c31a4
  if (events != NULL)
Packit Service 7c31a4
    /* Invalidate events with same file descriptor */
Packit Service 7c31a4
    for (i = 0; i < nfds; i++)
Packit Service 7c31a4
      if ((int) events[i].fd == fd)
Packit Service 7c31a4
        events[i].fd = -1;
Packit Service 7c31a4
Packit Service 7c31a4
  /* Remove the file descriptor from the poll set */
Packit Service 7c31a4
  pc.events = 0;
Packit Service 7c31a4
  pc.cmd = PS_DELETE;
Packit Service 7c31a4
  pc.fd = fd;
Packit Service 7c31a4
  if(loop->backend_fd >= 0)
Packit Service 7c31a4
    pollset_ctl(loop->backend_fd, &pc, 1);
Packit Service 7c31a4
}