From: LukᚠZaoral Date: Thu, 23 Oct 2025 07:16:52 +0000 (+0200) Subject: fts: Introduce the FTS_MOUNT flag. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=911133ba4fce786b237e3601918e0d2bc67b32c5;p=thirdparty%2Fgnulib.git fts: Introduce the FTS_MOUNT flag. This mimics behaviour of the FTW_MOUNT flag described in nftw(3) which implements the behaviour of find(1) -mount primary standardized by POSIX.1-2024. * lib/fts.in.h (FTS_MOUNT): New flag. (FTS_OPTIONMASK): Adjust. (FTS_NAMEONLY): Adjust. (FTS_STOP): Adjust. * lib/fts.c (fts_read): Implement FTS_MOUNT. (fts_build): Do not skip stat(2) when FTS_MOUNT as set. --- diff --git a/ChangeLog b/ChangeLog index 13c9a9e96e..48bf95cd41 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2025-11-02 Lukáš Zaoral + + fts: Introduce the FTS_MOUNT flag. + This mimics behaviour of the FTW_MOUNT flag described in nftw(3) which + implements the behaviour of find(1) -mount primary standardized by + POSIX.1-2024. + * lib/fts.in.h (FTS_MOUNT): New flag. + (FTS_OPTIONMASK): Adjust. + (FTS_NAMEONLY): Adjust. + (FTS_STOP): Adjust. + * lib/fts.c (fts_read): Implement FTS_MOUNT. + (fts_build): Do not skip stat(2) when FTS_MOUNT as set. + 2025-11-01 Pádraig Brady doc: mcel: give more detail on error interface diff --git a/lib/fts.c b/lib/fts.c index db6a0a3efa..6ddfb6f022 100644 --- a/lib/fts.c +++ b/lib/fts.c @@ -1017,11 +1017,18 @@ check_for_dir: fts_assert (p->fts_statp->st_size == FTS_NO_STAT_REQUIRED); } + /* Skip files with different device numbers when FTS_MOUNT + is set. */ + if (ISSET (FTS_MOUNT) && p->fts_info != FTS_NS && + p->fts_level != FTS_ROOTLEVEL && + p->fts_statp->st_dev != sp->fts_dev) + goto next; + if (p->fts_info == FTS_D) { - /* Now that P->fts_statp is guaranteed to be valid, - if this is a command-line directory, record its - device number, to be used for FTS_XDEV. */ + /* Now that P->fts_statp is guaranteed to be valid, if + this is a command-line directory, record its device + number, to be used for FTS_MOUNT and FTS_XDEV. */ if (p->fts_level == FTS_ROOTLEVEL) sp->fts_dev = p->fts_statp->st_dev; Dprintf ((" entering: %s\n", p->fts_path)); @@ -1529,19 +1536,21 @@ mem1: saved_errno = errno; entry. In many cases, it will simply fts_stat it, but we can take advantage of any d_type information to optimize away the unnecessary stat calls. I.e., - if FTS_NOSTAT is in effect and we're not following - symlinks (FTS_PHYSICAL) and d_type indicates this - is *not* a directory, then we won't have to stat it - at all. If it *is* a directory, then (currently) - we stat it regardless, in order to get device and - inode numbers. Some day we might optimize that - away, too, for directories where d_ino is known to - be valid. */ + if FTS_NOSTAT is in effect, we don't need device + numbers unconditionally (FTS_MOUNT) and we're not + following symlinks (FTS_PHYSICAL) and d_type + indicates this is *not* a directory, then we won't + have to stat it at all. If it *is* a directory, + then (currently) we stat it regardless, in order to + get device and inode numbers. Some day we might + optimize that away, too, for directories where + d_ino is known to be valid. */ bool skip_stat = (ISSET(FTS_NOSTAT) && DT_IS_KNOWN(dp) && ! DT_MUST_BE(dp, DT_DIR) && (ISSET(FTS_PHYSICAL) - || ! DT_MUST_BE(dp, DT_LNK))); + || ! DT_MUST_BE(dp, DT_LNK)) + && ! ISSET(FTS_MOUNT)); p->fts_info = FTS_NSOK; /* Propagate dirent.d_type information back to caller, when possible. */ diff --git a/lib/fts.in.h b/lib/fts.in.h index 9acc445039..ac36ed3f2d 100644 --- a/lib/fts.in.h +++ b/lib/fts.in.h @@ -186,11 +186,12 @@ typedef struct { /* Use this flag to disable stripping of trailing slashes from input path names during fts_open initialization. */ # define FTS_VERBATIM 0x0800 +# define FTS_MOUNT 0x1000 /* skip other devices */ -# define FTS_OPTIONMASK 0x0fff /* valid user option mask */ +# define FTS_OPTIONMASK 0x1fff /* valid user option mask */ -# define FTS_NAMEONLY 0x1000 /* (private) child names only */ -# define FTS_STOP 0x2000 /* (private) unrecoverable error */ +# define FTS_NAMEONLY 0x2000 /* (private) child names only */ +# define FTS_STOP 0x4000 /* (private) unrecoverable error */ int fts_options; /* fts_open options, global flags */ /* Map a directory's device number to a boolean. The boolean is