123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- void
- usage(void)
- {
- fprint(2, "usage: unbflz [file]\n");
- exits("usage");
- }
- 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++;
- }
- void
- main(int argc, char **argv)
- {
- Biobuf *b, bin;
- char buf[5];
- uchar *data;
- ulong *blk, l;
- int nblk, mblk;
- int sum;
- int i, j, length, m, n, o;
- ARGBEGIN{
- default:
- usage();
- }ARGEND
- switch(argc){
- default:
- usage();
- case 0:
- Binit(&bin, 0, OREAD);
- b = &bin;
- break;
- case 1:
- if((b = Bopen(argv[0], OREAD)) == nil)
- sysfatal("open %s: %r", argv[0]);
- break;
- }
- 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");
- }
- l = Bgetint(b);
- blk[nblk++] = l;
- if(l&(1<<31))
- l &= ~(1<<31);
- else
- blk[nblk++] = Bgetint(b);
- sum += l;
- }
- 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(1, data, length);
- exits(nil);
- }
|