Home | History | Annotate | Line # | Download | only in test
minigzip.c revision 1.1.1.2
      1      1.1  christos /* minigzip.c -- simulate gzip using the zlib compression library
      2      1.1  christos  * Copyright (C) 1995-2006, 2010, 2011, 2016 Jean-loup Gailly
      3      1.1  christos  * For conditions of distribution and use, see copyright notice in zlib.h
      4      1.1  christos  */
      5      1.1  christos 
      6      1.1  christos /*
      7      1.1  christos  * minigzip is a minimal implementation of the gzip utility. This is
      8      1.1  christos  * only an example of using zlib and isn't meant to replace the
      9      1.1  christos  * full-featured gzip. No attempt is made to deal with file systems
     10      1.1  christos  * limiting names to 14 or 8+3 characters, etc... Error checking is
     11      1.1  christos  * very limited. So use minigzip only for testing; use gzip for the
     12      1.1  christos  * real thing. On MSDOS, use only on file names without extension
     13      1.1  christos  * or in pipe mode.
     14      1.1  christos  */
     15      1.1  christos 
     16      1.1  christos /* @(#) $Id: minigzip.c,v 1.1.1.2 2022/10/15 19:38:38 christos Exp $ */
     17      1.1  christos 
     18      1.1  christos #include "zlib.h"
     19      1.1  christos #include <stdio.h>
     20      1.1  christos 
     21      1.1  christos #ifdef STDC
     22      1.1  christos #  include <string.h>
     23      1.1  christos #  include <stdlib.h>
     24      1.1  christos #endif
     25      1.1  christos 
     26      1.1  christos #ifdef USE_MMAP
     27      1.1  christos #  include <sys/types.h>
     28      1.1  christos #  include <sys/mman.h>
     29      1.1  christos #  include <sys/stat.h>
     30      1.1  christos #endif
     31      1.1  christos 
     32      1.1  christos #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
     33      1.1  christos #  include <fcntl.h>
     34      1.1  christos #  include <io.h>
     35      1.1  christos #  ifdef UNDER_CE
     36      1.1  christos #    include <stdlib.h>
     37      1.1  christos #  endif
     38      1.1  christos #  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
     39      1.1  christos #else
     40      1.1  christos #  define SET_BINARY_MODE(file)
     41      1.1  christos #endif
     42      1.1  christos 
     43      1.1  christos #if defined(_MSC_VER) && _MSC_VER < 1900
     44      1.1  christos #  define snprintf _snprintf
     45      1.1  christos #endif
     46      1.1  christos 
     47      1.1  christos #ifdef VMS
     48      1.1  christos #  define unlink delete
     49      1.1  christos #  define GZ_SUFFIX "-gz"
     50      1.1  christos #endif
     51      1.1  christos #ifdef RISCOS
     52      1.1  christos #  define unlink remove
     53      1.1  christos #  define GZ_SUFFIX "-gz"
     54      1.1  christos #  define fileno(file) file->__file
     55      1.1  christos #endif
     56      1.1  christos #if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
     57      1.1  christos #  include <unix.h> /* for fileno */
     58      1.1  christos #endif
     59      1.1  christos 
     60      1.1  christos #if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
     61      1.1  christos #ifndef WIN32 /* unlink already in stdio.h for WIN32 */
     62      1.1  christos   extern int unlink OF((const char *));
     63      1.1  christos #endif
     64      1.1  christos #endif
     65      1.1  christos 
     66      1.1  christos #if defined(UNDER_CE)
     67      1.1  christos #  include <windows.h>
     68      1.1  christos #  define perror(s) pwinerror(s)
     69      1.1  christos 
     70      1.1  christos /* Map the Windows error number in ERROR to a locale-dependent error
     71      1.1  christos    message string and return a pointer to it.  Typically, the values
     72      1.1  christos    for ERROR come from GetLastError.
     73      1.1  christos 
     74      1.1  christos    The string pointed to shall not be modified by the application,
     75      1.1  christos    but may be overwritten by a subsequent call to strwinerror
     76      1.1  christos 
     77      1.1  christos    The strwinerror function does not change the current setting
     78      1.1  christos    of GetLastError.  */
     79      1.1  christos 
     80      1.1  christos static char *strwinerror (error)
     81      1.1  christos      DWORD error;
     82      1.1  christos {
     83      1.1  christos     static char buf[1024];
     84      1.1  christos 
     85      1.1  christos     wchar_t *msgbuf;
     86      1.1  christos     DWORD lasterr = GetLastError();
     87      1.1  christos     DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
     88      1.1  christos         | FORMAT_MESSAGE_ALLOCATE_BUFFER,
     89      1.1  christos         NULL,
     90      1.1  christos         error,
     91      1.1  christos         0, /* Default language */
     92      1.1  christos         (LPVOID)&msgbuf,
     93      1.1  christos         0,
     94      1.1  christos         NULL);
     95      1.1  christos     if (chars != 0) {
     96      1.1  christos         /* If there is an \r\n appended, zap it.  */
     97      1.1  christos         if (chars >= 2
     98      1.1  christos             && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
     99      1.1  christos             chars -= 2;
    100      1.1  christos             msgbuf[chars] = 0;
    101      1.1  christos         }
    102      1.1  christos 
    103      1.1  christos         if (chars > sizeof (buf) - 1) {
    104      1.1  christos             chars = sizeof (buf) - 1;
    105      1.1  christos             msgbuf[chars] = 0;
    106      1.1  christos         }
    107      1.1  christos 
    108      1.1  christos         wcstombs(buf, msgbuf, chars + 1);
    109      1.1  christos         LocalFree(msgbuf);
    110      1.1  christos     }
    111      1.1  christos     else {
    112      1.1  christos         sprintf(buf, "unknown win32 error (%ld)", error);
    113      1.1  christos     }
    114      1.1  christos 
    115      1.1  christos     SetLastError(lasterr);
    116      1.1  christos     return buf;
    117      1.1  christos }
    118      1.1  christos 
    119      1.1  christos static void pwinerror (s)
    120      1.1  christos     const char *s;
    121      1.1  christos {
    122      1.1  christos     if (s && *s)
    123      1.1  christos         fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));
    124      1.1  christos     else
    125      1.1  christos         fprintf(stderr, "%s\n", strwinerror(GetLastError ()));
    126      1.1  christos }
    127      1.1  christos 
    128      1.1  christos #endif /* UNDER_CE */
    129      1.1  christos 
    130      1.1  christos #ifndef GZ_SUFFIX
    131      1.1  christos #  define GZ_SUFFIX ".gz"
    132      1.1  christos #endif
    133      1.1  christos #define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
    134      1.1  christos 
    135      1.1  christos #define BUFLEN      16384
    136      1.1  christos #define MAX_NAME_LEN 1024
    137      1.1  christos 
    138      1.1  christos #ifdef MAXSEG_64K
    139      1.1  christos #  define local static
    140      1.1  christos    /* Needed for systems with limitation on stack size. */
    141      1.1  christos #else
    142      1.1  christos #  define local
    143      1.1  christos #endif
    144      1.1  christos 
    145      1.1  christos #ifdef Z_SOLO
    146      1.1  christos /* for Z_SOLO, create simplified gz* functions using deflate and inflate */
    147      1.1  christos 
    148      1.1  christos #if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
    149      1.1  christos #  include <unistd.h>       /* for unlink() */
    150      1.1  christos #endif
    151      1.1  christos 
    152      1.1  christos void *myalloc OF((void *, unsigned, unsigned));
    153      1.1  christos void myfree OF((void *, void *));
    154      1.1  christos 
    155      1.1  christos void *myalloc(q, n, m)
    156      1.1  christos     void *q;
    157      1.1  christos     unsigned n, m;
    158      1.1  christos {
    159      1.1  christos     (void)q;
    160      1.1  christos     return calloc(n, m);
    161      1.1  christos }
    162      1.1  christos 
    163      1.1  christos void myfree(q, p)
    164      1.1  christos     void *q, *p;
    165      1.1  christos {
    166      1.1  christos     (void)q;
    167      1.1  christos     free(p);
    168      1.1  christos }
    169      1.1  christos 
    170      1.1  christos typedef struct gzFile_s {
    171      1.1  christos     FILE *file;
    172      1.1  christos     int write;
    173      1.1  christos     int err;
    174      1.1  christos     char *msg;
    175      1.1  christos     z_stream strm;
    176      1.1  christos } *gzFile;
    177      1.1  christos 
    178      1.1  christos gzFile gzopen OF((const char *, const char *));
    179      1.1  christos gzFile gzdopen OF((int, const char *));
    180      1.1  christos gzFile gz_open OF((const char *, int, const char *));
    181      1.1  christos 
    182      1.1  christos gzFile gzopen(path, mode)
    183      1.1  christos const char *path;
    184      1.1  christos const char *mode;
    185      1.1  christos {
    186      1.1  christos     return gz_open(path, -1, mode);
    187      1.1  christos }
    188      1.1  christos 
    189      1.1  christos gzFile gzdopen(fd, mode)
    190      1.1  christos int fd;
    191      1.1  christos const char *mode;
    192      1.1  christos {
    193      1.1  christos     return gz_open(NULL, fd, mode);
    194      1.1  christos }
    195      1.1  christos 
    196      1.1  christos gzFile gz_open(path, fd, mode)
    197      1.1  christos     const char *path;
    198      1.1  christos     int fd;
    199      1.1  christos     const char *mode;
    200      1.1  christos {
    201      1.1  christos     gzFile gz;
    202      1.1  christos     int ret;
    203      1.1  christos 
    204      1.1  christos     gz = malloc(sizeof(struct gzFile_s));
    205      1.1  christos     if (gz == NULL)
    206      1.1  christos         return NULL;
    207      1.1  christos     gz->write = strchr(mode, 'w') != NULL;
    208      1.1  christos     gz->strm.zalloc = myalloc;
    209      1.1  christos     gz->strm.zfree = myfree;
    210      1.1  christos     gz->strm.opaque = Z_NULL;
    211      1.1  christos     if (gz->write)
    212      1.1  christos         ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0);
    213      1.1  christos     else {
    214      1.1  christos         gz->strm.next_in = 0;
    215      1.1  christos         gz->strm.avail_in = Z_NULL;
    216      1.1  christos         ret = inflateInit2(&(gz->strm), 15 + 16);
    217      1.1  christos     }
    218      1.1  christos     if (ret != Z_OK) {
    219      1.1  christos         free(gz);
    220      1.1  christos         return NULL;
    221      1.1  christos     }
    222      1.1  christos     gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") :
    223      1.1  christos                               fopen(path, gz->write ? "wb" : "rb");
    224      1.1  christos     if (gz->file == NULL) {
    225      1.1  christos         gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm));
    226      1.1  christos         free(gz);
    227      1.1  christos         return NULL;
    228      1.1  christos     }
    229      1.1  christos     gz->err = 0;
    230      1.1  christos     gz->msg = "";
    231      1.1  christos     return gz;
    232      1.1  christos }
    233      1.1  christos 
    234      1.1  christos int gzwrite OF((gzFile, const void *, unsigned));
    235      1.1  christos 
    236      1.1  christos int gzwrite(gz, buf, len)
    237      1.1  christos     gzFile gz;
    238      1.1  christos     const void *buf;
    239      1.1  christos     unsigned len;
    240      1.1  christos {
    241      1.1  christos     z_stream *strm;
    242      1.1  christos     unsigned char out[BUFLEN];
    243      1.1  christos 
    244      1.1  christos     if (gz == NULL || !gz->write)
    245      1.1  christos         return 0;
    246      1.1  christos     strm = &(gz->strm);
    247      1.1  christos     strm->next_in = (void *)buf;
    248      1.1  christos     strm->avail_in = len;
    249      1.1  christos     do {
    250      1.1  christos         strm->next_out = out;
    251      1.1  christos         strm->avail_out = BUFLEN;
    252      1.1  christos         (void)deflate(strm, Z_NO_FLUSH);
    253      1.1  christos         fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
    254      1.1  christos     } while (strm->avail_out == 0);
    255      1.1  christos     return len;
    256      1.1  christos }
    257      1.1  christos 
    258      1.1  christos int gzread OF((gzFile, void *, unsigned));
    259      1.1  christos 
    260      1.1  christos int gzread(gz, buf, len)
    261      1.1  christos     gzFile gz;
    262      1.1  christos     void *buf;
    263      1.1  christos     unsigned len;
    264      1.1  christos {
    265      1.1  christos     int ret;
    266      1.1  christos     unsigned got;
    267      1.1  christos     unsigned char in[1];
    268      1.1  christos     z_stream *strm;
    269      1.1  christos 
    270      1.1  christos     if (gz == NULL || gz->write)
    271      1.1  christos         return 0;
    272      1.1  christos     if (gz->err)
    273      1.1  christos         return 0;
    274      1.1  christos     strm = &(gz->strm);
    275      1.1  christos     strm->next_out = (void *)buf;
    276      1.1  christos     strm->avail_out = len;
    277      1.1  christos     do {
    278      1.1  christos         got = fread(in, 1, 1, gz->file);
    279      1.1  christos         if (got == 0)
    280      1.1  christos             break;
    281      1.1  christos         strm->next_in = in;
    282      1.1  christos         strm->avail_in = 1;
    283      1.1  christos         ret = inflate(strm, Z_NO_FLUSH);
    284      1.1  christos         if (ret == Z_DATA_ERROR) {
    285      1.1  christos             gz->err = Z_DATA_ERROR;
    286      1.1  christos             gz->msg = strm->msg;
    287      1.1  christos             return 0;
    288      1.1  christos         }
    289      1.1  christos         if (ret == Z_STREAM_END)
    290      1.1  christos             inflateReset(strm);
    291      1.1  christos     } while (strm->avail_out);
    292      1.1  christos     return len - strm->avail_out;
    293      1.1  christos }
    294      1.1  christos 
    295      1.1  christos int gzclose OF((gzFile));
    296      1.1  christos 
    297      1.1  christos int gzclose(gz)
    298      1.1  christos     gzFile gz;
    299      1.1  christos {
    300      1.1  christos     z_stream *strm;
    301      1.1  christos     unsigned char out[BUFLEN];
    302      1.1  christos 
    303      1.1  christos     if (gz == NULL)
    304      1.1  christos         return Z_STREAM_ERROR;
    305      1.1  christos     strm = &(gz->strm);
    306      1.1  christos     if (gz->write) {
    307      1.1  christos         strm->next_in = Z_NULL;
    308      1.1  christos         strm->avail_in = 0;
    309      1.1  christos         do {
    310      1.1  christos             strm->next_out = out;
    311      1.1  christos             strm->avail_out = BUFLEN;
    312      1.1  christos             (void)deflate(strm, Z_FINISH);
    313      1.1  christos             fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
    314      1.1  christos         } while (strm->avail_out == 0);
    315      1.1  christos         deflateEnd(strm);
    316      1.1  christos     }
    317      1.1  christos     else
    318      1.1  christos         inflateEnd(strm);
    319      1.1  christos     fclose(gz->file);
    320      1.1  christos     free(gz);
    321      1.1  christos     return Z_OK;
    322      1.1  christos }
    323      1.1  christos 
    324      1.1  christos const char *gzerror OF((gzFile, int *));
    325      1.1  christos 
    326      1.1  christos const char *gzerror(gz, err)
    327      1.1  christos     gzFile gz;
    328      1.1  christos     int *err;
    329      1.1  christos {
    330      1.1  christos     *err = gz->err;
    331      1.1  christos     return gz->msg;
    332      1.1  christos }
    333      1.1  christos 
    334      1.1  christos #endif
    335      1.1  christos 
    336      1.1  christos static char *prog;
    337      1.1  christos 
    338      1.1  christos void error            OF((const char *msg));
    339      1.1  christos void gz_compress      OF((FILE   *in, gzFile out));
    340      1.1  christos #ifdef USE_MMAP
    341      1.1  christos int  gz_compress_mmap OF((FILE   *in, gzFile out));
    342      1.1  christos #endif
    343      1.1  christos void gz_uncompress    OF((gzFile in, FILE   *out));
    344      1.1  christos void file_compress    OF((char  *file, char *mode));
    345      1.1  christos void file_uncompress  OF((char  *file));
    346      1.1  christos int  main             OF((int argc, char *argv[]));
    347      1.1  christos 
    348      1.1  christos /* ===========================================================================
    349      1.1  christos  * Display error message and exit
    350      1.1  christos  */
    351      1.1  christos void error(msg)
    352      1.1  christos     const char *msg;
    353      1.1  christos {
    354      1.1  christos     fprintf(stderr, "%s: %s\n", prog, msg);
    355      1.1  christos     exit(1);
    356      1.1  christos }
    357      1.1  christos 
    358      1.1  christos /* ===========================================================================
    359      1.1  christos  * Compress input to output then close both files.
    360      1.1  christos  */
    361      1.1  christos 
    362      1.1  christos void gz_compress(in, out)
    363      1.1  christos     FILE   *in;
    364      1.1  christos     gzFile out;
    365      1.1  christos {
    366      1.1  christos     local char buf[BUFLEN];
    367      1.1  christos     int len;
    368      1.1  christos     int err;
    369      1.1  christos 
    370      1.1  christos #ifdef USE_MMAP
    371      1.1  christos     /* Try first compressing with mmap. If mmap fails (minigzip used in a
    372      1.1  christos      * pipe), use the normal fread loop.
    373      1.1  christos      */
    374      1.1  christos     if (gz_compress_mmap(in, out) == Z_OK) return;
    375      1.1  christos #endif
    376      1.1  christos     for (;;) {
    377      1.1  christos         len = (int)fread(buf, 1, sizeof(buf), in);
    378      1.1  christos         if (ferror(in)) {
    379      1.1  christos             perror("fread");
    380      1.1  christos             exit(1);
    381      1.1  christos         }
    382      1.1  christos         if (len == 0) break;
    383      1.1  christos 
    384      1.1  christos         if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
    385      1.1  christos     }
    386      1.1  christos     fclose(in);
    387      1.1  christos     if (gzclose(out) != Z_OK) error("failed gzclose");
    388      1.1  christos }
    389      1.1  christos 
    390      1.1  christos #ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech (at) eso.org> */
    391      1.1  christos 
    392      1.1  christos /* Try compressing the input file at once using mmap. Return Z_OK if
    393      1.1  christos  * if success, Z_ERRNO otherwise.
    394      1.1  christos  */
    395      1.1  christos int gz_compress_mmap(in, out)
    396      1.1  christos     FILE   *in;
    397      1.1  christos     gzFile out;
    398      1.1  christos {
    399      1.1  christos     int len;
    400      1.1  christos     int err;
    401      1.1  christos     int ifd = fileno(in);
    402      1.1  christos     caddr_t buf;    /* mmap'ed buffer for the entire input file */
    403      1.1  christos     off_t buf_len;  /* length of the input file */
    404      1.1  christos     struct stat sb;
    405      1.1  christos 
    406      1.1  christos     /* Determine the size of the file, needed for mmap: */
    407      1.1  christos     if (fstat(ifd, &sb) < 0) return Z_ERRNO;
    408      1.1  christos     buf_len = sb.st_size;
    409      1.1  christos     if (buf_len <= 0) return Z_ERRNO;
    410      1.1  christos 
    411      1.1  christos     /* Now do the actual mmap: */
    412      1.1  christos     buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
    413      1.1  christos     if (buf == (caddr_t)(-1)) return Z_ERRNO;
    414      1.1  christos 
    415      1.1  christos     /* Compress the whole file at once: */
    416      1.1  christos     len = gzwrite(out, (char *)buf, (unsigned)buf_len);
    417      1.1  christos 
    418      1.1  christos     if (len != (int)buf_len) error(gzerror(out, &err));
    419      1.1  christos 
    420      1.1  christos     munmap(buf, buf_len);
    421      1.1  christos     fclose(in);
    422      1.1  christos     if (gzclose(out) != Z_OK) error("failed gzclose");
    423      1.1  christos     return Z_OK;
    424      1.1  christos }
    425      1.1  christos #endif /* USE_MMAP */
    426      1.1  christos 
    427      1.1  christos /* ===========================================================================
    428      1.1  christos  * Uncompress input to output then close both files.
    429      1.1  christos  */
    430      1.1  christos void gz_uncompress(in, out)
    431      1.1  christos     gzFile in;
    432      1.1  christos     FILE   *out;
    433      1.1  christos {
    434      1.1  christos     local char buf[BUFLEN];
    435      1.1  christos     int len;
    436      1.1  christos     int err;
    437      1.1  christos 
    438      1.1  christos     for (;;) {
    439      1.1  christos         len = gzread(in, buf, sizeof(buf));
    440      1.1  christos         if (len < 0) error (gzerror(in, &err));
    441      1.1  christos         if (len == 0) break;
    442      1.1  christos 
    443      1.1  christos         if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
    444      1.1  christos             error("failed fwrite");
    445      1.1  christos         }
    446      1.1  christos     }
    447      1.1  christos     if (fclose(out)) error("failed fclose");
    448      1.1  christos 
    449      1.1  christos     if (gzclose(in) != Z_OK) error("failed gzclose");
    450      1.1  christos }
    451      1.1  christos 
    452      1.1  christos 
    453      1.1  christos /* ===========================================================================
    454      1.1  christos  * Compress the given file: create a corresponding .gz file and remove the
    455      1.1  christos  * original.
    456      1.1  christos  */
    457      1.1  christos void file_compress(file, mode)
    458      1.1  christos     char  *file;
    459      1.1  christos     char  *mode;
    460      1.1  christos {
    461      1.1  christos     local char outfile[MAX_NAME_LEN];
    462      1.1  christos     FILE  *in;
    463      1.1  christos     gzFile out;
    464      1.1  christos 
    465      1.1  christos     if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
    466      1.1  christos         fprintf(stderr, "%s: filename too long\n", prog);
    467      1.1  christos         exit(1);
    468      1.1  christos     }
    469      1.1  christos 
    470      1.1  christos #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
    471      1.1  christos     snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX);
    472      1.1  christos #else
    473      1.1  christos     strcpy(outfile, file);
    474      1.1  christos     strcat(outfile, GZ_SUFFIX);
    475      1.1  christos #endif
    476      1.1  christos 
    477      1.1  christos     in = fopen(file, "rb");
    478      1.1  christos     if (in == NULL) {
    479      1.1  christos         perror(file);
    480      1.1  christos         exit(1);
    481      1.1  christos     }
    482      1.1  christos     out = gzopen(outfile, mode);
    483      1.1  christos     if (out == NULL) {
    484      1.1  christos         fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
    485      1.1  christos         exit(1);
    486      1.1  christos     }
    487      1.1  christos     gz_compress(in, out);
    488      1.1  christos 
    489      1.1  christos     unlink(file);
    490      1.1  christos }
    491      1.1  christos 
    492      1.1  christos 
    493      1.1  christos /* ===========================================================================
    494      1.1  christos  * Uncompress the given file and remove the original.
    495      1.1  christos  */
    496      1.1  christos void file_uncompress(file)
    497      1.1  christos     char  *file;
    498      1.1  christos {
    499      1.1  christos     local char buf[MAX_NAME_LEN];
    500      1.1  christos     char *infile, *outfile;
    501      1.1  christos     FILE  *out;
    502      1.1  christos     gzFile in;
    503  1.1.1.2  christos     z_size_t len = strlen(file);
    504      1.1  christos 
    505      1.1  christos     if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
    506      1.1  christos         fprintf(stderr, "%s: filename too long\n", prog);
    507      1.1  christos         exit(1);
    508      1.1  christos     }
    509      1.1  christos 
    510      1.1  christos #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
    511      1.1  christos     snprintf(buf, sizeof(buf), "%s", file);
    512      1.1  christos #else
    513      1.1  christos     strcpy(buf, file);
    514      1.1  christos #endif
    515      1.1  christos 
    516      1.1  christos     if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
    517      1.1  christos         infile = file;
    518      1.1  christos         outfile = buf;
    519      1.1  christos         outfile[len-3] = '\0';
    520      1.1  christos     } else {
    521      1.1  christos         outfile = file;
    522      1.1  christos         infile = buf;
    523      1.1  christos #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
    524      1.1  christos         snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX);
    525      1.1  christos #else
    526      1.1  christos         strcat(infile, GZ_SUFFIX);
    527      1.1  christos #endif
    528      1.1  christos     }
    529      1.1  christos     in = gzopen(infile, "rb");
    530      1.1  christos     if (in == NULL) {
    531      1.1  christos         fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
    532      1.1  christos         exit(1);
    533      1.1  christos     }
    534      1.1  christos     out = fopen(outfile, "wb");
    535      1.1  christos     if (out == NULL) {
    536      1.1  christos         perror(file);
    537      1.1  christos         exit(1);
    538      1.1  christos     }
    539      1.1  christos 
    540      1.1  christos     gz_uncompress(in, out);
    541      1.1  christos 
    542      1.1  christos     unlink(infile);
    543      1.1  christos }
    544      1.1  christos 
    545      1.1  christos 
    546      1.1  christos /* ===========================================================================
    547      1.1  christos  * Usage:  minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
    548      1.1  christos  *   -c : write to standard output
    549      1.1  christos  *   -d : decompress
    550      1.1  christos  *   -f : compress with Z_FILTERED
    551      1.1  christos  *   -h : compress with Z_HUFFMAN_ONLY
    552      1.1  christos  *   -r : compress with Z_RLE
    553      1.1  christos  *   -1 to -9 : compression level
    554      1.1  christos  */
    555      1.1  christos 
    556      1.1  christos int main(argc, argv)
    557      1.1  christos     int argc;
    558      1.1  christos     char *argv[];
    559      1.1  christos {
    560      1.1  christos     int copyout = 0;
    561      1.1  christos     int uncompr = 0;
    562      1.1  christos     gzFile file;
    563      1.1  christos     char *bname, outmode[20];
    564      1.1  christos 
    565      1.1  christos #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
    566      1.1  christos     snprintf(outmode, sizeof(outmode), "%s", "wb6 ");
    567      1.1  christos #else
    568      1.1  christos     strcpy(outmode, "wb6 ");
    569      1.1  christos #endif
    570      1.1  christos 
    571      1.1  christos     prog = argv[0];
    572      1.1  christos     bname = strrchr(argv[0], '/');
    573      1.1  christos     if (bname)
    574      1.1  christos       bname++;
    575      1.1  christos     else
    576      1.1  christos       bname = argv[0];
    577      1.1  christos     argc--, argv++;
    578      1.1  christos 
    579      1.1  christos     if (!strcmp(bname, "gunzip"))
    580      1.1  christos       uncompr = 1;
    581      1.1  christos     else if (!strcmp(bname, "zcat"))
    582      1.1  christos       copyout = uncompr = 1;
    583      1.1  christos 
    584      1.1  christos     while (argc > 0) {
    585      1.1  christos       if (strcmp(*argv, "-c") == 0)
    586      1.1  christos         copyout = 1;
    587      1.1  christos       else if (strcmp(*argv, "-d") == 0)
    588      1.1  christos         uncompr = 1;
    589      1.1  christos       else if (strcmp(*argv, "-f") == 0)
    590      1.1  christos         outmode[3] = 'f';
    591      1.1  christos       else if (strcmp(*argv, "-h") == 0)
    592      1.1  christos         outmode[3] = 'h';
    593      1.1  christos       else if (strcmp(*argv, "-r") == 0)
    594      1.1  christos         outmode[3] = 'R';
    595      1.1  christos       else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
    596      1.1  christos                (*argv)[2] == 0)
    597      1.1  christos         outmode[2] = (*argv)[1];
    598      1.1  christos       else
    599      1.1  christos         break;
    600      1.1  christos       argc--, argv++;
    601      1.1  christos     }
    602      1.1  christos     if (outmode[3] == ' ')
    603      1.1  christos         outmode[3] = 0;
    604      1.1  christos     if (argc == 0) {
    605      1.1  christos         SET_BINARY_MODE(stdin);
    606      1.1  christos         SET_BINARY_MODE(stdout);
    607      1.1  christos         if (uncompr) {
    608      1.1  christos             file = gzdopen(fileno(stdin), "rb");
    609      1.1  christos             if (file == NULL) error("can't gzdopen stdin");
    610      1.1  christos             gz_uncompress(file, stdout);
    611      1.1  christos         } else {
    612      1.1  christos             file = gzdopen(fileno(stdout), outmode);
    613      1.1  christos             if (file == NULL) error("can't gzdopen stdout");
    614      1.1  christos             gz_compress(stdin, file);
    615      1.1  christos         }
    616      1.1  christos     } else {
    617      1.1  christos         if (copyout) {
    618      1.1  christos             SET_BINARY_MODE(stdout);
    619      1.1  christos         }
    620      1.1  christos         do {
    621      1.1  christos             if (uncompr) {
    622      1.1  christos                 if (copyout) {
    623      1.1  christos                     file = gzopen(*argv, "rb");
    624      1.1  christos                     if (file == NULL)
    625      1.1  christos                         fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
    626      1.1  christos                     else
    627      1.1  christos                         gz_uncompress(file, stdout);
    628      1.1  christos                 } else {
    629      1.1  christos                     file_uncompress(*argv);
    630      1.1  christos                 }
    631      1.1  christos             } else {
    632      1.1  christos                 if (copyout) {
    633      1.1  christos                     FILE * in = fopen(*argv, "rb");
    634      1.1  christos 
    635      1.1  christos                     if (in == NULL) {
    636      1.1  christos                         perror(*argv);
    637      1.1  christos                     } else {
    638      1.1  christos                         file = gzdopen(fileno(stdout), outmode);
    639      1.1  christos                         if (file == NULL) error("can't gzdopen stdout");
    640      1.1  christos 
    641      1.1  christos                         gz_compress(in, file);
    642      1.1  christos                     }
    643      1.1  christos 
    644      1.1  christos                 } else {
    645      1.1  christos                     file_compress(*argv, outmode);
    646      1.1  christos                 }
    647      1.1  christos             }
    648      1.1  christos         } while (argv++, --argc);
    649      1.1  christos     }
    650      1.1  christos     return 0;
    651      1.1  christos }
    652