📄 funzip.c
字号:
int flush(w) /* used by inflate.c (FLUSH macro) */ulg w; /* number of bytes to flush */{ G.crc32val = crc32(G.crc32val, slide, (extent)w); if (fwrite((char *)slide,1,(extent)w,out) != (extent)w && !PIPE_ERROR) err(9, "out of space on stdout"); outsiz += w; return 0;}#endif /* ?(USE_DEFLATE64 && __16BIT__) */int main(argc, argv)int argc;char **argv;/* Given a zipfile on stdin, decompress the first entry to stdout. */{ ush n; uch h[LOCHDR]; /* first local header (GZPHDR < LOCHDR) */ int g = 0; /* true if gzip format */ unsigned method = 0; /* initialized here to shut up gcc warning */#if CRYPT char *s = " [-password]"; char *p; /* password */#else /* !CRYPT */ char *s = "";#endif /* ?CRYPT */ CONSTRUCTGLOBALS(); /* skip executable name */ argc--; argv++;#if CRYPT /* get the command line password, if any */ p = (char *)NULL; if (argc && **argv == '-') { argc--; p = 1 + *argv++; }#endif /* CRYPT */#ifdef MALLOC_WORK /* The following expression is a cooked-down simplyfication of the calculation for the work area size of UnZip (see unzip.c). For fUnZip, the work area does not need to match the granularity of the complex unshrink structures, because it only supports inflation. But, like in UnZip, the zcalloc() wrapper function is needed for the allocation, to support the 64kByte buffer on 16-bit systems. */# define UZ_SLIDE_CHUNK (sizeof(shrint)+sizeof(uch)+sizeof(uch))# define UZ_NUMOF_CHUNKS (unsigned)( (WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK ) G.area.Slide = (uch *)zcalloc(UZ_NUMOF_CHUNKS, UZ_SLIDE_CHUNK);# undef UZ_SLIDE_CHUNK# undef UZ_NUMOF_CHUNKS#endif /* if no file argument and stdin not redirected, give the user help */ if (argc == 0 && isatty(0)) { Info(slide, 1, ((char *)slide, "fUnZip (filter UnZip), version %s\n", VERSION)); Info(slide, 1, ((char *)slide, "usage: ... | funzip%s | ...\n", s)); Info(slide, 1, ((char *)slide, " ... | funzip%s > outfile\n", s)); Info(slide, 1, ((char *)slide, " funzip%s infile.zip > outfile\n",s)); Info(slide, 1, ((char *)slide, " funzip%s infile.gz > outfile\n", s)); Info(slide, 1, ((char *)slide, "Extracts to stdout the gzip file or first\ zip entry of stdin or the given file.\n")); DESTROYGLOBALS(); EXIT(3); } /* prepare to be a binary filter */ if (argc) { if ((G.in = fopen(*argv, FOPR)) == (FILE *)NULL) err(2, "cannot find input file"); } else {#ifdef DOS_FLX_NLM_OS2_W32#if (defined(__HIGHC__) && !defined(FLEXOS)) setmode(stdin, _BINARY);#else setmode(0, O_BINARY); /* some buggy C libraries require BOTH setmode() */#endif /* call AND the fdopen() in binary mode :-( */#endif /* DOS_FLX_NLM_OS2_W32 */#ifdef RISCOS G.in = stdin;#else if ((G.in = fdopen(0, FOPR)) == (FILE *)NULL) err(2, "cannot find stdin");#endif }#ifdef DOS_FLX_H68_NLM_OS2_W32#if (defined(__HIGHC__) && !defined(FLEXOS)) setmode(stdout, _BINARY);#else setmode(1, O_BINARY);#endif#endif /* DOS_FLX_H68_NLM_OS2_W32 */#ifdef RISCOS out = stdout;#else if ((out = fdopen(1, FOPW)) == (FILE *)NULL) err(2, "cannot write to stdout");#endif /* read local header, check validity, and skip name and extra fields */ n = getc(G.in); n |= getc(G.in) << 8; if (n == ZIPMAG) { if (fread((char *)h, 1, LOCHDR, G.in) != LOCHDR || SH(h) != LOCREM) err(3, "invalid zipfile"); switch (method = SH(h + LOCHOW)) { case STORED: case DEFLATED:#ifdef USE_DEFLATE64 case ENHDEFLATED:#endif break; default: err(3, "first entry not deflated or stored--cannot unpack"); break; } for (n = SH(h + LOCFIL); n--; ) g = getc(G.in); for (n = SH(h + LOCEXT); n--; ) g = getc(G.in); g = 0; encrypted = h[LOCFLG] & CRPFLG; } else if (n == GZPMAG) { if (fread((char *)h, 1, GZPHDR, G.in) != GZPHDR) err(3, "invalid gzip file"); if ((method = h[GZPHOW]) != DEFLATED && method != ENHDEFLATED) err(3, "gzip file not deflated"); if (h[GZPFLG] & GZPMUL) err(3, "cannot handle multi-part gzip files"); if (h[GZPFLG] & GZPISX) { n = getc(G.in); n |= getc(G.in) << 8; while (n--) g = getc(G.in); } if (h[GZPFLG] & GZPISF) while ((g = getc(G.in)) != 0 && g != EOF) ; if (h[GZPFLG] & GZPISC) while ((g = getc(G.in)) != 0 && g != EOF) ; g = 1; encrypted = h[GZPFLG] & GZPISE; } else err(3, "input not a zip or gzip file"); /* if entry encrypted, decrypt and validate encryption header */ if (encrypted)#if CRYPT { ush i, e; if (p == (char *)NULL) { if ((p = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL) err(1, "out of memory"); else if ((p = getp("Enter password: ", p, IZ_PWLEN+1)) == (char *)NULL) err(1, "no tty to prompt for password"); }#if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB)) /* initialize crc_32_tab pointer for decryption */ CRC_32_TAB = (ZCONST ulg Far *)get_crc_table();#endif init_keys(p); for (i = 0; i < RAND_HEAD_LEN; i++) e = NEXTBYTE; if (e != (ush)(h[LOCFLG] & EXTFLG ? h[LOCTIM + 1] : h[LOCCRC + 3])) err(3, "incorrect password for first entry"); }#else /* !CRYPT */ err(3, "cannot decrypt entry (need to recompile with full crypt.c)");#endif /* ?CRYPT */ /* prepare output buffer and crc */ G.outptr = slide; G.outcnt = 0L; outsiz = 0L; G.crc32val = CRCVAL_INITIAL; /* decompress */ if (g || h[LOCHOW]) { /* deflated entry */ int r;#ifdef USE_ZLIB /* need to allocate and prepare input buffer */ if ((G.inbuf = (uch *)malloc(INBUFSIZ)) == (uch *)NULL) err(1, "out of memory");#endif /* USE_ZLIB */ if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) { if (r == 3) err(1, "out of memory"); else err(4, "invalid compressed data--format violated"); } inflate_free(__G); } else { /* stored entry */ register ulg n; n = LG(h + LOCLEN);#if CRYPT if (n != LG(h + LOCSIZ) - (encrypted ? RAND_HEAD_LEN : 0)) {#else if (n != LG(h + LOCSIZ)) {#endif Info(slide, 1, ((char *)slide, "len %ld, siz %ld\n", n, LG(h + LOCSIZ))); err(4, "invalid compressed data--length mismatch"); } while (n--) { ush c = getc(G.in);#if CRYPT if (encrypted) zdecode(c);#endif *G.outptr++ = (uch)c;#if (defined(USE_DEFLATE64) && defined(__16BIT__)) if (++G.outcnt == (WSIZE>>1)) /* do FlushOutput() */#else if (++G.outcnt == WSIZE) /* do FlushOutput() */#endif { G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt); if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt && !PIPE_ERROR) err(9, "out of space on stdout"); outsiz += G.outcnt; G.outptr = slide; G.outcnt = 0L; } } } if (G.outcnt) /* flush one last time; no need to reset G.outptr/outcnt */ { G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt); if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt && !PIPE_ERROR) err(9, "out of space on stdout"); outsiz += G.outcnt; } fflush(out); /* if extended header, get it */ if (g) { if (fread((char *)h + LOCCRC, 1, 8, G.in) != 8) err(3, "gzip file ended prematurely"); } else if ((h[LOCFLG] & EXTFLG) && fread((char *)h + LOCCRC - 4, 1, EXTHDR, G.in) != EXTHDR) err(3, "zipfile ended prematurely"); /* validate decompression */ if (LG(h + LOCCRC) != G.crc32val) err(4, "invalid compressed data--crc error"); if (LG((g ? (h + LOCSIZ) : (h + LOCLEN))) != outsiz) err(4, "invalid compressed data--length error"); /* check if there are more entries */ if (!g && fread((char *)h, 1, 4, G.in) == 4 && LG(h) == LOCSIG) Info(slide, 1, ((char *)slide, "funzip warning: zipfile has more than one entry--rest ignored\n")); DESTROYGLOBALS(); RETURN (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -