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