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(a)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