X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=gzip.c;h=61f721e6ed725d3375e88755e3522d607f1f84fe;hb=db00b4e39677b0dbf3ea6f7694e0eac7be4ef141;hp=b18a0a9103a90c2813fa3261a930ef9b2d7c2f83;hpb=302189d124ed5849c2589ea92e912eb24fdc4ab3;p=gzip diff --git a/gzip.c b/gzip.c index b18a0a9..61f721e 100644 --- a/gzip.c +++ b/gzip.c @@ -1,5 +1,5 @@ /* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface - * Copyright (C) 1999, 2001 Free Software Foundation, Inc. + * Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. * 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' @@ -11,7 +11,7 @@ */ static char *license_msg[] = { -"Copyright 2001 Free Software Foundation", +"Copyright 2002 Free Software Foundation", "Copyright 1992-1993 Jean-loup Gailly", "This program comes with ABSOLUTELY NO WARRANTY.", "You may redistribute copies of this program", @@ -103,6 +103,9 @@ static char rcsid[] = "$Id: gzip.c,v 0.24 1993/06/24 10:52:07 jloup Exp $"; # define DIR_OPT "NO_DIR" # endif #endif +#ifndef NO_DIR +# define NO_DIR 0 +#endif #ifdef CLOSEDIR_VOID # define CLOSEDIR(d) (closedir(d), 0) @@ -110,6 +113,10 @@ static char rcsid[] = "$Id: gzip.c,v 0.24 1993/06/24 10:52:07 jloup Exp $"; # define CLOSEDIR(d) closedir(d) #endif +#if !defined(HAVE_LSTAT) && !defined(lstat) +# define lstat(name, buf) stat(name, buf) +#endif + #ifdef HAVE_UTIME # ifdef HAVE_UTIME_H # include @@ -234,7 +241,7 @@ 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) */ -int z_len; /* strlen(z_suffix) */ +size_t z_len; /* strlen(z_suffix) */ off_t bytes_in; /* number of input bytes */ off_t bytes_out; /* number of output bytes */ @@ -249,6 +256,7 @@ int ofd; /* output file descriptor */ unsigned insize; /* valid bytes in inbuf */ unsigned inptr; /* index of next byte to be processed in inbuf */ unsigned outcnt; /* bytes in output buffer */ +int rsync = 0; /* make ryncable chunks */ struct option longopts[] = { @@ -278,6 +286,7 @@ struct option longopts[] = {"best", 0, 0, '9'}, /* compress better */ {"lzw", 0, 0, 'Z'}, /* make output compatible with old compress */ {"bits", 1, 0, 'b'}, /* max number of bits per code (implies -Z) */ + {"rsyncable", 0, 0, 'R'}, /* make rsync-friendly archive */ { 0, 0, 0, 0 } }; @@ -306,7 +315,7 @@ local void do_exit OF((int exitcode)); int main OF((int argc, char **argv)); int (*work) OF((int infile, int outfile)) = zip; /* function to call */ -#ifndef NO_DIR +#if ! NO_DIR local void treat_dir OF((char *dir)); #endif #ifdef HAVE_UTIME @@ -320,17 +329,7 @@ local void usage() { printf ("usage: %s [-%scdfhlLnN%stvV19] [-S suffix] [file ...]\n", progname, -#if O_BINARY - "a", -#else - "", -#endif -#ifdef NO_DIR - "" -#else - "r" -#endif - ); + O_BINARY ? "a" : "", NO_DIR ? "" : "r"); } /* ======================================================================== */ @@ -355,7 +354,7 @@ local void help() " -n --no-name do not save or restore the original name and time stamp", " -N --name save or restore the original name and time stamp", " -q --quiet suppress all warnings", -#ifndef NO_DIR +#if ! NO_DIR " -r --recursive operate recursively on directories", #endif " -S .suf --suffix .suf use suffix .suf on compressed files", @@ -368,6 +367,7 @@ local void help() " -Z --lzw produce output compatible with old compress", " -b --bits maxbits max number of bits per code (implies -Z)", #endif + " --rsyncable Make rsync-friendly archive", " file... files to (de)compress. If none given, use standard input.", "Report bugs to .", 0}; @@ -539,13 +539,16 @@ int main (argc, argv) case 'q': quiet = 1; verbose = 0; break; case 'r': -#ifdef NO_DIR +#if NO_DIR fprintf(stderr, "%s: -r not supported on this system\n", progname); usage(); do_exit(ERROR); break; #else recursive = 1; break; #endif + case 'R': + rsync = 1; break; + case 'S': #ifdef NO_MULTIPLE_DOTS if (*optarg == '.') optarg++; @@ -603,7 +606,7 @@ int main (argc, argv) #endif if ((z_len == 0 && !decompress) || z_len > MAX_SUFFIX) { fprintf(stderr, "%s: incorrect suffix '%s'\n", - progname, optarg); + progname, z_suffix); do_exit(ERROR); } if (do_lzw && !decompress) work = lzw; @@ -773,7 +776,7 @@ local void treat_file(iname) /* If the input name is that of a directory, recurse or ignore: */ if (S_ISDIR(istat.st_mode)) { -#ifndef NO_DIR +#if ! NO_DIR if (recursive) { struct stat st; st = istat; @@ -878,8 +881,11 @@ local void treat_file(iname) } close(ifd); - if (!to_stdout && close(ofd)) { - write_error(); + if (!to_stdout) { + /* Copy modes, times, ownership, and remove the input file */ + copy_stat(&istat); + if (close(ofd)) + write_error(); } if (method == -1) { if (!to_stdout) xunlink (ofname); @@ -899,10 +905,6 @@ local void treat_file(iname) } fprintf(stderr, "\n"); } - /* Copy modes, times, ownership, and remove the input file */ - if (!to_stdout) { - copy_stat(&istat); - } } /* ======================================================================== @@ -976,11 +978,9 @@ local int do_stat(name, sbuf) struct stat *sbuf; { errno = 0; -#ifdef HAVE_LSTAT if (!to_stdout && !force) { return lstat(name, sbuf); } -#endif return stat(name, sbuf); } @@ -1322,6 +1322,7 @@ local int get_method(in) /* Copy the base name. Keep a directory prefix intact. */ char *p = base_name (ofname); char *base = p; + char *base2; for (;;) { *p = (char)get_char(); if (*p++ == '\0') break; @@ -1329,6 +1330,8 @@ local int get_method(in) error("corrupted input -- file name too large"); } } + base2 = base_name (base); + strcpy(base, base2); /* If necessary, adapt the name to local OS conventions: */ if (!list) { MAKE_LEGAL_NAME(base); @@ -1543,7 +1546,7 @@ local int name_too_long(name, statb) tstat = *statb; /* Just in case OS does not fill all fields */ name[s-1] = '\0'; - res = stat(name, &tstat) == 0 && same_file(statb, &tstat); + res = lstat(name, &tstat) == 0 && same_file(statb, &tstat); name[s-1] = c; Trace((stderr, " too_long(%s) => %d\n", name, res)); return res; @@ -1633,12 +1636,12 @@ local int check_ofname() * instead of silently truncating filenames). */ errno = 0; - while (stat(ofname, &ostat) != 0) { + while (lstat(ofname, &ostat) != 0) { if (errno != ENAMETOOLONG) return 0; /* ofname does not exist */ shorten_name(ofname); } #else - if (stat(ofname, &ostat) != 0) return 0; + if (lstat(ofname, &ostat) != 0) return 0; #endif /* Check for name truncation on existing file. Do this even on systems * defining ENAMETOOLONG, because on most systems the strict Posix @@ -1646,7 +1649,7 @@ local int check_ofname() */ if (!decompress && name_too_long(ofname, &ostat)) { shorten_name(ofname); - if (stat(ofname, &ostat) != 0) return 0; + if (lstat(ofname, &ostat) != 0) return 0; } /* Check that the input and output files are different (could be @@ -1730,7 +1733,7 @@ local void copy_stat(ifstat) reset_times(ofname, ifstat); #endif /* Copy the protection modes */ - if (chmod(ofname, ifstat->st_mode & 07777)) { + if (fchmod(ofd, ifstat->st_mode & 07777)) { int e = errno; WARN((stderr, "%s: ", progname)); if (!quiet) { @@ -1739,7 +1742,7 @@ local void copy_stat(ifstat) } } #ifndef NO_CHOWN - chown(ofname, ifstat->st_uid, ifstat->st_gid); /* Copy ownership */ + fchown(ofd, ifstat->st_uid, ifstat->st_gid); /* Copy ownership */ #endif remove_ofname = 0; /* It's now safe to remove the input file: */ @@ -1753,7 +1756,7 @@ local void copy_stat(ifstat) } } -#ifndef NO_DIR +#if ! NO_DIR /* ======================================================================== * Recurse through the given directory. This code is taken from ncompress. @@ -1819,7 +1822,7 @@ local void treat_dir(dir) if (CLOSEDIR(dirp) != 0) progerror(dir); } -#endif /* ? NO_DIR */ +#endif /* ! NO_DIR */ /* ======================================================================== * Free all dynamically allocated variables and exit with the given code.