Blame


1 ff3adf60 2004-04-14 devnull #include <u.h>
2 ff3adf60 2004-04-14 devnull #include <libc.h>
3 ff3adf60 2004-04-14 devnull #include <bio.h>
4 ff3adf60 2004-04-14 devnull #include <flate.h>
5 ff3adf60 2004-04-14 devnull #include "gzip.h"
6 ff3adf60 2004-04-14 devnull
7 ff3adf60 2004-04-14 devnull typedef struct GZHead GZHead;
8 ff3adf60 2004-04-14 devnull
9 ff3adf60 2004-04-14 devnull struct GZHead
10 ff3adf60 2004-04-14 devnull {
11 8425b514 2010-02-23 rsc u32int mtime;
12 ff3adf60 2004-04-14 devnull char *file;
13 ff3adf60 2004-04-14 devnull };
14 ff3adf60 2004-04-14 devnull
15 ff3adf60 2004-04-14 devnull static int crcwrite(void *bout, void *buf, int n);
16 ff3adf60 2004-04-14 devnull static int get1(Biobuf *b);
17 8425b514 2010-02-23 rsc static u32int get4(Biobuf *b);
18 ff3adf60 2004-04-14 devnull static int gunzipf(char *file, int stdout);
19 ff3adf60 2004-04-14 devnull static int gunzip(int ofd, char *ofile, Biobuf *bin);
20 ff3adf60 2004-04-14 devnull static void header(Biobuf *bin, GZHead *h);
21 ff3adf60 2004-04-14 devnull static void trailer(Biobuf *bin, long wlen);
22 ff3adf60 2004-04-14 devnull static void error(char*, ...);
23 ff3adf60 2004-04-14 devnull /* #pragma varargck argpos error 1 */
24 ff3adf60 2004-04-14 devnull
25 ff3adf60 2004-04-14 devnull static Biobuf bin;
26 8425b514 2010-02-23 rsc static u32int crc;
27 8425b514 2010-02-23 rsc static u32int *crctab;
28 ff3adf60 2004-04-14 devnull static int debug;
29 ff3adf60 2004-04-14 devnull static char *delfile;
30 ff3adf60 2004-04-14 devnull static vlong gzok;
31 ff3adf60 2004-04-14 devnull static char *infile;
32 ff3adf60 2004-04-14 devnull static int settimes;
33 ff3adf60 2004-04-14 devnull static int table;
34 ff3adf60 2004-04-14 devnull static int verbose;
35 ff3adf60 2004-04-14 devnull static int wbad;
36 8425b514 2010-02-23 rsc static u32int wlen;
37 ff3adf60 2004-04-14 devnull static jmp_buf zjmp;
38 ff3adf60 2004-04-14 devnull
39 ff3adf60 2004-04-14 devnull void
40 ff3adf60 2004-04-14 devnull usage(void)
41 ff3adf60 2004-04-14 devnull {
42 ff3adf60 2004-04-14 devnull fprint(2, "usage: gunzip [-ctvTD] [file ....]\n");
43 ff3adf60 2004-04-14 devnull exits("usage");
44 ff3adf60 2004-04-14 devnull }
45 ff3adf60 2004-04-14 devnull
46 ff3adf60 2004-04-14 devnull void
47 ff3adf60 2004-04-14 devnull main(int argc, char *argv[])
48 ff3adf60 2004-04-14 devnull {
49 ff3adf60 2004-04-14 devnull int i, ok, stdout;
50 ff3adf60 2004-04-14 devnull
51 ff3adf60 2004-04-14 devnull stdout = 0;
52 ff3adf60 2004-04-14 devnull ARGBEGIN{
53 ff3adf60 2004-04-14 devnull case 'D':
54 ff3adf60 2004-04-14 devnull debug++;
55 ff3adf60 2004-04-14 devnull break;
56 ff3adf60 2004-04-14 devnull case 'c':
57 ff3adf60 2004-04-14 devnull stdout++;
58 ff3adf60 2004-04-14 devnull break;
59 ff3adf60 2004-04-14 devnull case 't':
60 ff3adf60 2004-04-14 devnull table++;
61 ff3adf60 2004-04-14 devnull break;
62 ff3adf60 2004-04-14 devnull case 'T':
63 ff3adf60 2004-04-14 devnull settimes++;
64 ff3adf60 2004-04-14 devnull break;
65 ff3adf60 2004-04-14 devnull case 'v':
66 ff3adf60 2004-04-14 devnull verbose++;
67 ff3adf60 2004-04-14 devnull break;
68 ff3adf60 2004-04-14 devnull default:
69 ff3adf60 2004-04-14 devnull usage();
70 ff3adf60 2004-04-14 devnull break;
71 ff3adf60 2004-04-14 devnull }ARGEND
72 ff3adf60 2004-04-14 devnull
73 ff3adf60 2004-04-14 devnull crctab = mkcrctab(GZCRCPOLY);
74 ff3adf60 2004-04-14 devnull ok = inflateinit();
75 ff3adf60 2004-04-14 devnull if(ok != FlateOk)
76 ff3adf60 2004-04-14 devnull sysfatal("inflateinit failed: %s\n", flateerr(ok));
77 ff3adf60 2004-04-14 devnull
78 ff3adf60 2004-04-14 devnull if(argc == 0){
79 ff3adf60 2004-04-14 devnull Binit(&bin, 0, OREAD);
80 ff3adf60 2004-04-14 devnull settimes = 0;
81 ff3adf60 2004-04-14 devnull infile = "<stdin>";
82 ff3adf60 2004-04-14 devnull ok = gunzip(1, "<stdout>", &bin);
83 ff3adf60 2004-04-14 devnull }else{
84 ff3adf60 2004-04-14 devnull ok = 1;
85 ff3adf60 2004-04-14 devnull if(stdout)
86 ff3adf60 2004-04-14 devnull settimes = 0;
87 ff3adf60 2004-04-14 devnull for(i = 0; i < argc; i++)
88 ff3adf60 2004-04-14 devnull ok &= gunzipf(argv[i], stdout);
89 ff3adf60 2004-04-14 devnull }
90 ff3adf60 2004-04-14 devnull
91 ff3adf60 2004-04-14 devnull exits(ok ? nil: "errors");
92 ff3adf60 2004-04-14 devnull }
93 ff3adf60 2004-04-14 devnull
94 ff3adf60 2004-04-14 devnull static int
95 ff3adf60 2004-04-14 devnull gunzipf(char *file, int stdout)
96 ff3adf60 2004-04-14 devnull {
97 ff3adf60 2004-04-14 devnull char ofile[256], *s;
98 ff3adf60 2004-04-14 devnull int ofd, ifd, ok;
99 ff3adf60 2004-04-14 devnull
100 ff3adf60 2004-04-14 devnull infile = file;
101 ff3adf60 2004-04-14 devnull ifd = open(file, OREAD);
102 ff3adf60 2004-04-14 devnull if(ifd < 0){
103 ff3adf60 2004-04-14 devnull fprint(2, "gunzip: can't open %s: %r\n", file);
104 ff3adf60 2004-04-14 devnull return 0;
105 ff3adf60 2004-04-14 devnull }
106 ff3adf60 2004-04-14 devnull
107 ff3adf60 2004-04-14 devnull Binit(&bin, ifd, OREAD);
108 ff3adf60 2004-04-14 devnull if(Bgetc(&bin) != GZMAGIC1 || Bgetc(&bin) != GZMAGIC2 || Bgetc(&bin) != GZDEFLATE){
109 ff3adf60 2004-04-14 devnull fprint(2, "gunzip: %s is not a gzip deflate file\n", file);
110 ff3adf60 2004-04-14 devnull Bterm(&bin);
111 ff3adf60 2004-04-14 devnull close(ifd);
112 ff3adf60 2004-04-14 devnull return 0;
113 ff3adf60 2004-04-14 devnull }
114 ff3adf60 2004-04-14 devnull Bungetc(&bin);
115 ff3adf60 2004-04-14 devnull Bungetc(&bin);
116 ff3adf60 2004-04-14 devnull Bungetc(&bin);
117 ff3adf60 2004-04-14 devnull
118 ff3adf60 2004-04-14 devnull if(table)
119 ff3adf60 2004-04-14 devnull ofd = -1;
120 ff3adf60 2004-04-14 devnull else if(stdout){
121 ff3adf60 2004-04-14 devnull ofd = 1;
122 ff3adf60 2004-04-14 devnull strcpy(ofile, "<stdout>");
123 ff3adf60 2004-04-14 devnull }else{
124 ff3adf60 2004-04-14 devnull s = strrchr(file, '/');
125 ff3adf60 2004-04-14 devnull if(s != nil)
126 ff3adf60 2004-04-14 devnull s++;
127 ff3adf60 2004-04-14 devnull else
128 ff3adf60 2004-04-14 devnull s = file;
129 ff3adf60 2004-04-14 devnull strecpy(ofile, ofile+sizeof ofile, s);
130 ff3adf60 2004-04-14 devnull s = strrchr(ofile, '.');
131 ff3adf60 2004-04-14 devnull if(s != nil && s != ofile && strcmp(s, ".gz") == 0)
132 ff3adf60 2004-04-14 devnull *s = '\0';
133 ff3adf60 2004-04-14 devnull else if(s != nil && strcmp(s, ".tgz") == 0)
134 ff3adf60 2004-04-14 devnull strcpy(s, ".tar");
135 ff3adf60 2004-04-14 devnull else if(strcmp(file, ofile) == 0){
136 ff3adf60 2004-04-14 devnull fprint(2, "gunzip: can't overwrite %s\n", file);
137 ff3adf60 2004-04-14 devnull Bterm(&bin);
138 ff3adf60 2004-04-14 devnull close(ifd);
139 ff3adf60 2004-04-14 devnull return 0;
140 ff3adf60 2004-04-14 devnull }
141 ff3adf60 2004-04-14 devnull
142 ff3adf60 2004-04-14 devnull ofd = create(ofile, OWRITE, 0666);
143 ff3adf60 2004-04-14 devnull if(ofd < 0){
144 ff3adf60 2004-04-14 devnull fprint(2, "gunzip: can't create %s: %r\n", ofile);
145 ff3adf60 2004-04-14 devnull Bterm(&bin);
146 ff3adf60 2004-04-14 devnull close(ifd);
147 ff3adf60 2004-04-14 devnull return 0;
148 ff3adf60 2004-04-14 devnull }
149 ff3adf60 2004-04-14 devnull delfile = ofile;
150 ff3adf60 2004-04-14 devnull }
151 ff3adf60 2004-04-14 devnull
152 ff3adf60 2004-04-14 devnull wbad = 0;
153 ff3adf60 2004-04-14 devnull ok = gunzip(ofd, ofile, &bin);
154 ff3adf60 2004-04-14 devnull Bterm(&bin);
155 ff3adf60 2004-04-14 devnull close(ifd);
156 ff3adf60 2004-04-14 devnull if(wbad){
157 ff3adf60 2004-04-14 devnull fprint(2, "gunzip: can't write %s: %r\n", ofile);
158 ff3adf60 2004-04-14 devnull if(delfile)
159 ff3adf60 2004-04-14 devnull remove(delfile);
160 ff3adf60 2004-04-14 devnull }
161 ff3adf60 2004-04-14 devnull delfile = nil;
162 ff3adf60 2004-04-14 devnull if(!stdout && ofd >= 0)
163 ff3adf60 2004-04-14 devnull close(ofd);
164 ff3adf60 2004-04-14 devnull return ok;
165 ff3adf60 2004-04-14 devnull }
166 ff3adf60 2004-04-14 devnull
167 ff3adf60 2004-04-14 devnull static int
168 ff3adf60 2004-04-14 devnull gunzip(int ofd, char *ofile, Biobuf *bin)
169 ff3adf60 2004-04-14 devnull {
170 ff3adf60 2004-04-14 devnull Dir *d;
171 ff3adf60 2004-04-14 devnull GZHead h;
172 ff3adf60 2004-04-14 devnull int err;
173 ff3adf60 2004-04-14 devnull
174 ff3adf60 2004-04-14 devnull h.file = nil;
175 ff3adf60 2004-04-14 devnull gzok = 0;
176 ff3adf60 2004-04-14 devnull for(;;){
177 ff3adf60 2004-04-14 devnull if(Bgetc(bin) < 0)
178 ff3adf60 2004-04-14 devnull return 1;
179 ff3adf60 2004-04-14 devnull Bungetc(bin);
180 ff3adf60 2004-04-14 devnull
181 ff3adf60 2004-04-14 devnull if(setjmp(zjmp))
182 ff3adf60 2004-04-14 devnull return 0;
183 ff3adf60 2004-04-14 devnull header(bin, &h);
184 ff3adf60 2004-04-14 devnull gzok = 0;
185 ff3adf60 2004-04-14 devnull
186 ff3adf60 2004-04-14 devnull wlen = 0;
187 ff3adf60 2004-04-14 devnull crc = 0;
188 ff3adf60 2004-04-14 devnull
189 ff3adf60 2004-04-14 devnull if(!table && verbose)
190 ff3adf60 2004-04-14 devnull fprint(2, "extracting %s to %s\n", h.file, ofile);
191 ff3adf60 2004-04-14 devnull
192 3ca675a5 2006-04-20 devnull err = inflate((void*)(uintptr)ofd, crcwrite, bin, (int(*)(void*))Bgetc);
193 ff3adf60 2004-04-14 devnull if(err != FlateOk)
194 ff3adf60 2004-04-14 devnull error("inflate failed: %s", flateerr(err));
195 ff3adf60 2004-04-14 devnull
196 ff3adf60 2004-04-14 devnull trailer(bin, wlen);
197 ff3adf60 2004-04-14 devnull
198 ff3adf60 2004-04-14 devnull if(table){
199 ff3adf60 2004-04-14 devnull if(verbose)
200 ff3adf60 2004-04-14 devnull print("%-32s %10ld %s", h.file, wlen, ctime(h.mtime));
201 ff3adf60 2004-04-14 devnull else
202 ff3adf60 2004-04-14 devnull print("%s\n", h.file);
203 ff3adf60 2004-04-14 devnull }else if(settimes && h.mtime && (d=dirfstat(ofd)) != nil){
204 ff3adf60 2004-04-14 devnull d->mtime = h.mtime;
205 ff3adf60 2004-04-14 devnull dirfwstat(ofd, d);
206 ff3adf60 2004-04-14 devnull free(d);
207 ff3adf60 2004-04-14 devnull }
208 ff3adf60 2004-04-14 devnull
209 ff3adf60 2004-04-14 devnull free(h.file);
210 ff3adf60 2004-04-14 devnull h.file = nil;
211 ff3adf60 2004-04-14 devnull gzok = Boffset(bin);
212 ff3adf60 2004-04-14 devnull }
213 d7925b13 2005-01-14 devnull /* return 0; */
214 ff3adf60 2004-04-14 devnull }
215 ff3adf60 2004-04-14 devnull
216 ff3adf60 2004-04-14 devnull static void
217 ff3adf60 2004-04-14 devnull header(Biobuf *bin, GZHead *h)
218 ff3adf60 2004-04-14 devnull {
219 ff3adf60 2004-04-14 devnull char *s;
220 ff3adf60 2004-04-14 devnull int i, c, flag, ns, nsa;
221 ff3adf60 2004-04-14 devnull
222 ff3adf60 2004-04-14 devnull if(get1(bin) != GZMAGIC1 || get1(bin) != GZMAGIC2)
223 ff3adf60 2004-04-14 devnull error("bad gzip file magic");
224 ff3adf60 2004-04-14 devnull if(get1(bin) != GZDEFLATE)
225 ff3adf60 2004-04-14 devnull error("unknown compression type");
226 ff3adf60 2004-04-14 devnull
227 ff3adf60 2004-04-14 devnull flag = get1(bin);
228 ff3adf60 2004-04-14 devnull if(flag & ~(GZFTEXT|GZFEXTRA|GZFNAME|GZFCOMMENT|GZFHCRC))
229 ff3adf60 2004-04-14 devnull fprint(2, "gunzip: reserved flags set, data may not be decompressed correctly\n");
230 ff3adf60 2004-04-14 devnull
231 ff3adf60 2004-04-14 devnull /* mod time */
232 ff3adf60 2004-04-14 devnull h->mtime = get4(bin);
233 ff3adf60 2004-04-14 devnull
234 ff3adf60 2004-04-14 devnull /* extra flags */
235 ff3adf60 2004-04-14 devnull get1(bin);
236 ff3adf60 2004-04-14 devnull
237 ff3adf60 2004-04-14 devnull /* OS type */
238 ff3adf60 2004-04-14 devnull get1(bin);
239 ff3adf60 2004-04-14 devnull
240 ff3adf60 2004-04-14 devnull if(flag & GZFEXTRA)
241 ff3adf60 2004-04-14 devnull for(i=get1(bin); i>0; i--)
242 ff3adf60 2004-04-14 devnull get1(bin);
243 ff3adf60 2004-04-14 devnull
244 ff3adf60 2004-04-14 devnull /* name */
245 ff3adf60 2004-04-14 devnull if(flag & GZFNAME){
246 ff3adf60 2004-04-14 devnull nsa = 32;
247 ff3adf60 2004-04-14 devnull ns = 0;
248 ff3adf60 2004-04-14 devnull s = malloc(nsa);
249 ff3adf60 2004-04-14 devnull if(s == nil)
250 ff3adf60 2004-04-14 devnull error("out of memory");
251 ff3adf60 2004-04-14 devnull while((c = get1(bin)) != 0){
252 ff3adf60 2004-04-14 devnull s[ns++] = c;
253 ff3adf60 2004-04-14 devnull if(ns >= nsa){
254 ff3adf60 2004-04-14 devnull nsa += 32;
255 ff3adf60 2004-04-14 devnull s = realloc(s, nsa);
256 ff3adf60 2004-04-14 devnull if(s == nil)
257 ff3adf60 2004-04-14 devnull error("out of memory");
258 ff3adf60 2004-04-14 devnull }
259 ff3adf60 2004-04-14 devnull }
260 ff3adf60 2004-04-14 devnull s[ns] = '\0';
261 ff3adf60 2004-04-14 devnull h->file = s;
262 ff3adf60 2004-04-14 devnull }else
263 ff3adf60 2004-04-14 devnull h->file = strdup("<unnamed file>");
264 ff3adf60 2004-04-14 devnull
265 ff3adf60 2004-04-14 devnull /* comment */
266 ff3adf60 2004-04-14 devnull if(flag & GZFCOMMENT)
267 ff3adf60 2004-04-14 devnull while(get1(bin) != 0)
268 ff3adf60 2004-04-14 devnull ;
269 ff3adf60 2004-04-14 devnull
270 ff3adf60 2004-04-14 devnull /* crc16 */
271 ff3adf60 2004-04-14 devnull if(flag & GZFHCRC){
272 ff3adf60 2004-04-14 devnull get1(bin);
273 ff3adf60 2004-04-14 devnull get1(bin);
274 ff3adf60 2004-04-14 devnull }
275 ff3adf60 2004-04-14 devnull }
276 ff3adf60 2004-04-14 devnull
277 ff3adf60 2004-04-14 devnull static void
278 ff3adf60 2004-04-14 devnull trailer(Biobuf *bin, long wlen)
279 ff3adf60 2004-04-14 devnull {
280 8425b514 2010-02-23 rsc u32int tcrc;
281 ff3adf60 2004-04-14 devnull long len;
282 ff3adf60 2004-04-14 devnull
283 ff3adf60 2004-04-14 devnull tcrc = get4(bin);
284 ff3adf60 2004-04-14 devnull if(tcrc != crc)
285 ff3adf60 2004-04-14 devnull error("crc mismatch");
286 ff3adf60 2004-04-14 devnull
287 ff3adf60 2004-04-14 devnull len = get4(bin);
288 ff3adf60 2004-04-14 devnull
289 ff3adf60 2004-04-14 devnull if(len != wlen)
290 ff3adf60 2004-04-14 devnull error("bad output length: expected %lud got %lud", wlen, len);
291 ff3adf60 2004-04-14 devnull }
292 ff3adf60 2004-04-14 devnull
293 8425b514 2010-02-23 rsc static u32int
294 ff3adf60 2004-04-14 devnull get4(Biobuf *b)
295 ff3adf60 2004-04-14 devnull {
296 8425b514 2010-02-23 rsc u32int v;
297 ff3adf60 2004-04-14 devnull int i, c;
298 ff3adf60 2004-04-14 devnull
299 ff3adf60 2004-04-14 devnull v = 0;
300 ff3adf60 2004-04-14 devnull for(i = 0; i < 4; i++){
301 ff3adf60 2004-04-14 devnull c = Bgetc(b);
302 ff3adf60 2004-04-14 devnull if(c < 0)
303 ff3adf60 2004-04-14 devnull error("unexpected eof reading file information");
304 ff3adf60 2004-04-14 devnull v |= c << (i * 8);
305 ff3adf60 2004-04-14 devnull }
306 ff3adf60 2004-04-14 devnull return v;
307 ff3adf60 2004-04-14 devnull }
308 ff3adf60 2004-04-14 devnull
309 ff3adf60 2004-04-14 devnull static int
310 ff3adf60 2004-04-14 devnull get1(Biobuf *b)
311 ff3adf60 2004-04-14 devnull {
312 ff3adf60 2004-04-14 devnull int c;
313 ff3adf60 2004-04-14 devnull
314 ff3adf60 2004-04-14 devnull c = Bgetc(b);
315 ff3adf60 2004-04-14 devnull if(c < 0)
316 ff3adf60 2004-04-14 devnull error("unexpected eof reading file information");
317 ff3adf60 2004-04-14 devnull return c;
318 ff3adf60 2004-04-14 devnull }
319 ff3adf60 2004-04-14 devnull
320 ff3adf60 2004-04-14 devnull static int
321 ff3adf60 2004-04-14 devnull crcwrite(void *out, void *buf, int n)
322 ff3adf60 2004-04-14 devnull {
323 ff3adf60 2004-04-14 devnull int fd, nw;
324 ff3adf60 2004-04-14 devnull
325 ff3adf60 2004-04-14 devnull wlen += n;
326 ff3adf60 2004-04-14 devnull crc = blockcrc(crctab, crc, buf, n);
327 3ca675a5 2006-04-20 devnull fd = (int)(uintptr)out;
328 ff3adf60 2004-04-14 devnull if(fd < 0)
329 ff3adf60 2004-04-14 devnull return n;
330 ff3adf60 2004-04-14 devnull nw = write(fd, buf, n);
331 ff3adf60 2004-04-14 devnull if(nw != n)
332 ff3adf60 2004-04-14 devnull wbad = 1;
333 ff3adf60 2004-04-14 devnull return nw;
334 ff3adf60 2004-04-14 devnull }
335 ff3adf60 2004-04-14 devnull
336 ff3adf60 2004-04-14 devnull static void
337 ff3adf60 2004-04-14 devnull error(char *fmt, ...)
338 ff3adf60 2004-04-14 devnull {
339 ff3adf60 2004-04-14 devnull va_list arg;
340 ff3adf60 2004-04-14 devnull
341 ff3adf60 2004-04-14 devnull if(gzok)
342 ff3adf60 2004-04-14 devnull fprint(2, "gunzip: %s: corrupted data after byte %lld ignored\n", infile, gzok);
343 ff3adf60 2004-04-14 devnull else{
344 ff3adf60 2004-04-14 devnull fprint(2, "gunzip: ");
345 ff3adf60 2004-04-14 devnull if(infile)
346 ff3adf60 2004-04-14 devnull fprint(2, "%s: ", infile);
347 ff3adf60 2004-04-14 devnull va_start(arg, fmt);
348 ff3adf60 2004-04-14 devnull vfprint(2, fmt, arg);
349 ff3adf60 2004-04-14 devnull va_end(arg);
350 ff3adf60 2004-04-14 devnull fprint(2, "\n");
351 ff3adf60 2004-04-14 devnull
352 ff3adf60 2004-04-14 devnull if(delfile != nil){
353 ff3adf60 2004-04-14 devnull fprint(2, "gunzip: removing output file %s\n", delfile);
354 ff3adf60 2004-04-14 devnull remove(delfile);
355 ff3adf60 2004-04-14 devnull delfile = nil;
356 ff3adf60 2004-04-14 devnull }
357 ff3adf60 2004-04-14 devnull }
358 ff3adf60 2004-04-14 devnull
359 ff3adf60 2004-04-14 devnull longjmp(zjmp, 1);
360 ff3adf60 2004-04-14 devnull }