Prefer new POSIX 200x interfaces over futimesat.
authorEric Blake <ebb9@byu.net>
Thu, 29 May 2008 03:29:02 +0000 (21:29 -0600)
committerEric Blake <ebb9@byu.net>
Thu, 29 May 2008 12:05:53 +0000 (06:05 -0600)
* m4/utimens.m4 (gl_UTIMENS): Check for futimens, utimensat.
* lib/utimens.c (gl_futimens): Use them for nanosecond resolution
when available.
[HAVE_BUGGY_NFS_TIME_STAMPS]: Allow C89 compilation.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
lib/utimens.c
m4/utimens.m4

index 9644194..dbabf96 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-05-29  Eric Blake  <ebb9@byu.net>
+
+       Prefer new POSIX 200x interfaces over futimesat.
+       * m4/utimens.m4 (gl_UTIMENS): Check for futimens, utimensat.
+       * lib/utimens.c (gl_futimens): Use them for nanosecond resolution
+       when available.
+       [HAVE_BUGGY_NFS_TIME_STAMPS]: Allow C89 compilation.
+
 2008-05-28  Bruno Haible  <bruno@clisp.org>
 
        * modules/stpcpy (License): Change to LGPLv2+.
index e128219..25bc965 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <sys/stat.h>
 #include <sys/time.h>
 #include <unistd.h>
 
@@ -94,89 +95,101 @@ gl_futimens (int fd ATTRIBUTE_UNUSED,
     fsync (fd);
 #endif
 
-  /* There's currently no interface to set file timestamps with
+  /* POSIX 200x added two interfaces to set file timestamps with
+     nanosecond resolution.  */
+#if HAVE_UTIMENSAT
+  if (fd < 0)
+    return utimensat (AT_FDCWD, file, timespec, 0);
+#endif
+#if HAVE_FUTIMENS
+  return futimens (fd, timespec);
+#else
+
+  /* The platform lacks an interface to set file timestamps with
      nanosecond resolution, so do the best we can, discarding any
      fractional part of the timestamp.  */
-#if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
-  struct timeval timeval[2];
-  struct timeval const *t;
-  if (timespec)
-    {
-      timeval[0].tv_sec = timespec[0].tv_sec;
-      timeval[0].tv_usec = timespec[0].tv_nsec / 1000;
-      timeval[1].tv_sec = timespec[1].tv_sec;
-      timeval[1].tv_usec = timespec[1].tv_nsec / 1000;
-      t = timeval;
-    }
-  else
-    t = NULL;
+  {
+# if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
+    struct timeval timeval[2];
+    struct timeval const *t;
+    if (timespec)
+      {
+       timeval[0].tv_sec = timespec[0].tv_sec;
+       timeval[0].tv_usec = timespec[0].tv_nsec / 1000;
+       timeval[1].tv_sec = timespec[1].tv_sec;
+       timeval[1].tv_usec = timespec[1].tv_nsec / 1000;
+       t = timeval;
+      }
+    else
+      t = NULL;
 
+    if (fd < 0)
+      {
+#  if HAVE_FUTIMESAT
+       return futimesat (AT_FDCWD, file, t);
+#  endif
+      }
+    else
+      {
+       /* 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
+          right away, but these cases are rare enough that they're not
+          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_FUTIMESAT
+       if (futimesat (fd, NULL, t) == 0)
+         return 0;
+#  elif HAVE_FUTIMES
+       if (futimes (fd, t) == 0)
+         return 0;
+#  endif
+      }
+# endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
 
-  if (fd < 0)
-    {
-# if HAVE_FUTIMESAT
-      return futimesat (AT_FDCWD, file, t);
-# endif
-    }
-  else
-    {
-      /* 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
-        right away, but these cases are rare enough that they're not
-        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_FUTIMESAT
-      if (futimesat (fd, NULL, t) == 0)
-       return 0;
-# elif HAVE_FUTIMES
-      if (futimes (fd, t) == 0)
-       return 0;
+    if (!file)
+      {
+# if ! (HAVE_FUTIMESAT || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
+       errno = ENOSYS;
 # endif
-    }
-#endif
 
-  if (!file)
-    {
-#if ! (HAVE_FUTIMESAT || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
-      errno = ENOSYS;
-#endif
+       /* Prefer EBADF to ENOSYS if both error numbers apply.  */
+       if (errno == ENOSYS)
+         {
+           int fd2 = dup (fd);
+           int dup_errno = errno;
+           if (0 <= fd2)
+             close (fd2);
+           errno = (fd2 < 0 && dup_errno == EBADF ? EBADF : ENOSYS);
+         }
+
+       return -1;
+      }
 
-      /* Prefer EBADF to ENOSYS if both error numbers apply.  */
-      if (errno == ENOSYS)
+# if HAVE_WORKING_UTIMES
+    return utimes (file, t);
+# else
+    {
+      struct utimbuf utimbuf;
+      struct utimbuf const *ut;
+      if (timespec)
        {
-         int fd2 = dup (fd);
-         int dup_errno = errno;
-         if (0 <= fd2)
-           close (fd2);
-         errno = (fd2 < 0 && dup_errno == EBADF ? EBADF : ENOSYS);
+         utimbuf.actime = timespec[0].tv_sec;
+         utimbuf.modtime = timespec[1].tv_sec;
+         ut = &utimbuf;
        }
+      else
+       ut = NULL;
 
-      return -1;
+      return utime (file, ut);
     }
-
-#if HAVE_WORKING_UTIMES
-  return utimes (file, t);
-#else
-  {
-    struct utimbuf utimbuf;
-    struct utimbuf const *ut;
-    if (timespec)
-      {
-       utimbuf.actime = timespec[0].tv_sec;
-       utimbuf.modtime = timespec[1].tv_sec;
-       ut = &utimbuf;
-      }
-    else
-      ut = NULL;
-
-    return utime (file, ut);
+# endif /* !HAVE_WORKING_UTIMES */
   }
-#endif
+#endif /* !HAVE_FUTIMENS */
 }
 
 /* Set the access and modification time stamps of FILE to be
index 9ac9c3e..01a3184 100644 (file)
@@ -1,8 +1,11 @@
-dnl Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+dnl Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Free Software
+dnl Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
 
+dnl serial 2
+
 AC_DEFUN([gl_UTIMENS],
 [
   AC_LIBOBJ([utimens])
@@ -11,5 +14,5 @@ AC_DEFUN([gl_UTIMENS],
   AC_REQUIRE([gl_FUNC_UTIMES])
   AC_REQUIRE([gl_CHECK_TYPE_STRUCT_TIMESPEC])
   AC_REQUIRE([gl_CHECK_TYPE_STRUCT_UTIMBUF])
-  AC_CHECK_FUNCS_ONCE([futimes futimesat])
+  AC_CHECK_FUNCS_ONCE([futimes futimesat futimens utimensat])
 ])