bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] test-utime: port to noatime file systems


From: Paul Eggert
Subject: [PATCH] test-utime: port to noatime file systems
Date: Fri, 9 Aug 2024 14:05:52 -0700

Problem encountered on Ubuntu 24.04 zfs mounted noatime.
* tests/test-fdutimensat.c (main):
* tests/test-futimens.h (test_futimens):
* tests/test-lutimens.h (test_lutimens):
* tests/test-utime.c (test_utime):
* tests/test-utimens-common.h (checkable_atime): New function.
* tests/test-utimens.h (test_utimens):
* tests/test-utimensat.c (main):
Do not check atime on file systems mounted noatime.
---
 ChangeLog                          | 13 ++++++++
 doc/posix-functions/futimens.texi  |  4 +++
 doc/posix-functions/utimensat.texi |  4 +++
 doc/posix-functions/utimes.texi    |  4 +++
 tests/test-fdutimensat.c           | 10 ++++--
 tests/test-futimens.h              | 36 ++++++++++++++--------
 tests/test-lutimens.h              | 49 +++++++++++++++++++-----------
 tests/test-utime.c                 | 27 +++++++++++-----
 tests/test-utimens-common.h        | 21 +++++++++++++
 tests/test-utimens.h               | 46 +++++++++++++++++++++-------
 tests/test-utimensat.c             | 12 ++++++--
 11 files changed, 171 insertions(+), 55 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index c31e68d8ee..e82dd02834 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2024-08-09  Paul Eggert  <eggert@cs.ucla.edu>
+
+       test-utime: port to noatime file systems
+       Problem encountered on Ubuntu 24.04 zfs mounted noatime.
+       * tests/test-fdutimensat.c (main):
+       * tests/test-futimens.h (test_futimens):
+       * tests/test-lutimens.h (test_lutimens):
+       * tests/test-utime.c (test_utime):
+       * tests/test-utimens-common.h (checkable_atime): New function.
+       * tests/test-utimens.h (test_utimens):
+       * tests/test-utimensat.c (main):
+       Do not check atime on file systems mounted noatime.
+
 2024-08-09  Bruno Haible  <bruno@clisp.org>
 
        pthread-rwlock: Attempt to avoid test failure on some machines.
diff --git a/doc/posix-functions/futimens.texi 
b/doc/posix-functions/futimens.texi
index 2c8beca267..7df36c09ce 100644
--- a/doc/posix-functions/futimens.texi
+++ b/doc/posix-functions/futimens.texi
@@ -35,6 +35,10 @@ glibc 2.11, musl libc, Solaris 11.
 Portability problems not fixed by Gnulib:
 @itemize
 @item
+On file systems mounted with the @code{noatime} attribute,
+this function might not modify the access time as requested:
+Linux kernel 6.9.
+@item
 Some platforms lack the ability to change the timestamps of a file
 descriptor, so the replacement can fail with @code{ENOSYS}; the gnulib
 module @samp{utimens} provides a more reliable interface @code{fdutimens}.
diff --git a/doc/posix-functions/utimensat.texi 
b/doc/posix-functions/utimensat.texi
index 9024235416..189c5cb79a 100644
--- a/doc/posix-functions/utimensat.texi
+++ b/doc/posix-functions/utimensat.texi
@@ -44,6 +44,10 @@ AIX 7.2.
 Portability problems not fixed by Gnulib:
 @itemize
 @item
+On file systems mounted with the @code{noatime} attribute,
+this function might not modify the access time as requested:
+Linux kernel 6.9.
+@item
 On some platforms, timestamps of symbolic links cannot be modified, so
 the replacement fails with @code{ENOSYS} if passed the flag
 @code{AT_SYMLINK_NOFOLLOW} on a symlink.
diff --git a/doc/posix-functions/utimes.texi b/doc/posix-functions/utimes.texi
index 70ab62f4b7..98a97184d9 100644
--- a/doc/posix-functions/utimes.texi
+++ b/doc/posix-functions/utimes.texi
@@ -24,6 +24,10 @@ some platforms incorrectly round rather than truncate.  Use
 @code{utimensat(AT_FDCWD,file,times,0)}, or the gnulib module @code{utimens},
 instead.
 @item
