1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 5 void 6 usage(void) 7 { 8 fprint(2, "usage: unbflz [file]\n"); 9 exits("usage"); 10 } 11 12 int 13 Bgetint(Biobuf *b) 14 { 15 uchar p[4]; 16 17 if(Bread(b, p, 4) != 4) 18 sysfatal("short read"); 19 return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; 20 } 21 22 /* 23 * memmove but make sure overlap works properly. 24 */ 25 void 26 copy(uchar *dst, uchar *src, int n) 27 { 28 while(n-- > 0) 29 *dst++ = *src++; 30 } 31 32 void 33 main(int argc, char **argv) 34 { 35 Biobuf *b, bin; 36 char buf[5]; 37 uchar *data; 38 ulong *blk, l; 39 int nblk, mblk; 40 int sum; 41 int i, j, length, m, n, o; 42 43 ARGBEGIN{ 44 default: 45 usage(); 46 }ARGEND 47 48 switch(argc){ 49 default: 50 usage(); 51 case 0: 52 Binit(&bin, 0, OREAD); 53 b = &bin; 54 break; 55 case 1: 56 if((b = Bopen(argv[0], OREAD)) == nil) 57 sysfatal("open %s: %r", argv[0]); 58 break; 59 } 60 61 if(Bread(b, buf, 4) != 4) 62 sysfatal("short read"); 63 64 if(memcmp(buf, "BLZ\n", 4) != 0) 65 sysfatal("bad header"); 66 67 length = Bgetint(b); 68 data = malloc(length); 69 if(data == nil) 70 sysfatal("out of memory"); 71 sum = 0; 72 nblk = 0; 73 mblk = 0; 74 blk = nil; 75 while(sum < length){ 76 if(nblk>=mblk){ 77 mblk += 16384; 78 blk = realloc(blk, (mblk+1)*sizeof(blk[0])); 79 if(blk == nil) 80 sysfatal("out of memory"); 81 } 82 l = Bgetint(b); 83 blk[nblk++] = l; 84 if(l&(1<<31)) 85 l &= ~(1<<31); 86 else 87 blk[nblk++] = Bgetint(b); 88 sum += l; 89 } 90 if(sum != length) 91 sysfatal("bad compressed data %d %d", sum, length); 92 i = 0; 93 j = 0; 94 while(i < length){ 95 assert(j < nblk); 96 n = blk[j++]; 97 if(n&(1<<31)){ 98 n &= ~(1<<31); 99 if((m=Bread(b, data+i, n)) != n) 100 sysfatal("short read %d %d", n, m); 101 }else{ 102 o = blk[j++]; 103 copy(data+i, data+o, n); 104 } 105 i += n; 106 } 107 write(1, data, length); 108 exits(nil); 109 } 110