Blame nss/lib/zlib/minigzip.c

Packit 40b132
/* minigzip.c -- simulate gzip using the zlib compression library
Packit 40b132
 * Copyright (C) 1995-2006, 2010 Jean-loup Gailly.
Packit 40b132
 * For conditions of distribution and use, see copyright notice in zlib.h
Packit 40b132
 */
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * minigzip is a minimal implementation of the gzip utility. This is
Packit 40b132
 * only an example of using zlib and isn't meant to replace the
Packit 40b132
 * full-featured gzip. No attempt is made to deal with file systems
Packit 40b132
 * limiting names to 14 or 8+3 characters, etc... Error checking is
Packit 40b132
 * very limited. So use minigzip only for testing; use gzip for the
Packit 40b132
 * real thing. On MSDOS, use only on file names without extension
Packit 40b132
 * or in pipe mode.
Packit 40b132
 */
Packit 40b132
Packit 40b132
/* @(#) $Id$ */
Packit 40b132
Packit 40b132
#include "zlib.h"
Packit 40b132
#include <stdio.h>
Packit 40b132
Packit 40b132
#ifdef STDC
Packit 40b132
#  include <string.h>
Packit 40b132
#  include <stdlib.h>
Packit 40b132
#endif
Packit 40b132
Packit 40b132
#ifdef USE_MMAP
Packit 40b132
#  include <sys/types.h>
Packit 40b132
#  include <sys/mman.h>
Packit 40b132
#  include <sys/stat.h>
Packit 40b132
#endif
Packit 40b132
Packit 40b132
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
Packit 40b132
#  include <fcntl.h>
Packit 40b132
#  include <io.h>
Packit 40b132
#  ifdef UNDER_CE
Packit 40b132
#    include <stdlib.h>
Packit 40b132
#  endif
Packit 40b132
#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
Packit 40b132
#else
Packit 40b132
#  define SET_BINARY_MODE(file)
Packit 40b132
#endif
Packit 40b132
Packit 40b132
#ifdef VMS
Packit 40b132
#  define unlink delete
Packit 40b132
#  define GZ_SUFFIX "-gz"
Packit 40b132
#endif
Packit 40b132
#ifdef RISCOS
Packit 40b132
#  define unlink remove
Packit 40b132
#  define GZ_SUFFIX "-gz"
Packit 40b132
#  define fileno(file) file->__file
Packit 40b132
#endif
Packit 40b132
#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
Packit 40b132
#  include <unix.h> /* for fileno */
Packit 40b132
#endif
Packit 40b132
Packit 40b132
#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
Packit 40b132
#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
Packit 40b132
  extern int unlink OF((const char *));
Packit 40b132
#endif
Packit 40b132
#endif
Packit 40b132
Packit 40b132
#if defined(UNDER_CE)
Packit 40b132
#  include <windows.h>
Packit 40b132
#  define perror(s) pwinerror(s)
Packit 40b132
Packit 40b132
/* Map the Windows error number in ERROR to a locale-dependent error
Packit 40b132
   message string and return a pointer to it.  Typically, the values
Packit 40b132
   for ERROR come from GetLastError.
Packit 40b132
Packit 40b132
   The string pointed to shall not be modified by the application,
Packit 40b132
   but may be overwritten by a subsequent call to strwinerror
Packit 40b132
Packit 40b132
   The strwinerror function does not change the current setting
Packit 40b132
   of GetLastError.  */
Packit 40b132
Packit 40b132
static char *strwinerror (error)
Packit 40b132
     DWORD error;
Packit 40b132
{
Packit 40b132
    static char buf[1024];
Packit 40b132
Packit 40b132
    wchar_t *msgbuf;
Packit 40b132
    DWORD lasterr = GetLastError();
Packit 40b132
    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
Packit 40b132
        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
Packit 40b132
        NULL,
Packit 40b132
        error,
Packit 40b132
        0, /* Default language */
Packit 40b132
        (LPVOID)&msgbuf,
Packit 40b132
        0,
Packit 40b132
        NULL);
Packit 40b132
    if (chars != 0) {
Packit 40b132
        /* If there is an \r\n appended, zap it.  */
Packit 40b132
        if (chars >= 2
Packit 40b132
            && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
Packit 40b132
            chars -= 2;
Packit 40b132
            msgbuf[chars] = 0;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        if (chars > sizeof (buf) - 1) {
Packit 40b132
            chars = sizeof (buf) - 1;
Packit 40b132
            msgbuf[chars] = 0;
Packit 40b132
        }
Packit 40b132
Packit 40b132
        wcstombs(buf, msgbuf, chars + 1);
Packit 40b132
        LocalFree(msgbuf);
Packit 40b132
    }
Packit 40b132
    else {
Packit 40b132
        sprintf(buf, "unknown win32 error (%ld)", error);
Packit 40b132
    }
Packit 40b132
Packit 40b132
    SetLastError(lasterr);
Packit 40b132
    return buf;
Packit 40b132
}
Packit 40b132
Packit 40b132
static void pwinerror (s)
Packit 40b132
    const char *s;
