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