xref: /freebsd-src/sys/contrib/zstd/zlibWrapper/examples/minigzip.c (revision c6879c6c14eedbd060ba588a3129a6c60ebbe783)
10c16b537SWarner Losh /* minigzip.c contains minimal changes required to be compiled with zlibWrapper:
20c16b537SWarner Losh  * - #include "zlib.h" was changed to #include "zstd_zlibwrapper.h"        */
30c16b537SWarner Losh 
40c16b537SWarner Losh /* minigzip.c -- simulate gzip using the zlib compression library
50c16b537SWarner Losh  * Copyright (C) 1995-2006, 2010, 2011 Jean-loup Gailly.
60c16b537SWarner Losh  * For conditions of distribution and use, see http://www.zlib.net/zlib_license.html
70c16b537SWarner Losh  */
80c16b537SWarner Losh 
90c16b537SWarner Losh /*
100c16b537SWarner Losh  * minigzip is a minimal implementation of the gzip utility. This is
110c16b537SWarner Losh  * only an example of using zlib and isn't meant to replace the
120c16b537SWarner Losh  * full-featured gzip. No attempt is made to deal with file systems
130c16b537SWarner Losh  * limiting names to 14 or 8+3 characters, etc... Error checking is
140c16b537SWarner Losh  * very limited. So use minigzip only for testing; use gzip for the
150c16b537SWarner Losh  * real thing. On MSDOS, use only on file names without extension
160c16b537SWarner Losh  * or in pipe mode.
170c16b537SWarner Losh  */
180c16b537SWarner Losh 
190c16b537SWarner Losh /* @(#) $Id$ */
200c16b537SWarner Losh 
21*0f743729SConrad Meyer #define _POSIX_SOURCE /* fileno */
22*0f743729SConrad Meyer 
230c16b537SWarner Losh #include "zstd_zlibwrapper.h"
240c16b537SWarner Losh #include <stdio.h>
250c16b537SWarner Losh 
260c16b537SWarner Losh #ifdef STDC
270c16b537SWarner Losh #  include <string.h>
280c16b537SWarner Losh #  include <stdlib.h>
290c16b537SWarner Losh #endif
300c16b537SWarner Losh 
310c16b537SWarner Losh #ifdef USE_MMAP
320c16b537SWarner Losh #  include <sys/types.h>
330c16b537SWarner Losh #  include <sys/mman.h>
340c16b537SWarner Losh #  include <sys/stat.h>
350c16b537SWarner Losh #endif
360c16b537SWarner Losh 
370c16b537SWarner Losh #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
380c16b537SWarner Losh #  include <fcntl.h>
390c16b537SWarner Losh #  include <io.h>
400c16b537SWarner Losh #  ifdef UNDER_CE
410c16b537SWarner Losh #    include <stdlib.h>
420c16b537SWarner Losh #  endif
430c16b537SWarner Losh #  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
440c16b537SWarner Losh #else
450c16b537SWarner Losh #  define SET_BINARY_MODE(file)
460c16b537SWarner Losh #endif
470c16b537SWarner Losh 
480c16b537SWarner Losh #ifdef _MSC_VER
490c16b537SWarner Losh #  define snprintf _snprintf
500c16b537SWarner Losh #endif
510c16b537SWarner Losh 
520c16b537SWarner Losh #ifdef VMS
530c16b537SWarner Losh #  define unlink delete
540c16b537SWarner Losh #  define GZ_SUFFIX "-gz"
550c16b537SWarner Losh #endif
560c16b537SWarner Losh #ifdef RISCOS
570c16b537SWarner Losh #  define unlink remove
580c16b537SWarner Losh #  define GZ_SUFFIX "-gz"
590c16b537SWarner Losh #  define fileno(file) file->__file
600c16b537SWarner Losh #endif
610c16b537SWarner Losh #if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
620c16b537SWarner Losh #  include <unix.h> /* for fileno */
630c16b537SWarner Losh #endif
640c16b537SWarner Losh 
650c16b537SWarner Losh #if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
660c16b537SWarner Losh #ifndef WIN32 /* unlink already in stdio.h for WIN32 */
670c16b537SWarner Losh   extern int unlink OF((const char *));
680c16b537SWarner Losh #endif
690c16b537SWarner Losh #endif
700c16b537SWarner Losh 
710c16b537SWarner Losh #if defined(UNDER_CE)
720c16b537SWarner Losh #  include <windows.h>
730c16b537SWarner Losh #  define perror(s) pwinerror(s)
740c16b537SWarner Losh 
750c16b537SWarner Losh /* Map the Windows error number in ERROR to a locale-dependent error
760c16b537SWarner Losh    message string and return a pointer to it.  Typically, the values
770c16b537SWarner Losh    for ERROR come from GetLastError.
780c16b537SWarner Losh 
790c16b537SWarner Losh    The string pointed to shall not be modified by the application,
800c16b537SWarner Losh    but may be overwritten by a subsequent call to strwinerror
810c16b537SWarner Losh 
820c16b537SWarner Losh    The strwinerror function does not change the current setting
830c16b537SWarner Losh    of GetLastError.  */
840c16b537SWarner Losh 
strwinerror(error)850c16b537SWarner Losh static char *strwinerror (error)
860c16b537SWarner Losh      DWORD error;
870c16b537SWarner Losh {
880c16b537SWarner Losh     static char buf[1024];
890c16b537SWarner Losh 
900c16b537SWarner Losh     wchar_t *msgbuf;
910c16b537SWarner Losh     DWORD lasterr = GetLastError();
920c16b537SWarner Losh     DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
930c16b537SWarner Losh         | FORMAT_MESSAGE_ALLOCATE_BUFFER,
940c16b537SWarner Losh         NULL,
950c16b537SWarner Losh         error,
960c16b537SWarner Losh         0, /* Default language */
970c16b537SWarner Losh         (LPVOID)&msgbuf,
980c16b537SWarner Losh         0,
990c16b537SWarner Losh         NULL);
1000c16b537SWarner Losh     if (chars != 0) {
1010c16b537SWarner Losh         /* If there is an \r\n appended, zap it.  */
1020c16b537SWarner Losh         if (chars >= 2
1030c16b537SWarner Losh             && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
1040c16b537SWarner Losh             chars -= 2;
1050c16b537SWarner Losh             msgbuf[chars] = 0;
1060c16b537SWarner Losh         }
1070c16b537SWarner Losh 
1080c16b537SWarner Losh         if (chars > sizeof (buf) - 1) {
1090c16b537SWarner Losh             chars = sizeof (buf) - 1;
1100c16b537SWarner Losh             msgbuf[chars] = 0;
1110c16b537SWarner Losh         }
1120c16b537SWarner Losh 
1130c16b537SWarner Losh         wcstombs(buf, msgbuf, chars + 1);
1140c16b537SWarner Losh         LocalFree(msgbuf);
1150c16b537SWarner Losh     }
1160c16b537SWarner Losh     else {
1170c16b537SWarner Losh         sprintf(buf, "unknown win32 error (%ld)", error);
1180c16b537SWarner Losh     }
1190c16b537SWarner Losh 
1200c16b537SWarner Losh     SetLastError(lasterr);
1210c16b537SWarner Losh     return buf;
1220c16b537SWarner Losh }
1230c16b537SWarner Losh 
pwinerror(s)1240c16b537SWarner Losh static void pwinerror (s)
1250c16b537SWarner Losh     const char *s;
1260c16b537SWarner Losh {
1270c16b537SWarner Losh     if (s && *s)
1280c16b537SWarner Losh         fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));
1290c16b537SWarner Losh     else
1300c16b537SWarner Losh         fprintf(stderr, "%s\n", strwinerror(GetLastError ()));
1310c16b537SWarner Losh }
1320c16b537SWarner Losh 
1330c16b537SWarner Losh #endif /* UNDER_CE */
1340c16b537SWarner Losh 
1350c16b537SWarner Losh #ifndef GZ_SUFFIX
1360c16b537SWarner Losh #  define GZ_SUFFIX ".gz"
1370c16b537SWarner Losh #endif
1380c16b537SWarner Losh #define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
1390c16b537SWarner Losh 
1400c16b537SWarner Losh #define BUFLEN      16384
1410c16b537SWarner Losh #define MAX_NAME_LEN 1024
1420c16b537SWarner Losh 
1430c16b537SWarner Losh #ifdef MAXSEG_64K
1440c16b537SWarner Losh #  define local static
1450c16b537SWarner Losh    /* Needed for systems with limitation on stack size. */
1460c16b537SWarner Losh #else
1470c16b537SWarner Losh #  define local
1480c16b537SWarner Losh #endif
1490c16b537SWarner Losh 
1500c16b537SWarner Losh #ifdef Z_SOLO
1510c16b537SWarner Losh /* for Z_SOLO, create simplified gz* functions using deflate and inflate */
1520c16b537SWarner Losh 
1530c16b537SWarner Losh #if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
1540c16b537SWarner Losh #  include <unistd.h>       /* for unlink() */
1550c16b537SWarner Losh #endif
1560c16b537SWarner Losh 
1570c16b537SWarner Losh void *myalloc OF((void *, unsigned, unsigned));
1580c16b537SWarner Losh void myfree OF((void *, void *));
1590c16b537SWarner Losh 
myalloc(q,n,m)1600c16b537SWarner Losh void *myalloc(q, n, m)
1610c16b537SWarner Losh     void *q;
1620c16b537SWarner Losh     unsigned n, m;
1630c16b537SWarner Losh {
1640c16b537SWarner Losh     q = Z_NULL;
1650c16b537SWarner Losh     return calloc(n, m);
1660c16b537SWarner Losh }
1670c16b537SWarner Losh 
myfree(q,p)1680c16b537SWarner Losh void myfree(q, p)
1690c16b537SWarner Losh     void *q, *p;
1700c16b537SWarner Losh {
1710c16b537SWarner Losh     q = Z_NULL;
1720c16b537SWarner Losh     free(p);
1730c16b537SWarner Losh }
1740c16b537SWarner Losh 
1750c16b537SWarner Losh typedef struct gzFile_s {
1760c16b537SWarner Losh     FILE *file;
1770c16b537SWarner Losh     int write;
1780c16b537SWarner Losh     int err;
1790c16b537SWarner Losh     char *msg;
1800c16b537SWarner Losh     z_stream strm;
1810c16b537SWarner Losh } *gzFile;
1820c16b537SWarner Losh 
1830c16b537SWarner Losh gzFile gzopen OF((const char *, const char *));
1840c16b537SWarner Losh gzFile gzdopen OF((int, const char *));
1850c16b537SWarner Losh gzFile gz_open OF((const char *, int, const char *));
1860c16b537SWarner Losh 
gzopen(path,mode)1870c16b537SWarner Losh gzFile gzopen(path, mode)
1880c16b537SWarner Losh const char *path;
1890c16b537SWarner Losh const char *mode;
1900c16b537SWarner Losh {
1910c16b537SWarner Losh     return gz_open(path, -1, mode);
1920c16b537SWarner Losh }
1930c16b537SWarner Losh 
gzdopen(fd,mode)1940c16b537SWarner Losh gzFile gzdopen(fd, mode)
1950c16b537SWarner Losh int fd;
1960c16b537SWarner Losh const char *mode;
1970c16b537SWarner Losh {
1980c16b537SWarner Losh     return gz_open(NULL, fd, mode);
1990c16b537SWarner Losh }
2000c16b537SWarner Losh 
gz_open(path,fd,mode)2010c16b537SWarner Losh gzFile gz_open(path, fd, mode)
2020c16b537SWarner Losh     const char *path;
2030c16b537SWarner Losh     int fd;
2040c16b537SWarner Losh     const char *mode;
2050c16b537SWarner Losh {
2060c16b537SWarner Losh     gzFile gz;
2070c16b537SWarner Losh     int ret;
2080c16b537SWarner Losh 
2090c16b537SWarner Losh     gz = malloc(sizeof(struct gzFile_s));
2100c16b537SWarner Losh     if (gz == NULL)
2110c16b537SWarner Losh         return NULL;
2120c16b537SWarner Losh     gz->write = strchr(mode, 'w') != NULL;
2130c16b537SWarner Losh     gz->strm.zalloc = myalloc;
2140c16b537SWarner Losh     gz->strm.zfree = myfree;
2150c16b537SWarner Losh     gz->strm.opaque = Z_NULL;
2160c16b537SWarner Losh     if (gz->write)
2170c16b537SWarner Losh         ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0);
2180c16b537SWarner Losh     else {
2190c16b537SWarner Losh         gz->strm.next_in = 0;
2200c16b537SWarner Losh         gz->strm.avail_in = Z_NULL;
2210c16b537SWarner Losh         ret = inflateInit2(&(gz->strm), 15 + 16);
2220c16b537SWarner Losh     }
2230c16b537SWarner Losh     if (ret != Z_OK) {
2240c16b537SWarner Losh         free(gz);
2250c16b537SWarner Losh         return NULL;
2260c16b537SWarner Losh     }
2270c16b537SWarner Losh     gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") :
2280c16b537SWarner Losh                               fopen(path, gz->write ? "wb" : "rb");
2290c16b537SWarner Losh     if (gz->file == NULL) {
2300c16b537SWarner Losh         gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm));
2310c16b537SWarner Losh         free(gz);
2320c16b537SWarner Losh         return NULL;
2330c16b537SWarner Losh     }
2340c16b537SWarner Losh     gz->err = 0;
2350c16b537SWarner Losh     gz->msg = "";
2360c16b537SWarner Losh     return gz;
2370c16b537SWarner Losh }
2380c16b537SWarner Losh 
2390c16b537SWarner Losh int gzwrite OF((gzFile, const void *, unsigned));
2400c16b537SWarner Losh 
gzwrite(gz,buf,len)2410c16b537SWarner Losh int gzwrite(gz, buf, len)
2420c16b537SWarner Losh     gzFile gz;
2430c16b537SWarner Losh     const void *buf;
2440c16b537SWarner Losh     unsigned len;
2450c16b537SWarner Losh {
2460c16b537SWarner Losh     z_stream *strm;
2470c16b537SWarner Losh     unsigned char out[BUFLEN];
2480c16b537SWarner Losh 
2490c16b537SWarner Losh     if (gz == NULL || !gz->write)
2500c16b537SWarner Losh         return 0;
2510c16b537SWarner Losh     strm = &(gz->strm);
2520c16b537SWarner Losh     strm->next_in = (void *)buf;
2530c16b537SWarner Losh     strm->avail_in = len;
2540c16b537SWarner Losh     do {
2550c16b537SWarner Losh         strm->next_out = out;
2560c16b537SWarner Losh         strm->avail_out = BUFLEN;
2570c16b537SWarner Losh         (void)deflate(strm, Z_NO_FLUSH);
2580c16b537SWarner Losh         fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
2590c16b537SWarner Losh     } while (strm->avail_out == 0);
2600c16b537SWarner Losh     return len;
2610c16b537SWarner Losh }
2620c16b537SWarner Losh 
2630c16b537SWarner Losh int gzread OF((gzFile, void *, unsigned));
2640c16b537SWarner Losh 
gzread(gz,buf,len)2650c16b537SWarner Losh int gzread(gz, buf, len)
2660c16b537SWarner Losh     gzFile gz;
2670c16b537SWarner Losh     void *buf;
2680c16b537SWarner Losh     unsigned len;
2690c16b537SWarner Losh {
2700c16b537SWarner Losh     int ret;
2710c16b537SWarner Losh     unsigned got;
2720c16b537SWarner Losh     unsigned char in[1];
2730c16b537SWarner Losh     z_stream *strm;
2740c16b537SWarner Losh 
2750c16b537SWarner Losh     if (gz == NULL || gz->write)
2760c16b537SWarner Losh         return 0;
2770c16b537SWarner Losh     if (gz->err)
2780c16b537SWarner Losh         return 0;
2790c16b537SWarner Losh     strm = &(gz->strm);
2800c16b537SWarner Losh     strm->next_out = (void *)buf;
2810c16b537SWarner Losh     strm->avail_out = len;
2820c16b537SWarner Losh     do {
2830c16b537SWarner Losh         got = fread(in, 1, 1, gz->file);
2840c16b537SWarner Losh         if (got == 0)
2850c16b537SWarner Losh             break;
2860c16b537SWarner Losh         strm->next_in = in;
2870c16b537SWarner Losh         strm->avail_in = 1;
2880c16b537SWarner Losh         ret = inflate(strm, Z_NO_FLUSH);
2890c16b537SWarner Losh         if (ret == Z_DATA_ERROR) {
2900c16b537SWarner Losh             gz->err = Z_DATA_ERROR;
2910c16b537SWarner Losh             gz->msg = strm->msg;
2920c16b537SWarner Losh             return 0;
2930c16b537SWarner Losh         }
2940c16b537SWarner Losh         if (ret == Z_STREAM_END)
2950c16b537SWarner Losh             inflateReset(strm);
2960c16b537SWarner Losh     } while (strm->avail_out);
2970c16b537SWarner Losh     return len - strm->avail_out;
2980c16b537SWarner Losh }
2990c16b537SWarner Losh 
3000c16b537SWarner Losh int gzclose OF((gzFile));
3010c16b537SWarner Losh 
gzclose(gz)3020c16b537SWarner Losh int gzclose(gz)
3030c16b537SWarner Losh     gzFile gz;
3040c16b537SWarner Losh {
3050c16b537SWarner Losh     z_stream *strm;
3060c16b537SWarner Losh     unsigned char out[BUFLEN];
3070c16b537SWarner Losh 
3080c16b537SWarner Losh     if (gz == NULL)
3090c16b537SWarner Losh         return Z_STREAM_ERROR;
3100c16b537SWarner Losh     strm = &(gz->strm);
3110c16b537SWarner Losh     if (gz->write) {
3120c16b537SWarner Losh         strm->next_in = Z_NULL;
3130c16b537SWarner Losh         strm->avail_in = 0;
3140c16b537SWarner Losh         do {
3150c16b537SWarner Losh             strm->next_out = out;
3160c16b537SWarner Losh             strm->avail_out = BUFLEN;
3170c16b537SWarner Losh             (void)deflate(strm, Z_FINISH);
3180c16b537SWarner Losh             fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
3190c16b537SWarner Losh         } while (strm->avail_out == 0);
3200c16b537SWarner Losh         deflateEnd(strm);
3210c16b537SWarner Losh     }
3220c16b537SWarner Losh     else
3230c16b537SWarner Losh         inflateEnd(strm);
3240c16b537SWarner Losh     fclose(gz->file);
3250c16b537SWarner Losh     free(gz);
3260c16b537SWarner Losh     return Z_OK;
3270c16b537SWarner Losh }
3280c16b537SWarner Losh 
3290c16b537SWarner Losh const char *gzerror OF((gzFile, int *));
3300c16b537SWarner Losh 
gzerror(gz,err)3310c16b537SWarner Losh const char *gzerror(gz, err)
3320c16b537SWarner Losh     gzFile gz;
3330c16b537SWarner Losh     int *err;
3340c16b537SWarner Losh {
3350c16b537SWarner Losh     *err = gz->err;
3360c16b537SWarner Losh     return gz->msg;
3370c16b537SWarner Losh }
3380c16b537SWarner Losh 
3390c16b537SWarner Losh #endif
3400c16b537SWarner Losh 
3410c16b537SWarner Losh char *prog;
3420c16b537SWarner Losh 
3430c16b537SWarner Losh void error            OF((const char *msg));
3440c16b537SWarner Losh void gz_compress      OF((FILE   *in, gzFile out));
3450c16b537SWarner Losh #ifdef USE_MMAP
3460c16b537SWarner Losh int  gz_compress_mmap OF((FILE   *in, gzFile out));
3470c16b537SWarner Losh #endif
3480c16b537SWarner Losh void gz_uncompress    OF((gzFile in, FILE   *out));
3490c16b537SWarner Losh void file_compress    OF((char  *file, char *mode));
3500c16b537SWarner Losh void file_uncompress  OF((char  *file));
3510c16b537SWarner Losh int  main             OF((int argc, char *argv[]));
3520c16b537SWarner Losh 
3530c16b537SWarner Losh /* ===========================================================================
3540c16b537SWarner Losh  * Display error message and exit
3550c16b537SWarner Losh  */
error(msg)3560c16b537SWarner Losh void error(msg)
3570c16b537SWarner Losh     const char *msg;
3580c16b537SWarner Losh {
3590c16b537SWarner Losh     fprintf(stderr, "%s: %s\n", prog, msg);
3600c16b537SWarner Losh     exit(1);
3610c16b537SWarner Losh }
3620c16b537SWarner Losh 
3630c16b537SWarner Losh /* ===========================================================================
3640c16b537SWarner Losh  * Compress input to output then close both files.
3650c16b537SWarner Losh  */
3660c16b537SWarner Losh 
gz_compress(in,out)3670c16b537SWarner Losh void gz_compress(in, out)
3680c16b537SWarner Losh     FILE   *in;
3690c16b537SWarner Losh     gzFile out;
3700c16b537SWarner Losh {
3710c16b537SWarner Losh     local char buf[BUFLEN];
3720c16b537SWarner Losh     int len;
3730c16b537SWarner Losh     int err;
3740c16b537SWarner Losh 
3750c16b537SWarner Losh #ifdef USE_MMAP
3760c16b537SWarner Losh     /* Try first compressing with mmap. If mmap fails (minigzip used in a
3770c16b537SWarner Losh      * pipe), use the normal fread loop.
3780c16b537SWarner Losh      */
3790c16b537SWarner Losh     if (gz_compress_mmap(in, out) == Z_OK) return;
3800c16b537SWarner Losh #endif
3810c16b537SWarner Losh     for (;;) {
3820c16b537SWarner Losh         len = (int)fread(buf, 1, sizeof(buf), in);
3830c16b537SWarner Losh         if (ferror(in)) {
3840c16b537SWarner Losh             perror("fread");
3850c16b537SWarner Losh             exit(1);
3860c16b537SWarner Losh         }
3870c16b537SWarner Losh         if (len == 0) break;
3880c16b537SWarner Losh 
3890c16b537SWarner Losh         if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
3900c16b537SWarner Losh     }
3910c16b537SWarner Losh     fclose(in);
3920c16b537SWarner Losh     if (gzclose(out) != Z_OK) error("failed gzclose");
3930c16b537SWarner Losh }
3940c16b537SWarner Losh 
3950c16b537SWarner Losh #ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
3960c16b537SWarner Losh 
3970c16b537SWarner Losh /* Try compressing the input file at once using mmap. Return Z_OK if
3980c16b537SWarner Losh  * if success, Z_ERRNO otherwise.
3990c16b537SWarner Losh  */
gz_compress_mmap(in,out)4000c16b537SWarner Losh int gz_compress_mmap(in, out)
4010c16b537SWarner Losh     FILE   *in;
4020c16b537SWarner Losh     gzFile out;
4030c16b537SWarner Losh {
4040c16b537SWarner Losh     int len;
4050c16b537SWarner Losh     int err;
4060c16b537SWarner Losh     int ifd = fileno(in);
4070c16b537SWarner Losh     caddr_t buf;    /* mmap'ed buffer for the entire input file */
4080c16b537SWarner Losh     off_t buf_len;  /* length of the input file */
4090c16b537SWarner Losh     struct stat sb;
4100c16b537SWarner Losh 
4110c16b537SWarner Losh     /* Determine the size of the file, needed for mmap: */
4120c16b537SWarner Losh     if (fstat(ifd, &sb) < 0) return Z_ERRNO;
4130c16b537SWarner Losh     buf_len = sb.st_size;
4140c16b537SWarner Losh     if (buf_len <= 0) return Z_ERRNO;
4150c16b537SWarner Losh 
4160c16b537SWarner Losh     /* Now do the actual mmap: */
4170c16b537SWarner Losh     buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
4180c16b537SWarner Losh     if (buf == (caddr_t)(-1)) return Z_ERRNO;
4190c16b537SWarner Losh 
4200c16b537SWarner Losh     /* Compress the whole file at once: */
4210c16b537SWarner Losh     len = gzwrite(out, (char *)buf, (unsigned)buf_len);
4220c16b537SWarner Losh 
4230c16b537SWarner Losh     if (len != (int)buf_len) error(gzerror(out, &err));
4240c16b537SWarner Losh 
4250c16b537SWarner Losh     munmap(buf, buf_len);
4260c16b537SWarner Losh     fclose(in);
4270c16b537SWarner Losh     if (gzclose(out) != Z_OK) error("failed gzclose");
4280c16b537SWarner Losh     return Z_OK;
4290c16b537SWarner Losh }
4300c16b537SWarner Losh #endif /* USE_MMAP */
4310c16b537SWarner Losh 
4320c16b537SWarner Losh /* ===========================================================================
4330c16b537SWarner Losh  * Uncompress input to output then close both files.
4340c16b537SWarner Losh  */
gz_uncompress(in,out)4350c16b537SWarner Losh void gz_uncompress(in, out)
4360c16b537SWarner Losh     gzFile in;
4370c16b537SWarner Losh     FILE   *out;
4380c16b537SWarner Losh {
4390c16b537SWarner Losh     local char buf[BUFLEN];
4400c16b537SWarner Losh     int len;
4410c16b537SWarner Losh     int err;
4420c16b537SWarner Losh 
4430c16b537SWarner Losh     for (;;) {
4440c16b537SWarner Losh         len = gzread(in, buf, sizeof(buf));
4450c16b537SWarner Losh         if (len < 0) error (gzerror(in, &err));
4460c16b537SWarner Losh         if (len == 0) break;
4470c16b537SWarner Losh 
4480c16b537SWarner Losh         if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
4490c16b537SWarner Losh             error("failed fwrite");
4500c16b537SWarner Losh         }
4510c16b537SWarner Losh     }
4520c16b537SWarner Losh     if (fclose(out)) error("failed fclose");
4530c16b537SWarner Losh 
4540c16b537SWarner Losh     if (gzclose(in) != Z_OK) error("failed gzclose");
4550c16b537SWarner Losh }
4560c16b537SWarner Losh 
4570c16b537SWarner Losh 
4580c16b537SWarner Losh /* ===========================================================================
4590c16b537SWarner Losh  * Compress the given file: create a corresponding .gz file and remove the
4600c16b537SWarner Losh  * original.
4610c16b537SWarner Losh  */
file_compress(file,mode)4620c16b537SWarner Losh void file_compress(file, mode)
4630c16b537SWarner Losh     char  *file;
4640c16b537SWarner Losh     char  *mode;
4650c16b537SWarner Losh {
4660c16b537SWarner Losh     local char outfile[MAX_NAME_LEN];
4670c16b537SWarner Losh     FILE  *in;
4680c16b537SWarner Losh     gzFile out;
4690c16b537SWarner Losh 
4700c16b537SWarner Losh     if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
4710c16b537SWarner Losh         fprintf(stderr, "%s: filename too long\n", prog);
4720c16b537SWarner Losh         exit(1);
4730c16b537SWarner Losh     }
4740c16b537SWarner Losh 
4750c16b537SWarner Losh     strcpy(outfile, file);
4760c16b537SWarner Losh     strcat(outfile, GZ_SUFFIX);
4770c16b537SWarner Losh 
4780c16b537SWarner Losh     in = fopen(file, "rb");
4790c16b537SWarner Losh     if (in == NULL) {
4800c16b537SWarner Losh         perror(file);
4810c16b537SWarner Losh         exit(1);
4820c16b537SWarner Losh     }
4830c16b537SWarner Losh     out = gzopen(outfile, mode);
4840c16b537SWarner Losh     if (out == NULL) {
4850c16b537SWarner Losh         fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
4860c16b537SWarner Losh         exit(1);
4870c16b537SWarner Losh     }
4880c16b537SWarner Losh     gz_compress(in, out);
4890c16b537SWarner Losh 
4900c16b537SWarner Losh     unlink(file);
4910c16b537SWarner Losh }
4920c16b537SWarner Losh 
4930c16b537SWarner Losh 
4940c16b537SWarner Losh /* ===========================================================================
4950c16b537SWarner Losh  * Uncompress the given file and remove the original.
4960c16b537SWarner Losh  */
file_uncompress(file)4970c16b537SWarner Losh void file_uncompress(file)
4980c16b537SWarner Losh     char  *file;
4990c16b537SWarner Losh {
5000c16b537SWarner Losh     local char buf[MAX_NAME_LEN];
5010c16b537SWarner Losh     char *infile, *outfile;
5020c16b537SWarner Losh     FILE  *out;
5030c16b537SWarner Losh     gzFile in;
5040c16b537SWarner Losh     size_t len = strlen(file);
5050c16b537SWarner Losh 
5060c16b537SWarner Losh     if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
5070c16b537SWarner Losh         fprintf(stderr, "%s: filename too long\n", prog);
5080c16b537SWarner Losh         exit(1);
5090c16b537SWarner Losh     }
5100c16b537SWarner Losh 
5110c16b537SWarner Losh     strcpy(buf, file);
5120c16b537SWarner Losh 
5130c16b537SWarner Losh     if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
5140c16b537SWarner Losh         infile = file;
5150c16b537SWarner Losh         outfile = buf;
5160c16b537SWarner Losh         outfile[len-3] = '\0';
5170c16b537SWarner Losh     } else {
5180c16b537SWarner Losh         outfile = file;
5190c16b537SWarner Losh         infile = buf;
5200c16b537SWarner Losh         strcat(infile, GZ_SUFFIX);
5210c16b537SWarner Losh     }
5220c16b537SWarner Losh     in = gzopen(infile, "rb");
5230c16b537SWarner Losh     if (in == NULL) {
5240c16b537SWarner Losh         fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
5250c16b537SWarner Losh         exit(1);
5260c16b537SWarner Losh     }
5270c16b537SWarner Losh     out = fopen(outfile, "wb");
5280c16b537SWarner Losh     if (out == NULL) {
5290c16b537SWarner Losh         perror(file);
5300c16b537SWarner Losh         exit(1);
5310c16b537SWarner Losh     }
5320c16b537SWarner Losh 
5330c16b537SWarner Losh     gz_uncompress(in, out);
5340c16b537SWarner Losh 
5350c16b537SWarner Losh     unlink(infile);
5360c16b537SWarner Losh }
5370c16b537SWarner Losh 
5380c16b537SWarner Losh 
5390c16b537SWarner Losh /* ===========================================================================
5400c16b537SWarner Losh  * Usage:  minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
5410c16b537SWarner Losh  *   -c : write to standard output
5420c16b537SWarner Losh  *   -d : decompress
5430c16b537SWarner Losh  *   -f : compress with Z_FILTERED
5440c16b537SWarner Losh  *   -h : compress with Z_HUFFMAN_ONLY
5450c16b537SWarner Losh  *   -r : compress with Z_RLE
5460c16b537SWarner Losh  *   -1 to -9 : compression level
5470c16b537SWarner Losh  */
5480c16b537SWarner Losh 
main(argc,argv)5490c16b537SWarner Losh int main(argc, argv)
5500c16b537SWarner Losh     int argc;
5510c16b537SWarner Losh     char *argv[];
5520c16b537SWarner Losh {
5530c16b537SWarner Losh     int copyout = 0;
5540c16b537SWarner Losh     int uncompr = 0;
5550c16b537SWarner Losh     gzFile file;
5560c16b537SWarner Losh     char *bname, outmode[20];
5570c16b537SWarner Losh 
5580c16b537SWarner Losh     strcpy(outmode, "wb6 ");
5590c16b537SWarner Losh 
5600c16b537SWarner Losh     prog = argv[0];
5610c16b537SWarner Losh     bname = strrchr(argv[0], '/');
5620c16b537SWarner Losh     if (bname)
5630c16b537SWarner Losh       bname++;
5640c16b537SWarner Losh     else
5650c16b537SWarner Losh       bname = argv[0];
5660c16b537SWarner Losh     argc--, argv++;
5670c16b537SWarner Losh 
5680c16b537SWarner Losh     if (!strcmp(bname, "gunzip"))
5690c16b537SWarner Losh       uncompr = 1;
5700c16b537SWarner Losh     else if (!strcmp(bname, "zcat"))
5710c16b537SWarner Losh       copyout = uncompr = 1;
5720c16b537SWarner Losh 
5730c16b537SWarner Losh     while (argc > 0) {
5740c16b537SWarner Losh       if (strcmp(*argv, "-c") == 0)
5750c16b537SWarner Losh         copyout = 1;
5760c16b537SWarner Losh       else if (strcmp(*argv, "-d") == 0)
5770c16b537SWarner Losh         uncompr = 1;
5780c16b537SWarner Losh       else if (strcmp(*argv, "-f") == 0)
5790c16b537SWarner Losh         outmode[3] = 'f';
5800c16b537SWarner Losh       else if (strcmp(*argv, "-h") == 0)
5810c16b537SWarner Losh         outmode[3] = 'h';
5820c16b537SWarner Losh       else if (strcmp(*argv, "-r") == 0)
5830c16b537SWarner Losh         outmode[3] = 'R';
5840c16b537SWarner Losh       else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
5850c16b537SWarner Losh                (*argv)[2] == 0)
5860c16b537SWarner Losh         outmode[2] = (*argv)[1];
5870c16b537SWarner Losh       else
5880c16b537SWarner Losh         break;
5890c16b537SWarner Losh       argc--, argv++;
5900c16b537SWarner Losh     }
5910c16b537SWarner Losh     if (outmode[3] == ' ')
5920c16b537SWarner Losh         outmode[3] = 0;
5930c16b537SWarner Losh     if (argc == 0) {
5940c16b537SWarner Losh         SET_BINARY_MODE(stdin);
5950c16b537SWarner Losh         SET_BINARY_MODE(stdout);
5960c16b537SWarner Losh         if (uncompr) {
5970c16b537SWarner Losh             file = gzdopen(fileno(stdin), "rb");
5980c16b537SWarner Losh             if (file == NULL) error("can't gzdopen stdin");
5990c16b537SWarner Losh             gz_uncompress(file, stdout);
6000c16b537SWarner Losh         } else {
6010c16b537SWarner Losh             file = gzdopen(fileno(stdout), outmode);
6020c16b537SWarner Losh             if (file == NULL) error("can't gzdopen stdout");
6030c16b537SWarner Losh             gz_compress(stdin, file);
6040c16b537SWarner Losh         }
6050c16b537SWarner Losh     } else {
6060c16b537SWarner Losh         if (copyout) {
6070c16b537SWarner Losh             SET_BINARY_MODE(stdout);
6080c16b537SWarner Losh         }
6090c16b537SWarner Losh         do {
6100c16b537SWarner Losh             if (uncompr) {
6110c16b537SWarner Losh                 if (copyout) {
6120c16b537SWarner Losh                     file = gzopen(*argv, "rb");
6130c16b537SWarner Losh                     if (file == NULL)
6140c16b537SWarner Losh                         fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
6150c16b537SWarner Losh                     else
6160c16b537SWarner Losh                         gz_uncompress(file, stdout);
6170c16b537SWarner Losh                 } else {
6180c16b537SWarner Losh                     file_uncompress(*argv);
6190c16b537SWarner Losh                 }
6200c16b537SWarner Losh             } else {
6210c16b537SWarner Losh                 if (copyout) {
6220c16b537SWarner Losh                     FILE * in = fopen(*argv, "rb");
6230c16b537SWarner Losh 
6240c16b537SWarner Losh                     if (in == NULL) {
6250c16b537SWarner Losh                         perror(*argv);
6260c16b537SWarner Losh                     } else {
6270c16b537SWarner Losh                         file = gzdopen(fileno(stdout), outmode);
6280c16b537SWarner Losh                         if (file == NULL) error("can't gzdopen stdout");
6290c16b537SWarner Losh 
6300c16b537SWarner Losh                         gz_compress(in, file);
6310c16b537SWarner Losh                     }
6320c16b537SWarner Losh 
6330c16b537SWarner Losh                 } else {
6340c16b537SWarner Losh                     file_compress(*argv, outmode);
6350c16b537SWarner Losh                 }
6360c16b537SWarner Losh             }
6370c16b537SWarner Losh         } while (argv++, --argc);
6380c16b537SWarner Losh     }
6390c16b537SWarner Losh     return 0;
6400c16b537SWarner Losh }
641