maint: more fallout from Gnulib sync
[gzip.git] / gzip.c
blobb17f26428d70d56932fded6bcb300c449e08d6b6
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 <stddef.h>
62 #include <sys/stat.h>
63 #include <errno.h>
65 #include "tailor.h"
66 #include "gzip.h"
67 #include "intprops.h"
68 #include "lzw.h"
69 #include "revision.h"
70 #include "timespec.h"
72 #include "dirname.h"
73 #include "fcntl--.h"
74 #include "filename.h"
75 #include "getopt.h"
76 #include "ignore-value.h"
77 #include "stat-time.h"
78 #include "version.h"
79 #include "xalloc.h"
80 #include "yesno.h"
82 /* configuration */
84 #include <limits.h>
85 #include <unistd.h>
86 #include <stdlib.h>
87 #include <errno.h>
89 #ifndef NO_DIR
90 # define NO_DIR 0
91 #endif
92 #if !NO_DIR
93 # include <dirent.h>
94 # include <savedir.h>
95 #endif
97 #ifndef NO_UTIME
98 # include <utimens.h>
99 #endif
101 #ifndef MAX_PATH_LEN
102 # define MAX_PATH_LEN 1024 /* max pathname length */
103 #endif
105 #ifndef SEEK_END
106 # define SEEK_END 2
107 #endif
109 #ifndef CHAR_BIT
110 # define CHAR_BIT 8
111 #endif
113 #ifdef off_t
114 off_t lseek (int fd, off_t offset, int whence);
115 #endif
117 #ifndef HAVE_WORKING_O_NOFOLLOW
118 # define HAVE_WORKING_O_NOFOLLOW 0
119 #endif
121 /* Separator for file name parts (see shorten_name()) */
122 #ifdef NO_MULTIPLE_DOTS
123 # define PART_SEP "-"
124 #else
125 # define PART_SEP "."
126 #endif
128 /* global buffers */
130 /* With IBM_Z_DFLTCC, DEFLATE COMPRESSION works faster with
131 page-aligned input and output buffers, and requires page-aligned
132 windows; the alignment requirement is 4096. On other platforms
133 alignment doesn't hurt, and alignment up to 4096 is portable so
134 let's do that. */
135 #if defined HAVE_C_ALIGNASOF || defined alignas
136 # define BUFFER_ALIGNED alignas (4096)
137 #else
138 # define BUFFER_ALIGNED /**/
139 #endif
140 DECLARE(uch BUFFER_ALIGNED, inbuf, INBUFSIZ +INBUF_EXTRA);
141 DECLARE(uch BUFFER_ALIGNED, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
142 DECLARE(ush, d_buf, DIST_BUFSIZE);
143 DECLARE(uch BUFFER_ALIGNED, window, 2L*WSIZE);
144 #ifndef MAXSEG_64K
145 DECLARE(ush, tab_prefix, 1L<<BITS);
146 #else
147 DECLARE(ush, tab_prefix0, 1L<<(BITS-1));
148 DECLARE(ush, tab_prefix1, 1L<<(BITS-1));
149 #endif
151 /* local variables */
153 /* If true, pretend that standard input is a tty. This option
154 is deliberately not documented, and only for testing. */
155 static bool presume_input_tty;
157 /* If true, transfer output data to the output file's storage device
158 when supported. Otherwise, if the system crashes around the time
159 gzip is run, the user might lose both input and output data. See:
160 Pillai TS et al. All file systems are not created equal: on the
161 complexity of crafting crash-consistent applications. OSDI'14. 2014:433-48.
162 https://www.usenix.org/conference/osdi14/technical-sessions/presentation/pillai */
163 static bool synchronous;
165 static int ascii = 0; /* convert end-of-lines to local OS conventions */
166 int to_stdout = 0; /* output to stdout (-c) */
167 static int decompress = 0; /* decompress (-d) */
168 static int force = 0; /* don't ask questions, compress links (-f) */
169 static int keep = 0; /* keep (don't delete) input files */
170 static int no_name = -1; /* don't save or restore the original file name */
171 static int no_time = -1; /* don't save or restore the original file time */
172 static int recursive = 0; /* recurse through directories (-r) */
173 static int list = 0; /* list the file contents (-l) */
174 #ifndef DEBUG
175 static
176 #endif
177 int verbose = 0; /* be verbose (-v) */
178 int quiet = 0; /* be very quiet (-q) */
179 int test = 0; /* test .gz file integrity */
180 static int foreground = 0; /* set if program run in foreground */
181 char *program_name; /* program name */
182 int maxbits = BITS; /* max bits per code for LZW */
183 int method = DEFLATED;/* compression method */
184 int level = 6; /* compression level */
185 int exit_code = OK; /* program exit code */
186 int save_orig_name; /* set if original name must be saved */
187 static int last_member; /* set for .zip and .Z files */
188 static int part_nb; /* number of parts in .gz file */
189 off_t ifile_size; /* input file size, -1 for devices (debug only) */
190 static char *env; /* contents of GZIP env variable */
191 static char const *z_suffix; /* default suffix (can be set with --suffix) */
192 static size_t z_len; /* strlen(z_suffix) */
194 /* The original timestamp (modification time). If the original is
195 unknown, TIME_STAMP.tv_nsec is negative. If the original is
196 greater than struct timespec range, TIME_STAMP is the maximal
197 struct timespec value; this can happen on hosts with 32-bit signed
198 time_t because the gzip format's MTIME is 32-bit unsigned.
199 The original cannot be less than struct timespec range. */
200 struct timespec time_stamp;
202 /* The set of signals that are caught. */
203 static sigset_t caught_signals;
205 /* If nonzero then exit with status WARNING, rather than with the usual
206 signal status, on receipt of a signal with this value. This
207 suppresses a "Broken Pipe" message with some shells. */
208 static int volatile exiting_signal;
210 /* If nonnegative, close this file descriptor and unlink remove_ofname
211 on error. */
212 static int volatile remove_ofname_fd = -1;
213 static char volatile remove_ofname[MAX_PATH_LEN];
215 static bool stdin_was_read;
217 off_t bytes_in; /* number of input bytes */
218 off_t bytes_out; /* number of output bytes */
219 static off_t total_in; /* input bytes for all files */
220 static off_t total_out; /* output bytes for all files */
221 char ifname[MAX_PATH_LEN]; /* input file name */
222 char ofname[MAX_PATH_LEN]; /* output file name */
223 static char dfname[MAX_PATH_LEN]; /* name of dir containing output file */
224 static struct stat istat; /* status for input file */
225 int ifd; /* input file descriptor */
226 int ofd; /* output file descriptor */
227 static int dfd = -1; /* output directory file descriptor */
228 unsigned insize; /* valid bytes in inbuf */
229 unsigned inptr; /* index of next byte to be processed in inbuf */
230 unsigned outcnt; /* bytes in output buffer */
231 int rsync = 0; /* make rsyncable chunks */
233 static int handled_sig[] =
235 /* SIGINT must be first, as 'foreground' depends on it. */
236 SIGINT
238 #ifdef SIGHUP
239 , SIGHUP
240 #endif
241 #if SIGPIPE
242 , SIGPIPE
243 #endif
244 #ifdef SIGTERM
245 , SIGTERM
246 #endif
247 #ifdef SIGXCPU
248 , SIGXCPU
249 #endif
250 #ifdef SIGXFSZ
251 , SIGXFSZ
252 #endif
255 /* For long options that have no equivalent short option, use a
256 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
257 enum
259 PRESUME_INPUT_TTY_OPTION = CHAR_MAX + 1,
260 RSYNCABLE_OPTION,
261 SYNCHRONOUS_OPTION,
263 /* A value greater than all valid long options, used as a flag to
264 distinguish options derived from the GZIP environment variable. */
265 ENV_OPTION
268 static char const shortopts[] = "ab:cdfhH?klLmMnNqrS:tvVZ123456789";
270 static const struct option longopts[] =
272 /* { name has_arg *flag val } */
273 {"ascii", 0, 0, 'a'}, /* ascii text mode */
274 {"to-stdout", 0, 0, 'c'}, /* write output on standard output */
275 {"stdout", 0, 0, 'c'}, /* write output on standard output */
276 {"decompress", 0, 0, 'd'}, /* decompress */
277 {"uncompress", 0, 0, 'd'}, /* decompress */
278 /* {"encrypt", 0, 0, 'e'}, encrypt */
279 {"force", 0, 0, 'f'}, /* force overwrite of output file */
280 {"help", 0, 0, 'h'}, /* give help */
281 /* {"pkzip", 0, 0, 'k'}, force output in pkzip format */
282 {"keep", 0, 0, 'k'}, /* keep (don't delete) input files */
283 {"list", 0, 0, 'l'}, /* list .gz file contents */
284 {"license", 0, 0, 'L'}, /* display software license */
285 {"no-name", 0, 0, 'n'}, /* don't save or restore original name & time */
286 {"name", 0, 0, 'N'}, /* save or restore original name & time */
287 {"-presume-input-tty", no_argument, NULL, PRESUME_INPUT_TTY_OPTION},
288 {"quiet", 0, 0, 'q'}, /* quiet mode */
289 {"silent", 0, 0, 'q'}, /* quiet mode */
290 {"synchronous",0, 0, SYNCHRONOUS_OPTION},
291 {"recursive", 0, 0, 'r'}, /* recurse through directories */
292 {"suffix", 1, 0, 'S'}, /* use given suffix instead of .gz */
293 {"test", 0, 0, 't'}, /* test compressed file integrity */
294 {"verbose", 0, 0, 'v'}, /* verbose mode */
295 {"version", 0, 0, 'V'}, /* display version number */
296 {"fast", 0, 0, '1'}, /* compress faster */
297 {"best", 0, 0, '9'}, /* compress better */
298 {"lzw", 0, 0, 'Z'}, /* make output compatible with old compress */
299 {"bits", 1, 0, 'b'}, /* max number of bits per code (implies -Z) */
300 {"rsyncable", 0, 0, RSYNCABLE_OPTION}, /* make rsync-friendly archive */
301 { 0, 0, 0, 0 }
304 /* local functions */
306 _Noreturn static void try_help (void);
307 static void help (void);
308 static void license (void);
309 static void version (void);
310 static int input_eof (void);
311 static void treat_stdin (void);
312 static void treat_file (char *iname);
313 static int create_outfile (void);
314 static char *get_suffix (char *name);
315 static int open_input_file (char *iname, struct stat *sbuf);
316 static void discard_input_bytes (size_t nbytes, unsigned int flags);
317 static int make_ofname (void);
318 static void shorten_name (char *name);
319 static int get_method (int in);
320 static void do_list (int method);
321 static int check_ofname (void);
322 static void copy_stat (struct stat *ifstat);
323 static void install_signal_handlers (void);
324 static void remove_output_file (bool);
325 static void abort_gzip_signal (int);
326 _Noreturn static void do_exit (int exitcode);
327 static void finish_out (void);
328 int main (int argc, char **argv);
329 static int (*work) (int infile, int outfile) = zip; /* function to call */
331 #if ! NO_DIR
332 static void treat_dir (int fd, char *dir);
333 #endif
335 #define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
337 static void
338 try_help ()
340 fprintf (stderr, "Try `%s --help' for more information.\n",
341 program_name);
342 do_exit (ERROR);
345 /* ======================================================================== */
346 static void
347 help ()
349 static char const* const help_msg[] = {
350 "Compress or uncompress FILEs (by default, compress FILES in-place).",
352 "Mandatory arguments to long options are mandatory for short options too.",
354 #if O_BINARY
355 " -a, --ascii ascii text; convert end-of-line using local conventions",
356 #endif
357 " -c, --stdout write on standard output, keep original files unchanged",
358 " -d, --decompress decompress",
359 /* -e, --encrypt encrypt */
360 " -f, --force force overwrite of output file and compress links",
361 " -h, --help give this help",
362 /* -k, --pkzip force output in pkzip format */
363 " -k, --keep keep (don't delete) input files",
364 " -l, --list list compressed file contents",
365 " -L, --license display software license",
366 #ifdef UNDOCUMENTED
367 " -m do not save or restore the original modification time",
368 " -M, --time save or restore the original modification time",
369 #endif
370 " -n, --no-name do not save or restore the original name and timestamp",
371 " -N, --name save or restore the original name and timestamp",
372 " -q, --quiet suppress all warnings",
373 #if ! NO_DIR
374 " -r, --recursive operate recursively on directories",
375 #endif
376 " --rsyncable make rsync-friendly archive",
377 " -S, --suffix=SUF use suffix SUF on compressed files",
378 " --synchronous synchronous output (safer if system crashes, but slower)",
379 " -t, --test test compressed file integrity",
380 " -v, --verbose verbose mode",
381 " -V, --version display version number",
382 " -1, --fast compress faster",
383 " -9, --best compress better",
385 "With no FILE, or when FILE is -, read standard input.",
387 "Report bugs to <bug-gzip@gnu.org>.",
389 char const *const *p = help_msg;
391 printf ("Usage: %s [OPTION]... [FILE]...\n", program_name);
392 while (*p) printf ("%s\n", *p++);
395 /* ======================================================================== */
396 static void
397 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 static void
407 version ()
409 license ();
410 printf ("\n");
411 printf ("Written by Jean-loup Gailly.\n");
414 static void
415 progerror (char const *string)
417 int e = errno;
418 fprintf (stderr, "%s: ", program_name);
419 errno = e;
420 perror(string);
421 exit_code = ERROR;
424 /* ======================================================================== */
425 int main (int argc, char **argv)
427 int file_count; /* number of files to process */
428 size_t proglen; /* length of program_name */
429 char **argv_copy;
430 int env_argc;
431 char **env_argv;
433 EXPAND(argc, argv); /* wild card expansion if necessary */
435 program_name = gzip_base_name (argv[0]);
436 proglen = strlen (program_name);
438 /* Suppress .exe for MSDOS and OS/2: */
439 if (4 < proglen && strequ (program_name + proglen - 4, ".exe"))
440 program_name[proglen - 4] = '\0';
442 /* Add options in GZIP environment variable if there is one */
443 argv_copy = argv;
444 env = add_envopt (&env_argc, &argv_copy, OPTIONS_VAR);
445 env_argv = env ? argv_copy : NULL;
447 #ifndef GNU_STANDARD
448 # define GNU_STANDARD 1
449 #endif
450 #if !GNU_STANDARD
451 /* For compatibility with old compress, use program name as an option.
452 * Unless you compile with -DGNU_STANDARD=0, this program will behave as
453 * gzip even if it is invoked under the name gunzip or zcat.
455 * Systems which do not support links can still use -d or -dc.
456 * Ignore an .exe extension for MSDOS and OS/2.
458 if (strncmp (program_name, "un", 2) == 0 /* ungzip, uncompress */
459 || strncmp (program_name, "gun", 3) == 0) /* gunzip */
460 decompress = 1;
461 else if (strequ (program_name + 1, "cat") /* zcat, pcat, gcat */
462 || strequ (program_name, "gzcat")) /* gzcat */
463 decompress = to_stdout = 1;
464 #endif
466 z_suffix = Z_SUFFIX;
467 z_len = strlen(z_suffix);
469 while (true) {
470 int optc;
471 int longind = -1;
473 if (env_argv)
475 if (env_argv[optind] && strequ (env_argv[optind], "--"))
476 optc = ENV_OPTION + '-';
477 else
479 optc = getopt_long (env_argc, env_argv, shortopts, longopts,
480 &longind);
481 if (0 <= optc)
482 optc += ENV_OPTION;
483 else
485 if (optind != env_argc)
487 fprintf (stderr,
488 ("%s: %s: non-option in "OPTIONS_VAR
489 " environment variable\n"),
490 program_name, env_argv[optind]);
491 try_help ();
494 /* Wait until here before warning, so that GZIP='-q'
495 doesn't warn. */
496 if (env_argc != 1 && !quiet)
497 fprintf (stderr,
498 ("%s: warning: "OPTIONS_VAR" environment variable"
499 " is deprecated; use an alias or script\n"),
500 program_name);
502 /* Start processing ARGC and ARGV instead. */
503 free (env_argv);
504 env_argv = NULL;
505 optind = 1;
506 longind = -1;
511 if (!env_argv)
512 optc = getopt_long (argc, argv, shortopts, longopts, &longind);
513 if (optc < 0)
514 break;
516 switch (optc) {
517 case 'a':
518 ascii = 1; break;
519 case 'b':
520 maxbits = atoi(optarg);
521 for (; *optarg; optarg++)
522 if (! ('0' <= *optarg && *optarg <= '9'))
524 fprintf (stderr, "%s: -b operand is not an integer\n",
525 program_name);
526 try_help ();
528 break;
529 case 'c':
530 to_stdout = 1; break;
531 case 'd':
532 decompress = 1; break;
533 case 'f':
534 force++; break;
535 case 'h': case 'H':
536 help (); finish_out (); break;
537 case 'k':
538 keep = 1; break;
539 case 'l':
540 list = decompress = test = to_stdout = 1; break;
541 case 'L':
542 license (); finish_out (); break;
543 case 'm': /* undocumented, may change later */
544 no_time = 1; break;
545 case 'M': /* undocumented, may change later */
546 no_time = 0; break;
547 case 'n':
548 case 'n' + ENV_OPTION:
549 no_name = no_time = 1; break;
550 case 'N':
551 case 'N' + ENV_OPTION:
552 no_name = no_time = 0; break;
553 case PRESUME_INPUT_TTY_OPTION:
554 presume_input_tty = true; break;
555 case 'q':
556 case 'q' + ENV_OPTION:
557 quiet = 1; verbose = 0; break;
558 case 'r':
559 #if NO_DIR
560 fprintf (stderr, "%s: -r not supported on this system\n",
561 program_name);
562 try_help ();
563 #else
564 recursive = 1;
565 #endif
566 break;
568 case RSYNCABLE_OPTION:
569 case RSYNCABLE_OPTION + ENV_OPTION:
570 rsync = 1;
571 break;
572 case 'S':
573 #ifdef NO_MULTIPLE_DOTS
574 if (*optarg == '.') optarg++;
575 #endif
576 z_len = strlen(optarg);
577 z_suffix = optarg;
578 break;
579 case SYNCHRONOUS_OPTION:
580 synchronous = true;
581 break;
582 case 't':
583 test = decompress = to_stdout = 1;
584 break;
585 case 'v':
586 case 'v' + ENV_OPTION:
587 verbose++; quiet = 0; break;
588 case 'V':
589 version (); finish_out (); break;
590 case 'Z':
591 fprintf(stderr, "%s: -Z not supported in this version\n",
592 program_name);
593 try_help ();
594 break;
595 case '1' + ENV_OPTION: case '2' + ENV_OPTION: case '3' + ENV_OPTION:
596 case '4' + ENV_OPTION: case '5' + ENV_OPTION: case '6' + ENV_OPTION:
597 case '7' + ENV_OPTION: case '8' + ENV_OPTION: case '9' + ENV_OPTION:
598 optc -= ENV_OPTION;
599 FALLTHROUGH;
600 case '1': case '2': case '3': case '4':
601 case '5': case '6': case '7': case '8': case '9':
602 level = optc - '0';
603 break;
605 default:
606 if (ENV_OPTION <= optc && optc != ENV_OPTION + '?')
608 /* Output a diagnostic, since getopt_long didn't. */
609 fprintf (stderr, "%s: ", program_name);
610 if (longind < 0)
611 fprintf (stderr, "-%c: ", optc - ENV_OPTION);
612 else
613 fprintf (stderr, "--%s: ", longopts[longind].name);
614 fprintf (stderr, ("option not valid in "OPTIONS_VAR
615 " environment variable\n"));
617 try_help ();
619 } /* loop on all arguments */
621 /* By default, save name and timestamp on compression but do not
622 * restore them on decompression.
624 if (no_time < 0) no_time = decompress;
625 if (no_name < 0) no_name = decompress;
627 file_count = argc - optind;
629 #if O_BINARY
630 #else
631 if (ascii && !quiet) {
632 fprintf(stderr, "%s: option --ascii ignored on this system\n",
633 program_name);
635 #endif
636 if (z_len == 0 || z_len > MAX_SUFFIX) {
637 fprintf(stderr, "%s: invalid suffix '%s'\n", program_name, z_suffix);
638 do_exit(ERROR);
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
653 #if SIGPIPE
654 exiting_signal = quiet ? SIGPIPE : 0;
655 #endif
656 install_signal_handlers ();
658 /* And get to work */
659 if (file_count != 0) {
660 if (to_stdout && !test && (!decompress || !ascii)) {
661 SET_BINARY_MODE (STDOUT_FILENO);
663 while (optind < argc) {
664 treat_file(argv[optind++]);
666 } else { /* Standard input */
667 treat_stdin();
669 if (stdin_was_read && close (STDIN_FILENO) != 0)
671 strcpy (ifname, "stdin");
672 read_error ();
674 if (list)
676 /* Output any totals, and check for output errors. */
677 if (!quiet && 1 < file_count)
678 do_list (-1);
679 if (fflush (stdout) != 0)
680 write_error ();
682 if (to_stdout
683 && ((synchronous
684 && fdatasync (STDOUT_FILENO) != 0 && errno != EINVAL)
685 || close (STDOUT_FILENO) != 0)
686 && errno != EBADF)
687 write_error ();
688 do_exit(exit_code);
691 /* Return nonzero when at end of file on input. */
692 static int
693 input_eof ()
695 if (!decompress || last_member)
696 return 1;
698 if (inptr == insize)
700 if (insize != INBUFSIZ || fill_inbuf (1) == EOF)
701 return 1;
703 /* Unget the char that fill_inbuf got. */
704 inptr = 0;
707 return 0;
710 static void
711 get_input_size_and_time (void)
713 ifile_size = -1;
714 time_stamp.tv_nsec = -1;
716 /* Record the input file's size and timestamp only if it is a
717 regular file. Doing this for the timestamp helps to keep gzip's
718 output more reproducible when it is used as part of a
719 pipeline. */
721 if (S_ISREG (istat.st_mode))
723 ifile_size = istat.st_size;
724 if (!no_time || list)
725 time_stamp = get_stat_mtime (&istat);
729 /* ========================================================================
730 * Compress or decompress stdin
732 static void
733 treat_stdin ()
735 if (!force && !list
736 && (presume_input_tty
737 || isatty (decompress ? STDIN_FILENO : STDOUT_FILENO))) {
738 /* Do not send compressed data to the terminal or read it from
739 * the terminal. We get here when user invoked the program
740 * without parameters, so be helpful. According to the GNU standards:
742 * If there is one behavior you think is most useful when the output
743 * is to a terminal, and another that you think is most useful when
744 * the output is a file or a pipe, then it is usually best to make
745 * the default behavior the one that is useful with output to a
746 * terminal, and have an option for the other behavior.
748 * Here we use the --force option to get the other behavior.
750 if (! quiet)
751 fprintf (stderr,
752 ("%s: compressed data not %s a terminal."
753 " Use -f to force %scompression.\n"
754 "For help, type: %s -h\n"),
755 program_name,
756 decompress ? "read from" : "written to",
757 decompress ? "de" : "",
758 program_name);
759 do_exit(ERROR);
762 if (decompress || !ascii) {
763 SET_BINARY_MODE (STDIN_FILENO);
765 if (!test && (!decompress || !ascii)) {
766 SET_BINARY_MODE (STDOUT_FILENO);
768 strcpy(ifname, "stdin");
769 strcpy(ofname, "stdout");
771 /* Get the file's timestamp and size. */
772 if (fstat (STDIN_FILENO, &istat) != 0)
774 progerror ("standard input");
775 do_exit (ERROR);
778 get_input_size_and_time ();
780 clear_bufs(); /* clear input and output buffers */
781 to_stdout = 1;
782 part_nb = 0;
783 ifd = STDIN_FILENO;
784 stdin_was_read = true;
786 if (decompress) {
787 method = get_method(ifd);
788 if (method < 0) {
789 do_exit(exit_code); /* error message already emitted */
793 /* Actually do the compression/decompression. Loop over zipped members.
795 for (;;) {
796 if (work (STDIN_FILENO, STDOUT_FILENO) != OK)
797 return;
799 if (input_eof ())
800 break;
802 method = get_method(ifd);
803 if (method < 0) return; /* error message already emitted */
804 bytes_out = 0; /* required for length check */
807 if (list)
809 do_list (method);
810 return;
813 if (verbose) {
814 if (test) {
815 fprintf(stderr, " OK\n");
817 } else if (!decompress) {
818 display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
819 fprintf(stderr, "\n");
820 #ifdef DISPLAY_STDIN_RATIO
821 } else {
822 display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
823 fprintf(stderr, "\n");
824 #endif
829 static char const dot = '.';
831 /* True if the cached directory for calls to openat etc. is DIR, with
832 length DIRLEN. DIR need not be null-terminated. DIRLEN must be
833 less than MAX_PATH_LEN. */
834 static bool
835 atdir_eq (char const *dir, ptrdiff_t dirlen)
837 if (dirlen == 0)
838 dir = &dot, dirlen = 1;
839 return memcmp (dfname, dir, dirlen) == 0 && !dfname[dirlen];
842 /* Set the directory used for calls to openat etc. to be the directory
843 DIR, with length DIRLEN. DIR need not be null-terminated.
844 DIRLEN must be less than MAX_PATH_LEN. Return a file descriptor for
845 the directory, or -1 if one could not be obtained. */
846 static int
847 atdir_set (char const *dir, ptrdiff_t dirlen)
849 /* Don't bother opening directories on older systems that
850 lack openat and unlinkat. It's not worth the porting hassle. */
851 #if HAVE_OPENAT && HAVE_UNLINKAT
852 enum { try_opening_directories = true };
853 #else
854 enum { try_opening_directories = false };
855 #endif
857 if (try_opening_directories && ! atdir_eq (dir, dirlen))
859 if (0 <= dfd)
860 close (dfd);
861 if (dirlen == 0)
862 dir = &dot, dirlen = 1;
863 memcpy (dfname, dir, dirlen);
864 dfname[dirlen] = '\0';
865 dfd = open (dfname, O_SEARCH | O_DIRECTORY);
868 return dfd;
871 /* ========================================================================
872 * Compress or decompress the given file
874 static void
875 treat_file (char *iname)
877 /* Accept "-" as synonym for stdin */
878 if (strequ(iname, "-")) {
879 int cflag = to_stdout;
880 treat_stdin();
881 to_stdout = cflag;
882 return;
885 /* Check if the input file is present, set ifname and istat: */
886 ifd = open_input_file (iname, &istat);
887 if (ifd < 0)
888 return;
890 /* If the input name is that of a directory, recurse or ignore: */
891 if (S_ISDIR(istat.st_mode)) {
892 #if ! NO_DIR
893 if (recursive) {
894 treat_dir (ifd, iname);
895 /* Warning: ifname is now garbage */
896 return;
898 #endif
899 close (ifd);
900 WARN ((stderr, "%s: %s is a directory -- ignored\n",
901 program_name, ifname));
902 return;
905 if (! to_stdout)
907 if (! S_ISREG (istat.st_mode))
909 WARN ((stderr,
910 "%s: %s is not a directory or a regular file - ignored\n",
911 program_name, ifname));
912 close (ifd);
913 return;
915 if (istat.st_mode & S_ISUID)
917 WARN ((stderr, "%s: %s is set-user-ID on execution - ignored\n",
918 program_name, ifname));
919 close (ifd);
920 return;
922 if (istat.st_mode & S_ISGID)
924 WARN ((stderr, "%s: %s is set-group-ID on execution - ignored\n",
925 program_name, ifname));
926 close (ifd);
927 return;
930 if (! force)
932 if (istat.st_mode & S_ISVTX)
934 WARN ((stderr,
935 "%s: %s has the sticky bit set - file ignored\n",
936 program_name, ifname));
937 close (ifd);
938 return;
940 if (2 <= istat.st_nlink)
942 WARN ((stderr, "%s: %s has %lu other link%s -- file ignored\n",
943 program_name, ifname,
944 (unsigned long int) istat.st_nlink - 1,
945 istat.st_nlink == 2 ? "" : "s"));
946 close (ifd);
947 return;
952 get_input_size_and_time ();
954 /* Generate output file name. For -r and (-t or -l), skip files
955 * without a valid gzip suffix (check done in make_ofname).
957 if (to_stdout && !test) {
958 strcpy(ofname, "stdout");
960 } else if (make_ofname() != OK) {
961 close (ifd);
962 return;
965 clear_bufs(); /* clear input and output buffers */
966 part_nb = 0;
968 if (decompress) {
969 method = get_method(ifd); /* updates ofname if original given */
970 if (method < 0) {
971 close(ifd);
972 return; /* error message already emitted */
976 /* If compressing to a file, check if ofname is not ambiguous
977 * because the operating system truncates names. Otherwise, generate
978 * a new ofname and save the original name in the compressed file.
980 if (to_stdout) {
981 ofd = STDOUT_FILENO;
982 /* Keep remove_ofname_fd negative. */
983 } else {
984 if (create_outfile() != OK) return;
986 if (!decompress && save_orig_name && !verbose && !quiet) {
987 fprintf(stderr, "%s: %s compressed to %s\n",
988 program_name, ifname, ofname);
991 /* Keep the name even if not truncated except with --no-name: */
992 if (!save_orig_name) save_orig_name = !no_name;
994 if (verbose && !list) {
995 fprintf(stderr, "%s:\t", ifname);
998 /* Actually do the compression/decompression. Loop over zipped members.
1000 for (;;) {
1001 if ((*work)(ifd, ofd) != OK) {
1002 method = -1; /* force cleanup */
1003 break;
1006 if (input_eof ())
1007 break;
1009 method = get_method(ifd);
1010 if (method < 0) break; /* error message already emitted */
1011 bytes_out = 0; /* required for length check */
1014 if (close (ifd) != 0)
1015 read_error ();
1017 if (list)
1019 do_list (method);
1020 return;
1023 if (!to_stdout)
1025 copy_stat (&istat);
1027 if ((synchronous
1028 && ((0 <= dfd && fdatasync (dfd) != 0 && errno != EINVAL)
1029 || (fsync (ofd) != 0 && errno != EINVAL)))
1030 || close (ofd) != 0)
1031 write_error ();
1033 if (!keep)
1035 sigset_t oldset;
1036 int unlink_errno;
1037 char *ifbase = last_component (ifname);
1038 int ufd = atdir_eq (ifname, ifbase - ifname) ? dfd : -1;
1039 int res;
1041 sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
1042 remove_ofname_fd = -1;
1043 res = ufd < 0 ? xunlink (ifname) : unlinkat (ufd, ifbase, 0);
1044 unlink_errno = res == 0 ? 0 : errno;
1045 sigprocmask (SIG_SETMASK, &oldset, NULL);
1047 if (unlink_errno)
1049 WARN ((stderr, "%s: ", program_name));
1050 if (!quiet)
1052 errno = unlink_errno;
1053 perror (ifname);
1059 if (method == -1) {
1060 if (!to_stdout)
1061 remove_output_file (false);
1062 return;
1065 /* Display statistics */
1066 if(verbose) {
1067 if (test) {
1068 fprintf(stderr, " OK");
1069 } else if (decompress) {
1070 display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
1071 } else {
1072 display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
1074 if (!test)
1075 fprintf(stderr, " -- %s %s", keep ? "created" : "replaced with",
1076 ofname);
1077 fprintf(stderr, "\n");
1081 static void
1082 volatile_strcpy (char volatile *dst, char const volatile *src)
1084 while ((*dst++ = *src++))
1085 continue;
1088 /* ========================================================================
1089 * Create the output file. Return OK or ERROR.
1090 * Try several times if necessary to avoid truncating the z_suffix. For
1091 * example, do not create a compressed file of name "1234567890123."
1092 * Sets save_orig_name to true if the file name has been truncated.
1093 * IN assertions: the input file has already been open (ifd is set) and
1094 * ofname has already been updated if there was an original name.
1095 * OUT assertions: ifd and ofd are closed in case of error.
1097 static int
1098 create_outfile ()
1100 int name_shortened = 0;
1101 int flags = (O_WRONLY | O_CREAT | O_EXCL
1102 | (ascii && decompress ? 0 : O_BINARY));
1103 char const *base = ofname;
1104 int atfd = AT_FDCWD;
1106 if (!keep)
1108 char const *b = last_component (ofname);
1109 int f = atdir_set (ofname, b - ofname);
1110 if (0 <= f)
1112 base = b;
1113 atfd = f;
1117 for (;;)
1119 int open_errno;
1120 sigset_t oldset;
1122 volatile_strcpy (remove_ofname, ofname);
1124 sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
1125 remove_ofname_fd = ofd = openat (atfd, base, flags, S_IRUSR | S_IWUSR);
1126 open_errno = errno;
1127 sigprocmask (SIG_SETMASK, &oldset, NULL);
1129 if (0 <= ofd)
1130 break;
1132 switch (open_errno)
1134 #ifdef ENAMETOOLONG
1135 case ENAMETOOLONG:
1136 shorten_name (ofname);
1137 name_shortened = 1;
1138 break;
1139 #endif
1141 case EEXIST:
1142 if (check_ofname () != OK)
1144 close (ifd);
1145 return ERROR;
1147 break;
1149 default:
1150 progerror (ofname);
1151 close (ifd);
1152 return ERROR;
1156 if (name_shortened && decompress)
1158 /* name might be too long if an original name was saved */
1159 WARN ((stderr, "%s: %s: warning, name truncated\n",
1160 program_name, ofname));
1163 return OK;
1166 /* ========================================================================
1167 * Return a pointer to the 'z' suffix of a file name, or NULL. For all
1168 * systems, ".gz", ".z", ".Z", ".taz", ".tgz", "-gz", "-z" and "_z" are
1169 * accepted suffixes, in addition to the value of the --suffix option.
1170 * ".tgz" is a useful convention for tar.z files on systems limited
1171 * to 3 characters extensions. On such systems, ".?z" and ".??z" are
1172 * also accepted suffixes. For Unix, we do not want to accept any
1173 * .??z suffix as indicating a compressed file; some people use .xyz
1174 * to denote volume data.
1176 static char *
1177 get_suffix (char *name)
1179 int nlen, slen;
1180 char suffix[MAX_SUFFIX+3]; /* last chars of name, forced to lower case */
1181 static char const *known_suffixes[] =
1182 {NULL, ".gz", ".z", ".taz", ".tgz", "-gz", "-z", "_z",
1183 #ifdef MAX_EXT_CHARS
1184 "z",
1185 #endif
1186 NULL, NULL};
1187 char const **suf;
1188 bool suffix_of_builtin = false;
1190 /* Normally put Z_SUFFIX at the start of KNOWN_SUFFIXES, but if it
1191 is a suffix of one of them, put it at the end. */
1192 for (suf = known_suffixes + 1; *suf; suf++)
1194 size_t suflen = strlen (*suf);
1195 if (z_len < suflen && strequ (z_suffix, *suf + suflen - z_len))
1197 suffix_of_builtin = true;
1198 break;
1202 char *z_lower = xstrdup(z_suffix);
1203 strlwr(z_lower);
1204 known_suffixes[suffix_of_builtin
1205 ? sizeof known_suffixes / sizeof *known_suffixes - 2
1206 : 0] = z_lower;
1207 suf = known_suffixes + suffix_of_builtin;
1209 nlen = strlen(name);
1210 if (nlen <= MAX_SUFFIX+2) {
1211 strcpy(suffix, name);
1212 } else {
1213 strcpy(suffix, name+nlen-MAX_SUFFIX-2);
1215 strlwr(suffix);
1216 slen = strlen(suffix);
1217 char *match = NULL;
1218 do {
1219 int s = strlen(*suf);
1220 if (slen > s && ! ISSLASH (suffix[slen - s - 1])
1221 && strequ(suffix + slen - s, *suf)) {
1222 match = name+nlen-s;
1223 break;
1225 } while (*++suf != NULL);
1226 free(z_lower);
1228 return match;
1232 /* Open file NAME with the given flags and store its status
1233 into *ST. Return a file descriptor to the newly opened file, or -1
1234 (setting errno) on failure. */
1235 static int
1236 open_and_stat (char *name, int flags, struct stat *st)
1238 int fd;
1239 int atfd = AT_FDCWD;
1240 char const *base = name;
1242 /* Refuse to follow symbolic links unless -c or -f. */
1243 if (!to_stdout && !force)
1245 if (HAVE_WORKING_O_NOFOLLOW)
1246 flags |= O_NOFOLLOW;
1247 else
1249 #ifdef S_ISLNK
1250 if (lstat (name, st) != 0)
1251 return -1;
1252 else if (S_ISLNK (st->st_mode))
1254 errno = ELOOP;
1255 return -1;
1257 #endif
1261 if (!keep)
1263 char const *b = last_component (name);
1264 int f = atdir_set (name, b - name);
1265 if (0 <= f)
1267 base = b;
1268 atfd = f;
1272 fd = openat (atfd, base, flags);
1273 if (0 <= fd && fstat (fd, st) != 0)
1275 int e = errno;
1276 close (fd);
1277 errno = e;
1278 return -1;
1280 return fd;
1284 /* ========================================================================
1285 * Set ifname to the input file name (with a suffix appended if necessary)
1286 * and istat to its stats. For decompression, if no file exists with the
1287 * original name, try adding successively z_suffix, .gz, .z, -z and .Z.
1288 * For MSDOS, we try only z_suffix and z.
1289 * Return an open file descriptor or -1.
1291 static int
1292 open_input_file (char *iname, struct stat *sbuf)
1294 int ilen; /* strlen(ifname) */
1295 int z_suffix_errno = 0;
1296 static char const *suffixes[] = {NULL, ".gz", ".z", "-z", ".Z", NULL};
1297 char const **suf = suffixes;
1298 char const *s;
1299 #ifdef NO_MULTIPLE_DOTS
1300 char *dot; /* pointer to ifname extension, or NULL */
1301 #endif
1302 int fd;
1303 int open_flags = (O_RDONLY | O_NONBLOCK | O_NOCTTY
1304 | (ascii && !decompress ? 0 : O_BINARY));
1306 *suf = z_suffix;
1308 if (sizeof ifname - 1 <= strlen (iname))
1309 goto name_too_long;
1311 strcpy(ifname, iname);
1313 /* If input file exists, return OK. */
1314 fd = open_and_stat (ifname, open_flags, sbuf);
1315 if (0 <= fd)
1316 return fd;
1318 if (!decompress || errno != ENOENT) {
1319 progerror(ifname);
1320 return -1;
1322 /* File.ext doesn't exist. Try adding a suffix. */
1323 s = get_suffix(ifname);
1324 if (s != NULL) {
1325 progerror(ifname); /* ifname already has z suffix and does not exist */
1326 return -1;
1328 #ifdef NO_MULTIPLE_DOTS
1329 dot = strrchr(ifname, '.');
1330 if (dot == NULL) {
1331 strcat(ifname, ".");
1332 dot = strrchr(ifname, '.');
1334 #endif
1335 ilen = strlen(ifname);
1336 if (strequ(z_suffix, ".gz")) suf++;
1338 /* Search for all suffixes */
1339 do {
1340 char const *s0 = s = *suf;
1341 strcpy (ifname, iname);
1342 #ifdef NO_MULTIPLE_DOTS
1343 if (*s == '.') s++;
1344 if (*dot == '\0') strcpy (dot, ".");
1345 #endif
1346 #ifdef MAX_EXT_CHARS
1347 if (MAX_EXT_CHARS < strlen (s) + strlen (dot + 1))
1348 dot[MAX_EXT_CHARS + 1 - strlen (s)] = '\0';
1349 #endif
1350 if (sizeof ifname <= ilen + strlen (s))
1351 goto name_too_long;
1352 strcat(ifname, s);
1353 fd = open_and_stat (ifname, open_flags, sbuf);
1354 if (0 <= fd)
1355 return fd;
1356 if (errno != ENOENT)
1358 progerror (ifname);
1359 return -1;
1361 if (strequ (s0, z_suffix))
1362 z_suffix_errno = errno;
1363 } while (*++suf != NULL);
1365 /* No suffix found, complain using z_suffix: */
1366 strcpy(ifname, iname);
1367 #ifdef NO_MULTIPLE_DOTS
1368 if (*dot == '\0') strcpy(dot, ".");
1369 #endif
1370 #ifdef MAX_EXT_CHARS
1371 if (MAX_EXT_CHARS < z_len + strlen (dot + 1))
1372 dot[MAX_EXT_CHARS + 1 - z_len] = '\0';
1373 #endif
1374 strcat(ifname, z_suffix);
1375 errno = z_suffix_errno;
1376 progerror(ifname);
1377 return -1;
1379 name_too_long:
1380 fprintf (stderr, "%s: %s: file name too long\n", program_name, iname);
1381 exit_code = ERROR;
1382 return -1;
1385 /* ========================================================================
1386 * Generate ofname given ifname. Return OK, or WARNING if file must be skipped.
1387 * Sets save_orig_name to true if the file name has been truncated.
1389 static int
1390 make_ofname ()
1392 char *suff; /* ofname z suffix */
1394 strcpy(ofname, ifname);
1395 /* strip a version number if any and get the gzip suffix if present: */
1396 suff = get_suffix(ofname);
1398 if (decompress) {
1399 if (suff == NULL) {
1400 /* With -t or -l, try all files (even without .gz suffix)
1401 * except with -r (behave as with just -dr).
1403 if (!recursive && test)
1404 return OK;
1406 /* Avoid annoying messages with -r */
1407 if (verbose || (!recursive && !quiet)) {
1408 WARN((stderr,"%s: %s: unknown suffix -- ignored\n",
1409 program_name, ifname));
1411 return WARNING;
1413 /* Make a special case for .tgz and .taz: */
1414 strlwr(suff);
1415 if (strequ(suff, ".tgz") || strequ(suff, ".taz")) {
1416 strcpy(suff, ".tar");
1417 } else {
1418 *suff = '\0'; /* strip the z suffix */
1420 /* ofname might be changed later if infile contains an original name */
1422 } else if (suff && ! force) {
1423 /* Avoid annoying messages with -r (see treat_dir()) */
1424 if (verbose || (!recursive && !quiet)) {
1425 /* Don't use WARN, as it affects exit status. */
1426 fprintf (stderr, "%s: %s already has %s suffix -- unchanged\n",
1427 program_name, ifname, suff);
1429 return WARNING;
1430 } else {
1431 save_orig_name = 0;
1433 #ifdef NO_MULTIPLE_DOTS
1434 suff = strrchr(ofname, '.');
1435 if (suff == NULL) {
1436 if (sizeof ofname <= strlen (ofname) + 1)
1437 goto name_too_long;
1438 strcat(ofname, ".");
1439 # ifdef MAX_EXT_CHARS
1440 if (strequ(z_suffix, "z")) {
1441 if (sizeof ofname <= strlen (ofname) + 2)
1442 goto name_too_long;
1443 strcat(ofname, "gz"); /* enough room */
1444 return OK;
1446 /* On the Atari and some versions of MSDOS,
1447 * ENAMETOOLONG does not work correctly. So we
1448 * must truncate here.
1450 } else if (strlen(suff)-1 + z_len > MAX_SUFFIX) {
1451 suff[MAX_SUFFIX+1-z_len] = '\0';
1452 save_orig_name = 1;
1453 # endif
1455 #endif /* NO_MULTIPLE_DOTS */
1456 if (sizeof ofname <= strlen (ofname) + z_len)
1457 goto name_too_long;
1458 strcat(ofname, z_suffix);
1460 } /* decompress ? */
1461 return OK;
1463 name_too_long:
1464 WARN ((stderr, "%s: %s: file name too long\n", program_name, ifname));
1465 return WARNING;
1468 /* Discard NBYTES input bytes from the input, or up through the next
1469 zero byte if NBYTES == (size_t) -1. If FLAGS say that the header
1470 CRC should be computed, update the CRC accordingly. */
1471 static void
1472 discard_input_bytes (size_t nbytes, unsigned int flags)
1474 while (nbytes != 0)
1476 uch c = get_byte ();
1477 if (flags & HEADER_CRC)
1478 updcrc (&c, 1);
1479 if (nbytes != (size_t) -1)
1480 nbytes--;
1481 else if (! c)
1482 break;
1486 /* ========================================================================
1487 * Check the magic number of the input file and update ofname if an
1488 * original name was given and to_stdout is not set.
1489 * Return the compression method, -1 for error, -2 for warning.
1490 * Set inptr to the offset of the next byte to be processed.
1491 * Updates time_stamp if there is one and neither -m nor -n is used.
1492 * This function may be called repeatedly for an input file consisting
1493 * of several contiguous gzip'ed members.
1494 * 'in' is the input file descriptor.
1495 * IN assertions: there is at least one remaining compressed member.
1496 * If the member is a zip file, it must be the only one.
1498 static int
1499 get_method (int in)
1501 uch flags; /* compression flags */
1502 uch magic[10]; /* magic header */
1503 int imagic0; /* first magic byte or EOF */
1504 int imagic1; /* like magic[1], but can represent EOF */
1505 ulg stamp; /* timestamp */
1507 /* If --force and --stdout, zcat == cat, so do not complain about
1508 * premature end of file: use try_byte instead of get_byte.
1510 if (force && to_stdout) {
1511 imagic0 = try_byte();
1512 magic[0] = imagic0;
1513 imagic1 = try_byte ();
1514 magic[1] = imagic1;
1515 /* If try_byte returned EOF, magic[1] == (char) EOF. */
1516 } else {
1517 magic[0] = get_byte ();
1518 imagic0 = 0;
1519 if (magic[0]) {
1520 magic[1] = get_byte ();
1521 imagic1 = 0; /* avoid lint warning */
1522 } else {
1523 imagic1 = try_byte ();
1524 magic[1] = imagic1;
1527 method = -1; /* unknown yet */
1528 part_nb++; /* number of parts in gzip file */
1529 header_bytes = 0;
1530 last_member = 0;
1531 /* assume multiple members in gzip file except for record oriented I/O */
1533 if (memcmp(magic, GZIP_MAGIC, 2) == 0
1534 || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
1536 method = (int)get_byte();
1537 if (method != DEFLATED) {
1538 fprintf(stderr,
1539 "%s: %s: unknown method %d -- not supported\n",
1540 program_name, ifname, method);
1541 exit_code = ERROR;
1542 return -1;
1544 work = unzip;
1545 flags = (uch)get_byte();
1547 if ((flags & ENCRYPTED) != 0) {
1548 fprintf(stderr,
1549 "%s: %s is encrypted -- not supported\n",
1550 program_name, ifname);
1551 exit_code = ERROR;
1552 return -1;
1554 if ((flags & RESERVED) != 0) {
1555 fprintf(stderr,
1556 "%s: %s has flags 0x%x -- not supported\n",
1557 program_name, ifname, flags);
1558 exit_code = ERROR;
1559 if (force <= 1) return -1;
1561 stamp = (ulg)get_byte();
1562 stamp |= ((ulg)get_byte()) << 8;
1563 stamp |= ((ulg)get_byte()) << 16;
1564 stamp |= ((ulg)get_byte()) << 24;
1565 if (stamp != 0 && !no_time)
1567 if (stamp <= TYPE_MAXIMUM (time_t))
1569 time_stamp.tv_sec = stamp;
1570 time_stamp.tv_nsec = 0;
1572 else
1574 WARN ((stderr,
1575 "%s: %s: MTIME %lu out of range for this platform\n",
1576 program_name, ifname, stamp));
1577 time_stamp.tv_sec = TYPE_MAXIMUM (time_t);
1578 time_stamp.tv_nsec = TIMESPEC_RESOLUTION - 1;
1582 magic[8] = get_byte (); /* Ignore extra flags. */
1583 magic[9] = get_byte (); /* Ignore OS type. */
1585 if (flags & HEADER_CRC)
1587 magic[2] = DEFLATED;
1588 magic[3] = flags;
1589 magic[4] = stamp & 0xff;
1590 magic[5] = (stamp >> 8) & 0xff;
1591 magic[6] = (stamp >> 16) & 0xff;
1592 magic[7] = stamp >> 24;
1593 updcrc (NULL, 0);
1594 updcrc (magic, 10);
1597 if ((flags & EXTRA_FIELD) != 0) {
1598 uch lenbuf[2];
1599 unsigned int len = lenbuf[0] = get_byte ();
1600 len |= (lenbuf[1] = get_byte ()) << 8;
1601 if (verbose) {
1602 fprintf(stderr,"%s: %s: extra field of %u bytes ignored\n",
1603 program_name, ifname, len);
1605 if (flags & HEADER_CRC)
1606 updcrc (lenbuf, 2);
1607 discard_input_bytes (len, flags);
1610 /* Get original file name if it was truncated */
1611 if ((flags & ORIG_NAME) != 0) {
1612 if (no_name || (to_stdout && !list) || part_nb > 1) {
1613 /* Discard the old name */
1614 discard_input_bytes (-1, flags);
1615 } else {
1616 /* Copy the base name. Keep a directory prefix intact. */
1617 char *p = gzip_base_name (ofname);
1618 char *base = p;
1619 for (;;) {
1620 *p = (char) get_byte ();
1621 if (*p++ == '\0') break;
1622 if (p >= ofname+sizeof(ofname)) {
1623 gzip_error ("corrupted input -- file name too large");
1626 if (flags & HEADER_CRC)
1627 updcrc ((uch *) base, p - base);
1628 p = gzip_base_name (base);
1629 memmove (base, p, strlen (p) + 1);
1630 /* If necessary, adapt the name to local OS conventions: */
1631 if (!list) {
1632 MAKE_LEGAL_NAME(base);
1633 if (base) list=0; /* avoid warning about unused variable */
1635 } /* no_name || to_stdout */
1636 } /* ORIG_NAME */
1638 /* Discard file comment if any */
1639 if ((flags & COMMENT) != 0) {
1640 discard_input_bytes (-1, flags);
1643 if (flags & HEADER_CRC)
1645 unsigned int crc16 = updcrc (magic, 0) & 0xffff;
1646 unsigned int header16 = get_byte ();
1647 header16 |= ((unsigned int) get_byte ()) << 8;
1648 if (header16 != crc16)
1650 fprintf (stderr,
1651 "%s: %s: header checksum 0x%04x != computed checksum 0x%04x\n",
1652 program_name, ifname, header16, crc16);
1653 exit_code = ERROR;
1654 if (force <= 1)
1655 return -1;
1659 if (part_nb == 1) {
1660 header_bytes = inptr + 2*4; /* include crc and size */
1663 } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
1664 && memcmp((char*)inbuf, PKZIP_MAGIC, 4) == 0) {
1665 /* To simplify the code, we support a zip file when alone only.
1666 * We are thus guaranteed that the entire local header fits in inbuf.
1668 inptr = 0;
1669 work = unzip;
1670 if (check_zipfile(in) != OK) return -1;
1671 /* check_zipfile may get ofname from the local header */
1672 last_member = 1;
1674 } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
1675 work = unpack;
1676 method = PACKED;
1678 } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {
1679 work = unlzw;
1680 method = COMPRESSED;
1681 last_member = 1;
1683 } else if (memcmp(magic, LZH_MAGIC, 2) == 0) {
1684 work = unlzh;
1685 method = LZHED;
1686 last_member = 1;
1688 } else if (force && to_stdout && !list) { /* pass input unchanged */
1689 method = STORED;
1690 work = copy;
1691 if (imagic1 != EOF)
1692 inptr--;
1693 last_member = 1;
1694 if (imagic0 != EOF) {
1695 write_buf (STDOUT_FILENO, magic, 1);
1698 if (method >= 0) return method;
1700 if (part_nb == 1) {
1701 fprintf (stderr, "\n%s: %s: not in gzip format\n",
1702 program_name, ifname);
1703 exit_code = ERROR;
1704 return -1;
1705 } else {
1706 if (magic[0] == 0)
1708 int inbyte;
1709 for (inbyte = imagic1; inbyte == 0; inbyte = try_byte ())
1710 continue;
1711 if (inbyte == EOF)
1713 if (verbose)
1714 WARN ((stderr, "\n%s: %s: decompression OK, trailing zero bytes ignored\n",
1715 program_name, ifname));
1716 return -3;
1720 WARN((stderr, "\n%s: %s: decompression OK, trailing garbage ignored\n",
1721 program_name, ifname));
1722 return -2;
1726 /* ========================================================================
1727 * Display the characteristics of the compressed file.
1728 * If the given method is < 0, display the accumulated totals.
1729 * IN assertions: time_stamp, header_bytes and ifile_size are initialized.
1731 static void
1732 do_list (int method)
1734 ulg crc; /* original crc */
1735 static int first_time = 1;
1736 static char const *const methods[MAX_METHODS] = {
1737 "store", /* 0 */
1738 "compr", /* 1 */
1739 "pack ", /* 2 */
1740 "lzh ", /* 3 */
1741 "", "", "", "", /* 4 to 7 reserved */
1742 "defla"}; /* 8 */
1743 int positive_off_t_width = INT_STRLEN_BOUND (off_t) - 1;
1745 if (first_time && method >= 0) {
1746 first_time = 0;
1747 if (verbose) {
1748 printf("method crc date time ");
1750 if (!quiet) {
1751 printf("%*.*s %*.*s ratio uncompressed_name\n",
1752 positive_off_t_width, positive_off_t_width, "compressed",
1753 positive_off_t_width, positive_off_t_width, "uncompressed");
1755 } else if (method < 0) {
1756 if (total_in <= 0 || total_out <= 0) return;
1757 if (verbose) {
1758 printf(" ");
1760 if (verbose || !quiet) {
1761 fprint_off(stdout, total_in, positive_off_t_width);
1762 printf(" ");
1763 fprint_off(stdout, total_out, positive_off_t_width);
1764 printf(" ");
1766 display_ratio(total_out-(total_in-header_bytes), total_out, stdout);
1767 /* header_bytes is not meaningful but used to ensure the same
1768 * ratio if there is a single file.
1770 printf(" (totals)\n");
1771 return;
1773 crc = (ulg)~0; /* unknown */
1775 if (method == DEFLATED && !last_member) {
1776 crc = unzip_crc;
1779 if (verbose)
1781 static char const month_abbr[][4]
1782 = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1783 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
1784 struct tm *tm = localtime (&time_stamp.tv_sec);
1785 printf ("%5s %08lx ", methods[method], crc);
1786 if (tm)
1787 printf ("%s%3d %02d:%02d ", month_abbr[tm->tm_mon],
1788 tm->tm_mday, tm->tm_hour, tm->tm_min);
1789 else
1790 printf ("??? ?? ??:?? ");
1792 fprint_off(stdout, bytes_in, positive_off_t_width);
1793 printf(" ");
1794 fprint_off(stdout, bytes_out, positive_off_t_width);
1795 printf(" ");
1796 if (bytes_in == -1L) {
1797 total_in = -1L;
1798 bytes_in = bytes_out = header_bytes = 0;
1799 } else if (total_in >= 0) {
1800 total_in += bytes_in;
1802 if (bytes_out == -1L) {
1803 total_out = -1L;
1804 bytes_in = bytes_out = header_bytes = 0;
1805 } else if (total_out >= 0) {
1806 total_out += bytes_out;
1808 display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out, stdout);
1809 printf(" %s\n", ofname);
1812 /* ========================================================================
1813 * Shorten the given name by one character, or replace a .tar extension
1814 * with .tgz. Truncate the last part of the name which is longer than
1815 * MIN_PART characters: 1234.678.012.gz -> 123.678.012.gz. If the name
1816 * has only parts shorter than MIN_PART truncate the longest part.
1817 * For decompression, just remove the last character of the name.
1819 * IN assertion: for compression, the suffix of the given name is z_suffix.
1821 static void
1822 shorten_name (char *name)
1824 int len; /* length of name without z_suffix */
1825 char *trunc = NULL; /* character to be truncated */
1826 int plen; /* current part length */
1827 int min_part = MIN_PART; /* current minimum part length */
1828 char *p;
1830 len = strlen(name);
1831 if (decompress) {
1832 if (len <= 1)
1833 gzip_error ("name too short");
1834 name[len-1] = '\0';
1835 return;
1837 p = get_suffix(name);
1838 if (! p)
1839 gzip_error ("can't recover suffix\n");
1840 *p = '\0';
1841 save_orig_name = 1;
1843 /* compress 1234567890.tar to 1234567890.tgz */
1844 if (len > 4 && strequ(p-4, ".tar")) {
1845 strcpy(p-4, ".tgz");
1846 return;
1848 /* Try keeping short extensions intact:
1849 * 1234.678.012.gz -> 123.678.012.gz
1851 do {
1852 p = last_component (name);
1853 while (*p) {
1854 plen = strcspn(p, PART_SEP);
1855 p += plen;
1856 if (plen > min_part) trunc = p-1;
1857 if (*p) p++;
1859 } while (trunc == NULL && --min_part != 0);
1861 if (trunc != NULL) {
1862 do {
1863 trunc[0] = trunc[1];
1864 } while (*trunc++);
1865 trunc--;
1866 } else {
1867 trunc = strrchr(name, PART_SEP[0]);
1868 if (!trunc)
1869 gzip_error ("internal error in shorten_name");
1870 if (trunc[1] == '\0') trunc--; /* force truncation */
1872 strcpy(trunc, z_suffix);
1875 /* ========================================================================
1876 * The compressed file already exists, so ask for confirmation.
1877 * Return ERROR if the file must be skipped.
1879 static int
1880 check_ofname ()
1882 /* Ask permission to overwrite the existing file */
1883 if (!force) {
1884 int ok = 0;
1885 fprintf (stderr, "%s: %s already exists;", program_name, ofname);
1886 if (foreground && (presume_input_tty || isatty (STDIN_FILENO))) {
1887 fprintf(stderr, " do you wish to overwrite (y or n)? ");
1888 fflush(stderr);
1889 ok = yesno();
1891 if (!ok) {
1892 fprintf(stderr, "\tnot overwritten\n");
1893 if (exit_code == OK) exit_code = WARNING;
1894 return ERROR;
1897 if (xunlink (ofname)) {
1898 progerror(ofname);
1899 return ERROR;
1901 return OK;
1904 /* Change the owner and group of a file. FD is a file descriptor for
1905 the file and NAME its name. Change it to user UID and to group GID.
1906 If UID or GID is -1, though, do not change the corresponding user
1907 or group. */
1908 #if ! (HAVE_FCHOWN || HAVE_CHOWN)
1909 /* The types uid_t and gid_t do not exist on mingw, so don't assume them. */
1910 # define do_chown(fd, name, uid, gid) ((void) 0)
1911 #else
1912 static void
1913 do_chown (int fd, char const *name, uid_t uid, gid_t gid)
1915 # if HAVE_FCHOWN
1916 ignore_value (fchown (fd, uid, gid));
1917 # else
1918 ignore_value (chown (name, uid, gid));
1919 # endif
1921 #endif
1923 /* ========================================================================
1924 * Copy modes, times, ownership from input file to output file.
1925 * IN assertion: to_stdout is false.
1927 static void
1928 copy_stat (struct stat *ifstat)
1930 mode_t mode = ifstat->st_mode & S_IRWXUGO;
1931 int r;
1933 #ifndef NO_UTIME
1934 bool restoring;
1935 struct timespec timespec[2];
1936 timespec[0] = get_stat_atime (ifstat);
1937 timespec[1] = get_stat_mtime (ifstat);
1938 restoring = (decompress && 0 <= time_stamp.tv_nsec
1939 && ! (timespec[1].tv_sec == time_stamp.tv_sec
1940 && timespec[1].tv_nsec == time_stamp.tv_nsec));
1941 if (restoring)
1942 timespec[1] = time_stamp;
1944 if (fdutimens (ofd, ofname, timespec) == 0)
1946 if (restoring && 1 < verbose) {
1947 fprintf(stderr, "%s: timestamp restored\n", ofname);
1950 else
1952 int e = errno;
1953 WARN ((stderr, "%s: ", program_name));
1954 if (!quiet)
1956 errno = e;
1957 perror (ofname);
1960 #endif
1962 /* Change the group first, then the permissions, then the owner.
1963 That way, the permissions will be correct on systems that allow
1964 users to give away files, without introducing a security hole.
1965 Security depends on permissions not containing the setuid or
1966 setgid bits. */
1968 do_chown (ofd, ofname, -1, ifstat->st_gid);
1970 #if HAVE_FCHMOD
1971 r = fchmod (ofd, mode);
1972 #else
1973 r = chmod (ofname, mode);
1974 #endif
1975 if (r != 0) {
1976 int e = errno;
1977 WARN ((stderr, "%s: ", program_name));
1978 if (!quiet) {
1979 errno = e;
1980 perror(ofname);
1984 do_chown (ofd, ofname, ifstat->st_uid, -1);
1987 #if ! NO_DIR
1989 /* ========================================================================
1990 * Recurse through the given directory.
1992 static void
1993 treat_dir (int fd, char *dir)
1995 DIR *dirp;
1996 char nbuf[MAX_PATH_LEN];
1997 char *entries;
1998 char const *entry;
1999 size_t entrylen;
2001 dirp = fdopendir (fd);
2003 if (dirp == NULL) {
2004 progerror(dir);
2005 close (fd);
2006 return ;
2009 entries = streamsavedir (dirp, SAVEDIR_SORT_NONE);
2010 if (! entries)
2011 progerror (dir);
2012 if (closedir (dirp) != 0)
2013 progerror (dir);
2014 if (! entries)
2015 return;
2017 for (entry = entries; *entry; entry += entrylen + 1) {
2018 size_t len = strlen (dir);
2019 entrylen = strlen (entry);
2020 if (strequ (entry, ".") || strequ (entry, ".."))
2021 continue;
2022 if (len + entrylen < MAX_PATH_LEN - 2) {
2023 strcpy(nbuf,dir);
2024 if (*last_component (nbuf) && !ISSLASH (nbuf[len - 1]))
2025 nbuf[len++] = '/';
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;
2034 free (entries);
2036 #endif /* ! NO_DIR */
2038 /* Make sure signals get handled properly. */
2040 static void
2041 install_signal_handlers ()
2043 int nsigs = sizeof handled_sig / sizeof handled_sig[0];
2044 int i;
2045 struct sigaction act;
2047 sigemptyset (&caught_signals);
2048 for (i = 0; i < nsigs; i++)
2050 sigaction (handled_sig[i], NULL, &act);
2051 if (act.sa_handler != SIG_IGN)
2052 sigaddset (&caught_signals, handled_sig[i]);
2055 act.sa_handler = abort_gzip_signal;
2056 act.sa_mask = caught_signals;
2057 act.sa_flags = 0;
2059 for (i = 0; i < nsigs; i++)
2060 if (sigismember (&caught_signals, handled_sig[i]))
2062 if (i == 0)
2063 foreground = 1;
2064 sigaction (handled_sig[i], &act, NULL);
2068 /* ========================================================================
2069 * Free all dynamically allocated variables and exit with the given code.
2071 static void
2072 do_exit (int exitcode)
2074 static int in_exit = 0;
2076 if (in_exit) exit(exitcode);
2077 in_exit = 1;
2078 free(env);
2079 env = NULL;
2080 FREE(inbuf);
2081 FREE(outbuf);
2082 FREE(d_buf);
2083 FREE(window);
2084 #ifndef MAXSEG_64K
2085 FREE(tab_prefix);
2086 #else
2087 FREE(tab_prefix0);
2088 FREE(tab_prefix1);
2089 #endif
2090 exit(exitcode);
2093 static void
2094 finish_out ()
2096 if (fclose (stdout) != 0)
2097 write_error ();
2098 do_exit (OK);
2101 /* ========================================================================
2102 * Close and unlink the output file.
2104 static void
2105 remove_output_file (bool signals_already_blocked)
2107 int fd;
2108 sigset_t oldset;
2110 if (!signals_already_blocked)
2111 sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
2112 fd = remove_ofname_fd;
2113 if (0 <= fd)
2115 char fname[MAX_PATH_LEN];
2116 remove_ofname_fd = -1;
2117 close (fd);
2118 volatile_strcpy (fname, remove_ofname);
2119 xunlink (fname);
2121 if (!signals_already_blocked)
2122 sigprocmask (SIG_SETMASK, &oldset, NULL);
2125 /* ========================================================================
2126 * Error handler.
2128 void
2129 abort_gzip ()
2131 remove_output_file (false);
2132 do_exit(ERROR);
2135 /* ========================================================================
2136 * Signal handler.
2138 static void
2139 abort_gzip_signal (int sig)
2141 remove_output_file (true);
2142 if (sig == exiting_signal)
2143 _exit (WARNING);
2144 signal (sig, SIG_DFL);
2145 raise (sig);