utimens: cache whether utimensat syscall works
[pspp] / lib / dup3.c
index 62cdb53d317a73611339ed649d8a3f9fbe4fe3b0..879a9074f2cfbf53626ddc3839db7f1a5eaf093a 100644 (file)
@@ -29,6 +29,8 @@
 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
 /* Native Woe32 API.  */
 
+# include <string.h>
+
 /* Get declarations of the Win32 API functions.  */
 # define WIN32_LEAN_AND_MEAN
 # include <windows.h>
@@ -53,9 +55,22 @@ dup3 (int oldfd, int newfd, int flags)
   /* Try the system call first, if it exists.  (We may be running with a glibc
      that has the function but with an older kernel that lacks it.)  */
   {
-    int result = dup3 (oldfd, newfd, flags);
-    if (!(result < 0 && errno == ENOSYS))
-      return result;
+    /* Cache the information whether the system call really exists.  */
+    static int have_dup3_really; /* 0 = unknown, 1 = yes, -1 = no */
+    if (have_dup3_really >= 0)
+      {
+       int result = dup3 (oldfd, newfd, flags);
+       if (!(result < 0 && errno == ENOSYS))
+         {
+           have_dup3_really = 1;
+#if REPLACE_FCHDIR
+           if (0 <= result)
+             result = _gl_register_dup (oldfd, newfd);
+#endif
+           return result;
+         }
+       have_dup3_really = -1;
+      }
   }
 #endif
 
@@ -169,6 +184,10 @@ dup3 (int oldfd, int newfd, int flags)
        errno = saved_errno;
       }
 
+#if REPLACE_FCHDIR
+      if (result == newfd)
+       result = _gl_register_dup (oldfd, newfd);
+#endif
       return result;
     }
 
@@ -207,5 +226,8 @@ dup3 (int oldfd, int newfd, int flags)
     setmode (newfd, O_TEXT);
 #endif
 
+#if REPLACE_FCHDIR
+  newfd = _gl_register_dup (oldfd, newfd);
+#endif
   return newfd;
 }