+2009-07-21 Eric Blake <ebb9@byu.net>
+
+ dup2: fix more mingw problems
+ * lib/dup2.c (rpl_dup2) [_WIN32]: Avoid hanging when duplicating
+ fd to itself.
+ * doc/posix-functions/dup2.texi (dup2): Document the bug.
+ * lib/unistd.in.h (dup2) [REPLACE_FCHDIR]: Avoid name collision.
+ * lib/fchdir.c (dup2): Manage preprocessor macros correctly.
+ (rpl_dup2_fchdir): Rename from rpl_dup2, and let dup2 module take
+ care of mingw bugs.
+
2009-07-21 Jim Meyering <meyering@redhat.com>
vc-list-files: avoid failure when /bin/sh is dash
This function always returns 0 for success on some platforms:
mingw.
+@item
+This function can hang when duplicating an fd to itself on some platforms:
+mingw.
+
@item
This function returns 0 for dup2 (1, 1) on some platforms:
Cygwin 1.5.x.
#include <errno.h>
#include <fcntl.h>
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Get declarations of the Win32 API functions. */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
#if REPLACE_DUP2
-/* On mingw, dup2 exists, but always returns 0 for success. */
+
+# undef dup2
+
int
-dup2 (int fd, int desired_fd)
-#undef dup2
+rpl_dup2 (int fd, int desired_fd)
{
- int result = dup2 (fd, desired_fd);
+ int result;
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open,
+ dup2 (fd, fd) returns 0, but all further attempts to use fd in
+ future dup2 calls will hang. */
+ if (fd == desired_fd)
+ {
+ if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+ return fd;
+ }
+# endif
+ result = dup2 (fd, desired_fd);
if (result == 0)
result = desired_fd;
return result;
}
#else /* !REPLACE_DUP2 */
+
/* On older platforms, dup2 did not exist. */
# ifndef F_DUPFD
return newfd;
}
+/* Our <unistd.h> replacement overrides dup2 twice; be sure to pick
+ the one we want. */
+#if REPLACE_DUP2
+# undef dup2
+# define dup2 rpl_dup2
+#endif
+
int
-rpl_dup2 (int oldfd, int newfd)
-#undef dup2
+rpl_dup2_fchdir (int oldfd, int newfd)
{
int retval = dup2 (oldfd, newfd);
-#if REPLACE_DUP2
- /* Inline mingw replacement from dup2.c. */
- if (retval == 0)
- retval = newfd;
-#endif
- if (retval >= 0 && oldfd >= 0 && newfd >= 0 && newfd != oldfd)
+ if (retval >= 0 && newfd != oldfd)
{
ensure_dirs_slot (newfd);
if (newfd < dirs_allocated)
# define dup rpl_dup
extern int dup (int);
-# if !@REPLACE_DUP2@
-# define dup2 rpl_dup2
-extern int dup2 (int, int);
+
+# if @REPLACE_DUP2@
+# undef dup2
# endif
+# define dup2 rpl_dup2_fchdir
+extern int dup2 (int, int);
# endif
#elif defined GNULIB_POSIXCHECK