aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xenstore/xenstore_client.c
diff options
context:
space:
mode:
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>2005-10-18 02:08:26 +0100
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>2005-10-18 02:08:26 +0100
commit006b46b2d010366415749591af35dd2900e6e6a0 (patch)
tree76ededf4512b971c3624144a0e257db8592b918b /tools/xenstore/xenstore_client.c
parentfe453929d395355f1bd2a63a350fa8b22212bdec (diff)
downloadxen-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.c52
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;
}