dup2.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /* Duplicate an open file descriptor to a specified file descriptor.
  2. Copyright (C) 1999, 2004-2007, 2009-2010 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 of the License, or
  6. (at your option) 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
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. /* written by Paul Eggert */
  14. #include <config.h>
  15. /* Specification. */
  16. #include <unistd.h>
  17. #include <errno.h>
  18. #include <fcntl.h>
  19. #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
  20. /* Get declarations of the Win32 API functions. */
  21. # define WIN32_LEAN_AND_MEAN
  22. # include <windows.h>
  23. #endif
  24. #if HAVE_DUP2
  25. # undef dup2
  26. int
  27. rpl_dup2 (int fd, int desired_fd)
  28. {
  29. int result;
  30. # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
  31. /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open,
  32. dup2 (fd, fd) returns 0, but all further attempts to use fd in
  33. future dup2 calls will hang. */
  34. if (fd == desired_fd)
  35. {
  36. if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE)
  37. {
  38. errno = EBADF;
  39. return -1;
  40. }
  41. return fd;
  42. }
  43. /* Wine 1.0.1 return 0 when desired_fd is negative but not -1:
  44. http://bugs.winehq.org/show_bug.cgi?id=21289 */
  45. if (desired_fd < 0)
  46. {
  47. errno = EBADF;
  48. return -1;
  49. }
  50. # endif
  51. result = dup2 (fd, desired_fd);
  52. # ifdef __linux__
  53. /* Correct a Linux return value.
  54. <http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.30.y.git;a=commitdiff;h=2b79bc4f7ebbd5af3c8b867968f9f15602d5f802>
  55. */
  56. if (fd == desired_fd && result == (unsigned int) -EBADF)
  57. {
  58. errno = EBADF;
  59. result = -1;
  60. }
  61. # endif
  62. if (result == 0)
  63. result = desired_fd;
  64. /* Correct a cygwin 1.5.x errno value. */
  65. else if (result == -1 && errno == EMFILE)
  66. errno = EBADF;
  67. # if REPLACE_FCHDIR
  68. if (fd != desired_fd && result != -1)
  69. result = _gl_register_dup (fd, result);
  70. # endif
  71. return result;
  72. }
  73. #else /* !HAVE_DUP2 */
  74. /* On older platforms, dup2 did not exist. */
  75. # ifndef F_DUPFD
  76. static int
  77. dupfd (int fd, int desired_fd)
  78. {
  79. int duplicated_fd = dup (fd);
  80. if (duplicated_fd < 0 || duplicated_fd == desired_fd)
  81. return duplicated_fd;
  82. else
  83. {
  84. int r = dupfd (fd, desired_fd);
  85. int e = errno;
  86. close (duplicated_fd);
  87. errno = e;
  88. return r;
  89. }
  90. }
  91. # endif
  92. int
  93. dup2 (int fd, int desired_fd)
  94. {
  95. int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd;
  96. if (result == -1 || fd == desired_fd)
  97. return result;
  98. close (desired_fd);
  99. # ifdef F_DUPFD
  100. result = fcntl (fd, F_DUPFD, desired_fd);
  101. # if REPLACE_FCHDIR
  102. if (0 <= result)
  103. result = _gl_register_dup (fd, result);
  104. # endif
  105. # else
  106. result = dupfd (fd, desired_fd);
  107. # endif
  108. if (result == -1 && (errno == EMFILE || errno == EINVAL))
  109. errno = EBADF;
  110. return result;
  111. }
  112. #endif /* !HAVE_DUP2 */