gzip: clarify "other links" diagnostic
[gzip.git] / gzip.c
blobf75b61425d9d996d3e4a839035638b88a3026794
1 /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
3 Copyright (C) 1999, 2001-2002, 2006-2007, 2009-2021 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) 2018 Free Software Foundation, Inc.",
33 "Copyright (C) 1993 Jean-loup Gailly.",
34 "This is free software. You may redistribute copies of it under the terms of",
35 "the GNU General Public License <https://www.gnu.org/licenses/gpl.html>.",
36 "There is NO WARRANTY, to the extent permitted by law.",
37 0};
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 int verbose = 0; /* be verbose (-v) */
177 int quiet = 0; /* be very quiet (-q) */
178 static int do_lzw = 0; /* generate output compatible with old compress (-Z) */
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 ryncable 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 local noreturn void try_help (void);
307 local void help (void);
308 local void license (void);
309 local void version (void);
310 local int input_eof (void);
311 local void treat_stdin (void);
312 local void treat_file (char *iname);
313 local int create_outfile (void);
314 local char *get_suffix (char *name);
315 local int open_input_file (char *iname, struct stat *sbuf);
316 local void discard_input_bytes (size_t nbytes, unsigned int flags);
317 local int make_ofname (void);
318 local void shorten_name (char *name);
319 local int get_method (int in);
320 local void do_list (int ifd, int method);
321 local int check_ofname (void);
322 local void copy_stat (struct stat *ifstat);
323 local void install_signal_handlers (void);
324 static void remove_output_file (bool);
325 static void abort_gzip_signal (int);
326 local noreturn 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 local 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 local void help()
348 static char const* const help_msg[] = {
349 "Compress or uncompress FILEs (by default, compress FILES in-place).",
351 "Mandatory arguments to long options are mandatory for short options too.",
353 #if O_BINARY
354 " -a, --ascii ascii text; convert end-of-line using local conventions",
355 #endif
356 " -c, --stdout write on standard output, keep original files unchanged",
357 " -d, --decompress decompress",
358 /* -e, --encrypt encrypt */
359 " -f, --force force overwrite of output file and compress links",
360 " -h, --help give this help",
361 /* -k, --pkzip force output in pkzip format */
362 " -k, --keep keep (don't delete) input files",
363 " -l, --list list compressed file contents",
364 " -L, --license display software license",
365 #ifdef UNDOCUMENTED
366 " -m do not save or restore the original modification time",
367 " -M, --time save or restore the original modification time",
368 #endif
369 " -n, --no-name do not save or restore the original name and timestamp",
370 " -N, --name save or restore the original name and timestamp",
371 " -q, --quiet suppress all warnings",
372 #if ! NO_DIR
373 " -r, --recursive operate recursively on directories",
374 #endif
375 " --rsyncable make rsync-friendly archive",
376 " -S, --suffix=SUF use suffix SUF on compressed files",
377 " --synchronous synchronous output (safer if system crashes, but slower)",
378 " -t, --test test compressed file integrity",
379 " -v, --verbose verbose mode",
380 " -V, --version display version number",
381 " -1, --fast compress faster",
382 " -9, --best compress better",
383 #ifdef LZW
384 " -Z, --lzw produce output compatible with old compress",
385 " -b, --bits=BITS max number of bits per code (implies -Z)",
386 #endif
388 "With no FILE, or when FILE is -, read standard input.",
390 "Report bugs to <bug-gzip@gnu.org>.",
392 char const *const *p = help_msg;
394 printf ("Usage: %s [OPTION]... [FILE]...\n", program_name);
395 while (*p) printf ("%s\n", *p++);
398 /* ======================================================================== */
399 local void license()
401 char const *const *p = license_msg;
403 printf ("%s %s\n", program_name, Version);
404 while (*p) printf ("%s\n", *p++);
407 /* ======================================================================== */
408 local void version()
410 license ();
411 printf ("\n");
412 printf ("Written by Jean-loup Gailly.\n");
415 local void 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 = 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 #ifdef LZW
592 do_lzw = 1; break;
593 #else
594 fprintf(stderr, "%s: -Z not supported in this version\n",
595 program_name);
596 try_help ();
597 break;
598 #endif
599 case '1' + ENV_OPTION: case '2' + ENV_OPTION: case '3' + ENV_OPTION:
600 case '4' + ENV_OPTION: case '5' + ENV_OPTION: case '6' + ENV_OPTION:
601 case '7' + ENV_OPTION: case '8' + ENV_OPTION: case '9' + ENV_OPTION:
602 optc -= ENV_OPTION;
603 FALLTHROUGH;
604 case '1': case '2': case '3': case '4':
605 case '5': case '6': case '7': case '8': case '9':
606 level = optc - '0';
607 break;
609 default:
610 if (ENV_OPTION <= optc && optc != ENV_OPTION + '?')
612 /* Output a diagnostic, since getopt_long didn't. */
613 fprintf (stderr, "%s: ", program_name);
614 if (longind < 0)
615 fprintf (stderr, "-%c: ", optc - ENV_OPTION);
616 else
617 fprintf (stderr, "--%s: ", longopts[longind].name);
618 fprintf (stderr, ("option not valid in "OPTIONS_VAR
619 " environment variable\n"));
621 try_help ();
623 } /* loop on all arguments */
625 /* By default, save name and timestamp on compression but do not
626 * restore them on decompression.
628 if (no_time < 0) no_time = decompress;
629 if (no_name < 0) no_name = decompress;
631 file_count = argc - optind;
633 #if O_BINARY
634 #else
635 if (ascii && !quiet) {
636 fprintf(stderr, "%s: option --ascii ignored on this system\n",
637 program_name);
639 #endif
640 if (z_len == 0 || z_len > MAX_SUFFIX) {
641 fprintf(stderr, "%s: invalid suffix '%s'\n", program_name, z_suffix);
642 do_exit(ERROR);
645 if (do_lzw && !decompress) work = lzw;
647 /* Allocate all global buffers (for DYN_ALLOC option) */
648 ALLOC(uch, inbuf, INBUFSIZ +INBUF_EXTRA);
649 ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
650 ALLOC(ush, d_buf, DIST_BUFSIZE);
651 ALLOC(uch, window, 2L*WSIZE);
652 #ifndef MAXSEG_64K
653 ALLOC(ush, tab_prefix, 1L<<BITS);
654 #else
655 ALLOC(ush, tab_prefix0, 1L<<(BITS-1));
656 ALLOC(ush, tab_prefix1, 1L<<(BITS-1));
657 #endif
659 #if SIGPIPE
660 exiting_signal = quiet ? SIGPIPE : 0;
661 #endif
662 install_signal_handlers ();
664 /* And get to work */
665 if (file_count != 0) {
666 if (to_stdout && !test && !list && (!decompress || !ascii)) {
667 SET_BINARY_MODE (STDOUT_FILENO);
669 while (optind < argc) {
670 treat_file(argv[optind++]);
672 } else { /* Standard input */
673 treat_stdin();
675 if (stdin_was_read && close (STDIN_FILENO) != 0)
677 strcpy (ifname, "stdin");
678 read_error ();
680 if (list)
682 /* Output any totals, and check for output errors. */
683 if (!quiet && 1 < file_count)
684 do_list (-1, -1);
685 if (fflush (stdout) != 0)
686 write_error ();
688 if (to_stdout
689 && ((synchronous
690 && fdatasync (STDOUT_FILENO) != 0 && errno != EINVAL)
691 || close (STDOUT_FILENO) != 0)
692 && errno != EBADF)
693 write_error ();
694 do_exit(exit_code);
697 /* Return nonzero when at end of file on input. */
698 local int
699 input_eof ()
701 if (!decompress || last_member)
702 return 1;
704 if (inptr == insize)
706 if (insize != INBUFSIZ || fill_inbuf (1) == EOF)
707 return 1;
709 /* Unget the char that fill_inbuf got. */
710 inptr = 0;
713 return 0;
716 static void
717 get_input_size_and_time (void)
719 ifile_size = -1;
720 time_stamp.tv_nsec = -1;
722 /* Record the input file's size and timestamp only if it is a
723 regular file. Doing this for the timestamp helps to keep gzip's
724 output more reproducible when it is used as part of a
725 pipeline. */
727 if (S_ISREG (istat.st_mode))
729 ifile_size = istat.st_size;
730 if (!no_time || list)
731 time_stamp = get_stat_mtime (&istat);
735 /* ========================================================================
736 * Compress or decompress stdin
738 local void treat_stdin()
740 if (!force && !list
741 && (presume_input_tty
742 || isatty (decompress ? STDIN_FILENO : STDOUT_FILENO))) {
743 /* Do not send compressed data to the terminal or read it from
744 * the terminal. We get here when user invoked the program
745 * without parameters, so be helpful. According to the GNU standards:
747 * If there is one behavior you think is most useful when the output
748 * is to a terminal, and another that you think is most useful when
749 * the output is a file or a pipe, then it is usually best to make
750 * the default behavior the one that is useful with output to a
751 * terminal, and have an option for the other behavior.
753 * Here we use the --force option to get the other behavior.
755 if (! quiet)
756 fprintf (stderr,
757 ("%s: compressed data not %s a terminal."
758 " Use -f to force %scompression.\n"
759 "For help, type: %s -h\n"),
760 program_name,
761 decompress ? "read from" : "written to",
762 decompress ? "de" : "",
763 program_name);
764 do_exit(ERROR);
767 if (decompress || !ascii) {
768 SET_BINARY_MODE (STDIN_FILENO);
770 if (!test && !list && (!decompress || !ascii)) {
771 SET_BINARY_MODE (STDOUT_FILENO);
773 strcpy(ifname, "stdin");
774 strcpy(ofname, "stdout");
776 /* Get the file's timestamp and size. */
777 if (fstat (STDIN_FILENO, &istat) != 0)
779 progerror ("standard input");
780 do_exit (ERROR);
783 get_input_size_and_time ();
785 clear_bufs(); /* clear input and output buffers */
786 to_stdout = 1;
787 part_nb = 0;
788 ifd = STDIN_FILENO;
789 stdin_was_read = true;
791 if (decompress) {
792 method = get_method(ifd);
793 if (method < 0) {
794 do_exit(exit_code); /* error message already emitted */
797 if (list) {
798 do_list(ifd, method);
799 return;
802 /* Actually do the compression/decompression. Loop over zipped members.
804 for (;;) {
805 if (work (STDIN_FILENO, STDOUT_FILENO) != OK)
806 return;
808 if (input_eof ())
809 break;
811 method = get_method(ifd);
812 if (method < 0) return; /* error message already emitted */
813 bytes_out = 0; /* required for length check */
816 if (verbose) {
817 if (test) {
818 fprintf(stderr, " OK\n");
820 } else if (!decompress) {
821 display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
822 fprintf(stderr, "\n");
823 #ifdef DISPLAY_STDIN_RATIO
824 } else {
825 display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
826 fprintf(stderr, "\n");
827 #endif
832 static char const dot = '.';
834 /* True if the cached directory for calls to openat etc. is DIR, with
835 length DIRLEN. DIR need not be null-terminated. DIRLEN must be
836 less than MAX_PATH_LEN. */
837 static bool
838 atdir_eq (char const *dir, ptrdiff_t dirlen)
840 if (dirlen == 0)
841 dir = &dot, dirlen = 1;
842 return memcmp (dfname, dir, dirlen) == 0 && !dfname[dirlen];
845 /* Set the directory used for calls to openat etc. to be the directory
846 DIR, with length DIRLEN. DIR need not be null-terminated.
847 DIRLEN must be less than MAX_PATH_LEN. Return a file descriptor for
848 the directory, or -1 if one could not be obtained. */
849 static int
850 atdir_set (char const *dir, ptrdiff_t dirlen)
852 /* Don't bother opening directories on older systems that
853 lack openat and unlinkat. It's not worth the porting hassle. */
854 #if HAVE_OPENAT && HAVE_UNLINKAT
855 enum { try_opening_directories = true };
856 #else
857 enum { try_opening_directories = false };
858 #endif
860 if (try_opening_directories && ! atdir_eq (dir, dirlen))
862 if (0 <= dfd)
863 close (dfd);
864 if (dirlen == 0)
865 dir = &dot, dirlen = 1;
866 memcpy (dfname, dir, dirlen);
867 dfname[dirlen] = '\0';
868 dfd = open (dfname, O_SEARCH | O_DIRECTORY);
871 return dfd;
874 /* ========================================================================
875 * Compress or decompress the given file
877 local void treat_file(iname)
878 char *iname;
880 /* Accept "-" as synonym for stdin */
881 if (strequ(iname, "-")) {
882 int cflag = to_stdout;
883 treat_stdin();
884 to_stdout = cflag;
885 return;
888 /* Check if the input file is present, set ifname and istat: */
889 ifd = open_input_file (iname, &istat);
890 if (ifd < 0)
891 return;
893 /* If the input name is that of a directory, recurse or ignore: */
894 if (S_ISDIR(istat.st_mode)) {
895 #if ! NO_DIR
896 if (recursive) {
897 treat_dir (ifd, iname);
898 /* Warning: ifname is now garbage */
899 return;
901 #endif
902 close (ifd);
903 WARN ((stderr, "%s: %s is a directory -- ignored\n",
904 program_name, ifname));
905 return;
908 if (! to_stdout)
910 if (! S_ISREG (istat.st_mode))
912 WARN ((stderr,
913 "%s: %s is not a directory or a regular file - ignored\n",
914 program_name, ifname));
915 close (ifd);
916 return;
918 if (istat.st_mode & S_ISUID)
920 WARN ((stderr, "%s: %s is set-user-ID on execution - ignored\n",
921 program_name, ifname));
922 close (ifd);
923 return;
925 if (istat.st_mode & S_ISGID)
927 WARN ((stderr, "%s: %s is set-group-ID on execution - ignored\n",
928 program_name, ifname));
929 close (ifd);
930 return;
933 if (! force)
935 if (istat.st_mode & S_ISVTX)
937 WARN ((stderr,
938 "%s: %s has the sticky bit set - file ignored\n",
939 program_name, ifname));
940 close (ifd);
941 return;
943 if (2 <= istat.st_nlink)
945 WARN ((stderr, "%s: %s has %lu other link%s -- file ignored\n",
946 program_name, ifname,
947 (unsigned long int) istat.st_nlink - 1,
948 istat.st_nlink == 2 ? "" : "s"));
949 close (ifd);
950 return;
955 get_input_size_and_time ();
957 /* Generate output file name. For -r and (-t or -l), skip files
958 * without a valid gzip suffix (check done in make_ofname).
960 if (to_stdout && !list && !test) {
961 strcpy(ofname, "stdout");
963 } else if (make_ofname() != OK) {
964 close (ifd);
965 return;
968 clear_bufs(); /* clear input and output buffers */
969 part_nb = 0;
971 if (decompress) {
972 method = get_method(ifd); /* updates ofname if original given */
973 if (method < 0) {
974 close(ifd);
975 return; /* error message already emitted */
978 if (list) {
979 do_list(ifd, method);
980 if (close (ifd) != 0)
981 read_error ();
982 return;
985 /* If compressing to a file, check if ofname is not ambiguous
986 * because the operating system truncates names. Otherwise, generate
987 * a new ofname and save the original name in the compressed file.
989 if (to_stdout) {
990 ofd = STDOUT_FILENO;
991 /* Keep remove_ofname_fd negative. */
992 } else {
993 if (create_outfile() != OK) return;
995 if (!decompress && save_orig_name && !verbose && !quiet) {
996 fprintf(stderr, "%s: %s compressed to %s\n",
997 program_name, ifname, ofname);
1000 /* Keep the name even if not truncated except with --no-name: */
1001 if (!save_orig_name) save_orig_name = !no_name;
1003 if (verbose) {
1004 fprintf(stderr, "%s:\t", ifname);
1007 /* Actually do the compression/decompression. Loop over zipped members.
1009 for (;;) {
1010 if ((*work)(ifd, ofd) != OK) {
1011 method = -1; /* force cleanup */
1012 break;
1015 if (input_eof ())
1016 break;
1018 method = get_method(ifd);
1019 if (method < 0) break; /* error message already emitted */
1020 bytes_out = 0; /* required for length check */
1023 if (close (ifd) != 0)
1024 read_error ();
1026 if (!to_stdout)
1028 copy_stat (&istat);
1030 if ((synchronous
1031 && ((0 <= dfd && fdatasync (dfd) != 0 && errno != EINVAL)
1032 || (fsync (ofd) != 0 && errno != EINVAL)))
1033 || close (ofd) != 0)
1034 write_error ();
1036 if (!keep)
1038 sigset_t oldset;
1039 int unlink_errno;
1040 char *ifbase = last_component (ifname);
1041 int ufd = atdir_eq (ifname, ifbase - ifname) ? dfd : -1;
1042 int res;
1044 sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
1045 remove_ofname_fd = -1;
1046 res = ufd < 0 ? xunlink (ifname) : unlinkat (ufd, ifbase, 0);
1047 unlink_errno = res == 0 ? 0 : errno;
1048 sigprocmask (SIG_SETMASK, &oldset, NULL);
1050 if (unlink_errno)
1052 WARN ((stderr, "%s: ", program_name));
1053 if (!quiet)
1055 errno = unlink_errno;
1056 perror (ifname);
1062 if (method == -1) {
1063 if (!to_stdout)
1064 remove_output_file (false);
1065 return;
1068 /* Display statistics */
1069 if(verbose) {
1070 if (test) {
1071 fprintf(stderr, " OK");
1072 } else if (decompress) {
1073 display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
1074 } else {
1075 display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
1077 if (!test && !to_stdout)
1078 fprintf(stderr, " -- %s %s", keep ? "created" : "replaced with",
1079 ofname);
1080 fprintf(stderr, "\n");
1084 static void
1085 volatile_strcpy (char volatile *dst, char const volatile *src)
1087 while ((*dst++ = *src++))
1088 continue;
1091 /* ========================================================================
1092 * Create the output file. Return OK or ERROR.
1093 * Try several times if necessary to avoid truncating the z_suffix. For
1094 * example, do not create a compressed file of name "1234567890123."
1095 * Sets save_orig_name to true if the file name has been truncated.
1096 * IN assertions: the input file has already been open (ifd is set) and
1097 * ofname has already been updated if there was an original name.
1098 * OUT assertions: ifd and ofd are closed in case of error.
1100 local int create_outfile()
1102 int name_shortened = 0;
1103 int flags = (O_WRONLY | O_CREAT | O_EXCL
1104 | (ascii && decompress ? 0 : O_BINARY));
1105 char const *base = ofname;
1106 int atfd = AT_FDCWD;
1108 if (!keep)
1110 char const *b = last_component (ofname);
1111 int f = atdir_set (ofname, b - ofname);
1112 if (0 <= f)
1114 base = b;
1115 atfd = f;
1119 for (;;)
1121 int open_errno;
1122 sigset_t oldset;
1124 volatile_strcpy (remove_ofname, ofname);
1126 sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
1127 remove_ofname_fd = ofd = openat (atfd, base, flags, S_IRUSR | S_IWUSR);
1128 open_errno = errno;
1129 sigprocmask (SIG_SETMASK, &oldset, NULL);
1131 if (0 <= ofd)
1132 break;
1134 switch (open_errno)
1136 #ifdef ENAMETOOLONG
1137 case ENAMETOOLONG:
1138 shorten_name (ofname);
1139 name_shortened = 1;
1140 break;
1141 #endif
1143 case EEXIST:
1144 if (check_ofname () != OK)
1146 close (ifd);
1147 return ERROR;
1149 break;
1151 default:
1152 progerror (ofname);
1153 close (ifd);
1154 return ERROR;
1158 if (name_shortened && decompress)
1160 /* name might be too long if an original name was saved */
1161 WARN ((stderr, "%s: %s: warning, name truncated\n",
1162 program_name, ofname));
1165 return OK;
1168 /* ========================================================================
1169 * Return a pointer to the 'z' suffix of a file name, or NULL. For all
1170 * systems, ".gz", ".z", ".Z", ".taz", ".tgz", "-gz", "-z" and "_z" are
1171 * accepted suffixes, in addition to the value of the --suffix option.
1172 * ".tgz" is a useful convention for tar.z files on systems limited
1173 * to 3 characters extensions. On such systems, ".?z" and ".??z" are
1174 * also accepted suffixes. For Unix, we do not want to accept any
1175 * .??z suffix as indicating a compressed file; some people use .xyz
1176 * to denote volume data.
1178 local char *get_suffix(name)
1179 char *name;
1181 int nlen, slen;
1182 char suffix[MAX_SUFFIX+3]; /* last chars of name, forced to lower case */
1183 static char const *known_suffixes[] =
1184 {NULL, ".gz", ".z", ".taz", ".tgz", "-gz", "-z", "_z",
1185 #ifdef MAX_EXT_CHARS
1186 "z",
1187 #endif
1188 NULL, NULL};
1189 char const **suf;
1190 bool suffix_of_builtin = false;
1192 /* Normally put Z_SUFFIX at the start of KNOWN_SUFFIXES, but if it
1193 is a suffix of one of them, put it at the end. */
1194 for (suf = known_suffixes + 1; *suf; suf++)
1196 size_t suflen = strlen (*suf);
1197 if (z_len < suflen && strequ (z_suffix, *suf + suflen - z_len))
1199 suffix_of_builtin = true;
1200 break;
1204 char *z_lower = xstrdup(z_suffix);
1205 strlwr(z_lower);
1206 known_suffixes[suffix_of_builtin
1207 ? sizeof known_suffixes / sizeof *known_suffixes - 2
1208 : 0] = z_lower;
1209 suf = known_suffixes + suffix_of_builtin;
1211 nlen = strlen(name);
1212 if (nlen <= MAX_SUFFIX+2) {
1213 strcpy(suffix, name);
1214 } else {
1215 strcpy(suffix, name+nlen-MAX_SUFFIX-2);
1217 strlwr(suffix);
1218 slen = strlen(suffix);
1219 char *match = NULL;
1220 do {
1221 int s = strlen(*suf);
1222 if (slen > s && ! ISSLASH (suffix[slen - s - 1])
1223 && strequ(suffix + slen - s, *suf)) {
1224 match = name+nlen-s;
1225 break;
1227 } while (*++suf != NULL);
1228 free(z_lower);
1230 return match;
1234 /* Open file NAME with the given flags and store its status
1235 into *ST. Return a file descriptor to the newly opened file, or -1
1236 (setting errno) on failure. */
1237 static int
1238 open_and_stat (char *name, int flags, struct stat *st)
1240 int fd;
1241 int atfd = AT_FDCWD;
1242 char const *base = name;
1244 /* Refuse to follow symbolic links unless -c or -f. */
1245 if (!to_stdout && !force)
1247 if (HAVE_WORKING_O_NOFOLLOW)
1248 flags |= O_NOFOLLOW;
1249 else
1251 #ifdef S_ISLNK
1252 if (lstat (name, st) != 0)
1253 return -1;
1254 else if (S_ISLNK (st->st_mode))
1256 errno = ELOOP;
1257 return -1;
1259 #endif
1263 if (!keep)
1265 char const *b = last_component (name);
1266 int f = atdir_set (name, b - name);
1267 if (0 <= f)
1269 base = b;
1270 atfd = f;
1274 fd = openat (atfd, base, flags);
1275 if (0 <= fd && fstat (fd, st) != 0)
1277 int e = errno;
1278 close (fd);
1279 errno = e;
1280 return -1;
1282 return fd;
1286 /* ========================================================================
1287 * Set ifname to the input file name (with a suffix appended if necessary)
1288 * and istat to its stats. For decompression, if no file exists with the
1289 * original name, try adding successively z_suffix, .gz, .z, -z and .Z.
1290 * For MSDOS, we try only z_suffix and z.
1291 * Return an open file descriptor or -1.
1293 static int
1294 open_input_file (iname, sbuf)
1295 char *iname;
1296 struct stat *sbuf;
1298 int ilen; /* strlen(ifname) */
1299 int z_suffix_errno = 0;
1300 static char const *suffixes[] = {NULL, ".gz", ".z", "-z", ".Z", NULL};
1301 char const **suf = suffixes;
1302 char const *s;
1303 #ifdef NO_MULTIPLE_DOTS
1304 char *dot; /* pointer to ifname extension, or NULL */
1305 #endif
1306 int fd;
1307 int open_flags = (O_RDONLY | O_NONBLOCK | O_NOCTTY
1308 | (ascii && !decompress ? 0 : O_BINARY));
1310 *suf = z_suffix;
1312 if (sizeof ifname - 1 <= strlen (iname))
1313 goto name_too_long;
1315 strcpy(ifname, iname);
1317 /* If input file exists, return OK. */
1318 fd = open_and_stat (ifname, open_flags, sbuf);
1319 if (0 <= fd)
1320 return fd;
1322 if (!decompress || errno != ENOENT) {
1323 progerror(ifname);
1324 return -1;
1326 /* File.ext doesn't exist. Try adding a suffix. */
1327 s = get_suffix(ifname);
1328 if (s != NULL) {
1329 progerror(ifname); /* ifname already has z suffix and does not exist */
1330 return -1;
1332 #ifdef NO_MULTIPLE_DOTS
1333 dot = strrchr(ifname, '.');
1334 if (dot == NULL) {
1335 strcat(ifname, ".");
1336 dot = strrchr(ifname, '.');
1338 #endif
1339 ilen = strlen(ifname);
1340 if (strequ(z_suffix, ".gz")) suf++;
1342 /* Search for all suffixes */
1343 do {
1344 char const *s0 = s = *suf;
1345 strcpy (ifname, iname);
1346 #ifdef NO_MULTIPLE_DOTS
1347 if (*s == '.') s++;
1348 if (*dot == '\0') strcpy (dot, ".");
1349 #endif
1350 #ifdef MAX_EXT_CHARS
1351 if (MAX_EXT_CHARS < strlen (s) + strlen (dot + 1))
1352 dot[MAX_EXT_CHARS + 1 - strlen (s)] = '\0';
1353 #endif
1354 if (sizeof ifname <= ilen + strlen (s))
1355 goto name_too_long;
1356 strcat(ifname, s);
1357 fd = open_and_stat (ifname, open_flags, sbuf);
1358 if (0 <= fd)
1359 return fd;
1360 if (errno != ENOENT)
1362 progerror (ifname);
1363 return -1;
1365 if (strequ (s0, z_suffix))
1366 z_suffix_errno = errno;
1367 } while (*++suf != NULL);
1369 /* No suffix found, complain using z_suffix: */
1370 strcpy(ifname, iname);
1371 #ifdef NO_MULTIPLE_DOTS
1372 if (*dot == '\0') strcpy(dot, ".");
1373 #endif
1374 #ifdef MAX_EXT_CHARS
1375 if (MAX_EXT_CHARS < z_len + strlen (dot + 1))
1376 dot[MAX_EXT_CHARS + 1 - z_len] = '\0';
1377 #endif
1378 strcat(ifname, z_suffix);
1379 errno = z_suffix_errno;
1380 progerror(ifname);
1381 return -1;
1383 name_too_long:
1384 fprintf (stderr, "%s: %s: file name too long\n", program_name, iname);
1385 exit_code = ERROR;
1386 return -1;
1389 /* ========================================================================
1390 * Generate ofname given ifname. Return OK, or WARNING if file must be skipped.
1391 * Sets save_orig_name to true if the file name has been truncated.
1393 local int make_ofname()
1395 char *suff; /* ofname z suffix */
1397 strcpy(ofname, ifname);
1398 /* strip a version number if any and get the gzip suffix if present: */
1399 suff = get_suffix(ofname);
1401 if (decompress) {
1402 if (suff == NULL) {
1403 /* With -t or -l, try all files (even without .gz suffix)
1404 * except with -r (behave as with just -dr).
1406 if (!recursive && (list || test)) return OK;
1408 /* Avoid annoying messages with -r */
1409 if (verbose || (!recursive && !quiet)) {
1410 WARN((stderr,"%s: %s: unknown suffix -- ignored\n",
1411 program_name, ifname));
1413 return WARNING;
1415 /* Make a special case for .tgz and .taz: */
1416 strlwr(suff);
1417 if (strequ(suff, ".tgz") || strequ(suff, ".taz")) {
1418 strcpy(suff, ".tar");
1419 } else {
1420 *suff = '\0'; /* strip the z suffix */
1422 /* ofname might be changed later if infile contains an original name */
1424 } else if (suff && ! force) {
1425 /* Avoid annoying messages with -r (see treat_dir()) */
1426 if (verbose || (!recursive && !quiet)) {
1427 /* Don't use WARN, as it affects exit status. */
1428 fprintf (stderr, "%s: %s already has %s suffix -- unchanged\n",
1429 program_name, ifname, suff);
1431 return WARNING;
1432 } else {
1433 save_orig_name = 0;
1435 #ifdef NO_MULTIPLE_DOTS
1436 suff = strrchr(ofname, '.');
1437 if (suff == NULL) {
1438 if (sizeof ofname <= strlen (ofname) + 1)
1439 goto name_too_long;
1440 strcat(ofname, ".");
1441 # ifdef MAX_EXT_CHARS
1442 if (strequ(z_suffix, "z")) {
1443 if (sizeof ofname <= strlen (ofname) + 2)
1444 goto name_too_long;
1445 strcat(ofname, "gz"); /* enough room */
1446 return OK;
1448 /* On the Atari and some versions of MSDOS,
1449 * ENAMETOOLONG does not work correctly. So we
1450 * must truncate here.
1452 } else if (strlen(suff)-1 + z_len > MAX_SUFFIX) {
1453 suff[MAX_SUFFIX+1-z_len] = '\0';
1454 save_orig_name = 1;
1455 # endif
1457 #endif /* NO_MULTIPLE_DOTS */
1458 if (sizeof ofname <= strlen (ofname) + z_len)
1459 goto name_too_long;
1460 strcat(ofname, z_suffix);
1462 } /* decompress ? */
1463 return OK;
1465 name_too_long:
1466 WARN ((stderr, "%s: %s: file name too long\n", program_name, ifname));
1467 return WARNING;
1470 /* Discard NBYTES input bytes from the input, or up through the next
1471 zero byte if NBYTES == (size_t) -1. If FLAGS say that the header
1472 CRC should be computed, update the CRC accordingly. */
1473 static void
1474 discard_input_bytes (nbytes, flags)
1475 size_t nbytes;
1476 unsigned int flags;
1478 while (nbytes != 0)
1480 uch c = get_byte ();
1481 if (flags & HEADER_CRC)
1482 updcrc (&c, 1);
1483 if (nbytes != (size_t) -1)
1484 nbytes--;
1485 else if (! c)
1486 break;
1490 /* ========================================================================
1491 * Check the magic number of the input file and update ofname if an
1492 * original name was given and to_stdout is not set.
1493 * Return the compression method, -1 for error, -2 for warning.
1494 * Set inptr to the offset of the next byte to be processed.
1495 * Updates time_stamp if there is one and neither -m nor -n is used.
1496 * This function may be called repeatedly for an input file consisting
1497 * of several contiguous gzip'ed members.
1498 * IN assertions: there is at least one remaining compressed member.
1499 * If the member is a zip file, it must be the only one.
1501 local int get_method(in)
1502 int in; /* input file descriptor */
1504 uch flags; /* compression flags */
1505 uch magic[10]; /* magic header */
1506 int imagic0; /* first magic byte or EOF */
1507 int imagic1; /* like magic[1], but can represent EOF */
1508 ulg stamp; /* timestamp */
1510 /* If --force and --stdout, zcat == cat, so do not complain about
1511 * premature end of file: use try_byte instead of get_byte.
1513 if (force && to_stdout) {
1514 imagic0 = try_byte();
1515 magic[0] = imagic0;
1516 imagic1 = try_byte ();
1517 magic[1] = imagic1;
1518 /* If try_byte returned EOF, magic[1] == (char) EOF. */
1519 } else {
1520 magic[0] = get_byte ();
1521 imagic0 = 0;
1522 if (magic[0]) {
1523 magic[1] = get_byte ();
1524 imagic1 = 0; /* avoid lint warning */
1525 } else {
1526 imagic1 = try_byte ();
1527 magic[1] = imagic1;
1530 method = -1; /* unknown yet */
1531 part_nb++; /* number of parts in gzip file */
1532 header_bytes = 0;
1533 last_member = 0;
1534 /* assume multiple members in gzip file except for record oriented I/O */
1536 if (memcmp(magic, GZIP_MAGIC, 2) == 0
1537 || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
1539 method = (int)get_byte();
1540 if (method != DEFLATED) {
1541 fprintf(stderr,
1542 "%s: %s: unknown method %d -- not supported\n",
1543 program_name, ifname, method);
1544 exit_code = ERROR;
1545 return -1;
1547 work = unzip;
1548 flags = (uch)get_byte();
1550 if ((flags & ENCRYPTED) != 0) {
1551 fprintf(stderr,
1552 "%s: %s is encrypted -- not supported\n",
1553 program_name, ifname);
1554 exit_code = ERROR;
1555 return -1;
1557 if ((flags & RESERVED) != 0) {
1558 fprintf(stderr,
1559 "%s: %s has flags 0x%x -- not supported\n",
1560 program_name, ifname, flags);
1561 exit_code = ERROR;
1562 if (force <= 1) return -1;
1564 stamp = (ulg)get_byte();
1565 stamp |= ((ulg)get_byte()) << 8;
1566 stamp |= ((ulg)get_byte()) << 16;
1567 stamp |= ((ulg)get_byte()) << 24;
1568 if (stamp != 0 && !no_time)
1570 if (stamp <= TYPE_MAXIMUM (time_t))
1572 time_stamp.tv_sec = stamp;
1573 time_stamp.tv_nsec = 0;
1575 else
1577 WARN ((stderr,
1578 "%s: %s: MTIME %lu out of range for this platform\n",
1579 program_name, ifname, stamp));
1580 time_stamp.tv_sec = TYPE_MAXIMUM (time_t);
1581 time_stamp.tv_nsec = TIMESPEC_RESOLUTION - 1;
1585 magic[8] = get_byte (); /* Ignore extra flags. */
1586 magic[9] = get_byte (); /* Ignore OS type. */
1588 if (flags & HEADER_CRC)
1590 magic[2] = DEFLATED;
1591 magic[3] = flags;
1592 magic[4] = stamp & 0xff;
1593 magic[5] = (stamp >> 8) & 0xff;
1594 magic[6] = (stamp >> 16) & 0xff;
1595 magic[7] = stamp >> 24;
1596 updcrc (NULL, 0);
1597 updcrc (magic, 10);
1600 if ((flags & EXTRA_FIELD) != 0) {
1601 uch lenbuf[2];
1602 unsigned int len = lenbuf[0] = get_byte ();
1603 len |= (lenbuf[1] = get_byte ()) << 8;
1604 if (verbose) {
1605 fprintf(stderr,"%s: %s: extra field of %u bytes ignored\n",
1606 program_name, ifname, len);
1608 if (flags & HEADER_CRC)
1609 updcrc (lenbuf, 2);
1610 discard_input_bytes (len, flags);
1613 /* Get original file name if it was truncated */
1614 if ((flags & ORIG_NAME) != 0) {
1615 if (no_name || (to_stdout && !list) || part_nb > 1) {
1616 /* Discard the old name */
1617 discard_input_bytes (-1, flags);
1618 } else {
1619 /* Copy the base name. Keep a directory prefix intact. */
1620 char *p = gzip_base_name (ofname);
1621 char *base = p;
1622 for (;;) {
1623 *p = (char) get_byte ();
1624 if (*p++ == '\0') break;
1625 if (p >= ofname+sizeof(ofname)) {
1626 gzip_error ("corrupted input -- file name too large");
1629 if (flags & HEADER_CRC)
1630 updcrc ((uch *) base, p - base);
1631 p = gzip_base_name (base);
1632 memmove (base, p, strlen (p) + 1);
1633 /* If necessary, adapt the name to local OS conventions: */
1634 if (!list) {
1635 MAKE_LEGAL_NAME(base);
1636 if (base) list=0; /* avoid warning about unused variable */
1638 } /* no_name || to_stdout */
1639 } /* ORIG_NAME */
1641 /* Discard file comment if any */
1642 if ((flags & COMMENT) != 0) {
1643 discard_input_bytes (-1, flags);
1646 if (flags & HEADER_CRC)
1648 unsigned int crc16 = updcrc (magic, 0) & 0xffff;
1649 unsigned int header16 = get_byte ();
1650 header16 |= ((unsigned int) get_byte ()) << 8;
1651 if (header16 != crc16)
1653 fprintf (stderr,
1654 "%s: %s: header checksum 0x%04x != computed checksum 0x%04x\n",
1655 program_name, ifname, header16, crc16);
1656 exit_code = ERROR;
1657 if (force <= 1)
1658 return -1;
1662 if (part_nb == 1) {
1663 header_bytes = inptr + 2*4; /* include crc and size */
1666 } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
1667 && memcmp((char*)inbuf, PKZIP_MAGIC, 4) == 0) {
1668 /* To simplify the code, we support a zip file when alone only.
1669 * We are thus guaranteed that the entire local header fits in inbuf.
1671 inptr = 0;
1672 work = unzip;
1673 if (check_zipfile(in) != OK) return -1;
1674 /* check_zipfile may get ofname from the local header */
1675 last_member = 1;
1677 } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
1678 work = unpack;
1679 method = PACKED;
1681 } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {
1682 work = unlzw;
1683 method = COMPRESSED;
1684 last_member = 1;
1686 } else if (memcmp(magic, LZH_MAGIC, 2) == 0) {
1687 work = unlzh;
1688 method = LZHED;
1689 last_member = 1;
1691 } else if (force && to_stdout && !list) { /* pass input unchanged */
1692 method = STORED;
1693 work = copy;
1694 if (imagic1 != EOF)
1695 inptr--;
1696 last_member = 1;
1697 if (imagic0 != EOF) {
1698 write_buf (STDOUT_FILENO, magic, 1);
1699 bytes_out++;
1702 if (method >= 0) return method;
1704 if (part_nb == 1) {
1705 fprintf (stderr, "\n%s: %s: not in gzip format\n",
1706 program_name, ifname);
1707 exit_code = ERROR;
1708 return -1;
1709 } else {
1710 if (magic[0] == 0)
1712 int inbyte;
1713 for (inbyte = imagic1; inbyte == 0; inbyte = try_byte ())
1714 continue;
1715 if (inbyte == EOF)
1717 if (verbose)
1718 WARN ((stderr, "\n%s: %s: decompression OK, trailing zero bytes ignored\n",
1719 program_name, ifname));
1720 return -3;
1724 WARN((stderr, "\n%s: %s: decompression OK, trailing garbage ignored\n",
1725 program_name, ifname));
1726 return -2;
1730 /* ========================================================================
1731 * Display the characteristics of the compressed file.
1732 * If the given method is < 0, display the accumulated totals.
1733 * IN assertions: time_stamp, header_bytes and ifile_size are initialized.
1735 local void do_list(ifd, method)
1736 int ifd; /* input file descriptor */
1737 int method; /* compression method */
1739 ulg crc; /* original crc */
1740 static int first_time = 1;
1741 static char const *const methods[MAX_METHODS] = {
1742 "store", /* 0 */
1743 "compr", /* 1 */
1744 "pack ", /* 2 */
1745 "lzh ", /* 3 */
1746 "", "", "", "", /* 4 to 7 reserved */
1747 "defla"}; /* 8 */
1748 int positive_off_t_width = INT_STRLEN_BOUND (off_t) - 1;
1750 if (first_time && method >= 0) {
1751 first_time = 0;
1752 if (verbose) {
1753 printf("method crc date time ");
1755 if (!quiet) {
1756 printf("%*.*s %*.*s ratio uncompressed_name\n",
1757 positive_off_t_width, positive_off_t_width, "compressed",
1758 positive_off_t_width, positive_off_t_width, "uncompressed");
1760 } else if (method < 0) {
1761 if (total_in <= 0 || total_out <= 0) return;
1762 if (verbose) {
1763 printf(" ");
1765 if (verbose || !quiet) {
1766 fprint_off(stdout, total_in, positive_off_t_width);
1767 printf(" ");
1768 fprint_off(stdout, total_out, positive_off_t_width);
1769 printf(" ");
1771 display_ratio(total_out-(total_in-header_bytes), total_out, stdout);
1772 /* header_bytes is not meaningful but used to ensure the same
1773 * ratio if there is a single file.
1775 printf(" (totals)\n");
1776 return;
1778 crc = (ulg)~0; /* unknown */
1779 bytes_out = -1L;
1780 bytes_in = ifile_size;
1782 if (method == DEFLATED && !last_member) {
1783 /* Get the crc and uncompressed size for gzip'ed (not zip'ed) files.
1784 * If the lseek fails, we could use read() to get to the end, but
1785 * --list is used to get quick results.
1786 * Use "gunzip < foo.gz | wc -c" to get the uncompressed size if
1787 * you are not concerned about speed.
1789 bytes_in = lseek(ifd, (off_t)(-8), SEEK_END);
1790 if (bytes_in != -1L) {
1791 uch buf[8];
1792 bytes_in += 8L;
1793 if (read(ifd, (char*)buf, sizeof(buf)) != sizeof(buf)) {
1794 read_error();
1796 crc = LG(buf);
1797 bytes_out = LG(buf+4);
1801 if (verbose)
1803 static char const month_abbr[][4]
1804 = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1805 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
1806 struct tm *tm = localtime (&time_stamp.tv_sec);
1807 printf ("%5s %08lx ", methods[method], crc);
1808 if (tm)
1809 printf ("%s%3d %02d:%02d ", month_abbr[tm->tm_mon],
1810 tm->tm_mday, tm->tm_hour, tm->tm_min);
1811 else
1812 printf ("??? ?? ??:?? ");
1814 fprint_off(stdout, bytes_in, positive_off_t_width);
1815 printf(" ");
1816 fprint_off(stdout, bytes_out, positive_off_t_width);
1817 printf(" ");
1818 if (bytes_in == -1L) {
1819 total_in = -1L;
1820 bytes_in = bytes_out = header_bytes = 0;
1821 } else if (total_in >= 0) {
1822 total_in += bytes_in;
1824 if (bytes_out == -1L) {
1825 total_out = -1L;
1826 bytes_in = bytes_out = header_bytes = 0;
1827 } else if (total_out >= 0) {
1828 total_out += bytes_out;
1830 display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out, stdout);
1831 printf(" %s\n", ofname);
1834 /* ========================================================================
1835 * Shorten the given name by one character, or replace a .tar extension
1836 * with .tgz. Truncate the last part of the name which is longer than
1837 * MIN_PART characters: 1234.678.012.gz -> 123.678.012.gz. If the name
1838 * has only parts shorter than MIN_PART truncate the longest part.
1839 * For decompression, just remove the last character of the name.
1841 * IN assertion: for compression, the suffix of the given name is z_suffix.
1843 local void shorten_name(name)
1844 char *name;
1846 int len; /* length of name without z_suffix */
1847 char *trunc = NULL; /* character to be truncated */
1848 int plen; /* current part length */
1849 int min_part = MIN_PART; /* current minimum part length */
1850 char *p;
1852 len = strlen(name);
1853 if (decompress) {
1854 if (len <= 1)
1855 gzip_error ("name too short");
1856 name[len-1] = '\0';
1857 return;
1859 p = get_suffix(name);
1860 if (! p)
1861 gzip_error ("can't recover suffix\n");
1862 *p = '\0';
1863 save_orig_name = 1;
1865 /* compress 1234567890.tar to 1234567890.tgz */
1866 if (len > 4 && strequ(p-4, ".tar")) {
1867 strcpy(p-4, ".tgz");
1868 return;
1870 /* Try keeping short extensions intact:
1871 * 1234.678.012.gz -> 123.678.012.gz
1873 do {
1874 p = last_component (name);
1875 while (*p) {
1876 plen = strcspn(p, PART_SEP);
1877 p += plen;
1878 if (plen > min_part) trunc = p-1;
1879 if (*p) p++;
1881 } while (trunc == NULL && --min_part != 0);
1883 if (trunc != NULL) {
1884 do {
1885 trunc[0] = trunc[1];
1886 } while (*trunc++);
1887 trunc--;
1888 } else {
1889 trunc = strrchr(name, PART_SEP[0]);
1890 if (!trunc)
1891 gzip_error ("internal error in shorten_name");
1892 if (trunc[1] == '\0') trunc--; /* force truncation */
1894 strcpy(trunc, z_suffix);
1897 /* ========================================================================
1898 * The compressed file already exists, so ask for confirmation.
1899 * Return ERROR if the file must be skipped.
1901 local int check_ofname()
1903 /* Ask permission to overwrite the existing file */
1904 if (!force) {
1905 int ok = 0;
1906 fprintf (stderr, "%s: %s already exists;", program_name, ofname);
1907 if (foreground && (presume_input_tty || isatty (STDIN_FILENO))) {
1908 fprintf(stderr, " do you wish to overwrite (y or n)? ");
1909 fflush(stderr);
1910 ok = yesno();
1912 if (!ok) {
1913 fprintf(stderr, "\tnot overwritten\n");
1914 if (exit_code == OK) exit_code = WARNING;
1915 return ERROR;
1918 if (xunlink (ofname)) {
1919 progerror(ofname);
1920 return ERROR;
1922 return OK;
1925 /* Change the owner and group of a file. FD is a file descriptor for
1926 the file and NAME its name. Change it to user UID and to group GID.
1927 If UID or GID is -1, though, do not change the corresponding user
1928 or group. */
1929 #if ! (HAVE_FCHOWN || HAVE_CHOWN)
1930 /* The types uid_t and gid_t do not exist on mingw, so don't assume them. */
1931 # define do_chown(fd, name, uid, gid) ((void) 0)
1932 #else
1933 static void
1934 do_chown (int fd, char const *name, uid_t uid, gid_t gid)
1936 # if HAVE_FCHOWN
1937 ignore_value (fchown (fd, uid, gid));
1938 # else
1939 ignore_value (chown (name, uid, gid));
1940 # endif
1942 #endif
1944 /* ========================================================================
1945 * Copy modes, times, ownership from input file to output file.
1946 * IN assertion: to_stdout is false.
1948 local void copy_stat(ifstat)
1949 struct stat *ifstat;
1951 mode_t mode = ifstat->st_mode & S_IRWXUGO;
1952 int r;
1954 #ifndef NO_UTIME
1955 bool restoring;
1956 struct timespec timespec[2];
1957 timespec[0] = get_stat_atime (ifstat);
1958 timespec[1] = get_stat_mtime (ifstat);
1959 restoring = (decompress && 0 <= time_stamp.tv_nsec
1960 && ! (timespec[1].tv_sec == time_stamp.tv_sec
1961 && timespec[1].tv_nsec == time_stamp.tv_nsec));
1962 if (restoring)
1963 timespec[1] = time_stamp;
1965 if (fdutimens (ofd, ofname, timespec) == 0)
1967 if (restoring && 1 < verbose) {
1968 fprintf(stderr, "%s: timestamp restored\n", ofname);
1971 else
1973 int e = errno;
1974 WARN ((stderr, "%s: ", program_name));
1975 if (!quiet)
1977 errno = e;
1978 perror (ofname);
1981 #endif
1983 /* Change the group first, then the permissions, then the owner.
1984 That way, the permissions will be correct on systems that allow
1985 users to give away files, without introducing a security hole.
1986 Security depends on permissions not containing the setuid or
1987 setgid bits. */
1989 do_chown (ofd, ofname, -1, ifstat->st_gid);
1991 #if HAVE_FCHMOD
1992 r = fchmod (ofd, mode);
1993 #else
1994 r = chmod (ofname, mode);
1995 #endif
1996 if (r != 0) {
1997 int e = errno;
1998 WARN ((stderr, "%s: ", program_name));
1999 if (!quiet) {
2000 errno = e;
2001 perror(ofname);
2005 do_chown (ofd, ofname, ifstat->st_uid, -1);
2008 #if ! NO_DIR
2010 /* ========================================================================
2011 * Recurse through the given directory.
2013 local void treat_dir (fd, dir)
2014 int fd;
2015 char *dir;
2017 DIR *dirp;
2018 char nbuf[MAX_PATH_LEN];
2019 char *entries;
2020 char const *entry;
2021 size_t entrylen;
2023 dirp = fdopendir (fd);
2025 if (dirp == NULL) {
2026 progerror(dir);
2027 close (fd);
2028 return ;
2031 entries = streamsavedir (dirp, SAVEDIR_SORT_NONE);
2032 if (! entries)
2033 progerror (dir);
2034 if (closedir (dirp) != 0)
2035 progerror (dir);
2036 if (! entries)
2037 return;
2039 for (entry = entries; *entry; entry += entrylen + 1) {
2040 size_t len = strlen (dir);
2041 entrylen = strlen (entry);
2042 if (strequ (entry, ".") || strequ (entry, ".."))
2043 continue;
2044 if (len + entrylen < MAX_PATH_LEN - 2) {
2045 strcpy(nbuf,dir);
2046 if (*last_component (nbuf) && !ISSLASH (nbuf[len - 1]))
2047 nbuf[len++] = '/';
2048 strcpy (nbuf + len, entry);
2049 treat_file(nbuf);
2050 } else {
2051 fprintf(stderr,"%s: %s/%s: pathname too long\n",
2052 program_name, dir, entry);
2053 exit_code = ERROR;
2056 free (entries);
2058 #endif /* ! NO_DIR */
2060 /* Make sure signals get handled properly. */
2062 static void
2063 install_signal_handlers ()
2065 int nsigs = sizeof handled_sig / sizeof handled_sig[0];
2066 int i;
2067 struct sigaction act;
2069 sigemptyset (&caught_signals);
2070 for (i = 0; i < nsigs; i++)
2072 sigaction (handled_sig[i], NULL, &act);
2073 if (act.sa_handler != SIG_IGN)
2074 sigaddset (&caught_signals, handled_sig[i]);
2077 act.sa_handler = abort_gzip_signal;
2078 act.sa_mask = caught_signals;
2079 act.sa_flags = 0;
2081 for (i = 0; i < nsigs; i++)
2082 if (sigismember (&caught_signals, handled_sig[i]))
2084 if (i == 0)
2085 foreground = 1;
2086 sigaction (handled_sig[i], &act, NULL);
2090 /* ========================================================================
2091 * Free all dynamically allocated variables and exit with the given code.
2093 local void do_exit(exitcode)
2094 int exitcode;
2096 static int in_exit = 0;
2098 if (in_exit) exit(exitcode);
2099 in_exit = 1;
2100 free(env);
2101 env = NULL;
2102 FREE(inbuf);
2103 FREE(outbuf);
2104 FREE(d_buf);
2105 FREE(window);
2106 #ifndef MAXSEG_64K
2107 FREE(tab_prefix);
2108 #else
2109 FREE(tab_prefix0);
2110 FREE(tab_prefix1);
2111 #endif
2112 exit(exitcode);
2115 static void
2116 finish_out (void)
2118 if (fclose (stdout) != 0)
2119 write_error ();
2120 do_exit (OK);
2123 /* ========================================================================
2124 * Close and unlink the output file.
2126 static void
2127 remove_output_file (bool signals_already_blocked)
2129 int fd;
2130 sigset_t oldset;
2132 if (!signals_already_blocked)
2133 sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
2134 fd = remove_ofname_fd;
2135 if (0 <= fd)
2137 char fname[MAX_PATH_LEN];
2138 remove_ofname_fd = -1;
2139 close (fd);
2140 volatile_strcpy (fname, remove_ofname);
2141 xunlink (fname);
2143 if (!signals_already_blocked)
2144 sigprocmask (SIG_SETMASK, &oldset, NULL);
2147 /* ========================================================================
2148 * Error handler.
2150 void
2151 abort_gzip (void)
2153 remove_output_file (false);
2154 do_exit(ERROR);
2157 /* ========================================================================
2158 * Signal handler.
2160 static void
2161 abort_gzip_signal (int sig)
2163 remove_output_file (true);
2164 if (sig == exiting_signal)
2165 _exit (WARNING);
2166 signal (sig, SIG_DFL);
2167 raise (sig);