#define MIN(a, b) (((a) < (b))? (a) : (b))
-static void do_ls(struct xs_handle *h, char *path, int cur_depth, int show_perms)
+static int do_ls(struct xs_handle *h, char *path, int cur_depth, int show_perms, int error, int ignore_errors)
{
char **e;
char *newpath, *val;
e = xs_directory(h, XBT_NULL, path, &num);
if (e == NULL) {
- if (cur_depth && errno == ENOENT) {
- /* If a node disappears while recursing, silently move on. */
- return;
+ if (cur_depth && (errno == ENOENT || errno == EACCES)) {
+ /*
+ * If a node disappears or becomes inaccessible while traversing,
+ * only print an error if previous operations on this node haven't
+ * done do. Then move on.
+ */
+ error = errno;
+ if (!ignore_errors)
+ warn("xs_directory (%s)", path);
+ return error;
}
err(1, "xs_directory (%s)", path);
/* Print value */
if (val == NULL) {
- printf(":\n");
+ error = errno;
+ printf(": (%s)", strerror(error));
}
else {
if (max_width < (linewid + len + TAG_LEN)) {
if (show_perms) {
perms = xs_get_permissions(h, XBT_NULL, newpath, &nperms);
if (perms == NULL) {
- warn("\ncould not access permissions for %s", e[i]);
+ error = errno;
+ val = NULL;
+ /* Don't repeat an error message if xs_read() already failed */
+ if (val)
+ warn("could not access permissions for %s", e[i]);
}
else {
int i;
}
putchar('\n');
-
- do_ls(h, newpath, cur_depth+1, show_perms);
+
+ error = do_ls(h, newpath, cur_depth+1, show_perms, error, !val);
}
free(e);
free(newpath);
+
+ return error;
}
static void
break;
}
case MODE_ls: {
- do_ls(xsh, argv[optind], 0, prefix);
+ int error = do_ls(xsh, argv[optind], 0, prefix, 0, 0);
+ if (error) {
+ errx(1, "Errors during traversal. Last error: %s", strerror(error));
+ }
optind++;
break;
}