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