/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
- Copyright (C) 1999, 2001, 2002, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2001-2002, 2006-2007, 2009-2010 Free Software
+ Foundation, Inc.
Copyright (C) 1992-1993 Jean-loup Gailly
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
+ the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
* See the file algorithm.doc for the compression algorithms and file formats.
*/
-static char *license_msg[] = {
-"Copyright (C) 2006 Free Software Foundation, Inc.",
+static char const *const license_msg[] = {
+"Copyright (C) 2007 Free Software Foundation, Inc.",
"Copyright (C) 1993 Jean-loup Gailly.",
"This is free software. You may redistribute copies of it under the terms of",
"the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.",
* For the meaning of all compilation flags, see comments in Makefile.in.
*/
-#ifdef RCSID
-static char rcsid[] = "$Id: gzip.c,v 1.11 2006/12/12 00:03:17 eggert Exp $";
-#endif
-
#include <config.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
+#include "closein.h"
#include "tailor.h"
#include "gzip.h"
#include "lzw.h"
#include "fcntl-safer.h"
#include "getopt.h"
+#include "ignore-value.h"
#include "stat-time.h"
-#include "timespec.h"
/* configuration */
-#ifdef HAVE_TIME_H
-# include <time.h>
-#else
-# include <sys/time.h>
-#endif
-
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-
-#ifdef HAVE_LIMITS_H
-# include <limits.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#if defined STDC_HEADERS || defined HAVE_STDLIB_H
-# include <stdlib.h>
-#else
- extern int errno;
-#endif
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
#ifndef NO_DIR
# define NO_DIR 0
int quiet = 0; /* be very quiet (-q) */
int do_lzw = 0; /* generate output compatible with old compress (-Z) */
int test = 0; /* test .gz file integrity */
-int foreground; /* set if program run in foreground */
+int foreground = 0; /* set if program run in foreground */
char *program_name; /* program name */
int maxbits = BITS; /* max bits per code for LZW */
int method = DEFLATED;/* compression method */
off_t ifile_size; /* input file size, -1 for devices (debug only) */
char *env; /* contents of GZIP env variable */
char **args = NULL; /* argv pointer if GZIP env variable defined */
-char *z_suffix; /* default suffix (can be set with --suffix) */
+char const *z_suffix; /* default suffix (can be set with --suffix) */
size_t z_len; /* strlen(z_suffix) */
/* The set of signals that are caught. */
static sigset_t caught_signals;
-/* If nonzero then exit with status 1, rather than with the usual
+/* If nonzero then exit with status WARNING, rather than with the usual
signal status, on receipt of a signal with this value. This
suppresses a "Broken Pipe" message with some shells. */
static int volatile exiting_signal;
unsigned outcnt; /* bytes in output buffer */
int rsync = 0; /* make ryncable chunks */
+static int handled_sig[] =
+ {
+ /* SIGINT must be first, as 'foreground' depends on it. */
+ SIGINT
+
+#ifdef SIGHUP
+ , SIGHUP
+#endif
+#ifdef SIGPIPE
+ , SIGPIPE
+#else
+# define SIGPIPE 0
+#endif
+#ifdef SIGTERM
+ , SIGTERM
+#endif
+#ifdef SIGXCPU
+ , SIGXCPU
+#endif
+#ifdef SIGXFSZ
+ , SIGXFSZ
+#endif
+ };
+
struct option longopts[] =
{
/* { name has_arg *flag val } */
/* ======================================================================== */
local void help()
{
- static char *help_msg[] = {
+ static char const* const help_msg[] = {
"Compress or uncompress FILEs (by default, compress FILES in-place).",
"",
"Mandatory arguments to long options are mandatory for short options too.",
" -Z, --lzw produce output compatible with old compress",
" -b, --bits=BITS max number of bits per code (implies -Z)",
#endif
- " --rsyncable Make rsync-friendly archive",
+ " --rsyncable Make rsync-friendly archive",
"",
"With no FILE, or when FILE is -, read standard input.",
"",
"Report bugs to <bug-gzip@gnu.org>.",
0};
- char **p = help_msg;
+ char const *const *p = help_msg;
printf ("Usage: %s [OPTION]... [FILE]...\n", program_name);
while (*p) printf ("%s\n", *p++);
/* ======================================================================== */
local void license()
{
- char **p = license_msg;
+ char const *const *p = license_msg;
printf ("%s %s\n", program_name, VERSION);
while (*p) printf ("%s\n", *p++);
printf ("Written by Jean-loup Gailly.\n");
}
-local void progerror (string)
- char *string;
+local void progerror (char const *string)
{
int e = errno;
fprintf (stderr, "%s: ", program_name);
}
/* ======================================================================== */
-int main (argc, argv)
- int argc;
- char **argv;
+int main (int argc, char **argv)
{
int file_count; /* number of files to process */
size_t proglen; /* length of program_name */
program_name = gzip_base_name (argv[0]);
proglen = strlen (program_name);
+ atexit (close_stdin);
+
/* Suppress .exe for MSDOS, OS/2 and VMS: */
if (4 < proglen && strequ (program_name + proglen - 4, ".exe"))
program_name[proglen - 4] = '\0';
if (env != NULL) args = argv;
#ifndef GNU_STANDARD
+# define GNU_STANDARD 1
+#endif
+#if !GNU_STANDARD
/* For compatibility with old compress, use program name as an option.
- * If you compile with -DGNU_STANDARD, this program will behave as
+ * Unless you compile with -DGNU_STANDARD=0, this program will behave as
* gzip even if it is invoked under the name gunzip or zcat.
*
* Systems which do not support links can still use -d or -dc.
#else
recursive = 1;
#endif
- case 'R':
+ break;
+ case 'R':
rsync = 1; break;
case 'S':
strcpy(ifname, "stdin");
strcpy(ofname, "stdout");
- /* Get the time stamp on the input file. */
- time_stamp.tv_nsec = -1; /* The time is unknown by default. */
-
-#ifndef NO_STDIN_FSTAT
- if (list || !no_time) {
- if (fstat(fileno(stdin), &istat) != 0) {
- progerror("standard input");
- do_exit(ERROR);
- }
-# ifdef NO_PIPE_TIMESTAMP
- if (S_ISREG(istat.st_mode))
-# endif
- time_stamp = get_stat_mtime (&istat);
-#endif /* NO_STDIN_FSTAT */
- }
- ifile_size = -1L; /* convention for unknown size */
+ /* Get the file's time stamp and size. */
+ if (fstat (fileno (stdin), &istat) != 0)
+ {
+ progerror ("standard input");
+ do_exit (ERROR);
+ }
+ ifile_size = S_ISREG (istat.st_mode) ? istat.st_size : -1;
+ time_stamp.tv_nsec = -1;
+ if (!no_time || list)
+ time_stamp = get_stat_mtime (&istat);
clear_bufs(); /* clear input and output buffers */
to_stdout = 1;
part_nb = 0;
+ ifd = fileno(stdin);
if (decompress) {
method = get_method(ifd);
program_name, ifname));
return;
}
- if (!S_ISREG(istat.st_mode)) {
- WARN((stderr,
- "%s: %s is not a directory or a regular file - ignored\n",
- program_name, ifname));
- close (ifd);
- return;
- }
- if (istat.st_mode & S_ISUID)
- {
- WARN ((stderr, "%s: %s is set-user-ID on execution - ignored\n",
- program_name, ifname));
- close (ifd);
- return;
- }
- if (istat.st_mode & S_ISGID)
+ if (! to_stdout)
{
- WARN ((stderr, "%s: %s is set-group-ID on execution - ignored\n",
- program_name, ifname));
- close (ifd);
- return;
- }
- if (istat.st_mode & S_ISVTX)
- {
- WARN ((stderr, "%s: %s has the sticky bit set - file ignored\n",
- program_name, ifname));
- close (ifd);
- return;
- }
+ if (! S_ISREG (istat.st_mode))
+ {
+ WARN ((stderr,
+ "%s: %s is not a directory or a regular file - ignored\n",
+ program_name, ifname));
+ close (ifd);
+ return;
+ }
+ if (istat.st_mode & S_ISUID)
+ {
+ WARN ((stderr, "%s: %s is set-user-ID on execution - ignored\n",
+ program_name, ifname));
+ close (ifd);
+ return;
+ }
+ if (istat.st_mode & S_ISGID)
+ {
+ WARN ((stderr, "%s: %s is set-group-ID on execution - ignored\n",
+ program_name, ifname));
+ close (ifd);
+ return;
+ }
- if (istat.st_nlink > 1 && !to_stdout && !force) {
- WARN((stderr, "%s: %s has %lu other link%c -- unchanged\n",
- program_name, ifname, (unsigned long) istat.st_nlink - 1,
- istat.st_nlink > 2 ? 's' : ' '));
- close (ifd);
- return;
- }
+ if (! force)
+ {
+ if (istat.st_mode & S_ISVTX)
+ {
+ WARN ((stderr,
+ "%s: %s has the sticky bit set - file ignored\n",
+ program_name, ifname));
+ close (ifd);
+ return;
+ }
+ if (2 <= istat.st_nlink)
+ {
+ WARN ((stderr, "%s: %s has %lu other link%c -- unchanged\n",
+ program_name, ifname,
+ (unsigned long int) istat.st_nlink - 1,
+ istat.st_nlink == 2 ? ' ' : 's'));
+ close (ifd);
+ return;
+ }
+ }
+ }
- ifile_size = istat.st_size;
- if (no_time && !list)
- time_stamp.tv_nsec = -1;
- else
+ ifile_size = S_ISREG (istat.st_mode) ? istat.st_size : -1;
+ time_stamp.tv_nsec = -1;
+ if (!no_time || list)
time_stamp = get_stat_mtime (&istat);
/* Generate output file name. For -r and (-t or -l), skip files
{
int nlen, slen;
char suffix[MAX_SUFFIX+3]; /* last chars of name, forced to lower case */
- static char *known_suffixes[] =
+ static char const *known_suffixes[] =
{NULL, ".gz", ".z", ".taz", ".tgz", "-gz", "-z", "_z",
#ifdef MAX_EXT_CHARS
"z",
#endif
NULL};
- char **suf = known_suffixes;
+ char const **suf = known_suffixes;
*suf = z_suffix;
if (strequ(z_suffix, "z")) suf++; /* check long suffixes first */
{
int ilen; /* strlen(ifname) */
int z_suffix_errno = 0;
- static char *suffixes[] = {NULL, ".gz", ".z", "-z", ".Z", NULL};
- char **suf = suffixes;
- char *s;
+ static char const *suffixes[] = {NULL, ".gz", ".z", "-z", ".Z", NULL};
+ char const **suf = suffixes;
+ char const *s;
#ifdef NO_MULTIPLE_DOTS
char *dot; /* pointer to ifname extension, or NULL */
#endif
/* Search for all suffixes */
do {
- char *s0 = s = *suf;
+ char const *s0 = s = *suf;
strcpy (ifname, iname);
#ifdef NO_MULTIPLE_DOTS
if (*s == '.') s++;
}
/* ofname might be changed later if infile contains an original name */
- } else if (suff != NULL) {
+ } else if (suff && ! force) {
/* Avoid annoying messages with -r (see treat_dir()) */
if (verbose || (!recursive && !quiet)) {
/* Don't use WARN, as it affects exit status. */
/* If try_byte returned EOF, magic[1] == (char) EOF. */
} else {
magic[0] = (char)get_byte();
- magic[1] = (char)get_byte();
- imagic1 = 0; /* avoid lint warning */
+ if (magic[0]) {
+ magic[1] = (char)get_byte();
+ imagic1 = 0; /* avoid lint warning */
+ } else {
+ imagic1 = try_byte ();
+ magic[1] = (char) imagic1;
+ }
}
method = -1; /* unknown yet */
part_nb++; /* number of parts in gzip file */
}
if ((flags & CONTINUATION) != 0) {
fprintf(stderr,
- "%s: %s is a a multi-part gzip file -- not supported\n",
+ "%s: %s is a multi-part gzip file -- not supported\n",
program_name, ifname);
exit_code = ERROR;
if (force <= 1) return -1;
{
ulg crc; /* original crc */
static int first_time = 1;
- static char* methods[MAX_METHODS] = {
+ static char const *const methods[MAX_METHODS] = {
"store", /* 0 */
"compr", /* 1 */
"pack ", /* 2 */
}
}
- if (futimens (ofd, ofname, timespec) != 0)
+ if (gl_futimens (ofd, ofname, timespec) != 0)
{
int e = errno;
WARN ((stderr, "%s: ", program_name));
#endif
#ifndef NO_CHOWN
+ /* Copy ownership */
# if HAVE_FCHOWN
- fchown (ofd, ifstat->st_uid, ifstat->st_gid); /* Copy ownership */
+ ignore_value (fchown (ofd, ifstat->st_uid, ifstat->st_gid));
# elif HAVE_CHOWN
- chown(ofname, ifstat->st_uid, ifstat->st_gid); /* Copy ownership */
+ ignore_value (chown (ofname, ifstat->st_uid, ifstat->st_gid));
# endif
#endif
char nbuf[MAX_PATH_LEN];
int len;
-#if HAVE_FDOPENDIR
dirp = fdopendir (fd);
-#else
- close (fd);
- dirp = opendir(dir);
-#endif
if (dirp == NULL) {
progerror(dir);
-#if HAVE_FDOPENDIR
close (fd);
-#endif
return ;
}
/*
static void
install_signal_handlers ()
{
- static int sig[] =
- {
- /* SIGINT must be first, as 'foreground' depends on it. */
- SIGINT
-
-#ifdef SIGHUP
- , SIGHUP
-#endif
-#ifdef SIGPIPE
- , SIGPIPE
-#else
-# define SIGPIPE 0
-#endif
-#ifdef SIGTERM
- , SIGTERM
-#endif
-#ifdef SIGXCPU
- , SIGXCPU
-#endif
-#ifdef SIGXFSZ
- , SIGXFSZ
-#endif
- };
- int nsigs = sizeof sig / sizeof sig[0];
+ int nsigs = sizeof handled_sig / sizeof handled_sig[0];
int i;
#if SA_NOCLDSTOP
sigemptyset (&caught_signals);
for (i = 0; i < nsigs; i++)
{
- sigaction (sig[i], NULL, &act);
+ sigaction (handled_sig[i], NULL, &act);
if (act.sa_handler != SIG_IGN)
- sigaddset (&caught_signals, sig[i]);
+ sigaddset (&caught_signals, handled_sig[i]);
}
act.sa_handler = abort_gzip_signal;
act.sa_flags = 0;
for (i = 0; i < nsigs; i++)
- if (sigismember (&caught_signals, sig[i]))
+ if (sigismember (&caught_signals, handled_sig[i]))
{
if (i == 0)
foreground = 1;
- sigaction (sig[i], &act, NULL);
+ sigaction (handled_sig[i], &act, NULL);
}
#else
for (i = 0; i < nsigs; i++)
- if (signal (sig[i], SIG_IGN) != SIG_IGN)
+ if (signal (handled_sig[i], SIG_IGN) != SIG_IGN)
{
if (i == 0)
foreground = 1;
- signal (sig[i], abort_gzip_signal);
- siginterrupt (sig[i], 1);
+ signal (handled_sig[i], abort_gzip_signal);
+ siginterrupt (handled_sig[i], 1);
}
#endif
}
if (in_exit) exit(exitcode);
in_exit = 1;
- if (env != NULL) free(env), env = NULL;
- if (args != NULL) free((char*)args), args = NULL;
+ free(env);
+ env = NULL;
+ free(args);
+ args = NULL;
FREE(inbuf);
FREE(outbuf);
FREE(d_buf);
signal (sig, SIG_IGN);
remove_output_file ();
if (sig == exiting_signal)
- _exit (ERROR);
+ _exit (WARNING);
signal (sig, SIG_DFL);
raise (sig);
}