xref: /plan9-contrib/sys/src/cmd/gs/zlib/minigzip.c (revision 9b943567965ba040fd275927fbe088656eb8ce4f)
1 /* minigzip.c -- simulate gzip using the zlib compression library
2  * Copyright (C) 1995-1996 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.10 1996/07/24 13:41:04 me 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 
29 #if defined(MSDOS) || defined(OS2) || defined(WIN32)
30 #  include <fcntl.h>
31 #  include <io.h>
32 #  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
33 #else
34 #  define SET_BINARY_MODE(file)
35 #endif
36 
37 #ifdef VMS
38 #  define unlink delete
39 #  define GZ_SUFFIX "-gz"
40 #endif
41 #ifdef RISCOS
42 #  define unlink remove
43 #  define GZ_SUFFIX "-gz"
44 #  define fileno(file) file->__file
45 #endif
46 
47 #ifndef GZ_SUFFIX
48 #  define GZ_SUFFIX ".gz"
49 #endif
50 #define SUFFIX_LEN sizeof(GZ_SUFFIX)
51 
52 extern int unlink OF((const char *));
53 
54 #define BUFLEN 4096
55 #define MAX_NAME_LEN 1024
56 
57 #define local static
58 /* For MSDOS and other systems with limitation on stack size. For Unix,
59     #define local
60    works also.
61  */
62 
63 char *prog;
64 
65 void error           OF((const char *msg));
66 void gz_compress     OF((FILE   *in, gzFile out));
67 void gz_uncompress   OF((gzFile in, FILE   *out));
68 void file_compress   OF((char  *file));
69 void file_uncompress OF((char  *file));
70 int  main            OF((int argc, char *argv[]));
71 
72 /* ===========================================================================
73  * Display error message and exit
74  */
75 void error(msg)
76     const char *msg;
77 {
78     fprintf(stderr, "%s: %s\n", prog, msg);
79     exit(1);
80 }
81 
82 /* ===========================================================================
83  * Compress input to output then close both files.
84  */
85 void gz_compress(in, out)
86     FILE   *in;
87     gzFile out;
88 {
89     local char buf[BUFLEN];
90     int len;
91     int err;
92 
93     for (;;) {
94         len = fread(buf, 1, sizeof(buf), in);
95         if (ferror(in)) {
96             perror("fread");
97             exit(1);
98         }
99         if (len == 0) break;
100 
101         if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
102     }
103     fclose(in);
104     if (gzclose(out) != Z_OK) error("failed gzclose");
105 }
106 
107 /* ===========================================================================
108  * Uncompress input to output then close both files.
109  */
110 void gz_uncompress(in, out)
111     gzFile in;
112     FILE   *out;
113 {
114     local char buf[BUFLEN];
115     int len;
116     int err;
117 
118     for (;;) {
119         len = gzread(in, buf, sizeof(buf));
120         if (len < 0) error (gzerror(in, &err));
121         if (len == 0) break;
122 
123         if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
124 	    error("failed fwrite");
125 	}
126     }
127     if (fclose(out)) error("failed fclose");
128 
129     if (gzclose(in) != Z_OK) error("failed gzclose");
130 }
131 
132 
133 /* ===========================================================================
134  * Compress the given file: create a corresponding .gz file and remove the
135  * original.
136  */
137 void file_compress(file)
138     char  *file;
139 {
140     local char outfile[MAX_NAME_LEN];
141     FILE  *in;
142     gzFile out;
143 
144     strcpy(outfile, file);
145     strcat(outfile, GZ_SUFFIX);
146 
147     in = fopen(file, "rb");
148     if (in == NULL) {
149         perror(file);
150         exit(1);
151     }
152     out = gzopen(outfile, "wb"); /* use "wb9" for maximal compression */
153     if (out == NULL) {
154         fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
155         exit(1);
156     }
157     gz_compress(in, out);
158 
159     unlink(file);
160 }
161 
162 
163 /* ===========================================================================
164  * Uncompress the given file and remove the original.
165  */
166 void file_uncompress(file)
167     char  *file;
168 {
169     local char buf[MAX_NAME_LEN];
170     char *infile, *outfile;
171     FILE  *out;
172     gzFile in;
173     int len = strlen(file);
174 
175     strcpy(buf, file);
176 
177     if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
178         infile = file;
179         outfile = buf;
180         outfile[len-3] = '\0';
181     } else {
182         outfile = file;
183         infile = buf;
184         strcat(infile, GZ_SUFFIX);
185     }
186     in = gzopen(infile, "rb");
187     if (in == NULL) {
188         fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
189         exit(1);
190     }
191     out = fopen(outfile, "wb");
192     if (out == NULL) {
193         perror(file);
194         exit(1);
195     }
196 
197     gz_uncompress(in, out);
198 
199     unlink(infile);
200 }
201 
202 
203 /* ===========================================================================
204  * Usage:  minigzip [-d] [files...]
205  */
206 
207 int main(argc, argv)
208     int argc;
209     char *argv[];
210 {
211     int uncompr = 0;
212     gzFile file;
213 
214     prog = argv[0];
215     argc--, argv++;
216 
217     if (argc > 0) {
218         uncompr = (strcmp(*argv, "-d") == 0);
219         if (uncompr) {
220             argc--, argv++;
221         }
222     }
223     if (argc == 0) {
224         SET_BINARY_MODE(stdin);
225         SET_BINARY_MODE(stdout);
226         if (uncompr) {
227             file = gzdopen(fileno(stdin), "rb");
228             if (file == NULL) error("can't gzdopen stdin");
229             gz_uncompress(file, stdout);
230         } else {
231             file = gzdopen(fileno(stdout), "wb"); /* "wb9" for max compr. */
232             if (file == NULL) error("can't gzdopen stdout");
233             gz_compress(stdin, file);
234         }
235     } else {
236         do {
237             if (uncompr) {
238                 file_uncompress(*argv);
239             } else {
240                 file_compress(*argv);
241             }
242         } while (argv++, --argc);
243     }
244     exit(0);
245     return 0; /* to avoid warning */
246 }
247