diff options
author | cinap_lenrek <cinap_lenrek@localhost> | 2011-06-26 07:03:12 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@localhost> | 2011-06-26 07:03:12 +0200 |
commit | bc1ff6985c03402497a052d2b4e2a299b3cdf218 (patch) | |
tree | 92dcfc77cd3fed9adae59994fd4825a7770bead8 /sys/src/cmd/hgfs/zip.c | |
parent | 8fa679d04171417d9420b91471cf45e148b4cc50 (diff) |
add hgfs, a mercurial filesystem
Diffstat (limited to 'sys/src/cmd/hgfs/zip.c')
-rw-r--r-- | sys/src/cmd/hgfs/zip.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/sys/src/cmd/hgfs/zip.c b/sys/src/cmd/hgfs/zip.c new file mode 100644 index 000000000..31ab65f64 --- /dev/null +++ b/sys/src/cmd/hgfs/zip.c @@ -0,0 +1,97 @@ +#include <u.h> +#include <libc.h> +#include <thread.h> +#include "dat.h" +#include "fns.h" + +#include <flate.h> + +struct zbuf { + int fd; + int len; + + uchar *b, *p, *e; +}; + +static int +zwrite(void *a, void *p, int n) +{ + int *ofd = a; + + if(write(*ofd, p, n) != n) + return -1; + return n; +} + +static int +zgetc(void *a) +{ + struct zbuf *z = a; + int n; + + for(;;){ + if(z->p < z->e) + return *z->p++; + if(z->len <= 0) + return -1; + if((n = BUFSZ) > z->len) + n = z->len; + if((n = read(z->fd, z->p = z->b, n)) <= 0) + return -1; + z->len -= n; + z->e = z->p + n; + } +} + +int +funzip(int ofd, int zfd, int len) +{ + uchar buf[BUFSZ]; + struct zbuf z; + int wlen, n; + uchar *p; + + if(len == 0) + return 0; + + wlen = 0; + if((n = BUFSZ) > len) + n = len; + if((n = read(zfd, p = buf, n)) <= 0) + return -1; + len -= n; + switch(*p){ + default: + return -1; + case 'u': + p++; + n--; + /* no break */ + case '\0': + while((n > 0) && (write(ofd, p, n) == n)){ + wlen += n; + if(len <= 0) + break; + if((n = BUFSZ) > len) + n = len; + if((n = read(zfd, p = buf, n)) <= 0) + break; + len -= n; + } + break; + case 'x': + if(n < 2) + return -1; + z.fd = zfd; + z.len = len; + z.b = buf; + z.p = p + 2; + z.e = p + n; + if((wlen = inflate(&ofd, zwrite, &z, zgetc)) < 0){ + werrstr("%s", flateerr(wlen)); + return -1; + } + break; + } + return wlen; +} |