Packit 40b132
{
Packit 40b132
    if (s && *s)
Packit 40b132
        fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));
Packit 40b132
    else
Packit 40b132
        fprintf(stderr, "%s\n", strwinerror(GetLastError ()));
Packit 40b132
}
Packit 40b132
Packit 40b132
#endif /* UNDER_CE */
Packit 40b132
Packit 40b132
#ifndef GZ_SUFFIX
Packit 40b132
#  define GZ_SUFFIX ".gz"
Packit 40b132
#endif
Packit 40b132
#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
Packit 40b132
Packit 40b132
#define BUFLEN      16384
Packit 40b132
#define MAX_NAME_LEN 1024
Packit 40b132
Packit 40b132
#ifdef MAXSEG_64K
Packit 40b132
#  define local static
Packit 40b132
   /* Needed for systems with limitation on stack size. */
Packit 40b132
#else
Packit 40b132
#  define local
Packit 40b132
#endif
Packit 40b132
Packit 40b132
char *prog;
Packit 40b132
Packit 40b132
void error            OF((const char *msg));
Packit 40b132
void gz_compress      OF((FILE   *in, gzFile out));
Packit 40b132
#ifdef USE_MMAP
Packit 40b132
int  gz_compress_mmap OF((FILE   *in, gzFile out));
Packit 40b132
#endif
Packit 40b132
void gz_uncompress    OF((gzFile in, FILE   *out));
Packit 40b132
void file_compress    OF((char  *file, char *mode));
Packit 40b132
void file_uncompress  OF((char  *file));
Packit 40b132
int  main             OF((int argc, char *argv[]));
Packit 40b132
Packit 40b132
/* ===========================================================================
Packit 40b132
 * Display error message and exit
Packit 40b132
 */
Packit 40b132
void error(msg)
Packit 40b132
    const char *msg;
Packit 40b132
{
Packit 40b132
    fprintf(stderr, "%s: %s\n", prog, msg);
Packit 40b132
    exit(1);
Packit 40b132
}
Packit 40b132
Packit 40b132
/* ===========================================================================
Packit 40b132
 * Compress input to output then close both files.
Packit 40b132
 */
Packit 40b132
Packit 40b132
void gz_compress(in, out)
Packit 40b132
    FILE   *in;
Packit 40b132
    gzFile out;
Packit 40b132
{
Packit 40b132
    local char buf[BUFLEN];
Packit 40b132
    int len;
Packit 40b132
    int err;
Packit 40b132
Packit 40b132
#ifdef USE_MMAP
Packit 40b132
    /* Try first compressing with mmap. If mmap fails (minigzip used in a
Packit 40b132
     * pipe), use the normal fread loop.
Packit 40b132
     */
Packit 40b132
    if (gz_compress_mmap(in, out) == Z_OK) return;
Packit 40b132
#endif
Packit 40b132
    for (;;) {
Packit 40b132
        len = (int)fread(buf, 1, sizeof(buf), in);
Packit 40b132
        if (ferror(in)) {
Packit 40b132
            perror("fread");
Packit 40b132
            exit(1);
Packit 40b132
        }
Packit 40b132
        if (len == 0) break;
Packit 40b132
Packit 40b132
        if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
Packit 40b132
    }
Packit 40b132
    fclose(in);
Packit 40b132
    if (gzclose(out) != Z_OK) error("failed gzclose");
Packit 40b132
}
Packit 40b132
Packit 40b132
#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
Packit 40b132
Packit 40b132
/* Try compressing the input file at once using mmap. Return Z_OK if
Packit 40b132
 * if success, Z_ERRNO otherwise.
Packit 40b132
 */
Packit 40b132
int gz_compress_mmap(in, out)
Packit 40b132
    FILE   *in;
Packit 40b132
    gzFile out;
