pipe2.c 4.2 KB

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