📄 unzip.c
字号:
++NumLoseFiles;
else
++NumWinFiles;
if (error > error_in_archive)
error_in_archive = error;
Trace((stderr, "do_seekable(1) returns %d\n", error));
}
#endif /* ?SFX */
FFLUSH(stdout);
FFLUSH(stderr);
/*---------------------------------------------------------------------------
Print summary of all zipfiles, assuming zipfile spec was a wildcard (no
need for a summary if just one zipfile).
---------------------------------------------------------------------------*/
#ifndef SFX
if (iswild(wildzipfn)) {
if (NumMissFiles + NumLoseFiles + NumWarnFiles > 0 || NumWinFiles != 1)
FPRINTF(stderr, "\n");
if ((NumWinFiles > 1) || (NumWinFiles == 1 &&
NumMissDirs + NumMissFiles + NumLoseFiles + NumWarnFiles > 0))
FPRINTF(stderr, LoadFarString(FilesProcessOK),
NumWinFiles, (NumWinFiles == 1)? " was" : "s were");
if (NumWarnFiles > 0)
FPRINTF(stderr, LoadFarString(ArchiveWarning),
NumWarnFiles, (NumWarnFiles == 1)? "" : "s");
if (NumLoseFiles > 0)
FPRINTF(stderr, LoadFarString(ArchiveFatalError),
NumLoseFiles, (NumLoseFiles == 1)? "" : "s");
if (NumMissFiles > 0)
FPRINTF(stderr, LoadFarString(FileHadNoZipfileDir),
NumMissFiles, (NumMissFiles == 1)? "" : "s");
if (NumMissDirs == 1)
FPRINTF(stderr, LoadFarString(ZipfileWasDir));
else if (NumMissDirs > 0)
FPRINTF(stderr, LoadFarString(ManyZipfilesWereDir), NumMissDirs);
if (NumWinFiles + NumLoseFiles + NumWarnFiles == 0)
FPRINTF(stderr, LoadFarString(NoZipfileFound));
}
#endif /* !SFX */
/* free allocated memory */
inflate_free();
checkdir((char *)NULL, END);
#ifndef SMALL_MEM
if (outbuf2)
free(outbuf2); /* malloc'd ONLY if unshrink and -a */
#endif
free(outbuf);
free(inbuf);
return error_in_archive;
} /* end function process_zipfiles() */
/**************************/
/* Function do_seekable() */
/**************************/
int do_seekable(lastchance) /* return PK-type error code */
int lastchance;
{
#ifndef SFX
static int no_ecrec = FALSE;
int maybe_exe=FALSE;
#endif
int error=0, error_in_archive;
/*---------------------------------------------------------------------------
Open the zipfile for reading in BINARY mode to prevent CR/LF translation,
which would corrupt the bit streams.
---------------------------------------------------------------------------*/
if (SSTAT(zipfn, &statbuf) || (error = S_ISDIR(statbuf.st_mode)) != 0) {
#ifndef SFX
if (lastchance)
if (no_ecrec)
FPRINTF(stderr, LoadFarString(CantFindZipfileDirMsg),
zipinfo_mode? "zipinfo" : "unzip",
wildzipfn, zipinfo_mode? " " : "",
#ifdef UNIX
wildzipfn,
#endif
zipfn);
else
FPRINTF(stderr,
LoadFarString(CantFindEitherZipfile),
zipinfo_mode? "zipinfo" : "unzip", wildzipfn,
#ifdef UNIX
wildzipfn,
#endif
zipfn);
#endif /* !SFX */
return error? IZ_DIR : PK_NOZIP;
}
ziplen = statbuf.st_size;
#ifndef SFX
#if defined(UNIX) || defined(DOS_NT_OS2)
if (statbuf.st_mode & S_IEXEC) /* no extension on Unix exec's: might */
maybe_exe = TRUE; /* find unzip, not unzip.zip; etc. */
#endif
#endif /* !SFX */
#ifdef VMS
if (check_format()) /* check for variable-length format */
return PK_ERR;
#endif
if (open_input_file()) /* this should never happen, given */
return PK_NOZIP; /* the stat() test above, but... */
/*---------------------------------------------------------------------------
Find and process the end-of-central-directory header. UnZip need only
check last 65557 bytes of zipfile: comment may be up to 65535, end-of-
central-directory record is 18 bytes, and signature itself is 4 bytes;
add some to allow for appended garbage. Since ZipInfo is often used as
a debugging tool, search the whole zipfile if zipinfo_mode is true.
---------------------------------------------------------------------------*/
cur_zipfile_bufstart = 0;
inptr = inbuf;
if (!qflag && !zipinfo_mode)
PRINTF("Archive: %s\n", zipfn);
if ((
#ifndef NO_ZIPINFO
zipinfo_mode &&
((error_in_archive = find_ecrec(ziplen)) != 0 ||
(error_in_archive = zi_end_central()) > PK_WARN))
|| (!zipinfo_mode &&
#endif
((error_in_archive = find_ecrec(MIN(ziplen,66000L))) != 0 ||
(error_in_archive = uz_end_central()) > PK_WARN)))
{
close(zipfd);
#ifdef SFX
++lastchance; /* avoid picky compiler warnings */
return error_in_archive;
#else
if (maybe_exe)
FPRINTF(stderr, LoadFarString(MaybeExe), zipfn);
if (lastchance)
return error_in_archive;
else {
no_ecrec = TRUE; /* assume we found wrong file: e.g., */
return PK_NOZIP; /* unzip instead of unzip.zip */
}
#endif /* ?SFX */
}
if ((zflag > 0) && !zipinfo_mode) { /* in unzip, zflag = comment ONLY */
close(zipfd);
return error_in_archive;
}
/*---------------------------------------------------------------------------
Test the end-of-central-directory info for incompatibilities (multi-disk
archives) or inconsistencies (missing or extra bytes in zipfile).
---------------------------------------------------------------------------*/
#ifdef NO_MULTIPART
error = !zipinfo_mode && (ecrec.number_this_disk == 1) &&
(ecrec.num_disk_with_start_central_dir == 1);
#else
error = !zipinfo_mode && (ecrec.number_this_disk != 0);
#endif
#ifndef SFX
if (zipinfo_mode &&
ecrec.number_this_disk != ecrec.num_disk_with_start_central_dir)
{
FPRINTF(stderr, LoadFarString(CentDirNotInZipMsg));
error_in_archive = PK_FIND;
#ifdef NO_MULTIPART /* concatenation of multiple parts works in some cases */
} else if (!zipinfo_mode && !error && ecrec.number_this_disk != 0) {
FPRINTF(stderr, LoadFarString(NoMultiDiskArcSupport), zipfn);
error_in_archive = PK_FIND;
#endif
} else { /* this is a (relatively) normal zipfile: process normally */
if (error) {
FPRINTF(stderr, LoadFarString(MaybePakBug), zipfn);
error_in_archive = PK_WARN;
}
#endif
if ((extra_bytes = real_ecrec_offset-expect_ecrec_offset) < (LONGINT)0)
{
FPRINTF(stderr, LoadFarString(MissingBytes), zipfn,
(long)(-extra_bytes));
error_in_archive = PK_ERR;
} else if (extra_bytes > 0) {
if ((ecrec.offset_start_central_directory == 0) &&
(ecrec.size_central_directory != 0)) /* zip 1.5 -go bug */
{
FPRINTF(stderr, LoadFarString(NullCentDirOffset), zipfn);
ecrec.offset_start_central_directory = extra_bytes;
extra_bytes = 0;
error_in_archive = PK_ERR;
}
#ifndef SFX
else {
FPRINTF(stderr, LoadFarString(ExtraBytesAtStart), zipfn,
(long)extra_bytes);
error_in_archive = PK_WARN;
}
#endif
}
/*-----------------------------------------------------------------------
Check for empty zipfile and exit now if so.
-----------------------------------------------------------------------*/
if (expect_ecrec_offset == 0L && ecrec.size_central_directory == 0) {
if (zipinfo_mode)
PRINTF("%sEmpty zipfile.\n", lflag>9 ? "\n " : "");
else
FPRINTF(stderr, LoadFarString(ZipfileEmpty), zipfn);
close(zipfd);
return (error_in_archive > PK_WARN)? error_in_archive : PK_WARN;
}
/*-----------------------------------------------------------------------
Compensate for missing or extra bytes, and seek to where the start
of central directory should be. If header not found, uncompensate
and try again (necessary for at least some Atari archives created
with STZip, as well as archives created by J.H. Holm's ZIPSPLIT 1.1).
-----------------------------------------------------------------------*/
LSEEK( ecrec.offset_start_central_directory )
#ifdef OLD_SEEK_TEST
if (readbuf(sig, 4) == 0) {
close(zipfd);
return PK_ERR; /* file may be locked, or possibly disk error(?) */
}
if (strncmp(sig, central_hdr_sig, 4))
#else
if ((readbuf(sig, 4) == 0) || strncmp(sig, central_hdr_sig, 4))
#endif
{
long tmp = extra_bytes;
extra_bytes = 0;
LSEEK( ecrec.offset_start_central_directory )
if ((readbuf(sig, 4) == 0) || strncmp(sig, central_hdr_sig, 4)) {
FPRINTF(stderr, LoadFarString(CentDirStartNotFound), zipfn,
LoadFarStringSmall(ReportMsg));
close(zipfd);
return PK_BADERR;
}
FPRINTF(stderr, LoadFarString(CentDirTooLong), zipfn, -tmp);
error_in_archive = PK_ERR;
}
/*-----------------------------------------------------------------------
Seek to the start of the central directory one last time, since we
have just read the first entry's signature bytes; then list, extract
or test member files as instructed, and close the zipfile.
-----------------------------------------------------------------------*/
Trace((stderr, "about to extract/list files (error = %d)\n",
error_in_archive));
LSEEK( ecrec.offset_start_central_directory )
#ifndef NO_ZIPINFO
if (zipinfo_mode) {
error = zipinfo(); /* ZIPINFO 'EM */
if (lflag > 9)
PRINTF("\n");
} else
#endif
#ifndef SFX
if (vflag && !tflag && !cflag)
error = list_files(); /* LIST 'EM */
else
#endif
error = extract_or_test_files(); /* EXTRACT OR TEST 'EM */
Trace((stderr, "done with extract/list files (error = %d)\n", error));
if (error > error_in_archive) /* don't overwrite stronger error */
error_in_archive = error; /* with (for example) a warning */
#ifndef SFX
}
#endif
close(zipfd);
return error_in_archive;
} /* end function do_seekable() */
/*****************************/
/* Function uz_end_central() */
/*****************************/
int uz_end_central() /* return PK-type error code */
{
int error = PK_COOL;
/*---------------------------------------------------------------------------
Get the zipfile comment (up to 64KB long), if any, and print it out.
Then position the file pointer to the beginning of the central directory
and fill buffer.
---------------------------------------------------------------------------*/
#ifdef MSWIN
cchComment = ecrec.zipfile_comment_length; /* save for comment button */
if (ecrec.zipfile_comment_length && (zflag > 0))
#else
if (ecrec.zipfile_comment_length && (zflag > 0 || (zflag == 0 && !qflag)))
#endif
{
#if 0
#ifndef MSWIN
if (zflag == 0) (add "&& single_zipfile" perhaps; unnecessary with
PRINTF("[%s] comment:\n", zipfn); multiple zipfiles: "Archive:...")
#endif /* !MSWIN */
#endif /* 0 */
if (do_string(ecrec.zipfile_comment_length,DISPLAY)) {
FPRINTF(stderr, LoadFarString(ZipfileCommTrunc1));
error = PK_WARN;
}
}
return error;
} /* end function uz_end_central() */
/************************************/
/* Function process_cdir_file_hdr() */
/************************************/
int process_cdir_file_hdr() /* return PK-type error code */
{
int error;
/*---------------------------------------------------------------------------
Get central directory info, save host and method numbers, and set flag
for lowercase conversion of filename, depending on the OS from which the
file is coming.
---------------------------------------------------------------------------*/
if ((error = get_cdir_ent()) != 0)
return error;
pInfo->hostnum = MIN(crec.version_made_by[1], NUM_HOSTS);
/* extnum = MIN(crec.v
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -