Finally, now that everything is prepared, we can wire up formatted messages for iohelper too. Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list