fdutimensat: drop atflag validation
authorEric Blake <eblake@redhat.com>
Fri, 17 Sep 2010 14:29:16 +0000 (08:29 -0600)
committerEric Blake <eblake@redhat.com>
Fri, 17 Sep 2010 14:34:59 +0000 (08:34 -0600)
* 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>
ChangeLog
lib/fdutimensat.c
tests/test-fdutimensat.c

index 624e41222175f8cdf87b4733e2698b69b4dd2e38..54319d5c5d44f61d213d104cf38a8323ec0faab5 100644 (file)
--- 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.
index 77f893bb3b05ff25ffa117aff9142c13561afdb0..0219a783266477deae65ab25595546f5f42d741e 100644 (file)
@@ -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 @@ fdutimensat (int dir, char const *file, int fd, struct timespec const ts[2],
              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)
index 67f03bbb507b27b62e856d993761772bc28845be..80eb373d0076b024b15b27d0675e8876d5998ed8 100644 (file)
@@ -53,6 +53,7 @@ do_fdutimens (char const *name, struct timespec const times[2])
     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 @@ main (void)
   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);
   {