summaryrefslogtreecommitdiff
path: root/package/cfgfs/src/fts_subs.c
diff options
context:
space:
mode:
Diffstat (limited to 'package/cfgfs/src/fts_subs.c')
-rw-r--r--package/cfgfs/src/fts_subs.c163
1 files changed, 163 insertions, 0 deletions
diff --git a/package/cfgfs/src/fts_subs.c b/package/cfgfs/src/fts_subs.c
new file mode 100644
index 000000000..ec40219f8
--- /dev/null
+++ b/package/cfgfs/src/fts_subs.c
@@ -0,0 +1,163 @@
+/* $MirOS: contrib/hosted/fwcf/fts_subs.c,v 1.8 2007/07/02 14:53:03 tg Exp $ */
+
+/*-
+ * Copyright (c) 2006
+ * Thorsten Glaser <tg@mirbsd.de>
+ *
+ * Licensee is hereby permitted to deal in this work without restric-
+ * tion, including unlimited rights to use, publicly perform, modify,
+ * merge, distribute, sell, give away or sublicence, provided all co-
+ * pyright notices above, these terms and the disclaimer are retained
+ * in all redistributions or reproduced in accompanying documentation
+ * or other materials provided with binary redistributions.
+ *
+ * Licensor offers the work "AS IS" and WITHOUT WARRANTY of any kind,
+ * express, or implied, to the maximum extent permitted by applicable
+ * law, without malicious intent or gross negligence; in no event may
+ * licensor, an author or contributor be held liable for any indirect
+ * or other damage, or direct damage except proven a consequence of a
+ * direct error of said person and intended use of this work, loss or
+ * other issues arising in any way out of its use, even if advised of
+ * the possibility of such damage or existence of a defect.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
+#if !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__APPLE__)
+#include "fts_gnu.h"
+#else
+#include <fts.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "defs.h"
+#define FTSF_INTERNALS
+#include "fts_subs.h"
+
+__RCSID("$MirOS: contrib/hosted/fwcf/fts_subs.c,v 1.8 2007/07/02 14:53:03 tg Exp $");
+
+static FTS *handle;
+
+char ftsf_prefix[PATH_MAX];
+size_t ftsf_prefixlen;
+
+void
+ftsf_start(const char *root)
+{
+ char *paths[2];
+
+ if (handle != NULL) {
+ if (fts_close(handle))
+ warn("fts_close");
+ free(handle);
+ }
+
+ if (realpath(root, ftsf_prefix) == NULL)
+ err(1, "determine realpath for %s", root);
+ ftsf_prefixlen = strlen(ftsf_prefix) + 1;
+
+ paths[0] = ftsf_prefix;
+ paths[1] = NULL;
+
+ handle = fts_open(paths, FTS_NOCHDIR | FTS_PHYSICAL, NULL);
+
+ if (handle == NULL)
+ err(1, "fts_open on %s for %s", ftsf_prefix, root);
+}
+
+int
+ftsf_next(ftsf_entry *e)
+{
+ FTSENT *ent;
+ char *ename;
+
+ memset(e, 0, sizeof (ftsf_entry));
+
+ if (handle == NULL) {
+ warn("ftsf_next called before ftsf_open");
+ return (-1);
+ }
+
+ ftsf_continue:
+ if ((ent = fts_read(handle)) == NULL) {
+ if (errno == 0) {
+ if (fts_close(handle))
+ warn("fts_close");
+ handle = NULL;
+ return (0);
+ }
+ warn("fts_read");
+ if (fts_close(handle))
+ warn("fts_close");
+ handle = NULL;
+ return (-1);
+ }
+
+ ename = ent->fts_path;
+#if 0 /* debug */
+ if (asprintf(&ename, "accpath<%s> path<%s> name<%s>", ent->fts_accpath,
+ ent->fts_path, ent->fts_name) == -1)
+ err(1, "asprintf");
+#endif
+ if (strcmp(ename, ftsf_prefix)) {
+ if (strlcpy(e->pathname, ename + ftsf_prefixlen,
+ sizeof (e->pathname)) >= sizeof (e->pathname))
+ warn("truncating file name '%s' to '%s'", ename,
+ e->pathname);
+ } else
+ memcpy(e->pathname, ".", 2);
+
+ switch (ent->fts_info) {
+ case FTS_D:
+ e->etype = FTSF_DIR;
+ break;
+ case FTS_DNR:
+ warn("directory %s not readable, skipping: %s", ename,
+ strerror(ent->fts_errno));
+ /* FALLTHROUGH */
+ case FTS_DC:
+ case FTS_DOT:
+ case FTS_DP:
+ goto ftsf_continue;
+ case FTS_DEFAULT:
+ if (S_ISDIR(ent->fts_statp->st_mode))
+ e->etype = FTSF_DIR;
+ else if (S_ISREG(ent->fts_statp->st_mode))
+ e->etype = FTSF_FILE;
+ else if (S_ISLNK(ent->fts_statp->st_mode))
+ e->etype = FTSF_SYMLINK;
+ else
+ e->etype = FTSF_OTHER;
+ break;
+ case FTS_ERR:
+ warn("generic error condition %s on %s, skipping",
+ strerror(ent->fts_errno), ename);
+ goto ftsf_continue;
+ case FTS_F:
+ e->etype = FTSF_FILE;
+ break;
+ case FTS_NSOK:
+ ent->fts_errno = 0;
+ /* FALLTHROUGH */
+ case FTS_NS:
+ warn("skipping due to no stat(2) information on %s: %s",
+ ename, strerror(ent->fts_errno));
+ goto ftsf_continue;
+ case FTS_SL:
+ case FTS_SLNONE:
+ e->etype = FTSF_SYMLINK;
+ break;
+ default:
+ warn("unknown fts_info field for %s: %d, skipping",
+ ename, (int)ent->fts_info);
+ warn("ent->fts_errno = %d (%s)", ent->fts_errno,
+ strerror(ent->fts_errno));
+ goto ftsf_continue;
+ }
+
+ e->statp = ent->fts_statp;
+ return (1);
+}