164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross/*	$OpenBSD: fts.c,v 1.43 2009/08/27 16:19:27 millert Exp $	*/
264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross/*-
464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * Copyright (c) 1990, 1993, 1994
564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross *	The Regents of the University of California.  All rights reserved.
664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross *
764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * Redistribution and use in source and binary forms, with or without
864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * modification, are permitted provided that the following conditions
964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * are met:
1064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * 1. Redistributions of source code must retain the above copyright
1164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross *    notice, this list of conditions and the following disclaimer.
1264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * 2. Redistributions in binary form must reproduce the above copyright
1364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross *    notice, this list of conditions and the following disclaimer in the
1464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross *    documentation and/or other materials provided with the distribution.
1564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * 3. Neither the name of the University nor the names of its contributors
1664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross *    may be used to endorse or promote products derived from this software
1764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross *    without specific prior written permission.
1864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross *
1964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * SUCH DAMAGE.
3064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross */
3164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
3264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#include <sys/param.h>
3364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#include <sys/stat.h>
3464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
3564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#include <dirent.h>
3664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#include <errno.h>
3764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#include <fcntl.h>
3864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#include <fts.h>
3964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#include <stdlib.h>
4064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#include <string.h>
4164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#include <unistd.h>
4264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
4364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#define MAX(a,b) ((a)>(b)?(a):(b))
4464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
4564ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic FTSENT	*fts_alloc(FTS *, char *, size_t);
4664ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic FTSENT	*fts_build(FTS *, int);
4764ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic void	 fts_lfree(FTSENT *);
4864ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic void	 fts_load(FTS *, FTSENT *);
4964ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic size_t	 fts_maxarglen(char * const *);
5064ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic void	 fts_padjust(FTS *, FTSENT *);
5164ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic int	 fts_palloc(FTS *, size_t);
5264ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic FTSENT	*fts_sort(FTS *, FTSENT *, int);
5364ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic u_short	 fts_stat(FTS *, FTSENT *, int);
5464ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic int	 fts_safe_changedir(FTS *, FTSENT *, int, char *);
5564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
5664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#define	ISDOT(a)	(a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
5764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
5864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#define	CLR(opt)	(sp->fts_options &= ~(opt))
5964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#define	ISSET(opt)	(sp->fts_options & (opt))
6064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#define	SET(opt)	(sp->fts_options |= (opt))
6164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
6264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#define	FCHDIR(sp, fd)	(!ISSET(FTS_NOCHDIR) && fchdir(fd))
6364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
6464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross/* fts_build flags */
6564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#define	BCHILD		1		/* fts_children */
6664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#define	BNAMES		2		/* fts_children, names only */
6764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#define	BREAD		3		/* fts_read */
6864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
6964ceac3f493e3063a289aec4a12c74787be974e4Colin CrossFTS *
7064ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_open(char * const *argv, int options,
7164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross    int (*compar)(const FTSENT **, const FTSENT **))
7264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
7364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	FTS *sp;
7464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	FTSENT *p, *root;
7564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	int nitems;
7664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	FTSENT *parent, *tmp;
7764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	size_t len;
7864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
7964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Options check. */
8064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (options & ~FTS_OPTIONMASK) {
8164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		errno = EINVAL;
8264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (NULL);
8364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
8464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
8564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Allocate/initialize the stream */
8664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if ((sp = calloc(1, sizeof(FTS))) == NULL)
8764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (NULL);
8864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	sp->fts_compar = compar;
8964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	sp->fts_options = options;
9064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
9164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Logical walks turn on NOCHDIR; symbolic links are too hard. */
9264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (ISSET(FTS_LOGICAL))
9364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		SET(FTS_NOCHDIR);
9464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
9564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
9664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * Start out with 1K of path space, and enough, in any case,
9764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * to hold the user's paths.
9864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
9964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
10064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		goto mem1;
10164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
10264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Allocate/initialize root's parent. */
10364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if ((parent = fts_alloc(sp, "", 0)) == NULL)
10464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		goto mem2;
10564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	parent->fts_level = FTS_ROOTPARENTLEVEL;
10664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
10764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Allocate/initialize root(s). */
10864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) {
10964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		/* Don't allow zero-length paths. */
11064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if ((len = strlen(*argv)) == 0) {
11164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			errno = ENOENT;
11264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			goto mem3;
11364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
11464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
11564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if ((p = fts_alloc(sp, *argv, len)) == NULL)
11664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			goto mem3;
11764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p->fts_level = FTS_ROOTLEVEL;
11864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p->fts_parent = parent;
11964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p->fts_accpath = p->fts_name;
12064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
12164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
12264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		/* Command-line "." and ".." are real directories. */
12364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (p->fts_info == FTS_DOT)
12464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			p->fts_info = FTS_D;
12564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
12664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		/*
12764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * If comparison routine supplied, traverse in sorted
12864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * order; otherwise traverse in the order specified.
12964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 */
13064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (compar) {
13164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			p->fts_link = root;
13264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			root = p;
13364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		} else {
13464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			p->fts_link = NULL;
13564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (root == NULL)
13664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				tmp = root = p;
13764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			else {
13864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				tmp->fts_link = p;
13964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				tmp = p;
14064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			}
14164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
14264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
14364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (compar && nitems > 1)
14464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		root = fts_sort(sp, root, nitems);
14564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
14664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
14764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * Allocate a dummy pointer and make fts_read think that we've just
14864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * finished the node before the root(s); set p->fts_info to FTS_INIT
14964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * so that everything about the "current" node is ignored.
15064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
15164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
15264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		goto mem3;
15364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	sp->fts_cur->fts_link = root;
15464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	sp->fts_cur->fts_info = FTS_INIT;
15564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
15664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
15764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * If using chdir(2), grab a file descriptor pointing to dot to ensure
15864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * that we can get back here; this could be avoided for some paths,
15964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * but almost certainly not worth the effort.  Slashes, symbolic links,
16064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * and ".." are all fairly nasty problems.  Note, if we can't get the
16164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * descriptor we run anyway, just more slowly.
16264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
16364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0)
16464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		SET(FTS_NOCHDIR);
16564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
16664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (nitems == 0)
16764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		free(parent);
16864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
16964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	return (sp);
17064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
17164ceac3f493e3063a289aec4a12c74787be974e4Colin Crossmem3:	fts_lfree(root);
17264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	free(parent);
17364ceac3f493e3063a289aec4a12c74787be974e4Colin Crossmem2:	free(sp->fts_path);
17464ceac3f493e3063a289aec4a12c74787be974e4Colin Crossmem1:	free(sp);
17564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	return (NULL);
17664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
17764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
17864ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic void
17964ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_load(FTS *sp, FTSENT *p)
18064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
18164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	size_t len;
18264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	char *cp;
18364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
18464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
18564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * Load the stream structure for the next traversal.  Since we don't
18664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * actually enter the directory until after the preorder visit, set
18764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * the fts_accpath field specially so the chdir gets done to the right
18864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * place and the user can access the first node.  From fts_open it's
18964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * known that the path will fit.
19064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
19164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	len = p->fts_pathlen = p->fts_namelen;
19264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	memmove(sp->fts_path, p->fts_name, len + 1);
19364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
19464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		len = strlen(++cp);
19564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		memmove(p->fts_name, cp, len + 1);
19664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p->fts_namelen = len;
19764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
19864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	p->fts_accpath = p->fts_path = sp->fts_path;
19964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	sp->fts_dev = p->fts_dev;
20064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
20164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
20264ceac3f493e3063a289aec4a12c74787be974e4Colin Crossint
20364ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_close(FTS *sp)
20464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
20564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	FTSENT *freep, *p;
20664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	int rfd, error = 0;
20764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
20864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
20964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * This still works if we haven't read anything -- the dummy structure
21064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * points to the root list, so we step through to the end of the root
21164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * list which has a valid parent pointer.
21264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
21364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (sp->fts_cur) {
21464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
21564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			freep = p;
21664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			p = p->fts_link ? p->fts_link : p->fts_parent;
21764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			free(freep);
21864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
21964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		free(p);
22064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
22164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
22264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Stash the original directory fd if needed. */
22364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	rfd = ISSET(FTS_NOCHDIR) ? -1 : sp->fts_rfd;
22464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
22564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Free up child linked list, sort array, path buffer, stream ptr.*/
22664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (sp->fts_child)
22764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		fts_lfree(sp->fts_child);
22864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (sp->fts_array)
22964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		free(sp->fts_array);
23064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	free(sp->fts_path);
23164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	free(sp);
23264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
23364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Return to original directory, checking for error. */
23464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (rfd != -1) {
23564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		int saved_errno;
23664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		error = fchdir(rfd);
23764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		saved_errno = errno;
23864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		(void)close(rfd);
23964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		errno = saved_errno;
24064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
24164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
24264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	return (error);
24364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
24464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
24564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross/*
24664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * Special case of "/" at the end of the path so that slashes aren't
24764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * appended which would cause paths to be written as "....//foo".
24864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross */
24964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#define	NAPPEND(p)							\
25064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	(p->fts_path[p->fts_pathlen - 1] == '/'				\
25164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	    ? p->fts_pathlen - 1 : p->fts_pathlen)
25264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
25364ceac3f493e3063a289aec4a12c74787be974e4Colin CrossFTSENT *
25464ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_read(FTS *sp)
25564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
25664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	FTSENT *p, *tmp;
25764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	int instr;
25864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	char *t;
25964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	int saved_errno;
26064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
26164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* If finished or unrecoverable error, return NULL. */
26264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (sp->fts_cur == NULL || ISSET(FTS_STOP))
26364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (NULL);
26464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
26564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Set current node pointer. */
26664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	p = sp->fts_cur;
26764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
26864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Save and zero out user instructions. */
26964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	instr = p->fts_instr;
27064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	p->fts_instr = FTS_NOINSTR;
27164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
27264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Any type of file may be re-visited; re-stat and re-turn. */
27364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (instr == FTS_AGAIN) {
27464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p->fts_info = fts_stat(sp, p, 0);
27564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (p);
27664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
27764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
27864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
27964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * Following a symlink -- SLNONE test allows application to see
28064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * SLNONE and recover.  If indirecting through a symlink, have
28164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * keep a pointer to current location.  If unable to get that
28264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * pointer, follow fails.
28364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
28464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (instr == FTS_FOLLOW &&
28564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	    (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
28664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p->fts_info = fts_stat(sp, p, 1);
28764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
28864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) {
28964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				p->fts_errno = errno;
29064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				p->fts_info = FTS_ERR;
29164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			} else
29264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				p->fts_flags |= FTS_SYMFOLLOW;
29364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
29464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (p);
29564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
29664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
29764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Directory in pre-order. */
29864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (p->fts_info == FTS_D) {
29964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		/* If skipped or crossed mount point, do post-order visit. */
30064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (instr == FTS_SKIP ||
30164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		    (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
30264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (p->fts_flags & FTS_SYMFOLLOW)
30364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				(void)close(p->fts_symfd);
30464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (sp->fts_child) {
30564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				fts_lfree(sp->fts_child);
30664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				sp->fts_child = NULL;
30764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			}
30864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			p->fts_info = FTS_DP;
30964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			return (p);
31064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
31164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
31264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		/* Rebuild if only read the names and now traversing. */
31364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (sp->fts_child && ISSET(FTS_NAMEONLY)) {
31464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			CLR(FTS_NAMEONLY);
31564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			fts_lfree(sp->fts_child);
31664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			sp->fts_child = NULL;
31764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
31864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
31964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		/*
32064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * Cd to the subdirectory.
32164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 *
32264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * If have already read and now fail to chdir, whack the list
32364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * to make the names come out right, and set the parent errno
32464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * so the application will eventually get an error condition.
32564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * Set the FTS_DONTCHDIR flag so that when we logically change
32664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * directories back to the parent we don't do a chdir.
32764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 *
32864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * If haven't read do so.  If the read fails, fts_build sets
32964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * FTS_STOP or the fts_info field of the node.
33064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 */
33164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (sp->fts_child) {
33264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
33364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				p->fts_errno = errno;
33464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				p->fts_flags |= FTS_DONTCHDIR;
33564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				for (p = sp->fts_child; p; p = p->fts_link)
33664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross					p->fts_accpath =
33764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross					    p->fts_parent->fts_accpath;
33864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			}
33964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		} else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
34064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (ISSET(FTS_STOP))
34164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				return (NULL);
34264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			return (p);
34364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
34464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p = sp->fts_child;
34564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		sp->fts_child = NULL;
34664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		goto name;
34764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
34864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
34964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Move to the next node on this level. */
35064ceac3f493e3063a289aec4a12c74787be974e4Colin Crossnext:	tmp = p;
35164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if ((p = p->fts_link)) {
35264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		free(tmp);
35364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
35464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		/*
35564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * If reached the top, return to the original directory (or
35664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * the root of the tree), and load the paths for the next root.
35764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 */
35864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (p->fts_level == FTS_ROOTLEVEL) {
35964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (FCHDIR(sp, sp->fts_rfd)) {
36064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				SET(FTS_STOP);
36164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				return (NULL);
36264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			}
36364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			fts_load(sp, p);
36464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			return (sp->fts_cur = p);
36564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
36664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
36764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		/*
36864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * User may have called fts_set on the node.  If skipped,
36964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * ignore.  If followed, get a file descriptor so we can
37064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * get back if necessary.
37164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 */
37264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (p->fts_instr == FTS_SKIP)
37364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			goto next;
37464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (p->fts_instr == FTS_FOLLOW) {
37564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			p->fts_info = fts_stat(sp, p, 1);
37664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
37764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				if ((p->fts_symfd =
37864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				    open(".", O_RDONLY, 0)) < 0) {
37964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross					p->fts_errno = errno;
38064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross					p->fts_info = FTS_ERR;
38164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				} else
38264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross					p->fts_flags |= FTS_SYMFOLLOW;
38364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			}
38464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			p->fts_instr = FTS_NOINSTR;
38564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
38664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
38764ceac3f493e3063a289aec4a12c74787be974e4Colin Crossname:		t = sp->fts_path + NAPPEND(p->fts_parent);
38864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		*t++ = '/';
38964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		memmove(t, p->fts_name, p->fts_namelen + 1);
39064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (sp->fts_cur = p);
39164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
39264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
39364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Move up to the parent node. */
39464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	p = tmp->fts_parent;
39564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	free(tmp);
39664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
39764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (p->fts_level == FTS_ROOTPARENTLEVEL) {
39864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		/*
39964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * Done; free everything up and set errno to 0 so the user
40064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * can distinguish between error and EOF.
40164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 */
40264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		free(p);
40364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		errno = 0;
40464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (sp->fts_cur = NULL);
40564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
40664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
40764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* NUL terminate the pathname. */
40864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	sp->fts_path[p->fts_pathlen] = '\0';
40964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
41064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
41164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * Return to the parent directory.  If at a root node or came through
41264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * a symlink, go back through the file descriptor.  Otherwise, cd up
41364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * one directory.
41464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
41564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (p->fts_level == FTS_ROOTLEVEL) {
41664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (FCHDIR(sp, sp->fts_rfd)) {
41764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			SET(FTS_STOP);
41864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			sp->fts_cur = p;
41964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			return (NULL);
42064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
42164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	} else if (p->fts_flags & FTS_SYMFOLLOW) {
42264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (FCHDIR(sp, p->fts_symfd)) {
42364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			saved_errno = errno;
42464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			(void)close(p->fts_symfd);
42564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			errno = saved_errno;
42664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			SET(FTS_STOP);
42764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			sp->fts_cur = p;
42864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			return (NULL);
42964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
43064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		(void)close(p->fts_symfd);
43164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	} else if (!(p->fts_flags & FTS_DONTCHDIR) &&
43264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	    fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
43364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		SET(FTS_STOP);
43464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		sp->fts_cur = p;
43564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (NULL);
43664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
43764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
43864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	return (sp->fts_cur = p);
43964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
44064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
44164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross/*
44264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * Fts_set takes the stream as an argument although it's not used in this
44364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * implementation; it would be necessary if anyone wanted to add global
44464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * semantics to fts using fts_set.  An error return is allowed for similar
44564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * reasons.
44664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross */
44764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross/* ARGSUSED */
44864ceac3f493e3063a289aec4a12c74787be974e4Colin Crossint
44964ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_set(FTS *sp, FTSENT *p, int instr)
45064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
45164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
45264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	    instr != FTS_NOINSTR && instr != FTS_SKIP) {
45364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		errno = EINVAL;
45464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (1);
45564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
45664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	p->fts_instr = instr;
45764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	return (0);
45864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
45964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
46064ceac3f493e3063a289aec4a12c74787be974e4Colin CrossFTSENT *
46164ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_children(FTS *sp, int instr)
46264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
46364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	FTSENT *p;
46464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	int fd;
46564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
46664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (instr && instr != FTS_NAMEONLY) {
46764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		errno = EINVAL;
46864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (NULL);
46964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
47064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
47164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Set current node pointer. */
47264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	p = sp->fts_cur;
47364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
47464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
47564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * Errno set to 0 so user can distinguish empty directory from
47664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * an error.
47764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
47864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	errno = 0;
47964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
48064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Fatal errors stop here. */
48164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (ISSET(FTS_STOP))
48264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (NULL);
48364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
48464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Return logical hierarchy of user's arguments. */
48564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (p->fts_info == FTS_INIT)
48664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (p->fts_link);
48764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
48864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
48964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * If not a directory being visited in pre-order, stop here.  Could
49064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * allow FTS_DNR, assuming the user has fixed the problem, but the
49164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * same effect is available with FTS_AGAIN.
49264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
49364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
49464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (NULL);
49564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
49664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Free up any previous child list. */
49764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (sp->fts_child)
49864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		fts_lfree(sp->fts_child);
49964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
50064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (instr == FTS_NAMEONLY) {
50164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		SET(FTS_NAMEONLY);
50264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		instr = BNAMES;
50364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	} else
50464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		instr = BCHILD;
50564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
50664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
50764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * If using chdir on a relative path and called BEFORE fts_read does
50864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * its chdir to the root of a traversal, we can lose -- we need to
50964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * chdir into the subdirectory, and we don't know where the current
51064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * directory is, so we can't get back so that the upcoming chdir by
51164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * fts_read will work.
51264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
51364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
51464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	    ISSET(FTS_NOCHDIR))
51564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (sp->fts_child = fts_build(sp, instr));
51664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
51764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if ((fd = open(".", O_RDONLY, 0)) < 0)
51864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (NULL);
51964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	sp->fts_child = fts_build(sp, instr);
52064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (fchdir(fd)) {
52164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		(void)close(fd);
52264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (NULL);
52364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
52464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	(void)close(fd);
52564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	return (sp->fts_child);
52664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
52764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
52864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross/*
52964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * This is the tricky part -- do not casually change *anything* in here.  The
53064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * idea is to build the linked list of entries that are used by fts_children
53164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * and fts_read.  There are lots of special cases.
53264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross *
53364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * The real slowdown in walking the tree is the stat calls.  If FTS_NOSTAT is
53464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * set and it's a physical walk (so that symbolic links can't be directories),
53564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * we can do things quickly.  First, if it's a 4.4BSD file system, the type
53664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * of the file is in the directory entry.  Otherwise, we assume that the number
53764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * of subdirectories in a node is equal to the number of links to the parent.
53864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * The former skips all stat calls.  The latter skips stat calls in any leaf
53964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * directories and for any files after the subdirectories in the directory have
54064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * been found, cutting the stat calls by about 2/3.
54164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross */
54264ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic FTSENT *
54364ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_build(FTS *sp, int type)
54464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
54564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	struct dirent *dp;
54664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	FTSENT *p, *head;
54764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	FTSENT *cur, *tail;
54864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	DIR *dirp;
54964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	void *oldaddr;
55064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	size_t len, maxlen;
55150ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner	int nitems, cderrno, descend, level, nlinks, nostat = 0, doadjust;
55264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	int saved_errno;
55350ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner	char *cp = NULL;
55464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
55564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Set current node pointer. */
55664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	cur = sp->fts_cur;
55764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
55864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
55964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * Open the directory for reading.  If this fails, we're done.
56064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * If being called from fts_read, set the fts_info field.
56164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
56264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if ((dirp = opendir(cur->fts_accpath)) == NULL) {
56364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (type == BREAD) {
56464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			cur->fts_info = FTS_DNR;
56564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			cur->fts_errno = errno;
56664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
56764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (NULL);
56864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
56964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
57064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
57164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * Nlinks is the number of possible entries of type directory in the
57264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * directory if we're cheating on stat calls, 0 if we're not doing
57364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * any stat calls at all, -1 if we're doing stats on everything.
57464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
57564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (type == BNAMES)
57664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		nlinks = 0;
57764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
57864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
57964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		nostat = 1;
58064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	} else {
58164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		nlinks = -1;
58264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		nostat = 0;
58364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
58464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
58564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#ifdef notdef
58664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	(void)printf("nlinks == %d (cur: %u)\n", nlinks, cur->fts_nlink);
58764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	(void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
58864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	    ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
58964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#endif
59064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
59164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * If we're going to need to stat anything or we want to descend
59264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * and stay in the directory, chdir.  If this fails we keep going,
59364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * but set a flag so we don't chdir after the post-order visit.
59464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * We won't be able to stat anything, but we can still return the
59564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * names themselves.  Note, that since fts_read won't be able to
59664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * chdir into the directory, it will have to return different path
59764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * names than before, i.e. "a/b" instead of "b".  Since the node
59864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * has already been visited in pre-order, have to wait until the
59964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * post-order visit to return the error.  There is a special case
60064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * here, if there was nothing to stat then it's not an error to
60164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * not be able to stat.  This is all fairly nasty.  If a program
60264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * needed sorted entries or stat information, they had better be
60364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * checking FTS_NS on the returned nodes.
60464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
60564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	cderrno = 0;
60664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (nlinks || type == BREAD) {
60764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
60864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (nlinks && type == BREAD)
60964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				cur->fts_errno = errno;
61064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			cur->fts_flags |= FTS_DONTCHDIR;
61164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			descend = 0;
61264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			cderrno = errno;
61364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			(void)closedir(dirp);
61464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			dirp = NULL;
61564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		} else
61664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			descend = 1;
61764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	} else
61864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		descend = 0;
61964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
62064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
62164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * Figure out the max file name length that can be stored in the
62264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * current path -- the inner loop allocates more path as necessary.
62364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * We really wouldn't have to do the maxlen calculations here, we
62464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * could do them in fts_read before returning the path, but it's a
62564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * lot easier here since the length is part of the dirent structure.
62664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 *
62764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * If not changing directories set a pointer so that can just append
62864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * each new name into the path.
62964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
63064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	len = NAPPEND(cur);
63164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (ISSET(FTS_NOCHDIR)) {
63264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		cp = sp->fts_path + len;
63364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		*cp++ = '/';
63464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
63564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	len++;
63664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	maxlen = sp->fts_pathlen - len;
63764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
63864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
63964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * fts_level is a short so we must prevent it from wrapping
64064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * around to FTS_ROOTLEVEL and FTS_ROOTPARENTLEVEL.
64164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
64264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	level = cur->fts_level;
64364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (level < FTS_MAXLEVEL)
64464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	    level++;
64564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
64664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Read the directory, attaching each entry to the `link' pointer. */
64764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	doadjust = 0;
64864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) {
64964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
65064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			continue;
65164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
65264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (!(p = fts_alloc(sp, dp->d_name, strlen(dp->d_name))))
65364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			goto mem1;
65464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (strlen(dp->d_name) >= maxlen) {	/* include space for NUL */
65564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			oldaddr = sp->fts_path;
65664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (fts_palloc(sp, strlen(dp->d_name) +len + 1)) {
65764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				/*
65864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				 * No more memory for path or structures.  Save
65964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				 * errno, free up the current structure and the
66064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				 * structures already allocated.
66164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				 */
66264ceac3f493e3063a289aec4a12c74787be974e4Colin Crossmem1:				saved_errno = errno;
66364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				if (p)
66464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross					free(p);
66564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				fts_lfree(head);
66664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				(void)closedir(dirp);
66764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				cur->fts_info = FTS_ERR;
66864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				SET(FTS_STOP);
66964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				errno = saved_errno;
67064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				return (NULL);
67164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			}
67264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			/* Did realloc() change the pointer? */
67364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (oldaddr != sp->fts_path) {
67464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				doadjust = 1;
67564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				if (ISSET(FTS_NOCHDIR))
67664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross					cp = sp->fts_path + len;
67764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			}
67864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			maxlen = sp->fts_pathlen - len;
67964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
68064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
68164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p->fts_level = level;
68264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p->fts_parent = sp->fts_cur;
68364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p->fts_pathlen = len + strlen(dp->d_name);
68464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (p->fts_pathlen < len) {
68564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			/*
68664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			 * If we wrap, free up the current structure and
68764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			 * the structures already allocated, then error
68864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			 * out with ENAMETOOLONG.
68964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			 */
69064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			free(p);
69164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			fts_lfree(head);
69264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			(void)closedir(dirp);
69364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			cur->fts_info = FTS_ERR;
69464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			SET(FTS_STOP);
69564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			errno = ENAMETOOLONG;
69664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			return (NULL);
69764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
69864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
69964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (cderrno) {
70064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (nlinks) {
70164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				p->fts_info = FTS_NS;
70264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				p->fts_errno = cderrno;
70364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			} else
70464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				p->fts_info = FTS_NSOK;
70564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			p->fts_accpath = cur->fts_accpath;
70664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		} else if (nlinks == 0
70764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#ifdef DT_DIR
70864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		    || (nostat &&
70964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		    dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
71064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#endif
71164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		    ) {
71264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			p->fts_accpath =
71364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			    ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
71464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			p->fts_info = FTS_NSOK;
71564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		} else {
71664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			/* Build a file name for fts_stat to stat. */
71764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (ISSET(FTS_NOCHDIR)) {
71864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				p->fts_accpath = p->fts_path;
71964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				memmove(cp, p->fts_name, p->fts_namelen + 1);
72064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			} else
72164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				p->fts_accpath = p->fts_name;
72264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			/* Stat it. */
72364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			p->fts_info = fts_stat(sp, p, 0);
72464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
72564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			/* Decrement link count if applicable. */
72664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (nlinks > 0 && (p->fts_info == FTS_D ||
72764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			    p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
72864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				--nlinks;
72964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
73064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
73164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		/* We walk in directory order so "ls -f" doesn't get upset. */
73264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p->fts_link = NULL;
73364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (head == NULL)
73464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			head = tail = p;
73564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		else {
73664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			tail->fts_link = p;
73764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			tail = p;
73864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
73964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		++nitems;
74064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
74164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (dirp)
74264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		(void)closedir(dirp);
74364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
74464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
74564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * If realloc() changed the address of the path, adjust the
74664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * addresses for the rest of the tree and the dir list.
74764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
74864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (doadjust)
74964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		fts_padjust(sp, head);
75064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
75164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
75264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * If not changing directories, reset the path back to original
75364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * state.
75464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
75564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (ISSET(FTS_NOCHDIR)) {
75664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (len == sp->fts_pathlen || nitems == 0)
75764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			--cp;
75864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		*cp = '\0';
75964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
76064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
76164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
76264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * If descended after called from fts_children or after called from
76364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * fts_read and nothing found, get back.  At the root level we use
76464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * the saved fd; if one of fts_open()'s arguments is a relative path
76564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * to an empty directory, we wind up here with no other way back.  If
76664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * can't get back, we're done.
76764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
76864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (descend && (type == BCHILD || !nitems) &&
76964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	    (cur->fts_level == FTS_ROOTLEVEL ? FCHDIR(sp, sp->fts_rfd) :
77064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	    fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
77164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		cur->fts_info = FTS_ERR;
77264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		SET(FTS_STOP);
77364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (NULL);
77464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
77564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
77664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* If didn't find anything, return NULL. */
77764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (!nitems) {
77864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (type == BREAD)
77964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			cur->fts_info = FTS_DP;
78064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (NULL);
78164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
78264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
78364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Sort the entries. */
78464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (sp->fts_compar && nitems > 1)
78564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		head = fts_sort(sp, head, nitems);
78664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	return (head);
78764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
78864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
78964ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic u_short
79064ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_stat(FTS *sp, FTSENT *p, int follow)
79164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
79264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	FTSENT *t;
79364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	dev_t dev;
79464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	ino_t ino;
79564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	struct stat *sbp, sb;
79664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	int saved_errno;
79764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
79864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* If user needs stat info, stat buffer already allocated. */
79964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
80064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
80164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
80264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * If doing a logical walk, or application requested FTS_FOLLOW, do
80364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * a stat(2).  If that fails, check for a non-existent symlink.  If
80464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * fail, set the errno from the stat call.
80564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
80664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (ISSET(FTS_LOGICAL) || follow) {
80764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (stat(p->fts_accpath, sbp)) {
80864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			saved_errno = errno;
80964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (!lstat(p->fts_accpath, sbp)) {
81064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				errno = 0;
81164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				return (FTS_SLNONE);
81264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			}
81364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			p->fts_errno = saved_errno;
81464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			goto err;
81564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
81664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	} else if (lstat(p->fts_accpath, sbp)) {
81764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p->fts_errno = errno;
81864ceac3f493e3063a289aec4a12c74787be974e4Colin Crosserr:		memset(sbp, 0, sizeof(struct stat));
81964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (FTS_NS);
82064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
82164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
82264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (S_ISDIR(sbp->st_mode)) {
82364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		/*
82464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * Set the device/inode.  Used to find cycles and check for
82564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * crossing mount points.  Also remember the link count, used
82664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * in fts_build to limit the number of stat calls.  It is
82764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * understood that these fields are only referenced if fts_info
82864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * is set to FTS_D.
82964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 */
83064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		dev = p->fts_dev = sbp->st_dev;
83164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		ino = p->fts_ino = sbp->st_ino;
83264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p->fts_nlink = sbp->st_nlink;
83364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
83464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (ISDOT(p->fts_name))
83564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			return (FTS_DOT);
83664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
83764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		/*
83864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * Cycle detection is done by brute force when the directory
83964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * is first encountered.  If the tree gets deep enough or the
84064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * number of symbolic links to directories is high enough,
84164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 * something faster might be worthwhile.
84264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		 */
84364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		for (t = p->fts_parent;
84464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		    t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
84564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (ino == t->fts_ino && dev == t->fts_dev) {
84664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				p->fts_cycle = t;
84764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				return (FTS_DC);
84864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			}
84964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (FTS_D);
85064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
85164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (S_ISLNK(sbp->st_mode))
85264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (FTS_SL);
85364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (S_ISREG(sbp->st_mode))
85464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (FTS_F);
85564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	return (FTS_DEFAULT);
85664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
85764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
85864ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic FTSENT *
85964ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_sort(FTS *sp, FTSENT *head, int nitems)
86064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
86164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	FTSENT **ap, *p;
86264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
86364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
86464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * Construct an array of pointers to the structures and call qsort(3).
86564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * Reassemble the array in the order returned by qsort.  If unable to
86664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * sort for memory reasons, return the directory entries in their
86764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * current order.  Allocate enough space for the current needs plus
86864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * 40 so don't realloc one entry at a time.
86964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
87064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (nitems > sp->fts_nitems) {
87164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		struct _ftsent **a;
87264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
87364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		sp->fts_nitems = nitems + 40;
87464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if ((a = realloc(sp->fts_array,
87564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		    sp->fts_nitems * sizeof(FTSENT *))) == NULL) {
87664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			if (sp->fts_array)
87764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross				free(sp->fts_array);
87864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			sp->fts_array = NULL;
87964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			sp->fts_nitems = 0;
88064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			return (head);
88164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		}
88264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		sp->fts_array = a;
88364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
88464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	for (ap = sp->fts_array, p = head; p; p = p->fts_link)
88564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		*ap++ = p;
88664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
88764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	for (head = *(ap = sp->fts_array); --nitems; ++ap)
88864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		ap[0]->fts_link = ap[1];
88964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	ap[0]->fts_link = NULL;
89064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	return (head);
89164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
89264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
89364ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic FTSENT *
89464ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_alloc(FTS *sp, char *name, size_t namelen)
89564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
89664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	FTSENT *p;
89764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	size_t len;
89864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
89964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
90064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * The file name is a variable length array and no stat structure is
90164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * necessary if the user has set the nostat bit.  Allocate the FTSENT
90264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * structure, the file name and the stat structure in one chunk, but
90364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * be careful that the stat structure is reasonably aligned.  Since the
90464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * fts_name field is declared to be of size 1, the fts_name pointer is
90564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * namelen + 2 before the first possible address of the stat structure.
90664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
90764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	len = sizeof(FTSENT) + namelen;
90864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (!ISSET(FTS_NOSTAT))
90964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		len += sizeof(struct stat) + ALIGNBYTES;
91064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if ((p = malloc(len)) == NULL)
91164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (NULL);
91264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
91364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	memset(p, 0, len);
91464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	p->fts_path = sp->fts_path;
91564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	p->fts_namelen = namelen;
91664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	p->fts_instr = FTS_NOINSTR;
91764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (!ISSET(FTS_NOSTAT))
91864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
91964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	memcpy(p->fts_name, name, namelen);
92064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
92164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	return (p);
92264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
92364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
92464ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic void
92564ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_lfree(FTSENT *head)
92664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
92764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	FTSENT *p;
92864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
92964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Free a linked list of structures. */
93064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	while ((p = head)) {
93164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		head = head->fts_link;
93264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		free(p);
93364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
93464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
93564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
93664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross/*
93764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
93864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * Most systems will allow creation of paths much longer than MAXPATHLEN, even
93964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * though the kernel won't resolve them.  Add the size (not just what's needed)
94064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * plus 256 bytes so don't realloc the path 2 bytes at a time.
94164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross */
94264ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic int
94364ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_palloc(FTS *sp, size_t more)
94464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
94564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	char *p;
94664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
94764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/*
94864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 * Check for possible wraparound.
94964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	 */
95064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	more += 256;
95164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (sp->fts_pathlen + more < sp->fts_pathlen) {
95264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (sp->fts_path)
95364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			free(sp->fts_path);
95464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		sp->fts_path = NULL;
95564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		errno = ENAMETOOLONG;
95664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (1);
95764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
95864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	sp->fts_pathlen += more;
95964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	p = realloc(sp->fts_path, sp->fts_pathlen);
96064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (p == NULL) {
96164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if (sp->fts_path)
96264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			free(sp->fts_path);
96364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		sp->fts_path = NULL;
96464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (1);
96564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
96664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	sp->fts_path = p;
96764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	return (0);
96864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
96964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
97064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross/*
97164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * When the path is realloc'd, have to fix all of the pointers in structures
97264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * already returned.
97364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross */
97464ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic void
97564ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_padjust(FTS *sp, FTSENT *head)
97664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
97764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	FTSENT *p;
97864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	char *addr = sp->fts_path;
97964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
98064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross#define	ADJUST(p) {							\
98164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if ((p)->fts_accpath != (p)->fts_name) {			\
98264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		(p)->fts_accpath =					\
98364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		    (char *)addr + ((p)->fts_accpath - (p)->fts_path);	\
98464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}								\
98564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	(p)->fts_path = addr;						\
98664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
98764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Adjust the current set of children. */
98864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	for (p = sp->fts_child; p; p = p->fts_link)
98964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		ADJUST(p);
99064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
99164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	/* Adjust the rest of the tree, including the current level. */
99264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
99364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		ADJUST(p);
99464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		p = p->fts_link ? p->fts_link : p->fts_parent;
99564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
99664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
99764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
99864ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic size_t
99964ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_maxarglen(char * const *argv)
100064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
100164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	size_t len, max;
100264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
100364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	for (max = 0; *argv; ++argv)
100464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		if ((len = strlen(*argv)) > max)
100564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross			max = len;
100664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	return (max + 1);
100764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
100864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
100964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross/*
101064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * Change to dir specified by fd or p->fts_accpath without getting
101164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * tricked by someone changing the world out from underneath us.
101264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross * Assumes p->fts_dev and p->fts_ino are filled in.
101364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross */
101464ceac3f493e3063a289aec4a12c74787be974e4Colin Crossstatic int
101564ceac3f493e3063a289aec4a12c74787be974e4Colin Crossfts_safe_changedir(FTS *sp, FTSENT *p, int fd, char *path)
101664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross{
101764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	int ret, oerrno, newfd;
101864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	struct stat sb;
101964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross
102064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	newfd = fd;
102164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (ISSET(FTS_NOCHDIR))
102264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (0);
102364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (fd < 0 && (newfd = open(path, O_RDONLY, 0)) < 0)
102464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		return (-1);
102564ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (fstat(newfd, &sb)) {
102664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		ret = -1;
102764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		goto bail;
102864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
102964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) {
103064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		errno = ENOENT;		/* disinformation */
103164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		ret = -1;
103264ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		goto bail;
103364ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	}
103464ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	ret = fchdir(newfd);
103564ceac3f493e3063a289aec4a12c74787be974e4Colin Crossbail:
103664ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	oerrno = errno;
103764ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	if (fd < 0)
103864ceac3f493e3063a289aec4a12c74787be974e4Colin Cross		(void)close(newfd);
103964ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	errno = oerrno;
104064ceac3f493e3063a289aec4a12c74787be974e4Colin Cross	return (ret);
104164ceac3f493e3063a289aec4a12c74787be974e4Colin Cross}
1042