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