105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Create a pipe, with specific opening flags.
205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Copyright (C) 2009-2012 Free Software Foundation, Inc.
305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is free software; you can redistribute it and/or modify
505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   it under the terms of the GNU General Public License as published by
605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   the Free Software Foundation; either version 3, or (at your option)
705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   any later version.
805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is distributed in the hope that it will be useful,
1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   but WITHOUT ANY WARRANTY; without even the implied warranty of
1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   GNU General Public License for more details.
1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   You should have received a copy of the GNU General Public License along
1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   with this program; if not, see <http://www.gnu.org/licenses/>.  */
1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <config.h>
1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Specification.  */
2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <unistd.h>
2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <errno.h>
2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <fcntl.h>
2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "binary-io.h"
2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "verify.h"
2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if GNULIB_defined_O_NONBLOCK
2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "nonblocking.h"
3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Native Windows API.  */
3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <io.h>
3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
3905436638acc7c010349a69c3395f1a57c642dc62Ying Wangint
4005436638acc7c010349a69c3395f1a57c642dc62Ying Wangpipe2 (int fd[2], int flags)
4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Mingw _pipe() corrupts fd on failure; also, if we succeed at
4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang     creating the pipe but later fail at changing fcntl, we want
4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang     to leave fd unchanged: http://austingroupbugs.net/view.php?id=467  */
4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  int tmp[2];
4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  tmp[0] = fd[0];
4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  tmp[1] = fd[1];
4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_PIPE2
5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# undef pipe2
5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Try the system call first, if it exists.  (We may be running with a glibc
5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang     that has the function but with an older kernel that lacks it.)  */
5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  {
5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    /* Cache the information whether the system call really exists.  */
5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    static int have_pipe2_really; /* 0 = unknown, 1 = yes, -1 = no */
5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    if (have_pipe2_really >= 0)
5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        int result = pipe2 (fd, flags);
5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        if (!(result < 0 && errno == ENOSYS))
6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang            have_pipe2_really = 1;
6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang            return result;
6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        have_pipe2_really = -1;
6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  }
6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Check the supported flags.  */
7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if ((flags & ~(O_CLOEXEC | O_NONBLOCK | O_BINARY | O_TEXT)) != 0)
7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      errno = EINVAL;
7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      return -1;
7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Native Windows API.  */
7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (_pipe (fd, 4096, flags & ~O_NONBLOCK) < 0)
8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      fd[0] = tmp[0];
8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      fd[1] = tmp[1];
8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      return -1;
8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* O_NONBLOCK handling.
8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang     On native Windows platforms, O_NONBLOCK is defined by gnulib.  Use the
8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang     functions defined by the gnulib module 'nonblocking'.  */
8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if GNULIB_defined_O_NONBLOCK
9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (flags & O_NONBLOCK)
9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (set_nonblocking_flag (fd[0], true) != 0
9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          || set_nonblocking_flag (fd[1], true) != 0)
9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        goto fail;
9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else
9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  {
9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    verify (O_NONBLOCK == 0);
9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  }
10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return 0;
10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else
10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Unix API.  */
10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (pipe (fd) < 0)
10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return -1;
10905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* POSIX <http://www.opengroup.org/onlinepubs/9699919799/functions/pipe.html>
11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang     says that initially, the O_NONBLOCK and FD_CLOEXEC flags are cleared on
11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang     both fd[0] and fd[1].  */
11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* O_NONBLOCK handling.
11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang     On Unix platforms, O_NONBLOCK is defined by the system.  Use fcntl().  */
11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (flags & O_NONBLOCK)
11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      int fcntl_flags;
11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
12005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if ((fcntl_flags = fcntl (fd[1], F_GETFL, 0)) < 0
12105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          || fcntl (fd[1], F_SETFL, fcntl_flags | O_NONBLOCK) == -1
12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          || (fcntl_flags = fcntl (fd[0], F_GETFL, 0)) < 0
12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) == -1)
12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        goto fail;
12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
12705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (flags & O_CLOEXEC)
12805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      int fcntl_flags;
13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if ((fcntl_flags = fcntl (fd[1], F_GETFD, 0)) < 0
13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          || fcntl (fd[1], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1
13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang          || (fcntl_flags = fcntl (fd[0], F_GETFD, 0)) < 0
13405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          || fcntl (fd[0], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1)
13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        goto fail;
13605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
13705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
13805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if O_BINARY
13905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (flags & O_BINARY)
14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      setmode (fd[1], O_BINARY);
14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      setmode (fd[0], O_BINARY);
14305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
14405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else if (flags & O_TEXT)
14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
14605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      setmode (fd[1], O_TEXT);
14705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      setmode (fd[0], O_TEXT);
14805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
14905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif
15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
15105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return 0;
15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
15305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
15405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if GNULIB_defined_O_NONBLOCK || \
15605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
15705436638acc7c010349a69c3395f1a57c642dc62Ying Wang fail:
15805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  {
15905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    int saved_errno = errno;
16005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    close (fd[0]);
16105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    close (fd[1]);
16205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    fd[0] = tmp[0];
16305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    fd[1] = tmp[1];
16405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    errno = saved_errno;
16505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return -1;
16605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  }
16705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
16805436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
169