(root)/
binutils-2.41/
zlib/
minigzip.c
       1  /* minigzip.c -- simulate gzip using the zlib compression library
       2   * Copyright (C) 1995-2006, 2010 Jean-loup Gailly.
       3   * For conditions of distribution and use, see copyright notice in zlib.h
       4   */
       5  
       6  /*
       7   * minigzip is a minimal implementation of the gzip utility. This is
       8   * only an example of using zlib and isn't meant to replace the
       9   * full-featured gzip. No attempt is made to deal with file systems
      10   * limiting names to 14 or 8+3 characters, etc... Error checking is
      11   * very limited. So use minigzip only for testing; use gzip for the
      12   * real thing. On MSDOS, use only on file names without extension
      13   * or in pipe mode.
      14   */
      15  
      16  /* @(#) $Id: minigzip.c,v 1.1.1.2 2002/03/11 21:53:26 tromey Exp $ */
      17  
      18  #include "zlib.h"
      19  #include <stdio.h>
      20  
      21  #ifdef STDC
      22  #  include <string.h>
      23  #  include <stdlib.h>
      24  #endif
      25  
      26  #ifdef USE_MMAP
      27  #  include <sys/types.h>
      28  #  include <sys/mman.h>
      29  #  include <sys/stat.h>
      30  #endif
      31  
      32  #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
      33  #  include <fcntl.h>
      34  #  include <io.h>
      35  #  ifdef UNDER_CE
      36  #    include <stdlib.h>
      37  #  endif
      38  #  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
      39  #else
      40  #  define SET_BINARY_MODE(file)
      41  #endif
      42  
      43  #ifdef VMS
      44  #  define unlink delete
      45  #  define GZ_SUFFIX "-gz"
      46  #endif
      47  #ifdef RISCOS
      48  #  define unlink remove
      49  #  define GZ_SUFFIX "-gz"
      50  #  define fileno(file) file->__file
      51  #endif
      52  #if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
      53  #  include <unix.h> /* for fileno */
      54  #endif
      55  
      56  #if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
      57  #ifndef WIN32 /* unlink already in stdio.h for WIN32 */
      58    extern int unlink OF((const char *));
      59  #endif
      60  #endif
      61  
      62  #if defined(UNDER_CE)
      63  #  include <windows.h>
      64  #  define perror(s) pwinerror(s)
      65  
      66  /* Map the Windows error number in ERROR to a locale-dependent error
      67     message string and return a pointer to it.  Typically, the values
      68     for ERROR come from GetLastError.
      69  
      70     The string pointed to shall not be modified by the application,
      71     but may be overwritten by a subsequent call to strwinerror
      72  
      73     The strwinerror function does not change the current setting
      74     of GetLastError.  */
      75  
      76  static char *strwinerror (error)
      77       DWORD error;
      78  {
      79      static char buf[1024];
      80  
      81      wchar_t *msgbuf;
      82      DWORD lasterr = GetLastError();
      83      DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
      84          | FORMAT_MESSAGE_ALLOCATE_BUFFER,
      85          NULL,
      86          error,
      87          0, /* Default language */
      88          (LPVOID)&msgbuf,
      89          0,
      90          NULL);
      91      if (chars != 0) {
      92          /* If there is an \r\n appended, zap it.  */
      93          if (chars >= 2
      94              && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
      95              chars -= 2;
      96              msgbuf[chars] = 0;
      97          }
      98  
      99          if (chars > sizeof (buf) - 1) {
     100              chars = sizeof (buf) - 1;
     101              msgbuf[chars] = 0;
     102          }
     103  
     104          wcstombs(buf, msgbuf, chars + 1);
     105          LocalFree(msgbuf);
     106      }
     107      else {
     108          sprintf(buf, "unknown win32 error (%ld)", error);
     109      }
     110  
     111      SetLastError(lasterr);
     112      return buf;
     113  }
     114  
     115  static void pwinerror (s)
     116      const char *s;
     117  {
     118      if (s && *s)
     119          fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));
     120      else
     121          fprintf(stderr, "%s\n", strwinerror(GetLastError ()));
     122  }
     123  
     124  #endif /* UNDER_CE */
     125  
     126  #ifndef GZ_SUFFIX
     127  #  define GZ_SUFFIX ".gz"
     128  #endif
     129  #define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
     130  
     131  #define BUFLEN      16384
     132  #define MAX_NAME_LEN 1024
     133  
     134  #ifdef MAXSEG_64K
     135  #  define local static
     136     /* Needed for systems with limitation on stack size. */
     137  #else
     138  #  define local
     139  #endif
     140  
     141  char *prog;
     142  
     143  void error            OF((const char *msg));
     144  void gz_compress      OF((FILE   *in, gzFile out));
     145  #ifdef USE_MMAP
     146  int  gz_compress_mmap OF((FILE   *in, gzFile out));
     147  #endif
     148  void gz_uncompress    OF((gzFile in, FILE   *out));
     149  void file_compress    OF((char  *file, char *mode));
     150  void file_uncompress  OF((char  *file));
     151  int  main             OF((int argc, char *argv[]));
     152  
     153  /* ===========================================================================
     154   * Display error message and exit
     155   */
     156  void error(msg)
     157      const char *msg;
     158  {
     159      fprintf(stderr, "%s: %s\n", prog, msg);
     160      exit(1);
     161  }
     162  
     163  /* ===========================================================================
     164   * Compress input to output then close both files.
     165   */
     166  
     167  void gz_compress(in, out)
     168      FILE   *in;
     169      gzFile out;
     170  {
     171      local char buf[BUFLEN];
     172      int len;
     173      int err;
     174  
     175  #ifdef USE_MMAP
     176      /* Try first compressing with mmap. If mmap fails (minigzip used in a
     177       * pipe), use the normal fread loop.
     178       */
     179      if (gz_compress_mmap(in, out) == Z_OK) return;
     180  #endif
     181      for (;;) {
     182          len = (int)fread(buf, 1, sizeof(buf), in);
     183          if (ferror(in)) {
     184              perror("fread");
     185              exit(1);
     186          }
     187          if (len == 0) break;
     188  
     189          if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
     190      }
     191      fclose(in);
     192      if (gzclose(out) != Z_OK) error("failed gzclose");
     193  }
     194  
     195  #ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
     196  
     197  /* Try compressing the input file at once using mmap. Return Z_OK if
     198   * if success, Z_ERRNO otherwise.
     199   */
     200  int gz_compress_mmap(in, out)
     201      FILE   *in;
     202      gzFile out;
     203  {
     204      int len;
     205      int err;
     206      int ifd = fileno(in);
     207      caddr_t buf;    /* mmap'ed buffer for the entire input file */
     208      off_t buf_len;  /* length of the input file */
     209      struct stat sb;
     210  
     211      /* Determine the size of the file, needed for mmap: */
     212      if (fstat(ifd, &sb) < 0) return Z_ERRNO;
     213      buf_len = sb.st_size;
     214      if (buf_len <= 0) return Z_ERRNO;
     215  
     216      /* Now do the actual mmap: */
     217      buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
     218      if (buf == (caddr_t)(-1)) return Z_ERRNO;
     219  
     220      /* Compress the whole file at once: */
     221      len = gzwrite(out, (char *)buf, (unsigned)buf_len);
     222  
     223      if (len != (int)buf_len) error(gzerror(out, &err));
     224  
     225      munmap(buf, buf_len);
     226      fclose(in);
     227      if (gzclose(out) != Z_OK) error("failed gzclose");
     228      return Z_OK;
     229  }
     230  #endif /* USE_MMAP */
     231  
     232  /* ===========================================================================
     233   * Uncompress input to output then close both files.
     234   */
     235  void gz_uncompress(in, out)
     236      gzFile in;
     237      FILE   *out;
     238  {
     239      local char buf[BUFLEN];
     240      int len;
     241      int err;
     242  
     243      for (;;) {
     244          len = gzread(in, buf, sizeof(buf));
     245          if (len < 0) error (gzerror(in, &err));
     246          if (len == 0) break;
     247  
     248          if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
     249              error("failed fwrite");
     250          }
     251      }
     252      if (fclose(out)) error("failed fclose");
     253  
     254      if (gzclose(in) != Z_OK) error("failed gzclose");
     255  }
     256  
     257  
     258  /* ===========================================================================
     259   * Compress the given file: create a corresponding .gz file and remove the
     260   * original.
     261   */
     262  void file_compress(file, mode)
     263      char  *file;
     264      char  *mode;
     265  {
     266      local char outfile[MAX_NAME_LEN];
     267      FILE  *in;
     268      gzFile out;
     269  
     270      if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
     271          fprintf(stderr, "%s: filename too long\n", prog);
     272          exit(1);
     273      }
     274  
     275      strcpy(outfile, file);
     276      strcat(outfile, GZ_SUFFIX);
     277  
     278      in = fopen(file, "rb");
     279      if (in == NULL) {
     280          perror(file);
     281          exit(1);
     282      }
     283      out = gzopen(outfile, mode);
     284      if (out == NULL) {
     285          fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
     286          exit(1);
     287      }
     288      gz_compress(in, out);
     289  
     290      unlink(file);
     291  }
     292  
     293  
     294  /* ===========================================================================
     295   * Uncompress the given file and remove the original.
     296   */
     297  void file_uncompress(file)
     298      char  *file;
     299  {
     300      local char buf[MAX_NAME_LEN];
     301      char *infile, *outfile;
     302      FILE  *out;
     303      gzFile in;
     304      size_t len = strlen(file);
     305  
     306      if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
     307          fprintf(stderr, "%s: filename too long\n", prog);
     308          exit(1);
     309      }
     310  
     311      strcpy(buf, file);
     312  
     313      if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
     314          infile = file;
     315          outfile = buf;
     316          outfile[len-3] = '\0';
     317      } else {
     318          outfile = file;
     319          infile = buf;
     320          strcat(infile, GZ_SUFFIX);
     321      }
     322      in = gzopen(infile, "rb");
     323      if (in == NULL) {
     324          fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
     325          exit(1);
     326      }
     327      out = fopen(outfile, "wb");
     328      if (out == NULL) {
     329          perror(file);
     330          exit(1);
     331      }
     332  
     333      gz_uncompress(in, out);
     334  
     335      unlink(infile);
     336  }
     337  
     338  
     339  /* ===========================================================================
     340   * Usage:  minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
     341   *   -c : write to standard output
     342   *   -d : decompress
     343   *   -f : compress with Z_FILTERED
     344   *   -h : compress with Z_HUFFMAN_ONLY
     345   *   -r : compress with Z_RLE
     346   *   -1 to -9 : compression level
     347   */
     348  
     349  int main(argc, argv)
     350      int argc;
     351      char *argv[];
     352  {
     353      int copyout = 0;
     354      int uncompr = 0;
     355      gzFile file;
     356      char *bname, outmode[20];
     357  
     358      strcpy(outmode, "wb6 ");
     359  
     360      prog = argv[0];
     361      bname = strrchr(argv[0], '/');
     362      if (bname)
     363        bname++;
     364      else
     365        bname = argv[0];
     366      argc--, argv++;
     367  
     368      if (!strcmp(bname, "gunzip"))
     369        uncompr = 1;
     370      else if (!strcmp(bname, "zcat"))
     371        copyout = uncompr = 1;
     372  
     373      while (argc > 0) {
     374        if (strcmp(*argv, "-c") == 0)
     375          copyout = 1;
     376        else if (strcmp(*argv, "-d") == 0)
     377          uncompr = 1;
     378        else if (strcmp(*argv, "-f") == 0)
     379          outmode[3] = 'f';
     380        else if (strcmp(*argv, "-h") == 0)
     381          outmode[3] = 'h';
     382        else if (strcmp(*argv, "-r") == 0)
     383          outmode[3] = 'R';
     384        else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
     385                 (*argv)[2] == 0)
     386          outmode[2] = (*argv)[1];
     387        else
     388          break;
     389        argc--, argv++;
     390      }
     391      if (outmode[3] == ' ')
     392          outmode[3] = 0;
     393      if (argc == 0) {
     394          SET_BINARY_MODE(stdin);
     395          SET_BINARY_MODE(stdout);
     396          if (uncompr) {
     397              file = gzdopen(fileno(stdin), "rb");
     398              if (file == NULL) error("can't gzdopen stdin");
     399              gz_uncompress(file, stdout);
     400          } else {
     401              file = gzdopen(fileno(stdout), outmode);
     402              if (file == NULL) error("can't gzdopen stdout");
     403              gz_compress(stdin, file);
     404          }
     405      } else {
     406          if (copyout) {
     407              SET_BINARY_MODE(stdout);
     408          }
     409          do {
     410              if (uncompr) {
     411                  if (copyout) {
     412                      file = gzopen(*argv, "rb");
     413                      if (file == NULL)
     414                          fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
     415                      else
     416                          gz_uncompress(file, stdout);
     417                  } else {
     418                      file_uncompress(*argv);
     419                  }
     420              } else {
     421                  if (copyout) {
     422                      FILE * in = fopen(*argv, "rb");
     423  
     424                      if (in == NULL) {
     425                          perror(*argv);
     426                      } else {
     427                          file = gzdopen(fileno(stdout), outmode);
     428                          if (file == NULL) error("can't gzdopen stdout");
     429  
     430                          gz_compress(in, file);
     431                      }
     432  
     433                  } else {
     434                      file_compress(*argv, outmode);
     435                  }
     436              }
     437          } while (argv++, --argc);
     438      }
     439      return 0;
     440  }