xref: /openbsd-src/lib/libc/gen/ftw.c (revision bf198cc6eba0ca1f6d79f71e8e2243d386241fa8)
1*bf198cc6Smillert /*	$OpenBSD: ftw.c,v 1.6 2019/01/25 00:19:25 millert Exp $	*/
29c72459dSmillert 
39c72459dSmillert /*
4*bf198cc6Smillert  * Copyright (c) 2003, 2004 Todd C. Miller <millert@openbsd.org>
59c72459dSmillert  *
6f5f7ab2eSmillert  * Permission to use, copy, modify, and distribute this software for any
7f5f7ab2eSmillert  * purpose with or without fee is hereby granted, provided that the above
8f5f7ab2eSmillert  * copyright notice and this permission notice appear in all copies.
99c72459dSmillert  *
10f5f7ab2eSmillert  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11f5f7ab2eSmillert  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12f5f7ab2eSmillert  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13f5f7ab2eSmillert  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14f5f7ab2eSmillert  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15f5f7ab2eSmillert  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16f5f7ab2eSmillert  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17f5f7ab2eSmillert  *
18f5f7ab2eSmillert  * Sponsored in part by the Defense Advanced Research Projects
19f5f7ab2eSmillert  * Agency (DARPA) and Air Force Research Laboratory, Air Force
20f5f7ab2eSmillert  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
219c72459dSmillert  */
229c72459dSmillert 
239c72459dSmillert #include <sys/types.h>
249c72459dSmillert #include <sys/stat.h>
259c72459dSmillert #include <errno.h>
269c72459dSmillert #include <fts.h>
279c72459dSmillert #include <ftw.h>
289c72459dSmillert #include <limits.h>
299c72459dSmillert 
309c72459dSmillert int
ftw(const char * path,int (* fn)(const char *,const struct stat *,int),int nfds)319c72459dSmillert ftw(const char *path, int (*fn)(const char *, const struct stat *, int),
329c72459dSmillert     int nfds)
339c72459dSmillert {
34c1e28e31Smillert 	char * const paths[2] = { (char *)path, NULL };
359c72459dSmillert 	FTSENT *cur;
369c72459dSmillert 	FTS *ftsp;
37c1e28e31Smillert 	int error = 0, fnflag, sverrno;
389c72459dSmillert 
399c72459dSmillert 	/* XXX - nfds is currently unused */
409c72459dSmillert 	if (nfds < 1 || nfds > OPEN_MAX) {
419c72459dSmillert 		errno = EINVAL;
429c72459dSmillert 		return (-1);
439c72459dSmillert 	}
449c72459dSmillert 
45c1e28e31Smillert 	ftsp = fts_open(paths, FTS_LOGICAL | FTS_COMFOLLOW | FTS_NOCHDIR, NULL);
469c72459dSmillert 	if (ftsp == NULL)
479c72459dSmillert 		return (-1);
489c72459dSmillert 	while ((cur = fts_read(ftsp)) != NULL) {
499c72459dSmillert 		switch (cur->fts_info) {
509c72459dSmillert 		case FTS_D:
519c72459dSmillert 			fnflag = FTW_D;
529c72459dSmillert 			break;
539c72459dSmillert 		case FTS_DNR:
549c72459dSmillert 			fnflag = FTW_DNR;
559c72459dSmillert 			break;
569c72459dSmillert 		case FTS_DP:
579c72459dSmillert 			/* we only visit in preorder */
589c72459dSmillert 			continue;
599c72459dSmillert 		case FTS_F:
609c72459dSmillert 		case FTS_DEFAULT:
619c72459dSmillert 			fnflag = FTW_F;
629c72459dSmillert 			break;
639c72459dSmillert 		case FTS_NS:
649c72459dSmillert 		case FTS_NSOK:
659c72459dSmillert 		case FTS_SLNONE:
669c72459dSmillert 			fnflag = FTW_NS;
679c72459dSmillert 			break;
689c72459dSmillert 		case FTS_SL:
699c72459dSmillert 			fnflag = FTW_SL;
709c72459dSmillert 			break;
719c72459dSmillert 		case FTS_DC:
729c72459dSmillert 			errno = ELOOP;
739c72459dSmillert 			/* FALLTHROUGH */
749c72459dSmillert 		default:
759c72459dSmillert 			error = -1;
769c72459dSmillert 			goto done;
779c72459dSmillert 		}
789c72459dSmillert 		error = fn(cur->fts_path, cur->fts_statp, fnflag);
799c72459dSmillert 		if (error != 0)
809c72459dSmillert 			break;
819c72459dSmillert 	}
829c72459dSmillert done:
839c72459dSmillert 	sverrno = errno;
8419066a52Smillert 	if (fts_close(ftsp) != 0 && error == 0)
8519066a52Smillert 		error = -1;
8619066a52Smillert 	else
879c72459dSmillert 		errno = sverrno;
889c72459dSmillert 	return (error);
899c72459dSmillert }
90