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