diff options
Diffstat (limited to 'src/gunzip.c')
-rw-r--r-- | src/gunzip.c | 252 |
1 files changed, 0 insertions, 252 deletions
diff --git a/src/gunzip.c b/src/gunzip.c deleted file mode 100644 index 96138b0..0000000 --- a/src/gunzip.c +++ /dev/null @@ -1,252 +0,0 @@ -/* gunzip.c - Alpine Package Keeper (APK) - * - * Copyright (C) 2008-2011 Timo Teräs <timo.teras@iki.fi> - * 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 <errno.h> -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <malloc.h> -#include <zlib.h> - -#include "apk_defines.h" -#include "apk_io.h" - -struct apk_gzip_istream { - struct apk_istream is; - struct apk_istream *zis; - z_stream zs; - - apk_multipart_cb cb; - void *cbctx; - void *cbprev; - apk_blob_t cbarg; -}; - -static void gzi_get_meta(struct apk_istream *is, struct apk_file_meta *meta) -{ - struct apk_gzip_istream *gis = container_of(is, struct apk_gzip_istream, is); - apk_istream_get_meta(gis->zis, meta); -} - -static int gzi_boundary_change(struct apk_gzip_istream *gis) -{ - int r; - - r = gis->cb(gis->cbctx, gis->is.err ? APK_MPART_END : APK_MPART_BOUNDARY, gis->cbarg); - if (r > 0) r = -ECANCELED; - if (r != 0) gis->is.err = r; - return r; -} - -static ssize_t gzi_read(struct apk_istream *is, void *ptr, size_t size) -{ - struct apk_gzip_istream *gis = container_of(is, struct apk_gzip_istream, is); - int r; - - gis->zs.avail_out = size; - gis->zs.next_out = ptr; - - while (gis->zs.avail_out != 0 && gis->is.err == 0) { - if (!APK_BLOB_IS_NULL(gis->cbarg)) { - if (gzi_boundary_change(gis)) - goto ret; - gis->cbarg = APK_BLOB_NULL; - } - if (gis->zs.avail_in == 0) { - apk_blob_t blob; - - if (gis->cb != NULL && gis->cbprev != NULL && - gis->cbprev != gis->zs.next_in) { - gis->cb(gis->cbctx, APK_MPART_DATA, - APK_BLOB_PTR_LEN(gis->cbprev, - (void *)gis->zs.next_in - gis->cbprev)); - } - blob = apk_istream_get_all(gis->zis); - gis->cbprev = blob.ptr; - gis->zs.avail_in = blob.len; - gis->zs.next_in = (void *) gis->cbprev; - if (blob.len < 0) { - gis->is.err = blob.len; - goto ret; - } else if (gis->zs.avail_in == 0) { - gis->is.err = 1; - gis->cbarg = APK_BLOB_NULL; - gzi_boundary_change(gis); - goto ret; - } - } - - r = inflate(&gis->zs, Z_NO_FLUSH); - switch (r) { - case Z_STREAM_END: - /* Digest the inflated bytes */ - if (gis->zis->err && gis->zs.avail_in == 0) - gis->is.err = gis->zis->err; - if (gis->cb != NULL) { - gis->cbarg = APK_BLOB_PTR_LEN(gis->cbprev, (void *) gis->zs.next_in - gis->cbprev); - gis->cbprev = gis->zs.next_in; - } - /* If we hit end of the bitstream (not end - * of just this gzip), we need to do the - * callback here, as we won't be called again. - * For boundaries it should be postponed to not - * be called until next gzip read is started. */ - if (gis->is.err) { - gzi_boundary_change(gis); - goto ret; - } - inflateEnd(&gis->zs); - if (inflateInit2(&gis->zs, 15+32) != Z_OK) - return -ENOMEM; - if (gis->cb) goto ret; - break; - case Z_OK: - break; - default: - gis->is.err = -EIO; - break; - } - } - -ret: - return size - gis->zs.avail_out; -} - -static void gzi_close(struct apk_istream *is) -{ - struct apk_gzip_istream *gis = container_of(is, struct apk_gzip_istream, is); - - inflateEnd(&gis->zs); - apk_istream_close(gis->zis); - free(gis); -} - -static const struct apk_istream_ops gunzip_istream_ops = { - .get_meta = gzi_get_meta, - .read = gzi_read, - .close = gzi_close, -}; - -struct apk_istream *apk_istream_gunzip_mpart(struct apk_istream *is, apk_multipart_cb cb, void *ctx) -{ - struct apk_gzip_istream *gis; - - if (IS_ERR_OR_NULL(is)) return ERR_CAST(is); - - gis = malloc(sizeof(*gis) + apk_io_bufsize); - if (!gis) goto err; - - *gis = (struct apk_gzip_istream) { - .is.ops = &gunzip_istream_ops, - .is.buf = (uint8_t*)(gis + 1), - .is.buf_size = apk_io_bufsize, - .zis = is, - .cb = cb, - .cbctx = ctx, - }; - - if (inflateInit2(&gis->zs, 15+32) != Z_OK) { - free(gis); - goto err; - } - - return &gis->is; -err: - apk_istream_close(is); - return ERR_PTR(-ENOMEM); -} - -struct apk_gzip_ostream { - struct apk_ostream os; - struct apk_ostream *output; - z_stream zs; -}; - -static ssize_t gzo_write(struct apk_ostream *os, const void *ptr, size_t size) -{ - struct apk_gzip_ostream *gos = container_of(os, struct apk_gzip_ostream, os); - unsigned char buffer[1024]; - ssize_t have, r; - - gos->zs.avail_in = size; - gos->zs.next_in = (void *) ptr; - while (gos->zs.avail_in) { - gos->zs.avail_out = sizeof(buffer); - gos->zs.next_out = buffer; - r = deflate(&gos->zs, Z_NO_FLUSH); - if (r == Z_STREAM_ERROR) - return -EIO; - have = sizeof(buffer) - gos->zs.avail_out; - if (have != 0) { - r = apk_ostream_write(gos->output, buffer, have); - if (r != have) - return -EIO; - } - } - - return size; -} - -static int gzo_close(struct apk_ostream *os) -{ - struct apk_gzip_ostream *gos = container_of(os, struct apk_gzip_ostream, os); - unsigned char buffer[1024]; - size_t have; - int r, rc = 0; - - do { - gos->zs.avail_out = sizeof(buffer); - gos->zs.next_out = buffer; - r = deflate(&gos->zs, Z_FINISH); - have = sizeof(buffer) - gos->zs.avail_out; - if (apk_ostream_write(gos->output, buffer, have) != have) - rc = -EIO; - } while (r == Z_OK); - r = apk_ostream_close(gos->output); - if (r != 0) - rc = r; - - deflateEnd(&gos->zs); - free(gos); - - return rc; -} - -static const struct apk_ostream_ops gzip_ostream_ops = { - .write = gzo_write, - .close = gzo_close, -}; - -struct apk_ostream *apk_ostream_gzip(struct apk_ostream *output) -{ - struct apk_gzip_ostream *gos; - - if (IS_ERR_OR_NULL(output)) return ERR_CAST(output); - - gos = malloc(sizeof(struct apk_gzip_ostream)); - if (gos == NULL) goto err; - - *gos = (struct apk_gzip_ostream) { - .os.ops = &gzip_ostream_ops, - .output = output, - }; - - if (deflateInit2(&gos->zs, 9, Z_DEFLATED, 15 | 16, 8, - Z_DEFAULT_STRATEGY) != Z_OK) { - free(gos); - goto err; - } - - return &gos->os; -err: - apk_ostream_close(output); - return ERR_PTR(-ENOMEM); -} - |