Mercurial > gnulib
annotate lib/fts.c @ 19484:10eb9086bea0
maint: Run 'make update-copyright'
author | Paul Eggert <eggert@cs.ucla.edu> |
---|---|
date | Mon, 01 Jan 2018 00:57:25 +0000 |
parents | d86e08b1f555 |
children | 1fa2f90267d3 |
rev | line source |
---|---|
5858 | 1 /* Traverse a file hierarchy. |
2 | |
19484
10eb9086bea0
maint: Run 'make update-copyright'
Paul Eggert <eggert@cs.ucla.edu>
parents:
19192
diff
changeset
|
3 Copyright (C) 2004-2018 Free Software Foundation, Inc. |
5858 | 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 | 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 | 9 |
10 This program is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 GNU General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU General Public License | |
19190 | 16 along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
5858 | 17 |
18 /*- | |
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 | 21 * |
22 * Redistribution and use in source and binary forms, with or without | |
23 * modification, are permitted provided that the following conditions | |
24 * are met: | |
25 * 1. Redistributions of source code must retain the above copyright | |
26 * notice, this list of conditions and the following disclaimer. | |
27 * 2. Redistributions in binary form must reproduce the above copyright | |
28 * notice, this list of conditions and the following disclaimer in the | |
29 * documentation and/or other materials provided with the distribution. | |
30 * 4. Neither the name of the University nor the names of its contributors | |
31 * may be used to endorse or promote products derived from this software | |
32 * without specific prior written permission. | |
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 | 35 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
36 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
37 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
38 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
39 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
40 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
41 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
42 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
43 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
44 * SUCH DAMAGE. | |
45 */ | |
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 | 48 |
18325 | 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 | 51 #endif |
5858 | 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 | 55 #if HAVE_SYS_PARAM_H || defined _LIBC |
56 # include <sys/param.h> | |
57 #endif | |
58 #ifdef _LIBC | |
59 # include <include/sys/stat.h> | |
60 #else | |
61 # include <sys/stat.h> | |
62 #endif | |
63 #include <fcntl.h> | |
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 | 68 #include <stdlib.h> |
69 #include <string.h> | |
70 #include <unistd.h> | |
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 | 73 # include "fcntl--.h" |
18403
4434607ac1ce
flexmember: port better to GCC + valgrind
Paul Eggert <eggert@cs.ucla.edu>
parents:
18338
diff
changeset
|
74 # include "flexmember.h" |
11946 | 75 # 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
|
76 # 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
|
77 #endif |
96149b1bbb32
(fts_cross_check) [FTS_DEBUG]: s/active_dir_ht/fts_cycle.ht/.
Jim Meyering <jim@meyering.net>
parents:
5907
diff
changeset
|
78 |
6949
96af1224c6fa
* backupfile.c, dirfd.h, fts.c, getcwd.c, glob.c, glob_.h:
Paul Eggert <eggert@cs.ucla.edu>
parents:
6934
diff
changeset
|
79 #include <dirent.h> |
17642
8af917141d49
fts: avoid unnecessary strlen calls
Eric Blake <eblake@redhat.com>
parents:
17641
diff
changeset
|
80 #ifndef _D_EXACT_NAMLEN |
8af917141d49
fts: avoid unnecessary strlen calls
Eric Blake <eblake@redhat.com>
parents:
17641
diff
changeset
|
81 # define _D_EXACT_NAMLEN(dirent) strlen ((dirent)->d_name) |
8af917141d49
fts: avoid unnecessary strlen calls
Eric Blake <eblake@redhat.com>
parents:
17641
diff
changeset
|
82 #endif |
5858 | 83 |
7482
26914593f079
Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents:
7408
diff
changeset
|
84 #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
|
85 /* 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
|
86 # 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
|
87 /* 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
|
88 # 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
|
89 # 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
|
90 #else |
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) false |
26914593f079
Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents:
7408
diff
changeset
|
92 # 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
|
93 # 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
|
94 |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
95 # undef DT_UNKNOWN |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
96 # 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
|
97 |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
98 /* 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
|
99 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
|
100 # undef DT_BLK |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
101 # undef DT_CHR |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
102 # undef DT_DIR |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
103 # undef DT_FIFO |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
104 # undef DT_LNK |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
105 # undef DT_REG |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
106 # undef DT_SOCK |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
107 # 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
|
108 # 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
|
109 # 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
|
110 # 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
|
111 # 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
|
112 # 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
|
113 # 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
|
114 #endif |
26914593f079
Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents:
7408
diff
changeset
|
115 |
10863
054d026819f0
work around mingw's lack of some S_IF definitions
Jim Meyering <meyering@redhat.com>
parents:
10844
diff
changeset
|
116 #ifndef S_IFLNK |
054d026819f0
work around mingw's lack of some S_IF definitions
Jim Meyering <meyering@redhat.com>
parents:
10844
diff
changeset
|
117 # define S_IFLNK 0 |
054d026819f0
work around mingw's lack of some S_IF definitions
Jim Meyering <meyering@redhat.com>
parents:
10844
diff
changeset
|
118 #endif |
054d026819f0
work around mingw's lack of some S_IF definitions
Jim Meyering <meyering@redhat.com>
parents:
10844
diff
changeset
|
119 #ifndef S_IFSOCK |
054d026819f0
work around mingw's lack of some S_IF definitions
Jim Meyering <meyering@redhat.com>
parents:
10844
diff
changeset
|
120 # define S_IFSOCK 0 |
054d026819f0
work around mingw's lack of some S_IF definitions
Jim Meyering <meyering@redhat.com>
parents:
10844
diff
changeset
|
121 #endif |
054d026819f0
work around mingw's lack of some S_IF definitions
Jim Meyering <meyering@redhat.com>
parents:
10844
diff
changeset
|
122 |
10481
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
123 enum |
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
124 { |
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
125 NOT_AN_INODE_NUMBER = 0 |
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
126 }; |
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
127 |
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
128 #ifdef D_INO_IN_DIRENT |
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
129 # 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
|
130 #else |
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
131 /* 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
|
132 # 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
|
133 #endif |
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
134 |
15531
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
135 /* 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
|
136 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
|
137 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
|
138 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
|
139 #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
|
140 # 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
|
141 #endif |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
142 |
10481
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
143 /* 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
|
144 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
|
145 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
|
146 #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
|
147 # 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
|
148 #endif |
15531
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
149 |
10481
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
150 enum |
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
151 { |
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
152 _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
|
153 }; |
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
154 |
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
|
155 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
|
156 { |
26914593f079
Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents:
7408
diff
changeset
|
157 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
|
158 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
|
159 }; |
26914593f079
Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents:
7408
diff
changeset
|
160 |
5858 | 161 #ifdef _LIBC |
162 # undef close | |
163 # define close __close | |
164 # undef closedir | |
165 # define closedir __closedir | |
166 # undef fchdir | |
167 # define fchdir __fchdir | |
168 # undef open | |
169 # define open __open | |
170 # undef readdir | |
171 # define readdir __readdir | |
172 #else | |
173 # undef internal_function | |
174 # define internal_function /* empty */ | |
175 #endif | |
176 | |
177 #ifndef __set_errno | |
178 # define __set_errno(Val) errno = (Val) | |
179 #endif | |
180 | |
7151 | 181 /* If this host provides the openat function, then we can avoid |
182 attempting to open "." in some initialization code below. */ | |
183 #ifdef HAVE_OPENAT | |
184 # define HAVE_OPENAT_SUPPORT 1 | |
185 #else | |
186 # define HAVE_OPENAT_SUPPORT 0 | |
187 #endif | |
5858 | 188 |
7785
3246679850d5
Slight readability improvement: use an assert-like macro
Jim Meyering <jim@meyering.net>
parents:
7707
diff
changeset
|
189 #ifdef NDEBUG |
17840 | 190 # 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
|
191 #else |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
192 # define fts_assert(expr) \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
193 do \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
194 { \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
195 if (!(expr)) \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
196 abort (); \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
197 } \ |
7785
3246679850d5
Slight readability improvement: use an assert-like macro
Jim Meyering <jim@meyering.net>
parents:
7707
diff
changeset
|
198 while (false) |
3246679850d5
Slight readability improvement: use an assert-like macro
Jim Meyering <jim@meyering.net>
parents:
7707
diff
changeset
|
199 #endif |
3246679850d5
Slight readability improvement: use an assert-like macro
Jim Meyering <jim@meyering.net>
parents:
7707
diff
changeset
|
200 |
18930
50d1e186bf78
fallthrough: update for GCC 7/8
Jim Meyering <meyering@fb.com>
parents:
18626
diff
changeset
|
201 #ifndef FALLTHROUGH |
50d1e186bf78
fallthrough: update for GCC 7/8
Jim Meyering <meyering@fb.com>
parents:
18626
diff
changeset
|
202 # if __GNUC__ < 7 |
50d1e186bf78
fallthrough: update for GCC 7/8
Jim Meyering <meyering@fb.com>
parents:
18626
diff
changeset
|
203 # define FALLTHROUGH ((void) 0) |
50d1e186bf78
fallthrough: update for GCC 7/8
Jim Meyering <meyering@fb.com>
parents:
18626
diff
changeset
|
204 # else |
50d1e186bf78
fallthrough: update for GCC 7/8
Jim Meyering <meyering@fb.com>
parents:
18626
diff
changeset
|
205 # define FALLTHROUGH __attribute__ ((__fallthrough__)) |
50d1e186bf78
fallthrough: update for GCC 7/8
Jim Meyering <meyering@fb.com>
parents:
18626
diff
changeset
|
206 # endif |
50d1e186bf78
fallthrough: update for GCC 7/8
Jim Meyering <meyering@fb.com>
parents:
18626
diff
changeset
|
207 #endif |
50d1e186bf78
fallthrough: update for GCC 7/8
Jim Meyering <meyering@fb.com>
parents:
18626
diff
changeset
|
208 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
209 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
|
210 static FTSENT *fts_build (FTS *, int) internal_function; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
211 static void fts_lfree (FTSENT *) internal_function; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
212 static void fts_load (FTS *, FTSENT *) internal_function; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
213 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
|
214 static void fts_padjust (FTS *, FTSENT *) internal_function; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
215 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
|
216 static FTSENT *fts_sort (FTS *, FTSENT *, size_t) internal_function; |
5858 | 217 static unsigned short int fts_stat (FTS *, FTSENT *, bool) internal_function; |
218 static int fts_safe_changedir (FTS *, FTSENT *, int, const char *) | |
219 internal_function; | |
220 | |
13091
3af48780d248
Remove vestiges of fts-lgpl module.
Bruno Haible <bruno@clisp.org>
parents:
12772
diff
changeset
|
221 #include "fts-cycle.c" |
5872 | 222 |
5858 | 223 #ifndef MAX |
224 # define MAX(a,b) ((a) > (b) ? (a) : (b)) | |
225 #endif | |
226 | |
227 #ifndef SIZE_MAX | |
228 # define SIZE_MAX ((size_t) -1) | |
229 #endif | |
230 | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
231 #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
|
232 #define STREQ(a, b) (strcmp (a, b) == 0) |
5858 | 233 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
234 #define CLR(opt) (sp->fts_options &= ~(opt)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
235 #define ISSET(opt) (sp->fts_options & (opt)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
236 #define SET(opt) (sp->fts_options |= (opt)) |
5858 | 237 |
7639
1670d42131d7
Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents:
7635
diff
changeset
|
238 /* 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
|
239 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
|
240 #define FCHDIR(sp, fd) \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
241 (!ISSET(FTS_NOCHDIR) && (ISSET(FTS_CWDFD) \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
242 ? (cwd_advance_fd ((sp), (fd), true), 0) \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
243 : fchdir (fd))) |
7151 | 244 |
5858 | 245 |
246 /* 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
|
247 /* FIXME: make this an enum */ |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
248 #define BCHILD 1 /* fts_children */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
249 #define BNAMES 2 /* fts_children, names only */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
250 #define BREAD 3 /* fts_read */ |
5858 | 251 |
252 #if FTS_DEBUG | |
5894
d09af5fbd9f2
* modules/fts (Files): Remove m4/inttypes-pri.m4.
Paul Eggert <eggert@cs.ucla.edu>
parents:
5877
diff
changeset
|
253 # include <inttypes.h> |
d09af5fbd9f2
* modules/fts (Files): Remove m4/inttypes-pri.m4.
Paul Eggert <eggert@cs.ucla.edu>
parents:
5877
diff
changeset
|
254 # include <stdint.h> |
d09af5fbd9f2
* modules/fts (Files): Remove m4/inttypes-pri.m4.
Paul Eggert <eggert@cs.ucla.edu>
parents:
5877
diff
changeset
|
255 # 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
|
256 # include "getcwdat.h" |
5858 | 257 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
|
258 # define Dprintf(x) do { if (fts_debug) printf x; } while (false) |
5858 | 259 #else |
260 # 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
|
261 # 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
|
262 # define fd_ring_print(a, b, c) |
5858 | 263 #endif |
264 | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
265 #define LEAVE_DIR(Fts, Ent, Tag) \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
266 do \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
267 { \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
268 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
|
269 leave_dir (Fts, Ent); \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
270 fd_ring_check (Fts); \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
271 } \ |
5872 | 272 while (false) |
5858 | 273 |
7639
1670d42131d7
Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents:
7635
diff
changeset
|
274 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
|
275 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
|
276 { |
1670d42131d7
Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents:
7635
diff
changeset
|
277 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
|
278 { |
1670d42131d7
Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents:
7635
diff
changeset
|
279 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
|
280 if (0 <= fd) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
281 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
|
282 } |
1670d42131d7
Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents:
7635
diff
changeset
|
283 } |
1670d42131d7
Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents:
7635
diff
changeset
|
284 |
7482
26914593f079
Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents:
7408
diff
changeset
|
285 /* 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
|
286 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
|
287 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
|
288 static void |
26914593f079
Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents:
7408
diff
changeset
|
289 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
|
290 { |
7785
3246679850d5
Slight readability improvement: use an assert-like macro
Jim Meyering <jim@meyering.net>
parents:
7707
diff
changeset
|
291 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
|
292 p->fts_statp->st_size = (required |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
293 ? FTS_STAT_REQUIRED |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
294 : 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
|
295 } |
26914593f079
Big performance improvement for fts-based tools that use FTS_NOSTAT.
Jim Meyering <jim@meyering.net>
parents:
7408
diff
changeset
|
296 |
7151 | 297 /* file-descriptor-relative opendir. */ |
298 /* 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
|
299 static DIR * |
7151 | 300 internal_function |
13676
223800d7ac7d
fts, getcwd, glob: audit for dirfd returning -1
Paul Eggert <eggert@cs.ucla.edu>
parents:
13674
diff
changeset
|
301 opendirat (int fd, char const *dir, int extra_flags, int *pdir_fd) |
7151 | 302 { |
19047 | 303 int open_flags = (O_RDONLY | O_CLOEXEC | O_DIRECTORY | O_NOCTTY |
304 | O_NONBLOCK | extra_flags); | |
305 int new_fd = openat (fd, dir, open_flags); | |
7151 | 306 DIR *dirp; |
307 | |
308 if (new_fd < 0) | |
309 return NULL; | |
310 dirp = fdopendir (new_fd); | |
13676
223800d7ac7d
fts, getcwd, glob: audit for dirfd returning -1
Paul Eggert <eggert@cs.ucla.edu>
parents:
13674
diff
changeset
|
311 if (dirp) |
223800d7ac7d
fts, getcwd, glob: audit for dirfd returning -1
Paul Eggert <eggert@cs.ucla.edu>
parents:
13674
diff
changeset
|
312 *pdir_fd = new_fd; |
223800d7ac7d
fts, getcwd, glob: audit for dirfd returning -1
Paul Eggert <eggert@cs.ucla.edu>
parents:
13674
diff
changeset
|
313 else |
7151 | 314 { |
315 int saved_errno = errno; | |
316 close (new_fd); | |
317 errno = saved_errno; | |
318 } | |
319 return dirp; | |
320 } | |
321 | |
7639
1670d42131d7
Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents:
7635
diff
changeset
|
322 /* 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
|
323 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
|
324 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
|
325 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
|
326 down. */ |
7151 | 327 static void |
328 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
|
329 cwd_advance_fd (FTS *sp, int fd, bool chdir_down_one) |
7151 | 330 { |
331 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
|
332 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
|
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 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
|
335 { |
1670d42131d7
Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents:
7635
diff
changeset
|
336 /* Push "old" onto the ring. |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
337 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
|
338 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
|
339 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
|
340 if (0 <= prev_fd_in_slot) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
341 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
|
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 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
|
344 { |
1670d42131d7
Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents:
7635
diff
changeset
|
345 if (0 <= old) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
346 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
|
347 } |
1670d42131d7
Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents:
7635
diff
changeset
|
348 |
7151 | 349 sp->fts_cwd_fd = fd; |
350 } | |
351 | |
15988
cd7ac59d8eb5
fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents:
15531
diff
changeset
|
352 /* 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
|
353 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
|
354 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
|
355 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
|
356 static int |
cd7ac59d8eb5
fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents:
15531
diff
changeset
|
357 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
|
358 { |
cd7ac59d8eb5
fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents:
15531
diff
changeset
|
359 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
|
360 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
|
361 return fail; |
cd7ac59d8eb5
fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents:
15531
diff
changeset
|
362 } |
cd7ac59d8eb5
fts: close parent dir FD before returning from post-traversal fts_read
Jim Meyering <meyering@redhat.com>
parents:
15531
diff
changeset
|
363 |
5858 | 364 /* Open the directory DIR if possible, and return a file |
365 descriptor. Return -1 and set errno on failure. It doesn't matter | |
366 whether the file descriptor has read or write access. */ | |
367 | |
17188
d7a44f0f7a15
ftruncate, fts, lstat, openat, raise: no 'static inline'
Paul Eggert <eggert@cs.ucla.edu>
parents:
17160
diff
changeset
|
368 static int |
5858 | 369 internal_function |
7151 | 370 diropen (FTS const *sp, char const *dir) |
5858 | 371 { |
19047 | 372 int open_flags = (O_SEARCH | O_CLOEXEC | O_DIRECTORY | O_NOCTTY | O_NONBLOCK |
15374
04a9f678e342
fts: introduce FTS_NOATIME
Eric Blake <eblake@redhat.com>
parents:
14774
diff
changeset
|
373 | (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0) |
04a9f678e342
fts: introduce FTS_NOATIME
Eric Blake <eblake@redhat.com>
parents:
14774
diff
changeset
|
374 | (ISSET (FTS_NOATIME) ? O_NOATIME : 0)); |
7151 | 375 |
11940 | 376 int fd = (ISSET (FTS_CWDFD) |
377 ? openat (sp->fts_cwd_fd, dir, open_flags) | |
378 : open (dir, open_flags)); | |
379 return fd; | |
5858 | 380 } |
381 | |
382 FTS * | |
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 | 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 | 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 | 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 | 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 | 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 | 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 | 460 #ifndef MAXPATHLEN |
461 # define MAXPATHLEN 1024 | |
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 | 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; |
19008
a6fc0157c611
fts: nlink_t signedness fixups
Paul Eggert <eggert@cs.ucla.edu>
parents:
18930
diff
changeset
|
474 parent->fts_n_dirs_remaining = -1; |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
475 } |
5858 | 476 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
477 /* 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
|
478 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
|
479 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
|
480 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
|
481 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
|
482 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
|
483 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
|
484 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
|
485 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
|
486 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
|
487 data via the fts_statp pointer. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
488 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
|
489 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
490 /* Allocate/initialize root(s). */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
491 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
|
492 /* *Do* allow zero-length file names. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
493 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
|
494 |
17160
72f4bab621be
fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents:
17074
diff
changeset
|
495 if ( ! (options & FTS_VERBATIM)) |
72f4bab621be
fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents:
17074
diff
changeset
|
496 { |
72f4bab621be
fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents:
17074
diff
changeset
|
497 /* 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
|
498 but don't change "//" to "/", and do map "///" to "/". */ |
72f4bab621be
fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents:
17074
diff
changeset
|
499 char const *v = *argv; |
72f4bab621be
fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents:
17074
diff
changeset
|
500 if (2 < len && v[len - 1] == '/') |
72f4bab621be
fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents:
17074
diff
changeset
|
501 while (1 < len && v[len - 2] == '/') |
72f4bab621be
fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents:
17074
diff
changeset
|
502 --len; |
72f4bab621be
fts: introduce FTS_VERBATIM
Dmitry V. Levin <ldv@altlinux.org>
parents:
17074
diff
changeset
|
503 } |
17074
d4ccb0388f18
fts: reduce two or more trailing slashes to just one, usually
Jim Meyering <meyering@redhat.com>
parents:
17073
diff
changeset
|
504 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
505 if ((p = fts_alloc(sp, *argv, len)) == NULL) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
506 goto mem3; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
507 p->fts_level = FTS_ROOTLEVEL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
508 p->fts_parent = parent; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
509 p->fts_accpath = p->fts_name; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
510 /* 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
|
511 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
|
512 FTS_XDEV) requires that. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
513 if (defer_stat && root != NULL) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
514 p->fts_info = FTS_NSOK; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
515 fts_set_stat_required(p, true); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
516 } else { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
517 p->fts_info = fts_stat(sp, p, false); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
518 } |
5858 | 519 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
520 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
521 * If comparison routine supplied, traverse in sorted |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
522 * order; otherwise traverse in the order specified. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
523 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
524 if (compar) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
525 p->fts_link = root; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
526 root = p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
527 } else { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
528 p->fts_link = NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
529 if (root == NULL) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
530 tmp = root = p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
531 else { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
532 tmp->fts_link = p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
533 tmp = p; |
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 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
537 if (compar && nitems > 1) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
538 root = fts_sort(sp, root, nitems); |
5858 | 539 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
540 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
541 * 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
|
542 * 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
|
543 * 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
|
544 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
545 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
|
546 goto mem3; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
547 sp->fts_cur->fts_link = root; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
548 sp->fts_cur->fts_info = FTS_INIT; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
549 if (! setup_dir (sp)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
550 goto mem3; |
5858 | 551 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
552 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
553 * 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
|
554 * 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
|
555 * 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
|
556 * 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
|
557 * descriptor we run anyway, just more slowly. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
558 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
559 if (!ISSET(FTS_NOCHDIR) && !ISSET(FTS_CWDFD) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
560 && (sp->fts_rfd = diropen (sp, ".")) < 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
561 SET(FTS_NOCHDIR); |
5858 | 562 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
563 i_ring_init (&sp->fts_fd_ring, -1); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
564 return (sp); |
5858 | 565 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
566 mem3: fts_lfree(root); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
567 free(parent); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
568 mem2: free(sp->fts_path); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
569 mem1: free(sp); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
570 return (NULL); |
5858 | 571 } |
572 | |
573 static void | |
574 internal_function | |
575 fts_load (FTS *sp, register FTSENT *p) | |
576 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
577 register size_t len; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
578 register char *cp; |
5858 | 579 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
580 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
581 * 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
|
582 * 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
|
583 * 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
|
584 * 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
|
585 * known that the file name will fit. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
586 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
587 len = p->fts_pathlen = p->fts_namelen; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
588 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
|
589 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
|
590 len = strlen(++cp); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
591 memmove(p->fts_name, cp, len + 1); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
592 p->fts_namelen = len; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
593 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
594 p->fts_accpath = p->fts_path = sp->fts_path; |
5858 | 595 } |
596 | |
597 int | |
598 fts_close (FTS *sp) | |
599 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
600 register FTSENT *freep, *p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
601 int saved_errno = 0; |
5858 | 602 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
603 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
604 * 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
|
605 * 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
|
606 * list which has a valid parent pointer. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
607 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
608 if (sp->fts_cur) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
609 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
|
610 freep = p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
611 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
|
612 free(freep); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
613 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
614 free(p); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
615 } |
5858 | 616 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
617 /* 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
|
618 if (sp->fts_child) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
619 fts_lfree(sp->fts_child); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
620 free(sp->fts_array); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
621 free(sp->fts_path); |
5858 | 622 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
623 if (ISSET(FTS_CWDFD)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
624 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
625 if (0 <= sp->fts_cwd_fd) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
626 if (close (sp->fts_cwd_fd)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
627 saved_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
628 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
629 else if (!ISSET(FTS_NOCHDIR)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
630 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
631 /* Return to original directory, save errno if necessary. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
632 if (fchdir(sp->fts_rfd)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
633 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
|
634 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
635 /* 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
|
636 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
|
637 if (close (sp->fts_rfd)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
638 if (saved_errno == 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
639 saved_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
640 } |
5858 | 641 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
642 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
|
643 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
644 if (sp->fts_leaf_optimization_works_ht) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
645 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
|
646 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
647 free_dir (sp); |
5858 | 648 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
649 /* Free up the stream pointer. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
650 free(sp); |
5858 | 651 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
652 /* Set errno and return. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
653 if (saved_errno) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
654 __set_errno (saved_errno); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
655 return (-1); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
656 } |
5858 | 657 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
658 return (0); |
5858 | 659 } |
660 | |
19009
7201d8037bb3
fts: introduce MIN_DIR_NLINK
Paul Eggert <eggert@cs.ucla.edu>
parents:
19008
diff
changeset
|
661 /* Minimum link count of a traditional Unix directory. When leaf |
7201d8037bb3
fts: introduce MIN_DIR_NLINK
Paul Eggert <eggert@cs.ucla.edu>
parents:
19008
diff
changeset
|
662 optimization is OK and MIN_DIR_NLINK <= st_nlink, then st_nlink is |
7201d8037bb3
fts: introduce MIN_DIR_NLINK
Paul Eggert <eggert@cs.ucla.edu>
parents:
19008
diff
changeset
|
663 an upper bound on the number of subdirectories (counting "." and |
7201d8037bb3
fts: introduce MIN_DIR_NLINK
Paul Eggert <eggert@cs.ucla.edu>
parents:
19008
diff
changeset
|
664 ".."). */ |
7201d8037bb3
fts: introduce MIN_DIR_NLINK
Paul Eggert <eggert@cs.ucla.edu>
parents:
19008
diff
changeset
|
665 enum { MIN_DIR_NLINK = 2 }; |
7201d8037bb3
fts: introduce MIN_DIR_NLINK
Paul Eggert <eggert@cs.ucla.edu>
parents:
19008
diff
changeset
|
666 |
19011
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
667 /* Whether leaf optimization is OK for a directory. */ |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
668 enum leaf_optimization |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
669 { |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
670 /* st_nlink is not reliable for this directory's subdirectories. */ |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
671 NO_LEAF_OPTIMIZATION, |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
672 |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
673 /* Leaf optimization is OK, but is not useful for avoiding stat calls. */ |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
674 OK_LEAF_OPTIMIZATION, |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
675 |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
676 /* Leaf optimization is not only OK: it is useful for avoiding |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
677 stat calls, because dirent.d_type does not work. */ |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
678 NOSTAT_LEAF_OPTIMIZATION |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
679 }; |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
680 |
11163
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
681 #if defined __linux__ \ |
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
682 && 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
|
683 |
14379
2330aac2ae54
maint: adjust cpp indentation to reflect nesting depth
Jim Meyering <meyering@redhat.com>
parents:
14079
diff
changeset
|
684 # include <sys/vfs.h> |
11163
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 /* Linux-specific constants from coreutils' src/fs.h */ |
19011
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
687 # define S_MAGIC_AFS 0x5346414F |
11163
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
688 # define S_MAGIC_NFS 0x6969 |
19011
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
689 # define S_MAGIC_PROC 0x9FA0 |
11164
90715da41753
fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents:
11163
diff
changeset
|
690 # define S_MAGIC_REISERFS 0x52654973 |
19011
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
691 # define S_MAGIC_TMPFS 0x1021994 |
18179
4b6df746d1f3
fts: enable leaf optimization for XFS
Pádraig Brady <P@draigBrady.com>
parents:
18137
diff
changeset
|
692 # define S_MAGIC_XFS 0x58465342 |
11163
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
693 |
19045
bf63563adfd2
fts: port recent changes to CentOS 6
Paul Eggert <eggert@cs.ucla.edu>
parents:
19027
diff
changeset
|
694 # ifdef HAVE___FSWORD_T |
bf63563adfd2
fts: port recent changes to CentOS 6
Paul Eggert <eggert@cs.ucla.edu>
parents:
19027
diff
changeset
|
695 typedef __fsword_t fsword; |
bf63563adfd2
fts: port recent changes to CentOS 6
Paul Eggert <eggert@cs.ucla.edu>
parents:
19027
diff
changeset
|
696 # else |
bf63563adfd2
fts: port recent changes to CentOS 6
Paul Eggert <eggert@cs.ucla.edu>
parents:
19027
diff
changeset
|
697 typedef long int fsword; |
bf63563adfd2
fts: port recent changes to CentOS 6
Paul Eggert <eggert@cs.ucla.edu>
parents:
19027
diff
changeset
|
698 # endif |
bf63563adfd2
fts: port recent changes to CentOS 6
Paul Eggert <eggert@cs.ucla.edu>
parents:
19027
diff
changeset
|
699 |
19010
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
700 /* Map a stat.st_dev number to a file system type number f_ftype. */ |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
701 struct dev_type |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
702 { |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
703 dev_t st_dev; |
19045
bf63563adfd2
fts: port recent changes to CentOS 6
Paul Eggert <eggert@cs.ucla.edu>
parents:
19027
diff
changeset
|
704 fsword f_type; |
19010
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
705 }; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
706 |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
707 /* Use a tiny initial size. If a traversal encounters more than |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
708 a few devices, the cost of growing/rehashing this table will be |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
709 rendered negligible by the number of inodes processed. */ |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
710 enum { DEV_TYPE_HT_INITIAL_SIZE = 13 }; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
711 |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
712 static size_t |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
713 dev_type_hash (void const *x, size_t table_size) |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
714 { |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
715 struct dev_type const *ax = x; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
716 uintmax_t dev = ax->st_dev; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
717 return dev % table_size; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
718 } |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
719 |
11163
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
720 static bool |
19010
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
721 dev_type_compare (void const *x, void const *y) |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
722 { |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
723 struct dev_type const *ax = x; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
724 struct dev_type const *ay = y; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
725 return ax->st_dev == ay->st_dev; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
726 } |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
727 |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
728 /* Return the file system type of P, or 0 if not known. |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
729 Try to cache known values. */ |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
730 |
19045
bf63563adfd2
fts: port recent changes to CentOS 6
Paul Eggert <eggert@cs.ucla.edu>
parents:
19027
diff
changeset
|
731 static fsword |
19010
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
732 filesystem_type (FTSENT const *p) |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
733 { |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
734 FTS *sp = p->fts_fts; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
735 Hash_table *h = sp->fts_leaf_optimization_works_ht; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
736 struct dev_type *ent; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
737 struct statfs fs_buf; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
738 |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
739 /* If we're not in CWDFD mode, don't bother with this optimization, |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
740 since the caller is not serious about performance. */ |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
741 if (!ISSET (FTS_CWDFD)) |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
742 return 0; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
743 |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
744 if (! h) |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
745 h = sp->fts_leaf_optimization_works_ht |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
746 = hash_initialize (DEV_TYPE_HT_INITIAL_SIZE, NULL, dev_type_hash, |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
747 dev_type_compare, free); |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
748 if (h) |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
749 { |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
750 struct dev_type tmp; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
751 tmp.st_dev = p->fts_statp->st_dev; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
752 ent = hash_lookup (h, &tmp); |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
753 if (ent) |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
754 return ent->f_type; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
755 } |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
756 |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
757 /* Look-up failed. Query directly and cache the result. */ |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
758 if (fstatfs (p->fts_fts->fts_cwd_fd, &fs_buf) != 0) |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
759 return 0; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
760 |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
761 if (h) |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
762 { |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
763 struct dev_type *t2 = malloc (sizeof *t2); |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
764 if (t2) |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
765 { |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
766 t2->st_dev = p->fts_statp->st_dev; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
767 t2->f_type = fs_buf.f_type; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
768 |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
769 ent = hash_insert (h, t2); |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
770 if (ent) |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
771 fts_assert (ent == t2); |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
772 else |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
773 free (t2); |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
774 } |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
775 } |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
776 |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
777 return fs_buf.f_type; |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
778 } |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
779 |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
780 /* Return false if it is easy to determine the file system type of the |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
781 directory P, and sorting dirents on inode numbers is known not to |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
782 improve traversal performance with that type of file system. |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
783 Otherwise, return true. */ |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
784 static bool |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
785 dirent_inode_sort_may_be_useful (FTSENT const *p) |
11163
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
786 { |
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
787 /* 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
|
788 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
|
789 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
|
790 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
|
791 a very large constant. */ |
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
792 |
19010
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
793 switch (filesystem_type (p)) |
11163
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
794 { |
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
795 case S_MAGIC_TMPFS: |
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
796 case S_MAGIC_NFS: |
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
797 /* 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
|
798 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
|
799 return false; |
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
800 |
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
801 default: |
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
802 return true; |
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
803 } |
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
804 } |
11164
90715da41753
fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents:
11163
diff
changeset
|
805 |
19010
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
806 /* Given an FTS entry P for a directory D, |
19009
7201d8037bb3
fts: introduce MIN_DIR_NLINK
Paul Eggert <eggert@cs.ucla.edu>
parents:
19008
diff
changeset
|
807 return true if it is both useful and valid to apply leaf optimization. |
7201d8037bb3
fts: introduce MIN_DIR_NLINK
Paul Eggert <eggert@cs.ucla.edu>
parents:
19008
diff
changeset
|
808 The optimization is useful only for file systems that lack usable |
7201d8037bb3
fts: introduce MIN_DIR_NLINK
Paul Eggert <eggert@cs.ucla.edu>
parents:
19008
diff
changeset
|
809 dirent.d_type info. The optimization is valid if an st_nlink value |
7201d8037bb3
fts: introduce MIN_DIR_NLINK
Paul Eggert <eggert@cs.ucla.edu>
parents:
19008
diff
changeset
|
810 of at least MIN_DIR_NLINK is an upper bound on the number of |
7201d8037bb3
fts: introduce MIN_DIR_NLINK
Paul Eggert <eggert@cs.ucla.edu>
parents:
19008
diff
changeset
|
811 subdirectories of D, counting "." and ".." as subdirectories. */ |
19011
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
812 static enum leaf_optimization |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
813 leaf_optimization (FTSENT const *p) |
11164
90715da41753
fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents:
11163
diff
changeset
|
814 { |
19010
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
815 switch (filesystem_type (p)) |
11164
90715da41753
fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents:
11163
diff
changeset
|
816 { |
19136
504d2bd44d07
* lib/fts.c: Fix XFS comments.
Paul Eggert <eggert@cs.ucla.edu>
parents:
19047
diff
changeset
|
817 /* List here the file system types that may lack usable dirent.d_type |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
818 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
|
819 case S_MAGIC_REISERFS: |
19136
504d2bd44d07
* lib/fts.c: Fix XFS comments.
Paul Eggert <eggert@cs.ucla.edu>
parents:
19047
diff
changeset
|
820 case S_MAGIC_XFS: /* XFS lacked it until 2013-08-22 commit. */ |
19011
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
821 return NOSTAT_LEAF_OPTIMIZATION; |
11164
90715da41753
fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents:
11163
diff
changeset
|
822 |
19011
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
823 case 0: |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
824 /* Leaf optimization is unsafe if the file system type is unknown. */ |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
825 FALLTHROUGH; |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
826 case S_MAGIC_AFS: |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
827 /* Although AFS mount points are not counted in st_nlink, they |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
828 act like directories. See <https://bugs.debian.org/143111>. */ |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
829 FALLTHROUGH; |
18216
973834698be5
fts: don't unconditionally use leaf optimization for NFS
Pádraig Brady <P@draigBrady.com>
parents:
18189
diff
changeset
|
830 case S_MAGIC_NFS: |
973834698be5
fts: don't unconditionally use leaf optimization for NFS
Pádraig Brady <P@draigBrady.com>
parents:
18189
diff
changeset
|
831 /* 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
|
832 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
|
833 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
|
834 all implementations as per <https://bugzilla.redhat.com/1299169>. */ |
18930
50d1e186bf78
fallthrough: update for GCC 7/8
Jim Meyering <meyering@fb.com>
parents:
18626
diff
changeset
|
835 FALLTHROUGH; |
11164
90715da41753
fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents:
11163
diff
changeset
|
836 case S_MAGIC_PROC: |
19192
d86e08b1f555
all: Replace many more http URLs by https URLs. Update stale URLs.
Bruno Haible <bruno@clisp.org>
parents:
19190
diff
changeset
|
837 /* Per <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=143111> /proc |
d86e08b1f555
all: Replace many more http URLs by https URLs. Update stale URLs.
Bruno Haible <bruno@clisp.org>
parents:
19190
diff
changeset
|
838 may have bogus stat.st_nlink values. */ |
19011
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
839 return NO_LEAF_OPTIMIZATION; |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
840 |
11164
90715da41753
fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents:
11163
diff
changeset
|
841 default: |
19011
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
842 return OK_LEAF_OPTIMIZATION; |
11164
90715da41753
fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents:
11163
diff
changeset
|
843 } |
90715da41753
fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents:
11163
diff
changeset
|
844 } |
90715da41753
fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents:
11163
diff
changeset
|
845 |
11163
f448fc8fe832
fts: move a function definition "up" (no semantic change)
Jim Meyering <meyering@redhat.com>
parents:
11162
diff
changeset
|
846 #else |
12050 | 847 static bool |
19010
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
848 dirent_inode_sort_may_be_useful (FTSENT const *p _GL_UNUSED) |
11164
90715da41753
fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents:
11163
diff
changeset
|
849 { |
19010
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
850 return true; |
11164
90715da41753
fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents:
11163
diff
changeset
|
851 } |
19011
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
852 static enum leaf_optimization |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
853 leaf_optimization (FTSENT const *p _GL_UNUSED) |
19010
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
854 { |
19011
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
855 return NO_LEAF_OPTIMIZATION; |
19010
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
856 } |
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
857 #endif |
11164
90715da41753
fts: arrange not to stat non-directories in more cases
Jim Meyering <meyering@redhat.com>
parents:
11163
diff
changeset
|
858 |
5858 | 859 /* |
5907 | 860 * Special case of "/" at the end of the file name so that slashes aren't |
861 * appended which would cause file names to be written as "....//foo". | |
5858 | 862 */ |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
863 #define NAPPEND(p) \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
864 (p->fts_path[p->fts_pathlen - 1] == '/' \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
865 ? p->fts_pathlen - 1 : p->fts_pathlen) |
5858 | 866 |
867 FTSENT * | |
868 fts_read (register FTS *sp) | |
869 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
870 register FTSENT *p, *tmp; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
871 register unsigned short int instr; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
872 register char *t; |
5858 | 873 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
874 /* If finished or unrecoverable error, return NULL. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
875 if (sp->fts_cur == NULL || ISSET(FTS_STOP)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
876 return (NULL); |
5858 | 877 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
878 /* Set current node pointer. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
879 p = sp->fts_cur; |
5858 | 880 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
881 /* Save and zero out user instructions. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
882 instr = p->fts_instr; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
883 p->fts_instr = FTS_NOINSTR; |
5858 | 884 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
885 /* 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
|
886 if (instr == FTS_AGAIN) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
887 p->fts_info = fts_stat(sp, p, false); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
888 return (p); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
889 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
890 Dprintf (("fts_read: p=%s\n", |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
891 p->fts_info == FTS_INIT ? "" : p->fts_path)); |
5858 | 892 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
893 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
894 * 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
|
895 * 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
|
896 * 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
|
897 * pointer, follow fails. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
898 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
899 if (instr == FTS_FOLLOW && |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
900 (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
|
901 p->fts_info = fts_stat(sp, p, true); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
902 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
|
903 if ((p->fts_symfd = diropen (sp, ".")) < 0) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
904 p->fts_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
905 p->fts_info = FTS_ERR; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
906 } else |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
907 p->fts_flags |= FTS_SYMFOLLOW; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
908 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
909 goto check_for_dir; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
910 } |
5858 | 911 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
912 /* Directory in pre-order. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
913 if (p->fts_info == FTS_D) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
914 /* 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
|
915 if (instr == FTS_SKIP || |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
916 (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
|
917 if (p->fts_flags & FTS_SYMFOLLOW) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
918 (void)close(p->fts_symfd); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
919 if (sp->fts_child) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
920 fts_lfree(sp->fts_child); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
921 sp->fts_child = NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
922 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
923 p->fts_info = FTS_DP; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
924 LEAVE_DIR (sp, p, "1"); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
925 return (p); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
926 } |
5858 | 927 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
928 /* 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
|
929 if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
930 CLR(FTS_NAMEONLY); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
931 fts_lfree(sp->fts_child); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
932 sp->fts_child = NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
933 } |
5858 | 934 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
935 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
936 * Cd to the subdirectory. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
937 * |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
938 * 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
|
939 * 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
|
940 * 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
|
941 * 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
|
942 * 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
|
943 * |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
944 * 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
|
945 * 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
|
946 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
947 if (sp->fts_child != NULL) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
948 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
|
949 p->fts_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
950 p->fts_flags |= FTS_DONTCHDIR; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
951 for (p = sp->fts_child; p != NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
952 p = p->fts_link) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
953 p->fts_accpath = |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
954 p->fts_parent->fts_accpath; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
955 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
956 } 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
|
957 if (ISSET(FTS_STOP)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
958 return (NULL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
959 /* 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
|
960 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
|
961 subdirectory, tell the caller. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
962 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
|
963 p->fts_info = FTS_ERR; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
964 LEAVE_DIR (sp, p, "2"); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
965 return (p); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
966 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
967 p = sp->fts_child; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
968 sp->fts_child = NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
969 goto name; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
970 } |
5858 | 971 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
972 /* Move to the next node on this level. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
973 next: tmp = p; |
15531
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
974 |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
975 /* 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
|
976 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
|
977 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
|
978 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
|
979 { |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
980 p = tmp->fts_parent; |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
981 sp->fts_cur = p; |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
982 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
|
983 |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
984 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
|
985 { |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
986 if (ISSET(FTS_STOP)) |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
987 return NULL; |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
988 goto cd_dot_dot; |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
989 } |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
990 |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
991 free(tmp); |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
992 goto name; |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
993 } |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
994 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
995 if ((p = p->fts_link) != NULL) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
996 sp->fts_cur = p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
997 free(tmp); |
5858 | 998 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
999 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1000 * 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
|
1001 * 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
|
1002 * root. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1003 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1004 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
|
1005 if (restore_initial_cwd(sp)) { |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1006 SET(FTS_STOP); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1007 return (NULL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1008 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1009 free_dir(sp); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1010 fts_load(sp, p); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1011 setup_dir(sp); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1012 goto check_for_dir; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1013 } |
5858 | 1014 |
12421
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 * 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
|
1017 * 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
|
1018 * get back if necessary. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1019 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1020 if (p->fts_instr == FTS_SKIP) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1021 goto next; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1022 if (p->fts_instr == FTS_FOLLOW) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1023 p->fts_info = fts_stat(sp, p, true); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1024 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
|
1025 if ((p->fts_symfd = diropen (sp, ".")) < 0) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1026 p->fts_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1027 p->fts_info = FTS_ERR; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1028 } else |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1029 p->fts_flags |= FTS_SYMFOLLOW; |
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_instr = FTS_NOINSTR; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1032 } |
5858 | 1033 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1034 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
|
1035 *t++ = '/'; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1036 memmove(t, p->fts_name, p->fts_namelen + 1); |
5872 | 1037 check_for_dir: |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1038 sp->fts_cur = p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1039 if (p->fts_info == FTS_NSOK) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1040 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1041 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
|
1042 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1043 FTSENT *parent = p->fts_parent; |
19008
a6fc0157c611
fts: nlink_t signedness fixups
Paul Eggert <eggert@cs.ucla.edu>
parents:
18930
diff
changeset
|
1044 if (parent->fts_n_dirs_remaining == 0 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1045 && ISSET(FTS_NOSTAT) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1046 && ISSET(FTS_PHYSICAL) |
19011
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
1047 && (leaf_optimization (parent) |
c152c191727b
fts: three levels of leaf optimization
Paul Eggert <eggert@cs.ucla.edu>
parents:
19010
diff
changeset
|
1048 == NOSTAT_LEAF_OPTIMIZATION)) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1049 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1050 /* nothing more needed */ |
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 else |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1053 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1054 p->fts_info = fts_stat(sp, p, false); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1055 if (S_ISDIR(p->fts_statp->st_mode) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1056 && p->fts_level != FTS_ROOTLEVEL |
19008
a6fc0157c611
fts: nlink_t signedness fixups
Paul Eggert <eggert@cs.ucla.edu>
parents:
18930
diff
changeset
|
1057 && 0 < parent->fts_n_dirs_remaining |
a6fc0157c611
fts: nlink_t signedness fixups
Paul Eggert <eggert@cs.ucla.edu>
parents:
18930
diff
changeset
|
1058 && parent->fts_n_dirs_remaining != (nlink_t) -1) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1059 parent->fts_n_dirs_remaining--; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1060 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1061 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1062 else |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1063 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
|
1064 } |
7707
3f57a32346a2
* lib/fts.c (fts_load): Don't set sp->fts_dev here, since
Jim Meyering <jim@meyering.net>
parents:
7684
diff
changeset
|
1065 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1066 if (p->fts_info == FTS_D) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1067 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1068 /* 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
|
1069 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
|
1070 device number, to be used for FTS_XDEV. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1071 if (p->fts_level == FTS_ROOTLEVEL) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1072 sp->fts_dev = p->fts_statp->st_dev; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1073 Dprintf ((" entering: %s\n", p->fts_path)); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1074 if (! enter_dir (sp, p)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1075 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1076 __set_errno (ENOMEM); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1077 return NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1078 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1079 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1080 return p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1081 } |
15531
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1082 cd_dot_dot: |
5858 | 1083 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1084 /* Move up to the parent node. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1085 p = tmp->fts_parent; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1086 sp->fts_cur = p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1087 free(tmp); |
5858 | 1088 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1089 if (p->fts_level == FTS_ROOTPARENTLEVEL) { |
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 * 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
|
1092 * can distinguish between error and EOF. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1093 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1094 free(p); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1095 __set_errno (0); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1096 return (sp->fts_cur = NULL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1097 } |
5858 | 1098 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1099 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
|
1100 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1101 /* NUL terminate the file name. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1102 sp->fts_path[p->fts_pathlen] = '\0'; |
5858 | 1103 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1104 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1105 * 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
|
1106 * 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
|
1107 * 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
|
1108 * one level, via "..". |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1109 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1110 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
|
1111 if (restore_initial_cwd(sp)) { |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1112 p->fts_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1113 SET(FTS_STOP); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1114 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1115 } else if (p->fts_flags & FTS_SYMFOLLOW) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1116 if (FCHDIR(sp, p->fts_symfd)) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1117 p->fts_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1118 SET(FTS_STOP); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1119 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1120 (void)close(p->fts_symfd); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1121 } else if (!(p->fts_flags & FTS_DONTCHDIR) && |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1122 fts_safe_changedir(sp, p->fts_parent, -1, "..")) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1123 p->fts_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1124 SET(FTS_STOP); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1125 } |
17914
644307da6af9
fts: avoid crash when a cycle is added while traversing
Kamil Dudka <kdudka@redhat.com>
parents:
17848
diff
changeset
|
1126 |
644307da6af9
fts: avoid crash when a cycle is added while traversing
Kamil Dudka <kdudka@redhat.com>
parents:
17848
diff
changeset
|
1127 /* 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
|
1128 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
|
1129 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
|
1130 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
|
1131 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
|
1132 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
|
1133 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
|
1134 } |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1135 return ISSET(FTS_STOP) ? NULL : p; |
5858 | 1136 } |
1137 | |
1138 /* | |
1139 * Fts_set takes the stream as an argument although it's not used in this | |
1140 * implementation; it would be necessary if anyone wanted to add global | |
1141 * semantics to fts using fts_set. An error return is allowed for similar | |
1142 * reasons. | |
1143 */ | |
1144 /* ARGSUSED */ | |
1145 int | |
12482
11bc92a9e2bc
gnulib-common: prefer _GL_UNUSED over _UNUSED_PARAMETER_
Eric Blake <ebb9@byu.net>
parents:
12421
diff
changeset
|
1146 fts_set(FTS *sp _GL_UNUSED, FTSENT *p, int instr) |
5858 | 1147 { |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1148 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
|
1149 instr != FTS_NOINSTR && instr != FTS_SKIP) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1150 __set_errno (EINVAL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1151 return (1); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1152 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1153 p->fts_instr = instr; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1154 return (0); |
5858 | 1155 } |
1156 | |
1157 FTSENT * | |
1158 fts_children (register FTS *sp, int instr) | |
1159 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1160 register FTSENT *p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1161 int fd; |
5858 | 1162 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1163 if (instr != 0 && instr != FTS_NAMEONLY) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1164 __set_errno (EINVAL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1165 return (NULL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1166 } |
5858 | 1167 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1168 /* Set current node pointer. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1169 p = sp->fts_cur; |
5858 | 1170 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1171 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1172 * 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
|
1173 * an error. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1174 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1175 __set_errno (0); |
5858 | 1176 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1177 /* Fatal errors stop here. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1178 if (ISSET(FTS_STOP)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1179 return (NULL); |
5858 | 1180 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1181 /* Return logical hierarchy of user's arguments. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1182 if (p->fts_info == FTS_INIT) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1183 return (p->fts_link); |
5858 | 1184 |
12421
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 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
|
1187 * 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
|
1188 * same effect is available with FTS_AGAIN. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1189 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1190 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
|
1191 return (NULL); |
5858 | 1192 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1193 /* Free up any previous child list. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1194 if (sp->fts_child != NULL) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1195 fts_lfree(sp->fts_child); |
5858 | 1196 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1197 if (instr == FTS_NAMEONLY) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1198 SET(FTS_NAMEONLY); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1199 instr = BNAMES; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1200 } else |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1201 instr = BCHILD; |
5858 | 1202 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1203 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1204 * 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
|
1205 * 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
|
1206 * 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
|
1207 * 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
|
1208 * fts_read will work. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1209 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1210 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
|
1211 ISSET(FTS_NOCHDIR)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1212 return (sp->fts_child = fts_build(sp, instr)); |
5858 | 1213 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1214 if ((fd = diropen (sp, ".")) < 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1215 return (sp->fts_child = NULL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1216 sp->fts_child = fts_build(sp, instr); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1217 if (ISSET(FTS_CWDFD)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1218 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1219 cwd_advance_fd (sp, fd, true); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1220 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1221 else |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1222 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1223 if (fchdir(fd)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1224 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1225 int saved_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1226 close (fd); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1227 __set_errno (saved_errno); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1228 return NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1229 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1230 close (fd); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1231 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1232 return (sp->fts_child); |
5858 | 1233 } |
1234 | |
10481
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
1235 /* 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
|
1236 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
|
1237 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
|
1238 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
|
1239 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
|
1240 static int |
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
1241 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
|
1242 { |
10482
e8d1a5b2c49c
fts: tweak inode comparison function
Jim Meyering <meyering@redhat.com>
parents:
10481
diff
changeset
|
1243 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
|
1244 : 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
|
1245 } |
47fe4e48e158
fts: sort dirent entries on inode number before traversing
Jim Meyering <meyering@redhat.com>
parents:
9718
diff
changeset
|
1246 |
10843
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1247 /* 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
|
1248 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
|
1249 static void |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1250 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
|
1251 { |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1252 mode_t type; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1253 switch (dtype) |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1254 { |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1255 case DT_BLK: |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1256 type = S_IFBLK; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1257 break; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1258 case DT_CHR: |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1259 type = S_IFCHR; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1260 break; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1261 case DT_DIR: |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1262 type = S_IFDIR; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1263 break; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1264 case DT_FIFO: |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1265 type = S_IFIFO; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1266 break; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1267 case DT_LNK: |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1268 type = S_IFLNK; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1269 break; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1270 case DT_REG: |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1271 type = S_IFREG; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1272 break; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1273 case DT_SOCK: |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1274 type = S_IFSOCK; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1275 break; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1276 default: |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1277 type = 0; |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1278 } |
10844 | 1279 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
|
1280 } |
36479bd141ee
fts: provide dirent.d_type via FTSENT.fts_statp, when possible
Jim Meyering <meyering@redhat.com>
parents:
10688
diff
changeset
|
1281 |
15529
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1282 #define closedir_and_clear(dirp) \ |
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1283 do \ |
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1284 { \ |
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1285 closedir (dirp); \ |
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1286 dirp = NULL; \ |
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1287 } \ |
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1288 while (0) |
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1289 |
15528
8203b056cc79
maint: fts: give __opendir2 a new parameter and rename
Jim Meyering <meyering@redhat.com>
parents:
15527
diff
changeset
|
1290 #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
|
1291 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
|
1292 ? 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
|
1293 file, \ |
792927a7e09d
maint: fts.c: move __opendir2 #define "up" out of function body
Jim Meyering <meyering@redhat.com>
parents:
15524
diff
changeset
|
1294 (((ISSET(FTS_PHYSICAL) \ |
792927a7e09d
maint: fts.c: move __opendir2 #define "up" out of function body
Jim Meyering <meyering@redhat.com>
parents:
15524
diff
changeset
|
1295 && ! (ISSET(FTS_COMFOLLOW) \ |
792927a7e09d
maint: fts.c: move __opendir2 #define "up" out of function body
Jim Meyering <meyering@redhat.com>
parents:
15524
diff
changeset
|
1296 && 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
|
1297 ? O_NOFOLLOW : 0) \ |
792927a7e09d
maint: fts.c: move __opendir2 #define "up" out of function body
Jim Meyering <meyering@redhat.com>
parents:
15524
diff
changeset
|
1298 | (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
|
1299 Pdir_fd) |
15525
792927a7e09d
maint: fts.c: move __opendir2 #define "up" out of function body
Jim Meyering <meyering@redhat.com>
parents:
15524
diff
changeset
|
1300 |
5858 | 1301 /* |
1302 * This is the tricky part -- do not casually change *anything* in here. The | |
1303 * idea is to build the linked list of entries that are used by fts_children | |
1304 * and fts_read. There are lots of special cases. | |
1305 * | |
1306 * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is | |
1307 * set and it's a physical walk (so that symbolic links can't be directories), | |
1308 * we can do things quickly. First, if it's a 4.4BSD file system, the type | |
1309 * of the file is in the directory entry. Otherwise, we assume that the number | |
1310 * of subdirectories in a node is equal to the number of links to the parent. | |
1311 * The former skips all stat calls. The latter skips stat calls in any leaf | |
1312 * directories and for any files after the subdirectories in the directory have | |
1313 * been found, cutting the stat calls by about 2/3. | |
1314 */ | |
1315 static FTSENT * | |
1316 internal_function | |
1317 fts_build (register FTS *sp, int type) | |
1318 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1319 register FTSENT *p, *head; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1320 register size_t nitems; |
15529
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1321 FTSENT *tail; |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1322 void *oldaddr; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1323 int saved_errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1324 bool descend; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1325 bool doadjust; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1326 ptrdiff_t level; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1327 size_t len, maxlen, new_len; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1328 char *cp; |
13676
223800d7ac7d
fts, getcwd, glob: audit for dirfd returning -1
Paul Eggert <eggert@cs.ucla.edu>
parents:
13674
diff
changeset
|
1329 int dir_fd; |
15529
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1330 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
|
1331 bool continue_readdir = !!cur->fts_dirp; |
17797 | 1332 size_t max_entries; |
5858 | 1333 |
15531
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1334 /* 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
|
1335 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
|
1336 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
|
1337 if (continue_readdir) |
15526
95cf436ab3b8
maint: fts.c: correct off-by-one indentation
Jim Meyering <meyering@redhat.com>
parents:
15525
diff
changeset
|
1338 { |
15531
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1339 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
|
1340 dir_fd = dirfd (dp); |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1341 if (dir_fd < 0) |
15526
95cf436ab3b8
maint: fts.c: correct off-by-one indentation
Jim Meyering <meyering@redhat.com>
parents:
15525
diff
changeset
|
1342 { |
15531
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1343 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
|
1344 if (type == BREAD) |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1345 { |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1346 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
|
1347 cur->fts_errno = errno; |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1348 } |
15526
95cf436ab3b8
maint: fts.c: correct off-by-one indentation
Jim Meyering <meyering@redhat.com>
parents:
15525
diff
changeset
|
1349 return NULL; |
95cf436ab3b8
maint: fts.c: correct off-by-one indentation
Jim Meyering <meyering@redhat.com>
parents:
15525
diff
changeset
|
1350 } |
95cf436ab3b8
maint: fts.c: correct off-by-one indentation
Jim Meyering <meyering@redhat.com>
parents:
15525
diff
changeset
|
1351 } |
15531
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1352 else |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1353 { |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1354 /* 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
|
1355 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
|
1356 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
|
1357 { |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1358 if (type == BREAD) |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1359 { |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1360 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
|
1361 cur->fts_errno = errno; |
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 return NULL; |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1364 } |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1365 /* 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
|
1366 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
|
1367 opening it. */ |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1368 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
|
1369 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
|
1370 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
|
1371 { |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1372 /* 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
|
1373 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
|
1374 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
|
1375 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
|
1376 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
|
1377 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
|
1378 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
|
1379 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
|
1380 { |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1381 __set_errno (ENOMEM); |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1382 return NULL; |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1383 } |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1384 } |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1385 } |
5858 | 1386 |
15531
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1387 /* 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
|
1388 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
|
1389 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
|
1390 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
|
1391 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
|
1392 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
|
1393 sorting, yet not so large that we risk exhausting memory. */ |
17797 | 1394 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
|
1395 |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1396 /* |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1397 * 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
|
1398 * 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
|
1399 * 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
|
1400 * 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
|
1401 * 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
|
1402 * 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
|
1403 * 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
|
1404 * 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
|
1405 * 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
|
1406 * 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
|
1407 * 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
|
1408 * 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
|
1409 * checking FTS_NS on the returned nodes. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1410 */ |
15531
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1411 if (continue_readdir) |
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 /* 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
|
1414 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
|
1415 descend = true; |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1416 } |
19012 | 1417 else |
1418 { | |
1419 /* Try to descend unless it is a names-only fts_children, | |
19136
504d2bd44d07
* lib/fts.c: Fix XFS comments.
Paul Eggert <eggert@cs.ucla.edu>
parents:
19047
diff
changeset
|
1420 or the directory is known to lack subdirectories. */ |
19012 | 1421 descend = (type != BNAMES |
1422 && ! (ISSET (FTS_NOSTAT) && ISSET (FTS_PHYSICAL) | |
1423 && ! ISSET (FTS_SEEDOT) | |
1424 && cur->fts_statp->st_nlink == MIN_DIR_NLINK | |
1425 && (leaf_optimization (cur) | |
1426 != NO_LEAF_OPTIMIZATION))); | |
1427 if (descend || type == BREAD) | |
1428 { | |
13676
223800d7ac7d
fts, getcwd, glob: audit for dirfd returning -1
Paul Eggert <eggert@cs.ucla.edu>
parents:
13674
diff
changeset
|
1429 if (ISSET(FTS_CWDFD)) |
19047 | 1430 dir_fd = fcntl (dir_fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 1); |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1431 if (dir_fd < 0 || fts_safe_changedir(sp, cur, dir_fd, NULL)) { |
19012 | 1432 if (descend && type == BREAD) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1433 cur->fts_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1434 cur->fts_flags |= FTS_DONTCHDIR; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1435 descend = false; |
15529
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1436 closedir_and_clear(cur->fts_dirp); |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1437 if (ISSET(FTS_CWDFD) && 0 <= dir_fd) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1438 close (dir_fd); |
15529
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1439 cur->fts_dirp = NULL; |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1440 } else |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1441 descend = true; |
19012 | 1442 } |
1443 } | |
5858 | 1444 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1445 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1446 * 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
|
1447 * 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
|
1448 * 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
|
1449 * 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
|
1450 * 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
|
1451 * |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1452 * 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
|
1453 * each new component into the file name. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1454 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1455 len = NAPPEND(cur); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1456 if (ISSET(FTS_NOCHDIR)) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1457 cp = sp->fts_path + len; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1458 *cp++ = '/'; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1459 } else { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1460 /* GCC, you're too verbose. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1461 cp = NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1462 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1463 len++; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1464 maxlen = sp->fts_pathlen - len; |
5858 | 1465 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1466 level = cur->fts_level + 1; |
5858 | 1467 |
16235
18a38c9615f0
In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
1468 /* 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
|
1469 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
|
1470 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
|
1471 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
|
1472 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
|
1473 while (cur->fts_dirp) { |
17640
aa5bda4ec2ae
fts: avoid unnecessary strlen calls
Bernhard Voelker <mail@bernhard-voelker.de>
parents:
17576
diff
changeset
|
1474 size_t d_namelen; |
18338
7276fe79480b
fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents:
18325
diff
changeset
|
1475 __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
|
1476 struct dirent *dp = readdir(cur->fts_dirp); |
18338
7276fe79480b
fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents:
18325
diff
changeset
|
1477 if (dp == NULL) { |
7276fe79480b
fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents:
18325
diff
changeset
|
1478 if (errno) { |
7276fe79480b
fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents:
18325
diff
changeset
|
1479 cur->fts_errno = errno; |
7276fe79480b
fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents:
18325
diff
changeset
|
1480 /* If we've not read any items yet, treat |
7276fe79480b
fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents:
18325
diff
changeset
|
1481 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
|
1482 cur->fts_info = (continue_readdir || nitems) |
7276fe79480b
fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents:
18325
diff
changeset
|
1483 ? FTS_ERR : FTS_DNR; |
7276fe79480b
fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents:
18325
diff
changeset
|
1484 } |
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
|
1485 break; |
18338
7276fe79480b
fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents:
18325
diff
changeset
|
1486 } |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1487 if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1488 continue; |
5858 | 1489 |
17641
019200939aa7
fts: avoid unnecessary strlen calls
Paul Eggert <eggert@cs.ucla.edu>
parents:
17640
diff
changeset
|
1490 d_namelen = _D_EXACT_NAMLEN (dp); |
019200939aa7
fts: avoid unnecessary strlen calls
Paul Eggert <eggert@cs.ucla.edu>
parents:
17640
diff
changeset
|
1491 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
|
1492 if (!p) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1493 goto mem1; |
17640
aa5bda4ec2ae
fts: avoid unnecessary strlen calls
Bernhard Voelker <mail@bernhard-voelker.de>
parents:
17576
diff
changeset
|
1494 if (d_namelen >= maxlen) { |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1495 /* include space for NUL */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1496 oldaddr = sp->fts_path; |
17640
aa5bda4ec2ae
fts: avoid unnecessary strlen calls
Bernhard Voelker <mail@bernhard-voelker.de>
parents:
17576
diff
changeset
|
1497 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
|
1498 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1499 * No more memory. Save |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1500 * errno, free up the current structure and the |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1501 * structures already allocated. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1502 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1503 mem1: saved_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1504 free(p); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1505 fts_lfree(head); |
15529
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1506 closedir_and_clear(cur->fts_dirp); |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1507 cur->fts_info = FTS_ERR; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1508 SET(FTS_STOP); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1509 __set_errno (saved_errno); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1510 return (NULL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1511 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1512 /* Did realloc() change the pointer? */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1513 if (oldaddr != sp->fts_path) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1514 doadjust = true; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1515 if (ISSET(FTS_NOCHDIR)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1516 cp = sp->fts_path + len; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1517 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1518 maxlen = sp->fts_pathlen - len; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1519 } |
5858 | 1520 |
17640
aa5bda4ec2ae
fts: avoid unnecessary strlen calls
Bernhard Voelker <mail@bernhard-voelker.de>
parents:
17576
diff
changeset
|
1521 new_len = len + d_namelen; |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1522 if (new_len < len) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1523 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1524 * 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
|
1525 * 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
|
1526 * the current structure and the structures already |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1527 * allocated, then error out with ENAMETOOLONG. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1528 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1529 free(p); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1530 fts_lfree(head); |
15529
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1531 closedir_and_clear(cur->fts_dirp); |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1532 cur->fts_info = FTS_ERR; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1533 SET(FTS_STOP); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1534 __set_errno (ENAMETOOLONG); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1535 return (NULL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1536 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1537 p->fts_level = level; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1538 p->fts_parent = sp->fts_cur; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1539 p->fts_pathlen = new_len; |
5858 | 1540 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1541 /* 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
|
1542 entries before processing them. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1543 p->fts_statp->st_ino = D_INO (dp); |
5858 | 1544 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1545 /* 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
|
1546 if (ISSET(FTS_NOCHDIR)) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1547 p->fts_accpath = p->fts_path; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1548 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
|
1549 } else |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1550 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
|
1551 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1552 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
|
1553 /* 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
|
1554 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
|
1555 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
|
1556 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
|
1557 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
|
1558 symlinks (FTS_PHYSICAL) and d_type indicates this |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1559 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
|
1560 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
|
1561 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
|
1562 inode numbers. Some day we might optimize that |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1563 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
|
1564 be valid. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1565 bool skip_stat = (ISSET(FTS_PHYSICAL) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1566 && ISSET(FTS_NOSTAT) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1567 && DT_IS_KNOWN(dp) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1568 && ! DT_MUST_BE(dp, DT_DIR)); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1569 p->fts_info = FTS_NSOK; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1570 /* Propagate dirent.d_type information back |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1571 to caller, when possible. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1572 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
|
1573 fts_set_stat_required(p, !skip_stat); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1574 } else { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1575 p->fts_info = fts_stat(sp, p, false); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1576 } |
5858 | 1577 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1578 /* 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
|
1579 p->fts_link = NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1580 if (head == NULL) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1581 head = tail = p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1582 else { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1583 tail->fts_link = p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1584 tail = p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1585 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1586 ++nitems; |
15531
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1587 if (max_entries <= nitems) { |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1588 /* 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
|
1589 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
|
1590 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
|
1591 goto break_without_closedir; |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1592 } |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1593 } |
15531
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1594 |
15529
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1595 if (cur->fts_dirp) |
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1596 closedir_and_clear(cur->fts_dirp); |
5858 | 1597 |
15531
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1598 break_without_closedir: |
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1599 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1600 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1601 * 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
|
1602 * 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
|
1603 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1604 if (doadjust) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1605 fts_padjust(sp, head); |
5858 | 1606 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1607 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1608 * 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
|
1609 * state. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1610 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1611 if (ISSET(FTS_NOCHDIR)) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1612 if (len == sp->fts_pathlen || nitems == 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1613 --cp; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1614 *cp = '\0'; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1615 } |
5858 | 1616 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1617 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1618 * 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
|
1619 * 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
|
1620 * 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
|
1621 * 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
|
1622 * can't get back, we're done. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1623 */ |
15531
65fb6cc5f301
fts: do not exhaust memory when processing million-entry directories
Jim Meyering <meyering@redhat.com>
parents:
15530
diff
changeset
|
1624 if (!continue_readdir && descend && (type == BCHILD || !nitems) && |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1625 (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
|
1626 ? restore_initial_cwd(sp) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1627 : fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1628 cur->fts_info = FTS_ERR; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1629 SET(FTS_STOP); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1630 fts_lfree(head); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1631 return (NULL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1632 } |
5858 | 1633 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1634 /* If didn't find anything, return NULL. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1635 if (!nitems) { |
18338
7276fe79480b
fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents:
18325
diff
changeset
|
1636 if (type == BREAD |
7276fe79480b
fts: handle readdir() errors
Pádraig Brady <P@draigBrady.com>
parents:
18325
diff
changeset
|
1637 && 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
|
1638 cur->fts_info = FTS_DP; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1639 fts_lfree(head); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1640 return (NULL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1641 } |
5858 | 1642 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1643 /* 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
|
1644 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
|
1645 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
|
1646 inode numbers. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1647 if (nitems > _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1648 && !sp->fts_compar |
19010
53fb2576bf3c
fts: cache dirent_inode_sort_may_be_useful too
Paul Eggert <eggert@cs.ucla.edu>
parents:
19009
diff
changeset
|
1649 && dirent_inode_sort_may_be_useful (cur)) { |
12421
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 | 1659 } |
1660 | |
1661 #if FTS_DEBUG | |
1662 | |
1663 /* Walk ->fts_parent links starting at E_CURR, until the root of the | |
1664 current hierarchy. There should be a directory with dev/inode | |
1665 matching those of AD. If not, print a lot of diagnostics. */ | |
1666 static void | |
1667 find_matching_ancestor (FTSENT const *e_curr, struct Active_dir const *ad) | |
1668 { | |
1669 FTSENT const *ent; | |
1670 for (ent = e_curr; ent->fts_level >= FTS_ROOTLEVEL; ent = ent->fts_parent) | |
1671 { | |
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 | 1675 } |
1676 printf ("ERROR: tree dir, %s, not active\n", ad->fts_ent->fts_accpath); | |
1677 printf ("active dirs:\n"); | |
1678 for (ent = e_curr; | |
1679 ent->fts_level >= FTS_ROOTLEVEL; ent = ent->fts_parent) | |
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 | 1687 } |
1688 | |
1689 void | |
1690 fts_cross_check (FTS const *sp) | |
1691 { | |
1692 FTSENT const *ent = sp->fts_cur; | |
1693 FTSENT const *t; | |
1694 if ( ! ISSET (FTS_TIGHT_CYCLE_CHECK)) | |
1695 return; | |
1696 | |
1697 Dprintf (("fts-cross-check cur=%s\n", ent->fts_path)); | |
1698 /* Make sure every parent dir is in the tree. */ | |
1699 for (t = ent->fts_parent; t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent) | |
1700 { | |
1701 struct Active_dir ad; | |
1702 ad.ino = t->fts_statp->st_ino; | |
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 | 1706 } |
1707 | |
1708 /* Make sure every dir in the tree is an active dir. | |
1709 But ENT is not necessarily a directory. If so, just skip this part. */ | |
1710 if (ent->fts_parent->fts_level >= FTS_ROOTLEVEL | |
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 | 1713 { |
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 | 1720 } |
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; |
19047 | 1772 cwd_fd = fcntl (cwd_fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 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
|
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 { |
19047 | 1781 int open_flags = O_SEARCH | O_CLOEXEC | O_NOATIME; |
1782 int parent_fd = openat (cwd_fd, "..", open_flags); | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1783 if (parent_fd < 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1784 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1785 // Warn? |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1786 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1787 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1788 if (!same_fd (fd, parent_fd)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1789 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1790 char *cwd = getcwdat (fd, NULL, 0); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1791 error (0, errno, "ring : %s", cwd); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1792 char *c2 = getcwdat (parent_fd, NULL, 0); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1793 error (0, errno, "parent: %s", c2); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1794 free (cwd); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1795 free (c2); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1796 fts_assert (0); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1797 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1798 close (cwd_fd); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1799 cwd_fd = parent_fd; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1800 } |
7639
1670d42131d7
Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents:
7635
diff
changeset
|
1801 } |
1670d42131d7
Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents:
7635
diff
changeset
|
1802 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
|
1803 } |
5858 | 1804 #endif |
1805 | |
1806 static unsigned short int | |
1807 internal_function | |
1808 fts_stat(FTS *sp, register FTSENT *p, bool follow) | |
1809 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1810 struct stat *sbp = p->fts_statp; |
5858 | 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 if (errno == ENOENT |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1823 && lstat(p->fts_accpath, sbp) == 0) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1824 __set_errno (0); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1825 return (FTS_SLNONE); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1826 } |
19027
a444c9308698
Don't interpret EOVERFLOW to mean nonexistence
Paul Eggert <eggert@cs.ucla.edu>
parents:
19012
diff
changeset
|
1827 p->fts_errno = errno; |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1828 goto err; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1829 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1830 } 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
|
1831 AT_SYMLINK_NOFOLLOW)) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1832 p->fts_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1833 err: memset(sbp, 0, sizeof(struct stat)); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1834 return (FTS_NS); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1835 } |
5858 | 1836 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1837 if (S_ISDIR(sbp->st_mode)) { |
19008
a6fc0157c611
fts: nlink_t signedness fixups
Paul Eggert <eggert@cs.ucla.edu>
parents:
18930
diff
changeset
|
1838 p->fts_n_dirs_remaining |
19009
7201d8037bb3
fts: introduce MIN_DIR_NLINK
Paul Eggert <eggert@cs.ucla.edu>
parents:
19008
diff
changeset
|
1839 = ((sbp->st_nlink < MIN_DIR_NLINK |
19008
a6fc0157c611
fts: nlink_t signedness fixups
Paul Eggert <eggert@cs.ucla.edu>
parents:
18930
diff
changeset
|
1840 || p->fts_level <= FTS_ROOTLEVEL) |
a6fc0157c611
fts: nlink_t signedness fixups
Paul Eggert <eggert@cs.ucla.edu>
parents:
18930
diff
changeset
|
1841 ? -1 |
19009
7201d8037bb3
fts: introduce MIN_DIR_NLINK
Paul Eggert <eggert@cs.ucla.edu>
parents:
19008
diff
changeset
|
1842 : sbp->st_nlink - (ISSET (FTS_SEEDOT) ? 0 : MIN_DIR_NLINK)); |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1843 if (ISDOT(p->fts_name)) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1844 /* Command-line "." and ".." are real directories. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1845 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
|
1846 } |
5872 | 1847 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1848 return (FTS_D); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1849 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1850 if (S_ISLNK(sbp->st_mode)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1851 return (FTS_SL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1852 if (S_ISREG(sbp->st_mode)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1853 return (FTS_F); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1854 return (FTS_DEFAULT); |
5858 | 1855 } |
1856 | |
1857 static int | |
1858 fts_compar (void const *a, void const *b) | |
1859 { | |
1860 /* Convert A and B to the correct types, to pacify the compiler, and | |
1861 for portability to bizarre hosts where "void const *" and "FTSENT | |
1862 const **" differ in runtime representation. The comparison | |
1863 function cannot modify *a and *b, but there is no compile-time | |
1864 check for this. */ | |
1865 FTSENT const **pa = (FTSENT const **) a; | |
1866 FTSENT const **pb = (FTSENT const **) b; | |
1867 return pa[0]->fts_fts->fts_compar (pa, pb); | |
1868 } | |
1869 | |
1870 static FTSENT * | |
1871 internal_function | |
1872 fts_sort (FTS *sp, FTSENT *head, register size_t nitems) | |
1873 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1874 register FTSENT **ap, *p; |
5858 | 1875 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1876 /* 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
|
1877 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
|
1878 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
|
1879 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
|
1880 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
|
1881 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
|
1882 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
|
1883 FTSENT *dummy; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1884 int (*compare) (void const *, void const *) = |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1885 ((sizeof &dummy == sizeof (void *) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1886 && (long int) &dummy == (long int) (void *) &dummy) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1887 ? (int (*) (void const *, void const *)) sp->fts_compar |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1888 : fts_compar); |
5858 | 1889 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1890 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1891 * 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
|
1892 * 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
|
1893 * 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
|
1894 * 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
|
1895 * 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
|
1896 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1897 if (nitems > sp->fts_nitems) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1898 FTSENT **a; |
5858 | 1899 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1900 sp->fts_nitems = nitems + 40; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1901 if (SIZE_MAX / sizeof *a < sp->fts_nitems |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1902 || ! (a = realloc (sp->fts_array, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1903 sp->fts_nitems * sizeof *a))) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1904 free(sp->fts_array); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1905 sp->fts_array = NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1906 sp->fts_nitems = 0; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1907 return (head); |
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 sp->fts_array = a; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1910 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1911 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
|
1912 *ap++ = p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1913 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
|
1914 for (head = *(ap = sp->fts_array); --nitems; ++ap) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1915 ap[0]->fts_link = ap[1]; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1916 ap[0]->fts_link = NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1917 return (head); |
5858 | 1918 } |
1919 | |
1920 static FTSENT * | |
1921 internal_function | |
1922 fts_alloc (FTS *sp, const char *name, register size_t namelen) | |
1923 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1924 register FTSENT *p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1925 size_t len; |
5858 | 1926 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1927 /* |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1928 * 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
|
1929 * structure and the file name in one chunk. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1930 */ |
18403
4434607ac1ce
flexmember: port better to GCC + valgrind
Paul Eggert <eggert@cs.ucla.edu>
parents:
18338
diff
changeset
|
1931 len = FLEXSIZEOF(FTSENT, fts_name, namelen + 1); |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1932 if ((p = malloc(len)) == NULL) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1933 return (NULL); |
5858 | 1934 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1935 /* 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
|
1936 memcpy(p->fts_name, name, namelen); |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1937 p->fts_name[namelen] = '\0'; |
5858 | 1938 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1939 p->fts_namelen = namelen; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1940 p->fts_fts = sp; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1941 p->fts_path = sp->fts_path; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1942 p->fts_errno = 0; |
15529
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1943 p->fts_dirp = NULL; |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1944 p->fts_flags = 0; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1945 p->fts_instr = FTS_NOINSTR; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1946 p->fts_number = 0; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1947 p->fts_pointer = NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1948 return (p); |
5858 | 1949 } |
1950 | |
1951 static void | |
1952 internal_function | |
1953 fts_lfree (register FTSENT *head) | |
1954 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1955 register FTSENT *p; |
5858 | 1956 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1957 /* Free a linked list of structures. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1958 while ((p = head)) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1959 head = head->fts_link; |
15529
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1960 if (p->fts_dirp) |
894e5e6ae541
fts: add/use new struct member, fts_dirp
Jim Meyering <meyering@redhat.com>
parents:
15528
diff
changeset
|
1961 closedir (p->fts_dirp); |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1962 free(p); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1963 } |
5858 | 1964 } |
1965 | |
1966 /* | |
5907 | 1967 * Allow essentially unlimited file name lengths; find, rm, ls should |
1968 * all work on any tree. Most systems will allow creation of file | |
1969 * names much longer than MAXPATHLEN, even though the kernel won't | |
1970 * resolve them. Add the size (not just what's needed) plus 256 bytes | |
1971 * so don't realloc the file name 2 bytes at a time. | |
5858 | 1972 */ |
1973 static bool | |
1974 internal_function | |
1975 fts_palloc (FTS *sp, size_t more) | |
1976 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1977 char *p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1978 size_t new_len = sp->fts_pathlen + more + 256; |
5858 | 1979 |
12421
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 * See if fts_pathlen would overflow. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1982 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1983 if (new_len < sp->fts_pathlen) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1984 free(sp->fts_path); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1985 sp->fts_path = NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1986 __set_errno (ENAMETOOLONG); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1987 return false; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1988 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1989 sp->fts_pathlen = new_len; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1990 p = realloc(sp->fts_path, sp->fts_pathlen); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1991 if (p == NULL) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1992 free(sp->fts_path); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1993 sp->fts_path = NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1994 return false; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1995 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1996 sp->fts_path = p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
1997 return true; |
5858 | 1998 } |
1999 | |
2000 /* | |
5907 | 2001 * When the file name is realloc'd, have to fix all of the pointers in |
2002 * structures already returned. | |
5858 | 2003 */ |
2004 static void | |
2005 internal_function | |
2006 fts_padjust (FTS *sp, FTSENT *head) | |
2007 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2008 FTSENT *p; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2009 char *addr = sp->fts_path; |
5858 | 2010 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2011 #define ADJUST(p) do { \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2012 if ((p)->fts_accpath != (p)->fts_name) { \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2013 (p)->fts_accpath = \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2014 (char *)addr + ((p)->fts_accpath - (p)->fts_path); \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2015 } \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2016 (p)->fts_path = addr; \ |
5858 | 2017 } while (0) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2018 /* Adjust the current set of children. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2019 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
|
2020 ADJUST(p); |
5858 | 2021 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2022 /* 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
|
2023 for (p = head; p->fts_level >= FTS_ROOTLEVEL;) { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2024 ADJUST(p); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2025 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
|
2026 } |
5858 | 2027 } |
2028 | |
2029 static size_t | |
16128
6beadb731202
mark functions with const and pure attributes
Jim Meyering <meyering@redhat.com>
parents:
15988
diff
changeset
|
2030 internal_function _GL_ATTRIBUTE_PURE |
5858 | 2031 fts_maxarglen (char * const *argv) |
2032 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2033 size_t len, max; |
5858 | 2034 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2035 for (max = 0; *argv; ++argv) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2036 if ((len = strlen(*argv)) > max) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2037 max = len; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2038 return (max + 1); |
5858 | 2039 } |
2040 | |
2041 /* | |
5907 | 2042 * Change to dir specified by fd or file name without getting |
5858 | 2043 * tricked by someone changing the world out from underneath us. |
2044 * Assumes p->fts_statp->st_dev and p->fts_statp->st_ino are filled in. | |
7151 | 2045 * 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
|
2046 * and to be closed eventually. So don't pass e.g., 'dirfd(dirp)' and then |
7151 | 2047 * do closedir(dirp), because that would invalidate the saved FD. |
2048 * Upon failure, close FD immediately and return nonzero. | |
5858 | 2049 */ |
2050 static int | |
2051 internal_function | |
5907 | 2052 fts_safe_changedir (FTS *sp, FTSENT *p, int fd, char const *dir) |
5858 | 2053 { |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2054 int ret; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2055 bool is_dotdot = dir && STREQ (dir, ".."); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2056 int newfd; |
7623
5bfad7d666d6
* lib/fts.c (fts_safe_changedir): Add a comment.
Jim Meyering <jim@meyering.net>
parents:
7621
diff
changeset
|
2057 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2058 /* 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
|
2059 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
|
2060 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
|
2061 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
|
2062 if (ISSET (FTS_NOCHDIR)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2063 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2064 if (ISSET (FTS_CWDFD) && 0 <= fd) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2065 close (fd); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2066 return 0; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2067 } |
5858 | 2068 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2069 if (fd < 0 && is_dotdot && ISSET (FTS_CWDFD)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2070 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2071 /* 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
|
2072 comparison. I.e., when changing to parent directory |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2073 (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
|
2074 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
|
2075 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
|
2076 if ( ! i_ring_empty (&sp->fts_fd_ring)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2077 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2078 int parent_fd; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2079 fd_ring_print (sp, stderr, "pre-pop"); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2080 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
|
2081 is_dotdot = true; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2082 if (0 <= parent_fd) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2083 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2084 fd = parent_fd; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2085 dir = NULL; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2086 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2087 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2088 } |
7639
1670d42131d7
Make fts (in FTS_CWDFD mode) more efficient by caching a few open
Jim Meyering <jim@meyering.net>
parents:
7635
diff
changeset
|
2089 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2090 newfd = fd; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2091 if (fd < 0 && (newfd = diropen (sp, dir)) < 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2092 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
|
2093 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2094 /* 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
|
2095 "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
|
2096 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
|
2097 (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
|
2098 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
|
2099 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
|
2100 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
|
2101 if (ISSET(FTS_LOGICAL) || ! HAVE_WORKING_O_NOFOLLOW |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2102 || (dir && STREQ (dir, ".."))) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2103 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2104 struct stat sb; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2105 if (fstat(newfd, &sb)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2106 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2107 ret = -1; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2108 goto bail; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2109 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2110 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
|
2111 || p->fts_statp->st_ino != sb.st_ino) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2112 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2113 __set_errno (ENOENT); /* disinformation */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2114 ret = -1; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2115 goto bail; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2116 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2117 } |
7151 | 2118 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2119 if (ISSET(FTS_CWDFD)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2120 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2121 cwd_advance_fd (sp, newfd, ! is_dotdot); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2122 return 0; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2123 } |
7151 | 2124 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2125 ret = fchdir(newfd); |
5858 | 2126 bail: |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2127 if (fd < 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2128 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2129 int oerrno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2130 (void)close(newfd); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2131 __set_errno (oerrno); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2132 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12378
diff
changeset
|
2133 return ret; |
5858 | 2134 } |