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