diff options
author | cl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk> | 2005-10-18 02:08:26 +0100 |
---|---|---|
committer | cl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk> | 2005-10-18 02:08:26 +0100 |
commit | 006b46b2d010366415749591af35dd2900e6e6a0 (patch) | |
tree | 76ededf4512b971c3624144a0e257db8592b918b /tools/xenstore/xenstore_client.c | |
parent | fe453929d395355f1bd2a63a350fa8b22212bdec (diff) | |
download | xen-006b46b2d010366415749591af35dd2900e6e6a0.tar.gz xen-006b46b2d010366415749591af35dd2900e6e6a0.tar.bz2 xen-006b46b2d010366415749591af35dd2900e6e6a0.zip |
Fix transaction EAGAIN handling in xenstore client programs.
Redirect all output to a buffer and only print the buffer once the
transaction succeeds, discarding output from previous attempts.
In particular, fixes failures when the (block) backend driver would
not configure because reads from the hotplug script did get double
output when a transaction had to be redone.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
Diffstat (limited to 'tools/xenstore/xenstore_client.c')
-rw-r--r-- | tools/xenstore/xenstore_client.c | 52 |
1 files changed, 45 insertions, 7 deletions
diff --git a/tools/xenstore/xenstore_client.c b/tools/xenstore/xenstore_client.c index d18b2de5e1..2d36520653 100644 --- a/tools/xenstore/xenstore_client.c +++ b/tools/xenstore/xenstore_client.c @@ -9,13 +9,45 @@ */ #include <err.h> +#include <errno.h> #include <fcntl.h> #include <getopt.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <xs.h> -#include <errno.h> + +static char *output_buf = NULL; +static int output_pos = 0; + +#if defined(CLIENT_read) || defined(CLIENT_list) +static int output_size = 0; + +static void +output(const char *fmt, ...) { + va_list ap; + int len; + char buf[1]; + + va_start(ap, fmt); + len = vsnprintf(buf, 1, fmt, ap); + if (len < 0) + err(1, "output"); + va_end(ap); + if (len + 1 + output_pos > output_size) { + output_size += len + 1024; + output_buf = realloc(output_buf, output_size); + if (output_buf == NULL) + err(1, "malloc"); + } + va_start(ap, fmt); + if (vsnprintf(&output_buf[output_pos], len + 1, fmt, ap) != len) + err(1, "output"); + va_end(ap); + output_pos += len; +} +#endif static void usage(const char *progname) @@ -34,7 +66,7 @@ usage(const char *progname) #if defined(CLIENT_rm) static int -do_rm(char * path, struct xs_handle *xsh, struct xs_transaction_handle *xth) +do_rm(char *path, struct xs_handle *xsh, struct xs_transaction_handle *xth) { if (xs_rm(xsh, xth, path)) { return 0; @@ -59,8 +91,8 @@ perform(int optind, int argc, char **argv, struct xs_handle *xsh, return 1; } if (prefix) - printf("%s: ", argv[optind]); - printf("%s\n", val); + output("%s: ", argv[optind]); + output("%s\n", val); free(val); optind++; #elif defined(CLIENT_write) @@ -131,8 +163,8 @@ perform(int optind, int argc, char **argv, struct xs_handle *xsh, } for (i = 0; i < num; i++) { if (prefix) - printf("%s/", argv[optind]); - printf("%s\n", list[i]); + output("%s/", argv[optind]); + output("%s\n", list[i]); } free(list); optind++; @@ -217,9 +249,15 @@ main(int argc, char **argv) ret = perform(optind, argc, argv, xsh, xth, prefix, tidy); if (!xs_transaction_end(xsh, xth, ret)) { - if (ret == 0 && errno == EAGAIN) + if (ret == 0 && errno == EAGAIN) { + output_pos = 0; goto again; + } errx(1, "couldn't end transaction"); } + + if (output_pos) + printf("%s", output_buf); + return ret; } |