Eric Blake
2019-Jul-02 22:36 UTC
[Libguestfs] [nbdkit PATCH] sh: Parse a larger number of error messages
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@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
Richard W.M. Jones
2019-Jul-04 09:50 UTC
Re: [Libguestfs] [nbdkit PATCH] sh: Parse a larger number of error messages
ACK, thanks. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://people.redhat.com/~rjones/virt-top
Reasonably Related Threads
- [PATCH nbdkit] common/include: Add locale-safe ascii_strcasecmp and ascii_strncasecmp.
- [PATCH nbdkit] sh: Don't need to cast parameter of ascii_is* to (unsigned char).
- [nbdkit PATCH 1/3] server: Add internal support for NBDKIT_FLAG_FAST_ZERO
- [nbdkit PATCH] sh: Allow pwrite to not consume all data
- [nbdkit PATCH] sh: Allow pwrite to not consume all data