123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #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;
- uint32_t *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;
- }
|