ref: 2e05af858ec745ffc174e503148ef7928f697c22
dir: /sys/src/cmd/bzfs/unbflz.c/
#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; }