*** empty log message ***
[coreutils.git] / lib / fts.c
blob1e8e5cc8f6ab3999fe8418393839f46535364e15
1 /*-
2 * Copyright (c) 1990, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
34 #if defined(LIBC_SCCS) && !defined(lint)
35 static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
36 #endif /* LIBC_SCCS and not lint */
38 #if HAVE_SYS_PARAM_H || defined _LIBC
39 # include <sys/param.h>
40 #endif
41 #ifdef _LIBC
42 # include <include/sys/stat.h>
43 #else
44 # include <sys/stat.h>
45 # undef __P
46 # define __P(x) x
47 #endif
48 #include <fcntl.h>
49 #include <errno.h>
50 #include "fts_.h"
51 #include <stdlib.h>
52 #include <string.h>
53 #include <unistd.h>
54 #if HAVE_INTTYPES_H
55 # include <inttypes.h>
56 #endif
58 #if defined _LIBC
59 # include <dirent.h>
60 # define NAMLEN(dirent) _D_EXACT_NAMLEN (dirent)
61 #else
62 # if HAVE_DIRENT_H
63 # include <dirent.h>
64 # define NAMLEN(dirent) strlen ((dirent)->d_name)
65 # else
66 # define dirent direct
67 # define NAMLEN(dirent) (dirent)->d_namlen
68 # if HAVE_SYS_NDIR_H
69 # include <sys/ndir.h>
70 # endif
71 # if HAVE_SYS_DIR_H
72 # include <sys/dir.h>
73 # endif
74 # if HAVE_NDIR_H
75 # include <ndir.h>
76 # endif
77 # endif
78 #endif
80 #ifdef _LIBC
81 # undef close
82 # define close __close
83 # undef closedir
84 # define closedir __closedir
85 # undef fchdir
86 # define fchdir __fchdir
87 # undef open
88 # define open __open
89 # undef opendir
90 # define opendir __opendir
91 # undef readdir
92 # define readdir __readdir
93 #else
94 # undef internal_function
95 # define internal_function /* empty */
96 #endif
98 /* Arrange to make lstat calls go through the wrapper function
99 on systems with an lstat function that does not dereference symlinks
100 that are specified with a trailing slash. */
101 #if ! _LIBC && ! LSTAT_FOLLOWS_SLASHED_SYMLINK
102 int rpl_lstat (const char *, struct stat *);
103 # undef lstat
104 # define lstat(Name, Stat_buf) rpl_lstat(Name, Stat_buf)
105 #endif
107 #ifndef __set_errno
108 # define __set_errno(Val) errno = (Val)
109 #endif
111 /* Largest alignment size needed, minus one.
112 Usually long double is the worst case. */
113 # if __GNUC__ >= 2
114 # define ALIGNBYTES (__alignof__ (long double) - 1)
115 #else
116 # define ALIGNBYTES (sizeof (long double) - 1)
117 #endif
118 /* Align P to that size. */
119 #ifndef ALIGN
120 # define ALIGN(p) (((unsigned long int) (p) + ALIGNBYTES) & ~ALIGNBYTES)
121 #endif
124 static FTSENT *fts_alloc __P((FTS *, const char *, int)) internal_function;
125 static FTSENT *fts_build __P((FTS *, int)) internal_function;
126 static void fts_lfree __P((FTSENT *)) internal_function;
127 static void fts_load __P((FTS *, FTSENT *)) internal_function;
128 static size_t fts_maxarglen __P((char * const *)) internal_function;
129 static void fts_padjust __P((FTS *, FTSENT *)) internal_function;
130 static int fts_palloc __P((FTS *, size_t)) internal_function;
131 static FTSENT *fts_sort __P((FTS *, FTSENT *, int)) internal_function;
132 static u_short fts_stat __P((FTS *, FTSENT *, int)) internal_function;
133 static int fts_safe_changedir __P((FTS *, FTSENT *, int, const char *))
134 internal_function;
136 #ifndef MAX
137 # define MAX(a,b) ((a) > (b) ? (a) : (b))
138 #endif
140 #define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
142 #define CLR(opt) (sp->fts_options &= ~(opt))
143 #define ISSET(opt) (sp->fts_options & (opt))
144 #define SET(opt) (sp->fts_options |= (opt))
146 #define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd))
148 /* fts_build flags */
149 #define BCHILD 1 /* fts_children */
150 #define BNAMES 2 /* fts_children, names only */
151 #define BREAD 3 /* fts_read */
153 #define HT_INITIAL_SIZE 31
155 #if FTS_DEBUG
156 int fts_debug = 0;
157 # include <stdio.h>
158 # define Dprintf(x) do { if (fts_debug) printf x; } while (0)
159 #else
160 # define Dprintf(x)
161 #endif
163 #define ENTER_DIR(Fts, Ent, Tag) \
164 do { \
165 Dprintf ((" %s-entering: %s\n", Tag, (Ent)->fts_path)); \
166 enter_dir (sp, p); \
167 } while (0)
169 #define LEAVE_DIR(Fts, Ent, Tag) \
170 do { \
171 Dprintf ((" %s-leaving: %s\n", Tag, (Ent)->fts_path)); \
172 leave_dir (sp, p); \
173 } while (0)
175 /* Use these each of these to map a device/inode pair to an FTSENT. */
176 struct Active_dir
178 dev_t dev;
179 ino_t ino;
180 FTSENT *fts_ent;
183 static bool
184 AD_compare (void const *x, void const *y)
186 struct Active_dir const *ax = x;
187 struct Active_dir const *ay = y;
188 return ax->ino == ay->ino
189 && ax->dev == ay->dev;
192 static size_t
193 AD_hash (void const *x, size_t table_size)
195 struct Active_dir const *ax = x;
196 return (uintmax_t) ax->ino % table_size;
199 static void
200 enter_dir (FTS *fts, FTSENT *ent)
202 if (fts->active_dir_ht)
204 struct stat const *st = ent->fts_statp;
205 struct Active_dir *ad = malloc (sizeof (struct Active_dir));
206 struct Active_dir *ad_from_table;
208 if (ad == NULL)
209 goto give_up;
211 ad->dev = st->st_dev;
212 ad->ino = st->st_ino;
213 ad->fts_ent = ent;
215 /* See if we've already encountered this directory.
216 This can happen when following symlinks as well as
217 with a corrupted directory hierarchy. */
218 ad_from_table = hash_insert (fts->active_dir_ht, ad);
220 if (ad_from_table == NULL)
222 give_up:
223 /* Insertion failed due to lack of memory. Free the hash
224 table and turn off this sort of cycle detection. */
225 hash_free (fts->active_dir_ht);
226 fts->active_dir_ht = NULL;
227 return;
230 if (ad_from_table != ad)
232 /* There was an entry with matching dev/inode already in the table.
233 Record the fact that we've found a cycle. */
234 ent->fts_cycle = ad_from_table->fts_ent;
235 ent->fts_info = FTS_DC;
237 /* ad was not inserted, so free it. */
238 free (ad);
241 else if (fts->cycle_state)
243 if (cycle_check (fts->cycle_state, ent->fts_statp))
245 /* FIXME: setting fts_cycle like this isn't proper.
246 To do what the documentation requires, we'd have to
247 go around the cycle again and find the right entry.
248 But no callers in coreutils use the fts_cycle member. */
249 ent->fts_cycle = ent;
250 ent->fts_info = FTS_DC;
255 static void
256 leave_dir (FTS *fts, FTSENT *ent)
258 if (fts->active_dir_ht)
260 struct stat const *st = ent->fts_statp;
261 struct Active_dir obj;
262 void *found;
263 obj.dev = st->st_dev;
264 obj.ino = st->st_ino;
265 found = hash_delete (fts->active_dir_ht, &obj);
266 if (!found)
267 abort ();
268 free (found);
272 FTS *
273 fts_open(argv, options, compar)
274 char * const *argv;
275 register int options;
276 int (*compar) __P((const FTSENT **, const FTSENT **));
278 register FTS *sp;
279 register FTSENT *p, *root;
280 register int nitems;
281 FTSENT *parent, *tmp = NULL; /* pacify gcc */
282 int len;
284 /* Options check. */
285 if (options & ~FTS_OPTIONMASK) {
286 __set_errno (EINVAL);
287 return (NULL);
290 /* Allocate/initialize the stream */
291 if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
292 return (NULL);
293 memset(sp, 0, sizeof(FTS));
294 sp->fts_compar = (int (*) __P((const void *, const void *))) compar;
295 sp->fts_options = options;
297 /* Logical walks turn on NOCHDIR; symbolic links are too hard. */
298 if (ISSET(FTS_LOGICAL))
299 SET(FTS_NOCHDIR);
302 * Start out with 1K of path space, and enough, in any case,
303 * to hold the user's paths.
305 #ifndef MAXPATHLEN
306 # define MAXPATHLEN 1024
307 #endif
308 if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
309 goto mem1;
311 /* Allocate/initialize root's parent. */
312 if ((parent = fts_alloc(sp, "", 0)) == NULL)
313 goto mem2;
314 parent->fts_level = FTS_ROOTPARENTLEVEL;
316 /* Allocate/initialize root(s). */
317 for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
318 /* Don't allow zero-length paths. */
319 if ((len = strlen(*argv)) == 0) {
320 __set_errno (ENOENT);
321 goto mem3;
324 if ((p = fts_alloc(sp, *argv, len)) == NULL)
325 goto mem3;
326 p->fts_level = FTS_ROOTLEVEL;
327 p->fts_parent = parent;
328 p->fts_accpath = p->fts_name;
329 p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
331 /* Command-line "." and ".." are real directories. */
332 if (p->fts_info == FTS_DOT)
333 p->fts_info = FTS_D;
336 * If comparison routine supplied, traverse in sorted
337 * order; otherwise traverse in the order specified.
339 if (compar) {
340 p->fts_link = root;
341 root = p;
342 } else {
343 p->fts_link = NULL;
344 if (root == NULL)
345 tmp = root = p;
346 else {
347 tmp->fts_link = p;
348 tmp = p;
352 if (compar && nitems > 1)
353 root = fts_sort(sp, root, nitems);
356 * Allocate a dummy pointer and make fts_read think that we've just
357 * finished the node before the root(s); set p->fts_info to FTS_INIT
358 * so that everything about the "current" node is ignored.
360 if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
361 goto mem3;
362 sp->fts_cur->fts_link = root;
363 sp->fts_cur->fts_info = FTS_INIT;
365 if (ISSET (FTS_TIGHT_CYCLE_CHECK))
367 sp->active_dir_ht = hash_initialize (HT_INITIAL_SIZE,
368 NULL, AD_hash,
369 AD_compare, free);
370 if (sp->active_dir_ht == NULL)
371 goto mem3;
372 sp->cycle_state = malloc (sizeof *sp->cycle_state);
374 else
376 sp->cycle_state = malloc (sizeof *sp->cycle_state);
377 if (sp->cycle_state == NULL)
378 goto mem3;
379 cycle_check_init (sp->cycle_state);
380 sp->active_dir_ht = NULL;
384 * If using chdir(2), grab a file descriptor pointing to dot to ensure
385 * that we can get back here; this could be avoided for some paths,
386 * but almost certainly not worth the effort. Slashes, symbolic links,
387 * and ".." are all fairly nasty problems. Note, if we can't get the
388 * descriptor we run anyway, just more slowly.
390 if (!ISSET(FTS_NOCHDIR)
391 && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0)
392 SET(FTS_NOCHDIR);
394 return (sp);
396 mem3: fts_lfree(root);
397 free(parent);
398 mem2: free(sp->fts_path);
399 mem1: free(sp);
400 return (NULL);
403 static void
404 internal_function
405 fts_load(sp, p)
406 FTS *sp;
407 register FTSENT *p;
409 register int len;
410 register char *cp;
413 * Load the stream structure for the next traversal. Since we don't
414 * actually enter the directory until after the preorder visit, set
415 * the fts_accpath field specially so the chdir gets done to the right
416 * place and the user can access the first node. From fts_open it's
417 * known that the path will fit.
419 len = p->fts_pathlen = p->fts_namelen;
420 memmove(sp->fts_path, p->fts_name, len + 1);
421 if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
422 len = strlen(++cp);
423 memmove(p->fts_name, cp, len + 1);
424 p->fts_namelen = len;
426 p->fts_accpath = p->fts_path = sp->fts_path;
427 sp->fts_dev = p->fts_dev;
431 fts_close(sp)
432 FTS *sp;
434 register FTSENT *freep, *p;
435 int saved_errno = 0;
438 * This still works if we haven't read anything -- the dummy structure
439 * points to the root list, so we step through to the end of the root
440 * list which has a valid parent pointer.
442 if (sp->fts_cur) {
443 for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
444 freep = p;
445 p = p->fts_link != NULL ? p->fts_link : p->fts_parent;
446 free(freep);
448 free(p);
451 /* Free up child linked list, sort array, path buffer. */
452 if (sp->fts_child)
453 fts_lfree(sp->fts_child);
454 if (sp->fts_array)
455 free(sp->fts_array);
456 free(sp->fts_path);
458 /* Return to original directory, save errno if necessary. */
459 if (!ISSET(FTS_NOCHDIR)) {
460 if (fchdir(sp->fts_rfd))
461 saved_errno = errno;
462 (void)close(sp->fts_rfd);
465 /* Free any memory used for cycle detection. */
466 if (sp->active_dir_ht)
467 hash_free (sp->active_dir_ht);
468 if (sp->cycle_state)
469 free (sp->cycle_state);
471 /* Free up the stream pointer. */
472 free(sp);
474 /* Set errno and return. */
475 if (saved_errno) {
476 __set_errno (saved_errno);
477 return (-1);
480 return (0);
484 * Special case of "/" at the end of the path so that slashes aren't
485 * appended which would cause paths to be written as "....//foo".
487 #define NAPPEND(p) \
488 (p->fts_path[p->fts_pathlen - 1] == '/' \
489 ? p->fts_pathlen - 1 : p->fts_pathlen)
491 FTSENT *
492 fts_read(sp)
493 register FTS *sp;
495 register FTSENT *p, *tmp;
496 register int instr;
497 register char *t;
498 int saved_errno;
500 /* If finished or unrecoverable error, return NULL. */
501 if (sp->fts_cur == NULL || ISSET(FTS_STOP))
502 return (NULL);
504 /* Set current node pointer. */
505 p = sp->fts_cur;
507 /* Save and zero out user instructions. */
508 instr = p->fts_instr;
509 p->fts_instr = FTS_NOINSTR;
511 /* Any type of file may be re-visited; re-stat and re-turn. */
512 if (instr == FTS_AGAIN) {
513 p->fts_info = fts_stat(sp, p, 0);
514 return (p);
516 Dprintf (("fts_read: p=%s\n",
517 p->fts_info == FTS_INIT ? "" : p->fts_path));
520 * Following a symlink -- SLNONE test allows application to see
521 * SLNONE and recover. If indirecting through a symlink, have
522 * keep a pointer to current location. If unable to get that
523 * pointer, follow fails.
525 if (instr == FTS_FOLLOW &&
526 (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
527 p->fts_info = fts_stat(sp, p, 1);
528 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
529 if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) {
530 p->fts_errno = errno;
531 p->fts_info = FTS_ERR;
532 } else
533 p->fts_flags |= FTS_SYMFOLLOW;
535 if (p->fts_info == FTS_D)
536 ENTER_DIR (sp, p, "7");
537 return (p);
540 /* Directory in pre-order. */
541 if (p->fts_info == FTS_D) {
542 /* If skipped or crossed mount point, do post-order visit. */
543 if (instr == FTS_SKIP ||
544 (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
545 if (p->fts_flags & FTS_SYMFOLLOW)
546 (void)close(p->fts_symfd);
547 if (sp->fts_child) {
548 fts_lfree(sp->fts_child);
549 sp->fts_child = NULL;
551 p->fts_info = FTS_DP;
552 LEAVE_DIR (sp, p, "1");
553 return (p);
556 /* Rebuild if only read the names and now traversing. */
557 if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {
558 CLR(FTS_NAMEONLY);
559 fts_lfree(sp->fts_child);
560 sp->fts_child = NULL;
564 * Cd to the subdirectory.
566 * If have already read and now fail to chdir, whack the list
567 * to make the names come out right, and set the parent errno
568 * so the application will eventually get an error condition.
569 * Set the FTS_DONTCHDIR flag so that when we logically change
570 * directories back to the parent we don't do a chdir.
572 * If haven't read do so. If the read fails, fts_build sets
573 * FTS_STOP or the fts_info field of the node.
575 if (sp->fts_child != NULL) {
576 if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
577 p->fts_errno = errno;
578 p->fts_flags |= FTS_DONTCHDIR;
579 for (p = sp->fts_child; p != NULL;
580 p = p->fts_link)
581 p->fts_accpath =
582 p->fts_parent->fts_accpath;
584 } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
585 if (ISSET(FTS_STOP))
586 return (NULL);
587 /* If fts_build's call to fts_safe_changedir failed
588 because it was not able to fchdir into a
589 subdirectory, tell the caller. */
590 if (p->fts_errno)
591 p->fts_info = FTS_ERR;
592 /* FIXME: see if this should be in an else block */
593 LEAVE_DIR (sp, p, "2");
594 return (p);
596 p = sp->fts_child;
597 sp->fts_child = NULL;
598 goto name;
601 /* Move to the next node on this level. */
602 next: tmp = p;
603 if ((p = p->fts_link) != NULL) {
604 free(tmp);
607 * If reached the top, return to the original directory (or
608 * the root of the tree), and load the paths for the next root.
610 if (p->fts_level == FTS_ROOTLEVEL) {
611 if (FCHDIR(sp, sp->fts_rfd)) {
612 SET(FTS_STOP);
613 return (NULL);
615 fts_load(sp, p);
616 if (p->fts_info == FTS_D)
617 ENTER_DIR (sp, p, "8");
618 return (sp->fts_cur = p);
622 * User may have called fts_set on the node. If skipped,
623 * ignore. If followed, get a file descriptor so we can
624 * get back if necessary.
626 if (p->fts_instr == FTS_SKIP)
627 goto next;
628 if (p->fts_instr == FTS_FOLLOW) {
629 p->fts_info = fts_stat(sp, p, 1);
630 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
631 if ((p->fts_symfd =
632 open(".", O_RDONLY, 0)) < 0) {
633 p->fts_errno = errno;
634 p->fts_info = FTS_ERR;
635 } else
636 p->fts_flags |= FTS_SYMFOLLOW;
638 p->fts_instr = FTS_NOINSTR;
641 name: t = sp->fts_path + NAPPEND(p->fts_parent);
642 *t++ = '/';
643 memmove(t, p->fts_name, p->fts_namelen + 1);
644 if (p->fts_info == FTS_D)
645 ENTER_DIR (sp, p, "9");
646 return (sp->fts_cur = p);
649 /* Move up to the parent node. */
650 p = tmp->fts_parent;
651 free(tmp);
653 if (p->fts_level == FTS_ROOTPARENTLEVEL) {
655 * Done; free everything up and set errno to 0 so the user
656 * can distinguish between error and EOF.
658 free(p);
659 __set_errno (0);
660 return (sp->fts_cur = NULL);
663 /* NUL terminate the pathname. */
664 sp->fts_path[p->fts_pathlen] = '\0';
667 * Return to the parent directory. If at a root node or came through
668 * a symlink, go back through the file descriptor. Otherwise, cd up
669 * one directory.
671 if (p->fts_level == FTS_ROOTLEVEL) {
672 if (FCHDIR(sp, sp->fts_rfd)) {
673 SET(FTS_STOP);
674 return (NULL);
676 } else if (p->fts_flags & FTS_SYMFOLLOW) {
677 if (FCHDIR(sp, p->fts_symfd)) {
678 saved_errno = errno;
679 (void)close(p->fts_symfd);
680 __set_errno (saved_errno);
681 SET(FTS_STOP);
682 return (NULL);
684 (void)close(p->fts_symfd);
685 } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
686 fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
687 SET(FTS_STOP);
688 return (NULL);
690 p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
691 if (p->fts_errno == 0)
692 LEAVE_DIR (sp, p, "3");
693 return (sp->fts_cur = p);
697 * Fts_set takes the stream as an argument although it's not used in this
698 * implementation; it would be necessary if anyone wanted to add global
699 * semantics to fts using fts_set. An error return is allowed for similar
700 * reasons.
702 /* ARGSUSED */
704 fts_set(sp, p, instr)
705 FTS *sp;
706 FTSENT *p;
707 int instr;
709 if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
710 instr != FTS_NOINSTR && instr != FTS_SKIP) {
711 __set_errno (EINVAL);
712 return (1);
714 p->fts_instr = instr;
715 return (0);
718 FTSENT *
719 fts_children(sp, instr)
720 register FTS *sp;
721 int instr;
723 register FTSENT *p;
724 int fd;
726 if (instr != 0 && instr != FTS_NAMEONLY) {
727 __set_errno (EINVAL);
728 return (NULL);
731 /* Set current node pointer. */
732 p = sp->fts_cur;
735 * Errno set to 0 so user can distinguish empty directory from
736 * an error.
738 __set_errno (0);
740 /* Fatal errors stop here. */
741 if (ISSET(FTS_STOP))
742 return (NULL);
744 /* Return logical hierarchy of user's arguments. */
745 if (p->fts_info == FTS_INIT)
746 return (p->fts_link);
749 * If not a directory being visited in pre-order, stop here. Could
750 * allow FTS_DNR, assuming the user has fixed the problem, but the
751 * same effect is available with FTS_AGAIN.
753 if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
754 return (NULL);
756 /* Free up any previous child list. */
757 if (sp->fts_child != NULL)
758 fts_lfree(sp->fts_child);
760 if (instr == FTS_NAMEONLY) {
761 SET(FTS_NAMEONLY);
762 instr = BNAMES;
763 } else
764 instr = BCHILD;
767 * If using chdir on a relative path and called BEFORE fts_read does
768 * its chdir to the root of a traversal, we can lose -- we need to
769 * chdir into the subdirectory, and we don't know where the current
770 * directory is, so we can't get back so that the upcoming chdir by
771 * fts_read will work.
773 if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
774 ISSET(FTS_NOCHDIR))
775 return (sp->fts_child = fts_build(sp, instr));
777 if ((fd = open(".", O_RDONLY, 0)) < 0)
778 return (sp->fts_child = NULL);
779 sp->fts_child = fts_build(sp, instr);
780 if (fchdir(fd)) {
781 (void)close(fd);
782 return (NULL);
784 (void)close(fd);
785 return (sp->fts_child);
789 * This is the tricky part -- do not casually change *anything* in here. The
790 * idea is to build the linked list of entries that are used by fts_children
791 * and fts_read. There are lots of special cases.
793 * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is
794 * set and it's a physical walk (so that symbolic links can't be directories),
795 * we can do things quickly. First, if it's a 4.4BSD file system, the type
796 * of the file is in the directory entry. Otherwise, we assume that the number
797 * of subdirectories in a node is equal to the number of links to the parent.
798 * The former skips all stat calls. The latter skips stat calls in any leaf
799 * directories and for any files after the subdirectories in the directory have
800 * been found, cutting the stat calls by about 2/3.
802 static FTSENT *
803 internal_function
804 fts_build(sp, type)
805 register FTS *sp;
806 int type;
808 register struct dirent *dp;
809 register FTSENT *p, *head;
810 register int nitems;
811 FTSENT *cur, *tail;
812 DIR *dirp;
813 void *oldaddr;
814 int cderrno, descend, level, nlinks, saved_errno,
815 nostat, doadjust;
816 size_t len, maxlen, new_len;
817 char *cp;
819 /* Set current node pointer. */
820 cur = sp->fts_cur;
823 * Open the directory for reading. If this fails, we're done.
824 * If being called from fts_read, set the fts_info field.
826 #if defined FTS_WHITEOUT && 0
827 if (ISSET(FTS_WHITEOUT))
828 oflag = DTF_NODUP|DTF_REWIND;
829 else
830 oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
831 #else
832 # define __opendir2(path, flag) opendir(path)
833 #endif
834 if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
835 if (type == BREAD) {
836 cur->fts_info = FTS_DNR;
837 cur->fts_errno = errno;
839 return (NULL);
843 * Nlinks is the number of possible entries of type directory in the
844 * directory if we're cheating on stat calls, 0 if we're not doing
845 * any stat calls at all, -1 if we're doing stats on everything.
847 if (type == BNAMES) {
848 nlinks = 0;
849 /* Be quiet about nostat, GCC. */
850 nostat = 0;
851 } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
852 nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
853 nostat = 1;
854 } else {
855 nlinks = -1;
856 nostat = 0;
859 #ifdef notdef
860 (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
861 (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
862 ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
863 #endif
865 * If we're going to need to stat anything or we want to descend
866 * and stay in the directory, chdir. If this fails we keep going,
867 * but set a flag so we don't chdir after the post-order visit.
868 * We won't be able to stat anything, but we can still return the
869 * names themselves. Note, that since fts_read won't be able to
870 * chdir into the directory, it will have to return different path
871 * names than before, i.e. "a/b" instead of "b". Since the node
872 * has already been visited in pre-order, have to wait until the
873 * post-order visit to return the error. There is a special case
874 * here, if there was nothing to stat then it's not an error to
875 * not be able to stat. This is all fairly nasty. If a program
876 * needed sorted entries or stat information, they had better be
877 * checking FTS_NS on the returned nodes.
879 cderrno = 0;
880 if (nlinks || type == BREAD) {
881 if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
882 if (nlinks && type == BREAD)
883 cur->fts_errno = errno;
884 cur->fts_flags |= FTS_DONTCHDIR;
885 descend = 0;
886 cderrno = errno;
887 (void)closedir(dirp);
888 dirp = NULL;
889 } else
890 descend = 1;
891 } else
892 descend = 0;
895 * Figure out the max file name length that can be stored in the
896 * current path -- the inner loop allocates more path as necessary.
897 * We really wouldn't have to do the maxlen calculations here, we
898 * could do them in fts_read before returning the path, but it's a
899 * lot easier here since the length is part of the dirent structure.
901 * If not changing directories set a pointer so that can just append
902 * each new name into the path.
904 len = NAPPEND(cur);
905 if (ISSET(FTS_NOCHDIR)) {
906 cp = sp->fts_path + len;
907 *cp++ = '/';
908 } else {
909 /* GCC, you're too verbose. */
910 cp = NULL;
912 len++;
913 maxlen = sp->fts_pathlen - len;
915 level = cur->fts_level + 1;
917 /* Read the directory, attaching each entry to the `link' pointer. */
918 doadjust = 0;
919 for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) {
920 if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
921 continue;
923 if ((p = fts_alloc(sp, dp->d_name, (int)NAMLEN (dp))) == NULL)
924 goto mem1;
925 if (NAMLEN (dp) >= maxlen) {/* include space for NUL */
926 oldaddr = sp->fts_path;
927 if (fts_palloc(sp, NAMLEN (dp) + len + 1)) {
929 * No more memory for path or structures. Save
930 * errno, free up the current structure and the
931 * structures already allocated.
933 mem1: saved_errno = errno;
934 if (p)
935 free(p);
936 fts_lfree(head);
937 (void)closedir(dirp);
938 cur->fts_info = FTS_ERR;
939 SET(FTS_STOP);
940 __set_errno (saved_errno);
941 return (NULL);
943 /* Did realloc() change the pointer? */
944 if (oldaddr != sp->fts_path) {
945 doadjust = 1;
946 if (ISSET(FTS_NOCHDIR))
947 cp = sp->fts_path + len;
949 maxlen = sp->fts_pathlen - len;
952 new_len = len + NAMLEN (dp);
953 if (new_len < len) {
955 * In the unlikely even that we would end up
956 * with a path longer than SIZE_MAX, free up
957 * the current structure and the structures already
958 * allocated, then error out with ENAMETOOLONG.
960 free(p);
961 fts_lfree(head);
962 (void)closedir(dirp);
963 cur->fts_info = FTS_ERR;
964 SET(FTS_STOP);
965 __set_errno (ENAMETOOLONG);
966 return (NULL);
968 p->fts_level = level;
969 p->fts_parent = sp->fts_cur;
970 p->fts_pathlen = new_len;
972 #if defined FTS_WHITEOUT && 0
973 if (dp->d_type == DT_WHT)
974 p->fts_flags |= FTS_ISW;
975 #endif
977 if (cderrno) {
978 if (nlinks) {
979 p->fts_info = FTS_NS;
980 p->fts_errno = cderrno;
981 } else
982 p->fts_info = FTS_NSOK;
983 p->fts_accpath = cur->fts_accpath;
984 } else if (nlinks == 0
985 # if HAVE_STRUCT_DIRENT_D_TYPE
986 || (nostat &&
987 dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
988 #endif
990 p->fts_accpath =
991 ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
992 p->fts_info = FTS_NSOK;
993 } else {
994 /* Build a file name for fts_stat to stat. */
995 if (ISSET(FTS_NOCHDIR)) {
996 p->fts_accpath = p->fts_path;
997 memmove(cp, p->fts_name, p->fts_namelen + 1);
998 } else
999 p->fts_accpath = p->fts_name;
1000 /* Stat it. */
1001 p->fts_info = fts_stat(sp, p, 0);
1003 /* Decrement link count if applicable. */
1004 if (nlinks > 0 && (p->fts_info == FTS_D ||
1005 p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
1006 --nlinks;
1009 /* We walk in directory order so "ls -f" doesn't get upset. */
1010 p->fts_link = NULL;
1011 if (head == NULL)
1012 head = tail = p;
1013 else {
1014 tail->fts_link = p;
1015 tail = p;
1017 ++nitems;
1019 if (dirp)
1020 (void)closedir(dirp);
1023 * If realloc() changed the address of the path, adjust the
1024 * addresses for the rest of the tree and the dir list.
1026 if (doadjust)
1027 fts_padjust(sp, head);
1030 * If not changing directories, reset the path back to original
1031 * state.
1033 if (ISSET(FTS_NOCHDIR)) {
1034 if (len == sp->fts_pathlen || nitems == 0)
1035 --cp;
1036 *cp = '\0';
1040 * If descended after called from fts_children or after called from
1041 * fts_read and nothing found, get back. At the root level we use
1042 * the saved fd; if one of fts_open()'s arguments is a relative path
1043 * to an empty directory, we wind up here with no other way back. If
1044 * can't get back, we're done.
1046 if (descend && (type == BCHILD || !nitems) &&
1047 (cur->fts_level == FTS_ROOTLEVEL ?
1048 FCHDIR(sp, sp->fts_rfd) :
1049 fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
1050 cur->fts_info = FTS_ERR;
1051 SET(FTS_STOP);
1052 return (NULL);
1055 /* If didn't find anything, return NULL. */
1056 if (!nitems) {
1057 if (type == BREAD)
1058 cur->fts_info = FTS_DP;
1059 return (NULL);
1062 /* Sort the entries. */
1063 if (sp->fts_compar && nitems > 1)
1064 head = fts_sort(sp, head, nitems);
1065 return (head);
1068 #if FTS_DEBUG
1070 /* Walk ->fts_parent links starting at E_CURR, until the root of the
1071 current hierarchy. There should be a directory with dev/inode
1072 matching those of AD. If not, print a lot of diagnostics. */
1073 static void
1074 find_matching_ancestor (FTSENT const *e_curr, struct Active_dir const *ad)
1076 FTSENT const *ent;
1077 for (ent = e_curr; ent->fts_level >= FTS_ROOTLEVEL; ent = ent->fts_parent)
1079 if (ad->ino == ent->fts_statp->st_ino
1080 && ad->dev == ent->fts_statp->st_dev)
1081 return;
1083 printf ("ERROR: tree dir, %s, not active\n", ad->fts_ent->fts_accpath);
1084 printf ("active dirs:\n");
1085 for (ent = e_curr;
1086 ent->fts_level >= FTS_ROOTLEVEL; ent = ent->fts_parent)
1087 printf (" %s(%d/%d) to %s(%d/%d)...\n",
1088 ad->fts_ent->fts_accpath,
1089 (int)ad->dev,
1090 (int)ad->ino,
1091 ent->fts_accpath,
1092 (int)ent->fts_statp->st_dev,
1093 (int)ent->fts_statp->st_ino);
1096 void
1097 fts_cross_check (FTS const *sp)
1099 FTSENT const *ent = sp->fts_cur;
1100 FTSENT const *t;
1101 if ( ! ISSET (FTS_TIGHT_CYCLE_CHECK))
1102 return;
1104 Dprintf (("fts-cross-check cur=%s\n", ent->fts_path));
1105 /* Make sure every parent dir is in the tree. */
1106 for (t = ent->fts_parent; t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
1108 struct Active_dir ad;
1109 ad.ino = t->fts_statp->st_ino;
1110 ad.dev = t->fts_statp->st_dev;
1111 if ( ! hash_lookup (sp->active_dir_ht, &ad))
1112 printf ("ERROR: active dir, %s, not in tree\n", t->fts_path);
1115 /* Make sure every dir in the tree is an active dir.
1116 But ENT is not necessarily a directory. If so, just skip this part. */
1117 if (ent->fts_parent->fts_level >= FTS_ROOTLEVEL
1118 && (ent->fts_info == FTS_DP
1119 || ent->fts_info == FTS_D))
1121 struct Active_dir *ad;
1122 for (ad = hash_get_first (sp->active_dir_ht); ad != NULL;
1123 ad = hash_get_next (sp->active_dir_ht, ad))
1125 find_matching_ancestor (ent, ad);
1129 #endif
1131 static u_short
1132 internal_function
1133 fts_stat(sp, p, follow)
1134 FTS *sp;
1135 register FTSENT *p;
1136 int follow;
1138 struct stat *sbp, sb;
1139 int saved_errno;
1141 /* If user needs stat info, stat buffer already allocated. */
1142 sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
1144 #if defined FTS_WHITEOUT && 0
1145 /* check for whiteout */
1146 if (p->fts_flags & FTS_ISW) {
1147 if (sbp != &sb) {
1148 memset(sbp, '\0', sizeof (*sbp));
1149 sbp->st_mode = S_IFWHT;
1151 return (FTS_W);
1153 #endif
1156 * If doing a logical walk, or application requested FTS_FOLLOW, do
1157 * a stat(2). If that fails, check for a non-existent symlink. If
1158 * fail, set the errno from the stat call.
1160 if (ISSET(FTS_LOGICAL) || follow) {
1161 if (stat(p->fts_accpath, sbp)) {
1162 saved_errno = errno;
1163 if (!lstat(p->fts_accpath, sbp)) {
1164 __set_errno (0);
1165 return (FTS_SLNONE);
1167 p->fts_errno = saved_errno;
1168 goto err;
1170 } else if (lstat(p->fts_accpath, sbp)) {
1171 p->fts_errno = errno;
1172 err: memset(sbp, 0, sizeof(struct stat));
1173 return (FTS_NS);
1176 if (S_ISDIR(sbp->st_mode)) {
1178 * Set the device/inode. Used to find cycles and check for
1179 * crossing mount points. Also remember the link count, used
1180 * in fts_build to limit the number of stat calls. It is
1181 * understood that these fields are only referenced if fts_info
1182 * is set to FTS_D.
1184 p->fts_dev = sbp->st_dev;
1185 p->fts_ino = sbp->st_ino;
1186 p->fts_nlink = sbp->st_nlink;
1188 if (ISDOT(p->fts_name))
1189 return (FTS_DOT);
1191 return (FTS_D);
1193 if (S_ISLNK(sbp->st_mode))
1194 return (FTS_SL);
1195 if (S_ISREG(sbp->st_mode))
1196 return (FTS_F);
1197 return (FTS_DEFAULT);
1200 static FTSENT *
1201 internal_function
1202 fts_sort(sp, head, nitems)
1203 FTS *sp;
1204 FTSENT *head;
1205 register int nitems;
1207 register FTSENT **ap, *p;
1210 * Construct an array of pointers to the structures and call qsort(3).
1211 * Reassemble the array in the order returned by qsort. If unable to
1212 * sort for memory reasons, return the directory entries in their
1213 * current order. Allocate enough space for the current needs plus
1214 * 40 so don't realloc one entry at a time.
1216 if (nitems > sp->fts_nitems) {
1217 struct _ftsent **a;
1219 sp->fts_nitems = nitems + 40;
1220 if ((a = realloc(sp->fts_array,
1221 (size_t)(sp->fts_nitems * sizeof(FTSENT *)))) == NULL) {
1222 free(sp->fts_array);
1223 sp->fts_array = NULL;
1224 sp->fts_nitems = 0;
1225 return (head);
1227 sp->fts_array = a;
1229 for (ap = sp->fts_array, p = head; p; p = p->fts_link)
1230 *ap++ = p;
1231 qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
1232 for (head = *(ap = sp->fts_array); --nitems; ++ap)
1233 ap[0]->fts_link = ap[1];
1234 ap[0]->fts_link = NULL;
1235 return (head);
1238 static FTSENT *
1239 internal_function
1240 fts_alloc(sp, name, namelen)
1241 FTS *sp;
1242 const char *name;
1243 register int namelen;
1245 register FTSENT *p;
1246 size_t len;
1249 * The file name is a variable length array and no stat structure is
1250 * necessary if the user has set the nostat bit. Allocate the FTSENT
1251 * structure, the file name and the stat structure in one chunk, but
1252 * be careful that the stat structure is reasonably aligned. Since the
1253 * fts_name field is declared to be of size 1, the fts_name pointer is
1254 * namelen + 2 before the first possible address of the stat structure.
1256 len = sizeof(FTSENT) + namelen;
1257 if (!ISSET(FTS_NOSTAT))
1258 len += sizeof(struct stat) + ALIGNBYTES;
1259 if ((p = malloc(len)) == NULL)
1260 return (NULL);
1262 /* Copy the name and guarantee NUL termination. */
1263 memmove(p->fts_name, name, namelen);
1264 p->fts_name[namelen] = '\0';
1266 if (!ISSET(FTS_NOSTAT))
1267 p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
1268 p->fts_namelen = namelen;
1269 p->fts_path = sp->fts_path;
1270 p->fts_errno = 0;
1271 p->fts_flags = 0;
1272 p->fts_instr = FTS_NOINSTR;
1273 p->fts_number = 0;
1274 p->fts_pointer = NULL;
1275 return (p);
1278 static void
1279 internal_function
1280 fts_lfree(head)
1281 register FTSENT *head;
1283 register FTSENT *p;
1285 /* Free a linked list of structures. */
1286 while ((p = head)) {
1287 head = head->fts_link;
1288 free(p);
1293 * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
1294 * Most systems will allow creation of paths much longer than MAXPATHLEN, even
1295 * though the kernel won't resolve them. Add the size (not just what's needed)
1296 * plus 256 bytes so don't realloc the path 2 bytes at a time.
1298 static int
1299 internal_function
1300 fts_palloc(sp, more)
1301 FTS *sp;
1302 size_t more;
1304 char *p;
1305 size_t new_len = sp->fts_pathlen + more + 256;
1308 * See if fts_pathlen would overflow.
1310 if (new_len < sp->fts_pathlen) {
1311 if (sp->fts_path) {
1312 free(sp->fts_path);
1313 sp->fts_path = NULL;
1315 sp->fts_path = NULL;
1316 __set_errno (ENAMETOOLONG);
1317 return (1);
1319 sp->fts_pathlen = new_len;
1320 p = realloc(sp->fts_path, sp->fts_pathlen);
1321 if (p == NULL) {
1322 free(sp->fts_path);
1323 sp->fts_path = NULL;
1324 return 1;
1326 sp->fts_path = p;
1327 return 0;
1331 * When the path is realloc'd, have to fix all of the pointers in structures
1332 * already returned.
1334 static void
1335 internal_function
1336 fts_padjust(sp, head)
1337 FTS *sp;
1338 FTSENT *head;
1340 FTSENT *p;
1341 char *addr = sp->fts_path;
1343 #define ADJUST(p) do { \
1344 if ((p)->fts_accpath != (p)->fts_name) { \
1345 (p)->fts_accpath = \
1346 (char *)addr + ((p)->fts_accpath - (p)->fts_path); \
1348 (p)->fts_path = addr; \
1349 } while (0)
1350 /* Adjust the current set of children. */
1351 for (p = sp->fts_child; p; p = p->fts_link)
1352 ADJUST(p);
1354 /* Adjust the rest of the tree, including the current level. */
1355 for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
1356 ADJUST(p);
1357 p = p->fts_link ? p->fts_link : p->fts_parent;
1361 static size_t
1362 internal_function
1363 fts_maxarglen(argv)
1364 char * const *argv;
1366 size_t len, max;
1368 for (max = 0; *argv; ++argv)
1369 if ((len = strlen(*argv)) > max)
1370 max = len;
1371 return (max + 1);
1375 * Change to dir specified by fd or p->fts_accpath without getting
1376 * tricked by someone changing the world out from underneath us.
1377 * Assumes p->fts_dev and p->fts_ino are filled in.
1379 static int
1380 internal_function
1381 fts_safe_changedir(sp, p, fd, path)
1382 FTS *sp;
1383 FTSENT *p;
1384 int fd;
1385 const char *path;
1387 int ret, oerrno, newfd;
1388 struct stat sb;
1390 newfd = fd;
1391 if (ISSET(FTS_NOCHDIR))
1392 return (0);
1393 if (fd < 0 && (newfd = open(path, O_RDONLY, 0)) < 0)
1394 return (-1);
1395 if (fstat(newfd, &sb)) {
1396 ret = -1;
1397 goto bail;
1399 if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) {
1400 __set_errno (ENOENT); /* disinformation */
1401 ret = -1;
1402 goto bail;
1404 ret = fchdir(newfd);
1405 bail:
1406 oerrno = errno;
1407 if (fd < 0)
1408 (void)close(newfd);
1409 __set_errno (oerrno);
1410 return (ret);