Path: blob/main/sys/contrib/zstd/zlibWrapper/examples/minigzip.c
48375 views
/* minigzip.c contains minimal changes required to be compiled with zlibWrapper:1* - #include "zlib.h" was changed to #include "zstd_zlibwrapper.h" */23/* minigzip.c -- simulate gzip using the zlib compression library4* Copyright (C) 1995-2006, 2010, 2011 Jean-loup Gailly.5* For conditions of distribution and use, see http://www.zlib.net/zlib_license.html6*/78/*9* minigzip is a minimal implementation of the gzip utility. This is10* only an example of using zlib and isn't meant to replace the11* full-featured gzip. No attempt is made to deal with file systems12* limiting names to 14 or 8+3 characters, etc... Error checking is13* very limited. So use minigzip only for testing; use gzip for the14* real thing. On MSDOS, use only on file names without extension15* or in pipe mode.16*/1718/* @(#) $Id$ */1920#define _POSIX_SOURCE /* fileno */2122#include "zstd_zlibwrapper.h"23#include <stdio.h>2425#ifdef STDC26# include <string.h>27# include <stdlib.h>28#endif2930#ifdef USE_MMAP31# include <sys/types.h>32# include <sys/mman.h>33# include <sys/stat.h>34#endif3536#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)37# include <fcntl.h>38# include <io.h>39# ifdef UNDER_CE40# include <stdlib.h>41# endif42# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)43#else44# define SET_BINARY_MODE(file)45#endif4647#ifdef _MSC_VER48# define snprintf _snprintf49#endif5051#ifdef VMS52# define unlink delete53# define GZ_SUFFIX "-gz"54#endif55#ifdef RISCOS56# define unlink remove57# define GZ_SUFFIX "-gz"58# define fileno(file) file->__file59#endif60#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os61# include <unix.h> /* for fileno */62#endif6364#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)65#ifndef WIN32 /* unlink already in stdio.h for WIN32 */66extern int unlink OF((const char *));67#endif68#endif6970#if defined(UNDER_CE)71# include <windows.h>72# define perror(s) pwinerror(s)7374/* Map the Windows error number in ERROR to a locale-dependent error75message string and return a pointer to it. Typically, the values76for ERROR come from GetLastError.7778The string pointed to shall not be modified by the application,79but may be overwritten by a subsequent call to strwinerror8081The strwinerror function does not change the current setting82of GetLastError. */8384static char *strwinerror (error)85DWORD error;86{87static char buf[1024];8889wchar_t *msgbuf;90DWORD lasterr = GetLastError();91DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM92| FORMAT_MESSAGE_ALLOCATE_BUFFER,93NULL,94error,950, /* Default language */96(LPVOID)&msgbuf,970,98NULL);99if (chars != 0) {100/* If there is an \r\n appended, zap it. */101if (chars >= 2102&& msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {103chars -= 2;104msgbuf[chars] = 0;105}106107if (chars > sizeof (buf) - 1) {108chars = sizeof (buf) - 1;109msgbuf[chars] = 0;110}111112wcstombs(buf, msgbuf, chars + 1);113LocalFree(msgbuf);114}115else {116sprintf(buf, "unknown win32 error (%ld)", error);117}118119SetLastError(lasterr);120return buf;121}122123static void pwinerror (s)124const char *s;125{126if (s && *s)127fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));128else129fprintf(stderr, "%s\n", strwinerror(GetLastError ()));130}131132#endif /* UNDER_CE */133134#ifndef GZ_SUFFIX135# define GZ_SUFFIX ".gz"136#endif137#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)138139#define BUFLEN 16384140#define MAX_NAME_LEN 1024141142#ifdef MAXSEG_64K143# define local static144/* Needed for systems with limitation on stack size. */145#else146# define local147#endif148149#ifdef Z_SOLO150/* for Z_SOLO, create simplified gz* functions using deflate and inflate */151152#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)153# include <unistd.h> /* for unlink() */154#endif155156void *myalloc OF((void *, unsigned, unsigned));157void myfree OF((void *, void *));158159void *myalloc(q, n, m)160void *q;161unsigned n, m;162{163q = Z_NULL;164return calloc(n, m);165}166167void myfree(q, p)168void *q, *p;169{170q = Z_NULL;171free(p);172}173174typedef struct gzFile_s {175FILE *file;176int write;177int err;178char *msg;179z_stream strm;180} *gzFile;181182gzFile gzopen OF((const char *, const char *));183gzFile gzdopen OF((int, const char *));184gzFile gz_open OF((const char *, int, const char *));185186gzFile gzopen(path, mode)187const char *path;188const char *mode;189{190return gz_open(path, -1, mode);191}192193gzFile gzdopen(fd, mode)194int fd;195const char *mode;196{197return gz_open(NULL, fd, mode);198}199200gzFile gz_open(path, fd, mode)201const char *path;202int fd;203const char *mode;204{205gzFile gz;206int ret;207208gz = malloc(sizeof(struct gzFile_s));209if (gz == NULL)210return NULL;211gz->write = strchr(mode, 'w') != NULL;212gz->strm.zalloc = myalloc;213gz->strm.zfree = myfree;214gz->strm.opaque = Z_NULL;215if (gz->write)216ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0);217else {218gz->strm.next_in = 0;219gz->strm.avail_in = Z_NULL;220ret = inflateInit2(&(gz->strm), 15 + 16);221}222if (ret != Z_OK) {223free(gz);224return NULL;225}226gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") :227fopen(path, gz->write ? "wb" : "rb");228if (gz->file == NULL) {229gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm));230free(gz);231return NULL;232}233gz->err = 0;234gz->msg = "";235return gz;236}237238int gzwrite OF((gzFile, const void *, unsigned));239240int gzwrite(gz, buf, len)241gzFile gz;242const void *buf;243unsigned len;244{245z_stream *strm;246unsigned char out[BUFLEN];247248if (gz == NULL || !gz->write)249return 0;250strm = &(gz->strm);251strm->next_in = (void *)buf;252strm->avail_in = len;253do {254strm->next_out = out;255strm->avail_out = BUFLEN;256(void)deflate(strm, Z_NO_FLUSH);257fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);258} while (strm->avail_out == 0);259return len;260}261262int gzread OF((gzFile, void *, unsigned));263264int gzread(gz, buf, len)265gzFile gz;266void *buf;267unsigned len;268{269int ret;270unsigned got;271unsigned char in[1];272z_stream *strm;273274if (gz == NULL || gz->write)275return 0;276if (gz->err)277return 0;278strm = &(gz->strm);279strm->next_out = (void *)buf;280strm->avail_out = len;281do {282got = fread(in, 1, 1, gz->file);283if (got == 0)284break;285strm->next_in = in;286strm->avail_in = 1;287ret = inflate(strm, Z_NO_FLUSH);288if (ret == Z_DATA_ERROR) {289gz->err = Z_DATA_ERROR;290gz->msg = strm->msg;291return 0;292}293if (ret == Z_STREAM_END)294inflateReset(strm);295} while (strm->avail_out);296return len - strm->avail_out;297}298299int gzclose OF((gzFile));300301int gzclose(gz)302gzFile gz;303{304z_stream *strm;305unsigned char out[BUFLEN];306307if (gz == NULL)308return Z_STREAM_ERROR;309strm = &(gz->strm);310if (gz->write) {311strm->next_in = Z_NULL;312strm->avail_in = 0;313do {314strm->next_out = out;315strm->avail_out = BUFLEN;316(void)deflate(strm, Z_FINISH);317fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);318} while (strm->avail_out == 0);319deflateEnd(strm);320}321else322inflateEnd(strm);323fclose(gz->file);324free(gz);325return Z_OK;326}327328const char *gzerror OF((gzFile, int *));329330const char *gzerror(gz, err)331gzFile gz;332int *err;333{334*err = gz->err;335return gz->msg;336}337338#endif339340char *prog;341342void error OF((const char *msg));343void gz_compress OF((FILE *in, gzFile out));344#ifdef USE_MMAP345int gz_compress_mmap OF((FILE *in, gzFile out));346#endif347void gz_uncompress OF((gzFile in, FILE *out));348void file_compress OF((char *file, char *mode));349void file_uncompress OF((char *file));350int main OF((int argc, char *argv[]));351352/* ===========================================================================353* Display error message and exit354*/355void error(msg)356const char *msg;357{358fprintf(stderr, "%s: %s\n", prog, msg);359exit(1);360}361362/* ===========================================================================363* Compress input to output then close both files.364*/365366void gz_compress(in, out)367FILE *in;368gzFile out;369{370local char buf[BUFLEN];371int len;372int err;373374#ifdef USE_MMAP375/* Try first compressing with mmap. If mmap fails (minigzip used in a376* pipe), use the normal fread loop.377*/378if (gz_compress_mmap(in, out) == Z_OK) return;379#endif380for (;;) {381len = (int)fread(buf, 1, sizeof(buf), in);382if (ferror(in)) {383perror("fread");384exit(1);385}386if (len == 0) break;387388if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));389}390fclose(in);391if (gzclose(out) != Z_OK) error("failed gzclose");392}393394#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <[email protected]> */395396/* Try compressing the input file at once using mmap. Return Z_OK if397* if success, Z_ERRNO otherwise.398*/399int gz_compress_mmap(in, out)400FILE *in;401gzFile out;402{403int len;404int err;405int ifd = fileno(in);406caddr_t buf; /* mmap'ed buffer for the entire input file */407off_t buf_len; /* length of the input file */408struct stat sb;409410/* Determine the size of the file, needed for mmap: */411if (fstat(ifd, &sb) < 0) return Z_ERRNO;412buf_len = sb.st_size;413if (buf_len <= 0) return Z_ERRNO;414415/* Now do the actual mmap: */416buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);417if (buf == (caddr_t)(-1)) return Z_ERRNO;418419/* Compress the whole file at once: */420len = gzwrite(out, (char *)buf, (unsigned)buf_len);421422if (len != (int)buf_len) error(gzerror(out, &err));423424munmap(buf, buf_len);425fclose(in);426if (gzclose(out) != Z_OK) error("failed gzclose");427return Z_OK;428}429#endif /* USE_MMAP */430431/* ===========================================================================432* Uncompress input to output then close both files.433*/434void gz_uncompress(in, out)435gzFile in;436FILE *out;437{438local char buf[BUFLEN];439int len;440int err;441442for (;;) {443len = gzread(in, buf, sizeof(buf));444if (len < 0) error (gzerror(in, &err));445if (len == 0) break;446447if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {448error("failed fwrite");449}450}451if (fclose(out)) error("failed fclose");452453if (gzclose(in) != Z_OK) error("failed gzclose");454}455456457/* ===========================================================================458* Compress the given file: create a corresponding .gz file and remove the459* original.460*/461void file_compress(file, mode)462char *file;463char *mode;464{465local char outfile[MAX_NAME_LEN];466FILE *in;467gzFile out;468469if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {470fprintf(stderr, "%s: filename too long\n", prog);471exit(1);472}473474strcpy(outfile, file);475strcat(outfile, GZ_SUFFIX);476477in = fopen(file, "rb");478if (in == NULL) {479perror(file);480exit(1);481}482out = gzopen(outfile, mode);483if (out == NULL) {484fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);485exit(1);486}487gz_compress(in, out);488489unlink(file);490}491492493/* ===========================================================================494* Uncompress the given file and remove the original.495*/496void file_uncompress(file)497char *file;498{499local char buf[MAX_NAME_LEN];500char *infile, *outfile;501FILE *out;502gzFile in;503size_t len = strlen(file);504505if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {506fprintf(stderr, "%s: filename too long\n", prog);507exit(1);508}509510strcpy(buf, file);511512if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {513infile = file;514outfile = buf;515outfile[len-3] = '\0';516} else {517outfile = file;518infile = buf;519strcat(infile, GZ_SUFFIX);520}521in = gzopen(infile, "rb");522if (in == NULL) {523fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);524exit(1);525}526out = fopen(outfile, "wb");527if (out == NULL) {528perror(file);529exit(1);530}531532gz_uncompress(in, out);533534unlink(infile);535}536537538/* ===========================================================================539* Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]540* -c : write to standard output541* -d : decompress542* -f : compress with Z_FILTERED543* -h : compress with Z_HUFFMAN_ONLY544* -r : compress with Z_RLE545* -1 to -9 : compression level546*/547548int main(argc, argv)549int argc;550char *argv[];551{552int copyout = 0;553int uncompr = 0;554gzFile file;555char *bname, outmode[20];556557strcpy(outmode, "wb6 ");558559prog = argv[0];560bname = strrchr(argv[0], '/');561if (bname)562bname++;563else564bname = argv[0];565argc--, argv++;566567if (!strcmp(bname, "gunzip"))568uncompr = 1;569else if (!strcmp(bname, "zcat"))570copyout = uncompr = 1;571572while (argc > 0) {573if (strcmp(*argv, "-c") == 0)574copyout = 1;575else if (strcmp(*argv, "-d") == 0)576uncompr = 1;577else if (strcmp(*argv, "-f") == 0)578outmode[3] = 'f';579else if (strcmp(*argv, "-h") == 0)580outmode[3] = 'h';581else if (strcmp(*argv, "-r") == 0)582outmode[3] = 'R';583else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&584(*argv)[2] == 0)585outmode[2] = (*argv)[1];586else587break;588argc--, argv++;589}590if (outmode[3] == ' ')591outmode[3] = 0;592if (argc == 0) {593SET_BINARY_MODE(stdin);594SET_BINARY_MODE(stdout);595if (uncompr) {596file = gzdopen(fileno(stdin), "rb");597if (file == NULL) error("can't gzdopen stdin");598gz_uncompress(file, stdout);599} else {600file = gzdopen(fileno(stdout), outmode);601if (file == NULL) error("can't gzdopen stdout");602gz_compress(stdin, file);603}604} else {605if (copyout) {606SET_BINARY_MODE(stdout);607}608do {609if (uncompr) {610if (copyout) {611file = gzopen(*argv, "rb");612if (file == NULL)613fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);614else615gz_uncompress(file, stdout);616} else {617file_uncompress(*argv);618}619} else {620if (copyout) {621FILE * in = fopen(*argv, "rb");622623if (in == NULL) {624perror(*argv);625} else {626file = gzdopen(fileno(stdout), outmode);627if (file == NULL) error("can't gzdopen stdout");628629gz_compress(in, file);630}631632} else {633file_compress(*argv, outmode);634}635}636} while (argv++, --argc);637}638return 0;639}640641642