From 0df50640a4ece7c74f17827f158f6c8812c6bede Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Thu, 20 Nov 2025 12:16:15 +0100 Subject: [PATCH] Use __fstat64_time64 in __fts64_children_time64 (bug 33653) Make sure that fts_safe_changedir can handle a directory with a time stamp after y2038. --- io/Makefile | 1 + io/fts.c | 5 +++-- io/fts64-time64.c | 1 + io/fts64.c | 1 + io/tst-fts-time64-y2038.c | 3 +++ io/tst-fts.c | 35 ++++++++++++++++++++++++++++++++++- 6 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 io/tst-fts-time64-y2038.c diff --git a/io/Makefile b/io/Makefile index 435f5a994f..269a3151a2 100644 --- a/io/Makefile +++ b/io/Makefile @@ -235,6 +235,7 @@ tests := \ tests-time64 := \ tst-fcntl-time64 \ tst-fts-time64 \ + tst-fts-time64-y2038 \ tst-futimens-time64 \ tst-futimes-time64\ tst-futimesat-time64 \ diff --git a/io/fts.c b/io/fts.c index d03b059177..674a98530d 100644 --- a/io/fts.c +++ b/io/fts.c @@ -85,6 +85,7 @@ static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94"; # define STRUCT_STAT stat # define STAT __stat # define LSTAT __lstat +# define FSTAT __fstat #endif static FTSENTRY *fts_alloc (FTSOBJ *, const char *, size_t); @@ -1111,14 +1112,14 @@ static int fts_safe_changedir (FTSOBJ *sp, FTSENTRY *p, int fd, const char *path) { int ret, oerrno, newfd; - struct stat64 sb; + struct STRUCT_STAT sb; newfd = fd; if (ISSET(FTS_NOCHDIR)) return (0); if (fd < 0 && (newfd = __open(path, O_RDONLY, 0)) < 0) return (-1); - if (__fstat64(newfd, &sb)) { + if (FSTAT (newfd, &sb)) { ret = -1; goto bail; } diff --git a/io/fts64-time64.c b/io/fts64-time64.c index cd36125d7d..f8b7b590a0 100644 --- a/io/fts64-time64.c +++ b/io/fts64-time64.c @@ -30,6 +30,7 @@ # define STRUCT_STAT __stat64_t64 # define STAT __stat64_time64 # define LSTAT __lstat64_time64 +# define FSTAT __fstat64_time64 # include "fts.c" #endif diff --git a/io/fts64.c b/io/fts64.c index 41c079b664..cf67cc19f7 100644 --- a/io/fts64.c +++ b/io/fts64.c @@ -27,5 +27,6 @@ #define STRUCT_STAT stat64 #define STAT __stat64 #define LSTAT __lstat64 +#define FSTAT __fstat64 #include "fts.c" diff --git a/io/tst-fts-time64-y2038.c b/io/tst-fts-time64-y2038.c new file mode 100644 index 0000000000..bddf259b0c --- /dev/null +++ b/io/tst-fts-time64-y2038.c @@ -0,0 +1,3 @@ +/* Test for bug 33653 in fts_safe_changedir. */ +#define TST_FTS_Y2038 +#include "tst-fts.c" diff --git a/io/tst-fts.c b/io/tst-fts.c index d97aaef431..c472c1b4cc 100644 --- a/io/tst-fts.c +++ b/io/tst-fts.c @@ -26,6 +26,7 @@ #include #include #include +#include static void prepare (void); static int do_test (void); @@ -54,6 +55,28 @@ make_dir (const char *dirname) add_temp_file (name); } +#ifdef TST_FTS_Y2038 +static void +set_time_y2038 (const char *dirname) +{ + char *name; + if (asprintf (&name, "%s/%s", fts_test_dir, dirname) < 0) + { + puts ("out of memory"); + exit (1); + } + + struct utimbuf ut = { 0x100000000, 0x100000000 }; + if (utime (name, &ut) < 0) + { + printf ("cannot set time on dir \"%s\": %m\n", name); + exit (1); + } + + free (name); +} +#endif + static void make_file (const char *filename) { @@ -108,6 +131,10 @@ prepare (void) make_file ("bbb/1234"); make_file ("bbb/5678"); make_file ("bbb/90ab"); + +#ifdef TST_FTS_Y2038 + set_time_y2038 ("bbb"); +#endif } /* Largest name wins, otherwise strcmp. */ @@ -160,7 +187,13 @@ do_test (void) { char *paths[2] = { fts_test_dir, NULL }; FTS *fts; - fts = fts_open (paths, FTS_LOGICAL, &compare_ents); + int flags = 0; + /* FTS_LOGICAL implies FTS_NOCHDIR, thus when testing for bug 33653, + don't use FTS_LOGICAL. */ +#ifndef TST_FTS_Y2038 + flags |= FTS_LOGICAL; +#endif + fts = fts_open (paths, flags, &compare_ents); if (fts == NULL) { printf ("FAIL: fts_open: %m\n");