diff --git a/tar/tree.c b/tar/tree.c index 9ec3c2ff..e245ee0e 100644 --- a/tar/tree.c +++ b/tar/tree.c @@ -392,6 +392,7 @@ tree_next(struct tree *t) if (de == NULL) { if (errno) { /* If readdir fails, we're screwed. */ + t->tree_errno = errno; closedir(t->d); t->d = NULL; t->visit_type = TREE_ERROR_FATAL; @@ -438,16 +439,16 @@ tree_next(struct tree *t) t->dirname_length = t->path_length; if (chdir(t->stack->name) != 0) { /* chdir() failed; return error */ - tree_pop(t); t->tree_errno = errno; + tree_pop(t); return (t->visit_type = TREE_ERROR_DIR); } t->depth++; t->d = opendir("."); if (t->d == NULL) { + t->tree_errno = errno; r = tree_ascend(t); /* Undo "chdir" */ tree_pop(t); - t->tree_errno = errno; t->visit_type = r != 0 ? r : TREE_ERROR_DIR; return (t->visit_type); } diff --git a/tar/tree.h b/tar/tree.h index a7513174..dd3f3e9a 100644 --- a/tar/tree.h +++ b/tar/tree.h @@ -71,7 +71,8 @@ int tree_close(struct tree *); * fatal error, but it does imply that the relevant subtree won't be * visited. TREE_ERROR_FATAL is returned for an error that left the * traversal completely hosed. Right now, this is only returned for - * chdir() failures during ascent. + * chdir() failures during ascent, or readdir() failures when looking + * for the next entry. */ #define TREE_REGULAR 1 #define TREE_POSTDESCENT 2 diff --git a/tar/write.c b/tar/write.c index 5615d990..136c97d8 100644 --- a/tar/write.c +++ b/tar/write.c @@ -793,7 +793,7 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path) "%s: Unable to continue traversing directory tree", name); if (tree_ret == TREE_ERROR_DIR) { - bsdtar_warnc(bsdtar, errno, + bsdtar_warnc(bsdtar, tree_errno(tree), "%s: Couldn't visit directory", name); bsdtar->return_value = 1; }