1/* $NetBSD */
2
3/*	From OpenBSD: nftw.c,v 1.2 2003/07/21 21:15:32 millert Exp 	*/
4
5/*
6 * Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *
20 * Sponsored in part by the Defense Advanced Research Projects
21 * Agency (DARPA) and Air Force Research Laboratory, Air Force
22 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
23 */
24
25#include <sys/cdefs.h>
26
27#ifndef lint
28__RCSID("$NetBSD: nftw.c,v 1.1 2005/12/30 23:07:32 agc Exp $");
29#endif
30
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <errno.h>
34#include <fts.h>
35#include <ftw.h>
36#include <limits.h>
37
38int
39nftw(const char *path, int (*fn)(const char *, const struct stat *, int,
40     struct FTW *), int nfds, int ftwflags)
41{
42	/* LINTED */
43	char * const paths[2] = { __UNCONST(path), NULL };
44	struct FTW f;
45	FTSENT *cur;
46	FTS *ftsp;
47	int ftsflags, fnflag, error, postorder, sverrno;
48
49	/* XXX - nfds is currently unused */
50	if (nfds < 1 || nfds > OPEN_MAX) {
51		errno = EINVAL;
52		return (-1);
53	}
54
55	ftsflags = FTS_COMFOLLOW;
56	if (!(ftwflags & FTW_CHDIR))
57		ftsflags |= FTS_NOCHDIR;
58	if (ftwflags & FTW_MOUNT)
59		ftsflags |= FTS_XDEV;
60	if (ftwflags & FTW_PHYS)
61		ftsflags |= FTS_PHYSICAL;
62	postorder = (ftwflags & FTW_DEPTH) != 0;
63	ftsp = fts_open(paths, ftsflags, NULL);
64	if (ftsp == NULL)
65		return (-1);
66	error = 0;
67	while ((cur = fts_read(ftsp)) != NULL) {
68		switch (cur->fts_info) {
69		case FTS_D:
70			if (postorder)
71				continue;
72			fnflag = FTW_D;
73			break;
74		case FTS_DNR:
75			fnflag = FTW_DNR;
76			break;
77		case FTS_DP:
78			if (!postorder)
79				continue;
80			fnflag = FTW_DP;
81			break;
82		case FTS_F:
83		case FTS_DEFAULT:
84			fnflag = FTW_F;
85			break;
86		case FTS_NS:
87		case FTS_NSOK:
88			fnflag = FTW_NS;
89			break;
90		case FTS_SL:
91			fnflag = FTW_SL;
92			break;
93		case FTS_SLNONE:
94			fnflag = FTW_SLN;
95			break;
96		case FTS_DC:
97			errno = ELOOP;
98			/* FALLTHROUGH */
99		default:
100			error = -1;
101			goto done;
102		}
103		f.base = cur->fts_pathlen - cur->fts_namelen;
104		f.level = cur->fts_level;
105		error = fn(cur->fts_path, cur->fts_statp, fnflag, &f);
106		if (error != 0)
107			break;
108	}
109done:
110	sverrno = errno;
111	(void) fts_close(ftsp);
112	errno = sverrno;
113	return (error);
114}
115