Packit 40b132
{
Packit 40b132
    int len;
Packit 40b132
    int err;
Packit 40b132
    int ifd = fileno(in);
Packit 40b132
    caddr_t buf;    /* mmap'ed buffer for the entire input file */
Packit 40b132
    off_t buf_len;  /* length of the input file */
Packit 40b132
    struct stat sb;
Packit 40b132
Packit 40b132
    /* Determine the size of the file, needed for mmap: */
Packit 40b132
    if (fstat(ifd, &sb) < 0) return Z_ERRNO;
Packit 40b132
    buf_len = sb.st_size;
Packit 40b132
    if (buf_len <= 0) return Z_ERRNO;
Packit 40b132
Packit 40b132
    /* Now do the actual mmap: */
Packit 40b132
    buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
Packit 40b132
    if (buf == (caddr_t)(-1)) return Z_ERRNO;
Packit 40b132
Packit 40b132
    /* Compress the whole file at once: */
Packit 40b132
    len = gzwrite(out, (char *)buf, (unsigned)buf_len);
Packit 40b132
Packit 40b132
    if (len != (int)buf_len) error(gzerror(out, &err));
Packit 40b132
Packit 40b132
    munmap(buf, buf_len);
Packit 40b132
    fclose(in);
Packit 40b132
    if (gzclose(out) != Z_OK) error("failed gzclose");
Packit 40b132
    return Z_OK;
Packit 40b132
}
Packit 40b132
#endif /* USE_MMAP */
Packit 40b132
Packit 40b132
/* ===========================================================================
Packit 40b132
 * Uncompress input to output then close both files.
Packit 40b132
 */
Packit 40b132
void gz_uncompress(in, out)
Packit 40b132
    gzFile in;
Packit 40b132
    FILE   *out;
Packit 40b132
{
Packit 40b132
    local char buf[BUFLEN];
Packit 40b132
    int len;
Packit 40b132
    int err;
Packit 40b132
Packit 40b132
    for (;;) {
Packit 40b132
        len = gzread(in, buf, sizeof(buf));
Packit 40b132
        if (len < 0) error (gzerror(in, &err));
Packit 40b132
        if (len == 0) break;
Packit 40b132
Packit 40b132
        if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
Packit 40b132
            error("failed fwrite");
Packit 40b132
        }
Packit 40b132
    }
Packit 40b132
    if (fclose(out)) error("failed fclose");
Packit 40b132
Packit 40b132
    if (gzclose(in) != Z_OK) error("failed gzclose");
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
/* ===========================================================================
Packit 40b132
 * Compress the given file: create a corresponding .gz file and remove the
Packit 40b132
 * original.
Packit 40b132
 */
Packit 40b132
void file_compress(file, mode)
Packit 40b132
    char  *file;
Packit 40b132
    char  *mode;
Packit 40b132
{
Packit 40b132
    local char outfile[MAX_NAME_LEN];
Packit 40b132
    FILE  *in;
Packit 40b132
    gzFile out;
Packit 40b132
Packit 40b132
    if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
Packit 40b132
        fprintf(stderr, "%s: filename too long\n", prog);
Packit 40b132
        exit(1);
Packit 40b132
    }
Packit 40b132
Packit 40b132
    strcpy(outfile, file);
Packit 40b132
    strcat(outfile, GZ_SUFFIX);
Packit 40b132
Packit 40b132
    in = fopen(file, "rb");
Packit 40b132
    if (in == NULL) {
Packit 40b132
        perror(file);
Packit 40b132
        exit(1);
Packit 40b132
    }
Packit 40b132
    out = gzopen(outfile, mode);
Packit 40b132
    if (out == NULL) {
Packit 40b132
        fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
Packit 40b132
        exit(1);
Packit 40b132
    }
Packit 40b132
    gz_compress(in, out);
Packit 40b132
Packit 40b132
    unlink(file);
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
/* ===========================================================================
Packit 40b132
 * Uncompress the given file and remove the original.
Packit 40b132
 */
Packit 40b132
void file_uncompress(file)
Packit 40b132
    char  *file;
Packit 40b132
{
Packit 40b132
    local char buf[MAX_NAME_LEN];
Packit 40b132
    char *infile, *outfile;
Packit 40b132
    FILE  *out;
Packit 40b132
    gzFile in;
Packit 40b132
    size_t len = strlen(file);
Packit 40b132
Packit 40b132
    if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
Packit 40b132
        fprintf(stderr, "%s: filename too long\n", prog);
Packit 40b132
        exit(1);
Packit 40b132
    }
Packit 40b132
Packit 40b132
    strcpy(buf, file);
Packit 40b132
Packit 40b132
    if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
Packit 40b132
        infile = file;
Packit 40b132
        outfile = buf;
Packit 40b132
        outfile[len-3] = '\0';
Packit 40b132
    } else {
Packit 40b132
        outfile = file;
Packit 40b132
        infile = buf;
Packit 40b132
        strcat(infile, GZ_SUFFIX);
Packit 40b132
    }
Packit 40b132
    in = gzopen(infile, "rb");
Packit 40b132
    if (in == NULL) {
Packit 40b132
        fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
Packit 40b132
        exit(1);
Packit 40b132
    }
Packit 40b132
    out = fopen(outfile, "wb");
Packit 40b132
    if (out == NULL) {
Packit 40b132
        perror(file);
Packit 40b132
        exit(1);
Packit 40b132
    }
Packit 40b132
Packit 40b132
    gz_uncompress(in, out);
Packit 40b132
Packit 40b132
    unlink(infile);
