Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/fdstream.c | 35 +++++++++++++++++++++++++++++++----
1 file changed, 31 insertions(+), 4 deletions(-)
diff --git a/src/fdstream.c b/src/fdstream.c
index a85cf9d..403ddf6 100644
--- a/src/fdstream.c
+++ b/src/fdstream.c
@@ -353,10 +353,14 @@ virFDStreamAbort(virStreamPtr st)
return virFDStreamCloseInt(st, true);
}
-static int virFDStreamWrite(virStreamPtr st, const char *bytes, size_t nbytes)
+static int
+virFDStreamWriteInternal(virStreamPtr st,
+ off_t offset,
+ const char *bytes,
+ size_t nbytes)
{
struct virFDStreamData *fdst = st->privateData;
- int ret;
+ int ret = -1;
if (nbytes > INT_MAX) {
virReportSystemError(ERANGE, "%s",
@@ -376,14 +380,20 @@ static int virFDStreamWrite(virStreamPtr st, const char *bytes,
size_t nbytes)
if (fdst->length == fdst->offset) {
virReportSystemError(ENOSPC, "%s",
_("cannot write to stream"));
- virMutexUnlock(&fdst->lock);
- return -1;
+ goto cleanup;
}
if ((fdst->length - fdst->offset) < nbytes)
nbytes = fdst->length - fdst->offset;
}
+ if (offset != (off_t) -1 &&
+ lseek(fdst->fd, offset, SEEK_SET) < 0) {
+ virReportSystemError(errno, "%s",
+ _("unable to set stream position"));
+ goto cleanup;
+ }
+
retry:
ret = write(fdst->fd, bytes, nbytes);
if (ret < 0) {
@@ -395,15 +405,31 @@ static int virFDStreamWrite(virStreamPtr st, const char *bytes,
size_t nbytes)
ret = -1;
virReportSystemError(errno, "%s",
_("cannot write to stream"));
+ goto cleanup;
}
} else if (fdst->length) {
fdst->offset += ret;
}
+ cleanup:
virMutexUnlock(&fdst->lock);
return ret;
}
+static int
+virFDStreamWrite(virStreamPtr st, const char *bytes, size_t nbytes)
+{
+ return virFDStreamWriteInternal(st, (off_t) -1, bytes, nbytes);
+}
+
+static int
+virFDStreamWriteOffset(virStreamPtr st,
+ unsigned long long offset,
+ const char *bytes,
+ size_t nbytes)
+{
+ return virFDStreamWriteInternal(st, offset, bytes, nbytes);
+}
static int virFDStreamRead(virStreamPtr st, char *bytes, size_t nbytes)
{
@@ -457,6 +483,7 @@ static int virFDStreamRead(virStreamPtr st, char *bytes, size_t
nbytes)
static virStreamDriver virFDStreamDrv = {
.streamSend = virFDStreamWrite,
+ .streamSendOffset = virFDStreamWriteOffset,
.streamRecv = virFDStreamRead,
.streamFinish = virFDStreamClose,
.streamAbort = virFDStreamAbort,
--
2.4.10