maint: update --version copyright dates
[gzip.git] / gzip.c
blobd6afad4f7ee7ca304b13d6691715906a3eef760e
1 /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
3 Copyright (C) 1999, 2001-2002, 2006-2007, 2009-2022 Free Software
4 Foundation, Inc.
5 Copyright (C) 1992-1993 Jean-loup Gailly
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.
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.
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. */
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.
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.
31 static char const *const license_msg[] = {
32 "Copyright (C) 2022 Free Software Foundation, Inc.",
33 "Copyright (C) 1993 Jean-loup Gailly.",
34 "This is free software. You may redistribute copies of it under the terms of",
35 "the GNU General Public License <https://www.gnu.org/licenses/gpl.html>.",
36 "There is NO WARRANTY, to the extent permitted by law.",
37 0};
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.
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.
54 * For the meaning of all compilation flags, see comments in Makefile.in.
57 #include <config.h>
58 #include <ctype.h>
59 #include <sys/types.h>
60 #include <signal.h>
61 #include <stdalign.h>
62 #include <stdbool.h>
63 #include <stddef.h>
64 #include <sys/stat.h>
65 #include <errno.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"
74 #include "dirname.h"
75 #include "dosname.h"
76 #include "fcntl--.h"
77 #include "getopt.h"
78 #include "ignore-value.h"
79 #include "stat-time.h"
80 #include "version.h"
81 #include "xalloc.h"
82 #include "yesno.h"
84 /* configuration */
86 #include <limits.h>
87 #include <unistd.h>
88 #include <stdlib.h>
89 #include <errno.h>
91 #ifndef NO_DIR
92 # define NO_DIR 0
93 #endif
94 #if !NO_DIR
95 # include <dirent.h>
96 # include <savedir.h>
97 #endif
99 #ifndef NO_UTIME
100 # include <utimens.h>
101 #endif
103 #ifndef MAX_PATH_LEN
104 # define MAX_PATH_LEN 1024 /* max pathname length */
105 #endif
107 #ifndef SEEK_END
108 # define SEEK_END 2
109 #endif
111 #ifndef CHAR_BIT
112 # define CHAR_BIT 8
113 #endif
115 #ifdef off_t
116 off_t lseek (int fd, off_t offset, int whence);
117 #endif
119 #ifndef HAVE_WORKING_O_NOFOLLOW
120 # define HAVE_WORKING_O_NOFOLLOW 0
121 #endif
123 /* Separator for file name parts (see shorten_name()) */
124 #ifdef NO_MULTIPLE_DOTS
125 # define PART_SEP "-"
126 #else
127 # define PART_SEP "."
128 #endif
130 /* global buffers */
132 /* With IBM_Z_DFLTCC, DEFLATE COMPRESSION works faster with
133 page-aligned input and output buffers, and requires page-aligned
134 windows; the alignment requirement is 4096. On other platforms
135 alignment doesn't hurt, and alignment up to 4096 is portable so
136 let's do that. */
137 #ifdef __alignas_is_defined
138 # define BUFFER_ALIGNED alignas (4096)
139 #else
140 # define BUFFER_ALIGNED /**/
141 #endif
142 DECLARE(uch BUFFER_ALIGNED, inbuf, INBUFSIZ +INBUF_EXTRA);
143 DECLARE(uch BUFFER_ALIGNED, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
144 DECLARE(ush, d_buf, DIST_BUFSIZE);
145 DECLARE(uch BUFFER_ALIGNED, window, 2L*WSIZE);
146 #ifndef MAXSEG_64K
147 DECLARE(ush, tab_prefix, 1L<<BITS);
148 #else
149 DECLARE(ush, tab_prefix0, 1L<<(BITS-1));
150 DECLARE(ush, tab_prefix1, 1L<<(BITS-1));
151 #endif
153 /* local variables */
155 /* If true, pretend that standard input is a tty. This option
156 is deliberately not documented, and only for testing. */
157 static bool presume_input_tty;
159 /* If true, transfer output data to the output file's storage device
160 when supported. Otherwise, if the system crashes around the time
161 gzip is run, the user might lose both input and output data. See:
162 Pillai TS et al. All file systems are not created equal: on the
163 complexity of crafting crash-consistent applications. OSDI'14. 2014:433-48.
164 https://www.usenix.org/conference/osdi14/technical-sessions/presentation/pillai */
165 static bool synchronous;
167 static int ascii = 0; /* convert end-of-lines to local OS conventions */
168 int to_stdout = 0; /* output to stdout (-c) */
169 static int decompress = 0; /* decompress (-d) */
170 static int force = 0; /* don't ask questions, compress links (-f) */
171 static int keep = 0; /* keep (don't delete) input files */
172 static int no_name = -1; /* don't save or restore the original file name */
173 static int no_time = -1; /* don't save or restore the original file time */
174 static int recursive = 0; /* recurse through directories (-r) */
175 static int list = 0; /* list the file contents (-l) */
176 #ifndef DEBUG
177 static
178 #endif
179 int verbose = 0; /* be verbose (-v) */
180 int quiet = 0; /* be very quiet (-q) */
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 off_t ifile_size; /* input file size, -1 for devices (debug only) */
192 static char *env; /* contents of GZIP env variable */
193 static char const *z_suffix; /* default suffix (can be set with --suffix) */
194 static size_t z_len; /* strlen(z_suffix) */
196 /* The original timestamp (modification time). If the original is
197 unknown, TIME_STAMP.tv_nsec is negative. If the original is
198 greater than struct timespec range, TIME_STAMP is the maximal
199 struct timespec value; this can happen on hosts with 32-bit signed
200 time_t because the gzip format's MTIME is 32-bit unsigned.
201 The original cannot be less than struct timespec range. */
202 struct timespec time_stamp;
204 /* The set of signals that are caught. */
205 static sigset_t caught_signals;
207 /* If nonzero then exit with status WARNING, rather than with the usual
208 signal status, on receipt of a signal with this value. This
209 suppresses a "Broken Pipe" message with some shells. */
210 static int volatile exiting_signal;
212 /* If nonnegative, close this file descriptor and unlink remove_ofname
213 on error. */
214 static int volatile remove_ofname_fd = -1;
215 static char volatile remove_ofname[MAX_PATH_LEN];
217 static bool stdin_was_read;
219 off_t bytes_in; /* number of input bytes */
220 off_t bytes_out; /* number of output bytes */
221 static off_t total_in; /* input bytes for all files */
222 static off_t total_out; /* output bytes for all files */
223 char ifname[MAX_PATH_LEN]; /* input file name */
224 char ofname[MAX_PATH_LEN]; /* output file name */
225 static char dfname[MAX_PATH_LEN]; /* name of dir containing output file */
226 static struct stat istat; /* status for input file */
227 int ifd; /* input file descriptor */
228 int ofd; /* output file descriptor */
229 static int dfd = -1; /* output directory file descriptor */
230 unsigned insize; /* valid bytes in inbuf */
231 unsigned inptr; /* index of next byte to be processed in inbuf */
232 unsigned outcnt; /* bytes in output buffer */
233 int rsync = 0; /* make rsyncable chunks */
235 static int handled_sig[] =
237 /* SIGINT must be first, as 'foreground' depends on it. */
238 SIGINT
240 #ifdef SIGHUP
241 , SIGHUP
242 #endif
243 #if SIGPIPE
244 , SIGPIPE
245 #endif
246 #ifdef SIGTERM
247 , SIGTERM
248 #endif
249 #ifdef SIGXCPU
250 , SIGXCPU
251 #endif
252 #ifdef SIGXFSZ
253 , SIGXFSZ
254 #endif
257 /* For long options that have no equivalent short option, use a
258 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
259 enum
261 PRESUME_INPUT_TTY_OPTION = CHAR_MAX + 1,
262 RSYNCABLE_OPTION,
263 SYNCHRONOUS_OPTION,
265 /* A value greater than all valid long options, used as a flag to
266 distinguish options derived from the GZIP environment variable. */
267 ENV_OPTION
270 static char const shortopts[] = "ab:cdfhH?klLmMnNqrS:tvVZ123456789";
272 static const struct option longopts[] =
274 /* { name has_arg *flag val } */
275 {"ascii", 0, 0, 'a'}, /* ascii text mode */
276 {"to-stdout", 0, 0, 'c'}, /* write output on standard output */
277 {"stdout", 0, 0, 'c'}, /* write output on standard output */
278 {"decompress", 0, 0, 'd'}, /* decompress */
279 {"uncompress", 0, 0, 'd'}, /* decompress */
280 /* {"encrypt", 0, 0, 'e'}, encrypt */
281 {"force", 0, 0, 'f'}, /* force overwrite of output file */
282 {"help", 0, 0, 'h'}, /* give help */
283 /* {"pkzip", 0, 0, 'k'}, force output in pkzip format */
284 {"keep", 0, 0, 'k'}, /* keep (don't delete) input files */
285 {"list", 0, 0, 'l'}, /* list .gz file contents */
286 {"license", 0, 0, 'L'}, /* display software license */
287 {"no-name", 0, 0, 'n'}, /* don't save or restore original name & time */
288 {"name", 0, 0, 'N'}, /* save or restore original name & time */
289 {"-presume-input-tty", no_argument, NULL, PRESUME_INPUT_TTY_OPTION},
290 {"quiet", 0, 0, 'q'}, /* quiet mode */
291 {"silent", 0, 0, 'q'}, /* quiet mode */
292 {"synchronous",0, 0, SYNCHRONOUS_OPTION},
293 {"recursive", 0, 0, 'r'}, /* recurse through directories */
294 {"suffix", 1, 0, 'S'}, /* use given suffix instead of .gz */
295 {"test", 0, 0, 't'}, /* test compressed file integrity */
296 {"verbose", 0, 0, 'v'}, /* verbose mode */
297 {"version", 0, 0, 'V'}, /* display version number */
298 {"fast", 0, 0, '1'}, /* compress faster */
299 {"best", 0, 0, '9'}, /* compress better */
300 {"lzw", 0, 0, 'Z'}, /* make output compatible with old compress */
301 {"bits", 1, 0, 'b'}, /* max number of bits per code (implies -Z) */
302 {"rsyncable", 0, 0, RSYNCABLE_OPTION}, /* make rsync-friendly archive */
303 { 0, 0, 0, 0 }
306 /* local functions */
308 local noreturn void try_help (void);
309 local void help (void);
310 local void license (void);
311 local void version (void);
312 local int input_eof (void);
313 local void treat_stdin (void);
314 local void treat_file (char *iname);
315 local int create_outfile (void);
316 local char *get_suffix (char *name);
317 local int open_input_file (char *iname, struct stat *sbuf);
318 local void discard_input_bytes (size_t nbytes, unsigned int flags);
319 local int make_ofname (void);
320 local void shorten_name (char *name);
321 local int get_method (int in);
322 local void do_list (int method);
323 local int check_ofname (void);
324 local void copy_stat (struct stat *ifstat);
325 local void install_signal_handlers (void);
326 static void remove_output_file (bool);
327 static void abort_gzip_signal (int);
328 local noreturn void do_exit (int exitcode);
329 static void finish_out (void);
330 int main (int argc, char **argv);
331 static int (*work) (int infile, int outfile) = zip; /* function to call */
333 #if ! NO_DIR
334 local void treat_dir (int fd, char *dir);
335 #endif
337 #define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
339 static void
340 try_help ()
342 fprintf (stderr, "Try `%s --help' for more information.\n",
343 program_name);
344 do_exit (ERROR);
347 /* ======================================================================== */
348 local void help()
350 static char const* const help_msg[] = {
351 "Compress or uncompress FILEs (by default, compress FILES in-place).",
353 "Mandatory arguments to long options are mandatory for short options too.",
355 #if O_BINARY
356 " -a, --ascii ascii text; convert end-of-line using local conventions",
357 #endif
358 " -c, --stdout write on standard output, keep original files unchanged",
359 " -d, --decompress decompress",
360 /* -e, --encrypt encrypt */
361 " -f, --force force overwrite of output file and compress links",
362 " -h, --help give this help",
363 /* -k, --pkzip force output in pkzip format */
364 " -k, --keep keep (don't delete) input files",
365 " -l, --list list compressed file contents",
366 " -L, --license display software license",
367 #ifdef UNDOCUMENTED
368 " -m do not save or restore the original modification time",
369 " -M, --time save or restore the original modification time",
370 #endif
371 " -n, --no-name do not save or restore the original name and timestamp",
372 " -N, --name save or restore the original name and timestamp",
373 " -q, --quiet suppress all warnings",
374 #if ! NO_DIR
375 " -r, --recursive operate recursively on directories",
376 #endif
377 " --rsyncable make rsync-friendly archive",
378 " -S, --suffix=SUF use suffix SUF on compressed files",
379 " --synchronous synchronous output (safer if system crashes, but slower)",
380 " -t, --test test compressed file integrity",
381 " -v, --verbose verbose mode",
382 " -V, --version display version number",
383 " -1, --fast compress faster",
384 " -9, --best compress better",
386 "With no FILE, or when FILE is -, read standard input.",
388 "Report bugs to <bug-gzip@gnu.org>.",
390 char const *const *p = help_msg;
392 printf ("Usage: %s [OPTION]... [FILE]...\n", program_name);
393 while (*p) printf ("%s\n", *p++);
396 /* ======================================================================== */
397 local void license()
399 char const *const *p = license_msg;
401 printf ("%s %s\n", program_name, Version);
402 while (*p) printf ("%s\n", *p++);
405 /* ======================================================================== */
406 local void version()
408 license ();
409 printf ("\n");
410 printf ("Written by Jean-loup Gailly.\n");
413 local void progerror (char const *string)
415 int e = errno;
416 fprintf (stderr, "%s: ", program_name);
417 errno = e;
418 perror(string);
419 exit_code = ERROR;
422 /* ======================================================================== */
423 int main (int argc, char **argv)
425 int file_count; /* number of files to process */
426 size_t proglen; /* length of program_name */
427 char **argv_copy;
428 int env_argc;
429 char **env_argv;
431 EXPAND(argc, argv); /* wild card expansion if necessary */
433 program_name = gzip_base_name (argv[0]);
434 proglen = strlen (program_name);
436 /* Suppress .exe for MSDOS and OS/2: */
437 if (4 < proglen && strequ (program_name + proglen - 4, ".exe"))
438 program_name[proglen - 4] = '\0';
440 /* Add options in GZIP environment variable if there is one */
441 argv_copy = argv;
442 env = add_envopt (&env_argc, &argv_copy, OPTIONS_VAR);
443 env_argv = env ? argv_copy : NULL;
445 #ifndef GNU_STANDARD
446 # define GNU_STANDARD 1
447 #endif
448 #if !GNU_STANDARD
449 /* For compatibility with old compress, use program name as an option.
450 * Unless you compile with -DGNU_STANDARD=0, this program will behave as
451 * gzip even if it is invoked under the name gunzip or zcat.
453 * Systems which do not support links can still use -d or -dc.
454 * Ignore an .exe extension for MSDOS and OS/2.
456 if (strncmp (program_name, "un", 2) == 0 /* ungzip, uncompress */
457 || strncmp (program_name, "gun", 3) == 0) /* gunzip */
458 decompress = 1;
459 else if (strequ (program_name + 1, "cat") /* zcat, pcat, gcat */
460 || strequ (program_name, "gzcat")) /* gzcat */
461 decompress = to_stdout = 1;
462 #endif
464 z_suffix = Z_SUFFIX;
465 z_len = strlen(z_suffix);
467 while (true) {
468 int optc;
469 int longind = -1;
471 if (env_argv)
473 if (env_argv[optind] && strequ (env_argv[optind], "--"))
474 optc = ENV_OPTION + '-';
475 else
477 optc = getopt_long (env_argc, env_argv, shortopts, longopts,
478 &longind);
479 if (0 <= optc)
480 optc += ENV_OPTION;
481 else
483 if (optind != env_argc)
485 fprintf (stderr,
486 ("%s: %s: non-option in "OPTIONS_VAR
487 " environment variable\n"),
488 program_name, env_argv[optind]);
489 try_help ();
492 /* Wait until here before warning, so that GZIP='-q'
493 doesn't warn. */
494 if (env_argc != 1 && !quiet)
495 fprintf (stderr,
496 ("%s: warning: "OPTIONS_VAR" environment variable"
497 " is deprecated; use an alias or script\n"),
498 program_name);
500 /* Start processing ARGC and ARGV instead. */
501 free (env_argv);
502 env_argv = NULL;
503 optind = 1;
504 longind = -1;
509 if (!env_argv)
510 optc = getopt_long (argc, argv, shortopts, longopts, &longind);
511 if (optc < 0)
512 break;
514 switch (optc) {
515 case 'a':
516 ascii = 1; break;
517 case 'b':
518 maxbits = atoi(optarg);
519 for (; *optarg; optarg++)
520 if (! ('0' <= *optarg && *optarg <= '9'))
522 fprintf (stderr, "%s: -b operand is not an integer\n",
523 program_name);
524 try_help ();
526 break;
527 case 'c':
528 to_stdout = 1; break;
529 case 'd':
530 decompress = 1; break;
531 case 'f':
532 force++; break;
533 case 'h': case 'H':
534 help (); finish_out (); break;
535 case 'k':
536 keep = 1; break;
537 case 'l':
538 list = decompress = test = to_stdout = 1; break;
539 case 'L':
540 license (); finish_out (); break;
541 case 'm': /* undocumented, may change later */
542 no_time = 1; break;
543 case 'M': /* undocumented, may change later */
544 no_time = 0; break;
545 case 'n':
546 case 'n' + ENV_OPTION:
547 no_name = no_time = 1; break;
548 case 'N':
549 case 'N' + ENV_OPTION:
550 no_name = no_time = 0; break;
551 case PRESUME_INPUT_TTY_OPTION:
552 presume_input_tty = true; break;
553 case 'q':
554 case 'q' + ENV_OPTION:
555 quiet = 1; verbose = 0; break;
556 case 'r':
557 #if NO_DIR
558 fprintf (stderr, "%s: -r not supported on this system\n",
559 program_name);
560 try_help ();
561 #else
562 recursive = 1;
563 #endif
564 break;
566 case RSYNCABLE_OPTION:
567 case RSYNCABLE_OPTION + ENV_OPTION:
568 rsync = 1;
569 break;
570 case 'S':
571 #ifdef NO_MULTIPLE_DOTS
572 if (*optarg == '.') optarg++;
573 #endif
574 z_len = strlen(optarg);
575 z_suffix = optarg;
576 break;
577 case SYNCHRONOUS_OPTION:
578 synchronous = true;
579 break;
580 case 't':
581 test = decompress = to_stdout = 1;
582 break;
583 case 'v':
584 case 'v' + ENV_OPTION:
585 verbose++; quiet = 0; break;
586 case 'V':
587 version (); finish_out (); break;
588 case 'Z':
589 fprintf(stderr, "%s: -Z not supported in this version\n",
590 program_name);
591 try_help ();
592 break;
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 FALLTHROUGH;
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;
603 default:
604 if (ENV_OPTION <= optc && optc != ENV_OPTION + '?')
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"));
615 try_help ();
617 } /* loop on all arguments */
619 /* By default, save name and timestamp on compression but do not
620 * restore them on decompression.
622 if (no_time < 0) no_time = decompress;
623 if (no_name < 0) no_name = decompress;
625 file_count = argc - optind;
627 #if O_BINARY
628 #else
629 if (ascii && !quiet) {
630 fprintf(stderr, "%s: option --ascii ignored on this system\n",
631 program_name);
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);
639 /* Allocate all global buffers (for DYN_ALLOC option) */
640 ALLOC(uch, inbuf, INBUFSIZ +INBUF_EXTRA);
641 ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
642 ALLOC(ush, d_buf, DIST_BUFSIZE);
643 ALLOC(uch, window, 2L*WSIZE);
644 #ifndef MAXSEG_64K
645 ALLOC(ush, tab_prefix, 1L<<BITS);
646 #else
647 ALLOC(ush, tab_prefix0, 1L<<(BITS-1));
648 ALLOC(ush, tab_prefix1, 1L<<(BITS-1));
649 #endif
651 #if SIGPIPE
652 exiting_signal = quiet ? SIGPIPE : 0;
653 #endif
654 install_signal_handlers ();
656 /* And get to work */
657 if (file_count != 0) {
658 if (to_stdout && !test && (!decompress || !ascii)) {
659 SET_BINARY_MODE (STDOUT_FILENO);
661 while (optind < argc) {
662 treat_file(argv[optind++]);
664 } else { /* Standard input */
665 treat_stdin();
667 if (stdin_was_read && close (STDIN_FILENO) != 0)
669 strcpy (ifname, "stdin");
670 read_error ();
672 if (list)
674 /* Output any totals, and check for output errors. */
675 if (!quiet && 1 < file_count)
676 do_list (-1);
677 if (fflush (stdout) != 0)
678 write_error ();
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);
689 /* Return nonzero when at end of file on input. */
690 local int
691 input_eof ()
693 if (!decompress || last_member)
694 return 1;
696 if (inptr == insize)
698 if (insize != INBUFSIZ || fill_inbuf (1) == EOF)
699 return 1;
701 /* Unget the char that fill_inbuf got. */
702 inptr = 0;
705 return 0;
708 static void
709 get_input_size_and_time (void)
711 ifile_size = -1;
712 time_stamp.tv_nsec = -1;
714 /* Record the input file's size and timestamp only if it is a
715 regular file. Doing this for the timestamp helps to keep gzip's
716 output more reproducible when it is used as part of a
717 pipeline. */
719 if (S_ISREG (istat.st_mode))
721 ifile_size = istat.st_size;
722 if (!no_time || list)
723 time_stamp = get_stat_mtime (&istat);
727 /* ========================================================================
728 * Compress or decompress stdin
730 local void treat_stdin()
732 if (!force && !list
733 && (presume_input_tty
734 || isatty (decompress ? STDIN_FILENO : STDOUT_FILENO))) {
735 /* Do not send compressed data to the terminal or read it from
736 * the terminal. We get here when user invoked the program
737 * without parameters, so be helpful. According to the GNU standards:
739 * If there is one behavior you think is most useful when the output
740 * is to a terminal, and another that you think is most useful when
741 * the output is a file or a pipe, then it is usually best to make
742 * the default behavior the one that is useful with output to a
743 * terminal, and have an option for the other behavior.
745 * Here we use the --force option to get the other behavior.
747 if (! quiet)
748 fprintf (stderr,
749 ("%s: compressed data not %s a terminal."
750 " Use -f to force %scompression.\n"
751 "For help, type: %s -h\n"),
752 program_name,
753 decompress ? "read from" : "written to",
754 decompress ? "de" : "",
755 program_name);
756 do_exit(ERROR);
759 if (decompress || !ascii) {
760 SET_BINARY_MODE (STDIN_FILENO);
762 if (!test && (!decompress || !ascii)) {
763 SET_BINARY_MODE (STDOUT_FILENO);
765 strcpy(ifname, "stdin");
766 strcpy(ofname, "stdout");
768 /* Get the file's timestamp and size. */
769 if (fstat (STDIN_FILENO, &istat) != 0)
771 progerror ("standard input");
772 do_exit (ERROR);
775 get_input_size_and_time ();
777 clear_bufs(); /* clear input and output buffers */
778 to_stdout = 1;
779 part_nb = 0;
780 ifd = STDIN_FILENO;
781 stdin_was_read = true;
783 if (decompress) {
784 method = get_method(ifd);
785 if (method < 0) {
786 do_exit(exit_code); /* error message already emitted */
790 /* Actually do the compression/decompression. Loop over zipped members.
792 for (;;) {
793 if (work (STDIN_FILENO, STDOUT_FILENO) != OK)
794 return;
796 if (input_eof ())
797 break;
799 method = get_method(ifd);
800 if (method < 0) return; /* error message already emitted */
801 bytes_out = 0; /* required for length check */
804 if (list)
806 do_list (method);
807 return;
810 if (verbose) {
811 if (test) {
812 fprintf(stderr, " OK\n");
814 } else if (!decompress) {
815 display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
816 fprintf(stderr, "\n");
817 #ifdef DISPLAY_STDIN_RATIO
818 } else {
819 display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
820 fprintf(stderr, "\n");
821 #endif
826 static char const dot = '.';
828 /* True if the cached directory for calls to openat etc. is DIR, with
829 length DIRLEN. DIR need not be null-terminated. DIRLEN must be
830 less than MAX_PATH_LEN. */
831 static bool
832 atdir_eq (char const *dir, ptrdiff_t dirlen)
834 if (dirlen == 0)
835 dir = &dot, dirlen = 1;
836 return memcmp (dfname, dir, dirlen) == 0 && !dfname[dirlen];
839 /* Set the directory used for calls to openat etc. to be the directory
840 DIR, with length DIRLEN. DIR need not be null-terminated.
841 DIRLEN must be less than MAX_PATH_LEN. Return a file descriptor for
842 the directory, or -1 if one could not be obtained. */
843 static int
844 atdir_set (char const *dir, ptrdiff_t dirlen)
846 /* Don't bother opening directories on older systems that
847 lack openat and unlinkat. It's not worth the porting hassle. */
848 #if HAVE_OPENAT && HAVE_UNLINKAT
849 enum { try_opening_directories = true };
850 #else
851 enum { try_opening_directories = false };
852 #endif
854 if (try_opening_directories && ! atdir_eq (dir, dirlen))
856 if (0 <= dfd)
857 close (dfd);
858 if (dirlen == 0)
859 dir = &dot, dirlen = 1;
860 memcpy (dfname, dir, dirlen);
861 dfname[dirlen] = '\0';
862 dfd = open (dfname, O_SEARCH | O_DIRECTORY);
865 return dfd;
868 /* ========================================================================
869 * Compress or decompress the given file
871 local void treat_file(iname)
872 char *iname;
874 /* Accept "-" as synonym for stdin */
875 if (strequ(iname, "-")) {
876 int cflag = to_stdout;
877 treat_stdin();
878 to_stdout = cflag;
879 return;
882 /* Check if the input file is present, set ifname and istat: */
883 ifd = open_input_file (iname, &istat);
884 if (ifd < 0)
885 return;
887 /* If the input name is that of a directory, recurse or ignore: */
888 if (S_ISDIR(istat.st_mode)) {
889 #if ! NO_DIR
890 if (recursive) {
891 treat_dir (ifd, iname);
892 /* Warning: ifname is now garbage */
893 return;
895 #endif
896 close (ifd);
897 WARN ((stderr, "%s: %s is a directory -- ignored\n",
898 program_name, ifname));
899 return;
902 if (! to_stdout)
904 if (! S_ISREG (istat.st_mode))
906 WARN ((stderr,
907 "%s: %s is not a directory or a regular file - ignored\n",
908 program_name, ifname));
909 close (ifd);
910 return;
912 if (istat.st_mode & S_ISUID)
914 WARN ((stderr, "%s: %s is set-user-ID on execution - ignored\n",
915 program_name, ifname));
916 close (ifd);
917 return;
919 if (istat.st_mode & S_ISGID)
921 WARN ((stderr, "%s: %s is set-group-ID on execution - ignored\n",
922 program_name, ifname));
923 close (ifd);
924 return;
927 if (! force)
929 if (istat.st_mode & S_ISVTX)
931 WARN ((stderr,
932 "%s: %s has the sticky bit set - file ignored\n",
933 program_name, ifname));
934 close (ifd);
935 return;
937 if (2 <= istat.st_nlink)
939 WARN ((stderr, "%s: %s has %lu other link%s -- file ignored\n",
940 program_name, ifname,
941 (unsigned long int) istat.st_nlink - 1,
942 istat.st_nlink == 2 ? "" : "s"));
943 close (ifd);
944 return;
949 get_input_size_and_time ();
951 /* Generate output file name. For -r and (-t or -l), skip files
952 * without a valid gzip suffix (check done in make_ofname).
954 if (to_stdout && !test) {
955 strcpy(ofname, "stdout");
957 } else if (make_ofname() != OK) {
958 close (ifd);
959 return;
962 clear_bufs(); /* clear input and output buffers */
963 part_nb = 0;
965 if (decompress) {
966 method = get_method(ifd); /* updates ofname if original given */
967 if (method < 0) {
968 close(ifd);
969 return; /* error message already emitted */
973 /* If compressing to a file, check if ofname is not ambiguous
974 * because the operating system truncates names. Otherwise, generate
975 * a new ofname and save the original name in the compressed file.
977 if (to_stdout) {
978 ofd = STDOUT_FILENO;
979 /* Keep remove_ofname_fd negative. */
980 } else {
981 if (create_outfile() != OK) return;
983 if (!decompress && save_orig_name && !verbose && !quiet) {
984 fprintf(stderr, "%s: %s compressed to %s\n",
985 program_name, ifname, ofname);
988 /* Keep the name even if not truncated except with --no-name: */
989 if (!save_orig_name) save_orig_name = !no_name;
991 if (verbose && !list) {
992 fprintf(stderr, "%s:\t", ifname);
995 /* Actually do the compression/decompression. Loop over zipped members.
997 for (;;) {
998 if ((*work)(ifd, ofd) != OK) {
999 method = -1; /* force cleanup */
1000 break;
1003 if (input_eof ())
1004 break;
1006 method = get_method(ifd);
1007 if (method < 0) break; /* error message already emitted */
1008 bytes_out = 0; /* required for length check */
1011 if (close (ifd) != 0)
1012 read_error ();
1014 if (list)
1016 do_list (method);
1017 return;
1020 if (!to_stdout)
1022 copy_stat (&istat);
1024 if ((synchronous
1025 && ((0 <= dfd && fdatasync (dfd) != 0 && errno != EINVAL)
1026 || (fsync (ofd) != 0 && errno != EINVAL)))
1027 || close (ofd) != 0)
1028 write_error ();
1030 if (!keep)
1032 sigset_t oldset;
1033 int unlink_errno;
1034 char *ifbase = last_component (ifname);
1035 int ufd = atdir_eq (ifname, ifbase - ifname) ? dfd : -1;
1036 int res;
1038 sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
1039 remove_ofname_fd = -1;
1040 res = ufd < 0 ? xunlink (ifname) : unlinkat (ufd, ifbase, 0);
1041 unlink_errno = res == 0 ? 0 : errno;
1042 sigprocmask (SIG_SETMASK, &oldset, NULL);
1044 if (unlink_errno)
1046 WARN ((stderr, "%s: ", program_name));
1047 if (!quiet)
1049 errno = unlink_errno;
1050 perror (ifname);
1056 if (method == -1) {
1057 if (!to_stdout)
1058 remove_output_file (false);
1059 return;
1062 /* Display statistics */
1063 if(verbose) {
1064 if (test) {
1065 fprintf(stderr, " OK");
1066 } else if (decompress) {
1067 display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
1068 } else {
1069 display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
1071 if (!test)
1072 fprintf(stderr, " -- %s %s", keep ? "created" : "replaced with",
1073 ofname);
1074 fprintf(stderr, "\n");
1078 static void
1079 volatile_strcpy (char volatile *dst, char const volatile *src)
1081 while ((*dst++ = *src++))
1082 continue;
1085 /* ========================================================================
1086 * Create the output file. Return OK or ERROR.
1087 * Try several times if necessary to avoid truncating the z_suffix. For
1088 * example, do not create a compressed file of name "1234567890123."
1089 * Sets save_orig_name to true if the file name has been truncated.
1090 * IN assertions: the input file has already been open (ifd is set) and
1091 * ofname has already been updated if there was an original name.
1092 * OUT assertions: ifd and ofd are closed in case of error.
1094 local int create_outfile()
1096 int name_shortened = 0;
1097 int flags = (O_WRONLY | O_CREAT | O_EXCL
1098 | (ascii && decompress ? 0 : O_BINARY));
1099 char const *base = ofname;
1100 int atfd = AT_FDCWD;
1102 if (!keep)
1104 char const *b = last_component (ofname);
1105 int f = atdir_set (ofname, b - ofname);
1106 if (0 <= f)
1108 base = b;
1109 atfd = f;
1113 for (;;)
1115 int open_errno;
1116 sigset_t oldset;
1118 volatile_strcpy (remove_ofname, ofname);
1120 sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
1121 remove_ofname_fd = ofd = openat (atfd, base, flags, S_IRUSR | S_IWUSR);
1122 open_errno = errno;
1123 sigprocmask (SIG_SETMASK, &oldset, NULL);
1125 if (0 <= ofd)
1126 break;
1128 switch (open_errno)
1130 #ifdef ENAMETOOLONG
1131 case ENAMETOOLONG:
1132 shorten_name (ofname);
1133 name_shortened = 1;
1134 break;
1135 #endif
1137 case EEXIST:
1138 if (check_ofname () != OK)
1140 close (ifd);
1141 return ERROR;
1143 break;
1145 default:
1146 progerror (ofname);
1147 close (ifd);
1148 return ERROR;
1152 if (name_shortened && decompress)
1154 /* name might be too long if an original name was saved */
1155 WARN ((stderr, "%s: %s: warning, name truncated\n",
1156 program_name, ofname));
1159 return OK;
1162 /* ========================================================================
1163 * Return a pointer to the 'z' suffix of a file name, or NULL. For all
1164 * systems, ".gz", ".z", ".Z", ".taz", ".tgz", "-gz", "-z" and "_z" are
1165 * accepted suffixes, in addition to the value of the --suffix option.
1166 * ".tgz" is a useful convention for tar.z files on systems limited
1167 * to 3 characters extensions. On such systems, ".?z" and ".??z" are
1168 * also accepted suffixes. For Unix, we do not want to accept any
1169 * .??z suffix as indicating a compressed file; some people use .xyz
1170 * to denote volume data.
1172 local char *get_suffix(name)
1173 char *name;
1175 int nlen, slen;
1176 char suffix[MAX_SUFFIX+3]; /* last chars of name, forced to lower case */
1177 static char const *known_suffixes[] =
1178 {NULL, ".gz", ".z", ".taz", ".tgz", "-gz", "-z", "_z",
1179 #ifdef MAX_EXT_CHARS
1180 "z",
1181 #endif
1182 NULL, NULL};
1183 char const **suf;
1184 bool suffix_of_builtin = false;
1186 /* Normally put Z_SUFFIX at the start of KNOWN_SUFFIXES, but if it
1187 is a suffix of one of them, put it at the end. */
1188 for (suf = known_suffixes + 1; *suf; suf++)
1190 size_t suflen = strlen (*suf);
1191 if (z_len < suflen && strequ (z_suffix, *suf + suflen - z_len))
1193 suffix_of_builtin = true;
1194 break;
1198 char *z_lower = xstrdup(z_suffix);
1199 strlwr(z_lower);
1200 known_suffixes[suffix_of_builtin
1201 ? sizeof known_suffixes / sizeof *known_suffixes - 2
1202 : 0] = z_lower;
1203 suf = known_suffixes + suffix_of_builtin;
1205 nlen = strlen(name);
1206 if (nlen <= MAX_SUFFIX+2) {
1207 strcpy(suffix, name);
1208 } else {
1209 strcpy(suffix, name+nlen-MAX_SUFFIX-2);
1211 strlwr(suffix);
1212 slen = strlen(suffix);
1213 char *match = NULL;
1214 do {
1215 int s = strlen(*suf);
1216 if (slen > s && ! ISSLASH (suffix[slen - s - 1])
1217 && strequ(suffix + slen - s, *suf)) {
1218 match = name+nlen-s;
1219 break;
1221 } while (*++suf != NULL);
1222 free(z_lower);
1224 return match;
1228 /* Open file NAME with the given flags and store its status
1229 into *ST. Return a file descriptor to the newly opened file, or -1
1230 (setting errno) on failure. */
1231 static int
1232 open_and_stat (char *name, int flags, struct stat *st)
1234 int fd;
1235 int atfd = AT_FDCWD;
1236 char const *base = name;
1238 /* Refuse to follow symbolic links unless -c or -f. */
1239 if (!to_stdout && !force)
1241 if (HAVE_WORKING_O_NOFOLLOW)
1242 flags |= O_NOFOLLOW;
1243 else
1245 #ifdef S_ISLNK
1246 if (lstat (name, st) != 0)
1247 return -1;
1248 else if (S_ISLNK (st->st_mode))
1250 errno = ELOOP;
1251 return -1;
1253 #endif
1257 if (!keep)
1259 char const *b = last_component (name);
1260 int f = atdir_set (name, b - name);
1261 if (0 <= f)
1263 base = b;
1264 atfd = f;
1268 fd = openat (atfd, base, flags);
1269 if (0 <= fd && fstat (fd, st) != 0)
1271 int e = errno;
1272 close (fd);
1273 errno = e;
1274 return -1;
1276 return fd;
1280 /* ========================================================================
1281 * Set ifname to the input file name (with a suffix appended if necessary)
1282 * and istat to its stats. For decompression, if no file exists with the
1283 * original name, try adding successively z_suffix, .gz, .z, -z and .Z.
1284 * For MSDOS, we try only z_suffix and z.
1285 * Return an open file descriptor or -1.
1287 static int
1288 open_input_file (iname, sbuf)
1289 char *iname;
1290 struct stat *sbuf;
1292 int ilen; /* strlen(ifname) */
1293 int z_suffix_errno = 0;
1294 static char const *suffixes[] = {NULL, ".gz", ".z", "-z", ".Z", NULL};
1295 char const **suf = suffixes;
1296 char const *s;
1297 #ifdef NO_MULTIPLE_DOTS
1298 char *dot; /* pointer to ifname extension, or NULL */
1299 #endif
1300 int fd;
1301 int open_flags = (O_RDONLY | O_NONBLOCK | O_NOCTTY
1302 | (ascii && !decompress ? 0 : O_BINARY));
1304 *suf = z_suffix;
1306 if (sizeof ifname - 1 <= strlen (iname))
1307 goto name_too_long;
1309 strcpy(ifname, iname);
1311 /* If input file exists, return OK. */
1312 fd = open_and_stat (ifname, open_flags, sbuf);
1313 if (0 <= fd)
1314 return fd;
1316 if (!decompress || errno != ENOENT) {
1317 progerror(ifname);
1318 return -1;
1320 /* File.ext doesn't exist. Try adding a suffix. */
1321 s = get_suffix(ifname);
1322 if (s != NULL) {
1323 progerror(ifname); /* ifname already has z suffix and does not exist */
1324 return -1;
1326 #ifdef NO_MULTIPLE_DOTS
1327 dot = strrchr(ifname, '.');
1328 if (dot == NULL) {
1329 strcat(ifname, ".");
1330 dot = strrchr(ifname, '.');
1332 #endif
1333 ilen = strlen(ifname);
1334 if (strequ(z_suffix, ".gz")) suf++;
1336 /* Search for all suffixes */
1337 do {
1338 char const *s0 = s = *suf;
1339 strcpy (ifname, iname);
1340 #ifdef NO_MULTIPLE_DOTS
1341 if (*s == '.') s++;
1342 if (*dot == '\0') strcpy (dot, ".");
1343 #endif
1344 #ifdef MAX_EXT_CHARS
1345 if (MAX_EXT_CHARS < strlen (s) + strlen (dot + 1))
1346 dot[MAX_EXT_CHARS + 1 - strlen (s)] = '\0';
1347 #endif
1348 if (sizeof ifname <= ilen + strlen (s))
1349 goto name_too_long;
1350 strcat(ifname, s);
1351 fd = open_and_stat (ifname, open_flags, sbuf);
1352 if (0 <= fd)
1353 return fd;
1354 if (errno != ENOENT)
1356 progerror (ifname);
1357 return -1;
1359 if (strequ (s0, z_suffix))
1360 z_suffix_errno = errno;
1361 } while (*++suf != NULL);
1363 /* No suffix found, complain using z_suffix: */
1364 strcpy(ifname, iname);
1365 #ifdef NO_MULTIPLE_DOTS
1366 if (*dot == '\0') strcpy(dot, ".");
1367 #endif
1368 #ifdef MAX_EXT_CHARS
1369 if (MAX_EXT_CHARS < z_len + strlen (dot + 1))
1370 dot[MAX_EXT_CHARS + 1 - z_len] = '\0';
1371 #endif
1372 strcat(ifname, z_suffix);
1373 errno = z_suffix_errno;
1374 progerror(ifname);
1375 return -1;
1377 name_too_long:
1378 fprintf (stderr, "%s: %s: file name too long\n", program_name, iname);
1379 exit_code = ERROR;
1380 return -1;
1383 /* ========================================================================
1384 * Generate ofname given ifname. Return OK, or WARNING if file must be skipped.
1385 * Sets save_orig_name to true if the file name has been truncated.
1387 local int make_ofname()
1389 char *suff; /* ofname z suffix */
1391 strcpy(ofname, ifname);
1392 /* strip a version number if any and get the gzip suffix if present: */
1393 suff = get_suffix(ofname);
1395 if (decompress) {
1396 if (suff == NULL) {
1397 /* With -t or -l, try all files (even without .gz suffix)
1398 * except with -r (behave as with just -dr).
1400 if (!recursive && test)
1401 return OK;
1403 /* Avoid annoying messages with -r */
1404 if (verbose || (!recursive && !quiet)) {
1405 WARN((stderr,"%s: %s: unknown suffix -- ignored\n",
1406 program_name, ifname));
1408 return WARNING;
1410 /* Make a special case for .tgz and .taz: */
1411 strlwr(suff);
1412 if (strequ(suff, ".tgz") || strequ(suff, ".taz")) {
1413 strcpy(suff, ".tar");
1414 } else {
1415 *suff = '\0'; /* strip the z suffix */
1417 /* ofname might be changed later if infile contains an original name */
1419 } else if (suff && ! force) {
1420 /* Avoid annoying messages with -r (see treat_dir()) */
1421 if (verbose || (!recursive && !quiet)) {
1422 /* Don't use WARN, as it affects exit status. */
1423 fprintf (stderr, "%s: %s already has %s suffix -- unchanged\n",
1424 program_name, ifname, suff);
1426 return WARNING;
1427 } else {
1428 save_orig_name = 0;
1430 #ifdef NO_MULTIPLE_DOTS
1431 suff = strrchr(ofname, '.');
1432 if (suff == NULL) {
1433 if (sizeof ofname <= strlen (ofname) + 1)
1434 goto name_too_long;
1435 strcat(ofname, ".");
1436 # ifdef MAX_EXT_CHARS
1437 if (strequ(z_suffix, "z")) {
1438 if (sizeof ofname <= strlen (ofname) + 2)
1439 goto name_too_long;
1440 strcat(ofname, "gz"); /* enough room */
1441 return OK;
1443 /* On the Atari and some versions of MSDOS,
1444 * ENAMETOOLONG does not work correctly. So we
1445 * must truncate here.
1447 } else if (strlen(suff)-1 + z_len > MAX_SUFFIX) {
1448 suff[MAX_SUFFIX+1-z_len] = '\0';
1449 save_orig_name = 1;
1450 # endif
1452 #endif /* NO_MULTIPLE_DOTS */
1453 if (sizeof ofname <= strlen (ofname) + z_len)
1454 goto name_too_long;
1455 strcat(ofname, z_suffix);
1457 } /* decompress ? */
1458 return OK;
1460 name_too_long:
1461 WARN ((stderr, "%s: %s: file name too long\n", program_name, ifname));
1462 return WARNING;
1465 /* Discard NBYTES input bytes from the input, or up through the next
1466 zero byte if NBYTES == (size_t) -1. If FLAGS say that the header
1467 CRC should be computed, update the CRC accordingly. */
1468 static void
1469 discard_input_bytes (nbytes, flags)
1470 size_t nbytes;
1471 unsigned int flags;
1473 while (nbytes != 0)
1475 uch c = get_byte ();
1476 if (flags & HEADER_CRC)
1477 updcrc (&c, 1);
1478 if (nbytes != (size_t) -1)
1479 nbytes--;
1480 else if (! c)
1481 break;
1485 /* ========================================================================
1486 * Check the magic number of the input file and update ofname if an
1487 * original name was given and to_stdout is not set.
1488 * Return the compression method, -1 for error, -2 for warning.
1489 * Set inptr to the offset of the next byte to be processed.
1490 * Updates time_stamp if there is one and neither -m nor -n is used.
1491 * This function may be called repeatedly for an input file consisting
1492 * of several contiguous gzip'ed members.
1493 * IN assertions: there is at least one remaining compressed member.
1494 * If the member is a zip file, it must be the only one.
1496 local int get_method(in)
1497 int in; /* input file descriptor */
1499 uch flags; /* compression flags */
1500 uch magic[10]; /* magic header */
1501 int imagic0; /* first magic byte or EOF */
1502 int imagic1; /* like magic[1], but can represent EOF */
1503 ulg stamp; /* timestamp */
1505 /* If --force and --stdout, zcat == cat, so do not complain about
1506 * premature end of file: use try_byte instead of get_byte.
1508 if (force && to_stdout) {
1509 imagic0 = try_byte();
1510 magic[0] = imagic0;
1511 imagic1 = try_byte ();
1512 magic[1] = imagic1;
1513 /* If try_byte returned EOF, magic[1] == (char) EOF. */
1514 } else {
1515 magic[0] = get_byte ();
1516 imagic0 = 0;
1517 if (magic[0]) {
1518 magic[1] = get_byte ();
1519 imagic1 = 0; /* avoid lint warning */
1520 } else {
1521 imagic1 = try_byte ();
1522 magic[1] = imagic1;
1525 method = -1; /* unknown yet */
1526 part_nb++; /* number of parts in gzip file */
1527 header_bytes = 0;
1528 last_member = 0;
1529 /* assume multiple members in gzip file except for record oriented I/O */
1531 if (memcmp(magic, GZIP_MAGIC, 2) == 0
1532 || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
1534 method = (int)get_byte();
1535 if (method != DEFLATED) {
1536 fprintf(stderr,
1537 "%s: %s: unknown method %d -- not supported\n",
1538 program_name, ifname, method);
1539 exit_code = ERROR;
1540 return -1;
1542 work = unzip;
1543 flags = (uch)get_byte();
1545 if ((flags & ENCRYPTED) != 0) {
1546 fprintf(stderr,
1547 "%s: %s is encrypted -- not supported\n",
1548 program_name, ifname);
1549 exit_code = ERROR;
1550 return -1;
1552 if ((flags & RESERVED) != 0) {
1553 fprintf(stderr,
1554 "%s: %s has flags 0x%x -- not supported\n",
1555 program_name, ifname, flags);
1556 exit_code = ERROR;
1557 if (force <= 1) return -1;
1559 stamp = (ulg)get_byte();
1560 stamp |= ((ulg)get_byte()) << 8;
1561 stamp |= ((ulg)get_byte()) << 16;
1562 stamp |= ((ulg)get_byte()) << 24;
1563 if (stamp != 0 && !no_time)
1565 if (stamp <= TYPE_MAXIMUM (time_t))
1567 time_stamp.tv_sec = stamp;
1568 time_stamp.tv_nsec = 0;
1570 else
1572 WARN ((stderr,
1573 "%s: %s: MTIME %lu out of range for this platform\n",
1574 program_name, ifname, stamp));
1575 time_stamp.tv_sec = TYPE_MAXIMUM (time_t);
1576 time_stamp.tv_nsec = TIMESPEC_RESOLUTION - 1;
1580 magic[8] = get_byte (); /* Ignore extra flags. */
1581 magic[9] = get_byte (); /* Ignore OS type. */
1583 if (flags & HEADER_CRC)
1585 magic[2] = DEFLATED;
1586 magic[3] = flags;
1587 magic[4] = stamp & 0xff;
1588 magic[5] = (stamp >> 8) & 0xff;
1589 magic[6] = (stamp >> 16) & 0xff;
1590 magic[7] = stamp >> 24;
1591 updcrc (NULL, 0);
1592 updcrc (magic, 10);
1595 if ((flags & EXTRA_FIELD) != 0) {
1596 uch lenbuf[2];
1597 unsigned int len = lenbuf[0] = get_byte ();
1598 len |= (lenbuf[1] = get_byte ()) << 8;
1599 if (verbose) {
1600 fprintf(stderr,"%s: %s: extra field of %u bytes ignored\n",
1601 program_name, ifname, len);
1603 if (flags & HEADER_CRC)
1604 updcrc (lenbuf, 2);
1605 discard_input_bytes (len, flags);
1608 /* Get original file name if it was truncated */
1609 if ((flags & ORIG_NAME) != 0) {
1610 if (no_name || (to_stdout && !list) || part_nb > 1) {
1611 /* Discard the old name */
1612 discard_input_bytes (-1, flags);
1613 } else {
1614 /* Copy the base name. Keep a directory prefix intact. */
1615 char *p = gzip_base_name (ofname);
1616 char *base = p;
1617 for (;;) {
1618 *p = (char) get_byte ();
1619 if (*p++ == '\0') break;
1620 if (p >= ofname+sizeof(ofname)) {
1621 gzip_error ("corrupted input -- file name too large");
1624 if (flags & HEADER_CRC)
1625 updcrc ((uch *) base, p - base);
1626 p = gzip_base_name (base);
1627 memmove (base, p, strlen (p) + 1);
1628 /* If necessary, adapt the name to local OS conventions: */
1629 if (!list) {
1630 MAKE_LEGAL_NAME(base);
1631 if (base) list=0; /* avoid warning about unused variable */
1633 } /* no_name || to_stdout */
1634 } /* ORIG_NAME */
1636 /* Discard file comment if any */
1637 if ((flags & COMMENT) != 0) {
1638 discard_input_bytes (-1, flags);
1641 if (flags & HEADER_CRC)
1643 unsigned int crc16 = updcrc (magic, 0) & 0xffff;
1644 unsigned int header16 = get_byte ();
1645 header16 |= ((unsigned int) get_byte ()) << 8;
1646 if (header16 != crc16)
1648 fprintf (stderr,
1649 "%s: %s: header checksum 0x%04x != computed checksum 0x%04x\n",
1650 program_name, ifname, header16, crc16);
1651 exit_code = ERROR;
1652 if (force <= 1)
1653 return -1;
1657 if (part_nb == 1) {
1658 header_bytes = inptr + 2*4; /* include crc and size */
1661 } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
1662 && memcmp((char*)inbuf, PKZIP_MAGIC, 4) == 0) {
1663 /* To simplify the code, we support a zip file when alone only.
1664 * We are thus guaranteed that the entire local header fits in inbuf.
1666 inptr = 0;
1667 work = unzip;
1668 if (check_zipfile(in) != OK) return -1;
1669 /* check_zipfile may get ofname from the local header */
1670 last_member = 1;
1672 } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
1673 work = unpack;
1674 method = PACKED;
1676 } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {
1677 work = unlzw;
1678 method = COMPRESSED;
1679 last_member = 1;
1681 } else if (memcmp(magic, LZH_MAGIC, 2) == 0) {
1682 work = unlzh;
1683 method = LZHED;
1684 last_member = 1;
1686 } else if (force && to_stdout && !list) { /* pass input unchanged */
1687 method = STORED;
1688 work = copy;
1689 if (imagic1 != EOF)
1690 inptr--;
1691 last_member = 1;
1692 if (imagic0 != EOF) {
1693 write_buf (STDOUT_FILENO, magic, 1);
1696 if (method >= 0) return method;
1698 if (part_nb == 1) {
1699 fprintf (stderr, "\n%s: %s: not in gzip format\n",
1700 program_name, ifname);
1701 exit_code = ERROR;
1702 return -1;
1703 } else {
1704 if (magic[0] == 0)
1706 int inbyte;
1707 for (inbyte = imagic1; inbyte == 0; inbyte = try_byte ())
1708 continue;
1709 if (inbyte == EOF)
1711 if (verbose)
1712 WARN ((stderr, "\n%s: %s: decompression OK, trailing zero bytes ignored\n",
1713 program_name, ifname));
1714 return -3;
1718 WARN((stderr, "\n%s: %s: decompression OK, trailing garbage ignored\n",
1719 program_name, ifname));
1720 return -2;
1724 /* ========================================================================
1725 * Display the characteristics of the compressed file.
1726 * If the given method is < 0, display the accumulated totals.
1727 * IN assertions: time_stamp, header_bytes and ifile_size are initialized.
1729 static void
1730 do_list (int method)
1732 ulg crc; /* original crc */
1733 static int first_time = 1;
1734 static char const *const methods[MAX_METHODS] = {
1735 "store", /* 0 */
1736 "compr", /* 1 */
1737 "pack ", /* 2 */
1738 "lzh ", /* 3 */
1739 "", "", "", "", /* 4 to 7 reserved */
1740 "defla"}; /* 8 */
1741 int positive_off_t_width = INT_STRLEN_BOUND (off_t) - 1;
1743 if (first_time && method >= 0) {
1744 first_time = 0;
1745 if (verbose) {
1746 printf("method crc date time ");
1748 if (!quiet) {
1749 printf("%*.*s %*.*s ratio uncompressed_name\n",
1750 positive_off_t_width, positive_off_t_width, "compressed",
1751 positive_off_t_width, positive_off_t_width, "uncompressed");
1753 } else if (method < 0) {
1754 if (total_in <= 0 || total_out <= 0) return;
1755 if (verbose) {
1756 printf(" ");
1758 if (verbose || !quiet) {
1759 fprint_off(stdout, total_in, positive_off_t_width);
1760 printf(" ");
1761 fprint_off(stdout, total_out, positive_off_t_width);
1762 printf(" ");
1764 display_ratio(total_out-(total_in-header_bytes), total_out, stdout);
1765 /* header_bytes is not meaningful but used to ensure the same
1766 * ratio if there is a single file.
1768 printf(" (totals)\n");
1769 return;
1771 crc = (ulg)~0; /* unknown */
1773 if (method == DEFLATED && !last_member) {
1774 crc = unzip_crc;
1777 if (verbose)
1779 static char const month_abbr[][4]
1780 = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1781 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
1782 struct tm *tm = localtime (&time_stamp.tv_sec);
1783 printf ("%5s %08lx ", methods[method], crc);
1784 if (tm)
1785 printf ("%s%3d %02d:%02d ", month_abbr[tm->tm_mon],
1786 tm->tm_mday, tm->tm_hour, tm->tm_min);
1787 else
1788 printf ("??? ?? ??:?? ");
1790 fprint_off(stdout, bytes_in, positive_off_t_width);
1791 printf(" ");
1792 fprint_off(stdout, bytes_out, positive_off_t_width);
1793 printf(" ");
1794 if (bytes_in == -1L) {
1795 total_in = -1L;
1796 bytes_in = bytes_out = header_bytes = 0;
1797 } else if (total_in >= 0) {
1798 total_in += bytes_in;
1800 if (bytes_out == -1L) {
1801 total_out = -1L;
1802 bytes_in = bytes_out = header_bytes = 0;
1803 } else if (total_out >= 0) {
1804 total_out += bytes_out;
1806 display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out, stdout);
1807 printf(" %s\n", ofname);
1810 /* ========================================================================
1811 * Shorten the given name by one character, or replace a .tar extension
1812 * with .tgz. Truncate the last part of the name which is longer than
1813 * MIN_PART characters: 1234.678.012.gz -> 123.678.012.gz. If the name
1814 * has only parts shorter than MIN_PART truncate the longest part.
1815 * For decompression, just remove the last character of the name.
1817 * IN assertion: for compression, the suffix of the given name is z_suffix.
1819 local void shorten_name(name)
1820 char *name;
1822 int len; /* length of name without z_suffix */
1823 char *trunc = NULL; /* character to be truncated */
1824 int plen; /* current part length */
1825 int min_part = MIN_PART; /* current minimum part length */
1826 char *p;
1828 len = strlen(name);
1829 if (decompress) {
1830 if (len <= 1)
1831 gzip_error ("name too short");
1832 name[len-1] = '\0';
1833 return;
1835 p = get_suffix(name);
1836 if (! p)
1837 gzip_error ("can't recover suffix\n");
1838 *p = '\0';
1839 save_orig_name = 1;
1841 /* compress 1234567890.tar to 1234567890.tgz */
1842 if (len > 4 && strequ(p-4, ".tar")) {
1843 strcpy(p-4, ".tgz");
1844 return;
1846 /* Try keeping short extensions intact:
1847 * 1234.678.012.gz -> 123.678.012.gz
1849 do {
1850 p = last_component (name);
1851 while (*p) {
1852 plen = strcspn(p, PART_SEP);
1853 p += plen;
1854 if (plen > min_part) trunc = p-1;
1855 if (*p) p++;
1857 } while (trunc == NULL && --min_part != 0);
1859 if (trunc != NULL) {
1860 do {
1861 trunc[0] = trunc[1];
1862 } while (*trunc++);
1863 trunc--;
1864 } else {
1865 trunc = strrchr(name, PART_SEP[0]);
1866 if (!trunc)
1867 gzip_error ("internal error in shorten_name");
1868 if (trunc[1] == '\0') trunc--; /* force truncation */
1870 strcpy(trunc, z_suffix);
1873 /* ========================================================================
1874 * The compressed file already exists, so ask for confirmation.
1875 * Return ERROR if the file must be skipped.
1877 local int check_ofname()
1879 /* Ask permission to overwrite the existing file */
1880 if (!force) {
1881 int ok = 0;
1882 fprintf (stderr, "%s: %s already exists;", program_name, ofname);
1883 if (foreground && (presume_input_tty || isatty (STDIN_FILENO))) {
1884 fprintf(stderr, " do you wish to overwrite (y or n)? ");
1885 fflush(stderr);
1886 ok = yesno();
1888 if (!ok) {
1889 fprintf(stderr, "\tnot overwritten\n");
1890 if (exit_code == OK) exit_code = WARNING;
1891 return ERROR;
1894 if (xunlink (ofname)) {
1895 progerror(ofname);
1896 return ERROR;
1898 return OK;
1901 /* Change the owner and group of a file. FD is a file descriptor for
1902 the file and NAME its name. Change it to user UID and to group GID.
1903 If UID or GID is -1, though, do not change the corresponding user
1904 or group. */
1905 #if ! (HAVE_FCHOWN || HAVE_CHOWN)
1906 /* The types uid_t and gid_t do not exist on mingw, so don't assume them. */
1907 # define do_chown(fd, name, uid, gid) ((void) 0)
1908 #else
1909 static void
1910 do_chown (int fd, char const *name, uid_t uid, gid_t gid)
1912 # if HAVE_FCHOWN
1913 ignore_value (fchown (fd, uid, gid));
1914 # else
1915 ignore_value (chown (name, uid, gid));
1916 # endif
1918 #endif
1920 /* ========================================================================
1921 * Copy modes, times, ownership from input file to output file.
1922 * IN assertion: to_stdout is false.
1924 local void copy_stat(ifstat)
1925 struct stat *ifstat;
1927 mode_t mode = ifstat->st_mode & S_IRWXUGO;
1928 int r;
1930 #ifndef NO_UTIME
1931 bool restoring;
1932 struct timespec timespec[2];
1933 timespec[0] = get_stat_atime (ifstat);
1934 timespec[1] = get_stat_mtime (ifstat);
1935 restoring = (decompress && 0 <= time_stamp.tv_nsec
1936 && ! (timespec[1].tv_sec == time_stamp.tv_sec
1937 && timespec[1].tv_nsec == time_stamp.tv_nsec));
1938 if (restoring)
1939 timespec[1] = time_stamp;
1941 if (fdutimens (ofd, ofname, timespec) == 0)
1943 if (restoring && 1 < verbose) {
1944 fprintf(stderr, "%s: timestamp restored\n", ofname);
1947 else
1949 int e = errno;
1950 WARN ((stderr, "%s: ", program_name));
1951 if (!quiet)
1953 errno = e;
1954 perror (ofname);
1957 #endif
1959 /* Change the group first, then the permissions, then the owner.
1960 That way, the permissions will be correct on systems that allow
1961 users to give away files, without introducing a security hole.
1962 Security depends on permissions not containing the setuid or
1963 setgid bits. */
1965 do_chown (ofd, ofname, -1, ifstat->st_gid);
1967 #if HAVE_FCHMOD
1968 r = fchmod (ofd, mode);
1969 #else
1970 r = chmod (ofname, mode);
1971 #endif
1972 if (r != 0) {
1973 int e = errno;
1974 WARN ((stderr, "%s: ", program_name));
1975 if (!quiet) {
1976 errno = e;
1977 perror(ofname);
1981 do_chown (ofd, ofname, ifstat->st_uid, -1);
1984 #if ! NO_DIR
1986 /* ========================================================================
1987 * Recurse through the given directory.
1989 local void treat_dir (fd, dir)
1990 int fd;
1991 char *dir;
1993 DIR *dirp;
1994 char nbuf[MAX_PATH_LEN];
1995 char *entries;
1996 char const *entry;
1997 size_t entrylen;
1999 dirp = fdopendir (fd);
2001 if (dirp == NULL) {
2002 progerror(dir);
2003 close (fd);
2004 return ;
2007 entries = streamsavedir (dirp, SAVEDIR_SORT_NONE);
2008 if (! entries)
2009 progerror (dir);
2010 if (closedir (dirp) != 0)
2011 progerror (dir);
2012 if (! entries)
2013 return;
2015 for (entry = entries; *entry; entry += entrylen + 1) {
2016 size_t len = strlen (dir);
2017 entrylen = strlen (entry);
2018 if (strequ (entry, ".") || strequ (entry, ".."))
2019 continue;
2020 if (len + entrylen < MAX_PATH_LEN - 2) {
2021 strcpy(nbuf,dir);
2022 if (*last_component (nbuf) && !ISSLASH (nbuf[len - 1]))
2023 nbuf[len++] = '/';
2024 strcpy (nbuf + len, entry);
2025 treat_file(nbuf);
2026 } else {
2027 fprintf(stderr,"%s: %s/%s: pathname too long\n",
2028 program_name, dir, entry);
2029 exit_code = ERROR;
2032 free (entries);
2034 #endif /* ! NO_DIR */
2036 /* Make sure signals get handled properly. */
2038 static void
2039 install_signal_handlers ()
2041 int nsigs = sizeof handled_sig / sizeof handled_sig[0];
2042 int i;
2043 struct sigaction act;
2045 sigemptyset (&caught_signals);
2046 for (i = 0; i < nsigs; i++)
2048 sigaction (handled_sig[i], NULL, &act);
2049 if (act.sa_handler != SIG_IGN)
2050 sigaddset (&caught_signals, handled_sig[i]);
2053 act.sa_handler = abort_gzip_signal;
2054 act.sa_mask = caught_signals;
2055 act.sa_flags = 0;
2057 for (i = 0; i < nsigs; i++)
2058 if (sigismember (&caught_signals, handled_sig[i]))
2060 if (i == 0)
2061 foreground = 1;
2062 sigaction (handled_sig[i], &act, NULL);
2066 /* ========================================================================
2067 * Free all dynamically allocated variables and exit with the given code.
2069 local void do_exit(exitcode)
2070 int exitcode;
2072 static int in_exit = 0;
2074 if (in_exit) exit(exitcode);
2075 in_exit = 1;
2076 free(env);
2077 env = NULL;
2078 FREE(inbuf);
2079 FREE(outbuf);
2080 FREE(d_buf);
2081 FREE(window);
2082 #ifndef MAXSEG_64K
2083 FREE(tab_prefix);
2084 #else
2085 FREE(tab_prefix0);
2086 FREE(tab_prefix1);
2087 #endif
2088 exit(exitcode);
2091 static void
2092 finish_out (void)
2094 if (fclose (stdout) != 0)
2095 write_error ();
2096 do_exit (OK);
2099 /* ========================================================================
2100 * Close and unlink the output file.
2102 static void
2103 remove_output_file (bool signals_already_blocked)
2105 int fd;
2106 sigset_t oldset;
2108 if (!signals_already_blocked)
2109 sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
2110 fd = remove_ofname_fd;
2111 if (0 <= fd)
2113 char fname[MAX_PATH_LEN];
2114 remove_ofname_fd = -1;
2115 close (fd);
2116 volatile_strcpy (fname, remove_ofname);
2117 xunlink (fname);
2119 if (!signals_already_blocked)
2120 sigprocmask (SIG_SETMASK, &oldset, NULL);
2123 /* ========================================================================
2124 * Error handler.
2126 void
2127 abort_gzip (void)
2129 remove_output_file (false);
2130 do_exit(ERROR);
2133 /* ========================================================================
2134 * Signal handler.
2136 static void
2137 abort_gzip_signal (int sig)
2139 remove_output_file (true);
2140 if (sig == exiting_signal)
2141 _exit (WARNING);
2142 signal (sig, SIG_DFL);
2143 raise (sig);