home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Telecom
/
1996-04-telecom-walnutcreek.iso
/
utils
/
unix
/
unzip512
/
unzip.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-23
|
67KB
|
1,907 lines
/*---------------------------------------------------------------------------
unzip.c
UnZip - a zipfile extraction utility. See below for make instructions, or
read the comments in Makefile and the various Contents files for more de-
tailed explanations. To report a bug, send a *complete* description to
zip-bugs@wkuvx1.wku.edu; include machine type, operating system and ver-
sion, compiler and version, and reasonably detailed error messages or prob-
lem report. To join Info-ZIP, see the instructions in README.
UnZip 5.x is a greatly expanded and partially rewritten successor to 4.x,
which in turn was almost a complete rewrite of version 3.x. For a detailed
revision history, see UnzpHist.zip at quest.jpl.nasa.gov. For a list of
the many (near infinite) contributors, see "CONTRIBS" in the UnZip source
distribution.
---------------------------------------------------------------------------
[from original zipinfo.c]
This program reads great gobs of totally nifty information, including the
central directory stuff, from ZIP archives ("zipfiles" for short). It
started as just a testbed for fooling with zipfiles, but at this point it
is actually a useful utility. It also became the basis for the rewrite of
UnZip (3.16 -> 4.0), using the central directory for processing rather than
the individual (local) file headers.
As of ZipInfo v2.0 and UnZip v5.1, the two programs are combined into one.
If the executable is named "unzip" (or "unzip.exe", depending), it behaves
like UnZip by default; if it is named "zipinfo" or "ii", it behaves like
ZipInfo. The ZipInfo behavior may also be triggered by use of unzip's -Z
option; for example, "unzip -Z [zipinfo_options] archive.zip".
Another dandy product from your buddies at Newtware!
Author: Greg Roelofs, newt@uchicago.edu, 23 August 1990 -> ... 1994
---------------------------------------------------------------------------
Version: unzip512.{tar.Z | zip | zoo} for Unix, VMS, OS/2, MS-DOS, Windows,
Windows NT, Macintosh, Amiga, Atari, Human68K and TOPS-20. De-
cryption requires sources in zcrypt23.zip, and Windows (not NT)
support requires sources in wunz20sr.zip (not up to date). See
accompanying file "Where" in the main source distribution for
ftp, uucp and mail-server sites.
Copyrights: see accompanying file "COPYING" in UnZip source distribution.
---------------------------------------------------------------------------*/
#include "unzip.h" /* includes, typedefs, macros, prototypes, etc. */
#include "crypt.h"
#include "version.h"
#ifdef MSWIN
# include "wizunzip.h"
#endif
/**********************/
/* Global Variables */
/**********************/
int zipinfo_mode; /* behave like ZipInfo or like normal UnZip? */
int aflag=0; /* -a: do ASCII-EBCDIC and/or end-of-line translation */
int cflag=0; /* -c: output to stdout */
int C_flag=0; /* -C: match filenames case-insensitively */
int dflag=0; /* -d: all args are files/dirs to be extracted */
int fflag=0; /* -f: "freshen" (extract only newer files) */
int hflag=0; /* -h: header line (zipinfo) */
int jflag=0; /* -j: junk pathnames (unzip) */
int lflag=(-1); /* -12slmv: listing format (zipinfo) */
int L_flag=0; /* -L: convert filenames from some OSes to lowercase */
int overwrite_none=0; /* -n: never overwrite files (no prompting) */
int overwrite_all=0; /* -o: OK to overwrite files without prompting */
int force_flag=0; /* (shares -o for now): force to override errors, etc. */
int qflag=0; /* -q: produce a lot less output */
#ifdef DOS_NT_OS2
int sflag=0; /* -s: convert filename spaces (blanks) to underscores */
int volflag=0; /* -$: extract volume labels */
#endif
int tflag=0; /* -t: test (unzip) or totals line (zipinfo) */
int T_flag=0; /* -T: decimal time format (zipinfo) */
int uflag=0; /* -u: "update" (extract only newer & brand-new files) */
int vflag=0; /* -v: (verbosely) list directory */
int V_flag=0; /* -V: don't strip VMS version numbers */
#ifdef VMS
int secinf=0; /* -X: keep owner/protection */
#endif
int zflag=0; /* -z: display the zipfile comment (only, for unzip) */
int filespecs; /* number of real file specifications to be matched */
int xfilespecs; /* number of excluded filespecs to be matched */
int process_all_files = 0;
int create_dirs; /* used by main(), mapname(), checkdir() */
int extract_flag;
#if (defined(CRYPT) || !defined(NO_ZIPINFO))
int newzip; /* used in extract.c, crypt.c, zipinfo.c */
#endif
LONGINT real_ecrec_offset, expect_ecrec_offset;
long csize; /* used by list_files(), ReadByte(): must be signed */
long ucsize; /* used by list_files(), unReduce(), explode() */
long used_csize; /* used by extract_or_test_member(), explode() */
static char *fnames[2] = {"*", NULL}; /* default filenames vector */
char **pfnames = fnames, **pxnames = &fnames[1];
char near sig[5];
char near answerbuf[10];
min_info info[DIR_BLKSIZ], *pInfo=info;
/*---------------------------------------------------------------------------
unreduce/unshrink/explode/inflate working storage and globals:
---------------------------------------------------------------------------*/
union work area; /* see unzip.h for the definition of work */
ulg crc32val;
ush near mask_bits[] = {
0x0000,
0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
};
/*---------------------------------------------------------------------------
Input file variables:
---------------------------------------------------------------------------*/
uch *inbuf, *inptr; /* input buffer (any size is OK) and pointer */
int incnt;
ulg bitbuf;
int bits_left;
boolean zipeof;
#ifdef SFX
char *argv0; /* used for NT and EXE_EXTENSION */
#else
char *wildzipfn;
#endif
char *zipfn; /* GRR: MSWIN: must nuke any malloc'd zipfn... */
int zipfd; /* zipfile file handle */
LONGINT ziplen;
uch *hold;
char near local_hdr_sig[5]; /* initialize signatures at runtime so unzip */
char near central_hdr_sig[5]; /* executable won't look like a zipfile */
char near end_central_sig[5];
/* char extd_local_sig[5]; NOT USED YET */
cdir_file_hdr crec; /* used in unzip.c, extract.c, misc.c */
local_file_hdr lrec; /* used in unzip.c, extract.c */
ecdir_rec ecrec; /* used in unzip.c, extract.c */
struct stat statbuf; /* used by main, mapname, check_for_newer */
LONGINT cur_zipfile_bufstart; /* extract_or_test_files, readbuf, ReadByte */
LONGINT extra_bytes = 0; /* used in unzip.c, misc.c */
uch *extra_field = (uch *)NULL; /* used by VMS, Mac and OS/2 versions */
#ifdef MACOS
short gnVRefNum;
long glDirID;
OSType gostCreator;
OSType gostType;
boolean fMacZipped;
boolean macflag;
CursHandle rghCursor[4]; /* status cursors */
short giCursor = 0;
#endif
/*---------------------------------------------------------------------------
Output stream variables:
---------------------------------------------------------------------------*/
int mem_mode = 0;
int disk_full;
#ifdef SYMLINKS
int symlnk;
#endif
FILE *outfile;
uch *outbuf;
uch *outptr;
ulg outcnt; /* number of chars stored in outbuf */
#ifdef SMALL_MEM
uch *outbuf2; /* initialized in main() (never changes) */
#else
uch *outbuf2 = (uch *)NULL; /* malloc'd ONLY if unshrink and -a */
#endif
#ifdef MSWIN
char *filename;
#else
char near filename[FILNAMSIZ]; /* also used by NT for temporary SFX path */
#endif
/********************/
/* Global strings */
/********************/
char Far UnzipVersion[] = UZ_VERSION; /* now defined in version.h */
#ifndef NO_ZIPINFO
char Far ZipinfoVersion[] = ZI_VERSION;
#endif
char Far EndSigMsg[] = "\nnote:\
didn't find end-of-central-dir signature at end of central dir.\n";
char Far CentSigMsg[] =
"error: expected central file header signature not found (file #%u).\n";
char Far SeekMsg[] =
"error [%s]: attempt to seek before beginning of zipfile\n%s";
char Far FilenameNotMatched[] = "caution: filename not matched: %s\n";
char Far ExclFilenameNotMatched[] =
"caution: excluded filename not matched: %s\n";
#ifndef SFX
char Far CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
#endif
#ifdef VMS
char Far ReportMsg[] = "\
(please check that you have transferred or created the zipfile in the\n\
appropriate BINARY mode--this includes ftp, Kermit, AND unzip'd zipfiles)\n";
#else
char Far ReportMsg[] = "\
(please check that you have transferred or created the zipfile in the\n\
appropriate BINARY mode and that you have compiled unzip properly)\n";
#endif
/*******************/
/* Local strings */
/*******************/
#ifndef SFX
static char Far EnvUnZip[] = ENV_UNZIP;
static char Far EnvUnZip2[] = ENV_UNZIP2;
static char Far EnvZipInfo[] = ENV_ZIPINFO;
static char Far EnvZipInfo2[] = ENV_ZIPINFO2;
#endif
#if (!defined(SFX) || defined(SFX_EXDIR))
static char Far NotExtracting[] = "caution: not extracting; -d ignored\n";
static char Far MustGiveExdir[] =
"error: must specify directory to which to extract with -d option\n";
#endif
static char Far CentDirTooLong[] =
"error [%s]: reported length of central directory is\n\
%d bytes too long (Atari STZip zipfile? J.H.Holm ZIPSPLIT 1.1\n\
zipfile?). Compensating...\n";
static char Far InvalidOptionsMsg[] = "error:\
-fn or any combination of -c, -l, -p, -t, -u and -v options invalid\n";
static char Far IgnoreOOptionMsg[] =
"caution: both -n and -o specified; ignoring -o\n";
static char Far CantAllocateBuffers[] =
"error: can't allocate unzip buffers\n";
/* usage() strings */
#ifndef VMSCLI
#ifndef SFX
#ifdef VMS
static char Far Example2[] = "vms.c";
static char Far Example1[] =
"unzip \"-V\" foo \"Bar\" => must quote uppercase options and filenames in VMS";
#else
static char Far Example2[] = "ReadMe";
static char Far Example1[] =
"unzip -p foo | more => send contents of foo.zip via pipe into program more";
#endif /* ?VMS */
#ifdef DOS_NT_OS2
static char Far loc_str[] = " -$ label removables (-$$ => fixed disks)";
static char Far loc2str[] = "\
-s spaces in filenames => '_'\n";
#else /* !DOS_NT_OS2 */
#ifdef VMS
static char Far loc_str[] = "\"-X\" restore owner/protection info";
static char Far loc2str[] = "\n";
#else
static char Far loc_str[] = ""; /* Unix, Amiga, Mac, etc. */
/* char Far loc_str[] = " -X restore UID/GID info"; Unix version, in 5.2 */
static char Far loc2str[] = "";
#endif /* ?VMS */
#endif /* ?DOS_NT_OS2 */
#endif /* !SFX */
#ifndef NO_ZIPINFO
#ifdef VMSWILD
static char Far ZipInfoExample[] = "* or % (e.g., \"*font-%.zip\")";
#else
static char Far ZipInfoExample[] = "*, ?, [] (e.g., \"[a-j]*.zip\")";
#endif
static char Far ZipInfoUsageLine1[] = "\
ZipInfo %s, by Newtware and the fine folks at Info-ZIP.\n\
\n\
List name, date/time, attribute, size, compression method, etc., about files\n\
in list (excluding those in xlist) contained in the specified .zip archive(s).\
\n\"file[.zip]\" may be a wildcard name containing %s.\n\n\
usage: zipinfo [-12smlvhtTz] file[.zip] [list...] [-x xlist...]\n\
or: unzip %s-Z%s [-12smlvhtTz] file[.zip] [list...] [-x xlist...]\n";
static char Far ZipInfoUsageLine2[] = "\nmain\
listing-format options: -s short Unix \"ls -l\" format (def.)\n\
-1 filenames ONLY, one per line -m medium Unix \"ls -l\" format\n\
-2 just filenames but allow -h/-t/-z -l long Unix \"ls -l\" format\n\
-v verbose, multi-page format\n";
static char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\
-h print header line -t print totals for listed files or for all\n\
-z print zipfile comment %c-T%c print file times in sortable decimal format\
\n -x exclude filenames that follow from listing\n";
/*" -p disable automatic \"more\" function (for pipes) [not implemented]\n";*/
#endif /* !NO_ZIPINFO */
#endif /* !VMSCLI */
#ifdef BETA
static char Far BetaVersion[] = "%s\
THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n";
#endif
#ifdef SFX
# if (defined(SFX_EXDIR) && !defined(VMS))
static char Far UnzipSFXUsage[] = "\
UnZipSFX %s, by Info-ZIP (zip-bugs@wkuvx1.wku.edu).\n\
Valid options are -tfupcz and -d <exdir>; modifiers are -abjnoqCLV%s.\n";
# else
static char Far UnzipSFXUsage[] = "\
UnZipSFX %s, by Info-ZIP (zip-bugs@wkuvx1.wku.edu).\n\
Valid options are -tfupcz; modifiers are -abjnoqCLV%s.\n";
# endif
static char Far CantFindMyself[] =
"unzipsfx: can't find myself! [%s]\n";
#else /* !SFX */
static char Far CompileOptions[] = "UnZip special compilation options:\n";
static char Far CompileOptFormat[] = "\t%s\n";
static char Far EnvOptions[] = "\nUnZip and ZipInfo environment options:\n";
static char Far EnvOptFormat[] = "%16s: %s\n";
static char Far None[] = "[none]";
# ifdef NO_ZIPINFO
static char Far No_ZipInfo[] = "NO_ZIPINFO";
# endif
# ifdef CHECK_EOF
static char Far Check_EOF[] = "CHECK_EOF";
# endif
# ifdef DOSWILD
static char Far DosWild[] = "DOSWILD";
# endif
# ifdef VMSWILD
static char Far VmsWild[] = "VMSWILD";
# endif
# ifdef VMSCLI
static char Far VmsCLI[] = "VMSCLI";
# endif
# ifdef ASM_INFLATECODES
static char Far AsmInflateCodes[] = "ASM_INFLATECODES";
# endif
# ifdef ASM_CRC
static char Far AsmCRC[] = "ASM_CRC";
# endif
# ifdef REGARGS
static char Far RegArgs[] = "REGARGS";
# endif
# ifdef OLD_EXDIR
static char Far Old_Exdir[] = "OLD_EXDIR";
# endif
# ifdef CHECK_VERSIONS
static char Far Check_Versions[] = "CHECK_VERSIONS";
# endif
# ifdef RETURN_CODES
static char Far Return_Codes[] = "RETURN_CODES";
# endif
# ifdef RETURN_SEVERITY
static char Far Return_Severity[] = "RETURN_SEVERITY";
# endif
# ifdef DEBUG
static char Far Debug[] = "DEBUG";
# endif
# ifdef DEBUG_TIME
static char Far DebugTime[] = "DEBUG_TIME";
# endif
# ifdef CRYPT
static char Far Decryption[] = "[decryption]";
# endif
# ifdef __EMX__
static char Far EnvEMX[] = "EMX";
static char Far EnvEMXOPT[] = "EMXOPT";
# endif
# ifdef __GO32__
static char Far EnvGO32[] = "GO32";
static char Far EnvGO32TMP[] = "GO32TMP";
# endif
/* UnzipUsageLine1[] is also used in vms/cmdline.c: do not make it static */
char Far UnzipUsageLine1[] = "\
UnZip %s, by Info-ZIP. Portions (c) 1989 by S. H. Smith.\n\
Send bug reports to authors at zip-bugs@wkuvx1.wku.edu; see README for details.\
\n\n";
static char Far UnzipUsageLine2a[] = "\
Latest sources and executables are always in ftp.uu.net:/pub/archiving/zip, at\
\nleast as of date of this release; see \"Where\" for other ftp and non-ftp \
sites.\n\n";
#ifndef VMSCLI
static char Far UnzipUsageLine2[] = "\
Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]\n \
Default action is to extract files in list, except those in xlist, to exdir;\n\
file[.zip] may be a wildcard. %s\n\n";
#ifdef NO_ZIPINFO
# define ZIPINFO_MODE_OPTION ""
static char Far ZipinfoMode[] =
"(ZipInfo mode is disabled in this version.)";
#else
# define ZIPINFO_MODE_OPTION "[-Z] "
# ifdef VMS
static char Far ZipinfoMode[] =
"\"-Z\" => ZipInfo mode (`unzip \"-Z\"' for usage).";
# else
static char Far ZipinfoMode[] =
"-Z => ZipInfo mode (\"unzip -Z\" for usage).";
# endif
#endif /* ?NO_ZIPINFO */
static char Far UnzipUsageLine3[] = "\
-p extract files to pipe, no messages -l list files (short format)\n\
-f freshen existing files, create none -t test compressed archive data\n\
-u update files, create if necessary -z display archive comment\n\
-x exclude files which follow (in xlist) -d extract files into exdir\n\n";
static char Far UnzipUsageLine4[] = "\
modifiers: -q quiet mode (-qq => quieter)\n\
-n never overwrite existing files -a auto-convert any text files\n\
-o overwrite files WITHOUT prompting -aa treat ALL files as text\n \
-j junk paths (don't make directories) -v be verbose/print version info\n\
%c-C%c match filenames case-insensitively %c-L%c make (some) names \
lowercase\n %-42s %c-V%c retain VMS version numbers\n%s";
static char Far UnzipUsageLine5[] = "\
Examples (see unzip.doc for more info):\n\
unzip data1 -x joe => extract all files except joe from zipfile data1.zip\n\
%s\n\
unzip -fo foo %-6s => quietly replace existing %s if archive file newer\n";
#endif /* !VMSCLI */
/* process_zipfiles() strings */
static char Far FilesProcessOK[] = "%d archive%s successfully processed.\n";
static char Far ArchiveWarning[] =
"%d archive%s had warnings but no fatal errors.\n";
static char Far ArchiveFatalError[] = "%d archive%s had fatal errors.\n";
static char Far FileHadNoZipfileDir[] =
"%d file%s had no zipfile directory.\n";
static char Far ZipfileWasDir[] = "1 \"zipfile\" was a directory.\n";
static char Far ManyZipfilesWereDir[] =
"%d \"zipfiles\" were directories.\n";
static char Far NoZipfileFound[] = "No zipfiles found.\n";
#endif /* ?SFX */
/* do_seekable() strings */
#ifndef SFX
#ifdef UNIX
static char Far CantFindZipfileDirMsg[] =
"%s: can't find zipfile directory in one of %s or\n\
%s%s.zip, and can't find %s, period.\n";
static char Far CantFindEitherZipfile[] =
"%s: can't find %s, %s.zip or %s, so there.\n";
#else /* !UNIX */
static char Far CantFindZipfileDirMsg[] =
"%s: can't find zipfile directory in %s,\n\
%sand can't find %s, period.\n";
static char Far CantFindEitherZipfile[] =
"%s: can't find either %s or %s, so there.\n";
#endif /* ?UNIX */
static char Far MaybeExe[] =
"note: %s may be a plain executable, not an archive\n";
static char Far CentDirNotInZipMsg[] = "\n\
Zipfile is part of a multi-disk archive, and this is not the disk on\n\
which the central zipfile directory begins.\n";
#ifdef NO_MULTIPART
static char Far NoMultiDiskArcSupport[] =
"\nerror [%s]: zipfile is part of multi-disk archive\n\
(sorry, not yet supported).\n";
static 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 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 char Far ExtraBytesAtStart[] =
"warning [%s]: extra %ld bytes at beginning or within zipfile\n\
(attempting to process anyway)\n";
#endif /* !SFX */
static char Far MissingBytes[] =
"error [%s]: missing %ld bytes in zipfile\n\
(attempting to process anyway)\n";
static char Far NullCentDirOffset[] =
"error [%s]: NULL central directory offset\n\
(attempting to process anyway)\n";
static char Far ZipfileEmpty[] = "warning [%s]: zipfile is empty\n";
static char Far CentDirStartNotFound[] =
"error [%s]: start of central directory not found;\n\
zipfile corrupt.\n%s";
static char Far ZipfileCommTrunc1[] = "\ncaution: zipfile comment truncated\n";
#ifdef MSWIN
# include "winsetup.c" /* duplicates some code in main() */
#else /* !MSWIN */
/******************/
/* Main program */
/******************/
int MAIN(argc, argv) /* return PK-type error code (except under VMS) */
int argc;
char *argv[];
{
#ifndef NO_ZIPINFO
char *p;
#endif
int error=FALSE;
#if defined(__IBMC__) && defined(__DEBUG_ALLOC__)
extern void DebugMalloc(void);
atexit(DebugMalloc);
#endif
/*---------------------------------------------------------------------------
Macintosh initialization code.
---------------------------------------------------------------------------*/
#ifdef MACOS
int a;
for (a = 0; a < 4; ++a)
rghCursor[a] = GetCursor(a+128);
giCursor = 0;
aflag=cflag=dflag=fflag=L_flag=jflag=qflag=tflag=uflag=vflag=zflag = 0;
local_hdr_sig[1] = central_hdr_sig[1] = end_central_sig[1] = '\0';
/* extd_local_sig[1] = '\0'; */
error = FALSE;
overwrite_none = overwrite_all = force_flag = 0;
#endif /* MACOS */
#ifdef MALLOC_WORK
area.Slide = (uch *)calloc(8193, sizeof(short)+sizeof(char)+sizeof(char));
area.shrink.Prefix_of = (short *)area.Slide;
area.shrink.Suffix_of = area.Slide + (sizeof(short)*(HSIZE+1));
area.shrink.Stack = area.Slide + (sizeof(short) + sizeof(char))*(HSIZE+1);
#endif
/*---------------------------------------------------------------------------
Human68K initialization code.
---------------------------------------------------------------------------*/
#ifdef __human68k__
InitTwentyOne();
#endif
/*---------------------------------------------------------------------------
Set signal handler for restoring echo, warn of zipfile corruption, etc.
---------------------------------------------------------------------------*/
signal(SIGINT, handler);
#ifdef SIGTERM /* some systems really have no SIGTERM */
signal(SIGTERM, handler);
#endif
#ifdef SIGBUS
signal(SIGBUS, handler);
#endif
#ifdef SIGSEGV
signal(SIGSEGV, handler);
#endif
/*---------------------------------------------------------------------------
First figure out if we're running in UnZip mode or ZipInfo mode, and put
the appropriate environment-variable options into the queue. Then rip
through any command-line options lurking about...
---------------------------------------------------------------------------*/
#ifdef SFX
argv0 = argv[0];
#if defined(OS2) || defined(NT)
zipfn = GetLoadPath(); /* non-MSC NT puts path into filename[] */
#else
zipfn = argv0;
#endif
zipinfo_mode = FALSE;
if ((error = uz_opts(&argc, &argv)) != 0)
RETURN(error);
#else /* !SFX */
#ifdef MSDOS
/* extract MKS extended argument list from environment (before envargs!) */
mksargs(&argc, &argv);
#endif
#ifdef VMSCLI
{
ulg status = vms_unzip_cmdline(&argc, &argv);
if (!(status & 1))
return status;
}
#endif /* VMSCLI */
#ifndef NO_ZIPINFO
if ((p = strrchr(argv[0], DIR_END)) == (char *)NULL)
p = argv[0];
else
++p;
if (STRNICMP(p, "zipinfo", 7) == 0 || STRNICMP(p, "ii", 2) == 0 ||
(argc > 1 && strncmp(argv[1], "-Z", 2) == 0))
{
zipinfo_mode = TRUE;
envargs(&argc, &argv, LoadFarStringSmall(EnvZipInfo),
LoadFarStringSmall2(EnvZipInfo2));
error = zi_opts(&argc, &argv);
} else
#endif /* NO_ZIPINFO */
{
zipinfo_mode = FALSE;
envargs(&argc, &argv, LoadFarStringSmall(EnvUnZip),
LoadFarStringSmall2(EnvUnZip2));
error = uz_opts(&argc, &argv);
}
if ((argc < 0) || error)
RETURN(error);
#endif /* ?SFX */
/*---------------------------------------------------------------------------
Now get the zipfile name from the command line and then process any re-
maining options and file specifications.
---------------------------------------------------------------------------*/
#ifdef DOS_NT_OS2
/* convert MSDOS-style directory separators to Unix-style ones for
* user's convenience (include zipfile name itself)
*/
pfnames = argv;
while (*pfnames != NULL) {
char *q;
for (q = *pfnames; *q; ++q)
if (*q == '\\')
*q = '/';
++pfnames;
}
#endif /* DOS_NT_OS2 */
#ifndef SFX
wildzipfn = *argv++;
#endif
#if (defined(OLD_EXDIR) || (defined(SFX) && !defined(SFX_EXDIR)))
#ifndef SFX
if (argc > 0) {
/* -d: "name/" immediately after zipfile name is a stored directory to
* be extracted--do NOT treat as directory to which to extract files
*/
if (extract_flag && !dflag) {
create_dirs = !fflag;
if ((error = checkdir(*argv, ROOT)) > 2) /* mem, or file in way */
RETURN(error);
else if (!error) { /* it IS extract-to dir, so adjust pointers */
++argv;
--argc;
}
}
}
#endif /* !SFX */
filespecs = argc;
xfilespecs = 0;
if (argc > 0) {
char **pp = argv-1;
pfnames = argv;
while (*++pp)
if (strcmp(*pp, "-x") == 0) {
if (pp > argv) {
*pp = 0; /* terminate pfnames */
filespecs = pp - pfnames;
} else {
pfnames = fnames; /* defaults */
filespecs = 0;
}
pxnames = pp + 1; /* excluded-names ptr starts after -x */
xfilespecs = argc - filespecs - 1;
break; /* skip rest of args */
}
process_all_files = FALSE;
} else
process_all_files = TRUE; /* for speed */
#else /* !(OLD_EXDIR || (SFX && !SFX_EXDIR)) */
filespecs = argc;
xfilespecs = 0;
if (argc > 0) {
int in_files=FALSE, in_xfiles=FALSE;
char **pp = argv-1;
process_all_files = FALSE;
pfnames = argv;
while (*++pp) {
Trace((stderr, "pp - argv = %d\n", pp-argv));
if (!dflag && strncmp(*pp, "-d", 2) == 0) {
char *q = *pp;
int firstarg = (pp == argv);
dflag = TRUE;
if (in_files) { /* ... zipfile ... -d exdir ... */
*pp = 0; /* terminate pfnames */
filespecs = pp - pfnames;
in_files = FALSE;
} else if (in_xfiles) {
*pp = 0; /* terminate pxnames */
xfilespecs = pp - pxnames;
/* "... -x xlist -d exdir": nothing left */
}
/* first check for "-dpath", then for "-d path" */
if (q[2])
q += 2;
else if (*++pp)
q = *pp;
else {
FPRINTF(stderr, LoadFarString(MustGiveExdir));
RETURN(PK_PARAM); /* don't extract here by accident */
}
if (extract_flag) {
create_dirs = !fflag;
if ((error = checkdir(q, ROOT)) > 2)
RETURN(error); /* out of memory, or file in way */
} else
FPRINTF(stderr, LoadFarString(NotExtracting));
if (firstarg) /* ... zipfile -d exdir ... */
if (pp[1]) {
pfnames = pp + 1; /* argv+2 */
filespecs = argc - (pfnames-argv); /* for now... */
} else {
process_all_files = TRUE;
pfnames = fnames; /* GRR: necessary? */
filespecs = 0; /* GRR: necessary? */
break;
}
} else if (!in_xfiles) {
if (strcmp(*pp, "-x") == 0) {
in_xfiles = TRUE;
if (pp == argv || (pp == argv+2 && dflag)) {
pfnames = fnames; /* defaults */
filespecs = 0;
} else if (in_files) {
*pp = 0; /* terminate pfnames */
filespecs = pp - pfnames; /* adjust count */
in_files = FALSE;
}
pxnames = pp + 1; /* excluded-names ptr starts after -x */
xfilespecs = argc - (pxnames-argv); /* anything left... */
} else
in_files = TRUE;
}
}
} else
process_all_files = TRUE; /* for speed */
#endif /* ?(OLD_EXDIR || (SFX && !SFX_EXDIR)) */
/*---------------------------------------------------------------------------
Okey dokey, we have everything we need to get started. Let's roll.
---------------------------------------------------------------------------*/
inbuf = (uch *)malloc(INBUFSIZ + 4); /* 4 extra for hold[] (below) */
outbuf = (uch *)malloc(OUTBUFSIZ + 1); /* 1 extra for string termin. */
if ((inbuf == (uch *)NULL) || (outbuf == (uch *)NULL)) {
FPRINTF(stderr, LoadFarString(CantAllocateBuffers));
RETURN(PK_MEM);
}
hold = inbuf + INBUFSIZ; /* to check for boundary-spanning signatures */
#ifdef SMALL_MEM
outbuf2 = outbuf+RAWBUFSIZ; /* never changes */
#endif
RETURN(process_zipfiles()); /* keep passing errors back... */
} /* end main() */
/**********************/
/* Function uz_opts() */
/**********************/
int uz_opts(pargc, pargv)
int *pargc;
char ***pargv;
{
char **argv, *s;
int argc, c, error=FALSE, negative=0;
argc = *pargc;
argv = *pargv;
while (--argc > 0 && (*++argv)[0] == '-') {
s = argv[0] + 1;
while ((c = *s++) != 0) { /* "!= 0": prevent Turbo C warning */
switch (c) {
case ('-'):
++negative;
break;
case ('a'):
if (negative) {
aflag = MAX(aflag-negative,0);
negative = 0;
} else
++aflag;
break;
case ('b'):
if (negative)
negative = 0; /* do nothing: "-b" is default */
else
aflag = 0;
break;
case ('c'):
if (negative) {
cflag = FALSE, negative = 0;
#ifdef NATIVE
aflag = 0;
#endif
} else {
cflag = TRUE;
#ifdef NATIVE
aflag = 2; /* so you can read it on the screen */
#endif
}
break;
case ('C'): /* -C: match filenames case-insensitively */
if (negative)
C_flag = FALSE, negative = 0;
else
C_flag = TRUE;
break;
case ('d'): /* arg after zipfn is stored dir, not extract-to */
#ifdef OLD_EXDIR
if (negative)
dflag = FALSE, negative = 0;
else
dflag = TRUE;
#endif
break;
case ('e'): /* just ignore -e, -x options (extract) */
break;
case ('f'): /* "freshen" (extract only newer files) */
if (negative)
fflag = uflag = FALSE, negative = 0;
else
fflag = uflag = TRUE;
break;
case ('j'): /* junk pathnames/directory structure */
if (negative)
jflag = FALSE, negative = 0;
else
jflag = TRUE;
break;
#ifndef SFX
case ('l'):
if (negative) {
vflag = MAX(vflag-negative,0);
negative = 0;
} else
++vflag;
break;
#endif /* !SFX */
case ('L'): /* convert (some) filenames to lowercase */
if (negative)
L_flag = FALSE, negative = 0;
else
L_flag = TRUE;
break;
case ('n'): /* don't overwrite any files */
if (negative)
overwrite_none = FALSE, negative = 0;
else
overwrite_none = TRUE;
break;
case ('o'): /* OK to overwrite files without prompting */
if (negative) {
overwrite_all = MAX(overwrite_all-negative,0);
force_flag = MAX(force_flag-negative,0);
negative = 0;
} else {
++overwrite_all;
++force_flag; /* (share -o for now) force to cont. */
}
break;
case ('p'): /* pipes: extract to stdout, no messages */
if (negative) {
cflag = FALSE;
qflag = MAX(qflag-999,0);
negative = 0;
} else {
cflag = TRUE;
qflag += 999;
}
break;
case ('q'): /* quiet: fewer comments/messages */
if (negative) {
qflag = MAX(qflag-negative,0);
negative = 0;
} else
++qflag;
break;
#ifdef DOS_NT_OS2
case ('s'): /* spaces in filenames: allow by default */
if (negative)
sflag = FALSE, negative = 0;
else
sflag = TRUE;
break;
#endif
case ('t'):
if (negative)
tflag = FALSE, negative = 0;
else
tflag = TRUE;
break;
case ('u'): /* update (extract only new and newer files) */
if (negative)
uflag = FALSE, negative = 0;
else
uflag = TRUE;
break;
case ('U'): /* obsolete; to be removed in future release */
if (negative)
L_flag = TRUE, negative = 0;
else
L_flag = FALSE;
break;
#ifndef SFX
case ('v'): /* verbose */
if (negative) {
vflag = MAX(vflag-negative,0);
negative = 0;
} else if (vflag)
++vflag;
else
vflag = 2;
break;
#endif /* !SFX */
case ('V'): /* Version (retain VMS/DEC-20 file versions) */
if (negative)
V_flag = FALSE, negative = 0;
else
V_flag = TRUE;
break;
case ('x'): /* extract: default */
break;
#ifdef VMS
case ('X'): /* restore owner/protection info (need privs?) */
if (negative)
secinf = FALSE, negative = 0;
else
secinf = TRUE;
break;
#endif /* VMS */
case ('z'): /* display only the archive comment */
if (negative) {
zflag -= negative;
negative = 0;
} else
++zflag;
break;
#ifdef DOS_NT_OS2
case ('$'):
if (negative) {
volflag = MAX(volflag-negative,0);
negative = 0;
} else
++volflag;
break;
#endif /* DOS_NT_OS2 */
default:
error = TRUE;
break;
} /* end switch */
} /* end while (not end of argument string) */
} /* end while (not done with switches) */
/*---------------------------------------------------------------------------
Check for nonsensical combinations of options.
---------------------------------------------------------------------------*/
if ((cflag && tflag) || (cflag && uflag) || (tflag && uflag) ||
(fflag && overwrite_none)) {
FPRINTF(stderr, LoadFarString(InvalidOptionsMsg));
error = TRUE;
}
if (aflag > 2)
aflag = 2;
if (overwrite_all && overwrite_none) {
FPRINTF(stderr, LoadFarString(IgnoreOOptionMsg));
overwrite_all = FALSE;
}
#ifdef SFX
if (error)
#else
if ((argc-- == 0) || error)
#endif
{
*pargc = argc;
*pargv = argv;
#ifndef SFX
if (vflag >= 2 && argc == -1) {
if (qflag > 3)
PRINTF("%d\n", (UZ_MAJORVER*100 + UZ_MINORVER*10 + PATCHLEVEL));
else {
char *envptr, *getenv();
int numopts = 0;
PRINTF(LoadFarString(UnzipUsageLine1),
LoadFarStringSmall(UnzipVersion));
PRINTF(LoadFarString(UnzipUsageLine2a));
version();
PRINTF(LoadFarString(CompileOptions));
#ifdef NO_ZIPINFO
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(No_ZipInfo));
++numopts;
#endif
#ifdef CHECK_EOF
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(Check_EOF));
++numopts;
#endif
#ifdef DOSWILD
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(DosWild));
++numopts;
#endif
#ifdef VMSWILD
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(VmsWild));
++numopts;
#endif
#ifdef VMSCLI
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(VmsCLI));
++numopts;
#endif
#ifdef ASM_INFLATECODES
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(AsmInflateCodes));
++numopts;
#endif
#ifdef ASM_CRC
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(AsmCRC));
++numopts;
#endif
#ifdef REGARGS
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(RegArgs));
++numopts;
#endif
#ifdef OLD_EXDIR
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(Old_Exdir));
++numopts;
#endif
#ifdef CHECK_VERSIONS
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(Check_Versions));
++numopts;
#endif
#ifdef RETURN_CODES
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(Return_Codes));
++numopts;
#endif
#ifdef RETURN_SEVERITY
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(Return_Severity));
++numopts;
#endif
#ifdef DEBUG
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(Debug));
++numopts;
#endif
#ifdef DEBUG_TIME
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(DebugTime));
++numopts;
#endif
#ifdef CRYPT
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(Decryption));
++numopts;
#endif
if (numopts == 0)
PRINTF(LoadFarString(CompileOptFormat),
LoadFarStringSmall(None));
PRINTF(LoadFarString(EnvOptions));
envptr = getenv(LoadFarStringSmall(EnvUnZip));
PRINTF(LoadFarString(EnvOptFormat),
LoadFarStringSmall(EnvUnZip),
(envptr == (char *)NULL || *envptr == 0)?
LoadFarStringSmall2(None) : envptr);
envptr = getenv(LoadFarStringSmall(EnvUnZip2));
PRINTF(LoadFarString(EnvOptFormat),
LoadFarStringSmall(EnvUnZip2),
(envptr == (char *)NULL || *envptr == 0)?
LoadFarStringSmall2(None) : envptr);
envptr = getenv(LoadFarStringSmall(EnvZipInfo));
PRINTF(LoadFarString(EnvOptFormat),
LoadFarStringSmall(EnvZipInfo),
(envptr == (char *)NULL || *envptr == 0)?
LoadFarStringSmall2(None) : envptr);
envptr = getenv(LoadFarStringSmall(EnvZipInfo2));
PRINTF(LoadFarString(EnvOptFormat),
LoadFarStringSmall(EnvZipInfo2),
(envptr == (char *)NULL || *envptr == 0)?
LoadFarStringSmall2(None) : envptr);
#ifdef __EMX__
envptr = getenv(LoadFarStringSmall(EnvEMX));
PRINTF(LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvEMX),
(envptr == (char *)NULL || *envptr == 0)?
LoadFarStringSmall2(None) : envptr);
envptr = getenv(LoadFarStringSmall(EnvEMXOPT));
PRINTF(LoadFarString(EnvOptFormat),
LoadFarStringSmall(EnvEMXOPT),
(envptr == (char *)NULL || *envptr == 0)?
LoadFarStringSmall2(None) : envptr);
#endif /* __EMX__ */
#ifdef __GO32__
envptr = getenv(LoadFarStringSmall(EnvGO32));
PRINTF(LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvGO32),
(envptr == (char *)NULL || *envptr == 0)?
LoadFarStringSmall2(None) : envptr);
envptr = getenv(LoadFarStringSmall(EnvGO32TMP));
PRINTF(LoadFarString(EnvOptFormat),
LoadFarStringSmall(EnvGO32TMP),
(envptr == (char *)NULL || *envptr == 0)?
LoadFarStringSmall2(None) : envptr);
#endif /* __GO32__ */
}
return 0;
} else
#endif /* !SFX */
return usage(error);
}
if (cflag || tflag || vflag)
extract_flag = FALSE;
else
extract_flag = TRUE;
*pargc = argc;
*pargv = argv;
return 0;
} /* end function uz_opts() */
/********************/
/* Function usage() */
/********************/
#ifdef SFX
# ifdef VMS
# define LOCAL "X. Quote uppercase options"
# else
# ifdef DOS_NT_OS2
# define LOCAL "s$"
# else
# ifdef AMIGA
# define LOCAL "$"
# else
# define LOCAL ""
# endif
# endif /* ?DOS_NT_OS2 */
# endif /* ?VMS */
int usage(error) /* return PK-type error code */
int error;
{
FILE *usagefp;
if (error)
usagefp = (FILE *)stderr;
else
usagefp = (FILE *)stdout;
FPRINTF(usagefp, LoadFarString(UnzipSFXUsage),
LoadFarStringSmall(UnzipVersion), LOCAL);
#ifdef BETA
FPRINTF(usagefp, LoadFarString(BetaVersion), "\n", "SFX");
#endif
if (error)
return PK_PARAM;
else
return PK_COOL; /* just wanted usage screen: no error */
} /* end function usage() */
#else /* !SFX */
#ifndef VMSCLI
int usage(error) /* return PK-type error code */
int error;
{
#ifdef VMS
# define QUOT '\"'
# define QUOTS "\""
#else
# define QUOT ' '
# define QUOTS ""
#endif
FILE *usagefp;
/*---------------------------------------------------------------------------
If user requested usage, send it to stdout; else send to stderr.
---------------------------------------------------------------------------*/
if (error)
usagefp = (FILE *)stderr;
else
usagefp = (FILE *)stdout;
/*---------------------------------------------------------------------------
Print either ZipInfo usage or UnZip usage, depending on incantation.
(Strings must be no longer than 512 bytes for Turbo C, apparently.)
---------------------------------------------------------------------------*/
if (zipinfo_mode) {
#ifndef NO_ZIPINFO
FPRINTF(usagefp, LoadFarString(ZipInfoUsageLine1),
LoadFarStringSmall(ZipinfoVersion),
LoadFarStringSmall2(ZipInfoExample), QUOTS,QUOTS);
FPRINTF(usagefp, LoadFarString(ZipInfoUsageLine2));
FPRINTF(usagefp, LoadFarString(ZipInfoUsageLine3), QUOT,QUOT);
#ifdef VMS
FPRINTF(usagefp, "\nRemember that non-lowercase filespecs must be\
quoted in VMS (e.g., \"Makefile\").\n");
#endif
#endif /* !NO_ZIPINFO */
} else { /* UnZip mode */
FPRINTF(usagefp, LoadFarString(UnzipUsageLine1),
LoadFarStringSmall(UnzipVersion));
#ifdef BETA
FPRINTF(usagefp, LoadFarString(BetaVersion), "", "");
#endif
FPRINTF(usagefp, LoadFarString(UnzipUsageLine2), ZIPINFO_MODE_OPTION,
LoadFarStringSmall(ZipinfoMode));
FPRINTF(usagefp, LoadFarString(UnzipUsageLine3));
FPRINTF(usagefp, LoadFarString(UnzipUsageLine4), QUOT,QUOT, QUOT,QUOT,
LoadFarStringSmall(loc_str), QUOT,QUOT,
LoadFarStringSmall2(loc2str));
/* This is extra work for SMALL_MEM, but it will work since
* LoadFarStringSmall2 uses the same buffer. Remember, this
* is a hack. */
FPRINTF(usagefp, LoadFarString(UnzipUsageLine5),
LoadFarStringSmall(Example1),
LoadFarStringSmall2(Example2),
LoadFarStringSmall2(Example2));
}
if (error)
return PK_PARAM;
else
return PK_COOL; /* just wanted usage screen: no error */
} /* end function usage() */
#endif /* !VMSCLI */
#endif /* ?SFX */
#endif /* ?MSWIN */
/*******************************/
/* Function process_zipfiles() */
/*******************************/
int process_zipfiles() /* return PK-type error code */
{
#ifndef SFX
char *lastzipfn = (char *)NULL;
int NumWinFiles, NumLoseFiles, NumWarnFiles;
int NumMissDirs, NumMissFiles;
#endif
int error=0, error_in_archive=0;
/*---------------------------------------------------------------------------
Start by constructing the various PK signature strings.
---------------------------------------------------------------------------*/
local_hdr_sig[0] /* = extd_local_sig[0] */ = '\120'; /* ASCII 'P', */
central_hdr_sig[0] = end_central_sig[0] = '\120'; /* not EBCDIC */
strcpy(local_hdr_sig+1, LOCAL_HDR_SIG);
strcpy(central_hdr_sig+1, CENTRAL_HDR_SIG);
strcpy(end_central_sig+1, END_CENTRAL_SIG);
/* strcpy(extd_local_sig+1, EXTD_LOCAL_SIG); still to be used in multi? */
/*---------------------------------------------------------------------------
Match (possible) wildcard zipfile specification with existing files and
attempt to process each. If no hits, try again after appending ".zip"
suffix. If still no luck, give up.
---------------------------------------------------------------------------*/
#ifdef SFX
if ((error = do_seekable(0)) == PK_NOZIP) {
#ifdef EXE_EXTENSION
int len=strlen(argv0);
/* append .exe if appropriate; also .sfx? */
if ((zipfn = (char *)malloc(len+5)) != (char *)NULL) {
strcpy(zipfn, argv0);
strcpy(zipfn+len, EXE_EXTENSION);
error = do_seekable(0);
free(zipfn);
zipfn = argv0; /* for "can't find myself" message only */
}
#endif /* EXE_EXTENSION */
#ifdef NT
zipfn = argv0; /* for "can't find myself" message only */
#endif
}
if (error) {
if (error == IZ_DIR)
error_in_archive = PK_NOZIP;
else
error_in_archive = error;
if (error == PK_NOZIP)
FPRINTF(stderr, LoadFarString(CantFindMyself), zipfn);
}
#else /* !SFX */
NumWinFiles = NumLoseFiles = NumWarnFiles = 0;
NumMissDirs = NumMissFiles = 0;
while ((zipfn = do_wild(wildzipfn)) != (char *)NULL) {
Trace((stderr, "do_wild( %s ) returns %s\n", wildzipfn, zipfn));
lastzipfn = zipfn;
/* print a blank line between the output of different zipfiles */
if (!qflag && error != PK_NOZIP && error != IZ_DIR &&
(NumWinFiles+NumLoseFiles+NumWarnFiles+NumMissFiles) > 0)
PRINTF("\n");
FFLUSH(stdout);
if ((error = do_seekable(0)) == PK_WARN)
++NumWarnFiles;
else if (error == IZ_DIR)
++NumMissDirs;
else if (error == PK_NOZIP)
++NumMissFiles;
else if (error)
++NumLoseFiles;
else
++NumWinFiles;
if (error != IZ_DIR && error > error_in_archive)
error_in_archive = error;
Trace((stderr, "do_seekable(0) returns %d\n", error));
} /* end while-loop (wildcard zipfiles) */
if ((NumWinFiles + NumWarnFiles + NumLoseFiles) == 0 &&
(NumMissDirs + NumMissFiles) == 1 && lastzipfn != (char *)NULL)
{
char *p = lastzipfn + strlen(lastzipfn);
NumMissDirs = NumMissFiles = 0;
if (error_in_archive == PK_NOZIP)
error_in_archive = PK_COOL;
zipfn = lastzipfn;
strcpy(p, ".zip");
#ifdef UNIX
if ((error = do_seekable(0)) == PK_NOZIP || error == IZ_DIR) {
if (error == IZ_DIR)
++NumMissDirs;
strcpy(p, ".ZIP");
error = do_seekable(1);
}
#else
error = do_seekable(1);
#endif
if (error == PK_WARN)
++NumWarnFiles;
else if (error == IZ_DIR)
++NumMissDirs;
else if (error == PK_NOZIP)
/* if increment again => bug: "1 file had no zipfile directory." */
/* ++NumMissFiles */ ;
else if (error)
++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.version_needed_to_extract[1], NUM_HOSTS); */
pInfo->lcflag = 0;
if (L_flag) /* user specified case-conversion */
switch (pInfo->hostnum) {
case FS_FAT_: /* PKZIP and zip -k store in uppercase */
case ATARI_: /* MS-DOS filesystem */
case CPM_: /* like MS-DOS, right? */
case VM_CMS_: /* all caps? */
case TOPS20_:
case VMS_: /* our Zip uses lowercase, but ASi's doesn't */
/* case Z_SYSTEM_: ? */
/* case QDOS_: ? */
pInfo->lcflag = 1; /* convert filename to lowercase */
break;
default: /* AMIGA_, FS_HPFS_, FS_NTFS_, MAC_, UNIX_, */
break; /* (Z_SYSTEM_): no conversion */
}
/* do Amigas (AMIGA_) also have volume labels? */
if (IS_VOLID(crec.external_file_attributes) &&
(pInfo->hostnum == FS_FAT_ || pInfo->hostnum == FS_HPFS_ ||
pInfo->hostnum == FS_NTFS_ || pInfo->hostnum == ATARI_))
{
pInfo->vollabel = TRUE;
pInfo->lcflag = 0; /* preserve case of volume labels */
} else
pInfo->vollabel = FALSE;
return PK_COOL;
} /* end function process_cdir_file_hdr() */
/*************************************/
/* Function process_local_file_hdr() */
/*************************************/
int process_local_file_hdr() /* return PK-type error code */
{
local_byte_hdr byterec;
/*---------------------------------------------------------------------------
Read the next local file header and do any necessary machine-type con-
versions (byte ordering, structure padding compensation--do so by copy-
ing the data from the array into which it was read (byterec) to the
usable struct (lrec)).
---------------------------------------------------------------------------*/
if (readbuf((char *)byterec, LREC_SIZE) == 0)
return PK_EOF;
lrec.version_needed_to_extract[0] = byterec[L_VERSION_NEEDED_TO_EXTRACT_0];
lrec.version_needed_to_extract[1] = byterec[L_VERSION_NEEDED_TO_EXTRACT_1];
lrec.general_purpose_bit_flag = makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]);
lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]);
lrec.last_mod_file_time = makeword(&byterec[L_LAST_MOD_FILE_TIME]);
lrec.last_mod_file_date = makeword(&byterec[L_LAST_MOD_FILE_DATE]);
lrec.crc32 = makelong(&byterec[L_CRC32]);
lrec.csize = makelong(&byterec[L_COMPRESSED_SIZE]);
lrec.ucsize = makelong(&byterec[L_UNCOMPRESSED_SIZE]);
lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]);
lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]);
csize = (long) lrec.csize;
ucsize = (long) lrec.ucsize;
if ((lrec.general_purpose_bit_flag & 8) != 0) {
/* can't trust local header, use central directory: */
lrec.crc32 = pInfo->crc;
csize = (long)(lrec.csize = pInfo->compr_size);
}
return PK_COOL;
} /* end function process_local_file_hdr() */