]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Linux: Accept null arguments for utimensat pathname
authorFlorian Weimer <fweimer@redhat.com>
Thu, 19 Dec 2024 19:56:44 +0000 (20:56 +0100)
committerFlorian Weimer <fweimer@redhat.com>
Thu, 19 Dec 2024 20:21:30 +0000 (21:21 +0100)
This matches kernel behavior.  With this change, it is possible
to use utimensat as a replacement for the futimens interface,
similar to what glibc does internally.

Reviewed-by: Paul Eggert <eggert@cs.ucla.edu>
io/sys/stat.h
io/tst-utimensat.c
sysdeps/unix/sysv/linux/utimensat.c

index 0e4edb483d1f20616040524577ceb004c6b2618d..dd96b88d0f740a22d614ea7680076d209c41d8f7 100644 (file)
@@ -433,13 +433,13 @@ extern int mkfifoat (int __fd, const char *__path, __mode_t __mode)
 extern int utimensat (int __fd, const char *__path,
                      const struct timespec __times[2],
                      int __flags)
-     __THROW __nonnull ((2));
+     __THROW;
 # else
 #  ifdef __REDIRECT_NTH
 extern int __REDIRECT_NTH (utimensat, (int fd, const char *__path,
                                        const struct timespec __times[2],
                                        int flags),
-                           __utimensat64) __nonnull ((2));
+                           __utimensat64);
 #  else
 #   define utimensat __utimensat64
 #  endif
index 2a756d7b07b6b07ff8cf5e5dcba387de4004996f..43786817b501c62a72b9f808ec0224ba13cacd53 100644 (file)
@@ -39,6 +39,38 @@ test_utimesat_helper (const char *testfile, int fd, const char *testlink,
     TEST_COMPARE (st.stx_mtime.tv_sec, ts[1].tv_sec);
   }
 
+  /* Alter the timestamp using a NULL path.  */
+  {
+    struct timespec ts1[2] = {ts[0], ts[1]};
+    ts1[0].tv_sec ^= 1;
+    ts1[1].tv_sec ^= 1;
+
+    TEST_VERIFY_EXIT (utimensat (fd, NULL, ts1, 0) == 0);
+
+    struct statx st;
+    xstatx (fd, "", AT_EMPTY_PATH, STATX_BASIC_STATS, &st);
+
+    /* Check if seconds for atime match */
+    TEST_COMPARE (st.stx_atime.tv_sec, ts[0].tv_sec ^ 1);
+
+    /* Check if seconds for mtime match */
+    TEST_COMPARE (st.stx_mtime.tv_sec, ts[1].tv_sec ^ 1);
+  }
+
+  /* And switch it back using a NULL path.  */
+  {
+    TEST_VERIFY_EXIT (utimensat (fd, NULL, ts, 0) == 0);
+
+    struct statx st;
+    xstatx (fd, "", AT_EMPTY_PATH, STATX_BASIC_STATS, &st);
+
+    /* Check if seconds for atime match */
+    TEST_COMPARE (st.stx_atime.tv_sec, ts[0].tv_sec);
+
+    /* Check if seconds for mtime match */
+    TEST_COMPARE (st.stx_mtime.tv_sec, ts[1].tv_sec);
+  }
+
   {
     struct statx stfile_orig;
     xstatx (AT_FDCWD, testfile, AT_SYMLINK_NOFOLLOW, STATX_BASIC_STATS,
index 991897f50d14209c185ed33d1d4374b119216a60..f3ba1aa6471bbfa107ee0c1d99b168361dd4e832 100644 (file)
@@ -75,9 +75,6 @@ int
 __utimensat64 (int fd, const char *file, const struct __timespec64 tsp64[2],
                int flags)
 {
-  if (file == NULL)
-    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
-
   return __utimensat64_helper (fd, file, &tsp64[0], flags);
 }