1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 void
usage(void)6 usage(void)
7 {
8 fprint(2, "usage: unbflz [file]\n");
9 exits("usage");
10 }
11
12 int
Bgetint(Biobuf * b)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
copy(uchar * dst,uchar * src,int n)26 copy(uchar *dst, uchar *src, int n)
27 {
28 while(n-- > 0)
29 *dst++ = *src++;
30 }
31
32 void
main(int argc,char ** argv)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