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