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