xref: /openbsd-src/regress/lib/libz/minigzip.c (revision b0b511c0b490f43041ffa8cb2f90c4950edbede4)
12569963fSbluhm /* minigzip.c -- simulate gzip using the zlib compression library
22569963fSbluhm  * Copyright (C) 1995-2006, 2010, 2011, 2016 Jean-loup Gailly
32569963fSbluhm  * For conditions of distribution and use, see copyright notice in zlib.h
42569963fSbluhm  */
52569963fSbluhm 
62569963fSbluhm /*
72569963fSbluhm  * minigzip is a minimal implementation of the gzip utility. This is
82569963fSbluhm  * only an example of using zlib and isn't meant to replace the
92569963fSbluhm  * full-featured gzip. No attempt is made to deal with file systems
102569963fSbluhm  * limiting names to 14 or 8+3 characters, etc... Error checking is
112569963fSbluhm  * very limited. So use minigzip only for testing; use gzip for the
122569963fSbluhm  * real thing. On MSDOS, use only on file names without extension
132569963fSbluhm  * or in pipe mode.
142569963fSbluhm  */
152569963fSbluhm 
16*b0b511c0Stb /* @(#) $Id: minigzip.c,v 1.2 2023/11/18 22:40:14 tb Exp $ */
172569963fSbluhm 
182569963fSbluhm #include "zlib.h"
192569963fSbluhm #include <stdio.h>
202569963fSbluhm 
212569963fSbluhm #ifdef STDC
222569963fSbluhm #  include <string.h>
232569963fSbluhm #  include <stdlib.h>
242569963fSbluhm #endif
252569963fSbluhm 
262569963fSbluhm #ifdef USE_MMAP
272569963fSbluhm #  include <sys/types.h>
282569963fSbluhm #  include <sys/mman.h>
292569963fSbluhm #  include <sys/stat.h>
302569963fSbluhm #endif
312569963fSbluhm 
322569963fSbluhm #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
332569963fSbluhm #  include <fcntl.h>
342569963fSbluhm #  include <io.h>
352569963fSbluhm #  ifdef UNDER_CE
362569963fSbluhm #    include <stdlib.h>
372569963fSbluhm #  endif
382569963fSbluhm #  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
392569963fSbluhm #else
402569963fSbluhm #  define SET_BINARY_MODE(file)
412569963fSbluhm #endif
422569963fSbluhm 
432569963fSbluhm #if defined(_MSC_VER) && _MSC_VER < 1900
442569963fSbluhm #  define snprintf _snprintf
452569963fSbluhm #endif
462569963fSbluhm 
472569963fSbluhm #ifdef VMS
482569963fSbluhm #  define unlink delete
492569963fSbluhm #  define GZ_SUFFIX "-gz"
502569963fSbluhm #endif
512569963fSbluhm #ifdef RISCOS
522569963fSbluhm #  define unlink remove
532569963fSbluhm #  define GZ_SUFFIX "-gz"
542569963fSbluhm #  define fileno(file) file->__file
552569963fSbluhm #endif
562569963fSbluhm #if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
572569963fSbluhm #  include <unix.h> /* for fileno */
582569963fSbluhm #endif
592569963fSbluhm 
602569963fSbluhm #if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
612569963fSbluhm #ifndef WIN32 /* unlink already in stdio.h for WIN32 */
62*b0b511c0Stb   extern int unlink(const char *);
632569963fSbluhm #endif
642569963fSbluhm #endif
652569963fSbluhm 
662569963fSbluhm #if defined(UNDER_CE)
672569963fSbluhm #  include <windows.h>
682569963fSbluhm #  define perror(s) pwinerror(s)
692569963fSbluhm 
702569963fSbluhm /* Map the Windows error number in ERROR to a locale-dependent error
712569963fSbluhm    message string and return a pointer to it.  Typically, the values
722569963fSbluhm    for ERROR come from GetLastError.
732569963fSbluhm 
742569963fSbluhm    The string pointed to shall not be modified by the application,
752569963fSbluhm    but may be overwritten by a subsequent call to strwinerror
762569963fSbluhm 
772569963fSbluhm    The strwinerror function does not change the current setting
782569963fSbluhm    of GetLastError.  */
792569963fSbluhm 
strwinerror(error)802569963fSbluhm static char *strwinerror (error)
812569963fSbluhm      DWORD error;
822569963fSbluhm {
832569963fSbluhm     static char buf[1024];
842569963fSbluhm 
852569963fSbluhm     wchar_t *msgbuf;
862569963fSbluhm     DWORD lasterr = GetLastError();
872569963fSbluhm     DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
882569963fSbluhm         | FORMAT_MESSAGE_ALLOCATE_BUFFER,
892569963fSbluhm         NULL,
902569963fSbluhm         error,
912569963fSbluhm         0, /* Default language */
922569963fSbluhm         (LPVOID)&msgbuf,
932569963fSbluhm         0,
942569963fSbluhm         NULL);
952569963fSbluhm     if (chars != 0) {
962569963fSbluhm         /* If there is an \r\n appended, zap it.  */
972569963fSbluhm         if (chars >= 2
982569963fSbluhm             && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
992569963fSbluhm             chars -= 2;
1002569963fSbluhm             msgbuf[chars] = 0;
1012569963fSbluhm         }
1022569963fSbluhm 
1032569963fSbluhm         if (chars > sizeof (buf) - 1) {
1042569963fSbluhm             chars = sizeof (buf) - 1;
1052569963fSbluhm             msgbuf[chars] = 0;
1062569963fSbluhm         }
1072569963fSbluhm 
1082569963fSbluhm         wcstombs(buf, msgbuf, chars + 1);
1092569963fSbluhm         LocalFree(msgbuf);
1102569963fSbluhm     }
1112569963fSbluhm     else {
1122569963fSbluhm         sprintf(buf, "unknown win32 error (%ld)", error);
1132569963fSbluhm     }
1142569963fSbluhm 
1152569963fSbluhm     SetLastError(lasterr);
1162569963fSbluhm     return buf;
1172569963fSbluhm }
1182569963fSbluhm 
pwinerror(s)1192569963fSbluhm static void pwinerror (s)
1202569963fSbluhm     const char *s;
1212569963fSbluhm {
1222569963fSbluhm     if (s && *s)
1232569963fSbluhm         fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));
1242569963fSbluhm     else
1252569963fSbluhm         fprintf(stderr, "%s\n", strwinerror(GetLastError ()));
1262569963fSbluhm }
1272569963fSbluhm 
1282569963fSbluhm #endif /* UNDER_CE */
1292569963fSbluhm 
1302569963fSbluhm #ifndef GZ_SUFFIX
1312569963fSbluhm #  define GZ_SUFFIX ".gz"
1322569963fSbluhm #endif
1332569963fSbluhm #define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
1342569963fSbluhm 
1352569963fSbluhm #define BUFLEN      16384
1362569963fSbluhm #define MAX_NAME_LEN 1024
1372569963fSbluhm 
1382569963fSbluhm #ifdef MAXSEG_64K
1392569963fSbluhm #  define local static
1402569963fSbluhm    /* Needed for systems with limitation on stack size. */
1412569963fSbluhm #else
1422569963fSbluhm #  define local
1432569963fSbluhm #endif
1442569963fSbluhm 
1452569963fSbluhm #ifdef Z_SOLO
1462569963fSbluhm /* for Z_SOLO, create simplified gz* functions using deflate and inflate */
1472569963fSbluhm 
1482569963fSbluhm #if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
1492569963fSbluhm #  include <unistd.h>       /* for unlink() */
1502569963fSbluhm #endif
1512569963fSbluhm 
myalloc(void * q,unsigned n,unsigned m)152*b0b511c0Stb static void *myalloc(void *q, unsigned n, unsigned m) {
1532569963fSbluhm     (void)q;
1542569963fSbluhm     return calloc(n, m);
1552569963fSbluhm }
1562569963fSbluhm 
myfree(void * q,void * p)157*b0b511c0Stb static void myfree(void *q, void *p) {
1582569963fSbluhm     (void)q;
1592569963fSbluhm     free(p);
1602569963fSbluhm }
1612569963fSbluhm 
1622569963fSbluhm typedef struct gzFile_s {
1632569963fSbluhm     FILE *file;
1642569963fSbluhm     int write;
1652569963fSbluhm     int err;
1662569963fSbluhm     char *msg;
1672569963fSbluhm     z_stream strm;
1682569963fSbluhm } *gzFile;
1692569963fSbluhm 
gz_open(const char * path,int fd,const char * mode)170*b0b511c0Stb static gzFile gz_open(const char *path, int fd, const char *mode) {
1712569963fSbluhm     gzFile gz;
1722569963fSbluhm     int ret;
1732569963fSbluhm 
1742569963fSbluhm     gz = malloc(sizeof(struct gzFile_s));
1752569963fSbluhm     if (gz == NULL)
1762569963fSbluhm         return NULL;
1772569963fSbluhm     gz->write = strchr(mode, 'w') != NULL;
1782569963fSbluhm     gz->strm.zalloc = myalloc;
1792569963fSbluhm     gz->strm.zfree = myfree;
1802569963fSbluhm     gz->strm.opaque = Z_NULL;
1812569963fSbluhm     if (gz->write)
1822569963fSbluhm         ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0);
1832569963fSbluhm     else {
1842569963fSbluhm         gz->strm.next_in = 0;
1852569963fSbluhm         gz->strm.avail_in = Z_NULL;
1862569963fSbluhm         ret = inflateInit2(&(gz->strm), 15 + 16);
1872569963fSbluhm     }
1882569963fSbluhm     if (ret != Z_OK) {
1892569963fSbluhm         free(gz);
1902569963fSbluhm         return NULL;
1912569963fSbluhm     }
1922569963fSbluhm     gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") :
1932569963fSbluhm                               fopen(path, gz->write ? "wb" : "rb");
1942569963fSbluhm     if (gz->file == NULL) {
1952569963fSbluhm         gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm));
1962569963fSbluhm         free(gz);
1972569963fSbluhm         return NULL;
1982569963fSbluhm     }
1992569963fSbluhm     gz->err = 0;
2002569963fSbluhm     gz->msg = "";
2012569963fSbluhm     return gz;
2022569963fSbluhm }
2032569963fSbluhm 
gzopen(const char * path,const char * mode)204*b0b511c0Stb static gzFile gzopen(const char *path, const char *mode) {
205*b0b511c0Stb     return gz_open(path, -1, mode);
206*b0b511c0Stb }
2072569963fSbluhm 
gzdopen(int fd,const char * mode)208*b0b511c0Stb static gzFile gzdopen(int fd, const char *mode) {
209*b0b511c0Stb     return gz_open(NULL, fd, mode);
210*b0b511c0Stb }
211*b0b511c0Stb 
gzwrite(gzFile gz,const void * buf,unsigned len)212*b0b511c0Stb static int gzwrite(gzFile gz, const void *buf, unsigned len) {
2132569963fSbluhm     z_stream *strm;
2142569963fSbluhm     unsigned char out[BUFLEN];
2152569963fSbluhm 
2162569963fSbluhm     if (gz == NULL || !gz->write)
2172569963fSbluhm         return 0;
2182569963fSbluhm     strm = &(gz->strm);
2192569963fSbluhm     strm->next_in = (void *)buf;
2202569963fSbluhm     strm->avail_in = len;
2212569963fSbluhm     do {
2222569963fSbluhm         strm->next_out = out;
2232569963fSbluhm         strm->avail_out = BUFLEN;
2242569963fSbluhm         (void)deflate(strm, Z_NO_FLUSH);
2252569963fSbluhm         fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
2262569963fSbluhm     } while (strm->avail_out == 0);
2272569963fSbluhm     return len;
2282569963fSbluhm }
2292569963fSbluhm 
gzread(gzFile gz,void * buf,unsigned len)230*b0b511c0Stb static int gzread(gzFile gz, void *buf, unsigned len) {
2312569963fSbluhm     int ret;
2322569963fSbluhm     unsigned got;
2332569963fSbluhm     unsigned char in[1];
2342569963fSbluhm     z_stream *strm;
2352569963fSbluhm 
2362569963fSbluhm     if (gz == NULL || gz->write)
2372569963fSbluhm         return 0;
2382569963fSbluhm     if (gz->err)
2392569963fSbluhm         return 0;
2402569963fSbluhm     strm = &(gz->strm);
2412569963fSbluhm     strm->next_out = (void *)buf;
2422569963fSbluhm     strm->avail_out = len;
2432569963fSbluhm     do {
2442569963fSbluhm         got = fread(in, 1, 1, gz->file);
2452569963fSbluhm         if (got == 0)
2462569963fSbluhm             break;
2472569963fSbluhm         strm->next_in = in;
2482569963fSbluhm         strm->avail_in = 1;
2492569963fSbluhm         ret = inflate(strm, Z_NO_FLUSH);
2502569963fSbluhm         if (ret == Z_DATA_ERROR) {
2512569963fSbluhm             gz->err = Z_DATA_ERROR;
2522569963fSbluhm             gz->msg = strm->msg;
2532569963fSbluhm             return 0;
2542569963fSbluhm         }
2552569963fSbluhm         if (ret == Z_STREAM_END)
2562569963fSbluhm             inflateReset(strm);
2572569963fSbluhm     } while (strm->avail_out);
2582569963fSbluhm     return len - strm->avail_out;
2592569963fSbluhm }
2602569963fSbluhm 
gzclose(gzFile gz)261*b0b511c0Stb static int gzclose(gzFile gz) {
2622569963fSbluhm     z_stream *strm;
2632569963fSbluhm     unsigned char out[BUFLEN];
2642569963fSbluhm 
2652569963fSbluhm     if (gz == NULL)
2662569963fSbluhm         return Z_STREAM_ERROR;
2672569963fSbluhm     strm = &(gz->strm);
2682569963fSbluhm     if (gz->write) {
2692569963fSbluhm         strm->next_in = Z_NULL;
2702569963fSbluhm         strm->avail_in = 0;
2712569963fSbluhm         do {
2722569963fSbluhm             strm->next_out = out;
2732569963fSbluhm             strm->avail_out = BUFLEN;
2742569963fSbluhm             (void)deflate(strm, Z_FINISH);
2752569963fSbluhm             fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
2762569963fSbluhm         } while (strm->avail_out == 0);
2772569963fSbluhm         deflateEnd(strm);
2782569963fSbluhm     }
2792569963fSbluhm     else
2802569963fSbluhm         inflateEnd(strm);
2812569963fSbluhm     fclose(gz->file);
2822569963fSbluhm     free(gz);
2832569963fSbluhm     return Z_OK;
2842569963fSbluhm }
2852569963fSbluhm 
gzerror(gzFile gz,int * err)286*b0b511c0Stb static const char *gzerror(gzFile gz, int *err) {
2872569963fSbluhm     *err = gz->err;
2882569963fSbluhm     return gz->msg;
2892569963fSbluhm }
2902569963fSbluhm 
2912569963fSbluhm #endif
2922569963fSbluhm 
2932569963fSbluhm static char *prog;
2942569963fSbluhm 
2952569963fSbluhm /* ===========================================================================
2962569963fSbluhm  * Display error message and exit
2972569963fSbluhm  */
error(const char * msg)298*b0b511c0Stb static void error(const char *msg) {
2992569963fSbluhm     fprintf(stderr, "%s: %s\n", prog, msg);
3002569963fSbluhm     exit(1);
3012569963fSbluhm }
3022569963fSbluhm 
3032569963fSbluhm #ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
3042569963fSbluhm 
3052569963fSbluhm /* Try compressing the input file at once using mmap. Return Z_OK if
3062569963fSbluhm  * if success, Z_ERRNO otherwise.
3072569963fSbluhm  */
gz_compress_mmap(FILE * in,gzFile out)308*b0b511c0Stb static int gz_compress_mmap(FILE *in, gzFile out) {
3092569963fSbluhm     int len;
3102569963fSbluhm     int err;
3112569963fSbluhm     int ifd = fileno(in);
3122569963fSbluhm     caddr_t buf;    /* mmap'ed buffer for the entire input file */
3132569963fSbluhm     off_t buf_len;  /* length of the input file */
3142569963fSbluhm     struct stat sb;
3152569963fSbluhm 
3162569963fSbluhm     /* Determine the size of the file, needed for mmap: */
3172569963fSbluhm     if (fstat(ifd, &sb) < 0) return Z_ERRNO;
3182569963fSbluhm     buf_len = sb.st_size;
3192569963fSbluhm     if (buf_len <= 0) return Z_ERRNO;
3202569963fSbluhm 
3212569963fSbluhm     /* Now do the actual mmap: */
3222569963fSbluhm     buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
3232569963fSbluhm     if (buf == (caddr_t)(-1)) return Z_ERRNO;
3242569963fSbluhm 
3252569963fSbluhm     /* Compress the whole file at once: */
3262569963fSbluhm     len = gzwrite(out, (char *)buf, (unsigned)buf_len);
3272569963fSbluhm 
3282569963fSbluhm     if (len != (int)buf_len) error(gzerror(out, &err));
3292569963fSbluhm 
3302569963fSbluhm     munmap(buf, buf_len);
3312569963fSbluhm     fclose(in);
3322569963fSbluhm     if (gzclose(out) != Z_OK) error("failed gzclose");
3332569963fSbluhm     return Z_OK;
3342569963fSbluhm }
3352569963fSbluhm #endif /* USE_MMAP */
3362569963fSbluhm 
3372569963fSbluhm /* ===========================================================================
338*b0b511c0Stb  * Compress input to output then close both files.
339*b0b511c0Stb  */
340*b0b511c0Stb 
gz_compress(FILE * in,gzFile out)341*b0b511c0Stb static void gz_compress(FILE *in, gzFile out) {
342*b0b511c0Stb     local char buf[BUFLEN];
343*b0b511c0Stb     int len;
344*b0b511c0Stb     int err;
345*b0b511c0Stb 
346*b0b511c0Stb #ifdef USE_MMAP
347*b0b511c0Stb     /* Try first compressing with mmap. If mmap fails (minigzip used in a
348*b0b511c0Stb      * pipe), use the normal fread loop.
349*b0b511c0Stb      */
350*b0b511c0Stb     if (gz_compress_mmap(in, out) == Z_OK) return;
351*b0b511c0Stb #endif
352*b0b511c0Stb     for (;;) {
353*b0b511c0Stb         len = (int)fread(buf, 1, sizeof(buf), in);
354*b0b511c0Stb         if (ferror(in)) {
355*b0b511c0Stb             perror("fread");
356*b0b511c0Stb             exit(1);
357*b0b511c0Stb         }
358*b0b511c0Stb         if (len == 0) break;
359*b0b511c0Stb 
360*b0b511c0Stb         if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
361*b0b511c0Stb     }
362*b0b511c0Stb     fclose(in);
363*b0b511c0Stb     if (gzclose(out) != Z_OK) error("failed gzclose");
364*b0b511c0Stb }
365*b0b511c0Stb 
366*b0b511c0Stb /* ===========================================================================
3672569963fSbluhm  * Uncompress input to output then close both files.
3682569963fSbluhm  */
gz_uncompress(gzFile in,FILE * out)369*b0b511c0Stb static void gz_uncompress(gzFile in, FILE *out) {
3702569963fSbluhm     local char buf[BUFLEN];
3712569963fSbluhm     int len;
3722569963fSbluhm     int err;
3732569963fSbluhm 
3742569963fSbluhm     for (;;) {
3752569963fSbluhm         len = gzread(in, buf, sizeof(buf));
3762569963fSbluhm         if (len < 0) error (gzerror(in, &err));
3772569963fSbluhm         if (len == 0) break;
3782569963fSbluhm 
3792569963fSbluhm         if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
3802569963fSbluhm             error("failed fwrite");
3812569963fSbluhm         }
3822569963fSbluhm     }
3832569963fSbluhm     if (fclose(out)) error("failed fclose");
3842569963fSbluhm 
3852569963fSbluhm     if (gzclose(in) != Z_OK) error("failed gzclose");
3862569963fSbluhm }
3872569963fSbluhm 
3882569963fSbluhm 
3892569963fSbluhm /* ===========================================================================
3902569963fSbluhm  * Compress the given file: create a corresponding .gz file and remove the
3912569963fSbluhm  * original.
3922569963fSbluhm  */
file_compress(char * file,char * mode)393*b0b511c0Stb static void file_compress(char *file, char *mode) {
3942569963fSbluhm     local char outfile[MAX_NAME_LEN];
3952569963fSbluhm     FILE  *in;
3962569963fSbluhm     gzFile out;
3972569963fSbluhm 
3982569963fSbluhm     if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
3992569963fSbluhm         fprintf(stderr, "%s: filename too long\n", prog);
4002569963fSbluhm         exit(1);
4012569963fSbluhm     }
4022569963fSbluhm 
4032569963fSbluhm #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
4042569963fSbluhm     snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX);
4052569963fSbluhm #else
4062569963fSbluhm     strcpy(outfile, file);
4072569963fSbluhm     strcat(outfile, GZ_SUFFIX);
4082569963fSbluhm #endif
4092569963fSbluhm 
4102569963fSbluhm     in = fopen(file, "rb");
4112569963fSbluhm     if (in == NULL) {
4122569963fSbluhm         perror(file);
4132569963fSbluhm         exit(1);
4142569963fSbluhm     }
4152569963fSbluhm     out = gzopen(outfile, mode);
4162569963fSbluhm     if (out == NULL) {
4172569963fSbluhm         fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
4182569963fSbluhm         exit(1);
4192569963fSbluhm     }
4202569963fSbluhm     gz_compress(in, out);
4212569963fSbluhm 
4222569963fSbluhm     unlink(file);
4232569963fSbluhm }
4242569963fSbluhm 
4252569963fSbluhm 
4262569963fSbluhm /* ===========================================================================
4272569963fSbluhm  * Uncompress the given file and remove the original.
4282569963fSbluhm  */
file_uncompress(char * file)429*b0b511c0Stb static void file_uncompress(char *file) {
4302569963fSbluhm     local char buf[MAX_NAME_LEN];
4312569963fSbluhm     char *infile, *outfile;
4322569963fSbluhm     FILE  *out;
4332569963fSbluhm     gzFile in;
434*b0b511c0Stb     z_size_t len = strlen(file);
4352569963fSbluhm 
4362569963fSbluhm     if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
4372569963fSbluhm         fprintf(stderr, "%s: filename too long\n", prog);
4382569963fSbluhm         exit(1);
4392569963fSbluhm     }
4402569963fSbluhm 
4412569963fSbluhm #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
4422569963fSbluhm     snprintf(buf, sizeof(buf), "%s", file);
4432569963fSbluhm #else
4442569963fSbluhm     strcpy(buf, file);
4452569963fSbluhm #endif
4462569963fSbluhm 
4472569963fSbluhm     if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
4482569963fSbluhm         infile = file;
4492569963fSbluhm         outfile = buf;
4502569963fSbluhm         outfile[len-3] = '\0';
4512569963fSbluhm     } else {
4522569963fSbluhm         outfile = file;
4532569963fSbluhm         infile = buf;
4542569963fSbluhm #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
4552569963fSbluhm         snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX);
4562569963fSbluhm #else
4572569963fSbluhm         strcat(infile, GZ_SUFFIX);
4582569963fSbluhm #endif
4592569963fSbluhm     }
4602569963fSbluhm     in = gzopen(infile, "rb");
4612569963fSbluhm     if (in == NULL) {
4622569963fSbluhm         fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
4632569963fSbluhm         exit(1);
4642569963fSbluhm     }
4652569963fSbluhm     out = fopen(outfile, "wb");
4662569963fSbluhm     if (out == NULL) {
4672569963fSbluhm         perror(file);
4682569963fSbluhm         exit(1);
4692569963fSbluhm     }
4702569963fSbluhm 
4712569963fSbluhm     gz_uncompress(in, out);
4722569963fSbluhm 
4732569963fSbluhm     unlink(infile);
4742569963fSbluhm }
4752569963fSbluhm 
4762569963fSbluhm 
4772569963fSbluhm /* ===========================================================================
4782569963fSbluhm  * Usage:  minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
4792569963fSbluhm  *   -c : write to standard output
4802569963fSbluhm  *   -d : decompress
4812569963fSbluhm  *   -f : compress with Z_FILTERED
4822569963fSbluhm  *   -h : compress with Z_HUFFMAN_ONLY
4832569963fSbluhm  *   -r : compress with Z_RLE
4842569963fSbluhm  *   -1 to -9 : compression level
4852569963fSbluhm  */
4862569963fSbluhm 
main(int argc,char * argv[])487*b0b511c0Stb int main(int argc, char *argv[]) {
4882569963fSbluhm     int copyout = 0;
4892569963fSbluhm     int uncompr = 0;
4902569963fSbluhm     gzFile file;
4912569963fSbluhm     char *bname, outmode[20];
4922569963fSbluhm 
4932569963fSbluhm #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
4942569963fSbluhm     snprintf(outmode, sizeof(outmode), "%s", "wb6 ");
4952569963fSbluhm #else
4962569963fSbluhm     strcpy(outmode, "wb6 ");
4972569963fSbluhm #endif
4982569963fSbluhm 
4992569963fSbluhm     prog = argv[0];
5002569963fSbluhm     bname = strrchr(argv[0], '/');
5012569963fSbluhm     if (bname)
5022569963fSbluhm       bname++;
5032569963fSbluhm     else
5042569963fSbluhm       bname = argv[0];
5052569963fSbluhm     argc--, argv++;
5062569963fSbluhm 
5072569963fSbluhm     if (!strcmp(bname, "gunzip"))
5082569963fSbluhm       uncompr = 1;
5092569963fSbluhm     else if (!strcmp(bname, "zcat"))
5102569963fSbluhm       copyout = uncompr = 1;
5112569963fSbluhm 
5122569963fSbluhm     while (argc > 0) {
5132569963fSbluhm       if (strcmp(*argv, "-c") == 0)
5142569963fSbluhm         copyout = 1;
5152569963fSbluhm       else if (strcmp(*argv, "-d") == 0)
5162569963fSbluhm         uncompr = 1;
5172569963fSbluhm       else if (strcmp(*argv, "-f") == 0)
5182569963fSbluhm         outmode[3] = 'f';
5192569963fSbluhm       else if (strcmp(*argv, "-h") == 0)
5202569963fSbluhm         outmode[3] = 'h';
5212569963fSbluhm       else if (strcmp(*argv, "-r") == 0)
5222569963fSbluhm         outmode[3] = 'R';
5232569963fSbluhm       else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
5242569963fSbluhm                (*argv)[2] == 0)
5252569963fSbluhm         outmode[2] = (*argv)[1];
5262569963fSbluhm       else
5272569963fSbluhm         break;
5282569963fSbluhm       argc--, argv++;
5292569963fSbluhm     }
5302569963fSbluhm     if (outmode[3] == ' ')
5312569963fSbluhm         outmode[3] = 0;
5322569963fSbluhm     if (argc == 0) {
5332569963fSbluhm         SET_BINARY_MODE(stdin);
5342569963fSbluhm         SET_BINARY_MODE(stdout);
5352569963fSbluhm         if (uncompr) {
5362569963fSbluhm             file = gzdopen(fileno(stdin), "rb");
5372569963fSbluhm             if (file == NULL) error("can't gzdopen stdin");
5382569963fSbluhm             gz_uncompress(file, stdout);
5392569963fSbluhm         } else {
5402569963fSbluhm             file = gzdopen(fileno(stdout), outmode);
5412569963fSbluhm             if (file == NULL) error("can't gzdopen stdout");
5422569963fSbluhm             gz_compress(stdin, file);
5432569963fSbluhm         }
5442569963fSbluhm     } else {
5452569963fSbluhm         if (copyout) {
5462569963fSbluhm             SET_BINARY_MODE(stdout);
5472569963fSbluhm         }
5482569963fSbluhm         do {
5492569963fSbluhm             if (uncompr) {
5502569963fSbluhm                 if (copyout) {
5512569963fSbluhm                     file = gzopen(*argv, "rb");
5522569963fSbluhm                     if (file == NULL)
5532569963fSbluhm                         fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
5542569963fSbluhm                     else
5552569963fSbluhm                         gz_uncompress(file, stdout);
5562569963fSbluhm                 } else {
5572569963fSbluhm                     file_uncompress(*argv);
5582569963fSbluhm                 }
5592569963fSbluhm             } else {
5602569963fSbluhm                 if (copyout) {
5612569963fSbluhm                     FILE * in = fopen(*argv, "rb");
5622569963fSbluhm 
5632569963fSbluhm                     if (in == NULL) {
5642569963fSbluhm                         perror(*argv);
5652569963fSbluhm                     } else {
5662569963fSbluhm                         file = gzdopen(fileno(stdout), outmode);
5672569963fSbluhm                         if (file == NULL) error("can't gzdopen stdout");
5682569963fSbluhm 
5692569963fSbluhm                         gz_compress(in, file);
5702569963fSbluhm                     }
5712569963fSbluhm 
5722569963fSbluhm                 } else {
5732569963fSbluhm                     file_compress(*argv, outmode);
5742569963fSbluhm                 }
5752569963fSbluhm             }
5762569963fSbluhm         } while (argv++, --argc);
5772569963fSbluhm     }
5782569963fSbluhm     return 0;
5792569963fSbluhm }
580