use libarchive for compressed stream support Signed-off-by: Vasiliy Tolstov <v.tolstov@xxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list