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