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