On 18/03/2021 22:18, YunQiang Su wrote:
> diff --git a/sysdeps/unix/sysv/linux/fstatat.c b/sysdeps/unix/sysv/linux/fstatat.c
> index 59efff615f..ccb6027b64 100644
> --- a/sysdeps/unix/sysv/linux/fstatat.c
> +++ b/sysdeps/unix/sysv/linux/fstatat.c
> @@ -37,7 +37,12 @@ __fstatat (int fd, const char *file, struct stat *buf, int flag)
> || buf->__st_blocks_pad != 0))
> return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
> # else
> -# ifdef __NR_fstatat64
> +# if defined(STAT_KERNEL64_TIME32_T)
> + /* Some architecture, like MIPS N64, is 64bit, while its kernel_stat has 32bit timespec.
> + Since they are 64bit, and time_t is also 64bit, it is safe for this cast */
> + return __fstatat64_time64(fd, file, (struct __stat64_t64 *)buf, flag);
> +# endif
I am not very found of this aliasing violation, specially because my
refactor tried exactly to avoid it on the newer implementations
(only the old xstat does require them because of the way the compat
is implemented).
> diff --git a/sysdeps/unix/sysv/linux/statx_cp.h b/sysdeps/unix/sysv/linux/statx_cp.h
> index 634330aaa6..cc1ae4698d 100644
> --- a/sysdeps/unix/sysv/linux/statx_cp.h
> +++ b/sysdeps/unix/sysv/linux/statx_cp.h
> @@ -18,6 +18,10 @@
>
> extern void __cp_stat64_statx (struct stat64 *to, struct statx *from)
> attribute_hidden;
> +#if defined(STAT_KERNEL64_TIME32_T)
> +# define __cp_stat64_t64_statx __cp_stat64_statx
> +#else
> extern void __cp_stat64_t64_statx (struct __stat64_t64 *to,
> const struct statx *from)
> attribute_hidden;
> +#endif
Instead of adding this hack, it is better to just open code the
__cp_stat64_t64_statx (it is used solely on fstatat64).
> diff --git a/sysdeps/unix/sysv/linux/tst-futimens.c b/sysdeps/unix/sysv/linux/tst-futimens.c
> index 785cd87557..67a411db74 100644
> --- a/sysdeps/unix/sysv/linux/tst-futimens.c
> +++ b/sysdeps/unix/sysv/linux/tst-futimens.c
> @@ -37,6 +37,9 @@ const struct timespec t2[2] = { { 0x80000001ULL, 0 }, { 0x80000002ULL, 0 } };
> /* struct timespec array around Y2038 threshold. */
> const struct timespec t3[2] = { { 0x7FFFFFFE, 0 }, { 0x80000002ULL, 0 } };
>
> +/* struct timespec array around -1: may trigger Y2106 problem */
> +const struct timespec t4[2] = { { -1, 0 }, { -2, 0 } };
> +
> #define PREPARE do_prepare
> static void
> do_prepare (int argc, char *argv[])
> @@ -83,6 +86,7 @@ do_test (void)
> test_futimens_helper (&t1[0]);
> test_futimens_helper (&t2[0]);
> test_futimens_helper (&t3[0]);
> + test_futimens_helper (&t4[0]);
>
> return 0;
> }
This test will fail on MIPSn64 kernels older than 4.11.
I have sent a more complete fix, that also fixes the s390 issue regarding
missing nanoseconds and improves the tests to handle the y2106 issue as
well [1].
[1] https://patchwork.sourceware.org/project/glibc/list/?series=1878
@@ -37,7 +37,12 @@ __fstatat (int fd, const char *file, struct stat *buf, int flag)
|| buf->__st_blocks_pad != 0))
return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
# else
-# ifdef __NR_fstatat64
+# if defined(STAT_KERNEL64_TIME32_T)
+ /* Some architecture, like MIPS N64, is 64bit, while its kernel_stat has 32bit timespec.
+ Since they are 64bit, and time_t is also 64bit, it is safe for this cast */
+ return __fstatat64_time64(fd, file, (struct __stat64_t64 *)buf, flag);
+# endif
+# if defined(__NR_fstatat64)
/* Old KABIs with old non-LFS support, e.g. arm, i386, hppa, m68k, mips32,
microblaze, s390, sh, powerpc, and sparc. */
struct stat64 st64;
@@ -72,7 +77,7 @@ __fstatat (int fd, const char *file, struct stat *buf, int flag)
return 0;
}
# else
- /* 64-bit kabi outlier, e.g. mips64 and mips64-n32. */
+ /* 64-bit kabi outlier, e.g. mips64-n32. */
struct kernel_stat kst;
r = INTERNAL_SYSCALL_CALL (newfstatat, fd, file, &kst, flag);
if (r == 0)
@@ -47,9 +47,12 @@ __fstatat64_time64 (int fd, const char *file, struct __stat64_t64 *buf,
int r;
#if (__WORDSIZE == 32 \
- && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
+ && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
+ || defined(STAT_KERNEL64_TIME32_T)
/* 32-bit kABI with default 64-bit time_t, e.g. arc, riscv32. Also
64-bit time_t support is done through statx syscall. */
+ /* the time_sec members of kernel_stat struct on some architecture
+ is unsigned 32bit, which has Y2106 problem. MIPS N64 is an example. */
struct statx tmp;
r = INTERNAL_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT | flag,
STATX_BASIC_STATS, &tmp);
@@ -68,4 +68,9 @@ struct kernel_stat
# define STATFS_IS_STATFS64 0
#endif
+/* the time_sec members of kernel_stat struct is uint32_t, which has Y2106 problem */
+#if _MIPS_SIM == _ABI64
+#define STAT_KERNEL64_TIME32_T 1
+#endif
+
#endif
@@ -18,6 +18,10 @@
extern void __cp_stat64_statx (struct stat64 *to, struct statx *from)
attribute_hidden;
+#if defined(STAT_KERNEL64_TIME32_T)
+# define __cp_stat64_t64_statx __cp_stat64_statx
+#else
extern void __cp_stat64_t64_statx (struct __stat64_t64 *to,
const struct statx *from)
attribute_hidden;
+#endif
@@ -37,6 +37,9 @@ const struct timespec t2[2] = { { 0x80000001ULL, 0 }, { 0x80000002ULL, 0 } };
/* struct timespec array around Y2038 threshold. */
const struct timespec t3[2] = { { 0x7FFFFFFE, 0 }, { 0x80000002ULL, 0 } };
+/* struct timespec array around -1: may trigger Y2106 problem */
+const struct timespec t4[2] = { { -1, 0 }, { -2, 0 } };
+
#define PREPARE do_prepare
static void
do_prepare (int argc, char *argv[])
@@ -83,6 +86,7 @@ do_test (void)
test_futimens_helper (&t1[0]);
test_futimens_helper (&t2[0]);
test_futimens_helper (&t3[0]);
+ test_futimens_helper (&t4[0]);
return 0;
}
@@ -39,6 +39,9 @@ const static struct utimbuf t2 = { 0x80000001ULL, 0x80000002ULL };
/* struct utimbuf around Y2038 threshold. */
const static struct utimbuf t3 = { 0x7FFFFFFE, 0x80000002ULL };
+/* struct timespec array around -1: may trigger Y2106 problem */
+const static struct utimbuf t4 = { -1, -2 };
+
#define PREPARE do_prepare
static void
do_prepare (int argc, char *argv[])
@@ -85,6 +88,7 @@ do_test (void)
test_utime_helper (&t1);
test_utime_helper (&t2);
test_utime_helper (&t3);
+ test_utime_helper (&t4);
return 0;
}
@@ -40,6 +40,10 @@ struct timeval t2[2] = { { 0x80000001ULL, 0 }, { 0x80000002ULL, 0 } };
const static
struct timeval t3[2] = { { 0x7FFFFFFE, 0 }, { 0x80000002ULL, 0 } };
+/* struct timespec array around -1: may trigger Y2106 problem */
+const static
+struct timeval t4[2] = { { -1, 0 }, { -2, 0 } };
+
#define PREPARE do_prepare
static void
do_prepare (int argc, char *argv[])
@@ -86,6 +90,7 @@ do_test (void)
test_utime_helper (&t1[0]);
test_utime_helper (&t2[0]);
test_utime_helper (&t3[0]);
+ test_utime_helper (&t4[0]);
return 0;
}