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