Browse Source

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 <dm.chestnykh@gmail.com>
Dmitry Chestnykh 2 months ago
parent
commit
ee7e012b71

+ 4 - 0
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

+ 0 - 3
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__

+ 3 - 2
libc/sysdeps/linux/common/fstat.c

@@ -10,10 +10,11 @@
 #include <unistd.h>
 #include <sys/stat.h>
 #include <sys/syscall.h>
+#include <bits/uClibc_arch_features.h>
 
 #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 <fcntl.h>
 # include <statx_cp.h>
 

+ 1 - 1
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;
 }

+ 2 - 9
libc/sysdeps/linux/common/fstatat.c

@@ -9,13 +9,14 @@
 #include <sys/syscall.h>
 #include <sys/stat.h>
 #include "xstatconv.h"
+#include <bits/uClibc_arch_features.h>
 
 /* 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;

+ 3 - 5
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

+ 2 - 1
libc/sysdeps/linux/common/lstat.c

@@ -9,8 +9,9 @@
 #include <sys/syscall.h>
 #include <unistd.h>
 #include <sys/stat.h>
+#include <bits/uClibc_arch_features.h>
 
-#if defined __NR_fstatat64 && !defined __NR_lstat
+#if defined __NR_fstatat64 && !defined __NR_lstat && !defined(__UCLIBC_USE_TIME64__)
 # include <fcntl.h>
 
 int lstat(const char *file_name, struct stat *buf)

+ 2 - 1
libc/sysdeps/linux/common/stat.c

@@ -9,10 +9,11 @@
 #include <sys/syscall.h>
 #include <unistd.h>
 #include <sys/stat.h>
+#include <bits/uClibc_arch_features.h>
 
 #undef stat
 
-#if defined __NR_fstatat64 && !defined __NR_stat
+#if defined __NR_fstatat64 && !defined __NR_stat && !defined(__UCLIBC_USE_TIME64__)
 # include <fcntl.h>
 
 int stat(const char *file_name, struct stat *buf)

+ 1 - 1
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;
 }

+ 1 - 1
libc/sysdeps/linux/common/statx_cp.c

@@ -24,7 +24,7 @@
 
 #include <statx_cp.h>
 
-#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)
 {

+ 0 - 3
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__

+ 0 - 3
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__
 

+ 0 - 3
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__