1 /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
2 * Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
3 * Copyright (C) 1992-1993 Jean-loup Gailly
4 * The unzip code was written and put in the public domain by Mark Adler.
5 * Portions of the lzw code are derived from the public domain 'compress'
6 * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
7 * Ken Turkowski, Dave Mack and Peter Jannesen.
9 * See the license_msg below and the file COPYING for the software license.
10 * See the file algorithm.doc for the compression algorithms and file formats.
13 static char *license_msg[] = {
14 "Copyright 2002 Free Software Foundation",
15 "Copyright 1992-1993 Jean-loup Gailly",
16 "This program comes with ABSOLUTELY NO WARRANTY.",
17 "You may redistribute copies of this program",
18 "under the terms of the GNU General Public License.",
19 "For more information about these matters, see the file named COPYING.",
22 /* Compress files with zip algorithm and 'compress' interface.
23 * See usage() and help() functions below for all options.
25 * file.gz: compressed file with same mode, owner, and utimes
26 * or stdout with -c option or if stdin used as input.
27 * If the output file name had to be truncated, the original name is kept
28 * in the compressed file.
29 * On MSDOS, file.tmp -> file.tmz. On VMS, file.tmp -> file.tmp-gz.
31 * Using gz on MSDOS would create too many file name conflicts. For
32 * example, foo.txt -> foo.tgz (.tgz must be reserved as shorthand for
33 * tar.gz). Similarly, foo.dir and foo.doc would both be mapped to foo.dgz.
34 * I also considered 12345678.txt -> 12345txt.gz but this truncates the name
35 * too heavily. There is no ideal solution given the MSDOS 8+3 limitation.
37 * For the meaning of all compilation flags, see comments in Makefile.in.
41 static char rcsid[] = "$Id: gzip.c,v 0.24 1993/06/24 10:52:07 jloup Exp $";
46 #include <sys/types.h>
62 # include <sys/time.h>
77 #if defined STDC_HEADERS || defined HAVE_STDLIB_H
85 # define NAMLEN(direct) strlen((direct)->d_name)
86 # define DIR_OPT "DIRENT"
88 # define dirent direct
89 # define NAMLEN(direct) ((direct)->d_namlen)
90 # ifdef HAVE_SYS_NDIR_H
91 # include <sys/ndir.h>
92 # define DIR_OPT "SYS_NDIR"
94 # ifdef HAVE_SYS_DIR_H
96 # define DIR_OPT "SYS_DIR"
100 # define DIR_OPT "NDIR"
103 # define DIR_OPT "NO_DIR"
111 # define CLOSEDIR(d) (closedir(d), 0)
113 # define CLOSEDIR(d) closedir(d)
116 #if !defined(HAVE_LSTAT) && !defined(lstat)
117 # define lstat(name, buf) stat(name, buf)
123 # define TIME_OPT "UTIME"
125 # ifdef HAVE_SYS_UTIME_H
126 # include <sys/utime.h>
127 # define TIME_OPT "SYS_UTIME"
133 # define TIME_OPT "STRUCT_UTIMBUF"
137 # define TIME_OPT "NO_UTIME"
140 #if !defined(S_ISDIR) && defined(S_IFDIR)
141 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
143 #if !defined(S_ISREG) && defined(S_IFREG)
144 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
147 typedef RETSIGTYPE (*sig_type) OF((int));
150 # define O_BINARY 0 /* creation mode for open() */
154 /* Pure BSD system? */
155 # include <sys/file.h>
157 # define O_CREAT FCREAT
160 # define O_EXCL FEXCL
165 # define S_IRUSR 0400
168 # define S_IWUSR 0200
170 #define RW_USER (S_IRUSR | S_IWUSR) /* creation mode for open() */
173 # define MAX_PATH_LEN 1024 /* max pathname length */
185 off_t lseek OF((int fd, off_t offset, int whence));
189 #define OFF_T_MIN (~ (off_t) 0 << (sizeof (off_t) * CHAR_BIT - 1))
193 #define OFF_T_MAX (~ (off_t) 0 - OFF_T_MIN)
196 /* Separator for file name parts (see shorten_name()) */
197 #ifdef NO_MULTIPLE_DOTS
198 # define PART_SEP "-"
200 # define PART_SEP "."
205 DECLARE(uch, inbuf, INBUFSIZ +INBUF_EXTRA);
206 DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
207 DECLARE(ush, d_buf, DIST_BUFSIZE);
208 DECLARE(uch, window, 2L*WSIZE);
210 DECLARE(ush, tab_prefix, 1L<<BITS);
212 DECLARE(ush, tab_prefix0, 1L<<(BITS-1));
213 DECLARE(ush, tab_prefix1, 1L<<(BITS-1));
216 /* local variables */
218 int ascii = 0; /* convert end-of-lines to local OS conventions */
219 int to_stdout = 0; /* output to stdout (-c) */
220 int decompress = 0; /* decompress (-d) */
221 int force = 0; /* don't ask questions, compress links (-f) */
222 int no_name = -1; /* don't save or restore the original file name */
223 int no_time = -1; /* don't save or restore the original file time */
224 int recursive = 0; /* recurse through directories (-r) */
225 int list = 0; /* list the file contents (-l) */
226 int verbose = 0; /* be verbose (-v) */
227 int quiet = 0; /* be very quiet (-q) */
228 int do_lzw = 0; /* generate output compatible with old compress (-Z) */
229 int test = 0; /* test .gz file integrity */
230 int foreground; /* set if program run in foreground */
231 char *progname; /* program name */
232 int maxbits = BITS; /* max bits per code for LZW */
233 int method = DEFLATED;/* compression method */
234 int level = 6; /* compression level */
235 int exit_code = OK; /* program exit code */
236 int save_orig_name; /* set if original name must be saved */
237 int last_member; /* set for .zip and .Z files */
238 int part_nb; /* number of parts in .gz file */
239 time_t time_stamp; /* original time stamp (modification time) */
240 off_t ifile_size; /* input file size, -1 for devices (debug only) */
241 char *env; /* contents of GZIP env variable */
242 char **args = NULL; /* argv pointer if GZIP env variable defined */
243 char *z_suffix; /* default suffix (can be set with --suffix) */
244 size_t z_len; /* strlen(z_suffix) */
246 off_t bytes_in; /* number of input bytes */
247 off_t bytes_out; /* number of output bytes */
248 off_t total_in; /* input bytes for all files */
249 off_t total_out; /* output bytes for all files */
250 char ifname[MAX_PATH_LEN]; /* input file name */
251 char ofname[MAX_PATH_LEN]; /* output file name */
252 int remove_ofname = 0; /* remove output file on error */
253 struct stat istat; /* status for input file */
254 int ifd; /* input file descriptor */
255 int ofd; /* output file descriptor */
256 unsigned insize; /* valid bytes in inbuf */
257 unsigned inptr; /* index of next byte to be processed in inbuf */
258 unsigned outcnt; /* bytes in output buffer */
260 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 {"list", 0, 0, 'l'}, /* list .gz file contents */
273 {"license", 0, 0, 'L'}, /* display software license */
274 {"no-name", 0, 0, 'n'}, /* don't save or restore original name & time */
275 {"name", 0, 0, 'N'}, /* save or restore original name & time */
276 {"quiet", 0, 0, 'q'}, /* quiet mode */
277 {"silent", 0, 0, 'q'}, /* quiet mode */
278 {"recursive", 0, 0, 'r'}, /* recurse through directories */
279 {"suffix", 1, 0, 'S'}, /* use given suffix instead of .gz */
280 {"test", 0, 0, 't'}, /* test compressed file integrity */
281 {"no-time", 0, 0, 'T'}, /* don't save or restore the time stamp */
282 {"verbose", 0, 0, 'v'}, /* verbose mode */
283 {"version", 0, 0, 'V'}, /* display version number */
284 {"fast", 0, 0, '1'}, /* compress faster */
285 {"best", 0, 0, '9'}, /* compress better */
286 {"lzw", 0, 0, 'Z'}, /* make output compatible with old compress */
287 {"bits", 1, 0, 'b'}, /* max number of bits per code (implies -Z) */
291 /* local functions */
293 local void usage OF((void));
294 local void help OF((void));
295 local void license OF((void));
296 local void version OF((void));
297 local int input_eof OF((void));
298 local void treat_stdin OF((void));
299 local void treat_file OF((char *iname));
300 local int create_outfile OF((void));
301 local int do_stat OF((char *name, struct stat *sbuf));
302 local char *get_suffix OF((char *name));
303 local int get_istat OF((char *iname, struct stat *sbuf));
304 local int make_ofname OF((void));
305 local int same_file OF((struct stat *stat1, struct stat *stat2));
306 local int name_too_long OF((char *name, struct stat *statb));
307 local void shorten_name OF((char *name));
308 local int get_method OF((int in));
309 local void do_list OF((int ifd, int method));
310 local int check_ofname OF((void));
311 local void copy_stat OF((struct stat *ifstat));
312 local void do_exit OF((int exitcode));
313 int main OF((int argc, char **argv));
314 int (*work) OF((int infile, int outfile)) = zip; /* function to call */
317 local void treat_dir OF((char *dir));
320 local void reset_times OF((char *name, struct stat *statb));
323 #define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
325 /* ======================================================================== */
328 printf ("usage: %s [-%scdfhlLnN%stvV19] [-S suffix] [file ...]\n",
330 O_BINARY ? "a" : "", NO_DIR ? "" : "r");
333 /* ======================================================================== */
336 static char *help_msg[] = {
338 " -a --ascii ascii text; convert end-of-lines using local conventions",
340 " -c --stdout write on standard output, keep original files unchanged",
341 " -d --decompress decompress",
342 /* -e --encrypt encrypt */
343 " -f --force force overwrite of output file and compress links",
344 " -h --help give this help",
345 /* -k --pkzip force output in pkzip format */
346 " -l --list list compressed file contents",
347 " -L --license display software license",
349 " -m --no-time do not save or restore the original modification time",
350 " -M --time save or restore the original modification time",
352 " -n --no-name do not save or restore the original name and time stamp",
353 " -N --name save or restore the original name and time stamp",
354 " -q --quiet suppress all warnings",
356 " -r --recursive operate recursively on directories",
358 " -S .suf --suffix .suf use suffix .suf on compressed files",
359 " -t --test test compressed file integrity",
360 " -v --verbose verbose mode",
361 " -V --version display version number",
362 " -1 --fast compress faster",
363 " -9 --best compress better",
365 " -Z --lzw produce output compatible with old compress",
366 " -b --bits maxbits max number of bits per code (implies -Z)",
368 " file... files to (de)compress. If none given, use standard input.",
369 "Report bugs to <bug-gzip@gnu.org>.",
373 printf ("%s %s\n(%s)\n", progname, VERSION, REVDATE);
375 while (*p) printf ("%s\n", *p++);
378 /* ======================================================================== */
381 char **p = license_msg;
383 printf ("%s %s\n(%s)\n", progname, VERSION, REVDATE);
384 while (*p) printf ("%s\n", *p++);
387 /* ======================================================================== */
391 printf ("Compilation options:\n%s %s ", DIR_OPT, TIME_OPT);
393 printf ("STDC_HEADERS ");
396 printf ("HAVE_UNISTD_H ");
399 printf ("HAVE_MEMORY_H ");
402 printf ("HAVE_STRING_H ");
405 printf ("HAVE_LSTAT ");
407 #ifdef NO_MULTIPLE_DOTS
408 printf ("NO_MULTIPLE_DOTS ");
411 printf ("HAVE_CHOWN ");
423 printf ("DYN_ALLOC ");
426 printf ("MAXSEG_64K");
429 printf ("Written by Jean-loup Gailly.\n");
432 local void progerror (string)
436 fprintf(stderr, "%s: ", progname);
442 /* ======================================================================== */
443 int main (argc, argv)
447 int file_count; /* number of files to precess */
448 int proglen; /* length of progname */
449 int optc; /* current option */
451 EXPAND(argc, argv); /* wild card expansion if necessary */
453 progname = base_name (argv[0]);
454 proglen = strlen(progname);
456 /* Suppress .exe for MSDOS, OS/2 and VMS: */
457 if (proglen > 4 && strequ(progname+proglen-4, ".exe")) {
458 progname[proglen-4] = '\0';
461 /* Add options in GZIP environment variable if there is one */
462 env = add_envopt(&argc, &argv, OPTIONS_VAR);
463 if (env != NULL) args = argv;
465 foreground = signal(SIGINT, SIG_IGN) != SIG_IGN;
467 (void) signal (SIGINT, (sig_type)abort_gzip);
470 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
471 (void) signal(SIGTERM, (sig_type)abort_gzip);
475 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
476 (void) signal(SIGHUP, (sig_type)abort_gzip);
481 /* For compatibility with old compress, use program name as an option.
482 * If you compile with -DGNU_STANDARD, this program will behave as
483 * gzip even if it is invoked under the name gunzip or zcat.
485 * Systems which do not support links can still use -d or -dc.
486 * Ignore an .exe extension for MSDOS, OS/2 and VMS.
488 if ( strncmp(progname, "un", 2) == 0 /* ungzip, uncompress */
489 || strncmp(progname, "gun", 3) == 0) { /* gunzip */
491 } else if (strequ(progname+1, "cat") /* zcat, pcat, gcat */
492 || strequ(progname, "gzcat")) { /* gzcat */
493 decompress = to_stdout = 1;
498 z_len = strlen(z_suffix);
500 while ((optc = getopt_long (argc, argv, "ab:cdfhH?lLmMnNqrS:tvVZ123456789",
501 longopts, (int *)0)) != -1) {
506 maxbits = atoi(optarg);
507 for (; *optarg; optarg++)
508 if (! ('0' <= *optarg && *optarg <= '9'))
510 fprintf (stderr, "%s: -b operand is not an integer\n",
517 to_stdout = 1; break;
519 decompress = 1; break;
522 case 'h': case 'H': case '?':
523 help(); do_exit(OK); break;
525 list = decompress = to_stdout = 1; break;
527 license(); do_exit(OK); break;
528 case 'm': /* undocumented, may change later */
530 case 'M': /* undocumented, may change later */
533 no_name = no_time = 1; break;
535 no_name = no_time = 0; break;
537 quiet = 1; verbose = 0; break;
540 fprintf(stderr, "%s: -r not supported on this system\n", progname);
542 do_exit(ERROR); break;
544 recursive = 1; break;
547 #ifdef NO_MULTIPLE_DOTS
548 if (*optarg == '.') optarg++;
550 z_len = strlen(optarg);
554 test = decompress = to_stdout = 1;
557 verbose++; quiet = 0; break;
559 version(); do_exit(OK); break;
564 fprintf(stderr, "%s: -Z not supported in this version\n",
567 do_exit(ERROR); break;
569 case '1': case '2': case '3': case '4':
570 case '5': case '6': case '7': case '8': case '9':
574 /* Error message already emitted by getopt_long. */
578 } /* loop on all arguments */
581 /* Ignore "Broken Pipe" message with --quiet */
582 if (quiet && signal (SIGPIPE, SIG_IGN) != SIG_IGN)
583 signal (SIGPIPE, (sig_type) abort_gzip);
586 /* By default, save name and timestamp on compression but do not
587 * restore them on decompression.
589 if (no_time < 0) no_time = decompress;
590 if (no_name < 0) no_name = decompress;
592 file_count = argc - optind;
596 if (ascii && !quiet) {
597 fprintf(stderr, "%s: option --ascii ignored on this system\n",
601 if ((z_len == 0 && !decompress) || z_len > MAX_SUFFIX) {
602 fprintf(stderr, "%s: incorrect suffix '%s'\n",
606 if (do_lzw && !decompress) work = lzw;
608 /* Allocate all global buffers (for DYN_ALLOC option) */
609 ALLOC(uch, inbuf, INBUFSIZ +INBUF_EXTRA);
610 ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
611 ALLOC(ush, d_buf, DIST_BUFSIZE);
612 ALLOC(uch, window, 2L*WSIZE);
614 ALLOC(ush, tab_prefix, 1L<<BITS);
616 ALLOC(ush, tab_prefix0, 1L<<(BITS-1));
617 ALLOC(ush, tab_prefix1, 1L<<(BITS-1));
620 /* And get to work */
621 if (file_count != 0) {
622 if (to_stdout && !test && !list && (!decompress || !ascii)) {
623 SET_BINARY_MODE(fileno(stdout));
625 while (optind < argc) {
626 treat_file(argv[optind++]);
628 } else { /* Standard input */
631 if (list && !quiet && file_count > 1) {
632 do_list(-1, -1); /* print totals */
635 return exit_code; /* just to avoid lint warning */
638 /* Return nonzero when at end of file on input. */
642 if (!decompress || last_member)
647 if (insize != INBUFSIZ || fill_inbuf (1) == EOF)
650 /* Unget the char that fill_inbuf got. */
657 /* ========================================================================
658 * Compress or decompress stdin
660 local void treat_stdin()
662 if (!force && !list &&
663 isatty(fileno((FILE *)(decompress ? stdin : stdout)))) {
664 /* Do not send compressed data to the terminal or read it from
665 * the terminal. We get here when user invoked the program
666 * without parameters, so be helpful. According to the GNU standards:
668 * If there is one behavior you think is most useful when the output
669 * is to a terminal, and another that you think is most useful when
670 * the output is a file or a pipe, then it is usually best to make
671 * the default behavior the one that is useful with output to a
672 * terminal, and have an option for the other behavior.
674 * Here we use the --force option to get the other behavior.
677 "%s: compressed data not %s a terminal. Use -f to force %scompression.\n",
678 progname, decompress ? "read from" : "written to",
679 decompress ? "de" : "");
680 fprintf(stderr,"For help, type: %s -h\n", progname);
684 if (decompress || !ascii) {
685 SET_BINARY_MODE(fileno(stdin));
687 if (!test && !list && (!decompress || !ascii)) {
688 SET_BINARY_MODE(fileno(stdout));
690 strcpy(ifname, "stdin");
691 strcpy(ofname, "stdout");
693 /* Get the time stamp on the input file. */
694 time_stamp = 0; /* time unknown by default */
696 #ifndef NO_STDIN_FSTAT
697 if (list || !no_time) {
698 if (fstat(fileno(stdin), &istat) != 0) {
699 progerror("standard input");
702 # ifdef NO_PIPE_TIMESTAMP
703 if (S_ISREG(istat.st_mode))
705 time_stamp = istat.st_mtime;
706 #endif /* NO_STDIN_FSTAT */
708 ifile_size = -1L; /* convention for unknown size */
710 clear_bufs(); /* clear input and output buffers */
715 method = get_method(ifd);
717 do_exit(exit_code); /* error message already emitted */
721 do_list(ifd, method);
725 /* Actually do the compression/decompression. Loop over zipped members.
728 if ((*work)(fileno(stdin), fileno(stdout)) != OK) return;
733 method = get_method(ifd);
734 if (method < 0) return; /* error message already emitted */
735 bytes_out = 0; /* required for length check */
740 fprintf(stderr, " OK\n");
742 } else if (!decompress) {
743 display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
744 fprintf(stderr, "\n");
745 #ifdef DISPLAY_STDIN_RATIO
747 display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
748 fprintf(stderr, "\n");
754 /* ========================================================================
755 * Compress or decompress the given file
757 local void treat_file(iname)
760 /* Accept "-" as synonym for stdin */
761 if (strequ(iname, "-")) {
762 int cflag = to_stdout;
768 /* Check if the input file is present, set ifname and istat: */
769 if (get_istat(iname, &istat) != OK) return;
771 /* If the input name is that of a directory, recurse or ignore: */
772 if (S_ISDIR(istat.st_mode)) {
778 /* Warning: ifname is now garbage */
780 reset_times (iname, &st);
784 WARN((stderr,"%s: %s is a directory -- ignored\n", progname, ifname));
787 if (!S_ISREG(istat.st_mode)) {
789 "%s: %s is not a directory or a regular file - ignored\n",
793 if (istat.st_nlink > 1 && !to_stdout && !force) {
794 WARN((stderr, "%s: %s has %lu other link%c -- unchanged\n",
795 progname, ifname, (unsigned long) istat.st_nlink - 1,
796 istat.st_nlink > 2 ? 's' : ' '));
800 ifile_size = istat.st_size;
801 time_stamp = no_time && !list ? 0 : istat.st_mtime;
803 /* Generate output file name. For -r and (-t or -l), skip files
804 * without a valid gzip suffix (check done in make_ofname).
806 if (to_stdout && !list && !test) {
807 strcpy(ofname, "stdout");
809 } else if (make_ofname() != OK) {
813 /* Open the input file and determine compression method. The mode
814 * parameter is ignored but required by some systems (VMS) and forbidden
815 * on other systems (MacOS).
817 ifd = OPEN(ifname, ascii && !decompress ? O_RDONLY : O_RDONLY | O_BINARY,
823 clear_bufs(); /* clear input and output buffers */
827 method = get_method(ifd); /* updates ofname if original given */
830 return; /* error message already emitted */
834 do_list(ifd, method);
839 /* If compressing to a file, check if ofname is not ambiguous
840 * because the operating system truncates names. Otherwise, generate
841 * a new ofname and save the original name in the compressed file.
844 ofd = fileno(stdout);
845 /* keep remove_ofname as zero */
847 if (create_outfile() != OK) return;
849 if (!decompress && save_orig_name && !verbose && !quiet) {
850 fprintf(stderr, "%s: %s compressed to %s\n",
851 progname, ifname, ofname);
854 /* Keep the name even if not truncated except with --no-name: */
855 if (!save_orig_name) save_orig_name = !no_name;
858 fprintf(stderr, "%s:\t", ifname);
861 /* Actually do the compression/decompression. Loop over zipped members.
864 if ((*work)(ifd, ofd) != OK) {
865 method = -1; /* force cleanup */
872 method = get_method(ifd);
873 if (method < 0) break; /* error message already emitted */
874 bytes_out = 0; /* required for length check */
878 if (!to_stdout && close(ofd)) {
882 if (!to_stdout) xunlink (ofname);
885 /* Display statistics */
888 fprintf(stderr, " OK");
889 } else if (decompress) {
890 display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
892 display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
894 if (!test && !to_stdout) {
895 fprintf(stderr, " -- replaced with %s", ofname);
897 fprintf(stderr, "\n");
899 /* Copy modes, times, ownership, and remove the input file */
905 /* ========================================================================
906 * Create the output file. Return OK or ERROR.
907 * Try several times if necessary to avoid truncating the z_suffix. For
908 * example, do not create a compressed file of name "1234567890123."
909 * Sets save_orig_name to true if the file name has been truncated.
910 * IN assertions: the input file has already been open (ifd is set) and
911 * ofname has already been updated if there was an original name.
912 * OUT assertions: ifd and ofd are closed in case of error.
914 local int create_outfile()
916 struct stat ostat; /* stat for ofname */
917 int flags = O_WRONLY | O_CREAT | O_EXCL | O_BINARY;
919 if (ascii && decompress) {
920 flags &= ~O_BINARY; /* force ascii text mode */
923 /* Make sure that ofname is not an existing file */
924 if (check_ofname() != OK) {
928 /* Create the output file */
930 ofd = OPEN(ofname, flags, RW_USER);
937 /* Check for name truncation on new file (1234567890123.gz) */
939 if (stat(ofname, &ostat) != 0) {
941 if (fstat(ofd, &ostat) != 0) {
944 close(ifd); close(ofd);
948 if (!name_too_long(ofname, &ostat)) return OK;
951 /* name might be too long if an original name was saved */
952 WARN((stderr, "%s: %s: warning, name truncated\n",
958 #ifdef NO_MULTIPLE_DOTS
959 /* Should never happen, see check_ofname() */
960 fprintf(stderr, "%s: %s: name too long\n", progname, ofname);
963 shorten_name(ofname);
967 /* ========================================================================
968 * Use lstat if available, except for -c or -f. Use stat otherwise.
969 * This allows links when not removing the original file.
971 local int do_stat(name, sbuf)
976 if (!to_stdout && !force) {
977 return lstat(name, sbuf);
979 return stat(name, sbuf);
982 /* ========================================================================
983 * Return a pointer to the 'z' suffix of a file name, or NULL. For all
984 * systems, ".gz", ".z", ".Z", ".taz", ".tgz", "-gz", "-z" and "_z" are
985 * accepted suffixes, in addition to the value of the --suffix option.
986 * ".tgz" is a useful convention for tar.z files on systems limited
987 * to 3 characters extensions. On such systems, ".?z" and ".??z" are
988 * also accepted suffixes. For Unix, we do not want to accept any
989 * .??z suffix as indicating a compressed file; some people use .xyz
990 * to denote volume data.
991 * On systems allowing multiple versions of the same file (such as VMS),
992 * this function removes any version suffix in the given name.
994 local char *get_suffix(name)
998 char suffix[MAX_SUFFIX+3]; /* last chars of name, forced to lower case */
999 static char *known_suffixes[] =
1000 {NULL, ".gz", ".z", ".taz", ".tgz", "-gz", "-z", "_z",
1001 #ifdef MAX_EXT_CHARS
1005 char **suf = known_suffixes;
1008 if (strequ(z_suffix, "z")) suf++; /* check long suffixes first */
1011 /* strip a version number from the file name */
1013 char *v = strrchr(name, SUFFIX_SEP);
1014 if (v != NULL) *v = '\0';
1017 nlen = strlen(name);
1018 if (nlen <= MAX_SUFFIX+2) {
1019 strcpy(suffix, name);
1021 strcpy(suffix, name+nlen-MAX_SUFFIX-2);
1024 slen = strlen(suffix);
1026 int s = strlen(*suf);
1027 if (slen > s && suffix[slen-s-1] != PATH_SEP
1028 && strequ(suffix + slen - s, *suf)) {
1031 } while (*++suf != NULL);
1037 /* ========================================================================
1038 * Set ifname to the input file name (with a suffix appended if necessary)
1039 * and istat to its stats. For decompression, if no file exists with the
1040 * original name, try adding successively z_suffix, .gz, .z, -z and .Z.
1041 * For MSDOS, we try only z_suffix and z.
1042 * Return OK or ERROR.
1044 local int get_istat(iname, sbuf)
1048 int ilen; /* strlen(ifname) */
1049 int z_suffix_errno = 0;
1050 static char *suffixes[] = {NULL, ".gz", ".z", "-z", ".Z", NULL};
1051 char **suf = suffixes;
1053 #ifdef NO_MULTIPLE_DOTS
1054 char *dot; /* pointer to ifname extension, or NULL */
1059 if (sizeof ifname - 1 <= strlen (iname))
1062 strcpy(ifname, iname);
1064 /* If input file exists, return OK. */
1065 if (do_stat(ifname, sbuf) == 0) return OK;
1067 if (!decompress || errno != ENOENT) {
1071 /* file.ext doesn't exist, try adding a suffix (after removing any
1072 * version number for VMS).
1074 s = get_suffix(ifname);
1076 progerror(ifname); /* ifname already has z suffix and does not exist */
1079 #ifdef NO_MULTIPLE_DOTS
1080 dot = strrchr(ifname, '.');
1082 strcat(ifname, ".");
1083 dot = strrchr(ifname, '.');
1086 ilen = strlen(ifname);
1087 if (strequ(z_suffix, ".gz")) suf++;
1089 /* Search for all suffixes */
1091 char *s0 = s = *suf;
1092 strcpy (ifname, iname);
1093 #ifdef NO_MULTIPLE_DOTS
1095 if (*dot == '\0') strcpy (dot, ".");
1097 #ifdef MAX_EXT_CHARS
1098 if (MAX_EXT_CHARS < strlen (s) + strlen (dot + 1))
1099 dot[MAX_EXT_CHARS + 1 - strlen (s)] = '\0';
1101 if (sizeof ifname <= ilen + strlen (s))
1104 if (do_stat(ifname, sbuf) == 0) return OK;
1105 if (strequ (s0, z_suffix))
1106 z_suffix_errno = errno;
1107 } while (*++suf != NULL);
1109 /* No suffix found, complain using z_suffix: */
1110 strcpy(ifname, iname);
1111 #ifdef NO_MULTIPLE_DOTS
1112 if (*dot == '\0') strcpy(dot, ".");
1114 #ifdef MAX_EXT_CHARS
1115 if (MAX_EXT_CHARS < z_len + strlen (dot + 1))
1116 dot[MAX_EXT_CHARS + 1 - z_len] = '\0';
1118 strcat(ifname, z_suffix);
1119 errno = z_suffix_errno;
1124 fprintf (stderr, "%s: %s: file name too long\n", progname, iname);
1129 /* ========================================================================
1130 * Generate ofname given ifname. Return OK, or WARNING if file must be skipped.
1131 * Sets save_orig_name to true if the file name has been truncated.
1133 local int make_ofname()
1135 char *suff; /* ofname z suffix */
1137 strcpy(ofname, ifname);
1138 /* strip a version number if any and get the gzip suffix if present: */
1139 suff = get_suffix(ofname);
1143 /* With -t or -l, try all files (even without .gz suffix)
1144 * except with -r (behave as with just -dr).
1146 if (!recursive && (list || test)) return OK;
1148 /* Avoid annoying messages with -r */
1149 if (verbose || (!recursive && !quiet)) {
1150 WARN((stderr,"%s: %s: unknown suffix -- ignored\n",
1155 /* Make a special case for .tgz and .taz: */
1157 if (strequ(suff, ".tgz") || strequ(suff, ".taz")) {
1158 strcpy(suff, ".tar");
1160 *suff = '\0'; /* strip the z suffix */
1162 /* ofname might be changed later if infile contains an original name */
1164 } else if (suff != NULL) {
1165 /* Avoid annoying messages with -r (see treat_dir()) */
1166 if (verbose || (!recursive && !quiet)) {
1167 WARN((stderr, "%s: %s already has %s suffix -- unchanged\n",
1168 progname, ifname, suff));
1174 #ifdef NO_MULTIPLE_DOTS
1175 suff = strrchr(ofname, '.');
1177 if (sizeof ofname <= strlen (ofname) + 1)
1179 strcat(ofname, ".");
1180 # ifdef MAX_EXT_CHARS
1181 if (strequ(z_suffix, "z")) {
1182 if (sizeof ofname <= strlen (ofname) + 2)
1184 strcat(ofname, "gz"); /* enough room */
1187 /* On the Atari and some versions of MSDOS, name_too_long()
1188 * does not work correctly because of a bug in stat(). So we
1189 * must truncate here.
1191 } else if (strlen(suff)-1 + z_len > MAX_SUFFIX) {
1192 suff[MAX_SUFFIX+1-z_len] = '\0';
1196 #endif /* NO_MULTIPLE_DOTS */
1197 if (sizeof ofname <= strlen (ofname) + z_len)
1199 strcat(ofname, z_suffix);
1201 } /* decompress ? */
1205 WARN ((stderr, "%s: %s: file name too long\n", progname, ifname));
1210 /* ========================================================================
1211 * Check the magic number of the input file and update ofname if an
1212 * original name was given and to_stdout is not set.
1213 * Return the compression method, -1 for error, -2 for warning.
1214 * Set inptr to the offset of the next byte to be processed.
1215 * Updates time_stamp if there is one and --no-time is not used.
1216 * This function may be called repeatedly for an input file consisting
1217 * of several contiguous gzip'ed members.
1218 * IN assertions: there is at least one remaining compressed member.
1219 * If the member is a zip file, it must be the only one.
1221 local int get_method(in)
1222 int in; /* input file descriptor */
1224 uch flags; /* compression flags */
1225 char magic[2]; /* magic header */
1226 int imagic1; /* like magic[1], but can represent EOF */
1227 ulg stamp; /* time stamp */
1229 /* If --force and --stdout, zcat == cat, so do not complain about
1230 * premature end of file: use try_byte instead of get_byte.
1232 if (force && to_stdout) {
1233 magic[0] = (char)try_byte();
1234 imagic1 = try_byte ();
1235 magic[1] = (char) imagic1;
1236 /* If try_byte returned EOF, magic[1] == (char) EOF. */
1238 magic[0] = (char)get_byte();
1239 magic[1] = (char)get_byte();
1240 imagic1 = 0; /* avoid lint warning */
1242 method = -1; /* unknown yet */
1243 part_nb++; /* number of parts in gzip file */
1245 last_member = RECORD_IO;
1246 /* assume multiple members in gzip file except for record oriented I/O */
1248 if (memcmp(magic, GZIP_MAGIC, 2) == 0
1249 || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
1251 method = (int)get_byte();
1252 if (method != DEFLATED) {
1254 "%s: %s: unknown method %d -- not supported\n",
1255 progname, ifname, method);
1260 flags = (uch)get_byte();
1262 if ((flags & ENCRYPTED) != 0) {
1264 "%s: %s is encrypted -- not supported\n",
1269 if ((flags & CONTINUATION) != 0) {
1271 "%s: %s is a a multi-part gzip file -- not supported\n",
1274 if (force <= 1) return -1;
1276 if ((flags & RESERVED) != 0) {
1278 "%s: %s has flags 0x%x -- not supported\n",
1279 progname, ifname, flags);
1281 if (force <= 1) return -1;
1283 stamp = (ulg)get_byte();
1284 stamp |= ((ulg)get_byte()) << 8;
1285 stamp |= ((ulg)get_byte()) << 16;
1286 stamp |= ((ulg)get_byte()) << 24;
1287 if (stamp != 0 && !no_time) time_stamp = stamp;
1289 (void)get_byte(); /* Ignore extra flags for the moment */
1290 (void)get_byte(); /* Ignore OS type for the moment */
1292 if ((flags & CONTINUATION) != 0) {
1293 unsigned part = (unsigned)get_byte();
1294 part |= ((unsigned)get_byte())<<8;
1296 fprintf(stderr,"%s: %s: part number %u\n",
1297 progname, ifname, part);
1300 if ((flags & EXTRA_FIELD) != 0) {
1301 unsigned len = (unsigned)get_byte();
1302 len |= ((unsigned)get_byte())<<8;
1304 fprintf(stderr,"%s: %s: extra field of %u bytes ignored\n",
1305 progname, ifname, len);
1307 while (len--) (void)get_byte();
1310 /* Get original file name if it was truncated */
1311 if ((flags & ORIG_NAME) != 0) {
1312 if (no_name || (to_stdout && !list) || part_nb > 1) {
1313 /* Discard the old name */
1314 char c; /* dummy used for NeXTstep 3.0 cc optimizer bug */
1315 do {c=get_byte();} while (c != 0);
1317 /* Copy the base name. Keep a directory prefix intact. */
1318 char *p = base_name (ofname);
1321 *p = (char)get_char();
1322 if (*p++ == '\0') break;
1323 if (p >= ofname+sizeof(ofname)) {
1324 error("corrupted input -- file name too large");
1327 /* If necessary, adapt the name to local OS conventions: */
1329 MAKE_LEGAL_NAME(base);
1330 if (base) list=0; /* avoid warning about unused variable */
1332 } /* no_name || to_stdout */
1335 /* Discard file comment if any */
1336 if ((flags & COMMENT) != 0) {
1337 while (get_char() != 0) /* null */ ;
1340 header_bytes = inptr + 2*sizeof(long); /* include crc and size */
1343 } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
1344 && memcmp((char*)inbuf, PKZIP_MAGIC, 4) == 0) {
1345 /* To simplify the code, we support a zip file when alone only.
1346 * We are thus guaranteed that the entire local header fits in inbuf.
1350 if (check_zipfile(in) != OK) return -1;
1351 /* check_zipfile may get ofname from the local header */
1354 } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
1358 } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {
1360 method = COMPRESSED;
1363 } else if (memcmp(magic, LZH_MAGIC, 2) == 0) {
1368 } else if (force && to_stdout && !list) { /* pass input unchanged */
1374 if (method >= 0) return method;
1377 fprintf(stderr, "\n%s: %s: not in gzip format\n", progname, ifname);
1384 for (inbyte = imagic1; inbyte == 0; inbyte = try_byte ())
1389 WARN ((stderr, "\n%s: %s: decompression OK, trailing zero bytes ignored\n",
1395 WARN((stderr, "\n%s: %s: decompression OK, trailing garbage ignored\n",
1401 /* ========================================================================
1402 * Display the characteristics of the compressed file.
1403 * If the given method is < 0, display the accumulated totals.
1404 * IN assertions: time_stamp, header_bytes and ifile_size are initialized.
1406 local void do_list(ifd, method)
1407 int ifd; /* input file descriptor */
1408 int method; /* compression method */
1410 ulg crc; /* original crc */
1411 static int first_time = 1;
1412 static char* methods[MAX_METHODS] = {
1417 "", "", "", "", /* 4 to 7 reserved */
1420 int positive_off_t_width = 1;
1423 for (o = OFF_T_MAX; 9 < o; o /= 10) {
1424 positive_off_t_width++;
1427 if (first_time && method >= 0) {
1430 printf("method crc date time ");
1433 printf("%*.*s %*.*s ratio uncompressed_name\n",
1434 positive_off_t_width, positive_off_t_width, "compressed",
1435 positive_off_t_width, positive_off_t_width, "uncompressed");
1437 } else if (method < 0) {
1438 if (total_in <= 0 || total_out <= 0) return;
1442 if (verbose || !quiet) {
1443 fprint_off(stdout, total_in, positive_off_t_width);
1445 fprint_off(stdout, total_out, positive_off_t_width);
1448 display_ratio(total_out-(total_in-header_bytes), total_out, stdout);
1449 /* header_bytes is not meaningful but used to ensure the same
1450 * ratio if there is a single file.
1452 printf(" (totals)\n");
1455 crc = (ulg)~0; /* unknown */
1457 bytes_in = ifile_size;
1460 if (method == DEFLATED && !last_member) {
1461 /* Get the crc and uncompressed size for gzip'ed (not zip'ed) files.
1462 * If the lseek fails, we could use read() to get to the end, but
1463 * --list is used to get quick results.
1464 * Use "gunzip < foo.gz | wc -c" to get the uncompressed size if
1465 * you are not concerned about speed.
1467 bytes_in = lseek(ifd, (off_t)(-8), SEEK_END);
1468 if (bytes_in != -1L) {
1471 if (read(ifd, (char*)buf, sizeof(buf)) != sizeof(buf)) {
1475 bytes_out = LG(buf+4);
1478 #endif /* RECORD_IO */
1479 date = ctime((time_t*)&time_stamp) + 4; /* skip the day of the week */
1480 date[12] = '\0'; /* suppress the 1/100sec and the year */
1482 printf("%5s %08lx %11s ", methods[method], crc, date);
1484 fprint_off(stdout, bytes_in, positive_off_t_width);
1486 fprint_off(stdout, bytes_out, positive_off_t_width);
1488 if (bytes_in == -1L) {
1490 bytes_in = bytes_out = header_bytes = 0;
1491 } else if (total_in >= 0) {
1492 total_in += bytes_in;
1494 if (bytes_out == -1L) {
1496 bytes_in = bytes_out = header_bytes = 0;
1497 } else if (total_out >= 0) {
1498 total_out += bytes_out;
1500 display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out, stdout);
1501 printf(" %s\n", ofname);
1504 /* ========================================================================
1505 * Return true if the two stat structures correspond to the same file.
1507 local int same_file(stat1, stat2)
1511 return stat1->st_ino == stat2->st_ino
1512 && stat1->st_dev == stat2->st_dev
1514 /* Can't rely on st_ino and st_dev, use other fields: */
1515 && stat1->st_mode == stat2->st_mode
1516 && stat1->st_uid == stat2->st_uid
1517 && stat1->st_gid == stat2->st_gid
1518 && stat1->st_size == stat2->st_size
1519 && stat1->st_atime == stat2->st_atime
1520 && stat1->st_mtime == stat2->st_mtime
1521 && stat1->st_ctime == stat2->st_ctime
1526 /* ========================================================================
1527 * Return true if a file name is ambiguous because the operating system
1528 * truncates file names.
1530 local int name_too_long(name, statb)
1531 char *name; /* file name to check */
1532 struct stat *statb; /* stat buf for this file name */
1534 int s = strlen(name);
1536 struct stat tstat; /* stat for truncated name */
1539 tstat = *statb; /* Just in case OS does not fill all fields */
1541 res = lstat(name, &tstat) == 0 && same_file(statb, &tstat);
1543 Trace((stderr, " too_long(%s) => %d\n", name, res));
1547 /* ========================================================================
1548 * Shorten the given name by one character, or replace a .tar extension
1549 * with .tgz. Truncate the last part of the name which is longer than
1550 * MIN_PART characters: 1234.678.012.gz -> 123.678.012.gz. If the name
1551 * has only parts shorter than MIN_PART truncate the longest part.
1552 * For decompression, just remove the last character of the name.
1554 * IN assertion: for compression, the suffix of the given name is z_suffix.
1556 local void shorten_name(name)
1559 int len; /* length of name without z_suffix */
1560 char *trunc = NULL; /* character to be truncated */
1561 int plen; /* current part length */
1562 int min_part = MIN_PART; /* current minimum part length */
1567 if (len <= 1) error("name too short");
1571 p = get_suffix(name);
1572 if (p == NULL) error("can't recover suffix\n");
1576 /* compress 1234567890.tar to 1234567890.tgz */
1577 if (len > 4 && strequ(p-4, ".tar")) {
1578 strcpy(p-4, ".tgz");
1581 /* Try keeping short extensions intact:
1582 * 1234.678.012.gz -> 123.678.012.gz
1585 p = strrchr(name, PATH_SEP);
1588 plen = strcspn(p, PART_SEP);
1590 if (plen > min_part) trunc = p-1;
1593 } while (trunc == NULL && --min_part != 0);
1595 if (trunc != NULL) {
1597 trunc[0] = trunc[1];
1601 trunc = strrchr(name, PART_SEP[0]);
1602 if (trunc == NULL) error("internal error in shorten_name");
1603 if (trunc[1] == '\0') trunc--; /* force truncation */
1605 strcpy(trunc, z_suffix);
1608 /* ========================================================================
1609 * If compressing to a file, check if ofname is not ambiguous
1610 * because the operating system truncates names. Otherwise, generate
1611 * a new ofname and save the original name in the compressed file.
1612 * If the compressed file already exists, ask for confirmation.
1613 * The check for name truncation is made dynamically, because different
1614 * file systems on the same OS might use different truncation rules (on SVR4
1615 * s5 truncates to 14 chars and ufs does not truncate).
1616 * This function returns -1 if the file must be skipped, and
1617 * updates save_orig_name if necessary.
1618 * IN assertions: save_orig_name is already set if ofname has been
1619 * already truncated because of NO_MULTIPLE_DOTS. The input file has
1620 * already been open and istat is set.
1622 local int check_ofname()
1624 struct stat ostat; /* stat for ofname */
1627 /* Check for strictly conforming Posix systems (which return ENAMETOOLONG
1628 * instead of silently truncating filenames).
1631 while (lstat(ofname, &ostat) != 0) {
1632 if (errno != ENAMETOOLONG) return 0; /* ofname does not exist */
1633 shorten_name(ofname);
1636 if (lstat(ofname, &ostat) != 0) return 0;
1638 /* Check for name truncation on existing file. Do this even on systems
1639 * defining ENAMETOOLONG, because on most systems the strict Posix
1640 * behavior is disabled by default (silent name truncation allowed).
1642 if (!decompress && name_too_long(ofname, &ostat)) {
1643 shorten_name(ofname);
1644 if (lstat(ofname, &ostat) != 0) return 0;
1647 /* Check that the input and output files are different (could be
1648 * the same by name truncation or links).
1650 if (same_file(&istat, &ostat)) {
1651 if (strequ(ifname, ofname)) {
1652 fprintf(stderr, "%s: %s: cannot %scompress onto itself\n",
1653 progname, ifname, decompress ? "de" : "");
1655 fprintf(stderr, "%s: %s and %s are the same file\n",
1656 progname, ifname, ofname);
1661 /* Ask permission to overwrite the existing file */
1664 fprintf(stderr, "%s: %s already exists;", progname, ofname);
1665 if (foreground && isatty(fileno(stdin))) {
1666 fprintf(stderr, " do you wish to overwrite (y or n)? ");
1671 fprintf(stderr, "\tnot overwritten\n");
1672 if (exit_code == OK) exit_code = WARNING;
1676 if (xunlink (ofname)) {
1685 /* ========================================================================
1686 * Set the access and modification times from the given stat buffer.
1688 local void reset_times (name, statb)
1692 struct utimbuf timep;
1694 /* Copy the time stamp */
1695 timep.actime = statb->st_atime;
1696 timep.modtime = statb->st_mtime;
1698 /* Some systems (at least OS/2) do not support utime on directories */
1699 if (utime(name, &timep) && !S_ISDIR(statb->st_mode)) {
1701 WARN((stderr, "%s: ", progname));
1711 /* ========================================================================
1712 * Copy modes, times, ownership from input file to output file.
1713 * IN assertion: to_stdout is false.
1715 local void copy_stat(ifstat)
1716 struct stat *ifstat;
1719 if (decompress && time_stamp != 0 && ifstat->st_mtime != time_stamp) {
1720 ifstat->st_mtime = time_stamp;
1722 fprintf(stderr, "%s: time stamp restored\n", ofname);
1725 reset_times(ofname, ifstat);
1727 /* Copy the protection modes */
1728 if (chmod(ofname, ifstat->st_mode & 07777)) {
1730 WARN((stderr, "%s: ", progname));
1737 chown(ofname, ifstat->st_uid, ifstat->st_gid); /* Copy ownership */
1740 /* It's now safe to remove the input file: */
1741 if (xunlink (ifname)) {
1743 WARN((stderr, "%s: ", progname));
1753 /* ========================================================================
1754 * Recurse through the given directory. This code is taken from ncompress.
1756 local void treat_dir(dir)
1761 char nbuf[MAX_PATH_LEN];
1764 dirp = opendir(dir);
1771 ** WARNING: the following algorithm could occasionally cause
1772 ** compress to produce error warnings of the form "<filename>.gz
1773 ** already has .gz suffix - ignored". This occurs when the
1774 ** .gz output file is inserted into the directory below
1775 ** readdir's current pointer.
1776 ** These warnings are harmless but annoying, so they are suppressed
1777 ** with option -r (except when -v is on). An alternative
1778 ** to allowing this would be to store the entire directory
1779 ** list in memory, then compress the entries in the stored
1780 ** list. Given the depth-first recursive algorithm used here,
1781 ** this could use up a tremendous amount of memory. I don't
1782 ** think it's worth it. -- Dave Mack
1783 ** (An other alternative might be two passes to avoid depth-first.)
1786 while ((errno = 0, dp = readdir(dirp)) != NULL) {
1788 if (strequ(dp->d_name,".") || strequ(dp->d_name,"..")) {
1792 if (len + NAMLEN(dp) + 1 < MAX_PATH_LEN - 1) {
1794 if (len != 0 /* dir = "" means current dir on Amiga */
1796 && dir[len-1] != PATH_SEP2
1799 && dir[len-1] != PATH_SEP3
1802 nbuf[len++] = PATH_SEP;
1804 strcpy(nbuf+len, dp->d_name);
1807 fprintf(stderr,"%s: %s/%s: pathname too long\n",
1808 progname, dir, dp->d_name);
1814 if (CLOSEDIR(dirp) != 0)
1817 #endif /* ! NO_DIR */
1819 /* ========================================================================
1820 * Free all dynamically allocated variables and exit with the given code.
1822 local void do_exit(exitcode)
1825 static int in_exit = 0;
1827 if (in_exit) exit(exitcode);
1829 if (env != NULL) free(env), env = NULL;
1830 if (args != NULL) free((char*)args), args = NULL;
1844 /* ========================================================================
1845 * Signal and error handler.
1847 RETSIGTYPE abort_gzip()
1849 if (remove_ofname) {