• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/zlib/minigzip.c

00001 /* minigzip.c -- simulate gzip using the zlib compression library
00002  * Copyright (C) 1995-2006, 2010 Jean-loup Gailly.
00003  * For conditions of distribution and use, see copyright notice in zlib.h
00004  */
00005 
00006 /*
00007  * minigzip is a minimal implementation of the gzip utility. This is
00008  * only an example of using zlib and isn't meant to replace the
00009  * full-featured gzip. No attempt is made to deal with file systems
00010  * limiting names to 14 or 8+3 characters, etc... Error checking is
00011  * very limited. So use minigzip only for testing; use gzip for the
00012  * real thing. On MSDOS, use only on file names without extension
00013  * or in pipe mode.
00014  */
00015 
00016 /* @(#) $Id$ */
00017 
00018 #include "zlib.h"
00019 #include <stdio.h>
00020 
00021 #ifdef STDC
00022 #  include <string.h>
00023 #  include <stdlib.h>
00024 #endif
00025 
00026 #ifdef USE_MMAP
00027 #  include <sys/types.h>
00028 #  include <sys/mman.h>
00029 #  include <sys/stat.h>
00030 #endif
00031 
00032 #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
00033 #  include <fcntl.h>
00034 #  include <io.h>
00035 #  ifdef UNDER_CE
00036 #    include <stdlib.h>
00037 #  endif
00038 #  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
00039 #else
00040 #  define SET_BINARY_MODE(file)
00041 #endif
00042 
00043 #ifdef VMS
00044 #  define unlink delete
00045 #  define GZ_SUFFIX "-gz"
00046 #endif
00047 #ifdef RISCOS
00048 #  define unlink remove
00049 #  define GZ_SUFFIX "-gz"
00050 #  define fileno(file) file->__file
00051 #endif
00052 #if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
00053 #  include <unix.h> /* for fileno */
00054 #endif
00055 
00056 #if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
00057 #ifndef WIN32 /* unlink already in stdio.h for WIN32 */
00058   extern int unlink OF((const char *));
00059 #endif
00060 #endif
00061 
00062 #if defined(UNDER_CE)
00063 #  include <windows.h>
00064 #  define perror(s) pwinerror(s)
00065 
00066 /* Map the Windows error number in ERROR to a locale-dependent error
00067    message string and return a pointer to it.  Typically, the values
00068    for ERROR come from GetLastError.
00069 
00070    The string pointed to shall not be modified by the application,
00071    but may be overwritten by a subsequent call to strwinerror
00072 
00073    The strwinerror function does not change the current setting
00074    of GetLastError.  */
00075 
00076 static char *strwinerror (error)
00077      DWORD error;
00078 {
00079     static char buf[1024];
00080 
00081     wchar_t *msgbuf;
00082     DWORD lasterr = GetLastError();
00083     DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
00084         | FORMAT_MESSAGE_ALLOCATE_BUFFER,
00085         NULL,
00086         error,
00087         0, /* Default language */
00088         (LPVOID)&msgbuf,
00089         0,
00090         NULL);
00091     if (chars != 0) {
00092         /* If there is an \r\n appended, zap it.  */
00093         if (chars >= 2
00094             && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
00095             chars -= 2;
00096             msgbuf[chars] = 0;
00097         }
00098 
00099         if (chars > sizeof (buf) - 1) {
00100             chars = sizeof (buf) - 1;
00101             msgbuf[chars] = 0;
00102         }
00103 
00104         wcstombs(buf, msgbuf, chars + 1);
00105         LocalFree(msgbuf);
00106     }
00107     else {
00108         sprintf(buf, "unknown win32 error (%ld)", error);
00109     }
00110 
00111     SetLastError(lasterr);
00112     return buf;
00113 }
00114 
00115 static void pwinerror (s)
00116     const char *s;
00117 {
00118     if (s && *s)
00119         fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));
00120     else
00121         fprintf(stderr, "%s\n", strwinerror(GetLastError ()));
00122 }
00123 
00124 #endif /* UNDER_CE */
00125 
00126 #ifndef GZ_SUFFIX
00127 #  define GZ_SUFFIX ".gz"
00128 #endif
00129 #define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
00130 
00131 #define BUFLEN      16384
00132 #define MAX_NAME_LEN 1024
00133 
00134 #ifdef MAXSEG_64K
00135 #  define local static
00136    /* Needed for systems with limitation on stack size. */
00137 #else
00138 #  define local
00139 #endif
00140 
00141 char *prog;
00142 
00143 void error            OF((const char *msg));
00144 void gz_compress      OF((FILE   *in, gzFile out));
00145 #ifdef USE_MMAP
00146 int  gz_compress_mmap OF((FILE   *in, gzFile out));
00147 #endif
00148 void gz_uncompress    OF((gzFile in, FILE   *out));
00149 void file_compress    OF((char  *file, char *mode));
00150 void file_uncompress  OF((char  *file));
00151 int  main             OF((int argc, char *argv[]));
00152 
00153 /* ===========================================================================
00154  * Display error message and exit
00155  */
00156 void error(msg)
00157     const char *msg;
00158 {
00159     fprintf(stderr, "%s: %s\n", prog, msg);
00160     exit(1);
00161 }
00162 
00163 /* ===========================================================================
00164  * Compress input to output then close both files.
00165  */
00166 
00167 void gz_compress(in, out)
00168     FILE   *in;
00169     gzFile out;
00170 {
00171     local char buf[BUFLEN];
00172     int len;
00173     int err;
00174 
00175 #ifdef USE_MMAP
00176     /* Try first compressing with mmap. If mmap fails (minigzip used in a
00177      * pipe), use the normal fread loop.
00178      */
00179     if (gz_compress_mmap(in, out) == Z_OK) return;
00180 #endif
00181     for (;;) {
00182         len = (int)fread(buf, 1, sizeof(buf), in);
00183         if (ferror(in)) {
00184             perror("fread");
00185             exit(1);
00186         }
00187         if (len == 0) break;
00188 
00189         if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
00190     }
00191     fclose(in);
00192     if (gzclose(out) != Z_OK) error("failed gzclose");
00193 }
00194 
00195 #ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
00196 
00197 /* Try compressing the input file at once using mmap. Return Z_OK if
00198  * if success, Z_ERRNO otherwise.
00199  */
00200 int gz_compress_mmap(in, out)
00201     FILE   *in;
00202     gzFile out;
00203 {
00204     int len;
00205     int err;
00206     int ifd = fileno(in);
00207     caddr_t buf;    /* mmap'ed buffer for the entire input file */
00208     off_t buf_len;  /* length of the input file */
00209     struct stat sb;
00210 
00211     /* Determine the size of the file, needed for mmap: */
00212     if (fstat(ifd, &sb) < 0) return Z_ERRNO;
00213     buf_len = sb.st_size;
00214     if (buf_len <= 0) return Z_ERRNO;
00215 
00216     /* Now do the actual mmap: */
00217     buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
00218     if (buf == (caddr_t)(-1)) return Z_ERRNO;
00219 
00220     /* Compress the whole file at once: */
00221     len = gzwrite(out, (char *)buf, (unsigned)buf_len);
00222 
00223     if (len != (int)buf_len) error(gzerror(out, &err));
00224 
00225     munmap(buf, buf_len);
00226     fclose(in);
00227     if (gzclose(out) != Z_OK) error("failed gzclose");
00228     return Z_OK;
00229 }
00230 #endif /* USE_MMAP */
00231 
00232 /* ===========================================================================
00233  * Uncompress input to output then close both files.
00234  */
00235 void gz_uncompress(in, out)
00236     gzFile in;
00237     FILE   *out;
00238 {
00239     local char buf[BUFLEN];
00240     int len;
00241     int err;
00242 
00243     for (;;) {
00244         len = gzread(in, buf, sizeof(buf));
00245         if (len < 0) error (gzerror(in, &err));
00246         if (len == 0) break;
00247 
00248         if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
00249             error("failed fwrite");
00250         }
00251     }
00252     if (fclose(out)) error("failed fclose");
00253 
00254     if (gzclose(in) != Z_OK) error("failed gzclose");
00255 }
00256 
00257 
00258 /* ===========================================================================
00259  * Compress the given file: create a corresponding .gz file and remove the
00260  * original.
00261  */
00262 void file_compress(file, mode)
00263     char  *file;
00264     char  *mode;
00265 {
00266     local char outfile[MAX_NAME_LEN];
00267     FILE  *in;
00268     gzFile out;
00269 
00270     if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
00271         fprintf(stderr, "%s: filename too long\n", prog);
00272         exit(1);
00273     }
00274 
00275     strcpy(outfile, file);
00276     strcat(outfile, GZ_SUFFIX);
00277 
00278     in = fopen(file, "rb");
00279     if (in == NULL) {
00280         perror(file);
00281         exit(1);
00282     }
00283     out = gzopen(outfile, mode);
00284     if (out == NULL) {
00285         fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
00286         exit(1);
00287     }
00288     gz_compress(in, out);
00289 
00290     unlink(file);
00291 }
00292 
00293 
00294 /* ===========================================================================
00295  * Uncompress the given file and remove the original.
00296  */
00297 void file_uncompress(file)
00298     char  *file;
00299 {
00300     local char buf[MAX_NAME_LEN];
00301     char *infile, *outfile;
00302     FILE  *out;
00303     gzFile in;
00304     size_t len = strlen(file);
00305 
00306     if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
00307         fprintf(stderr, "%s: filename too long\n", prog);
00308         exit(1);
00309     }
00310 
00311     strcpy(buf, file);
00312 
00313     if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
00314         infile = file;
00315         outfile = buf;
00316         outfile[len-3] = '\0';
00317     } else {
00318         outfile = file;
00319         infile = buf;
00320         strcat(infile, GZ_SUFFIX);
00321     }
00322     in = gzopen(infile, "rb");
00323     if (in == NULL) {
00324         fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
00325         exit(1);
00326     }
00327     out = fopen(outfile, "wb");
00328     if (out == NULL) {
00329         perror(file);
00330         exit(1);
00331     }
00332 
00333     gz_uncompress(in, out);
00334 
00335     unlink(infile);
00336 }
00337 
00338 
00339 /* ===========================================================================
00340  * Usage:  minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
00341  *   -c : write to standard output
00342  *   -d : decompress
00343  *   -f : compress with Z_FILTERED
00344  *   -h : compress with Z_HUFFMAN_ONLY
00345  *   -r : compress with Z_RLE
00346  *   -1 to -9 : compression level
00347  */
00348 
00349 int main(argc, argv)
00350     int argc;
00351     char *argv[];
00352 {
00353     int copyout = 0;
00354     int uncompr = 0;
00355     gzFile file;
00356     char *bname, outmode[20];
00357 
00358     strcpy(outmode, "wb6 ");
00359 
00360     prog = argv[0];
00361     bname = strrchr(argv[0], '/');
00362     if (bname)
00363       bname++;
00364     else
00365       bname = argv[0];
00366     argc--, argv++;
00367 
00368     if (!strcmp(bname, "gunzip"))
00369       uncompr = 1;
00370     else if (!strcmp(bname, "zcat"))
00371       copyout = uncompr = 1;
00372 
00373     while (argc > 0) {
00374       if (strcmp(*argv, "-c") == 0)
00375         copyout = 1;
00376       else if (strcmp(*argv, "-d") == 0)
00377         uncompr = 1;
00378       else if (strcmp(*argv, "-f") == 0)
00379         outmode[3] = 'f';
00380       else if (strcmp(*argv, "-h") == 0)
00381         outmode[3] = 'h';
00382       else if (strcmp(*argv, "-r") == 0)
00383         outmode[3] = 'R';
00384       else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
00385                (*argv)[2] == 0)
00386         outmode[2] = (*argv)[1];
00387       else
00388         break;
00389       argc--, argv++;
00390     }
00391     if (outmode[3] == ' ')
00392         outmode[3] = 0;
00393     if (argc == 0) {
00394         SET_BINARY_MODE(stdin);
00395         SET_BINARY_MODE(stdout);
00396         if (uncompr) {
00397             file = gzdopen(fileno(stdin), "rb");
00398             if (file == NULL) error("can't gzdopen stdin");
00399             gz_uncompress(file, stdout);
00400         } else {
00401             file = gzdopen(fileno(stdout), outmode);
00402             if (file == NULL) error("can't gzdopen stdout");
00403             gz_compress(stdin, file);
00404         }
00405     } else {
00406         if (copyout) {
00407             SET_BINARY_MODE(stdout);
00408         }
00409         do {
00410             if (uncompr) {
00411                 if (copyout) {
00412                     file = gzopen(*argv, "rb");
00413                     if (file == NULL)
00414                         fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
00415                     else
00416                         gz_uncompress(file, stdout);
00417                 } else {
00418                     file_uncompress(*argv);
00419                 }
00420             } else {
00421                 if (copyout) {
00422                     FILE * in = fopen(*argv, "rb");
00423 
00424                     if (in == NULL) {
00425                         perror(*argv);
00426                     } else {
00427                         file = gzdopen(fileno(stdout), outmode);
00428                         if (file == NULL) error("can't gzdopen stdout");
00429 
00430                         gz_compress(in, file);
00431                     }
00432 
00433                 } else {
00434                     file_compress(*argv, outmode);
00435                 }
00436             }
00437         } while (argv++, --argc);
00438     }
00439     return 0;
00440 }

Generated on Wed Oct 20 2010 11:12:18 for APBS by  doxygen 1.7.2