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