199767f8919635c4928607450d9e0abb932109ceToomas Soome/* minigzip.c -- simulate gzip using the zlib compression library
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (C) 1995-2006, 2010, 2011 Jean-loup Gailly.
199767f8919635c4928607450d9e0abb932109ceToomas Soome * For conditions of distribution and use, see copyright notice in zlib.h
199767f8919635c4928607450d9e0abb932109ceToomas Soome * minigzip is a minimal implementation of the gzip utility. This is
199767f8919635c4928607450d9e0abb932109ceToomas Soome * only an example of using zlib and isn't meant to replace the
199767f8919635c4928607450d9e0abb932109ceToomas Soome * full-featured gzip. No attempt is made to deal with file systems
199767f8919635c4928607450d9e0abb932109ceToomas Soome * limiting names to 14 or 8+3 characters, etc... Error checking is
199767f8919635c4928607450d9e0abb932109ceToomas Soome * very limited. So use minigzip only for testing; use gzip for the
199767f8919635c4928607450d9e0abb932109ceToomas Soome * real thing. On MSDOS, use only on file names without extension
199767f8919635c4928607450d9e0abb932109ceToomas Soome * or in pipe mode.
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* @(#) $Id$ */
199767f8919635c4928607450d9e0abb932109ceToomas Soome#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
199767f8919635c4928607450d9e0abb932109ceToomas Soome# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
199767f8919635c4928607450d9e0abb932109ceToomas Soome#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
199767f8919635c4928607450d9e0abb932109ceToomas Soome#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* Map the Windows error number in ERROR to a locale-dependent error
199767f8919635c4928607450d9e0abb932109ceToomas Soome message string and return a pointer to it. Typically, the values
199767f8919635c4928607450d9e0abb932109ceToomas Soome for ERROR come from GetLastError.
199767f8919635c4928607450d9e0abb932109ceToomas Soome The string pointed to shall not be modified by the application,
199767f8919635c4928607450d9e0abb932109ceToomas Soome but may be overwritten by a subsequent call to strwinerror
199767f8919635c4928607450d9e0abb932109ceToomas Soome The strwinerror function does not change the current setting
199767f8919635c4928607450d9e0abb932109ceToomas Soome of GetLastError. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
199767f8919635c4928607450d9e0abb932109ceToomas Soome 0, /* Default language */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* If there is an \r\n appended, zap it. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
199767f8919635c4928607450d9e0abb932109ceToomas Soome sprintf(buf, "unknown win32 error (%ld)", error);
199767f8919635c4928607450d9e0abb932109ceToomas Soome const char *s;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (s && *s)
199767f8919635c4928607450d9e0abb932109ceToomas Soome fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));
199767f8919635c4928607450d9e0abb932109ceToomas Soome fprintf(stderr, "%s\n", strwinerror(GetLastError ()));
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif /* UNDER_CE */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Needed for systems with limitation on stack size. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* for Z_SOLO, create simplified gz* functions using deflate and inflate */
199767f8919635c4928607450d9e0abb932109ceToomas Soome#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
199767f8919635c4928607450d9e0abb932109ceToomas Soome unsigned n, m;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return calloc(n, m);
199767f8919635c4928607450d9e0abb932109ceToomas Soome void *q, *p;
199767f8919635c4928607450d9e0abb932109ceToomas SoomegzFile gz_open OF((const char *, int, const char *));
199767f8919635c4928607450d9e0abb932109ceToomas Soome const char *path;
199767f8919635c4928607450d9e0abb932109ceToomas Soome const char *mode;
199767f8919635c4928607450d9e0abb932109ceToomas Soome ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") :
199767f8919635c4928607450d9e0abb932109ceToomas Soome gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm));
199767f8919635c4928607450d9e0abb932109ceToomas Soomeint gzwrite OF((gzFile, const void *, unsigned));
199767f8919635c4928607450d9e0abb932109ceToomas Soome const void *buf;
199767f8919635c4928607450d9e0abb932109ceToomas Soome fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
199767f8919635c4928607450d9e0abb932109ceToomas Soome fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
199767f8919635c4928607450d9e0abb932109ceToomas Soomeint gz_compress_mmap OF((FILE *in, gzFile out));
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid file_compress OF((char *file, char *mode));
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* ===========================================================================
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Display error message and exit
199767f8919635c4928607450d9e0abb932109ceToomas Soome const char *msg;
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* ===========================================================================
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Compress input to output then close both files.
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Try first compressing with mmap. If mmap fails (minigzip used in a
199767f8919635c4928607450d9e0abb932109ceToomas Soome * pipe), use the normal fread loop.
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (len == 0) break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (gzclose(out) != Z_OK) error("failed gzclose");
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* Try compressing the input file at once using mmap. Return Z_OK if
199767f8919635c4928607450d9e0abb932109ceToomas Soome * if success, Z_ERRNO otherwise.
199767f8919635c4928607450d9e0abb932109ceToomas Soome caddr_t buf; /* mmap'ed buffer for the entire input file */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Determine the size of the file, needed for mmap: */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Now do the actual mmap: */
199767f8919635c4928607450d9e0abb932109ceToomas Soome buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Compress the whole file at once: */
199767f8919635c4928607450d9e0abb932109ceToomas Soome len = gzwrite(out, (char *)buf, (unsigned)buf_len);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (len != (int)buf_len) error(gzerror(out, &err));
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (gzclose(out) != Z_OK) error("failed gzclose");
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif /* USE_MMAP */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* ===========================================================================
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Uncompress input to output then close both files.
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (len == 0) break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (gzclose(in) != Z_OK) error("failed gzclose");
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* ===========================================================================
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Compress the given file: create a corresponding .gz file and remove the
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome fprintf(stderr, "%s: filename too long\n", prog);
199767f8919635c4928607450d9e0abb932109ceToomas Soome#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
199767f8919635c4928607450d9e0abb932109ceToomas Soome snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX);
199767f8919635c4928607450d9e0abb932109ceToomas Soome fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* ===========================================================================
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Uncompress the given file and remove the original.
199767f8919635c4928607450d9e0abb932109ceToomas Soome fprintf(stderr, "%s: filename too long\n", prog);
199767f8919635c4928607450d9e0abb932109ceToomas Soome#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
199767f8919635c4928607450d9e0abb932109ceToomas Soome snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX);
199767f8919635c4928607450d9e0abb932109ceToomas Soome fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* ===========================================================================
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
199767f8919635c4928607450d9e0abb932109ceToomas Soome * -c : write to standard output
199767f8919635c4928607450d9e0abb932109ceToomas Soome * -d : decompress
199767f8919635c4928607450d9e0abb932109ceToomas Soome * -f : compress with Z_FILTERED
199767f8919635c4928607450d9e0abb932109ceToomas Soome * -h : compress with Z_HUFFMAN_ONLY
199767f8919635c4928607450d9e0abb932109ceToomas Soome * -r : compress with Z_RLE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * -1 to -9 : compression level
199767f8919635c4928607450d9e0abb932109ceToomas Soome#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
199767f8919635c4928607450d9e0abb932109ceToomas Soome snprintf(outmode, sizeof(outmode), "%s", "wb6 ");
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (argc > 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (file == NULL) error("can't gzdopen stdin");
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (file == NULL) error("can't gzdopen stdout");
199767f8919635c4928607450d9e0abb932109ceToomas Soome fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (file == NULL) error("can't gzdopen stdout");