From f095481862ccd175d297da67d0e313d135bd75c3 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 27 May 2024 13:37:49 -0400 Subject: eval: Print more information on filesystem loops --- src/bftw.c | 2 ++ src/bftw.h | 2 ++ src/eval.c | 16 +++++++++++++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/bftw.c b/src/bftw.c index c80ac74..b3fd62a 100644 --- a/src/bftw.c +++ b/src/bftw.c @@ -1676,6 +1676,7 @@ static void bftw_init_ftwbuf(struct bftw_state *state, enum bftw_visit visit) { ftwbuf->visit = visit; ftwbuf->type = BFS_UNKNOWN; ftwbuf->error = state->direrror; + ftwbuf->loopoff = 0; ftwbuf->at_fd = AT_FDCWD; ftwbuf->at_path = ftwbuf->path; bftw_stat_init(&ftwbuf->stat_bufs, &state->stat_buf, &state->lstat_buf); @@ -1733,6 +1734,7 @@ static void bftw_init_ftwbuf(struct bftw_state *state, enum bftw_visit visit) { if (ancestor->dev == statbuf->dev && ancestor->ino == statbuf->ino) { ftwbuf->type = BFS_ERROR; ftwbuf->error = ELOOP; + ftwbuf->loopoff = ancestor->nameoff + ancestor->namelen; return; } } diff --git a/src/bftw.h b/src/bftw.h index 8656ca7..a2a201c 100644 --- a/src/bftw.h +++ b/src/bftw.h @@ -56,6 +56,8 @@ struct BFTW { enum bfs_type type; /** The errno that occurred, if type == BFS_ERROR. */ int error; + /** For filesystem loops, the length of the loop prefix. */ + size_t loopoff; /** A parent file descriptor for the *at() family of calls. */ int at_fd; diff --git a/src/eval.c b/src/eval.c index 8490bd4..36b2f11 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1433,10 +1433,20 @@ static enum bftw_action eval_callback(const struct BFTW *ftwbuf, void *ptr) { } if (ftwbuf->type == BFS_ERROR) { - if (!eval_should_ignore(&state, ftwbuf->error)) { - eval_error(&state, "%s.\n", xstrerror(ftwbuf->error)); - } state.action = BFTW_PRUNE; + + if (ftwbuf->error == ELOOP && ftwbuf->loopoff > 0) { + char *loop = strndup(ftwbuf->path, ftwbuf->loopoff); + if (loop) { + eval_error(&state, "Filesystem loop back to ${di}%pq${rs}\n", loop); + free(loop); + goto done; + } + } else if (eval_should_ignore(&state, ftwbuf->error)) { + goto done; + } + + eval_error(&state, "%s.\n", xstrerror(ftwbuf->error)); goto done; } -- cgit v1.2.3