]> xenbits.xensource.com Git - people/dwmw2/xen.git/commitdiff
tools/xenstore: Accumulate errors in xenstore-ls and exit appropriately xenstore-ls
authorDavid Woodhouse <dwmw@amazon.co.uk>
Fri, 9 Aug 2019 12:09:46 +0000 (13:09 +0100)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Thu, 19 Mar 2020 20:32:31 +0000 (20:32 +0000)
Report only one error to stderr for each node, regardless of whether it's
xs_read, xs_get_permissions or xs_directory on the child that fails.

Always exit with a non-zero code if any failure happens, reporting the
last error that occurred.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
tools/xenstore/xenstore_client.c

index ae7ed3eb9e37256544d869ebaa7acd0515476c51..0c891961aebd7b3551069cc4d40f53400828a770 100644 (file)
@@ -140,7 +140,7 @@ static int show_whole_path = 0;
 
 #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;
@@ -150,9 +150,16 @@ static void do_ls(struct xs_handle *h, char *path, int cur_depth, int show_perms
 
     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);
@@ -197,7 +204,8 @@ static void do_ls(struct xs_handle *h, char *path, int cur_depth, int show_perms
 
         /* Print value */
         if (val == NULL) {
-            printf(":\n");
+            error = errno;
+            printf(": (%s)", strerror(error));
         }
         else {
             if (max_width < (linewid + len + TAG_LEN)) {
@@ -222,7 +230,11 @@ static void do_ls(struct xs_handle *h, char *path, int cur_depth, int show_perms
         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;
@@ -238,11 +250,13 @@ static void do_ls(struct xs_handle *h, char *path, int cur_depth, int show_perms
         }
 
         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
@@ -448,7 +462,10 @@ perform(enum mode mode, int optind, int argc, char **argv, struct xs_handle *xsh
             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;
         }