On 2026-04-13 09:15, Collin Funk wrote:
Also worth noting that if dracut only needs the file type it can continue to use FTS_NOSTAT. In the Gnulib implementation fts_statp->st_mode will be set to a file type based on the d_type from readdir or set to 0 if unknown.
Yes, but that should be documented, otherwise callers can't rely on it. glibc document this stuff in in the public include headers, and these headers need better comments.
I noticed that Gnulib's fts.h documents this behavior for the new FTS_DEFER_STAT flag, but not for the existing FTS_NOSTAT flag that you mentioned, so I installed the attached patches into Gnulib. The first patch fixes FTS_DEFER_STAT to behave as per documentation even for roots after the first one (this matters for unlikely situations where the comparison function looks at a later root's file type); the second fixes the documentation to say that FTS_STAT acts like FTS_DEFER_STAT in the situation you're describing.
I think these patches should be propagated into glibc. cc'ing bug-gnulib since it's a Gnulib change.PS. This stuff should also be documented in the glibc manual, but that's a bigger change that we can do at our convenience.
From f5ee21eacc5be459a7d08b344196f2245a5de801 Mon Sep 17 00:00:00 2001 From: Paul Eggert <[email protected]> Date: Wed, 15 Apr 2026 14:45:53 -0700 Subject: [PATCH 1/2] fts: match doc for FTS_DEFER_STAT mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * lib/fts.c (fts_open): Clear fts_statp->fts_mode for the FTS_DEFER_STAT case too, since it’s documented to work since 2008. --- ChangeLog | 6 ++++++ lib/fts.c | 1 + 2 files changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index 761d1edc0c..1145ad4fe2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2026-04-15 Paul Eggert <[email protected]> + + fts: match doc for FTS_DEFER_STAT mode + * lib/fts.c (fts_open): Clear fts_statp->fts_mode for the + FTS_DEFER_STAT case too, since it’s documented to work since 2008. + 2026-04-15 Bruno Haible <[email protected]> sigdelay: Add tests. diff --git a/lib/fts.c b/lib/fts.c index c61e8d89d8..daaa7d3e3c 100644 --- a/lib/fts.c +++ b/lib/fts.c @@ -485,6 +485,7 @@ fts_open (char * const *argv, FTS_XDEV) requires that. */ if (defer_stat && root != NULL) { p->fts_info = FTS_NSOK; + p->fts_statp->st_mode = 0; fts_set_stat_required(p, true); } else { p->fts_info = fts_stat(sp, p, false); -- 2.53.0
From 9ab4bbed73172085c57b38a337d3dc279b1043b0 Mon Sep 17 00:00:00 2001 From: Paul Eggert <[email protected]> Date: Wed, 15 Apr 2026 14:47:55 -0700 Subject: [PATCH 2/2] doc: doc FTS_NOSTAT similarity to FTS_DEFER_STAT * lib/fts.in.h (FTS_NOSTAT, FTS_DEFER_STAT): Document that FTS_NOSTAT updates fts_statp->st_mode similarly with FTS_DEFER_STAT. --- ChangeLog | 5 +++++ lib/fts.in.h | 14 ++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1145ad4fe2..e3a2961cd1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2026-04-15 Paul Eggert <[email protected]> + doc: doc FTS_NOSTAT similarity to FTS_DEFER_STAT + * lib/fts.in.h (FTS_NOSTAT, FTS_DEFER_STAT): + Document that FTS_NOSTAT updates fts_statp->st_mode + similarly with FTS_DEFER_STAT. + fts: match doc for FTS_DEFER_STAT mode * lib/fts.c (fts_open): Clear fts_statp->fts_mode for the FTS_DEFER_STAT case too, since it’s documented to work since 2008. diff --git a/lib/fts.in.h b/lib/fts.in.h index 9233111d57..c45cd63b0b 100644 --- a/lib/fts.in.h +++ b/lib/fts.in.h @@ -128,7 +128,15 @@ typedef struct { # define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */ # define FTS_LOGICAL 0x0002 /* logical walk */ # define FTS_NOCHDIR 0x0004 /* don't change directories */ + + /* For efficiency do not set *fts_statp except for fts_statp->st_mode, + which is set to zero if the file type is unknown, + and which otherwise has at least its S_IFMT type bits set. + When fts_info == FTS_NSOK this supports expressions like + (fts_statp->st_mode ? !!S_ISDIR (fts_statp->st_mode): -1), which yields + 1 for a directory, 0 for a non-directory, and -1 for unknown. */ # define FTS_NOSTAT 0x0008 /* don't get stat info */ + # define FTS_PHYSICAL 0x0010 /* physical walk */ # define FTS_SEEDOT 0x0020 /* return dot and dot-dot */ # define FTS_XDEV 0x0040 /* don't cross devices */ @@ -177,10 +185,8 @@ typedef struct { Use this flag to make fts_open and fts_read defer the stat/lstat/fststat of each entry until it is actually processed. However, note that if you use this option and also specify a comparison function, that function may - not examine any data via fts_statp. However, when fts_statp->st_mode is - nonzero, the S_IFMT type bits are valid, with mapped dirent.d_type data. - Of course, that happens only on file systems that provide useful - dirent.d_type data. */ + not examine any data via fts_statp, other than fts_statp->st_mode + which is set similarly to how FTS_NOSTAT behaves. */ # define FTS_DEFER_STAT 0x0400 /* Use this flag to disable stripping of trailing slashes -- 2.53.0
