changeset 12317:407921985bc0

utimens: fix regression on Solaris Revert commit 26c5fd742f. Solaris lacks futimens and futimes, so futimesat is the only way to change fd timestamps. But since FreeBSD futimesat can't change fd timestamps, we need a configure check to avoid the crash there. * m4/utimens.m4 (gl_UTIMENS): Check for BSD bug. * lib/utimens.c (fdutimens): Revert 2009-11-08 change; Solaris 10 can only change fd timestamps via futimesat. Instead, use an additional witness macro to avoid BSD bug. Reported by Jim Meyering. Signed-off-by: Eric Blake <ebb9@byu.net>
author Eric Blake <ebb9@byu.net>
date Wed, 18 Nov 2009 06:59:44 -0700
parents d47887220b68
children 0661ed228251
files ChangeLog lib/utimens.c m4/utimens.m4
diffstat 3 files changed, 43 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2009-11-18  Eric Blake  <ebb9@byu.net>
+
+	utimens: fix regression on Solaris
+	* m4/utimens.m4 (gl_UTIMENS): Check for BSD bug.
+	* lib/utimens.c (fdutimens): Revert 2009-11-08 change; Solaris 10
+	can only change fd timestamps via futimesat.  Instead, use an
+	additional witness macro to avoid BSD bug.
+	Reported by Jim Meyering.
+
 2009-11-17  Eric Blake  <ebb9@byu.net>
 
 	usleep: use it to simplify tests
--- a/lib/utimens.c
+++ b/lib/utimens.c
@@ -280,9 +280,9 @@
       }
     else
       {
-        /* If futimesat (above) or futimes fails here, don't try to speed
-           things up by returning right away.  glibc can incorrectly fail
-           with errno == ENOENT if /proc isn't mounted.  Also, Mandrake 10.0
+        /* If futimesat or futimes fails here, don't try to speed things
+           up by returning right away.  glibc can incorrectly fail with
+           errno == ENOENT if /proc isn't mounted.  Also, Mandrake 10.0
            in high security mode doesn't allow ordinary users to read
            /proc/self, so glibc incorrectly fails with errno == EACCES.
            If errno == EIO, EPERM, or EROFS, it's probably safe to fail
@@ -290,7 +290,10 @@
            worth optimizing, and who knows what other messed-up systems
            are out there?  So play it safe and fall back on the code
            below.  */
-# if HAVE_FUTIMES
+# if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
+        if (futimesat (fd, NULL, t) == 0)
+          return 0;
+# elif HAVE_FUTIMES
         if (futimes (fd, t) == 0)
           return 0;
 # endif
@@ -299,7 +302,8 @@
 
     if (!file)
       {
-#if ! (HAVE_FUTIMESAT || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
+#if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG)          \
+        || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
         errno = ENOSYS;
 #endif
         return -1;
--- a/m4/utimens.m4
+++ b/m4/utimens.m4
@@ -4,7 +4,7 @@
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
 
-dnl serial 3
+dnl serial 4
 
 AC_DEFUN([gl_UTIMENS],
 [
@@ -15,4 +15,28 @@
   AC_REQUIRE([gl_CHECK_TYPE_STRUCT_TIMESPEC])
   AC_REQUIRE([gl_CHECK_TYPE_STRUCT_UTIMBUF])
   AC_CHECK_FUNCS_ONCE([futimes futimesat futimens utimensat lutimes])
+
+  if test $ac_cv_func_futimens = no && test $ac_cv_func_futimesat = yes; then
+    dnl FreeBSD 8.0-rc2 mishandles futimesat(fd,NULL,time).  It is not
+    dnl standardized, but Solaris implemented it first and uses it as
+    dnl its only means to set fd time.
+    AC_CACHE_CHECK([whether futimesat handles NULL file],
+      [gl_cv_func_futimesat_works],
+      [touch conftest.file
+       AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#include <stddef.h>
+#include <sys/times.h>
+]], [[    int fd = open ("conftest.file", O_RDWR);
+          if (fd < 0) return 1;
+          if (futimesat (fd, NULL, NULL)) return 2;
+        ]])],
+        [gl_cv_func_futimesat_works=yes],
+        [gl_cv_func_futimesat_works=no],
+        [gl_cv_func_futimesat_works="guessing no"])
+      rm -f conftest.file])
+    if test "$gl_cv_func_futimesat_works" != yes; then
+      AC_DEFINE([FUTIMESAT_NULL_BUG], [1],
+        [Define to 1 if futimesat mishandles a NULL file name.])
+    fi
+  fi
 ])