1e66f31c5Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 3e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to 4e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the 5e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 6e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 7e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions: 8e66f31c5Sopenharmony_ci * 9e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 10e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software. 11e66f31c5Sopenharmony_ci * 12e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 18e66f31c5Sopenharmony_ci * IN THE SOFTWARE. 19e66f31c5Sopenharmony_ci */ 20e66f31c5Sopenharmony_ci 21e66f31c5Sopenharmony_ci#include "uv.h" 22e66f31c5Sopenharmony_ci#include "uv_log.h" 23e66f31c5Sopenharmony_ci#include "internal.h" 24e66f31c5Sopenharmony_ci#include "strtok.h" 25e66f31c5Sopenharmony_ci 26e66f31c5Sopenharmony_ci#include <stddef.h> /* NULL */ 27e66f31c5Sopenharmony_ci#include <stdio.h> /* printf */ 28e66f31c5Sopenharmony_ci#include <stdlib.h> 29e66f31c5Sopenharmony_ci#include <string.h> /* strerror */ 30e66f31c5Sopenharmony_ci#include <errno.h> 31e66f31c5Sopenharmony_ci#include <assert.h> 32e66f31c5Sopenharmony_ci#include <unistd.h> 33e66f31c5Sopenharmony_ci#include <sys/types.h> 34e66f31c5Sopenharmony_ci#include <sys/stat.h> 35e66f31c5Sopenharmony_ci#include <fcntl.h> /* O_CLOEXEC */ 36e66f31c5Sopenharmony_ci#include <sys/ioctl.h> 37e66f31c5Sopenharmony_ci#include <sys/socket.h> 38e66f31c5Sopenharmony_ci#include <sys/un.h> 39e66f31c5Sopenharmony_ci#include <netinet/in.h> 40e66f31c5Sopenharmony_ci#include <arpa/inet.h> 41e66f31c5Sopenharmony_ci#include <limits.h> /* INT_MAX, PATH_MAX, IOV_MAX */ 42e66f31c5Sopenharmony_ci#include <sys/uio.h> /* writev */ 43e66f31c5Sopenharmony_ci#include <sys/resource.h> /* getrusage */ 44e66f31c5Sopenharmony_ci#include <pwd.h> 45e66f31c5Sopenharmony_ci#include <grp.h> 46e66f31c5Sopenharmony_ci#include <sys/utsname.h> 47e66f31c5Sopenharmony_ci#include <sys/time.h> 48e66f31c5Sopenharmony_ci#include <time.h> /* clock_gettime */ 49e66f31c5Sopenharmony_ci 50e66f31c5Sopenharmony_ci#ifdef __sun 51e66f31c5Sopenharmony_ci# include <sys/filio.h> 52e66f31c5Sopenharmony_ci# include <sys/wait.h> 53e66f31c5Sopenharmony_ci#endif 54e66f31c5Sopenharmony_ci 55e66f31c5Sopenharmony_ci#if defined(__APPLE__) 56e66f31c5Sopenharmony_ci# include <sys/filio.h> 57e66f31c5Sopenharmony_ci# endif /* defined(__APPLE__) */ 58e66f31c5Sopenharmony_ci 59e66f31c5Sopenharmony_ci 60e66f31c5Sopenharmony_ci#if defined(__APPLE__) && !TARGET_OS_IPHONE 61e66f31c5Sopenharmony_ci# include <crt_externs.h> 62e66f31c5Sopenharmony_ci# include <mach-o/dyld.h> /* _NSGetExecutablePath */ 63e66f31c5Sopenharmony_ci# define environ (*_NSGetEnviron()) 64e66f31c5Sopenharmony_ci#else /* defined(__APPLE__) && !TARGET_OS_IPHONE */ 65e66f31c5Sopenharmony_ciextern char** environ; 66e66f31c5Sopenharmony_ci#endif /* !(defined(__APPLE__) && !TARGET_OS_IPHONE) */ 67e66f31c5Sopenharmony_ci 68e66f31c5Sopenharmony_ci 69e66f31c5Sopenharmony_ci#if defined(__DragonFly__) || \ 70e66f31c5Sopenharmony_ci defined(__FreeBSD__) || \ 71e66f31c5Sopenharmony_ci defined(__NetBSD__) || \ 72e66f31c5Sopenharmony_ci defined(__OpenBSD__) 73e66f31c5Sopenharmony_ci# include <sys/sysctl.h> 74e66f31c5Sopenharmony_ci# include <sys/filio.h> 75e66f31c5Sopenharmony_ci# include <sys/wait.h> 76e66f31c5Sopenharmony_ci# include <sys/param.h> 77e66f31c5Sopenharmony_ci# if defined(__FreeBSD__) 78e66f31c5Sopenharmony_ci# include <sys/cpuset.h> 79e66f31c5Sopenharmony_ci# define uv__accept4 accept4 80e66f31c5Sopenharmony_ci# endif 81e66f31c5Sopenharmony_ci# if defined(__NetBSD__) 82e66f31c5Sopenharmony_ci# define uv__accept4(a, b, c, d) paccept((a), (b), (c), NULL, (d)) 83e66f31c5Sopenharmony_ci# endif 84e66f31c5Sopenharmony_ci#endif 85e66f31c5Sopenharmony_ci 86e66f31c5Sopenharmony_ci#if defined(__MVS__) 87e66f31c5Sopenharmony_ci# include <sys/ioctl.h> 88e66f31c5Sopenharmony_ci# include "zos-sys-info.h" 89e66f31c5Sopenharmony_ci#endif 90e66f31c5Sopenharmony_ci 91e66f31c5Sopenharmony_ci#if defined(__linux__) 92e66f31c5Sopenharmony_ci# include <sched.h> 93e66f31c5Sopenharmony_ci# include <sys/syscall.h> 94e66f31c5Sopenharmony_ci# define gettid() syscall(SYS_gettid) 95e66f31c5Sopenharmony_ci# define uv__accept4 accept4 96e66f31c5Sopenharmony_ci#endif 97e66f31c5Sopenharmony_ci 98e66f31c5Sopenharmony_ci#if defined(__linux__) && defined(__SANITIZE_THREAD__) && defined(__clang__) 99e66f31c5Sopenharmony_ci# include <sanitizer/linux_syscall_hooks.h> 100e66f31c5Sopenharmony_ci#endif 101e66f31c5Sopenharmony_ci 102e66f31c5Sopenharmony_cistatic void uv__run_pending(uv_loop_t* loop); 103e66f31c5Sopenharmony_ci 104e66f31c5Sopenharmony_ci/* Verify that uv_buf_t is ABI-compatible with struct iovec. */ 105e66f31c5Sopenharmony_ciSTATIC_ASSERT(sizeof(uv_buf_t) == sizeof(struct iovec)); 106e66f31c5Sopenharmony_ciSTATIC_ASSERT(sizeof(((uv_buf_t*) 0)->base) == 107e66f31c5Sopenharmony_ci sizeof(((struct iovec*) 0)->iov_base)); 108e66f31c5Sopenharmony_ciSTATIC_ASSERT(sizeof(((uv_buf_t*) 0)->len) == 109e66f31c5Sopenharmony_ci sizeof(((struct iovec*) 0)->iov_len)); 110e66f31c5Sopenharmony_ciSTATIC_ASSERT(offsetof(uv_buf_t, base) == offsetof(struct iovec, iov_base)); 111e66f31c5Sopenharmony_ciSTATIC_ASSERT(offsetof(uv_buf_t, len) == offsetof(struct iovec, iov_len)); 112e66f31c5Sopenharmony_ci 113e66f31c5Sopenharmony_ci 114e66f31c5Sopenharmony_ci/* https://github.com/libuv/libuv/issues/1674 */ 115e66f31c5Sopenharmony_ciint uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts) { 116e66f31c5Sopenharmony_ci struct timespec t; 117e66f31c5Sopenharmony_ci int r; 118e66f31c5Sopenharmony_ci 119e66f31c5Sopenharmony_ci if (ts == NULL) 120e66f31c5Sopenharmony_ci return UV_EFAULT; 121e66f31c5Sopenharmony_ci 122e66f31c5Sopenharmony_ci switch (clock_id) { 123e66f31c5Sopenharmony_ci default: 124e66f31c5Sopenharmony_ci return UV_EINVAL; 125e66f31c5Sopenharmony_ci case UV_CLOCK_MONOTONIC: 126e66f31c5Sopenharmony_ci r = clock_gettime(CLOCK_MONOTONIC, &t); 127e66f31c5Sopenharmony_ci break; 128e66f31c5Sopenharmony_ci case UV_CLOCK_REALTIME: 129e66f31c5Sopenharmony_ci r = clock_gettime(CLOCK_REALTIME, &t); 130e66f31c5Sopenharmony_ci break; 131e66f31c5Sopenharmony_ci } 132e66f31c5Sopenharmony_ci 133e66f31c5Sopenharmony_ci if (r) 134e66f31c5Sopenharmony_ci return UV__ERR(errno); 135e66f31c5Sopenharmony_ci 136e66f31c5Sopenharmony_ci ts->tv_sec = t.tv_sec; 137e66f31c5Sopenharmony_ci ts->tv_nsec = t.tv_nsec; 138e66f31c5Sopenharmony_ci 139e66f31c5Sopenharmony_ci return 0; 140e66f31c5Sopenharmony_ci} 141e66f31c5Sopenharmony_ci 142e66f31c5Sopenharmony_ci 143e66f31c5Sopenharmony_ciuint64_t uv_hrtime(void) { 144e66f31c5Sopenharmony_ci return uv__hrtime(UV_CLOCK_PRECISE); 145e66f31c5Sopenharmony_ci} 146e66f31c5Sopenharmony_ci 147e66f31c5Sopenharmony_ci 148e66f31c5Sopenharmony_civoid uv_close(uv_handle_t* handle, uv_close_cb close_cb) { 149e66f31c5Sopenharmony_ci assert(!uv__is_closing(handle)); 150e66f31c5Sopenharmony_ci 151e66f31c5Sopenharmony_ci handle->flags |= UV_HANDLE_CLOSING; 152e66f31c5Sopenharmony_ci handle->close_cb = close_cb; 153e66f31c5Sopenharmony_ci 154e66f31c5Sopenharmony_ci switch (handle->type) { 155e66f31c5Sopenharmony_ci case UV_NAMED_PIPE: 156e66f31c5Sopenharmony_ci uv__pipe_close((uv_pipe_t*)handle); 157e66f31c5Sopenharmony_ci break; 158e66f31c5Sopenharmony_ci 159e66f31c5Sopenharmony_ci case UV_TTY: 160e66f31c5Sopenharmony_ci uv__stream_close((uv_stream_t*)handle); 161e66f31c5Sopenharmony_ci break; 162e66f31c5Sopenharmony_ci 163e66f31c5Sopenharmony_ci case UV_TCP: 164e66f31c5Sopenharmony_ci uv__tcp_close((uv_tcp_t*)handle); 165e66f31c5Sopenharmony_ci break; 166e66f31c5Sopenharmony_ci 167e66f31c5Sopenharmony_ci case UV_UDP: 168e66f31c5Sopenharmony_ci uv__udp_close((uv_udp_t*)handle); 169e66f31c5Sopenharmony_ci break; 170e66f31c5Sopenharmony_ci 171e66f31c5Sopenharmony_ci case UV_PREPARE: 172e66f31c5Sopenharmony_ci uv__prepare_close((uv_prepare_t*)handle); 173e66f31c5Sopenharmony_ci break; 174e66f31c5Sopenharmony_ci 175e66f31c5Sopenharmony_ci case UV_CHECK: 176e66f31c5Sopenharmony_ci uv__check_close((uv_check_t*)handle); 177e66f31c5Sopenharmony_ci break; 178e66f31c5Sopenharmony_ci 179e66f31c5Sopenharmony_ci case UV_IDLE: 180e66f31c5Sopenharmony_ci uv__idle_close((uv_idle_t*)handle); 181e66f31c5Sopenharmony_ci break; 182e66f31c5Sopenharmony_ci 183e66f31c5Sopenharmony_ci case UV_ASYNC: 184e66f31c5Sopenharmony_ci uv__async_close((uv_async_t*)handle); 185e66f31c5Sopenharmony_ci break; 186e66f31c5Sopenharmony_ci 187e66f31c5Sopenharmony_ci case UV_TIMER: 188e66f31c5Sopenharmony_ci uv__timer_close((uv_timer_t*)handle); 189e66f31c5Sopenharmony_ci break; 190e66f31c5Sopenharmony_ci 191e66f31c5Sopenharmony_ci case UV_PROCESS: 192e66f31c5Sopenharmony_ci uv__process_close((uv_process_t*)handle); 193e66f31c5Sopenharmony_ci break; 194e66f31c5Sopenharmony_ci 195e66f31c5Sopenharmony_ci case UV_FS_EVENT: 196e66f31c5Sopenharmony_ci uv__fs_event_close((uv_fs_event_t*)handle); 197e66f31c5Sopenharmony_ci#if defined(__sun) || defined(__MVS__) 198e66f31c5Sopenharmony_ci /* 199e66f31c5Sopenharmony_ci * On Solaris, illumos, and z/OS we will not be able to dissociate the 200e66f31c5Sopenharmony_ci * watcher for an event which is pending delivery, so we cannot always call 201e66f31c5Sopenharmony_ci * uv__make_close_pending() straight away. The backend will call the 202e66f31c5Sopenharmony_ci * function once the event has cleared. 203e66f31c5Sopenharmony_ci */ 204e66f31c5Sopenharmony_ci return; 205e66f31c5Sopenharmony_ci#endif 206e66f31c5Sopenharmony_ci break; 207e66f31c5Sopenharmony_ci 208e66f31c5Sopenharmony_ci case UV_POLL: 209e66f31c5Sopenharmony_ci uv__poll_close((uv_poll_t*)handle); 210e66f31c5Sopenharmony_ci break; 211e66f31c5Sopenharmony_ci 212e66f31c5Sopenharmony_ci case UV_FS_POLL: 213e66f31c5Sopenharmony_ci uv__fs_poll_close((uv_fs_poll_t*)handle); 214e66f31c5Sopenharmony_ci /* Poll handles use file system requests, and one of them may still be 215e66f31c5Sopenharmony_ci * running. The poll code will call uv__make_close_pending() for us. */ 216e66f31c5Sopenharmony_ci return; 217e66f31c5Sopenharmony_ci 218e66f31c5Sopenharmony_ci case UV_SIGNAL: 219e66f31c5Sopenharmony_ci uv__signal_close((uv_signal_t*) handle); 220e66f31c5Sopenharmony_ci break; 221e66f31c5Sopenharmony_ci 222e66f31c5Sopenharmony_ci default: 223e66f31c5Sopenharmony_ci assert(0); 224e66f31c5Sopenharmony_ci } 225e66f31c5Sopenharmony_ci 226e66f31c5Sopenharmony_ci uv__make_close_pending(handle); 227e66f31c5Sopenharmony_ci} 228e66f31c5Sopenharmony_ci 229e66f31c5Sopenharmony_ciint uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) { 230e66f31c5Sopenharmony_ci int r; 231e66f31c5Sopenharmony_ci int fd; 232e66f31c5Sopenharmony_ci socklen_t len; 233e66f31c5Sopenharmony_ci 234e66f31c5Sopenharmony_ci if (handle == NULL || value == NULL) 235e66f31c5Sopenharmony_ci return UV_EINVAL; 236e66f31c5Sopenharmony_ci 237e66f31c5Sopenharmony_ci if (handle->type == UV_TCP || handle->type == UV_NAMED_PIPE) 238e66f31c5Sopenharmony_ci fd = uv__stream_fd((uv_stream_t*) handle); 239e66f31c5Sopenharmony_ci else if (handle->type == UV_UDP) 240e66f31c5Sopenharmony_ci fd = ((uv_udp_t *) handle)->io_watcher.fd; 241e66f31c5Sopenharmony_ci else 242e66f31c5Sopenharmony_ci return UV_ENOTSUP; 243e66f31c5Sopenharmony_ci 244e66f31c5Sopenharmony_ci len = sizeof(*value); 245e66f31c5Sopenharmony_ci 246e66f31c5Sopenharmony_ci if (*value == 0) 247e66f31c5Sopenharmony_ci r = getsockopt(fd, SOL_SOCKET, optname, value, &len); 248e66f31c5Sopenharmony_ci else 249e66f31c5Sopenharmony_ci r = setsockopt(fd, SOL_SOCKET, optname, (const void*) value, len); 250e66f31c5Sopenharmony_ci 251e66f31c5Sopenharmony_ci if (r < 0) 252e66f31c5Sopenharmony_ci return UV__ERR(errno); 253e66f31c5Sopenharmony_ci 254e66f31c5Sopenharmony_ci return 0; 255e66f31c5Sopenharmony_ci} 256e66f31c5Sopenharmony_ci 257e66f31c5Sopenharmony_civoid uv__make_close_pending(uv_handle_t* handle) { 258e66f31c5Sopenharmony_ci assert(handle->flags & UV_HANDLE_CLOSING); 259e66f31c5Sopenharmony_ci assert(!(handle->flags & UV_HANDLE_CLOSED)); 260e66f31c5Sopenharmony_ci handle->next_closing = handle->loop->closing_handles; 261e66f31c5Sopenharmony_ci handle->loop->closing_handles = handle; 262e66f31c5Sopenharmony_ci} 263e66f31c5Sopenharmony_ci 264e66f31c5Sopenharmony_ciint uv__getiovmax(void) { 265e66f31c5Sopenharmony_ci#if defined(IOV_MAX) 266e66f31c5Sopenharmony_ci return IOV_MAX; 267e66f31c5Sopenharmony_ci#elif defined(_SC_IOV_MAX) 268e66f31c5Sopenharmony_ci static _Atomic int iovmax_cached = -1; 269e66f31c5Sopenharmony_ci int iovmax; 270e66f31c5Sopenharmony_ci 271e66f31c5Sopenharmony_ci iovmax = atomic_load_explicit(&iovmax_cached, memory_order_relaxed); 272e66f31c5Sopenharmony_ci if (iovmax != -1) 273e66f31c5Sopenharmony_ci return iovmax; 274e66f31c5Sopenharmony_ci 275e66f31c5Sopenharmony_ci /* On some embedded devices (arm-linux-uclibc based ip camera), 276e66f31c5Sopenharmony_ci * sysconf(_SC_IOV_MAX) can not get the correct value. The return 277e66f31c5Sopenharmony_ci * value is -1 and the errno is EINPROGRESS. Degrade the value to 1. 278e66f31c5Sopenharmony_ci */ 279e66f31c5Sopenharmony_ci iovmax = sysconf(_SC_IOV_MAX); 280e66f31c5Sopenharmony_ci if (iovmax == -1) 281e66f31c5Sopenharmony_ci iovmax = 1; 282e66f31c5Sopenharmony_ci 283e66f31c5Sopenharmony_ci atomic_store_explicit(&iovmax_cached, iovmax, memory_order_relaxed); 284e66f31c5Sopenharmony_ci 285e66f31c5Sopenharmony_ci return iovmax; 286e66f31c5Sopenharmony_ci#else 287e66f31c5Sopenharmony_ci return 1024; 288e66f31c5Sopenharmony_ci#endif 289e66f31c5Sopenharmony_ci} 290e66f31c5Sopenharmony_ci 291e66f31c5Sopenharmony_ci 292e66f31c5Sopenharmony_cistatic void uv__finish_close(uv_handle_t* handle) { 293e66f31c5Sopenharmony_ci uv_signal_t* sh; 294e66f31c5Sopenharmony_ci 295e66f31c5Sopenharmony_ci /* Note: while the handle is in the UV_HANDLE_CLOSING state now, it's still 296e66f31c5Sopenharmony_ci * possible for it to be active in the sense that uv__is_active() returns 297e66f31c5Sopenharmony_ci * true. 298e66f31c5Sopenharmony_ci * 299e66f31c5Sopenharmony_ci * A good example is when the user calls uv_shutdown(), immediately followed 300e66f31c5Sopenharmony_ci * by uv_close(). The handle is considered active at this point because the 301e66f31c5Sopenharmony_ci * completion of the shutdown req is still pending. 302e66f31c5Sopenharmony_ci */ 303e66f31c5Sopenharmony_ci assert(handle->flags & UV_HANDLE_CLOSING); 304e66f31c5Sopenharmony_ci assert(!(handle->flags & UV_HANDLE_CLOSED)); 305e66f31c5Sopenharmony_ci handle->flags |= UV_HANDLE_CLOSED; 306e66f31c5Sopenharmony_ci 307e66f31c5Sopenharmony_ci switch (handle->type) { 308e66f31c5Sopenharmony_ci case UV_PREPARE: 309e66f31c5Sopenharmony_ci case UV_CHECK: 310e66f31c5Sopenharmony_ci case UV_IDLE: 311e66f31c5Sopenharmony_ci case UV_ASYNC: 312e66f31c5Sopenharmony_ci case UV_TIMER: 313e66f31c5Sopenharmony_ci case UV_PROCESS: 314e66f31c5Sopenharmony_ci case UV_FS_EVENT: 315e66f31c5Sopenharmony_ci case UV_FS_POLL: 316e66f31c5Sopenharmony_ci case UV_POLL: 317e66f31c5Sopenharmony_ci break; 318e66f31c5Sopenharmony_ci 319e66f31c5Sopenharmony_ci case UV_SIGNAL: 320e66f31c5Sopenharmony_ci /* If there are any caught signals "trapped" in the signal pipe, 321e66f31c5Sopenharmony_ci * we can't call the close callback yet. Reinserting the handle 322e66f31c5Sopenharmony_ci * into the closing queue makes the event loop spin but that's 323e66f31c5Sopenharmony_ci * okay because we only need to deliver the pending events. 324e66f31c5Sopenharmony_ci */ 325e66f31c5Sopenharmony_ci sh = (uv_signal_t*) handle; 326e66f31c5Sopenharmony_ci if (sh->caught_signals > sh->dispatched_signals) { 327e66f31c5Sopenharmony_ci handle->flags ^= UV_HANDLE_CLOSED; 328e66f31c5Sopenharmony_ci uv__make_close_pending(handle); /* Back into the queue. */ 329e66f31c5Sopenharmony_ci return; 330e66f31c5Sopenharmony_ci } 331e66f31c5Sopenharmony_ci break; 332e66f31c5Sopenharmony_ci 333e66f31c5Sopenharmony_ci case UV_NAMED_PIPE: 334e66f31c5Sopenharmony_ci case UV_TCP: 335e66f31c5Sopenharmony_ci case UV_TTY: 336e66f31c5Sopenharmony_ci uv__stream_destroy((uv_stream_t*)handle); 337e66f31c5Sopenharmony_ci break; 338e66f31c5Sopenharmony_ci 339e66f31c5Sopenharmony_ci case UV_UDP: 340e66f31c5Sopenharmony_ci uv__udp_finish_close((uv_udp_t*)handle); 341e66f31c5Sopenharmony_ci break; 342e66f31c5Sopenharmony_ci 343e66f31c5Sopenharmony_ci default: 344e66f31c5Sopenharmony_ci assert(0); 345e66f31c5Sopenharmony_ci break; 346e66f31c5Sopenharmony_ci } 347e66f31c5Sopenharmony_ci 348e66f31c5Sopenharmony_ci uv__handle_unref(handle); 349e66f31c5Sopenharmony_ci uv__queue_remove(&handle->handle_queue); 350e66f31c5Sopenharmony_ci 351e66f31c5Sopenharmony_ci if (handle->close_cb) { 352e66f31c5Sopenharmony_ci handle->close_cb(handle); 353e66f31c5Sopenharmony_ci } 354e66f31c5Sopenharmony_ci} 355e66f31c5Sopenharmony_ci 356e66f31c5Sopenharmony_ci 357e66f31c5Sopenharmony_cistatic void uv__run_closing_handles(uv_loop_t* loop) { 358e66f31c5Sopenharmony_ci uv_handle_t* p; 359e66f31c5Sopenharmony_ci uv_handle_t* q; 360e66f31c5Sopenharmony_ci 361e66f31c5Sopenharmony_ci p = loop->closing_handles; 362e66f31c5Sopenharmony_ci loop->closing_handles = NULL; 363e66f31c5Sopenharmony_ci 364e66f31c5Sopenharmony_ci while (p) { 365e66f31c5Sopenharmony_ci q = p->next_closing; 366e66f31c5Sopenharmony_ci uv__finish_close(p); 367e66f31c5Sopenharmony_ci p = q; 368e66f31c5Sopenharmony_ci } 369e66f31c5Sopenharmony_ci} 370e66f31c5Sopenharmony_ci 371e66f31c5Sopenharmony_ci 372e66f31c5Sopenharmony_ciint uv_is_closing(const uv_handle_t* handle) { 373e66f31c5Sopenharmony_ci return uv__is_closing(handle); 374e66f31c5Sopenharmony_ci} 375e66f31c5Sopenharmony_ci 376e66f31c5Sopenharmony_ci 377e66f31c5Sopenharmony_ciint uv_backend_fd(const uv_loop_t* loop) { 378e66f31c5Sopenharmony_ci return loop->backend_fd; 379e66f31c5Sopenharmony_ci} 380e66f31c5Sopenharmony_ci 381e66f31c5Sopenharmony_ci 382e66f31c5Sopenharmony_cistatic int uv__loop_alive(const uv_loop_t* loop) { 383e66f31c5Sopenharmony_ci return uv__has_active_handles(loop) || 384e66f31c5Sopenharmony_ci uv__has_active_reqs(loop) || 385e66f31c5Sopenharmony_ci !uv__queue_empty(&loop->pending_queue) || 386e66f31c5Sopenharmony_ci loop->closing_handles != NULL; 387e66f31c5Sopenharmony_ci} 388e66f31c5Sopenharmony_ci 389e66f31c5Sopenharmony_ci 390e66f31c5Sopenharmony_cistatic int uv__backend_timeout(const uv_loop_t* loop) { 391e66f31c5Sopenharmony_ci if (loop->stop_flag == 0 && 392e66f31c5Sopenharmony_ci /* uv__loop_alive(loop) && */ 393e66f31c5Sopenharmony_ci (uv__has_active_handles(loop) || uv__has_active_reqs(loop)) && 394e66f31c5Sopenharmony_ci uv__queue_empty(&loop->pending_queue) && 395e66f31c5Sopenharmony_ci uv__queue_empty(&loop->idle_handles) && 396e66f31c5Sopenharmony_ci (loop->flags & UV_LOOP_REAP_CHILDREN) == 0 && 397e66f31c5Sopenharmony_ci loop->closing_handles == NULL) 398e66f31c5Sopenharmony_ci return uv__next_timeout(loop); 399e66f31c5Sopenharmony_ci return 0; 400e66f31c5Sopenharmony_ci} 401e66f31c5Sopenharmony_ci 402e66f31c5Sopenharmony_ci 403e66f31c5Sopenharmony_ciint uv_backend_timeout(const uv_loop_t* loop) { 404e66f31c5Sopenharmony_ci if (uv__queue_empty(&loop->watcher_queue)) 405e66f31c5Sopenharmony_ci return uv__backend_timeout(loop); 406e66f31c5Sopenharmony_ci /* Need to call uv_run to update the backend fd state. */ 407e66f31c5Sopenharmony_ci return 0; 408e66f31c5Sopenharmony_ci} 409e66f31c5Sopenharmony_ci 410e66f31c5Sopenharmony_ci 411e66f31c5Sopenharmony_ciint uv_loop_alive(const uv_loop_t* loop) { 412e66f31c5Sopenharmony_ci return uv__loop_alive(loop); 413e66f31c5Sopenharmony_ci} 414e66f31c5Sopenharmony_ci 415e66f31c5Sopenharmony_ci 416e66f31c5Sopenharmony_ciint uv_loop_alive_taskpool(const uv_loop_t* loop, int initial_handles) { 417e66f31c5Sopenharmony_ci return loop->active_handles > initial_handles || 418e66f31c5Sopenharmony_ci uv__has_active_reqs(loop) || 419e66f31c5Sopenharmony_ci !uv__queue_empty(&loop->pending_queue) || 420e66f31c5Sopenharmony_ci loop->closing_handles != NULL; 421e66f31c5Sopenharmony_ci} 422e66f31c5Sopenharmony_ci 423e66f31c5Sopenharmony_ci 424e66f31c5Sopenharmony_ciint is_uv_loop_good_magic(const uv_loop_t* loop); 425e66f31c5Sopenharmony_ci 426e66f31c5Sopenharmony_ci 427e66f31c5Sopenharmony_ciint uv_run(uv_loop_t* loop, uv_run_mode mode) { 428e66f31c5Sopenharmony_ci int timeout; 429e66f31c5Sopenharmony_ci int r; 430e66f31c5Sopenharmony_ci int can_sleep; 431e66f31c5Sopenharmony_ci 432e66f31c5Sopenharmony_ci if (!is_uv_loop_good_magic(loop)) { 433e66f31c5Sopenharmony_ci return 0; 434e66f31c5Sopenharmony_ci } 435e66f31c5Sopenharmony_ci 436e66f31c5Sopenharmony_ci r = uv__loop_alive(loop); 437e66f31c5Sopenharmony_ci if (!r) 438e66f31c5Sopenharmony_ci uv__update_time(loop); 439e66f31c5Sopenharmony_ci 440e66f31c5Sopenharmony_ci while (r != 0 && loop->stop_flag == 0) { 441e66f31c5Sopenharmony_ci if (!is_uv_loop_good_magic(loop)) { 442e66f31c5Sopenharmony_ci return 0; 443e66f31c5Sopenharmony_ci } 444e66f31c5Sopenharmony_ci 445e66f31c5Sopenharmony_ci uv__update_time(loop); 446e66f31c5Sopenharmony_ci uv__run_timers(loop); 447e66f31c5Sopenharmony_ci 448e66f31c5Sopenharmony_ci can_sleep = 449e66f31c5Sopenharmony_ci uv__queue_empty(&loop->pending_queue) && 450e66f31c5Sopenharmony_ci uv__queue_empty(&loop->idle_handles); 451e66f31c5Sopenharmony_ci 452e66f31c5Sopenharmony_ci uv__run_pending(loop); 453e66f31c5Sopenharmony_ci uv__run_idle(loop); 454e66f31c5Sopenharmony_ci uv__run_prepare(loop); 455e66f31c5Sopenharmony_ci 456e66f31c5Sopenharmony_ci timeout = 0; 457e66f31c5Sopenharmony_ci if ((mode == UV_RUN_ONCE && can_sleep) || mode == UV_RUN_DEFAULT) 458e66f31c5Sopenharmony_ci timeout = uv__backend_timeout(loop); 459e66f31c5Sopenharmony_ci 460e66f31c5Sopenharmony_ci uv__metrics_inc_loop_count(loop); 461e66f31c5Sopenharmony_ci 462e66f31c5Sopenharmony_ci uv__io_poll(loop, timeout); 463e66f31c5Sopenharmony_ci 464e66f31c5Sopenharmony_ci /* Process immediate callbacks (e.g. write_cb) a small fixed number of 465e66f31c5Sopenharmony_ci * times to avoid loop starvation.*/ 466e66f31c5Sopenharmony_ci for (r = 0; r < 8 && !uv__queue_empty(&loop->pending_queue); r++) 467e66f31c5Sopenharmony_ci uv__run_pending(loop); 468e66f31c5Sopenharmony_ci 469e66f31c5Sopenharmony_ci /* Run one final update on the provider_idle_time in case uv__io_poll 470e66f31c5Sopenharmony_ci * returned because the timeout expired, but no events were received. This 471e66f31c5Sopenharmony_ci * call will be ignored if the provider_entry_time was either never set (if 472e66f31c5Sopenharmony_ci * the timeout == 0) or was already updated b/c an event was received. 473e66f31c5Sopenharmony_ci */ 474e66f31c5Sopenharmony_ci uv__metrics_update_idle_time(loop); 475e66f31c5Sopenharmony_ci 476e66f31c5Sopenharmony_ci uv__run_check(loop); 477e66f31c5Sopenharmony_ci uv__run_closing_handles(loop); 478e66f31c5Sopenharmony_ci 479e66f31c5Sopenharmony_ci if (mode == UV_RUN_ONCE) { 480e66f31c5Sopenharmony_ci /* UV_RUN_ONCE implies forward progress: at least one callback must have 481e66f31c5Sopenharmony_ci * been invoked when it returns. uv__io_poll() can return without doing 482e66f31c5Sopenharmony_ci * I/O (meaning: no callbacks) when its timeout expires - which means we 483e66f31c5Sopenharmony_ci * have pending timers that satisfy the forward progress constraint. 484e66f31c5Sopenharmony_ci * 485e66f31c5Sopenharmony_ci * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from 486e66f31c5Sopenharmony_ci * the check. 487e66f31c5Sopenharmony_ci */ 488e66f31c5Sopenharmony_ci uv__update_time(loop); 489e66f31c5Sopenharmony_ci uv__run_timers(loop); 490e66f31c5Sopenharmony_ci } 491e66f31c5Sopenharmony_ci 492e66f31c5Sopenharmony_ci r = uv__loop_alive(loop); 493e66f31c5Sopenharmony_ci if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT) 494e66f31c5Sopenharmony_ci break; 495e66f31c5Sopenharmony_ci } 496e66f31c5Sopenharmony_ci 497e66f31c5Sopenharmony_ci /* The if statement lets gcc compile it to a conditional store. Avoids 498e66f31c5Sopenharmony_ci * dirtying a cache line. 499e66f31c5Sopenharmony_ci */ 500e66f31c5Sopenharmony_ci if (loop->stop_flag != 0) 501e66f31c5Sopenharmony_ci loop->stop_flag = 0; 502e66f31c5Sopenharmony_ci 503e66f31c5Sopenharmony_ci return r; 504e66f31c5Sopenharmony_ci} 505e66f31c5Sopenharmony_ci 506e66f31c5Sopenharmony_ci 507e66f31c5Sopenharmony_civoid uv_update_time(uv_loop_t* loop) { 508e66f31c5Sopenharmony_ci uv__update_time(loop); 509e66f31c5Sopenharmony_ci} 510e66f31c5Sopenharmony_ci 511e66f31c5Sopenharmony_ci 512e66f31c5Sopenharmony_ciint uv_is_active(const uv_handle_t* handle) { 513e66f31c5Sopenharmony_ci return uv__is_active(handle); 514e66f31c5Sopenharmony_ci} 515e66f31c5Sopenharmony_ci 516e66f31c5Sopenharmony_ci 517e66f31c5Sopenharmony_ci/* Open a socket in non-blocking close-on-exec mode, atomically if possible. */ 518e66f31c5Sopenharmony_ciint uv__socket(int domain, int type, int protocol) { 519e66f31c5Sopenharmony_ci int sockfd; 520e66f31c5Sopenharmony_ci int err; 521e66f31c5Sopenharmony_ci 522e66f31c5Sopenharmony_ci#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) 523e66f31c5Sopenharmony_ci sockfd = socket(domain, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol); 524e66f31c5Sopenharmony_ci if (sockfd != -1) 525e66f31c5Sopenharmony_ci return sockfd; 526e66f31c5Sopenharmony_ci 527e66f31c5Sopenharmony_ci if (errno != EINVAL) 528e66f31c5Sopenharmony_ci return UV__ERR(errno); 529e66f31c5Sopenharmony_ci#endif 530e66f31c5Sopenharmony_ci 531e66f31c5Sopenharmony_ci sockfd = socket(domain, type, protocol); 532e66f31c5Sopenharmony_ci if (sockfd == -1) 533e66f31c5Sopenharmony_ci return UV__ERR(errno); 534e66f31c5Sopenharmony_ci 535e66f31c5Sopenharmony_ci err = uv__nonblock(sockfd, 1); 536e66f31c5Sopenharmony_ci if (err == 0) 537e66f31c5Sopenharmony_ci err = uv__cloexec(sockfd, 1); 538e66f31c5Sopenharmony_ci 539e66f31c5Sopenharmony_ci if (err) { 540e66f31c5Sopenharmony_ci uv__close(sockfd); 541e66f31c5Sopenharmony_ci return err; 542e66f31c5Sopenharmony_ci } 543e66f31c5Sopenharmony_ci 544e66f31c5Sopenharmony_ci#if defined(SO_NOSIGPIPE) 545e66f31c5Sopenharmony_ci { 546e66f31c5Sopenharmony_ci int on = 1; 547e66f31c5Sopenharmony_ci setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on)); 548e66f31c5Sopenharmony_ci } 549e66f31c5Sopenharmony_ci#endif 550e66f31c5Sopenharmony_ci 551e66f31c5Sopenharmony_ci return sockfd; 552e66f31c5Sopenharmony_ci} 553e66f31c5Sopenharmony_ci 554e66f31c5Sopenharmony_ci/* get a file pointer to a file in read-only and close-on-exec mode */ 555e66f31c5Sopenharmony_ciFILE* uv__open_file(const char* path) { 556e66f31c5Sopenharmony_ci int fd; 557e66f31c5Sopenharmony_ci FILE* fp; 558e66f31c5Sopenharmony_ci 559e66f31c5Sopenharmony_ci fd = uv__open_cloexec(path, O_RDONLY); 560e66f31c5Sopenharmony_ci if (fd < 0) 561e66f31c5Sopenharmony_ci return NULL; 562e66f31c5Sopenharmony_ci 563e66f31c5Sopenharmony_ci fp = fdopen(fd, "r"); 564e66f31c5Sopenharmony_ci if (fp == NULL) 565e66f31c5Sopenharmony_ci uv__close(fd); 566e66f31c5Sopenharmony_ci 567e66f31c5Sopenharmony_ci return fp; 568e66f31c5Sopenharmony_ci} 569e66f31c5Sopenharmony_ci 570e66f31c5Sopenharmony_ci 571e66f31c5Sopenharmony_ciint uv__accept(int sockfd) { 572e66f31c5Sopenharmony_ci int peerfd; 573e66f31c5Sopenharmony_ci int err; 574e66f31c5Sopenharmony_ci 575e66f31c5Sopenharmony_ci (void) &err; 576e66f31c5Sopenharmony_ci assert(sockfd >= 0); 577e66f31c5Sopenharmony_ci 578e66f31c5Sopenharmony_ci do 579e66f31c5Sopenharmony_ci#ifdef uv__accept4 580e66f31c5Sopenharmony_ci peerfd = uv__accept4(sockfd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); 581e66f31c5Sopenharmony_ci#else 582e66f31c5Sopenharmony_ci peerfd = accept(sockfd, NULL, NULL); 583e66f31c5Sopenharmony_ci#endif 584e66f31c5Sopenharmony_ci while (peerfd == -1 && errno == EINTR); 585e66f31c5Sopenharmony_ci 586e66f31c5Sopenharmony_ci if (peerfd == -1) 587e66f31c5Sopenharmony_ci return UV__ERR(errno); 588e66f31c5Sopenharmony_ci 589e66f31c5Sopenharmony_ci#ifndef uv__accept4 590e66f31c5Sopenharmony_ci err = uv__cloexec(peerfd, 1); 591e66f31c5Sopenharmony_ci if (err == 0) 592e66f31c5Sopenharmony_ci err = uv__nonblock(peerfd, 1); 593e66f31c5Sopenharmony_ci 594e66f31c5Sopenharmony_ci if (err != 0) { 595e66f31c5Sopenharmony_ci uv__close(peerfd); 596e66f31c5Sopenharmony_ci return err; 597e66f31c5Sopenharmony_ci } 598e66f31c5Sopenharmony_ci#endif 599e66f31c5Sopenharmony_ci 600e66f31c5Sopenharmony_ci return peerfd; 601e66f31c5Sopenharmony_ci} 602e66f31c5Sopenharmony_ci 603e66f31c5Sopenharmony_ci 604e66f31c5Sopenharmony_ci/* close() on macos has the "interesting" quirk that it fails with EINTR 605e66f31c5Sopenharmony_ci * without closing the file descriptor when a thread is in the cancel state. 606e66f31c5Sopenharmony_ci * That's why libuv calls close$NOCANCEL() instead. 607e66f31c5Sopenharmony_ci * 608e66f31c5Sopenharmony_ci * glibc on linux has a similar issue: close() is a cancellation point and 609e66f31c5Sopenharmony_ci * will unwind the thread when it's in the cancel state. Work around that 610e66f31c5Sopenharmony_ci * by making the system call directly. Musl libc is unaffected. 611e66f31c5Sopenharmony_ci */ 612e66f31c5Sopenharmony_ciint uv__close_nocancel(int fd) { 613e66f31c5Sopenharmony_ci#if defined(__APPLE__) 614e66f31c5Sopenharmony_ci#pragma GCC diagnostic push 615e66f31c5Sopenharmony_ci#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension" 616e66f31c5Sopenharmony_ci#if defined(__LP64__) || TARGET_OS_IPHONE 617e66f31c5Sopenharmony_ci extern int close$NOCANCEL(int); 618e66f31c5Sopenharmony_ci return close$NOCANCEL(fd); 619e66f31c5Sopenharmony_ci#else 620e66f31c5Sopenharmony_ci extern int close$NOCANCEL$UNIX2003(int); 621e66f31c5Sopenharmony_ci return close$NOCANCEL$UNIX2003(fd); 622e66f31c5Sopenharmony_ci#endif 623e66f31c5Sopenharmony_ci#pragma GCC diagnostic pop 624e66f31c5Sopenharmony_ci#elif defined(__linux__) && defined(__SANITIZE_THREAD__) && defined(__clang__) 625e66f31c5Sopenharmony_ci long rc; 626e66f31c5Sopenharmony_ci __sanitizer_syscall_pre_close(fd); 627e66f31c5Sopenharmony_ci rc = syscall(SYS_close, fd); 628e66f31c5Sopenharmony_ci __sanitizer_syscall_post_close(rc, fd); 629e66f31c5Sopenharmony_ci return rc; 630e66f31c5Sopenharmony_ci#elif defined(__linux__) && !defined(__SANITIZE_THREAD__) 631e66f31c5Sopenharmony_ci return syscall(SYS_close, fd); 632e66f31c5Sopenharmony_ci#else 633e66f31c5Sopenharmony_ci return close(fd); 634e66f31c5Sopenharmony_ci#endif 635e66f31c5Sopenharmony_ci} 636e66f31c5Sopenharmony_ci 637e66f31c5Sopenharmony_ci 638e66f31c5Sopenharmony_ciint uv__close_nocheckstdio(int fd) { 639e66f31c5Sopenharmony_ci int saved_errno; 640e66f31c5Sopenharmony_ci int rc; 641e66f31c5Sopenharmony_ci 642e66f31c5Sopenharmony_ci assert(fd > -1); /* Catch uninitialized io_watcher.fd bugs. */ 643e66f31c5Sopenharmony_ci 644e66f31c5Sopenharmony_ci saved_errno = errno; 645e66f31c5Sopenharmony_ci rc = uv__close_nocancel(fd); 646e66f31c5Sopenharmony_ci if (rc == -1) { 647e66f31c5Sopenharmony_ci rc = UV__ERR(errno); 648e66f31c5Sopenharmony_ci if (rc == UV_EINTR || rc == UV__ERR(EINPROGRESS)) 649e66f31c5Sopenharmony_ci rc = 0; /* The close is in progress, not an error. */ 650e66f31c5Sopenharmony_ci errno = saved_errno; 651e66f31c5Sopenharmony_ci } 652e66f31c5Sopenharmony_ci 653e66f31c5Sopenharmony_ci return rc; 654e66f31c5Sopenharmony_ci} 655e66f31c5Sopenharmony_ci 656e66f31c5Sopenharmony_ci 657e66f31c5Sopenharmony_ciint uv__close(int fd) { 658e66f31c5Sopenharmony_ci assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */ 659e66f31c5Sopenharmony_ci#if defined(__MVS__) 660e66f31c5Sopenharmony_ci SAVE_ERRNO(epoll_file_close(fd)); 661e66f31c5Sopenharmony_ci#endif 662e66f31c5Sopenharmony_ci return uv__close_nocheckstdio(fd); 663e66f31c5Sopenharmony_ci} 664e66f31c5Sopenharmony_ci 665e66f31c5Sopenharmony_ci#if UV__NONBLOCK_IS_IOCTL 666e66f31c5Sopenharmony_ciint uv__nonblock_ioctl(int fd, int set) { 667e66f31c5Sopenharmony_ci int r; 668e66f31c5Sopenharmony_ci 669e66f31c5Sopenharmony_ci do 670e66f31c5Sopenharmony_ci r = ioctl(fd, FIONBIO, &set); 671e66f31c5Sopenharmony_ci while (r == -1 && errno == EINTR); 672e66f31c5Sopenharmony_ci 673e66f31c5Sopenharmony_ci if (r) 674e66f31c5Sopenharmony_ci return UV__ERR(errno); 675e66f31c5Sopenharmony_ci 676e66f31c5Sopenharmony_ci return 0; 677e66f31c5Sopenharmony_ci} 678e66f31c5Sopenharmony_ci#endif 679e66f31c5Sopenharmony_ci 680e66f31c5Sopenharmony_ci 681e66f31c5Sopenharmony_ciint uv__nonblock_fcntl(int fd, int set) { 682e66f31c5Sopenharmony_ci int flags; 683e66f31c5Sopenharmony_ci int r; 684e66f31c5Sopenharmony_ci 685e66f31c5Sopenharmony_ci do 686e66f31c5Sopenharmony_ci r = fcntl(fd, F_GETFL); 687e66f31c5Sopenharmony_ci while (r == -1 && errno == EINTR); 688e66f31c5Sopenharmony_ci 689e66f31c5Sopenharmony_ci if (r == -1) 690e66f31c5Sopenharmony_ci return UV__ERR(errno); 691e66f31c5Sopenharmony_ci 692e66f31c5Sopenharmony_ci /* Bail out now if already set/clear. */ 693e66f31c5Sopenharmony_ci if (!!(r & O_NONBLOCK) == !!set) 694e66f31c5Sopenharmony_ci return 0; 695e66f31c5Sopenharmony_ci 696e66f31c5Sopenharmony_ci if (set) 697e66f31c5Sopenharmony_ci flags = r | O_NONBLOCK; 698e66f31c5Sopenharmony_ci else 699e66f31c5Sopenharmony_ci flags = r & ~O_NONBLOCK; 700e66f31c5Sopenharmony_ci 701e66f31c5Sopenharmony_ci do 702e66f31c5Sopenharmony_ci r = fcntl(fd, F_SETFL, flags); 703e66f31c5Sopenharmony_ci while (r == -1 && errno == EINTR); 704e66f31c5Sopenharmony_ci 705e66f31c5Sopenharmony_ci if (r) 706e66f31c5Sopenharmony_ci return UV__ERR(errno); 707e66f31c5Sopenharmony_ci 708e66f31c5Sopenharmony_ci return 0; 709e66f31c5Sopenharmony_ci} 710e66f31c5Sopenharmony_ci 711e66f31c5Sopenharmony_ci 712e66f31c5Sopenharmony_ciint uv__cloexec(int fd, int set) { 713e66f31c5Sopenharmony_ci int flags; 714e66f31c5Sopenharmony_ci int r; 715e66f31c5Sopenharmony_ci 716e66f31c5Sopenharmony_ci flags = 0; 717e66f31c5Sopenharmony_ci if (set) 718e66f31c5Sopenharmony_ci flags = FD_CLOEXEC; 719e66f31c5Sopenharmony_ci 720e66f31c5Sopenharmony_ci do 721e66f31c5Sopenharmony_ci r = fcntl(fd, F_SETFD, flags); 722e66f31c5Sopenharmony_ci while (r == -1 && errno == EINTR); 723e66f31c5Sopenharmony_ci 724e66f31c5Sopenharmony_ci if (r) 725e66f31c5Sopenharmony_ci return UV__ERR(errno); 726e66f31c5Sopenharmony_ci 727e66f31c5Sopenharmony_ci return 0; 728e66f31c5Sopenharmony_ci} 729e66f31c5Sopenharmony_ci 730e66f31c5Sopenharmony_ci 731e66f31c5Sopenharmony_cissize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) { 732e66f31c5Sopenharmony_ci#if defined(__ANDROID__) || \ 733e66f31c5Sopenharmony_ci defined(__DragonFly__) || \ 734e66f31c5Sopenharmony_ci defined(__FreeBSD__) || \ 735e66f31c5Sopenharmony_ci defined(__NetBSD__) || \ 736e66f31c5Sopenharmony_ci defined(__OpenBSD__) || \ 737e66f31c5Sopenharmony_ci defined(__linux__) 738e66f31c5Sopenharmony_ci ssize_t rc; 739e66f31c5Sopenharmony_ci rc = recvmsg(fd, msg, flags | MSG_CMSG_CLOEXEC); 740e66f31c5Sopenharmony_ci if (rc == -1) 741e66f31c5Sopenharmony_ci return UV__ERR(errno); 742e66f31c5Sopenharmony_ci return rc; 743e66f31c5Sopenharmony_ci#else 744e66f31c5Sopenharmony_ci struct cmsghdr* cmsg; 745e66f31c5Sopenharmony_ci int* pfd; 746e66f31c5Sopenharmony_ci int* end; 747e66f31c5Sopenharmony_ci ssize_t rc; 748e66f31c5Sopenharmony_ci rc = recvmsg(fd, msg, flags); 749e66f31c5Sopenharmony_ci if (rc == -1) 750e66f31c5Sopenharmony_ci return UV__ERR(errno); 751e66f31c5Sopenharmony_ci if (msg->msg_controllen == 0) 752e66f31c5Sopenharmony_ci return rc; 753e66f31c5Sopenharmony_ci for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) 754e66f31c5Sopenharmony_ci if (cmsg->cmsg_type == SCM_RIGHTS) 755e66f31c5Sopenharmony_ci for (pfd = (int*) CMSG_DATA(cmsg), 756e66f31c5Sopenharmony_ci end = (int*) ((char*) cmsg + cmsg->cmsg_len); 757e66f31c5Sopenharmony_ci pfd < end; 758e66f31c5Sopenharmony_ci pfd += 1) 759e66f31c5Sopenharmony_ci uv__cloexec(*pfd, 1); 760e66f31c5Sopenharmony_ci return rc; 761e66f31c5Sopenharmony_ci#endif 762e66f31c5Sopenharmony_ci} 763e66f31c5Sopenharmony_ci 764e66f31c5Sopenharmony_ci 765e66f31c5Sopenharmony_ciint uv_cwd(char* buffer, size_t* size) { 766e66f31c5Sopenharmony_ci char scratch[1 + UV__PATH_MAX]; 767e66f31c5Sopenharmony_ci 768e66f31c5Sopenharmony_ci if (buffer == NULL || size == NULL) 769e66f31c5Sopenharmony_ci return UV_EINVAL; 770e66f31c5Sopenharmony_ci 771e66f31c5Sopenharmony_ci /* Try to read directly into the user's buffer first... */ 772e66f31c5Sopenharmony_ci if (getcwd(buffer, *size) != NULL) 773e66f31c5Sopenharmony_ci goto fixup; 774e66f31c5Sopenharmony_ci 775e66f31c5Sopenharmony_ci if (errno != ERANGE) 776e66f31c5Sopenharmony_ci return UV__ERR(errno); 777e66f31c5Sopenharmony_ci 778e66f31c5Sopenharmony_ci /* ...or into scratch space if the user's buffer is too small 779e66f31c5Sopenharmony_ci * so we can report how much space to provide on the next try. 780e66f31c5Sopenharmony_ci */ 781e66f31c5Sopenharmony_ci if (getcwd(scratch, sizeof(scratch)) == NULL) 782e66f31c5Sopenharmony_ci return UV__ERR(errno); 783e66f31c5Sopenharmony_ci 784e66f31c5Sopenharmony_ci buffer = scratch; 785e66f31c5Sopenharmony_ci 786e66f31c5Sopenharmony_cifixup: 787e66f31c5Sopenharmony_ci 788e66f31c5Sopenharmony_ci *size = strlen(buffer); 789e66f31c5Sopenharmony_ci 790e66f31c5Sopenharmony_ci if (*size > 1 && buffer[*size - 1] == '/') { 791e66f31c5Sopenharmony_ci *size -= 1; 792e66f31c5Sopenharmony_ci buffer[*size] = '\0'; 793e66f31c5Sopenharmony_ci } 794e66f31c5Sopenharmony_ci 795e66f31c5Sopenharmony_ci if (buffer == scratch) { 796e66f31c5Sopenharmony_ci *size += 1; 797e66f31c5Sopenharmony_ci return UV_ENOBUFS; 798e66f31c5Sopenharmony_ci } 799e66f31c5Sopenharmony_ci 800e66f31c5Sopenharmony_ci return 0; 801e66f31c5Sopenharmony_ci} 802e66f31c5Sopenharmony_ci 803e66f31c5Sopenharmony_ci 804e66f31c5Sopenharmony_ciint uv_chdir(const char* dir) { 805e66f31c5Sopenharmony_ci if (chdir(dir)) 806e66f31c5Sopenharmony_ci return UV__ERR(errno); 807e66f31c5Sopenharmony_ci 808e66f31c5Sopenharmony_ci return 0; 809e66f31c5Sopenharmony_ci} 810e66f31c5Sopenharmony_ci 811e66f31c5Sopenharmony_ci 812e66f31c5Sopenharmony_civoid uv_disable_stdio_inheritance(void) { 813e66f31c5Sopenharmony_ci int fd; 814e66f31c5Sopenharmony_ci 815e66f31c5Sopenharmony_ci /* Set the CLOEXEC flag on all open descriptors. Unconditionally try the 816e66f31c5Sopenharmony_ci * first 16 file descriptors. After that, bail out after the first error. 817e66f31c5Sopenharmony_ci */ 818e66f31c5Sopenharmony_ci for (fd = 0; ; fd++) 819e66f31c5Sopenharmony_ci if (uv__cloexec(fd, 1) && fd > 15) 820e66f31c5Sopenharmony_ci break; 821e66f31c5Sopenharmony_ci} 822e66f31c5Sopenharmony_ci 823e66f31c5Sopenharmony_ci 824e66f31c5Sopenharmony_ciint uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) { 825e66f31c5Sopenharmony_ci int fd_out; 826e66f31c5Sopenharmony_ci 827e66f31c5Sopenharmony_ci switch (handle->type) { 828e66f31c5Sopenharmony_ci case UV_TCP: 829e66f31c5Sopenharmony_ci case UV_NAMED_PIPE: 830e66f31c5Sopenharmony_ci case UV_TTY: 831e66f31c5Sopenharmony_ci fd_out = uv__stream_fd((uv_stream_t*) handle); 832e66f31c5Sopenharmony_ci break; 833e66f31c5Sopenharmony_ci 834e66f31c5Sopenharmony_ci case UV_UDP: 835e66f31c5Sopenharmony_ci fd_out = ((uv_udp_t *) handle)->io_watcher.fd; 836e66f31c5Sopenharmony_ci break; 837e66f31c5Sopenharmony_ci 838e66f31c5Sopenharmony_ci case UV_POLL: 839e66f31c5Sopenharmony_ci fd_out = ((uv_poll_t *) handle)->io_watcher.fd; 840e66f31c5Sopenharmony_ci break; 841e66f31c5Sopenharmony_ci 842e66f31c5Sopenharmony_ci default: 843e66f31c5Sopenharmony_ci return UV_EINVAL; 844e66f31c5Sopenharmony_ci } 845e66f31c5Sopenharmony_ci 846e66f31c5Sopenharmony_ci if (uv__is_closing(handle) || fd_out == -1) 847e66f31c5Sopenharmony_ci return UV_EBADF; 848e66f31c5Sopenharmony_ci 849e66f31c5Sopenharmony_ci *fd = fd_out; 850e66f31c5Sopenharmony_ci return 0; 851e66f31c5Sopenharmony_ci} 852e66f31c5Sopenharmony_ci 853e66f31c5Sopenharmony_ci 854e66f31c5Sopenharmony_cistatic void uv__run_pending(uv_loop_t* loop) { 855e66f31c5Sopenharmony_ci struct uv__queue* q; 856e66f31c5Sopenharmony_ci struct uv__queue pq; 857e66f31c5Sopenharmony_ci uv__io_t* w; 858e66f31c5Sopenharmony_ci 859e66f31c5Sopenharmony_ci uv__queue_move(&loop->pending_queue, &pq); 860e66f31c5Sopenharmony_ci 861e66f31c5Sopenharmony_ci while (!uv__queue_empty(&pq)) { 862e66f31c5Sopenharmony_ci q = uv__queue_head(&pq); 863e66f31c5Sopenharmony_ci uv__queue_remove(q); 864e66f31c5Sopenharmony_ci uv__queue_init(q); 865e66f31c5Sopenharmony_ci w = uv__queue_data(q, uv__io_t, pending_queue); 866e66f31c5Sopenharmony_ci w->cb(loop, w, POLLOUT); 867e66f31c5Sopenharmony_ci } 868e66f31c5Sopenharmony_ci} 869e66f31c5Sopenharmony_ci 870e66f31c5Sopenharmony_ci 871e66f31c5Sopenharmony_cistatic unsigned int next_power_of_two(unsigned int val) { 872e66f31c5Sopenharmony_ci val -= 1; 873e66f31c5Sopenharmony_ci val |= val >> 1; 874e66f31c5Sopenharmony_ci val |= val >> 2; 875e66f31c5Sopenharmony_ci val |= val >> 4; 876e66f31c5Sopenharmony_ci val |= val >> 8; 877e66f31c5Sopenharmony_ci val |= val >> 16; 878e66f31c5Sopenharmony_ci val += 1; 879e66f31c5Sopenharmony_ci return val; 880e66f31c5Sopenharmony_ci} 881e66f31c5Sopenharmony_ci 882e66f31c5Sopenharmony_cistatic void maybe_resize(uv_loop_t* loop, unsigned int len) { 883e66f31c5Sopenharmony_ci uv__io_t** watchers; 884e66f31c5Sopenharmony_ci void* fake_watcher_list; 885e66f31c5Sopenharmony_ci void* fake_watcher_count; 886e66f31c5Sopenharmony_ci unsigned int nwatchers; 887e66f31c5Sopenharmony_ci unsigned int i; 888e66f31c5Sopenharmony_ci 889e66f31c5Sopenharmony_ci if (len <= loop->nwatchers) 890e66f31c5Sopenharmony_ci return; 891e66f31c5Sopenharmony_ci 892e66f31c5Sopenharmony_ci /* Preserve fake watcher list and count at the end of the watchers */ 893e66f31c5Sopenharmony_ci if (loop->watchers != NULL) { 894e66f31c5Sopenharmony_ci fake_watcher_list = loop->watchers[loop->nwatchers]; 895e66f31c5Sopenharmony_ci fake_watcher_count = loop->watchers[loop->nwatchers + 1]; 896e66f31c5Sopenharmony_ci } else { 897e66f31c5Sopenharmony_ci fake_watcher_list = NULL; 898e66f31c5Sopenharmony_ci fake_watcher_count = NULL; 899e66f31c5Sopenharmony_ci } 900e66f31c5Sopenharmony_ci 901e66f31c5Sopenharmony_ci nwatchers = next_power_of_two(len + 2) - 2; 902e66f31c5Sopenharmony_ci watchers = uv__reallocf(loop->watchers, 903e66f31c5Sopenharmony_ci (nwatchers + 2) * sizeof(loop->watchers[0])); 904e66f31c5Sopenharmony_ci 905e66f31c5Sopenharmony_ci if (watchers == NULL) 906e66f31c5Sopenharmony_ci abort(); 907e66f31c5Sopenharmony_ci for (i = loop->nwatchers; i < nwatchers; i++) 908e66f31c5Sopenharmony_ci watchers[i] = NULL; 909e66f31c5Sopenharmony_ci watchers[nwatchers] = fake_watcher_list; 910e66f31c5Sopenharmony_ci watchers[nwatchers + 1] = fake_watcher_count; 911e66f31c5Sopenharmony_ci 912e66f31c5Sopenharmony_ci loop->watchers = watchers; 913e66f31c5Sopenharmony_ci loop->nwatchers = nwatchers; 914e66f31c5Sopenharmony_ci} 915e66f31c5Sopenharmony_ci 916e66f31c5Sopenharmony_ci 917e66f31c5Sopenharmony_civoid uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) { 918e66f31c5Sopenharmony_ci assert(cb != NULL); 919e66f31c5Sopenharmony_ci assert(fd >= -1); 920e66f31c5Sopenharmony_ci uv__queue_init(&w->pending_queue); 921e66f31c5Sopenharmony_ci uv__queue_init(&w->watcher_queue); 922e66f31c5Sopenharmony_ci w->cb = cb; 923e66f31c5Sopenharmony_ci w->fd = fd; 924e66f31c5Sopenharmony_ci w->events = 0; 925e66f31c5Sopenharmony_ci w->pevents = 0; 926e66f31c5Sopenharmony_ci} 927e66f31c5Sopenharmony_ci 928e66f31c5Sopenharmony_ci 929e66f31c5Sopenharmony_civoid uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) { 930e66f31c5Sopenharmony_ci assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI))); 931e66f31c5Sopenharmony_ci assert(0 != events); 932e66f31c5Sopenharmony_ci assert(w->fd >= 0); 933e66f31c5Sopenharmony_ci assert(w->fd < INT_MAX); 934e66f31c5Sopenharmony_ci 935e66f31c5Sopenharmony_ci w->pevents |= events; 936e66f31c5Sopenharmony_ci maybe_resize(loop, w->fd + 1); 937e66f31c5Sopenharmony_ci 938e66f31c5Sopenharmony_ci#if !defined(__sun) 939e66f31c5Sopenharmony_ci /* The event ports backend needs to rearm all file descriptors on each and 940e66f31c5Sopenharmony_ci * every tick of the event loop but the other backends allow us to 941e66f31c5Sopenharmony_ci * short-circuit here if the event mask is unchanged. 942e66f31c5Sopenharmony_ci */ 943e66f31c5Sopenharmony_ci if (w->events == w->pevents) 944e66f31c5Sopenharmony_ci return; 945e66f31c5Sopenharmony_ci#endif 946e66f31c5Sopenharmony_ci 947e66f31c5Sopenharmony_ci if (uv__queue_empty(&w->watcher_queue)) 948e66f31c5Sopenharmony_ci uv__queue_insert_tail(&loop->watcher_queue, &w->watcher_queue); 949e66f31c5Sopenharmony_ci 950e66f31c5Sopenharmony_ci if (loop->watchers[w->fd] == NULL) { 951e66f31c5Sopenharmony_ci loop->watchers[w->fd] = w; 952e66f31c5Sopenharmony_ci loop->nfds++; 953e66f31c5Sopenharmony_ci } 954e66f31c5Sopenharmony_ci} 955e66f31c5Sopenharmony_ci 956e66f31c5Sopenharmony_ci 957e66f31c5Sopenharmony_civoid uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) { 958e66f31c5Sopenharmony_ci assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI))); 959e66f31c5Sopenharmony_ci assert(0 != events); 960e66f31c5Sopenharmony_ci 961e66f31c5Sopenharmony_ci if (w->fd == -1) 962e66f31c5Sopenharmony_ci return; 963e66f31c5Sopenharmony_ci 964e66f31c5Sopenharmony_ci assert(w->fd >= 0); 965e66f31c5Sopenharmony_ci 966e66f31c5Sopenharmony_ci /* Happens when uv__io_stop() is called on a handle that was never started. */ 967e66f31c5Sopenharmony_ci if ((unsigned) w->fd >= loop->nwatchers) 968e66f31c5Sopenharmony_ci return; 969e66f31c5Sopenharmony_ci 970e66f31c5Sopenharmony_ci w->pevents &= ~events; 971e66f31c5Sopenharmony_ci 972e66f31c5Sopenharmony_ci if (w->pevents == 0) { 973e66f31c5Sopenharmony_ci uv__queue_remove(&w->watcher_queue); 974e66f31c5Sopenharmony_ci uv__queue_init(&w->watcher_queue); 975e66f31c5Sopenharmony_ci w->events = 0; 976e66f31c5Sopenharmony_ci 977e66f31c5Sopenharmony_ci if (w == loop->watchers[w->fd]) { 978e66f31c5Sopenharmony_ci assert(loop->nfds > 0); 979e66f31c5Sopenharmony_ci loop->watchers[w->fd] = NULL; 980e66f31c5Sopenharmony_ci loop->nfds--; 981e66f31c5Sopenharmony_ci } 982e66f31c5Sopenharmony_ci } 983e66f31c5Sopenharmony_ci else if (uv__queue_empty(&w->watcher_queue)) 984e66f31c5Sopenharmony_ci uv__queue_insert_tail(&loop->watcher_queue, &w->watcher_queue); 985e66f31c5Sopenharmony_ci} 986e66f31c5Sopenharmony_ci 987e66f31c5Sopenharmony_ci 988e66f31c5Sopenharmony_civoid uv__io_close(uv_loop_t* loop, uv__io_t* w) { 989e66f31c5Sopenharmony_ci uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI); 990e66f31c5Sopenharmony_ci uv__queue_remove(&w->pending_queue); 991e66f31c5Sopenharmony_ci 992e66f31c5Sopenharmony_ci /* Remove stale events for this file descriptor */ 993e66f31c5Sopenharmony_ci if (w->fd != -1) 994e66f31c5Sopenharmony_ci uv__platform_invalidate_fd(loop, w->fd); 995e66f31c5Sopenharmony_ci} 996e66f31c5Sopenharmony_ci 997e66f31c5Sopenharmony_ci 998e66f31c5Sopenharmony_civoid uv__io_feed(uv_loop_t* loop, uv__io_t* w) { 999e66f31c5Sopenharmony_ci if (uv__queue_empty(&w->pending_queue)) 1000e66f31c5Sopenharmony_ci uv__queue_insert_tail(&loop->pending_queue, &w->pending_queue); 1001e66f31c5Sopenharmony_ci} 1002e66f31c5Sopenharmony_ci 1003e66f31c5Sopenharmony_ci 1004e66f31c5Sopenharmony_ciint uv__io_active(const uv__io_t* w, unsigned int events) { 1005e66f31c5Sopenharmony_ci assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI))); 1006e66f31c5Sopenharmony_ci assert(0 != events); 1007e66f31c5Sopenharmony_ci return 0 != (w->pevents & events); 1008e66f31c5Sopenharmony_ci} 1009e66f31c5Sopenharmony_ci 1010e66f31c5Sopenharmony_ci 1011e66f31c5Sopenharmony_ciint uv__fd_exists(uv_loop_t* loop, int fd) { 1012e66f31c5Sopenharmony_ci return (unsigned) fd < loop->nwatchers && loop->watchers[fd] != NULL; 1013e66f31c5Sopenharmony_ci} 1014e66f31c5Sopenharmony_ci 1015e66f31c5Sopenharmony_ci 1016e66f31c5Sopenharmony_ciint uv_getrusage(uv_rusage_t* rusage) { 1017e66f31c5Sopenharmony_ci struct rusage usage; 1018e66f31c5Sopenharmony_ci 1019e66f31c5Sopenharmony_ci if (getrusage(RUSAGE_SELF, &usage)) 1020e66f31c5Sopenharmony_ci return UV__ERR(errno); 1021e66f31c5Sopenharmony_ci 1022e66f31c5Sopenharmony_ci rusage->ru_utime.tv_sec = usage.ru_utime.tv_sec; 1023e66f31c5Sopenharmony_ci rusage->ru_utime.tv_usec = usage.ru_utime.tv_usec; 1024e66f31c5Sopenharmony_ci 1025e66f31c5Sopenharmony_ci rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec; 1026e66f31c5Sopenharmony_ci rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec; 1027e66f31c5Sopenharmony_ci 1028e66f31c5Sopenharmony_ci#if !defined(__MVS__) && !defined(__HAIKU__) 1029e66f31c5Sopenharmony_ci rusage->ru_maxrss = usage.ru_maxrss; 1030e66f31c5Sopenharmony_ci rusage->ru_ixrss = usage.ru_ixrss; 1031e66f31c5Sopenharmony_ci rusage->ru_idrss = usage.ru_idrss; 1032e66f31c5Sopenharmony_ci rusage->ru_isrss = usage.ru_isrss; 1033e66f31c5Sopenharmony_ci rusage->ru_minflt = usage.ru_minflt; 1034e66f31c5Sopenharmony_ci rusage->ru_majflt = usage.ru_majflt; 1035e66f31c5Sopenharmony_ci rusage->ru_nswap = usage.ru_nswap; 1036e66f31c5Sopenharmony_ci rusage->ru_inblock = usage.ru_inblock; 1037e66f31c5Sopenharmony_ci rusage->ru_oublock = usage.ru_oublock; 1038e66f31c5Sopenharmony_ci rusage->ru_msgsnd = usage.ru_msgsnd; 1039e66f31c5Sopenharmony_ci rusage->ru_msgrcv = usage.ru_msgrcv; 1040e66f31c5Sopenharmony_ci rusage->ru_nsignals = usage.ru_nsignals; 1041e66f31c5Sopenharmony_ci rusage->ru_nvcsw = usage.ru_nvcsw; 1042e66f31c5Sopenharmony_ci rusage->ru_nivcsw = usage.ru_nivcsw; 1043e66f31c5Sopenharmony_ci#endif 1044e66f31c5Sopenharmony_ci 1045e66f31c5Sopenharmony_ci /* Most platforms report ru_maxrss in kilobytes; macOS and Solaris are 1046e66f31c5Sopenharmony_ci * the outliers because of course they are. 1047e66f31c5Sopenharmony_ci */ 1048e66f31c5Sopenharmony_ci#if defined(__APPLE__) 1049e66f31c5Sopenharmony_ci rusage->ru_maxrss /= 1024; /* macOS and iOS report bytes. */ 1050e66f31c5Sopenharmony_ci#elif defined(__sun) 1051e66f31c5Sopenharmony_ci rusage->ru_maxrss /= getpagesize() / 1024; /* Solaris reports pages. */ 1052e66f31c5Sopenharmony_ci#endif 1053e66f31c5Sopenharmony_ci 1054e66f31c5Sopenharmony_ci return 0; 1055e66f31c5Sopenharmony_ci} 1056e66f31c5Sopenharmony_ci 1057e66f31c5Sopenharmony_ci 1058e66f31c5Sopenharmony_ciint uv__open_cloexec(const char* path, int flags) { 1059e66f31c5Sopenharmony_ci#if defined(O_CLOEXEC) 1060e66f31c5Sopenharmony_ci int fd; 1061e66f31c5Sopenharmony_ci 1062e66f31c5Sopenharmony_ci fd = open(path, flags | O_CLOEXEC); 1063e66f31c5Sopenharmony_ci if (fd == -1) 1064e66f31c5Sopenharmony_ci return UV__ERR(errno); 1065e66f31c5Sopenharmony_ci 1066e66f31c5Sopenharmony_ci return fd; 1067e66f31c5Sopenharmony_ci#else /* O_CLOEXEC */ 1068e66f31c5Sopenharmony_ci int err; 1069e66f31c5Sopenharmony_ci int fd; 1070e66f31c5Sopenharmony_ci 1071e66f31c5Sopenharmony_ci fd = open(path, flags); 1072e66f31c5Sopenharmony_ci if (fd == -1) 1073e66f31c5Sopenharmony_ci return UV__ERR(errno); 1074e66f31c5Sopenharmony_ci 1075e66f31c5Sopenharmony_ci err = uv__cloexec(fd, 1); 1076e66f31c5Sopenharmony_ci if (err) { 1077e66f31c5Sopenharmony_ci uv__close(fd); 1078e66f31c5Sopenharmony_ci return err; 1079e66f31c5Sopenharmony_ci } 1080e66f31c5Sopenharmony_ci 1081e66f31c5Sopenharmony_ci return fd; 1082e66f31c5Sopenharmony_ci#endif /* O_CLOEXEC */ 1083e66f31c5Sopenharmony_ci} 1084e66f31c5Sopenharmony_ci 1085e66f31c5Sopenharmony_ci 1086e66f31c5Sopenharmony_ciint uv__slurp(const char* filename, char* buf, size_t len) { 1087e66f31c5Sopenharmony_ci ssize_t n; 1088e66f31c5Sopenharmony_ci int fd; 1089e66f31c5Sopenharmony_ci 1090e66f31c5Sopenharmony_ci assert(len > 0); 1091e66f31c5Sopenharmony_ci 1092e66f31c5Sopenharmony_ci fd = uv__open_cloexec(filename, O_RDONLY); 1093e66f31c5Sopenharmony_ci if (fd < 0) 1094e66f31c5Sopenharmony_ci return fd; 1095e66f31c5Sopenharmony_ci 1096e66f31c5Sopenharmony_ci do 1097e66f31c5Sopenharmony_ci n = read(fd, buf, len - 1); 1098e66f31c5Sopenharmony_ci while (n == -1 && errno == EINTR); 1099e66f31c5Sopenharmony_ci 1100e66f31c5Sopenharmony_ci if (uv__close_nocheckstdio(fd)) 1101e66f31c5Sopenharmony_ci abort(); 1102e66f31c5Sopenharmony_ci 1103e66f31c5Sopenharmony_ci if (n < 0) 1104e66f31c5Sopenharmony_ci return UV__ERR(errno); 1105e66f31c5Sopenharmony_ci 1106e66f31c5Sopenharmony_ci buf[n] = '\0'; 1107e66f31c5Sopenharmony_ci 1108e66f31c5Sopenharmony_ci return 0; 1109e66f31c5Sopenharmony_ci} 1110e66f31c5Sopenharmony_ci 1111e66f31c5Sopenharmony_ci 1112e66f31c5Sopenharmony_ciint uv__dup2_cloexec(int oldfd, int newfd) { 1113e66f31c5Sopenharmony_ci#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__linux__) 1114e66f31c5Sopenharmony_ci int r; 1115e66f31c5Sopenharmony_ci 1116e66f31c5Sopenharmony_ci r = dup3(oldfd, newfd, O_CLOEXEC); 1117e66f31c5Sopenharmony_ci if (r == -1) 1118e66f31c5Sopenharmony_ci return UV__ERR(errno); 1119e66f31c5Sopenharmony_ci 1120e66f31c5Sopenharmony_ci return r; 1121e66f31c5Sopenharmony_ci#else 1122e66f31c5Sopenharmony_ci int err; 1123e66f31c5Sopenharmony_ci int r; 1124e66f31c5Sopenharmony_ci 1125e66f31c5Sopenharmony_ci r = dup2(oldfd, newfd); /* Never retry. */ 1126e66f31c5Sopenharmony_ci if (r == -1) 1127e66f31c5Sopenharmony_ci return UV__ERR(errno); 1128e66f31c5Sopenharmony_ci 1129e66f31c5Sopenharmony_ci err = uv__cloexec(newfd, 1); 1130e66f31c5Sopenharmony_ci if (err != 0) { 1131e66f31c5Sopenharmony_ci uv__close(newfd); 1132e66f31c5Sopenharmony_ci return err; 1133e66f31c5Sopenharmony_ci } 1134e66f31c5Sopenharmony_ci 1135e66f31c5Sopenharmony_ci return r; 1136e66f31c5Sopenharmony_ci#endif 1137e66f31c5Sopenharmony_ci} 1138e66f31c5Sopenharmony_ci 1139e66f31c5Sopenharmony_ci 1140e66f31c5Sopenharmony_ciint uv_os_homedir(char* buffer, size_t* size) { 1141e66f31c5Sopenharmony_ci uv_passwd_t pwd; 1142e66f31c5Sopenharmony_ci size_t len; 1143e66f31c5Sopenharmony_ci int r; 1144e66f31c5Sopenharmony_ci 1145e66f31c5Sopenharmony_ci /* Check if the HOME environment variable is set first. The task of 1146e66f31c5Sopenharmony_ci performing input validation on buffer and size is taken care of by 1147e66f31c5Sopenharmony_ci uv_os_getenv(). */ 1148e66f31c5Sopenharmony_ci r = uv_os_getenv("HOME", buffer, size); 1149e66f31c5Sopenharmony_ci 1150e66f31c5Sopenharmony_ci if (r != UV_ENOENT) 1151e66f31c5Sopenharmony_ci return r; 1152e66f31c5Sopenharmony_ci 1153e66f31c5Sopenharmony_ci /* HOME is not set, so call uv_os_get_passwd() */ 1154e66f31c5Sopenharmony_ci r = uv_os_get_passwd(&pwd); 1155e66f31c5Sopenharmony_ci 1156e66f31c5Sopenharmony_ci if (r != 0) { 1157e66f31c5Sopenharmony_ci return r; 1158e66f31c5Sopenharmony_ci } 1159e66f31c5Sopenharmony_ci 1160e66f31c5Sopenharmony_ci len = strlen(pwd.homedir); 1161e66f31c5Sopenharmony_ci 1162e66f31c5Sopenharmony_ci if (len >= *size) { 1163e66f31c5Sopenharmony_ci *size = len + 1; 1164e66f31c5Sopenharmony_ci uv_os_free_passwd(&pwd); 1165e66f31c5Sopenharmony_ci return UV_ENOBUFS; 1166e66f31c5Sopenharmony_ci } 1167e66f31c5Sopenharmony_ci 1168e66f31c5Sopenharmony_ci memcpy(buffer, pwd.homedir, len + 1); 1169e66f31c5Sopenharmony_ci *size = len; 1170e66f31c5Sopenharmony_ci uv_os_free_passwd(&pwd); 1171e66f31c5Sopenharmony_ci 1172e66f31c5Sopenharmony_ci return 0; 1173e66f31c5Sopenharmony_ci} 1174e66f31c5Sopenharmony_ci 1175e66f31c5Sopenharmony_ci 1176e66f31c5Sopenharmony_ciint uv_os_tmpdir(char* buffer, size_t* size) { 1177e66f31c5Sopenharmony_ci const char* buf; 1178e66f31c5Sopenharmony_ci size_t len; 1179e66f31c5Sopenharmony_ci 1180e66f31c5Sopenharmony_ci if (buffer == NULL || size == NULL || *size == 0) 1181e66f31c5Sopenharmony_ci return UV_EINVAL; 1182e66f31c5Sopenharmony_ci 1183e66f31c5Sopenharmony_ci#define CHECK_ENV_VAR(name) \ 1184e66f31c5Sopenharmony_ci do { \ 1185e66f31c5Sopenharmony_ci buf = getenv(name); \ 1186e66f31c5Sopenharmony_ci if (buf != NULL) \ 1187e66f31c5Sopenharmony_ci goto return_buffer; \ 1188e66f31c5Sopenharmony_ci } \ 1189e66f31c5Sopenharmony_ci while (0) 1190e66f31c5Sopenharmony_ci 1191e66f31c5Sopenharmony_ci /* Check the TMPDIR, TMP, TEMP, and TEMPDIR environment variables in order */ 1192e66f31c5Sopenharmony_ci CHECK_ENV_VAR("TMPDIR"); 1193e66f31c5Sopenharmony_ci CHECK_ENV_VAR("TMP"); 1194e66f31c5Sopenharmony_ci CHECK_ENV_VAR("TEMP"); 1195e66f31c5Sopenharmony_ci CHECK_ENV_VAR("TEMPDIR"); 1196e66f31c5Sopenharmony_ci 1197e66f31c5Sopenharmony_ci#undef CHECK_ENV_VAR 1198e66f31c5Sopenharmony_ci 1199e66f31c5Sopenharmony_ci /* No temp environment variables defined */ 1200e66f31c5Sopenharmony_ci #if defined(__ANDROID__) 1201e66f31c5Sopenharmony_ci buf = "/data/local/tmp"; 1202e66f31c5Sopenharmony_ci #else 1203e66f31c5Sopenharmony_ci buf = "/tmp"; 1204e66f31c5Sopenharmony_ci #endif 1205e66f31c5Sopenharmony_ci 1206e66f31c5Sopenharmony_cireturn_buffer: 1207e66f31c5Sopenharmony_ci len = strlen(buf); 1208e66f31c5Sopenharmony_ci 1209e66f31c5Sopenharmony_ci if (len >= *size) { 1210e66f31c5Sopenharmony_ci *size = len + 1; 1211e66f31c5Sopenharmony_ci return UV_ENOBUFS; 1212e66f31c5Sopenharmony_ci } 1213e66f31c5Sopenharmony_ci 1214e66f31c5Sopenharmony_ci /* The returned directory should not have a trailing slash. */ 1215e66f31c5Sopenharmony_ci if (len > 1 && buf[len - 1] == '/') { 1216e66f31c5Sopenharmony_ci len--; 1217e66f31c5Sopenharmony_ci } 1218e66f31c5Sopenharmony_ci 1219e66f31c5Sopenharmony_ci memcpy(buffer, buf, len + 1); 1220e66f31c5Sopenharmony_ci buffer[len] = '\0'; 1221e66f31c5Sopenharmony_ci *size = len; 1222e66f31c5Sopenharmony_ci 1223e66f31c5Sopenharmony_ci return 0; 1224e66f31c5Sopenharmony_ci} 1225e66f31c5Sopenharmony_ci 1226e66f31c5Sopenharmony_ci 1227e66f31c5Sopenharmony_cistatic int uv__getpwuid_r(uv_passwd_t *pwd, uid_t uid) { 1228e66f31c5Sopenharmony_ci struct passwd pw; 1229e66f31c5Sopenharmony_ci struct passwd* result; 1230e66f31c5Sopenharmony_ci char* buf; 1231e66f31c5Sopenharmony_ci size_t bufsize; 1232e66f31c5Sopenharmony_ci size_t name_size; 1233e66f31c5Sopenharmony_ci size_t homedir_size; 1234e66f31c5Sopenharmony_ci size_t shell_size; 1235e66f31c5Sopenharmony_ci int r; 1236e66f31c5Sopenharmony_ci 1237e66f31c5Sopenharmony_ci if (pwd == NULL) 1238e66f31c5Sopenharmony_ci return UV_EINVAL; 1239e66f31c5Sopenharmony_ci 1240e66f31c5Sopenharmony_ci /* Calling sysconf(_SC_GETPW_R_SIZE_MAX) would get the suggested size, but it 1241e66f31c5Sopenharmony_ci * is frequently 1024 or 4096, so we can just use that directly. The pwent 1242e66f31c5Sopenharmony_ci * will not usually be large. */ 1243e66f31c5Sopenharmony_ci for (bufsize = 2000;; bufsize *= 2) { 1244e66f31c5Sopenharmony_ci buf = uv__malloc(bufsize); 1245e66f31c5Sopenharmony_ci 1246e66f31c5Sopenharmony_ci if (buf == NULL) 1247e66f31c5Sopenharmony_ci return UV_ENOMEM; 1248e66f31c5Sopenharmony_ci 1249e66f31c5Sopenharmony_ci do 1250e66f31c5Sopenharmony_ci r = getpwuid_r(uid, &pw, buf, bufsize, &result); 1251e66f31c5Sopenharmony_ci while (r == EINTR); 1252e66f31c5Sopenharmony_ci 1253e66f31c5Sopenharmony_ci if (r != 0 || result == NULL) 1254e66f31c5Sopenharmony_ci uv__free(buf); 1255e66f31c5Sopenharmony_ci 1256e66f31c5Sopenharmony_ci if (r != ERANGE) 1257e66f31c5Sopenharmony_ci break; 1258e66f31c5Sopenharmony_ci } 1259e66f31c5Sopenharmony_ci 1260e66f31c5Sopenharmony_ci if (r != 0) 1261e66f31c5Sopenharmony_ci return UV__ERR(r); 1262e66f31c5Sopenharmony_ci 1263e66f31c5Sopenharmony_ci if (result == NULL) 1264e66f31c5Sopenharmony_ci return UV_ENOENT; 1265e66f31c5Sopenharmony_ci 1266e66f31c5Sopenharmony_ci /* Allocate memory for the username, shell, and home directory */ 1267e66f31c5Sopenharmony_ci name_size = strlen(pw.pw_name) + 1; 1268e66f31c5Sopenharmony_ci homedir_size = strlen(pw.pw_dir) + 1; 1269e66f31c5Sopenharmony_ci shell_size = strlen(pw.pw_shell) + 1; 1270e66f31c5Sopenharmony_ci pwd->username = uv__malloc(name_size + homedir_size + shell_size); 1271e66f31c5Sopenharmony_ci 1272e66f31c5Sopenharmony_ci if (pwd->username == NULL) { 1273e66f31c5Sopenharmony_ci uv__free(buf); 1274e66f31c5Sopenharmony_ci return UV_ENOMEM; 1275e66f31c5Sopenharmony_ci } 1276e66f31c5Sopenharmony_ci 1277e66f31c5Sopenharmony_ci /* Copy the username */ 1278e66f31c5Sopenharmony_ci memcpy(pwd->username, pw.pw_name, name_size); 1279e66f31c5Sopenharmony_ci 1280e66f31c5Sopenharmony_ci /* Copy the home directory */ 1281e66f31c5Sopenharmony_ci pwd->homedir = pwd->username + name_size; 1282e66f31c5Sopenharmony_ci memcpy(pwd->homedir, pw.pw_dir, homedir_size); 1283e66f31c5Sopenharmony_ci 1284e66f31c5Sopenharmony_ci /* Copy the shell */ 1285e66f31c5Sopenharmony_ci pwd->shell = pwd->homedir + homedir_size; 1286e66f31c5Sopenharmony_ci memcpy(pwd->shell, pw.pw_shell, shell_size); 1287e66f31c5Sopenharmony_ci 1288e66f31c5Sopenharmony_ci /* Copy the uid and gid */ 1289e66f31c5Sopenharmony_ci pwd->uid = pw.pw_uid; 1290e66f31c5Sopenharmony_ci pwd->gid = pw.pw_gid; 1291e66f31c5Sopenharmony_ci 1292e66f31c5Sopenharmony_ci uv__free(buf); 1293e66f31c5Sopenharmony_ci 1294e66f31c5Sopenharmony_ci return 0; 1295e66f31c5Sopenharmony_ci} 1296e66f31c5Sopenharmony_ci 1297e66f31c5Sopenharmony_ci 1298e66f31c5Sopenharmony_ciint uv_os_get_group(uv_group_t* grp, uv_uid_t gid) { 1299e66f31c5Sopenharmony_ci#if defined(__ANDROID__) && __ANDROID_API__ < 24 1300e66f31c5Sopenharmony_ci /* This function getgrgid_r() was added in Android N (level 24) */ 1301e66f31c5Sopenharmony_ci return UV_ENOSYS; 1302e66f31c5Sopenharmony_ci#else 1303e66f31c5Sopenharmony_ci struct group gp; 1304e66f31c5Sopenharmony_ci struct group* result; 1305e66f31c5Sopenharmony_ci char* buf; 1306e66f31c5Sopenharmony_ci char* gr_mem; 1307e66f31c5Sopenharmony_ci size_t bufsize; 1308e66f31c5Sopenharmony_ci size_t name_size; 1309e66f31c5Sopenharmony_ci long members; 1310e66f31c5Sopenharmony_ci size_t mem_size; 1311e66f31c5Sopenharmony_ci int r; 1312e66f31c5Sopenharmony_ci 1313e66f31c5Sopenharmony_ci if (grp == NULL) 1314e66f31c5Sopenharmony_ci return UV_EINVAL; 1315e66f31c5Sopenharmony_ci 1316e66f31c5Sopenharmony_ci /* Calling sysconf(_SC_GETGR_R_SIZE_MAX) would get the suggested size, but it 1317e66f31c5Sopenharmony_ci * is frequently 1024 or 4096, so we can just use that directly. The pwent 1318e66f31c5Sopenharmony_ci * will not usually be large. */ 1319e66f31c5Sopenharmony_ci for (bufsize = 2000;; bufsize *= 2) { 1320e66f31c5Sopenharmony_ci buf = uv__malloc(bufsize); 1321e66f31c5Sopenharmony_ci 1322e66f31c5Sopenharmony_ci if (buf == NULL) 1323e66f31c5Sopenharmony_ci return UV_ENOMEM; 1324e66f31c5Sopenharmony_ci 1325e66f31c5Sopenharmony_ci do 1326e66f31c5Sopenharmony_ci r = getgrgid_r(gid, &gp, buf, bufsize, &result); 1327e66f31c5Sopenharmony_ci while (r == EINTR); 1328e66f31c5Sopenharmony_ci 1329e66f31c5Sopenharmony_ci if (r != 0 || result == NULL) 1330e66f31c5Sopenharmony_ci uv__free(buf); 1331e66f31c5Sopenharmony_ci 1332e66f31c5Sopenharmony_ci if (r != ERANGE) 1333e66f31c5Sopenharmony_ci break; 1334e66f31c5Sopenharmony_ci } 1335e66f31c5Sopenharmony_ci 1336e66f31c5Sopenharmony_ci if (r != 0) 1337e66f31c5Sopenharmony_ci return UV__ERR(r); 1338e66f31c5Sopenharmony_ci 1339e66f31c5Sopenharmony_ci if (result == NULL) 1340e66f31c5Sopenharmony_ci return UV_ENOENT; 1341e66f31c5Sopenharmony_ci 1342e66f31c5Sopenharmony_ci /* Allocate memory for the groupname and members. */ 1343e66f31c5Sopenharmony_ci name_size = strlen(gp.gr_name) + 1; 1344e66f31c5Sopenharmony_ci members = 0; 1345e66f31c5Sopenharmony_ci mem_size = sizeof(char*); 1346e66f31c5Sopenharmony_ci for (r = 0; gp.gr_mem[r] != NULL; r++) { 1347e66f31c5Sopenharmony_ci mem_size += strlen(gp.gr_mem[r]) + 1 + sizeof(char*); 1348e66f31c5Sopenharmony_ci members++; 1349e66f31c5Sopenharmony_ci } 1350e66f31c5Sopenharmony_ci 1351e66f31c5Sopenharmony_ci gr_mem = uv__malloc(name_size + mem_size); 1352e66f31c5Sopenharmony_ci if (gr_mem == NULL) { 1353e66f31c5Sopenharmony_ci uv__free(buf); 1354e66f31c5Sopenharmony_ci return UV_ENOMEM; 1355e66f31c5Sopenharmony_ci } 1356e66f31c5Sopenharmony_ci 1357e66f31c5Sopenharmony_ci /* Copy the members */ 1358e66f31c5Sopenharmony_ci grp->members = (char**) gr_mem; 1359e66f31c5Sopenharmony_ci grp->members[members] = NULL; 1360e66f31c5Sopenharmony_ci gr_mem = (char*) &grp->members[members + 1]; 1361e66f31c5Sopenharmony_ci for (r = 0; r < members; r++) { 1362e66f31c5Sopenharmony_ci grp->members[r] = gr_mem; 1363e66f31c5Sopenharmony_ci strcpy(gr_mem, gp.gr_mem[r]); 1364e66f31c5Sopenharmony_ci gr_mem += strlen(gr_mem) + 1; 1365e66f31c5Sopenharmony_ci } 1366e66f31c5Sopenharmony_ci assert(gr_mem == (char*)grp->members + mem_size); 1367e66f31c5Sopenharmony_ci 1368e66f31c5Sopenharmony_ci /* Copy the groupname */ 1369e66f31c5Sopenharmony_ci grp->groupname = gr_mem; 1370e66f31c5Sopenharmony_ci memcpy(grp->groupname, gp.gr_name, name_size); 1371e66f31c5Sopenharmony_ci gr_mem += name_size; 1372e66f31c5Sopenharmony_ci 1373e66f31c5Sopenharmony_ci /* Copy the gid */ 1374e66f31c5Sopenharmony_ci grp->gid = gp.gr_gid; 1375e66f31c5Sopenharmony_ci 1376e66f31c5Sopenharmony_ci uv__free(buf); 1377e66f31c5Sopenharmony_ci 1378e66f31c5Sopenharmony_ci return 0; 1379e66f31c5Sopenharmony_ci#endif 1380e66f31c5Sopenharmony_ci} 1381e66f31c5Sopenharmony_ci 1382e66f31c5Sopenharmony_ci 1383e66f31c5Sopenharmony_ciint uv_os_get_passwd(uv_passwd_t* pwd) { 1384e66f31c5Sopenharmony_ci return uv__getpwuid_r(pwd, geteuid()); 1385e66f31c5Sopenharmony_ci} 1386e66f31c5Sopenharmony_ci 1387e66f31c5Sopenharmony_ci 1388e66f31c5Sopenharmony_ciint uv_os_get_passwd2(uv_passwd_t* pwd, uv_uid_t uid) { 1389e66f31c5Sopenharmony_ci return uv__getpwuid_r(pwd, uid); 1390e66f31c5Sopenharmony_ci} 1391e66f31c5Sopenharmony_ci 1392e66f31c5Sopenharmony_ci 1393e66f31c5Sopenharmony_ciint uv_translate_sys_error(int sys_errno) { 1394e66f31c5Sopenharmony_ci /* If < 0 then it's already a libuv error. */ 1395e66f31c5Sopenharmony_ci return sys_errno <= 0 ? sys_errno : -sys_errno; 1396e66f31c5Sopenharmony_ci} 1397e66f31c5Sopenharmony_ci 1398e66f31c5Sopenharmony_ci 1399e66f31c5Sopenharmony_ciint uv_os_environ(uv_env_item_t** envitems, int* count) { 1400e66f31c5Sopenharmony_ci int i, j, cnt; 1401e66f31c5Sopenharmony_ci uv_env_item_t* envitem; 1402e66f31c5Sopenharmony_ci 1403e66f31c5Sopenharmony_ci *envitems = NULL; 1404e66f31c5Sopenharmony_ci *count = 0; 1405e66f31c5Sopenharmony_ci 1406e66f31c5Sopenharmony_ci for (i = 0; environ[i] != NULL; i++); 1407e66f31c5Sopenharmony_ci 1408e66f31c5Sopenharmony_ci *envitems = uv__calloc(i, sizeof(**envitems)); 1409e66f31c5Sopenharmony_ci 1410e66f31c5Sopenharmony_ci if (*envitems == NULL) 1411e66f31c5Sopenharmony_ci return UV_ENOMEM; 1412e66f31c5Sopenharmony_ci 1413e66f31c5Sopenharmony_ci for (j = 0, cnt = 0; j < i; j++) { 1414e66f31c5Sopenharmony_ci char* buf; 1415e66f31c5Sopenharmony_ci char* ptr; 1416e66f31c5Sopenharmony_ci 1417e66f31c5Sopenharmony_ci if (environ[j] == NULL) 1418e66f31c5Sopenharmony_ci break; 1419e66f31c5Sopenharmony_ci 1420e66f31c5Sopenharmony_ci buf = uv__strdup(environ[j]); 1421e66f31c5Sopenharmony_ci if (buf == NULL) 1422e66f31c5Sopenharmony_ci goto fail; 1423e66f31c5Sopenharmony_ci 1424e66f31c5Sopenharmony_ci ptr = strchr(buf, '='); 1425e66f31c5Sopenharmony_ci if (ptr == NULL) { 1426e66f31c5Sopenharmony_ci uv__free(buf); 1427e66f31c5Sopenharmony_ci continue; 1428e66f31c5Sopenharmony_ci } 1429e66f31c5Sopenharmony_ci 1430e66f31c5Sopenharmony_ci *ptr = '\0'; 1431e66f31c5Sopenharmony_ci 1432e66f31c5Sopenharmony_ci envitem = &(*envitems)[cnt]; 1433e66f31c5Sopenharmony_ci envitem->name = buf; 1434e66f31c5Sopenharmony_ci envitem->value = ptr + 1; 1435e66f31c5Sopenharmony_ci 1436e66f31c5Sopenharmony_ci cnt++; 1437e66f31c5Sopenharmony_ci } 1438e66f31c5Sopenharmony_ci 1439e66f31c5Sopenharmony_ci *count = cnt; 1440e66f31c5Sopenharmony_ci return 0; 1441e66f31c5Sopenharmony_ci 1442e66f31c5Sopenharmony_cifail: 1443e66f31c5Sopenharmony_ci for (i = 0; i < cnt; i++) { 1444e66f31c5Sopenharmony_ci envitem = &(*envitems)[cnt]; 1445e66f31c5Sopenharmony_ci uv__free(envitem->name); 1446e66f31c5Sopenharmony_ci } 1447e66f31c5Sopenharmony_ci uv__free(*envitems); 1448e66f31c5Sopenharmony_ci 1449e66f31c5Sopenharmony_ci *envitems = NULL; 1450e66f31c5Sopenharmony_ci *count = 0; 1451e66f31c5Sopenharmony_ci return UV_ENOMEM; 1452e66f31c5Sopenharmony_ci} 1453e66f31c5Sopenharmony_ci 1454e66f31c5Sopenharmony_ci 1455e66f31c5Sopenharmony_ciint uv_os_getenv(const char* name, char* buffer, size_t* size) { 1456e66f31c5Sopenharmony_ci char* var; 1457e66f31c5Sopenharmony_ci size_t len; 1458e66f31c5Sopenharmony_ci 1459e66f31c5Sopenharmony_ci if (name == NULL || buffer == NULL || size == NULL || *size == 0) 1460e66f31c5Sopenharmony_ci return UV_EINVAL; 1461e66f31c5Sopenharmony_ci 1462e66f31c5Sopenharmony_ci var = getenv(name); 1463e66f31c5Sopenharmony_ci 1464e66f31c5Sopenharmony_ci if (var == NULL) 1465e66f31c5Sopenharmony_ci return UV_ENOENT; 1466e66f31c5Sopenharmony_ci 1467e66f31c5Sopenharmony_ci len = strlen(var); 1468e66f31c5Sopenharmony_ci 1469e66f31c5Sopenharmony_ci if (len >= *size) { 1470e66f31c5Sopenharmony_ci *size = len + 1; 1471e66f31c5Sopenharmony_ci return UV_ENOBUFS; 1472e66f31c5Sopenharmony_ci } 1473e66f31c5Sopenharmony_ci 1474e66f31c5Sopenharmony_ci memcpy(buffer, var, len + 1); 1475e66f31c5Sopenharmony_ci *size = len; 1476e66f31c5Sopenharmony_ci 1477e66f31c5Sopenharmony_ci return 0; 1478e66f31c5Sopenharmony_ci} 1479e66f31c5Sopenharmony_ci 1480e66f31c5Sopenharmony_ci 1481e66f31c5Sopenharmony_ciint uv_os_setenv(const char* name, const char* value) { 1482e66f31c5Sopenharmony_ci if (name == NULL || value == NULL) 1483e66f31c5Sopenharmony_ci return UV_EINVAL; 1484e66f31c5Sopenharmony_ci 1485e66f31c5Sopenharmony_ci if (setenv(name, value, 1) != 0) 1486e66f31c5Sopenharmony_ci return UV__ERR(errno); 1487e66f31c5Sopenharmony_ci 1488e66f31c5Sopenharmony_ci return 0; 1489e66f31c5Sopenharmony_ci} 1490e66f31c5Sopenharmony_ci 1491e66f31c5Sopenharmony_ci 1492e66f31c5Sopenharmony_ciint uv_os_unsetenv(const char* name) { 1493e66f31c5Sopenharmony_ci if (name == NULL) 1494e66f31c5Sopenharmony_ci return UV_EINVAL; 1495e66f31c5Sopenharmony_ci 1496e66f31c5Sopenharmony_ci if (unsetenv(name) != 0) 1497e66f31c5Sopenharmony_ci return UV__ERR(errno); 1498e66f31c5Sopenharmony_ci 1499e66f31c5Sopenharmony_ci return 0; 1500e66f31c5Sopenharmony_ci} 1501e66f31c5Sopenharmony_ci 1502e66f31c5Sopenharmony_ci 1503e66f31c5Sopenharmony_ciint uv_os_gethostname(char* buffer, size_t* size) { 1504e66f31c5Sopenharmony_ci /* 1505e66f31c5Sopenharmony_ci On some platforms, if the input buffer is not large enough, gethostname() 1506e66f31c5Sopenharmony_ci succeeds, but truncates the result. libuv can detect this and return ENOBUFS 1507e66f31c5Sopenharmony_ci instead by creating a large enough buffer and comparing the hostname length 1508e66f31c5Sopenharmony_ci to the size input. 1509e66f31c5Sopenharmony_ci */ 1510e66f31c5Sopenharmony_ci char buf[UV_MAXHOSTNAMESIZE]; 1511e66f31c5Sopenharmony_ci size_t len; 1512e66f31c5Sopenharmony_ci 1513e66f31c5Sopenharmony_ci if (buffer == NULL || size == NULL || *size == 0) 1514e66f31c5Sopenharmony_ci return UV_EINVAL; 1515e66f31c5Sopenharmony_ci 1516e66f31c5Sopenharmony_ci if (gethostname(buf, sizeof(buf)) != 0) 1517e66f31c5Sopenharmony_ci return UV__ERR(errno); 1518e66f31c5Sopenharmony_ci 1519e66f31c5Sopenharmony_ci buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */ 1520e66f31c5Sopenharmony_ci len = strlen(buf); 1521e66f31c5Sopenharmony_ci 1522e66f31c5Sopenharmony_ci if (len >= *size) { 1523e66f31c5Sopenharmony_ci *size = len + 1; 1524e66f31c5Sopenharmony_ci return UV_ENOBUFS; 1525e66f31c5Sopenharmony_ci } 1526e66f31c5Sopenharmony_ci 1527e66f31c5Sopenharmony_ci memcpy(buffer, buf, len + 1); 1528e66f31c5Sopenharmony_ci *size = len; 1529e66f31c5Sopenharmony_ci return 0; 1530e66f31c5Sopenharmony_ci} 1531e66f31c5Sopenharmony_ci 1532e66f31c5Sopenharmony_ci 1533e66f31c5Sopenharmony_ciuv_os_fd_t uv_get_osfhandle(int fd) { 1534e66f31c5Sopenharmony_ci return fd; 1535e66f31c5Sopenharmony_ci} 1536e66f31c5Sopenharmony_ci 1537e66f31c5Sopenharmony_ciint uv_open_osfhandle(uv_os_fd_t os_fd) { 1538e66f31c5Sopenharmony_ci return os_fd; 1539e66f31c5Sopenharmony_ci} 1540e66f31c5Sopenharmony_ci 1541e66f31c5Sopenharmony_ciuv_pid_t uv_os_getpid(void) { 1542e66f31c5Sopenharmony_ci return getpid(); 1543e66f31c5Sopenharmony_ci} 1544e66f31c5Sopenharmony_ci 1545e66f31c5Sopenharmony_ci 1546e66f31c5Sopenharmony_ciuv_pid_t uv_os_getppid(void) { 1547e66f31c5Sopenharmony_ci return getppid(); 1548e66f31c5Sopenharmony_ci} 1549e66f31c5Sopenharmony_ci 1550e66f31c5Sopenharmony_ciint uv_cpumask_size(void) { 1551e66f31c5Sopenharmony_ci#if UV__CPU_AFFINITY_SUPPORTED 1552e66f31c5Sopenharmony_ci return CPU_SETSIZE; 1553e66f31c5Sopenharmony_ci#else 1554e66f31c5Sopenharmony_ci return UV_ENOTSUP; 1555e66f31c5Sopenharmony_ci#endif 1556e66f31c5Sopenharmony_ci} 1557e66f31c5Sopenharmony_ci 1558e66f31c5Sopenharmony_ciint uv_os_getpriority(uv_pid_t pid, int* priority) { 1559e66f31c5Sopenharmony_ci int r; 1560e66f31c5Sopenharmony_ci 1561e66f31c5Sopenharmony_ci if (priority == NULL) 1562e66f31c5Sopenharmony_ci return UV_EINVAL; 1563e66f31c5Sopenharmony_ci 1564e66f31c5Sopenharmony_ci errno = 0; 1565e66f31c5Sopenharmony_ci r = getpriority(PRIO_PROCESS, (int) pid); 1566e66f31c5Sopenharmony_ci 1567e66f31c5Sopenharmony_ci if (r == -1 && errno != 0) 1568e66f31c5Sopenharmony_ci return UV__ERR(errno); 1569e66f31c5Sopenharmony_ci 1570e66f31c5Sopenharmony_ci *priority = r; 1571e66f31c5Sopenharmony_ci return 0; 1572e66f31c5Sopenharmony_ci} 1573e66f31c5Sopenharmony_ci 1574e66f31c5Sopenharmony_ci 1575e66f31c5Sopenharmony_ciint uv_os_setpriority(uv_pid_t pid, int priority) { 1576e66f31c5Sopenharmony_ci if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW) 1577e66f31c5Sopenharmony_ci return UV_EINVAL; 1578e66f31c5Sopenharmony_ci 1579e66f31c5Sopenharmony_ci if (setpriority(PRIO_PROCESS, (int) pid, priority) != 0) 1580e66f31c5Sopenharmony_ci return UV__ERR(errno); 1581e66f31c5Sopenharmony_ci 1582e66f31c5Sopenharmony_ci return 0; 1583e66f31c5Sopenharmony_ci} 1584e66f31c5Sopenharmony_ci 1585e66f31c5Sopenharmony_ci/** 1586e66f31c5Sopenharmony_ci * If the function succeeds, the return value is 0. 1587e66f31c5Sopenharmony_ci * If the function fails, the return value is non-zero. 1588e66f31c5Sopenharmony_ci * for Linux, when schedule policy is SCHED_OTHER (default), priority is 0. 1589e66f31c5Sopenharmony_ci * So the output parameter priority is actually the nice value. 1590e66f31c5Sopenharmony_ci*/ 1591e66f31c5Sopenharmony_ciint uv_thread_getpriority(uv_thread_t tid, int* priority) { 1592e66f31c5Sopenharmony_ci int r; 1593e66f31c5Sopenharmony_ci int policy; 1594e66f31c5Sopenharmony_ci struct sched_param param; 1595e66f31c5Sopenharmony_ci#ifdef __linux__ 1596e66f31c5Sopenharmony_ci pid_t pid = gettid(); 1597e66f31c5Sopenharmony_ci#endif 1598e66f31c5Sopenharmony_ci 1599e66f31c5Sopenharmony_ci if (priority == NULL) 1600e66f31c5Sopenharmony_ci return UV_EINVAL; 1601e66f31c5Sopenharmony_ci 1602e66f31c5Sopenharmony_ci r = pthread_getschedparam(tid, &policy, ¶m); 1603e66f31c5Sopenharmony_ci if (r != 0) 1604e66f31c5Sopenharmony_ci return UV__ERR(errno); 1605e66f31c5Sopenharmony_ci 1606e66f31c5Sopenharmony_ci#ifdef __linux__ 1607e66f31c5Sopenharmony_ci if (SCHED_OTHER == policy && pthread_equal(tid, pthread_self())) { 1608e66f31c5Sopenharmony_ci errno = 0; 1609e66f31c5Sopenharmony_ci r = getpriority(PRIO_PROCESS, pid); 1610e66f31c5Sopenharmony_ci if (r == -1 && errno != 0) 1611e66f31c5Sopenharmony_ci return UV__ERR(errno); 1612e66f31c5Sopenharmony_ci *priority = r; 1613e66f31c5Sopenharmony_ci return 0; 1614e66f31c5Sopenharmony_ci } 1615e66f31c5Sopenharmony_ci#endif 1616e66f31c5Sopenharmony_ci 1617e66f31c5Sopenharmony_ci *priority = param.sched_priority; 1618e66f31c5Sopenharmony_ci return 0; 1619e66f31c5Sopenharmony_ci} 1620e66f31c5Sopenharmony_ci 1621e66f31c5Sopenharmony_ci#ifdef __linux__ 1622e66f31c5Sopenharmony_cistatic int set_nice_for_calling_thread(int priority) { 1623e66f31c5Sopenharmony_ci int r; 1624e66f31c5Sopenharmony_ci int nice; 1625e66f31c5Sopenharmony_ci 1626e66f31c5Sopenharmony_ci if (priority < UV_THREAD_PRIORITY_LOWEST || priority > UV_THREAD_PRIORITY_HIGHEST) 1627e66f31c5Sopenharmony_ci return UV_EINVAL; 1628e66f31c5Sopenharmony_ci 1629e66f31c5Sopenharmony_ci pid_t pid = gettid(); 1630e66f31c5Sopenharmony_ci nice = 0 - priority * 2; 1631e66f31c5Sopenharmony_ci r = setpriority(PRIO_PROCESS, pid, nice); 1632e66f31c5Sopenharmony_ci if (r != 0) 1633e66f31c5Sopenharmony_ci return UV__ERR(errno); 1634e66f31c5Sopenharmony_ci return 0; 1635e66f31c5Sopenharmony_ci} 1636e66f31c5Sopenharmony_ci#endif 1637e66f31c5Sopenharmony_ci 1638e66f31c5Sopenharmony_ci/** 1639e66f31c5Sopenharmony_ci * If the function succeeds, the return value is 0. 1640e66f31c5Sopenharmony_ci * If the function fails, the return value is non-zero. 1641e66f31c5Sopenharmony_ci*/ 1642e66f31c5Sopenharmony_ciint uv_thread_setpriority(uv_thread_t tid, int priority) { 1643e66f31c5Sopenharmony_ci int r; 1644e66f31c5Sopenharmony_ci int min; 1645e66f31c5Sopenharmony_ci int max; 1646e66f31c5Sopenharmony_ci int range; 1647e66f31c5Sopenharmony_ci int prio; 1648e66f31c5Sopenharmony_ci int policy; 1649e66f31c5Sopenharmony_ci struct sched_param param; 1650e66f31c5Sopenharmony_ci 1651e66f31c5Sopenharmony_ci if (priority < UV_THREAD_PRIORITY_LOWEST || priority > UV_THREAD_PRIORITY_HIGHEST) 1652e66f31c5Sopenharmony_ci return UV_EINVAL; 1653e66f31c5Sopenharmony_ci 1654e66f31c5Sopenharmony_ci r = pthread_getschedparam(tid, &policy, ¶m); 1655e66f31c5Sopenharmony_ci if (r != 0) 1656e66f31c5Sopenharmony_ci return UV__ERR(errno); 1657e66f31c5Sopenharmony_ci 1658e66f31c5Sopenharmony_ci#ifdef __linux__ 1659e66f31c5Sopenharmony_ci/** 1660e66f31c5Sopenharmony_ci * for Linux, when schedule policy is SCHED_OTHER (default), priority must be 0, 1661e66f31c5Sopenharmony_ci * we should set the nice value in this case. 1662e66f31c5Sopenharmony_ci*/ 1663e66f31c5Sopenharmony_ci if (SCHED_OTHER == policy && pthread_equal(tid, pthread_self())) 1664e66f31c5Sopenharmony_ci return set_nice_for_calling_thread(priority); 1665e66f31c5Sopenharmony_ci#endif 1666e66f31c5Sopenharmony_ci 1667e66f31c5Sopenharmony_ci#ifdef __PASE__ 1668e66f31c5Sopenharmony_ci min = 1; 1669e66f31c5Sopenharmony_ci max = 127; 1670e66f31c5Sopenharmony_ci#else 1671e66f31c5Sopenharmony_ci min = sched_get_priority_min(policy); 1672e66f31c5Sopenharmony_ci max = sched_get_priority_max(policy); 1673e66f31c5Sopenharmony_ci#endif 1674e66f31c5Sopenharmony_ci 1675e66f31c5Sopenharmony_ci if (min == -1 || max == -1) 1676e66f31c5Sopenharmony_ci return UV__ERR(errno); 1677e66f31c5Sopenharmony_ci 1678e66f31c5Sopenharmony_ci range = max - min; 1679e66f31c5Sopenharmony_ci 1680e66f31c5Sopenharmony_ci switch (priority) { 1681e66f31c5Sopenharmony_ci case UV_THREAD_PRIORITY_HIGHEST: 1682e66f31c5Sopenharmony_ci prio = max; 1683e66f31c5Sopenharmony_ci break; 1684e66f31c5Sopenharmony_ci case UV_THREAD_PRIORITY_ABOVE_NORMAL: 1685e66f31c5Sopenharmony_ci prio = min + range * 3 / 4; 1686e66f31c5Sopenharmony_ci break; 1687e66f31c5Sopenharmony_ci case UV_THREAD_PRIORITY_NORMAL: 1688e66f31c5Sopenharmony_ci prio = min + range / 2; 1689e66f31c5Sopenharmony_ci break; 1690e66f31c5Sopenharmony_ci case UV_THREAD_PRIORITY_BELOW_NORMAL: 1691e66f31c5Sopenharmony_ci prio = min + range / 4; 1692e66f31c5Sopenharmony_ci break; 1693e66f31c5Sopenharmony_ci case UV_THREAD_PRIORITY_LOWEST: 1694e66f31c5Sopenharmony_ci prio = min; 1695e66f31c5Sopenharmony_ci break; 1696e66f31c5Sopenharmony_ci default: 1697e66f31c5Sopenharmony_ci return 0; 1698e66f31c5Sopenharmony_ci } 1699e66f31c5Sopenharmony_ci 1700e66f31c5Sopenharmony_ci if (param.sched_priority != prio) { 1701e66f31c5Sopenharmony_ci param.sched_priority = prio; 1702e66f31c5Sopenharmony_ci r = pthread_setschedparam(tid, policy, ¶m); 1703e66f31c5Sopenharmony_ci if (r != 0) 1704e66f31c5Sopenharmony_ci return UV__ERR(errno); 1705e66f31c5Sopenharmony_ci } 1706e66f31c5Sopenharmony_ci 1707e66f31c5Sopenharmony_ci return 0; 1708e66f31c5Sopenharmony_ci} 1709e66f31c5Sopenharmony_ci 1710e66f31c5Sopenharmony_ciint uv_os_uname(uv_utsname_t* buffer) { 1711e66f31c5Sopenharmony_ci struct utsname buf; 1712e66f31c5Sopenharmony_ci int r; 1713e66f31c5Sopenharmony_ci 1714e66f31c5Sopenharmony_ci if (buffer == NULL) 1715e66f31c5Sopenharmony_ci return UV_EINVAL; 1716e66f31c5Sopenharmony_ci 1717e66f31c5Sopenharmony_ci if (uname(&buf) == -1) { 1718e66f31c5Sopenharmony_ci r = UV__ERR(errno); 1719e66f31c5Sopenharmony_ci goto error; 1720e66f31c5Sopenharmony_ci } 1721e66f31c5Sopenharmony_ci 1722e66f31c5Sopenharmony_ci r = uv__strscpy(buffer->sysname, buf.sysname, sizeof(buffer->sysname)); 1723e66f31c5Sopenharmony_ci if (r == UV_E2BIG) 1724e66f31c5Sopenharmony_ci goto error; 1725e66f31c5Sopenharmony_ci 1726e66f31c5Sopenharmony_ci#ifdef _AIX 1727e66f31c5Sopenharmony_ci r = snprintf(buffer->release, 1728e66f31c5Sopenharmony_ci sizeof(buffer->release), 1729e66f31c5Sopenharmony_ci "%s.%s", 1730e66f31c5Sopenharmony_ci buf.version, 1731e66f31c5Sopenharmony_ci buf.release); 1732e66f31c5Sopenharmony_ci if (r >= sizeof(buffer->release)) { 1733e66f31c5Sopenharmony_ci r = UV_E2BIG; 1734e66f31c5Sopenharmony_ci goto error; 1735e66f31c5Sopenharmony_ci } 1736e66f31c5Sopenharmony_ci#else 1737e66f31c5Sopenharmony_ci r = uv__strscpy(buffer->release, buf.release, sizeof(buffer->release)); 1738e66f31c5Sopenharmony_ci if (r == UV_E2BIG) 1739e66f31c5Sopenharmony_ci goto error; 1740e66f31c5Sopenharmony_ci#endif 1741e66f31c5Sopenharmony_ci 1742e66f31c5Sopenharmony_ci r = uv__strscpy(buffer->version, buf.version, sizeof(buffer->version)); 1743e66f31c5Sopenharmony_ci if (r == UV_E2BIG) 1744e66f31c5Sopenharmony_ci goto error; 1745e66f31c5Sopenharmony_ci 1746e66f31c5Sopenharmony_ci#if defined(_AIX) || defined(__PASE__) 1747e66f31c5Sopenharmony_ci r = uv__strscpy(buffer->machine, "ppc64", sizeof(buffer->machine)); 1748e66f31c5Sopenharmony_ci#else 1749e66f31c5Sopenharmony_ci r = uv__strscpy(buffer->machine, buf.machine, sizeof(buffer->machine)); 1750e66f31c5Sopenharmony_ci#endif 1751e66f31c5Sopenharmony_ci 1752e66f31c5Sopenharmony_ci if (r == UV_E2BIG) 1753e66f31c5Sopenharmony_ci goto error; 1754e66f31c5Sopenharmony_ci 1755e66f31c5Sopenharmony_ci return 0; 1756e66f31c5Sopenharmony_ci 1757e66f31c5Sopenharmony_cierror: 1758e66f31c5Sopenharmony_ci buffer->sysname[0] = '\0'; 1759e66f31c5Sopenharmony_ci buffer->release[0] = '\0'; 1760e66f31c5Sopenharmony_ci buffer->version[0] = '\0'; 1761e66f31c5Sopenharmony_ci buffer->machine[0] = '\0'; 1762e66f31c5Sopenharmony_ci return r; 1763e66f31c5Sopenharmony_ci} 1764e66f31c5Sopenharmony_ci 1765e66f31c5Sopenharmony_ciint uv__getsockpeername(const uv_handle_t* handle, 1766e66f31c5Sopenharmony_ci uv__peersockfunc func, 1767e66f31c5Sopenharmony_ci struct sockaddr* name, 1768e66f31c5Sopenharmony_ci int* namelen) { 1769e66f31c5Sopenharmony_ci socklen_t socklen; 1770e66f31c5Sopenharmony_ci uv_os_fd_t fd; 1771e66f31c5Sopenharmony_ci int r; 1772e66f31c5Sopenharmony_ci 1773e66f31c5Sopenharmony_ci r = uv_fileno(handle, &fd); 1774e66f31c5Sopenharmony_ci if (r < 0) 1775e66f31c5Sopenharmony_ci return r; 1776e66f31c5Sopenharmony_ci 1777e66f31c5Sopenharmony_ci /* sizeof(socklen_t) != sizeof(int) on some systems. */ 1778e66f31c5Sopenharmony_ci socklen = (socklen_t) *namelen; 1779e66f31c5Sopenharmony_ci 1780e66f31c5Sopenharmony_ci if (func(fd, name, &socklen)) 1781e66f31c5Sopenharmony_ci return UV__ERR(errno); 1782e66f31c5Sopenharmony_ci 1783e66f31c5Sopenharmony_ci *namelen = (int) socklen; 1784e66f31c5Sopenharmony_ci return 0; 1785e66f31c5Sopenharmony_ci} 1786e66f31c5Sopenharmony_ci 1787e66f31c5Sopenharmony_ciint uv_gettimeofday(uv_timeval64_t* tv) { 1788e66f31c5Sopenharmony_ci struct timeval time; 1789e66f31c5Sopenharmony_ci 1790e66f31c5Sopenharmony_ci if (tv == NULL) 1791e66f31c5Sopenharmony_ci return UV_EINVAL; 1792e66f31c5Sopenharmony_ci 1793e66f31c5Sopenharmony_ci if (gettimeofday(&time, NULL) != 0) 1794e66f31c5Sopenharmony_ci return UV__ERR(errno); 1795e66f31c5Sopenharmony_ci 1796e66f31c5Sopenharmony_ci tv->tv_sec = (int64_t) time.tv_sec; 1797e66f31c5Sopenharmony_ci tv->tv_usec = (int32_t) time.tv_usec; 1798e66f31c5Sopenharmony_ci return 0; 1799e66f31c5Sopenharmony_ci} 1800e66f31c5Sopenharmony_ci 1801e66f31c5Sopenharmony_civoid uv_sleep(unsigned int msec) { 1802e66f31c5Sopenharmony_ci struct timespec timeout; 1803e66f31c5Sopenharmony_ci int rc; 1804e66f31c5Sopenharmony_ci 1805e66f31c5Sopenharmony_ci timeout.tv_sec = msec / 1000; 1806e66f31c5Sopenharmony_ci timeout.tv_nsec = (msec % 1000) * 1000 * 1000; 1807e66f31c5Sopenharmony_ci 1808e66f31c5Sopenharmony_ci do 1809e66f31c5Sopenharmony_ci rc = nanosleep(&timeout, &timeout); 1810e66f31c5Sopenharmony_ci while (rc == -1 && errno == EINTR); 1811e66f31c5Sopenharmony_ci 1812e66f31c5Sopenharmony_ci assert(rc == 0); 1813e66f31c5Sopenharmony_ci} 1814e66f31c5Sopenharmony_ci 1815e66f31c5Sopenharmony_ciint uv__search_path(const char* prog, char* buf, size_t* buflen) { 1816e66f31c5Sopenharmony_ci char abspath[UV__PATH_MAX]; 1817e66f31c5Sopenharmony_ci size_t abspath_size; 1818e66f31c5Sopenharmony_ci char trypath[UV__PATH_MAX]; 1819e66f31c5Sopenharmony_ci char* cloned_path; 1820e66f31c5Sopenharmony_ci char* path_env; 1821e66f31c5Sopenharmony_ci char* token; 1822e66f31c5Sopenharmony_ci char* itr; 1823e66f31c5Sopenharmony_ci 1824e66f31c5Sopenharmony_ci if (buf == NULL || buflen == NULL || *buflen == 0) 1825e66f31c5Sopenharmony_ci return UV_EINVAL; 1826e66f31c5Sopenharmony_ci 1827e66f31c5Sopenharmony_ci /* 1828e66f31c5Sopenharmony_ci * Possibilities for prog: 1829e66f31c5Sopenharmony_ci * i) an absolute path such as: /home/user/myprojects/nodejs/node 1830e66f31c5Sopenharmony_ci * ii) a relative path such as: ./node or ../myprojects/nodejs/node 1831e66f31c5Sopenharmony_ci * iii) a bare filename such as "node", after exporting PATH variable 1832e66f31c5Sopenharmony_ci * to its location. 1833e66f31c5Sopenharmony_ci */ 1834e66f31c5Sopenharmony_ci 1835e66f31c5Sopenharmony_ci /* Case i) and ii) absolute or relative paths */ 1836e66f31c5Sopenharmony_ci if (strchr(prog, '/') != NULL) { 1837e66f31c5Sopenharmony_ci if (realpath(prog, abspath) != abspath) 1838e66f31c5Sopenharmony_ci return UV__ERR(errno); 1839e66f31c5Sopenharmony_ci 1840e66f31c5Sopenharmony_ci abspath_size = strlen(abspath); 1841e66f31c5Sopenharmony_ci 1842e66f31c5Sopenharmony_ci *buflen -= 1; 1843e66f31c5Sopenharmony_ci if (*buflen > abspath_size) 1844e66f31c5Sopenharmony_ci *buflen = abspath_size; 1845e66f31c5Sopenharmony_ci 1846e66f31c5Sopenharmony_ci memcpy(buf, abspath, *buflen); 1847e66f31c5Sopenharmony_ci buf[*buflen] = '\0'; 1848e66f31c5Sopenharmony_ci 1849e66f31c5Sopenharmony_ci return 0; 1850e66f31c5Sopenharmony_ci } 1851e66f31c5Sopenharmony_ci 1852e66f31c5Sopenharmony_ci /* Case iii). Search PATH environment variable */ 1853e66f31c5Sopenharmony_ci cloned_path = NULL; 1854e66f31c5Sopenharmony_ci token = NULL; 1855e66f31c5Sopenharmony_ci path_env = getenv("PATH"); 1856e66f31c5Sopenharmony_ci 1857e66f31c5Sopenharmony_ci if (path_env == NULL) 1858e66f31c5Sopenharmony_ci return UV_EINVAL; 1859e66f31c5Sopenharmony_ci 1860e66f31c5Sopenharmony_ci cloned_path = uv__strdup(path_env); 1861e66f31c5Sopenharmony_ci if (cloned_path == NULL) 1862e66f31c5Sopenharmony_ci return UV_ENOMEM; 1863e66f31c5Sopenharmony_ci 1864e66f31c5Sopenharmony_ci token = uv__strtok(cloned_path, ":", &itr); 1865e66f31c5Sopenharmony_ci while (token != NULL) { 1866e66f31c5Sopenharmony_ci snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, prog); 1867e66f31c5Sopenharmony_ci if (realpath(trypath, abspath) == abspath) { 1868e66f31c5Sopenharmony_ci /* Check the match is executable */ 1869e66f31c5Sopenharmony_ci if (access(abspath, X_OK) == 0) { 1870e66f31c5Sopenharmony_ci abspath_size = strlen(abspath); 1871e66f31c5Sopenharmony_ci 1872e66f31c5Sopenharmony_ci *buflen -= 1; 1873e66f31c5Sopenharmony_ci if (*buflen > abspath_size) 1874e66f31c5Sopenharmony_ci *buflen = abspath_size; 1875e66f31c5Sopenharmony_ci 1876e66f31c5Sopenharmony_ci memcpy(buf, abspath, *buflen); 1877e66f31c5Sopenharmony_ci buf[*buflen] = '\0'; 1878e66f31c5Sopenharmony_ci 1879e66f31c5Sopenharmony_ci uv__free(cloned_path); 1880e66f31c5Sopenharmony_ci return 0; 1881e66f31c5Sopenharmony_ci } 1882e66f31c5Sopenharmony_ci } 1883e66f31c5Sopenharmony_ci token = uv__strtok(NULL, ":", &itr); 1884e66f31c5Sopenharmony_ci } 1885e66f31c5Sopenharmony_ci uv__free(cloned_path); 1886e66f31c5Sopenharmony_ci 1887e66f31c5Sopenharmony_ci /* Out of tokens (path entries), and no match found */ 1888e66f31c5Sopenharmony_ci return UV_EINVAL; 1889e66f31c5Sopenharmony_ci} 1890e66f31c5Sopenharmony_ci 1891e66f31c5Sopenharmony_ci 1892e66f31c5Sopenharmony_ciunsigned int uv_available_parallelism(void) { 1893e66f31c5Sopenharmony_ci#ifdef __linux__ 1894e66f31c5Sopenharmony_ci cpu_set_t set; 1895e66f31c5Sopenharmony_ci long rc; 1896e66f31c5Sopenharmony_ci 1897e66f31c5Sopenharmony_ci memset(&set, 0, sizeof(set)); 1898e66f31c5Sopenharmony_ci 1899e66f31c5Sopenharmony_ci /* sysconf(_SC_NPROCESSORS_ONLN) in musl calls sched_getaffinity() but in 1900e66f31c5Sopenharmony_ci * glibc it's... complicated... so for consistency try sched_getaffinity() 1901e66f31c5Sopenharmony_ci * before falling back to sysconf(_SC_NPROCESSORS_ONLN). 1902e66f31c5Sopenharmony_ci */ 1903e66f31c5Sopenharmony_ci if (0 == sched_getaffinity(0, sizeof(set), &set)) 1904e66f31c5Sopenharmony_ci rc = CPU_COUNT(&set); 1905e66f31c5Sopenharmony_ci else 1906e66f31c5Sopenharmony_ci rc = sysconf(_SC_NPROCESSORS_ONLN); 1907e66f31c5Sopenharmony_ci 1908e66f31c5Sopenharmony_ci if (rc < 1) 1909e66f31c5Sopenharmony_ci rc = 1; 1910e66f31c5Sopenharmony_ci 1911e66f31c5Sopenharmony_ci return (unsigned) rc; 1912e66f31c5Sopenharmony_ci#elif defined(__MVS__) 1913e66f31c5Sopenharmony_ci int rc; 1914e66f31c5Sopenharmony_ci 1915e66f31c5Sopenharmony_ci rc = __get_num_online_cpus(); 1916e66f31c5Sopenharmony_ci if (rc < 1) 1917e66f31c5Sopenharmony_ci rc = 1; 1918e66f31c5Sopenharmony_ci 1919e66f31c5Sopenharmony_ci return (unsigned) rc; 1920e66f31c5Sopenharmony_ci#else /* __linux__ */ 1921e66f31c5Sopenharmony_ci long rc; 1922e66f31c5Sopenharmony_ci 1923e66f31c5Sopenharmony_ci rc = sysconf(_SC_NPROCESSORS_ONLN); 1924e66f31c5Sopenharmony_ci if (rc < 1) 1925e66f31c5Sopenharmony_ci rc = 1; 1926e66f31c5Sopenharmony_ci 1927e66f31c5Sopenharmony_ci return (unsigned) rc; 1928e66f31c5Sopenharmony_ci#endif /* __linux__ */ 1929e66f31c5Sopenharmony_ci} 1930e66f31c5Sopenharmony_ci 1931e66f31c5Sopenharmony_ciint uv_register_task_to_event(struct uv_loop_s* loop, uv_post_task func, void* handler) 1932e66f31c5Sopenharmony_ci{ 1933e66f31c5Sopenharmony_ci#if defined(__aarch64__) 1934e66f31c5Sopenharmony_ci if (loop == NULL) 1935e66f31c5Sopenharmony_ci return -1; 1936e66f31c5Sopenharmony_ci 1937e66f31c5Sopenharmony_ci struct uv_loop_data* data = (struct uv_loop_data*)malloc(sizeof(struct uv_loop_data)); 1938e66f31c5Sopenharmony_ci if (data == NULL) 1939e66f31c5Sopenharmony_ci return -1; 1940e66f31c5Sopenharmony_ci if ((uint64_t)data >> UV_EVENT_MAGIC_OFFSETBITS != 0x0) { 1941e66f31c5Sopenharmony_ci UV_LOGE("malloc address error"); 1942e66f31c5Sopenharmony_ci free(data); 1943e66f31c5Sopenharmony_ci return -1; 1944e66f31c5Sopenharmony_ci } 1945e66f31c5Sopenharmony_ci 1946e66f31c5Sopenharmony_ci (void)memset(data, 0, sizeof(struct uv_loop_data)); 1947e66f31c5Sopenharmony_ci data->post_task_func = func; 1948e66f31c5Sopenharmony_ci data->event_handler = handler; 1949e66f31c5Sopenharmony_ci data = (struct uv_loop_data*)((uint64_t)data | (UV_EVENT_MAGIC_OFFSET << UV_EVENT_MAGIC_OFFSETBITS)); 1950e66f31c5Sopenharmony_ci loop->data = (void *)data; 1951e66f31c5Sopenharmony_ci return 0; 1952e66f31c5Sopenharmony_ci#else 1953e66f31c5Sopenharmony_ci return -1; 1954e66f31c5Sopenharmony_ci#endif 1955e66f31c5Sopenharmony_ci} 1956e66f31c5Sopenharmony_ci 1957e66f31c5Sopenharmony_ci 1958e66f31c5Sopenharmony_ciint uv_unregister_task_to_event(struct uv_loop_s* loop) 1959e66f31c5Sopenharmony_ci{ 1960e66f31c5Sopenharmony_ci#if defined(__aarch64__) 1961e66f31c5Sopenharmony_ci if (loop == NULL || loop->data == NULL || 1962e66f31c5Sopenharmony_ci ((uint64_t)loop->data >> UV_EVENT_MAGIC_OFFSETBITS) != (uint64_t)(UV_EVENT_MAGIC_OFFSET)) 1963e66f31c5Sopenharmony_ci return -1; 1964e66f31c5Sopenharmony_ci loop->data = (struct uv_loop_data*)((uint64_t)loop->data - 1965e66f31c5Sopenharmony_ci (UV_EVENT_MAGIC_OFFSET << UV_EVENT_MAGIC_OFFSETBITS)); 1966e66f31c5Sopenharmony_ci free(loop->data); 1967e66f31c5Sopenharmony_ci loop->data = NULL; 1968e66f31c5Sopenharmony_ci return 0; 1969e66f31c5Sopenharmony_ci#else 1970e66f31c5Sopenharmony_ci return -1; 1971e66f31c5Sopenharmony_ci#endif 1972e66f31c5Sopenharmony_ci} 1973e66f31c5Sopenharmony_ci 1974e66f31c5Sopenharmony_ci 1975e66f31c5Sopenharmony_ciint uv_check_data_valid(struct uv_loop_data* data) { 1976e66f31c5Sopenharmony_ci#if defined(__aarch64__) 1977e66f31c5Sopenharmony_ci if (data == NULL || ((uint64_t)data >> UV_EVENT_MAGIC_OFFSETBITS) != (uint64_t)(UV_EVENT_MAGIC_OFFSET)) { 1978e66f31c5Sopenharmony_ci return -1; 1979e66f31c5Sopenharmony_ci } 1980e66f31c5Sopenharmony_ci struct uv_loop_data* addr = (struct uv_loop_data*)((uint64_t)data - 1981e66f31c5Sopenharmony_ci (UV_EVENT_MAGIC_OFFSET << UV_EVENT_MAGIC_OFFSETBITS)); 1982e66f31c5Sopenharmony_ci if (addr->post_task_func == NULL) { 1983e66f31c5Sopenharmony_ci UV_LOGE("post_task_func NULL"); 1984e66f31c5Sopenharmony_ci return -1; 1985e66f31c5Sopenharmony_ci } 1986e66f31c5Sopenharmony_ci return 0; 1987e66f31c5Sopenharmony_ci#else 1988e66f31c5Sopenharmony_ci return -1; 1989e66f31c5Sopenharmony_ci#endif 1990e66f31c5Sopenharmony_ci} 1991e66f31c5Sopenharmony_ci 1992