changeset 12401:4e193de62444

dup2: fix logic bugs If the platform has dup2, don't register with fchdir if the destination was -1. If the platform lacks dup2 (are there any these days?), then don't close the destination unless the source is valid, make sure errno is correct, and only register with fchdir on fcntl (since dup is already overridden to do a registration). * lib/dup2.c (dup2): Fix logic bugs. Use HAVE_DUP2 rather than REPLACE_DUP2 to decide when rpl_dup2 is needed. * m4/dup2.m4 (gl_REPLACE_DUP2): Only define REPLACE_DUP2 when dup2 exists. (gl_FUNC_DUP2): Drop unneeded AC_SUBST. Signed-off-by: Eric Blake <ebb9@byu.net>
author Eric Blake <ebb9@byu.net>
date Mon, 07 Dec 2009 21:08:17 -0700
parents eacc6f30863b
children af3596b94c7a
files ChangeLog lib/dup2.c m4/dup2.m4
diffstat 3 files changed, 29 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2009-12-08  Eric Blake  <ebb9@byu.net>
+
+	dup2: fix logic bugs
+	* lib/dup2.c (dup2): Fix logic bugs.  Use HAVE_DUP2 rather than
+	REPLACE_DUP2 to decide when rpl_dup2 is needed.
+	* m4/dup2.m4 (gl_REPLACE_DUP2): Only define REPLACE_DUP2 when dup2
+	exists.
+	(gl_FUNC_DUP2): Drop unneeded AC_SUBST.
+
 2009-12-07  Eric Blake  <ebb9@byu.net>
 
 	unlink: fix m4 detection
--- a/lib/dup2.c
+++ b/lib/dup2.c
@@ -32,7 +32,7 @@
 # include <windows.h>
 #endif
 
-#if REPLACE_DUP2
+#if HAVE_DUP2
 
 # undef dup2
 
@@ -70,14 +70,14 @@
   /* Correct a cygwin 1.5.x errno value.  */
   else if (result == -1 && errno == EMFILE)
     errno = EBADF;
-#if REPLACE_FCHDIR
-  if (fd != desired_fd && result == desired_fd)
-    result = _gl_register_dup (fd, desired_fd);
-#endif
+# if REPLACE_FCHDIR
+  if (fd != desired_fd && result != -1)
+    result = _gl_register_dup (fd, result);
+# endif
   return result;
 }
 
-#else /* !REPLACE_DUP2 */
+#else /* !HAVE_DUP2 */
 
 /* On older platforms, dup2 did not exist.  */
 
@@ -102,19 +102,21 @@
 int
 dup2 (int fd, int desired_fd)
 {
-  int result;
-  if (fd == desired_fd)
-    return fcntl (fd, F_GETFL) < 0 ? -1 : fd;
+  int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd;
+  if (result == -1 || fd == desired_fd)
+    return result;
   close (desired_fd);
 # ifdef F_DUPFD
   result = fcntl (fd, F_DUPFD, desired_fd);
+#  if REPLACE_FCHDIR
+  if (0 <= result)
+    result = _gl_register_dup (fd, result);
+#  endif
 # else
   result = dupfd (fd, desired_fd);
 # endif
-#if REPLACE_FCHDIR
-  if (0 <= result)
-    result = _gl_register_dup (fd, desired_fd);
-#endif
+  if (result == -1 && (errno == EMFILE || errno == EINVAL))
+    errno = EBADF;
   return result;
 }
-#endif /* !REPLACE_DUP2 */
+#endif /* !HAVE_DUP2 */
--- a/m4/dup2.m4
+++ b/m4/dup2.m4
@@ -1,4 +1,4 @@
-#serial 9
+#serial 10
 dnl Copyright (C) 2002, 2005, 2007, 2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -46,13 +46,13 @@
       gl_REPLACE_DUP2
     fi
   fi
-  AC_DEFINE_UNQUOTED([REPLACE_DUP2], [$REPLACE_DUP2],
-    [Define to 1 if dup2 returns 0 instead of the target fd.])
 ])
 
 AC_DEFUN([gl_REPLACE_DUP2],
 [
   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
-  REPLACE_DUP2=1
+  if test $ac_cv_func_dup2 = yes; then
+    REPLACE_DUP2=1
+  fi
   AC_LIBOBJ([dup2])
 ])