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