use libarchive for compressed stream support
Signed-off-by: Vasiliy Tolstov <v.tolstov(a)selfip.ru>
---
configure.ac | 11 ++++++--
include/libvirt/libvirt-stream.h | 6 +++++
m4/virt-archive.m4 | 26 +++++++++++++++++++
src/fdstream.c | 47 +++++++++++++++++++++++++++++++++
src/libvirt-stream.c | 56 +++++++++++++++++++++++++++++++++++++++-
src/libvirt_public.syms | 7 +++++
6 files changed, 150 insertions(+), 3 deletions(-)
create mode 100644 m4/virt-archive.m4
diff --git a/configure.ac b/configure.ac
index 03463b0..4018b49 100644
--- a/configure.ac
+++ b/configure.ac
@@ -250,6 +250,7 @@ LIBVIRT_CHECK_SANLOCK
LIBVIRT_CHECK_SASL
LIBVIRT_CHECK_SELINUX
LIBVIRT_CHECK_SSH2
+LIBVIRT_CHECK_LIBARCHIVE
LIBVIRT_CHECK_SYSTEMD_DAEMON
LIBVIRT_CHECK_UDEV
LIBVIRT_CHECK_WIRESHARK
@@ -1603,8 +1604,6 @@ fi
AC_SUBST([LIBPCAP_CFLAGS])
AC_SUBST([LIBPCAP_LIBS])
-
-
dnl
dnl Checks for the UML driver
dnl
@@ -2097,6 +2096,13 @@ AM_CONDITIONAL([WITH_STORAGE_DISK], [test
"$with_storage_disk" = "yes"])
AC_SUBST([LIBPARTED_CFLAGS])
AC_SUBST([LIBPARTED_LIBS])
+if test "$with_libarchive" = "yes" || test
"$with_libarchive" = "check"; then
+ PKG_CHECK_MODULES([LIBARCHIVE], [libarchive >= 3.1.2], [], [LIBARCHIVE_FOUND=no])
+fi
+AC_SUBST([LIBARCHIVE_CFLAGS])
+AC_SUBST([LIBARCHIVE_LIBS])
+
+
if test "$with_storage_mpath" = "yes" ||
test "$with_storage_disk" = "yes"; then
DEVMAPPER_CFLAGS=
@@ -2892,6 +2898,7 @@ LIBVIRT_RESULT_SANLOCK
LIBVIRT_RESULT_SASL
LIBVIRT_RESULT_SELINUX
LIBVIRT_RESULT_SSH2
+LIBVIRT_RESULT_LIBARCHIVE
LIBVIRT_RESULT_SYSTEMD_DAEMON
LIBVIRT_RESULT_UDEV
LIBVIRT_RESULT_WIRESHARK
diff --git a/include/libvirt/libvirt-stream.h b/include/libvirt/libvirt-stream.h
index 831640d..ac48fba 100644
--- a/include/libvirt/libvirt-stream.h
+++ b/include/libvirt/libvirt-stream.h
@@ -35,6 +35,12 @@ typedef enum {
virStreamPtr virStreamNew(virConnectPtr conn,
unsigned int flags);
+virStreamPtr virStreamNewLz4(virConnectPtr conn,
+ unsigned int flags);
+virStreamPtr virStreamNewGzip(virConnectPtr conn,
+ unsigned int flags);
+virStreamPtr virStreamNewXz(virConnectPtr conn,
+ unsigned int flags);
int virStreamRef(virStreamPtr st);
int virStreamSend(virStreamPtr st,
diff --git a/m4/virt-archive.m4 b/m4/virt-archive.m4
new file mode 100644
index 0000000..b550c41
--- /dev/null
+++ b/m4/virt-archive.m4
@@ -0,0 +1,26 @@
+dnl The libarchive.so library
+dnl
+dnl Copyright (C) 2012-2013 Red Hat, Inc.
+dnl
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Lesser General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2.1 of the License, or (at your option) any later version.
+dnl
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl Lesser General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU Lesser General Public
+dnl License along with this library. If not, see
+dnl <
http://www.gnu.org/licenses/>.
+dnl
+
+AC_DEFUN([LIBVIRT_CHECK_LIBARCHIVE],[
+ LIBVIRT_CHECK_PKG([LIBARCHIVE], [libarchive], [3.1.2])
+])
+
+AC_DEFUN([LIBVIRT_RESULT_LIBARCHIVE],[
+ LIBVIRT_RESULT_LIB([LIBARCHIVE])
+])
diff --git a/src/fdstream.c b/src/fdstream.c
index b8ea86e..82f0e8c 100644
--- a/src/fdstream.c
+++ b/src/fdstream.c
@@ -33,6 +33,10 @@
#include <netinet/in.h>
#include <termios.h>
+#ifdef WITH_LIBARCHIVE
+# include <archive.h>
+#endif
+
#include "fdstream.h"
#include "virerror.h"
#include "datatypes.h"
@@ -75,6 +79,9 @@ struct virFDStreamData {
void *icbOpaque;
virMutex lock;
+#ifdef WITH_LIBARCHIVE
+ void *archive;
+#endif
};
@@ -319,6 +326,12 @@ virFDStreamCloseInt(virStreamPtr st, bool streamAbort)
if (VIR_CLOSE(fdst->errfd) < 0)
VIR_DEBUG("ignoring failed close on fd %d", fdst->errfd);
+#ifdef WITH_LIBARCHIVE
+ if (fdst->archive != NULL) {
+ archive_write_free(fdst->archive);
+ archive_read_free(fdst->archive);
+ }
+#endif
st->privateData = NULL;
/* call the internal stream closing callback */
@@ -385,7 +398,16 @@ static int virFDStreamWrite(virStreamPtr st, const char *bytes,
size_t nbytes)
}
retry:
+#ifdef WITH_LIBARCHIVE
+ if (fdst->archive != NULL) {
+ archive_write_open_fd(fdst->archive, fdst->fd);
+ ret = archive_write_data(fdst->archive, bytes, nbytes);
+ } else {
+ ret = write(fdst->fd, bytes, nbytes);
+ }
+#else
ret = write(fdst->fd, bytes, nbytes);
+#endif
if (ret < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
ret = -2;
@@ -397,7 +419,15 @@ static int virFDStreamWrite(virStreamPtr st, const char *bytes,
size_t nbytes)
_("cannot write to stream"));
}
} else if (fdst->length) {
+#ifdef WITH_LIBARCHIVE
+ if (fdst->archive != NULL) {
+ fdst->offset += nbytes;
+ } else {
+ fdst->offset += ret;
+ }
+#else
fdst->offset += ret;
+#endif
}
virMutexUnlock(&fdst->lock);
@@ -435,7 +465,16 @@ static int virFDStreamRead(virStreamPtr st, char *bytes, size_t
nbytes)
}
retry:
+#ifdef WITH_LIBARCHIVE
+ if (fdst->archive != NULL) {
+ archive_read_open_fd(fdst->archive, fdst->fd, 4096);
+ ret = archive_read_data(fdst->archive, bytes, nbytes);
+ } else {
+ ret = read(fdst->fd, bytes, nbytes);
+ }
+#else
ret = read(fdst->fd, bytes, nbytes);
+#endif
if (ret < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
ret = -2;
@@ -447,7 +486,15 @@ static int virFDStreamRead(virStreamPtr st, char *bytes, size_t
nbytes)
_("cannot read from stream"));
}
} else if (fdst->length) {
+#ifdef WITH_LIBARCHIVE
+ if (fdst->archive != NULL) {
+ fdst->offset += nbytes;
+ } else {
+ fdst->offset += ret;
+ }
+#else
fdst->offset += ret;
+#endif
}
virMutexUnlock(&fdst->lock);
diff --git a/src/libvirt-stream.c b/src/libvirt-stream.c
index c16f586..40702dc 100644
--- a/src/libvirt-stream.c
+++ b/src/libvirt-stream.c
@@ -23,12 +23,16 @@
#include "datatypes.h"
#include "viralloc.h"
#include "virlog.h"
+#include "fdstream.h"
+
+#include <archive.h>
+
+struct virFDStreamData;
VIR_LOG_INIT("libvirt.stream");
#define VIR_FROM_THIS VIR_FROM_STREAMS
-
/**
* virStreamNew:
* @conn: pointer to the connection
@@ -69,6 +73,56 @@ virStreamNew(virConnectPtr conn,
return st;
}
+virStreamPtr
+virStreamNewLz4(virConnectPtr conn,
+ unsigned int flags)
+{
+ virStreamPtr st;
+
+ st = virStreamNew(conn, flags);
+ if (st != NULL) {
+ struct virFDStreamData *fdst = st->privateData;
+ fdst->archive = archive_write_new();
+ archive_write_add_filter(fdst->archive, ARCHIVE_FILTER_LZ4);
+ }
+
+ return st;
+}
+
+virStreamPtr
+virStreamNewGzip(virConnectPtr conn,
+ unsigned int flags)
+{
+ virStreamPtr st;
+
+ st = virStreamNew(conn, flags);
+ if (st != NULL) {
+ struct virFDStreamData *fdst = st->privateData;
+ fdst->archive = archive_write_new();
+ archive_write_add_filter(fdst->archive, ARCHIVE_FILTER_GZIP);
+ }
+
+ return st;
+}
+
+
+virStreamPtr
+virStreamNewXz(virConnectPtr conn,
+ unsigned int flags)
+{
+ virStreamPtr st;
+
+ st = virStreamNew(conn, flags);
+ if (st != NULL) {
+ struct virFDStreamData *fdst = st->privateData;
+ fdst->archive = archive_write_new();
+ archive_write_add_filter(fdst->archive, ARCHIVE_FILTER_XZ);
+ }
+
+ return st;
+}
+
+
/**
* virStreamRef:
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index dd94191..46519ce 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -725,4 +725,11 @@ LIBVIRT_1.2.19 {
virDomainRename;
} LIBVIRT_1.2.17;
+LIBVIRT_1.2.20 {
+ global:
+ virStreamNewLz4;
+ virStreamNewGzip;
+ virStreamNewXz;
+} LIBVIRT_1.2.19;
+
# .... define new API here using predicted next version number ....
--
2.5.0