• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /* Create a pipe, with specific opening flags.
2     Copyright (C) 2009-2012 Free Software Foundation, Inc.
3  
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 3, or (at your option)
7     any later version.
8  
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13  
14     You should have received a copy of the GNU General Public License along
15     with this program; if not, see <http://www.gnu.org/licenses/>.  */
16  
17  #include <config.h>
18  
19  /* Specification.  */
20  #include <unistd.h>
21  
22  #include <errno.h>
23  #include <fcntl.h>
24  
25  #include "binary-io.h"
26  #include "verify.h"
27  
28  #if GNULIB_defined_O_NONBLOCK
29  # include "nonblocking.h"
30  #endif
31  
32  #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
33  /* Native Windows API.  */
34  
35  # include <io.h>
36  
37  #endif
38  
39  int
pipe2(int fd[2],int flags)40  pipe2 (int fd[2], int flags)
41  {
42    /* Mingw _pipe() corrupts fd on failure; also, if we succeed at
43       creating the pipe but later fail at changing fcntl, we want
44       to leave fd unchanged: http://austingroupbugs.net/view.php?id=467  */
45    int tmp[2];
46    tmp[0] = fd[0];
47    tmp[1] = fd[1];
48  
49  #if HAVE_PIPE2
50  # undef pipe2
51    /* Try the system call first, if it exists.  (We may be running with a glibc
52       that has the function but with an older kernel that lacks it.)  */
53    {
54      /* Cache the information whether the system call really exists.  */
55      static int have_pipe2_really; /* 0 = unknown, 1 = yes, -1 = no */
56      if (have_pipe2_really >= 0)
57        {
58          int result = pipe2 (fd, flags);
59          if (!(result < 0 && errno == ENOSYS))
60            {
61              have_pipe2_really = 1;
62              return result;
63            }
64          have_pipe2_really = -1;
65        }
66    }
67  #endif
68  
69    /* Check the supported flags.  */
70    if ((flags & ~(O_CLOEXEC | O_NONBLOCK | O_BINARY | O_TEXT)) != 0)
71      {
72        errno = EINVAL;
73        return -1;
74      }
75  
76  #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
77  /* Native Windows API.  */
78  
79    if (_pipe (fd, 4096, flags & ~O_NONBLOCK) < 0)
80      {
81        fd[0] = tmp[0];
82        fd[1] = tmp[1];
83        return -1;
84      }
85  
86    /* O_NONBLOCK handling.
87       On native Windows platforms, O_NONBLOCK is defined by gnulib.  Use the
88       functions defined by the gnulib module 'nonblocking'.  */
89  # if GNULIB_defined_O_NONBLOCK
90    if (flags & O_NONBLOCK)
91      {
92        if (set_nonblocking_flag (fd[0], true) != 0
93            || set_nonblocking_flag (fd[1], true) != 0)
94          goto fail;
95      }
96  # else
97    {
98      verify (O_NONBLOCK == 0);
99    }
100  # endif
101  
102    return 0;
103  
104  #else
105  /* Unix API.  */
106  
107    if (pipe (fd) < 0)
108      return -1;
109  
110    /* POSIX <http://www.opengroup.org/onlinepubs/9699919799/functions/pipe.html>
111       says that initially, the O_NONBLOCK and FD_CLOEXEC flags are cleared on
112       both fd[0] and fd[1].  */
113  
114    /* O_NONBLOCK handling.
115       On Unix platforms, O_NONBLOCK is defined by the system.  Use fcntl().  */
116    if (flags & O_NONBLOCK)
117      {
118        int fcntl_flags;
119  
120        if ((fcntl_flags = fcntl (fd[1], F_GETFL, 0)) < 0
121            || fcntl (fd[1], F_SETFL, fcntl_flags | O_NONBLOCK) == -1
122            || (fcntl_flags = fcntl (fd[0], F_GETFL, 0)) < 0
123            || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) == -1)
124          goto fail;
125      }
126  
127    if (flags & O_CLOEXEC)
128      {
129        int fcntl_flags;
130  
131        if ((fcntl_flags = fcntl (fd[1], F_GETFD, 0)) < 0
132            || fcntl (fd[1], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1
133            || (fcntl_flags = fcntl (fd[0], F_GETFD, 0)) < 0
134            || fcntl (fd[0], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1)
135          goto fail;
136      }
137  
138  # if O_BINARY
139    if (flags & O_BINARY)
140      {
141        setmode (fd[1], O_BINARY);
142        setmode (fd[0], O_BINARY);
143      }
144    else if (flags & O_TEXT)
145      {
146        setmode (fd[1], O_TEXT);
147        setmode (fd[0], O_TEXT);
148      }
149  # endif
150  
151    return 0;
152  
153  #endif
154  
155  #if GNULIB_defined_O_NONBLOCK || \
156    !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
157   fail:
158    {
159      int saved_errno = errno;
160      close (fd[0]);
161      close (fd[1]);
162      fd[0] = tmp[0];
163      fd[1] = tmp[1];
164      errno = saved_errno;
165      return -1;
166    }
167  #endif
168  }
169