aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cftw.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/cftw.c b/cftw.c
index f512232..5083cc4 100644
--- a/cftw.c
+++ b/cftw.c
@@ -101,11 +101,14 @@ failure:
return NULL;
}
-static enum cftw_state run(struct cftw *const c, struct cftw_entry *const e)
+static enum cftw_state run(struct cftw *const c, struct cftw_entry *const e,
+ struct cftw_entry *const root)
{
- int error;
+ int error = 0;
struct dirent *de;
struct dynstr d;
+ const char *const dirpath = e->dirpath;
+ struct stat sb;
dynstr_init(&d);
errno = 0;
@@ -117,15 +120,25 @@ static enum cftw_state run(struct cftw *const c, struct cftw_entry *const e)
goto failure;
}
else if (!de)
- return CFTW_OK;
+ {
+ if (e == root)
+ return CFTW_OK;
+ else if (stat(dirpath, &sb))
+ {
+ fprintf(stderr, "%s: stat(2) %s: %s\n", __func__, dirpath,
+ strerror(errno));
+ goto failure;
+ }
- const char *const path = de->d_name, *const dirpath = e->dirpath;
+ return c->fn(dirpath, &sb, &c->done, c->user) ? CFTW_FATAL : CFTW_OK;
+ }
+
+ const char *const path = de->d_name;
if (!strcmp(path, ".") || !strcmp(path, ".."))
return CFTW_AGAIN;
const char *const sep = dirpath[strlen(dirpath) - 1] == '/' ? "" : "/";
- struct stat sb;
if (dynstr_append(&d, "%s%s%s", dirpath, sep, path))
{
@@ -145,8 +158,6 @@ static enum cftw_state run(struct cftw *const c, struct cftw_entry *const e)
{
if (!(e->child = entry(d.str)))
goto failure;
-
- error = c->fn(d.str, &sb, &c->done, c->user);
}
else if (S_ISREG(sb.st_mode))
error = c->fn(d.str, &sb, &c->done, c->user);
@@ -171,11 +182,12 @@ failure:
return CFTW_FATAL;
}
-static enum cftw_state step(struct cftw *const c, struct cftw_entry *const e)
+static enum cftw_state step(struct cftw *const c, struct cftw_entry *const e,
+ struct cftw_entry *const root)
{
if (e->child)
{
- switch (step(c, e->child))
+ switch (step(c, e->child, root))
{
case CFTW_AGAIN:
return CFTW_AGAIN;
@@ -195,12 +207,12 @@ static enum cftw_state step(struct cftw *const c, struct cftw_entry *const e)
return CFTW_AGAIN;
}
- return run(c, e);
+ return run(c, e, root);
}
-enum cftw_state cftw_step(struct cftw *c)
+enum cftw_state cftw_step(struct cftw *const c)
{
- return step(c, c->root);
+ return step(c, c->root, c->root);
}
struct cftw *cftw(const char *const dirpath, int (*const fn)(const char *,