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