Finally, now that everything is prepared, we can wire up
formatted messages for iohelper too.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/Makefile.am | 2 +
src/iohelper/iohelper.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 115 insertions(+)
diff --git a/src/Makefile.am b/src/Makefile.am
index 1cce603..f5bc5b6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2867,6 +2867,8 @@ libvirt_iohelper_LDFLAGS = \
$(NULL)
libvirt_iohelper_LDADD = \
libvirt_util.la \
+ libvirt-iohelper.la \
+ libvirt-net-rpc.la \
../gnulib/lib/libgnu.la
if WITH_DTRACE_PROBES
libvirt_iohelper_LDADD += libvirt_probes.lo
diff --git a/src/iohelper/iohelper.c b/src/iohelper/iohelper.c
index 65fbc63..4b431af 100644
--- a/src/iohelper/iohelper.c
+++ b/src/iohelper/iohelper.c
@@ -32,6 +32,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "iohelper_message.h"
#include "virutil.h"
#include "virthread.h"
#include "virfile.h"
@@ -40,6 +41,7 @@
#include "virrandom.h"
#include "virstring.h"
#include "virgettext.h"
+#include "virobject.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE
@@ -228,6 +230,114 @@ runIOBasic(const char *path, int fd, int oflags, unsigned long long
length)
static int
+runIOFormatted(const char *path,
+ int fd,
+ int oflags,
+ unsigned long long length)
+{
+ int ret = -1;
+ int fdin, fdout;
+ const char *fdinname, *fdoutname;
+ unsigned long long total = 0;
+ iohelperCtlPtr ioCtl = NULL;
+ char *buf = NULL;
+ size_t bufLen = 1024 * 1024;
+ bool formattedIN, formattedOUT;
+
+ if (VIR_ALLOC_N(buf, bufLen) < 0)
+ goto cleanup;
+
+ if (setupFDs(path, fd, oflags,
+ &fdin, &fdinname,
+ &fdout, &fdoutname) < 0)
+ goto cleanup;
+
+ /* Maybe this looks a bit silly. But it's simple. Either we
+ * are reading from @fd and writing to stdout, or we're
+ * reading from stdin and writing to @fd. But the formatted
+ * messages occurs just on std* not @fd. */
+ formattedIN = fdout == fd;
+ formattedOUT = fdin == fd;
+
+ if (!(ioCtl = iohelperCtlNew(formattedIN ? fdin : fdout, true)))
+ goto cleanup;
+
+ while (true) {
+ ssize_t nread, nwritten, want = bufLen;
+ int inData = 1;
+ unsigned long long sectionLength;
+
+ if (formattedOUT) {
+ if (virFileInData(fdin, &inData, §ionLength) < 0)
+ goto cleanup;
+
+ if (!inData) {
+ if (iohelperSkip(ioCtl, sectionLength) < 0)
+ goto cleanup;
+ if (!sectionLength)
+ break;
+ if (lseek(fdin, sectionLength, SEEK_CUR) == (off_t) -1) {
+ virReportSystemError(errno,
+ _("Unable to seek in %s"),
fdoutname);
+ goto cleanup;
+ }
+ continue;
+ } else {
+ want = MIN(sectionLength, bufLen);
+ }
+ } else {
+ if (iohelperInData(ioCtl, &inData, §ionLength) < 0)
+ goto cleanup;
+
+ if (!inData) {
+ if (!sectionLength)
+ break;
+
+ if (lseek(fdout, sectionLength, SEEK_CUR) == (off_t) -1) {
+ virReportSystemError(errno,
+ _("Unable to seek in %s"),
fdoutname);
+ goto cleanup;
+ }
+ continue;
+ } else {
+ want = MIN(sectionLength, bufLen);
+ }
+ }
+
+ if (length &&
+ (length - total) < want)
+ want = length - total;
+
+ if (want == 0)
+ break; /* End of requested data from client */
+
+ if ((formattedIN && (nread = iohelperRead(ioCtl, buf, want)) < 0) ||
+ (!formattedIN && (nread = saferead(fdin, buf, want)) < 0)) {
+ virReportSystemError(errno, _("Unable to read %s"), fdinname);
+ goto cleanup;
+ }
+
+ if (!nread)
+ break;
+
+ total += nread;
+
+ if ((formattedOUT && (nwritten = iohelperWrite(ioCtl, buf, nread)) <
0) ||
+ (!formattedOUT && (nwritten = safewrite(fdout, buf, nread)) < 0))
{
+ virReportSystemError(errno, _("Unable to write %s"), fdoutname);
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+ cleanup:
+ virObjectUnref(ioCtl);
+ VIR_FREE(buf);
+ return ret;
+}
+
+
+static int
runIO(const char *path, int fd, int oflags,
unsigned long long length, bool sparse)
{
@@ -240,6 +350,9 @@ runIO(const char *path, int fd, int oflags,
return -1;
}
+ if (sparse)
+ return runIOFormatted(path, fd, oflags, length);
+
return runIOBasic(path, fd, oflags, length);
}
--
2.8.4