source: trunk/third/zlib/minigzip.c @ 15211

Revision 15211, 7.7 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15210, which included commits to RCS files with non-trunk default branches.
Line 
1/* minigzip.c -- simulate gzip using the zlib compression library
2 * Copyright (C) 1995-1998 Jean-loup Gailly.
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6/*
7 * minigzip is a minimal implementation of the gzip utility. This is
8 * only an example of using zlib and isn't meant to replace the
9 * full-featured gzip. No attempt is made to deal with file systems
10 * limiting names to 14 or 8+3 characters, etc... Error checking is
11 * very limited. So use minigzip only for testing; use gzip for the
12 * real thing. On MSDOS, use only on file names without extension
13 * or in pipe mode.
14 */
15
16/* @(#) $Id: minigzip.c,v 1.1.1.1 2000-10-28 01:10:38 ghudson Exp $ */
17
18#include <stdio.h>
19#include "zlib.h"
20
21#ifdef STDC
22#  include <string.h>
23#  include <stdlib.h>
24#else
25   extern void exit  OF((int));
26#endif
27
28#ifdef USE_MMAP
29#  include <sys/types.h>
30#  include <sys/mman.h>
31#  include <sys/stat.h>
32#endif
33
34#if defined(MSDOS) || defined(OS2) || defined(WIN32)
35#  include <fcntl.h>
36#  include <io.h>
37#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
38#else
39#  define SET_BINARY_MODE(file)
40#endif
41
42#ifdef VMS
43#  define unlink delete
44#  define GZ_SUFFIX "-gz"
45#endif
46#ifdef RISCOS
47#  define unlink remove
48#  define GZ_SUFFIX "-gz"
49#  define fileno(file) file->__file
50#endif
51#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
52#  include <unix.h> /* for fileno */
53#endif
54
55#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
56  extern int unlink OF((const char *));
57#endif
58
59#ifndef GZ_SUFFIX
60#  define GZ_SUFFIX ".gz"
61#endif
62#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
63
64#define BUFLEN      16384
65#define MAX_NAME_LEN 1024
66
67#ifdef MAXSEG_64K
68#  define local static
69   /* Needed for systems with limitation on stack size. */
70#else
71#  define local
72#endif
73
74char *prog;
75
76void error            OF((const char *msg));
77void gz_compress      OF((FILE   *in, gzFile out));
78#ifdef USE_MMAP
79int  gz_compress_mmap OF((FILE   *in, gzFile out));
80#endif
81void gz_uncompress    OF((gzFile in, FILE   *out));
82void file_compress    OF((char  *file, char *mode));
83void file_uncompress  OF((char  *file));
84int  main             OF((int argc, char *argv[]));
85
86/* ===========================================================================
87 * Display error message and exit
88 */
89void error(msg)
90    const char *msg;
91{
92    fprintf(stderr, "%s: %s\n", prog, msg);
93    exit(1);
94}
95
96/* ===========================================================================
97 * Compress input to output then close both files.
98 */
99
100void gz_compress(in, out)
101    FILE   *in;
102    gzFile out;
103{
104    local char buf[BUFLEN];
105    int len;
106    int err;
107
108#ifdef USE_MMAP
109    /* Try first compressing with mmap. If mmap fails (minigzip used in a
110     * pipe), use the normal fread loop.
111     */
112    if (gz_compress_mmap(in, out) == Z_OK) return;
113#endif
114    for (;;) {
115        len = fread(buf, 1, sizeof(buf), in);
116        if (ferror(in)) {
117            perror("fread");
118            exit(1);
119        }
120        if (len == 0) break;
121
122        if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
123    }
124    fclose(in);
125    if (gzclose(out) != Z_OK) error("failed gzclose");
126}
127
128#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
129
130/* Try compressing the input file at once using mmap. Return Z_OK if
131 * if success, Z_ERRNO otherwise.
132 */
133int gz_compress_mmap(in, out)
134    FILE   *in;
135    gzFile out;
136{
137    int len;
138    int err;
139    int ifd = fileno(in);
140    caddr_t buf;    /* mmap'ed buffer for the entire input file */
141    off_t buf_len;  /* length of the input file */
142    struct stat sb;
143
144    /* Determine the size of the file, needed for mmap: */
145    if (fstat(ifd, &sb) < 0) return Z_ERRNO;
146    buf_len = sb.st_size;
147    if (buf_len <= 0) return Z_ERRNO;
148
149    /* Now do the actual mmap: */
150    buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
151    if (buf == (caddr_t)(-1)) return Z_ERRNO;
152
153    /* Compress the whole file at once: */
154    len = gzwrite(out, (char *)buf, (unsigned)buf_len);
155
156    if (len != (int)buf_len) error(gzerror(out, &err));
157
158    munmap(buf, buf_len);
159    fclose(in);
160    if (gzclose(out) != Z_OK) error("failed gzclose");
161    return Z_OK;
162}
163#endif /* USE_MMAP */
164
165/* ===========================================================================
166 * Uncompress input to output then close both files.
167 */
168void gz_uncompress(in, out)
169    gzFile in;
170    FILE   *out;
171{
172    local char buf[BUFLEN];
173    int len;
174    int err;
175
176    for (;;) {
177        len = gzread(in, buf, sizeof(buf));
178        if (len < 0) error (gzerror(in, &err));
179        if (len == 0) break;
180
181        if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
182            error("failed fwrite");
183        }
184    }
185    if (fclose(out)) error("failed fclose");
186
187    if (gzclose(in) != Z_OK) error("failed gzclose");
188}
189
190
191/* ===========================================================================
192 * Compress the given file: create a corresponding .gz file and remove the
193 * original.
194 */
195void file_compress(file, mode)
196    char  *file;
197    char  *mode;
198{
199    local char outfile[MAX_NAME_LEN];
200    FILE  *in;
201    gzFile out;
202
203    strcpy(outfile, file);
204    strcat(outfile, GZ_SUFFIX);
205
206    in = fopen(file, "rb");
207    if (in == NULL) {
208        perror(file);
209        exit(1);
210    }
211    out = gzopen(outfile, mode);
212    if (out == NULL) {
213        fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
214        exit(1);
215    }
216    gz_compress(in, out);
217
218    unlink(file);
219}
220
221
222/* ===========================================================================
223 * Uncompress the given file and remove the original.
224 */
225void file_uncompress(file)
226    char  *file;
227{
228    local char buf[MAX_NAME_LEN];
229    char *infile, *outfile;
230    FILE  *out;
231    gzFile in;
232    int len = strlen(file);
233
234    strcpy(buf, file);
235
236    if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
237        infile = file;
238        outfile = buf;
239        outfile[len-3] = '\0';
240    } else {
241        outfile = file;
242        infile = buf;
243        strcat(infile, GZ_SUFFIX);
244    }
245    in = gzopen(infile, "rb");
246    if (in == NULL) {
247        fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
248        exit(1);
249    }
250    out = fopen(outfile, "wb");
251    if (out == NULL) {
252        perror(file);
253        exit(1);
254    }
255
256    gz_uncompress(in, out);
257
258    unlink(infile);
259}
260
261
262/* ===========================================================================
263 * Usage:  minigzip [-d] [-f] [-h] [-1 to -9] [files...]
264 *   -d : decompress
265 *   -f : compress with Z_FILTERED
266 *   -h : compress with Z_HUFFMAN_ONLY
267 *   -1 to -9 : compression level
268 */
269
270int main(argc, argv)
271    int argc;
272    char *argv[];
273{
274    int uncompr = 0;
275    gzFile file;
276    char outmode[20];
277
278    strcpy(outmode, "wb6 ");
279
280    prog = argv[0];
281    argc--, argv++;
282
283    while (argc > 0) {
284      if (strcmp(*argv, "-d") == 0)
285        uncompr = 1;
286      else if (strcmp(*argv, "-f") == 0)
287        outmode[3] = 'f';
288      else if (strcmp(*argv, "-h") == 0)
289        outmode[3] = 'h';
290      else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
291               (*argv)[2] == 0)
292        outmode[2] = (*argv)[1];
293      else
294        break;
295      argc--, argv++;
296    }
297    if (argc == 0) {
298        SET_BINARY_MODE(stdin);
299        SET_BINARY_MODE(stdout);
300        if (uncompr) {
301            file = gzdopen(fileno(stdin), "rb");
302            if (file == NULL) error("can't gzdopen stdin");
303            gz_uncompress(file, stdout);
304        } else {
305            file = gzdopen(fileno(stdout), outmode);
306            if (file == NULL) error("can't gzdopen stdout");
307            gz_compress(stdin, file);
308        }
309    } else {
310        do {
311            if (uncompr) {
312                file_uncompress(*argv);
313            } else {
314                file_compress(*argv, outmode);
315            }
316        } while (argv++, --argc);
317    }
318    exit(0);
319    return 0; /* to avoid warning */
320}
Note: See TracBrowser for help on using the repository browser.