summaryrefslogtreecommitdiffstats
path: root/src/package.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/package.c')
-rw-r--r--src/package.c348
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);
}