1 /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
3 Copyright (C) 1999, 2001-2002, 2006-2007, 2009-2024 Free Software
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)
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, see <https://www.gnu.org/licenses/>. */
21 * The unzip code was written and put in the public domain by Mark Adler.
22 * Portions of the lzw code are derived from the public domain 'compress'
23 * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
24 * Ken Turkowski, Dave Mack and Peter Jannesen.
26 * See the license_msg below and the file COPYING for the software license.
27 * See the file algorithm.doc for the compression algorithms and file formats.
30 static char const *const license_msg
[] = {
31 "Copyright (C) 2024 Free Software Foundation, Inc.",
32 "Copyright (C) 1993 Jean-loup Gailly.",
33 "This is free software. You may redistribute copies of it under the terms of",
34 "the GNU General Public License <https://www.gnu.org/licenses/gpl.html>.",
35 "There is NO WARRANTY, to the extent permitted by law.",
38 /* Compress files with zip algorithm and 'compress' interface.
39 * See help() function below for all options.
41 * file.gz: compressed file with same mode, owner, and utimes
42 * or stdout with -c option or if stdin used as input.
43 * If the output file name had to be truncated, the original name is kept
44 * in the compressed file.
45 * On MSDOS, file.tmp -> file.tmz.
47 * Using gz on MSDOS would create too many file name conflicts. For
48 * example, foo.txt -> foo.tgz (.tgz must be reserved as shorthand for
49 * tar.gz). Similarly, foo.dir and foo.doc would both be mapped to foo.dgz.
50 * I also considered 12345678.txt -> 12345txt.gz but this truncates the name
51 * too heavily. There is no ideal solution given the MSDOS 8+3 limitation.
53 * For the meaning of all compilation flags, see comments in Makefile.in.
58 #include <sys/types.h>
75 #include "ignore-value.h"
76 #include "stat-time.h"
101 # define MAX_PATH_LEN 1024 /* max pathname length */
109 off_t
lseek (int fd
, off_t offset
, int whence
);
112 #ifndef HAVE_WORKING_O_NOFOLLOW
113 # define HAVE_WORKING_O_NOFOLLOW 0
116 /* Separator for file name parts (see shorten_name()) */
117 #ifdef NO_MULTIPLE_DOTS
118 # define PART_SEP "-"
120 # define PART_SEP "."
125 /* With IBM_Z_DFLTCC, DEFLATE COMPRESSION works faster with
126 page-aligned input and output buffers, and requires page-aligned
127 windows; the alignment requirement is 4096. On other platforms
128 alignment doesn't hurt, and alignment up to 4096 is portable so
130 #if defined HAVE_C_ALIGNASOF || defined alignas
131 # define BUFFER_ALIGNED alignas (4096)
133 # define BUFFER_ALIGNED /**/
135 DECLARE(uch BUFFER_ALIGNED
, inbuf
, INBUFSIZ
+INBUF_EXTRA
);
136 DECLARE(uch BUFFER_ALIGNED
, outbuf
, OUTBUFSIZ
+OUTBUF_EXTRA
);
137 DECLARE(ush
, d_buf
, DIST_BUFSIZE
);
138 DECLARE(uch BUFFER_ALIGNED
, window
, 2L*WSIZE
);
140 DECLARE(ush
, tab_prefix
, 1L<<BITS
);
142 DECLARE(ush
, tab_prefix0
, 1L<<(BITS
-1));
143 DECLARE(ush
, tab_prefix1
, 1L<<(BITS
-1));
146 /* local variables */
148 /* If true, pretend that standard input is a tty. This option
149 is deliberately not documented, and only for testing. */
150 static bool presume_input_tty
;
152 /* If true, transfer output data to the output file's storage device
153 when supported. Otherwise, if the system crashes around the time
154 gzip is run, the user might lose both input and output data. See:
155 Pillai TS et al. All file systems are not created equal: on the
156 complexity of crafting crash-consistent applications. OSDI'14. 2014:433-48.
157 https://www.usenix.org/conference/osdi14/technical-sessions/presentation/pillai */
158 static bool synchronous
;
160 static int ascii
= 0; /* convert end-of-lines to local OS conventions */
161 int to_stdout
= 0; /* output to stdout (-c) */
162 static int decompress
= 0; /* decompress (-d) */
163 static int force
= 0; /* don't ask questions, compress links (-f) */
164 static int keep
= 0; /* keep (don't delete) input files */
165 static int no_name
= -1; /* don't save or restore the original file name */
166 static int no_time
= -1; /* don't save or restore the original file time */
167 static int recursive
= 0; /* recurse through directories (-r) */
168 static int list
= 0; /* list the file contents (-l) */
172 int verbose
= 0; /* be verbose (-v) */
173 int quiet
= 0; /* be very quiet (-q) */
174 int test
= 0; /* test .gz file integrity */
175 static int foreground
= 0; /* set if program run in foreground */
176 char *program_name
; /* program name */
177 int maxbits
= BITS
; /* max bits per code for LZW */
178 int method
= DEFLATED
;/* compression method */
179 int level
= 6; /* compression level */
180 int exit_code
= OK
; /* program exit code */
181 int save_orig_name
; /* set if original name must be saved */
182 static int last_member
; /* set for .zip and .Z files */
183 static int part_nb
; /* number of parts in .gz file */
184 off_t ifile_size
; /* input file size, -1 for devices (debug only) */
185 static char *env
; /* contents of GZIP env variable */
186 static char const *z_suffix
; /* default suffix (can be set with --suffix) */
187 static size_t z_len
; /* strlen(z_suffix) */
189 /* The original timestamp (modification time). If the original is
190 unknown, TIME_STAMP.tv_nsec is negative. If the original is
191 greater than struct timespec range, TIME_STAMP is the maximal
192 struct timespec value; this can happen on hosts with 32-bit signed
193 time_t because the gzip format's MTIME is 32-bit unsigned.
194 The original cannot be less than struct timespec range. */
195 struct timespec time_stamp
;
197 /* The set of signals that are caught. */
198 static sigset_t caught_signals
;
200 /* If nonnegative, close this file descriptor and unlink remove_ofname
202 static int volatile remove_ofname_fd
= -1;
203 static char volatile remove_ofname
[MAX_PATH_LEN
];
205 static bool stdin_was_read
;
207 off_t bytes_in
; /* number of input bytes */
208 off_t bytes_out
; /* number of output bytes */
209 static off_t total_in
; /* input bytes for all files */
210 static off_t total_out
; /* output bytes for all files */
211 char ifname
[MAX_PATH_LEN
]; /* input file name */
212 char ofname
[MAX_PATH_LEN
]; /* output file name */
213 static char dfname
[MAX_PATH_LEN
]; /* name of dir containing output file */
214 static struct stat istat
; /* status for input file */
215 int ifd
; /* input file descriptor */
216 int ofd
; /* output file descriptor */
217 static int dfd
= -1; /* output directory file descriptor */
218 unsigned insize
; /* valid bytes in inbuf */
219 unsigned inptr
; /* index of next byte to be processed in inbuf */
220 unsigned outcnt
; /* bytes in output buffer */
221 int rsync
= 0; /* make rsyncable chunks */
223 static int handled_sig
[] =
225 /* SIGINT must be first, as 'foreground' depends on it. */
245 /* For long options that have no equivalent short option, use a
246 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
249 PRESUME_INPUT_TTY_OPTION
= CHAR_MAX
+ 1,
253 /* A value greater than all valid long options, used as a flag to
254 distinguish options derived from the GZIP environment variable. */
258 static char const shortopts
[] = "ab:cdfhH?klLmMnNqrS:tvVZ123456789";
260 static const struct option longopts
[] =
262 /* { name has_arg *flag val } */
263 {"ascii", 0, 0, 'a'}, /* ascii text mode */
264 {"to-stdout", 0, 0, 'c'}, /* write output on standard output */
265 {"stdout", 0, 0, 'c'}, /* write output on standard output */
266 {"decompress", 0, 0, 'd'}, /* decompress */
267 {"uncompress", 0, 0, 'd'}, /* decompress */
268 /* {"encrypt", 0, 0, 'e'}, encrypt */
269 {"force", 0, 0, 'f'}, /* force overwrite of output file */
270 {"help", 0, 0, 'h'}, /* give help */
271 /* {"pkzip", 0, 0, 'k'}, force output in pkzip format */
272 {"keep", 0, 0, 'k'}, /* keep (don't delete) input files */
273 {"list", 0, 0, 'l'}, /* list .gz file contents */
274 {"license", 0, 0, 'L'}, /* display software license */
275 {"no-name", 0, 0, 'n'}, /* don't save or restore original name & time */
276 {"name", 0, 0, 'N'}, /* save or restore original name & time */
277 {"-presume-input-tty", no_argument
, NULL
, PRESUME_INPUT_TTY_OPTION
},
278 {"quiet", 0, 0, 'q'}, /* quiet mode */
279 {"silent", 0, 0, 'q'}, /* quiet mode */
280 {"synchronous",0, 0, SYNCHRONOUS_OPTION
},
281 {"recursive", 0, 0, 'r'}, /* recurse through directories */
282 {"suffix", 1, 0, 'S'}, /* use given suffix instead of .gz */
283 {"test", 0, 0, 't'}, /* test compressed file integrity */
284 {"verbose", 0, 0, 'v'}, /* verbose mode */
285 {"version", 0, 0, 'V'}, /* display version number */
286 {"fast", 0, 0, '1'}, /* compress faster */
287 {"best", 0, 0, '9'}, /* compress better */
288 {"lzw", 0, 0, 'Z'}, /* make output compatible with old compress */
289 {"bits", 1, 0, 'b'}, /* max number of bits per code (implies -Z) */
290 {"rsyncable", 0, 0, RSYNCABLE_OPTION
}, /* make rsync-friendly archive */
294 /* local functions */
296 _Noreturn
static void try_help (void);
297 static void help (void);
298 static void license (void);
299 static void version (void);
300 static int input_eof (void);
301 static void treat_stdin (void);
302 static void treat_file (char *iname
);
303 static int create_outfile (void);
304 static char *get_suffix (char *name
);
305 static int open_input_file (char *iname
, struct stat
*sbuf
);
306 static void discard_input_bytes (size_t nbytes
, unsigned int flags
);
307 static int make_ofname (void);
308 static void shorten_name (char *name
);
309 static int get_method (int in
);
310 static void do_list (int method
);
311 static int check_ofname (void);
312 static void copy_stat (struct stat
*ifstat
);
313 static void install_signal_handlers (void);
314 static void remove_output_file (bool);
315 static void abort_gzip_signal (int);
316 _Noreturn
static void do_exit (int exitcode
);
317 static void finish_out (void);
318 int main (int argc
, char **argv
);
319 static int (*work
) (int infile
, int outfile
) = zip
; /* function to call */
322 static void treat_dir (int fd
, char *dir
);
325 #define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
330 fprintf (stderr
, "Try `%s --help' for more information.\n",
335 /* ======================================================================== */
339 static char const* const help_msg
[] = {
340 "Compress or uncompress FILEs (by default, compress FILES in-place).",
342 "Mandatory arguments to long options are mandatory for short options too.",
345 " -a, --ascii ascii text; convert end-of-line using local conventions",
347 " -c, --stdout write on standard output, keep original files unchanged",
348 " -d, --decompress decompress",
349 /* -e, --encrypt encrypt */
350 " -f, --force force overwrite of output file and compress links",
351 " -h, --help give this help",
352 /* -k, --pkzip force output in pkzip format */
353 " -k, --keep keep (don't delete) input files",
354 " -l, --list list compressed file contents",
355 " -L, --license display software license",
357 " -m do not save or restore the original modification time",
358 " -M, --time save or restore the original modification time",
360 " -n, --no-name do not save or restore the original name and timestamp",
361 " -N, --name save or restore the original name and timestamp",
362 " -q, --quiet suppress all warnings",
364 " -r, --recursive operate recursively on directories",
366 " --rsyncable make rsync-friendly archive",
367 " -S, --suffix=SUF use suffix SUF on compressed files",
368 " --synchronous synchronous output (safer if system crashes, but slower)",
369 " -t, --test test compressed file integrity",
370 " -v, --verbose verbose mode",
371 " -V, --version display version number",
372 " -1, --fast compress faster",
373 " -9, --best compress better",
375 "With no FILE, or when FILE is -, read standard input.",
377 "Report bugs to <bug-gzip@gnu.org>.",
379 char const *const *p
= help_msg
;
381 printf ("Usage: %s [OPTION]... [FILE]...\n", program_name
);
382 while (*p
) printf ("%s\n", *p
++);
385 /* ======================================================================== */
389 char const *const *p
= license_msg
;
391 printf ("%s %s\n", program_name
, Version
);
392 while (*p
) printf ("%s\n", *p
++);
395 /* ======================================================================== */
401 printf ("Written by Jean-loup Gailly.\n");
405 progerror (char const *string
)
407 fprintf (stderr
, "%s: %s: %s\n", program_name
, string
, strerror (errno
));
411 /* ======================================================================== */
412 int main (int argc
, char **argv
)
414 int file_count
; /* number of files to process */
415 size_t proglen
; /* length of program_name */
420 EXPAND(argc
, argv
); /* wild card expansion if necessary */
422 program_name
= gzip_base_name (argv
[0]);
423 proglen
= strlen (program_name
);
425 /* Suppress .exe for MSDOS and OS/2: */
426 if (4 < proglen
&& strequ (program_name
+ proglen
- 4, ".exe"))
427 program_name
[proglen
- 4] = '\0';
429 /* Add options in GZIP environment variable if there is one */
431 env
= add_envopt (&env_argc
, &argv_copy
, OPTIONS_VAR
);
432 env_argv
= env
? argv_copy
: NULL
;
435 # define GNU_STANDARD 1
438 /* For compatibility with old compress, use program name as an option.
439 * Unless you compile with -DGNU_STANDARD=0, this program will behave as
440 * gzip even if it is invoked under the name gunzip or zcat.
442 * Systems which do not support links can still use -d or -dc.
443 * Ignore an .exe extension for MSDOS and OS/2.
445 if (strncmp (program_name
, "un", 2) == 0 /* ungzip, uncompress */
446 || strncmp (program_name
, "gun", 3) == 0) /* gunzip */
448 else if (strequ (program_name
+ 1, "cat") /* zcat, pcat, gcat */
449 || strequ (program_name
, "gzcat")) /* gzcat */
450 decompress
= to_stdout
= 1;
454 z_len
= strlen(z_suffix
);
462 if (env_argv
[optind
] && strequ (env_argv
[optind
], "--"))
463 optc
= ENV_OPTION
+ '-';
466 optc
= getopt_long (env_argc
, env_argv
, shortopts
, longopts
,
472 if (optind
!= env_argc
)
475 ("%s: %s: non-option in "OPTIONS_VAR
476 " environment variable\n"),
477 program_name
, env_argv
[optind
]);
481 /* Wait until here before warning, so that GZIP='-q'
483 if (env_argc
!= 1 && !quiet
)
485 ("%s: warning: "OPTIONS_VAR
" environment variable"
486 " is deprecated; use an alias or script\n"),
489 /* Start processing ARGC and ARGV instead. */
499 optc
= getopt_long (argc
, argv
, shortopts
, longopts
, &longind
);
507 maxbits
= atoi(optarg
);
508 for (; *optarg
; optarg
++)
509 if (! ('0' <= *optarg
&& *optarg
<= '9'))
511 fprintf (stderr
, "%s: -b operand is not an integer\n",
517 to_stdout
= 1; break;
519 decompress
= 1; break;
523 help (); finish_out (); break;
527 list
= decompress
= test
= to_stdout
= 1; break;
529 license (); finish_out (); break;
530 case 'm': /* undocumented, may change later */
532 case 'M': /* undocumented, may change later */
535 case 'n' + ENV_OPTION
:
536 no_name
= no_time
= 1; break;
538 case 'N' + ENV_OPTION
:
539 no_name
= no_time
= 0; break;
540 case PRESUME_INPUT_TTY_OPTION
:
541 presume_input_tty
= true; break;
543 case 'q' + ENV_OPTION
:
544 quiet
= 1; verbose
= 0; break;
547 fprintf (stderr
, "%s: -r not supported on this system\n",
555 case RSYNCABLE_OPTION
:
556 case RSYNCABLE_OPTION
+ ENV_OPTION
:
560 #ifdef NO_MULTIPLE_DOTS
561 if (*optarg
== '.') optarg
++;
563 for (z_len
= 0; optarg
[z_len
]; z_len
++)
564 if (optarg
[z_len
] == '/')
566 fprintf (stderr
, "%s: suffix contains '/'\n", program_name
);
571 case SYNCHRONOUS_OPTION
:
575 test
= decompress
= to_stdout
= 1;
578 case 'v' + ENV_OPTION
:
579 verbose
++; quiet
= 0; break;
581 version (); finish_out (); break;
583 fprintf(stderr
, "%s: -Z not supported in this version\n",
587 case '1' + ENV_OPTION
: case '2' + ENV_OPTION
: case '3' + ENV_OPTION
:
588 case '4' + ENV_OPTION
: case '5' + ENV_OPTION
: case '6' + ENV_OPTION
:
589 case '7' + ENV_OPTION
: case '8' + ENV_OPTION
: case '9' + ENV_OPTION
:
592 case '1': case '2': case '3': case '4':
593 case '5': case '6': case '7': case '8': case '9':
598 if (ENV_OPTION
<= optc
&& optc
!= ENV_OPTION
+ '?')
600 /* Output a diagnostic, since getopt_long didn't. */
601 fprintf (stderr
, "%s: ", program_name
);
603 fprintf (stderr
, "-%c: ", optc
- ENV_OPTION
);
605 fprintf (stderr
, "--%s: ", longopts
[longind
].name
);
606 fprintf (stderr
, ("option not valid in "OPTIONS_VAR
607 " environment variable\n"));
611 } /* loop on all arguments */
613 /* By default, save name and timestamp on compression but do not
614 * restore them on decompression.
616 if (no_time
< 0) no_time
= decompress
;
617 if (no_name
< 0) no_name
= decompress
;
619 file_count
= argc
- optind
;
623 if (ascii
&& !quiet
) {
624 fprintf(stderr
, "%s: option --ascii ignored on this system\n",
628 if (z_len
== 0 || z_len
> MAX_SUFFIX
) {
629 fprintf(stderr
, "%s: invalid suffix '%s'\n", program_name
, z_suffix
);
633 /* Allocate all global buffers (for DYN_ALLOC option) */
634 ALLOC(uch
, inbuf
, INBUFSIZ
+INBUF_EXTRA
);
635 ALLOC(uch
, outbuf
, OUTBUFSIZ
+OUTBUF_EXTRA
);
636 ALLOC(ush
, d_buf
, DIST_BUFSIZE
);
637 ALLOC(uch
, window
, 2L*WSIZE
);
639 ALLOC(ush
, tab_prefix
, 1L<<BITS
);
641 ALLOC(ush
, tab_prefix0
, 1L<<(BITS
-1));
642 ALLOC(ush
, tab_prefix1
, 1L<<(BITS
-1));
645 /* And get to work */
646 if (file_count
!= 0) {
647 if (to_stdout
&& !test
&& (!decompress
|| !ascii
)) {
648 SET_BINARY_MODE (STDOUT_FILENO
);
650 while (optind
< argc
) {
651 treat_file(argv
[optind
++]);
653 } else { /* Standard input */
656 if (stdin_was_read
&& close (STDIN_FILENO
) != 0)
658 strcpy (ifname
, "stdin");
663 /* Output any totals, and check for output errors. */
664 if (!quiet
&& 1 < file_count
)
666 if (fflush (stdout
) != 0)
671 && fdatasync (STDOUT_FILENO
) != 0 && errno
!= EINVAL
)
672 || close (STDOUT_FILENO
) != 0)
678 /* Return nonzero when at end of file on input. */
682 if (!decompress
|| last_member
)
687 if (insize
!= INBUFSIZ
|| fill_inbuf (1) == EOF
)
690 /* Unget the char that fill_inbuf got. */
698 get_input_size_and_time (void)
701 time_stamp
.tv_nsec
= -1;
703 /* Record the input file's size and timestamp only if it is a
704 regular file. Doing this for the timestamp helps to keep gzip's
705 output more reproducible when it is used as part of a
708 if (S_ISREG (istat
.st_mode
))
710 ifile_size
= istat
.st_size
;
711 if (!no_time
|| list
)
712 time_stamp
= get_stat_mtime (&istat
);
716 /* ========================================================================
717 * Compress or decompress stdin
723 && (presume_input_tty
724 || isatty (decompress
? STDIN_FILENO
: STDOUT_FILENO
))) {
725 /* Do not send compressed data to the terminal or read it from
726 * the terminal. We get here when user invoked the program
727 * without parameters, so be helpful. According to the GNU standards:
729 * If there is one behavior you think is most useful when the output
730 * is to a terminal, and another that you think is most useful when
731 * the output is a file or a pipe, then it is usually best to make
732 * the default behavior the one that is useful with output to a
733 * terminal, and have an option for the other behavior.
735 * Here we use the --force option to get the other behavior.
739 ("%s: compressed data not %s a terminal."
740 " Use -f to force %scompression.\n"
741 "For help, type: %s -h\n"),
743 decompress
? "read from" : "written to",
744 decompress
? "de" : "",
749 if (decompress
|| !ascii
) {
750 SET_BINARY_MODE (STDIN_FILENO
);
752 if (!test
&& (!decompress
|| !ascii
)) {
753 SET_BINARY_MODE (STDOUT_FILENO
);
755 strcpy(ifname
, "stdin");
756 strcpy(ofname
, "stdout");
758 /* Get the file's timestamp and size. */
759 if (fstat (STDIN_FILENO
, &istat
) != 0)
761 progerror ("standard input");
765 get_input_size_and_time ();
767 clear_bufs(); /* clear input and output buffers */
771 stdin_was_read
= true;
774 method
= get_method(ifd
);
776 do_exit(exit_code
); /* error message already emitted */
780 /* Actually do the compression/decompression. Loop over zipped members.
783 if (work (STDIN_FILENO
, STDOUT_FILENO
) != OK
)
789 method
= get_method(ifd
);
790 if (method
< 0) return; /* error message already emitted */
801 fprintf(stderr
, " OK\n");
803 } else if (!decompress
) {
804 display_ratio(bytes_in
-(bytes_out
-header_bytes
), bytes_in
, stderr
);
805 fprintf(stderr
, "\n");
806 #ifdef DISPLAY_STDIN_RATIO
808 display_ratio(bytes_out
-(bytes_in
-header_bytes
), bytes_out
,stderr
);
809 fprintf(stderr
, "\n");
815 static char const dot
= '.';
817 /* True if the cached directory for calls to openat etc. is DIR, with
818 length DIRLEN. DIR need not be null-terminated. DIRLEN must be
819 less than MAX_PATH_LEN. */
821 atdir_eq (char const *dir
, ptrdiff_t dirlen
)
824 dir
= &dot
, dirlen
= 1;
825 return memcmp (dfname
, dir
, dirlen
) == 0 && !dfname
[dirlen
];
828 /* Set the directory used for calls to openat etc. to be the directory
829 DIR, with length DIRLEN. DIR need not be null-terminated.
830 DIRLEN must be less than MAX_PATH_LEN. Return a file descriptor for
831 the directory, or -1 if one could not be obtained. */
833 atdir_set (char const *dir
, ptrdiff_t dirlen
)
835 /* Don't bother opening directories on older systems that
836 lack openat and unlinkat. It's not worth the porting hassle. */
837 #if HAVE_OPENAT && HAVE_UNLINKAT
838 enum { try_opening_directories
= true };
840 enum { try_opening_directories
= false };
843 if (try_opening_directories
&& ! atdir_eq (dir
, dirlen
))
848 dir
= &dot
, dirlen
= 1;
849 memcpy (dfname
, dir
, dirlen
);
850 dfname
[dirlen
] = '\0';
851 dfd
= open (dfname
, O_SEARCH
| O_DIRECTORY
);
857 /* ========================================================================
858 * Compress or decompress the given file
861 treat_file (char *iname
)
863 /* Accept "-" as synonym for stdin */
864 if (strequ(iname
, "-")) {
865 int cflag
= to_stdout
;
871 /* Check if the input file is present, set ifname and istat: */
872 ifd
= open_input_file (iname
, &istat
);
876 /* If the input name is that of a directory, recurse or ignore: */
877 if (S_ISDIR(istat
.st_mode
)) {
880 treat_dir (ifd
, iname
);
881 /* Warning: ifname is now garbage */
886 WARN ((stderr
, "%s: %s is a directory -- ignored\n",
887 program_name
, ifname
));
893 if (! S_ISREG (istat
.st_mode
))
896 "%s: %s is not a directory or a regular file - ignored\n",
897 program_name
, ifname
));
901 if (istat
.st_mode
& S_ISUID
)
903 WARN ((stderr
, "%s: %s is set-user-ID on execution - ignored\n",
904 program_name
, ifname
));
908 if (istat
.st_mode
& S_ISGID
)
910 WARN ((stderr
, "%s: %s is set-group-ID on execution - ignored\n",
911 program_name
, ifname
));
918 if (istat
.st_mode
& S_ISVTX
)
921 "%s: %s has the sticky bit set - file ignored\n",
922 program_name
, ifname
));
926 if (2 <= istat
.st_nlink
)
928 WARN ((stderr
, "%s: %s has %lu other link%s -- file ignored\n",
929 program_name
, ifname
,
930 (unsigned long int) istat
.st_nlink
- 1,
931 istat
.st_nlink
== 2 ? "" : "s"));
938 get_input_size_and_time ();
940 /* Generate output file name. For -r and (-t or -l), skip files
941 * without a valid gzip suffix (check done in make_ofname).
943 if (to_stdout
&& !test
) {
944 strcpy(ofname
, "stdout");
946 } else if (make_ofname() != OK
) {
951 clear_bufs(); /* clear input and output buffers */
955 method
= get_method(ifd
); /* updates ofname if original given */
958 return; /* error message already emitted */
962 /* If compressing to a file, check if ofname is not ambiguous
963 * because the operating system truncates names. Otherwise, generate
964 * a new ofname and save the original name in the compressed file.
968 /* Keep remove_ofname_fd negative. */
970 if (create_outfile() != OK
) return;
972 if (!decompress
&& save_orig_name
&& !verbose
&& !quiet
) {
973 fprintf(stderr
, "%s: %s compressed to %s\n",
974 program_name
, ifname
, ofname
);
977 /* Keep the name even if not truncated except with --no-name: */
978 if (!save_orig_name
) save_orig_name
= !no_name
;
980 if (verbose
&& !list
) {
981 fprintf(stderr
, "%s:\t", ifname
);
984 /* Actually do the compression/decompression. Loop over zipped members.
987 if ((*work
)(ifd
, ofd
) != OK
) {
988 method
= -1; /* force cleanup */
995 method
= get_method(ifd
);
996 if (method
< 0) break; /* error message already emitted */
999 if (close (ifd
) != 0)
1013 && ((0 <= dfd
&& fdatasync (dfd
) != 0 && errno
!= EINVAL
)
1014 || (fsync (ofd
) != 0 && errno
!= EINVAL
)))
1015 || close (ofd
) != 0)
1022 char *ifbase
= last_component (ifname
);
1023 int ufd
= atdir_eq (ifname
, ifbase
- ifname
) ? dfd
: -1;
1026 sigprocmask (SIG_BLOCK
, &caught_signals
, &oldset
);
1027 remove_ofname_fd
= -1;
1028 res
= ufd
< 0 ? xunlink (ifname
) : unlinkat (ufd
, ifbase
, 0);
1029 unlink_errno
= res
== 0 ? 0 : errno
;
1030 sigprocmask (SIG_SETMASK
, &oldset
, NULL
);
1033 WARN ((stderr
, "%s: %s: %s\n", program_name
, ifname
,
1034 strerror (unlink_errno
)));
1040 remove_output_file (false);
1044 /* Display statistics */
1047 fprintf(stderr
, " OK");
1048 } else if (decompress
) {
1049 display_ratio(bytes_out
-(bytes_in
-header_bytes
), bytes_out
,stderr
);
1051 display_ratio(bytes_in
-(bytes_out
-header_bytes
), bytes_in
, stderr
);
1054 fprintf(stderr
, " -- %s %s", keep
? "created" : "replaced with",
1056 fprintf(stderr
, "\n");
1061 volatile_strcpy (char volatile *dst
, char const volatile *src
)
1063 while ((*dst
++ = *src
++))
1067 /* ========================================================================
1068 * Create the output file. Return OK or ERROR.
1069 * Try several times if necessary to avoid truncating the z_suffix. For
1070 * example, do not create a compressed file of name "1234567890123."
1071 * Sets save_orig_name to true if the file name has been truncated.
1072 * IN assertions: the input file has already been open (ifd is set) and
1073 * ofname has already been updated if there was an original name.
1074 * OUT assertions: ifd and ofd are closed in case of error.
1079 static bool signal_handlers_installed
;
1080 int name_shortened
= 0;
1081 int flags
= (O_WRONLY
| O_CREAT
| O_EXCL
1082 | (ascii
&& decompress
? 0 : O_BINARY
));
1083 char const *base
= ofname
;
1084 int atfd
= AT_FDCWD
;
1088 char const *b
= last_component (ofname
);
1089 int f
= atdir_set (ofname
, b
- ofname
);
1097 if (!signal_handlers_installed
)
1099 signal_handlers_installed
= true;
1100 install_signal_handlers ();
1108 volatile_strcpy (remove_ofname
, ofname
);
1110 sigprocmask (SIG_BLOCK
, &caught_signals
, &oldset
);
1111 remove_ofname_fd
= ofd
= openat (atfd
, base
, flags
, S_IRUSR
| S_IWUSR
);
1113 sigprocmask (SIG_SETMASK
, &oldset
, NULL
);
1122 shorten_name (ofname
);
1128 if (check_ofname () != OK
)
1142 if (name_shortened
&& decompress
)
1144 /* name might be too long if an original name was saved */
1145 WARN ((stderr
, "%s: %s: warning, name truncated\n",
1146 program_name
, ofname
));
1152 /* ========================================================================
1153 * Return a pointer to the 'z' suffix of a file name, or NULL. For all
1154 * systems, ".gz", ".z", ".Z", ".taz", ".tgz", "-gz", "-z" and "_z" are
1155 * accepted suffixes, in addition to the value of the --suffix option.
1156 * ".tgz" is a useful convention for tar.z files on systems limited
1157 * to 3 characters extensions. On such systems, ".?z" and ".??z" are
1158 * also accepted suffixes. For Unix, we do not want to accept any
1159 * .??z suffix as indicating a compressed file; some people use .xyz
1160 * to denote volume data.
1163 get_suffix (char *name
)
1166 char suffix
[MAX_SUFFIX
+3]; /* last chars of name, forced to lower case */
1167 static char const *known_suffixes
[] =
1168 {NULL
, ".gz", ".z", ".taz", ".tgz", "-gz", "-z", "_z",
1169 #ifdef MAX_EXT_CHARS
1174 bool suffix_of_builtin
= false;
1176 /* Normally put Z_SUFFIX at the start of KNOWN_SUFFIXES, but if it
1177 is a suffix of one of them, put it at the end. */
1178 for (suf
= known_suffixes
+ 1; *suf
; suf
++)
1180 size_t suflen
= strlen (*suf
);
1181 if (z_len
< suflen
&& strequ (z_suffix
, *suf
+ suflen
- z_len
))
1183 suffix_of_builtin
= true;
1188 char *z_lower
= xstrdup(z_suffix
);
1190 known_suffixes
[suffix_of_builtin
1191 ? sizeof known_suffixes
/ sizeof *known_suffixes
- 2
1193 suf
= known_suffixes
+ suffix_of_builtin
;
1195 nlen
= strlen(name
);
1196 if (nlen
<= MAX_SUFFIX
+2) {
1197 strcpy(suffix
, name
);
1199 strcpy(suffix
, name
+nlen
-MAX_SUFFIX
-2);
1202 slen
= strlen(suffix
);
1205 int s
= strlen(*suf
);
1206 if (slen
> s
&& ! ISSLASH (suffix
[slen
- s
- 1])
1207 && strequ(suffix
+ slen
- s
, *suf
)) {
1208 match
= name
+nlen
-s
;
1211 } while (*++suf
!= NULL
);
1218 /* Open file NAME with the given flags and store its status
1219 into *ST. Return a file descriptor to the newly opened file, or -1
1220 (setting errno) on failure. */
1222 open_and_stat (char *name
, int flags
, struct stat
*st
)
1225 int atfd
= AT_FDCWD
;
1226 char const *base
= name
;
1228 /* Refuse to follow symbolic links unless -c or -f. */
1229 if (!to_stdout
&& !force
)
1231 if (HAVE_WORKING_O_NOFOLLOW
)
1232 flags
|= O_NOFOLLOW
;
1236 if (lstat (name
, st
) != 0)
1238 else if (S_ISLNK (st
->st_mode
))
1249 char const *b
= last_component (name
);
1250 int f
= atdir_set (name
, b
- name
);
1258 fd
= openat (atfd
, base
, flags
);
1259 if (0 <= fd
&& fstat (fd
, st
) != 0)
1270 /* ========================================================================
1271 * Set ifname to the input file name (with a suffix appended if necessary)
1272 * and istat to its stats. For decompression, if no file exists with the
1273 * original name, try adding successively z_suffix, .gz, .z, -z and .Z.
1274 * For MSDOS, we try only z_suffix and z.
1275 * Return an open file descriptor or -1.
1278 open_input_file (char *iname
, struct stat
*sbuf
)
1280 int ilen
; /* strlen(ifname) */
1281 int z_suffix_errno
= 0;
1282 static char const *suffixes
[] = {NULL
, ".gz", ".z", "-z", ".Z", NULL
};
1283 char const **suf
= suffixes
;
1285 #ifdef NO_MULTIPLE_DOTS
1286 char *dot
; /* pointer to ifname extension, or NULL */
1289 int open_flags
= (O_RDONLY
| O_NONBLOCK
| O_NOCTTY
1290 | (ascii
&& !decompress
? 0 : O_BINARY
));
1294 if (sizeof ifname
- 1 <= strlen (iname
))
1297 strcpy(ifname
, iname
);
1299 /* If input file exists, return OK. */
1300 fd
= open_and_stat (ifname
, open_flags
, sbuf
);
1304 if (!decompress
|| errno
!= ENOENT
) {
1308 /* File.ext doesn't exist. Try adding a suffix. */
1309 s
= get_suffix(ifname
);
1311 progerror(ifname
); /* ifname already has z suffix and does not exist */
1314 #ifdef NO_MULTIPLE_DOTS
1315 dot
= strrchr(ifname
, '.');
1317 strcat(ifname
, ".");
1318 dot
= strrchr(ifname
, '.');
1321 ilen
= strlen(ifname
);
1322 if (strequ(z_suffix
, ".gz")) suf
++;
1324 /* Search for all suffixes */
1326 char const *s0
= s
= *suf
;
1327 strcpy (ifname
, iname
);
1328 #ifdef NO_MULTIPLE_DOTS
1330 if (*dot
== '\0') strcpy (dot
, ".");
1332 #ifdef MAX_EXT_CHARS
1333 if (MAX_EXT_CHARS
< strlen (s
) + strlen (dot
+ 1))
1334 dot
[MAX_EXT_CHARS
+ 1 - strlen (s
)] = '\0';
1336 if (sizeof ifname
<= ilen
+ strlen (s
))
1339 fd
= open_and_stat (ifname
, open_flags
, sbuf
);
1342 if (errno
!= ENOENT
)
1347 if (strequ (s0
, z_suffix
))
1348 z_suffix_errno
= errno
;
1349 } while (*++suf
!= NULL
);
1351 /* No suffix found, complain using z_suffix: */
1352 strcpy(ifname
, iname
);
1353 #ifdef NO_MULTIPLE_DOTS
1354 if (*dot
== '\0') strcpy(dot
, ".");
1356 #ifdef MAX_EXT_CHARS
1357 if (MAX_EXT_CHARS
< z_len
+ strlen (dot
+ 1))
1358 dot
[MAX_EXT_CHARS
+ 1 - z_len
] = '\0';
1360 strcat(ifname
, z_suffix
);
1361 errno
= z_suffix_errno
;
1366 fprintf (stderr
, "%s: %s: file name too long\n", program_name
, iname
);
1371 /* ========================================================================
1372 * Generate ofname given ifname. Return OK, or WARNING if file must be skipped.
1373 * Sets save_orig_name to true if the file name has been truncated.
1378 char *suff
; /* ofname z suffix */
1380 strcpy(ofname
, ifname
);
1381 /* strip a version number if any and get the gzip suffix if present: */
1382 suff
= get_suffix(ofname
);
1386 /* With -t or -l, try all files (even without .gz suffix)
1387 * except with -r (behave as with just -dr).
1389 if (!recursive
&& test
)
1392 /* Avoid annoying messages with -r */
1393 if (verbose
|| (!recursive
&& !quiet
)) {
1394 WARN((stderr
,"%s: %s: unknown suffix -- ignored\n",
1395 program_name
, ifname
));
1399 /* Make a special case for .tgz and .taz: */
1401 if (strequ(suff
, ".tgz") || strequ(suff
, ".taz")) {
1402 strcpy(suff
, ".tar");
1404 *suff
= '\0'; /* strip the z suffix */
1406 /* ofname might be changed later if infile contains an original name */
1408 } else if (suff
&& ! force
) {
1409 /* Avoid annoying messages with -r (see treat_dir()) */
1410 if (verbose
|| (!recursive
&& !quiet
)) {
1411 /* Don't use WARN, as it affects exit status. */
1412 fprintf (stderr
, "%s: %s already has %s suffix -- unchanged\n",
1413 program_name
, ifname
, suff
);
1419 #ifdef NO_MULTIPLE_DOTS
1420 suff
= strrchr(ofname
, '.');
1422 if (sizeof ofname
<= strlen (ofname
) + 1)
1424 strcat(ofname
, ".");
1425 # ifdef MAX_EXT_CHARS
1426 if (strequ(z_suffix
, "z")) {
1427 if (sizeof ofname
<= strlen (ofname
) + 2)
1429 strcat(ofname
, "gz"); /* enough room */
1432 /* On the Atari and some versions of MSDOS,
1433 * ENAMETOOLONG does not work correctly. So we
1434 * must truncate here.
1436 } else if (strlen(suff
)-1 + z_len
> MAX_SUFFIX
) {
1437 suff
[MAX_SUFFIX
+1-z_len
] = '\0';
1441 #endif /* NO_MULTIPLE_DOTS */
1442 if (sizeof ofname
<= strlen (ofname
) + z_len
)
1444 strcat(ofname
, z_suffix
);
1446 } /* decompress ? */
1450 WARN ((stderr
, "%s: %s: file name too long\n", program_name
, ifname
));
1454 /* Discard NBYTES input bytes from the input, or up through the next
1455 zero byte if NBYTES == (size_t) -1. If FLAGS say that the header
1456 CRC should be computed, update the CRC accordingly. */
1458 discard_input_bytes (size_t nbytes
, unsigned int flags
)
1462 uch c
= get_byte ();
1463 if (flags
& HEADER_CRC
)
1465 if (nbytes
!= (size_t) -1)
1472 /* ========================================================================
1473 * Check the magic number of the input file and update ofname if an
1474 * original name was given and to_stdout is not set.
1475 * Return the compression method, -1 for error, -2 for warning.
1476 * Set inptr to the offset of the next byte to be processed.
1477 * Updates time_stamp if there is one and neither -m nor -n is used.
1478 * This function may be called repeatedly for an input file consisting
1479 * of several contiguous gzip'ed members.
1480 * 'in' is the input file descriptor.
1481 * IN assertions: there is at least one remaining compressed member.
1482 * If the member is a zip file, it must be the only one.
1487 uch flags
; /* compression flags */
1488 uch magic
[10]; /* magic header */
1489 int imagic0
; /* first magic byte or EOF */
1490 int imagic1
; /* like magic[1], but can represent EOF */
1491 ulg stamp
; /* timestamp */
1493 /* If --force and --stdout, zcat == cat, so do not complain about
1494 * premature end of file: use try_byte instead of get_byte.
1496 if (force
&& to_stdout
) {
1497 imagic0
= try_byte();
1499 imagic1
= try_byte ();
1501 /* If try_byte returned EOF, magic[1] == (char) EOF. */
1503 magic
[0] = get_byte ();
1506 magic
[1] = get_byte ();
1507 imagic1
= 0; /* avoid lint warning */
1509 imagic1
= try_byte ();
1513 method
= -1; /* unknown yet */
1514 part_nb
++; /* number of parts in gzip file */
1517 /* assume multiple members in gzip file except for record oriented I/O */
1519 if (memcmp(magic
, GZIP_MAGIC
, 2) == 0
1520 || memcmp(magic
, OLD_GZIP_MAGIC
, 2) == 0) {
1522 method
= (int)get_byte();
1523 if (method
!= DEFLATED
) {
1525 "%s: %s: unknown method %d -- not supported\n",
1526 program_name
, ifname
, method
);
1531 flags
= (uch
)get_byte();
1533 if ((flags
& ENCRYPTED
) != 0) {
1535 "%s: %s is encrypted -- not supported\n",
1536 program_name
, ifname
);
1540 if ((flags
& RESERVED
) != 0) {
1542 "%s: %s has flags 0x%x -- not supported\n",
1543 program_name
, ifname
, flags
);
1545 if (force
<= 1) return -1;
1547 stamp
= (ulg
)get_byte();
1548 stamp
|= ((ulg
)get_byte()) << 8;
1549 stamp
|= ((ulg
)get_byte()) << 16;
1550 stamp
|= ((ulg
)get_byte()) << 24;
1551 if (stamp
!= 0 && !no_time
)
1553 if (stamp
<= TYPE_MAXIMUM (time_t))
1555 time_stamp
.tv_sec
= stamp
;
1556 time_stamp
.tv_nsec
= 0;
1561 "%s: %s: MTIME %lu out of range for this platform\n",
1562 program_name
, ifname
, stamp
));
1563 time_stamp
.tv_sec
= TYPE_MAXIMUM (time_t);
1564 time_stamp
.tv_nsec
= TIMESPEC_RESOLUTION
- 1;
1568 magic
[8] = get_byte (); /* Ignore extra flags. */
1569 magic
[9] = get_byte (); /* Ignore OS type. */
1571 if (flags
& HEADER_CRC
)
1573 magic
[2] = DEFLATED
;
1575 magic
[4] = stamp
& 0xff;
1576 magic
[5] = (stamp
>> 8) & 0xff;
1577 magic
[6] = (stamp
>> 16) & 0xff;
1578 magic
[7] = stamp
>> 24;
1583 if ((flags
& EXTRA_FIELD
) != 0) {
1585 unsigned int len
= lenbuf
[0] = get_byte ();
1586 len
|= (lenbuf
[1] = get_byte ()) << 8;
1588 fprintf(stderr
,"%s: %s: extra field of %u bytes ignored\n",
1589 program_name
, ifname
, len
);
1591 if (flags
& HEADER_CRC
)
1593 discard_input_bytes (len
, flags
);
1596 /* Get original file name if it was truncated */
1597 if ((flags
& ORIG_NAME
) != 0) {
1598 if (no_name
|| (to_stdout
&& !list
) || part_nb
> 1) {
1599 /* Discard the old name */
1600 discard_input_bytes (-1, flags
);
1602 /* Copy the base name. Keep a directory prefix intact. */
1603 char *p
= gzip_base_name (ofname
);
1606 *p
= (char) get_byte ();
1607 if (*p
++ == '\0') break;
1608 if (p
>= ofname
+sizeof(ofname
)) {
1609 gzip_error ("corrupted input -- file name too large");
1612 if (flags
& HEADER_CRC
)
1613 updcrc ((uch
*) base
, p
- base
);
1614 p
= gzip_base_name (base
);
1615 memmove (base
, p
, strlen (p
) + 1);
1616 /* If necessary, adapt the name to local OS conventions: */
1618 MAKE_LEGAL_NAME(base
);
1619 if (base
) list
=0; /* avoid warning about unused variable */
1621 } /* no_name || to_stdout */
1624 /* Discard file comment if any */
1625 if ((flags
& COMMENT
) != 0) {
1626 discard_input_bytes (-1, flags
);
1629 if (flags
& HEADER_CRC
)
1631 unsigned int crc16
= updcrc (magic
, 0) & 0xffff;
1632 unsigned int header16
= get_byte ();
1633 header16
|= ((unsigned int) get_byte ()) << 8;
1634 if (header16
!= crc16
)
1637 "%s: %s: header checksum 0x%04x != computed checksum 0x%04x\n",
1638 program_name
, ifname
, header16
, crc16
);
1646 header_bytes
= inptr
+ 2*4; /* include crc and size */
1649 } else if (memcmp(magic
, PKZIP_MAGIC
, 2) == 0 && inptr
== 2
1650 && memcmp((char*)inbuf
, PKZIP_MAGIC
, 4) == 0) {
1651 /* To simplify the code, we support a zip file when alone only.
1652 * We are thus guaranteed that the entire local header fits in inbuf.
1656 if (check_zipfile(in
) != OK
) return -1;
1657 /* check_zipfile may get ofname from the local header */
1660 } else if (memcmp(magic
, PACK_MAGIC
, 2) == 0) {
1664 } else if (memcmp(magic
, LZW_MAGIC
, 2) == 0) {
1666 method
= COMPRESSED
;
1669 } else if (memcmp(magic
, LZH_MAGIC
, 2) == 0) {
1674 } else if (force
&& to_stdout
&& !list
) { /* pass input unchanged */
1680 if (imagic0
!= EOF
) {
1681 write_buf (STDOUT_FILENO
, magic
, 1);
1684 if (method
>= 0) return method
;
1687 fprintf (stderr
, "\n%s: %s: not in gzip format\n",
1688 program_name
, ifname
);
1695 for (inbyte
= imagic1
; inbyte
== 0; inbyte
= try_byte ())
1700 WARN ((stderr
, "\n%s: %s: decompression OK, trailing zero bytes ignored\n",
1701 program_name
, ifname
));
1706 WARN((stderr
, "\n%s: %s: decompression OK, trailing garbage ignored\n",
1707 program_name
, ifname
));
1712 /* ========================================================================
1713 * Display the characteristics of the compressed file.
1714 * If the given method is < 0, display the accumulated totals.
1715 * IN assertions: time_stamp, header_bytes and ifile_size are initialized.
1718 do_list (int method
)
1720 ulg crc
; /* original crc */
1721 static int first_time
= 1;
1722 static char const *const methods
[MAX_METHODS
] = {
1727 "", "", "", "", /* 4 to 7 reserved */
1729 int positive_off_t_width
= INT_STRLEN_BOUND (off_t
) - 1;
1731 if (first_time
&& method
>= 0) {
1734 printf("method crc date time ");
1737 printf("%*.*s %*.*s ratio uncompressed_name\n",
1738 positive_off_t_width
, positive_off_t_width
, "compressed",
1739 positive_off_t_width
, positive_off_t_width
, "uncompressed");
1741 } else if (method
< 0) {
1742 if (total_in
<= 0 || total_out
<= 0) return;
1746 if (verbose
|| !quiet
)
1747 printf ("%*jd %*jd ", positive_off_t_width
, (intmax_t) total_in
,
1748 positive_off_t_width
, (intmax_t) total_out
);
1749 display_ratio(total_out
-(total_in
-header_bytes
), total_out
, stdout
);
1750 /* header_bytes is not meaningful but used to ensure the same
1751 * ratio if there is a single file.
1753 printf(" (totals)\n");
1756 crc
= (ulg
)~0; /* unknown */
1758 if (method
== DEFLATED
&& !last_member
) {
1764 static char const month_abbr
[][4]
1765 = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1766 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
1767 struct tm
*tm
= localtime (&time_stamp
.tv_sec
);
1768 printf ("%5s %08lx ", methods
[method
], crc
);
1770 printf ("%s%3d %02d:%02d ", month_abbr
[tm
->tm_mon
],
1771 tm
->tm_mday
, tm
->tm_hour
, tm
->tm_min
);
1773 printf ("??? ?? ??:?? ");
1775 printf ("%*jd %*jd ", positive_off_t_width
, (intmax_t) bytes_in
,
1776 positive_off_t_width
, (intmax_t) bytes_out
);
1777 if (bytes_in
== -1L) {
1779 bytes_in
= bytes_out
= header_bytes
= 0;
1780 } else if (total_in
>= 0) {
1781 total_in
+= bytes_in
;
1783 if (bytes_out
== -1L) {
1785 bytes_in
= bytes_out
= header_bytes
= 0;
1786 } else if (total_out
>= 0) {
1787 total_out
+= bytes_out
;
1789 display_ratio(bytes_out
-(bytes_in
-header_bytes
), bytes_out
, stdout
);
1790 printf(" %s\n", ofname
);
1793 /* ========================================================================
1794 * Shorten the given name by one character, or replace a .tar extension
1795 * with .tgz. Truncate the last part of the name which is longer than
1796 * MIN_PART characters: 1234.678.012.gz -> 123.678.012.gz. If the name
1797 * has only parts shorter than MIN_PART truncate the longest part.
1798 * For decompression, just remove the last character of the name.
1800 * IN assertion: for compression, the suffix of the given name is z_suffix.
1803 shorten_name (char *name
)
1805 int len
; /* length of name without z_suffix */
1806 char *trunc
= NULL
; /* character to be truncated */
1807 int plen
; /* current part length */
1808 int min_part
= MIN_PART
; /* current minimum part length */
1814 gzip_error ("name too short");
1818 p
= get_suffix(name
);
1820 gzip_error ("can't recover suffix\n");
1824 /* compress 1234567890.tar to 1234567890.tgz */
1825 if (len
> 4 && strequ(p
-4, ".tar")) {
1826 strcpy(p
-4, ".tgz");
1829 /* Try keeping short extensions intact:
1830 * 1234.678.012.gz -> 123.678.012.gz
1833 p
= last_component (name
);
1835 plen
= strcspn(p
, PART_SEP
);
1837 if (plen
> min_part
) trunc
= p
-1;
1840 } while (trunc
== NULL
&& --min_part
!= 0);
1842 if (trunc
!= NULL
) {
1844 trunc
[0] = trunc
[1];
1848 trunc
= strrchr(name
, PART_SEP
[0]);
1850 gzip_error ("internal error in shorten_name");
1851 if (trunc
[1] == '\0') trunc
--; /* force truncation */
1853 strcpy(trunc
, z_suffix
);
1856 /* ========================================================================
1857 * The compressed file already exists, so ask for confirmation.
1858 * Return ERROR if the file must be skipped.
1863 /* Ask permission to overwrite the existing file */
1866 fprintf (stderr
, "%s: %s already exists;", program_name
, ofname
);
1867 if (foreground
&& (presume_input_tty
|| isatty (STDIN_FILENO
))) {
1868 fprintf(stderr
, " do you wish to overwrite (y or n)? ");
1873 fprintf(stderr
, "\tnot overwritten\n");
1874 if (exit_code
== OK
) exit_code
= WARNING
;
1878 if (xunlink (ofname
)) {
1885 /* Change the owner and group of a file. FD is a file descriptor for
1886 the file and NAME its name. Change it to user UID and to group GID.
1887 If UID or GID is -1, though, do not change the corresponding user
1889 #if ! (HAVE_FCHOWN || HAVE_CHOWN)
1890 /* The types uid_t and gid_t do not exist on mingw, so don't assume them. */
1891 # define do_chown(fd, name, uid, gid) ((void) 0)
1894 do_chown (int fd
, char const *name
, uid_t uid
, gid_t gid
)
1897 ignore_value (fchown (fd
, uid
, gid
));
1899 ignore_value (chown (name
, uid
, gid
));
1904 /* ========================================================================
1905 * Copy modes, times, ownership from input file to output file.
1906 * IN assertion: to_stdout is false.
1909 copy_stat (struct stat
*ifstat
)
1911 mode_t mode
= ifstat
->st_mode
& S_IRWXUGO
;
1916 struct timespec timespec
[2];
1917 timespec
[0] = get_stat_atime (ifstat
);
1918 timespec
[1] = get_stat_mtime (ifstat
);
1919 restoring
= (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
;
1925 if (fdutimens (ofd
, ofname
, timespec
) == 0)
1927 if (restoring
&& 1 < verbose
) {
1928 fprintf(stderr
, "%s: timestamp restored\n", ofname
);
1932 WARN ((stderr
, "%s: %s: %s\n", program_name
, ofname
, strerror (errno
)));
1935 /* Change the group first, then the permissions, then the owner.
1936 That way, the permissions will be correct on systems that allow
1937 users to give away files, without introducing a security hole.
1938 Security depends on permissions not containing the setuid or
1941 do_chown (ofd
, ofname
, -1, ifstat
->st_gid
);
1944 r
= fchmod (ofd
, mode
);
1946 r
= chmod (ofname
, mode
);
1949 WARN ((stderr
, "%s: %s: %s\n", program_name
, ofname
, strerror (errno
)));
1951 do_chown (ofd
, ofname
, ifstat
->st_uid
, -1);
1956 /* ========================================================================
1957 * Recurse through the given directory.
1960 treat_dir (int fd
, char *dir
)
1963 char nbuf
[MAX_PATH_LEN
];
1968 dirp
= fdopendir (fd
);
1976 entries
= streamsavedir (dirp
, SAVEDIR_SORT_NONE
);
1979 if (closedir (dirp
) != 0)
1984 for (entry
= entries
; *entry
; entry
+= entrylen
+ 1) {
1985 size_t len
= strlen (dir
);
1986 entrylen
= strlen (entry
);
1987 if (strequ (entry
, ".") || strequ (entry
, ".."))
1989 if (len
+ entrylen
< MAX_PATH_LEN
- 2) {
1991 if (*last_component (nbuf
) && !ISSLASH (nbuf
[len
- 1]))
1993 strcpy (nbuf
+ len
, entry
);
1996 fprintf(stderr
,"%s: %s/%s: pathname too long\n",
1997 program_name
, dir
, entry
);
2003 #endif /* ! NO_DIR */
2005 /* Make sure signals get handled properly. */
2008 install_signal_handlers ()
2010 int nsigs
= sizeof handled_sig
/ sizeof handled_sig
[0];
2012 struct sigaction act
;
2014 sigemptyset (&caught_signals
);
2015 for (i
= 0; i
< nsigs
; i
++)
2017 sigaction (handled_sig
[i
], NULL
, &act
);
2018 if (act
.sa_handler
!= SIG_IGN
)
2019 sigaddset (&caught_signals
, handled_sig
[i
]);
2022 act
.sa_handler
= abort_gzip_signal
;
2023 act
.sa_mask
= caught_signals
;
2026 for (i
= 0; i
< nsigs
; i
++)
2027 if (sigismember (&caught_signals
, handled_sig
[i
]))
2031 sigaction (handled_sig
[i
], &act
, NULL
);
2035 /* ========================================================================
2036 * Free all dynamically allocated variables and exit with the given code.
2039 do_exit (int exitcode
)
2041 static int in_exit
= 0;
2043 if (in_exit
) exit(exitcode
);
2063 if (fclose (stdout
) != 0)
2068 /* ========================================================================
2069 * Close and unlink the output file.
2072 remove_output_file (bool signals_already_blocked
)
2077 if (!signals_already_blocked
)
2078 sigprocmask (SIG_BLOCK
, &caught_signals
, &oldset
);
2079 fd
= remove_ofname_fd
;
2082 char fname
[MAX_PATH_LEN
];
2083 remove_ofname_fd
= -1;
2085 volatile_strcpy (fname
, remove_ofname
);
2088 if (!signals_already_blocked
)
2089 sigprocmask (SIG_SETMASK
, &oldset
, NULL
);
2092 /* ========================================================================
2096 finish_up_gzip (int exitcode
)
2098 if (0 <= remove_ofname_fd
)
2099 remove_output_file (false);
2105 finish_up_gzip (ERROR
);
2107 /* ========================================================================
2111 abort_gzip_signal (int sig
)
2113 remove_output_file (true);
2114 signal (sig
, SIG_DFL
);