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