add got_inflate_read_fd() and got_inflate_to_fd()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
diff --git a/lib/got_lib_zbuf.h b/lib/got_lib_zbuf.h
index 9285ed5..0f06cc0 100644
--- a/lib/got_lib_zbuf.h
+++ b/lib/got_lib_zbuf.h
@@ -31,6 +31,9 @@ const struct got_error *got_inflate_init(struct got_zstream_buf *, uint8_t *,
size_t);
const struct got_error *got_inflate_read(struct got_zstream_buf *, FILE *,
size_t *);
+const struct got_error *got_inflate_read_fd(struct got_zstream_buf *, int,
+ size_t *);
void got_inflate_end(struct got_zstream_buf *);
const struct got_error *got_inflate_to_mem(uint8_t **, size_t *, FILE *);
const struct got_error *got_inflate_to_file(size_t *, FILE *, FILE *);
+const struct got_error *got_inflate_to_fd(size_t *, int, int);
diff --git a/lib/zbuf.c b/lib/zbuf.c
index 2b3120f..dcb2c9d 100644
--- a/lib/zbuf.c
+++ b/lib/zbuf.c
@@ -105,6 +105,45 @@ got_inflate_read(struct got_zstream_buf *zb, FILE *f, size_t *outlenp)
return NULL;
}
+const struct got_error *
+got_inflate_read_fd(struct got_zstream_buf *zb, int fd, size_t *outlenp)
+{
+ size_t last_total_out = zb->z.total_out;
+ z_stream *z = &zb->z;
+ int ret = Z_ERRNO;
+
+ z->next_out = zb->outbuf;
+ z->avail_out = zb->outlen;
+
+ *outlenp = 0;
+ do {
+ if (z->avail_in == 0) {
+ ssize_t n = read(fd, zb->inbuf, zb->inlen);
+ if (n < 0)
+ return got_error_from_errno();
+ else if (n == 0) {
+ /* EOF */
+ ret = Z_STREAM_END;
+ break;
+ }
+ z->next_in = zb->inbuf;
+ z->avail_in = n;
+ }
+ ret = inflate(z, Z_SYNC_FLUSH);
+ } while (ret == Z_OK && z->avail_out > 0);
+
+ if (ret == Z_OK) {
+ zb->flags |= GOT_ZSTREAM_F_HAVE_MORE;
+ } else {
+ if (ret != Z_STREAM_END)
+ return got_error(GOT_ERR_DECOMPRESSION);
+ zb->flags &= ~GOT_ZSTREAM_F_HAVE_MORE;
+ }
+
+ *outlenp = z->total_out - last_total_out;
+ return NULL;
+}
+
void
got_inflate_end(struct got_zstream_buf *zb)
{
@@ -158,6 +197,43 @@ done:
}
const struct got_error *
+got_inflate_to_fd(size_t *outlen, int infd, int outfd)
+{
+ const struct got_error *err = NULL;
+ size_t avail;
+ struct got_zstream_buf zb;
+
+ err = got_inflate_init(&zb, NULL, GOT_ZSTREAM_BUFSIZE);
+ if (err)
+ goto done;
+
+ *outlen = 0;
+
+ do {
+ err = got_inflate_read_fd(&zb, infd, &avail);
+ if (err)
+ return err;
+ if (avail > 0) {
+ ssize_t n;
+ n = write(outfd, zb.outbuf, avail);
+ if (n != avail) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ *outlen += avail;
+ }
+ } while (zb.flags & GOT_ZSTREAM_F_HAVE_MORE);
+
+done:
+ if (err == NULL) {
+ if (lseek(outfd, SEEK_SET, 0) == -1)
+ err = got_error_from_errno();
+ }
+ got_inflate_end(&zb);
+ return err;
+}
+
+const struct got_error *
got_inflate_to_file(size_t *outlen, FILE *infile, FILE *outfile)
{
const struct got_error *err;