+On file systems mounted with the @code{noatime} attribute,
+this function might not modify the access time as requested:
+Linux kernel 6.9.
+@item
 On some platforms, @code{utimes (file, NULL)} fails to set the
 file's timestamp to the current time:
 glibc 2.3.3.
diff --git a/tests/test-fdutimensat.c b/tests/test-fdutimensat.c
index a21e297f03..5f8d0f6d07 100644
--- a/tests/test-fdutimensat.c
+++ b/tests/test-fdutimensat.c
@@ -118,7 +118,7 @@ main (void)
   /* Directory relative tests.  */
   ASSERT (mkdir (BASE "dir", 0700) == 0);
   ASSERT (chdir (BASE "dir") == 0);
-  fd = creat ("file", 0600);
+  fd = open ("file", O_RDWR | O_CREAT | O_TRUNC, 0600);
   ASSERT (0 <= fd);
   errno = 0;
   ASSERT (fdutimensat (AT_FDCWD, fd, ".", NULL, 0) == -1);
@@ -126,13 +126,17 @@ main (void)
   {
     struct timespec ts[2];
     struct stat st;
+    bool check_atime = checkable_atime (fd, &st);
     ts[0].tv_sec = Y2K;
     ts[0].tv_nsec = 0;
     ts[1] = ts[0];
     ASSERT (fdutimensat (fd, dfd, BASE "dir/file", ts, 0) == 0);
     ASSERT (stat ("file", &st) == 0);
-    ASSERT (st.st_atime == Y2K);
-    ASSERT (get_stat_atime_ns (&st) == 0);
+    if (check_atime)
+      {
+        ASSERT (st.st_atime == Y2K);
+        ASSERT (get_stat_atime_ns (&st) == 0);
+      }
     ASSERT (st.st_mtime == Y2K);
     ASSERT (get_stat_mtime_ns (&st) == 0);
   }
