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