diff --git a/usr.bin/gzip/Makefile b/usr.bin/gzip/Makefile index 7f7125e..38e8d05 100644 --- a/usr.bin/gzip/Makefile +++ b/usr.bin/gzip/Makefile @@ -24,11 +24,13 @@ SCRIPTS= gzexe zdiff zforce zmore znew MLINKS+= gzip.1 gunzip.1 \ gzip.1 gzcat.1 \ gzip.1 zcat.1 \ - zdiff.1 zcmp.1 + zdiff.1 zcmp.1 \ + zmore.1 zless.1 LINKS+= ${BINDIR}/gzip ${BINDIR}/gunzip \ ${BINDIR}/gzip ${BINDIR}/gzcat \ ${BINDIR}/gzip ${BINDIR}/zcat \ - ${BINDIR}/zdiff ${BINDIR}/zcmp + ${BINDIR}/zdiff ${BINDIR}/zcmp \ + ${BINDIR}/zmore ${BINDIR}/zless .include diff --git a/usr.bin/gzip/gzexe b/usr.bin/gzip/gzexe index 9b7bda6..c9408bd 100644 --- a/usr.bin/gzip/gzexe +++ b/usr.bin/gzip/gzexe @@ -2,7 +2,7 @@ # # $NetBSD: gzexe,v 1.2 2003/12/28 12:43:43 wiz Exp $ # $DragonFly: src/usr.bin/gzip/gzexe,v 1.1 2004/10/26 11:19:31 joerg Exp $ -# $OpenBSD: gzexe,v 1.3 2003/08/05 18:22:17 deraadt Exp $ +# $OpenBSD: gzexe,v 1.4 2005/09/30 06:50:44 otto Exp $ # # Copyright (c) 2003 Otto Moerbeek # @@ -89,7 +89,7 @@ check () { fi case `basename "$1"` in - sh | mktemp | rm | echo | tail | gzip | chmod) + sh | mktemp | rm | echo | tail | gzip | chmod | basename) echo "$prog: cannot compress $1, I depend on it" return 1 esac @@ -103,6 +103,38 @@ check () { echo "$prog: cannot compress $1, it has an s bit set" return 1 fi + + # Build a list of files we should not compress. + # * files we need to decompress + CHECK_LIST=" + /bin/chmod + /bin/echo + /bin/sh + /bin/rm + /usr/bin/basename + /usr/bin/gzip + /usr/bin/mktemp + /usr/bin/tail + " + # * files in /bin and /sbin (decompression fails if /usr/bin is not mounted) + # (You could skip these if /usr/bin is always mounted on the same mount point.) + CHECK_LIST="$CHECK_LIST + /bin/* + /sbin/* + " + # See if the program we are trying to compress is in the list. + # To avoid compressing hardlinked files (eg compress & gzip) + # we compare the device & inode. + PROG_STAT_INFO=`stat -f '%d %i' "$1"` + for CHECK in $CHECK_LIST; do + if test -f "$CHECK"; then + CHECK_STAT_INFO=`stat -f '%d %i' "$CHECK"` + if test "X$PROG_STAT_INFO" == "X$CHECK_STAT_INFO"; then + echo "$prog: cannot compress $1, it is the same file as $CHECK" + return 1 + fi + fi + done } # Compress a file diff --git a/usr.bin/gzip/gzexe.1 b/usr.bin/gzip/gzexe.1 index 06b53b8..c96eada 100644 --- a/usr.bin/gzip/gzexe.1 +++ b/usr.bin/gzip/gzexe.1 @@ -1,5 +1,5 @@ .\" $NetBSD: gzexe.1,v 1.2 2003/12/28 12:43:43 wiz Exp $ -.\" $OpenBSD: gzexe.1,v 1.1 2003/07/31 07:32:47 otto Exp $ +.\" $OpenBSD: gzexe.1,v 1.5 2007/05/31 19:20:08 jmc Exp $ .\" $DragonFly: src/usr.bin/gzip/gzexe.1,v 1.2 2007/07/29 17:27:45 swildner Exp $ .\" .\" Copyright (c) 2003 Otto Moerbeek @@ -16,7 +16,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd July 30, 2003 +.Dd Sep 30, 2005 .Dt GZEXE 1 .Os .Sh NAME @@ -53,9 +53,11 @@ The program refuses to compress non-regular or non-executable files, files with a setuid or setgid bit set, files that are already compressed using -.Nm +.Nm , +files in /bin or /sbin, or programs it needs to perform on-the-fly decompression: .Xr sh 1 , +.Xr basename 1 , .Xr mktemp 1 , .Xr rm 1 , .Xr echo 1 , diff --git a/usr.bin/gzip/gzip.1 b/usr.bin/gzip/gzip.1 index c17f76f..dce325a 100644 --- a/usr.bin/gzip/gzip.1 +++ b/usr.bin/gzip/gzip.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: gzip.1,v 1.16 2004/04/27 02:25:06 mrg Exp $ +.\" $NetBSD: gzip.1,v 1.19 2008/05/29 14:51:27 mrg Exp $ .\" $DragonFly: src/usr.bin/gzip/gzip.1,v 1.2 2007/12/06 19:54:52 hasso Exp $ .\" .\" Copyright (c) 1997, 2003, 2004 Matthew R. Green @@ -12,8 +12,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -138,7 +136,7 @@ This option displays information about the file's compressed and uncompressed size, ratio, uncompressed name. With the .Fl v -option, it also displays the compression method, CRC, data and time +option, it also displays the compression method, CRC, date and time embedded in the file. .It Fl N , -name This option causes the stored filename in the input file to be used diff --git a/usr.bin/gzip/gzip.c b/usr.bin/gzip/gzip.c index de30a08..05bdc94 100644 --- a/usr.bin/gzip/gzip.c +++ b/usr.bin/gzip/gzip.c @@ -1,8 +1,8 @@ -/* $NetBSD: gzip.c,v 1.67 2004/09/11 11:07:44 dsl Exp $ */ +/* $NetBSD: gzip.c,v 1.91 2008/05/29 14:51:27 mrg Exp $ */ /* $DragonFly: src/usr.bin/gzip/gzip.c,v 1.7 2007/12/06 19:54:52 hasso Exp $ */ /* - * Copyright (c) 1997, 1998, 2003, 2004 Matthew R. Green + * Copyright (c) 1997, 1998, 2003, 2004, 2006 Matthew R. Green * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -13,8 +13,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -57,15 +55,16 @@ #include #include #include +#include #include #include #ifndef PRIdOFF -#define PRIdOFF PRId64 +#define PRIdOFF PRId64 #endif #ifndef PRId64 -#define PRId64 "lld" +#define PRId64 "lld" #endif /* what type of file are we dealing with */ @@ -139,7 +138,7 @@ static suffixes_t suffixes[] = { }; #define NUM_SUFFIXES (sizeof suffixes / sizeof suffixes[0]) -static const char gzip_version[] = "NetBSD gzip 20040830"; +static const char gzip_version[] = "NetBSD gzip 20060927"; static int cflag; /* stdout mode */ static int dflag; /* decompress mode */ @@ -191,17 +190,18 @@ static void print_list(int fd, off_t, const char *, time_t); static void usage(void); static void display_version(void); static const suffixes_t *check_suffix(char *, int); +static ssize_t read_retry(int, void *, size_t); #ifdef SMALL #define unlink_input(f, sb) unlink(f) #else -static off_t cat_fd(unsigned char *, ssize_t, off_t *, int fd); +static off_t cat_fd(unsigned char *, size_t, off_t *, int fd); static void prepend_gzip(char *, int *, char ***); static void handle_dir(char *); static void print_verbage(const char *, const char *, off_t, off_t); static void print_test(const char *, int); -static void copymodes(const char *, struct stat *); -static int check_outfile(const char *outfile, struct stat *sb); +static void copymodes(int fd, const struct stat *, const char *file); +static int check_outfile(const char *outfile); #endif #ifndef NO_BZIP2_SUPPORT @@ -277,13 +277,18 @@ main(int argc, char **argv) dflag = cflag = 1; #ifdef SMALL -#define OPT_LIST "cdhHltV123456789" +#define OPT_LIST "123456789cdhltV" #else -#define OPT_LIST "cdfhHklnNqrS:tvV123456789" +#define OPT_LIST "123456789cdfhklNnqrS:tVv" #endif while ((ch = getopt_long(argc, argv, OPT_LIST, longopts, NULL)) != -1) { switch (ch) { + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + numflag = ch - '0'; + break; case 'c': cflag = 1; break; @@ -297,11 +302,6 @@ main(int argc, char **argv) case 'V': display_version(); /* NOTREACHED */ - case '1': case '2': case '3': - case '4': case '5': case '6': - case '7': case '8': case '9': - numflag = ch - '0'; - break; #ifndef SMALL case 'f': fflag = 1; @@ -309,14 +309,14 @@ main(int argc, char **argv) case 'k': kflag = 1; break; - case 'n': - nflag = 1; - Nflag = 0; - break; case 'N': nflag = 0; Nflag = 1; break; + case 'n': + nflag = 1; + Nflag = 0; + break; case 'q': qflag = 1; break; @@ -550,7 +550,7 @@ gz_compress(int in, int out, off_t *gsizep, const char *origname, uint32_t mtime z.avail_out = BUFLEN - i; error = deflateInit2(&z, numflag, Z_DEFLATED, - -MAX_WBITS, 8, Z_DEFAULT_STRATEGY); + (-MAX_WBITS), 8, Z_DEFAULT_STRATEGY); if (error != Z_OK) { maybe_warnx("deflateInit2 failed"); in_tot = -1; @@ -562,7 +562,7 @@ gz_compress(int in, int out, off_t *gsizep, const char *origname, uint32_t mtime if (z.avail_out == 0) { if (write(out, outbufp, BUFLEN) != BUFLEN) { maybe_warn("write"); - in_tot = -1; + out_tot = -1; goto out; } @@ -597,7 +597,8 @@ gz_compress(int in, int out, off_t *gsizep, const char *origname, uint32_t mtime /* clean up */ for (;;) { - ssize_t len; + size_t len; + ssize_t w; error = deflate(&z, Z_FINISH); if (error != Z_OK && error != Z_STREAM_END) { @@ -608,7 +609,8 @@ gz_compress(int in, int out, off_t *gsizep, const char *origname, uint32_t mtime len = (char *)z.next_out - outbufp; - if (write(out, outbufp, len) != len) { + w = write(out, outbufp, len); + if (w == -1 || (size_t)w != len) { maybe_warn("write"); out_tot = -1; goto out; @@ -638,6 +640,10 @@ gz_compress(int in, int out, off_t *gsizep, const char *origname, uint32_t mtime (int)(in_tot >> 24) & 0xff); if (i != 8) maybe_err("snprintf"); +#if 0 + if (in_tot > 0xffffffff) + maybe_warn("input file size >= 4GB cannot be saved"); +#endif if (write(out, outbufp, i) != i) { maybe_warn("write"); in_tot = -1; @@ -665,7 +671,7 @@ gz_uncompress(int in, int out, char *pre, size_t prelen, off_t *gsizep, { z_stream z; char *outbufp, *inbufp; - off_t out_tot = prelen, in_tot = 0; + off_t out_tot = -1, in_tot = 0; uint32_t out_sub_tot = 0; enum { GZSTATE_MAGIC0, @@ -686,9 +692,10 @@ gz_uncompress(int in, int out, char *pre, size_t prelen, off_t *gsizep, GZSTATE_LEN, } state = GZSTATE_MAGIC0; int flags = 0, skip_count = 0; - int error = 0, done_reading = 0; + int error = Z_STREAM_ERROR, done_reading = 0; uLong crc = 0; ssize_t wr; + int needmore = 0; #define ADVANCE() { z.next_in++; z.avail_in--; } @@ -710,39 +717,50 @@ gz_uncompress(int in, int out, char *pre, size_t prelen, off_t *gsizep, z.zfree = NULL; z.opaque = 0; + in_tot = prelen; + out_tot = 0; for (;;) { - if (z.avail_in == 0 && done_reading == 0) { - ssize_t in_size = read(in, inbufp, BUFLEN); + if ((z.avail_in == 0 || needmore) && done_reading == 0) { + ssize_t in_size; + + if (z.avail_in > 0) { + memmove(inbufp, z.next_in, z.avail_in); + } + z.next_in = inbufp; + in_size = read(in, z.next_in + z.avail_in, + BUFLEN - z.avail_in); if (in_size == -1) { -#ifndef SMALL - if (tflag && vflag) - print_test(filename, 0); -#endif maybe_warn("failed to read stdin"); - out_tot = -1; - goto stop; - } else if (in_size == 0) + goto stop_and_fail; + } else if (in_size == 0) { done_reading = 1; + } - z.avail_in = in_size; - z.next_in = inbufp; + z.avail_in += in_size; + needmore = 0; in_tot += in_size; } if (z.avail_in == 0) { - if (done_reading && state != GZSTATE_MAGIC0) + if (done_reading && state != GZSTATE_MAGIC0) { maybe_warnx("%s: unexpected end of file", filename); + goto stop_and_fail; + } goto stop; } switch (state) { case GZSTATE_MAGIC0: if (*z.next_in != GZIP_MAGIC0) { + if (in_tot > 0) { + maybe_warnx("%s: trailing garbage " + "ignored", filename); + goto stop; + } maybe_warnx("input not gziped (MAGIC0)"); - out_tot = -1; - goto stop; + goto stop_and_fail; } ADVANCE(); state++; @@ -754,8 +772,7 @@ gz_uncompress(int in, int out, char *pre, size_t prelen, off_t *gsizep, if (*z.next_in != GZIP_MAGIC1 && *z.next_in != GZIP_OMAGIC1) { maybe_warnx("input not gziped (MAGIC1)"); - out_tot = -1; - goto stop; + goto stop_and_fail; } ADVANCE(); state++; @@ -764,8 +781,7 @@ gz_uncompress(int in, int out, char *pre, size_t prelen, off_t *gsizep, case GZSTATE_METHOD: if (*z.next_in != Z_DEFLATED) { maybe_warnx("unknown compression method"); - out_tot = -1; - goto stop; + goto stop_and_fail; } ADVANCE(); state++; @@ -849,18 +865,37 @@ gz_uncompress(int in, int out, char *pre, size_t prelen, off_t *gsizep, case GZSTATE_INIT: if (inflateInit2(&z, -MAX_WBITS) != Z_OK) { maybe_warnx("failed to inflateInit"); - out_tot = -1; - goto stop; + goto stop_and_fail; } state++; break; case GZSTATE_READ: error = inflate(&z, Z_FINISH); + switch (error) { /* Z_BUF_ERROR goes with Z_FINISH... */ - if (error != Z_STREAM_END && error != Z_BUF_ERROR) - /* Just need more input */ + case Z_BUF_ERROR: + case Z_STREAM_END: + case Z_OK: break; + + case Z_NEED_DICT: + maybe_warnx("Z_NEED_DICT error"); + goto stop_and_fail; + case Z_DATA_ERROR: + maybe_warnx("data stream error"); + goto stop_and_fail; + case Z_STREAM_ERROR: + maybe_warnx("internal stream error"); + goto stop_and_fail; + case Z_MEM_ERROR: + maybe_warnx("memory allocation error"); + goto stop_and_fail; + + default: + maybe_warn("unknown error from inflate(): %d", + error); + } wr = BUFLEN - z.avail_out; if (wr != 0) { @@ -872,8 +907,7 @@ gz_uncompress(int in, int out, char *pre, size_t prelen, off_t *gsizep, #endif write(out, outbufp, wr) != wr) { maybe_warn("error writing to output"); - out_tot = -1; - goto stop; + goto stop_and_fail; } out_tot += wr; @@ -891,17 +925,16 @@ gz_uncompress(int in, int out, char *pre, size_t prelen, off_t *gsizep, break; case GZSTATE_CRC: { - static int empty_buffer = 0; uLong origcrc; if (z.avail_in < 4) { - if (!done_reading && empty_buffer++ < 4) + if (!done_reading) { + needmore = 1; continue; + } maybe_warnx("truncated input"); - out_tot = -1; - goto stop; + goto stop_and_fail; } - empty_buffer = 0; origcrc = ((unsigned)z.next_in[0] & 0xff) | ((unsigned)z.next_in[1] & 0xff) << 8 | ((unsigned)z.next_in[2] & 0xff) << 16 | @@ -909,31 +942,30 @@ gz_uncompress(int in, int out, char *pre, size_t prelen, off_t *gsizep, if (origcrc != crc) { maybe_warnx("invalid compressed" " data--crc error"); - out_tot = -1; - goto stop; + goto stop_and_fail; } } z.avail_in -= 4; z.next_in += 4; - if (!z.avail_in) + if (!z.avail_in && done_reading) { goto stop; + } state++; break; case GZSTATE_LEN: { - static int empty_buffer = 0; uLong origlen; if (z.avail_in < 4) { - if (!done_reading && empty_buffer++ < 4) + if (!done_reading) { + needmore = 1; continue; + } maybe_warnx("truncated input"); - out_tot = -1; - goto stop; + goto stop_and_fail; } - empty_buffer = 0; origlen = ((unsigned)z.next_in[0] & 0xff) | ((unsigned)z.next_in[1] & 0xff) << 8 | ((unsigned)z.next_in[2] & 0xff) << 16 | @@ -942,8 +974,7 @@ gz_uncompress(int in, int out, char *pre, size_t prelen, off_t *gsizep, if (origlen != out_sub_tot) { maybe_warnx("invalid compressed" " data--length error"); - out_tot = -1; - goto stop; + goto stop_and_fail; } } @@ -952,24 +983,20 @@ gz_uncompress(int in, int out, char *pre, size_t prelen, off_t *gsizep, if (error < 0) { maybe_warnx("decompression error"); - out_tot = -1; - goto stop; + goto stop_and_fail; } state = GZSTATE_MAGIC0; break; } continue; +stop_and_fail: + out_tot = -1; stop: break; } if (state > GZSTATE_INIT) inflateEnd(&z); -#ifndef SMALL - if (tflag && vflag) - print_test(filename, out_tot != -1); -#endif - free(inbufp); out1: free(outbufp); @@ -981,12 +1008,14 @@ out2: #ifndef SMALL /* - * set the owner, mode, flags & utimes for a file + * set the owner, mode, flags & utimes using the given file descriptor. + * file is only used in possible warning messages. */ static void -copymodes(const char *file, struct stat *sbp) +copymodes(int fd, const struct stat *sbp, const char *file) { struct timeval times[2]; + struct stat sb; /* * If we have no info on the input, give this file some @@ -995,30 +1024,31 @@ copymodes(const char *file, struct stat *sbp) if (sbp == NULL) { mode_t mask = umask(022); - (void)chmod(file, DEFFILEMODE & ~mask); + (void)fchmod(fd, DEFFILEMODE & ~mask); (void)umask(mask); return; } + sb = *sbp; /* if the chown fails, remove set-id bits as-per compress(1) */ - if (chown(file, sbp->st_uid, sbp->st_gid) < 0) { + if (fchown(fd, sb.st_uid, sb.st_gid) < 0) { if (errno != EPERM) - maybe_warn("couldn't chown: %s", file); - sbp->st_mode &= ~(S_ISUID|S_ISGID); + maybe_warn("couldn't fchown: %s", file); + sb.st_mode &= ~(S_ISUID|S_ISGID); } /* we only allow set-id and the 9 normal permission bits */ - sbp->st_mode &= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; - if (chmod(file, sbp->st_mode) < 0) - maybe_warn("couldn't chmod: %s", file); + sb.st_mode &= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; + if (fchmod(fd, sb.st_mode) < 0) + maybe_warn("couldn't fchmod: %s", file); /* only try flags if they exist already */ - if (sbp->st_flags != 0 && chflags(file, sbp->st_flags) < 0) - maybe_warn("couldn't chflags: %s", file); + if (sb.st_flags != 0 && fchflags(fd, sb.st_flags) < 0) + maybe_warn("couldn't fchflags: %s", file); - TIMESPEC_TO_TIMEVAL(×[0], &sbp->st_atimespec); - TIMESPEC_TO_TIMEVAL(×[1], &sbp->st_mtimespec); - if (utimes(file, times) < 0) + TIMESPEC_TO_TIMEVAL(×[0], &sb.st_atimespec); + TIMESPEC_TO_TIMEVAL(×[1], &sb.st_mtimespec); + if (futimes(fd, times) < 0) maybe_warn("couldn't utimes: %s", file); } #endif @@ -1049,11 +1079,12 @@ file_gettype(u_char *buf) #ifndef SMALL /* check the outfile is OK. */ static int -check_outfile(const char *outfile, struct stat *sb) +check_outfile(const char *outfile) { + struct stat sb; int ok = 1; - if (lflag == 0 && stat(outfile, sb) == 0) { + if (lflag == 0 && stat(outfile, &sb) == 0) { if (fflag) unlink(outfile); else if (isatty(STDIN_FILENO)) { @@ -1076,13 +1107,12 @@ check_outfile(const char *outfile, struct stat *sb) } static void -unlink_input(const char *file, struct stat *sb) +unlink_input(const char *file, const struct stat *sb) { struct stat nsb; if (kflag) return; - if (stat(file, &nsb) != 0) /* Must be gone alrady */ return; @@ -1137,7 +1167,7 @@ file_compress(char *file, char *outfile, size_t outsize) if (cflag == 0) { #ifndef SMALL - if (stat(file, &isb) == 0) { + if (fstat(in, &isb) == 0) { if (isb.st_nlink > 1 && fflag == 0) { maybe_warnx("%s has %d other link%s -- " "skipping", file, isb.st_nlink - 1, @@ -1163,7 +1193,7 @@ file_compress(char *file, char *outfile, size_t outsize) suffixes[0].zipped, suffixes[0].ziplen + 1); #ifndef SMALL - if (check_outfile(outfile, &osb) == 0) { + if (check_outfile(outfile) == 0) { close(in); return -1; } @@ -1194,11 +1224,8 @@ file_compress(char *file, char *outfile, size_t outsize) if (cflag != 0) return insize == -1 ? -1 : size; - if (close(out) == -1) - maybe_warn("couldn't close ouput"); - #ifndef SMALL - if (stat(outfile, &osb) < 0) { + if (fstat(out, &osb) != 0) { maybe_warn("couldn't stat: %s", outfile); goto bad_outfile; } @@ -1210,8 +1237,10 @@ file_compress(char *file, char *outfile, size_t outsize) goto bad_outfile; } - copymodes(outfile, &isb); + copymodes(out, &isb, outfile); #endif + if (close(out) == -1) + maybe_warn("couldn't close output"); /* output is good, ok to delete input */ unlink_input(file, &isb); @@ -1219,6 +1248,9 @@ file_compress(char *file, char *outfile, size_t outsize) #ifndef SMALL bad_outfile: + if (close(out) == -1) + maybe_warn("couldn't close output"); + maybe_warnx("leaving original %s", file); unlink(outfile); return size; @@ -1234,7 +1266,7 @@ file_uncompress(char *file, char *outfile, size_t outsize) ssize_t rbytes; unsigned char header1[4]; enum filetype method; - int fd, zfd = -1; + int rv, fd, ofd, zfd = -1; #ifndef SMALL time_t timestamp = 0; unsigned char name[PATH_MAX + 1]; @@ -1264,7 +1296,7 @@ file_uncompress(char *file, char *outfile, size_t outsize) if (rbytes == -1) maybe_warn("can't read %s", file); else - maybe_warnx("%s: unexpected end of file", file); + goto unexpected_EOF; goto lose; } @@ -1282,7 +1314,10 @@ file_uncompress(char *file, char *outfile, size_t outsize) if (method == FT_GZIP && Nflag) { unsigned char ts[4]; /* timestamp */ - if (pread(fd, ts, sizeof ts, GZIP_TIMESTAMP) != sizeof ts) { + rv = pread(fd, ts, sizeof ts, GZIP_TIMESTAMP); + if (rv >= 0 && rv < sizeof ts) + goto unexpected_EOF; + if (rv == -1) { if (!fflag) maybe_warn("can't read %s", file); goto lose; @@ -1322,7 +1357,7 @@ file_uncompress(char *file, char *outfile, size_t outsize) } if (nflag == 0 && timestamp) isb.st_mtime = timestamp; - if (check_outfile(outfile, &osb) == 0) + if (check_outfile(outfile) == 0) goto lose; #endif } @@ -1437,24 +1472,36 @@ file_uncompress(char *file, char *outfile, size_t outsize) /* * if we can't stat the file don't remove the file. */ - if (stat(outfile, &osb) < 0) { + + ofd = open(outfile, O_RDWR, 0); + if (ofd == -1) { + maybe_warn("couldn't open (leaving original): %s", + outfile); + return -1; + } + if (fstat(ofd, &osb) != 0) { maybe_warn("couldn't stat (leaving original): %s", outfile); + close(ofd); return -1; } if (osb.st_size != size) { - maybe_warn("stat gave different size: %" PRIdOFF + maybe_warnx("stat gave different size: %" PRIdOFF " != %" PRIdOFF " (leaving original)", size, osb.st_size); + close(ofd); unlink(outfile); return -1; } unlink_input(file, &isb); #ifndef SMALL - copymodes(outfile, &isb); + copymodes(ofd, &isb, outfile); #endif + close(ofd); return size; + unexpected_EOF: + maybe_warnx("%s: unexpected end of file", file); lose: if (fd != -1) close(fd); @@ -1465,18 +1512,21 @@ file_uncompress(char *file, char *outfile, size_t outsize) #ifndef SMALL static off_t -cat_fd(unsigned char * prepend, ssize_t count, off_t *gsizep, int fd) +cat_fd(unsigned char * prepend, size_t count, off_t *gsizep, int fd) { char buf[BUFLEN]; - ssize_t rv; off_t in_tot; + ssize_t w; in_tot = count; - if (write(STDOUT_FILENO, prepend, count) != count) { + w = write(STDOUT_FILENO, prepend, count); + if (w == -1 || (size_t)w != count) { maybe_warn("write to stdout"); return -1; } for (;;) { + ssize_t rv; + rv = read(fd, buf, sizeof buf); if (rv == 0) break; @@ -1504,6 +1554,7 @@ handle_stdin(void) unsigned char header1[4]; off_t usize, gsize; enum filetype method; + ssize_t bytes_read; #ifndef NO_COMPRESS_SUPPORT FILE *in; #endif @@ -1527,9 +1578,13 @@ handle_stdin(void) return; } - if (read(STDIN_FILENO, header1, sizeof header1) != sizeof header1) { + bytes_read = read_retry(STDIN_FILENO, header1, sizeof header1); + if (bytes_read == -1) { maybe_warn("can't read stdin"); return; + } else if (bytes_read != sizeof(header1)) { + maybe_warnx("(stdin): unexpected end of file"); + return; } method = file_gettype(header1); @@ -1569,6 +1624,8 @@ handle_stdin(void) #ifndef SMALL if (vflag && !tflag && usize != -1 && gsize != -1) print_verbage(NULL, NULL, usize, gsize); + if (vflag && tflag) + print_test("(stdin)", usize != -1); #endif } @@ -1577,6 +1634,10 @@ static void handle_stdout(void) { off_t gsize, usize; + struct stat sb; + time_t systime; + uint32_t mtime; + int ret; #ifndef SMALL if (fflag == 0 && isatty(STDOUT_FILENO)) { @@ -1584,9 +1645,31 @@ handle_stdout(void) return; } #endif - usize = gz_compress(STDIN_FILENO, STDOUT_FILENO, &gsize, "", 0); + /* If stdin is a file use it's mtime, otherwise use current time */ + ret = fstat(STDIN_FILENO, &sb); #ifndef SMALL + if (ret < 0) { + maybe_warn("Can't stat stdin"); + return; + } +#endif + + if (S_ISREG(sb.st_mode)) + mtime = (uint32_t)sb.st_mtime; + else { + systime = time(NULL); +#ifndef SMALL + if (systime == -1) { + maybe_warn("time"); + return; + } +#endif + mtime = (uint32_t)systime; + } + + usize = gz_compress(STDIN_FILENO, STDOUT_FILENO, &gsize, "", mtime); +#ifndef SMALL if (vflag && !tflag && usize != -1 && gsize != -1) print_verbage(NULL, NULL, usize, gsize); #endif @@ -1611,7 +1694,7 @@ handle_pathname(char *path) } retry: - if (stat(path, &sb) < 0) { + if (stat(path, &sb) != 0) { /* lets try .gz if we're decompressing */ if (dflag && s == NULL && errno == ENOENT) { len = strlen(path); @@ -1658,6 +1741,10 @@ handle_file(char *file, struct stat *sbp) infile = file; if (dflag) { usize = file_uncompress(file, outfile, sizeof(outfile)); +#ifndef SMALL + if (vflag && tflag) + print_test(file, usize != -1); +#endif if (usize == -1) return; gsize = sbp->st_size; @@ -1790,8 +1877,7 @@ print_list(int fd, off_t out, const char *outfile, time_t ts) static off_t in_tot, out_tot; uint32_t crc = 0; #endif - off_t in = 0; - int rv; + off_t in = 0, rv; if (first) { #ifndef SMALL @@ -1818,13 +1904,21 @@ print_list(int fd, off_t out, const char *outfile, time_t ts) unsigned char buf[8]; uint32_t usize; - if (read(fd, (char *)buf, sizeof(buf)) != sizeof(buf)) + rv = read(fd, (char *)buf, sizeof(buf)); + if (rv == -1) maybe_warn("read of uncompressed size"); - usize = buf[4] | buf[5] << 8 | buf[6] << 16 | buf[7] << 24; - in = (off_t)usize; + else if (rv != sizeof(buf)) + maybe_warnx("read of uncompressed size"); + + else { + usize = buf[4] | buf[5] << 8 | + buf[6] << 16 | buf[7] << 24; + in = (off_t)usize; #ifndef SMALL - crc = buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24; + crc = buf[0] | buf[1] << 8 | + buf[2] << 16 | buf[3] << 24; #endif + } } } @@ -1855,30 +1949,31 @@ usage(void) fprintf(stderr, "%s\n", gzip_version); fprintf(stderr, #ifdef SMALL - "usage: %s [-" OPT_LIST "] [ [ ...]]\n", + "usage: %s [-" OPT_LIST "] [ [ ...]]\n", #else - "usage: %s [-123456789acdfhklLNnqrtVv] [-S .suffix] [ [ ...]]\n" - " -c --stdout write to stdout, keep original files\n" - " --to-stdout\n" - " -d --decompress uncompress files\n" - " --uncompress\n" - " -f --force force overwriting & compress links\n" - " -h --help display this help\n" - " -k --keep don't delete input files during operation\n" - " -n --no-name don't save original file name or time stamp\n" - " -N --name save or restore original file name and time stamp\n" - " -q --quiet output no warnings\n" - " -r --recursive recursively compress files in directories\n" - " -S .suf use suffix .suf instead of .gz\n" - " --suffix .suf\n" - " -t --test test compressed file\n" - " -v --verbose print extra statistics\n" - " -V --version display program version\n" - " -1 --fast fastest (worst) compression\n" - " -2 .. -8 set compression level\n" - " -9 --best best (slowest) compression\n", -#endif - getprogname()); + "usage: %s [-123456789acdfhklLNnqrtVv] [-S .suffix] [ [ ...]]\n" + " -1 --fast fastest (worst) compression\n" + " -2 .. -8 set compression level\n" + " -9 --best best (slowest) compression\n" + " -c --stdout write to stdout, keep original files\n" + " --to-stdout\n" + " -d --decompress uncompress files\n" + " --uncompress\n" + " -f --force force overwriting & compress links\n" + " -h --help display this help\n" + " -k --keep don't delete input files during operation\n" + " -l --list list compressed file contents\n" + " -N --name save or restore original file name and time stamp\n" + " -n --no-name don't save original file name or time stamp\n" + " -q --quiet output no warnings\n" + " -r --recursive recursively compress files in directories\n" + " -S .suf use suffix .suf instead of .gz\n" + " --suffix .suf\n" + " -t --test test compressed file\n" + " -V --version display program version\n" + " -v --verbose print extra statistics\n", +#endif + getprogname()); exit(0); } @@ -1897,3 +1992,25 @@ display_version(void) #ifndef NO_COMPRESS_SUPPORT #include "zuncompress.c" #endif + +static ssize_t +read_retry(int fd, void *buf, size_t sz) +{ + char *cp = buf; + size_t left = MIN(sz, (size_t) SSIZE_MAX); + + while (left > 0) { + ssize_t ret; + + ret = read(fd, cp, left); + if (ret == -1) { + return ret; + } else if (ret == 0) { + break; /* EOF */ + } + cp += ret; + left -= ret; + } + + return sz - left; +} diff --git a/usr.bin/gzip/unbzip2.c b/usr.bin/gzip/unbzip2.c index 696ceca..34b8000 100644 --- a/usr.bin/gzip/unbzip2.c +++ b/usr.bin/gzip/unbzip2.c @@ -1,13 +1,41 @@ -/* $NetBSD: unbzip2.c,v 1.5 2004/05/25 04:34:40 mrg Exp $ */ +/* $NetBSD: unbzip2.c,v 1.11 2008/04/28 20:24:13 martin Exp $ */ /* $DragonFly: src/usr.bin/gzip/unbzip2.c,v 1.1 2004/10/26 11:19:31 joerg Exp $ */ +/*- + * Copyright (c) 2006 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Simon Burge. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + /* This file is #included by gzip.c */ static off_t unbzip2(int in, int out, char *pre, size_t prelen, off_t *bytes_in) { int ret, end_of_file; - ssize_t n; off_t bytes_out = 0; bz_stream bzs; static char *inbuf, *outbuf; @@ -35,8 +63,10 @@ unbzip2(int in, int out, char *pre, size_t prelen, off_t *bytes_in) if (bytes_in) *bytes_in = prelen; - while (ret != BZ_STREAM_END) { + while (ret >= BZ_OK && ret != BZ_STREAM_END) { if (bzs.avail_in == 0 && !end_of_file) { + ssize_t n; + n = read(in, inbuf, BUFLEN); if (n < 0) maybe_err("read"); @@ -58,11 +88,13 @@ unbzip2(int in, int out, char *pre, size_t prelen, off_t *bytes_in) if (ret == BZ_OK && end_of_file) maybe_err("read"); if (!tflag) { + ssize_t n; + n = write(out, outbuf, BUFLEN - bzs.avail_out); if (n < 0) maybe_err("write"); + bytes_out += n; } - bytes_out += n; break; case BZ_DATA_ERROR: diff --git a/usr.bin/gzip/zdiff.1 b/usr.bin/gzip/zdiff.1 index 538aa21..8ff1134 100644 --- a/usr.bin/gzip/zdiff.1 +++ b/usr.bin/gzip/zdiff.1 @@ -89,7 +89,7 @@ Temporary file for .El .Sh SEE ALSO .Xr cmp 1 , -.Xr compress 1 , +.Xr gzip 1 , .Xr diff 1 .Sh CAVEATS .Nm zcmp diff --git a/usr.bin/gzip/zgrep b/usr.bin/gzip/zgrep index f5c889f..157d682 100644 --- a/usr.bin/gzip/zgrep +++ b/usr.bin/gzip/zgrep @@ -1,6 +1,6 @@ #!/bin/sh # -# $NetBSD: zgrep,v 1.3 2004/04/27 09:18:16 jdolecek Exp $ +# $NetBSD: zgrep,v 1.7 2008/05/08 15:35:23 wiz Exp $ # $DragonFly: src/usr.bin/gzip/zgrep,v 1.1 2004/10/26 11:19:31 joerg Exp $ # # Copyright (c) 2003 Thomas Klausner. @@ -13,8 +13,6 @@ # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. -# 3. The name of the author may not be used to endorse or promote products -# derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -33,6 +31,8 @@ zcat=/usr/bin/zcat endofopts=0 pattern_found=0 grep_args="" +hyphen=0 +silent=0 prg=$0 @@ -52,28 +52,35 @@ do case $1 in # from GNU grep-2.5.1 -- keep in sync! -[ABCDXdefm]) + if [ $# -lt 2 ] + then + echo "${prg}: missing argument for $1 flag" >&2 + exit 1 + fi case $1 in -e) - pattern_found=1;; + pattern="$2" + pattern_found=1 + shift 2 + break + ;; *) ;; esac - - if [ $# -lt 2 ] - then - echo "${prg}: missing argument for ${saved_arg} flag" >&2 - exit 1 - fi grep_args="${grep_args} $1 $2" shift 2 ;; --) - grep_args="${grep_args} $1" shift endofopts=1 ;; -) - endofopts=1 + hyphen=1 + shift + ;; + -h) + silent=1 + shift ;; -*) grep_args="${grep_args} $1" @@ -89,25 +96,30 @@ done # if no -e option was found, take next argument as grep-pattern if [ ${pattern_found} -lt 1 ] then - if [ $# -lt 1 ] - then + if [ $# -ge 1 ]; then + pattern="$1" + shift + elif [ ${hyphen} -gt 0 ]; then + pattern="-" + else echo "${prg}: missing pattern" >&2 exit 1 fi - pattern=$1 - shift fi # call grep ... if [ $# -lt 1 ] then # ... on stdin - ${zcat} -fq - | ${grep} ${grep_args} "${pattern}" - + ${zcat} -fq - | ${grep} ${grep_args} -- "${pattern}" - else # ... on all files given on the command line + if [ ${silent} -lt 1 ]; then + grep_args="-H ${grep_args}" + fi while [ $# -gt 0 ] do - ${zcat} -fq -- "$1" | ${grep} -H --label="${1}" "${pattern}" ${grep_args} - + ${zcat} -fq -- "$1" | ${grep} --label="${1}" ${grep_args} -- "${pattern}" - shift done fi diff --git a/usr.bin/gzip/zgrep.1 b/usr.bin/gzip/zgrep.1 index 1c67771..49dafd0 100644 --- a/usr.bin/gzip/zgrep.1 +++ b/usr.bin/gzip/zgrep.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: zgrep.1,v 1.1 2003/12/28 17:26:00 wiz Exp $ +.\" $NetBSD: zgrep.1,v 1.3 2008/05/08 15:35:23 wiz Exp $ .\" $DragonFly: src/usr.bin/gzip/zgrep.1,v 1.2 2006/03/01 08:08:44 swildner Exp $ .\" .\" Copyright (c) 2003 Thomas Klausner. @@ -11,8 +11,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES diff --git a/usr.bin/gzip/zmore b/usr.bin/gzip/zmore index 6cd50c0..cfa7d69 100644 --- a/usr.bin/gzip/zmore +++ b/usr.bin/gzip/zmore @@ -41,15 +41,21 @@ while test $# -ne 0; do esac done +if [ `basename $0` == "zless" ] ; then + pager=${PAGER-less} +else + pager=${PAGER-more} +fi + # No files means read from stdin if [ $# -eq 0 ]; then - gzip -cdfq 2>&1 | ${PAGER-more} $flags + gzip -cdfq 2>&1 | $pager $flags exit 0 fi oterm=`stty -g 2>/dev/null` while test $# -ne 0; do - gzip -cdfq "$1" 2>&1 | ${PAGER-more} $flags + gzip -cdfq "$1" 2>&1 | $pager $flags prev="$1" shift if tty -s && test -n "$oterm" -a $# -gt 0; then diff --git a/usr.bin/gzip/zmore.1 b/usr.bin/gzip/zmore.1 index a2d6a1e..b9e0ad4 100644 --- a/usr.bin/gzip/zmore.1 +++ b/usr.bin/gzip/zmore.1 @@ -1,5 +1,5 @@ .\" $NetBSD: zmore.1,v 1.2 2003/12/28 12:43:43 wiz Exp $ -.\" $OpenBSD: zmore.1,v 1.3 2003/06/23 21:00:48 deraadt Exp $ +.\" $OpenBSD: zmore.1,v 1.9 2007/05/31 19:20:09 jmc Exp $ .\" $DragonFly: src/usr.bin/gzip/zmore.1,v 1.2 2007/07/29 17:27:45 swildner Exp $ .\" .\" Copyright (c) 2003 Todd C. Miller @@ -20,16 +20,20 @@ .\" Agency (DARPA) and Air Force Research Laboratory, Air Force .\" Materiel Command, USAF, under agreement number F39502-99-1-0512. .\" -.Dd June 23, 2003 +.Dd May 31, 2008 .Dt ZMORE 1 .Os .Sh NAME -.Nm zmore -.Nd view compressed files on a CRT +.Nm zmore , +.Nm zless +.Nd view compressed files .Sh SYNOPSIS .Nm .Op Ar flags .Op Ar file ... +.Nm zless +.Op Ar flags +.Op Ar file ... .Sh DESCRIPTION .Nm is a filter that allows the viewing of files compressed with Lempel-Ziv @@ -51,6 +55,14 @@ that are specified are passed to the user's preferred .Pa /usr/bin/more by default). .Pp +.Nm zless +is equivalent to +.Nm zmore +but uses +.Xr less 1 +as a pager instead of +.Xr more 1 . +.Pp When multiple files are specified, .Nm will pause at the end of each file and present the following prompt to the user: @@ -86,9 +98,13 @@ style compression since there is no suffix on which to make a decision. Program used to display files. If unset, .Pa /usr/bin/more -is used. +is used +.Pq Nm zmore +or +.Pa /usr/bin/less +.Pq Nm zless . .El .Sh SEE ALSO -.Xr compress 1 , +.Xr gzip 1 , .Xr less 1 , .Xr more 1 diff --git a/usr.bin/gzip/znew b/usr.bin/gzip/znew index 1966ac6..4852a06 100644 --- a/usr.bin/gzip/znew +++ b/usr.bin/gzip/znew @@ -1,6 +1,6 @@ #!/bin/ksh - # -# $NetBSD: znew,v 1.2 2003/12/28 12:43:43 wiz Exp $ +# $NetBSD: znew,v 1.3 2008/04/27 09:07:13 nakayama Exp $ # $DragonFly: src/usr.bin/gzip/znew,v 1.1 2004/10/26 11:19:31 joerg Exp $ # $OpenBSD: znew,v 1.2 2003/08/05 18:22:17 deraadt Exp $ # @@ -59,7 +59,7 @@ process () { trap 'rm -f "$tmp"; exit 1' HUP INT QUIT PIPE TERM # Do the actual work, producing a file "$tmp" - if uncompress -f -c < "$filez" | gzip -f $gzipflags -o "$tmp"; then + if uncompress -f -c < "$filez" | gzip -f $gzipflags > "$tmp"; then if test $kflag -eq 1 && smaller "$filez" "$tmp"; then echo -n "$prog: $filez is smaller than $filegz" @@ -98,7 +98,7 @@ process () { } prog=`basename "$0"` -usage="usage: $prog [-ftv9K] file ..." +usage="usage: $prog [-9fKtv] file ..." fflag=0 tflag=0 diff --git a/usr.bin/gzip/zuncompress.c b/usr.bin/gzip/zuncompress.c index a5b021f..6cd7a8a 100644 --- a/usr.bin/gzip/zuncompress.c +++ b/usr.bin/gzip/zuncompress.c @@ -1,4 +1,4 @@ -/* $NetBSD: zuncompress.c,v 1.4 2004/05/25 04:34:40 mrg Exp $ */ +/* $NetBSD: zuncompress.c,v 1.6 2005/11/22 09:05:30 mrg Exp $ */ /* $DragonFly: src/usr.bin/gzip/zuncompress.c,v 1.1 2004/10/26 11:19:31 joerg Exp $ */ /*- @@ -147,7 +147,7 @@ zuncompress(FILE *in, FILE *out, char *pre, size_t prelen, compressed_pre = NULL; while ((bin = fread(buf, 1, sizeof(buf), in)) != 0) { - if (fwrite(buf, 1, bin, out) != bin) { + if (tflag == 0 && fwrite(buf, 1, bin, out) != bin) { free(buf); return -1; }