Packit 40b132
}
Packit 40b132
Packit 40b132
Packit 40b132
/* ===========================================================================
Packit 40b132
 * Usage:  minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
Packit 40b132
 *   -c : write to standard output
Packit 40b132
 *   -d : decompress
Packit 40b132
 *   -f : compress with Z_FILTERED
Packit 40b132
 *   -h : compress with Z_HUFFMAN_ONLY
Packit 40b132
 *   -r : compress with Z_RLE
Packit 40b132
 *   -1 to -9 : compression level
Packit 40b132
 */
Packit 40b132
Packit 40b132
int main(argc, argv)
Packit 40b132
    int argc;
Packit 40b132
    char *argv[];
Packit 40b132
{
Packit 40b132
    int copyout = 0;
Packit 40b132
    int uncompr = 0;
Packit 40b132
    gzFile file;
Packit 40b132
    char *bname, outmode[20];
Packit 40b132
Packit 40b132
    strcpy(outmode, "wb6 ");
Packit 40b132
Packit 40b132
    prog = argv[0];
Packit 40b132
    bname = strrchr(argv[0], '/');
Packit 40b132
    if (bname)
Packit 40b132
      bname++;
Packit 40b132
    else
Packit 40b132
      bname = argv[0];
Packit 40b132
    argc--, argv++;
Packit 40b132
Packit 40b132
    if (!strcmp(bname, "gunzip"))
Packit 40b132
      uncompr = 1;
Packit 40b132
    else if (!strcmp(bname, "zcat"))
Packit 40b132
      copyout = uncompr = 1;
Packit 40b132
Packit 40b132
    while (argc > 0) {
Packit 40b132
      if (strcmp(*argv, "-c") == 0)
Packit 40b132
        copyout = 1;
Packit 40b132
      else if (strcmp(*argv, "-d") == 0)
Packit 40b132
        uncompr = 1;
Packit 40b132
      else if (strcmp(*argv, "-f") == 0)
Packit 40b132
        outmode[3] = 'f';
Packit 40b132
      else if (strcmp(*argv, "-h") == 0)
Packit 40b132
        outmode[3] = 'h';
Packit 40b132
      else if (strcmp(*argv, "-r") == 0)
Packit 40b132
        outmode[3] = 'R';
Packit 40b132
      else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
Packit 40b132
               (*argv)[2] == 0)
Packit 40b132
        outmode[2] = (*argv)[1];
Packit 40b132
      else
Packit 40b132
        break;
Packit 40b132
      argc--, argv++;
Packit 40b132
    }
Packit 40b132
    if (outmode[3] == ' ')
Packit 40b132
        outmode[3] = 0;
Packit 40b132
    if (argc == 0) {
Packit 40b132
        SET_BINARY_MODE(stdin);
Packit 40b132
        SET_BINARY_MODE(stdout);
Packit 40b132
        if (uncompr) {
Packit 40b132
            file = gzdopen(fileno(stdin), "rb");
Packit 40b132
            if (file == NULL) error("can't gzdopen stdin");
Packit 40b132
            gz_uncompress(file, stdout);
Packit 40b132
        } else {
Packit 40b132
            file = gzdopen(fileno(stdout), outmode);
Packit 40b132
            if (file == NULL) error("can't gzdopen stdout");
Packit 40b132
            gz_compress(stdin, file);
Packit 40b132
        }
Packit 40b132
    } else {
Packit 40b132
        if (copyout) {
Packit 40b132
            SET_BINARY_MODE(stdout);
Packit 40b132
        }
Packit 40b132
        do {
Packit 40b132
            if (uncompr) {
Packit 40b132
                if (copyout) {
Packit 40b132
                    file = gzopen(*argv, "rb");
Packit 40b132
                    if (file == NULL)
Packit 40b132
                        fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
Packit 40b132
                    else
Packit 40b132
                        gz_uncompress(file, stdout);
Packit 40b132
                } else {
Packit 40b132
                    file_uncompress(*argv);
Packit 40b132
                }
Packit 40b132
            } else {
Packit 40b132
                if (copyout) {
Packit 40b132
                    FILE * in = fopen(*argv, "rb");
Packit 40b132
Packit 40b132
                    if (in == NULL) {
Packit 40b132
                        perror(*argv);
Packit 40b132
                    } else {
Packit 40b132
                        file = gzdopen(fileno(stdout), outmode);
Packit 40b132
                        if (file == NULL) error("can't gzdopen stdout");
Packit 40b132
Packit 40b132
                        gz_compress(in, file);
Packit 40b132
                    }
Packit 40b132
Packit 40b132
                } else {
Packit 40b132
                    file_compress(*argv, outmode);
Packit 40b132
                }
Packit 40b132
            }
Packit 40b132
        } while (argv++, --argc);
Packit 40b132
    }
Packit 40b132
    return 0;
Packit 40b132
}