diff options
Diffstat (limited to 'src/package.c')
-rw-r--r-- | src/package.c | 348 |
1 files changed, 298 insertions, 50 deletions
diff --git a/src/package.c b/src/package.c index 0c26fef..c684020 100644 --- a/src/package.c +++ b/src/package.c @@ -30,6 +30,8 @@ #include <sys/stat.h> #include <fcntl.h> +#include <zlib.h> + #include "package.h" #include "util.h" #include "syrep.h" @@ -43,10 +45,14 @@ struct package_item { struct package_item *next; }; +#define ZBUFSIZE (64*1024) + struct package { char *base; int count; int read_fd, write_fd; + z_stream read_z, write_z; + void *read_zbuf, *write_zbuf; int x_endianess; int compressed; struct package_item *items; @@ -54,37 +60,205 @@ struct package { }; +static int alloc_read_zbuf(struct package *p) { + if (!p->read_zbuf) + if (!(p->read_zbuf = malloc(ZBUFSIZE))) { + fprintf(stderr, "malloc(): %s\n", strerror(errno)); + return -1; + } + + return 0; +} + +static int alloc_write_zbuf(struct package *p) { + if (!p->write_zbuf) + if (!(p->write_zbuf = malloc(ZBUFSIZE))) { + fprintf(stderr, "malloc(): %s\n", strerror(errno)); + return -1; + } + + return 0; +} + static ssize_t package_read(struct package *p, void *d, size_t l) { - if (!p->compressed) - return loop_read(p->read_fd, d, l); + ssize_t r = -1; + + if (!p->compressed) { + + if ((r = loop_read(p->read_fd, d, l)) < 0) + fprintf(stderr, "read(): %s\n", strerror(errno)); + + goto finish; + } + + if (!p->read_zbuf && alloc_read_zbuf(p) < 0) + return -1; + + p->read_z.next_out = d; + p->read_z.avail_out = l; + + while (p->read_z.avail_out > 0) { + int z; + + if (p->read_z.avail_in <= 0) { + ssize_t n; + + if ((n = read(p->read_fd, p->read_zbuf, ZBUFSIZE)) < 0) { + fprintf(stderr, "read(): %s\n", strerror(errno)); + goto finish; + } + + if (!n) { + r = (void*) p->read_z.next_out - d; + goto finish; + } + + p->read_z.next_in = p->read_zbuf; + p->read_z.avail_in = n; + } + + if ((z = inflate(&p->read_z, 0)) != Z_OK) { + + if (z == Z_STREAM_END) { + r = (void*) p->read_z.next_out - d; + goto finish; + } + + + fprintf(stderr, "XXX inflate() failed %i\n", z); + goto finish; + } + } + + r = l; - assert(0); +finish: - return -1; + return r; } static ssize_t package_write(struct package *p, void *d, size_t l) { - if (!args.compress_flag) - return loop_write(p->write_fd, d, l); + ssize_t r = -1; + + if (!args.compress_flag) { + + if ((r = loop_write(p->write_fd, d, l)) < 0) + fprintf(stderr, "write(): %s\n", strerror(errno)); + + goto finish; + } - assert(0); + if (!p->write_zbuf && alloc_write_zbuf(p) < 0) + return -1; - return -1; + p->write_z.next_in = d; + p->write_z.avail_in = l; + + while (p->write_z.avail_in > 0) { + size_t t; + + p->write_z.next_out = p->write_zbuf; + p->write_z.avail_out = ZBUFSIZE; + + + if (deflate(&p->write_z, Z_NO_FLUSH) != Z_OK) { + fprintf(stderr, "deflate() failed\n"); + goto finish; + } + + t = (void*) p->write_z.next_out - p->write_zbuf; + + if (t) { + ssize_t n; + + if ((n = loop_write(p->write_fd, p->write_zbuf, t)) < 0) { + fprintf(stderr, "loop_write(): %s\n", strerror(errno)); + goto finish; + } + + if (n != t) { + if ((r = (void*) p->write_z.next_in - d) > 0) + r --; + + goto finish; + } + } + } + + r = l; + +finish: + + return r; + } +#define CBUFSIZE ZBUFSIZE static int copy_deflate(struct package *p, int sfd, off_t l) { + void *buf = NULL; + int r = -1; - assert(0); + if (!(buf = malloc(CBUFSIZE))) { + fprintf(stderr, "malloc(): %s\n", strerror(errno)); + goto finish; + } - return 0; + while (l > 0) { + size_t t = MIN(l, CBUFSIZE); + ssize_t n; + + if ((n = loop_read(sfd, buf, t)) != t) { + fprintf(stderr, "read() : %s\n", n < 0 ? strerror(errno) : "EOF"); + goto finish; + } + + if (package_write(p, buf, n) != n) + goto finish; + + l -= n; + } + + r = 0; + +finish: + if (buf) + free(buf); + + return r; } static int copy_inflate(struct package *p, int dfd, off_t l) { + void *buf = NULL; + int r = -1; - assert(0); + if (!(buf = malloc(CBUFSIZE))) { + fprintf(stderr, "malloc(): %s\n", strerror(errno)); + goto finish; + } - return 0; + while (l > 0) { + size_t t = MIN(l, CBUFSIZE); + ssize_t n; + + if (package_read(p, buf, t) != t) + goto finish; + + if ((n = loop_write(dfd, buf, t)) != t) { + fprintf(stderr, "write() : %s\n", n < 0 ? strerror(errno) : "EOF"); + goto finish; + } + + l -= n; + } + + r = 0; + +finish: + if (buf) + free(buf); + + return r; } static char *tmp(char *fn, int l) { @@ -147,6 +321,67 @@ static void append_item(struct package *p, struct package_item *i) { p->items = p->last = i; } +static void close_read_fd(struct package *p) { + assert(p); + + if (p->read_fd >= 0) { + if (p->compressed) + inflateEnd(&p->read_z); + + if (p->read_fd != STDIN_FILENO) + close(p->read_fd); + p->read_fd = -1; + } +} + +static int close_write_fd(struct package *p) { + int r = 0; + assert(p); + + if (p->write_fd >= 0) { + if (args.compress_flag) { + int z; + + p->write_z.next_in = NULL; + p->write_z.avail_in = 0; + + do { + size_t t; + ssize_t n; + + p->write_z.next_out = p->write_zbuf; + p->write_z.avail_out = ZBUFSIZE; + + z = deflate(&p->write_z, Z_FINISH); + + t = (void*) p->write_z.next_out - p->write_zbuf; + if (t) { + if ((n = loop_write(p->write_fd, p->write_zbuf, t)) != t) { + fprintf(stderr, "loop_write(): %s\n", n < 0 ? strerror(errno) : "EOF"); + r = -1; + break; + } + } + + } while (z == Z_OK); + + if (!r && z != Z_STREAM_END) { + fprintf(stderr, "Final deflate() failure\n"); + r = -1; + } + + deflateEnd(&p->write_z); + } + + if (p->write_fd != STDOUT_FILENO) + close(p->write_fd); + + p->write_fd = -1; + } + + return r; +} + #define X32(i) (((i)<<24)|(((i)<<8)&0x00FF0000)|(((i)>>8)&0x0000FF00)|((i)>>24)) #define X64(i) (X32((i)>>32)|X32((i)>>32)) @@ -164,22 +399,17 @@ static int read_item(struct package *p) { if ((r = package_read(p, name, PACKAGE_ITEMNAMELEN)) != PACKAGE_ITEMNAMELEN) { if (r == 0) { - close(p->read_fd); - p->read_fd = -1; + close_read_fd(p); return 0; } else if (r > 0) fprintf(stderr, "Short read\n"); - else - fprintf(stderr, "read(): %s\n", strerror(errno)); goto fail; } - if ((r = package_read(p, &l, 8) != 8)) { + if ((r = package_read(p, &l, 8)) != 8) { if (r >= 0) fprintf(stderr, "Short read\n"); - else - fprintf(stderr, "read(): %s\n", strerror(errno)); goto fail; } @@ -247,21 +477,17 @@ static int write_item(struct package *p, struct package_item *i) { memset(name, 0, sizeof(name)); strncpy(name, i->name, PACKAGE_ITEMNAMELEN); - if ((r = package_write(p, name, PACKAGE_ITEMNAMELEN) != PACKAGE_ITEMNAMELEN)) { + if ((r = package_write(p, name, PACKAGE_ITEMNAMELEN)) != PACKAGE_ITEMNAMELEN) { if (r >= 0) fprintf(stderr, "Short write\n"); - else - fprintf(stderr, "write(): %s\n", strerror(errno)); goto fail; } l = (uint64_t) size; - if ((r = package_write(p, &l, 8) != 8)) { + if ((r = package_write(p, &l, 8)) != 8) { if (r >= 0) fprintf(stderr, "Short write\n"); - else - fprintf(stderr, "write(): %s\n", strerror(errno)); goto fail; } @@ -312,30 +538,31 @@ struct package* package_open(const char *fn, int force) { if (fn) { - if ((p->read_fd = open(fn, O_RDONLY)) < 0) { + + if (!strcmp(fn, "-")) + p->read_fd = STDIN_FILENO; + else if ((p->read_fd = open(fn, O_RDONLY)) < 0) { if (errno != ENOENT || !force) { fprintf(stderr, "Failed to open <%s>: %s\n", fn, strerror(errno)); goto finish; } - - } else if (p->read_fd >= 0) { + } + + if (p->read_fd >= 0) { uint32_t id; ssize_t r; if ((r = loop_read(p->read_fd, &id, 4)) != 4) { - if (r < 0) - fprintf(stderr, "read(): %s\n", strerror(errno)); - else - fprintf(stderr, "Short read\n"); - + fprintf(stderr, "read(): %s\n", r < 0 ? strerror(errno) : "EOF"); + goto finish; } if (id == PACKAGE_FILEID) - p->x_endianess = 0; + p->x_endianess = p->compressed = 0; else if (id == X32(PACKAGE_FILEID)) - p->x_endianess = 1; + p->x_endianess = !(p->compressed = 0); else if (id == PACKAGE_FILEIDCOMPRESSED) p->x_endianess = !(p->compressed = 1); else if (id == X32(PACKAGE_FILEIDCOMPRESSED)) @@ -348,6 +575,19 @@ struct package* package_open(const char *fn, int force) { } + if (p->compressed) { + + memset(&p->read_z, 0, sizeof(p->read_z)); + + if (inflateInit(&p->read_z) != Z_OK) { + fprintf(stderr, "zlib initialisation failure\n"); + goto finish; + } + + + } + + return p; finish: @@ -385,25 +625,32 @@ int package_save(struct package *p, const char *fn) { if (load_complete(p) < 0) goto finish; - if (!fn) + if (!fn || !strcmp(fn, "-")) p->write_fd = STDOUT_FILENO; else if ((p->write_fd = open(fn, O_RDWR|O_TRUNC|O_CREAT, 0666)) < 0) { /* RDWR for mmap compatibility */ fprintf(stderr, "open(\"%s\") XX: %s\n", fn, strerror(errno)); goto finish; } - id = p->compressed ? PACKAGE_FILEIDCOMPRESSED : PACKAGE_FILEID; + id = args.compress_flag ? PACKAGE_FILEIDCOMPRESSED : PACKAGE_FILEID; - if ((n = loop_write(p->write_fd, &id, 4) != 4)) { + if ((n = loop_write(p->write_fd, &id, 4)) != 4) { if (n < 0) - fprintf(stderr, "write(): %s\n", strerror(errno)); - else - fprintf(stderr, "Short write\n"); + fprintf(stderr, "write(): %s\n", r < 0 ? strerror(errno) : "EOF"); goto finish; } - + if (args.compress_flag) { + + memset(&p->write_z, 0, sizeof(p->write_z)); + + if (deflateInit(&p->write_z, Z_DEFAULT_COMPRESSION) != Z_OK) { + fprintf(stderr, "zlib initialisation failure\n"); + goto finish; + } + } + for (i = p->items; i; i = i->next) { if (!i->name || !i->path) @@ -419,10 +666,8 @@ int package_save(struct package *p, const char *fn) { finish: - if (fn && p->write_fd >= 0) - close(p->write_fd); - - p->write_fd = -1; + if (close_write_fd(p) < 0) + r = -1; if (r < 0 && fn) unlink(fn); @@ -507,11 +752,14 @@ void package_remove(struct package *p) { free(p->base); } - if (p->read_fd >= 0) - close(p->read_fd); + close_read_fd(p); + close_write_fd(p); - if (p->write_fd >= 0) - close(p->write_fd); + if (p->read_zbuf) + free(p->read_zbuf); + + if (p->write_zbuf) + free(p->write_zbuf); free(p); } |