1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include "bzfs.h"
5
6 int
Bgetint(Biobuf * b)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
copy(uchar * dst,uchar * src,int n)20 copy(uchar *dst, uchar *src, int n)
21 {
22 while(n-- > 0)
23 *dst++ = *src++;
24 }
25
26 int
unbflz(int in)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