mirror of
https://sourceware.org/git/glibc.git
synced 2026-10-28 10:25:13 +08:00
This patch synchronizes the glibc fts implementation with the latest version from gnulib (as of 2026-02-16). The primary motivation is to address limitations in the legacy glibc implementation, most notably BZ 22944, where fts fails with an ENAMETOOLONG error when traversing very long paths or deeply nested directory trees. The gnulib implementation dynamically reallocates path buffers and uses openat/fchdir optimizations, effectively lifting the MAXPATHLEN limitation. The gnulib implementation also added extra features, which are used by different GNU projects (coreutils, diffutils): * FTS_TIGHT_CYCLE_CHECK: used to enable a strict, immediate cycle-detection algorithm during a file system traversal. This is done internally using a hash table: every time the traversal enters a directory, it records the directory's device and inode (dev/ino) pair in the hash table, and before entering any directory, fts checks the hash table. * FTS_CWDFD: instead of actually changing the process's current working directory, it maintains a virtual current working directory using file descriptors. The file descriptor is store at the fts_cwd_fd field and all subsequent file operations are performed relative to this file descriptor using *at functions. * FTS_DEFER_STAT: performance-oriented flag that instructs the file tree traversal engine to delay fetching file metadata. When the flag is used, fts skips the immediate stat call. Instead, it marks the entry with a special internal state (FTS_NSOK and FTS_STAT_REQUIRED). The actual stat call is pushed down the line and executed by fts_read right before the application actually accesses the entry. * FTS_VERBATIM: fts_open accept and use the path strings exactly as they were provided in the arguments array without slash trimming. * FTS_MOUNT: it restrict the file tree walk to a single file system. Hopefully,it would allow some GNU projects to use the glibc implementation instead of pulling the gnulib one. It requires some changes to keep compatibility, compared to gnulib: * The new required fields are added at the end of FTS structure, and the new FTS flags are adjusted to avoid change FTS_NAMEONLY/FTS_STOP (even though they are marked as private). * The FTSENT uses a flexible array (fts_name), so two adjustments are required: the two new members (fts_fts and fts_dirp) are place *before* the struct and the fts_statp is now always allocated and accounted (the gnulib implementation uses an alwyas allocated member). Checked on x86_64-linux-gnu and i686-linux-gnu.
78 lines
3.2 KiB
C
78 lines
3.2 KiB
C
/* Sizes of structs with flexible array members.
|
|
|
|
Copyright 2016-2026 Free Software Foundation, Inc.
|
|
|
|
This file is part of the GNU C Library.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, see
|
|
<https://www.gnu.org/licenses/>.
|
|
|
|
Written by Paul Eggert. */
|
|
|
|
/* This file uses _Alignof. */
|
|
#if !_LIBC && !_GL_CONFIG_H_INCLUDED
|
|
#error "Please include config.h first."
|
|
#endif
|
|
|
|
#include <stddef.h>
|
|
|
|
/* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below.
|
|
If _Alignof might not exist or might not work correctly on
|
|
structs with flexible array members, use a pessimistic bound that is
|
|
safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1.
|
|
Otherwise, use _Alignof to get a tighter bound. */
|
|
|
|
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 || defined _Alignof
|
|
# define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1))
|
|
#else
|
|
# define FLEXALIGNOF(type) _Alignof (type)
|
|
#endif
|
|
|
|
/* Yield a properly aligned upper bound on the size of a struct of
|
|
type TYPE with a flexible array member named MEMBER that is
|
|
followed by N bytes of other data. The result is suitable as an
|
|
argument to malloc. For example:
|
|
|
|
struct s { int a; char d[FLEXIBLE_ARRAY_MEMBER]; };
|
|
struct s *p = malloc (FLEXSIZEOF (struct s, d, n * sizeof (char)));
|
|
|
|
FLEXSIZEOF (TYPE, MEMBER, N) is not simply (sizeof (TYPE) + N),
|
|
since FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms. Nor is
|
|
it simply (offsetof (TYPE, MEMBER) + N), as that might yield a size
|
|
that causes malloc to yield a pointer that is not properly aligned
|
|
for TYPE; for example, if sizeof (int) == alignof (int) == 4,
|
|
malloc (offsetof (struct s, d) + 3 * sizeof (char)) is equivalent
|
|
to malloc (7) and might yield a pointer that is not a multiple of 4
|
|
(which means the pointer is not properly aligned for struct s),
|
|
whereas malloc (FLEXSIZEOF (struct s, d, 3 * sizeof (char))) is
|
|
equivalent to malloc (8) and must yield a pointer that is a
|
|
multiple of 4.
|
|
|
|
Yield a value less than N if and only if arithmetic overflow occurs. */
|
|
|
|
#define FLEXSIZEOF(type, member, n) \
|
|
((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \
|
|
& ~ (FLEXALIGNOF (type) - 1))
|
|
|
|
/* Yield a properly aligned upper bound on the size of a struct of
|
|
type TYPE with a flexible array member named MEMBER that has N
|
|
elements. The result is suitable as an argument to malloc.
|
|
For example:
|
|
|
|
struct s { int a; double d[FLEXIBLE_ARRAY_MEMBER]; };
|
|
struct s *p = malloc (FLEXNSIZEOF (struct s, d, n));
|
|
*/
|
|
#define FLEXNSIZEOF(type, member, n) \
|
|
FLEXSIZEOF (type, member, (n) * sizeof (((type *) 0)->member[0]))
|