Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/gzip Redo suffix handling so that gunzip xxx.tgx => ...



details:   https://anonhg.NetBSD.org/src/rev/98228d05c2cb
branches:  trunk
changeset: 569701:98228d05c2cb
user:      dsl <dsl%NetBSD.org@localhost>
date:      Mon Aug 30 14:36:51 2004 +0000

description:
Redo suffix handling so that gunzip xxx.tgx => xxx.tar
Rework logic of gz_{un}compress to make it much less likely to leak fds
    (at least 2 non-error paths leaked them!)
Make -S ".xyz" and -S "" both do something sensible.
Make in-situ compression work - only lose the file on error.
Pass an open fd to zopen (renamed zdopen) to avoid fd leakage (was badly borked)
Write header into first 64k output block to writes are aligned.
    (more efficient and might avoid some problem with code that doesn't
    like receiving partial buffers)
Check file size on compression - double checks against fs full.
Remove some pointless casts, and otherwise simplify some logic.

diffstat:

 usr.bin/gzip/gzip.c        |  673 ++++++++++++++++++++++----------------------
 usr.bin/gzip/zuncompress.c |   28 +-
 2 files changed, 353 insertions(+), 348 deletions(-)

diffs (truncated from 1180 to 300 lines):

diff -r 245bee322013 -r 98228d05c2cb usr.bin/gzip/gzip.c
--- a/usr.bin/gzip/gzip.c       Mon Aug 30 12:54:39 2004 +0000
+++ b/usr.bin/gzip/gzip.c       Mon Aug 30 14:36:51 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: gzip.c,v 1.62 2004/07/16 22:44:01 he Exp $     */
+/*     $NetBSD: gzip.c,v 1.63 2004/08/30 14:36:51 dsl Exp $    */
 
 /*
  * Copyright (c) 1997, 1998, 2003, 2004 Matthew R. Green
@@ -32,14 +32,13 @@
 #ifndef lint
 __COPYRIGHT("@(#) Copyright (c) 1997, 1998, 2003, 2004 Matthew R. Green\n\
      All rights reserved.\n");
-__RCSID("$NetBSD: gzip.c,v 1.62 2004/07/16 22:44:01 he Exp $");
+__RCSID("$NetBSD: gzip.c,v 1.63 2004/08/30 14:36:51 dsl Exp $");
 #endif /* not lint */
 
 /*
  * gzip.c -- GPL free gzip using zlib.
  *
  * TODO:
- *     - handle .taz/.tgz files?
  *     - use mmap where possible
  *     - handle some signals better (remove outfile?)
  *     - make bzip2/compress -v/-t/-l support work as well as possible
@@ -49,6 +48,7 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 
+#include <inttypes.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <string.h>
@@ -62,6 +62,10 @@
 #include <stdarg.h>
 #include <getopt.h>
 
+#ifndef PRIdOFF
+#define PRIdOFF PRId64
+#endif
+
 /* what type of file are we dealing with */
 enum filetype {
        FT_GZIP,
@@ -105,20 +109,36 @@
 
 #define OS_CODE                3       /* Unix */
 
+typedef struct {
+    char       zipped[8];
+    int                ziplen;
+    char       normal[8];
+    int                norlen;
+} suffixes_t;
+static suffixes_t suffixes[] = {
+#define        SUFFIX(Z, N) {Z, sizeof Z - 1, N, sizeof N - 0}
+       SUFFIX(GZ_SUFFIX,       ""),    /* Overwritten by -S .xxx */
 #ifndef SMALL
-static char    const *suffixes[] = {
-       GZ_SUFFIX, ".z", ".taz", ".tgz", "-gz", "-z", "_z",
+       SUFFIX(GZ_SUFFIX,       ""),
+       SUFFIX(".z",            ""),
+       SUFFIX("-gz",           ""),
+       SUFFIX("-z",            ""),
+       SUFFIX("_z",            ""),
+       SUFFIX(".taz",          ".tar"),
+       SUFFIX(".tgz",          ".tar"),
 #ifndef NO_BZIP2_SUPPORT
-       BZ2_SUFFIX,
+       SUFFIX(BZ2_SUFFIX,      ""),
 #endif
 #ifndef NO_COMPRESS_SUPPORT
-       Z_SUFFIX,
+       SUFFIX(Z_SUFFIX,        ""),
 #endif
-       NULL
+       SUFFIX(GZ_SUFFIX,       ""),    /* Overwritten by -S "" */
+#endif /* SMALL */
+#undef SUFFIX
 };
-#endif /* SMALL */
+#define NUM_SUFFIXES (sizeof suffixes / sizeof suffixes[0])
 
-static const char      gzip_version[] = "NetBSD gzip 20040711";
+static const char      gzip_version[] = "NetBSD gzip 20040830";
 
 static int     cflag;                  /* stdout mode */
 static int     dflag;                  /* decompress mode */
@@ -132,7 +152,6 @@
 static int     qflag;                  /* quiet mode */
 static int     rflag;                  /* recursive mode */
 static int     tflag;                  /* test */
-static char    *Sflag;
 static int     vflag;                  /* verbose mode */
 #else
 #define                qflag   0
@@ -140,16 +159,21 @@
 
 static int     exit_value = 0;         /* exit value */
 
-static const char      *suffix;
-#define suffix_len     (strlen(suffix) + 1)    /* len + nul */
 static char    *infile;                /* name of file coming in */
 
-static void    maybe_err(const char *fmt, ...);
-static void    maybe_errx(const char *fmt, ...);
-static void    maybe_warn(const char *fmt, ...);
-static void    maybe_warnx(const char *fmt, ...);
+static void    maybe_err(const char *fmt, ...)
+    __attribute__((__format__(__printf__, 1, 2)));
+static void    maybe_errx(const char *fmt, ...)
+    __attribute__((__format__(__printf__, 1, 2)));
+static void    maybe_warn(const char *fmt, ...)
+    __attribute__((__format__(__printf__, 1, 2)));
+static void    maybe_warnx(const char *fmt, ...)
+    __attribute__((__format__(__printf__, 1, 2)));
 static enum filetype file_gettype(u_char *);
-static off_t   gz_compress(FILE *, int, off_t *, const char *, time_t);
+#ifdef SMALL
+#define gz_compress(if, of, sz, fn, tm) gz_compress(if, of, sz)
+#endif
+static off_t   gz_compress(int, int, off_t *, const char *, uint32_t);
 static off_t   gz_uncompress(int, int, char *, size_t, off_t *, const char *);
 static off_t   file_compress(char *, char *, size_t);
 static off_t   file_uncompress(char *, char *, size_t);
@@ -162,15 +186,17 @@
 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);
 
-#ifndef SMALL
+#ifdef SMALL
+#define unlink_input(f, sb) unlink(f)
+#else
 static void    prepend_gzip(char *, int *, char ***);
 static void    handle_dir(char *, struct stat *);
-static void    print_verbage(char *, char *, off_t, off_t);
+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 const char *check_suffix(char *);
 #endif
 
 #ifndef NO_BZIP2_SUPPORT
@@ -178,7 +204,7 @@
 #endif
 
 #ifndef NO_COMPRESS_SUPPORT
-static FILE    *zopen(const char *, FILE *);
+static FILE    *zdopen(int);
 static off_t   zuncompress(FILE *, FILE *, char *, size_t, off_t *);
 #endif
 
@@ -223,13 +249,12 @@
        const char *progname = getprogname();
 #ifndef SMALL
        char *gzip;
+       int len;
 #endif
        int ch;
 
        /* XXX set up signals */
 
-       suffix = GZ_SUFFIX;
-
 #ifndef SMALL
        if ((gzip = getenv("GZIP")) != NULL)
                prepend_gzip(gzip, &argc, &argv);
@@ -251,7 +276,7 @@
 #define OPT_LIST "cdfhHlnNqrS:tvV123456789"
 #endif
 
-       while ((ch = getopt_long(argc, argv, OPT_LIST, longopts, NULL)) != -1)
+       while ((ch = getopt_long(argc, argv, OPT_LIST, longopts, NULL)) != -1) {
                switch (ch) {
                case 'c':
                        cflag = 1;
@@ -290,7 +315,17 @@
                        rflag = 1;
                        break;
                case 'S':
-                       Sflag = optarg;
+                       len = strlen(optarg);
+                       if (len >= sizeof suffixes[0].zipped)
+                               /* 7 bytes of suffix is enough for anyone... */
+                               usage();
+                       if (len != 0) {
+                               memcpy(suffixes[0].zipped, optarg, len + 1);
+                               suffixes[0].ziplen = len;
+                       } else {
+                               suffixes[NUM_SUFFIXES - 1].zipped[0] = 0;
+                               suffixes[NUM_SUFFIXES - 1].ziplen = 0;
+                       }
                        break;
                case 't':
                        cflag = 1;
@@ -305,6 +340,7 @@
                        usage();
                        /* NOTREACHED */
                }
+       }
        argv += optind;
        argc -= optind;
 
@@ -442,53 +478,61 @@
 }
 #endif
 
