pipe2.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /* Create a pipe, with specific opening flags.
  2. Copyright (C) 2009-2020 Free Software Foundation, Inc.
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 3, or (at your option)
  6. any later version.
  7. This program 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 General Public License for more details.
  11. You should have received a copy of the GNU General Public License along
  12. 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. }