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