-/* compress input to output then close both files */
+/* compress input to output. Return bytes read, -1 on error */
 static off_t
-gz_compress(FILE *in, int out, off_t *gsizep, const char *origname, time_t mtime)
+gz_compress(int in, int out, off_t *gsizep, const char *origname, uint32_t mtime)
 {
        z_stream z;
        char *outbufp, *inbufp;
        off_t in_tot = 0, out_tot = 0;
        ssize_t in_size;
-       char *str;
        int i, error;
        uLong crc;
+#ifdef SMALL
+       static char header[] = { GZIP_MAGIC0, GZIP_MAGIC1, Z_DEFLATED, 0,
+                                0, 0, 0, 0,
+                                0, OS_CODE };
+#endif
 
-       if ((outbufp = malloc(BUFLEN)) == NULL) {
+       outbufp = malloc(BUFLEN);
+       inbufp = malloc(BUFLEN);
+       if (outbufp == NULL || inbufp == NULL) {
                maybe_err("malloc failed");
-               goto out2;
-       }
-       if ((inbufp = malloc(BUFLEN)) == NULL) {
-               maybe_err("malloc failed");
-               goto out1;
+               goto out;
        }
 
-       i = asprintf(&str, "%c%c%c%c%c%c%c%c%c%c%s", 
-                    GZIP_MAGIC0, GZIP_MAGIC1,
-                    Z_DEFLATED, origname ? ORIG_NAME : 0,
-                    (int)mtime & 0xff,
-                    (int)(mtime >> 8) & 0xff,
-                    (int)(mtime >> 16) & 0xff,
-                    (int)(mtime >> 24) & 0xff,
-                    0, OS_CODE, origname ? origname : "");
-       if (i == -1)     
-               maybe_err("asprintf");
-       if (origname)
-               i++;
-       if (write(out, str, i) != i) {
-               maybe_warn("write");
-               in_tot = -1;
-               goto out;
-       }
-       free(str);
-
        memset(&z, 0, sizeof z);
-       z.next_out = outbufp;
-       z.avail_out = BUFLEN;
        z.zalloc = Z_NULL;
        z.zfree = Z_NULL;
        z.opaque = 0;
 
+#ifdef SMALL
+       memcpy(outbufp, header, sizeof header);
+       i = sizeof header;
+#else
+       if (nflag != 0) {
+               mtime = 0;
+               origname = "";
+       }
+
+       i = snprintf(outbufp, BUFLEN, "%c%c%c%c%c%c%c%c%c%c%s", 
+                    GZIP_MAGIC0, GZIP_MAGIC1, Z_DEFLATED,
+                    *origname ? ORIG_NAME : 0,
+                    mtime & 0xff,
+                    (mtime >> 8) & 0xff,
+                    (mtime >> 16) & 0xff,
+                    (mtime >> 24) & 0xff,
+                    0, OS_CODE, origname);
+       if (i >= BUFLEN)     
+               /* this need PATH_MAX > BUFLEN ... */
+               maybe_err("snprintf");
+       if (*origname)
+               i++;
+#endif
+
+       z.next_out = outbufp + i;
+       z.avail_out = BUFLEN - i;
+
        error = deflateInit2(&z, numflag, Z_DEFLATED,
                             -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
        if (error != Z_OK) {
@@ -512,9 +556,9 @@
                }



Home | Main Index | Thread Index | Old Index