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