From aef0f036f08f8949e4e2a5b84c9199ef8ec40595 Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Fri, 7 Nov 2008 17:11:08 +0200 Subject: use zlib internally to decompress --- src/gunzip.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/gunzip.c (limited to 'src/gunzip.c') diff --git a/src/gunzip.c b/src/gunzip.c new file mode 100644 index 0000000..f488fa4 --- /dev/null +++ b/src/gunzip.c @@ -0,0 +1,93 @@ +/* gunzip.c - Alpine Package Keeper (APK) + * + * Copyright (C) 2008 Timo Teräs + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. See http://www.gnu.org/ for details. + */ + +#include +#include +#include +#include +#include + +#include "apk_defines.h" +#include "apk_io.h" + +struct apk_gzip_istream { + struct apk_istream is; + struct apk_bstream *bs; + z_stream zs; + int z_err; +}; + +static size_t gz_read(void *stream, void *ptr, size_t size) +{ + struct apk_gzip_istream *gis = + container_of(stream, struct apk_gzip_istream, is); + + if (gis->z_err == Z_DATA_ERROR || gis->z_err == Z_ERRNO) + return -1; + if (gis->z_err == Z_STREAM_END) + return 0; + + if (ptr == NULL) + return apk_istream_skip(&gis->is, size); + + gis->zs.avail_out = size; + gis->zs.next_out = ptr; + + while (gis->zs.avail_out != 0 && gis->z_err == Z_OK) { + if (gis->zs.avail_in == 0) { + gis->zs.avail_in = gis->bs->read(gis->bs, (void **) &gis->zs.next_in); + if (gis->zs.avail_in < 0) { + gis->z_err = Z_DATA_ERROR; + return size - gis->zs.avail_out; + } + } + + gis->z_err = inflate(&gis->zs, Z_NO_FLUSH); + } + + if (gis->z_err != Z_OK && gis->z_err != Z_STREAM_END) + return -1; + + return size - gis->zs.avail_out; +} + +static void gz_close(void *stream) +{ + struct apk_gzip_istream *gis = + container_of(stream, struct apk_gzip_istream, is); + + inflateEnd(&gis->zs); + free(gis); +} + +struct apk_istream *apk_gunzip_bstream(struct apk_bstream *bs) +{ + struct apk_gzip_istream *gis; + + gis = malloc(sizeof(struct apk_gzip_istream)); + if (gis == NULL) + return NULL; + + *gis = (struct apk_gzip_istream) { + .is.read = gz_read, + .is.splice = apk_istream_splice, + .is.close = gz_close, + .bs = bs, + .z_err = 0, + }; + + if (inflateInit2(&gis->zs, 15+32) != Z_OK) { + free(gis); + return NULL; + } + + return &gis->is; +} + -- cgit v1.2.3-60-g2f50