pipe2.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /* Create a pipe, with specific opening flags.
  2. Copyright (C) 2009-2022 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. #include "verify.h"
  20. #if GNULIB_defined_O_NONBLOCK
  21. # include "nonblocking.h"
  22. #endif
  23. #if defined _WIN32 && ! defined __CYGWIN__
  24. /* Native Windows API. */
  25. # include <io.h>
  26. #endif
  27. int
  28. pipe2 (int fd[2], int flags)
  29. {
  30. /* Mingw _pipe() corrupts fd on failure; also, if we succeed at
  31. creating the pipe but later fail at changing fcntl, we want
  32. to leave fd unchanged: http://austingroupbugs.net/view.php?id=467 */
  33. int tmp[2];
  34. tmp[0] = fd[0];
  35. tmp[1] = fd[1];
  36. #if HAVE_PIPE2
  37. # undef pipe2
  38. /* Try the system call first, if it exists. (We may be running with a glibc
  39. that has the function but with an older kernel that lacks it.) */
  40. {
  41. /* Cache the information whether the system call really exists. */
  42. static int have_pipe2_really; /* 0 = unknown, 1 = yes, -1 = no */
  43. if (have_pipe2_really >= 0)
  44. {
  45. int result = pipe2 (fd, flags);
  46. if (!(result < 0 && errno == ENOSYS))
  47. {
  48. have_pipe2_really = 1;
  49. return result;
  50. }
  51. have_pipe2_really = -1;
  52. }
  53. }
  54. #endif
  55. /* Check the supported flags. */
  56. if ((flags & ~(O_CLOEXEC | O_NONBLOCK | O_BINARY | O_TEXT)) != 0)
  57. {
  58. errno = EINVAL;
  59. return -1;
  60. }
  61. #if defined _WIN32 && ! defined __CYGWIN__
  62. /* Native Windows API. */
  63. if (_pipe (fd, 4096, flags & ~O_NONBLOCK) < 0)
  64. {
  65. fd[0] = tmp[0];
  66. fd[1] = tmp[1];
  67. return -1;
  68. }
  69. /* O_NONBLOCK handling.
  70. On native Windows platforms, O_NONBLOCK is defined by gnulib. Use the
  71. functions defined by the gnulib module 'nonblocking'. */
  72. # if GNULIB_defined_O_NONBLOCK
  73. if (flags & O_NONBLOCK)
  74. {
  75. if (set_nonblocking_flag (fd[0], true) != 0
  76. || set_nonblocking_flag (fd[1], true) != 0)
  77. goto fail;
  78. }
  79. # else
  80. {
  81. verify (O_NONBLOCK == 0);
  82. }
  83. # endif
  84. return 0;
  85. #else
  86. /* Unix API. */
  87. if (pipe (fd) < 0)
  88. return -1;
  89. /* POSIX <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html>
  90. says that initially, the O_NONBLOCK and FD_CLOEXEC flags are cleared on
  91. both fd[0] and fd[1]. */
  92. /* O_NONBLOCK handling.
  93. On Unix platforms, O_NONBLOCK is defined by the system. Use fcntl(). */
  94. if (flags & O_NONBLOCK)
  95. {
  96. int fcntl_flags;
  97. if ((fcntl_flags = fcntl (fd[1], F_GETFL, 0)) < 0
  98. || fcntl (fd[1], F_SETFL, fcntl_flags | O_NONBLOCK) == -1
  99. || (fcntl_flags = fcntl (fd[0], F_GETFL, 0)) < 0
  100. || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) == -1)
  101. goto fail;
  102. }
  103. if (flags & O_CLOEXEC)
  104. {
  105. int fcntl_flags;
  106. if ((fcntl_flags = fcntl (fd[1], F_GETFD, 0)) < 0
  107. || fcntl (fd[1], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1
  108. || (fcntl_flags = fcntl (fd[0], F_GETFD, 0)) < 0
  109. || fcntl (fd[0], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1)
  110. goto fail;
  111. }
  112. # if O_BINARY
  113. if (flags & O_BINARY)
  114. {
  115. set_binary_mode (fd[1], O_BINARY);
  116. set_binary_mode (fd[0], O_BINARY);
  117. }
  118. else if (flags & O_TEXT)
  119. {
  120. set_binary_mode (fd[1], O_TEXT);
  121. set_binary_mode (fd[0], O_TEXT);
  122. }
  123. # endif
  124. return 0;
  125. #endif
  126. #if GNULIB_defined_O_NONBLOCK || !(defined _WIN32 && ! defined __CYGWIN__)
  127. fail:
  128. {
  129. int saved_errno = errno;
  130. close (fd[0]);
  131. close (fd[1]);
  132. fd[0] = tmp[0];
  133. fd[1] = tmp[1];
  134. errno = saved_errno;
  135. return -1;
  136. }
  137. #endif
  138. }