annotate lib/fts.c @ 18403:4434607ac1ce

flexmember: port better to GCC + valgrind With a char[] flexible array member in a struct with nontrivial alignment, GCC-generated code can access past the end of the array, because GCC assumes there are padding bytes to get the struct aligned. So the common idiom of malloc (offsetof (struct s, m), n) does not properly allocate an n-byte trailing member, as malloc’s argument should be the next multiple of alignof (struct s). See GCC Bug#66661: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66661 Although C11 apparently permits this GCC optimization (i.e., there was a bug in Gnulib not in GCC), possibly this is a defect in C11. See the thread containing: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg00317.html * lib/flexmember.h: New file. * lib/fnmatch.c, lib/fts.c, lib/glob.c, lib/idcache.c: * lib/localename.c, lib/time_rz.c: Include flexmember.h. * lib/fnmatch_loop.c (struct patternlist): * lib/localename.c (struct hash_node): Use FLEXIBLE_ARRAY_MEMBER. * lib/fnmatch_loop.c (EXT): * lib/fts.c (fts_alloc): * lib/glob.c (glob_in_dir): * lib/idcache.c (getuser, getuidbyname, getgroup, getgidbyname): * lib/localename.c (gl_lock_define_initialized): * lib/time_rz.c (tzalloc): Use FLEXSIZEOF instead of offsetof. * m4/flexmember.m4 (AC_C_FLEXIBLE_ARRAY_MEMBER): Check that the size of the struct can be taken. * modules/flexmember (Files): Add lib/flexmember.h. * modules/fnmatch, modules/glob, modules/localename (Depends-on): Add flexmember.
author Paul Eggert <eggert@cs.ucla.edu>
date Wed, 07 Sep 2016 02:01:42 -0700
parents 7276fe79480b
children 12df2165ec1c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1 /* Traverse a file hierarchy.
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2
18189
31b2239ca59c version-etc: new year
Paul Eggert <eggert@cs.ucla.edu>
parents: 18180
diff changeset
3 Copyright (C) 2004-2016 Free Software Foundation, Inc.
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
4
9309
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 9129
diff changeset
5 This program is free software: you can redistribute it and/or modify
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
6 it under the terms of the GNU General Public License as published by
9309
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 9129
diff changeset
7 the Free Software Foundation; either version 3 of the License, or
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 9129
diff changeset
8 (at your option) any later version.
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
9
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
10 This program is distributed in the hope that it will be useful,
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
13 GNU General Public License for more details.
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
14
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
15 You should have received a copy of the GNU General Public License
9309
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 9129
diff changeset
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
17
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
18 /*-
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
19 * Copyright (c) 1990, 1993, 1994
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
20 * The Regents of the University of California. All rights reserved.
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
21 *
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
22 * Redistribution and use in source and binary forms, with or without
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
23 * modification, are permitted provided that the following conditions
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
24 * are met:
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
25 * 1. Redistributions of source code must retain the above copyright
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
26 * notice, this list of conditions and the following disclaimer.
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
27 * 2. Redistributions in binary form must reproduce the above copyright
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
28 * notice, this list of conditions and the following disclaimer in the
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
29 * documentation and/or other materials provided with the distribution.
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
30 * 4. Neither the name of the University nor the names of its contributors
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
31 * may be used to endorse or promote products derived from this software
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
32 * without specific prior written permission.
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
33 *
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
34 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
35 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
36 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
37 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
38 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
39 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
40 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
41 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
42 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
43 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
44 * SUCH DAMAGE.
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
45 */
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
46
7302
8a1a9361108c * _fpending.c: Include <config.h> unconditionally, since we no
Paul Eggert <eggert@cs.ucla.edu>
parents: 7225
diff changeset
47 #include <config.h>
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
48
18325
33db65a13e67 Use GCC_LINT, not lint
Paul Eggert <eggert@cs.ucla.edu>
parents: 18216
diff changeset
49 #if defined LIBC_SCCS && !defined GCC_LINT && !defined lint
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
50 static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
18325
33db65a13e67 Use GCC_LINT, not lint
Paul Eggert <eggert@cs.ucla.edu>
parents: 18216
diff changeset
51 #endif
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
52
5867
67b499052f7f * fts.c: Include fts_.h first, to check interface.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5858
diff changeset
53 #include "fts_.h"
67b499052f7f * fts.c: Include fts_.h first, to check interface.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5858
diff changeset
54
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
55 #if HAVE_SYS_PARAM_H || defined _LIBC
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
56 # include <sys/param.h>
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
57 #endif
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
58 #ifdef _LIBC
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
59 # include <include/sys/stat.h>
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
60 #else
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
61 # include <sys/stat.h>
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
62 #endif
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
63 #include <fcntl.h>
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
64 #include <errno.h>
18026
1a086f523d28 fts: avoid reading beyond the heap allocation
Pádraig Brady <P@draigBrady.com>
parents: 17974
diff changeset
65 #include <stdalign.h>
5867
67b499052f7f * fts.c: Include fts_.h first, to check interface.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5858
diff changeset
66 #include <stdbool.h>
18137
d76e9e9d345e fts: port to C11 alignof
Paul Eggert <eggert@cs.ucla.edu>
parents: 18026
diff changeset
67 #include <stddef.h>
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
68 #include <stdlib.h>
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
69 #include <string.h>
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
70 #include <unistd.h>
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
71
6034
96149b1bbb32 (fts_cross_check) [FTS_DEBUG]: s/active_dir_ht/fts_cycle.ht/.
Jim Meyering <jim@meyering.net>
parents: 5907
diff changeset
72 #if ! _LIBC
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
73 # include "fcntl--.h"
11938
7cbcde229d97 backupfile, chdir-long, fts, savedir: make safer
Eric Blake <ebb9@byu.net>
parents: 11924
diff changeset
74 # include "dirent--.h"
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
75 # include "unistd--.h"
11940
6dd8c8815b1f fts: avoid leaking fds
Eric Blake <ebb9@byu.net>
parents: 11939
diff changeset
76 /* FIXME - use fcntl(F_DUPFD_CLOEXEC)/openat(O_CLOEXEC) once they are
6dd8c8815b1f fts: avoid leaking fds
Eric Blake <ebb9@byu.net>
parents: 11939
diff changeset
77 supported. */
6dd8c8815b1f fts: avoid leaking fds
Eric Blake <ebb9@byu.net>
parents: 11939
diff changeset
78 # include "cloexec.h"
18403
4434607ac1ce flexmember: port better to GCC + valgrind
Paul Eggert <eggert@cs.ucla.edu>
parents: 18338
diff changeset
79 # include "flexmember.h"
11946
7604970d1a9f fts: fix compilation error
Eric Blake <ebb9@byu.net>
parents: 11940
diff changeset
80 # include "openat.h"
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
81 # include "same-inode.h"
6034
96149b1bbb32 (fts_cross_check) [FTS_DEBUG]: s/active_dir_ht/fts_cycle.ht/.
Jim Meyering <jim@meyering.net>
parents: 5907
diff changeset
82 #endif
96149b1bbb32 (fts_cross_check) [FTS_DEBUG]: s/active_dir_ht/fts_cycle.ht/.
Jim Meyering <jim@meyering.net>
parents: 5907
diff changeset
83
6949
96af1224c6fa * backupfile.c, dirfd.h, fts.c, getcwd.c, glob.c, glob_.h:
Paul Eggert <eggert@cs.ucla.edu>
parents: 6934
diff changeset
84 #include <dirent.h>
17642
8af917141d49 fts: avoid unnecessary strlen calls
Eric Blake <eblake@redhat.com>
parents: 17641
diff changeset
85 #ifndef _D_EXACT_NAMLEN
8af917141d49 fts: avoid unnecessary strlen calls
Eric Blake <eblake@redhat.com>
parents: 17641
diff changeset
86 # define _D_EXACT_NAMLEN(dirent) strlen ((dirent)->d_name)
8af917141d49 fts: avoid unnecessary strlen calls
Eric Blake <eblake@redhat.com>
parents: 17641
diff changeset
87 #endif
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
88
7482
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
89 #if HAVE_STRUCT_DIRENT_D_TYPE
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
90 /* True if the type of the directory entry D is known. */
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
91 # define DT_IS_KNOWN(d) ((d)->d_type != DT_UNKNOWN)
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
92 /* True if the type of the directory entry D must be T. */
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
93 # define DT_MUST_BE(d, t) ((d)->d_type == (t))
10843
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
94 # define D_TYPE(d) ((d)->d_type)
7482
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
95 #else
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
96 # define DT_IS_KNOWN(d) false
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
97 # define DT_MUST_BE(d, t) false
10843
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
98 # define D_TYPE(d) DT_UNKNOWN
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
99
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
100 # undef DT_UNKNOWN
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
101 # define DT_UNKNOWN 0
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
102
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
103 /* Any nonzero values will do here, so long as they're distinct.
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
104 Undef any existing macros out of the way. */
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
105 # undef DT_BLK
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
106 # undef DT_CHR
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
107 # undef DT_DIR
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
108 # undef DT_FIFO
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
109 # undef DT_LNK
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
110 # undef DT_REG
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
111 # undef DT_SOCK
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
112 # define DT_BLK 1
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
113 # define DT_CHR 2
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
114 # define DT_DIR 3
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
115 # define DT_FIFO 4
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
116 # define DT_LNK 5
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
117 # define DT_REG 6
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
118 # define DT_SOCK 7
7482
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
119 #endif
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
120
10863
054d026819f0 work around mingw's lack of some S_IF definitions
Jim Meyering <meyering@redhat.com>
parents: 10844
diff changeset
121 #ifndef S_IFLNK
054d026819f0 work around mingw's lack of some S_IF definitions
Jim Meyering <meyering@redhat.com>
parents: 10844
diff changeset
122 # define S_IFLNK 0
054d026819f0 work around mingw's lack of some S_IF definitions
Jim Meyering <meyering@redhat.com>
parents: 10844
diff changeset
123 #endif
054d026819f0 work around mingw's lack of some S_IF definitions
Jim Meyering <meyering@redhat.com>
parents: 10844
diff changeset
124 #ifndef S_IFSOCK
054d026819f0 work around mingw's lack of some S_IF definitions
Jim Meyering <meyering@redhat.com>
parents: 10844
diff changeset
125 # define S_IFSOCK 0
054d026819f0 work around mingw's lack of some S_IF definitions
Jim Meyering <meyering@redhat.com>
parents: 10844
diff changeset
126 #endif
054d026819f0 work around mingw's lack of some S_IF definitions
Jim Meyering <meyering@redhat.com>
parents: 10844
diff changeset
127
10481
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
128 enum
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
129 {
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
130 NOT_AN_INODE_NUMBER = 0
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
131 };
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
132
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
133 #ifdef D_INO_IN_DIRENT
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
134 # define D_INO(dp) (dp)->d_ino
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
135 #else
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
136 /* Some systems don't have inodes, so fake them to avoid lots of ifdefs. */
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
137 # define D_INO(dp) NOT_AN_INODE_NUMBER
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
138 #endif
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
139
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
140 /* If possible (see max_entries, below), read no more than this many directory
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
141 entries at a time. Without this limit (i.e., when using non-NULL
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
142 fts_compar), processing a directory with 4,000,000 entries requires ~1GiB
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
143 of memory, and handling 64M entries would require 16GiB of memory. */
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
144 #ifndef FTS_MAX_READDIR_ENTRIES
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
145 # define FTS_MAX_READDIR_ENTRIES 100000
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
146 #endif
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
147
10481
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
148 /* If there are more than this many entries in a directory,
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
149 and the conditions mentioned below are satisfied, then sort
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
150 the entries on inode number before any further processing. */
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
151 #ifndef FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
152 # define FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD 10000
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
153 #endif
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
154
10481
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
155 enum
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
156 {
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
157 _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD = FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
158 };
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
159
7684
784e80c3d895 Work around a compile-time error from the HP-UX 11.00 /bin/cc.
Jim Meyering <jim@meyering.net>
parents: 7681
diff changeset
160 enum Fts_stat
7482
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
161 {
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
162 FTS_NO_STAT_REQUIRED = 1,
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
163 FTS_STAT_REQUIRED = 2
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
164 };
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
165
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
166 #ifdef _LIBC
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
167 # undef close
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
168 # define close __close
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
169 # undef closedir
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
170 # define closedir __closedir
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
171 # undef fchdir
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
172 # define fchdir __fchdir
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
173 # undef open
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
174 # define open __open
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
175 # undef readdir
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
176 # define readdir __readdir
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
177 #else
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
178 # undef internal_function
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
179 # define internal_function /* empty */
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
180 #endif
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
181
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
182 #ifndef __set_errno
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
183 # define __set_errno(Val) errno = (Val)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
184 #endif
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
185
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
186 /* If this host provides the openat function, then we can avoid
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
187 attempting to open "." in some initialization code below. */
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
188 #ifdef HAVE_OPENAT
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
189 # define HAVE_OPENAT_SUPPORT 1
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
190 #else
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
191 # define HAVE_OPENAT_SUPPORT 0
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
192 #endif
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
193
7785
3246679850d5 Slight readability improvement: use an assert-like macro
Jim Meyering <jim@meyering.net>
parents: 7707
diff changeset
194 #ifdef NDEBUG
17840
39c9960ea17b assure: new module
Paul Eggert <eggert@cs.ucla.edu>
parents: 17797
diff changeset
195 # define fts_assert(expr) ((void) (0 && (expr)))
7785
3246679850d5 Slight readability improvement: use an assert-like macro
Jim Meyering <jim@meyering.net>
parents: 7707
diff changeset
196 #else
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
197 # define fts_assert(expr) \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
198 do \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
199 { \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
200 if (!(expr)) \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
201 abort (); \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
202 } \
7785
3246679850d5 Slight readability improvement: use an assert-like macro
Jim Meyering <jim@meyering.net>
parents: 7707
diff changeset
203 while (false)
3246679850d5 Slight readability improvement: use an assert-like macro
Jim Meyering <jim@meyering.net>
parents: 7707
diff changeset
204 #endif
3246679850d5 Slight readability improvement: use an assert-like macro
Jim Meyering <jim@meyering.net>
parents: 7707
diff changeset
205
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
206 static FTSENT *fts_alloc (FTS *, const char *, size_t) internal_function;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
207 static FTSENT *fts_build (FTS *, int) internal_function;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
208 static void fts_lfree (FTSENT *) internal_function;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
209 static void fts_load (FTS *, FTSENT *) internal_function;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
210 static size_t fts_maxarglen (char * const *) internal_function;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
211 static void fts_padjust (FTS *, FTSENT *) internal_function;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
212 static bool fts_palloc (FTS *, size_t) internal_function;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
213 static FTSENT *fts_sort (FTS *, FTSENT *, size_t) internal_function;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
214 static unsigned short int fts_stat (FTS *, FTSENT *, bool) internal_function;
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
215 static int fts_safe_changedir (FTS *, FTSENT *, int, const char *)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
216 internal_function;
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
217
13091
3af48780d248 Remove vestiges of fts-lgpl module.
Bruno Haible <bruno@clisp.org>
parents: 12772
diff changeset
218 #include "fts-cycle.c"
5872
fab6701e5cb2 New fts module.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5867
diff changeset
219
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
220 #ifndef MAX
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
221 # define MAX(a,b) ((a) > (b) ? (a) : (b))
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
222 #endif
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
223
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
224 #ifndef SIZE_MAX
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
225 # define SIZE_MAX ((size_t) -1)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
226 #endif
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
227
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
228 #define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
12772
2ea3e3fab7ee define STREQ(a,b) consistently, removing useless parentheses
Jim Meyering <meyering@redhat.com>
parents: 12559
diff changeset
229 #define STREQ(a, b) (strcmp (a, b) == 0)
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
230
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
231 #define CLR(opt) (sp->fts_options &= ~(opt))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
232 #define ISSET(opt) (sp->fts_options & (opt))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
233 #define SET(opt) (sp->fts_options |= (opt))
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
234
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
235 /* FIXME: FTS_NOCHDIR is now misnamed.
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
236 Call it FTS_USE_FULL_RELATIVE_FILE_NAMES instead. */
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
237 #define FCHDIR(sp, fd) \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
238 (!ISSET(FTS_NOCHDIR) && (ISSET(FTS_CWDFD) \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
239 ? (cwd_advance_fd ((sp), (fd), true), 0) \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
240 : fchdir (fd)))
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
241
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
242
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
243 /* fts_build flags */
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
244 /* FIXME: make this an enum */
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
245 #define BCHILD 1 /* fts_children */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
246 #define BNAMES 2 /* fts_children, names only */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
247 #define BREAD 3 /* fts_read */
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
248
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
249 #if FTS_DEBUG
5894
d09af5fbd9f2 * modules/fts (Files): Remove m4/inttypes-pri.m4.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5877
diff changeset
250 # include <inttypes.h>
d09af5fbd9f2 * modules/fts (Files): Remove m4/inttypes-pri.m4.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5877
diff changeset
251 # include <stdint.h>
d09af5fbd9f2 * modules/fts (Files): Remove m4/inttypes-pri.m4.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5877
diff changeset
252 # include <stdio.h>
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
253 # include "getcwdat.h"
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
254 bool fts_debug = false;
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
255 # define Dprintf(x) do { if (fts_debug) printf x; } while (false)
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
256 #else
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
257 # define Dprintf(x)
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
258 # define fd_ring_check(x)
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
259 # define fd_ring_print(a, b, c)
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
260 #endif
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
261
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
262 #define LEAVE_DIR(Fts, Ent, Tag) \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
263 do \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
264 { \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
265 Dprintf ((" %s-leaving: %s\n", Tag, (Ent)->fts_path)); \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
266 leave_dir (Fts, Ent); \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
267 fd_ring_check (Fts); \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
268 } \
5872
fab6701e5cb2 New fts module.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5867
diff changeset
269 while (false)
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
270
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
271 static void
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
272 fd_ring_clear (I_ring *fd_ring)
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
273 {
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
274 while ( ! i_ring_empty (fd_ring))
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
275 {
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
276 int fd = i_ring_pop (fd_ring);
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
277 if (0 <= fd)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
278 close (fd);
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
279 }
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
280 }
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
281
7482
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
282 /* Overload the fts_statp->st_size member (otherwise unused, when
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
283 fts_info is FTS_NSOK) to indicate whether fts_read should stat
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
284 this entry or not. */
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
285 static void
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
286 fts_set_stat_required (FTSENT *p, bool required)
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
287 {
7785
3246679850d5 Slight readability improvement: use an assert-like macro
Jim Meyering <jim@meyering.net>
parents: 7707
diff changeset
288 fts_assert (p->fts_info == FTS_NSOK);
7482
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
289 p->fts_statp->st_size = (required
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
290 ? FTS_STAT_REQUIRED
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
291 : FTS_NO_STAT_REQUIRED);
7482
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
292 }
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
293
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
294 /* file-descriptor-relative opendir. */
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
295 /* FIXME: if others need this function, move it into lib/openat.c */
17188
d7a44f0f7a15 ftruncate, fts, lstat, openat, raise: no 'static inline'
Paul Eggert <eggert@cs.ucla.edu>
parents: 17160
diff changeset
296 static DIR *
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
297 internal_function
13676
223800d7ac7d fts, getcwd, glob: audit for dirfd returning -1
Paul Eggert <eggert@cs.ucla.edu>
parents: 13674
diff changeset
298 opendirat (int fd, char const *dir, int extra_flags, int *pdir_fd)
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
299 {
11939
cd48f861a7a7 fts: make directory fds more robust
Eric Blake <ebb9@byu.net>
parents: 11938
diff changeset
300 int new_fd = openat (fd, dir,
13674
5c447be5815d fts: use O_NOFOLLOW to avoid race condition when opening a directory
Paul Eggert <eggert@cs.ucla.edu>
parents: 13671
diff changeset
301 (O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
5c447be5815d fts: use O_NOFOLLOW to avoid race condition when opening a directory
Paul Eggert <eggert@cs.ucla.edu>
parents: 13671
diff changeset
302 | extra_flags));
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
303 DIR *dirp;
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
304
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
305 if (new_fd < 0)
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
306 return NULL;
11940
6dd8c8815b1f fts: avoid leaking fds
Eric Blake <ebb9@byu.net>
parents: 11939
diff changeset
307 set_cloexec_flag (new_fd, true);
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
308 dirp = fdopendir (new_fd);
13676
223800d7ac7d fts, getcwd, glob: audit for dirfd returning -1
Paul Eggert <eggert@cs.ucla.edu>
parents: 13674
diff changeset
309 if (dirp)
223800d7ac7d fts, getcwd, glob: audit for dirfd returning -1
Paul Eggert <eggert@cs.ucla.edu>
parents: 13674
diff changeset
310 *pdir_fd = new_fd;
223800d7ac7d fts, getcwd, glob: audit for dirfd returning -1
Paul Eggert <eggert@cs.ucla.edu>
parents: 13674
diff changeset
311 else
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
312 {
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
313 int saved_errno = errno;
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
314 close (new_fd);
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
315 errno = saved_errno;
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
316 }
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
317 return dirp;
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
318 }
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
319
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
320 /* Virtual fchdir. Advance SP's working directory file descriptor,
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
321 SP->fts_cwd_fd, to FD, and push the previous value onto the fd_ring.
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
322 CHDIR_DOWN_ONE is true if FD corresponds to an entry in the directory
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
323 open on sp->fts_cwd_fd; i.e., to move the working directory one level
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
324 down. */
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
325 static void
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
326 internal_function
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
327 cwd_advance_fd (FTS *sp, int fd, bool chdir_down_one)
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
328 {
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
329 int old = sp->fts_cwd_fd;
7785
3246679850d5 Slight readability improvement: use an assert-like macro
Jim Meyering <jim@meyering.net>
parents: 7707
diff changeset
330 fts_assert (old != fd || old == AT_FDCWD);
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
331
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
332 if (chdir_down_one)
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
333 {
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
334 /* Push "old" onto the ring.
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
335 If the displaced file descriptor is non-negative, close it. */
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
336 int prev_fd_in_slot = i_ring_push (&sp->fts_fd_ring, old);
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
337 fd_ring_print (sp, stderr, "post-push");
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
338 if (0 <= prev_fd_in_slot)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
339 close (prev_fd_in_slot); /* ignore any close failure */
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
340 }
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
341 else if ( ! ISSET (FTS_NOCHDIR))
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
342 {
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
343 if (0 <= old)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
344 close (old); /* ignore any close failure */
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
345 }
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
346
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
347 sp->fts_cwd_fd = fd;
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
348 }
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
349
15988
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
350 /* Restore the initial, pre-traversal, "working directory".
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
351 In FTS_CWDFD mode, we merely call cwd_advance_fd, otherwise,
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
352 we may actually change the working directory.
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
353 Return 0 upon success. Upon failure, set errno and return nonzero. */
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
354 static int
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
355 restore_initial_cwd (FTS *sp)
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
356 {
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
357 int fail = FCHDIR (sp, ISSET (FTS_CWDFD) ? AT_FDCWD : sp->fts_rfd);
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
358 fd_ring_clear (&(sp->fts_fd_ring));
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
359 return fail;
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
360 }
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
361
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
362 /* Open the directory DIR if possible, and return a file
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
363 descriptor. Return -1 and set errno on failure. It doesn't matter
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
364 whether the file descriptor has read or write access. */
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
365
17188
d7a44f0f7a15 ftruncate, fts, lstat, openat, raise: no 'static inline'
Paul Eggert <eggert@cs.ucla.edu>
parents: 17160
diff changeset
366 static int
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
367 internal_function
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
368 diropen (FTS const *sp, char const *dir)
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
369 {
13616
acc972b5da60 fcntl-h, etc.: prefer O_SEARCH to O_RDONLY when applicable
Paul Eggert <eggert@cs.ucla.edu>
parents: 13091
diff changeset
370 int open_flags = (O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
15374
04a9f678e342 fts: introduce FTS_NOATIME
Eric Blake <eblake@redhat.com>
parents: 14774
diff changeset
371 | (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0)
04a9f678e342 fts: introduce FTS_NOATIME
Eric Blake <eblake@redhat.com>
parents: 14774
diff changeset
372 | (ISSET (FTS_NOATIME) ? O_NOATIME : 0));
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
373
11940
6dd8c8815b1f fts: avoid leaking fds
Eric Blake <ebb9@byu.net>
parents: 11939
diff changeset
374 int fd = (ISSET (FTS_CWDFD)
6dd8c8815b1f fts: avoid leaking fds
Eric Blake <ebb9@byu.net>
parents: 11939
diff changeset
375 ? openat (sp->fts_cwd_fd, dir, open_flags)
6dd8c8815b1f fts: avoid leaking fds
Eric Blake <ebb9@byu.net>
parents: 11939
diff changeset
376 : open (dir, open_flags));
6dd8c8815b1f fts: avoid leaking fds
Eric Blake <ebb9@byu.net>
parents: 11939
diff changeset
377 if (0 <= fd)
6dd8c8815b1f fts: avoid leaking fds
Eric Blake <ebb9@byu.net>
parents: 11939
diff changeset
378 set_cloexec_flag (fd, true);
6dd8c8815b1f fts: avoid leaking fds
Eric Blake <ebb9@byu.net>
parents: 11939
diff changeset
379 return fd;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
380 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
381
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
382 FTS *
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
383 fts_open (char * const *argv,
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
384 register int options,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
385 int (*compar) (FTSENT const **, FTSENT const **))
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
386 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
387 register FTS *sp;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
388 register FTSENT *p, *root;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
389 register size_t nitems;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
390 FTSENT *parent = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
391 FTSENT *tmp = NULL; /* pacify gcc */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
392 bool defer_stat;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
393
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
394 /* Options check. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
395 if (options & ~FTS_OPTIONMASK) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
396 __set_errno (EINVAL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
397 return (NULL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
398 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
399 if ((options & FTS_NOCHDIR) && (options & FTS_CWDFD)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
400 __set_errno (EINVAL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
401 return (NULL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
402 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
403 if ( ! (options & (FTS_LOGICAL | FTS_PHYSICAL))) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
404 __set_errno (EINVAL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
405 return (NULL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
406 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
407
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
408 /* Allocate/initialize the stream */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
409 if ((sp = malloc(sizeof(FTS))) == NULL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
410 return (NULL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
411 memset(sp, 0, sizeof(FTS));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
412 sp->fts_compar = compar;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
413 sp->fts_options = options;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
414
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
415 /* Logical walks turn on NOCHDIR; symbolic links are too hard. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
416 if (ISSET(FTS_LOGICAL)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
417 SET(FTS_NOCHDIR);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
418 CLR(FTS_CWDFD);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
419 }
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
420
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
421 /* Initialize fts_cwd_fd. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
422 sp->fts_cwd_fd = AT_FDCWD;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
423 if ( ISSET(FTS_CWDFD) && ! HAVE_OPENAT_SUPPORT)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
424 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
425 /* While it isn't technically necessary to open "." this
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
426 early, doing it here saves us the trouble of ensuring
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
427 later (where it'd be messier) that "." can in fact
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
428 be opened. If not, revert to FTS_NOCHDIR mode. */
15374
04a9f678e342 fts: introduce FTS_NOATIME
Eric Blake <eblake@redhat.com>
parents: 14774
diff changeset
429 int fd = open (".",
04a9f678e342 fts: introduce FTS_NOATIME
Eric Blake <eblake@redhat.com>
parents: 14774
diff changeset
430 O_SEARCH | (ISSET (FTS_NOATIME) ? O_NOATIME : 0));
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
431 if (fd < 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
432 {
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
433 /* Even if "." is unreadable, don't revert to FTS_NOCHDIR mode
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
434 on systems like Linux+PROC_FS, where our openat emulation
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
435 is good enough. Note: on a system that emulates
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
436 openat via /proc, this technique can still fail, but
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
437 only in extreme conditions, e.g., when the working
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
438 directory cannot be saved (i.e. save_cwd fails) --
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
439 and that happens on Linux only when "." is unreadable
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
440 and the CWD would be longer than PATH_MAX.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
441 FIXME: once Linux kernel openat support is well established,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
442 replace the above open call and this entire if/else block
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
443 with the body of the if-block below. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
444 if ( openat_needs_fchdir ())
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
445 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
446 SET(FTS_NOCHDIR);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
447 CLR(FTS_CWDFD);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
448 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
449 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
450 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
451 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
452 close (fd);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
453 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
454 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
455
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
456 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
457 * Start out with 1K of file name space, and enough, in any case,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
458 * to hold the user's file names.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
459 */
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
460 #ifndef MAXPATHLEN
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
461 # define MAXPATHLEN 1024
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
462 #endif
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
463 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
464 size_t maxarglen = fts_maxarglen(argv);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
465 if (! fts_palloc(sp, MAX(maxarglen, MAXPATHLEN)))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
466 goto mem1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
467 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
468
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
469 /* Allocate/initialize root's parent. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
470 if (*argv != NULL) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
471 if ((parent = fts_alloc(sp, "", 0)) == NULL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
472 goto mem2;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
473 parent->fts_level = FTS_ROOTPARENTLEVEL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
474 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
475
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
476 /* The classic fts implementation would call fts_stat with
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
477 a new entry for each iteration of the loop below.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
478 If the comparison function is not specified or if the
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
479 FTS_DEFER_STAT option is in effect, don't stat any entry
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
480 in this loop. This is an attempt to minimize the interval
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
481 between the initial stat/lstat/fstatat and the point at which
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
482 a directory argument is first opened. This matters for any
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
483 directory command line argument that resides on a file system
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
484 without genuine i-nodes. If you specify FTS_DEFER_STAT along
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
485 with a comparison function, that function must not access any
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
486 data via the fts_statp pointer. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
487 defer_stat = (compar == NULL || ISSET(FTS_DEFER_STAT));
7482
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
488
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
489 /* Allocate/initialize root(s). */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
490 for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
491 /* *Do* allow zero-length file names. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
492 size_t len = strlen(*argv);
17074
d4ccb0388f18 fts: reduce two or more trailing slashes to just one, usually
Jim Meyering <meyering@redhat.com>
parents: 17073
diff changeset
493
17160
72f4bab621be fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents: 17074
diff changeset
494 if ( ! (options & FTS_VERBATIM))
72f4bab621be fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents: 17074
diff changeset
495 {
72f4bab621be fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents: 17074
diff changeset
496 /* If there are two or more trailing slashes, trim all but one,
72f4bab621be fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents: 17074
diff changeset
497 but don't change "//" to "/", and do map "///" to "/". */
72f4bab621be fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents: 17074
diff changeset
498 char const *v = *argv;
72f4bab621be fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents: 17074
diff changeset
499 if (2 < len && v[len - 1] == '/')
72f4bab621be fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents: 17074
diff changeset
500 while (1 < len && v[len - 2] == '/')
72f4bab621be fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents: 17074
diff changeset
501 --len;
72f4bab621be fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents: 17074
diff changeset
502 }
17074
d4ccb0388f18 fts: reduce two or more trailing slashes to just one, usually
Jim Meyering <meyering@redhat.com>
parents: 17073
diff changeset
503
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
504 if ((p = fts_alloc(sp, *argv, len)) == NULL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
505 goto mem3;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
506 p->fts_level = FTS_ROOTLEVEL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
507 p->fts_parent = parent;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
508 p->fts_accpath = p->fts_name;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
509 /* Even when defer_stat is true, be sure to stat the first
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
510 command line argument, since fts_read (at least with
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
511 FTS_XDEV) requires that. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
512 if (defer_stat && root != NULL) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
513 p->fts_info = FTS_NSOK;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
514 fts_set_stat_required(p, true);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
515 } else {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
516 p->fts_info = fts_stat(sp, p, false);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
517 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
518
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
519 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
520 * If comparison routine supplied, traverse in sorted
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
521 * order; otherwise traverse in the order specified.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
522 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
523 if (compar) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
524 p->fts_link = root;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
525 root = p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
526 } else {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
527 p->fts_link = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
528 if (root == NULL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
529 tmp = root = p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
530 else {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
531 tmp->fts_link = p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
532 tmp = p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
533 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
534 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
535 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
536 if (compar && nitems > 1)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
537 root = fts_sort(sp, root, nitems);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
538
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
539 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
540 * Allocate a dummy pointer and make fts_read think that we've just
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
541 * finished the node before the root(s); set p->fts_info to FTS_INIT
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
542 * so that everything about the "current" node is ignored.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
543 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
544 if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
545 goto mem3;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
546 sp->fts_cur->fts_link = root;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
547 sp->fts_cur->fts_info = FTS_INIT;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
548 if (! setup_dir (sp))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
549 goto mem3;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
550
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
551 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
552 * If using chdir(2), grab a file descriptor pointing to dot to ensure
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
553 * that we can get back here; this could be avoided for some file names,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
554 * but almost certainly not worth the effort. Slashes, symbolic links,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
555 * and ".." are all fairly nasty problems. Note, if we can't get the
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
556 * descriptor we run anyway, just more slowly.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
557 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
558 if (!ISSET(FTS_NOCHDIR) && !ISSET(FTS_CWDFD)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
559 && (sp->fts_rfd = diropen (sp, ".")) < 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
560 SET(FTS_NOCHDIR);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
561
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
562 i_ring_init (&sp->fts_fd_ring, -1);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
563 return (sp);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
564
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
565 mem3: fts_lfree(root);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
566 free(parent);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
567 mem2: free(sp->fts_path);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
568 mem1: free(sp);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
569 return (NULL);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
570 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
571
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
572 static void
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
573 internal_function
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
574 fts_load (FTS *sp, register FTSENT *p)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
575 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
576 register size_t len;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
577 register char *cp;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
578
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
579 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
580 * Load the stream structure for the next traversal. Since we don't
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
581 * actually enter the directory until after the preorder visit, set
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
582 * the fts_accpath field specially so the chdir gets done to the right
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
583 * place and the user can access the first node. From fts_open it's
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
584 * known that the file name will fit.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
585 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
586 len = p->fts_pathlen = p->fts_namelen;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
587 memmove(sp->fts_path, p->fts_name, len + 1);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
588 if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
589 len = strlen(++cp);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
590 memmove(p->fts_name, cp, len + 1);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
591 p->fts_namelen = len;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
592 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
593 p->fts_accpath = p->fts_path = sp->fts_path;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
594 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
595
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
596 int
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
597 fts_close (FTS *sp)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
598 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
599 register FTSENT *freep, *p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
600 int saved_errno = 0;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
601
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
602 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
603 * This still works if we haven't read anything -- the dummy structure
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
604 * points to the root list, so we step through to the end of the root
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
605 * list which has a valid parent pointer.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
606 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
607 if (sp->fts_cur) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
608 for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
609 freep = p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
610 p = p->fts_link != NULL ? p->fts_link : p->fts_parent;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
611 free(freep);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
612 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
613 free(p);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
614 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
615
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
616 /* Free up child linked list, sort array, file name buffer. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
617 if (sp->fts_child)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
618 fts_lfree(sp->fts_child);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
619 free(sp->fts_array);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
620 free(sp->fts_path);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
621
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
622 if (ISSET(FTS_CWDFD))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
623 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
624 if (0 <= sp->fts_cwd_fd)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
625 if (close (sp->fts_cwd_fd))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
626 saved_errno = errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
627 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
628 else if (!ISSET(FTS_NOCHDIR))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
629 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
630 /* Return to original directory, save errno if necessary. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
631 if (fchdir(sp->fts_rfd))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
632 saved_errno = errno;
11924
10d064d93551 fts: fts_close now fails also when closing a dir file descriptor fails
Jim Meyering <meyering@redhat.com>
parents: 11722
diff changeset
633
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
634 /* If close fails, record errno only if saved_errno is zero,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
635 so that we report the probably-more-meaningful fchdir errno. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
636 if (close (sp->fts_rfd))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
637 if (saved_errno == 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
638 saved_errno = errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
639 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
640
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
641 fd_ring_clear (&sp->fts_fd_ring);
11164
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
642
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
643 if (sp->fts_leaf_optimization_works_ht)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
644 hash_free (sp->fts_leaf_optimization_works_ht);
11164
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
645
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
646 free_dir (sp);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
647
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
648 /* Free up the stream pointer. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
649 free(sp);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
650
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
651 /* Set errno and return. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
652 if (saved_errno) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
653 __set_errno (saved_errno);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
654 return (-1);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
655 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
656
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
657 return (0);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
658 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
659
11163
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
660 #if defined __linux__ \
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
661 && HAVE_SYS_VFS_H && HAVE_FSTATFS && HAVE_STRUCT_STATFS_F_TYPE
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
662
14379
2330aac2ae54 maint: adjust cpp indentation to reflect nesting depth
Jim Meyering <meyering@redhat.com>
parents: 14079
diff changeset
663 # include <sys/vfs.h>
11163
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
664
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
665 /* Linux-specific constants from coreutils' src/fs.h */
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
666 # define S_MAGIC_TMPFS 0x1021994
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
667 # define S_MAGIC_NFS 0x6969
11164
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
668 # define S_MAGIC_REISERFS 0x52654973
18179
4b6df746d1f3 fts: enable leaf optimization for XFS
Pádraig Brady <P@draigBrady.com>
parents: 18137
diff changeset
669 # define S_MAGIC_XFS 0x58465342
11164
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
670 # define S_MAGIC_PROC 0x9FA0
11163
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
671
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
672 /* Return false if it is easy to determine the file system type of
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
673 the directory on which DIR_FD is open, and sorting dirents on
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
674 inode numbers is known not to improve traversal performance with
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
675 that type of file system. Otherwise, return true. */
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
676 static bool
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
677 dirent_inode_sort_may_be_useful (int dir_fd)
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
678 {
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
679 /* Skip the sort only if we can determine efficiently
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
680 that skipping it is the right thing to do.
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
681 The cost of performing an unnecessary sort is negligible,
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
682 while the cost of *not* performing it can be O(N^2) with
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
683 a very large constant. */
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
684 struct statfs fs_buf;
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
685
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
686 /* If fstatfs fails, assume sorting would be useful. */
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
687 if (fstatfs (dir_fd, &fs_buf) != 0)
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
688 return true;
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
689
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
690 /* FIXME: what about when f_type is not an integral type?
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
691 deal with that if/when it's encountered. */
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
692 switch (fs_buf.f_type)
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
693 {
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
694 case S_MAGIC_TMPFS:
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
695 case S_MAGIC_NFS:
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
696 /* On a file system of any of these types, sorting
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
697 is unnecessary, and hence wasteful. */
11163
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
698 return false;
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
699
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
700 default:
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
701 return true;
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
702 }
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
703 }
11164
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
704
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
705 /* Given a file descriptor DIR_FD open on a directory D,
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
706 return true if it is valid to apply the leaf-optimization
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
707 technique of counting directories in D via stat.st_nlink. */
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
708 static bool
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
709 leaf_optimization_applies (int dir_fd)
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
710 {
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
711 struct statfs fs_buf;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
712
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
713 /* If fstatfs fails, assume we can't use the optimization. */
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
714 if (fstatfs (dir_fd, &fs_buf) != 0)
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
715 return false;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
716
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
717 /* FIXME: do we need to detect AFS mount points? I doubt it,
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
718 unless fstatfs can report S_MAGIC_REISERFS for such a directory. */
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
719
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
720 switch (fs_buf.f_type)
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
721 {
16358
a712776b11ce maint: spelling fixes
Paul Eggert <eggert@cs.ucla.edu>
parents: 16235
diff changeset
722 /* List here the file system types that lack usable dirent.d_type
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
723 info, yet for which the optimization does apply. */
11164
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
724 case S_MAGIC_REISERFS:
18179
4b6df746d1f3 fts: enable leaf optimization for XFS
Pádraig Brady <P@draigBrady.com>
parents: 18137
diff changeset
725 case S_MAGIC_XFS:
11164
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
726 return true;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
727
18216
973834698be5 fts: don't unconditionally use leaf optimization for NFS
Pádraig Brady <P@draigBrady.com>
parents: 18189
diff changeset
728 /* Explicitly list here any other file system type for which the
973834698be5 fts: don't unconditionally use leaf optimization for NFS
Pádraig Brady <P@draigBrady.com>
parents: 18189
diff changeset
729 optimization is not applicable, but need documentation. */
973834698be5 fts: don't unconditionally use leaf optimization for NFS
Pádraig Brady <P@draigBrady.com>
parents: 18189
diff changeset
730 case S_MAGIC_NFS:
973834698be5 fts: don't unconditionally use leaf optimization for NFS
Pádraig Brady <P@draigBrady.com>
parents: 18189
diff changeset
731 /* NFS provides usable dirent.d_type but not necessarily for all entries
973834698be5 fts: don't unconditionally use leaf optimization for NFS
Pádraig Brady <P@draigBrady.com>
parents: 18189
diff changeset
732 of large directories, so as per <https://bugzilla.redhat.com/1252549>
973834698be5 fts: don't unconditionally use leaf optimization for NFS
Pádraig Brady <P@draigBrady.com>
parents: 18189
diff changeset
733 NFS should return true. However st_nlink values are not accurate on
973834698be5 fts: don't unconditionally use leaf optimization for NFS
Pádraig Brady <P@draigBrady.com>
parents: 18189
diff changeset
734 all implementations as per <https://bugzilla.redhat.com/1299169>. */
973834698be5 fts: don't unconditionally use leaf optimization for NFS
Pádraig Brady <P@draigBrady.com>
parents: 18189
diff changeset
735 /* fall through */
11164
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
736 case S_MAGIC_PROC:
18216
973834698be5 fts: don't unconditionally use leaf optimization for NFS
Pádraig Brady <P@draigBrady.com>
parents: 18189
diff changeset
737 /* Per <http://bugs.debian.org/143111> /proc may have
973834698be5 fts: don't unconditionally use leaf optimization for NFS
Pádraig Brady <P@draigBrady.com>
parents: 18189
diff changeset
738 bogus stat.st_nlink values. */
11164
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
739 /* fall through */
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
740 default:
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
741 return false;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
742 }
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
743 }
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
744
11163
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
745 #else
12050
d1840b588599 fts: avoid compiler warning
Eric Blake <ebb9@byu.net>
parents: 11946
diff changeset
746 static bool
12482
11bc92a9e2bc gnulib-common: prefer _GL_UNUSED over _UNUSED_PARAMETER_
Eric Blake <ebb9@byu.net>
parents: 12421
diff changeset
747 dirent_inode_sort_may_be_useful (int dir_fd _GL_UNUSED) { return true; }
12050
d1840b588599 fts: avoid compiler warning
Eric Blake <ebb9@byu.net>
parents: 11946
diff changeset
748 static bool
12482
11bc92a9e2bc gnulib-common: prefer _GL_UNUSED over _UNUSED_PARAMETER_
Eric Blake <ebb9@byu.net>
parents: 12421
diff changeset
749 leaf_optimization_applies (int dir_fd _GL_UNUSED) { return false; }
11163
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
750 #endif
f448fc8fe832 fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents: 11162
diff changeset
751
11164
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
752 /* link-count-optimization entry:
14774
70d101744577 maint: correct misuse of "a" and "an"
Jim Meyering <meyering@redhat.com>
parents: 14612
diff changeset
753 map a stat.st_dev number to a boolean: leaf_optimization_works */
11164
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
754 struct LCO_ent
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
755 {
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
756 dev_t st_dev;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
757 bool opt_ok;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
758 };
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
759
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
760 /* Use a tiny initial size. If a traversal encounters more than
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
761 a few devices, the cost of growing/rehashing this table will be
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
762 rendered negligible by the number of inodes processed. */
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
763 enum { LCO_HT_INITIAL_SIZE = 13 };
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
764
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
765 static size_t
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
766 LCO_hash (void const *x, size_t table_size)
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
767 {
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
768 struct LCO_ent const *ax = x;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
769 return (uintmax_t) ax->st_dev % table_size;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
770 }
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
771
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
772 static bool
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
773 LCO_compare (void const *x, void const *y)
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
774 {
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
775 struct LCO_ent const *ax = x;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
776 struct LCO_ent const *ay = y;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
777 return ax->st_dev == ay->st_dev;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
778 }
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
779
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
780 /* Ask the same question as leaf_optimization_applies, but query
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
781 the cache first (FTS.fts_leaf_optimization_works_ht), and if necessary,
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
782 update that cache. */
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
783 static bool
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
784 link_count_optimize_ok (FTSENT const *p)
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
785 {
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
786 FTS *sp = p->fts_fts;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
787 Hash_table *h = sp->fts_leaf_optimization_works_ht;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
788 struct LCO_ent tmp;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
789 struct LCO_ent *ent;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
790 bool opt_ok;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
791 struct LCO_ent *t2;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
792
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
793 /* If we're not in CWDFD mode, don't bother with this optimization,
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
794 since the caller is not serious about performance. */
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
795 if (!ISSET(FTS_CWDFD))
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
796 return false;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
797
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
798 /* map st_dev to the boolean, leaf_optimization_works */
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
799 if (h == NULL)
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
800 {
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
801 h = sp->fts_leaf_optimization_works_ht
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
802 = hash_initialize (LCO_HT_INITIAL_SIZE, NULL, LCO_hash,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
803 LCO_compare, free);
11164
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
804 if (h == NULL)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
805 return false;
11164
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
806 }
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
807 tmp.st_dev = p->fts_statp->st_dev;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
808 ent = hash_lookup (h, &tmp);
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
809 if (ent)
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
810 return ent->opt_ok;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
811
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
812 /* Look-up failed. Query directly and cache the result. */
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
813 t2 = malloc (sizeof *t2);
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
814 if (t2 == NULL)
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
815 return false;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
816
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
817 /* Is it ok to perform the optimization in the dir, FTS_CWD_FD? */
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
818 opt_ok = leaf_optimization_applies (sp->fts_cwd_fd);
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
819 t2->opt_ok = opt_ok;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
820 t2->st_dev = p->fts_statp->st_dev;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
821
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
822 ent = hash_insert (h, t2);
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
823 if (ent == NULL)
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
824 {
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
825 /* insertion failed */
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
826 free (t2);
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
827 return false;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
828 }
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
829 fts_assert (ent == t2);
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
830
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
831 return opt_ok;
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
832 }
90715da41753 fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents: 11163
diff changeset
833
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
834 /*
5907
c47674a83a78 Sync from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5894
diff changeset
835 * Special case of "/" at the end of the file name so that slashes aren't
c47674a83a78 Sync from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5894
diff changeset
836 * appended which would cause file names to be written as "....//foo".
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
837 */
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
838 #define NAPPEND(p) \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
839 (p->fts_path[p->fts_pathlen - 1] == '/' \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
840 ? p->fts_pathlen - 1 : p->fts_pathlen)
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
841
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
842 FTSENT *
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
843 fts_read (register FTS *sp)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
844 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
845 register FTSENT *p, *tmp;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
846 register unsigned short int instr;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
847 register char *t;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
848
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
849 /* If finished or unrecoverable error, return NULL. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
850 if (sp->fts_cur == NULL || ISSET(FTS_STOP))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
851 return (NULL);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
852
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
853 /* Set current node pointer. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
854 p = sp->fts_cur;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
855
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
856 /* Save and zero out user instructions. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
857 instr = p->fts_instr;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
858 p->fts_instr = FTS_NOINSTR;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
859
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
860 /* Any type of file may be re-visited; re-stat and re-turn. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
861 if (instr == FTS_AGAIN) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
862 p->fts_info = fts_stat(sp, p, false);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
863 return (p);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
864 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
865 Dprintf (("fts_read: p=%s\n",
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
866 p->fts_info == FTS_INIT ? "" : p->fts_path));
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
867
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
868 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
869 * Following a symlink -- SLNONE test allows application to see
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
870 * SLNONE and recover. If indirecting through a symlink, have
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
871 * keep a pointer to current location. If unable to get that
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
872 * pointer, follow fails.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
873 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
874 if (instr == FTS_FOLLOW &&
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
875 (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
876 p->fts_info = fts_stat(sp, p, true);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
877 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
878 if ((p->fts_symfd = diropen (sp, ".")) < 0) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
879 p->fts_errno = errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
880 p->fts_info = FTS_ERR;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
881 } else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
882 p->fts_flags |= FTS_SYMFOLLOW;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
883 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
884 goto check_for_dir;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
885 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
886
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
887 /* Directory in pre-order. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
888 if (p->fts_info == FTS_D) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
889 /* If skipped or crossed mount point, do post-order visit. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
890 if (instr == FTS_SKIP ||
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
891 (ISSET(FTS_XDEV) && p->fts_statp->st_dev != sp->fts_dev)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
892 if (p->fts_flags & FTS_SYMFOLLOW)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
893 (void)close(p->fts_symfd);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
894 if (sp->fts_child) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
895 fts_lfree(sp->fts_child);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
896 sp->fts_child = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
897 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
898 p->fts_info = FTS_DP;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
899 LEAVE_DIR (sp, p, "1");
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
900 return (p);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
901 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
902
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
903 /* Rebuild if only read the names and now traversing. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
904 if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
905 CLR(FTS_NAMEONLY);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
906 fts_lfree(sp->fts_child);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
907 sp->fts_child = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
908 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
909
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
910 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
911 * Cd to the subdirectory.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
912 *
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
913 * If have already read and now fail to chdir, whack the list
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
914 * to make the names come out right, and set the parent errno
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
915 * so the application will eventually get an error condition.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
916 * Set the FTS_DONTCHDIR flag so that when we logically change
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
917 * directories back to the parent we don't do a chdir.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
918 *
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
919 * If haven't read do so. If the read fails, fts_build sets
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
920 * FTS_STOP or the fts_info field of the node.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
921 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
922 if (sp->fts_child != NULL) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
923 if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
924 p->fts_errno = errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
925 p->fts_flags |= FTS_DONTCHDIR;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
926 for (p = sp->fts_child; p != NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
927 p = p->fts_link)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
928 p->fts_accpath =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
929 p->fts_parent->fts_accpath;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
930 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
931 } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
932 if (ISSET(FTS_STOP))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
933 return (NULL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
934 /* If fts_build's call to fts_safe_changedir failed
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
935 because it was not able to fchdir into a
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
936 subdirectory, tell the caller. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
937 if (p->fts_errno && p->fts_info != FTS_DNR)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
938 p->fts_info = FTS_ERR;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
939 LEAVE_DIR (sp, p, "2");
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
940 return (p);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
941 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
942 p = sp->fts_child;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
943 sp->fts_child = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
944 goto name;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
945 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
946
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
947 /* Move to the next node on this level. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
948 next: tmp = p;
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
949
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
950 /* If we have so many directory entries that we're reading them
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
951 in batches, and we've reached the end of the current batch,
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
952 read in a new batch. */
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
953 if (p->fts_link == NULL && p->fts_parent->fts_dirp)
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
954 {
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
955 p = tmp->fts_parent;
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
956 sp->fts_cur = p;
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
957 sp->fts_path[p->fts_pathlen] = '\0';
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
958
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
959 if ((p = fts_build (sp, BREAD)) == NULL)
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
960 {
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
961 if (ISSET(FTS_STOP))
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
962 return NULL;
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
963 goto cd_dot_dot;
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
964 }
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
965
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
966 free(tmp);
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
967 goto name;
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
968 }
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
969
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
970 if ((p = p->fts_link) != NULL) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
971 sp->fts_cur = p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
972 free(tmp);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
973
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
974 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
975 * If reached the top, return to the original directory (or
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
976 * the root of the tree), and load the file names for the next
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
977 * root.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
978 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
979 if (p->fts_level == FTS_ROOTLEVEL) {
15988
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
980 if (restore_initial_cwd(sp)) {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
981 SET(FTS_STOP);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
982 return (NULL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
983 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
984 free_dir(sp);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
985 fts_load(sp, p);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
986 setup_dir(sp);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
987 goto check_for_dir;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
988 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
989
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
990 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
991 * User may have called fts_set on the node. If skipped,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
992 * ignore. If followed, get a file descriptor so we can
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
993 * get back if necessary.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
994 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
995 if (p->fts_instr == FTS_SKIP)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
996 goto next;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
997 if (p->fts_instr == FTS_FOLLOW) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
998 p->fts_info = fts_stat(sp, p, true);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
999 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1000 if ((p->fts_symfd = diropen (sp, ".")) < 0) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1001 p->fts_errno = errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1002 p->fts_info = FTS_ERR;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1003 } else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1004 p->fts_flags |= FTS_SYMFOLLOW;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1005 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1006 p->fts_instr = FTS_NOINSTR;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1007 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1008
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1009 name: t = sp->fts_path + NAPPEND(p->fts_parent);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1010 *t++ = '/';
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1011 memmove(t, p->fts_name, p->fts_namelen + 1);
5872
fab6701e5cb2 New fts module.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5867
diff changeset
1012 check_for_dir:
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1013 sp->fts_cur = p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1014 if (p->fts_info == FTS_NSOK)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1015 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1016 if (p->fts_statp->st_size == FTS_STAT_REQUIRED)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1017 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1018 FTSENT *parent = p->fts_parent;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1019 if (FTS_ROOTLEVEL < p->fts_level
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1020 /* ->fts_n_dirs_remaining is not valid
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1021 for command-line-specified names. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1022 && parent->fts_n_dirs_remaining == 0
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1023 && ISSET(FTS_NOSTAT)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1024 && ISSET(FTS_PHYSICAL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1025 && link_count_optimize_ok (parent))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1026 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1027 /* nothing more needed */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1028 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1029 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1030 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1031 p->fts_info = fts_stat(sp, p, false);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1032 if (S_ISDIR(p->fts_statp->st_mode)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1033 && p->fts_level != FTS_ROOTLEVEL
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1034 && parent->fts_n_dirs_remaining)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1035 parent->fts_n_dirs_remaining--;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1036 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1037 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1038 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1039 fts_assert (p->fts_statp->st_size == FTS_NO_STAT_REQUIRED);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1040 }
7707
3f57a32346a2 * lib/fts.c (fts_load): Don't set sp->fts_dev here, since
Jim Meyering <jim@meyering.net>
parents: 7684
diff changeset
1041
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1042 if (p->fts_info == FTS_D)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1043 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1044 /* Now that P->fts_statp is guaranteed to be valid,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1045 if this is a command-line directory, record its
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1046 device number, to be used for FTS_XDEV. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1047 if (p->fts_level == FTS_ROOTLEVEL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1048 sp->fts_dev = p->fts_statp->st_dev;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1049 Dprintf ((" entering: %s\n", p->fts_path));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1050 if (! enter_dir (sp, p))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1051 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1052 __set_errno (ENOMEM);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1053 return NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1054 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1055 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1056 return p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1057 }
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1058 cd_dot_dot:
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1059
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1060 /* Move up to the parent node. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1061 p = tmp->fts_parent;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1062 sp->fts_cur = p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1063 free(tmp);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1064
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1065 if (p->fts_level == FTS_ROOTPARENTLEVEL) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1066 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1067 * Done; free everything up and set errno to 0 so the user
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1068 * can distinguish between error and EOF.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1069 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1070 free(p);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1071 __set_errno (0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1072 return (sp->fts_cur = NULL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1073 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1074
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1075 fts_assert (p->fts_info != FTS_NSOK);
7482
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
1076
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1077 /* NUL terminate the file name. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1078 sp->fts_path[p->fts_pathlen] = '\0';
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1079
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1080 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1081 * Return to the parent directory. If at a root node, restore
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1082 * the initial working directory. If we came through a symlink,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1083 * go back through the file descriptor. Otherwise, move up
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1084 * one level, via "..".
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1085 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1086 if (p->fts_level == FTS_ROOTLEVEL) {
15988
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
1087 if (restore_initial_cwd(sp)) {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1088 p->fts_errno = errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1089 SET(FTS_STOP);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1090 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1091 } else if (p->fts_flags & FTS_SYMFOLLOW) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1092 if (FCHDIR(sp, p->fts_symfd)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1093 p->fts_errno = errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1094 SET(FTS_STOP);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1095 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1096 (void)close(p->fts_symfd);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1097 } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1098 fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1099 p->fts_errno = errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1100 SET(FTS_STOP);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1101 }
17914
644307da6af9 fts: avoid crash when a cycle is added while traversing
Kamil Dudka <kdudka@redhat.com>
parents: 17848
diff changeset
1102
644307da6af9 fts: avoid crash when a cycle is added while traversing
Kamil Dudka <kdudka@redhat.com>
parents: 17848
diff changeset
1103 /* If the directory causes a cycle, preserve the FTS_DC flag and keep
644307da6af9 fts: avoid crash when a cycle is added while traversing
Kamil Dudka <kdudka@redhat.com>
parents: 17848
diff changeset
1104 the corresponding dev/ino pair in the hash table. It is going to be
644307da6af9 fts: avoid crash when a cycle is added while traversing
Kamil Dudka <kdudka@redhat.com>
parents: 17848
diff changeset
1105 removed when leaving the original directory. */
644307da6af9 fts: avoid crash when a cycle is added while traversing
Kamil Dudka <kdudka@redhat.com>
parents: 17848
diff changeset
1106 if (p->fts_info != FTS_DC) {
644307da6af9 fts: avoid crash when a cycle is added while traversing
Kamil Dudka <kdudka@redhat.com>
parents: 17848
diff changeset
1107 p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
644307da6af9 fts: avoid crash when a cycle is added while traversing
Kamil Dudka <kdudka@redhat.com>
parents: 17848
diff changeset
1108 if (p->fts_errno == 0)
644307da6af9 fts: avoid crash when a cycle is added while traversing
Kamil Dudka <kdudka@redhat.com>
parents: 17848
diff changeset
1109 LEAVE_DIR (sp, p, "3");
644307da6af9 fts: avoid crash when a cycle is added while traversing
Kamil Dudka <kdudka@redhat.com>
parents: 17848
diff changeset
1110 }
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1111 return ISSET(FTS_STOP) ? NULL : p;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1112 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1113
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1114 /*
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1115 * Fts_set takes the stream as an argument although it's not used in this
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1116 * implementation; it would be necessary if anyone wanted to add global
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1117 * semantics to fts using fts_set. An error return is allowed for similar
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1118 * reasons.
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1119 */
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1120 /* ARGSUSED */
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1121 int
12482
11bc92a9e2bc gnulib-common: prefer _GL_UNUSED over _UNUSED_PARAMETER_
Eric Blake <ebb9@byu.net>
parents: 12421
diff changeset
1122 fts_set(FTS *sp _GL_UNUSED, FTSENT *p, int instr)
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1123 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1124 if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1125 instr != FTS_NOINSTR && instr != FTS_SKIP) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1126 __set_errno (EINVAL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1127 return (1);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1128 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1129 p->fts_instr = instr;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1130 return (0);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1131 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1132
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1133 FTSENT *
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1134 fts_children (register FTS *sp, int instr)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1135 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1136 register FTSENT *p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1137 int fd;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1138
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1139 if (instr != 0 && instr != FTS_NAMEONLY) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1140 __set_errno (EINVAL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1141 return (NULL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1142 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1143
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1144 /* Set current node pointer. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1145 p = sp->fts_cur;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1146
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1147 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1148 * Errno set to 0 so user can distinguish empty directory from
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1149 * an error.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1150 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1151 __set_errno (0);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1152
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1153 /* Fatal errors stop here. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1154 if (ISSET(FTS_STOP))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1155 return (NULL);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1156
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1157 /* Return logical hierarchy of user's arguments. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1158 if (p->fts_info == FTS_INIT)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1159 return (p->fts_link);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1160
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1161 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1162 * If not a directory being visited in pre-order, stop here. Could
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1163 * allow FTS_DNR, assuming the user has fixed the problem, but the
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1164 * same effect is available with FTS_AGAIN.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1165 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1166 if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1167 return (NULL);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1168
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1169 /* Free up any previous child list. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1170 if (sp->fts_child != NULL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1171 fts_lfree(sp->fts_child);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1172
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1173 if (instr == FTS_NAMEONLY) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1174 SET(FTS_NAMEONLY);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1175 instr = BNAMES;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1176 } else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1177 instr = BCHILD;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1178
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1179 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1180 * If using chdir on a relative file name and called BEFORE fts_read
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1181 * does its chdir to the root of a traversal, we can lose -- we need to
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1182 * chdir into the subdirectory, and we don't know where the current
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1183 * directory is, so we can't get back so that the upcoming chdir by
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1184 * fts_read will work.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1185 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1186 if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1187 ISSET(FTS_NOCHDIR))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1188 return (sp->fts_child = fts_build(sp, instr));
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1189
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1190 if ((fd = diropen (sp, ".")) < 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1191 return (sp->fts_child = NULL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1192 sp->fts_child = fts_build(sp, instr);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1193 if (ISSET(FTS_CWDFD))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1194 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1195 cwd_advance_fd (sp, fd, true);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1196 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1197 else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1198 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1199 if (fchdir(fd))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1200 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1201 int saved_errno = errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1202 close (fd);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1203 __set_errno (saved_errno);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1204 return NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1205 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1206 close (fd);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1207 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1208 return (sp->fts_child);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1209 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1210
10481
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
1211 /* A comparison function to sort on increasing inode number.
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
1212 For some file system types, sorting either way makes a huge
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
1213 performance difference for a directory with very many entries,
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
1214 but sorting on increasing values is slightly better than sorting
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
1215 on decreasing values. The difference is in the 5% range. */
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
1216 static int
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
1217 fts_compare_ino (struct _ftsent const **a, struct _ftsent const **b)
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
1218 {
10482
e8d1a5b2c49c fts: tweak inode comparison function
Jim Meyering <meyering@redhat.com>
parents: 10481
diff changeset
1219 return (a[0]->fts_statp->st_ino < b[0]->fts_statp->st_ino ? -1
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1220 : b[0]->fts_statp->st_ino < a[0]->fts_statp->st_ino ? 1 : 0);
10481
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
1221 }
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
1222
10843
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1223 /* Map the dirent.d_type value, DTYPE, to the corresponding stat.st_mode
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1224 S_IF* bit and set ST.st_mode, thus clearing all other bits in that field. */
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1225 static void
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1226 set_stat_type (struct stat *st, unsigned int dtype)
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1227 {
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1228 mode_t type;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1229 switch (dtype)
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1230 {
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1231 case DT_BLK:
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1232 type = S_IFBLK;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1233 break;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1234 case DT_CHR:
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1235 type = S_IFCHR;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1236 break;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1237 case DT_DIR:
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1238 type = S_IFDIR;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1239 break;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1240 case DT_FIFO:
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1241 type = S_IFIFO;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1242 break;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1243 case DT_LNK:
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1244 type = S_IFLNK;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1245 break;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1246 case DT_REG:
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1247 type = S_IFREG;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1248 break;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1249 case DT_SOCK:
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1250 type = S_IFSOCK;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1251 break;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1252 default:
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1253 type = 0;
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1254 }
10844
70fc7855343a fts: fix a thinko
Jim Meyering <meyering@redhat.com>
parents: 10843
diff changeset
1255 st->st_mode = type;
10843
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1256 }
36479bd141ee fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents: 10688
diff changeset
1257
15529
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1258 #define closedir_and_clear(dirp) \
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1259 do \
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1260 { \
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1261 closedir (dirp); \
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1262 dirp = NULL; \
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1263 } \
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1264 while (0)
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1265
15528
8203b056cc79 maint: fts: give __opendir2 a new parameter and rename
Jim Meyering <meyering@redhat.com>
parents: 15527
diff changeset
1266 #define fts_opendir(file, Pdir_fd) \
15525
792927a7e09d maint: fts.c: move __opendir2 #define "up" out of function body
Jim Meyering <meyering@redhat.com>
parents: 15524
diff changeset
1267 opendirat((! ISSET(FTS_NOCHDIR) && ISSET(FTS_CWDFD) \
792927a7e09d maint: fts.c: move __opendir2 #define "up" out of function body
Jim Meyering <meyering@redhat.com>
parents: 15524
diff changeset
1268 ? sp->fts_cwd_fd : AT_FDCWD), \
792927a7e09d maint: fts.c: move __opendir2 #define "up" out of function body
Jim Meyering <meyering@redhat.com>
parents: 15524
diff changeset
1269 file, \
792927a7e09d maint: fts.c: move __opendir2 #define "up" out of function body
Jim Meyering <meyering@redhat.com>
parents: 15524
diff changeset
1270 (((ISSET(FTS_PHYSICAL) \
792927a7e09d maint: fts.c: move __opendir2 #define "up" out of function body
Jim Meyering <meyering@redhat.com>
parents: 15524
diff changeset
1271 && ! (ISSET(FTS_COMFOLLOW) \
792927a7e09d maint: fts.c: move __opendir2 #define "up" out of function body
Jim Meyering <meyering@redhat.com>
parents: 15524
diff changeset
1272 && cur->fts_level == FTS_ROOTLEVEL)) \
792927a7e09d maint: fts.c: move __opendir2 #define "up" out of function body
Jim Meyering <meyering@redhat.com>
parents: 15524
diff changeset
1273 ? O_NOFOLLOW : 0) \
792927a7e09d maint: fts.c: move __opendir2 #define "up" out of function body
Jim Meyering <meyering@redhat.com>
parents: 15524
diff changeset
1274 | (ISSET (FTS_NOATIME) ? O_NOATIME : 0)), \
15528
8203b056cc79 maint: fts: give __opendir2 a new parameter and rename
Jim Meyering <meyering@redhat.com>
parents: 15527
diff changeset
1275 Pdir_fd)
15525
792927a7e09d maint: fts.c: move __opendir2 #define "up" out of function body
Jim Meyering <meyering@redhat.com>
parents: 15524
diff changeset
1276
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1277 /*
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1278 * This is the tricky part -- do not casually change *anything* in here. The
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1279 * idea is to build the linked list of entries that are used by fts_children
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1280 * and fts_read. There are lots of special cases.
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1281 *
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1282 * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1283 * set and it's a physical walk (so that symbolic links can't be directories),
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1284 * we can do things quickly. First, if it's a 4.4BSD file system, the type
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1285 * of the file is in the directory entry. Otherwise, we assume that the number
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1286 * of subdirectories in a node is equal to the number of links to the parent.
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1287 * The former skips all stat calls. The latter skips stat calls in any leaf
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1288 * directories and for any files after the subdirectories in the directory have
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1289 * been found, cutting the stat calls by about 2/3.
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1290 */
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1291 static FTSENT *
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1292 internal_function
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1293 fts_build (register FTS *sp, int type)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1294 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1295 register FTSENT *p, *head;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1296 register size_t nitems;
15529
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1297 FTSENT *tail;
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1298 void *oldaddr;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1299 int saved_errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1300 bool descend;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1301 bool doadjust;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1302 ptrdiff_t level;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1303 nlink_t nlinks;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1304 bool nostat;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1305 size_t len, maxlen, new_len;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1306 char *cp;
13676
223800d7ac7d fts, getcwd, glob: audit for dirfd returning -1
Paul Eggert <eggert@cs.ucla.edu>
parents: 13674
diff changeset
1307 int dir_fd;
15529
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1308 FTSENT *cur = sp->fts_cur;
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1309 bool continue_readdir = !!cur->fts_dirp;
17797
dffad0ca4bc1 fts: port to C89
Paul Eggert <eggert@cs.ucla.edu>
parents: 17642
diff changeset
1310 size_t max_entries;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1311
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1312 /* When cur->fts_dirp is non-NULL, that means we should
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1313 continue calling readdir on that existing DIR* pointer
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1314 rather than opening a new one. */
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1315 if (continue_readdir)
15526
95cf436ab3b8 maint: fts.c: correct off-by-one indentation
Jim Meyering <meyering@redhat.com>
parents: 15525
diff changeset
1316 {
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1317 DIR *dp = cur->fts_dirp;
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1318 dir_fd = dirfd (dp);
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1319 if (dir_fd < 0)
15526
95cf436ab3b8 maint: fts.c: correct off-by-one indentation
Jim Meyering <meyering@redhat.com>
parents: 15525
diff changeset
1320 {
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1321 closedir_and_clear (cur->fts_dirp);
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1322 if (type == BREAD)
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1323 {
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1324 cur->fts_info = FTS_DNR;
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1325 cur->fts_errno = errno;
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1326 }
15526
95cf436ab3b8 maint: fts.c: correct off-by-one indentation
Jim Meyering <meyering@redhat.com>
parents: 15525
diff changeset
1327 return NULL;
95cf436ab3b8 maint: fts.c: correct off-by-one indentation
Jim Meyering <meyering@redhat.com>
parents: 15525
diff changeset
1328 }
95cf436ab3b8 maint: fts.c: correct off-by-one indentation
Jim Meyering <meyering@redhat.com>
parents: 15525
diff changeset
1329 }
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1330 else
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1331 {
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1332 /* Open the directory for reading. If this fails, we're done.
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1333 If being called from fts_read, set the fts_info field. */
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1334 if ((cur->fts_dirp = fts_opendir(cur->fts_accpath, &dir_fd)) == NULL)
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1335 {
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1336 if (type == BREAD)
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1337 {
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1338 cur->fts_info = FTS_DNR;
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1339 cur->fts_errno = errno;
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1340 }
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1341 return NULL;
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1342 }
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1343 /* Rather than calling fts_stat for each and every entry encountered
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1344 in the readdir loop (below), stat each directory only right after
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1345 opening it. */
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1346 if (cur->fts_info == FTS_NSOK)
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1347 cur->fts_info = fts_stat(sp, cur, false);
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1348 else if (sp->fts_options & FTS_TIGHT_CYCLE_CHECK)
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1349 {
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1350 /* Now read the stat info again after opening a directory to
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1351 reveal eventual changes caused by a submount triggered by
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1352 the traversal. But do it only for utilities which use
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1353 FTS_TIGHT_CYCLE_CHECK. Therefore, only find and du
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1354 benefit/suffer from this feature for now. */
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1355 LEAVE_DIR (sp, cur, "4");
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1356 fts_stat (sp, cur, false);
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1357 if (! enter_dir (sp, cur))
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1358 {
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1359 __set_errno (ENOMEM);
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1360 return NULL;
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1361 }
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1362 }
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1363 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1364
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1365 /* Maximum number of readdir entries to read at one time. This
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1366 limitation is to avoid reading millions of entries into memory
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1367 at once. When an fts_compar function is specified, we have no
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1368 choice: we must read all entries into memory before calling that
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1369 function. But when no such function is specified, we can read
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1370 entries in batches that are large enough to help us with inode-
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1371 sorting, yet not so large that we risk exhausting memory. */
17797
dffad0ca4bc1 fts: port to C89
Paul Eggert <eggert@cs.ucla.edu>
parents: 17642
diff changeset
1372 max_entries = sp->fts_compar ? SIZE_MAX : FTS_MAX_READDIR_ENTRIES;
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1373
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1374 /*
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1375 * Nlinks is the number of possible entries of type directory in the
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1376 * directory if we're cheating on stat calls, 0 if we're not doing
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1377 * any stat calls at all, (nlink_t) -1 if we're statting everything.
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1378 */
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1379 if (type == BNAMES) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1380 nlinks = 0;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1381 /* Be quiet about nostat, GCC. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1382 nostat = false;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1383 } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1384 nlinks = (cur->fts_statp->st_nlink
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1385 - (ISSET(FTS_SEEDOT) ? 0 : 2));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1386 nostat = true;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1387 } else {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1388 nlinks = -1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1389 nostat = false;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1390 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1391
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1392 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1393 * If we're going to need to stat anything or we want to descend
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1394 * and stay in the directory, chdir. If this fails we keep going,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1395 * but set a flag so we don't chdir after the post-order visit.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1396 * We won't be able to stat anything, but we can still return the
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1397 * names themselves. Note, that since fts_read won't be able to
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1398 * chdir into the directory, it will have to return different file
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1399 * names than before, i.e. "a/b" instead of "b". Since the node
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1400 * has already been visited in pre-order, have to wait until the
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1401 * post-order visit to return the error. There is a special case
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1402 * here, if there was nothing to stat then it's not an error to
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1403 * not be able to stat. This is all fairly nasty. If a program
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1404 * needed sorted entries or stat information, they had better be
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1405 * checking FTS_NS on the returned nodes.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1406 */
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1407 if (continue_readdir)
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1408 {
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1409 /* When resuming a short readdir run, we already have
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1410 the required dirp and dir_fd. */
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1411 descend = true;
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1412 }
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1413 else if (nlinks || type == BREAD) {
13676
223800d7ac7d fts, getcwd, glob: audit for dirfd returning -1
Paul Eggert <eggert@cs.ucla.edu>
parents: 13674
diff changeset
1414 if (ISSET(FTS_CWDFD))
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1415 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1416 dir_fd = dup (dir_fd);
13671
228e72ae2254 fts: don't operate on an invalid file descriptor after failed dup
Jim Meyering <meyering@redhat.com>
parents: 13616
diff changeset
1417 if (0 <= dir_fd)
228e72ae2254 fts: don't operate on an invalid file descriptor after failed dup
Jim Meyering <meyering@redhat.com>
parents: 13616
diff changeset
1418 set_cloexec_flag (dir_fd, true);
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1419 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1420 if (dir_fd < 0 || fts_safe_changedir(sp, cur, dir_fd, NULL)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1421 if (nlinks && type == BREAD)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1422 cur->fts_errno = errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1423 cur->fts_flags |= FTS_DONTCHDIR;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1424 descend = false;
15529
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1425 closedir_and_clear(cur->fts_dirp);
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1426 if (ISSET(FTS_CWDFD) && 0 <= dir_fd)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1427 close (dir_fd);
15529
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1428 cur->fts_dirp = NULL;
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1429 } else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1430 descend = true;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1431 } else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1432 descend = false;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1433
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1434 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1435 * Figure out the max file name length that can be stored in the
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1436 * current buffer -- the inner loop allocates more space as necessary.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1437 * We really wouldn't have to do the maxlen calculations here, we
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1438 * could do them in fts_read before returning the name, but it's a
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1439 * lot easier here since the length is part of the dirent structure.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1440 *
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1441 * If not changing directories set a pointer so that can just append
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1442 * each new component into the file name.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1443 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1444 len = NAPPEND(cur);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1445 if (ISSET(FTS_NOCHDIR)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1446 cp = sp->fts_path + len;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1447 *cp++ = '/';
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1448 } else {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1449 /* GCC, you're too verbose. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1450 cp = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1451 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1452 len++;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1453 maxlen = sp->fts_pathlen - len;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1454
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1455 level = cur->fts_level + 1;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1456
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
1457 /* Read the directory, attaching each entry to the "link" pointer. */
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1458 doadjust = false;
15530
ddc76c261e25 maint: fts: move decl of `dp' down into while loop; split a long line
Jim Meyering <meyering@redhat.com>
parents: 15529
diff changeset
1459 head = NULL;
ddc76c261e25 maint: fts: move decl of `dp' down into while loop; split a long line
Jim Meyering <meyering@redhat.com>
parents: 15529
diff changeset
1460 tail = NULL;
ddc76c261e25 maint: fts: move decl of `dp' down into while loop; split a long line
Jim Meyering <meyering@redhat.com>
parents: 15529
diff changeset
1461 nitems = 0;
ddc76c261e25 maint: fts: move decl of `dp' down into while loop; split a long line
Jim Meyering <meyering@redhat.com>
parents: 15529
diff changeset
1462 while (cur->fts_dirp) {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1463 bool is_dir;
17640
aa5bda4ec2ae fts: avoid unnecessary strlen calls
Bernhard Voelker <mail@bernhard-voelker.de>
parents: 17576
diff changeset
1464 size_t d_namelen;
18338
7276fe79480b fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents: 18325
diff changeset
1465 __set_errno (0);
15530
ddc76c261e25 maint: fts: move decl of `dp' down into while loop; split a long line
Jim Meyering <meyering@redhat.com>
parents: 15529
diff changeset
1466 struct dirent *dp = readdir(cur->fts_dirp);
18338
7276fe79480b fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents: 18325
diff changeset
1467 if (dp == NULL) {
7276fe79480b fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents: 18325
diff changeset
1468 if (errno) {
7276fe79480b fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents: 18325
diff changeset
1469 cur->fts_errno = errno;
7276fe79480b fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents: 18325
diff changeset
1470 /* If we've not read any items yet, treat
7276fe79480b fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents: 18325
diff changeset
1471 the error as if we can't access the dir. */
7276fe79480b fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents: 18325
diff changeset
1472 cur->fts_info = (continue_readdir || nitems)
7276fe79480b fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents: 18325
diff changeset
1473 ? FTS_ERR : FTS_DNR;
7276fe79480b fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents: 18325
diff changeset
1474 }
15530
ddc76c261e25 maint: fts: move decl of `dp' down into while loop; split a long line
Jim Meyering <meyering@redhat.com>
parents: 15529
diff changeset
1475 break;
18338
7276fe79480b fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents: 18325
diff changeset
1476 }
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1477 if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1478 continue;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1479
17641
019200939aa7 fts: avoid unnecessary strlen calls
Paul Eggert <eggert@cs.ucla.edu>
parents: 17640
diff changeset
1480 d_namelen = _D_EXACT_NAMLEN (dp);
019200939aa7 fts: avoid unnecessary strlen calls
Paul Eggert <eggert@cs.ucla.edu>
parents: 17640
diff changeset
1481 p = fts_alloc (sp, dp->d_name, d_namelen);
019200939aa7 fts: avoid unnecessary strlen calls
Paul Eggert <eggert@cs.ucla.edu>
parents: 17640
diff changeset
1482 if (!p)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1483 goto mem1;
17640
aa5bda4ec2ae fts: avoid unnecessary strlen calls
Bernhard Voelker <mail@bernhard-voelker.de>
parents: 17576
diff changeset
1484 if (d_namelen >= maxlen) {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1485 /* include space for NUL */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1486 oldaddr = sp->fts_path;
17640
aa5bda4ec2ae fts: avoid unnecessary strlen calls
Bernhard Voelker <mail@bernhard-voelker.de>
parents: 17576
diff changeset
1487 if (! fts_palloc(sp, d_namelen + len + 1)) {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1488 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1489 * No more memory. Save
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1490 * errno, free up the current structure and the
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1491 * structures already allocated.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1492 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1493 mem1: saved_errno = errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1494 free(p);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1495 fts_lfree(head);
15529
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1496 closedir_and_clear(cur->fts_dirp);
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1497 cur->fts_info = FTS_ERR;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1498 SET(FTS_STOP);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1499 __set_errno (saved_errno);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1500 return (NULL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1501 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1502 /* Did realloc() change the pointer? */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1503 if (oldaddr != sp->fts_path) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1504 doadjust = true;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1505 if (ISSET(FTS_NOCHDIR))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1506 cp = sp->fts_path + len;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1507 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1508 maxlen = sp->fts_pathlen - len;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1509 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1510
17640
aa5bda4ec2ae fts: avoid unnecessary strlen calls
Bernhard Voelker <mail@bernhard-voelker.de>
parents: 17576
diff changeset
1511 new_len = len + d_namelen;
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1512 if (new_len < len) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1513 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1514 * In the unlikely event that we would end up
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1515 * with a file name longer than SIZE_MAX, free up
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1516 * the current structure and the structures already
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1517 * allocated, then error out with ENAMETOOLONG.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1518 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1519 free(p);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1520 fts_lfree(head);
15529
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1521 closedir_and_clear(cur->fts_dirp);
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1522 cur->fts_info = FTS_ERR;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1523 SET(FTS_STOP);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1524 __set_errno (ENAMETOOLONG);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1525 return (NULL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1526 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1527 p->fts_level = level;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1528 p->fts_parent = sp->fts_cur;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1529 p->fts_pathlen = new_len;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1530
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1531 /* Store dirent.d_ino, in case we need to sort
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1532 entries before processing them. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1533 p->fts_statp->st_ino = D_INO (dp);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1534
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1535 /* Build a file name for fts_stat to stat. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1536 if (ISSET(FTS_NOCHDIR)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1537 p->fts_accpath = p->fts_path;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1538 memmove(cp, p->fts_name, p->fts_namelen + 1);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1539 } else
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1540 p->fts_accpath = p->fts_name;
7482
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
1541
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1542 if (sp->fts_compar == NULL || ISSET(FTS_DEFER_STAT)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1543 /* Record what fts_read will have to do with this
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1544 entry. In many cases, it will simply fts_stat it,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1545 but we can take advantage of any d_type information
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1546 to optimize away the unnecessary stat calls. I.e.,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1547 if FTS_NOSTAT is in effect and we're not following
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1548 symlinks (FTS_PHYSICAL) and d_type indicates this
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1549 is *not* a directory, then we won't have to stat it
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1550 at all. If it *is* a directory, then (currently)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1551 we stat it regardless, in order to get device and
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1552 inode numbers. Some day we might optimize that
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1553 away, too, for directories where d_ino is known to
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1554 be valid. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1555 bool skip_stat = (ISSET(FTS_PHYSICAL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1556 && ISSET(FTS_NOSTAT)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1557 && DT_IS_KNOWN(dp)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1558 && ! DT_MUST_BE(dp, DT_DIR));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1559 p->fts_info = FTS_NSOK;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1560 /* Propagate dirent.d_type information back
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1561 to caller, when possible. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1562 set_stat_type (p->fts_statp, D_TYPE (dp));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1563 fts_set_stat_required(p, !skip_stat);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1564 is_dir = (ISSET(FTS_PHYSICAL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1565 && DT_MUST_BE(dp, DT_DIR));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1566 } else {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1567 p->fts_info = fts_stat(sp, p, false);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1568 is_dir = (p->fts_info == FTS_D
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1569 || p->fts_info == FTS_DC
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1570 || p->fts_info == FTS_DOT);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1571 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1572
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1573 /* Decrement link count if applicable. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1574 if (nlinks > 0 && is_dir)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1575 nlinks -= nostat;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1576
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1577 /* We walk in directory order so "ls -f" doesn't get upset. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1578 p->fts_link = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1579 if (head == NULL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1580 head = tail = p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1581 else {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1582 tail->fts_link = p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1583 tail = p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1584 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1585 ++nitems;
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1586 if (max_entries <= nitems) {
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1587 /* When there are too many dir entries, leave
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1588 fts_dirp open, so that a subsequent fts_read
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1589 can take up where we leave off. */
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1590 goto break_without_closedir;
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1591 }
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1592 }
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1593
15529
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1594 if (cur->fts_dirp)
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1595 closedir_and_clear(cur->fts_dirp);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1596
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1597 break_without_closedir:
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1598
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1599 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1600 * If realloc() changed the address of the file name, adjust the
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1601 * addresses for the rest of the tree and the dir list.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1602 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1603 if (doadjust)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1604 fts_padjust(sp, head);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1605
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1606 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1607 * If not changing directories, reset the file name back to original
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1608 * state.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1609 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1610 if (ISSET(FTS_NOCHDIR)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1611 if (len == sp->fts_pathlen || nitems == 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1612 --cp;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1613 *cp = '\0';
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1614 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1615
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1616 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1617 * If descended after called from fts_children or after called from
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1618 * fts_read and nothing found, get back. At the root level we use
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1619 * the saved fd; if one of fts_open()'s arguments is a relative name
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1620 * to an empty directory, we wind up here with no other way back. If
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1621 * can't get back, we're done.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1622 */
15531
65fb6cc5f301 fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents: 15530
diff changeset
1623 if (!continue_readdir && descend && (type == BCHILD || !nitems) &&
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1624 (cur->fts_level == FTS_ROOTLEVEL
15988
cd7ac59d8eb5 fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents: 15531
diff changeset
1625 ? restore_initial_cwd(sp)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1626 : fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1627 cur->fts_info = FTS_ERR;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1628 SET(FTS_STOP);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1629 fts_lfree(head);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1630 return (NULL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1631 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1632
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1633 /* If didn't find anything, return NULL. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1634 if (!nitems) {
18338
7276fe79480b fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents: 18325
diff changeset
1635 if (type == BREAD
7276fe79480b fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents: 18325
diff changeset
1636 && cur->fts_info != FTS_DNR && cur->fts_info != FTS_ERR)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1637 cur->fts_info = FTS_DP;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1638 fts_lfree(head);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1639 return (NULL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1640 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1641
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1642 /* If there are many entries, no sorting function has been specified,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1643 and this file system is of a type that may be slow with a large
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1644 number of entries, then sort the directory entries on increasing
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1645 inode numbers. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1646 if (nitems > _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1647 && !sp->fts_compar
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1648 && ISSET (FTS_CWDFD)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1649 && dirent_inode_sort_may_be_useful (sp->fts_cwd_fd)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1650 sp->fts_compar = fts_compare_ino;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1651 head = fts_sort (sp, head, nitems);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1652 sp->fts_compar = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1653 }
10481
47fe4e48e158 fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents: 9718
diff changeset
1654
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1655 /* Sort the entries. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1656 if (sp->fts_compar && nitems > 1)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1657 head = fts_sort(sp, head, nitems);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1658 return (head);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1659 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1660
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1661 #if FTS_DEBUG
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1662
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1663 /* Walk ->fts_parent links starting at E_CURR, until the root of the
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1664 current hierarchy. There should be a directory with dev/inode
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1665 matching those of AD. If not, print a lot of diagnostics. */
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1666 static void
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1667 find_matching_ancestor (FTSENT const *e_curr, struct Active_dir const *ad)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1668 {
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1669 FTSENT const *ent;
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1670 for (ent = e_curr; ent->fts_level >= FTS_ROOTLEVEL; ent = ent->fts_parent)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1671 {
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1672 if (ad->ino == ent->fts_statp->st_ino
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1673 && ad->dev == ent->fts_statp->st_dev)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1674 return;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1675 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1676 printf ("ERROR: tree dir, %s, not active\n", ad->fts_ent->fts_accpath);
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1677 printf ("active dirs:\n");
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1678 for (ent = e_curr;
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1679 ent->fts_level >= FTS_ROOTLEVEL; ent = ent->fts_parent)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1680 printf (" %s(%"PRIuMAX"/%"PRIuMAX") to %s(%"PRIuMAX"/%"PRIuMAX")...\n",
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1681 ad->fts_ent->fts_accpath,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1682 (uintmax_t) ad->dev,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1683 (uintmax_t) ad->ino,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1684 ent->fts_accpath,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1685 (uintmax_t) ent->fts_statp->st_dev,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1686 (uintmax_t) ent->fts_statp->st_ino);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1687 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1688
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1689 void
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1690 fts_cross_check (FTS const *sp)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1691 {
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1692 FTSENT const *ent = sp->fts_cur;
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1693 FTSENT const *t;
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1694 if ( ! ISSET (FTS_TIGHT_CYCLE_CHECK))
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1695 return;
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1696
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1697 Dprintf (("fts-cross-check cur=%s\n", ent->fts_path));
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1698 /* Make sure every parent dir is in the tree. */
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1699 for (t = ent->fts_parent; t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1700 {
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1701 struct Active_dir ad;
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1702 ad.ino = t->fts_statp->st_ino;
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1703 ad.dev = t->fts_statp->st_dev;
6034
96149b1bbb32 (fts_cross_check) [FTS_DEBUG]: s/active_dir_ht/fts_cycle.ht/.
Jim Meyering <jim@meyering.net>
parents: 5907
diff changeset
1704 if ( ! hash_lookup (sp->fts_cycle.ht, &ad))
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1705 printf ("ERROR: active dir, %s, not in tree\n", t->fts_path);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1706 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1707
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1708 /* Make sure every dir in the tree is an active dir.
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1709 But ENT is not necessarily a directory. If so, just skip this part. */
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1710 if (ent->fts_parent->fts_level >= FTS_ROOTLEVEL
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1711 && (ent->fts_info == FTS_DP
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1712 || ent->fts_info == FTS_D))
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1713 {
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1714 struct Active_dir *ad;
6034
96149b1bbb32 (fts_cross_check) [FTS_DEBUG]: s/active_dir_ht/fts_cycle.ht/.
Jim Meyering <jim@meyering.net>
parents: 5907
diff changeset
1715 for (ad = hash_get_first (sp->fts_cycle.ht); ad != NULL;
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1716 ad = hash_get_next (sp->fts_cycle.ht, ad))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1717 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1718 find_matching_ancestor (ent, ad);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1719 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1720 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1721 }
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1722
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1723 static bool
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1724 same_fd (int fd1, int fd2)
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1725 {
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1726 struct stat sb1, sb2;
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1727 return (fstat (fd1, &sb1) == 0
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1728 && fstat (fd2, &sb2) == 0
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1729 && SAME_INODE (sb1, sb2));
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1730 }
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1731
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1732 static void
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1733 fd_ring_print (FTS const *sp, FILE *stream, char const *msg)
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1734 {
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1735 I_ring const *fd_ring = &sp->fts_fd_ring;
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1736 unsigned int i = fd_ring->fts_front;
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1737 char *cwd = getcwdat (sp->fts_cwd_fd, NULL, 0);
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1738 fprintf (stream, "=== %s ========== %s\n", msg, cwd);
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1739 free (cwd);
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1740 if (i_ring_empty (fd_ring))
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1741 return;
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1742
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1743 while (true)
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1744 {
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1745 int fd = fd_ring->fts_fd_ring[i];
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1746 if (fd < 0)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1747 fprintf (stream, "%d: %d:\n", i, fd);
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1748 else
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1749 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1750 char *wd = getcwdat (fd, NULL, 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1751 fprintf (stream, "%d: %d: %s\n", i, fd, wd);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1752 free (wd);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1753 }
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1754 if (i == fd_ring->fts_back)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1755 break;
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1756 i = (i + I_RING_SIZE - 1) % I_RING_SIZE;
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1757 }
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1758 }
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1759
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1760 /* Ensure that each file descriptor on the fd_ring matches a
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1761 parent, grandparent, etc. of the current working directory. */
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1762 static void
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1763 fd_ring_check (FTS const *sp)
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1764 {
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1765 if (!fts_debug)
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1766 return;
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1767
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1768 /* Make a writable copy. */
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1769 I_ring fd_w = sp->fts_fd_ring;
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1770
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1771 int cwd_fd = sp->fts_cwd_fd;
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1772 cwd_fd = dup (cwd_fd);
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1773 char *dot = getcwdat (cwd_fd, NULL, 0);
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1774 error (0, 0, "===== check ===== cwd: %s", dot);
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1775 free (dot);
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1776 while ( ! i_ring_empty (&fd_w))
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1777 {
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1778 int fd = i_ring_pop (&fd_w);
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1779 if (0 <= fd)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1780 {
15374
04a9f678e342 fts: introduce FTS_NOATIME
Eric Blake <eblake@redhat.com>
parents: 14774
diff changeset
1781 int parent_fd = openat (cwd_fd, "..", O_SEARCH | O_NOATIME);
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1782 if (parent_fd < 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1783 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1784 // Warn?
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1785 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1786 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1787 if (!same_fd (fd, parent_fd))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1788 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1789 char *cwd = getcwdat (fd, NULL, 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1790 error (0, errno, "ring : %s", cwd);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1791 char *c2 = getcwdat (parent_fd, NULL, 0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1792 error (0, errno, "parent: %s", c2);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1793 free (cwd);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1794 free (c2);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1795 fts_assert (0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1796 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1797 close (cwd_fd);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1798 cwd_fd = parent_fd;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1799 }
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1800 }
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1801 close (cwd_fd);
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
1802 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1803 #endif
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1804
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1805 static unsigned short int
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1806 internal_function
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1807 fts_stat(FTS *sp, register FTSENT *p, bool follow)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1808 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1809 struct stat *sbp = p->fts_statp;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1810 int saved_errno;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1811
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1812 if (p->fts_level == FTS_ROOTLEVEL && ISSET(FTS_COMFOLLOW))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1813 follow = true;
7482
26914593f079 Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents: 7408
diff changeset
1814
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1815 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1816 * If doing a logical walk, or application requested FTS_FOLLOW, do
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1817 * a stat(2). If that fails, check for a non-existent symlink. If
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1818 * fail, set the errno from the stat call.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1819 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1820 if (ISSET(FTS_LOGICAL) || follow) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1821 if (stat(p->fts_accpath, sbp)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1822 saved_errno = errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1823 if (errno == ENOENT
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1824 && lstat(p->fts_accpath, sbp) == 0) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1825 __set_errno (0);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1826 return (FTS_SLNONE);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1827 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1828 p->fts_errno = saved_errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1829 goto err;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1830 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1831 } else if (fstatat(sp->fts_cwd_fd, p->fts_accpath, sbp,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1832 AT_SYMLINK_NOFOLLOW)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1833 p->fts_errno = errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1834 err: memset(sbp, 0, sizeof(struct stat));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1835 return (FTS_NS);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1836 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1837
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1838 if (S_ISDIR(sbp->st_mode)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1839 p->fts_n_dirs_remaining = (sbp->st_nlink
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1840 - (ISSET(FTS_SEEDOT) ? 0 : 2));
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1841 if (ISDOT(p->fts_name)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1842 /* Command-line "." and ".." are real directories. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1843 return (p->fts_level == FTS_ROOTLEVEL ? FTS_D : FTS_DOT);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1844 }
5872
fab6701e5cb2 New fts module.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5867
diff changeset
1845
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1846 return (FTS_D);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1847 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1848 if (S_ISLNK(sbp->st_mode))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1849 return (FTS_SL);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1850 if (S_ISREG(sbp->st_mode))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1851 return (FTS_F);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1852 return (FTS_DEFAULT);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1853 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1854
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1855 static int
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1856 fts_compar (void const *a, void const *b)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1857 {
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1858 /* Convert A and B to the correct types, to pacify the compiler, and
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1859 for portability to bizarre hosts where "void const *" and "FTSENT
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1860 const **" differ in runtime representation. The comparison
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1861 function cannot modify *a and *b, but there is no compile-time
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1862 check for this. */
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1863 FTSENT const **pa = (FTSENT const **) a;
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1864 FTSENT const **pb = (FTSENT const **) b;
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1865 return pa[0]->fts_fts->fts_compar (pa, pb);
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1866 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1867
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1868 static FTSENT *
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1869 internal_function
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1870 fts_sort (FTS *sp, FTSENT *head, register size_t nitems)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1871 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1872 register FTSENT **ap, *p;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1873
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1874 /* On most modern hosts, void * and FTSENT ** have the same
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1875 run-time representation, and one can convert sp->fts_compar to
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1876 the type qsort expects without problem. Use the heuristic that
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1877 this is OK if the two pointer types are the same size, and if
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1878 converting FTSENT ** to long int is the same as converting
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1879 FTSENT ** to void * and then to long int. This heuristic isn't
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1880 valid in general but we don't know of any counterexamples. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1881 FTSENT *dummy;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1882 int (*compare) (void const *, void const *) =
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1883 ((sizeof &dummy == sizeof (void *)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1884 && (long int) &dummy == (long int) (void *) &dummy)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1885 ? (int (*) (void const *, void const *)) sp->fts_compar
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1886 : fts_compar);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1887
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1888 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1889 * Construct an array of pointers to the structures and call qsort(3).
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1890 * Reassemble the array in the order returned by qsort. If unable to
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1891 * sort for memory reasons, return the directory entries in their
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1892 * current order. Allocate enough space for the current needs plus
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1893 * 40 so don't realloc one entry at a time.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1894 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1895 if (nitems > sp->fts_nitems) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1896 FTSENT **a;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1897
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1898 sp->fts_nitems = nitems + 40;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1899 if (SIZE_MAX / sizeof *a < sp->fts_nitems
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1900 || ! (a = realloc (sp->fts_array,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1901 sp->fts_nitems * sizeof *a))) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1902 free(sp->fts_array);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1903 sp->fts_array = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1904 sp->fts_nitems = 0;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1905 return (head);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1906 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1907 sp->fts_array = a;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1908 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1909 for (ap = sp->fts_array, p = head; p; p = p->fts_link)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1910 *ap++ = p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1911 qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), compare);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1912 for (head = *(ap = sp->fts_array); --nitems; ++ap)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1913 ap[0]->fts_link = ap[1];
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1914 ap[0]->fts_link = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1915 return (head);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1916 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1917
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1918 static FTSENT *
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1919 internal_function
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1920 fts_alloc (FTS *sp, const char *name, register size_t namelen)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1921 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1922 register FTSENT *p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1923 size_t len;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1924
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1925 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1926 * The file name is a variable length array. Allocate the FTSENT
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1927 * structure and the file name in one chunk.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1928 */
18403
4434607ac1ce flexmember: port better to GCC + valgrind
Paul Eggert <eggert@cs.ucla.edu>
parents: 18338
diff changeset
1929 len = FLEXSIZEOF(FTSENT, fts_name, namelen + 1);
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1930 if ((p = malloc(len)) == NULL)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1931 return (NULL);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1932
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1933 /* Copy the name and guarantee NUL termination. */
17073
60627a1a95ff fts: when there is no risk of overlap, use memcpy, not memmove
Jim Meyering <meyering@redhat.com>
parents: 16358
diff changeset
1934 memcpy(p->fts_name, name, namelen);
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1935 p->fts_name[namelen] = '\0';
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1936
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1937 p->fts_namelen = namelen;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1938 p->fts_fts = sp;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1939 p->fts_path = sp->fts_path;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1940 p->fts_errno = 0;
15529
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1941 p->fts_dirp = NULL;
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1942 p->fts_flags = 0;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1943 p->fts_instr = FTS_NOINSTR;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1944 p->fts_number = 0;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1945 p->fts_pointer = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1946 return (p);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1947 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1948
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1949 static void
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1950 internal_function
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1951 fts_lfree (register FTSENT *head)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1952 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1953 register FTSENT *p;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1954
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1955 /* Free a linked list of structures. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1956 while ((p = head)) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1957 head = head->fts_link;
15529
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1958 if (p->fts_dirp)
894e5e6ae541 fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents: 15528
diff changeset
1959 closedir (p->fts_dirp);
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1960 free(p);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1961 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1962 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1963
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1964 /*
5907
c47674a83a78 Sync from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5894
diff changeset
1965 * Allow essentially unlimited file name lengths; find, rm, ls should
c47674a83a78 Sync from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5894
diff changeset
1966 * all work on any tree. Most systems will allow creation of file
c47674a83a78 Sync from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5894
diff changeset
1967 * names much longer than MAXPATHLEN, even though the kernel won't
c47674a83a78 Sync from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5894
diff changeset
1968 * resolve them. Add the size (not just what's needed) plus 256 bytes
c47674a83a78 Sync from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5894
diff changeset
1969 * so don't realloc the file name 2 bytes at a time.
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1970 */
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1971 static bool
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1972 internal_function
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1973 fts_palloc (FTS *sp, size_t more)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1974 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1975 char *p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1976 size_t new_len = sp->fts_pathlen + more + 256;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1977
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1978 /*
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1979 * See if fts_pathlen would overflow.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1980 */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1981 if (new_len < sp->fts_pathlen) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1982 free(sp->fts_path);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1983 sp->fts_path = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1984 __set_errno (ENAMETOOLONG);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1985 return false;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1986 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1987 sp->fts_pathlen = new_len;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1988 p = realloc(sp->fts_path, sp->fts_pathlen);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1989 if (p == NULL) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1990 free(sp->fts_path);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1991 sp->fts_path = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1992 return false;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1993 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1994 sp->fts_path = p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
1995 return true;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1996 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1997
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
1998 /*
5907
c47674a83a78 Sync from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5894
diff changeset
1999 * When the file name is realloc'd, have to fix all of the pointers in
c47674a83a78 Sync from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5894
diff changeset
2000 * structures already returned.
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2001 */
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2002 static void
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2003 internal_function
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2004 fts_padjust (FTS *sp, FTSENT *head)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2005 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2006 FTSENT *p;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2007 char *addr = sp->fts_path;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2008
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2009 #define ADJUST(p) do { \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2010 if ((p)->fts_accpath != (p)->fts_name) { \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2011 (p)->fts_accpath = \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2012 (char *)addr + ((p)->fts_accpath - (p)->fts_path); \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2013 } \
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2014 (p)->fts_path = addr; \
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2015 } while (0)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2016 /* Adjust the current set of children. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2017 for (p = sp->fts_child; p; p = p->fts_link)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2018 ADJUST(p);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2019
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2020 /* Adjust the rest of the tree, including the current level. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2021 for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2022 ADJUST(p);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2023 p = p->fts_link ? p->fts_link : p->fts_parent;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2024 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2025 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2026
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2027 static size_t
16128
6beadb731202 mark functions with const and pure attributes
Jim Meyering <meyering@redhat.com>
parents: 15988
diff changeset
2028 internal_function _GL_ATTRIBUTE_PURE
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2029 fts_maxarglen (char * const *argv)
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2030 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2031 size_t len, max;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2032
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2033 for (max = 0; *argv; ++argv)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2034 if ((len = strlen(*argv)) > max)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2035 max = len;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2036 return (max + 1);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2037 }
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2038
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2039 /*
5907
c47674a83a78 Sync from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5894
diff changeset
2040 * Change to dir specified by fd or file name without getting
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2041 * tricked by someone changing the world out from underneath us.
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2042 * Assumes p->fts_statp->st_dev and p->fts_statp->st_ino are filled in.
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
2043 * If FD is non-negative, expect it to be used after this function returns,
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
2044 * and to be closed eventually. So don't pass e.g., 'dirfd(dirp)' and then
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
2045 * do closedir(dirp), because that would invalidate the saved FD.
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
2046 * Upon failure, close FD immediately and return nonzero.
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2047 */
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2048 static int
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2049 internal_function
5907
c47674a83a78 Sync from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 5894
diff changeset
2050 fts_safe_changedir (FTS *sp, FTSENT *p, int fd, char const *dir)
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2051 {
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2052 int ret;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2053 bool is_dotdot = dir && STREQ (dir, "..");
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2054 int newfd;
7623
5bfad7d666d6 * lib/fts.c (fts_safe_changedir): Add a comment.
Jim Meyering <jim@meyering.net>
parents: 7621
diff changeset
2055
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2056 /* This clause handles the unusual case in which FTS_NOCHDIR
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2057 is specified, along with FTS_CWDFD. In that case, there is
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2058 no need to change even the virtual cwd file descriptor.
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2059 However, if FD is non-negative, we do close it here. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2060 if (ISSET (FTS_NOCHDIR))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2061 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2062 if (ISSET (FTS_CWDFD) && 0 <= fd)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2063 close (fd);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2064 return 0;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2065 }
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2066
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2067 if (fd < 0 && is_dotdot && ISSET (FTS_CWDFD))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2068 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2069 /* When possible, skip the diropen and subsequent fstat+dev/ino
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2070 comparison. I.e., when changing to parent directory
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2071 (chdir ("..")), use a file descriptor from the ring and
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2072 save the overhead of diropen+fstat, as well as avoiding
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2073 failure when we lack "x" access to the virtual cwd. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2074 if ( ! i_ring_empty (&sp->fts_fd_ring))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2075 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2076 int parent_fd;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2077 fd_ring_print (sp, stderr, "pre-pop");
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2078 parent_fd = i_ring_pop (&sp->fts_fd_ring);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2079 is_dotdot = true;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2080 if (0 <= parent_fd)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2081 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2082 fd = parent_fd;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2083 dir = NULL;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2084 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2085 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2086 }
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
2087
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2088 newfd = fd;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2089 if (fd < 0 && (newfd = diropen (sp, dir)) < 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2090 return -1;
7639
1670d42131d7 Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents: 7635
diff changeset
2091
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2092 /* The following dev/inode check is necessary if we're doing a
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
2093 "logical" traversal (through symlinks, a la chown -L), if the
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2094 system lacks O_NOFOLLOW support, or if we're changing to ".."
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2095 (but not via a popped file descriptor). When changing to the
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2096 name "..", O_NOFOLLOW can't help. In general, when the target is
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2097 not "..", diropen's use of O_NOFOLLOW ensures we don't mistakenly
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2098 follow a symlink, so we can avoid the expense of this fstat. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2099 if (ISSET(FTS_LOGICAL) || ! HAVE_WORKING_O_NOFOLLOW
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2100 || (dir && STREQ (dir, "..")))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2101 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2102 struct stat sb;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2103 if (fstat(newfd, &sb))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2104 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2105 ret = -1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2106 goto bail;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2107 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2108 if (p->fts_statp->st_dev != sb.st_dev
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2109 || p->fts_statp->st_ino != sb.st_ino)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2110 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2111 __set_errno (ENOENT); /* disinformation */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2112 ret = -1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2113 goto bail;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2114 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2115 }
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
2116
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2117 if (ISSET(FTS_CWDFD))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2118 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2119 cwd_advance_fd (sp, newfd, ! is_dotdot);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2120 return 0;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2121 }
7151
43e3888c56c4 Update from coreutils.
Paul Eggert <eggert@cs.ucla.edu>
parents: 6949
diff changeset
2122
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2123 ret = fchdir(newfd);
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2124 bail:
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2125 if (fd < 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2126 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2127 int oerrno = errno;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2128 (void)close(newfd);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2129 __set_errno (oerrno);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2130 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12378
diff changeset
2131 return ret;
5858
942c4d17dd7d New files, from coreutils.
Jim Meyering <jim@meyering.net>
parents:
diff changeset
2132 }