diff options
Diffstat (limited to 'package/cfgfs/src/fts_subs.c')
-rw-r--r-- | package/cfgfs/src/fts_subs.c | 163 |
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); +} |