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