#define UNZIP_INTERNAL
#include "unzip.h"
#ifdef WINDLL
# ifdef POCKET_UNZIP
# include "wince/intrface.h"
# else
# include "windll/windll.h"
# endif
#endif
static int do_seekable OF((__GPRO__ int lastchance));
static int find_ecrec OF((__GPRO__ long searchlen));
static ZCONST char Far CannotAllocateBuffers[] =
"error: cannot allocate unzip buffers\n";
#ifdef SFX
static ZCONST char Far CannotFindMyself[] =
"unzipsfx: cannot find myself! [%s]\n";
# ifdef CHEAP_SFX_AUTORUN
static ZCONST char Far AutorunPrompt[] =
"\nAuto-run command: %s\nExecute this command? [y/n] ";
static ZCONST char Far NotAutoRunning[] =
"Not executing auto-run command.";
# endif
#else
# if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
static ZCONST char Far WarnInvalidTZ[] =
"Warning: TZ environment variable not found, cannot use UTC times!!\n";
# endif
static ZCONST char Far FilesProcessOK[] =
"%d archive%s successfully processed.\n";
static ZCONST char Far ArchiveWarning[] =
"%d archive%s had warnings but no fatal errors.\n";
static ZCONST char Far ArchiveFatalError[] =
"%d archive%s had fatal errors.\n";
static ZCONST char Far FileHadNoZipfileDir[] =
"%d file%s had no zipfile directory.\n";
static ZCONST char Far ZipfileWasDir[] = "1 \"zipfile\" was a directory.\n";
static ZCONST char Far ManyZipfilesWereDir[] =
"%d \"zipfiles\" were directories.\n";
static ZCONST char Far NoZipfileFound[] = "No zipfiles found.\n";
# ifdef UNIX
static ZCONST char Far CannotFindZipfileDirMsg[] =
"%s: cannot find zipfile directory in one of %s or\n\
%s%s.zip, and cannot find %s, period.\n";
static ZCONST char Far CannotFindEitherZipfile[] =
"%s: cannot find %s, %s.zip or %s.\n";
# else
# ifndef AMIGA
static ZCONST char Far CannotFindWildcardMatch[] =
"%s: cannot find any matches for wildcard specification \"%s\".\n";
# endif
static ZCONST char Far CannotFindZipfileDirMsg[] =
"%s: cannot find zipfile directory in %s,\n\
%sand cannot find %s, period.\n";
static ZCONST char Far CannotFindEitherZipfile[] =
"%s: cannot find either %s or %s.\n";
# endif
extern ZCONST char Far Zipnfo[];
#ifndef WINDLL
static ZCONST char Far Unzip[] = "unzip";
#else
static ZCONST char Far Unzip[] = "UnZip DLL";
#endif
static ZCONST char Far MaybeExe[] =
"note: %s may be a plain executable, not an archive\n";
static ZCONST char Far CentDirNotInZipMsg[] = "\n\
[%s]:\n\
Zipfile is disk %u of a multi-disk archive, and this is not the disk on\n\
which the central zipfile directory begins (disk %u).\n";
static ZCONST char Far EndCentDirBogus[] =
"\nwarning [%s]: end-of-central-directory record claims this\n\
is disk %u but that the central directory starts on disk %u; this is a\n\
contradiction. Attempting to process anyway.\n";
# ifdef NO_MULTIPART
static ZCONST char Far NoMultiDiskArcSupport[] =
"\nerror [%s]: zipfile is part of multi-disk archive\n\
(sorry, not yet supported).\n";
static ZCONST char Far MaybePakBug[] = "warning [%s]:\
zipfile claims to be 2nd disk of a 2-part archive;\n\
attempting to process anyway. If no further errors occur, this archive\n\
was probably created by PAK v2.51 or earlier. This bug was reported to\n\
NoGate in March 1991 and was supposed to have been fixed by mid-1991; as\n\
of mid-1992 it still hadn't been. (If further errors do occur, archive\n\
was probably created by PKZIP 2.04c or later; UnZip does not yet support\n\
multi-part archives.)\n";
# else
static ZCONST char Far MaybePakBug[] = "warning [%s]:\
zipfile claims to be last disk of a multi-part archive;\n\
attempting to process anyway, assuming all parts have been concatenated\n\
together in order. Expect \"errors\" and warnings...true multi-part support\
\n doesn't exist yet (coming soon).\n";
# endif
static ZCONST char Far ExtraBytesAtStart[] =
"warning [%s]: %ld extra byte%s at beginning or within zipfile\n\
(attempting to process anyway)\n";
#endif
static ZCONST char Far MissingBytes[] =
"error [%s]: missing %ld bytes in zipfile\n\
(attempting to process anyway)\n";
static ZCONST char Far NullCentDirOffset[] =
"error [%s]: NULL central directory offset\n\
(attempting to process anyway)\n";
static ZCONST char Far ZipfileEmpty[] = "warning [%s]: zipfile is empty\n";
static ZCONST char Far CentDirStartNotFound[] =
"error [%s]: start of central directory not found;\n\
zipfile corrupt.\n%s";
#ifndef SFX
static ZCONST char Far CentDirTooLong[] =
"error [%s]: reported length of central directory is\n\
%ld bytes too long (Atari STZip zipfile? J.H.Holm ZIPSPLIT 1.1\n\
zipfile?). Compensating...\n";
static ZCONST char Far CentDirEndSigNotFound[] = "\
End-of-central-directory signature not found. Either this file is not\n\
a zipfile, or it constitutes one disk of a multi-part archive. In the\n\
latter case the central directory and zipfile comment will be found on\n\
the last disk(s) of this archive.\n";
#else
static ZCONST char Far CentDirEndSigNotFound[] =
" End-of-central-directory signature not found.\n";
#endif
static ZCONST char Far ZipfileCommTrunc1[] =
"\ncaution: zipfile comment truncated\n";
int process_zipfiles(__G)
__GDEF
{
#ifndef SFX
char *lastzipfn = (char *)NULL;
int NumWinFiles, NumLoseFiles, NumWarnFiles;
int NumMissDirs, NumMissFiles;
#endif
int error=0, error_in_archive=0;
G.inbuf = (uch *)malloc(INBUFSIZ + 4);
G.outbuf = (uch *)malloc(OUTBUFSIZ + 1);
if ((G.inbuf == (uch *)NULL) || (G.outbuf == (uch *)NULL)) {
Info(slide, 0x401, ((char *)slide,
LoadFarString(CannotAllocateBuffers)));
return(PK_MEM);
}
G.hold = G.inbuf + INBUFSIZ;
#ifndef VMS
#ifdef SMALL_MEM
G.outbuf2 = G.outbuf+RAWBUFSIZ;
#endif
#endif
#if 0
CRC_32_TAB = NULL;
#endif
local_hdr_sig[0] =
central_hdr_sig[0] = end_central_sig[0] = 0x50;
local_hdr_sig[1] =
central_hdr_sig[1] = end_central_sig[1] = 0x4B;
#if (defined(WIN32) && defined(USE_EF_UT_TIME))
iz_w32_prepareTZenv();
#endif
#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
# ifndef VALID_TIMEZONE
# define VALID_TIMEZONE(tmp) \
(((tmp = getenv("TZ")) != NULL) && (*tmp != '\0'))
# endif
{
char *p;
G.tz_is_valid = VALID_TIMEZONE(p);
# ifndef SFX
if (!G.tz_is_valid) {
Info(slide, 0x401, ((char *)slide, LoadFarString(WarnInvalidTZ)));
error_in_archive = error = PK_WARN;
}
# endif
}
#endif
#if (!defined(T20_VMS) && !defined(MACOS) && !defined(RISCOS) && !defined(QDOS))
#if (!defined(BSD) && !defined(MTS) && !defined(CMS_MVS) && !defined(TANDEM))
tzset();
#endif
#endif
G.overwrite_mode = (uO.overwrite_none ? OVERWRT_NEVER :
(uO.overwrite_all ? OVERWRT_ALWAYS : OVERWRT_QUERY));
#ifdef SFX
if ((error = do_seekable(__G__ 0)) == PK_NOZIP) {
#ifdef EXE_EXTENSION
int len=strlen(G.argv0);
if ( (G.zipfn = (char *)malloc(len+sizeof(EXE_EXTENSION))) !=
(char *)NULL ) {
strcpy(G.zipfn, G.argv0);
strcpy(G.zipfn+len, EXE_EXTENSION);
error = do_seekable(__G__ 0);
free(G.zipfn);
G.zipfn = G.argv0;
}
#endif
#ifdef WIN32
G.zipfn = G.argv0;
#endif
}
if (error) {
if (error == IZ_DIR)
error_in_archive = PK_NOZIP;
else
error_in_archive = error;
if (error == PK_NOZIP)
Info(slide, 1, ((char *)slide, LoadFarString(CannotFindMyself),
G.zipfn));
}
#ifdef CHEAP_SFX_AUTORUN
if (G.autorun_command[0] && !uO.qflag) {
Info(slide, 0x81, ((char *)slide, LoadFarString(AutorunPrompt),
FnFilter1(G.autorun_command)));
if (fgets(G.answerbuf, 9, stdin) != (char *)NULL
&& toupper(*G.answerbuf) == 'Y')
system(G.autorun_command);
else
Info(slide, 1, ((char *)slide, LoadFarString(NotAutoRunning)));
}
#endif
#else
NumWinFiles = NumLoseFiles = NumWarnFiles = 0;
NumMissDirs = NumMissFiles = 0;
while ((G.zipfn = do_wild(__G__ G.wildzipfn)) != (char *)NULL) {
Trace((stderr, "do_wild( %s ) returns %s\n", G.wildzipfn, G.zipfn));
lastzipfn = G.zipfn;
if (!uO.qflag && error != PK_NOZIP && error != IZ_DIR
#ifdef TIMESTAMP
&& (!uO.T_flag || uO.zipinfo_mode)
#endif
&& (NumWinFiles+NumLoseFiles+NumWarnFiles+NumMissFiles) > 0)
(*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
if ((error = do_seekable(__G__ 0)) == PK_WARN)
++NumWarnFiles;
else if (error == IZ_DIR)
++NumMissDirs;
else if (error == PK_NOZIP)
++NumMissFiles;
else if (error)
++NumLoseFiles;
else
++NumWinFiles;
Trace((stderr, "do_seekable(0) returns %d\n", error));
if (error != IZ_DIR && error > error_in_archive)
error_in_archive = error;
#ifdef WINDLL
if (error == IZ_CTRLC) {
free_G_buffers(__G);
return error;
}
#endif
}
if ((NumWinFiles + NumWarnFiles + NumLoseFiles) == 0 &&
(NumMissDirs + NumMissFiles) == 1 && lastzipfn != (char *)NULL)
{
NumMissDirs = NumMissFiles = 0;
if (error_in_archive == PK_NOZIP)
error_in_archive = PK_COOL;
#if (!defined(UNIX) && !defined(AMIGA))
if (iswild(G.wildzipfn))
Info(slide, 0x401, ((char *)slide,
LoadFarString(CannotFindWildcardMatch), uO.zipinfo_mode?
LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
G.wildzipfn));
else
#endif
{
char *p = lastzipfn + strlen(lastzipfn);
G.zipfn = lastzipfn;
strcpy(p, ZSUFX);
#if defined(UNIX) || defined(QDOS)
if ((error = do_seekable(__G__ 0)) == PK_NOZIP || error == IZ_DIR) {
if (error == IZ_DIR)
++NumMissDirs;
strcpy(p, ALT_ZSUFX);
error = do_seekable(__G__ 1);
}
#else
error = do_seekable(__G__ 1);
#endif
Trace((stderr, "do_seekable(1) returns %d\n", error));
switch (error) {
case PK_WARN:
++NumWarnFiles;
break;
case IZ_DIR:
++NumMissDirs;
error = PK_NOZIP;
break;
case PK_NOZIP:
;
break;
default:
if (error)
++NumLoseFiles;
else
++NumWinFiles;
break;
}
if (error > error_in_archive)
error_in_archive = error;
#ifdef WINDLL
if (error == IZ_CTRLC) {
free_G_buffers(__G);
return error;
}
#endif
}
}
#endif
#ifndef SFX
if (iswild(G.wildzipfn) && uO.qflag < 3
#ifdef TIMESTAMP
&& !(uO.T_flag && uO.qflag && !uO.zipinfo_mode)
#endif
)
{
if ((NumMissFiles + NumLoseFiles + NumWarnFiles > 0 || NumWinFiles != 1)
#ifdef TIMESTAMP
&& !(uO.T_flag && !uO.zipinfo_mode)
#endif
&& !(uO.tflag && uO.qflag > 1))
(*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0x401);
if ((NumWinFiles > 1) || (NumWinFiles == 1 &&
NumMissDirs + NumMissFiles + NumLoseFiles + NumWarnFiles > 0))
Info(slide, 0x401, ((char *)slide, LoadFarString(FilesProcessOK),
NumWinFiles, (NumWinFiles == 1)? " was" : "s were"));
if (NumWarnFiles > 0)
Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveWarning),
NumWarnFiles, (NumWarnFiles == 1)? "" : "s"));
if (NumLoseFiles > 0)
Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveFatalError),
NumLoseFiles, (NumLoseFiles == 1)? "" : "s"));
if (NumMissFiles > 0)
Info(slide, 0x401, ((char *)slide,
LoadFarString(FileHadNoZipfileDir), NumMissFiles,
(NumMissFiles == 1)? "" : "s"));
if (NumMissDirs == 1)
Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileWasDir)));
else if (NumMissDirs > 0)
Info(slide, 0x401, ((char *)slide,
LoadFarString(ManyZipfilesWereDir), NumMissDirs));
if (NumWinFiles + NumLoseFiles + NumWarnFiles == 0)
Info(slide, 0x401, ((char *)slide, LoadFarString(NoZipfileFound)));
}
#endif
free_G_buffers(__G);
return error_in_archive;
}
void free_G_buffers(__G)
__GDEF
{
inflate_free(__G);
checkdir(__G__ (char *)NULL, END);
#ifdef DYNALLOC_CRCTAB
if (CRC_32_TAB) {
free_crc_table();
CRC_32_TAB = NULL;
}
#endif
if (G.key != (char *)NULL) {
free(G.key);
G.key = (char *)NULL;
}
if (G.extra_field != (uch *)NULL) {
free(G.extra_field);
G.extra_field = (uch *)NULL;
}
#if (!defined(VMS) && !defined(SMALL_MEM))
if (G.outbuf2) {
free(G.outbuf2);
G.outbuf2 = (uch *)NULL;
}
#endif
if (G.outbuf)
free(G.outbuf);
if (G.inbuf)
free(G.inbuf);
G.inbuf = G.outbuf = (uch *)NULL;
#ifdef MALLOC_WORK
if (G.area.Slide) {
free(G.area.Slide);
G.area.Slide = (uch *)NULL;
}
#endif
}
static int do_seekable(__G__ lastchance)
__GDEF
int lastchance;
{
#ifndef SFX
int maybe_exe=FALSE;
int too_weird_to_continue=FALSE;
#ifdef TIMESTAMP
time_t uxstamp;
ulg nmember = 0L;
#endif
#endif
int error=0, error_in_archive;
if (SSTAT(G.zipfn, &G.statbuf) ||
#ifdef THEOS
(error = S_ISLIB(G.statbuf.st_mode)) != 0 ||
#endif
(error = S_ISDIR(G.statbuf.st_mode)) != 0)
{
#ifndef SFX
if (lastchance && (uO.qflag < 3)) {
#if defined(UNIX) || defined(QDOS)
if (G.no_ecrec)
Info(slide, 1, ((char *)slide,
LoadFarString(CannotFindZipfileDirMsg), uO.zipinfo_mode?
LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
G.wildzipfn, uO.zipinfo_mode? " " : "", G.wildzipfn,
G.zipfn));
else
Info(slide, 1, ((char *)slide,
LoadFarString(CannotFindEitherZipfile), uO.zipinfo_mode?
LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
G.wildzipfn, G.wildzipfn, G.zipfn));
#else
if (G.no_ecrec)
Info(slide, 0x401, ((char *)slide,
LoadFarString(CannotFindZipfileDirMsg), uO.zipinfo_mode?
LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
G.wildzipfn, uO.zipinfo_mode? " " : "", G.zipfn));
else
Info(slide, 0x401, ((char *)slide,
LoadFarString(CannotFindEitherZipfile), uO.zipinfo_mode?
LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
G.wildzipfn, G.zipfn));
#endif
}
#endif
return error? IZ_DIR : PK_NOZIP;
}
G.ziplen = G.statbuf.st_size;
#ifndef SFX
#if defined(UNIX) || defined(DOS_OS2_W32) || defined(THEOS)
if (G.statbuf.st_mode & S_IEXEC)
maybe_exe = TRUE;
#endif
#endif
#ifdef VMS
if (check_format(__G))
return PK_ERR;
#endif
if (open_input_file(__G))
return PK_NOZIP;
if (CRC_32_TAB == NULL) {
if ((CRC_32_TAB = get_crc_table()) == NULL) {
CLOSE_INFILE();
return PK_MEM;
}
}
#if (!defined(SFX) || defined(SFX_EXDIR))
if (uO.exdir != (char *)NULL && G.extract_flag) {
G.create_dirs = !uO.fflag;
if ((error = checkdir(__G__ uO.exdir, ROOT)) > MPN_INF_SKIP) {
CLOSE_INFILE();
return (error == MPN_NOMEM ? PK_MEM : PK_ERR);
}
}
#endif
G.cur_zipfile_bufstart = 0;
G.inptr = G.inbuf;
#if (!defined(WINDLL) && !defined(SFX))
#ifdef TIMESTAMP
if (!uO.zipinfo_mode && !uO.qflag && !uO.T_flag)
#else
if (!uO.zipinfo_mode && !uO.qflag)
#endif
#ifdef WIN32
Info(slide, 0, ((char *)slide, "Archive: %s\n", FnFilter1(G.zipfn)));
#else
Info(slide, 0, ((char *)slide, "Archive: %s\n", G.zipfn));
#endif
#endif
if ((
#ifndef NO_ZIPINFO
uO.zipinfo_mode &&
((error_in_archive = find_ecrec(__G__ G.ziplen)) != 0 ||
(error_in_archive = zi_end_central(__G)) > PK_WARN))
|| (!uO.zipinfo_mode &&
#endif
((error_in_archive = find_ecrec(__G__ MIN(G.ziplen,66000L))) != 0 ||
(error_in_archive = uz_end_central(__G)) > PK_WARN)))
{
CLOSE_INFILE();
#ifdef SFX
++lastchance;
return error_in_archive;
#else
if (maybe_exe)
Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeExe),
G.zipfn));
if (lastchance)
return error_in_archive;
else {
G.no_ecrec = TRUE;
return PK_NOZIP;
}
#endif
}
if ((uO.zflag > 0) && !uO.zipinfo_mode) {
CLOSE_INFILE();
return error_in_archive;
}
#ifdef NO_MULTIPART
error = !uO.zipinfo_mode && (G.ecrec.number_this_disk == 1) &&
(G.ecrec.num_disk_start_cdir == 1);
#else
error = !uO.zipinfo_mode && (G.ecrec.number_this_disk != 0);
#endif
#ifndef SFX
if (uO.zipinfo_mode &&
G.ecrec.number_this_disk != G.ecrec.num_disk_start_cdir)
{
if (G.ecrec.number_this_disk > G.ecrec.num_disk_start_cdir) {
Info(slide, 0x401, ((char *)slide,
LoadFarString(CentDirNotInZipMsg), G.zipfn,
G.ecrec.number_this_disk, G.ecrec.num_disk_start_cdir));
error_in_archive = PK_FIND;
too_weird_to_continue = TRUE;
} else {
Info(slide, 0x401, ((char *)slide,
LoadFarString(EndCentDirBogus), G.zipfn,
G.ecrec.number_this_disk, G.ecrec.num_disk_start_cdir));
error_in_archive = PK_WARN;
}
#ifdef NO_MULTIPART
} else if (!uO.zipinfo_mode && !error && G.ecrec.number_this_disk != 0) {
Info(slide, 0x401, ((char *)slide, LoadFarString(NoMultiDiskArcSupport),
G.zipfn));
error_in_archive = PK_FIND;
too_weird_to_continue = TRUE;
#endif
}
if (!too_weird_to_continue) {
if (error) {
Info(slide, 0x401, ((char *)slide, LoadFarString(MaybePakBug),
G.zipfn));
error_in_archive = PK_WARN;
}
#endif
if ((G.extra_bytes = G.real_ecrec_offset-G.expect_ecrec_offset) <
(LONGINT)0)
{
Info(slide, 0x401, ((char *)slide, LoadFarString(MissingBytes),
G.zipfn, (long)(-G.extra_bytes)));
error_in_archive = PK_ERR;
} else if (G.extra_bytes > 0) {
if ((G.ecrec.offset_start_central_directory == 0) &&
(G.ecrec.size_central_directory != 0))
{
Info(slide, 0x401, ((char *)slide,
LoadFarString(NullCentDirOffset), G.zipfn));
G.ecrec.offset_start_central_directory = G.extra_bytes;
G.extra_bytes = 0;
error_in_archive = PK_ERR;
}
#ifndef SFX
else {
Info(slide, 0x401, ((char *)slide,
LoadFarString(ExtraBytesAtStart), G.zipfn,
(long)G.extra_bytes, (G.extra_bytes == 1)? "":"s"));
error_in_archive = PK_WARN;
}
#endif
}
if (G.expect_ecrec_offset==0L && G.ecrec.size_central_directory==0) {
if (uO.zipinfo_mode)
Info(slide, 0, ((char *)slide, "%sEmpty zipfile.\n",
uO.lflag>9? "\n " : ""));
else
Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileEmpty),
G.zipfn));
CLOSE_INFILE();
return (error_in_archive > PK_WARN)? error_in_archive : PK_WARN;
}
error = seek_zipf(__G__ G.ecrec.offset_start_central_directory);
if (error == PK_BADERR) {
CLOSE_INFILE();
return PK_BADERR;
}
#ifdef OLD_SEEK_TEST
if (error != PK_OK || readbuf(__G__ G.sig, 4) == 0) {
CLOSE_INFILE();
return PK_ERR;
}
if (strncmp(G.sig, central_hdr_sig, 4))
#else
if ((error != PK_OK) || (readbuf(__G__ G.sig, 4) == 0) ||
strncmp(G.sig, central_hdr_sig, 4))
#endif
{
#ifndef SFX
long tmp = G.extra_bytes;
#endif
G.extra_bytes = 0;
error = seek_zipf(__G__ G.ecrec.offset_start_central_directory);
if ((error != PK_OK) || (readbuf(__G__ G.sig, 4) == 0) ||
strncmp(G.sig, central_hdr_sig, 4))
{
if (error != PK_BADERR)
Info(slide, 0x401, ((char *)slide,
LoadFarString(CentDirStartNotFound), G.zipfn,
LoadFarStringSmall(ReportMsg)));
CLOSE_INFILE();
return (error != PK_OK ? error : PK_BADERR);
}
#ifndef SFX
Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirTooLong),
G.zipfn, -tmp));
#endif
error_in_archive = PK_ERR;
}
error = seek_zipf(__G__ G.ecrec.offset_start_central_directory);
if (error != PK_OK) {
CLOSE_INFILE();
return error;
}
Trace((stderr, "about to extract/list files (error = %d)\n",
error_in_archive));
#ifdef DLL
if (!G.fValidate)
#endif
{
#ifndef NO_ZIPINFO
if (uO.zipinfo_mode)
error = zipinfo(__G);
else
#endif
#ifndef SFX
#ifdef TIMESTAMP
if (uO.T_flag)
error = get_time_stamp(__G__ &uxstamp, &nmember);
else
#endif
if (uO.vflag && !uO.tflag && !uO.cflag)
error = list_files(__G);
else
#endif
error = extract_or_test_files(__G);
Trace((stderr, "done with extract/list files (error = %d)\n",
error));
}
if (error > error_in_archive)
error_in_archive = error;
#ifndef SFX
}
#endif
CLOSE_INFILE();
#ifdef TIMESTAMP
if (uO.T_flag && !uO.zipinfo_mode && (nmember > 0L)) {
# ifdef WIN32
if (stamp_file(__G__ G.zipfn, uxstamp)) {
# else
if (stamp_file(G.zipfn, uxstamp)) {
# endif
if (uO.qflag < 3)
Info(slide, 0x201, ((char *)slide,
"warning: cannot set time for %s\n", G.zipfn));
if (error_in_archive < PK_WARN)
error_in_archive = PK_WARN;
}
}
#endif
return error_in_archive;
}
static int find_ecrec(__G__ searchlen)
__GDEF
long searchlen;
{
int i, numblks, found=FALSE;
LONGINT tail_len;
ec_byte_rec byterec;
if (G.ziplen <= INBUFSIZ) {
lseek(G.zipfd, 0L, SEEK_SET);
if ((G.incnt = read(G.zipfd,(char *)G.inbuf,(unsigned int)G.ziplen))
== (int)G.ziplen)
for (G.inptr = G.inbuf+(int)G.ziplen-(ECREC_SIZE+4);
G.inptr >= G.inbuf;
--G.inptr) {
if ( (*G.inptr == (uch)0x50) &&
!strncmp((char *)G.inptr, end_central_sig, 4)) {
G.incnt -= (int)(G.inptr - G.inbuf);
found = TRUE;
break;
}
}
} else {
if ((tail_len = G.ziplen % INBUFSIZ) > ECREC_SIZE) {
#ifdef USE_STRM_INPUT
fseek((FILE *)G.zipfd, G.ziplen-tail_len, SEEK_SET);
G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
#else
G.cur_zipfile_bufstart = lseek(G.zipfd, G.ziplen-tail_len,
SEEK_SET);
#endif
if ((G.incnt = read(G.zipfd, (char *)G.inbuf,
(unsigned int)tail_len)) != (int)tail_len)
goto fail;
for (G.inptr = G.inbuf+(int)tail_len-(ECREC_SIZE+4);
G.inptr >= G.inbuf;
--G.inptr) {
if ( (*G.inptr == (uch)0x50) &&
!strncmp((char *)G.inptr, end_central_sig, 4)) {
G.incnt -= (int)(G.inptr - G.inbuf);
found = TRUE;
break;
}
}
memcpy((char *)G.hold, (char *)G.inbuf, 3);
} else
G.cur_zipfile_bufstart = G.ziplen - tail_len;
numblks = (int)((searchlen - tail_len + (INBUFSIZ-1)) / INBUFSIZ);
for (i = 1; !found && (i <= numblks); ++i) {
G.cur_zipfile_bufstart -= INBUFSIZ;
lseek(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET);
if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ))
!= INBUFSIZ)
break;
for (G.inptr = G.inbuf+INBUFSIZ-1; G.inptr >= G.inbuf;
--G.inptr)
if ((native(*G.inptr) == 'P') &&
!strncmp((char *)G.inptr, end_central_sig, 4)) {
G.incnt -= (int)(G.inptr - G.inbuf);
found = TRUE;
break;
}
memcpy((char *)G.hold, (char *)G.inbuf, 3);
}
}
fail:
if (!found) {
if (uO.qflag || uO.zipinfo_mode)
Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn));
Info(slide, 0x401, ((char *)slide,
LoadFarString(CentDirEndSigNotFound)));
return PK_ERR;
}
G.real_ecrec_offset = G.cur_zipfile_bufstart + (G.inptr-G.inbuf);
#ifdef TEST
printf("\n found end-of-central-dir signature at offset %ld (%.8lXh)\n",
G.real_ecrec_offset, G.real_ecrec_offset);
printf(" from beginning of file; offset %d (%.4Xh) within block\n",
G.inptr-G.inbuf, G.inptr-G.inbuf);
#endif
if (readbuf(__G__ (char *)byterec, ECREC_SIZE+4) == 0)
return PK_EOF;
G.ecrec.number_this_disk =
makeword(&byterec[NUMBER_THIS_DISK]);
G.ecrec.num_disk_start_cdir =
makeword(&byterec[NUM_DISK_WITH_START_CENTRAL_DIR]);
G.ecrec.num_entries_centrl_dir_ths_disk =
makeword(&byterec[NUM_ENTRIES_CENTRL_DIR_THS_DISK]);
G.ecrec.total_entries_central_dir =
makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]);
G.ecrec.size_central_directory =
makelong(&byterec[SIZE_CENTRAL_DIRECTORY]);
G.ecrec.offset_start_central_directory =
makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);
G.ecrec.zipfile_comment_length =
makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);
G.expect_ecrec_offset = G.ecrec.offset_start_central_directory +
G.ecrec.size_central_directory;
return PK_COOL;
}
int uz_end_central(__G)
__GDEF
{
int error = PK_COOL;
#ifdef WINDLL
if ((!G.fValidate) && (G.lpUserFunctions != NULL))
G.lpUserFunctions->cchComment = G.ecrec.zipfile_comment_length;
if (G.ecrec.zipfile_comment_length && (uO.zflag > 0))
#else
if (G.ecrec.zipfile_comment_length && (uO.zflag > 0 ||
(uO.zflag == 0 &&
#ifdef TIMESTAMP
!uO.T_flag &&
#endif
!uO.qflag)))
#endif
{
#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))
if (do_string(__G__ G.ecrec.zipfile_comment_length, CHECK_AUTORUN)) {
#else
if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) {
#endif
Info(slide, 0x401, ((char *)slide,
LoadFarString(ZipfileCommTrunc1)));
error = PK_WARN;
}
}
#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))
else if (G.ecrec.zipfile_comment_length) {
if (do_string(__G__ G.ecrec.zipfile_comment_length, CHECK_AUTORUN_Q)) {
Info(slide, 0x401, ((char *)slide,
LoadFarString(ZipfileCommTrunc1)));
error = PK_WARN;
}
}
#endif
return error;
}
int process_cdir_file_hdr(__G)
__GDEF
{
int error;
if ((error = get_cdir_ent(__G)) != 0)
return error;
G.pInfo->hostver = G.crec.version_made_by[0];
G.pInfo->hostnum = MIN(G.crec.version_made_by[1], NUM_HOSTS);
G.pInfo->lcflag = 0;
if (uO.L_flag == 1)
switch (G.pInfo->hostnum) {
case FS_FAT_:
case CPM_:
case VM_CMS_:
case MVS_:
case TANDEM_:
case TOPS20_:
case VMS_:
G.pInfo->lcflag = 1;
break;
default:
break;
}
else if (uO.L_flag > 1)
G.pInfo->lcflag = 1;
if (IS_VOLID(G.crec.external_file_attributes) &&
(G.pInfo->hostnum == FS_FAT_ || G.pInfo->hostnum == FS_HPFS_ ||
G.pInfo->hostnum == FS_NTFS_ || G.pInfo->hostnum == ATARI_))
{
G.pInfo->vollabel = TRUE;
G.pInfo->lcflag = 0;
} else
G.pInfo->vollabel = FALSE;
G.pInfo->HasUxAtt = (G.crec.external_file_attributes & 0xffff0000L) != 0L;
return PK_COOL;
}
int get_cdir_ent(__G)
__GDEF
{
cdir_byte_hdr byterec;
if (readbuf(__G__ (char *)byterec, CREC_SIZE) == 0)
return PK_EOF;
G.crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0];
G.crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1];
G.crec.version_needed_to_extract[0] =
byterec[C_VERSION_NEEDED_TO_EXTRACT_0];
G.crec.version_needed_to_extract[1] =
byterec[C_VERSION_NEEDED_TO_EXTRACT_1];
G.crec.general_purpose_bit_flag =
makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]);
G.crec.compression_method =
makeword(&byterec[C_COMPRESSION_METHOD]);
G.crec.last_mod_dos_datetime =
makelong(&byterec[C_LAST_MOD_DOS_DATETIME]);
G.crec.crc32 =
makelong(&byterec[C_CRC32]);
G.crec.csize =
makelong(&byterec[C_COMPRESSED_SIZE]);
G.crec.ucsize =
makelong(&byterec[C_UNCOMPRESSED_SIZE]);
G.crec.filename_length =
makeword(&byterec[C_FILENAME_LENGTH]);
G.crec.extra_field_length =
makeword(&byterec[C_EXTRA_FIELD_LENGTH]);
G.crec.file_comment_length =
makeword(&byterec[C_FILE_COMMENT_LENGTH]);
G.crec.disk_number_start =
makeword(&byterec[C_DISK_NUMBER_START]);
G.crec.internal_file_attributes =
makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]);
G.crec.external_file_attributes =
makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]);
G.crec.relative_offset_local_header =
makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]);
return PK_COOL;
}
int process_local_file_hdr(__G)
__GDEF
{
local_byte_hdr byterec;
if (readbuf(__G__ (char *)byterec, LREC_SIZE) == 0)
return PK_EOF;
G.lrec.version_needed_to_extract[0] =
byterec[L_VERSION_NEEDED_TO_EXTRACT_0];
G.lrec.version_needed_to_extract[1] =
byterec[L_VERSION_NEEDED_TO_EXTRACT_1];
G.lrec.general_purpose_bit_flag =
makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]);
G.lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]);
G.lrec.last_mod_dos_datetime = makelong(&byterec[L_LAST_MOD_DOS_DATETIME]);
G.lrec.crc32 = makelong(&byterec[L_CRC32]);
G.lrec.csize = makelong(&byterec[L_COMPRESSED_SIZE]);
G.lrec.ucsize = makelong(&byterec[L_UNCOMPRESSED_SIZE]);
G.lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]);
G.lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]);
if ((G.lrec.general_purpose_bit_flag & 8) != 0) {
G.lrec.crc32 = G.pInfo->crc;
G.lrec.csize = G.pInfo->compr_size;
G.lrec.ucsize = G.pInfo->uncompr_size;
}
G.csize = (long)G.lrec.csize;
return PK_COOL;
}
#ifdef USE_EF_UT_TIME
unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos_mdatetime,
z_utim, z_uidgid)
ZCONST uch *ef_buf;
unsigned ef_len;
int ef_is_c;
ulg dos_mdatetime;
iztimes *z_utim;
ush *z_uidgid;
{
unsigned flags = 0;
unsigned eb_id;
unsigned eb_len;
int have_new_type_eb = FALSE;
long i_time;
#ifdef TIME_T_TYPE_DOUBLE
int ut_in_archive_sgn = 0;
#else
int ut_zip_unzip_compatible = FALSE;
#endif
if (ef_len == 0 || ef_buf == NULL || (z_utim == 0 && z_uidgid == NULL))
return 0;
TTrace((stderr,"\nef_scan_for_izux: scanning extra field of length %u\n",
ef_len));
while (ef_len >= EB_HEADSIZE) {
eb_id = makeword(EB_ID + ef_buf);
eb_len = makeword(EB_LEN + ef_buf);
if (eb_len > (ef_len - EB_HEADSIZE)) {
TTrace((stderr,
"ef_scan_for_izux: block length %u > rest ef_size %u\n", eb_len,
ef_len - EB_HEADSIZE));
break;
}
switch (eb_id) {
case EF_TIME:
flags &= ~0x0ff;
have_new_type_eb = TRUE;
if ( eb_len >= EB_UT_MINLEN && z_utim != NULL) {
unsigned eb_idx = EB_UT_TIME1;
TTrace((stderr,"ef_scan_for_izux: found TIME extra field\n"));
flags |= (ef_buf[EB_HEADSIZE+EB_UT_FLAGS] & 0x0ff);
if ((flags & EB_UT_FL_MTIME)) {
if ((eb_idx+4) <= eb_len) {
i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf);
eb_idx += 4;
TTrace((stderr," UT e.f. modification time = %ld\n",
i_time));
#ifdef TIME_T_TYPE_DOUBLE
if ((ulg)(i_time) & (ulg)(0x80000000L)) {
if (dos_mdatetime == DOSTIME_MINIMUM) {
ut_in_archive_sgn = -1;
z_utim->mtime =
(time_t)((long)i_time | (~(long)0x7fffffffL));
} else if (dos_mdatetime >= DOSTIME_2038_01_18) {
ut_in_archive_sgn = 1;
z_utim->mtime =
(time_t)((ulg)i_time & (ulg)0xffffffffL);
} else {
ut_in_archive_sgn = 0;
flags &= ~0x0ff;
TTrace((stderr,
" UT modtime range error; ignore e.f.!\n"));
break;
}
} else {
ut_in_archive_sgn = 0;
z_utim->mtime = (time_t)i_time;
}
#else
if ((ulg)(i_time) & (ulg)(0x80000000L)) {
ut_zip_unzip_compatible =
((time_t)0x80000000L < (time_t)0L)
? (dos_mdatetime == DOSTIME_MINIMUM)
: (dos_mdatetime >= DOSTIME_2038_01_18);
if (!ut_zip_unzip_compatible) {
flags &= ~0x0ff;
TTrace((stderr,
" UT modtime range error; ignore e.f.!\n"));
break;
}
} else {
ut_zip_unzip_compatible = FALSE;
}
z_utim->mtime = (time_t)i_time;
#endif
} else {
flags &= ~EB_UT_FL_MTIME;
TTrace((stderr," UT e.f. truncated; no modtime\n"));
}
}
if (ef_is_c) {
break;
}
if (flags & EB_UT_FL_ATIME) {
if ((eb_idx+4) <= eb_len) {
i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf);
eb_idx += 4;
TTrace((stderr," UT e.f. access time = %ld\n",
i_time));
#ifdef TIME_T_TYPE_DOUBLE
if ((ulg)(i_time) & (ulg)(0x80000000L)) {
if (ut_in_archive_sgn == -1)
z_utim->atime =
(time_t)((long)i_time | (~(long)0x7fffffffL));
} else if (ut_in_archive_sgn == 1) {
z_utim->atime =
(time_t)((ulg)i_time & (ulg)0xffffffffL);
} else {
flags &= ~EB_UT_FL_ATIME;
TTrace((stderr,
" UT access time range error: skip time!\n"));
}
} else {
z_utim->atime = (time_t)i_time;
}
#else
if (((ulg)(i_time) & (ulg)(0x80000000L)) &&
!ut_zip_unzip_compatible) {
flags &= ~EB_UT_FL_ATIME;
TTrace((stderr,
" UT access time range error: skip time!\n"));
} else {
z_utim->atime = (time_t)i_time;
}
#endif
} else {
flags &= ~EB_UT_FL_ATIME;
}
}
if (flags & EB_UT_FL_CTIME) {
if ((eb_idx+4) <= eb_len) {
i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf);
TTrace((stderr," UT e.f. creation time = %ld\n",
i_time));
#ifdef TIME_T_TYPE_DOUBLE
if ((ulg)(i_time) & (ulg)(0x80000000L)) {
if (ut_in_archive_sgn == -1)
z_utim->ctime =
(time_t)((long)i_time | (~(long)0x7fffffffL));
} else if (ut_in_archive_sgn == 1) {
z_utim->ctime =
(time_t)((ulg)i_time & (ulg)0xffffffffL);
} else {
flags &= ~EB_UT_FL_CTIME;
TTrace((stderr,
" UT creation time range error: skip time!\n"));
}
} else {
z_utim->ctime = (time_t)i_time;
}
#else
if (((ulg)(i_time) & (ulg)(0x80000000L)) &&
!ut_zip_unzip_compatible) {
flags &= ~EB_UT_FL_CTIME;
TTrace((stderr,
" UT creation time range error: skip time!\n"));
} else {
z_utim->ctime = (time_t)i_time;
}
#endif
} else {
flags &= ~EB_UT_FL_CTIME;
}
}
}
break;
case EF_IZUNIX2:
if (!have_new_type_eb) {
flags &= ~0x0ff;
have_new_type_eb = TRUE;
}
if (eb_len >= EB_UX2_MINLEN && z_uidgid != NULL) {
z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX2_UID) + ef_buf);
z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX2_GID) + ef_buf);
flags |= EB_UX2_VALID;
}
break;
case EF_IZUNIX:
case EF_PKUNIX:
if (eb_len >= EB_UX_MINLEN) {
TTrace((stderr,"ef_scan_for_izux: found %s extra field\n",
(eb_id == EF_IZUNIX ? "IZUNIX" : "PKUNIX")));
if (have_new_type_eb) {
break;
}
if (z_utim != NULL) {
flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME);
i_time = (long)makelong((EB_HEADSIZE+EB_UX_MTIME)+ef_buf);
TTrace((stderr," Unix EF modtime = %ld\n", i_time));
#ifdef TIME_T_TYPE_DOUBLE
if ((ulg)(i_time) & (ulg)(0x80000000L)) {
if (dos_mdatetime == DOSTIME_MINIMUM) {
ut_in_archive_sgn = -1;
z_utim->mtime =
(time_t)((long)i_time | (~(long)0x7fffffffL));
} else if (dos_mdatetime >= DOSTIME_2038_01_18) {
ut_in_archive_sgn = 1;
z_utim->mtime =
(time_t)((ulg)i_time & (ulg)0xffffffffL);
} else {
ut_in_archive_sgn = 0;
flags &= ~0x0ff;
TTrace((stderr,
" UX modtime range error: ignore e.f.!\n"));
}
} else {
ut_in_archive_sgn = 0;
z_utim->mtime = (time_t)i_time;
}
#else
if ((ulg)(i_time) & (ulg)(0x80000000L)) {
ut_zip_unzip_compatible =
((time_t)0x80000000L < (time_t)0L)
? (dos_mdatetime == DOSTIME_MINIMUM)
: (dos_mdatetime >= DOSTIME_2038_01_18);
if (!ut_zip_unzip_compatible) {
flags &= ~0x0ff;
TTrace((stderr,
" UX modtime range error: ignore e.f.!\n"));
}
} else {
ut_zip_unzip_compatible = FALSE;
}
z_utim->mtime = (time_t)i_time;
#endif
i_time = (long)makelong((EB_HEADSIZE+EB_UX_ATIME)+ef_buf);
TTrace((stderr," Unix EF actime = %ld\n", i_time));
#ifdef TIME_T_TYPE_DOUBLE
if ((ulg)(i_time) & (ulg)(0x80000000L)) {
if (ut_in_archive_sgn == -1)
z_utim->atime =
(time_t)((long)i_time | (~(long)0x7fffffffL));
} else if (ut_in_archive_sgn == 1) {
z_utim->atime =
(time_t)((ulg)i_time & (ulg)0xffffffffL);
} else if (flags & 0x0ff) {
flags &= ~EB_UT_FL_ATIME;
TTrace((stderr,
" UX access time range error: skip time!\n"));
}
} else {
z_utim->atime = (time_t)i_time;
}
#else
if (((ulg)(i_time) & (ulg)(0x80000000L)) &&
!ut_zip_unzip_compatible && (flags & 0x0ff)) {
flags &= ~EB_UT_FL_ATIME;
TTrace((stderr,
" UX access time range error: skip time!\n"));
} else {
z_utim->atime = (time_t)i_time;
}
#endif
}
if (eb_len >= EB_UX_FULLSIZE && z_uidgid != NULL) {
z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX_UID) + ef_buf);
z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX_GID) + ef_buf);
flags |= EB_UX2_VALID;
}
}
break;
default:
break;
}
ef_buf += (eb_len + EB_HEADSIZE);
ef_len -= (eb_len + EB_HEADSIZE);
}
return flags;
}
#endif
#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
#define SPARKID_2 0x30435241
zvoid *getRISCOSexfield(ef_buf, ef_len)
ZCONST uch *ef_buf;
unsigned ef_len;
{
unsigned eb_id;
unsigned eb_len;
if (ef_len == 0 || ef_buf == NULL)
return NULL;
TTrace((stderr,"\ngetRISCOSexfield: scanning extra field of length %u\n",
ef_len));
while (ef_len >= EB_HEADSIZE) {
eb_id = makeword(EB_ID + ef_buf);
eb_len = makeword(EB_LEN + ef_buf);
if (eb_len > (ef_len - EB_HEADSIZE)) {
TTrace((stderr,
"getRISCOSexfield: block length %u > rest ef_size %u\n", eb_len,
ef_len - EB_HEADSIZE));
break;
}
if (eb_id == EF_SPARK && (eb_len == 24 || eb_len == 20)) {
if (makelong(EB_HEADSIZE + ef_buf) == SPARKID_2) {
return (zvoid *)ef_buf;
}
}
ef_buf += (eb_len + EB_HEADSIZE);
ef_len -= (eb_len + EB_HEADSIZE);
}
return NULL;
}
#endif