fts.c revision 1.41 1 /* $NetBSD: fts.c,v 1.41 2011/10/15 23:00:01 christos Exp $ */
2
3 /*-
4 * Copyright (c) 1990, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #if HAVE_NBTOOL_CONFIG_H
33 #include "nbtool_config.h"
34 #endif
35
36 #include <sys/cdefs.h>
37 #if defined(LIBC_SCCS) && !defined(lint)
38 #if 0
39 static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
40 #else
41 __RCSID("$NetBSD: fts.c,v 1.41 2011/10/15 23:00:01 christos Exp $");
42 #endif
43 #endif /* LIBC_SCCS and not lint */
44
45 #include "namespace.h"
46 #include <sys/param.h>
47 #include <sys/stat.h>
48
49 #include <assert.h>
50 #include <dirent.h>
51 #include <errno.h>
52 #include <fcntl.h>
53 #include <fts.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <unistd.h>
57
58 #if ! HAVE_NBTOOL_CONFIG_H
59 #define HAVE_STRUCT_DIRENT_D_NAMLEN
60 #endif
61
62 static FTSENT *fts_alloc(FTS *, const char *, size_t);
63 static FTSENT *fts_build(FTS *, int);
64 static void fts_free(FTSENT *);
65 static void fts_lfree(FTSENT *);
66 static void fts_load(FTS *, FTSENT *);
67 static size_t fts_maxarglen(char * const *);
68 static size_t fts_pow2(size_t);
69 static int fts_palloc(FTS *, size_t);
70 static void fts_padjust(FTS *, FTSENT *);
71 static FTSENT *fts_sort(FTS *, FTSENT *, size_t);
72 static unsigned short fts_stat(FTS *, FTSENT *, int);
73 static int fts_safe_changedir(const FTS *, const FTSENT *, int,
74 const char *);
75
76 #if defined(ALIGNBYTES) && defined(ALIGN)
77 #define FTS_ALLOC_ALIGNED 1
78 #else
79 #undef FTS_ALLOC_ALIGNED
80 #endif
81
82 #define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
83
84 #define CLR(opt) (sp->fts_options &= ~(opt))
85 #define ISSET(opt) (sp->fts_options & (opt))
86 #define SET(opt) (sp->fts_options |= (opt))
87
88 #define CHDIR(sp, path) (!ISSET(FTS_NOCHDIR) && chdir(path))
89 #define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd))
90
91 /* fts_build flags */
92 #define BCHILD 1 /* fts_children */
93 #define BNAMES 2 /* fts_children, names only */
94 #define BREAD 3 /* fts_read */
95
96 #ifndef DTF_HIDEW
97 #undef FTS_WHITEOUT
98 #endif
99
100 FTS *
101 fts_open(char * const *argv, int options,
102 int (*compar)(const FTSENT **, const FTSENT **))
103 {
104 FTS *sp;
105 FTSENT *p, *root;
106 size_t nitems;
107 FTSENT *parent, *tmp = NULL; /* pacify gcc */
108 size_t len;
109
110 _DIAGASSERT(argv != NULL);
111
112 /* Options check. */
113 if (options & ~FTS_OPTIONMASK) {
114 errno = EINVAL;
115 return (NULL);
116 }
117
118 /* Allocate/initialize the stream */
119 if ((sp = malloc((unsigned int)sizeof(FTS))) == NULL)
120 return (NULL);
121 memset(sp, 0, sizeof(FTS));
122 sp->fts_compar = compar;
123 sp->fts_options = options;
124
125 /* Logical walks turn on NOCHDIR; symbolic links are too hard. */
126 if (ISSET(FTS_LOGICAL))
127 SET(FTS_NOCHDIR);
128
129 /*
130 * Start out with 1K of path space, and enough, in any case,
131 * to hold the user's paths.
132 */
133 if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
134 goto mem1;
135
136 /* Allocate/initialize root's parent. */
137 if ((parent = fts_alloc(sp, "", 0)) == NULL)
138 goto mem2;
139 parent->fts_level = FTS_ROOTPARENTLEVEL;
140
141 /* Allocate/initialize root(s). */
142 for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) {
143 /* Don't allow zero-length paths. */
144 if ((len = strlen(*argv)) == 0) {
145 errno = ENOENT;
146 goto mem3;
147 }
148
149 if ((p = fts_alloc(sp, *argv, len)) == NULL)
150 goto mem3;
151 p->fts_level = FTS_ROOTLEVEL;
152 p->fts_parent = parent;
153 p->fts_accpath = p->fts_name;
154 p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
155
156 /* Command-line "." and ".." are real directories. */
157 if (p->fts_info == FTS_DOT)
158 p->fts_info = FTS_D;
159
160 /*
161 * If comparison routine supplied, traverse in sorted
162 * order; otherwise traverse in the order specified.
163 */
164 if (compar) {
165 p->fts_link = root;
166 root = p;
167 } else {
168 p->fts_link = NULL;
169 if (root == NULL)
170 tmp = root = p;
171 else {
172 tmp->fts_link = p;
173 tmp = p;
174 }
175 }
176 }
177 if (compar && nitems > 1)
178 root = fts_sort(sp, root, nitems);
179
180 /*
181 * Allocate a dummy pointer and make fts_read think that we've just
182 * finished the node before the root(s); set p->fts_info to FTS_INIT
183 * so that everything about the "current" node is ignored.
184 */
185 if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
186 goto mem3;
187 sp->fts_cur->fts_link = root;
188 sp->fts_cur->fts_info = FTS_INIT;
189
190 /*
191 * If using chdir(2), grab a file descriptor pointing to dot to insure
192 * that we can get back here; this could be avoided for some paths,
193 * but almost certainly not worth the effort. Slashes, symbolic links,
194 * and ".." are all fairly nasty problems. Note, if we can't get the
195 * descriptor we run anyway, just more slowly.
196 */
197 if (!ISSET(FTS_NOCHDIR)) {
198 if ((sp->fts_rfd = open(".", O_RDONLY | O_CLOEXEC, 0)) == -1)
199 SET(FTS_NOCHDIR);
200 }
201
202 if (nitems == 0)
203 fts_free(parent);
204
205 return (sp);
206
207 mem3: fts_lfree(root);
208 fts_free(parent);
209 mem2: free(sp->fts_path);
210 mem1: free(sp);
211 return (NULL);
212 }
213
214 static void
215 fts_load(FTS *sp, FTSENT *p)
216 {
217 size_t len;
218 char *cp;
219
220 _DIAGASSERT(sp != NULL);
221 _DIAGASSERT(p != NULL);
222
223 /*
224 * Load the stream structure for the next traversal. Since we don't
225 * actually enter the directory until after the preorder visit, set
226 * the fts_accpath field specially so the chdir gets done to the right
227 * place and the user can access the first node. From fts_open it's
228 * known that the path will fit.
229 */
230 len = p->fts_pathlen = p->fts_namelen;
231 memmove(sp->fts_path, p->fts_name, len + 1);
232 if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
233 len = strlen(++cp);
234 memmove(p->fts_name, cp, len + 1);
235 p->fts_namelen = len;
236 }
237 p->fts_accpath = p->fts_path = sp->fts_path;
238 sp->fts_dev = p->fts_dev;
239 }
240
241 int
242 fts_close(FTS *sp)
243 {
244 FTSENT *freep, *p;
245 int saved_errno = 0;
246
247 _DIAGASSERT(sp != NULL);
248
249 /*
250 * This still works if we haven't read anything -- the dummy structure
251 * points to the root list, so we step through to the end of the root
252 * list which has a valid parent pointer.
253 */
254 if (sp->fts_cur) {
255 if (sp->fts_cur->fts_flags & FTS_SYMFOLLOW)
256 (void)close(sp->fts_cur->fts_symfd);
257 for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
258 freep = p;
259 p = p->fts_link ? p->fts_link : p->fts_parent;
260 fts_free(freep);
261 }
262 fts_free(p);
263 }
264
265 /* Free up child linked list, sort array, path buffer. */
266 if (sp->fts_child)
267 fts_lfree(sp->fts_child);
268 if (sp->fts_array)
269 free(sp->fts_array);
270 free(sp->fts_path);
271
272 /* Return to original directory, save errno if necessary. */
273 if (!ISSET(FTS_NOCHDIR)) {
274 if (fchdir(sp->fts_rfd) == -1)
275 saved_errno = errno;
276 (void)close(sp->fts_rfd);
277 }
278
279 /* Free up the stream pointer. */
280 free(sp);
281 if (saved_errno) {
282 errno = saved_errno;
283 return -1;
284 }
285
286 return 0;
287 }
288
289 #if !defined(__FTS_COMPAT_TAILINGSLASH)
290
291 /*
292 * Special case of "/" at the end of the path so that slashes aren't
293 * appended which would cause paths to be written as "....//foo".
294 */
295 #define NAPPEND(p) \
296 (p->fts_path[p->fts_pathlen - 1] == '/' \
297 ? p->fts_pathlen - 1 : p->fts_pathlen)
298
299 #else /* !defined(__FTS_COMPAT_TAILINGSLASH) */
300
301 /*
302 * compatibility with the old behaviour.
303 *
304 * Special case a root of "/" so that slashes aren't appended which would
305 * cause paths to be written as "//foo".
306 */
307
308 #define NAPPEND(p) \
309 (p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 && \
310 p->fts_path[0] == '/' ? 0 : p->fts_pathlen)
311
312 #endif /* !defined(__FTS_COMPAT_TAILINGSLASH) */
313
314 FTSENT *
315 fts_read(FTS *sp)
316 {
317 FTSENT *p, *tmp;
318 int instr;
319 char *t;
320 int saved_errno;
321
322 _DIAGASSERT(sp != NULL);
323
324 /* If finished or unrecoverable error, return NULL. */
325 if (sp->fts_cur == NULL || ISSET(FTS_STOP))
326 return (NULL);
327
328 /* Set current node pointer. */
329 p = sp->fts_cur;
330
331 /* Save and zero out user instructions. */
332 instr = p->fts_instr;
333 p->fts_instr = FTS_NOINSTR;
334
335 /* Any type of file may be re-visited; re-stat and re-turn. */
336 if (instr == FTS_AGAIN) {
337 p->fts_info = fts_stat(sp, p, 0);
338 return (p);
339 }
340
341 /*
342 * Following a symlink -- SLNONE test allows application to see
343 * SLNONE and recover. If indirecting through a symlink, have
344 * keep a pointer to current location. If unable to get that
345 * pointer, follow fails.
346 */
347 if (instr == FTS_FOLLOW &&
348 (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
349 p->fts_info = fts_stat(sp, p, 1);
350 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
351 if ((p->fts_symfd = open(".", O_RDONLY | O_CLOEXEC, 0))
352 == -1) {
353 p->fts_errno = errno;
354 p->fts_info = FTS_ERR;
355 } else
356 p->fts_flags |= FTS_SYMFOLLOW;
357 }
358 return (p);
359 }
360
361 /* Directory in pre-order. */
362 if (p->fts_info == FTS_D) {
363 /* If skipped or crossed mount point, do post-order visit. */
364 if (instr == FTS_SKIP ||
365 (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
366 if (p->fts_flags & FTS_SYMFOLLOW)
367 (void)close(p->fts_symfd);
368 if (sp->fts_child) {
369 fts_lfree(sp->fts_child);
370 sp->fts_child = NULL;
371 }
372 p->fts_info = FTS_DP;
373 return (p);
374 }
375
376 /* Rebuild if only read the names and now traversing. */
377 if (sp->fts_child && ISSET(FTS_NAMEONLY)) {
378 CLR(FTS_NAMEONLY);
379 fts_lfree(sp->fts_child);
380 sp->fts_child = NULL;
381 }
382
383 /*
384 * Cd to the subdirectory.
385 *
386 * If have already read and now fail to chdir, whack the list
387 * to make the names come out right, and set the parent errno
388 * so the application will eventually get an error condition.
389 * Set the FTS_DONTCHDIR flag so that when we logically change
390 * directories back to the parent we don't do a chdir.
391 *
392 * If haven't read do so. If the read fails, fts_build sets
393 * FTS_STOP or the fts_info field of the node.
394 */
395 if (sp->fts_child) {
396 if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
397 p->fts_errno = errno;
398 p->fts_flags |= FTS_DONTCHDIR;
399 for (p = sp->fts_child; p; p = p->fts_link)
400 p->fts_accpath =
401 p->fts_parent->fts_accpath;
402 }
403 } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
404 if (ISSET(FTS_STOP))
405 return (NULL);
406 return (p);
407 }
408 p = sp->fts_child;
409 sp->fts_child = NULL;
410 goto name;
411 }
412
413 /* Move to the next node on this level. */
414 next: tmp = p;
415 if ((p = p->fts_link) != NULL) {
416 fts_free(tmp);
417
418 /*
419 * If reached the top, return to the original directory, and
420 * load the paths for the next root.
421 */
422 if (p->fts_level == FTS_ROOTLEVEL) {
423 if (FCHDIR(sp, sp->fts_rfd)) {
424 SET(FTS_STOP);
425 return (NULL);
426 }
427 fts_load(sp, p);
428 return (sp->fts_cur = p);
429 }
430
431 /*
432 * User may have called fts_set on the node. If skipped,
433 * ignore. If followed, get a file descriptor so we can
434 * get back if necessary.
435 */
436 if (p->fts_instr == FTS_SKIP)
437 goto next;
438 if (p->fts_instr == FTS_FOLLOW) {
439 p->fts_info = fts_stat(sp, p, 1);
440 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
441 if ((p->fts_symfd =
442 open(".", O_RDONLY | O_CLOEXEC, 0)) == -1) {
443 p->fts_errno = errno;
444 p->fts_info = FTS_ERR;
445 } else
446 p->fts_flags |= FTS_SYMFOLLOW;
447 }
448 p->fts_instr = FTS_NOINSTR;
449 }
450
451 name: t = sp->fts_path + NAPPEND(p->fts_parent);
452 *t++ = '/';
453 memmove(t, p->fts_name, (size_t)(p->fts_namelen + 1));
454 return (sp->fts_cur = p);
455 }
456
457 /* Move up to the parent node. */
458 p = tmp->fts_parent;
459 fts_free(tmp);
460
461 if (p->fts_level == FTS_ROOTPARENTLEVEL) {
462 /*
463 * Done; free everything up and set errno to 0 so the user
464 * can distinguish between error and EOF.
465 */
466 fts_free(p);
467 errno = 0;
468 return (sp->fts_cur = NULL);
469 }
470
471 /* Nul terminate the pathname. */
472 sp->fts_path[p->fts_pathlen] = '\0';
473
474 /*
475 * Return to the parent directory. If at a root node or came through
476 * a symlink, go back through the file descriptor. Otherwise, cd up
477 * one directory.
478 */
479 if (p->fts_level == FTS_ROOTLEVEL) {
480 if (FCHDIR(sp, sp->fts_rfd)) {
481 SET(FTS_STOP);
482 return (NULL);
483 }
484 } else if (p->fts_flags & FTS_SYMFOLLOW) {
485 if (FCHDIR(sp, p->fts_symfd)) {
486 saved_errno = errno;
487 (void)close(p->fts_symfd);
488 errno = saved_errno;
489 SET(FTS_STOP);
490 return (NULL);
491 }
492 (void)close(p->fts_symfd);
493 } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
494 fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
495 SET(FTS_STOP);
496 return (NULL);
497 }
498 p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
499 return (sp->fts_cur = p);
500 }
501
502 /*
503 * Fts_set takes the stream as an argument although it's not used in this
504 * implementation; it would be necessary if anyone wanted to add global
505 * semantics to fts using fts_set. An error return is allowed for similar
506 * reasons.
507 */
508 /* ARGSUSED */
509 int
510 fts_set(FTS *sp, FTSENT *p, int instr)
511 {
512
513 _DIAGASSERT(sp != NULL);
514 _DIAGASSERT(p != NULL);
515
516 if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
517 instr != FTS_NOINSTR && instr != FTS_SKIP) {
518 errno = EINVAL;
519 return (1);
520 }
521 p->fts_instr = instr;
522 return (0);
523 }
524
525 FTSENT *
526 fts_children(FTS *sp, int instr)
527 {
528 FTSENT *p;
529 int fd;
530
531 _DIAGASSERT(sp != NULL);
532
533 if (instr && instr != FTS_NAMEONLY) {
534 errno = EINVAL;
535 return (NULL);
536 }
537
538 /* Set current node pointer. */
539 p = sp->fts_cur;
540
541 /*
542 * Errno set to 0 so user can distinguish empty directory from
543 * an error.
544 */
545 errno = 0;
546
547 /* Fatal errors stop here. */
548 if (ISSET(FTS_STOP))
549 return (NULL);
550
551 /* Return logical hierarchy of user's arguments. */
552 if (p->fts_info == FTS_INIT)
553 return (p->fts_link);
554
555 /*
556 * If not a directory being visited in pre-order, stop here. Could
557 * allow FTS_DNR, assuming the user has fixed the problem, but the
558 * same effect is available with FTS_AGAIN.
559 */
560 if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
561 return (NULL);
562
563 /* Free up any previous child list. */
564 if (sp->fts_child)
565 fts_lfree(sp->fts_child);
566
567 if (instr == FTS_NAMEONLY) {
568 SET(FTS_NAMEONLY);
569 instr = BNAMES;
570 } else
571 instr = BCHILD;
572
573 /*
574 * If using chdir on a relative path and called BEFORE fts_read does
575 * its chdir to the root of a traversal, we can lose -- we need to
576 * chdir into the subdirectory, and we don't know where the current
577 * directory is, so we can't get back so that the upcoming chdir by
578 * fts_read will work.
579 */
580 if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
581 ISSET(FTS_NOCHDIR))
582 return (sp->fts_child = fts_build(sp, instr));
583
584 if ((fd = open(".", O_RDONLY, 0)) == -1)
585 return (sp->fts_child = NULL);
586 sp->fts_child = fts_build(sp, instr);
587 if (fchdir(fd)) {
588 (void)close(fd);
589 return (NULL);
590 }
591 (void)close(fd);
592 return (sp->fts_child);
593 }
594
595 /*
596 * This is the tricky part -- do not casually change *anything* in here. The
597 * idea is to build the linked list of entries that are used by fts_children
598 * and fts_read. There are lots of special cases.
599 *
600 * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is
601 * set and it's a physical walk (so that symbolic links can't be directories),
602 * we can do things quickly. First, if it's a 4.4BSD file system, the type
603 * of the file is in the directory entry. Otherwise, we assume that the number
604 * of subdirectories in a node is equal to the number of links to the parent.
605 * The former skips all stat calls. The latter skips stat calls in any leaf
606 * directories and for any files after the subdirectories in the directory have
607 * been found, cutting the stat calls by about 2/3.
608 */
609 static FTSENT *
610 fts_build(FTS *sp, int type)
611 {
612 struct dirent *dp;
613 FTSENT *p, *head;
614 size_t nitems;
615 FTSENT *cur, *tail;
616 DIR *dirp;
617 void *oldaddr;
618 size_t dnamlen;
619 int cderrno, descend, level, nlinks, saved_errno, nostat, doadjust;
620 size_t len, maxlen;
621 #ifdef FTS_WHITEOUT
622 int oflag;
623 #endif
624 char *cp = NULL; /* pacify gcc */
625
626 _DIAGASSERT(sp != NULL);
627
628 /* Set current node pointer. */
629 cur = sp->fts_cur;
630
631 /*
632 * Open the directory for reading. If this fails, we're done.
633 * If being called from fts_read, set the fts_info field.
634 */
635 #ifdef FTS_WHITEOUT
636 if (ISSET(FTS_WHITEOUT))
637 oflag = DTF_NODUP|DTF_REWIND;
638 else
639 oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
640 #else
641 #define __opendir2(path, flag) opendir(path)
642 #endif
643 if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
644 if (type == BREAD) {
645 cur->fts_info = FTS_DNR;
646 cur->fts_errno = errno;
647 }
648 return (NULL);
649 }
650
651 /*
652 * Nlinks is the number of possible entries of type directory in the
653 * directory if we're cheating on stat calls, 0 if we're not doing
654 * any stat calls at all, -1 if we're doing stats on everything.
655 */
656 if (type == BNAMES) {
657 nlinks = 0;
658 nostat = 1;
659 } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
660 nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
661 nostat = 1;
662 } else {
663 nlinks = -1;
664 nostat = 0;
665 }
666
667 #ifdef notdef
668 (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
669 (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
670 ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
671 #endif
672 /*
673 * If we're going to need to stat anything or we want to descend
674 * and stay in the directory, chdir. If this fails we keep going,
675 * but set a flag so we don't chdir after the post-order visit.
676 * We won't be able to stat anything, but we can still return the
677 * names themselves. Note, that since fts_read won't be able to
678 * chdir into the directory, it will have to return different path
679 * names than before, i.e. "a/b" instead of "b". Since the node
680 * has already been visited in pre-order, have to wait until the
681 * post-order visit to return the error. There is a special case
682 * here, if there was nothing to stat then it's not an error to
683 * not be able to stat. This is all fairly nasty. If a program
684 * needed sorted entries or stat information, they had better be
685 * checking FTS_NS on the returned nodes.
686 */
687 cderrno = 0;
688 if (nlinks || type == BREAD) {
689 if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
690 if (nlinks && type == BREAD)
691 cur->fts_errno = errno;
692 cur->fts_flags |= FTS_DONTCHDIR;
693 descend = 0;
694 cderrno = errno;
695 } else
696 descend = 1;
697 } else
698 descend = 0;
699
700 /*
701 * Figure out the max file name length that can be stored in the
702 * current path -- the inner loop allocates more path as necessary.
703 * We really wouldn't have to do the maxlen calculations here, we
704 * could do them in fts_read before returning the path, but it's a
705 * lot easier here since the length is part of the dirent structure.
706 *
707 * If not changing directories set a pointer so that can just append
708 * each new name into the path.
709 */
710 len = NAPPEND(cur);
711 if (ISSET(FTS_NOCHDIR)) {
712 cp = sp->fts_path + len;
713 *cp++ = '/';
714 }
715 len++;
716 maxlen = sp->fts_pathlen - len;
717
718 #if defined(__FTS_COMPAT_LEVEL)
719 if (cur->fts_level == SHRT_MAX) {
720 (void)closedir(dirp);
721 cur->fts_info = FTS_ERR;
722 SET(FTS_STOP);
723 errno = ENAMETOOLONG;
724 return (NULL);
725 }
726 #endif
727
728 level = cur->fts_level + 1;
729
730 /* Read the directory, attaching each entry to the `link' pointer. */
731 doadjust = 0;
732 for (head = tail = NULL, nitems = 0; (dp = readdir(dirp)) != NULL;) {
733
734 if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
735 continue;
736
737 #if defined(HAVE_STRUCT_DIRENT_D_NAMLEN)
738 dnamlen = dp->d_namlen;
739 #else
740 dnamlen = strlen(dp->d_name);
741 #endif
742 if ((p = fts_alloc(sp, dp->d_name, dnamlen)) == NULL)
743 goto mem1;
744 if (dnamlen >= maxlen) { /* include space for NUL */
745 oldaddr = sp->fts_path;
746 if (fts_palloc(sp, dnamlen + len + 1)) {
747 /*
748 * No more memory for path or structures. Save
749 * errno, free up the current structure and the
750 * structures already allocated.
751 */
752 mem1: saved_errno = errno;
753 if (p)
754 fts_free(p);
755 fts_lfree(head);
756 (void)closedir(dirp);
757 errno = saved_errno;
758 cur->fts_info = FTS_ERR;
759 SET(FTS_STOP);
760 return (NULL);
761 }
762 /* Did realloc() change the pointer? */
763 if (oldaddr != sp->fts_path) {
764 doadjust = 1;
765 if (ISSET(FTS_NOCHDIR))
766 cp = sp->fts_path + len;
767 }
768 maxlen = sp->fts_pathlen - len;
769 }
770
771 #if defined(__FTS_COMPAT_LENGTH)
772 if (len + dnamlen >= USHRT_MAX) {
773 /*
774 * In an FTSENT, fts_pathlen is an unsigned short
775 * so it is possible to wraparound here.
776 * If we do, free up the current structure and the
777 * structures already allocated, then error out
778 * with ENAMETOOLONG.
779 */
780 fts_free(p);
781 fts_lfree(head);
782 (void)closedir(dirp);
783 cur->fts_info = FTS_ERR;
784 SET(FTS_STOP);
785 errno = ENAMETOOLONG;
786 return (NULL);
787 }
788 #endif
789 p->fts_level = level;
790 p->fts_pathlen = len + dnamlen;
791 p->fts_parent = sp->fts_cur;
792
793 #ifdef FTS_WHITEOUT
794 if (dp->d_type == DT_WHT)
795 p->fts_flags |= FTS_ISW;
796 #endif
797
798 if (cderrno) {
799 if (nlinks) {
800 p->fts_info = FTS_NS;
801 p->fts_errno = cderrno;
802 } else
803 p->fts_info = FTS_NSOK;
804 p->fts_accpath = cur->fts_accpath;
805 } else if (nlinks == 0
806 #ifdef DT_DIR
807 || (nostat &&
808 dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
809 #endif
810 ) {
811 p->fts_accpath =
812 ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
813 p->fts_info = FTS_NSOK;
814 } else {
815 /* Build a file name for fts_stat to stat. */
816 if (ISSET(FTS_NOCHDIR)) {
817 p->fts_accpath = p->fts_path;
818 memmove(cp, p->fts_name,
819 (size_t)(p->fts_namelen + 1));
820 } else
821 p->fts_accpath = p->fts_name;
822 /* Stat it. */
823 p->fts_info = fts_stat(sp, p, 0);
824
825 /* Decrement link count if applicable. */
826 if (nlinks > 0 && (p->fts_info == FTS_D ||
827 p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
828 --nlinks;
829 }
830
831 /* We walk in directory order so "ls -f" doesn't get upset. */
832 p->fts_link = NULL;
833 if (head == NULL)
834 head = tail = p;
835 else {
836 tail->fts_link = p;
837 tail = p;
838 }
839 ++nitems;
840 }
841 (void)closedir(dirp);
842
843 /*
844 * If had to realloc the path, adjust the addresses for the rest
845 * of the tree.
846 */
847 if (doadjust)
848 fts_padjust(sp, head);
849
850 /*
851 * If not changing directories, reset the path back to original
852 * state.
853 */
854 if (ISSET(FTS_NOCHDIR)) {
855 if (len == sp->fts_pathlen || nitems == 0)
856 --cp;
857 *cp = '\0';
858 }
859
860 /*
861 * If descended after called from fts_children or after called from
862 * fts_read and nothing found, get back. At the root level we use
863 * the saved fd; if one of fts_open()'s arguments is a relative path
864 * to an empty directory, we wind up here with no other way back. If
865 * can't get back, we're done.
866 */
867 if (descend && (type == BCHILD || !nitems) &&
868 (cur->fts_level == FTS_ROOTLEVEL ?
869 FCHDIR(sp, sp->fts_rfd) :
870 fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
871 cur->fts_info = FTS_ERR;
872 SET(FTS_STOP);
873 return (NULL);
874 }
875
876 /* If didn't find anything, return NULL. */
877 if (!nitems) {
878 if (type == BREAD)
879 cur->fts_info = FTS_DP;
880 return (NULL);
881 }
882
883 /* Sort the entries. */
884 if (sp->fts_compar && nitems > 1)
885 head = fts_sort(sp, head, nitems);
886 return (head);
887 }
888
889 static unsigned short
890 fts_stat(FTS *sp, FTSENT *p, int follow)
891 {
892 FTSENT *t;
893 dev_t dev;
894 __fts_ino_t ino;
895 __fts_stat_t *sbp, sb;
896 int saved_errno;
897
898 _DIAGASSERT(sp != NULL);
899 _DIAGASSERT(p != NULL);
900
901 /* If user needs stat info, stat buffer already allocated. */
902 sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
903
904 #ifdef FTS_WHITEOUT
905 /* check for whiteout */
906 if (p->fts_flags & FTS_ISW) {
907 if (sbp != &sb) {
908 memset(sbp, '\0', sizeof (*sbp));
909 sbp->st_mode = S_IFWHT;
910 }
911 return (FTS_W);
912 }
913 #endif
914
915 /*
916 * If doing a logical walk, or application requested FTS_FOLLOW, do
917 * a stat(2). If that fails, check for a non-existent symlink. If
918 * fail, set the errno from the stat call.
919 */
920 if (ISSET(FTS_LOGICAL) || follow) {
921 if (stat(p->fts_accpath, sbp)) {
922 saved_errno = errno;
923 if (!lstat(p->fts_accpath, sbp)) {
924 errno = 0;
925 return (FTS_SLNONE);
926 }
927 p->fts_errno = saved_errno;
928 goto err;
929 }
930 } else if (lstat(p->fts_accpath, sbp)) {
931 p->fts_errno = errno;
932 err: memset(sbp, 0, sizeof(*sbp));
933 return (FTS_NS);
934 }
935
936 if (S_ISDIR(sbp->st_mode)) {
937 /*
938 * Set the device/inode. Used to find cycles and check for
939 * crossing mount points. Also remember the link count, used
940 * in fts_build to limit the number of stat calls. It is
941 * understood that these fields are only referenced if fts_info
942 * is set to FTS_D.
943 */
944 dev = p->fts_dev = sbp->st_dev;
945 ino = p->fts_ino = sbp->st_ino;
946 p->fts_nlink = sbp->st_nlink;
947
948 if (ISDOT(p->fts_name))
949 return (FTS_DOT);
950
951 /*
952 * Cycle detection is done by brute force when the directory
953 * is first encountered. If the tree gets deep enough or the
954 * number of symbolic links to directories is high enough,
955 * something faster might be worthwhile.
956 */
957 for (t = p->fts_parent;
958 t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
959 if (ino == t->fts_ino && dev == t->fts_dev) {
960 p->fts_cycle = t;
961 return (FTS_DC);
962 }
963 return (FTS_D);
964 }
965 if (S_ISLNK(sbp->st_mode))
966 return (FTS_SL);
967 if (S_ISREG(sbp->st_mode))
968 return (FTS_F);
969 return (FTS_DEFAULT);
970 }
971
972 static FTSENT *
973 fts_sort(FTS *sp, FTSENT *head, size_t nitems)
974 {
975 FTSENT **ap, *p;
976
977 _DIAGASSERT(sp != NULL);
978 _DIAGASSERT(head != NULL);
979
980 /*
981 * Construct an array of pointers to the structures and call qsort(3).
982 * Reassemble the array in the order returned by qsort. If unable to
983 * sort for memory reasons, return the directory entries in their
984 * current order. Allocate enough space for the current needs plus
985 * 40 so don't realloc one entry at a time.
986 */
987 if (nitems > sp->fts_nitems) {
988 FTSENT **new;
989
990 new = realloc(sp->fts_array, sizeof(FTSENT *) * (nitems + 40));
991 if (new == 0)
992 return (head);
993 sp->fts_array = new;
994 sp->fts_nitems = nitems + 40;
995 }
996 for (ap = sp->fts_array, p = head; p; p = p->fts_link)
997 *ap++ = p;
998 qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *),
999 (int (*)(const void *, const void *))sp->fts_compar);
1000 for (head = *(ap = sp->fts_array); --nitems; ++ap)
1001 ap[0]->fts_link = ap[1];
1002 ap[0]->fts_link = NULL;
1003 return (head);
1004 }
1005
1006 static FTSENT *
1007 fts_alloc(FTS *sp, const char *name, size_t namelen)
1008 {
1009 FTSENT *p;
1010 #if defined(FTS_ALLOC_ALIGNED)
1011 size_t len;
1012 #endif
1013
1014 _DIAGASSERT(sp != NULL);
1015 _DIAGASSERT(name != NULL);
1016
1017 #if defined(FTS_ALLOC_ALIGNED)
1018 /*
1019 * The file name is a variable length array and no stat structure is
1020 * necessary if the user has set the nostat bit. Allocate the FTSENT
1021 * structure, the file name and the stat structure in one chunk, but
1022 * be careful that the stat structure is reasonably aligned. Since the
1023 * fts_name field is declared to be of size 1, the fts_name pointer is
1024 * namelen + 2 before the first possible address of the stat structure.
1025 */
1026 len = sizeof(FTSENT) + namelen;
1027 if (!ISSET(FTS_NOSTAT))
1028 len += sizeof(*(p->fts_statp)) + ALIGNBYTES;
1029 if ((p = malloc(len)) == NULL)
1030 return (NULL);
1031
1032 if (!ISSET(FTS_NOSTAT))
1033 p->fts_statp = (__fts_stat_t *)ALIGN(
1034 (unsigned long)(p->fts_name + namelen + 2));
1035 #else
1036 if ((p = malloc(sizeof(FTSENT) + namelen)) == NULL)
1037 return (NULL);
1038
1039 if (!ISSET(FTS_NOSTAT))
1040 if ((p->fts_statp = malloc(sizeof(*(p->fts_statp)))) == NULL) {
1041 free(p);
1042 return (NULL);
1043 }
1044 #endif
1045
1046 if (ISSET(FTS_NOSTAT))
1047 p->fts_statp = NULL;
1048
1049 /* Copy the name plus the trailing NULL. */
1050 memmove(p->fts_name, name, namelen + 1);
1051
1052 p->fts_namelen = namelen;
1053 p->fts_path = sp->fts_path;
1054 p->fts_errno = 0;
1055 p->fts_flags = 0;
1056 p->fts_instr = FTS_NOINSTR;
1057 p->fts_number = 0;
1058 p->fts_pointer = NULL;
1059 return (p);
1060 }
1061
1062 static void
1063 fts_free(FTSENT *p)
1064 {
1065 #if !defined(FTS_ALLOC_ALIGNED)
1066 if (p->fts_statp)
1067 free(p->fts_statp);
1068 #endif
1069 free(p);
1070 }
1071
1072 static void
1073 fts_lfree(FTSENT *head)
1074 {
1075 FTSENT *p;
1076
1077 /* XXX: head may be NULL ? */
1078
1079 /* Free a linked list of structures. */
1080 while ((p = head) != NULL) {
1081 head = head->fts_link;
1082 fts_free(p);
1083 }
1084 }
1085
1086 static size_t
1087 fts_pow2(size_t x)
1088 {
1089
1090 x--;
1091 x |= x>>1;
1092 x |= x>>2;
1093 x |= x>>4;
1094 x |= x>>8;
1095 x |= x>>16;
1096 #if LONG_BIT > 32
1097 x |= x>>32;
1098 #endif
1099 #if LONG_BIT > 64
1100 x |= x>>64;
1101 #endif
1102 x++;
1103 return (x);
1104 }
1105
1106 /*
1107 * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
1108 * Most systems will allow creation of paths much longer than MAXPATHLEN, even
1109 * though the kernel won't resolve them. Round up the new size to a power of 2,
1110 * so we don't realloc the path 2 bytes at a time.
1111 */
1112 static int
1113 fts_palloc(FTS *sp, size_t size)
1114 {
1115 char *new;
1116
1117 _DIAGASSERT(sp != NULL);
1118
1119 #ifdef __FTS_COMPAT_LENGTH
1120 /* Protect against fts_pathlen overflow. */
1121 if (size > USHRT_MAX + 1) {
1122 errno = ENAMETOOLONG;
1123 return (1);
1124 }
1125 #endif
1126 size = fts_pow2(size);
1127 new = realloc(sp->fts_path, size);
1128 if (new == 0)
1129 return (1);
1130 sp->fts_path = new;
1131 sp->fts_pathlen = size;
1132 return (0);
1133 }
1134
1135 /*
1136 * When the path is realloc'd, have to fix all of the pointers in structures
1137 * already returned.
1138 */
1139 static void
1140 fts_padjust(FTS *sp, FTSENT *head)
1141 {
1142 FTSENT *p;
1143 char *addr;
1144
1145 _DIAGASSERT(sp != NULL);
1146
1147 #define ADJUST(p) do { \
1148 if ((p)->fts_accpath != (p)->fts_name) \
1149 (p)->fts_accpath = \
1150 addr + ((p)->fts_accpath - (p)->fts_path); \
1151 (p)->fts_path = addr; \
1152 } while (/*CONSTCOND*/0)
1153
1154 addr = sp->fts_path;
1155
1156 /* Adjust the current set of children. */
1157 for (p = sp->fts_child; p; p = p->fts_link)
1158 ADJUST(p);
1159
1160 /* Adjust the rest of the tree, including the current level. */
1161 for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
1162 ADJUST(p);
1163 p = p->fts_link ? p->fts_link : p->fts_parent;
1164 }
1165 }
1166
1167 static size_t
1168 fts_maxarglen(char * const *argv)
1169 {
1170 size_t len, max;
1171
1172 _DIAGASSERT(argv != NULL);
1173
1174 for (max = 0; *argv; ++argv)
1175 if ((len = strlen(*argv)) > max)
1176 max = len;
1177 return (max + 1);
1178 }
1179
1180 /*
1181 * Change to dir specified by fd or p->fts_accpath without getting
1182 * tricked by someone changing the world out from underneath us.
1183 * Assumes p->fts_dev and p->fts_ino are filled in.
1184 */
1185 static int
1186 fts_safe_changedir(const FTS *sp, const FTSENT *p, int fd, const char *path)
1187 {
1188 int oldfd = fd, ret = -1;
1189 __fts_stat_t sb;
1190
1191 if (ISSET(FTS_NOCHDIR))
1192 return 0;
1193
1194 if (oldfd < 0 && (fd = open(path, O_RDONLY)) == -1)
1195 return -1;
1196
1197 if (fstat(fd, &sb) == -1)
1198 goto bail;
1199
1200 if (sb.st_ino != p->fts_ino || sb.st_dev != p->fts_dev) {
1201 errno = ENOENT;
1202 goto bail;
1203 }
1204
1205 ret = fchdir(fd);
1206
1207 bail:
1208 if (oldfd < 0) {
1209 int save_errno = errno;
1210 (void)close(fd);
1211 errno = save_errno;
1212 }
1213 return ret;
1214 }
1215