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