]> git.cworth.org Git - gzip/blob - gzip.c
Imported Upstream version 1.3.2
[gzip] / gzip.c
1 /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
2  * Copyright (C) 1999, 2001 Free Software Foundation, Inc.
3  * Copyright (C) 1992-1993 Jean-loup Gailly
4  * The unzip code was written and put in the public domain by Mark Adler.
5  * Portions of the lzw code are derived from the public domain 'compress'
6  * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
7  * Ken Turkowski, Dave Mack and Peter Jannesen.
8  *
9  * See the license_msg below and the file COPYING for the software license.
10  * See the file algorithm.doc for the compression algorithms and file formats.
11  */
12
13 static char  *license_msg[] = {
14 "Copyright 2001 Free Software Foundation",
15 "Copyright 1992-1993 Jean-loup Gailly",
16 "This program comes with ABSOLUTELY NO WARRANTY.",
17 "You may redistribute copies of this program",
18 "under the terms of the GNU General Public License.",
19 "For more information about these matters, see the file named COPYING.",
20 0};
21
22 /* Compress files with zip algorithm and 'compress' interface.
23  * See usage() and help() functions below for all options.
24  * Outputs:
25  *        file.gz:   compressed file with same mode, owner, and utimes
26  *     or stdout with -c option or if stdin used as input.
27  * If the output file name had to be truncated, the original name is kept
28  * in the compressed file.
29  * On MSDOS, file.tmp -> file.tmz. On VMS, file.tmp -> file.tmp-gz.
30  *
31  * Using gz on MSDOS would create too many file name conflicts. For
32  * example, foo.txt -> foo.tgz (.tgz must be reserved as shorthand for
33  * tar.gz). Similarly, foo.dir and foo.doc would both be mapped to foo.dgz.
34  * I also considered 12345678.txt -> 12345txt.gz but this truncates the name
35  * too heavily. There is no ideal solution given the MSDOS 8+3 limitation. 
36  *
37  * For the meaning of all compilation flags, see comments in Makefile.in.
38  */
39
40 #ifdef RCSID
41 static char rcsid[] = "$Id: gzip.c,v 0.24 1993/06/24 10:52:07 jloup Exp $";
42 #endif
43
44 #include <config.h>
45 #include <ctype.h>
46 #include <sys/types.h>
47 #include <signal.h>
48 #include <sys/stat.h>
49 #include <errno.h>
50
51 #include "tailor.h"
52 #include "gzip.h"
53 #include "lzw.h"
54 #include "revision.h"
55 #include "getopt.h"
56
57                 /* configuration */
58
59 #ifdef HAVE_TIME_H
60 #  include <time.h>
61 #else
62 #  include <sys/time.h>
63 #endif
64
65 #ifdef HAVE_FCNTL_H
66 #  include <fcntl.h>
67 #endif
68
69 #ifdef HAVE_LIMITS_H
70 #  include <limits.h>
71 #endif
72
73 #ifdef HAVE_UNISTD_H
74 #  include <unistd.h>
75 #endif
76
77 #if defined STDC_HEADERS || defined HAVE_STDLIB_H
78 #  include <stdlib.h>
79 #else
80    extern int errno;
81 #endif
82
83 #ifdef HAVE_DIRENT_H
84 #  include <dirent.h>
85 #  define NAMLEN(direct) strlen((direct)->d_name)
86 #  define DIR_OPT "DIRENT"
87 #else
88 #  define dirent direct
89 #  define NAMLEN(direct) ((direct)->d_namlen)
90 #  ifdef HAVE_SYS_NDIR_H
91 #    include <sys/ndir.h>
92 #    define DIR_OPT "SYS_NDIR"
93 #  endif
94 #  ifdef HAVE_SYS_DIR_H
95 #    include <sys/dir.h>
96 #    define DIR_OPT "SYS_DIR"
97 #  endif
98 #  ifdef HAVE_NDIR_H
99 #    include <ndir.h>
100 #    define DIR_OPT "NDIR"
101 #  endif
102 #  ifndef DIR_OPT
103 #    define DIR_OPT "NO_DIR"
104 #  endif
105 #endif
106
107 #ifdef CLOSEDIR_VOID
108 # define CLOSEDIR(d) (closedir(d), 0)
109 #else
110 # define CLOSEDIR(d) closedir(d)
111 #endif
112
113 #ifdef HAVE_UTIME
114 #  ifdef HAVE_UTIME_H
115 #    include <utime.h>
116 #    define TIME_OPT "UTIME"
117 #  else
118 #    ifdef HAVE_SYS_UTIME_H
119 #      include <sys/utime.h>
120 #      define TIME_OPT "SYS_UTIME"
121 #    else
122        struct utimbuf {
123          time_t actime;
124          time_t modtime;
125        };
126 #      define TIME_OPT "STRUCT_UTIMBUF"
127 #    endif
128 #  endif
129 #else
130 #  define TIME_OPT "NO_UTIME"
131 #endif
132
133 #if !defined(S_ISDIR) && defined(S_IFDIR)
134 #  define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
135 #endif
136 #if !defined(S_ISREG) && defined(S_IFREG)
137 #  define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
138 #endif
139
140 typedef RETSIGTYPE (*sig_type) OF((int));
141
142 #ifndef O_BINARY
143 #  define  O_BINARY  0  /* creation mode for open() */
144 #endif
145
146 #ifndef O_CREAT
147    /* Pure BSD system? */
148 #  include <sys/file.h>
149 #  ifndef O_CREAT
150 #    define O_CREAT FCREAT
151 #  endif
152 #  ifndef O_EXCL
153 #    define O_EXCL FEXCL
154 #  endif
155 #endif
156
157 #ifndef S_IRUSR
158 #  define S_IRUSR 0400
159 #endif
160 #ifndef S_IWUSR
161 #  define S_IWUSR 0200
162 #endif
163 #define RW_USER (S_IRUSR | S_IWUSR)  /* creation mode for open() */
164
165 #ifndef MAX_PATH_LEN
166 #  define MAX_PATH_LEN   1024 /* max pathname length */
167 #endif
168
169 #ifndef SEEK_END
170 #  define SEEK_END 2
171 #endif
172
173 #ifndef CHAR_BIT
174 #  define CHAR_BIT 8
175 #endif
176
177 #ifdef off_t
178   off_t lseek OF((int fd, off_t offset, int whence));
179 #endif
180
181 #ifndef OFF_T_MIN
182 #define OFF_T_MIN (~ (off_t) 0 << (sizeof (off_t) * CHAR_BIT - 1))
183 #endif
184
185 #ifndef OFF_T_MAX
186 #define OFF_T_MAX (~ (off_t) 0 - OFF_T_MIN)
187 #endif
188
189 /* Separator for file name parts (see shorten_name()) */
190 #ifdef NO_MULTIPLE_DOTS
191 #  define PART_SEP "-"
192 #else
193 #  define PART_SEP "."
194 #endif
195
196                 /* global buffers */
197
198 DECLARE(uch, inbuf,  INBUFSIZ +INBUF_EXTRA);
199 DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
200 DECLARE(ush, d_buf,  DIST_BUFSIZE);
201 DECLARE(uch, window, 2L*WSIZE);
202 #ifndef MAXSEG_64K
203     DECLARE(ush, tab_prefix, 1L<<BITS);
204 #else
205     DECLARE(ush, tab_prefix0, 1L<<(BITS-1));
206     DECLARE(ush, tab_prefix1, 1L<<(BITS-1));
207 #endif
208
209                 /* local variables */
210
211 int ascii = 0;        /* convert end-of-lines to local OS conventions */
212 int to_stdout = 0;    /* output to stdout (-c) */
213 int decompress = 0;   /* decompress (-d) */
214 int force = 0;        /* don't ask questions, compress links (-f) */
215 int no_name = -1;     /* don't save or restore the original file name */
216 int no_time = -1;     /* don't save or restore the original file time */
217 int recursive = 0;    /* recurse through directories (-r) */
218 int list = 0;         /* list the file contents (-l) */
219 int verbose = 0;      /* be verbose (-v) */
220 int quiet = 0;        /* be very quiet (-q) */
221 int do_lzw = 0;       /* generate output compatible with old compress (-Z) */
222 int test = 0;         /* test .gz file integrity */
223 int foreground;       /* set if program run in foreground */
224 char *progname;       /* program name */
225 int maxbits = BITS;   /* max bits per code for LZW */
226 int method = DEFLATED;/* compression method */
227 int level = 6;        /* compression level */
228 int exit_code = OK;   /* program exit code */
229 int save_orig_name;   /* set if original name must be saved */
230 int last_member;      /* set for .zip and .Z files */
231 int part_nb;          /* number of parts in .gz file */
232 time_t time_stamp;      /* original time stamp (modification time) */
233 off_t ifile_size;      /* input file size, -1 for devices (debug only) */
234 char *env;            /* contents of GZIP env variable */
235 char **args = NULL;   /* argv pointer if GZIP env variable defined */
236 char *z_suffix;       /* default suffix (can be set with --suffix) */
237 int  z_len;           /* strlen(z_suffix) */
238
239 off_t bytes_in;             /* number of input bytes */
240 off_t bytes_out;            /* number of output bytes */
241 off_t total_in;             /* input bytes for all files */
242 off_t total_out;            /* output bytes for all files */
243 char ifname[MAX_PATH_LEN]; /* input file name */
244 char ofname[MAX_PATH_LEN]; /* output file name */
245 int  remove_ofname = 0;    /* remove output file on error */
246 struct stat istat;         /* status for input file */
247 int  ifd;                  /* input file descriptor */
248 int  ofd;                  /* output file descriptor */
249 unsigned insize;           /* valid bytes in inbuf */
250 unsigned inptr;            /* index of next byte to be processed in inbuf */
251 unsigned outcnt;           /* bytes in output buffer */
252
253 struct option longopts[] =
254 {
255  /* { name  has_arg  *flag  val } */
256     {"ascii",      0, 0, 'a'}, /* ascii text mode */
257     {"to-stdout",  0, 0, 'c'}, /* write output on standard output */
258     {"stdout",     0, 0, 'c'}, /* write output on standard output */
259     {"decompress", 0, 0, 'd'}, /* decompress */
260     {"uncompress", 0, 0, 'd'}, /* decompress */
261  /* {"encrypt",    0, 0, 'e'},    encrypt */
262     {"force",      0, 0, 'f'}, /* force overwrite of output file */
263     {"help",       0, 0, 'h'}, /* give help */
264  /* {"pkzip",      0, 0, 'k'},    force output in pkzip format */
265     {"list",       0, 0, 'l'}, /* list .gz file contents */
266     {"license",    0, 0, 'L'}, /* display software license */
267     {"no-name",    0, 0, 'n'}, /* don't save or restore original name & time */
268     {"name",       0, 0, 'N'}, /* save or restore original name & time */
269     {"quiet",      0, 0, 'q'}, /* quiet mode */
270     {"silent",     0, 0, 'q'}, /* quiet mode */
271     {"recursive",  0, 0, 'r'}, /* recurse through directories */
272     {"suffix",     1, 0, 'S'}, /* use given suffix instead of .gz */
273     {"test",       0, 0, 't'}, /* test compressed file integrity */
274     {"no-time",    0, 0, 'T'}, /* don't save or restore the time stamp */
275     {"verbose",    0, 0, 'v'}, /* verbose mode */
276     {"version",    0, 0, 'V'}, /* display version number */
277     {"fast",       0, 0, '1'}, /* compress faster */
278     {"best",       0, 0, '9'}, /* compress better */
279     {"lzw",        0, 0, 'Z'}, /* make output compatible with old compress */
280     {"bits",       1, 0, 'b'}, /* max number of bits per code (implies -Z) */
281     { 0, 0, 0, 0 }
282 };
283
284 /* local functions */
285
286 local void usage        OF((void));
287 local void help         OF((void));
288 local void license      OF((void));
289 local void version      OF((void));
290 local int input_eof     OF((void));
291 local void treat_stdin  OF((void));
292 local void treat_file   OF((char *iname));
293 local int create_outfile OF((void));
294 local int  do_stat      OF((char *name, struct stat *sbuf));
295 local char *get_suffix  OF((char *name));
296 local int  get_istat    OF((char *iname, struct stat *sbuf));
297 local int  make_ofname  OF((void));
298 local int  same_file    OF((struct stat *stat1, struct stat *stat2));
299 local int name_too_long OF((char *name, struct stat *statb));
300 local void shorten_name  OF((char *name));
301 local int  get_method   OF((int in));
302 local void do_list      OF((int ifd, int method));
303 local int  check_ofname OF((void));
304 local void copy_stat    OF((struct stat *ifstat));
305 local void do_exit      OF((int exitcode));
306       int main          OF((int argc, char **argv));
307 int (*work) OF((int infile, int outfile)) = zip; /* function to call */
308
309 #ifndef NO_DIR
310 local void treat_dir    OF((char *dir));
311 #endif
312 #ifdef HAVE_UTIME
313 local void reset_times  OF((char *name, struct stat *statb));
314 #endif
315
316 #define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
317
318 /* ======================================================================== */
319 local void usage()
320 {
321     printf ("usage: %s [-%scdfhlLnN%stvV19] [-S suffix] [file ...]\n",
322             progname,
323 #if O_BINARY
324             "a",
325 #else
326             "",
327 #endif
328 #ifdef NO_DIR
329             ""
330 #else
331             "r"
332 #endif
333             );
334 }
335
336 /* ======================================================================== */
337 local void help()
338 {
339     static char  *help_msg[] = {
340 #if O_BINARY
341  " -a --ascii       ascii text; convert end-of-lines using local conventions",
342 #endif
343  " -c --stdout      write on standard output, keep original files unchanged",
344  " -d --decompress  decompress",
345 /* -e --encrypt     encrypt */
346  " -f --force       force overwrite of output file and compress links",
347  " -h --help        give this help",
348 /* -k --pkzip       force output in pkzip format */
349  " -l --list        list compressed file contents",
350  " -L --license     display software license",
351 #ifdef UNDOCUMENTED
352  " -m --no-time     do not save or restore the original modification time",
353  " -M --time        save or restore the original modification time",
354 #endif
355  " -n --no-name     do not save or restore the original name and time stamp",
356  " -N --name        save or restore the original name and time stamp",
357  " -q --quiet       suppress all warnings",
358 #ifndef NO_DIR
359  " -r --recursive   operate recursively on directories",
360 #endif
361  " -S .suf  --suffix .suf     use suffix .suf on compressed files",
362  " -t --test        test compressed file integrity",
363  " -v --verbose     verbose mode",
364  " -V --version     display version number",
365  " -1 --fast        compress faster",
366  " -9 --best        compress better",
367 #ifdef LZW
368  " -Z --lzw         produce output compatible with old compress",
369  " -b --bits maxbits   max number of bits per code (implies -Z)",
370 #endif
371  " file...          files to (de)compress. If none given, use standard input.",
372  "Report bugs to <bug-gzip@gnu.org>.",
373   0};
374     char **p = help_msg;
375
376     printf ("%s %s\n(%s)\n", progname, VERSION, REVDATE);
377     usage();
378     while (*p) printf ("%s\n", *p++);
379 }
380
381 /* ======================================================================== */
382 local void license()
383 {
384     char **p = license_msg;
385
386     printf ("%s %s\n(%s)\n", progname, VERSION, REVDATE);
387     while (*p) printf ("%s\n", *p++);
388 }
389
390 /* ======================================================================== */
391 local void version()
392 {
393     license ();
394     printf ("Compilation options:\n%s %s ", DIR_OPT, TIME_OPT);
395 #ifdef STDC_HEADERS
396     printf ("STDC_HEADERS ");
397 #endif
398 #ifdef HAVE_UNISTD_H
399     printf ("HAVE_UNISTD_H ");
400 #endif
401 #ifdef HAVE_MEMORY_H
402     printf ("HAVE_MEMORY_H ");
403 #endif
404 #ifdef HAVE_STRING_H
405     printf ("HAVE_STRING_H ");
406 #endif
407 #ifdef HAVE_LSTAT
408     printf ("HAVE_LSTAT ");
409 #endif
410 #ifdef NO_MULTIPLE_DOTS
411     printf ("NO_MULTIPLE_DOTS ");
412 #endif
413 #ifdef HAVE_CHOWN
414     printf ("HAVE_CHOWN ");
415 #endif
416 #ifdef PROTO
417     printf ("PROTO ");
418 #endif
419 #ifdef ASMV
420     printf ("ASMV ");
421 #endif
422 #ifdef DEBUG
423     printf ("DEBUG ");
424 #endif
425 #ifdef DYN_ALLOC
426     printf ("DYN_ALLOC ");
427 #endif
428 #ifdef MAXSEG_64K
429     printf ("MAXSEG_64K");
430 #endif
431     printf ("\n");
432     printf ("Written by Jean-loup Gailly.\n");
433 }
434
435 local void progerror (string)
436     char *string;
437 {
438     int e = errno;
439     fprintf(stderr, "%s: ", progname);
440     errno = e;
441     perror(string);
442     exit_code = ERROR;
443 }
444
445 /* ======================================================================== */
446 int main (argc, argv)
447     int argc;
448     char **argv;
449 {
450     int file_count;     /* number of files to precess */
451     int proglen;        /* length of progname */
452     int optc;           /* current option */
453
454     EXPAND(argc, argv); /* wild card expansion if necessary */
455
456     progname = base_name (argv[0]);
457     proglen = strlen(progname);
458
459     /* Suppress .exe for MSDOS, OS/2 and VMS: */
460     if (proglen > 4 && strequ(progname+proglen-4, ".exe")) {
461         progname[proglen-4] = '\0';
462     }
463
464     /* Add options in GZIP environment variable if there is one */
465     env = add_envopt(&argc, &argv, OPTIONS_VAR);
466     if (env != NULL) args = argv;
467
468     foreground = signal(SIGINT, SIG_IGN) != SIG_IGN;
469     if (foreground) {
470         (void) signal (SIGINT, (sig_type)abort_gzip);
471     }
472 #ifdef SIGTERM
473     if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
474         (void) signal(SIGTERM, (sig_type)abort_gzip);
475     }
476 #endif
477 #ifdef SIGHUP
478     if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
479         (void) signal(SIGHUP,  (sig_type)abort_gzip);
480     }
481 #endif
482
483 #ifndef GNU_STANDARD
484     /* For compatibility with old compress, use program name as an option.
485      * If you compile with -DGNU_STANDARD, this program will behave as
486      * gzip even if it is invoked under the name gunzip or zcat.
487      *
488      * Systems which do not support links can still use -d or -dc.
489      * Ignore an .exe extension for MSDOS, OS/2 and VMS.
490      */
491     if (  strncmp(progname, "un",  2) == 0     /* ungzip, uncompress */
492        || strncmp(progname, "gun", 3) == 0) {  /* gunzip */
493         decompress = 1;
494     } else if (strequ(progname+1, "cat")       /* zcat, pcat, gcat */
495             || strequ(progname, "gzcat")) {    /* gzcat */
496         decompress = to_stdout = 1;
497     }
498 #endif
499
500     z_suffix = Z_SUFFIX;
501     z_len = strlen(z_suffix);
502
503     while ((optc = getopt_long (argc, argv, "ab:cdfhH?lLmMnNqrS:tvVZ123456789",
504                                 longopts, (int *)0)) != -1) {
505         switch (optc) {
506         case 'a':
507             ascii = 1; break;
508         case 'b':
509             maxbits = atoi(optarg);
510             for (; *optarg; optarg++)
511               if (! ('0' <= *optarg && *optarg <= '9'))
512                 {
513                   fprintf (stderr, "%s: -b operand is not an integer\n",
514                            progname);
515                   usage ();
516                   do_exit (ERROR);
517                 }
518             break;
519         case 'c':
520             to_stdout = 1; break;
521         case 'd':
522             decompress = 1; break;
523         case 'f':
524             force++; break;
525         case 'h': case 'H': case '?':
526             help(); do_exit(OK); break;
527         case 'l':
528             list = decompress = to_stdout = 1; break;
529         case 'L':
530             license(); do_exit(OK); break;
531         case 'm': /* undocumented, may change later */
532             no_time = 1; break;
533         case 'M': /* undocumented, may change later */
534             no_time = 0; break;
535         case 'n':
536             no_name = no_time = 1; break;
537         case 'N':
538             no_name = no_time = 0; break;
539         case 'q':
540             quiet = 1; verbose = 0; break;
541         case 'r':
542 #ifdef NO_DIR
543             fprintf(stderr, "%s: -r not supported on this system\n", progname);
544             usage();
545             do_exit(ERROR); break;
546 #else
547             recursive = 1; break;
548 #endif
549         case 'S':
550 #ifdef NO_MULTIPLE_DOTS
551             if (*optarg == '.') optarg++;
552 #endif
553             z_len = strlen(optarg);
554             z_suffix = optarg;
555             break;
556         case 't':
557             test = decompress = to_stdout = 1;
558             break;
559         case 'v':
560             verbose++; quiet = 0; break;
561         case 'V':
562             version(); do_exit(OK); break;
563         case 'Z':
564 #ifdef LZW
565             do_lzw = 1; break;
566 #else
567             fprintf(stderr, "%s: -Z not supported in this version\n",
568                     progname);
569             usage();
570             do_exit(ERROR); break;
571 #endif
572         case '1':  case '2':  case '3':  case '4':
573         case '5':  case '6':  case '7':  case '8':  case '9':
574             level = optc - '0';
575             break;
576         default:
577             /* Error message already emitted by getopt_long. */
578             usage();
579             do_exit(ERROR);
580         }
581     } /* loop on all arguments */
582
583 #ifdef SIGPIPE
584     /* Ignore "Broken Pipe" message with --quiet */
585     if (quiet && signal (SIGPIPE, SIG_IGN) != SIG_IGN)
586       signal (SIGPIPE, (sig_type) abort_gzip);
587 #endif
588
589     /* By default, save name and timestamp on compression but do not
590      * restore them on decompression.
591      */
592     if (no_time < 0) no_time = decompress;
593     if (no_name < 0) no_name = decompress;
594
595     file_count = argc - optind;
596
597 #if O_BINARY
598 #else
599     if (ascii && !quiet) {
600         fprintf(stderr, "%s: option --ascii ignored on this system\n",
601                 progname);
602     }
603 #endif
604     if ((z_len == 0 && !decompress) || z_len > MAX_SUFFIX) {
605         fprintf(stderr, "%s: incorrect suffix '%s'\n",
606                 progname, optarg);
607         do_exit(ERROR);
608     }
609     if (do_lzw && !decompress) work = lzw;
610
611     /* Allocate all global buffers (for DYN_ALLOC option) */
612     ALLOC(uch, inbuf,  INBUFSIZ +INBUF_EXTRA);
613     ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
614     ALLOC(ush, d_buf,  DIST_BUFSIZE);
615     ALLOC(uch, window, 2L*WSIZE);
616 #ifndef MAXSEG_64K
617     ALLOC(ush, tab_prefix, 1L<<BITS);
618 #else
619     ALLOC(ush, tab_prefix0, 1L<<(BITS-1));
620     ALLOC(ush, tab_prefix1, 1L<<(BITS-1));
621 #endif
622
623     /* And get to work */
624     if (file_count != 0) {
625         if (to_stdout && !test && !list && (!decompress || !ascii)) {
626             SET_BINARY_MODE(fileno(stdout));
627         }
628         while (optind < argc) {
629             treat_file(argv[optind++]);
630         }
631     } else {  /* Standard input */
632         treat_stdin();
633     }
634     if (list && !quiet && file_count > 1) {
635         do_list(-1, -1); /* print totals */
636     }
637     do_exit(exit_code);
638     return exit_code; /* just to avoid lint warning */
639 }
640
641 /* Return nonzero when at end of file on input.  */
642 local int
643 input_eof ()
644 {
645   if (!decompress || last_member)
646     return 1;
647
648   if (inptr == insize)
649     {
650       if (insize != INBUFSIZ || fill_inbuf (1) == EOF)
651         return 1;
652
653       /* Unget the char that fill_inbuf got.  */
654       inptr = 0;
655     }
656
657   return 0;
658 }
659
660 /* ========================================================================
661  * Compress or decompress stdin
662  */
663 local void treat_stdin()
664 {
665     if (!force && !list &&
666         isatty(fileno((FILE *)(decompress ? stdin : stdout)))) {
667         /* Do not send compressed data to the terminal or read it from
668          * the terminal. We get here when user invoked the program
669          * without parameters, so be helpful. According to the GNU standards:
670          *
671          *   If there is one behavior you think is most useful when the output
672          *   is to a terminal, and another that you think is most useful when
673          *   the output is a file or a pipe, then it is usually best to make
674          *   the default behavior the one that is useful with output to a
675          *   terminal, and have an option for the other behavior.
676          *
677          * Here we use the --force option to get the other behavior.
678          */
679         fprintf(stderr,
680     "%s: compressed data not %s a terminal. Use -f to force %scompression.\n",
681                 progname, decompress ? "read from" : "written to",
682                 decompress ? "de" : "");
683         fprintf(stderr,"For help, type: %s -h\n", progname);
684         do_exit(ERROR);
685     }
686
687     if (decompress || !ascii) {
688         SET_BINARY_MODE(fileno(stdin));
689     }
690     if (!test && !list && (!decompress || !ascii)) {
691         SET_BINARY_MODE(fileno(stdout));
692     }
693     strcpy(ifname, "stdin");
694     strcpy(ofname, "stdout");
695
696     /* Get the time stamp on the input file. */
697     time_stamp = 0; /* time unknown by default */
698
699 #ifndef NO_STDIN_FSTAT
700     if (list || !no_time) {
701         if (fstat(fileno(stdin), &istat) != 0) {
702             progerror("standard input");
703             do_exit(ERROR);
704         }
705 # ifdef NO_PIPE_TIMESTAMP
706         if (S_ISREG(istat.st_mode))
707 # endif
708             time_stamp = istat.st_mtime;
709 #endif /* NO_STDIN_FSTAT */
710     }
711     ifile_size = -1L; /* convention for unknown size */
712
713     clear_bufs(); /* clear input and output buffers */
714     to_stdout = 1;
715     part_nb = 0;
716
717     if (decompress) {
718         method = get_method(ifd);
719         if (method < 0) {
720             do_exit(exit_code); /* error message already emitted */
721         }
722     }
723     if (list) {
724         do_list(ifd, method);
725         return;
726     }
727
728     /* Actually do the compression/decompression. Loop over zipped members.
729      */
730     for (;;) {
731         if ((*work)(fileno(stdin), fileno(stdout)) != OK) return;
732
733         if (input_eof ())
734           break;
735
736         method = get_method(ifd);
737         if (method < 0) return; /* error message already emitted */
738         bytes_out = 0;            /* required for length check */
739     }
740
741     if (verbose) {
742         if (test) {
743             fprintf(stderr, " OK\n");
744
745         } else if (!decompress) {
746             display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
747             fprintf(stderr, "\n");
748 #ifdef DISPLAY_STDIN_RATIO
749         } else {
750             display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
751             fprintf(stderr, "\n");
752 #endif
753         }
754     }
755 }
756
757 /* ========================================================================
758  * Compress or decompress the given file
759  */
760 local void treat_file(iname)
761     char *iname;
762 {
763     /* Accept "-" as synonym for stdin */
764     if (strequ(iname, "-")) {
765         int cflag = to_stdout;
766         treat_stdin();
767         to_stdout = cflag;
768         return;
769     }
770
771     /* Check if the input file is present, set ifname and istat: */
772     if (get_istat(iname, &istat) != OK) return;
773
774     /* If the input name is that of a directory, recurse or ignore: */
775     if (S_ISDIR(istat.st_mode)) {
776 #ifndef NO_DIR
777         if (recursive) {
778             struct stat st;
779             st = istat;
780             treat_dir(iname);
781             /* Warning: ifname is now garbage */
782 #  ifndef NO_UTIME
783             reset_times (iname, &st);
784 #  endif
785         } else
786 #endif
787         WARN((stderr,"%s: %s is a directory -- ignored\n", progname, ifname));
788         return;
789     }
790     if (!S_ISREG(istat.st_mode)) {
791         WARN((stderr,
792               "%s: %s is not a directory or a regular file - ignored\n",
793               progname, ifname));
794         return;
795     }
796     if (istat.st_nlink > 1 && !to_stdout && !force) {
797         WARN((stderr, "%s: %s has %lu other link%c -- unchanged\n",
798               progname, ifname, (unsigned long) istat.st_nlink - 1,
799               istat.st_nlink > 2 ? 's' : ' '));
800         return;
801     }
802
803     ifile_size = istat.st_size;
804     time_stamp = no_time && !list ? 0 : istat.st_mtime;
805
806     /* Generate output file name. For -r and (-t or -l), skip files
807      * without a valid gzip suffix (check done in make_ofname).
808      */
809     if (to_stdout && !list && !test) {
810         strcpy(ofname, "stdout");
811
812     } else if (make_ofname() != OK) {
813         return;
814     }
815
816     /* Open the input file and determine compression method. The mode
817      * parameter is ignored but required by some systems (VMS) and forbidden
818      * on other systems (MacOS).
819      */
820     ifd = OPEN(ifname, ascii && !decompress ? O_RDONLY : O_RDONLY | O_BINARY,
821                RW_USER);
822     if (ifd == -1) {
823         progerror(ifname);
824         return;
825     }
826     clear_bufs(); /* clear input and output buffers */
827     part_nb = 0;
828
829     if (decompress) {
830         method = get_method(ifd); /* updates ofname if original given */
831         if (method < 0) {
832             close(ifd);
833             return;               /* error message already emitted */
834         }
835     }
836     if (list) {
837         do_list(ifd, method);
838         close(ifd);
839         return;
840     }
841
842     /* If compressing to a file, check if ofname is not ambiguous
843      * because the operating system truncates names. Otherwise, generate
844      * a new ofname and save the original name in the compressed file.
845      */
846     if (to_stdout) {
847         ofd = fileno(stdout);
848         /* keep remove_ofname as zero */
849     } else {
850         if (create_outfile() != OK) return;
851
852         if (!decompress && save_orig_name && !verbose && !quiet) {
853             fprintf(stderr, "%s: %s compressed to %s\n",
854                     progname, ifname, ofname);
855         }
856     }
857     /* Keep the name even if not truncated except with --no-name: */
858     if (!save_orig_name) save_orig_name = !no_name;
859
860     if (verbose) {
861         fprintf(stderr, "%s:\t", ifname);
862     }
863
864     /* Actually do the compression/decompression. Loop over zipped members.
865      */
866     for (;;) {
867         if ((*work)(ifd, ofd) != OK) {
868             method = -1; /* force cleanup */
869             break;
870         }
871
872         if (input_eof ())
873           break;
874
875         method = get_method(ifd);
876         if (method < 0) break;    /* error message already emitted */
877         bytes_out = 0;            /* required for length check */
878     }
879
880     close(ifd);
881     if (!to_stdout && close(ofd)) {
882         write_error();
883     }
884     if (method == -1) {
885         if (!to_stdout) xunlink (ofname);
886         return;
887     }
888     /* Display statistics */
889     if(verbose) {
890         if (test) {
891             fprintf(stderr, " OK");
892         } else if (decompress) {
893             display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
894         } else {
895             display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
896         }
897         if (!test && !to_stdout) {
898             fprintf(stderr, " -- replaced with %s", ofname);
899         }
900         fprintf(stderr, "\n");
901     }
902     /* Copy modes, times, ownership, and remove the input file */
903     if (!to_stdout) {
904         copy_stat(&istat);
905     }
906 }
907
908 /* ========================================================================
909  * Create the output file. Return OK or ERROR.
910  * Try several times if necessary to avoid truncating the z_suffix. For
911  * example, do not create a compressed file of name "1234567890123."
912  * Sets save_orig_name to true if the file name has been truncated.
913  * IN assertions: the input file has already been open (ifd is set) and
914  *   ofname has already been updated if there was an original name.
915  * OUT assertions: ifd and ofd are closed in case of error.
916  */
917 local int create_outfile()
918 {
919     struct stat ostat; /* stat for ofname */
920     int flags = O_WRONLY | O_CREAT | O_EXCL | O_BINARY;
921
922     if (ascii && decompress) {
923         flags &= ~O_BINARY; /* force ascii text mode */
924     }
925     for (;;) {
926         /* Make sure that ofname is not an existing file */
927         if (check_ofname() != OK) {
928             close(ifd);
929             return ERROR;
930         }
931         /* Create the output file */
932         remove_ofname = 1;
933         ofd = OPEN(ofname, flags, RW_USER);
934         if (ofd == -1) {
935             progerror(ofname);
936             close(ifd);
937             return ERROR;
938         }
939
940         /* Check for name truncation on new file (1234567890123.gz) */
941 #ifdef NO_FSTAT
942         if (stat(ofname, &ostat) != 0) {
943 #else
944         if (fstat(ofd, &ostat) != 0) {
945 #endif
946             progerror(ofname);
947             close(ifd); close(ofd);
948             xunlink (ofname);
949             return ERROR;
950         }
951         if (!name_too_long(ofname, &ostat)) return OK;
952
953         if (decompress) {
954             /* name might be too long if an original name was saved */
955             WARN((stderr, "%s: %s: warning, name truncated\n",
956                   progname, ofname));
957             return OK;
958         }
959         close(ofd);
960         xunlink (ofname);
961 #ifdef NO_MULTIPLE_DOTS
962         /* Should never happen, see check_ofname() */
963         fprintf(stderr, "%s: %s: name too long\n", progname, ofname);
964         do_exit(ERROR);
965 #endif
966         shorten_name(ofname);
967     }
968 }
969
970 /* ========================================================================
971  * Use lstat if available, except for -c or -f. Use stat otherwise.
972  * This allows links when not removing the original file.
973  */
974 local int do_stat(name, sbuf)
975     char *name;
976     struct stat *sbuf;
977 {
978     errno = 0;
979 #ifdef HAVE_LSTAT
980     if (!to_stdout && !force) {
981         return lstat(name, sbuf);
982     }
983 #endif
984     return stat(name, sbuf);
985 }
986
987 /* ========================================================================
988  * Return a pointer to the 'z' suffix of a file name, or NULL. For all
989  * systems, ".gz", ".z", ".Z", ".taz", ".tgz", "-gz", "-z" and "_z" are
990  * accepted suffixes, in addition to the value of the --suffix option.
991  * ".tgz" is a useful convention for tar.z files on systems limited
992  * to 3 characters extensions. On such systems, ".?z" and ".??z" are
993  * also accepted suffixes. For Unix, we do not want to accept any
994  * .??z suffix as indicating a compressed file; some people use .xyz
995  * to denote volume data.
996  *   On systems allowing multiple versions of the same file (such as VMS),
997  * this function removes any version suffix in the given name.
998  */
999 local char *get_suffix(name)
1000     char *name;
1001 {
1002     int nlen, slen;
1003     char suffix[MAX_SUFFIX+3]; /* last chars of name, forced to lower case */
1004     static char *known_suffixes[] =
1005        {NULL, ".gz", ".z", ".taz", ".tgz", "-gz", "-z", "_z",
1006 #ifdef MAX_EXT_CHARS
1007           "z",
1008 #endif
1009           NULL};
1010     char **suf = known_suffixes;
1011
1012     *suf = z_suffix;
1013     if (strequ(z_suffix, "z")) suf++; /* check long suffixes first */
1014
1015 #ifdef SUFFIX_SEP
1016     /* strip a version number from the file name */
1017     {
1018         char *v = strrchr(name, SUFFIX_SEP);
1019         if (v != NULL) *v = '\0';
1020     }
1021 #endif
1022     nlen = strlen(name);
1023     if (nlen <= MAX_SUFFIX+2) {
1024         strcpy(suffix, name);
1025     } else {
1026         strcpy(suffix, name+nlen-MAX_SUFFIX-2);
1027     }
1028     strlwr(suffix);
1029     slen = strlen(suffix);
1030     do {
1031        int s = strlen(*suf);
1032        if (slen > s && suffix[slen-s-1] != PATH_SEP
1033            && strequ(suffix + slen - s, *suf)) {
1034            return name+nlen-s;
1035        }
1036     } while (*++suf != NULL);
1037
1038     return NULL;
1039 }
1040
1041
1042 /* ========================================================================
1043  * Set ifname to the input file name (with a suffix appended if necessary)
1044  * and istat to its stats. For decompression, if no file exists with the
1045  * original name, try adding successively z_suffix, .gz, .z, -z and .Z.
1046  * For MSDOS, we try only z_suffix and z.
1047  * Return OK or ERROR.
1048  */
1049 local int get_istat(iname, sbuf)
1050     char *iname;
1051     struct stat *sbuf;
1052 {
1053     int ilen;  /* strlen(ifname) */
1054     int z_suffix_errno = 0;
1055     static char *suffixes[] = {NULL, ".gz", ".z", "-z", ".Z", NULL};
1056     char **suf = suffixes;
1057     char *s;
1058 #ifdef NO_MULTIPLE_DOTS
1059     char *dot; /* pointer to ifname extension, or NULL */
1060 #endif
1061
1062     *suf = z_suffix;
1063
1064     if (sizeof ifname - 1 <= strlen (iname))
1065         goto name_too_long;
1066
1067     strcpy(ifname, iname);
1068
1069     /* If input file exists, return OK. */
1070     if (do_stat(ifname, sbuf) == 0) return OK;
1071
1072     if (!decompress || errno != ENOENT) {
1073         progerror(ifname);
1074         return ERROR;
1075     }
1076     /* file.ext doesn't exist, try adding a suffix (after removing any
1077      * version number for VMS).
1078      */
1079     s = get_suffix(ifname);
1080     if (s != NULL) {
1081         progerror(ifname); /* ifname already has z suffix and does not exist */
1082         return ERROR;
1083     }
1084 #ifdef NO_MULTIPLE_DOTS
1085     dot = strrchr(ifname, '.');
1086     if (dot == NULL) {
1087         strcat(ifname, ".");
1088         dot = strrchr(ifname, '.');
1089     }
1090 #endif
1091     ilen = strlen(ifname);
1092     if (strequ(z_suffix, ".gz")) suf++;
1093
1094     /* Search for all suffixes */
1095     do {
1096         char *s0 = s = *suf;
1097         strcpy (ifname, iname);
1098 #ifdef NO_MULTIPLE_DOTS
1099         if (*s == '.') s++;
1100         if (*dot == '\0') strcpy (dot, ".");
1101 #endif
1102 #ifdef MAX_EXT_CHARS
1103         if (MAX_EXT_CHARS < strlen (s) + strlen (dot + 1))
1104           dot[MAX_EXT_CHARS + 1 - strlen (s)] = '\0';
1105 #endif
1106         if (sizeof ifname <= ilen + strlen (s))
1107           goto name_too_long;
1108         strcat(ifname, s);
1109         if (do_stat(ifname, sbuf) == 0) return OK;
1110         if (strequ (s0, z_suffix))
1111           z_suffix_errno = errno;
1112     } while (*++suf != NULL);
1113
1114     /* No suffix found, complain using z_suffix: */
1115     strcpy(ifname, iname);
1116 #ifdef NO_MULTIPLE_DOTS
1117     if (*dot == '\0') strcpy(dot, ".");
1118 #endif
1119 #ifdef MAX_EXT_CHARS
1120     if (MAX_EXT_CHARS < z_len + strlen (dot + 1))
1121       dot[MAX_EXT_CHARS + 1 - z_len] = '\0';
1122 #endif
1123     strcat(ifname, z_suffix);
1124     errno = z_suffix_errno;
1125     progerror(ifname);
1126     return ERROR;
1127       
1128  name_too_long:
1129     fprintf (stderr, "%s: %s: file name too long\n", progname, iname);
1130     exit_code = ERROR;
1131     return ERROR;
1132 }
1133
1134 /* ========================================================================
1135  * Generate ofname given ifname. Return OK, or WARNING if file must be skipped.
1136  * Sets save_orig_name to true if the file name has been truncated.
1137  */
1138 local int make_ofname()
1139 {
1140     char *suff;            /* ofname z suffix */
1141
1142     strcpy(ofname, ifname);
1143     /* strip a version number if any and get the gzip suffix if present: */
1144     suff = get_suffix(ofname);
1145
1146     if (decompress) {
1147         if (suff == NULL) {
1148             /* With -t or -l, try all files (even without .gz suffix)
1149              * except with -r (behave as with just -dr).
1150              */
1151             if (!recursive && (list || test)) return OK;
1152
1153             /* Avoid annoying messages with -r */
1154             if (verbose || (!recursive && !quiet)) {
1155                 WARN((stderr,"%s: %s: unknown suffix -- ignored\n",
1156                       progname, ifname));
1157             }
1158             return WARNING;
1159         }
1160         /* Make a special case for .tgz and .taz: */
1161         strlwr(suff);
1162         if (strequ(suff, ".tgz") || strequ(suff, ".taz")) {
1163             strcpy(suff, ".tar");
1164         } else {
1165             *suff = '\0'; /* strip the z suffix */
1166         }
1167         /* ofname might be changed later if infile contains an original name */
1168
1169     } else if (suff != NULL) {
1170         /* Avoid annoying messages with -r (see treat_dir()) */
1171         if (verbose || (!recursive && !quiet)) {
1172             WARN((stderr, "%s: %s already has %s suffix -- unchanged\n",
1173                   progname, ifname, suff));
1174         }
1175         return WARNING;
1176     } else {
1177         save_orig_name = 0;
1178
1179 #ifdef NO_MULTIPLE_DOTS
1180         suff = strrchr(ofname, '.');
1181         if (suff == NULL) {
1182             if (sizeof ofname <= strlen (ofname) + 1)
1183                 goto name_too_long;
1184             strcat(ofname, ".");
1185 #  ifdef MAX_EXT_CHARS
1186             if (strequ(z_suffix, "z")) {
1187                 if (sizeof ofname <= strlen (ofname) + 2)
1188                     goto name_too_long;
1189                 strcat(ofname, "gz"); /* enough room */
1190                 return OK;
1191             }
1192         /* On the Atari and some versions of MSDOS, name_too_long()
1193          * does not work correctly because of a bug in stat(). So we
1194          * must truncate here.
1195          */
1196         } else if (strlen(suff)-1 + z_len > MAX_SUFFIX) {
1197             suff[MAX_SUFFIX+1-z_len] = '\0';
1198             save_orig_name = 1;
1199 #  endif
1200         }
1201 #endif /* NO_MULTIPLE_DOTS */
1202         if (sizeof ofname <= strlen (ofname) + z_len)
1203             goto name_too_long;
1204         strcat(ofname, z_suffix);
1205
1206     } /* decompress ? */
1207     return OK;
1208
1209  name_too_long:
1210     WARN ((stderr, "%s: %s: file name too long\n", progname, ifname));
1211     return WARNING;
1212 }
1213
1214
1215 /* ========================================================================
1216  * Check the magic number of the input file and update ofname if an
1217  * original name was given and to_stdout is not set.
1218  * Return the compression method, -1 for error, -2 for warning.
1219  * Set inptr to the offset of the next byte to be processed.
1220  * Updates time_stamp if there is one and --no-time is not used.
1221  * This function may be called repeatedly for an input file consisting
1222  * of several contiguous gzip'ed members.
1223  * IN assertions: there is at least one remaining compressed member.
1224  *   If the member is a zip file, it must be the only one.
1225  */
1226 local int get_method(in)
1227     int in;        /* input file descriptor */
1228 {
1229     uch flags;     /* compression flags */
1230     char magic[2]; /* magic header */
1231     int imagic1;   /* like magic[1], but can represent EOF */
1232     ulg stamp;     /* time stamp */
1233
1234     /* If --force and --stdout, zcat == cat, so do not complain about
1235      * premature end of file: use try_byte instead of get_byte.
1236      */
1237     if (force && to_stdout) {
1238         magic[0] = (char)try_byte();
1239         imagic1 = try_byte ();
1240         magic[1] = (char) imagic1;
1241         /* If try_byte returned EOF, magic[1] == (char) EOF.  */
1242     } else {
1243         magic[0] = (char)get_byte();
1244         magic[1] = (char)get_byte();
1245         imagic1 = 0; /* avoid lint warning */
1246     }
1247     method = -1;                 /* unknown yet */
1248     part_nb++;                   /* number of parts in gzip file */
1249     header_bytes = 0;
1250     last_member = RECORD_IO;
1251     /* assume multiple members in gzip file except for record oriented I/O */
1252
1253     if (memcmp(magic, GZIP_MAGIC, 2) == 0
1254         || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
1255
1256         method = (int)get_byte();
1257         if (method != DEFLATED) {
1258             fprintf(stderr,
1259                     "%s: %s: unknown method %d -- not supported\n",
1260                     progname, ifname, method);
1261             exit_code = ERROR;
1262             return -1;
1263         }
1264         work = unzip;
1265         flags  = (uch)get_byte();
1266
1267         if ((flags & ENCRYPTED) != 0) {
1268             fprintf(stderr,
1269                     "%s: %s is encrypted -- not supported\n",
1270                     progname, ifname);
1271             exit_code = ERROR;
1272             return -1;
1273         }
1274         if ((flags & CONTINUATION) != 0) {
1275             fprintf(stderr,
1276                     "%s: %s is a a multi-part gzip file -- not supported\n",
1277                     progname, ifname);
1278             exit_code = ERROR;
1279             if (force <= 1) return -1;
1280         }
1281         if ((flags & RESERVED) != 0) {
1282             fprintf(stderr,
1283                     "%s: %s has flags 0x%x -- not supported\n",
1284                     progname, ifname, flags);
1285             exit_code = ERROR;
1286             if (force <= 1) return -1;
1287         }
1288         stamp  = (ulg)get_byte();
1289         stamp |= ((ulg)get_byte()) << 8;
1290         stamp |= ((ulg)get_byte()) << 16;
1291         stamp |= ((ulg)get_byte()) << 24;
1292         if (stamp != 0 && !no_time) time_stamp = stamp;
1293
1294         (void)get_byte();  /* Ignore extra flags for the moment */
1295         (void)get_byte();  /* Ignore OS type for the moment */
1296
1297         if ((flags & CONTINUATION) != 0) {
1298             unsigned part = (unsigned)get_byte();
1299             part |= ((unsigned)get_byte())<<8;
1300             if (verbose) {
1301                 fprintf(stderr,"%s: %s: part number %u\n",
1302                         progname, ifname, part);
1303             }
1304         }
1305         if ((flags & EXTRA_FIELD) != 0) {
1306             unsigned len = (unsigned)get_byte();
1307             len |= ((unsigned)get_byte())<<8;
1308             if (verbose) {
1309                 fprintf(stderr,"%s: %s: extra field of %u bytes ignored\n",
1310                         progname, ifname, len);
1311             }
1312             while (len--) (void)get_byte();
1313         }
1314
1315         /* Get original file name if it was truncated */
1316         if ((flags & ORIG_NAME) != 0) {
1317             if (no_name || (to_stdout && !list) || part_nb > 1) {
1318                 /* Discard the old name */
1319                 char c; /* dummy used for NeXTstep 3.0 cc optimizer bug */
1320                 do {c=get_byte();} while (c != 0);
1321             } else {
1322                 /* Copy the base name. Keep a directory prefix intact. */
1323                 char *p = base_name (ofname);
1324                 char *base = p;
1325                 for (;;) {
1326                     *p = (char)get_char();
1327                     if (*p++ == '\0') break;
1328                     if (p >= ofname+sizeof(ofname)) {
1329                         error("corrupted input -- file name too large");
1330                     }
1331                 }
1332                 /* If necessary, adapt the name to local OS conventions: */
1333                 if (!list) {
1334                    MAKE_LEGAL_NAME(base);
1335                    if (base) list=0; /* avoid warning about unused variable */
1336                 }
1337             } /* no_name || to_stdout */
1338         } /* ORIG_NAME */
1339
1340         /* Discard file comment if any */
1341         if ((flags & COMMENT) != 0) {
1342             while (get_char() != 0) /* null */ ;
1343         }
1344         if (part_nb == 1) {
1345             header_bytes = inptr + 2*sizeof(long); /* include crc and size */
1346         }
1347
1348     } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
1349             && memcmp((char*)inbuf, PKZIP_MAGIC, 4) == 0) {
1350         /* To simplify the code, we support a zip file when alone only.
1351          * We are thus guaranteed that the entire local header fits in inbuf.
1352          */
1353         inptr = 0;
1354         work = unzip;
1355         if (check_zipfile(in) != OK) return -1;
1356         /* check_zipfile may get ofname from the local header */
1357         last_member = 1;
1358
1359     } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
1360         work = unpack;
1361         method = PACKED;
1362
1363     } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {
1364         work = unlzw;
1365         method = COMPRESSED;
1366         last_member = 1;
1367
1368     } else if (memcmp(magic, LZH_MAGIC, 2) == 0) {
1369         work = unlzh;
1370         method = LZHED;
1371         last_member = 1;
1372
1373     } else if (force && to_stdout && !list) { /* pass input unchanged */
1374         method = STORED;
1375         work = copy;
1376         inptr = 0;
1377         last_member = 1;
1378     }
1379     if (method >= 0) return method;
1380
1381     if (part_nb == 1) {
1382         fprintf(stderr, "\n%s: %s: not in gzip format\n", progname, ifname);
1383         exit_code = ERROR;
1384         return -1;
1385     } else {
1386         if (magic[0] == 0)
1387           {
1388             int inbyte;
1389             for (inbyte = imagic1;  inbyte == 0;  inbyte = try_byte ())
1390               continue;
1391             if (inbyte == EOF)
1392               {
1393                 if (verbose)
1394                   WARN ((stderr, "\n%s: %s: decompression OK, trailing zero bytes ignored\n",
1395                          progname, ifname));
1396                 return -3;
1397               }
1398           }
1399
1400         WARN((stderr, "\n%s: %s: decompression OK, trailing garbage ignored\n",
1401               progname, ifname));
1402         return -2;
1403     }
1404 }
1405
1406 /* ========================================================================
1407  * Display the characteristics of the compressed file.
1408  * If the given method is < 0, display the accumulated totals.
1409  * IN assertions: time_stamp, header_bytes and ifile_size are initialized.
1410  */
1411 local void do_list(ifd, method)
1412     int ifd;     /* input file descriptor */
1413     int method;  /* compression method */
1414 {
1415     ulg crc;  /* original crc */
1416     static int first_time = 1;
1417     static char* methods[MAX_METHODS] = {
1418         "store",  /* 0 */
1419         "compr",  /* 1 */
1420         "pack ",  /* 2 */
1421         "lzh  ",  /* 3 */
1422         "", "", "", "", /* 4 to 7 reserved */
1423         "defla"}; /* 8 */
1424     char *date;
1425     int positive_off_t_width = 1;
1426     off_t o;
1427
1428     for (o = OFF_T_MAX;  9 < o;  o /= 10) {
1429         positive_off_t_width++;
1430     }
1431
1432     if (first_time && method >= 0) {
1433         first_time = 0;
1434         if (verbose)  {
1435             printf("method  crc     date  time  ");
1436         }
1437         if (!quiet) {
1438             printf("%*.*s %*.*s  ratio uncompressed_name\n",
1439                    positive_off_t_width, positive_off_t_width, "compressed",
1440                    positive_off_t_width, positive_off_t_width, "uncompressed");
1441         }
1442     } else if (method < 0) {
1443         if (total_in <= 0 || total_out <= 0) return;
1444         if (verbose) {
1445             printf("                            ");
1446         }
1447         if (verbose || !quiet) {
1448             fprint_off(stdout, total_in, positive_off_t_width);
1449             printf(" ");
1450             fprint_off(stdout, total_out, positive_off_t_width);
1451             printf(" ");
1452         }
1453         display_ratio(total_out-(total_in-header_bytes), total_out, stdout);
1454         /* header_bytes is not meaningful but used to ensure the same
1455          * ratio if there is a single file.
1456          */
1457         printf(" (totals)\n");
1458         return;
1459     }
1460     crc = (ulg)~0; /* unknown */
1461     bytes_out = -1L;
1462     bytes_in = ifile_size;
1463
1464 #if RECORD_IO == 0
1465     if (method == DEFLATED && !last_member) {
1466         /* Get the crc and uncompressed size for gzip'ed (not zip'ed) files.
1467          * If the lseek fails, we could use read() to get to the end, but
1468          * --list is used to get quick results.
1469          * Use "gunzip < foo.gz | wc -c" to get the uncompressed size if
1470          * you are not concerned about speed.
1471          */
1472         bytes_in = lseek(ifd, (off_t)(-8), SEEK_END);
1473         if (bytes_in != -1L) {
1474             uch buf[8];
1475             bytes_in += 8L;
1476             if (read(ifd, (char*)buf, sizeof(buf)) != sizeof(buf)) {
1477                 read_error();
1478             }
1479             crc       = LG(buf);
1480             bytes_out = LG(buf+4);
1481         }
1482     }
1483 #endif /* RECORD_IO */
1484     date = ctime((time_t*)&time_stamp) + 4; /* skip the day of the week */
1485     date[12] = '\0';               /* suppress the 1/100sec and the year */
1486     if (verbose) {
1487         printf("%5s %08lx %11s ", methods[method], crc, date);
1488     }
1489     fprint_off(stdout, bytes_in, positive_off_t_width);
1490     printf(" ");
1491     fprint_off(stdout, bytes_out, positive_off_t_width);
1492     printf(" ");
1493     if (bytes_in  == -1L) {
1494         total_in = -1L;
1495         bytes_in = bytes_out = header_bytes = 0;
1496     } else if (total_in >= 0) {
1497         total_in  += bytes_in;
1498     }
1499     if (bytes_out == -1L) {
1500         total_out = -1L;
1501         bytes_in = bytes_out = header_bytes = 0;
1502     } else if (total_out >= 0) {
1503         total_out += bytes_out;
1504     }
1505     display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out, stdout);
1506     printf(" %s\n", ofname);
1507 }
1508
1509 /* ========================================================================
1510  * Return true if the two stat structures correspond to the same file.
1511  */
1512 local int same_file(stat1, stat2)
1513     struct stat *stat1;
1514     struct stat *stat2;
1515 {
1516     return stat1->st_ino   == stat2->st_ino
1517         && stat1->st_dev   == stat2->st_dev
1518 #ifdef NO_ST_INO
1519         /* Can't rely on st_ino and st_dev, use other fields: */
1520         && stat1->st_mode  == stat2->st_mode
1521         && stat1->st_uid   == stat2->st_uid
1522         && stat1->st_gid   == stat2->st_gid
1523         && stat1->st_size  == stat2->st_size
1524         && stat1->st_atime == stat2->st_atime
1525         && stat1->st_mtime == stat2->st_mtime
1526         && stat1->st_ctime == stat2->st_ctime
1527 #endif
1528             ;
1529 }
1530
1531 /* ========================================================================
1532  * Return true if a file name is ambiguous because the operating system
1533  * truncates file names.
1534  */
1535 local int name_too_long(name, statb)
1536     char *name;           /* file name to check */
1537     struct stat *statb;   /* stat buf for this file name */
1538 {
1539     int s = strlen(name);
1540     char c = name[s-1];
1541     struct stat tstat; /* stat for truncated name */
1542     int res;
1543
1544     tstat = *statb;      /* Just in case OS does not fill all fields */
1545     name[s-1] = '\0';
1546     res = stat(name, &tstat) == 0 && same_file(statb, &tstat);
1547     name[s-1] = c;
1548     Trace((stderr, " too_long(%s) => %d\n", name, res));
1549     return res;
1550 }
1551
1552 /* ========================================================================
1553  * Shorten the given name by one character, or replace a .tar extension
1554  * with .tgz. Truncate the last part of the name which is longer than
1555  * MIN_PART characters: 1234.678.012.gz -> 123.678.012.gz. If the name
1556  * has only parts shorter than MIN_PART truncate the longest part.
1557  * For decompression, just remove the last character of the name.
1558  *
1559  * IN assertion: for compression, the suffix of the given name is z_suffix.
1560  */
1561 local void shorten_name(name)
1562     char *name;
1563 {
1564     int len;                 /* length of name without z_suffix */
1565     char *trunc = NULL;      /* character to be truncated */
1566     int plen;                /* current part length */
1567     int min_part = MIN_PART; /* current minimum part length */
1568     char *p;
1569
1570     len = strlen(name);
1571     if (decompress) {
1572         if (len <= 1) error("name too short");
1573         name[len-1] = '\0';
1574         return;
1575     }
1576     p = get_suffix(name);
1577     if (p == NULL) error("can't recover suffix\n");
1578     *p = '\0';
1579     save_orig_name = 1;
1580
1581     /* compress 1234567890.tar to 1234567890.tgz */
1582     if (len > 4 && strequ(p-4, ".tar")) {
1583         strcpy(p-4, ".tgz");
1584         return;
1585     }
1586     /* Try keeping short extensions intact:
1587      * 1234.678.012.gz -> 123.678.012.gz
1588      */
1589     do {
1590         p = strrchr(name, PATH_SEP);
1591         p = p ? p+1 : name;
1592         while (*p) {
1593             plen = strcspn(p, PART_SEP);
1594             p += plen;
1595             if (plen > min_part) trunc = p-1;
1596             if (*p) p++;
1597         }
1598     } while (trunc == NULL && --min_part != 0);
1599
1600     if (trunc != NULL) {
1601         do {
1602             trunc[0] = trunc[1];
1603         } while (*trunc++);
1604         trunc--;
1605     } else {
1606         trunc = strrchr(name, PART_SEP[0]);
1607         if (trunc == NULL) error("internal error in shorten_name");
1608         if (trunc[1] == '\0') trunc--; /* force truncation */
1609     }
1610     strcpy(trunc, z_suffix);
1611 }
1612
1613 /* ========================================================================
1614  * If compressing to a file, check if ofname is not ambiguous
1615  * because the operating system truncates names. Otherwise, generate
1616  * a new ofname and save the original name in the compressed file.
1617  * If the compressed file already exists, ask for confirmation.
1618  *    The check for name truncation is made dynamically, because different
1619  * file systems on the same OS might use different truncation rules (on SVR4
1620  * s5 truncates to 14 chars and ufs does not truncate).
1621  *    This function returns -1 if the file must be skipped, and
1622  * updates save_orig_name if necessary.
1623  * IN assertions: save_orig_name is already set if ofname has been
1624  * already truncated because of NO_MULTIPLE_DOTS. The input file has
1625  * already been open and istat is set.
1626  */
1627 local int check_ofname()
1628 {
1629     struct stat ostat; /* stat for ofname */
1630
1631 #ifdef ENAMETOOLONG
1632     /* Check for strictly conforming Posix systems (which return ENAMETOOLONG
1633      * instead of silently truncating filenames).
1634      */
1635     errno = 0;
1636     while (stat(ofname, &ostat) != 0) {
1637         if (errno != ENAMETOOLONG) return 0; /* ofname does not exist */
1638         shorten_name(ofname);
1639     }
1640 #else
1641     if (stat(ofname, &ostat) != 0) return 0;
1642 #endif
1643     /* Check for name truncation on existing file. Do this even on systems
1644      * defining ENAMETOOLONG, because on most systems the strict Posix
1645      * behavior is disabled by default (silent name truncation allowed).
1646      */
1647     if (!decompress && name_too_long(ofname, &ostat)) {
1648         shorten_name(ofname);
1649         if (stat(ofname, &ostat) != 0) return 0;
1650     }
1651
1652     /* Check that the input and output files are different (could be
1653      * the same by name truncation or links).
1654      */
1655     if (same_file(&istat, &ostat)) {
1656         if (strequ(ifname, ofname)) {
1657             fprintf(stderr, "%s: %s: cannot %scompress onto itself\n",
1658                     progname, ifname, decompress ? "de" : "");
1659         } else {
1660             fprintf(stderr, "%s: %s and %s are the same file\n",
1661                     progname, ifname, ofname);
1662         }
1663         exit_code = ERROR;
1664         return ERROR;
1665     }
1666     /* Ask permission to overwrite the existing file */
1667     if (!force) {
1668         int ok = 0;
1669         fprintf(stderr, "%s: %s already exists;", progname, ofname);
1670         if (foreground && isatty(fileno(stdin))) {
1671             fprintf(stderr, " do you wish to overwrite (y or n)? ");
1672             fflush(stderr);
1673             ok = yesno();
1674         }
1675         if (!ok) {
1676             fprintf(stderr, "\tnot overwritten\n");
1677             if (exit_code == OK) exit_code = WARNING;
1678             return ERROR;
1679         }
1680     }
1681     if (xunlink (ofname)) {
1682         progerror(ofname);
1683         return ERROR;
1684     }
1685     return OK;
1686 }
1687
1688
1689 #ifndef NO_UTIME
1690 /* ========================================================================
1691  * Set the access and modification times from the given stat buffer.
1692  */
1693 local void reset_times (name, statb)
1694     char *name;
1695     struct stat *statb;
1696 {
1697     struct utimbuf      timep;
1698
1699     /* Copy the time stamp */
1700     timep.actime  = statb->st_atime;
1701     timep.modtime = statb->st_mtime;
1702
1703     /* Some systems (at least OS/2) do not support utime on directories */
1704     if (utime(name, &timep) && !S_ISDIR(statb->st_mode)) {
1705         int e = errno;
1706         WARN((stderr, "%s: ", progname));
1707         if (!quiet) {
1708             errno = e;
1709             perror(ofname);
1710         }
1711     }
1712 }
1713 #endif
1714
1715
1716 /* ========================================================================
1717  * Copy modes, times, ownership from input file to output file.
1718  * IN assertion: to_stdout is false.
1719  */
1720 local void copy_stat(ifstat)
1721     struct stat *ifstat;
1722 {
1723 #ifndef NO_UTIME
1724     if (decompress && time_stamp != 0 && ifstat->st_mtime != time_stamp) {
1725         ifstat->st_mtime = time_stamp;
1726         if (verbose > 1) {
1727             fprintf(stderr, "%s: time stamp restored\n", ofname);
1728         }
1729     }
1730     reset_times(ofname, ifstat);
1731 #endif
1732     /* Copy the protection modes */
1733     if (chmod(ofname, ifstat->st_mode & 07777)) {
1734         int e = errno;
1735         WARN((stderr, "%s: ", progname));
1736         if (!quiet) {
1737             errno = e;
1738             perror(ofname);
1739         }
1740     }
1741 #ifndef NO_CHOWN
1742     chown(ofname, ifstat->st_uid, ifstat->st_gid);  /* Copy ownership */
1743 #endif
1744     remove_ofname = 0;
1745     /* It's now safe to remove the input file: */
1746     if (xunlink (ifname)) {
1747         int e = errno;
1748         WARN((stderr, "%s: ", progname));
1749         if (!quiet) {
1750             errno = e;
1751             perror(ifname);
1752         }
1753     }
1754 }
1755
1756 #ifndef NO_DIR
1757
1758 /* ========================================================================
1759  * Recurse through the given directory. This code is taken from ncompress.
1760  */
1761 local void treat_dir(dir)
1762     char *dir;
1763 {
1764     struct dirent *dp;
1765     DIR      *dirp;
1766     char     nbuf[MAX_PATH_LEN];
1767     int      len;
1768
1769     dirp = opendir(dir);
1770     
1771     if (dirp == NULL) {
1772         progerror(dir);
1773         return ;
1774     }
1775     /*
1776      ** WARNING: the following algorithm could occasionally cause
1777      ** compress to produce error warnings of the form "<filename>.gz
1778      ** already has .gz suffix - ignored". This occurs when the
1779      ** .gz output file is inserted into the directory below
1780      ** readdir's current pointer.
1781      ** These warnings are harmless but annoying, so they are suppressed
1782      ** with option -r (except when -v is on). An alternative
1783      ** to allowing this would be to store the entire directory
1784      ** list in memory, then compress the entries in the stored
1785      ** list. Given the depth-first recursive algorithm used here,
1786      ** this could use up a tremendous amount of memory. I don't
1787      ** think it's worth it. -- Dave Mack
1788      ** (An other alternative might be two passes to avoid depth-first.)
1789      */
1790     
1791     while ((errno = 0, dp = readdir(dirp)) != NULL) {
1792
1793         if (strequ(dp->d_name,".") || strequ(dp->d_name,"..")) {
1794             continue;
1795         }
1796         len = strlen(dir);
1797         if (len + NAMLEN(dp) + 1 < MAX_PATH_LEN - 1) {
1798             strcpy(nbuf,dir);
1799             if (len != 0 /* dir = "" means current dir on Amiga */
1800 #ifdef PATH_SEP2
1801                 && dir[len-1] != PATH_SEP2
1802 #endif
1803 #ifdef PATH_SEP3
1804                 && dir[len-1] != PATH_SEP3
1805 #endif
1806             ) {
1807                 nbuf[len++] = PATH_SEP;
1808             }
1809             strcpy(nbuf+len, dp->d_name);
1810             treat_file(nbuf);
1811         } else {
1812             fprintf(stderr,"%s: %s/%s: pathname too long\n",
1813                     progname, dir, dp->d_name);
1814             exit_code = ERROR;
1815         }
1816     }
1817     if (errno != 0)
1818         progerror(dir);
1819     if (CLOSEDIR(dirp) != 0)
1820         progerror(dir);
1821 }
1822 #endif /* ? NO_DIR */
1823
1824 /* ========================================================================
1825  * Free all dynamically allocated variables and exit with the given code.
1826  */
1827 local void do_exit(exitcode)
1828     int exitcode;
1829 {
1830     static int in_exit = 0;
1831
1832     if (in_exit) exit(exitcode);
1833     in_exit = 1;
1834     if (env != NULL)  free(env),  env  = NULL;
1835     if (args != NULL) free((char*)args), args = NULL;
1836     FREE(inbuf);
1837     FREE(outbuf);
1838     FREE(d_buf);
1839     FREE(window);
1840 #ifndef MAXSEG_64K
1841     FREE(tab_prefix);
1842 #else
1843     FREE(tab_prefix0);
1844     FREE(tab_prefix1);
1845 #endif
1846     exit(exitcode);
1847 }
1848
1849 /* ========================================================================
1850  * Signal and error handler.
1851  */
1852 RETSIGTYPE abort_gzip()
1853 {
1854    if (remove_ofname) {
1855        close(ofd);
1856        xunlink (ofname);
1857    }
1858    do_exit(ERROR);
1859 }