[Libguestfs] [nbdkit PATCH] sh: Parse a larger number of error messages

Eric Blake eblake at redhat.com
Tue Jul 2 22:36:26 UTC 2019


In order to trigger a non-EIO failure, a script had to output
_exactly_ 'EINVAL ' or similar, with one trailing space and no
message, because we forgot to limit the length of the string
comparison. Fix things to tolerate an error name without a message,
as well as to be case-insensitive.

Also, parse EOVERFLOW (missed in commit 6f8c8084).

Signed-off-by: Eric Blake <eblake at redhat.com>
---

I'm also working on adding tests/test-sh-errors.h to ensure we
don't regress, I'll push that along with this once I get it working.

 plugins/sh/nbdkit-sh-plugin.pod |  4 +--
 plugins/sh/call.c               | 45 +++++++++++++++++++++++----------
 2 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/plugins/sh/nbdkit-sh-plugin.pod b/plugins/sh/nbdkit-sh-plugin.pod
index f108051f..55ee6c69 100644
--- a/plugins/sh/nbdkit-sh-plugin.pod
+++ b/plugins/sh/nbdkit-sh-plugin.pod
@@ -85,5 +85,5 @@ The method was executed successfully.

 =item 1 and 8-127

-There was an error.  The script may print on stderr an errno and a
-message, for example:
+There was an error.  The script may print on stderr an errno name,
+optionally followed by whitespace and a message, for example:

  ENOSPC Out of space

diff --git a/plugins/sh/call.c b/plugins/sh/call.c
index f69523c1..585bd32c 100644
--- a/plugins/sh/call.c
+++ b/plugins/sh/call.c
@@ -42,6 +42,7 @@
 #include <poll.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <ctype.h>

 #include <nbdkit-plugin.h>

@@ -267,32 +268,36 @@ static void
 handle_script_error (char *ebuf, size_t len)
 {
   int err;
-  size_t skip;
+  size_t skip = 0;
   char *p;

-  if (strcmp (ebuf, "EPERM ") == 0) {
+  if (strncasecmp (ebuf, "EPERM", 5) == 0) {
     err = EPERM;
-    skip = 6;
+    skip = 5;
   }
-  else if (strcmp (ebuf, "EIO ") == 0) {
+  else if (strncasecmp (ebuf, "EIO", 3) == 0) {
     err = EIO;
-    skip = 4;
+    skip = 3;
   }
-  else if (strcmp (ebuf, "ENOMEM ") == 0) {
+  else if (strncasecmp (ebuf, "ENOMEM", 6) == 0) {
     err = ENOMEM;
-    skip = 7;
+    skip = 6;
   }
-  else if (strcmp (ebuf, "EINVAL ") == 0) {
+  else if (strncasecmp (ebuf, "EINVAL", 6) == 0) {
     err = EINVAL;
-    skip = 7;
+    skip = 6;
   }
-  else if (strcmp (ebuf, "ENOSPC ") == 0) {
+  else if (strncasecmp (ebuf, "ENOSPC", 6) == 0) {
     err = ENOSPC;
     skip = 7;
   }
-  else if (strcmp (ebuf, "ESHUTDOWN ") == 0) {
+  else if (strncasecmp (ebuf, "EOVERFLOW", 9) == 0) {
+    err = EOVERFLOW;
+    skip = 9;
+  }
+  else if (strncasecmp (ebuf, "ESHUTDOWN", 9) == 0) {
     err = ESHUTDOWN;
-    skip = 10;
+    skip = 9;
   }
   else {
     /* Default to EIO. */
@@ -300,6 +305,18 @@ handle_script_error (char *ebuf, size_t len)
     skip = 0;
   }

+  if (skip && ebuf[skip]) {
+    if (!isspace ((unsigned char) ebuf[skip])) {
+      /* Treat 'EINVALID' as EIO, not EINVAL */
+      err = EIO;
+      skip = 0;
+    }
+    else
+      do
+        skip++;
+      while (isspace ((unsigned char) ebuf[skip]));
+  }
+
   while (len > 0 && ebuf[len-1] == '\n')
     ebuf[--len] = '\0';

@@ -311,8 +328,8 @@ handle_script_error (char *ebuf, size_t len)
       /* ... but truncate it for the error message below. */
       *p = '\0';
     }
-    if (strlen (ebuf) >= skip)
-      ebuf += skip;
+    assert (strlen (ebuf) >= skip);
+    ebuf += skip;
     nbdkit_error ("%s: %s", script, ebuf);
   }
   else
-- 
2.20.1




More information about the Libguestfs mailing list