/* * Compress input and feed it to a block-oriented back end. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <inttypes.h> #include <stdbool.h> #include <zlib.h> #include "upload_backend.h" #include "ctime.h" #define ALLOC_CHUNK 65536 int init_data(struct upload_backend *be, const char *argv[]) { be->now = posix_time(); be->argv = argv; memset(&be->zstream, 0, sizeof be->zstream); be->zstream.next_out = NULL; be->outbuf = NULL; be->zstream.avail_out = be->alloc = 0; be->dbytes = be->zbytes = 0; /* Initialize a gzip data stream */ if (deflateInit2(&be->zstream, 9, Z_DEFLATED, 16+15, 9, Z_DEFAULT_STRATEGY) < 0) return -1; return 0; } static int do_deflate(struct upload_backend *be, int flush) { int rv; char *buf; while (1) { rv = deflate(&be->zstream, flush); be->zbytes = be->alloc - be->zstream.avail_out; if (be->zstream.avail_out) return rv; /* Not an issue of output space... */ buf = realloc(be->outbuf, be->alloc + ALLOC_CHUNK); if (!buf) return Z_MEM_ERROR; be->outbuf = buf; be->alloc += ALLOC_CHUNK; be->zstream.next_out = (void *)(buf + be->zbytes); be->zstream.avail_out = be->alloc - be->zbytes; } } int write_data(struct upload_backend *be, const void *buf, size_t len) { int rv = Z_OK; be->zstream.next_in = (void *)buf; be->zstream.avail_in = len; be->dbytes += len; while (be->zstream.avail_in) { rv = do_deflate(be, Z_NO_FLUSH); if (rv < 0) { printf("do_deflate returned %d\n", rv); return -1; } } return 0; } /* Output the data and shut down the stream */ int flush_data(struct upload_backend *be) { int rv = Z_OK; int err=-1; while (rv != Z_STREAM_END) { rv = do_deflate(be, Z_FINISH); if (rv < 0) return -1; } // printf("Uploading data, %u bytes... ", be->zbytes); if ((err=be->write(be)) != 0) return err; free(be->outbuf); be->outbuf = NULL; be->dbytes = be->zbytes = be->alloc = 0; // printf("done.\n"); return 0; }