📄 extract.c
字号:
/*--------------------------------------------------------------------------- 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_member() TestExtraField() test_compr_eb() memextract() memflush() fnfilter() ---------------------------------------------------------------------------*/#define EXTRACT_C#define UNZIP_INTERNAL#include "unzip.h"#include "crypt.h"#ifdef WINDLL# ifdef POCKET_UNZIP# include "wince/intrface.h"# else# include "windll/windll.h"# endif#endif#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));static 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#ifdef SET_DIR_ATTRIB static int 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 CmprEnDeflate[] = "enhanced deflate"; static ZCONST char Far CmprDCLImplode[] = "DCL implode"; static ZCONST char Far *ComprNames[NUM_METHODS] = { CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce, CmprImplode, CmprTokenize, CmprDeflate, CmprEnDeflate, CmprDCLImplode };#endif /* !SFX */static ZCONST char Far FilNamMsg[] = "%s: bad filename length (%s)\n";static ZCONST char Far ExtFieldMsg[] = "%s: bad extra field length (%s)\n";static ZCONST char Far OffsetMsg[] = "file #%u: 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 #%u: 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 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";#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[] = "%u 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 %u file%s tested.\n";static ZCONST char Far FilesSkipped[] = "%u 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{ uch *cd_inptr; unsigned i, j, filnum=0, blknum=0; int cd_incnt, renamed, query; int error, error_in_archive=PK_COOL, *fn_matched=NULL, *xn_matched=NULL;#ifdef WINDLL int done_once = 0;#else extent len;#endif unsigned members_remaining, num_skipped=0, num_bad_pwd=0; long cd_bufstart, bufstart, inbuf_offset, request; LONGINT old_extra_bytes = 0L;#ifdef SET_DIR_ATTRIB unsigned num_dirs=0; dirtime *dirlist=(dirtime *)NULL, **sorted_dirlist=(dirtime **)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 the outer one loops over blocks. There's some file-pointer positioning stuff in between, but that's about it. Btw, it's because of this jump- ing around that we can afford to be lenient if an error occurs in one of the member files: we should still be able to go find the other members, since we know the offset of each from the beginning of the zipfile. ---------------------------------------------------------------------------*/ G.pInfo = G.info; members_remaining = (unsigned)G.ecrec.total_entries_central_dir;#if CRYPT G.newzip = TRUE;#endif#ifndef SFX G.reported_backslash = FALSE;#endif /* malloc space for check on unmatched filespecs (OK if one or both NULL) */ if (G.filespecs > 0 && (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL) for (i = 0; i < G.filespecs; ++i) fn_matched[i] = FALSE; if (G.xfilespecs > 0 && (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL) for (i = 0; i < G.xfilespecs; ++i) xn_matched[i] = FALSE;/*--------------------------------------------------------------------------- Begin main loop over blocks of member files. We know the entire central directory is on this disk: we would not have any of this information un- less the end-of-central-directory record was on this disk, and we would not have gotten to this routine unless this is also the disk on which the central directory starts. In practice, this had better be the ONLY disk in the archive, but we'll add multi-disk support soon. ---------------------------------------------------------------------------*/ while (members_remaining) { j = 0;#ifdef AMIGA memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *));#endif /* * Loop through files in central directory, storing offsets, file * attributes, case-conversion and text-conversion flags until block * size is reached. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -