diff options
author | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-04-11 19:47:05 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@centraldogma> | 2011-04-11 19:47:05 +0000 |
commit | 45bab89362ebe122d60d5e9b1e2b949b26168db3 (patch) | |
tree | c430eb677a06d8c823fd1d2d4a9f7790c0c275d2 /sys/lib/dist.old/cmd/bzfs/unbflz.c | |
parent | 05569f6f2c54a19c1c85a7f10742913cd8904787 (diff) |
livecd
Diffstat (limited to 'sys/lib/dist.old/cmd/bzfs/unbflz.c')
-rw-r--r-- | sys/lib/dist.old/cmd/bzfs/unbflz.c | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/sys/lib/dist.old/cmd/bzfs/unbflz.c b/sys/lib/dist.old/cmd/bzfs/unbflz.c new file mode 100644 index 000000000..661d65e4d --- /dev/null +++ b/sys/lib/dist.old/cmd/bzfs/unbflz.c @@ -0,0 +1,108 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include "bzfs.h" + +int +Bgetint(Biobuf *b) +{ + uchar p[4]; + + if(Bread(b, p, 4) != 4) + sysfatal("short read"); + return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; +} + +/* + * memmove but make sure overlap works properly. + */ +void +copy(uchar *dst, uchar *src, int n) +{ + while(n-- > 0) + *dst++ = *src++; +} + +int +unbflz(int in) +{ + int rv, out, p[2]; + Biobuf *b, bin; + char buf[5]; + uchar *data; + int i, j, length, n, m, o, sum; + ulong *blk; + int nblk, mblk; + + if(pipe(p) < 0) + sysfatal("pipe: %r"); + + rv = p[0]; + out = p[1]; + switch(rfork(RFPROC|RFFDG|RFNOTEG|RFMEM)){ + case -1: + sysfatal("fork: %r"); + case 0: + close(rv); + break; + default: + close(in); + close(out); + return rv; + } + + Binit(&bin, in, OREAD); + b = &bin; + + if(Bread(b, buf, 4) != 4) + sysfatal("short read"); + + if(memcmp(buf, "BLZ\n", 4) != 0) + sysfatal("bad header"); + + length = Bgetint(b); + data = malloc(length); + if(data == nil) + sysfatal("out of memory"); + sum = 0; + nblk = 0; + mblk = 0; + blk = nil; + while(sum < length){ + if(nblk>=mblk){ + mblk += 16384; + blk = realloc(blk, (mblk+1)*sizeof(blk[0])); + if(blk == nil) + sysfatal("out of memory"); + } + n = Bgetint(b); + blk[nblk++] = n; + if(n&(1<<31)) + n &= ~(1<<31); + else + blk[nblk++] = Bgetint(b); + sum += n; + } + if(sum != length) + sysfatal("bad compressed data %d %d", sum, length); + i = 0; + j = 0; + while(i < length){ + assert(j < nblk); + n = blk[j++]; + if(n&(1<<31)){ + n &= ~(1<<31); + if((m=Bread(b, data+i, n)) != n) + sysfatal("short read %d %d", n, m); + }else{ + o = blk[j++]; + copy(data+i, data+o, n); + } + i += n; + } + write(out, data, length); + close(in); + close(out); + _exits(0); + return -1; +} |