📄 extract.c
字号:
/* Copyright (c) 1990-2005 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html*//*--------------------------------------------------------------------------- extract.c This file contains the high-level routines ("driver routines") for extrac- ting and testing zipfile members. It calls the low-level routines in files explode.c, inflate.c, unreduce.c and unshrink.c. Contains: extract_or_test_files() store_info() extract_or_test_entrylist() extract_or_test_member() TestExtraField() test_compr_eb() memextract() memflush() extract_izvms_block() (VMS or VMS_TEXT_CONV) set_deferred_symlink() (SYMLINKS only) fnfilter() ---------------------------------------------------------------------------*/#define __EXTRACT_C /* identifies this source module */#define UNZIP_INTERNAL#include "unzip.h"#ifdef WINDLL# ifdef POCKET_UNZIP# include "wince/intrface.h"# else# include "windll/windll.h"# endif#endif#include "crypt.h"#define GRRDUMP(buf,len) { \ int i, j; \ \ for (j = 0; j < (len)/16; ++j) { \ printf(" "); \ for (i = 0; i < 16; ++i) \ printf("%02x ", (uch)(buf)[i+(j<<4)]); \ printf("\n "); \ for (i = 0; i < 16; ++i) { \ char c = (char)(buf)[i+(j<<4)]; \ \ if (c == '\n') \ printf("\\n "); \ else if (c == '\r') \ printf("\\r "); \ else \ printf(" %c ", c); \ } \ printf("\n"); \ } \ if ((len) % 16) { \ printf(" "); \ for (i = j<<4; i < (len); ++i) \ printf("%02x ", (uch)(buf)[i]); \ printf("\n "); \ for (i = j<<4; i < (len); ++i) { \ char c = (char)(buf)[i]; \ \ if (c == '\n') \ printf("\\n "); \ else if (c == '\r') \ printf("\\r "); \ else \ printf(" %c ", c); \ } \ printf("\n"); \ } \}static int store_info OF((__GPRO));#ifdef SET_DIR_ATTRIBstatic int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk, ulg *pfilnum, ulg *pnum_bad_pwd, Z_OFF_T *pold_extra_bytes, unsigned *pnum_dirs, direntry **pdirlist, int error_in_archive));#elsestatic int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk, ulg *pfilnum, ulg *pnum_bad_pwd, Z_OFF_T *pold_extra_bytes, int error_in_archive));#endifstatic int extract_or_test_member OF((__GPRO));#ifndef SFX static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len)); static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size, unsigned compr_offset, int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size, uch *eb_ucptr, ulg eb_ucsize)));#endif#if (defined(VMS) || defined(VMS_TEXT_CONV)) static void decompress_bits OF((uch *outptr, unsigned needlen, ZCONST uch *bitptr));#endif#ifdef SYMLINKS static void set_deferred_symlink OF((__GPRO__ slinkentry *slnk_entry));#endif#ifdef SET_DIR_ATTRIB static int Cdecl dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b));#endif/*******************************//* Strings used in extract.c *//*******************************/static ZCONST char Far VersionMsg[] = " skipping: %-22s need %s compat. v%u.%u (can do v%u.%u)\n";static ZCONST char Far ComprMsgNum[] = " skipping: %-22s unsupported compression method %u\n";#ifndef SFX static ZCONST char Far ComprMsgName[] = " skipping: %-22s `%s' method not supported\n"; static ZCONST char Far CmprNone[] = "store"; static ZCONST char Far CmprShrink[] = "shrink"; static ZCONST char Far CmprReduce[] = "reduce"; static ZCONST char Far CmprImplode[] = "implode"; static ZCONST char Far CmprTokenize[] = "tokenize"; static ZCONST char Far CmprDeflate[] = "deflate"; static ZCONST char Far CmprDeflat64[] = "deflate64"; static ZCONST char Far CmprDCLImplode[] = "DCL implode"; static ZCONST char Far *ComprNames[NUM_METHODS] = { CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce, CmprImplode, CmprTokenize, CmprDeflate, CmprDeflat64, CmprDCLImplode };#endif /* !SFX */static ZCONST char Far FilNamMsg[] = "%s: bad filename length (%s)\n";#ifndef SFX static ZCONST char Far WarnNoMemCFName[] = "%s: warning, no memory for comparison with local header\n"; static ZCONST char Far LvsCFNamMsg[] = "%s: mismatching \"local\" filename (%s),\n\ continuing with \"central\" filename version\n";#endif /* !SFX */static ZCONST char Far WrnStorUCSizCSizDiff[] = "%s: ucsize %lu <> csize %lu for STORED entry\n\ continuing with \"compressed\" size value\n";static ZCONST char Far ExtFieldMsg[] = "%s: bad extra field length (%s)\n";static ZCONST char Far OffsetMsg[] = "file #%lu: bad zipfile offset (%s): %ld\n";static ZCONST char Far ExtractMsg[] = "%8sing: %-22s %s%s";#ifndef SFX static ZCONST char Far LengthMsg[] = "%s %s: %ld bytes required to uncompress to %lu bytes;\n %s\ supposed to require %lu bytes%s%s%s\n";#endifstatic ZCONST char Far BadFileCommLength[] = "%s: bad file comment length\n";static ZCONST char Far LocalHdrSig[] = "local header sig";static ZCONST char Far BadLocalHdr[] = "file #%lu: bad local header\n";static ZCONST char Far AttemptRecompensate[] = " (attempting to re-compensate)\n";#ifndef SFX static ZCONST char Far BackslashPathSep[] = "warning: %s appears to use backslashes as path separators\n";#endifstatic ZCONST char Far AbsolutePathWarning[] = "warning: stripped absolute path spec from %s\n";static ZCONST char Far SkipVolumeLabel[] = " skipping: %-22s %svolume label\n";#ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */ static ZCONST char Far DirlistEntryNoMem[] = "warning: cannot alloc memory for dir times/permissions/UID/GID\n"; static ZCONST char Far DirlistSortNoMem[] = "warning: cannot alloc memory to sort dir times/perms/etc.\n"; static ZCONST char Far DirlistSetAttrFailed[] = "warning: set times/attribs failed for %s\n"; static ZCONST char Far DirlistFailAttrSum[] = " failed setting attrib/times for %lu dir entries";#endif#ifdef SYMLINKS /* messages of the deferred symlinks handler */ static ZCONST char Far SymLnkWarnNoMem[] = "warning: deferred symlink (%s) failed:\n\ out of memory\n"; static ZCONST char Far SymLnkWarnInvalid[] = "warning: deferred symlink (%s) failed:\n\ invalid placeholder file\n"; static ZCONST char Far SymLnkDeferred[] = "finishing deferred symbolic links:\n"; static ZCONST char Far SymLnkFinish[] = " %-22s -> %s\n";#endif#ifndef WINDLL static ZCONST char Far ReplaceQuery[] = "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: "; static ZCONST char Far AssumeNone[] = " NULL\n(assuming [N]one)\n"; static ZCONST char Far NewNameQuery[] = "new name: "; static ZCONST char Far InvalidResponse[] = "error: invalid response [%c]\n";#endif /* !WINDLL */static ZCONST char Far ErrorInArchive[] = "At least one %serror was detected in %s.\n";static ZCONST char Far ZeroFilesTested[] = "Caution: zero files tested in %s.\n";#ifndef VMS static ZCONST char Far VMSFormatQuery[] = "\n%s: stored in VMS format. Extract anyway? (y/n) ";#endif#if CRYPT static ZCONST char Far SkipCannotGetPasswd[] = " skipping: %-22s unable to get password\n"; static ZCONST char Far SkipIncorrectPasswd[] = " skipping: %-22s incorrect password\n"; static ZCONST char Far FilesSkipBadPasswd[] = "%lu file%s skipped because of incorrect password.\n"; static ZCONST char Far MaybeBadPasswd[] = " (may instead be incorrect password)\n";#else static ZCONST char Far SkipEncrypted[] = " skipping: %-22s encrypted (not supported)\n";#endifstatic ZCONST char Far NoErrInCompData[] = "No errors detected in compressed data of %s.\n";static ZCONST char Far NoErrInTestedFiles[] = "No errors detected in %s for the %lu file%s tested.\n";static ZCONST char Far FilesSkipped[] = "%lu file%s skipped because of unsupported compression or encoding.\n";static ZCONST char Far ErrUnzipFile[] = " error: %s%s %s\n";static ZCONST char Far ErrUnzipNoFile[] = "\n error: %s%s\n";static ZCONST char Far NotEnoughMem[] = "not enough memory to ";static ZCONST char Far InvalidComprData[] = "invalid compressed data to ";static ZCONST char Far Inflate[] = "inflate";#ifndef SFX static ZCONST char Far Explode[] = "explode";#ifndef LZW_CLEAN static ZCONST char Far Unshrink[] = "unshrink";#endif#endif#if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK)) static ZCONST char Far FileTruncated[] = "warning: %s is probably truncated\n";#endifstatic ZCONST char Far FileUnknownCompMethod[] = "%s: unknown compression method\n";static ZCONST char Far BadCRC[] = " bad CRC %08lx (should be %08lx)\n"; /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s";char ZCONST Far TruncNTSD[] = " compressed WinNT security data missing (%d bytes)%s";#ifndef SFX static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \ EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n"; static ZCONST char Far InvalidComprDataEAs[] = " invalid compressed data for EAs\n";# if (defined(WIN32) && defined(NTSD_EAS)) static ZCONST char Far InvalidSecurityEAs[] = " EAs fail security check\n";# endif static ZCONST char Far UnsuppNTSDVersEAs[] = " unsupported NTSD EAs version %d\n"; static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributes\n"; static ZCONST char Far UnknComprMethodEAs[] = " unknown compression method for EAs (%u)\n"; static ZCONST char Far NotEnoughMemEAs[] = " out of memory while inflating EAs\n"; static ZCONST char Far UnknErrorEAs[] = " unknown error on extended attributes\n";#endif /* !SFX */static ZCONST char Far UnsupportedExtraField[] = "\nerror: unsupported extra-field compression type (%u)--skipping\n";static ZCONST char Far BadExtraFieldCRC[] = "error [%s]: bad extra-field CRC %08lx (should be %08lx)\n";/**************************************//* Function extract_or_test_files() *//**************************************/int extract_or_test_files(__G) /* return PK-type error code */ __GDEF{ unsigned i, j; Z_OFF_T cd_bufstart; uch *cd_inptr; int cd_incnt; ulg filnum=0L, blknum=0L; int reached_end, no_endsig_found; int error, error_in_archive=PK_COOL; int *fn_matched=NULL, *xn_matched=NULL; unsigned members_processed; ulg num_skipped=0L, num_bad_pwd=0L; Z_OFF_T old_extra_bytes = 0L;#ifdef SET_DIR_ATTRIB unsigned num_dirs=0; direntry *dirlist=(direntry *)NULL, **sorted_dirlist=(direntry **)NULL;#endif/*--------------------------------------------------------------------------- The basic idea of this function is as follows. Since the central di- rectory lies at the end of the zipfile and the member files lie at the beginning or middle or wherever, it is not very desirable to simply read a central directory entry, jump to the member and extract it, and then jump back to the central directory. In the case of a large zipfile this would lead to a whole lot of disk-grinding, especially if each mem- ber file is small. Instead, we read from the central directory the per- tinent information for a block of files, then go extract/test the whole block. Thus this routine contains two small(er) loops within a very large outer loop: the first of the small ones reads a block of files from the central directory; the second extracts or tests each file; and
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -