[BACK]Return to gzip.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.bin / gzip

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/usr.bin/gzip/gzip.c between version 1.29.2.29.2.2 and 1.29.2.29.2.3

version 1.29.2.29.2.2, 2005/05/13 17:21:22 version 1.29.2.29.2.3, 2005/07/24 21:21:17
Line 38  __RCSID("$NetBSD$");
Line 38  __RCSID("$NetBSD$");
 /*  /*
  * gzip.c -- GPL free gzip using zlib.   * gzip.c -- GPL free gzip using zlib.
  *   *
    * RFC 1950 covers the zlib format
    * RFC 1951 covers the deflate format
    * RFC 1952 covers the gzip format
    *
  * TODO:   * TODO:
  *      - handle .taz/.tgz files?  
  *      - use mmap where possible   *      - use mmap where possible
  *      - handle some signals better (remove outfile?)   *      - handle some signals better (remove outfile?)
  *      - make bzip2/compress -v/-t/-l support work as well as possible   *      - make bzip2/compress -v/-t/-l support work as well as possible
Line 49  __RCSID("$NetBSD$");
Line 52  __RCSID("$NetBSD$");
 #include <sys/stat.h>  #include <sys/stat.h>
 #include <sys/time.h>  #include <sys/time.h>
   
   #include <inttypes.h>
 #include <unistd.h>  #include <unistd.h>
 #include <stdio.h>  #include <stdio.h>
 #include <string.h>  #include <string.h>
Line 63  __RCSID("$NetBSD$");
Line 67  __RCSID("$NetBSD$");
 #include <getopt.h>  #include <getopt.h>
 #include <time.h>  #include <time.h>
   
   #ifndef PRIdOFF
   #define PRIdOFF PRId64
   #endif
   
 /* what type of file are we dealing with */  /* what type of file are we dealing with */
 enum filetype {  enum filetype {
         FT_GZIP,          FT_GZIP,
Line 106  enum filetype {
Line 114  enum filetype {
   
 #define OS_CODE         3       /* Unix */  #define OS_CODE         3       /* Unix */
   
 #ifndef SMALL  typedef struct {
 static  char    const *suffixes[] = {      const char  *zipped;
         GZ_SUFFIX, ".z", ".taz", ".tgz", "-gz", "-z", "_z",      int         ziplen;
       const char  *normal;        /* for unzip - must not be longer than zipped */
   } suffixes_t;
   static suffixes_t suffixes[] = {
   #define SUFFIX(Z, N) {Z, sizeof Z - 1, N}
           SUFFIX(GZ_SUFFIX,       ""),    /* Overwritten by -S .xxx */
   #ifndef SMALL
           SUFFIX(GZ_SUFFIX,       ""),
           SUFFIX(".z",            ""),
           SUFFIX("-gz",           ""),
           SUFFIX("-z",            ""),
           SUFFIX("_z",            ""),
           SUFFIX(".taz",          ".tar"),
           SUFFIX(".tgz",          ".tar"),
 #ifndef NO_BZIP2_SUPPORT  #ifndef NO_BZIP2_SUPPORT
         BZ2_SUFFIX,          SUFFIX(BZ2_SUFFIX,      ""),
 #endif  #endif
 #ifndef NO_COMPRESS_SUPPORT  #ifndef NO_COMPRESS_SUPPORT
         Z_SUFFIX,          SUFFIX(Z_SUFFIX,        ""),
 #endif  #endif
         NULL          SUFFIX(GZ_SUFFIX,       ""),    /* Overwritten by -S "" */
 };  
 #endif /* SMALL */  #endif /* SMALL */
   #undef SUFFIX
   };
   #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     cflag;                  /* stdout mode */
 static  int     dflag;                  /* decompress mode */  static  int     dflag;                  /* decompress mode */
Line 133  static int Nflag;   /* don't restore nam
Line 156  static int Nflag;   /* don't restore nam
 static  int     qflag;                  /* quiet mode */  static  int     qflag;                  /* quiet mode */
 static  int     rflag;                  /* recursive mode */  static  int     rflag;                  /* recursive mode */
 static  int     tflag;                  /* test */  static  int     tflag;                  /* test */
 static  char    *Sflag;  
 static  int     vflag;                  /* verbose mode */  static  int     vflag;                  /* verbose mode */
 #else  #else
 #define         qflag   0  #define         qflag   0
   #define         tflag   0
 #endif  #endif
   
 static  int     exit_value = 0;         /* exit value */  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  char    *infile;                /* name of file coming in */
   
 static  void    maybe_err(const char *fmt, ...);  static  void    maybe_err(const char *fmt, ...)
 static  void    maybe_errx(const char *fmt, ...);      __attribute__((__format__(__printf__, 1, 2)));
 static  void    maybe_warn(const char *fmt, ...);  #ifndef NO_BZIP2_SUPPORT
 static  void    maybe_warnx(const char *fmt, ...);  static  void    maybe_errx(const char *fmt, ...)
       __attribute__((__format__(__printf__, 1, 2)));
   #endif
   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  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   gz_uncompress(int, int, char *, size_t, off_t *, const char *);
 static  off_t   file_compress(char *, char *, size_t);  static  off_t   file_compress(char *, char *, size_t);
 static  off_t   file_uncompress(char *, char *, size_t);  static  off_t   file_uncompress(char *, char *, size_t);
 static  off_t   cat_fd(unsigned char *, size_t, off_t *, int fd);  
 static  void    handle_pathname(char *);  static  void    handle_pathname(char *);
 static  void    handle_file(char *, struct stat *);  static  void    handle_file(char *, struct stat *);
 static  void    handle_stdin(void);  static  void    handle_stdin(void);
Line 163  static void print_ratio(off_t, off_t, FI
Line 192  static void print_ratio(off_t, off_t, FI
 static  void    print_list(int fd, off_t, const char *, time_t);  static  void    print_list(int fd, off_t, const char *, time_t);
 static  void    usage(void);  static  void    usage(void);
 static  void    display_version(void);  static  void    display_version(void);
   static  const suffixes_t *check_suffix(char *, int);
   static  ssize_t read_retry(int, void *, size_t);
   
 #ifndef SMALL  #ifdef SMALL
   #define unlink_input(f, sb) unlink(f)
   #else
   static  off_t   cat_fd(unsigned char *, size_t, off_t *, int fd);
 static  void    prepend_gzip(char *, int *, char ***);  static  void    prepend_gzip(char *, int *, char ***);
 static  void    handle_dir(char *, struct stat *);  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    print_test(const char *, int);
 static  void    copymodes(const char *, struct stat *);  static  void    copymodes(const char *, struct stat *);
 static  int     check_outfile(const char *outfile, struct stat *sb);  static  int     check_outfile(const char *outfile, struct stat *sb);
 static  const char *check_suffix(char *);  
 #endif  #endif
   
 #ifndef NO_BZIP2_SUPPORT  #ifndef NO_BZIP2_SUPPORT
Line 179  static off_t unbzip2(int, int, char *, s
Line 212  static off_t unbzip2(int, int, char *, s
 #endif  #endif
   
 #ifndef NO_COMPRESS_SUPPORT  #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 *);  static  off_t   zuncompress(FILE *, FILE *, char *, size_t, off_t *);
 #endif  #endif
   
Line 224  main(int argc, char **argv)
Line 257  main(int argc, char **argv)
         const char *progname = getprogname();          const char *progname = getprogname();
 #ifndef SMALL  #ifndef SMALL
         char *gzip;          char *gzip;
           int len;
 #endif  #endif
         int ch;          int ch;
   
         /* XXX set up signals */          /* XXX set up signals */
   
         suffix = GZ_SUFFIX;  
   
 #ifndef SMALL  #ifndef SMALL
         if ((gzip = getenv("GZIP")) != NULL)          if ((gzip = getenv("GZIP")) != NULL)
                 prepend_gzip(gzip, &argc, &argv);                  prepend_gzip(gzip, &argc, &argv);
Line 252  main(int argc, char **argv)
Line 284  main(int argc, char **argv)
 #define OPT_LIST "cdfhHlnNqrS:tvV123456789"  #define OPT_LIST "cdfhHlnNqrS:tvV123456789"
 #endif  #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) {                  switch (ch) {
                 case 'c':                  case 'c':
                         cflag = 1;                          cflag = 1;
Line 291  main(int argc, char **argv)
Line 323  main(int argc, char **argv)
                         rflag = 1;                          rflag = 1;
                         break;                          break;
                 case 'S':                  case 'S':
                         Sflag = optarg;                          len = strlen(optarg);
                           if (len != 0) {
                                   suffixes[0].zipped = optarg;
                                   suffixes[0].ziplen = len;
                           } else {
                                   suffixes[NUM_SUFFIXES - 1].zipped = "";
                                   suffixes[NUM_SUFFIXES - 1].ziplen = 0;
                           }
                         break;                          break;
                 case 't':                  case 't':
                         cflag = 1;                          cflag = 1;
Line 306  main(int argc, char **argv)
Line 345  main(int argc, char **argv)
                         usage();                          usage();
                         /* NOTREACHED */                          /* NOTREACHED */
                 }                  }
           }
         argv += optind;          argv += optind;
         argc -= optind;          argc -= optind;
   
Line 370  maybe_err(const char *fmt, ...)
Line 410  maybe_err(const char *fmt, ...)
         exit(2);          exit(2);
 }  }
   
   #ifndef NO_BZIP2_SUPPORT
 /* ... without an errno. */  /* ... without an errno. */
 void  void
 maybe_errx(const char *fmt, ...)  maybe_errx(const char *fmt, ...)
Line 383  maybe_errx(const char *fmt, ...)
Line 424  maybe_errx(const char *fmt, ...)
         }          }
         exit(2);          exit(2);
 }  }
   #endif
   
 #ifndef SMALL  #ifndef SMALL
 /* split up $GZIP and prepend it to the argument list */  /* split up $GZIP and prepend it to the argument list */
Line 393  prepend_gzip(char *gzip, int *argc, char
Line 435  prepend_gzip(char *gzip, int *argc, char
         int nenvarg = 0, i;          int nenvarg = 0, i;
   
         /* scan how many arguments there are */          /* scan how many arguments there are */
         for (s = gzip; *s; s++) {          for (s = gzip;;) {
                 if (*s == ' ' || *s == '\t')                  while (*s == ' ' || *s == '\t')
                         continue;                          s++;
                   if (*s == 0)
                           goto count_done;
                 nenvarg++;                  nenvarg++;
                 for (; *s; s++)                  while (*s != ' ' && *s != '\t')
                         if (*s == ' ' || *s == '\t')                          if (*s++ == 0)
                                 break;                                  goto count_done;
                 if (*s == 0x0)  
                         break;  
         }          }
   count_done:
         /* punt early */          /* punt early */
         if (nenvarg == 0)          if (nenvarg == 0)
                 return;                  return;
Line 425  prepend_gzip(char *gzip, int *argc, char
Line 468  prepend_gzip(char *gzip, int *argc, char
         s = strdup(gzip);          s = strdup(gzip);
         if (s == NULL)          if (s == NULL)
                 maybe_err("strdup");                  maybe_err("strdup");
         for (; *s; s++) {          for (;;) {
                 if (*s == ' ' || *s == '\t')                  /* Skip whitespaces. */
                         continue;                  while (*s == ' ' || *s == '\t')
                           s++;
                   if (*s == 0)
                           goto copy_done;
                 nargv[i++] = s;                  nargv[i++] = s;
                 for (; *s; s++)                  /* Find the end of this argument. */
                         if (*s == ' ' || *s == '\t') {                  while (*s != ' ' && *s != '\t')
                                 *s = 0;                          if (*s++ == 0)
                                 break;                                  /* Argument followed by NUL. */
                         }                                  goto copy_done;
                   /* Terminate by overwriting ' ' or '\t' with NUL. */
                   *s++ = 0;
         }          }
   copy_done:
   
         /* copy the original arguments and a NULL */          /* copy the original arguments and a NULL */
         while (*ac)          while (*ac)
Line 443  prepend_gzip(char *gzip, int *argc, char
Line 492  prepend_gzip(char *gzip, int *argc, char
 }  }
 #endif  #endif
   
 /* compress input to output then close both files */  /* compress input to output. Return bytes read, -1 on error */
 static off_t  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;          z_stream z;
         char *outbufp, *inbufp;          char *outbufp, *inbufp;
         off_t in_tot = 0, out_tot = 0;          off_t in_tot = 0, out_tot = 0;
         ssize_t in_size;          ssize_t in_size;
         char *str;  
         int i, error;          int i, error;
         uLong crc;          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");                  maybe_err("malloc failed");
                 goto out2;  
         }  
         if ((inbufp = malloc(BUFLEN)) == NULL) {  
                 maybe_err("malloc failed");  
                 goto out1;  
         }  
   
         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;                  goto out;
         }          }
         free(str);  
   
         memset(&z, 0, sizeof z);          memset(&z, 0, sizeof z);
         z.next_out = outbufp;  
         z.avail_out = BUFLEN;  
         z.zalloc = Z_NULL;          z.zalloc = Z_NULL;
         z.zfree = Z_NULL;          z.zfree = Z_NULL;
         z.opaque = 0;          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,
                        numflag == 1 ? 4 : numflag == 9 ? 2 : 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,          error = deflateInit2(&z, numflag, Z_DEFLATED,
                              -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);                               -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
         if (error != Z_OK) {          if (error != Z_OK) {
Line 513  gz_compress(FILE *in, int out, off_t *gs
Line 571  gz_compress(FILE *in, int out, off_t *gs
                 }                  }
   
                 if (z.avail_in == 0) {                  if (z.avail_in == 0) {
                         in_size = fread(inbufp, 1, BUFLEN, in);                          in_size = read(in, inbufp, BUFLEN);
                         if (ferror(in)) {                          if (in_size < 0) {
                                 maybe_warn("fread");                                  maybe_warn("read");
                                 in_tot = -1;                                  in_tot = -1;
                                 goto out;                                  goto out;
                         }                          }
Line 547  gz_compress(FILE *in, int out, off_t *gs
Line 605  gz_compress(FILE *in, int out, off_t *gs
                         goto out;                          goto out;
                 }                  }
   
                 len = BUFLEN - z.avail_out;                  len = (char *)z.next_out - outbufp;
   
                 if (write(out, outbufp, len) != len) {                  if (write(out, outbufp, len) != len) {
                         maybe_warn("write");                          maybe_warn("write");
Line 568  gz_compress(FILE *in, int out, off_t *gs
Line 626  gz_compress(FILE *in, int out, off_t *gs
                 goto out;                  goto out;
         }          }
   
         i = asprintf(&str, "%c%c%c%c%c%c%c%c",          i = snprintf(outbufp, BUFLEN, "%c%c%c%c%c%c%c%c",
                  (int)crc & 0xff,                   (int)crc & 0xff,
                  (int)(crc >> 8) & 0xff,                   (int)(crc >> 8) & 0xff,
                  (int)(crc >> 16) & 0xff,                   (int)(crc >> 16) & 0xff,
Line 578  gz_compress(FILE *in, int out, off_t *gs
Line 636  gz_compress(FILE *in, int out, off_t *gs
                  (int)(in_tot >> 16) & 0xff,                   (int)(in_tot >> 16) & 0xff,
                  (int)(in_tot >> 24) & 0xff);                   (int)(in_tot >> 24) & 0xff);
         if (i != 8)          if (i != 8)
                 maybe_err("asprintf");                  maybe_err("snprintf");
         if (write(out, str, i) != i) {          if (write(out, outbufp, i) != i) {
                 maybe_warn("write");                  maybe_warn("write");
                 in_tot = -1;                  in_tot = -1;
         }          } else
         free(str);                  out_tot += i;
   
 out:  out:
         free(inbufp);          if (inbufp != NULL)
 out1:                  free(inbufp);
         free(outbufp);          if (outbufp != NULL)
 out2:                  free(outbufp);
         if (gsizep)          if (gsizep)
                 *gsizep = out_tot;                  *gsizep = out_tot;
         return in_tot;          return in_tot;
Line 606  gz_uncompress(int in, int out, char *pre
Line 664  gz_uncompress(int in, int out, char *pre
 {  {
         z_stream z;          z_stream z;
         char *outbufp, *inbufp;          char *outbufp, *inbufp;
         off_t out_tot, in_tot;          off_t out_tot = -1, in_tot = 0;
         uint32_t out_sub_tot;          uint32_t out_sub_tot = 0;
         enum {          enum {
                 GZSTATE_MAGIC0,                  GZSTATE_MAGIC0,
                 GZSTATE_MAGIC1,                  GZSTATE_MAGIC1,
Line 627  gz_uncompress(int in, int out, char *pre
Line 685  gz_uncompress(int in, int out, char *pre
                 GZSTATE_LEN,                  GZSTATE_LEN,
         } state = GZSTATE_MAGIC0;          } state = GZSTATE_MAGIC0;
         int flags = 0, skip_count = 0;          int flags = 0, skip_count = 0;
         int error, done_reading = 0;          int error = Z_STREAM_ERROR, done_reading = 0;
         uLong crc;          uLong crc = 0;
           ssize_t wr;
           int needmore = 0;
   
 #define ADVANCE()       { z.next_in++; z.avail_in--; }  #define ADVANCE()       { z.next_in++; z.avail_in--; }
   
Line 654  gz_uncompress(int in, int out, char *pre
Line 714  gz_uncompress(int in, int out, char *pre
         out_tot = 0;          out_tot = 0;
   
         for (;;) {          for (;;) {
                 if (z.avail_in == 0 && done_reading == 0) {                  if ((z.avail_in == 0 || needmore) && done_reading == 0) {
                         size_t in_size = read(in, inbufp, BUFLEN);                          size_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) {                          if (in_size == -1) {
 #ifndef SMALL  #ifndef SMALL
Line 665  gz_uncompress(int in, int out, char *pre
Line 732  gz_uncompress(int in, int out, char *pre
                                 maybe_warn("failed to read stdin");                                  maybe_warn("failed to read stdin");
                                 out_tot = -1;                                  out_tot = -1;
                                 goto stop;                                  goto stop;
                         } else if (in_size == 0)                          } else if (in_size == 0) {
                                 done_reading = 1;                                  done_reading = 1;
                           }
   
                         z.avail_in = in_size;                          z.avail_in += in_size;
                         z.next_in = inbufp;                          needmore = 0;
   
                         in_tot += in_size;                          in_tot += in_size;
                 }                  }
Line 800  gz_uncompress(int in, int out, char *pre
Line 868  gz_uncompress(int in, int out, char *pre
                 case GZSTATE_READ:                  case GZSTATE_READ:
                         error = inflate(&z, Z_FINISH);                          error = inflate(&z, Z_FINISH);
                         /* Z_BUF_ERROR goes with Z_FINISH... */                          /* Z_BUF_ERROR goes with Z_FINISH... */
                         if (error == Z_STREAM_END || error == Z_BUF_ERROR) {                          if (error != Z_STREAM_END && error != Z_BUF_ERROR)
                                 ssize_t wr = BUFLEN - z.avail_out;                                  /* Just need more input */
                                   break;
                                 /* Nothing left? */                          wr = BUFLEN - z.avail_out;
                                 if (wr == 0)  
                                         goto stop;  
   
                           if (wr != 0) {
                                 crc = crc32(crc, (const Bytef *)outbufp, (unsigned)wr);                                  crc = crc32(crc, (const Bytef *)outbufp, (unsigned)wr);
                                 if (                                  if (
 #ifndef SMALL  #ifndef SMALL
Line 821  gz_uncompress(int in, int out, char *pre
Line 888  gz_uncompress(int in, int out, char *pre
   
                                 out_tot += wr;                                  out_tot += wr;
                                 out_sub_tot += wr;                                  out_sub_tot += wr;
                           }
   
                                 if (error == Z_STREAM_END) {                          if (error == Z_STREAM_END) {
                                         inflateEnd(&z);                                  inflateEnd(&z);
                                         state++;                                  state++;
                                 }                          }
   
                                 z.next_out = outbufp;                          z.next_out = outbufp;
                                 z.avail_out = BUFLEN;                          z.avail_out = BUFLEN;
   
                                 break;                          break;
                         }  
                 case GZSTATE_CRC:                  case GZSTATE_CRC:
                         {                          {
                                 static int empty_buffer = 0;  
                                 uLong origcrc;                                  uLong origcrc;
   
                                 if (z.avail_in < 4) {                                  if (z.avail_in < 4) {
                                         if (!done_reading && empty_buffer++ < 4)                                          if (!done_reading) {
                                                   needmore = 1;
                                                 continue;                                                  continue;
                                           }
                                         maybe_warnx("truncated input");                                          maybe_warnx("truncated input");
                                         out_tot = -1;                                          out_tot = -1;
                                         goto stop;                                          goto stop;
                                 }                                  }
                                 empty_buffer = 0;  
                                 origcrc = ((unsigned)z.next_in[0] & 0xff) |                                  origcrc = ((unsigned)z.next_in[0] & 0xff) |
                                         ((unsigned)z.next_in[1] & 0xff) << 8 |                                          ((unsigned)z.next_in[1] & 0xff) << 8 |
                                         ((unsigned)z.next_in[2] & 0xff) << 16 |                                          ((unsigned)z.next_in[2] & 0xff) << 16 |
Line 860  gz_uncompress(int in, int out, char *pre
Line 927  gz_uncompress(int in, int out, char *pre
                         z.avail_in -= 4;                          z.avail_in -= 4;
                         z.next_in += 4;                          z.next_in += 4;
   
                         if (!z.avail_in)                          if (!z.avail_in && done_reading) {
                                 goto stop;                                  goto stop;
                           }
                         state++;                          state++;
                         break;                          break;
                 case GZSTATE_LEN:                  case GZSTATE_LEN:
                         {                          {
                                 static int empty_buffer = 0;  
                                 uLong origlen;                                  uLong origlen;
   
                                 if (z.avail_in < 4) {                                  if (z.avail_in < 4) {
                                         if (!done_reading && empty_buffer++ < 4)                                          if (!done_reading) {
                                                   needmore = 1;
                                                 continue;                                                  continue;
                                           }
                                         maybe_warnx("truncated input");                                          maybe_warnx("truncated input");
                                         out_tot = -1;                                          out_tot = -1;
                                         goto stop;                                          goto stop;
                                 }                                  }
                                 empty_buffer = 0;  
                                 origlen = ((unsigned)z.next_in[0] & 0xff) |                                  origlen = ((unsigned)z.next_in[0] & 0xff) |
                                         ((unsigned)z.next_in[1] & 0xff) << 8 |                                          ((unsigned)z.next_in[1] & 0xff) << 8 |
                                         ((unsigned)z.next_in[2] & 0xff) << 16 |                                          ((unsigned)z.next_in[2] & 0xff) << 16 |
Line 951  copymodes(const char *file, struct stat 
Line 1019  copymodes(const char *file, struct stat 
         }          }
   
         /* we only allow set-id and the 9 normal permission bits */          /* we only allow set-id and the 9 normal permission bits */
         sbp->st_mode &= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;          sbp->st_mode &= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO;
         if (chmod(file, sbp->st_mode) < 0)          if (chmod(file, sbp->st_mode) < 0)
                 maybe_warn("couldn't chmod: %s", file);                  maybe_warn("couldn't chmod: %s", file);
   
Line 1018  check_outfile(const char *outfile, struc
Line 1086  check_outfile(const char *outfile, struc
         return ok;          return ok;
 }  }
   
 static const char *  static void
 check_suffix(char *file)  unlink_input(const char *file, struct stat *sb)
 {  {
         char const **s;          struct stat nsb;
         size_t slen, len = strlen(file);  
   
         for (s = suffixes; *s; s++) {          if (stat(file, &nsb) != 0)
                 slen = strlen(*s);                  /* Must be gone alrady */
                   return;
           if (nsb.st_dev != sb->st_dev || nsb.st_ino != sb->st_ino)
                   /* Definitely a different file */
                   return;
           unlink(file);
   }
   #endif
   
   static const suffixes_t *
   check_suffix(char *file, int xlate)
   {
           const suffixes_t *s;
           int len = strlen(file);
           char *sp;
   
           for (s = suffixes; s != suffixes + NUM_SUFFIXES; s++) {
                 /* if it doesn't fit in "a.suf", don't bother */                  /* if it doesn't fit in "a.suf", don't bother */
                 if (slen + 1 > len)                  if (s->ziplen >= len)
                           continue;
                   sp = file + len - s->ziplen;
                   if (strcmp(s->zipped, sp) != 0)
                         continue;                          continue;
                 if (strcmp(*s, file + len - slen) == 0)                  if (xlate)
                         return *s;                          strcpy(sp, s->normal);
                   return s;
         }          }
         return NULL;          return NULL;
 }  }
 #endif  
   
 /*  /*
  * compress the given file: create a corresponding .gz file and remove the   * compress the given file: create a corresponding .gz file and remove the
Line 1043  check_suffix(char *file)
Line 1129  check_suffix(char *file)
 static off_t  static off_t
 file_compress(char *file, char *outfile, size_t outsize)  file_compress(char *file, char *outfile, size_t outsize)
 {  {
         FILE *in;          int in;
         int out;          int out;
         struct stat isb, osb;          off_t size, insize;
         off_t size;  
 #ifndef SMALL  #ifndef SMALL
         u_int32_t mtime = 0;          struct stat isb, osb;
         char *savename;          const suffixes_t *suff;
 #endif  
   
         if (cflag == 0) {  
 #ifndef SMALL  
                 const char *suff;  
   
                 if (fflag == 0 && (suff = check_suffix(file))) {  
                         maybe_warnx("%s already has %s suffix -- unchanged",  
                                     file, suff);  
                         goto lose;  
                 }  
   
 #endif  #endif
   
                 (void)strncpy(outfile, file, outsize - suffix_len);          in = open(file, O_RDONLY);
                 outfile[outsize - suffix_len] = '\0';          if (in == -1) {
                 (void)strlcat(outfile, suffix, outsize);                  maybe_warn("can't open %s", file);
                   return -1;
           }
   
           if (cflag == 0) {
 #ifndef SMALL  #ifndef SMALL
                 if (check_outfile(outfile, &osb) == 0)  
                         goto lose;  
   
                 if (stat(file, &isb) == 0) {                  if (stat(file, &isb) == 0) {
                         if (isb.st_nlink > 1 && fflag == 0) {                          if (isb.st_nlink > 1 && fflag == 0) {
                                 maybe_warnx("%s has %d other link%s -- "                                  maybe_warnx("%s has %d other link%s -- "
                                             "skipping", file, isb.st_nlink - 1,                                              "skipping", file, isb.st_nlink - 1,
                                             isb.st_nlink == 1 ? "" : "s");                                              isb.st_nlink == 1 ? "" : "s");
                                 goto lose;                                  close(in);
                                   return -1;
                         }                          }
                         if (nflag == 0)                  }
                                 mtime = (u_int32_t)isb.st_mtime;  
                   if (fflag == 0 && (suff = check_suffix(file, 0))
                       && suff->zipped[0] != 0) {
                           maybe_warnx("%s already has %s suffix -- unchanged",
                                       file, suff->zipped);
                           close(in);
                           return -1;
                 }                  }
 #endif  #endif
         }  
         in = fopen(file, "r");                  /* Add (usually) .gz to filename */
         if (in == NULL) {                  if (snprintf(outfile, outsize, "%s%s",
                 maybe_warn("can't fopen %s", file);                                          file, suffixes[0].zipped) >= outsize)
                 goto lose;                          memcpy(outfile - suffixes[0].ziplen - 1,
         }                                  suffixes[0].zipped, suffixes[0].ziplen + 1);
   
 #ifndef SMALL  #ifndef SMALL
         if (nflag == 0)                  if (check_outfile(outfile, &osb) == 0) {
                 savename = basename(file);                          close(in);
         else                          return -1;
                 savename = NULL;                  }
 #endif  #endif
           }
   
         if (cflag == 0) {          if (cflag == 0) {
                 out = open(outfile, O_WRONLY|O_CREAT|O_EXCL, 0600);                  out = open(outfile, O_WRONLY | O_CREAT | O_EXCL, 0600);
                 if (out == -1) {                  if (out == -1) {
                         maybe_warn("could not create output: %s", outfile);                          maybe_warn("could not create output: %s", outfile);
                         goto lose;                          fclose(stdin);
                           return -1;
                 }                  }
         } else          } else
                 out = STDOUT_FILENO;                  out = STDOUT_FILENO;
   
 #ifdef SMALL          insize = gz_compress(in, out, &size, basename(file), (uint32_t)isb.st_mtime);
         gz_compress(in, out, NULL, NULL, 0);  
 #else  
         gz_compress(in, out, NULL, savename, mtime);  
 #endif  
   
         (void)fclose(in);          (void)close(in);
   
         /*          /*
          * if we compressed to stdout, we don't know the size and           * If there was an error, insize will be -1.
          * we don't know the new file name, punt.  if we can't stat           * If we compressed to stdout, just return the size.
          * the file, whine, otherwise set the size from the stat           * Otherwise stat the file and check it is the correct size.
          * buffer.  we only blow away the file if we can stat the           * We only blow away the file if we can stat the output and it
          * output, just in case.           * has the expected size.
          */           */
         if (cflag == 0) {          if (cflag != 0)
                 if (close(out) == -1)                  return insize == -1 ? -1 : size;
                         maybe_warn("couldn't close ouput");  
           if (close(out) == -1)
                   maybe_warn("couldn't close ouput");
   
                 if (stat(outfile, &osb) < 0) {  
                         maybe_warn("couldn't stat: %s", outfile);  
                         maybe_warnx("leaving original %s", file);  
                         size = 0;  
                 } else {  
                         unlink(file);  
                         size = osb.st_size;  
                 }  
 #ifndef SMALL  #ifndef SMALL
                 copymodes(outfile, &isb);          if (stat(outfile, &osb) < 0) {
 #endif                  maybe_warn("couldn't stat: %s", outfile);
         } else {                  goto bad_outfile;
 lose:          }
                 size = -1;  
           if (osb.st_size != size) {
                   maybe_warnx("output file: %s wrong size (%" PRIdOFF
                                   " != %" PRIdOFF "), deleting",
                                   outfile, osb.st_size, size);
                   goto bad_outfile;
         }          }
   
         return (size);          copymodes(outfile, &isb);
   #endif
   
           /* output is good, ok to delete input */
           unlink_input(file, &isb);
           return size;
   
   #ifndef SMALL
       bad_outfile:
           maybe_warnx("leaving original %s", file);
           unlink(outfile);
           return size;
   #endif
 }  }
   
 /* uncompress the given file and remove the original */  /* uncompress the given file and remove the original */
Line 1148  static off_t
Line 1238  static off_t
 file_uncompress(char *file, char *outfile, size_t outsize)  file_uncompress(char *file, char *outfile, size_t outsize)
 {  {
         struct stat isb, osb;          struct stat isb, osb;
         char *s;  
         off_t size;          off_t size;
         ssize_t rbytes, len = strlen(file);          ssize_t rbytes;
         unsigned char header1[4], name[PATH_MAX + 1];          unsigned char header1[4];
         enum filetype method;          enum filetype method;
         int fd, zfd;          int fd, zfd = -1;
 #ifndef SMALL  #ifndef SMALL
         time_t timestamp = 0;          time_t timestamp = 0;
           unsigned char name[PATH_MAX + 1];
 #endif  #endif
   
         /* gather the old name info */          /* gather the old name info */
Line 1165  file_uncompress(char *file, char *outfil
Line 1255  file_uncompress(char *file, char *outfil
                 maybe_warn("can't open %s", file);                  maybe_warn("can't open %s", file);
                 goto lose;                  goto lose;
         }          }
   
           strlcpy(outfile, file, outsize);
           if (check_suffix(outfile, 1) == NULL && !(cflag || lflag)) {
                   maybe_warnx("%s: unknown suffix -- ignored", file);
                   goto lose;
           }
   
         rbytes = read(fd, header1, sizeof header1);          rbytes = read(fd, header1, sizeof header1);
         if (rbytes != sizeof header1) {          if (rbytes != sizeof header1) {
                 /* we don't want to fail here. */                  /* we don't want to fail here. */
 #ifndef SMALL  #ifndef SMALL
                 if (fflag)                  if (fflag)
                         goto lose_close_it;                          goto lose;
 #endif  #endif
                 if (rbytes == -1)                  if (rbytes == -1)
                         maybe_warn("can't read %s", file);                          maybe_warn("can't read %s", file);
                 else                  else
                         maybe_warnx("%s: unexpected end of file", file);                          maybe_warnx("%s: unexpected end of file", file);
                 goto lose_close_it;                  goto lose;
         }          }
   
         method = file_gettype(header1);          method = file_gettype(header1);
   
 #ifndef SMALL  #ifndef SMALL
         if (Sflag == NULL) {  
 # ifndef NO_BZIP2_SUPPORT  
                 if (method == FT_BZIP2)  
                         suffix = BZ2_SUFFIX;  
                 else  
 # endif  
 # ifndef NO_COMPRESS_SUPPORT  
                 if (method == FT_Z)  
                         suffix = Z_SUFFIX;  
 # endif  
         }  
   
         if (fflag == 0 && method == FT_UNKNOWN) {          if (fflag == 0 && method == FT_UNKNOWN) {
                 maybe_warnx("%s: not in gzip format", file);                  maybe_warnx("%s: not in gzip format", file);
                 goto lose_close_it;                  goto lose;
         }  
 #endif  
   
         if (cflag == 0 || lflag) {  
                 s = 0;  
                 if (len - suffix_len + 1 > 0 &&  
                     (s = &file[len - suffix_len + 1]) &&  
                     strncmp(s, suffix, suffix_len) == 0) {  
                         (void)strncpy(outfile, file, len - suffix_len + 1);  
                         outfile[len - suffix_len + 1] = '\0';  
                 } else if (lflag == 0) {  
                         maybe_warnx("%s: unknown suffix -- ignored", file);  
                         goto lose_close_it;  
                 }  
         }          }
   
 #ifdef SMALL  
         if (method == FT_GZIP && lflag)  
 #else  
         if (method == FT_GZIP && (Nflag || lflag))  
 #endif  #endif
         {  
 #ifndef SMALL  #ifndef SMALL
                 unsigned char header2[4];       /* timestamp */          if (method == FT_GZIP && Nflag) {
                   unsigned char ts[4];    /* timestamp */
   
                 if (lseek(fd, GZIP_TIMESTAMP, SEEK_SET) == -1) {                  if (pread(fd, ts, sizeof ts, GZIP_TIMESTAMP) != sizeof ts) {
                         maybe_warn("can't lseek %s", file);                          if (!fflag)
                         goto close_header_read;                                  maybe_warn("can't read %s", file);
                 }                          goto lose;
                 if (read(fd, header2, sizeof header2) != sizeof header2) {                  }
                         if (fflag)                  timestamp = ts[3] << 24 | ts[2] << 16 | ts[1] << 8 | ts[0];
                                 goto lose_close_it;  
                         maybe_warn("can't read %s", file);  
                         goto lose_close_it;  
                }  
                timestamp = ((time_t)header2[3] << 24)  
                          + ((time_t)header2[2] << 16)  
                          + ((time_t)header2[1] << 8)  
                          +  (time_t)header2[0];  
 #endif  
   
                 if (header1[3] & ORIG_NAME) {                  if (header1[3] & ORIG_NAME) {
                         int i;                          rbytes = pread(fd, name, sizeof name, GZIP_ORIGNAME);
   
                         if (lseek(fd, GZIP_ORIGNAME, SEEK_SET) == -1) {  
                                 maybe_warn("can't lseek %s", file);  
                                 goto close_header_read;  
                         }  
                         rbytes = read(fd, name, PATH_MAX + 1);  
                         if (rbytes < 0) {                          if (rbytes < 0) {
                                 maybe_warn("can't read %s", file);                                  maybe_warn("can't read %s", file);
                                 goto lose_close_it;                                  goto lose;
                         }                          }
                         for (i = 0; i < rbytes && name[i]; i++)                          if (name[0] != 0) {
                                 ;                                  /* preserve original directory name */
                         if (i < rbytes) {                                  char *dp = strrchr(file, '/');
                                 name[i] = 0;                                  if (dp == NULL)
                                 /* now maybe merge old dirname */                                          dp = file;
                                 if (strchr(outfile, '/') == NULL)                                  else
                                         (void) strlcpy(outfile, name, outsize);                                          dp++;
                                 else {                                  snprintf(outfile, outsize, "%.*s%.*s",
                                         char    newbuf[PATH_MAX + 1];                                                  (int) (dp - file),
                                                   file, (int) rbytes, name);
                                         (void) snprintf(newbuf, sizeof(newbuf),  
                                                 "%s/%s", dirname(outfile),  
                                                 name);  
                                         (void) strlcpy(outfile, newbuf,  
                                                 outsize);  
                                 }  
                         }                          }
                 }                  }
         }          }
 close_header_read:  #endif
         close(fd);          lseek(fd, 0, SEEK_SET);
   
         if (cflag == 0 || lflag) {          if (cflag == 0 || lflag) {
                   if (fstat(fd, &isb) != 0)
                           goto lose;
 #ifndef SMALL  #ifndef SMALL
                   if (isb.st_nlink > 1 && lflag == 0 && fflag == 0) {
                           maybe_warnx("%s has %d other links -- skipping",
                               file, isb.st_nlink - 1);
                           goto lose;
                   }
                   if (nflag == 0 && timestamp)
                           isb.st_mtime = timestamp;
                 if (check_outfile(outfile, &osb) == 0)                  if (check_outfile(outfile, &osb) == 0)
                         goto lose;                          goto lose;
   
 #endif  
                 if (stat(file, &isb) == 0) {  
 #ifndef SMALL  
                         if (isb.st_nlink > 1 && lflag == 0 && fflag == 0) {  
                                 maybe_warnx("%s has %d other links -- skipping",  
                                     file, isb.st_nlink - 1);  
                                 goto lose;  
                         }  
                         if (nflag == 0 && timestamp)  
                                 isb.st_mtime = timestamp;  
 #endif  #endif
                 } else  
                         goto lose;  
         }          }
   
         if (cflag == 0 && lflag == 0) {          if (cflag == 0 && lflag == 0) {
                 zfd = open(outfile, O_WRONLY|O_CREAT|O_EXCL, 0600);                  zfd = open(outfile, O_WRONLY|O_CREAT|O_EXCL, 0600);
                   if (zfd == STDOUT_FILENO) {
                           /* We won't close STDOUT_FILENO later... */
                           zfd = dup(zfd);
                           close(STDOUT_FILENO);
                   }
                 if (zfd == -1) {                  if (zfd == -1) {
                         maybe_warn("can't open %s", outfile);                          maybe_warn("can't open %s", outfile);
                         goto lose;                          goto lose;
Line 1303  close_header_read:
Line 1351  close_header_read:
   
 #ifndef NO_BZIP2_SUPPORT  #ifndef NO_BZIP2_SUPPORT
         if (method == FT_BZIP2) {          if (method == FT_BZIP2) {
                 int in;  
   
                 /* XXX */                  /* XXX */
                 if (lflag) {                  if (lflag) {
Line 1311  close_header_read:
Line 1358  close_header_read:
                         goto lose;                          goto lose;
                 }                  }
   
                 if ((in = open(file, O_RDONLY)) == -1) {                  size = unbzip2(fd, zfd, NULL, 0, NULL);
                         maybe_warn("open for read: %s", file);  
                         goto lose;  
                 }  
   
                 size = unbzip2(in, zfd, NULL, 0, NULL);  
                 if (size == -1) {  
                         if (cflag == 0)  
                                 unlink(outfile);  
                         maybe_warnx("%s: uncompress failed", file);  
                         goto lose;  
                 }  
                 if (close(in) != 0)  
                         maybe_warn("couldn't close input");  
                 if (cflag == 0 && close(zfd) != 0)  
                         maybe_warn("couldn't close output");  
         } else          } else
 #endif  #endif
   
Line 1340  close_header_read:
Line 1372  close_header_read:
                         goto lose;                          goto lose;
                 }                  }
   
                 if ((in = zopen(file, NULL)) == NULL) {                  if ((in = zdopen(fd)) == NULL) {
                         maybe_warn("open for read: %s", file);                          maybe_warn("zdopen for read: %s", file);
                         goto lose;                          goto lose;
                 }                  }
   
                 out = fdopen(zfd, "w");                  out = fdopen(dup(zfd), "w");
                 if (out == NULL) {                  if (out == NULL) {
                         maybe_warn("open for write: %s", outfile);                          maybe_warn("fdopen for write: %s", outfile);
                           fclose(in);
                         goto lose;                          goto lose;
                 }                  }
   
                 size = zuncompress(in, out, NULL, 0, NULL);                  size = zuncompress(in, out, NULL, 0, NULL);
                 if (ferror(in) || fclose(in) != 0) {                  /* need to fclose() if ferror() is true... */
                   if (ferror(in) | fclose(in)) {
                           maybe_warn("failed infile fclose");
                         unlink(outfile);                          unlink(outfile);
                         (void)fclose(out);                          (void)fclose(out);
                         maybe_warn("failed infile fclose");  
                 }                  }
                 if (cflag == 0) {                  if (fclose(out) != 0) {
                         if (size == -1) {                          maybe_warn("failed outfile fclose");
                                 maybe_warnx("%s: uncompress failed", file);                          unlink(outfile);
                                 (void)fclose(out);                          goto lose;
                                 unlink(outfile);  
                                 goto lose;  
                         }  
                         if (fclose(out) != 0) {  
                                 unlink(outfile);  
                                 maybe_warn("failed outfile close");  
                                 goto lose;  
                         }  
                 }                  }
         } else          } else
 #endif  #endif
   
 #ifndef SMALL  #ifndef SMALL
         if (method == FT_UNKNOWN) {          if (method == FT_UNKNOWN) {
                 int in;                  if (lflag) {
                           maybe_warnx("no -l for unknown filetypes");
                 in = open(file, O_RDONLY);  
                 if (in == -1) {  
                         maybe_warn("can't open %s", file);  
                         goto lose;                          goto lose;
                 }                  }
                 size = cat_fd(NULL, 0, NULL, in);                  size = cat_fd(NULL, 0, NULL, fd);
         } else          } else
 #endif  #endif
         {          {
                 int in;  
   
                 if (lflag) {                  if (lflag) {
                         if ((zfd = open(file, O_RDONLY)) == -1) {                          print_list(fd, isb.st_size, outfile, isb.st_mtime);
                                 maybe_warn("open: %s", file);                          close(fd);
                                 goto lose;  
                         }  
                         print_list(zfd, isb.st_size, outfile, isb.st_mtime);  
                         return -1;      /* XXX */                          return -1;      /* XXX */
                 }                  }
   
                 in = open(file, O_RDONLY);                  size = gz_uncompress(fd, zfd, NULL, 0, NULL, file);
                 if (in == -1) {          }
                         maybe_warn("can't open %s", file);  
                         goto lose;  
                 }  
   
                 size = gz_uncompress(in, zfd, NULL, 0, NULL, file);          if (close(fd) != 0)
                 (void)close(in);                  maybe_warn("couldn't close input");
                 if (cflag == 0) {          if (zfd != STDOUT_FILENO && close(zfd) != 0)
                         if (close(zfd))                  maybe_warn("couldn't close output");
                                 maybe_warn("failed close");  
                         if (size == -1) {          if (size == -1) {
                                 maybe_warnx("%s: uncompress failed", file);                  if (cflag == 0)
                                 unlink(outfile);                          unlink(outfile);
                                 goto lose;                  maybe_warnx("%s: uncompress failed", file);
                         }                  return -1;
                 }  
         }          }
   
         /* if testing, or we uncompressed to stdout, this is all we need */          /* if testing, or we uncompressed to stdout, this is all we need */
 #ifndef SMALL  #ifndef SMALL
         if (tflag)          if (tflag)
                 return (size);                  return size;
 #endif  #endif
         /* if we are uncompressing to stdin, don't remove the file. */          /* if we are uncompressing to stdin, don't remove the file. */
         if (cflag)          if (cflag)
                 return (size);                  return size;
   
         /*          /*
          * if we create a file...           * if we create a file...
          */           */
         if (cflag == 0) {          /*
                 /*           * if we can't stat the file don't remove the file.
                  * if we can't stat the file don't remove the file.           */
                  */          if (stat(outfile, &osb) < 0) {
                 if (stat(outfile, &osb) < 0) {                  maybe_warn("couldn't stat (leaving original): %s",
                         maybe_warn("couldn't stat (leaving original): %s",                             outfile);
                                    outfile);                  return -1;
                         goto lose;          }
                 }          if (osb.st_size != size) {
                 if (osb.st_size != size) {                  maybe_warn("stat gave different size: %" PRIdOFF
                         maybe_warn("stat gave different size: %llu != %llu "                                  " != %" PRIdOFF " (leaving original)",
                             "(leaving original)",                                  size, osb.st_size);
                             (unsigned long long)size,                  unlink(outfile);
                             (unsigned long long)osb.st_size);                  return -1;
                         goto lose;          }
                 }          unlink_input(file, &isb);
                 if (cflag == 0)  
                         unlink(file);  
                 size = osb.st_size;  
 #ifndef SMALL  #ifndef SMALL
                 copymodes(outfile, &isb);          copymodes(outfile, &isb);
 #endif  #endif
         }          return size;
         return (size);  
   
 lose_close_it:      lose:
         close(fd);          if (fd != -1)
 lose:                  close(fd);
           if (zfd != -1 && zfd != STDOUT_FILENO)
                   close(fd);
         return -1;          return -1;
 }  }
   
Line 1500  handle_stdin(void)
Line 1512  handle_stdin(void)
         unsigned char header1[4];          unsigned char header1[4];
         off_t usize, gsize;          off_t usize, gsize;
         enum filetype method;          enum filetype method;
           ssize_t bytes_read;
 #ifndef NO_COMPRESS_SUPPORT  #ifndef NO_COMPRESS_SUPPORT
         FILE *in;          FILE *in;
 #endif  #endif
Line 1523  handle_stdin(void)
Line 1536  handle_stdin(void)
                 return;                  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");                  maybe_warn("can't read stdin");
                 return;                  return;
           } else if (bytes_read != sizeof(header1)) {
                   maybe_warnx("unexpected EOF");
                   return;
         }          }
   
         method = file_gettype(header1);          method = file_gettype(header1);
Line 1551  handle_stdin(void)
Line 1568  handle_stdin(void)
 #endif  #endif
 #ifndef NO_COMPRESS_SUPPORT  #ifndef NO_COMPRESS_SUPPORT
         case FT_Z:          case FT_Z:
                 if ((in = zopen(NULL, stdin)) == NULL) {                  if ((in = zdopen(STDIN_FILENO)) == NULL) {
                         maybe_warnx("zopen of stdin");                          maybe_warnx("zopen of stdin");
                         return;                          return;
                 }                  }
   
                 usize = zuncompress(in, stdout, header1, sizeof header1, &gsize);                  usize = zuncompress(in, stdout, header1, sizeof header1, &gsize);
                   fclose(in);
                 break;                  break;
 #endif  #endif
         }          }
   
 #ifndef SMALL  #ifndef SMALL
         if (vflag && !tflag && usize != -1 && gsize != -1)          if (vflag && !tflag && usize != -1 && gsize != -1)
                 print_verbage(NULL, 0, usize, gsize);                  print_verbage(NULL, NULL, usize, gsize);
 #endif  #endif
   
 }  }
Line 1605  handle_stdout(void)
Line 1623  handle_stdout(void)
 #endif  #endif
                 mtime = (uint32_t)systime;                  mtime = (uint32_t)systime;
         }          }
   
         usize = gz_compress(stdin, STDOUT_FILENO, &gsize, NULL, mtime);          usize = gz_compress(STDIN_FILENO, STDOUT_FILENO, &gsize, "", mtime);
 #ifndef SMALL  #ifndef SMALL
         if (vflag && !tflag && usize != -1 && gsize != -1)          if (vflag && !tflag && usize != -1 && gsize != -1)
                 print_verbage(NULL, 0, usize, gsize);                  print_verbage(NULL, NULL, usize, gsize);
 #endif  #endif
 }  }
   
Line 1619  handle_pathname(char *path)
Line 1637  handle_pathname(char *path)
 {  {
         char *opath = path, *s = NULL;          char *opath = path, *s = NULL;
         ssize_t len;          ssize_t len;
           int slen;
         struct stat sb;          struct stat sb;
   
         /* check for stdout/stdin */          /* check for stdout/stdin */
Line 1635  retry:
Line 1654  retry:
                 /* lets try <path>.gz if we're decompressing */                  /* lets try <path>.gz if we're decompressing */
                 if (dflag && s == NULL && errno == ENOENT) {                  if (dflag && s == NULL && errno == ENOENT) {
                         len = strlen(path);                          len = strlen(path);
                         s = malloc(len + suffix_len + 1);                          slen = suffixes[0].ziplen;
                           s = malloc(len + slen + 1);
                         if (s == NULL)                          if (s == NULL)
                                 maybe_err("malloc");                                  maybe_err("malloc");
                         memmove(s, path, len);                          memcpy(s, path, len);
                         memmove(&s[len], suffix, suffix_len);                          memcpy(s + len, suffixes[0].zipped, slen + 1);
                         s[len + suffix_len] = 0x0;  
                         path = s;                          path = s;
                         goto retry;                          goto retry;
                 }                  }
Line 1660  retry:
Line 1679  retry:
   
         if (S_ISREG(sb.st_mode))          if (S_ISREG(sb.st_mode))
                 handle_file(path, &sb);                  handle_file(path, &sb);
           else
                   maybe_warnx("%s is not a regular file", path);
   
 out:  out:
         if (s)          if (s)
Line 1694  handle_file(char *file, struct stat *sbp
Line 1715  handle_file(char *file, struct stat *sbp
 }  }
   
 #ifndef SMALL  #ifndef SMALL
 /* this is used with -r to recursively decend directories */  /* this is used with -r to recursively descend directories */
 static void  static void
 handle_dir(char *dir, struct stat *sbp)  handle_dir(char *dir, struct stat *sbp)
 {  {
Line 1729  handle_dir(char *dir, struct stat *sbp)
Line 1750  handle_dir(char *dir, struct stat *sbp)
 }  }
 #endif  #endif
   
 /* print a ratio */  /* print a ratio - size reduction as a fraction of uncompressed size */
 static void  static void
 print_ratio(off_t in, off_t out, FILE *where)  print_ratio(off_t in, off_t out, FILE *where)
 {  {
         int64_t percent10;      /* 10 * percent */          int percent10;  /* 10 * percent */
         off_t diff = in - out;          off_t diff;
         char ch;          char buff[8];
           int len;
         if (in == 0)  
                 percent10 = 0;  
         else if (diff > 0x400000)       /* anything with 22 or more bits */  
                 percent10 = diff / (in / 1000);  
         else  
                 percent10 = (1000 * diff) / in;  
   
         if (percent10 < 0) {          diff = in - out/2;
                 percent10 = -percent10;          if (diff <= 0)
                 ch = '-';                  /*
         } else                   * Output is more than double size of input! print -99.9%
                 ch = ' ';                   * Quite possibly we've failed to get the original size.
                    */
                   percent10 = -999;
           else {
                   /*
                    * We only need 12 bits of result from the final division,
                    * so reduce the values until a 32bit division will suffice.
                    */
                   while (in > 0x100000) {
                           diff >>= 1;
                           in >>= 1;
                   }
                   if (in != 0)
                           percent10 = ((u_int)diff * 2000) / (u_int)in - 1000;
                   else
                           percent10 = 0;
           }
   
         /*          len = snprintf(buff, sizeof buff, "%2.2d.", percent10);
          * ugh.  for negative percentages < 10, we need to avoid printing a          /* Move the '.' to before the last digit */
          * a space between the "-" and the single number.          buff[len - 1] = buff[len - 2];
          */          buff[len - 2] = '.';
         if (ch == '-' && percent10 / 10LL < 10)          fprintf(where, "%5s%%", buff);
                 fprintf(where, " -%1d.%1u%%", (unsigned)(percent10 / 10LL),  
                                               (unsigned)(percent10 % 10LL));  
         else  
                 fprintf(where, "%c%2d.%1u%%", ch, (unsigned)(percent10 / 10LL),  
                                                   (unsigned)(percent10 % 10LL));  
 }  }
   
 #ifndef SMALL  #ifndef SMALL
 /* print compression statistics, and the new name (if there is one!) */  /* print compression statistics, and the new name (if there is one!) */
 static void  static void
 print_verbage(char *file, char *nfile, off_t usize, off_t gsize)  print_verbage(const char *file, const char *nfile, off_t usize, off_t gsize)
 {  {
         if (file)          if (file)
                 fprintf(stderr, "%s:%s  ", file,                  fprintf(stderr, "%s:%s  ", file,
                     strlen(file) < 7 ? "\t\t" : "\t");                      strlen(file) < 7 ? "\t\t" : "\t");
         print_ratio((off_t)usize, (off_t)gsize, stderr);          print_ratio(usize, gsize, stderr);
         if (nfile)          if (nfile)
                 fprintf(stderr, " -- replaced with %s", nfile);                  fprintf(stderr, " -- replaced with %s", nfile);
         fprintf(stderr, "\n");          fprintf(stderr, "\n");
Line 1801  print_list(int fd, off_t out, const char
Line 1827  print_list(int fd, off_t out, const char
         static int first = 1;          static int first = 1;
 #ifndef SMALL  #ifndef SMALL
         static off_t in_tot, out_tot;          static off_t in_tot, out_tot;
         u_int32_t crc;          uint32_t crc = 0;
 #endif  #endif
         off_t in;          off_t in = 0;
         int rv;          int rv;
   
         if (first) {          if (first) {
Line 1829  print_list(int fd, off_t out, const char
Line 1855  print_list(int fd, off_t out, const char
                 rv = lseek(fd, (off_t)(-8), SEEK_END);                  rv = lseek(fd, (off_t)(-8), SEEK_END);
                 if (rv != -1) {                  if (rv != -1) {
                         unsigned char buf[8];                          unsigned char buf[8];
                         u_int32_t usize;                          uint32_t usize;
   
                         if (read(fd, (char *)buf, sizeof(buf)) != sizeof(buf))                          if (read(fd, (char *)buf, sizeof(buf)) != sizeof(buf))
                                 maybe_warn("read of uncompressed size");                                  maybe_warn("read of uncompressed size");
Line 1909  display_version(void)
Line 1935  display_version(void)
 #ifndef NO_COMPRESS_SUPPORT  #ifndef NO_COMPRESS_SUPPORT
 #include "zuncompress.c"  #include "zuncompress.c"
 #endif  #endif
   
   static ssize_t
   read_retry(int fd, void *buf, size_t sz)
   {
           char *cp = buf;
           ssize_t left = sz;
   
           while (left > 0) {
                   ssize_t ret;
   
                   ret = read(fd, cp, sz);
                   if (ret == -1) {
                           return ret;
                   } else if (ret == 0) {
                           break; /* EOF */
                   }
                   cp += ret;
                   left -= ret;
           }
   
           return sz - left;
   }

Legend:
Removed from v.1.29.2.29.2.2  
changed lines
  Added in v.1.29.2.29.2.3

CVSweb <webmaster@jp.NetBSD.org>