This API can be used to tell the other side of the stream to skip
some bytes in the stream. This can be used to create a sparse
file on the receiving side of a stream.
It takes just one argument @offset, which says how big the hole
is. Since our streams are not rewindable like regular files, we
don't need @whence argument like seek(2) has.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
include/libvirt/libvirt-stream.h | 3 +++
src/driver-stream.h | 5 +++++
src/libvirt-stream.c | 40 ++++++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 5 +++++
4 files changed, 53 insertions(+)
diff --git a/include/libvirt/libvirt-stream.h b/include/libvirt/libvirt-stream.h
index 831640d..f12d695 100644
--- a/include/libvirt/libvirt-stream.h
+++ b/include/libvirt/libvirt-stream.h
@@ -45,6 +45,9 @@ int virStreamRecv(virStreamPtr st,
char *data,
size_t nbytes);
+int virStreamSkip(virStreamPtr st,
+ unsigned long long offset);
+
/**
* virStreamSourceFunc:
diff --git a/src/driver-stream.h b/src/driver-stream.h
index 85b4e3b..786d7b6 100644
--- a/src/driver-stream.h
+++ b/src/driver-stream.h
@@ -36,6 +36,10 @@ typedef int
size_t nbytes);
typedef int
+(*virDrvStreamSkip)(virStreamPtr st,
+ unsigned long long offset);
+
+typedef int
(*virDrvStreamEventAddCallback)(virStreamPtr stream,
int events,
virStreamEventCallback cb,
@@ -61,6 +65,7 @@ typedef virStreamDriver *virStreamDriverPtr;
struct _virStreamDriver {
virDrvStreamSend streamSend;
virDrvStreamRecv streamRecv;
+ virDrvStreamSkip streamSkip;
virDrvStreamEventAddCallback streamEventAddCallback;
virDrvStreamEventUpdateCallback streamEventUpdateCallback;
virDrvStreamEventRemoveCallback streamEventRemoveCallback;
diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
index 8384b37..1c9a12b 100644
--- a/src/libvirt-stream.c
+++ b/src/libvirt-stream.c
@@ -286,6 +286,46 @@ virStreamRecv(virStreamPtr stream,
/**
+ * virStreamSkip:
+ * @stream: pointer to the stream object
+ * @offset: number of bytes to skip
+ *
+ * Skip @offset bytes in the stream. This is useful when there's
+ * no actual data in the stream, just a hole. If that's the case,
+ * this API can be used to skip the hole properly instead of
+ * transmitting zeroes to the other side.
+ *
+ * Returns 0 on success,
+ * -1 error
+ */
+int
+virStreamSkip(virStreamPtr stream,
+ unsigned long long offset)
+{
+ VIR_DEBUG("stream=%p, offset=%llu", stream, offset);
+
+ virResetLastError();
+
+ virCheckStreamReturn(stream, -1);
+
+ if (stream->driver &&
+ stream->driver->streamSkip) {
+ int ret;
+ ret = (stream->driver->streamSkip)(stream, offset);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+
+ error:
+ virDispatchError(stream->conn);
+ return -1;
+}
+
+
+/**
* virStreamSendAll:
* @stream: pointer to the stream object
* @handler: source callback for reading data from application
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 1e920d6..b4c693a 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -732,4 +732,9 @@ LIBVIRT_1.3.3 {
virDomainSetPerfEvents;
} LIBVIRT_1.2.19;
+LIBVIRT_1.3.5 {
+ global:
+ virStreamSkip;
+} LIBVIRT_1.3.3;
+
# .... define new API here using predicted next version number ....
--
2.8.1