minigzip.c revision 1.1.1.2 1 1.1 christos /* minigzip.c -- simulate gzip using the zlib compression library
2 1.1 christos * Copyright (C) 1995-2006, 2010, 2011, 2016 Jean-loup Gailly
3 1.1 christos * For conditions of distribution and use, see copyright notice in zlib.h
4 1.1 christos */
5 1.1 christos
6 1.1 christos /*
7 1.1 christos * minigzip is a minimal implementation of the gzip utility. This is
8 1.1 christos * only an example of using zlib and isn't meant to replace the
9 1.1 christos * full-featured gzip. No attempt is made to deal with file systems
10 1.1 christos * limiting names to 14 or 8+3 characters, etc... Error checking is
11 1.1 christos * very limited. So use minigzip only for testing; use gzip for the
12 1.1 christos * real thing. On MSDOS, use only on file names without extension
13 1.1 christos * or in pipe mode.
14 1.1 christos */
15 1.1 christos
16 1.1 christos /* @(#) $Id: minigzip.c,v 1.1.1.2 2022/10/15 19:38:38 christos Exp $ */
17 1.1 christos
18 1.1 christos #include "zlib.h"
19 1.1 christos #include <stdio.h>
20 1.1 christos
21 1.1 christos #ifdef STDC
22 1.1 christos # include <string.h>
23 1.1 christos # include <stdlib.h>
24 1.1 christos #endif
25 1.1 christos
26 1.1 christos #ifdef USE_MMAP
27 1.1 christos # include <sys/types.h>
28 1.1 christos # include <sys/mman.h>
29 1.1 christos # include <sys/stat.h>
30 1.1 christos #endif
31 1.1 christos
32 1.1 christos #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
33 1.1 christos # include <fcntl.h>
34 1.1 christos # include <io.h>
35 1.1 christos # ifdef UNDER_CE
36 1.1 christos # include <stdlib.h>
37 1.1 christos # endif
38 1.1 christos # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
39 1.1 christos #else
40 1.1 christos # define SET_BINARY_MODE(file)
41 1.1 christos #endif
42 1.1 christos
43 1.1 christos #if defined(_MSC_VER) && _MSC_VER < 1900
44 1.1 christos # define snprintf _snprintf
45 1.1 christos #endif
46 1.1 christos
47 1.1 christos #ifdef VMS
48 1.1 christos # define unlink delete
49 1.1 christos # define GZ_SUFFIX "-gz"
50 1.1 christos #endif
51 1.1 christos #ifdef RISCOS
52 1.1 christos # define unlink remove
53 1.1 christos # define GZ_SUFFIX "-gz"
54 1.1 christos # define fileno(file) file->__file
55 1.1 christos #endif
56 1.1 christos #if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
57 1.1 christos # include <unix.h> /* for fileno */
58 1.1 christos #endif
59 1.1 christos
60 1.1 christos #if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
61 1.1 christos #ifndef WIN32 /* unlink already in stdio.h for WIN32 */
62 1.1 christos extern int unlink OF((const char *));
63 1.1 christos #endif
64 1.1 christos #endif
65 1.1 christos
66 1.1 christos #if defined(UNDER_CE)
67 1.1 christos # include <windows.h>
68 1.1 christos # define perror(s) pwinerror(s)
69 1.1 christos
70 1.1 christos /* Map the Windows error number in ERROR to a locale-dependent error
71 1.1 christos message string and return a pointer to it. Typically, the values
72 1.1 christos for ERROR come from GetLastError.
73 1.1 christos
74 1.1 christos The string pointed to shall not be modified by the application,
75 1.1 christos but may be overwritten by a subsequent call to strwinerror
76 1.1 christos
77 1.1 christos The strwinerror function does not change the current setting
78 1.1 christos of GetLastError. */
79 1.1 christos
80 1.1 christos static char *strwinerror (error)
81 1.1 christos DWORD error;
82 1.1 christos {
83 1.1 christos static char buf[1024];
84 1.1 christos
85 1.1 christos wchar_t *msgbuf;
86 1.1 christos DWORD lasterr = GetLastError();
87 1.1 christos DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
88 1.1 christos | FORMAT_MESSAGE_ALLOCATE_BUFFER,
89 1.1 christos NULL,
90 1.1 christos error,
91 1.1 christos 0, /* Default language */
92 1.1 christos (LPVOID)&msgbuf,
93 1.1 christos 0,
94 1.1 christos NULL);
95 1.1 christos if (chars != 0) {
96 1.1 christos /* If there is an \r\n appended, zap it. */
97 1.1 christos if (chars >= 2
98 1.1 christos && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
99 1.1 christos chars -= 2;
100 1.1 christos msgbuf[chars] = 0;
101 1.1 christos }
102 1.1 christos
103 1.1 christos if (chars > sizeof (buf) - 1) {
104 1.1 christos chars = sizeof (buf) - 1;
105 1.1 christos msgbuf[chars] = 0;
106 1.1 christos }
107 1.1 christos
108 1.1 christos wcstombs(buf, msgbuf, chars + 1);
109 1.1 christos LocalFree(msgbuf);
110 1.1 christos }
111 1.1 christos else {
112 1.1 christos sprintf(buf, "unknown win32 error (%ld)", error);
113 1.1 christos }
114 1.1 christos
115 1.1 christos SetLastError(lasterr);
116 1.1 christos return buf;
117 1.1 christos }
118 1.1 christos
119 1.1 christos static void pwinerror (s)
120 1.1 christos const char *s;
121 1.1 christos {
122 1.1 christos if (s && *s)
123 1.1 christos fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));
124 1.1 christos else
125 1.1 christos fprintf(stderr, "%s\n", strwinerror(GetLastError ()));
126 1.1 christos }
127 1.1 christos
128 1.1 christos #endif /* UNDER_CE */
129 1.1 christos
130 1.1 christos #ifndef GZ_SUFFIX
131 1.1 christos # define GZ_SUFFIX ".gz"
132 1.1 christos #endif
133 1.1 christos #define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
134 1.1 christos
135 1.1 christos #define BUFLEN 16384
136 1.1 christos #define MAX_NAME_LEN 1024
137 1.1 christos
138 1.1 christos #ifdef MAXSEG_64K
139 1.1 christos # define local static
140 1.1 christos /* Needed for systems with limitation on stack size. */
141 1.1 christos #else
142 1.1 christos # define local
143 1.1 christos #endif
144 1.1 christos
145 1.1 christos #ifdef Z_SOLO
146 1.1 christos /* for Z_SOLO, create simplified gz* functions using deflate and inflate */
147 1.1 christos
148 1.1 christos #if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
149 1.1 christos # include <unistd.h> /* for unlink() */
150 1.1 christos #endif
151 1.1 christos
152 1.1 christos void *myalloc OF((void *, unsigned, unsigned));
153 1.1 christos void myfree OF((void *, void *));
154 1.1 christos
155 1.1 christos void *myalloc(q, n, m)
156 1.1 christos void *q;
157 1.1 christos unsigned n, m;
158 1.1 christos {
159 1.1 christos (void)q;
160 1.1 christos return calloc(n, m);
161 1.1 christos }
162 1.1 christos
163 1.1 christos void myfree(q, p)
164 1.1 christos void *q, *p;
165 1.1 christos {
166 1.1 christos (void)q;
167 1.1 christos free(p);
168 1.1 christos }
169 1.1 christos
170 1.1 christos typedef struct gzFile_s {
171 1.1 christos FILE *file;
172 1.1 christos int write;
173 1.1 christos int err;
174 1.1 christos char *msg;
175 1.1 christos z_stream strm;
176 1.1 christos } *gzFile;
177 1.1 christos
178 1.1 christos gzFile gzopen OF((const char *, const char *));
179 1.1 christos gzFile gzdopen OF((int, const char *));
180 1.1 christos gzFile gz_open OF((const char *, int, const char *));
181 1.1 christos
182 1.1 christos gzFile gzopen(path, mode)
183 1.1 christos const char *path;
184 1.1 christos const char *mode;
185 1.1 christos {
186 1.1 christos return gz_open(path, -1, mode);
187 1.1 christos }
188 1.1 christos
189 1.1 christos gzFile gzdopen(fd, mode)
190 1.1 christos int fd;
191 1.1 christos const char *mode;
192 1.1 christos {
193 1.1 christos return gz_open(NULL, fd, mode);
194 1.1 christos }
195 1.1 christos
196 1.1 christos gzFile gz_open(path, fd, mode)
197 1.1 christos const char *path;
198 1.1 christos int fd;
199 1.1 christos const char *mode;
200 1.1 christos {
201 1.1 christos gzFile gz;
202 1.1 christos int ret;
203 1.1 christos
204 1.1 christos gz = malloc(sizeof(struct gzFile_s));
205 1.1 christos if (gz == NULL)
206 1.1 christos return NULL;
207 1.1 christos gz->write = strchr(mode, 'w') != NULL;
208 1.1 christos gz->strm.zalloc = myalloc;
209 1.1 christos gz->strm.zfree = myfree;
210 1.1 christos gz->strm.opaque = Z_NULL;
211 1.1 christos if (gz->write)
212 1.1 christos ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0);
213 1.1 christos else {
214 1.1 christos gz->strm.next_in = 0;
215 1.1 christos gz->strm.avail_in = Z_NULL;
216 1.1 christos ret = inflateInit2(&(gz->strm), 15 + 16);
217 1.1 christos }
218 1.1 christos if (ret != Z_OK) {
219 1.1 christos free(gz);
220 1.1 christos return NULL;
221 1.1 christos }
222 1.1 christos gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") :
223 1.1 christos fopen(path, gz->write ? "wb" : "rb");
224 1.1 christos if (gz->file == NULL) {
225 1.1 christos gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm));
226 1.1 christos free(gz);
227 1.1 christos return NULL;
228 1.1 christos }
229 1.1 christos gz->err = 0;
230 1.1 christos gz->msg = "";
231 1.1 christos return gz;
232 1.1 christos }
233 1.1 christos
234 1.1 christos int gzwrite OF((gzFile, const void *, unsigned));
235 1.1 christos
236 1.1 christos int gzwrite(gz, buf, len)
237 1.1 christos gzFile gz;
238 1.1 christos const void *buf;
239 1.1 christos unsigned len;
240 1.1 christos {
241 1.1 christos z_stream *strm;
242 1.1 christos unsigned char out[BUFLEN];
243 1.1 christos
244 1.1 christos if (gz == NULL || !gz->write)
245 1.1 christos return 0;
246 1.1 christos strm = &(gz->strm);
247 1.1 christos strm->next_in = (void *)buf;
248 1.1 christos strm->avail_in = len;
249 1.1 christos do {
250 1.1 christos strm->next_out = out;
251 1.1 christos strm->avail_out = BUFLEN;
252 1.1 christos (void)deflate(strm, Z_NO_FLUSH);
253 1.1 christos fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
254 1.1 christos } while (strm->avail_out == 0);
255 1.1 christos return len;
256 1.1 christos }
257 1.1 christos
258 1.1 christos int gzread OF((gzFile, void *, unsigned));
259 1.1 christos
260 1.1 christos int gzread(gz, buf, len)
261 1.1 christos gzFile gz;
262 1.1 christos void *buf;
263 1.1 christos unsigned len;
264 1.1 christos {
265 1.1 christos int ret;
266 1.1 christos unsigned got;
267 1.1 christos unsigned char in[1];
268 1.1 christos z_stream *strm;
269 1.1 christos
270 1.1 christos if (gz == NULL || gz->write)
271 1.1 christos return 0;
272 1.1 christos if (gz->err)
273 1.1 christos return 0;
274 1.1 christos strm = &(gz->strm);
275 1.1 christos strm->next_out = (void *)buf;
276 1.1 christos strm->avail_out = len;
277 1.1 christos do {
278 1.1 christos got = fread(in, 1, 1, gz->file);
279 1.1 christos if (got == 0)
280 1.1 christos break;
281 1.1 christos strm->next_in = in;
282 1.1 christos strm->avail_in = 1;
283 1.1 christos ret = inflate(strm, Z_NO_FLUSH);
284 1.1 christos if (ret == Z_DATA_ERROR) {
285 1.1 christos gz->err = Z_DATA_ERROR;
286 1.1 christos gz->msg = strm->msg;
287 1.1 christos return 0;
288 1.1 christos }
289 1.1 christos if (ret == Z_STREAM_END)
290 1.1 christos inflateReset(strm);
291 1.1 christos } while (strm->avail_out);
292 1.1 christos return len - strm->avail_out;
293 1.1 christos }
294 1.1 christos
295 1.1 christos int gzclose OF((gzFile));
296 1.1 christos
297 1.1 christos int gzclose(gz)
298 1.1 christos gzFile gz;
299 1.1 christos {
300 1.1 christos z_stream *strm;
301 1.1 christos unsigned char out[BUFLEN];
302 1.1 christos
303 1.1 christos if (gz == NULL)
304 1.1 christos return Z_STREAM_ERROR;
305 1.1 christos strm = &(gz->strm);
306 1.1 christos if (gz->write) {
307 1.1 christos strm->next_in = Z_NULL;
308 1.1 christos strm->avail_in = 0;
309 1.1 christos do {
310 1.1 christos strm->next_out = out;
311 1.1 christos strm->avail_out = BUFLEN;
312 1.1 christos (void)deflate(strm, Z_FINISH);
313 1.1 christos fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
314 1.1 christos } while (strm->avail_out == 0);
315 1.1 christos deflateEnd(strm);
316 1.1 christos }
317 1.1 christos else
318 1.1 christos inflateEnd(strm);
319 1.1 christos fclose(gz->file);
320 1.1 christos free(gz);
321 1.1 christos return Z_OK;
322 1.1 christos }
323 1.1 christos
324 1.1 christos const char *gzerror OF((gzFile, int *));
325 1.1 christos
326 1.1 christos const char *gzerror(gz, err)
327 1.1 christos gzFile gz;
328 1.1 christos int *err;
329 1.1 christos {
330 1.1 christos *err = gz->err;
331 1.1 christos return gz->msg;
332 1.1 christos }
333 1.1 christos
334 1.1 christos #endif
335 1.1 christos
336 1.1 christos static char *prog;
337 1.1 christos
338 1.1 christos void error OF((const char *msg));
339 1.1 christos void gz_compress OF((FILE *in, gzFile out));
340 1.1 christos #ifdef USE_MMAP
341 1.1 christos int gz_compress_mmap OF((FILE *in, gzFile out));
342 1.1 christos #endif
343 1.1 christos void gz_uncompress OF((gzFile in, FILE *out));
344 1.1 christos void file_compress OF((char *file, char *mode));
345 1.1 christos void file_uncompress OF((char *file));
346 1.1 christos int main OF((int argc, char *argv[]));
347 1.1 christos
348 1.1 christos /* ===========================================================================
349 1.1 christos * Display error message and exit
350 1.1 christos */
351 1.1 christos void error(msg)
352 1.1 christos const char *msg;
353 1.1 christos {
354 1.1 christos fprintf(stderr, "%s: %s\n", prog, msg);
355 1.1 christos exit(1);
356 1.1 christos }
357 1.1 christos
358 1.1 christos /* ===========================================================================
359 1.1 christos * Compress input to output then close both files.
360 1.1 christos */
361 1.1 christos
362 1.1 christos void gz_compress(in, out)
363 1.1 christos FILE *in;
364 1.1 christos gzFile out;
365 1.1 christos {
366 1.1 christos local char buf[BUFLEN];
367 1.1 christos int len;
368 1.1 christos int err;
369 1.1 christos
370 1.1 christos #ifdef USE_MMAP
371 1.1 christos /* Try first compressing with mmap. If mmap fails (minigzip used in a
372 1.1 christos * pipe), use the normal fread loop.
373 1.1 christos */
374 1.1 christos if (gz_compress_mmap(in, out) == Z_OK) return;
375 1.1 christos #endif
376 1.1 christos for (;;) {
377 1.1 christos len = (int)fread(buf, 1, sizeof(buf), in);
378 1.1 christos if (ferror(in)) {
379 1.1 christos perror("fread");
380 1.1 christos exit(1);
381 1.1 christos }
382 1.1 christos if (len == 0) break;
383 1.1 christos
384 1.1 christos if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
385 1.1 christos }
386 1.1 christos fclose(in);
387 1.1 christos if (gzclose(out) != Z_OK) error("failed gzclose");
388 1.1 christos }
389 1.1 christos
390 1.1 christos #ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech (at) eso.org> */
391 1.1 christos
392 1.1 christos /* Try compressing the input file at once using mmap. Return Z_OK if
393 1.1 christos * if success, Z_ERRNO otherwise.
394 1.1 christos */
395 1.1 christos int gz_compress_mmap(in, out)
396 1.1 christos FILE *in;
397 1.1 christos gzFile out;
398 1.1 christos {
399 1.1 christos int len;
400 1.1 christos int err;
401 1.1 christos int ifd = fileno(in);
402 1.1 christos caddr_t buf; /* mmap'ed buffer for the entire input file */
403 1.1 christos off_t buf_len; /* length of the input file */
404 1.1 christos struct stat sb;
405 1.1 christos
406 1.1 christos /* Determine the size of the file, needed for mmap: */
407 1.1 christos if (fstat(ifd, &sb) < 0) return Z_ERRNO;
408 1.1 christos buf_len = sb.st_size;
409 1.1 christos if (buf_len <= 0) return Z_ERRNO;
410 1.1 christos
411 1.1 christos /* Now do the actual mmap: */
412 1.1 christos buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
413 1.1 christos if (buf == (caddr_t)(-1)) return Z_ERRNO;
414 1.1 christos
415 1.1 christos /* Compress the whole file at once: */
416 1.1 christos len = gzwrite(out, (char *)buf, (unsigned)buf_len);
417 1.1 christos
418 1.1 christos if (len != (int)buf_len) error(gzerror(out, &err));
419 1.1 christos
420 1.1 christos munmap(buf, buf_len);
421 1.1 christos fclose(in);
422 1.1 christos if (gzclose(out) != Z_OK) error("failed gzclose");
423 1.1 christos return Z_OK;
424 1.1 christos }
425 1.1 christos #endif /* USE_MMAP */
426 1.1 christos
427 1.1 christos /* ===========================================================================
428 1.1 christos * Uncompress input to output then close both files.
429 1.1 christos */
430 1.1 christos void gz_uncompress(in, out)
431 1.1 christos gzFile in;
432 1.1 christos FILE *out;
433 1.1 christos {
434 1.1 christos local char buf[BUFLEN];
435 1.1 christos int len;
436 1.1 christos int err;
437 1.1 christos
438 1.1 christos for (;;) {
439 1.1 christos len = gzread(in, buf, sizeof(buf));
440 1.1 christos if (len < 0) error (gzerror(in, &err));
441 1.1 christos if (len == 0) break;
442 1.1 christos
443 1.1 christos if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
444 1.1 christos error("failed fwrite");
445 1.1 christos }
446 1.1 christos }
447 1.1 christos if (fclose(out)) error("failed fclose");
448 1.1 christos
449 1.1 christos if (gzclose(in) != Z_OK) error("failed gzclose");
450 1.1 christos }
451 1.1 christos
452 1.1 christos
453 1.1 christos /* ===========================================================================
454 1.1 christos * Compress the given file: create a corresponding .gz file and remove the
455 1.1 christos * original.
456 1.1 christos */
457 1.1 christos void file_compress(file, mode)
458 1.1 christos char *file;
459 1.1 christos char *mode;
460 1.1 christos {
461 1.1 christos local char outfile[MAX_NAME_LEN];
462 1.1 christos FILE *in;
463 1.1 christos gzFile out;
464 1.1 christos
465 1.1 christos if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
466 1.1 christos fprintf(stderr, "%s: filename too long\n", prog);
467 1.1 christos exit(1);
468 1.1 christos }
469 1.1 christos
470 1.1 christos #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
471 1.1 christos snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX);
472 1.1 christos #else
473 1.1 christos strcpy(outfile, file);
474 1.1 christos strcat(outfile, GZ_SUFFIX);
475 1.1 christos #endif
476 1.1 christos
477 1.1 christos in = fopen(file, "rb");
478 1.1 christos if (in == NULL) {
479 1.1 christos perror(file);
480 1.1 christos exit(1);
481 1.1 christos }
482 1.1 christos out = gzopen(outfile, mode);
483 1.1 christos if (out == NULL) {
484 1.1 christos fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
485 1.1 christos exit(1);
486 1.1 christos }
487 1.1 christos gz_compress(in, out);
488 1.1 christos
489 1.1 christos unlink(file);
490 1.1 christos }
491 1.1 christos
492 1.1 christos
493 1.1 christos /* ===========================================================================
494 1.1 christos * Uncompress the given file and remove the original.
495 1.1 christos */
496 1.1 christos void file_uncompress(file)
497 1.1 christos char *file;
498 1.1 christos {
499 1.1 christos local char buf[MAX_NAME_LEN];
500 1.1 christos char *infile, *outfile;
501 1.1 christos FILE *out;
502 1.1 christos gzFile in;
503 1.1.1.2 christos z_size_t len = strlen(file);
504 1.1 christos
505 1.1 christos if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
506 1.1 christos fprintf(stderr, "%s: filename too long\n", prog);
507 1.1 christos exit(1);
508 1.1 christos }
509 1.1 christos
510 1.1 christos #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
511 1.1 christos snprintf(buf, sizeof(buf), "%s", file);
512 1.1 christos #else
513 1.1 christos strcpy(buf, file);
514 1.1 christos #endif
515 1.1 christos
516 1.1 christos if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
517 1.1 christos infile = file;
518 1.1 christos outfile = buf;
519 1.1 christos outfile[len-3] = '\0';
520 1.1 christos } else {
521 1.1 christos outfile = file;
522 1.1 christos infile = buf;
523 1.1 christos #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
524 1.1 christos snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX);
525 1.1 christos #else
526 1.1 christos strcat(infile, GZ_SUFFIX);
527 1.1 christos #endif
528 1.1 christos }
529 1.1 christos in = gzopen(infile, "rb");
530 1.1 christos if (in == NULL) {
531 1.1 christos fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
532 1.1 christos exit(1);
533 1.1 christos }
534 1.1 christos out = fopen(outfile, "wb");
535 1.1 christos if (out == NULL) {
536 1.1 christos perror(file);
537 1.1 christos exit(1);
538 1.1 christos }
539 1.1 christos
540 1.1 christos gz_uncompress(in, out);
541 1.1 christos
542 1.1 christos unlink(infile);
543 1.1 christos }
544 1.1 christos
545 1.1 christos
546 1.1 christos /* ===========================================================================
547 1.1 christos * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
548 1.1 christos * -c : write to standard output
549 1.1 christos * -d : decompress
550 1.1 christos * -f : compress with Z_FILTERED
551 1.1 christos * -h : compress with Z_HUFFMAN_ONLY
552 1.1 christos * -r : compress with Z_RLE
553 1.1 christos * -1 to -9 : compression level
554 1.1 christos */
555 1.1 christos
556 1.1 christos int main(argc, argv)
557 1.1 christos int argc;
558 1.1 christos char *argv[];
559 1.1 christos {
560 1.1 christos int copyout = 0;
561 1.1 christos int uncompr = 0;
562 1.1 christos gzFile file;
563 1.1 christos char *bname, outmode[20];
564 1.1 christos
565 1.1 christos #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
566 1.1 christos snprintf(outmode, sizeof(outmode), "%s", "wb6 ");
567 1.1 christos #else
568 1.1 christos strcpy(outmode, "wb6 ");
569 1.1 christos #endif
570 1.1 christos
571 1.1 christos prog = argv[0];
572 1.1 christos bname = strrchr(argv[0], '/');
573 1.1 christos if (bname)
574 1.1 christos bname++;
575 1.1 christos else
576 1.1 christos bname = argv[0];
577 1.1 christos argc--, argv++;
578 1.1 christos
579 1.1 christos if (!strcmp(bname, "gunzip"))
580 1.1 christos uncompr = 1;
581 1.1 christos else if (!strcmp(bname, "zcat"))
582 1.1 christos copyout = uncompr = 1;
583 1.1 christos
584 1.1 christos while (argc > 0) {
585 1.1 christos if (strcmp(*argv, "-c") == 0)
586 1.1 christos copyout = 1;
587 1.1 christos else if (strcmp(*argv, "-d") == 0)
588 1.1 christos uncompr = 1;
589 1.1 christos else if (strcmp(*argv, "-f") == 0)
590 1.1 christos outmode[3] = 'f';
591 1.1 christos else if (strcmp(*argv, "-h") == 0)
592 1.1 christos outmode[3] = 'h';
593 1.1 christos else if (strcmp(*argv, "-r") == 0)
594 1.1 christos outmode[3] = 'R';
595 1.1 christos else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
596 1.1 christos (*argv)[2] == 0)
597 1.1 christos outmode[2] = (*argv)[1];
598 1.1 christos else
599 1.1 christos break;
600 1.1 christos argc--, argv++;
601 1.1 christos }
602 1.1 christos if (outmode[3] == ' ')
603 1.1 christos outmode[3] = 0;
604 1.1 christos if (argc == 0) {
605 1.1 christos SET_BINARY_MODE(stdin);
606 1.1 christos SET_BINARY_MODE(stdout);
607 1.1 christos if (uncompr) {
608 1.1 christos file = gzdopen(fileno(stdin), "rb");
609 1.1 christos if (file == NULL) error("can't gzdopen stdin");
610 1.1 christos gz_uncompress(file, stdout);
611 1.1 christos } else {
612 1.1 christos file = gzdopen(fileno(stdout), outmode);
613 1.1 christos if (file == NULL) error("can't gzdopen stdout");
614 1.1 christos gz_compress(stdin, file);
615 1.1 christos }
616 1.1 christos } else {
617 1.1 christos if (copyout) {
618 1.1 christos SET_BINARY_MODE(stdout);
619 1.1 christos }
620 1.1 christos do {
621 1.1 christos if (uncompr) {
622 1.1 christos if (copyout) {
623 1.1 christos file = gzopen(*argv, "rb");
624 1.1 christos if (file == NULL)
625 1.1 christos fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
626 1.1 christos else
627 1.1 christos gz_uncompress(file, stdout);
628 1.1 christos } else {
629 1.1 christos file_uncompress(*argv);
630 1.1 christos }
631 1.1 christos } else {
632 1.1 christos if (copyout) {
633 1.1 christos FILE * in = fopen(*argv, "rb");
634 1.1 christos
635 1.1 christos if (in == NULL) {
636 1.1 christos perror(*argv);
637 1.1 christos } else {
638 1.1 christos file = gzdopen(fileno(stdout), outmode);
639 1.1 christos if (file == NULL) error("can't gzdopen stdout");
640 1.1 christos
641 1.1 christos gz_compress(in, file);
642 1.1 christos }
643 1.1 christos
644 1.1 christos } else {
645 1.1 christos file_compress(*argv, outmode);
646 1.1 christos }
647 1.1 christos }
648 1.1 christos } while (argv++, --argc);
649 1.1 christos }
650 1.1 christos return 0;
651 1.1 christos }
652