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, 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) 2024 Free Software Foundation, Inc.",
33 "Copyright (C) 1993 Jean-loup Gailly.",
34 "This is free software. You may redistribute copies of it under the terms of",
35 "the GNU General Public License <https://www.gnu.org/licenses/gpl.html>.",
36 "There is NO WARRANTY, to the extent permitted by law.",
39 /* Compress files with zip algorithm and 'compress' interface.
40 * See help() function below for all options.
42 * file.gz: compressed file with same mode, owner, and utimes
43 * or stdout with -c option or if stdin used as input.
44 * If the output file name had to be truncated, the original name is kept
45 * in the compressed file.
46 * On MSDOS, file.tmp -> file.tmz.
48 * Using gz on MSDOS would create too many file name conflicts. For
49 * example, foo.txt -> foo.tgz (.tgz must be reserved as shorthand for
50 * tar.gz). Similarly, foo.dir and foo.doc would both be mapped to foo.dgz.
51 * I also considered 12345678.txt -> 12345txt.gz but this truncates the name
52 * too heavily. There is no ideal solution given the MSDOS 8+3 limitation.
54 * For the meaning of all compilation flags, see comments in Makefile.in.
59 #include <sys/types.h>
76 #include "ignore-value.h"
77 #include "stat-time.h"
101 # define MAX_PATH_LEN 1024 /* max pathname length */
113 off_t
lseek (int fd
, off_t offset
, int whence
);
116 #ifndef HAVE_WORKING_O_NOFOLLOW
117 # define HAVE_WORKING_O_NOFOLLOW 0
120 /* Separator for file name parts (see shorten_name()) */
121 #ifdef NO_MULTIPLE_DOTS
122 # define PART_SEP "-"
124 # define PART_SEP "."
129 /* With IBM_Z_DFLTCC, DEFLATE COMPRESSION works faster with
130 page-aligned input and output buffers, and requires page-aligned
131 windows; the alignment requirement is 4096. On other platforms
132 alignment doesn't hurt, and alignment up to 4096 is portable so
134 #if defined HAVE_C_ALIGNASOF || defined alignas
135 # define BUFFER_ALIGNED alignas (4096)
137 # define BUFFER_ALIGNED /**/
139 DECLARE(uch BUFFER_ALIGNED
, inbuf
, INBUFSIZ
+INBUF_EXTRA
);
140 DECLARE(uch BUFFER_ALIGNED
, outbuf
, OUTBUFSIZ
+OUTBUF_EXTRA
);
141 DECLARE(ush
, d_buf
, DIST_BUFSIZE
);
142 DECLARE(uch BUFFER_ALIGNED
, window
, 2L*WSIZE
);
144 DECLARE(ush
, tab_prefix
, 1L<<BITS
);
146 DECLARE(ush
, tab_prefix0
, 1L<<(BITS
-1));
147 DECLARE(ush
, tab_prefix1
, 1L<<(BITS
-1));
150 /* local variables */
152 /* If true, pretend that standard input is a tty. This option
153 is deliberately not documented, and only for testing. */
154 static bool presume_input_tty
;
156 /* If true, transfer output data to the output file's storage device
157 when supported. Otherwise, if the system crashes around the time
158 gzip is run, the user might lose both input and output data. See:
159 Pillai TS et al. All file systems are not created equal: on the
160 complexity of crafting crash-consistent applications. OSDI'14. 2014:433-48.
161 https://www.usenix.org/conference/osdi14/technical-sessions/presentation/pillai */
162 static bool synchronous
;
164 static int ascii
= 0; /* convert end-of-lines to local OS conventions */
165 int to_stdout
= 0; /* output to stdout (-c) */
166 static int decompress
= 0; /* decompress (-d) */
167 static int force
= 0; /* don't ask questions, compress links (-f) */
168 static int keep
= 0; /* keep (don't delete) input files */
169 static int no_name
= -1; /* don't save or restore the original file name */
170 static int no_time
= -1; /* don't save or restore the original file time */
171 static int recursive
= 0; /* recurse through directories (-r) */
172 static int list
= 0; /* list the file contents (-l) */
176 int verbose
= 0; /* be verbose (-v) */
177 int quiet
= 0; /* be very quiet (-q) */
178 int test
= 0; /* test .gz file integrity */
179 static int foreground
= 0; /* set if program run in foreground */
180 char *program_name
; /* program name */
181 int maxbits
= BITS
; /* max bits per code for LZW */
182 int method
= DEFLATED
;/* compression method */
183 int level
= 6; /* compression level */
184 int exit_code
= OK
; /* program exit code */
185 int save_orig_name
; /* set if original name must be saved */
186 static int last_member
; /* set for .zip and .Z files */
187 static int part_nb
; /* number of parts in .gz file */
188 off_t ifile_size
; /* input file size, -1 for devices (debug only) */
189 static char *env
; /* contents of GZIP env variable */
190 static char const *z_suffix
; /* default suffix (can be set with --suffix) */
191 static size_t z_len
; /* strlen(z_suffix) */
193 /* The original timestamp (modification time). If the original is
194 unknown, TIME_STAMP.tv_nsec is negative. If the original is
195 greater than struct timespec range, TIME_STAMP is the maximal
196 struct timespec value; this can happen on hosts with 32-bit signed
197 time_t because the gzip format's MTIME is 32-bit unsigned.
198 The original cannot be less than struct timespec range. */
199 struct timespec time_stamp
;
201 /* The set of signals that are caught. */
202 static sigset_t caught_signals
;
204 /* If nonnegative, close this file descriptor and unlink remove_ofname
206 static int volatile remove_ofname_fd
= -1;
207 static char volatile remove_ofname
[MAX_PATH_LEN
];
209 static bool stdin_was_read
;
211 off_t bytes_in
; /* number of input bytes */
212 off_t bytes_out
; /* number of output bytes */
213 static off_t total_in
; /* input bytes for all files */
214 static off_t total_out
; /* output bytes for all files */
215 char ifname
[MAX_PATH_LEN
]; /* input file name */
216 char ofname
[MAX_PATH_LEN
]; /* output file name */
217 static char dfname
[MAX_PATH_LEN
]; /* name of dir containing output file */
218 static struct stat istat
; /* status for input file */
219 int ifd
; /* input file descriptor */
220 int ofd
; /* output file descriptor */
221 static int dfd
= -1; /* output directory file descriptor */
222 unsigned insize
; /* valid bytes in inbuf */
223 unsigned inptr
; /* index of next byte to be processed in inbuf */
224 unsigned outcnt
; /* bytes in output buffer */
225 int rsync
= 0; /* make rsyncable chunks */
227 static int handled_sig
[] =
229 /* SIGINT must be first, as 'foreground' depends on it. */
249 /* For long options that have no equivalent short option, use a
250 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
253 PRESUME_INPUT_TTY_OPTION
= CHAR_MAX
+ 1,
257 /* A value greater than all valid long options, used as a flag to
258 distinguish options derived from the GZIP environment variable. */
262 static char const shortopts
[] = "ab:cdfhH?klLmMnNqrS:tvVZ123456789";
264 static const struct option longopts
[] =
266 /* { name has_arg *flag val } */
267 {"ascii", 0, 0, 'a'}, /* ascii text mode */
268 {"to-stdout", 0, 0, 'c'}, /* write output on standard output */
269 {"stdout", 0, 0, 'c'}, /* write output on standard output */
270 {"decompress", 0, 0, 'd'}, /* decompress */
271 {"uncompress", 0, 0, 'd'}, /* decompress */
272 /* {"encrypt", 0, 0, 'e'}, encrypt */
273 {"force", 0, 0, 'f'}, /* force overwrite of output file */
274 {"help", 0, 0, 'h'}, /* give help */
275 /* {"pkzip", 0, 0, 'k'}, force output in pkzip format */
276 {"keep", 0, 0, 'k'}, /* keep (don't delete) input files */
277 {"list", 0, 0, 'l'}, /* list .gz file contents */
278 {"license", 0, 0, 'L'}, /* display software license */
279 {"no-name", 0, 0, 'n'}, /* don't save or restore original name & time */
280 {"name", 0, 0, 'N'}, /* save or restore original name & time */
281 {"-presume-input-tty", no_argument
, NULL
, PRESUME_INPUT_TTY_OPTION
},
282 {"quiet", 0, 0, 'q'}, /* quiet mode */
283 {"silent", 0, 0, 'q'}, /* quiet mode */
284 {"synchronous",0, 0, SYNCHRONOUS_OPTION
},
285 {"recursive", 0, 0, 'r'}, /* recurse through directories */
286 {"suffix", 1, 0, 'S'}, /* use given suffix instead of .gz */
287 {"test", 0, 0, 't'}, /* test compressed file integrity */
288 {"verbose", 0, 0, 'v'}, /* verbose mode */
289 {"version", 0, 0, 'V'}, /* display version number */
290 {"fast", 0, 0, '1'}, /* compress faster */
291 {"best", 0, 0, '9'}, /* compress better */
292 {"lzw", 0, 0, 'Z'}, /* make output compatible with old compress */
293 {"bits", 1, 0, 'b'}, /* max number of bits per code (implies -Z) */
294 {"rsyncable", 0, 0, RSYNCABLE_OPTION
}, /* make rsync-friendly archive */
298 /* local functions */
300 _Noreturn
static void try_help (void);
301 static void help (void);
302 static void license (void);
303 static void version (void);
304 static int input_eof (void);
305 static void treat_stdin (void);
306 static void treat_file (char *iname
);
307 static int create_outfile (void);
308 static char *get_suffix (char *name
);
309 static int open_input_file (char *iname
, struct stat
*sbuf
);
310 static void discard_input_bytes (size_t nbytes
, unsigned int flags
);
311 static int make_ofname (void);
312 static void shorten_name (char *name
);
313 static int get_method (int in
);
314 static void do_list (int method
);
315 static int check_ofname (void);
316 static void copy_stat (struct stat
*ifstat
);
317 static void install_signal_handlers (void);
318 static void remove_output_file (bool);
319 static void abort_gzip_signal (int);
320 _Noreturn
static void do_exit (int exitcode
);
321 static void finish_out (void);
322 int main (int argc
, char **argv
);
323 static int (*work
) (int infile
, int outfile
) = zip
; /* function to call */
326 static void treat_dir (int fd
, char *dir
);
329 #define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
334 fprintf (stderr
, "Try `%s --help' for more information.\n",
339 /* ======================================================================== */
343 static char const* const help_msg
[] = {
344 "Compress or uncompress FILEs (by default, compress FILES in-place).",
346 "Mandatory arguments to long options are mandatory for short options too.",
349 " -a, --ascii ascii text; convert end-of-line using local conventions",
351 " -c, --stdout write on standard output, keep original files unchanged",
352 " -d, --decompress decompress",
353 /* -e, --encrypt encrypt */
354 " -f, --force force overwrite of output file and compress links",
355 " -h, --help give this help",
356 /* -k, --pkzip force output in pkzip format */
357 " -k, --keep keep (don't delete) input files",
358 " -l, --list list compressed file contents",
359 " -L, --license display software license",
361 " -m do not save or restore the original modification time",
362 " -M, --time save or restore the original modification time",
364 " -n, --no-name do not save or restore the original name and timestamp",
365 " -N, --name save or restore the original name and timestamp",
366 " -q, --quiet suppress all warnings",
368 " -r, --recursive operate recursively on directories",
370 " --rsyncable make rsync-friendly archive",
371 " -S, --suffix=SUF use suffix SUF on compressed files",
372 " --synchronous synchronous output (safer if system crashes, but slower)",
373 " -t, --test test compressed file integrity",
374 " -v, --verbose verbose mode",
375 " -V, --version display version number",
376 " -1, --fast compress faster",
377 " -9, --best compress better",
379 "With no FILE, or when FILE is -, read standard input.",
381 "Report bugs to <bug-gzip@gnu.org>.",
383 char const *const *p
= help_msg
;
385 printf ("Usage: %s [OPTION]... [FILE]...\n", program_name
);
386 while (*p
) printf ("%s\n", *p
++);
389 /* ======================================================================== */
393 char const *const *p
= license_msg
;
395 printf ("%s %s\n", program_name
, Version
);
396 while (*p
) printf ("%s\n", *p
++);
399 /* ======================================================================== */
405 printf ("Written by Jean-loup Gailly.\n");
409 progerror (char const *string
)
411 fprintf (stderr
, "%s: %s: %s\n", program_name
, string
, strerror (errno
));
415 /* ======================================================================== */
416 int main (int argc
, char **argv
)
418 int file_count
; /* number of files to process */
419 size_t proglen
; /* length of program_name */
424 EXPAND(argc
, argv
); /* wild card expansion if necessary */
426 program_name
= gzip_base_name (argv
[0]);
427 proglen
= strlen (program_name
);
429 /* Suppress .exe for MSDOS and OS/2: */
430 if (4 < proglen
&& strequ (program_name
+ proglen
- 4, ".exe"))
431 program_name
[proglen
- 4] = '\0';
433 /* Add options in GZIP environment variable if there is one */
435 env
= add_envopt (&env_argc
, &argv_copy
, OPTIONS_VAR
);
436 env_argv
= env
? argv_copy
: NULL
;
439 # define GNU_STANDARD 1
442 /* For compatibility with old compress, use program name as an option.
443 * Unless you compile with -DGNU_STANDARD=0, this program will behave as
444 * gzip even if it is invoked under the name gunzip or zcat.
446 * Systems which do not support links can still use -d or -dc.
447 * Ignore an .exe extension for MSDOS and OS/2.
449 if (strncmp (program_name
, "un", 2) == 0 /* ungzip, uncompress */
450 || strncmp (program_name
, "gun", 3) == 0) /* gunzip */
452 else if (strequ (program_name
+ 1, "cat") /* zcat, pcat, gcat */
453 || strequ (program_name
, "gzcat")) /* gzcat */
454 decompress
= to_stdout
= 1;
458 z_len
= strlen(z_suffix
);
466 if (env_argv
[optind
] && strequ (env_argv
[optind
], "--"))
467 optc
= ENV_OPTION
+ '-';
470 optc
= getopt_long (env_argc
, env_argv
, shortopts
, longopts
,
476 if (optind
!= env_argc
)
479 ("%s: %s: non-option in "OPTIONS_VAR
480 " environment variable\n"),
481 program_name
, env_argv
[optind
]);
485 /* Wait until here before warning, so that GZIP='-q'
487 if (env_argc
!= 1 && !quiet
)
489 ("%s: warning: "OPTIONS_VAR
" environment variable"
490 " is deprecated; use an alias or script\n"),
493 /* Start processing ARGC and ARGV instead. */
503 optc
= getopt_long (argc
, argv
, shortopts
, longopts
, &longind
);
511 maxbits
= atoi(optarg
);
512 for (; *optarg
; optarg
++)
513 if (! ('0' <= *optarg
&& *optarg
<= '9'))
515 fprintf (stderr
, "%s: -b operand is not an integer\n",
521 to_stdout
= 1; break;
523 decompress
= 1; break;
527 help (); finish_out (); break;
531 list
= decompress
= test
= to_stdout
= 1; break;
533 license (); finish_out (); break;
534 case 'm': /* undocumented, may change later */
536 case 'M': /* undocumented, may change later */
539 case 'n' + ENV_OPTION
:
540 no_name
= no_time
= 1; break;
542 case 'N' + ENV_OPTION
:
543 no_name
= no_time
= 0; break;
544 case PRESUME_INPUT_TTY_OPTION
:
545 presume_input_tty
= true; break;
547 case 'q' + ENV_OPTION
:
548 quiet
= 1; verbose
= 0; break;
551 fprintf (stderr
, "%s: -r not supported on this system\n",
559 case RSYNCABLE_OPTION
:
560 case RSYNCABLE_OPTION
+ ENV_OPTION
:
564 #ifdef NO_MULTIPLE_DOTS
565 if (*optarg
== '.') optarg
++;
567 z_len
= strlen(optarg
);
570 case SYNCHRONOUS_OPTION
:
574 test
= decompress
= to_stdout
= 1;
577 case 'v' + ENV_OPTION
:
578 verbose
++; quiet
= 0; break;
580 version (); finish_out (); break;
582 fprintf(stderr
, "%s: -Z not supported in this version\n",
586 case '1' + ENV_OPTION
: case '2' + ENV_OPTION
: case '3' + ENV_OPTION
:
587 case '4' + ENV_OPTION
: case '5' + ENV_OPTION
: case '6' + ENV_OPTION
:
588 case '7' + ENV_OPTION
: case '8' + ENV_OPTION
: case '9' + ENV_OPTION
:
591 case '1': case '2': case '3': case '4':
592 case '5': case '6': case '7': case '8': case '9':
597 if (ENV_OPTION
<= optc
&& optc
!= ENV_OPTION
+ '?')
599 /* Output a diagnostic, since getopt_long didn't. */
600 fprintf (stderr
, "%s: ", program_name
);
602 fprintf (stderr
, "-%c: ", optc
- ENV_OPTION
);
604 fprintf (stderr
, "--%s: ", longopts
[longind
].name
);
605 fprintf (stderr
, ("option not valid in "OPTIONS_VAR
606 " environment variable\n"));
610 } /* loop on all arguments */
612 /* By default, save name and timestamp on compression but do not
613 * restore them on decompression.
615 if (no_time
< 0) no_time
= decompress
;
616 if (no_name
< 0) no_name
= decompress
;
618 file_count
= argc
- optind
;
622 if (ascii
&& !quiet
) {
623 fprintf(stderr
, "%s: option --ascii ignored on this system\n",
627 if (z_len
== 0 || z_len
> MAX_SUFFIX
) {
628 fprintf(stderr
, "%s: invalid suffix '%s'\n", program_name
, z_suffix
);
632 /* Allocate all global buffers (for DYN_ALLOC option) */
633 ALLOC(uch
, inbuf
, INBUFSIZ
+INBUF_EXTRA
);
634 ALLOC(uch
, outbuf
, OUTBUFSIZ
+OUTBUF_EXTRA
);
635 ALLOC(ush
, d_buf
, DIST_BUFSIZE
);
636 ALLOC(uch
, window
, 2L*WSIZE
);
638 ALLOC(ush
, tab_prefix
, 1L<<BITS
);
640 ALLOC(ush
, tab_prefix0
, 1L<<(BITS
-1));
641 ALLOC(ush
, tab_prefix1
, 1L<<(BITS
-1));
644 /* And get to work */
645 if (file_count
!= 0) {
646 if (to_stdout
&& !test
&& (!decompress
|| !ascii
)) {
647 SET_BINARY_MODE (STDOUT_FILENO
);
649 while (optind
< argc
) {
650 treat_file(argv
[optind
++]);
652 } else { /* Standard input */
655 if (stdin_was_read
&& close (STDIN_FILENO
) != 0)
657 strcpy (ifname
, "stdin");
662 /* Output any totals, and check for output errors. */
663 if (!quiet
&& 1 < file_count
)
665 if (fflush (stdout
) != 0)
670 && fdatasync (STDOUT_FILENO
) != 0 && errno
!= EINVAL
)
671 || close (STDOUT_FILENO
) != 0)
677 /* Return nonzero when at end of file on input. */
681 if (!decompress
|| last_member
)
686 if (insize
!= INBUFSIZ
|| fill_inbuf (1) == EOF
)
689 /* Unget the char that fill_inbuf got. */
697 get_input_size_and_time (void)
700 time_stamp
.tv_nsec
= -1;
702 /* Record the input file's size and timestamp only if it is a
703 regular file. Doing this for the timestamp helps to keep gzip's
704 output more reproducible when it is used as part of a
707 if (S_ISREG (istat
.st_mode
))
709 ifile_size
= istat
.st_size
;
710 if (!no_time
|| list
)
711 time_stamp
= get_stat_mtime (&istat
);
715 /* ========================================================================
716 * Compress or decompress stdin
722 && (presume_input_tty
723 || isatty (decompress
? STDIN_FILENO
: STDOUT_FILENO
))) {
724 /* Do not send compressed data to the terminal or read it from
725 * the terminal. We get here when user invoked the program
726 * without parameters, so be helpful. According to the GNU standards:
728 * If there is one behavior you think is most useful when the output
729 * is to a terminal, and another that you think is most useful when
730 * the output is a file or a pipe, then it is usually best to make
731 * the default behavior the one that is useful with output to a
732 * terminal, and have an option for the other behavior.
734 * Here we use the --force option to get the other behavior.
738 ("%s: compressed data not %s a terminal."
739 " Use -f to force %scompression.\n"
740 "For help, type: %s -h\n"),
742 decompress
? "read from" : "written to",
743 decompress
? "de" : "",
748 if (decompress
|| !ascii
) {
749 SET_BINARY_MODE (STDIN_FILENO
);
751 if (!test
&& (!decompress
|| !ascii
)) {
752 SET_BINARY_MODE (STDOUT_FILENO
);
754 strcpy(ifname
, "stdin");
755 strcpy(ofname
, "stdout");
757 /* Get the file's timestamp and size. */
758 if (fstat (STDIN_FILENO
, &istat
) != 0)
760 progerror ("standard input");
764 get_input_size_and_time ();
766 clear_bufs(); /* clear input and output buffers */
770 stdin_was_read
= true;
773 method
= get_method(ifd
);
775 do_exit(exit_code
); /* error message already emitted */
779 /* Actually do the compression/decompression. Loop over zipped members.
782 if (work (STDIN_FILENO
, STDOUT_FILENO
) != OK
)
788 method
= get_method(ifd
);
789 if (method
< 0) return; /* error message already emitted */
800 fprintf(stderr
, " OK\n");
802 } else if (!decompress
) {
803 display_ratio(bytes_in
-(bytes_out
-header_bytes
), bytes_in
, stderr
);
804 fprintf(stderr
, "\n");
805 #ifdef DISPLAY_STDIN_RATIO
807 display_ratio(bytes_out
-(bytes_in
-header_bytes
), bytes_out
,stderr
);
808 fprintf(stderr
, "\n");
814 static char const dot
= '.';
816 /* True if the cached directory for calls to openat etc. is DIR, with
817 length DIRLEN. DIR need not be null-terminated. DIRLEN must be
818 less than MAX_PATH_LEN. */
820 atdir_eq (char const *dir
, ptrdiff_t dirlen
)
823 dir
= &dot
, dirlen
= 1;
824 return memcmp (dfname
, dir
, dirlen
) == 0 && !dfname
[dirlen
];
827 /* Set the directory used for calls to openat etc. to be the directory
828 DIR, with length DIRLEN. DIR need not be null-terminated.
829 DIRLEN must be less than MAX_PATH_LEN. Return a file descriptor for
830 the directory, or -1 if one could not be obtained. */
832 atdir_set (char const *dir
, ptrdiff_t dirlen
)
834 /* Don't bother opening directories on older systems that
835 lack openat and unlinkat. It's not worth the porting hassle. */
836 #if HAVE_OPENAT && HAVE_UNLINKAT
837 enum { try_opening_directories
= true };
839 enum { try_opening_directories
= false };
842 if (try_opening_directories
&& ! atdir_eq (dir
, dirlen
))
847 dir
= &dot
, dirlen
= 1;
848 memcpy (dfname
, dir
, dirlen
);
849 dfname
[dirlen
] = '\0';
850 dfd
= open (dfname
, O_SEARCH
| O_DIRECTORY
);
856 /* ========================================================================
857 * Compress or decompress the given file
860 treat_file (char *iname
)
862 /* Accept "-" as synonym for stdin */
863 if (strequ(iname
, "-")) {
864 int cflag
= to_stdout
;
870 /* Check if the input file is present, set ifname and istat: */
871 ifd
= open_input_file (iname
, &istat
);
875 /* If the input name is that of a directory, recurse or ignore: */
876 if (S_ISDIR(istat
.st_mode
)) {
879 treat_dir (ifd
, iname
);
880 /* Warning: ifname is now garbage */
885 WARN ((stderr
, "%s: %s is a directory -- ignored\n",
886 program_name
, ifname
));
892 if (! S_ISREG (istat
.st_mode
))
895 "%s: %s is not a directory or a regular file - ignored\n",
896 program_name
, ifname
));
900 if (istat
.st_mode
& S_ISUID
)
902 WARN ((stderr
, "%s: %s is set-user-ID on execution - ignored\n",
903 program_name
, ifname
));
907 if (istat
.st_mode
& S_ISGID
)
909 WARN ((stderr
, "%s: %s is set-group-ID on execution - ignored\n",
910 program_name
, ifname
));
917 if (istat
.st_mode
& S_ISVTX
)
920 "%s: %s has the sticky bit set - file ignored\n",
921 program_name
, ifname
));
925 if (2 <= istat
.st_nlink
)
927 WARN ((stderr
, "%s: %s has %lu other link%s -- file ignored\n",
928 program_name
, ifname
,
929 (unsigned long int) istat
.st_nlink
- 1,
930 istat
.st_nlink
== 2 ? "" : "s"));
937 get_input_size_and_time ();
939 /* Generate output file name. For -r and (-t or -l), skip files
940 * without a valid gzip suffix (check done in make_ofname).
942 if (to_stdout
&& !test
) {
943 strcpy(ofname
, "stdout");
945 } else if (make_ofname() != OK
) {
950 clear_bufs(); /* clear input and output buffers */
954 method
= get_method(ifd
); /* updates ofname if original given */
957 return; /* error message already emitted */
961 /* If compressing to a file, check if ofname is not ambiguous
962 * because the operating system truncates names. Otherwise, generate
963 * a new ofname and save the original name in the compressed file.
967 /* Keep remove_ofname_fd negative. */
969 if (create_outfile() != OK
) return;
971 if (!decompress
&& save_orig_name
&& !verbose
&& !quiet
) {
972 fprintf(stderr
, "%s: %s compressed to %s\n",
973 program_name
, ifname
, ofname
);
976 /* Keep the name even if not truncated except with --no-name: */
977 if (!save_orig_name
) save_orig_name
= !no_name
;
979 if (verbose
&& !list
) {
980 fprintf(stderr
, "%s:\t", ifname
);
983 /* Actually do the compression/decompression. Loop over zipped members.
986 if ((*work
)(ifd
, ofd
) != OK
) {
987 method
= -1; /* force cleanup */
994 method
= get_method(ifd
);
995 if (method
< 0) break; /* error message already emitted */
998 if (close (ifd
) != 0)
1012 && ((0 <= dfd
&& fdatasync (dfd
) != 0 && errno
!= EINVAL
)
1013 || (fsync (ofd
) != 0 && errno
!= EINVAL
)))
1014 || close (ofd
) != 0)
1021 char *ifbase
= last_component (ifname
);
1022 int ufd
= atdir_eq (ifname
, ifbase
- ifname
) ? dfd
: -1;
1025 sigprocmask (SIG_BLOCK
, &caught_signals
, &oldset
);
1026 remove_ofname_fd
= -1;
1027 res
= ufd
< 0 ? xunlink (ifname
) : unlinkat (ufd
, ifbase
, 0);
1028 unlink_errno
= res
== 0 ? 0 : errno
;
1029 sigprocmask (SIG_SETMASK
, &oldset
, NULL
);
1032 WARN ((stderr
, "%s: %s: %s\n", program_name
, ifname
,
1033 strerror (unlink_errno
)));
1039 remove_output_file (false);
1043 /* Display statistics */
1046 fprintf(stderr
, " OK");
1047 } else if (decompress
) {
1048 display_ratio(bytes_out
-(bytes_in
-header_bytes
), bytes_out
,stderr
);
1050 display_ratio(bytes_in
-(bytes_out
-header_bytes
), bytes_in
, stderr
);
1053 fprintf(stderr
, " -- %s %s", keep
? "created" : "replaced with",
1055 fprintf(stderr
, "\n");
1060 volatile_strcpy (char volatile *dst
, char const volatile *src
)
1062 while ((*dst
++ = *src
++))
1066 /* ========================================================================
1067 * Create the output file. Return OK or ERROR.
1068 * Try several times if necessary to avoid truncating the z_suffix. For
1069 * example, do not create a compressed file of name "1234567890123."
1070 * Sets save_orig_name to true if the file name has been truncated.
1071 * IN assertions: the input file has already been open (ifd is set) and
1072 * ofname has already been updated if there was an original name.
1073 * OUT assertions: ifd and ofd are closed in case of error.
1078 static bool signal_handlers_installed
;
1079 int name_shortened
= 0;
1080 int flags
= (O_WRONLY
| O_CREAT
| O_EXCL
1081 | (ascii
&& decompress
? 0 : O_BINARY
));
1082 char const *base
= ofname
;
1083 int atfd
= AT_FDCWD
;
1087 char const *b
= last_component (ofname
);
1088 int f
= atdir_set (ofname
, b
- ofname
);
1096 if (!signal_handlers_installed
)
1098 signal_handlers_installed
= true;
1099 install_signal_handlers ();
1107 volatile_strcpy (remove_ofname
, ofname
);
1109 sigprocmask (SIG_BLOCK
, &caught_signals
, &oldset
);
1110 remove_ofname_fd
= ofd
= openat (atfd
, base
, flags
, S_IRUSR
| S_IWUSR
);
1112 sigprocmask (SIG_SETMASK
, &oldset
, NULL
);
1121 shorten_name (ofname
);
1127 if (check_ofname () != OK
)
1141 if (name_shortened
&& decompress
)
1143 /* name might be too long if an original name was saved */
1144 WARN ((stderr
, "%s: %s: warning, name truncated\n",
1145 program_name
, ofname
));
1151 /* ========================================================================
1152 * Return a pointer to the 'z' suffix of a file name, or NULL. For all
1153 * systems, ".gz", ".z", ".Z", ".taz", ".tgz", "-gz", "-z" and "_z" are
1154 * accepted suffixes, in addition to the value of the --suffix option.
1155 * ".tgz" is a useful convention for tar.z files on systems limited
1156 * to 3 characters extensions. On such systems, ".?z" and ".??z" are
1157 * also accepted suffixes. For Unix, we do not want to accept any
1158 * .??z suffix as indicating a compressed file; some people use .xyz
1159 * to denote volume data.
1162 get_suffix (char *name
)
1165 char suffix
[MAX_SUFFIX
+3]; /* last chars of name, forced to lower case */
1166 static char const *known_suffixes
[] =
1167 {NULL
, ".gz", ".z", ".taz", ".tgz", "-gz", "-z", "_z",
1168 #ifdef MAX_EXT_CHARS
1173 bool suffix_of_builtin
= false;
1175 /* Normally put Z_SUFFIX at the start of KNOWN_SUFFIXES, but if it
1176 is a suffix of one of them, put it at the end. */
1177 for (suf
= known_suffixes
+ 1; *suf
; suf
++)
1179 size_t suflen
= strlen (*suf
);
1180 if (z_len
< suflen
&& strequ (z_suffix
, *suf
+ suflen
- z_len
))
1182 suffix_of_builtin
= true;
1187 char *z_lower
= xstrdup(z_suffix
);
1189 known_suffixes
[suffix_of_builtin
1190 ? sizeof known_suffixes
/ sizeof *known_suffixes
- 2
1192 suf
= known_suffixes
+ suffix_of_builtin
;
1194 nlen
= strlen(name
);
1195 if (nlen
<= MAX_SUFFIX
+2) {
1196 strcpy(suffix
, name
);
1198 strcpy(suffix
, name
+nlen
-MAX_SUFFIX
-2);
1201 slen
= strlen(suffix
);
1204 int s
= strlen(*suf
);
1205 if (slen
> s
&& ! ISSLASH (suffix
[slen
- s
- 1])
1206 && strequ(suffix
+ slen
- s
, *suf
)) {
1207 match
= name
+nlen
-s
;
1210 } while (*++suf
!= NULL
);
1217 /* Open file NAME with the given flags and store its status
1218 into *ST. Return a file descriptor to the newly opened file, or -1
1219 (setting errno) on failure. */
1221 open_and_stat (char *name
, int flags
, struct stat
*st
)
1224 int atfd
= AT_FDCWD
;
1225 char const *base
= name
;
1227 /* Refuse to follow symbolic links unless -c or -f. */
1228 if (!to_stdout
&& !force
)
1230 if (HAVE_WORKING_O_NOFOLLOW
)
1231 flags
|= O_NOFOLLOW
;
1235 if (lstat (name
, st
) != 0)
1237 else if (S_ISLNK (st
->st_mode
))
1248 char const *b
= last_component (name
);
1249 int f
= atdir_set (name
, b
- name
);
1257 fd
= openat (atfd
, base
, flags
);
1258 if (0 <= fd
&& fstat (fd
, st
) != 0)
1269 /* ========================================================================
1270 * Set ifname to the input file name (with a suffix appended if necessary)
1271 * and istat to its stats. For decompression, if no file exists with the
1272 * original name, try adding successively z_suffix, .gz, .z, -z and .Z.
1273 * For MSDOS, we try only z_suffix and z.
1274 * Return an open file descriptor or -1.
1277 open_input_file (char *iname
, struct stat
*sbuf
)
1279 int ilen
; /* strlen(ifname) */
1280 int z_suffix_errno
= 0;
1281 static char const *suffixes
[] = {NULL
, ".gz", ".z", "-z", ".Z", NULL
};
1282 char const **suf
= suffixes
;
1284 #ifdef NO_MULTIPLE_DOTS
1285 char *dot
; /* pointer to ifname extension, or NULL */
1288 int open_flags
= (O_RDONLY
| O_NONBLOCK
| O_NOCTTY
1289 | (ascii
&& !decompress
? 0 : O_BINARY
));
1293 if (sizeof ifname
- 1 <= strlen (iname
))
1296 strcpy(ifname
, iname
);
1298 /* If input file exists, return OK. */
1299 fd
= open_and_stat (ifname
, open_flags
, sbuf
);
1303 if (!decompress
|| errno
!= ENOENT
) {
1307 /* File.ext doesn't exist. Try adding a suffix. */
1308 s
= get_suffix(ifname
);
1310 progerror(ifname
); /* ifname already has z suffix and does not exist */
1313 #ifdef NO_MULTIPLE_DOTS
1314 dot
= strrchr(ifname
, '.');
1316 strcat(ifname
, ".");
1317 dot
= strrchr(ifname
, '.');
1320 ilen
= strlen(ifname
);
1321 if (strequ(z_suffix
, ".gz")) suf
++;
1323 /* Search for all suffixes */
1325 char const *s0
= s
= *suf
;
1326 strcpy (ifname
, iname
);
1327 #ifdef NO_MULTIPLE_DOTS
1329 if (*dot
== '\0') strcpy (dot
, ".");
1331 #ifdef MAX_EXT_CHARS
1332 if (MAX_EXT_CHARS
< strlen (s
) + strlen (dot
+ 1))
1333 dot
[MAX_EXT_CHARS
+ 1 - strlen (s
)] = '\0';
1335 if (sizeof ifname
<= ilen
+ strlen (s
))
1338 fd
= open_and_stat (ifname
, open_flags
, sbuf
);
1341 if (errno
!= ENOENT
)
1346 if (strequ (s0
, z_suffix
))
1347 z_suffix_errno
= errno
;
1348 } while (*++suf
!= NULL
);
1350 /* No suffix found, complain using z_suffix: */
1351 strcpy(ifname
, iname
);
1352 #ifdef NO_MULTIPLE_DOTS
1353 if (*dot
== '\0') strcpy(dot
, ".");
1355 #ifdef MAX_EXT_CHARS
1356 if (MAX_EXT_CHARS
< z_len
+ strlen (dot
+ 1))
1357 dot
[MAX_EXT_CHARS
+ 1 - z_len
] = '\0';
1359 strcat(ifname
, z_suffix
);
1360 errno
= z_suffix_errno
;
1365 fprintf (stderr
, "%s: %s: file name too long\n", program_name
, iname
);
1370 /* ========================================================================
1371 * Generate ofname given ifname. Return OK, or WARNING if file must be skipped.
1372 * Sets save_orig_name to true if the file name has been truncated.
1377 char *suff
; /* ofname z suffix */
1379 strcpy(ofname
, ifname
);
1380 /* strip a version number if any and get the gzip suffix if present: */
1381 suff
= get_suffix(ofname
);
1385 /* With -t or -l, try all files (even without .gz suffix)
1386 * except with -r (behave as with just -dr).
1388 if (!recursive
&& test
)
1391 /* Avoid annoying messages with -r */
1392 if (verbose
|| (!recursive
&& !quiet
)) {
1393 WARN((stderr
,"%s: %s: unknown suffix -- ignored\n",
1394 program_name
, ifname
));
1398 /* Make a special case for .tgz and .taz: */
1400 if (strequ(suff
, ".tgz") || strequ(suff
, ".taz")) {
1401 strcpy(suff
, ".tar");
1403 *suff
= '\0'; /* strip the z suffix */
1405 /* ofname might be changed later if infile contains an original name */
1407 } else if (suff
&& ! force
) {
1408 /* Avoid annoying messages with -r (see treat_dir()) */
1409 if (verbose
|| (!recursive
&& !quiet
)) {
1410 /* Don't use WARN, as it affects exit status. */
1411 fprintf (stderr
, "%s: %s already has %s suffix -- unchanged\n",
1412 program_name
, ifname
, suff
);
1418 #ifdef NO_MULTIPLE_DOTS
1419 suff
= strrchr(ofname
, '.');
1421 if (sizeof ofname
<= strlen (ofname
) + 1)
1423 strcat(ofname
, ".");
1424 # ifdef MAX_EXT_CHARS
1425 if (strequ(z_suffix
, "z")) {
1426 if (sizeof ofname
<= strlen (ofname
) + 2)
1428 strcat(ofname
, "gz"); /* enough room */
1431 /* On the Atari and some versions of MSDOS,
1432 * ENAMETOOLONG does not work correctly. So we
1433 * must truncate here.
1435 } else if (strlen(suff
)-1 + z_len
> MAX_SUFFIX
) {
1436 suff
[MAX_SUFFIX
+1-z_len
] = '\0';
1440 #endif /* NO_MULTIPLE_DOTS */
1441 if (sizeof ofname
<= strlen (ofname
) + z_len
)
1443 strcat(ofname
, z_suffix
);
1445 } /* decompress ? */
1449 WARN ((stderr
, "%s: %s: file name too long\n", program_name
, ifname
));
1453 /* Discard NBYTES input bytes from the input, or up through the next
1454 zero byte if NBYTES == (size_t) -1. If FLAGS say that the header
1455 CRC should be computed, update the CRC accordingly. */
1457 discard_input_bytes (size_t nbytes
, unsigned int flags
)
1461 uch c
= get_byte ();
1462 if (flags
& HEADER_CRC
)
1464 if (nbytes
!= (size_t) -1)
1471 /* ========================================================================
1472 * Check the magic number of the input file and update ofname if an
1473 * original name was given and to_stdout is not set.
1474 * Return the compression method, -1 for error, -2 for warning.
1475 * Set inptr to the offset of the next byte to be processed.
1476 * Updates time_stamp if there is one and neither -m nor -n is used.
1477 * This function may be called repeatedly for an input file consisting
1478 * of several contiguous gzip'ed members.
1479 * 'in' is the input file descriptor.
1480 * IN assertions: there is at least one remaining compressed member.
1481 * If the member is a zip file, it must be the only one.
1486 uch flags
; /* compression flags */
1487 uch magic
[10]; /* magic header */
1488 int imagic0
; /* first magic byte or EOF */
1489 int imagic1
; /* like magic[1], but can represent EOF */
1490 ulg stamp
; /* timestamp */
1492 /* If --force and --stdout, zcat == cat, so do not complain about
1493 * premature end of file: use try_byte instead of get_byte.
1495 if (force
&& to_stdout
) {
1496 imagic0
= try_byte();
1498 imagic1
= try_byte ();
1500 /* If try_byte returned EOF, magic[1] == (char) EOF. */
1502 magic
[0] = get_byte ();
1505 magic
[1] = get_byte ();
1506 imagic1
= 0; /* avoid lint warning */
1508 imagic1
= try_byte ();
1512 method
= -1; /* unknown yet */
1513 part_nb
++; /* number of parts in gzip file */
1516 /* assume multiple members in gzip file except for record oriented I/O */
1518 if (memcmp(magic
, GZIP_MAGIC
, 2) == 0
1519 || memcmp(magic
, OLD_GZIP_MAGIC
, 2) == 0) {
1521 method
= (int)get_byte();
1522 if (method
!= DEFLATED
) {
1524 "%s: %s: unknown method %d -- not supported\n",
1525 program_name
, ifname
, method
);
1530 flags
= (uch
)get_byte();
1532 if ((flags
& ENCRYPTED
) != 0) {
1534 "%s: %s is encrypted -- not supported\n",
1535 program_name
, ifname
);
1539 if ((flags
& RESERVED
) != 0) {
1541 "%s: %s has flags 0x%x -- not supported\n",
1542 program_name
, ifname
, flags
);
1544 if (force
<= 1) return -1;
1546 stamp
= (ulg
)get_byte();
1547 stamp
|= ((ulg
)get_byte()) << 8;
1548 stamp
|= ((ulg
)get_byte()) << 16;
1549 stamp
|= ((ulg
)get_byte()) << 24;
1550 if (stamp
!= 0 && !no_time
)
1552 if (stamp
<= TYPE_MAXIMUM (time_t))
1554 time_stamp
.tv_sec
= stamp
;
1555 time_stamp
.tv_nsec
= 0;
1560 "%s: %s: MTIME %lu out of range for this platform\n",
1561 program_name
, ifname
, stamp
));
1562 time_stamp
.tv_sec
= TYPE_MAXIMUM (time_t);
1563 time_stamp
.tv_nsec
= TIMESPEC_RESOLUTION
- 1;
1567 magic
[8] = get_byte (); /* Ignore extra flags. */
1568 magic
[9] = get_byte (); /* Ignore OS type. */
1570 if (flags
& HEADER_CRC
)
1572 magic
[2] = DEFLATED
;
1574 magic
[4] = stamp
& 0xff;
1575 magic
[5] = (stamp
>> 8) & 0xff;
1576 magic
[6] = (stamp
>> 16) & 0xff;
1577 magic
[7] = stamp
>> 24;
1582 if ((flags
& EXTRA_FIELD
) != 0) {
1584 unsigned int len
= lenbuf
[0] = get_byte ();
1585 len
|= (lenbuf
[1] = get_byte ()) << 8;
1587 fprintf(stderr
,"%s: %s: extra field of %u bytes ignored\n",
1588 program_name
, ifname
, len
);
1590 if (flags
& HEADER_CRC
)
1592 discard_input_bytes (len
, flags
);
1595 /* Get original file name if it was truncated */
1596 if ((flags
& ORIG_NAME
) != 0) {
1597 if (no_name
|| (to_stdout
&& !list
) || part_nb
> 1) {
1598 /* Discard the old name */
1599 discard_input_bytes (-1, flags
);
1601 /* Copy the base name. Keep a directory prefix intact. */
1602 char *p
= gzip_base_name (ofname
);
1605 *p
= (char) get_byte ();
1606 if (*p
++ == '\0') break;
1607 if (p
>= ofname
+sizeof(ofname
)) {
1608 gzip_error ("corrupted input -- file name too large");
1611 if (flags
& HEADER_CRC
)
1612 updcrc ((uch
*) base
, p
- base
);
1613 p
= gzip_base_name (base
);
1614 memmove (base
, p
, strlen (p
) + 1);
1615 /* If necessary, adapt the name to local OS conventions: */
1617 MAKE_LEGAL_NAME(base
);
1618 if (base
) list
=0; /* avoid warning about unused variable */
1620 } /* no_name || to_stdout */
1623 /* Discard file comment if any */
1624 if ((flags
& COMMENT
) != 0) {
1625 discard_input_bytes (-1, flags
);
1628 if (flags
& HEADER_CRC
)
1630 unsigned int crc16
= updcrc (magic
, 0) & 0xffff;
1631 unsigned int header16
= get_byte ();
1632 header16
|= ((unsigned int) get_byte ()) << 8;
1633 if (header16
!= crc16
)
1636 "%s: %s: header checksum 0x%04x != computed checksum 0x%04x\n",
1637 program_name
, ifname
, header16
, crc16
);
1645 header_bytes
= inptr
+ 2*4; /* include crc and size */
1648 } else if (memcmp(magic
, PKZIP_MAGIC
, 2) == 0 && inptr
== 2
1649 && memcmp((char*)inbuf
, PKZIP_MAGIC
, 4) == 0) {
1650 /* To simplify the code, we support a zip file when alone only.
1651 * We are thus guaranteed that the entire local header fits in inbuf.
1655 if (check_zipfile(in
) != OK
) return -1;
1656 /* check_zipfile may get ofname from the local header */
1659 } else if (memcmp(magic
, PACK_MAGIC
, 2) == 0) {
1663 } else if (memcmp(magic
, LZW_MAGIC
, 2) == 0) {
1665 method
= COMPRESSED
;
1668 } else if (memcmp(magic
, LZH_MAGIC
, 2) == 0) {
1673 } else if (force
&& to_stdout
&& !list
) { /* pass input unchanged */
1679 if (imagic0
!= EOF
) {
1680 write_buf (STDOUT_FILENO
, magic
, 1);
1683 if (method
>= 0) return method
;
1686 fprintf (stderr
, "\n%s: %s: not in gzip format\n",
1687 program_name
, ifname
);
1694 for (inbyte
= imagic1
; inbyte
== 0; inbyte
= try_byte ())
1699 WARN ((stderr
, "\n%s: %s: decompression OK, trailing zero bytes ignored\n",
1700 program_name
, ifname
));
1705 WARN((stderr
, "\n%s: %s: decompression OK, trailing garbage ignored\n",
1706 program_name
, ifname
));
1711 /* ========================================================================
1712 * Display the characteristics of the compressed file.
1713 * If the given method is < 0, display the accumulated totals.
1714 * IN assertions: time_stamp, header_bytes and ifile_size are initialized.
1717 do_list (int method
)
1719 ulg crc
; /* original crc */
1720 static int first_time
= 1;
1721 static char const *const methods
[MAX_METHODS
] = {
1726 "", "", "", "", /* 4 to 7 reserved */
1728 int positive_off_t_width
= INT_STRLEN_BOUND (off_t
) - 1;
1730 if (first_time
&& method
>= 0) {
1733 printf("method crc date time ");
1736 printf("%*.*s %*.*s ratio uncompressed_name\n",
1737 positive_off_t_width
, positive_off_t_width
, "compressed",
1738 positive_off_t_width
, positive_off_t_width
, "uncompressed");
1740 } else if (method
< 0) {
1741 if (total_in
<= 0 || total_out
<= 0) return;
1745 if (verbose
|| !quiet
) {
1746 fprint_off(stdout
, total_in
, positive_off_t_width
);
1748 fprint_off(stdout
, total_out
, positive_off_t_width
);
1751 display_ratio(total_out
-(total_in
-header_bytes
), total_out
, stdout
);
1752 /* header_bytes is not meaningful but used to ensure the same
1753 * ratio if there is a single file.
1755 printf(" (totals)\n");
1758 crc
= (ulg
)~0; /* unknown */
1760 if (method
== DEFLATED
&& !last_member
) {
1766 static char const month_abbr
[][4]
1767 = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1768 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
1769 struct tm
*tm
= localtime (&time_stamp
.tv_sec
);
1770 printf ("%5s %08lx ", methods
[method
], crc
);
1772 printf ("%s%3d %02d:%02d ", month_abbr
[tm
->tm_mon
],
1773 tm
->tm_mday
, tm
->tm_hour
, tm
->tm_min
);
1775 printf ("??? ?? ??:?? ");
1777 fprint_off(stdout
, bytes_in
, positive_off_t_width
);
1779 fprint_off(stdout
, bytes_out
, positive_off_t_width
);
1781 if (bytes_in
== -1L) {
1783 bytes_in
= bytes_out
= header_bytes
= 0;
1784 } else if (total_in
>= 0) {
1785 total_in
+= bytes_in
;
1787 if (bytes_out
== -1L) {
1789 bytes_in
= bytes_out
= header_bytes
= 0;
1790 } else if (total_out
>= 0) {
1791 total_out
+= bytes_out
;
1793 display_ratio(bytes_out
-(bytes_in
-header_bytes
), bytes_out
, stdout
);
1794 printf(" %s\n", ofname
);
1797 /* ========================================================================
1798 * Shorten the given name by one character, or replace a .tar extension
1799 * with .tgz. Truncate the last part of the name which is longer than
1800 * MIN_PART characters: 1234.678.012.gz -> 123.678.012.gz. If the name
1801 * has only parts shorter than MIN_PART truncate the longest part.
1802 * For decompression, just remove the last character of the name.
1804 * IN assertion: for compression, the suffix of the given name is z_suffix.
1807 shorten_name (char *name
)
1809 int len
; /* length of name without z_suffix */
1810 char *trunc
= NULL
; /* character to be truncated */
1811 int plen
; /* current part length */
1812 int min_part
= MIN_PART
; /* current minimum part length */
1818 gzip_error ("name too short");
1822 p
= get_suffix(name
);
1824 gzip_error ("can't recover suffix\n");
1828 /* compress 1234567890.tar to 1234567890.tgz */
1829 if (len
> 4 && strequ(p
-4, ".tar")) {
1830 strcpy(p
-4, ".tgz");
1833 /* Try keeping short extensions intact:
1834 * 1234.678.012.gz -> 123.678.012.gz
1837 p
= last_component (name
);
1839 plen
= strcspn(p
, PART_SEP
);
1841 if (plen
> min_part
) trunc
= p
-1;
1844 } while (trunc
== NULL
&& --min_part
!= 0);
1846 if (trunc
!= NULL
) {
1848 trunc
[0] = trunc
[1];
1852 trunc
= strrchr(name
, PART_SEP
[0]);
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.
1867 /* Ask permission to overwrite the existing file */
1870 fprintf (stderr
, "%s: %s already exists;", program_name
, ofname
);
1871 if (foreground
&& (presume_input_tty
|| isatty (STDIN_FILENO
))) {
1872 fprintf(stderr
, " do you wish to overwrite (y or n)? ");
1877 fprintf(stderr
, "\tnot overwritten\n");
1878 if (exit_code
== OK
) exit_code
= WARNING
;
1882 if (xunlink (ofname
)) {
1889 /* Change the owner and group of a file. FD is a file descriptor for
1890 the file and NAME its name. Change it to user UID and to group GID.
1891 If UID or GID is -1, though, do not change the corresponding user
1893 #if ! (HAVE_FCHOWN || HAVE_CHOWN)
1894 /* The types uid_t and gid_t do not exist on mingw, so don't assume them. */
1895 # define do_chown(fd, name, uid, gid) ((void) 0)
1898 do_chown (int fd
, char const *name
, uid_t uid
, gid_t gid
)
1901 ignore_value (fchown (fd
, uid
, gid
));
1903 ignore_value (chown (name
, uid
, gid
));
1908 /* ========================================================================
1909 * Copy modes, times, ownership from input file to output file.
1910 * IN assertion: to_stdout is false.
1913 copy_stat (struct stat
*ifstat
)
1915 mode_t mode
= ifstat
->st_mode
& S_IRWXUGO
;
1920 struct timespec timespec
[2];
1921 timespec
[0] = get_stat_atime (ifstat
);
1922 timespec
[1] = get_stat_mtime (ifstat
);
1923 restoring
= (decompress
&& 0 <= time_stamp
.tv_nsec
1924 && ! (timespec
[1].tv_sec
== time_stamp
.tv_sec
1925 && timespec
[1].tv_nsec
== time_stamp
.tv_nsec
));
1927 timespec
[1] = time_stamp
;
1929 if (fdutimens (ofd
, ofname
, timespec
) == 0)
1931 if (restoring
&& 1 < verbose
) {
1932 fprintf(stderr
, "%s: timestamp restored\n", ofname
);
1936 WARN ((stderr
, "%s: %s: %s\n", program_name
, ofname
, strerror (errno
)));
1939 /* Change the group first, then the permissions, then the owner.
1940 That way, the permissions will be correct on systems that allow
1941 users to give away files, without introducing a security hole.
1942 Security depends on permissions not containing the setuid or
1945 do_chown (ofd
, ofname
, -1, ifstat
->st_gid
);
1948 r
= fchmod (ofd
, mode
);
1950 r
= chmod (ofname
, mode
);
1953 WARN ((stderr
, "%s: %s: %s\n", program_name
, ofname
, strerror (errno
)));
1955 do_chown (ofd
, ofname
, ifstat
->st_uid
, -1);
1960 /* ========================================================================
1961 * Recurse through the given directory.
1964 treat_dir (int fd
, char *dir
)
1967 char nbuf
[MAX_PATH_LEN
];
1972 dirp
= fdopendir (fd
);
1980 entries
= streamsavedir (dirp
, SAVEDIR_SORT_NONE
);
1983 if (closedir (dirp
) != 0)
1988 for (entry
= entries
; *entry
; entry
+= entrylen
+ 1) {
1989 size_t len
= strlen (dir
);
1990 entrylen
= strlen (entry
);
1991 if (strequ (entry
, ".") || strequ (entry
, ".."))
1993 if (len
+ entrylen
< MAX_PATH_LEN
- 2) {
1995 if (*last_component (nbuf
) && !ISSLASH (nbuf
[len
- 1]))
1997 strcpy (nbuf
+ len
, entry
);
2000 fprintf(stderr
,"%s: %s/%s: pathname too long\n",
2001 program_name
, dir
, entry
);
2007 #endif /* ! NO_DIR */
2009 /* Make sure signals get handled properly. */
2012 install_signal_handlers ()
2014 int nsigs
= sizeof handled_sig
/ sizeof handled_sig
[0];
2016 struct sigaction act
;
2018 sigemptyset (&caught_signals
);
2019 for (i
= 0; i
< nsigs
; i
++)
2021 sigaction (handled_sig
[i
], NULL
, &act
);
2022 if (act
.sa_handler
!= SIG_IGN
)
2023 sigaddset (&caught_signals
, handled_sig
[i
]);
2026 act
.sa_handler
= abort_gzip_signal
;
2027 act
.sa_mask
= caught_signals
;
2030 for (i
= 0; i
< nsigs
; i
++)
2031 if (sigismember (&caught_signals
, handled_sig
[i
]))
2035 sigaction (handled_sig
[i
], &act
, NULL
);
2039 /* ========================================================================
2040 * Free all dynamically allocated variables and exit with the given code.
2043 do_exit (int exitcode
)
2045 static int in_exit
= 0;
2047 if (in_exit
) exit(exitcode
);
2067 if (fclose (stdout
) != 0)
2072 /* ========================================================================
2073 * Close and unlink the output file.
2076 remove_output_file (bool signals_already_blocked
)
2081 if (!signals_already_blocked
)
2082 sigprocmask (SIG_BLOCK
, &caught_signals
, &oldset
);
2083 fd
= remove_ofname_fd
;
2086 char fname
[MAX_PATH_LEN
];
2087 remove_ofname_fd
= -1;
2089 volatile_strcpy (fname
, remove_ofname
);
2092 if (!signals_already_blocked
)
2093 sigprocmask (SIG_SETMASK
, &oldset
, NULL
);
2096 /* ========================================================================
2100 finish_up_gzip (int exitcode
)
2102 if (0 <= remove_ofname_fd
)
2103 remove_output_file (false);
2109 finish_up_gzip (ERROR
);
2111 /* ========================================================================
2115 abort_gzip_signal (int sig
)
2117 remove_output_file (true);
2118 signal (sig
, SIG_DFL
);