/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface * Copyright (C) 1992-1993 Jean-loup Gailly * The unzip code was written and put in the public domain by Mark Adler. * Portions of the lzw code are derived from the public domain 'compress' * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies, * Ken Turkowski, Dave Mack and Peter Jannesen. * * See the license_msg below and the file COPYING for the software license. * See the file algorithm.doc for the compression algorithms and file formats. */ /* Compress files with zip algorithm and 'compress' interface. * See usage() and help() functions below for all options. * Outputs: * file.gz: compressed file with same mode, owner, and utimes * or stdout with -c option or if stdin used as input. * If the output file name had to be truncated, the original name is kept * in the compressed file. * On MSDOS, file.tmp -> file.tmz. On VMS, file.tmp -> file.tmp-gz. * * Using gz on MSDOS would create too many file name conflicts. For * example, foo.txt -> foo.tgz (.tgz must be reserved as shorthand for * tar.gz). Similarly, foo.dir and foo.doc would both be mapped to foo.dgz. * I also considered 12345678.txt -> 12345txt.gz but this truncates the name * too heavily. There is no ideal solution given the MSDOS 8+3 limitation. * * For the meaning of all compilation flags, see comments in Makefile.in. */ #ifdef RCSID static char rcsid[] = "$Id$"; #endif #include #include #include #include #include #include #include "tailor.h" #include "gzip.h" #include "lzw.h" /* configuration */ #ifdef HAVE_TIME_H # include #else # include #endif #ifdef HAVE_FCNTL_H # include #endif #ifdef HAVE_LIMITS_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else extern int errno; #endif #ifdef HAVE_DIRENT_H # include # define NAMLEN(direct) strlen((direct)->d_name) # define DIR_OPT "DIRENT" #else # define dirent direct # define NAMLEN(direct) ((direct)->d_namlen) # ifdef HAVE_SYS_NDIR_H # include # define DIR_OPT "SYS_NDIR" # endif # ifdef HAVE_SYS_DIR_H # include # define DIR_OPT "SYS_DIR" # endif # ifdef HAVE_NDIR_H # include # define DIR_OPT "NDIR" # endif # ifndef DIR_OPT # define DIR_OPT "NO_DIR" # endif #endif #ifdef CLOSEDIR_VOID # define CLOSEDIR(d) (closedir(d), 0) #else # define CLOSEDIR(d) closedir(d) #endif #ifdef HAVE_UTIME # ifdef HAVE_UTIME_H # include # define TIME_OPT "UTIME" # else # ifdef HAVE_SYS_UTIME_H # include # define TIME_OPT "SYS_UTIME" # else struct utimbuf { time_t actime; time_t modtime; }; # define TIME_OPT "STRUCT_UTIMBUF" # endif # endif #else # define TIME_OPT "NO_UTIME" #endif #if !defined(S_ISDIR) && defined(S_IFDIR) # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #if !defined(S_ISREG) && defined(S_IFREG) # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif typedef RETSIGTYPE (*sig_type) OF((int)); #ifndef O_BINARY # define O_BINARY 0 /* creation mode for open() */ #endif #ifndef O_CREAT /* Pure BSD system? */ # include # ifndef O_CREAT # define O_CREAT FCREAT # endif # ifndef O_EXCL # define O_EXCL FEXCL # endif #endif #ifndef S_IRUSR # define S_IRUSR 0400 #endif #ifndef S_IWUSR # define S_IWUSR 0200 #endif #define RW_USER (S_IRUSR | S_IWUSR) /* creation mode for open() */ #ifndef MAX_PATH_LEN # define MAX_PATH_LEN 1024 /* max pathname length */ #endif #ifndef SEEK_END # define SEEK_END 2 #endif #ifndef CHAR_BIT # define CHAR_BIT 8 #endif #ifdef off_t off_t lseek OF((int fd, off_t offset, int whence)); #endif #ifndef OFF_T_MIN #define OFF_T_MIN (~ (off_t) 0 << (sizeof (off_t) * CHAR_BIT - 1)) #endif #ifndef OFF_T_MAX #define OFF_T_MAX (~ (off_t) 0 - OFF_T_MIN) #endif /* global buffers */ DECLARE(uch, inbuf, INBUFSIZ +INBUF_EXTRA); DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); DECLARE(ush, d_buf, DIST_BUFSIZE); DECLARE(uch, window, 2L*WSIZE); #ifndef MAXSEG_64K DECLARE(ush, tab_prefix, 1L< 4 && strequ(progname+proglen-4, ".exe")) { progname[proglen-4] = '\0'; } foreground = signal(SIGINT, SIG_IGN) != SIG_IGN; if (foreground) { (void) signal (SIGINT, (sig_type)abort_gzip); } #ifdef SIGTERM if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { (void) signal(SIGTERM, (sig_type)abort_gzip); } #endif #ifdef SIGHUP if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { (void) signal(SIGHUP, (sig_type)abort_gzip); } #endif if (do_decompress_arg) decompress = 1; z_suffix = Z_SUFFIX; z_len = strlen(z_suffix); #ifdef SIGPIPE /* Ignore "Broken Pipe" message with --quiet */ if (quiet && signal (SIGPIPE, SIG_IGN) != SIG_IGN) signal (SIGPIPE, (sig_type) abort_gzip); #endif /* By default, save name and timestamp on compression but do not * restore them on decompression. */ if (no_time < 0) no_time = decompress; if (no_name < 0) no_name = decompress; file_count = argc - optind; /* Allocate all global buffers (for DYN_ALLOC option) */ ALLOC(uch, inbuf, INBUFSIZ +INBUF_EXTRA); ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA); ALLOC(ush, d_buf, DIST_BUFSIZE); ALLOC(uch, window, 2L*WSIZE); #ifndef MAXSEG_64K ALLOC(ush, tab_prefix, 1L<= 0) return method; if (part_nb == 1) { fprintf(stderr, "\n%s: %s: not in gzip format\n", progname, ifname); exit_code = ERROR; return -1; } else { if (magic[0] == 0) { int inbyte; for (inbyte = imagic1; inbyte == 0; inbyte = try_byte ()) continue; if (inbyte == EOF) { return -3; } } WARN((stderr, "\n%s: %s: decompression OK, trailing garbage ignored\n", progname, ifname)); return -2; } } /* ======================================================================== * Free all dynamically allocated variables and exit with the given code. */ local void do_exit(exitcode) int exitcode; { static int in_exit = 0; if (in_exit) exit(exitcode); in_exit = 1; if (env != NULL) free(env), env = NULL; if (args != NULL) free((char*)args), args = NULL; FREE(inbuf); FREE(outbuf); FREE(d_buf); FREE(window); #ifndef MAXSEG_64K FREE(tab_prefix); #else FREE(tab_prefix0); FREE(tab_prefix1); #endif exit(exitcode); } /* ======================================================================== * Signal and error handler. */ RETSIGTYPE abort_gzip() { if (remove_ofname) { close(ofd); unlink (ofname); } do_exit(ERROR); }