diff options
author | Timo Teräs <timo.teras@iki.fi> | 2020-01-10 11:02:48 +0200 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2020-01-11 03:44:23 +0200 |
commit | 7ca0d146ecaf2f99781653d1203bd3db7afc85ba (patch) | |
tree | 0b167bd627a174be8e0d24f2af0f3697904ad5de /src/gunzip.c | |
parent | 9dda2d3c21d1116077257caafa065b659ffe419b (diff) | |
download | apk-tools-7ca0d146ecaf2f99781653d1203bd3db7afc85ba.tar.gz apk-tools-7ca0d146ecaf2f99781653d1203bd3db7afc85ba.tar.bz2 apk-tools-7ca0d146ecaf2f99781653d1203bd3db7afc85ba.tar.xz apk-tools-7ca0d146ecaf2f99781653d1203bd3db7afc85ba.zip |
istream: add buffering capability
Convert all implementations to do buffering. This is in preparation
to remove bstream interface as redundant.
istream_read() will return full reads unless end-of-file. The backends
can return short reads to optimize buffering or due to other reasons
like boundary change for gz.
Diffstat (limited to 'src/gunzip.c')
-rw-r--r-- | src/gunzip.c | 34 |
1 files changed, 12 insertions, 22 deletions
diff --git a/src/gunzip.c b/src/gunzip.c index 2c35c5b..17b74a3 100644 --- a/src/gunzip.c +++ b/src/gunzip.c @@ -22,7 +22,6 @@ struct apk_gzip_istream { struct apk_istream is; struct apk_bstream *bs; z_stream zs; - int err; apk_multipart_cb cb; void *cbctx; @@ -40,9 +39,9 @@ static int gzi_boundary_change(struct apk_gzip_istream *gis) { int r; - r = gis->cb(gis->cbctx, gis->err ? APK_MPART_END : APK_MPART_BOUNDARY, gis->cbarg); + 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->err = r; + if (r != 0) gis->is.err = r; return r; } @@ -51,19 +50,10 @@ 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; - if (gis->err != 0) { - if (gis->err > 0) - return 0; - return gis->err; - } - - 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->err == 0) { + while (gis->zs.avail_out != 0 && gis->is.err == 0) { if (!APK_BLOB_IS_NULL(gis->cbarg)) { if (gzi_boundary_change(gis)) goto ret; @@ -83,10 +73,10 @@ static ssize_t gzi_read(struct apk_istream *is, void *ptr, size_t size) gis->zs.avail_in = blob.len; gis->zs.next_in = (void *) gis->cbprev; if (blob.len < 0) { - gis->err = blob.len; + gis->is.err = blob.len; goto ret; } else if (gis->zs.avail_in == 0) { - gis->err = 1; + gis->is.err = 1; gis->cbarg = APK_BLOB_NULL; gzi_boundary_change(gis); goto ret; @@ -99,7 +89,7 @@ static ssize_t gzi_read(struct apk_istream *is, void *ptr, size_t size) /* Digest the inflated bytes */ if ((gis->bs->flags & APK_BSTREAM_EOF) && gis->zs.avail_in == 0) - gis->err = 1; + gis->is.err = 1; 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; @@ -109,26 +99,24 @@ static ssize_t gzi_read(struct apk_istream *is, void *ptr, size_t size) * 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->err) { + 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->err = -EIO; + gis->is.err = -EIO; break; } } ret: - if (size - gis->zs.avail_out == 0) - return gis->err < 0 ? gis->err : 0; - return size - gis->zs.avail_out; } @@ -154,11 +142,13 @@ struct apk_istream *apk_bstream_gunzip_mpart(struct apk_bstream *bs, if (IS_ERR_OR_NULL(bs)) return ERR_CAST(bs); - gis = malloc(sizeof(struct apk_gzip_istream)); + 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, .bs = bs, .cb = cb, .cbctx = ctx, |