]> git.cworth.org Git - gzip/blob - gzip.c
Imported Debian patch 1.3.2-3woody4
[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) {
882         /* Copy modes, times, ownership, and remove the input file */
883         copy_stat(&istat);
884         if (close(ofd))
885                 write_error();
886     }
887     if (method == -1) {
888         if (!to_stdout) xunlink (ofname);
889         return;
890     }
891     /* Display statistics */
892     if(verbose) {
893         if (test) {
894             fprintf(stderr, " OK");
895         } else if (decompress) {
896             display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
897         } else {
898             display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
899         }
900         if (!test && !to_stdout) {
901             fprintf(stderr, " -- replaced with %s", ofname);
902         }
903         fprintf(stderr, "\n");
904     }
905 }
906
907 /* ========================================================================
908  * Create the output file. Return OK or ERROR.
909  * Try several times if necessary to avoid truncating the z_suffix. For
910  * example, do not create a compressed file of name "1234567890123."
911  * Sets save_orig_name to true if the file name has been truncated.
912  * IN assertions: the input file has already been open (ifd is set) and
913  *   ofname has already been updated if there was an original name.
914  * OUT assertions: ifd and ofd are closed in case of error.
915  */
916 local int create_outfile()
917 {
918     struct stat ostat; /* stat for ofname */
919     int flags = O_WRONLY | O_CREAT | O_EXCL | O_BINARY;
920
921     if (ascii && decompress) {
922         flags &= ~O_BINARY; /* force ascii text mode */
923     }
924     for (;;) {
925         /* Make sure that ofname is not an existing file */
926         if (check_ofname() != OK) {
927             close(ifd);
928             return ERROR;
929         }
930         /* Create the output file */
931         remove_ofname = 1;
932         ofd = OPEN(ofname, flags, RW_USER);
933         if (ofd == -1) {
934             progerror(ofname);
935             close(ifd);
936             return ERROR;
937         }
938
939         /* Check for name truncation on new file (1234567890123.gz) */
940 #ifdef NO_FSTAT
941         if (stat(ofname, &ostat) != 0) {
942 #else
943         if (fstat(ofd, &ostat) != 0) {
944 #endif
945             progerror(ofname);
946             close(ifd); close(ofd);
947             xunlink (ofname);
948             return ERROR;
949         }
950         if (!name_too_long(ofname, &ostat)) return OK;
951
952         if (decompress) {
953             /* name might be too long if an original name was saved */
954             WARN((stderr, "%s: %s: warning, name truncated\n",
955                   progname, ofname));
956             return OK;
957         }
958         close(ofd);
959         xunlink (ofname);
960 #ifdef NO_MULTIPLE_DOTS
961         /* Should never happen, see check_ofname() */
962         fprintf(stderr, "%s: %s: name too long\n", progname, ofname);
963         do_exit(ERROR);
964 #endif
965         shorten_name(ofname);
966     }
967 }
968
969 /* ========================================================================
970  * Use lstat if available, except for -c or -f. Use stat otherwise.
971  * This allows links when not removing the original file.
972  */
973 local int do_stat(name, sbuf)
974     char *name;
975     struct stat *sbuf;
976 {
977     errno = 0;
978 #ifdef HAVE_LSTAT
979     if (!to_stdout && !force) {
980         return lstat(name, sbuf);
981     }
982 #endif
983     return stat(name, sbuf);
984 }
985
986 /* ========================================================================
987  * Return a pointer to the 'z' suffix of a file name, or NULL. For all
988  * systems, ".gz", ".z", ".Z", ".taz", ".tgz", "-gz", "-z" and "_z" are
989  * accepted suffixes, in addition to the value of the --suffix option.
990  * ".tgz" is a useful convention for tar.z files on systems limited
991  * to 3 characters extensions. On such systems, ".?z" and ".??z" are
992  * also accepted suffixes. For Unix, we do not want to accept any
993  * .??z suffix as indicating a compressed file; some people use .xyz
994  * to denote volume data.
995  *   On systems allowing multiple versions of the same file (such as VMS),
996  * this function removes any version suffix in the given name.
997  */
998 local char *get_suffix(name)
999     char *name;
1000 {
1001     int nlen, slen;
1002     char suffix[MAX_SUFFIX+3]; /* last chars of name, forced to lower case */
1003     static char *known_suffixes[] =
1004        {NULL, ".gz", ".z", ".taz", ".tgz", "-gz", "-z", "_z",
1005 #ifdef MAX_EXT_CHARS
1006           "z",
1007 #endif
1008           NULL};
1009     char **suf = known_suffixes;
1010
1011     *suf = z_suffix;
1012     if (strequ(z_suffix, "z")) suf++; /* check long suffixes first */
1013
1014 #ifdef SUFFIX_SEP
1015     /* strip a version number from the file name */
1016     {
1017         char *v = strrchr(name, SUFFIX_SEP);
1018         if (v != NULL) *v = '\0';
1019     }
1020 #endif
1021     nlen = strlen(name);
1022     if (nlen <= MAX_SUFFIX+2) {
1023         strcpy(suffix, name);
1024     } else {
1025         strcpy(suffix, name+nlen-MAX_SUFFIX-2);
1026     }
1027     strlwr(suffix);
1028     slen = strlen(suffix);
1029     do {
1030        int s = strlen(*suf);
1031        if (slen > s && suffix[slen-s-1] != PATH_SEP
1032            && strequ(suffix + slen - s, *suf)) {
1033            return name+nlen-s;
1034        }
1035     } while (*++suf != NULL);
1036
1037     return NULL;
1038 }
1039
1040
1041 /* ========================================================================
1042  * Set ifname to the input file name (with a suffix appended if necessary)
1043  * and istat to its stats. For decompression, if no file exists with the
1044  * original name, try adding successively z_suffix, .gz, .z, -z and .Z.
1045  * For MSDOS, we try only z_suffix and z.
1046  * Return OK or ERROR.
1047  */
1048 local int get_istat(iname, sbuf)
1049     char *iname;
1050     struct stat *sbuf;
1051 {
1052     int ilen;  /* strlen(ifname) */
1053     int z_suffix_errno = 0;
1054     static char *suffixes[] = {NULL, ".gz", ".z", "-z", ".Z", NULL};
1055     char **suf = suffixes;
1056     char *s;
1057 #ifdef NO_MULTIPLE_DOTS
1058     char *dot; /* pointer to ifname extension, or NULL */
1059 #endif
1060
1061     *suf = z_suffix;
1062
1063     if (sizeof ifname - 1 <= strlen (iname))
1064         goto name_too_long;
1065
1066     strcpy(ifname, iname);
1067
1068     /* If input file exists, return OK. */
1069     if (do_stat(ifname, sbuf) == 0) return OK;
1070
1071     if (!decompress || errno != ENOENT) {
1072         progerror(ifname);
1073         return ERROR;
1074     }
1075     /* file.ext doesn't exist, try adding a suffix (after removing any
1076      * version number for VMS).
1077      */
1078     s = get_suffix(ifname);
1079     if (s != NULL) {
1080         progerror(ifname); /* ifname already has z suffix and does not exist */
1081         return ERROR;
1082     }
1083 #ifdef NO_MULTIPLE_DOTS
1084     dot = strrchr(ifname, '.');
1085     if (dot == NULL) {
1086         strcat(ifname, ".");
1087         dot = strrchr(ifname, '.');
1088     }
1089 #endif
1090     ilen = strlen(ifname);
1091     if (strequ(z_suffix, ".gz")) suf++;
1092
1093     /* Search for all suffixes */
1094     do {
1095         char *s0 = s = *suf;
1096         strcpy (ifname, iname);
1097 #ifdef NO_MULTIPLE_DOTS
1098         if (*s == '.') s++;
1099         if (*dot == '\0') strcpy (dot, ".");
1100 #endif
1101 #ifdef MAX_EXT_CHARS
1102         if (MAX_EXT_CHARS < strlen (s) + strlen (dot + 1))
1103           dot[MAX_EXT_CHARS + 1 - strlen (s)] = '\0';
1104 #endif
1105         if (sizeof ifname <= ilen + strlen (s))
1106           goto name_too_long;
1107         strcat(ifname, s);
1108         if (do_stat(ifname, sbuf) == 0) return OK;
1109         if (strequ (s0, z_suffix))
1110           z_suffix_errno = errno;
1111     } while (*++suf != NULL);
1112
1113     /* No suffix found, complain using z_suffix: */
1114     strcpy(ifname, iname);
1115 #ifdef NO_MULTIPLE_DOTS
1116     if (*dot == '\0') strcpy(dot, ".");
1117 #endif
1118 #ifdef MAX_EXT_CHARS
1119     if (MAX_EXT_CHARS < z_len + strlen (dot + 1))
1120       dot[MAX_EXT_CHARS + 1 - z_len] = '\0';
1121 #endif
1122     strcat(ifname, z_suffix);
1123     errno = z_suffix_errno;
1124     progerror(ifname);
1125     return ERROR;
1126       
1127  name_too_long:
1128     fprintf (stderr, "%s: %s: file name too long\n", progname, iname);
1129     exit_code = ERROR;
1130     return ERROR;
1131 }
1132
1133 /* ========================================================================
1134  * Generate ofname given ifname. Return OK, or WARNING if file must be skipped.
1135  * Sets save_orig_name to true if the file name has been truncated.
1136  */
1137 local int make_ofname()
1138 {
1139     char *suff;            /* ofname z suffix */
1140
1141     strcpy(ofname, ifname);
1142     /* strip a version number if any and get the gzip suffix if present: */
1143     suff = get_suffix(ofname);
1144
1145     if (decompress) {
1146         if (suff == NULL) {
1147             /* With -t or -l, try all files (even without .gz suffix)
1148              * except with -r (behave as with just -dr).
1149              */
1150             if (!recursive && (list || test)) return OK;
1151
1152             /* Avoid annoying messages with -r */
1153             if (verbose || (!recursive && !quiet)) {
1154                 WARN((stderr,"%s: %s: unknown suffix -- ignored\n",
1155                       progname, ifname));
1156             }
1157             return WARNING;
1158         }
1159         /* Make a special case for .tgz and .taz: */
1160         strlwr(suff);
1161         if (strequ(suff, ".tgz") || strequ(suff, ".taz")) {
1162             strcpy(suff, ".tar");
1163         } else {
1164             *suff = '\0'; /* strip the z suffix */
1165         }
1166         /* ofname might be changed later if infile contains an original name */
1167
1168     } else if (suff != NULL) {
1169         /* Avoid annoying messages with -r (see treat_dir()) */
1170         if (verbose || (!recursive && !quiet)) {
1171             WARN((stderr, "%s: %s already has %s suffix -- unchanged\n",
1172                   progname, ifname, suff));
1173         }
1174         return WARNING;
1175     } else {
1176         save_orig_name = 0;
1177
1178 #ifdef NO_MULTIPLE_DOTS
1179         suff = strrchr(ofname, '.');
1180         if (suff == NULL) {
1181             if (sizeof ofname <= strlen (ofname) + 1)
1182                 goto name_too_long;
1183             strcat(ofname, ".");
1184 #  ifdef MAX_EXT_CHARS
1185             if (strequ(z_suffix, "z")) {
1186                 if (sizeof ofname <= strlen (ofname) + 2)
1187                     goto name_too_long;
1188                 strcat(ofname, "gz"); /* enough room */
1189                 return OK;
1190             }
1191         /* On the Atari and some versions of MSDOS, name_too_long()
1192          * does not work correctly because of a bug in stat(). So we
1193          * must truncate here.
1194          */
1195         } else if (strlen(suff)-1 + z_len > MAX_SUFFIX) {
1196             suff[MAX_SUFFIX+1-z_len] = '\0';
1197             save_orig_name = 1;
1198 #  endif
1199         }
1200 #endif /* NO_MULTIPLE_DOTS */
1201         if (sizeof ofname <= strlen (ofname) + z_len)
1202             goto name_too_long;
1203         strcat(ofname, z_suffix);
1204
1205     } /* decompress ? */
1206     return OK;
1207
1208  name_too_long:
1209     WARN ((stderr, "%s: %s: file name too long\n", progname, ifname));
1210     return WARNING;
1211 }
1212
1213
1214 /* ========================================================================
1215  * Check the magic number of the input file and update ofname if an
1216  * original name was given and to_stdout is not set.
1217  * Return the compression method, -1 for error, -2 for warning.
1218  * Set inptr to the offset of the next byte to be processed.
1219  * Updates time_stamp if there is one and --no-time is not used.
1220  * This function may be called repeatedly for an input file consisting
1221  * of several contiguous gzip'ed members.
1222  * IN assertions: there is at least one remaining compressed member.
1223  *   If the member is a zip file, it must be the only one.
1224  */
1225 local int get_method(in)
1226     int in;        /* input file descriptor */
1227 {
1228     uch flags;     /* compression flags */
1229     char magic[2]; /* magic header */
1230     int imagic1;   /* like magic[1], but can represent EOF */
1231     ulg stamp;     /* time stamp */
1232
1233     /* If --force and --stdout, zcat == cat, so do not complain about
1234      * premature end of file: use try_byte instead of get_byte.
1235      */
1236     if (force && to_stdout) {
1237         magic[0] = (char)try_byte();
1238         imagic1 = try_byte ();
1239         magic[1] = (char) imagic1;
1240         /* If try_byte returned EOF, magic[1] == (char) EOF.  */
1241     } else {
1242         magic[0] = (char)get_byte();
1243         magic[1] = (char)get_byte();
1244         imagic1 = 0; /* avoid lint warning */
1245     }
1246     method = -1;                 /* unknown yet */
1247     part_nb++;                   /* number of parts in gzip file */
1248     header_bytes = 0;
1249     last_member = RECORD_IO;
1250     /* assume multiple members in gzip file except for record oriented I/O */
1251
1252     if (memcmp(magic, GZIP_MAGIC, 2) == 0
1253         || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
1254
1255         method = (int)get_byte();
1256         if (method != DEFLATED) {
1257             fprintf(stderr,
1258                     "%s: %s: unknown method %d -- not supported\n",
1259                     progname, ifname, method);
1260             exit_code = ERROR;
1261             return -1;
1262         }
1263         work = unzip;
1264         flags  = (uch)get_byte();
1265
1266         if ((flags & ENCRYPTED) != 0) {
1267             fprintf(stderr,
1268                     "%s: %s is encrypted -- not supported\n",
1269                     progname, ifname);
1270             exit_code = ERROR;
1271             return -1;
1272         }
1273         if ((flags & CONTINUATION) != 0) {
1274             fprintf(stderr,
1275                     "%s: %s is a a multi-part gzip file -- not supported\n",
1276                     progname, ifname);
1277             exit_code = ERROR;
1278             if (force <= 1) return -1;
1279         }
1280         if ((flags & RESERVED) != 0) {
1281             fprintf(stderr,
1282                     "%s: %s has flags 0x%x -- not supported\n",
1283                     progname, ifname, flags);
1284             exit_code = ERROR;
1285             if (force <= 1) return -1;
1286         }
1287         stamp  = (ulg)get_byte();
1288         stamp |= ((ulg)get_byte()) << 8;
1289         stamp |= ((ulg)get_byte()) << 16;
1290         stamp |= ((ulg)get_byte()) << 24;
1291         if (stamp != 0 && !no_time) time_stamp = stamp;
1292
1293         (void)get_byte();  /* Ignore extra flags for the moment */
1294         (void)get_byte();  /* Ignore OS type for the moment */
1295
1296         if ((flags & CONTINUATION) != 0) {
1297             unsigned part = (unsigned)get_byte();
1298             part |= ((unsigned)get_byte())<<8;
1299             if (verbose) {
1300                 fprintf(stderr,"%s: %s: part number %u\n",
1301                         progname, ifname, part);
1302             }
1303         }
1304         if ((flags & EXTRA_FIELD) != 0) {
1305             unsigned len = (unsigned)get_byte();
1306             len |= ((unsigned)get_byte())<<8;
1307             if (verbose) {
1308                 fprintf(stderr,"%s: %s: extra field of %u bytes ignored\n",
1309                         progname, ifname, len);
1310             }
1311             while (len--) (void)get_byte();
1312         }
1313
1314         /* Get original file name if it was truncated */
1315         if ((flags & ORIG_NAME) != 0) {
1316             if (no_name || (to_stdout && !list) || part_nb > 1) {
1317                 /* Discard the old name */
1318                 char c; /* dummy used for NeXTstep 3.0 cc optimizer bug */
1319                 do {c=get_byte();} while (c != 0);
1320             } else {
1321                 /* Copy the base name. Keep a directory prefix intact. */
1322                 char *p = base_name (ofname);
1323                 char *base = p;
1324                 char *base2;
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                 base2 = base_name (base);
1333                 strcpy(base, base2);
1334                 /* If necessary, adapt the name to local OS conventions: */
1335                 if (!list) {
1336                    MAKE_LEGAL_NAME(base);
1337                    if (base) list=0; /* avoid warning about unused variable */
1338                 }
1339             } /* no_name || to_stdout */
1340         } /* ORIG_NAME */
1341
1342         /* Discard file comment if any */
1343         if ((flags & COMMENT) != 0) {
1344             while (get_char() != 0) /* null */ ;
1345         }
1346         if (part_nb == 1) {
1347             header_bytes = inptr + 2*sizeof(long); /* include crc and size */
1348         }
1349
1350     } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
1351             && memcmp((char*)inbuf, PKZIP_MAGIC, 4) == 0) {
1352         /* To simplify the code, we support a zip file when alone only.
1353          * We are thus guaranteed that the entire local header fits in inbuf.
1354          */
1355         inptr = 0;
1356         work = unzip;
1357         if (check_zipfile(in) != OK) return -1;
1358         /* check_zipfile may get ofname from the local header */
1359         last_member = 1;
1360
1361     } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
1362         work = unpack;
1363         method = PACKED;
1364
1365     } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {
1366         work = unlzw;
1367         method = COMPRESSED;
1368         last_member = 1;
1369
1370     } else if (memcmp(magic, LZH_MAGIC, 2) == 0) {
1371         work = unlzh;
1372         method = LZHED;
1373         last_member = 1;
1374
1375     } else if (force && to_stdout && !list) { /* pass input unchanged */
1376         method = STORED;
1377         work = copy;
1378         inptr = 0;
1379         last_member = 1;
1380     }
1381     if (method >= 0) return method;
1382
1383     if (part_nb == 1) {
1384         fprintf(stderr, "\n%s: %s: not in gzip format\n", progname, ifname);
1385         exit_code = ERROR;
1386         return -1;
1387     } else {
1388         if (magic[0] == 0)
1389           {
1390             int inbyte;
1391             for (inbyte = imagic1;  inbyte == 0;  inbyte = try_byte ())
1392               continue;
1393             if (inbyte == EOF)
1394               {
1395                 if (verbose)
1396                   WARN ((stderr, "\n%s: %s: decompression OK, trailing zero bytes ignored\n",
1397                          progname, ifname));
1398                 return -3;
1399               }
1400           }
1401
1402         WARN((stderr, "\n%s: %s: decompression OK, trailing garbage ignored\n",
1403               progname, ifname));
1404         return -2;
1405     }
1406 }
1407
1408 /* ========================================================================
1409  * Display the characteristics of the compressed file.
1410  * If the given method is < 0, display the accumulated totals.
1411  * IN assertions: time_stamp, header_bytes and ifile_size are initialized.
1412  */
1413 local void do_list(ifd, method)
1414     int ifd;     /* input file descriptor */
1415     int method;  /* compression method */
1416 {
1417     ulg crc;  /* original crc */
1418     static int first_time = 1;
1419     static char* methods[MAX_METHODS] = {
1420         "store",  /* 0 */
1421         "compr",  /* 1 */
1422         "pack ",  /* 2 */
1423         "lzh  ",  /* 3 */
1424         "", "", "", "", /* 4 to 7 reserved */
1425         "defla"}; /* 8 */
1426     char *date;
1427     int positive_off_t_width = 1;
1428     off_t o;
1429
1430     for (o = OFF_T_MAX;  9 < o;  o /= 10) {
1431         positive_off_t_width++;
1432     }
1433
1434     if (first_time && method >= 0) {
1435         first_time = 0;
1436         if (verbose)  {
1437             printf("method  crc     date  time  ");
1438         }
1439         if (!quiet) {
1440             printf("%*.*s %*.*s  ratio uncompressed_name\n",
1441                    positive_off_t_width, positive_off_t_width, "compressed",
1442                    positive_off_t_width, positive_off_t_width, "uncompressed");
1443         }
1444     } else if (method < 0) {
1445         if (total_in <= 0 || total_out <= 0) return;
1446         if (verbose) {
1447             printf("                            ");
1448         }
1449         if (verbose || !quiet) {
1450             fprint_off(stdout, total_in, positive_off_t_width);
1451             printf(" ");
1452             fprint_off(stdout, total_out, positive_off_t_width);
1453             printf(" ");
1454         }
1455         display_ratio(total_out-(total_in-header_bytes), total_out, stdout);
1456         /* header_bytes is not meaningful but used to ensure the same
1457          * ratio if there is a single file.
1458          */
1459         printf(" (totals)\n");
1460         return;
1461     }
1462     crc = (ulg)~0; /* unknown */
1463     bytes_out = -1L;
1464     bytes_in = ifile_size;
1465
1466 #if RECORD_IO == 0
1467     if (method == DEFLATED && !last_member) {
1468         /* Get the crc and uncompressed size for gzip'ed (not zip'ed) files.
1469          * If the lseek fails, we could use read() to get to the end, but
1470          * --list is used to get quick results.
1471          * Use "gunzip < foo.gz | wc -c" to get the uncompressed size if
1472          * you are not concerned about speed.
1473          */
1474         bytes_in = lseek(ifd, (off_t)(-8), SEEK_END);
1475         if (bytes_in != -1L) {
1476             uch buf[8];
1477             bytes_in += 8L;
1478             if (read(ifd, (char*)buf, sizeof(buf)) != sizeof(buf)) {
1479                 read_error();
1480             }
1481             crc       = LG(buf);
1482             bytes_out = LG(buf+4);
1483         }
1484     }
1485 #endif /* RECORD_IO */
1486     date = ctime((time_t*)&time_stamp) + 4; /* skip the day of the week */
1487     date[12] = '\0';               /* suppress the 1/100sec and the year */
1488     if (verbose) {
1489         printf("%5s %08lx %11s ", methods[method], crc, date);
1490     }
1491     fprint_off(stdout, bytes_in, positive_off_t_width);
1492     printf(" ");
1493     fprint_off(stdout, bytes_out, positive_off_t_width);
1494     printf(" ");
1495     if (bytes_in  == -1L) {
1496         total_in = -1L;
1497         bytes_in = bytes_out = header_bytes = 0;
1498     } else if (total_in >= 0) {
1499         total_in  += bytes_in;
1500     }
1501     if (bytes_out == -1L) {
1502         total_out = -1L;
1503         bytes_in = bytes_out = header_bytes = 0;
1504     } else if (total_out >= 0) {
1505         total_out += bytes_out;
1506     }
1507     display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out, stdout);
1508     printf(" %s\n", ofname);
1509 }
1510
1511 /* ========================================================================
1512  * Return true if the two stat structures correspond to the same file.
1513  */
1514 local int same_file(stat1, stat2)
1515     struct stat *stat1;
1516     struct stat *stat2;
1517 {
1518     return stat1->st_ino   == stat2->st_ino
1519         && stat1->st_dev   == stat2->st_dev
1520 #ifdef NO_ST_INO
1521         /* Can't rely on st_ino and st_dev, use other fields: */
1522         && stat1->st_mode  == stat2->st_mode
1523         && stat1->st_uid   == stat2->st_uid
1524         && stat1->st_gid   == stat2->st_gid
1525         && stat1->st_size  == stat2->st_size
1526         && stat1->st_atime == stat2->st_atime
1527         && stat1->st_mtime == stat2->st_mtime
1528         && stat1->st_ctime == stat2->st_ctime
1529 #endif
1530             ;
1531 }
1532
1533 /* ========================================================================
1534  * Return true if a file name is ambiguous because the operating system
1535  * truncates file names.
1536  */
1537 local int name_too_long(name, statb)
1538     char *name;           /* file name to check */
1539     struct stat *statb;   /* stat buf for this file name */
1540 {
1541     int s = strlen(name);
1542     char c = name[s-1];
1543     struct stat tstat; /* stat for truncated name */
1544     int res;
1545
1546     tstat = *statb;      /* Just in case OS does not fill all fields */
1547     name[s-1] = '\0';
1548     res = stat(name, &tstat) == 0 && same_file(statb, &tstat);
1549     name[s-1] = c;
1550     Trace((stderr, " too_long(%s) => %d\n", name, res));
1551     return res;
1552 }
1553
1554 /* ========================================================================
1555  * Shorten the given name by one character, or replace a .tar extension
1556  * with .tgz. Truncate the last part of the name which is longer than
1557  * MIN_PART characters: 1234.678.012.gz -> 123.678.012.gz. If the name
1558  * has only parts shorter than MIN_PART truncate the longest part.
1559  * For decompression, just remove the last character of the name.
1560  *
1561  * IN assertion: for compression, the suffix of the given name is z_suffix.
1562  */
1563 local void shorten_name(name)
1564     char *name;
1565 {
1566     int len;                 /* length of name without z_suffix */
1567     char *trunc = NULL;      /* character to be truncated */
1568     int plen;                /* current part length */
1569     int min_part = MIN_PART; /* current minimum part length */
1570     char *p;
1571
1572     len = strlen(name);
1573     if (decompress) {
1574         if (len <= 1) error("name too short");
1575         name[len-1] = '\0';
1576         return;
1577     }
1578     p = get_suffix(name);
1579     if (p == NULL) error("can't recover suffix\n");
1580     *p = '\0';
1581     save_orig_name = 1;
1582
1583     /* compress 1234567890.tar to 1234567890.tgz */
1584     if (len > 4 && strequ(p-4, ".tar")) {
1585         strcpy(p-4, ".tgz");
1586         return;
1587     }
1588     /* Try keeping short extensions intact:
1589      * 1234.678.012.gz -> 123.678.012.gz
1590      */
1591     do {
1592         p = strrchr(name, PATH_SEP);
1593         p = p ? p+1 : name;
1594         while (*p) {
1595             plen = strcspn(p, PART_SEP);
1596             p += plen;
1597             if (plen > min_part) trunc = p-1;
1598             if (*p) p++;
1599         }
1600     } while (trunc == NULL && --min_part != 0);
1601
1602     if (trunc != NULL) {
1603         do {
1604             trunc[0] = trunc[1];
1605         } while (*trunc++);
1606         trunc--;
1607     } else {
1608         trunc = strrchr(name, PART_SEP[0]);
1609         if (trunc == NULL) error("internal error in shorten_name");
1610         if (trunc[1] == '\0') trunc--; /* force truncation */
1611     }
1612     strcpy(trunc, z_suffix);
1613 }
1614
1615 /* ========================================================================
1616  * If compressing to a file, check if ofname is not ambiguous
1617  * because the operating system truncates names. Otherwise, generate
1618  * a new ofname and save the original name in the compressed file.
1619  * If the compressed file already exists, ask for confirmation.
1620  *    The check for name truncation is made dynamically, because different
1621  * file systems on the same OS might use different truncation rules (on SVR4
1622  * s5 truncates to 14 chars and ufs does not truncate).
1623  *    This function returns -1 if the file must be skipped, and
1624  * updates save_orig_name if necessary.
1625  * IN assertions: save_orig_name is already set if ofname has been
1626  * already truncated because of NO_MULTIPLE_DOTS. The input file has
1627  * already been open and istat is set.
1628  */
1629 local int check_ofname()
1630 {
1631     struct stat ostat; /* stat for ofname */
1632
1633 #ifdef ENAMETOOLONG
1634     /* Check for strictly conforming Posix systems (which return ENAMETOOLONG
1635      * instead of silently truncating filenames).
1636      */
1637     errno = 0;
1638     while (stat(ofname, &ostat) != 0) {
1639         if (errno != ENAMETOOLONG) return 0; /* ofname does not exist */
1640         shorten_name(ofname);
1641     }
1642 #else
1643     if (stat(ofname, &ostat) != 0) return 0;
1644 #endif
1645     /* Check for name truncation on existing file. Do this even on systems
1646      * defining ENAMETOOLONG, because on most systems the strict Posix
1647      * behavior is disabled by default (silent name truncation allowed).
1648      */
1649     if (!decompress && name_too_long(ofname, &ostat)) {
1650         shorten_name(ofname);
1651         if (stat(ofname, &ostat) != 0) return 0;
1652     }
1653
1654     /* Check that the input and output files are different (could be
1655      * the same by name truncation or links).
1656      */
1657     if (same_file(&istat, &ostat)) {
1658         if (strequ(ifname, ofname)) {
1659             fprintf(stderr, "%s: %s: cannot %scompress onto itself\n",
1660                     progname, ifname, decompress ? "de" : "");
1661         } else {
1662             fprintf(stderr, "%s: %s and %s are the same file\n",
1663                     progname, ifname, ofname);
1664         }
1665         exit_code = ERROR;
1666         return ERROR;
1667     }
1668     /* Ask permission to overwrite the existing file */
1669     if (!force) {
1670         int ok = 0;
1671         fprintf(stderr, "%s: %s already exists;", progname, ofname);
1672         if (foreground && isatty(fileno(stdin))) {
1673             fprintf(stderr, " do you wish to overwrite (y or n)? ");
1674             fflush(stderr);
1675             ok = yesno();
1676         }
1677         if (!ok) {
1678             fprintf(stderr, "\tnot overwritten\n");
1679             if (exit_code == OK) exit_code = WARNING;
1680             return ERROR;
1681         }
1682     }
1683     if (xunlink (ofname)) {
1684         progerror(ofname);
1685         return ERROR;
1686     }
1687     return OK;
1688 }
1689
1690
1691 #ifndef NO_UTIME
1692 /* ========================================================================
1693  * Set the access and modification times from the given stat buffer.
1694  */
1695 local void reset_times (name, statb)
1696     char *name;
1697     struct stat *statb;
1698 {
1699     struct utimbuf      timep;
1700
1701     /* Copy the time stamp */
1702     timep.actime  = statb->st_atime;
1703     timep.modtime = statb->st_mtime;
1704
1705     /* Some systems (at least OS/2) do not support utime on directories */
1706     if (utime(name, &timep) && !S_ISDIR(statb->st_mode)) {
1707         int e = errno;
1708         WARN((stderr, "%s: ", progname));
1709         if (!quiet) {
1710             errno = e;
1711             perror(ofname);
1712         }
1713     }
1714 }
1715 #endif
1716
1717
1718 /* ========================================================================
1719  * Copy modes, times, ownership from input file to output file.
1720  * IN assertion: to_stdout is false.
1721  */
1722 local void copy_stat(ifstat)
1723     struct stat *ifstat;
1724 {
1725 #ifndef NO_UTIME
1726     if (decompress && time_stamp != 0 && ifstat->st_mtime != time_stamp) {
1727         ifstat->st_mtime = time_stamp;
1728         if (verbose > 1) {
1729             fprintf(stderr, "%s: time stamp restored\n", ofname);
1730         }
1731     }
1732     reset_times(ofname, ifstat);
1733 #endif
1734     /* Copy the protection modes */
1735     if (fchmod(ofd, ifstat->st_mode & 07777)) {
1736         int e = errno;
1737         WARN((stderr, "%s: ", progname));
1738         if (!quiet) {
1739             errno = e;
1740             perror(ofname);
1741         }
1742     }
1743 #ifndef NO_CHOWN
1744     (void) fchown(ofd, ifstat->st_uid, ifstat->st_gid);  /* Copy ownership */
1745 #endif
1746     remove_ofname = 0;
1747     /* It's now safe to remove the input file: */
1748     if (xunlink (ifname)) {
1749         int e = errno;
1750         WARN((stderr, "%s: ", progname));
1751         if (!quiet) {
1752             errno = e;
1753             perror(ifname);
1754         }
1755     }
1756 }
1757
1758 #ifndef NO_DIR
1759
1760 /* ========================================================================
1761  * Recurse through the given directory. This code is taken from ncompress.
1762  */
1763 local void treat_dir(dir)
1764     char *dir;
1765 {
1766     struct dirent *dp;
1767     DIR      *dirp;
1768     char     nbuf[MAX_PATH_LEN];
1769     int      len;
1770
1771     dirp = opendir(dir);
1772     
1773     if (dirp == NULL) {
1774         progerror(dir);
1775         return ;
1776     }
1777     /*
1778      ** WARNING: the following algorithm could occasionally cause
1779      ** compress to produce error warnings of the form "<filename>.gz
1780      ** already has .gz suffix - ignored". This occurs when the
1781      ** .gz output file is inserted into the directory below
1782      ** readdir's current pointer.
1783      ** These warnings are harmless but annoying, so they are suppressed
1784      ** with option -r (except when -v is on). An alternative
1785      ** to allowing this would be to store the entire directory
1786      ** list in memory, then compress the entries in the stored
1787      ** list. Given the depth-first recursive algorithm used here,
1788      ** this could use up a tremendous amount of memory. I don't
1789      ** think it's worth it. -- Dave Mack
1790      ** (An other alternative might be two passes to avoid depth-first.)
1791      */
1792     
1793     while ((errno = 0, dp = readdir(dirp)) != NULL) {
1794
1795         if (strequ(dp->d_name,".") || strequ(dp->d_name,"..")) {
1796             continue;
1797         }
1798         len = strlen(dir);
1799         if (len + NAMLEN(dp) + 1 < MAX_PATH_LEN - 1) {
1800             strcpy(nbuf,dir);
1801             if (len != 0 /* dir = "" means current dir on Amiga */
1802 #ifdef PATH_SEP2
1803                 && dir[len-1] != PATH_SEP2
1804 #endif
1805 #ifdef PATH_SEP3
1806                 && dir[len-1] != PATH_SEP3
1807 #endif
1808             ) {
1809                 nbuf[len++] = PATH_SEP;
1810             }
1811             strcpy(nbuf+len, dp->d_name);
1812             treat_file(nbuf);
1813         } else {
1814             fprintf(stderr,"%s: %s/%s: pathname too long\n",
1815                     progname, dir, dp->d_name);
1816             exit_code = ERROR;
1817         }
1818     }
1819     if (errno != 0)
1820         progerror(dir);
1821     if (CLOSEDIR(dirp) != 0)
1822         progerror(dir);
1823 }
1824 #endif /* ? NO_DIR */
1825
1826 /* ========================================================================
1827  * Free all dynamically allocated variables and exit with the given code.
1828  */
1829 local void do_exit(exitcode)
1830     int exitcode;
1831 {
1832     static int in_exit = 0;
1833
1834     if (in_exit) exit(exitcode);
1835     in_exit = 1;
1836     if (env != NULL)  free(env),  env  = NULL;
1837     if (args != NULL) free((char*)args), args = NULL;
1838     FREE(inbuf);
1839     FREE(outbuf);
1840     FREE(d_buf);
1841     FREE(window);
1842 #ifndef MAXSEG_64K
1843     FREE(tab_prefix);
1844 #else
1845     FREE(tab_prefix0);
1846     FREE(tab_prefix1);
1847 #endif
1848     exit(exitcode);
1849 }
1850
1851 /* ========================================================================
1852  * Signal and error handler.
1853  */
1854 RETSIGTYPE abort_gzip()
1855 {
1856    if (remove_ofname) {
1857        close(ofd);
1858        xunlink (ofname);
1859    }
1860    do_exit(ERROR);
1861 }