changeset 13694:5a8df829305e

fdutimensat: drop atflag validation * lib/fdutimensat.c (fdutimensat): Allow AT_SYMLINK_NOFOLLOW even with valid fd, to close a race scenario where futimens is unsupported and FILE was replaced by a symlink. * tests/test-fdutimensat.c (do_fdutimens, main): Adjust test accordingly. Suggested by Paul Eggert. Signed-off-by: Eric Blake <eblake@redhat.com>
author Eric Blake <eblake@redhat.com>
date Fri, 17 Sep 2010 08:29:16 -0600
parents 9b64bed10922
children 8a06cdf65b57
files ChangeLog lib/fdutimensat.c tests/test-fdutimensat.c
diffstat 3 files changed, 14 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2010-09-17  Eric Blake  <eblake@redhat.com>
+
+	fdutimensat: drop atflag validation
+	* lib/fdutimensat.c (fdutimensat): Allow AT_SYMLINK_NOFOLLOW even
+	with valid fd, to close a race scenario where futimens is
+	unsupported and FILE was replaced by a symlink.
+	* tests/test-fdutimensat.c (do_fdutimens, main): Adjust test
+	accordingly.
+	Suggested by Paul Eggert.
+
 2010-09-16  Bruno Haible  <bruno@clisp.org>
 
 	unlockpt: Fix declaration within GNULIB_POSIXCHECK.
--- a/lib/fdutimensat.c
+++ b/lib/fdutimensat.c
@@ -35,8 +35,8 @@
    use just futimes (or equivalent) instead of utimes (or equivalent),
    and fail if on an old system without futimes (or equivalent).
    If TIMESPEC is null, set the time stamps to the current time.
-   ATFLAG must be 0 if FD is non-negative; otherwise it may be
-   AT_SYMLINK_NOFOLLOW to operate on FILE as a symlink.
+   ATFLAG is passed to utimensat if FD is negative or futimens was
+   unsupported, which can allow operation on FILE as a symlink.
    Return 0 on success, -1 (setting errno) on failure.  */
 
 int
@@ -44,20 +44,8 @@
              int atflag)
 {
   int result = 1;
-  if (atflag & ~AT_SYMLINK_NOFOLLOW)
-    {
-      errno = EINVAL;
-      return -1;
-    }
   if (0 <= fd)
-    {
-      if (atflag)
-        {
-          errno = EINVAL;
-          return -1;
-        }
-      result = futimens (fd, ts);
-    }
+    result = futimens (fd, ts);
   if (file && (fd < 0 || (result == -1 && errno == ENOSYS)))
     result = utimensat (dir, file, ts, atflag);
   if (result == 1)
--- a/tests/test-fdutimensat.c
+++ b/tests/test-fdutimensat.c
@@ -53,6 +53,7 @@
     fd = openat (dfd, name, O_RDONLY);
   errno = 0;
   result = fdutimensat (dfd, name, fd, times, 0);
+  ASSERT (fdutimensat (dfd, name, fd, times, AT_SYMLINK_NOFOLLOW) == result);
   if (0 <= fd)
     {
       int saved_errno = errno;
@@ -116,9 +117,6 @@
   fd = creat ("file", 0600);
   ASSERT (0 <= fd);
   errno = 0;
-  ASSERT (fdutimensat (fd, ".", fd, NULL, AT_SYMLINK_NOFOLLOW) == -1);
-  ASSERT (errno == EINVAL);
-  errno = 0;
   ASSERT (fdutimensat (fd, ".", AT_FDCWD, NULL, 0) == -1);
   ASSERT (errno == ENOTDIR);
   {