blob: 9d81031d704795698ea4f66ae20306cfa96f2064 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Erik Andersen61677fe2000-04-13 01:18:56 +00002/*
3 * Gzip implementation for busybox
4 *
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +00005 * Based on GNU gzip v1.2.4 Copyright (C) 1992-1993 Jean-loup Gailly.
Erik Andersen61677fe2000-04-13 01:18:56 +00006 *
7 * Originally adjusted for busybox by Sven Rudolph <sr1@inf.tu-dresden.de>
8 * based on gzip sources
9 *
10 * Adjusted further by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
11 * to support files as well as stdin/stdout, and to generally behave itself wrt
12 * command line handling.
13 *
Glenn L McGrath58e42d52001-03-28 05:38:24 +000014 * General cleanup to better adhere to the style guide and make use of standard
15 * busybox functions by Glenn McGrath <bug1@optushome.com.au>
16 *
Erik Andersen61677fe2000-04-13 01:18:56 +000017 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 *
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +000031 *
32 * gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
Eric Andersenb052b471999-11-18 00:21:59 +000033 * Copyright (C) 1992-1993 Jean-loup Gailly
34 * The unzip code was written and put in the public domain by Mark Adler.
35 * Portions of the lzw code are derived from the public domain 'compress'
36 * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
37 * Ken Turkowski, Dave Mack and Peter Jannesen.
38 *
39 * See the license_msg below and the file COPYING for the software license.
40 * See the file algorithm.doc for the compression algorithms and file formats.
41 */
42
43#if 0
Erik Andersene49d5ec2000-02-08 19:58:47 +000044static char *license_msg[] = {
45 " Copyright (C) 1992-1993 Jean-loup Gailly",
46 " This program is free software; you can redistribute it and/or modify",
47 " it under the terms of the GNU General Public License as published by",
48 " the Free Software Foundation; either version 2, or (at your option)",
49 " any later version.",
50 "",
51 " This program is distributed in the hope that it will be useful,",
52 " but WITHOUT ANY WARRANTY; without even the implied warranty of",
53 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
54 " GNU General Public License for more details.",
55 "",
56 " You should have received a copy of the GNU General Public License",
57 " along with this program; if not, write to the Free Software",
58 " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.",
59 0
60};
Eric Andersenb052b471999-11-18 00:21:59 +000061#endif
62
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +000063#include <getopt.h>
Eric Andersenb052b471999-11-18 00:21:59 +000064#include <ctype.h>
65#include <sys/types.h>
Glenn L McGrath58e42d52001-03-28 05:38:24 +000066#include <sys/wait.h>
Eric Andersenb052b471999-11-18 00:21:59 +000067#include <signal.h>
Glenn L McGrath58e42d52001-03-28 05:38:24 +000068//#include <errno.h>
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +000069#include <stdio.h>
70#include <string.h>
71#include <memory.h>
72#include <unistd.h>
73#include <fcntl.h>
74#include <stdlib.h>
75#include <time.h>
76#include <dirent.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000077#include "busybox.h"
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +000078#define BB_DECLARE_EXTERN
79#define bb_need_memory_exhausted
80#define bb_need_name_too_long
81#include "messages.c"
Eric Andersenb052b471999-11-18 00:21:59 +000082
Glenn L McGrath58e42d52001-03-28 05:38:24 +000083FILE *in_file, *out_file;
84
85static unsigned long *crc_table;
86static unsigned long crc = 0xffffffffL; /* shift register contents */
Eric Andersenb052b471999-11-18 00:21:59 +000087
Eric Andersenb052b471999-11-18 00:21:59 +000088/* Return codes from gzip */
Mark Whitley59ab0252001-01-23 22:30:04 +000089static const int ERROR = 1;
Eric Andersenb052b471999-11-18 00:21:59 +000090
Glenn L McGrath58e42d52001-03-28 05:38:24 +000091/*
92 * window size--must be a power of two, and
93 * at least 32K for zip's deflate method
94 */
95static const int WSIZE = 0x8000;
Eric Andersenb052b471999-11-18 00:21:59 +000096
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +000097/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
Mark Whitley59ab0252001-01-23 22:30:04 +000098static const int BMAX = 16; /* maximum bit length of any code (16 for explode) */
99static const int N_MAX = 288; /* maximum number of codes in any set */
Eric Andersenb052b471999-11-18 00:21:59 +0000100
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000101static unsigned char *window;
Eric Andersenb052b471999-11-18 00:21:59 +0000102
Eric Andersen63a86222000-11-07 06:52:13 +0000103static long bytes_out; /* number of output bytes */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000104static unsigned long outcnt; /* bytes in output buffer */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000105
106unsigned hufts; /* track memory usage */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000107unsigned long bb; /* bit buffer */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000108unsigned bk; /* bits in bit buffer */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000109
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000110typedef struct huft_s {
111 unsigned char e; /* number of extra bits or operation */
112 unsigned char b; /* number of bits in this code or subcode */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000113 union {
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000114 unsigned short n; /* literal, length base, or distance base */
115 struct huft_s *t; /* pointer to next level of table */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000116 } v;
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000117} huft_t;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000118
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000119unsigned short mask_bits[] = {
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000120 0x0000,
121 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
122 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
123};
124
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000125//static int error_number = 0;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000126/* ========================================================================
127 * Signal and error handler.
128 */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000129static void abort_gzip()
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000130{
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000131 error_msg("gzip aborted\n");
132// exit(ERROR);
133 return;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000134}
135
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000136static void make_crc_table()
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000137{
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000138 unsigned long table_entry; /* crc shift register */
139 unsigned long poly = 0; /* polynomial exclusive-or pattern */
140 int i; /* counter for all possible eight bit values */
141 int k; /* byte being shifted into crc apparatus */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000142
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000143 /* terms of polynomial defining this crc (except x^32): */
144 static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000145
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000146 crc_table = (unsigned long *) malloc(256 * sizeof(unsigned long));
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000147
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000148 /* Make exclusive-or pattern from polynomial (0xedb88320) */
149 for (i = 0; i < sizeof(p)/sizeof(int); i++)
150 poly |= 1L << (31 - p[i]);
151
152 /* Compute and print table of CRC's, five per line */
153 for (i = 0; i < 256; i++) {
154 table_entry = i;
155 /* The idea to initialize the register with the byte instead of
156 * zero was stolen from Haruhiko Okumura's ar002
157 */
158 for (k = 8; k; k--) {
159 table_entry = table_entry & 1 ? (table_entry >> 1) ^ poly : table_entry >> 1;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000160 }
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000161 crc_table[i]=table_entry;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000162 }
163}
164
165/* ===========================================================================
166 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
167 * (Used for the decompressed data only.)
168 */
169void flush_window()
170{
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000171 int n;
172
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000173 if (outcnt == 0)
174 return;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000175
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000176 for (n = 0; n < outcnt; n++) {
177 crc = crc_table[((int) crc ^ (window[n])) & 0xff] ^ (crc >> 8);
178 }
179
180 if (fwrite(window, 1, outcnt, out_file) != outcnt) {
181 error_msg_and_die("Couldnt write");
182 }
183 bytes_out += (unsigned long) outcnt;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000184 outcnt = 0;
185}
186
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000187/*
188 * Free the malloc'ed tables built by huft_build(), which makes a linked
189 * list of the tables it made, with the links in a dummy first entry of
190 * each table.
191 * t: table to free
192 */
193static int huft_free(huft_t *t)
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000194{
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000195 huft_t *p, *q;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000196
197 /* Go through linked list, freeing from the malloced (t[-1]) address. */
198 p = t;
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000199 while (p != (huft_t *) NULL) {
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000200 q = (--p)->v.t;
201 free((char *) p);
202 p = q;
203 }
204 return 0;
205}
206
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000207/* Given a list of code lengths and a maximum table size, make a set of
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000208 * tables to decode that set of codes. Return zero on success, one if
209 * the given code set is incomplete (the tables are still built in this
210 * case), two if the input is invalid (all zero length codes or an
211 * oversubscribed set of lengths), and three if not enough memory.
212 *
213 * b: code lengths in bits (all assumed <= BMAX)
214 * n: number of codes (assumed <= N_MAX)
215 * s: number of simple-valued codes (0..s-1)
216 * d: list of base values for non-simple codes
217 * e: list of extra bits for non-simple codes
218 * t: result: starting table
219 * m: maximum lookup bits, returns actual
220 */
221static int huft_build(unsigned int *b, const unsigned int n, const unsigned int s,
222 const unsigned short *d, const unsigned short *e, huft_t **t, int *m)
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000223{
224 unsigned a; /* counter for codes of length k */
225 unsigned c[BMAX + 1]; /* bit length count table */
226 unsigned f; /* i repeats in table every f entries */
227 int g; /* maximum code length */
228 int h; /* table level */
229 register unsigned i; /* counter, current code */
230 register unsigned j; /* counter */
231 register int k; /* number of bits in current code */
232 int l; /* bits per table (returned in m) */
233 register unsigned *p; /* pointer into c[], b[], or v[] */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000234 register huft_t *q; /* points to current table */
235 huft_t r; /* table entry for structure assignment */
236 huft_t *u[BMAX]; /* table stack */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000237 unsigned v[N_MAX]; /* values in order of bit length */
238 register int w; /* bits before this table == (l * h) */
239 unsigned x[BMAX + 1]; /* bit offsets, then code stack */
240 unsigned *xp; /* pointer into x */
241 int y; /* number of dummy codes added */
242 unsigned z; /* number of entries in current table */
243
244 /* Generate counts for each bit length */
245 memset ((void *)(c), 0, sizeof(c));
246 p = b;
247 i = n;
248 do {
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000249 c[*p]++; /* assume all entries <= BMAX */
250 p++; /* Can't combine with above line (Solaris bug) */
251 } while (--i);
252 if (c[0] == n) { /* null input--all zero length codes */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000253 *t = (huft_t *) NULL;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000254 *m = 0;
255 return 0;
256 }
257
258 /* Find minimum and maximum length, bound *m by those */
259 l = *m;
260 for (j = 1; j <= BMAX; j++)
261 if (c[j])
262 break;
263 k = j; /* minimum code length */
264 if ((unsigned) l < j)
265 l = j;
266 for (i = BMAX; i; i--)
267 if (c[i])
268 break;
269 g = i; /* maximum code length */
270 if ((unsigned) l > i)
271 l = i;
272 *m = l;
273
274 /* Adjust last length count to fill out codes, if needed */
275 for (y = 1 << j; j < i; j++, y <<= 1)
276 if ((y -= c[j]) < 0)
277 return 2; /* bad input: more codes than bits */
278 if ((y -= c[i]) < 0)
279 return 2;
280 c[i] += y;
281
282 /* Generate starting offsets into the value table for each length */
283 x[1] = j = 0;
284 p = c + 1;
285 xp = x + 2;
286 while (--i) { /* note that i == g from above */
287 *xp++ = (j += *p++);
288 }
289
290 /* Make a table of values in order of bit lengths */
291 p = b;
292 i = 0;
293 do {
294 if ((j = *p++) != 0)
295 v[x[j]++] = i;
296 } while (++i < n);
297
298 /* Generate the Huffman codes and for each, make the table entries */
299 x[0] = i = 0; /* first Huffman code is zero */
300 p = v; /* grab values in bit order */
301 h = -1; /* no tables yet--level -1 */
302 w = -l; /* bits decoded == (l * h) */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000303 u[0] = (huft_t *) NULL; /* just to keep compilers happy */
304 q = (huft_t *) NULL; /* ditto */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000305 z = 0; /* ditto */
306
307 /* go through the bit lengths (k already is bits in shortest code) */
308 for (; k <= g; k++) {
309 a = c[k];
310 while (a--) {
311 /* here i is the Huffman code of length k bits for value *p */
312 /* make tables up to required level */
313 while (k > w + l) {
314 h++;
315 w += l; /* previous table always l bits */
316
317 /* compute minimum size table less than or equal to l bits */
318 z = (z = g - w) > (unsigned) l ? l : z; /* upper limit on table size */
319 if ((f = 1 << (j = k - w)) > a + 1) { /* try a k-w bit table *//* too few codes for k-w bit table */
320 f -= a + 1; /* deduct codes from patterns left */
321 xp = c + k;
322 while (++j < z) { /* try smaller tables up to z bits */
323 if ((f <<= 1) <= *++xp)
324 break; /* enough codes to use up j bits */
325 f -= *xp; /* else deduct codes from patterns */
326 }
327 }
328 z = 1 << j; /* table entries for j-bit table */
329
330 /* allocate and link in new table */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000331 if ((q = (huft_t *) xmalloc((z + 1) * sizeof(huft_t))) == NULL) {
332 if (h) {
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000333 huft_free(u[0]);
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000334 }
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000335 return 3; /* not enough memory */
336 }
337 hufts += z + 1; /* track memory usage */
338 *t = q + 1; /* link to list for huft_free() */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000339 *(t = &(q->v.t)) = NULL;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000340 u[h] = ++q; /* table starts after link */
341
342 /* connect to last table, if there is one */
343 if (h) {
344 x[h] = i; /* save pattern for backing up */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000345 r.b = (unsigned char) l; /* bits to dump before this table */
346 r.e = (unsigned char) (16 + j); /* bits in this table */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000347 r.v.t = q; /* pointer to this table */
348 j = i >> (w - l); /* (get around Turbo C bug) */
349 u[h - 1][j] = r; /* connect to last table */
350 }
351 }
352
353 /* set up table entry in r */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000354 r.b = (unsigned char) (k - w);
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000355 if (p >= v + n)
356 r.e = 99; /* out of values--invalid code */
357 else if (*p < s) {
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000358 r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is end-of-block code */
359 r.v.n = (unsigned short) (*p); /* simple code is just the value */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000360 p++; /* one compiler does not like *p++ */
361 } else {
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000362 r.e = (unsigned char) e[*p - s]; /* non-simple--look up in lists */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000363 r.v.n = d[*p++ - s];
364 }
365
366 /* fill code-like entries with r */
367 f = 1 << (k - w);
368 for (j = i >> w; j < z; j += f)
369 q[j] = r;
370
371 /* backwards increment the k-bit code i */
372 for (j = 1 << (k - 1); i & j; j >>= 1)
373 i ^= j;
374 i ^= j;
375
376 /* backup over finished tables */
377 while ((i & ((1 << w) - 1)) != x[h]) {
378 h--; /* don't need to update q */
379 w -= l;
380 }
381 }
382 }
383 /* Return true (1) if we were given an incomplete table */
384 return y != 0 && g != 1;
385}
386
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000387/*
388 * inflate (decompress) the codes in a deflated (compressed) block.
389 * Return an error code or zero if it all goes ok.
390 *
391 * tl, td: literal/length and distance decoder tables
392 * bl, bd: number of bits decoded by tl[] and td[]
393 */
394static int inflate_codes(huft_t *tl, huft_t *td, int bl, int bd)
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000395{
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000396 register unsigned long e; /* table entry flag/number of extra bits */
397 unsigned long n, d; /* length and index for copy */
398 unsigned long w; /* current window position */
399 huft_t *t; /* pointer to table entry */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000400 unsigned ml, md; /* masks for bl and bd bits */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000401 register unsigned long b; /* bit buffer */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000402 register unsigned k; /* number of bits in bit buffer */
403
404 /* make local copies of globals */
405 b = bb; /* initialize bit buffer */
406 k = bk;
407 w = outcnt; /* initialize window position */
408
409 /* inflate the coded data */
410 ml = mask_bits[bl]; /* precompute masks for speed */
411 md = mask_bits[bd];
412 for (;;) { /* do until end of block */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000413 while (k < (unsigned) bl) {
414 b |= ((unsigned long)fgetc(in_file)) << k;
415 k += 8;
416 }
417 if ((e = (t = tl + ((unsigned) b & ml))->e) > 16)
418 do {
419 if (e == 99) {
420 return 1;
421 }
422 b >>= t->b;
423 k -= t->b;
424 e -= 16;
425 while (k < e) {
426 b |= ((unsigned long)fgetc(in_file)) << k;
427 k += 8;
428 }
429 } while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
430 b >>= t->b;
431 k -= t->b;
432 if (e == 16) { /* then it's a literal */
433 window[w++] = (unsigned char) t->v.n;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000434 if (w == WSIZE) {
435// flush_output(w);
436 outcnt=(w),
437 flush_window();
438 w = 0;
439 }
440 } else { /* it's an EOB or a length */
441
442 /* exit if end of block */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000443 if (e == 15) {
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000444 break;
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000445 }
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000446
447 /* get length of block to copy */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000448 while (k < e) {
449 b |= ((unsigned long)fgetc(in_file)) << k;
450 k += 8;
451 }
452 n = t->v.n + ((unsigned) b & mask_bits[e]);
453 b >>= e;
454 k -= e;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000455
456 /* decode distance of block to copy */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000457 while (k < (unsigned) bd) {
458 b |= ((unsigned long)fgetc(in_file)) << k;
459 k += 8;
460 }
461
462 if ((e = (t = td + ((unsigned) b & md))->e) > 16)
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000463 do {
464 if (e == 99)
465 return 1;
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000466 b >>= t->b;
467 k -= t->b;
468 e -= 16;
469 while (k < e) {
470 b |= ((unsigned long)fgetc(in_file)) << k;
471 k += 8;
472 }
473 } while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
474 b >>= t->b;
475 k -= t->b;
476 while (k < e) {
477 b |= ((unsigned long)fgetc(in_file)) << k;
478 k += 8;
479 }
480 d = w - t->v.n - ((unsigned) b & mask_bits[e]);
481 b >>= e;
482 k -= e;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000483
484 /* do the copy */
485 do {
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000486 n -= (e = (e = WSIZE - ((d &= WSIZE - 1) > w ? d : w)) > n ? n : e);
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000487#if !defined(NOMEMCPY) && !defined(DEBUG)
488 if (w - d >= e) { /* (this test assumes unsigned comparison) */
489 memcpy(window + w, window + d, e);
490 w += e;
491 d += e;
492 } else /* do it slow to avoid memcpy() overlap */
493#endif /* !NOMEMCPY */
494 do {
495 window[w++] = window[d++];
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000496 } while (--e);
497 if (w == WSIZE) {
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000498 outcnt=(w),
499 flush_window();
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000500 w = 0;
501 }
502 } while (n);
503 }
504 }
505
506 /* restore the globals from the locals */
507 outcnt = w; /* restore global window pointer */
508 bb = b; /* restore global bit buffer */
509 bk = k;
510
511 /* done */
512 return 0;
513}
514
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000515/*
516 * decompress an inflated block
517 * e: last block flag
518 *
519 * GLOBAL VARIABLES: bb, kk,
520 */
521static int inflate_block(int *e)
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000522{
523 unsigned t; /* block type */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000524 register unsigned long b; /* bit buffer */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000525 register unsigned k; /* number of bits in bit buffer */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000526 static unsigned short cplens[] = { /* Copy lengths for literal codes 257..285 */
527 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
528 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
529 };
530 /* note: see note #13 above about the 258 in this list. */
531 static unsigned short cplext[] = { /* Extra bits for literal codes 257..285 */
532 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
533 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99
534 }; /* 99==invalid */
535 static unsigned short cpdist[] = { /* Copy offsets for distance codes 0..29 */
536 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
537 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
538 8193, 12289, 16385, 24577
539 };
540 static unsigned short cpdext[] = { /* Extra bits for distance codes */
541 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
542 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
543 12, 12, 13, 13
544 };
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000545
546 /* make local bit buffer */
547 b = bb;
548 k = bk;
549
550 /* read in last block bit */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000551 while (k < 1) {
552 b |= ((unsigned long)fgetc(in_file)) << k;
553 k += 8;
554 }
555 *e = (int) b & 1;
556 b >>= 1;
557 k -= 1;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000558
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000559 /* read in block type */
560 while (k < 2) {
561 b |= ((unsigned long)fgetc(in_file)) << k;
562 k += 8;
563 }
564 t = (unsigned) b & 3;
565 b >>= 2;
566 k -= 2;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000567
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000568 /* restore the global bit buffer */
569 bb = b;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000570 bk = k;
571
572 /* inflate that block type */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000573 switch (t) {
574 case 0: /* Inflate stored */
575 {
576 unsigned long n; /* number of bytes in block */
577 unsigned long w; /* current window position */
578 register unsigned long b_stored; /* bit buffer */
579 register unsigned long k_stored; /* number of bits in bit buffer */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000580
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000581 /* make local copies of globals */
582 b_stored = bb; /* initialize bit buffer */
583 k_stored = bk;
584 w = outcnt; /* initialize window position */
585
586 /* go to byte boundary */
587 n = k_stored & 7;
588 b_stored >>= n;
589 k_stored -= n;
590
591 /* get the length and its complement */
592 while (k_stored < 16) {
593 b_stored |= ((unsigned long)fgetc(in_file)) << k_stored;
594 k_stored += 8;
595 }
596 n = ((unsigned) b_stored & 0xffff);
597 b_stored >>= 16;
598 k_stored -= 16;
599 while (k_stored < 16) {
600 b_stored |= ((unsigned long)fgetc(in_file)) << k_stored;
601 k_stored += 8;
602 }
603 if (n != (unsigned) ((~b_stored) & 0xffff)) {
604 return 1; /* error in compressed data */
605 }
606 b_stored >>= 16;
607 k_stored -= 16;
608
609 /* read and output the compressed data */
610 while (n--) {
611 while (k_stored < 8) {
612 b_stored |= ((unsigned long)fgetc(in_file)) << k_stored;
613 k_stored += 8;
614 }
615 window[w++] = (unsigned char) b_stored;
616 if (w == (unsigned long)WSIZE) {
617 outcnt=(w),
618 flush_window();
619 w = 0;
620 }
621 b_stored >>= 8;
622 k_stored -= 8;
623 }
624
625 /* restore the globals from the locals */
626 outcnt = w; /* restore global window pointer */
627 bb = b_stored; /* restore global bit buffer */
628 bk = k_stored;
629 return 0;
630 }
631 case 1: /* Inflate fixed
632 * decompress an inflated type 1 (fixed Huffman codes) block. We should
633 * either replace this with a custom decoder, or at least precompute the
634 * Huffman tables.
635 */
636 {
637 int i; /* temporary variable */
638 huft_t *tl; /* literal/length code table */
639 huft_t *td; /* distance code table */
640 int bl; /* lookup bits for tl */
641 int bd; /* lookup bits for td */
642 unsigned int l[288]; /* length list for huft_build */
643
644 /* set up literal table */
645 for (i = 0; i < 144; i++) {
646 l[i] = 8;
647 }
648 for (; i < 256; i++) {
649 l[i] = 9;
650 }
651 for (; i < 280; i++) {
652 l[i] = 7;
653 }
654 for (; i < 288; i++) { /* make a complete, but wrong code set */
655 l[i] = 8;
656 }
657 bl = 7;
658 if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0) {
659 return i;
660 }
661
662 /* set up distance table */
663 for (i = 0; i < 30; i++) { /* make an incomplete code set */
664 l[i] = 5;
665 }
666 bd = 5;
667 if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1) {
668 huft_free(tl);
669 return i;
670 }
671
672 /* decompress until an end-of-block code */
673 if (inflate_codes(tl, td, bl, bd))
674 return 1;
675
676 /* free the decoding tables, return */
677 huft_free(tl);
678 huft_free(td);
679 return 0;
680 }
681 case 2: /* Inflate dynamic */
682 {
683 /* Tables for deflate from PKZIP's appnote.txt. */
684 static unsigned border[] = { /* Order of the bit length code lengths */
685 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
686 };
687 int dbits = 6; /* bits in base distance lookup table */
688 int lbits = 9; /* bits in base literal/length lookup table */
689
690 int i; /* temporary variables */
691 unsigned j;
692 unsigned l; /* last length */
693 unsigned m; /* mask for bit lengths table */
694 unsigned n; /* number of lengths to get */
695 huft_t *tl; /* literal/length code table */
696 huft_t *td; /* distance code table */
697 int bl; /* lookup bits for tl */
698 int bd; /* lookup bits for td */
699 unsigned nb; /* number of bit length codes */
700 unsigned nl; /* number of literal/length codes */
701 unsigned nd; /* number of distance codes */
702
703 unsigned ll[286 + 30]; /* literal/length and distance code lengths */
704 register unsigned long b_dynamic; /* bit buffer */
705 register unsigned k_dynamic; /* number of bits in bit buffer */
706
707 /* make local bit buffer */
708 b_dynamic = bb;
709 k_dynamic = bk;
710
711 /* read in table lengths */
712 while (k_dynamic < 5) {
713 b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic;
714 k_dynamic += 8;
715 }
716 nl = 257 + ((unsigned) b_dynamic & 0x1f); /* number of literal/length codes */
717 b_dynamic >>= 5;
718 k_dynamic -= 5;
719 while (k_dynamic < 5) {
720 b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic;
721 k_dynamic += 8;
722 }
723 nd = 1 + ((unsigned) b_dynamic & 0x1f); /* number of distance codes */
724 b_dynamic >>= 5;
725 k_dynamic -= 5;
726 while (k_dynamic < 4) {
727 b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic;
728 k_dynamic += 8;
729 }
730 nb = 4 + ((unsigned) b_dynamic & 0xf); /* number of bit length codes */
731 b_dynamic >>= 4;
732 k_dynamic -= 4;
733 if (nl > 286 || nd > 30) {
734 return 1; /* bad lengths */
735 }
736
737 /* read in bit-length-code lengths */
738 for (j = 0; j < nb; j++) {
739 while (k_dynamic < 3) {
740 b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic;
741 k_dynamic += 8;
742 }
743 ll[border[j]] = (unsigned) b_dynamic & 7;
744 b_dynamic >>= 3;
745 k_dynamic -= 3;
746 }
747 for (; j < 19; j++) {
748 ll[border[j]] = 0;
749 }
750
751 /* build decoding table for trees--single level, 7 bit lookup */
752 bl = 7;
753 if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) {
754 if (i == 1) {
755 huft_free(tl);
756 }
757 return i; /* incomplete code set */
758 }
759
760 /* read in literal and distance code lengths */
761 n = nl + nd;
762 m = mask_bits[bl];
763 i = l = 0;
764 while ((unsigned) i < n) {
765 while (k_dynamic < (unsigned) bl) {
766 b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic;
767 k_dynamic += 8;
768 }
769 j = (td = tl + ((unsigned) b_dynamic & m))->b;
770 b_dynamic >>= j;
771 k_dynamic -= j;
772 j = td->v.n;
773 if (j < 16) { /* length of code in bits (0..15) */
774 ll[i++] = l = j; /* save last length in l */
775 }
776 else if (j == 16) { /* repeat last length 3 to 6 times */
777 while (k_dynamic < 2) {
778 b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic;
779 k_dynamic += 8;
780 }
781 j = 3 + ((unsigned) b_dynamic & 3);
782 b_dynamic >>= 2;
783 k_dynamic -= 2;
784 if ((unsigned) i + j > n) {
785 return 1;
786 }
787 while (j--) {
788 ll[i++] = l;
789 }
790 } else if (j == 17) { /* 3 to 10 zero length codes */
791 while (k_dynamic < 3) {
792 b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic;
793 k_dynamic += 8;
794 }
795 j = 3 + ((unsigned) b_dynamic & 7);
796 b_dynamic >>= 3;
797 k_dynamic -= 3;
798 if ((unsigned) i + j > n) {
799 return 1;
800 }
801 while (j--) {
802 ll[i++] = 0;
803 }
804 l = 0;
805 } else { /* j == 18: 11 to 138 zero length codes */
806 while (k_dynamic < 7) {
807 b_dynamic |= ((unsigned long)fgetc(in_file)) << k_dynamic;
808 k_dynamic += 8;
809 }
810 j = 11 + ((unsigned) b_dynamic & 0x7f);
811 b_dynamic >>= 7;
812 k_dynamic -= 7;
813 if ((unsigned) i + j > n) {
814 return 1;
815 }
816 while (j--) {
817 ll[i++] = 0;
818 }
819 l = 0;
820 }
821 }
822
823 /* free decoding table for trees */
824 huft_free(tl);
825
826 /* restore the global bit buffer */
827 bb = b_dynamic;
828 bk = k_dynamic;
829
830 /* build the decoding tables for literal/length and distance codes */
831 bl = lbits;
832 if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) {
833 if (i == 1) {
834 error_msg("Incomplete literal tree");
835 huft_free(tl);
836 }
837 return i; /* incomplete code set */
838 }
839 bd = dbits;
840 if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) {
841 if (i == 1) {
842 error_msg("incomplete distance tree");
843 huft_free(td);
844 }
845 huft_free(tl);
846 return i; /* incomplete code set */
847 }
848
849 /* decompress until an end-of-block code */
850 if (inflate_codes(tl, td, bl, bd))
851 return 1;
852
853 /* free the decoding tables, return */
854 huft_free(tl);
855 huft_free(td);
856 return 0;
857 }
858 default:
859 /* bad block type */
860 return 2;
861 }
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000862}
863
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000864/*
865 * decompress an inflated entry
866 *
867 * GLOBAL VARIABLES: outcnt, bk, bb, hufts, inptr
868 */
869static int inflate()
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000870{
871 int e; /* last block flag */
872 int r; /* result code */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000873 unsigned h = 0; /* maximum struct huft's malloc'ed */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000874
875 /* initialize window, bit buffer */
876 outcnt = 0;
877 bk = 0;
878 bb = 0;
879
880 /* decompress until the last block */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000881 do {
882 hufts = 0;
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000883 if ((r = inflate_block(&e)) != 0) {
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000884 return r;
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000885 }
886 if (hufts > h) {
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000887 h = hufts;
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000888 }
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000889 } while (!e);
890
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000891 /* flush out window */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000892 flush_window();
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000893
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000894 /* return success */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000895 return 0;
896}
897
898/* ===========================================================================
899 * Unzip in to out. This routine works on both gzip and pkzip files.
900 *
901 * IN assertions: the buffer inbuf contains already the beginning of
902 * the compressed data, from offsets inptr to insize-1 included.
903 * The magic header has already been checked. The output buffer is cleared.
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000904 * in, out: input and output file descriptors
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000905 */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000906extern int unzip(FILE *l_in_file, FILE *l_out_file)
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000907{
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000908 const int extra_field = 0x04; /* bit 2 set: extra field present */
909 const int orig_name = 0x08; /* bit 3 set: original file name present */
910 const int comment = 0x10; /* bit 4 set: file comment present */
911 unsigned char buf[8]; /* extended local header */
912 unsigned char flags; /* compression flags */
913 char magic[2]; /* magic header */
914 int method;
915 typedef void (*sig_type) (int);
916 int exit_code=0; /* program exit code */
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000917
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000918 in_file = l_in_file;
919 out_file = l_out_file;
Glenn L McGrathc2bf5ca2000-09-29 06:46:59 +0000920
Glenn L McGrath018e9e62001-03-28 07:27:26 +0000921/* if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
Glenn L McGrath00732b52000-12-10 00:51:42 +0000922 (void) signal(SIGINT, (sig_type) abort_gzip);
923 }
924#ifdef SIGTERM
925 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
926 (void) signal(SIGTERM, (sig_type) abort_gzip);
927 }
928#endif
929#ifdef SIGHUP
930 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
931 (void) signal(SIGHUP, (sig_type) abort_gzip);
932 }
933#endif
Glenn L McGrath018e9e62001-03-28 07:27:26 +0000934*/
Glenn L McGrath00732b52000-12-10 00:51:42 +0000935 /* Allocate all global buffers (for DYN_ALLOC option) */
Glenn L McGrath58e42d52001-03-28 05:38:24 +0000936 window = xmalloc((size_t)(((2L*WSIZE)+1L)*sizeof(unsigned char)));
937 outcnt = 0;
938 bytes_out = 0L;
939
940 /* set the buffer size */
941 setvbuf(in_file, NULL, _IOFBF, 0x8000);
942
943 magic[0] = fgetc(in_file);
944 magic[1] = fgetc(in_file);
945
946 /* Magic header for gzip files, 1F 8B = \037\213 */
947 if (memcmp(magic, "\037\213", 2) != 0) {
948 error_msg("Invalid gzip magic");
949 return EXIT_FAILURE;
950 }
951
952 method = (int) fgetc(in_file);
953 if (method != 8) {
954 error_msg("unknown method %d -- get newer version of gzip", method);
955 exit_code = 1;
956 return -1;
957 }
958
959 flags = (unsigned char) fgetc(in_file);
960
961 /* Ignore time stamp(4), extra flags(1), OS type(1) */
962 fseek(in_file, 6, SEEK_CUR);
963
964 if ((flags & extra_field) != 0) {
965 fseek(in_file, (size_t) fgetc(in_file) + ((size_t)fgetc(in_file) << 8), SEEK_CUR);
966 }
967
968 /* Discard original name if any */
969 if ((flags & orig_name) != 0) {
970 while (fgetc(in_file) != 0); /* null */
971 }
972
973 /* Discard file comment if any */
974 if ((flags & comment) != 0) {
975 while (fgetc(in_file) != 0); /* null */
976 }
977
978 if (method < 0) {
979 printf("it failed\n");
980 return(exit_code); /* error message already emitted */
981 }
982
983 make_crc_table();
984
985 /* Decompress */
986 if (method == 8) {
987
988 int res = inflate();
989
990 if (res == 3) {
991 error_msg(memory_exhausted);
992 } else if (res != 0) {
993 error_msg("invalid compressed data--format violated");
994 }
995
996 } else {
997 error_msg("internal error, invalid method");
998 }
999
1000 /* Get the crc and original length
1001 * crc32 (see algorithm.doc)
1002 * uncompressed input size modulo 2^32
1003 */
1004 fread(buf, 1, 8, in_file);
1005
1006 /* Validate decompression - crc */
1007 if (((buf[0] | (buf[1] << 8)) |((buf[2] | (buf[3] << 8)) << 16)) != (crc ^ 0xffffffffL)) {
1008 error_msg("invalid compressed data--crc error");
1009 }
1010 /* Validate decompression - size */
1011 if (((buf[4] | (buf[5] << 8)) |((buf[6] | (buf[7] << 8)) << 16)) != (unsigned long) bytes_out) {
1012 error_msg("invalid compressed data--length error");
1013 }
1014
1015 free(window);
1016 free(crc_table);
1017
1018 return 0;
Glenn L McGrath00732b52000-12-10 00:51:42 +00001019}
1020
Glenn L McGrath018e9e62001-03-28 07:27:26 +00001021extern int gz_open(FILE *compressed_file, int *pid)
Eric Andersenb052b471999-11-18 00:21:59 +00001022{
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001023 int unzip_pipe[2];
Eric Andersenb052b471999-11-18 00:21:59 +00001024
Glenn L McGrath018e9e62001-03-28 07:27:26 +00001025// signal(SIGCHLD, abort_gzip);
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001026 if (pipe(unzip_pipe)!=0) {
1027 error_msg("pipe error");
Glenn L McGrath018e9e62001-03-28 07:27:26 +00001028 return(EXIT_FAILURE);
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001029 }
1030 if ((*pid = fork()) == -1) {
1031 error_msg("fork failured");
Glenn L McGrath018e9e62001-03-28 07:27:26 +00001032 return(EXIT_FAILURE);
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001033 }
1034 if (*pid==0) {
1035 /* child process */
1036 close(unzip_pipe[0]);
1037 unzip(compressed_file, fdopen(unzip_pipe[1], "w"));
Glenn L McGrath018e9e62001-03-28 07:27:26 +00001038 printf("finished unzipping\n");
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001039 fflush(NULL);
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001040 fclose(compressed_file);
1041 close(unzip_pipe[1]);
1042 exit(EXIT_SUCCESS);
1043 }
1044
1045 close(unzip_pipe[1]);
Glenn L McGrath018e9e62001-03-28 07:27:26 +00001046 return(unzip_pipe[0]);
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001047}
Mark Whitley59ab0252001-01-23 22:30:04 +00001048
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001049extern void gz_close(int gunzip_pid)
1050{
1051 if (kill(gunzip_pid, SIGTERM) == -1) {
1052 error_msg_and_die("*** Couldnt kill old gunzip process *** aborting");
Erik Andersen59b9e872000-05-10 05:05:45 +00001053 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00001054
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001055 if (waitpid(gunzip_pid, NULL, 0) == -1) {
1056 printf("Couldnt wait ?");
1057 }
1058 free(window);
1059 free(crc_table);
1060}
1061
1062extern int gunzip_main(int argc, char **argv)
1063{
1064 struct stat stat_buf;
1065
1066 char *if_name = NULL;
1067 char *of_name = NULL;
1068 char *delete_file_name = NULL;
1069
1070 const int gunzip_to_stdout = 1;
1071 const int gunzip_from_stdin = 2;
1072 const int gunzip_force = 4;
1073 const int gunzip_test = 8;
1074
1075 int flags = 0;
1076 int opt = 0;
1077 int delete_old_file = FALSE;
1078
1079#ifdef BB_ZCAT
1080 /* if called as zcat */
1081 if (strcmp(applet_name, "zcat") == 0) {
1082 if (argc != 2) {
1083 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00001084 }
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001085 flags |= gunzip_force;
1086 flags |= gunzip_to_stdout;
1087 } else
1088#endif
1089 {
1090 /* workout flags as regular gunzip */
1091 /* set default flags */
1092 if (argc == 1) {
1093 flags |= (gunzip_from_stdin | gunzip_to_stdout);
1094 }
1095
1096 /* Parse any options */
1097 while ((opt = getopt(argc, argv, "ctfh")) != -1) {
1098 switch (opt) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00001099 case 'c':
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001100 flags |= gunzip_to_stdout;
Erik Andersene49d5ec2000-02-08 19:58:47 +00001101 break;
Eric Andersenea824fb2000-07-21 22:17:39 +00001102 case 'f':
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001103 flags |= gunzip_force;
Eric Andersenea824fb2000-07-21 22:17:39 +00001104 break;
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001105 case 't':
1106 flags |= gunzip_test;
1107 break;
1108 case 'h':
Erik Andersene49d5ec2000-02-08 19:58:47 +00001109 default:
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001110 show_usage(); /* exit's inside usage */
Erik Andersene49d5ec2000-02-08 19:58:47 +00001111 }
1112 }
1113 }
Eric Andersene99674a2000-09-01 00:41:10 +00001114
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001115 /* Set input filename and number */
1116 if (flags & gunzip_from_stdin) {
1117 in_file = stdin;
1118 if ((flags & gunzip_force) == 0) {
1119 error_msg_and_die("data not written to terminal. Use -f to force it.");
1120 }
1121 strcpy(if_name, "stdin");
Eric Andersenb052b471999-11-18 00:21:59 +00001122 } else {
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001123 if_name = strdup(argv[optind]);
1124 /* Open input file */
1125 in_file = xfopen(if_name, "r");
Erik Andersene49d5ec2000-02-08 19:58:47 +00001126
Erik Andersene49d5ec2000-02-08 19:58:47 +00001127 /* Get the time stamp on the input file. */
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001128 if (stat(if_name, &stat_buf) < 0) {
1129 error_msg_and_die("Couldnt stat file %s",if_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00001130 }
Eric Andersenb052b471999-11-18 00:21:59 +00001131 }
1132
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001133 /* Set output filename and number */
1134 if (flags & gunzip_to_stdout) {
1135 out_file = stdout;
1136 /* whats the best way to do this with streams ? */
1137 if (isatty(fileno(out_file)) && ((flags & gunzip_force) == 0)) {
1138 error_msg_and_die("data not written to terminal. Use -f to force it.");
1139 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00001140
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001141 strcpy(of_name, "stdout");
1142 } else if (flags & gunzip_test) {
1143 out_file = xfopen("/dev/null", "w"); /* why does test use filenum 2 ? */
Erik Andersene49d5ec2000-02-08 19:58:47 +00001144 } else {
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001145 char *extension;
1146 int length = strlen(if_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00001147
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001148 delete_old_file = TRUE;
1149 extension = strrchr(if_name, '.');
1150 if (strcmp(extension, ".gz") == 0) {
1151 length -= 3;
1152 } else if (strcmp(extension, ".tgz") == 0) {
1153 length -= 4;
Erik Andersene49d5ec2000-02-08 19:58:47 +00001154 } else {
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001155 error_msg_and_die("Invalid extension");
Erik Andersene49d5ec2000-02-08 19:58:47 +00001156 }
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001157 of_name = (char *) xcalloc(sizeof(char), length + 1);
1158 strncpy(of_name, if_name, length);
Erik Andersene49d5ec2000-02-08 19:58:47 +00001159
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001160 /* Open output file */
1161 out_file = xfopen(of_name, "w");
1162
Erik Andersene49d5ec2000-02-08 19:58:47 +00001163 /* Set permissions on the file */
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001164 chmod(of_name, stat_buf.st_mode);
1165 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00001166
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001167 /* do the decompression, and cleanup */
1168 if (unzip(in_file, out_file) == 0) {
1169 /* Success, remove .gz file */
1170 delete_file_name = if_name;
1171 } else {
1172 /* remove failed attempt */
1173 delete_file_name = of_name;
1174 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00001175
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001176 fclose(out_file);
1177 fclose(in_file);
Erik Andersene49d5ec2000-02-08 19:58:47 +00001178
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001179 if (delete_old_file == TRUE) {
1180 if (unlink(delete_file_name) < 0) {
1181 error_msg_and_die("Couldnt remove %s", delete_file_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00001182 }
Eric Andersenb052b471999-11-18 00:21:59 +00001183 }
Glenn L McGrath58e42d52001-03-28 05:38:24 +00001184
1185 free(of_name);
1186
1187 return(EXIT_SUCCESS);
Eric Andersenb052b471999-11-18 00:21:59 +00001188}