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