ยปCore Development>Code coverage>Modules/zlib/minigzip.c

Python code coverage for Modules/zlib/minigzip.c

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