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