Index: ChangeLog
===================================================================
--- ChangeLog	(revision 4953)
+++ ChangeLog	(revision 4956)
@@ -9,4 +9,5 @@
 	* Added support for non-stream execs (Closes: #32)
 	* Done some libroardsp header cleanup (Closes: #36)
+	* Use zlib for gzip and zlib format (Closes: #29)
 
 v. 0.4beta5 - Tue Apr 26 2011 08:42 CEST
Index: Makefile.inc
===================================================================
--- Makefile.inc	(revision 4899)
+++ Makefile.inc	(revision 4956)
@@ -10,5 +10,5 @@
 LIBROAR_V       = $(COMMON_SOVERSION)
 NETLIBS         = $(lib_dnet) $(lib_wsock32) $(lib_ws2_32)
-AUXLIBS         = $(lib_slp) $(lib_ssl) $(lib_gcrypt) $(lib_sendfile) $(lib_dl) $(lib_x11)
+AUXLIBS         = $(lib_slp) $(lib_ssl) $(lib_gcrypt) $(lib_sendfile) $(lib_dl) $(lib_x11) $(lib_z)
 LIBROAR_NS      = $(AUXLIBS) $(NETLIBS)
 
Index: include/libroar/libroar.h
===================================================================
--- include/libroar/libroar.h	(revision 4943)
+++ include/libroar/libroar.h	(revision 4956)
@@ -137,4 +137,5 @@
 #include "vio_buffer_store.h"
 #include "vio_cmd.h"
+#include "vio_zlib.h"
 #include "vio_ops.h"
 #include "vio_string.h"
Index: include/libroar/vio_dstr.h
===================================================================
--- include/libroar/vio_dstr.h	(revision 4746)
+++ include/libroar/vio_dstr.h	(revision 4956)
@@ -107,4 +107,5 @@
 
 #define ROAR_VIO_DSTR_OBJT_GZIP           (0x10|ROAR_VIO_DSTR_OBJGT_COMP)
+#define ROAR_VIO_DSTR_OBJT_ZLIB           (0x11|ROAR_VIO_DSTR_OBJGT_COMP)
 #define ROAR_VIO_DSTR_OBJT_BZIP2          (0x22|ROAR_VIO_DSTR_OBJGT_COMP)
 
Index: include/libroar/vio_zlib.h
===================================================================
--- include/libroar/vio_zlib.h	(revision 4956)
+++ include/libroar/vio_zlib.h	(revision 4956)
@@ -0,0 +1,45 @@
+//vio_gzip.h:
+
+/*
+ *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011
+ *
+ *  This file is part of libroar a part of RoarAudio,
+ *  a cross-platform sound system for both, home and professional use.
+ *  See README for details.
+ *
+ *  This file is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3
+ *  as published by the Free Software Foundation.
+ *
+ *  libroar is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this software; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ *  NOTE for everyone want's to change something and send patches:
+ *  read README and HACKING! There a addition information on
+ *  the license of this document you need to read before you send
+ *  any patches.
+ *
+ *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
+ *  or libpulse*:
+ *  The libs libroaresd, libroararts and libroarpulse link this lib
+ *  and are therefore GPL. Because of this it may be illigal to use
+ *  them with any software that uses libesd, libartsc or libpulse*.
+ */
+
+#ifndef _LIBROARVIO_GZIP_H_
+#define _LIBROARVIO_GZIP_H_
+
+#include "libroar.h"
+
+int roar_vio_open_zlib(struct roar_vio_calls * calls, struct roar_vio_calls * dst, int level, int gzip);
+
+#endif
+
+//ll
Index: libroar/Makefile
===================================================================
--- libroar/Makefile	(revision 4824)
+++ libroar/Makefile	(revision 4956)
@@ -7,5 +7,5 @@
 VIO_META=vio.o vio_select.o vio_ops.o vio_string.o
 VIO_BRIDGE=vio_bio.o vio_stdio.o
-VIO=$(VIO_META) $(VIO_BRIDGE) vio_cmd.o vio_magic.o vio_pipe.o vio_socket.o vio_winsock.o vio_stack.o vio_jumbo.o vio_proto.o vio_dstr.o vio_tantalos.o vio_rtp.o vio_buffer.o vio_buffer_store.o vio_stdvios.o vio_misc.o
+VIO=$(VIO_META) $(VIO_BRIDGE) vio_cmd.o vio_magic.o vio_pipe.o vio_socket.o vio_winsock.o vio_stack.o vio_jumbo.o vio_proto.o vio_dstr.o vio_tantalos.o vio_rtp.o vio_buffer.o vio_buffer_store.o vio_stdvios.o vio_misc.o vio_zlib.o
 HASHES=hash.o hash_tiger.o
 PASSWORD=passwordapi.o pinentry.o sshaskpass.o
Index: libroar/vio_cmd.c
===================================================================
--- libroar/vio_cmd.c	(revision 4708)
+++ libroar/vio_cmd.c	(revision 4956)
@@ -596,17 +596,7 @@
 // MISC:
 int roar_vio_open_gzip(struct roar_vio_calls * calls, struct roar_vio_calls * dst, int level) {
-#if defined(ROAR_HAVE_BIN_GZIP) || !defined(ROAR_WITHOUT_VIO_CMD)
- char   wbuf[80];
- char * writer = ROAR_HAVE_BIN_GZIP " -c";
-
- if ( level != -1 ) {
-  snprintf(wbuf, 80, "%s -c%i", ROAR_HAVE_BIN_GZIP, level);
-  writer = wbuf;
- }
-
- return roar_vio_open_cmd(calls, dst, ROAR_HAVE_BIN_GZIP " -dc", writer, ROAR_VIO_CMD_OPTS_ON_DEMAND);
-#else
- return -1;
-#endif
+ roar_debug_warn_obsolete("roar_vio_open_gzip", "roar_vio_open_zlib", NULL);
+
+ return roar_vio_open_zlib(calls, dst, level, 1);
 }
 
Index: libroar/vio_dstr.c
===================================================================
--- libroar/vio_dstr.c	(revision 4876)
+++ libroar/vio_dstr.c	(revision 4956)
@@ -154,4 +154,7 @@
       NULL, NULL,
       {ROAR_VIO_DEF_TYPE_EOL}},
+ {ROAR_VIO_DSTR_OBJT_ZLIB,       "zlib",
+      NULL, NULL,
+      {ROAR_VIO_DEF_TYPE_EOL}},
  {ROAR_VIO_DSTR_OBJT_BZIP2,      "bzip2",
       NULL, NULL,
@@ -537,4 +540,5 @@
    case ROAR_VIO_DSTR_OBJT_RTP2: // we currently only forward the defs
    case ROAR_VIO_DSTR_OBJT_GZIP:
+   case ROAR_VIO_DSTR_OBJT_ZLIB:
    case ROAR_VIO_DSTR_OBJT_BZIP2:
    case ROAR_VIO_DSTR_OBJT_PGP:
@@ -831,5 +835,12 @@
      break;
     case ROAR_VIO_DSTR_OBJT_GZIP:
-      if ( roar_vio_open_gzip(tc, prev, -1) == -1 ) {
+      //if ( roar_vio_open_gzip(tc, prev, -1) == -1 ) {
+      if ( roar_vio_open_zlib(tc, prev, -1, 1) == -1 ) {
+       _ret(-1);
+      }
+     break;
+    case ROAR_VIO_DSTR_OBJT_ZLIB:
+      //if ( roar_vio_open_gzip(tc, prev, -1) == -1 ) {
+      if ( roar_vio_open_zlib(tc, prev, -1, 0) == -1 ) {
        _ret(-1);
       }
Index: libroar/vio_zlib.c
===================================================================
--- libroar/vio_zlib.c	(revision 4956)
+++ libroar/vio_zlib.c	(revision 4956)
@@ -0,0 +1,556 @@
+//vio_gzip.c:
+
+/*
+ *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011
+ *
+ *  This file is part of libroar a part of RoarAudio,
+ *  a cross-platform sound system for both, home and professional use.
+ *  See README for details.
+ *
+ *  This file is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3
+ *  as published by the Free Software Foundation.
+ *
+ *  libroar is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this software; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ *  NOTE for everyone want's to change something and send patches:
+ *  read README and HACKING! There a addition information on
+ *  the license of this document you need to read before you send
+ *  any patches.
+ *
+ *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
+ *  or libpulse*:
+ *  The libs libroaresd, libroararts and libroarpulse link this lib
+ *  and are therefore GPL. Because of this it may be illigal to use
+ *  them with any software that uses libesd, libartsc or libpulse*.
+ */
+
+#include "libroar.h"
+
+#ifdef ROAR_HAVE_LIBZ
+
+#include <zlib.h>
+
+struct roar_vio_gzip {
+ struct roar_vio_calls * next;
+ struct roar_buffer * outbuf, * inbuf;
+ int compressor_error, decompressor_error;
+ int compressor_flush;
+ int compressor_used;
+ z_stream compressor, decompressor;
+ gz_header gz_compressorheader, gz_decompressorheader;
+};
+
+static void * _zalloc(voidpf opaque, uInt items, uInt size) {
+ return roar_mm_calloc(items, size);
+}
+
+static void _zfree(voidpf opaque, voidpf address) {
+ roar_mm_free(address);
+}
+
+static void _set_error (int error) {
+ int raerror = ROAR_ERROR_UNKNOWN;
+
+ switch (error) {
+  case Z_OK:            raerror = ROAR_ERROR_NONE;       break;
+  case Z_STREAM_END:    raerror = ROAR_ERROR_NODATA;     break;
+  case Z_NEED_DICT:     raerror = ROAR_ERROR_INVAL;      break;
+  case Z_ERRNO:         roar_err_from_errno();           break;
+  case Z_STREAM_ERROR:  raerror = ROAR_ERROR_INVAL;      break;
+  case Z_DATA_ERROR:    raerror = ROAR_ERROR_BADCKSUM;   break;
+  case Z_MEM_ERROR:     raerror = ROAR_ERROR_NOMEM;      break;
+  case Z_BUF_ERROR:     raerror = ROAR_ERROR_FAULT;      break;
+  case Z_VERSION_ERROR: raerror = ROAR_ERROR_BADVERSION; break;
+ }
+
+ ROAR_DBG("_set_error(error=%i): raerror=%s", error, roar_error2str(raerror));
+ roar_err_set(raerror);
+}
+
+static int _init(struct roar_vio_gzip * self, struct roar_vio_calls * dst, int level, int gzip) {
+ int ret;
+
+ ROAR_DBG("_init(self=%p, dst=%p, level=%i, gzip=%i) = ?", self, dst, level, gzip);
+
+ if ( self == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ ROAR_DBG("_init(self=%p, dst=%p, level=%i, gzip=%i) = ?", self, dst, level, gzip);
+
+ if ( level == -1 ) {
+  level = Z_DEFAULT_COMPRESSION;
+ }
+
+ memset(self, 0, sizeof(struct roar_vio_gzip));
+
+ self->next   = dst;
+
+ self->outbuf = NULL;
+ self->inbuf  = NULL;
+
+ self->compressor_error    = ROAR_ERROR_NONE;
+ self->decompressor_error  = ROAR_ERROR_NONE;
+
+ self->compressor_flush    = Z_SYNC_FLUSH;
+ self->compressor_used     = 0;
+
+ self->compressor.zalloc   = _zalloc;
+ self->compressor.zfree    = _zfree;
+ self->compressor.opaque   = NULL;
+ self->compressor.next_in  = NULL;
+ self->compressor.next_out = NULL;
+
+ self->decompressor.zalloc   = _zalloc;
+ self->decompressor.zfree    = _zfree;
+ self->decompressor.opaque   = NULL;
+ self->decompressor.next_in  = NULL;
+ self->decompressor.next_out = NULL;
+
+ ROAR_DBG("_init(self=%p, dst=%p, level=%i, gzip=%i) = ?", self, dst, level, gzip);
+
+ // for the magic numbers: see the zlib.h header file. There are no const for them.
+ if ( (ret = deflateInit2(&(self->compressor), level, Z_DEFLATED, 15 + (gzip ? 16 : 0), 8, Z_DEFAULT_STRATEGY)) != Z_OK ) {
+  _set_error(ret);
+  return -1;
+ }
+
+ ROAR_DBG("_init(self=%p, dst=%p, level=%i, gzip=%i) = ?", self, dst, level, gzip);
+
+ if ( (ret = inflateInit2(&(self->decompressor), 15+32)) != Z_OK ) {
+  deflateEnd(&(self->compressor));
+  _set_error(ret);
+  return -1;
+ }
+
+ ROAR_DBG("_init(self=%p, dst=%p, level=%i, gzip=%i) = ?", self, dst, level, gzip);
+
+ // gzheader is descriped in RFC1952.
+ memset(&(self->gz_compressorheader), 0, sizeof(self->gz_compressorheader));
+ self->gz_compressorheader.os   = 255; // os='unknown'
+ self->gz_compressorheader.hcrc = 0;   // for compatibility
+
+ memset(&(self->gz_decompressorheader), 0, sizeof(self->gz_decompressorheader));
+ self->gz_decompressorheader.os   = 255; // os='unknown'
+ self->gz_decompressorheader.hcrc = 0;   // for compatibility
+
+ if ( gzip ) {
+  if ( (ret = deflateSetHeader(&(self->compressor), &(self->gz_compressorheader))) != Z_OK ) {
+   deflateEnd(&(self->compressor));
+   inflateEnd(&(self->decompressor));
+   _set_error(ret);
+   return -1;
+  }
+ }
+
+ ROAR_DBG("_init(self=%p, dst=%p, level=%i, gzip=%i) = 0", self, dst, level, gzip);
+
+ return 0;
+}
+
+static ssize_t roar_vio_zlib_read    (struct roar_vio_calls * vio, void *buf, size_t count) {
+ struct roar_vio_gzip * self = vio->inst;
+ struct roar_buffer * leftbuf;
+ void * leftbufdata;
+ size_t buflen;
+ ssize_t len;
+ size_t have = 0;
+ int ret;
+ unsigned char inbuf[1024];
+
+ ROAR_DBG("roar_vio_zlib_read(vio=%p, buf=%p, count=%llu) = ?", vio, buf, (long long unsigned)count);
+
+ if ( self->decompressor_error != ROAR_ERROR_NONE ) {
+  roar_err_set(self->decompressor_error);
+  return -1;
+ }
+
+ ROAR_DBG("roar_vio_zlib_read(vio=%p, buf=%p, count=%llu) = ?", vio, buf, (long long unsigned)count);
+
+ while ( self->inbuf != NULL ) {
+  ROAR_DBG("roar_vio_zlib_read(vio=%p, buf=%p, count=%llu): self->inbuf=%p", vio, buf, (long long unsigned)count, self->inbuf);
+  if ( roar_buffer_get_data(self->inbuf, &leftbufdata) == -1 )
+   return -1;
+  if ( roar_buffer_get_len(self->inbuf, &buflen) == -1 )
+   return -1;
+
+  ROAR_DBG("roar_vio_zlib_read(vio=%p, buf=%p, count=%llu) = ?", vio, buf, (long long unsigned)count, self->inbuf);
+
+  self->decompressor.next_out  = buf;
+  self->decompressor.avail_out = count;
+
+  self->decompressor.next_in  = leftbufdata;
+  self->decompressor.avail_in = buflen;
+
+  ROAR_DBG("roar_vio_zlib_read(vio=%p, buf=%p, count=%llu): in: %llu Bytes, out: count Bytes.", vio, buf, (long long unsigned)count, (long long unsigned int)buflen);
+
+  ret = inflate(&(self->decompressor), Z_NO_FLUSH);
+
+  ROAR_DBG("roar_vio_zlib_read(vio=%p, buf=%p, count=%llu): inflate() returned %i", vio, buf, (long long unsigned)count, ret);
+
+  len    = count - self->decompressor.avail_out;
+
+  if ( ret == Z_STREAM_END ) {
+   count = len;
+   ret = Z_OK;
+  }
+
+  if ( ret != Z_OK ) {
+   if ( len == 0 ) {
+    _set_error(ret);
+    return -1;
+   } else {
+    have += len;
+    return have;
+   }
+  }
+
+  buf   += len;
+  have  += len;
+  count -= len;
+
+  if ( len == buflen ) {
+   ret = roar_buffer_next(&(self->inbuf));
+  } else {
+   ret = roar_buffer_set_offset(self->inbuf, len);
+  }
+
+  if ( ret == -1 ) {
+   roar_err_set((self->decompressor_error = ROAR_ERROR_LOSTSYNC));
+   return -1;
+  }
+
+  if ( count == 0 )
+   return have;
+ }
+
+ ROAR_DBG("roar_vio_zlib_read(vio=%p, buf=%p, count=%llu) = ?", vio, buf, (long long unsigned)count);
+
+ self->decompressor.next_out  = buf;
+ self->decompressor.avail_out = count;
+
+ self->decompressor.next_in  = NULL;
+ self->decompressor.avail_in = 0;
+
+ while (self->decompressor.avail_out > 0) {
+  ROAR_DBG("roar_vio_zlib_read(vio=%p, buf=%p, count=%llu): generating new output...", vio, buf, (long long unsigned)count);
+
+  if ( self->decompressor.avail_in == 0 ) {
+   ROAR_DBG("roar_vio_zlib_read(vio=%p, buf=%p, count=%llu): reading more data", vio, buf, (long long unsigned)count);
+
+   len = roar_vio_read(self->next, inbuf, sizeof(inbuf));
+   if ( len == -1 ) {
+    have += count - self->decompressor.avail_out;
+    if ( have == 0 ) {
+     // error is still set (by roar_vio_read()).
+     return -1;
+    } else {
+     return 0;
+    }
+   } else if ( len == 0 ) {
+    break;
+   }
+
+   ROAR_DBG("roar_vio_zlib_read(vio=%p, buf=%p, count=%llu): len=%llu", vio, buf, (long long unsigned)count, (long long unsigned)len);
+
+   self->decompressor.next_in  = inbuf;
+   self->decompressor.avail_in = len;
+  }
+
+  ret = inflate(&(self->decompressor), Z_NO_FLUSH);
+  ROAR_DBG("roar_vio_zlib_read(vio=%p, buf=%p, count=%llu): inflate() returned %i", vio, buf, (long long unsigned)count, ret);
+
+  if ( ret == Z_STREAM_END )
+   ret = Z_OK;
+
+  if ( ret != Z_OK ) {
+   if ( (count - self->decompressor.avail_out) == 0 ) {
+    _set_error(ret);
+    return -1;
+   } else {
+    break;
+   }
+  }
+
+  ROAR_DBG("roar_vio_zlib_read(vio=%p, buf=%p, count=%llu) = ?", vio, buf, (long long unsigned)count);
+ }
+
+ if ( self->decompressor.avail_in != 0 ) {
+  if ( roar_buffer_new_data(&leftbuf, self->decompressor.avail_in, &leftbufdata) == -1 ) {
+   roar_err_set((self->decompressor_error = ROAR_ERROR_LOSTSYNC));
+   return -1;
+  }
+
+  memcpy(leftbufdata, self->decompressor.next_in, self->decompressor.avail_in);
+
+  if ( self->inbuf == NULL ) {
+   self->inbuf = leftbuf;
+  } else {
+   if ( roar_buffer_add(self->inbuf, leftbuf) == -1 ) {
+    roar_buffer_free(leftbuf);
+    roar_err_set((self->decompressor_error = ROAR_ERROR_LOSTSYNC));
+    return -1;
+   }
+  }
+ }
+
+ have += count - self->decompressor.avail_out;
+
+ ROAR_DBG("roar_vio_zlib_read(vio=%p, buf=%p, count=%llu) = %llu", vio, buf, (long long unsigned)count, (long long unsigned)have);
+
+ return have;
+}
+
+static ssize_t roar_vio_zlib_write   (struct roar_vio_calls * vio, void *buf, size_t count) {
+ struct roar_vio_gzip * self = vio->inst;
+ struct roar_buffer * leftbuf;
+ void * leftbufdata;
+ size_t outlen;
+ size_t buflen;
+ char outbuf[1024];
+ ssize_t len;
+ int ret;
+
+ ROAR_DBG("roar_vio_zlib_write(vio=%p, buf=%p, count=%llu) = ?", vio, buf, (long long unsigned)count);
+
+ self->compressor_used = 1;
+
+ if ( self->compressor_error != ROAR_ERROR_NONE ) {
+  roar_err_set(self->compressor_error);
+  return -1;
+ }
+
+ ROAR_DBG("roar_vio_zlib_write(vio=%p, buf=%p, count=%llu) = ?", vio, buf, (long long unsigned)count);
+
+ while (self->outbuf != NULL) {
+  if ( roar_buffer_get_data(self->outbuf, &leftbufdata) == -1 )
+   return -1;
+  if ( roar_buffer_get_len(self->outbuf, &buflen) == -1 )
+   return -1;
+
+  len = roar_vio_write(self->next, leftbufdata, buflen);
+  if ( len == -1 ) {
+   return -1;
+  } else if ( len == buflen ) {
+   if ( roar_buffer_next(&(self->outbuf)) == -1 ) {
+    roar_err_set((self->compressor_error = ROAR_ERROR_LOSTSYNC));
+    return -1;
+   }
+
+   
+  } else {
+   if ( roar_buffer_set_offset(self->outbuf, len) == -1 ) {
+    roar_err_set((self->compressor_error = ROAR_ERROR_LOSTSYNC));
+    return -1;
+   }
+
+   return 0;
+  }
+ }
+
+ ROAR_DBG("roar_vio_zlib_write(vio=%p, buf=%p, count=%llu) = ?", vio, buf, (long long unsigned)count);
+
+ self->compressor.next_in  = buf;
+ self->compressor.avail_in = count;
+
+ while (self->compressor.avail_in || count == 0) {
+  self->compressor.next_out  = (unsigned char *)outbuf;
+  self->compressor.avail_out = sizeof(outbuf);
+  outlen = self->compressor.total_out;
+
+  ret = deflate(&(self->compressor), count == 0 ? self->compressor_flush : Z_NO_FLUSH);
+
+  outlen = self->compressor.total_out - outlen;
+
+  ROAR_DBG("roar_vio_zlib_write(vio=%p, buf=%p, count=%llu): deflate() returned %i", vio, buf, (long long unsigned)count, ret);
+ ROAR_DBG("roar_vio_zlib_write(vio=%p, buf=%p, count=%llu): outlen=%llu", vio, buf, (long long unsigned)count, (long long unsigned int)outlen);
+
+  if ( count != 0 && ret != Z_OK ) {
+   len = count - self->compressor.avail_in;
+   if ( len != 0 ) {
+    return len;
+   } else {
+    _set_error(ret);
+    return -1;
+   }
+  }
+
+  if ( outlen != 0 ) {
+   len = roar_vio_write(self->next, outbuf, outlen);
+
+   if ( len < outlen ) {
+    if ( roar_buffer_new_data(&leftbuf, outlen - len, &leftbufdata) == -1 ) {
+     roar_err_set((self->compressor_error = ROAR_ERROR_LOSTSYNC));
+     return -1;
+    }
+
+    memcpy(leftbufdata, outbuf+len, outlen - len);
+
+    if ( self->outbuf == NULL ) {
+     self->outbuf = leftbuf;
+    } else {
+     if ( roar_buffer_add(self->outbuf, leftbuf) == -1 ) {
+      roar_buffer_free(leftbuf);
+      roar_err_set((self->compressor_error = ROAR_ERROR_LOSTSYNC));
+      return -1;
+     }
+    } 
+    break;
+   }
+  }
+
+  ROAR_DBG("roar_vio_zlib_write(vio=%p, buf=%p, count=%llu) = ?", vio, buf, (long long unsigned)count);
+
+  if ( count == 0 && (
+         (self->compressor_flush == Z_FINISH && ret == Z_STREAM_END) ||
+         (self->compressor_flush != Z_FINISH && ret == Z_BUF_ERROR)   ) )
+   return 0;
+
+  ROAR_DBG("roar_vio_zlib_write(vio=%p, buf=%p, count=%llu) = ?", vio, buf, (long long unsigned)count);
+ }
+
+ len = count - self->compressor.avail_in;
+
+ ROAR_DBG("roar_vio_zlib_write(vio=%p, buf=%p, count=%llu) = %llu", vio, buf, (long long unsigned)count, (long long unsigned int)len);
+
+ return len;
+}
+
+static off_t   roar_vio_zlib_lseek   (struct roar_vio_calls * vio, off_t offset, int whence) {
+ roar_err_set(ROAR_ERROR_NOSYS);
+ return (off_t)-1;
+}
+
+static int     roar_vio_zlib_nonblock(struct roar_vio_calls * vio, int state) {
+ struct roar_vio_gzip * self = vio->inst;
+ return roar_vio_nonblock(self->next, state);
+}
+
+static int     roar_vio_zlib_sync    (struct roar_vio_calls * vio) {
+ struct roar_vio_gzip * self = vio->inst;
+
+ if ( self->compressor_used )
+  if ( self->compressor_error == ROAR_ERROR_NONE )
+   if ( roar_vio_zlib_write(vio, NULL, 0) == -1 )
+    return -1;
+
+ roar_err_set(ROAR_ERROR_NOSYS);
+ return -1;
+}
+
+static int     roar_vio_zlib_ctl     (struct roar_vio_calls * vio, int cmd, void * data) {
+ struct roar_vio_gzip * self;
+
+ if ( vio == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ self = vio->inst;
+
+ switch (cmd) {
+  case ROAR_VIO_CTL_GET_NAME:
+    if ( data == NULL )
+     return -1;
+
+    *(char**)data = "zlib";
+    return 0;
+   break;
+  case ROAR_VIO_CTL_GET_NEXT:
+    *(struct roar_vio_calls **)data = self->next;
+    return 0;
+   break;
+  case ROAR_VIO_CTL_GET_FH:
+  case ROAR_VIO_CTL_GET_READ_FH:
+  case ROAR_VIO_CTL_GET_WRITE_FH:
+  case ROAR_VIO_CTL_GET_SELECT_FH:
+  case ROAR_VIO_CTL_GET_SELECT_READ_FH:
+  case ROAR_VIO_CTL_GET_SELECT_WRITE_FH:
+    roar_err_set(ROAR_ERROR_NOTSUP);
+    return -1;
+   break;
+  default:
+    roar_err_set(ROAR_ERROR_BADRQC);
+    return -1;
+ }
+}
+
+static int     roar_vio_zlib_close   (struct roar_vio_calls * vio) {
+ struct roar_vio_gzip * self;
+
+ if ( vio == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ self = vio->inst;
+
+ self->compressor_flush = Z_FINISH;
+
+ roar_vio_zlib_sync(vio);
+
+ deflateEnd(&(self->compressor));
+ inflateEnd(&(self->decompressor));
+
+ if ( self->outbuf != NULL )
+  roar_buffer_free(self->outbuf);
+ if ( self->inbuf != NULL )
+  roar_buffer_free(self->inbuf);
+
+ roar_mm_free(self);
+
+ return 0;
+}
+
+int roar_vio_open_zlib(struct roar_vio_calls * calls, struct roar_vio_calls * dst, int level, int gzip) {
+ struct roar_vio_gzip * self;
+ int err;
+
+ ROAR_DBG("roar_vio_open_zlib(calls=%p, dst=%p, level=%i, gzip=%i) = ?", calls, dst, level, gzip);
+
+ if ( calls == NULL || dst == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ self = roar_mm_malloc(sizeof(struct roar_vio_gzip));
+
+ if ( _init(self, dst, level, gzip) == -1 ) {
+  err = roar_error;
+  roar_mm_free(self);
+  roar_err_set(err);
+  ROAR_DBG("roar_vio_open_zlib(calls=%p, dst=%p, level=%i, gzip=%i) = -1 // error=%s", calls, dst, level, gzip, roar_error2str(err));
+  return -1;
+ }
+
+ ROAR_DBG("roar_vio_open_zlib(calls=%p, dst=%p, level=%i, gzip=%i) = ?", calls, dst, level, gzip);
+
+ memset(calls, 0, sizeof(struct roar_vio_calls));
+
+ calls->inst       = self;
+ calls->read       = roar_vio_zlib_read;
+ calls->write      = roar_vio_zlib_write;
+ calls->lseek      = roar_vio_zlib_lseek;
+ calls->nonblock   = roar_vio_zlib_nonblock;
+ calls->sync       = roar_vio_zlib_sync;
+ calls->ctl        = roar_vio_zlib_ctl;
+ calls->close      = roar_vio_zlib_close;
+
+ ROAR_DBG("roar_vio_open_zlib(calls=%p, dst=%p, level=%i, gzip=%i) = 0", calls, dst, level, gzip);
+
+ return 0;
+}
+
+#endif
+
+//ll
