1275793eaSopenharmony_ci/* minigzip.c -- simulate gzip using the zlib compression library
2275793eaSopenharmony_ci * Copyright (C) 1995-2006, 2010, 2011, 2016 Jean-loup Gailly
3275793eaSopenharmony_ci * For conditions of distribution and use, see copyright notice in zlib.h
4275793eaSopenharmony_ci */
5275793eaSopenharmony_ci
6275793eaSopenharmony_ci/*
7275793eaSopenharmony_ci * minigzip is a minimal implementation of the gzip utility. This is
8275793eaSopenharmony_ci * only an example of using zlib and isn't meant to replace the
9275793eaSopenharmony_ci * full-featured gzip. No attempt is made to deal with file systems
10275793eaSopenharmony_ci * limiting names to 14 or 8+3 characters, etc... Error checking is
11275793eaSopenharmony_ci * very limited. So use minigzip only for testing; use gzip for the
12275793eaSopenharmony_ci * real thing. On MSDOS, use only on file names without extension
13275793eaSopenharmony_ci * or in pipe mode.
14275793eaSopenharmony_ci */
15275793eaSopenharmony_ci
16275793eaSopenharmony_ci/* @(#) $Id$ */
17275793eaSopenharmony_ci
18275793eaSopenharmony_ci#include "zlib.h"
19275793eaSopenharmony_ci#include <stdio.h>
20275793eaSopenharmony_ci
21275793eaSopenharmony_ci#ifdef STDC
22275793eaSopenharmony_ci#  include <string.h>
23275793eaSopenharmony_ci#  include <stdlib.h>
24275793eaSopenharmony_ci#endif
25275793eaSopenharmony_ci
26275793eaSopenharmony_ci#ifdef USE_MMAP
27275793eaSopenharmony_ci#  include <sys/types.h>
28275793eaSopenharmony_ci#  include <sys/mman.h>
29275793eaSopenharmony_ci#  include <sys/stat.h>
30275793eaSopenharmony_ci#endif
31275793eaSopenharmony_ci
32275793eaSopenharmony_ci#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
33275793eaSopenharmony_ci#  include <fcntl.h>
34275793eaSopenharmony_ci#  include <io.h>
35275793eaSopenharmony_ci#  ifdef UNDER_CE
36275793eaSopenharmony_ci#    include <stdlib.h>
37275793eaSopenharmony_ci#  endif
38275793eaSopenharmony_ci#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
39275793eaSopenharmony_ci#else
40275793eaSopenharmony_ci#  define SET_BINARY_MODE(file)
41275793eaSopenharmony_ci#endif
42275793eaSopenharmony_ci
43275793eaSopenharmony_ci#if defined(_MSC_VER) && _MSC_VER < 1900
44275793eaSopenharmony_ci#  define snprintf _snprintf
45275793eaSopenharmony_ci#endif
46275793eaSopenharmony_ci
47275793eaSopenharmony_ci#ifdef VMS
48275793eaSopenharmony_ci#  define unlink delete
49275793eaSopenharmony_ci#  define GZ_SUFFIX "-gz"
50275793eaSopenharmony_ci#endif
51275793eaSopenharmony_ci#ifdef RISCOS
52275793eaSopenharmony_ci#  define unlink remove
53275793eaSopenharmony_ci#  define GZ_SUFFIX "-gz"
54275793eaSopenharmony_ci#  define fileno(file) file->__file
55275793eaSopenharmony_ci#endif
56275793eaSopenharmony_ci#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
57275793eaSopenharmony_ci#  include <unix.h> /* for fileno */
58275793eaSopenharmony_ci#endif
59275793eaSopenharmony_ci
60275793eaSopenharmony_ci#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
61275793eaSopenharmony_ci#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
62275793eaSopenharmony_ci  extern int unlink(const char *);
63275793eaSopenharmony_ci#endif
64275793eaSopenharmony_ci#endif
65275793eaSopenharmony_ci
66275793eaSopenharmony_ci#if defined(UNDER_CE)
67275793eaSopenharmony_ci#  include <windows.h>
68275793eaSopenharmony_ci#  define perror(s) pwinerror(s)
69275793eaSopenharmony_ci
70275793eaSopenharmony_ci/* Map the Windows error number in ERROR to a locale-dependent error
71275793eaSopenharmony_ci   message string and return a pointer to it.  Typically, the values
72275793eaSopenharmony_ci   for ERROR come from GetLastError.
73275793eaSopenharmony_ci
74275793eaSopenharmony_ci   The string pointed to shall not be modified by the application,
75275793eaSopenharmony_ci   but may be overwritten by a subsequent call to strwinerror
76275793eaSopenharmony_ci
77275793eaSopenharmony_ci   The strwinerror function does not change the current setting
78275793eaSopenharmony_ci   of GetLastError.  */
79275793eaSopenharmony_ci
80275793eaSopenharmony_cistatic char *strwinerror (error)
81275793eaSopenharmony_ci     DWORD error;
82275793eaSopenharmony_ci{
83275793eaSopenharmony_ci    static char buf[1024];
84275793eaSopenharmony_ci
85275793eaSopenharmony_ci    wchar_t *msgbuf;
86275793eaSopenharmony_ci    DWORD lasterr = GetLastError();
87275793eaSopenharmony_ci    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
88275793eaSopenharmony_ci        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
89275793eaSopenharmony_ci        NULL,
90275793eaSopenharmony_ci        error,
91275793eaSopenharmony_ci        0, /* Default language */
92275793eaSopenharmony_ci        (LPVOID)&msgbuf,
93275793eaSopenharmony_ci        0,
94275793eaSopenharmony_ci        NULL);
95275793eaSopenharmony_ci    if (chars != 0) {
96275793eaSopenharmony_ci        /* If there is an \r\n appended, zap it.  */
97275793eaSopenharmony_ci        if (chars >= 2
98275793eaSopenharmony_ci            && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
99275793eaSopenharmony_ci            chars -= 2;
100275793eaSopenharmony_ci            msgbuf[chars] = 0;
101275793eaSopenharmony_ci        }
102275793eaSopenharmony_ci
103275793eaSopenharmony_ci        if (chars > sizeof (buf) - 1) {
104275793eaSopenharmony_ci            chars = sizeof (buf) - 1;
105275793eaSopenharmony_ci            msgbuf[chars] = 0;
106275793eaSopenharmony_ci        }
107275793eaSopenharmony_ci
108275793eaSopenharmony_ci        wcstombs(buf, msgbuf, chars + 1);
109275793eaSopenharmony_ci        LocalFree(msgbuf);
110275793eaSopenharmony_ci    }
111275793eaSopenharmony_ci    else {
112275793eaSopenharmony_ci        sprintf(buf, "unknown win32 error (%ld)", error);
113275793eaSopenharmony_ci    }
114275793eaSopenharmony_ci
115275793eaSopenharmony_ci    SetLastError(lasterr);
116275793eaSopenharmony_ci    return buf;
117275793eaSopenharmony_ci}
118275793eaSopenharmony_ci
119275793eaSopenharmony_cistatic void pwinerror (s)
120275793eaSopenharmony_ci    const char *s;
121275793eaSopenharmony_ci{
122275793eaSopenharmony_ci    if (s && *s)
123275793eaSopenharmony_ci        fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));
124275793eaSopenharmony_ci    else
125275793eaSopenharmony_ci        fprintf(stderr, "%s\n", strwinerror(GetLastError ()));
126275793eaSopenharmony_ci}
127275793eaSopenharmony_ci
128275793eaSopenharmony_ci#endif /* UNDER_CE */
129275793eaSopenharmony_ci
130275793eaSopenharmony_ci#ifndef GZ_SUFFIX
131275793eaSopenharmony_ci#  define GZ_SUFFIX ".gz"
132275793eaSopenharmony_ci#endif
133275793eaSopenharmony_ci#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
134275793eaSopenharmony_ci
135275793eaSopenharmony_ci#define BUFLEN      16384
136275793eaSopenharmony_ci#define MAX_NAME_LEN 1024
137275793eaSopenharmony_ci
138275793eaSopenharmony_ci#ifdef MAXSEG_64K
139275793eaSopenharmony_ci#  define local static
140275793eaSopenharmony_ci   /* Needed for systems with limitation on stack size. */
141275793eaSopenharmony_ci#else
142275793eaSopenharmony_ci#  define local
143275793eaSopenharmony_ci#endif
144275793eaSopenharmony_ci
145275793eaSopenharmony_ci#ifdef Z_SOLO
146275793eaSopenharmony_ci/* for Z_SOLO, create simplified gz* functions using deflate and inflate */
147275793eaSopenharmony_ci
148275793eaSopenharmony_ci#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
149275793eaSopenharmony_ci#  include <unistd.h>       /* for unlink() */
150275793eaSopenharmony_ci#endif
151275793eaSopenharmony_ci
152275793eaSopenharmony_cistatic void *myalloc(void *q, unsigned n, unsigned m)
153275793eaSopenharmony_ci{
154275793eaSopenharmony_ci    (void)q;
155275793eaSopenharmony_ci    return calloc(n, m);
156275793eaSopenharmony_ci}
157275793eaSopenharmony_ci
158275793eaSopenharmony_cistatic void myfree(void *q, void *p)
159275793eaSopenharmony_ci{
160275793eaSopenharmony_ci    (void)q;
161275793eaSopenharmony_ci    free(p);
162275793eaSopenharmony_ci}
163275793eaSopenharmony_ci
164275793eaSopenharmony_citypedef struct gzFile_s {
165275793eaSopenharmony_ci    FILE *file;
166275793eaSopenharmony_ci    int write;
167275793eaSopenharmony_ci    int err;
168275793eaSopenharmony_ci    char *msg;
169275793eaSopenharmony_ci    z_stream strm;
170275793eaSopenharmony_ci} *gzFile;
171275793eaSopenharmony_ci
172275793eaSopenharmony_cistatic gzFile gz_open(const char *path, int fd, const char *mode)
173275793eaSopenharmony_ci{
174275793eaSopenharmony_ci    gzFile gz;
175275793eaSopenharmony_ci    int ret;
176275793eaSopenharmony_ci
177275793eaSopenharmony_ci    gz = malloc(sizeof(struct gzFile_s));
178275793eaSopenharmony_ci    if (gz == NULL)
179275793eaSopenharmony_ci        return NULL;
180275793eaSopenharmony_ci    gz->write = strchr(mode, 'w') != NULL;
181275793eaSopenharmony_ci    gz->strm.zalloc = myalloc;
182275793eaSopenharmony_ci    gz->strm.zfree = myfree;
183275793eaSopenharmony_ci    gz->strm.opaque = Z_NULL;
184275793eaSopenharmony_ci    if (gz->write)
185275793eaSopenharmony_ci        ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0);
186275793eaSopenharmony_ci    else {
187275793eaSopenharmony_ci        gz->strm.next_in = 0;
188275793eaSopenharmony_ci        gz->strm.avail_in = Z_NULL;
189275793eaSopenharmony_ci        ret = inflateInit2(&(gz->strm), 15 + 16);
190275793eaSopenharmony_ci    }
191275793eaSopenharmony_ci    if (ret != Z_OK) {
192275793eaSopenharmony_ci        free(gz);
193275793eaSopenharmony_ci        return NULL;
194275793eaSopenharmony_ci    }
195275793eaSopenharmony_ci    gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") :
196275793eaSopenharmony_ci                              fopen(path, gz->write ? "wb" : "rb");
197275793eaSopenharmony_ci    if (gz->file == NULL) {
198275793eaSopenharmony_ci        gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm));
199275793eaSopenharmony_ci        free(gz);
200275793eaSopenharmony_ci        return NULL;
201275793eaSopenharmony_ci    }
202275793eaSopenharmony_ci    gz->err = 0;
203275793eaSopenharmony_ci    gz->msg = "";
204275793eaSopenharmony_ci    return gz;
205275793eaSopenharmony_ci}
206275793eaSopenharmony_ci
207275793eaSopenharmony_cistatic gzFile gzopen(const char *path, const char *mode)
208275793eaSopenharmony_ci{
209275793eaSopenharmony_ci    return gz_open(path, -1, mode);
210275793eaSopenharmony_ci}
211275793eaSopenharmony_ci
212275793eaSopenharmony_cistatic gzFile gzdopen(int fd, const char *mode)
213275793eaSopenharmony_ci{
214275793eaSopenharmony_ci    return gz_open(NULL, fd, mode);
215275793eaSopenharmony_ci}
216275793eaSopenharmony_ci
217275793eaSopenharmony_cistatic int gzwrite(gzFile gz, const void *buf, unsigned len)
218275793eaSopenharmony_ci{
219275793eaSopenharmony_ci    z_stream *strm;
220275793eaSopenharmony_ci    unsigned char out[BUFLEN];
221275793eaSopenharmony_ci
222275793eaSopenharmony_ci    if (gz == NULL || !gz->write)
223275793eaSopenharmony_ci        return 0;
224275793eaSopenharmony_ci    strm = &(gz->strm);
225275793eaSopenharmony_ci    strm->next_in = (void *)buf;
226275793eaSopenharmony_ci    strm->avail_in = len;
227275793eaSopenharmony_ci    do {
228275793eaSopenharmony_ci        strm->next_out = out;
229275793eaSopenharmony_ci        strm->avail_out = BUFLEN;
230275793eaSopenharmony_ci        (void)deflate(strm, Z_NO_FLUSH);
231275793eaSopenharmony_ci        fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
232275793eaSopenharmony_ci    } while (strm->avail_out == 0);
233275793eaSopenharmony_ci    return len;
234275793eaSopenharmony_ci}
235275793eaSopenharmony_ci
236275793eaSopenharmony_cistatic int gzread(gzFile gz, void *buf, unsigned len)
237275793eaSopenharmony_ci{
238275793eaSopenharmony_ci    int ret;
239275793eaSopenharmony_ci    unsigned got;
240275793eaSopenharmony_ci    unsigned char in[1];
241275793eaSopenharmony_ci    z_stream *strm;
242275793eaSopenharmony_ci
243275793eaSopenharmony_ci    if (gz == NULL || gz->write)
244275793eaSopenharmony_ci        return 0;
245275793eaSopenharmony_ci    if (gz->err)
246275793eaSopenharmony_ci        return 0;
247275793eaSopenharmony_ci    strm = &(gz->strm);
248275793eaSopenharmony_ci    strm->next_out = (void *)buf;
249275793eaSopenharmony_ci    strm->avail_out = len;
250275793eaSopenharmony_ci    do {
251275793eaSopenharmony_ci        got = fread(in, 1, 1, gz->file);
252275793eaSopenharmony_ci        if (got == 0)
253275793eaSopenharmony_ci            break;
254275793eaSopenharmony_ci        strm->next_in = in;
255275793eaSopenharmony_ci        strm->avail_in = 1;
256275793eaSopenharmony_ci        ret = inflate(strm, Z_NO_FLUSH);
257275793eaSopenharmony_ci        if (ret == Z_DATA_ERROR) {
258275793eaSopenharmony_ci            gz->err = Z_DATA_ERROR;
259275793eaSopenharmony_ci            gz->msg = strm->msg;
260275793eaSopenharmony_ci            return 0;
261275793eaSopenharmony_ci        }
262275793eaSopenharmony_ci        if (ret == Z_STREAM_END)
263275793eaSopenharmony_ci            inflateReset(strm);
264275793eaSopenharmony_ci    } while (strm->avail_out);
265275793eaSopenharmony_ci    return len - strm->avail_out;
266275793eaSopenharmony_ci}
267275793eaSopenharmony_ci
268275793eaSopenharmony_cistatic int gzclose(gzFile gz)
269275793eaSopenharmony_ci{
270275793eaSopenharmony_ci    z_stream *strm;
271275793eaSopenharmony_ci    unsigned char out[BUFLEN];
272275793eaSopenharmony_ci
273275793eaSopenharmony_ci    if (gz == NULL)
274275793eaSopenharmony_ci        return Z_STREAM_ERROR;
275275793eaSopenharmony_ci    strm = &(gz->strm);
276275793eaSopenharmony_ci    if (gz->write) {
277275793eaSopenharmony_ci        strm->next_in = Z_NULL;
278275793eaSopenharmony_ci        strm->avail_in = 0;
279275793eaSopenharmony_ci        do {
280275793eaSopenharmony_ci            strm->next_out = out;
281275793eaSopenharmony_ci            strm->avail_out = BUFLEN;
282275793eaSopenharmony_ci            (void)deflate(strm, Z_FINISH);
283275793eaSopenharmony_ci            fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
284275793eaSopenharmony_ci        } while (strm->avail_out == 0);
285275793eaSopenharmony_ci        deflateEnd(strm);
286275793eaSopenharmony_ci    }
287275793eaSopenharmony_ci    else
288275793eaSopenharmony_ci        inflateEnd(strm);
289275793eaSopenharmony_ci    fclose(gz->file);
290275793eaSopenharmony_ci    free(gz);
291275793eaSopenharmony_ci    return Z_OK;
292275793eaSopenharmony_ci}
293275793eaSopenharmony_ci
294275793eaSopenharmony_cistatic const char *gzerror(gzFile gz, int *err)
295275793eaSopenharmony_ci{
296275793eaSopenharmony_ci    *err = gz->err;
297275793eaSopenharmony_ci    return gz->msg;
298275793eaSopenharmony_ci}
299275793eaSopenharmony_ci
300275793eaSopenharmony_ci#endif
301275793eaSopenharmony_ci
302275793eaSopenharmony_cistatic char *prog;
303275793eaSopenharmony_ci
304275793eaSopenharmony_ci/* ===========================================================================
305275793eaSopenharmony_ci * Display error message and exit
306275793eaSopenharmony_ci */
307275793eaSopenharmony_cistatic void error(const char *msg)
308275793eaSopenharmony_ci{
309275793eaSopenharmony_ci    fprintf(stderr, "%s: %s\n", prog, msg);
310275793eaSopenharmony_ci    exit(1);
311275793eaSopenharmony_ci}
312275793eaSopenharmony_ci
313275793eaSopenharmony_ci#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
314275793eaSopenharmony_ci
315275793eaSopenharmony_ci/* Try compressing the input file at once using mmap. Return Z_OK if
316275793eaSopenharmony_ci * success, Z_ERRNO otherwise.
317275793eaSopenharmony_ci */
318275793eaSopenharmony_cistatic int gz_compress_mmap(FILE *in, gzFile out)
319275793eaSopenharmony_ci{
320275793eaSopenharmony_ci    int len;
321275793eaSopenharmony_ci    int err;
322275793eaSopenharmony_ci    int ifd = fileno(in);
323275793eaSopenharmony_ci    caddr_t buf;    /* mmap'ed buffer for the entire input file */
324275793eaSopenharmony_ci    off_t buf_len;  /* length of the input file */
325275793eaSopenharmony_ci    struct stat sb;
326275793eaSopenharmony_ci
327275793eaSopenharmony_ci    /* Determine the size of the file, needed for mmap: */
328275793eaSopenharmony_ci    if (fstat(ifd, &sb) < 0)
329275793eaSopenharmony_ci    {
330275793eaSopenharmony_ci        return Z_ERRNO;
331275793eaSopenharmony_ci    }
332275793eaSopenharmony_ci    buf_len = sb.st_size;
333275793eaSopenharmony_ci    if (buf_len <= 0)
334275793eaSopenharmony_ci    {
335275793eaSopenharmony_ci        return Z_ERRNO;
336275793eaSopenharmony_ci    }
337275793eaSopenharmony_ci
338275793eaSopenharmony_ci    /* Now do the actual mmap: */
339275793eaSopenharmony_ci    buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
340275793eaSopenharmony_ci    if (buf == (caddr_t)(-1))
341275793eaSopenharmony_ci    {
342275793eaSopenharmony_ci        return Z_ERRNO;
343275793eaSopenharmony_ci    }
344275793eaSopenharmony_ci
345275793eaSopenharmony_ci    /* Compress the whole file at once: */
346275793eaSopenharmony_ci    len = gzwrite(out, (char *)buf, (unsigned)buf_len);
347275793eaSopenharmony_ci
348275793eaSopenharmony_ci    if (len != (int)buf_len)
349275793eaSopenharmony_ci    {
350275793eaSopenharmony_ci        error(gzerror(out, &err));
351275793eaSopenharmony_ci    }
352275793eaSopenharmony_ci
353275793eaSopenharmony_ci    munmap(buf, buf_len);
354275793eaSopenharmony_ci    fclose(in);
355275793eaSopenharmony_ci    if (gzclose(out) != Z_OK)
356275793eaSopenharmony_ci    {
357275793eaSopenharmony_ci        error("failed gzclose");
358275793eaSopenharmony_ci    }
359275793eaSopenharmony_ci    return Z_OK;
360275793eaSopenharmony_ci}
361275793eaSopenharmony_ci#endif /* USE_MMAP */
362275793eaSopenharmony_ci
363275793eaSopenharmony_ci/* ===========================================================================
364275793eaSopenharmony_ci * Compress input to output then close both files.
365275793eaSopenharmony_ci */
366275793eaSopenharmony_ci
367275793eaSopenharmony_cistatic void gz_compress(FILE *in, gzFile out)
368275793eaSopenharmony_ci{
369275793eaSopenharmony_ci    local char buf[BUFLEN];
370275793eaSopenharmony_ci    int len;
371275793eaSopenharmony_ci    int err;
372275793eaSopenharmony_ci
373275793eaSopenharmony_ci#ifdef USE_MMAP
374275793eaSopenharmony_ci    /* Try first compressing with mmap. If mmap fails (minigzip used in a
375275793eaSopenharmony_ci     * pipe), use the normal fread loop.
376275793eaSopenharmony_ci     */
377275793eaSopenharmony_ci    if (gz_compress_mmap(in, out) == Z_OK) return;
378275793eaSopenharmony_ci#endif
379275793eaSopenharmony_ci    for (;;) {
380275793eaSopenharmony_ci        len = (int)fread(buf, 1, sizeof(buf), in);
381275793eaSopenharmony_ci        if (ferror(in)) {
382275793eaSopenharmony_ci            perror("fread");
383275793eaSopenharmony_ci            exit(1);
384275793eaSopenharmony_ci        }
385275793eaSopenharmony_ci        if (len == 0)
386275793eaSopenharmony_ci        {
387275793eaSopenharmony_ci            break;
388275793eaSopenharmony_ci        }
389275793eaSopenharmony_ci
390275793eaSopenharmony_ci        if (gzwrite(out, buf, (unsigned)len) != len)
391275793eaSopenharmony_ci        {
392275793eaSopenharmony_ci            error(gzerror(out, &err));
393275793eaSopenharmony_ci        }
394275793eaSopenharmony_ci    }
395275793eaSopenharmony_ci    fclose(in);
396275793eaSopenharmony_ci    if (gzclose(out) != Z_OK)
397275793eaSopenharmony_ci    {
398275793eaSopenharmony_ci        error("failed gzclose");
399275793eaSopenharmony_ci    }
400275793eaSopenharmony_ci}
401275793eaSopenharmony_ci
402275793eaSopenharmony_ci/* ===========================================================================
403275793eaSopenharmony_ci * Uncompress input to output then close both files.
404275793eaSopenharmony_ci */
405275793eaSopenharmony_cistatic void gz_uncompress(gzFile in, FILE *out)
406275793eaSopenharmony_ci{
407275793eaSopenharmony_ci    local char buf[BUFLEN];
408275793eaSopenharmony_ci    int len;
409275793eaSopenharmony_ci    int err;
410275793eaSopenharmony_ci
411275793eaSopenharmony_ci    for (;;) {
412275793eaSopenharmony_ci        len = gzread(in, buf, sizeof(buf));
413275793eaSopenharmony_ci        if (len < 0)
414275793eaSopenharmony_ci        {
415275793eaSopenharmony_ci            error (gzerror(in, &err));
416275793eaSopenharmony_ci        }
417275793eaSopenharmony_ci        if (len == 0)
418275793eaSopenharmony_ci        {
419275793eaSopenharmony_ci            break;
420275793eaSopenharmony_ci        }
421275793eaSopenharmony_ci
422275793eaSopenharmony_ci        if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
423275793eaSopenharmony_ci            error("failed fwrite");
424275793eaSopenharmony_ci        }
425275793eaSopenharmony_ci    }
426275793eaSopenharmony_ci    if (fclose(out))
427275793eaSopenharmony_ci    {
428275793eaSopenharmony_ci        error("failed fclose");
429275793eaSopenharmony_ci    }
430275793eaSopenharmony_ci
431275793eaSopenharmony_ci    if (gzclose(in) != Z_OK)
432275793eaSopenharmony_ci    {
433275793eaSopenharmony_ci        error("failed gzclose");
434275793eaSopenharmony_ci    }
435275793eaSopenharmony_ci}
436275793eaSopenharmony_ci
437275793eaSopenharmony_ci
438275793eaSopenharmony_ci/* ===========================================================================
439275793eaSopenharmony_ci * Compress the given file: create a corresponding .gz file and remove the
440275793eaSopenharmony_ci * original.
441275793eaSopenharmony_ci */
442275793eaSopenharmony_cistatic void file_compress(char *file, char *mode)
443275793eaSopenharmony_ci{
444275793eaSopenharmony_ci    local char outfile[MAX_NAME_LEN];
445275793eaSopenharmony_ci    FILE  *in;
446275793eaSopenharmony_ci    gzFile out;
447275793eaSopenharmony_ci
448275793eaSopenharmony_ci    if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
449275793eaSopenharmony_ci        fprintf(stderr, "%s: filename too long\n", prog);
450275793eaSopenharmony_ci        exit(1);
451275793eaSopenharmony_ci    }
452275793eaSopenharmony_ci
453275793eaSopenharmony_ci#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
454275793eaSopenharmony_ci    snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX);
455275793eaSopenharmony_ci#else
456275793eaSopenharmony_ci    strcpy(outfile, file);
457275793eaSopenharmony_ci    strcat(outfile, GZ_SUFFIX);
458275793eaSopenharmony_ci#endif
459275793eaSopenharmony_ci
460275793eaSopenharmony_ci    in = fopen(file, "rb");
461275793eaSopenharmony_ci    if (in == NULL) {
462275793eaSopenharmony_ci        perror(file);
463275793eaSopenharmony_ci        exit(1);
464275793eaSopenharmony_ci    }
465275793eaSopenharmony_ci    out = gzopen(outfile, mode);
466275793eaSopenharmony_ci    if (out == NULL) {
467275793eaSopenharmony_ci        fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
468275793eaSopenharmony_ci        exit(1);
469275793eaSopenharmony_ci    }
470275793eaSopenharmony_ci    gz_compress(in, out);
471275793eaSopenharmony_ci
472275793eaSopenharmony_ci    unlink(file);
473275793eaSopenharmony_ci}
474275793eaSopenharmony_ci
475275793eaSopenharmony_ci
476275793eaSopenharmony_ci/* ===========================================================================
477275793eaSopenharmony_ci * Uncompress the given file and remove the original.
478275793eaSopenharmony_ci */
479275793eaSopenharmony_cistatic void file_uncompress(char *file)
480275793eaSopenharmony_ci{
481275793eaSopenharmony_ci    local char buf[MAX_NAME_LEN];
482275793eaSopenharmony_ci    char *infile, *outfile;
483275793eaSopenharmony_ci    FILE  *out;
484275793eaSopenharmony_ci    gzFile in;
485275793eaSopenharmony_ci    z_size_t len = strlen(file);
486275793eaSopenharmony_ci
487275793eaSopenharmony_ci    if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
488275793eaSopenharmony_ci        fprintf(stderr, "%s: filename too long\n", prog);
489275793eaSopenharmony_ci        exit(1);
490275793eaSopenharmony_ci    }
491275793eaSopenharmony_ci
492275793eaSopenharmony_ci#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
493275793eaSopenharmony_ci    snprintf(buf, sizeof(buf), "%s", file);
494275793eaSopenharmony_ci#else
495275793eaSopenharmony_ci    strcpy(buf, file);
496275793eaSopenharmony_ci#endif
497275793eaSopenharmony_ci
498275793eaSopenharmony_ci    if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
499275793eaSopenharmony_ci        infile = file;
500275793eaSopenharmony_ci        outfile = buf;
501275793eaSopenharmony_ci        outfile[len-3] = '\0';
502275793eaSopenharmony_ci    } else {
503275793eaSopenharmony_ci        outfile = file;
504275793eaSopenharmony_ci        infile = buf;
505275793eaSopenharmony_ci#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
506275793eaSopenharmony_ci        snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX);
507275793eaSopenharmony_ci#else
508275793eaSopenharmony_ci        strcat(infile, GZ_SUFFIX);
509275793eaSopenharmony_ci#endif
510275793eaSopenharmony_ci    }
511275793eaSopenharmony_ci    in = gzopen(infile, "rb");
512275793eaSopenharmony_ci    if (in == NULL) {
513275793eaSopenharmony_ci        fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
514275793eaSopenharmony_ci        exit(1);
515275793eaSopenharmony_ci    }
516275793eaSopenharmony_ci    out = fopen(outfile, "wb");
517275793eaSopenharmony_ci    if (out == NULL) {
518275793eaSopenharmony_ci        perror(file);
519275793eaSopenharmony_ci        exit(1);
520275793eaSopenharmony_ci    }
521275793eaSopenharmony_ci
522275793eaSopenharmony_ci    gz_uncompress(in, out);
523275793eaSopenharmony_ci
524275793eaSopenharmony_ci    unlink(infile);
525275793eaSopenharmony_ci}
526275793eaSopenharmony_ci
527275793eaSopenharmony_ci
528275793eaSopenharmony_ci/* ===========================================================================
529275793eaSopenharmony_ci * Usage:  minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
530275793eaSopenharmony_ci *   -c : write to standard output
531275793eaSopenharmony_ci *   -d : decompress
532275793eaSopenharmony_ci *   -f : compress with Z_FILTERED
533275793eaSopenharmony_ci *   -h : compress with Z_HUFFMAN_ONLY
534275793eaSopenharmony_ci *   -r : compress with Z_RLE
535275793eaSopenharmony_ci *   -1 to -9 : compression level
536275793eaSopenharmony_ci */
537275793eaSopenharmony_ci
538275793eaSopenharmony_ciint main(int argc, char *argv[])
539275793eaSopenharmony_ci{
540275793eaSopenharmony_ci    int copyout = 0;
541275793eaSopenharmony_ci    int uncompr = 0;
542275793eaSopenharmony_ci    gzFile file;
543275793eaSopenharmony_ci    char *bname, outmode[20];
544275793eaSopenharmony_ci
545275793eaSopenharmony_ci#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
546275793eaSopenharmony_ci    snprintf(outmode, sizeof(outmode), "%s", "wb6 ");
547275793eaSopenharmony_ci#else
548275793eaSopenharmony_ci    strcpy(outmode, "wb6 ");
549275793eaSopenharmony_ci#endif
550275793eaSopenharmony_ci
551275793eaSopenharmony_ci    prog = argv[0];
552275793eaSopenharmony_ci    bname = strrchr(argv[0], '/');
553275793eaSopenharmony_ci    if (bname)
554275793eaSopenharmony_ci    {
555275793eaSopenharmony_ci      bname++;
556275793eaSopenharmony_ci    }
557275793eaSopenharmony_ci    else
558275793eaSopenharmony_ci    {
559275793eaSopenharmony_ci      bname = argv[0];
560275793eaSopenharmony_ci    }
561275793eaSopenharmony_ci    argc--, argv++;
562275793eaSopenharmony_ci
563275793eaSopenharmony_ci    if (!strcmp(bname, "gunzip"))
564275793eaSopenharmony_ci    {
565275793eaSopenharmony_ci      uncompr = 1;
566275793eaSopenharmony_ci    }
567275793eaSopenharmony_ci    else if (!strcmp(bname, "zcat"))
568275793eaSopenharmony_ci    {
569275793eaSopenharmony_ci      copyout = uncompr = 1;
570275793eaSopenharmony_ci    }
571275793eaSopenharmony_ci
572275793eaSopenharmony_ci    while (argc > 0) {
573275793eaSopenharmony_ci      if (strcmp(*argv, "-c") == 0)
574275793eaSopenharmony_ci      {
575275793eaSopenharmony_ci        copyout = 1;
576275793eaSopenharmony_ci      }
577275793eaSopenharmony_ci      else if (strcmp(*argv, "-d") == 0)
578275793eaSopenharmony_ci      {
579275793eaSopenharmony_ci        uncompr = 1;
580275793eaSopenharmony_ci      }
581275793eaSopenharmony_ci      else if (strcmp(*argv, "-f") == 0)
582275793eaSopenharmony_ci      {
583275793eaSopenharmony_ci        outmode[3] = 'f';
584275793eaSopenharmony_ci      }
585275793eaSopenharmony_ci      else if (strcmp(*argv, "-h") == 0)
586275793eaSopenharmony_ci      {
587275793eaSopenharmony_ci        outmode[3] = 'h';
588275793eaSopenharmony_ci      }
589275793eaSopenharmony_ci      else if (strcmp(*argv, "-r") == 0)
590275793eaSopenharmony_ci      {
591275793eaSopenharmony_ci        outmode[3] = 'R';
592275793eaSopenharmony_ci      }
593275793eaSopenharmony_ci      else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
594275793eaSopenharmony_ci               (*argv)[2] == 0)
595275793eaSopenharmony_ci      {
596275793eaSopenharmony_ci        outmode[2] = (*argv)[1];
597275793eaSopenharmony_ci      }
598275793eaSopenharmony_ci      else
599275793eaSopenharmony_ci      {
600275793eaSopenharmony_ci        break;
601275793eaSopenharmony_ci      }
602275793eaSopenharmony_ci      argc--, argv++;
603275793eaSopenharmony_ci    }
604275793eaSopenharmony_ci    if (outmode[3] == ' ')
605275793eaSopenharmony_ci    {
606275793eaSopenharmony_ci        outmode[3] = 0;
607275793eaSopenharmony_ci    }
608275793eaSopenharmony_ci    if (argc == 0) {
609275793eaSopenharmony_ci        SET_BINARY_MODE(stdin);
610275793eaSopenharmony_ci        SET_BINARY_MODE(stdout);
611275793eaSopenharmony_ci        if (uncompr) {
612275793eaSopenharmony_ci            file = gzdopen(fileno(stdin), "rb");
613275793eaSopenharmony_ci            if (file == NULL)
614275793eaSopenharmony_ci            {
615275793eaSopenharmony_ci                error("can't gzdopen stdin");
616275793eaSopenharmony_ci            }
617275793eaSopenharmony_ci            gz_uncompress(file, stdout);
618275793eaSopenharmony_ci        } else {
619275793eaSopenharmony_ci            file = gzdopen(fileno(stdout), outmode);
620275793eaSopenharmony_ci            if (file == NULL)
621275793eaSopenharmony_ci            {
622275793eaSopenharmony_ci                error("can't gzdopen stdout");
623275793eaSopenharmony_ci            }
624275793eaSopenharmony_ci            gz_compress(stdin, file);
625275793eaSopenharmony_ci        }
626275793eaSopenharmony_ci    } else {
627275793eaSopenharmony_ci        if (copyout) {
628275793eaSopenharmony_ci            SET_BINARY_MODE(stdout);
629275793eaSopenharmony_ci        }
630275793eaSopenharmony_ci        do {
631275793eaSopenharmony_ci            if (uncompr) {
632275793eaSopenharmony_ci                if (copyout) {
633275793eaSopenharmony_ci                    file = gzopen(*argv, "rb");
634275793eaSopenharmony_ci                    if (file == NULL)
635275793eaSopenharmony_ci                    {
636275793eaSopenharmony_ci                        fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
637275793eaSopenharmony_ci                    }
638275793eaSopenharmony_ci                    else
639275793eaSopenharmony_ci                    {
640275793eaSopenharmony_ci                        gz_uncompress(file, stdout);
641275793eaSopenharmony_ci                    }
642275793eaSopenharmony_ci                } else {
643275793eaSopenharmony_ci                    file_uncompress(*argv);
644275793eaSopenharmony_ci                }
645275793eaSopenharmony_ci            } else {
646275793eaSopenharmony_ci                if (copyout) {
647275793eaSopenharmony_ci                    FILE * in = fopen(*argv, "rb");
648275793eaSopenharmony_ci
649275793eaSopenharmony_ci                    if (in == NULL) {
650275793eaSopenharmony_ci                        perror(*argv);
651275793eaSopenharmony_ci                    } else {
652275793eaSopenharmony_ci                        file = gzdopen(fileno(stdout), outmode);
653275793eaSopenharmony_ci                        if (file == NULL)
654275793eaSopenharmony_ci                        {
655275793eaSopenharmony_ci                            error("can't gzdopen stdout");
656275793eaSopenharmony_ci                        }
657275793eaSopenharmony_ci
658275793eaSopenharmony_ci                        gz_compress(in, file);
659275793eaSopenharmony_ci                    }
660275793eaSopenharmony_ci
661275793eaSopenharmony_ci                } else {
662275793eaSopenharmony_ci                    file_compress(*argv, outmode);
663275793eaSopenharmony_ci                }
664275793eaSopenharmony_ci            }
665275793eaSopenharmony_ci        } while (argv++, --argc);
666275793eaSopenharmony_ci    }
667275793eaSopenharmony_ci    return 0;
668275793eaSopenharmony_ci}
669