xref: /netbsd-src/external/mit/libuv/dist/src/unix/pipe.c (revision 5f2f42719cd62ff11fd913b40b7ce19f07c4fd25)
10e552da7Schristos /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
20e552da7Schristos  *
30e552da7Schristos  * Permission is hereby granted, free of charge, to any person obtaining a copy
40e552da7Schristos  * of this software and associated documentation files (the "Software"), to
50e552da7Schristos  * deal in the Software without restriction, including without limitation the
60e552da7Schristos  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
70e552da7Schristos  * sell copies of the Software, and to permit persons to whom the Software is
80e552da7Schristos  * furnished to do so, subject to the following conditions:
90e552da7Schristos  *
100e552da7Schristos  * The above copyright notice and this permission notice shall be included in
110e552da7Schristos  * all copies or substantial portions of the Software.
120e552da7Schristos  *
130e552da7Schristos  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
140e552da7Schristos  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
150e552da7Schristos  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
160e552da7Schristos  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
170e552da7Schristos  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
180e552da7Schristos  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
190e552da7Schristos  * IN THE SOFTWARE.
200e552da7Schristos  */
210e552da7Schristos 
220e552da7Schristos #include "uv.h"
230e552da7Schristos #include "internal.h"
240e552da7Schristos 
250e552da7Schristos #include <assert.h>
260e552da7Schristos #include <errno.h>
270e552da7Schristos #include <string.h>
280e552da7Schristos #include <sys/un.h>
290e552da7Schristos #include <unistd.h>
300e552da7Schristos #include <stdlib.h>
310e552da7Schristos 
320e552da7Schristos 
uv_pipe_init(uv_loop_t * loop,uv_pipe_t * handle,int ipc)330e552da7Schristos int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
340e552da7Schristos   uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
350e552da7Schristos   handle->shutdown_req = NULL;
360e552da7Schristos   handle->connect_req = NULL;
370e552da7Schristos   handle->pipe_fname = NULL;
380e552da7Schristos   handle->ipc = ipc;
390e552da7Schristos   return 0;
400e552da7Schristos }
410e552da7Schristos 
420e552da7Schristos 
uv_pipe_bind(uv_pipe_t * handle,const char * name)430e552da7Schristos int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
440e552da7Schristos   struct sockaddr_un saddr;
450e552da7Schristos   const char* pipe_fname;
460e552da7Schristos   int sockfd;
470e552da7Schristos   int err;
480e552da7Schristos 
490e552da7Schristos   pipe_fname = NULL;
500e552da7Schristos 
510e552da7Schristos   /* Already bound? */
520e552da7Schristos   if (uv__stream_fd(handle) >= 0)
530e552da7Schristos     return UV_EINVAL;
54*5f2f4271Schristos   if (uv__is_closing(handle)) {
55*5f2f4271Schristos     return UV_EINVAL;
56*5f2f4271Schristos   }
570e552da7Schristos   /* Make a copy of the file name, it outlives this function's scope. */
580e552da7Schristos   pipe_fname = uv__strdup(name);
590e552da7Schristos   if (pipe_fname == NULL)
600e552da7Schristos     return UV_ENOMEM;
610e552da7Schristos 
620e552da7Schristos   /* We've got a copy, don't touch the original any more. */
630e552da7Schristos   name = NULL;
640e552da7Schristos 
650e552da7Schristos   err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
660e552da7Schristos   if (err < 0)
670e552da7Schristos     goto err_socket;
680e552da7Schristos   sockfd = err;
690e552da7Schristos 
700e552da7Schristos   memset(&saddr, 0, sizeof saddr);
710e552da7Schristos   uv__strscpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path));
720e552da7Schristos   saddr.sun_family = AF_UNIX;
730e552da7Schristos 
740e552da7Schristos   if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
750e552da7Schristos     err = UV__ERR(errno);
760e552da7Schristos     /* Convert ENOENT to EACCES for compatibility with Windows. */
770e552da7Schristos     if (err == UV_ENOENT)
780e552da7Schristos       err = UV_EACCES;
790e552da7Schristos 
800e552da7Schristos     uv__close(sockfd);
810e552da7Schristos     goto err_socket;
820e552da7Schristos   }
830e552da7Schristos 
840e552da7Schristos   /* Success. */
850e552da7Schristos   handle->flags |= UV_HANDLE_BOUND;
860e552da7Schristos   handle->pipe_fname = pipe_fname; /* Is a strdup'ed copy. */
870e552da7Schristos   handle->io_watcher.fd = sockfd;
880e552da7Schristos   return 0;
890e552da7Schristos 
900e552da7Schristos err_socket:
910e552da7Schristos   uv__free((void*)pipe_fname);
920e552da7Schristos   return err;
930e552da7Schristos }
940e552da7Schristos 
950e552da7Schristos 
uv__pipe_listen(uv_pipe_t * handle,int backlog,uv_connection_cb cb)96*5f2f4271Schristos int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
970e552da7Schristos   if (uv__stream_fd(handle) == -1)
980e552da7Schristos     return UV_EINVAL;
990e552da7Schristos 
1000e552da7Schristos   if (handle->ipc)
1010e552da7Schristos     return UV_EINVAL;
1020e552da7Schristos 
1030e552da7Schristos #if defined(__MVS__) || defined(__PASE__)
1040e552da7Schristos   /* On zOS, backlog=0 has undefined behaviour */
1050e552da7Schristos   /* On IBMi PASE, backlog=0 leads to "Connection refused" error */
1060e552da7Schristos   if (backlog == 0)
1070e552da7Schristos     backlog = 1;
1080e552da7Schristos   else if (backlog < 0)
1090e552da7Schristos     backlog = SOMAXCONN;
1100e552da7Schristos #endif
1110e552da7Schristos 
1120e552da7Schristos   if (listen(uv__stream_fd(handle), backlog))
1130e552da7Schristos     return UV__ERR(errno);
1140e552da7Schristos 
1150e552da7Schristos   handle->connection_cb = cb;
1160e552da7Schristos   handle->io_watcher.cb = uv__server_io;
1170e552da7Schristos   uv__io_start(handle->loop, &handle->io_watcher, POLLIN);
1180e552da7Schristos   return 0;
1190e552da7Schristos }
1200e552da7Schristos 
1210e552da7Schristos 
uv__pipe_close(uv_pipe_t * handle)1220e552da7Schristos void uv__pipe_close(uv_pipe_t* handle) {
1230e552da7Schristos   if (handle->pipe_fname) {
1240e552da7Schristos     /*
1250e552da7Schristos      * Unlink the file system entity before closing the file descriptor.
1260e552da7Schristos      * Doing it the other way around introduces a race where our process
1270e552da7Schristos      * unlinks a socket with the same name that's just been created by
1280e552da7Schristos      * another thread or process.
1290e552da7Schristos      */
1300e552da7Schristos     unlink(handle->pipe_fname);
1310e552da7Schristos     uv__free((void*)handle->pipe_fname);
1320e552da7Schristos     handle->pipe_fname = NULL;
1330e552da7Schristos   }
1340e552da7Schristos 
1350e552da7Schristos   uv__stream_close((uv_stream_t*)handle);
1360e552da7Schristos }
1370e552da7Schristos 
1380e552da7Schristos 
uv_pipe_open(uv_pipe_t * handle,uv_file fd)1390e552da7Schristos int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
1400e552da7Schristos   int flags;
1410e552da7Schristos   int mode;
1420e552da7Schristos   int err;
1430e552da7Schristos   flags = 0;
1440e552da7Schristos 
1450e552da7Schristos   if (uv__fd_exists(handle->loop, fd))
1460e552da7Schristos     return UV_EEXIST;
1470e552da7Schristos 
1480e552da7Schristos   do
1490e552da7Schristos     mode = fcntl(fd, F_GETFL);
1500e552da7Schristos   while (mode == -1 && errno == EINTR);
1510e552da7Schristos 
1520e552da7Schristos   if (mode == -1)
1530e552da7Schristos     return UV__ERR(errno); /* according to docs, must be EBADF */
1540e552da7Schristos 
1550e552da7Schristos   err = uv__nonblock(fd, 1);
1560e552da7Schristos   if (err)
1570e552da7Schristos     return err;
1580e552da7Schristos 
1590e552da7Schristos #if defined(__APPLE__)
1600e552da7Schristos   err = uv__stream_try_select((uv_stream_t*) handle, &fd);
1610e552da7Schristos   if (err)
1620e552da7Schristos     return err;
1630e552da7Schristos #endif /* defined(__APPLE__) */
1640e552da7Schristos 
1650e552da7Schristos   mode &= O_ACCMODE;
1660e552da7Schristos   if (mode != O_WRONLY)
1670e552da7Schristos     flags |= UV_HANDLE_READABLE;
1680e552da7Schristos   if (mode != O_RDONLY)
1690e552da7Schristos     flags |= UV_HANDLE_WRITABLE;
1700e552da7Schristos 
1710e552da7Schristos   return uv__stream_open((uv_stream_t*)handle, fd, flags);
1720e552da7Schristos }
1730e552da7Schristos 
1740e552da7Schristos 
uv_pipe_connect(uv_connect_t * req,uv_pipe_t * handle,const char * name,uv_connect_cb cb)1750e552da7Schristos void uv_pipe_connect(uv_connect_t* req,
1760e552da7Schristos                     uv_pipe_t* handle,
1770e552da7Schristos                     const char* name,
1780e552da7Schristos                     uv_connect_cb cb) {
1790e552da7Schristos   struct sockaddr_un saddr;
1800e552da7Schristos   int new_sock;
1810e552da7Schristos   int err;
1820e552da7Schristos   int r;
1830e552da7Schristos 
1840e552da7Schristos   new_sock = (uv__stream_fd(handle) == -1);
1850e552da7Schristos 
1860e552da7Schristos   if (new_sock) {
1870e552da7Schristos     err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
1880e552da7Schristos     if (err < 0)
1890e552da7Schristos       goto out;
1900e552da7Schristos     handle->io_watcher.fd = err;
1910e552da7Schristos   }
1920e552da7Schristos 
1930e552da7Schristos   memset(&saddr, 0, sizeof saddr);
1940e552da7Schristos   uv__strscpy(saddr.sun_path, name, sizeof(saddr.sun_path));
1950e552da7Schristos   saddr.sun_family = AF_UNIX;
1960e552da7Schristos 
1970e552da7Schristos   do {
1980e552da7Schristos     r = connect(uv__stream_fd(handle),
1990e552da7Schristos                 (struct sockaddr*)&saddr, sizeof saddr);
2000e552da7Schristos   }
2010e552da7Schristos   while (r == -1 && errno == EINTR);
2020e552da7Schristos 
2030e552da7Schristos   if (r == -1 && errno != EINPROGRESS) {
2040e552da7Schristos     err = UV__ERR(errno);
2050e552da7Schristos #if defined(__CYGWIN__) || defined(__MSYS__)
2060e552da7Schristos     /* EBADF is supposed to mean that the socket fd is bad, but
2070e552da7Schristos        Cygwin reports EBADF instead of ENOTSOCK when the file is
2080e552da7Schristos        not a socket.  We do not expect to see a bad fd here
2090e552da7Schristos        (e.g. due to new_sock), so translate the error.  */
2100e552da7Schristos     if (err == UV_EBADF)
2110e552da7Schristos       err = UV_ENOTSOCK;
2120e552da7Schristos #endif
2130e552da7Schristos     goto out;
2140e552da7Schristos   }
2150e552da7Schristos 
2160e552da7Schristos   err = 0;
2170e552da7Schristos   if (new_sock) {
2180e552da7Schristos     err = uv__stream_open((uv_stream_t*)handle,
2190e552da7Schristos                           uv__stream_fd(handle),
2200e552da7Schristos                           UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
2210e552da7Schristos   }
2220e552da7Schristos 
2230e552da7Schristos   if (err == 0)
2240e552da7Schristos     uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
2250e552da7Schristos 
2260e552da7Schristos out:
2270e552da7Schristos   handle->delayed_error = err;
2280e552da7Schristos   handle->connect_req = req;
2290e552da7Schristos 
2300e552da7Schristos   uv__req_init(handle->loop, req, UV_CONNECT);
2310e552da7Schristos   req->handle = (uv_stream_t*)handle;
2320e552da7Schristos   req->cb = cb;
2330e552da7Schristos   QUEUE_INIT(&req->queue);
2340e552da7Schristos 
2350e552da7Schristos   /* Force callback to run on next tick in case of error. */
2360e552da7Schristos   if (err)
2370e552da7Schristos     uv__io_feed(handle->loop, &handle->io_watcher);
2380e552da7Schristos 
2390e552da7Schristos }
2400e552da7Schristos 
2410e552da7Schristos 
uv__pipe_getsockpeername(const uv_pipe_t * handle,uv__peersockfunc func,char * buffer,size_t * size)2420e552da7Schristos static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
2430e552da7Schristos                                     uv__peersockfunc func,
2440e552da7Schristos                                     char* buffer,
2450e552da7Schristos                                     size_t* size) {
2460e552da7Schristos   struct sockaddr_un sa;
2470e552da7Schristos   socklen_t addrlen;
2480e552da7Schristos   int err;
2490e552da7Schristos 
2500e552da7Schristos   addrlen = sizeof(sa);
2510e552da7Schristos   memset(&sa, 0, addrlen);
2520e552da7Schristos   err = uv__getsockpeername((const uv_handle_t*) handle,
2530e552da7Schristos                             func,
2540e552da7Schristos                             (struct sockaddr*) &sa,
2550e552da7Schristos                             (int*) &addrlen);
2560e552da7Schristos   if (err < 0) {
2570e552da7Schristos     *size = 0;
2580e552da7Schristos     return err;
2590e552da7Schristos   }
2600e552da7Schristos 
2610e552da7Schristos #if defined(__linux__)
2620e552da7Schristos   if (sa.sun_path[0] == 0)
2630e552da7Schristos     /* Linux abstract namespace */
2640e552da7Schristos     addrlen -= offsetof(struct sockaddr_un, sun_path);
2650e552da7Schristos   else
2660e552da7Schristos #endif
2670e552da7Schristos     addrlen = strlen(sa.sun_path);
2680e552da7Schristos 
2690e552da7Schristos 
2700e552da7Schristos   if ((size_t)addrlen >= *size) {
2710e552da7Schristos     *size = addrlen + 1;
2720e552da7Schristos     return UV_ENOBUFS;
2730e552da7Schristos   }
2740e552da7Schristos 
2750e552da7Schristos   memcpy(buffer, sa.sun_path, addrlen);
2760e552da7Schristos   *size = addrlen;
2770e552da7Schristos 
2780e552da7Schristos   /* only null-terminate if it's not an abstract socket */
2790e552da7Schristos   if (buffer[0] != '\0')
2800e552da7Schristos     buffer[addrlen] = '\0';
2810e552da7Schristos 
2820e552da7Schristos   return 0;
2830e552da7Schristos }
2840e552da7Schristos 
2850e552da7Schristos 
uv_pipe_getsockname(const uv_pipe_t * handle,char * buffer,size_t * size)2860e552da7Schristos int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) {
2870e552da7Schristos   return uv__pipe_getsockpeername(handle, getsockname, buffer, size);
2880e552da7Schristos }
2890e552da7Schristos 
2900e552da7Schristos 
uv_pipe_getpeername(const uv_pipe_t * handle,char * buffer,size_t * size)2910e552da7Schristos int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
2920e552da7Schristos   return uv__pipe_getsockpeername(handle, getpeername, buffer, size);
2930e552da7Schristos }
2940e552da7Schristos 
2950e552da7Schristos 
uv_pipe_pending_instances(uv_pipe_t * handle,int count)2960e552da7Schristos void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {
2970e552da7Schristos }
2980e552da7Schristos 
2990e552da7Schristos 
uv_pipe_pending_count(uv_pipe_t * handle)3000e552da7Schristos int uv_pipe_pending_count(uv_pipe_t* handle) {
3010e552da7Schristos   uv__stream_queued_fds_t* queued_fds;
3020e552da7Schristos 
3030e552da7Schristos   if (!handle->ipc)
3040e552da7Schristos     return 0;
3050e552da7Schristos 
3060e552da7Schristos   if (handle->accepted_fd == -1)
3070e552da7Schristos     return 0;
3080e552da7Schristos 
3090e552da7Schristos   if (handle->queued_fds == NULL)
3100e552da7Schristos     return 1;
3110e552da7Schristos 
3120e552da7Schristos   queued_fds = handle->queued_fds;
3130e552da7Schristos   return queued_fds->offset + 1;
3140e552da7Schristos }
3150e552da7Schristos 
3160e552da7Schristos 
uv_pipe_pending_type(uv_pipe_t * handle)3170e552da7Schristos uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
3180e552da7Schristos   if (!handle->ipc)
3190e552da7Schristos     return UV_UNKNOWN_HANDLE;
3200e552da7Schristos 
3210e552da7Schristos   if (handle->accepted_fd == -1)
3220e552da7Schristos     return UV_UNKNOWN_HANDLE;
3230e552da7Schristos   else
324*5f2f4271Schristos     return uv_guess_handle(handle->accepted_fd);
3250e552da7Schristos }
3260e552da7Schristos 
3270e552da7Schristos 
uv_pipe_chmod(uv_pipe_t * handle,int mode)3280e552da7Schristos int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
3290e552da7Schristos   unsigned desired_mode;
3300e552da7Schristos   struct stat pipe_stat;
3310e552da7Schristos   char* name_buffer;
3320e552da7Schristos   size_t name_len;
3330e552da7Schristos   int r;
3340e552da7Schristos 
3350e552da7Schristos   if (handle == NULL || uv__stream_fd(handle) == -1)
3360e552da7Schristos     return UV_EBADF;
3370e552da7Schristos 
3380e552da7Schristos   if (mode != UV_READABLE &&
3390e552da7Schristos       mode != UV_WRITABLE &&
3400e552da7Schristos       mode != (UV_WRITABLE | UV_READABLE))
3410e552da7Schristos     return UV_EINVAL;
3420e552da7Schristos 
3430e552da7Schristos   /* Unfortunately fchmod does not work on all platforms, we will use chmod. */
3440e552da7Schristos   name_len = 0;
3450e552da7Schristos   r = uv_pipe_getsockname(handle, NULL, &name_len);
3460e552da7Schristos   if (r != UV_ENOBUFS)
3470e552da7Schristos     return r;
3480e552da7Schristos 
3490e552da7Schristos   name_buffer = uv__malloc(name_len);
3500e552da7Schristos   if (name_buffer == NULL)
3510e552da7Schristos     return UV_ENOMEM;
3520e552da7Schristos 
3530e552da7Schristos   r = uv_pipe_getsockname(handle, name_buffer, &name_len);
3540e552da7Schristos   if (r != 0) {
3550e552da7Schristos     uv__free(name_buffer);
3560e552da7Schristos     return r;
3570e552da7Schristos   }
3580e552da7Schristos 
3590e552da7Schristos   /* stat must be used as fstat has a bug on Darwin */
3600e552da7Schristos   if (stat(name_buffer, &pipe_stat) == -1) {
3610e552da7Schristos     uv__free(name_buffer);
3620e552da7Schristos     return -errno;
3630e552da7Schristos   }
3640e552da7Schristos 
3650e552da7Schristos   desired_mode = 0;
3660e552da7Schristos   if (mode & UV_READABLE)
3670e552da7Schristos     desired_mode |= S_IRUSR | S_IRGRP | S_IROTH;
3680e552da7Schristos   if (mode & UV_WRITABLE)
3690e552da7Schristos     desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
3700e552da7Schristos 
3710e552da7Schristos   /* Exit early if pipe already has desired mode. */
3720e552da7Schristos   if ((pipe_stat.st_mode & desired_mode) == desired_mode) {
3730e552da7Schristos     uv__free(name_buffer);
3740e552da7Schristos     return 0;
3750e552da7Schristos   }
3760e552da7Schristos 
3770e552da7Schristos   pipe_stat.st_mode |= desired_mode;
3780e552da7Schristos 
3790e552da7Schristos   r = chmod(name_buffer, pipe_stat.st_mode);
3800e552da7Schristos   uv__free(name_buffer);
3810e552da7Schristos 
3820e552da7Schristos   return r != -1 ? 0 : UV__ERR(errno);
3830e552da7Schristos }
384*5f2f4271Schristos 
385*5f2f4271Schristos 
uv_pipe(uv_os_fd_t fds[2],int read_flags,int write_flags)386*5f2f4271Schristos int uv_pipe(uv_os_fd_t fds[2], int read_flags, int write_flags) {
387*5f2f4271Schristos   uv_os_fd_t temp[2];
388*5f2f4271Schristos   int err;
389*5f2f4271Schristos #if defined(__FreeBSD__) || defined(__linux__)
390*5f2f4271Schristos   int flags = O_CLOEXEC;
391*5f2f4271Schristos 
392*5f2f4271Schristos   if ((read_flags & UV_NONBLOCK_PIPE) && (write_flags & UV_NONBLOCK_PIPE))
393*5f2f4271Schristos     flags |= UV_FS_O_NONBLOCK;
394*5f2f4271Schristos 
395*5f2f4271Schristos   if (pipe2(temp, flags))
396*5f2f4271Schristos     return UV__ERR(errno);
397*5f2f4271Schristos 
398*5f2f4271Schristos   if (flags & UV_FS_O_NONBLOCK) {
399*5f2f4271Schristos     fds[0] = temp[0];
400*5f2f4271Schristos     fds[1] = temp[1];
401*5f2f4271Schristos     return 0;
402*5f2f4271Schristos   }
403*5f2f4271Schristos #else
404*5f2f4271Schristos   if (pipe(temp))
405*5f2f4271Schristos     return UV__ERR(errno);
406*5f2f4271Schristos 
407*5f2f4271Schristos   if ((err = uv__cloexec(temp[0], 1)))
408*5f2f4271Schristos     goto fail;
409*5f2f4271Schristos 
410*5f2f4271Schristos   if ((err = uv__cloexec(temp[1], 1)))
411*5f2f4271Schristos     goto fail;
412*5f2f4271Schristos #endif
413*5f2f4271Schristos 
414*5f2f4271Schristos   if (read_flags & UV_NONBLOCK_PIPE)
415*5f2f4271Schristos     if ((err = uv__nonblock(temp[0], 1)))
416*5f2f4271Schristos       goto fail;
417*5f2f4271Schristos 
418*5f2f4271Schristos   if (write_flags & UV_NONBLOCK_PIPE)
419*5f2f4271Schristos     if ((err = uv__nonblock(temp[1], 1)))
420*5f2f4271Schristos       goto fail;
421*5f2f4271Schristos 
422*5f2f4271Schristos   fds[0] = temp[0];
423*5f2f4271Schristos   fds[1] = temp[1];
424*5f2f4271Schristos   return 0;
425*5f2f4271Schristos 
426*5f2f4271Schristos fail:
427*5f2f4271Schristos   uv__close(temp[0]);
428*5f2f4271Schristos   uv__close(temp[1]);
429*5f2f4271Schristos   return err;
430*5f2f4271Schristos }
431*5f2f4271Schristos 
432*5f2f4271Schristos 
uv__make_pipe(int fds[2],int flags)433*5f2f4271Schristos int uv__make_pipe(int fds[2], int flags) {
434*5f2f4271Schristos   return uv_pipe(fds,
435*5f2f4271Schristos                  flags & UV_NONBLOCK_PIPE,
436*5f2f4271Schristos                  flags & UV_NONBLOCK_PIPE);
437*5f2f4271Schristos }
438