1e66f31c5Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2e66f31c5Sopenharmony_ci * 3e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 4e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to 5e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the 6e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 8e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions: 9e66f31c5Sopenharmony_ci * 10e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 11e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software. 12e66f31c5Sopenharmony_ci * 13e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19e66f31c5Sopenharmony_ci * IN THE SOFTWARE. 20e66f31c5Sopenharmony_ci */ 21e66f31c5Sopenharmony_ci 22e66f31c5Sopenharmony_ci#include "uv.h" 23e66f31c5Sopenharmony_ci#include "internal.h" 24e66f31c5Sopenharmony_ci 25e66f31c5Sopenharmony_ci#include <assert.h> 26e66f31c5Sopenharmony_ci#include <errno.h> 27e66f31c5Sopenharmony_ci#include <string.h> 28e66f31c5Sopenharmony_ci#include <sys/un.h> 29e66f31c5Sopenharmony_ci#include <unistd.h> 30e66f31c5Sopenharmony_ci#include <stdlib.h> 31e66f31c5Sopenharmony_ci 32e66f31c5Sopenharmony_ci 33e66f31c5Sopenharmony_ci/* Does the file path contain embedded nul bytes? */ 34e66f31c5Sopenharmony_cistatic int includes_nul(const char *s, size_t n) { 35e66f31c5Sopenharmony_ci if (n == 0) 36e66f31c5Sopenharmony_ci return 0; 37e66f31c5Sopenharmony_ci#ifdef __linux__ 38e66f31c5Sopenharmony_ci /* Accept abstract socket namespace path ("\0/virtual/path"). */ 39e66f31c5Sopenharmony_ci s++; 40e66f31c5Sopenharmony_ci n--; 41e66f31c5Sopenharmony_ci#endif 42e66f31c5Sopenharmony_ci return NULL != memchr(s, '\0', n); 43e66f31c5Sopenharmony_ci} 44e66f31c5Sopenharmony_ci 45e66f31c5Sopenharmony_ci 46e66f31c5Sopenharmony_ciint uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { 47e66f31c5Sopenharmony_ci uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE); 48e66f31c5Sopenharmony_ci handle->shutdown_req = NULL; 49e66f31c5Sopenharmony_ci handle->connect_req = NULL; 50e66f31c5Sopenharmony_ci handle->pipe_fname = NULL; 51e66f31c5Sopenharmony_ci handle->ipc = ipc; 52e66f31c5Sopenharmony_ci return 0; 53e66f31c5Sopenharmony_ci} 54e66f31c5Sopenharmony_ci 55e66f31c5Sopenharmony_ci 56e66f31c5Sopenharmony_ciint uv_pipe_bind(uv_pipe_t* handle, const char* name) { 57e66f31c5Sopenharmony_ci return uv_pipe_bind2(handle, name, strlen(name), 0); 58e66f31c5Sopenharmony_ci} 59e66f31c5Sopenharmony_ci 60e66f31c5Sopenharmony_ci 61e66f31c5Sopenharmony_ciint uv_pipe_bind2(uv_pipe_t* handle, 62e66f31c5Sopenharmony_ci const char* name, 63e66f31c5Sopenharmony_ci size_t namelen, 64e66f31c5Sopenharmony_ci unsigned int flags) { 65e66f31c5Sopenharmony_ci struct sockaddr_un saddr; 66e66f31c5Sopenharmony_ci char* pipe_fname; 67e66f31c5Sopenharmony_ci int sockfd; 68e66f31c5Sopenharmony_ci int err; 69e66f31c5Sopenharmony_ci socklen_t addrlen; 70e66f31c5Sopenharmony_ci 71e66f31c5Sopenharmony_ci pipe_fname = NULL; 72e66f31c5Sopenharmony_ci 73e66f31c5Sopenharmony_ci if (flags & ~UV_PIPE_NO_TRUNCATE) 74e66f31c5Sopenharmony_ci return UV_EINVAL; 75e66f31c5Sopenharmony_ci 76e66f31c5Sopenharmony_ci if (name == NULL) 77e66f31c5Sopenharmony_ci return UV_EINVAL; 78e66f31c5Sopenharmony_ci 79e66f31c5Sopenharmony_ci if (namelen == 0) 80e66f31c5Sopenharmony_ci return UV_EINVAL; 81e66f31c5Sopenharmony_ci 82e66f31c5Sopenharmony_ci if (includes_nul(name, namelen)) 83e66f31c5Sopenharmony_ci return UV_EINVAL; 84e66f31c5Sopenharmony_ci 85e66f31c5Sopenharmony_ci if (flags & UV_PIPE_NO_TRUNCATE) 86e66f31c5Sopenharmony_ci if (namelen > sizeof(saddr.sun_path)) 87e66f31c5Sopenharmony_ci return UV_EINVAL; 88e66f31c5Sopenharmony_ci 89e66f31c5Sopenharmony_ci /* Truncate long paths. Documented behavior. */ 90e66f31c5Sopenharmony_ci if (namelen > sizeof(saddr.sun_path)) 91e66f31c5Sopenharmony_ci namelen = sizeof(saddr.sun_path); 92e66f31c5Sopenharmony_ci 93e66f31c5Sopenharmony_ci /* Already bound? */ 94e66f31c5Sopenharmony_ci if (uv__stream_fd(handle) >= 0) 95e66f31c5Sopenharmony_ci return UV_EINVAL; 96e66f31c5Sopenharmony_ci 97e66f31c5Sopenharmony_ci if (uv__is_closing(handle)) 98e66f31c5Sopenharmony_ci return UV_EINVAL; 99e66f31c5Sopenharmony_ci 100e66f31c5Sopenharmony_ci /* Make a copy of the file path unless it is an abstract socket. 101e66f31c5Sopenharmony_ci * We unlink the file later but abstract sockets disappear 102e66f31c5Sopenharmony_ci * automatically since they're not real file system entities. 103e66f31c5Sopenharmony_ci */ 104e66f31c5Sopenharmony_ci if (*name == '\0') { 105e66f31c5Sopenharmony_ci addrlen = offsetof(struct sockaddr_un, sun_path) + namelen; 106e66f31c5Sopenharmony_ci } else { 107e66f31c5Sopenharmony_ci pipe_fname = uv__malloc(namelen + 1); 108e66f31c5Sopenharmony_ci if (pipe_fname == NULL) 109e66f31c5Sopenharmony_ci return UV_ENOMEM; 110e66f31c5Sopenharmony_ci memcpy(pipe_fname, name, namelen); 111e66f31c5Sopenharmony_ci pipe_fname[namelen] = '\0'; 112e66f31c5Sopenharmony_ci addrlen = sizeof saddr; 113e66f31c5Sopenharmony_ci } 114e66f31c5Sopenharmony_ci 115e66f31c5Sopenharmony_ci err = uv__socket(AF_UNIX, SOCK_STREAM, 0); 116e66f31c5Sopenharmony_ci if (err < 0) 117e66f31c5Sopenharmony_ci goto err_socket; 118e66f31c5Sopenharmony_ci sockfd = err; 119e66f31c5Sopenharmony_ci 120e66f31c5Sopenharmony_ci memset(&saddr, 0, sizeof saddr); 121e66f31c5Sopenharmony_ci memcpy(&saddr.sun_path, name, namelen); 122e66f31c5Sopenharmony_ci saddr.sun_family = AF_UNIX; 123e66f31c5Sopenharmony_ci 124e66f31c5Sopenharmony_ci if (bind(sockfd, (struct sockaddr*)&saddr, addrlen)) { 125e66f31c5Sopenharmony_ci err = UV__ERR(errno); 126e66f31c5Sopenharmony_ci /* Convert ENOENT to EACCES for compatibility with Windows. */ 127e66f31c5Sopenharmony_ci if (err == UV_ENOENT) 128e66f31c5Sopenharmony_ci err = UV_EACCES; 129e66f31c5Sopenharmony_ci 130e66f31c5Sopenharmony_ci uv__close(sockfd); 131e66f31c5Sopenharmony_ci goto err_socket; 132e66f31c5Sopenharmony_ci } 133e66f31c5Sopenharmony_ci 134e66f31c5Sopenharmony_ci /* Success. */ 135e66f31c5Sopenharmony_ci handle->flags |= UV_HANDLE_BOUND; 136e66f31c5Sopenharmony_ci handle->pipe_fname = pipe_fname; /* NULL or a copy of |name| */ 137e66f31c5Sopenharmony_ci handle->io_watcher.fd = sockfd; 138e66f31c5Sopenharmony_ci return 0; 139e66f31c5Sopenharmony_ci 140e66f31c5Sopenharmony_cierr_socket: 141e66f31c5Sopenharmony_ci uv__free(pipe_fname); 142e66f31c5Sopenharmony_ci return err; 143e66f31c5Sopenharmony_ci} 144e66f31c5Sopenharmony_ci 145e66f31c5Sopenharmony_ci 146e66f31c5Sopenharmony_ciint uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { 147e66f31c5Sopenharmony_ci if (uv__stream_fd(handle) == -1) 148e66f31c5Sopenharmony_ci return UV_EINVAL; 149e66f31c5Sopenharmony_ci 150e66f31c5Sopenharmony_ci if (handle->ipc) 151e66f31c5Sopenharmony_ci return UV_EINVAL; 152e66f31c5Sopenharmony_ci 153e66f31c5Sopenharmony_ci#if defined(__MVS__) || defined(__PASE__) 154e66f31c5Sopenharmony_ci /* On zOS, backlog=0 has undefined behaviour */ 155e66f31c5Sopenharmony_ci /* On IBMi PASE, backlog=0 leads to "Connection refused" error */ 156e66f31c5Sopenharmony_ci if (backlog == 0) 157e66f31c5Sopenharmony_ci backlog = 1; 158e66f31c5Sopenharmony_ci else if (backlog < 0) 159e66f31c5Sopenharmony_ci backlog = SOMAXCONN; 160e66f31c5Sopenharmony_ci#endif 161e66f31c5Sopenharmony_ci 162e66f31c5Sopenharmony_ci if (listen(uv__stream_fd(handle), backlog)) 163e66f31c5Sopenharmony_ci return UV__ERR(errno); 164e66f31c5Sopenharmony_ci 165e66f31c5Sopenharmony_ci handle->connection_cb = cb; 166e66f31c5Sopenharmony_ci handle->io_watcher.cb = uv__server_io; 167e66f31c5Sopenharmony_ci uv__io_start(handle->loop, &handle->io_watcher, POLLIN); 168e66f31c5Sopenharmony_ci return 0; 169e66f31c5Sopenharmony_ci} 170e66f31c5Sopenharmony_ci 171e66f31c5Sopenharmony_ci 172e66f31c5Sopenharmony_civoid uv__pipe_close(uv_pipe_t* handle) { 173e66f31c5Sopenharmony_ci if (handle->pipe_fname) { 174e66f31c5Sopenharmony_ci /* 175e66f31c5Sopenharmony_ci * Unlink the file system entity before closing the file descriptor. 176e66f31c5Sopenharmony_ci * Doing it the other way around introduces a race where our process 177e66f31c5Sopenharmony_ci * unlinks a socket with the same name that's just been created by 178e66f31c5Sopenharmony_ci * another thread or process. 179e66f31c5Sopenharmony_ci */ 180e66f31c5Sopenharmony_ci unlink(handle->pipe_fname); 181e66f31c5Sopenharmony_ci uv__free((void*)handle->pipe_fname); 182e66f31c5Sopenharmony_ci handle->pipe_fname = NULL; 183e66f31c5Sopenharmony_ci } 184e66f31c5Sopenharmony_ci 185e66f31c5Sopenharmony_ci uv__stream_close((uv_stream_t*)handle); 186e66f31c5Sopenharmony_ci} 187e66f31c5Sopenharmony_ci 188e66f31c5Sopenharmony_ci 189e66f31c5Sopenharmony_ciint uv_pipe_open(uv_pipe_t* handle, uv_file fd) { 190e66f31c5Sopenharmony_ci int flags; 191e66f31c5Sopenharmony_ci int mode; 192e66f31c5Sopenharmony_ci int err; 193e66f31c5Sopenharmony_ci flags = 0; 194e66f31c5Sopenharmony_ci 195e66f31c5Sopenharmony_ci if (uv__fd_exists(handle->loop, fd)) 196e66f31c5Sopenharmony_ci return UV_EEXIST; 197e66f31c5Sopenharmony_ci 198e66f31c5Sopenharmony_ci do 199e66f31c5Sopenharmony_ci mode = fcntl(fd, F_GETFL); 200e66f31c5Sopenharmony_ci while (mode == -1 && errno == EINTR); 201e66f31c5Sopenharmony_ci 202e66f31c5Sopenharmony_ci if (mode == -1) 203e66f31c5Sopenharmony_ci return UV__ERR(errno); /* according to docs, must be EBADF */ 204e66f31c5Sopenharmony_ci 205e66f31c5Sopenharmony_ci err = uv__nonblock(fd, 1); 206e66f31c5Sopenharmony_ci if (err) 207e66f31c5Sopenharmony_ci return err; 208e66f31c5Sopenharmony_ci 209e66f31c5Sopenharmony_ci#if defined(__APPLE__) 210e66f31c5Sopenharmony_ci err = uv__stream_try_select((uv_stream_t*) handle, &fd); 211e66f31c5Sopenharmony_ci if (err) 212e66f31c5Sopenharmony_ci return err; 213e66f31c5Sopenharmony_ci#endif /* defined(__APPLE__) */ 214e66f31c5Sopenharmony_ci 215e66f31c5Sopenharmony_ci mode &= O_ACCMODE; 216e66f31c5Sopenharmony_ci if (mode != O_WRONLY) 217e66f31c5Sopenharmony_ci flags |= UV_HANDLE_READABLE; 218e66f31c5Sopenharmony_ci if (mode != O_RDONLY) 219e66f31c5Sopenharmony_ci flags |= UV_HANDLE_WRITABLE; 220e66f31c5Sopenharmony_ci 221e66f31c5Sopenharmony_ci return uv__stream_open((uv_stream_t*)handle, fd, flags); 222e66f31c5Sopenharmony_ci} 223e66f31c5Sopenharmony_ci 224e66f31c5Sopenharmony_ci 225e66f31c5Sopenharmony_civoid uv_pipe_connect(uv_connect_t* req, 226e66f31c5Sopenharmony_ci uv_pipe_t* handle, 227e66f31c5Sopenharmony_ci const char* name, 228e66f31c5Sopenharmony_ci uv_connect_cb cb) { 229e66f31c5Sopenharmony_ci int err; 230e66f31c5Sopenharmony_ci 231e66f31c5Sopenharmony_ci err = uv_pipe_connect2(req, handle, name, strlen(name), 0, cb); 232e66f31c5Sopenharmony_ci 233e66f31c5Sopenharmony_ci if (err) { 234e66f31c5Sopenharmony_ci handle->delayed_error = err; 235e66f31c5Sopenharmony_ci handle->connect_req = req; 236e66f31c5Sopenharmony_ci 237e66f31c5Sopenharmony_ci uv__req_init(handle->loop, req, UV_CONNECT); 238e66f31c5Sopenharmony_ci req->handle = (uv_stream_t*) handle; 239e66f31c5Sopenharmony_ci req->cb = cb; 240e66f31c5Sopenharmony_ci uv__queue_init(&req->queue); 241e66f31c5Sopenharmony_ci 242e66f31c5Sopenharmony_ci /* Force callback to run on next tick in case of error. */ 243e66f31c5Sopenharmony_ci uv__io_feed(handle->loop, &handle->io_watcher); 244e66f31c5Sopenharmony_ci } 245e66f31c5Sopenharmony_ci} 246e66f31c5Sopenharmony_ci 247e66f31c5Sopenharmony_ci 248e66f31c5Sopenharmony_ciint uv_pipe_connect2(uv_connect_t* req, 249e66f31c5Sopenharmony_ci uv_pipe_t* handle, 250e66f31c5Sopenharmony_ci const char* name, 251e66f31c5Sopenharmony_ci size_t namelen, 252e66f31c5Sopenharmony_ci unsigned int flags, 253e66f31c5Sopenharmony_ci uv_connect_cb cb) { 254e66f31c5Sopenharmony_ci struct sockaddr_un saddr; 255e66f31c5Sopenharmony_ci int new_sock; 256e66f31c5Sopenharmony_ci int err; 257e66f31c5Sopenharmony_ci int r; 258e66f31c5Sopenharmony_ci socklen_t addrlen; 259e66f31c5Sopenharmony_ci 260e66f31c5Sopenharmony_ci if (flags & ~UV_PIPE_NO_TRUNCATE) 261e66f31c5Sopenharmony_ci return UV_EINVAL; 262e66f31c5Sopenharmony_ci 263e66f31c5Sopenharmony_ci if (name == NULL) 264e66f31c5Sopenharmony_ci return UV_EINVAL; 265e66f31c5Sopenharmony_ci 266e66f31c5Sopenharmony_ci if (namelen == 0) 267e66f31c5Sopenharmony_ci return UV_EINVAL; 268e66f31c5Sopenharmony_ci 269e66f31c5Sopenharmony_ci if (includes_nul(name, namelen)) 270e66f31c5Sopenharmony_ci return UV_EINVAL; 271e66f31c5Sopenharmony_ci 272e66f31c5Sopenharmony_ci if (flags & UV_PIPE_NO_TRUNCATE) 273e66f31c5Sopenharmony_ci if (namelen > sizeof(saddr.sun_path)) 274e66f31c5Sopenharmony_ci return UV_EINVAL; 275e66f31c5Sopenharmony_ci 276e66f31c5Sopenharmony_ci /* Truncate long paths. Documented behavior. */ 277e66f31c5Sopenharmony_ci if (namelen > sizeof(saddr.sun_path)) 278e66f31c5Sopenharmony_ci namelen = sizeof(saddr.sun_path); 279e66f31c5Sopenharmony_ci 280e66f31c5Sopenharmony_ci new_sock = (uv__stream_fd(handle) == -1); 281e66f31c5Sopenharmony_ci 282e66f31c5Sopenharmony_ci if (new_sock) { 283e66f31c5Sopenharmony_ci err = uv__socket(AF_UNIX, SOCK_STREAM, 0); 284e66f31c5Sopenharmony_ci if (err < 0) 285e66f31c5Sopenharmony_ci goto out; 286e66f31c5Sopenharmony_ci handle->io_watcher.fd = err; 287e66f31c5Sopenharmony_ci } 288e66f31c5Sopenharmony_ci 289e66f31c5Sopenharmony_ci memset(&saddr, 0, sizeof saddr); 290e66f31c5Sopenharmony_ci memcpy(&saddr.sun_path, name, namelen); 291e66f31c5Sopenharmony_ci saddr.sun_family = AF_UNIX; 292e66f31c5Sopenharmony_ci 293e66f31c5Sopenharmony_ci if (*name == '\0') 294e66f31c5Sopenharmony_ci addrlen = offsetof(struct sockaddr_un, sun_path) + namelen; 295e66f31c5Sopenharmony_ci else 296e66f31c5Sopenharmony_ci addrlen = sizeof saddr; 297e66f31c5Sopenharmony_ci 298e66f31c5Sopenharmony_ci do { 299e66f31c5Sopenharmony_ci r = connect(uv__stream_fd(handle), (struct sockaddr*)&saddr, addrlen); 300e66f31c5Sopenharmony_ci } 301e66f31c5Sopenharmony_ci while (r == -1 && errno == EINTR); 302e66f31c5Sopenharmony_ci 303e66f31c5Sopenharmony_ci if (r == -1 && errno != EINPROGRESS) { 304e66f31c5Sopenharmony_ci err = UV__ERR(errno); 305e66f31c5Sopenharmony_ci#if defined(__CYGWIN__) || defined(__MSYS__) 306e66f31c5Sopenharmony_ci /* EBADF is supposed to mean that the socket fd is bad, but 307e66f31c5Sopenharmony_ci Cygwin reports EBADF instead of ENOTSOCK when the file is 308e66f31c5Sopenharmony_ci not a socket. We do not expect to see a bad fd here 309e66f31c5Sopenharmony_ci (e.g. due to new_sock), so translate the error. */ 310e66f31c5Sopenharmony_ci if (err == UV_EBADF) 311e66f31c5Sopenharmony_ci err = UV_ENOTSOCK; 312e66f31c5Sopenharmony_ci#endif 313e66f31c5Sopenharmony_ci goto out; 314e66f31c5Sopenharmony_ci } 315e66f31c5Sopenharmony_ci 316e66f31c5Sopenharmony_ci err = 0; 317e66f31c5Sopenharmony_ci if (new_sock) { 318e66f31c5Sopenharmony_ci err = uv__stream_open((uv_stream_t*)handle, 319e66f31c5Sopenharmony_ci uv__stream_fd(handle), 320e66f31c5Sopenharmony_ci UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); 321e66f31c5Sopenharmony_ci } 322e66f31c5Sopenharmony_ci 323e66f31c5Sopenharmony_ci if (err == 0) 324e66f31c5Sopenharmony_ci uv__io_start(handle->loop, &handle->io_watcher, POLLOUT); 325e66f31c5Sopenharmony_ci 326e66f31c5Sopenharmony_ciout: 327e66f31c5Sopenharmony_ci handle->delayed_error = err; 328e66f31c5Sopenharmony_ci handle->connect_req = req; 329e66f31c5Sopenharmony_ci 330e66f31c5Sopenharmony_ci uv__req_init(handle->loop, req, UV_CONNECT); 331e66f31c5Sopenharmony_ci req->handle = (uv_stream_t*) handle; 332e66f31c5Sopenharmony_ci req->cb = cb; 333e66f31c5Sopenharmony_ci uv__queue_init(&req->queue); 334e66f31c5Sopenharmony_ci 335e66f31c5Sopenharmony_ci /* Force callback to run on next tick in case of error. */ 336e66f31c5Sopenharmony_ci if (err) 337e66f31c5Sopenharmony_ci uv__io_feed(handle->loop, &handle->io_watcher); 338e66f31c5Sopenharmony_ci 339e66f31c5Sopenharmony_ci return 0; 340e66f31c5Sopenharmony_ci} 341e66f31c5Sopenharmony_ci 342e66f31c5Sopenharmony_ci 343e66f31c5Sopenharmony_cistatic int uv__pipe_getsockpeername(const uv_pipe_t* handle, 344e66f31c5Sopenharmony_ci uv__peersockfunc func, 345e66f31c5Sopenharmony_ci char* buffer, 346e66f31c5Sopenharmony_ci size_t* size) { 347e66f31c5Sopenharmony_ci struct sockaddr_un sa; 348e66f31c5Sopenharmony_ci socklen_t addrlen; 349e66f31c5Sopenharmony_ci int err; 350e66f31c5Sopenharmony_ci 351e66f31c5Sopenharmony_ci addrlen = sizeof(sa); 352e66f31c5Sopenharmony_ci memset(&sa, 0, addrlen); 353e66f31c5Sopenharmony_ci err = uv__getsockpeername((const uv_handle_t*) handle, 354e66f31c5Sopenharmony_ci func, 355e66f31c5Sopenharmony_ci (struct sockaddr*) &sa, 356e66f31c5Sopenharmony_ci (int*) &addrlen); 357e66f31c5Sopenharmony_ci if (err < 0) { 358e66f31c5Sopenharmony_ci *size = 0; 359e66f31c5Sopenharmony_ci return err; 360e66f31c5Sopenharmony_ci } 361e66f31c5Sopenharmony_ci 362e66f31c5Sopenharmony_ci#if defined(__linux__) 363e66f31c5Sopenharmony_ci if (sa.sun_path[0] == 0) 364e66f31c5Sopenharmony_ci /* Linux abstract namespace */ 365e66f31c5Sopenharmony_ci addrlen -= offsetof(struct sockaddr_un, sun_path); 366e66f31c5Sopenharmony_ci else 367e66f31c5Sopenharmony_ci#endif 368e66f31c5Sopenharmony_ci addrlen = strlen(sa.sun_path); 369e66f31c5Sopenharmony_ci 370e66f31c5Sopenharmony_ci 371e66f31c5Sopenharmony_ci if ((size_t)addrlen >= *size) { 372e66f31c5Sopenharmony_ci *size = addrlen + 1; 373e66f31c5Sopenharmony_ci return UV_ENOBUFS; 374e66f31c5Sopenharmony_ci } 375e66f31c5Sopenharmony_ci 376e66f31c5Sopenharmony_ci memcpy(buffer, sa.sun_path, addrlen); 377e66f31c5Sopenharmony_ci *size = addrlen; 378e66f31c5Sopenharmony_ci 379e66f31c5Sopenharmony_ci /* only null-terminate if it's not an abstract socket */ 380e66f31c5Sopenharmony_ci if (buffer[0] != '\0') 381e66f31c5Sopenharmony_ci buffer[addrlen] = '\0'; 382e66f31c5Sopenharmony_ci 383e66f31c5Sopenharmony_ci return 0; 384e66f31c5Sopenharmony_ci} 385e66f31c5Sopenharmony_ci 386e66f31c5Sopenharmony_ci 387e66f31c5Sopenharmony_ciint uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) { 388e66f31c5Sopenharmony_ci return uv__pipe_getsockpeername(handle, getsockname, buffer, size); 389e66f31c5Sopenharmony_ci} 390e66f31c5Sopenharmony_ci 391e66f31c5Sopenharmony_ci 392e66f31c5Sopenharmony_ciint uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) { 393e66f31c5Sopenharmony_ci return uv__pipe_getsockpeername(handle, getpeername, buffer, size); 394e66f31c5Sopenharmony_ci} 395e66f31c5Sopenharmony_ci 396e66f31c5Sopenharmony_ci 397e66f31c5Sopenharmony_civoid uv_pipe_pending_instances(uv_pipe_t* handle, int count) { 398e66f31c5Sopenharmony_ci} 399e66f31c5Sopenharmony_ci 400e66f31c5Sopenharmony_ci 401e66f31c5Sopenharmony_ciint uv_pipe_pending_count(uv_pipe_t* handle) { 402e66f31c5Sopenharmony_ci uv__stream_queued_fds_t* queued_fds; 403e66f31c5Sopenharmony_ci 404e66f31c5Sopenharmony_ci if (!handle->ipc) 405e66f31c5Sopenharmony_ci return 0; 406e66f31c5Sopenharmony_ci 407e66f31c5Sopenharmony_ci if (handle->accepted_fd == -1) 408e66f31c5Sopenharmony_ci return 0; 409e66f31c5Sopenharmony_ci 410e66f31c5Sopenharmony_ci if (handle->queued_fds == NULL) 411e66f31c5Sopenharmony_ci return 1; 412e66f31c5Sopenharmony_ci 413e66f31c5Sopenharmony_ci queued_fds = handle->queued_fds; 414e66f31c5Sopenharmony_ci return queued_fds->offset + 1; 415e66f31c5Sopenharmony_ci} 416e66f31c5Sopenharmony_ci 417e66f31c5Sopenharmony_ci 418e66f31c5Sopenharmony_ciuv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) { 419e66f31c5Sopenharmony_ci if (!handle->ipc) 420e66f31c5Sopenharmony_ci return UV_UNKNOWN_HANDLE; 421e66f31c5Sopenharmony_ci 422e66f31c5Sopenharmony_ci if (handle->accepted_fd == -1) 423e66f31c5Sopenharmony_ci return UV_UNKNOWN_HANDLE; 424e66f31c5Sopenharmony_ci else 425e66f31c5Sopenharmony_ci return uv_guess_handle(handle->accepted_fd); 426e66f31c5Sopenharmony_ci} 427e66f31c5Sopenharmony_ci 428e66f31c5Sopenharmony_ci 429e66f31c5Sopenharmony_ciint uv_pipe_chmod(uv_pipe_t* handle, int mode) { 430e66f31c5Sopenharmony_ci unsigned desired_mode; 431e66f31c5Sopenharmony_ci struct stat pipe_stat; 432e66f31c5Sopenharmony_ci char* name_buffer; 433e66f31c5Sopenharmony_ci size_t name_len; 434e66f31c5Sopenharmony_ci int r; 435e66f31c5Sopenharmony_ci 436e66f31c5Sopenharmony_ci if (handle == NULL || uv__stream_fd(handle) == -1) 437e66f31c5Sopenharmony_ci return UV_EBADF; 438e66f31c5Sopenharmony_ci 439e66f31c5Sopenharmony_ci if (mode != UV_READABLE && 440e66f31c5Sopenharmony_ci mode != UV_WRITABLE && 441e66f31c5Sopenharmony_ci mode != (UV_WRITABLE | UV_READABLE)) 442e66f31c5Sopenharmony_ci return UV_EINVAL; 443e66f31c5Sopenharmony_ci 444e66f31c5Sopenharmony_ci /* Unfortunately fchmod does not work on all platforms, we will use chmod. */ 445e66f31c5Sopenharmony_ci name_len = 0; 446e66f31c5Sopenharmony_ci r = uv_pipe_getsockname(handle, NULL, &name_len); 447e66f31c5Sopenharmony_ci if (r != UV_ENOBUFS) 448e66f31c5Sopenharmony_ci return r; 449e66f31c5Sopenharmony_ci 450e66f31c5Sopenharmony_ci name_buffer = uv__malloc(name_len); 451e66f31c5Sopenharmony_ci if (name_buffer == NULL) 452e66f31c5Sopenharmony_ci return UV_ENOMEM; 453e66f31c5Sopenharmony_ci 454e66f31c5Sopenharmony_ci r = uv_pipe_getsockname(handle, name_buffer, &name_len); 455e66f31c5Sopenharmony_ci if (r != 0) { 456e66f31c5Sopenharmony_ci uv__free(name_buffer); 457e66f31c5Sopenharmony_ci return r; 458e66f31c5Sopenharmony_ci } 459e66f31c5Sopenharmony_ci 460e66f31c5Sopenharmony_ci /* stat must be used as fstat has a bug on Darwin */ 461e66f31c5Sopenharmony_ci if (uv__stat(name_buffer, &pipe_stat) == -1) { 462e66f31c5Sopenharmony_ci uv__free(name_buffer); 463e66f31c5Sopenharmony_ci return -errno; 464e66f31c5Sopenharmony_ci } 465e66f31c5Sopenharmony_ci 466e66f31c5Sopenharmony_ci desired_mode = 0; 467e66f31c5Sopenharmony_ci if (mode & UV_READABLE) 468e66f31c5Sopenharmony_ci desired_mode |= S_IRUSR | S_IRGRP | S_IROTH; 469e66f31c5Sopenharmony_ci if (mode & UV_WRITABLE) 470e66f31c5Sopenharmony_ci desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH; 471e66f31c5Sopenharmony_ci 472e66f31c5Sopenharmony_ci /* Exit early if pipe already has desired mode. */ 473e66f31c5Sopenharmony_ci if ((pipe_stat.st_mode & desired_mode) == desired_mode) { 474e66f31c5Sopenharmony_ci uv__free(name_buffer); 475e66f31c5Sopenharmony_ci return 0; 476e66f31c5Sopenharmony_ci } 477e66f31c5Sopenharmony_ci 478e66f31c5Sopenharmony_ci pipe_stat.st_mode |= desired_mode; 479e66f31c5Sopenharmony_ci 480e66f31c5Sopenharmony_ci r = chmod(name_buffer, pipe_stat.st_mode); 481e66f31c5Sopenharmony_ci uv__free(name_buffer); 482e66f31c5Sopenharmony_ci 483e66f31c5Sopenharmony_ci return r != -1 ? 0 : UV__ERR(errno); 484e66f31c5Sopenharmony_ci} 485e66f31c5Sopenharmony_ci 486e66f31c5Sopenharmony_ci 487e66f31c5Sopenharmony_ciint uv_pipe(uv_os_fd_t fds[2], int read_flags, int write_flags) { 488e66f31c5Sopenharmony_ci uv_os_fd_t temp[2]; 489e66f31c5Sopenharmony_ci int err; 490e66f31c5Sopenharmony_ci#if defined(__FreeBSD__) || defined(__linux__) 491e66f31c5Sopenharmony_ci int flags = O_CLOEXEC; 492e66f31c5Sopenharmony_ci 493e66f31c5Sopenharmony_ci if ((read_flags & UV_NONBLOCK_PIPE) && (write_flags & UV_NONBLOCK_PIPE)) 494e66f31c5Sopenharmony_ci flags |= UV_FS_O_NONBLOCK; 495e66f31c5Sopenharmony_ci 496e66f31c5Sopenharmony_ci if (pipe2(temp, flags)) 497e66f31c5Sopenharmony_ci return UV__ERR(errno); 498e66f31c5Sopenharmony_ci 499e66f31c5Sopenharmony_ci if (flags & UV_FS_O_NONBLOCK) { 500e66f31c5Sopenharmony_ci fds[0] = temp[0]; 501e66f31c5Sopenharmony_ci fds[1] = temp[1]; 502e66f31c5Sopenharmony_ci return 0; 503e66f31c5Sopenharmony_ci } 504e66f31c5Sopenharmony_ci#else 505e66f31c5Sopenharmony_ci if (pipe(temp)) 506e66f31c5Sopenharmony_ci return UV__ERR(errno); 507e66f31c5Sopenharmony_ci 508e66f31c5Sopenharmony_ci if ((err = uv__cloexec(temp[0], 1))) 509e66f31c5Sopenharmony_ci goto fail; 510e66f31c5Sopenharmony_ci 511e66f31c5Sopenharmony_ci if ((err = uv__cloexec(temp[1], 1))) 512e66f31c5Sopenharmony_ci goto fail; 513e66f31c5Sopenharmony_ci#endif 514e66f31c5Sopenharmony_ci 515e66f31c5Sopenharmony_ci if (read_flags & UV_NONBLOCK_PIPE) 516e66f31c5Sopenharmony_ci if ((err = uv__nonblock(temp[0], 1))) 517e66f31c5Sopenharmony_ci goto fail; 518e66f31c5Sopenharmony_ci 519e66f31c5Sopenharmony_ci if (write_flags & UV_NONBLOCK_PIPE) 520e66f31c5Sopenharmony_ci if ((err = uv__nonblock(temp[1], 1))) 521e66f31c5Sopenharmony_ci goto fail; 522e66f31c5Sopenharmony_ci 523e66f31c5Sopenharmony_ci fds[0] = temp[0]; 524e66f31c5Sopenharmony_ci fds[1] = temp[1]; 525e66f31c5Sopenharmony_ci return 0; 526e66f31c5Sopenharmony_ci 527e66f31c5Sopenharmony_cifail: 528e66f31c5Sopenharmony_ci uv__close(temp[0]); 529e66f31c5Sopenharmony_ci uv__close(temp[1]); 530e66f31c5Sopenharmony_ci return err; 531e66f31c5Sopenharmony_ci} 532e66f31c5Sopenharmony_ci 533e66f31c5Sopenharmony_ci 534e66f31c5Sopenharmony_ciint uv__make_pipe(int fds[2], int flags) { 535e66f31c5Sopenharmony_ci return uv_pipe(fds, 536e66f31c5Sopenharmony_ci flags & UV_NONBLOCK_PIPE, 537e66f31c5Sopenharmony_ci flags & UV_NONBLOCK_PIPE); 538e66f31c5Sopenharmony_ci} 539