xref: /plan9/sys/lib/dist/cmd/unbflz.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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