summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/Makefile3
-rw-r--r--include/ftw.h107
-rw-r--r--lib/libc/gen/Makefile.inc5
-rw-r--r--lib/libc/gen/ftw.c208
4 files changed, 320 insertions, 3 deletions
diff --git a/include/Makefile b/include/Makefile
index 130e226..28b5294 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -7,7 +7,8 @@ CLEANFILES= osreldate.h version vers.c
SUBDIR= arpa protocols rpcsvc rpc
INCS= a.out.h ar.h assert.h bitstring.h complex.h cpio.h ctype.h db.h \
dirent.h dlfcn.h elf.h elf-hints.h err.h fmtmsg.h fnmatch.h fstab.h \
- fts.h getopt.h glob.h grp.h hesiod.h histedit.h ieeefp.h ifaddrs.h \
+ fts.h ftw.h getopt.h glob.h grp.h \
+ hesiod.h histedit.h ieeefp.h ifaddrs.h \
inttypes.h iso646.h kenv.h langinfo.h libgen.h limits.h link.h \
locale.h malloc.h memory.h monetary.h mpool.h ndbm.h netconfig.h \
netdb.h nl_types.h nlist.h nss.h nsswitch.h objformat.h paths.h \
diff --git a/include/ftw.h b/include/ftw.h
new file mode 100644
index 0000000..e0cf085
--- /dev/null
+++ b/include/ftw.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2003 by Joel Baker.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Author nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _FTW_H
+#define _FTW_H
+
+#include <sys/stat.h>
+
+__BEGIN_DECLS
+
+/* Enumerated values for 'flag' when calling [n]ftw */
+
+enum {
+ FTW_D, /* Directories */
+ FTW_DNR, /* Unreadable directory */
+ FTW_F, /* Regular files */
+ FTW_SL, /* Symbolic link */
+ FTW_NS, /* stat(2) failed */
+
+#if __XSI_VISIBLE /* X/Open */
+
+/* Flags for nftw only */
+
+ FTW_DP, /* Directory, subdirs visited */
+ FTW_SLN, /* Dangling symlink */
+
+#endif /* __XSI_VISIBLE */
+};
+
+#if __XSI_VISIBLE /* X/Open */
+
+/* Enumerated values for 'flags' when calling nftw */
+
+enum {
+ FTW_CHDIR = 1, /* Do a chdir(2) when entering a directory */
+ FTW_DEPTH = 2, /* Report files first (before directory) */
+ FTW_MOUNT = 4, /* Single filesystem */
+ FTW_PHYS = 8 /* Physical walk; ignore symlinks */
+};
+
+#define FTW_PHYS FTW_PHYS
+#define FTW_MOUNT FTW_MOUNT
+#define FTW_CHDIR FTW_CHDIR
+#define FTW_DEPTH FTW_DEPTH
+
+/* FTW struct for callbacks from nftw */
+
+struct FTW {
+ int base;
+ int level;
+};
+
+#endif /* __XSI_VISIBLE */
+
+/* Typecasts for callback functions */
+
+typedef int (*__ftw_func_t) \
+ (const char *file, const struct stat *status, int flag);
+
+/* ftw: walk a directory tree, calling a function for each element */
+
+extern int ftw (const char *dir, __ftw_func_t func, int descr);
+
+#if __XSI_VISIBLE /* X/Open */
+
+typedef int (*__nftw_func_t) \
+ (const char *file, const struct stat *status, int flag, struct FTW *detail);
+
+/* nftw: walk a directory tree, calling a function for each element; much
+ * like ftw, but with behavior flags and minty freshness.
+ */
+
+extern int nftw (const char *dir, __nftw_func_t func, int descr, int flags);
+
+#endif /* __XSI_VISIBLE */
+
+__END_DECLS
+
+#endif /* _FTW_H */
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index 01844e5..a7d164b 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -9,7 +9,8 @@ SRCS+= __xuname.c _pthread_stubs.c _rand48.c _spinlock_stub.c _thread_init.c \
clock.c closedir.c confstr.c \
crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \
dlfcn.c dlfunc.c drand48.c erand48.c err.c errlst.c errno.c \
- exec.c fmtcheck.c fmtmsg.c fnmatch.c fpclassify.c fstab.c ftok.c fts.c \
+ exec.c fmtcheck.c fmtmsg.c fnmatch.c \
+ fpclassify.c fstab.c ftok.c fts.c ftw.c \
getbootfile.c getbsize.c \
getcap.c getcwd.c getdomainname.c getgrent.c getgrouplist.c \
gethostname.c getloadavg.c getlogin.c getmntinfo.c getnetgrent.c \
@@ -42,7 +43,7 @@ MAN+= alarm.3 arc4random.3 \
confstr.3 ctermid.3 daemon.3 devname.3 directory.3 dirname.3 \
dladdr.3 dlinfo.3 dllockinit.3 dlopen.3 \
err.3 exec.3 fmtcheck.3 fmtmsg.3 fnmatch.3 fpclassify.3 frexp.3 \
- ftok.3 fts.3 \
+ ftok.3 fts.3 ftw.3 \
getbootfile.3 getbsize.3 getcap.3 getcontext.3 getcwd.3 \
getdiskbyname.3 getdomainname.3 getfsent.3 \
getgrent.3 getgrouplist.3 gethostname.3 getloadavg.3 \
diff --git a/lib/libc/gen/ftw.c b/lib/libc/gen/ftw.c
new file mode 100644
index 0000000..a13aa17
--- /dev/null
+++ b/lib/libc/gen/ftw.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2003 by Joel Baker.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Author nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h> /* Because fts(3) says so */
+#include <sys/stat.h>
+#include <fts.h>
+
+#include <unistd.h> /* We want strcpy */
+
+#include <errno.h> /* Because errno is our friend */
+
+#include "ftw.h"
+
+/* I like symbolic values - this is only used in this file. */
+
+enum __ftw_modes {
+ MODE_FTW,
+ MODE_NFTW
+};
+
+/* Prototype this so that we can have it later */
+
+static int __ftw_core(const char *, void *, int, int, enum __ftw_modes);
+
+/*
+ * The external function calls are really just wrappers around __ftw_core,
+ * since the work they do is 90% the same.
+ */
+
+int ftw (const char *dir, __ftw_func_t func, int descr) {
+ return __ftw_core(dir, func, descr, 0, MODE_FTW);
+}
+
+int nftw (const char *dir, __nftw_func_t func, int descr, int flags) {
+ return __ftw_core(dir, func, descr, flags, MODE_NFTW);
+}
+
+/*
+typedef int (*__ftw_func_t) \
+ (const char *file, const struct stat status, int flag);
+typedef int (*__nftw_func_t) \
+ (const char *file, const struct stat status, int flag, struct FTW detail);
+*/
+
+static int __ftw_core(const char *dir, void *func, int descr, int flags,
+ enum __ftw_modes mode) {
+ FTS *hierarchy;
+ FTSENT *entry;
+ int fts_options;
+ const char *paths[2];
+ int ftw_flag, func_ret;
+ struct FTW ftw_st;
+ int skip_entry;
+ __ftw_func_t ftw_func;
+ __nftw_func_t nftw_func;
+ int saved_errno;
+
+ errno = 0;
+
+ /* We need at least one descriptor to call fts */
+
+ if (descr < 1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Decide which mode we're running in, and set the FTS options suitably. */
+
+ if (MODE_NFTW == mode) { /* NFTW mode, with all the bells and whistles. */
+ fts_options = (flags & FTW_PHYS) ? FTS_PHYSICAL : FTS_LOGICAL;
+ fts_options |= (flags & FTW_CHDIR) ? 0 : FTS_NOCHDIR;
+ fts_options |= (flags & FTW_MOUNT) ? FTS_XDEV : 0;
+ } else { /* We must be in FTW mode. Nothing else makes sense. */
+ fts_options = FTS_LOGICAL;
+ }
+
+ /* FTW gets a const char *, but FTS expects a null-term array of them. */
+
+ paths[0] = dir;
+ paths[1] = NULL;
+
+ /* Open the file hierarchy. */
+
+ if (!(hierarchy = fts_open((char * const *)paths, fts_options, NULL))) {
+ if (EACCES == errno) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+
+ /* The main loop. Is it not nifty? Worship the loop. */
+
+ while ((entry = fts_read(hierarchy))) {
+ skip_entry = 0;
+
+ switch (entry->fts_info) {
+
+ case FTS_D:
+ if ((MODE_NFTW != mode) || !(flags & FTW_DEPTH)) {
+ ftw_flag = FTW_D;
+ } else {
+ skip_entry = 1;
+ }
+ break;
+
+ case FTS_DNR:
+ ftw_flag = FTW_DNR;
+ break;
+
+ case FTS_F:
+ ftw_flag = FTW_F;
+ break;
+
+ case FTS_SL:
+ ftw_flag = FTW_SL;
+ break;
+
+ case FTS_NS:
+ ftw_flag = FTW_NS;
+ break;
+
+ /* Values that should only occur in nftw mode */
+
+ case FTS_SLNONE:
+ if (MODE_NFTW == mode) {
+ ftw_flag = FTW_SLN;
+ } else {
+ ftw_flag = FTW_SL;
+ }
+ break;
+
+ case FTS_DP:
+ if ((MODE_NFTW == mode) && (flags & FTW_DEPTH)) {
+ ftw_flag = FTW_D;
+ } else {
+ skip_entry = 1;
+ }
+ break;
+
+ default:
+ /* I'm not sure this is right, but we don't have a valid FTW
+ * type to call with, so cowardice seems the better part of
+ * guessing.
+ */
+
+ skip_entry = 1;
+ }
+
+ if (MODE_FTW == mode) {
+ ftw_func = (__ftw_func_t) func;
+ func_ret = (*ftw_func)
+ (entry->fts_path, entry->fts_statp, ftw_flag);
+ } else if (MODE_NFTW == mode) {
+ ftw_st.base = (entry->fts_pathlen - entry->fts_namelen);
+ ftw_st.level = entry->fts_level;
+
+ nftw_func = (__nftw_func_t) func;
+ func_ret = (*nftw_func)
+ (entry->fts_path, entry->fts_statp, ftw_flag, &ftw_st);
+ }
+
+ if (0 != func_ret) {
+ saved_errno = errno;
+ fts_close(hierarchy);
+ errno = saved_errno;
+ return func_ret;
+ }
+ }
+
+ /* The janitors will be upset if we don't clean up after ourselves. */
+
+ saved_errno = errno;
+ fts_close(hierarchy);
+ if (0 != saved_errno) { /* fts_read returned NULL, and set errno - bail */
+ errno = saved_errno;
+ }
+
+ return errno ? -1 : 0;
+}
OpenPOWER on IntegriCloud