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