diff --git a/tests/test-futimens.h b/tests/test-futimens.h
index a6fd5c15cf..af8f630cc9 100644
--- a/tests/test-futimens.h
+++ b/tests/test-futimens.h
@@ -24,14 +24,14 @@ static int
 test_futimens (int (*func) (int, struct timespec const *),
                bool print)
 {
-  int fd = creat (BASE "file", 0600);
+  int fd = open (BASE "file", O_RDWR | O_CREAT | O_TRUNC, 0600);
   int result;
   struct stat st1;
   struct stat st2;
   ASSERT (0 <= fd);
+  bool check_atime = checkable_atime (fd, &st1);
 
   /* Sanity check.  */
-  ASSERT (fstat (fd, &st1) == 0);
   nap ();
   errno = 0;
   result = func (fd, NULL);
@@ -117,8 +117,11 @@ test_futimens (int (*func) (int, struct timespec const *),
     ASSERT (errno == EINVAL);
   }
   ASSERT (fstat (fd, &st2) == 0);
-  ASSERT (st1.st_atime == st2.st_atime);
-  ASSERT (get_stat_atime_ns (&st1) == get_stat_atime_ns (&st2));
+  if (check_atime)
+    {
+      ASSERT (st1.st_atime == st2.st_atime);
+      ASSERT (get_stat_atime_ns (&st1) == get_stat_atime_ns (&st2));
+    }
   ASSERT (utimecmp (BASE "file", &st1, &st2, 0) == 0);
 
   /* Set both times.  */
@@ -130,9 +133,12 @@ test_futimens (int (*func) (int, struct timespec const *),
     ts[1].tv_nsec = BILLION - 1;
     ASSERT (func (fd, ts) == 0);
     ASSERT (fstat (fd, &st2) == 0);
-    ASSERT (st2.st_atime == Y2K);
-    ASSERT (0 <= get_stat_atime_ns (&st2));
-    ASSERT (get_stat_atime_ns (&st2) < BILLION / 2);
+    if (check_atime)
+      {
+        ASSERT (st2.st_atime == Y2K);
+        ASSERT (0 <= get_stat_atime_ns (&st2));
+        ASSERT (get_stat_atime_ns (&st2) < BILLION / 2);
+      }
     ASSERT (st2.st_mtime == Y2K);
     ASSERT (0 <= get_stat_mtime_ns (&st2));
     ASSERT (get_stat_mtime_ns (&st2) < BILLION);
@@ -151,9 +157,12 @@ test_futimens (int (*func) (int, struct timespec const *),
     nap ();
     ASSERT (func (fd, ts) == 0);
     ASSERT (fstat (fd, &st3) == 0);
-    ASSERT (st3.st_atime == Y2K);
-    ASSERT (0 <= get_stat_atime_ns (&st3));
-    ASSERT (get_stat_atime_ns (&st3) <= BILLION / 2);
+    if (check_atime)
+      {
+        ASSERT (st3.st_atime == Y2K);
+        ASSERT (0 <= get_stat_atime_ns (&st3));
+        ASSERT (get_stat_atime_ns (&st3) <= BILLION / 2);
+      }
     ASSERT (utimecmp (BASE "file", &st1, &st3, UTIMECMP_TRUNCATE_SOURCE) <= 0);
     if (check_ctime)
       ASSERT (ctime_compare (&st2, &st3) < 0);
@@ -162,8 +171,11 @@ test_futimens (int (*func) (int, struct timespec const *),
     ts[1].tv_nsec = UTIME_OMIT;
     ASSERT (func (fd, ts) == 0);
     ASSERT (fstat (fd, &st2) == 0);
-    ASSERT (st2.st_atime == BILLION);
-    ASSERT (get_stat_atime_ns (&st2) == 0);
+    if (check_atime)
+      {
+        ASSERT (st2.st_atime == BILLION);
+        ASSERT (get_stat_atime_ns (&st2) == 0);
+      }
     ASSERT (st3.st_mtime == st2.st_mtime);
     ASSERT (get_stat_mtime_ns (&st3) == get_stat_mtime_ns (&st2));
     if (check_ctime > 0)
diff --git a/tests/test-lutimens.h b/tests/test-lutimens.h
index 385b3c0acc..b909ec4b75 100644
--- a/tests/test-lutimens.h
+++ b/tests/test-lutimens.h
@@ -27,7 +27,6 @@ test_lutimens (int (*func) (char const *, struct timespec 
const *), bool print)
   int saved_errno;
   struct stat st1;
   struct stat st2;
-  bool atime_supported = true;
 
   /* Non-symlinks should be handled just like utimens.  */
   errno = 0;
@@ -39,10 +38,15 @@ test_lutimens (int (*func) (char const *, struct timespec 
const *), bool print)
   errno = 0;
   ASSERT (func ("", NULL) == -1);
   ASSERT (errno == ENOENT);
-  ASSERT (close (creat (BASE "file", 0600)) == 0);
-  ASSERT (stat (BASE "file", &st1) == 0);
+
+  int fd = open (BASE "file", O_RDWR | O_CREAT | O_TRUNC, 0600);
+  ASSERT (0 <= fd);
+
+  bool check_atime = checkable_atime (fd, &st1);
+  ASSERT (close (fd) == 0);
   ASSERT (st1.st_atime != Y2K);
   ASSERT (st1.st_mtime != Y2K);
+
   {
     struct timespec ts[2];
     ts[0].tv_sec = Y2K;
@@ -52,7 +56,8 @@ test_lutimens (int (*func) (char const *, struct timespec 
const *), bool print)
     ASSERT (func (BASE "file/", ts) == -1);
     ASSERT (errno == ENOTDIR);
     ASSERT (stat (BASE "file", &st2) == 0);
-    ASSERT (st1.st_atime == st2.st_atime);
+    if (check_atime)
+      ASSERT (st1.st_atime == st2.st_atime);
     ASSERT (st1.st_mtime == st2.st_mtime);
   }
   {
@@ -64,7 +69,8 @@ test_lutimens (int (*func) (char const *, struct timespec 
const *), bool print)
     ASSERT (func (BASE "file", ts) == 0);
   }
   ASSERT (stat (BASE "file", &st2) == 0);
-  ASSERT (st2.st_atime == Y2K);
+  if (check_atime)
+    ASSERT (st2.st_atime == Y2K);
   ASSERT (st2.st_mtime == Y2K);
   if (check_ctime)
     ASSERT (ctime_compare (&st1, &st2) < 0);
@@ -83,10 +89,12 @@ test_lutimens (int (*func) (char const *, struct timespec 
const *), bool print)
   saved_errno = errno;
   /* Make sure we did not reference through link by accident.  */
   ASSERT (stat (BASE "file", &st1) == 0);
-  ASSERT (st1.st_atime == Y2K);
+  if (check_atime)
+    ASSERT (st1.st_atime == Y2K);
   ASSERT (st1.st_mtime == Y2K);
   ASSERT (lstat (BASE "link", &st1) == 0);
-  ASSERT (st1.st_atime != Y2K);
+  if (check_atime)
+    ASSERT (st1.st_atime != Y2K);
   ASSERT (st1.st_mtime != Y2K);
   ASSERT (unlink (BASE "file") == 0);
   if (result == -1 && saved_errno == ENOSYS)
@@ -100,13 +108,16 @@ test_lutimens (int (*func) (char const *, struct timespec 
const *), bool print)
     }
   ASSERT (!result);
   ASSERT (lstat (BASE "link", &st1) == 0);
-  /* On cygwin, lstat() changes atime of symlinks, so that lutimens
-     can only effectively modify mtime.  */
   nap ();
   ASSERT (lstat (BASE "link", &st2) == 0);
-  if (st1.st_atime != st2.st_atime
-      || get_stat_atime_ns (&st1) != get_stat_atime_ns (&st2))
-    atime_supported = false;
+
+  /* On cygwin, lstat() changes atime of symlinks, so that lutimens
+     can effectively modify only mtime.  */
+  bool check_atime_on_symlinks
+    = (check_atime
+       && st1.st_atime == st2.st_atime
+       && get_stat_atime_ns (&st1) == get_stat_atime_ns (&st2));
+
   ASSERT (st1.st_ctime == st2.st_ctime);
   ASSERT (get_stat_ctime_ns (&st1) == get_stat_ctime_ns (&st2));
 
@@ -132,7 +143,7 @@ test_lutimens (int (*func) (char const *, struct timespec 
const *), bool print)
     ASSERT (errno == EINVAL);
   }
   ASSERT (lstat (BASE "link", &st2) == 0);
-  if (atime_supported)
+  if (check_atime_on_symlinks)
     {
       ASSERT (st1.st_atime == st2.st_atime);
       ASSERT (get_stat_atime_ns (&st1) == get_stat_atime_ns (&st2));
@@ -149,7 +160,7 @@ test_lutimens (int (*func) (char const *, struct timespec 
const *), bool print)
     nap ();
     ASSERT (func (BASE "link", ts) == 0);
     ASSERT (lstat (BASE "link", &st2) == 0);
-    if (atime_supported)
+    if (check_atime_on_symlinks)
       {
         ASSERT (st2.st_atime == Y2K);
         ASSERT (0 <= get_stat_atime_ns (&st2));
@@ -173,7 +184,7 @@ test_lutimens (int (*func) (char const *, struct timespec 
const *), bool print)
     nap ();
     ASSERT (func (BASE "link", ts) == 0);
     ASSERT (lstat (BASE "link", &st3) == 0);
-    if (atime_supported)
+    if (check_atime_on_symlinks)
       {
         ASSERT (st3.st_atime == Y2K);
         ASSERT (0 <= get_stat_atime_ns (&st3));
@@ -187,7 +198,7 @@ test_lutimens (int (*func) (char const *, struct timespec 
const *), bool print)
     ts[1].tv_nsec = UTIME_OMIT;
     ASSERT (func (BASE "link", ts) == 0);
     ASSERT (lstat (BASE "link", &st2) == 0);
-    if (atime_supported)
+    if (check_atime_on_symlinks)
       {
         ASSERT (st2.st_atime == BILLION);
         ASSERT (get_stat_atime_ns (&st2) == 0);
@@ -214,13 +225,15 @@ test_lutimens (int (*func) (char const *, struct timespec 
const *), bool print)
   ASSERT (stat (BASE "dir", &st1) == 0);
   ASSERT (st1.st_mtime == Y2K);
   ASSERT (lstat (BASE "link", &st1) == 0);
-  ASSERT (st1.st_atime != Y2K);
+  if (check_atime)
+    ASSERT (st1.st_atime != Y2K);
   ASSERT (st1.st_mtime != Y2K);
   ASSERT (func (BASE "link", NULL) == 0);
   ASSERT (stat (BASE "dir", &st1) == 0);
   ASSERT (st1.st_mtime == Y2K);
   ASSERT (lstat (BASE "link", &st1) == 0);
-  ASSERT (st1.st_atime != Y2K);
+  if (check_atime)
+    ASSERT (st1.st_atime != Y2K);
   ASSERT (st1.st_mtime != Y2K);
 
   /* Cleanup.  */
diff --git a/tests/test-utime.c b/tests/test-utime.c
index 00cee63265..fd87f91cd8 100644
--- a/tests/test-utime.c
+++ b/tests/test-utime.c
@@ -35,8 +35,11 @@ test_utime (bool print)
   struct stat st1;
   struct stat st2;
 
-  ASSERT (close (creat (BASE "file", 0600)) == 0);
-  ASSERT (stat (BASE "file", &st1) == 0);
+  int fd = open (BASE "file", O_RDWR | O_CREAT | O_TRUNC, 0600);
+  ASSERT (0 <= fd);
+  bool check_atime = checkable_atime (fd, &st1);
+  ASSERT (close (fd) == 0);
+
   nap ();
   ASSERT (utime (BASE "file", NULL) == 0);
   ASSERT (stat (BASE "file", &st2) == 0);
@@ -76,8 +79,11 @@ test_utime (bool print)
     ASSERT (errno == ENOTDIR || errno == EINVAL);
   }
   ASSERT (stat (BASE "file", &st2) == 0);
-  ASSERT (st1.st_atime == st2.st_atime);
-  ASSERT (get_stat_atime_ns (&st1) == get_stat_atime_ns (&st2));
+  if (check_atime)
+    {
+      ASSERT (st1.st_atime == st2.st_atime);
+      ASSERT (get_stat_atime_ns (&st1) == get_stat_atime_ns (&st2));
+    }
   ASSERT (utimecmp (BASE "file", &st1, &st2, 0) == 0);
 
   /* Set both times.  */
@@ -86,9 +92,12 @@ test_utime (bool print)
     ts.actime = ts.modtime = Y2K;
     ASSERT (utime (BASE "file", &ts) == 0);
     ASSERT (stat (BASE "file", &st2) == 0);
-    ASSERT (st2.st_atime == Y2K);
-    ASSERT (0 <= get_stat_atime_ns (&st2));
-    ASSERT (get_stat_atime_ns (&st2) < BILLION / 2);
+    if (check_atime)
+      {
+        ASSERT (st2.st_atime == Y2K);
+        ASSERT (0 <= get_stat_atime_ns (&st2));
+        ASSERT (get_stat_atime_ns (&st2) < BILLION / 2);
+      }
     ASSERT (st2.st_mtime == Y2K);
     ASSERT (0 <= get_stat_mtime_ns (&st2));
     ASSERT (get_stat_mtime_ns (&st2) < BILLION);
@@ -117,7 +126,9 @@ test_utime (bool print)
     ts.actime = ts.modtime = Y2K;
     ASSERT (utime (BASE "link", &ts) == 0);
     ASSERT (lstat (BASE "link", &st2) == 0);
-    /* Can't compare atimes, since lstat() changes symlink atime on cygwin.  */
+    /* Make sure symlink time hasn't been modified.
+       Can't compare symlink atimes, since when utime follows the
+       symlink it might update the symlink atime.  */
     ASSERT (st1.st_mtime == st2.st_mtime);
     ASSERT (stat (BASE "link", &st2) == 0);
     ASSERT (st2.st_mtime == Y2K);
diff --git a/tests/test-utimens-common.h b/tests/test-utimens-common.h
index 317a01b3da..f9fdb9a867 100644
--- a/tests/test-utimens-common.h
+++ b/tests/test-utimens-common.h
@@ -79,4 +79,25 @@ ctime_compare (struct stat const *a, struct stat const *b)
     return 0;
 }
 
+/* Test whether FD's file access times are updated by the file system.
+   FD must be readable.  Set *ST to the file's status, after any
+   change to its access time due to the test.  */
+static bool
+checkable_atime (int fd, struct stat *st)
+{
+  char buf[1];
+  struct stat st1, st2;
+
+  ASSERT (fstat (fd, &st1) == 0);
+  nap ();
+  ASSERT (read (fd, buf, sizeof buf) == 0);
+  ASSERT (fstat (fd, &st2) == 0);
+  bool check_atime
+    = (st1.st_atime != st2.st_atime
+       || get_stat_atime_ns (&st1) != get_stat_atime_ns (&st2));
+  if (st)
+    *st = st2;
+  return check_atime;
+}
+
 #endif /* GL_TEST_UTIMENS_COMMON */
diff --git a/tests/test-utimens.h b/tests/test-utimens.h
index 83d785a4dd..256d48de90 100644
--- a/tests/test-utimens.h
+++ b/tests/test-utimens.h
@@ -26,13 +26,18 @@ test_utimens (int (*func) (char const *, struct timespec 
const *), bool print)
   struct stat st1;
   struct stat st2;
 
-  ASSERT (close (creat (BASE "file", 0600)) == 0);
+  int fd = open (BASE "file", O_RDWR | O_CREAT | O_TRUNC, 0600);
+  ASSERT (0 <= fd);
   /* If utimens truncates to worse resolution than the file system
      supports, then time can appear to go backwards between now and a
      follow-up utimens with UTIME_NOW or a NULL timespec.  Use
      UTIMECMP_TRUNCATE_SOURCE to compensate, with st1 as the
      source.  */
-  ASSERT (stat (BASE "file", &st1) == 0);
+  bool check_atime = checkable_atime (fd, &st1);
+  ASSERT (close (fd) == 0);
+  ASSERT (st1.st_atime != Y2K);
+  ASSERT (st1.st_mtime != Y2K);
+
   nap ();
   ASSERT (func (BASE "file", NULL) == 0);
   ASSERT (stat (BASE "file", &st2) == 0);
@@ -108,9 +113,12 @@ test_utimens (int (*func) (char const *, struct timespec 
const *), bool print)
     ts[1].tv_nsec = BILLION - 1;
     ASSERT (func (BASE "file", ts) == 0);
     ASSERT (stat (BASE "file", &st2) == 0);
-    ASSERT (st2.st_atime == Y2K);
-    ASSERT (0 <= get_stat_atime_ns (&st2));
-    ASSERT (get_stat_atime_ns (&st2) < BILLION / 2);
+    if (check_atime)
+      {
+        ASSERT (st2.st_atime == Y2K);
+        ASSERT (0 <= get_stat_atime_ns (&st2));
+        ASSERT (get_stat_atime_ns (&st2) < BILLION / 2);
+      }
     ASSERT (st2.st_mtime == Y2K);
     ASSERT (0 <= get_stat_mtime_ns (&st2));
     ASSERT (get_stat_mtime_ns (&st2) < BILLION);
@@ -129,9 +137,12 @@ test_utimens (int (*func) (char const *, struct timespec 
const *), bool print)
     nap ();
     ASSERT (func (BASE "file", ts) == 0);
     ASSERT (stat (BASE "file", &st3) == 0);
-    ASSERT (st3.st_atime == Y2K);
-    ASSERT (0 <= get_stat_atime_ns (&st3));
-    ASSERT (get_stat_atime_ns (&st3) < BILLION / 2);
+    if (check_atime)
+      {
+        ASSERT (st3.st_atime == Y2K);
+        ASSERT (0 <= get_stat_atime_ns (&st3));
+        ASSERT (get_stat_atime_ns (&st3) < BILLION / 2);
+      }
     /* See comment above about this utimecmp call.  */
     ASSERT (0 <= utimecmp (BASE "file", &st3, &st1, UTIMECMP_TRUNCATE_SOURCE));
     if (check_ctime)
@@ -141,8 +152,11 @@ test_utimens (int (*func) (char const *, struct timespec 
const *), bool print)
     ts[1].tv_nsec = UTIME_OMIT;
     ASSERT (func (BASE "file", ts) == 0);
     ASSERT (stat (BASE "file", &st2) == 0);
-    ASSERT (st2.st_atime == BILLION);
-    ASSERT (get_stat_atime_ns (&st2) == 0);
+    if (check_atime)
+      {
+        ASSERT (st2.st_atime == BILLION);
+        ASSERT (get_stat_atime_ns (&st2) == 0);
+      }
     ASSERT (st3.st_mtime == st2.st_mtime);
     ASSERT (get_stat_mtime_ns (&st3) == get_stat_mtime_ns (&st2));
     if (check_ctime > 0)
@@ -170,9 +184,19 @@ test_utimens (int (*func) (char const *, struct timespec 
const *), bool print)
     ts[1] = ts[0];
     ASSERT (func (BASE "link", ts) == 0);
     ASSERT (lstat (BASE "link", &st2) == 0);
-    /* Can't compare atimes, since lstat() changes symlink atime on cygwin.  */
+
+    /* Make sure symlink time hasn't been modified.
+       Can't compare symlink atimes, since when func follows the
+       symlink it might update the symlink atime.  */
     ASSERT (st1.st_mtime == st2.st_mtime);
+    ASSERT (get_stat_mtime_ns (&st1) == get_stat_mtime_ns (&st2));
+
     ASSERT (stat (BASE "link", &st2) == 0);
+    if (check_atime)
+      {
+        ASSERT (st2.st_atime == BILLION);
+        ASSERT (get_stat_atime_ns (&st2) == 0);
+      }
     ASSERT (st2.st_mtime == Y2K);
     ASSERT (get_stat_mtime_ns (&st2) == 0);
   }
diff --git a/tests/test-utimensat.c b/tests/test-utimensat.c
index 6819a335de..0f7d73b3c1 100644
--- a/tests/test-utimensat.c
+++ b/tests/test-utimensat.c
@@ -94,8 +94,11 @@ main (void)
   /* Directory-relative tests.  */
   ASSERT (mkdir (BASE "dir", 0700) == 0);
   ASSERT (chdir (BASE "dir") == 0);
-  fd = creat ("file", 0600);
+  fd = open ("file", O_RDWR | O_CREAT | O_TRUNC, 0600);
   ASSERT (0 <= fd);
+
+  bool check_atime = checkable_atime (fd, NULL);
+
   errno = 0;
   ASSERT (utimensat (fd, ".", NULL, 0) == -1);
   ASSERT (errno == ENOTDIR);
@@ -108,8 +111,11 @@ main (void)
     ts[1].tv_nsec = 0;
     ASSERT (utimensat (dfd, BASE "dir/file", ts, AT_SYMLINK_NOFOLLOW) == 0);
     ASSERT (stat ("file", &st) == 0);
-    ASSERT (st.st_atime == Y2K);
-    ASSERT (get_stat_atime_ns (&st) == 0);
+    if (check_atime)
+      {
+        ASSERT (st.st_atime == Y2K);
+        ASSERT (get_stat_atime_ns (&st) == 0);
+      }
     ASSERT (st.st_mtime == Y2K);
     ASSERT (get_stat_mtime_ns (&st) == 0);
   }
-- 
2.43.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]