New upstream version 1.9
[debian/gzip] / gzip.c
1 /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
2
3    Copyright (C) 1999, 2001-2002, 2006-2007, 2009-2018 Free Software
4    Foundation, Inc.
5    Copyright (C) 1992-1993 Jean-loup Gailly
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3, or (at your option)
10    any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software Foundation,
19    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
20
21 /*
22  * The unzip code was written and put in the public domain by Mark Adler.
23  * Portions of the lzw code are derived from the public domain 'compress'
24  * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
25  * Ken Turkowski, Dave Mack and Peter Jannesen.
26  *
27  * See the license_msg below and the file COPYING for the software license.
28  * See the file algorithm.doc for the compression algorithms and file formats.
29  */
30
31 static char const *const license_msg[] = {
32 "Copyright (C) 2017 Free Software Foundation, Inc.",
33 "Copyright (C) 1993 Jean-loup Gailly.",
34 "This is free software.  You may redistribute copies of it under the terms of",
35 "the GNU General Public License <https://www.gnu.org/licenses/gpl.html>.",
36 "There is NO WARRANTY, to the extent permitted by law.",
37 0};
38
39 /* Compress files with zip algorithm and 'compress' interface.
40  * See help() function below for all options.
41  * Outputs:
42  *        file.gz:   compressed file with same mode, owner, and utimes
43  *     or stdout with -c option or if stdin used as input.
44  * If the output file name had to be truncated, the original name is kept
45  * in the compressed file.
46  * On MSDOS, file.tmp -> file.tmz.
47  *
48  * Using gz on MSDOS would create too many file name conflicts. For
49  * example, foo.txt -> foo.tgz (.tgz must be reserved as shorthand for
50  * tar.gz). Similarly, foo.dir and foo.doc would both be mapped to foo.dgz.
51  * I also considered 12345678.txt -> 12345txt.gz but this truncates the name
52  * too heavily. There is no ideal solution given the MSDOS 8+3 limitation.
53  *
54  * For the meaning of all compilation flags, see comments in Makefile.in.
55  */
56
57 #include <config.h>
58 #include <ctype.h>
59 #include <sys/types.h>
60 #include <signal.h>
61 #include <stdbool.h>
62 #include <stddef.h>
63 #include <sys/stat.h>
64 #include <errno.h>
65
66 #include "tailor.h"
67 #include "gzip.h"
68 #include "intprops.h"
69 #include "lzw.h"
70 #include "revision.h"
71 #include "timespec.h"
72
73 #include "dirname.h"
74 #include "dosname.h"
75 #include "fcntl--.h"
76 #include "getopt.h"
77 #include "ignore-value.h"
78 #include "stat-time.h"
79 #include "version.h"
80 #include "xalloc.h"
81 #include "yesno.h"
82
83                 /* configuration */
84
85 #include <limits.h>
86 #include <unistd.h>
87 #include <stdlib.h>
88 #include <errno.h>
89
90 #ifndef NO_DIR
91 # define NO_DIR 0
92 #endif
93 #if !NO_DIR
94 # include <dirent.h>
95 # include <savedir.h>
96 #endif
97
98 #ifndef NO_UTIME
99 #  include <utimens.h>
100 #endif
101
102 #ifndef MAX_PATH_LEN
103 #  define MAX_PATH_LEN   1024 /* max pathname length */
104 #endif
105
106 #ifndef SEEK_END
107 #  define SEEK_END 2
108 #endif
109
110 #ifndef CHAR_BIT
111 #  define CHAR_BIT 8
112 #endif
113
114 #ifdef off_t
115   off_t lseek (int fd, off_t offset, int whence);
116 #endif
117
118 #ifndef OFF_T_MAX
119 # define OFF_T_MAX TYPE_MAXIMUM (off_t)
120 #endif
121
122 /* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is
123    present.  */
124 #ifndef SA_NOCLDSTOP
125 # define SA_NOCLDSTOP 0
126 # define sigprocmask(how, set, oset) /* empty */
127 # define sigset_t int
128 # if ! HAVE_SIGINTERRUPT
129 #  define siginterrupt(sig, flag) /* empty */
130 # endif
131 #endif
132
133 #ifndef HAVE_WORKING_O_NOFOLLOW
134 # define HAVE_WORKING_O_NOFOLLOW 0
135 #endif
136
137 /* Separator for file name parts (see shorten_name()) */
138 #ifdef NO_MULTIPLE_DOTS
139 #  define PART_SEP "-"
140 #else
141 #  define PART_SEP "."
142 #endif
143
144                 /* global buffers */
145
146 DECLARE(uch, inbuf,  INBUFSIZ +INBUF_EXTRA);
147 DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
148 DECLARE(ush, d_buf,  DIST_BUFSIZE);
149 DECLARE(uch, window, 2L*WSIZE);
150 #ifndef MAXSEG_64K
151     DECLARE(ush, tab_prefix, 1L<<BITS);
152 #else
153     DECLARE(ush, tab_prefix0, 1L<<(BITS-1));
154     DECLARE(ush, tab_prefix1, 1L<<(BITS-1));
155 #endif
156
157                 /* local variables */
158
159 /* If true, pretend that standard input is a tty.  This option
160    is deliberately not documented, and only for testing.  */
161 static bool presume_input_tty;
162
163 /* If true, transfer output data to the output file's storage device
164    when supported.  Otherwise, if the system crashes around the time
165    gzip is run, the user might lose both input and output data.  See:
166    Pillai TS et al.  All file systems are not created equal: on the
167    complexity of crafting crash-consistent applications. OSDI'14. 2014:433-48.
168    https://www.usenix.org/conference/osdi14/technical-sessions/presentation/pillai */
169 static bool synchronous;
170
171 static int ascii = 0;        /* convert end-of-lines to local OS conventions */
172        int to_stdout = 0;    /* output to stdout (-c) */
173 static int decompress = 0;   /* decompress (-d) */
174 static int force = 0;        /* don't ask questions, compress links (-f) */
175 static int keep = 0;         /* keep (don't delete) input files */
176 static int no_name = -1;     /* don't save or restore the original file name */
177 static int no_time = -1;     /* don't save or restore the original file time */
178 static int recursive = 0;    /* recurse through directories (-r) */
179 static int list = 0;         /* list the file contents (-l) */
180        int verbose = 0;      /* be verbose (-v) */
181        int quiet = 0;        /* be very quiet (-q) */
182 static int do_lzw = 0;       /* generate output compatible with old compress (-Z) */
183        int test = 0;         /* test .gz file integrity */
184 static int foreground = 0;   /* set if program run in foreground */
185        char *program_name;   /* program name */
186        int maxbits = BITS;   /* max bits per code for LZW */
187        int method = DEFLATED;/* compression method */
188        int level = 6;        /* compression level */
189        int exit_code = OK;   /* program exit code */
190        int save_orig_name;   /* set if original name must be saved */
191 static int last_member;      /* set for .zip and .Z files */
192 static int part_nb;          /* number of parts in .gz file */
193        off_t ifile_size;      /* input file size, -1 for devices (debug only) */
194 static char *env;            /* contents of GZIP env variable */
195 static char const *z_suffix; /* default suffix (can be set with --suffix) */
196 static size_t z_len;         /* strlen(z_suffix) */
197
198 /* The original timestamp (modification time).  If the original is
199    unknown, TIME_STAMP.tv_nsec is negative.  If the original is
200    greater than struct timespec range, TIME_STAMP is the maximal
201    struct timespec value; this can happen on hosts with 32-bit signed
202    time_t because the gzip format's MTIME is 32-bit unsigned.
203    The original cannot be less than struct timespec range.  */
204 struct timespec time_stamp;
205
206 /* The set of signals that are caught.  */
207 static sigset_t caught_signals;
208
209 /* If nonzero then exit with status WARNING, rather than with the usual
210    signal status, on receipt of a signal with this value.  This
211    suppresses a "Broken Pipe" message with some shells.  */
212 static int volatile exiting_signal;
213
214 /* If nonnegative, close this file descriptor and unlink ofname on error.  */
215 static int volatile remove_ofname_fd = -1;
216
217 static bool stdin_was_read;
218
219 off_t bytes_in;             /* number of input bytes */
220 off_t bytes_out;            /* number of output bytes */
221 static off_t total_in;      /* input bytes for all files */
222 static off_t total_out;     /* output bytes for all files */
223 char ifname[MAX_PATH_LEN]; /* input file name */
224 char ofname[MAX_PATH_LEN]; /* output file name */
225 static char dfname[MAX_PATH_LEN]; /* name of dir containing output file */
226 static struct stat istat;         /* status for input file */
227 int  ifd;                  /* input file descriptor */
228 int  ofd;                  /* output file descriptor */
229 static int dfd = -1;       /* output directory file descriptor */
230 unsigned insize;           /* valid bytes in inbuf */
231 unsigned inptr;            /* index of next byte to be processed in inbuf */
232 unsigned outcnt;           /* bytes in output buffer */
233 int rsync = 0;             /* make ryncable chunks */
234
235 static int handled_sig[] =
236   {
237     /* SIGINT must be first, as 'foreground' depends on it.  */
238     SIGINT
239
240 #ifdef SIGHUP
241     , SIGHUP
242 #endif
243 #if SIGPIPE
244     , SIGPIPE
245 #endif
246 #ifdef SIGTERM
247     , SIGTERM
248 #endif
249 #ifdef SIGXCPU
250     , SIGXCPU
251 #endif
252 #ifdef SIGXFSZ
253     , SIGXFSZ
254 #endif
255   };
256
257 /* For long options that have no equivalent short option, use a
258    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
259 enum
260 {
261   PRESUME_INPUT_TTY_OPTION = CHAR_MAX + 1,
262   RSYNCABLE_OPTION,
263   SYNCHRONOUS_OPTION,
264
265   /* A value greater than all valid long options, used as a flag to
266      distinguish options derived from the GZIP environment variable.  */
267   ENV_OPTION
268 };
269
270 static char const shortopts[] = "ab:cdfhH?klLmMnNqrS:tvVZ123456789";
271
272 static const struct option longopts[] =
273 {
274  /* { name  has_arg  *flag  val } */
275     {"ascii",      0, 0, 'a'}, /* ascii text mode */
276     {"to-stdout",  0, 0, 'c'}, /* write output on standard output */
277     {"stdout",     0, 0, 'c'}, /* write output on standard output */
278     {"decompress", 0, 0, 'd'}, /* decompress */
279     {"uncompress", 0, 0, 'd'}, /* decompress */
280  /* {"encrypt",    0, 0, 'e'},    encrypt */
281     {"force",      0, 0, 'f'}, /* force overwrite of output file */
282     {"help",       0, 0, 'h'}, /* give help */
283  /* {"pkzip",      0, 0, 'k'},    force output in pkzip format */
284     {"keep",       0, 0, 'k'}, /* keep (don't delete) input files */
285     {"list",       0, 0, 'l'}, /* list .gz file contents */
286     {"license",    0, 0, 'L'}, /* display software license */
287     {"no-name",    0, 0, 'n'}, /* don't save or restore original name & time */
288     {"name",       0, 0, 'N'}, /* save or restore original name & time */
289     {"-presume-input-tty", no_argument, NULL, PRESUME_INPUT_TTY_OPTION},
290     {"quiet",      0, 0, 'q'}, /* quiet mode */
291     {"silent",     0, 0, 'q'}, /* quiet mode */
292     {"synchronous",0, 0, SYNCHRONOUS_OPTION},
293     {"recursive",  0, 0, 'r'}, /* recurse through directories */
294     {"suffix",     1, 0, 'S'}, /* use given suffix instead of .gz */
295     {"test",       0, 0, 't'}, /* test compressed file integrity */
296     {"verbose",    0, 0, 'v'}, /* verbose mode */
297     {"version",    0, 0, 'V'}, /* display version number */
298     {"fast",       0, 0, '1'}, /* compress faster */
299     {"best",       0, 0, '9'}, /* compress better */
300     {"lzw",        0, 0, 'Z'}, /* make output compatible with old compress */
301     {"bits",       1, 0, 'b'}, /* max number of bits per code (implies -Z) */
302     {"rsyncable",  0, 0, RSYNCABLE_OPTION}, /* make rsync-friendly archive */
303     { 0, 0, 0, 0 }
304 };
305
306 /* local functions */
307
308 local noreturn void try_help (void);
309 local void help         (void);
310 local void license      (void);
311 local void version      (void);
312 local int input_eof     (void);
313 local void treat_stdin  (void);
314 local void treat_file   (char *iname);
315 local int create_outfile (void);
316 local char *get_suffix  (char *name);
317 local int  open_input_file (char *iname, struct stat *sbuf);
318 local void discard_input_bytes (size_t nbytes, unsigned int flags);
319 local int  make_ofname  (void);
320 local void shorten_name  (char *name);
321 local int  get_method   (int in);
322 local void do_list      (int ifd, int method);
323 local int  check_ofname (void);
324 local void copy_stat    (struct stat *ifstat);
325 local void install_signal_handlers (void);
326 local void remove_output_file (void);
327 local RETSIGTYPE abort_gzip_signal (int);
328 local noreturn void do_exit (int exitcode);
329 static void finish_out (void);
330       int main          (int argc, char **argv);
331 static int (*work) (int infile, int outfile) = zip; /* function to call */
332
333 #if ! NO_DIR
334 local void treat_dir    (int fd, char *dir);
335 #endif
336
337 #define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
338
339 static void
340 try_help ()
341 {
342   fprintf (stderr, "Try `%s --help' for more information.\n",
343            program_name);
344   do_exit (ERROR);
345 }
346
347 /* ======================================================================== */
348 local void help()
349 {
350     static char const* const help_msg[] = {
351  "Compress or uncompress FILEs (by default, compress FILES in-place).",
352  "",
353  "Mandatory arguments to long options are mandatory for short options too.",
354  "",
355 #if O_BINARY
356  "  -a, --ascii       ascii text; convert end-of-line using local conventions",
357 #endif
358  "  -c, --stdout      write on standard output, keep original files unchanged",
359  "  -d, --decompress  decompress",
360 /*  -e, --encrypt     encrypt */
361  "  -f, --force       force overwrite of output file and compress links",
362  "  -h, --help        give this help",
363 /*  -k, --pkzip       force output in pkzip format */
364  "  -k, --keep        keep (don't delete) input files",
365  "  -l, --list        list compressed file contents",
366  "  -L, --license     display software license",
367 #ifdef UNDOCUMENTED
368  "  -m                do not save or restore the original modification time",
369  "  -M, --time        save or restore the original modification time",
370 #endif
371  "  -n, --no-name     do not save or restore the original name and timestamp",
372  "  -N, --name        save or restore the original name and timestamp",
373  "  -q, --quiet       suppress all warnings",
374 #if ! NO_DIR
375  "  -r, --recursive   operate recursively on directories",
376 #endif
377  "      --rsyncable   make rsync-friendly archive",
378  "  -S, --suffix=SUF  use suffix SUF on compressed files",
379  "      --synchronous synchronous output (safer if system crashes, but slower)",
380  "  -t, --test        test compressed file integrity",
381  "  -v, --verbose     verbose mode",
382  "  -V, --version     display version number",
383  "  -1, --fast        compress faster",
384  "  -9, --best        compress better",
385 #ifdef LZW
386  "  -Z, --lzw         produce output compatible with old compress",
387  "  -b, --bits=BITS   max number of bits per code (implies -Z)",
388 #endif
389  "",
390  "With no FILE, or when FILE is -, read standard input.",
391  "",
392  "Report bugs to <bug-gzip@gnu.org>.",
393   0};
394     char const *const *p = help_msg;
395
396     printf ("Usage: %s [OPTION]... [FILE]...\n", program_name);
397     while (*p) printf ("%s\n", *p++);
398 }
399
400 /* ======================================================================== */
401 local void license()
402 {
403     char const *const *p = license_msg;
404
405     printf ("%s %s\n", program_name, Version);
406     while (*p) printf ("%s\n", *p++);
407 }
408
409 /* ======================================================================== */
410 local void version()
411 {
412     license ();
413     printf ("\n");
414     printf ("Written by Jean-loup Gailly.\n");
415 }
416
417 local void progerror (char const *string)
418 {
419     int e = errno;
420     fprintf (stderr, "%s: ", program_name);
421     errno = e;
422     perror(string);
423     exit_code = ERROR;
424 }
425
426 /* ======================================================================== */
427 int main (int argc, char **argv)
428 {
429     int file_count;     /* number of files to process */
430     size_t proglen;     /* length of program_name */
431     char **argv_copy;
432     int env_argc;
433     char **env_argv;
434
435     EXPAND(argc, argv); /* wild card expansion if necessary */
436
437     program_name = gzip_base_name (argv[0]);
438     proglen = strlen (program_name);
439
440     /* Suppress .exe for MSDOS and OS/2: */
441     if (4 < proglen && strequ (program_name + proglen - 4, ".exe"))
442       program_name[proglen - 4] = '\0';
443
444     /* Add options in GZIP environment variable if there is one */
445     argv_copy = argv;
446     env = add_envopt (&env_argc, &argv_copy, OPTIONS_VAR);
447     env_argv = env ? argv_copy : NULL;
448
449 #ifndef GNU_STANDARD
450 # define GNU_STANDARD 1
451 #endif
452 #if !GNU_STANDARD
453     /* For compatibility with old compress, use program name as an option.
454      * Unless you compile with -DGNU_STANDARD=0, this program will behave as
455      * gzip even if it is invoked under the name gunzip or zcat.
456      *
457      * Systems which do not support links can still use -d or -dc.
458      * Ignore an .exe extension for MSDOS and OS/2.
459      */
460     if (strncmp (program_name, "un",  2) == 0     /* ungzip, uncompress */
461         || strncmp (program_name, "gun", 3) == 0) /* gunzip */
462         decompress = 1;
463     else if (strequ (program_name + 1, "cat")     /* zcat, pcat, gcat */
464              || strequ (program_name, "gzcat"))   /* gzcat */
465         decompress = to_stdout = 1;
466 #endif
467
468     z_suffix = Z_SUFFIX;
469     z_len = strlen(z_suffix);
470
471     while (true) {
472         int optc;
473         int longind = -1;
474
475         if (env_argv)
476           {
477             if (env_argv[optind] && strequ (env_argv[optind], "--"))
478               optc = ENV_OPTION + '-';
479             else
480               {
481                 optc = getopt_long (env_argc, env_argv, shortopts, longopts,
482                                     &longind);
483                 if (0 <= optc)
484                   optc += ENV_OPTION;
485                 else
486                   {
487                     if (optind != env_argc)
488                       {
489                         fprintf (stderr,
490                                  ("%s: %s: non-option in "OPTIONS_VAR
491                                   " environment variable\n"),
492                                  program_name, env_argv[optind]);
493                         try_help ();
494                       }
495
496                     /* Wait until here before warning, so that GZIP='-q'
497                        doesn't warn.  */
498                     if (env_argc != 1 && !quiet)
499                       fprintf (stderr,
500                                ("%s: warning: "OPTIONS_VAR" environment variable"
501                                 " is deprecated; use an alias or script\n"),
502                                program_name);
503
504                     /* Start processing ARGC and ARGV instead.  */
505                     free (env_argv);
506                     env_argv = NULL;
507                     optind = 1;
508                     longind = -1;
509                   }
510               }
511           }
512
513         if (!env_argv)
514           optc = getopt_long (argc, argv, shortopts, longopts, &longind);
515         if (optc < 0)
516           break;
517
518         switch (optc) {
519         case 'a':
520             ascii = 1; break;
521         case 'b':
522             maxbits = atoi(optarg);
523             for (; *optarg; optarg++)
524               if (! ('0' <= *optarg && *optarg <= '9'))
525                 {
526                   fprintf (stderr, "%s: -b operand is not an integer\n",
527                            program_name);
528                   try_help ();
529                 }
530             break;
531         case 'c':
532             to_stdout = 1; break;
533         case 'd':
534             decompress = 1; break;
535         case 'f':
536             force++; break;
537         case 'h': case 'H':
538             help (); finish_out (); break;
539         case 'k':
540             keep = 1; break;
541         case 'l':
542             list = decompress = to_stdout = 1; break;
543         case 'L':
544             license (); finish_out (); break;
545         case 'm': /* undocumented, may change later */
546             no_time = 1; break;
547         case 'M': /* undocumented, may change later */
548             no_time = 0; break;
549         case 'n':
550         case 'n' + ENV_OPTION:
551             no_name = no_time = 1; break;
552         case 'N':
553         case 'N' + ENV_OPTION:
554             no_name = no_time = 0; break;
555         case PRESUME_INPUT_TTY_OPTION:
556             presume_input_tty = true; break;
557         case 'q':
558         case 'q' + ENV_OPTION:
559             quiet = 1; verbose = 0; break;
560         case 'r':
561 #if NO_DIR
562             fprintf (stderr, "%s: -r not supported on this system\n",
563                      program_name);
564             try_help ();
565 #else
566             recursive = 1;
567 #endif
568             break;
569
570         case RSYNCABLE_OPTION:
571         case RSYNCABLE_OPTION + ENV_OPTION:
572             rsync = 1;
573             break;
574         case 'S':
575 #ifdef NO_MULTIPLE_DOTS
576             if (*optarg == '.') optarg++;
577 #endif
578             z_len = strlen(optarg);
579             z_suffix = optarg;
580             break;
581         case SYNCHRONOUS_OPTION:
582             synchronous = true;
583             break;
584         case 't':
585             test = decompress = to_stdout = 1;
586             break;
587         case 'v':
588         case 'v' + ENV_OPTION:
589             verbose++; quiet = 0; break;
590         case 'V':
591             version (); finish_out (); break;
592         case 'Z':
593 #ifdef LZW
594             do_lzw = 1; break;
595 #else
596             fprintf(stderr, "%s: -Z not supported in this version\n",
597                     program_name);
598             try_help ();
599             break;
600 #endif
601         case '1' + ENV_OPTION:  case '2' + ENV_OPTION:  case '3' + ENV_OPTION:
602         case '4' + ENV_OPTION:  case '5' + ENV_OPTION:  case '6' + ENV_OPTION:
603         case '7' + ENV_OPTION:  case '8' + ENV_OPTION:  case '9' + ENV_OPTION:
604             optc -= ENV_OPTION;
605             FALLTHROUGH;
606         case '1':  case '2':  case '3':  case '4':
607         case '5':  case '6':  case '7':  case '8':  case '9':
608             level = optc - '0';
609             break;
610
611         default:
612             if (ENV_OPTION <= optc && optc != ENV_OPTION + '?')
613               {
614                 /* Output a diagnostic, since getopt_long didn't.  */
615                 fprintf (stderr, "%s: ", program_name);
616                 if (longind < 0)
617                   fprintf (stderr, "-%c: ", optc - ENV_OPTION);
618                 else
619                   fprintf (stderr, "--%s: ", longopts[longind].name);
620                 fprintf (stderr, ("option not valid in "OPTIONS_VAR
621                                   " environment variable\n"));
622               }
623             try_help ();
624         }
625     } /* loop on all arguments */
626
627     /* By default, save name and timestamp on compression but do not
628      * restore them on decompression.
629      */
630     if (no_time < 0) no_time = decompress;
631     if (no_name < 0) no_name = decompress;
632
633     file_count = argc - optind;
634
635 #if O_BINARY
636 #else
637     if (ascii && !quiet) {
638         fprintf(stderr, "%s: option --ascii ignored on this system\n",
639                 program_name);
640     }
641 #endif
642     if (z_len == 0 || z_len > MAX_SUFFIX) {
643         fprintf(stderr, "%s: invalid suffix '%s'\n", program_name, z_suffix);
644         do_exit(ERROR);
645     }
646
647     if (do_lzw && !decompress) work = lzw;
648
649     /* Allocate all global buffers (for DYN_ALLOC option) */
650     ALLOC(uch, inbuf,  INBUFSIZ +INBUF_EXTRA);
651     ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
652     ALLOC(ush, d_buf,  DIST_BUFSIZE);
653     ALLOC(uch, window, 2L*WSIZE);
654 #ifndef MAXSEG_64K
655     ALLOC(ush, tab_prefix, 1L<<BITS);
656 #else
657     ALLOC(ush, tab_prefix0, 1L<<(BITS-1));
658     ALLOC(ush, tab_prefix1, 1L<<(BITS-1));
659 #endif
660
661     exiting_signal = quiet ? SIGPIPE : 0;
662     install_signal_handlers ();
663
664     /* And get to work */
665     if (file_count != 0) {
666         if (to_stdout && !test && !list && (!decompress || !ascii)) {
667             SET_BINARY_MODE (STDOUT_FILENO);
668         }
669         while (optind < argc) {
670             treat_file(argv[optind++]);
671         }
672     } else {  /* Standard input */
673         treat_stdin();
674     }
675     if (stdin_was_read && close (STDIN_FILENO) != 0)
676       {
677         strcpy (ifname, "stdin");
678         read_error ();
679       }
680     if (list)
681       {
682         /* Output any totals, and check for output errors.  */
683         if (!quiet && 1 < file_count)
684           do_list (-1, -1);
685         if (fflush (stdout) != 0)
686           write_error ();
687       }
688     if (to_stdout
689         && ((synchronous
690              && fdatasync (STDOUT_FILENO) != 0 && errno != EINVAL)
691             || close (STDOUT_FILENO) != 0)
692         && errno != EBADF)
693       write_error ();
694     do_exit(exit_code);
695     return exit_code; /* just to avoid lint warning */
696 }
697
698 /* Return nonzero when at end of file on input.  */
699 local int
700 input_eof ()
701 {
702   if (!decompress || last_member)
703     return 1;
704
705   if (inptr == insize)
706     {
707       if (insize != INBUFSIZ || fill_inbuf (1) == EOF)
708         return 1;
709
710       /* Unget the char that fill_inbuf got.  */
711       inptr = 0;
712     }
713
714   return 0;
715 }
716
717 /* ========================================================================
718  * Compress or decompress stdin
719  */
720 local void treat_stdin()
721 {
722     if (!force && !list
723         && (presume_input_tty
724             || isatty (decompress ? STDIN_FILENO : STDOUT_FILENO))) {
725         /* Do not send compressed data to the terminal or read it from
726          * the terminal. We get here when user invoked the program
727          * without parameters, so be helpful. According to the GNU standards:
728          *
729          *   If there is one behavior you think is most useful when the output
730          *   is to a terminal, and another that you think is most useful when
731          *   the output is a file or a pipe, then it is usually best to make
732          *   the default behavior the one that is useful with output to a
733          *   terminal, and have an option for the other behavior.
734          *
735          * Here we use the --force option to get the other behavior.
736          */
737         if (! quiet)
738           fprintf (stderr,
739                    ("%s: compressed data not %s a terminal."
740                     " Use -f to force %scompression.\n"
741                     "For help, type: %s -h\n"),
742                    program_name,
743                    decompress ? "read from" : "written to",
744                    decompress ? "de" : "",
745                    program_name);
746         do_exit(ERROR);
747     }
748
749     if (decompress || !ascii) {
750       SET_BINARY_MODE (STDIN_FILENO);
751     }
752     if (!test && !list && (!decompress || !ascii)) {
753       SET_BINARY_MODE (STDOUT_FILENO);
754     }
755     strcpy(ifname, "stdin");
756     strcpy(ofname, "stdout");
757
758     /* Get the file's timestamp and size.  */
759     if (fstat (STDIN_FILENO, &istat) != 0)
760       {
761         progerror ("standard input");
762         do_exit (ERROR);
763       }
764     ifile_size = S_ISREG (istat.st_mode) ? istat.st_size : -1;
765     time_stamp.tv_nsec = -1;
766     if (!no_time || list)
767       {
768         if (S_ISREG (istat.st_mode))
769           time_stamp = get_stat_mtime (&istat);
770         else
771           gettime (&time_stamp);
772       }
773
774     clear_bufs(); /* clear input and output buffers */
775     to_stdout = 1;
776     part_nb = 0;
777     ifd = STDIN_FILENO;
778     stdin_was_read = true;
779
780     if (decompress) {
781         method = get_method(ifd);
782         if (method < 0) {
783             do_exit(exit_code); /* error message already emitted */
784         }
785     }
786     if (list) {
787         do_list(ifd, method);
788         return;
789     }
790
791     /* Actually do the compression/decompression. Loop over zipped members.
792      */
793     for (;;) {
794         if (work (STDIN_FILENO, STDOUT_FILENO) != OK)
795           return;
796
797         if (input_eof ())
798           break;
799
800         method = get_method(ifd);
801         if (method < 0) return; /* error message already emitted */
802         bytes_out = 0;            /* required for length check */
803     }
804
805     if (verbose) {
806         if (test) {
807             fprintf(stderr, " OK\n");
808
809         } else if (!decompress) {
810             display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
811             fprintf(stderr, "\n");
812 #ifdef DISPLAY_STDIN_RATIO
813         } else {
814             display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
815             fprintf(stderr, "\n");
816 #endif
817         }
818     }
819 }
820
821 static char const dot = '.';
822
823 /* True if the cached directory for calls to openat etc. is DIR, with
824    length DIRLEN.  DIR need not be null-terminated.  DIRLEN must be
825    less than MAX_PATH_LEN.  */
826 static bool
827 atdir_eq (char const *dir, ptrdiff_t dirlen)
828 {
829   if (dirlen == 0)
830     dir = &dot, dirlen = 1;
831   return memcmp (dfname, dir, dirlen) == 0 && !dfname[dirlen];
832 }
833
834 /* Set the directory used for calls to openat etc. to be the directory
835    DIR, with length DIRLEN.  DIR need not be null-terminated.
836    DIRLEN must be less than MAX_PATH_LEN.  Return a file descriptor for
837    the directory, or -1 if one could not be obtained.  */
838 static int
839 atdir_set (char const *dir, ptrdiff_t dirlen)
840 {
841   /* Don't bother opening directories on older systems that
842      lack openat and unlinkat.  It's not worth the porting hassle.  */
843   #if HAVE_OPENAT && HAVE_UNLINKAT
844     enum { try_opening_directories = true };
845   #else
846     enum { try_opening_directories = false };
847   #endif
848
849   if (try_opening_directories && ! atdir_eq (dir, dirlen))
850     {
851       if (0 <= dfd)
852         close (dfd);
853       if (dirlen == 0)
854         dir = &dot, dirlen = 1;
855       memcpy (dfname, dir, dirlen);
856       dfname[dirlen] = '\0';
857       dfd = open (dfname, O_SEARCH | O_DIRECTORY);
858     }
859
860   return dfd;
861 }
862
863 /* ========================================================================
864  * Compress or decompress the given file
865  */
866 local void treat_file(iname)
867     char *iname;
868 {
869     /* Accept "-" as synonym for stdin */
870     if (strequ(iname, "-")) {
871         int cflag = to_stdout;
872         treat_stdin();
873         to_stdout = cflag;
874         return;
875     }
876
877     /* Check if the input file is present, set ifname and istat: */
878     ifd = open_input_file (iname, &istat);
879     if (ifd < 0)
880       return;
881
882     /* If the input name is that of a directory, recurse or ignore: */
883     if (S_ISDIR(istat.st_mode)) {
884 #if ! NO_DIR
885         if (recursive) {
886             treat_dir (ifd, iname);
887             /* Warning: ifname is now garbage */
888             return;
889         }
890 #endif
891         close (ifd);
892         WARN ((stderr, "%s: %s is a directory -- ignored\n",
893                program_name, ifname));
894         return;
895     }
896
897     if (! to_stdout)
898       {
899         if (! S_ISREG (istat.st_mode))
900           {
901             WARN ((stderr,
902                    "%s: %s is not a directory or a regular file - ignored\n",
903                    program_name, ifname));
904             close (ifd);
905             return;
906           }
907         if (istat.st_mode & S_ISUID)
908           {
909             WARN ((stderr, "%s: %s is set-user-ID on execution - ignored\n",
910                    program_name, ifname));
911             close (ifd);
912             return;
913           }
914         if (istat.st_mode & S_ISGID)
915           {
916             WARN ((stderr, "%s: %s is set-group-ID on execution - ignored\n",
917                    program_name, ifname));
918             close (ifd);
919             return;
920           }
921
922         if (! force)
923           {
924             if (istat.st_mode & S_ISVTX)
925               {
926                 WARN ((stderr,
927                        "%s: %s has the sticky bit set - file ignored\n",
928                        program_name, ifname));
929                 close (ifd);
930                 return;
931               }
932             if (2 <= istat.st_nlink)
933               {
934                 WARN ((stderr, "%s: %s has %lu other link%c -- unchanged\n",
935                        program_name, ifname,
936                        (unsigned long int) istat.st_nlink - 1,
937                        istat.st_nlink == 2 ? ' ' : 's'));
938                 close (ifd);
939                 return;
940               }
941           }
942       }
943
944     ifile_size = S_ISREG (istat.st_mode) ? istat.st_size : -1;
945     time_stamp.tv_nsec = -1;
946     if (!no_time || list)
947       time_stamp = get_stat_mtime (&istat);
948
949     /* Generate output file name. For -r and (-t or -l), skip files
950      * without a valid gzip suffix (check done in make_ofname).
951      */
952     if (to_stdout && !list && !test) {
953         strcpy(ofname, "stdout");
954
955     } else if (make_ofname() != OK) {
956         close (ifd);
957         return;
958     }
959
960     clear_bufs(); /* clear input and output buffers */
961     part_nb = 0;
962
963     if (decompress) {
964         method = get_method(ifd); /* updates ofname if original given */
965         if (method < 0) {
966             close(ifd);
967             return;               /* error message already emitted */
968         }
969     }
970     if (list) {
971         do_list(ifd, method);
972         if (close (ifd) != 0)
973           read_error ();
974         return;
975     }
976
977     /* If compressing to a file, check if ofname is not ambiguous
978      * because the operating system truncates names. Otherwise, generate
979      * a new ofname and save the original name in the compressed file.
980      */
981     if (to_stdout) {
982         ofd = STDOUT_FILENO;
983         /* Keep remove_ofname_fd negative.  */
984     } else {
985         if (create_outfile() != OK) return;
986
987         if (!decompress && save_orig_name && !verbose && !quiet) {
988             fprintf(stderr, "%s: %s compressed to %s\n",
989                     program_name, ifname, ofname);
990         }
991     }
992     /* Keep the name even if not truncated except with --no-name: */
993     if (!save_orig_name) save_orig_name = !no_name;
994
995     if (verbose) {
996         fprintf(stderr, "%s:\t", ifname);
997     }
998
999     /* Actually do the compression/decompression. Loop over zipped members.
1000      */
1001     for (;;) {
1002         if ((*work)(ifd, ofd) != OK) {
1003             method = -1; /* force cleanup */
1004             break;
1005         }
1006
1007         if (input_eof ())
1008           break;
1009
1010         method = get_method(ifd);
1011         if (method < 0) break;    /* error message already emitted */
1012         bytes_out = 0;            /* required for length check */
1013     }
1014
1015     if (close (ifd) != 0)
1016       read_error ();
1017
1018     if (!to_stdout)
1019       {
1020         copy_stat (&istat);
1021
1022         if ((synchronous
1023              && ((0 <= dfd && fdatasync (dfd) != 0 && errno != EINVAL)
1024                  || (fsync (ofd) != 0 && errno != EINVAL)))
1025             || close (ofd) != 0)
1026           write_error ();
1027
1028         if (!keep)
1029           {
1030             sigset_t oldset;
1031             int unlink_errno;
1032             char *ifbase = last_component (ifname);
1033             int ufd = atdir_eq (ifname, ifbase - ifname) ? dfd : -1;
1034             int res;
1035
1036             sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
1037             remove_ofname_fd = -1;
1038             res = ufd < 0 ? xunlink (ifname) : unlinkat (ufd, ifbase, 0);
1039             unlink_errno = res == 0 ? 0 : errno;
1040             sigprocmask (SIG_SETMASK, &oldset, NULL);
1041
1042             if (unlink_errno)
1043               {
1044                 WARN ((stderr, "%s: ", program_name));
1045                 if (!quiet)
1046                   {
1047                     errno = unlink_errno;
1048                     perror (ifname);
1049                   }
1050               }
1051           }
1052       }
1053
1054     if (method == -1) {
1055         if (!to_stdout)
1056           remove_output_file ();
1057         return;
1058     }
1059
1060     /* Display statistics */
1061     if(verbose) {
1062         if (test) {
1063             fprintf(stderr, " OK");
1064         } else if (decompress) {
1065             display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
1066         } else {
1067             display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
1068         }
1069         if (!test && !to_stdout)
1070           fprintf(stderr, " -- %s %s", keep ? "created" : "replaced with",
1071                   ofname);
1072         fprintf(stderr, "\n");
1073     }
1074 }
1075
1076 /* ========================================================================
1077  * Create the output file. Return OK or ERROR.
1078  * Try several times if necessary to avoid truncating the z_suffix. For
1079  * example, do not create a compressed file of name "1234567890123."
1080  * Sets save_orig_name to true if the file name has been truncated.
1081  * IN assertions: the input file has already been open (ifd is set) and
1082  *   ofname has already been updated if there was an original name.
1083  * OUT assertions: ifd and ofd are closed in case of error.
1084  */
1085 local int create_outfile()
1086 {
1087   int name_shortened = 0;
1088   int flags = (O_WRONLY | O_CREAT | O_EXCL
1089                | (ascii && decompress ? 0 : O_BINARY));
1090   char const *base = ofname;
1091   int atfd = AT_FDCWD;
1092
1093   if (!keep)
1094     {
1095       char const *b = last_component (ofname);
1096       int f = atdir_set (ofname, b - ofname);
1097       if (0 <= f)
1098         {
1099           base = b;
1100           atfd = f;
1101         }
1102     }
1103
1104   for (;;)
1105     {
1106       int open_errno;
1107       sigset_t oldset;
1108
1109       sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
1110       remove_ofname_fd = ofd = openat (atfd, base, flags, S_IRUSR | S_IWUSR);
1111       open_errno = errno;
1112       sigprocmask (SIG_SETMASK, &oldset, NULL);
1113
1114       if (0 <= ofd)
1115         break;
1116
1117       switch (open_errno)
1118         {
1119 #ifdef ENAMETOOLONG
1120         case ENAMETOOLONG:
1121           shorten_name (ofname);
1122           name_shortened = 1;
1123           break;
1124 #endif
1125
1126         case EEXIST:
1127           if (check_ofname () != OK)
1128             {
1129               close (ifd);
1130               return ERROR;
1131             }
1132           break;
1133
1134         default:
1135           progerror (ofname);
1136           close (ifd);
1137           return ERROR;
1138         }
1139     }
1140
1141   if (name_shortened && decompress)
1142     {
1143       /* name might be too long if an original name was saved */
1144       WARN ((stderr, "%s: %s: warning, name truncated\n",
1145              program_name, ofname));
1146     }
1147
1148   return OK;
1149 }
1150
1151 /* ========================================================================
1152  * Return a pointer to the 'z' suffix of a file name, or NULL. For all
1153  * systems, ".gz", ".z", ".Z", ".taz", ".tgz", "-gz", "-z" and "_z" are
1154  * accepted suffixes, in addition to the value of the --suffix option.
1155  * ".tgz" is a useful convention for tar.z files on systems limited
1156  * to 3 characters extensions. On such systems, ".?z" and ".??z" are
1157  * also accepted suffixes. For Unix, we do not want to accept any
1158  * .??z suffix as indicating a compressed file; some people use .xyz
1159  * to denote volume data.
1160  */
1161 local char *get_suffix(name)
1162     char *name;
1163 {
1164     int nlen, slen;
1165     char suffix[MAX_SUFFIX+3]; /* last chars of name, forced to lower case */
1166     static char const *known_suffixes[] =
1167        {NULL, ".gz", ".z", ".taz", ".tgz", "-gz", "-z", "_z",
1168 #ifdef MAX_EXT_CHARS
1169           "z",
1170 #endif
1171         NULL, NULL};
1172     char const **suf;
1173     bool suffix_of_builtin = false;
1174
1175     /* Normally put Z_SUFFIX at the start of KNOWN_SUFFIXES, but if it
1176        is a suffix of one of them, put it at the end.  */
1177     for (suf = known_suffixes + 1; *suf; suf++)
1178       {
1179         size_t suflen = strlen (*suf);
1180         if (z_len < suflen && strequ (z_suffix, *suf + suflen - z_len))
1181           {
1182             suffix_of_builtin = true;
1183             break;
1184           }
1185       }
1186
1187     char *z_lower = xstrdup(z_suffix);
1188     strlwr(z_lower);
1189     known_suffixes[suffix_of_builtin
1190                    ? sizeof known_suffixes / sizeof *known_suffixes - 2
1191                    : 0] = z_lower;
1192     suf = known_suffixes + suffix_of_builtin;
1193
1194     nlen = strlen(name);
1195     if (nlen <= MAX_SUFFIX+2) {
1196         strcpy(suffix, name);
1197     } else {
1198         strcpy(suffix, name+nlen-MAX_SUFFIX-2);
1199     }
1200     strlwr(suffix);
1201     slen = strlen(suffix);
1202     char *match = NULL;
1203     do {
1204        int s = strlen(*suf);
1205        if (slen > s && ! ISSLASH (suffix[slen - s - 1])
1206            && strequ(suffix + slen - s, *suf)) {
1207            match = name+nlen-s;
1208            break;
1209        }
1210     } while (*++suf != NULL);
1211     free(z_lower);
1212
1213     return match;
1214 }
1215
1216
1217 /* Open file NAME with the given flags and store its status
1218    into *ST.  Return a file descriptor to the newly opened file, or -1
1219    (setting errno) on failure.  */
1220 static int
1221 open_and_stat (char *name, int flags, struct stat *st)
1222 {
1223   int fd;
1224   int atfd = AT_FDCWD;
1225   char const *base = name;
1226
1227   /* Refuse to follow symbolic links unless -c or -f.  */
1228   if (!to_stdout && !force)
1229     {
1230       if (HAVE_WORKING_O_NOFOLLOW)
1231         flags |= O_NOFOLLOW;
1232       else
1233         {
1234 #ifdef S_ISLNK
1235           if (lstat (name, st) != 0)
1236             return -1;
1237           else if (S_ISLNK (st->st_mode))
1238             {
1239               errno = ELOOP;
1240               return -1;
1241             }
1242 #endif
1243         }
1244     }
1245
1246   if (!keep)
1247     {
1248       char const *b = last_component (name);
1249       int f = atdir_set (name, b - name);
1250       if (0 <= f)
1251         {
1252           base = b;
1253           atfd = f;
1254         }
1255     }
1256
1257   fd = openat (atfd, base, flags);
1258   if (0 <= fd && fstat (fd, st) != 0)
1259     {
1260       int e = errno;
1261       close (fd);
1262       errno = e;
1263       return -1;
1264     }
1265   return fd;
1266 }
1267
1268
1269 /* ========================================================================
1270  * Set ifname to the input file name (with a suffix appended if necessary)
1271  * and istat to its stats. For decompression, if no file exists with the
1272  * original name, try adding successively z_suffix, .gz, .z, -z and .Z.
1273  * For MSDOS, we try only z_suffix and z.
1274  * Return an open file descriptor or -1.
1275  */
1276 static int
1277 open_input_file (iname, sbuf)
1278     char *iname;
1279     struct stat *sbuf;
1280 {
1281     int ilen;  /* strlen(ifname) */
1282     int z_suffix_errno = 0;
1283     static char const *suffixes[] = {NULL, ".gz", ".z", "-z", ".Z", NULL};
1284     char const **suf = suffixes;
1285     char const *s;
1286 #ifdef NO_MULTIPLE_DOTS
1287     char *dot; /* pointer to ifname extension, or NULL */
1288 #endif
1289     int fd;
1290     int open_flags = (O_RDONLY | O_NONBLOCK | O_NOCTTY
1291                       | (ascii && !decompress ? 0 : O_BINARY));
1292
1293     *suf = z_suffix;
1294
1295     if (sizeof ifname - 1 <= strlen (iname))
1296         goto name_too_long;
1297
1298     strcpy(ifname, iname);
1299
1300     /* If input file exists, return OK. */
1301     fd = open_and_stat (ifname, open_flags, sbuf);
1302     if (0 <= fd)
1303       return fd;
1304
1305     if (!decompress || errno != ENOENT) {
1306         progerror(ifname);
1307         return -1;
1308     }
1309     /* File.ext doesn't exist.  Try adding a suffix.  */
1310     s = get_suffix(ifname);
1311     if (s != NULL) {
1312         progerror(ifname); /* ifname already has z suffix and does not exist */
1313         return -1;
1314     }
1315 #ifdef NO_MULTIPLE_DOTS
1316     dot = strrchr(ifname, '.');
1317     if (dot == NULL) {
1318         strcat(ifname, ".");
1319         dot = strrchr(ifname, '.');
1320     }
1321 #endif
1322     ilen = strlen(ifname);
1323     if (strequ(z_suffix, ".gz")) suf++;
1324
1325     /* Search for all suffixes */
1326     do {
1327         char const *s0 = s = *suf;
1328         strcpy (ifname, iname);
1329 #ifdef NO_MULTIPLE_DOTS
1330         if (*s == '.') s++;
1331         if (*dot == '\0') strcpy (dot, ".");
1332 #endif
1333 #ifdef MAX_EXT_CHARS
1334         if (MAX_EXT_CHARS < strlen (s) + strlen (dot + 1))
1335           dot[MAX_EXT_CHARS + 1 - strlen (s)] = '\0';
1336 #endif
1337         if (sizeof ifname <= ilen + strlen (s))
1338           goto name_too_long;
1339         strcat(ifname, s);
1340         fd = open_and_stat (ifname, open_flags, sbuf);
1341         if (0 <= fd)
1342           return fd;
1343         if (errno != ENOENT)
1344           {
1345             progerror (ifname);
1346             return -1;
1347           }
1348         if (strequ (s0, z_suffix))
1349           z_suffix_errno = errno;
1350     } while (*++suf != NULL);
1351
1352     /* No suffix found, complain using z_suffix: */
1353     strcpy(ifname, iname);
1354 #ifdef NO_MULTIPLE_DOTS
1355     if (*dot == '\0') strcpy(dot, ".");
1356 #endif
1357 #ifdef MAX_EXT_CHARS
1358     if (MAX_EXT_CHARS < z_len + strlen (dot + 1))
1359       dot[MAX_EXT_CHARS + 1 - z_len] = '\0';
1360 #endif
1361     strcat(ifname, z_suffix);
1362     errno = z_suffix_errno;
1363     progerror(ifname);
1364     return -1;
1365
1366  name_too_long:
1367     fprintf (stderr, "%s: %s: file name too long\n", program_name, iname);
1368     exit_code = ERROR;
1369     return -1;
1370 }
1371
1372 /* ========================================================================
1373  * Generate ofname given ifname. Return OK, or WARNING if file must be skipped.
1374  * Sets save_orig_name to true if the file name has been truncated.
1375  */
1376 local int make_ofname()
1377 {
1378     char *suff;            /* ofname z suffix */
1379
1380     strcpy(ofname, ifname);
1381     /* strip a version number if any and get the gzip suffix if present: */
1382     suff = get_suffix(ofname);
1383
1384     if (decompress) {
1385         if (suff == NULL) {
1386             /* With -t or -l, try all files (even without .gz suffix)
1387              * except with -r (behave as with just -dr).
1388              */
1389             if (!recursive && (list || test)) return OK;
1390
1391             /* Avoid annoying messages with -r */
1392             if (verbose || (!recursive && !quiet)) {
1393                 WARN((stderr,"%s: %s: unknown suffix -- ignored\n",
1394                       program_name, ifname));
1395             }
1396             return WARNING;
1397         }
1398         /* Make a special case for .tgz and .taz: */
1399         strlwr(suff);
1400         if (strequ(suff, ".tgz") || strequ(suff, ".taz")) {
1401             strcpy(suff, ".tar");
1402         } else {
1403             *suff = '\0'; /* strip the z suffix */
1404         }
1405         /* ofname might be changed later if infile contains an original name */
1406
1407     } else if (suff && ! force) {
1408         /* Avoid annoying messages with -r (see treat_dir()) */
1409         if (verbose || (!recursive && !quiet)) {
1410             /* Don't use WARN, as it affects exit status.  */
1411             fprintf (stderr, "%s: %s already has %s suffix -- unchanged\n",
1412                      program_name, ifname, suff);
1413         }
1414         return WARNING;
1415     } else {
1416         save_orig_name = 0;
1417
1418 #ifdef NO_MULTIPLE_DOTS
1419         suff = strrchr(ofname, '.');
1420         if (suff == NULL) {
1421             if (sizeof ofname <= strlen (ofname) + 1)
1422                 goto name_too_long;
1423             strcat(ofname, ".");
1424 #  ifdef MAX_EXT_CHARS
1425             if (strequ(z_suffix, "z")) {
1426                 if (sizeof ofname <= strlen (ofname) + 2)
1427                     goto name_too_long;
1428                 strcat(ofname, "gz"); /* enough room */
1429                 return OK;
1430             }
1431         /* On the Atari and some versions of MSDOS,
1432          * ENAMETOOLONG does not work correctly.  So we
1433          * must truncate here.
1434          */
1435         } else if (strlen(suff)-1 + z_len > MAX_SUFFIX) {
1436             suff[MAX_SUFFIX+1-z_len] = '\0';
1437             save_orig_name = 1;
1438 #  endif
1439         }
1440 #endif /* NO_MULTIPLE_DOTS */
1441         if (sizeof ofname <= strlen (ofname) + z_len)
1442             goto name_too_long;
1443         strcat(ofname, z_suffix);
1444
1445     } /* decompress ? */
1446     return OK;
1447
1448  name_too_long:
1449     WARN ((stderr, "%s: %s: file name too long\n", program_name, ifname));
1450     return WARNING;
1451 }
1452
1453 /* Discard NBYTES input bytes from the input, or up through the next
1454    zero byte if NBYTES == (size_t) -1.  If FLAGS say that the header
1455    CRC should be computed, update the CRC accordingly.  */
1456 static void
1457 discard_input_bytes (nbytes, flags)
1458     size_t nbytes;
1459     unsigned int flags;
1460 {
1461   while (nbytes != 0)
1462     {
1463       uch c = get_byte ();
1464       if (flags & HEADER_CRC)
1465         updcrc (&c, 1);
1466       if (nbytes != (size_t) -1)
1467         nbytes--;
1468       else if (! c)
1469         break;
1470     }
1471 }
1472
1473 /* ========================================================================
1474  * Check the magic number of the input file and update ofname if an
1475  * original name was given and to_stdout is not set.
1476  * Return the compression method, -1 for error, -2 for warning.
1477  * Set inptr to the offset of the next byte to be processed.
1478  * Updates time_stamp if there is one and neither -m nor -n is used.
1479  * This function may be called repeatedly for an input file consisting
1480  * of several contiguous gzip'ed members.
1481  * IN assertions: there is at least one remaining compressed member.
1482  *   If the member is a zip file, it must be the only one.
1483  */
1484 local int get_method(in)
1485     int in;        /* input file descriptor */
1486 {
1487     uch flags;     /* compression flags */
1488     uch magic[10]; /* magic header */
1489     int imagic0;   /* first magic byte or EOF */
1490     int imagic1;   /* like magic[1], but can represent EOF */
1491     ulg stamp;     /* timestamp */
1492
1493     /* If --force and --stdout, zcat == cat, so do not complain about
1494      * premature end of file: use try_byte instead of get_byte.
1495      */
1496     if (force && to_stdout) {
1497         imagic0 = try_byte();
1498         magic[0] = imagic0;
1499         imagic1 = try_byte ();
1500         magic[1] = imagic1;
1501         /* If try_byte returned EOF, magic[1] == (char) EOF.  */
1502     } else {
1503         magic[0] = get_byte ();
1504         imagic0 = 0;
1505         if (magic[0]) {
1506             magic[1] = get_byte ();
1507             imagic1 = 0; /* avoid lint warning */
1508         } else {
1509             imagic1 = try_byte ();
1510             magic[1] = imagic1;
1511         }
1512     }
1513     method = -1;                 /* unknown yet */
1514     part_nb++;                   /* number of parts in gzip file */
1515     header_bytes = 0;
1516     last_member = 0;
1517     /* assume multiple members in gzip file except for record oriented I/O */
1518
1519     if (memcmp(magic, GZIP_MAGIC, 2) == 0
1520         || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
1521
1522         method = (int)get_byte();
1523         if (method != DEFLATED) {
1524             fprintf(stderr,
1525                     "%s: %s: unknown method %d -- not supported\n",
1526                     program_name, ifname, method);
1527             exit_code = ERROR;
1528             return -1;
1529         }
1530         work = unzip;
1531         flags  = (uch)get_byte();
1532
1533         if ((flags & ENCRYPTED) != 0) {
1534             fprintf(stderr,
1535                     "%s: %s is encrypted -- not supported\n",
1536                     program_name, ifname);
1537             exit_code = ERROR;
1538             return -1;
1539         }
1540         if ((flags & RESERVED) != 0) {
1541             fprintf(stderr,
1542                     "%s: %s has flags 0x%x -- not supported\n",
1543                     program_name, ifname, flags);
1544             exit_code = ERROR;
1545             if (force <= 1) return -1;
1546         }
1547         stamp  = (ulg)get_byte();
1548         stamp |= ((ulg)get_byte()) << 8;
1549         stamp |= ((ulg)get_byte()) << 16;
1550         stamp |= ((ulg)get_byte()) << 24;
1551         if (stamp != 0 && !no_time)
1552           {
1553             if (stamp <= TYPE_MAXIMUM (time_t))
1554               {
1555                 time_stamp.tv_sec = stamp;
1556                 time_stamp.tv_nsec = 0;
1557               }
1558             else
1559               {
1560                 WARN ((stderr,
1561                        "%s: %s: MTIME %lu out of range for this platform\n",
1562                        program_name, ifname, stamp));
1563                 time_stamp.tv_sec = TYPE_MAXIMUM (time_t);
1564                 time_stamp.tv_nsec = TIMESPEC_RESOLUTION - 1;
1565               }
1566           }
1567
1568         magic[8] = get_byte ();  /* Ignore extra flags.  */
1569         magic[9] = get_byte ();  /* Ignore OS type.  */
1570
1571         if (flags & HEADER_CRC)
1572           {
1573             magic[2] = DEFLATED;
1574             magic[3] = flags;
1575             magic[4] = stamp & 0xff;
1576             magic[5] = (stamp >> 8) & 0xff;
1577             magic[6] = (stamp >> 16) & 0xff;
1578             magic[7] = stamp >> 24;
1579             updcrc (NULL, 0);
1580             updcrc (magic, 10);
1581           }
1582
1583         if ((flags & EXTRA_FIELD) != 0) {
1584             uch lenbuf[2];
1585             unsigned int len = lenbuf[0] = get_byte ();
1586             len |= (lenbuf[1] = get_byte ()) << 8;
1587             if (verbose) {
1588                 fprintf(stderr,"%s: %s: extra field of %u bytes ignored\n",
1589                         program_name, ifname, len);
1590             }
1591             if (flags & HEADER_CRC)
1592               updcrc (lenbuf, 2);
1593             discard_input_bytes (len, flags);
1594         }
1595
1596         /* Get original file name if it was truncated */
1597         if ((flags & ORIG_NAME) != 0) {
1598             if (no_name || (to_stdout && !list) || part_nb > 1) {
1599                 /* Discard the old name */
1600                 discard_input_bytes (-1, flags);
1601             } else {
1602                 /* Copy the base name. Keep a directory prefix intact. */
1603                 char *p = gzip_base_name (ofname);
1604                 char *base = p;
1605                 for (;;) {
1606                     *p = (char) get_byte ();
1607                     if (*p++ == '\0') break;
1608                     if (p >= ofname+sizeof(ofname)) {
1609                         gzip_error ("corrupted input -- file name too large");
1610                     }
1611                 }
1612                 if (flags & HEADER_CRC)
1613                   updcrc ((uch *) base, p - base);
1614                 p = gzip_base_name (base);
1615                 memmove (base, p, strlen (p) + 1);
1616                 /* If necessary, adapt the name to local OS conventions: */
1617                 if (!list) {
1618                    MAKE_LEGAL_NAME(base);
1619                    if (base) list=0; /* avoid warning about unused variable */
1620                 }
1621             } /* no_name || to_stdout */
1622         } /* ORIG_NAME */
1623
1624         /* Discard file comment if any */
1625         if ((flags & COMMENT) != 0) {
1626             discard_input_bytes (-1, flags);
1627         }
1628
1629         if (flags & HEADER_CRC)
1630           {
1631             unsigned int crc16 = updcrc (magic, 0) & 0xffff;
1632             unsigned int header16 = get_byte ();
1633             header16 |= ((unsigned int) get_byte ()) << 8;
1634             if (header16 != crc16)
1635               {
1636                 fprintf (stderr,
1637                          "%s: %s: header checksum 0x%04x != computed checksum 0x%04x\n",
1638                          program_name, ifname, header16, crc16);
1639                 exit_code = ERROR;
1640                 if (force <= 1)
1641                   return -1;
1642               }
1643           }
1644
1645         if (part_nb == 1) {
1646             header_bytes = inptr + 2*4; /* include crc and size */
1647         }
1648
1649     } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
1650             && memcmp((char*)inbuf, PKZIP_MAGIC, 4) == 0) {
1651         /* To simplify the code, we support a zip file when alone only.
1652          * We are thus guaranteed that the entire local header fits in inbuf.
1653          */
1654         inptr = 0;
1655         work = unzip;
1656         if (check_zipfile(in) != OK) return -1;
1657         /* check_zipfile may get ofname from the local header */
1658         last_member = 1;
1659
1660     } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
1661         work = unpack;
1662         method = PACKED;
1663
1664     } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {
1665         work = unlzw;
1666         method = COMPRESSED;
1667         last_member = 1;
1668
1669     } else if (memcmp(magic, LZH_MAGIC, 2) == 0) {
1670         work = unlzh;
1671         method = LZHED;
1672         last_member = 1;
1673
1674     } else if (force && to_stdout && !list) { /* pass input unchanged */
1675         method = STORED;
1676         work = copy;
1677         if (imagic1 != EOF)
1678             inptr--;
1679         last_member = 1;
1680         if (imagic0 != EOF) {
1681             write_buf (STDOUT_FILENO, magic, 1);
1682             bytes_out++;
1683         }
1684     }
1685     if (method >= 0) return method;
1686
1687     if (part_nb == 1) {
1688         fprintf (stderr, "\n%s: %s: not in gzip format\n",
1689                  program_name, ifname);
1690         exit_code = ERROR;
1691         return -1;
1692     } else {
1693         if (magic[0] == 0)
1694           {
1695             int inbyte;
1696             for (inbyte = imagic1;  inbyte == 0;  inbyte = try_byte ())
1697               continue;
1698             if (inbyte == EOF)
1699               {
1700                 if (verbose)
1701                   WARN ((stderr, "\n%s: %s: decompression OK, trailing zero bytes ignored\n",
1702                          program_name, ifname));
1703                 return -3;
1704               }
1705           }
1706
1707         WARN((stderr, "\n%s: %s: decompression OK, trailing garbage ignored\n",
1708               program_name, ifname));
1709         return -2;
1710     }
1711 }
1712
1713 /* ========================================================================
1714  * Display the characteristics of the compressed file.
1715  * If the given method is < 0, display the accumulated totals.
1716  * IN assertions: time_stamp, header_bytes and ifile_size are initialized.
1717  */
1718 local void do_list(ifd, method)
1719     int ifd;     /* input file descriptor */
1720     int method;  /* compression method */
1721 {
1722     ulg crc;  /* original crc */
1723     static int first_time = 1;
1724     static char const *const methods[MAX_METHODS] = {
1725         "store",  /* 0 */
1726         "compr",  /* 1 */
1727         "pack ",  /* 2 */
1728         "lzh  ",  /* 3 */
1729         "", "", "", "", /* 4 to 7 reserved */
1730         "defla"}; /* 8 */
1731     int positive_off_t_width = 1;
1732     off_t o;
1733
1734     for (o = OFF_T_MAX;  9 < o;  o /= 10) {
1735         positive_off_t_width++;
1736     }
1737
1738     if (first_time && method >= 0) {
1739         first_time = 0;
1740         if (verbose)  {
1741             printf("method  crc     date  time  ");
1742         }
1743         if (!quiet) {
1744             printf("%*.*s %*.*s  ratio uncompressed_name\n",
1745                    positive_off_t_width, positive_off_t_width, "compressed",
1746                    positive_off_t_width, positive_off_t_width, "uncompressed");
1747         }
1748     } else if (method < 0) {
1749         if (total_in <= 0 || total_out <= 0) return;
1750         if (verbose) {
1751             printf("                            ");
1752         }
1753         if (verbose || !quiet) {
1754             fprint_off(stdout, total_in, positive_off_t_width);
1755             printf(" ");
1756             fprint_off(stdout, total_out, positive_off_t_width);
1757             printf(" ");
1758         }
1759         display_ratio(total_out-(total_in-header_bytes), total_out, stdout);
1760         /* header_bytes is not meaningful but used to ensure the same
1761          * ratio if there is a single file.
1762          */
1763         printf(" (totals)\n");
1764         return;
1765     }
1766     crc = (ulg)~0; /* unknown */
1767     bytes_out = -1L;
1768     bytes_in = ifile_size;
1769
1770     if (method == DEFLATED && !last_member) {
1771         /* Get the crc and uncompressed size for gzip'ed (not zip'ed) files.
1772          * If the lseek fails, we could use read() to get to the end, but
1773          * --list is used to get quick results.
1774          * Use "gunzip < foo.gz | wc -c" to get the uncompressed size if
1775          * you are not concerned about speed.
1776          */
1777         bytes_in = lseek(ifd, (off_t)(-8), SEEK_END);
1778         if (bytes_in != -1L) {
1779             uch buf[8];
1780             bytes_in += 8L;
1781             if (read(ifd, (char*)buf, sizeof(buf)) != sizeof(buf)) {
1782                 read_error();
1783             }
1784             crc       = LG(buf);
1785             bytes_out = LG(buf+4);
1786         }
1787     }
1788
1789     if (verbose)
1790       {
1791         static char const month_abbr[][4]
1792           = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1793               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
1794         struct tm *tm = localtime (&time_stamp.tv_sec);
1795         printf ("%5s %08lx ", methods[method], crc);
1796         if (tm)
1797           printf ("%s%3d %02d:%02d ", month_abbr[tm->tm_mon],
1798                   tm->tm_mday, tm->tm_hour, tm->tm_min);
1799         else
1800           printf ("??? ?? ??:?? ");
1801       }
1802     fprint_off(stdout, bytes_in, positive_off_t_width);
1803     printf(" ");
1804     fprint_off(stdout, bytes_out, positive_off_t_width);
1805     printf(" ");
1806     if (bytes_in  == -1L) {
1807         total_in = -1L;
1808         bytes_in = bytes_out = header_bytes = 0;
1809     } else if (total_in >= 0) {
1810         total_in  += bytes_in;
1811     }
1812     if (bytes_out == -1L) {
1813         total_out = -1L;
1814         bytes_in = bytes_out = header_bytes = 0;
1815     } else if (total_out >= 0) {
1816         total_out += bytes_out;
1817     }
1818     display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out, stdout);
1819     printf(" %s\n", ofname);
1820 }
1821
1822 /* ========================================================================
1823  * Shorten the given name by one character, or replace a .tar extension
1824  * with .tgz. Truncate the last part of the name which is longer than
1825  * MIN_PART characters: 1234.678.012.gz -> 123.678.012.gz. If the name
1826  * has only parts shorter than MIN_PART truncate the longest part.
1827  * For decompression, just remove the last character of the name.
1828  *
1829  * IN assertion: for compression, the suffix of the given name is z_suffix.
1830  */
1831 local void shorten_name(name)
1832     char *name;
1833 {
1834     int len;                 /* length of name without z_suffix */
1835     char *trunc = NULL;      /* character to be truncated */
1836     int plen;                /* current part length */
1837     int min_part = MIN_PART; /* current minimum part length */
1838     char *p;
1839
1840     len = strlen(name);
1841     if (decompress) {
1842         if (len <= 1)
1843           gzip_error ("name too short");
1844         name[len-1] = '\0';
1845         return;
1846     }
1847     p = get_suffix(name);
1848     if (! p)
1849       gzip_error ("can't recover suffix\n");
1850     *p = '\0';
1851     save_orig_name = 1;
1852
1853     /* compress 1234567890.tar to 1234567890.tgz */
1854     if (len > 4 && strequ(p-4, ".tar")) {
1855         strcpy(p-4, ".tgz");
1856         return;
1857     }
1858     /* Try keeping short extensions intact:
1859      * 1234.678.012.gz -> 123.678.012.gz
1860      */
1861     do {
1862         p = last_component (name);
1863         while (*p) {
1864             plen = strcspn(p, PART_SEP);
1865             p += plen;
1866             if (plen > min_part) trunc = p-1;
1867             if (*p) p++;
1868         }
1869     } while (trunc == NULL && --min_part != 0);
1870
1871     if (trunc != NULL) {
1872         do {
1873             trunc[0] = trunc[1];
1874         } while (*trunc++);
1875         trunc--;
1876     } else {
1877         trunc = strrchr(name, PART_SEP[0]);
1878         if (!trunc)
1879           gzip_error ("internal error in shorten_name");
1880         if (trunc[1] == '\0') trunc--; /* force truncation */
1881     }
1882     strcpy(trunc, z_suffix);
1883 }
1884
1885 /* ========================================================================
1886  * The compressed file already exists, so ask for confirmation.
1887  * Return ERROR if the file must be skipped.
1888  */
1889 local int check_ofname()
1890 {
1891     /* Ask permission to overwrite the existing file */
1892     if (!force) {
1893         int ok = 0;
1894         fprintf (stderr, "%s: %s already exists;", program_name, ofname);
1895         if (foreground && (presume_input_tty || isatty (STDIN_FILENO))) {
1896             fprintf(stderr, " do you wish to overwrite (y or n)? ");
1897             fflush(stderr);
1898             ok = yesno();
1899         }
1900         if (!ok) {
1901             fprintf(stderr, "\tnot overwritten\n");
1902             if (exit_code == OK) exit_code = WARNING;
1903             return ERROR;
1904         }
1905     }
1906     if (xunlink (ofname)) {
1907         progerror(ofname);
1908         return ERROR;
1909     }
1910     return OK;
1911 }
1912
1913 /* Change the owner and group of a file.  FD is a file descriptor for
1914    the file and NAME its name.  Change it to user UID and to group GID.
1915    If UID or GID is -1, though, do not change the corresponding user
1916    or group.  */
1917 static void
1918 do_chown (int fd, char const *name, uid_t uid, gid_t gid)
1919 {
1920 #ifndef NO_CHOWN
1921 # if HAVE_FCHOWN
1922   ignore_value (fchown (fd, uid, gid));
1923 # else
1924   ignore_value (chown (name, uid, gid));
1925 # endif
1926 #endif
1927 }
1928
1929 /* ========================================================================
1930  * Copy modes, times, ownership from input file to output file.
1931  * IN assertion: to_stdout is false.
1932  */
1933 local void copy_stat(ifstat)
1934     struct stat *ifstat;
1935 {
1936     mode_t mode = ifstat->st_mode & S_IRWXUGO;
1937     int r;
1938
1939 #ifndef NO_UTIME
1940     bool restoring;
1941     struct timespec timespec[2];
1942     timespec[0] = get_stat_atime (ifstat);
1943     timespec[1] = get_stat_mtime (ifstat);
1944     restoring = (decompress && 0 <= time_stamp.tv_nsec
1945                  && ! (timespec[1].tv_sec == time_stamp.tv_sec
1946                        && timespec[1].tv_nsec == time_stamp.tv_nsec));
1947     if (restoring)
1948       timespec[1] = time_stamp;
1949
1950     if (fdutimens (ofd, ofname, timespec) == 0)
1951       {
1952         if (restoring && 1 < verbose) {
1953             fprintf(stderr, "%s: timestamp restored\n", ofname);
1954         }
1955       }
1956     else
1957       {
1958         int e = errno;
1959         WARN ((stderr, "%s: ", program_name));
1960         if (!quiet)
1961           {
1962             errno = e;
1963             perror (ofname);
1964           }
1965       }
1966 #endif
1967
1968     /* Change the group first, then the permissions, then the owner.
1969        That way, the permissions will be correct on systems that allow
1970        users to give away files, without introducing a security hole.
1971        Security depends on permissions not containing the setuid or
1972        setgid bits.  */
1973
1974     do_chown (ofd, ofname, -1, ifstat->st_gid);
1975
1976 #if HAVE_FCHMOD
1977     r = fchmod (ofd, mode);
1978 #else
1979     r = chmod (ofname, mode);
1980 #endif
1981     if (r != 0) {
1982         int e = errno;
1983         WARN ((stderr, "%s: ", program_name));
1984         if (!quiet) {
1985             errno = e;
1986             perror(ofname);
1987         }
1988     }
1989
1990     do_chown (ofd, ofname, ifstat->st_uid, -1);
1991 }
1992
1993 #if ! NO_DIR
1994
1995 /* ========================================================================
1996  * Recurse through the given directory.
1997  */
1998 local void treat_dir (fd, dir)
1999     int fd;
2000     char *dir;
2001 {
2002     DIR      *dirp;
2003     char     nbuf[MAX_PATH_LEN];
2004     char *entries;
2005     char const *entry;
2006     size_t entrylen;
2007
2008     dirp = fdopendir (fd);
2009
2010     if (dirp == NULL) {
2011         progerror(dir);
2012         close (fd);
2013         return ;
2014     }
2015
2016     entries = streamsavedir (dirp, SAVEDIR_SORT_NONE);
2017     if (! entries)
2018       progerror (dir);
2019     if (closedir (dirp) != 0)
2020       progerror (dir);
2021     if (! entries)
2022       return;
2023
2024     for (entry = entries; *entry; entry += entrylen + 1) {
2025         size_t len = strlen (dir);
2026         entrylen = strlen (entry);
2027         if (strequ (entry, ".") || strequ (entry, ".."))
2028           continue;
2029         if (len + entrylen < MAX_PATH_LEN - 2) {
2030             strcpy(nbuf,dir);
2031             if (*last_component (nbuf) && !ISSLASH (nbuf[len - 1]))
2032               nbuf[len++] = '/';
2033             strcpy (nbuf + len, entry);
2034             treat_file(nbuf);
2035         } else {
2036             fprintf(stderr,"%s: %s/%s: pathname too long\n",
2037                     program_name, dir, entry);
2038             exit_code = ERROR;
2039         }
2040     }
2041     free (entries);
2042 }
2043 #endif /* ! NO_DIR */
2044
2045 /* Make sure signals get handled properly.  */
2046
2047 static void
2048 install_signal_handlers ()
2049 {
2050   int nsigs = sizeof handled_sig / sizeof handled_sig[0];
2051   int i;
2052
2053 #if SA_NOCLDSTOP
2054   struct sigaction act;
2055
2056   sigemptyset (&caught_signals);
2057   for (i = 0; i < nsigs; i++)
2058     {
2059       sigaction (handled_sig[i], NULL, &act);
2060       if (act.sa_handler != SIG_IGN)
2061         sigaddset (&caught_signals, handled_sig[i]);
2062     }
2063
2064   act.sa_handler = abort_gzip_signal;
2065   act.sa_mask = caught_signals;
2066   act.sa_flags = 0;
2067
2068   for (i = 0; i < nsigs; i++)
2069     if (sigismember (&caught_signals, handled_sig[i]))
2070       {
2071         if (i == 0)
2072           foreground = 1;
2073         sigaction (handled_sig[i], &act, NULL);
2074       }
2075 #else
2076   for (i = 0; i < nsigs; i++)
2077     if (signal (handled_sig[i], SIG_IGN) != SIG_IGN)
2078       {
2079         if (i == 0)
2080           foreground = 1;
2081         signal (handled_sig[i], abort_gzip_signal);
2082         siginterrupt (handled_sig[i], 1);
2083       }
2084 #endif
2085 }
2086
2087 /* ========================================================================
2088  * Free all dynamically allocated variables and exit with the given code.
2089  */
2090 local void do_exit(exitcode)
2091     int exitcode;
2092 {
2093     static int in_exit = 0;
2094
2095     if (in_exit) exit(exitcode);
2096     in_exit = 1;
2097     free(env);
2098     env  = NULL;
2099     FREE(inbuf);
2100     FREE(outbuf);
2101     FREE(d_buf);
2102     FREE(window);
2103 #ifndef MAXSEG_64K
2104     FREE(tab_prefix);
2105 #else
2106     FREE(tab_prefix0);
2107     FREE(tab_prefix1);
2108 #endif
2109     exit(exitcode);
2110 }
2111
2112 static void
2113 finish_out (void)
2114 {
2115   if (fclose (stdout) != 0)
2116     write_error ();
2117   do_exit (OK);
2118 }
2119
2120 /* ========================================================================
2121  * Close and unlink the output file.
2122  */
2123 static void
2124 remove_output_file ()
2125 {
2126   int fd;
2127   sigset_t oldset;
2128
2129   sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
2130   fd = remove_ofname_fd;
2131   if (0 <= fd)
2132     {
2133       remove_ofname_fd = -1;
2134       close (fd);
2135       xunlink (ofname);
2136     }
2137   sigprocmask (SIG_SETMASK, &oldset, NULL);
2138 }
2139
2140 /* ========================================================================
2141  * Error handler.
2142  */
2143 void
2144 abort_gzip ()
2145 {
2146    remove_output_file ();
2147    do_exit(ERROR);
2148 }
2149
2150 /* ========================================================================
2151  * Signal handler.
2152  */
2153 static RETSIGTYPE
2154 abort_gzip_signal (sig)
2155      int sig;
2156 {
2157   if (! SA_NOCLDSTOP)
2158     signal (sig, SIG_IGN);
2159    remove_output_file ();
2160    if (sig == exiting_signal)
2161      _exit (WARNING);
2162    signal (sig, SIG_DFL);
2163    raise (sig);
2164 }