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