aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2024-12-19 20:56:44 +0100
committerFlorian Weimer <fweimer@redhat.com>2024-12-19 21:21:30 +0100
commit70d083630563831e7069ad412cd3ab0b33638e92 (patch)
tree19489200ed8cdda06adac90a48b3b602bdd0fefe
parent30d3fd7f4f4bc8f767d73ad4e4b005c1bd234310 (diff)
downloadglibc-70d083630563831e7069ad412cd3ab0b33638e92.tar.xz
glibc-70d083630563831e7069ad412cd3ab0b33638e92.zip
Linux: Accept null arguments for utimensat pathname
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>
-rw-r--r--io/sys/stat.h4
-rw-r--r--io/tst-utimensat.c32
-rw-r--r--sysdeps/unix/sysv/linux/utimensat.c3
3 files changed, 34 insertions, 5 deletions
diff --git a/io/sys/stat.h b/io/sys/stat.h
index 0e4edb483d..dd96b88d0f 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -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
diff --git a/io/tst-utimensat.c b/io/tst-utimensat.c
index 2a756d7b07..43786817b5 100644
--- a/io/tst-utimensat.c
+++ b/io/tst-utimensat.c
@@ -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,
diff --git a/sysdeps/unix/sysv/linux/utimensat.c b/sysdeps/unix/sysv/linux/utimensat.c
index 991897f50d..f3ba1aa647 100644
--- a/sysdeps/unix/sysv/linux/utimensat.c
+++ b/sysdeps/unix/sysv/linux/utimensat.c
@@ -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);
}