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