From ee7e012b71dd3a964dc8bd3a82acddc24aceebc7 Mon Sep 17 00:00:00 2001 From: Dmitry Chestnykh Date: Mon, 26 Feb 2024 22:13:22 +0300 Subject: Fix *stat() and *stat64() when the time is beyond year 2038. To obtain correct `st_atim`, `st_mtim` and `st_ctim` fields we need to use statx() syscall and then convert the data from the kernel to the regular stat structure. Signed-off-by: Dmitry Chestnykh --- Rules.mak | 4 ++++ libc/sysdeps/linux/arm/bits/uClibc_arch_features.h | 3 --- libc/sysdeps/linux/common/fstat.c | 5 +++-- libc/sysdeps/linux/common/fstat64.c | 2 +- libc/sysdeps/linux/common/fstatat.c | 11 ++--------- libc/sysdeps/linux/common/fstatat64.c | 8 +++----- libc/sysdeps/linux/common/lstat.c | 3 ++- libc/sysdeps/linux/common/stat.c | 3 ++- libc/sysdeps/linux/common/stat64.c | 2 +- libc/sysdeps/linux/common/statx_cp.c | 2 +- libc/sysdeps/linux/mips/bits/uClibc_arch_features.h | 3 --- libc/sysdeps/linux/powerpc/bits/uClibc_arch_features.h | 3 --- libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h | 3 --- 13 files changed, 19 insertions(+), 33 deletions(-) diff --git a/Rules.mak b/Rules.mak index a51e98b92..55c2f81fe 100644 --- a/Rules.mak +++ b/Rules.mak @@ -670,6 +670,10 @@ ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) CFLAGS += -D__USE_STDIO_FUTEXES__ endif +ifeq ($(UCLIBC_USE_TIME64),y) +CFLAGS += -D__UCLIBC_HAVE_STATX__ +endif + ifeq ($(UCLIBC_HAS_THREADS),y) ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) PTNAME := nptl diff --git a/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h b/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h index b0b093c99..671afd3ac 100644 --- a/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h +++ b/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h @@ -11,9 +11,6 @@ /* can your target use syscall6() for mmap ? */ #undef __UCLIBC_MMAP_HAS_6_ARGS__ -/* does your target use statx */ -#undef __UCLIBC_HAVE_STATX__ - /* does your target align 64bit values in register pairs ? (32bit arches only) */ #ifdef __ARM_EABI__ #define __UCLIBC_SYSCALL_ALIGN_64BIT__ diff --git a/libc/sysdeps/linux/common/fstat.c b/libc/sysdeps/linux/common/fstat.c index 86c24bff6..65e879799 100644 --- a/libc/sysdeps/linux/common/fstat.c +++ b/libc/sysdeps/linux/common/fstat.c @@ -10,10 +10,11 @@ #include #include #include +#include #include "xstatconv.h" -#if defined __NR_fstat64 && !defined __NR_fstat +#if defined __NR_fstat64 && !defined __NR_fstat && !defined(__UCLIBC_USE_TIME64__) int fstat(int fd, struct stat *buf) { return INLINE_SYSCALL(fstat64, 2, fd, buf); @@ -29,7 +30,7 @@ int fstat(int fd, struct stat *buf) } libc_hidden_def(fstat) -#elif __NR_statx && defined __UCLIBC_HAVE_STATX__ +#elif defined __NR_statx && defined __UCLIBC_HAVE_STATX__ # include # include diff --git a/libc/sysdeps/linux/common/fstat64.c b/libc/sysdeps/linux/common/fstat64.c index fe1cb4fe5..20a9acf01 100644 --- a/libc/sysdeps/linux/common/fstat64.c +++ b/libc/sysdeps/linux/common/fstat64.c @@ -45,7 +45,7 @@ int fstat64(int fd, struct stat64 *buf) int rc = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH, STATX_BASIC_STATS, &tmp); if (rc == 0) - __cp_stat_statx ((struct stat64 *)buf, &tmp); + __cp_stat64_statx ((struct stat64 *)buf, &tmp); return rc; } diff --git a/libc/sysdeps/linux/common/fstatat.c b/libc/sysdeps/linux/common/fstatat.c index d4f566a62..14b118cc0 100644 --- a/libc/sysdeps/linux/common/fstatat.c +++ b/libc/sysdeps/linux/common/fstatat.c @@ -9,13 +9,14 @@ #include #include #include "xstatconv.h" +#include /* 64bit ports tend to favor newfstatat() */ #if __WORDSIZE == 64 && defined __NR_newfstatat # define __NR_fstatat64 __NR_newfstatat #endif -#ifdef __NR_fstatat64 +#if defined(__NR_fstatat64) && !defined(__UCLIBC_USE_TIME64__) int fstatat(int fd, const char *file, struct stat *buf, int flag) { int ret; @@ -62,14 +63,6 @@ int fstatat(int fd, const char *file, struct stat *buf, int flag) .st_mtim.tv_nsec = tmp.stx_mtime.tv_nsec, .st_ctim.tv_sec = tmp.stx_ctime.tv_sec, .st_ctim.tv_nsec = tmp.stx_ctime.tv_nsec, -#if defined(__UCLIBC_USE_TIME64__) && !defined(__mips__) - .__st_atim32.tv_sec = stx.stx_atime.tv_sec, - .__st_atim32.tv_nsec = stx.stx_atime.tv_nsec, - .__st_mtim32.tv_sec = stx.stx_mtime.tv_sec, - .__st_mtim32.tv_nsec = stx.stx_mtime.tv_nsec, - .__st_ctim32.tv_sec = stx.stx_ctime.tv_sec, - .__st_ctim32.tv_nsec = stx.stx_ctime.tv_nsec, -#endif }; return ret; diff --git a/libc/sysdeps/linux/common/fstatat64.c b/libc/sysdeps/linux/common/fstatat64.c index 836ed4114..fdd17a0b7 100644 --- a/libc/sysdeps/linux/common/fstatat64.c +++ b/libc/sysdeps/linux/common/fstatat64.c @@ -56,12 +56,10 @@ int fstatat64(int fd, const char *file, struct stat64 *buf, int flag) int r = INLINE_SYSCALL(statx, 5, fd, file, AT_NO_AUTOMOUNT | flag, STATX_BASIC_STATS, &tmp); - if (r != 0) - return r; + if (r == 0) + __cp_stat64_statx ((struct stat *)buf, &tmp); - __cp_stat_statx ((struct stat *)buf, &tmp); - - return 0; + return r; } libc_hidden_def(fstatat64) #endif diff --git a/libc/sysdeps/linux/common/lstat.c b/libc/sysdeps/linux/common/lstat.c index 8a0baf85f..2ebd8615e 100644 --- a/libc/sysdeps/linux/common/lstat.c +++ b/libc/sysdeps/linux/common/lstat.c @@ -9,8 +9,9 @@ #include #include #include +#include -#if defined __NR_fstatat64 && !defined __NR_lstat +#if defined __NR_fstatat64 && !defined __NR_lstat && !defined(__UCLIBC_USE_TIME64__) # include int lstat(const char *file_name, struct stat *buf) diff --git a/libc/sysdeps/linux/common/stat.c b/libc/sysdeps/linux/common/stat.c index 99ce8d2dd..42f39aea6 100644 --- a/libc/sysdeps/linux/common/stat.c +++ b/libc/sysdeps/linux/common/stat.c @@ -9,10 +9,11 @@ #include #include #include +#include #undef stat -#if defined __NR_fstatat64 && !defined __NR_stat +#if defined __NR_fstatat64 && !defined __NR_stat && !defined(__UCLIBC_USE_TIME64__) # include int stat(const char *file_name, struct stat *buf) diff --git a/libc/sysdeps/linux/common/stat64.c b/libc/sysdeps/linux/common/stat64.c index 47d938b11..fdd2c49a9 100644 --- a/libc/sysdeps/linux/common/stat64.c +++ b/libc/sysdeps/linux/common/stat64.c @@ -30,7 +30,7 @@ int stat64(const char *file_name, struct stat64 *buf) int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, file_name, AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &tmp); if (rc == 0) - __cp_stat_statx ((struct stat64 *)buf, &tmp); + __cp_stat64_statx ((struct stat64 *)buf, &tmp); return rc; } diff --git a/libc/sysdeps/linux/common/statx_cp.c b/libc/sysdeps/linux/common/statx_cp.c index 9f024eec8..c50d28ecb 100644 --- a/libc/sysdeps/linux/common/statx_cp.c +++ b/libc/sysdeps/linux/common/statx_cp.c @@ -24,7 +24,7 @@ #include -#if !defined(__NR_fstat64) || !defined(__NR_fstatat64) +#if (!defined(__NR_fstat64) || !defined(__NR_fstatat64)) || defined(__UCLIBC_USE_TIME64__) void __cp_stat64_statx (struct stat64 *to, struct statx *from) { diff --git a/libc/sysdeps/linux/mips/bits/uClibc_arch_features.h b/libc/sysdeps/linux/mips/bits/uClibc_arch_features.h index 59d9f0807..bcdf124a4 100644 --- a/libc/sysdeps/linux/mips/bits/uClibc_arch_features.h +++ b/libc/sysdeps/linux/mips/bits/uClibc_arch_features.h @@ -12,9 +12,6 @@ /* can your target use syscall6() for mmap ? */ #define __UCLIBC_MMAP_HAS_6_ARGS__ -/* does your target use statx */ -#undef __UCLIBC_HAVE_STATX__ - /* does your target align 64bit values in register pairs ? (32bit arches only) */ #if _MIPS_SIM == _ABIO32 #define __UCLIBC_SYSCALL_ALIGN_64BIT__ diff --git a/libc/sysdeps/linux/powerpc/bits/uClibc_arch_features.h b/libc/sysdeps/linux/powerpc/bits/uClibc_arch_features.h index bc6ae652e..661069384 100644 --- a/libc/sysdeps/linux/powerpc/bits/uClibc_arch_features.h +++ b/libc/sysdeps/linux/powerpc/bits/uClibc_arch_features.h @@ -11,9 +11,6 @@ /* can your target use syscall6() for mmap ? */ #define __UCLIBC_MMAP_HAS_6_ARGS__ -/* does your target use statx */ -#undef __UCLIBC_HAVE_STATX__ - /* does your target align 64bit values in register pairs ? (32bit arches only) */ #define __UCLIBC_SYSCALL_ALIGN_64BIT__ diff --git a/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h b/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h index de9b38983..a15744c2f 100644 --- a/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h +++ b/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h @@ -11,9 +11,6 @@ /* can your target use syscall6() for mmap ? */ #define __UCLIBC_MMAP_HAS_6_ARGS__ -/* does your target use statx */ -#undef __UCLIBC_HAVE_STATX__ - /* does your target align 64bit values in register pairs ? (32bit arches only) */ #define __UCLIBC_SYSCALL_ALIGN_64BIT__ -- cgit v1.2.3