diff --git a/include/libvirt/libvirt-stream.h b/include/libvirt/libvirt-stream.h index bee25168b4..14c9af1429 100644 --- a/include/libvirt/libvirt-stream.h +++ b/include/libvirt/libvirt-stream.h @@ -50,6 +50,10 @@ int virStreamRecvFlags(virStreamPtr st, size_t nbytes, unsigned int flags); +int virStreamSendHole(virStreamPtr st, + long long length, + unsigned int flags); + /** * virStreamSourceFunc: diff --git a/src/driver-stream.h b/src/driver-stream.h index d4b048018d..0a52014312 100644 --- a/src/driver-stream.h +++ b/src/driver-stream.h @@ -41,6 +41,11 @@ typedef int size_t nbytes, unsigned int flags); +typedef int +(*virDrvStreamSendHole)(virStreamPtr st, + long long length, + unsigned int flags); + typedef int (*virDrvStreamEventAddCallback)(virStreamPtr stream, int events, @@ -68,6 +73,7 @@ struct _virStreamDriver { virDrvStreamSend streamSend; virDrvStreamRecv streamRecv; virDrvStreamRecvFlags streamRecvFlags; + virDrvStreamSendHole streamSendHole; virDrvStreamEventAddCallback streamEventAddCallback; virDrvStreamEventUpdateCallback streamEventUpdateCallback; virDrvStreamEventRemoveCallback streamEventRemoveCallback; diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c index 7535deb3c7..a09896dcdf 100644 --- a/src/libvirt-stream.c +++ b/src/libvirt-stream.c @@ -344,6 +344,67 @@ virStreamRecvFlags(virStreamPtr stream, } +/** + * virStreamSendHole: + * @stream: pointer to the stream object + * @length: number of bytes to skip + * @flags: extra flags; not used yet, so callers should always pass 0 + * + * Rather than transmitting empty file space, this API directs + * the @stream target to create @length bytes of empty space. + * This API would be used when uploading or downloading sparsely + * populated files to avoid the needless copy of empty file + * space. + * + * An example using this with a hypothetical file upload API + * looks like: + * + * virStream st; + * + * while (1) { + * char buf[4096]; + * size_t len; + * if (..in hole...) { + * ..get hole size... + * virStreamSendHole(st, len, 0); + * } else { + * ...read len bytes... + * virStreamSend(st, buf, len); + * } + * } + * + * Returns 0 on success, + * -1 error + */ +int +virStreamSendHole(virStreamPtr stream, + long long length, + unsigned int flags) +{ + VIR_DEBUG("stream=%p, length=%lld flags=%x", + stream, length, flags); + + virResetLastError(); + + virCheckStreamReturn(stream, -1); + + if (stream->driver && + stream->driver->streamSendHole) { + int ret; + ret = (stream->driver->streamSendHole)(stream, length, flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(stream->conn); + return -1; +} + + /** * virStreamSendAll: * @stream: pointer to the stream object diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index d50b36a247..3be7cc6a0b 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -762,6 +762,7 @@ LIBVIRT_3.1.0 { LIBVIRT_3.4.0 { global: virStreamRecvFlags; + virStreamSendHole; } LIBVIRT_3.1.0; # .... define new API here using predicted next version number ....