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