xref: /plan9-contrib/sys/src/nboot/bitsy/inflate.c (revision 529c1f209803c78c4f2cda11b13818a57f01c872)
1 #include "u.h"
2 #include "lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include <flate.h>
8 
9 typedef struct Biobuf	Biobuf;
10 
11 struct Biobuf
12 {
13 	uchar *bp;
14 	uchar *p;
15 	uchar *ep;
16 };
17 
18 static int	header(Biobuf*);
19 static int	trailer(Biobuf*, Biobuf*);
20 static int	getc(void*);
21 static ulong	offset(Biobuf*);
22 static int	crcwrite(void *out, void *buf, int n);
23 static ulong	get4(Biobuf *b);
24 static ulong	Boffset(Biobuf *bp);
25 
26 /* GZIP flags */
27 enum {
28 	Ftext=		(1<<0),
29 	Fhcrc=		(1<<1),
30 	Fextra=		(1<<2),
31 	Fname=		(1<<3),
32 	Fcomment=	(1<<4),
33 
34 	GZCRCPOLY	= 0xedb88320UL,
35 };
36 
37 static ulong	*crctab;
38 static ulong	crc;
39 
40 int
gunzip(uchar * out,int outn,uchar * in,int inn)41 gunzip(uchar *out, int outn, uchar *in, int inn)
42 {
43 	Biobuf bin, bout;
44 	int err;
45 
46 	crc = 0;
47 	crctab = mkcrctab(GZCRCPOLY);
48 	err = inflateinit();
49 	if(err != FlateOk)
50 		print("inflateinit failed: %s\n", flateerr(err));
51 
52 	bin.bp = bin.p = in;
53 	bin.ep = in+inn;
54 	bout.bp = bout.p = out;
55 	bout.ep = out+outn;
56 
57 	err = header(&bin);
58 	if(err != FlateOk)
59 		return err;
60 
61 	err = inflate(&bout, crcwrite, &bin, getc);
62 	if(err != FlateOk)
63 		print("inflate failed: %s\n", flateerr(err));
64 
65 	err = trailer(&bout, &bin);
66 	if(err != FlateOk)
67 		return err;
68 
69 	return Boffset(&bout);
70 }
71 
72 static int
header(Biobuf * bin)73 header(Biobuf *bin)
74 {
75 	int i, flag;
76 
77 	if(getc(bin) != 0x1f || getc(bin) != 0x8b){
78 		print("bad magic\n");
79 		return FlateCorrupted;
80 	}
81 	if(getc(bin) != 8){
82 		print("unknown compression type\n");
83 		return FlateCorrupted;
84 	}
85 
86 	flag = getc(bin);
87 
88 	/* mod time */
89 	get4(bin);
90 
91 	/* extra flags */
92 	getc(bin);
93 
94 	/* OS type */
95 	getc(bin);
96 
97 	if(flag & Fextra)
98 		for(i=getc(bin); i>0; i--)
99 			getc(bin);
100 
101 	/* name */
102 	if(flag&Fname)
103 		while(getc(bin) != 0)
104 			;
105 
106 	/* comment */
107 	if(flag&Fcomment)
108 		while(getc(bin) != 0)
109 			;
110 
111 	/* crc16 */
112 	if(flag&Fhcrc) {
113 		getc(bin);
114 		getc(bin);
115 	}
116 
117 	return FlateOk;
118 }
119 
120 static int
trailer(Biobuf * bout,Biobuf * bin)121 trailer(Biobuf *bout, Biobuf *bin)
122 {
123 	/* crc32 */
124 	ulong x;
125 
126 	x = get4(bin);
127 	if(crc != x){
128 		print("crc mismatch %lux %lux\n", crc, x);
129 		return FlateCorrupted;
130 	}
131 
132 	/* length */
133 	if(get4(bin) != Boffset(bout)){
134 		print("bad output len\n");
135 		return FlateCorrupted;
136 	}
137 	return FlateOk;
138 }
139 
140 static ulong
get4(Biobuf * b)141 get4(Biobuf *b)
142 {
143 	ulong v;
144 	int i, c;
145 
146 	v = 0;
147 	for(i = 0; i < 4; i++){
148 		c = getc(b);
149 		v |= c << (i * 8);
150 	}
151 	return v;
152 }
153 
154 static int
getc(void * in)155 getc(void *in)
156 {
157 	Biobuf *bp = in;
158 
159 	if((bp->p - bp->bp) % 10000 == 0)
160 		print(".");
161 	if(bp->p >= bp->ep)
162 		return -1;
163 	return *bp->p++;
164 }
165 
166 static ulong
Boffset(Biobuf * bp)167 Boffset(Biobuf *bp)
168 {
169 	return bp->p - bp->bp;
170 }
171 
172 static int
crcwrite(void * out,void * buf,int n)173 crcwrite(void *out, void *buf, int n)
174 {
175 	Biobuf *bp;
176 
177 	crc = blockcrc(crctab, crc, buf, n);
178 	bp = out;
179 	if(n > bp->ep-bp->p)
180 		n = bp->ep-bp->p;
181 	memmove(bp->p, buf, n);
182 	bp->p += n;
183 	return n;
184 }
185 
186 #undef malloc
187 #undef free
188 
189 static ulong ibrkp = ~0;
190 
191 void *
malloc(ulong n)192 malloc(ulong n)
193 {
194 	ulong rv;
195 
196 	if(ibrkp == ~0)
197 		ibrkp = ((ulong)end)+1024*1024;
198 	n = (n+3)>>2;
199 	n <<= 2;
200 	rv = ibrkp;
201 	ibrkp += n;
202 	return (void*)rv;
203 }
204 
205 void
free(void *)206 free(void *)
207 {
208 }
209