Tizen 2.0 Release tizen_2.0 accepted/tizen_2.0/20130215.202531 submit/tizen_2.0/20130215.192141
authorHyungKyu Song <hk76.song@samsung.com>
Fri, 15 Feb 2013 15:51:52 +0000 (00:51 +0900)
committerHyungKyu Song <hk76.song@samsung.com>
Fri, 15 Feb 2013 15:51:52 +0000 (00:51 +0900)
326 files changed:
BUGS [new file with mode: 0644]
CHANGES [new file with mode: 0644]
INSTALL [new file with mode: 0644]
LICENSE [new file with mode: 0644]
MANUAL [new file with mode: 0644]
README [new file with mode: 0644]
README.CR [new file with mode: 0644]
TODO [new file with mode: 0644]
USexport.msg [new file with mode: 0644]
WHATSNEW [new file with mode: 0644]
WHERE [new file with mode: 0644]
acorn/GMakefile [new file with mode: 0644]
acorn/ReadMe [new file with mode: 0644]
acorn/ReadMe.GMakefile [new file with mode: 0644]
acorn/RunMe1st [new file with mode: 0644]
acorn/acornzip.c [new file with mode: 0644]
acorn/makefile [new file with mode: 0644]
acorn/match.s [new file with mode: 0644]
acorn/osdep.h [new file with mode: 0644]
acorn/riscos.c [new file with mode: 0644]
acorn/riscos.h [new file with mode: 0644]
acorn/sendbits.s [new file with mode: 0644]
acorn/srcrename [new file with mode: 0644]
acorn/swiven.h [new file with mode: 0644]
acorn/swiven.s [new file with mode: 0644]
acorn/zipup.h [new file with mode: 0644]
amiga/LMKfile [new file with mode: 0644]
amiga/README [new file with mode: 0644]
amiga/amiga.c [new file with mode: 0644]
amiga/amiga.h [new file with mode: 0644]
amiga/amigazip.c [new file with mode: 0644]
amiga/crc_68.a [new file with mode: 0644]
amiga/deflate.a [new file with mode: 0644]
amiga/filedate.c [new file with mode: 0644]
amiga/makefile.azt [new file with mode: 0644]
amiga/match.a [new file with mode: 0644]
amiga/match_68.a [new file with mode: 0644]
amiga/osdep.h [new file with mode: 0644]
amiga/smakefile [new file with mode: 0644]
amiga/stat.c [new file with mode: 0644]
amiga/time_lib.c [new file with mode: 0644]
amiga/timezone.doc [new file with mode: 0644]
amiga/z-stat.h [new file with mode: 0644]
amiga/z-time.h [new file with mode: 0644]
amiga/zipup.h [new file with mode: 0644]
aosvs/aosvs.c [new file with mode: 0644]
aosvs/make.cli [new file with mode: 0644]
api.c [new file with mode: 0644]
api.h [new file with mode: 0644]
atari/Makefile [new file with mode: 0644]
atari/README [new file with mode: 0644]
atari/atari.c [new file with mode: 0644]
atari/make_all.mup [new file with mode: 0644]
atari/make_zip.mup [new file with mode: 0644]
atari/osdep.h [new file with mode: 0644]
atari/zipup.h [new file with mode: 0644]
atheos/Contents [new file with mode: 0644]
atheos/Makefile [new file with mode: 0644]
atheos/README [new file with mode: 0644]
atheos/atheos.c [new file with mode: 0644]
atheos/osdep.h [new file with mode: 0644]
atheos/zipup.h [new file with mode: 0644]
beos/Contents [new file with mode: 0644]
beos/Makefile [new file with mode: 0644]
beos/README [new file with mode: 0644]
beos/beos.c [new file with mode: 0644]
beos/osdep.h [new file with mode: 0644]
beos/zipup.h [new file with mode: 0644]
cmsmvs/README.CMS [new file with mode: 0644]
cmsmvs/README.MVS [new file with mode: 0644]
cmsmvs/README.MVS.LE [new file with mode: 0644]
cmsmvs/cczip.exec [new file with mode: 0644]
cmsmvs/cms.c [new file with mode: 0644]
cmsmvs/cmsmvs.c [new file with mode: 0644]
cmsmvs/cmsmvs.h [new file with mode: 0644]
cmsmvs/cstat.h [new file with mode: 0644]
cmsmvs/mc.exec [new file with mode: 0644]
cmsmvs/mvs.c [new file with mode: 0644]
cmsmvs/mvs.h [new file with mode: 0644]
cmsmvs/mvs.mki [new file with mode: 0644]
cmsmvs/pipzip.rexx [new file with mode: 0644]
cmsmvs/zip.exec [new file with mode: 0644]
cmsmvs/zip.makefile [new file with mode: 0644]
cmsmvs/zipcloak.exec [new file with mode: 0644]
cmsmvs/zipmvsc.job [new file with mode: 0644]
cmsmvs/zipname.conven [new file with mode: 0644]
cmsmvs/zipnote.exec [new file with mode: 0644]
cmsmvs/zipsplit.exec [new file with mode: 0644]
cmsmvs/zipup.h [new file with mode: 0644]
cmsmvs/zipvmc.exec [new file with mode: 0644]
crc32.c [new file with mode: 0644]
crc_i386.S [new file with mode: 0644]
crctab.c [new file with mode: 0644]
crypt.c [new file with mode: 0644]
crypt.h [new file with mode: 0644]
deflate.c [new file with mode: 0644]
ebcdic.h [new file with mode: 0644]
file_id.diz [new file with mode: 0644]
fileio.c [new file with mode: 0644]
globals.c [new file with mode: 0644]
human68k/Makefile [new file with mode: 0644]
human68k/Makefile.gcc [new file with mode: 0644]
human68k/crc_68.s [new file with mode: 0644]
human68k/deflate.s [new file with mode: 0644]
human68k/human68k.c [new file with mode: 0644]
human68k/match.s [new file with mode: 0644]
human68k/osdep.h [new file with mode: 0644]
human68k/zipup.h [new file with mode: 0644]
macos/Contents [new file with mode: 0644]
macos/HISTORY.TXT [new file with mode: 0644]
macos/README.TXT [new file with mode: 0644]
macos/ZipLib.h [new file with mode: 0644]
macos/ZipSx.h [new file with mode: 0644]
macos/ZpPrj.hqx [new file with mode: 0644]
macos/osdep.h [new file with mode: 0644]
macos/readme.1st [new file with mode: 0644]
macos/source/VolWarn.h [new file with mode: 0644]
macos/source/charmap.h [new file with mode: 0644]
macos/source/extrafld.c [new file with mode: 0644]
macos/source/getenv.c [new file with mode: 0644]
macos/source/helpers.c [new file with mode: 0644]
macos/source/helpers.h [new file with mode: 0644]
macos/source/macglob.h [new file with mode: 0644]
macos/source/macopen.c [new file with mode: 0644]
macos/source/macopen.h [new file with mode: 0644]
macos/source/macos.c [new file with mode: 0644]
macos/source/macstuff.c [new file with mode: 0644]
macos/source/macstuff.h [new file with mode: 0644]
macos/source/mactime.c [new file with mode: 0644]
macos/source/mactime.h [new file with mode: 0644]
macos/source/pathname.c [new file with mode: 0644]
macos/source/pathname.h [new file with mode: 0644]
macos/source/recurse.c [new file with mode: 0644]
macos/source/recurse.h [new file with mode: 0644]
macos/source/unixlike.c [new file with mode: 0644]
macos/source/unixlike.h [new file with mode: 0644]
macos/source/zip_rc.hqx [new file with mode: 0644]
macos/zipup.h [new file with mode: 0644]
man/zip.1 [new file with mode: 0644]
match.S [new file with mode: 0644]
mktime.c [new file with mode: 0644]
msdos/README.DOS [new file with mode: 0644]
msdos/crc_i86.asm [new file with mode: 0644]
msdos/makefile.bor [new file with mode: 0644]
msdos/makefile.dj1 [new file with mode: 0644]
msdos/makefile.dj2 [new file with mode: 0644]
msdos/makefile.emx [new file with mode: 0644]
msdos/makefile.msc [new file with mode: 0644]
msdos/makefile.tc [new file with mode: 0644]
msdos/makefile.wat [new file with mode: 0644]
msdos/match.asm [new file with mode: 0644]
msdos/msdos.c [new file with mode: 0644]
msdos/osdep.h [new file with mode: 0644]
msdos/zipup.h [new file with mode: 0644]
os2/makefile.os2 [new file with mode: 0644]
os2/match32.asm [new file with mode: 0644]
os2/os2.c [new file with mode: 0644]
os2/os2acl.c [new file with mode: 0644]
os2/os2acl.h [new file with mode: 0644]
os2/os2zip.c [new file with mode: 0644]
os2/os2zip.h [new file with mode: 0644]
os2/osdep.h [new file with mode: 0644]
os2/zip.def [new file with mode: 0644]
os2/zipup.h [new file with mode: 0644]
packaging/exec-shield.patch [new file with mode: 0644]
packaging/zcrypt29.tar.gz [new file with mode: 0644]
packaging/zip-2.3-currdir.patch [new file with mode: 0644]
packaging/zip-2.31-configure.patch [new file with mode: 0644]
packaging/zip-2.31-install.patch [new file with mode: 0644]
packaging/zip-2.31-near-4GB.patch [new file with mode: 0644]
packaging/zip.spec [new file with mode: 0644]
packaging/zip23-umask.patch [new file with mode: 0644]
packaging/zip23.patch [new file with mode: 0644]
proginfo/3rdparty.bug [new file with mode: 0644]
proginfo/ZipPorts [new file with mode: 0644]
proginfo/algorith.txt [new file with mode: 0644]
proginfo/extra.fld [new file with mode: 0644]
proginfo/fileinfo.cms [new file with mode: 0644]
proginfo/infozip.who [new file with mode: 0644]
proginfo/nt.sd [new file with mode: 0644]
proginfo/perform.dos [new file with mode: 0644]
proginfo/txtvsbin.txt [new file with mode: 0644]
proginfo/ziplimit.txt [new file with mode: 0644]
qdos/IZREADME.SMS [new file with mode: 0644]
qdos/Makefile.qdos [new file with mode: 0644]
qdos/Makefile.qlzip [new file with mode: 0644]
qdos/config.s [new file with mode: 0644]
qdos/crc68.s [new file with mode: 0644]
qdos/match.s [new file with mode: 0644]
qdos/osdep.h [new file with mode: 0644]
qdos/qdos.c [new file with mode: 0644]
qdos/qfileio.c [new file with mode: 0644]
qdos/zipup.h [new file with mode: 0644]
revision.h [new file with mode: 0644]
tailor.h [new file with mode: 0644]
tandem/DOIT [new file with mode: 0644]
tandem/HISTORY [new file with mode: 0644]
tandem/README [new file with mode: 0644]
tandem/commacs [new file with mode: 0644]
tandem/macros [new file with mode: 0644]
tandem/make [new file with mode: 0644]
tandem/tandem.c [new file with mode: 0644]
tandem/tandem.h [new file with mode: 0644]
tandem/tannsk.h [new file with mode: 0644]
tandem/tanzip.c [new file with mode: 0644]
tandem/tanzip.h [new file with mode: 0644]
tandem/zipup.h [new file with mode: 0644]
theos/Makefile [new file with mode: 0644]
theos/README [new file with mode: 0644]
theos/_chmod.c [new file with mode: 0644]
theos/_fprintf.c [new file with mode: 0644]
theos/_isatty.c [new file with mode: 0644]
theos/_rename.c [new file with mode: 0644]
theos/_setargv.c [new file with mode: 0644]
theos/_stat.c [new file with mode: 0644]
theos/charconv.h [new file with mode: 0644]
theos/osdep.h [new file with mode: 0644]
theos/stat.h [new file with mode: 0644]
theos/theos.c [new file with mode: 0644]
theos/zipup.h [new file with mode: 0644]
tops20/make.mic [new file with mode: 0644]
tops20/osdep.h [new file with mode: 0644]
tops20/rename.mic [new file with mode: 0644]
tops20/tops20.c [new file with mode: 0644]
tops20/zipup.h [new file with mode: 0644]
trees.c [new file with mode: 0644]
ttyio.c [new file with mode: 0644]
ttyio.h [new file with mode: 0644]
unix/Makefile [new file with mode: 0644]
unix/Packaging/README [new file with mode: 0644]
unix/Packaging/pkginfo.in [new file with mode: 0644]
unix/Packaging/postinstall [new file with mode: 0755]
unix/Packaging/preinstall.in [new file with mode: 0755]
unix/Packaging/prototype [new file with mode: 0644]
unix/README.OS390 [new file with mode: 0644]
unix/configure [new file with mode: 0755]
unix/osdep.h [new file with mode: 0644]
unix/unix.c [new file with mode: 0644]
unix/zipup.h [new file with mode: 0644]
util.c [new file with mode: 0644]
vms/00binary.vms [new file with mode: 0644]
vms/00readme.txt [new file with mode: 0644]
vms/cmdline.c [new file with mode: 0644]
vms/cvthelp.tpu [new file with mode: 0644]
vms/descrip.mms [new file with mode: 0644]
vms/link_zip.com [new file with mode: 0755]
vms/make_zip.com [new file with mode: 0755]
vms/makefile.vms [new file with mode: 0644]
vms/osdep.h [new file with mode: 0644]
vms/vms.c [new file with mode: 0644]
vms/vms.h [new file with mode: 0644]
vms/vms_im.c [new file with mode: 0644]
vms/vms_pk.c [new file with mode: 0644]
vms/vms_zip.rnh [new file with mode: 0644]
vms/vmsdefs.h [new file with mode: 0644]
vms/vmsmunch.c [new file with mode: 0644]
vms/vmsmunch.h [new file with mode: 0644]
vms/vmszip.c [new file with mode: 0644]
vms/zip_cli.cld [new file with mode: 0644]
vms/zip_cli.help [new file with mode: 0644]
vms/zipup.h [new file with mode: 0644]
win32/README.NT [new file with mode: 0644]
win32/README.TZ [new file with mode: 0644]
win32/crc_i386.asm [new file with mode: 0644]
win32/crc_i386.c [new file with mode: 0644]
win32/crc_lcc.asm [new file with mode: 0644]
win32/gvmat64.asm [new file with mode: 0644]
win32/lm32_lcc.asm [new file with mode: 0644]
win32/makefile.a64 [new file with mode: 0644]
win32/makefile.bor [new file with mode: 0644]
win32/makefile.dj [new file with mode: 0644]
win32/makefile.emx [new file with mode: 0644]
win32/makefile.gcc [new file with mode: 0644]
win32/makefile.ibm [new file with mode: 0644]
win32/makefile.lcc [new file with mode: 0644]
win32/makefile.w10 [new file with mode: 0644]
win32/makefile.w32 [new file with mode: 0644]
win32/makefile.wat [new file with mode: 0644]
win32/match32.asm [new file with mode: 0644]
win32/nt.c [new file with mode: 0644]
win32/nt.h [new file with mode: 0644]
win32/osdep.h [new file with mode: 0644]
win32/readme.a64 [new file with mode: 0644]
win32/rsxntwin.h [new file with mode: 0644]
win32/vc6/zip.dsp [new file with mode: 0644]
win32/vc6/zip.dsw [new file with mode: 0644]
win32/vc6/zipcloak.dsp [new file with mode: 0644]
win32/vc6/zipnote.dsp [new file with mode: 0644]
win32/vc6/zipsplit.dsp [new file with mode: 0644]
win32/win32.c [new file with mode: 0644]
win32/win32zip.c [new file with mode: 0644]
win32/win32zip.h [new file with mode: 0644]
win32/zip.def [new file with mode: 0644]
win32/zipup.h [new file with mode: 0644]
windll/contents [new file with mode: 0644]
windll/example.c [new file with mode: 0644]
windll/example.h [new file with mode: 0644]
windll/resource.h [new file with mode: 0644]
windll/structs.h [new file with mode: 0644]
windll/vb/VBZIP.vbw [new file with mode: 0644]
windll/vb/VBZipBas.bas [new file with mode: 0644]
windll/vb/Vbzip.vbp [new file with mode: 0644]
windll/vb/Vbzipfrm.frm [new file with mode: 0644]
windll/vb/readmeVB.txt [new file with mode: 0644]
windll/visualc/dll/zip32.dsp [new file with mode: 0644]
windll/visualc/dll/zip32.dsw [new file with mode: 0644]
windll/visualc/dll/zip32.mak [new file with mode: 0644]
windll/visualc/lib/zip32.dsp [new file with mode: 0644]
windll/visualc/lib/zip32.dsw [new file with mode: 0644]
windll/visualc/lib/zip32.mak [new file with mode: 0644]
windll/windll.c [new file with mode: 0644]
windll/windll.h [new file with mode: 0644]
windll/windll.rc [new file with mode: 0644]
windll/windll.txt [new file with mode: 0644]
windll/windll16.def [new file with mode: 0644]
windll/windll32.def [new file with mode: 0644]
windll/ziplib.def [new file with mode: 0644]
windll/zipver.h [new file with mode: 0644]
zip.c [new file with mode: 0644]
zip.h [new file with mode: 0644]
zipcloak.c [new file with mode: 0644]
ziperr.h [new file with mode: 0644]
zipfile.c [new file with mode: 0644]
zipnote.c [new file with mode: 0644]
zipsplit.c [new file with mode: 0644]
zipup.c [new file with mode: 0644]

diff --git a/BUGS b/BUGS
new file mode 100644 (file)
index 0000000..21a9013
--- /dev/null
+++ b/BUGS
@@ -0,0 +1,6 @@
+- zip sometimes crashes on some versions of NetBSD (0.8, 0.9 and early
+  0.9-current), FreeBSD (<= 1.1) and BSDI (< 1.1) . This is due to a
+  bug in stdio.
+  Upgrading the stdio package in /usr/src/lib/libc/stdio should
+  fix the problem. See *BSD mirrors in src/lib/libc/stdio
+  You must at least replace setvbuf.o in all the libc's with a newer version.
diff --git a/CHANGES b/CHANGES
new file mode 100644 (file)
index 0000000..b033871
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,1013 @@
+------------------------- August 7th 1996 version 2.2a ------------------
+ 1. QDOS port (Jonathan Hudson)
+ 2. win32 volumelabel handling (Paul)
+ 3. VM/CMS clean up (Greg Hartwig)
+ 4. leading "../" in internal filenames are allowed (Paul)
+ 5. System V packages support (John Bush)
+ 6. Fix handling of atx in zipup() (Onno, Greg)
+ 7. Fixed typo that caused zip -R to dump core (Onno)
+ 8. msdos/makefile.dj2: fix for command line too long when linking zip.exe
+ 9. win95 long filename support with djgpp v2 (Onno, Kimio Itoh)
+------------------------- August 9th 1996 version 2.2b ------------------
+ 1. windll: use wiz instead of wizip (Mike)
+ 2. use z->name NOT z->zname to open files (Onno, Mike)
+------------------------ September 1st 1996 version 2.2c ------------------
+ 1. windll: use fprintf instead of putc to send data to std{out,err} (Mike)
+ 2. os2: make borlandc version detection equal to unzip 5.30d (Kai Uwe)
+ 3. use #elif constructions for msdos,os2 and win32 compiler detection (Onno)
+ 4. fix for incorrect free in zip.c (Onno, Mike, Steve)
+ 5. BeBox port from Chris
+ 6. unix/{configure,Makefile} fixes for SCO Xenix 286 (Tom Schmidt)
+ 7. remove zilog entry from unix/Makefile (Onno)
+ 8. man page fixes (Tom Schmidt)
+ 9. SCO ODT {3,5} fixes (Bill Davidsen)
+------------------------ October 8th 1996 version 2.2d ------------------
+ 1. Fix bug in QDOS patch that broke zipsplit.c (Onno, Paul)
+ 2. Fix a couple of warnings from BorlandC (Mike)
+ 3. msdos/makefile.wat: Delete some more files when cleaning up (Paul)
+ 4. store msdos volumelabels without a dot in them (Paul)
+ 5. clean up of unix/{Makefile,configure,packaging} (Tom Schmidt)
+ 6. make QDOS port case independent (Jonathan Hudson)
+ 7. new amiga SASC makefile (Walter Haidinger)
+ 8. don't truncate filenames in win32's in2ex() (Paul)
+ 9. os2/makefile.os2 update for emx 0.9c (Kai Uwe)
+10. password() function for QDOS (Jonathan)
+11. fix the last(?) free() related bug (Mike)
+12. win32: security descriptors operations (Scott Field)
+13. win32: FILE_SHARE_DELETE is not defined in some win32 compilers (Onno)
+14. win32: fix makefile.wat to include nt.c (Onno)
+------------------------ January 17th 1997 version 2.2e ------------------
+ 1. define USE_CASE_MAP in osdep.h for those ports that need it (Onno)
+ 2. define PROCNAME in osdep.h for those ports that need it (Onno)
+ 3. wild() prototype decl only if PROCNAME defined => delete MSVMS define (Onno)
+ 4. add DOS EMX makefile (E-Yen Tan)
+ 5. include <qdos.h> a little earlier in qdos/qdos.c (Jonathan)
+ 6. add ttyio.o to OBJZ in qdos/Makefile.qdos (Jonathan)
+ 7. remove unused fprintebc define from zip.c (Onno)
+ 8. use the right password routine in ttyio.c for unzip (Mike)
+ 9. BeOS update from Chris
+10. Fix for 'zip -r foo x:' (Paul)
+11. Fix library bug on beos (Chris)
+12. Fix calculating version number (kitoh_@mix.or.jp, Walter Haidinger)
+13. IsWinNT always returned TRUE (Mike)
+14. Windll update from Mike
+15. Improved crc routines for x86 from Scott Field
+16. Detect in unix/configure if we can use crc_i386.S (Onno)
+17. Fix spurious internal logic error (Paul)
+18. Fix to include directory names on the Acorn when needed (Sergio)
+19. include zip.h in mvs.h (Onno, George Carr)
+20. add workaround for AZTEC C compiler bug to revision.h (Paul, Walter)
+21. MVS doesn't have rmdir (George Carr)
+22. define and use USE_ZIPMAIN for WINDLL en VM_CMS (Onno)
+23. Fixes from Greg Hartwig to make CMS standalone versions possible.
+24. Move OS specific encryption stuff to the os specific directories (Christian)
+25. Change password fetching interface in ttyio and crypt (Christian)
+26. Update emx support for 0.9c (Christian)
+27. Define WINDLL instead of MSWIN (Christian)
+28. Extended time stamp extra field format support (Christian)
+29. Support for rsxnt-emx 0.9c win32 compiler (Christian)
+30. Use izshr017b (Christian)
+------------------------ March 11th 1997 version 2.2f ------------------
+ 1. Move makefile.emx, rsxwinnt.h and zip.def to win32 subdir (Kai Uwe)
+ 2. Add win32 target to makefile.os2 to allow cross compilation (Kai Uwe)
+ 3. Fix NTSD_EAS link time failures with win32 (Paul)
+ 4. Fix buffer freed too early in password verification code (Mike)
+ 5. Remove unix/zipgrep and man/zipgrep.1 (sanvila@ctv.es)
+ 6. Only use crc_i386.o when we're using an x86 (Onno, Mark)
+ 7. Remove carriage returns from amiga/crc_68.a (Paul)
+ 8. New windll from Mike
+ 9. Fix typo in os2/os2zip.c (Kai Uwe)
+10. Don't use ctime (last file status change) for unix and qdos cross compile
+    (Greg)
+11. added gccwin32 crosscompilation target (RSXNT) to os2/makefile.os2 (Kai Uwe)
+12. fixed the OS/2 file attribute and time stamp generation for zipping
+    stdin ("-") (Kai Uwe)
+13. fixed the atime and ctime stat fields for the OS/2 Watcom C library
+    (Kai Uwe)
+14. added atime and ctime support for the UT extra field when generated under
+    OS/2, the atime and ctime values are only stored when zipping (Kai Uwe)
+15. qdos patches from Jonathan Hudson mainly for extended time flag handling
+16. amiga aztec compiler bug workaround (Paul)
+17. fix -v output of zipcloak, zipnote and zipsplit (Paul)
+18. new amiga/makefile.azt with targets for debug versions (Paul)
+------------------------ March 31st 1997 version 2.2g ------------------
+ 1. remove -I/usr/local/include from unix/Makefile (Chris)
+ 2. Update versinfolines in revision.h (Greg)
+ 3. change 1U to 0x1 to accomodate non ANSI compilers (Onno, Rodney Brown)
+ 4. win32zip.c: cast buffer parameter in memcompress() to char * (Mike)
+ 5. remove beos/zipgrep (Chris)
+ 6. correct the -e password verification check in zip.c (Christian)
+ 7. use ZCONST instead of const in the generic code. (Christian)
+ 8. fix mktime timezone correction when time is near to daylight/nodaylight
+    switch points. (Christian)
+ 9. correct dependencies in makefile.os2 (Christian)
+10. use a more sensible default for iztime.ctime than "0" when system does not
+    not support creation time stamps. (Christian)
+11. fix VMS_PK_EXTRA function interface declarations. (Christian)
+12. implement atime/ctime support in win32. (Christian)
+13. win32/win32.c: replacement getch() for Watcom. (Paul)
+14. win32/makefile.wat: debug object files kept separate. (Paul)
+15. msdos/makefile.wat: debug object files kept separate. (Paul)
+16. Fix extended time defines for the acorn. (Sergio)
+17. Define PROCNAME() in acorn/osdep.h (Sergio)
+18. Ignore exit status of ${INSTALL_D} in unix/Makefile (Chris)
+19. Add Metroworks and BEOS info to version() in several files (Chris)
+20. Move defines for the password fetch to zip.h (Christian)
+21. Support the obsolete version rsxnt 1.1 / emx 0.9b (Christian)
+22. Remove obsolete "#define PROCNAME ..." from cmsmvs/cmsmvs.h (Christian)
+23. Fix extended time defines for qdos (Jonathan Hudson)
+24. Use watcom getch() from unz530q in win32/win32.c (Onno)
+25. Don't install zipgrep via the unix package tools (John Bush)
+26. use izshr021 (Onno)
+27. Fix zipnote: use iname not zname in zipnote.c (Onno)
+28. Create proginfo directory (Christian)
+------------------------ May 5th 1997 version 2.2h --------------------
+ 1. Fix vms/zipup.h: iztime --> iztimes  (Onno, Mike Freeman)
+ 2. Remove windll/wizdll.def (Mike)
+ 3. Add a couple of external variable declaration to windll.h (Mike)
+ 4. Remove zipgrep from install in unix/Makefile (Onno)
+ 5. Make updating .zip files with extended time fields possible (Kai Uwe)
+ 6. Delete beos/Makefile.gcc, beos/Makefiles handles both compilers (Chris)
+ 7. Fixes for unused variables (Chris)
+ 8. Added very simplistic example how to load and call the windll (Mike)
+ 9. Updated windll documentation to note this example (Mike)
+10. Removed an unused memeber of a structure in windll (Mike)
+11. Add BUGS instead of infozip.who and algorith.doc with the packaging
+    tools (John Bush)
+12. tailor.h: increment NUM_HOSTS to keep in sync with UnZip (Christian)
+13. win32/osdep.h: remove NO_SECURE_TESTS define (Christian)
+14. zip.h: add declaration for free_crc_table() (Christian)
+15. windll: move everything that's not windows specific into api.* (Mike)
+16. use iname when checking for directory names in zipfile.c (Sergio)
+17. improved mktime.c with better error checking (Christian)
+18. improved crc routines (Christian, Rodney Brown)
+19. get the -z option working again (Onno, Brad Clarke)
+20. define BROKEN_FSEEK and seekable() for those systems where fseek()
+    always returns 0 (== OK) (Onno, Jeffrey Altman)
+------------------------ May 10th 1997 version 2.2i --------------------
+ 1. win32's seekable should only check for FILE_TYPE_DISK (Onno, Jeffrey Altman)
+ 2. add (ulg) cast to zipbeg = ~0 in zipfile.c (Steve)
+ 3. seekable() *really* belongs in flush_block, keep it there (Onno)
+ 4. seekable() calls fseekable(FILE *) (Onno)
+ 5. define HAVE_FSEEKABLE if a port has their own fseekable (Onno)
+ 6. WatCom doesn't have _get_osfhandle, use _os_handle instead (Paul)
+ 7. upgrade to Mike's latest windll sources (Mike)
+ 8. add -P option so you can specify a password on the commandline (Onno)
+ 9. Get -@ working again (Onno)
+10. emx+RSXNT doesn't know about _get_osfhandle() (Kai Uwe)
+11. fix a couple of typos in the OS/2 makefiles (Kai Uwe)
+12. fix initialization bug in windll code (Mike)
+13. tweak deletedir for RISC OS (Sergio)
+14. RISCOS doesn't know about fstat() (Sergio)
+15. Remove acorn/acorn (Sergio)
+16. Delete debugging statements from version_local() in msdos.c (Greg)
+17. Fix huge bug in readzipfile() (Onno)
+------------------------ May 18th 1997 version 2.2j --------------------
+ 1. Add missing ';' after return ZE_PARMS in zip.c (Mike)
+ 2. Remove obsolete 'struct stat st' in zipfile.c (Onno)
+ 3. Get Amiga SFX handling working again (Paul)
+ 4. Get zip -A working again (Onno)
+ 5. Change an && to & in zipfile.c (Johnny)
+ 6. Fix handling of empty sfx archives (Onno, Mike)
+ 7. Remove experimental entries from the makefiles (Jean-loup)
+ 8. Add exit codes to the manual page (Onno)
+ 9. Remove lines from the help screen that contain lesser used options (Onno)
+------------------------ June 8th 1997 version 2.2k --------------------
+ 1. use zip -t ddmmyyyy for year 2000 stuff (Greg)
+ 2. zip -@ only handles ONE filename per line (Jean-loup)
+ 3. beos support for DR9 filesystem and symlinks (Chris)
+ 4. VB support for windll (Mike)
+------------------------ June 10th 1997 version 2.2l -------------------
+ 1. beos filetype support (Chris)
+ 2. fill the buffer in getnam() to get it working again (Onno)
+ 3. implement -x@filename and -i@filename (Onno)
+------------------------ June 22nd 1997 version 2.2m -------------------
+ 1. Add a ; after de nextarg label in main() (Onno, Erik Baatz)
+ 2. Initialize p to NULL in get_filters() (Onno, Frank Donahoe)
+ 3. Fix typo in first if statement in filetypes() (Johnny Lee)
+ 4. zip -A works again (Onno, Greg)
+ 5. don't free zipbuf for VMS and CMS_MVS in main() (Onno, Mike Freeman)
+ 6. fix make_zip.com, link_zip.com and vmsdefs.h for gcc 2.6.3 on VMS (Onno)
+ 7. clarify -g option in the man page (Jean-loup)
+------------------------ July 6th 1997 version 2.2n -------------------
+ 1. use local in readzipfile2() declaration (Onno, Mike Freeman)
+ 2. return values with windll in get_filters() (Mike)
+ 3. a couple of minor patches for BEOS (Chris)
+ 4. zip -g works again (Onno, Chris)
+ 5. Some more Visual Basic dll support (Mike)
+ 6. Fix stack overflow in readzipfile() for DOS (Onno, Michael Mauch)
+------------------------ August 19th 1997 version 2.2o -------------------
+ 1. beos README and Makefile tweaks from Chris.
+ 2. Syntax corrections for README and man/zip.1  (Frank Donahoe)
+ 3. Use name not iname when deleting directories in trash() (Christian)
+ 4. change several wkuvx1 to lists in e-mail addresses (Christian)
+ 5. default to PK style extra fields for VMS (Christian)
+ 6. use izshr023 (Christian)
+ 7. replace buggy time library functions (Walter Haidinger, Paul, Christian)
+ 8. in2ex() and stat() are needed also when UTIL isn't defined (Greg Hartwig)
+ 9. don't use type=record in fopen() for MVS and CMS (Greg Hartwig)
+10. Change P and K literals to hex for EBCDIC systems (Greg Hartwig)
+11. Add output path support for CMS and MVS (Greg Hartwig)
+12. Add memtoasc and memtoebc for EBCDIC systems (Greg Hartwig)
+13. Handle comments correctly to fix zipnote for CMS and MVS (Greg Hartwig)
+14. Add -tt option (do not operate on files after date mmddyy) (Christian)
+15. move alloc routines for DOS into the !UTIL block (Christian)
+16. move UTIL blocks and version_local() functions to a more logical place
+    (Christian)
+17. Handle -P, -R, -x@, -i@ and -tt for the VMS CLI (Christian)
+18. Update VMS help file with the new options (Christian)
+19. Use iname in MATCH, not zname (Jonathan Hudson)
+20. windll: more Visual Basic support (Mike)
+21. windll: more project makefiles (Mike)
+22. windll: insert Zip in front of global variable names (Mike)
+------------------------ August 25th 1997 version 2.2p -------------------
+ 1. Remove unused flags from LFLAGS2 in unix/Makefile (Onno)
+ 2. SunOS make bug: change unix_.o rule in unix/Makefile (Onno, Mike Freeman)
+ 3. ZipIsWinNT() instead of IsWinNT() in zip.h (Mike)
+ 4. Fix -t and -tt behaviour for windll (Mike)
+ 5. Remove windll makefiles that are now elsewhere (Mike)
+ 6. BEOS: preserve file attributes associated with symbolic links (Chris)
+ 7. No need to use in2ex() for ziputils (Christian)
+ 8. Fix comment handling for EBCDIC systems (Christian)
+ 9. EBCDIC conversion for entry names read from zipfile in UTIL mode (Christian)
+10. Fix "fatal" error messages on EBCDIC systems (Christian)
+11. zipnote.c: Fix handling of entry name changes for EBCDIC systems (Christian)
+12. removed a large part of "dead" code from ziputils version (Christian)
+13. use z->iname in comparison functions for sorting (Christian)
+14. new installation utils for the acorn (Sergio)
+15. use LSSTAT in set_extra_field for unix and beos (Onno)
+16. perror(z->zname) instead of perror("zip warning") (Onno, Geoff Pennington)
+17. Amiga SFX should work again (Paul)
+18. refer to zip22 in install.doc (Frank Donahoe)
+------------------------ September 10th 1997 version 2.2q -------------------
+ 1. Change .doc to .txt, these aren't MS-Word documents (John D. Mitchell)
+ 2. Change msdos$_(OBJ) to msdos_$(OBJ) (Kai Uwe)
+ 3. Fix a couple of amiga related glitches (Paul)
+ 4. Support for DOS packed .exe files in makefile.dj2 (Frank Donahoe)
+ 5. Change warning message for zip -A (Greg)
+------------------------ September 29th 1997 version 2.2r -------------------
+ 1. Fix make svr4package (Eric Baatz)
+ 2. Fix VMS warning (Mike Freeman, Christian)
+ 3. Clean up beos gcc port and beos README (Chris)
+-------------------------- October 6th 1997 version 2.2s --------------------
+ 1. Change lpPrint to lpZipPrint for windll (Mike)
+ 2. Change lpPassword to lpZipPassword for windll (Mike)
+ 3. Amiga timezone fixes (Paul)
+ 4. WatCom C 11.0 makefile fixes (Paul)
+ 5. Tandem port from Dave Smith
+ 6. Corrections and updates for install.txt (Christian)
+ 7. Minor VMS README update (Christian)
+-------------------------- October 12th 1997 version 2.2t --------------------
+ 1. qdos compiler bug workaround (Jonathan)
+ 2. prevent storing qdos specific filenames that exceed filesystem limits
+    (Jonathan)
+ 3. fix undelimited comment in fileio.c (Frank Donahoe)
+ 4. disable storing of symlinks in BEOS until OS support is available (Chris)
+ 5. Init hash_head to 0 in amiga/deflate.a (Paul)
+ 6. Upgrade to izshr025 (Christian)
+ 7. don't add ".zip" to ZIP name for TANDEM (Dave Smith)
+ 8. use zipup.h not tandem.h in zipup.c (Dave Smith)
+ 9. rename history to CHANGES (Onno)
+10. rename install.txt to INSTALL (Onno)
+11. rename zip.txt to ZIPMAN (Onno)
+12. create WHATSNEW (Onno)
+-------------------------- October 15th 1997 version 2.2u --------------------
+ 1. Use Info-ZIP instead of Info-Zip (Christian)
+ 2. Note recent filename changes in several files (Christian)
+ 3. Remove a couple of items from the TODO list (Christian, Onno)
+ 4. Add windll port, zip -t yyyymmdd and zip -R to WHATSNEW (Christian)
+ 5. VMS documentation cleanups and clarifications (Christian)
+ 6. dist entry in unix/Makefile (Onno)
+ 7. remove duplicate amiga/timezone.txt (Christian)
+ 8. rename ZIPMAN to MANUAL and update a couple of files regarding this (Onno)
+-------------------------- October 24th 1997 version 2.2v --------------------
+ 1. izshr026: in WHERE wiz40 instead of wiz30 (Christian)
+ 2. izshr026: another couple of Info-ZIP spelling fixes (Christian)
+ 3. Remove zipgrep from the makefiles that still had it (Christian)
+ 4. Update makefiles to handle the MANUAL renaming change (Christian)
+ 5. Fix the last daylight savings bug on the Amiga (Paul)
+ 6. Fix the SCO Unix specialty detection in unix/configure (Onno,
+    bug reported by Bo Kullmar for Solaris 2.6 and with uname -X output
+    for SCO Unix from ken@apisys.com and dgsmith@vnet.ibm.com)
+ 7. Update WHERE and amiga/time_lib.c from unzip 5.32g (Greg)
+-------------------------- October 26th 1997 version 2.2w --------------------
+ 1. Additional +Onolimit check in unix/configure (Onno, Peter Jones)
+ 2. Use ZIPERR macro instead of ziperr (Christian)
+ 3. initialize z->lflg for zip entries without extra field (Christian)
+ 4. "local (+ locextend)" vs. "central" header consistency check (Christian)
+ 5. Override local header values with central header values with -A
+    and differences between these headers (Christain)
+ 6. made "deltaoff" signed long; offset adjustment may be negative (Christian)
+ 7. fix a number of "wild" deallocation bugs (Christian)
+ 8. When zipping from a FAT drive (only 8.3 DOS names) under OS/2 or
+    WIN32, set z->vem to "OS_DOS | <real zip version number>".
+    Mark as "made by DOS PKZIP 2.0" only when dosify was requested. (Christian)
+ 9. DOS port should not store fake unix style external attributes. (Christian)
+10. amiga/time_lib.c from izshr028 (Christian)
+-------------------------- October 31st 1997 version 2.2y --------------------
+ 1. amiga/time_lib.c from izshr029 (Christian)
+ 2. Turbo C++ version code clarification (E-Yen Tan)
+ 3. Fix spelling in cmsvms/zipname.conven (Rodney Brown)
+ 4. Fix memset check in unix/configure for Unixware 2.1.1 (Rodney Brown)
+ 5. Forward declaration fixes for HP-UX bundled compiler (Rodney Brown)
+-------------------------- November 3rd 1997 version 2.2 --------------------
+ 1. Update WHERE (Greg).
+-------------------------- January 4th 1998 version 2.21a -------------------
+ 1. BSD friendly version of version_local() in unix/unix.c (Onno)
+ 2. No NT versions in DOS version_local() (Steve Salisbury)
+ 3. -t mmddyyyy instead of -t ddmmyyyy in WHATSNEW (Walter Haidinger)
+ 4. use generic fseekable() for rsxnt (Christian)
+ 5. Fix MSC 8.x warnings (Christian, Steve Salisbury)
+ 6. win32 Borland C++ makefile (E-Yen Tan)
+ 7. Tandem doesn't know about extensions like .zip,.arj, ... (Dave Smith)
+ 8. Use dosmatch for EMX and DJGPP too (Christian)
+ 9. dummy djgpp startup functions to remove command line globbing and
+    recognition of environment variables from djgpp.env (Christian)
+10. include DJGPP_MINOR in DOS version_local() (Christian)
+11. TC 2.0 doesn't have mktime() (Christian, mmp@earthling.net)
+12. VMS: rename opendir() to zopendir() so avoiding name clash with
+    VMS 7.x POSIX libraries (Christian, Martin Zinser)
+13. Add support for VMS DEC C V 5.6 features (Christian)
+14. Use iname for comparison in check_dup (Christian Spieler, Christian Michel)
+15. Fix access to uninitialized ioctx records in vms_get_attributes()
+    Christian, Robert Nielsen)
+16. Parenthesis around MAX_MATCH>>1 in match.S (Greg)
+17. Use strchr() not strrchr() for -i and -x to get -i@ and -x@ really
+    working (Onno, Kai Uwe)
+18. add chmod statements to unix/Makefile (Quentin Barnes)
+19. Windll: handle both -r and -R (Mike)
+20. Windll: general error handler in main() via setjmp/longjmp (Mike)
+21. Don't allow zip -i@x.lst foo.zip (Onno)
+22. vms/link_zip.com: use .eqs. not .nes. when checking with f$search
+    for the zip AXP object library (David Dachtera)
+23. rsxnt 1.3.1 fixes (E-Yen Tan)
+-------------------------- January 20th 1998 version 2.21b -------------------
+ 1. Bigger PATH_MAX for win32's windll (Mike)
+ 2. Update windll.txt w.r.t. PATH_MAX (Mike)
+ 3. Amiga SAS/C fixes (Walter, Paul)
+ 4. zip -i@ and -x@ should *really* work now ...... (Onno)
+-------------------------- February 20th 1998 version 2.21c -------------------
+ 1. make -f unix/Makefile qnx needs LN=ln in its options (Chris)
+ 2. Support Metroworks Codewarrior/x86 on BEOS (Chris)
+ 3. Add Norbert Pueschel to proginfo/infozip.who (Walter)
+ 4. Use big endian for Be types (Chris)
+ 5. zip -i and -x were broken by the -i@ fix last time around (Christian)
+ 6. win32 stat bandaid (Paul)
+ 7. acorn filetype and timestamp fixes (Sergio, D. Krumbholz)
+ 8. update to izshr30 (Christian)
+ 9. Support for NTSD in the RSXNT environment (Christian)
+10. restructure readzipfile() (Christian)
+11. Where needed define MATCH in osdep.h (Christian)
+12. version_local() fixes for RSXNT (Christian)
+13. New vmsmunch.c (Christian)
+-------------------------- March 15th 1998 version 2.3a -------------------
+ 1. Fixes for the windll API (Mike)
+ 2. Use CPUTYPE in BorlandC Makefile for DOS (E-Yen Tan)
+ 3. BEOS: -rostr not available for the x86 compiler (Chris)
+ 4. preserve file attributes of a symlink on BEOS (Chris)
+ 5. New VM/CMS README.CMS and version_local() (Ian Gorman)
+ 6. INSTALL fixes from Takahiro Watanabe
+ 7. OS/390 port from Paul von Behren
+ 8. new api.h from Mike
+-------------------------- April 19th 1998 version 2.3b -------------------
+ 1. Improve Tandem file I/O performance (Dave Smith)
+ 2. New VM/CMS README.CMS and version_local() (Ian Gorman)
+ 3. cygwin32 port from Cosmin Truta
+ 4. Workaround for tasm32 5.0 bug in win32/crc_i386.asm (Cosmin Truta)
+ 5. win32/match32.asm fixes for tasm 5.0 (Cosmin Truta)
+ 6. simplify OS/390 port (Christian)
+ 7. win32 timezone handling fixes (Christian)
+ 8. fix 40-bit time conversion on the acorn (Sergio and Christian)
+ 9. strip network part from UNC type filenames (Christian)
+10. Makefile for OpenMVS (Ian Gorman)
+11. Use the Watcom getch() for cygwin32 (Christian)
+12. Borland C++ 5.x added to win32's version_local() (Cosmin Truta)
+13. Borland C++ needs tzset() in win32 (Christian, Cosmin Truta)
+-------------------------- May 21st 1998 version 2.3c -------------------
+ 1. Better error messages for -i and -x (Christian)
+ 2. Win32 stat() wrapper needs dos2unixtime (Christian,Paul,Mike)
+ 3. DJGPP: use _chmod to handle LFN attributes correctly (Michael Mauch)
+ 4. Fix Borlandc warnings (Mike)
+ 5. win32/makefile.bor fixes from Michael Mauch
+ 6. win32/makefile.{dj,emx} fixes from E-Yen Tan
+ 7. Use izshr031 (Christian)
+ 8. CMS: use RECFM=V LRECL=32760 by adding "byteseek" (Greg Hartwig)
+ 9. Check external name for trailing "/" (Greg Hartwig)
+10. More specific info in CMS version_local() (Greg Hartwig)
+11. Changed usage info to refer to "fm" rather than "path" on CMS (Greg Hartwig)
+12. No more "extra data" messages when using the same OS (Greg Hartwig)
+13. Rewritten README.CMS, one version for ZIP and UNZIP (Greg Hartwig)
+14. DOS/OS2/WIN32/UNIX: ex2in() strips off "//host/share/" from UNC names (SPC)
+-------------------------- June 23rd 1998 version 2.3d -------------------
+ 1. Fixed Win32's stat() bandaid handling of time stamps (SPC)
+ 2. General fix of file selections for DELETE and FRESHEN action (SPC)
+ 3. CMS_MVS: Use ASCII coding for TIME extra field ID (SPC)
+ 4. EBCDIC: Repaired bogus CMS_MVS fix in zipup.c; check the internal
+    name for trailing (ASCII) '/' to detect directory entries (SPC)
+ 5. Use explicit ASCII coding when comparing or setting chars in iname (SPC)
+ 6. Fixed win32/makefile.bor, win32/makefile.dj (support NTSD),
+    win32/makefile.emx (SPC)
+ 7. Replaced win32/makefile.cyg by win32/makefile.gcc, containing new
+    support for mingw32 GCC environment (SPC)
+ 8. Use izshr032 (SPC)
+ 9. Modified zipup.c to hold (un)compressed lengths in "ulg" variables, in
+    an attempt to support handling of huge (>2GByte) files. (SPC)
+10. Removed some duplicate #defines from api.h, they are now in crypt.h (SPC)
+11. Reenabled "extra data size" info messages in noisy mode for all systems
+    except RISCOS and CMS_MVS (SPC)
+12. For EMX 0.9c, the runtime lib contains a working mktime(), use it (SPC)
+13. Miscellanous cosmetic changes (SPC)
+14. Move win32/makefile.emx to msdos (E-Yen Tan)
+15. make api.h work with zcrypt2.8 (Mike)
+16. define ydays differently in api.h to avoid linking problems (Mike)
+17. New windll.txt (Mike)
+18. win32 lcc patches  (E-Yen Tan)
+19. win32 lcc makefile (E-Yen Tan)
+20. Multiple inclusion bug: no malloc.h when using lcc-win32 (E-Yen Tan)
+21. New VB support files for windll (Mike Le Voi, Raymond King)
+22. MacOS port by Dirk Haase
+-------------------------- August 1st 1998 version 2.3e -------------------
+ 1. Generalized check for validy of TZ timezone setup info, similar to
+    UnZip; use it on AMIGA and MSDOS, as before. (SPC)
+ 2. Apply TZ validy check on OS/2 and enable creation of UT e.f. (SPC)
+ 3. BEOS: New Makefile, updates for README and Contents (Chris Herborth)
+ 4. beos/beos.c: declare some private functions as "local" (SPC)
+ 5. Include memcompress() code only for ports that make use of it, controlled
+    by preprocessor symbol ZP_NEED_MEMCOMPR (SPC)
+ 6. cmsmvs/README.CMS fix: Zip archive entries to be extracted into var-length
+    records CMS files should >>NOT<< contain binary data ... (SPC)
+ 7. crc32.c, crctab.c: the crc polynom table is ZCONST (SPC)
+ 8. trees.c: fixed a bug in the deflate algorithm that limited the compressed
+    size of an archive member to 512 MByte (SPC)
+ 9. deflate.c: Integrated the changes found in zlib that are neccessary to make
+    the deflate algorithm deterministic; modified msdos/match.asm to take
+    care of the "nice_match" global no longer being constant.  (SPC)
+10. deflate.c, trees.c, zipup.c: Reorganized and simplified deflate's
+    compressed output buffer handling. I/O and compression code are now
+    separated more cleanly. (SPC)
+11. Killed bits.c by moving its contents into trees.c resp. zipup.c;
+    synchronized all Makefiles and Make procedures with this change. (SPC)
+12. Integrated support for optionally replacement of deflate and crc32 by
+    public domain zlib code. (SPC)
+13. Synchronize the different variants (UNIX/GNU C, OS/2, WIN32) of i386
+    assembler replacement for deflate's longest_match() (SPC)
+14. Moved the EMX+rsxnt Makefile.emx from msdos/ back into win32/ (SPC)
+15. Restored a separate Makefile.emx for DOS; on DOS, some make programs may
+    have difficulties with recursive invokation (SPC)
+16. Fixed the "include header mess" of the new MACOS port and removed the
+    "work-around hacks" caused by these bad MACOS .h-file includes (SPC)
+17. Integrated Dirk Haase's beta4 (27-Jun-98) release of MacZIP (Dirk Haase)
+18. Added support for MS Quick C in the MSDOS version_local() report (SPC)
+19. Added WIN32 rsxnt targets linking against the emx crtl DLL to Makefile.emx
+    in os2/ and win32/ (SPC)
+20. Fixed typo in os2/os2.c wild() function. (Kai Uwe Rommel)
+21. Removed ChangeNameForFAT() from os2/os2.c in2ex() to fix problem with
+    long filename support. (Kai Uwe Rommel)
+22. os2/os2zip.[ch]: correct type of DOS-style timestamp data is "ulg" (SPC)
+23. vms/cmdline.c: Removed wrong ';' behind if condition (Johnny Lee)
+24. VMS: Preliminary preparations in C code for supporting GNU C on OpenVMS
+    Alpha (Onno van der Linden, Christian Spieler)
+25. VMS: Fixed check against adding zipfile to itself in fileio.c (SPC)
+26. WIN32: Added lcc-Win32 variants of i386 assembler code for crc32() and
+    longest_match(). (SPC)
+27. WIN32: Removed bogus type-cast in assignment to statb st_mode member (SPC)
+28. zip.c: Fixed MACOS-related typo that broke "-@" command option (SPC)
+29. zipup.c: Fixed messed-up expression for assignment to z->ver (SPC)
+30. MACOS extra fields: check realloc return values (Onno, Johnny Lee)
+31. Fix the PUTBYTE macro in trees.c: >= instead of < (Onno)
+-------------------------- September 6th 1998 version 2.3f -------------------
+ 1. Add zp_tz_is_valid to globals.c (Onno, Frank Donahoe)
+ 2. Updated tandem files from Dave Smith
+ 3. Windll: allow comments to zip archive with VB (Mike)
+ 4. Windll: add support for -b and update the documentation (Mike)
+ 5. win32: use wbS for FOPW to handle large zip files better (Steve Miller)
+ 6. MVS fix: use fseek();clearerr() instead of rewind() (Onno, Lee Burton)
+ 7. Updated VB examples for windll (Mike)
+ 8. Tandem: use UTC timestamps and GID/UID in extra field (Dave Smith)
+ 9. Tandem: handle -o option (Dave Smith)
+10. default for ZCONST is const in tailor.h, override in osdep.h (Onno)
+11. additional Macintosh options in zip.c (Dirk Haase)
+12. additional Macintosh options in zip.1 and MANUAL (Onno, Dirk Haase)
+13. Integrate Beta 5 of the Macintosh Port (Dirk Haase)
+-------------------------- October 27th 1998 version 2.3g -------------------
+ 1. zip_tz_is_valid should be zp_tz_is_valid (Kai Uwe)
+ 2. MVS native (not OE) beta fixes (Keith Owens)
+ 3. LynxOS support from Giuseppe Guerrini
+ 4. MVS already has stat() and fstat() so use 'em (Keith Owens)
+ 5. MVS fix in readzipfile() for new, unopened dataset without EOF marker
+    (Keith Owens)
+ 6. Remove 16-bit stuff from windll/windll.rc (Mike)
+ 7. Windll: Use hCurrentInst not hInst (Mike)
+ 8. In util.c compare strchr() return value with NULL (Onno, Frank Donahoe)
+ 9. unix/unix.c: initialize variable t in ex2in() (Onno, Frank Danahoe)
+10. Remove windll/borland subdirectory (Mike)
+11. Really fix extra field realloc() for BeOS and MacOS (Christian)
+12. Fix the dj2 LFN related access violation bug (Christian, Joe Forster)
+13. proginfo/3rdparty.bug: Added more info about other Zip clone's bugs.
+14. The global copyright definitions in revision.h now depend on DEFCPYRT
+    (Christian).
+15. tandem/macros: removed obsolete object file references (Christian)
+16. fix memory leak with the "filter" patterns (Christian, Leah Kramer)
+17. zip.c: completed the support for MacOS specific -N (Christian)
+18. reorganized the Mac specific help screen code (Christian)
+19. zipup.c: corrected the USE_ZLIB code to emit "stored" entries under
+    the same conditions as the "native deflate" code (Christian)
+20. A couple of vars that will never be negative should be unsigned (Christian)
+-------------------------- November 18th 1998 version 2.3h -------------------
+ 1. DJGPP: When compressing from stdin don't set binary mode if stdin is
+    a terminal (E-Yen Tan)
+ 2. Fix signed/unsigned comparisons in fileio.c, util.c and zipcloak.c
+    (Frank Donahoe)
+ 3. Move macgetch() prototype from macos/source/macos.c to macos/osdep.h
+    (Christian)
+ 4. _doserrno should have type int, not unsigned int (Christian)
+ 5. In zipfile.c init a file pointer with NULL to fix gcc warning (Christian)
+ 6. Upgrade to MacOS beta 7 (Dirk Haase)
+ 7. Move the #pragma statements from generic sources to cmsmvs.h (Christian)
+ 8. Support for QNX/Neutrino 2.0 (Chris)
+ 9. Default to -r in help screen add -R at the bottom (Chris)
+10. Clean up Makefile for BeOS R4 on x86 (Chris)
+11. Beos: If not storing symlinks store attributes of symlink target (Chris)
+12. Use izshr037 (Christian)
+13. Remove ZIPERR() macro from in {msdos,win32}/osdep.h (Christian)
+14. win32/win32.c: Fix 1-day offset in non-64bit FileTime2utime() (Christian)
+15. win32: enable 64-bit FileTime2utime() for MS VC++ >= 5.0 (Christian)
+16. cygwin32 only has _P_WAIT (Thomas Klausner)
+17. msname() should *really* ignore illegal characters (Thomas Klausner)
+18. Fix a missing ')' in Opendir() from win32zip.c (Thomas Klausner)
+-------------------------- December 5th 1998 version 2.3i -------------------
+ 1. Remove the #pragma statements that were forgotten the first time (Ian)
+ 2. Remove obsolete macos/source/CharMap.h (Steve Salisbury)
+ 3. isatty(fileno(zstdin)) in zipup.c should be isatty(zstdin)
+    (Onno, E-Yen Tan)
+ 4. several "shut up warnings from compiler" fixes (Christian)
+ 5. several cosmetic source changes (Christian)
+ 6. win32: make NTSD handling to be robust against alignment and structure
+    padding problems (Christian)
+ 7. Apply don't set binary mode when stdin is a terminal in zipup.c for
+    MSDOS and human68k (Christian)
+ 8. Upgrade to MacOS beta 8 (Dirk Haase)
+ 9. Add callback for WINDLL to handle user termination (Mike)
+10. Fix typo in acornzip.c (Darren Salt)
+11. acorn/sendbits.s: pass correct parameters to flush_outbuf() (Darren Salt)
+12. Fixes for IBM C/C++ 3.6 where time_t is a double (Kai Uwe)
+13. Fixes for IBM Visual Age C++ for win32 (Douglas Hendrix)
+14. man/zip.1: some version numbers in the text were still "2.2" (Christian)
+15. win32/makefile.emx: added a compilation variant that generates
+    standalone executables (Christian)
+16. change __CYGWIN32__ into __CYGWIN__ and add compatiblity definition for
+    B19 and older (Cosmin Truta)
+17. create uniform win32 getch() replacement (Christian)
+18. put back in define of USE_EF_UT_TIME in tandem.h (Dave Smith)
+19. put back in define of USE_CASE_MAP in tandem.h (Dave Smith)
+20. updates to make/macros to allow the object to be licensed (Dave Smith)
+21. updates to macros/doit to remove mktime.c (Dave Smith)
+22. updates to tandem.c for in2ex/mapname/chmod amendments to match Unzip
+    (Dave Smith)
+23. Use izshr039.zip (Christian)
+24. Init filenotes to 0 for the amiga too (Onno)
+25. get_filters(): remove one flag=0 statement to make -R work again (Onno)
+-------------------------- December 17th 1998 version 2.3j ------------------
+ 1. FOPWT defines opening a temp file for writing (Ian)
+ 2. Remove handling of bits.c from a couple of tandem files (Christian)
+ 3. A couple of "shut up warnings from compiler" fixes (Christian)
+ 4. win32/osdep.h: removed duplicate "IZ_PACKED" definition (Christian)
+ 5. win32/zipup.h: remove invalid "elseif" preprocessor token (Christian)
+ 6. sync MacOS help screen with other ports (Christian)
+ 7. get_filters(): set flag to 0 when -R isn't used (Christian)
+ 8. "local extra != central extra" now has "info" status (Christian)
+ 9. use windll directory as "home" directory for builds (Mike)
+10. CMS/MVS: define FOPWT (Ian)
+11. Upgrade to MacOS beta 9 (Dirk Haase)
+-------------------------- January 17th 1999 version 2.3k ------------------
+ 1. Change FOPW into FOPW_TMP (Christian)
+ 2. win32: #include uses paths relative to the parent directory (Christian)
+ 3. Use forward slashes as path separator in #include statements (Christian)
+ 4. windll: fix descriptions of f{In,Ex}cludeDate (Christian)
+ 5. win32/makefile.lcc: add some -I<path> options to find files in the
+    right places (Christian)
+ 6. Supply default empty IZ_PACKED define (Christian)
+ 7. windll: Fix some typos, descriptions (Christian)
+ 8. windll project files: use relative paths, no specific root directory
+    (Christian)
+ 9. windll project files: remove link references to import libraries that
+    are not used by the zip library (Christian)
+10. windll: fix potential infinite loop in a VB sample (Mike)
+11. windll/windll.txt: remove "may not work with VB" statement (Mike)
+12. Multibyte character set support from Yoshioka Tsuneo
+13. Theos port from Jean-Michel Dubois
+14. Tandem: added simple handling of Enscribe files by converting them into
+    text type files (Dave Smith)
+15. Tandem Extra Field ("TA") containing Tandem File Attributes (Dave Smith)
+16. Tandem history file showing background info to (UN)ZIP ports (Dave Smith)
+17. create ZIP file on tandem with special file code (1001) (Dave Smith)
+18. made tandem.c & tandem.h code completely the same as UNZIP (Dave Smith)
+19. unix/configure: move +Onolimit and -Olimit into the machine specific
+    section (Onno, John Wiersba)
+-------------------------- February 21st 1999 version 2.3l ------------------
+ 1. Fix qdos Makefile (Jonathan Hudson)
+ 2. fgets instead of gets in zipnote to fix linker warnings (Jonathan Hudson)
+ 3. Theos: remove _setargv.c and a reference in zip.c (Jean-Michel Dubois)
+ 4. Theos README (Jean-Michel Dubois)
+ 5. interchanged the fRecurse flag values for "-R" and "-r" (Christian)
+ 6. add "z" pr prefix to MBCS functions to avoid name clashes (Christian)
+ 7. Whenever the position of the increment operator does not matter, the
+    INCSTR variant is used, which has been mapped to the {PRE|POS}INCSTR
+    variant that is more efficient. (Christian)
+ 8. fixed the "-R" handling in fileio.c, filter() function (Christian)
+ 9. simplified some THEOS specific code additions (Christian)
+10. changed the line break of the compiler version message in version_local()
+    for MSDOS and Win32 to take into account some verbose compilers (Christian)
+11. removed the THEOS changes from ttyio.c. Instead, a THEOS specific
+    setup was added to ttyio.h (Christian)
+12. sync vms/link_zip.com with the corresponding make_zip.com (Christian)
+13. added compatibility settings for support of MBCS on Win32 with all tested
+    compilers to win32/osdep.h
+14. added type-casts to isalpha() macro calls (Christian)
+15. fixed win32's wild_match which was clobbered by the MBCS addition
+    (Christian)
+16. finished up the "potential infinite loop" problems in the VB sample
+    that Mike started to repair (Christian)
+17. in ziperr.h, AZTEK C might require the false comma that was removed
+    to satisfy THEOS C (Christian)
+18. removed the bogus THEOS specific isdir check in zipup.c (Christian)
+19. modified the code for line ending translation to be independent
+    of the local system's convention for '\n' and '\r'; this allowed
+    the removal of the THEOS specialities (Christian)
+20. Tandem: -B option to zip Enscribe files with no record delimiters
+    (Dave Smith)
+21. Tandem: attempt to catch Large Transfer mode failure (Dave Smith)
+22. Theos: Fixed keyboard entry functions. (Jean-Michel Dubois)
+23. Theos: workaround for the argument wild card expansion that is bugged
+    in the standard library. Managed by MAINWA_BUG flag. (Jean-Michel Dubois)
+24. Theos: support for filenames and notes with accented characters.
+    (Jean-Michel Dubois)
+25. Upgrade to MacOS final (Dirk Haase)
+-------------------------- March 31st 1999 version 2.3m -------------------
+ 1. Theos: for relative paths to root directory cause open, fopen and stat
+    failure, workaround this. (Jean-Michel Dubois)
+ 2. Theos: when no path is indicated in a file or directory name and the
+    file or directory doesn't exist in the current directory it looks for
+    the file or directory in the root directory, workaround this.
+    (Jean-Michel Dubois)
+ 3. Corrected some typos and spelling error in macos/HISTORY.TXT; skipped
+    off invisible trailing whitespace (Christian)
+ 4. proginfo/extra.fld: added documentation for Tandem and Theos extra
+    field layout (Christian with Dave D Smith resp. Jean-Michel Dubois)
+ 5. qdos/Makefile.qdos: The build of ZipCloak requires inclusion of
+    the crctab object module; qfileio_.o compilation requires the -DUTIL
+    flag (Christian)
+ 6. win32: fix incorrect MB_CUR_MAX macro for mingw32 and lcc (Christian)
+ 7. theos/_fprintf.c, theos/_rename.c, theos/osdep.h: Some function
+    parameters require the "const" attribute to achieve compatibility
+    with ANSI C requirements (Christian)
+ 8. theos/theos.c: map Theos' (No)Hidden file attribute to MSDOS Hidden
+    bit in the MSDOS part of zipentry header's external attribute field;
+ 9. theos/stat.h: prevent multiple inclusions
+10. Theos: Fixed wild card management for options other than adding
+    (Jean-Michel Dubois)
+11. Theos: Removed modifications of const strings (Jean-Michel Dubois)
+12. Split tandem.c up into separate zip/unzip parts (Dave Smith, Christian)
+13. Move inclusion of OS specific zipup.h files to tailor.h (Onno)
+-------------------------- August 14th 1999 version 2.3n -------------------
+ 1. Move inclusion of OS specific zipup.h files back to zipup.c (Onno)
+ 2. Remove getline() from zipnote.c and use gets() again (Onno)
+ 3. BeOS PowerPC R4.1 support (Chris)
+ 4. New DOIT and MACROS files for the tandem port (Dave Smith)
+ 5. Don't switch the console to binary mode (Michel de Ruiter)
+ 6. In some circumstances undosm could be freed twice (Mike)
+ 7. Also define const in tailor.h for ultrix (Onno, Foppa Uberti Massimo)
+ 8. Tandem: Change zopen in TANZIPC to allow opening of files with missing
+    alt keys (err 4) (Dave Smith)
+ 9. Tandem: Assume not DST if can't resolve time (no DST table available)
+    (Dave Smith)
+10. WIN32: skip trailing dots and spaces in getnam (Onno, Dan Kegel)
+11. Use ZE_NONE when nothing to freshen or update (Onno, Yuri Sidorenko)
+12. Remove tabs from files that don't need them (Onno)
+13. Remove tabs and spaces from the end of a text line (Onno)
+14. Upgrade macos to 1.04b2 (Dirk)
+15. Add -Q documentation to manual page (Jonathan Hudson)
+16. Copy hiperspace files instead of renaming them (Keith Owens)
+17. Disallow some more characters to appear in DOS filenames when using -k
+    (Onno, Thomas Klausner)
+18. Document missing options and environment variables in the manual (Onno)
+19. New acorn/GMakefile to compile with gcc on RISCOS (Darren Salt)
+20. ISO 8601 date format support for -t and -tt (Rodney Brown)
+-------------------------- September 21st 1999 version 2.3o -------------------
+ 1. Sync zip.h license with LICENSE (Onno)
+ 2. Add copyright notice to README, os2zip.c and os2.zip.h (Onno, Greg)
+ 3. Fix the ASM variable in acorn/GMakefile (Darren Salt)
+ 4. Add another requirement to acorn/ReadMe.GMakefile (Darren Salt)
+ 5. Fix unbalanced parenthesis in vms_get_attributes declaration in zip.h
+    and move it to vms/zipup.h (Onno, Mike Freeman)
+ 6. Make a couple of os2 files public domain (Kai Uwe)
+ 7. Change and rename disclaimer array in revision.h (Onno)
+ 8. Change copyright array in revision.h (Onno)
+ 9. macstuff.c copyright is the same as macstuff.h (Christian)
+10. WHATSNEW: add ISO 8601 dates supported (Christian)
+11. fileio.c - msname(): strip off leading dots, these are illegal for
+    MSDOS compatible names (Christian)
+13. fileio.c - replace(): deactivate "dead" code for CMS_MVS (Christian)
+14. man/zip.1: "-$" option is also used for WIN32 ports
+15. msdos/msdos.c - version_local(): break the version line for
+    GNU compilers too (Christian)
+16. tailor.h: added typecasts to MBCS macros, to suppress "type mismatch"
+    warnings (Christian)
+17. util.c, zip.h, zipfile.c: ZCONSTify several pointers (Christian)
+18. util.c - recmatch(), zip.c - version_info(): add compile time option
+    WILD_STOP_AT_DIR (Christian, Darren Salt)
+19. util.c - envargs(): MBCS related fixes (Christian)
+20. win32/lm32_lcc.asm: add TAB characters that are required by the lcc
+    assembler source parser (Christian)
+21. zip.c: fix the "is a console" check (Christian)
+22. zipnote.c: use getline() (Christian)
+23. zipup.c: use zclose() in case of I/O errors (Christian)
+24. zipup.c: use ZE_WRITE when a write error occurs (Christian)
+25. win32/win32.c: HAVE_INT64 is used by mingw32 (Cosmin Truta)
+26. update shared sources to match izshr041 (Christian)
+-------------------------- November 29th 1999 version 2.3 ------------------
+ 1. Missing parenthesis in win32/win32.c (Steve Salisbury)
+ 2. Add Cosmin Truta to proginfo/infozip.who (Onno)
+ 3. Remove one parenthesis pair too many from vms_get_attributes() declaration
+    in vms/zipup.h (Mike Freeman)
+ 4. qdos .s are expected to start with a #, work around it (Jonathan Hudson)
+ 5. tandem: -B0 should be deflating not storing (Dave Smith)
+ 6. human68k updates from Shimazaki Ryo
+ 7. beos Makefile cleanup (Chris)
+ 8. workaround for fseek to negativate offset behaviour of the RISC OS
+    SharedCLibrary (Darren Salt)
+ 9. set file type for RISC OS in zipcloak.c (Darren Salt)
+10. change tandem zgetch() to allow crypt version to work (Dave Smith)
+11. fix a comment typo in acorn/riscos.c (Christian)
+12. fileio.c: two type-cast to shut up noisy compilers (Christian)
+13. human68k: fix missing case_flag argmument (Christian)
+14. win32/win32.c: remove HAVE_INT64 completely (Christian)
+15. zip.c: raise "cannot zip to console" error when stdout IS a tty (Christian)
+16. zip.h: don't use dummy argument names in declarations (Christian)
+17. Add missing semicolon in fileio.c (Shimazaki Ryo)
+18. win32.c: IBMC compiler >= 3.50 have int64 (Kai Uwe)
+19. Handle initialization error return value from MVS stat() in procname()
+    (Keith Owens)
+20. Use RISC OS instead of RiscOS in the manual (Darren Salt)
+21. Use # instead of ? as single character wildcard on RISC OS (Darren Salt)
+22. New windll example.c (Mike)
+23. Correct storage of 8-bit char filenames with RSXNT (Burkhard Hirzinger)
+24. fix install in unix/Makefile (Santiago Vila, Onno)
+25. Fix zip -L output (Santiago Vila, Onno)
+26. Ignore unix special files (Jonathan O'Brien)
+27. Upgrade to izshr042 (Onno)
+28. Make copyright notice the same as in izshr042 (Onno)
+29. Make copyright notice in zip.h the same as LICENSE (Christian)
+30. Set tempzf to NULL _after_ it has been closed (Chris Kacher)
+31. Change email address for Jonathan Hudson (Jonathan Hudson)
+32. Remove win32/winzip.c.orig (Steve Salisbury)
+33. Use 'Steve Salisbury' throughout the documentation (Steve Salisbury)
+34. Change email address for Steve Salisbury (Steve Salisbury)
+35. Change email address for Chris Herborth (Chris Herborth)
+36. Use zip23 in INSTALL (Roger Cornelius)
+37. Use zcrypt28 in INSTALL (Onno)
+38. New acorn/srcrename (Darren Salt)
+39. amiga/makefile.azt: make clean should remove some more items (Paul)
+40. Change email address for Cosmin Truta (Cosmin Truta)
+------------------------ December 10th 2004 version 2.31a ------------------
+This is a patch to Zip 2.3 including various bug fixes.
+See Zip 3.0 for the latest additional features.
+ 1. Crypt added to source by default now that export restrictions have been
+    relaxed (Ed Gordon)
+ 2. Debian patch 001 for bug 99659 - Converted quoted strings in version compile
+    information to defines (Debian patch 001, Ed)
+ 3. Debian patch 002 - Sets the "normal" unix permissions in the Makefile, so
+    don't have to change them in debian/rules (Debian patch 002, Ed)
+ 4. Debian patch 003 - to support DEB_BUILD_OPTIONS as required by latest
+    policy.  The LFLAGS1 thing could be considered debian-specific, but
+    INSTALL_PROGRAM thing should be in the upstream version (Debian patch 003, Ed)
+ 5. Debian patch 004 - Make gcc happy (probably gcc 3.x) - apply 2.4i configure
+    changes to remove need for -fno-builtin in unix/configure (Onno, Ed)
+ 6. Debian patch 005 for bug 279867 - Fix for FNMAX path bug that could crash
+    on large paths and create security problem (Greg)
+------------------------ December 17th 2004 version 2.31b ------------------
+ 1. File cleanup (Ed)
+------------------------ December 30th 2004 version 2.31c ------------------
+ 1. Add VMS tempname (Steven Schweda (SMS))
+ 2. Add VMS option -VV for archiving most all file types on VMS and fix -V to create
+    more portable archives (SMS)
+ 3. Update VMS command line interface
+ 4. Update README (Ed)
+------------------------ January 1st 2005 version 2.31d ------------------
+ 1. Delete duplicate free(name) in filetime in unix/unix.c (Johnny Lee)
+------------------------ January 8th 2005 version 2.31e ------------------
+ 1. Change zfstat to fstat in unix/unix.c (Ed)
+------------------------ January 22nd 2005 version 2.31f ------------------
+ 1. Update file_id.diz  (Cosmin Truta)
+ 2. Initialize use_longname_ea under both OS2 and WIN32.  zip.c (Cosmin)
+ 3. Enclose option -! and use_privileges under NTSD_EAS guard.  api.c,
+    zip.c (Cosmin)
+ 4. Implement partial support for Cygwin inside the Unix port (Cosmin)
+ 5. Add i586, i686 and Cygwin to version_local().  unix/unix.c (Cosmin)
+ 6. Ensure stat'ing always works on file names with trailing '/' in
+    set_extra_field().  unix/unix.c (Cosmin)
+ 7. Define ASM_CRC by default.  win32/osdep.h (Cosmin)
+ 8. Update from zip24h.  win32/makefile.bor, win32/makefile.w32 (Cosmin)
+ 9. Enable the i686-optimized code by default.  crc_i386.S,
+    win32/crc_i386.asm, win32/crc_i386.c (Cosmin)
+10. Replaced win32/VC6.dsp with a complete Visual C++ 6.0 project to build
+    zip, zipnote, zipsplit and zipcloak, with both ASM and non-ASM settings.
+    (Note that win32/VC6.dsp was a new addition since Zip 2.3 and at this
+    point won't be released since this new workspace is better.  Ed)
+    win32/vc6/zip.dsw (new) (Cosmin)
+11. Add AtheOS port (Ruslan Nickolaev, Ed)
+12. Formatting and consistency fixes (Johnny Lee, Ed)
+13. Add kluge to api.c so zip32.dll supports string parameters in Visual
+    Basic.  See VB project files (Ed)
+------------------------ January 28th 2005 version 2.31g ------------------
+ 1. Adjust binary detection in trees.c by changing 20% binary (4 out of 5
+    ascii) to 2% (64 out of 65) (Ed)
+ 2. Update license and license headers (Ed)
+ 3. Update Install and Readme.cr (Ed)
+ 4. Update windll.rc (Ed)
+ 5. Update Readme (Ed)
+ 6. Update Manual (Ed)
+------------------------ February 5th 2005 version 2.31h ------------------
+ 1. Add error return for filetime() FXMAX bug fix where missed in acornzip.c,
+    atari.c, beos.c, human68k.c, msdos.c, os2.c, theos.c, tops20.c, and
+    win32zip.c (Ed)
+ 2. Move -r and -R code in api.c lower down to avoid -R bug (Ed)
+ 3. Update VB project ReadmeVB files and notes in new VB project (Ed)
+ 4. Update license.  revision.h (Ed)
+ 5. Update Readme.cr with updated encryption information and update zip.c
+    to include encryption notice in version information (Ed)
+ 6. Remove win32/VC6-old.dsp (Cosmin)
+ 7. Check for symlink support in procname().  unix/unix.c (Cosmin)
+ 8. Define (again) ASM_CRC by default.  win32/osdep.h (Cosmin)
+ 9. Use the right type (DWORD) for volSerNo, maxCompLen and fileSysFlags
+    in FSusesLocalTime().  win32/win32.c (Cosmin)
+10. Update win32/makefile.bor, win32/makefile.gcc, win32/makefile.w32 (Cosmin)
+11. Update Readme (Ed)
+------------------------ February 15th 2005 version 2.31i ------------------
+ 1. WHERE updated (Cosmin, Christian)
+ 2. Allow for reverting to Win32 time handling using NO_W32TIMES_IZFIX.
+    win32/win32.c, win32/win32zip.h, zip.c (Christian)
+ 3. Update crypt comments and default behavior.  crypt.h
+ 4. Kludge to work around non-standard S_IFREG flag used in DJGPP V2.x,
+    compiler version strings changes.  msdos/msdos.c (Christian)
+ 5. Changes to MS rtl function declarations.  win32/osdep.h (Christian)
+ 6. Time changes including GetPlatformLocalTimezone; force use of registry
+    to get timezone info with MS C rtl.  win32/win32.c (Christian)
+ 7. Compiler version string changes.  win32/win32.c (Christian, Brad Clarke)
+ 8. Changes to extra field bytes to compress.  win32/win32zip.c (Christian)
+ 9. Changes to get_filters(), changes to help and version option detection
+    (allow redirection of version screen to file), add set dosflag for DOS to
+    force the use of msdos style when updating zip entries originally created
+    under non-DOS OS.  zip.c (Christian)
+10. License update.  zip.h (Christian)
+11. Rename errors array to ziperrors to avoid MacOSX library clash.
+    ziperr.h (Mark)
+12. Updates to zipcloak.c for crypt and other changes. (Christian)
+13. Updates to zipsplit.c (use ZCONST in prototypes where appropiate).
+    (Christian)
+14. Update version.  windll/zipver.h (Mike)
+15. Makefile updates (use UPX compressor and ...).  msdos/makefile.bor,
+    msdos/makefile.dj2, msdos/makefile.msc, msdos/makefile.tc (Christian)
+16. Detect Turbo C 2.01 in msdos/osdep.h NO_MKTIME definition. (Brian Lindholm)
+17. Readme update.  msdos/README.DOS (Christian, Ed)
+18. Change Zip limits description.  msdos/README.DOS (Christian)
+19. Fixed ASFLAGS for watcom16dos.  os2/makefile.os2 (Christian)
+20. Changes to GetLongPathEA(); fix OS/2's ACL compression code.
+    os2/os2zip.c, os2/os2zip.h (Christian, Kai Uwe)
+21. Changes to acorn.  acorn/acornzip.c, acorn/GMakefile, acorn/makefile,
+    acorn/osdep.h, acorn/ReadMe.GMakefile, acorn/riscos.c, acorn/riscos.h,
+    acorn/RunMe1st (Darren Salt, Andy Wingate, Christian)
+22. Update proginfo/extra.fld (and appnote.iz). (Christian)
+23. Correct translation of EBCDIC passwords to ASCII. (Christian)
+------------------------ February 19th 2005 version 2.31j ------------------
+ 1. Data corruption, buffer size, type cast and other fixes for VMS.
+    vms/vms_pk.c, vms/vmsmunch.c (SMS)
+ 2. Update version in file_id.diz. (Cosmin)
+ 3. Update file version.  readme.cr (Cosmin)
+ 4. Put mktemp() declaration inside the NO_PROTO guard.  tailor.h (Cosmin)
+ 5. Remove getenv() declaration.  util.c (Cosmin)
+ 6. Document and implement a new text detection scheme in set_file_type().
+    proginfo/txtvsbin.txt, trees.c (Cosmin)
+ 7. Set the "zip Debug" configuration as default.  win32/vc6/zip.dsp (Cosmin)
+ 8. Move new encryption notice from zip.c into revision.h where the other
+    notice texts reside. (Cosmin)
+ 9. Change USE_ZLIB compiler message from -v to show version.  zip.c (Cosmin)
+10. Removed change of Zip 2.31i to MS rtl function declarations.
+    win32/osdep.h (Cosmin, Christian)
+11. Don't use mmap for stored entries.  zipup.c (Christian)
+12. msdos/msdos.c, corrected missing change in version_local. (Christian)
+13. BIG_MEM and MMAP cannot be defined at the same time. tailor.h (Christian)
+14. Update LICENSE to include the new Zip maintainer Ed Gordon and
+    Cosmin Truta.  LICENSE, revision.h (Christian)
+15. Format changes.  LICENSE, revision.h (Cosmin, Christian, Ed)
+16. WHERE: URLs updated, removed last zcrXXX references. (Christian)
+17. Note that ZIP64 enhancements will (probably) never be applicable for
+    MSDOS.  msdos/README.DOS (Christian, Ed)
+18. msdos/makefile.wat, win32/makefile.wat: bug-fixes (added creation of
+    intermediate object directories). (Christian)
+19. win32/win32.c, minor indentation and code format changes. (Christian)
+20. Modified zipnote.c to handle line widths of at least 2047 characters in
+    write mode. (Christian)
+------------------------ February 20th 2005 version 2.31k ------------------
+ 1. Update to msdos/README.DOS noting splits can support some Zip64 features
+    but we may not get to most Zip64 features for MSDOS. (Christian, Ed)
+ 2. Move encryption notice in revision.h and delete blank line. (Christian)
+ 3. Change old binary detection to new black list version.  Provided by
+    Cosmin.  trees.c (Cosmin, Johnny, Christian)
+ 4. Update documentation for new binary detection.  trees.c (Christian, Ed)
+ 5. Set debug directory to od32w.  win32/makefile.wat (Christian, Ed)
+ 6. Allow -@ and - (stdout) at same time.  The check for -@ and - was
+    intended to prevent having both file contents and file names from stdin
+    at the same time but prevented this case instead.  The case where both
+    -@ and - (stdin) is used at the same time was not trapped before and
+    is still not trapped in Zip 2.31.  It apparently results in an empty
+    file called "-" in the archive.  (This may be fixed in a later Zip 2.x
+    release.  It is fixed in the Zip 3.0 beta.  Ed) (Christian)
+ 7. Update zip.h with new license (Christian)
+ 8. Update version.  revision.h (Ed)
+ 9. Add check for file size beyond 4 GB limit to file_read but should only
+    get used for OS that support large files but Zip was not compiled with
+    large file support.  zipup.c (Christian)
+10. Allow store method in memcompress.  zipup.c (Christian)
+11. Add note to ToDo (Ed)
+12. Update ZE_BIG to include reading and writing.  ziperr.h (Ed)
+13. Update Whatsnew (Ed)
+------------------------ February 26th 2005 version 2.31l ------------------
+ 1. License date change, ftp site change from ftp.uu.net to ftp.info-zip.org,
+    and other minor changes in Readme (Ed)
+ 2. Update windll/VB-orig/readmeVB.txt, windll/VB/readmeVB.txt (Ed)
+ 3. Update man page including updating the date, notes about wildcard
+    escaping on various ports, add a note to -ll about binary detection,
+    note on -v now allowing stdin to print version, and update error code 6
+    (ZE_BIG) to include read and written files.  man/zip.1 (Ed)
+ 4. Remove zip32-old.dsp from windll/visualc/dll and windll/visualc/lib (Ed)
+ 5. Update notes on crypt, TZ, WIN32, and WINDLL.  INSTALL (Christian)
+ 6. Update indentation and add Steven Schweda to LICENSE (Christian)
+ 7. Add Steven Schweda to license.  zip.h (Ed)
+ 8. Update copyright and version in atheos/Makefile (Christian)
+ 9. Format changes.  atheos/README, athoes/atheos.c, atheos/osdep.h (Christian)
+10. Update header and error 6 in ziperr.h (Christian)
+11. Change 64k entries note, add Zip64 note, and add Zip 3 and UnZip 6 note.
+    proginfo/ziplimit.txt (Christian)
+11. Update report problems address.  proginfo/ziplimit.txt (Ed)
+12. Add Steven Schweda to license.  revision.h (Ed)
+13. Add directory for files.  makefile.w10 (Christian)
+14. Change ob32w to od32w for debugging.  makefile.wat (Christian)
+15. Remove Borland and Win16 support.  windll/contents (Christian)
+16. Update formatting of license.  zip.h (Christian)
+------------------------ February 28th 2005 version 2.31m ------------------
+ 1. Update txtvsbin.txt.  proginfo/txtvsbin.txt (Cosmin)
+ 2. Changes to comments for binary detection.  trees.c (Cosmin)
+ 3. Add USE_ZLIB note.  zip.c (Cosmin)
+ 4. Update zipcloak.c to use new crypto notice (Cosmin)
+ 5. Remove duplicate license copyright note.  zipnote.c (Cosmin)
+ 6. Remove duplicate license copyright note.  zipsplit.c (Cosmin)
+ 7. Format change in LICENSE (Christian)
+ 8. Update copyright.  atheos/zipup.h (Christian)
+ 9. Update license to match final official version.  revision.h (Christian)
+10. Update license to match final official version.  zip.h (Christian)
+11. Update version to Zip 2.31 for release.  revision.h (Ed)
+12. Update notes in VB files.  windll/vb/vbzipfrm.frm,
+    windll/vb/readmeVB.txt (Ed)
+13. Formatting fixes for Manual to get dashes to be consistent and other
+    changes.  man/zip.1 (Cosmin)
+14. Change Makefile to filter out tabs using col -bx to create MANUAL to
+    avoid problems with spacing on WIN32.  unix/Makefile (Ed)
+15. Additional formatting and other changes to manual (Ed)
+16. Recompile MANUAL from man/zip.1 (Ed)
+17. Fix ZipCloak to remove old crypt comment and get encryption notice off
+    front page and move to the version page.  zipcloak.c (Ed)
+18. Update file times on unchanged files that somehow became off 6 hours
+    to match times in Zip 2.3 release.  Bugs, USexport.msg, and many files
+    in acorn, amiga, aosvs, atari, beos, cmsmvs, human68k, macos, msdos,
+    os2, proginfo, qdos, tandem, theos, tops20, unix, vms, win32, and
+    windll (Cosmin)
+19. Add new longest_match in WIN64 assembler.  Must use the new makefile
+    to compile it.  Also change win32/osdep.h to allow use of assembler
+    for longest_match without using assembler for CRC.  THIS IS UNTESTED.
+    win32/gvmat64.asm, win32/readme.x64, win32/makefile.asm64,
+    win32/osdep.h (Gilles Vollant)
+20. Add note WIN64 assembler not completely tested.  win32/readme.x64 (Ed)
+21. Minor change of wording on regulations involving crypt.  readme.cr (Ed)
+22. Update release date to 28 Feb 2005 (Ed)
+23. Update USexport.msg (Greg)
+24. Rename makefile.asm64 to makefile.a64 to stay in 8.3 name restriction
+    if someone unpacks all this on MSDOS and rename readme.x64 to
+    readme.a64 to match.  win32/readme.a64, win32/makefile.a64 (Ed)
+------------------------ March 4th 2005 version 2.31n ------------------
+ 1. Fix byte counts on exit in zipcloak() and zipbare() to fix zipcloak bug.
+    crypt.c (Paul, Christian)
+ 2. Fix swlicense size from 40 to 50.  revision.h (Cosmin)
+ 3. For ZLIB use www.zlib.net instead of www.zlib.org.  WHERE (Cosmin)
+ 4. Remove windll/windll.aps as it is not needed (Cosmin)
+ 5. Update version date.  revision.h (Ed)
+ 6. Remove windll/vb-orig project (Ed)
+ 7. Changes to VB project comments.  readmeVB.txt, VBZipBas.bas (Ed)
+ 8. Change to ZCONST.  amiga/amiga.c (Paul)
+ 9. Update Atheos port to most recent changes.  zipup.c, zipnote.c, zip.h,
+    ttyio.c, tailor.h, atheos/atheos.c, atheos/contents, atheos/Makefile,
+    atheos/osdep.h, atheos/Readme, atheos/zipup.h (Ruslan Nickolaev, Ed)
+------------------------ March 8th 2005 version 2.31 ------------------
+ 1. Update gvmat64.asm (Gilles)
+ 2. Update version.  revision.h (Ed)
+ 3. Update WhatsNew (Ed)
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..7549e8d
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,188 @@
+HOW TO INSTALL ZIP
+
+     Zip is distributed as C source code that can be compiled on a
+     wide range of systems: Unix, VMS, MSDOS, OS/2, NT, Amiga, Atari,
+     BeOS, VM/CMS, ...  You will need Unzip 5.0p1 (under any system) or
+     PKUNZIP 2.04g or later (under MSDOS) to unpack the distribution
+     file, zip231.zip. But since you read this, you have unpacked it
+     already, or you cheated and got a tar.Z file...
+
+Installation on Unix
+
+     Let's assume that you start from scratch and have not yet
+     unpacked the sources. First, unpack the source as follows,
+     assuming that you have zip231.zip in the current directory.
+
+          mkdir zipsrc
+          cd zipsrc
+          unzip ../zip231
+
+     This extracts all source files and documentation in the
+     directory called "zipsrc". This release now includes the standard
+     encryption code previously in the separate package zcrypt29.zip,
+     but you still can decide wether to activate the crypt code or not.
+     Crypt is enabled by default, but you may disable it by specifying
+     the option -DNO_CRYPT in the LOCAL_ZIP environment variable (or by
+     adding this option to the compilation options in the appropiate
+     makefile).
+     See Readme.cr for more on crypt.
+
+     You then do:
+
+          make -f unix/Makefile system
+
+     where "system" is one of: generic, generic_gcc,
+     att6300, coherent, cray_v3, minix, sco_x286, xenix, zilog.
+
+     Try "make -f unix/Makefile generic" first, this works on many systems.
+     If this fails, then use one of the special targets given above.
+
+     Among other special systems are Cray Unicos, Zilog Zeus and MINIX.
+
+     If you get error messages "constant expected" in deflate.c, add
+     -DDYN_ALLOC to CFLAGS in your makefile entry.
+
+     If you have lots of memory, try compiling with -DBIG_MEM. If your
+     system supports mmap(), try compiling with -DMMAP. This generally
+     gives faster compression but uses more memory. See the unix/Makefile
+     entry mmap_gcc for an example.
+
+     If none of these compiles, links, and functions properly on
+     your Unix system, see the file README for how to get help.
+
+     If the appropriate system was selected, then the executables
+     zip, zipnote and zipsplit will be created.  You can copy them
+     to an appropriate directory in the search path using:
+
+          make -f unix/Makefile install
+
+     The defaults are /usr/local/bin for the executables and
+     /usr/local/man/man1 for the manual page. Change the macros
+     BINDIR and MANDIR in makefile if appropriate.
+
+     You can use the command "set" to see the current search
+     path.  If you are using the C-Shell (csh), enter the com-
+     mand:
+
+          rehash
+
+     so csh can find the new command in the path.  You are now
+     ready to use Zip.
+
+     You can get rid of the now unnecessary source and object
+     files with:
+
+          cd ..
+          rm -r zipsrc
+
+     This will remove the directory zip and its contents created
+     by unzip.  You should keep the zip231.zip file around though,
+     in case you need to build it again or want to give it to a
+     colleague.
+
+     You can add the following lines to the file /etc/magic for
+     usage by the 'file' command:
+
+0       string          PK              Zip archive
+>4      byte            011             (at least v0.9 to extract)
+>4      byte            012             (at least v1.0 to extract)
+>4      byte            013             (at least v1.1 to extract)
+>4      byte            024             (at least v2.0 to extract)
+>4      byte            025             (at least v2.1 to extract)
+
+
+Installation on other systems
+
+     The steps for installation under VMS, MSDOS, OS/2, NT, Amiga and
+     Atari are similar to the above: first unzip the distribution
+     files into their own directory.  The system dependant files are
+     stored in special subdirectories.
+
+     For all the non-unix ports which support the creation of "UT" extra
+     fields (these ports contain USE_EF_UT_TIME in the list of optional
+     features displayed with "zip -v"), the timezone environment variable TZ
+     should be set according to the local timezone in order for the -f,
+     -u and -o options to work correctly.  This is not needed for the WIN32
+     and WinDLL ports, since they get the timezone information from the OS by
+     other means.
+
+  MSDOS:
+
+     Do one of:
+
+          make msdos\makefile.msc               (Microsoft C 5.1)
+          nmake -f msdos\makefile.msc           (Microsoft C 6.0 and newer)
+          make -fmsdos\makefile.bor -DCC_REV=1  (Borland Turbo C++ 1.0)
+          make -fmsdos\makefile.bor             (Borland C++ 2.0 and newer)
+          make -fmsdos\makefile.tc              (Borland Turbo C 2.0x)
+          make -f msdos/makefile.dj1            (DJGPP v1.12m4)
+          make -f msdos/makefile.dj2            (DJGPP v2.01 and newer)
+          make -f msdos/makefile.emx            (gcc/emx 0.9b and newer)
+          make -f os2/makefile.os2 gccdos       (gcc/emx 0.9b and newer)
+          wmake -f msdos\makefile.wat           (Watcom C 11.x 16-bit)
+          wmake -f msdos\makefile.wat PM=1      (Watcom C 11.x 32-bit, PMODE/W)
+
+
+     for Microsoft, Borland C++ and Turbo C, Watcom C/C++ and the various
+     free GNU C implementations, respectively. More detailed instructions
+     can be found in the respective makefiles.
+
+
+  WIN32 (Windows NT/2K/XP/2K3 and Windows 95/98/ME):
+
+     Supported compilers are Microsoft Visual C++, Borland C++, Watcom C/C++,
+     and miscellaneous free GNU C implementations (gcc/mingw, CygWin, ...).
+     The makefiles supplied in the win32/ subdirectory contain further
+     information.
+
+
+  Windows DLL (WIN32):
+
+     Supported environments are Visual C++ (32-bit only, 5.x and newer).
+     For instructions how to build the DLLs and where find the makefiles,
+     look into windll/contents.
+
+
+  OS/2:
+
+     Type
+
+          {make} -f os2/makefile.os2
+
+     to get a list of supported targets/compiling environments.
+     (replace "{make}" with the name of your OS/2 make utility.)
+
+     To initiate the actual compiling process, you have to specify
+     a system target:
+
+          {make} -f os2/makefile.os2 {system}
+
+     An example: type
+
+          nmake -f os2/makefile.os2 msc
+
+     for Microsoft C 6.00.
+
+
+  VMS (OpenVMS):
+
+     Apply
+
+          @[.vms]make_zip
+
+     or use DEC's MMS make utility (or the MMK clone) if available:
+
+          mms /descr=[.vms]descrip.mms /macro=(__ALPHA__=1)   for Alpha AXP
+          mms /descr=[.vms]descrip.mms /macro=(__DECC__=1)    for DEC C on VAX
+          mms /descr=[.vms]descrip.mms /macro=(__VAXC__=1)    for VAX C
+          mms /descr=[.vms]descrip.mms /macro=(__GNUC__=1)    for GNU C on VAX
+
+     (If you have installed both DEC C and VAX C on your VAX and want to use
+      the latter compiler, you should define the macro "__FORCE_VAXC__"
+      instead of "__VAXC__".)
+
+     For further information please consult 00readme.txt in the vms/
+     subdirectory.
+
+For command help on any of the zip* utilities, simply enter
+the name with no arguments.
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..9cc83dc
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,55 @@
+This is version 2005-Feb-10 of the Info-ZIP copyright and license.
+The definitive version of this document should be available at
+ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely.
+
+
+Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+For the purposes of this copyright and license, "Info-ZIP" is defined as
+the following set of individuals:
+
+   Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,
+   Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,
+   Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,
+   David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,
+   Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,
+   Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,
+   Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,
+   Rich Wales, Mike White
+
+This software is provided "as is," without warranty of any kind, express
+or implied.  In no event shall Info-ZIP or its contributors be held liable
+for any direct, indirect, incidental, special or consequential damages
+arising out of the use of or inability to use this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+    1. Redistributions of source code must retain the above copyright notice,
+       definition, disclaimer, and this list of conditions.
+
+    2. Redistributions in binary form (compiled executables) must reproduce
+       the above copyright notice, definition, disclaimer, and this list of
+       conditions in documentation and/or other materials provided with the
+       distribution.  The sole exception to this condition is redistribution
+       of a standard UnZipSFX binary (including SFXWiz) as part of a
+       self-extracting archive; that is permitted without inclusion of this
+       license, as long as the normal SFX banner has not been removed from
+       the binary or disabled.
+
+    3. Altered versions--including, but not limited to, ports to new operating
+       systems, existing ports with new graphical interfaces, and dynamic,
+       shared, or static library versions--must be plainly marked as such
+       and must not be misrepresented as being the original source.  Such
+       altered versions also must not be misrepresented as being Info-ZIP
+       releases--including, but not limited to, labeling of the altered
+       versions with the names "Info-ZIP" (or any variation thereof, including,
+       but not limited to, different capitalizations), "Pocket UnZip," "WiZ"
+       or "MacZip" without the explicit permission of Info-ZIP.  Such altered
+       versions are further prohibited from misrepresentative use of the
+       Zip-Bugs or Info-ZIP e-mail addresses or of the Info-ZIP URL(s).
+
+    4. Info-ZIP retains the right to use the names "Info-ZIP," "Zip," "UnZip,"
+       "UnZipSFX," "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip" for its
+       own source and binary releases.
diff --git a/MANUAL b/MANUAL
new file mode 100644 (file)
index 0000000..6b6f88b
--- /dev/null
+++ b/MANUAL
@@ -0,0 +1,804 @@
+ZIP(1L)                                                                ZIP(1L)
+
+NAME
+       zip, zipcloak, zipnote, zipsplit - package and compress (archive) files
+
+SYNOPSIS
+       zip   [-aABcdDeEfFghjklLmoqrRSTuvVwXyz!@$]   [-b path]    [-n suffixes]
+       [-t mmddyyyy] [-tt mmddyyyy] [ zipfile [ file1 file2 ...]] [-xi list]
+
+       zipcloak [-dhL] [-b path] zipfile
+
+       zipnote [-hwL] [-b path] zipfile
+
+       zipsplit [-hiLpst] [-n size] [-b path] zipfile
+
+DESCRIPTION
+       zip  is  a compression and file packaging utility for Unix, VMS, MSDOS,
+       OS/2, Windows NT, Minix, Atari and Macintosh, Amiga and Acorn RISC  OS.
+
+       It  is  analogous to a combination of the UNIX commands tar(1) and com-
+       press(1) and is compatible with PKZIP (Phil Katz's ZIP for  MSDOS  sys-
+       tems).
+
+       A  companion  program  (unzip(1L)),  unpacks zip archives.  The zip and
+       unzip(1L) programs can work with archives produced by PKZIP, and  PKZIP
+       and  PKUNZIP  can work with archives produced by zip.  zip version 2.31
+       is compatible with PKZIP 2.04.  Note that PKUNZIP 1.10  cannot  extract
+       files produced by PKZIP 2.04 or zip 2.31. You must use PKUNZIP 2.04g or
+       unzip 5.0p1 (or later versions) to extract them.
+
+       For a brief help on zip and unzip,  run  each  without  specifying  any
+       parameters on the command line.
+
+       The  program  is  useful for packaging a set of files for distribution;
+       for archiving files; and for saving disk space by temporarily compress-
+       ing unused files or directories.
+
+       The  zip  program  puts  one or more compressed files into a single zip
+       archive, along with information about the files (name, path, date, time
+       of  last modification, protection, and check information to verify file
+       integrity).  An entire directory structure can be  packed  into  a  zip
+       archive  with  a  single command.  Compression ratios of 2:1 to 3:1 are
+       common for text files.  zip has one compression method (deflation)  and
+       can  also  store  files without compression.  zip automatically chooses
+       the better of the two for each file to be compressed.
+
+       When given the name of an existing zip archive, zip will replace  iden-
+       tically  named entries in the zip archive or add entries for new names.
+       For example, if foo.zip exists and contains  foo/file1  and  foo/file2,
+       and the directory foo contains the files foo/file1 and foo/file3, then:
+
+              zip -r foo foo
+
+       will replace foo/file1 in foo.zip and add foo/file3 to foo.zip.   After
+       this,  foo.zip  contains  foo/file1,  foo/file2,  and  foo/file3,  with
+       foo/file2 unchanged from before.
+
+       If the file list is specified as -@, [Not on MacOS] zip takes the  list
+       of  input  files  from  standard input.  Under UNIX, this option can be
+       used to powerful effect in conjunction with the find(1)  command.   For
+       example, to archive all the C source files in the current directory and
+       its subdirectories:
+
+              find . -name "*.[ch]" -print | zip source -@
+
+       (note that the pattern must be quoted to keep the shell from  expanding
+       it).  zip will also accept a single dash ("-") as the zip file name, in
+       which case it will write the zip file to standard output, allowing  the
+       output to be piped to another program. For example:
+
+              zip -r - . | dd of=/dev/nrst0 obs=16k
+
+       would  write the zip output directly to a tape with the specified block
+       size for the purpose of backing up the current directory.
+
+       zip also accepts a single dash ("-") as the name of a file to  be  com-
+       pressed,  in  which  case  it  will  read the file from standard input,
+       allowing zip to take input from another program. For example:
+
+              tar cf - . | zip backup -
+
+       would compress the output of the tar command for the purpose of backing
+       up  the  current  directory. This generally produces better compression
+       than the previous example using the -r option,  because  zip  can  take
+       advantage of redundancy between files. The backup can be restored using
+       the command
+
+              unzip -p backup | tar xf -
+
+       When no zip file name is given and stdout is not a terminal,  zip  acts
+       as  a filter, compressing standard input to standard output.  For exam-
+       ple,
+
+              tar cf - . | zip | dd of=/dev/nrst0 obs=16k
+
+       is equivalent to
+
+              tar cf - . | zip - - | dd of=/dev/nrst0 obs=16k
+
+       zip archives created in this manner can be extracted with  the  program
+       funzip  which  is  provided in the unzip package, or by gunzip which is
+       provided in the gzip package. For example:
+
+              dd if=/dev/nrst0  ibs=16k | funzip | tar xvf -
+
+       When changing an existing zip archive, zip will write a temporary  file
+       with the new contents, and only replace the old one when the process of
+       creating the new version has been completed without error.
+
+       If the name of the zip archive  does  not  contain  an  extension,  the
+       extension  .zip  is  added.  If  the name already contains an extension
+       other than .zip the existing extension is kept unchanged.
+
+OPTIONS
+       -a     [Systems using EBCDIC] Translate file to ASCII format.
+
+       -A     Adjust self-extracting executable  archive.   A  self-extracting
+              executable  archive  is created by prepending the SFX stub to an
+              existing archive. The -A option tells zip to  adjust  the  entry
+              offsets  stored in the archive to take into account this "pream-
+              ble" data.
+
+       Note: self-extracting archives for the Amiga are a  special  case.   At
+       present, only the Amiga port of Zip is capable of adjusting or updating
+       these without corrupting them.  -J can be used to remove the  SFX  stub
+       if other updates need to be made.
+
+       -B     [VM/CMS and MVS] force file to be read binary (default is text).
+
+       -Bn    [TANDEM] set Edit/Enscribe formatting options with n defined as
+              bit  0: Don't add delimiter (Edit/Enscribe)
+              bit 1: Use LF rather than CR/LF as delimiter (Edit/Enscribe)
+              bit  2: Space fill record to maximum record length (Enscribe)
+              bit  3: Trim trailing space (Enscribe)
+              bit 8: Force 30K (Expand) large read for unstructured files
+
+       -b path
+              Use the specified path for the temporary zip archive. For  exam-
+              ple:
+
+                     zip -b /tmp stuff *
+
+              will  put the temporary zip archive in the directory /tmp, copy-
+              ing over stuff.zip to the  current  directory  when  done.  This
+              option is only useful when updating an existing archive, and the
+              file system containing this old archive  does  not  have  enough
+              space to hold both old and new archives at the same time.
+
+       -c     Add  one-line  comments for each file.  File operations (adding,
+              updating) are done first, and the user is then  prompted  for  a
+              one-line  comment  for each file.  Enter the comment followed by
+              return, or just return for no comment.
+
+       -d     Remove (delete) entries from a zip archive.  For example:
+
+                     zip -d foo foo/tom/junk foo/harry/\* \*.o
+
+              will remove the entry foo/tom/junk, all of the files that  start
+              with  foo/harry/,  and all of the files that end with .o (in any
+              path).  Note that shell pathname expansion  has  been  inhibited
+              with  backslashes,  so  that zip can see the asterisks, enabling
+              zip to match on the contents of the zip archive instead  of  the
+              contents of the current directory.
+
+              Under systems where the shell does not expand wildcards, such as
+              MSDOS, the backslashes are not needed.  The above would then be
+
+                     zip -d foo foo/tom/junk foo/harry/* *.o
+
+              Under MSDOS, -d is case sensitive when it matches names  in  the
+              zip  archive.  This requires that file names be entered in upper
+              case if they were zipped by PKZIP on an MSDOS system.
+
+       -df    [MacOS] Include only data-fork of files zipped into the archive.
+              Good   for   exporting   files   to  foreign  operating-systems.
+              Resource-forks will be ignored at all.
+
+       -D     Do not create  entries  in  the  zip  archive  for  directories.
+              Directory   entries   are  created  by  default  so  that  their
+              attributes can be saved in the  zip  archive.   The  environment
+              variable  ZIPOPT  can be used to change the default options. For
+              example under Unix with sh:
+
+                     ZIPOPT="-D"; export ZIPOPT
+
+              (The variable ZIPOPT can be used for any option except -i and -x
+              and  can  include several options.) The option -D is a shorthand
+              for -x "*/" but the latter cannot  be  set  as  default  in  the
+              ZIPOPT environment variable.
+
+       -e     Encrypt  the  contents of the zip archive using a password which
+              is entered on the terminal in response to a  prompt  (this  will
+              not  be  echoed;  if  standard error is not a tty, zip will exit
+              with an error).  The password prompt is  repeated  to  save  the
+              user from typing errors.
+
+       -E     [OS/2]  Use the .LONGNAME Extended Attribute (if found) as file-
+              name.
+
+       -f     Replace (freshen) an existing entry in the zip archive  only  if
+              it  has  been modified more recently than the version already in
+              the zip archive; unlike the update option (-u) this will not add
+              files that are not already in the zip archive.  For example:
+
+                     zip -f foo
+
+              This  command  should  be run from the same directory from which
+              the original zip command was run,  since  paths  stored  in  zip
+              archives are always relative.
+
+              Note  that  the  timezone  environment variable TZ should be set
+              according to the local timezone in order for the -f , -u and  -o
+              options to work correctly.
+
+              The  reasons behind this are somewhat subtle but have to do with
+              the differences between the Unix-format file  times  (always  in
+              GMT) and most of the other operating systems (always local time)
+              and the necessity to compare the two.  A  typical  TZ  value  is
+              ``MET-1MEST''  (Middle  European  time with automatic adjustment
+              for ``summertime'' or Daylight Savings Time).
+
+       -F     Fix the zip archive. This option can be used if some portions of
+              the  archive  are  missing. It is not guaranteed to work, so you
+              MUST make a backup of the original archive first.
+
+              When doubled as in -FF the compressed  sizes  given  inside  the
+              damaged archive are not trusted and zip scans for special signa-
+              tures to identify the limits between the  archive  members.  The
+              single  -F  is more reliable if the archive is not too much dam-
+              aged, for example if it has only been  truncated,  so  try  this
+              option first.
+
+              Neither  option will recover archives that have been incorrectly
+              transferred in ascii mode instead of binary. After  the  repair,
+              the  -t option of unzip may show that some files have a bad CRC.
+              Such files cannot be recovered; you can  remove  them  from  the
+              archive using the -d option of zip.
+
+       -g     Grow  (append to) the specified zip archive, instead of creating
+              a new one. If this operation fails, zip attempts to restore  the
+              archive  to  its  original  state. If the restoration fails, the
+              archive might become corrupted.  This  option  is  ignored  when
+              there's  no existing archive or when at least one archive member
+              must be updated or deleted.
+
+       -h     Display the zip help information (this also appears  if  zip  is
+              run with no arguments).
+
+       -i files
+              Include only the specified files, as in:
+
+                     zip -r foo . -i \*.c
+
+              which  will include only the files that end in .c in the current
+              directory and its subdirectories. (Note  for  PKZIP  users:  the
+              equivalent command is
+
+                     pkzip -rP foo *.c
+
+              PKZIP  does  not  allow  recursion in directories other than the
+              current one.)  The backslash avoids the shell filename substitu-
+              tion,  so  that  the  name  matching  is performed by zip at all
+              directory levels.  Not escaping  wildcards  on  shells  that  do
+              wildcard  substitution before zip gets the command line may seem
+              to work but files in subdirectories matching  the  pattern  will
+              never  be checked and so not matched.  For shells, such as Win32
+              command prompts, that do not replace  file  patterns  containing
+              wildcards with the respective file names, zip will do the recur-
+              sion and escaping the wildcards is not needed.
+
+              Also possible:
+
+                     zip -r foo  . -i@include.lst
+
+              which will only include the files in the current  directory  and
+              its   subdirectories   that  match  the  patterns  in  the  file
+              include.lst.
+
+       -I     [Acorn RISC OS] Don't scan through Image files.  When used,  zip
+              will  not  consider  Image  files  (eg.  DOS partitions or Spark
+              archives when SparkFS is loaded) as directories but  will  store
+              them as single files.
+
+              For example, if you have SparkFS loaded, zipping a Spark archive
+              will result in a zipfile containing a directory  (and  its  con-
+              tent)  while  using the 'I' option will result in a zipfile con-
+              taining a Spark archive. Obviously this second case will also be
+              obtained (without the 'I' option) if SparkFS isn't loaded.
+
+       -j     Store  just the name of a saved file (junk the path), and do not
+              store directory names. By default, zip will store the full  path
+              (relative to the current path).
+
+       -jj    [MacOS] record Fullpath (+ Volname). The complete path including
+              volume will be stored. By default  the  relative  path  will  be
+              stored.
+
+       -J     Strip any prepended data (e.g. a SFX stub) from the archive.
+
+       -k     Attempt  to  convert  the  names  and paths to conform to MSDOS,
+              store only the MSDOS attribute (just the  user  write  attribute
+              from  UNIX), and mark the entry as made under MSDOS (even though
+              it was not); for compatibility with PKUNZIP  under  MSDOS  which
+              cannot handle certain names such as those with two dots.
+
+       -l     Translate  the Unix end-of-line character LF into the MSDOS con-
+              vention CR LF. This option should not be used on  binary  files.
+              This  option can be used on Unix if the zip file is intended for
+              PKUNZIP under MSDOS. If the input files already contain  CR  LF,
+              this option adds an extra CR. This ensures that unzip -a on Unix
+              will get back an exact copy of the original file,  to  undo  the
+              effect  of  zip  -l.   See  the note on binary detection for -ll
+              below.
+
+       -ll    Translate the MSDOS end-of-line CR LF into Unix LF.  This option
+              should  not be used on binary files and a warning will be issued
+              when a file is converted that later is detected  to  be  binary.
+              This option can be used on MSDOS if the zip file is intended for
+              unzip under Unix.
+
+              In Zip 2.31 binary detection has been changed from a simple per-
+              centage  of  binary characters being considered binary to a more
+              selective method that should consider files  in  many  character
+              sets, including UTF-8, that only include text characters in that
+              character set to be text.  This allows unzip -a to convert these
+              files.
+
+       -L     Display the zip license.
+
+       -m     Move  the  specified  files into the zip archive; actually, this
+              deletes the target directories/files after making the  specified
+              zip  archive.  If a directory becomes empty after removal of the
+              files, the directory is also  removed.  No  deletions  are  done
+              until zip has created the archive without error.  This is useful
+              for conserving disk space, but is potentially dangerous so it is
+              recommended to use it in combination with -T to test the archive
+              before removing all input files.
+
+       -n suffixes
+              Do not attempt to compress files named with the given  suffixes.
+              Such  files are simply stored (0% compression) in the output zip
+              file, so that zip doesn't waste  its  time  trying  to  compress
+              them.   The  suffixes  are  separated  by either colons or semi-
+              colons.  For example:
+
+                     zip -rn .Z:.zip:.tiff:.gif:.snd  foo foo
+
+              will copy everything from foo into foo.zip, but will  store  any
+              files  that end in .Z, .zip, .tiff, .gif, or .snd without trying
+              to compress them (image and sound files  often  have  their  own
+              specialized compression methods).  By default, zip does not com-
+              press     files     with     extensions     in     the      list
+              .Z:.zip:.zoo:.arc:.lzh:.arj.   Such files are stored directly in
+              the output archive.  The environment variable ZIPOPT can be used
+              to change the default options. For example under Unix with csh:
+
+                     setenv ZIPOPT "-n .gif:.zip"
+
+              To attempt compression on all files, use:
+
+                     zip -n : foo
+
+              The  maximum  compression option -9 also attempts compression on
+              all files regardless of extension.
+
+              On Acorn RISC OS systems the suffixes are actually filetypes  (3
+              hex  digit format). By default, zip does not compress files with
+              filetypes in the list DDC:D96:68E (i.e. Archives, CFS files  and
+              PackDir files).
+
+       -N     [Amiga,  MacOS]  Save  Amiga  or MacOS filenotes as zipfile com-
+              ments. They can be restored by using the -N option of unzip.  If
+              -c  is  used  also, you are prompted for comments only for those
+              files that do not have filenotes.
+
+       -o     Set the "last modified" time of the zip archive  to  the  latest
+              (oldest) "last modified" time found among the entries in the zip
+              archive.  This can be used  without  any  other  operations,  if
+              desired.  For example:
+
+                     zip -o foo
+
+              will change the last modified time of foo.zip to the latest time
+              of the entries in foo.zip.
+
+       -P password
+              use password to encrypt zipfile entries (if any).  THIS IS INSE-
+              CURE!   Many  multi-user  operating systems provide ways for any
+              user to see the current command line of any other user; even  on
+              stand-alone  systems  there  is  always  the threat of over-the-
+              shoulder peeking.  Storing the plaintext password as part  of  a
+              command  line  in  an  automated script is even worse.  Whenever
+              possible, use the non-echoing, interactive prompt to enter pass-
+              words.   (And  where  security  is  truly  important, use strong
+              encryption such as Pretty Good Privacy instead of the relatively
+              weak encryption provided by standard zipfile utilities.)
+
+       -q     Quiet   mode;   eliminate  informational  messages  and  comment
+              prompts.  (Useful, for example, in shell scripts and  background
+              tasks).
+
+       -Qn    [QDOS]  store information about the file in the file header with
+              n defined as
+              bit  0: Don't add headers for any file
+              bit  1: Add headers for all files
+              bit  2: Don't wait for interactive key press on exit
+
+       -r     Travel the directory structure recursively; for example:
+
+                     zip -r foo foo
+
+              In this case, all the files and directories in foo are saved  in
+              a zip archive named foo.zip, including files with names starting
+              with ".", since the recursion does not use the shell's file-name
+              substitution  mechanism.  If you wish to include only a specific
+              subset of the files in directory foo and its subdirectories, use
+              the  -i  option  to specify the pattern of files to be included.
+              You should not use -r with the name  ".*",  since  that  matches
+              ".."   which will attempt to zip up the parent directory (proba-
+              bly not what was intended).
+
+       -R     Travel the directory structure recursively starting at the  cur-
+              rent directory; for example:
+
+                     zip -R foo '*.c'
+
+              In this case, all the files matching *.c in the tree starting at
+              the current directory  are  stored  into  a  zip  archive  named
+              foo.zip.  Note for PKZIP users: the equivalent command is
+
+                     pkzip -rP foo *.c
+
+       -S     [MSDOS,  OS/2, WIN32 and ATARI] Include system and hidden files.
+              [MacOS] Includes finder invisible files, which are ignored  oth-
+              erwise.
+
+       -t mmddyyyy
+              Do  not  operate  on files modified prior to the specified date,
+              where mm is the month (0-12), dd is the day of the month (1-31),
+              and  yyyy  is  the year.  The ISO 8601 date format yyyy-mm-dd is
+              also accepted.  For example:
+
+                     zip -rt 12071991 infamy foo
+
+                     zip -rt 1991-12-07 infamy foo
+
+              will add all the files in foo and its subdirectories  that  were
+              last  modified  on  or after 7 December 1991, to the zip archive
+              infamy.zip.
+
+       -tt mmddyyyy
+              Do not operate on files modified after or at the specified date,
+              where mm is the month (0-12), dd is the day of the month (1-31),
+              and yyyy is the year.  The ISO 8601 date  format  yyyy-mm-dd  is
+              also accepted.  For example:
+
+                     zip -rtt 11301995 infamy foo
+
+                     zip -rtt 1995-11-30 infamy foo
+
+              will  add  all the files in foo and its subdirectories that were
+              last modified before the 30 November 1995, to  the  zip  archive
+              infamy.zip.
+
+       -T     Test  the integrity of the new zip file. If the check fails, the
+              old zip file is unchanged and (with  the  -m  option)  no  input
+              files are removed.
+
+       -u     Replace (update) an existing entry in the zip archive only if it
+              has been modified more recently than the version already in  the
+              zip archive.  For example:
+
+                     zip -u stuff *
+
+              will  add any new files in the current directory, and update any
+              files which have been modified since the zip  archive  stuff.zip
+              was  last  created/modified  (note that zip will not try to pack
+              stuff.zip into itself when you do this).
+
+              Note that the -u option with  no  arguments  acts  like  the  -f
+              (freshen) option.
+
+       -v     Verbose mode or print diagnostic version info.
+
+              Normally,  when  applied to real operations, this option enables
+              the display of  a  progress  indicator  during  compression  and
+              requests  verbose  diagnostic info about zipfile structure oddi-
+              ties.
+
+              When -v is the only command line argument, and either  stdin  or
+              stdout  is  not  redirected  to  a  file, a diagnostic screen is
+              printed. In addition to the  help  screen  header  with  program
+              name,  version,  and release date, some pointers to the Info-ZIP
+              home and distribution sites are given. Then, it  shows  informa-
+              tion about the target environment (compiler type and version, OS
+              version, compilation date and the enabled optional features used
+              to create the zip executable.
+
+       -V     [VMS]  Save  VMS  file  attributes  and  use portable form.  zip
+              archives created with this option are truncated at EOF but still
+              may  not  be usable on other systems depending on the file types
+              being zipped.
+
+       -VV    [VMS] Save VMS file attributes.  zip archives created with  this
+              option  include  the  entire file and should be able to recreate
+              most VMS files on VMS systems but these archives will  generally
+              not be usable on other systems.
+
+       -w     [VMS]  Append  the  version  number  of  the  files to the name,
+              including multiple versions of files.  (default:  use  only  the
+              most recent version of a specified file).
+
+       -x files
+              Explicitly exclude the specified files, as in:
+
+                     zip -r foo foo -x \*.o
+
+              which  will include the contents of foo in foo.zip while exclud-
+              ing all the files that end in  .o.   The  backslash  avoids  the
+              shell  filename  substitution, so that the name matching is per-
+              formed by zip at all directory levels.  If  you  do  not  escape
+              wildcards in patterns it may seem to work but files in subdirec-
+              tories will not be checked for matches.
+
+              Also possible:
+
+                     zip -r foo foo -x@exclude.lst
+
+              which will include the contents of foo in foo.zip while  exclud-
+              ing   all  the  files  that  match  the  patterns  in  the  file
+              exclude.lst (each file pattern on a separate line).
+
+       -X     Do not save extra file attributes (Extended Attributes on  OS/2,
+              uid/gid and file times on Unix).
+
+       -y     Store symbolic links as such in the zip archive, instead of com-
+              pressing and storing the file referred  to  by  the  link  (UNIX
+              only).
+
+       -z     Prompt for a multi-line comment for the entire zip archive.  The
+              comment is ended by a line containing just a period, or  an  end
+              of  file condition (^D on UNIX, ^Z on MSDOS, OS/2, and VAX/VMS).
+              The comment can be taken from a file:
+
+                     zip -z foo < foowhat
+
+       -#     Regulate the speed of compression using the specified  digit  #,
+              where  -0  indicates  no compression (store all files), -1 indi-
+              cates the fastest compression method (less compression)  and  -9
+              indicates  the  slowest compression method (optimal compression,
+              ignores the suffix list). The default compression level is -6.
+
+       -!     [WIN32] Use priviliges (if granted) to  obtain  all  aspects  of
+              WinNT security.
+
+       -@     Take the list of input files from standard input. Only one file-
+              name per line.
+
+       -$     [MSDOS, OS/2, WIN32] Include the  volume  label  for  the  drive
+              holding the first file to be compressed.  If you want to include
+              only the volume label or to force  a  specific  drive,  use  the
+              drive name as first file name, as in:
+
+                     zip -$ foo a: c:bar
+
+EXAMPLES
+       The simplest example:
+
+              zip stuff *
+
+       creates the archive stuff.zip (assuming it does not exist) and puts all
+       the files in the current directory in it, in compressed form (the  .zip
+       suffix  is added automatically, unless that archive name given contains
+       a dot already; this allows the explicit  specification  of  other  suf-
+       fixes).
+
+       Because of the way the shell does filename substitution, files starting
+       with "." are not included; to include these as well:
+
+              zip stuff .* *
+
+       Even this will not include any subdirectories from the  current  direc-
+       tory.
+
+       To zip up an entire directory, the command:
+
+              zip -r foo foo
+
+       creates  the  archive foo.zip, containing all the files and directories
+       in the directory foo that is contained within the current directory.
+
+       You may want to make a zip archive that  contains  the  files  in  foo,
+       without  recording  the directory name, foo.  You can use the -j option
+       to leave off the paths, as in:
+
+              zip -j foo foo/*
+
+       If you are short on disk space, you might not have enough room to  hold
+       both  the  original  directory  and  the  corresponding  compressed zip
+       archive.  In this case, you can create the archive in steps  using  the
+       -m  option.   If  foo contains the subdirectories tom, dick, and harry,
+       you can:
+
+              zip -rm foo foo/tom
+              zip -rm foo foo/dick
+              zip -rm foo foo/harry
+
+       where the first command creates foo.zip, and the next two  add  to  it.
+       At  the  completion  of  each  zip command, the last created archive is
+       deleted, making room for the next zip command to function.
+
+PATTERN MATCHING
+       This section applies only to UNIX, though the  ?,  *,  and  []  special
+       characters  are implemented on other systems including MSDOS and Win32.
+       Watch this space for details on MSDOS and VMS operation.
+
+       The UNIX shells (sh(1) and csh(1)) do filename substitution on  command
+       arguments.  The special characters are:
+
+       ?      match any single character
+
+       *      match any number of characters (including none)
+
+       []     match  any  character in the range indicated within the brackets
+              (example: [a-f], [0-9]).
+
+       When these characters are encountered (without  being  escaped  with  a
+       backslash  or  quotes),  the  shell will look for files relative to the
+       current path that match the pattern, and replace the  argument  with  a
+       list of the names that matched.
+
+       The  zip  program can do the same matching on names that are in the zip
+       archive being modified or, in the  case  of  the  -x  (exclude)  or  -i
+       (include)  options,  on  the  list of files to be operated on, by using
+       backslashes or quotes to tell the shell not to do the  name  expansion.
+       In  general,  when zip encounters a name in the list of files to do, it
+       first looks for the name in the file system.  If it finds it,  it  then
+       adds  it  to the list of files to do.  If it does not find it, it looks
+       for the name in the zip archive being modified (if  it  exists),  using
+       the  pattern matching characters described above, if present.  For each
+       match, it will add that name to the list  of  files  to  be  processed,
+       unless  this  name  matches  one  given with the -x option, or does not
+       match any name given with the -i option.
+
+       The pattern matching includes the path, and so patterns like \*.o match
+       names  that  end in ".o", no matter what the path prefix is.  Note that
+       the backslash must precede every special character (i.e. ?*[]), or  the
+       entire argument must be enclosed in double quotes ("").
+
+       In  general, use backslash to make zip do the pattern matching with the
+       -f (freshen) and -d  (delete)  options,  and  sometimes  after  the  -x
+       (exclude)  option when used with an appropriate operation (add, -u, -f,
+       or -d).
+
+ENVIRONMENT
+       ZIPOPT contains default options that will be used when running zip
+
+       ZIP    [Not on RISC OS and VMS] see ZIPOPT
+
+       Zip$Options
+              [RISC OS] see ZIPOPT
+
+       Zip$Exts
+              [RISC OS] contains extensions separated by a : that  will  cause
+              native  filenames  with  one  of  the specified extensions to be
+              added to the zip file with basename and extension swapped.  zip
+
+       ZIP_OPTS
+              [VMS] see ZIPOPT
+
+SEE ALSO
+       compress(1), shar(1L), tar(1), unzip(1L), gzip(1L)
+
+DIAGNOSTICS
+       The exit status (or error level) approximates the exit codes defined by
+       PKWARE and takes on the following values, except under VMS:
+
+              0      normal; no errors or warnings detected.
+
+              2      unexpected end of zip file.
+
+              3      a generic error in the zipfile format was detected.  Pro-
+                     cessing may have completed successfully anyway; some bro-
+                     ken zipfiles created by other archivers have simple work-
+                     arounds.
+
+              4      zip was unable to allocate memory for one or more buffers
+                     during program initialization.
+
+              5      a  severe error in the zipfile format was detected.  Pro-
+                     cessing probably failed immediately.
+
+              6      entry too large to split (with zipsplit), read, or write
+
+              7      invalid comment format
+
+              8      zip -T failed or out of memory
+
+              9      the user aborted zip prematurely with control-C (or simi-
+                     lar)
+
+              10     zip encountered an error while using a temp file
+
+              11     read or seek error
+
+              12     zip has nothing to do
+
+              13     missing or empty zip file
+
+              14     error writing to a file
+
+              15     zip was unable to create a file to write to
+
+              16     bad command line parameters
+
+              18     zip could not open a specified file to read
+
+       VMS  interprets  standard Unix (or PC) return values as other, scarier-
+       looking things, so zip instead maps them into VMS-style  status  codes.
+       The current mapping is as follows:   1 (success) for normal exit,
+        and (0x7fff000? + 16*normal_zip_exit_status) for all errors, where the
+       `?' is 0 (warning) for zip value 12, 2 (error) for the zip values 3, 6,
+       7, 9, 13, 16, 18, and 4 (fatal error) for the remaining ones.
+
+BUGS
+       zip  2.31  is  not compatible with PKUNZIP 1.10. Use zip 1.1 to produce
+       zip files which can be extracted by PKUNZIP 1.10.
+
+       zip files produced by zip 2.31 must not be updated by zip 1.1 or  PKZIP
+       1.10,  if  they contain encrypted members or if they have been produced
+       in a pipe or on a non-seekable device. The old versions of zip or PKZIP
+       would create an archive with an incorrect format.  The old versions can
+       list the contents of the zip file but cannot extract it anyway (because
+       of  the  new  compression algorithm).  If you do not use encryption and
+       use regular disk files, you do not have to care about this problem.
+
+       Under VMS, not all of the odd file formats are treated properly.   Only
+       stream-LF  format  zip files are expected to work with zip.  Others can
+       be converted using Rahul Dhesi's BILF program.   This  version  of  zip
+       handles some of the conversion internally.  When using Kermit to trans-
+       fer zip files from Vax to MSDOS, type "set file type block" on the Vax.
+       When  transfering  from MSDOS to Vax, type "set file type fixed" on the
+       Vax.  In both cases, type "set file type binary" on MSDOS.
+
+       Under VMS, zip hangs for file specification  that  uses  DECnet  syntax
+       foo::*.*.
+
+       On OS/2, zip cannot match some names, such as those including an excla-
+       mation mark or a hash sign.  This is a bug in OS/2 itself:  the  32-bit
+       DosFindFirst/Next  don't  find  such names.  Other programs such as GNU
+       tar are also affected by this bug.
+
+       Under OS/2, the amount of Extended Attributes displayed by DIR is  (for
+       compatibility)  the  amount returned by the 16-bit version of DosQuery-
+       PathInfo(). Otherwise OS/2 1.3 and 2.0 would report different EA  sizes
+       when  DIRing  a  file.   However,  the structure layout returned by the
+       32-bit DosQueryPathInfo() is a bit different,  it  uses  extra  padding
+       bytes  and  link  pointers  (it's  a linked list) to have all fields on
+       4-byte boundaries for portability to future RISC OS/2 versions.  There-
+       fore  the value reported by zip (which uses this 32-bit-mode size) dif-
+       fers from that reported by DIR.   zip  stores  the  32-bit  format  for
+       portability, even the 16-bit MS-C-compiled version running on OS/2 1.3,
+       so even this one shows the 32-bit-mode size.
+
+       Development of Zip 3.0 is underway.  See that source  distribution  for
+       many new features and the latest bug fixes.
+
+AUTHORS
+       Copyright (C) 1997-2005 Info-ZIP.
+
+       Copyright (C) 1990-1997 Mark Adler, Richard B. Wales, Jean-loup Gailly,
+       Onno van der Linden, Kai Uwe Rommel, Igor Mandrichenko, John  Bush  and
+       Paul  Kienitz.   Permission is granted to any individual or institution
+       to use, copy, or redistribute this software so long as all of the orig-
+       inal  files are included, that it is not sold for profit, and that this
+       copyright notice is retained.
+
+       LIKE ANYTHING ELSE THAT'S FREE, ZIP AND ITS  ASSOCIATED  UTILITIES  ARE
+       PROVIDED  AS IS AND COME WITH NO WARRANTY OF ANY KIND, EITHER EXPRESSED
+       OR IMPLIED. IN NO EVENT WILL THE COPYRIGHT HOLDERS BE  LIABLE  FOR  ANY
+       DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE.
+
+       Please  send bug reports and comments to: zip-bugs at www.info-zip.org.
+       For bug reports, please include the version of zip  (see  zip -h),  the
+       make options used to compile it (see zip -v), the machine and operating
+       system in use, and as much additional information as possible.
+
+ACKNOWLEDGEMENTS
+       Thanks to R. P. Byrne for his Shrink.Pas program, which  inspired  this
+       project,  and  from which the shrink algorithm was stolen; to Phil Katz
+       for placing in the public domain the zip file format, compression  for-
+       mat,  and  .ZIP  filename extension, and for accepting minor changes to
+       the file format; to Steve Burg for clarifications on the  deflate  for-
+       mat;  to Haruhiko Okumura and Leonid Broukhis for providing some useful
+       ideas for the compression algorithm; to  Keith  Petersen,  Rich  Wales,
+       Hunter Goatley and Mark Adler for providing a mailing list and ftp site
+       for the Info-ZIP group to use; and most importantly,  to  the  Info-ZIP
+       group  itself  (listed  in the file infozip.who) without whose tireless
+       testing and bug-fixing efforts a portable zip would not have been  pos-
+       sible.   Finally  we should thank (blame) the first Info-ZIP moderator,
+       David Kirschbaum, for getting us into this mess  in  the  first  place.
+       The manual page was rewritten for UNIX by R. P. C. Rodgers.
+
+Info-ZIP                   27 February 2005 (v2.31)                    ZIP(1L)
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..3cd10c3
--- /dev/null
+++ b/README
@@ -0,0 +1,155 @@
+Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+See the accompanying file LICENSE, version 2005-Feb-10 or later
+(the contents of which are also included in zip.h) for terms of use.
+If, for some reason, both of these files are missing, the Info-ZIP license
+also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+
+This is Zip 2.31, a maintenance update for Zip 2.3.  Changes include a
+few bug fixes for Debian and SourceForge bugs, inclusion of the standard
+zip encryption code in the main code, some VMS updates, some changes to
+the Win32 projects, and some other bug fixes.  We are also working on
+the new Zip 3.0 and companion UnZip 6.00 that finally support files and
+archives larger than 4 GB on systems that support large files and include
+other new features.  See the latest betas for details and the new releases
+when available.
+
+Zip 2.31 is a compression and file packaging utility.  It is compatible with
+PKZIP 2.04g (Phil Katz ZIP) for MSDOS systems.  There is a companion to zip
+called unzip (of course) which you should be able to find the same place
+you got zip. See the file 'WHERE' for details on ftp sites and mail
+servers.
+
+This version of zip has been ported to a wide array of Unix and other
+mainframes, minis, and micros including VMS, OS/2, Minix, MSDOS, Windows NT,
+Atari, Amiga, BeOS and VM/CMS. Although highly compatible with PKware's
+PKZIP and PKUNZIP utilities of MSDOS fame, our primary objective has been
+one of portability and other-than-MSDOS functionality.  Features not found
+in the PKWare version include creation of zip files in a pipe or on a
+device, VMS, BeOS and OS/2 extended file attributes, conversion from Unix to
+MSDOS text file format; and, of course, the ability to run on most of your
+favorite operating systems.  And it's free.
+
+See the file WhatsNew for a summary of new features and the file 'CHANGES' for
+a detailed list of all changes.
+
+This version does not support multi-volume archives as in pkzip 2.04g.
+This is currently being looked at and may be provided in the release of
+Zip 3.0 if time permits.
+
+Please read the file INSTALL for information on how to compile and install
+zip, zipsplit, zipcloak, and zipnote.  Please read the file MANUAL for
+information on how to use them.  The file "contents" is a complete list
+of the files you should have in this distribution.  Also, if you are
+using MSDOS, you should read the note on file formats at the end of the
+contents file.  (The contents file somehow got misplaced apparently in
+the Zip 2.3 distribution.  If time permits we will create a new one.)
+
+This version supports standard zip encryption.  The encryption code was
+distributed separately before this version because of US export regulations but
+recent relaxing of export restrictions now allow the code to be included.  Note
+that standard zip encryption is considered weak by today's standards.  We are
+looking at adding strong encryption to a later release.  Decryption can be made
+with unzip 5.0p1 or later, or with zipcloak.
+
+All bug reports should go to zip-bugs using the web form at www.info-zip.org,
+and suggestions for new features can be sent using the same form (although
+we don't promise to use all suggestions).  Contact us to send patches as we
+currently don't have a standard way to do that.  Patches should be sent as
+context diffs only (diff -c).
+
+If you're considering a port, please check in with zip-bugs FIRST,
+since the code is constantly being updated behind the scenes.  We'll
+arrange to give you access to the latest source.
+
+If you'd like to keep up to date with our Zip (and companion UnZip utility)
+development, join the ranks of BETA testers, add your own thoughts and con-
+tributions, etc., send a two-line mail message containing the commands HELP
+and LIST (on separate lines in the body of the message, not on the subject
+line) to mxserver@lists.wku.edu.  You'll receive two messages listing the
+various Info-ZIP mailing-list formats which are available (and also various
+unrelated lists) and instructions on how to subscribe to one or more of them
+(courtesy of Hunter Goatley).  (Currently these are all discontinued but
+we are considering implementing new versions.  However, a discussion
+group for Info-ZIP issues is at http://www.quicktopic.com/27/H/V6ZQZ54uKNL
+and can be used to discuss issues, request features, and is one place new
+betas and releases are announced.)
+
+Frequently asked questions on zip and unzip:
+
+Q. When unzipping I get an error message about "compression method 8".
+
+A. Please get the latest version of unzip. See the file 'WHERE' for details.
+
+
+Q. I can't extract this zip file that I just downloaded. I get
+   "zipfile is part of multi-disk archive" or some other message.
+
+A. Please make sure that you made the transfer in binary mode. Check
+   in particular that your copy has exactly the same size as the original.
+
+
+Q. When running unzip, I get a message about "End-of-central-directory
+   signature not found".
+
+A. This usually means that your zip archive is damaged, or that you
+   have an uncompressed file with the same name in the same directory.
+   In the first case, it makes more sense to contact the person you
+   obtained the zip file from rather than the Info-ZIP software
+   developers, and to make sure that your copy is strictly identical to
+   the original.  In the second case, use "unzip zipfile.zip" instead
+   of "unzip zipfile", to let unzip know which file is the zip archive
+   you want to extract.
+
+
+Q. Why doesn't zip do <something> just like PKZIP does?
+
+A. Zip is not a PKZIP clone and is not intended to be one.  In some
+   cases we feel PKZIP does not do the right thing (e.g., not
+   including pathnames by default); in some cases the operating system
+   itself is responsible (e.g., under Unix it is the shell which
+   expands wildcards, not zip).  Info-ZIP's and PKWARE's zipfiles
+   are interchangeable, not the programs.
+
+   For example, if you are used to the following PKZIP command:
+               pkzip -rP foo *.c
+   you must use instead on Unix:
+               zip -R foo '*.c'
+   (the singled quotes are needed to let the shell know that it should
+    not expand the *.c argument but instead pass it on to the program)
+
+
+Q. Can I distribute zip and unzip sources and/or executables?
+
+A. You may redistribute the latest official distributions without any
+   modification, without even asking us for permission. You can charge
+   for the cost of the media (CDROM, diskettes, etc...) and a small copying
+   fee.  If you want to distribute modified versions please contact us at
+   zip-bugs at www.info-zip.org first. You must not distribute beta versions.
+   The latest official distributions are on ftp.info-zip.org in directory
+   /pub/archiving/zip and subdirectories as well as on mirror sites.
+
+
+Q. Can I use the executables of zip and unzip to distribute my software?
+
+A. Yes, so long as it is made clear in the product documentation that
+   zip or unzip are not being sold, that the source code is freely
+   available, and that there are no extra or hidden charges resulting
+   from its use by or inclusion with the commercial product. Here is
+   an example of a suitable notice:
+
+     NOTE:  <Product> is packaged on this CD using Info-ZIP's compression
+     utility.  The installation program uses UnZip to read zip files from
+     the CD.  Info-ZIP's software (Zip, UnZip and related utilities) is
+     free and can be obtained as source code or executables from various
+     anonymous-ftp sites, including ftp.info-zip.org:/pub/archiving/zip/*.
+
+
+Q. Can I use the source code of zip and unzip in my commercial application?
+
+A. Yes, so long as you include in your product an acknowledgment and an
+   offer of the original compression sources for free or for a small
+   copying fee, and make clear that there are no extra or hidden charges
+   resulting from the use of the compression code by your product. In other
+   words, you are allowed to sell only your own work, not ours. If you have
+   special requirements contact us at zip-bugs at www.info-zip.org.
diff --git a/README.CR b/README.CR
new file mode 100644 (file)
index 0000000..79d4ca7
--- /dev/null
+++ b/README.CR
@@ -0,0 +1,115 @@
+_____________________________________________________________________________
+
+  This is Info-ZIP's README.CR for zcrypt29.zip, last updated 28 February 2005.
+_____________________________________________________________________________
+
+
+The files described below contain the encryption/decryption code for Zip 2.31,
+UnZip 5.52, and WiZ 5.02 (and later).  These files are included in the main
+source for all of these.  This file both describes the history of this package
+and notes the current conditions for use.  Check the comments at the top
+of crypt.c and crypt.h for additional information.
+
+As of version 2.9, this encryption source code is copyrighted by Info-ZIP;
+see the enclosed LICENSE file for details.  Older versions remain in the pub-
+lic domain.  Zcrypt was originally written in Europe and, as of April 2000,
+can be freely distributed from the US as well as other countries.
+
+(The ability to export from the US is new and is due to a change in the Bureau
+of Export Administration's regulations, as published in Volume 65, Number
+10, of the Federal Register [14 January 2000].  Info-ZIP filed the required
+notification via e-mail on 9 April 2000; see the USexport.msg file in this
+archive.  However, as of June 2002, it can now be freely distributed in both
+source and object forms from any country, including the USA under License
+Exception TSU of the U.S. Export Administration Regulations (section 740.13(e))
+of 6 June 2002.)
+
+    LIKE ANYTHING ELSE THAT IS FREE, ZIP, UNZIP AND THEIR ASSOCIATED
+    UTILITIES ARE PROVIDED AS IS AND COME WITH NO WARRANTY OF ANY KIND,
+    EITHER EXPRESSED OR IMPLIED. IN NO EVENT WILL THE AUTHORS BE LIABLE
+    FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE.
+
+The encryption code is a direct transcription of the algorithm from
+Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
+file is distributed with the PKZIP program (even in the version without
+encryption capabilities).  Note that the encryption will probably resist
+attacks by amateurs if the password is well chosen and long enough (at 
+least 8 characters) but it will probably not resist attacks by experts.
+Paul Kocher has made available information concerning a known-plaintext
+attack for the PKWARE encryption scheme; see http://www.cryptography.com/
+for details.)  Short passwords consisting of lowercase letters only can be
+recovered in a few hours on any workstation.  But for casual cryptography
+designed to keep your mother from reading your mail, it's OK.
+
+For more serious encryption, check into PGP (Pretty Good Privacy), a
+public-key-based encryption system available from various Internet sites.
+PGP has Zip and UnZip built into it.  The most recent version at the time
+this was written was 6.5, although older versions are still widespread.
+
+We are looking at adding AES strong encryption to future versions of Zip and
+UnZip.
+
+Zip 2.3x and UnZip 5.5x are compatible with PKZIP 2.04g.  (Thanks to Phil
+Katz for accepting our suggested minor changes to the zipfile format.)
+
+IMPORTANT NOTE:
+
+  Zip archives produced by Zip 2.0 or later must not be *updated* by
+  Zip 1.1 or PKZIP 1.10 or PKZIP 1.93a, if they contain encrypted members
+  or if they have been produced in a pipe or on a non-seekable device.
+  The old versions of Zip or PKZIP would destroy the zip structure.  The
+  old versions can list the contents of the zipfile but cannot extract
+  it anyway (because of the new compression algorithm).  If you do not
+  use encryption and compress regular disk files, you need not worry about
+  this problem.
+
+
+Contents that were distributed and now are part of the main source files:
+
+  file           what it is
+  ----           ----------
+  README.CR      this file
+  LICENSE        Info-ZIP license (terms of reuse and redistribution)
+  USexport.msg   export notice sent to US Bureau of Export Administration
+  WHERE          where Zip/UnZip/WiZ and related utilities can be found
+  crypt.c        code for encryption and decryption
+  crypt.h        code for encryption and decryption
+  file_id.diz    description file for some BBSes
+
+Most all of the files are in Unix (LF only) format.  On MSDOS systems, you
+can use the -a option of UnZip to convert the source files to CRLF
+format.  This is only necessary if you wish to edit the files -- they
+will compile as is with Microsoft C and Turbo/Borland C++ 1.0 or
+later.  However, you will have to convert the files (using "unzip -a")
+to the CRLF format to compile with the older Turbo C 1.0 or 2.0.  You
+should be able to find Zip and UnZip in the same place you found this 
+(see ftp://ftp.info-zip.org/pub/infozip/Info-ZIP.html or the file
+"WHERE" for details).
+
+To update previous versions using the zcrypt sources:
+
+  (1) Get the main sources (e.g., Zip 2.3) and unpack into a working
+      directory, as usual.
+
+  (2) Overwrite the dummy crypt.c and crypt.h from the main sources with 
+      the versions from this package.  If you want to overwrite directly
+      out of the zcrypt29 archive, do not use UnZip's freshen/updating
+      option; the dummy files may be newer than the real sources in
+      zcrypt29.  ("unzip -o zcrypt29 -d /your/working/dir" will do the
+      Right Thing in most cases, although it may overwrite a newer WHERE
+      file under some circumstances.)
+
+  (3) Read the main INSTALL document and compile normally!  No makefile
+      changes are necessary on account of the zcrypt sources.  You can
+      check that the version you just compiled has encryption or decryption
+      support enabled by typing "zip -v" or "unzip -v" and verifying that
+      the last "special compilation option" says encryption or decryption
+      is included.
+
+Encryption enables new "-e" and "-P password" options in Zip, and a new
+"-P password" option in UnZip--see the normal Zip and UnZip documentation
+for details.  (Note that passing a plaintext password on the command line
+is potentially much more insecure than being prompted for it interactively,
+which is the default for UnZip and for Zip with "-e".  Also note that the
+interactive method allows UnZip to deal with archives that use different
+passwords for different files.)
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..a3510a7
--- /dev/null
+++ b/TODO
@@ -0,0 +1,72 @@
+This is old.  See Changes and WhatsNew for what has been implemented.
+
+(See the latest Zip 3.0 beta for an update to this list.)
+
+Main features still missing for next official version:
+
+- use install in unix/Makefile instead of mkdir -p, look at install sh script.
+- #elif for those ports that can handle it.
+- what about zopen vs. fopen ?
+- Add zcreate or zfcreate for win32.
+- Assembler stuff in match.S (subexpressions)
+- zipping huge files (> 2G, unsigned 32bit)
+- Testsuite for zip and unzip (John D. Mitchell)
+- make a version.c or version.h that includes all the compiler names
+- run utils with dmalloc().
+- what to do with zip -F and zip -FF (readzipfile2()) ?
+- profiling of the code
+- multi disk zip files
+- zipfile modification tool (Greg)
+- Implement -- option (Thomas Klauser, wiz@danbala.tuwien.ac.at)
+- don't add files with "Archive bit "
+  or add files with "Archive bit " (uwe.becher@metronet.de)
+- 32 bit file attributes
+- generate output without having to seek at all
+- remove contractions from zip error messages, make them clearer (Steve)
+- display "[text]" for ascii files when not quiet (no -q) (Timo Salmi)
+- does zipnote accept names with version number?
+- for a WORM, zip should create temp file only when updating; new archives
+  should be created directly.
+- APPNOTE.TXT specifies "4) The entries in the central directory may
+  not necessarily be in the same order that files appear in the zipfile"
+  but readzipfile() relies on same order.
+- on Mac, MPW C 3.3.1 requires #if (a || b)  ["#if a || b" taken as "#if a"]
+- on Unix, let -S be "include non-regular files without reading from them"
+  (as pkzip on Unix). This requires unzip support.
+- zip -l should do ebcdic->ascii translation on CMS and MVS
+- zip as subroutine (zdig/241)
+- accept k and M in zipsplit
+- store / (part of file name) as ! in OS/2 (problem only with -E ?)
+
+Known bugs:
+
+- On VMS, zip fails reading some files with "byte record too large for
+  user's buffer". You must use the "-V" option for such files.
+
+- on MSDOS, zip386.exe does not like "zip -bc: foo ..."
+
+- on MSDOS, zip386.exe is sometimes much slower than zip.exe. This is
+  probably a problem with DJGPP (to be investigated).
+
+- on NT with C shell, zip should not do file name expansion again.
+
+- zip zipfile ... ignores existing zipfile if name does not have an extension
+  (except for the -A option, generally used on self-extracting files).
+
+- For an sfx file without extension, "zip -A sfx" works but "zip sfx -A"
+  doesn't.
+
+- When storing files in a zipfile (-0), zip marks all of them as binary.
+
+- On VMS, some indexed files are not restored correctly after zip -V and unzip.
+  (This is now known to be a problem of UnZip. The workaround for Zip 2.2
+  and newer is to use PK-style VMS extra fields; this is now the default.
+  NOTE that UnZip 5.32 has been fixed [971019]!)
+
+- zip and unzip should use the same pattern matching rules, particularly
+  on MSDOS and OS/2. On OS/2, "zip foo *.*" should also match files
+  without extension.
+  Partially DONE (OS/2 "*.*" matches "*".)
+
+- there should be a way to avoid updating archive members (only addition
+  of new files allowed)
diff --git a/USexport.msg b/USexport.msg
new file mode 100644 (file)
index 0000000..068aa9f
--- /dev/null
@@ -0,0 +1,75 @@
+From roelofs (at) sonic.net  Tue Jun 17 08:26:55 2003
+Date: Tue, 17 Jun 2003 08:26:50 -0700
+Message-Id: <200306171526.h5HFQoaw014091 (at) bolt.sonic.net>
+From: Greg Roelofs <newt (at) pobox.com>
+Reply-To: Greg Roelofs <newt (at) pobox.com>
+To: crypt (at) bis.doc.gov, enc (at) ncsc.mil, web_site (at) bis.doc.gov
+Subject: TSU NOTIFICATION - Encryption (Info-ZIP zcrypt.zip)
+Cc: newt (at) pobox.com, zip-bugs (at) lists.wku.edu
+
+
+   SUBMISSION TYPE:       TSU
+   SUBMITTED BY:          Greg Roelofs
+   SUBMITTED FOR:         the Info-ZIP group (an informal, Internet-based
+                          collection of software developers with the contact
+                          address given in next item)
+   POINT OF CONTACT:      Zip-Bugs (at) lists.wku.edu
+   PHONE and/or FAX:      n/a
+   MANUFACTURER:          n/a
+   PRODUCT NAME/MODEL #:  zcrypt
+   ECCN:                  5D002
+
+   NOTIFICATION:
+
+       ftp://ftp.info-zip.org/pub/infozip/src/zcrypt.zip
+
+
+FURTHER COMMENTS:
+
+(1) This notice is being sent in order to ensure that we may legally
+    take advantage of the 6 June 2002 amendment to 740.13 regarding
+    "corresponding object code."  The encryption code in question is
+    unchanged since our original notification of 9 April 2000, appended
+    below and also reproduced within the above zcrypt.zip archive.
+    (Indeed, there has been no change to the core encryption/decryption
+    code in well over five years.)
+
+(2) The (larger) source archives for Zip, UnZip, MacZip, WiZ, and
+    potentially other packages, currently available in the same ftp
+    directory given above, also contain (or may contain) copies of
+    the same zcrypt source code.
+
+(3) ftp.info-zip.org currently points to a site in Germany, so techni-
+    cally it is not involved in "US export" in any direct way.  However,
+    we encourage other sites to "mirror" our software, and some of these
+    mirror sites may be US-based (and therefore involved in reexport of
+    the code in question).  In addition, some Info-ZIP members reside in
+    the US, and www.info-zip.org currently points to a site in Kentucky.
+
+
+ORIGINAL NOTIFICATION:
+
+From roelofs (at) sonic.net  Sun Apr  9 15:11:45 2000
+Date: Sun, 9 Apr 2000 15:11:27 -0700
+Message-Id: <200004092211.PAA20023 (at) sonic.net>
+From: Greg Roelofs <newt (at) pobox.com>
+To: crypt (at) bxa.doc.gov
+Subject: notice of export of unrestricted encryption source code
+Cc: newt (at) pobox.com, zip-bugs (at) lists.wku.edu
+
+The Info-ZIP group, an informal, Internet-based collection of software
+developers with contact address Zip-Bugs (at) lists.wku.edu, hereby notifies
+the US Bureau of Export Administration (BXA) of the posting of freely
+available encryption source code on the Internet under License Exception
+TSU, to commence later today at this location:
+
+       ftp://ftp.info-zip.org/pub/infozip/src/zcrypt.zip
+
+This notification is in accordance with section 740.13(e) of the amended
+Export Administration Regulations, as published in the 14 January 2000
+issue of the Federal Register.
+
+-- 
+Greg Roelofs            newt (at) pobox.com            http://pobox.com/~newt/
+Newtware, PNG Group, Info-ZIP, Philips Research, ...
+
diff --git a/WHATSNEW b/WHATSNEW
new file mode 100644 (file)
index 0000000..a0c1a2d
--- /dev/null
+++ b/WHATSNEW
@@ -0,0 +1,51 @@
+WhatsNew file for Zip 2.31
+
+(See Changes for details)
+
+New things in Zip 2.31
+
+- Crypt now part of source distribution (see Readme.cr)
+- Bug fixes:
+  - Debian patch 001 - Converted quoted strings
+  - Debian patch 002 - Makefile changes
+  - Debian patch 003 - Build changes
+  - Debian patch 004 - Changes to unix/configure
+  - Debian patch 005 - Fix for FNMAX path bug
+- Split VMS -V into -V and -VV (see Manual)
+- New VC6 project files thanks to Cosmin
+- AtheOS port (thanks to Ruslan Nickolaev)
+- Add api.c kluge for zip32.dll to support Visual Basic
+- Binary detection changed from 20% binary to new algorithm
+  that should better detect word processing files as binary
+  and should accept UTF-8 files as text.  This flags the file
+  in the archive as TEXT or BINARY for use by UnZip for line
+  end conversion (see proginfo/txtvsbin.txt)
+- License update
+- DJGPP fixes
+- Many Makefile updates
+- Fixes to ZipSplit, ZipNotes, and ZipCloak
+
+New things in Zip 2.3
+
+- IBM OS/390 port (Unix like, but EBCDIC) by Paul von Behren
+- Apple Macintosh (MACOS) port by Dirk Haase
+- Theos port by Jean-Michel Dubois
+- Multibyte characterset support by Yoshioka Tsuneo
+- Support for ISO 8601 date format with -t and -tt options
+- Info-ZIP license
+
+New things in Zip 2.2
+
+- BEOS port by Chris Herborth
+- QDOS port by Jonathan Hudson
+- TANDEM port by Dave Smith
+- WINDLL port (16-bit Win 3.x and 32-bit WinNT/Win95) by Mike White
+- SYSV packages support by John Bush
+- zip -P SeCrEt encrypts entries in the zip file with password SeCrEt
+  (WARNING: THIS IS INSECURE, use at your own risk)
+- zip -R recurses into subdirectories of current dir like "PKZIP -rP"
+- zip -x@exclude.lst excludes files specified in the file exclude.lst
+- zip -i@include.lst includes files specified in the file include.lst
+- zip -@ only handles one filename per line, but supports whitespace in names
+- zip -t mmddyyyy, 4 digit year number for uniqueness of years beyond 2000
+- zip -tt mmddyyyy only includes files before a specified date
diff --git a/WHERE b/WHERE
new file mode 100644 (file)
index 0000000..c5f6c0b
--- /dev/null
+++ b/WHERE
@@ -0,0 +1,258 @@
+__________________________________________________________________________
+
+   This is the Info-ZIP file ``WHERE,'' last updated on 1 March 2005.
+__________________________________________________________________________
+
+   The latest version of this file can be found online at:
+
+           ftp://ftp.info-zip.org/pub/infozip/doc/WHERE
+
+   Note that some ftp sites may not yet have the latest versions of Zip
+   and UnZip when you read this.  The latest versions always appear in
+   ftp://ftp.info-zip.org/pub/infozip/ (and subdirectories thereof) first,
+   except for encryption binaries, which always appear in
+   ftp://ftp.icce.rug.nl/infozip/ (and subdirectories) first.
+
+   IF YOU FIND AN ERROR:  please let us know!  We don't have time to
+   check each and every site personally (or even collectively), so any
+   number of the sites listed below may have moved or disappeared en-
+   tirely.  E-mail to Zip-Bugs@lists.wku.edu and we'll update this file.
+__________________________________________________________________________
+
+
+Info-ZIP's home WWW site is listed on Yahoo and is at:
+
+   ftp://ftp.info-zip.org/pub/infozip/Info-ZIP.html  (master version)
+   http://ftp.info-zip.org/pub/infozip/              (master version)
+   http://www.info-zip.org/
+
+Note that the old sites at http://www.cdrom.com/pub/infozip/ and
+http://www.freesoftware.com/pub/infozip are PERMANENTLY BROKEN.  They
+cannot be updated or removed, apparently.
+
+The Zip and UnZip pages have links to most known mirror sites carrying our
+source and/or binary distributions, and they generally are more up-to-date
+and have better information than what you are reading:
+
+   ftp://ftp.info-zip.org/pub/infozip/Zip.html
+   ftp://ftp.info-zip.org/pub/infozip/UnZip.html
+
+The related zlib package by Info-ZIP's Jean-loup Gailly and Mark Adler is at:
+
+   http://www.zlib.net/
+
+Source-code archives for Info-ZIP's portable Zip, UnZip, and related
+utilities:
+
+   zip231.zip        Zip 2.31 (deflation; includes zipnote/zipsplit/zipcloak)
+   zip231.tar.Z      ditto, compress'd tar format
+
+   zip11.zip         Zip 1.1 (shrinking, implosion; compatible w. PKUNZIP 1.1)
+   zip11.tar.Z       ditto, compress'd tar format
+
+   unzip552.zip      UnZip 5.52 (all methods[*]; unzip/funzip/unzipsfx/zipgrep)
+   unzip552.tar.gz   ditto, gzip'd tar format
+   unzip552.tar.Z    ditto, compress'd tar format
+
+   unred552.zip      UnZip 5.52 add-on, contains copyrighted unreduce support
+
+   zcrypt29.zip      encryption support for Zip 2.3[**]
+   zcrypt10.zip      encryption support for Zip 1.1
+
+   MacZip106src.zip  contains all the GUI stuff and the project files to build
+                     the MacZip main-app.  To build MacZip successfully, both
+                     the Zip 2.31 and UnZip 5.52 sources are required, too.
+
+   wiz502.zip        WiZ 5.02, Windows 9x/NT GUI front-end for Info-ZIP DLLs
+   wiz502+dlls.zip   WiZ 5.02, Windows 9x/NT GUI front-end plus DLL sources
+
+[*] Unreducing is disabled by default, but is available as add-on.
+    As of July 2004, Unisys's LZW patent was expired worldwide, and
+    unshrinking is turned on by default since the release of UnZip 5.52.
+    See UnZip's INSTALL file for details.
+
+[**] As of January 2000, US export regulations were amended to allow export
+     of free encryption source code from the US.  As of June 2002, these
+     regulations were further relaxed to allow export of encryption binaries
+     associated with free encryption source code.  The Zip 2.31, UnZip 5.52
+     and Wiz 5.02 archives now include full crypto source code.  As of the
+     Zip 2.31 release, all official binaries include encryption support; the
+     former "zcr" archives ceased to exist.
+     (Note that restrictions may still exist in other countries, of course.)
+
+Executables archives (and related files) for Info-ZIP's software; not all
+of these will be immediately available due to lack of access to appropriate
+systems on the part of Info-ZIP members.
+
+   zip231x.zip       MSDOS executables and docs
+   zip231x1.zip      OS/2 1.x (16-bit) executables and docs
+   zip231x2.zip      OS/2 2/3/4.x (32-bit) executables and docs
+   zip231xA.zip      Amiga executables and docs
+   zip231xB.zip      BeOS executables and docs
+   zip231xC.zip      VM/CMS executable and docs
+   zip231xK.zip      Tandem NSK executables and docs
+   zip231xM.xmit     MVS classic executable
+   zip231xM-docs.zip MVS classic port, docs only
+   zip231dN.zip      WinNT/Win9x (Intel) DLL, header files, docs
+   zip231xN.zip      WinNT/Win9x (Intel) executables and docs
+   zip231xN-axp.zip  WinNT (Alpha AXP) executables and docs
+   zip231xN-mip.zip  WinNT (MIPS R4000) executables and docs
+   zip231xN-ppc.zip  WinNT (PowerPC) executables and docs
+   zip231xO.zip      IBM OS/390 Open Edition binaries and docs
+   zip231xQ.zip      SMS/QDOS executables and docs
+   zip231xR.zip      Acorn RISC OS executables and docs
+   zip231xT.zip      Atari TOS executables and docs
+   zip231-vms-axp-obj.zip
+                     VMS (Alpha AXP) object libs, link procedure and docs
+   zip231-vms-axp-exe.zip
+                     VMS (Alpha AXP) executables for VMS 6.1 or later and docs
+   zip231-vms-vax-decc-obj.zip
+                     VMS (VAX) object libs (new DEC C), link procedure and docs
+   zip231-vms-vax-decc-exe.zip
+                     VMS (VAX) executables (DEC C) for VMS 6.1 or later; docs
+   zip231-vms-vax-vaxc-obj.zip
+                     VMS (VAX) object libs (old VAX C), link procedure and docs
+   zip231x.hqx       Macintosh BinHex'd executables and docs
+
+   unz552x.exe       MSDOS self-extracting executable (16-bit unzip, ..., docs)
+   unz552x3.exe      MSDOS self-extracting executable (16-, 32-bit unzip, docs)
+   unz552x1.exe      OS/2 1.x (16-bit) self-extracting executables and docs
+   unz552x2.exe      OS/2 2/3/4.x (32-bit) self-extracting executables and docs
+   unz552d2.zip      OS/2 2/3/4.x (32-bit) DLL, header file, demo exe and docs
+   unz552xA.ami      Amiga self-extracting executables and docs
+   unz552xA.lha      Amiga executables and docs, LHa archive
+   unz552xB.sfx      BeOS self-extracting executables and docs
+   unz552xB.tar.gz   BeOS executables and docs, gzip'd tar archive
+   unz552xC.mod      VM/CMS executable module in "packed" format
+   unz552xC-docs.zip VM/CMS docs, only
+   unz552xF.zip      FlexOS executable and docs
+   unz552xK.zip      Tandem NSK executable and docs
+   unz552xM.xmit     MVS classic executable
+   unz552xM-docs.zip MVS classic port, docs only
+   unz552dN.zip      NT4/W2K/XP/2K3/W9x (32-bit Intel) DLL, header files, docs
+   unz552xN.exe      NT/2K/XP/2K3/W9x self-extracting i386 executables and docs
+   unz552xN-axp.exe  WinNT (Alpha AXP) self-extracting executables and docs
+   unz552xN-mip.exe  WinNT (MIPS R4000) self-extracting executables and docs
+   unz552xN-ppc.exe  WinNT (PowerPC) self-extracting executables and docs
+   unz552xQ.sfx      SMS/QDOS self-extracting executables and docs
+   unz552xO.tar.Z    IBM OS/390 Open edition (Unix-like), exes and docs
+   unz552xR.exe      Acorn RISC OS self-extracting executables and docs
+   unz552xR.spk      Acorn RISC OS Spark'd executables and docs
+   unz552xT.tos      Atari TOS self-extracting executables and docs
+   unz552x-vms-axp-obj.bck    VMS backup saveset,
+                     contains UnZip (Alpha) obj libs, link procedure, docs
+   unz552x-vms-axp-obj.exe    VMS (Alpha AXP) SFX archive (statically linked),
+                     contains UnZip (Alpha) obj libs, link procedure, docs
+   unz552x-vms-axp-exe.exe    VMS (Alpha AXP) SFX archive (dynamically linked),
+                     contains UnZip (Alpha AXP, DEC C) executables and docs,
+                     smaller than object archive, but requires VMS 6.1
+   unz552x-vms-vax-decc-obj.bck   VMS backup saveset,
+                     contains UnZip (new DEC C) obj libs, link procedure, docs
+   unz552x-vms-vax-decc-obj.exe   VMS (VAX) SFX archive (statically linked),
+                     contains UnZip (new DEC C) obj libs, link procedure, docs
+   unz552x-vms-vax-decc-exe.exe   VMS (VAX) SFX archive (dynamically linked),
+                     contains UnZip (new DEC C) executables and docs,
+                     smaller than object archive, but requires VMS 6.1
+   unz552x-vms-vax-vaxc-obj.bck   VMS backup saveset,
+                     contains UnZip (old VAX C) obj libs, link procedure, docs
+   unz552x-vms-vax-vaxc-obj.exe   VMS (VAX) SFX archive (statically linked),
+                     contains UnZip (old VAX C) obj libs, link procedure, docs
+   unz552x.hqx       Macintosh BinHex'd executables and docs for unzip
+  (unz552x.tar.{Z,gz}  Unix exes/docs for Solaris 2.x, SCO Unix, Linux, etc.,
+                     depending on directory/location; generally only provided
+                     in cases where the OS does *not* ship with a bundled C
+                     compiler)
+
+   MacZip106nc.hqx   Macintosh combined Zip&UnZip application with GUI,
+                     executables and docs (no encryption)
+   MacZip106c.hqx    Macintosh combined Zip&UnZip application with GUI,
+                     executables and docs (with encryption)
+
+   wiz502xN.exe      WiZ 5.02 32-bit (Win9x/NT/2K/XP/2K3) app+docs (self-extr.)
+
+   UnzpHist.zip      complete changes-history of UnZip and its precursors
+   ZipHist.zip       complete changes-history of Zip
+
+ftp/web sites for the US-exportable sources and executables:
+
+   NOTE:  Look for the Info-ZIP file names given above (not PKWARE or third-
+   party stuff) in the following locations.  Some sites like to use slightly
+   different names, such as zip-2.31.tar.gz instead of zip231.tar.Z.
+
+   ftp://ftp.info-zip.org/pub/infozip/                 [THE INFO-ZIP HOME SITE]
+   ftp://sunsite.doc.ic.ac.uk/packages/zip/    [MIRRORS THE INFO-ZIP HOME SITE]
+   ftp://unix.hensa.ac.uk/mirrors/uunet/pub/archiving/zip/
+
+   ftp://ftp.cmdl.noaa.gov/aerosol/doc/archiver/{all,dos,os2,mac,vax_alpha}/
+   ftp://garbo.uwasa.fi/pc/arcers/                    [AND OTHER GARBO MIRRORS]
+   ftp://garbo.uwasa.fi/unix/arcers/                  [AND OTHER GARBO MIRRORS]
+   ftp://ftp.elf.stuba.sk/pub/pc/pack/                [AND OTHER STUBA MIRRORS]
+   ftp://ftp-os2.cdrom.com/pub/os2/archiver/
+   ftp://ftp-os2.nmsu.edu/os2/archiver/
+   ftp://ftp.informatik.tu-muenchen.de/pub/comp/os/os2/archiver/
+   ftp://sumex-aim.stanford.edu/info-mac/cmp/
+   ftp://ftp.wustl.edu/pub/aminet/util/arc/          [AND OTHER AMINET MIRRORS]
+   ftp://atari.archive.umich.edu/pub/Archivers/       [AND OTHER UMICH MIRRORS]
+   http://www.umich.edu/~archive/atari/Archivers/
+   ftp://jake.educom.com.au/pub/infozip/acorn/                  [Acorn RISC OS]
+   http://www.sitec.net/maczip/                                   [MacZip port]
+
+ftp/web sites for the encryption and decryption sources and/or executables:
+
+   Outside the US:
+      ftp://ftp.info-zip.org/pub/infozip/   [THE INFO-ZIP HOME SITE]
+      ftp://ftp.icce.rug.nl/infozip/        [THE INFO-ZIP ENCRYPTION HOME SITE]
+      ftp://ftp.elf.stuba.sk/pub/pc/pack/
+      ftp://garbo.uwasa.fi/pc/arcers/
+      ftp://ftp.inria.fr/system/arch-compr/
+      ftp://ftp.leo.org/pub/comp/os/os2/leo/archiver/
+        (mail server at ftp-mailer@ftp.leo.org)
+
+      ftp://ftp.win.tue.nl/pub/compression/zip/
+      ftp://ftp.uni-erlangen.de/pub/pc/msdos/arc-utils/zip/
+
+
+The primary distribution site for the MacZip port can be found at:
+
+   http://www.sitec.net/maczip/
+
+ftp sites for VMS-format Zip and UnZip packages (sources, object files and
+executables, no encryption/decryption--see also "Mail servers" section below):
+
+   ftp.spc.edu [192.107.46.27] and ftp.wku.edu:
+
+   [.MACRO32]AAAREADME.TXT
+   [.MACRO32.SAVESETS]UNZIP.BCK  or  UNZIP.ZIP  (if already have older version)
+   [.MACRO32.SAVESETS]ZIP.ZIP
+
+To find other ftp/web sites:
+
+   The "archie" ftp database utility can be used to find an ftp site near
+   you (although the command-line versions always seem to find old ver-
+   sions...the `FTPsearch' server at http://ftpsearch.ntnu.no/ftpsearch
+   --formerly `Archie 95'--is quite up-to-date, however).  Or check a stan-
+   dard WWW search engine like AltaVista (http://www.altavista.digital.com/)
+   or Yahoo (http://www.yahoo.com/).  If you don't know how to use these,
+   DON'T ASK US--read the web sites' help pages or check the Usenet groups
+   news.announce.newusers or news.answers or some such, or ask your system
+   administrator.
+
+Mail servers:
+
+   To get the encryption sources by e-mail, send the following commands
+   to ftp-mailer@informatik.tu-muenchen.de:
+
+      get /pub/comp/os/os2/archiver/zcrypt29.zip
+      quit
+
+   To get the VMS Zip/UnZip package by e-mail, send the following
+   commands in the body of a mail message to fileserv@wku.edu (the
+   "HELP" command is also accepted):
+
+      SEND FILESERV_TOOLS
+      SEND UNZIP
+      SEND ZIP
+
+   To get Atari executables by e-mail, send a message to
+   atari@atari.archive.umich.edu for information about the mail server.
+__________________________________________________________________________
diff --git a/acorn/GMakefile b/acorn/GMakefile
new file mode 100644 (file)
index 0000000..e9f02bc
--- /dev/null
@@ -0,0 +1,130 @@
+# Makefile for Zip, ZipNote, ZipCloak and ZipSplit
+
+# add -g to CC to debug
+# add -d to BIND to debug
+CC   = gcc -mlibscl
+BIND = $(CC)
+AS   = $(CC) -c
+ASM  = AS
+SQUEEZE = squeeze -v
+E    =
+
+# flags
+#   CFLAGS    flags for C compile
+#   LFLAGS1   flags after output file spec, before obj file list
+#   LFLAGS2   flags after obj file list (libraries, etc)
+#
+LIB      =
+CFLAGS   = -O2 -mthrowback -DASMV
+ASMFLAGS = -throwback -objasm -upper
+LFLAGS1  = 
+LFLAGS2  = $(LIB)
+
+# Uncomment the following line to enable support for Unix
+# Extra Field (Timezone)
+#CFLAGS  = $(CFLAGS) -DUSE_EF_UT_TIME
+
+# object file lists
+OBJZ = o.zip o.zipfile o.zipup o.fileio o.util o.globals o.crc32 o.crctab \
+       o.crypt o.ttyio o.riscos o.acornzip o.swiven
+
+OBJI = o.deflate o.trees
+OBJA = o.match o.sendbits
+OBJU = o.zipfile_ o.fileio_ o.util_ o.globals o.riscos o.acornzip_ o.swiven
+OBJN = o.zipnote  $(OBJU)
+OBJC = o.zipcloak $(OBJU) o.crctab o.crypt_ o.ttyio
+OBJS = o.zipsplit $(OBJU)
+
+ZIP_H = h.zip h.ziperr h.tailor acorn.h.osdep acorn.h.riscos acorn.h.swiven
+
+all:      zip zipnote zipsplit zipcloak
+
+install:  %.zip %.zipnote %.zipsplit %.zipcloak %.acorn.zipsfx \
+          zip zipnote zipsplit zipcloak acorn.zipsfx
+       $(SQUEEZE) zip %.zip
+       $(SQUEEZE) zipnote %.zipnote
+       $(SQUEEZE) zipsplit %.zipsplit
+       $(SQUEEZE) zipcloak %.zipcloak
+       copy acorn.zipsfx %.zipsfx ~CVF
+
+# rules for zip, zipnote, zipcloak and zipsplit
+
+o.api:         c.api
+       $(CC) $(CFLAGS) -c c.api -o o.api
+o.crc32:       c.crc32 $(ZIP_H)
+       $(CC) $(CFLAGS) -c c.crc32 -o o.crc32
+o.crctab:      c.crctab $(ZIP_H)
+       $(CC) $(CFLAGS) -c c.crctab -o o.crctab
+o.crypt:       c.crypt $(ZIP_H) h.crypt h.ttyio
+       $(CC) $(CFLAGS) -c c.crypt -o o.crypt
+o.deflate:     c.deflate $(ZIP_H)
+       $(CC) $(CFLAGS) -c c.deflate -o o.deflate
+o.fileio:      c.fileio $(ZIP_H)
+       $(CC) $(CFLAGS) -c c.fileio -o o.fileio
+o.globals:     c.globals $(ZIP_H)
+       $(CC) $(CFLAGS) -c c.globals -o o.globals
+o.mktime:      c.mktime
+       $(CC) $(CFLAGS) -c c.mktime -o o.mktime
+o.trees:       c.trees $(ZIP_H)
+       $(CC) $(CFLAGS) -c c.trees -o o.trees
+o.ttyio:       c.ttyio $(ZIP_H) h.crypt
+       $(CC) $(CFLAGS) -c c.ttyio -o o.ttyio
+o.util:                c.util $(ZIP_H)
+       $(CC) $(CFLAGS) -c c.util -o o.util
+o.zip:         c.zip $(ZIP_H) h.crypt h.revision h.ttyio
+       $(CC) $(CFLAGS) -c c.zip -o o.zip
+o.zipcloak:    c.zipcloak $(ZIP_H) h.crypt h.revision h.ttyio
+       $(CC) $(CFLAGS) -c c.zipcloak -o o.zipcloak
+o.zipfile:     c.zipfile $(ZIP_H)
+       $(CC) $(CFLAGS) -c c.zipfile -o o.zipfile
+o.zipnote:     c.zipnote $(ZIP_H) h.revision
+       $(CC) $(CFLAGS) -c c.zipnote -o o.zipnote
+o.zipsplit:    c.zipsplit $(ZIP_H) h.revision
+       $(CC) $(CFLAGS) -c c.zipsplit -o o.zipsplit
+o.zipup:       c.zipup $(ZIP_H) h.crypt h.revision
+       $(CC) $(CFLAGS) -c c.zipup -o o.zipup
+
+o.crypt_: c.crypt $(ZIP_H) h.crypt h.ttyio
+       $(CC) $(CFLAGS) -DUTIL -c c.crypt -o o.crypt_
+o.util_: c.util $(ZIP_H)
+       $(CC) $(CFLAGS) -DUTIL -c c.util -o o.util_
+o.fileio_: c.fileio $(ZIP_H)
+       $(CC) $(CFLAGS) -DUTIL -c c.fileio -o o.fileio_
+o.zipfile_: c.zipfile $(ZIP_H)
+       $(CC) $(CFLAGS) -DUTIL -c c.zipfile -o o.zipfile_
+o.acornzip_: acorn.c.acornzip $(ZIP_H)
+       $(CC) $(CFLAGS) -I@ -DUTIL -c acorn.c.acornzip -o o.acornzip_
+
+o.riscos: acorn.c.riscos acorn.h.riscos $(ZIP_H)
+       $(CC) $(CFLAGS) -I@ -c acorn.c.riscos -o o.riscos
+
+o.acornzip: acorn.c.acornzip $(ZIP_H)
+       $(CC) $(CFLAGS) -I@ -c acorn.c.acornzip -o o.acornzip
+
+o.match: acorn.s.match
+       $(ASM) $(ASMFLAGS) -I@ acorn.s.match -o o.match
+
+o.sendbits: acorn.s.sendbits
+       $(ASM) $(ASMFLAGS) -I@ acorn.s.sendbits -o o.sendbits
+
+o.swiven: acorn.s.swiven
+       $(ASM) $(ASMFLAGS) -I@ acorn.s.swiven -o o.swiven
+
+zip:   $(OBJZ) $(OBJI) $(OBJA)
+       $(BIND) -o zip$(E) $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)
+zipnote:  $(OBJN)
+       $(BIND) -o zipnote$(E) $(LFLAGS1) $(OBJN) $(LFLAGS2)
+zipcloak: $(OBJC)
+       $(BIND) -o zipcloak$(E) $(LFLAGS1) $(OBJC) $(LFLAGS2)
+zipsplit: $(OBJS)
+       $(BIND) -o zipsplit$(E) $(LFLAGS1) $(OBJS) $(LFLAGS2)
+
+clean: 
+       remove zip
+       remove zipcloak 
+       remove zipsplit
+       remove zipnote
+       create o.!fake! 0
+       wipe o.* ~cf
+
+# end of Makefile
diff --git a/acorn/ReadMe b/acorn/ReadMe
new file mode 100644 (file)
index 0000000..41c37a5
--- /dev/null
@@ -0,0 +1,85 @@
+Acorn-specific compile instructions
+-----------------------------------
+
+Use the "RunMe1st" file (it is an Obey file) to convert all the files from
+"filename/[chs]" to "[chs].filename" (so that zip could be easily compiled
+under RISC OS). It will also set the correct makefile.
+
+To compile just set the CSD to the main zip directory and run 'amu'.
+
+Currently only the Acorn C V5 compiler has been tested but probably also
+Acorn C V4 and the Acorn Assembler V2 will be able to compile zip.
+
+The default makefile is configured without the support for the
+Extended Timestamp Extra Field. If you wan to enable it you have to
+add "-DUSE_EF_UT_TIME" to CFLAGS (see makefile). Without the Extended
+Timestamp Field support, zipfiles created by zip are identical to the
+zipfiles created by SparkFS. However, the Extended Timestamp Field can
+be useful if you are going to unzip your zipfiles on a non-RISC OS machine
+since the correct time stamp will be preserved across different timezones.
+Note that in this case, both the SparkFS Extra Field and the Extended
+Timestamp Extra Field will be used, so the zipfiles will still be fully
+compatible with SparkFS and with the RISC OS version of unzip.
+
+The executables-only distributions will be compiled without the support for
+the Extended Timestamp Extra Field. If you need it but you can't compile zip
+yourself, you can contact the authors at the Info-ZIP address who will do it
+for you.
+
+
+Acorn-specific usage instructions
+---------------------------------
+
+An extra option ('I') has been added to the Acorn port: if it is specified
+zip will not consider Image files (eg. DOS partitions or Spark archives when
+SparkFS is loaded) as directories but will store them as single files. This
+means that if you have, say, SparkFS loaded, zipping a Spark archive will
+result in a zipfile containing a directory (and its content) while using the
+'I' option will result in a zipfile containing a Spark archive. Obviously
+this second case will also be obtained (without the 'I' option) if SparkFS
+isn't loaded.
+
+When adding files to a zipfile; to maintain FileCore compliance, all
+files named "file/ext" will be added to the archive as "file.ext".
+This presents no problem if you wish to use unzip to extract them on any
+other machine, as the files are correctly named. This also presents no
+problem if you use unzip for RISC OS, as the files are converted back to
+"file/ext" format. The only problem appears when you use SparkFS to
+decompress the files, as a file called "file.ext" will be extracted as
+"file_ext", not what it was added as. You must be careful about this.
+
+Case Specific. Depending on how you type the command, files will be added
+exactly as named; in this example:
+*zip new/zip newfile
+*zip new/zip NewFile
+*zip new/zip NEWFILE
+will create an archive containing 3 copies of the same Risc OS file 'newfile'
+called 'newfile', 'NewFile' and 'NEWFILE'. Please be careful.
+
+The Acorn port conserves file attributes, including filetype, so if you
+zip on an Acorn, and unzip on another Acorn, filetypes will be maintained
+precisely as if you used uncompressed files. If you de-archive on another
+machine (PC, Mac, Unix etc..), filetypes will be ignored, but the files
+will be identical despite this. This feature is fully compatible with
+SparkFS, so zipfiles created by zip will be correctly uncompressed (including
+filetype, etc.) by SparkFS.
+
+An additional feature went into this port to cope better with C-code
+and extensions. This allows the acorn files "c.foo" to be added to the
+archive as "foo/c", eventually appearing in the archive as "foo.c", allowing
+for better handling of C or C++ code. Example:
+*Set Zip$Exts "dir1:dir2:dir3"
+*zip new/zip dir1.file
+*zip new/zip dir2.help
+*zip new/zip dir3.textfile
+Creates a zipfile new/zip, with entries file.dir1, help.dir2, textfile.dir3.
+The usual settings for Zip$Exts are "h:o:s:c", allowing C code to be added
+to the archive in standard form.
+
+A final note about the Acorn port regards the use of the 'n' option: this is
+used to specify a list of suffixes that will not be compressed (eg. .ZIP,
+since it is already a compressed file). Since RISC OS uses filetypes instead
+of suffixes, this list of suffixes is actually considered as a list of
+filetypes (3 hex digit format). By default, zip doesn't compress filetypes
+DDC (Archive, Spark or Zip), D96 (CFS files) and 68E (PackDir).
+
diff --git a/acorn/ReadMe.GMakefile b/acorn/ReadMe.GMakefile
new file mode 100644 (file)
index 0000000..714fe2d
--- /dev/null
@@ -0,0 +1,14 @@
+GMakefile is for use with Acorn RISC OS and the forthcoming
+post-Acorn RISC OS for the compilation of both the current release and
+development versions of zip.
+
+It is recommended that you use gcc 2.95.4 or higher and you will need a 
+suitable 'make' utility. Both are available from 
+<URL:http://hard-mofo.dsvr.net/gcc/>.
+
+You will need the files gcc.zip and cc1.zip for the C compiler with the
+documentation available in the gccdoc.zip archive. GNU make can be 
+found in the utils.zip archive, although most versions of 'make' should be
+fine.
+
+When using gcc, check RunMe1st for two lines which need uncommenting.
diff --git a/acorn/RunMe1st b/acorn/RunMe1st
new file mode 100644 (file)
index 0000000..a330adb
--- /dev/null
@@ -0,0 +1,23 @@
+| This Obey file prepares the zip port for a Desktop C re-compile.
+| Run it and it will copy all the needed files into the correct
+| place.
+
+| Set the correct type of 'srcrename' so that the only requirement
+| for the user is to set 'RunMe1st' to Obey
+SetType <Obey$Dir>.srcrename FF8
+
+| Run 'srcrename' on the main zip directory with recursion enabled
+/<Obey$Dir>.srcrename -r -e c:h:s:o <Obey$Dir>.^
+
+| Create the 'o' directory
+CDir <Obey$Dir>.^.o
+
+| Put the Makefile in its correct place and set the correct filetype
+Copy <Obey$Dir>.makefile <Obey$Dir>.^.makefile ~C ~V F
+
+| Uncomment the following lines if you're using gcc
+|| Put the Makefile in its correct place and set the correct filetype
+|Copy <Obey$Dir>.GMakefile <Obey$Dir>.^.makefile ~C~VF
+
+SetType <Obey$Dir>.^.makefile FE1
+SetType <Obey$Dir>.zipsfx Obey
diff --git a/acorn/acornzip.c b/acorn/acornzip.c
new file mode 100644 (file)
index 0000000..8de308c
--- /dev/null
@@ -0,0 +1,593 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, all these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include <stdlib.h>
+#include <string.h>
+#include "zip.h"
+
+#ifndef UTIL
+
+#define PAD 0
+#define PATH_END '/'
+
+
+local int wild_recurse(char *whole, char *wildtail);
+local int uxtime2acornftime(unsigned *pexadr, unsigned *pldadr, time_t ut);
+
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+char *readd(DIR *d)
+/* Return a pointer to the next name in the directory stream d, or NULL if
+   no more entries or an error occurs. */
+{
+   struct dirent *e;
+
+   e = readdir(d);
+   return (e == NULL ? (char *) NULL : e->d_name);
+}
+
+/* What we have here is a mostly-generic routine using opend()/readd() and */
+/* isshexp()/MATCH() to find all the files matching a multi-part filespec  */
+/* using the portable pattern syntax.  It shouldn't take too much fiddling */
+/* to make it usable for any other platform that has directory hierarchies */
+/* but no shell-level pattern matching.  It works for patterns throughout  */
+/* the pathname, such as "foo:*.?/source/x*.[ch]".                         */
+
+/* whole is a pathname with wildcards, wildtail points somewhere in the  */
+/* middle of it.  All wildcards to be expanded must come AFTER wildtail. */
+
+local int wild_recurse(whole, wildtail) char *whole; char *wildtail;
+{
+    DIR *dir;
+    char *subwild, *name, *newwhole = NULL, *glue = NULL, plug = 0, plug2;
+    ush newlen, amatch = 0;
+    struct stat statb;
+    int disk_not_mounted=0;
+    int e = ZE_MISS;
+
+    if (!isshexp(wildtail)) {
+        if (stat(whole,&statb)==0 && (statb.st_mode & S_IREAD)!=0) {
+            return procname(whole, 0);
+        } else
+            return ZE_MISS;                     /* woops, no wildcards! */
+    }
+
+    /* back up thru path components till existing dir found */
+    do {
+        name = wildtail + strlen(wildtail) - 1;
+        for (;;)
+            if (name-- <= wildtail || *name == '.') {
+                subwild = name + 1;
+                plug2 = *subwild;
+                *subwild = 0;
+                break;
+            }
+        if (glue)
+            *glue = plug;
+        glue = subwild;
+        plug = plug2;
+        dir = opendir(whole);
+    } while (!dir && !disk_not_mounted && subwild > wildtail);
+    wildtail = subwild;                 /* skip past non-wild components */
+
+    if ((subwild = strchr(wildtail + 1, '.')) != NULL) {
+        /* this "+ 1" dodges the   ^^^ hole left by *glue == 0 */
+        *(subwild++) = 0;               /* wildtail = one component pattern */
+        newlen = strlen(whole) + strlen(subwild) + 32;
+    } else
+        newlen = strlen(whole) + 31;
+    if (!dir || !(newwhole = malloc(newlen))) {
+        if (glue)
+            *glue = plug;
+        e = dir ? ZE_MEM : ZE_MISS;
+        goto ohforgetit;
+    }
+    strcpy(newwhole, whole);
+    newlen = strlen(newwhole);
+    if (glue)
+        *glue = plug;                           /* repair damage to whole */
+    if (!isshexp(wildtail)) {
+        e = ZE_MISS;                            /* non-wild name not found */
+        goto ohforgetit;
+    }
+
+    while (name = readd(dir)) {
+        if (MATCH(wildtail, name, 0)) {
+            strcpy(newwhole + newlen, name);
+            if (subwild) {
+                name = newwhole + strlen(newwhole);
+                *(name++) = '.';
+                strcpy(name, subwild);
+                e = wild_recurse(newwhole, name);
+            } else
+                e = procname(newwhole, 0);
+            newwhole[newlen] = 0;
+            if (e == ZE_OK)
+                amatch = 1;
+            else if (e != ZE_MISS)
+                break;
+        }
+    }
+
+  ohforgetit:
+    if (dir) closedir(dir);
+    if (subwild) *--subwild = '.';
+    if (newwhole) free(newwhole);
+    if (e == ZE_MISS && amatch)
+        e = ZE_OK;
+    return e;
+}
+
+int wild(p)
+char *p;
+{
+  char *path;
+  int toret;
+
+  /* special handling of stdin request */
+  if (strcmp(p, "-") == 0)   /* if compressing stdin */
+    return newname(p, 0, 0);
+
+  path=p;
+  if (strchr(p, ':')==NULL && *p!='@') {
+    if (!(path=malloc(strlen(p)+3))) {
+      return ZE_MEM;
+    }
+    strcpy(path,"@.");
+    strcat(path,p);
+  }
+
+  toret=wild_recurse(path, path);
+
+  if (path!=p) {
+    free(path);
+  }
+  return toret;
+}
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  char *a;              /* path and name for recursion */
+  DIR *d;               /* directory stream from opendir() */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (LSSTAT(n, &s))
+  {
+    /* Not a file or directory--search for shell expression in zip file */
+    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+  if ((s.st_mode & S_IFDIR) == 0)
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  } else {
+    /* Add trailing / to the directory name */
+    if ((p = malloc(strlen(n)+2)) == NULL)
+      return ZE_MEM;
+    if (strcmp(n, ".") == 0) {
+      *p = '\0';  /* avoid "./" prefix and do not create zip entry */
+    } else {
+      strcpy(p, n);
+      a = p + strlen(p);
+      if (a[-1] != '.')
+        strcpy(a, ".");
+      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+        free((zvoid *)p);
+        return m;
+      }
+    }
+    /* recurse into directory */
+    if (recurse && (d = opendir(n)) != NULL)
+    {
+      while ((e = readd(d)) != NULL) {
+        if (strcmp(e, ".") && strcmp(e, ".."))
+        {
+          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+          {
+            closedir(d);
+            free((zvoid *)p);
+            return ZE_MEM;
+          }
+          strcat(strcpy(a, p), e);
+          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
+          {
+            if (m == ZE_MISS)
+              zipwarn("name not matched: ", a);
+            else
+              ziperr(m, a);
+          }
+          free((zvoid *)a);
+        }
+      }
+      closedir(d);
+    }
+    free((zvoid *)p);
+  } /* (s.st_mode & S_IFDIR) == 0) */
+  return ZE_OK;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t;              /* shortened name */
+  char *tmp;
+  int dosflag;
+  char *lastlastdir=NULL;   /* pointer to 2 dirs before... */
+  char *lastdir=NULL;       /* pointer to last dir... */
+
+  /* Malloc space for internal name and copy it */
+  if ((tmp = malloc(strlen(x) + 1)) == NULL)
+    return NULL;
+  strcpy(tmp, x);
+
+  dosflag = dosify; /* default for non-DOS and non-OS/2 */
+
+  /* Find starting point in name before doing malloc */
+  for(t=tmp;*t;t++) {
+    if (*t=='/') {
+      *t='.';
+    }
+    else if (*t=='.') {
+      *t='/';
+      lastlastdir=lastdir;
+      lastdir=t+1;
+    }
+  }
+
+  t=strchr(tmp,'$');      /* skip FS name */
+  if (t!=NULL)
+    t+=2;                 /* skip '.' after '$' */
+  else
+    t=tmp;
+  if (*t=='@')            /* skip @. at the beginning of filenames */
+    t+=2;
+
+  /* Make changes, if any, to the copied name (leave original intact) */
+
+  /* return a pointer to '\0' if the file is a directory with the same
+     same name as an extension to swap (eg. 'c', 'h', etc.) */
+  if (isdir && exts2swap!=NULL) {
+    if (lastlastdir==NULL)
+      lastlastdir=t;
+    if (checkext(lastlastdir)) {
+      free((void *)tmp);
+      n=malloc(1);
+      if (n!=NULL)
+        *n='\0';
+      return n;
+    }
+  }
+
+  if (exts2swap!=NULL && lastdir!=NULL) {
+    if (lastlastdir==NULL)
+      lastlastdir=t;
+    if (checkext(lastlastdir)) {
+      if (swapext(lastlastdir,lastdir-1)) {
+        free((void *)tmp);
+        return NULL;
+      }
+    }
+  }
+
+  if (!pathput)
+    t = last(t, PATH_END);
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL) {
+    free((void *)tmp);
+    return NULL;
+  }
+  strcpy(n, t);
+
+  free((void *)tmp);
+
+  if (dosify)
+    msname(n);
+
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+  return n;
+}
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+  char *t;              /* scans name */
+  char *lastext=NULL;   /* pointer to last extension */
+  char *lastdir=NULL;   /* pointer to last dir */
+
+  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+    return NULL;
+  strcpy(x, n);
+
+  for(t=x;*t;t++) {
+    if (*t=='.') {
+      *t='/';
+      lastext=t+1;
+    }
+    else if (*t=='/') {
+      *t='.';
+      lastdir=t+1;
+    }
+  }
+
+  if (exts2swap!=NULL && (int)lastext>(int)lastdir) {
+    if (lastdir==NULL)
+      lastdir=x;
+    if (checkext(lastext)) {
+      if (swapext(lastdir,lastext-1)) {
+        free((void *)x);
+        return NULL;
+      }
+    }
+  }
+
+  return x;
+}
+
+local int uxtime2acornftime(unsigned *pexadr, unsigned *pldadr, time_t ut)
+{
+  unsigned timlo;       /* 3 lower bytes of acorn file-time plus carry byte */
+  unsigned timhi;       /* 2 high bytes of acorn file-time */
+
+  timlo = ((unsigned)ut & 0x00ffffffU) * 100 + 0x00996a00U;
+  timhi = ((unsigned)ut >> 24);
+  timhi = timhi * 100 + 0x0000336eU + (timlo >> 24);
+  if (timhi & 0xffff0000U)
+      return 1;         /* calculation overflow, do not change time */
+
+  /* insert the five time bytes into loadaddr and execaddr variables */
+  *pexadr = (timlo & 0x00ffffffU) | ((timhi & 0x000000ffU) << 24);
+  *pldadr = (*pldadr & 0xffffff00U) | ((timhi >> 8) & 0x000000ffU);
+
+  return 0;             /* subject to future extension to signal overflow */
+}
+
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+  time_t m_time;
+  unsigned int loadaddr, execaddr;
+  int attr;
+
+  /* Convert DOS time to time_t format in m_time */
+  m_time = dos2unixtime(d);
+
+  /* set the file's modification time */
+  SWI_OS_File_5(f,NULL,&loadaddr,NULL,NULL,&attr);
+
+  if (uxtime2acornftime(&execaddr, &loadaddr, m_time) != 0)
+      return;
+
+  SWI_OS_File_1(f,loadaddr,execaddr,attr);
+}
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  char *name;
+  unsigned int len = strlen(f);
+
+  if (f == label) {
+    if (a != NULL)
+      *a = label_mode;
+    if (n != NULL)
+      *n = -2L; /* convention for a label name */
+    if (t != NULL)
+      t->atime = t->mtime = t->ctime = label_utim;
+    return label_time;
+  }
+
+  if ((name = malloc(len + 1)) == NULL) {
+    ZIPERR(ZE_MEM, "filetime");
+  }
+  strcpy(name, f);
+  if (name[len - 1] == '.')
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+
+  if (strcmp(f, "-") == 0) {
+  /* forge stat values for stdin since Amiga and RISCOS have no fstat() */
+    s.st_mode = (S_IREAD|S_IWRITE|S_IFREG);
+    s.st_size = -1;
+    s.st_mtime = time(&s.st_mtime);
+  } else if (LSSTAT(name, &s) != 0) {
+             /* Accept about any file kind including directories
+              * (stored with trailing / with -r option)
+              */
+    free(name);
+    return 0;
+  }
+
+  if (a != NULL) {
+    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
+    if ((s.st_mode & S_IFDIR) != 0) {
+      *a |= MSDOS_DIR_ATTR;
+    }
+  }
+  if (n != NULL)
+    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = s.st_ctime;
+  }
+
+  free(name);
+
+  return unix2dostime((time_t *) &s.st_mtime);
+}
+
+int set_extra_field(z, z_utim)
+        struct zlist far *z;
+        iztimes *z_utim;
+{
+#ifdef USE_EF_UT_TIME
+  char *eb_ptr;
+#endif /* USE_EF_UT_TIME */
+  char *name;
+  extra_block *block;
+
+#define EB_SPARK_LEN    20
+#define EB_SPARK_SIZE (EB_HEADSIZE+EB_SPARK_LEN)
+#ifdef USE_EF_UT_TIME
+# ifdef IZ_CHECK_TZ
+#  define EB_UTTIME_SIZE (zp_tz_is_valid ? EB_HEADSIZE+EB_UT_LEN(1) : 0)
+# else
+#  define EB_UTTIME_SIZE (EB_HEADSIZE+EB_UT_LEN(1))
+# endif
+#else
+#  define EB_UTTIME_SIZE 0
+#endif
+#define EF_SPARK_TOTALSIZE (EB_SPARK_SIZE + EB_UTTIME_SIZE)
+
+  if ((name=(char *)malloc(strlen(z->name)+1))==NULL) {
+    fprintf(stderr," set_extra_field: not enough memory for directory name\n");
+    return ZE_MEM;
+  }
+
+  strcpy(name,z->name);
+
+  if (name[strlen(name)-1]=='.') {  /* remove the last '.' in directory names */
+    name[strlen(name)-1]=0;
+  }
+
+  z->extra=(char *)malloc(EF_SPARK_TOTALSIZE);
+  if (z->extra==NULL) {
+    fprintf(stderr," set_extra_field: not enough memory\n");
+    free(name);
+    return ZE_MEM;
+  }
+  z->cextra = z->extra;
+  z->cext = z->ext = EF_SPARK_TOTALSIZE;
+
+  block=(extra_block *)z->extra;
+  block->ID=SPARKID;
+  block->size=EB_SPARK_LEN;
+  block->ID_2=SPARKID_2;
+  block->zero=0;
+
+  if (SWI_OS_File_5(name,NULL,&block->loadaddr,&block->execaddr,
+                    NULL,&block->attr) != NULL) {
+    fprintf(stderr," OS error while set_extra_field of %s\n",name);
+  }
+
+  free(name);
+
+#ifdef USE_EF_UT_TIME
+# ifdef IZ_CHECK_TZ
+  if (zp_tz_is_valid) {
+# endif
+    eb_ptr = z->extra + EB_SPARK_SIZE;
+
+    eb_ptr[0]  = 'U';
+    eb_ptr[1]  = 'T';
+    eb_ptr[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */
+    eb_ptr[3]  = 0;
+    eb_ptr[4]  = EB_UT_FL_MTIME;
+    eb_ptr[5]  = (char)(z_utim->mtime);
+    eb_ptr[6]  = (char)(z_utim->mtime >> 8);
+    eb_ptr[7]  = (char)(z_utim->mtime >> 16);
+    eb_ptr[8]  = (char)(z_utim->mtime >> 24);
+# ifdef IZ_CHECK_TZ
+  }
+# endif
+#endif /* USE_EF_UT_TIME */
+
+  return ZE_OK;
+}
+
+#endif /* !UTIL */
+
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+void version_local()
+{
+    static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
+
+    printf(CompiledWith,
+#ifdef __GNUC__
+      "gcc ", __VERSION__,
+#else
+#  ifdef __CC_NORCROFT
+      "Norcroft ", "cc",
+#  else
+      "cc", "",
+#  endif
+#endif
+
+      "RISC OS",
+
+      " (Acorn Computers Ltd)",
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+      );
+
+} /* end function version_local() */
diff --git a/acorn/makefile b/acorn/makefile
new file mode 100644 (file)
index 0000000..5aa1c5c
--- /dev/null
@@ -0,0 +1,111 @@
+# Makefile for Zip, ZipNote, ZipCloak and ZipSplit
+
+# add -g to CC to debug
+# add -d to BIND to debug
+CC   = cc
+BIND = link
+AS   = $(CC) -c
+ASM  = objasm
+SQUEEZE = squeeze -v
+E    =
+
+# flags
+#   CFLAGS    flags for C compile
+#   LFLAGS1   flags after output file spec, before obj file list
+#   LFLAGS2   flags after obj file list (libraries, etc)
+#
+LIB      =
+CBASE    = -throwback -wn -DASMV -apcs 3/26
+CFLAGS   = $(CBASE) -IC:,@.
+ASMFLAGS = -Throwback -Stamp -NoCache -CloseExec -quit -apcs 3/26
+LFLAGS1  =
+LFLAGS2  = $(LIB) C:o.Stubs
+
+# Uncomment the following line to enable support for Unix
+# Extra Field (Timezone)
+#CFLAGS  = $(CFLAGS) -DUSE_EF_UT_TIME
+
+# object file lists
+OBJZ = zip.o zipfile.o zipup.o fileio.o util.o globals.o crc32.o crctab.o \
+       crypt.o ttyio.o riscos.o acornzip.o swiven.o
+
+OBJI = deflate.o trees.o
+OBJA = match.o sendbits.o
+OBJU = zipfile_.o fileio_.o util_.o globals.o riscos.o acornzip_.o swiven.o
+OBJN = zipnote.o  $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt_.o ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h acorn/osdep.h acorn/riscos.h acorn/swiven.h
+
+all:      zip zipnote zipsplit zipcloak
+
+
+install:  %.zip %.zipnote %.zipsplit %.zipcloak %.zipsfx \
+          zip zipnote zipsplit zipcloak zipsfx
+        $(SQUEEZE) zip %.zip
+        $(SQUEEZE) zipnote %.zipnote
+        $(SQUEEZE) zipsplit %.zipsplit
+        $(SQUEEZE) zipcloak %.zipcloak
+        copy acorn.zipsfx %.zipsfx ~CVF
+
+# suffix rules
+.SUFFIXES:      _.o .o .c
+.c_.o:
+        $(CC) $(CFLAGS) -DUTIL -c $*.c -o $*_.o
+.c.o:
+        $(CC) $(CFLAGS) -c $<
+.s.o:
+        $(ASM) $(ASMFLAGS) -from @*.s -to @*.o
+
+# rules for zip, zipnote, zipcloak and zipsplit
+$(OBJZ): $(ZIP_H)
+$(OBJI): $(ZIP_H)
+$(OBJN): $(ZIP_H)
+$(OBJS): $(ZIP_H)
+$(OBJC): $(ZIP_H)
+zip.o zipup.o crypt.o ttyio.o zipcloak.o crypt_.o: crypt.h
+zip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h
+zip.o crypt.o ttyio.o zipcloak.o crypt_.o: ttyio.h
+
+crypt_.o: crypt.c
+        $(CC) $(CFLAGS) -DUTIL -c c.crypt -o o.crypt_
+util_.o: util.c
+        $(CC) $(CFLAGS) -DUTIL -c c.util -o o.util_
+fileio_.o: fileio.c
+        $(CC) $(CFLAGS) -DUTIL -c c.fileio -o o.fileio_
+zipfile_.o: zipfile.c
+        $(CC) $(CFLAGS) -DUTIL -c c.zipfile -o o.zipfile_
+acornzip_.o: acorn/acornzip.c $(ZIP_H)
+        $(CC) $(CFLAGS) -DUTIL -c acorn/acornzip.c -o o.acornzip_
+
+riscos.o: acorn/riscos.c acorn/riscos.h
+        $(CC) $(CFLAGS) -c acorn/riscos.c
+
+acornzip.o: acorn/acornzip.c $(ZIP_H)
+        $(CC) $(CFLAGS) -c acorn/acornzip.c
+
+match.o: acorn/match.s
+        $(ASM) $(ASMFLAGS) -from acorn.s.match -to o.match
+
+sendbits.o: acorn/sendbits.s
+        $(ASM) $(ASMFLAGS) -from acorn.s.sendbits -to o.sendbits
+
+swiven.o: acorn/swiven.s
+        $(ASM) $(ASMFLAGS) -from acorn.s.swiven -to o.swiven
+
+zip:      $(OBJZ) $(OBJI) $(OBJA)
+          $(BIND) -o zip$(E) $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)
+zipnote:  $(OBJN)
+          $(BIND) -o zipnote$(E) $(LFLAGS1) $(OBJN) $(LFLAGS2)
+zipcloak: $(OBJC)
+          $(BIND) -o zipcloak$(E) $(LFLAGS1) $(OBJC) $(LFLAGS2)
+zipsplit: $(OBJS)
+          $(BIND) -o zipsplit$(E) $(LFLAGS1) $(OBJS) $(LFLAGS2)
+
+clean:  ;remove zip; remove zipcloak;
+        remove zipsplit; remove zipnote;
+        create o.!fake! 0
+        wipe o.* ~cf
+
+# end of Makefile
diff --git a/acorn/match.s b/acorn/match.s
new file mode 100644 (file)
index 0000000..ee68ce6
--- /dev/null
@@ -0,0 +1,217 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; match.s for ARM by Sergio Monesi.
+
+r0 RN 0
+r1 RN 1
+r2 RN 2
+r3 RN 3
+r4 RN 4
+r5 RN 5
+r6 RN 6
+r7 RN 7
+r8 RN 8
+r9 RN 9
+sl RN 10
+fp RN 11
+ip RN 12
+sp RN 13
+lr RN 14
+pc RN 15
+
+MAX_DIST   EQU  32506
+WMASK      EQU  32767
+MAX_MATCH  EQU  258
+
+                AREA    |C$$code|, CODE, READONLY
+
+
+; r1 = chain_lenght
+; r2 = scan
+; r3 = match
+; r4 = len (tmp)
+; r5 = best_len
+; r6 = limit
+; r7 = strend
+; r8 = scan_end1
+; r9 = scan_end
+; lr = window
+; fp = prev
+
+|__max_chain_length|
+        IMPORT  max_chain_length
+        DCD     max_chain_length
+|__window|
+        IMPORT  window
+        DCD     window
+|__prev|
+        IMPORT  prev
+        DCD     prev
+|__prev_length|
+        IMPORT  prev_length
+        DCD     prev_length
+|__strstart|
+        IMPORT  strstart
+        DCD     strstart
+|__good_match|
+        IMPORT  good_match
+        DCD     good_match
+|__nice_match|
+        IMPORT  nice_match
+        DCD     nice_match
+|__match_start|
+        IMPORT  match_start
+        DCD     match_start
+
+        DCB     "longest_match"
+        DCB     &00,&00,&00
+        DCD     &ff000010
+
+        EXPORT  longest_match
+longest_match
+        STMFD   sp!, {r4-r9,fp,lr}
+
+        LDR     fp, [pc, #|__prev|-.-8]
+
+        LDR     r1, [pc, #|__max_chain_length|-.-8]
+        LDR     r1, [r1]
+        LDR     lr, [pc, #|__window|-.-8]
+
+        LDR     ip, [pc, #|__strstart|-.-8]
+        LDR     ip, [ip]
+        ADD     r2, lr, ip
+        LDR     r5, [pc, #|__prev_length|-.-8]
+        LDR     r5, [r5]
+        SUBS    ip, ip, #MAX_DIST-250       ; if r6 > MAX_DIST
+        SUBCSS  r6, ip, #250                ; r6 = r6 - MAXDIST
+        MOVLS   r6, #0                      ; else r6 = 0
+
+        ADD     r7, r2, #MAX_MATCH-256
+        ADD     r7, r7, #256                ; r7 = r2 + MAX_MATCH (=258);
+
+        SUB     ip, r5, #1
+        LDRB    r8, [r2, ip]
+        LDRB    r9, [r2, r5]
+
+        LDR     ip, [pc, #|__good_match|-.-8]
+        LDR     ip, [ip]
+        CMP     r5, ip
+        MOVCS   r1, r1, LSR #2
+
+cycle
+        ADD     r3, lr, r0
+
+        LDRB    ip, [r3, r5]
+        CMP     ip, r9
+        BNE     cycle_end
+
+        SUB     ip, r5, #1
+        LDRB    ip, [r3, ip]
+        CMP     ip, r8
+        BNE     cycle_end
+
+        LDRB    ip, [r2]
+        LDRB    r4, [r3]
+        CMP     ip, r4
+        BNE     cycle_end
+
+        LDRB    ip, [r3, #1]
+        LDRB    r4, [r2, #1]
+        CMP     ip, r4
+        BNE     cycle_end
+
+        ADD     r2, r2, #2
+        ADD     r3, r3, #2
+
+inn_cycle
+        LDRB    ip, [r2, #1]!
+        LDRB    r4, [r3, #1]!
+        CMP     ip, r4
+        BNE     exit_inn_cycle
+
+        LDRB    ip, [r2, #1]!
+        LDRB    r4, [r3, #1]!
+        CMP     ip, r4
+        BNE     exit_inn_cycle
+
+        LDRB    ip, [r2, #1]!
+        LDRB    r4, [r3, #1]!
+        CMP     ip, r4
+        BNE     exit_inn_cycle
+
+        LDRB    ip, [r2, #1]!
+        LDRB    r4, [r3, #1]!
+        CMP     ip, r4
+        BNE     exit_inn_cycle
+
+        LDRB    ip, [r2, #1]!
+        LDRB    r4, [r3, #1]!
+        CMP     ip, r4
+        BNE     exit_inn_cycle
+
+        LDRB    ip, [r2, #1]!
+        LDRB    r4, [r3, #1]!
+        CMP     ip, r4
+        BNE     exit_inn_cycle
+
+        LDRB    ip, [r2, #1]!
+        LDRB    r4, [r3, #1]!
+        CMP     ip, r4
+        BNE     exit_inn_cycle
+
+        LDRB    ip, [r2, #1]!
+        LDRB    r4, [r3, #1]!
+        CMP     ip, r4
+        BNE     exit_inn_cycle
+
+        CMP     r2, r7
+        BCC     inn_cycle
+
+exit_inn_cycle
+        SUB     r4, r2, r7               ; len = MAX_MATCH - (int)(strend - scan);
+        ADD     r4, r4, #MAX_MATCH-256
+        ADD     r4, r4, #256
+
+        SUB     r2, r2, r4               ; scan = strend - MAX_MATCH
+
+        CMP     r4, r5                   ; if (len > best_len) {
+        BLE     cycle_end
+
+        LDR     ip, [pc, #|__match_start|-.-8]  ; match_start = cur_match;
+        STR     r0, [ip]
+        MOV     r5, r4                          ; best_len = len;
+
+        LDR     ip, [pc, #|__nice_match|-.-8]   ; if (len >= nice_match)
+        LDR     ip, [ip]
+        CMP     r4, ip
+        BGE     exit_match                      ;   break;
+
+        SUB     ip, r5, #1                      ; scan_end1  = scan[best_len-1];
+        LDRB    r8, [r2, ip]
+        LDRB    r9, [r2, r5]                    ; scan_end   = scan[best_len];
+
+cycle_end
+        MOV     ip, r0, LSL #17          ; cur_match & WMASK
+        MOV     ip, ip, LSR #17
+
+        LDR     r0, [fp, ip, ASL #1]     ; cur_match = prev[cur_match & WMASK]
+        MOV     r0, r0, ASL #16
+        MOV     r0, r0, LSR #16
+
+        CMP     r0, r6                  ; cur_match > limit
+        BLS     exit_match
+        SUBS    r1, r1, #1              ; --chain_length
+        BNE     cycle                   ; chain_length != 0
+
+exit_match
+        MOV     r0, r5
+
+        LDMFD   sp!, {r4-r9,fp,pc}^
+
+        END
diff --git a/acorn/osdep.h b/acorn/osdep.h
new file mode 100644 (file)
index 0000000..ea002ef
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, all these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include "riscos.h"
+
+#define RISCOS
+#define NO_SYMLINK
+#define NO_FCNTL_H
+#define NO_UNISTD_H
+#define NO_MKTEMP
+
+#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \
+                     procname(n, 1))
+
+#define isatty(a) 1
+#define fseek(f,o,t) riscos_fseek((f),(o),(t))
+
+#define localtime riscos_localtime
+#define gmtime riscos_gmtime
+
+#ifdef ZCRYPT_INTERNAL
+#  define ZCR_SEED2     (unsigned)3141592654L   /* use PI as seed pattern */
+#endif
diff --git a/acorn/riscos.c b/acorn/riscos.c
new file mode 100644 (file)
index 0000000..eb1b897
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, all these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* riscos.c */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "zip.h"
+#include "riscos.h"
+
+#define MAXEXT 256
+
+/* External globals */
+extern int scanimage;
+
+/* Local globals (!?!?) */
+char *exts2swap = NULL; /* Extensions to swap (actually, directory names) */
+
+int stat(char *filename,struct stat *res)
+{
+ int attr;              /* object attributes */
+ unsigned int load;     /* load address */
+ unsigned int exec;     /* exec address */
+ int type;              /* type: 0 not found, 1 file, 2 dir, 3 image */
+
+ if (!res)
+   return -1;
+
+ if (SWI_OS_File_5(filename,&type,&load,&exec,(int *)&res->st_size,&attr)!=NULL)
+   return -1;
+
+ if (type==0)
+   return -1;
+
+ res->st_dev=0;
+ res->st_ino=0;
+ res->st_nlink=0;
+ res->st_uid=1;
+ res->st_gid=1;
+ res->st_rdev=0;
+ res->st_blksize=1024;
+
+ res->st_mode = ((attr & 0001) << 8) | ((attr & 0002) << 6) |
+                ((attr & 0020) >> 2) | ((attr & 0040) >> 4);
+
+ switch (type) {
+   case 1:                        /* File */
+    res->st_mode |= S_IFREG;
+    break;
+   case 2:                        /* Directory */
+    res->st_mode |= S_IFDIR | 0700;
+    break;
+   case 3:                        /* Image file */
+    if (scanimage)
+      res->st_mode |= S_IFDIR | 0700;
+    else
+      res->st_mode |= S_IFREG;
+    break;
+ }
+
+ if ((((unsigned int) load) >> 20) == 0xfff) {     /* date stamped file */
+   unsigned int t1, t2, tc;
+
+   t1 = (unsigned int) (exec);
+   t2 = (unsigned int) (load & 0xff);
+
+   tc = 0x6e996a00U;
+   if (t1 < tc)
+     t2--;
+   t1 -= tc;
+   t2 -= 0x33;          /* 00:00:00 Jan. 1 1970 = 0x336e996a00 */
+
+   t1 = (t1 / 100) + (t2 * 42949673U);  /* 0x100000000 / 100 = 42949672.96 */
+   t1 -= (t2 / 25);             /* compensate for .04 error */
+
+   res->st_atime = res->st_mtime = res->st_ctime = t1;
+ }
+ else
+   res->st_atime = res->st_mtime = res->st_ctime = 0;
+
+ return 0;
+}
+
+#ifndef SFX
+
+DIR *opendir(char *dirname)
+{
+ DIR *thisdir;
+ int type;
+ int attr;
+ os_error *er;
+
+ thisdir=(DIR *)malloc(sizeof(DIR));
+ if (thisdir==NULL)
+   return NULL;
+
+ thisdir->dirname=(char *)malloc(strlen(dirname)+1);
+ if (thisdir->dirname==NULL) {
+   free(thisdir);
+   return NULL;
+ }
+
+ strcpy(thisdir->dirname,dirname);
+ if (thisdir->dirname[strlen(thisdir->dirname)-1]=='.')
+   thisdir->dirname[strlen(thisdir->dirname)-1]=0;
+
+ if (er=SWI_OS_File_5(thisdir->dirname,&type,NULL,NULL,NULL,&attr),er!=NULL ||
+     type<=1 || (type==3 && !scanimage))
+ {
+   free(thisdir->dirname);
+   free(thisdir);
+   return NULL;
+ }
+
+ thisdir->buf=malloc(DIR_BUFSIZE);
+ if (thisdir->buf==NULL) {
+   free(thisdir->dirname);
+   free(thisdir);
+   return NULL;
+ }
+
+ thisdir->size=DIR_BUFSIZE;
+ thisdir->offset=0;
+ thisdir->read=0;
+
+ return thisdir;
+}
+
+struct dirent *readdir(DIR *d)
+{
+ static struct dirent dent;
+
+ if (d->read==0) {    /* no more objects read in the buffer */
+   if (d->offset==-1) {    /* no more objects to read */
+     return NULL;
+   }
+
+   d->read=255;
+   if (SWI_OS_GBPB_9(d->dirname,d->buf,&d->read,&d->offset,DIR_BUFSIZE,NULL)!=NULL)
+     return NULL;
+
+   if (d->read==0) {
+     d->offset=-1;
+     return NULL;
+   }
+   d->read--;
+   d->act=(char *)d->buf;
+ }
+ else {     /* some object is ready in buffer */
+   d->read--;
+   d->act=(char *)(d->act+strlen(d->act)+1);
+ }
+
+ strcpy(dent.d_name,d->act);
+ dent.d_namlen=strlen(dent.d_name);
+
+ return &dent;
+}
+
+void closedir(DIR *d)
+{
+ if (d->buf!=NULL)
+   free(d->buf);
+ if (d->dirname!=NULL)
+   free(d->dirname);
+ free(d);
+}
+
+int unlink(f)
+char *f;                /* file to delete */
+/* Delete the file *f, returning non-zero on failure. */
+{
+ os_error *er;
+ char canon[256];
+ int size=255;
+
+ er=SWI_OS_FSControl_37(f,canon,&size);
+ if (er==NULL) {
+   er=SWI_OS_FSControl_27(canon,0x100);
+ }
+ else {
+   er=SWI_OS_FSControl_27(f,0x100);
+ }
+ return (int)er;
+}
+
+int deletedir(char *d)
+{
+ int objtype;
+ char *s;
+ int len;
+ os_error *er;
+
+ len = strlen(d);
+ if ((s = malloc(len + 1)) == NULL)
+   return -1;
+
+ strcpy(s,d);
+ if (s[len-1]=='.')
+   s[len-1]=0;
+
+ if (er=SWI_OS_File_5(s,&objtype,NULL,NULL,NULL,NULL),er!=NULL) {
+   free(s);
+   return -1;
+ }
+ if (objtype<2 || (!scanimage && objtype==3)) {
+   /* this is a file or it doesn't exist */
+   free(s);
+   return -1;
+ }
+
+ if (er=SWI_OS_File_6(s),er!=NULL) {
+   /* maybe this is a problem with the DDEUtils module, try to canonicalise the path */
+   char canon[256];
+   int size=255;
+
+   if (er=SWI_OS_FSControl_37(s,canon,&size),er!=NULL) {
+     free(s);
+     return -1;
+   }
+   if (er=SWI_OS_File_6(canon),er!=NULL) {
+     free(s);
+     return -1;
+   }
+ }
+ free(s);
+ return 0;
+}
+
+#endif /* !SFX */
+
+int chmod(char *file, int mode)
+{
+/*************** NOT YET IMPLEMENTED!!!!!! ******************/
+/* I don't know if this will be needed or not... */
+ file=file;
+ mode=mode;
+ return 0;
+}
+
+void setfiletype(char *fname,int ftype)
+{
+ char str[256];
+ sprintf(str,"SetType %s &%3.3X",fname,ftype);
+ SWI_OS_CLI(str);
+}
+
+void getRISCOSexts(char *envstr)
+{
+ char *envptr;                               /* value returned by getenv */
+
+ envptr = getenv(envstr);
+ if (envptr == NULL || *envptr == 0) return;
+
+ exts2swap=malloc(1+strlen(envptr));
+ if (exts2swap == NULL)
+   return;
+
+ strcpy(exts2swap, envptr);
+}
+
+int checkext(char *suff)
+{
+ register char *extptr=exts2swap;
+ register char *suffptr;
+ register int e,s;
+
+ if (extptr != NULL) while(*extptr) {
+   suffptr=suff;
+   e=*extptr; s=*suffptr;
+   while (e && e!=':' && s && s!='.' && s!='/' && e==s) {
+     e=*++extptr; s=*++suffptr;
+   }
+   if (e==':') e=0;
+   if (s=='.' || s=='/') s=0;
+   if (!e && !s) {
+     return 1;
+   }
+   while(*extptr!=':' && *extptr!='\0')    /* skip to next extension */
+     extptr++;
+   if (*extptr!='\0')
+     extptr++;
+ }
+ return 0;
+}
+
+int swapext(char *name, char *exptr)
+{
+ char *ext;
+ char *p1=exptr;
+ char *p2;
+ int extchar=*exptr;
+ unsigned int i=0;
+
+ while(*++p1 && *p1!='.' && *p1!='/')
+   ;
+ ext=malloc(i=p1-exptr);
+ if (!ext)
+   return 1;
+ memcpy(ext, exptr+1, i);
+ p2=exptr-1;
+ p1=exptr+i-1;
+ while(p2 >= name)
+   *p1--=*p2--;
+ strcpy(name,ext);
+ *p1=(extchar=='/'?'.':'/');
+ free(ext);
+ return 0;
+}
+
+void remove_prefix(void)
+{
+ SWI_DDEUtils_Prefix(NULL);
+}
+
+void set_prefix(void)
+{
+ char *pref;
+ int size=0;
+
+ if (SWI_OS_FSControl_37("@",pref,&size)!=NULL)
+   return;
+
+ size=1-size;
+
+ if (pref=malloc(size),pref!=NULL) {
+   if (SWI_OS_FSControl_37("@",pref,&size)!=NULL) {
+     free(pref);
+     return;
+   }
+
+   if (SWI_DDEUtils_Prefix(pref)==NULL) {
+     atexit(remove_prefix);
+   }
+
+   free(pref);
+ }
+}
+
+#ifdef localtime
+#  undef localtime
+#endif
+
+#ifdef gmtime
+#  undef gmtime
+#endif
+
+/* Acorn's implementation of localtime() and gmtime()
+ * doesn't consider the timezone offset, so we have to
+ * add it before calling the library functions
+ */
+
+struct tm *riscos_localtime(const time_t *timer)
+{
+ time_t localt=*timer;
+
+ localt+=SWI_Read_Timezone()/100;
+
+ return localtime(&localt);
+}
+
+struct tm *riscos_gmtime(const time_t *timer)
+{
+ time_t localt=*timer;
+
+ localt+=SWI_Read_Timezone()/100;
+
+ return gmtime(&localt);
+}
+
+
+int riscos_fseek(FILE *fd, long offset, int whence)
+{
+  int ret;
+  switch (whence)
+  {
+    case SEEK_END:
+      ret = (fseek) (fd, 0, SEEK_END);
+      if (ret)
+        return ret;
+      /* fall through */
+    case SEEK_CUR:
+      offset += ftell (fd);
+      /* fall through */
+    default: /* SEEK_SET */
+      return (fseek) (fd, offset < 0 ? 0 : offset, SEEK_SET);
+  }
+}
diff --git a/acorn/riscos.h b/acorn/riscos.h
new file mode 100644 (file)
index 0000000..2bbd72e
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.htmlse.html
+*/
+/* riscos.h */
+
+#ifndef __riscos_h
+#define __riscos_h
+
+#include <time.h>
+#include <stdio.h>
+
+typedef struct {
+  int errnum;
+  char errmess[252];
+} os_error;
+
+#ifndef __swiven_h
+#  include "swiven.h"
+#endif
+
+#define MAXPATHLEN 256
+#define MAXFILENAMELEN 64  /* should be 11 for ADFS, 13 for DOS, 64 seems a sensible value... */
+#define DIR_BUFSIZE 1024   /* this should be enough to read a whole E-Format directory */
+
+struct stat {
+  unsigned int st_dev;
+  int st_ino;
+  unsigned int st_mode;
+  int st_nlink;
+  unsigned short st_uid;
+  unsigned short st_gid;
+  unsigned int st_rdev;
+  unsigned int st_size;
+  unsigned int st_blksize;
+  time_t st_atime;
+  time_t st_mtime;
+  time_t st_ctime;
+};
+
+typedef struct {
+  char *dirname;
+  void *buf;
+  int size;
+  char *act;
+  int offset;
+  int read;
+} DIR;
+
+#define dstrm DIR
+
+struct dirent {
+  unsigned int d_off;          /* offset of next disk directory entry */
+  int d_fileno;                /* file number of entry */
+  size_t d_reclen;             /* length of this record */
+  size_t d_namlen;             /* length of d_name */
+  char d_name[MAXFILENAMELEN]; /* name */
+};
+
+typedef struct {
+  unsigned int load_addr;
+  unsigned int exec_addr;
+  int lenght;
+  int attrib;
+  int objtype;
+  char name[13];
+} riscos_direntry;
+
+#define SPARKID   0x4341        /* = "AC" */
+#define SPARKID_2 0x30435241    /* = "ARC0" */
+
+typedef struct {
+  short         ID;
+  short         size;
+  int           ID_2;
+  unsigned int  loadaddr;
+  unsigned int  execaddr;
+  int           attr;
+  int           zero;
+} extra_block;
+
+
+#define S_IFMT  0770000
+
+#define S_IFDIR 0040000
+#define S_IFREG 0100000  /* 0200000 in UnixLib !?!?!?!? */
+
+#ifndef S_IEXEC
+#  define S_IEXEC  0000100
+#  define S_IWRITE 0000200
+#  define S_IREAD  0000400
+#endif
+
+extern char *exts2swap; /* Extensions to swap */
+
+int stat(char *filename,struct stat *res);
+DIR *opendir(char *dirname);
+struct dirent *readdir(DIR *d);
+char *readd(DIR *d);
+void closedir(DIR *d);
+int unlink(char *f);
+int chmod(char *file, int mode);
+void setfiletype(char *fname,int ftype);
+void getRISCOSexts(char *envstr);
+int checkext(char *suff);
+int swapext(char *name, char *exptr);
+void remove_prefix(void);
+void set_prefix(void);
+struct tm *riscos_localtime(const time_t *timer);
+struct tm *riscos_gmtime(const time_t *timer);
+
+int riscos_fseek(FILE *fd, long offset, int whence);
+/* work around broken assumption that fseek() is OK with -ve file offsets */
+
+#endif /* !__riscos_h */
diff --git a/acorn/sendbits.s b/acorn/sendbits.s
new file mode 100644 (file)
index 0000000..f12921a
--- /dev/null
@@ -0,0 +1,105 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; sendbits.s for ARM by Sergio Monesi and Darren Salt.
+
+r0      RN      0
+r1      RN      1
+r2      RN      2
+r3      RN      3
+r4      RN      4
+r5      RN      5
+r6      RN      6
+r7      RN      7
+r8      RN      8
+r9      RN      9
+sl      RN      10
+fp      RN      11
+ip      RN      12
+sp      RN      13
+lr      RN      14
+pc      RN      15
+
+        AREA    |Asm$$Code|, CODE, READONLY
+
+        =       "send_bits",0
+        ALIGN
+        &       &FF00000C
+
+        IMPORT  __rt_stkovf_split_small
+        IMPORT  flush_outbuf
+
+        IMPORT  bi_valid
+        IMPORT  bi_buf
+        IMPORT  out_size
+        IMPORT  out_offset
+        IMPORT  out_buf
+
+        EXPORT  send_bits
+send_bits
+        MOV     ip,sp
+        STMDB   sp!,{r4,r5,fp,ip,lr,pc}
+        SUB     fp,ip,#4
+        LDR     r5,=bi_buf
+        LDR     r3,=bi_valid
+        LDR     r4,[r5]
+        LDR     r2,[r3]
+        ORR     r4,r4,r0,LSL r2 ; |= value<<bi_valid
+        ADD     r2,r2,r1        ; += length
+        CMP     r2,#&10
+        STRLE   r2,[r3]         ; short? store & return
+        STRLE   r4,[r5]
+        LDMLEDB fp,{r4,r5,fp,sp,pc}^
+
+        SUB     r2,r2,#&10      ; adjust bi_valid, bi_buf
+        MOV     ip,r4,LSR #16   ;  (done early, keeping the old bi_buf
+        STR     r2,[r3]         ;  in R4 for later storage)
+        STR     ip,[r5]
+
+        LDR     r0,=out_size
+        LDR     r1,=out_offset
+        LDR     r0,[r0]
+        LDR     r2,[r1]
+        SUB     r0,r0,#1
+        CMP     r2,r0           ; if out_offset >= out_size-1
+        LDRHS   r0,=out_buf
+        LDRHS   r0,[r0]
+        BLHS    flush_outbuf    ; then flush the buffer
+        LDR     r0,=out_buf
+        LDR     r1,=out_offset
+        LDR     r0,[r0]
+        LDR     r2,[r1]
+        MOV     r5,r4,LSR #8
+        STRB    r4,[r0,r2]!     ; store 'old' bi_buf
+        STRB    r5,[r0,#1]
+        ADD     r2,r2,#2
+        STR     r2,[r1]
+
+        LDMDB   fp,{r4,r5,fp,sp,pc}^
+
+
+ptr_bi          &       bi_valid
+                &       bi_buf
+
+
+        =       "bi_reverse",0
+        ALIGN
+        &       &FF00000C
+
+        EXPORT  bi_reverse
+bi_reverse
+        MOV     r2,#0
+loop    MOVS    r0,r0,LSR #1
+        ADCS    r2,r2,r2
+        SUBS    r1,r1,#1
+        BNE     loop
+        MOV     r0,r2
+        MOVS    pc,lr
+
+
+        END
diff --git a/acorn/srcrename b/acorn/srcrename
new file mode 100644 (file)
index 0000000..7bd6119
Binary files /dev/null and b/acorn/srcrename differ
diff --git a/acorn/swiven.h b/acorn/swiven.h
new file mode 100644 (file)
index 0000000..c860d7d
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/* swiven.h */
+
+#ifndef __swiven_h
+#define __swiven_h
+
+os_error *SWI_OS_FSControl_26(char *source, char *dest, int actionmask);
+/* copy */
+
+os_error *SWI_OS_FSControl_27(char *filename, int actionmask);
+/* wipe */
+
+os_error *SWI_OS_GBPB_9(char *dirname, void *buf, int *number,
+                        int *offset, int size, char *match);
+/* read dir */
+
+os_error *SWI_OS_File_1(char *filename, unsigned int loadaddr,
+                        unsigned int execaddr, int attrib);
+/* write file attributes */
+
+os_error *SWI_OS_File_5(char *filename, int *objtype, unsigned int *loadaddr,
+                        unsigned int *execaddr, int *length, int *attrib);
+/* read file info */
+
+os_error *SWI_OS_File_6(char *filename);
+/* delete */
+
+os_error *SWI_OS_File_7(char *filename, int loadaddr, int execaddr, int size);
+/* create an empty file */
+
+os_error *SWI_OS_CLI(char *cmd);
+/* execute a command */
+
+int SWI_OS_ReadC(void);
+/* get a key from the keyboard buffer */
+
+os_error *SWI_OS_ReadVarVal(char *var, char *buf, int len, int *bytesused);
+/* reads an OS varibale */
+
+os_error *SWI_OS_FSControl_54(char *buffer, int dir, char *fsname, int *size);
+/* reads the path of a specified directory */
+
+os_error *SWI_OS_FSControl_37(char *pathname, char *buffer, int *size);
+/* canonicalise path */
+
+os_error *SWI_DDEUtils_Prefix(char *dir);
+/* sets the 'prefix' directory */
+
+int SWI_Read_Timezone(void);
+/* returns the timezone offset (centiseconds) */
+
+#endif /* !__swiven_h */
diff --git a/acorn/swiven.s b/acorn/swiven.s
new file mode 100644 (file)
index 0000000..1630124
--- /dev/null
@@ -0,0 +1,276 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; SWI veneers used by Zip/Unzip
+;
+
+r0              RN      0
+r1              RN      1
+r2              RN      2
+r3              RN      3
+r4              RN      4
+r5              RN      5
+r6              RN      6
+r7              RN      7
+r8              RN      8
+r9              RN      9
+r10             RN      10
+r11             RN      11
+r12             RN      12
+sp              RN      13
+lr              RN      14
+pc              RN      15
+
+sl              RN      10
+fp              RN      11
+ip              RN      12
+
+
+XOS_Bit                         EQU &020000
+
+OS_GBPB                         EQU &00000C
+OS_File                         EQU &000008
+OS_FSControl                    EQU &000029
+OS_CLI                          EQU &000005
+OS_ReadC                        EQU &000004
+OS_ReadVarVal                   EQU &000023
+DDEUtils_Prefix                 EQU &042580
+Territory_ReadCurrentTimeZone   EQU &043048
+
+        MACRO
+        STARTCODE $name
+        EXPORT $name
+$name
+        MEND
+
+
+                AREA    |C$$code|, CODE, READONLY
+
+; os_error *SWI_OS_FSControl_26(char *source, char *dest, int actionmask);
+
+        STARTCODE SWI_OS_FSControl_26
+
+        MOV     ip, lr
+
+        MOV     r3, r2
+        MOV     r2, r1
+        MOV     r1, r0
+        MOV     r0, #26
+
+        SWI     OS_FSControl + XOS_Bit
+
+        MOVVC   r0, #0
+
+        MOVS    pc, ip
+
+
+; os_error *SWI_OS_FSControl_27(char *filename, int actionmask);
+
+        STARTCODE SWI_OS_FSControl_27
+
+        MOV     ip, lr
+
+        MOV     r3, r1
+        MOV     r1, r0
+        MOV     r0, #27
+
+        SWI     OS_FSControl + XOS_Bit
+
+        MOVVC   r0, #0
+
+        MOVS    pc, ip
+
+
+; os_error *SWI_OS_GBPB_9(char *dirname, void *buf, int *number,
+;                         int *offset, int size, char *match);
+
+        STARTCODE SWI_OS_GBPB_9
+
+        MOV     ip, sp
+        STMFD   sp!, {r2-r6,lr}
+        LDMIA   ip, {r5,r6}
+        LDR     r4, [r3]
+        LDR     r3, [r2]
+        MOV     r2, r1
+        MOV     r1, r0
+        MOV     r0, #9
+        SWI     OS_GBPB + XOS_Bit
+        LDMVSFD sp!, {r2-r6,pc}^
+        MOV     r0, #0
+        LDMFD   sp, {r5,r6}
+        STR     r3, [r5]
+        STR     r4, [r6]
+        LDMFD   sp!, {r2-r6,pc}^
+
+
+; os_error *SWI_OS_File_1(char *filename, int loadaddr, int execaddr, int attrib);
+
+        STARTCODE SWI_OS_File_1
+
+        STMFD   sp!, {r5,lr}
+        MOV     r5, r3
+        MOV     r3, r2
+        MOV     r2, r1
+        MOV     r1, r0
+        MOV     r0, #1
+        SWI     OS_File + XOS_Bit
+        MOVVC   r0, #0
+        LDMFD   sp!, {r5,pc}^
+
+
+
+; os_error *SWI_OS_File_5(char *filename, int *objtype, int *loadaddr,
+;                         int *execaddr, int *length, int *attrib);
+
+        STARTCODE SWI_OS_File_5
+
+        STMFD   sp!, {r1-r5,lr}
+        MOV     r1, r0
+        MOV     r0, #5
+        SWI     OS_File + XOS_Bit
+        LDMVSFD sp!, {r1-r5,pc}^
+        LDR     lr, [sp]
+        TEQ     lr, #0
+        STRNE   r0, [lr]
+        LDR     lr, [sp, #4]
+        TEQ     lr ,#0
+        STRNE   r2, [lr]
+        LDR     lr, [sp, #8]
+        TEQ     lr, #0
+        STRNE   r3, [lr]
+        LDR     lr, [sp ,#24]
+        TEQ     lr, #0
+        STRNE   r4, [lr]
+        LDR     lr, [sp ,#28]
+        TEQ     lr, #0
+        STRNE   r5, [lr]
+        MOV     r0, #0
+        LDMFD   sp!, {r1-r5,pc}^
+
+
+; os_error *SWI_OS_File_6(char *filename);
+
+        STARTCODE SWI_OS_File_6
+
+        STMFD   sp!, {r4-r5,lr}
+        MOV     r1, r0
+        MOV     r0, #6
+        SWI     OS_File + XOS_Bit
+        MOVVC   r0, #0
+        LDMFD   sp!, {r4-r5,pc}^
+
+
+; os_error *SWI_OS_File_7(char *filename, int loadaddr, int execaddr, int size);
+
+        STARTCODE SWI_OS_File_7
+
+        STMFD   sp!, {r4-r5,lr}
+        MOV     r5, r3
+        MOV     r4, #0
+        MOV     r3, r2
+        MOV     r2, r1
+        MOV     r1, r0
+        MOV     r0, #7
+        SWI     OS_File + XOS_Bit
+        MOVVC   r0, #0
+        LDMFD   sp!, {r4-r5,pc}^
+
+
+; os_error *SWI_OS_CLI(char *cmd);
+
+        STARTCODE SWI_OS_CLI
+
+        MOV     ip, lr
+        SWI     OS_CLI + XOS_Bit
+        MOVVC   r0, #0
+        MOVS    pc, ip
+
+
+; int SWI_OS_ReadC(void);
+
+        STARTCODE SWI_OS_ReadC
+
+        MOV     ip, lr
+        SWI     OS_ReadC + XOS_Bit
+        MOVS    pc, ip
+
+
+; os_error *SWI_OS_ReadVarVal(char *var, char *buf, int len, int *bytesused);
+
+        STARTCODE SWI_OS_ReadVarVal
+
+        STMFD   sp!, {r4,lr}
+        MOV     ip, r3
+        MOV     r3, #0
+        MOV     r4, #0
+        SWI     OS_ReadVarVal + XOS_Bit
+        LDMVSFD sp!, {r4,pc}^
+        TEQ     ip, #0
+        STRNE   r2, [ip]
+        MOV     r0, #0
+        LDMFD   sp!, {r4,pc}^
+
+
+; os_error *SWI_OS_FSControl_54(char *buffer, int dir, char *fsname, int *size);
+
+        STARTCODE SWI_OS_FSControl_54
+
+        STMFD   sp!, {r3-r6,lr}
+        LDR     r5, [r3]
+        MOV     r3, r2
+        MOV     r2, r1
+        MOV     r1, r0
+        MOV     r0, #54
+        SWI     OS_FSControl + XOS_Bit
+        LDMVSFD sp!, {r3-r6,pc}^
+        MOV     r0, #0
+        LDMFD   sp!, {r3}
+        STR     r5, [r3]
+        LDMFD   sp!, {r4-r6,pc}^
+
+
+; os_error *SWI_OS_FSControl_37(char *pathname, char *buffer, int *size);
+
+        STARTCODE SWI_OS_FSControl_37
+
+        STMFD   sp!, {r2,r3-r5,lr}
+        LDR     r5, [r2]
+        MOV     r3, #0
+        MOV     r4, #0
+        MOV     r2, r1
+        MOV     r1, r0
+        MOV     r0, #37
+        SWI     OS_FSControl + XOS_Bit
+        LDMVSFD sp!, {r2,r3-r5,pc}^
+        MOV     r0, #0
+        LDMFD   sp!, {r2}
+        STR     r5, [r2]
+        LDMFD   sp!, {r3-r5,pc}^
+
+
+; os_error *SWI_DDEUtils_Prefix(char *dir);
+
+        STARTCODE SWI_DDEUtils_Prefix
+
+        MOV     ip, lr
+        SWI     DDEUtils_Prefix + XOS_Bit
+        MOVVC   r0, #0
+        MOVS    pc, ip
+
+; int SWI_Read_Timezone(void);
+
+        STARTCODE SWI_Read_Timezone
+
+        MOV     ip, lr
+        SWI     Territory_ReadCurrentTimeZone + XOS_Bit
+        MOVVC   r0, r1
+        MOVVS   r0, #0
+        MOVS    pc, ip
+
+
+        END
diff --git a/acorn/zipup.h b/acorn/zipup.h
new file mode 100644 (file)
index 0000000..47c3536
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#define fhow "r"
+#define fbad (NULL)
+typedef FILE *ftype;
+#define zopen(n,p) fopen(n,p)
+#define zread(f,b,n) fread((b),1,(n),(FILE*)(f))
+#define zclose(f) fclose(f)
+#define zerr(f) (k==(extent)(-1L))
+#define zstdin 0
diff --git a/amiga/LMKfile b/amiga/LMKfile
new file mode 100644 (file)
index 0000000..6b6aa40
--- /dev/null
@@ -0,0 +1,116 @@
+# Makefile for Zip, ZipNote, ZipCloak and ZipSplit, Amiga SAS/C 5.10b
+# See the master Makefile under the top level Zip/Unzip source directory
+# for more information on compiler macros and flags for this version.
+# Last update: Jun 25, 1998
+# -John Bush, <J.Bush@MD-B.Prime.COM>, <JBush@BIX.COM>
+
+
+#######################
+# MACROBE DEFINITIONS #
+#######################
+
+# Compiler and loader debug flags.  Omit comments as req'd.
+# Do not set when building production version.
+# CDBG = -d3
+# LDBG = ADDSYM
+
+DEFINES = -DNO_MKTEMP
+CC = lc
+OPT = -O
+CFLAGS = $(OPT) $(DEFINES) $(CDBG) -v -mat -cuisf -b0 -j85i86i87i100i
+
+LD = blink
+LDSTART = LIB:c.o
+LDFLAGS = LIB LIB:lc.lib+LIB:amiga.lib
+
+TMPFILE = ram:MakeZip.tmp
+
+###############################################
+# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES #
+###############################################
+
+# default C rules
+.c.o:
+        $(CC) $(CFLAGS) -o$@ $*.c
+
+# Alternate rules for routines containing entries needed by utilities
+.c.oo:
+        $(CC) $(CFLAGS) -DUTIL -o$*.oo $*.c
+
+# object file macrough lists
+
+HFILES = zip.h ziperr.h tailor.h revision.h crypt.h ttyio.h amiga/amiga.h \
+         amiga/zipup.h amiga/osdep.h
+
+OBJA = zipfile.o zipup.o fileio.o util.o globals.o crc32.o crctab.o crypt.o \
+       ttyio.o amiga.o amigazip.o time_lib.o
+OBJI = deflate.o trees.o
+OBJU = zipfile.oo fileio.oo util.oo globals.o amiga.o amigazip.oo time_lib.o
+
+OBJZ = zip.o $(OBJA) $(OBJI)
+
+OBJN = zipnote.o  $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt.oo ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+ZIPS = zip zipnote zipcloak zipsplit
+
+all:      Message $(ZIPS)
+
+Message:
+       -echo " "
+       -echo "WARNING: Lattice 5.x HAS NOT BEEN TESTED WITH THIS ZIP VERSION"
+       -echo "Report problems to <zip-bugs@lists.wku.edu>"
+       -echo " "
+
+zip: $(OBJZ) $(HFILES)
+        -echo "$(OBJZ)" > $(TMPFILE)
+       $(LD) TO Zip      FROM $(LDSTART) WITH $(TMPFILE) $(LDFLAGS) $(LDBG)
+        -delete $(TMPFILE) Zip.info
+
+zipnote: $(OBJN) $(HFILES)
+        -echo "$(OBJN)" > $(TMPFILE)
+       $(LD) TO ZipNote  FROM $(LDSTART) WITH $(TMPFILE) $(LDFLAGS) $(LDBG)
+        -delete $(TMPFILE) ZipNote.info
+
+zipcloak: $(OBJC) $(HFILES)
+        -echo "$(OBJC)" > $(TMPFILE)
+       $(LD) TO ZipCloak FROM $(LDSTART) WITH $(TMPFILE) $(LDFLAGS) $(LDBG)
+        -delete $(TMPFILE) ZipCloak.info
+
+zipsplit: $(OBJS) $(HFILES)
+        -echo "$(OBJS)" > $(TMPFILE)
+       $(LD) TO ZipSplit FROM $(LDSTART) WITH $(TMPFILE) $(LDFLAGS) $(LDBG)
+        -delete $(TMPFILE) ZipSplit.info
+
+clean:
+       -delete $(OBJZ) all quiet force >nil:
+       -delete $(OBJU) all quiet force >nil:
+       -delete $(OBJA) all quiet force >nil:
+       -delete $(OBJI) all quiet force >nil:
+       -delete $(OBJN) all quiet force >nil:
+       -delete $(OBJC) all quiet force >nil:
+       -delete $(OBJS) all quiet force >nil:
+
+zip.o:      zip.c      $(HFILES)
+zipnote.o:  zipnote.c  $(HFILES)
+zipcloak.o: zipcloak.c $(HFILES)
+crypt.o:    crypt.c    $(HFILES)
+ttyio.o:    ttyio.c    $(HFILES)
+zipsplit.o: zipsplit.c $(HFILES)
+deflate.o:  deflate.c  $(HFILES)
+trees.o:    trees.c    $(HFILES)
+zipfile.o:  zipfile.c  $(HFILES)
+zipup.o:    zipup.c    $(HFILES)
+fileio.o:   fileio.c   $(HFILES)
+util.o:     util.c     $(HFILES)
+crc32.o:    crc32.c    $(HFILES)
+crctab.o:   crctab.c   $(HFILES)
+globals.o:  globals.c  $(HFILES)
+
+# Amiga specific objects
+amiga.o: amiga/amiga.c $(HFILES)
+amigazip.o: amiga/amigazip.c $(HFILES)
+time_lib.o: amiga/time_lib.c
+
+# end of Makefile
diff --git a/amiga/README b/amiga/README
new file mode 100644 (file)
index 0000000..861ff85
--- /dev/null
@@ -0,0 +1 @@
+the -A option currently does not work for the amiga.
diff --git a/amiga/amiga.c b/amiga/amiga.c
new file mode 100644 (file)
index 0000000..93bd495
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* OS specific routines for AMIGA platform.
+ *
+ * John Bush    <John.Bush@east.sun.com>  BIX: jbush
+ * Paul Kienitz <kie@pacbell.net>
+ *
+ * History:
+ *
+ * Date     DoBee    Comments
+ * -------  -------- -----------------------------------------------
+ * 21Jan93  JBush    Original coding.
+ *                   Incorporated filedate.c (existing routine).
+ *
+ * 31Jan93  JBush    Made filedate.c include unconditional.
+ *
+ * 18Jul93  PaulK    Moved Aztec _abort() here from stat.c because we
+ *                   can't share the same one between Zip and UnZip.
+ *                   Added close_leftover_open_dirs() call to it.
+ *
+ * 17Apr95  PaulK    Added Amiga internal version string so that
+ *                   installer programs can compare the version being
+ *                   installed to see if the copy the user already has
+ *                   is older or newer.  Added Prestart_Hook to support
+ *                   debug tracing in deflate.a.
+ *
+ *  6May95  PaulK    Added GetComment() for filenote support.
+ *
+ * 12Nov95  PaulK    Added #define ZIP in front of filedate.c, for
+ *                   new options in there; removed declare of set_con()
+ *                   since echon() no longer expands to it (or anything).
+ *
+ * 12Feb96  PaulK    Removed call of echon() entirely.
+ *
+ * 12Jul97  PaulK    Made both Aztec and SAS define USE_TIME_LIB for filedate.c
+ *
+ * 26Aug97  PaulK    Added ClearIOErr_exit()
+ *
+ *  2Jan98  HWalt    Adapted for SAS/C using stat.c replacement functions
+ */
+
+#include <exec/memory.h>
+#ifdef AZTEC_C
+#  include <libraries/dos.h>
+#  include <libraries/dosextens.h>
+#  include <clib/exec_protos.h>
+#  include <clib/dos_protos.h>
+#  include <pragmas/exec_lib.h>
+#  include <pragmas/dos_lib.h>
+#else
+#  include <proto/exec.h>
+#  include <proto/dos.h>
+#endif
+#include <stdlib.h>
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+#include "ziperr.h"
+void ziperr(int c, ZCONST char *h);
+
+#if defined(AZTEC_C) || defined(__SASC)
+#  define USE_TIME_LIB
+#endif
+
+#define ZIP
+#if !defined(UTIL) && !defined(USE_TIME_LIB)
+#  define NO_MKTIME
+#endif
+
+#ifdef AZTEC_C
+
+/* ============================================================= */
+/* filedate.c is an external file, since it's shared with UnZip. */
+/* Aztec includes it here, but SAS/C now compiles it separately. */
+#  include "amiga/filedate.c"
+
+/* the same applies to stat.c                                    */
+#  include "amiga/stat.c"
+
+#  define setenv BOGUS_INCOMPATIBLE_setenv
+#  include <fcntl.h>
+#  undef setenv
+#  ifdef DEBUG
+#    define PRESTART_HOOK
+#  endif
+#endif
+
+extern void close_leftover_open_dirs(void);
+
+
+/* the following handles cleanup when a ^C interrupt happens: */
+
+void _abort(void)               /* called when ^C is pressed */
+{
+    close_leftover_open_dirs();
+    ziperr(ZE_ABORT, "^C");
+}
+
+void ClearIOErr_exit(int e)     /* EXIT is defined as this */
+{
+    if (!e)
+        ((struct Process *) FindTask(NULL))->pr_Result2 = 0;
+    /* we clear IoErr() since we are successful, in a 1.x-compatible way */
+    exit(e);
+}
+
+
+/* Make sure the version number here matches the number in revision.h */
+/* as closely as possible in strict decimal "#.#" form:               */
+const char version_id[] = "\0$VER: Zip 2.3 ("
+#  include "env:VersionDate"
+")\r\n";
+
+/* call this with an arg of NULL to free storage: */
+
+char *GetComment(char *filename)
+{
+    BPTR lk;
+    static struct FileInfoBlock *fib = NULL;
+
+    if (!filename) {
+        if (fib) FreeMem(fib, sizeof(*fib));
+        fib = NULL;
+        return NULL;
+    }
+    if (!fib) {
+        if (!(fib = AllocMem(sizeof(*fib), MEMF_PUBLIC)))
+            ziperr(ZE_MEM, "was checking filenotes");
+    }
+    if (!(lk = Lock(filename, ACCESS_READ)))
+        return NULL;
+    if (!Examine(lk, fib))
+        fib->fib_Comment[0] = '\0';
+    UnLock(lk);
+    return fib->fib_Comment[0] ? &fib->fib_Comment[0] : NULL;
+}
diff --git a/amiga/amiga.h b/amiga/amiga.h
new file mode 100644 (file)
index 0000000..a1461d8
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __amiga_amiga_h
+#define __amiga_amiga_h
+
+/* amiga.h
+ *
+ * Globular definitions that affect all of AmigaDom.
+ *
+ * Originally included in unzip.h, extracted for simplicity and eeze of
+ * maintenance by John Bush.
+ *
+ * This version is for use with Zip.  It is not globally included, but used
+ * only by functions in amiga/amigazip.c.  Much material that was needed for
+ * UnZip is absent here.
+ *
+ */
+
+#include <fcntl.h>          /* O_BINARY for open() w/o CR/LF translation */
+#include "amiga/z-stat.h"  /* substitute for <stat.h> and <dire(c|n)t.h> */
+#define direct dirent
+
+#ifndef MODERN
+#  define MODERN
+#endif
+
+#ifdef AZTEC_C                          /* Manx Aztec C, 5.0 or newer only */
+#  include <clib/dos_protos.h>
+#  include <pragmas/dos_lib.h>          /* do inline dos.library calls */
+#  define O_BINARY 0
+#endif /* AZTEC_C */
+
+
+#ifdef __SASC
+#  include <dirent.h>
+#  include <dos.h>
+#  define disk_not_mounted 0
+#  if ( (!defined(O_BINARY)) && defined(O_RAW))
+#    define O_BINARY O_RAW
+#  endif
+#endif /* SASC */
+
+
+/* Funkshine Prough Toe Taipes */
+
+LONG FileDate (char *, time_t[]);
+
+#endif /* __amiga_amiga_h */
diff --git a/amiga/amigazip.c b/amiga/amigazip.c
new file mode 100644 (file)
index 0000000..f72f27d
--- /dev/null
@@ -0,0 +1,510 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include "zip.h"
+#include "amiga/amiga.h"
+
+#ifndef UTIL    /* the companion #endif is a bit of ways down ... */
+
+#define utime FileDate
+
+#define PAD 0
+#define PATH_END '/'
+
+/* Local globals (kinda like "military intelligence" or "broadcast quality") */
+
+extern char *label;             /* still declared in fileio.c */
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+/* Local functions */
+local char *readd OF((DIR *));
+local int wild_recurse OF((char *, char *));
+
+
+local char *readd(d)
+DIR *d;                 /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+   no more entries or an error occurs. */
+{
+  struct dirent *e = readdir(d);
+  return e == NULL ? (char *) NULL : e->d_name;
+}
+
+
+/* What we have here is a mostly-generic routine using opendir()/readd() and */
+/* isshexp()/MATCH() to find all the files matching a multi-part filespec  */
+/* using the portable pattern syntax.  It shouldn't take too much fiddling */
+/* to make it usable for any other platform that has directory hierarchies */
+/* but no shell-level pattern matching.  It works for patterns throughout  */
+/* the pathname, such as "foo:*.?/source/x*.[ch]".                         */
+
+#define ONENAMELEN 30
+/* the length of one filename component on the Amiga */
+
+/* whole is a pathname with wildcards, wildtail points somewhere in the  */
+/* middle of it.  All wildcards to be expanded must come AFTER wildtail. */
+
+local int wild_recurse(whole, wildtail) char *whole; char *wildtail;
+{
+    DIR *dir;
+    char *subwild, *name, *newwhole = NULL, *glue = NULL, plug = 0, plug2;
+    ush newlen, amatch = 0;
+    BPTR lok;
+    int e = ZE_MISS;
+
+    if (!isshexp(wildtail))
+        if (lok = Lock(whole, ACCESS_READ)) {       /* p exists? */
+            UnLock(lok);
+            return procname(whole, 0);
+        } else
+            return ZE_MISS;                     /* woops, no wildcards! */
+
+    /* back up thru path components till existing dir found */
+    do {
+        name = wildtail + strlen(wildtail) - 1;
+        for (;;)
+            if (name-- <= wildtail || *name == PATH_END) {
+                subwild = name + 1;
+                plug2 = *subwild;
+                *subwild = 0;
+                break;
+            }
+        if (glue)
+            *glue = plug;
+        glue = subwild;
+        plug = plug2;
+        dir = opendir(whole);
+    } while (!dir && !disk_not_mounted && subwild > wildtail);
+    wildtail = subwild;                 /* skip past non-wild components */
+
+    if ((subwild = strchr(wildtail + 1, PATH_END)) != NULL) {
+        /* this "+ 1" dodges the   ^^^ hole left by *glue == 0 */
+        *(subwild++) = 0;               /* wildtail = one component pattern */
+        newlen = strlen(whole) + strlen(subwild) + (ONENAMELEN + 2);
+    } else
+        newlen = strlen(whole) + (ONENAMELEN + 1);
+    if (!dir || !(newwhole = malloc(newlen))) {
+        if (glue)
+            *glue = plug;
+
+        e = dir ? ZE_MEM : ZE_MISS;
+        goto ohforgetit;
+    }
+    strcpy(newwhole, whole);
+    newlen = strlen(newwhole);
+    if (glue)
+        *glue = plug;                           /* repair damage to whole */
+    if (!isshexp(wildtail)) {
+        e = ZE_MISS;                            /* non-wild name not found */
+        goto ohforgetit;
+    }
+
+    while (name = readd(dir)) {
+        if (MATCH(wildtail, name, 0)) {
+            strcpy(newwhole + newlen, name);
+            if (subwild) {
+                name = newwhole + strlen(newwhole);
+                *(name++) = PATH_END;
+                strcpy(name, subwild);
+                e = wild_recurse(newwhole, name);
+            } else
+                e = procname(newwhole, 0);
+            newwhole[newlen] = 0;
+            if (e == ZE_OK)
+                amatch = 1;
+            else if (e != ZE_MISS)
+                break;
+        }
+    }
+
+  ohforgetit:
+    if (dir) closedir(dir);
+    if (subwild) *--subwild = PATH_END;
+    if (newwhole) free(newwhole);
+    if (e == ZE_MISS && amatch)
+        e = ZE_OK;
+    return e;
+}
+
+int wild(p) char *p;
+{
+    char *use;
+
+    /* special handling of stdin request */
+    if (strcmp(p, "-") == 0)    /* if compressing stdin */
+        return newname(p, 0, 0);
+
+    /* wild_recurse() can't handle colons in wildcard part: */
+    if (use = strchr(p, ':')) {
+        if (strchr(++use, ':'))
+            return ZE_PARMS;
+    } else
+        use = p;
+
+    return wild_recurse(p, use);
+}
+
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  char *a;              /* path and name for recursion */
+  DIR *d;               /* directory stream from opendir() */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (LSSTAT(n, &s))
+  {
+    /* Not a file or directory--search for shell expression in zip file */
+    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+  if ((s.st_mode & S_IFDIR) == 0)
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  } else {
+    /* Add trailing / to the directory name */
+    if ((p = malloc(strlen(n)+2)) == NULL)
+      return ZE_MEM;
+    strcpy(p, n);
+    a = p + strlen(p);
+    if (*p && a[-1] != '/' && a[-1] != ':')
+      strcpy(a, "/");
+    if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+      free((zvoid *)p);
+      return m;
+    }
+    /* recurse into directory */
+    if (recurse && (d = opendir(n)) != NULL)
+    {
+      while ((e = readd(d)) != NULL) {
+        if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+        {
+          closedir(d);
+          free((zvoid *)p);
+          return ZE_MEM;
+        }
+        strcat(strcpy(a, p), e);
+        if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
+        {
+          if (m == ZE_MISS)
+            zipwarn("name not matched: ", a);
+          else
+            ziperr(m, a);
+        }
+        free((zvoid *)a);
+      }
+      closedir(d);
+    }
+    free((zvoid *)p);
+  } /* (s.st_mode & S_IFDIR) == 0) */
+  return ZE_OK;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t;              /* shortened name */
+  int dosflag;
+
+  dosflag = dosify;     /* default for non-DOS and non-OS/2 */
+
+  /* Find starting point in name before doing malloc */
+  if ((t = strrchr(x, ':')) != NULL)    /* reject ":" */
+    t++;
+  else
+    t = x;
+  {                                     /* reject "//" */
+    char *tt = t;
+    while (tt = strchr(tt, '/'))
+      while (*++tt == '/')
+        t = tt;
+  }
+  while (*t == '/')             /* reject leading "/" on what's left */
+    t++;
+
+  if (!pathput)
+    t = last(t, PATH_END);
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL)
+    return NULL;
+  strcpy(n, t);
+
+  if (dosify)
+    msname(n);
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+  return n;
+}
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+
+  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+      return NULL;
+  strcpy(x, n);
+  return x;
+}
+
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+  time_t u[2];          /* argument for utime() */
+
+  /* Convert DOS time to time_t format in u */
+  u[0] = u[1] = dos2unixtime(d);
+
+  /* Set updated and accessed times of f */
+  utime(f, u);
+}
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  char *name;
+  unsigned int len = strlen(f);
+
+  if (f == label) {
+    if (a != NULL)
+      *a = label_mode;
+    if (n != NULL)
+      *n = -2L; /* convention for a label name */
+    if (t != NULL)
+      t->atime = t->mtime = t->ctime = label_utim;
+    return label_time;
+  }
+
+  if ((name = malloc(len + 1)) == NULL) {
+    ZIPERR(ZE_MEM, "filetime");
+  }
+  strcpy(name, f);
+  if (name[len - 1] == '/')
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+
+  if (strcmp(f, "-") == 0) {
+    if (fstat(fileno(stdin), &s) != 0) {
+      free(name);
+      error("fstat(stdin)");
+    }
+  } else if (SSTAT(name, &s) != 0) {
+             /* Accept about any file kind including directories
+              * (stored with trailing / with -r option)
+              */
+    free(name);
+    return 0;
+  }
+
+  if (a != NULL) {
+    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
+    if ((s.st_mode & S_IFDIR) != 0) {
+      *a |= MSDOS_DIR_ATTR;
+    }
+  }
+  if (n != NULL)
+    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = s.st_ctime;
+  }
+
+   free(name);
+
+   return unix2dostime(&s.st_mtime);
+}
+
+int set_extra_field(z, z_utim)
+  struct zlist far *z;
+  iztimes *z_utim;
+  /* create extra field and change z->att if desired */
+{
+#ifdef USE_EF_UT_TIME
+#ifdef IZ_CHECK_TZ
+  if (!zp_tz_is_valid) return ZE_OK;    /* skip silently if no valid TZ info */
+#endif
+
+  if ((z->extra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL)
+    return ZE_MEM;
+
+  z->extra[0]  = 'U';
+  z->extra[1]  = 'T';
+  z->extra[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */
+  z->extra[3]  = 0;
+  z->extra[4]  = EB_UT_FL_MTIME;
+  z->extra[5]  = (char)(z_utim->mtime);
+  z->extra[6]  = (char)(z_utim->mtime >> 8);
+  z->extra[7]  = (char)(z_utim->mtime >> 16);
+  z->extra[8]  = (char)(z_utim->mtime >> 24);
+
+  z->cextra = z->extra;
+  z->cext = z->ext  = (EB_HEADSIZE+EB_UT_LEN(1));
+
+  return ZE_OK;
+#else /* !USE_EF_UT_TIME */
+  return (int)(z-z);
+#endif /* ?USE_EF_UT_TIME */
+}
+
+int deletedir(d)
+char *d;                /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+   Return the result of rmdir(), delete(), or system().
+   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).
+ */
+{
+    return rmdir(d);
+}
+
+#endif /* !UTIL */
+
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+
+/* NOTE:  the following include depends upon the environment
+ *        variable $Workbench to be set correctly.  (Set by
+ *        default, by Version command in Startup-sequence.)
+ */
+int WBversion = (int)
+#include "ENV:Workbench"
+;
+
+void version_local()
+{
+   static ZCONST char CompiledWith[] = "Compiled with %s%s under %s%s%s%s.\n\n";
+
+/* Define buffers. */
+
+   char buf1[16];  /* compiler name */
+   char buf2[16];  /* revstamp */
+   char buf3[16];  /* OS */
+   char buf4[16];  /* Date */
+/*   char buf5[16];  /* Time */
+
+/* format "with" name strings */
+
+#ifdef AMIGA
+# ifdef __SASC
+   strcpy(buf1,"SAS/C ");
+# else
+#  ifdef LATTICE
+    strcpy(buf1,"Lattice C ");
+#  else
+#   ifdef AZTEC_C
+     strcpy(buf1,"Manx Aztec C ");
+#   else
+     strcpy(buf1,"UNKNOWN ");
+#   endif
+#  endif
+# endif
+/* "under" */
+  sprintf(buf3,"AmigaDOS v%d",WBversion);
+#else
+  strcpy(buf1,"Unknown compiler ");
+  strcpy(buf3,"Unknown OS");
+#endif
+
+/* Define revision, date, and time strings.
+ * NOTE:  Do not calculate run time, be sure to use time compiled.
+ * Pass these strings via your makefile if undefined.
+ */
+
+#if defined(__VERSION__) && defined(__REVISION__)
+  sprintf(buf2,"version %d.%d",__VERSION__,__REVISION__);
+#else
+# ifdef __VERSION__
+  sprintf(buf2,"version %d",__VERSION__);
+# else
+  sprintf(buf2,"unknown version");
+# endif
+#endif
+
+#ifdef __DATE__
+  sprintf(buf4," on %s",__DATE__);
+#else
+  strcpy(buf4," unknown date");
+#endif
+
+/******
+#ifdef __TIME__
+  sprintf(buf5," at %s",__TIME__);
+#else
+  strcpy(buf5," unknown time");
+#endif
+******/
+
+/* Print strings using "CompiledWith" mask defined above.
+ *  ("Compiled with %s%s under %s%s%s%s.")
+ */
+
+   printf(CompiledWith,
+     buf1,
+     buf2,
+     buf3,
+     buf4,
+     /* buf5, */ "",
+     "" );  /* buf6 not used */
+
+} /* end function version_local() */
diff --git a/amiga/crc_68.a b/amiga/crc_68.a
new file mode 100644 (file)
index 0000000..809a0ba
--- /dev/null
@@ -0,0 +1,144 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; crc_68 created by Paul Kienitz, last modified 04 Jan 96.
+;
+; Return an updated 32 bit CRC value, given the old value and a block of data.
+; The CRC table used to compute the value is gotten by calling get_crc_table().
+; This replaces the older updcrc() function used in Zip and fUnZip.  The
+; prototype of the function is:
+;
+;    ulg crc32(ulg crcval, uch *text, extent textlen);
+;
+; On the Amiga, type extent is always unsigned long, not unsigned int, because
+; int can be short or long at whim, but size_t is long.
+;
+; If using this source on a non-Amiga 680x0 system, note that we treat
+; a0/a1/d0/d1 as scratch registers not preserved across function calls.
+; We do not bother to support registerized arguments for crc32() -- the
+; textlen parm is usually large enough so that savings outside the loop
+; are pointless.
+;
+; Define NO_UNROLLED_LOOPS to use a simple short loop which might be more
+; efficient on certain machines with dinky instruction caches ('020?), or for
+; processing short strings.  If loops are unrolled, the textlen parm must be
+; less than 512K; if not unrolled, it must be less than 64K.
+
+        xdef    _crc32          ; (ulg val, uch *buf, extent bufsize)
+
+DO_CRC0 MACRO
+        moveq  #0,ltemp
+        move.b (textbuf)+,ltemp
+        eor.b  crcval,ltemp
+        lsl.w  #2,ltemp
+        move.l (crc_table,ltemp.w),ltemp
+        lsr.l  #8,crcval
+        eor.l  ltemp,crcval
+        ENDM
+
+        machine mc68020
+
+DO_CRC2 MACRO
+        move.b (textbuf)+,btemp
+        eor.b  crcval,btemp
+        lsr.l  #8,crcval
+        move.l (crc_table,btemp.w*4),ltemp
+        eor.l  ltemp,crcval
+        ENDM
+
+crc_table       equr    a0      array of unsigned long
+crcval          equr    d0      unsigned long initial value
+textbuf         equr    a1      array of unsigned char
+textbufsize     equr    d1      unsigned long (count of bytes in textbuf)
+btemp           equr    d2
+ltemp           equr    d3
+
+
+        xref    _get_crc_table  ; ulg *get_crc_table(void)
+
+        NOLIST
+        INCLUDE 'exec/execbase.i'
+        LIST
+        xref    _SysBase        ; struct ExecBase *
+
+
+_crc32:
+        move.l  8(sp),d0
+        bne.s   valid
+         moveq  #0,d0
+         rts
+valid:  movem.l btemp/ltemp,-(sp)
+        jsr     _get_crc_table
+        move.l  d0,ltemp
+        move.l  12(sp),crcval
+        move.l  16(sp),textbuf
+        move.l  20(sp),textbufsize
+        not.l   crcval
+        move.l  _SysBase,crc_table
+        move.w  AttnFlags(crc_table),btemp
+        move.l  ltemp,crc_table
+        btst    #AFB_68020,btemp
+        bne     twenty
+
+    IFD     NO_UNROLLED_LOOPS
+
+        bra.s   decr
+loop:    DO_CRC0
+decr:    dbra   textbufsize,loop
+        bra.s   done
+
+twenty: moveq   #0,btemp
+        bra.s   decr2
+loop2:   DO_CRC2
+decr2:   dbra   textbufsize,loop2
+
+    ELSE    ; !NO_UNROLLED_LOOPS
+
+        move.l  textbufsize,btemp
+        lsr.l   #3,textbufsize
+        bra     decr8
+loop8:   DO_CRC0
+         DO_CRC0
+         DO_CRC0
+         DO_CRC0
+         DO_CRC0
+         DO_CRC0
+         DO_CRC0
+         DO_CRC0
+decr8:   dbra   textbufsize,loop8
+        and.w   #7,btemp
+        bra.s   decr1
+loop1:   DO_CRC0
+decr1:   dbra   btemp,loop1
+        bra     done
+
+twenty: moveq   #0,btemp
+        move.l  textbufsize,-(sp)
+        lsr.l   #3,textbufsize
+        bra     decr82
+loop82:  DO_CRC2
+         DO_CRC2
+         DO_CRC2
+         DO_CRC2
+         DO_CRC2
+         DO_CRC2
+         DO_CRC2
+         DO_CRC2
+decr82:  dbra   textbufsize,loop82
+        move.l  (sp)+,textbufsize
+        and.w   #7,textbufsize
+        bra.s   decr12
+loop12:  DO_CRC2
+decr12:  dbra   textbufsize,loop12
+
+    ENDC    ; ?NO_UNROLLED_LOOPS
+
+done:   movem.l (sp)+,btemp/ltemp
+        not.l   crcval
+;;;;;   move.l  crcval,d0               ; crcval already is d0
+        rts
diff --git a/amiga/deflate.a b/amiga/deflate.a
new file mode 100644 (file)
index 0000000..b21adae
--- /dev/null
@@ -0,0 +1,1053 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; This is a 680x0 assembly language translation of the Info-ZIP source file
+; deflate.c, by Paul Kienitz. The function longest_match is based in part
+; on match.a by Carsten Steger, which in turn is partly based on match.s
+; for 386 by Jean-loup Gailly and Kai Uwe Rommel.  Mostly, however, this
+; material is based on deflate.c, by Gailly, Rommel, and Igor Mandrichenko.
+; This code is not commented very much; see deflate.c for comments that explain
+; what the functions are doing.
+;
+; The symbols that can be used to select different versions are as follows:
+;
+;   CPU020     if defined, use 68020 instructions always.
+;
+;   CPUTEST    if defined, check at runtime for CPU type.  Another symbol
+;               specifying the platform-specific test must be used with this.
+;               If neither of these is defined, use 68000 instructions only.
+;               Runtime test is nonportable; it is different for each OS.
+;
+;   AMIGA      use Amiga-specific test for 68020, if CPUTEST defined.  Also
+;               tells it that registers d0/a0/d1/a1 are not preserved by
+;               function calls.  At present, if AMIGA is not defined, it
+;               causes functions to preserve all registers.  ALL OF THIS CODE
+;               CURRENTLY ASSUMES THAT REGISTERS D2-D7/A2-A6 WILL BE PRESERVED
+;               BY ANY FUNCTIONS THAT IT CALLS.
+;
+;   DYN_ALLOC  should be defined here if it is defined for C source; tells us
+;               that big arrays are allocated instead of static.
+;
+;   WSIZE      must be defined as the same number used for WSIZE in the C
+;               source, and must be a power of two <= 32768.  As elsewhere,
+;               the default value is 32768.
+;
+;   INT16      define this if ints are 16 bits; otherwise 32 bit ints assumed.
+;
+;   SMALL_MEM  define this if it is defined in the C source; otherwise it uses
+;               the MEDIUM_MEM model.  BIG_MEM and MMAP are *not* supported.
+;               The FULL_SEARCH option in deflate.c is also not supported.
+;
+;   DEBUG      activates some tracing output, as in the C source.
+;
+;   QUADLONG   this selects a different version of the innermost longest_match
+;               loop code for 68020 operations, comparing bytes four at a time
+;               instead of two at a time.  It seems to be a tiny bit faster on
+;               average, but it's slower often enough that one can't generalize.
+;
+; This code currently assumes that function results are returned in D0 for
+; all platforms.  It assumes that args to functions are pushed onto the stack,
+; last arg first.  It also currently assumes that all C symbols have an
+; underscore prepended when referenced from assembly.
+
+    IFND    CPU020
+     IFND   CPUTEST
+CPU000  equ     1
+     ENDC
+    ENDC
+
+; Use these macros for accessing variables of type int:
+    IFD     INT16
+MOVINT  MACRO
+        move.w  \1,\2
+        ENDM
+CLRINT  MACRO
+        clr.w   \1
+        ENDM
+INTSIZE equ     2
+    ELSE    ; !INT16
+MOVINT  MACRO
+        move.l  \1,\2
+        ENDM
+CLRINT  MACRO
+        clr.l   \1
+        ENDM
+INTSIZE equ     4
+    ENDC
+
+    IFD     DYN_ALLOC
+BASEPTR MACRO
+        move.l  \1,\2
+        ENDM
+    ELSE
+BASEPTR MACRO
+        lea     \1,\2
+        ENDM
+    ENDC
+
+; constants we use, many of them adjustable:
+
+MAX_MATCH       equ     258
+MIN_MATCH       equ     3
+TOO_FAR         equ     4096
+    IFND    WSIZE
+WSIZE           equ     32768
+    ENDC
+WMASK           equ     WSIZE-1
+MAX_DIST        equ     WSIZE-MAX_MATCH-MIN_MATCH-1
+MIN_LOOKAHEAD   equ     MAX_MATCH+MIN_MATCH+1
+;    IFD     BIG_MEM      ; NOT supported -- type Pos needs to be 32 bits
+;HASH_BITS      equ     15
+;    ELSE
+    IFD    SMALL_MEM
+HASH_BITS       equ     13
+    ELSE
+HASH_BITS       equ     14      ; default -- MEDIUM_MEM
+    ENDC
+;    ENDC    ; BIG_MEM
+HASH_SIZE       equ     1<<HASH_BITS
+HASH_MASK       equ     HASH_SIZE-1
+H_SHIFT         equ     (HASH_BITS+MIN_MATCH-1)/MIN_MATCH
+B_SLOW          equ     1
+B_FAST          equ     2
+ZE_MEM          equ     4
+EOF             equ     -1
+
+; struct config is defined by these offsets:
+Good_length     equ     0
+Max_lazy        equ     2
+Nice_length     equ     4
+Max_chain       equ     6
+Sizeof_config   equ     8
+
+
+; external functions we call:
+        xref    _ct_tally       ; int ct_tally(int, int)
+        xref    _flush_block    ; unsigned long F(char *, unsigned long, int)
+        xref    _ziperr         ; void ziperr(int, char *)
+        xref    _error          ; void error(char *)
+        xref    _calloc         ; stdlib function: void *calloc(size_t, size_t)
+        xref    _free           ; stdlib function: void free(void *)
+    IFD     DEBUG
+        xref    _fputc          ; stdio function: int fputc(int, FILE *)
+        xref    _stderr         ; pointer to FILE, which we pass to fputc
+    ENDC
+
+; our entry points:
+        xdef    _lm_init        ; void lm_init(int level, unsigned short *flags)
+        xdef    _lm_free        ; void lm_free(void)
+        xdef    _deflate        ; void deflate(void)  ...the big one
+        xdef    _fill_window    ; this line is just for debugging
+
+
+; ============================================================================
+; Here is where we have our global variables.
+
+        section deflatevars,data
+
+; external global variables we reference:
+        xref    _verbose        ; signed int
+        xref    _level          ; signed int
+        xref    _read_buf       ; int (*read_buf)(char *, unsigned int)
+
+; global variables we make available:
+
+        xdef    _window
+        xdef    _prev
+        xdef    _head
+        xdef    _window_size
+        xdef    _block_start
+        xdef    _strstart
+
+    IFD     DYN_ALLOC
+_prev:          ds.l    1       ; pointer to calloc()'d unsigned short array
+_head:          ds.l    1       ; pointer to calloc()'d unsigned short array
+_window:        ds.l    1       ; pointer to calloc()'d unsigned char array
+    ELSE    ; !DYN_ALLOC
+_prev:          ds.w    WSIZE           ; array of unsigned short
+_head:          ds.w    HASH_SIZE       ; array of unsigned short
+_window:        ds.b    2*WSIZE         ; array of unsigned char
+    ENDC    ; ?DYN_ALLOC
+_window_size:   ds.l    1               ; unsigned long
+_block_start:   ds.l    1               ; unsigned long
+_strstart:      ds.w    INTSIZE/2       ; unsigned int
+
+; Now here are our private variables:
+
+    IFD     CPUTEST
+is020:          ds.w    1       ; bool: CPU type is '020 or higher
+    ENDC
+ins_h:          ds.w    1       ; unsigned short
+sliding:        ds.w    1       ; bool: the file is read a piece at a time
+eofile:         ds.w    1       ; bool: we have read in the end of the file
+max_lazy_match: ds.w    1       ; unsigned short
+lookahead:      ds.w    1       ; unsigned short
+
+; These are NOT DECLARED AS STATIC in deflate.c, but currently could be:
+max_chain_len:  ds.w    1       ; unsigned short (unsigned int in deflate.c)
+prev_length:    ds.w    1       ; unsigned short (unsigned int in deflate.c)
+good_match:     ds.w    1       ; unsigned short (unsigned int in deflate.c)
+nice_match:     ds.w    1       ; unsigned short (signed int in deflate.c)
+match_start:    ds.w    1       ; unsigned short (unsigned int in deflate.c)
+
+; This array of struct config is a constant and could be in the code section:
+config_table:   dc.w    0,0,0,0         ; level 0: store uncompressed
+                dc.w    4,4,8,4         ; level 1: fastest, loosest compression
+                dc.w    4,5,16,8        ; level 2
+                dc.w    4,6,32,32       ; level 3: highest to use deflate_fast
+                dc.w    4,4,16,16       ; level 4: lowest to use lazy matches
+                dc.w    8,16,32,32      ; level 5
+                dc.w    8,16,128,128    ; level 6: the default level
+                dc.w    8,32,128,256    ; level 7
+                dc.w    32,128,258,1024 ; level 8
+                dc.w    32,258,258,4096 ; level 9: maximum compression, slow
+
+
+;;CAL_SH  MACRO                   ; macro for calling zcalloc()
+;;     IFD    INT16
+;;        move.w  #2,-(sp)
+;;        move.w  #\1,-(sp)
+;;        jsr     _zcalloc
+;;        addq    #4,sp
+;;     ELSE
+;;        pea     2
+;;        pea     \1
+;;        jsr     _zcalloc
+;;        addq    #8,sp
+;;     ENDC
+;;        ENDM
+
+CAL_SH  MACRO                   ; Okay, we're back to using regular calloc()...
+        pea     2
+        pea     \1
+        jsr     _calloc
+        addq    #8,sp
+        ENDM
+
+; ============================================================================
+; And here we begin our functions.  match_init is for internal use only:
+
+        section deflate,code
+
+match_init:
+    IFD     CPUTEST             ; now check for platform type
+     IFD    AMIGA               ; Amiga specific test for '020 CPU:
+        xref    _SysBase
+        NOLIST
+        INCLUDE       'exec/execbase.i'
+        LIST
+
+        clr.w   is020                   ; default value is 68000
+        move.l  _SysBase,a0
+        btst    #AFB_68020,AttnFlags+1(a0)
+        beq.s   cheap
+        move.w  #1,is020
+cheap:
+     ELSE   ; !AMIGA
+
+        FAIL    Write an '020-detector for your system here!
+; On the Macintosh, I believe GetEnvironment() provides the information.
+
+     ENDC   ; AMIGA
+    ENDC    ; CPUTEST
+        rts     ; match_init consists only of rts if CPUTEST unset
+
+
+; ============================================================================
+; Here is longest_match(), the function that the rest of this was built up
+; from, the hottest hot spot in the program and therefore the most heavily
+; optimized.  It has two different versions, one for '020 and higher CPUs, and
+; one for 68000/68010.  It can test at runtime which version to use if you
+; create a test function in match_init for your platform.  Currently such a
+; test is implemented for the Amiga.  It can also be assembled to use '000 or
+; '020 code only.
+
+Cur_Match       equr    d0              ; unsigned int, kept valid as long
+Best_Len        equr    d1              ; unsigned int, kept valid as long
+Scan_Start      equr    d3              ; pair of bytes
+Scan_End        equr    d4              ; pair of bytes
+Limit           equr    d5              ; unsigned int
+Chain_Length    equr    d6              ; unsigned int
+Scan_Test       equr    d7              ; counter, pair of bytes sometimes
+Scan            equr    a0              ; pointer to unsigned char
+Match           equr    a1              ; pointer to unsigned char
+Prev_Address    equr    a2              ; pointer to unsigned short
+Scan_Ini        equr    a3              ; pointer to unsigned char
+Match_Ini       equr    a5              ; pointer to unsigned char
+; Note: "pair of bytes" means the two low order bytes of the register in
+; 68020 code, but means the lowest and third lowest bytes on the 68000.
+    IFD     AMIGA
+SAVEREGS        reg     d3-d7/a2/a3/a5      ; don't protect d0/d1/a0/a1
+    ELSE    ; !AMIGA
+SAVEREGS        reg     d1/d3-d7/a0-a3/a5   ; protect all except d0 return val
+    ENDC    ; ?AMIGA
+; d2, a4, a6 not used... on Amiga, a4 is used by small-data memory model
+
+
+longest_match:
+        movem.l SAVEREGS,-(sp)
+
+; setup steps common to byte and word versions:
+    IFD     INT16
+        and.l   #$0000FFFF,Cur_Match    ; upper half must be zero!
+; we use an and.l down here for the sake of ATSIGN/REGARGS.
+        moveq   #0,Limit                ; so adding to Scan_Ini works
+    ENDC
+        move.w  max_chain_len,Chain_Length
+        move.w  prev_length,Best_Len
+        MOVINT  _strstart,Limit
+        BASEPTR _prev,Prev_Address
+        BASEPTR _window,Match_Ini
+        move.l  Match_Ini,Scan_Ini
+        addq    #MIN_MATCH,Match_Ini    ; optimizes inner loop
+        add.l   Limit,Scan_Ini
+        sub.w   #MAX_DIST,Limit
+        bhi.s   limit_ok
+        moveq   #0,Limit
+limit_ok:
+        cmp.w   good_match,Best_Len
+        blo.s   length_ok
+        lsr.w   #2,Chain_Length
+length_ok:
+        subq.w  #1,Chain_Length
+
+    IFD     CPUTEST
+        tst.w   is020                   ; can we use '020 stuff today?
+        bne     WORD_match
+    ENDC
+
+    IFND    CPU020
+
+; for 68000 or 68010, use byte operations:
+        moveq   #0,Scan_Start           ; clear 2nd & 4th bytes, use 1st & 3rd
+        moveq   #0,Scan_End             ; likewise
+        moveq   #0,Scan_Test            ; likewise
+        move.b  (Scan_Ini),Scan_Start
+        swap    Scan_Start              ; swap is faster than 8 bit shift
+        move.b  1(Scan_Ini),Scan_Start
+        move.b  -1(Scan_Ini,Best_Len.w),Scan_End
+        swap    Scan_End
+        move.b  0(Scan_Ini,Best_Len.w),Scan_End
+        bra.s   bdo_scan
+
+blong_loop:
+        move.b  -1(Scan_Ini,Best_Len.w),Scan_End
+        swap    Scan_End
+        move.b  0(Scan_Ini,Best_Len.w),Scan_End
+
+bshort_loop:
+        add.w   Cur_Match,Cur_Match     ; assert value before doubling < 32K
+     IFNE   32768-WSIZE
+        and.w   #(WMASK*2),Cur_Match
+     ENDC
+        move.w  (Prev_Address,Cur_Match.l),Cur_Match
+        cmp.w   Limit,Cur_Match
+        dbls    Chain_Length,bdo_scan
+        bra     return
+
+bdo_scan:
+        move.l  Match_Ini,Match
+        add.l   Cur_Match,Match
+        move.b  -MIN_MATCH-1(Match,Best_Len.w),Scan_Test
+        swap    Scan_Test
+        move.b  -MIN_MATCH(Match,Best_Len.w),Scan_Test
+        cmp.l   Scan_Test,Scan_End
+        bne.s   bshort_loop
+        move.b  -MIN_MATCH(Match),Scan_Test
+        swap    Scan_Test
+        move.b  -MIN_MATCH+1(Match),Scan_Test
+        cmp.l   Scan_Test,Scan_Start
+        bne.s   bshort_loop
+        move.w  #(MAX_MATCH-3),Scan_Test
+        lea     MIN_MATCH(Scan_Ini),Scan        ; offset optimizes inner loop
+
+bscan_loop:
+        cmp.b   (Match)+,(Scan)+
+        dbne    Scan_Test,bscan_loop
+        subq    #1,Scan
+
+        sub.l   Scan_Ini,Scan           ; assert difference is 16 bits
+        cmp.w   Best_Len,Scan
+        bls.s   bshort_loop
+        MOVINT  Scan,Best_Len
+        move.w  Cur_Match,match_start
+        cmp.w   nice_match,Best_Len
+        blo.s   blong_loop
+     IFD    CPUTEST
+        bra     return
+     ENDC
+
+    ENDC    ; !CPU020
+
+    IFND    CPU000
+        MACHINE MC68020
+
+; for 68020 or higher, use word operations even on odd addresses:
+WORD_match:
+        move.w  (Scan_Ini),Scan_Start
+        move.w  -1(Scan_Ini,Best_Len.w),Scan_End
+        bra.s   wdo_scan
+
+wlong_loop:
+        move.w  -1(Scan_Ini,Best_Len.w),Scan_End
+
+wshort_loop:
+        and.w   #WMASK,Cur_Match
+        move.w  (Prev_Address,Cur_Match.w*2),Cur_Match  ; '020 addressing mode
+        cmp.w   Limit,Cur_Match
+        dbls    Chain_Length,wdo_scan
+        bra.s   return
+
+wdo_scan:
+        move.l  Match_Ini,Match
+        add.l   Cur_Match,Match
+        cmp.w   -MIN_MATCH-1(Match,Best_Len.w),Scan_End
+        bne.s   wshort_loop
+        cmp.w   -MIN_MATCH(Match),Scan_Start
+        bne.s   wshort_loop
+     IFD    QUADLONG
+; By some measurements, this version of the code is a little tiny bit faster.
+; But on some files it's slower.  It probably pays off only when there are
+; long match strings, and costs in the most common case of three-byte matches.
+        moveq   #((MAX_MATCH-MIN_MATCH)/16),Scan_Test     ; value = 15
+        lea     MIN_MATCH(Scan_Ini),Scan        ; offset optimizes inner loop
+
+wscan_loop:
+        cmp.l   (Match)+,(Scan)+                ; test four bytes at a time
+        bne.s   odd
+        cmp.l   (Match)+,(Scan)+
+        bne.s   odd
+        cmp.l   (Match)+,(Scan)+
+        bne.s   odd
+        cmp.l   (Match)+,(Scan)+
+        dbne    Scan_Test,wscan_loop            ; '020 can cache a bigger loop
+odd:
+        subq    #4,Scan
+        subq    #4,Match
+        cmp.b   (Match)+,(Scan)+        ; find good bytes in bad longword
+        bne.s   even
+        cmp.b   (Match)+,(Scan)+
+        bne.s   even
+        cmp.b   (Match)+,(Scan)+
+        beq.s   steven
+even:   subq    #1,Scan
+     ELSE   ; !QUADLONG
+        moveq   #((MAX_MATCH-MIN_MATCH)/2),Scan_Test    ; value = 127
+        lea     MIN_MATCH(Scan_Ini),Scan        ; offset optimizes inner loop
+
+wscan_loop:
+        cmp.w   (Match)+,(Scan)+
+        dbne    Scan_Test,wscan_loop
+        subq    #2,Scan
+        move.b  -2(Match),Scan_Test
+        cmp.b   (Scan),Scan_Test
+        bne.s   steven
+        addq    #1,Scan
+     ENDC   ; ?QUADLONG
+steven:
+        sub.l   Scan_Ini,Scan           ; assert: difference is 16 bits
+        cmp.w   Best_Len,Scan
+        bls.s   wshort_loop
+        MOVINT  Scan,Best_Len
+        move.w  Cur_Match,match_start
+        cmp.w   nice_match,Best_Len
+        blo.s   wlong_loop
+
+        MACHINE MC68000
+    ENDC    ; !CPU000
+
+return:
+        MOVINT  Best_Len,d0         ; return value (upper half should be clear)
+        movem.l (sp)+,SAVEREGS
+        rts
+
+
+; =============================================================================
+; This is the deflate() function itself, our main entry point.  It calls
+; longest_match, above, and some outside functions.  It is a hot spot, but not
+; as hot as longest_match.  It uses no special '020 code.
+
+; ================== Several macros used in deflate() and later functions:
+
+; Arg 1 is D-reg that new ins_h value is to be left in,
+; arg 2 is the byte value to be hashed into it, which must not be the same reg
+UP_HASH MACRO
+        move.w  ins_h,\1
+        asl.w   #H_SHIFT,\1
+        eor.b   \2,\1
+        and.w   #HASH_MASK,\1           ; ((ins_h << H_SHIFT) ^ c) & HASH_MASK
+        move.w  \1,ins_h                ; ins_h = that
+        ENDM
+
+; Arg 1 is scratch A, arg 2 is scratch D
+IN_STR  MACRO
+        move.l  Strst,\2
+        addq.w  #MIN_MATCH-1,\2
+        move.b  (Window,\2.l),\2        ; window[strstart + MIN_MATCH - 1]
+        UP_HASH Head,\2
+        add.l   Head,Head               ; assert upper word is zero before add
+        BASEPTR _head,\1
+        add.l   Head,\1
+        move.w  (\1),Head               ; hash_head = head[ins_h]
+        move.w  Strst,(\1)              ; head[ins_h] = strstart
+        move.l  Strst,\2
+    IFNE    WSIZE-32768
+        and.w   #WMASK,\2
+    ENDC
+        add.w   \2,\2                   ; masks implicitly when WSIZE == 32768
+        move.w  Head,(Prev,\2.l)        ; prev[str_start & WMASK] = hash_head
+        ENDM
+
+; Arg 1 is bool (int) EOF flag, flush_block result is in d0, trashes d1/a0/a1
+FLUSH_B MACRO
+    IFC     '\1','#0'
+        CLRINT  -(sp)
+    ELSE
+        MOVINT  \1,-(sp)
+    ENDC
+        move.l  _block_start,d0
+        blt.s   nenu\@
+        move.l  Window,a0
+        add.l   d0,a0
+        bra.s   nun\@
+nenu\@: sub.l   a0,a0           ; if block_start < 0, push NULL
+nun\@:  sub.l   Strst,d0
+        neg.l   d0
+        move.l  d0,-(sp)
+        move.l  a0,-(sp)
+        jsr     _flush_block
+        lea     8+INTSIZE(sp),sp
+        ENDM
+
+; This expands to nothing unless DEBUG is defined.
+; Arg 1 is a byte to be trace-outputted -- if it is d0 it must be a valid int
+TRACE_C MACRO
+    IFD    DEBUG
+        cmp.w  #1,_verbose+INTSIZE-2    ; test lower word only
+        ble.s   qui\@
+     IFNC    '\1','d0'
+        moveq   #0,d0
+        move.b  \1,d0
+     ENDC
+        move.l  _stderr,-(sp)
+        MOVINT  d0,-(sp)
+        jsr     _fputc
+        addq    #4+INTSIZE,sp
+qui\@:
+    ENDC    ; DEBUG
+        ENDM
+
+; ================== Here are the register vars we use, and deflate() itself:
+
+Window  equr    a2              ; cached address of window[]
+Prev    equr    a3              ; cached address of prev[]
+Strst   equr    d7              ; strstart cached as a longword
+Look    equr    d6              ; lookahead cached as short
+Head    equr    d5              ; local variable hash_head, short
+PrevL   equr    d4              ; prev_length cached as short
+MatchL  equr    d3              ; local variable match_length, unsigned short
+Avail   equr    d2              ; local variable available_match, bool
+PrevM   equr    a5              ; local variable prev_match, int in an A-reg
+
+    IFD     AMIGA
+DEFREGS reg     d2-d7/a2/a3/a5
+    ELSE
+DEFREGS reg     d0-d7/a0/a2/a3/a5       ; play it safe, preserve all regs
+    ENDC
+
+
+_deflate:           ; first, setup steps common to deflate and deflate_fast:
+        movem.l DEFREGS,-(sp)
+    IFD     INT16
+        moveq   #0,Strst                ; make sure strstart is valid as a long
+    ENDC
+        moveq   #0,Head                 ; ditto for hash_head
+        MOVINT  _strstart,Strst
+        move.w  lookahead,Look
+        move.w  prev_length,PrevL
+        BASEPTR _window,Window
+        BASEPTR _prev,Prev
+        MOVINT  _level,d0
+        cmp.w   #3,d0
+        ble     deflate_fast
+        moveq   #MIN_MATCH-1,MatchL
+        moveq   #0,Avail
+
+look_loop:
+        tst.w   Look
+        beq     last_tally
+        IN_STR  a0,d0
+        move.w  MatchL,PrevL
+        move.w  match_start,PrevM
+        move.w  #MIN_MATCH-1,MatchL
+
+        tst.w   Head
+        beq.s   no_new_match
+        cmp.w   max_lazy_match,PrevL
+        bhs.s   no_new_match
+        move.w  Strst,d0
+        sub.w   Head,d0
+        cmp.w   #MAX_DIST,d0
+        bhi.s   no_new_match
+        move.w  PrevL,prev_length       ; longest_match reads these variables
+        MOVINT  Strst,_strstart
+        MOVINT  Head,d0                 ; parm for longest_match
+        bsr     longest_match           ; sets match_start
+        cmp.w   Look,d0                 ; does length exceed valid data?
+        bls.s   stml
+        move.w  Look,d0
+stml:   move.w  d0,MatchL               ; valid length of match
+        cmp.w   #MIN_MATCH,MatchL       ; is the match only three bytes?
+        bne.s   no_new_match
+        move.w  match_start,d0
+        sub.w   Strst,d0
+        cmp.w   #-TOO_FAR,d0
+        bge.s   no_new_match
+        moveq   #MIN_MATCH-1,MatchL     ; mark the current match as no good
+
+no_new_match:
+        cmp.w   #MIN_MATCH,PrevL
+        blo     literal
+        cmp.w   MatchL,PrevL
+        blo     literal
+        ; CHECK_MATCH   Strst-1,PrevM,PrevL
+        MOVINT  Strst,_strstart         ; ct_tally reads this variable
+        move.l  PrevL,d0
+        subq.w  #MIN_MATCH,d0
+        MOVINT  d0,-(sp)
+        move.l  Strst,d0
+        sub.w   PrevM,d0
+        subq.w  #1,d0
+        MOVINT  d0,-(sp)
+        jsr     _ct_tally               ; sets d0 true if we have to flush
+        addq    #2*INTSIZE,sp
+        subq.w  #3,PrevL                ; convert for dbra (prev_length - 2)
+        sub.w   PrevL,Look
+        subq.w  #2,Look
+insertmatch:
+        addq.w  #1,Strst
+        IN_STR  a0,d1                   ; don't clobber d0
+        dbra    PrevL,insertmatch
+        moveq   #0,Avail
+        moveq   #0,PrevL                ; not needed?
+        moveq   #MIN_MATCH-1,MatchL
+        addq.w  #1,Strst
+        tst.w   d0
+        beq     refill
+        FLUSH_B #0
+        move.l  Strst,_block_start
+        bra.s   refill
+
+literal:
+        tst.w   Avail
+        bne.s   yeslit
+        moveq   #1,Avail
+        bra.s   skipliteral
+yeslit: TRACE_C <-1(Window,Strst.l)>
+        MOVINT  Strst,_strstart         ; ct_tally reads this variable
+        moveq   #0,d0
+        move.b  -1(Window,Strst.l),d0
+        MOVINT  d0,-(sp)
+        CLRINT  -(sp)
+        jsr     _ct_tally
+        addq    #2*INTSIZE,sp
+        tst.w   d0
+        beq.s   skipliteral
+        FLUSH_B #0
+        move.l  Strst,_block_start
+skipliteral:
+        addq.w  #1,Strst
+        subq.w  #1,Look
+
+refill:
+        cmp.w   #MIN_LOOKAHEAD,Look
+        bhs     look_loop
+        bsr     fill_window
+        bra     look_loop
+
+last_tally:
+        tst.w   Avail
+        beq     last_flush
+        MOVINT  Strst,_strstart         ; ct_tally reads this variable
+        moveq   #0,d0
+        move.b  -1(Window,Strst.l),d0
+        MOVINT  d0,-(sp)
+        CLRINT  -(sp)
+        jsr     _ct_tally
+        addq    #2*INTSIZE,sp
+last_flush:
+        FLUSH_B #1
+        bra     deflate_exit
+
+; ================== This is another version used for low compression levels:
+
+deflate_fast:
+        moveq   #0,MatchL
+        moveq   #MIN_MATCH-1,PrevL
+flook_loop:
+        tst.w   Look
+        beq     flast_flush
+
+        IN_STR  a0,d0
+        tst.w   Head
+        beq.s   fno_new_match
+        move.w  Strst,d0
+        sub.w   Head,d0
+        cmp.w   #MAX_DIST,d0
+        bhi.s   fno_new_match
+        move.w  PrevL,prev_length       ; longest_match reads these variables
+        MOVINT  Strst,_strstart
+        MOVINT  Head,d0                 ; parm for longest_match
+        bsr     longest_match           ; sets match_start
+        cmp.w   Look,d0                 ; does length exceed valid data?
+        bls.s   fstml
+        move.w  Look,d0
+fstml:  move.w  d0,MatchL               ; valid length of match
+
+fno_new_match:
+        cmp.w   #MIN_MATCH,MatchL
+        blo     fliteral
+        ; CHECK_MATCH   Strst,match_start,MatchL
+        MOVINT  Strst,_strstart         ; ct_tally reads this variable
+        move.l  MatchL,d0
+        subq.w  #MIN_MATCH,d0
+        MOVINT  d0,-(sp)
+        move.l  Strst,d0
+        sub.w   match_start,d0
+        MOVINT  d0,-(sp)
+        jsr     _ct_tally               ; sets d0 true if we have to flush
+        addq    #2*INTSIZE,sp
+        sub.w   MatchL,Look
+        cmp.w   max_lazy_match,MatchL
+        bhi     ftoolong
+        subq.w  #2,MatchL
+finsertmatch:
+        addq.w  #1,Strst
+        IN_STR  a0,d1                   ; preserve d0
+        dbra    MatchL,finsertmatch
+        moveq   #0,MatchL               ; not needed?
+        addq.w  #1,Strst
+        bra.s   flushfill
+
+ftoolong:
+        add.w   MatchL,Strst
+        moveq   #0,MatchL
+        moveq   #0,d1                   ; preserve d0
+        move.b  (Window,Strst.l),d1
+        move.w  d1,ins_h
+; My assembler objects to passing <1(Window,Strst.l)> directly to UP_HASH...
+        move.b  1(Window,Strst.l),Avail ; Avail is not used in deflate_fast
+        UP_HASH d1,Avail                ; preserve d0
+    IFNE    MIN_MATCH-3
+        FAIL  needs to UP_HASH another MIN_MATCH-3 times, but with what arg?
+    ENDC
+        bra.s   flushfill
+
+fliteral:
+        TRACE_C <(Window,Strst.l)>
+        MOVINT  Strst,_strstart         ; ct_tally reads this variable
+        moveq   #0,d0
+        move.b  (Window,Strst.l),d0
+        MOVINT  d0,-(sp)
+        CLRINT  -(sp)
+        jsr     _ct_tally               ; d0 set if we need to flush
+        addq    #2*INTSIZE,sp
+        addq.w  #1,Strst
+        subq.w  #1,Look
+
+flushfill:
+        tst.w   d0
+        beq.s   frefill
+        FLUSH_B #0
+        move.l  Strst,_block_start
+frefill:
+        cmp.w   #MIN_LOOKAHEAD,Look
+        bhs     flook_loop
+        bsr     fill_window
+        bra     flook_loop
+
+flast_flush:
+        FLUSH_B #1                      ; sets our return value
+
+deflate_exit:
+        MOVINT  Strst,_strstart         ; save back cached values
+        move.w  PrevL,prev_length
+        move.w  Look,lookahead
+        movem.l (sp)+,DEFREGS
+        rts
+
+
+; =========================================================================
+; void fill_window(void) calls the input function to refill the sliding
+; window that we use to find substring matches in.
+
+More    equr    Head                    ; local variable in fill_window
+WindTop equr    Prev                    ; local variable used for sliding
+SlidIx  equr    PrevL                   ; local variable used for sliding
+
+    IFD     AMIGA
+FWREGS  reg     d2-d5/a2-a6             ; does NOT include Look and Strst
+    ELSE
+FWREGS  reg     d1-d5/a0-a6             ; likewise
+    ENDC
+; all registers available to be clobbered by the sliding operation:
+; we exclude More, WindTop, SlidIx, Look, Strst, Window, a4 and a7.
+SPAREGS reg     d0-d3/a0-a1/a5-a6
+SPCOUNT equ     8                       ; number of registers in SPAREGS
+
+
+_fill_window:                           ; C-callable entry point
+        movem.l Strst/Look,-(sp)
+    IFD     INT16
+        moveq   #0,Strst                ; Strst must be valid as a long
+    ENDC
+        MOVINT  _strstart,Strst
+        move.w  lookahead,Look
+        BASEPTR _window,Window
+        bsr.s   fill_window
+        MOVINT  Strst,_strstart
+        move.w  Look,lookahead
+        movem.l (sp)+,Strst/Look
+        rts
+
+; strstart, lookahead, and window must be cached in Strst, Look, and Window:
+fill_window:                            ; asm-callable entry point
+        movem.l FWREGS,-(sp)
+        tst.w   eofile                  ; we put this up here for speed
+        bne     fwdone
+        and.l   #$FFFF,Look             ; make sure Look is valid as long
+fw_refill:
+        move.l  _window_size,More       ; <= 64K
+        sub.l   Look,More
+        sub.l   Strst,More              ; Strst is already valid as long
+        cmp.w   #EOF,More
+        bne.s   notboundary
+        subq.w  #1,More
+        bra     checkend
+
+notboundary:
+        tst.w   sliding
+        beq     checkend
+        cmp.w   #WSIZE+MAX_DIST,Strst
+        blo     checkend
+    IFGT    32768-WSIZE
+        lea     WSIZE(Window),WindTop   ; WindTop is aligned when Window is
+    ELSE
+        move.l  Window,WindTop
+        add.l   #WSIZE,WindTop
+    ENDC
+        move.l  Window,d0
+        and.w   #3,d0
+        beq.s   isaligned
+        subq.w  #1,d0
+align:  move.b  (WindTop)+,(Window)+    ; copy up to a longword boundary
+        dbra    d0,align
+isaligned:
+; This is faster than a simple move.l (WindTop)+,(Window)+ / dbra loop:
+        move.w  #(WSIZE-1)/(4*SPCOUNT),SlidIx
+slide:  movem.l (WindTop)+,SPAREGS      ; copy, 32 bytes at a time!
+        movem.l SPAREGS,(Window)        ; a slight overshoot doesn't matter.
+        lea     4*SPCOUNT(Window),Window        ; can't use (aN)+ as movem.l dest
+        dbra    SlidIx,slide
+        BASEPTR _window,Window                  ; restore cached value
+        sub.w   #WSIZE,match_start
+        sub.w   #WSIZE,Strst
+        sub.l   #WSIZE,_block_start
+        add.w   #WSIZE,More
+        BASEPTR _head,a0
+        move.w  #HASH_SIZE-1,d0
+fixhead:
+        move.w  (a0),d1
+        sub.w   #WSIZE,d1
+        bpl.s   headok
+        moveq   #0,d1
+headok: move.w  d1,(a0)+
+        dbra    d0,fixhead
+        BASEPTR _prev,a0
+        move.w  #WSIZE-1,d0
+fixprev:
+        move.w  (a0),d1
+        sub.w   #WSIZE,d1
+        bpl.s   prevok
+        moveq   #0,d1
+prevok: move.w  d1,(a0)+
+        dbra    d0,fixprev
+        TRACE_C #'.'
+
+checkend:                               ; assert eofile is false
+        MOVINT  More,-(sp)              ; assert More's upper word is zero
+        move.l  Strst,d0
+        add.w   Look,d0
+        add.l   Window,d0
+        move.l  d0,-(sp)
+        move.l  _read_buf,a0
+        jsr     (a0)                    ; refill the upper part of the window
+        addq    #4+INTSIZE,sp
+        tst.w   d0
+        beq.s   iseof
+        cmp.w   #EOF,d0
+        beq.s   iseof
+        add.w   d0,Look
+        cmp.w   #MIN_LOOKAHEAD,Look
+        blo     fw_refill               ; eofile is still false
+
+        bra.s   fwdone
+iseof:  move.w  #1,eofile
+fwdone: movem.l (sp)+,FWREGS
+        rts
+
+
+; =========================================================================
+; void lm_free(void) frees dynamic arrays in the DYN_ALLOC version.
+
+        xdef    _lm_free                ; the entry point
+
+_lm_free:
+    IFD     DYN_ALLOC
+        move.l  _window,d0
+        beq.s   lf_no_window
+        move.l  d0,-(sp)
+        jsr     _free
+        addq    #4,sp
+        clr.l   _window
+lf_no_window:
+        move.l  _prev,d0
+        beq.s   lf_no_prev
+        move.l  d0,-(sp)
+        jsr     _free
+        move.l  _head,(sp)              ; reuse the same stack arg slot
+        jsr     _free
+        addq    #4,sp
+        clr.l   _prev
+        clr.l   _head
+lf_no_prev:
+    ENDC
+        rts
+
+; ============================================================================
+; void lm_init(int pack_level, unsigned short *flags) allocates dynamic arrays
+; if any, and initializes all variables so that deflate() is ready to go.
+
+        xdef    _lm_init                ; the entry point
+
+Level   equr    d2
+;Window equr    a2      ; as in deflate()
+    IFD     AMIGA
+INIREGS reg     d2/a2
+    ELSE
+INIREGS reg     d0-d2/a0-a1
+    ENDC
+
+_lm_init:
+        MOVINT  4(sp),d0
+        move.l  4+INTSIZE(sp),a0
+        movem.l INIREGS,-(sp)
+        move.w  d0,Level
+        cmp.w   #1,Level
+        blt.s   levelerr
+        bgt.s   try9
+        bset.b  #B_FAST,1(a0)
+try9:   cmp.w   #9,Level
+        bgt.s   levelerr
+        blt.s   levelok
+        bset.b  #B_SLOW,1(a0)
+        bra.s   levelok
+levelerr:
+        pea     level_message
+        jsr     _error                  ; never returns
+levelok:
+        clr.w   sliding
+        tst.l   _window_size
+        bne.s   gotawindowsize
+        move.w  #1,sliding
+        move.l  #2*WSIZE,_window_size
+gotawindowsize:
+
+        BASEPTR _window,Window
+    IFD     DYN_ALLOC
+        move.l  Window,d0               ; fake tst.l
+        bne.s   gotsomewind
+        CAL_SH  WSIZE
+        move.l  d0,Window
+        move.l  d0,_window
+        bne.s   gotsomewind
+        pea     window_message
+        MOVINT  #ZE_MEM,-(sp)
+        jsr     _ziperr                 ; never returns
+gotsomewind:
+        tst.l   _prev
+        bne.s   gotsomehead
+        CAL_SH  WSIZE
+        move.l  d0,_prev
+        beq.s   nohead
+        CAL_SH  HASH_SIZE
+        move.l  d0,_head
+        bne.s   gotfreshhead            ; newly calloc'd memory is zeroed
+nohead: pea     hash_message
+        MOVINT  #ZE_MEM,-(sp)
+        jsr     _ziperr                 ; never returns
+gotsomehead:
+    ENDC    ; DYN_ALLOC
+
+        move.w  #(HASH_SIZE/2)-1,d0     ; two shortwords per loop
+        BASEPTR _head,a0
+wipeh:  clr.l   (a0)+
+        dbra    d0,wipeh
+gotfreshhead:
+        move.l  Level,d0
+    IFEQ    Sizeof_config-8
+        asl.l   #3,d0
+    ELSE
+        mulu    #Sizeof_config,d0
+    ENDC
+        lea     config_table,a0
+        add.l   d0,a0
+        move.w  Max_lazy(a0),max_lazy_match
+        move.w  Good_length(a0),good_match
+        move.w  Nice_length(a0),nice_match
+        move.w  Max_chain(a0),max_chain_len
+        CLRINT  _strstart
+        clr.l   _block_start
+        bsr     match_init
+
+        clr.w   eofile
+        MOVINT  #WSIZE,-(sp)    ; We read only 32K because lookahead is short
+        move.l  Window,-(sp)    ; even when int size is long, as if deflate.c
+        move.l  _read_buf,a0    ; were compiled with MAXSEG_64K defined.
+        jsr     (a0)
+        addq    #4+INTSIZE,sp
+        move.w  d0,lookahead
+        beq.s   noread
+        cmp.w   #EOF,d0
+        bne.s   irefill
+noread: move.w  #1,eofile
+        clr.w   lookahead
+        bra.s   init_done
+
+irefill:
+        move.w  lookahead,d0
+        cmp.w   #MIN_LOOKAHEAD,d0
+        bhs.s   hashify
+        bsr     _fill_window            ; use the C-callable version
+hashify:
+        clr.w   ins_h
+        moveq   #MIN_MATCH-2,d0
+hash1:  move.b  (Window)+,d1
+        UP_HASH Level,d1
+        dbra    d0,hash1
+
+init_done:
+        movem.l (sp)+,INIREGS
+        rts
+
+; strings for error messages:
+hash_message    dc.b    'hash table allocation',0
+window_message  dc.b    'window allocation',0
+level_message   dc.b    'bad pack level',0
+
+        end
diff --git a/amiga/filedate.c b/amiga/filedate.c
new file mode 100644 (file)
index 0000000..84c7bed
--- /dev/null
@@ -0,0 +1,636 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* Low-level Amiga routines shared between Zip and UnZip.
+ *
+ * Contains:  FileDate()
+ *            locale_TZ()
+ *            getenv()          [Aztec C only; replaces bad C library versions]
+ *            setenv()          [ditto]
+ *            tzset()           [ditto]
+ *            gmtime()          [ditto]
+ *            localtime()       [ditto]
+ *            time()            [ditto]
+ *            sendpkt()
+ *            Agetch()
+ *
+ * The first nine are used by all Info-ZIP programs except fUnZip.
+ * The last two are used by all except the non-CRYPT version of fUnZip.
+ * Probably some of the stuff in here is unused by ZipNote and ZipSplit too...
+ * sendpkt() is used by Agetch() and FileDate(), and by windowheight() in
+ * amiga/amiga.c (UnZip).  time() is used only by Zip.
+ */
+
+
+/* HISTORY/CHANGES
+ *  2 Sep 92, Greg Roelofs, Original coding.
+ *  6 Sep 92, John Bush, Incorporated into UnZip 5.1
+ *  6 Sep 92, John Bush, Interlude "FileDate()" defined, which calls or
+ *            redefines SetFileDate() depending upon AMIGADOS2 definition.
+ * 11 Oct 92, John Bush, Eliminated AMIGADOS2 switch by determining
+ *            revision via OpenLibrary() call.  Now only one version of
+ *            the program runs on both platforms (1.3.x vs. 2.x)
+ * 11 Oct 92, John Bush, Merged with Zip version and changed arg passing
+ *            to take time_t input instead of struct DateStamp.
+ *            Arg passing made to conform with utime().
+ * 22 Nov 92, Paul Kienitz, fixed includes for Aztec and cleaned up some
+ *            lint-ish errors; simplified test for AmigaDOS version.
+ * 11 Nov 95, Paul Kienitz, added Agetch() for crypt password input and
+ *            UnZip's "More" prompt -- simplifies crypt.h and avoids
+ *            use of library code redundant with sendpkt().  Made it
+ *            available to fUnZip, which does not use FileDate().
+ * 22 Nov 95, Paul Kienitz, created a new tzset() that gets the current
+ *            timezone from the Locale preferences.  These exist only under
+ *            AmigaDOS 2.1 and up, but it is probably correctly set on more
+ *            Amigas than the TZ environment variable is.  We check that
+ *            only if TZ is not validly set.  We do not parse daylight
+ *            savings syntax except to check for presence vs. absence of a
+ *            DST part; United States rules are assumed.  This is better
+ *            than the tzset()s in the Amiga compilers' libraries do.
+ * 15 Jan 96, Chr. Spieler, corrected the logic when to select low level
+ *            sendpkt() (when FileDate(), Agetch() or windowheight() is used),
+ *            and AMIGA's Agetch() (CRYPT, and UnZip(SFX)'s UzpMorePause()).
+ * 10 Feb 96, Paul Kienitz, re-fiddled that selection logic again, moved
+ *            stuff around for clarity.
+ * 16 Mar 96, Paul Kienitz, created a replacement localtime() to go with the
+ *            new tzset(), because Aztec's is hopelessly broken.  Also
+ *            gmtime(), which localtime() calls.
+ * 12 Apr 96, Paul Kienitz, daylight savings was being handled incorrectly.
+ * 21 Apr 96, Paul Kienitz, had to replace time() as well, Aztec's returns
+ *            local time instead of GMT.  That's why their localtime() was bad,
+ *            because it assumed time_t was already local, and gmtime() was
+ *            the one that checked TZ.
+ * 23 Apr 96, Chr. Spieler, deactivated time() replacement for UnZip stuff.
+ *            Currently, the UnZip sources do not make use of time() (and do
+ *            not supply the working mktime() replacement, either!).
+ * 29 Apr 96, Paul Kienitz, created a replacement getenv() out of code that
+ *            was previously embedded in tzset(), for reliable global test
+ *            of whether TZ is set or not.
+ * 19 Jun 96, Haidinger Walter, re-adapted for current SAS/C compiler.
+ *  7 Jul 96, Paul Kienitz, smoothed together compiler-related changes.
+ *  4 Feb 97, Haidinger Walter, added set_TZ() for SAS/C.
+ * 23 Apr 97, Paul Kienitz, corrected Unix->Amiga DST error by adding
+ *            mkgmtime() so localtime() could be used.
+ * 28 Apr 97, Christian Spieler, deactivated mkgmtime() definition for ZIP;
+ *            the Zip sources supply this function as part of util.c.
+ * 24 May 97, Haidinger Walter, added time_lib support for SAS/C and moved
+ *            set_TZ() to time_lib.c.
+ * 12 Jul 97, Paul Kienitz, adapted time_lib stuff for Aztec.
+ * 26 Jul 97, Chr. Spieler, old mkgmtime() fixed (ydays[] def, sign vs unsign).
+ * 30 Dec 97, Haidinger Walter, adaptation for SAS/C using z-stat.h functions.
+ * 19 Feb 98, Haidinger Walter, removed alloc_remember, more SAS.C fixes.
+ * 23 Apr 98, Chr. Spieler, removed mkgmtime(), changed FileDate to convert to
+ *            Amiga file-time directly.
+ * 24 Apr 98, Paul Kienitz, clip Unix dates earlier than 1978 in FileDate().
+ * 02 Sep 98, Paul Kienitz, C. Spieler, always include zip.h to get a defined
+ *            header inclusion sequence that resolves all header dependencies.
+ */
+
+#ifndef __amiga_filedate_c
+#define __amiga_filedate_c
+
+
+#include "zip.h"
+#include <ctype.h>
+#include <errno.h>
+
+#include <exec/types.h>
+#include <exec/execbase.h>
+#include <exec/memory.h>
+
+#ifdef AZTEC_C
+#  include <libraries/dos.h>
+#  include <libraries/dosextens.h>
+#  include <clib/exec_protos.h>
+#  include <clib/dos_protos.h>
+#  include <clib/locale_protos.h>
+#  include <pragmas/exec_lib.h>
+#  include <pragmas/dos_lib.h>
+#  include <pragmas/locale_lib.h>
+#  define ESRCH  ENOENT
+#  define EOSERR EIO
+#endif
+
+#ifdef __SASC
+#  include <stdlib.h>
+#  if (defined(_M68020) && (!defined(__USE_SYSBASE)))
+                            /* on 68020 or higher processors it is faster   */
+#    define __USE_SYSBASE   /* to use the pragma libcall instead of syscall */
+#  endif                    /* to access functions of the exec.library      */
+#  include <proto/exec.h>   /* see SAS/C manual:part 2,chapter 2,pages 6-7  */
+#  include <proto/dos.h>
+#  include <proto/locale.h>
+#  ifdef DEBUG
+#     include <sprof.h>
+#  endif
+#  ifdef MWDEBUG
+#    include <stdio.h>      /* include both before memwatch.h again just */
+#    include <stdlib.h>     /* to be safe */
+#    include "memwatch.h"
+#  endif /* MWDEBUG */
+#endif /* __SASC */
+
+#include "crypt.h"            /* just so we can tell if CRYPT is supported */
+
+
+
+#ifndef FUNZIP
+
+#ifndef SUCCESS
+#  define SUCCESS (-1L)
+#  define FAILURE 0L
+#endif
+
+#define ReqVers 36L        /* required library version for SetFileDate() */
+#define ENVSIZE 100        /* max space allowed for an environment var   */
+
+extern struct ExecBase *SysBase;
+
+#ifndef USE_TIME_LIB
+#ifdef AZTEC_C                  /* should be pretty safe for reentrancy */
+   long timezone = 0;           /* already declared SAS/C external */
+   int daylight = 0;            /* likewise */
+#endif
+int real_timezone_is_set = FALSE;       /* set by tzset() */
+#endif /* !USE_TIME_LIB */
+
+/* prototypes */
+char *getenv(const char *var);
+#ifdef __SASC
+int setenv(const char *var, const char *value, int overwrite);
+/*  !!!!  We have really got to find a way to operate without this. */
+#endif
+
+LONG FileDate (char *filename, time_t u[]);
+LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
+int Agetch(void);
+
+/* prototypes for time replacement functions */
+#ifndef USE_TIME_LIB
+  void tzset(void);
+  int locale_TZ(void);
+  struct tm *gmtime(const time_t *when);
+  struct tm *localtime(const time_t *when);
+#  ifdef __SASC
+     extern void set_TZ(long time_zone, int day_light);  /* in time_lib.c */
+#  endif
+#  ifdef ZIP
+     time_t time(time_t *tp);
+#  endif
+#endif /* !USE_TIME_LIB */
+
+/* =============================================================== */
+
+/***********************/
+/* Function filedate() */
+/***********************/
+
+/*  FileDate() (originally utime.c), by Paul Wells.  Modified by John Bush
+ *  and others (see also sendpkt() comments, below); NewtWare SetFileDate()
+ *  clone cheaply ripped off from utime().
+ */
+
+/* DESCRIPTION
+ * This routine chooses between 2 methods to set the file date on AMIGA.
+ * Since AmigaDOS 2.x came out, SetFileDate() was available in ROM (v.36
+ * and higher).  Under AmigaDOS 1.3.x (less than v.36 ROM), SetFileDate()
+ * must be accomplished by constructing a message packet and sending it
+ * to the file system handler of the file to be stamped.
+ *
+ * The system's ROM version is extracted from the external system Library
+ * base.
+ *
+ * NOTE:  although argument passing conforms with utime(), note the
+ *        following differences:
+ *          - Return value is boolean success/failure.
+ *          - If a structure or array is passed, only the first value
+ *            is used, which *may* correspond to date accessed and not
+ *            date modified.
+ */
+
+/* Nonzero if `y' is a leap year, else zero. */
+#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
+
+/* Number of leap years from 1970 to `y' (not including `y' itself). */
+#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
+
+/* Accumulated number of days from 01-Jan up to start of current month. */
+#ifdef ZIP
+static const unsigned short ydays[] =
+{  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+#else
+extern const unsigned short ydays[];  /* in unzip's fileio.c */
+#endif
+
+LONG FileDate(filename, u)
+    char *filename;
+    time_t u[];
+{
+    LONG SetFileDate(UBYTE *filename, struct DateStamp *pDate);
+    LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
+    struct MsgPort *taskport;
+    BPTR dirlock, lock;
+    struct FileInfoBlock *fib;
+    LONG pktargs[4];
+    UBYTE *ptr;
+    long ret;
+
+    struct DateStamp pDate;
+    struct tm *ltm;
+    int years;
+
+    /* tzset(); */
+    /* Amiga file date is based on 01-Jan-1978 00:00:00 (local time):
+     * 8 years and 2 leapdays difference from Unix time.
+     */
+    ltm = localtime(&u[0]);
+    years = ltm->tm_year + 1900;
+    if (years < 1978)
+        pDate.ds_Days = pDate.ds_Minute = pDate.ds_Tick = 0;
+    else {
+        pDate.ds_Days = (years - 1978) * 365L + (nleap(years) - 2) +
+                        ((ltm->tm_mon > 1 && leap(years)) ? 1 : 0) +
+                        ydays[ltm->tm_mon] + (ltm->tm_mday - 1);
+        pDate.ds_Minute = ltm->tm_hour * 60 + ltm->tm_min;
+        pDate.ds_Tick = ltm->tm_sec * TICKS_PER_SECOND;
+    }
+
+    if (SysBase->LibNode.lib_Version >= ReqVers)
+    {
+        return (SetFileDate(filename,&pDate));  /* native routine at 2.0+ */
+    }
+    else  /* !(SysBase->lib_Version >=ReqVers) */
+    {
+        if( !(taskport = (struct MsgPort *)DeviceProc(filename)) )
+        {
+            errno = ESRCH;          /* no such process */
+            return FAILURE;
+        }
+
+        if( !(lock = Lock(filename,SHARED_LOCK)) )
+        {
+            errno = ENOENT;         /* no such file */
+            return FAILURE;
+        }
+
+        if( !(fib = (struct FileInfoBlock *)AllocMem(
+            (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) )
+        {
+            errno = ENOMEM;         /* insufficient memory */
+            UnLock(lock);
+            return FAILURE;
+        }
+
+        if( Examine(lock,fib)==FAILURE )
+        {
+            errno = EOSERR;         /* operating system error */
+            UnLock(lock);
+            FreeMem(fib,(long)sizeof(*fib));
+            return FAILURE;
+        }
+
+        dirlock = ParentDir(lock);
+        ptr = (UBYTE *)AllocMem(64L,MEMF_PUBLIC);
+        strcpy((ptr+1),fib->fib_FileName);
+        *ptr = strlen(fib->fib_FileName);
+        FreeMem(fib,(long)sizeof(*fib));
+        UnLock(lock);
+
+        /* now fill in argument array */
+
+        pktargs[0] = 0;
+        pktargs[1] = (LONG)dirlock;
+        pktargs[2] = (LONG)&ptr[0] >> 2;
+        pktargs[3] = (LONG)&pDate;
+
+        errno = ret = sendpkt(taskport,ACTION_SET_DATE,pktargs,4L);
+
+        FreeMem(ptr,64L);
+        UnLock(dirlock);
+
+        return SUCCESS;
+    }  /* ?(SysBase->lib_Version >= ReqVers) */
+} /* FileDate() */
+
+
+char *getenv(const char *var)         /* not reentrant! */
+{
+    static char space[ENVSIZE];
+    struct Process *me = (void *) FindTask(NULL);
+    void *old_window = me->pr_WindowPtr;
+    char *ret = NULL;
+
+    me->pr_WindowPtr = (void *) -1;   /* suppress any "Please insert" popups */
+    if (SysBase->LibNode.lib_Version >= ReqVers) {
+        if (GetVar((char *) var, space, ENVSIZE - 1, /* GVF_GLOBAL_ONLY */ 0) > 0)
+            ret = space;
+    } else {                    /* early AmigaDOS, get env var the crude way */
+        BPTR hand, foot, spine;
+        int z = 0;
+        if (foot = Lock("ENV:", ACCESS_READ)) {
+            spine = CurrentDir(foot);
+            if (hand = Open((char *) var, MODE_OLDFILE)) {
+                z = Read(hand, space, ENVSIZE - 1);
+                Close(hand);
+            }
+            UnLock(CurrentDir(spine));
+        }
+        if (z > 0) {
+            space[z] = '\0';
+            ret = space;
+        }
+    }
+    me->pr_WindowPtr = old_window;
+    return ret;
+}
+
+#ifdef __SASC
+int setenv(const char *var, const char *value, int overwrite)
+{
+    struct Process *me = (void *) FindTask(NULL);
+    void *old_window = me->pr_WindowPtr;
+    int ret = -1;
+
+    me->pr_WindowPtr = (void *) -1;   /* suppress any "Please insert" popups */
+    if (SysBase->LibNode.lib_Version >= ReqVers)
+        ret = !SetVar((char *) var, (char *) value, -1, GVF_GLOBAL_ONLY | LV_VAR);
+    else {
+        BPTR hand, foot, spine;
+        long len = value ? strlen(value) : 0;
+        if (foot = Lock("ENV:", ACCESS_READ)) {
+            spine = CurrentDir(foot);
+            if (len) {
+                if (hand = Open((char *) var, MODE_NEWFILE)) {
+                    ret = Write(hand, (char *) value, len + 1) >= len;
+                    Close(hand);
+                }
+            } else
+                ret = DeleteFile((char *) var);
+            UnLock(CurrentDir(spine));
+        }
+    }
+    me->pr_WindowPtr = old_window;
+    return ret;
+}
+#endif /* __SASC */
+
+
+#ifndef USE_TIME_LIB
+
+/* set timezone and daylight to settings found in locale.library */
+int locale_TZ(void)
+{
+    struct Library *LocaleBase;
+    struct Locale *ll;
+    struct Process *me = (void *) FindTask(NULL);
+    void *old_window = me->pr_WindowPtr;
+    BPTR eh;
+    int z, valid = FALSE;
+
+    /* read timezone from locale.library if TZ envvar missing */
+    me->pr_WindowPtr = (void *) -1;   /* suppress any "Please insert" popups */
+    if (LocaleBase = OpenLibrary("locale.library", 0)) {
+        if (ll = OpenLocale(NULL)) {
+            z = ll->loc_GMTOffset;
+            if (z == -300) {
+                if (eh = Lock("ENV:sys/locale.prefs", ACCESS_READ))
+                    UnLock(eh);
+                else
+                    z = 300; /* bug: locale not initialized, default is bogus! */
+            } else
+                real_timezone_is_set = TRUE;
+            timezone = z * 60;
+            daylight = (z >= 4*60 && z <= 9*60);    /* apply in the Americas */
+            valid = TRUE;
+            CloseLocale(ll);
+        }
+        CloseLibrary(LocaleBase);
+    }
+    me->pr_WindowPtr = old_window;
+    return valid;
+}
+
+void tzset(void)
+{
+    char *p,*TZstring;
+    int z,valid = FALSE;
+
+    if (real_timezone_is_set)
+        return;
+    timezone = 0;       /* default is GMT0 which means no offsets */
+    daylight = 0;       /* from local system time                 */
+    TZstring = getenv("TZ");              /* read TZ envvar */
+    if (TZstring && TZstring[0]) {        /* TZ exists and has contents? */
+        z = 3600;
+        for (p = TZstring; *p && !isdigit(*p) && *p != '-'; p++) ;
+        if (*p == '-')
+            z = -3600, p++;
+        if (*p) {
+            timezone = 0;
+            do {
+                while (isdigit(*p))
+                    timezone = timezone * 10 + z * (*p++ - '0'), valid = TRUE;
+                if (*p == ':') p++;
+            } while (isdigit(*p) && (z /= 60) > 0);
+        }
+        while (isspace(*p)) p++;                      /* probably not needed */
+        if (valid) {
+            real_timezone_is_set = TRUE;
+            daylight = !!*p;                       /* a DST name part exists */
+        }
+    }
+    if (!valid)
+        locale_TZ();               /* read locale.library */
+#ifdef __SASC
+    /* Some SAS/C library functions, e.g. stat(), call library     */
+    /* __tzset() themselves. So envvar TZ *must* exist in order to */
+    /* to get the right offset from GMT.  XXX  WE SHOULD TRY HARD  */
+    /* find and replace any remaining functions that need this!    */
+    set_TZ(timezone, daylight);
+#endif /* __SASC */
+}
+
+
+struct tm *gmtime(const time_t *when)
+{
+    static struct tm tbuf;   /* this function is intrinsically non-reentrant */
+    static short smods[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+    long days = *when / 86400;
+    long secs = *when % 86400;
+    short yell, yday;
+
+    tbuf.tm_wday = (days + 4) % 7;                   /* 1/1/70 is a Thursday */
+    tbuf.tm_year = 70 + 4 * (days / 1461);
+    yday = days % 1461;
+    while (yday >= (yell = (tbuf.tm_year & 3 ? 365 : 366)))
+        yday -= yell, tbuf.tm_year++;
+    smods[1] = (tbuf.tm_year & 3 ? 28 : 29);
+    tbuf.tm_mon = 0;
+    tbuf.tm_yday = yday;
+    while (yday >= smods[tbuf.tm_mon])
+        yday -= smods[tbuf.tm_mon++];
+    tbuf.tm_mday = yday + 1;
+    tbuf.tm_isdst = 0;
+    tbuf.tm_sec = secs % 60;
+    tbuf.tm_min = (secs / 60) % 60;
+    tbuf.tm_hour = secs / 3600;
+#ifdef AZTEC_C
+    tbuf.tm_hsec = 0;                   /* this field exists for Aztec only */
+#endif
+    return &tbuf;
+}
+
+struct tm *localtime(const time_t *when)
+{
+    struct tm *t;
+    time_t localwhen;
+    int dst = FALSE, sundays, lastweekday;
+
+    tzset();
+    localwhen = *when - timezone;
+    t = gmtime(&localwhen);
+    /* So far we support daylight savings correction by the USA rule only: */
+    if (daylight && t->tm_mon >= 3 && t->tm_mon <= 9) {
+        if (t->tm_mon > 3 && t->tm_mon < 9)      /* May Jun Jul Aug Sep: yes */
+            dst = TRUE;
+        else {
+            sundays = (t->tm_mday + 6 - t->tm_wday) / 7;
+            if (t->tm_wday == 0 && t->tm_hour < 2 && sundays)
+                sundays--;           /* a Sunday does not count until 2:00am */
+            if (t->tm_mon == 3 && sundays > 0)      /* first sunday in April */
+                dst = TRUE;
+            else if (t->tm_mon == 9) {
+                lastweekday = (t->tm_wday + 31 - t->tm_mday) % 7;
+                if (sundays < (37 - lastweekday) / 7)
+                    dst = TRUE;                    /* last sunday in October */
+            }
+        }
+        if (dst) {
+            localwhen += 3600;
+            t = gmtime(&localwhen);                   /* crude but effective */
+            t->tm_isdst = 1;
+        }
+    }
+    return t;
+}
+
+
+#  ifdef ZIP
+time_t time(time_t *tp)
+{
+    time_t t;
+    struct DateStamp ds;
+    DateStamp(&ds);
+    t = ds.ds_Tick / TICKS_PER_SECOND + ds.ds_Minute * 60
+                                      + (ds.ds_Days + 2922) * 86400;
+    t = mktime(gmtime(&t));
+    /* gmtime leaves ds in the local timezone, mktime converts it to GMT */
+    if (tp) *tp = t;
+    return t;
+}
+#  endif /* ZIP */
+#endif /* !USE_TIME_LIB */
+
+#endif /* !FUNZIP */
+
+
+#if CRYPT || !defined(FUNZIP)
+
+/*  sendpkt.c
+ *  by A. Finkel, P. Lindsay, C. Sheppner
+ *  returns Res1 of the reply packet
+ */
+/*
+#include <exec/types.h>
+#include <exec/memory.h>
+#include <libraries/dos.h>
+#include <libraries/dosextens.h>
+#include <proto/exec.h>
+#include <proto/dos.h>
+*/
+
+LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
+
+LONG sendpkt(pid,action,args,nargs)
+struct MsgPort *pid;           /* process identifier (handler message port) */
+LONG action,                   /* packet type (desired action)              */
+     *args,                    /* a pointer to argument list                */
+     nargs;                    /* number of arguments in list               */
+{
+
+    struct MsgPort *replyport, *CreatePort(UBYTE *, long);
+    void DeletePort(struct MsgPort *);
+    struct StandardPacket *packet;
+    LONG count, *pargs, res1;
+
+    replyport = CreatePort(NULL,0L);
+    if( !replyport ) return(0);
+
+    packet = (struct StandardPacket *)AllocMem(
+            (long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);
+    if( !packet )
+    {
+        DeletePort(replyport);
+        return(0);
+    }
+
+    packet->sp_Msg.mn_Node.ln_Name  = (char *)&(packet->sp_Pkt);
+    packet->sp_Pkt.dp_Link          = &(packet->sp_Msg);
+    packet->sp_Pkt.dp_Port          = replyport;
+    packet->sp_Pkt.dp_Type          = action;
+
+    /* copy the args into the packet */
+    pargs = &(packet->sp_Pkt.dp_Arg1);      /* address of 1st argument */
+    for( count=0; count<nargs; count++ )
+        pargs[count] = args[count];
+
+    PutMsg(pid,(struct Message *)packet);   /* send packet */
+
+    WaitPort(replyport);
+    GetMsg(replyport);
+
+    res1 = packet->sp_Pkt.dp_Res1;
+
+    FreeMem((char *)packet,(long)sizeof(*packet));
+    DeletePort(replyport);
+
+    return(res1);
+
+} /* sendpkt() */
+
+#endif /* CRYPT || !FUNZIP */
+
+
+#if CRYPT || (defined(UNZIP) && !defined(FUNZIP))
+
+/* Agetch() reads one raw keystroke -- uses sendpkt() */
+
+int Agetch(void)
+{
+    LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
+    struct Task *me = FindTask(NULL);
+    struct CommandLineInterface *cli = BADDR(((struct Process *) me)->pr_CLI);
+    BPTR fh = cli->cli_StandardInput;   /* this is immune to < redirection */
+    void *conp = ((struct FileHandle *) BADDR(fh))->fh_Type;
+    char longspace[8];
+    long *flag = (long *) ((ULONG) &longspace[4] & ~3); /* LONGWORD ALIGNED! */
+    UBYTE c;
+
+    *flag = 1;
+    sendpkt(conp, ACTION_SCREEN_MODE, flag, 1);         /* assume success */
+    Read(fh, &c, 1);
+    *flag = 0;
+    sendpkt(conp, ACTION_SCREEN_MODE, flag, 1);
+    if (c == 3)                                         /* ^C in input */
+        Signal(me, SIGBREAKF_CTRL_C);
+    return c;
+}
+
+#endif /* CRYPT || (UNZIP && !FUNZIP) */
+
+#endif /* __amiga_filedate_c*/
diff --git a/amiga/makefile.azt b/amiga/makefile.azt
new file mode 100644 (file)
index 0000000..08f1cee
--- /dev/null
@@ -0,0 +1,282 @@
+# Makefile for Zip, ZipNote, ZipCloak, ZipSplit for Aztec C 5.2
+# Also ZipLM, a version of Zip that needs much less free memory
+#   -- Paul Kienitz, last updated 25 Jun 98
+
+# Make sure platform is defined correctly, and select memory usage options:
+DEFINES = -d AMIGA -d DYN_ALLOC -d ASM_CRC
+# ASM_CRC now serves only as a notation for "Zip -L".
+
+CC = cc
+AS = as
+CFLAGS = -psb0e -sabfmnpu -wcr0u $(DEFINES)
+# -pbs means unsigned chars and short ints, -sabfmnpu is various small
+# optimizations, -wcr0u adjusts type checking strictness
+
+CFLAGD = -bs -psb0e -s0f0n -wcr0u $(DEFINES)
+# -bs is include source debugging info, -s0f0n is avoid hard-to-debug optimizations
+
+WSIZ = WSIZE=4096
+LOWFLAGS = $(CFLAGS) -d $(WSIZ) -d SMALL_MEM
+# used for compiling a low-memory-use version of Zip
+
+LOWFLAGD = $(CFLAGD) -d $(WSIZ) -d SMALL_MEM
+# for the debuggable low-memory-use version
+
+ASOPTS = -n -eAMIGA -eDYN_ALLOC -eCPUTEST -eINT16
+LOWASOPTS = $(ASOPTS) -e$(WSIZ) -eSMALL_MEM
+# Options used for assembling amiga/deflate.a; must generally match the
+# settings in DEFINES.  LOWASOPTS are for the low-memory version.
+
+LD = ln
+LDLIBS = -lc16
+LDFLAGS = -m +q
+
+LDFLAGD = -m +q -g -w
+
+
+# default C rules
+.c.o :
+       $(CC) $(CFLAGS) -o $@ $*.c
+
+# rules for routines containing entries needed by utilities
+.c.oo :
+       $(CC) $(CFLAGS) -d UTIL -o $@ $*.c
+
+# rules for the low-memory version:
+
+.c.ol :
+       $(CC) $(LOWFLAGS) -o $@ $*.c
+
+# default C rules for debugging
+.c.od :
+       $(CC) $(CFLAGD) -o $@ $*.c
+
+# debugging rules for routines containing entries needed by utilities
+.c.dd :
+       $(CC) $(CFLAGD) -d UTIL -o $@ $*.c
+
+# rules for the low-memory version:
+
+.c.dl :
+       $(CC) $(LOWFLAGD) -o $@ $*.c
+
+
+# object file lists
+
+ZIP_H = zip.h ziperr.h tailor.h amiga/osdep.h amiga/z-stat.h amiga/z-time.h
+
+
+OBJZ = zip.o deflate.o trees.o zipfile.o zipup.o util.o \
+        fileio.o globals.o amiga/amiga.o amiga/amigazip.o amiga/crc_68.o \
+        amiga/time_lib.o crctab.o crypt.o ttyio.o
+
+OBJL = zip.ol deflate.ol trees.ol zipfile.ol \
+        zipup.ol util.ol fileio.ol globals.ol crypt.ol ttyio.ol crctab.ol \
+        amiga/amiga.ol amiga/amigazip.ol amiga/crc_68.o amiga/time_lib.o
+
+OBJU = zipfile.oo fileio.oo util.oo globals.o amiga/amiga.oo \
+        amiga/amigazip.oo amiga/time_lib.o
+OBJN = zipnote.o  $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt.oo ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+# These are the debuggable versions:
+
+DBJZ = zip.od deflate.od trees.od zipfile.od zipup.od \
+        util.od fileio.od globals.od amiga/amiga.od amiga/amigazip.od \
+        amiga/crc_68.o amiga/time_lib.od crctab.od crypt.od ttyio.od
+
+DBJL = zip.dl deflate.dl trees.dl zipfile.dl zipup.dl util.dl \
+        fileio.dl globals.dl amiga/amiga.dl amiga/amigazip.dl amiga/crc_68.o \
+        amiga/time_lib.od crctab.dl crypt.dl ttyio.dl
+
+DBJU = zipfile.dd fileio.dd util.dd globals.od amiga/amiga.dd \
+        amiga/amigazip.dd amiga/time_lib.od
+DBJN = zipnote.od  $(DBJU)
+DBJC = zipcloak.od $(DBJU) crctab.od crypt.dd ttyio.od
+DBJS = zipsplit.od $(DBJU)
+
+
+#  HERE WE GO:
+
+all : Zip ZipNote ZipSplit ZipCloak
+
+z : Zip
+
+n : ZipNote
+
+s : ZipSplit
+
+c : ZipCloak
+
+l : ZipLM
+
+# Debug versions:
+
+dall : Zip.dbg ZipNote.dbg ZipSplit.dbg ZipCloak.dbg
+
+dz : Zip.dbg
+
+dn : ZipNote.dbg
+
+ds : ZipSplit.dbg
+
+dc : ZipCloak.dbg
+
+dl : ZipLM.dbg
+
+
+Zip : $(OBJZ) $(ZIP_H)
+       $(LD) $(LDFLAGS) -o $@ $(OBJZ) $(LDLIBS)
+       -@delete Zip.dbg
+
+ZipNote : $(OBJN) $(ZIP_H)
+       $(LD) $(LDFLAGS) -o $@ $(OBJN) $(LDLIBS)
+       -@delete ZipNote.dbg
+
+ZipSplit : $(OBJS) $(ZIP_H)
+       $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
+       -@delete ZipSplit.dbg
+
+ZipCloak : $(OBJC) $(ZIP_H)
+       $(LD) $(LDFLAGS) -o $@ $(OBJC) $(LDLIBS)
+       -@delete ZipCloak.dbg
+
+ZipLM : $(OBJL) $(ZIP_H)
+       $(LD) $(LDFLAGS) -o $@ $(OBJL) $(LDLIBS)
+       -@delete ZipLM.dbg
+
+
+Zip.dbg : $(DBJZ) $(ZIP_H)
+       $(LD) $(LDFLAGD) -o Zip $(DBJZ) $(LDLIBS)
+
+ZipNote.dbg : $(DBJN) $(ZIP_H)
+       $(LD) $(LDFLAGD) -o ZipNote $(DBJN) $(LDLIBS)
+
+ZipSplit.dbg : $(DBJS) $(ZIP_H)
+       $(LD) $(LDFLAGD) -o ZipSplit $(DBJS) $(LDLIBS)
+
+ZipCloak.dbg : $(DBJC) $(ZIP_H)
+       $(LD) $(LDFLAGD) -o ZipCloak $(DBJC) $(LDLIBS)
+
+ZipLM.dbg : $(DBJL) $(ZIP_H)
+       $(LD) $(LDFLAGD) -o ZipLM $(DBJL) $(LDLIBS)
+
+
+clean : bugclean
+       -delete quiet $(OBJZ)
+       -delete quiet $(OBJL)
+       -delete quiet zipnote.o zipcloak.o zipsplit.o \
+                       crypt.oo $(OBJU)
+
+bugclean :
+       -delete quiet $(DBJZ)
+       -delete quiet $(DBJL)
+       -delete quiet zipnote.od zipcloak.od zipsplit.od \
+                       crypt.dd $(DBJU)
+
+cleaner : clean
+       -delete quiet Zip ZipNote ZipSplit ZipCloak ZipLM
+       -delete quiet Zip.dbg ZipNote.dbg ZipSplit.dbg ZipCloak.dbg ZipLM.dbg
+
+
+# header dependencies:
+
+zip.o zipnote.o zipcloak.o zipsplit.o crypt.o ttyio.o deflate.o \
+   trees.o zipfile.o zipup.o fileio.o util.o crctab.o \
+   globals.o amiga/amiga.o : $(ZIP_H)
+
+zip.ol zipnote.ol zipcloak.ol zipsplit.ol crypt.ol ttyio.ol deflate.ol \
+   trees.ol zipfile.ol zipup.ol fileio.ol util.ol crctab.ol \
+   globals.ol amiga/amiga.ol : $(ZIP_H)
+
+crypt.oo zipfile.oo fileio.oo util.oo : $(ZIP_H)
+
+amiga/amigazip.o amiga/amigazip.ol amiga/amigazip.oo : amiga/amiga.h $(ZIP_H)
+
+zip.o zipnote.o zipcloak.o zipsplit.o zipup.o \
+   zip.ol zipnote.ol zipcloak.ol zipsplit.ol zipup.ol : revision.h
+
+amiga/amiga.o amiga/amiga.ol : crypt.h
+
+crypt.o crypt.oo crypt.ol ttyio.o ttyio.ol zipcloak.o zipcloak.ol \
+   zip.o zip.ol zipup.o zipup.ol : crypt.h ttyio.h
+
+zipup.o zipup.ol : amiga/zipup.h
+
+
+# SPECIAL CASES:
+
+# -mr changes expression parsing; avoids a bogus "expression too complex" error:
+trees.o : trees.c
+       $(CC) $(CFLAGS) -mr -o $@ trees.c
+
+trees.ol : trees.c
+       $(CC) $(LOWFLAGS) -mr -o $@ trees.c
+
+trees.od : trees.c
+       $(CC) $(CFLAGD) -mr -o $@ trees.c
+
+trees.ld : trees.c
+       $(CC) $(LOWFLAGD) -mr -o $@ trees.c
+
+# Substitute the assembly version of deflate.c: (but not in debug version)
+deflate.o : amiga/deflate.a
+       $(AS) $(ASOPTS) -o $@ amiga/deflate.a
+
+deflate.ol : amiga/deflate.a
+       $(AS) $(LOWASOPTS) -o $@ amiga/deflate.a
+
+# The assembly CRC function:
+amiga/crc_68.o : amiga/crc_68.a
+       $(AS) -n -o $@ amiga/crc_68.a
+
+# Put the Amiga internal version data with today's date into amiga.c:
+amiga/amiga.o : amiga/amiga.c amiga/filedate.c amiga/stat.c
+       rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'"
+       $(CC) $(CFLAGS) -o $@ amiga/amiga.c
+       delete env:VersionDate
+
+amiga/amiga.ol : amiga/amiga.c amiga/filedate.c amiga/stat.c
+       rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'"
+       $(CC) $(LOWFLAGS) -o $@ amiga/amiga.c
+       delete env:VersionDate
+
+amiga/amiga.od : amiga/amiga.c amiga/filedate.c amiga/stat.c
+       rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'"
+       $(CC) $(CFLAGD) -o $@ amiga/amiga.c
+       delete env:VersionDate
+
+amiga/amiga.ld : amiga/amiga.c amiga/filedate.c amiga/stat.c
+       rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'"
+       $(CC) $(LOWFLAGD) -o $@ amiga/amiga.c
+       delete env:VersionDate
+
+amiga/amiga.oo : amiga/amiga.c amiga/filedate.c amiga/stat.c
+       rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'"
+       $(CC) $(CFLAGS) -d UTIL -o $@ amiga/amiga.c
+       delete env:VersionDate
+
+amiga/amiga.dd : amiga/amiga.c amiga/filedate.c amiga/stat.c
+       rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'"
+       $(CC) $(CFLAGD) -d UTIL -o $@ amiga/amiga.c
+       delete env:VersionDate
+
+# Put the compiler version number into amigazip.c:
+amiga/amigazip.o : amiga/amigazip.c
+       $(CC) $(CFLAGS) -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c
+
+amiga/amigazip.ol : amiga/amigazip.c
+       $(CC) $(LOWFLAGS) -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c
+
+amiga/amigazip.od : amiga/amigazip.c
+       $(CC) $(CFLAGD) -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c
+
+amiga/amigazip.ld : amiga/amigazip.c
+       $(CC) $(LOWFLAGD) -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c
+
+amiga/amigazip.oo : amiga/amigazip.c
+       $(CC) $(CFLAGS) -d UTIL -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c
+
+amiga/amigazip.dd : amiga/amigazip.c
+       $(CC) $(CFLAGD) -d UTIL -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c
diff --git a/amiga/match.a b/amiga/match.a
new file mode 100644 (file)
index 0000000..ec5bcf0
--- /dev/null
@@ -0,0 +1,182 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; match.a -- optional optimized asm version of longest match in deflate.c
+; Written by Jean-loup Gailly
+; Adapted for the Amiga by Carsten Steger <stegerc@informatik.tu-muenchen.de>
+; using the code in match.S.
+; The major change in this code consists of removing all unaligned
+; word accesses, because they cause 68000-based Amigas to crash.
+; For maximum speed, UNALIGNED_OK can be defined in Makefile.sasc.
+; The program will then only run on 68020-based Amigas, though.
+; If you have reduced WSIZE in zip.h, then make sure this is
+; assembled with an equivalent -dWSIZE=<whatever>.
+;
+; This code will run with registerized parameters too, unless SAS
+; changes parameter passing conventions between new releases of SAS/C.
+
+
+Cur_Match       reg     d0      ; Must be in d0!
+Best_Len        reg     d1
+Loop_Counter    reg     d2
+Scan_Start      reg     d3
+Scan_End        reg     d4
+Limit           reg     d5
+Chain_Length    reg     d6
+Scan_Test       reg     d7
+Scan            reg     a0
+Match           reg     a1
+Prev_Address    reg     a2
+Scan_Ini        reg     a3
+Match_Ini       reg     a4
+
+MAX_MATCH       equ     258
+MIN_MATCH       equ     3
+        ifnd    WSIZE
+WSIZE           equ     32768
+        endc
+MAX_DIST        equ     WSIZE-MAX_MATCH-MIN_MATCH-1
+
+
+        xref    _max_chain_length
+        xref    _prev_length
+        xref    _prev
+        xref    _window
+        xref    _strstart
+        xref    _good_match
+        xref    _match_start
+        xref    _nice_match
+
+
+        section match,code
+
+        xdef    _match_init
+        xdef    @match_init
+        xdef    _longest_match
+        xdef    @longest_match
+
+
+_match_init:
+@match_init:
+        rts
+
+
+_longest_match:
+        move.l  4(sp),Cur_Match
+@longest_match:
+        ifd     UNALIGNED_OK
+        movem.l d2-d6/a2-a4,-(sp)
+        else
+        movem.l d2-d7/a2-a4,-(sp)
+        endc
+        move.l  _max_chain_length,Chain_Length
+        move.l  _prev_length,Best_Len
+        lea     _prev,Prev_Address
+        lea     _window+MIN_MATCH,Match_Ini
+        move.l  _strstart,Limit
+        move.l  Match_Ini,Scan_Ini
+        add.l   Limit,Scan_Ini
+        subi.w  #MAX_DIST,Limit
+        bhi.b   limit_ok
+        moveq   #0,Limit
+limit_ok:
+        cmp.l   _good_match,Best_Len
+        bcs.b   length_ok
+        lsr.l   #2,Chain_Length
+length_ok:
+        subq.l  #1,Chain_Length
+
+        ifd     UNALIGNED_OK
+
+        move.w  -MIN_MATCH(Scan_Ini),Scan_Start
+        move.w  -MIN_MATCH-1(Scan_Ini,Best_Len.L),Scan_End
+
+        else
+
+        move.b  -MIN_MATCH(Scan_Ini),Scan_Start
+        lsl.w   #8,Scan_Start
+        move.b  -MIN_MATCH+1(Scan_Ini),Scan_Start
+        move.b  -MIN_MATCH-1(Scan_Ini,Best_Len.L),Scan_End
+        lsl.w   #8,Scan_End
+        move.b  -MIN_MATCH(Scan_Ini,Best_Len.L),Scan_End
+
+        endc
+
+        bra.b   do_scan
+
+long_loop:
+
+        ifd     UNALIGNED_OK
+
+        move.w  -MIN_MATCH-1(Scan_Ini,Best_Len.L),Scan_End
+
+        else
+
+        move.b  -MIN_MATCH-1(Scan_Ini,Best_Len.L),Scan_End
+        lsl.w   #8,Scan_End
+        move.b  -MIN_MATCH(Scan_Ini,Best_Len.L),Scan_End
+
+        endc
+
+short_loop:
+        lsl.w   #1,Cur_Match
+        move.w  0(Prev_Address,Cur_Match.L),Cur_Match
+        cmp.w   Limit,Cur_Match
+        dbls    Chain_Length,do_scan
+        bra.b   return
+
+do_scan:
+        move.l  Match_Ini,Match
+        add.l   Cur_Match,Match
+
+        ifd     UNALIGNED_OK
+
+        cmp.w   -MIN_MATCH-1(Match,Best_Len.L),Scan_End
+        bne.b   short_loop
+        cmp.w   -MIN_MATCH(Match),Scan_Start
+        bne.b   short_loop
+
+        else
+
+        move.b  -MIN_MATCH-1(Match,Best_Len.L),Scan_Test
+        lsl.w   #8,Scan_Test
+        move.b  -MIN_MATCH(Match,Best_Len.L),Scan_Test
+        cmp.w   Scan_Test,Scan_End
+        bne.b   short_loop
+        move.b  -MIN_MATCH(Match),Scan_Test
+        lsl.w   #8,Scan_Test
+        move.b  -MIN_MATCH+1(Match),Scan_Test
+        cmp.w   Scan_Test,Scan_Start
+        bne.b   short_loop
+
+        endc
+
+        move.w  #(MAX_MATCH-MIN_MATCH),Loop_Counter
+        move.l  Scan_Ini,Scan
+scan_loop:
+        cmpm.b  (Match)+,(Scan)+
+        dbne    Loop_Counter,scan_loop
+
+        sub.l   Scan_Ini,Scan
+        addq.l  #(MIN_MATCH-1),Scan
+        cmp.l   Best_Len,Scan
+        bls.b   short_loop
+        move.l  Scan,Best_Len
+        move.l  Cur_Match,_match_start
+        cmp.l   _nice_match,Best_Len
+        bcs.b   long_loop
+return:
+        move.l  Best_Len,d0
+        ifd     UNALIGNED_OK
+        movem.l (sp)+,d2-d6/a2-a4
+        else
+        movem.l (sp)+,d2-d7/a2-a4
+        endc
+        rts
+
+        end
diff --git a/amiga/match_68.a b/amiga/match_68.a
new file mode 100644 (file)
index 0000000..d1a6c39
--- /dev/null
@@ -0,0 +1,273 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; This is a 68000 assembly language version of the Zip function
+; longest_match().  It is written for any 680x0 based computer, but at this
+; time the feature for runtime testing of CPU type is only supported for the
+; Amiga.  Hopefully a similar test for the Macintosh is possible, and for any
+; other system that supports both 68000 and 68020+ CPUs.  This is written by
+; Paul Kienitz, partially derived from a simpler version by Carsten Steger,
+; derived in turn from a 386 assembly function by Jean-loup Gailly and Kai Uwe
+; Rommel... but also based directly on the C original.
+;
+; The main difference of this from other longest_match() implementations is
+; that it includes both byte based and word based versions of the function,
+; and various symbols can be defined to select whether to use one routine or
+; the other, or to do a platform-specific test at runtime.  The symbols that
+; can be used to select behavior are as follows:
+;
+;   CPU020     if defined, use 68020 instructions always
+;   CPUTEST    if defined, check at runtime for CPU type.  Another symbol
+;               specifying the platform-specific test must be used with this.
+;               If neither of these is defined, use 68000 instructions only.
+;   AMIGA      use Amiga-specific test for 68020, if CPUTEST defined.  Also
+;               tells it to let a0/a1/d1 be clobbered by functions.
+;   ATSIGN     define entry symbols in @foo form as well as _foo, with
+;               @longest_match taking its parm in d0 instead of on the stack.
+;   WSIZE      if defined, determines the sliding window size for deflate;
+;               the default is 32K. If you have reduced WSIZE for the C code,
+;               make sure that this module is assembled with an equivalent
+;               "-dWSIZE=<whatever>" (or "-e...") switch.
+;
+; NOTE: no provision is made for 16 bit ints.  All external int variables are
+; treated as 32 bit values.  This also assumes that longest_match's result is
+; returned in D0.
+
+        IFND    CPU020
+        IFND    CPUTEST
+CPU000  equ     1
+        ENDC
+        ENDC
+
+; global variables:
+        xref    _max_chain_length   ; unsigned int
+        xref    _prev_length        ; unsigned int
+        xref    _match_start        ; unsigned int
+        xref    _strstart           ; unsigned int
+        xref    _good_match         ; signed int
+        xref    _nice_match         ; signed int
+        xref    _window             ; array of unsigned char
+        xref    _prev               ; array of unsigned short
+
+; our entry points:
+        xdef    _match_init         ; void match_init(void);
+        xdef    _longest_match      ; int longest_match(unsigned cur_match);
+        IFD     ATSIGN
+        xdef    @match_init         ; for SAS assembler
+        xdef    @longest_match      ; ditto
+        ENDC
+
+; flag variable for remembering CPU type:
+        IFD     CPUTEST
+        section cpuflag,data
+is020:  ds.w    1
+        ENDC
+
+
+        section match,code
+_match_init:
+        IFD    ATSIGN
+@match_init:
+        ENDC
+
+        IFD     CPUTEST         ; now check for platform type
+        IFD     AMIGA           ; Amiga specific test for '020 CPU:
+
+        xref    _SysBase
+
+        NOLIST
+        INCLUDE       'exec/execbase.i'
+        LIST
+
+        clr.w   is020           ; default value is 68000
+        move.l  _SysBase,a0
+        btst    #AFB_68020,AttnFlags+1(a0)
+        beq.s   cheap
+        move.w  #1,is020
+
+cheap:
+        ELSE ; !AMIGA
+
+ !!   Write an '020-detector for your system here!
+
+        ENDC ; AMIGA
+        ENDC ; CPUTEST
+        rts                ; match_init consists only of rts if CPUTEST unset
+
+
+        IFD     AMIGA
+SAVEREGS        reg     d3-d7/a2/a3/a5      ; don't protect d0/d1/a0/a1
+        ELSE
+SAVEREGS        reg     d1/d3-d7/a0-a3/a5   ; protect all but d0 return val
+        ENDC
+
+Cur_Match       equr    d0                  ; Must be in d0!
+Best_Len        equr    d1
+Scan_Start      equr    d3
+Scan_End        equr    d4
+Limit           equr    d5
+Chain_Length    equr    d6
+Scan_Test       equr    d7
+Scan            equr    a0
+Match           equr    a1
+Prev_Address    equr    a2
+Scan_Ini        equr    a3
+Match_Ini       equr    a5
+
+
+MAX_MATCH       equ     258
+MIN_MATCH       equ     3
+        IFND    WSIZE
+WSIZE           equ     32768
+        ENDC
+MAX_DIST        equ     WSIZE-MAX_MATCH-MIN_MATCH-1
+
+_longest_match:
+        move.l  4(sp),Cur_Match         ; stack arg to register
+        IFD     ATSIGN
+@longest_match:
+        ENDC
+        movem.l SAVEREGS,-(sp)
+
+; setup steps common to byte and word versions:
+        move.l  _max_chain_length,Chain_Length
+        move.l  _prev_length,Best_Len
+        lea     _prev,Prev_Address
+        lea     _window,Match_Ini
+        move.l  _strstart,Limit
+        move.l  Match_Ini,Scan_Ini
+        addq    #MIN_MATCH,Match_Ini
+        add.l   Limit,Scan_Ini
+        subi.w  #MAX_DIST,Limit
+        bhi.s   limit_ok
+        moveq   #0,Limit
+limit_ok:
+        cmp.l   _good_match,Best_Len
+        bcs.s   length_ok
+        lsr.l   #2,Chain_Length
+length_ok:
+        subq.l  #1,Chain_Length
+
+        IFD     CPUTEST
+        tst.w   is020               ; can we use '020 stuff today?
+        bne     WORD_match
+        ENDC
+
+        IFND    CPU020
+
+; for 68000 or 68010, use byte operations:
+        moveq   #0,Scan_Start       ; clear 2nd and 4th bytes, use 1st & 3rd
+        moveq   #0,Scan_End
+        moveq   #0,Scan_Test
+        move.b  (Scan_Ini),Scan_Start
+        swap    Scan_Start
+        move.b  1(Scan_Ini),Scan_Start
+        move.b  -1(Scan_Ini,Best_Len),Scan_End
+        swap    Scan_End
+        move.b  0(Scan_Ini,Best_Len),Scan_End
+        bra.s   bdo_scan
+
+blong_loop:
+        move.b  -1(Scan_Ini,Best_Len),Scan_End
+        swap    Scan_End
+        move.b  0(Scan_Ini,Best_Len),Scan_End
+
+bshort_loop:
+        add.w   Cur_Match,Cur_Match
+        move.w  0(Prev_Address,Cur_Match.l),Cur_Match
+        cmp.l   Limit,Cur_Match
+        dbls    Chain_Length,bdo_scan
+        bra     return
+
+bdo_scan:
+        move.l  Match_Ini,Match
+        add.l   Cur_Match,Match
+        move.b  -MIN_MATCH-1(Match,Best_Len),Scan_Test
+        swap    Scan_Test
+        move.b  -MIN_MATCH(Match,Best_Len),Scan_Test
+        cmp.l   Scan_Test,Scan_End
+        bne.s   bshort_loop
+        move.b  -MIN_MATCH(Match),Scan_Test
+        swap    Scan_Test
+        move.b  -MIN_MATCH+1(Match),Scan_Test
+        cmp.l   Scan_Test,Scan_Start
+        bne.s   bshort_loop
+        move.w  #(MAX_MATCH-MIN_MATCH),Scan_Test
+        lea     MIN_MATCH(Scan_Ini),Scan
+
+bscan_loop:
+        cmpm.b  (Match)+,(Scan)+
+        dbne    Scan_Test,bscan_loop
+        subq    #1,Scan
+
+        sub.l   Scan_Ini,Scan
+        cmp.l   Best_Len,Scan
+        bls.s   bshort_loop
+        move.l  Scan,Best_Len
+        move.l  Cur_Match,_match_start
+        cmp.l   _nice_match,Best_Len
+        bcs.s   blong_loop
+        IFD     CPUTEST
+        bra     return
+        ENDC
+
+        ENDC ; !CPU020
+
+        IFND    CPU000
+
+; for 68020 or higher, use word operations even on odd addresses:
+WORD_match:
+        move.w  (Scan_Ini),Scan_Start
+        move.w  -1(Scan_Ini,Best_Len),Scan_End
+        bra.s   wdo_scan
+
+wlong_loop:
+        move.w  -1(Scan_Ini,Best_Len),Scan_End
+
+wshort_loop:
+        add.w   Cur_Match,Cur_Match
+        move.w  (Prev_Address,Cur_Match.l),Cur_Match
+        cmp.l   Limit,Cur_Match
+        dbls    Chain_Length,wdo_scan
+        bra.s   return
+
+wdo_scan:
+        move.l  Match_Ini,Match
+        add.l   Cur_Match,Match
+        cmp.w   -MIN_MATCH-1(Match,Best_Len),Scan_End
+        bne.s   wshort_loop
+        cmp.w   -MIN_MATCH(Match),Scan_Start
+        bne.s   wshort_loop
+        moveq   #((MAX_MATCH-MIN_MATCH)/2),Scan_Test    ; value = 127
+        lea     MIN_MATCH(Scan_Ini),Scan
+
+wscan_loop:
+        cmpm.w  (Match)+,(Scan)+
+        dbne    Scan_Test,wscan_loop
+        subq    #2,Scan
+        move.b  -MIN_MATCH+1(Match),Scan_Test
+        cmp.b   (Scan),Scan_Test
+        bne     steven
+        addq    #1,Scan
+steven:
+        sub.l   Scan_Ini,Scan
+        cmp.l   Best_Len,Scan
+        bls.s   wshort_loop
+        move.l  Scan,Best_Len
+        move.l  Cur_Match,_match_start
+        cmp.l   _nice_match,Best_Len
+        bcs.s   wlong_loop
+
+        ENDC ; !CPU000
+
+return:
+        move.l  Best_Len,d0             ; function return value
+        movem.l (sp)+,SAVEREGS
+        rts
+
+        end
diff --git a/amiga/osdep.h b/amiga/osdep.h
new file mode 100644 (file)
index 0000000..a5851e3
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __amiga_osdep_h
+#define __amiga_osdep_h
+
+/* default to MEDIUM_MEM, but allow makefile override */
+#if ( (!defined(BIG_MEM)) && (!defined(SMALL_MEM)))
+#  define MEDIUM_MEM
+#endif
+
+/* check that TZ environment variable is defined before using UTC times */
+#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ))
+#  define IZ_CHECK_TZ
+#endif
+
+#define USE_CASE_MAP
+#define USE_EF_UT_TIME
+#define HANDLE_AMIGA_SFX
+#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \
+                     procname(n, 1))
+#define EXIT(e) ClearIOErr_exit(e)
+void ClearIOErr_exit(int e);
+
+#include "amiga/z-stat.h"
+#ifndef USE_TIME_LIB
+#  define NO_MKTIME
+#endif
+
+#ifdef __SASC
+#  include <sys/types.h>
+#  include <exec/execbase.h>
+#  if (defined(_M68020) && (!defined(__USE_SYSBASE)))
+                            /* on 68020 or higher processors it is faster   */
+#    define __USE_SYSBASE   /* to use the pragma libcall instead of syscall */
+#  endif                    /* to access functions of the exec.library      */
+#  include <proto/exec.h>   /* see SAS/C manual:part 2,chapter 2,pages 6-7  */
+#  include <proto/dos.h>
+#  if (defined(_M68020) && !defined(UNALIGNED_OK))
+#     define UNALIGNED_OK
+#  endif
+#  ifndef REENTRANT
+#    define REENTRANT
+#  endif
+#  if (defined(_NEAR_DATA) && !defined(DYN_ALLOC))
+#    define DYN_ALLOC
+#  endif
+#  ifdef DEBUG
+#    include <sprof.h>      /* profiler header file */
+#  endif
+   /* define USE_TIME_LIB if replacement functions of time_lib are available */
+   /* replaced are: tzset(), time(), localtime() and gmtime()                */
+#  define USE_TIME_LIB
+
+/*
+ A word on short-integers and SAS/C (a bug of [mc]alloc?)
+ Using short integers (i.e. compiling with option SHORT-INTEGERS) is
+ *not* recommended. To get maximum compression ratio the window size stored
+ in WSIZE should be 32k (0x8000). However, since the size of the window[]
+ array is 2*WSIZE, 65536 bytes must be allocated. The calloc function can
+ only allocate UINT_MAX (defined in limits.h) bytes which is one byte short
+ (65535) of the maximum window size if you are compiling with short-ints.
+ You'll get an error message "Out of memory (window allocation)" whenever
+ you try to deflate. Note that the compiler won't produce any warning.
+ The maximum window size with short-integers is therefore 32768 bytes.
+ The following is only implemented to allow the use of short-integers but
+ it is once again not recommended because of a loss in compression ratio.
+*/
+#  if (defined(_SHORTINT) && !defined(WSIZE))
+#    define WSIZE 0x4000        /* only half of maximum window size */
+#  endif                        /* possible with short-integers     */
+#endif /* __SASC */
+
+#ifdef AZTEC_C
+#  define NO_UNISTD_H
+#  define NO_RMDIR
+#  define BROKEN_FSEEK
+#  define USE_TIME_LIB
+#endif
+
+#ifdef USE_TIME_LIB
+extern int real_timezone_is_set;
+#  define VALID_TIMEZONE(tempvar) (tzset(), real_timezone_is_set)
+#else
+#  define VALID_TIMEZONE(tempvar) ((tempvar = getenv("TZ")) && tempvar[0])
+#endif
+
+#ifdef ZCRYPT_INTERNAL
+#  ifndef CLIB_EXEC_PROTOS_H
+     void *FindTask(void *);
+#  endif
+#  define ZCR_SEED2     (unsigned)(ulg)FindTask(NULL)
+#endif
+
+int Agetch(void);               /* getch() like function, in amiga/filedate.c */
+char *GetComment(char *);
+
+#define FOPR "rb"
+#define FOPM "rb+"
+#define FOPW "wb"
+/* prototype for ctrl-C trap function */
+void _abort(void);
+
+#endif /* !__amiga_osdep_h */
diff --git a/amiga/smakefile b/amiga/smakefile
new file mode 100644 (file)
index 0000000..a772fcb
--- /dev/null
@@ -0,0 +1,671 @@
+#===========================================================================
+# Makefile for Zip, ZipNote, ZipCloak, ZipSplit     AMIGA SAS/C Version 6.58
+# Version:  2.3                                     last revised:  24 Aug 98
+#===========================================================================
+# -John Bush, <John.Bush@East.Sun.COM>
+#         or: <JBush@Bix.COM>
+
+# updated for SAS/C Version 6.56+ and AmigaDOS 3.1 (V40)
+# by Haidinger Walter, <walthaid@unix.ict.tuwien.ac.at>
+
+# additional supplements and maintenance by Paul Kienitz
+
+# This makefile should work with at least AmigaDOS 2.04 (V37)  (not tested)
+# and will probably not work with AmigaDOS 1.3 (V34)
+
+# If you have any improvements, critics or else please feel free to mail.
+# Any response is appreciated. Haidinger Walter <walthaid@unix.ict.tuwien.ac.at>
+
+# Available targets:
+# all           builds all executeables below
+# zip           builds zip executeable
+# zipsplit      builds zipsplit executeable
+# zipcloak      builds zipcloak executeable
+# zipnote       builds zipnote executeable
+# ziplm         builds low memory version of zip executable
+# clean         remove all files created by the compilation
+# spotless      like clean target but removes binaries too
+
+
+##########################
+# USER MACRO DEFINITIONS #
+##########################
+
+# *** NOTE ***
+# The assembly version is not implemented yet.
+# (Un)commenting the assembler macros has no effect unless the
+# file dependencies are changed too.
+# Most of the amiga/*.a files do not assmble with 68000 instructions.
+# Any help is appreciated, of course.
+
+# Set the processor to generate code for.
+# Compiler:    ANY 68000 68010 68020 68030 68040 68060
+# Assembler:     0     0     1     2     3     4   n/a
+# Defaults: ANY and 0
+#
+CUSECPU = ANY
+AUSECPU = 0
+
+# UNCOMMENT to use 68020 instructions in the assembly version of deflate.o
+# Only use if code is generated for 68020 or higher processors above.
+# Note: You could use CPUTEST too to enable runtime cpu detection.
+# However, it is not recommended since both 68000 and 68020 code will be
+# included which would be an unnecessary increase in size.
+# (see amiga/deflate.a for more information)
+#
+#AUSE020 = CPU020
+
+# To disable the assembler replacements and use the standard C source,
+# you have to change the Zip and ZipLM dependencies. See below for details.
+# (remember that assembler use is *not* implemented yet)
+
+# Uncomment both CUTIL and LUTIL to make use of utility.library of OS 2.04+
+# The utility.library is *not* used for UnZipSFX to ensure maximum portability
+# between the different Amiga systems (minimal config: 68000 and OS 1.2).
+# You can change this by adding the $(LUTIL) macro in the UnZipSFX linking
+# rules (See below: Final output targets, UnZipSFX:).
+# WARNINGS when using the utility library:
+# 1. All Executables will *only* work with AmigaDOS 2.04 (v37) or higher.
+# 2. You *need not* compile/link with short-integers using the
+#    utility.library. It will crash your machine. See Libraries below.
+#
+# Default: commented (not used)
+#
+#CUTIL = UTILLIB DEFINE=_UTILLIB
+#LUTIL = WITH SC:LIB/utillib.with    # include necessary linker defines
+# Choose one stack-handling method (default=faster)
+# StackExtend: Dynamic runtime stack extension. You won't notice stack overflows.
+# StackCheck: On a stack overflow a requester appears which allows you to exit.
+# Note that either stack watching will slow down your executable because of the
+# extra code run on each function entry. On the other hand, you won't crash
+# anymore due to stack overflows. However, you should not have *any* stack
+# problems with Info-ZIP programs if you raise your stack to 10000 (which I'd
+# recommend as a minimum default stack for all applications) or more using the
+# shell stack command. Type 'Stack 20000' or add it to your S:Shell-Startup.
+# BTW: Typing 'Stack' prints your current stack size.
+#
+CSTACK = NOSTACKCHECK STACKEXTEND     # slow, but always works
+#CSTACK = STACKCHECK NOSTACKEXTEND    # slow, requester & graceful exit
+#CSTACK = NOSTACKCHECK NOSTACKEXTEND  # faster but relies on larger stack (>=10K)
+
+
+#
+# LIBRARIES
+# ---------
+
+# Choose one DATAOPTS , SASLIB , ASMOPTS and LSTARTUP
+# Always comment/uncomment all macros of a set.
+
+# Library to use with near data and 2-byte integers
+# Notes: o  slower than 4-byte integers with 68000 cpu
+#        o  *not* recommended due to poor overall performance
+#        o  see comment in amiga/osdep.h
+#DATAOPTS = DATA=NEAR SHORTINTEGERS DEF=_NEAR_DATA
+#SASLIB   = scs
+#ASMOPTS  = -dINT16
+#LSTARTUP = cres.o
+
+# Library to use with near data and 4-byte integers (DEFAULT)
+# *** use this with the utility.library ***
+DATAOPTS = DATA=NEAR DEF=_NEAR_DATA
+SASLIB   = sc
+ASMOPTS  =
+LSTARTUP = cres.o
+
+# Library to use with far data and 2-byte integers
+# use if DYN_ALLOC is not defined
+# old default - far data always works but is slower
+#DATAOPTS = DATA=FAR SHORTINTEGERS DEF=_FAR_DATA
+#SASLIB   = scsnb
+#ASMOPTS  = -dINT16
+#LSTARTUP = c.o
+
+# Library to use with far data and 4-byte integers
+# if everything else fails: try this
+#DATAOPTS = DATA=FAR DEF=_FAR_DATA
+#SASLIB   = scnb
+#ASMOPTS  =
+#LSTARTUP = c.o
+
+
+#
+# DEBUGGING
+# ---------
+
+# Default: No debugging information added.
+# The three macros below will be overwritten if you choose to add
+# debug info, therefore no need to comment.
+
+CDBG = NODEBUG NOPROFILE NOCOVERAGE    # default: no debug info
+ADBG =
+LDBG = STRIPDEBUG                      # default: no debug info
+
+# Compiler and loader debug flags.  Uncomment as needed.  Recomment when done.
+# Optimization disabled for faster compilation (by using NOOPT)
+
+#CDBG1 = DEF=DEBUG DEF=DEBUG_TIME     # enables Info-Zip's debug output
+
+# Enable profiling and coverage when desired. Option COVERAGE commented
+# seperately because running coverage may corrupt your drive in case of a
+# system crash since a file 'cover.dat' is created in your working directory.
+# Note that the use of COVERAGE forces the use of the c.o startup module.
+
+#CDBG2 = PROFILE
+#CDBG3 = COVERAGE        # must use c.o startup code:
+#LSTARTUP = c.o          # Uncomment *only* when you use COVERAGE
+
+# *Uncomment* here macros CDBG, ADBG and LDBG to include debugging information
+
+#CDBG = $(CDBG1) $(CDBG2) $(CDBG3) ADDSYM DEBUG=FULLFLUSH STACKCHECK NOOPT
+#ADBG = DEBUG
+#LDBG = ADDSYM
+
+# Optional use of memwatch.library which can be found in your
+# sc:extras/memlib directory. Please read the short docs (memlib.doc).
+# Note that memwatch.library has a small bug: MWTerm() displays always
+# the first entry.
+# Get the latest version from aminet (dev/debug/memlib.lha) or
+# contact me to get the patch. Uncomment all macros to use.
+#CMEMLIB  = DEFINE=MWDEBUG=1       # define to enable library
+#LMEMLIB  = SC:LIB/memwatch.lib       # path to library
+#LSTARTUP = c.o                    # must use c.o with memlib!
+
+
+#
+# MAPPING
+# -------
+
+# Map filenames used when mapping (no need to comment)
+#
+MAPFZ = zip.map                # Zip      map filename
+MAPFN = zipnote.map            # ZipNote  map filename
+MAPFC = zipcloak.map           # ZipCloak map filename
+MAPFS = zipsplit.map           # ZipSplit map filename
+MAPFL = ziplm.map              # Zip low memory version map filename
+
+# Map file output: Uncomment to highlight and bold headings.
+#
+#MAPFSTYLE = FANCY
+
+# Map flags for each EXECUTABLE. Uncomment to enable mapping.
+# For map options please refer to:
+# SAS/C v6 manual, volume 1: user's guide, chapter 8, page 136: map
+# Default: all options enabled: f,h,l,o,s,x
+#                                 |-> options start here
+#LMAPZ = $(MAPFSTYLE) MAP $(MAPFZ) f,h,l,o,s,x   # Zip      maps
+#LMAPN = $(MAPFSTYLE) MAP $(MAPFN) f,h,l,o,s,x   # ZipNote  maps
+#LMAPC = $(MAPFSTYLE) MAP $(MAPFC) f,h,l,o,s,x   # ZipCloak maps
+#LMAPS = $(MAPFSTYLE) MAP $(MAPFS) f,h,l,o,s,x   # ZipSplit maps
+#LMAPL = $(MAPFSTYLE) MAP $(MAPFL) f,h,l,o,s,x   # Zip lowmem maps
+
+#
+# LISTINGS
+# --------
+
+# Listfile-extensions for each executable (enter *with* dot)
+#
+LISTEXTZ = .lst   # extension for Zip listfiles
+LISTEXTU = .ulst  # extension for utility listfiles (ZipNote,ZipCloak,ZipSplit)
+LISTEXTL = .llst  # extension for Zip low memory listfiles
+
+
+# List files and cross references for each OBJECT.
+# Add/remove flags as needed. Not all listed by default.
+# Use LISTINCLUDES to determine the dependencies for smake
+#
+CLISTOPT = LISTHEADERS LISTMACROS # LISTSYSTEM LISTINCLUDES
+CXREFOPT = XHEAD XSYS
+#
+# Uncomment to enable listing (default: commented)
+# *** WARNING: List files require *lots* of disk space!
+#
+#CLIST = LIST $(CLISTOPT)
+#CXREF = XREF $(CXREFOPT)
+
+
+#
+# SUPPRESSED COMPILER WARNINGS
+# ----------------------------
+
+# Compiler warnings to ignore
+#
+# Warning 105 : module does not define any externally-known symbols
+# Warning 304 : Dead assignment eliminated...
+# Note    306 : ...function inlined...
+# Warning 317 : possibly uninitialized variable...
+# Comment to enable.
+#
+CIGNORE = IGNORE=105,304,306,317
+
+
+#
+# OBJECT EXTENSIONS
+#
+
+# Extensions used for objects of each executeable.
+# Transformation rules require unique extensions.
+# Enter *with* dot.
+#
+O  = .o     # extension for Zip     objects
+OU = .uo    # extension for utility objects (ZipNote, ZipSplit and ZipCloak)
+OL = .lo    # extension for low memory Zip objects
+
+
+# Filename used to store converted options from environment variable
+# LOCAL_ZIP. Default: scoptions_local_zip
+#
+CWITHOPT = scoptions_local_zip
+
+
+# Filenames to store compiler options to prevent command line overflow
+#
+# Common options file for Zip and other executables
+CFILE = scoptions-zip
+
+
+# Temp filenames for object lists to load using linker "WITH" command.
+OBJLISTZ = zip_objlist.with            # Zip      object list
+OBJLISTN = zipnote_objlist.with        # ZipNote  object list
+OBJLISTC = zipcloak_objlist.with       # ZipCloak object list
+OBJLISTS = zipsplit_objlist.with       # ZipSplit object list
+OBJLISTL = ziplm_objlist.with          # Zip low-mem object list
+
+
+# Filenames to store linker options
+#
+LWITHZ = zip.lnk                       # zip      linker options
+LWITHN = zipnote.lnk                   # zipnote  linker options
+LWITHC = zipcloak.lnk                  # zipcloak linker options
+LWITHS = zipsplit.lnk                  # zipsplit linker options
+LWITHL = ziplm.lnk                     # zip low-mem linker options
+
+
+# Define AMIGA_BETA to print "Beta Notice" up front.  See tailor.h.
+# Undefine AMIGA_BETA when building a released version.
+#CDEFBETA = DEF=AMIGA_BETA
+
+#####################################
+# NOTHING TO CHANGE BEYOND HERE ... #
+#####################################
+# (except for C/asm dependencies)
+
+# Define MEDIUM_MEM for production release (per Paul Kienitz).
+# This reduces runtime memory requirement but not speed or compression.
+# Note: Do *not* use BIG_MEM or MMAP since it isn't yet supported by the
+        assembler version of deflate.c : amiga/deflate.a
+CUSEMEM = DEF=MEDIUM_MEM
+AUSEMEM = -DMEDIUM_MEM       # for asm deflate.o, must match above
+
+
+# Defines for building low-memory use version of Zip
+WSIZEL   = WSIZE=4096     # deflate.c window size for low-mem version
+CLOWMEM = DEF=SMALL_MEM DEF=$(WSIZEL)
+ALOWMEM = -DSMALL_MEM   -D$(WSIZEL)  # for asm deflate.o, must match above
+
+
+# Compiler definitions
+#
+CC = sc
+#
+# Optimizer flags
+#
+OPTPASSES = 6     # set number of global optimizer passes
+#
+OPT1 = OPT OPTINL OPTINLOCAL OPTTIME OPTLOOP OPTSCHED
+OPT2 = OPTCOMP=$(OPTPASSES) OPTDEP=$(OPTPASSES) OPTRDEP=$(OPTPASSES)
+OPT  = $(OPT1) $(OPT2)
+
+
+# Compiler flags
+#
+CDEFINES = $(CMEMLIB) $(CDEFBETA) DEF=AMIGA
+COPTIONS = $(DATAOPTS) CODE=NEAR CPU=$(CUSECPU) VERBOSE PARAMETERS=BOTH NOMINC
+COPTIONS = $(COPTIONS) ERRORREXX NOERRORCONSOLE MEMSIZE=HUGE $(CLIST) $(CXREF)
+COPTIONS = $(COPTIONS) $(CSTACK) $(CUTIL) STRICT UNSCHAR NOICONS STRINGMERGE
+CFLAGS = $(CDEFINES) $(COPTIONS) $(OPT) $(CDBG) $(CIGNORE)
+
+
+# Linker definitions
+#  See SASLIB definition above
+#
+LD = slink
+# special linker flags for pure (i.e. resident) binary.
+LDFLAGSS = FROM SC:LIB/$(LSTARTUP)
+# common linker flags for all other executeables
+LDFLAGSC = FROM SC:LIB/c.o
+LDFLAGS2 = NOICONS $(LDBG)
+LIBFLAGS = LIB $(LMEMLIB) SC:LIB/$(SASLIB).lib SC:LIB/amiga.lib
+
+
+# Assembler definitions
+#
+ASM = asm
+#
+# Options used for assembling amiga/deflate.a
+# Must match defines in C-Source.
+#
+AFLAGS0  = -d__SASC -dSASC -dAMIGA
+AFLAGS1  = $(AUSE020) $(ASMOPTS) $(ADBG)
+AFLAGS2  = -m$(AUSECPU) -jm -iINCLUDE:
+AFLAGS   = $(AFLAGS0) $(AFLAGS1) $(AFLAGS2)
+ASMOPTSZ = $(AFLAGS) $(AUSEMEM) -dDYN_ALLOC     # Zip asm flags
+ASMOPTSL = $(AFLAGS) $(ALOWMEM)                 # Zip low-mem version asm flags
+
+
+##################
+# TARGET OBJECTS #
+##################
+
+
+# Zip objects
+OBJZ1 = zip$(O) zipfile$(O) zipup$(O) fileio$(O) util$(O) globals$(O)
+OBJZ2 = crc32$(O) crctab$(O) crypt$(O) ttyio$(O)
+OBJZI = deflate$(O) trees$(O)
+OBJZA = amiga$(O) amigazip$(O) time_lib$(O) stat$(O) filedate$(O)
+OBJZ  = $(OBJZ1) $(OBJZ2) $(OBJZI) $(OBJZA)
+
+# Shared utility objects for ZipNote, ZipCloak and ZipSplit
+OBJU1 = globals$(O)
+OBJUU = zipfile$(OU) fileio$(OU) util$(OU)
+OBJUA = amigazip$(OU) amiga$(O) time_lib$(O) stat$(O) filedate$(O)
+OBJU  = $(OBJU1) $(OBJUU) $(OBJUA)
+
+# ZipNote objects
+OBJN1 = zipnote$(O)
+OBJN  = $(OBJN1) $(OBJU)
+
+# ZipCloak objects
+OBJC1 = zipcloak$(O)
+OBJCU = $(OBJU) crypt$(OU)
+OBJCS = crctab$(O) ttyio$(O)
+OBJC  = $(OBJC1) $(OBJCU) $(OBJCS)
+
+#ZipSplit objects
+OBJS1 = zipsplit$(O)
+OBJS  = $(OBJS1) $(OBJU)
+
+# ZipLM objects
+OBJL1 = zip$(OL) zipfile$(OL) zipup$(OL) fileio$(OL) util$(OL) globals$(OL)
+OBJL2 = crc32$(OL) crctab$(OL) crypt$(OL) ttyio$(OL)
+OBJLI = deflate$(OL) trees$(OL)
+OBJLA = amiga$(OL) amigazip$(OL) time_lib$(O) stat$(O) filedate$(O)
+OBJL  = $(OBJL1) $(OBJL2) $(OBJLI) $(OBJLA)
+
+# Common header files
+ZIP_H1 = zip.h ziperr.h tailor.h
+ZIP_HA = amiga/osdep.h amiga/z-stat.h amiga/z-time.h
+ZIP_H  = $(ZIP_H1) $(ZIP_HA)
+
+# Output targets
+ZIPS  = Zip ZipNote ZipCloak ZipSplit ZipLM
+
+
+# Temp filenames for object lists to load using linker "WITH" command.
+OBJLISTZ = zip_objlist.with            # Zip      object list
+OBJLISTN = zipnote_objlist.with        # ZipNote  object list
+OBJLISTC = zipcloak_objlist.with       # ZipCloak object list
+OBJLISTS = zipsplit_objlist.with       # ZipSplit object list
+OBJLISTL = ziplm_objlist.with          # Zip low-mem object list
+
+#######################################
+# DEFAULT TARGET AND PROCESSING RULES #
+#######################################
+
+all: request flush $(ZIPS)
+
+# Zip transformation rules
+#
+.c$(O):
+      $(CC) WITH=$(CFILE) $(CUSEMEM) LISTFILE=$>$(LISTEXTZ) OBJNAME=$@ $*.c
+
+# Zip low-memory version transformation rules
+#
+.c$(OL):
+      $(CC) WITH=$(CFILE) $(CLOWMEM) LISTFILE=$>$(LISTEXTL) OBJNAME=$@ $*.c
+
+# Utilities (ZipNote, ZipCloak and ZipSplit) transformation rules
+#
+.c$(OU):
+      $(CC) WITH=$(CFILE) $(CUSEMEM) DEF=UTIL LISTFILE=$>$(LISTEXTU) OBJNAME=$@ $*.c
+
+
+########################
+# Special target rules #
+########################
+
+# Special rule to build time_lib.o for Zip (requires NO_MKTIME define)
+time_lib$(O):
+      $(CC) WITH=$(CFILE) $(CUSEMEM) DEF=ZIP LISTFILE=$>$(LISTEXTZ) OBJNAME=$@ $*.c
+
+#########################
+# Final output targets. #
+#########################
+
+
+zip:      local_zip CommonFlags $(OBJZ)
+          @Echo "$(OBJZ)" > $(OBJLISTZ)
+          Type $(OBJLISTZ)
+          @Echo "$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTZ) $(LIBFLAGS)" \
+                "$(LDFLAGS2) $(LMAPZ)" >$(LWITHZ)
+          Type $(LWITHZ)
+          $(LD) TO Zip      WITH $(LWITHZ)
+
+zipnote:  local_zip CommonFlags $(OBJN)
+          @Echo "$(OBJN)" > $(OBJLISTN)
+          Type $(OBJLISTN)
+          @Echo "$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTN) $(LIBFLAGS) " \
+                "$(LDFLAGS2) $(LMAPN)" >$(LWITHN)
+          Type $(LWITHN)
+          $(LD) TO ZipNote  WITH $(LWITHN)
+
+zipcloak: local_zip CommonFlags $(OBJC)
+          @Echo "$(OBJC)" > $(OBJLISTC)
+          Type $(OBJLISTC)
+          @Echo "$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTC) $(LIBFLAGS) " \
+                "$(LDFLAGS2) $(LMAPC)" >$(LWITHC)
+          Type $(LWITHC)
+          $(LD) TO ZipCloak WITH $(LWITHC)
+
+zipsplit: local_zip CommonFlags $(OBJS)
+          @Echo "$(OBJS)" > $(OBJLISTS)
+          Type $(OBJLISTS)
+          @Echo "$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTS) $(LIBFLAGS) " \
+                "$(LDFLAGS2) $(LMAPS)" >$(LWITHS)
+          Type $(LWITHS)
+          $(LD) TO ZipSplit WITH $(LWITHS)
+
+ziplm:    local_zip CommonFlags $(OBJL)
+          @Echo "$(OBJL)" > $(OBJLISTL)
+          Type $(OBJLISTL)
+          @Echo "$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTL) $(LIBFLAGS) " \
+                "$(LDFLAGS2) $(LMAPL)" >$(LWITHL)
+          Type $(LWITHL)
+          $(LD) TO ZipLM    WITH $(LWITHL)
+
+
+clean:
+        -Delete >nil: $(OBJZ) quiet
+        -Delete >nil: $(OBJN) quiet
+        -Delete >nil: $(OBJC) quiet
+        -Delete >nil: $(OBJS) quiet
+        -Delete >nil: $(OBJL) quiet
+        -Delete >nil: $(OBJLISTZ) $(OBJLISTL) $(OBJLISTN) $(OBJLISTS) $(OBJLISTC) quiet
+        -Delete >nil: $(MAPFZ) $(MAPFN) $(MAPFC) $(MAPFS) $(MAPFL) quiet
+        -Delete >nil: \#?$(LISTEXTZ) \#?$(LISTEXTU) \#?$(LISTEXTL) quiet
+        -Delete >nil: $(CWITHOPT) $(CFILE) quiet
+        -Delete >nil: $(LWITHZ) $(LWITHN) $(LWITHC) $(LWITHS) $(LWITHL) quiet
+        -Delete >nil: env:VersionDate quiet
+        -Delete >nil: \#?.q.?? \#?.tmp \#?.cov quiet
+
+spotless: clean
+        -Delete >nil: $(ZIPS) quiet
+
+
+################
+# DEPENDENCIES #
+################
+
+# To change between the assembler and C sources, you have to comment/uncomment
+# the approprite lines. C sources are marked by #C-src and assembler sources
+# #asm-src at the end.
+# Zip dependencies:
+#
+
+zip$(O):        zip.c      $(ZIP_H) revision.h crypt.h ttyio.h
+zipup$(O):      zipup.c    $(ZIP_H) revision.h crypt.h amiga/zipup.h
+zipfile$(O):    zipfile.c  $(ZIP_H) revision.h
+crypt$(O):      crypt.c    $(ZIP_H) crypt.h ttyio.h
+ttyio$(O):      ttyio.c    $(ZIP_H) crypt.h ttyio.h
+deflate$(O):    deflate.c  $(ZIP_H)                          #C-src
+trees$(O):      trees.c    $(ZIP_H)
+fileio$(O):     fileio.c   $(ZIP_H)
+util$(O):       util.c     $(ZIP_H) mktime.c
+crc32$(O):      crc32.c    $(ZIP_H)
+crctab$(O):     crctab.c   $(ZIP_H)
+globals$(O):    globals.c  $(ZIP_H)
+# Amiga specific objects
+stat$(O):       amiga/stat.c     amiga/z-stat.h amiga/z-time.h
+filedate$(O):   amiga/filedate.c amiga/z-time.h crypt.h
+time_lib$(O):   amiga/time_lib.c amiga/z-time.h
+amiga$(O):      amiga/amiga.c    ziperr.h
+amigazip$(O):   amiga/amigazip.c $(ZIP_H) amiga/amiga.h env:Workbench
+# Substitute assembly version of deflate.c:
+#deflate$(O):  amiga/deflate.a                               #asm-src
+#        $(ASM) $(ASMOPTSZ) -o$@ $*.a                        #asm-src
+
+
+# Utility (ZipNote, ZipCloak, ZipSplit) dependencies:
+#
+zipnote$(O):    zipnote.c  $(ZIP_H) revision.h
+zipcloak$(O):   zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipsplit$(O):   zipsplit.c $(ZIP_H) revision.h
+zipfile$(OU):   zipfile.c  $(ZIP_H) revision.h
+fileio$(OU):    fileio.c   $(ZIP_H)
+util$(OU):      util.c     $(ZIP_H) mktime.c
+crypt$(OU):     crypt.c    $(ZIP_H) crypt.h ttyio.h
+# Amiga specific objects
+amigazip$(OU):   amiga/amigazip.c $(ZIP_H) amiga/amiga.h env:Workbench
+
+# ZipLM dependencies:
+#
+zip$(OL):       zip.c      $(ZIP_H) revision.h crypt.h ttyio.h
+zipup$(OL):     zipup.c    $(ZIP_H) revision.h crypt.h amiga/zipup.h
+zipfile$(OL):   zipfile.c  $(ZIP_H) revision.h
+crypt$(OL):     crypt.c    $(ZIP_H) crypt.h ttyio.h
+ttyio$(OL):     ttyio.c    $(ZIP_H) crypt.h ttyio.h
+deflate$(OL):   deflate.c  $(ZIP_H)
+trees$(OL):     trees.c    $(ZIP_H)
+fileio$(OL):    fileio.c   $(ZIP_H)
+util$(OL):      util.c     $(ZIP_H) mktime.c
+crc32$(OL):     crc32.c    $(ZIP_H)
+crctab$(OL):    crctab.c   $(ZIP_H)
+globals$(OL):   globals.c  $(ZIP_H)
+# Amiga specific objects
+stat$(OL):      amiga/stat.c     amiga/z-stat.h amiga/z-time.h
+filedate$(OL):  amiga/filedate.c amiga/z-time.h crypt.h
+time_lib$(OL):  amiga/time_lib.c amiga/z-time.h
+amiga$(OL):     amiga/amiga.c    ziperr.h
+# Substitute assembly version of deflate.c:
+#deflate$(OL): amiga/deflate.a
+#        $(ASM) $(ASMOPTSL) -o$@ $*.a
+
+
+########################
+# DEPENDECIES END HERE #
+########################
+
+# flush all libraries to provide more mem for compilation
+flush:
+        @Avail flush >nil:
+
+# write common compiler flags to file and echo to user
+CommonFlags:
+        @Echo "$(CFLAGS)"    >$(CFILE)
+        @Type "$(CWITHOPT)" >>$(CFILE)
+        -Type $(CFILE)
+
+
+# special rules for adding Amiga internal version number to amiga/amiga.c
+amiga$(O):
+         rx > env:VersionDate "say '""'translate(date('E'),'.','/')'""'"
+         $(CC) WITH=$(CFILE) $(CUSEMEM) LISTFILE=$>$(LISTEXTZ) OBJNAME=$@ $*.c
+         -Delete env:VersionDate
+
+amiga$(OL):
+         rx > env:VersionDate "say '""'translate(date('E'),'.','/')'""'"
+         $(CC) WITH=$(CFILE) $(CLOWMEM) LISTFILE=$>$(LISTEXTL) OBJNAME=$@ $*.c
+         -Delete env:VersionDate
+
+
+# needed in amiga/amigazip.c
+# should be set in startup-sequence, but just in case:
+# (only works with OS 2.0 and above)
+
+env\:WorkBench:
+        @Execute < < (Workbench_smk.tmp)
+           FailAt 21
+           If not exists ENV:Workbench
+              Version >nil:
+              SetEnv Workbench $$Workbench
+           Endif
+        <
+
+
+# Read environment variable LOCAL_ZIP and convert options to SAS format
+#
+# e.g.: to define FOO_ONE and FOO_TWO enter:
+#
+# SetEnv LOCAL_ZIP "-DFOO_ONE -DFOO_TWO"
+#
+# Put the statement into your startup-sequence or (for AmigaDOS 2.0 or higher
+# only) make sure LOCAL_ZIP is stored in the ENVARC: directory
+# ( Copy ENV:LOCAL_ZIP ENVARC: )
+#
+
+local_zip:
+        @Execute < < (Local_Zip_smk.tmp)
+           Failat 21
+           If exists ENV:LOCAL_ZIP
+              Echo "Using environment variable LOCAL_ZIP !"
+              Copy >NIL: ENV:LOCAL_ZIP SASCOPTS
+           Else
+              Echo "You could use envvar ZIP_OPT to set your special compilation options."
+              Delete >nil: SASCOPTS quiet
+           Endif
+           ; Do not remove the lctosc command! If LOCAL_ZIP is unset, an
+           ; empty file is created which needed by CommonFlags !
+           lctosc >$(CWITHOPT)
+        <
+
+
+
+# Echo request to the user
+#
+request:
+        @Echo ""
+        @Echo " This makefile is for use with SAS/C version 6.58."
+        @Echo " If you still have an older version, please upgrade!"
+        @Echo " Patches are available on the Aminet under biz/patch/sc\#?."
+        @Echo ""
+        @Echo " Just a simple request..."
+        @Echo " Please give me a mail that you compiled whether you encounter any errors"
+        @Echo " or not. I'd just like to know how many Amiga users actually make use of"
+        @Echo " this makefile."
+        @Echo " If you mail me, I'll put you on my mailing-list and notify you whenever"
+        @Echo " new versions of Info-Zip are released."
+        @Echo " Have a look at the makefile for changes like CPU type, UtilLib, etc."
+        @Echo " Feel free to mail comments, suggestions, etc."
+        @Echo " Enjoy Info-Zip !"
+        @Echo " Haidinger Walter, <walthaid@unix.ict.tuwien.ac.at>"
+        @Echo ""
+
+
+# Echo help in case of an error
+#
+.ONERROR:
+        @Echo ""
+        @Echo "[sigh] An error running this makefile was detected."
+        @Echo "This message may also appear if you interrupted smake by pressing CTRL-C."
+        @Echo "Contact Info-Zip authors at Zip-Bugs@lists.wku.edu or me for help."
+        @Echo "Haidinger Walter, <walthaid@unix.ict.tuwien.ac.at>"
+
diff --git a/amiga/stat.c b/amiga/stat.c
new file mode 100644 (file)
index 0000000..c453273
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* Here we have a handmade stat() function because Aztec's c.lib stat() */
+/* does not support an st_mode field, which we need... also a chmod().  */
+
+/* This stat() is by Paul Wells, modified by Paul Kienitz. */
+/* Originally for use with Aztec C >= 5.0 and Lattice C <= 4.01  */
+/* Adapted for SAS/C 6.5x by Haidinger Walter */
+
+/* POLICY DECISION: We will not attempt to remove global variables from */
+/* this source file for Aztec C.  These routines are essentially just   */
+/* augmentations of Aztec's c.lib, which is itself not reentrant.  If   */
+/* we want to produce a fully reentrant UnZip, we will have to use a    */
+/* suitable startup module, such as purify.a for Aztec by Paul Kienitz. */
+
+#ifndef __amiga_stat_c
+#define __amiga_stat_c
+
+#include <exec/types.h>
+#include <exec/memory.h>
+#include "amiga/z-stat.h"             /* fake version of stat.h */
+#include <string.h>
+
+#ifdef AZTEC_C
+#  include <libraries/dos.h>
+#  include <libraries/dosextens.h>
+#  include <clib/exec_protos.h>
+#  include <clib/dos_protos.h>
+#  include <pragmas/exec_lib.h>
+#  include <pragmas/dos_lib.h>
+#endif
+#ifdef __SASC
+#  include <sys/dir.h>               /* SAS/C dir function prototypes */
+#  include <sys/types.h>
+#  include <proto/exec.h>
+#  include <proto/dos.h>
+#endif
+
+#ifndef SUCCESS
+#  define SUCCESS (-1)
+#  define FAILURE (0)
+#endif
+
+
+void close_leftover_open_dirs(void);    /* prototype */
+
+static DIR *dir_cleanup_list = NULL;    /* for resource tracking */
+
+/* CALL THIS WHEN HANDLING CTRL-C OR OTHER UNEXPECTED EXIT! */
+void close_leftover_open_dirs(void)
+{
+    while (dir_cleanup_list)
+        closedir(dir_cleanup_list);
+}
+
+
+unsigned short disk_not_mounted;
+
+extern int stat(const char *file, struct stat *buf);
+
+stat(file,buf)
+const char *file;
+struct stat *buf;
+{
+
+        struct FileInfoBlock *inf;
+        BPTR lock;
+        time_t ftime;
+        struct tm local_tm;
+
+        if( (lock = Lock((char *)file,SHARED_LOCK))==0 )
+                /* file not found */
+                return(-1);
+
+        if( !(inf = (struct FileInfoBlock *)AllocMem(
+                (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) )
+        {
+                UnLock(lock);
+                return(-1);
+        }
+
+        if( Examine(lock,inf)==FAILURE )
+        {
+                FreeMem((char *)inf,(long)sizeof(*inf));
+                UnLock(lock);
+                return(-1);
+        }
+
+        /* fill in buf */
+        buf->st_dev         =
+        buf->st_nlink       =
+        buf->st_uid         =
+        buf->st_gid         =
+        buf->st_rdev        = 0;
+        buf->st_ino         = inf->fib_DiskKey;
+        buf->st_blocks      = inf->fib_NumBlocks;
+        buf->st_size        = inf->fib_Size;
+
+        /* now the date.  AmigaDOS has weird datestamps---
+         *      ds_Days is the number of days since 1-1-1978;
+         *      however, as Unix wants date since 1-1-1970...
+         */
+
+        ftime =
+                (inf->fib_Date.ds_Days * 86400 )                +
+                (inf->fib_Date.ds_Minute * 60 )                 +
+                (inf->fib_Date.ds_Tick / TICKS_PER_SECOND )     +
+                (86400 * 8 * 365 )                              +
+                (86400 * 2 );  /* two leap years */
+
+        tzset();
+        /* ftime += timezone; */
+        local_tm = *gmtime(&ftime);
+        local_tm.tm_isdst = -1;
+        ftime = mktime(&local_tm);
+
+        buf->st_ctime =
+        buf->st_atime =
+        buf->st_mtime = ftime;
+
+        buf->st_mode = (inf->fib_DirEntryType < 0 ? S_IFREG : S_IFDIR);
+
+        /* lastly, throw in the protection bits */
+        buf->st_mode |= ((inf->fib_Protection ^ 0xF) & 0xFF);
+
+        FreeMem((char *)inf, (long)sizeof(*inf));
+        UnLock((BPTR)lock);
+
+        return(0);
+
+}
+
+int fstat(int handle, struct stat *buf)
+{
+    /* fake some reasonable values for stdin */
+    buf->st_mode = (S_IREAD|S_IWRITE|S_IFREG);
+    buf->st_size = -1;
+    buf->st_mtime = time(&buf->st_mtime);
+    return 0;
+}
+
+
+/* opendir(), readdir(), closedir(), rmdir(), and chmod() by Paul Kienitz. */
+
+DIR *opendir(const char *path)
+{
+    DIR *dd = AllocMem(sizeof(DIR), MEMF_PUBLIC);
+    if (!dd) return NULL;
+    if (!(dd->d_parentlock = Lock((char *)path, MODE_OLDFILE))) {
+        disk_not_mounted = IoErr() == ERROR_DEVICE_NOT_MOUNTED;
+        FreeMem(dd, sizeof(DIR));
+        return NULL;
+    } else
+        disk_not_mounted = 0;
+    if (!Examine(dd->d_parentlock, &dd->d_fib) || dd->d_fib.fib_EntryType < 0) {
+        UnLock(dd->d_parentlock);
+        FreeMem(dd, sizeof(DIR));
+        return NULL;
+    }
+    dd->d_cleanuplink = dir_cleanup_list;       /* track them resources */
+    if (dir_cleanup_list)
+        dir_cleanup_list->d_cleanupparent = &dd->d_cleanuplink;
+    dd->d_cleanupparent = &dir_cleanup_list;
+    dir_cleanup_list = dd;
+    return dd;
+}
+
+void closedir(DIR *dd)
+{
+    if (dd) {
+        if (dd->d_cleanuplink)
+            dd->d_cleanuplink->d_cleanupparent = dd->d_cleanupparent;
+        *(dd->d_cleanupparent) = dd->d_cleanuplink;
+        if (dd->d_parentlock)
+            UnLock(dd->d_parentlock);
+        FreeMem(dd, sizeof(DIR));
+    }
+}
+
+struct dirent *readdir(DIR *dd)
+{
+    return (ExNext(dd->d_parentlock, &dd->d_fib) ? (struct dirent *)dd : NULL);
+}
+
+
+#ifdef AZTEC_C
+
+int rmdir(const char *path)
+{
+    return (DeleteFile((char *)path) ? 0 : IoErr());
+}
+
+int chmod(const char *filename, int bits)       /* bits are as for st_mode */
+{
+    long protmask = (bits & 0xFF) ^ 0xF;
+    return !SetProtection((char *)filename, protmask);
+}
+
+
+/* This here removes unnecessary bulk from the executable with Aztec: */
+void _wb_parse(void)  { }
+
+/* fake a unix function that does not apply to amigados: */
+int umask(void)  { return 0; }
+
+
+#  include <signal.h>
+
+/* C library signal() messes up debugging yet adds no actual usefulness */
+typedef void (*__signal_return_type)(int);
+__signal_return_type signal()  { return SIG_ERR; }
+
+
+/* The following replaces Aztec's argv-parsing function for compatibility with
+Unix-like syntax used on other platforms.  It also fixes the problem the
+standard _cli_parse() has of accepting only lower-ascii characters. */
+
+int _argc, _arg_len;
+char **_argv, *_arg_lin;
+
+void _cli_parse(struct Process *pp, long alen, register UBYTE *aptr)
+{
+    register UBYTE *cp;
+    register struct CommandLineInterface *cli;
+    register short c;
+    register short starred = 0;
+#  ifdef PRESTART_HOOK
+    void Prestart_Hook(void);
+#  endif
+
+    cli = (struct CommandLineInterface *) (pp->pr_CLI << 2);
+    cp = (UBYTE *) (cli->cli_CommandName << 2);
+    _arg_len = cp[0] + alen + 2;
+    if (!(_arg_lin = AllocMem((long) _arg_len, 0L)))
+        return;
+    c = cp[0];
+    strncpy(_arg_lin, cp + 1, c);
+    _arg_lin[c] = 0;
+    for (cp = _arg_lin + c + 1; alen && (*aptr < '\n' || *aptr > '\r'); alen--)
+        *cp++ = *aptr++;
+    *cp = 0;
+    aptr = cp = _arg_lin + c + 1;
+    for (_argc = 1; ; _argc++) {
+        while (*cp == ' ' || *cp == '\t')
+            cp++;
+        if (!*cp)
+            break;
+        if (*cp == '"') {
+            cp++;
+            while (c = *cp++) {
+                if (c == '"' && !starred) {
+                    *aptr++ = 0;
+                    starred = 0;
+                    break;
+                } else if (c == '\\' && !starred)
+                    starred = 1;
+                else {
+                    *aptr++ = c;
+                    starred = 0;
+                }
+            }
+        } else {
+            while ((c = *cp++) && c != ' ' && c != '\t')
+                *aptr++ = c;
+            *aptr++ = 0;
+        }
+        if (c == 0)
+            --cp;
+    }
+    *aptr = 0;
+    if (!(_argv = AllocMem((_argc + 1) * sizeof(*_argv), 0L))) {
+        _argc = 0;
+        return;
+    }
+    for (c = 0, cp = _arg_lin; c < _argc; c++) {
+        _argv[c] = cp;
+        cp += strlen(cp) + 1;
+    }
+    _argv[c] = NULL;
+#  ifdef PRESTART_HOOK
+    Prestart_Hook();
+#  endif
+}
+
+#endif /* AZTEC_C */
+
+#endif /* __amiga_stat_c */
diff --git a/amiga/time_lib.c b/amiga/time_lib.c
new file mode 100644 (file)
index 0000000..2804c05
--- /dev/null
@@ -0,0 +1,541 @@
+#define __amiga_time_lib_c
+
+/* -----------------------------------------------------------------------------
+This source is copyrighted by Norbert Pueschel <pueschel@imsdd.meb.uni-bonn.de>
+From 'clockdaemon.readme':
+(available from Aminet, main site is ftp.wustl.edu:/pub/aminet/ under
+ util/time/clockdaemon.lha)
+"The original SAS/C functions gmtime, localtime, mktime and time do not
+work correctly. The supplied link library time.lib contains replacement
+functions for them."
+The time.lib library consists of three parts (time.c, timezone.c and version.c),
+all included here. [time.lib 1.2 (1997-04-02)]
+Permission is granted to the Info-ZIP group to redistribute the time.lib source.
+The use of time.lib functions in own, noncommercial programs is permitted.
+It is only required to add the timezone.doc to such a distribution.
+Using the time.lib library in commercial software (including Shareware) is only
+permitted after prior consultation of the author.
+------------------------------------------------------------------------------*/
+/* History */
+/* 30 Mar 1997, Haidinger Walter, added AVAIL_GETVAR macro to support OS <V36 */
+/* 24 May 1997, Haidinger Walter, added NO_MKTIME macro to allow use of Zip's */
+/*              mktime.c. NO_MKTIME must be defined in the makefile, though.  */
+/* 25 May 1997, Haidinger Walter, moved set_TZ() here from filedate.c         */
+/* 20 Jul 1997, Paul Kienitz, adapted for Aztec C, added mkgmtime(),          */
+/*              debugged, and made New York settings default, as is common.   */
+/* 30 Sep 1997, Paul Kienitz, restored real_timezone_is_set flag              */
+/* 19 Oct 1997, Paul Kienitz, corrected 16 bit multiply overflow bug          */
+/* 21 Oct 1997, Chr. Spieler, shortened long lines, removed more 16 bit stuff */
+/*              (n.b. __stdoffset and __dstoffset now have to be long ints)   */
+/* 25 Oct 1997, Paul Kienitz, cleanup, make tzset() not redo work needlessly  */
+/* 29 Oct 1997, Chr. Spieler, initialized globals _TZ, real_timezone_is_set   */
+/* 31 Dec 1997, Haidinger Walter, created z-time.h to overcome sas/c header   */
+/*              dependencies. TZ_ENVVAR macro added. Happy New Year!          */
+/* 25 Apr 1998, Chr. Spieler, __timezone must always contain __stdoffset      */
+/* 28 Apr 1998, Chr. Spieler, P. Kienitz, changed __daylight to standard usage */
+
+#ifdef __SASC
+#  include <proto/dos.h>
+#  include <proto/locale.h>
+#  include <proto/exec.h>
+   /* this setenv() is in amiga/filedate.c */
+   extern int setenv(const char *var, const char *value, int overwrite);
+#else
+#  include <clib/dos_protos.h>
+#  include <clib/locale_protos.h>
+#  include <clib/exec_protos.h>
+#  include <pragmas/exec_lib.h>
+#  include <pragmas/dos_lib.h>
+#  include <pragmas/locale_lib.h>
+/* Info-ZIP accesses these by their standard names: */
+#  define __timezone timezone
+#  define __daylight daylight
+#  define __tzset    tzset
+#endif
+#define NO_TIME_H
+#include "amiga/z-time.h"
+#include <exec/execbase.h>
+#include <clib/alib_stdio_protos.h>
+#include <string.h>
+#include <stdlib.h>
+
+extern struct ExecBase *SysBase;
+extern char *getenv(const char *var);
+
+typedef unsigned long time_t;
+struct tm {
+    int tm_sec;      /* seconds after the minute */
+    int tm_min;      /* minutes after the hour */
+    int tm_hour;     /* hours since midnight */
+    int tm_mday;     /* day of the month */
+    int tm_mon;      /* months since January */
+    int tm_year;     /* years since 1900 */
+    int tm_wday;     /* days since Sunday */
+    int tm_yday;     /* days since January 1 */
+    int tm_isdst;    /* Daylight Savings Time flag */
+};
+struct dstdate {
+  enum { JULIAN0, JULIAN, MWD } dd_type;
+  int                           dd_day;
+  int                           dd_week;
+  int                           dd_month;
+  int                           dd_secs;
+};
+static struct dstdate __dststart;
+static struct dstdate __dstend;
+
+#define isleapyear(y)    (((y)%4==0&&(!((y)%100==0)||((y)%400==0)))?1:0)
+#define yearlen(y)       (isleapyear(y)?366:365)
+#define weekday(d)       (((d)+4)%7)
+#define jan1ofyear(y)    (((y)-70)*365+((y)-69)/4-((y)-1)/100+((y)+299)/400)
+#define wdayofyear(y)    weekday(jan1ofyear(y))
+#define AMIGA2UNIX       252460800 /* seconds between 1.1.1970 and 1.1.1978 */
+#define CHECK            300       /* min. time between checks of IXGMTOFFSET */
+#define GETVAR_REQVERS   36L       /* required OS version for GetVar() */
+#define AVAIL_GETVAR     (SysBase->LibNode.lib_Version >= GETVAR_REQVERS)
+#ifndef TZ_ENVVAR
+#  define TZ_ENVVAR      "TZ"      /* environment variable to parse */
+#endif
+
+#ifdef __SASC
+  extern int  __daylight;
+  extern long __timezone;
+  extern char *__tzname[2];
+  extern char *_TZ;
+#else
+  int __daylight;
+  long __timezone;
+  char *__tzname[2];
+  char *_TZ = NULL;
+#endif
+int real_timezone_is_set = FALSE;   /* globally visible TZ_is_valid signal */
+char __tzstn[MAXTIMEZONELEN];
+char __tzdtn[MAXTIMEZONELEN];
+/* the following 4 variables are only used internally; make them static ? */
+int __isdst;
+time_t __nextdstchange;
+long __stdoffset;
+long __dstoffset;
+#define TZLEN 64
+static char TZ[TZLEN];
+static struct tm TM;
+static const unsigned short days[2][13] = {
+  { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+  { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+};
+#ifndef NO_MKTIME     /* only used by mktime() */
+static const unsigned short monlen[2][12] = {
+  { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+  { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+#endif
+
+/* internal prototypes */
+static time_t dst2time(int year,struct dstdate *dst);
+static void time2tm(time_t time);
+static int checkdst(time_t time);
+#ifndef NO_MKTIME
+static void normalize(int *i,int *j,int norm);
+#endif
+static long gettime(char **s);
+static void getdstdate(char **s,struct dstdate *dst);
+#ifdef __SASC
+void set_TZ(long time_zone, int day_light);
+#endif
+
+/* prototypes for sc.lib replacement functions */
+struct tm *gmtime(const time_t *t);
+struct tm *localtime(const time_t *t);
+#ifndef NO_MKTIME
+time_t mkgmtime(struct tm *tm);
+time_t mktime(struct tm *tm);
+#endif
+time_t time(time_t *tm);
+void __tzset(void);
+
+
+static time_t dst2time(int year,struct dstdate *dst)
+{
+  int isleapyear,week,mon,mday;
+  mon = 0;
+  mday = dst->dd_day;
+  isleapyear = isleapyear(year);
+  switch(dst->dd_type) {
+    case JULIAN:
+      if(!isleapyear || dst->dd_day <= 59) break;
+    default:
+      mday++;
+      break;
+    case MWD:
+      mon = dst->dd_month-1;
+      week = dst->dd_week;
+      if(week == 5) {
+        mon++;
+        week = 0;
+      }
+      mday = dst->dd_day - weekday(jan1ofyear(year)+days[isleapyear][mon]);
+      if(mday < 0) mday += 7;
+      mday += (week - 1) * 7 + 1;
+      break;
+  }
+  return((time_t)(jan1ofyear(year)+days[isleapyear][mon]+mday-1)*(time_t)86400L+
+         (time_t)dst->dd_secs);
+}
+
+static void time2tm(time_t time)
+{
+  int isleapyear;
+  TM.tm_sec  = time % 60;
+  time /= 60;
+  TM.tm_min  = time % 60;
+  time /= 60;
+  TM.tm_hour = time % 24;
+  time /= 24;
+  TM.tm_year = time/365 + 70; /* guess year */
+  while((TM.tm_yday = time - jan1ofyear(TM.tm_year)) < 0) TM.tm_year--;
+  isleapyear = isleapyear(TM.tm_year);
+  for(TM.tm_mon = 0;
+      TM.tm_yday >= days[isleapyear][TM.tm_mon+1];
+      TM.tm_mon++);
+  TM.tm_mday = TM.tm_yday - days[isleapyear][TM.tm_mon] + 1;
+  TM.tm_wday = (time+4)%7;
+}
+
+static int checkdst(time_t time)
+{
+  int year,day;
+  time_t t,u;
+  day = time / 86400L;
+  year = day / 365 + 70; /* guess year */
+  while(day - jan1ofyear(year) < 0) year--;
+  t = dst2time(year,&__dststart) + __stdoffset;
+  u = dst2time(year,&__dstend)   + __dstoffset;
+  if(u > t) {
+    return((time >= t && time < u)?1:0);
+  }
+  else {
+    return((time < u || time >= t)?1:0);
+  }
+}
+
+struct tm *gmtime(const time_t *t)
+{
+  TM.tm_isdst = 0;
+  time2tm(*t);
+  return(&TM);
+}
+
+struct tm *localtime(const time_t *t)
+{
+  if(!_TZ) __tzset();
+  TM.tm_isdst = checkdst(*t);
+  time2tm(*t - (TM.tm_isdst ? __dstoffset : __stdoffset));
+  return(&TM);
+}
+
+#ifndef NO_MKTIME   /* normalize() only used by mktime() */
+static void normalize(int *i,int *j,int norm)
+{
+  while(*i < 0) {
+    *i += norm;
+    (*j)--;
+  }
+  while(*i >= norm) {
+    *i -= norm;
+    (*j)++;
+  }
+}
+
+time_t mkgmtime(struct tm *tm)
+{
+  time_t t;
+  normalize(&tm->tm_sec,&tm->tm_min,60);
+  normalize(&tm->tm_min,&tm->tm_hour,60);
+  normalize(&tm->tm_hour,&tm->tm_mday,24);
+  normalize(&tm->tm_mon,&tm->tm_year,12);
+  while(tm->tm_mday > monlen[isleapyear(tm->tm_year)][tm->tm_mon]) {
+    tm->tm_mday -= monlen[isleapyear(tm->tm_year)][tm->tm_mon];
+    tm->tm_mon++;
+    if(tm->tm_mon == 12) {
+      tm->tm_mon = 0;
+      tm->tm_year++;
+    }
+  }
+  while(tm->tm_mday < 0) {
+    tm->tm_mon--;
+    if(tm->tm_mon == -1) {
+      tm->tm_mon = 11;
+      tm->tm_year--;
+    }
+    tm->tm_mday += monlen[isleapyear(tm->tm_year)][tm->tm_mon];
+  }
+  tm->tm_yday = tm->tm_mday + days[isleapyear(tm->tm_year)][tm->tm_mon] - 1;
+  t = jan1ofyear(tm->tm_year) + tm->tm_yday;
+  tm->tm_wday = weekday(t);
+  if(tm->tm_year < 70) return((time_t)0);
+  t = t * 86400L + tm->tm_hour * 3600L + tm->tm_min * 60L + (time_t)tm->tm_sec;
+  return(t);
+}
+
+time_t mktime(struct tm *tm)
+{
+  time_t t;
+  if(!_TZ) __tzset();
+  t = mkgmtime(tm);
+  if(tm->tm_isdst < 0) tm->tm_isdst = checkdst(t);
+  t += tm->tm_isdst ? __dstoffset : __stdoffset;
+  return(t);
+}
+#endif /* !NO_MKTIME */
+
+static long gettime(char **s)
+{
+  long num,time;
+  for(num = 0;**s >= '0' && **s <= '9';(*s)++) {
+    num = 10*num + (**s - '0');
+  }
+  time = 3600L * num;
+  if(**s == ':') {
+    (*s)++;
+    for(num = 0;**s >= '0' && **s <= '9';(*s)++) {
+      num = 10*num + (**s - '0');
+    }
+    time += 60 * num;
+    if(**s == ':') {
+      (*s)++;
+      for(num = 0;**s >= '0' && **s <= '9';(*s)++) {
+        num = 10*num + (**s - '0');
+      }
+      time += num;
+    }
+  }
+  return(time);
+}
+
+static void getdstdate(char **s,struct dstdate *dst)
+{
+  switch(**s) {
+    case 'J':
+    case 'j':
+      (*s)++;
+      dst->dd_type = JULIAN;
+      for(dst->dd_day = 0;**s >= '0' && **s <= '9';(*s)++) {
+        dst->dd_day = 10*dst->dd_day + (**s - '0');
+      }
+      break;
+    case 'M':
+    case 'm':
+      (*s)++;
+      dst->dd_type = MWD;
+      for(dst->dd_month = 0;**s >= '0' && **s <= '9';(*s)++) {
+        dst->dd_month = 10*dst->dd_month + (**s - '0');
+      }
+      if(**s != '.') return;
+      (*s)++;
+      for(dst->dd_week = 0;**s >= '0' && **s <= '9';(*s)++) {
+        dst->dd_week = 10*dst->dd_week + (**s - '0');
+      }
+      if(**s != '.') return;
+      (*s)++;
+      for(dst->dd_day = 0;**s >= '0' && **s <= '9';(*s)++) {
+        dst->dd_day = 10*dst->dd_day + (**s - '0');
+      }
+      break;
+    default:
+      dst->dd_type = JULIAN0;
+      for(dst->dd_day = 0;**s >= '0' && **s <= '9';(*s)++) {
+        dst->dd_day = 10*dst->dd_day + (**s - '0');
+      }
+      break;
+  }
+  if(**s == '/') {
+    (*s)++;
+    dst->dd_secs = gettime(s);
+  }
+}
+
+void __tzset(void)
+{
+  char *s,*t;
+  int minus = 0;
+  time_t tm;
+  struct Library *LocaleBase;
+  struct Locale *loc = NULL;
+  if (real_timezone_is_set)
+    return;
+  real_timezone_is_set = TRUE;
+  __dststart.dd_secs = __dstend.dd_secs = 7200;
+  __dststart.dd_type = __dstend.dd_type = MWD;
+  __dststart.dd_month = 4;
+  __dststart.dd_week = 1;
+  __dstend.dd_month = 10;
+  __dstend.dd_week = 5;
+  __dststart.dd_day = __dstend.dd_day = 0; /* sunday */
+  _TZ = NULL;
+  if (AVAIL_GETVAR) {                /* GetVar() available? */
+    if(GetVar(TZ_ENVVAR,TZ,TZLEN,GVF_GLOBAL_ONLY) > 0)
+      _TZ = TZ;
+  } else
+      _TZ = getenv(TZ_ENVVAR);
+  if (_TZ == NULL || !_TZ[0]) {
+    static char gmt[MAXTIMEZONELEN] = DEFAULT_TZ_STR;
+    LocaleBase = OpenLibrary("locale.library",0);
+    if(LocaleBase) {
+      loc = OpenLocale(0);  /* cannot return null */
+      if (loc->loc_GMTOffset == -300 || loc->loc_GMTOffset == 300) {
+        BPTR eh;
+        if (eh = Lock("ENV:sys/locale.prefs", ACCESS_READ))
+          UnLock(eh);
+        else {
+          real_timezone_is_set = FALSE;
+          loc->loc_GMTOffset = 300; /* Amigados bug: default when locale is */
+        }                           /* not initialized can have wrong sign  */
+      }
+      sprintf(gmt, "GMT%ld:%02ld", loc->loc_GMTOffset / 60L,
+              labs(loc->loc_GMTOffset) % 60L);
+      CloseLocale(loc);
+      CloseLibrary(LocaleBase);
+    } else
+      real_timezone_is_set = FALSE;
+    _TZ = gmt;
+  }
+  for(s = _TZ,t = __tzstn;*s && *s != '+' && *s != '-' && *s != ',' &&
+      (*s < '0' || *s > '9');s++) {
+    if(t-__tzstn < MAXTIMEZONELEN-1) *(t++) = *s;
+  }
+  *t = '\0';
+  if(*s == '+') {
+    s++;
+  }
+  else {
+    if(*s == '-') {
+      minus = 1;
+      s++;
+    }
+  }
+  __stdoffset = gettime(&s);
+  if(minus) {
+    __stdoffset *= -1;
+  }
+  if(*s) {
+    minus = 0;
+    for(t = __tzdtn;*s && *s != '+' && *s != '-' && *s != ',' &&
+        (*s < '0' || *s > '9');s++) {
+      if(t-__tzdtn < MAXTIMEZONELEN-1) *(t++) = *s;
+    }
+    *t = '\0';
+    if(*s == '+') {
+      s++;
+    }
+    else {
+      if(*s == '-') {
+        minus = 1;
+        s++;
+      }
+    }
+    if(*s && *s != ',') {
+      __dstoffset = gettime(&s);
+      if(minus) {
+        __dstoffset *= -1;
+      }
+    }
+    else {
+      __dstoffset = __stdoffset - 3600L;
+    }
+    if(*s == ',') {
+      s++;
+      getdstdate(&s,&__dststart);
+      if(*s == ',') {
+        s++;
+        getdstdate(&s,&__dstend);
+      }
+    }
+  }
+  else {
+    __dstoffset = __stdoffset;
+  }
+  time2tm(time(&tm));
+  __isdst = checkdst(tm);
+  __daylight = (__dstoffset != __stdoffset);
+  __timezone = __stdoffset;
+  __nextdstchange = dst2time(TM.tm_year, __isdst ? &__dstend : &__dststart);
+  if(tm >= __nextdstchange) {
+    __nextdstchange = dst2time(TM.tm_year+1,
+                               __isdst ? &__dstend : &__dststart);
+  }
+  __tzname[0] = __tzstn;
+  __tzname[1] = __tzdtn;
+#ifdef __SASC
+  if (loc)         /* store TZ envvar if data read from locale */
+    set_TZ(__timezone, __daylight);
+#endif
+}
+
+time_t time(time_t *tm)
+{
+  static time_t last_check = 0;
+  static struct _ixgmtoffset {
+    LONG  Offset;
+    UBYTE DST;
+    UBYTE Null;
+  } ixgmtoffset;
+  static char *envvarstr; /* ptr to environm. string (used if !AVAIL_GETVAR) */
+  struct DateStamp ds;
+  time_t now;
+  DateStamp(&ds);
+  now = ds.ds_Days * 86400L + ds.ds_Minute * 60L +
+        ds.ds_Tick / TICKS_PER_SECOND;
+  if(now - last_check > CHECK) {
+    last_check = now;
+    if (AVAIL_GETVAR)    /* GetVar() available? */
+      if(GetVar("IXGMTOFFSET",(STRPTR)&ixgmtoffset,6,
+                GVF_BINARY_VAR|GVF_GLOBAL_ONLY) == -1) {
+        __tzset();
+        ixgmtoffset.Offset = __isdst ? __dstoffset : __stdoffset;
+      }
+    else
+      if (envvarstr=getenv("IXGMTOFFSET")) {
+        ixgmtoffset = *((struct _ixgmtoffset *)envvarstr);  /* copy to struct */
+        __tzset();
+        ixgmtoffset.Offset = __isdst ? __dstoffset : __stdoffset;
+      }
+  }
+  now += AMIGA2UNIX;
+  now += ixgmtoffset.Offset;
+  if(tm) *tm = now;
+  return(now);
+}
+
+#ifdef __SASC
+
+/* Stores data from timezone and daylight to ENV:TZ.                  */
+/* ENV:TZ is required to exist by some other SAS/C library functions, */
+/* like stat() or fstat().                                            */
+void set_TZ(long time_zone, int day_light)
+{
+  char put_tz[MAXTIMEZONELEN];  /* string for putenv: "TZ=aaabbb:bb:bbccc" */
+  int offset;
+  void *exists;     /* dummy ptr to see if global envvar TZ already exists */
+  if (AVAIL_GETVAR)
+     exists = (void *)FindVar(TZ_ENVVAR,GVF_GLOBAL_ONLY);  /* OS V36+ */
+  else
+     exists = (void *)getenv(TZ_ENVVAR);
+  /* see if there is already an envvar TZ_ENVVAR. If not, create it */
+  if (exists == NULL) {
+    /* create TZ string by pieces: */
+    sprintf(put_tz, "GMT%+ld", time_zone / 3600L);
+    if (time_zone % 3600L) {
+      offset = (int) labs(time_zone % 3600L);
+      sprintf(put_tz + strlen(put_tz), ":%02d", offset / 60);
+      if (offset % 60)
+        sprintf(put_tz + strlen(put_tz), ":%02d", offset % 60);
+    }
+    if (day_light)
+      strcat(put_tz,"DST");
+    if (AVAIL_GETVAR)       /* store TZ to ENV:TZ. */
+       SetVar(TZ_ENVVAR,put_tz,-1,GVF_GLOBAL_ONLY);     /* OS V36+ */
+    else
+       setenv(TZ_ENVVAR,put_tz, 1);
+  }
+}
+#endif /* __SASC */
diff --git a/amiga/timezone.doc b/amiga/timezone.doc
new file mode 100644 (file)
index 0000000..7868093
--- /dev/null
@@ -0,0 +1,85 @@
+Timezone strings:
+-----------------
+This is a description of valid timezone strings for ENV[ARC]:TZ:
+"XPG3TZ - time zone information"
+The form of the time zone information is based on the XPG3 specification of
+the TZ environment variable.  Spaces are allowed only in timezone
+designations, where they are significant.  The following description
+closely follows the XPG3 specification, except for the paragraphs starting
+**CLARIFICATION**.
+
+<std><offset>[<dst>[<offset>],<start>[/<time>],<end>[/<time>]]
+
+Where:
+<std> and <dst>
+      Are each three or more bytes that are the designation for the
+      standard (<std>) and daylight savings time (<dst>) timezones.
+      Only <std> is required - if <dst> is missing, then daylight
+      savings time does not apply in this locale.  Upper- and
+      lower-case letters are allowed.  Any characters except a
+      leading colon (:), digits, a comma (,), a minus (-) or a plus
+      (+) are allowed.
+      **CLARIFICATION**  The two-byte designation `UT' is permitted.
+<offset>
+      Indicates the value one must add to the local time to arrive
+      at Coordinated Universal Time.  The offset has the form:
+      <hh>[:<mm>[:<ss>]]
+      The minutes <mm> and seconds <ss> are optional.  The hour <hh>
+      is required and may be a single digit.  The offset following
+      <std> is required.  If no offset follows <dst>, daylight savings
+      time is assumed to be one hour ahead of standard time.  One or
+      more digits may be used; the value is always interpreted as a
+      decimal number.  The hour must be between 0 and 24, and the
+      minutes (and seconds) if present between 0 and 59.  Out of
+      range values may cause unpredictable behavior.  If preceded by
+      a `-', the timezone is east of the Prime Meridian; otherwise
+      it is west (which may be indicated by an optional preceding
+      `+' sign).
+      **CLARIFICATION**  No more than two digits are allowed in any
+      of <hh>, <mm> or <ss>.  Leading zeros are permitted.
+<start>/<time> and <end>/<time>
+      Indicates when to change to and back from daylight savings
+      time, where <start>/<time> describes when the change from
+      standard time to daylight savings time occurs, and
+      <end>/<time> describes when the change back happens.  Each
+      <time> field describes when, in current local time, the change
+      is made.
+      **CLARIFICATION**  It is recognized that in the Southern
+      hemisphere <start> will specify a date later than <end>.
+      The formats of <start> and <end> are one of the following:
+      J<n>    The Julian day <n> (1 <= <n> <= 365).  Leap days are not
+              counted.  That is, in all years, February 28 is day 59
+              and March 1 is day 60.  It is impossible to refer to
+              the occasional February 29.
+      <n>     The zero-based Julian day (0 <= <n> <= 365).  Leap days
+              are counted, and it is possible to refer to February
+              29.
+      M<m>.<n>.<d>
+              The <d>th day, (0 <= <d> <= 6) of week <n> of month <m>
+              of the year (1 <= <n> <= 5, 1 <= <m> <= 12), where week
+              5 means `the last <d>-day in month <m>' (which may
+              occur in either the fourth or the fifth week).  Week 1
+              is the first week in which the <d>th day occurs.  Day
+              zero is Sunday.
+              **CLARIFICATION**  Neither <n> nor <m> may have a
+              leading zero.  <d> must be a single digit.
+              **CLARIFICATION**  The default <start> and <end> values
+              are from the first Sunday in April until the last Sunday
+              in October.  This allows United States users to leave out
+              the <start> and <end> parts, as most are accustomed to
+              doing.
+      <time> has the same format as <offset> except that no leading
+      sign (`-' or `+') is allowed.  The default, if <time> is not
+      given is 02:00:00.
+      **CLARIFICATION**  The number of hours in <time> may be up
+      to 167, to allow encoding of rules such as `00:00hrs on the
+      Sunday after the second Friday in September'
+
+Example (for Central Europe):
+-----------------------------
+MET-1MEST,M3.5.0,M10.5.0/03
+
+Another example, for the US East Coast:
+---------------------------------------
+EST5EDT4,M4.1.0/02,M10.5.0/02
+This string describes the default values when no time zone is set.
diff --git a/amiga/z-stat.h b/amiga/z-stat.h
new file mode 100644 (file)
index 0000000..bb33b34
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __amiga_z_stat_h
+#define __amiga_z_stat_h
+
+/* Since older versions of the Lattice C compiler for Amiga, and all current */
+/* versions of the Manx Aztec C compiler for Amiga, either provide no stat() */
+/* function or provide one inadequate for unzip (Aztec's has no st_mode      */
+/* field), we provide our own stat() function in stat.c by Paul Wells, and   */
+/* this fake stat.h file by Paul Kienitz.  Paul Wells originally used the    */
+/* Lattice stat.h but that does not work for Aztec and is not distributable  */
+/* with this package, so I made a separate one.  This has to be pulled into  */
+/* unzip.h when compiling an Amiga version, as "amiga/z-stat.h".             */
+
+/* We also provide here a "struct dirent" for use with opendir() & readdir() */
+/* functions included in amiga/stat.c.  If you use amiga/stat.c, this must   */
+/* be included wherever you use either readdir() or stat().                  */
+
+#ifdef AZTEC_C
+#  define __STAT_H
+#else  /* __SASC */
+/* do not include the following header, replacement definitions are here */
+#  define _STAT_H      /* do not include SAS/C <stat.h> */
+#  define _DIRENT_H    /* do not include SAS/C <dirent.h> */
+#  define _SYS_DIR_H   /* do not include SAS/C <sys/dir.h> */
+#  define _COMMIFMT_H  /* do not include SAS/C <sys/commifmt.h> */
+#  include <dos.h>
+#endif
+#include <libraries/dos.h>
+#include "amiga/z-time.h"
+
+
+struct stat {
+    unsigned short st_mode;
+    time_t st_ctime, st_atime, st_mtime;
+    long st_size;
+    long st_ino;
+    long st_blocks;
+    short st_attr, st_dev, st_nlink, st_uid, st_gid, st_rdev;
+};
+
+#define S_IFDIR  (1<<11)
+#define S_IFREG  (1<<10)
+
+#if 0
+   /* these values here are totally random: */
+#  define S_IFLNK  (1<<14)
+#  define S_IFSOCK (1<<13)
+#  define S_IFCHR  (1<<8)
+#  define S_IFIFO  (1<<7)
+#  define S_IFMT   (S_IFDIR|S_IFREG|S_IFCHR|S_IFLNK)
+#else
+#  define S_IFMT   (S_IFDIR|S_IFREG)
+#endif
+
+#define S_IHIDDEN    (1<<7)
+#define S_ISCRIPT    (1<<6)
+#define S_IPURE      (1<<5)
+#define S_IARCHIVE   (1<<4)
+#define S_IREAD      (1<<3)
+#define S_IWRITE     (1<<2)
+#define S_IEXECUTE   (1<<1)
+#define S_IDELETE    (1<<0)
+
+int stat(const char *name, struct stat *buf);
+int fstat(int handle, struct stat *buf);      /* returns dummy values */
+
+typedef struct dirent {
+    struct dirent       *d_cleanuplink,
+                       **d_cleanupparent;
+    BPTR                 d_parentlock;
+    struct FileInfoBlock d_fib;
+} DIR;
+#define                  d_name  d_fib.fib_FileName
+
+extern unsigned short disk_not_mounted;         /* flag set by opendir() */
+
+DIR *opendir(const char *);
+void closedir(DIR *);
+void close_leftover_open_dirs(void);    /* call this if aborted in mid-run */
+struct dirent *readdir(DIR *);
+int umask(void);
+
+#ifdef AZTEC_C
+int rmdir(const char *);
+int chmod(const char *filename, int bits);
+#endif
+
+#endif /* __amiga_z_stat_h */
diff --git a/amiga/z-time.h b/amiga/z-time.h
new file mode 100644 (file)
index 0000000..53c01bf
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __amiga_z_time_h
+#define __amiga_z_time_h
+
+/* A <time.h> replacement for use with time_lib.c */
+/* Usage: * Define (or Undefine) USE_TIME_LIB below             */
+/*        * Replace any <time.h> includes by "amiga/z-time.h"   */
+
+/* First of all: Select whether to use time_lib functions or not */
+#if 1
+#  ifndef USE_TIME_LIB
+#  define USE_TIME_LIB
+#  endif
+#else
+#  ifdef USE_TIME_LIB
+#  undef USE_TIME_LIB
+#  endif
+#endif
+
+#ifdef USE_TIME_LIB
+   /* constants needed everywhere */
+#  define MAXTIMEZONELEN 16
+#  ifndef DEFAULT_TZ_STR
+#    define DEFAULT_TZ_STR "EST5EDT" /* US East Coast is the usual default */
+#  endif
+
+   /* define time_t where needed (everywhere but amiga/time_lib.c) */
+#  if defined(__SASC) && defined(NO_TIME_H) && !defined(__amiga_time_lib_c)
+     typedef unsigned long time_t;  /* override sas/c's time_t */
+#    define _TIME_T        1        /* mark it as already defined */
+#    define _COMMTIME_H             /* do not include sys/commtime.h */
+#  endif
+
+#  ifndef NO_TIME_H
+#    include <time.h>               /* time_lib.c uses NO_TIME_H */
+#  endif
+
+   /* adjust included time.h */
+#  ifdef __SASC
+     /* tz[sd]tn arrays have different length now: need different names */
+#    define __tzstn         tzstn
+#    define __tzdtn         tzdtn
+     /* prevent other possible name conflicts */
+#    define __nextdstchange nextdstchange
+#    define __stdoffset     stdoffset
+#    define __dstoffset     dstoffset
+
+#    ifndef __amiga_time_lib_c
+#      ifdef TZ
+#        undef TZ                       /* defined in sas/c time.h */
+#      endif TZ
+#      define TZ  DEFAULT_TZ_STR        /* redefine TZ to default timezone */
+       extern char __tzstn[MAXTIMEZONELEN];
+       extern char __tzdtn[MAXTIMEZONELEN];
+#    endif
+#  endif /* __SASC */
+
+#  ifdef AZTEC_C
+     void tzset(void);
+#  endif
+
+#else /* ?USE_TIME_LIB */
+
+#  ifndef NO_TIME_H
+#    include <time.h>
+#  endif
+#endif /* !USE_TIME_LIB */
+
+#endif /* __amiga_z_time_h */
diff --git a/amiga/zipup.h b/amiga/zipup.h
new file mode 100644 (file)
index 0000000..c9316f4
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __amiga_zipup_h
+#define __amiga_zipup_h
+
+#ifndef O_RAW
+#  define O_RAW      0
+#endif
+#define fhow         (O_RDONLY | O_RAW)
+#define fbad         (-1)
+typedef int          ftype;
+#define zopen(n,p)   open(n,p)
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f)    close(f)
+#define zerr(f)      (k == (extent)(-1L))
+#define zstdin       0
+
+#endif /* __amiga_zipup_h */
+
diff --git a/aosvs/aosvs.c b/aosvs/aosvs.c
new file mode 100644 (file)
index 0000000..3add126
--- /dev/null
@@ -0,0 +1,662 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include <dirent.h>
+#include <time.h>
+
+#include "zip.h"
+#include <paru.h>                 /* parameter definitions */
+#include <sys_calls.h>            /* AOS/VS system call interface */
+#include <packets/filestatus.h>   /* AOS/VS ?FSTAT packet defs */
+
+#ifndef UTIL            /* AOS/VS specific fileio code not needed for UTILs */
+
+#define PAD 0
+#define PATH_END ':'
+
+/*
+ * could probably avoid the union -
+ * all are same size & we're going to assume this
+ */
+typedef union zvsfstat_stru
+{
+     P_FSTAT        norm_fstat_packet;      /* normal fstat packet */
+     P_FSTAT_DIR    dir_fstat_packet;       /* DIR/CPD fstat packet */
+     P_FSTAT_UNIT   unit_fstat_packet;      /* unit (device) fstat packet */
+     P_FSTAT_IPC    ipc_fstat_packet;       /* IPC file fstat packet */
+} ZVSFSTAT_STRU;
+
+typedef struct zextrafld
+{
+     char           extra_header_id[2]; /* set to VS - in theory, an int */
+     char           extra_data_size[2]; /* size of rest, in Intel little-endian order */
+     char           extra_sentinel[4];  /* set to FCI w/ trailing null */
+     unsigned char  extra_rev;          /* set to 10 for rev 1.0 */
+     ZVSFSTAT_STRU  fstat_packet;       /* the fstat packet */
+     char           aclbuf[$MXACL];     /* raw ACL, or link-resolution name */
+} ZEXTRAFLD;
+
+#define ZEXTRA_HEADID   "VS"
+#define ZEXTRA_SENTINEL "FCI"
+#define ZEXTRA_REV      (unsigned char) 10
+
+local ZEXTRAFLD   zzextrafld;         /* buffer for extra field containing
+                                         ?FSTAT packet & ACL buffer */
+local char        zlinkres[$MXPL];    /* buf for link resolution contents */
+local char        znamebuf[$MXPL];    /* buf for AOS/VS filename */
+static char     vsnamebuf[$MXPL];
+static char     uxnamebuf[FNMAX];
+static P_FSTAT  vsfstatbuf;
+
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+/* Local functions */
+local char *readd OF((DIR *));
+
+char *readd(d)
+DIR *d;                 /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+   no more entries or an error occurs. */
+{
+  struct dirent *e;
+
+  e = readdir(d);
+  return e == NULL ? (char *) NULL : e->d_name;
+}
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  char *a;              /* path and name for recursion */
+  DIR *d;               /* directory stream from opendir() */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (LSSTAT(n, &s))
+  {
+    /* Not a file or directory--search for shell expression in zip file */
+    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+  if ((s.st_mode & S_IFDIR) == 0)
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  } else {
+    /* Add trailing / to the directory name */
+    if ((p = malloc(strlen(n)+2)) == NULL)
+      return ZE_MEM;
+    if (strcmp(n, ".") == 0) {
+      *p = '\0';  /* avoid "./" prefix and do not create zip entry */
+    } else {
+      strcpy(p, n);
+      a = p + strlen(p);
+      if (a[-1] != '/')
+        strcpy(a, "/");
+      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+        free((zvoid *)p);
+        return m;
+      }
+    }
+    /* recurse into directory */
+    if (recurse && (d = opendir(n)) != NULL)
+    {
+      while ((e = readd(d)) != NULL) {
+        if (strcmp(e, ".") && strcmp(e, ".."))
+        {
+          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+          {
+            closedir(d);
+            free((zvoid *)p);
+            return ZE_MEM;
+          }
+          strcat(strcpy(a, p), e);
+          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
+          {
+            if (m == ZE_MISS)
+              zipwarn("name not matched: ", a);
+            else
+              ziperr(m, a);
+          }
+          free((zvoid *)a);
+        }
+      }
+      closedir(d);
+    }
+    free((zvoid *)p);
+  } /* (s.st_mode & S_IFDIR) == 0) */
+  return ZE_OK;
+}
+
+char *strlower(s)
+char *s;                /* string to convert */
+/* Convert all uppercase letters to lowercase in string s */
+{
+  char *p;              /* scans string */
+
+  for (p = s; *p; p++)
+    if (*p >= 'A' && *p <= 'Z')
+      *p += 'a' - 'A';
+  return s;
+}
+
+char *strupper(s)
+char *s;                /* string to convert */
+/* Convert all lowercase letters to uppercase in string s */
+{
+  char *p;              /* scans string */
+
+  for (p = s; *p; p++)
+    if (*p >= 'a' && *p <= 'z')
+      *p -= 'a' - 'A';
+  return s;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t;              /* shortened name */
+  int dosflag;
+
+  dosflag = dosify; /* default for non-DOS and non-OS/2 */
+
+  /* Find starting point in name before doing malloc */
+  for (t = x; *t == '/'; t++)
+    ;
+
+  if (*t == '=')                /* AOS/VS for ./ */
+    t++;
+  else if (*t == ':')           /* AOS/VS for / */
+    t++;
+
+  if (!pathput)
+    t = last(t, PATH_END);
+
+  if (*t == '^')        /* AOS/VS for ../ */
+  {
+    if ((n = malloc(strlen(t) + 3)) == NULL)
+      return NULL;
+    strcpy(n, "../");
+    strcpy(n + 3, t + 1);
+  }
+  else if (*t == '@')   /* AOS/VS for :PER:, kind of like /dev/ */
+  {
+    if ((n = malloc(strlen(t) + 5)) == NULL)
+      return NULL;
+    strcpy(n, "/PER/");
+    strcpy(n + 5, t + 1);
+  }
+  else
+  {
+    if ((n = malloc(strlen(t) + 1)) == NULL)
+      return NULL;
+    strcpy(n, t);
+  }
+  /* now turn AOS/VS dir separators (colons) into slashes */
+  for (t = n;  *t != '\0';  t++)
+    if (*t == ':')
+      *t = '/';
+  /*
+   * Convert filename to uppercase (for correct matching).
+   * (It may make more sense to patch the matching code, since
+   * we may want those filenames in uppercase on the target system,
+   * but this seems better at present.  If we're converting, uppercase
+   * also seems to make sense.)
+   */
+  strupper(n);
+
+
+  if (dosify)
+    msname(n);
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+  return n;
+}
+
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+
+  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+      return NULL;
+  strcpy(x, n);
+
+  return x;
+}
+
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+  time_t u[2];          /* argument for utime() */
+
+  /* Convert DOS time to time_t format in u */
+  u[0] = u[1] = dos2unixtime(d);
+  utime(f, u);
+}
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  char *name;
+  unsigned int len = strlen(f);
+
+  if (f == label) {
+    if (a != NULL)
+      *a = label_mode;
+    if (n != NULL)
+      *n = -2L; /* convention for a label name */
+    if (t != NULL)
+      t->atime = t->mtime = t->ctime = label_utim;
+    return label_time;
+  }
+
+  if ((name = malloc(len + 1)) == NULL) {
+    ZIPERR(ZE_MEM, "filetime");
+  }
+  strcpy(name, f);
+  if (name[len - 1] == '/')
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+
+  if (strcmp(f, "-") == 0) {
+    if (fstat(fileno(stdin), &s) != 0) {
+      free(name);
+      error("fstat(stdin)");
+    }
+  } else if (LSSTAT(name, &s) != 0) {
+             /* Accept about any file kind including directories
+              * (stored with trailing / with -r option)
+              */
+    free(name);
+    return 0;
+  }
+
+  if (a != NULL) {
+    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
+    if ((s.st_mode & S_IFDIR) != 0) {
+      *a |= MSDOS_DIR_ATTR;
+    }
+  }
+  if (n != NULL)
+    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = s.st_ctime;
+  }
+
+  free(name);
+
+  return unix2dostime(&s.st_ctime);
+}
+
+int deletedir(d)
+char *d;
+{
+   return rmdir(d);
+}
+
+int set_extra_field(z, z_utim)
+  struct zlist far *z;
+  iztimes *z_utim;
+  /* create extra field and change z->att if desired */
+  /* NOTE: this AOS/VS version assumes the pathname in z->name is an
+   * AOS/VS pathname, not a unix-style one.  Since you can zip up using
+   * unix-style pathnames, this may create problems occasionally.
+   * We COULD add code to parse back to AOS/VS format ...
+   * (This might also fail for other reasons such as access denied, but
+   * that should already have occurred.)
+   * We set the central-dir extra fld pointer & length here to the same data.
+   */
+{
+  int             aclend = 0;
+/*
+ * use this to simplify because different calls depending on
+ * whether links are resolved
+ */
+  unsigned short  errc;
+
+  z->ext = 0;               /* init to no extra field */
+/* get the ?FSTAT info & the acl - if no errors, get memory & store.
+ * (first, we have to cut off the trailing slash that was added if
+ * it's a dir, since AOS/VS doesn't accept that kind of thing)
+ */
+  strncpy(znamebuf, z->name, $MXPL);
+  znamebuf[$MXPL-1] = '\0';
+  if (znamebuf[strlen(znamebuf)-1] == '/')
+    znamebuf[strlen(znamebuf)-1] = '\0';
+  if (linkput)
+    errc = sys_fstat(znamebuf, BIT1, &(zzextrafld.fstat_packet));
+  else
+    errc = sys_fstat(znamebuf, 0, &(zzextrafld.fstat_packet));
+  if (errc)
+  {
+    fprintf(stderr,
+            "\n    Warning: can't get ?FSTAT info & acl of %s - error %d\n    ",
+            znamebuf, errc);
+    perror("sys_fstat()");
+  }
+  else
+  {
+    /* store the ACL - or, if a link (no ACL!), store the resolution name */
+    if (zzextrafld.fstat_packet.norm_fstat_packet.styp_type != $FLNK)
+    {
+      if ((errc = sys_gacl(znamebuf, zzextrafld.aclbuf)) != 0)
+      {
+        fprintf(stderr, "\n    Warning: can't get acl of %s - error %d\n    ",
+                z->name, errc);
+        perror("sys_gacl()");
+      }
+      else
+      {
+        /* find length of ACL - ends with double-null */
+        while (aclend++ < $MXACL  &&
+               (zzextrafld.aclbuf[aclend - 1] != '\0'  ||
+                zzextrafld.aclbuf[aclend] != '\0'))
+          /* EMPTY LOOP */ ;
+        if ((z->cextra = z->extra =
+             malloc(sizeof(ZEXTRAFLD) - $MXACL + aclend + 4)) != NULL)
+        {
+          strncpy(zzextrafld.extra_header_id, ZEXTRA_HEADID,
+                  sizeof(zzextrafld.extra_header_id));
+          strncpy(zzextrafld.extra_sentinel, ZEXTRA_SENTINEL,
+                  sizeof(zzextrafld.extra_sentinel));
+          zzextrafld.extra_rev = ZEXTRA_REV;    /* this is a char, no need
+                                                   to worry about byte order */
+          /* set size (Intel (little-endian)) 2-byte int, which we've set
+             as array to make it easier */
+          errc = (unsigned short) (sizeof(ZEXTRAFLD) - $MXACL + aclend + 4 -
+                                   sizeof(zzextrafld.extra_header_id) -
+                                   sizeof(zzextrafld.extra_data_size));
+          zzextrafld.extra_data_size[0] = errc & 0xFF;  /* low-order byte */
+          zzextrafld.extra_data_size[1] = errc >> 8;    /* high-order byte */
+          memcpy((char *) z->extra, (char *) &zzextrafld,
+                 sizeof(ZEXTRAFLD) - $MXACL + aclend + 4);
+          z->cext = z->ext = sizeof(ZEXTRAFLD) - $MXACL + aclend + 4;
+        }
+      }
+    }
+    else /* a link */
+    {
+      if ((errc = sys_glink(z->name, zzextrafld.aclbuf)) != 0)
+      {
+        fprintf(stderr,
+              "\n    Warning: can't get link-resolution of %s - error %d\n    ",
+                z->name, errc);
+        perror("sys_glink()");
+      }
+      else
+      {
+        aclend = strlen(zzextrafld.aclbuf) + 1;
+        if ((z->extra = malloc(sizeof(ZEXTRAFLD) - $MXACL + aclend + 4))
+            != NULL)
+        {
+          strncpy(zzextrafld.extra_header_id, ZEXTRA_HEADID,
+                  sizeof(zzextrafld.extra_header_id));
+          strncpy(zzextrafld.extra_sentinel, ZEXTRA_SENTINEL,
+                  sizeof(zzextrafld.extra_sentinel));
+          zzextrafld.extra_rev = ZEXTRA_REV;    /* this is a char, no need
+                                                   to worry about byte order */
+          /* set size (Intel (little-endian)) 2-byte int, which we've set
+             as array to make it easier */
+          errc = (unsigned short) (sizeof(ZEXTRAFLD) - $MXACL + aclend + 4 -
+                                   sizeof(zzextrafld.extra_header_id) -
+                                   sizeof(zzextrafld.extra_data_size));
+          zzextrafld.extra_data_size[0] = errc & 0xFF;  /* low-order byte */
+          zzextrafld.extra_data_size[1] = errc >> 8;    /* high-order byte */
+          memcpy((char *) z->extra, (char *) &zzextrafld,
+                 sizeof(ZEXTRAFLD) - $MXACL + aclend + 4);
+          z->ext = sizeof(ZEXTRAFLD) - $MXACL + aclend + 4;
+        }
+      }
+    }
+  }
+  return ZE_OK;
+}
+
+#endif /* !UTIL */
+
+void version_local()
+{
+    printf("Compiled with %s under %s.\n",
+      "a C compiler",
+      "AOS/VS"
+    );
+}
+
+
+/*
+ * This file defines for AOS/VS two Unix functions relating to links;
+ * the calling code should have the following defines:
+ *
+ *    #define       lstat(path,buf)             zvs_lstat(path,buf)
+ *    #define       readlink(path,buf,nbytes)   zvs_readlink(path,buf,nbytes)
+ *
+ * For these functions, I'm going to define yet 2 MORE filename buffers
+ * and also insert code to change pathnames to Unix & back.  This is
+ * easier than changing all the other places this kind of thing happens to
+ * be efficient.  This is a kludge.  I'm also going to put the functions
+ * here for my immediate convenience rather than somewhere else for
+ * someone else's.
+ *
+ * WARNING: the use of static buffers means that you'd better get your
+ * data out of these buffers before the next call to any of these functions!
+ *
+ */
+
+/* =========================================================================
+ * ZVS_LSTAT() - get (or simulate) stat information WITHOUT following symlinks
+ *      This is intended to look to the outside like the unix lstat()
+ *      function.  We do a quick-&-dirty filename conversion.
+ *
+ *      If the file is NOT a symbolic link, we can just do a stat() on it and
+ *      that should be fine.  But if it IS a link, we have to set the elements
+ *      of the stat struct ourselves, since AOS/VS doesn't have a built-in
+ *      lstat() function.
+ *
+ *      RETURNS: 0 on success, or -1 otherwise
+ *
+ */
+
+int zvs_lstat(char *path, struct stat *buf)
+{
+    char        *cp_vs = vsnamebuf;
+    char        *cp_ux = path;
+    int         mm, dd, yy;
+
+    /*
+     * Convert the Unix pathname to an AOS/VS pathname.
+     * This is quick & dirty; it won't handle (for instance) pathnames with
+     * ../ in the middle of them, and may choke on other Unixisms.  We hope
+     * they're unlikely.
+     */
+    if (!strncmp(cp_ux, "../", 3))
+    {
+        *cp_vs++ = '^';        /* AOS/VS for ../ */
+        cp_ux += 3;
+    }
+    else if (!strncmp(cp_ux, "./", 2))
+    {
+        *cp_vs++ = '=';        /* AOS/VS for ./ */
+        cp_ux += 2;
+    }
+
+    do
+    {
+        if (*cp_ux == '/')
+        {
+            *cp_vs++ = ':';
+        }
+        else
+        {
+            *cp_vs++ = (char) toupper(*cp_ux);
+        }
+
+    } while (*cp_ux++ != '\0'  &&  cp_vs - vsnamebuf < sizeof(vsnamebuf));
+
+    /* If Unix name was too long for our buffer, return an error return */
+    if (cp_vs - vsnamebuf >= sizeof(vsnamebuf)  &&  *(cp_vs - 1) != '\0')
+        return (-1);     /* error */
+
+    /* Make AOS/VS ?FSTAT call that won't follow links & see if we find
+     * anything.  If not, we return error.
+     */
+    if (sys_fstat(vsnamebuf,
+                  BIT1,                 /* BIT1 says to not resolve links */
+                  &vsfstatbuf))
+        return (-1);     /* error */
+
+    /* If we DID find the file but it's not a link,
+     * call stat() and return its value.
+     */
+    if (vsfstatbuf.styp_type != $FLNK)
+        return (stat(path, buf));        /* call with Unix pathname ... */
+
+    /* Otherwise, we have to kludge up values for the stat structure */
+    memset((char *) buf, 0, sizeof(*buf));   /* init to nulls (0 values) */
+    buf->st_mode = S_IFLNK | 0777;           /* link and rwxrwxrwx */
+    buf->st_uid = -1;                        /* this is what we get on AOS/VS
+                                                anyway (maybe unless we set up
+                                                a dummy password file?) */
+    buf->st_nlink = 1;
+    /* The DG date we've got is days since 12/31/67 and seconds/2.  So we
+     * need to subtract 732 days (if that's not negative), convert to seconds,
+     * and add adjusted seconds.
+     */
+    if (vsfstatbuf.stch.short_time[0] < 732)
+        buf->st_ctime = buf->st_mtime = buf->st_atime = 0L;
+    else
+    {
+        buf->st_ctime = buf->st_mtime = buf->st_atime =
+                ((long) vsfstatbuf.stch.short_time[0] - 732L) * 24L * 3600L +
+                2L * (long) vsfstatbuf.stch.short_time[1];
+    }
+
+    /* And we need to get the filename linked to and use its length as
+     * the file size.  We'll use the Unix pathname buffer for this - hope
+     * it's big enough.  (We won't overwrite anything, but we could get a
+     * truncated path.)  If there's an error, here's our last chance to
+     * say anything.
+     */
+    if ((buf->st_size = zvs_readlink(vsnamebuf, uxnamebuf, FNMAX)) < 0)
+        return (-1);
+    else
+        return (0);
+
+} /* end zvs_lstat() */
+
+/* =========================================================================
+ * ZVS_READLINK() - get pathname pointed to by an AOS/VS link file
+ *      This is intended to look to the outside like the unix readlink()
+ *      function.  We do a quick-&-dirty filename conversion.
+ *
+ *      RETURNS: the length of the output path (in bytes), or -1 if an error
+ *
+ */
+
+int zvs_readlink(char *path, char *buf, int nbytes)
+{
+    char    *cp_vs = vsnamebuf;
+    char    *cp_ux = buf;
+
+    /* This is called with z->name, the filename the user gave, so we'll get
+     * the link-resolution name on the assumption that it's a valid AOS/VS
+     * name. We're also assuming a reasonable value (> 5) for nbytes.
+     */
+    if (sys_glink(path, vsnamebuf))
+        return (-1);     /* readlink() is supposed to return -1 on error */
+
+    /* Now, convert the AOS/VS pathname to a Unix pathname.
+     * Note that sys_glink(), unlike readlink(), does add a null.
+     */
+    if (*cp_vs == '^')        /* AOS/VS for ../ */
+    {
+        strncpy(cp_ux, "../", 3);
+        cp_ux += 3;
+        cp_vs++;
+    }
+    else if (*cp_vs == '@')   /* AOS/VS for :PER:, kind of like /dev/ */
+    {
+        strncpy(cp_ux, "/PER/", 5);
+        cp_ux += 5;
+        cp_vs++;
+    }
+    else if (*cp_vs == '=')   /* AOS/VS for ./ */
+    {
+        strncpy(cp_ux, "./", 2);
+        cp_ux += 2;
+        cp_vs++;
+    }
+    while (*cp_vs != '\0'  &&  cp_ux - buf < nbytes)
+    {
+        if (*cp_vs == ':')
+        {
+            *cp_ux++ = '/';
+        }
+        else
+        {
+            *cp_ux++ = (char) toupper(*cp_vs);
+        }
+        cp_vs++;
+    }
+
+    return (cp_ux - buf);   /* # characters in Unix path (no trailing null) */
+
+} /* end zvs_readlink() */
diff --git a/aosvs/make.cli b/aosvs/make.cli
new file mode 100644 (file)
index 0000000..304e799
--- /dev/null
@@ -0,0 +1,5 @@
+push
+prompt pop
+sea :c_4.10 :c_4.10:lang_rt [!sea]
+cc%0/%/link/NOUNX AOS_VS/DEFINE NODIR/DEFINE <ZIP CRC32 CRCTAB CRYPT DEFLATE FILEIO GLOBALS MKTIME TREES TTYIO UTIL ZIPFILE ZIPUP AOSVS>.C
+pop
diff --git a/api.c b/api.c
new file mode 100644 (file)
index 0000000..fc35b60
--- /dev/null
+++ b/api.c
@@ -0,0 +1,494 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+  api.c
+
+  This module supplies a Zip dll engine for use directly from C/C++
+  programs.
+
+  The entry points are:
+
+    ZpVer *ZpVersion(void);
+    int EXPENTRY ZpInit(LPZIPUSERFUNCTIONS lpZipUserFunc);
+    BOOL EXPENTRY ZpSetOptions(LPZPOPT Opts);
+    ZPOPT EXPENTRY ZpGetOptions(void);
+    int EXPENTRY ZpArchive(ZCL C);
+
+  This module is currently only used by the Windows dll, and is not used at
+  all by any of the other platforms, although it should be easy enough to
+  implement this on most platforms.
+
+  ---------------------------------------------------------------------------*/
+#define __API_C
+
+#ifdef WINDLL
+#  include <windows.h>
+#  include "windll/windll.h"
+#endif
+
+#ifdef OS2
+#  define  INCL_DOSMEMMGR
+#  include <os2.h>
+#endif
+
+#ifdef __BORLANDC__
+#include <dir.h>
+#endif
+#include <direct.h>
+#include <ctype.h>
+#include "api.h"                /* this includes zip.h */
+#include "crypt.h"
+#include "revision.h"
+#ifdef USE_ZLIB
+#  include "zlib.h"
+#endif
+
+
+DLLPRNT *lpZipPrint;
+DLLPASSWORD *lpZipPassword;
+extern DLLCOMMENT *lpComment;
+ZIPUSERFUNCTIONS ZipUserFunctions, far * lpZipUserFunctions;
+
+int ZipRet;
+
+/* ------------------------------------------------- */
+/* Visual Basic converts strings from VB native Unicode to
+   byte strings when passing to dlls.  It seems that any
+   strings pointed to in structures are converted and the
+   conversion passed to the dll, but when the dll call
+   returns the converted strings are garbage collected
+   unless the debugger prevents it.  This leaves the
+   pointers going to memory that may have been reused
+   by the time the following dll call is made.  This
+   affects the strings in the Options stucture.
+
+   The following kluge stores the strings locally in
+   the dll between calls.  A better fix is to redesign
+   the api interface so that strings in structures are
+   removed or are passed in the same call they are used.  EG
+
+/* oversized to be sure */
+#define MAX_ZIP_DATE_LEN 50
+#define MAX_ZIP_DIR_PATH_LEN 4098
+
+char szDate[MAX_ZIP_DATE_LEN + 1];
+char szRootDir[MAX_ZIP_DIR_PATH_LEN + 1];
+char szTempDir[MAX_ZIP_DIR_PATH_LEN + 1];   
+/* ------------------------------------------------- */
+
+/* Local forward declarations */
+extern int  zipmain OF((int, char **));
+int AllocMemory(int, char *, char *);
+
+ZPOPT Options;
+char **argVee;
+int argCee;
+
+/*---------------------------------------------------------------------------
+    Local functions
+  ---------------------------------------------------------------------------*/
+
+int AllocMemory(int i, char *cmd, char *str)
+{
+int j;
+if ((argVee[i] = (char *) malloc( sizeof(char) * strlen(cmd)+1 )) == NULL)
+   {
+   for (j = 0; j < i; j++)
+       {
+       free (argVee[j]);
+       argVee[j] = NULL;
+       }
+   free(argVee);
+   fprintf(stdout, "Unable to allocate memory in zip library at %s\n", str);
+   return ZE_MEM;
+   }
+strcpy( argVee[i], cmd );
+return ZE_OK;
+}
+
+/*---------------------------------------------------------------------------
+    Documented API entry points
+  ---------------------------------------------------------------------------*/
+
+int EXPENTRY ZpInit(LPZIPUSERFUNCTIONS lpZipUserFunc)
+{
+ZipUserFunctions = *lpZipUserFunc;
+lpZipUserFunctions = &ZipUserFunctions;
+
+if (!lpZipUserFunctions->print ||
+    !lpZipUserFunctions->comment)
+    return FALSE;
+
+return TRUE;
+}
+
+BOOL EXPENTRY ZpSetOptions(LPZPOPT Opts)
+{
+/* copy the structure including pointers to strings */
+Options = *Opts;
+
+/* fix for calling dll from VB - 2002-11-25 */
+/* make copies of strings in structure if not NULL passed for empty string */
+if (Options.Date) {
+  szDate[0] = '\0';
+  strncat(szDate, Options.Date, MAX_ZIP_DATE_LEN);
+  Options.Date = szDate;
+}
+if (Options.szRootDir) {
+  szRootDir[0] = '\0';
+  strncat(szRootDir, Options.szRootDir, MAX_ZIP_DIR_PATH_LEN);
+  Options.szRootDir = szRootDir;
+}
+if (Options.szTempDir) {
+  szTempDir[0] = '\0';
+  strncat(szTempDir, Options.szTempDir, MAX_ZIP_DIR_PATH_LEN);
+  Options.szTempDir = szTempDir;
+}
+
+return TRUE;
+}
+
+ZPOPT EXPENTRY ZpGetOptions(void)
+{
+#if CRYPT
+Options.fEncryption = TRUE;
+#else
+Options.fEncryption = FALSE;
+#endif
+return Options;
+}
+
+int EXPENTRY ZpArchive(ZCL C)
+/* Add, update, freshen, or delete zip entries in a zip file.  See the
+   command help in help() zip.c */
+{
+int i, k, j, m;
+char szOrigDir[PATH_MAX];
+
+argCee = 0;
+/* malloc additional 26 to allow for additional command line arguments */
+if ((argVee = (char **)malloc((C.argc+26)*sizeof(char *))) == NULL)
+   {
+   fprintf(stdout, "Unable to allocate memory in zip dll\n");
+   return ZE_MEM;
+   }
+if ((argVee[argCee] = (char *) malloc( sizeof(char) * strlen("wiz.exe")+1 )) == NULL)
+   {
+   free(argVee);
+   fprintf(stdout, "Unable to allocate memory in zip dll\n");
+   return ZE_MEM;
+   }
+strcpy( argVee[argCee], "wiz.exe" );
+argCee++;
+
+/* Set compression level efficacy -0...-9 */
+if (AllocMemory(argCee, "-0", "Compression") != ZE_OK)
+   return ZE_MEM;
+argVee[argCee][1] = Options.fLevel;
+argCee++;
+
+if (Options.fOffsets)    /* Update offsets for SFX prefix */
+   {
+   if (AllocMemory(argCee, "-A", "Offsets") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if (Options.fDeleteEntries)    /* Delete files from zip file -d */
+   {
+   if (AllocMemory(argCee, "-d", "Delete") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if (Options.fNoDirEntries) /* Do not add directory entries -D */
+   {
+   if (AllocMemory(argCee, "-D", "No Dir Entries") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if (Options.fFreshen) /* Freshen zip file--overwrite only -f */
+   {
+   if (AllocMemory(argCee, "-f", "Freshen") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if (Options.fRepair)  /* Fix archive -F or -FF */
+   {
+   if (Options.fRepair == 1)
+      {
+      if (AllocMemory(argCee, "-F", "Repair") != ZE_OK)
+         return ZE_MEM;
+      }
+   else
+      {
+      if (AllocMemory(argCee, "-FF", "Repair") != ZE_OK)
+         return ZE_MEM;
+      }
+   argCee++;
+   }
+if (Options.fGrow) /* Allow appending to a zip file -g */
+   {
+   if (AllocMemory(argCee, "-g", "Appending") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if (Options.fJunkDir) /* Junk directory names -j */
+   {
+   if (AllocMemory(argCee, "-j", "Junk Dir Names") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if (Options.fEncrypt) /* encrypt -e */
+   {
+   if (AllocMemory(argCee, "-e", "Encrypt") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if (Options.fJunkSFX) /* Junk sfx prefix */
+   {
+   if (AllocMemory(argCee, "-J", "Junk SFX") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+
+if (Options.fForce) /* Make entries using DOS names (k for Katz) -k */
+   {
+   if (AllocMemory(argCee, "-k", "Force DOS") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+
+if (Options.fLF_CRLF) /* Translate LF_CRLF -l */
+   {
+   if (AllocMemory(argCee, "-l", "LF-CRLF") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if (Options.fCRLF_LF) /* Translate CR/LF to LF -ll */
+   {
+   if (AllocMemory(argCee, "-ll", "CRLF-LF") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if (Options.fMove) /* Delete files added to or updated in zip file -m */
+   {
+   if (AllocMemory(argCee, "-m", "Move") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+
+if (Options.fLatestTime) /* Set zip file time to time of latest file in it -o */
+   {
+   if (AllocMemory(argCee, "-o", "Time") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+
+if (Options.fComment) /* Add archive comment "-z" */
+   {
+   if (AllocMemory(argCee, "-z", "Comment") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+
+if (Options.fQuiet) /* quiet operation -q */
+   {
+   if (AllocMemory(argCee, "-q", "Quiet") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if (Options.fSystem)  /* include system and hidden files -S */
+   {
+   if (AllocMemory(argCee, "-S", "System") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if (Options.fExcludeDate)    /* Exclude files newer than specified date -tt */
+   {
+   if ((Options.Date != NULL) && (Options.Date[0] != '\0'))
+      {
+      if (AllocMemory(argCee, "-tt", "Date") != ZE_OK)
+         return ZE_MEM;
+      argCee++;
+      if (AllocMemory(argCee, Options.Date, "Date") != ZE_OK)
+         return ZE_MEM;
+      argCee++;
+      }
+   }
+
+if (Options.fIncludeDate)    /* include files newer than specified date -t */
+   {
+   if ((Options.Date != NULL) && (Options.Date[0] != '\0'))
+      {
+      if (AllocMemory(argCee, "-t", "Date") != ZE_OK)
+         return ZE_MEM;
+      argCee++;
+      if (AllocMemory(argCee, Options.Date, "Date") != ZE_OK)
+         return ZE_MEM;
+      argCee++;
+      }
+   }
+
+if (Options.fUpdate) /* Update zip file--overwrite only if newer -u */
+   {
+   if (AllocMemory(argCee, "-u", "Update") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if (Options.fVerbose)  /* Mention oddities in zip file structure -v */
+   {
+   if (AllocMemory(argCee, "-v", "Verbose") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if (Options.fVolume)  /* Include volume label -$ */
+   {
+   if (AllocMemory(argCee, "-$", "Volume") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+#ifdef NTSD_EAS /* was WIN32 1/22/2005 EG */
+if (Options.fPrivilege)  /* Use privileges -! */
+   {
+   if (AllocMemory(argCee, "-!", "Privileges") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+#endif
+if (Options.fExtra)  /* Exclude extra attributes -X */
+   {
+   if (AllocMemory(argCee, "-X", "Extra") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if ((Options.szTempDir != NULL) && (Options.szTempDir[0] != '\0')
+     && Options.fTemp) /* Use temporary directory -b */
+   {
+   if (AllocMemory(argCee, "-b", "Temp dir switch command") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   if (AllocMemory(argCee, Options.szTempDir, "Temporary directory") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+/* -r and -R moved down here to avoid VB problem 1/31/2005 EG */
+if (Options.fRecurse == 1) /* recurse into subdirectories -r */
+   {
+   if (AllocMemory(argCee, "-r", "Recurse -r") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+else if (Options.fRecurse == 2) /* recurse into subdirectories -R */
+   {
+   if (AllocMemory(argCee, "-R", "Recurse -R") != ZE_OK)
+      return ZE_MEM;
+   argCee++;
+   }
+if (AllocMemory(argCee, C.lpszZipFN, "Zip file name") != ZE_OK)
+   return ZE_MEM;
+argCee++;
+
+getcwd(szOrigDir, PATH_MAX); /* Save current drive and directory */
+
+if ((Options.szRootDir != NULL) && (Options.szRootDir[0] != '\0'))
+   {
+   chdir(Options.szRootDir);
+#ifdef __BORLANDC__
+   setdisk(toupper(Options.szRootDir[0]) - 'A');
+#endif
+   lstrcat(Options.szRootDir, "\\"); /* append trailing \\ */
+   if (C.FNV != NULL)
+      {
+      for (k = 0; k < C.argc; k++)
+         {
+         if (AllocMemory(argCee, C.FNV[k], "Making argv") != ZE_OK)
+            return ZE_MEM;
+         if ((strncmp(Options.szRootDir, C.FNV[k], lstrlen(Options.szRootDir))) == 0)
+            {
+            m = 0;
+            for (j = lstrlen(Options.szRootDir); j < lstrlen(C.FNV[k]); j++)
+               argVee[argCee][m++] = C.FNV[k][j];
+            argVee[argCee][m] = '\0';
+            }
+         argCee++;
+         }
+      }
+   }
+else
+   if (C.FNV != NULL)
+      for (k = 0; k < C.argc; k++)
+         {
+         if (AllocMemory(argCee, C.FNV[k], "Making argv") != ZE_OK)
+            return ZE_MEM;
+         argCee++;
+         }
+
+argVee[argCee] = NULL;
+
+ZipRet = zipmain(argCee, argVee);
+
+chdir(szOrigDir);
+#ifdef __BORLANDC__
+setdisk(toupper(szOrigDir[0]) - 'A');
+#endif
+
+/* Free the arguments in the array */
+for (i = 0; i < argCee; i++)
+   {
+      free (argVee[i]);
+      argVee[i] = NULL;
+   }
+/* Then free the array itself */
+free(argVee);
+
+return ZipRet;
+}
+
+#if CRYPT
+int encr_passwd(int modeflag, char *pwbuf, int size, const char *zfn)
+{
+return (*lpZipUserFunctions->password)(pwbuf, size, ((modeflag == ZP_PW_VERIFY) ?
+                  "Verify password: " : "Enter password: "),
+                  (char *)zfn);
+}
+#endif /* CRYPT */
+
+void EXPENTRY ZpVersion(ZpVer far * p)   /* should be pointer to const struct */
+{
+    p->structlen = ZPVER_LEN;
+
+#ifdef BETA
+    p->flag = 1;
+#else
+    p->flag = 0;
+#endif
+    lstrcpy(p->betalevel, Z_BETALEVEL);
+    lstrcpy(p->date, REVDATE);
+
+#ifdef ZLIB_VERSION
+    lstrcpy(p->zlib_version, ZLIB_VERSION);
+    p->flag |= 2;
+#else
+    p->zlib_version[0] = '\0';
+#endif
+
+    p->zip.major = Z_MAJORVER;
+    p->zip.minor = Z_MINORVER;
+    p->zip.patchlevel = Z_PATCHLEVEL;
+
+
+    p->os2dll.major = D2_MAJORVER;
+    p->os2dll.minor = D2_MINORVER;
+    p->os2dll.patchlevel = D2_PATCHLEVEL;
+
+
+    p->windll.major = DW_MAJORVER;
+    p->windll.minor = DW_MINORVER;
+    p->windll.patchlevel = DW_PATCHLEVEL;
+}
diff --git a/api.h b/api.h
new file mode 100644 (file)
index 0000000..c2c0e8c
--- /dev/null
+++ b/api.h
@@ -0,0 +1,152 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* Only the Windows DLL is currently supported */
+#ifndef _ZIPAPI_H
+#define _ZIPAPI_H
+
+#include "zip.h"
+
+#ifdef WIN32
+#   ifndef PATH_MAX
+#      define PATH_MAX 260
+#   endif
+#else
+#   ifndef PATH_MAX
+#      define PATH_MAX 128
+#   endif
+#endif
+
+#if defined(WINDLL) || defined(API)
+#include <windows.h>
+/* Porting definations between Win 3.1x and Win32 */
+#ifdef WIN32
+#  define far
+#  define _far
+#  define __far
+#  define near
+#  define _near
+#  define __near
+#endif
+
+/*---------------------------------------------------------------------------
+    Prototypes for public Zip API (DLL) functions.
+  ---------------------------------------------------------------------------*/
+
+#define ZPVER_LEN    sizeof(ZpVer)
+/* These defines are set to zero for now, until OS/2 comes out
+   with a dll.
+ */
+#define D2_MAJORVER 0
+#define D2_MINORVER 0
+#define D2_PATCHLEVEL 0
+
+/* intended to be a private struct: */
+typedef struct _zip_ver {
+    uch major;              /* e.g., integer 5 */
+    uch minor;              /* e.g., 2 */
+    uch patchlevel;         /* e.g., 0 */
+    uch not_used;
+} _zip_version_type;
+
+typedef struct _ZpVer {
+    ulg structlen;          /* length of the struct being passed */
+    ulg flag;               /* bit 0: is_beta   bit 1: uses_zlib */
+    char betalevel[10];     /* e.g., "g BETA" or "" */
+    char date[20];          /* e.g., "4 Sep 95" (beta) or "4 September 1995" */
+    char zlib_version[10];  /* e.g., "0.95" or NULL */
+    _zip_version_type zip;
+    _zip_version_type os2dll;
+    _zip_version_type windll;
+} ZpVer;
+
+#  ifndef EXPENTRY
+#    define EXPENTRY WINAPI
+#  endif
+
+#ifndef DEFINED_ONCE
+#define DEFINED_ONCE
+typedef int (WINAPI DLLPRNT) (LPSTR, unsigned long);
+typedef int (WINAPI DLLPASSWORD) (LPSTR, int, LPCSTR, LPCSTR);
+typedef int (WINAPI DLLSERVICE) (LPCSTR, unsigned long);
+#endif
+typedef int (WINAPI DLLCOMMENT)(LPSTR);
+
+/* Structures */
+
+typedef struct {        /* zip options */
+LPSTR Date;             /* Date to include after */
+LPSTR szRootDir;        /* Directory to use as base for zipping */
+LPSTR szTempDir;        /* Temporary directory used during zipping */
+BOOL fTemp;             /* Use temporary directory '-b' during zipping */
+BOOL fSuffix;           /* include suffixes (not implemented) */
+BOOL fEncrypt;          /* encrypt files */
+BOOL fSystem;           /* include system and hidden files */
+BOOL fVolume;           /* Include volume label */
+BOOL fExtra;            /* Exclude extra attributes */
+BOOL fNoDirEntries;     /* Do not add directory entries */
+BOOL fExcludeDate;      /* Exclude files newer than specified date */
+BOOL fIncludeDate;      /* Include only files newer than specified date */
+BOOL fVerbose;          /* Mention oddities in zip file structure */
+BOOL fQuiet;            /* Quiet operation */
+BOOL fCRLF_LF;          /* Translate CR/LF to LF */
+BOOL fLF_CRLF;          /* Translate LF to CR/LF */
+BOOL fJunkDir;          /* Junk directory names */
+BOOL fGrow;             /* Allow appending to a zip file */
+BOOL fForce;            /* Make entries using DOS names (k for Katz) */
+BOOL fMove;             /* Delete files added or updated in zip file */
+BOOL fDeleteEntries;    /* Delete files from zip file */
+BOOL fUpdate;           /* Update zip file--overwrite only if newer */
+BOOL fFreshen;          /* Freshen zip file--overwrite only */
+BOOL fJunkSFX;          /* Junk SFX prefix */
+BOOL fLatestTime;       /* Set zip file time to time of latest file in it */
+BOOL fComment;          /* Put comment in zip file */
+BOOL fOffsets;          /* Update archive offsets for SFX files */
+BOOL fPrivilege;        /* Use privileges (WIN32 only) */
+BOOL fEncryption;       /* TRUE if encryption supported, else FALSE.
+                           this is a read only flag */
+int  fRecurse;          /* Recurse into subdirectories. 1 => -r, 2 => -R */
+int  fRepair;           /* Repair archive. 1 => -F, 2 => -FF */
+char fLevel;            /* Compression level (0 - 9) */
+} ZPOPT, _far *LPZPOPT;
+
+typedef struct {
+int  argc;              /* Count of files to zip */
+LPSTR lpszZipFN;        /* name of archive to create/update */
+char **FNV;             /* array of file names to zip up */
+} ZCL, _far *LPZCL;
+
+typedef struct {
+DLLPRNT *print;
+DLLCOMMENT *comment;
+DLLPASSWORD *password;
+DLLSERVICE *ServiceApplication;
+} ZIPUSERFUNCTIONS, far * LPZIPUSERFUNCTIONS;
+
+extern LPZIPUSERFUNCTIONS lpZipUserFunctions;
+
+void  EXPENTRY ZpVersion(ZpVer far *);
+int   EXPENTRY ZpInit(LPZIPUSERFUNCTIONS lpZipUserFunc);
+BOOL  EXPENTRY ZpSetOptions(LPZPOPT Opts);
+ZPOPT EXPENTRY ZpGetOptions(void);
+int   EXPENTRY ZpArchive(ZCL C);
+
+#if defined(ZIPLIB) || defined(COM_OBJECT)
+#   define ydays zp_ydays
+#endif
+
+
+
+/* Functions not yet supported */
+#if 0
+int      EXPENTRY ZpMain            (int argc, char **argv);
+int      EXPENTRY ZpAltMain         (int argc, char **argv, ZpInit *init);
+#endif
+#endif /* WINDLL? || API? */
+
+#endif /* _ZIPAPI_H */
diff --git a/atari/Makefile b/atari/Makefile
new file mode 100644 (file)
index 0000000..96b6ff5
--- /dev/null
@@ -0,0 +1,109 @@
+# Makefile for Zip, ZipNote, ZipCloak and ZipSplit
+
+MAKE = make
+SHELL = /bin/sh
+
+# (to use the Gnu compiler, change cc to gcc in CC and BIND)
+CC = cc
+BIND = $(CC)
+AS = $(CC) -c
+E =
+CPP = /lib/cpp
+
+# probably can change this to 'install' if you have it
+INSTALL = cp
+
+# target directories - where to install executables and man pages to
+BINDIR = /usr/local/bin
+manext=1
+MANDIR = /usr/local/man/man$(manext)
+
+# flags
+#   CFLAGS    flags for C compile
+#   LFLAGS1   flags after output file spec, before obj file list
+#   LFLAGS2   flags after obj file list (libraries, etc)
+CFLAGS = -O
+LFLAGS1 =
+LFLAGS2 = -s
+
+# object file lists
+OBJZ = zip.o zipfile.o zipup.o fileio.o util.o crc32.o crctab.o globals.o \
+       crypt.o ttyio.o atari.o
+
+OBJI = deflate.o trees.o
+OBJA =
+OBJU = zipfile_.o fileio_.o util_.o globals.o atari_.o
+OBJN = zipnote.o  $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt_.o ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h atari/osdep.h
+
+# suffix rules
+.SUFFIXES:
+.SUFFIXES: _.o .o .c .doc .1
+.c_.o:
+       rm -f $*_.c; ln $< $*_.c
+       $(CC) $(CFLAGS) -DUTIL -c $*_.c
+       rm -f $*_.c
+.c.o:
+       $(CC) $(CFLAGS) -c $<
+
+.1.doc:
+       nroff -man $< | col -b | uniq > $@
+
+# rules for zip, zipnote, zipcloak, zipsplit, and the Zip MANUAL.
+$(OBJZ): $(ZIP_H)
+$(OBJI): $(ZIP_H)
+$(OBJN): $(ZIP_H)
+$(OBJS): $(ZIP_H)
+$(OBJC): $(ZIP_H)
+zip.o zipup.o crypt.o ttyio.o zipcloak.o crypt_.o:  crypt.h
+zip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h
+zip.o crypt.o ttyio.o zipcloak.o crypt_.o: ttyio.h
+zipup.o: atari/zipup.h
+
+match.o: match.s
+       $(CPP) match.s > _match.s
+       $(AS) _match.s
+       mv _match.o match.o
+       rm -f _match.s
+
+ZIPS = zip$E zipnote$E zipsplit$E zipcloak$E
+
+zips: $(ZIPS)
+zipsman: $(ZIPS) $(ZIPMANUAL)
+
+zip$E: $(OBJZ) $(OBJI) $(OBJA)
+       $(BIND) -o zip$E $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)
+zipnote$E: $(OBJN)
+       $(BIND) -o zipnote$E $(LFLAGS1) $(OBJN) $(LFLAGS2)
+zipcloak$E: $(OBJC)
+       $(BIND) -o zipcloak$E $(LFLAGS1) $(OBJC) $(LFLAGS2)
+zipsplit$E: $(OBJS)
+       $(BIND) -o zipsplit$E $(LFLAGS1) $(OBJS) $(LFLAGS2)
+
+$(ZIPMANUAL): man/zip.1
+       nroff -man man/zip.1 | col -b | uniq > $(ZIPMANUAL)
+
+# install
+install:        $(ZIPS)
+       $(INSTALL) $(ZIPS) $(BINDIR)
+       $(INSTALL) man/zip.1 $(MANDIR)/zip.$(manext)
+
+uninstall:
+       -cd $(BINDIR); rm -f $(ZIPS)
+       -cd $(MANDIR); rm -f zip.$(manext)
+
+dist: $(ZIPMANUAL)
+       zip -u9T zip`sed -e '/VERSION/!d' -e 's/.*"\(.*\)".*/\1/' \
+                         -e s/[.]//g -e q revision.h` \
+         `awk '/^Makefile/,/vms_zip.rnh/ {print $$1}' < contents`
+
+# ATARI version (gcc 2.5.8 and Mintlibs PL46)
+atari:
+       $(MAKE) zips CFLAGS="-O -DATARI" OBJA=atari/atari.o CC=gcc E=.ttp
+
+# clean up after making stuff and installing it
+clean:
+       rm -f *.o $(ZIPS) flags
diff --git a/atari/README b/atari/README
new file mode 100644 (file)
index 0000000..cce4206
--- /dev/null
@@ -0,0 +1,5 @@
+From: harry@hal.westfalen.de (Harald Denker)
+
+The old zip ATARI port is based on TurboC which is no more
+supported (for more than 3 years). I used the GNU gcc 2.5.8 and
+MiNTlibs PL46.
diff --git a/atari/atari.c b/atari/atari.c
new file mode 100644 (file)
index 0000000..9bfb5d1
--- /dev/null
@@ -0,0 +1,682 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include "zip.h"
+
+#ifndef UTIL    /* the companion #endif is a bit of ways down ... */
+
+#include <time.h>
+#include <errno.h>
+#include <dirent.h>
+#include <mintbind.h>
+#include <osbind.h>
+#include <ostruct.h>
+
+
+#define PAD 0
+#define PATH_END '/'
+
+extern char *label;     /* defined in fileio.c */
+
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+
+local char *readd(d)
+DIR *d;                 /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+   no more entries or an error occurs. */
+{
+  struct dirent *e;
+
+  e = readdir(d);
+  return e == NULL ? (char *) NULL : e->d_name;
+}
+
+local char *getVolumeLabel(drive, vtime, vmode, utim)
+  int drive;  /* drive name: 'A' .. 'Z' or '\0' for current drive */
+  ulg *vtime; /* volume label creation time (DOS format) */
+  ulg *vmode; /* volume label file mode */
+  time_t utim;/* volume label creation time (UNIX format) */
+
+/* If a volume label exists for the given drive, return its name and
+   set its time and mode. The returned name must be static data. */
+{
+  static char vol[14];
+  _DTA *dtaptr;
+
+  if (drive) {
+    vol[0] = (char)drive;
+    strcpy(vol+1, ":/");
+  } else {
+    strcpy(vol, "/");
+  }
+  strcat(vol, "*.*");
+  if (Fsfirst(vol, FA_LABEL) == 0) {
+    dtaptr = Fgetdta();
+    strncpy(vol, dtaptr->dta_name, sizeof(vol)-1);
+    *vtime = ((ulg)dtaptr->dta_date << 16) |
+             ((ulg)dtaptr->dta_time & 0xffff);
+    *vmode = (ulg)dtaptr->dta_attribute;
+    return vol;
+  }
+  return NULL;
+}
+
+char GetFileMode(char *name)
+{
+   struct stat sb;
+
+   sb.st_attr = 0;
+   Fxattr(linkput ? 1 : 0, name, &sb);
+   if (errno == EINVAL) {
+      _DTA *dtaptr, *old;
+      old = Fgetdta();
+      Fsfirst(name, FA_RDONLY+FA_HIDDEN+FA_SYSTEM+FA_DIR);
+      dtaptr = Fgetdta();
+      sb.st_attr = dtaptr->dta_attribute;
+      Fsetdta(old);
+   }
+   return sb.st_attr & 0x3f;
+}
+
+
+int wild2(w)
+char *w;                /* path/pattern to match */
+/* If not in exclude mode, expand the pattern based on the contents of the
+   file system.  Return an error code in the ZE_ class. */
+{
+  DIR *d;               /* stream for reading directory */
+  char *e;              /* name found in directory */
+  int r;                /* temporary variable */
+  char *n;              /* constructed name from directory */
+  int f;                /* true if there was a match */
+  char *a;              /* alloc'ed space for name */
+  char *p;              /* path */
+  char *q;              /* name */
+  char v[5];            /* space for device current directory */
+
+  if (volume_label == 1) {
+    volume_label = 2;
+    label = getVolumeLabel(w[1] == ':' ? to_up(w[0]) : '\0',
+                           &label_time, &label_mode, &label_utim);
+    if (label != NULL) {
+       newname(label, 0, 0);
+    }
+    if (w[1] == ':' && w[2] == '\0') return ZE_OK;
+    /* "zip -$ foo a:" can be used to force drive name */
+  }
+
+  /* special handling of stdin request */
+  if (strcmp(w, "-") == 0)   /* if compressing stdin */
+    return newname(w, 0, 0);
+
+  /* Allocate and copy pattern */
+  if ((p = a = malloc(strlen(w) + 1)) == NULL)
+    return ZE_MEM;
+  strcpy(p, w);
+
+  /* Normalize path delimiter as '/'. */
+  for (q = p; *q; q++)                  /* use / consistently */
+    if (*q == '\\')
+      *q = '/';
+
+  /* Only name can have special matching characters */
+  if ((q = isshexp(p)) != NULL &&
+      (strrchr(q, '/') != NULL || strrchr(q, ':') != NULL))
+  {
+    free((zvoid *)a);
+    return ZE_PARMS;
+  }
+
+  /* Separate path and name into p and q */
+  if ((q = strrchr(p, '/')) != NULL && (q == p || q[-1] != ':'))
+  {
+    *q++ = '\0';                        /* path/name -> path, name */
+    if (*p == '\0')                     /* path is just / */
+      p = strcpy(v, "/.");
+  }
+  else if ((q = strrchr(p, ':')) != NULL)
+  {                                     /* has device and no or root path */
+    *q++ = '\0';
+    p = strcat(strcpy(v, p), ":");      /* copy device as path */
+    if (*q == '/')                      /* -> device:/., name */
+    {
+      strcat(p, "/");
+      q++;
+    }
+    strcat(p, ".");
+  }
+  else if (recurse && (strcmp(p, ".") == 0 ||  strcmp(p, "..") == 0))
+  {                                    /* current or parent directory */
+    /* I can't understand Mark's code so I am adding a hack here to get
+     * "zip -r foo ." to work. Allow the dubious "zip -r foo .." but
+     * reject "zip -rm foo ..".
+     */
+    if (dispose && strcmp(p, "..") == 0)
+       ziperr(ZE_PARMS, "cannot remove parent directory");
+    q = "*.*";
+  }
+  else                                  /* no path or device */
+  {
+    q = p;
+    p = strcpy(v, ".");
+  }
+  if (recurse && *q == '\0') {
+    q = "*.*";
+  }
+  /* Search that level for matching names */
+  if ((d = opendir(p)) == NULL)
+  {
+    free((zvoid *)a);
+    return ZE_MISS;
+  }
+  if ((r = strlen(p)) > 1 &&
+      (strcmp(p + r - 2, ":.") == 0 || strcmp(p + r - 2, "/.") == 0))
+    *(p + r - 1) = '\0';
+  f = 0;
+  while ((e = readd(d)) != NULL) {
+    if (strcmp(e, ".") && strcmp(e, "..") && MATCH(q, e, 0))
+    {
+      f = 1;
+      if (strcmp(p, ".") == 0) {                /* path is . */
+        r = procname(e, 0);                     /* name is name */
+        if (r) {
+           f = 0;
+           break;
+        }
+      } else
+      {
+        if ((n = malloc(strlen(p) + strlen(e) + 2)) == NULL)
+        {
+          free((zvoid *)a);
+          closedir(d);
+          return ZE_MEM;
+        }
+        n = strcpy(n, p);
+        if (n[r = strlen(n) - 1] != '/' && n[r] != ':')
+          strcat(n, "/");
+        r = procname(strcat(n, e), 0);          /* name is path/name */
+        free((zvoid *)n);
+        if (r) {
+          f = 0;
+          break;
+        }
+      }
+    }
+  }
+  closedir(d);
+
+  /* Done */
+  free((zvoid *)a);
+  return f ? ZE_OK : ZE_MISS;
+}
+
+
+#include <regexp.h>
+#include <osbind.h>
+
+void regerror( char ZCONST *msg ) {
+   perror( msg );
+}
+
+static int    ret;
+static regexp *regptr;
+static short  is_w, ind_w;
+static char   fullpath[FILENAME_MAX], file_arg[FILENAME_MAX];
+
+#define FTW_F   0
+#define FTW_D   1
+#define FTW_DNR 2
+#define FTW_NS  3
+
+static int ftwfunc( struct stat *stats, int ftw_status )
+{
+   char *path = &fullpath[0];
+
+   if (strncmp(path, "./", 2) == 0) path += 2;
+   switch (ftw_status) {
+   case FTW_NS:
+      zipwarn("can't stat file: ", path);
+      ret = ZE_MISS;
+      return 0;
+   case FTW_F:
+      if (!is_w || regexec(regptr, path, 1)) {
+#if 0
+         char fn[FILENAME_MAX];
+         int  k;
+         if (S_ISLNK(stats->st_mode) &&
+             (k = readlink(path, fn, FILENAME_MAX)) > 0) {
+            int l = strlen(path);
+            fn[k] = '\0';
+            strcat(strcat(path, " -> "), fn);
+            ret = newname(path, 0, 0); /* procname(path, 0); */
+            path[l] = '\0';
+         } else
+#endif
+            ret = newname(path, 0, 0); /* procname(path, 0); */
+      }
+      return 0;
+   case FTW_DNR:
+      zipwarn("can't open directory: ", path);
+      ret = ZE_MISS;
+      return 0;
+   case FTW_D:
+      if (strcmp(path, ".") == 0) return 0;
+      if (is_w && ind_w > 0 && strncmp(path, file_arg, ind_w) != 0)
+         return 4;
+   }
+   return 0;
+}
+
+static int myftw( int depth )
+{
+   register DIR   *dirp;
+   struct dirent  *entp;
+   struct stat    stats;
+   register char  *p,*q;
+   register long  i;
+
+   if (LSSTAT(fullpath, &stats) < 0)
+      return ftwfunc(&stats, FTW_NS);
+
+   if (!S_ISDIR(stats.st_mode))
+      return ftwfunc(&stats, FTW_F);
+
+   if ((dirp = opendir(fullpath)) == NULL)
+      return ftwfunc(&stats, FTW_DNR);
+
+   if (i = ftwfunc(&stats, FTW_D)) {
+      closedir(dirp);
+      return (i == 4 ? 0 : (int)i);
+   }
+   i = strlen(fullpath);
+   p = &fullpath[i];
+   *p++ = '/'; *p = '\0';
+   if (dirnames && i > 1) {
+      q = (strncmp(fullpath, "./", 2) == 0 ? &fullpath[2] : &fullpath[0]);
+      ret = newname(q, 1, 0);
+   }
+   i = 0;
+   while (depth > 0 && (entp = readdir(dirp)) != 0)
+      if (strcmp(entp->d_name,".") != 0 && strcmp(entp->d_name,"..") != 0) {
+         strcpy(p, entp->d_name);
+         if (i = myftw(depth-1))
+            depth = 0;       /* force User's finish */
+      }
+   closedir(dirp);
+   return (int)i;
+}
+
+int wild( char *p )
+{
+   char *d;
+
+   ret = ZE_OK;
+   if (p == NULL) p = "*";
+
+   if (strcmp(p, "-") == 0)     /* if compressing stdin */
+      ret = newname(p, 0, 0);
+
+   strcpy(fullpath, p);
+   /* now turning UNIX-Wildcards into basic regular expressions */
+   for (is_w = ind_w = 0, d = &file_arg[0]; *p; d++, p++)
+      switch (*p) {
+      case '*': *d++ = '.'; *d = *p; is_w = 1;  break;
+      case '?': *d = '.';            is_w = 1;  break;
+      case '[': *d = *p;
+                if (*(p+1) == '!') {
+                   *++d = '^'; p++;
+                }                    is_w = 1;  break;
+      case '.': *d++ = '\\'; *d = *p;           break;
+      default : *d = *p;
+                if (!is_w) ind_w++;
+      }
+   *++d = '\0';
+   if (is_w) {
+      strcat( file_arg, "$" );           /* to get things like *.[ch] work */
+      if ((regptr = regcomp( file_arg )) == NULL)
+         return ZE_MEM;
+      strcpy( fullpath, "." );
+      myftw( recurse ? 99 : 1 );
+      free(regptr);
+   } else if (recurse) {
+      myftw( 99 );
+   } else
+      myftw( 1 ); /* ret = procname( fullpath, 0 ); */
+   return ret;
+}
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  char *a;              /* path and name for recursion */
+  DIR *d;               /* directory stream from opendir() */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (LSSTAT(n, &s))
+  {
+    /* Not a file or directory--search for shell expression in zip file */
+    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+  for (p = n; *p; p++)          /* use / consistently */
+    if (*p == '\\')
+      *p = '/';
+  if (!S_ISDIR(s.st_mode))
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  } else {
+    /* Add trailing / to the directory name */
+    if ((p = malloc(strlen(n)+2)) == NULL)
+      return ZE_MEM;
+    if (strcmp(n, ".") == 0) {
+      *p = '\0';  /* avoid "./" prefix and do not create zip entry */
+    } else {
+      strcpy(p, n);
+      a = p + strlen(p);
+      if (a[-1] != '/')
+        strcpy(a, "/");
+      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+        free((zvoid *)p);
+        return m;
+      }
+    }
+    /* recurse into directory */
+    if (recurse && (d = opendir(n)) != NULL)
+    {
+      while ((e = readd(d)) != NULL) {
+        if (strcmp(e, ".") && strcmp(e, ".."))
+        {
+          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+          {
+            closedir(d);
+            free((zvoid *)p);
+            return ZE_MEM;
+          }
+          strcat(strcpy(a, p), e);
+          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
+          {
+            if (m == ZE_MISS)
+              zipwarn("name not matched: ", a);
+            else
+              ziperr(m, a);
+          }
+          free((zvoid *)a);
+        }
+      }
+      closedir(d);
+    }
+    free((zvoid *)p);
+  } /* (s.st_mode & S_IFDIR) == 0) */
+  return ZE_OK;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t, *p;          /* shortened name */
+  int dosflag;
+
+  dosflag = 0;
+
+  /* Find starting point in name before doing malloc */
+  t = *x && *(x + 1) == ':' ? x + 2 : x;
+  while (*t == '/' || *t == '\\')
+    t++;
+
+  /* Make changes, if any, to the copied name (leave original intact) */
+  for (n = t; *n; n++)
+    if (*n == '\\')
+      *n = '/';
+
+  if (!pathput)
+    t = last(t, PATH_END);
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL)
+    return NULL;
+  strcpy(n, t);
+#if 0
+  if (p = strstr(t, " -> "))       /* shorten "link -> data" to "link" */
+    *p = '\0';
+#endif
+  if (dosify)
+    msname(n);
+
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+  return n;
+}
+
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+
+  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+      return NULL;
+  strcpy(x, n);
+  return x;
+}
+
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+  struct utimbuf u;     /* argument for utime()  const ?? */
+
+  /* Convert DOS time to time_t format in u[0] and u[1] */
+  u.actime = u.modtime = dos2unixtime(d);
+
+  /* Set updated and accessed times of f */
+  utime(f, &u);
+}
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  char *name;
+  unsigned int len = strlen(f);
+
+  if (f == label) {
+    if (a != NULL)
+      *a = label_mode;
+    if (n != NULL)
+      *n = -2L; /* convention for a label name */
+    if (t != NULL)
+      t->atime = t->mtime = t->ctime = label_utim;
+    return label_time;
+  }
+
+  if ((name = malloc(len + 1)) == NULL) {
+    ZIPERR(ZE_MEM, "filetime");
+  }
+  strcpy(name, f);
+  if (name[len - 1] == '/')
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+
+  if (strcmp(f, "-") == 0) {
+    if (fstat(fileno(stdin), &s) != 0) {
+      free(name);
+      error("fstat(stdin)");
+    }
+  } else if (LSSTAT(name, &s) != 0) {
+             /* Accept about any file kind including directories
+              * (stored with trailing / with -r option)
+              */
+    free(name);
+    return 0;
+  }
+
+  if (a != NULL) {
+/*  *a = ((ulg)s.st_mode << 16) | (ulg)GetFileMode(name); */
+    *a = ((ulg)s.st_mode << 16) | (ulg)s.st_attr;
+  }
+  if (n != NULL)
+    *n = S_ISREG(s.st_mode) ? s.st_size : -1L;
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = s.st_ctime;
+  }
+
+  free(name);
+
+  return unix2dostime(&s.st_mtime);
+}
+
+int set_extra_field(z, z_utim)
+  struct zlist far *z;
+  iztimes *z_utim;
+  /* create extra field and change z->att if desired */
+{
+#ifdef USE_EF_UT_TIME
+#ifdef IZ_CHECK_TZ
+  if (!zp_tz_is_valid) return ZE_OK;    /* skip silently if no valid TZ info */
+#endif
+
+  if ((z->extra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(2))) == NULL)
+    return ZE_MEM;
+  if ((z->cextra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL)
+    return ZE_MEM;
+
+  z->extra[0]  = 'U';
+  z->extra[1]  = 'T';
+  z->extra[2]  = EB_UT_LEN(2);          /* length of data part of e.f. */
+  z->extra[3]  = 0;
+  z->extra[4]  = EB_UT_FL_MTIME | EB_UT_FL_ATIME;
+  z->extra[5]  = (char)(z_utim->mtime);
+  z->extra[6]  = (char)(z_utim->mtime >> 8);
+  z->extra[7]  = (char)(z_utim->mtime >> 16);
+  z->extra[8]  = (char)(z_utim->mtime >> 24);
+  z->extra[9]  = (char)(z_utim->atime);
+  z->extra[10] = (char)(z_utim->atime >> 8);
+  z->extra[11] = (char)(z_utim->atime >> 16);
+  z->extra[12] = (char)(z_utim->atime >> 24);
+
+  z->ext = (EB_HEADSIZE+EB_UX_LEN(2));
+
+  memcpy(z->cextra, z->extra, (EB_HEADSIZE+EB_UT_LEN(1)));
+  z->cextra[EB_LEN] = EB_UT_LEN(1);
+  z->cext = (EB_HEADSIZE+EB_UX_LEN(1));
+
+  return ZE_OK;
+#else /* !USE_EF_UT_TIME */
+  return (int)(z-z);
+#endif /* ?USE_EF_UT_TIME */
+}
+
+int deletedir(d)
+char *d;                /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+   Return the result of rmdir(), delete(), or system().
+   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).
+ */
+{
+    return rmdir(d);
+}
+
+#endif /* !UTIL */
+
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+void version_local()
+{
+    static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
+#ifdef __TURBOC__
+    char buf[40];
+#endif
+
+    printf(CompiledWith,
+
+#ifdef __GNUC__
+      "gcc ", __VERSION__,
+#else
+#  if 0
+      "cc ", (sprintf(buf, " version %d", _RELEASE), buf),
+#  else
+#  ifdef __TURBOC__
+      "Turbo C", (sprintf(buf, " (0x%04x = %d)", __TURBOC__, __TURBOC__), buf),
+#  else
+      "unknown compiler", "",
+#  endif
+#  endif
+#endif
+
+#ifdef __MINT__
+      "Atari TOS/MiNT",
+#else
+      "Atari TOS",
+#endif
+
+      " (Atari ST/TT/Falcon030)",
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+      );
+
+} /* end function version_local() */
diff --git a/atari/make_all.mup b/atari/make_all.mup
new file mode 100644 (file)
index 0000000..5f8c4dc
--- /dev/null
@@ -0,0 +1,7 @@
+rm -f *.o *.sym *.ttp
+make370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS="-O -DATARI" E=.ttp OBJA=atari.o zips
+#make370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS="-g -D__NO_INLINE__ -DATARI" E=.ttp OBJA=atari.o zip.ttp
+#make370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS="-g -D__NO_INLINE__ -DATARI" E=.sym OBJA=atari.o zip.sym LFLAGS2="-B/bin/sym-"
+#make370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS="-O -DATARI" E=.ttp OBJA=atari.o -n zips > make_all.mup
+#fixstk 32K pgp.ttp
+prgflags 017 007 *.ttp
diff --git a/atari/make_zip.mup b/atari/make_zip.mup
new file mode 100644 (file)
index 0000000..4ea4c31
--- /dev/null
@@ -0,0 +1,7 @@
+#rm -f *.o *.sym *.ttp
+#make370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS="-O -DATARI" E=.ttp OBJA=atari.o zips
+make370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS="-g -D__NO_INLINE__ -DATARI" E=.ttp OBJA=atari.o zip.ttp
+make370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS="-g -D__NO_INLINE__ -DATARI" E=.sym OBJA=atari.o zip.sym LFLAGS2="-B/bin/sym-"
+#make370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS="-O -DATARI" E=.ttp OBJA=atari.o -n zips > make_all.mup
+#fixstk 32K pgp.ttp
+prgflags 017 007 *.ttp
diff --git a/atari/osdep.h b/atari/osdep.h
new file mode 100644 (file)
index 0000000..46387b6
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#define FOPR "rb"
+#define FOPM "r+b"
+#define FOPW "wb"
+
+#define DIRENT
+#define NO_TERMIO
+#define USE_CASE_MAP
+#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \
+                     procname(n, 1))
+
+#include <sys/types.h>
+#include <sys/stat.h>
diff --git a/atari/zipup.h b/atari/zipup.h
new file mode 100644 (file)
index 0000000..1de3f61
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef O_RDONLY
+#  define O_RDONLY 0
+#endif
+#define fhow O_RDONLY
+#define fbad (-1)
+typedef int ftype;
+#define zopen(n,p) open(n,p)
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f) close(f)
+#define zerr(f) (k == (extent)(-1L))
+#define zstdin 0
diff --git a/atheos/Contents b/atheos/Contents
new file mode 100644 (file)
index 0000000..3ffaba6
--- /dev/null
@@ -0,0 +1,11 @@
+Contents of the "atheos" sub-directory for Zip 2.3 and later:
+
+  Contents      this file
+  README        Notes from the author of the AtheOS port
+  Makefile      makefile for building
+  atheos.c      AtheOS-specific routines (similar to the BeOS/UNIX ones)
+  osdep.h       AtheOS-specific includes and whatnot
+  zipup.h       Definitions for zip routines
+
+- Ruslan Nickolaev (nruslan@hotbox.ru)
+  Sep 06/2004
diff --git a/atheos/Makefile b/atheos/Makefile
new file mode 100644 (file)
index 0000000..265ff42
--- /dev/null
@@ -0,0 +1,144 @@
+######################################################################
+#
+# Makefile for Info-ZIP's zip, zipcloak, zipnote, and zipsplit on AtheOS
+#
+# Copyright (C) 1999-2005 Info-ZIP
+#                    Chris Herborth (chrish@pobox.com)
+#                    Ruslan Nickolaev (nruslan@hotbox.ru)
+#
+######################################################################
+# Things that don't change:
+
+# Punish people who don't have SMP hardware.
+MAKE  = make -j 4 -f atheos/Makefile
+SHELL = /bin/sh
+
+LN = ln -s
+RM = rm -f
+
+BIND = $(CC)
+AS   = as
+
+INSTALL = install
+
+# Target directories
+prefix = /usr
+BINDIR = $(prefix)/bin
+manext = 1
+MANDIR = $(prefix)/man/man$(manext)
+ZIPMANUAL = MANUAL
+
+VERSION = Version 2.31 of __DATE__
+
+######################################################################
+
+CC:=gcc
+CFLAGS:=-O3 -march=i586 -Wall -I. -DHAVE_DIRENT_H -DPASSWD_FROM_STDIN -DASMV -DASM_CRC
+LFLAGS1:=
+LFLAGS2:=
+TARGET=$(ZIPS)
+
+######################################################################
+# Helpful targets
+all:
+       $(MAKE) CC=$(CC) CFLAGS="$(CFLAGS)" \
+               LFLAGS1="$(LFLAGS1)" LFLAGS2="$(LFLAGS2)" \
+               $(TARGET)
+
+######################################################################
+# Object file lists and other build goodies
+
+# Object file lists
+OBJZ = zip.o zipfile.o zipup.o fileio.o util.o globals.o crypt.o ttyio.o \
+       atheos.o crctab.o
+OBJI = deflate.o trees.o
+OBJA = match.o crc_i386.o
+OBJU = zipfile_.o fileio_.o util_.o globals.o atheos_.o
+OBJN = zipnote.o  $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt_.o ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+# Headers
+ZIP_H = zip.h ziperr.h tailor.h atheos/osdep.h
+
+# What to build?
+ZIPS = zip zipnote zipsplit zipcloak
+
+# suffix rules
+.SUFFIXES:
+.SUFFIXES: _.o .o .c .doc .1
+.c_.o:
+       $(RM) $*_.c; $(LN) $< $*_.c
+       $(CC) -c $(CFLAGS) -DUTIL $*_.c
+       $(RM) $*_.c
+
+.c.o:
+       $(CC) -c $(CFLAGS) $<
+
+.1.doc:
+       groff -man -Tascii $< > $@
+
+# rules for zip, zipnote, zipcloak, zipsplit, and the Zip MANUAL.
+$(OBJZ): $(ZIP_H)
+$(OBJI): $(ZIP_H)
+$(OBJN): $(ZIP_H)
+$(OBJS): $(ZIP_H)
+$(OBJC): $(ZIP_H)
+zip.o zipup.o crypt.o ttyio.o zipcloak.o crypt_.o: crypt.h
+zip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h
+zip.o crypt.o ttyio.o zipcloak.o crypt_.o: ttyio.h
+zipup.o: atheos/zipup.h
+
+match.o: match.S
+       $(CC) -E match.S > matchs.s
+       $(AS) -o $@ matchs.s
+       $(RM) matchs.s
+
+crc_i386.o: crc_i386.S
+       $(CC) -E crc_i386.S > crc_i386s.s
+       $(AS) -o $@ crc_i386s.s
+       $(RM) crc_i386s.s
+
+atheos.o: atheos/atheos.c
+       $(CC) -c $(CFLAGS) atheos/atheos.c
+
+atheos_.o: atheos/atheos.c
+       $(RM) $*_.c; $(LN) atheos/atheos.c $*_.c
+       $(CC) -c $(CFLAGS) -DUTIL $*_.c
+       $(RM) $*_.c
+
+zips: $(ZIPS)
+zipsman: $(ZIPS) $(ZIPMANUAL)
+
+zip: $(OBJZ) $(OBJI) $(OBJA)
+       $(BIND) -o zip $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)
+zipnote: $(OBJN)
+       $(BIND) -o zipnote $(LFLAGS1) $(OBJN) $(LFLAGS2)
+zipcloak: $(OBJC)
+       $(BIND) -o zipcloak $(LFLAGS1) $(OBJC) $(LFLAGS2)
+zipsplit: $(OBJS)
+       $(BIND) -o zipsplit $(LFLAGS1) $(OBJS) $(LFLAGS2)
+
+$(ZIPMANUAL): man/zip.1
+       groff -man -Tascii man/zip.1 > $(ZIPMANUAL)
+
+# install
+install:        $(ZIPS)
+       $(INSTALL) -m755 $(ZIPS) $(BINDIR)
+       mkdir -p $(MANDIR)
+       $(INSTALL) -m644 man/zip.1 $(MANDIR)/zip.$(manext)
+
+uninstall:
+       -cd $(BINDIR); $(RM) $(ZIPS)
+       -cd $(MANDIR); $(RM) zip.$(manext)
+
+dist: $(ZIPMANUAL)
+       zip -u9T zip`sed -e '/VERSION/!d' -e 's/.*"\(.*\)".*/\1/' \
+                         -e s/[.]//g -e q revision.h` \
+         `awk '/^Makefile/,/vms_zip.rnh/ {print $$1}' < contents`
+
+# clean up after making stuff and installing it
+clean:
+       $(RM) *.o $(ZIPS) flags
+
+# end of Makefile
diff --git a/atheos/README b/atheos/README
new file mode 100644 (file)
index 0000000..e9731fe
--- /dev/null
@@ -0,0 +1,23 @@
+Info-ZIP's zip for AtheOS/Syllable
+
+FEATURES
+  stores AtheOS/Syllable file attributes, compressing them if possible
+
+TODO
+----
+There is only one thing to be fixed:
+  write_attr() should return count of bytes written. However that's a bug
+  related with AFS only.
+
+Please report any bugs to Info-ZIP at www.info-zip.org.
+If this bug related with AtheOS/Syllable only, you can mail me directly:
+ nruslan@hotbox.ru.
+
+Visit the Info-ZIP web site (http://www.info-zip.org) for all the
+latest zip and unzip information, FAQs, source code and ready-to-run
+executables.
+
+- Ruslan Nickolaev (nruslan@hotbox.ru)
+  Sep 06/2004
+
+(updated 12 November 2004)
diff --git a/atheos/atheos.c b/atheos/atheos.c
new file mode 100644 (file)
index 0000000..dac3ef8
--- /dev/null
@@ -0,0 +1,885 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2005-Feb-10 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, all these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+
+  This AtheOS - specific file is based on unix.c and beos.c;
+  changes by Ruslan Nickolaev (nruslan@hotbox.ru)
+*/
+
+#include "zip.h"
+
+#ifndef UTIL    /* the companion #endif is a bit of ways down ... */
+
+#include <time.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atheos/fs_attribs.h>
+
+
+#define PAD 0
+#define PATH_END '/'
+
+/* Library functions not in (most) header files */
+
+#ifdef _POSIX_VERSION
+#  include <utime.h>
+#else
+   int utime OF((char *, time_t *));
+#endif
+
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+/* Local functions */
+local char *readd OF((DIR *));
+local int get_attr_dir( const char *, char **, off_t * );
+local int add_UT_ef( struct zlist far * );
+local int add_Ux_ef( struct zlist far * );
+local int add_At_ef( struct zlist far * );
+
+local char *readd(d)
+DIR *d;                 /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+   no more entries or an error occurs. */
+{
+  struct dirent *e;
+
+  e = readdir(d);
+  return e == NULL ? (char *) NULL : e->d_name;
+}
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  char *a;              /* path and name for recursion */
+  DIR *d;               /* directory stream from opendir() */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (LSSTAT(n, &s))
+  {
+    /* Not a file or directory--search for shell expression in zip file */
+    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+  if ((s.st_mode & S_IFREG) == S_IFREG ||
+      (s.st_mode & S_IFLNK) == S_IFLNK)
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  }
+  else if ((s.st_mode & S_IFDIR) == S_IFDIR)
+  {
+    /* Add trailing / to the directory name */
+    if ((p = malloc(strlen(n)+2)) == NULL)
+      return ZE_MEM;
+    if (strcmp(n, ".") == 0) {
+      *p = '\0';  /* avoid "./" prefix and do not create zip entry */
+    } else {
+      strcpy(p, n);
+      a = p + strlen(p);
+      if (a[-1] != '/')
+        strcpy(a, "/");
+      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+        free((zvoid *)p);
+        return m;
+      }
+    }
+    /* recurse into directory */
+    if (recurse && (d = opendir(n)) != NULL)
+    {
+      while ((e = readd(d)) != NULL) {
+        if (strcmp(e, ".") && strcmp(e, ".."))
+        {
+          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+          {
+            closedir(d);
+            free((zvoid *)p);
+            return ZE_MEM;
+          }
+          strcat(strcpy(a, p), e);
+          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
+          {
+            if (m == ZE_MISS)
+              zipwarn("name not matched: ", a);
+            else
+              ziperr(m, a);
+          }
+          free((zvoid *)a);
+        }
+      }
+      closedir(d);
+    }
+    free((zvoid *)p);
+  } /* (s.st_mode & S_IFDIR) */
+  else
+    zipwarn("ignoring special file: ", n);
+  return ZE_OK;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t = NULL;       /* shortened name */
+  int dosflag;
+
+  dosflag = dosify;  /* default for non-DOS and non-OS/2 */
+
+  /* Find starting point in name before doing malloc */
+  /* Strip "//host/share/" part of a UNC name */
+  if (!strncmp(x,"//",2) && (x[2] != '\0' && x[2] != '/')) {
+    n = x + 2;
+    while (*n != '\0' && *n != '/')
+      n++;              /* strip host name */
+    if (*n != '\0') {
+      n++;
+      while (*n != '\0' && *n != '/')
+        n++;            /* strip `share' name */
+    }
+    if (*n != '\0')
+      t = n + 1;
+  } else
+      t = x;
+  while (*t == '/')
+    t++;                /* strip leading '/' chars to get a relative path */
+  while (*t == '.' && t[1] == '/')
+    t += 2;             /* strip redundant leading "./" sections */
+
+  /* Make changes, if any, to the copied name (leave original intact) */
+  if (!pathput)
+    t = last(t, PATH_END);
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL)
+    return NULL;
+  strcpy(n, t);
+
+  if (isdir == 42) return n;    /* avoid warning on unused variable */
+
+  if (dosify)
+    msname(n);
+
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+  return n;
+}
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+
+  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+    return NULL;
+  strcpy(x, n);
+  return x;
+}
+
+/*
+ * XXX use ztimbuf in both POSIX and non POSIX cases ?
+ */
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+#ifdef _POSIX_VERSION
+  struct utimbuf u;     /* argument for utime()  const ?? */
+#else
+  time_t u[2];          /* argument for utime() */
+#endif
+
+  /* Convert DOS time to time_t format in u */
+#ifdef _POSIX_VERSION
+  u.actime = u.modtime = dos2unixtime(d);
+  utime(f, &u);
+#else
+  u[0] = u[1] = dos2unixtime(d);
+  utime(f, u);
+#endif
+
+}
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  char *name;
+  int len = strlen(f);
+
+  if (f == label) {
+    if (a != NULL)
+      *a = label_mode;
+    if (n != NULL)
+      *n = -2L; /* convention for a label name */
+    if (t != NULL)
+      t->atime = t->mtime = t->ctime = label_utim;
+    return label_time;
+  }
+  if ((name = malloc(len + 1)) == NULL {
+    ZIPERR(ZE_MEM, "filetime");
+  }
+  strcpy(name, f);
+  if (name[len - 1] == '/')
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+  if (strcmp(f, "-") == 0) {
+    if (fstat(fileno(stdin), &s) != 0) {
+      free(name);
+      error("fstat(stdin)");
+    }
+  }
+  else if (LSSTAT(name, &s) != 0) {
+    /* Accept about any file kind including directories
+     * (stored with trailing / with -r option)
+     */
+    free(name);
+    return 0;
+  }
+  free(name);
+
+  if (a != NULL) {
+#ifndef OS390
+    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
+#else
+/*
+**  The following defines are copied from the unizip source and represent the
+**  legacy Unix mode flags.  These fixed bit masks are no longer required
+**  by XOPEN standards - the S_IS### macros being the new recommended method.
+**  The approach here of setting the legacy flags by testing the macros should
+**  work under any _XOPEN_SOURCE environment (and will just rebuild the same bit
+**  mask), but is required if the legacy bit flags differ from legacy Unix.
+*/
+#define UNX_IFDIR      0040000     /* Unix directory */
+#define UNX_IFREG      0100000     /* Unix regular file */
+#define UNX_IFSOCK     0140000     /* Unix socket (BSD, not SysV or Amiga) */
+#define UNX_IFLNK      0120000     /* Unix symbolic link (not SysV, Amiga) */
+#define UNX_IFBLK      0060000     /* Unix block special       (not Amiga) */
+#define UNX_IFCHR      0020000     /* Unix character special   (not Amiga) */
+#define UNX_IFIFO      0010000     /* Unix fifo    (BCC, not MSC or Amiga) */
+    {
+    mode_t legacy_modes;
+
+    /* Initialize with permission bits - which are not implementation optional */
+    legacy_modes = s.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX);
+    if (S_ISDIR(s.st_mode))
+      legacy_modes |= UNX_IFDIR;
+    if (S_ISREG(s.st_mode))
+      legacy_modes |= UNX_IFREG;
+    if (S_ISLNK(s.st_mode))
+      legacy_modes |= UNX_IFLNK;
+    if (S_ISBLK(s.st_mode))
+      legacy_modes |= UNX_IFBLK;
+    if (S_ISCHR(s.st_mode))
+      legacy_modes |= UNX_IFCHR;
+    if (S_ISFIFO(s.st_mode))
+      legacy_modes |= UNX_IFIFO;
+    if (S_ISSOCK(s.st_mode))
+      legacy_modes |= UNX_IFSOCK;
+    *a = ((ulg)legacy_modes << 16) | !(s.st_mode & S_IWRITE);
+    }
+#endif
+    if ((s.st_mode & S_IFMT) == S_IFDIR) {
+      *a |= MSDOS_DIR_ATTR;
+    }
+  }
+  if (n != NULL)
+    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = t->mtime;   /* best guess, (s.st_ctime: last status change!!) */
+  }
+  return unix2dostime(&s.st_mtime);
+}
+
+/* ----------------------------------------------------------------------
+
+Return a malloc()'d buffer containing all of the attributes and their names
+for the file specified in name.  You have to free() this yourself.  The length
+of the buffer is also returned.
+
+If get_attr_dir() fails, the buffer will be NULL, total_size will be 0,
+and an error will be returned:
+
+    EOK    - no errors occurred
+    EINVAL - attr_buff was pointing at a buffer
+    ENOMEM - insufficient memory for attribute buffer
+
+Other errors are possible (whatever is returned by the fs_attrib.h functions).
+
+PROBLEMS:
+
+- pointers are 32-bits; attributes are limited to ssize_t in size so it's
+  possible to overflow... in practice, this isn't too likely... your
+  machine will thrash like hell before that happens
+
+*/
+
+#define INITIAL_BUFF_SIZE 65536
+
+int get_attr_dir( const char *name, char **attr_buff, off_t *total_size )
+{
+    int               retval = EOK;
+    int               fd;
+    DIR              *fa_dir;
+    struct dirent    *fa_ent;
+    off_t             attrs_size = 0;
+    size_t           entname_size;
+    char             *ptr;
+    struct attr_info  fa_info;
+
+    *total_size = 0;
+
+    /* ----------------------------------------------------------------- */
+    /* Sanity-check.                                                     */
+    if( *attr_buff != NULL ) {
+        return EINVAL;
+    }
+
+    /* ----------------------------------------------------------------- */
+    /* Can we open the file/directory?                                   */
+    /*                                                                   */
+    /* linkput is a zip global; it's set to 1 if we're storing symbolic  */
+    /* links as symbolic links (instead of storing the thing the link    */
+    /* points to)... if we're storing the symbolic link as a link, we'll */
+    /* want the link's file attributes, otherwise we want the target's.  */
+
+    fd = open( name, linkput ? O_RDONLY | O_NOTRAVERSE : O_RDONLY );
+    if( fd < 0 ) {
+        return errno;
+    }
+
+    /* ----------------------------------------------------------------- */
+    /* Allocate an initial buffer; 64k should usually be enough.         */
+    *attr_buff = (char *)malloc( INITIAL_BUFF_SIZE );
+    ptr        = *attr_buff;
+    if( ptr == NULL ) {
+        close( fd );
+
+        return ENOMEM;
+    }
+
+    /* ----------------------------------------------------------------- */
+    /* Open the attributes directory for this file.                      */
+    fa_dir = open_attrdir( fd );
+    if( fa_dir == NULL ) {
+        close( fd );
+
+        free( ptr );
+        *attr_buff = NULL;
+
+        return retval;
+    }
+
+    /* ----------------------------------------------------------------- */
+    /* Read all the attributes; the buffer could grow > 64K if there are */
+    /* many and/or they are large.                                       */
+    while( ( fa_ent = read_attrdir( fa_dir ) ) != NULL ) {
+        retval = stat_attr( fd, fa_ent->d_name, &fa_info );
+        /* TODO: check retval != EOK */
+
+        entname_size = strlen( fa_ent->d_name ) + 1;
+        attrs_size += entname_size + sizeof( struct attr_info ) + fa_info.ai_size;
+
+        if( attrs_size > INITIAL_BUFF_SIZE ) {
+            unsigned long offset = ptr - *attr_buff;
+
+            *attr_buff = (char *)realloc( *attr_buff, attrs_size );
+            if( *attr_buff == NULL ) {
+                retval = close_attrdir( fa_dir );
+                /* TODO: check retval != EOK */
+                close( fd );
+                return ENOMEM;
+            }
+
+            ptr = *attr_buff + offset;
+        }
+
+        /* Now copy the data for this attribute into the buffer. */
+        strcpy( ptr, fa_ent->d_name );
+        ptr += entname_size;
+
+        memcpy( ptr, &fa_info, sizeof( struct attr_info ) );
+        ptr += sizeof( struct attr_info );
+
+        if( fa_info.ai_size > 0 ) {
+            ssize_t read_bytes = read_attr( fd, fa_ent->d_name, fa_info.ai_type, ptr, 0, fa_info.ai_size );
+            if( read_bytes != fa_info.ai_size ) {
+                /* print a warning about mismatched sizes */
+                char buff[80];
+                sprintf( buff, "read %d, expected %d", read_bytes, (ssize_t)fa_info.ai_size );
+                zipwarn( "attribute size mismatch: ", buff );
+            }
+
+            ptr += fa_info.ai_size;
+        }
+    }
+
+    /* ----------------------------------------------------------------- */
+    /* Close the attribute directory.                                    */
+    retval = close_attrdir( fa_dir );
+    /* TODO: check retval != EOK */
+
+    /* ----------------------------------------------------------------- */
+    /* If the buffer is too big, shrink it.                              */
+    if( attrs_size < INITIAL_BUFF_SIZE ) {
+        *attr_buff = (char *)realloc( *attr_buff, attrs_size );
+        if( *attr_buff == NULL ) {
+            close( fd );
+            return ENOMEM;
+        }
+    }
+
+    *total_size = attrs_size;
+
+    close( fd );
+
+    return EOK;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Add a 'UT' extra field to the zlist data pointed to by z.              */
+
+#define EB_L_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(2))
+#define EB_C_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(1))
+
+local int add_UT_ef( struct zlist far *z )
+{
+    char        *l_ef = NULL;
+    char        *c_ef = NULL;
+    struct stat  s;
+
+#ifdef IZ_CHECK_TZ
+    if (!zp_tz_is_valid)
+        return ZE_OK;           /* skip silently if no valid TZ info */
+#endif
+
+    /* We can't work if there's no entry to work on. */
+    if( z == NULL ) {
+        return ZE_LOGIC;
+    }
+
+    /* Check to make sure we've got enough room in the extra fields. */
+    if( z->ext + EB_L_UT_SIZE > USHRT_MAX ||
+        z->cext + EB_C_UT_SIZE > USHRT_MAX ) {
+        return ZE_MEM;
+    }
+
+    /* stat() the file (or the symlink) to get the data; if we can't get */
+    /* the data, there's no point in trying to fill out the fields.      */
+    if(LSSTAT( z->name, &s ) ) {
+        return ZE_OPEN;
+    }
+
+    /* Allocate memory for the local and central extra fields. */
+    if( z->extra && z->ext != 0 ) {
+        l_ef = (char *)realloc( z->extra, z->ext + EB_L_UT_SIZE );
+    } else {
+        l_ef = (char *)malloc( EB_L_UT_SIZE );
+        z->ext = 0;
+    }
+    if( l_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->extra = l_ef;
+    l_ef += z->ext;
+
+    if( z->cextra && z->cext != 0 ) {
+        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_UT_SIZE );
+    } else {
+        c_ef = (char *)malloc( EB_C_UT_SIZE );
+        z->cext = 0;
+    }
+    if( c_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->cextra = c_ef;
+    c_ef += z->cext;
+
+    /* Now add the local version of the field. */
+    *l_ef++ = 'U';
+    *l_ef++ = 'T';
+    *l_ef++ = (char)(EB_UT_LEN(2)); /* length of data in local EF */
+    *l_ef++ = (char)0;
+    *l_ef++ = (char)(EB_UT_FL_MTIME | EB_UT_FL_ATIME);
+    *l_ef++ = (char)(s.st_mtime);
+    *l_ef++ = (char)(s.st_mtime >> 8);
+    *l_ef++ = (char)(s.st_mtime >> 16);
+    *l_ef++ = (char)(s.st_mtime >> 24);
+    *l_ef++ = (char)(s.st_atime);
+    *l_ef++ = (char)(s.st_atime >> 8);
+    *l_ef++ = (char)(s.st_atime >> 16);
+    *l_ef++ = (char)(s.st_atime >> 24);
+
+    z->ext += EB_L_UT_SIZE;
+
+    /* Now add the central version. */
+    memcpy(c_ef, l_ef-EB_L_UT_SIZE, EB_C_UT_SIZE);
+    c_ef[EB_LEN] = (char)(EB_UT_LEN(1)); /* length of data in central EF */
+
+    z->cext += EB_C_UT_SIZE;
+
+    return ZE_OK;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Add a 'Ux' extra field to the zlist data pointed to by z.              */
+
+#define EB_L_UX2_SIZE   (EB_HEADSIZE + EB_UX2_MINLEN)
+#define EB_C_UX2_SIZE   (EB_HEADSIZE)
+
+local int add_Ux_ef( struct zlist far *z )
+{
+    char        *l_ef = NULL;
+    char        *c_ef = NULL;
+    struct stat  s;
+
+    /* Check to make sure we've got enough room in the extra fields. */
+    if( z->ext + EB_L_UX2_SIZE > USHRT_MAX ||
+        z->cext + EB_C_UX2_SIZE > USHRT_MAX ) {
+        return ZE_MEM;
+    }
+
+    /* stat() the file (or the symlink) to get the data; if we can't get */
+    /* the data, there's no point in trying to fill out the fields.      */
+    if(LSSTAT( z->name, &s ) ) {
+        return ZE_OPEN;
+    }
+
+    /* Allocate memory for the local and central extra fields. */
+    if( z->extra && z->ext != 0 ) {
+        l_ef = (char *)realloc( z->extra, z->ext + EB_L_UX2_SIZE );
+    } else {
+        l_ef = (char *)malloc( EB_L_UX2_SIZE );
+        z->ext = 0;
+    }
+    if( l_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->extra = l_ef;
+    l_ef += z->ext;
+
+    if( z->cextra && z->cext != 0 ) {
+        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_UX2_SIZE );
+    } else {
+        c_ef = (char *)malloc( EB_C_UX2_SIZE );
+        z->cext = 0;
+    }
+    if( c_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->cextra = c_ef;
+    c_ef += z->cext;
+
+    /* Now add the local version of the field. */
+    *l_ef++ = 'U';
+    *l_ef++ = 'x';
+    *l_ef++ = (char)(EB_UX2_MINLEN);
+    *l_ef++ = (char)(EB_UX2_MINLEN >> 8);
+    *l_ef++ = (char)(s.st_uid);
+    *l_ef++ = (char)(s.st_uid >> 8);
+    *l_ef++ = (char)(s.st_gid);
+    *l_ef++ = (char)(s.st_gid >> 8);
+
+    z->ext += EB_L_UX2_SIZE;
+
+    /* Now add the central version of the field. */
+    *c_ef++ = 'U';
+    *c_ef++ = 'x';
+    *c_ef++ = 0;
+    *c_ef++ = 0;
+
+    z->cext += EB_C_UX2_SIZE;
+
+    return ZE_OK;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Add a 'At' extra field to the zlist data pointed to by z.              */
+
+#define EB_L_AT_SIZE    (EB_HEADSIZE + EB_L_AT_LEN) /* + attr size */
+#define EB_C_AT_SIZE    (EB_HEADSIZE + EB_C_AT_LEN)
+
+#define MEMCOMPRESS_HEADER      6   /* ush compression type, ulg CRC */
+#define DEFLAT_WORSTCASE_ADD    5   /* byte blocktype, 2 * ush blocklength */
+#define MEMCOMPRESS_OVERHEAD    (MEMCOMPRESS_HEADER + DEFLAT_WORSTCASE_ADD)
+
+local int add_At_ef( struct zlist far *z )
+{
+    char *l_ef       = NULL;
+    char *c_ef       = NULL;
+    char *attrbuff   = NULL;
+    off_t attrsize   = 0;
+    char *compbuff   = NULL;
+    ush   compsize   = 0;
+    uch   flags      = 0;
+
+    /* Check to make sure we've got enough room in the extra fields. */
+    if( z->ext + EB_L_AT_SIZE > USHRT_MAX ||
+        z->cext + EB_C_AT_SIZE > USHRT_MAX ) {
+        return ZE_MEM;
+    }
+
+    /* Attempt to load up a buffer full of the file's attributes. */
+    {
+        if (get_attr_dir( z->name, &attrbuff, &attrsize) != EOK ) {
+            return ZE_OPEN;
+        }
+        if (attrsize == 0) {
+            return ZE_OK;
+        }
+        if (attrbuff == NULL) {
+            return ZE_LOGIC;
+        }
+
+        /* Check for way too much data. */
+        if (attrsize > (off_t)ULONG_MAX) {
+            zipwarn( "uncompressed attributes truncated", "" );
+            attrsize = (off_t)(ULONG_MAX - MEMCOMPRESS_OVERHEAD);
+        }
+    }
+
+    if (verbose) {
+        printf( "\t[in=%lu]", (unsigned long)attrsize );
+    }
+
+    /* Try compressing the data */
+    compbuff = (char *)malloc( (size_t)attrsize + MEMCOMPRESS_OVERHEAD );
+    if( compbuff == NULL ) {
+        return ZE_MEM;
+    }
+    compsize = memcompress( compbuff,
+                            (size_t)attrsize + MEMCOMPRESS_OVERHEAD,
+                            attrbuff,
+                            (size_t)attrsize );
+    if (verbose) {
+        printf( " [out=%u]", compsize );
+    }
+
+    /* Attempt to optimise very small attributes. */
+    if (compsize > attrsize) {
+        free( compbuff );
+        compsize = (ush)attrsize;
+        compbuff = attrbuff;
+
+        flags = EB_AT_FL_NATURAL;
+    }
+
+    /* Check to see if we really have enough room in the EF for the data. */
+    if( ( z->ext + compsize + EB_L_AT_LEN ) > USHRT_MAX ) {
+        compsize = USHRT_MAX - EB_L_AT_LEN - z->ext;
+    }
+
+    /* Allocate memory for the local and central extra fields. */
+    if( z->extra && z->ext != 0 ) {
+        l_ef = (char *)realloc( z->extra, z->ext + EB_L_AT_SIZE + compsize );
+    } else {
+        l_ef = (char *)malloc( EB_L_AT_SIZE + compsize );
+        z->ext = 0;
+    }
+    if( l_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->extra = l_ef;
+    l_ef += z->ext;
+
+    if( z->cextra && z->cext != 0 ) {
+        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_AT_SIZE );
+    } else {
+        c_ef = (char *)malloc( EB_C_AT_SIZE );
+        z->cext = 0;
+    }
+    if( c_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->cextra = c_ef;
+    c_ef += z->cext;
+
+    /* Now add the local version of the field. */
+    *l_ef++ = 'A';
+    *l_ef++ = 't';
+    *l_ef++ = (char)(compsize + EB_L_AT_LEN);
+    *l_ef++ = (char)((compsize + EB_L_AT_LEN) >> 8);
+    *l_ef++ = (char)((unsigned long)attrsize);
+    *l_ef++ = (char)((unsigned long)attrsize >> 8);
+    *l_ef++ = (char)((unsigned long)attrsize >> 16);
+    *l_ef++ = (char)((unsigned long)attrsize >> 24);
+    *l_ef++ = flags;
+    memcpy( l_ef, compbuff, (size_t)compsize );
+
+    z->ext += EB_L_AT_SIZE + compsize;
+
+    /* And the central version. */
+    *c_ef++ = 'A';
+    *c_ef++ = 't';
+    *c_ef++ = (char)(EB_C_AT_LEN);
+    *c_ef++ = (char)(EB_C_AT_LEN >> 8);
+    *c_ef++ = (char)compsize;
+    *c_ef++ = (char)(compsize >> 8);
+    *c_ef++ = (char)(compsize >> 16);
+    *c_ef++ = (char)(compsize >> 24);
+    *c_ef++ = flags;
+
+    z->cext += EB_C_AT_SIZE;
+
+    return ZE_OK;
+}
+
+/* Extra field info:
+   - 'UT' - UNIX time extra field
+   - 'Ux' - UNIX uid/gid extra field
+   - 'At' - AtheOS file attributes extra field
+
+   This is done the same way ../unix/unix.c stores the 'UT'/'Ux' fields
+   (full data in local header, only modification time in central header),
+   with the 'At' field added to the end and the size of the 'At' field
+   in the central header.
+
+   See the end of atheos/osdep.h for a simple explanation of the 'At' EF
+   layout.
+ */
+int set_extra_field(z, z_utim)
+  struct zlist far *z;
+  iztimes *z_utim;
+  /* store full data in local header but just modification time stamp info
+     in central header */
+{
+    int retval;
+
+    /* Check to make sure z is valid. */
+    if( z == NULL ) {
+        return ZE_LOGIC;
+    }
+
+    retval = add_UT_ef(z);
+    if( retval != ZE_OK ) {
+        return retval;
+    }
+
+    retval = add_Ux_ef(z);
+    if( retval != ZE_OK ) {
+        return retval;
+    }
+
+    return add_At_ef(z); /* last function; we can use return value directly */
+}
+
+/* ---------------------------------------------------------------------- */
+/* Set a file's MIME type.                                                */
+void setfiletype(const char *file, const char *type)
+{
+    int fd;
+    off_t nLen;
+    ssize_t nError;
+
+    fd = open( file, O_RDWR );
+
+    if (fd < 0) {
+        zipwarn( "can't open zipfile to write file type", "" );
+    }
+
+    else
+    {
+        nLen = strlen( type );
+        /* FIXME: write_attr() should return count of bytes written */
+        nError = write_attr( fd, "os::MimeType", O_TRUNC, ATTR_TYPE_STRING, type, 0, nLen );
+        if (nError < 0) {
+            zipwarn( "couldn't write complete file type", "" );
+        }
+        close( fd );
+    }
+}
+
+#endif /* !UTIL */
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+void version_local()
+{
+    static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
+
+    printf(CompiledWith,
+
+#ifdef __GNUC__
+      "gcc ", __VERSION__,
+#else
+      "(unknown compiler)", "",
+#endif
+
+      "Syllable",
+
+#if defined(i486) || defined(__i486) || defined(__i486__) || defined(i386) || defined(__i386) || defined(__i386__)
+      " (x86)",
+#else
+      " (unknown platform)",
+#endif
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+    );
+
+} /* end function version_local() */
diff --git a/atheos/osdep.h b/atheos/osdep.h
new file mode 100644 (file)
index 0000000..69fd5b2
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2005-Feb-10 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, all these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+
+#ifndef _OSDEP_H_
+#define _OSDEP_H_
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/unistd.h>
+
+#define USE_EF_UT_TIME          /* Enable use of "UT" extra field time info */
+
+#define EB_L_AT_LEN 5           /* min size is an unsigned long and flag */
+#define EB_C_AT_LEN 5           /* Length of data in local EF and flag.  */
+
+#define EB_AT_FL_NATURAL    0x01    /* data is 'natural' (not compressed) */
+#define EB_AT_FL_BADBITS    0xfe    /* bits currently undefined           */
+
+#ifndef ZP_NEED_MEMCOMPR
+#  define ZP_NEED_MEMCOMPR
+#endif
+
+#define deletedir(d) rmdir(d);
+
+/* Set a file's MIME type. */
+void setfiletype( const char *file, const char *type );
+
+/*
+'At' extra-field layout:
+
+'At'      - signature
+ef_size   - size of data in this EF (little-endian unsigned short)
+full_size - uncompressed data size (little-endian unsigned long)
+flag      - flags (byte)
+            flags & EB_AT_FL_NATURAL    = the data is not compressed
+            flags & EB_AT_FL_BADBITS    = the data is corrupted or we
+                                          can't handle it properly
+data      - compressed or uncompressed file attribute data
+
+If flag & EB_AT_FL_NATURAL, the data is not compressed; this optimisation is
+necessary to prevent wasted space for files with small attributes. In this
+case, there should be ( ef_size - EB_L_AT_LEN ) bytes of data, and full_size
+should equal ( ef_size - EB_L_AT_LEN ).
+
+If the data is compressed, there will be ( ef_size - EB_L_AT_LEN ) bytes of
+compressed data, and full_size bytes of uncompressed data.
+
+If a file has absolutely no attributes, there will not be a 'At' extra field.
+
+The uncompressed data is arranged like this:
+
+attr_name\0 - C string
+struct attr_info (little-endian)
+attr_data (length in attr_info.ai_size)
+*/
+
+#endif
diff --git a/atheos/zipup.h b/atheos/zipup.h
new file mode 100644 (file)
index 0000000..6cbc806
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2005-Feb-10 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, all these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#ifndef _ZIPUP_H_
+#define _ZIPUP_H_
+
+#ifndef O_RDONLY
+#  include <sys/fcntl.h>
+#endif
+#define fhow O_RDONLY
+#define fbad (-1)
+typedef int ftype;
+#define zopen(n,p) open(n,p)
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f) close(f)
+#define zerr(f) (k == (extent)(-1L))
+#define zstdin 0
+
+#endif /* _ZIPUP_H_ */
diff --git a/beos/Contents b/beos/Contents
new file mode 100644 (file)
index 0000000..939a535
--- /dev/null
@@ -0,0 +1,14 @@
+Contents of the "beos" sub-directory for Zip 2.2 and later:
+
+  Contents      this file
+  README        Notes from the author of the BeOS port
+  Makefile      makefile for building (sorry, no project files)
+  beos.c        BeOS-specific routines (similar to the UNIX ones)
+  osdep.h       BeOS-specific includes and whatnot
+  zipup.h       Definitions for zip routines
+
+This port supports both Metrowerks CodeWarrior and GNU C as the compiler,
+and PowerPC and x86 architectures.
+
+- Chris Herborth (chrish@pobox.com)
+  June 24, 1998
diff --git a/beos/Makefile b/beos/Makefile
new file mode 100644 (file)
index 0000000..0dc31e1
--- /dev/null
@@ -0,0 +1,180 @@
+######################################################################
+#
+# Makefile for Info-ZIP's zip, zipcloak, zipnote, and zipsplit on BeOS
+#
+# Copyright Â© 1999 Info-ZIP
+#             Chris Herborth (chrish@pobox.com)
+#
+# This is the new New and Improved Makefile for BeOS; it automatically
+# detects your platform and uses the appropriate compiler and compiler
+# flags.
+
+######################################################################
+# Things that don't change:
+
+# Punish people who don't have SMP hardware.
+MAKE  = make -j 4 -f beos/Makefile
+SHELL = /bin/sh
+
+LN = ln -s
+
+BIND = $(CC)
+AS   = $(CC) -c
+CPP  = $(CC) -E
+
+INSTALL = install
+
+# Target directories
+prefix = /boot/home/config
+BINDIR = $(prefix)/bin
+manext = 1
+MANDIR = $(prefix)/man/man$(manext)
+ZIPMANUAL = MANUAL
+
+VERSION = Version 2.3 of __DATE__
+
+######################################################################
+# Things that change:
+
+# PowerPC system
+ifeq "$(BE_HOST_CPU)" "ppc"
+
+CC:=mwcc
+
+ifeq "$(shell uname -r)" "4.0"
+
+CFLAGS:=-O7 -opt schedule604 -rostr -w9 \
+               -I. -DHAVE_DIRENT_H -DPASSWD_FROM_STDIN
+LFLAGS1:=-warn
+
+else
+
+CFLAGS:=-O7 -proc 604e -w9 -I. -DHAVE_DIRENT_H -DPASSWD_FROM_STDIN
+LFLAGS1:=-nodup
+
+endif
+
+LFLAGS2:=-L/boot/develop/lib/ppc -lbe -lroot
+OBJA =
+TARGET=$(ZIPS)
+
+# x86 system
+else
+
+CC:=gcc
+
+# Removed -Wconversion and -Wshadow because of the unnecessary warnings 
+# they generate. - Sept. 28, 1999
+CFLAGS:=-O3 -mpentiumpro \
+               -Wall -Wno-multichar -Wno-ctor-dtor-privacy \
+               -Wbad-function-cast -Woverloaded-virtual \
+               -I. -I/boot/develop/headers/be/support \
+           -I/boot/develop/headers/be/storage \
+           -DHAVE_DIRENT_H -DPASSWD_FROM_STDIN # -DASMV
+LFLAGS1:=
+LFLAGS2:=-L/boot/develop/lib/x86 -lbe -lroot
+OBJA = #match.o
+TARGET=$(ZIPS)
+
+endif
+
+######################################################################
+# Helpful targets
+all:
+       $(MAKE) CC=$(CC) CFLAGS="$(CFLAGS)" \
+               LFLAGS1="$(LFLAGS1)" LFLAGS2="$(LFLAGS2)" \
+               $(TARGET)
+
+######################################################################
+# Object file lists and other build goodies
+
+# Object file lists
+OBJZ = zip.o zipfile.o zipup.o fileio.o util.o globals.o crypt.o ttyio.o \
+       beos.o crc32.o crctab.o
+OBJI = deflate.o trees.o
+# OBJA moved into ifeq block above; we'll use assembly for x86
+OBJU = zipfile_.o fileio_.o util_.o globals.o beos_.o
+OBJN = zipnote.o  $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt_.o ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+# Headers
+ZIP_H = zip.h ziperr.h tailor.h beos/osdep.h
+
+# What to build?
+ZIPS = zip zipnote zipsplit zipcloak
+
+# suffix rules
+.SUFFIXES:
+.SUFFIXES: _.o .o .c .doc .1
+.c_.o:
+       rm -f $*_.c; $(LN) $< $*_.c
+       $(CC) -c $(CFLAGS) -DUTIL $*_.c
+       rm -f $*_.c
+
+.c.o:
+       $(CC) -c $(CFLAGS) $<
+
+.1.doc:
+       groff -man -Tascii $< > $@
+
+# rules for zip, zipnote, zipcloak, zipsplit, and the Zip MANUAL.
+$(OBJZ): $(ZIP_H)
+$(OBJI): $(ZIP_H)
+$(OBJN): $(ZIP_H)
+$(OBJS): $(ZIP_H)
+$(OBJC): $(ZIP_H)
+zip.o zipup.o crypt.o ttyio.o zipcloak.o crypt_.o: crypt.h
+zip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h
+zip.o crypt.o ttyio.o zipcloak.o crypt_.o: ttyio.h
+zipup.o: beos/zipup.h
+
+match.o: match.S
+       $(CPP) match.S > _match.s
+       $(AS) _match.s
+       mv -f _match.o match.o
+       rm -f _match.s
+
+beos.o: beos/beos.c
+       $(CC) -c $(CFLAGS) beos/beos.c
+
+beos_.o: beos/beos.c
+       rm -f $*_.c; $(LN) beos/beos.c $*_.c
+       $(CC) -c $(CFLAGS) -DUTIL $*_.c
+       rm -f $*_.c
+
+zips: $(ZIPS)
+zipsman: $(ZIPS) $(ZIPMANUAL)
+
+zip: $(OBJZ) $(OBJI) $(OBJA)
+       $(BIND) -o zip $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)
+zipnote: $(OBJN)
+       $(BIND) -o zipnote $(LFLAGS1) $(OBJN) $(LFLAGS2)
+zipcloak: $(OBJC)
+       $(BIND) -o zipcloak $(LFLAGS1) $(OBJC) $(LFLAGS2)
+zipsplit: $(OBJS)
+       $(BIND) -o zipsplit $(LFLAGS1) $(OBJS) $(LFLAGS2)
+
+$(ZIPMANUAL): man/zip.1
+       groff -man -Tascii man/zip.1 > $(ZIPMANUAL)
+
+# install
+install:        $(ZIPS)
+       $(INSTALL) -m755 $(ZIPS) $(BINDIR)
+       mkdir -p $(MANDIR)
+       $(INSTALL) -m644 man/zip.1 $(MANDIR)/zip.$(manext)
+
+uninstall:
+       -cd $(BINDIR); rm -f $(ZIPS)
+       -cd $(MANDIR); rm -f zip.$(manext)
+
+dist: $(ZIPMANUAL)
+       zip -u9T zip`sed -e '/VERSION/!d' -e 's/.*"\(.*\)".*/\1/' \
+                         -e s/[.]//g -e q revision.h` \
+         `awk '/^Makefile/,/vms_zip.rnh/ {print $$1}' < contents`
+
+# clean up after making stuff and installing it
+clean:
+       rm -f *.o $(ZIPS) flags
+
+# end of Makefile
diff --git a/beos/README b/beos/README
new file mode 100644 (file)
index 0000000..b985ea0
--- /dev/null
@@ -0,0 +1,31 @@
+Info-ZIP's zip for BeOS
+
+KNOWN BUGS
+
+- None! (as of zip 2.21)
+
+- building on x86 BeOS generates a hell of a lot of bugs; I'm not going to
+  worry about them until Be fixes their headers though...
+
+FEATURES
+
+- stores BeOS file attributes, compressing them if possible (as of 2.21,
+  this works properly for symbolic links, too; as of 2.3, this works
+  properly for symbolic links whether you're storing them as links or not)
+
+- zip files are created with the correct file type (application/zip)
+
+- supports both Metrowerks CodeWarrior (PowerPC platform) and GNU C
+  (x86 platform), automatically picking the default compiler for each
+  architecture
+
+Please report any bugs to the Zip-Bugs mailing list; our email address is
+zip-bugs@lists.wku.edu.  If it's something BeOS-specific, you could email
+me directly.
+
+Visit the Info-ZIP web site (http://www.cdrom.com/pub/infozip/) for all the
+latest zip and unzip information, FAQs, source code and ready-to-run
+executables.
+
+- Chris Herborth (chrish@pobox.com)
+  April 2/1999
diff --git a/beos/beos.c b/beos/beos.c
new file mode 100644 (file)
index 0000000..d64cbb3
--- /dev/null
@@ -0,0 +1,946 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, all these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+
+ This BeOS-specific file is based on unix.c in the unix directory; changes
+ by Chris Herborth (chrish@pobox.com).
+
+*/
+
+#include "zip.h"
+
+#ifndef UTIL    /* the companion #endif is a bit of ways down ... */
+
+#include <time.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <dirent.h>
+
+#include <kernel/fs_attr.h>
+#include <storage/Mime.h>
+#include <support/byteorder.h>
+
+
+#define PAD 0
+#define PATH_END '/'
+
+/* Library functions not in (most) header files */
+
+#ifdef _POSIX_VERSION
+#  include <utime.h>
+#else
+   int utime OF((char *, time_t *));
+#endif
+
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+/* Local functions */
+local char *readd OF((DIR *));
+local int get_attr_dir( const char *, char **, off_t * );
+local int add_UT_ef( struct zlist far * );
+local int add_Ux_ef( struct zlist far * );
+local int add_Be_ef( struct zlist far * );
+
+
+#ifdef NO_DIR                    /* for AT&T 3B1 */
+#include <sys/dir.h>
+#ifndef dirent
+#  define dirent direct
+#endif
+typedef FILE DIR;
+/*
+**  Apparently originally by Rich Salz.
+**  Cleaned up and modified by James W. Birdsall.
+*/
+
+#define opendir(path) fopen(path, "r")
+
+struct dirent *readdir(dirp)
+DIR *dirp;
+{
+  static struct dirent entry;
+
+  if (dirp == NULL)
+    return NULL;
+  for (;;)
+    if (fread (&entry, sizeof (struct dirent), 1, dirp) == 0)
+      return NULL;
+    else if (entry.d_ino)
+      return (&entry);
+} /* end of readdir() */
+
+#define closedir(dirp) fclose(dirp)
+#endif /* NO_DIR */
+
+
+local char *readd(d)
+DIR *d;                 /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+   no more entries or an error occurs. */
+{
+  struct dirent *e;
+
+  e = readdir(d);
+  return e == NULL ? (char *) NULL : e->d_name;
+}
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  char *a;              /* path and name for recursion */
+  DIR *d;               /* directory stream from opendir() */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (LSSTAT(n, &s))
+  {
+    /* Not a file or directory--search for shell expression in zip file */
+    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+  if ((s.st_mode & S_IFDIR) == 0)
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  } else {
+    /* Add trailing / to the directory name */
+    if ((p = malloc(strlen(n)+2)) == NULL)
+      return ZE_MEM;
+    if (strcmp(n, ".") == 0) {
+      *p = '\0';  /* avoid "./" prefix and do not create zip entry */
+    } else {
+      strcpy(p, n);
+      a = p + strlen(p);
+      if (a[-1] != '/')
+        strcpy(a, "/");
+      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+        free((zvoid *)p);
+        return m;
+      }
+    }
+    /* recurse into directory */
+    if (recurse && (d = opendir(n)) != NULL)
+    {
+      while ((e = readd(d)) != NULL) {
+        if (strcmp(e, ".") && strcmp(e, ".."))
+        {
+          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+          {
+            closedir(d);
+            free((zvoid *)p);
+            return ZE_MEM;
+          }
+          strcat(strcpy(a, p), e);
+          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
+          {
+            if (m == ZE_MISS)
+              zipwarn("name not matched: ", a);
+            else
+              ziperr(m, a);
+          }
+          free((zvoid *)a);
+        }
+      }
+      closedir(d);
+    }
+    free((zvoid *)p);
+  } /* (s.st_mode & S_IFDIR) == 0) */
+  return ZE_OK;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t;              /* shortened name */
+  int dosflag;
+
+  dosflag = dosify;  /* default for non-DOS and non-OS/2 */
+
+  /* Find starting point in name before doing malloc */
+  for (t = x; *t == '/'; t++)
+    ;                   /* strip leading '/' chars to get a relative path */
+  while (*t == '.' && t[1] == '/')
+    t += 2;             /* strip redundant leading "./" sections */
+
+  /* Make changes, if any, to the copied name (leave original intact) */
+  if (!pathput)
+    t = last(t, PATH_END);
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL)
+    return NULL;
+  strcpy(n, t);
+
+  if (isdir == 42) return n;    /* avoid warning on unused variable */
+
+  if (dosify)
+    msname(n);
+
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+  return n;
+}
+
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+
+  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+    return NULL;
+  strcpy(x, n);
+  return x;
+}
+
+/*
+ * XXX use ztimbuf in both POSIX and non POSIX cases ?
+ */
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+#ifdef _POSIX_VERSION
+  struct utimbuf u;     /* argument for utime()  const ?? */
+#else
+  time_t u[2];          /* argument for utime() */
+#endif
+
+  /* Convert DOS time to time_t format in u */
+#ifdef _POSIX_VERSION
+  u.actime = u.modtime = dos2unixtime(d);
+  utime(f, &u);
+#else
+  u[0] = u[1] = dos2unixtime(d);
+  utime(f, u);
+#endif
+
+}
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  char *name;
+  unsigned int len = strlen(f);
+
+  if (f == label) {
+    if (a != NULL)
+      *a = label_mode;
+    if (n != NULL)
+      *n = -2L; /* convention for a label name */
+    if (t != NULL)
+      t->atime = t->mtime = t->ctime = label_utim;
+    return label_time;
+  }
+
+  if ((name = malloc(len + 1)) == NULL) {
+    ZIPERR(ZE_MEM, "filetime");
+  }
+  strcpy(name, f);
+  if (name[len - 1] == '/')
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+  if (strcmp(f, "-") == 0) {
+    if (fstat(fileno(stdin), &s) != 0) {
+      free(name);
+      error("fstat(stdin)");
+    }
+  } else if (LSSTAT(name, &s) != 0) {
+             /* Accept about any file kind including directories
+              * (stored with trailing / with -r option)
+              */
+    free(name);
+    return 0;
+  }
+
+  if (a != NULL) {
+    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
+    if ((s.st_mode & S_IFMT) == S_IFDIR) {
+      *a |= MSDOS_DIR_ATTR;
+    }
+  }
+  if (n != NULL)
+    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = s.st_mtime;   /* best guess (s.st_ctime: last status change!) */
+  }
+
+  free(name);
+
+  return unix2dostime(&s.st_mtime);
+}
+
+/* ----------------------------------------------------------------------
+
+Return a malloc()'d buffer containing all of the attributes and their names
+for the file specified in name.  You have to free() this yourself.  The length
+of the buffer is also returned.
+
+If get_attr_dir() fails, the buffer will be NULL, total_size will be 0,
+and an error will be returned:
+
+    EOK    - no errors occurred
+    EINVAL - attr_buff was pointing at a buffer
+    ENOMEM - insufficient memory for attribute buffer
+
+Other errors are possible (whatever is returned by the fs_attr.h functions).
+
+PROBLEMS:
+
+- pointers are 32-bits; attributes are limited to off_t in size so it's
+  possible to overflow... in practice, this isn't too likely... your
+  machine will thrash like hell before that happens
+
+*/
+
+#define INITIAL_BUFF_SIZE 65536
+
+int get_attr_dir( const char *name, char **attr_buff, off_t *total_size )
+{
+    int               retval = EOK;
+    int               fd;
+    DIR              *fa_dir;
+    struct dirent    *fa_ent;
+    off_t             attrs_size;
+    off_t             this_size;
+    char             *ptr;
+    struct attr_info  fa_info;
+    struct attr_info  big_fa_info;
+
+    retval      = EOK;
+    attrs_size  = 0;    /* gcc still says this is used uninitialized... */
+    *total_size = 0;
+
+    /* ----------------------------------------------------------------- */
+    /* Sanity-check.                                                     */
+    if( *attr_buff != NULL ) {
+        return EINVAL;
+    }
+
+    /* ----------------------------------------------------------------- */
+    /* Can we open the file/directory?                                   */
+    /*                                                                   */
+    /* linkput is a zip global; it's set to 1 if we're storing symbolic  */
+    /* links as symbolic links (instead of storing the thing the link    */
+    /* points to)... if we're storing the symbolic link as a link, we'll */
+    /* want the link's file attributes, otherwise we want the target's.  */
+    if( linkput ) {
+        fd = open( name, O_RDONLY | O_NOTRAVERSE );
+    } else {
+        fd = open( name, O_RDONLY );
+    }
+    if( fd < 0 ) {
+        return errno;
+    }
+
+    /* ----------------------------------------------------------------- */
+    /* Allocate an initial buffer; 64k should usually be enough.         */
+    *attr_buff = (char *)malloc( INITIAL_BUFF_SIZE );
+    ptr        = *attr_buff;
+    if( ptr == NULL ) {
+        close( fd );
+
+        return ENOMEM;
+    }
+
+    /* ----------------------------------------------------------------- */
+    /* Open the attributes directory for this file.                      */
+    fa_dir = fs_fopen_attr_dir( fd );
+    if( fa_dir == NULL ) {
+        close( fd );
+
+        free( ptr );
+        *attr_buff = NULL;
+
+        return retval;
+    }
+
+    /* ----------------------------------------------------------------- */
+    /* Read all the attributes; the buffer could grow > 64K if there are */
+    /* many and/or they are large.                                       */
+    fa_ent = fs_read_attr_dir( fa_dir );
+    while( fa_ent != NULL ) {
+        retval = fs_stat_attr( fd, fa_ent->d_name, &fa_info );
+        /* TODO: check retval != EOK */
+
+        this_size  = strlen( fa_ent->d_name ) + 1;
+        this_size += sizeof( struct attr_info );
+        this_size += fa_info.size;
+
+        attrs_size += this_size;
+
+        if( attrs_size > INITIAL_BUFF_SIZE ) {
+            unsigned long offset = ptr - *attr_buff;
+
+            *attr_buff = (char *)realloc( *attr_buff, attrs_size );
+            if( *attr_buff == NULL ) {
+                retval = fs_close_attr_dir( fa_dir );
+                /* TODO: check retval != EOK */
+                close( fd );
+
+                return ENOMEM;
+            }
+
+            ptr = *attr_buff + offset;
+        }
+
+        /* Now copy the data for this attribute into the buffer. */
+        strcpy( ptr, fa_ent->d_name );
+        ptr += strlen( fa_ent->d_name );
+        *ptr++ = '\0';
+
+        /* We need to put a big-endian version of the fa_info data into */
+        /* the archive.                                                 */
+        big_fa_info.type = B_HOST_TO_BENDIAN_INT32( fa_info.type );
+        big_fa_info.size = B_HOST_TO_BENDIAN_INT64( fa_info.size );
+        memcpy( ptr, &big_fa_info, sizeof( struct attr_info ) );
+        ptr += sizeof( struct attr_info );
+
+        if( fa_info.size > 0 ) {
+            ssize_t read_bytes;
+
+            read_bytes = fs_read_attr( fd, fa_ent->d_name, fa_info.type, 0,
+                                       ptr, fa_info.size );
+            if( read_bytes != fa_info.size ) {
+                /* print a warning about mismatched sizes */
+                char buff[80];
+
+                sprintf( buff, "read %ld, expected %ld",
+                         (ssize_t)read_bytes, (ssize_t)fa_info.size );
+                zipwarn( "attribute size mismatch: ", buff );
+            }
+
+            /* Wave my magic wand... this swaps all the Be types to big- */
+            /* endian automagically.                                     */
+            (void)swap_data( fa_info.type, ptr, fa_info.size,
+                             B_SWAP_HOST_TO_BENDIAN );
+
+            ptr += fa_info.size;
+        }
+
+        fa_ent = fs_read_attr_dir( fa_dir );
+    }
+
+    /* ----------------------------------------------------------------- */
+    /* Close the attribute directory.                                    */
+    retval = fs_close_attr_dir( fa_dir );
+    /* TODO: check retval != EOK */
+
+    /* ----------------------------------------------------------------- */
+    /* If the buffer is too big, shrink it.                              */
+    if( attrs_size < INITIAL_BUFF_SIZE ) {
+        *attr_buff = (char *)realloc( *attr_buff, attrs_size );
+        if( *attr_buff == NULL ) {
+            /* This really shouldn't happen... */
+            close( fd );
+
+            return ENOMEM;
+        }
+    }
+
+    *total_size = attrs_size;
+
+    close( fd );
+
+    return EOK;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Add a 'UT' extra field to the zlist data pointed to by z.              */
+
+#define EB_L_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(2))
+#define EB_C_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(1))
+
+local int add_UT_ef( struct zlist far *z )
+{
+    char        *l_ef = NULL;
+    char        *c_ef = NULL;
+    struct stat  s;
+
+#ifdef IZ_CHECK_TZ
+    if (!zp_tz_is_valid)
+        return ZE_OK;           /* skip silently if no valid TZ info */
+#endif
+
+    /* We can't work if there's no entry to work on. */
+    if( z == NULL ) {
+        return ZE_LOGIC;
+    }
+
+    /* Check to make sure we've got enough room in the extra fields. */
+    if( z->ext + EB_L_UT_SIZE > USHRT_MAX ||
+        z->cext + EB_C_UT_SIZE > USHRT_MAX ) {
+        return ZE_MEM;
+    }
+
+    /* stat() the file (or the symlink) to get the data; if we can't get */
+    /* the data, there's no point in trying to fill out the fields.      */
+    if(LSSTAT( z->name, &s ) ) {
+        return ZE_OPEN;
+    }
+
+    /* Allocate memory for the local and central extra fields. */
+    if( z->extra && z->ext != 0 ) {
+        l_ef = (char *)realloc( z->extra, z->ext + EB_L_UT_SIZE );
+    } else {
+        l_ef = (char *)malloc( EB_L_UT_SIZE );
+        z->ext = 0;
+    }
+    if( l_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->extra = l_ef;
+    l_ef += z->ext;
+
+    if( z->cextra && z->cext != 0 ) {
+        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_UT_SIZE );
+    } else {
+        c_ef = (char *)malloc( EB_C_UT_SIZE );
+        z->cext = 0;
+    }
+    if( c_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->cextra = c_ef;
+    c_ef += z->cext;
+
+    /* Now add the local version of the field. */
+    *l_ef++ = 'U';
+    *l_ef++ = 'T';
+    *l_ef++ = (char)(EB_UT_LEN(2)); /* length of data in local EF */
+    *l_ef++ = (char)0;
+    *l_ef++ = (char)(EB_UT_FL_MTIME | EB_UT_FL_ATIME);
+    *l_ef++ = (char)(s.st_mtime);
+    *l_ef++ = (char)(s.st_mtime >> 8);
+    *l_ef++ = (char)(s.st_mtime >> 16);
+    *l_ef++ = (char)(s.st_mtime >> 24);
+    *l_ef++ = (char)(s.st_atime);
+    *l_ef++ = (char)(s.st_atime >> 8);
+    *l_ef++ = (char)(s.st_atime >> 16);
+    *l_ef++ = (char)(s.st_atime >> 24);
+
+    z->ext += EB_L_UT_SIZE;
+
+    /* Now add the central version. */
+    memcpy(c_ef, l_ef-EB_L_UT_SIZE, EB_C_UT_SIZE);
+    c_ef[EB_LEN] = (char)(EB_UT_LEN(1)); /* length of data in central EF */
+
+    z->cext += EB_C_UT_SIZE;
+
+    return ZE_OK;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Add a 'Ux' extra field to the zlist data pointed to by z.              */
+
+#define EB_L_UX2_SIZE   (EB_HEADSIZE + EB_UX2_MINLEN)
+#define EB_C_UX2_SIZE   (EB_HEADSIZE)
+
+local int add_Ux_ef( struct zlist far *z )
+{
+    char        *l_ef = NULL;
+    char        *c_ef = NULL;
+    struct stat  s;
+
+    /* Check to make sure we've got enough room in the extra fields. */
+    if( z->ext + EB_L_UX2_SIZE > USHRT_MAX ||
+        z->cext + EB_C_UX2_SIZE > USHRT_MAX ) {
+        return ZE_MEM;
+    }
+
+    /* stat() the file (or the symlink) to get the data; if we can't get */
+    /* the data, there's no point in trying to fill out the fields.      */
+    if(LSSTAT( z->name, &s ) ) {
+        return ZE_OPEN;
+    }
+
+    /* Allocate memory for the local and central extra fields. */
+    if( z->extra && z->ext != 0 ) {
+        l_ef = (char *)realloc( z->extra, z->ext + EB_L_UX2_SIZE );
+    } else {
+        l_ef = (char *)malloc( EB_L_UX2_SIZE );
+        z->ext = 0;
+    }
+    if( l_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->extra = l_ef;
+    l_ef += z->ext;
+
+    if( z->cextra && z->cext != 0 ) {
+        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_UX2_SIZE );
+    } else {
+        c_ef = (char *)malloc( EB_C_UX2_SIZE );
+        z->cext = 0;
+    }
+    if( c_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->cextra = c_ef;
+    c_ef += z->cext;
+
+    /* Now add the local version of the field. */
+    *l_ef++ = 'U';
+    *l_ef++ = 'x';
+    *l_ef++ = (char)(EB_UX2_MINLEN);
+    *l_ef++ = (char)(EB_UX2_MINLEN >> 8);
+    *l_ef++ = (char)(s.st_uid);
+    *l_ef++ = (char)(s.st_uid >> 8);
+    *l_ef++ = (char)(s.st_gid);
+    *l_ef++ = (char)(s.st_gid >> 8);
+
+    z->ext += EB_L_UX2_SIZE;
+
+    /* Now add the central version of the field. */
+    *c_ef++ = 'U';
+    *c_ef++ = 'x';
+    *c_ef++ = 0;
+    *c_ef++ = 0;
+
+    z->cext += EB_C_UX2_SIZE;
+
+    return ZE_OK;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Add a 'Be' extra field to the zlist data pointed to by z.              */
+
+#define EB_L_BE_SIZE    (EB_HEADSIZE + EB_L_BE_LEN) /* + attr size */
+#define EB_C_BE_SIZE    (EB_HEADSIZE + EB_C_BE_LEN)
+
+/* maximum memcompress overhead is the sum of the compression header length */
+/* (6 = ush compression type, ulg CRC) and the worstcase deflate overhead   */
+/* when uncompressible data are kept in 2 "stored" blocks (5 per block =    */
+/* byte blocktype + 2 * ush blocklength) */
+#define MEMCOMPRESS_OVERHEAD    (EB_MEMCMPR_HSIZ + EB_DEFLAT_EXTRA)
+
+local int add_Be_ef( struct zlist far *z )
+{
+    char *l_ef       = NULL;
+    char *c_ef       = NULL;
+    char *attrbuff   = NULL;
+    off_t attrsize   = 0;
+    char *compbuff   = NULL;
+    ush   compsize   = 0;
+    uch   flags      = 0;
+
+    /* Check to make sure we've got enough room in the extra fields. */
+    if( z->ext + EB_L_BE_SIZE > USHRT_MAX ||
+        z->cext + EB_C_BE_SIZE > USHRT_MAX ) {
+        return ZE_MEM;
+    }
+
+    /* Attempt to load up a buffer full of the file's attributes. */
+    {
+        int retval;
+
+        retval = get_attr_dir( z->name, &attrbuff, &attrsize );
+        if( retval != EOK ) {
+            return ZE_OPEN;
+        }
+        if( attrsize == 0 ) {
+            return ZE_OK;
+        }
+        if( attrbuff == NULL ) {
+            return ZE_LOGIC;
+        }
+
+        /* Check for way too much data. */
+        if( attrsize > (off_t)ULONG_MAX ) {
+            zipwarn( "uncompressed attributes truncated", "" );
+            attrsize = (off_t)(ULONG_MAX - MEMCOMPRESS_OVERHEAD);
+        }
+    }
+
+    if( verbose ) {
+        printf( "\t[in=%lu]", (unsigned long)attrsize );
+    }
+
+    /* Try compressing the data */
+    compbuff = (char *)malloc( (size_t)attrsize + MEMCOMPRESS_OVERHEAD );
+    if( compbuff == NULL ) {
+        return ZE_MEM;
+    }
+    compsize = memcompress( compbuff,
+                            (size_t)attrsize + MEMCOMPRESS_OVERHEAD,
+                            attrbuff,
+                            (size_t)attrsize );
+    if( verbose ) {
+        printf( " [out=%u]", compsize );
+    }
+
+    /* Attempt to optimise very small attributes. */
+    if( compsize > attrsize ) {
+        free( compbuff );
+        compsize = (ush)attrsize;
+        compbuff = attrbuff;
+
+        flags = EB_BE_FL_NATURAL;
+    }
+
+    /* Check to see if we really have enough room in the EF for the data. */
+    if( ( z->ext + compsize + EB_L_BE_LEN ) > USHRT_MAX ) {
+        compsize = USHRT_MAX - EB_L_BE_LEN - z->ext;
+    }
+
+    /* Allocate memory for the local and central extra fields. */
+    if( z->extra && z->ext != 0 ) {
+        l_ef = (char *)realloc( z->extra, z->ext + EB_L_BE_SIZE + compsize );
+    } else {
+        l_ef = (char *)malloc( EB_L_BE_SIZE + compsize );
+        z->ext = 0;
+    }
+    if( l_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->extra = l_ef;
+    l_ef += z->ext;
+
+    if( z->cextra && z->cext != 0 ) {
+        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_BE_SIZE );
+    } else {
+        c_ef = (char *)malloc( EB_C_BE_SIZE );
+        z->cext = 0;
+    }
+    if( c_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->cextra = c_ef;
+    c_ef += z->cext;
+
+    /* Now add the local version of the field. */
+    *l_ef++ = 'B';
+    *l_ef++ = 'e';
+    *l_ef++ = (char)(compsize + EB_L_BE_LEN);
+    *l_ef++ = (char)((compsize + EB_L_BE_LEN) >> 8);
+    *l_ef++ = (char)((unsigned long)attrsize);
+    *l_ef++ = (char)((unsigned long)attrsize >> 8);
+    *l_ef++ = (char)((unsigned long)attrsize >> 16);
+    *l_ef++ = (char)((unsigned long)attrsize >> 24);
+    *l_ef++ = flags;
+    memcpy( l_ef, compbuff, (size_t)compsize );
+
+    z->ext += EB_L_BE_SIZE + compsize;
+
+    /* And the central version. */
+    *c_ef++ = 'B';
+    *c_ef++ = 'e';
+    *c_ef++ = (char)(EB_C_BE_LEN);
+    *c_ef++ = (char)(EB_C_BE_LEN >> 8);
+    *c_ef++ = (char)compsize;
+    *c_ef++ = (char)(compsize >> 8);
+    *c_ef++ = (char)(compsize >> 16);
+    *c_ef++ = (char)(compsize >> 24);
+    *c_ef++ = flags;
+
+    z->cext += EB_C_BE_SIZE;
+
+    return ZE_OK;
+}
+
+/* Extra field info:
+   - 'UT' - UNIX time extra field
+   - 'Ux' - UNIX uid/gid extra field
+   - 'Be' - BeOS file attributes extra field
+
+   This is done the same way ../unix/unix.c stores the 'UT'/'Ux' fields
+   (full data in local header, only modification time in central header),
+   with the 'Be' field added to the end and the size of the 'Be' field
+   in the central header.
+
+   See the end of beos/osdep.h for a simple explanation of the 'Be' EF
+   layout.
+ */
+int set_extra_field(z, z_utim)
+  struct zlist far *z;
+  iztimes *z_utim;
+  /* store full data in local header but just modification time stamp info
+     in central header */
+{
+    int retval;
+
+    /* Tell picky compilers to shut up about unused variables. */
+    z_utim = z_utim;
+
+    /* Check to make sure z is valid. */
+    if( z == NULL ) {
+        return ZE_LOGIC;
+    }
+
+    /* This function is much simpler now that I've moved the extra fields */
+    /* out... it simplified the 'Be' code, too.                           */
+    retval = add_UT_ef( z );
+    if( retval != ZE_OK ) {
+        return retval;
+    }
+
+    retval = add_Ux_ef( z );
+    if( retval != ZE_OK ) {
+        return retval;
+    }
+
+    retval = add_Be_ef( z );
+    if( retval != ZE_OK ) {
+        return retval;
+    }
+
+    return ZE_OK;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Set a file's MIME type.                                                */
+void setfiletype( const char *file, const char *type )
+{
+    int fd;
+    attr_info fa;
+    ssize_t wrote_bytes;
+
+    fd = open( file, O_RDWR );
+    if( fd < 0 ) {
+        zipwarn( "can't open zipfile to write file type", "" );
+        return;
+    }
+
+    fa.type = B_MIME_STRING_TYPE;
+    fa.size = (off_t)(strlen( type ) + 1);
+
+    wrote_bytes = fs_write_attr( fd, BE_FILE_TYPE_NAME, fa.type, 0,
+                                 type, fa.size );
+    if( wrote_bytes != (ssize_t)fa.size ) {
+        zipwarn( "couldn't write complete file type", "" );
+    }
+
+    close( fd );
+}
+
+int deletedir(d)
+char *d;                /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+   Return the result of rmdir(), delete(), or system().
+   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).
+ */
+{
+# ifdef NO_RMDIR
+    /* code from Greg Roelofs, who horked it from Mark Edwards (unzip) */
+    int r, len;
+    char *s;              /* malloc'd string for system command */
+
+    len = strlen(d);
+    if ((s = malloc(len + 34)) == NULL)
+      return 127;
+
+    sprintf(s, "IFS=\" \t\n\" /bin/rmdir %s 2>/dev/null", d);
+    r = system(s);
+    free(s);
+    return r;
+# else /* !NO_RMDIR */
+    return rmdir(d);
+# endif /* ?NO_RMDIR */
+}
+
+#endif /* !UTIL */
+
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+void version_local()
+{
+    static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
+
+    printf(CompiledWith,
+
+#ifdef __MWERKS__
+      "Metrowerks CodeWarrior", "",
+#else
+#  ifdef __GNUC__
+      "gcc ", __VERSION__,
+#  endif
+#endif
+
+      "BeOS",
+
+#ifdef __POWERPC__
+      " (PowerPC)",
+#else
+#  ifdef __INTEL__
+      " (x86)",
+#  else
+      " (UNKNOWN!)",
+#  endif
+#endif
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+    );
+
+} /* end function version_local() */
diff --git a/beos/osdep.h b/beos/osdep.h
new file mode 100644 (file)
index 0000000..0197903
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <support/Errors.h>     /* for B_NO_ERROR */
+
+#define USE_EF_UT_TIME          /* Enable use of "UT" extra field time info */
+
+#define EB_L_BE_LEN 5           /* min size is an unsigned long and flag */
+#define EB_C_BE_LEN 5           /* Length of data in local EF and flag.  */
+
+#define EB_BE_FL_NATURAL    0x01    /* data is 'natural' (not compressed) */
+#define EB_BE_FL_BADBITS    0xfe    /* bits currently undefined           */
+
+#ifndef ZP_NEED_MEMCOMPR
+#  define ZP_NEED_MEMCOMPR
+#endif
+
+/* Set a file's MIME type. */
+#define BE_FILE_TYPE_NAME   "BEOS:TYPE"
+void setfiletype( const char *file, const char *type );
+
+/*
+DR9 'Be' extra-field layout:
+
+'Be'      - signature
+ef_size   - size of data in this EF (little-endian unsigned short)
+full_size - uncompressed data size (little-endian unsigned long)
+flag      - flags (byte)
+            flags & EB_BE_FL_NATURAL    = the data is not compressed
+            flags & EB_BE_FL_BADBITS    = the data is corrupted or we
+                                          can't handle it properly
+data      - compressed or uncompressed file attribute data
+
+If flag & EB_BE_FL_NATURAL, the data is not compressed; this optimisation is
+necessary to prevent wasted space for files with small attributes (which
+appears to be quite common on the Advanced Access DR9 release).  In this
+case, there should be ( ef_size - EB_L_BE_LEN ) bytes of data, and full_size
+should equal ( ef_size - EB_L_BE_LEN ).
+
+If the data is compressed, there will be ( ef_size - EB_L_BE_LEN ) bytes of
+compressed data, and full_size bytes of uncompressed data.
+
+If a file has absolutely no attributes, there will not be a 'Be' extra field.
+
+The uncompressed data is arranged like this:
+
+attr_name\0 - C string
+struct attr_info (big-endian)
+attr_data (length in attr_info.size)
+*/
diff --git a/beos/zipup.h b/beos/zipup.h
new file mode 100644 (file)
index 0000000..40c79eb
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef O_RDONLY
+#  include <fcntl.h>
+#endif
+#define fhow O_RDONLY
+#define fbad (-1)
+typedef int ftype;
+#define zopen(n,p) open(n,p)
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f) close(f)
+#define zerr(f) (k == (extent)(-1L))
+#define zstdin 0
diff --git a/cmsmvs/README.CMS b/cmsmvs/README.CMS
new file mode 100644 (file)
index 0000000..a4425da
--- /dev/null
@@ -0,0 +1,434 @@
+Using ZIP and UNZIP on VM/CMS
+=============================
+
+
+Installing executables
+----------------------
+
+The following CMS MODULEs are available:
+   ZIP
+   ZIPNOTE
+   ZIPCLOAK
+   ZIPSPLIT
+   UNZIP
+
+In addition to these, each MODULE file also has an EXEC with the same
+name.  These EXECs are front-ends to the MODULES that will attempt to
+set up the required runtime libraries before running the MODULE.
+All the EXECs are identical.  Only their names are different.
+They are stored as plain text files.
+
+The CMS MODULE files have been packed using the COPYFILE command to
+allow their file format to be properly restored, since variable length
+binary files will not currently unzip properly (see below for details).
+The MODULEs are shipped with a filetype or extension of CMO (for CMS
+MODULE).  Their names may vary on the distribution disk to indicate
+their level, etc.
+
+To restore them to executable MODULEs on CMS, do the following:
+   1. Upload them to CMS with a Fixed record length with LRECL 1024.
+      Example, from a DOS or OS/2 window, type this:
+         SEND unzip.cmo A:unzip module a (RECFM F LRECL 1024
+
+      Example, using FTP from CMS, type this:
+         BINARY FIXED 1024
+         GET unzip.cmo unzip.module.a
+
+      Note:  Replace "unzip.cmo" with the actual name.
+
+   2. Use COPYFILE to unpack the file.
+      Example, in CMS type this:
+         COPYFILE UNZIP MODULE A (UNPACK REPLACE OLDDATE
+
+   3. Repeat steps 1-2 for each of the programs.
+
+   4. Build the ZIPINFO module by typing this:
+         COPYFILE UNZIP MODULE A ZIPINFO MODULE A (OLDDATE
+
+   5. Upload the EXECs to CMS as text files (with ASCII-to-EBCDIC
+      translation).
+      Example, from a DOS or OS/2 window, type this:
+         SEND unzip.exc A:unzip exec a (CRLF
+
+      Example, using FTP from CMS, type this:
+         GET unzip.exc unzip.exec.a
+
+   6. Repeat steps 4 for each of the EXECs.
+
+
+Preparing the environment
+-------------------------
+
+The executables provided were compiled with IBM C 3.1.0 and
+require the the Language Environment (LE) runtime libraries.
+
+To provide access to the runtime libraries:
+   1. Link to the disk containing the Language Environment files,
+      if necessary.
+
+   2. Use the command "GLOBAL LOADLIB SCEERUN"
+
+   These commands can be placed in your PROFILE EXEC.
+
+   Note:  EXECs have been provided called ZIP, UNZIP, etc. that
+   issue the GLOBAL LOADLIB statement.  This was done to alleviate
+   frustration of users that don't have the GLOBAL LOADLIB statement
+   in their PROFILE EXEC.  These EXECs may require changing for
+   your system.
+
+   Unfortunately, there is no way, using IBM C, to produce a MODULE
+   that doesn't require a runtime library.
+
+
+Testing
+-------
+
+To test the MODULEs, just type ZIP or UNZIP.  They should
+show help information on using the commands.
+
+If you see something like this:
+   DMSLIO201W The following names are undefined:
+    CEEEV003
+   DMSABE155T User abend 4093 called from 00DCD298 reason code 000003EB
+
+Then you don't have access to the proper runtime libraries, as
+described above.
+
+Here is additional information on the ZIP and UNZIP programs that
+may assist support personnel:
+   - Compiled with IBM C V3R1M0 on VM/ESA 2.2.0 with
+     CMS level 13 Service Level 702.
+
+   - Require the SCEERUN LOADLIB runtime library.  This is
+     part of the Language Environment (LE).
+
+   - Linked with options RMODE ANY AMODE ANY RLDSAVE.
+
+If you continue to have trouble, report the problem to Zip-Bugs
+(see the bottom of this document).
+
+
+
+Compiling the source on VM/CMS
+------------------------------
+
+The source has been successfully compiled previously using
+C/370 2.1 and 2.2.  The source has been recently compiled using
+IBM C 3.1.0 on VM/ESA 2.2.0 with CMS level 13.  I don't have
+access to an MVS system so the code hasn't been tested there
+in a while.
+
+ 1. Unzip the source files required for CMS.  The root-level files
+    inside the ZIP file and the files in the CMSMVS subdirectory are
+    needed.  Example (use both commands):
+       unzip -aj zip23.zip -x */*   -dc
+       unzip -aj zip23.zip cmsmvs/* -dc
+
+    This example unzips the files to the C-disk, while translating
+    character data and ignoring paths.
+
+    If you don't already have a working UNZIP MODULE on CMS you will
+    have to unzip the files on another system and transport them
+    to CMS.  All the required files are plain text so they can
+    be transferred with ASCII-to-EBCDIC translations.
+
+ 2. Repeat step 1 with the zip file containing the UNZIP code.
+    Unzip the files to a different disk than the disk used for the ZIP
+    code.
+
+ 3. To compile the ZIP code, run the supplied CCZIP EXEC.
+    To compile the UNZIP code, run the supplied CCUNZIP EXEC.
+
+NOTE:
+Some of the ZIP and UNZIP source files have the same name.  It is
+recommended that you keep the source from each on separate disks and
+move the disk you are building from ahead of the other in the search
+order.
+
+For example, you may have a 192 disk with the ZIP source code and
+a 193 disk with the UNZIP source code.  To compile ZIP, access
+the 192 disk as B, then run CCZIP.  This will create the following
+modules:  ZIP, ZIPNOTE, ZIPSPLIT, ZIPCLOAK.
+
+To compile UNZIP, access 193 as B, then run CCUNZIP.  This will create
+the following modules:  UNZIP, ZIPINFO (a copy of UNZIP).
+
+
+=========================================================================
+
+
+Using ZIP/UNZIP
+---------------
+
+Documentation for the commands is in MANUAL NONAME (for ZIP) and in
+UNZIP DOC UNZIP.  INFOZIP DOC describes the use of the -Z option of
+UNZIP.
+
+The rest of this section explains special notes concerning the VM/CMS
+version of ZIP and UNZIP.
+
+
+Filenames and directories
+-------------------------
+
+ 1. Specifying filenames
+
+    a. When specifying CMS files, use filename.filetype.filemode format
+       (separate the three parts of the name with a period and use no
+       spaces).  Example:  profile.exec.a
+
+       Unfortunately, this prevents you from using ZIP from
+       FILELIST.  To unzip a zip file, however, you can type something
+       like this next to it in FILELIST:
+          unzip /n -d c
+
+       This will unzip the contents of the current file to a C-disk.
+
+    b. It is possible to use DD names with ZIP and UNZIP on CMS, though
+       it can be cumbersome.  Example:
+          filedef out disk myzip zip a
+          zip dd:out file1.txt file2.txt
+
+       While you can also use a DD name for the input files, ZIP
+       currently does not correctly resolve the filename and will
+       store something like "dd:in" inside the ZIP file.  A file stored
+       in this manor cannot easily be unzipped, as "dd:in" is an invalid
+       filename.
+
+    c. In places where a directory name would be used on a PC, such as
+       for the ZIP -b (work path) option or the UNZIP -d (destination
+       path) options, use a filemode letter for CMS.  For example,
+       to unzip files onto a C-disk, you might type something like this:
+          unzip myzip.zip -d c
+
+       Currently, ZIP uses the A-disk for work files.  When zipping
+       large files, you may want to specify a larger disk for work files.
+       This example will use a C-disk for work files.
+          zip -b C myzip.zip.c test.dat.a
+
+
+ 2. Filename conversions
+
+    a. Filemode letters are never stored into the zip file or take from
+       a zip file.  Only the filename and filetype are used.
+       ZIP removes the filemode when storing the filename into the
+       zip file.  UNZIP assumes "A" for the filemode unless the -d
+       option is used.
+
+    b. When unzipping, any path names are removed from the fileid
+       and the last two period-separated words are used as the
+       filename and filetype.  These are truncated to a maximum of
+       eight characters, if necessary.  If the filetype (extension)
+       is missing, then UNZIP uses "NONAME" for the filetype.
+       Any '(' or ')' characters are removed from the fileid.
+
+    c. All files are created in upper-case.  Files in mixed-case
+       cannot currently be stored into a ZIP file.
+
+    d. Shared File System (SFS) directories are not supported.
+       Files are always accessed by fn.ft.fm.  To use an SFS disk,
+       Assign it a filemode, then it can be used.
+
+
+ 3. Wildcards in file names
+
+    a. Wildcards are not supported in the zip filename.  The full
+       filename of the zip file must be given (but the .zip is not
+       necessary).  So, you can't do this:
+          unzip -t *.zip
+
+    b. Wildcards CAN be used with UNZIP to select (or exclude) files
+       inside a zip file.  Examples:
+          unzip myzip *.c          - Unzip all .c files.
+          unzip myzip *.c -x z*.c  - Unzip all .c files but those
+                                     starting with Z.
+
+    c. Wildcards cannot currently be used to select files with ZIP.
+       So, you can't do this:
+          zip -a myzip *.exec
+
+       I expect to fix this for CMS in the future.
+
+
+ 4. File timestamps
+
+    a. The dates and times of files being zipped or unzipped are not
+       currently read or set.  When a file is zipped, the timestamp
+       inside the zip file will always be the current system date and
+       time.  Likewise, when unzipping, the date and time of files
+       being unzipped will always be the current system date/time.
+
+    b. Existing files are assumed to be newer than files inside a zip
+       file when using the -f freshen option of UNZIP.  This will prevent
+       overwriting files that may be newer than the files inside the
+       zip file, but also effectively prevents the -f option from working.
+
+
+ 5. ASCII, EBCDIC, and binary data
+
+    Background
+    ----------
+    Most systems create data files as just a stream of bytes.  Record
+    breaks happen when certain characters (new line and/or carriage
+    return characters) are encountered in the data.  How to interpret
+    the data in a file is up to the user.  The system must be told
+    to either notice new line characters in the data or to assume
+    that the data in the file is binary data and should be read or
+    written as-is.
+
+    CMS and MVS are record-based systems.  All files are composed
+    of data records.  These can be stored in fixed-length files or
+    in variable length files.  With fixed-length files, each record
+    is the same length.  The record breaks are implied by the
+    LRECL (logical record length) attribute associated with the file.
+    With variable-length files, each record contains the length of
+    that record.  The separation of records are not part of the
+    data, but part of the file structure.
+
+    This means you can store any type of data in either type of file
+    structure without having to worry about the data being interpreted
+    as a record break.  Fixed-length files may have padding at the
+    end of the file to make up a full record.  Variable-length files
+    have no padding, but require extra record length data be stored
+    with the file data.
+
+    Storing fixed-length files into a zip file is simple, because all
+    the data can just be dumped into the zip file and the record
+    format (RECFM) and logical record length (LRECL) can be stored
+    in the extra data area of the zip file so they can be restored
+    when UNZIP is used.
+
+    Storing variable-length data is harder.  There is no place to put
+    the record length data needed for each record of the file.  This
+    data could be written to the zip file as the first two bytes of
+    each record and interpreted that way by UNZIP.  That would make
+    the data unusable on systems other than CMS and MVS, though.
+
+    Currently, there isn't a solution to this problem.  Each record is
+    written to the zip file and the record length information is
+    discarded.  Binary data stored in variable-length files can't be put
+    into a zip file then later unzipped back into the proper records.
+    This is fine for binary data that will be read as a stream of bytes
+    but not OK where the records matter, such as with CMS MODULEs.
+
+    If the data is text (character data), there is a solution.
+    This data can be converted into ASCII when it's stored into
+    a zip file.  The end of each record is now marked in the file
+    by new line characters.  Another advantage of this method is
+    that the data is now accessible to non-EBCDIC systems.  When
+    the data is unzipped on CMS or MVS, it is converted back into
+    EBCDIC and the records are recreated into a variable-length file.
+
+
+    So, here's what we have...
+
+    a. To store readable text data into a zip file that can be used
+       on other platforms, use the -a option with ZIP to convert the
+       data to ASCII.  These files will unzip into variable-length
+       files on CMS and should not contain binary data or corruption
+       may occur.
+
+    b. Files that were zipped on an ASCII-based system will be
+       automatically translated to EBCDIC when unzipped.  To prevent
+       this (to unzip binary data on CMS that was sent from an
+       ASCII-based system), use the -B option with UNZIP to force Binary
+       mode.  To zip binary files on CMS, use the -B option with ZIP to
+       force Binary mode.  This will prevent any data conversions from
+       taking place.
+
+    c. When using the ZIP program without specifying the "-a" or "-B"
+       option, ZIP defaults to "native" (EBCDIC) mode and tries to
+       preserve the file information (RECFM, LRECL, and BLKSIZE).  So
+       when you unzip a file zipped with ZIP under CMS or MVS, UNZIP
+       restores the file info.  The output will be fixed-length if the
+       original was fixed and variable-length if the original was
+       variable.
+
+    If UNZIP gives a "write error (disk full?)"  message, you may be
+    trying to unzip a binary file that was zipped as a text file
+    (without using the -B option)
+
+
+    Summary
+    -------
+    Here's how to ZIP the different types of files.
+
+    RECFM F text
+       Use the -a option with ZIP to convert to ASCII for use with other
+       platforms or no options for use on EBCDIC systems only.
+
+    RECFM V text
+       Use the -a option with ZIP to convert to ASCII for use with other
+       platforms or no options for use on EBCDIC systems only.
+
+
+    RECFM F binary
+       Use the -B option with ZIP (upper-case "B").
+
+    RECFM V binary
+       Use the -B option with ZIP.  Can be zipped OK but the record
+       structure is destroyed when unzipped.  This is OK for data files
+       read as binary streams but not OK for files such as CMS MODULEs.
+
+
+ 6. Character Sets
+
+    If you are used to running UNZIP on systems like UNIX, DOS, OS/2 or
+    Windows, you will may have some problems with differences in the
+    character set.
+
+    There are a number of different EBCDIC code pages, like there are a
+    number of different ASCII code pages.  For example, there is a US
+    EBCDIC, a German EBCDIC, and a Swedish EBCDIC.  As long as you are
+    working with other people who use the same EBCDIC code page, you
+    will have no trouble.  If you work with people who use ASCII, or who
+    use a different EBCDIC code page, you may need to do some
+    translation.
+
+    UNZIP translates ASCII text files to and from Open Systems EBCDIC
+    (IBM-1047), which may not be the EBCDIC that you are using.  For
+    example, US EBCDIC (IBM-037) uses different character codes for
+    square brackets.  In such cases, you can use the ICONV utility
+    (supplied with IBM C) to translate between your EBCDIC character set
+    and IBM-1047.
+
+    If your installation does not use IBM-1047 EBCDIC, messages from
+    UNZIP may look a little odd.  For example, in a US EBCDIC
+    installation, an opening square bracket will become an i-acute and a
+    closing square bracket will become a u-grave.
+
+    The supplied ZIP and UNZIP EXECs attempt to correct this by setting
+    CMS INPUT and OUTPUT translations to adjust the display of left and
+    right brackets.  You may need to change this if brackets don't
+    display correctly on your system.
+
+
+ 7. You can unzip using VM/CMS PIPELINES so unzip can be used as
+    a pipeline filter.  Example:
+       'PIPE COMMAND UNZIP -p test.zip george.test | Count Lines | Cons'
+
+
+
+
+Please report all bugs and problems to:
+   Zip-Bugs@lists.wku.edu
+
+
+-----------------------------------------------------------------------
+Original CMS/MVS port by George Petrov.
+e-mail:  c888090@nlevdpsb.snads.philips.nl
+tel:     +31-40-781155
+
+Philips C&P
+Eindhoven
+The Netherlands
+
+-----------------------------------------------------------------------
+Additional fixes and README re-write (4/98) by Greg Hartwig.
+e-mail:  ghartwig@ix.netcom.com
+         ghartwig@vnet.ibm.com
+
+-----------------------------------------------------------------------
+Additional notes from Ian E. Gorman.
+e-mail:  ian@iosphere.net
+
diff --git a/cmsmvs/README.MVS b/cmsmvs/README.MVS
new file mode 100644 (file)
index 0000000..4d451db
--- /dev/null
@@ -0,0 +1,92 @@
+Thank you for trying this first port of ZIP for VM/CMS and MVS!
+
+
+                        Using under MVS:
+                    ---------------------------
+
+1. To use the Info-ZIP's ZIP under MVS you need:
+
+   - C/370 ver 2.1 compiler or another compatible compiler supporting
+     long names for function/variable names.
+
+2. To compile the program under MVS do :
+
+   - unzip all the files from zip22.zip file. They are stored as
+     ASCII format so you have to unzip them first on PC or other
+     system that already have UNZIP, and then upload them to the
+     mainframe with ASCII to EBCDIC conversion.
+
+   - Copy all the .C files in the PDS called youruserid.ZIP.C
+
+   - Copy all the .H files in the PDS called youruserid.ZIP.H
+
+   - adjust the job ZIPMVSC.JOB to work on your size. Change my
+     userid - C888090 to yours
+
+   - execute the job ZIPMVSC to compile and link all the sources.
+
+   - maybe you have to preallocate PDS datasets named:
+     youruserid.ZIP.OBJ and youruserid.ZIP.LOAD
+
+   - execute ZIPVMC to compile and link all the sources.
+
+   - if everything is ok you will get an ZIP MODULE
+
+   - the warnings about the duplicated ASCII and EBCDIC symbols
+     are OK :-)
+
+3. Using ZIP
+
+   - Just read MANUAL
+
+   - A few exceptions concerning MVS
+
+     3.1. if you want to make a portable zip file that is to be unzipped
+          on ASCII based systems use the -a option
+
+     3.2. If you want to zip the input files as binary ebcdic files
+          use the -B (capital letter) option
+
+     3.3. The date/end the time of the input files is set in the zip's
+          dir to the current system date/time
+
+     3.4. Without specifying the "-a" or "-B" option, the ZIP program
+          defaults to "native" (EBCDIC) mode and tries to preserve the
+          file information (LRECL,BLKSIZE..)
+          So when you UNZIP a file zipped with ZIP under VM/MVS it
+          restores the file info.
+
+          There currently some problems with file with RECFM=V*
+          I don't save the length of each record yet :-)
+
+     3.5. No wildcards are supported as input file names:
+
+          So you CAN'T use things like: zip myzip *.c
+
+     3.6. You can use DD names for zipfilename for example:
+
+          under tso/rexx:
+
+           "alloc fi(input) da('myzip.zip')"
+           "zip dd:input file1.txt file2.txt ..."
+
+          under Batch:
+
+           //MYZIP    JOB  (account)
+           //STEP1    EXEC PGM=ZIP,PARM='dd:input file1.txt file2.txt'
+           //STEPLIB  DD DSN=userid.UNZIP.LOAD,DISP=SHR
+           //INPUT    DD DSN=userid.MYZIP.ZIP,DISP=NEW,
+           //            SPACE=(15000,(15000,10000),RLSE),
+           //            DCB=(LRECL=80,RECFM=F)
+           //SYSPRINT DD SYSOUT=*
+
+
+Please report all bugs and problems to :
+     zip-bugs@lists.wku.edu
+
+That's all for now.
+
+Have fun!
+
+
+George Petrov
diff --git a/cmsmvs/README.MVS.LE b/cmsmvs/README.MVS.LE
new file mode 100644 (file)
index 0000000..f7dcb8a
--- /dev/null
@@ -0,0 +1,286 @@
+Notes on Zip under MVS Language Environment (LE).
+
+First see README.MVS.  This note describes just one beta test on OS/390
+V2R5 using IBM's C compiler (5647A01), V2R4.  The major difference is
+the use of LE on the beta site, together with some MVS native mode
+fixes.  Changes have not been tested on CMS.
+
+Some of the notes are to clarify things that were not clear from the
+MANUAL or README.MVS.
+
+1.  By default, IBM C generates the same csect name for each input
+    source.  The prelink stage does not rename them and the linkage
+    editor throws away all but the first occurrence of each duplicate.
+    Oops, my code just disappeared :(.
+
+    To get around this "feature", compile with the CSECT option to
+    force sensible names on the code and data sections of each csect.
+    The name of the static data csect defaults to the source name in
+    lower case, the code csect defaults to the source name in upper
+    case.  These csect names still have to be unique, they cannot be
+    the same as function names.  Of course, several csects have a
+    function which is the same name as the source in lower case, not
+    exactly an unusual occurrence.  Therefore to make the csect name
+    unique, some of the sources have
+
+    #ifdef MVS
+    #  pragma csect(STATIC,xxxx_s)
+    #endif
+
+    Where xxxx is an abbreviation of the source name.  There has to be
+    a better way!
+
+2.  The prelink step always gets cond code 4.  It complains about
+    unresolved references, ignore it unless the linker also complains.
+    Prelink also complains about duplicate @@PPA2 sections and so does
+    the linker, but it seems to do no harm.  Compile and link steps
+    should get 0, just prelink gets 4.  See JCL at the bottom.
+
+3.  Under MVS native mode (not Open Edition), tmpnam() returns a quoted
+    name of 5 qualifiers.  The first is a HLQ chosen according to the
+    MVS LE algorithm (see below), the other qualifiers are time stamps.
+    If running on MVS and tmpnam() returns a quoted name with at leat
+    one '.', it is only safe to let the user change the high level
+    qualifier.  Therefore -b insists on a single qualifier without '.'
+    in the MVS native environment.
+
+4.  In Open Edition (OE) mode, the manual says that tmpnam() returns a
+    fully qualified name in directory TMPDIR or /tmp if TMPDIR is not
+    set.  There is no point in zip trying to override that name so -b
+    is ignored in MVS OE mode (untested).  The user should specify
+    environment variable TMPDIR instead.
+
+5.  The MVS LE algorithm for choosing the high level qualifier for
+    native filenames is interesting, as in "May you live in interesting
+    times".  The HLQ varies according to the environment the program is
+    running in, sometimes it is userid, sometimes it is TSO prefix.
+    See OS/390 C/C++ Programming Guide, Using a Data Set Name,
+    somewhere around section 2.9.
+
+    If in doubt, use fully qualified and quoted names.  Instead of
+    archive.zip, use 'prefix.archive.zip'.  For input files, instead of
+    filename, use 'prefix.filename'.  For PARM= in JCL, double up the
+    quotes.  You even have to quote filenames in stdin.
+
+6.  If your PARM includes any '/', make sure the PARM starts with '/'.
+    LE assumes anything before the first '/' is LE run time parameters.
+    It does no harm to always code a leading '/' for LE parms.
+
+7.  JCL limits a PARM= to 100 characters total with approx. 65 on a
+    single line.  Alas the syntax for continuing PARM= always embeds an
+    extra ',' somewhere in the parameters that the program finally
+    gets.  No workaround, limit your PARM to a single line.  With the
+    extra quotes around filenames, that does not leave much room.  In
+    most cases, you will have to use '-@' to read the list of filenames
+    from SYSIN (stdin), it will not fit on a single PARM line.
+
+8.  Filenames can be dataset names or you can refer to a ddname with
+    'DD:name', case insensitive for external files, case sensitive for
+    OE files.  You can even specify 'dd:name(mem)'.  No wildcards, to
+    zip a complete pds you have to specify each member individually.
+    Directory recursion in OE does not appear to work at the moment.
+
+9.  Zip attempts to map MVS filenames to Unix style names.  It did not
+    work correctly for quoted names, fixed.  Although you can pick up
+    an external (non-OE) file with a name using any case, be aware that
+    the mapping to a Unix style name faithfully follows the case you
+    supply.
+
+10. The archive file was being created with recfm=V and lrecl=32760.
+    32760 is not valid for recfm=V under MVS, I originally changed it
+    to lrecl=32756.  Then zip broke trying to fseek() over a record
+    boundary, I do not know whether this was a zip or LE bug.  Trial
+    and error showed that recfm=U with byteseek seems to work on MVS.
+    No BDW or RDW, just a byte stream.  The blocksize is always 6144.
+
+    NOTE: This is an incompatible change from the previous beta,
+          archive files used to be recfm=V.  That should not matter
+          because we just transfer the data, ignoring BDW and RDW
+          anyway.
+
+11. Zip used to complain about preallocated but empty archives, wrong
+    length records, no signature etc.  The usual IBM/360 problem of no
+    end of file marker in a new, unopened dataset.  Fixed, see routine
+    readzipfile in zipfile.c for the gory details.  PARM= works fine.
+
+12. Several source files have records that are more than 80 bytes long.
+    It works if you transfer to mainframe datasets with a larger lrecl,
+    I used recfm=fb,lrecl=120 for the .C and .H files.  To compile with
+    anything longer than 72 bytes, you need MVS C options NOMARGINS and
+    NOSEQUENCE (NOMAR,NOSEQ).
+
+13. cmsmvs was still using zname instead of name for open.  Fixed.
+
+14. zip has to jump through a lot of hoops to see if an existing
+    zipfile actually contains data.  A side effect of this is that
+    creating a zipfile with the RLSE parameter is a waste of time.
+
+Keith Owens <kaos@ocs.com.au>.  Not a maintainer, just a beta tester.
+Mon Sep 14 19:31:30 EST 1998
+
+
+Sample JCL to compile Zip under MVS LE.  You might need a large region,
+I used REGION=128M on the job card.  Also watch the output lines,
+75,000 with OPT(2), 100,000+ with OPT(2) replaced with DEF(DEBUG).  You
+need to allocate prefix.ZIP.C.OBJ (recfm=FB, lrecl=80) and
+prefix.ZIP.LOAD (recfm=U, blksize is site defined).
+
+//CBC    JCLLIB ORDER=CBC.SCBCPRC
+//ZIP EXEC EDCC,COND=(0,NE),CREGSIZ='4M',
+//    INFILE='prefix.ZIP.C(ZIP)',
+//    OUTFILE='prefix.ZIP.C.OBJ(ZIP),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',
+//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'
+//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR
+//CRYPT EXEC EDCC,COND=(0,NE),CREGSIZ='4M',
+//    INFILE='prefix.ZIP.C(CRYPT)',
+//    OUTFILE='prefix.ZIP.C.OBJ(CRYPT),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',
+//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'
+//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR
+//TTYIO EXEC EDCC,COND=(0,NE),CREGSIZ='4M',
+//    INFILE='prefix.ZIP.C(TTYIO)',
+//    OUTFILE='prefix.ZIP.C.OBJ(TTYIO),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',
+//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'
+//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR
+//TREES EXEC EDCC,COND=(0,NE),CREGSIZ='4M',
+//    INFILE='prefix.ZIP.C(TREES)',
+//    OUTFILE='prefix.ZIP.C.OBJ(TREES),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',
+//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'
+//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR
+//DEFLATE EXEC EDCC,COND=(0,NE),CREGSIZ='4M',
+//    INFILE='prefix.ZIP.C(DEFLATE)',
+//    OUTFILE='prefix.ZIP.C.OBJ(DEFLATE),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',
+//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'
+//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR
+//FILEIO EXEC EDCC,COND=(0,NE),CREGSIZ='4M',
+//    INFILE='prefix.ZIP.C(FILEIO)',
+//    OUTFILE='prefix.ZIP.C.OBJ(FILEIO),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',
+//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'
+//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR
+//GLOBALS EXEC EDCC,COND=(0,NE),CREGSIZ='4M',
+//    INFILE='prefix.ZIP.C(GLOBALS)',
+//    OUTFILE='prefix.ZIP.C.OBJ(GLOBALS),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',
+//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'
+//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR
+//UTIL EXEC EDCC,COND=(0,NE),CREGSIZ='4M',
+//    INFILE='prefix.ZIP.C(UTIL)',
+//    OUTFILE='prefix.ZIP.C.OBJ(UTIL),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',
+//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'
+//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR
+//CRC32 EXEC EDCC,COND=(0,NE),CREGSIZ='4M',
+//    INFILE='prefix.ZIP.C(CRC32)',
+//    OUTFILE='prefix.ZIP.C.OBJ(CRC32),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',
+//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'
+//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR
+//CRCTAB EXEC EDCC,COND=(0,NE),CREGSIZ='4M',
+//    INFILE='prefix.ZIP.C(CRCTAB)',
+//    OUTFILE='prefix.ZIP.C.OBJ(CRCTAB),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',
+//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'
+//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR
+//ZIPFILE EXEC EDCC,COND=(0,NE),CREGSIZ='4M',
+//    INFILE='prefix.ZIP.C(ZIPFILE)',
+//    OUTFILE='prefix.ZIP.C.OBJ(ZIPFILE),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',
+//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'
+//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR
+//ZIPUP EXEC EDCC,COND=(0,NE),CREGSIZ='4M',
+//    INFILE='prefix.ZIP.C(ZIPUP)',
+//    OUTFILE='prefix.ZIP.C.OBJ(ZIPUP),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',
+//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'
+//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR
+//CMSMVS EXEC EDCC,COND=(0,NE),CREGSIZ='4M',
+//    INFILE='prefix.ZIP.C(CMSMVS)',
+//    OUTFILE='prefix.ZIP.C.OBJ(CMSMVS),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',
+//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'
+//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR
+//MVS EXEC EDCC,COND=(0,NE),CREGSIZ='4M',
+//    INFILE='prefix.ZIP.C(MVS)',
+//    OUTFILE='prefix.ZIP.C.OBJ(MVS),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',
+//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'
+//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR
+//PLINK   EXEC  PROC=EDCPL,
+//    OUTFILE='prefix.ZIP.LOAD(ZIP),DISP=SHR',
+//    PREGSIZ=6M,
+//    PPARM='NONCAL,MAP,MEMORY',
+//    LPARM='LIST,MAP,XREF'
+//PLKED.SYSIN   DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(ZIP)
+//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(CRYPT)
+//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(TREES)
+//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(DEFLATE)
+//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(FILEIO)
+//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(GLOBALS)
+//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(UTIL)
+//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(CRC32)
+//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(CRCTAB)
+//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(ZIPFILE)
+//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(ZIPUP)
+//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(MVS)
+//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(CMSMVS)
+//LKED.SYSLIB   DD  DISP=SHR,DSN=CEE.SCEELKED
+//SYSUT1   DD  UNIT=SYSDA,SPACE=(CYL,(2,2))
+//
+
+Sample JCL to zip the mainframe .C and .H files as ASCII (-a).  Delete
+any existing archive first, point the temporary file at a particular
+prefix (-b), use 'prefix.ARCHIVE.ZIP' for the archive file, read the
+list of files to zip from stdin (SYSIN).
+
+//DELETE  EXEC PGM=IDCAMS
+//SYSPRINT DD  SYSOUT=*
+//SYSIN    DD  *
+ DELETE prefix.ARCHIVE.ZIP
+ SET MAXCC = 0
+//ZIP     EXEC PGM=ZIP,
+// PARM='/-a -v -b temppref ''prefix.ARCHIVE.ZIP'' -@'
+//STEPLIB  DD  DSN=prefix.ZIP.LOAD,DISP=SHR
+//SYSPRINT DD  SYSOUT=*
+//SYSOUT   DD  SYSOUT=*
+//CEEDUMP  DD  SYSOUT=*
+//ZIPC     DD  DISP=SHR,DSN=prefix.ZIP.C
+//ZIPH     DD  DISP=SHR,DSN=prefix.ZIP.H
+//SYSIN    DD  *
+dd:zipc(api)
+dd:zipc(cms)
+dd:zipc(cmsmvs)
+dd:zipc(crctab)
+dd:zipc(crc32)
+dd:zipc(crypt)
+dd:zipc(deflate)
+dd:zipc(fileio)
+dd:zipc(globals)
+dd:zipc(mktime)
+dd:zipc(mvs)
+dd:zipc(trees)
+dd:zipc(ttyio)
+dd:zipc(util)
+dd:zipc(zip)
+dd:zipc(zipcloak)
+dd:zipc(zipfile)
+dd:zipc(zipnote)
+dd:zipc(zipsplit)
+dd:zipc(zipup)
+dd:ziph(api)
+dd:ziph(cmsmvs)
+dd:ziph(crypt)
+dd:ziph(cstat)
+dd:ziph(ebcdic)
+dd:ziph(mvs)
+dd:ziph(revision)
+dd:ziph(stat)
+dd:ziph(tailor)
+dd:ziph(ttyio)
+dd:ziph(zip)
+dd:ziph(ziperr)
+dd:ziph(zipup)
diff --git a/cmsmvs/cczip.exec b/cmsmvs/cczip.exec
new file mode 100644 (file)
index 0000000..afa97d0
--- /dev/null
@@ -0,0 +1,124 @@
+/* CCZIP    EXEC   Compile zip for VM/CMS                           */
+/*                 Author: George Petrov, 11 Apr 1995 (VMCOMPIL EXEC) */
+/* Modified for IBM C V3R1 by Ian E. Gorman, 2 Nov 1998
+   Facilities for compiling and testing were provided by
+      OmniMark Technologies Corporation, Ottawa, Canada
+*/
+Address Command
+Signal On Error
+
+/* Allow longnames, compile re-entrant code.
+   globals.c and cmsmvs.c require EXTENDED features */
+CCopts = 'LONGNAME RENT LANGLVL(EXTENDED) NOEXECOPS'
+
+/* ZIP options -- VM_CMS, REENTRANT */
+CCopts = CCopts 'DEFINE(VM_CMS,REENTRANT)'
+
+/* Link the load module to run in more or less than 16MB memory */
+LINKopts = 'AMODE ANY RMODE ANY RLDSAVE'
+
+/* resources needed to build */
+'GLOBAL TXTLIB  SCEELKED CMSLIB'
+'GLOBAL LOADLIB SCEERUN'
+
+/* produce the TEXT (object) files */
+linklist=''
+modname='ZIP'
+Say 'Building' modname 'MODULE...'
+Call Compile 'ZIP'
+Call Compile 'CRCTAB'
+Call Compile 'CRC32'
+Call Compile 'CRYPT'
+Call Compile 'DEFLATE'
+Call Compile 'FILEIO'
+Call Compile 'GLOBALS'
+Call Compile 'TREES'
+Call Compile 'TTYIO'
+Call Compile 'UTIL'
+Call Compile 'ZIPUP'
+Call Compile 'ZIPFILE'
+Call Compile 'CMSMVS'
+Call Compile 'CMS'
+
+Say 'Linking...'
+'EXEC CMOD' linklist '(MODNAME' modname LINKopts
+Say modname 'built successfully.'
+
+
+/*---------------------------------------------------------------------*/
+/* Build utility programs                                              */
+/*---------------------------------------------------------------------*/
+CCopts = CCopts 'DEFINE(UTIL)'
+
+
+linklist=''
+modname='ZIPNOTE'
+Say
+Say 'Building' modname 'MODULE...'
+Call Compile 'ZIPNOTE'
+Call Compile 'ZIPFILE'
+Call Compile 'FILEIO'
+Call Compile 'UTIL'
+Call Compile 'GLOBALS'
+Call Compile 'CMSMVS'
+
+Say 'Linking...'
+'EXEC CMOD' linklist '(MODNAME' modname LINKopts
+Say modname 'built successfully.'
+
+
+linklist=''
+modname='ZIPSPLIT'
+Say
+Say 'Building' modname 'MODULE...'
+Call Compile 'ZIPSPLIT'
+Call Compile 'ZIPFILE'
+Call Compile 'FILEIO'
+Call Compile 'UTIL'
+Call Compile 'GLOBALS'
+Call Compile 'CMSMVS'
+
+Say 'Linking...'
+'EXEC CMOD' linklist '(MODNAME' modname LINKopts
+Say modname 'built successfully.'
+
+
+linklist=''
+modname='ZIPCLOAK'
+Say
+Say 'Building' modname 'MODULE...'
+Call Compile 'ZIPCLOAK'
+Call Compile 'ZIPFILE'
+Call Compile 'FILEIO'
+Call Compile 'UTIL'
+Call Compile 'GLOBALS'
+Call Compile 'CRCTAB'
+Call Compile 'CRYPT'
+Call Compile 'TTYIO'
+Call Compile 'CMSMVS'
+
+Say 'Linking...'
+'EXEC CMOD' linklist '(MODNAME' modname LINKopts
+Say modname 'built successfully.'
+Say 'Done.'
+
+Exit rc
+
+
+
+error:
+    Say 'Error' rc 'during compilation!'
+    Say 'Error in line' sigl':'
+    Say '   'Sourceline(sigl)
+    Exit rc
+
+
+
+Compile:  Procedure Expose CCopts LINKopts linklist
+    Parse arg filename filetype filemode .
+    If filetype='' Then filetype='C'
+    linklist = linklist filename
+
+    Say 'Compiling' filename filetype filemode '...'
+    'EXEC CC' filename filetype filemode '('CCopts
+    Return rc
diff --git a/cmsmvs/cms.c b/cmsmvs/cms.c
new file mode 100644 (file)
index 0000000..e8dfa34
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ * VM/CMS specific things.
+ */
+
+#include "zip.h"
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  FILE *stream;
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else {
+     if ((stream = fopen(n, "r")) != (FILE *)NULL)
+        {
+        fclose(stream);
+        return newname(n, 0, caseflag);
+        }
+     else return ZE_MISS;
+  }
+  return ZE_OK;
+}
diff --git a/cmsmvs/cmsmvs.c b/cmsmvs/cmsmvs.c
new file mode 100644 (file)
index 0000000..5297908
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ * routines common to VM/CMS and MVS
+ */
+
+#include "zip.h"
+
+#include <stdio.h>
+#include <time.h>
+#include <errno.h>
+
+#ifndef MVS  /* MVS has perfectly good definitions of the following */
+int stat(const char *path, struct stat *buf)
+{
+   if ((buf->fp = fopen(path, "r")) != NULL) {
+      fldata_t fdata;
+      if (fldata( buf->fp, buf->fname, &fdata ) == 0) {
+         buf->st_dev  = fdata.__device;
+         buf->st_mode = *(short *)(&fdata);
+      }
+      strcpy( buf->fname, path );
+      fclose(buf->fp);
+   }
+   return (buf->fp != NULL ? 0 : 1);
+}
+#endif /* MVS */
+
+
+#ifndef UTIL    /* the companion #endif is a bit of ways down ... */
+
+#define PAD 0
+#define PATH_END '/'
+
+/* Library functions not in (most) header files */
+
+#ifdef USE_ZIPMAIN
+int main OF((void));
+#endif
+
+int utime OF((char *, ztimbuf *));
+
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+#ifndef MVS  /* MVS has perfectly good definitions of the following */
+int fstat(int fd, struct stat *buf)
+{
+   fldata_t fdata;
+
+   if ((fd != -1) && (fldata( (FILE *)fd, buf->fname, &fdata ) == 0)) {
+      buf->st_dev  = fdata.__device;
+      buf->st_mode = *(short *)(&fdata);
+      buf->fp      = (FILE *)fd;
+      return 0;
+   }
+   return -1;
+}
+#endif /* MVS */
+
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t;              /* shortened name */
+  int dosflag;
+  char mem[10] = "";    /* member name */
+  char ext[10] = "";     /* extension name */
+
+  dosflag = dosify;  /* default for non-DOS non-OS/2 */
+
+  /* Find starting point in name before doing malloc */
+  for (t = x; *t == '/'; t++)
+    ;
+
+  /* Make changes, if any, to the copied name (leave original intact) */
+  if (!pathput)
+    t = last(t, PATH_END);
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL)
+    return NULL;
+  strcpy(n, t);
+
+#ifdef MVS
+  /* strip quotes from name, non-OE format */
+  if (*n == '\'' && (t = strrchr(n, '\'')) != n) {
+    if (!*(t+1)) {
+      /* yes, it is a quoted name */
+      int l = strlen(n) - 2;
+      memmove(n, n+1, l);
+      *(n+l) = '\0';
+    }
+  }
+  /* Change member names to fn.ext */
+  if (t = strrchr(n, '(')) {
+     *t = '\0';
+     strcpy(mem,t+1);        /* Save member name */
+     if (t = strchr(mem, ')')) *t = '\0';         /* Set end of mbr */
+     /* Save extension */
+     if (t = strrchr(n, '.')) t++;
+     else t = n;
+     strcpy(ext,t);
+     /* Build name as "member.ext" */
+     strcpy(t,mem);
+     strcat(t,".");
+     strcat(t,ext);
+  }
+
+  /* Change all but the last '.' to '/' */
+  if (t = strrchr(n, '.')) {
+     while (--t > n)
+        if (*t == '.')
+          *t = '/';
+  }
+#else
+  /* On CMS, remove the filemode (all past 2nd '.') */
+  if (t = strchr(n, '.'))
+     if (t = strchr(t+1, '.'))
+        *t = '\0';
+  t = n;
+#endif
+
+  strcpy(n, t);
+
+  if (isdir == 42) return n;    /* avoid warning on unused variable */
+
+  if (dosify)
+    msname(n);                  /* msname() needs string in native charset */
+
+  strtoasc(n, n);
+
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+  return n;
+}
+
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+
+  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+    return NULL;
+  strtoebc(x, n);
+  return x;
+}
+
+
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+  ztimbuf u;            /* argument for utime() */
+
+  /* Convert DOS time to time_t format in u.actime and u.modtime */
+  u.actime = u.modtime = dos2unixtime(d);
+
+  utime(f, &u);
+}
+
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+{
+  FILE *stream;
+  time_t ltime;
+
+  if (strcmp(f, "-") != 0) {    /* if not compressing stdin */
+     Trace((mesg, "opening file '%s' with '%s'\n", f, FOPR));
+     if ((stream = fopen(f, FOPR)) == (FILE *)NULL) {
+        return 0;
+     } else {
+        if (n != NULL) {
+           /* With byteseek, this will work */
+           fseek(stream, 0L, SEEK_END);
+           *n = ftell(stream);
+           Trace((mesg, "file size = %lu\n", *((ulg *)n)));
+        }
+        fclose(stream);
+     }
+  }
+  else {
+     /* Reading from stdin */
+     if (n != NULL) {
+        *n = -1L;
+     }
+  }
+
+  /* Return current time for all the times -- for now */
+  time(&ltime);
+  if (t != NULL)
+     t->atime = t->mtime = t->ctime = ltime;
+
+  /* Set attributes (always a file) */
+  if (a != NULL)
+     *a = 0;
+
+  return unix2dostime(&ltime);
+}
+
+
+
+int set_extra_field(z, z_utim)
+struct zlist far *z;
+iztimes *z_utim;
+/* create extra field and change z->att if desired */
+{
+   fldata_t fdata;
+   FILE *stream;
+   char *eb_ptr;
+#ifdef USE_EF_UT_TIME
+   extent ef_l_len = (EB_HEADSIZE+EB_UT_LEN(1));
+#else /* !USE_EF_UT_TIME */
+   extent ef_l_len = 0;
+#endif /* ?USE_EF_UT_TIME */
+   int set_cmsmvs_eb = 0;
+
+/*translate_eol = 0;*/
+  if (aflag == ASCII) {
+     z->att = ASCII;
+  } else {
+    if (bflag)
+      z->att = BINARY;
+    else
+      z->att = __EBCDIC;
+    ef_l_len += sizeof(fdata)+EB_HEADSIZE;
+    set_cmsmvs_eb = 1;
+  }
+
+  if (ef_l_len > 0) {
+    z->extra = (char *)malloc(ef_l_len);
+    if (z->extra == NULL) {
+       printf("\nFLDATA : Unable to allocate memory !\n");
+       return ZE_MEM;
+    }
+    z->cext = z->ext = ef_l_len;
+    eb_ptr = z->cextra = z->extra;
+
+    if (set_cmsmvs_eb) {
+      if (bflag)
+/***    stream = fopen(z->zname,"rb,type=record");   $RGH$ ***/
+        stream = fopen(z->name,"rb");
+      else
+        stream = fopen(z->name,"r");
+      if (stream == NULL) {
+        printf("\nFLDATA : Could not open file : %s !\n",z->name);
+        printf("Error %d: '%s'\n", errno, strerror(errno));
+        return ZE_NONE;
+      }
+
+      fldata(stream,z->name,&fdata);
+      /*put the system ID */
+#ifdef VM_CMS
+      *(eb_ptr) = EF_VMCMS & 0xFF;
+      *(eb_ptr+1) = EF_VMCMS >> 8;
+#else
+      *(eb_ptr) = EF_MVS & 0xFF;
+      *(eb_ptr+1) = EF_MVS >> 8;
+#endif
+      *(eb_ptr+2) = sizeof(fdata) & 0xFF;
+      *(eb_ptr+3) = sizeof(fdata) >> 8;
+
+      memcpy(eb_ptr+EB_HEADSIZE,&fdata,sizeof(fdata));
+      fclose(stream);
+#ifdef USE_EF_UT_TIME
+      eb_ptr += (sizeof(fdata)+EB_HEADSIZE);
+#endif /* USE_EF_UT_TIME */
+    }
+#ifdef USE_EF_UT_TIME
+    eb_ptr[0]  = 0x55;                  /* ascii[(unsigned)('U')] */
+    eb_ptr[1]  = 0x54;                  /* ascii[(unsigned)('T')] */
+    eb_ptr[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */
+    eb_ptr[3]  = 0;
+    eb_ptr[4]  = EB_UT_FL_MTIME;
+    eb_ptr[5]  = (char)(z_utim->mtime);
+    eb_ptr[6]  = (char)(z_utim->mtime >> 8);
+    eb_ptr[7]  = (char)(z_utim->mtime >> 16);
+    eb_ptr[8]  = (char)(z_utim->mtime >> 24);
+#endif /* USE_EF_UT_TIME */
+  }
+
+  return ZE_OK;
+}
+
+int deletedir(d)
+char *d;                /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+   Return the result of rmdir(), delete(), or system().
+   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).
+ */
+{
+    return 0;
+}
+
+#ifdef USE_ZIPMAIN
+/* This function is called as main() to parse arguments                */
+/* into argc and argv.  This is required for stand-alone               */
+/* execution.  This calls the "real" main() when done.                 */
+
+int main(void)
+   {
+    int  argc=0;
+    char *argv[50];
+
+    int  iArgLen;
+    char argstr[256];
+    char **pEPLIST, *pCmdStart, *pArgStart, *pArgEnd;
+
+   /* Get address of extended parameter list from S/370 Register 0 */
+   pEPLIST = (char **)__xregs(0);
+
+   /* Null-terminate the argument string */
+   pCmdStart = *(pEPLIST+0);
+   pArgStart = *(pEPLIST+1);
+   pArgEnd   = *(pEPLIST+2);
+   iArgLen   = pArgEnd - pCmdStart + 1;
+
+   /* Make a copy of the command string */
+   memcpy(argstr, pCmdStart, iArgLen);
+   argstr[iArgLen] = '\0';  /* Null-terminate */
+
+   /* Store first token (cmd) */
+   argv[argc++] = strtok(argstr, " ");
+
+   /* Store the rest (args) */
+   while (argv[argc-1])
+      argv[argc++] = strtok(NULL, " ");
+   argc--;  /* Back off last NULL entry */
+
+   /* Call "real" main() function */
+   return zipmain(argc, argv);
+
+}
+#endif /* USE_ZIPMAIN */
+
+#endif /* !UTIL */
+
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+void version_local()
+{
+    char liblvlmsg [50+1];
+    char *compiler = "?";
+    char *platform = "?";
+    char complevel[64];
+
+    /* Map the runtime library level information */
+    union {
+       unsigned int iVRM;
+       struct {
+          unsigned int pd:4;    /* Product designation */
+          unsigned int vv:4;    /* Version             */
+          unsigned int rr:8;    /* Release             */
+          unsigned int mm:16;   /* Modification level  */
+       } xVRM;
+    } VRM;
+
+
+    /* Break down the runtime library level */
+    VRM.iVRM = __librel();
+    sprintf(liblvlmsg, "Using runtime library level %s V%dR%dM%d",
+            (VRM.xVRM.pd==1 ? "LE" : "CE"),
+            VRM.xVRM.vv, VRM.xVRM.rr, VRM.xVRM.mm);
+    /* Note:  LE = Language Environment, CE = Common Env. (C/370). */
+    /* This refers ONLY to the current runtimes, not the compiler. */
+
+
+#ifdef VM_CMS
+    platform = "VM/CMS";
+    #ifdef __IBMC__
+       compiler = "IBM C";
+    #else
+       compiler  = "C/370";
+    #endif
+#endif
+
+#ifdef MVS
+    platform = "MVS";
+    #ifdef __IBMC__
+       compiler = "IBM C/C++";
+    #else
+       compiler = "C/370";
+    #endif
+#endif
+
+#ifdef __COMPILER_VER__
+    VRM.iVRM = __COMPILER_VER__;
+    sprintf(complevel," V%dR%dM%d",
+            VRM.xVRM.vv, VRM.xVRM.rr, VRM.xVRM.mm);
+#else
+#ifdef __IBMC__
+    sprintf(complevel," V%dR%d", __IBMC__ / 100, (__IBMC__ % 100)/10);
+#else
+    complevel[0] = '\0';
+#endif
+#endif
+
+
+    printf("Compiled with %s%s for %s%s%s.\n\n",
+
+    /* Add compiler name and level */
+    compiler, complevel,
+
+    /* Add platform */
+    platform,
+
+    /* Add timestamp */
+#ifdef __DATE__
+      " on " __DATE__
+#ifdef __TIME__
+      " at " __TIME__
+#endif
+#endif
+      ".\n",
+      liblvlmsg
+    );
+} /* end function version_local() */
diff --git a/cmsmvs/cmsmvs.h b/cmsmvs/cmsmvs.h
new file mode 100644 (file)
index 0000000..8fca61b
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/* Include file for VM/CMS and MVS */
+
+/* This is normally named osdep.h on most systems.  Since CMS       */
+/* generally doesn't support directories, it's been given a unique  */
+/* name to avoid confusion.                                         */
+
+
+#ifndef __cmsmvs_h   /* prevent multiple inclusions */
+#define __cmsmvs_h
+
+#ifdef MVS
+#  define _POSIX_SOURCE    /* tell MVS we want full definitions */
+#  include <features.h>
+#endif /* MVS */
+
+#include <time.h>               /* the usual non-BSD time functions */
+/* cstat.h is not required for MVS and actually gets in the way.  Is it
+ * needed for CMS?
+ */
+#ifdef MVS
+#  include <sys/stat.h>
+#  include <sys/modes.h>
+#else /* !MVS */
+#  include "cstat.h"
+#endif
+
+
+/* Newer compiler version defines something for us */
+#if defined(__VM__) && !defined(VM_CMS)
+#  define VM_CMS
+#endif
+
+#define CMS_MVS
+#define EBCDIC
+
+#ifndef MVS  /* MVS has perfectly good definitions for the following */
+#  define NO_UNISTD_H
+#  define NO_FCNTL_H
+#endif /*MVS */
+
+/* If we're generating a stand-alone CMS module, patch in        */
+/* a new main() function before the real main() for arg parsing. */
+#ifdef CMS_STAND_ALONE
+#  define USE_ZIPMAIN
+#endif
+
+#ifndef NULL
+#  define NULL 0
+#endif
+
+#define PASSWD_FROM_STDIN
+                  /* Kludge until we know how to open a non-echo tty channel */
+
+/* definition for ZIP */
+#define getch() getc(stdin)
+#define native(c)   ebcdic[(c)]
+#define MAXPATHLEN 128
+#define NO_RMDIR
+#define NO_MKTEMP
+#define USE_CASE_MAP
+#ifndef MVS  /* MVS has perfectly good definitions for the following */
+#  define fileno(x) (char *)(x)
+#  define fdopen fopen
+#  define unlink remove
+#  define link rename
+#  define utime(f,t)
+#  define isatty(t) 1
+#endif /*MVS */
+#ifdef ZCRYPT_INTERNAL
+#  define ZCR_SEED2     (unsigned)3141592654L   /* use PI as seed pattern */
+#endif
+
+#ifdef MVS
+#  if defined(__CRC32_C)
+#    pragma csect(STATIC,"crc32_s")
+#  elif defined(__DEFLATE_C)
+#    pragma csect(STATIC,"deflat_s")
+#  elif defined(__ZIPFILE_C)
+#    pragma csect(STATIC,"zipfil_s")
+#  elif defined(__ZIPUP_C)
+#    pragma csect(STATIC,"zipup_s")
+#  endif
+#endif /* MVS */
+
+/* end defines for ZIP */
+
+
+
+/* definitions for UNZIP */
+#ifdef UNZIP
+#define INBUFSIZ 8192
+
+#define USE_STRM_INPUT
+#define USE_FWRITE
+
+#define PATH_MAX 128
+#endif /* UNZIP */
+
+
+#if 0  /*$RGH$*/
+/* RECFM=F, LRECL=1 works for sure */
+#define FOPR "rb,recfm=fb"
+#define FOPM "r+"
+#define FOPW "wb,recfm=fb,lrecl=1"
+#define FOPWT "w"
+#endif
+
+/* Try allowing ZIP files to be RECFM=V with "byteseek" for CMS, recfm=U for MVS */
+#define FOPR "rb,byteseek"
+#define FOPM "r+,byteseek"
+#ifdef MVS
+  #define FOPW "wb,recfm=u,byteseek"
+#else /* !MVS */
+  #define FOPW "wb,recfm=v,lrecl=32760,byteseek"
+#endif /* MVS */
+
+#if 0
+#define FOPW_TMP "w,byteseek"
+#else
+#define FOPW_TMP "w,type=memory(hiperspace)"
+#endif
+
+#define CBSZ 0x40000
+#define ZBSZ 0x40000
+
+#endif /* !__cmsmvs_h */
diff --git a/cmsmvs/cstat.h b/cmsmvs/cstat.h
new file mode 100644 (file)
index 0000000..f02a5c3
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/*  cstat.h
+
+    Definitions used for file status functions
+
+*/
+
+#ifndef __STAT_H
+#define __STAT_H
+
+#include <stdio.h>
+
+#define S_IFMT  0xF000  /* file type mask */
+#define S_IFDIR 0x4000  /* directory */
+#define S_IFIFO 0x1000  /* FIFO special */
+#define S_IFCHR 0x2000  /* character special */
+#define S_IFBLK 0x3000  /* block special */
+#define S_IFREG 0x8000  /* or just 0x0000, regular */
+#define S_IREAD 0x0100  /* owner may read */
+#define S_IWRITE 0x0080 /* owner may write */
+#define S_IEXEC 0x0040  /* owner may execute <directory search> */
+
+struct  stat
+{
+    short st_dev;      /* Drive number of disk containing the  */
+                       /* file or file handle if the file is   */
+                       /* on device                            */
+    short st_ino;      /* Not meaningfull for VM/CMS           */
+    short st_mode;     /* Bit mask giving information about    */
+                       /* the file's mode                      */
+    short st_nlink;    /* Set to the integer constant 1        */
+    int   st_uid;      /* Not meaningfull for VM/CMS           */
+    int   st_gid;      /* Not meaningfull for VM/CMS           */
+    short st_rdev;     /* Same as st_dev                       */
+    long  st_size;     /* Size of the file in bytes            */
+    long  st_atime;    /* Most recent access                   */
+    long  st_mtime;    /* Same as st_atime                     */
+    long  st_ctime;    /* Same as st_atime                     */
+    FILE  *fp;
+    char  fname[FILENAME_MAX];
+};
+
+int stat(const char *path, struct stat *sb);
+int fstat(int fd, struct stat *sb);
+
+#endif  /* __STAT_H */
diff --git a/cmsmvs/mc.exec b/cmsmvs/mc.exec
new file mode 100644 (file)
index 0000000..ca22a18
--- /dev/null
@@ -0,0 +1,95 @@
+/* MAKECPIP EXEC      Make program to build a C/370 module           */
+/*                    Author: George Petrov, 29 Sep 1994             */
+
+arg fn . '(' cparms                   /* Filter name                 */
+'pipe (end ?) < 'fn' makefile',       /* get all source files from   */
+    '| frlab GLOBALS:'||,
+    '| drop',
+    '| strip',
+    '| var globals'
+cparms = cparms globals
+say ''
+say 'Compile options : 'cparms
+say ''
+if pos('REB',cparms) > 0 then do
+parse var cparms cp1 'REB' . ' ' cp2  /* REBuild options specified ? */
+cparms = cp1||cp2
+pipe1=,
+'pipe (end ?) < 'fn' makefile',       /* get all source files from   */
+    '| nfind *'||,                    /* the makefile and compile    */
+    '| frlab TEXT:'||,                /* only the those who are      */
+    '| r: tolab MODULE:'||,           /* changed or never compiled   */
+    '| drop',
+    '| o: fanout',
+    '| chop before str /(/',
+    '| statew',
+    '| c: fanout',                    /* compiled                    */
+    '| specs /Compiling / 1 w1-3 n / .../ n',
+    '| cons'
+end
+else do
+pipe1=,
+'pipe (end ?) < 'fn' makefile',       /* get all source files from   */
+    '| nfind *'||,                    /* the makefile and compile    */
+    '| frlab TEXT:'||,                /* only the those who are      */
+    '| r: tolab MODULE:'||,           /* changed or never compiled   */
+    '| drop',
+    '| o: fanout',
+    '| specs w1 1 /C/ nw w3 nw write w1 1 /TEXT A/ nw',
+    '| chop before str /(/',
+    '| statew',
+    '| change (57 66) / /0/',
+    '| sort 1.8 d',                  /* sort the date and time      */
+    '| uniq 1-17 singles',           /* if the first is a source    */
+    '| sort 1.8 d 64.2 d 57.2 d 60.2 d 66.8 d',    /* sort the date */
+    '| uniq 1-8 first',          /*    if the first is a source    */
+    '| locate 9.8 /C      /',         /* program then it has to be   */
+    '| c: fanout',                    /* compiled                    */
+    '| specs /Compiling / 1 w1-3 n / .../ n',
+    '| cons'
+end
+pipe2= '?',
+    'r:',
+    '| drop',
+    '| specs w1 1',                 /* save the module name in var  */
+    '| var module',
+    '?',
+    'o:',
+    '| specs w1 1',
+    '| join * / /',
+    '| var texts',                  /* save all the text file names */
+    '?',                            /* for later include            */
+    'c:',
+    '| specs /CC / 1 w1-3 n /(NOTERM 'cparms'/ nw',   /* compile! */
+    '| err: cms | cons',
+    '?',
+    'err:',
+    '| strip both',
+    '| nfind 0'||,
+    '| var err',
+    '| specs /----> Errors found! RC=/ 1 1-* n',
+    '| cons'
+/*  '| g: gate'*/
+pipe1 pipe2
+say ''
+if symbol('err') = 'VAR' & err ^= 0 then do
+      say 'Errors found in source files - link aborted! RC = 'err
+      exit err
+end
+say 'Generating module 'module
+'pipe cms cmod' fn texts' DMSCSL | > 'fn' LINK A'
+'set cmstype ht'
+'state 'fn' LINK A'
+rcc = rc
+'set cmstype rt'
+if rcc = 0 then do
+   say ''
+   say 'ERRORS discovered during linking!'
+   say 'See: 'fn' LINK A for more info'
+end
+exit rc
+error:
+say 'Error in REXX detected!'
+Say 'Syntax error on line' Sigl':' Sourceline(Sigl)
+Say 'Error was:' Errortext(RC)
+return rc
diff --git a/cmsmvs/mvs.c b/cmsmvs/mvs.c
new file mode 100644 (file)
index 0000000..fabc4f0
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ * MVS specific things
+ */
+#include "zip.h"
+#include "mvs.h"
+#include <errno.h>
+
+static int gen_node( DIR *dirp, RECORD *recptr )
+{
+   char *ptr, *name, ttr[TTRLEN];
+   int skip, count = 2;
+   unsigned int info_byte, alias, ttrn;
+   struct dirent *new;
+
+   ptr = recptr->rest;
+   while (count < recptr->count) {
+      if (!memcmp( ptr, endmark, NAMELEN ))
+         return 1;
+      name = ptr;                    /* member name */
+      ptr += NAMELEN;
+      memcpy( ttr, ptr, TTRLEN );    /* ttr name    */
+      ptr += TTRLEN;
+      info_byte = (unsigned int) (*ptr);   /* info byte */
+      if ( !(info_byte & ALIAS_MASK) ) {   /* no alias  */
+         new = malloc( sizeof(struct dirent) );
+         if (dirp->D_list == NULL)
+            dirp->D_list = dirp->D_curpos = new;
+         else
+            dirp->D_curpos = (dirp->D_curpos->d_next = new);
+         new->d_next = NULL;
+         memcpy( new->d_name, name, NAMELEN );
+         new->d_name[NAMELEN] = '\0';
+         if ((name = strchr( new->d_name, ' ' )) != NULL)
+            *name = '\0';      /* skip trailing blanks */
+      }
+      skip = (info_byte & SKIP_MASK) * 2 + 1;
+      ptr += skip;
+      count += (TTRLEN + NAMELEN + skip);
+   }
+   return 0;
+}
+
+DIR *opendir(const char *dirname)
+{
+   int bytes, list_end = 0;
+   DIR *dirp;
+   FILE *fp;
+   RECORD rec;
+
+   fp = fopen( dirname, "rb" );
+   if (fp != NULL) {
+      dirp = malloc( sizeof(DIR) );
+      if (dirp != NULL) {
+         dirp->D_list = dirp->D_curpos = NULL;
+         strcpy( dirp->D_path, dirname );
+         do {
+            bytes = fread( &rec, 1, sizeof(rec), fp );
+            if (bytes == sizeof(rec))
+               list_end = gen_node( dirp, &rec );
+         } while (!feof(fp) && !list_end);
+         fclose( fp );
+         dirp->D_curpos = dirp->D_list;
+         return dirp;
+      }
+      fclose( fp );
+   }
+   return NULL;
+}
+
+struct dirent *readdir(DIR *dirp)
+{
+   struct dirent *cur;
+
+   cur = dirp->D_curpos;
+   dirp->D_curpos = dirp->D_curpos->d_next;
+   return cur;
+}
+
+void rewinddir(DIR *dirp)
+{
+   dirp->D_curpos = dirp->D_list;
+}
+
+int closedir(DIR *dirp)
+{
+   struct dirent *node;
+
+   while (dirp->D_list != NULL) {
+      node = dirp->D_list;
+      dirp->D_list = dirp->D_list->d_next;
+      free( node );
+   }
+   free( dirp );
+   return 0;
+}
+
+local char *readd(d)
+DIR *d;                 /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+   no more entries or an error occurs. */
+{
+  struct dirent *e;
+
+  e = readdir(d);
+  return e == NULL ? (char *) NULL : e->d_name;
+}
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  char *a;              /* path and name for recursion */
+  DIR *d;               /* directory stream from opendir() */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+  int exists;           /* 1 if file exists */
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (!(exists = (LSSTAT(n, &s) == 0)))
+  {
+#ifdef MVS
+    /* special case for MVS.  stat does not work on non-HFS files so if
+     * stat fails with ENOENT, try to open the file for reading anyway.
+     * If the user has no OMVS segment, stat gets an initialization error,
+     * even on external files.
+     */
+    if (errno == ENOENT || errno == EMVSINITIAL) {
+      FILE *f = fopen(n, "r");
+      if (f) {
+        /* stat got ENOENT but fopen worked, external file */
+        fclose(f);
+        exists = 1;
+        memset(&s, '\0', sizeof(s));   /* stat data is unreliable for externals */
+        s.st_mode = S_IFREG;           /* fudge it */
+      }
+    }
+#endif /* MVS */
+  }
+  if (! exists) {
+    /* Not a file or directory--search for shell expression in zip file */
+    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+  if (!S_ISDIR(s.st_mode))
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  } else {
+    /* Add trailing / to the directory name */
+    if ((p = malloc(strlen(n)+2)) == NULL)
+      return ZE_MEM;
+    if (strcmp(n, ".") == 0) {
+      *p = '\0';  /* avoid "./" prefix and do not create zip entry */
+    } else {
+      strcpy(p, n);
+      a = p + strlen(p);
+      if (a[-1] != '/')
+        strcpy(a, "/");
+      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+        free((zvoid *)p);
+        return m;
+      }
+    }
+    /* recurse into directory */
+    if (recurse && (d = opendir(n)) != NULL)
+    {
+      while ((e = readd(d)) != NULL) {
+        if (strcmp(e, ".") && strcmp(e, ".."))
+        {
+          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+          {
+            closedir(d);
+            free((zvoid *)p);
+            return ZE_MEM;
+          }
+          strcat(strcpy(a, p), e);
+          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
+          {
+            if (m == ZE_MISS)
+              zipwarn("name not matched: ", a);
+            else
+              ziperr(m, a);
+          }
+          free((zvoid *)a);
+        }
+      }
+      closedir(d);
+    }
+    free((zvoid *)p);
+  } /* (s.st_mode & S_IFDIR) == 0) */
+  return ZE_OK;
+}
diff --git a/cmsmvs/mvs.h b/cmsmvs/mvs.h
new file mode 100644 (file)
index 0000000..b2f9760
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/* <dirent.h> definitions */
+
+#define NAMELEN     8
+
+struct dirent {
+   struct dirent *d_next;
+   char   d_name[NAMELEN+1];
+};
+
+typedef struct _DIR {
+   struct  dirent *D_list;
+   struct  dirent *D_curpos;
+   char            D_path[FILENAME_MAX];
+} DIR;
+
+DIR *          opendir(const char *dirname);
+struct dirent *readdir(DIR *dirp);
+void           rewinddir(DIR *dirp);
+int            closedir(DIR *dirp);
+char *         readd(DIR *dirp);
+
+#define ALIAS_MASK  (unsigned int) 0x80
+#define SKIP_MASK   (unsigned int) 0x1F
+#define TTRLEN      3
+#define RECLEN      254
+
+typedef _Packed struct {
+   unsigned short int count;
+   char rest[RECLEN];
+} RECORD;
+
+char    *endmark = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
diff --git a/cmsmvs/mvs.mki b/cmsmvs/mvs.mki
new file mode 100644 (file)
index 0000000..7990902
--- /dev/null
@@ -0,0 +1,128 @@
+# Makefile for the MVS (OS/390 Base) version of ZIP 2.3
+# Produced for C/C++ V3R2 in OS/390 1.2.0 by Ian E. Gorman, 2 Nov 1998
+# Facilities for compiling and testing were made available by
+#     OmniMark Technologies Corporation, Ottawa, Canada
+
+# NOTES
+#
+# The only tabs in this file are in the first character of each recipe
+# line, where they are required by make.
+#
+# Run this makefile in OpenMVS (OS/390 POSIX) using source files in the
+# HFS file system.  You can write the load module to either HFS file
+# system or to a PDS in the native MVS file system.  The PDS must have
+# sufficient free space to hold the load module.
+#
+# To compile to a member of a PDS:
+#   make
+# or
+#   make zip.mvs
+#
+# To compile a test version into the HFS file system:
+#   make hfs
+
+# ZIP options -- MVS, REENTRANT
+ZIPOPTS=-DMVS -DREENTRANT
+
+# directories
+
+# generic source code
+SRC=..
+SRC_P=$(SRC)/
+
+# source code for MVS
+CMSMVS=../cmsmvs
+CMSMVS_P=$(CMSMVS)/
+
+# include files
+INCLS=-I$(SRC) -I$(CMSMVS)
+
+# object files and load modules
+BLD_P=../mvs/
+
+# Other options
+
+# Suffixes (E and O must be different)
+E=
+O=.o
+
+# Need EXTENDED features for global.c and vmvms.c, so not using c89
+CC=cc
+CFLAGS=-D_OPEN_SYS $(ZIPOPTS) $(INCLS)
+
+LD=cc
+LDFLAGS=
+
+# Files
+
+# object (TEXT) files
+OBJECTS= $(BLD_P)zip$(O) $(BLD_P)trees$(O) \
+   $(BLD_P)crypt$(O)  $(BLD_P)ttyio$(O)   $(BLD_P)deflate$(O) \
+   $(BLD_P)fileio$(O) $(BLD_P)globals$(O) $(BLD_P)util$(O) \
+   $(BLD_P)crc32$(O)  $(BLD_P)crctab$(O)  $(BLD_P)zipfile$(O) \
+   $(BLD_P)zipup$(O)  $(BLD_P)cmsmvs$(O)  $(BLD_P)mvs$(O)
+
+# Header files
+HFILES= $(SRC_P)api.h $(SRC_P)crypt.h $(SRC_P)ebcdic.h \
+    $(SRC_P)revision.h $(SRC_P)tailor.h $(SRC_P)ttyio.h \
+    $(SRC_P)zip.h $(SRC_P)ziperr.h $(CMSMVS_P)cmsmvs.h \
+    $(CMSMVS_P)cstat.h $(CMSMVS_P)mvs.h $(CMSMVS_P)zipup.h
+
+# Rules
+
+all:  $(BLD_P)zip.mvs$(E)
+hfs:  $(BLD_P)zip$(E)
+
+# link
+
+$(BLD_P)zip.mvs$(E):     $(OBJECTS)
+       $(LD) -o "//INFOZIP.LOAD(ZIP)" $(LDFLAGS) $^
+       echo "tso call \"infozip(zip)\" \"'\"\"""$$""@""\"\"'\"" > $%
+       chmod a+x $%
+
+$(BLD_P)zip$(E):     $(OBJECTS)
+       $(LD) -o $% $(LDFLAGS) $^
+
+# compile
+
+$(BLD_P)trees$(O):   $(SRC_P)trees.c        $(HFILES)
+       $(CC) -c -o $% $(CFLAGS) $(SRC_P)trees.c
+
+$(BLD_P)crypt$(O):   $(SRC_P)crypt.c        $(HFILES)
+       $(CC) -c -o $% $(CFLAGS) $(SRC_P)crypt.c
+
+$(BLD_P)ttyio$(O):   $(SRC_P)ttyio.c        $(HFILES)
+       $(CC) -c -o $% $(CFLAGS) $(SRC_P)ttyio.c
+
+$(BLD_P)deflate$(O): $(SRC_P)deflate.c      $(HFILES)
+       $(CC) -c -o $% $(CFLAGS) $(SRC_P)deflate.c
+
+$(BLD_P)fileio$(O):  $(SRC_P)fileio.c       $(HFILES)
+       $(CC) -c -o $% $(CFLAGS) $(SRC_P)fileio.c
+
+$(BLD_P)globals$(O): $(SRC_P)globals.c      $(HFILES)
+       $(CC) -c -o $% $(CFLAGS) $(SRC_P)globals.c
+
+$(BLD_P)zip$(O):     $(SRC_P)zip.c          $(HFILES)
+       $(CC) -c -o $% $(CFLAGS) $(SRC_P)zip.c
+
+$(BLD_P)util$(O):    $(SRC_P)util.c         $(HFILES)
+       $(CC) -c -o $% $(CFLAGS) $(SRC_P)util.c
+
+$(BLD_P)crc32$(O):   $(SRC_P)crc32.c        $(HFILES)
+       $(CC) -c -o $% $(CFLAGS) $(SRC_P)crc32.c
+
+$(BLD_P)crctab$(O):  $(SRC_P)crctab.c       $(HFILES)
+       $(CC) -c -o $% $(CFLAGS) $(SRC_P)crctab.c
+
+$(BLD_P)zipfile$(O): $(SRC_P)zipfile.c      $(HFILES)
+       $(CC) -c -o $% $(CFLAGS) $(SRC_P)zipfile.c
+
+$(BLD_P)zipup$(O):   $(SRC_P)zipup.c        $(HFILES)
+       $(CC) -c -o $% $(CFLAGS) $(SRC_P)zipup.c
+
+$(BLD_P)cmsmvs$(O):  $(CMSMVS_P)cmsmvs.c    $(HFILES)
+       $(CC) -c -o $% $(CFLAGS) $(CMSMVS_P)cmsmvs.c
+
+$(BLD_P)mvs$(O):     $(CMSMVS_P)mvs.c       $(HFILES)
+       $(CC) -c -o $% $(CFLAGS) $(CMSMVS_P)mvs.c
diff --git a/cmsmvs/pipzip.rexx b/cmsmvs/pipzip.rexx
new file mode 100644 (file)
index 0000000..4249ded
--- /dev/null
@@ -0,0 +1,27 @@
+/* PIPZIP REXX     Rexx filter to use ZIP                             */
+/*                 Author : George Petrov, 8 May 1995                 */
+
+parse arg opts
+'callpipe *:',
+   '| specs w1 1 /./ n w2 n',
+   '| join * / /',
+   '| specs /zip 'opts'/ 1 1-* nw',
+   '| cms',
+   '| *:'
+
+exit rc
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cmsmvs/zip.exec b/cmsmvs/zip.exec
new file mode 100644 (file)
index 0000000..0b9de97
--- /dev/null
@@ -0,0 +1,66 @@
+/***********************************************************************/
+/*                                                                     */
+/* Front-end EXEC to set up linkage to the C runtime libraries         */
+/* before executing a MODULE generated from C code.                    */
+/*                                                                     */
+/* Copy this file as an EXEC with a filename matching the C MODULE.    */
+/*                                                                     */
+/* Greg Hartwig (ghartwig@vnet.ibm.com)   7/31/97, 4/24/98.            */
+/*                                                                     */
+/***********************************************************************/
+Address Command
+Parse Arg argstring
+Parse Source . . myname .
+
+/* Set output and input character translation so brackets show up */
+'SET OUTPUT AD' 'BA'x
+'SET OUTPUT BD' 'BB'x
+'SET INPUT  BA   AD'
+'SET INPUT  BB   BD'
+
+Call CLIB
+If rc<>0 Then Do
+   Say 'The required C runtime libraries don''t appear to be available.'
+   Say myname 'can not run.'
+   Exit 12
+End
+
+/* Run the command */
+myname argstring
+Exit rc
+
+
+
+
+/* Contents of the CLIB EXEC, modified for RC checking.        */
+/* Removed TXTLIB setting.  Only LOADLIB needed for execution. */
+CLIB:
+/***************************************************/
+/*      SET UP LIBRARIES FOR LE for MVS & VM       */
+/***************************************************/
+Address COMMAND
+
+loadlib  ='EDCLINK'               /* C/370 runtime                 */
+loadlib  ='SCEERUN'               /* LE runtime                    */
+
+
+theirs=queued()                           /* old stack contentsM068*/
+ 'QUERY LOADLIB ( LIFO'                   /* old setting       M068*/
+ LoadlibList=''                           /* init list         M068*/
+rc=0
+ Do while queued()^=theirs                /* all lines from cmdM068*/
+   Parse upper pull 'LOADLIB' '=' Ltemp   /* get one line      M068*/
+   LoadlibList= Ltemp Loadliblist         /* was stacked LIFO  M068*/
+ End                                                         /*M068*/
+ If loadlibList='NONE' ,
+ Then Do
+  'GLOBAL LOADLIB' Loadlib          /* enforce what we need         */
+ End
+ Else Do
+  Do xx=1 to Words(loadlib)
+  If Find(loadliblist,word(loadlib,xx)) = 0 ,
+   then loadliblist = loadliblist word(loadlib,xx)
+  End
+  'GLOBAL LOADLIB' loadliblist       /* enforce what we need         */
+ End
+Return
diff --git a/cmsmvs/zip.makefile b/cmsmvs/zip.makefile
new file mode 100644 (file)
index 0000000..b183367
--- /dev/null
@@ -0,0 +1,22 @@
+* This is a comment
+* this makefile compiles filter ZIPME
+
+GLOBALS:
+   long def(VM_CMS)
+TEXT:
+   trees c
+   crypt c
+   ttyio c
+   deflate c
+   fileio c
+   globals c
+   zip c
+   util c
+   crc32.c
+   crctab.c
+   zipfile c
+   zipup c
+   cmsmvs c
+   cms c
+MODULE:
+   zip module
diff --git a/cmsmvs/zipcloak.exec b/cmsmvs/zipcloak.exec
new file mode 100644 (file)
index 0000000..0b9de97
--- /dev/null
@@ -0,0 +1,66 @@
+/***********************************************************************/
+/*                                                                     */
+/* Front-end EXEC to set up linkage to the C runtime libraries         */
+/* before executing a MODULE generated from C code.                    */
+/*                                                                     */
+/* Copy this file as an EXEC with a filename matching the C MODULE.    */
+/*                                                                     */
+/* Greg Hartwig (ghartwig@vnet.ibm.com)   7/31/97, 4/24/98.            */
+/*                                                                     */
+/***********************************************************************/
+Address Command
+Parse Arg argstring
+Parse Source . . myname .
+
+/* Set output and input character translation so brackets show up */
+'SET OUTPUT AD' 'BA'x
+'SET OUTPUT BD' 'BB'x
+'SET INPUT  BA   AD'
+'SET INPUT  BB   BD'
+
+Call CLIB
+If rc<>0 Then Do
+   Say 'The required C runtime libraries don''t appear to be available.'
+   Say myname 'can not run.'
+   Exit 12
+End
+
+/* Run the command */
+myname argstring
+Exit rc
+
+
+
+
+/* Contents of the CLIB EXEC, modified for RC checking.        */
+/* Removed TXTLIB setting.  Only LOADLIB needed for execution. */
+CLIB:
+/***************************************************/
+/*      SET UP LIBRARIES FOR LE for MVS & VM       */
+/***************************************************/
+Address COMMAND
+
+loadlib  ='EDCLINK'               /* C/370 runtime                 */
+loadlib  ='SCEERUN'               /* LE runtime                    */
+
+
+theirs=queued()                           /* old stack contentsM068*/
+ 'QUERY LOADLIB ( LIFO'                   /* old setting       M068*/
+ LoadlibList=''                           /* init list         M068*/
+rc=0
+ Do while queued()^=theirs                /* all lines from cmdM068*/
+   Parse upper pull 'LOADLIB' '=' Ltemp   /* get one line      M068*/
+   LoadlibList= Ltemp Loadliblist         /* was stacked LIFO  M068*/
+ End                                                         /*M068*/
+ If loadlibList='NONE' ,
+ Then Do
+  'GLOBAL LOADLIB' Loadlib          /* enforce what we need         */
+ End
+ Else Do
+  Do xx=1 to Words(loadlib)
+  If Find(loadliblist,word(loadlib,xx)) = 0 ,
+   then loadliblist = loadliblist word(loadlib,xx)
+  End
+  'GLOBAL LOADLIB' loadliblist       /* enforce what we need         */
+ End
+Return
diff --git a/cmsmvs/zipmvsc.job b/cmsmvs/zipmvsc.job
new file mode 100644 (file)
index 0000000..6b4b1ca
--- /dev/null
@@ -0,0 +1,95 @@
+//CCZIP JOB (BI09255),
+//        MSGLEVEL=(1,1),MSGCLASS=C,CLASS=D,NOTIFY=C888090
+//PROCLIB JCLLIB ORDER=(SYS1.C370.PROCLIB.M24)
+//ZIP EXEC EDCC,COND=(12,LE),CREGSIZ='4M',
+//    INFILE='C888090.ZIP.C(ZIP)',
+//    OUTFILE='C888090.ZIP.C.OBJ(ZIP),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'
+//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR
+//CRYPT EXEC EDCC,COND=(12,LE),CREGSIZ='4M',
+//    INFILE='C888090.ZIP.C(CRYPT)',
+//    OUTFILE='C888090.ZIP.C.OBJ(CRYPT),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'
+//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR
+//TTYIO EXEC EDCC,COND=(12,LE),CREGSIZ='4M',
+//    INFILE='C888090.ZIP.C(TTYIO)',
+//    OUTFILE='C888090.ZIP.C.OBJ(TTYIO),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'
+//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR
+//TREES EXEC EDCC,COND=(12,LE),CREGSIZ='4M',
+//    INFILE='C888090.ZIP.C(TREES)',
+//    OUTFILE='C888090.ZIP.C.OBJ(TREES),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'
+//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR
+//DEFLATE EXEC EDCC,COND=(12,LE),CREGSIZ='4M',
+//    INFILE='C888090.ZIP.C(DEFLATE)',
+//    OUTFILE='C888090.ZIP.C.OBJ(DEFLATE),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'
+//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR
+//FILEIO EXEC EDCC,COND=(12,LE),CREGSIZ='4M',
+//    INFILE='C888090.ZIP.C(FILEIO)',
+//    OUTFILE='C888090.ZIP.C.OBJ(FILEIO),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'
+//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR
+//GLOBALS EXEC EDCC,COND=(12,LE),CREGSIZ='4M',
+//    INFILE='C888090.ZIP.C(GLOBALS)',
+//    OUTFILE='C888090.ZIP.C.OBJ(GLOBALS),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'
+//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR
+//UTIL EXEC EDCC,COND=(12,LE),CREGSIZ='4M',
+//    INFILE='C888090.ZIP.C(UTIL)',
+//    OUTFILE='C888090.ZIP.C.OBJ(UTIL),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'
+//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR
+//CRC32 EXEC EDCC,COND=(12,LE),CREGSIZ='4M',
+//    INFILE='C888090.ZIP.C(CRC32)',
+//    OUTFILE='C888090.ZIP.C.OBJ(CRC32),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'
+//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR
+//CRCTAB EXEC EDCC,COND=(12,LE),CREGSIZ='4M',
+//    INFILE='C888090.ZIP.C(CRCTAB)',
+//    OUTFILE='C888090.ZIP.C.OBJ(CRCTAB),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'
+//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR
+//ZIPFILE EXEC EDCC,COND=(12,LE),CREGSIZ='4M',
+//    INFILE='C888090.ZIP.C(ZIPFILE)',
+//    OUTFILE='C888090.ZIP.C.OBJ(ZIPFILE),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'
+//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR
+//ZIPUP EXEC EDCC,COND=(12,LE),CREGSIZ='4M',
+//    INFILE='C888090.ZIP.C(ZIPUP)',
+//    OUTFILE='C888090.ZIP.C.OBJ(ZIPUP),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'
+//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR
+//CMSMVS EXEC EDCC,COND=(12,LE),CREGSIZ='4M',
+//    INFILE='C888090.ZIP.C(CMSMVS)',
+//    OUTFILE='C888090.ZIP.C.OBJ(CMSMVS),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'
+//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR
+//MVS EXEC EDCC,COND=(12,LE),CREGSIZ='4M',
+//    INFILE='C888090.ZIP.C(MVS)',
+//    OUTFILE='C888090.ZIP.C.OBJ(MVS),DISP=SHR',
+//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'
+//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR
+//PLINK   EXEC  PROC=EDCPL,COND=(12,LE),
+//    OUTFILE='C888090.ZIP.LOAD(ZIP),DISP=SHR',
+//    PPARM='NONCAL,MAP',
+//    LPARM='LIST,MAP,XREF'
+//SYSPRINT DD  SYSOUT=*
+//PLKED.SYSIN   DD  DSN=C888090.ZIP.C.OBJ(ZIP),DISP=SHR
+//              DD  DSN=C888090.ZIP.C.OBJ(BITS),DISP=SHR
+//              DD  DSN=C888090.ZIP.C.OBJ(CRYPT),DISP=SHR
+//              DD  DSN=C888090.ZIP.C.OBJ(TREES),DISP=SHR
+//              DD  DSN=C888090.ZIP.C.OBJ(DEFLATE),DISP=SHR
+//              DD  DSN=C888090.ZIP.C.OBJ(FILEIO),DISP=SHR
+//              DD  DSN=C888090.ZIP.C.OBJ(GLOBALS),DISP=SHR
+//              DD  DSN=C888090.ZIP.C.OBJ(UTIL),DISP=SHR
+//              DD  DSN=C888090.ZIP.C.OBJ(CRC32),DISP=SHR
+//              DD  DSN=C888090.ZIP.C.OBJ(CRCTAB),DISP=SHR
+//              DD  DSN=C888090.ZIP.C.OBJ(ZIPFILE),DISP=SHR
+//              DD  DSN=C888090.ZIP.C.OBJ(ZIPUP),DISP=SHR
+//              DD  DSN=C888090.ZIP.C.OBJ(CMSMVS),DISP=SHR
+//              DD  DSN=C888090.ZIP.C.OBJ(MVS),DISP=SHR
+//PLKED.SYSLIB  DD  DSN=SYS1.C370.SEDCBASE,DISP=SHR
+//              DD  DSN=SYS1.PL1.SIBMBASE,DISP=SHR
+//SYSUT1   DD  UNIT=SYSDA,SPACE=(CYL,(2,2)),DISP=NEW
diff --git a/cmsmvs/zipname.conven b/cmsmvs/zipname.conven
new file mode 100644 (file)
index 0000000..e17fe9c
--- /dev/null
@@ -0,0 +1,200 @@
+
+         Zip file/directories name convention under MVS
+       ---------------------------------------------------
+                           Draft 1.1
+
+
+1. Translating native file names to Zip filenames.
+
+1.1 Zipping a PDS
+
+On MVS there are directories called PDS (Partition Data Set) which have
+the following format :   name1.name2.name3(mname)
+for example:             myuserid.unzip.c(unzip)
+
+So as you see the path delimiter is '.'. Each dir name can be max 8
+chars long beginning with a number.
+
+Between '(' and ')' there is the so called member name - it is also 8
+chars long. This is the actual file name.
+
+
+1.1.1 Converting MVS PDS name to zip path/filename  (status: not implemented)
+
+The PDS name is converted to zippath as follows:
+in the zip :     name1/name2/mname.name3
+becomes on MVS:  name1.name2.name3(mname)
+
+
+1.2 Unzipping as PDS                                (status: implemented)
+
+When you unzip the file name myuserid/unzip/unzip.c the same process
+is done backwards, so you get : myuserid.unzip.c(unzip)
+
+Notice that the file extension is used as last dirname!
+
+
+1.2 Unzipping to a different PDS                    (status: implemented)
+
+You can also use -d option while unzipping for example:
+unzip mytest myuserid/unzip/unzip.c -dnewdest.test
+
+then the new name will become:
+newdest.test.myuserid.unzip.c(unzip)
+
+              Second example:
+
+unzip mytest myuserid/unzip/*.c -dnewdest.test
+
+then you get a PDS:
+newdest.test.myuserid.unzip.c(...)
+
+with all *.c files in it.
+
+
+1.3 Zipping a Sequential Dataset               (status: not implemented)
+
+  Sequential dataset is a dataset with NO members.
+Such a dataset is translated from native MVS to zip format by replacing
+the '.' (points) with '/' (backslash).
+
+Example:
+on MVS:                  name1.name2.name3
+becomes in the zip :     name1/name2/name3
+
+NOTE : The new filename in the zip has NO extension this way it can be
+       recognised as a Sequential dataset and not a PDS.
+       But this also means that all files in the zip archive that have
+       no extension will be unzipped as Sequential datasets!
+
+
+1.4 Using a DDNAMES for input.                  (status: not implemented)
+
+To use DDNAMES as input file names put a 'dd:' before the ddname:
+example: zip myzip dd:name1 dd:name2 dd:sales
+
+In the Zip archive the ddnames are saved as name.DDNAME so if you try
+the example above you will get in your zip file (when listing it) :
+
+..size .. date time .. crc .. NAME1.DDNAME
+..size .. date time .. crc .. NAME2.DDNAME
+..size .. date time .. crc .. SALES.DDNAME
+
+
+1.4 Using a DDNAMES as zip name                    (status: implemented)
+
+It is allowed to use a DDNAME as zipfile, just put dd: before it
+example: unzip dd:myzip *.c
+   this will unzip all .c files from ddname myzip
+
+example2:   ZIP DD:MYZIP DD:MANE1 MYSOURCE.C MYDOC.TEXT(ZIPPING)
+   this will zip ddname name1 file mysource.c and PDS mydoc.text(zipping)
+   into as a zip file in the ddname myzip
+
+
+2. Converting longer path names (unix like)     (status: not implemented)
+   to native MVS names.
+
+When in the zip archive there are dirnames longer that 8 chars they are
+chopped at the 8 position. For example
+        MyLongZippath/WithLongFileName.text
+is translated to:
+        MYLONGZI.TEXT(WITHLONG)
+
+Notice that all chars are converted to uppercase.
+
+
+2.1 Using special characters                     (status: implemented)
+
+Also all '_' (underscore), '+' (plus), '-' (minus), '(' and ')'
+from the file name/path in the zip archive are skipped because they
+are not valid in the MVS filenames.
+
+
+2.2 Numeric file names                        (status: not implemented)
+
+On MVS no name can begin with a number, so when a dir/file name begins with
+one, a leading letter 'N' is inserted.  For example:
+          Contents.512
+becomes:
+          CONTENTS.N512
+
+
+
+
+        Zip file/directories name convention under VM/CMS
+       ---------------------------------------------------
+
+1. Translating native file names to Zip filenames.
+
+On VM/CMS (not ESA ) there are NO directories so you got only disks
+and files.
+
+The file names are delimited with spaces. But for use with unzip/zip
+you have to use '.' points as delimiters.
+
+For example on your A disk you have file called PROFILE EXEC
+if you want to zip it type : zip myzip profile.exec
+
+If the same file is on your F disk you have to type:
+zip myzip profile.exec.f
+
+So as you can see the general format is fname.ftype.fmode
+
+In the zipfile the disk from which the file comes is not saved!
+So only the fname.ftype is saved.
+
+If you unzip and you want to give a different destination disk just use
+the -d option like:
+
+                     unzip mytest *.c -df
+
+This will unzip all *.c files to your F disk.
+
+
+2. Converting longer path names (unix like) to native VM/CMS names.
+
+When in the zip archive there are dirnames longer that 8 chars they are
+chopped at the 8 position. Also the path is removed. For example
+        Zippath/WithLongFileName.text
+is translated to:
+        WITHLONG.TEXT
+
+Notice that all chars are converted to uppercase.
+
+Also all '+' (plus), '-' (minus), '(' and ')'
+from the file name/path in the zip archive are skipped because they
+are not valid in the VM/CMS filenames.
+
+If there is no extension for the file name in the zip archive, unzip
+will add .NONAME for example:
+        mypath/dir1/testfile
+becomes:
+        TESTFILE.NONAME
+
+3. Future?
+
+There is also discussion for a new option on ZIP that you can give
+a virtual directory to be added before each file name that is zipped.
+
+For example you want to zip a few .c file and put them in the zip
+structure under the directory 'mydir/test', but you can't create dirs on
+VM/CMS so you have to the something like:
+
+ZIP myzip file1.c file2.c -dmydir/test
+
+and you get in the zip archive files:
+
+       mydir/test/file1.c
+       mydir/test/file2.c
+
+-------------------------------------------------------------------------
+
+
+NOTE: Not all of those functions are implemented in the first beta
+      release of VM/MVS UNZIP/ZIP.
+
+Every ideas/corrections/bugs will be appreciated.
+Mail to maillist:  Info-ZIP@LISTS.WKU.EDU
+
+George Petrov
diff --git a/cmsmvs/zipnote.exec b/cmsmvs/zipnote.exec
new file mode 100644 (file)
index 0000000..0b9de97
--- /dev/null
@@ -0,0 +1,66 @@
+/***********************************************************************/
+/*                                                                     */
+/* Front-end EXEC to set up linkage to the C runtime libraries         */
+/* before executing a MODULE generated from C code.                    */
+/*                                                                     */
+/* Copy this file as an EXEC with a filename matching the C MODULE.    */
+/*                                                                     */
+/* Greg Hartwig (ghartwig@vnet.ibm.com)   7/31/97, 4/24/98.            */
+/*                                                                     */
+/***********************************************************************/
+Address Command
+Parse Arg argstring
+Parse Source . . myname .
+
+/* Set output and input character translation so brackets show up */
+'SET OUTPUT AD' 'BA'x
+'SET OUTPUT BD' 'BB'x
+'SET INPUT  BA   AD'
+'SET INPUT  BB   BD'
+
+Call CLIB
+If rc<>0 Then Do
+   Say 'The required C runtime libraries don''t appear to be available.'
+   Say myname 'can not run.'
+   Exit 12
+End
+
+/* Run the command */
+myname argstring
+Exit rc
+
+
+
+
+/* Contents of the CLIB EXEC, modified for RC checking.        */
+/* Removed TXTLIB setting.  Only LOADLIB needed for execution. */
+CLIB:
+/***************************************************/
+/*      SET UP LIBRARIES FOR LE for MVS & VM       */
+/***************************************************/
+Address COMMAND
+
+loadlib  ='EDCLINK'               /* C/370 runtime                 */
+loadlib  ='SCEERUN'               /* LE runtime                    */
+
+
+theirs=queued()                           /* old stack contentsM068*/
+ 'QUERY LOADLIB ( LIFO'                   /* old setting       M068*/
+ LoadlibList=''                           /* init list         M068*/
+rc=0
+ Do while queued()^=theirs                /* all lines from cmdM068*/
+   Parse upper pull 'LOADLIB' '=' Ltemp   /* get one line      M068*/
+   LoadlibList= Ltemp Loadliblist         /* was stacked LIFO  M068*/
+ End                                                         /*M068*/
+ If loadlibList='NONE' ,
+ Then Do
+  'GLOBAL LOADLIB' Loadlib          /* enforce what we need         */
+ End
+ Else Do
+  Do xx=1 to Words(loadlib)
+  If Find(loadliblist,word(loadlib,xx)) = 0 ,
+   then loadliblist = loadliblist word(loadlib,xx)
+  End
+  'GLOBAL LOADLIB' loadliblist       /* enforce what we need         */
+ End
+Return
diff --git a/cmsmvs/zipsplit.exec b/cmsmvs/zipsplit.exec
new file mode 100644 (file)
index 0000000..0b9de97
--- /dev/null
@@ -0,0 +1,66 @@
+/***********************************************************************/
+/*                                                                     */
+/* Front-end EXEC to set up linkage to the C runtime libraries         */
+/* before executing a MODULE generated from C code.                    */
+/*                                                                     */
+/* Copy this file as an EXEC with a filename matching the C MODULE.    */
+/*                                                                     */
+/* Greg Hartwig (ghartwig@vnet.ibm.com)   7/31/97, 4/24/98.            */
+/*                                                                     */
+/***********************************************************************/
+Address Command
+Parse Arg argstring
+Parse Source . . myname .
+
+/* Set output and input character translation so brackets show up */
+'SET OUTPUT AD' 'BA'x
+'SET OUTPUT BD' 'BB'x
+'SET INPUT  BA   AD'
+'SET INPUT  BB   BD'
+
+Call CLIB
+If rc<>0 Then Do
+   Say 'The required C runtime libraries don''t appear to be available.'
+   Say myname 'can not run.'
+   Exit 12
+End
+
+/* Run the command */
+myname argstring
+Exit rc
+
+
+
+
+/* Contents of the CLIB EXEC, modified for RC checking.        */
+/* Removed TXTLIB setting.  Only LOADLIB needed for execution. */
+CLIB:
+/***************************************************/
+/*      SET UP LIBRARIES FOR LE for MVS & VM       */
+/***************************************************/
+Address COMMAND
+
+loadlib  ='EDCLINK'               /* C/370 runtime                 */
+loadlib  ='SCEERUN'               /* LE runtime                    */
+
+
+theirs=queued()                           /* old stack contentsM068*/
+ 'QUERY LOADLIB ( LIFO'                   /* old setting       M068*/
+ LoadlibList=''                           /* init list         M068*/
+rc=0
+ Do while queued()^=theirs                /* all lines from cmdM068*/
+   Parse upper pull 'LOADLIB' '=' Ltemp   /* get one line      M068*/
+   LoadlibList= Ltemp Loadliblist         /* was stacked LIFO  M068*/
+ End                                                         /*M068*/
+ If loadlibList='NONE' ,
+ Then Do
+  'GLOBAL LOADLIB' Loadlib          /* enforce what we need         */
+ End
+ Else Do
+  Do xx=1 to Words(loadlib)
+  If Find(loadliblist,word(loadlib,xx)) = 0 ,
+   then loadliblist = loadliblist word(loadlib,xx)
+  End
+  'GLOBAL LOADLIB' loadliblist       /* enforce what we need         */
+ End
+Return
diff --git a/cmsmvs/zipup.h b/cmsmvs/zipup.h
new file mode 100644 (file)
index 0000000..0ea8962
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#define fhow  "r,byteseek"
+#define fhowb "rb,byteseek"
+
+#define fbad NULL
+typedef FILE *ftype;
+#define zopen(n,p)   (ftype)fopen((n),(p))
+#define zread(f,b,n) fread((b),1,(n),(FILE*)(f))
+#define zclose(f)    fclose((FILE*)(f))
+#define zerr(f)      ferror((FILE*)(f))
+#define zstdin       stdin
diff --git a/cmsmvs/zipvmc.exec b/cmsmvs/zipvmc.exec
new file mode 100644 (file)
index 0000000..3232649
--- /dev/null
@@ -0,0 +1,50 @@
+/* VMCOMPIL EXEC   Unzip compile for VM/CMS                           */
+/*                 Author : George Petrov, 11 Apr 1995                */
+
+signal on error
+
+parms = '(long def(VM_CMS)'
+
+/* Add local parms */
+parms = parms 'TARGET(COMPAT) SOURCE'
+
+
+say 'Compiling TREES C...'
+'cc trees c 'parms
+say 'Compiling CRYPT C...'
+'cc crypt c 'parms
+say 'Compiling TTYIO C...'
+'cc ttyio c 'parms
+say 'Compiling DEFLATE C...'
+'cc deflate c 'parms
+say 'Compiling FILEIO C...'
+'cc fileio c 'parms
+say 'Compiling GLOBALS C...'
+'cc globals c 'parms
+say 'Compiling ZIP C...'
+'cc zip c 'parms
+say 'Compiling UTIL C...'
+'cc util c 'parms
+say 'Compiling CRC32 C...'
+'cc crc32 c 'parms
+say 'Compiling CRCTAB C...'
+'cc crctab c 'parms
+say 'Compiling ZIPFILE C...'
+'cc zipfile c 'parms
+say 'Compiling ZIPUP C...'
+'cc zipup c 'parms
+say 'Compiling CMSMVS C...'
+'cc cmsmvs c 'parms
+say 'Compiling CMS C...'
+'cc cms c 'parms
+
+say 'Linking all files...'
+'cmod zip zip trees crypt deflate fileio globals ttyio',
+           'util crc32 crctab zipfile zipup cmsmvs cms'
+say 'All Done!'
+say "To run enter : ZIP parms"
+exit rc
+
+error:
+say 'Error durring compilation!'
+exit rc
diff --git a/crc32.c b/crc32.c
new file mode 100644 (file)
index 0000000..aaebb40
--- /dev/null
+++ b/crc32.c
@@ -0,0 +1,64 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $Id: crc32.c,v 1.5 1996/01/13 14:55:12 spc Exp $ */
+
+#define __CRC32_C       /* identifies this source module */
+
+#include "zip.h"
+
+#ifndef USE_ZLIB
+#ifndef ASM_CRC
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+
+#ifdef CRC32
+#  undef CRC32
+#endif
+#define CRC32(c, b) (crc_table[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
+#define DO1(buf)  crc = CRC32(crc, *buf++)
+#define DO2(buf)  DO1(buf); DO1(buf)
+#define DO4(buf)  DO2(buf); DO2(buf)
+#define DO8(buf)  DO4(buf); DO4(buf)
+
+/* ========================================================================= */
+ulg crc32(crc, buf, len)
+    register ulg crc;           /* crc shift register */
+    register ZCONST uch *buf;   /* pointer to bytes to pump through */
+    extent len;                 /* number of bytes in buf[] */
+/* Run a set of bytes through the crc shift register.  If buf is a NULL
+   pointer, then initialize the crc shift register contents instead.
+   Return the current crc in either case. */
+{
+  register ZCONST ulg near *crc_table;
+
+  if (buf == NULL) return 0L;
+
+  crc_table = get_crc_table();
+
+  crc = crc ^ 0xffffffffL;
+#ifndef NO_UNROLLED_LOOPS
+  while (len >= 8) {
+    DO8(buf);
+    len -= 8;
+  }
+#endif
+  if (len) do {
+    DO1(buf);
+  } while (--len);
+  return crc ^ 0xffffffffL;     /* (instead of ~c for 64-bit machines) */
+}
+#endif /* !ASM_CRC */
+#endif /* !USE_ZLIB */
diff --git a/crc_i386.S b/crc_i386.S
new file mode 100644 (file)
index 0000000..d23967b
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ * crc_i386.S, optimized CRC calculation function for Zip and UnZip,
+ * created by Paul Kienitz and Christian Spieler.
+ *
+ * GRR 961110:  incorporated Scott Field optimizations from win32/crc_i386.asm
+ *              => overall 6% speedup in "unzip -tq" on 9MB zipfile (486-66)
+ *
+ * SPC 970402:  revised for Rodney Brown's optimizations (32-bit-wide
+ *              aligned reads for most of the data from buffer), can be
+ *              disabled by defining the macro NO_32_BIT_LOADS
+ *
+ * SPC 971012:  added Rodney Brown's additional tweaks for 32-bit-optimized
+ *              CPUs (like the Pentium Pro, Pentium II, and probably some
+ *              Pentium clones). This optimization is controlled by the
+ *              preprocessor switch "__686" and is disabled by default.
+ *              (This default is based on the assumption that most users
+ *              do not yet work on a Pentium Pro or Pentium II machine ...)
+ *
+ * COS 050116:  Enabled the 686 build by default, because there are hardly any
+ *              pre-686 CPUs in serious use nowadays. (See SPC 970402 above.)
+ *
+ * FLAT memory model assumed.  Calling interface:
+ *   - args are pushed onto the stack from right to left,
+ *   - return value is given in the EAX register,
+ *   - all other registers (with exception of EFLAGS) are preserved. (With
+ *     GNU C 2.7.x, %edx and %ecx are `scratch' registers, but preserving
+ *     them nevertheless adds only 4 single byte instructions.)
+ *
+ * This source generates the function
+ * ulg crc32(ulg crc, ZCONST uch *buf, extent len).
+ *
+ * Loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.
+ * This results in shorter code at the expense of reduced performance.
+ */
+
+/* This file is NOT used in conjunction with zlib. */
+#ifndef USE_ZLIB
+
+/* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix
+ * external symbols with an underline character '_'.
+ */
+#if defined(NO_UNDERLINE) || defined(__ELF__)
+#  define _crc32            crc32
+#  define _get_crc_table    get_crc_table
+#endif
+/* Use 16-byte alignment if your assembler supports it. Warning: gas
+ * uses a log(x) parameter (.align 4 means 16-byte alignment). On SVR4
+ * the parameter is a number of bytes.
+ */
+#ifndef ALIGNMENT
+#  define ALIGNMENT .align 4,0x90
+#endif
+
+#if defined(i386) || defined(_i386) || defined(_I386) || defined(__i386)
+
+/* This version is for 386 Unix, OS/2, MSDOS in 32 bit mode (gcc & gas).
+ * Warning: it uses the AT&T syntax: mov source,dest
+ * This file is only optional. If you want to use the C version,
+ * remove -DASM_CRC from CFLAGS in Makefile and set OBJA to an empty string.
+ */
+
+                .file   "crc_i386.S"
+
+#if !defined(PRE_686) && !defined(__686)
+   /* Optimize for Pentium Pro and compatible CPUs by default. */
+#  define __686
+#endif
+
+#if defined(NO_STD_STACKFRAME) && defined(USE_STD_STACKFRAME)
+#  undef USE_STACKFRAME
+#else
+   /* The default is to use standard stack frame entry, because it
+    * results in smaller code!
+    */
+#  ifndef USE_STD_STACKFRAME
+#    define USE_STD_STACKFRAME
+#  endif
+#endif
+
+#ifdef USE_STD_STACKFRAME
+#  define _STD_ENTRY    pushl   %ebp ; movl   %esp,%ebp
+#  define arg1  8(%ebp)
+#  define arg2  12(%ebp)
+#  define arg3  16(%ebp)
+#  define _STD_LEAVE    popl    %ebp
+#else /* !USE_STD_STACKFRAME */
+#  define _STD_ENTRY
+#  define arg1  24(%esp)
+#  define arg2  28(%esp)
+#  define arg3  32(%esp)
+#  define _STD_LEAVE
+#endif /* ?USE_STD_STACKFRAME */
+
+/*
+ * These two (three) macros make up the loop body of the CRC32 cruncher.
+ * registers modified:
+ *   eax  : crc value "c"
+ *   esi  : pointer to next data byte (or lword) "buf++"
+ * registers read:
+ *   edi  : pointer to base of crc_table array
+ * scratch registers:
+ *   ebx  : index into crc_table array
+ *          (requires upper three bytes = 0 when __686 is undefined)
+ */
+#ifndef __686   /* optimize for 386, 486, Pentium */
+#define Do_CRC          /* c = (c >> 8) ^ table[c & 0xFF] */\
+                movb    %al, %bl                ;/* tmp = c & 0xFF  */\
+                shrl    $8, %eax                ;/* c = (c >> 8)    */\
+                xorl    (%edi, %ebx, 4), %eax   ;/* c ^= table[tmp] */
+#else   /* __686 : optimize for Pentium Pro and compatible CPUs */
+#define Do_CRC          /* c = (c >> 8) ^ table[c & 0xFF] */\
+                movzbl  %al, %ebx               ;/* tmp = c & 0xFF  */\
+                shrl    $8, %eax                ;/* c = (c >> 8)    */\
+                xorl    (%edi, %ebx, 4), %eax   ;/* c ^=table[tmp]  */
+#endif  /* ?__686 */
+
+#define Do_CRC_byte     /* c = (c >> 8) ^ table[(c^*buf++)&0xFF] */\
+                xorb    (%esi), %al     ;/* c ^= *buf  */\
+                incl    %esi            ;/* buf++      */\
+                Do_CRC
+
+#ifndef  NO_32_BIT_LOADS
+#define Do_CRC_lword \
+                xorl    (%esi), %eax    ;/* c ^= *(ulg *)buf */\
+                addl    $4, %esi        ;/* ((ulg *)buf)++   */\
+                Do_CRC \
+                Do_CRC \
+                Do_CRC \
+                Do_CRC
+#endif  /* !NO_32_BIT_LOADS */
+
+
+                .text
+
+                .globl  _crc32
+
+_crc32:                         /* ulg crc32(ulg crc, uch *buf, extent len) */
+                _STD_ENTRY
+                pushl   %edi
+                pushl   %esi
+                pushl   %ebx
+                pushl   %edx
+                pushl   %ecx
+
+                movl    arg2, %esi           /* 2nd arg: uch *buf            */
+                subl    %eax, %eax           /* > if (!buf)                  */
+                testl   %esi, %esi           /* >   return 0;                */
+                jz      .L_fine              /* > else {                     */
+                call    _get_crc_table
+                movl    %eax, %edi
+                movl    arg1, %eax           /* 1st arg: ulg crc             */
+#ifndef __686
+                subl    %ebx, %ebx           /* ebx=0; bl usable as dword    */
+#endif
+                movl    arg3, %ecx           /* 3rd arg: extent len          */
+                notl    %eax                 /* >   c = ~crc;                */
+
+                testl   %ecx, %ecx
+#ifndef  NO_UNROLLED_LOOPS
+                jz      .L_bail
+#  ifndef  NO_32_BIT_LOADS
+                /* Assert now have positive length */
+.L_align_loop:
+                testl   $3, %esi        /* Align buf on lword boundary */
+                jz      .L_aligned_now
+                Do_CRC_byte
+                decl    %ecx
+                jnz     .L_align_loop
+.L_aligned_now:
+#  endif  /* !NO_32_BIT_LOADS */
+                movl    %ecx, %edx           /* save len in edx */
+                shrl    $3, %ecx             /* ecx = len / 8   */
+                jz      .L_No_Eights
+/*  align loop head at start of 486 internal cache line !! */
+                ALIGNMENT
+.L_Next_Eight:
+#  ifndef NO_32_BIT_LOADS
+                 /* Do_CRC_lword */
+                 xorl    (%esi), %eax    ;/* c ^= *(ulg *)buf */
+                 addl    $4, %esi        ;/* ((ulg *)buf)++   */
+                 Do_CRC
+                 Do_CRC
+                 Do_CRC
+                 Do_CRC
+                 /* Do_CRC_lword */
+                 xorl    (%esi), %eax    ;/* c ^= *(ulg *)buf */
+                 addl    $4, %esi        ;/* ((ulg *)buf)++   */
+                 Do_CRC
+                 Do_CRC
+                 Do_CRC
+                 Do_CRC
+#  else   /* NO_32_BIT_LOADS */
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+#  endif  /* ?NO_32_BIT_LOADS */
+                decl    %ecx
+                jnz     .L_Next_Eight
+
+.L_No_Eights:
+                movl    %edx, %ecx
+                andl    $7, %ecx             /* ecx = len % 8   */
+#endif /* !NO_UNROLLED_LOOPS */
+                jz      .L_bail              /* > if (len)                   */
+/* align loop head at start of 486 internal cache line !! */
+                ALIGNMENT
+.L_loupe:                                    /* >   do {                     */
+                 Do_CRC_byte                 /*       c = CRC32(c, *buf++);  */
+                decl    %ecx                 /* >   } while (--len);         */
+                jnz     .L_loupe
+
+.L_bail:                                     /* > }                          */
+                notl    %eax                 /* > return ~c;                 */
+.L_fine:
+                popl    %ecx
+                popl    %edx
+                popl    %ebx
+                popl    %esi
+                popl    %edi
+                _STD_LEAVE
+                ret
+
+#else
+ error: this asm version is for 386 only
+#endif /* i386 || _i386 || _I386 || __i386 */
+
+#endif /* !USE_ZLIB */
diff --git a/crctab.c b/crctab.c
new file mode 100644 (file)
index 0000000..f47fda4
--- /dev/null
+++ b/crctab.c
@@ -0,0 +1,227 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* crctab.c -- supply the CRC table needed for CRC-32 calculations.
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $Id: crctab.c,v 1.4 1996/01/08 14:55:12 jloup Exp $ */
+
+/*
+  Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
+  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+  Polynomials over GF(2) are represented in binary, one bit per coefficient,
+  with the lowest powers in the most significant bit.  Then adding polynomials
+  is just exclusive-or, and multiplying a polynomial by x is a right shift by
+  one.  If we call the above polynomial p, and represent a byte as the
+  polynomial q, also with the lowest power in the most significant bit (so the
+  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+  where a mod b means the remainder after dividing a by b.
+
+  This calculation is done using the shift-register method of multiplying and
+  taking the remainder.  The register is initialized to zero, and for each
+  incoming bit, x^32 is added mod p to the register if the bit is a one (where
+  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+  x (which is shifting right by one and adding x^32 mod p if the bit shifted
+  out is a one).  We start with the highest power (least significant bit) of
+  q and repeat for all eight bits of q.
+
+  The table is simply the CRC of all possible eight bit values.  This is all
+  the information needed to generate CRC's on data a byte at a time for all
+  combinations of CRC register values and incoming bytes.
+*/
+
+#define __CRCTAB_C      /* identifies this source module */
+
+#include "zip.h"
+
+#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+
+#ifdef DYNAMIC_CRC_TABLE
+
+/* =========================================================================
+ * Make the crc table. This function is needed only if you want to compute
+ * the table dynamically.
+ */
+
+local void make_crc_table OF((void));
+
+#if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT))
+   error: Dynamic allocation of CRC table not safe with reentrant code.
+#endif /* DYNALLOC_CRCTAB && REENTRANT */
+
+#ifdef DYNALLOC_CRCTAB
+   local ulg near *crc_table = NULL;
+# if 0          /* not used, since sizeof("near *") <= sizeof(int) */
+   /* Use this section when access to a "local int" is faster than access to
+      a "local pointer" (e.g.: i86 16bit code with far pointers). */
+   local int crc_table_empty = 1;
+#  define CRC_TABLE_IS_EMPTY    (crc_table_empty != 0)
+#  define MARK_CRCTAB_FILLED    crc_table_empty = 0
+#  define MARK_CRCTAB_EMPTY     crc_table_empty = 1
+# else
+   /* Use this section on systems where the size of pointers and ints is
+      equal (e.g.: all 32bit systems). */
+#  define CRC_TABLE_IS_EMPTY    (crc_table == NULL)
+#  define MARK_CRCTAB_FILLED    crc_table = crctab_p
+#  define MARK_CRCTAB_EMPTY     crc_table = NULL
+# endif
+#else /* !DYNALLOC_CRCTAB */
+   local ulg near crc_table[256];
+   local int crc_table_empty = 1;
+#  define CRC_TABLE_IS_EMPTY    (crc_table_empty != 0)
+#  define MARK_CRCTAB_FILLED    crc_table_empty = 0
+#endif /* ?DYNALLOC_CRCTAB */
+
+
+local void make_crc_table()
+{
+  ulg c;                /* crc shift register */
+  int n;                /* counter for all possible eight bit values */
+  int k;                /* byte being shifted into crc apparatus */
+#ifdef DYNALLOC_CRCTAB
+  ulg near *crctab_p;   /* temporary pointer to allocated crc_table area */
+#else /* !DYNALLOC_CRCTAB */
+# define crctab_p crc_table
+#endif /* DYNALLOC_CRCTAB */
+
+#ifdef COMPUTE_XOR_PATTERN
+  /* This piece of code has been left here to explain how the XOR pattern
+   * used in the creation of the crc_table values can be recomputed.
+   * For production versions of this function, it is more efficient to
+   * supply the resultant pattern at compile time.
+   */
+  ulg xor;              /* polynomial exclusive-or pattern */
+  /* terms of polynomial defining this crc (except x^32): */
+  static uch p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+  /* make exclusive-or pattern from polynomial (0xedb88320L) */
+  xor = 0L;
+  for (i = 0; i < sizeof(p)/sizeof(uch); i++)
+    xor |= 1L << (31 - p[i]);
+#else
+# define xor 0xedb88320L
+#endif
+
+#ifdef DYNALLOC_CRCTAB
+  crctab_p = (ulg near *) nearmalloc (256*sizeof(ulg));
+  if (crctab_p == NULL) {
+    ziperr(ZE_MEM, "crc_table allocation");
+  }
+#endif /* DYNALLOC_CRCTAB */
+
+  for (n = 0; n < 256; n++) {
+    c = (ulg)n;
+    for (k = 8; k; k--)
+      c = c & 1 ? xor ^ (c >> 1) : c >> 1;
+    crctab_p[n] = c;
+  }
+  MARK_CRCTAB_FILLED;
+}
+
+#else /* !DYNAMIC_CRC_TABLE */
+
+#ifdef DYNALLOC_CRCTAB
+   error: Inconsistent flags, DYNALLOC_CRCTAB without DYNAMIC_CRC_TABLE.
+#endif
+
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by make_crc_table)
+ */
+local ZCONST ulg near crc_table[256] = {
+  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+  0x2d02ef8dL
+};
+#endif /* ?DYNAMIC_CRC_TABLE */
+
+/* use "OF((void))" here to work around a Borland TC++ 1.0 problem */
+#ifdef USE_ZLIB
+ZCONST uLongf *get_crc_table OF((void))
+#else
+ZCONST ulg near *get_crc_table OF((void))
+#endif
+{
+#ifdef DYNAMIC_CRC_TABLE
+  if (CRC_TABLE_IS_EMPTY)
+    make_crc_table();
+#endif
+#ifdef USE_ZLIB
+  return (ZCONST uLongf *)crc_table;
+#else
+  return (ZCONST ulg near *)crc_table;
+#endif
+}
+
+#ifdef DYNALLOC_CRCTAB
+void free_crc_table()
+{
+  if (!CRC_TABLE_IS_EMPTY)
+  {
+    nearfree((ulg near *)crc_table);
+    MARK_CRCTAB_EMPTY;
+  }
+}
+#endif
+
+#endif /* !USE_ZLIB || USE_OWN_CRCTAB */
diff --git a/crypt.c b/crypt.c
new file mode 100644 (file)
index 0000000..377d4fb
--- /dev/null
+++ b/crypt.c
@@ -0,0 +1,584 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+  crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
+
+  The encryption/decryption parts of this source code (as opposed to the
+  non-echoing password parts) were originally written in Europe.  The
+  whole source package can be freely distributed, including from the USA.
+  (Prior to January 2000, re-export from the US was a violation of US law.)
+ */
+
+/*
+  This encryption code is a direct transcription of the algorithm from
+  Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
+  file (appnote.txt) is distributed with the PKZIP program (even in the
+  version without encryption capabilities).
+ */
+
+#define ZCRYPT_INTERNAL
+#include "zip.h"
+#include "crypt.h"
+#include "ttyio.h"
+
+#if CRYPT
+
+#ifndef FALSE
+#  define FALSE 0
+#endif
+
+#ifdef ZIP
+   /* For the encoding task used in Zip (and ZipCloak), we want to initialize
+      the crypt algorithm with some reasonably unpredictable bytes, see
+      the crypthead() function. The standard rand() library function is
+      used to supply these `random' bytes, which in turn is initialized by
+      a srand() call. The srand() function takes an "unsigned" (at least 16bit)
+      seed value as argument to determine the starting point of the rand()
+      pseudo-random number generator.
+      This seed number is constructed as "Seed = Seed1 .XOR. Seed2" with
+      Seed1 supplied by the current time (= "(unsigned)time()") and Seed2
+      as some (hopefully) nondeterministic bitmask. On many (most) systems,
+      we use some "process specific" number, as the PID or something similar,
+      but when nothing unpredictable is available, a fixed number may be
+      sufficient.
+      NOTE:
+      1.) This implementation requires the availability of the following
+          standard UNIX C runtime library functions: time(), rand(), srand().
+          On systems where some of them are missing, the environment that
+          incorporates the crypt routines must supply suitable replacement
+          functions.
+      2.) It is a very bad idea to use a second call to time() to set the
+          "Seed2" number! In this case, both "Seed1" and "Seed2" would be
+          (almost) identical, resulting in a (mostly) "zero" constant seed
+          number passed to srand().
+
+      The implementation environment defined in the "zip.h" header should
+      supply a reasonable definition for ZCR_SEED2 (an unsigned number; for
+      most implementations of rand() and srand(), only the lower 16 bits are
+      significant!). An example that works on many systems would be
+           "#define ZCR_SEED2  (unsigned)getpid()".
+      The default definition for ZCR_SEED2 supplied below should be regarded
+      as a fallback to allow successful compilation in "beta state"
+      environments.
+    */
+#  include <time.h>     /* time() function supplies first part of crypt seed */
+   /* "last resort" source for second part of crypt seed pattern */
+#  ifndef ZCR_SEED2
+#    define ZCR_SEED2 (unsigned)3141592654L     /* use PI as default pattern */
+#  endif
+#  ifdef GLOBAL         /* used in Amiga system headers, maybe others too */
+#    undef GLOBAL
+#  endif
+#  define GLOBAL(g) g
+#else /* !ZIP */
+#  define GLOBAL(g) G.g
+#endif /* ?ZIP */
+
+
+#ifdef UNZIP
+   /* char *key = (char *)NULL; moved to globals.h */
+#  ifndef FUNZIP
+     local int testp OF((__GPRO__ ZCONST uch *h));
+     local int testkey OF((__GPRO__ ZCONST uch *h, ZCONST char *key));
+#  endif
+#endif /* UNZIP */
+
+#ifndef UNZIP             /* moved to globals.h for UnZip */
+   local ulg keys[3];     /* keys defining the pseudo-random sequence */
+#endif /* !UNZIP */
+
+#ifndef Trace
+#  ifdef CRYPT_DEBUG
+#    define Trace(x) fprintf x
+#  else
+#    define Trace(x)
+#  endif
+#endif
+
+#ifndef CRC_32_TAB
+#  define CRC_32_TAB     crc_32_tab
+#endif
+
+#define CRC32(c, b) (CRC_32_TAB[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
+
+/***********************************************************************
+ * Return the next byte in the pseudo-random sequence
+ */
+int decrypt_byte(__G)
+    __GDEF
+{
+    unsigned temp;  /* POTENTIAL BUG:  temp*(temp^1) may overflow in an
+                     * unpredictable manner on 16-bit systems; not a problem
+                     * with any known compiler so far, though */
+
+    temp = ((unsigned)GLOBAL(keys[2]) & 0xffff) | 2;
+    return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
+}
+
+/***********************************************************************
+ * Update the encryption keys with the next byte of plain text
+ */
+int update_keys(__G__ c)
+    __GDEF
+    int c;                      /* byte of plain text */
+{
+    GLOBAL(keys[0]) = CRC32(GLOBAL(keys[0]), c);
+    GLOBAL(keys[1]) += GLOBAL(keys[0]) & 0xff;
+    GLOBAL(keys[1]) = GLOBAL(keys[1]) * 134775813L + 1;
+    {
+      register int keyshift = (int)(GLOBAL(keys[1]) >> 24);
+      GLOBAL(keys[2]) = CRC32(GLOBAL(keys[2]), keyshift);
+    }
+    return c;
+}
+
+
+/***********************************************************************
+ * Initialize the encryption keys and the random header according to
+ * the given password.
+ */
+void init_keys(__G__ passwd)
+    __GDEF
+    ZCONST char *passwd;        /* password string with which to modify keys */
+{
+    GLOBAL(keys[0]) = 305419896L;
+    GLOBAL(keys[1]) = 591751049L;
+    GLOBAL(keys[2]) = 878082192L;
+    while (*passwd != '\0') {
+        update_keys(__G__ (int)*passwd);
+        passwd++;
+    }
+}
+
+
+#ifdef ZIP
+
+/***********************************************************************
+ * Write encryption header to file zfile using the password passwd
+ * and the cyclic redundancy check crc.
+ */
+void crypthead(passwd, crc, zfile)
+    ZCONST char *passwd;         /* password string */
+    ulg crc;                     /* crc of file being encrypted */
+    FILE *zfile;                 /* where to write header */
+{
+    int n;                       /* index in random header */
+    int t;                       /* temporary */
+    int c;                       /* random byte */
+    int ztemp;                   /* temporary for zencoded value */
+    uch header[RAND_HEAD_LEN-2]; /* random header */
+    static unsigned calls = 0;   /* ensure different random header each time */
+
+    /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
+     * output of rand() to get less predictability, since rand() is
+     * often poorly implemented.
+     */
+    if (++calls == 1) {
+        srand((unsigned)time(NULL) ^ ZCR_SEED2);
+    }
+    init_keys(passwd);
+    for (n = 0; n < RAND_HEAD_LEN-2; n++) {
+        c = (rand() >> 7) & 0xff;
+        header[n] = (uch)zencode(c, t);
+    }
+    /* Encrypt random header (last two bytes is high word of crc) */
+    init_keys(passwd);
+    for (n = 0; n < RAND_HEAD_LEN-2; n++) {
+        ztemp = zencode(header[n], t);
+        putc(ztemp, zfile);
+    }
+    ztemp = zencode((int)(crc >> 16) & 0xff, t);
+    putc(ztemp, zfile);
+    ztemp = zencode((int)(crc >> 24) & 0xff, t);
+    putc(ztemp, zfile);
+}
+
+
+#ifdef UTIL
+
+/***********************************************************************
+ * Encrypt the zip entry described by z from file source to file dest
+ * using the password passwd.  Return an error code in the ZE_ class.
+ */
+int zipcloak(z, source, dest, passwd)
+    struct zlist far *z;    /* zip entry to encrypt */
+    FILE *source, *dest;    /* source and destination files */
+    ZCONST char *passwd;    /* password string */
+{
+    int c;                  /* input byte */
+    int res;                /* result code */
+    ulg n;                  /* holds offset and counts size */
+    ush flag;               /* previous flags */
+    int t;                  /* temporary */
+    int ztemp;              /* temporary storage for zencode value */
+
+    /* Set encrypted bit, clear extended local header bit and write local
+       header to output file */
+    if ((n = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP;
+    z->off = n;
+    flag = z->flg;
+    z->flg |= 1,  z->flg &= ~8;
+    z->lflg |= 1, z->lflg &= ~8;
+    z->siz += RAND_HEAD_LEN;
+    if ((res = putlocal(z, dest)) != ZE_OK) return res;
+
+    /* Initialize keys with password and write random header */
+    crypthead(passwd, z->crc, dest);
+
+    /* Skip local header in input file */
+    if (fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext),
+              SEEK_CUR)) {
+        return ferror(source) ? ZE_READ : ZE_EOF;
+    }
+
+    /* Encrypt data */
+    for (n = z->siz - RAND_HEAD_LEN; n; n--) {
+        if ((c = getc(source)) == EOF) {
+            return ferror(source) ? ZE_READ : ZE_EOF;
+        }
+        ztemp = zencode(c, t);
+        putc(ztemp, dest);
+    }
+    /* Skip extended local header in input file if there is one */
+    if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) {
+        return ferror(source) ? ZE_READ : ZE_EOF;
+    }
+    if (fflush(dest) == EOF) return ZE_TEMP;
+
+    /* Update number of bytes written to output file */
+    tempzn += (4 + LOCHEAD) + z->nam + z->ext + z->siz;
+
+    return ZE_OK;
+}
+
+/***********************************************************************
+ * Decrypt the zip entry described by z from file source to file dest
+ * using the password passwd.  Return an error code in the ZE_ class.
+ */
+int zipbare(z, source, dest, passwd)
+    struct zlist far *z;  /* zip entry to encrypt */
+    FILE *source, *dest;  /* source and destination files */
+    ZCONST char *passwd;  /* password string */
+{
+    int c0, c1;           /* last two input bytes */
+    ulg offset;           /* used for file offsets */
+    ulg size;             /* size of input data */
+    int r;                /* size of encryption header */
+    int res;              /* return code */
+    ush flag;             /* previous flags */
+
+    /* Save position and skip local header in input file */
+    if ((offset = (ulg)ftell(source)) == (ulg)-1L ||
+        fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext),
+              SEEK_CUR)) {
+        return ferror(source) ? ZE_READ : ZE_EOF;
+    }
+    /* Initialize keys with password */
+    init_keys(passwd);
+
+    /* Decrypt encryption header, save last two bytes */
+    c1 = 0;
+    for (r = RAND_HEAD_LEN; r; r--) {
+        c0 = c1;
+        if ((c1 = getc(source)) == EOF) {
+            return ferror(source) ? ZE_READ : ZE_EOF;
+        }
+        Trace((stdout, " (%02x)", c1));
+        zdecode(c1);
+        Trace((stdout, " %02x", c1));
+    }
+    Trace((stdout, "\n"));
+
+    /* If last two bytes of header don't match crc (or file time in the
+     * case of an extended local header), back up and just copy. For
+     * pkzip 2.0, the check has been reduced to one byte only.
+     */
+#ifdef ZIP10
+    if ((ush)(c0 | (c1<<8)) !=
+        (z->flg & 8 ? (ush) z->tim & 0xffff : (ush)(z->crc >> 16))) {
+#else
+    c0++; /* avoid warning on unused variable */
+    if ((ush)c1 != (z->flg & 8 ? (ush) z->tim >> 8 : (ush)(z->crc >> 24))) {
+#endif
+        if (fseek(source, offset, SEEK_SET)) {
+            return ferror(source) ? ZE_READ : ZE_EOF;
+        }
+        if ((res = zipcopy(z, source, dest)) != ZE_OK) return res;
+        return ZE_MISS;
+    }
+
+    /* Clear encrypted bit and local header bit, and write local header to
+       output file */
+    if ((offset = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP;
+    z->off = offset;
+    flag = z->flg;
+    z->flg &= ~9;
+    z->lflg &= ~9;
+    z->siz -= RAND_HEAD_LEN;
+    if ((res = putlocal(z, dest)) != ZE_OK) return res;
+
+    /* Decrypt data */
+    for (size = z->siz; size; size--) {
+        if ((c1 = getc(source)) == EOF) {
+            return ferror(source) ? ZE_READ : ZE_EOF;
+        }
+        zdecode(c1);
+        putc(c1, dest);
+    }
+    /* Skip extended local header in input file if there is one */
+    if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) {
+        return ferror(source) ? ZE_READ : ZE_EOF;
+    }
+    if (fflush(dest) == EOF) return ZE_TEMP;
+
+    /* Update number of bytes written to output file */
+    tempzn += (4 + LOCHEAD) + z->nam + z->ext + z->siz;
+
+    return ZE_OK;
+}
+
+
+#else /* !UTIL */
+
+/***********************************************************************
+ * If requested, encrypt the data in buf, and in any case call fwrite()
+ * with the arguments to zfwrite().  Return what fwrite() returns.
+ */
+unsigned zfwrite(buf, item_size, nb, f)
+    zvoid *buf;                 /* data buffer */
+    extent item_size;           /* size of each item in bytes */
+    extent nb;                  /* number of items */
+    FILE *f;                    /* file to write to */
+{
+    int t;                      /* temporary */
+
+    if (key != (char *)NULL) {  /* key is the global password pointer */
+        ulg size;               /* buffer size */
+        char *p = (char*)buf;   /* steps through buffer */
+
+        /* Encrypt data in buffer */
+        for (size = item_size*(ulg)nb; size != 0; p++, size--) {
+            *p = (char)zencode(*p, t);
+        }
+    }
+    /* Write the buffer out */
+    return fwrite(buf, item_size, nb, f);
+}
+
+#endif /* ?UTIL */
+#endif /* ZIP */
+
+
+#if (defined(UNZIP) && !defined(FUNZIP))
+
+/***********************************************************************
+ * Get the password and set up keys for current zipfile member.
+ * Return PK_ class error.
+ */
+int decrypt(__G__ passwrd)
+    __GDEF
+    ZCONST char *passwrd;
+{
+    ush b;
+    int n, r;
+    uch h[RAND_HEAD_LEN];
+
+    Trace((stdout, "\n[incnt = %d]: ", GLOBAL(incnt)));
+
+    /* get header once (turn off "encrypted" flag temporarily so we don't
+     * try to decrypt the same data twice) */
+    GLOBAL(pInfo->encrypted) = FALSE;
+    defer_leftover_input(__G);
+    for (n = 0; n < RAND_HEAD_LEN; n++) {
+        b = NEXTBYTE;
+        h[n] = (uch)b;
+        Trace((stdout, " (%02x)", h[n]));
+    }
+    undefer_input(__G);
+    GLOBAL(pInfo->encrypted) = TRUE;
+
+    if (GLOBAL(newzip)) { /* this is first encrypted member in this zipfile */
+        GLOBAL(newzip) = FALSE;
+        if (passwrd != (char *)NULL) { /* user gave password on command line */
+            if (!GLOBAL(key)) {
+                if ((GLOBAL(key) = (char *)malloc(strlen(passwrd)+1)) ==
+                    (char *)NULL)
+                    return PK_MEM2;
+                strcpy(GLOBAL(key), passwrd);
+                GLOBAL(nopwd) = TRUE;  /* inhibit password prompting! */
+            }
+        } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */
+            free(GLOBAL(key));
+            GLOBAL(key) = (char *)NULL;
+        }
+    }
+
+    /* if have key already, test it; else allocate memory for it */
+    if (GLOBAL(key)) {
+        if (!testp(__G__ h))
+            return PK_COOL;   /* existing password OK (else prompt for new) */
+        else if (GLOBAL(nopwd))
+            return PK_WARN;   /* user indicated no more prompting */
+    } else if ((GLOBAL(key) = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL)
+        return PK_MEM2;
+
+    /* try a few keys */
+    n = 0;
+    do {
+        r = (*G.decr_passwd)((zvoid *)&G, &n, GLOBAL(key), IZ_PWLEN+1,
+                             GLOBAL(zipfn), GLOBAL(filename));
+        if (r == IZ_PW_ERROR) {         /* internal error in fetch of PW */
+            free (GLOBAL(key));
+            GLOBAL(key) = NULL;
+            return PK_MEM2;
+        }
+        if (r != IZ_PW_ENTERED) {       /* user replied "skip" or "skip all" */
+            *GLOBAL(key) = '\0';        /*   We try the NIL password, ... */
+            n = 0;                      /*   and cancel fetch for this item. */
+        }
+        if (!testp(__G__ h))
+            return PK_COOL;
+        if (r == IZ_PW_CANCELALL)       /* User replied "Skip all" */
+            GLOBAL(nopwd) = TRUE;       /*   inhibit any further PW prompt! */
+    } while (n > 0);
+
+    return PK_WARN;
+
+} /* end function decrypt() */
+
+
+
+/***********************************************************************
+ * Test the password.  Return -1 if bad, 0 if OK.
+ */
+local int testp(__G__ h)
+    __GDEF
+    ZCONST uch *h;
+{
+    int r;
+    char *key_translated;
+
+    /* On systems with "obscure" native character coding (e.g., EBCDIC),
+     * the first test translates the password to the "main standard"
+     * character coding. */
+
+#ifdef STR_TO_CP1
+    /* allocate buffer for translated password */
+    if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL)
+        return -1;
+    /* first try, test password translated "standard" charset */
+    r = testkey(__G__ h, STR_TO_CP1(key_translated, GLOBAL(key)));
+#else /* !STR_TO_CP1 */
+    /* first try, test password as supplied on the extractor's host */
+    r = testkey(__G__ h, GLOBAL(key));
+#endif /* ?STR_TO_CP1 */
+
+#ifdef STR_TO_CP2
+    if (r != 0) {
+#ifndef STR_TO_CP1
+        /* now prepare for second (and maybe third) test with translated pwd */
+        if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL)
+            return -1;
+#endif
+        /* second try, password translated to alternate ("standard") charset */
+        r = testkey(__G__ h, STR_TO_CP2(key_translated, GLOBAL(key)));
+#ifdef STR_TO_CP3
+        if (r != 0)
+            /* third try, password translated to another "standard" charset */
+            r = testkey(__G__ h, STR_TO_CP3(key_translated, GLOBAL(key)));
+#endif
+#ifndef STR_TO_CP1
+        free(key_translated);
+#endif
+    }
+#endif /* STR_TO_CP2 */
+
+#ifdef STR_TO_CP1
+    free(key_translated);
+    if (r != 0) {
+        /* last resort, test password as supplied on the extractor's host */
+        r = testkey(__G__ h, GLOBAL(key));
+    }
+#endif /* STR_TO_CP1 */
+
+    return r;
+
+} /* end function testp() */
+
+
+local int testkey(__G__ h, key)
+    __GDEF
+    ZCONST uch *h;      /* decrypted header */
+    ZCONST char *key;   /* decryption password to test */
+{
+    ush b;
+#ifdef ZIP10
+    ush c;
+#endif
+    int n;
+    uch *p;
+    uch hh[RAND_HEAD_LEN]; /* decrypted header */
+
+    /* set keys and save the encrypted header */
+    init_keys(__G__ key);
+    memcpy(hh, h, RAND_HEAD_LEN);
+
+    /* check password */
+    for (n = 0; n < RAND_HEAD_LEN; n++) {
+        zdecode(hh[n]);
+        Trace((stdout, " %02x", hh[n]));
+    }
+
+    Trace((stdout,
+      "\n  lrec.crc= %08lx  crec.crc= %08lx  pInfo->ExtLocHdr= %s\n",
+      GLOBAL(lrec.crc32), GLOBAL(pInfo->crc),
+      GLOBAL(pInfo->ExtLocHdr) ? "true":"false"));
+    Trace((stdout, "  incnt = %d  unzip offset into zipfile = %ld\n",
+      GLOBAL(incnt),
+      GLOBAL(cur_zipfile_bufstart)+(GLOBAL(inptr)-GLOBAL(inbuf))));
+
+    /* same test as in zipbare(): */
+
+#ifdef ZIP10 /* check two bytes */
+    c = hh[RAND_HEAD_LEN-2], b = hh[RAND_HEAD_LEN-1];
+    Trace((stdout,
+      "  (c | (b<<8)) = %04x  (crc >> 16) = %04x  lrec.time = %04x\n",
+      (ush)(c | (b<<8)), (ush)(GLOBAL(lrec.crc32) >> 16),
+      ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff))));
+    if ((ush)(c | (b<<8)) != (GLOBAL(pInfo->ExtLocHdr) ?
+                           ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff) :
+                           (ush)(GLOBAL(lrec.crc32) >> 16)))
+        return -1;  /* bad */
+#else
+    b = hh[RAND_HEAD_LEN-1];
+    Trace((stdout, "  b = %02x  (crc >> 24) = %02x  (lrec.time >> 8) = %02x\n",
+      b, (ush)(GLOBAL(lrec.crc32) >> 24),
+      ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff));
+    if (b != (GLOBAL(pInfo->ExtLocHdr) ?
+        ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff :
+        (ush)(GLOBAL(lrec.crc32) >> 24)))
+        return -1;  /* bad */
+#endif
+    /* password OK:  decrypt current buffer contents before leaving */
+    for (n = (long)GLOBAL(incnt) > GLOBAL(csize) ?
+             (int)GLOBAL(csize) : GLOBAL(incnt),
+         p = GLOBAL(inptr); n--; p++)
+        zdecode(*p);
+    return 0;       /* OK */
+
+} /* end function testkey() */
+
+#endif /* UNZIP && !FUNZIP */
+
+#else /* !CRYPT */
+
+/* something "externally visible" to shut up compiler/linker warnings */
+int zcr_dummy;
+
+#endif /* ?CRYPT */
diff --git a/crypt.h b/crypt.h
new file mode 100644 (file)
index 0000000..af8a069
--- /dev/null
+++ b/crypt.h
@@ -0,0 +1,175 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+  crypt.h (full version) by Info-ZIP.   Last revised:  [see CR_VERSION_DATE]
+
+  This encryption/decryption source code for Info-Zip software was
+  originally written in Europe.  The whole source package can be
+  freely distributed, including from the USA.  (Prior to January 2000,
+  re-export from the US was a violation of US law.)
+
+  NOTE on copyright history:
+  Previous versions of this source package (up to version 2.8) were
+  not copyrighted and put in the public domain.  If you cannot comply
+  with the Info-Zip LICENSE, you may want to look for one of those
+  public domain versions.
+ */
+
+#ifndef __crypt_h   /* don't include more than once */
+#define __crypt_h
+
+#ifdef CRYPT
+#  undef CRYPT
+#endif
+/*
+   Logic of selecting "full crypt" code:
+   a) default behaviour:
+      - dummy crypt code when compiling UnZipSFX stub, to minimize size
+      - full crypt code when used to compile Zip, UnZip and fUnZip
+   b) USE_CRYPT defined:
+      - always full crypt code
+   c) NO_CRYPT defined:
+      - never full crypt code
+   NO_CRYPT takes precedence over USE_CRYPT
+ */
+#if defined(NO_CRYPT)
+#  define CRYPT  0  /* dummy version */
+#else
+#if defined(USE_CRYPT)
+#  define CRYPT  1  /* full version */
+#else
+#if !defined(SFX)
+#  define CRYPT  1  /* full version for zip and main unzip*/
+#else
+#  define CRYPT  0  /* dummy version for unzip sfx */
+#endif
+#endif /* ?USE_CRYPT */
+#endif /* ?NO_CRYPT */
+
+#if CRYPT
+/* full version */
+
+#ifdef CR_BETA
+#  undef CR_BETA    /* this is not a beta release */
+#endif
+
+#define CR_MAJORVER        2
+#define CR_MINORVER        9
+#ifdef CR_BETA
+#  define CR_BETA_VER      "a BETA"
+#  define CR_VERSION_DATE  "05 May 2000"       /* last real code change */
+#else
+#  define CR_BETA_VER      ""
+#  define CR_VERSION_DATE  "05 May 2000"       /* last public release date */
+#  define CR_RELEASE
+#endif
+
+#ifndef __G         /* UnZip only, for now (DLL stuff) */
+#  define __G
+#  define __G__
+#  define __GDEF
+#  define __GPRO    void
+#  define __GPRO__
+#endif
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32)
+#  ifndef DOS_OS2_W32
+#    define DOS_OS2_W32
+#  endif
+#endif
+
+#if defined(DOS_OS2_W32) || defined(__human68k__)
+#  ifndef DOS_H68_OS2_W32
+#    define DOS_H68_OS2_W32
+#  endif
+#endif
+
+#if defined(VM_CMS) || defined(MVS)
+#  ifndef CMS_MVS
+#    define CMS_MVS
+#  endif
+#endif
+
+/* To allow combining of Zip and UnZip static libraries in a single binary,
+ * the Zip and UnZip versions of the crypt core functions have to be named
+ * differently.
+ */
+#ifdef ZIP
+#  ifdef REALLY_SHORT_SYMS
+#    define decrypt_byte   zdcrby
+#  else
+#    define decrypt_byte   zp_decrypt_byte
+#  endif
+#  define  update_keys     zp_update_keys
+#  define  init_keys       zp_init_keys
+#else /* !ZIP */
+#  ifdef REALLY_SHORT_SYMS
+#    define decrypt_byte   dcrbyt
+#  endif
+#endif /* ?ZIP */
+
+#define IZ_PWLEN  80    /* input buffer size for reading encryption key */
+#ifndef PWLEN           /* for compatibility with previous zcrypt release... */
+#  define PWLEN IZ_PWLEN
+#endif
+#define RAND_HEAD_LEN  12       /* length of encryption random header */
+
+/* the crc_32_tab array has to be provided externally for the crypt calculus */
+#ifndef CRC_32_TAB                   /* UnZip provides this in globals.h */
+# if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
+   extern ZCONST ulg near *crc_32_tab;
+# else
+   extern ZCONST ulg Far *crc_32_tab;
+# endif
+#endif /* !CRC_32_TAB */
+
+/* encode byte c, using temp t.  Warning: c must not have side effects. */
+#define zencode(c,t)  (t=decrypt_byte(__G), update_keys(c), t^(c))
+
+/* decode byte c in place */
+#define zdecode(c)   update_keys(__G__ c ^= decrypt_byte(__G))
+
+int  decrypt_byte OF((__GPRO));
+int  update_keys OF((__GPRO__ int c));
+void init_keys OF((__GPRO__ ZCONST char *passwd));
+
+#ifdef ZIP
+   void crypthead OF((ZCONST char *, ulg, FILE *));
+#  ifdef UTIL
+     int zipcloak OF((struct zlist far *, FILE *, FILE *, ZCONST char *));
+     int zipbare OF((struct zlist far *, FILE *, FILE *, ZCONST char *));
+#  else
+     unsigned zfwrite OF((zvoid *, extent, extent, FILE *));
+     extern char *key;
+#  endif
+#endif /* ZIP */
+
+#if (defined(UNZIP) && !defined(FUNZIP))
+   int  decrypt OF((__GPRO__ ZCONST char *passwrd));
+#endif
+
+#ifdef FUNZIP
+   extern int encrypted;
+#  ifdef NEXTBYTE
+#    undef NEXTBYTE
+#  endif
+#  define NEXTBYTE \
+   (encrypted? update_keys(__G__ getc(G.in)^decrypt_byte(__G)) : getc(G.in))
+#endif /* FUNZIP */
+
+#else /* !CRYPT */
+/* dummy version */
+
+#define zencode
+#define zdecode
+
+#define zfwrite  fwrite
+
+#endif /* ?CRYPT */
+#endif /* !__crypt_h */
diff --git a/deflate.c b/deflate.c
new file mode 100644 (file)
index 0000000..96abbb1
--- /dev/null
+++ b/deflate.c
@@ -0,0 +1,902 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *  deflate.c by Jean-loup Gailly.
+ *
+ *  PURPOSE
+ *
+ *      Identify new text as repetitions of old text within a fixed-
+ *      length sliding window trailing behind the new text.
+ *
+ *  DISCUSSION
+ *
+ *      The "deflation" process depends on being able to identify portions
+ *      of the input text which are identical to earlier input (within a
+ *      sliding window trailing behind the input currently being processed).
+ *
+ *      The most straightforward technique turns out to be the fastest for
+ *      most input files: try all possible matches and select the longest.
+ *      The key feature of this algorithm is that insertions into the string
+ *      dictionary are very simple and thus fast, and deletions are avoided
+ *      completely. Insertions are performed at each input character, whereas
+ *      string matches are performed only when the previous match ends. So it
+ *      is preferable to spend more time in matches to allow very fast string
+ *      insertions and avoid deletions. The matching algorithm for small
+ *      strings is inspired from that of Rabin & Karp. A brute force approach
+ *      is used to find longer strings when a small match has been found.
+ *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ *      (by Leonid Broukhis).
+ *         A previous version of this file used a more sophisticated algorithm
+ *      (by Fiala and Greene) which is guaranteed to run in linear amortized
+ *      time, but has a larger average cost, uses more memory and is patented.
+ *      However the F&G algorithm may be faster for some highly redundant
+ *      files if the parameter max_chain_length (described below) is too large.
+ *
+ *  ACKNOWLEDGEMENTS
+ *
+ *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ *      I found it in 'freeze' written by Leonid Broukhis.
+ *      Thanks to many info-zippers for bug reports and testing.
+ *
+ *  REFERENCES
+ *
+ *      APPNOTE.TXT documentation file in PKZIP 1.93a distribution.
+ *
+ *      A description of the Rabin and Karp algorithm is given in the book
+ *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ *      Fiala,E.R., and Greene,D.H.
+ *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ *  INTERFACE
+ *
+ *      void lm_init (int pack_level, ush *flags)
+ *          Initialize the "longest match" routines for a new file
+ *
+ *      ulg deflate (void)
+ *          Processes a new input file and return its compressed length. Sets
+ *          the compressed length, crc, deflate flags and internal file
+ *          attributes.
+ */
+
+#define __DEFLATE_C
+
+#include "zip.h"
+
+#ifndef USE_ZLIB
+
+/* ===========================================================================
+ * Configuration parameters
+ */
+
+/* Compile with MEDIUM_MEM to reduce the memory requirements or
+ * with SMALL_MEM to use as little memory as possible. Use BIG_MEM if the
+ * entire input file can be held in memory (not possible on 16 bit systems).
+ * Warning: defining these symbols affects HASH_BITS (see below) and thus
+ * affects the compression ratio. The compressed output
+ * is still correct, and might even be smaller in some cases.
+ */
+
+#ifdef SMALL_MEM
+#   define HASH_BITS  13  /* Number of bits used to hash strings */
+#endif
+#ifdef MEDIUM_MEM
+#   define HASH_BITS  14
+#endif
+#ifndef HASH_BITS
+#   define HASH_BITS  15
+   /* For portability to 16 bit machines, do not use values above 15. */
+#endif
+
+#define HASH_SIZE (unsigned)(1<<HASH_BITS)
+#define HASH_MASK (HASH_SIZE-1)
+#define WMASK     (WSIZE-1)
+/* HASH_SIZE and WSIZE must be powers of two */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#define FAST 4
+#define SLOW 2
+/* speed options for the general purpose bit flag */
+
+#ifndef TOO_FAR
+#  define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#if (defined(ASMV) && !defined(MSDOS16) && defined(DYN_ALLOC))
+   error: DYN_ALLOC not yet supported in match.S or match32.asm
+#endif
+
+#ifdef MEMORY16
+#  define MAXSEG_64K
+#endif
+
+/* ===========================================================================
+ * Local data used by the "longest match" routines.
+ */
+
+#if defined(MMAP) || defined(BIG_MEM)
+  typedef unsigned Pos; /* must be at least 32 bits */
+#else
+  typedef ush Pos;
+#endif
+typedef unsigned IPos;
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+#ifndef DYN_ALLOC
+  uch    window[2L*WSIZE];
+  /* Sliding window. Input bytes are read into the second half of the window,
+   * and move to the first half later to keep a dictionary of at least WSIZE
+   * bytes. With this organization, matches are limited to a distance of
+   * WSIZE-MAX_MATCH bytes, but this ensures that IO is always
+   * performed with a length multiple of the block size. Also, it limits
+   * the window size to 64K, which is quite useful on MSDOS.
+   * To do: limit the window size to WSIZE+CBSZ if SMALL_MEM (the code would
+   * be less efficient since the data would have to be copied WSIZE/CBSZ times)
+   */
+  Pos    prev[WSIZE];
+  /* Link to older string with same hash index. To limit the size of this
+   * array to 64K, this link is maintained only for the last 32K strings.
+   * An index in this array is thus a window index modulo 32K.
+   */
+  Pos    head[HASH_SIZE];
+  /* Heads of the hash chains or NIL. If your compiler thinks that
+   * HASH_SIZE is a dynamic value, recompile with -DDYN_ALLOC.
+   */
+#else
+  uch far * near window = NULL;
+  Pos far * near prev   = NULL;
+  Pos far * near head;
+#endif
+ulg window_size;
+/* window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the
+ * input file length plus MIN_LOOKAHEAD.
+ */
+
+long block_start;
+/* window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+local int sliding;
+/* Set to false when the input file is already in memory */
+
+local unsigned ins_h;  /* hash index of string to be inserted */
+
+#define H_SHIFT  ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)
+/* Number of bits by which ins_h and del_h must be shifted at each
+ * input step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ *   H_SHIFT * MIN_MATCH >= HASH_BITS
+ */
+
+unsigned int near prev_length;
+/* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+      unsigned near strstart;      /* start of string to insert */
+      unsigned near match_start;   /* start of matching string */
+local int           eofile;        /* flag set at end of input file */
+local unsigned      lookahead;     /* number of valid bytes ahead in window */
+
+unsigned near max_chain_length;
+/* To speed up deflation, hash chains are never searched beyond this length.
+ * A higher limit improves compression ratio but degrades the speed.
+ */
+
+local unsigned int max_lazy_match;
+/* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+#define max_insert_length  max_lazy_match
+/* Insert new strings in the hash table only if the match length
+ * is not greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+unsigned near good_match;
+/* Use a faster search when the previous match is longer than this */
+
+#ifdef  FULL_SEARCH
+# define nice_match MAX_MATCH
+#else
+  int near nice_match; /* Stop searching when current match exceeds this */
+#endif
+
+
+/* Values for max_lazy_match, good_match, nice_match and max_chain_length,
+ * depending on the desired pack level (0..9). The values given below have
+ * been tuned to exclude worst case performance for pathological files.
+ * Better values may be found for specific files.
+ */
+
+typedef struct config {
+   ush good_length; /* reduce lazy search above this match length */
+   ush max_lazy;    /* do not perform lazy search above this match length */
+   ush nice_length; /* quit search above this match length */
+   ush max_chain;
+} config;
+
+local config configuration_table[10] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0},  /* store only */
+/* 1 */ {4,    4,  8,    4},  /* maximum speed, no lazy matches */
+/* 2 */ {4,    5, 16,    8},
+/* 3 */ {4,    6, 32,   32},
+
+/* 4 */ {4,    4, 16,   16},  /* lazy matches */
+/* 5 */ {8,   16, 32,   32},
+/* 6 */ {8,   16, 128, 128},
+/* 7 */ {8,   32, 128, 256},
+/* 8 */ {32, 128, 258, 1024},
+/* 9 */ {32, 258, 258, 4096}}; /* maximum compression */
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+/* ===========================================================================
+ *  Prototypes for local functions.
+ */
+
+local void fill_window   OF((void));
+local ulg deflate_fast   OF((void));
+
+      int  longest_match OF((IPos cur_match));
+#if defined(ASMV) && !defined(RISCOS)
+      void match_init OF((void)); /* asm code initialization */
+#endif
+
+#ifdef DEBUG
+local  void check_match OF((IPos start, IPos match, int length));
+#endif
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
+ *    input characters, so that a running hash key can be computed from the
+ *    previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK)
+
+/* ===========================================================================
+ * Insert string s in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * IN  assertion: all calls to to INSERT_STRING are made with consecutive
+ *    input characters and the first MIN_MATCH bytes of s are valid
+ *    (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#define INSERT_STRING(s, match_head) \
+   (UPDATE_HASH(ins_h, window[(s) + (MIN_MATCH-1)]), \
+    prev[(s) & WMASK] = match_head = head[ins_h], \
+    head[ins_h] = (s))
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new file
+ *
+ * IN assertion: window_size is > 0 if the input file is already read or
+ *    mmap'ed in the window[] array, 0 otherwise. In the first case,
+ *    window_size is sufficient to contain the whole input file plus
+ *    MIN_LOOKAHEAD bytes (to avoid referencing memory beyond the end
+ *    of window[] when looking for matches towards the end).
+ */
+void lm_init (pack_level, flags)
+    int pack_level; /* 0: store, 1: best speed, 9: best compression */
+    ush *flags;     /* general purpose bit flag */
+{
+    register unsigned j;
+
+    if (pack_level < 1 || pack_level > 9) error("bad pack level");
+
+    /* Do not slide the window if the whole input is already in memory
+     * (window_size > 0)
+     */
+    sliding = 0;
+    if (window_size == 0L) {
+        sliding = 1;
+        window_size = (ulg)2L*WSIZE;
+    }
+
+    /* Use dynamic allocation if compiler does not like big static arrays: */
+#ifdef DYN_ALLOC
+    if (window == NULL) {
+        window = (uch far *) zcalloc(WSIZE,   2*sizeof(uch));
+        if (window == NULL) ziperr(ZE_MEM, "window allocation");
+    }
+    if (prev == NULL) {
+        prev   = (Pos far *) zcalloc(WSIZE,     sizeof(Pos));
+        head   = (Pos far *) zcalloc(HASH_SIZE, sizeof(Pos));
+        if (prev == NULL || head == NULL) {
+            ziperr(ZE_MEM, "hash table allocation");
+        }
+    }
+#endif /* DYN_ALLOC */
+
+    /* Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+     * prev[] will be initialized on the fly.
+     */
+    head[HASH_SIZE-1] = NIL;
+    memset((char*)head, NIL, (unsigned)(HASH_SIZE-1)*sizeof(*head));
+
+    /* Set the default configuration parameters:
+     */
+    max_lazy_match   = configuration_table[pack_level].max_lazy;
+    good_match       = configuration_table[pack_level].good_length;
+#ifndef FULL_SEARCH
+    nice_match       = configuration_table[pack_level].nice_length;
+#endif
+    max_chain_length = configuration_table[pack_level].max_chain;
+    if (pack_level <= 2) {
+       *flags |= FAST;
+    } else if (pack_level >= 8) {
+       *flags |= SLOW;
+    }
+    /* ??? reduce max_chain_length for binary files */
+
+    strstart = 0;
+    block_start = 0L;
+#if defined(ASMV) && !defined(RISCOS)
+    match_init(); /* initialize the asm code */
+#endif
+
+    j = WSIZE;
+#ifndef MAXSEG_64K
+    if (sizeof(int) > 2) j <<= 1; /* Can read 64K in one step */
+#endif
+    lookahead = (*read_buf)((char*)window, j);
+
+    if (lookahead == 0 || lookahead == (unsigned)EOF) {
+       eofile = 1, lookahead = 0;
+       return;
+    }
+    eofile = 0;
+    /* Make sure that we always have enough lookahead. This is important
+     * if input comes from a device such as a tty.
+     */
+    if (lookahead < MIN_LOOKAHEAD) fill_window();
+
+    ins_h = 0;
+    for (j=0; j<MIN_MATCH-1; j++) UPDATE_HASH(ins_h, window[j]);
+    /* If lookahead < MIN_MATCH, ins_h is garbage, but this is
+     * not important since only literal bytes will be emitted.
+     */
+}
+
+/* ===========================================================================
+ * Free the window and hash table
+ */
+void lm_free()
+{
+#ifdef DYN_ALLOC
+    if (window != NULL) {
+        zcfree(window);
+        window = NULL;
+    }
+    if (prev != NULL) {
+        zcfree(prev);
+        zcfree(head);
+        prev = head = NULL;
+    }
+#endif /* DYN_ALLOC */
+}
+
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0 and ARM, an optimized version is in match.asm or
+ * match.S. The code is functionally equivalent, so you can use the C version
+ * if desired.
+ */
+int longest_match(cur_match)
+    IPos cur_match;                             /* current match */
+{
+    unsigned chain_length = max_chain_length;   /* max hash chain length */
+    register uch far *scan = window + strstart; /* current string */
+    register uch far *match;                    /* matched string */
+    register int len;                           /* length of current match */
+    int best_len = prev_length;                 /* best match length so far */
+    IPos limit = strstart > (IPos)MAX_DIST ? strstart - (IPos)MAX_DIST : NIL;
+    /* Stop when cur_match becomes <= limit. To simplify the code,
+     * we prevent matches with the string of window index 0.
+     */
+
+/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+#if HASH_BITS < 8 || MAX_MATCH != 258
+   error: Code too clever
+#endif
+
+#ifdef UNALIGNED_OK
+    /* Compare two bytes at a time. Note: this is not always beneficial.
+     * Try with and without -DUNALIGNED_OK to check.
+     */
+    register uch far *strend = window + strstart + MAX_MATCH - 1;
+    register ush scan_start = *(ush far *)scan;
+    register ush scan_end   = *(ush far *)(scan+best_len-1);
+#else
+    register uch far *strend = window + strstart + MAX_MATCH;
+    register uch scan_end1  = scan[best_len-1];
+    register uch scan_end   = scan[best_len];
+#endif
+
+    /* Do not waste too much time if we already have a good match: */
+    if (prev_length >= good_match) {
+        chain_length >>= 2;
+    }
+
+    Assert(strstart <= window_size-MIN_LOOKAHEAD, "insufficient lookahead");
+
+    do {
+        Assert(cur_match < strstart, "no future");
+        match = window + cur_match;
+
+        /* Skip to next match if the match length cannot increase
+         * or if the match length is less than 2:
+         */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+        /* This code assumes sizeof(unsigned short) == 2. Do not use
+         * UNALIGNED_OK if your compiler uses a different size.
+         */
+        if (*(ush far *)(match+best_len-1) != scan_end ||
+            *(ush far *)match != scan_start) continue;
+
+        /* It is not necessary to compare scan[2] and match[2] since they are
+         * always equal when the other bytes match, given that the hash keys
+         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+         * strstart+3, +5, ... up to strstart+257. We check for insufficient
+         * lookahead only every 4th comparison; the 128th check will be made
+         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+         * necessary to put more guard bytes at the end of the window, or
+         * to check more often for insufficient lookahead.
+         */
+        scan++, match++;
+        do {
+        } while (*(ush far *)(scan+=2) == *(ush far *)(match+=2) &&
+                 *(ush far *)(scan+=2) == *(ush far *)(match+=2) &&
+                 *(ush far *)(scan+=2) == *(ush far *)(match+=2) &&
+                 *(ush far *)(scan+=2) == *(ush far *)(match+=2) &&
+                 scan < strend);
+        /* The funny "do {}" generates better code on most compilers */
+
+        /* Here, scan <= window+strstart+257 */
+        Assert(scan <= window+(unsigned)(window_size-1), "wild scan");
+        if (*scan == *match) scan++;
+
+        len = (MAX_MATCH - 1) - (int)(strend-scan);
+        scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+        if (match[best_len]   != scan_end  ||
+            match[best_len-1] != scan_end1 ||
+            *match            != *scan     ||
+            *++match          != scan[1])      continue;
+
+        /* The check at best_len-1 can be removed because it will be made
+         * again later. (This heuristic is not always a win.)
+         * It is not necessary to compare scan[2] and match[2] since they
+         * are always equal when the other bytes match, given that
+         * the hash keys are equal and that HASH_BITS >= 8.
+         */
+        scan += 2, match++;
+
+        /* We check for insufficient lookahead only every 8th comparison;
+         * the 256th check will be made at strstart+258.
+         */
+        do {
+        } while (*++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 scan < strend);
+
+        Assert(scan <= window+(unsigned)(window_size-1), "wild scan");
+
+        len = MAX_MATCH - (int)(strend - scan);
+        scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+        if (len > best_len) {
+            match_start = cur_match;
+            best_len = len;
+            if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+            scan_end = *(ush far *)(scan+best_len-1);
+#else
+            scan_end1  = scan[best_len-1];
+            scan_end   = scan[best_len];
+#endif
+        }
+    } while ((cur_match = prev[cur_match & WMASK]) > limit
+             && --chain_length != 0);
+
+    return best_len;
+}
+#endif /* ASMV */
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(start, match, length)
+    IPos start, match;
+    int length;
+{
+    /* check that the match is indeed a match */
+    if (memcmp((char*)window + match,
+                (char*)window + start, length) != EQUAL) {
+        fprintf(stderr,
+            " start %d, match %d, length %d\n",
+            start, match, length);
+        error("invalid match");
+    }
+    if (verbose > 1) {
+        fprintf(stderr,"\\[%d,%d]", start-match, length);
+#ifndef WINDLL
+        do { putc(window[start++], stderr); } while (--length != 0);
+#else
+        do { fprintf(stdout,"%c",window[start++]); } while (--length != 0);
+#endif
+    }
+}
+#else
+#  define check_match(start, match, length)
+#endif
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead, and sets eofile if end of input file.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ *    At least one byte has been read, or eofile is set; file reads are
+ *    performed for at least two bytes (required for the translate_eol option).
+ */
+local void fill_window()
+{
+    register unsigned n, m;
+    unsigned more;    /* Amount of free space at the end of the window. */
+
+    do {
+        more = (unsigned)(window_size - (ulg)lookahead - (ulg)strstart);
+
+        /* If the window is almost full and there is insufficient lookahead,
+         * move the upper half to the lower one to make room in the upper half.
+         */
+        if (more == (unsigned)EOF) {
+            /* Very unlikely, but possible on 16 bit machine if strstart == 0
+             * and lookahead == 1 (input done one byte at time)
+             */
+            more--;
+
+        /* For MMAP or BIG_MEM, the whole input file is already in memory so
+         * we must not perform sliding. We must however call (*read_buf)() in
+         * order to compute the crc, update lookahead and possibly set eofile.
+         */
+        } else if (strstart >= WSIZE+MAX_DIST && sliding) {
+
+            /* By the IN assertion, the window is not empty so we can't confuse
+             * more == 0 with more == 64K on a 16 bit machine.
+             */
+            memcpy((char*)window, (char*)window+WSIZE, (unsigned)WSIZE);
+            match_start -= WSIZE;
+            strstart    -= WSIZE; /* we now have strstart >= MAX_DIST: */
+
+            block_start -= (long) WSIZE;
+
+            for (n = 0; n < HASH_SIZE; n++) {
+                m = head[n];
+                head[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);
+            }
+            for (n = 0; n < WSIZE; n++) {
+                m = prev[n];
+                prev[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);
+                /* If n is not on any hash chain, prev[n] is garbage but
+                 * its value will never be used.
+                 */
+            }
+            more += WSIZE;
+#ifndef WINDLL
+            if (verbose) putc('.', stderr);
+#else
+            if (verbose) fprintf(stdout,"%c",'.');
+#endif
+        }
+        if (eofile) return;
+
+        /* If there was no sliding:
+         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+         *    more == window_size - lookahead - strstart
+         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+         * => more >= window_size - 2*WSIZE + 2
+         * In the MMAP or BIG_MEM case (not yet supported in gzip),
+         *   window_size == input_size + MIN_LOOKAHEAD  &&
+         *   strstart + lookahead <= input_size => more >= MIN_LOOKAHEAD.
+         * Otherwise, window_size == 2*WSIZE so more >= 2.
+         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+         */
+        Assert(more >= 2, "more < 2");
+
+        n = (*read_buf)((char*)window+strstart+lookahead, more);
+        if (n == 0 || n == (unsigned)EOF) {
+            eofile = 1;
+        } else {
+            lookahead += n;
+        }
+    } while (lookahead < MIN_LOOKAHEAD && !eofile);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK(eof) \
+   flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \
+                (char*)NULL, (long)strstart - block_start, (eof))
+
+/* ===========================================================================
+ * Processes a new input file and return its compressed length. This
+ * function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local ulg deflate_fast()
+{
+    IPos hash_head = NIL;       /* head of the hash chain */
+    int flush;                  /* set if current block must be flushed */
+    unsigned match_length = 0;  /* length of best match */
+
+    prev_length = MIN_MATCH-1;
+    while (lookahead != 0) {
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+#ifndef DEFL_UNDETERM
+        if (lookahead >= MIN_MATCH)
+#endif
+        INSERT_STRING(strstart, hash_head);
+
+        /* Find the longest match, discarding those <= prev_length.
+         * At this point we have always match_length < MIN_MATCH
+         */
+        if (hash_head != NIL && strstart - hash_head <= MAX_DIST) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+#ifndef HUFFMAN_ONLY
+#  ifndef DEFL_UNDETERM
+            /* Do not look for matches beyond the end of the input.
+             * This is necessary to make deflate deterministic.
+             */
+            if ((unsigned)nice_match > lookahead) nice_match = (int)lookahead;
+#  endif
+            match_length = longest_match (hash_head);
+            /* longest_match() sets match_start */
+            if (match_length > lookahead) match_length = lookahead;
+#endif
+        }
+        if (match_length >= MIN_MATCH) {
+            check_match(strstart, match_start, match_length);
+
+            flush = ct_tally(strstart-match_start, match_length - MIN_MATCH);
+
+            lookahead -= match_length;
+
+            /* Insert new strings in the hash table only if the match length
+             * is not too large. This saves time but degrades compression.
+             */
+            if (match_length <= max_insert_length
+#ifndef DEFL_UNDETERM
+                && lookahead >= MIN_MATCH
+#endif
+                                                 ) {
+                match_length--; /* string at strstart already in hash table */
+                do {
+                    strstart++;
+                    INSERT_STRING(strstart, hash_head);
+                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+                     * always MIN_MATCH bytes ahead.
+                     */
+#ifdef DEFL_UNDETERM
+                    /* If lookahead < MIN_MATCH these bytes are garbage,
+                     * but it does not matter since the next lookahead bytes
+                     * will be emitted as literals.
+                     */
+#endif
+                } while (--match_length != 0);
+                strstart++;
+            } else {
+                strstart += match_length;
+                match_length = 0;
+                ins_h = window[strstart];
+                UPDATE_HASH(ins_h, window[strstart+1]);
+#if MIN_MATCH != 3
+                Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+            }
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c",window[strstart]));
+            flush = ct_tally (0, window[strstart]);
+            lookahead--;
+            strstart++;
+        }
+        if (flush) FLUSH_BLOCK(0), block_start = strstart;
+
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (lookahead < MIN_LOOKAHEAD) fill_window();
+    }
+    return FLUSH_BLOCK(1); /* eof */
+}
+
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+ulg deflate()
+{
+    IPos hash_head = NIL;       /* head of hash chain */
+    IPos prev_match;            /* previous match */
+    int flush;                  /* set if current block must be flushed */
+    int match_available = 0;    /* set if previous match exists */
+    register unsigned match_length = MIN_MATCH-1; /* length of best match */
+#ifdef DEBUG
+    extern ulg isize;           /* byte length of input file, for debug only */
+#endif
+
+    if (level <= 3) return deflate_fast(); /* optimized for speed */
+
+    /* Process the input block. */
+    while (lookahead != 0) {
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+#ifndef DEFL_UNDETERM
+        if (lookahead >= MIN_MATCH)
+#endif
+        INSERT_STRING(strstart, hash_head);
+
+        /* Find the longest match, discarding those <= prev_length.
+         */
+        prev_length = match_length, prev_match = match_start;
+        match_length = MIN_MATCH-1;
+
+        if (hash_head != NIL && prev_length < max_lazy_match &&
+            strstart - hash_head <= MAX_DIST) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+#ifndef HUFFMAN_ONLY
+#  ifndef DEFL_UNDETERM
+            /* Do not look for matches beyond the end of the input.
+             * This is necessary to make deflate deterministic.
+             */
+            if ((unsigned)nice_match > lookahead) nice_match = (int)lookahead;
+#  endif
+            match_length = longest_match (hash_head);
+            /* longest_match() sets match_start */
+            if (match_length > lookahead) match_length = lookahead;
+#endif
+
+#ifdef FILTERED
+            /* Ignore matches of length <= 5 */
+            if (match_length <= 5) {
+#else
+            /* Ignore a length 3 match if it is too distant: */
+            if (match_length == MIN_MATCH && strstart-match_start > TOO_FAR){
+#endif
+                /* If prev_match is also MIN_MATCH, match_start is garbage
+                 * but we will ignore the current match anyway.
+                 */
+                match_length = MIN_MATCH-1;
+            }
+        }
+        /* If there was a match at the previous step and the current
+         * match is not better, output the previous match:
+         */
+        if (prev_length >= MIN_MATCH && match_length <= prev_length) {
+#ifndef DEFL_UNDETERM
+            unsigned max_insert = strstart + lookahead - MIN_MATCH;
+
+#endif
+            check_match(strstart-1, prev_match, prev_length);
+
+            flush = ct_tally(strstart-1-prev_match, prev_length - MIN_MATCH);
+
+            /* Insert in hash table all strings up to the end of the match.
+             * strstart-1 and strstart are already inserted.
+             */
+            lookahead -= prev_length-1;
+            prev_length -= 2;
+#ifndef DEFL_UNDETERM
+            do {
+                if (++strstart <= max_insert) {
+                    INSERT_STRING(strstart, hash_head);
+                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+                     * always MIN_MATCH bytes ahead.
+                     */
+                }
+            } while (--prev_length != 0);
+            strstart++;
+#else /* DEFL_UNDETERM */
+            do {
+                strstart++;
+                INSERT_STRING(strstart, hash_head);
+                /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+                 * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
+                 * these bytes are garbage, but it does not matter since the
+                 * next lookahead bytes will always be emitted as literals.
+                 */
+            } while (--prev_length != 0);
+            strstart++;
+#endif /* ?DEFL_UNDETERM */
+            match_available = 0;
+            match_length = MIN_MATCH-1;
+
+            if (flush) FLUSH_BLOCK(0), block_start = strstart;
+
+        } else if (match_available) {
+            /* If there was no match at the previous position, output a
+             * single literal. If there was a match but the current match
+             * is longer, truncate the previous match to a single literal.
+             */
+            Tracevv((stderr,"%c",window[strstart-1]));
+            if (ct_tally (0, window[strstart-1])) {
+                FLUSH_BLOCK(0), block_start = strstart;
+            }
+            strstart++;
+            lookahead--;
+        } else {
+            /* There is no previous match to compare with, wait for
+             * the next step to decide.
+             */
+            match_available = 1;
+            strstart++;
+            lookahead--;
+        }
+        Assert(strstart <= isize && lookahead <= isize, "a bit too far");
+
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (lookahead < MIN_LOOKAHEAD) fill_window();
+    }
+    if (match_available) ct_tally (0, window[strstart-1]);
+
+    return FLUSH_BLOCK(1); /* eof */
+}
+#endif /* !USE_ZLIB */
diff --git a/ebcdic.h b/ebcdic.h
new file mode 100644 (file)
index 0000000..c22307e
--- /dev/null
+++ b/ebcdic.h
@@ -0,0 +1,284 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+  ebcdic.h
+
+  The CECP 1047 (Extended de-facto EBCDIC) <-> ISO 8859-1 conversion tables,
+  from ftp://aix1.segi.ulg.ac.be/pub/docs/iso8859/iso8859.networking
+
+  NOTES:
+  <Paul_von_Behren@stortek.com> (OS/390 port 12/97)
+   These table no longer represent the standard mappings (for example in the
+   OS/390 iconv utility).  In order to follow current standards I remapped
+     ebcdic x0a to ascii x15    and
+     ebcdic x85 to ascii x25    (and vice-versa)
+   Without these changes, newlines in auto-convert text files appeared
+   as literal \045.
+   I'm not sure what effect this remap would have on the MVS and CMS ports, so
+   I ifdef'd these changes.  Hopefully these ifdef's can be removed when the
+   MVS/CMS folks test the new mappings.
+
+  Christian Spieler <spieler@ikp.tu-darmstadt.de>, 27-Apr-1998
+   The problem mentioned by Paul von Behren was already observed previously
+   on VM/CMS, during the preparation of the CMS&MVS port of UnZip 5.20 in
+   1996. At that point, the ebcdic tables were not changed since they seemed
+   to be an adopted standard (to my knowledge, these tables are still used
+   as presented in mainfraime KERMIT). Instead, the "end-of-line" conversion
+   feature of Zip's and UnZip's "text-translation" mode was used to force
+   correct mappings between ASCII and EBCDIC newline markers.
+   Before interchanging the ASCII mappings of the EBCDIC control characters
+   "NL" 0x25 and "LF" 0x15 according to the OS/390 setting, we have to
+   make sure that EBCDIC 0x15 is never used as line termination.
+
+  ---------------------------------------------------------------------------*/
+
+#ifndef __ebcdic_h      /* prevent multiple inclusions */
+#define __ebcdic_h
+
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+
+#ifdef EBCDIC
+#ifndef MTS             /* MTS uses a slightly "special" EBCDIC code page */
+
+ZCONST uch ebcdic[] = {
+    0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,  /* 00 - 07 */
+#ifdef OS390
+    0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */
+#else
+    0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */
+#endif
+    0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,  /* 10 - 17 */
+    0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */
+    0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,  /* 20 - 27 */
+    0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,  /* 28 - 2F */
+    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,  /* 30 - 37 */
+    0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,  /* 38 - 3F */
+    0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,  /* 40 - 47 */
+    0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,  /* 48 - 4F */
+    0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,  /* 50 - 57 */
+    0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,  /* 58 - 5F */
+    0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,  /* 60 - 67 */
+    0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,  /* 68 - 6F */
+    0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,  /* 70 - 77 */
+    0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,  /* 78 - 7F */
+#ifdef OS390
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17,  /* 80 - 87 */
+#else
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,  /* 80 - 87 */
+#endif
+    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B,  /* 88 - 8F */
+    0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08,  /* 90 - 97 */
+    0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF,  /* 98 - 9F */
+    0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5,  /* A0 - A7 */
+    0xBB, 0xB4, 0x9A, 0x8A, 0xB0, 0xCA, 0xAF, 0xBC,  /* A8 - AF */
+    0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3,  /* B0 - B7 */
+    0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB,  /* B8 - BF */
+    0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68,  /* C0 - C7 */
+    0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,  /* C8 - CF */
+    0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF,  /* D0 - D7 */
+    0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xBA, 0xAE, 0x59,  /* D8 - DF */
+    0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48,  /* E0 - E7 */
+    0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,  /* E8 - EF */
+    0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1,  /* F0 - F7 */
+    0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF   /* F8 - FF */
+};
+
+#if (defined(ZIP) || CRYPT)
+ZCONST uch ascii[] = {
+    0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,  /* 00 - 07 */
+    0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */
+#ifdef OS390
+    0x10, 0x11, 0x12, 0x13, 0x9D, 0x0A, 0x08, 0x87,  /* 10 - 17 */
+#else
+    0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,  /* 10 - 17 */
+#endif
+    0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */
+#ifdef OS390
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1B,  /* 20 - 27 */
+#else
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,  /* 20 - 27 */
+#endif
+    0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,  /* 28 - 2F */
+    0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,  /* 30 - 37 */
+    0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,  /* 38 - 3F */
+    0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,  /* 40 - 47 */
+    0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,  /* 48 - 4F */
+    0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,  /* 50 - 57 */
+    0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,  /* 58 - 5F */
+    0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,  /* 60 - 67 */
+    0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,  /* 68 - 6F */
+    0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,  /* 70 - 77 */
+    0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,  /* 78 - 7F */
+    0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,  /* 80 - 87 */
+    0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,  /* 88 - 8F */
+    0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,  /* 90 - 97 */
+    0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,  /* 98 - 9F */
+    0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,  /* A0 - A7 */
+    0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE,  /* A8 - AF */
+    0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,  /* B0 - B7 */
+    0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7,  /* B8 - BF */
+    0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,  /* C0 - C7 */
+    0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,  /* C8 - CF */
+    0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,  /* D0 - D7 */
+    0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,  /* D8 - DF */
+    0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,  /* E0 - E7 */
+    0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,  /* E8 - EF */
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,  /* F0 - F7 */
+    0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F   /* F8 - FF */
+};
+#endif /* ZIP || CRYPT */
+
+#else /* MTS */
+
+/*
+ * This is the MTS ASCII->EBCDIC translation table. It provides a 1-1
+ * translation from ISO 8859/1 8-bit ASCII to IBM Code Page 37 EBCDIC.
+ */
+
+ZCONST uch ebcdic[] = {
+    0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,  /* 00 - 07 */
+    0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */
+    0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,  /* 10 - 17 */
+    0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */
+    0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,  /* 20 - 27 */
+    0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,  /* 28 - 2F */
+    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,  /* 30 - 37 */
+    0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,  /* 38 - 3F */
+    0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,  /* 40 - 47 */
+    0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,  /* 48 - 4F */
+    0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,  /* 50 - 57 */
+    0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,  /* 58 - 5F */
+    0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,  /* 60 - 67 */
+    0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,  /* 68 - 6F */
+    0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,  /* 70 - 77 */
+    0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,  /* 78 - 7F */
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,  /* 80 - 87 */
+    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B,  /* 88 - 8F */
+    0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08,  /* 90 - 97 */
+    0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF,  /* 98 - 9F */
+    0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5,  /* A0 - A7 */
+    0xBD, 0xB4, 0x9A, 0x8A, 0x5F, 0xCA, 0xAF, 0xBC,  /* A8 - AF */
+    0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3,  /* B0 - B7 */
+    0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB,  /* B8 - BF */
+    0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68,  /* C0 - C7 */
+    0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,  /* C8 - CF */
+    0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF,  /* D0 - D7 */
+    0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xAD, 0xAE, 0x59,  /* D8 - DF */
+    0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48,  /* E0 - E7 */
+    0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,  /* E8 - EF */
+    0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1,  /* F0 - F7 */
+    0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF   /* F8 - FF */
+};
+
+#if (defined(ZIP) || CRYPT)
+ZCONST uch ascii[] = {
+    0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,  /* 00 - 07 */
+    0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */
+    0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,  /* 10 - 17 */
+    0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,  /* 20 - 27 */
+    0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,  /* 28 - 2F */
+    0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,  /* 30 - 37 */
+    0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,  /* 38 - 3F */
+    0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,  /* 40 - 47 */
+    0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,  /* 48 - 4F */
+    0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,  /* 50 - 57 */
+    0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC,  /* 58 - 5F */
+    0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,  /* 60 - 67 */
+    0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,  /* 68 - 6F */
+    0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,  /* 70 - 77 */
+    0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,  /* 78 - 7F */
+    0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,  /* 80 - 87 */
+    0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,  /* 88 - 8F */
+    0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,  /* 90 - 97 */
+    0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,  /* 98 - 9F */
+    0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,  /* A0 - A7 */
+    0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE,  /* A8 - AF */
+    0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,  /* B0 - B7 */
+    0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7,  /* B8 - BF */
+    0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,  /* C0 - C7 */
+    0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,  /* C8 - CF */
+    0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,  /* D0 - D7 */
+    0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,  /* D8 - DF */
+    0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,  /* E0 - E7 */
+    0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,  /* E8 - EF */
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,  /* F0 - F7 */
+    0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F   /* F8 - FF */
+};
+#endif /* ZIP || CRYPT */
+
+#endif /* ?MTS */
+#endif /* EBCDIC */
+
+/*---------------------------------------------------------------------------
+
+  The following conversion tables translate between IBM PC CP 850
+  (OEM codepage) and the "Western Europe & America" Windows codepage 1252.
+  The Windows codepage 1252 contains the ISO 8859-1 "Latin 1" codepage,
+  with some additional printable characters in the range (0x80 - 0x9F),
+  that is reserved to control codes in the ISO 8859-1 character table.
+
+  The ISO <--> OEM conversion tables were constructed with the help
+  of the WIN32 (Win16?) API's OemToAnsi() and AnsiToOem() conversion
+  functions and have been checked against the CP850 and LATIN1 tables
+  provided in the MS-Kermit 3.14 distribution.
+
+  ---------------------------------------------------------------------------*/
+
+#ifdef IZ_ISO2OEM_ARRAY
+ZCONST uch Far iso2oem[] = {
+    0x3F, 0x3F, 0x27, 0x9F, 0x22, 0x2E, 0xC5, 0xCE,  /* 80 - 87 */
+    0x5E, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F,  /* 88 - 8F */
+    0x3F, 0x27, 0x27, 0x22, 0x22, 0x07, 0x2D, 0x2D,  /* 90 - 97 */
+    0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59,  /* 98 - 9F */
+    0xFF, 0xAD, 0xBD, 0x9C, 0xCF, 0xBE, 0xDD, 0xF5,  /* A0 - A7 */
+    0xF9, 0xB8, 0xA6, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE,  /* A8 - AF */
+    0xF8, 0xF1, 0xFD, 0xFC, 0xEF, 0xE6, 0xF4, 0xFA,  /* B0 - B7 */
+    0xF7, 0xFB, 0xA7, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8,  /* B8 - BF */
+    0xB7, 0xB5, 0xB6, 0xC7, 0x8E, 0x8F, 0x92, 0x80,  /* C0 - C7 */
+    0xD4, 0x90, 0xD2, 0xD3, 0xDE, 0xD6, 0xD7, 0xD8,  /* C8 - CF */
+    0xD1, 0xA5, 0xE3, 0xE0, 0xE2, 0xE5, 0x99, 0x9E,  /* D0 - D7 */
+    0x9D, 0xEB, 0xE9, 0xEA, 0x9A, 0xED, 0xE8, 0xE1,  /* D8 - DF */
+    0x85, 0xA0, 0x83, 0xC6, 0x84, 0x86, 0x91, 0x87,  /* E0 - E7 */
+    0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B,  /* E8 - EF */
+    0xD0, 0xA4, 0x95, 0xA2, 0x93, 0xE4, 0x94, 0xF6,  /* F0 - F7 */
+    0x9B, 0x97, 0xA3, 0x96, 0x81, 0xEC, 0xE7, 0x98   /* F8 - FF */
+};
+#endif /* IZ_ISO2OEM_ARRAY */
+
+#ifdef IZ_OEM2ISO_ARRAY
+ZCONST uch Far oem2iso[] = {
+    0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7,  /* 80 - 87 */
+    0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5,  /* 88 - 8F */
+    0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9,  /* 90 - 97 */
+    0xFF, 0xD6, 0xDC, 0xF8, 0xA3, 0xD8, 0xD7, 0x83,  /* 98 - 9F */
+    0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA,  /* A0 - A7 */
+    0xBF, 0xAE, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB,  /* A8 - AF */
+    0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xC1, 0xC2, 0xC0,  /* B0 - B7 */
+    0xA9, 0xA6, 0xA6, 0x2B, 0x2B, 0xA2, 0xA5, 0x2B,  /* B8 - BF */
+    0x2B, 0x2D, 0x2D, 0x2B, 0x2D, 0x2B, 0xE3, 0xC3,  /* C0 - C7 */
+    0x2B, 0x2B, 0x2D, 0x2D, 0xA6, 0x2D, 0x2B, 0xA4,  /* C8 - CF */
+    0xF0, 0xD0, 0xCA, 0xCB, 0xC8, 0x69, 0xCD, 0xCE,  /* D0 - D7 */
+    0xCF, 0x2B, 0x2B, 0xA6, 0x5F, 0xA6, 0xCC, 0xAF,  /* D8 - DF */
+    0xD3, 0xDF, 0xD4, 0xD2, 0xF5, 0xD5, 0xB5, 0xFE,  /* E0 - E7 */
+    0xDE, 0xDA, 0xDB, 0xD9, 0xFD, 0xDD, 0xAF, 0xB4,  /* E8 - EF */
+    0xAD, 0xB1, 0x3D, 0xBE, 0xB6, 0xA7, 0xF7, 0xB8,  /* F0 - F7 */
+    0xB0, 0xA8, 0xB7, 0xB9, 0xB3, 0xB2, 0xA6, 0xA0   /* F8 - FF */
+};
+#endif /* IZ_OEM2ISO_ARRAY */
+
+#if defined(THEOS) || defined(THEOS_SUPPORT)
+#  include "theos/charconv.h"
+#endif
+
+#endif /* __ebcdic_h  */
diff --git a/file_id.diz b/file_id.diz
new file mode 100644 (file)
index 0000000..5420e59
--- /dev/null
@@ -0,0 +1,15 @@
+Info-ZIP's Zip 2.31: generic C sources.
+  Complete C source code for Info-ZIP's
+  PKZIP-compatible .zip archiver, for
+  all supported compilers and platforms
+  (Unix, OS/2, MS-DOS, NT, VMS, Amiga,
+  Atari, Mac, Acorn, VM/CMS, etc.), plus
+  lots of pretty decent documentation.
+  Includes Info-ZIP's ZCrypt 2.9 for
+  PKWARE-compatible standard encryption
+  and decryption support for Info-ZIP's
+  Zip 2.31, UnZip 5.52, and WiZ 5.02 (and
+  later).
+This is FREE (but copyrighted) software.
+See LICENSE for details on distribution
+and reuse.
diff --git a/fileio.c b/fileio.c
new file mode 100644 (file)
index 0000000..e59011c
--- /dev/null
+++ b/fileio.c
@@ -0,0 +1,986 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *  fileio.c by Mark Adler
+ */
+#define __FILEIO_C
+
+#include "zip.h"
+
+#ifdef MACOS
+#  include "helpers.h"
+#endif
+
+#include <time.h>
+
+#ifdef NO_MKTIME
+time_t mktime OF((struct tm *));
+#endif
+
+#ifdef OSF
+#define EXDEV 18   /* avoid a bug in the DEC OSF/1 header files. */
+#else
+#include <errno.h>
+#endif
+
+#ifdef NO_ERRNO
+extern int errno;
+#endif
+
+#if defined(VMS) || defined(TOPS20)
+#  define PAD 5
+#else
+#  define PAD 0
+#endif
+
+#ifdef NO_RENAME
+int rename OF((ZCONST char *, ZCONST char *));
+#endif
+
+
+#ifndef UTIL    /* the companion #endif is a bit of ways down ... */
+
+/* Local functions */
+local int fqcmp  OF((ZCONST zvoid *, ZCONST zvoid *));
+local int fqcmpz OF((ZCONST zvoid *, ZCONST zvoid *));
+
+/* Local module level variables. */
+char *label = NULL;                /* global, but only used in `system'.c */
+local struct stat zipstatb;
+#if (!defined(MACOS) && !defined(WINDLL))
+local int zipstate = -1;
+#else
+int zipstate;
+#endif
+/* -1 unknown, 0 old zip file exists, 1 new zip file */
+
+char *getnam(n, fp)
+char *n;                /* where to put name (must have >=FNMAX+1 bytes) */
+FILE *fp;
+/* Read a \n or \r delimited name from stdin into n, and return
+   n.  If EOF, then return NULL.  Also, if the name read is too big, return
+   NULL. */
+{
+  int c;                /* last character read */
+  char *p;              /* pointer into name area */
+
+  p = n;
+  while ((c = getc(fp)) == '\n' || c == '\r')
+    ;
+  if (c == EOF)
+    return NULL;
+  do {
+    if (p - n >= FNMAX)
+      return NULL;
+    *p++ = (char) c;
+    c = getc(fp);
+  } while (c != EOF && (c != '\n' && c != '\r'));
+#ifdef WIN32
+/*
+ * WIN32 strips off trailing spaces and periods in filenames
+ * XXX what about a filename that only consists of spaces ?
+ *     Answer: on WIN32, a filename must contain at least one non-space char
+ */
+  while (p > n) {
+    if ((c = p[-1]) != ' ' && c != '.')
+      break;
+    --p;
+  }
+#endif
+  *p = 0;
+  return n;
+}
+
+struct flist far *fexpel(f)
+struct flist far *f;    /* entry to delete */
+/* Delete the entry *f in the doubly-linked found list.  Return pointer to
+   next entry to allow stepping through list. */
+{
+  struct flist far *t;  /* temporary variable */
+
+  t = f->nxt;
+  *(f->lst) = t;                        /* point last to next, */
+  if (t != NULL)
+    t->lst = f->lst;                    /* and next to last */
+  if (f->name != NULL)                  /* free memory used */
+    free((zvoid *)(f->name));
+  if (f->zname != NULL)
+    free((zvoid *)(f->zname));
+  if (f->iname != NULL)
+    free((zvoid *)(f->iname));
+  farfree((zvoid far *)f);
+  fcount--;                             /* decrement count */
+  return t;                             /* return pointer to next */
+}
+
+
+local int fqcmp(a, b)
+ZCONST zvoid *a, *b;          /* pointers to pointers to found entries */
+/* Used by qsort() to compare entries in the found list by name. */
+{
+  return strcmp((*(struct flist far **)a)->name,
+                (*(struct flist far **)b)->name);
+}
+
+
+local int fqcmpz(a, b)
+ZCONST zvoid *a, *b;          /* pointers to pointers to found entries */
+/* Used by qsort() to compare entries in the found list by iname. */
+{
+  return strcmp((*(struct flist far **)a)->iname,
+                (*(struct flist far **)b)->iname);
+}
+
+
+char *last(p, c)
+char *p;                /* sequence of path components */
+int c;                  /* path components separator character */
+/* Return a pointer to the start of the last path component. For a directory
+ * name terminated by the character in c, the return value is an empty string.
+ */
+{
+  char *t;              /* temporary variable */
+
+  if ((t = strrchr(p, c)) != NULL)
+    return t + 1;
+  else
+#ifndef AOS_VS
+    return p;
+#else
+/* We want to allow finding of end of path in either AOS/VS-style pathnames
+ * or Unix-style pathnames.  This presents a few little problems ...
+ */
+  {
+    if (*p == '='  ||  *p == '^')      /* like ./ and ../ respectively */
+      return p + 1;
+    else
+      return p;
+  }
+#endif
+}
+
+
+char *msname(n)
+char *n;
+/* Reduce all path components to MSDOS upper case 8.3 style names. */
+{
+  int c;                /* current character */
+  int f;                /* characters in current component */
+  char *p;              /* source pointer */
+  char *q;              /* destination pointer */
+
+  p = q = n;
+  f = 0;
+  while ((c = (unsigned char)*POSTINCSTR(p)) != 0)
+    if (c == ' ' || c == ':' || c == '"' || c == '*' || c == '+' ||
+        c == ',' || c == ';' || c == '<' || c == '=' || c == '>' ||
+        c == '?' || c == '[' || c == ']' || c == '|')
+      continue;                         /* char is discarded */
+    else if (c == '/')
+    {
+      *POSTINCSTR(q) = (char)c;
+      f = 0;                            /* new component */
+    }
+#ifdef __human68k__
+    else if (ismbblead(c) && *p)
+    {
+      if (f == 7 || f == 11)
+        f++;
+      else if (*p && f < 12 && f != 8)
+      {
+        *q++ = c;
+        *q++ = *p++;
+        f += 2;
+      }
+    }
+#endif /* __human68k__ */
+    else if (c == '.')
+    {
+      if (f == 0)
+        continue;                       /* leading dots are discarded */
+      else if (f < 9)
+      {
+        *POSTINCSTR(q) = (char)c;
+        f = 9;                          /* now in file type */
+      }
+      else
+        f = 12;                         /* now just excess characters */
+    }
+    else
+      if (f < 12 && f != 8)
+      {
+        f += CLEN(p);                   /* do until end of name or type */
+        *POSTINCSTR(q) = (char)(to_up(c));
+      }
+  *q = 0;
+  return n;
+}
+
+int check_dup()
+/* Sort the found list and remove duplicates.
+   Return an error code in the ZE_ class. */
+{
+  struct flist far *f;          /* steps through found linked list */
+  extent j, k;                  /* indices for s */
+  struct flist far **s;         /* sorted table */
+  struct flist far **nodup;     /* sorted table without duplicates */
+
+  /* sort found list, remove duplicates */
+  if (fcount)
+  {
+    extent fl_size = fcount * sizeof(struct flist far *);
+    if ((fl_size / sizeof(struct flist far *)) != fcount ||
+        (s = (struct flist far **)malloc(fl_size)) == NULL)
+      return ZE_MEM;
+    for (j = 0, f = found; f != NULL; f = f->nxt)
+      s[j++] = f;
+    /* Check names as given (f->name) */
+    qsort((char *)s, fcount, sizeof(struct flist far *), fqcmp);
+    for (k = j = fcount - 1; j > 0; j--)
+      if (strcmp(s[j - 1]->name, s[j]->name) == 0)
+        /* remove duplicate entry from list */
+        fexpel(s[j]);           /* fexpel() changes fcount */
+      else
+        /* copy valid entry into destination position */
+        s[k--] = s[j];
+    s[k] = s[0];                /* First entry is always valid */
+    nodup = &s[k];              /* Valid entries are at end of array s */
+
+    /* sort only valid items and check for unique internal names (f->iname) */
+    qsort((char *)nodup, fcount, sizeof(struct flist far *), fqcmpz);
+    for (j = 1; j < fcount; j++)
+      if (strcmp(nodup[j - 1]->iname, nodup[j]->iname) == 0)
+      {
+        zipwarn("  first full name: ", nodup[j - 1]->name);
+        zipwarn(" second full name: ", nodup[j]->name);
+#ifdef EBCDIC
+        strtoebc(nodup[j]->iname, nodup[j]->iname);
+#endif
+        zipwarn("name in zip file repeated: ", nodup[j]->iname);
+#ifdef EBCDIC
+        strtoasc(nodup[j]->iname, nodup[j]->iname);
+#endif
+        return ZE_PARMS;
+      }
+    free((zvoid *)s);
+  }
+  return ZE_OK;
+}
+
+int filter(name, casesensitive)
+  char *name;
+  int casesensitive;
+  /* Scan the -i and -x lists for matches to the given name.
+     Return true if the name must be included, false otherwise.
+     Give precedence to -x over -i.
+   */
+{
+   unsigned int n;
+   int slashes;
+   int include = icount ? 0 : 1;
+   char *p, *q;
+
+   if (pcount == 0) return 1;
+
+   for (n = 0; n < pcount; n++) {
+      if (!patterns[n].zname[0])        /* it can happen... */
+          continue;
+      p = name;
+      if (patterns[n].select == 'R') {
+         /* With -R patterns, if the pattern has N path components (that is, */
+         /* N-1 slashes), then we test only the last N components of name.   */
+         slashes = 0;
+         for (q = patterns[n].zname; (q = MBSCHR(q, '/')) != NULL; INCSTR(q))
+            slashes++;
+         for (q = p; (q = MBSCHR(q, '/')) != NULL; INCSTR(q))
+            slashes--;
+         if (slashes < 0)
+            for (q = p; (q = MBSCHR(q, '/')) != NULL; INCSTR(q))
+               if (slashes++ == 0) {
+                  p = q + CLEN(q);
+                  break;
+               }
+      }
+      if (MATCH(patterns[n].zname, p, casesensitive)) {
+         if (patterns[n].select == 'x') return 0;
+         include = 1;
+      }
+   }
+   return include;
+}
+
+int newname(name, isdir, casesensitive)
+char *name;             /* name to add (or exclude) */
+int  isdir;             /* true for a directory */
+int  casesensitive;     /* true for case-sensitive matching */
+/* Add (or exclude) the name of an existing disk file.  Return an error
+   code in the ZE_ class. */
+{
+  char *iname, *zname;  /* internal name, external version of iname */
+  char *undosm;         /* zname version with "-j" and "-k" options disabled */
+  struct flist far *f;  /* where in found, or new found entry */
+  struct zlist far *z;  /* where in zfiles (if found) */
+  int dosflag;
+
+  /* Search for name in zip file.  If there, mark it, else add to
+     list of new names to do (or remove from that list). */
+  if ((iname = ex2in(name, isdir, &dosflag)) == NULL)
+    return ZE_MEM;
+
+  /* Discard directory names with zip -rj */
+  if (*iname == '\0') {
+#ifndef AMIGA
+/* A null string is a legitimate external directory name in AmigaDOS; also,
+ * a command like "zip -r zipfile FOO:" produces an empty internal name.
+ */
+# ifndef RISCOS
+ /* If extensions needs to be swapped, we will have empty directory names
+    instead of the original directory. For example, zipping 'c.', 'c.main'
+    should zip only 'main.c' while 'c.' will be converted to '\0' by ex2in. */
+
+    if (pathput && !recurse) error("empty name without -j or -r");
+
+# endif /* !RISCOS */
+#endif /* !AMIGA */
+    free((zvoid *)iname);
+    return ZE_OK;
+  }
+  undosm = NULL;
+  if (dosflag || !pathput) {
+    int save_dosify = dosify, save_pathput = pathput;
+    dosify = 0;
+    pathput = 1;
+    /* zname is temporarly mis-used as "undosmode" iname pointer */
+    if ((zname = ex2in(name, isdir, NULL)) != NULL) {
+      undosm = in2ex(zname);
+      free(zname);
+    }
+    dosify = save_dosify;
+    pathput = save_pathput;
+  }
+  if ((zname = in2ex(iname)) == NULL)
+    return ZE_MEM;
+  if (undosm == NULL)
+    undosm = zname;
+  if ((z = zsearch(zname)) != NULL) {
+    if (pcount && !filter(undosm, casesensitive)) {
+      /* Do not clear z->mark if "exclude", because, when "dosify || !pathput"
+       * is in effect, two files with different filter options may hit the
+       * same z entry.
+       */
+      if (verbose)
+        fprintf(mesg, "excluding %s\n", zname);
+      free((zvoid *)iname);
+      free((zvoid *)zname);
+    } else {
+      z->mark = 1;
+      if ((z->name = malloc(strlen(name) + 1 + PAD)) == NULL) {
+        if (undosm != zname)
+          free((zvoid *)undosm);
+        free((zvoid *)iname);
+        free((zvoid *)zname);
+        return ZE_MEM;
+      }
+      strcpy(z->name, name);
+      z->dosflag = dosflag;
+
+#ifdef FORCE_NEWNAME
+      free((zvoid *)(z->iname));
+      z->iname = iname;
+#else
+      /* Better keep the old name. Useful when updating on MSDOS a zip file
+       * made on Unix.
+       */
+      free((zvoid *)iname);
+      free((zvoid *)zname);
+#endif /* ? FORCE_NEWNAME */
+    }
+    if (name == label) {
+       label = z->name;
+    }
+  } else if (pcount == 0 || filter(undosm, casesensitive)) {
+
+    /* Check that we are not adding the zip file to itself. This
+     * catches cases like "zip -m foo ../dir/foo.zip".
+     */
+#ifndef CMS_MVS
+/* Version of stat() for CMS/MVS isn't complete enough to see if       */
+/* files match.  Just let ZIP.C compare the filenames.  That's good    */
+/* enough for CMS anyway since there aren't paths to worry about.      */
+    struct stat statb;
+
+    if (zipstate == -1)
+       zipstate = strcmp(zipfile, "-") != 0 &&
+                   stat(zipfile, &zipstatb) == 0;
+
+    if (zipstate == 1 && (statb = zipstatb, stat(name, &statb) == 0
+      && zipstatb.st_mode  == statb.st_mode
+#ifdef VMS
+      && memcmp(zipstatb.st_ino, statb.st_ino, sizeof(statb.st_ino)) == 0
+      && strcmp(zipstatb.st_dev, statb.st_dev) == 0
+      && zipstatb.st_uid   == statb.st_uid
+#else /* !VMS */
+      && zipstatb.st_ino   == statb.st_ino
+      && zipstatb.st_dev   == statb.st_dev
+      && zipstatb.st_uid   == statb.st_uid
+      && zipstatb.st_gid   == statb.st_gid
+#endif /* ?VMS */
+      && zipstatb.st_size  == statb.st_size
+      && zipstatb.st_mtime == statb.st_mtime
+      && zipstatb.st_ctime == statb.st_ctime)) {
+      /* Don't compare a_time since we are reading the file */
+         if (verbose)
+           fprintf(mesg, "file matches zip file -- skipping\n");
+         if (undosm != zname)
+           free((zvoid *)zname);
+         if (undosm != iname)
+           free((zvoid *)undosm);
+         free((zvoid *)iname);
+         return ZE_OK;
+    }
+#endif  /* CMS_MVS */
+
+    /* allocate space and add to list */
+    if ((f = (struct flist far *)farmalloc(sizeof(struct flist))) == NULL ||
+        fcount + 1 < fcount ||
+        (f->name = malloc(strlen(name) + 1 + PAD)) == NULL)
+    {
+      if (f != NULL)
+        farfree((zvoid far *)f);
+      if (undosm != zname)
+        free((zvoid *)undosm);
+      free((zvoid *)iname);
+      free((zvoid *)zname);
+      return ZE_MEM;
+    }
+    strcpy(f->name, name);
+    f->iname = iname;
+    f->zname = zname;
+    f->dosflag = dosflag;
+    *fnxt = f;
+    f->lst = fnxt;
+    f->nxt = NULL;
+    fnxt = &f->nxt;
+    fcount++;
+    if (name == label) {
+      label = f->name;
+    }
+  }
+  if (undosm != zname)
+    free((zvoid *)undosm);
+  return ZE_OK;
+}
+
+
+ulg dostime(y, n, d, h, m, s)
+int y;                  /* year */
+int n;                  /* month */
+int d;                  /* day */
+int h;                  /* hour */
+int m;                  /* minute */
+int s;                  /* second */
+/* Convert the date y/n/d and time h:m:s to a four byte DOS date and
+   time (date in high two bytes, time in low two bytes allowing magnitude
+   comparison). */
+{
+  return y < 1980 ? DOSTIME_MINIMUM /* dostime(1980, 1, 1, 0, 0, 0) */ :
+        (((ulg)y - 1980) << 25) | ((ulg)n << 21) | ((ulg)d << 16) |
+        ((ulg)h << 11) | ((ulg)m << 5) | ((ulg)s >> 1);
+}
+
+
+ulg unix2dostime(t)
+time_t *t;              /* unix time to convert */
+/* Return the Unix time t in DOS format, rounded up to the next two
+   second boundary. */
+{
+  time_t t_even;
+  struct tm *s;         /* result of localtime() */
+
+  t_even = (time_t)(((unsigned long)(*t) + 1) & (~1));
+                                /* Round up to even seconds. */
+  s = localtime(&t_even);       /* Use local time since MSDOS does. */
+  if (s == (struct tm *)NULL) {
+      /* time conversion error; use current time as emergency value
+         (assuming that localtime() does at least accept this value!) */
+      t_even = (time_t)(((unsigned long)time(NULL) + 1) & (~1));
+      s = localtime(&t_even);
+  }
+  return dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday,
+                 s->tm_hour, s->tm_min, s->tm_sec);
+}
+
+int issymlnk(a)
+ulg a;                  /* Attributes returned by filetime() */
+/* Return true if the attributes are those of a symbolic link */
+{
+#ifndef QDOS
+#ifdef S_IFLNK
+#ifdef __human68k__
+  int *_dos_importlnenv(void);
+
+  if (_dos_importlnenv() == NULL)
+    return 0;
+#endif
+  return ((a >> 16) & S_IFMT) == S_IFLNK;
+#else /* !S_IFLNK */
+  return (int)a & 0;    /* avoid warning on unused parameter */
+#endif /* ?S_IFLNK */
+#else
+  return 0;
+#endif
+}
+
+#endif /* !UTIL */
+
+
+#if (!defined(UTIL) && !defined(ZP_NEED_GEN_D2U_TIME))
+   /* There is no need for dos2unixtime() in the ZipUtils' code. */
+#  define ZP_NEED_GEN_D2U_TIME
+#endif
+#if ((defined(OS2) || defined(VMS)) && defined(ZP_NEED_GEN_D2U_TIME))
+   /* OS/2 and VMS use a special solution to handle time-stams of files. */
+#  undef ZP_NEED_GEN_D2U_TIME
+#endif
+#if (defined(W32_STATROOT_FIX) && !defined(ZP_NEED_GEN_D2U_TIME))
+   /* The Win32 stat()-bandaid to fix stat'ing root directories needs
+    * dos2unixtime() to calculate the time-stamps. */
+#  define ZP_NEED_GEN_D2U_TIME
+#endif
+
+#ifdef ZP_NEED_GEN_D2U_TIME
+
+time_t dos2unixtime(dostime)
+ulg dostime;            /* DOS time to convert */
+/* Return the Unix time_t value (GMT/UTC time) for the DOS format (local)
+ * time dostime, where dostime is a four byte value (date in most significant
+ * word, time in least significant word), see dostime() function.
+ */
+{
+  struct tm *t;         /* argument for mktime() */
+  ZCONST time_t clock = time(NULL);
+
+  t = localtime(&clock);
+  t->tm_isdst = -1;     /* let mktime() determine if DST is in effect */
+  /* Convert DOS time to UNIX time_t format */
+  t->tm_sec  = (((int)dostime) <<  1) & 0x3e;
+  t->tm_min  = (((int)dostime) >>  5) & 0x3f;
+  t->tm_hour = (((int)dostime) >> 11) & 0x1f;
+  t->tm_mday = (int)(dostime >> 16) & 0x1f;
+  t->tm_mon  = ((int)(dostime >> 21) & 0x0f) - 1;
+  t->tm_year = ((int)(dostime >> 25) & 0x7f) + 80;
+
+  return mktime(t);
+}
+
+#undef ZP_NEED_GEN_D2U_TIME
+#endif /* ZP_NEED_GEN_D2U_TIME */
+
+
+#ifndef MACOS
+int destroy(f)
+char *f;                /* file to delete */
+/* Delete the file *f, returning non-zero on failure. */
+{
+  return unlink(f);
+}
+
+
+int replace(d, s)
+char *d, *s;            /* destination and source file names */
+/* Replace file *d by file *s, removing the old *s.  Return an error code
+   in the ZE_ class. This function need not preserve the file attributes,
+   this will be done by setfileattr() later.
+ */
+{
+  struct stat t;        /* results of stat() */
+#if defined(CMS_MVS)
+  /* cmsmvs.h defines FOPW_TEMP as memory(hiperspace).  Since memory is
+   * lost at end of run, always do copy instead of rename.
+   */
+  int copy = 1;
+#else
+  int copy = 0;
+#endif
+  int d_exists;
+
+#if defined(VMS) || defined(CMS_MVS)
+  /* stat() is broken on VMS remote files (accessed through Decnet).
+   * This patch allows creation of remote zip files, but is not sufficient
+   * to update them or compress remote files */
+  unlink(d);
+#else /* !(VMS || CMS_MVS) */
+  d_exists = (LSTAT(d, &t) == 0);
+  if (d_exists)
+  {
+    /*
+     * respect existing soft and hard links!
+     */
+    if (t.st_nlink > 1
+# ifdef S_IFLNK
+        || (t.st_mode & S_IFMT) == S_IFLNK
+# endif
+        )
+       copy = 1;
+    else if (unlink(d))
+       return ZE_CREAT;                 /* Can't erase zip file--give up */
+  }
+#endif /* ?(VMS || CMS_MVS) */
+#ifndef CMS_MVS
+  if (!copy) {
+      if (rename(s, d)) {               /* Just move s on top of d */
+          copy = 1;                     /* failed ? */
+#if !defined(VMS) && !defined(ATARI) && !defined(AZTEC_C)
+#if !defined(CMS_MVS) && !defined(RISCOS) && !defined(QDOS)
+    /* For VMS, ATARI, AMIGA Aztec, VM_CMS, MVS, RISCOS,
+       always assume that failure is EXDEV */
+          if (errno != EXDEV
+#  ifdef THEOS
+           && errno != EEXIST
+#  else
+#    ifdef ENOTSAM
+           && errno != ENOTSAM /* Used at least on Turbo C */
+#    endif
+#  endif
+              ) return ZE_CREAT;
+#endif /* !CMS_MVS && !RISCOS */
+#endif /* !VMS && !ATARI && !AZTEC_C */
+      }
+  }
+#endif /* !CMS_MVS */
+
+  if (copy) {
+    FILE *f, *g;        /* source and destination files */
+    int r;              /* temporary variable */
+
+#ifdef RISCOS
+    if (SWI_OS_FSControl_26(s,d,0xA1)!=NULL) {
+#endif
+
+    if ((f = fopen(s, FOPR)) == NULL) {
+      fprintf(stderr," replace: can't open %s\n", s);
+      return ZE_TEMP;
+    }
+    if ((g = fopen(d, FOPW)) == NULL)
+    {
+      fclose(f);
+      return ZE_CREAT;
+    }
+    r = fcopy(f, g, (ulg)-1L);
+    fclose(f);
+    if (fclose(g) || r != ZE_OK)
+    {
+      unlink(d);
+      return r ? (r == ZE_TEMP ? ZE_WRITE : r) : ZE_WRITE;
+    }
+    unlink(s);
+#ifdef RISCOS
+    }
+#endif
+  }
+  return ZE_OK;
+}
+#endif /* !MACOS */
+
+
+int getfileattr(f)
+char *f;                /* file path */
+/* Return the file attributes for file f or 0 if failure */
+{
+#ifdef __human68k__
+  struct _filbuf buf;
+
+  return _dos_files(&buf, f, 0xff) < 0 ? 0x20 : buf.atr;
+#else
+  struct stat s;
+
+  return SSTAT(f, &s) == 0 ? (int) s.st_mode : 0;
+#endif
+}
+
+
+int setfileattr(f, a)
+char *f;                /* file path */
+int a;                  /* attributes returned by getfileattr() */
+/* Give the file f the attributes a, return non-zero on failure */
+{
+#if defined(TOPS20) || defined (CMS_MVS)
+  return 0;
+#else
+#ifdef __human68k__
+  return _dos_chmod(f, a) < 0 ? -1 : 0;
+#else
+  return chmod(f, a);
+#endif
+#endif
+}
+
+#ifndef VMS /* VMS-specific function is in VMS.C. */
+
+char *tempname(zip)
+char *zip;              /* path name of zip file to generate temp name for */
+
+/* Return a temporary file name in its own malloc'ed space, using tempath. */
+{
+  char *t = zip;   /* malloc'ed space for name (use zip to avoid warning) */
+
+#ifdef CMS_MVS
+  if ((t = malloc(strlen(tempath)+L_tmpnam+2)) == NULL)
+    return NULL;
+#  ifdef VM_CMS
+  tmpnam(t);
+  /* Remove filemode and replace with tempath, if any. */
+  /* Otherwise A-disk is used by default */
+  *(strrchr(t, ' ')+1) = '\0';
+  if (tempath!=NULL)
+     strcat(t, tempath);
+  return t;
+#  else   /* !VM_CMS */
+  /* For MVS */
+  tmpnam(t);
+  if (tempath != NULL)
+  {
+    int l1 = strlen(t);
+    char *dot;
+    if (*t == '\'' && *(t+l1-1) == '\'' && (dot = strchr(t, '.')))
+    {
+      /* MVS and not OE.  tmpnam() returns quoted string of 5 qualifiers.
+       * First is HLQ, rest are timestamps.  User can only replace HLQ.
+       */
+      int l2 = strlen(tempath);
+      if (strchr(tempath, '.') || l2 < 1 || l2 > 8)
+        ziperr(ZE_PARMS, "On MVS and not OE, tempath (-b) can only be HLQ");
+      memmove(t+1+l2, dot, l1+1-(dot-t));  /* shift dot ready for new hlq */
+      memcpy(t+1, tempath, l2);            /* insert new hlq */
+    }
+    else
+    {
+      /* MVS and probably OE.  tmpnam() returns filename based on TMPDIR,
+       * no point in even attempting to change it.  User should modify TMPDIR
+       * instead.
+       */
+      zipwarn("MVS, assumed to be OE, change TMPDIR instead of option -b: ",
+              tempath);
+    }
+  }
+  return t;
+#  endif  /* !VM_CMS */
+#else /* !CMS_MVS */
+#ifdef TANDEM
+  char cur_subvol [FILENAME_MAX];
+  char temp_subvol [FILENAME_MAX];
+  char *zptr;
+  char *ptr;
+  char *cptr = &cur_subvol[0];
+  char *tptr = &temp_subvol[0];
+  short err;
+
+  t = (char *)malloc(NAMELEN); /* malloc here as you cannot free */
+                               /* tmpnam allocated storage later */
+
+  zptr = strrchr(zip, TANDEM_DELIMITER);
+
+  if (zptr != NULL) {
+    /* ZIP file specifies a Subvol so make temp file there so it can just
+       be renamed at end */
+
+    *tptr = *cptr = '\0';
+    strcat(cptr, getenv("DEFAULTS"));
+
+    strncat(tptr, zip, _min(FILENAME_MAX, (zptr - zip)) ); /* temp subvol */
+    strncat(t,zip, _min(NAMELEN, ((zptr - zip) + 1)) );    /* temp stem   */
+
+    err = chvol(tptr);
+    ptr = t + strlen(t);  /* point to end of stem */
+    tmpnam(ptr);          /* Add filename part to temp subvol */
+    err = chvol(cptr);
+  }
+  else
+    t = tmpnam(t);
+
+  return t;
+
+#else /* !CMS_MVS && !TANDEM */
+/*
+ * Do something with TMPDIR, TMP, TEMP ????
+ */
+  if (tempath != NULL)
+  {
+    if ((t = malloc(strlen(tempath)+12)) == NULL)
+      return NULL;
+    strcpy(t, tempath);
+#if (!defined(VMS) && !defined(TOPS20))
+#  ifdef MSDOS
+    {
+      char c = (char)lastchar(t);
+      if (c != '/' && c != ':' && c != '\\')
+        strcat(t, "/");
+    }
+#  else
+#    ifdef AMIGA
+    {
+      char c = (char)lastchar(t);
+      if (c != '/' && c != ':')
+        strcat(t, "/");
+    }
+#    else /* !AMIGA */
+#      ifdef RISCOS
+    if (lastchar(t) != '.')
+      strcat(t, ".");
+#      else /* !RISCOS */
+#        ifdef QDOS
+    if (lastchar(t) != '_')
+      strcat(t, "_");
+#        else
+    if (lastchar(t) != '/')
+      strcat(t, "/");
+#        endif /* ?QDOS */
+#      endif /* ?RISCOS */
+#    endif  /* ?AMIGA */
+#  endif /* ?MSDOS */
+#endif /* !VMS && !TOPS20 */
+  }
+  else
+  {
+    if ((t = malloc(12)) == NULL)
+      return NULL;
+    *t = 0;
+  }
+#ifdef NO_MKTEMP
+  {
+    char *p = t + strlen(t);
+    sprintf(p, "%08lx", (ulg)time(NULL));
+    return t;
+  }
+#else
+  strcat(t, "ziXXXXXX"); /* must use lowercase for Linux dos file system */
+  return mktemp(t);
+#endif /* NO_MKTEMP */
+#endif /* TANDEM */
+#endif /* CMS_MVS */
+}
+
+#endif /* ndef VMS */
+
+int fcopy(f, g, n)
+FILE *f, *g;            /* source and destination files */
+ulg n;                  /* number of bytes to copy or -1 for all */
+/* Copy n bytes from file *f to file *g, or until EOF if n == -1.  Return
+   an error code in the ZE_ class. */
+{
+  char *b;              /* malloc'ed buffer for copying */
+  extent k;             /* result of fread() */
+  ulg m;                /* bytes copied so far */
+
+  if ((b = malloc(CBSZ)) == NULL)
+    return ZE_MEM;
+  m = 0;
+  while (n == (ulg)(-1L) || m < n)
+  {
+    if ((k = fread(b, 1, n == (ulg)(-1) ?
+                   CBSZ : (n - m < CBSZ ? (extent)(n - m) : CBSZ), f)) == 0)
+    {
+      if (ferror(f))
+      {
+        free((zvoid *)b);
+        return ZE_READ;
+      }
+      else
+        break;
+    }
+    if (fwrite(b, 1, k, g) != k)
+    {
+      free((zvoid *)b);
+      fprintf(stderr," fcopy: write error\n");
+      return ZE_TEMP;
+    }
+    m += k;
+  }
+  free((zvoid *)b);
+  return ZE_OK;
+}
+
+#ifdef NO_RENAME
+int rename(from, to)
+ZCONST char *from;
+ZCONST char *to;
+{
+    unlink(to);
+    if (link(from, to) == -1)
+        return -1;
+    if (unlink(from) == -1)
+        return -1;
+    return 0;
+}
+
+#endif /* NO_RENAME */
+
+
+#ifdef ZMEM
+
+/************************/
+/*  Function memset()   */
+/************************/
+
+/*
+ * memset - for systems without it
+ *  bill davidsen - March 1990
+ */
+
+char *
+memset(buf, init, len)
+register char *buf;     /* buffer loc */
+register int init;      /* initializer */
+register unsigned int len;   /* length of the buffer */
+{
+    char *start;
+
+    start = buf;
+    while (len--) *(buf++) = init;
+    return(start);
+}
+
+
+/************************/
+/*  Function memcpy()   */
+/************************/
+
+char *
+memcpy(dst,src,len)             /* v2.0f */
+register char *dst, *src;
+register unsigned int len;
+{
+    char *start;
+
+    start = dst;
+    while (len--)
+        *dst++ = *src++;
+    return(start);
+}
+
+
+/************************/
+/*  Function memcmp()   */
+/************************/
+
+int
+memcmp(b1,b2,len)                     /* jpd@usl.edu -- 11/16/90 */
+register char *b1, *b2;
+register unsigned int len;
+{
+
+    if (len) do {       /* examine each byte (if any) */
+      if (*b1++ != *b2++)
+        return (*((uch *)b1-1) - *((uch *)b2-1));  /* exit when miscompare */
+    } while (--len);
+
+    return(0);          /* no miscompares, yield 0 result */
+}
+
+#endif  /* ZMEM */
diff --git a/globals.c b/globals.c
new file mode 100644 (file)
index 0000000..c76e5a0
--- /dev/null
+++ b/globals.c
@@ -0,0 +1,96 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *  globals.c by Mark Adler
+ */
+#define __GLOBALS_C
+
+#define GLOBALS         /* include definition of errors[] in zip.h */
+#ifndef UTIL
+#define UTIL            /* do not declare the read_buf variable */
+#endif
+
+#include "zip.h"
+
+
+/* Handy place to build error messages */
+char errbuf[FNMAX+81];
+
+/* Argument processing globals */
+int recurse = 0;        /* 1=recurse into directories encountered */
+int dispose = 0;        /* 1=remove files after put in zip file */
+int pathput = 1;        /* 1=store path with name */
+#ifdef RISCOS
+int scanimage = 1;      /* 1=scan through image files */
+#endif
+int method = BEST;      /* one of BEST, DEFLATE (only), or STORE (only) */
+int dosify = 0;         /* 1=make new entries look like MSDOS */
+int verbose = 0;        /* 1=report oddities in zip file structure */
+int fix = 0;            /* 1=fix the zip file */
+int adjust = 0;         /* 1=adjust offsets for sfx'd file (keep preamble) */
+int level = 6;          /* 0=fastest compression, 9=best compression */
+int translate_eol = 0;  /* Translate end-of-line LF -> CR LF */
+#ifdef VMS
+   int vmsver = 0;      /* 1=append VMS version number to file names */
+   int vms_native = 0;  /* 1=store in VMS format */
+#endif /* VMS */
+#if defined(OS2) || defined(WIN32)
+   int use_longname_ea = 0; /* 1=use the .LONGNAME EA as the file's name */
+#endif
+int hidden_files = 0;   /* process hidden and system files */
+int volume_label = 0;   /* add volume label */
+int dirnames = 1;       /* include directory entries by default */
+int linkput = 0;        /* 1=store symbolic links as such */
+int noisy = 1;          /* 0=quiet operation */
+int extra_fields = 1;   /* 0=do not create extra fields */
+#ifdef NTSD_EAS
+    int use_privileges = 0; /* 1=use security privilege overrides */
+#endif
+#ifndef RISCOS
+#ifndef QDOS
+#ifndef TANDEM
+char *special = ".Z:.zip:.zoo:.arc:.lzh:.arj"; /* List of special suffixes */
+#else /* TANDEM */
+char *special = " Z: zip: zoo: arc: lzh: arj"; /* List of special suffixes */
+#endif
+#else /* QDOS */
+char *special = "_Z:_zip:_zoo:_arc:_lzh:_arj"; /* List of special suffixes */
+#endif
+#else /* RISCOS */
+char *special = "DDC:D96:68E";
+#endif /* ?RISCOS */
+char *key = NULL;       /* Scramble password if scrambling */
+char *tempath = NULL;   /* Path for temporary files */
+FILE *mesg;             /* stdout by default, stderr for piping */
+
+/* Zip file globals */
+char *zipfile;          /* New or existing zip archive (zip file) */
+ulg zipbeg;             /* Starting offset of zip structures */
+ulg cenbeg;             /* Starting offset of central directory */
+struct zlist far *zfiles = NULL;  /* Pointer to list of files in zip file */
+extent zcount;          /* Number of files in zip file */
+extent zcomlen;         /* Length of zip file comment */
+char *zcomment = NULL;  /* Zip file comment (not zero-terminated) */
+struct zlist far **zsort;       /* List of files sorted by name */
+ulg tempzn;             /* Count of bytes written to output zip file */
+
+/* Files to operate on that are not in zip file */
+struct flist far *found = NULL; /* List of names found */
+struct flist far * far *fnxt = &found;
+                        /* Where to put next name in found list */
+extent fcount;          /* Count of files in list */
+
+/* Patterns to be matched */
+struct plist *patterns = NULL;  /* List of patterns to be matched */
+unsigned pcount = 0;            /* number of patterns */
+unsigned icount = 0;            /* number of include only patterns */
+
+#ifdef IZ_CHECK_TZ
+int zp_tz_is_valid;     /* signals "timezone info is available" */
+#endif
diff --git a/human68k/Makefile b/human68k/Makefile
new file mode 100644 (file)
index 0000000..e50e429
--- /dev/null
@@ -0,0 +1,93 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for human68k
+# Written by NIIMI Satoshi <a01309@cfi.waseda.ac.jp>
+#
+# 1999/09/23: Modified by Shimazaki Ryo.
+
+ifeq "$(TARGET)" "X68030"
+COPT = -m68020-40
+AOPT = -m68020 -sCPU020
+LDFLAGS = -L/usr/local/lib/lib060
+endif
+
+VPATH = human68k
+
+CC = gcc2
+CFLAGS = $(COPT) -I. -Wall -O2 -fomit-frame-pointer -fstrength-reduce \
+        -DASM_CRC -D__DOS_INLINE__
+#LDFLAGS = -Wl,-x
+LIBS = -lhmem -lttyi -lsignal
+
+AS = g2as
+ASFLAGS = $(AOPT) -1 -c4 -y -w2
+
+# object file lists
+OBJZ = zip.o zipfile.o zipup.o fileio.o util.o globals.o crypt.o ttyio.o \
+       human68k.o crc_68.o crctab.o
+OBJI = deflate.o trees.o
+OBJA =
+OBJU = zipfile_.o fileio_.o util_.o globals.o human68k_.o
+OBJN = zipnote.o  $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt_.o ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h human68k/osdep.h
+
+all: zips
+
+.SUFFIXES: _.o .o .c
+.c_.o:
+       $(CC) $(CFLAGS) -DUTIL -c $< -o $@
+.c.o:
+       $(CC) $(CFLAGS) -c $< -o $@
+
+ZIPS = zip.x zipnote.x zipsplit.x zipcloak.x
+
+zips: $(ZIPS)
+
+zip.x: $(OBJZ) $(OBJI) $(OBJA)
+       $(CC) $(LDFLAGS) -o $@ $(OBJZ) $(OBJI) $(OBJA) $(LIBS)
+zipnote.x: $(OBJN)
+       $(CC) $(LDFLAGS) -o $@ $(OBJN) $(LIBS)
+zipcloak.x: $(OBJC)
+       $(CC) $(LDFLAGS) -o $@ $(OBJC) $(LIBS)
+zipsplit.x: $(OBJS)
+       $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+
+human68k.o: human68k/human68k.c
+       $(CC) $(CFLAGS) -c -o $@ $<
+
+human68k_.o: human68k/human68k.c
+       $(CC) $(CFLAGS) -c -o $@ $< -DUTIL
+
+#match.o: human68k/match.s
+#      $(AS) $(ASFLAGS) -o $@ $<
+
+deflate.o: human68k/deflate.s
+       $(AS) $(ASFLAGS) -o $@ $<
+
+crc_68.o: human68k/crc_68.s
+       $(AS) $(ASFLAGS) -o $@ $<
+
+
+clean:
+       rm -f *.o $(ZIPS)
+
+zip.bfd: $(ZIPS)
+       rm -f $@
+       for file in $(ZIPS); do \
+               bdif -A -R uploaded/$$file $$file $@; \
+       done
+
+# rules for zip, zipnote, zipcloak, zipsplit.
+$(OBJZ): $(ZIP_H)
+$(OBJI): $(ZIP_H)
+$(OBJN): $(ZIP_H)
+$(OBJS): $(ZIP_H)
+$(OBJC): $(ZIP_H)
+zip.o zipup.o crypt.o ttyio.o zipcloak.o crypt_.o: crypt.h
+zip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h
+zip.o crypt.o ttyio.o zipcloak.o crypt_.o: ttyio.h
+zipup.o: human68k/zipup.h
+
+# EOF
diff --git a/human68k/Makefile.gcc b/human68k/Makefile.gcc
new file mode 100644 (file)
index 0000000..07864bb
--- /dev/null
@@ -0,0 +1,76 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for human68k
+# Written by NIIMI Satoshi <a01309@cfi.waseda.ac.jp>
+
+VPATH = human68k
+
+CC = gcc
+AS = as
+
+# if you are using mc68030 (or higher) based X68000,
+# uncomment following defines
+#CC = gcc -DUNALIGNED_OK
+#AS = as -s UNALIGNED_OK
+
+CFLAGS = -Wall -O -fomit-frame-pointer -fstrength-reduce -DASMV
+LDFLAGS = -s
+LIBS = -lsignal -lmb -ldos
+
+# object file lists
+OBJZ = zip.o zipfile.o zipup.o fileio.o util.o crc32.o crctab.o globals.o \
+       crypt.o ttyio.o
+
+OBJI = deflate.o trees.o
+OBJA = match.o human68k.o
+OBJU = zipfile_.o fileio_.o util_.o globals.o human68_.o
+OBJN = zipnote.o  $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt_.o ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h human68k/osdep.h
+
+all: zips
+
+.SUFFIXES: _.o .o .c
+.c_.o:
+       $(CC) $(CFLAGS) -DUTIL -c $< -o $@
+.c.o:
+       $(CC) $(CFLAGS) -c $< -o $@
+
+ZIPS = zip.x zipnote.x zipsplit.x zipcloak.x
+
+zips: $(ZIPS)
+
+zip.x: $(OBJZ) $(OBJI) $(OBJA)
+       $(CC) -o zip.x $(LDFLAGS) $(OBJZ) $(OBJI) $(OBJA) $(LIBS)
+zipnote.x: $(OBJN)
+       $(CC) -o zipnote.x $(LDFLAGS) $(OBJN) $(LIBS)
+zipcloak.x: $(OBJC)
+       $(CC) -o zipcloak.x $(LDFLAGS) $(OBJC) $(LIBS)
+zipsplit.x: $(OBJS)
+       $(CC) -o zipsplit.x $(LDFLAGS) $(OBJS) $(LIBS)
+
+match.o: human68k/match.s
+       $(AS) -o $@ $<
+
+human68_.o: human68k/human68k.c
+       $(CC) $(CFLAGS) -DUTIL -c -o $@ $<
+
+clean:
+       rm -f *.o $(ZIPS)
+
+zip.bfd: $(ZIPS)
+       rm -f $@
+       for file in $(ZIPS); do \
+               bdif -A -R uploaded/$$file $$file $@; \
+       done
+
+# rules for zip, zipnote, zipcloak, zipsplit.
+$(OBJZ): $(ZIP_H)
+$(OBJI): $(ZIP_H)
+$(OBJN): $(ZIP_H)
+$(OBJS): $(ZIP_H)
+$(OBJC): $(ZIP_H)
+zip.o zipup.o crypt.o ttyio.o zipcloak.o crypt_.o:  crypt.h
+zip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h
+zip.o crypt.o ttyio.o zipcloak.o crypt_.o:  ttyio.h
+zipup.o:  human68k/zipup.h
diff --git a/human68k/crc_68.s b/human68k/crc_68.s
new file mode 100644 (file)
index 0000000..cc7c36c
--- /dev/null
@@ -0,0 +1,144 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; crc_68 created by Paul Kienitz, last modified 04 Jan 96.
+;
+; Return an updated 32 bit CRC value, given the old value and a block of data.
+; The CRC table used to compute the value is gotten by calling get_crc_table().
+; This replaces the older updcrc() function used in Zip and fUnZip.  The
+; prototype of the function is:
+;
+;    ulg crc32(ulg crcval, uch *text, extent textlen);
+;
+; On the Amiga, type extent is always unsigned long, not unsigned int, because
+; int can be short or long at whim, but size_t is long.
+;
+; If using this source on a non-Amiga 680x0 system, note that we treat
+; a0/a1/d0/d1 as scratch registers not preserved across function calls.
+; We do not bother to support registerized arguments for crc32() -- the
+; textlen parm is usually large enough so that savings outside the loop
+; are pointless.
+;
+; Define NO_UNROLLED_LOOPS to use a simple short loop which might be more
+; efficient on certain machines with dinky instruction caches ('020?), or for
+; processing short strings.  If loops are unrolled, the textlen parm must be
+; less than 512K; if not unrolled, it must be less than 64K.
+;
+; 1999/09/23: for Human68k: Modified by Shimazaki Ryo.
+
+        xdef    _crc32          ; (ulg val, uch *buf, extent bufsize)
+
+DO_CRC0 MACRO
+        moveq  #0,ltemp
+        move.b (textbuf)+,ltemp
+        eor.b  crcval,ltemp
+        lsl.w  #2,ltemp
+        move.l (crc_table,ltemp.w),ltemp
+        lsr.l  #8,crcval
+        eor.l  ltemp,crcval
+        ENDM
+
+
+DO_CRC2 MACRO
+        move.b (textbuf)+,btemp
+        eor.b  crcval,btemp
+        lsr.l  #8,crcval
+        move.l (crc_table,btemp.w*4),ltemp
+        eor.l  ltemp,crcval
+        ENDM
+
+crc_table       reg     a0      array of unsigned long
+crcval          reg     d0      unsigned long initial value
+textbuf         reg     a1      array of unsigned char
+textbufsize     reg     d1      unsigned long (count of bytes in textbuf)
+btemp           reg     d2
+ltemp           reg     d3
+
+
+        xref    _get_crc_table  ; ulg *get_crc_table(void)
+
+
+
+        quad
+_crc32:
+        move.l  8(sp),d0
+        bne.s   valid
+;;;;;   moveq  #0,d0
+         rts
+valid:  movem.l btemp/ltemp,-(sp)
+        jsr     _get_crc_table
+        movea.l d0,crc_table
+        move.l  12(sp),crcval
+        move.l  16(sp),textbuf
+        move.l  20(sp),textbufsize
+        not.l   crcval
+
+    ifdef   NO_UNROLLED_LOOPS
+
+    if CPU==68000
+        bra.s   decr
+loop:    DO_CRC0
+decr:    dbra   textbufsize,loop
+        bra.s   done
+
+    else
+twenty: moveq   #0,btemp
+        bra.s   decr2
+loop2:   DO_CRC2
+decr2:   dbra   textbufsize,loop2
+    endif
+
+    ELSE    ; !NO_UNROLLED_LOOPS
+
+    if CPU==68000
+        moveq   #7,btemp
+        and     textbufsize,btemp
+        lsr.l   #3,textbufsize
+        bra     decr8
+loop8:   DO_CRC0
+         DO_CRC0
+         DO_CRC0
+         DO_CRC0
+         DO_CRC0
+         DO_CRC0
+         DO_CRC0
+         DO_CRC0
+decr8:   dbra   textbufsize,loop8
+        bra.s   decr1
+loop1:   DO_CRC0
+decr1:   dbra   btemp,loop1
+        bra     done
+
+    else
+twenty: moveq   #0,btemp
+        move.l  textbufsize,-(sp)
+        lsr.l   #3,textbufsize
+        bra     decr82
+         quad
+loop82:  DO_CRC2
+         DO_CRC2
+         DO_CRC2
+         DO_CRC2
+         DO_CRC2
+         DO_CRC2
+         DO_CRC2
+         DO_CRC2
+decr82:  dbra   textbufsize,loop82
+        moveq   #7,textbufsize
+        and.l   (sp)+,textbufsize
+        bra.s   decr12
+loop12:  DO_CRC2
+decr12:  dbra   textbufsize,loop12
+    endif
+
+    ENDC    ; ?NO_UNROLLED_LOOPS
+
+done:   movem.l (sp)+,btemp/ltemp
+        not.l   crcval
+;;;;;   move.l  crcval,d0               ; crcval already is d0
+        rts
diff --git a/human68k/deflate.s b/human68k/deflate.s
new file mode 100644 (file)
index 0000000..246962c
--- /dev/null
@@ -0,0 +1,1076 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; This is a 680x0 assembly language translation of the Info-ZIP source file
+; deflate.c, by Paul Kienitz.  No rights reserved.  The function longest_match
+; is based in part on match.a by Carsten Steger, which in turn is partly based
+; on match.s for 386 by Jean-loup Gailly and Kai Uwe Rommel.  Mostly, however,
+; this material is based on deflate.c, by Gailly, Rommel, and Igor Mandrichenko.
+; This code is not commented very much; see deflate.c for comments that explain
+; what the functions are doing.
+;
+; The symbols that can be used to select different versions are as follows:
+;
+;   CPU020     if defined, use 68020 instructions always.
+;
+;   CPUTEST    if defined, check at runtime for CPU type.  Another symbol
+;               specifying the platform-specific test must be used with this.
+;               If neither of these is defined, use 68000 instructions only.
+;               Runtime test is nonportable; it is different for each OS.
+;
+;   AMIGA      use Amiga-specific test for 68020, if CPUTEST defined.  Also
+;               tells it that registers d0/a0/d1/a1 are not preserved by
+;               function calls.  At present, if AMIGA is not defined, it
+;               causes functions to preserve all registers.  ALL OF THIS CODE
+;               CURRENTLY ASSUMES THAT REGISTERS D2-D7/A2-A6 WILL BE PRESERVED
+;               BY ANY FUNCTIONS THAT IT CALLS.
+;
+;   DYN_ALLOC  should be defined here if it is defined for C source; tells us
+;               that big arrays are allocated instead of static.
+;
+;   WSIZE      must be defined as the same number used for WSIZE in the C
+;               source, and must be a power of two <= 32768.  As elsewhere,
+;               the default value is 32768.
+;
+;   INT16      define this if ints are 16 bits; otherwise 32 bit ints assumed.
+;
+;   SMALL_MEM  define this if it is defined in the C source; otherwise it uses
+;               the MEDIUM_MEM model.  BIG_MEM and MMAP are *not* supported.
+;               The FULL_SEARCH option in deflate.c is also not supported.
+;
+;   DEBUG      activates some tracing output, as in the C source.
+;
+;   QUADLONG   this selects a different version of the innermost longest_match
+;               loop code for 68020 operations, comparing bytes four at a time
+;               instead of two at a time.  It seems to be a tiny bit faster on
+;               average, but it's slower often enough that one can't generalize.
+;
+; This code currently assumes that function results are returned in D0 for
+; all platforms.  It assumes that args to functions are pushed onto the stack,
+; last arg first.  It also currently assumes that all C symbols have an
+; underscore prepended when referenced from assembly.
+;
+; 1999/09/23: for Human68k: Modified by Shimazaki Ryo.
+
+    IFNDEF  CPU020
+     IFNDEF CPUTEST
+CPU000  equ     1
+     ENDC
+    ENDC
+
+; Use these macros for accessing variables of type int:
+    IFDEF   INT16
+MOVINT  MACRO   _1,_2
+        move.w  _1,_2
+        ENDM
+CLRINT  MACRO   _1
+        clr.w   _1
+        ENDM
+INTSIZE equ     2
+    ELSE    ; !INT16
+MOVINT  MACRO   _1,_2
+        move.l  _1,_2
+        ENDM
+CLRINT  MACRO   _1
+        clr.l   _1
+        ENDM
+INTSIZE equ     4
+    ENDC
+
+    IFDEF   DYN_ALLOC
+BASEPTR MACRO   _1,_2
+        move.l  _1,_2
+        ENDM
+    ELSE
+BASEPTR MACRO   _1,_2
+        lea     _1,_2
+        ENDM
+    ENDC
+
+; constants we use, many of them adjustable:
+
+MAX_MATCH       equ     258
+MIN_MATCH       equ     3
+TOO_FAR         equ     4096
+    IFNDEF  WSIZE
+WSIZE           equ     32768
+    ENDC
+WMASK           equ     WSIZE-1
+MAX_DIST        equ     WSIZE-MAX_MATCH-MIN_MATCH-1
+MIN_LOOKAHEAD   equ     MAX_MATCH+MIN_MATCH+1
+;    IFD     BIG_MEM      ; NOT supported -- type Pos needs to be 32 bits
+;HASH_BITS      equ     15
+;    ELSE
+    IFDEF  SMALL_MEM
+HASH_BITS       equ     13
+    ELSE
+HASH_BITS       equ     14      ; default -- MEDIUM_MEM
+    ENDC
+;    ENDC    ; BIG_MEM
+HASH_SIZE       equ     1<<HASH_BITS
+HASH_MASK       equ     HASH_SIZE-1
+H_SHIFT         equ     (HASH_BITS+MIN_MATCH-1)/MIN_MATCH
+B_SLOW          equ     1
+B_FAST          equ     2
+ZE_MEM          equ     4
+EOF             equ     -1
+
+; struct config is defined by these offsets:
+Good_length     equ     0
+Max_lazy        equ     2
+Nice_length     equ     4
+Max_chain       equ     6
+Sizeof_config   equ     8
+
+
+; external functions we call:
+        xref    _ct_tally       ; int ct_tally(int, int)
+        xref    _flush_block    ; unsigned long F(char *, unsigned long, int)
+        xref    _ziperr         ; void ziperr(int, char *)
+        xref    _error          ; void error(char *)
+        xref    _calloc         ; stdlib function: void *calloc(size_t, size_t)
+        xref    _free           ; stdlib function: void free(void *)
+    IFDEF   DEBUG
+        xref    _fputc          ; stdio function: int fputc(int, FILE *)
+        xref    _stderr         ; pointer to FILE, which we pass to fputc
+    ENDC
+
+; our entry points:
+        xdef    _lm_init        ; void lm_init(int level, unsigned short *flags)
+        xdef    _lm_free        ; void lm_free(void)
+        xdef    _deflate        ; void deflate(void)  ...the big one
+        xdef    _fill_window    ; this line is just for debugging
+
+
+; ============================================================================
+; Here is where we have our global variables.
+
+;;;     section deflatevars,data
+
+; external global variables we reference:
+        xref    _verbose        ; signed int
+        xref    _level          ; signed int
+        xref    _read_buf       ; int (*read_buf)(char *, unsigned int)
+
+; global variables we make available:
+
+        xdef    _window
+        xdef    _prev
+        xdef    _head
+        xdef    _window_size
+        xdef    _block_start
+        xdef    _strstart
+
+        bss
+        quad
+
+    IFDEF   DYN_ALLOC
+_prev:          ds.l    1       ; pointer to calloc()'d unsigned short array
+_head:          ds.l    1       ; pointer to calloc()'d unsigned short array
+_window:        ds.l    1       ; pointer to calloc()'d unsigned char array
+    ELSE    ; !DYN_ALLOC
+_prev:          ds.w    WSIZE           ; array of unsigned short
+_head:          ds.w    HASH_SIZE       ; array of unsigned short
+_window:        ds.b    2*WSIZE         ; array of unsigned char
+    ENDC    ; ?DYN_ALLOC
+
+        text
+        quad
+_window_size:   ds.l    1               ; unsigned long
+_block_start:   ds.l    1               ; unsigned long
+_strstart:      ds.w    INTSIZE/2       ; unsigned int
+
+; Now here are our private variables:
+
+    IFDEF   CPUTEST
+is020:          ds.w    1       ; bool: CPU type is '020 or higher
+    ENDC
+ins_h:          ds.w    1       ; unsigned short
+sliding:        ds.w    1       ; bool: the file is read a piece at a time
+eofile:         ds.w    1       ; bool: we have read in the end of the file
+max_lazy_match: ds.w    1       ; unsigned short
+lookahead:      ds.w    1       ; unsigned short
+
+; These are NOT DECLARED AS STATIC in deflate.c, but currently could be:
+max_chain_len:  ds.w    1       ; unsigned short (unsigned int in deflate.c)
+prev_length:    ds.w    1       ; unsigned short (unsigned int in deflate.c)
+good_match:     ds.w    1       ; unsigned short (unsigned int in deflate.c)
+nice_match:     ds.w    1       ; unsigned short (signed int in deflate.c)
+match_start:    ds.w    1       ; unsigned short (unsigned int in deflate.c)
+
+; This array of struct config is a constant and could be in the code section:
+config_table:   dc.w    0,0,0,0         ; level 0: store uncompressed
+                dc.w    4,4,8,4         ; level 1: fastest, loosest compression
+                dc.w    4,5,16,8        ; level 2
+                dc.w    4,6,32,32       ; level 3: highest to use deflate_fast
+                dc.w    4,4,16,16       ; level 4: lowest to use lazy matches
+                dc.w    8,16,32,32      ; level 5
+                dc.w    8,16,128,128    ; level 6: the default level
+                dc.w    8,32,128,256    ; level 7
+                dc.w    32,128,258,1024 ; level 8
+                dc.w    32,258,258,4096 ; level 9: maximum compression, slow
+
+
+;;CAL_SH  MACRO                   ; macro for calling zcalloc()
+;;     IFD    INT16
+;;        move.w  #2,-(sp)
+;;        move.w  #\1,-(sp)
+;;        jsr     _zcalloc
+;;        addq    #4,sp
+;;     ELSE
+;;        pea     2
+;;        pea     \1
+;;        jsr     _zcalloc
+;;        addq    #8,sp
+;;     ENDC
+;;        ENDM
+
+CAL_SH  MACRO   _1              ; Okay, we're back to using regular calloc()...
+        movem.l d2/a2,-(sp)
+        pea     2
+        pea     _1
+        jsr     _calloc
+        addq    #8,sp
+        movem.l (sp)+,d2/a2
+        ENDM
+
+; ============================================================================
+; And here we begin our functions.  match_init is for internal use only:
+
+;;      section deflate,code
+
+match_init:
+    IFDEF   CPUTEST             ; now check for platform type
+     IFDEF  AMIGA               ; Amiga specific test for '020 CPU:
+        xref    _SysBase
+        NOLIST
+        INCLUDE       'exec/execbase.i'
+        LIST
+
+        clr.w   is020                   ; default value is 68000
+        move.l  _SysBase,a0
+        btst    #AFB_68020,AttnFlags+1(a0)
+        beq.s   cheap
+        move.w  #1,is020
+cheap:
+     ELSE   ; !AMIGA
+
+        FAIL    Write an '020-detector for your system here!
+; On the Macintosh, I believe GetEnvironment() provides the information.
+
+     ENDC   ; AMIGA
+    ENDC    ; CPUTEST
+        rts     ; match_init consists only of rts if CPUTEST unset
+
+
+; ============================================================================
+; Here is longest_match(), the function that the rest of this was built up
+; from, the hottest hot spot in the program and therefore the most heavily
+; optimized.  It has two different versions, one for '020 and higher CPUs, and
+; one for 68000/68010.  It can test at runtime which version to use if you
+; create a test function in match_init for your platform.  Currently such a
+; test is implemented for the Amiga.  It can also be assembled to use '000 or
+; '020 code only.
+
+Cur_Match       reg     d0              ; unsigned int, kept valid as long
+Best_Len        reg     d1              ; unsigned int, kept valid as long
+Scan_Start      reg     d3              ; pair of bytes
+Scan_End        reg     d4              ; pair of bytes
+Limit           reg     d5              ; unsigned int
+Chain_Length    reg     d6              ; unsigned int
+Scan_Test       reg     d7              ; counter, pair of bytes sometimes
+Scan            reg     a0              ; pointer to unsigned char
+Match           reg     a1              ; pointer to unsigned char
+Prev_Address    reg     a2              ; pointer to unsigned short
+Scan_Ini        reg     a3              ; pointer to unsigned char
+Match_Ini       reg     a5              ; pointer to unsigned char
+; Note: "pair of bytes" means the two low order bytes of the register in
+; 68020 code, but means the lowest and third lowest bytes on the 68000.
+SAVEREGS        reg     d3-d7/a2/a3/a5      ; don't protect d0/d1/a0/a1
+; d2, a4, a6 not used... on Amiga, a4 is used by small-data memory model
+
+
+longest_match:
+        movem.l SAVEREGS,-(sp)
+
+; setup steps common to byte and word versions:
+    IFDEF   INT16
+        and.l   #$0000FFFF,Cur_Match    ; upper half must be zero!
+; we use an and.l down here for the sake of ATSIGN/REGARGS.
+        moveq   #0,Limit                ; so adding to Scan_Ini works
+    ENDC
+        move.w  (max_chain_len,pc),Chain_Length
+        move.w  (prev_length,pc),Best_Len
+        MOVINT  (_strstart,pc),Limit
+        BASEPTR _prev,Prev_Address
+        BASEPTR _window,Match_Ini
+        move.l  Match_Ini,Scan_Ini
+        addq    #MIN_MATCH,Match_Ini    ; optimizes inner loop
+        add.l   Limit,Scan_Ini
+        sub.w   #MAX_DIST,Limit
+        bhi.s   limit_ok
+        moveq   #0,Limit
+limit_ok:
+        cmp.w   (good_match,pc),Best_Len
+        blo.s   length_ok
+        lsr.w   #2,Chain_Length
+length_ok:
+        subq.w  #1,Chain_Length
+
+    IFDEF   CPUTEST
+        tst.w   is020                   ; can we use '020 stuff today?
+        bne     WORD_match
+    ENDC
+
+    IFNDEF  CPU020
+
+; for 68000 or 68010, use byte operations:
+        moveq   #0,Scan_Start           ; clear 2nd & 4th bytes, use 1st & 3rd
+        moveq   #0,Scan_End             ; likewise
+        moveq   #0,Scan_Test            ; likewise
+        move.b  (Scan_Ini),Scan_Start
+        swap    Scan_Start              ; swap is faster than 8 bit shift
+        move.b  1(Scan_Ini),Scan_Start
+        move.b  -1(Scan_Ini,Best_Len.w),Scan_End
+        swap    Scan_End
+        move.b  0(Scan_Ini,Best_Len.w),Scan_End
+        bra.s   bdo_scan
+
+blong_loop:
+        move.b  -1(Scan_Ini,Best_Len.w),Scan_End
+        swap    Scan_End
+        move.b  0(Scan_Ini,Best_Len.w),Scan_End
+
+bshort_loop:
+        add.w   Cur_Match,Cur_Match     ; assert value before doubling < 32K
+     IFNE   32768-WSIZE
+        and.w   #(WMASK*2),Cur_Match
+     ENDC
+        move.w  (Prev_Address,Cur_Match.l),Cur_Match
+        cmp.w   Limit,Cur_Match
+        dbls    Chain_Length,bdo_scan
+        bra     return
+
+bdo_scan:
+        move.l  Match_Ini,Match
+        add.l   Cur_Match,Match
+        move.b  -MIN_MATCH-1(Match,Best_Len.w),Scan_Test
+        swap    Scan_Test
+        move.b  -MIN_MATCH(Match,Best_Len.w),Scan_Test
+        cmp.l   Scan_Test,Scan_End
+        bne.s   bshort_loop
+        move.b  -MIN_MATCH(Match),Scan_Test
+        swap    Scan_Test
+        move.b  -MIN_MATCH+1(Match),Scan_Test
+        cmp.l   Scan_Test,Scan_Start
+        bne.s   bshort_loop
+        move.w  #(MAX_MATCH-3),Scan_Test
+        lea     MIN_MATCH(Scan_Ini),Scan        ; offset optimizes inner loop
+
+bscan_loop:
+        cmp.b   (Match)+,(Scan)+
+        dbne    Scan_Test,bscan_loop
+        subq    #1,Scan
+
+        sub.l   Scan_Ini,Scan           ; assert difference is 16 bits
+        cmp.w   Best_Len,Scan
+        bls.s   bshort_loop
+        MOVINT  Scan,Best_Len
+        move.w  Cur_Match,match_start
+        cmp.w   (nice_match,pc),Best_Len
+        blo.s   blong_loop
+     IFDEF  CPUTEST
+        bra     return
+     ENDC
+
+    ENDC    ; !CPU020
+
+    IFNDEF  CPU000
+;;;     MACHINE MC68020
+
+; for 68020 or higher, use word operations even on odd addresses:
+WORD_match:
+        move.w  (Scan_Ini),Scan_Start
+        move.w  -1(Scan_Ini,Best_Len.w),Scan_End
+        bra.s   wdo_scan
+
+wlong_loop:
+        move.w  -1(Scan_Ini,Best_Len.w),Scan_End
+
+wshort_loop:
+        and.w   #WMASK,Cur_Match
+        move.w  (Prev_Address,Cur_Match.w*2),Cur_Match  ; '020 addressing mode
+        cmp.w   Limit,Cur_Match
+        dbls    Chain_Length,wdo_scan
+        bra.s   return
+
+wdo_scan:
+        move.l  Match_Ini,Match
+        add.l   Cur_Match,Match
+        cmp.w   -MIN_MATCH-1(Match,Best_Len.w),Scan_End
+        bne.s   wshort_loop
+        cmp.w   -MIN_MATCH(Match),Scan_Start
+        bne.s   wshort_loop
+     IFDEF  QUADLONG
+; By some measurements, this version of the code is a little tiny bit faster.
+; But on some files it's slower.  It probably pays off only when there are
+; long match strings, and costs in the most common case of three-byte matches.
+        moveq   #((MAX_MATCH-MIN_MATCH)/16),Scan_Test     ; value = 15
+        lea     MIN_MATCH(Scan_Ini),Scan        ; offset optimizes inner loop
+
+wscan_loop:
+        cmp.l   (Match)+,(Scan)+                ; test four bytes at a time
+        bne.s   odd
+        cmp.l   (Match)+,(Scan)+
+        bne.s   odd
+        cmp.l   (Match)+,(Scan)+
+        bne.s   odd
+        cmp.l   (Match)+,(Scan)+
+        dbne    Scan_Test,wscan_loop            ; '020 can cache a bigger loop
+odd:
+        subq    #4,Scan
+        subq    #4,Match
+        cmp.b   (Match)+,(Scan)+        ; find good bytes in bad longword
+        bne.s   even
+        cmp.b   (Match)+,(Scan)+
+        bne.s   even
+        cmp.b   (Match)+,(Scan)+
+        beq.s   steven
+even:   subq    #1,Scan
+     ELSE   ; !QUADLONG
+        moveq   #((MAX_MATCH-MIN_MATCH)/2),Scan_Test    ; value = 127
+        lea     MIN_MATCH(Scan_Ini),Scan        ; offset optimizes inner loop
+
+wscan_loop:
+        cmp.w   (Match)+,(Scan)+
+        dbne    Scan_Test,wscan_loop
+        subq    #2,Scan
+        move.b  -2(Match),Scan_Test
+        cmp.b   (Scan),Scan_Test
+        bne.s   steven
+        addq    #1,Scan
+     ENDC   ; ?QUADLONG
+steven:
+        sub.l   Scan_Ini,Scan           ; assert: difference is 16 bits
+        cmp.w   Best_Len,Scan
+        bls.s   wshort_loop
+        MOVINT  Scan,Best_Len
+        move.w  Cur_Match,match_start
+        cmp.w   (nice_match,pc),Best_Len
+        blo.s   wlong_loop
+
+;;;     MACHINE MC68000
+    ENDC    ; !CPU000
+
+return:
+        MOVINT  Best_Len,d0         ; return value (upper half should be clear)
+        movem.l (sp)+,SAVEREGS
+        rts
+
+
+; =============================================================================
+; This is the deflate() function itself, our main entry point.  It calls
+; longest_match, above, and some outside functions.  It is a hot spot, but not
+; as hot as longest_match.  It uses no special '020 code.
+
+; ================== Several macros used in deflate() and later functions:
+
+; Arg 1 is D-reg that new ins_h value is to be left in,
+; arg 2 is the byte value to be hashed into it, which must not be the same reg
+UP_HASH MACRO   _1,_2
+        move.w  (ins_h,pc),_1
+        asl.w   #H_SHIFT,_1
+        eor.b   _2,_1
+        and.w   #HASH_MASK,_1           ; ((ins_h << H_SHIFT) ^ c) & HASH_MASK
+        move.w  _1,ins_h                ; ins_h = that
+        ENDM
+
+; Arg 1 is scratch A, arg 2 is scratch D
+IN_STR  MACRO   _1,_2
+        move.l  Strst,_2
+        addq.w  #MIN_MATCH-1,_2
+        move.b  (Window,_2.l),_2        ; window[strstart + MIN_MATCH - 1]
+        UP_HASH Head,_2
+        add.l   Head,Head               ; assert upper word is zero before add
+        BASEPTR _head,_1
+        add.l   Head,_1
+        move.w  (_1),Head               ; hash_head = head[ins_h]
+        move.w  Strst,(_1)              ; head[ins_h] = strstart
+        move.l  Strst,_2
+    IFNE    WSIZE-32768
+        and.w   #WMASK,_2
+    ENDC
+        add.w   _2,_2                   ; masks implicitly when WSIZE == 32768
+        move.w  Head,(Prev,_2.l)        ; prev[str_start & WMASK] = hash_head
+        ENDM
+
+; Arg 1 is bool (int) EOF flag, flush_block result is in d0, trashes d1/a0/a1
+FLUSH_B MACRO   _1
+        local   nenu,nun
+        movem.l d2/a2,-(sp)
+    IF      _1==0
+        CLRINT  -(sp)
+    ELSEIF (INTSIZE==4).and.(_1<$8000)
+        pea     (_1).w
+    ELSE
+        MOVINT  #_1,-(sp)
+    ENDC
+        move.l  (_block_start,pc),d0
+        blt.s   nenu
+        move.l  Window,a0
+        add.l   d0,a0
+        bra.s   nun
+nenu:   sub.l   a0,a0           ; if block_start < 0, push NULL
+nun:    sub.l   Strst,d0
+        neg.l   d0
+        move.l  d0,-(sp)
+        move.l  a0,-(sp)
+        jsr     _flush_block
+        lea     8+INTSIZE(sp),sp
+        movem.l (sp)+,d2/a2
+        ENDM
+
+; This expands to nothing unless DEBUG is defined.
+; Arg 1 is a byte to be trace-outputted -- if it is d0 it must be a valid int
+TRACE_C MACRO  _1
+        local  qui
+    IFDEF  DEBUG
+        cmp.w  #1,_verbose+INTSIZE-2    ; test lower word only
+        ble.s   qui
+        moveq   #0,d0
+        move.b  ea,d0
+        movem.l d2/a2,-(sp)
+        move.l  _stderr,-(sp)
+        MOVINT  d0,-(sp)
+        jsr     _fputc
+        addq.l  #4+INTSIZE,sp
+        movem.l (sp)+,d2/a2
+qui:
+    ENDC    ; DEBUG
+        ENDM
+
+; ================== Here are the register vars we use, and deflate() itself:
+
+Window  reg     a2              ; cached address of window[]
+Prev    reg     a3              ; cached address of prev[]
+Strst   reg     d7              ; strstart cached as a longword
+Look    reg     d6              ; lookahead cached as short
+Head    reg     d5              ; local variable hash_head, short
+PrevL   reg     d4              ; prev_length cached as short
+MatchL  reg     d3              ; local variable match_length, unsigned short
+Avail   reg     d2              ; local variable available_match, bool
+PrevM   reg     a5              ; local variable prev_match, int in an A-reg
+
+DEFREGS reg     d3-d7/a3/a5
+
+
+_deflate:           ; first, setup steps common to deflate and deflate_fast:
+        movem.l DEFREGS,-(sp)
+    IFDEF   INT16
+        moveq   #0,Strst                ; make sure strstart is valid as a long
+    ENDC
+        moveq   #0,Head                 ; ditto for hash_head
+        MOVINT  (_strstart,pc),Strst
+        move.w  (lookahead,pc),Look
+        move.w  (prev_length,pc),PrevL
+        BASEPTR _window,Window
+        BASEPTR _prev,Prev
+        MOVINT  _level,d0
+        cmp.w   #3,d0
+        ble     deflate_fast
+        moveq   #MIN_MATCH-1,MatchL
+        moveq   #0,Avail
+
+look_loop:
+        tst.w   Look
+        beq     last_tally
+        IN_STR  a0,d0
+        move.w  MatchL,PrevL
+        move.w  (match_start,pc),PrevM
+        move.w  #MIN_MATCH-1,MatchL
+
+        tst.w   Head
+        beq.s   no_new_match
+        cmp.w   (max_lazy_match,pc),PrevL
+        bhs.s   no_new_match
+        move.w  Strst,d0
+        sub.w   Head,d0
+        cmp.w   #MAX_DIST,d0
+        bhi.s   no_new_match
+        move.w  PrevL,prev_length       ; longest_match reads these variables
+        MOVINT  Strst,_strstart
+        MOVINT  Head,d0                 ; parm for longest_match
+        bsr     longest_match           ; sets match_start
+        cmp.w   Look,d0                 ; does length exceed valid data?
+        bls.s   stml
+        move.w  Look,d0
+stml:   move.w  d0,MatchL               ; valid length of match
+        cmp.w   #MIN_MATCH,MatchL       ; is the match only three bytes?
+        bne.s   no_new_match
+        move.w  (match_start,pc),d0
+        sub.w   Strst,d0
+        cmp.w   #-TOO_FAR,d0
+        bge.s   no_new_match
+        moveq   #MIN_MATCH-1,MatchL     ; mark the current match as no good
+
+no_new_match:
+        cmp.w   #MIN_MATCH,PrevL
+        blo     literal
+        cmp.w   MatchL,PrevL
+        blo     literal
+        ; CHECK_MATCH   Strst-1,PrevM,PrevL
+        MOVINT  Strst,_strstart         ; ct_tally reads this variable
+        move.l  PrevL,d0
+        subq.w  #MIN_MATCH,d0
+        movem.l d2/a2,-(sp)
+        MOVINT  d0,-(sp)
+        move.l  Strst,d0
+        sub.w   PrevM,d0
+        subq.w  #1,d0
+        MOVINT  d0,-(sp)
+        jsr     _ct_tally               ; sets d0 true if we have to flush
+        addq    #2*INTSIZE,sp
+        movem.l (sp)+,d2/a2
+        subq.w  #3,PrevL                ; convert for dbra (prev_length - 2)
+        sub.w   PrevL,Look
+        subq.w  #2,Look
+insertmatch:
+        addq.w  #1,Strst
+        IN_STR  a0,d1                   ; don't clobber d0
+        dbra    PrevL,insertmatch
+        moveq   #0,Avail
+        moveq   #0,PrevL                ; not needed?
+        moveq   #MIN_MATCH-1,MatchL
+        addq.w  #1,Strst
+        tst.w   d0
+        beq     refill
+        FLUSH_B 0
+        move.l  Strst,_block_start
+        bra.s   refill
+
+literal:
+        tst.w   Avail
+        bne.s   yeslit
+        moveq   #1,Avail
+        bra.s   skipliteral
+yeslit: TRACE_C <-1(Window,Strst.l)>
+        MOVINT  Strst,_strstart         ; ct_tally reads this variable
+        moveq   #0,d0
+        move.b  -1(Window,Strst.l),d0
+        movem.l d2/a2,-(sp)
+        MOVINT  d0,-(sp)
+        CLRINT  -(sp)
+        jsr     _ct_tally
+        addq    #2*INTSIZE,sp
+        movem.l (sp)+,d2/a2
+        tst.w   d0
+        beq.s   skipliteral
+        FLUSH_B 0
+        move.l  Strst,_block_start
+skipliteral:
+        addq.w  #1,Strst
+        subq.w  #1,Look
+
+refill:
+        cmp.w   #MIN_LOOKAHEAD,Look
+        bhs     look_loop
+        bsr     fill_window
+        bra     look_loop
+
+last_tally:
+        tst.w   Avail
+        beq     last_flush
+        MOVINT  Strst,_strstart         ; ct_tally reads this variable
+        moveq   #0,d0
+        move.b  -1(Window,Strst.l),d0
+        movem.l d2/a2,-(sp)
+        MOVINT  d0,-(sp)
+        CLRINT  -(sp)
+        jsr     _ct_tally
+        addq    #2*INTSIZE,sp
+        movem.l (sp)+,d2/a2
+last_flush:
+        FLUSH_B 1
+        bra     deflate_exit
+
+; ================== This is another version used for low compression levels:
+
+deflate_fast:
+        moveq   #0,MatchL
+        moveq   #MIN_MATCH-1,PrevL
+flook_loop:
+        tst.w   Look
+        beq     flast_flush
+
+        IN_STR  a0,d0
+        tst.w   Head
+        beq.s   fno_new_match
+        move.w  Strst,d0
+        sub.w   Head,d0
+        cmp.w   #MAX_DIST,d0
+        bhi.s   fno_new_match
+        move.w  PrevL,prev_length       ; longest_match reads these variables
+        MOVINT  Strst,_strstart
+        MOVINT  Head,d0                 ; parm for longest_match
+        bsr     longest_match           ; sets match_start
+        cmp.w   Look,d0                 ; does length exceed valid data?
+        bls.s   fstml
+        move.w  Look,d0
+fstml:  move.w  d0,MatchL               ; valid length of match
+
+fno_new_match:
+        cmp.w   #MIN_MATCH,MatchL
+        blo     fliteral
+        ; CHECK_MATCH   Strst,match_start,MatchL
+        MOVINT  Strst,_strstart         ; ct_tally reads this variable
+        move.l  MatchL,d0
+        subq.w  #MIN_MATCH,d0
+        movem.l d2/a2,-(sp)
+        MOVINT  d0,-(sp)
+        move.l  Strst,d0
+        sub.w   (match_start,pc),d0
+        MOVINT  d0,-(sp)
+        jsr     _ct_tally               ; sets d0 true if we have to flush
+        addq    #2*INTSIZE,sp
+        movem.l (sp)+,d2/a2
+        sub.w   MatchL,Look
+        cmp.w   (max_lazy_match,pc),MatchL
+        bhi     ftoolong
+        subq.w  #2,MatchL
+finsertmatch:
+        addq.w  #1,Strst
+        IN_STR  a0,d1                   ; preserve d0
+        dbra    MatchL,finsertmatch
+        moveq   #0,MatchL               ; not needed?
+        addq.w  #1,Strst
+        bra.s   flushfill
+
+ftoolong:
+        add.w   MatchL,Strst
+        moveq   #0,MatchL
+        moveq   #0,d1                   ; preserve d0
+        move.b  (Window,Strst.l),d1
+        move.w  d1,ins_h
+; My assembler objects to passing <1(Window,Strst.l)> directly to UP_HASH...
+        move.b  1(Window,Strst.l),Avail ; Avail is not used in deflate_fast
+        UP_HASH d1,Avail                ; preserve d0
+    IFNE    MIN_MATCH-3
+        FAIL  needs to UP_HASH another MIN_MATCH-3 times, but with what arg?
+    ENDC
+        bra.s   flushfill
+
+fliteral:
+        TRACE_C <(Window,Strst.l)>
+        MOVINT  Strst,_strstart         ; ct_tally reads this variable
+        moveq   #0,d0
+        move.b  (Window,Strst.l),d0
+        movem.l d2/a2,-(sp)
+        MOVINT  d0,-(sp)
+        CLRINT  -(sp)
+        jsr     _ct_tally               ; d0 set if we need to flush
+        addq    #2*INTSIZE,sp
+        movem.l (sp)+,d2/a2
+        addq.w  #1,Strst
+        subq.w  #1,Look
+
+flushfill:
+        tst.w   d0
+        beq.s   frefill
+        FLUSH_B 0
+        move.l  Strst,_block_start
+frefill:
+        cmp.w   #MIN_LOOKAHEAD,Look
+        bhs     flook_loop
+        bsr     fill_window
+        bra     flook_loop
+
+flast_flush:
+        FLUSH_B 1                       ; sets our return value
+
+deflate_exit:
+        MOVINT  Strst,_strstart         ; save back cached values
+        move.w  PrevL,prev_length
+        move.w  Look,lookahead
+        movem.l (sp)+,DEFREGS
+        rts
+
+
+; =========================================================================
+; void fill_window(void) calls the input function to refill the sliding
+; window that we use to find substring matches in.
+
+More    reg     Head                    ; local variable in fill_window
+WindTop reg     Prev                    ; local variable used for sliding
+SlidIx  reg     PrevL                   ; local variable used for sliding
+
+FWREGS  reg     d2-d5/a2-a6             ; does NOT include Look and Strst
+; all registers available to be clobbered by the sliding operation:
+; we exclude More, WindTop, SlidIx, Look, Strst, Window, a4 and a7.
+SPAREGS reg     d0-d3/a0-a1/a5-a6
+SPCOUNT equ     8                       ; number of registers in SPAREGS
+
+
+_fill_window:                           ; C-callable entry point
+        movem.l Look/Strst,-(sp)
+    IFDEF   INT16
+        moveq   #0,Strst                ; Strst must be valid as a long
+    ENDC
+        MOVINT  (_strstart,pc),Strst
+        move.w  (lookahead,pc),Look
+        BASEPTR _window,Window
+        bsr.s   fill_window
+        MOVINT  Strst,_strstart
+        move.w  Look,lookahead
+        movem.l (sp)+,Look/Strst
+        rts
+
+; strstart, lookahead, and window must be cached in Strst, Look, and Window:
+fill_window:                            ; asm-callable entry point
+        movem.l FWREGS,-(sp)
+        move.w  (eofile,pc),d0          ; we put this up here for speed
+        bne     fwdone
+        and.l   #$FFFF,Look             ; make sure Look is valid as long
+fw_refill:
+        move.l  (_window_size,pc),More  ; <= 64K
+        sub.l   Look,More
+        sub.l   Strst,More              ; Strst is already valid as long
+        cmp.w   #EOF,More
+        bne.s   notboundary
+        subq.w  #1,More
+        bra     checkend
+
+notboundary:
+        move.w  (sliding,pc),d0
+        beq     checkend
+        cmp.w   #WSIZE+MAX_DIST,Strst
+        blo     checkend
+    IF      (32768-WSIZE)>0
+        lea     WSIZE(Window),WindTop   ; WindTop is aligned when Window is
+    ELSE
+        move.l  Window,WindTop
+        add.l   #WSIZE,WindTop
+    ENDC
+        move.l  Window,d0
+        and.w   #3,d0
+        beq.s   isaligned
+        subq.w  #1,d0
+align:  move.b  (WindTop)+,(Window)+    ; copy up to a longword boundary
+        dbra    d0,align
+isaligned:
+; This is faster than a simple move.l (WindTop)+,(Window)+ / dbra loop:
+        move.w  #(WSIZE-1)/(4*SPCOUNT),SlidIx
+slide:  movem.l (WindTop)+,SPAREGS      ; copy, 32 bytes at a time!
+        movem.l SPAREGS,(Window)        ; a slight overshoot doesn't matter.
+        lea     4*SPCOUNT(Window),Window        ; can't use (aN)+ as movem.l dest
+        dbra    SlidIx,slide
+        BASEPTR _window,Window                  ; restore cached value
+        sub.w   #WSIZE,match_start
+        sub.w   #WSIZE,Strst
+        sub.l   #WSIZE,_block_start
+        add.w   #WSIZE,More
+        BASEPTR _head,a0
+        move.w  #HASH_SIZE-1,d0
+fixhead:
+        move.w  (a0),d1
+        sub.w   #WSIZE,d1
+        bpl.s   headok
+        moveq   #0,d1
+headok: move.w  d1,(a0)+
+        dbra    d0,fixhead
+        BASEPTR _prev,a0
+        move.w  #WSIZE-1,d0
+fixprev:
+        move.w  (a0),d1
+        sub.w   #WSIZE,d1
+        bpl.s   prevok
+        moveq   #0,d1
+prevok: move.w  d1,(a0)+
+        dbra    d0,fixprev
+        TRACE_C #'.'
+
+        move    _verbose+INTSIZE-2,d0
+        beq     checkend
+        movem.l d2/a2,-(sp)
+        xref    _print_period
+        jsr     _print_period
+        movem.l (sp)+,d2/a2
+
+checkend:                               ; assert eofile is false
+        movem.l d2/a2,-(sp)
+        MOVINT  More,-(sp)              ; assert More's upper word is zero
+        move.l  Strst,d0
+        add.w   Look,d0
+        add.l   Window,d0
+        move.l  d0,-(sp)
+        move.l  _read_buf,a0
+        jsr     (a0)                    ; refill the upper part of the window
+        addq    #4+INTSIZE,sp
+        movem.l (sp)+,d2/a2
+        tst.w   d0
+        beq.s   iseof
+        cmp.w   #EOF,d0
+        beq.s   iseof
+        add.w   d0,Look
+        cmp.w   #MIN_LOOKAHEAD,Look
+        blo     fw_refill               ; eofile is still false
+
+        bra.s   fwdone
+iseof:  move.w  #1,eofile
+fwdone: movem.l (sp)+,FWREGS
+        rts
+
+
+; =========================================================================
+; void lm_free(void) frees dynamic arrays in the DYN_ALLOC version.
+
+;;;     xdef    _lm_free                ; the entry point
+
+_lm_free:
+    IFDEF   DYN_ALLOC
+        move.l  _window,d0
+        beq.s   lf_no_window
+        movem.l d2/a2,-(sp)
+        move.l  d0,-(sp)
+        jsr     _free
+        addq    #4,sp
+        movem.l (sp)+,d2/a2
+        clr.l   _window
+lf_no_window:
+        move.l  _prev,d0
+        beq.s   lf_no_prev
+        movem.l d2/a2,-(sp)
+        move.l  d0,-(sp)
+        jsr     _free
+        move.l  _head,(sp)              ; reuse the same stack arg slot
+        jsr     _free
+        addq    #4,sp
+        movem.l (sp)+,d2/a2
+        clr.l   _prev
+        clr.l   _head
+lf_no_prev:
+    ENDC
+        rts
+
+; ============================================================================
+; void lm_init(int pack_level, unsigned short *flags) allocates dynamic arrays
+; if any, and initializes all variables so that deflate() is ready to go.
+
+;;;     xdef    _lm_init                ; the entry point
+
+Level   reg     d2
+;Window reg     a2      ; as in deflate()
+
+_lm_init:
+        MOVINT  4(sp),d0
+        move.l  4+INTSIZE(sp),a0
+        move.w  d0,Level
+        cmp.w   #1,Level
+        blt.s   levelerr
+        bgt.s   try9
+        bset.b  #B_FAST,1(a0)
+try9:   cmp.w   #9,Level
+        bgt.s   levelerr
+        blt.s   levelok
+        bset.b  #B_SLOW,1(a0)
+        bra.s   levelok
+levelerr:
+        pea     (level_message,pc)
+        jsr     _error                  ; never returns
+levelok:
+        clr.w   sliding
+        move.l  (_window_size,pc),d0
+        bne.s   gotawindowsize
+        move.w  #1,sliding
+        move.l  #2*WSIZE,_window_size
+gotawindowsize:
+
+        BASEPTR _window,Window
+    IFDEF   DYN_ALLOC
+        move.l  Window,d0               ; fake tst.l
+        bne.s   gotsomewind
+        CAL_SH  WSIZE
+        move.l  d0,Window
+        move.l  d0,_window
+        bne.s   gotsomewind
+        pea     (window_message,pc)
+        bra     error
+gotsomewind:
+        tst.l   _prev
+        bne.s   gotsomehead
+        CAL_SH  WSIZE
+        move.l  d0,_prev
+        beq.s   nohead
+        CAL_SH  HASH_SIZE
+        move.l  d0,_head
+        bne.s   gotfreshhead            ; newly calloc'd memory is zeroed
+nohead: pea     (hash_message,pc)
+error:  MOVINT  #ZE_MEM,-(sp)
+        jsr     _ziperr                 ; never returns
+gotsomehead:
+    ENDC    ; DYN_ALLOC
+
+        move.w  #(HASH_SIZE/2)-1,d0     ; two shortwords per loop
+        BASEPTR _head,a0
+wipeh:  clr.l   (a0)+
+        dbra    d0,wipeh
+gotfreshhead:
+        move.l  Level,d0
+    IFEQ    Sizeof_config-8
+        asl.l   #3,d0
+    ELSE
+        mulu    #Sizeof_config,d0
+    ENDC
+        lea     (config_table,pc),a0
+        add.l   d0,a0
+        move.w  Max_lazy(a0),max_lazy_match
+        move.w  Good_length(a0),good_match
+        move.w  Nice_length(a0),nice_match
+        move.w  Max_chain(a0),max_chain_len
+        CLRINT  _strstart
+        clr.l   _block_start
+        bsr     match_init
+
+        clr.w   eofile
+        movem.l d2/a2,-(sp)
+        MOVINT  #WSIZE,-(sp)    ; We read only 32K because lookahead is short
+        move.l  Window,-(sp)    ; even when int size is long, as if deflate.c
+        move.l  _read_buf,a0    ; were compiled with MAXSEG_64K defined.
+        jsr     (a0)
+        addq    #4+INTSIZE,sp
+        movem.l (sp)+,d2/a2
+        move.w  d0,lookahead
+        beq.s   noread
+        cmp.w   #EOF,d0
+        bne.s   irefill
+noread: move.w  #1,eofile
+        clr.w   lookahead
+        bra.s   init_done
+
+irefill:
+        move.w  (lookahead,pc),d0
+        cmp.w   #MIN_LOOKAHEAD,d0
+        bhs.s   hashify
+        bsr     _fill_window            ; use the C-callable version
+hashify:
+        clr.w   ins_h
+        moveq   #MIN_MATCH-2,d0
+hash1:  move.b  (Window)+,d1
+        UP_HASH Level,d1
+        dbra    d0,hash1
+
+init_done:
+        rts
+
+; strings for error messages:
+    IFDEF   DYN_ALLOC
+hash_message    dc.b    'hash table allocation',0
+window_message  dc.b    'window allocation',0
+    ENDC
+level_message   dc.b    'bad pack level',0
+
+        end
diff --git a/human68k/human68k.c b/human68k/human68k.c
new file mode 100644 (file)
index 0000000..5e489e1
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include "zip.h"
+
+#include <time.h>
+#include <stdio.h>
+#include <dirent.h>
+#ifndef UTIL
+#include <sys/dos.h>
+#endif
+
+#define MATCH shmatch
+
+#define PAD 0
+
+
+#ifndef UTIL
+
+/* Library functions not in (most) header files */
+
+int utime OF((char *, ztimbuf *));
+
+/* Local functions */
+local char *readd OF((DIR *));
+
+local char *readd(DIR* d)
+{
+   struct dirent* e = readdir(d);
+
+   return e == NULL ? NULL : e->d_name;
+}
+
+int wild(char* w)
+{
+  struct _filbuf inf;
+  char name[FNMAX];
+  char *p;
+
+  if (strcmp(w, "-") == 0)   /* if compressing stdin */
+    return newname(w, 0, 0);
+  strcpy(name, w);
+  _toslash(name);
+
+  if ((p = strrchr(name, '/')) == NULL && (p = strrchr(name, ':')) == NULL)
+    p = name;
+  else
+    p++;
+  if (_dos_lfiles (&inf, w, 0xff) < 0)
+    return ZE_MISS;
+  do {
+    int r;
+
+    strcpy(p, inf.name);
+    r = procname(name, 0);
+    if (r != ZE_OK)
+      return r;
+  } while (_dos_nfiles(&inf) >= 0);
+
+  return ZE_OK;
+}
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  char *a;              /* path and name for recursion */
+  DIR *d;               /* directory stream from opendir() */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (LSSTAT(n, &s))
+  {
+    /* Not a file or directory--search for shell expression in zip file */
+    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+  _toslash(n);
+  if ((s.st_mode & S_IFDIR) == 0)
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  } else {
+    /* Add trailing / to the directory name */
+    if ((p = malloc(strlen(n)+2)) == NULL)
+      return ZE_MEM;
+    if (strcmp(n, ".") == 0) {
+      *p = '\0';  /* avoid "./" prefix and do not create zip entry */
+    } else {
+      strcpy(p, n);
+      a = p + strlen(p);
+      if (a[-1] != '/')
+        strcpy(a, "/");
+      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+        free((zvoid *)p);
+        return m;
+      }
+    }
+    /* recurse into directory */
+    if (recurse && (d = opendir(n)) != NULL)
+    {
+      while ((e = readd(d)) != NULL) {
+        if (strcmp(e, ".") && strcmp(e, ".."))
+        {
+          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+          {
+            closedir(d);
+            free((zvoid *)p);
+            return ZE_MEM;
+          }
+          strcat(strcpy(a, p), e);
+          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
+          {
+            if (m == ZE_MISS)
+              zipwarn("name not matched: ", a);
+            else
+              ziperr(m, a);
+          }
+          free((zvoid *)a);
+        }
+      }
+      closedir(d);
+    }
+    free((zvoid *)p);
+  } /* (s.st_mode & S_IFDIR) == 0) */
+  return ZE_OK;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t;              /* shortened name */
+
+  /* Find starting point in name before doing malloc */
+  t = (x[0] && x[1] == (char)':') ? x + 2 : x;
+  while (*t == (char)'/')
+    t++;
+
+  /* Make changes, if any, to the copied name (leave original intact) */
+  _toslash(t);
+
+  if (!pathput)
+    t = last(t, '/');
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL)
+    return NULL;
+  strcpy(n, t);
+
+  if (dosify)
+    msname(n);
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosify;
+  return n;
+}
+
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+      return NULL;
+  return strcpy(x, n);
+}
+
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+  ztimbuf u;            /* argument for utime() */
+
+  /* Convert DOS time to time_t format in u */
+  u.actime = u.modtime = dos2unixtime(d);
+
+  /* Set updated and accessed times of f */
+  utime(f, &u);
+}
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  char *name;
+  unsigned int len = strlen(f);
+  int isstdin = !strcmp(f, "-");
+
+  if ((name = malloc(len + 1)) == NULL) {
+    ZIPERR(ZE_MEM, "filetime");
+  }
+  strcpy(name, f);
+  if (name[len - 1] == '/')
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+
+  if (isstdin) {
+    if (fstat(fileno(stdin), &s) != 0) {
+      free(name);
+      error("fstat(stdin)");
+    }
+  } else if (LSSTAT(name, &s) != 0) {
+             /* Accept about any file kind including directories
+              * (stored with trailing / with -r option)
+              */
+    free(name);
+    return 0;
+  }
+
+  if (a != NULL) {
+    int atr = _dos_chmod(name, -1);
+
+    if (atr < 0)
+      atr = 0x20;
+    *a = ((ulg)s.st_mode << 16) | (isstdin ? 0L : (ulg)atr);
+  }
+  if (n != NULL)
+    *n = S_ISVOL(s.st_mode) ? -2L : S_ISREG(s.st_mode) ? s.st_size : -1L;
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = s.st_ctime;
+  }
+
+  free(name);
+
+  return unix2dostime(&s.st_mtime);
+}
+
+int set_extra_field(z, z_utim)
+  struct zlist far *z;
+  iztimes *z_utim;
+  /* create extra field and change z->att if desired */
+{
+#ifdef USE_EF_UT_TIME
+  if ((z->extra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL)
+    return ZE_MEM;
+
+  z->extra[0]  = 'U';
+  z->extra[1]  = 'T';
+  z->extra[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */
+  z->extra[3]  = 0;
+  z->extra[4]  = EB_UT_FL_MTIME;
+  z->extra[5]  = (char)(z_utim->mtime);
+  z->extra[6]  = (char)(z_utim->mtime >> 8);
+  z->extra[7]  = (char)(z_utim->mtime >> 16);
+  z->extra[8]  = (char)(z_utim->mtime >> 24);
+
+  z->cext = z->ext = (EB_HEADSIZE+EB_UT_LEN(1));
+  z->cextra = z->extra;
+
+  return ZE_OK;
+#else /* !USE_EF_UT_TIME */
+  return (int)(z-z);
+#endif /* ?USE_EF_UT_TIME */
+}
+
+int deletedir(d)
+char *d;                /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+   Return the result of rmdir(), delete(), or system().
+   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).
+ */
+{
+    return rmdir(d);
+}
+
+void print_period(void)
+{
+  fputc('.', stderr);
+}
+
+#endif /* !UTIL */
+
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+void version_local()
+{
+    static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
+#if 0
+    char buf[40];
+#endif
+
+    printf(CompiledWith,
+
+#ifdef __GNUC__
+      "gcc ", __VERSION__,
+#else
+#  if 0
+      "cc ", (sprintf(buf, " version %d", _RELEASE), buf),
+#  else
+      "unknown compiler", "",
+#  endif
+#endif
+
+      "Human68k",
+#ifdef __MC68020__
+      " (X68030)",
+#else
+      " (X680x0)",
+#endif
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+      );
+
+} /* end function version_local() */
diff --git a/human68k/match.s b/human68k/match.s
new file mode 100644 (file)
index 0000000..4e6bc1c
--- /dev/null
@@ -0,0 +1,163 @@
+*===========================================================================
+* Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+*
+* See the accompanying file LICENSE, version 1999-Oct-05 or later
+* (the contents of which are also included in zip.h) for terms of use.
+* If, for some reason, both of these files are missing, the Info-ZIP license
+* also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*===========================================================================
+*
+* match.s -- optional optimized asm version of longest match in deflate.c
+* Written by Jean-loup Gailly
+*
+* Adapted for X68000 by NIIMI Satoshi <a01309@cfi.waseda.ac.jp>
+* Adapted for the Amiga by Carsten Steger <stegerc@informatik.tu-muenchen.de>
+* using the code in match.S.
+* The major change in this code consists of removing all unaligned
+* word accesses, because they cause 68000-based machines to crash.
+* For maximum speed, UNALIGNED_OK can be defined.
+* The program will then only run on 68020-based machines, though.
+
+
+Cur_Match       reg     d0      ; Must be in d0!
+Best_Len        reg     d1
+Loop_Counter    reg     d2
+Scan_Start      reg     d3
+Scan_End        reg     d4
+Limit           reg     d5
+Chain_Length    reg     d6
+Scan_Test       reg     d7
+Scan            reg     a0
+Match           reg     a1
+Prev_Address    reg     a2
+Scan_Ini        reg     a3
+Match_Ini       reg     a4
+
+MAX_MATCH       equ     258
+MIN_MATCH       equ     3
+WSIZE           equ     32768
+MAX_DIST        equ     WSIZE-MAX_MATCH-MIN_MATCH-1
+
+
+        .xref   _max_chain_length
+        .xref   _prev_length
+        .xref   _prev
+        .xref   _window
+        .xref   _strstart
+        .xref   _good_match
+        .xref   _match_start
+        .xref   _nice_match
+
+
+        .xdef   _match_init
+        .xdef   _longest_match
+
+        .text
+        .even
+
+
+_match_init:
+        rts
+
+
+_longest_match:
+        move.l  4(sp),Cur_Match
+.ifdef  UNALIGNED_OK
+        movem.l d2-d6/a2-a4,-(sp)
+.else
+        movem.l d2-d7/a2-a4,-(sp)
+.endif
+        move.l  _max_chain_length,Chain_Length
+        move.l  _prev_length,Best_Len
+        lea     _prev,Prev_Address
+        lea     _window+MIN_MATCH,Match_Ini
+        move.l  _strstart,Limit
+        move.l  Match_Ini,Scan_Ini
+        add.l   Limit,Scan_Ini
+        subi.w  #MAX_DIST,Limit
+        bhi.b   limit_ok
+        moveq   #0,Limit
+limit_ok:
+        cmp.l   _good_match,Best_Len
+        bcs.b   length_ok
+        lsr.l   #2,Chain_Length
+length_ok:
+        subq.l  #1,Chain_Length
+
+.ifdef  UNALIGNED_OK
+        move.w  -MIN_MATCH(Scan_Ini),Scan_Start
+        move.w  -MIN_MATCH-1(Scan_Ini,Best_Len.w),Scan_End
+.else
+        move.b  -MIN_MATCH(Scan_Ini),Scan_Start
+        lsl.w   #8,Scan_Start
+        move.b  -MIN_MATCH+1(Scan_Ini),Scan_Start
+        move.b  -MIN_MATCH-1(Scan_Ini,Best_Len.w),Scan_End
+        lsl.w   #8,Scan_End
+        move.b  -MIN_MATCH(Scan_Ini,Best_Len.w),Scan_End
+.endif
+
+        bra.b   do_scan
+
+long_loop:
+
+.ifdef  UNALIGNED_OK
+        move.w  -MIN_MATCH-1(Scan_Ini,Best_Len.w),Scan_End
+.else
+        move.b  -MIN_MATCH-1(Scan_Ini,Best_Len.w),Scan_End
+        lsl.w   #8,Scan_End
+        move.b  -MIN_MATCH(Scan_Ini,Best_Len.w),Scan_End
+.endif
+
+short_loop:
+        lsl.w   #1,Cur_Match
+        move.w  0(Prev_Address,Cur_Match.l),Cur_Match
+        cmp.w   Limit,Cur_Match
+        dbls    Chain_Length,do_scan
+        bra.b   return
+
+do_scan:
+        move.l  Match_Ini,Match
+        add.l   Cur_Match,Match
+
+.ifdef  UNALIGNED_OK
+        cmp.w   -MIN_MATCH-1(Match,Best_Len.w),Scan_End
+        bne.b   short_loop
+        cmp.w   -MIN_MATCH(Match),Scan_Start
+        bne.b   short_loop
+.else
+        move.b  -MIN_MATCH-1(Match,Best_Len.w),Scan_Test
+        lsl.w   #8,Scan_Test
+        move.b  -MIN_MATCH(Match,Best_Len.w),Scan_Test
+        cmp.w   Scan_Test,Scan_End
+        bne.b   short_loop
+        move.b  -MIN_MATCH(Match),Scan_Test
+        lsl.w   #8,Scan_Test
+        move.b  -MIN_MATCH+1(Match),Scan_Test
+        cmp.w   Scan_Test,Scan_Start
+        bne.b   short_loop
+.endif
+
+        move.w  #(MAX_MATCH-MIN_MATCH),Loop_Counter
+        move.l  Scan_Ini,Scan
+scan_loop:
+        cmpm.b  (Match)+,(Scan)+
+        dbne    Loop_Counter,scan_loop
+
+        sub.l   Scan_Ini,Scan
+        addq.l  #(MIN_MATCH-1),Scan
+        cmp.l   Best_Len,Scan
+        bls.b   short_loop
+        move.l  Scan,Best_Len
+        move.l  Cur_Match,_match_start
+        cmp.l   _nice_match,Best_Len
+        bcs.b   long_loop
+return:
+        move.l  Best_Len,d0
+.ifdef  UNALIGNED_OK
+        movem.l (sp)+,d2-d6/a2-a4
+.else
+        movem.l (sp)+,d2-d7/a2-a4
+.endif
+        rts
+
+        end
diff --git a/human68k/osdep.h b/human68k/osdep.h
new file mode 100644 (file)
index 0000000..088a9ac
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#include <io.h>
+#include <sys/stat.h>
+#include <sys/xglob.h>
+
+#ifdef ZCRYPT_INTERNAL
+#  include <process.h>          /* getpid() declaration for srand seed */
+#endif
+
+#define USE_CASE_MAP
+
+#define ROUNDED_TIME(time)  (((time) + 1) & (~1))
+
+#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \
+                     procname(n, 1))
+
+#ifdef HAVE_MBCTYPE_H
+#  include <mbctype.h>
+#else
+#  define ismbblead(c) (0x80 <= (c) && ((c) < 0xa0 || 0xe0 <= (c)))
+#endif
diff --git a/human68k/zipup.h b/human68k/zipup.h
new file mode 100644 (file)
index 0000000..592cff8
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#define fhow (O_RDONLY|O_BINARY)
+#define fbad (-1)
+typedef int ftype;
+#define zopen(n,p) open(n,p)
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f) close(f)
+#define zerr(f) (k == (extent)(-1L))
+#define zstdin 0
diff --git a/macos/Contents b/macos/Contents
new file mode 100644 (file)
index 0000000..3aec069
--- /dev/null
@@ -0,0 +1,63 @@
+Contents of the "macos" sub-archive for Zip 2.3 and later:
+
+
+MacOS:
+
+  Contents          this file
+  readme.1st        Instruction to unpack mac specific files
+  README.TXT        Dirk Haase's infos on updated MacIntosh ports of Zip/UnZip
+  HISTORY.TXT       Dirk Haase's MacOS specific ChangeLog
+
+  zipup.h           MacOS
+  osdep.h           MacOS specific configuration and declarations
+
+  ZipLib.h          used to build a static library, global to the project
+  ZipSx.h           used to build a standalone App with MW Sioux, global
+                    to the project
+  ZpPrj.hqx         Metrowerks CodeWarrior pro3 project file (BinHex)
+
+
+  source/        subdirectory containing all sources:
+                  a) Zip specific code
+    extrafld.c      contains all code related to the mac extra field
+    extrafld.h
+    macglob.h
+    macopen.c       replaces fopen() and open()
+    macopen.h
+    macos.c         Macintosh-specific routines for use with Info-ZIP's Zip
+    MatWild.c       Pattern matching function
+    recurse.c       Functions to go through the directories
+    recurse.h
+    unixlike.c      This file provides a unix like file-stat routine
+    unixlike.h
+    VolWarn.h       contains the warning message, about volumes with the
+                    same name
+    zip_rc.hqx      resource file for Macintosh unzip (BinHex)
+
+
+                  b) general utilities shared between Zip and UnZip
+    charmap.h       character mapping tables ISO 8859-1 <--> MacRoman
+    helpers.c       some helper functions
+    helpers.h
+    macstuff.c      Mac filemanager routines copied from MoreFiles 1.4.8
+    macstuff.h
+    mactime.c       replacement for broken Metrowerks RTL time functions
+    pathname.c      functions for handling MacOS HFS path- /filenames
+    pathname.h
+
+The new ZpPrj.hqx project file should be "un-BinHex'ed" into ZpPrj,
+which builds the following targets:
+        - Zip Lib (68K)   -> static library 68k
+        - Zip Lib (PPC)   -> static library PPC
+        - Zip Sioux (68K) -> MW Sioux standalone App, good for debugging
+        - Zip Sioux (PPC) -> MW Sioux standalone App, good for debugging
+
+
+The resource files and the compiler project files are in BinHex form because
+they contain Macintosh resource forks.  The resource info cannot be
+maintained when handling (e.g. repacking) the master source collection on
+non-Macintosh systems.  The BinHex form is the traditional way for
+transferring such files via non-Macintosh systems.
+It's also the safest since it uses only printable characters.  The ".hqx"
+files must be converted with StuffitExpander or BinHex 4.0 (or equivalent)
+on a Macintosh system before using them.
diff --git a/macos/HISTORY.TXT b/macos/HISTORY.TXT
new file mode 100644 (file)
index 0000000..2720e55
--- /dev/null
@@ -0,0 +1,489 @@
+Macintosh Port of Info-ZIP's Zip
+By Dirk Haase, d_haase@sitec.net
+Home page: www.sitec.net/maczip
+Mirror page:
+www.haase-online.de/dirk/maczip
+================================
+
+
+
+
+Release MacZip ver1.04 beta 2
+02. June 1999
+--------------
+
+1) FIX: {unzip} added one more criteria to make the recognition
+         of macbinary more save.
+
+2) FIX: {unzip} sometimes, archive entries without any extra field
+         caused problems; the default setting of the extra field
+         was not set back to 'unknown' properly.
+
+3) FIX: {zip} Archive filename with invalid characters like '/' gets
+         renamed. However, I do not check the complete path - needs
+         some more work here.
+
+4) FIX: {zip} Filename match was case sensitive.
+
+6) CHG: {zip) switch to latest source level
+         unzip 2.30m beta release
+
+7) CHG: {unzip) switch to latest source level
+         unzip 5.41b beta release
+
+8) FIX: {zip/unzip 68k only) I have found a wrong compiler setting
+         for the 68k version. Because of this wrong setting the 68k
+         version crashed.
+
+
+
+
+Release MacZip ver1.04 beta 1
+30. March 1999
+--------------
+
+1) CHG: {unzip) switch to latest source level
+         unzip 5.41a beta release
+
+2) ADD: {all} Added message logging support for Syslogd
+        by Brian Bergstrand. Syslogd can be found at
+        http://www.classicalguitar.net/brian/apps/syslogd/
+        This feature is 'under construction'.
+
+3) FIX: {all} many small fixes and code cleanups
+
+
+
+
+Release MacZip ver1.03
+27. March 1999
+--------------
+
+1) CHG: {console} Like Stuffit Expander MacZip quits automatically when
+         used with drag'n drop or as Helper App (Web-Browser).
+
+2) CHG: {console} Since Macintosh users are used to be guided by their
+        software in order not to do something stupid, I added a check
+        to post an extra warning if the options -m and data fork only
+        are both checked.
+        This behavior can be disabled: See Applescript example and
+        "maczip.env".
+
+3) CHG: {zip} switch from immediate deletion to moving to the
+        trash. Immediate deletion is now an option in "maczip.env".
+
+4) CHG: {zip} enhanced progress display.
+
+5) CHG: {zip) switch to latest source level
+         zip 2.3l beta release
+
+6) CHG: {unzip} The zip archive contains file names greater than
+        31 characters. When MacZip tries to unzip the file, the
+        FSpCreate command fails because the filename length is to
+        long. MacZip correct this problem by trying to truncate
+        the file names to the 31 character limit.
+
+7) FIX: {zip/console} A couple of minor fixes
+
+8) CHG: {zip} Switched file-globbing to the Info-ZIP version.
+
+
+
+
+Release MacZip ver1.02
+14. February 1999
+-----------------
+
+1) CHG: {zip} Changed the rule of file inclusion if switch '-X'
+        is set. Following conditions are checked:
+        a) if length of resource-fork is equal zero *and* the
+              length of     data-fork is equal zero include the file.
+        b) if length of resource-fork  greater zero *and* the
+              length of     data-fork is equal zero don't include the file.
+        c) if length of     data-fork  greater zero include the file.
+
+2) CHG: {Console} Some users are very confused by the buttons "START PATH"
+        and "ZIP ARCHIVE". Somehow, it wasn't clear what the intended
+        meaning was. I changed the buttons to more clear labels on
+        them like: "file or folder to compress" and "location of
+        compressed file"
+
+3) CHG: {Console} I changed the menu structure to be more intuitive.
+
+4) FIX: {Console} Found a nasty bug which sometimes caused crashes
+        when the Zip / Unzip Dialogbox was used.
+
+5) CHG: {Console} Handling of file dialog is now a bit more restricted:
+        e.g: it's not possible to select a file if you have to select
+        a folder.
+
+
+
+
+Release MacZip ver1.01
+30. January 1999
+----------------------
+
+1) CHG: {console} The use of the "Current App" mechanism was clumsy
+        and forces the user into the Zip or Unzip modes. This kind
+        of modality is not so good for the command line. It's now
+        neccessary to enter zip or unzip to choose the action.
+
+2) FIX: {console} When Applescript sends quit to MacZip the script
+        that is running shows a spinning cursor and MacZip
+        does not quit.
+
+3) FIX: {console} MacZip gots accidentally the wrong creator code
+        (from BBedit)
+
+
+
+
+Final Release MacZip ver1.0
+---------------------------
+
+Released 21. January 1999
+
+
+
+
+9. Beta release 06.December.1998
+---------------------------------
+
+1) CHG: {console} The checkbox of Filedialog (for extract path and file path)
+        "Show all files" is now selected by default.
+
+2) CHG: {unzip/standalone} changed prototypes of mac[f]printf() to return
+        an int number (better ANSI conformance);
+
+3) FIX: {unzip} repaired "stdout/stderr" mode of macwrite(). So func
+        MacMessagePrnt() is now obsolete and removed.
+
+4) ADD: {zip/unzip} Compressed Mac3 extra-fields are now supported
+        (Thanks to Christian Spieler)
+
+5) ADD: {unzip} Extraction of ZipIt archive are now supported. This support
+        is not complete: Filenames are correct but folder names are only
+        restored with the public directory names.
+
+6) ADD: {zip/unzip} Improved documentation.
+
+7) FIX: {unzip} Function isZipfile() is completely rewritten.
+
+8) CHG: {zip/unzip) switch to latest source level
+        zip 2.3i beta and unzip 5.4 final release
+
+9) ADD: Applescript event "do_cmd".
+
+Unless there are big bugs found, this release will be the last
+beta release. The final release will come out in January 1999.
+
+
+
+
+8. Beta release 20.November.1998
+---------------------------------
+
+1) CHG: {zip/unzip) switch to latest source level
+        zip 2.3h beta and unzip 5.4 final release
+
+2) ADD: {zip} Zip finds "namelocked" files also, if switch "-S"
+        is set.
+
+3) FIX: {unzip} Function isZipfile() fails if the zip archive
+        has a comment.
+
+4) CHG: {zip} added some small speed improvements to pattern matching and
+        isZipFile() function.
+
+5) FIX: {unzip} Display of comments is fixed.
+        UzpMessagePrnt() is replaced by MacMessagePrnt(). I do not care
+        about ansi-bombs. I'm not sure, so this fix may be changed later.
+
+6) RMV: {unzip} Buildin More capability is removed since it's already built
+        into the GUI-App.
+
+
+
+7. Beta release 09.November.1998
+---------------------------------
+
+1) CHG: {all} switched to Metrowerks Codewarrior Pro 4
+
+2) FIX: {unzip} Display of comments stored in the zip-file is
+        now fixed
+
+3) FIX: {zip} Fixed display of the zip help-screen.
+
+4) CHG: {zip/unzip} Changed special dir 'Re$0urce.Fk' to 'XtraStuf.mac'
+        (see entry at 13.June.1998 item 3). I found it more descriptive for
+        users outside the mac-community.
+
+5) CHG: {all} switched to MoreFiles 1.4.9.
+
+6) CHG: {console} changed behaivor of the file open dialog: The select
+        button is now always enabled.
+
+7) ADD: {all} Environment variables are now supported.
+         Basically, it is possible to add timezone (= TZ environment variable)
+         support here, but it's not yet implemented.
+         See "MacZip.Env" for further info.
+
+8) RMV: {console} Targets "zip only" and "unzip only" are removed.
+
+
+
+6. Beta release 09.September.1998
+---------------------------------
+
+
+1) CHG: {Zip/Unzip} Metrowerks Standardlibrary time funktions are
+        rather broken and incomplete so I was forced to rewrite the
+        funktions: mktime(), localtime(), gmtime() and time().
+
+2) ADD: {Console} Added Pause Funktion for screen output.
+        The Pause-Function is selfadjusting: Count of lines is depending
+        on the window size.
+
+3) CHG: Extra-Field layout is changed: All datas are now in little-endian
+        format (see appnote)
+
+4) ADD: {Console} Added an option to test the archive automatically
+        after zipping. This option is only via Zip-Dialogbox available
+        because it needs the unzip-module also.
+
+5) CHG: {Zip} code is now up to date with the latest beta 2.3f.
+
+6) ADD: {Console} Added (drag'n) drop support. Drop on the MacZip icon.
+        The following situations are supported:
+                    1. drop of one or more zipfiles (action = unzip)
+                       each archive will be extracted in a separate folder
+                    2. drop of a folder (action = zip -r )
+                       The complete folder (inclusive sub-folders)
+                       will be zipped
+        Not (yet) supported is currently: dropping more than one file
+        to compress. Workaround: Put all your files in one folder and
+        drop that folder on MacZip.
+        MacZip recognize zip-archives automatically.
+
+
+5. Beta release 21.Aug.1998
+----------------------------
+
+
+1) ADD: {Console} Userinterface has now a Statusbar to show the
+        Progress.
+
+2) ADD: {Console} It's now possible to stop the run of Zip/Unzip
+        with the well known shortcut [Command] + [.]
+
+3) CHG: {Console} Improved user-entry routine.
+
+4) ADD: {Zip/Unzip} Crypt-code added. It's now possible to
+        encrypt/decrypt archives.
+
+5) RMV: {Unzip} Removed the warning of PKZip/Mac archive.
+        Unzip gets confused with the extra field of PKZip/Mac. So I assume
+        the extra field isn't compatible with Info-ZIP's definition.
+
+6) CHG: switched to Metrowerks Codewarrior Pro 3
+        this includes:
+        - new Universal Interfaces 3.1 Headers
+        - improved codegeneration
+
+7) CHG: {Zip} code is now up to date with the latest beta 2.3e.
+
+8) CHG: {Unzip} changed function names wprintf, wgets .. to macprintf, macgets ..
+        to avoid naming conflict standart library.
+
+9) ADD: {Zip/Unzip} FXinfo, Mac-Pathname, file-dates and Finder-Comments
+        are now stored in the extra-field. Extra-field layout is
+        changed accordingly. Unzip uses now the filename stored in the
+        extra-field when unzipping.
+
+10) CHG: {Unzip} code is now up to date with the latest beta 5.33g.
+
+11) CHG: {Unzip} code is (again) up to date with the latest beta 5.33h.
+
+12) ADD: {Unzip} following switches were added:
+       -J     [MacOS  only] ignore mac extra info. All macintosh
+              info are not restored. Datafork and resource-fork
+              are restored separatly.
+
+       -i     [MacOS  only] ignore filenames stored in mac extra
+              field. Use the most compatible filename stored in
+              the public field.
+
+       -E     [MacOS  only] show mac extra field during restoring
+
+13) ADD: {Zip/Unzip} Charset MacRoman to ISO8859 Latin and vice versa
+
+14) RMV: {Zip} -N option removed. This MacZip crashes using this option.
+         I will fix it later.
+
+
+I think I'm very close for a final release of "MacZip 1.0" :-)
+
+
+
+4. Beta release 27.June.1998
+----------------------------
+
+26.June.1998
+------------
+
+1) FIX: {Zip} extra field size value was wrong.
+
+
+
+25.June.1998
+------------
+
+1) CHG: {Zip} code is now up to date with the latest beta 2.3d.
+        So both modules, zip & unzip, uses now latest beta.
+
+2) ADD: {Zip} added a UT extra-field for better compatibility.
+
+3) CHG: {Unzip} changed the code to find the mac extra-field.
+        Unzip has to look for a mac extra-field because
+        mac-archives has now two extra-fields (UT + M3).
+
+4) CHG: {Unzip} changed the method to move extra-field data to
+        the internal extra-structure.
+        Old method was just BlockMove of the ef_structptr to ef_memptr.
+        This method was dangerous because not all members of the
+        structure seamless aligned. There are may be some fill
+        bytes in the structure depending on the compiler setting.
+
+5) ADD: {Unzip} added a warning if unzipping a ZipIt/PKZip archive.
+        ZipIt/PKZip archives are usually additionally coded somehow.
+        InfoZip's Unzip will *not* decode the files. So extracted
+        files are may be not decoded. (see also 6. and 7.)
+
+6) ADD: ZipIt (the Shareware Tool) has now a new extra-field signature:
+        0x2705. Found in "ZipIt 1.3.8". I added a new macro: EF_ZIPIT2
+
+7) ADD: Added PKWare's extra-field signature: 0xCF77.
+        Found in "PKZIP v2.03". I added a new macro: EF_PKMAC
+
+8) ADD: {console} It's now possible to save all screen outputs
+        to the disk.
+
+9) RMV: {console} this is the first beta without expire-date.
+
+
+16.June.1998
+------------
+
+1) FIX: {Unzip/console} Extract path now defaults to current-dir if
+        no path is given.
+
+2> CHG: {Unzip} creates now a extract-folder by default. This behavior
+        differs to the commandline tool of Unzip on other platforms.
+        However, for a mac-user is this behavior more convenient.
+
+
+3. Beta release 15.June.1998
+----------------------------
+
+15.June.1998
+------------
+
+1) CHG: {unzip/zip} I changed the layout of the extra field
+        to support more data.
+
+
+14.June.1998
+------------
+
+1) FIX: {Unzip} adjusted time_t value with an correct offset value.
+
+2) FIX: {Unzip} removed all unused code based on unfinished ideas by
+        former porter(s).
+
+3) CHG: use of shared code izshr 032.
+
+13.June.1998
+------------
+
+1) FIX: {Unzip} Filenames are only converted when needed. When zipping
+        with the switch 'datafork only' the filenames are shorted which
+        was wrong.
+
+2) CHG: {Unzip} code is now up to date with the latest beta 5.33f.
+
+3) CHG: {Zip} Changed the naming rule of filenames from old Johnny Lee's
+        to my implementation. Johnny Lee's idea is based on change of the
+        filenames which cases several problems when unziping on a non mac
+        plattform. My idea is to add a special directory: 'Re$0urce.Fk'.
+        For the future: Zip will create archives according the new nameing
+        rule. However unzip will be compatible with old nameing rule.
+        See also 4.
+
+4} ADD: {Unzip} Added a new nameing rule for resource forks filename.
+        Resource forks are now stored in a special directory: 'Re$0urce.Fk'.
+        This naming rule make it easier to for other platforms to use
+        mac zip-files.
+
+
+
+11.June.1998
+------------
+1) FIX: {Zip} Internal file attribute is set to BINARY by default
+        when zipping resource forks otherwise Unzip will create
+        sometimes wrong resource-forks.
+
+2) CHG: {Unzip} code is now up to date with the latest beta 5.33e.
+
+
+
+
+2. Beta release 10.June.1998
+--------------------------
+
+1) FIX: {Unzip} Long pathname fix solved. Unzip is now able to extract
+        archives with path longer than 256 chars.
+
+2) CHG: {Unzip} removed all conversion from c-style string to
+        pascal-string (see fix 1)
+
+3) ADD: {Unzip} Finderinfo of folders are also restored.
+
+4) ADD: {Console} Added info about current path in the command-line box.
+
+5) FIX: {Console} Construction of the command-line of the unzip-dialog
+        box fixed.
+
+
+
+First beta release 06.June.1998
+-----------------------------
+
+no history.
+Just to many code was neccessary to build the first mac-port.
+
+
+Start of the port MacZip
+February 1998
+
+
+--------------------------------------------------------------------------------
+Legende:
+
+FIX: fixes a bug
+CHG: inform about changed items.
+ADD: added feature
+RMV: removed Item
+
+{Unzip}   -> only related to the Unzip-module
+{Zip}     -> only related to the Zip-module
+             These are just libraries and are linked into the console-app.
+
+{Console} -> only related to the Userinterface (not SIOUX)
+             MacOS has no tool like a command-line. So it's neccessary
+             to write wrapper around the command-line tools.
+
+
+
+
+Dirk Haase
diff --git a/macos/README.TXT b/macos/README.TXT
new file mode 100644 (file)
index 0000000..bd69b3d
--- /dev/null
@@ -0,0 +1,560 @@
+Macintosh Port of Info-ZIP's Zip
+and UnZip
+By Dirk Haase, d_haase@sitec.net
+Home page: www.sitec.net/maczip
+Mirror page:
+www.haase-online.de/dirk/maczip
+================================
+
+
+
+Abstract:
+---------
+MacZip is a cross-platform compatible tool that
+includes both Zip (for compression) and UnZip (for extraction).
+
+Zip is a compression and file packaging utility for Unix,
+VMS, MSDOS, OS/2, Windows 9x, Windows NT, Atari, Macintosh,
+Amiga, Acorn RISC OS, and other systems.
+
+UnZip unpacks zip archives.
+The Zip and UnZip programs can process archives pro-
+duced by PKZIP, and PKZIP and PKUNZIP can work with
+archives produced by zip. Zip version 2.2 is compatible
+with PKZIP 2.04.
+
+
+
+Requirements
+------------
+MacZip requires at least System 7 and a Macintosh with a minimum of a
+Motorola 68020 or PowerPC 601 processor. Other configurations may work
+but it is not tested at all.
+
+The application is distributed as a fat binary with both regular 68K
+and native PowerPC versions included.
+
+
+
+Installation
+------------
+Move the executable(s) somewhere--for example, drag it (or them) to your
+Applications folder.  For easy access, make an alias in the Launcher Control
+Panel or directly on your desktop.
+The GUI is very simple. It was not my intention to make a full-blown GUI,
+however I think it is comfortable enough to use it as regular tool.
+
+This port supports also Apple-event. So you can install it in your
+WWW-Browser as a helper app.
+
+For more Info about the contents of this package, take a look into
+the "macos/Contents" (or :macos:Contents) file. Some notes on how to
+rebuild the Macintosh applications can be found in INSTALL.
+
+
+
+Usage:
+------
+
+Basically there are four ways to start MacZip:
+
+a) Drag'n Drop
+   To extract an archive, drop an archive on MacZip.
+   To compress files drop a file, folder or volume on MacZip.
+   Note: You cannot drop more than one item at the same time.
+
+
+
+b) using the Dialog box (Menu: File -> Zip/Unzip):
+   * Compression (Zip):
+   - Go to "File -> Zip"and the "Zip Options" Dialog Box appears.
+   - Click on "Location of the compressed File"
+   - The "Select an archive" dialog box appears
+        a) select a existing zip archive
+           -> Your files will be added to that zip archive.
+        b) select a folder and name your new zip archive
+           -> a new zip archive will be created with your files.
+   - Select one or more check boxes if you want.
+     see Zip.txt for more information.
+   - Click on "File or Folder to Compress"
+   - The "Select a File or Folder" dialog box appears
+        a) select a file
+           -> This file will be compressed.
+        b) select a folder
+           -> the contents of the folder will be compressed.
+   - Click on "Start Zip" to start the task.
+
+  * Extraction (Unzip):
+   - Go to "File -> Unzip"and the "Unzip Options" Dialog Box appears.
+   - Click on "Location of the compressed File"
+   - The "Select an archive" dialog box appears
+   - select a existing zip archive
+   - Select one or more check boxes if you want.
+     see Unzip.txt for more information.
+   - Click on "Location of the extracted Files"
+   - The "Select a Folder" dialog box appears
+        a) select a file
+           -> This file will be compressed.
+        b) select a folder
+           -> the contents of the archive will be extracted
+              into this folder.
+   - Click on "Start Unzip" to start the task.
+
+
+
+c) Using the Command line (Menu: File->Command Line):
+   The Zip & UnZip tools are command line tools. So the behavior is exactly
+   the same like the Zip & UnZip tools on Unix or Windows/DOS. This means,
+   if you want to zip some files, you have to write a command line like this:
+   "zip [switches] path_to_zip_archive path_to_files_folders"
+
+   - Go to "File" and select "Command Line" and the "MacZip Entry box"
+     Dialog Box appears.
+
+   An example:
+
+   a: your zip may be created at
+           Macintosh HD:applications:archive.zip
+
+   b: your files may be found at
+           Macintosh HD:somewhere:my_folder_to_archive:*
+
+   Note: At the end of the path there must be a filename or a wild card !
+   (see Footnote: 1 wild card, 2 Mac path names)
+
+   So the command line should look like (one line!):
+
+   zip "Macintosh HD:applications:archive.zip" "Macintosh HD:somewhere:my_folder_to_archive:*"
+
+   - Click on "Enter" to start the task.
+
+   Since you can not set a default folder you have to enter always a
+   full qualified path names. Full-qualified path names are path names
+   including the Volume name ! (see Footnote: 2 Mac path names)
+
+
+
+d) Using Applescript:
+
+There is only one additional event defined: "do_cmd". You can enter
+every valid command line. The first word must be "zip" or "unzip" to
+select the action (compress or extraction).
+
+See sample Applescript:
+
+        tell application "MacZip (PPC)"
+            activate
+            with timeout of 90000 seconds
+                do_cmd "zip -rjjN Volume:archive \"My Volume:*\" "
+            end timeout
+        end tell
+
+This script opens MacZip, brings it to the foreground on the Mac, starts the
+zip action with the command line: zip -rjjN Volume:archive "My Volume:*" .
+
+
+
+
+A short introduction is also available online:
+http://www.sitec.net/maczip/How-To-Do/
+
+It's possible to stop the run of Zip/Unzip with the well
+known shortcut [Command] + [.].
+
+
+---------------------------------------------------------------------------
+
+There are some Mac-specific switches available.
+Zip Module:
+       -df    [MacOS] Include only data-fork of files zipped into
+              the  archive.   Good for exporting files to foreign
+              operating-systems.  Resource-forks will be  ignored
+              at all.
+
+       -jj    [MacOS] record Fullpath (+ Volname).  The  complete
+              path  including  volume  will be stored. By default
+              the relative path will be stored.
+
+       -S     [MSDOS, OS/2, WIN32 and ATARI] Include  system  and
+              hidden files.
+              [MacOS]  Includes finder invisible files, which are
+              ignored otherwise.
+
+Unzip Module:
+       -E     [MacOS only] display contents of MacOS extra  field
+              during restore operation.
+
+       -i     [MacOS only] ignore filenames stored in MacOS extra
+              fields.  Instead,  the  most  compatible   filename
+              stored in the generic part of the entry's header is
+              used.
+
+       -J     [MacOS only] ignore MacOS extra fields.  All Macin-
+              tosh  specific  info  is  skipped.  Data-fork   and
+              resource-fork are restored as separate files.
+
+
+Select [File]->[Get Help on Zip/Unzip] for a complete list
+of switches.
+
+
+
+Limitations / Problems:
+-----------------------
+
+    - Aliases are not supported. I tried, but I got broken aliases
+      This port will silently ignore all aliases.
+      It's on my to-do list for future releases.
+
+    - Zip needs much memory to compress many files:
+      You may need to increase the 'Preferred Size' in 'Get Info'.
+      Values of 12 Megabytes or more are possible
+
+    - Unzip needs about 500 Kbytes of memory to unzip no matter
+      how many files were compressed and expanded.
+
+    - and finally one big macintosh-related problem:
+      This port has one weak point: It's based on path names.
+      As you may be already know: Path names are not unique on a Mac !
+      The main reason is that an attempt to implement support exact saving of
+      the MacOS specific internal file structures would require a throughout
+      rewrite of major parts of shared code, probably sacrifying compatibility
+      with other systems.
+      I have no solution at the moment. The port will just warn you if you try
+      zip from / to a volume which has a duplicate name.
+      MacZip has problems to find the archive or the files.
+      My (Big) recommendation: Name all your volumes with a unique name and
+      MacZip will run without any problem.
+
+
+Known Bugs:
+
+    - crypted files in a zip archive are sometimes corrupt:
+      I get an error message: invalid compressed data to inflate.
+      Appearance of this error is purely be chance:
+      I did a small test: Unzipping an archive containing 3589 files
+      56 files fails to unzip, so about 1.5%.
+      Root cause is completely unclear to me :(
+
+I strongly recommend to test your archive (e.g. unzip -t archive).
+
+
+
+
+
+Zip Programs / Macintosh Extra-Data:
+-----------------------------------------
+A brief overview:
+Currently, as far as I know, there are 4 Zip programs available
+for the Macintosh platform.
+These programs build (of course) different variants of Zip files:
+
+    - Info-ZIP's first Port of Zip. Ported by Johnny Lee
+      This Port is rather outdated and no longer supported (since 1992).
+      68K only. Only minimal Mac-info is stored (Creator/Type,
+      Finder attributes). Creator/Type: '????' / '????'
+      Until year 1998, only UnZip 5.32 survived.
+
+    - ZipIt by Tom Brown. This is Shareware and still supported I think.
+      ZipIt has a nice GUI, but I found it can't handle large Zip files
+      quite well. ZipIt compresses Macintosh files using the Mac Binary
+      format. So, transferring files to other platforms is not so easy.
+      Only minimal Mac-info is stored (Creator/Type, Finder attributes).
+      Mac filenames are changed to a most compatible filename.
+      Creator/Type: 'ZIP ' / 'ZIP '
+
+    - PKZIP/mac v2.03/210d. This is Shareware.
+      This Zip implementation for the Mac can be found on ASI's web site
+      (http://www.asizip.com/products/products.htm).  The name of this
+      program is misleading, it is NOT a product from PKWARE.  ASI's last
+      release version is v2.03, and they also offer a newer beta version
+      PKZIP/mac 210d. But even the Beta version is rather outdated (1995).
+      Only minimal Mac-info is stored (Creator/Type, Finder attributes).
+      The Zipfile format looks like incompatible to other platforms.
+      (More details about the compatibility issue can be found in
+      proginfo/3rdparty.bug!). Type: 'PKz1'
+      Mac filenames are restored without any change.
+
+and finally:
+    - Info-ZIP's latest Port of Zip. MacZip 1.0. Ported by me :-)
+      It is supported (of course) and up to date. Full set of macintosh
+      info is stored: Creator/Type, Finder attributes, Finder comments,
+      MacOS 8.0 Folder settings, Icon/Folder Positions ...
+      Mac filenames are restored without any change.
+      Creator/Type: 'IZip' / 'ZIP '
+
+
+Compatibility of my port; Extraction:
+   - Archives from Info-ZIP's first port (by Johnny Lee) are still compatible.
+   - Extraction of ZipIt archives is supported. This support is not
+     complete: Filenames are correct but Directory names are sometimes mangled
+     to a DOS compatible form. Segmented archives are not supported.
+   - PKZiP/mac archive files are extracted without resource-forks
+     and without any Finder info. I have no information about that zip format.
+
+Compatibility of my port; Compression:
+   - My port supports only the new Info-ZIP format
+     (introduced with this port). Therefore archives created by MacZip 1.0
+     (March 1999) must be extracted with this version or later releases
+     of Info-ZIP's UnZip to restore the complete set of Macintosh attributes.
+
+Note: This port is complete unrelated to the shareware ZipIt. Even more,
+handling of special Macintosh attributes is incompatible with ZipIt.
+This port (MacZip) may be used to extract archives created by ZipIt,
+but make sure that you get the result as you expected.
+
+
+
+Macintosh Files; File Forks:
+----------------------------
+
+All Macintosh files comprise two forks, known as the data fork and the
+resource fork.  Unlike the bytes stored in the resource fork, the bytes in
+the data fork do not have to exhibit any particular internal structure.
+The application is responsible for interpreting the bytes in the data fork
+in whatever manner is appropriate. The bytes in the resource fork usually
+have a defined internal structure and contain data object like menus,
+dialog boxes, icons and pictures.
+Although all Macintosh files contain both a data fork and a resource fork,
+one or both of these forks may be empty.
+
+MacZip stores data-forks and resource-forks separately. The Zipfile format
+does not allow to store two archive entries using exactly the same name.
+My solution is to modify the Path name of the resource-fork. All resource-fork
+names are prepended with a leading special directory named "XtraStuf.mac".
+So, when extracting on a Mac, you should never see this directory
+"XtraStuf.mac" on your *disk*.
+
+On all foreign systems that support directories in filenames (e.g.: OS/2, Unix,
+DOS/Windows, VMS) you will get a directory "XtraStuf.mac" when extracting
+MacZip archives.
+You can delete the complete directory "XtraStuf.mac" since Mac resources
+do not make much sense outside the MacOS world.
+
+
+
+Text encoding; Charsets of the Filenames:
+-----------------------------------------
+
+The following information is only important if you plan to transfer
+archives across different platforms/language systems:
+
+A typical Zip archive does not support different charsets. All filenames
+stored in the public area (= accessible by foreign systems other
+than MacOS) must be coded in the charset ISO-8859-1 (CP1252 in the Microsoft
+Windows world) or CP850 (DOSLatin1). The latter should only be used by
+Zip programs that mark the archive entries as "created under DOS".
+Apart from Macs, the commonly used platforms either support ISO-8859-1
+directly, or are compatible with it.
+To achieve maximum compatibility, MacZip convert filenames from the
+Mac OS Roman character set to ISO-8859-1 and vice versa.
+But not every char of the charset MacRoman has their equivalent
+in ISO-8859-1. To make the mapping in most cases possible, I chose
+most similar chars or at least the MIDDLE DOT.
+
+Mac OS Roman character set is used for at least the following Mac OS
+localizations:
+U.S., British, Canadian French, French, Swiss French,
+German, Swiss German, Italian, Swiss Italian, Dutch,
+Swedish, Norwegian, Danish, Finnish, Spanish, Catalan,
+Portuguese, Brazilian, and the default International system.
+
+In all Mac OS encodings, character codes 0x00-0x7F are identical to
+ASCII, except that
+  - in Mac OS Japanese, yen sign replaces reverse solidus
+  - in Mac OS Arabic, Farsi, and Hebrew, some of the punctuation in this
+    range is treated as having strong left-right directionality,
+    although the corresponding Unicode characters have neutral
+    directionality
+So, for best compatibility, confine filenames to the standard
+7-bit ASCII character set.
+
+If you generate a filename list of your archive (unzip -l), you will
+see the converted filenames. Your can also extract the archive with
+the switch '-i' (= ignore mac filenames), and test your result.
+
+This MacZip port uses its own filename stored in the archive.
+At the moment, the filename will be not converted. However,
+I'm planning to add support for Unicode.
+
+Currently, the following Mac OS encodings are NOT supported:
+Japanese, ChineseTrad, Korean, Arabic, Hebrew, Greek, Cyrillic,
+Devanagari, Gurmukhi, Gujarati, Oriya, Bengali, Tamil, Telugu
+Kannada, Malayalam, Sinhalese, Burmese, Khmer, Thai, Laotian,
+Georgian, Armenian, ChineseSimp, Tibetan, Mongolian, Ethiopic,
+Vietnamese, ExtArabic and finally:
+Symbol - this is the encoding for the font named "Symbol".
+Dingbats - this is the encoding for the font named "Zapf Dingbats".
+If you extract an archive coded with one of these charsets
+you will probably get filenames with funny characters.
+
+These problems apply only to filenames and NOT to the file
+content.
+of course: The content of the files will NEVER be converted !!
+
+
+
+File-/Creator Type:
+-------------
+
+This port uses the creator type 'IZip' and it is registered at Apple
+(since 08. March 1998). File types can not be registered any more.
+This port uses 'ZIP ' for Zip archive files.
+The creator 'IZip' type should be used for all future versions of
+MacZip.
+
+
+
+Hints for proper restoration of file-time stamps:
+-------------------------------------------------
+
+UnZip requires the host computer to have proper time zone information in
+order to handle certain tasks correctly (see unzip.doc).  To set the
+time zone on the Macintosh, go to the Map Control Panel and enter the
+correct number of hours (and, in a few locales, minutes) offset from
+Universal Time/Greenwich Mean Time.  For example, the US Pacific time zone
+is -8 hours from UTC/GMT during standard (winter) time and -7 hours from
+UTC/GMT during Daylight Savings Time.  The US Eastern time zone is -5 hours
+during the winter and -4 hours during the summer.
+
+Discussion of Daylight Savings Time
+-----------------------------------
+The setting in the Date & Time control panel for Daylight Savings time
+is a universal setting. That is, it assumes everybody in the world is
+observing Daylight Savings time when its check box is selected.
+
+If other areas of the world are not observing Daylight Savings time when
+the check box is selected in the Date & Time control panel, then the Map
+control panel will be off by an hour for all areas that are not recognizing
+Daylight Savings time.
+
+Conversely, if you set the Map control panel to an area that does not observe
+Daylight Savings time and deselect/uncheck the check box for Daylight Savings
+time in the Date & Time control panel, then time in all areas celebrating
+Daylight Savings time will be off by an hour in the Map control panel.
+
+Example:
+     In the case of Hawaiians, sometimes they are three hours
+     behind Pacific Standard Time (PST) and sometimes two hours
+     behind Pacific Daylight Time (PDT). The Map control panel
+     can only calculate differences between time zones relative
+     to Greenwich Mean Time (GMT). Hawaii will always show up as
+     three hours past the Pacific time zone and five hours past
+     the Central time zone.
+
+     When Hawaiians are not observing Daylight Savings time, but
+     the rest of the country is, there is no combination of
+     settings in Map and Date & Time control panels which will
+     enable you to display Hawaiian local time correctly AND
+     concurrently display the correct time in other places that
+     do observe Daylight Savings time.
+
+     The knowledge about which countries observe Daylight Savings
+     time and which do not is not built into the Map control
+     panel, so it does not allow for such a complex calculation.
+
+     This same situation also occurs in other parts of the world
+     besides Hawaii. Phoenix, Arizona is an example of an area of
+     the U.S. which also does not observe Daylight Savings time.
+
+Conclusion:
+MacZip only knows the GMT and DST offsets of the current time, not
+for the time in question.
+
+
+Projects & Packages:
+--------------------
+
+A Note to version numbers: Version of MacZip is currently 1.03 and
+is based on the zip code version 2.3 and unzip code version 5.4.
+See About Box for current version and compiler build date.
+
+Because of the amount of sources I splitted this port into
+several projects. See http://www.sitec.net/maczip for updates.
+
+- core source parts:
+    unzxxx.zip
+    zipxxx.zip
+      These archives contains the main parts of the port. You can build
+      libraries and a standalone App with Metrowerks standard console SIOUX.
+      They contain only sources, no executables.
+      These archives are exact copies of the standard Info-ZIP source
+      distributions; they were only repackaged under MacOS using MacZip,
+      with one minor addition: For those files that are stored in BinHex'ed
+      format in the Info-ZIP reference source archives, unpacked version
+      that are ready for use have been added.
+
+- additional source part:
+    MacZipxxx.zip: contains all the GUI stuff and the project files to
+      build the main-app.  Only sources of the GUI, no zip or unzip code.
+      To build MacZip successfully you will need to also download the zip
+      and unzip packages.
+
+- executables:
+    MacZipxxxnc.hqx: contains only executables and 'README.TXT',
+                     This version is without en-/decryption support !
+    MacZipxxxc.hqx:  contains only executables and 'README.TXT',
+                     This version supports en-/decryption !
+
+- encryption sources:
+    zcryptxx.zip: To build crypt versions of MacZip.
+    download from ftp://ftp.icce.rug.nl/infozip/ (and subdirectories)
+
+- documentation:
+    MacZipDocu.zip: contains some further docus about the algorithm,
+                    limits, Info-ZIP's appnote and a How-to-do Webpage.
+
+
+Credits:
+--------
+
+Macstuff.c and recurse.c: All the functions are from More Files.
+More Files fixes many of the broken or underfunctional
+parts of the file system. Thanks to Jim Luther.
+(see morefiles.doc)
+
+
+
+
+
+
+
+---------------------------------------------------------------------------
+Footnotes:
+
+1. wild card:
+    The '*' is a wild card and means 'all files'
+    Just in case you don't know wild cards:
+    '*' is a place holder for any character.
+    e.g.:
+    "this*" matches with "this_file" or  "this_textfile" but it
+    doesn't match with "only_this_file" or  "first_this_textfile"
+    "*this*" matches with "this_file" or  "this_textfile" AND
+    matches with "only_this_file" or  "first_this_textfile"
+
+
+2. Mac pathnames:
+The following characteristics of Macintosh pathnames should be noted:
+
+    A full pathname never begins with a colon, but must contain at
+    least one colon.
+    A partial pathname always begins with a colon separator except in
+    the case where the file partial pathname is a simple file or
+    directory name.
+    Single trailing separator colons in full or partial pathnames are
+    ignored except in the case of full pathnames to volumes.
+    In full pathnames to volumes, the trailing separator colon is required.
+    Consecutive separator colons can be used to ascend a level from a
+    directory to its parent directory. Two consecutive separator colons
+    will ascend one level, three consecutive separator colons will ascend
+    two levels, and so on. Ascending can only occur from a directory;
+    not a file.
+
+
+
+
+
+---------------------------------------------------------------------------
+
+Dirk Haase
+==========
diff --git a/macos/ZipLib.h b/macos/ZipLib.h
new file mode 100644 (file)
index 0000000..e3dacf3
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+  ZipLib.h
+
+  This header-files is global to the project ZipLib.
+
+  ---------------------------------------------------------------------------*/
+
+
+
+/*****************************************************************************/
+/*  Macros, typedefs                                                         */
+/*****************************************************************************/
+
+#define MACOS
+#define MACZIP
+
+#define OLDROUTINENAMES     0           /* use new function names only */
+#define OLDROUTINELOCATIONS 0           /* use new headerlocations only */
+#define SystemSevenOrLater  1           /* Runs only on System 7.0 or later */
+
+/* These functions are defined as a macro instead of a function.
+so we have to undefine them for replacing (see printf.c)  */
+#undef getc
+#undef getchar
+#undef putchar
+#undef putc
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+
+#define NAME_MAX    1024
+
+
+/*****************************************************************************/
+/*  Includes standard headers                                                */
+/*****************************************************************************/
+#include <ansi_prefix.mac.h>
+#include <stdio.h>
+#include <TextUtils.h>
+#include <Folders.h>
+#include <Aliases.h>
+#include <Resources.h>
+#include <Gestalt.h>
+#include <Traps.h>
+#include <Processes.h>
+#include <MacWindows.h>
+
+
+/* Many things are different for mac-users, so we need
+   special mac functions :-)  */
+int Zmacstat (const char *path, struct stat *buf);
+#define stat(path, bufPtr) Zmacstat(path, bufPtr)
+#define lstat(path, bufPtr) Zmacstat(path, bufPtr)
+
+int fprintf(FILE *file, const char *format, ...);
+int printf(const char *format, ...);
+void perror(const char *parm1);
+
+
+
+/*
+#define MAC_DEBUG  1
+#define DEBUG 1
+   */
+
+
+#ifdef MAC_DEBUG
+#define LOG_DEBUG   7   /* debug-level messages */
+int Print2Syslog(UInt8 priority, const char *format, ...);
+#include <ctype.h>
+
+
+#define Notify(msg)                                                 \
+        {                                                           \
+        (void)Print2Syslog(LOG_DEBUG, "%s (file: %s line: %d)",     \
+                     msg, __FILE__, __LINE__);        \
+        }
+
+
+
+
+#define Assert_it(cond,msg,kind)                                        \
+        {                                                               \
+        if (!(cond))                                                    \
+            {                                                           \
+            (void)Print2Syslog(LOG_DEBUG,"%s failed: [%s] cond: [%s] (file: %s line: %d)", \
+                          kind, msg, #cond, __FILE__, __LINE__);        \
+            }                                                           \
+        }
+
+
+
+
+
+#define AssertBool(b,msg) Assert_it (((b) == TRUE) || ((b) == FALSE),(msg),("AssertBool "))
+
+
+
+#define AssertStr(s,msg)                                            \
+    {                                                               \
+        int s_i = 0;                                                \
+        Assert_it ((s),(msg),("1. AssertStr "));                    \
+        while ((s)[s_i]) {                                          \
+            Assert_it ((!iscntrl((s)[s_i]) || ((s)[s_i] == 0x0A) ||  \
+                       ((s)[s_i] == 0x0D)),(s),("2. AssertStr "));  \
+            s_i++;                                                  \
+        }                                                           \
+    }
+
+
+
+#define AssertTime(t,msg)   Assert_it (((t).tm_sec  >=  0) && ((t).tm_sec  < 62) &&   \
+                ((t).tm_min  >=  0) && ((t).tm_min  < 60) &&   \
+                ((t).tm_hour >=  0) && ((t).tm_hour < 24) &&   \
+                ((t).tm_mday >=  1) && ((t).tm_mday < 32) &&   \
+                ((t).tm_mon  >=  0) && ((t).tm_mon  < 12) &&   \
+                ((t).tm_wday >=  0) && ((t).tm_wday < 7)  &&   \
+                ((t).tm_yday >=  0) && ((t).tm_yday < 366),(msg),("AssertStr "))
+
+
+
+#define AssertIntRange(myvalue,minimum,maximum, msg)  Assert_it ( \
+        ((myvalue) >= (minimum)) && ((myvalue) <= (maximum)), msg,("AssertIntRange "))
+
+
+
+
+#define AssertStrNoOverlap(str1,str2,msg)                           \
+    {                                                               \
+        long s_i = 0;                                               \
+        AssertStr((str1),(msg))                                     \
+        AssertStr((str2),(msg))                                     \
+        if ((str1) < (str2))                                        \
+            {                                                       \
+            s_i = strlen((str2));                                   \
+            Assert_it ( (((str1) + s_i) < (str2)),(msg),("AssertStrNoOverlap "));   \
+            }                                                       \
+        else                                                        \
+            {                                                       \
+            s_i = strlen((str1));                                   \
+            Assert_it ( (((str2) + s_i) < (str1)),(msg),("AssertStrNoOverlap "));   \
+            }                                                       \
+    }                                                               \
+
+
+
+
+#else
+#define Assert_it(cond,msg,kind)
+#define AssertBool(b,msg)
+#define AssertStr(s,msg)
+#define AssertTime(t,msg)
+#define AssertIntRange(myvalue,minimum,maximum,msg)
+#define AssertStrNoOverlap(str1,str2,msg)
+#endif
+
diff --git a/macos/ZipSx.h b/macos/ZipSx.h
new file mode 100644 (file)
index 0000000..d2b9ae8
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+  ZipSx.h
+
+  This header-files is global to the project ZipSioux.
+
+  ---------------------------------------------------------------------------*/
+
+
+/*****************************************************************************/
+/*  Macros, typedefs                                                         */
+/*****************************************************************************/
+
+#define MACOS
+#define USE_SIOUX
+#define MACZIP
+
+#define OLDROUTINENAMES     0           /* use new function names only */
+#define OLDROUTINELOCATIONS 0           /* use new headerlocations only */
+#define SystemSevenOrLater  1           /* Runs only on System 7.0 or later */
+
+/* These functions are defined as a macro instead of a function.
+so we have to undefine them for replacing (see printf.c)  */
+#undef getc
+#undef getchar
+#undef putchar
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+
+#define NAME_MAX    1024
+
+
+/*****************************************************************************/
+/*  Includes standard headers                                                */
+/*****************************************************************************/
+#include <ansi_prefix.mac.h>
+#include <stdio.h>
+#include <TextUtils.h>
+#include <Folders.h>
+#include <Aliases.h>
+#include <Resources.h>
+#include <Gestalt.h>
+#include <Traps.h>
+#include <Processes.h>
+#include <MacWindows.h>
+
+
+/* Many things are different for mac-users, so we need
+   special mac functions :-)  */
+int Zmacstat (const char *path, struct stat *buf);
+#define stat(path, bufPtr) Zmacstat(path, bufPtr)
+#define lstat(path, bufPtr) Zmacstat(path, bufPtr)
+
+int fprintf(FILE *file, const char *format, ...);
+int printf(const char *format, ...);
+void perror(const char *parm1);
+
+
+
+/*
+#define MAC_DEBUG  1
+  */
+
+
+
+
+
+
+#ifdef MAC_DEBUG
+#define LOG_DEBUG   7   /* debug-level messages */
+int Print2Syslog(UInt8 priority, const char *format, ...);
+#include <ctype.h>
+
+
+#define Notify(msg)                                                 \
+        {                                                           \
+        (void)Print2Syslog(LOG_DEBUG, "%s (file: %s line: %d)",     \
+                     msg, __FILE__, __LINE__);        \
+        }
+
+
+
+
+#define Assert_it(cond,msg,kind)                                        \
+        {                                                               \
+        if (!(cond))                                                    \
+            {                                                           \
+            (void)Print2Syslog(LOG_DEBUG,"%s failed: [%s] cond: [%s] (file: %s line: %d)", \
+                          kind, msg, #cond, __FILE__, __LINE__);        \
+            }                                                           \
+        }
+
+
+
+
+#define AssertBool(b,msg) Assert_it (((b) == TRUE) || ((b) == FALSE),(msg),("AssertBool "))
+
+
+
+#define AssertStr(s,msg)                                            \
+    {                                                               \
+        int s_i = 0;                                                \
+        Assert_it ((s),(msg),("1. AssertStr "));                    \
+        while ((s)[s_i]) {                                          \
+            Assert_it ((!iscntrl((s)[s_i]) || ((s)[s_i] == 0x0A) ||  \
+                       ((s)[s_i] == 0x0D)),(s),("2. AssertStr "));  \
+            s_i++;                                                  \
+        }                                                           \
+    }
+
+
+
+#define AssertTime(t,msg)   Assert_it (((t).tm_sec  >=  0) && ((t).tm_sec  < 62) &&   \
+                ((t).tm_min  >=  0) && ((t).tm_min  < 60) &&   \
+                ((t).tm_hour >=  0) && ((t).tm_hour < 24) &&   \
+                ((t).tm_mday >=  1) && ((t).tm_mday < 32) &&   \
+                ((t).tm_mon  >=  0) && ((t).tm_mon  < 12) &&   \
+                ((t).tm_wday >=  0) && ((t).tm_wday < 7)  &&   \
+                ((t).tm_yday >=  0) && ((t).tm_yday < 366),(msg),("AssertStr "))
+
+
+
+#define AssertIntRange(myvalue,minimum,maximum, msg)  Assert_it ( \
+        ((myvalue) >= (minimum)) && ((myvalue) <= (maximum)), msg,("AssertIntRange "))
+
+
+
+
+#define AssertStrNoOverlap(str1,str2,msg)                           \
+    {                                                               \
+        long s_i = 0;                                               \
+        AssertStr((str1),(msg))                                     \
+        AssertStr((str2),(msg))                                     \
+        if ((str1) < (str2))                                        \
+            {                                                       \
+            s_i = strlen((str2));                                   \
+            Assert_it ( (((str1) + s_i) < (str2)),(msg),("AssertStrNoOverlap "));   \
+            }                                                       \
+        else                                                        \
+            {                                                       \
+            s_i = strlen((str1));                                   \
+            Assert_it ( (((str2) + s_i) < (str1)),(msg),("AssertStrNoOverlap "));   \
+            }                                                       \
+    }                                                               \
+
+
+
+
+#else
+#define Assert_it(cond,msg,kind)
+#define AssertBool(b,msg)
+#define AssertStr(s,msg)
+#define AssertTime(t,msg)
+#define AssertIntRange(myvalue,minimum,maximum,msg)
+#define AssertStrNoOverlap(str1,str2,msg)
+#endif
+
diff --git a/macos/ZpPrj.hqx b/macos/ZpPrj.hqx
new file mode 100644 (file)
index 0000000..5bb3da0
--- /dev/null
@@ -0,0 +1,455 @@
+(This file must be converted with BinHex 4.0)
+:#9T`8(*U,R0TG!"6594%8dP8)3#3"&66!*!%Ip96593K!!%!!&66FNaKG3)!N!3
+@!*!$$39DF&"bDJ#3!aEf1!,VX93!6&MU!*!$J!#3"!,cIF3NA3#3'[q3"%e08(*
+$9dP&!3b[H&ZZXklEb3#3"3,E[3#3"P40!!$hQ!#3"L8D"RMDS*NlIS6ISVG-[(8
+R+hBY21RaEd$i`XJbN!"bQK8YHRN,mmTE("$HbP6f+lXeRq'lH*3I@AbbH%Ef3E+
+Yif3KHp54hE%@hq8Fj,%GAml1RLpN-E,i(GQARdH@0q0,K(GffT%p5)X[RVFF@D4
+BKrHBaXd@6VD,AXpZB5d!C#'6K@abQi`@mJ[Cj$MPC!8iDT2X[EaXE0rjRCHM[$`
+Ej#4Rp[RPjG6VcFj"ITHAR9DQepPe(-SAiAji1arZ(-5ApPP[lbMciLAdmP)if0m
+4Z#m[-q'q["cNPGI1p`,!!JLip@eQPi2X'farqH4p"**I)T!!,ckH3A`!+i#AjfI
+6V9BMbl,P@GDh0P[fhKZcCArkf5`lka2F0rFYkb28qpDfD[R@DP(8@d9PSQMYcUH
+l#l&K+CqqV@b6b'8EXQaE[)pm16Za$2kVE&Ajrhr50p-icq)mQh-k-9rKr#ThirR
+rPjaIiecK!m`jJh-@jcQFFcJAF-lMl1)dliLFcVQ"F`IR*Xk0R"GcEZCFalQ0mbl
+1fcR[i$c+q@,1jh$HcAQBm`MR4C`2FElF9MERGNj6amLPR&XjIj*c$@F2jmXiAm$
+j*XlAFlk"mi@FrjhcMcNrbIN*cSpcISVc6cMr,HHpR$r0q3#eRXTrcYrLI$mR'2-
+,R+rKI"hRIH3Bb9R2#IC-iM3GT%lK(-,CcQPUVdlJ(-lCbMQ1Xi(6p)BkME10Xj%
+c+PDCdr561TN6d2S-jjpa'Lb,I*!!mcpbrKVR@cNIiIaPcSFjIjhc9cKrNI2GR'r
+Mr#$RKcMIc[R[1Aq9mbfFlq6m*Fi,1*Ga,Z@mKI0IFGl*#5!Dh)bmK[09R,GaAX,
+j"jarb2RI1(q(FaIR4cJrb[Nqc[Gb(Z#mQA-Ijhl1Jp4a$2rr-qGri@idr`pa2Tr
+c#j`c1@GcRXXjPh-Kjha1dcX4X#IbK!KDTSmLi&#%2SXmRI-QcLq9Z!9QHAK&RJp
+`lZ(FbhNGjrfFi0ZA1@rJr$6RRh*qP[1jR(r"H68Rb4GarLERAh1H6mK%r[mHjqp
+bAXYTHM*b(ZI2F2iXj`61[`QF)`)'4&l"HCccMCcrM[2R16r(qAR1Rq!dI4jj2HF
+pR$r&qmEbrbAmTmDmG5@R`BL)@2XZiLEchf"#j+Fj$@j%`)h)-cJ0YN6%B*!!fZ"
+0"!b*Q-YJ5Z6l13f@4"l,H6RRrq,m"ZHMR,r0#FVclQpbISXh8X0[Fcl'q6MRDNj
+kp$ZFEqEm1FlAFVk)df"Bj'l1*Cc,1EXjRmhj4Fi(1@rN[*lcMcMr0HFV1DrKT2p
+IcEQEmcpaIScc2h$Zj2`0c[G`AX&j+HFl*#EQK*KF5AfSiiFjrbYhe2BUcZFYQ8#
+8`"SqHK"mJ1I3kr3C28Brd%[d&(J&2Y#Ep#9p$1pa'!D(S)I"!2UBIUI2k&ekQ$k
+NTkNhA)PD1m`$$m!AqJL1"DHLhq&FB#FB#Zm#3m%Rq0Hr%%46EGlDqbRHVF#K%H!
+jCH(Hi#JG!5E6*4lH8SZ90Sij`3pl6lJjll@6MSXbZAq0&J$qBllBSmf01Ffr4[l
+C`lkV[XcL4ASG'Uq6pdGP+lLTLlHfZ[CGhY-)T@1p"c3qUpkHR1ZA["4,,hRFkea
+YBX@*hcX-dG"#+9Im%9i"mj8`IdC`pR"ZifcRl1$Xj"c&1CTc$1GBcR'FNcQl1'G
+`VZ*FcEQ@Fb2R*XiYR$GclZHmKI0@cJ1F"cN2F4lQ[)hc+1IYR(G`2Src(Xjl19r
+!q41F@f-(QGk,(-FjM(-iCbXRM$VH@aj#JTLJCcJ!8S+3!+!HU!JLJMDJ)qJ*@MT
+N"$e"8C!!&83&)8&+Kk"K"%KC3E!i)0$PJemF2ha%-$h8ZV&k4A@S8HedmNlrlUV
+k4r+lI'5L-VEe@@SUj"`H)5q"0Af[ML&D&MAMJ*Q(BUqXb8H5K0BVJkB$kF&FTK+
+E1,G`MZBF`cQ@Fa,R+-j1cKXiEq5mQA-NjdE1rCbhF0l+HC!!Xiec'fF2Cc[R#-j
+9R$GacZ$FblQDFbhR2Xl*R)FjEq-mbRNAjpfFcq0m2ZFpR&XjQcLE1BG`YR!1j4`
+QQE%pEq+fM@mD("[Z(pkQ6*ArB1m@(2NMrbrTZlE[a'9UA)NZ-1G*h2#q2MlNie#
+FlAKr`'(q0ph`MVp(96SX3dYqJ(B)h'F3ShNX,hEQPI(CraA+,q4E26%a@U*4G2h
+S*GZQpp4VDZqA6Ni-IBGlai[LEVbSIX8L6)&*mGBRF[Cp'P`'R8-#ZKG'%!T3Na#
+3!-m)-8N-L68ZIi`Zd6(CV9@'cMfh-Y4UGPU0[2,dLj`Tq,X[KR+QI5p6KIl4ahY
+LPcQ1D'%LG1"lQRGkkX`5C4jc2[L!DZG,#8B,5U,`Fq[1G#3r8(Mci'9Ud,jSF#T
+ciQZmAjrirRI0jCeZYIacC+Q'iD#62CM9E%`2YX+JZLEVVGQjbYU*LD&c+[cadf`
+LhS-SY$AS24*%1!"B$AaU%FbHEZBiI&Le*&2dm*m[h!(MBQeX&DQ`Q-m4dY!$bD8
+kHP%6%rda"hqX)Y,(1*GLV%NarU3BRe1-mLR'G"6MGiV4*m@3!)"LY%a"B48MHSS
+40SAJU"bI-b0DLV%IaELIFKb+X6Xc5U8Bhe115CP42-9iN@)m66&kT4ME8S`!+ND
+`&'1!bP%MmhBlHQAHENIq6!ilBQEHEJF8c*[YH+'TL4e&-HqfSf(QcBaJ-HTRalI
+-QaR0XZ0rjXefp0#0fM&5apJFihD-d6&kamJGih@-",S41aQYXQ09M1SaQXGB%f0
+hCUc,MZFamX5i(102M-iaYZG'X%`IfUkLVScJ-8E&'"jMCi`p-N,'Q#)M9BcX-BV
+'Q"BMLBaU-CE)q"NMMibJ-IE)5"TMN!#-G$%qb@JJif#-"c++a@JM)f+-p6(ZaTJ
+KSh#-26)#akJG)cf-J$+'b"JAii#-CXPS(b0DGM63M36#+mfiD'a8e)cUfE&(4Kd
+CKh5MMSa1-LV*b#0MNk!-Sj!!M&'kN8P'*"Q9G118M&bD)4$'`aJTC265MR%bcZP
+'1aP9C066MABbqXIS'D10M!$+f+!Gph0MPS`&-QVTa[BB(@4-N4%h4J8CE@2Ncih
+9-3l(i)SE-Q%iaBfmqX-Q$+-`f-)J#i-SE[L%N8I'C"PjC'5@m8FcHQK(%4PcC%5
+6F6X'BaM6C151N8h'laK*C-54N6Y'(XfiR"fhBr5488I'm4LVBlb4F8Q898Bc'FY
+Nh*049XBecBLQ(FQ%Kc2UL6M+q#hFJh%l0j,,+#lMSCR"(KP@53lhm0'6rT!!Ma[
+UBD#(34i'HKMHBCL(34i'HK"a'44#hN"HmSGk'1Y&cf"FQ2N+aL@4LKMrCE5BN@,
+'N4QbB-5Bd@)h&X`i-#2'M!XMmM*kc2JK)kb-*6,HbYJK+J9ML)`I-YTS4LJ91+[
+!9`@q+["9JFF+r&AJV!*R&6LV`'N&,L[`9S(h#Xa9B+i#Fa@iVm"G"8G3F!F&eLZ
+iJS*$+,L&JPXSZ)@#@bK`AX%V&,a#`5Z8I)+4BS-IGPcBi!!MbBb1-Tl+q'Cb60[
+d$q2CGJcCi*%Ge6-iT-!K"3iTm%H"2`Vm8H#2!Rm8q+2!(`Aq+2$(MLFcrQS`5)&
+"#Ja5i)S#Ea4iSm!E4@mSX%%jSQQ`4i%j#Xa4p)d#Fa5BSm!I"HiSF%H"1`VF8H#
+1!RF8Z+-F$6DiSm!G"HiSF%H"1mUH-pLM`"d&lLK`4p'AM"`UqPf"!`SX925k!JF
+9Q+$!"!8Q+,"5JBm+E&$JJJ)A&,LJ`!-&(LM`3)%(#Ma3i)%#$a4iS-!$"4iSm%#
+"X3T-8'##!K-8H+$J&!T1SH!5#LkKY"8`A%2"+44F3X%I&0a!`8%82%,")a3m3X%
+M&$a#`5-82%,")a3m3X'R&(a+`DH8)r@')bNiNS+[+(Q5i5E+N@E$663pT1NK63p
+THNM6EjVHd[55TTFd[D6T58hrDAT+de1DRY,dP+DR0$fPk5G02fRk5G02'KcAm'%
+06dC@e["L63pVkUDTQkCZQVTTq,1'2f[iS)C$DlLcKQYV1,D'3fXiY)C$DlLfT[i
+D,00`F!fHDALeKMYUZ,@'-fViYBCIDrLeKPpVq,@'[fTiVBD6DMLPKXYUH+@'9fT
+iTBE[DRL`"PmeZ+[Kq"UFe'#N"L-eA&1$NaUFe25LTKFe[DMT3Dd8ErTF`fXe[Dl
+TG3d@D$"!dr1DRYId[!BM0&a4Jp%DM0$JY!B(0"aCJ`-DRUc"!Jd@D,"!Jh%Dr02
+JP!EV0"LSiG%D204`D3f(eR"S$3CUF&1$QaVFe'#3!!Er0IL[`Am09pC`!#d(-"U
+!JQmVH,L#0bXd!S8fS1$IL[STDU%F#6HDJD)HL[FUhUTiUq+YL[j8p*ULca4pT1J
+K43mTHNJjGXriY(Q[3RG3p)b#RbZiX,,Z"XXdZ+2",JfQDEL!KJYSY!X0(p"`!3e
+Id2!%$5I3F!)0*p$`#-dl0*a&`b-dr%H$[aVqSm&RMHDK`9)0(QY`@S2A'Pc@B,N
+'bc9BVZ&''McAe&C6Fdep0(LZ`A-0RQX`A-060(a,`m-d2%a66`dAdh!a$5jVF&Q
+$baTFe[")$Br8p)Q'#fPiNSCVDMLQKYGSZ*''-fNiU+Eq'JkRiD!D(UIK8jUHdh!
+R66pU1*H'FfNiPiCcDAL@KQGTH*D'@fRk9F1[0$fVk9P0VfUiPSCVDEL@KQYT1+k
+'(fTiSBB6D[T3``Ze[*!!mAZM%5Pd(iAZSp!8&0U43[qaNaMS)%CV8'J-QJ!0RpE
+`E!hre["[$Ir@m'm0lpE`EJh[e["Y$Gr@m'd0hpEU*ZJ8B3GIH-fNB'1B3JRj'%8
+aRe@'`bJ'fdl93qCGKdIr(k0G&iF0[#%M-bGm-JqU9h[+JqSeiaYjr%&'P,'fP!I
+eE&M+JlTf@5p2X8P-&!VFXe-H9,V,8aj8[#Y6(T5qUe)He-#V8ai8`fY5(P6&De-
+H9-IV8Ki8h4Y6(Y6JQe)HP12l8Kl8cGHP2#LMVdTj8&6IP2+JVViQj8&jI8A+Jc,
+l`T3(pIDG[6c*-6!Ipe"iVdM[339qIXU$8[lbP!FerD'8"mApH-U$+[r6+3r+rBG
+5(Y6p$kBm6!$X6AQB%VJKj@'5i2U8KdQ$25N28`L[6hQB9(K$bX-Nd'G5(UDD4U8
+m6$f05hQBL*U8mM#jp2k8KmNUjfrAPiGTUkRIb12M+00CAFIbK"Kqp3Y@*5%[Rr2
+%D'*LHfYpqd1Q'%8rU[TPTCU9!ZrB&'H)J%d0cjQiHAcFqDRB&leNmjEJSQ'UecM
+CQLfQFbPHr@*FabPMeHRc*Y[jG(e(hFQek)D4d@'j&[q0Q2c#a@3MMkmhTaZc05I
+D'Q*m6rbr,IjI&Iq[MIpAarm[@Ra(jh'GXKM83X+ha2rhaIpharmEirp0LqRE9p+
++ebL#f'+Ck)liId6m2b2qEer-fV*LI2YZEIKFj6VMre(arqMiIdcm2cEq(lIiL+%
+q!PP&aq$*mArABT+aChCf9BZm9TR'hl5,@R8pUE+P'BEVKm9m,ieYpS,irfL-Zcr
+H(iVr$mIr0mIrpmErqq2r@q,r@q2r!r(r`F9kk-F-ETSFU3"H4kT&[B5!ZXA`qZA
+"AU-ZTQk0riI(rif,Z4U@"am$Q`X(*[RI&2rEmX+B%cR9+L!QqAUp'"dpr(VhhhD
+Tq6pX-9IMiGF2MIq(a2mYLlQ'R,!jAd!C&4qcGAjq[ZpAGXmfpecHfH(mT08%'lH
+MKZq)!"i#`hK'VKNDAcqmTV*QrH$8)(phM!a0+BL'U(aQTLGV3*0flr!0CV`6RKD
+ki0la6eC+49ZBd)TjNY!!CKar%am6&-kZK6RZZZ9Mch%qRrR`k,*p'r84B-kl2PX
+jV[V,2,2PlqCM2YNce[6Q[CXDkY+HUZXC0R[cfUi,m$j`mpI-q60rcBFRJ*P)DG)
+I!4m#TNliQ1e[rGV0jF`imqpYfhGlCEd)4Q3ri%JrmrTf@S3lTLJk-KL00dmF1D0
+9*Q3fedk!N!#$'@ZQ2,KM*Ye-FYKm+19MXTHeR"p'(4lE,LHDm)H`8aIFiA(!c$G
+hq"G-D&3P8ma'-`1q`RPL2"-Q26Bl9DN)$i2*`IQ,qGY)KBHD'M&V5kpCc`J6BQI
+[D82QckGP0kiQMPR!b1Vjq6ZG'fAqRKPqFY"rdaR5CDD1qINC38KKKYEdE11ERB2
+%0i,CIZBBm@%i9e6dCP-Mj`C2'qC1lD`rZI%LB1DI1fScKrFaPiL2`0b!&(91$-d
+,MKpeeSZDF-Im2pi!h$(PJ%F!GbJRH!9`"kpF&0K"R6i@LhAm-(Gi3P`3H%5G1,0
+Nf6lEUNlI"r`%$"1Ydb-"A`(Lm(GBPYei0VQLBYCbqX2d@p4T('EVJ5`m$&C52p0
+,8AR"KF("*5T@@A`dG`K@6+"`"c)bZmmGRKV#DU*k5c$,cahH$!+j8AZ#(J35`8&
+QqlPMAKm"KMY`%NQ%1l`pQ2AR$Qm-XHfUelH$k4(Z!$*kKcZm+*J#!@EaD3#[Z+-
+(K-Nhk!H#4`"hH(2`GZl`bU$1h1&p)GTAJpL$K`"hH%hJ*F!GrK(i#A$(Zr%9i)i
+DibrJi"f0L$X`(FcKMNNZm*-lqJm["ZlJ%(JkF!F'iIR!(4J"4q#1hXBEJM[k$Bm
+)lZJ0F)-lkQM"hYcaCN3,lSM"1i)lH!EH%G`a@5&#C+2H+Ki6L4b[M`VBcKfq+8b
+kF)GR#Ah+(6iN6+a`KhF+lq)1la3Q6lM$"d@mS"VY-cJ#GhL,#-YXe,X$0BFlq)V
+-4$EU6m+%#(IiH9!Vl["6`EF#kX58UUHr4%k3!*2K"m-GrK,iaA#(PiF`Z5Ca6Ub
+QQm4FDXiGrK[icA!(IZ%l`adi!VrLMMk(Lh&(2m&aZ+2ZBTMEC)h!,ZjiJaK`0ZN
+PJcm0Gr3(rF8GILc`$ZlS$haVZ-0r"EcL$Jm8m*ml2%c`Xq%1(aCmEEM$Xi3q09q
+c&"C-jJjZK*m-Gr!aZ"Khm#+i*(IiPH!h`aeiL4m0Gr3"IMAFd3IieR!(VZ&I`af
+B!LC`4fq$eGc49rMCF%HYi92Fm@CmEEMM2A!ClZ$1q0a`"jE!EER$CiGBlP"&)$V
+F`A("(ql`Im%2KcY`'PmFl["h`4q(1caKm-RK$Zj)2jT[L2L"p`phm'&i!AId"pi
+rh)'le)3lZ!FFK$Y`'3mKlX![[)5iSmrKM0c4*h!dlRJRhN,Fi4-%$R"(Vq-*`Kf
+H0IJ,FBFR$I8hAiXF!VmKlZKMq$jhm!EmKlL$@q*$a"eiKKm4Gr!LhXXGh!1Zc4f
+B$Mjc"fk#4Gb"4hJ(F3F@L"V9BKhKGp`4!aIQ$Tk(pa"hq1R!hlQMcq#NjKZUPJ'
+qFBH4-jj%h+%hi%h%(AS*(NAF`62TFHlJBrJ6F3F[`UH)1hS1[b,Z`'@i'hIJ(6h
+&(4J%eq!1,)!cFNFIiQ[%(If![a&h["1I)ql`(!*EZ--R#El2(9J,0c6I-2%$rX)
+G@![[jJj0"GcQMKVMBF3G(MqmLc[k%NmMlUJVRNEF`CI!-HlJ'23AGr3L(NIFJBP
+J"AGJ%lb*1rS5[b2ZU#1q4pca(VJ$GhJNiB0N[Z&b"IJXGfJpk"MFJArJ*hG`82U
+D1cJr[)`lH$9p`4dm&Tf"1cJKh)3lF!@[+1lJ-r"PlZ!9V(R!(CK16EJ$Bm"UlX!
+JH"phB!Gib"hp$0IQM[i4,i6KeS,Hj!kY#mmZml@+2AKhFBH'KBFAGiM4j1'1'X-
+VZB-$@IFdFiIIM(F9q6jpC15bPAVMFfA[m,U4dHe@*rGNR,99rb"C0k"9Mb$4reV
+eqa$pVe92$h&DD0@$4[5r9[eM42r$q"SI,AZ(4jESIfek"(Q,A841eGG(p,mfrA'
+B,1F1hae`L6[mHG!IZ'1b8I5r0MhAi-lFi@&KhQM[m$J5rDp0,a,4rpVd(8'li!j
+[($(TEG-M"pcM$KmFdIrDp-!3r@m%pEAV+A#(Ra%H80cK833[i!lr(bDaZF26KfP
+Vl[!KNY8K4ZJj*2VI#,hMd(bi`fF1[XmG[NkLrih3I`N[,qlS[j!!P8'%N!#!ch5
+Zld9UKQh3UIlaLhZ90LfCB+HE04Mpm4GQjPMU'f(#A*C+bmcjdR*"KRLhZmQ08,H
+[Ch*Nq,54CMF[QRQh-McAEV5+r0pRT[Ur6AP)1bHILaTp'0X(QAcISH&iEi$ZScF
+mlc8)0G[Md%K)frGH9Emd,R`-A'LIRcm3"c&#fVlId9NjM3XIZD(i+B6ERML)&Y,
+frD(ZffPFq+-ELX(2N!0r1!irK,&p''UB[j[90TPU,PNEQM`-RQb*HFS@L#B23bP
+EBakcfP!j$`-V25N2`bcE8Ki'AEDRqM$XXMrQDAM31X[NB4$QPT5()CPE8ak'CJk
+Q2!c8(%Tj',BjR2)`L(0EbX13!-k4P)F"RU-T$m-kGkBm$2,FPI)`N!"cImT$ql2
+pLMH9AXQ$UAKGbS24H%[+Jq&i8mU$+IQ3!*3(dr,QP!GMmk'p2%@V4*1(3IJ$k6d
+-(Gk6mQ!!-5cP`FKKH-U$FAaVbS-C4&[+J`(pL*3(NrVfP)GKpcX5rM!dqjb8Kb(
+jBbN2`q1hTc`-'ADN1Q+k2c,P`C5r)H9KkBXa+3p,B)a2H9JJBh,+``$j"hTmVj`
+(+mI1p"i'(UI&2%1qPBGP0kBFHdq)i4H'X#E+2fr"9&SEjIYlr)6!I@'"`h2@5$@
+XVIAp,b53!%`d$*`dZh&N+M[`fHJ8C,BRr2`AhD$'h(AM3,CdGYQ"6pqFII`(Vqi
+krM+"V@0DaSBhE8%[[(kU@ZLPGYrNe1BRF[r3a)4HL*&hEklAp)TkY*Th4C82%iq
+2bFIE4DjReZFf0+VQrIV8Q(iBNDpGN4FG&*8KkiZ@8Zr8dQe2[QLp((qaRR$4hHA
+)KqGhG@rTUfMpEp565cp'kX-@1$-VjIicGLXF['%mMl&l5cA9mjfk9hqpPZKCC6h
+[6NY#rZjHS44HRrA9rYB4iH`*Vmmc#!5CUV+8f6pZ!a"Ep$)@PCJ$HhV$[hmbHml
+YhaU[c1RhKTR3a&4,B%(QHX@DbarGGB)p"0dhPY!2ZK)B9TMe*`h@Y!r&JV*KSYl
+8KKClZmEU4%[l9@chQXC'P!fX09ac&`0kX5`E-TBhAD%+Qpb@,UELh[T9N91i-[9
+NrEE)UPBRjrfXU49j6,h4m!j,aYE*A5hAVX)HX1fCGCF[X$E+)mCD9h$('N4Qci%
+EZZ4MIDE)k9bCfV#H915-Ur)K9j!!`TkdXe'h0U`&&APXc)GYiZMZd"6eBmfSb&R
+GaQ9BeGCTIcHfhKbL0R9DXBdEkMDB$+l6&RKmBcCRkVK1'@4#im4*hP5RGHE%UEa
+M2Q`m*kd[P%RUY*HF2&98XEQYdj+aka3#c4f@J&K#QqQZU"1i8jZeR0k+ZQVCY,V
+2L+a3fMKVfEihB+-B&H[%%XlD&SXPA&3l5,'%LfSTLBdhGr3L0QG'ZUNAJE"bT)A
+j2f[C[YFbE9b[*H,Xl,JDr91[*DKB3YFl`5Dlb0CVIcShi%'ppTlc!Kl8Db-j2q"
+"[6,1JS!($8lK,Jaid1$+D1F(2'M3i@&4`)-'LlXii%'$0V!A"$aSd,Cd5F#$"Ud
+eP`BmD,![Z`-H0'T&Z#cJ3D1iY6cJ3D0fDLX#(M4U&ESbp,He"Vi`i%'MY9`9m+"
+4kd`QE8hr0@TaZ5EQ`iCaEF#$*LHCe`8mD0,fqU+!"dhfjIU!"deDafi)H0#N4Hh
+'J!G0pZ@QJ!G0@S0Z$RM3T(hPPS!(eZjfDm#$CLd"QB3e&U$0@U!bl@TUhDbe-KD
+fc&GKb`XZQhkfYV2)C)DR0@Z&#KBE'd9V)iZ9XTN5EpBpJ9SCI"NLaQ!*E55i)GU
+YBJR08$a[`a,D@"X1dIlbXN[c+qR4)IDPXB51JK0$l-[,4fEDp-d3mIk+LDd9F(b
+)eTeAATTG62eDV199MEBeE,'@9iHG&PVN%pFd@&r6h#%[AVZK-X)l@qJl,+(T[aD
+YG+m2q0HLGHDHJ(mYpZAH)&1fL$&Q1I)ZV(f(1K&qif6H*FP3qr+Q#TIQMYlBPdp
+@i5e$R8k&NaJq0&3,BV'%(UT0VPK#$p8'9LbKKfSh+TE3`m5BJjplRQX3$"0E$l(
+&P*%kKr(f52YMChH`A"dQ0lTYjlS+9Uc@k[3)2U1Q"iD*-8GG0X,FB@plM0+Ep`l
+6J[9fHX[JeM"Y3ZmBBE-#dl,djA2fV"X%$iEEPhIZkSK,`m@#Zpbl`0a4ZqHLjCL
+q(QjIhKhH0e`Hmlc`2QXYq[afZdlGKfY9HSpl'aMUK&[!mBYRkp5j94jhEdCbF`F
+ZL#9dUpa#,+&Ea6#aK'l9fPFXS9[P,Q)*MF@RXi4Zdkj6,+(EY(mA5qJf-88XSGZ
+dXaC,k$CYPX85ZNhF%N[S0RYG,+(Ej%CL#6e#e`'aK"iK0a*,k"&LQ9K#Mp"'@bb
+K4fMT,*E3f'8k5qJ4@YH+*I3)E96&LDKG'9SXSG[P%')*hDiYV&K#YfZl,CE3l9S
+pLb9dZdD3!')*hDjPVPK#Yf[I+TE3(ES)L#9dKha,,+%lP0A%%VV$(K0,k!kYPX8
+5ZN1X&8[S$Zeca4,DZTb+*I4)TAQaK"iTpaG,k*(DUSXPp%Ml@5bK4jTA,+&(DQ8
+XPY!Mj59L#GdTrSQmhLPI&%[S6ZhZa4+k8qiVPY#GpVPB3RIk0V'%lY4#@5bK1m9
+AXB3H*4m95qK4FNkaK"iPISXPp#KYf-85HT6p,*E3Shbc@%+2dNjC,+&(DI-VPY#
+MGI!35qM4fUD,*I4ShbIQRD2&2,'%(QhrLbAdD0mTPY#Ma3baK"kYhDjB3Sq4GiS
+Pp"MjM9K#Me%E%8[S-H+J@%+2XFI%%RU-m@)*28D1,TE3Bm9TXB3H+fm@5qLa1UQ
+**I4BF8J'2FD+&f)*2GEDL5Ad@2QI@%*E&eZaK"iR*a0,k((b','%(LG(%N[SFH+
+b@%+2Xmr&%RUFla&,k((D'SXPp(MjX9K#MpFH@LbKamZra4*k[2aE,+((LhGL#6h
+HAK*,k2(q&d[S#GUML#Ad",&(,+%Rb&2&%RU#j&!XS5H)k@)*28&F%%[S#GC),+%
+Rb"h&%RULqS4B3Nq8CiXPp%6aALbK*fUR,jE3%m9VXB5H+,k)*I4%DbD@d1`$l5b
+K*pPRBJNp5@`35qK*BS0B3Nq51iNPp#5aALbK*iNMBJNpb6U+*I4NY65aK*kXTL1
+Z5*2&Bl'%RU`++jE3Nm9lXB5H,'F35qM*B*Q6r#E6Efk5QT@pR59dPfXDLN90&qp
+cFQfA&XaL#GhP'K0L#GhP@SJbG0)&6MK,k#jUjbbKTp"ccK*kLZX-LLAd&0Fb&%[
+S+DlP+CE38l3r&N[S+DkI*jE38qKcC`NpPEc1%RUUkb++*I48ebB85qLTV[JTPY"
+6A@94,+'RZK+M@%*2"3HG*I48HXpC3Npcl85aK*lQqSCL#6h0e42&%RSDIHBXSDI
+4Cmi5HTUVm)NPp$4`bPP#RdAr1%[SXeb285bKch)94,'%2N[A$l'%2X[e3m85qLc
+AmK2plbcAk"2plba`c9P#RdeIX9kM[@1e4V%j2PXR&Y(rcYCp"%l%(DZ-bNSBCp[
+(S[qGE8q)rRFf1-9DMRc6U6[V1GSlqPK@`TMZ@SUb%XCd9f58P6#QZjUNV)3ahA8
+"iHrFXDSL()FlJf@Xp-Jh`jj$cq'1pl'q!(IJK+b%-81A#h#E1pDDK(G`a`U#XK,
+'$([1p#cI6(#+G4hY(6dR+f(-G$e(@3PMTUY!bNSB-qdj@3PMTUY4bNSB-eeM8&E
+#Q+R&ZDb%F3kiaPU2pSkHNj8`cY%P4eE#1-F9)f8PM(0F+e9@`MM(05YP*BacA)G
+39X)iajk6P6$1"DIX#L2FQEUc(U5p`ajG9X)iejk6P6$1eETG9X)i9aYd@3RMA&H
+%P*8`cVARC#@-@IDdV)3abji6*ljC[Np@`TLP8iQXK$(,062&hA1@Db$+5KLcA#p
+59X+BEFr*5KLcj41b%XCXHdj@`TLYKLmVBFc@qPa@`TKYcmP+',1eETH9-'DlSU5
+-)ThR#UDb%XCji"TVAGSlHNkQ8Fl6CPe@`MM2e9e&rcY21h[4rmjc*8A4rmjcc8R
+4rqEBFl)5aKa`LV8`lCfT1qYKfMZXff8PM$RfR-bLc(&e@&N*BiiV@-UXaKbjKDb
+%-GHHNj8`jYV6XK,'A(Y19X+BkrYN*BbjmL&C#@1Z+cR+*-GFEHYP*BajFJYC#@1
+H25FVBFac$3"C#@1H25%VBFbcjd6rQqIkRk,rcG2@Ar5rHDk"+IVII,Q&k(rcAGP
+6p,rjFJ[4rqE,%8ArQbq1L[ihhe9#4IqE,dF8r@qqp[ULrbe`E9E4raCSSbrkh`*
+l6[5r"Fk!L2kh3'iKqYm#ZBASI`YF@92d[`@ZXbMkhd*A%aApEk%p*rVI3YmRqYp
+#ZBASI`YGT96d[iAbCY(r&XSY42mlhp9K4Imlhp9'4Imlhji3rHpmHdld[r1T1bZ
+DfMZ`Ar5rmee,325rmm8jdIm@ZA+Xk(q,A*&8p,p&VJSUqYmLZB[SIi[NjD,r,A+
+PAG(r&SRpS[mY%SG%re[XbUDLrbffjd6r@qbk!U,r,CC$LrkhQ(jJ(94laqU@S[m
+YGK94dIm@ZckNk(mAf(1LrehJqd6rZd!q*rVI"ESELIjh!E9QV8alaaUCS[pGi&U
+MS[pGJ)E#fTPm5q`2dIq@Z&+#k(p,A,Y8p,mPpU,SId[N(+,r,E'ZS[mYN4q)rVG
+%6LRkha*V,2VI%VQ)k(p,A,Y8p,mPVN8UqKqqkkbrDHrS,G(rPMV',2VI8PFm&Ie
+[UBjKS[mY&AY%re[U@JZLrbf9pi[qYe6X&re[+6'Xd@R[i!'Lrbfe[dArklBr42r
+VGL9AdIqkl3r4rlVP6+,rGDYYL2lA,GD+rYGYIiMqeff2L[lAEAq)rYGY286rklB
+HS[peLm'Lrbf6YiRqYmaq&Ie[QEa6p,pPVViUqYmb9h`9r@qCXf1Lrbd64dAr@bB
+I&Ie[QCJRqYmbqEVSIm[%E0(rPVRDTZKrbq9jS[mYPdH+rVIFZ624rjDVEBMqYe`
+R10(rPX[242pElMV)S[mYYcp%re[ZZJkLrbfh2d6r@klf*[VIFVQqk(mVe"*%reX
+K4a6pEi9VdBVqYm+C*G(r9UKeLIkh`M@'42pEBHq+rVI#PCC&re[KfUVH9H3RAIY
+8p,m9VKNUJ5[!-PElY(F'#eMadpkCrQ(96hYRDX(+Rh`VAI06p,q9VLJUqYp+-)p
+931dGUkD+rVI5Y94&re[TUV#LrkedY9I4reDkJU[SIbYGV96d[j@ZmbVkhdVA(4A
+pEb@pa9UPpXld-'Z1mPe),9LRe0ka)URSIaHkiURSIaGD$p(r,U4[@028hY%VS[p
+Gk)U[S[pGk1UaS[pG#+k`[LRI+RU'P8hYRAN$Dj[D1eC@&Ie[P5ZrL[khbRP$dIp
+@ZFUXk(qVA-e8p,p9VJSVqYmUed)5r@m9[Fh+ThbVID[SIkYGJeAd[p@Z&#[khfT
+`La93l4hVd)VqYpS99NAr@qekV+,rVAD09Y(r9S0pV02+YiEqC1e@HfIHCYG8iSl
+e@%Ar@q1DXD,rVA%0@p(reYK2S[qYF9eDdIr@Z&kYk(pVa"M4rpD!@DcYbVH@hQ0
+e9hYRmV,#UlfMaU,rVAApA0(reVVUVHKrDm8jdIr@LQfLrkeeV9c4rpEk9Y(reY'
+hV2aUlqJRdIr@ZEUYk(rVA)&Ap,peiTESIq[%+Y(reVNqV1KrkebY9[5rGI!+9Vl
+PBpNeeX+eG`B,@!rAhTQkXb+Z[@20@p(r,K)[4Iqlb09h4Iqlb(9K4Iqlb&9M4Iq
+lb,9e4Iqlb29j4IpE$qkc2Ukp-aM('VRfc[3`kq6D1r0qeXUeGkce+rVIHYIV&Ie
+[[D[$L[khAJiKqYpkelF9r@mpI)QeFrNfZ#kXk(mE`%h@d,9hF!A4rcEiEY(r0[K
+ZdImfZ0U[k(mEd%&B1GMHXHDXk(mEA,p@p,m0m#T@&1EEk,UeS[pY"0GB9GMHQ9j
+PC@&lCpl'kX,fMTi@r@qMDrk+rVI4eAj&rpYSEiRqYa(1b@V$I*[N!D,rEE+R4Ir
+E"0D`mV#p-rh!kX2f$S`8r@q6EaApEj0i,2VI*[Q0k(qEa#h4rcD*@k,rE4BM4Ir
+EE$q*rVFCM'"0BAYRHS"eL1dGka+,rVGCr"$pEl1i*IVICYI$&Ie[XlJPqYm@9li
+9r@q,DqU+rVI&GAY&rpX#"YQCDqlJ(k,rED%@V&jXleM49r5r,Dj2,2VI&YFd&[e
+[Laa,p,qYiSISIeYGK9Id[kfZmb[kheE`MV@0lChT6eBfYRIJPZKr@ehE9r5rVDi
+9,2VI9VQ)k(pEIEISIcfq@r5r(R&,p,mHF9Vd[alV,ITI$lh01X$fcY51YAlY(9a
+%p,mHZBMSIcfZ#LckA`pmRY9mqEDj2V$SIpYmUqKrfjaY&re[QaJTqYmfDbckhcE
+HcfV(pSkH&[e[QcdYqYmf0![@2HEElYUqS[pY&lG%rp[ZQX5LrffhaU,rE3FI@AR
+ChS%PS[pYTaDX[fc[i1LLrfehY@24rlDl3V$SIc[N(k,rlA!eBp(rGXJM4IrE)@D
+)rVH$AQ+GBR[(UX1Lrqe`c@E4rbjf2@(4rbjf4@,4rbjfY@E4rbjfK@R4rbkfEd6
+rZjMqBG9QH`IA&rh[B[Q6k(mlAA9Bp,qGVPJXqYp1hbIkhdljK1Kr1m&69SqfGh!
+QdIpfbZp&rpYTr86rfb@(%2e[PkXHLrkh5b0ddIpff4qLrqebr@R4rhEj2Y(rGP%
+[9Q+fGq#Ck(qla@r4rhEE(k,rlCDML2khfrH*rVGEc8$d[peb"G(rGSXVS[rYMUX
+[fc[d#G(r,T&2LrjhLAaDp,p,A&GDp,p,A2YDp,p,`&r@TEChk#kLree#h9N&fpl
+"+8ArHjDV*B[qpbaAB4Ep,r6Q-`KQ0P,F2ZP@IfB[aB0l[QX3&!Eka6G#-KJB+AG
+F$&YT!11#*+*UL0YR"d$-'%Km(8V-im,H--&Bk"cVYYF0$1c'Dfe1ClEC2pfD'@J
+AVGVXG,FcX,ZfCq##rJX'DUhTcN#eABqc)5%MAh&&Mj!!PXqbJ[!DZfUfq3L&@E-
+K$'(eJhT(&G1pPQimQGZcBF`b-KX)MM1rb0`LmiV-+9TI3R-bMmM-),1)c!XbHmJ
+X)[1#GJPkFc*hb'`JXi,-!M)rb"bJc2q&+Rb0#j`NJcFRh62rH@q'TpdjRmU6UQS
+)h"F@D&CX#&efAfA2Ir,[2RqIjE#%$3rr$f1UIBdPaIZAa9rX2S2K$NX0"N5h8Y"
+-T-NGqZ,XE0FFGa$B-p[SeYF0cADkVCQ+hU1(LKVZSVN8UkGCLreSCD,DeAdd&im
+(+rkMaR,ejZE1"e+XVhYeR3kNa34iN!$ZKH%G+kS2a"Zm0K&lmd[bjS2KkqSGVEm
+2E'p!%AYcb$"EEc5+NR'4,E6*h-!H$V5TC1%"ASC,UdAc`4U[h6!QlFK(EYTF'@p
+hkc2eUrlME4LE)jmG"J*+iGALfIKRMAdpe*[cmr5j(G9Qh[KkNKh9cR5eFD6kNU+
+[r!`69PZBm-%@6X`MpNE['0l`8'LP38cikXl-0aYJChl9NHTILVXeaDeNZ21LThq
+lq)4A#NZdUjlmlbS4GDY@b-Q%aZkh(p**8!&dSQY`6S)UQ"0HJA+Lbd$ZJLXBi$)
+%MH*L#deZQk)+i2(i)RlCq$ai%eH"EU,,`"d,,KHX!0S%$N!f+@U!R8K3+AFCV&e
+`IjZ@J0V&CQ%k&PKUK`T%%ed"D+,li*Ri-MLli&)TI@"1"TYUpF-`#5S`6(30KNP
+3K@(#+c"-G"Q'AA#P[ef'S#PFE+8TUM!FMbrLNSh2`c"a&4JQZJc$XH"b`3S`61!
+!$*1L"X1*"*9bPf(B"IHhD3Q'A@`@KQ1"TADS`$$4&4JQZJq'L5r$X!XZPE)-`qX
+(Til#-!NU-%ad$BC*8)9K`LX`6(3CKPe`TEpGKU!TA'bP+DS`()m[iT+0cm-`F48
+B*VS-`l(JFX%+-%cJ!!b6SJE$L359FTGKf!AhYfN*KPeX&SCMJD9fU-!`d48B*VS
+2KSN[`l!,,T8b"m1RC+P"BHU80(9#R"U8T`B%UY-59Ep)05"6R45U6NT9&E&U8+l
+kVVKd5Pik*6!05%bR4DCqQDNU0!e)6B0Ldk$FG%Vk'44r6XNr*`5J33PS3!3k,32
+e#d%$8Y"*-HLN(&34K!BPSHm+1+FNR&-LcS#-FeV)kCGbUQ,1J*`c+1J-5MURj*9
+"JH@8a(*#C"Q8@3D%PY055lrB-L#hR"4F6NSZ&G&P8(EjVNKb5LBj*C3-5#@RaC*
+qZD3UQ!a)*S1LbD"XNT`B,8NBk54jZ%YR+!*H1NN!HHN8HG",CmM"AMj"[Krc@C)
+GQBp209kQF3,i+q4)BdXQK`q"kGJm#+BcP'!`RDB)K-8NrHA+J@%q`FRfb`*L2Mi
+1L8&`AfrQB6'GS4mB+i*(1NNr-&C%Mh55!@$X&6l5'@V!@"8rmPP+R9N83$+0-`#
+-C4%NNk-A'(Z&N!"dKP2!@"&$LNRkbe8$aUSNNXr5ehjPB#`+)lN%9@$X&8I5d*N
+EH3J5e2!j0IU3!!iZL2RT($P"2jqJMerNK2ed(p5Uh$YM&@3)UPbH(%VRU&@j-%'
+8MkqU"lND$ik[9!GB6JjN$)aNp!pP$)aP*!TINI$55IV*@dA'5bFC)'qp8Pik3if
+m9H@mI*B5)"3P[8cM$*!!Yl+XPmR45pjkTEedKP2NV5,[&C2dPkY'hUSLAcj,ArZ
+9b9Y4kXXPU*+hV0bApiI*iQ+3!#-*Ld'#$#S'19+J''4)BQ)K`FfG9M0@Zr$%@h1
+XE-[K2U+@iT-GA8SL$9d+GbeED,F8QPC5a0#TN!$#`p)J0!QP33+IiTAMqdVS5&i
+3Qi2T)%X'TDXjDQhJBh3TrN4$*a#k&!j!Pf1VRC+%jb$"#A41XqBJK8qE5r(9q[V
+%14-IL*j"MKSr##62)%Fr2mJ+RS8%9AjJReMK"aQjY"4IJj1d@&S+Vl9E2cr)+k@
+&&%9qN!$95B-%II`JUh+9%q6j39'$$E)-mS0!J5hNU2+$J[jD5P*Yk")rb)L[[I%
+9IT!!P9k$"!2m)#-CPZ+VpHhM"i'Z&Z5SmB0!93Ybp21$V+C@5&$P"rD*&Ak3!&(
+N5[%e1%RVFDA`@V[emi1m'&G)8H3(@5NZ50$($l)DF6P"RKm8CEiJbb!r#%5q3Si
+U2bK)I+8NeBBZmB1-[YFEAq%(*p5p[1SHT1MM"fRG[46ZDJKiTA0Nq8'3!#2*$i)
+%'Ai3j%MaJb"$NKm%#Ab!,m8RmD#842UP&&lVPa6!9e,%N!#YN!$#!rJJ0!R`33)
+Ii-[aI59d!"r%jJ!qb*)"q'U1@K[i!&q+2p(3#B![K32`jGKUTb3"2NL3!!6i)%%
+Di)-82X#AiU[e6IVbQAS1!Rb3!#-*m%'#$-!(19)!(f4)!Rb3!-!(q&*m%Jp+5D4
+I5Z'eINN"I#9&$0N++6b!$d+6!"mNm!'q(0pA3JI`3@`1i)-X'B#[jULeJ3r`TIJ
+6$Cd!q&)i!&q1VAC+%Z#$"%Q!$a+N!6j)i30m+EjDhd%'ElYpDl@jFlDk-rmQ(X3
+bP0k`VMAp-+Vi1GK1*CK!F(&*8Z'#-N6#aDA)JiY+%JBAj*-%2bD*)hkJp*BINUe
+K#[46B6'%Li9ji1kZNi$ZJP)pPi`5D%r'C!T5DVBFI,[)$'5Ril*&p+(CMbQd83+
+#r4"J0hQIVPB5APe3%P*G8"T'ACJ2RAj-ZKBq4")6f'5iZ#`X"@BB,Li(5eR,#aH
+8JD@#XB8IQ+KKaViL9X-F,190+Q*KF9M+@P'iS"`XC3E%Nc'CJJ5`9$5eF*%",!A
+@&E'i0#`9$#Vm`(3EqE#8FCj)a+4J+HX[iB,bX*3CC[GMdV9)`e)!59Ni#U!S"d0
+C#-V!6`&kdV#6JC`mh15K*J%c@BM*`8X'@V+`%N"+%8i#+!PJ*!-K"IK)3iF2'aR
+)b-*&$LTL5aS9@%Fm1XXpiU%"!iP(jhK)2$E,4Z+K'8k5LXa#DLSm!@DT3"p1%jA
+2FC9-F",X%m&ahK)2bV+AH'L1`k4M%d`Q(9NXAF"UiY&&EK12$aK10VUhp"QfNiU
+X0QLDqD3#(Ip*4a@UQq9#mG"HQ#Z4khKd,mb9L(BmZJ4c"G)G$bh#A*Q!Tm+cA45
+3!2&%j8X`ed[-%m%CQ#Z3!24iD!RQ!X+HMLb@VJ*c&3SIMkr!A)R1*k),-&HQpUR
+`3S2QB#iJqmR)!1B+a(pVIIY$A-l&CL(1"3B!jf*cm1BLXq$Q!M23jXGPqmB26R5
+0(qCh4kc118K,K5Dl1KBDKc-ANJ8c&jL$XQ4N!XL5F8'a!K"cX88)Fp%"J+9M#iA
+1J*FI9fl"0($jB3kfNM(jDQBKb`9Q!@[Gk'KP,C(R2!"CmHJXD-9$!pL+4qH!+ak
+EKDjiD!Dm8T(ChNQ&*lSR&HMh5U,b14$,"#Hl1a%F"l*i8"E+iU%j-%[(*Z!X(9N
+XA3"TmHJLU-AM!eM,4[H@2J0YUFKUJkEK,4AS!#iG9DKZ&Z6LS39H9K)IA'b"Pj@
+%"aGEj'8&dF%&"VbX,$Mi`@P5%)J0X6SAH9Q[d"!,6I'bJXMJ!SZm,"!BNR&"X8U
+mV#)YZ1J5,b[*#V(B2#mV5`TqF,i&-l`X%"-5F6PH9K!5iKV$ZRcll-kGH9%*-*5
+1AMmemB!bNCmqL!GRCK"5N4I06HHd["RG+V`X2Db3!!SX#S@9%K)GP,"hVLFHA#b
+KLkb@-$m'P!S-q(433"HE+Tq,bKI2K@C+jmF9#ZFRb!X$3G&+`"'M,GQLpB+'#`f
++9J--2d%H0BYJi5M0KNCV1pKGNcG0Q3j8Qc8I9j!!1$hQd+X@!p!$Mb5&HF1qmmD
+rT6p+JV,1+2%&h"XSG%c+kLed,,jFD+F3$6bb9ZKdJ[,F3+l3[R4BU%"5VmX@14Q
+G,l%[JG@Hee[HI(L[k&BXE3fUNT5h80SqQ2*CC1ejeG*@!#SIA@#@)23!FT46q05
+N9X'"4bCTc-lC*KNb%&J)cr+f62$!``LI[k"ZP%M%JV,VZQLl'iUUr#FG[r$"QBE
+c+i1e@Yf-8RG$RG*PlAmp'ITH6hcKp35@AqqkT[4f&epmZBY1[pZ&e9lGefmZ[[,
+UI+qjX-+V`lbqh'j4N3heSU-fHp0-hZaQkm+DBE6rTTPfUqL@Ll,e6'bpjhT0YG&
+Si4Df-@qdXl'YPD#)fN5ASQ"BfC!!@b2+49$fr05C$BV-CYAQ,CHfLNDYIjTellC
+@K[TPKHZVDjpD[rbLfMRpP-,'#FN``9k)8CR0reLZZIIN-Z8)AJ&6R01)1AD0M'r
+CCKBEQeNT*l,Z[SK-Aj!!*&ClZC6DFqXTPC&Y3q-E&KV!aXAl`5D9D[(!@29LYhE
+c[4ZVdrPLaIeQm,0kpA34UI+C4V2PbfcX%PRA@m`aPG%%jc)@RZ&D)p13!,'fNiF
+PZciINNP$Gq4$-QQSBMl%KjA$"j1QA-d,9ZIj92&#T)0bUH,&5!GYU-lN*IXb3AI
+N"9eYeLE(81p)cZUNM%dF+V*S`HH(G(ppEEdJ*TZ)!J8af858*iM*@jAi26lc`[V
+pH*X+5SANE8dLk`Jm8LhUH@GG4$6hhh2-cF&q)U-Rr-5FG5f`'a[$JfAD&,Th(iD
+$iL0FE40AA@[(k0TE+j[bDZ%i8+lmX4GRHb!H@BT,i(iL@5`N8b9dX%20GBG)35Q
+*)`[9$V06HcNZN@kKFM91p-ck`bf6CJ@C[LQ&ji2&HL5blZ#&Q$ji!F$KFq[YrU*
+66*FAqrah3e&`FDaDCa9)Fh'S8mYMT1'GjYq0+2EHcHe'F(ecLi[EZr8'IfmU0ED
+Mh1`TVQahqAqXHf@CB%marC3,`rpMeHeFl-eh0+TG(h1Xb(06APr[qVGlS5VfCPr
+jekY,pd*KZJp@aZE`8NPYZ,,&k9kS6RFX6hH[2Yd(#p4pX%)Q`LX4&ek0ZRY&kMj
+BTHjBTKZVHmSiqHmpfUZ([6K3RHjdChIX)0CFlDfA98X%FHG&QBY$jFYL&h%3-E-
+,92&)8)RPdS(0NIb+HJHTLCFPlVc+QKKhBGj&!ab0&A"h8S"i+@bP[2ViY6*iF+M
+9f0kD+pXJGV82@H1'SUaAr-VGQ2caUpZEpEP'2E4,iLjfCC)PlZblVbX,',mbL'A
++[@Hfk*5[L&qj'pX#lST'1TbcFkrA8pk9Zr(H*9IQ"Nb3!##j1Pc8Qpfb4q-hZeU
+c"@`cNGS2L6@0LdQ8aBAijABaLAC*[-C9a)A%X-i&a-!Q8j98S@*3NkP+)X6[c8a
+9dQ8R`'*c)NlZ$AqjP$&%2f-m*,8MYL8ImHZNBZd(`dr@6lB[hh'`X0!F`kRNJGh
+ha1i*4(N1"Eqq,&Xk9bEq-(6V)&U$Akp%61`Ud@'*Q)6Fl"A-A@l)ZaYDphC"2)3
+E#)VI2BQBj'#TpkciYHQbJke!3e*A4pZ0ZL3QF4@V51)PANI0T+95!6C$3XG1*,H
+j2'S%lh)APY6k!1%&q"#BM["ca&Sj'4$,kEGP1Q*IPM[KZQF([54hA#9kbBp2"AQ
+*BPG"q,kib(YLr$@lfAYfr3YrMMFcZjZDedh1k'EQj6+@X9NhdB5cTKYP5mrGTQG
+YCEif2RbAmR2-'#HQ"eLcIS+q-@$@#6(K#ZJF$K-1II%Te$flUX9-p4"T@8Z)DC&
+i5*iLq5hU3V,FbQpc&j*P*$Rb%qIEQHFR8k6BQ'-mlMV,i(,X+8r&mTc4alTXL%P
+mY&Fc3G&dK%NV%I&H-h#qDblm0kK1#KI"K4GLmL0XT9iN%BA*Xm+mQ%'b'jTA,$i
+L&R"J@X3i8K*kpm"ib!'(*2CFAK-824DH[!qQGA)61SQTR0#a5Cc3KUq*A@,VbSf
+RSb`-fl*dh*Ehhq'c#q5#"k&[J*!!`)1'J!IGpDXkZiUJ+R4RJHQ'XH'"q9[(AXZ
++QF&M4H[jHE'R`d#A'FbrVR!fRm'1ZdTpfNb`l3Nbfej'4+qVjF85BfL4i!Ierid
+(4X)00k-,#6aJ(ra6H""f4Ki6H+!#(RJ1,EHhRAS2Ba1A%RMJk3FKE!K3a!0lUE-
+60l@`GHVlkXE'*ST(ASfk[AYife4rifLHR#e$kV[hi$[Z1[U1[*P$pKfH"D3hCeE
+i4Je16)`q8[PV19HhfrpCpbIHXAEmQMh(mKJI&!TEbl'fdAPiH1Rd1cE[,REdFcj
+6elEbV@[A,`h3(cXR0`mY$I!1Lc$AlcU+-,i,6qpRhh(6p*&hj,e*NPm-1IGeCai
+"%IZ1r8HlqR6IK``JqB([`8Hm(J-F"6HNlliM&)"CA$ib86RfeX%qSqr0,1Ak4pl
+"YlFe2IY)Mi',eMdM&1!GI(1Q'`aVrV#ZpKhlUppMThEZLRHB!G`IpePff$[cG5d
+p`5KlaNB[2TBRl8C@V2b1dBH4kV[[#!eJJYX[h[KI#*bb95Ym1dCEfjF'U%G)"6-
+G`2+NY9cY(E21A5VJ(Id&qIYhe)$mIlpMN!!422'1'qD1&Z68&cDJ*2b`le&X3JB
+8J)(Z5,ND9[[M-#iB)3([f(1N3`El)elA2EZqMBarril$4pMlB&eMl`J28%L1jMZ
+A#-#c8!#P*Aa#f6LkUr%`AdalFKBq()A#!Gl"0iFQHDDZ1`kqidG0B[@'q$i%a54
+$PTj35%*101A`!!BA+U'pKLXJqHN[krH8q5BYqD%*QY,f9[jT6E$bMR#6kC!!Tc5
+iFRGm6i-lmBiR0EJ6lhK5Jc[jMLFdZ-&hK&*SF29lEpR2"&iNHrc@ekeF1hBUpar
+)([r'IGRM2RA0SET1ZR9p0VlbcK9hR2abiq[hhPCEU%F)J`CADE5R0EM"GcbT`I8
+qi`FDh)Ph2+A"&4m54U$"pHF3rr16l`J&B0bBV!r@,'[%R[p#2l5m-U"p6mZV-TQ
+`!#f[jb%T3VlfSG%YNipd%%`RI'+k+$aJ+LMXC(VQeU--cKKh-VNApr*-I6'Q%ci
+aK@-mYhq-DGilISM!XHQCJ5QF[kY(q-hdc,'P!(`kc@)j#bqX,+k#NrP'ISF4Q)I
+81[ST4R$L(8mbJK2[H",*6llM#53II%Gi!*+(,mc6pGBec''HVY*S6c1#`AFmb3K
+kRr%$4R$L(8pTHF@(a0ia)$1CGpL0P%lJd*(m5*raL"Xk8C6SHdFSJ*E(&b)`,mC
++'08[SGK8%Gqmip$fhGpqarEYZapqKdc[XkCANF)0r4p[&I1+5Sjrm&DT[H2dY-U
+J@Ka#-+hb)`q5'00j`S1NeKrK!@Vk2hKeP1[a2Dq1@Pe2UpHRqjl[5Bq0@MhX1jl
+`aULp3hCeUJc#G5cj-3IR&6LSr02UGH8Gi44cF%pTAP5eGl,K(c@[%qpi8[-kmBi
+R0Dq6lhK#maTm4hM!r0T6@P9[2@)-lLP0TrFG2p"d"YpaNJP@J&@qN!!+Pk4`!#d
+QYAA!d%H")&X(0#DRj0$6,l@HR,H1BmM+&`ShJf5r-lL,$65L0chhr0,pHY+CFbZ
+ZZI[*h+r+6RrarZa(VQXFUZ[%keGRQfjrdiTRAhfAmG'EUTpCU-FCIm8''Xr80Fc
+"YIS-h@8$M4#iVfGbC2LdN5BDpX'm@aQHDcGDaAGpIcI"38KVZ%MSLPeUD-cA-($
+5l-D4UHc!THH(!'-frrR*Di1rG$IFDHRXXJ22I%Efm4qmZ[0f3LEdEFa1(K[HY!@
+RSHZRUS@Z-IG06Qeq)[F268b8cPV[f&b[UISm@XflSXU(L8H2qhLl++Fm2VHK86A
+[ekH3!&(-rmHCa$LDpI@GY,jS`BM9MkjBj+(4HVD+[pH8GrZc-rRlKM,`hZb(q2H
+0XQDcpF&@*j9hFl+ePDc[CmUlml+RmHr&-4p@qQq2GjZcl14ha#IZjY6Bjr,C!*!
+!0A`-k,lrlHYffqX'"P5ejh4QQrhXiM'A)BZpXp2GcX$ZfTk"#rS[')$*(afSYZX
+$5j)dJ%CS-+"SIk%[hmJe3q2VKpG8eU`IR"VNlik4SDNe5kXd3#-l*hKI$![-mN-
+)KrZP60k1-d@B-(P'm2H@P+HG[lHQ2#2jHc$PkH6[SC4R&(m2Tca`cpY5RM(m2C,
+bM1A[dC4R%Rr[6(NQmrHZP!ISZMrPJ5rAaccQUTaR0F&e+Fp'JTY5RNebq90jc)b
+`1M(PkH([JC4R'hr[5AQB+AX6JS'(Kj8mGa2HN!$HFar"Be1HPa!m-Z9jJ1#1P1H
+Pr,dqeI&"`M[6Hhk+i#NTcrd%Mcq@j``)i8[YF0EbD"*NKl2UAJ'KTamlR1'D9E2
+,$MIj3Z0QN!$1j#jf1(ZQVQ%11bHFD96XF&DrpjEpj4k9NlHqEZADX91jrd$fq$I
+ZbalhU@X1eAA5VHZcmC9hVVMMj*FEAlrhYYT#2Fk-AhBiLpiA&3kd#FXePhHkeBI
+dZ*!!K)qp3N*N2SYTCb!)fmVpMiq'!,D9q`UEbrREbRhQCVH91qBfF'(UfmU&ebJ
+-pGRb93GYp@FLe*jcIiS,iaI#8"Zeq1T`Z@hckS'!8"JT[2NHk$E6p(RS([c#"k!
+pqCC,qUlY1h%C5mkj,k5JCbZ2!L8F8X6%N!"5eH`3'cQLkdF[f6DpTekE+&UlYdi
+bZK*G%U"`q[jKM[pAm1+kK6fFQcLhFDlLA-fjNA-,jpfFScR(F)lPR-3jQA-8CbG
+R1fFEj`M1NC`c1'rK[)rc*C`2F,k8md&i01XDARCX,6b6Kh80RjhbG2$hmT5(G3f
+[6(PBer#UP!IalHU8Kh80VdPj@0I`fT4R((q[5hPBer$'P!FamUD8"ijiAmV$91c
+V8KkceQ(NG5N2`emReL%dHFckKj%hT$aQrF2)De)Hl%9HQ2+`rZ%9+3rV(cirjB(
+aI#EPH5(KSe1H&r(h$5Q2@4-aFPh+BpBV2,R@SFPMeMp8I5N2DbGf(FYcjSh`SA2
+!$H&pjQcRl1$Xj"c&1CTcM*`I2JpAKiI$XH(2F'0i,j`@[JSAK4I#qH"cF$9iQ19
+BU686KckD"&NcXES19HMTjiEU&erdX,0`@-NA#MH$C,m`932+-&V$Y-B!KXm`2XY
+d3L(S6ZScQaX0f65qDA"XZ(pifcG`hNlH@[CVrXMrV*d4,hRb`C%$R(rqD1jLEG2
+S6Fmp[p3"*jdjYq+DZjr-rDVXp"I[chlNZXDKZNkmIR@fkIBhVAMfeAFC(lfTqTQ
+&HTca9kaYqNaG`aa@[6XMGeREp!`%BCR0,5b`bFFbQlZZ[AHCcBh2F*R0SfmR*,a
+NQFd`Qp8G)kG2GQYZmm,-c0&@)lp[QM@ffCieRq+NdbllNb83DK0HYlTM+!`'K-4
+mBET,iRA'T461l"1B8qN,SpMX08aJ1BNcq35qH(+YNc2["8BCEX)+``MH-j(c#h&
+$V5r'kGqrF#mpmhdTX[-[Pa[c4V)[aXlkDScrbh#[IMM'I5h'ICeYfIRqUTaBMQ4
+ha[ar(E[UEf+qEf52+IrrEAcR0m0rY6UqkqciIhVm2b2Qr9CmclGMh-3BpeKmrq1
+aMYm*HEb1#G9P8Q&RAi`(0@qmZ$AEV'%T9NaNA38`46*XLSdP[c1rG@66qZCXB`N
+!"l,3d!r"+DA6%f#$E(4LU6FAP2P#!0Ce-kqUVrDhC[r[%H"mcf$T31-@KJSGk*2
+HZc1lK1q-*81&5Ba0Kq'S-'Gf#9p)mIa,b)ZbmVekrYqlm,E[c(3"!cc"4B`(*55
+FaVR90SPDJ3fI$!,92Y4HqDVf`#@a+a`#&d*PqMl4UfG5%MJCl`SDZCd6Kfq'mh(
+%EZ$%+4ZAl$'FZ(@c-eJ(j`M1PSJ&Z(HhFJlPC0q`8C`iGSrN(-[Cb6PZ+BIb[Qf
+1lESL-jhZi9hIM[eUPUdf,MdK1KERmk('(6cF*M2j-j1iQqm0Dq"p)q2lkQlV"AD
+r`VE`hZI(+4E5Uir[mq0QdLI0qfHkjHD1#D4U)&rN,Z,BBM)4erK-rR60G$Z(mc@
+k$CV8bArIX"qMc@I2Y$Z(ihEF4)[[RHRZ2&bR4VCDLjc+ZkPhiRe0lqI2Vmed'ke
+liaEZ*IqULG&10e[q"AGIQacL1Rq$2h2+AGEU2[3HlXi,F3HI$p4X#R([(65(&cI
+bAm8J,qjAAX$Gh""hP(k0V!jahcR("T2hI8aFmZ)qi@k$bf+q4rRc8"NAIHSRZ9X
+Hqjlpe6D(I!ql41D+%0IbjX9q5K#ECc1('1[,4&bcZ9eI*Z)Dpbhf65+ZjAf,IC1
+)fr2V[IlirFZiNeeqphbdeam(a9AC$(1IQ#Vpm4XIjUiRa"e`efhTM`FrapeP-Hj
+RH[eal58@91*H[G!IGDqmNl[,Ber5Rejr4+IXb5Y#A)Fpj08TqT+riNj`m"G@,p3
+THVUB)CZUYPqd8+IS#phD8RC,I35mP$T&Alk&ZcXLlKVmN!!k45rl-qi-2YKm2pI
+Vil2&0[+$kp4'k[4+0d58h9mll$q[6[T*Rq)12+&pIRDK6VV2A[pfL"[bSB8kkCF
+kFrTBL*Yaad+Gp-@rc0hMXBrT6kp1H[LVh*PGk[L@[R1K6ZV2k5d(MGeLQeFRYCq
+P&Kh$(Q+0Qd,rIH9hL9XCFAU5A-UVklV2%bFlZcA*2b6IPrqCZ+YM(*[SHIRUAJY
+h8qAZGbD1hHfmI0'9p*EbAB5mTjI[VKF6*cMG4"p,(far#RdJHq"&6KBc[,KYY3Z
+)Hh1Xhk[i-cA8pHh'I65q!kiRrG&XAF&R)2'qKIl3,`*Ve0q%Z+%Z-1ReKci$6U6
+q0[)!qY*lRck0RPIr&2[l&EhhcB5R+V',IUAZdRm["`m82@*j#FZmbIZ@`@r99b*
+1rc*raT9aNAH!P9VqDm,(mGDfDd2FErdLFI"Gmld+rY%3qLEb02L`PYqDI,2Jah0
+[$A&AITBiq+lj4T!!3adIiUk&HfKj-Hrq2B[VaGh`am5"lF4pDU'ZN5IF5KbFQcJ
+ifA$MMXrrfpR%JIrJUhQ61LlNqp3r%LFFZdQHXc,%(3*lY([rm3lUEYpKS28"iLC
+%r[3R[%0f$A`aNp[DA4piKmNK1"(jrp4'4r`B$BG6TiDii@ka*rJa",i5Z6$%IC'
+HeR'Rf(fmThiLe1qVD!Mk#5(ZY@q&,lD(I!rF6Gc8%0FU"lSqa+hm#q+Q44b#-bd
+*F4I6NeUmSNlS&F0Lhm`Qc[5)M3-RT-q@fdr6Babm6ITXrkZ*NfA[4UTcr(D)H`p
+[dq+YqFj'$e"RKEK4p,D@Hj)2h(mia!eP0d)0[lCi4RpErR&mrN[`84ehqecm,Zk
+NRbDq4#iZIB-Z)6Md+*a@"hkXR[A&(Jlp+9a,"hkXpVb`Kd26fDT9"hkXpY+[$SI
+Qd%-kEUJi(plTF1J&Vb,1B,AY*lLAp-HGRb"Z3Dc(bhVpd3'2e%q*G@9h4-'26R"
+D2cA%E8,RF$Kd%Ea(Xd1LlH0hpA$SCA"F(IF5(UDZ*1qiiUA%A4$L0X06(3jp4*b
+!2e)RH+h8qe*Lp)q(Z0Ir83q(ERdpFD)(Y)Q$JN-cl$p2$e$Ai4cLiC!!@9'$r[$
+d!(8pQaFk(2ShD"XkkJ&M`"k(3epq*A(#cpVNiB*$M@#"M[bXaIF,$Mh(ZSTr3E[
+i+(dfrAELi)1d'$a-qZc2i-BkEPSl(ClUF1Kcm%XGYdImHIL3!-1KYlfE10Q%GXQ
+024cDLGDLikSI(El(im'4#ATBK`eXe9XqeX1Kc3HiJpp42rLcdcqmc6PX[VGm'Fc
+m303riR'40kZ2I6VU(iQi$KeDR2i4Mp1VA(GiAp3r%[R'LSq#IbhL)VU@HIH[`9m
+GrVd@(Up(3Yb(U+Z(ImIRri%lc@k5a2hqTKlqADA@*6V+'cl6`lpAQdpdP!jjTr6
+P#ML%MMV+-(QGlF[MmhI"QcA[XR@LVi5(I84H*AZd[J9mF[MhN!$i,FXr,j!![`V
+qAB9fSXXG+mdlf#YIm1qem'1p1G6[@q#T`lqAL+qbIhi,f1EKhr(j[r`)FHKA*Y9
+MD+`1rqTrMMM`h(a,h5&6m'mY'S'@6jP8Mm2I(!rl@lL3!0iDqV*1(9,`le+iVik
+kdI9I1SKraqFr)$m6h@L2pE,iGhcqGM"H4peS*(c&iGp9k-3kkNB,ZA0pGJ303$m
+RpJ&i)(hfQ(Km9BKlUhJLq(H*20[61I4ap+Z(ImIRhb0HHMU(2PiG3["[S4a,&SF
+p+Mm8([B&qEfhEV-q!9cfm1rir#I4)(6Fd,VeAaEa,llITPi&$fLk,H*I)Zj4GCc
+24[b,ad9'hD$@i9mLhbKU%m1r4,iMERlTi9rG(iKcKYq4Ec3mAr![qMbd62fL%$I
+M,3[mVqjkZ)F15f[VTi'TJRpe0mK6Aa$LKS"hJRr4Xq`ESrPBR(MP3Pp'XlmMcQ#
+[VCr*iI6#0m+9pG8acR!D`DhSFm3RlXhI&R"+m#pk$KLKeAQS+hUKKhr4&k$&k*G
+&r%"AN!"hX$QT$MU62NqYb-1rZLqK9HMr&h%DMG29qeH*)cqdefJcJRr4R`!l0$c
+8pMhij1&Ip!`d"5fI0Arh`Q@&rp@pPEN'$DFMEYk[,H"Ih4[T-Id,i4e[**r`[qK
+b0!r0HrRHl2XprKGYJR&DcC0hdbFHrNA24[[3kUl`*(L&p0RH$a,h81`$F%[dc[2
+3ZE@m$lS06RMi&jeKGe-0CbGZ2ca@q&rGAm1400S&FEI)%ccmLfk&BfYe$qU%rLf
+kmLr"bEAp6MkMK`VrUrX!ZE9e-(m2fK1HAKKj#4LQj4hQlf&Q1qSLRhL1ld!,jAe
+SXCiq&aN&Fl9kX[NHNFm,hSpr'h(SYm6"ai6RAI%QiPi6hMId$rRRkAD4[@J6@Th
+Ir$hI2[0dZmLBZSlT8q+1bVfN6S[S#DhHDrlH$MpdGET'r[(kq!jd5DR6@,LG9Qq
+(ek+h5CfDj8RHRUakcXehT%j[KPYVDQAMk$HTdb'iR9C$0Rr[kZQ,NBYqM`"2(p9
+AbKfP6K2JkYSj#22hERLfUe1RrIe`L,Z(A[(UC2LCd@)d1'rj4a`r)Um'1c5kQFh
+h"ldkGGe-!2Q*-jcHeHQ2k@hY,!Ed!Aj[kh4mrJjjfb-alS1p1Vd0E8@(29reci0
+9VNl23S28kY[d2Ea3k[40Z,j@4b81RLae@Lm2"XISEhLMe1R6B)%11mAUUpACT8k
+[&+F0YK2h)R&@qZNAdBVdlm3q0K`dFXS-HjV(Z40apkR(I@QQHYr'fir)JcfFDhi
+E'V5'Aj!!lhki8AfSGr-Pe%kMT4$h-R6+ZX!2QRm*,926bm3pf01IQYk2VUc9YBL
+MRlak0rmQ'V4fYS8iH-A9)@kRZLNk$h(`L6H'Z!I%!h!2qN#pjAh[rJ)"4YHbF3C
+2ACeZG6NKG"jJhf#'e+RTYp'U0"SbFDp5(jGk2b`rH(q-3kH81Xf#NqL`DDaq[EU
+fe1P+HPZr0mBaKq(9UHNVmM0i",#2VLh[Hm"h'pb`F8E2P6SeI36Xdmie!0HQ,ed
+rrD5D%r-[`#pp)rAq1*U)GTk)12LN9kHQVm)9p3GL($c%Ue26qq3I[a[MQ,f3!$T
+p5pd4[3iHKQiZGCU#4U$9Bi(hH$mel9HI0[K'h-1pIQVq@IX!hBCh`0qN6Tm8bm&
+Em!bq,rh8U2i02`9qk6qTdjqM9@Zd'Z,HUZiMIIm+Z)K@*`GqdF'ppcAHBTfBU5%
+1r9IH[3*ZS1NG'iIZ+A'2q1k24(k*VL&a9cPRi-eKk0qbYlbjMBEIK`2V-)HKhiP
+1*('0Tk(Yk6#(SGmPGjGmAd-ld'%13pmJYjDicm*&0&SaFEr1ZpAji4hhUQ-C$B'
+iGpJhZd2F,(NB1J"aCMBLmUS3plKkkLG#h$["!q(aM4H+LfBHMEKh`IrGqckYR[(
+*%2GZF9EHph*a&ai(c$+(+1qE3UpUjKTXR1'"lRdcl32$PBKl,rc%[HpCkVl-#J'
+rr*IhVD8(p+G$h2[8YH9pCm%4p5dacZ#1Hpm'iicH50a[dJrZIBqTVe0ri*Fj5RR
+I+p&H0E-*0Jlp5plh#E"!bq1)-h0)lRd2b*rXM0lr"`#3!edP!!!:
diff --git a/macos/osdep.h b/macos/osdep.h
new file mode 100644 (file)
index 0000000..3627016
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __MACOS_OSDEP_H
+#define __MACOS_OSDEP_H 1
+
+#ifndef MACOS
+#  define MACOS
+#endif
+
+
+#include <setjmp.h>
+#include <types.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unix.h>
+#include <unistd.h>
+#include <console.h>
+
+#include <Errors.h>
+#include <Files.h>
+
+#include "unixlike.h"
+#include "macglob.h"
+
+#define NO_MKTEMP           1
+#define PASSWD_FROM_STDIN   1
+#define NO_SYMLINK          1
+
+#define USE_ZIPMAIN         1
+
+#define USE_CASE_MAP        1  /* case_map is used to ignore case in comparisons */
+
+
+
+
+/*
+#define DEBUG_TIME
+ */
+
+#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))
+#  define USE_EF_UT_TIME
+#endif
+
+#undef  IZ_CHECK_TZ
+
+#ifndef ZP_NEED_MEMCOMPR
+#  define ZP_NEED_MEMCOMPR
+#endif
+
+
+#define EXDEV  18
+
+#define PATHCUT ':'
+
+
+/* file operations use "b" for binary */
+#define FOPR  "rb"
+#define FOPM  "r+b"
+#define FOPW  "wb"
+
+/*
+#define DEBUG
+*/
+
+/* These functions are defined as a macro instead of a function.
+so we have to undefine them for replacing (see printf.c)  */
+#undef getc
+#undef getchar
+#undef putchar
+
+
+
+void setfiletype(char *file, unsigned long Creator, unsigned long Type);
+
+char *GetZipVersionsInfo(void);
+char *GetZipVersionLocal(void);
+char *GetZipCopyright(void);
+
+void InitAllVars(void);
+
+void PrintFileInfo(void);
+
+
+
+int fprintf(FILE *file, const char *format, ...);
+int printf(const char *format, ...);
+void perror(const char *parm1);
+int macgetch(void);
+
+
+int MacOpen(const char *path,int oflag,...);
+FILE *MacFopen(const char *path,const char *mode);
+#define fopen(path, mode)   MacFopen(path, mode)
+#define open(path, oflag)   MacOpen(path, oflag)
+
+
+char *GetComment(char *filename);
+int readlink(char *path, char *buf, int size);
+
+void PrintStatProgress(char *msg);
+void InformProgress(const long progressMax, const long progressSoFar );
+void ShowCounter(Boolean reset);
+void leftStatusString(char *status);
+
+
+
+
+#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \
+                     procname(n, 1))
+
+#endif   /* __MACOS_OSDEP_H */
diff --git a/macos/readme.1st b/macos/readme.1st
new file mode 100644 (file)
index 0000000..012d512
--- /dev/null
@@ -0,0 +1,12 @@
+Before you start:
+
+Extract "*.hqx" and "source:*.hqx" first and read the Readme.txt.
+
+The resource file and the compiler project files are in BinHex form because
+they contain Macintosh resource forks and as such can not be simply
+stored a normal file on a non-Macintosh system.  BinHex form is the
+traditional way for transferring such files via non-Macintosh systems.
+It's also the safest since it uses only printable characters.  The ".hqx"
+files must be converted with StuffitExpander or BinHex 4.0 (or equivalent)
+on a Macintosh system before using them.
+
diff --git a/macos/source/VolWarn.h b/macos/source/VolWarn.h
new file mode 100644 (file)
index 0000000..2d921eb
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/*
+
+This is an Important note  about pathnames
+
+*/
+
+static char DuplicVolumeNote[] = {
+    "\rIMPORTANT NOTE:" \
+    "\r" \
+    "\r This port has one weak point: It is based on pathnames !! " \
+    "\r Because it's a port !! Unlike MacOS: As far as I know all other "\
+    "\r Operatingsystems  (eg.: Unix, DOS, OS/2, ...) are based on pathnames" \
+    "\r " \
+    /* a short quote from "Inside Macintintosh, Files"; slightly modified by me */
+    "\r On a Mac: Files and directories located in the same directory " \
+    "\r must all have unique names. However, there is no requirement " \
+    "\r that volumes have unique names. It is perfectly acceptable for two mounted" \
+    "\r volumes to have the same name. This is one reason why a application should " \
+    "\r use volume reference numbers rather than volume names to specify volumes," \
+    "\r but for this Zip-Port I can't use reference numbers. " \
+    "\r " \
+    /* end quote */
+    "\r" \
+    "\r From the developers point of view:"\
+    "\r The use of pathnames, however, is highly discouraged. If the user changes"\
+    "\r names or moves things around, they are worthless." \
+    "\r Full pathnames are particularly unreliable as a means of identifying files," \
+    "\r directories or volumes within your application," \
+    "\r for two primary reasons:" \
+    "\r" \
+    "\r*  The user can change the name of any element in the path at" \
+    "\r   virtually any time." \
+    "\r*  Volume names on the Macintosh are *not* unique. Multiple" \
+    "\r   mounted volumes can have the same name. For this reason, the use of" \
+    "\r   a full pathname to identify a specific volume may not produce the" \
+    "\r   results you expect. If more than one volume has the same name and" \
+    "\r   a full pathname is used, the File Manager currently uses the first" \
+    "\r   mounted volume it finds with a matching name in the volume queue." \
+    "\r" \
+    "\r" \
+    "\r The main reason is that an attempt to implement support exact saving of" \
+    "\r the MacOS specific internal file-structures would require a throughout" \
+    "\r rewrite of major parts of shared code, probably sacrifying compatibility" \
+    "\r with other systems." \
+    "\r I have no solution at the moment. The port will just warn you if you try" \
+    "\r zip from / to a volume which has a duplicate name." \
+    "\r MacZip has problems to find the archives and files." \
+    "\r" \
+    "\r" \
+    "\r ... and the moral of this story:" \
+    "\r" \
+    "\r Don't mount multiple volumes with the same " \
+    "\r name while zip/unzip is running" \
+    "\r and "\
+    "\r My (Big) recommendation: Name all your volumes with a unique name "\
+    "\r (e.g: add a space character to the name) and" \
+    "\r MacZip will run without any problem." \
+    "\r" \
+    "\r" \
+    "\r Dirk Haase" \
+    };
diff --git a/macos/source/charmap.h b/macos/source/charmap.h
new file mode 100644 (file)
index 0000000..70f041d
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __macos_charmap_h
+#define __macos_charmap_h
+
+/*
+
+Conversion table from MacOS Roman to
+"Western Europe & America" Windows codepage 1252
+
+     Notes on Mac OS Roman:
+     ----------------------
+
+       Mac OS Roman character set is used for at least the following Mac OS
+       localizations: U.S., British, Canadian French, French, Swiss
+       French, German, Swiss German, Italian, Swiss Italian, Dutch,
+       Swedish, Norwegian, Danish, Finnish, Spanish, Catalan,
+       Portuguese, Brazilian, and the default International system.
+
+       Not every char of the charset MacRoman has their equivalent
+       in Windows CodePage1252.
+       To make the mapping in most cases possible, I choosed
+       most similar chars or at least the BULLET. Chars that
+       do not have a direct match are marked with '***'
+
+       The Windows codepage 1252 contains the ISO 8859-1 "Latin 1" codepage,
+       with some additional printable characters in the range (0x80 - 0x9F),
+       that is reserved to control codes in the ISO 8859-1 character table.
+
+In all Mac OS encodings, character codes 0x00-0x7F are identical to ASCII
+
+*/
+
+
+
+ZCONST unsigned char MacRoman_to_WinCP1252[128] = {
+/*  Win CP1252          UniCode  UniCode Names       */
+    0xC4    ,       /*  0x00C4  #LATIN CAPITAL LETTER A WITH DIAERESIS      */
+    0xC5    ,       /*  0x00C5  #LATIN CAPITAL LETTER A WITH RING ABOVE     */
+    0xC7    ,       /*  0x00C7  #LATIN CAPITAL LETTER C WITH CEDILLA        */
+    0xC9    ,       /*  0x00C9  #LATIN CAPITAL LETTER E WITH ACUTE      */
+    0xD1    ,       /*  0x00D1  #LATIN CAPITAL LETTER N WITH TILDE      */
+    0xD6    ,       /*  0x00D6  #LATIN CAPITAL LETTER O WITH DIAERESIS      */
+    0xDC    ,       /*  0x00DC  #LATIN CAPITAL LETTER U WITH DIAERESIS      */
+    0xE1    ,       /*  0x00E1  #LATIN SMALL LETTER A WITH ACUTE        */
+    0xE0    ,       /*  0x00E0  #LATIN SMALL LETTER A WITH GRAVE        */
+    0xE2    ,       /*  0x00E2  #LATIN SMALL LETTER A WITH CIRCUMFLEX       */
+    0xE4    ,       /*  0x00E4  #LATIN SMALL LETTER A WITH DIAERESIS        */
+    0xE3    ,       /*  0x00E3  #LATIN SMALL LETTER A WITH TILDE        */
+    0xE5    ,       /*  0x00E5  #LATIN SMALL LETTER A WITH RING ABOVE       */
+    0xE7    ,       /*  0x00E7  #LATIN SMALL LETTER C WITH CEDILLA      */
+    0xE9    ,       /*  0x00E9  #LATIN SMALL LETTER E WITH ACUTE        */
+    0xE8    ,       /*  0x00E8  #LATIN SMALL LETTER E WITH GRAVE        */
+    0xEA    ,       /*  0x00EA  #LATIN SMALL LETTER E WITH CIRCUMFLEX       */
+    0xEB    ,       /*  0x00EB  #LATIN SMALL LETTER E WITH DIAERESIS        */
+    0xED    ,       /*  0x00ED  #LATIN SMALL LETTER I WITH ACUTE        */
+    0xEC    ,       /*  0x00EC  #LATIN SMALL LETTER I WITH GRAVE        */
+    0xEE    ,       /*  0x00EE  #LATIN SMALL LETTER I WITH CIRCUMFLEX       */
+    0xEF    ,       /*  0x00EF  #LATIN SMALL LETTER I WITH DIAERESIS        */
+    0xF1    ,       /*  0x00F1  #LATIN SMALL LETTER N WITH TILDE        */
+    0xF3    ,       /*  0x00F3  #LATIN SMALL LETTER O WITH ACUTE        */
+    0xF2    ,       /*  0x00F2  #LATIN SMALL LETTER O WITH GRAVE        */
+    0xF4    ,       /*  0x00F4  #LATIN SMALL LETTER O WITH CIRCUMFLEX       */
+    0xF6    ,       /*  0x00F6  #LATIN SMALL LETTER O WITH DIAERESIS        */
+    0xF5    ,       /*  0x00F5  #LATIN SMALL LETTER O WITH TILDE        */
+    0xFA    ,       /*  0x00FA  #LATIN SMALL LETTER U WITH ACUTE        */
+    0xF9    ,       /*  0x00F9  #LATIN SMALL LETTER U WITH GRAVE        */
+    0xFB    ,       /*  0x00FB  #LATIN SMALL LETTER U WITH CIRCUMFLEX       */
+    0xFC    ,       /*  0x00FC  #LATIN SMALL LETTER U WITH DIAERESIS        */
+    0x86    ,       /*  0x2020  #DAGGER     */
+    0xB0    ,       /*  0x00B0  #DEGREE SIGN        */
+    0xA2    ,       /*  0x00A2  #CENT SIGN      */
+    0xA3    ,       /*  0x00A3  #POUND SIGN     */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x95    ,       /*  0x2022  #BULLET     */
+    0xB6    ,       /*  0x00B6  #PILCROW SIGN       */
+    0xDF    ,       /*  0x00DF  #LATIN SMALL LETTER SHARP S     */
+    0xAE    ,       /*  0x00AE  #REGISTERED SIGN        */
+    0xA9    ,       /*  0x00A9  #COPYRIGHT SIGN     */
+    0x99    ,       /*  0x2122  #TRADE MARK SIGN        */
+    0xB4    ,       /*  0x00B4  #ACUTE ACCENT       */
+    0xA8    ,       /*  0x00A8  #DIAERESIS      */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0xC6    ,       /*  0x00C6  #LATIN CAPITAL LETTER AE        */
+    0xD8    ,       /*  0x00D8  #LATIN CAPITAL LETTER O WITH STROKE     */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0xB1    ,       /*  0x00B1  #PLUS-MINUS SIGN        */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0xA5    ,       /*  0x00A5  #YEN SIGN       */
+    0xB5    ,       /*  0x00B5  #MICRO SIGN     */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0xAA    ,       /*  0x00AA  #FEMININE ORDINAL INDICATOR     */
+    0xBA    ,       /*  0x00BA  #MASCULINE ORDINAL INDICATOR        */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0xE6    ,       /*  0x00E6  #LATIN SMALL LETTER AE      */
+    0xF8    ,       /*  0x00F8  #LATIN SMALL LETTER O WITH STROKE       */
+    0xBF    ,       /*  0x00BF  #INVERTED QUESTION MARK     */
+    0xA1    ,       /*  0x00A1  #INVERTED EXCLAMATION MARK      */
+    0xAC    ,       /*  0x00AC  #NOT SIGN       */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x83    ,       /*  0x0192  #LATIN SMALL LETTER F WITH HOOK     */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0xAB    ,       /*  0x00AB  #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK      */
+    0xBB    ,       /*  0x00BB  #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK     */
+    0x85    ,       /*  0x2026  #HORIZONTAL ELLIPSIS        */
+    0xA0    ,       /*  0x00A0  #NO-BREAK SPACE     */
+    0xC0    ,       /*  0x00C0  #LATIN CAPITAL LETTER A WITH GRAVE      */
+    0xC3    ,       /*  0x00C3  #LATIN CAPITAL LETTER A WITH TILDE      */
+    0xD5    ,       /*  0x00D5  #LATIN CAPITAL LETTER O WITH TILDE      */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x96    ,       /*  0x2013  #EN DASH        */
+    0x97    ,       /*  0x2014  #EM DASH        */
+    0x93    ,       /*  0x201C  #LEFT DOUBLE QUOTATION MARK     */
+    0x94    ,       /*  0x201D  #RIGHT DOUBLE QUOTATION MARK        */
+    0x91    ,       /*  0x2018  #LEFT SINGLE QUOTATION MARK     */
+    0x92    ,       /*  0x2019  #RIGHT SINGLE QUOTATION MARK        */
+    0xF7    ,       /*  0x00F7  #DIVISION SIGN      */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0xFF    ,       /*  0x00FF  #LATIN SMALL LETTER Y WITH DIAERESIS        */
+    0x9F    ,       /*  0x0178  #LATIN CAPITAL LETTER Y WITH DIAERESIS      */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0xA4    ,       /*  0x00A4  #CURRENCY SIGN      */
+    0x8B    ,       /*  0x2039  #SINGLE LEFT-POINTING ANGLE QUOTATION MARK      */
+    0x9B    ,       /*  0x203A  #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK     */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x87    ,       /*  0x2021  #DOUBLE DAGGER      */
+    0xB7    ,       /*  0x00B7  #MIDDLE DOT     */
+    0x82    ,       /*  0x201A  #SINGLE LOW-9 QUOTATION MARK        */
+    0x84    ,       /*  0x201E  #DOUBLE LOW-9 QUOTATION MARK        */
+    0x89    ,       /*  0x2030  #PER MILLE SIGN     */
+    0xC2    ,       /*  0x00C2  #LATIN CAPITAL LETTER A WITH CIRCUMFLEX     */
+    0xCA    ,       /*  0x00CA  #LATIN CAPITAL LETTER E WITH CIRCUMFLEX     */
+    0xC1    ,       /*  0x00C1  #LATIN CAPITAL LETTER A WITH ACUTE      */
+    0xCB    ,       /*  0x00CB  #LATIN CAPITAL LETTER E WITH DIAERESIS      */
+    0xC8    ,       /*  0x00C8  #LATIN CAPITAL LETTER E WITH GRAVE      */
+    0xCD    ,       /*  0x00CD  #LATIN CAPITAL LETTER I WITH ACUTE      */
+    0xCE    ,       /*  0x00CE  #LATIN CAPITAL LETTER I WITH CIRCUMFLEX     */
+    0xCF    ,       /*  0x00CF  #LATIN CAPITAL LETTER I WITH DIAERESIS      */
+    0xCC    ,       /*  0x00CC  #LATIN CAPITAL LETTER I WITH GRAVE      */
+    0xD3    ,       /*  0x00D3  #LATIN CAPITAL LETTER O WITH ACUTE      */
+    0xD4    ,       /*  0x00D4  #LATIN CAPITAL LETTER O WITH CIRCUMFLEX     */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0xD2    ,       /*  0x00D2  #LATIN CAPITAL LETTER O WITH GRAVE      */
+    0xDA    ,       /*  0x00DA  #LATIN CAPITAL LETTER U WITH ACUTE      */
+    0xDB    ,       /*  0x00DB  #LATIN CAPITAL LETTER U WITH CIRCUMFLEX     */
+    0xD9    ,       /*  0x00D9  #LATIN CAPITAL LETTER U WITH GRAVE      */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x88    ,       /*  0x02C6  #MODIFIER LETTER CIRCUMFLEX ACCENT      */
+    0x98    ,       /*  0x02DC  #SMALL TILDE        */
+    0xAF    ,       /*  0x00AF  #MACRON     */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0xB8    ,       /*  0x00B8  #CEDILLA        */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x95    ,       /*  0x2022  # ***  BULLET       */
+    0x95            /*  0x2022  # ***  BULLET       */
+ };
+
+
+
+ZCONST unsigned char WinCP1252_to_MacRoman[128] = {
+/*  Mac Roman           UniCode  UniCode Names       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xE2    ,       /*  0x201A  # SINGLE LOW-9 QUOTATION MARK       */
+    0xC4    ,       /*  0x0192  # LATIN SMALL LETTER F WITH HOOK        */
+    0xE3    ,       /*  0x201E  # DOUBLE LOW-9 QUOTATION MARK       */
+    0xC9    ,       /*  0x2026  # HORIZONTAL ELLIPSIS       */
+    0xA0    ,       /*  0x2020  # DAGGER        */
+    0xE0    ,       /*  0x2021  # DOUBLE DAGGER     */
+    0xF6    ,       /*  0x02C6  # MODIFIER LETTER CIRCUMFLEX ACCENT     */
+    0xE4    ,       /*  0x2030  # PER MILLE SIGN        */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xDC    ,       /*  0x2039  # SINGLE LEFT-POINTING ANGLE QUOTATION MARK     */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xD4    ,       /*  0x2018  # LEFT SINGLE QUOTATION MARK        */
+    0xD5    ,       /*  0x2019  # RIGHT SINGLE QUOTATION MARK       */
+    0xD2    ,       /*  0x201C  # LEFT DOUBLE QUOTATION MARK        */
+    0xD3    ,       /*  0x201D  # RIGHT DOUBLE QUOTATION MARK       */
+    0xA5    ,       /*  0x2022  # BULLET        */
+    0xD0    ,       /*  0x2013  # EN DASH       */
+    0xD1    ,       /*  0x2014  # EM DASH       */
+    0xF7    ,       /*  0x02DC  # SMALL TILDE       */
+    0xAA    ,       /*  0x2122  # TRADE MARK SIGN       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xDD    ,       /*  0x203A  # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK        */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xD9    ,       /*  0x0178  # LATIN CAPITAL LETTER Y WITH DIAERESIS     */
+    0xCA    ,       /*  0x00A0  # NO-BREAK SPACE        */
+    0xC1    ,       /*  0x00A1  # INVERTED EXCLAMATION MARK     */
+    0xA2    ,       /*  0x00A2  # CENT SIGN     */
+    0xA3    ,       /*  0x00A3  # POUND SIGN        */
+    0xDB    ,       /*  0x00A4  # CURRENCY SIGN     */
+    0xB4    ,       /*  0x00A5  # YEN SIGN      */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xAC    ,       /*  0x00A8  # DIAERESIS     */
+    0xA9    ,       /*  0x00A9  # COPYRIGHT SIGN        */
+    0xBB    ,       /*  0x00AA  # FEMININE ORDINAL INDICATOR        */
+    0xC7    ,       /*  0x00AB  # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK     */
+    0xC2    ,       /*  0x00AC  # NOT SIGN      */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA8    ,       /*  0x00AE  # REGISTERED SIGN       */
+    0xF8    ,       /*  0x00AF  # MACRON        */
+    0xA1    ,       /*  0x00B0  # DEGREE SIGN       */
+    0xB1    ,       /*  0x00B1  # PLUS-MINUS SIGN       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xAB    ,       /*  0x00B4  # ACUTE ACCENT      */
+    0xB5    ,       /*  0x00B5  # MICRO SIGN        */
+    0xA6    ,       /*  0x00B6  # PILCROW SIGN      */
+    0xE1    ,       /*  0x00B7  # MIDDLE DOT        */
+    0xFC    ,       /*  0x00B8  # CEDILLA       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xBC    ,       /*  0x00BA  # MASCULINE ORDINAL INDICATOR       */
+    0xC8    ,       /*  0x00BB  # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK        */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xC0    ,       /*  0x00BF  # INVERTED QUESTION MARK        */
+    0xCB    ,       /*  0x00C0  # LATIN CAPITAL LETTER A WITH GRAVE     */
+    0xE7    ,       /*  0x00C1  # LATIN CAPITAL LETTER A WITH ACUTE     */
+    0xE5    ,       /*  0x00C2  # LATIN CAPITAL LETTER A WITH CIRCUMFLEX        */
+    0xCC    ,       /*  0x00C3  # LATIN CAPITAL LETTER A WITH TILDE     */
+    0x80    ,       /*  0x00C4  # LATIN CAPITAL LETTER A WITH DIAERESIS     */
+    0x81    ,       /*  0x00C5  # LATIN CAPITAL LETTER A WITH RING ABOVE        */
+    0xAE    ,       /*  0x00C6  # LATIN CAPITAL LETTER AE       */
+    0x82    ,       /*  0x00C7  # LATIN CAPITAL LETTER C WITH CEDILLA       */
+    0xE9    ,       /*  0x00C8  # LATIN CAPITAL LETTER E WITH GRAVE     */
+    0x83    ,       /*  0x00C9  # LATIN CAPITAL LETTER E WITH ACUTE     */
+    0xE6    ,       /*  0x00CA  # LATIN CAPITAL LETTER E WITH CIRCUMFLEX        */
+    0xE8    ,       /*  0x00CB  # LATIN CAPITAL LETTER E WITH DIAERESIS     */
+    0xED    ,       /*  0x00CC  # LATIN CAPITAL LETTER I WITH GRAVE     */
+    0xEA    ,       /*  0x00CD  # LATIN CAPITAL LETTER I WITH ACUTE     */
+    0xEB    ,       /*  0x00CE  # LATIN CAPITAL LETTER I WITH CIRCUMFLEX        */
+    0xEC    ,       /*  0x00CF  # LATIN CAPITAL LETTER I WITH DIAERESIS     */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0x84    ,       /*  0x00D1  # LATIN CAPITAL LETTER N WITH TILDE     */
+    0xF1    ,       /*  0x00D2  # LATIN CAPITAL LETTER O WITH GRAVE     */
+    0xEE    ,       /*  0x00D3  # LATIN CAPITAL LETTER O WITH ACUTE     */
+    0xEF    ,       /*  0x00D4  # LATIN CAPITAL LETTER O WITH CIRCUMFLEX        */
+    0xCD    ,       /*  0x00D5  # LATIN CAPITAL LETTER O WITH TILDE     */
+    0x85    ,       /*  0x00D6  # LATIN CAPITAL LETTER O WITH DIAERESIS     */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xAF    ,       /*  0x00D8  # LATIN CAPITAL LETTER O WITH STROKE        */
+    0xF4    ,       /*  0x00D9  # LATIN CAPITAL LETTER U WITH GRAVE     */
+    0xF2    ,       /*  0x00DA  # LATIN CAPITAL LETTER U WITH ACUTE     */
+    0xF3    ,       /*  0x00DB  # LATIN CAPITAL LETTER U WITH CIRCUMFLEX        */
+    0x86    ,       /*  0x00DC  # LATIN CAPITAL LETTER U WITH DIAERESIS     */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA7    ,       /*  0x00DF  # LATIN SMALL LETTER SHARP S        */
+    0x88    ,       /*  0x00E0  # LATIN SMALL LETTER A WITH GRAVE       */
+    0x87    ,       /*  0x00E1  # LATIN SMALL LETTER A WITH ACUTE       */
+    0x89    ,       /*  0x00E2  # LATIN SMALL LETTER A WITH CIRCUMFLEX      */
+    0x8B    ,       /*  0x00E3  # LATIN SMALL LETTER A WITH TILDE       */
+    0x8A    ,       /*  0x00E4  # LATIN SMALL LETTER A WITH DIAERESIS       */
+    0x8C    ,       /*  0x00E5  # LATIN SMALL LETTER A WITH RING ABOVE      */
+    0xBE    ,       /*  0x00E6  # LATIN SMALL LETTER AE     */
+    0x8D    ,       /*  0x00E7  # LATIN SMALL LETTER C WITH CEDILLA     */
+    0x8F    ,       /*  0x00E8  # LATIN SMALL LETTER E WITH GRAVE       */
+    0x8E    ,       /*  0x00E9  # LATIN SMALL LETTER E WITH ACUTE       */
+    0x90    ,       /*  0x00EA  # LATIN SMALL LETTER E WITH CIRCUMFLEX      */
+    0x91    ,       /*  0x00EB  # LATIN SMALL LETTER E WITH DIAERESIS       */
+    0x93    ,       /*  0x00EC  # LATIN SMALL LETTER I WITH GRAVE       */
+    0x92    ,       /*  0x00ED  # LATIN SMALL LETTER I WITH ACUTE       */
+    0x94    ,       /*  0x00EE  # LATIN SMALL LETTER I WITH CIRCUMFLEX      */
+    0x95    ,       /*  0x00EF  # LATIN SMALL LETTER I WITH DIAERESIS       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0x96    ,       /*  0x00F1  # LATIN SMALL LETTER N WITH TILDE       */
+    0x98    ,       /*  0x00F2  # LATIN SMALL LETTER O WITH GRAVE       */
+    0x97    ,       /*  0x00F3  # LATIN SMALL LETTER O WITH ACUTE       */
+    0x99    ,       /*  0x00F4  # LATIN SMALL LETTER O WITH CIRCUMFLEX      */
+    0x9B    ,       /*  0x00F5  # LATIN SMALL LETTER O WITH TILDE       */
+    0x9A    ,       /*  0x00F6  # LATIN SMALL LETTER O WITH DIAERESIS       */
+    0xD6    ,       /*  0x00F7  # DIVISION SIGN     */
+    0xBF    ,       /*  0x00F8  # LATIN SMALL LETTER O WITH STROKE      */
+    0x9D    ,       /*  0x00F9  # LATIN SMALL LETTER U WITH GRAVE       */
+    0x9C    ,       /*  0x00FA  # LATIN SMALL LETTER U WITH ACUTE       */
+    0x9E    ,       /*  0x00FB  # LATIN SMALL LETTER U WITH CIRCUMFLEX      */
+    0x9F    ,       /*  0x00FC  # LATIN SMALL LETTER U WITH DIAERESIS       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xA5    ,       /*  0x2022  # ***  BULLET       */
+    0xD8            /*  0x00FF  # LATIN SMALL LETTER Y WITH DIAERESIS       */
+ };
+
+
+/*
+
+The following characters has no equivalent
+to each other:
+
+MacCodes
+164 0xA4    0x00A7  # SECTION SIGN
+253 0xFD    0x02DD  # DOUBLE ACUTE ACCENT
+189 0xBD    0x03A9  # GREEK CAPITAL LETTER OMEGA
+185 0xB9    0x03C0  # GREEK SMALL LETTER PI
+255 0xFF    0x02C7  # CARON
+249 0xF9    0x02D8  # BREVE
+250 0xFA    0x02D9  # DOT ABOVE
+251 0xFB    0x02DA  # RING ABOVE
+254 0xFE    0x02DB  # OGONEK
+218 0xDA    0x2044  # FRACTION SLASH
+182 0xB6    0x2202  # PARTIAL DIFFERENTIAL
+198 0xC6    0x2206  # INCREMENT
+184 0xB8    0x220F  # N-ARY PRODUCT
+183 0xB7    0x2211  # N-ARY SUMMATION
+195 0xC3    0x221A  # SQUARE ROOT
+176 0xB0    0x221E  # INFINITY
+186 0xBA    0x222B  # INTEGRAL
+197 0xC5    0x2248  # ALMOST EQUAL TO
+173 0xAD    0x2260  # NOT EQUAL TO
+178 0xB2    0x2264  # LESS-THAN OR EQUAL TO
+179 0xB3    0x2265  # GREATER-THAN OR EQUAL TO
+215 0xD7    0x25CA  # LOZENGE
+240 0xF0    0xF8FF  # Apple logo
+222 0xDE    0xFB01  # LATIN SMALL LIGATURE FI
+223 0xDF    0xFB02  # LATIN SMALL LIGATURE FL
+245 0xF5    0x0131  # LATIN SMALL LETTER DOTLESS I
+206 0xCE    0x0152  # LATIN CAPITAL LIGATURE OE
+207 0xCF    0x0153  # LATIN SMALL LIGATURE OE
+
+WinCodes
+129 0x81            #UNDEFINED
+141 0x8D            #UNDEFINED
+143 0x8F            #UNDEFINED
+144 0x90            #UNDEFINED
+157 0x9D            #UNDEFINED
+167 0xA7    0x00A7  #SECTION SIGN
+173 0xAD    0x00AD  #SOFT HYPHEN
+178 0xB2    0x00B2  #SUPERSCRIPT TWO
+179 0xB3    0x00B3  #SUPERSCRIPT THREE
+185 0xB9    0x00B9  #SUPERSCRIPT ONE
+188 0xBC    0x00BC  #VULGAR FRACTION ONE QUARTER
+189 0xBD    0x00BD  #VULGAR FRACTION ONE HALF
+190 0xBE    0x00BE  #VULGAR FRACTION THREE QUARTERS
+208 0xD0    0x00D0  #LATIN CAPITAL LETTER ETH
+215 0xD7    0x00D7  #MULTIPLICATION SIGN
+221 0xDD    0x00DD  #LATIN CAPITAL LETTER Y WITH ACUTE
+222 0xDE    0x00DE  #LATIN CAPITAL LETTER THORN
+240 0xF0    0x00F0  #LATIN SMALL LETTER ETH
+253 0xFD    0x00FD  #LATIN SMALL LETTER Y WITH ACUTE
+254 0xFE    0x00FE  #LATIN SMALL LETTER THORN
+140 0x8C    0x0152  #LATIN CAPITAL LIGATURE OE
+156 0x9C    0x0153  #LATIN SMALL LIGATURE OE
+138 0x8A    0x0160  #LATIN CAPITAL LETTER S WITH CARON
+154 0x9A    0x0161  #LATIN SMALL LETTER S WITH CARON
+142 0x8E    0x017D  #LATIN CAPITAL LETTER Z WITH CARON
+158 0x9E    0x017E  #LATIN SMALL LETTER Z WITH CARON
+128 0x80    0x20AC  #EURO SIGN
+166 0xA6    0x00A6  #BROKEN BAR
+
+
+*/
+
+
+
+
+#endif /* !__macos_charmap_h */
diff --git a/macos/source/extrafld.c b/macos/source/extrafld.c
new file mode 100644 (file)
index 0000000..83e00a3
--- /dev/null
@@ -0,0 +1,920 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+  extrafld.c
+
+  contains functions to build extra-fields.
+
+  ---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/*  Includes                                                                 */
+/*****************************************************************************/
+
+#include <sound.h>
+#include "zip.h"
+#include "unixlike.h"
+#include "helpers.h"
+#include "pathname.h"
+
+
+/*****************************************************************************/
+/*  Macros, typedefs                                                         */
+/*****************************************************************************/
+
+/* ---------------------------------------------------------------------- */
+/* Add a 'MAC3' extra field to the zlist data pointed to by z.            */
+/* This is the (new) Info-zip extra block for Macintosh */
+#define EB_MAC3_HLEN          14    /* fixed length part of MAC3's header */
+#define EB_L_MAC3_FINFO_LEN   52    /* fixed part of MAC3 compressible data */
+
+#define EB_MAX_OF_VARDATA   1300    /* max possible datasize */
+
+#define EB_L_MAC3_SIZE    (EB_HEADSIZE + EB_MAC3_HLEN)
+#define EB_C_MAC3_SIZE    (EB_HEADSIZE + EB_MAC3_HLEN)
+
+#define MEMCOMPRESS_HEADER      6   /* ush compression type, ulg CRC */
+#define DEFLAT_WORSTCASE_ADD    5   /* byte blocktype, 2 * ush blocklength */
+#define MEMCOMPRESS_OVERHEAD    (MEMCOMPRESS_HEADER + DEFLAT_WORSTCASE_ADD)
+
+#define EXTRAFLD_MAX    (unsigned)0xFFFF
+
+#define EB_M3_FL_COMPRESS   0x00
+#define EB_M3_FL_DATFRK     0x01    /* data is data-fork */
+#define EB_M3_FL_NOCHANGE   0x02    /* filename will be not changed */
+#define EB_M3_FL_UNCMPR     0x04    /* data is 'natural' (not compressed) */
+#define EB_M3_FL_TIME64     0x08    /* time is coded in 64 bit */
+#define EB_M3_FL_NOUTC      0x10    /* only 'local' time-stamps are stored */
+
+
+#define EB_L_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(2))
+#define EB_C_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(1))
+
+/* disable compressing of extra field
+#define MAC_EXTRAFLD_UNCMPR       */
+
+/* ---------------------------------------------------------------------- */
+/* Add a 'JLEE' extra field to the zlist data pointed to by z.            */
+/* This is the (old) Info-zip resource-fork extra block for Macintosh
+(last Revision 1996-09-22) Layout made by Johnny Lee, Code made by me :-)  */
+#define EB_L_JLEE_LEN  40       /* fixed length of JLEE's header */
+#define EB_C_JLEE_LEN  40       /* fixed length of JLEE's header */
+
+#define EB_L_JLEE_SIZE    (EB_HEADSIZE + EB_L_JLEE_LEN)
+#define EB_C_JLEE_SIZE    (EB_HEADSIZE + EB_C_JLEE_LEN)
+
+
+
+/*****************************************************************************/
+/*  Global Vars                                                              */
+/*****************************************************************************/
+
+extern MacZipGlobals    MacZip;
+extern unsigned long count_of_Zippedfiles;
+
+
+
+/*****************************************************************************/
+/*  Prototypes                                                               */
+/*****************************************************************************/
+
+static int add_UT_ef(struct zlist far *z, iztimes *z_utim);
+static int add_JLEE_ef(struct zlist far *z);  /* old mac extra field */
+static int add_MAC3_ef(struct zlist far *z);  /* new mac extra field */
+
+static void make_extrafield_JLEE(char *l_ef);
+static unsigned make_extrafield_MAC3(char *ef);
+static char *make_EF_Head_MAC3(char *ef, unsigned compsize, ulg attrsize,
+                               unsigned flag);
+
+static void print_extra_info(void);
+void UserStop(void);
+
+
+/*****************************************************************************/
+/*  Functions                                                                */
+/*****************************************************************************/
+
+
+/*
+* Set the extra-field's for each compressed file
+*/
+int set_extra_field(struct zlist far *z, iztimes *z_utim)
+  /* store full data in local header but just modification time stamp info
+     in central header */
+{
+    int retval;
+
+    Assert_it(z, "set_extra_field","")
+    Assert_it(z_utim, "set_extra_field","")
+
+    z_utim = z_utim;
+
+    /* Check to make sure z is valid. */
+    if( z == NULL ) {
+        return ZE_LOGIC;
+    }
+
+    /* Resource forks are always binary */
+    if (MacZip.CurrentFork == ResourceFork) z->att = BINARY;
+
+    if (noisy)
+        {
+        count_of_Zippedfiles++;
+        InformProgress(MacZip.RawCountOfItems, count_of_Zippedfiles );
+        }
+
+    /*
+    PrintFileInfo();
+    */
+    switch (MacZip.MacZipMode)
+        {
+        case JohnnyLee_EF:
+            {
+            retval = add_JLEE_ef( z );
+            if (retval != ZE_OK) return retval;
+            break;
+            }
+        case NewZipMode_EF:
+            {     /*  */
+#ifdef USE_EF_UT_TIME
+            retval = add_UT_ef(z, z_utim);
+            if (retval != ZE_OK) return retval;
+#endif
+
+            retval = add_MAC3_ef( z );
+            if (retval != ZE_OK) return retval;
+            break;
+            }
+        default:
+            {
+            printerr("Unknown Extrafieldmode", -1, -1, __LINE__, __FILE__, "");
+            return ZE_LOGIC;  /* function should never reach this point */
+            }
+    }
+
+    /* MacStat information is now outdated and
+       must be refreshed for the next file */
+    MacZip.isMacStatValid = false;
+
+    return ZE_OK;
+}
+
+
+
+
+#ifdef USE_EF_UT_TIME
+/*
+* Build and add the Unix time extra-field. This extra field
+* will be included be default. Johnny Lee's implementation does
+* not use this kind of extra-field.
+* All datas are in Intel (=little-endian) format
+
+ Extra field info:
+   - 'UT' - UNIX time extra field
+
+   This is done the same way ../unix/unix.c stores the 'UT'/'Ux' fields
+   (full data in local header, only modification time in central header),
+   with the 'M3' field added to the end and the size of the 'M3' field
+   in the central header.
+ */
+
+static int add_UT_ef(struct zlist far *z, iztimes *z_utim)
+{
+    char        *l_ef = NULL;
+    char        *c_ef = NULL;
+
+    Assert_it(z, "add_UT_ef","")
+
+#ifdef IZ_CHECK_TZ
+    if (!zp_tz_is_valid)
+        return ZE_OK;           /* skip silently if no valid TZ info */
+#endif
+
+    /* We can't work if there's no entry to work on. */
+    if( z == NULL ) {
+        return ZE_LOGIC;
+    }
+
+    /* Check to make sure we've got enough room in the extra fields. */
+    if( z->ext + EB_L_UT_SIZE > EXTRAFLD_MAX ||
+        z->cext + EB_C_UT_SIZE > EXTRAFLD_MAX ) {
+        return ZE_MEM;
+    }
+
+    /* Allocate memory for the local and central extra fields. */
+    if( z->extra && z->ext != 0 ) {
+        l_ef = (char *)realloc( z->extra, z->ext + EB_L_UT_SIZE );
+    } else {
+        l_ef = (char *)malloc( EB_L_UT_SIZE );
+        z->ext = 0;
+    }
+    if( l_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->extra = l_ef;
+    l_ef += z->ext;
+
+    if( z->cextra && z->cext != 0 ) {
+        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_UT_SIZE );
+    } else {
+        c_ef = (char *)malloc( EB_C_UT_SIZE );
+        z->cext = 0;
+    }
+    if( c_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->cextra = c_ef;
+    c_ef += z->cext;
+
+    /* Now add the local version of the field. */
+    *l_ef++ = 'U';
+    *l_ef++ = 'T';
+    *l_ef++ = (char)(EB_UT_LEN(2)); /* length of data in local EF */
+    *l_ef++ = (char)0;
+    *l_ef++ = (char)(EB_UT_FL_MTIME | EB_UT_FL_CTIME);
+    *l_ef++ = (char)(z_utim->mtime);
+    *l_ef++ = (char)(z_utim->mtime >> 8);
+    *l_ef++ = (char)(z_utim->mtime >> 16);
+    *l_ef++ = (char)(z_utim->mtime >> 24);
+    *l_ef++ = (char)(z_utim->ctime);
+    *l_ef++ = (char)(z_utim->ctime >> 8);
+    *l_ef++ = (char)(z_utim->ctime >> 16);
+    *l_ef++ = (char)(z_utim->ctime >> 24);
+
+    z->ext += EB_L_UT_SIZE;
+
+    /* Now add the central version. */
+    memcpy(c_ef, l_ef-EB_L_UT_SIZE, EB_C_UT_SIZE);
+    c_ef[EB_LEN] = (char)(EB_UT_LEN(1)); /* length of data in central EF */
+
+    z->cext += EB_C_UT_SIZE;
+
+    return ZE_OK;
+}
+#endif /* USE_EF_UT_TIME */
+
+
+/*
+* Build and add the old 'Johnny Lee' Mac extra field
+* All native datas are in Motorola (=big-endian) format
+*/
+
+static int add_JLEE_ef( struct zlist far *z )
+{
+    char *l_ef       = NULL;
+    char *c_ef       = NULL;
+
+    Assert_it(z, "add_JLEE_ef","")
+
+    /* Check to make sure we've got enough room in the extra fields. */
+    if ( z->ext + EB_L_JLEE_SIZE > EXTRAFLD_MAX ||
+        z->cext + EB_C_JLEE_SIZE > EXTRAFLD_MAX ) {
+        return ZE_MEM;
+    }
+
+
+    /* Allocate memory for the local extra fields. */
+    if ( z->extra && z->ext != 0 ) {
+        l_ef = (char *)realloc( z->extra, z->ext + EB_L_JLEE_SIZE );
+    } else {
+        l_ef = (char *)malloc( EB_L_JLEE_SIZE );
+        z->ext = 0;
+    }
+    if ( l_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->extra = l_ef;
+    l_ef += z->ext;
+
+    /* Allocate memory for the  central extra fields. */
+    if ( z->cextra && z->cext != 0 ) {
+        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_JLEE_SIZE );
+    } else {
+        c_ef = (char *)malloc( EB_C_JLEE_SIZE );
+        z->cext = 0;
+    }
+    if ( c_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->cextra = c_ef;
+    c_ef += z->cext;
+
+
+    if ( verbose ) {
+        print_extra_info();
+    }
+
+
+    /**
+    **
+    **  Now add the local version of the field.
+    **/
+    make_extrafield_JLEE(l_ef);
+    z->ext += EB_L_JLEE_SIZE;
+
+
+    /**
+    **
+    **  Now add the central version of the field.
+    **  It's identical to the local header. I wonder why ??
+    *  the first two fields are in Intel little-endian format  */
+    make_extrafield_JLEE(c_ef);
+    z->cext += EB_C_JLEE_SIZE;
+
+    return ZE_OK;
+}
+
+
+
+/*
+* This is an implementation of Johnny Lee's extra field.
+* I never saw Johnny Lee's code. My code is based on the extra-field
+* definition mac (see latest appnote 1997-03-11)
+* and on some experiments with Johnny Lee's Zip-app version 1.0, 1992
+*
+* Unfortunately I cannot agree with his extra-field layout.
+*   - it wasted space
+*   - and holds not all mac-specific information
+*
+* I coded this extra-field only for testing purposes.
+* I don't want support this extra-field. Please use my implementation.
+*
+* This is old implementation of Johnny Lee's extra field.
+* All native datas are in Motorola (=big-endian) format
+*/
+
+static void make_extrafield_JLEE(char *ef)
+{
+
+    Assert_it(ef, "make_extrafield_JLEE","")
+
+    if (MacZip.isMacStatValid == false)
+        {
+        fprintf(stderr,"Internal Logic Error: [%d/%s] MacStat is out of sync !",
+                        __LINE__,__FILE__);
+        exit(-1);
+        }
+
+
+    /*  the first two fields are in Intel little-endian format  */
+    *ef++ = 0xC8;                             /* tag for this extra block */
+    *ef++ = 0x07;
+
+    *ef++ = (char)(EB_L_JLEE_LEN);            /* total data size this block */
+    *ef++ = (char)((EB_L_JLEE_LEN) >> 8);
+
+     /*  the following fields are in motorola big-endian format  */
+        *ef++ = 'J';                /* extra field signature:       4 Bytes */
+        *ef++ = 'L';                /* the old style extra field */
+        *ef++ = 'E';
+        *ef++ = 'E';
+
+                /* Start Macintosh Finder FInfo structure   16 Bytes overall */
+                                    /* Type:                        4 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 24);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 16);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType);
+
+                                    /* Creator:                     4 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 24);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 16);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator);
+
+                                     /* file Finder Flags:                2 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags);
+
+                                     /* Finders Icon position of a file*/
+                                     /* V/Y-Position:                2 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v);
+                                     /* H/X-Position:                2 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h);
+
+                               /* fdFldr Folder containing file    2 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFldr >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFldr);
+                /* End Macintosh Finder FInfo structure */
+
+
+                                                  /* Creation-time  4 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 24);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 16);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat);
+
+                                              /* Modification-time  4 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 24);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 16);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat);
+
+                                     /* info Bits                    4 Bytes */
+    *ef++ = 0x00;
+    *ef++ = 0x00;
+    *ef++ = 0x00;
+    if (MacZip.DataForkOnly)
+        {          /* don't convert filename for unzipping */
+                   /* 0x01 = data-fork; 0x00 = resource-fork */
+        *ef++ = (char) (MacZip.CurrentFork == DataFork) | 2;
+        }
+    else
+        {
+        *ef++ = (char) (MacZip.CurrentFork == DataFork);
+        }
+
+                                  /* file's location folder ID  4 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlParID >> 24);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlParID >> 16);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlParID >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlParID);
+                                                          /* ============  */
+                                                          /*     40 Bytes  */
+}
+
+
+
+/*
+* Build and add the new mac extra field
+* All native data are stored in Intel (=little-endian) format
+*/
+
+static int add_MAC3_ef( struct zlist far *z )
+{
+    char *l_ef        = NULL;
+    char *c_ef        = NULL;
+    char *attrbuff    = NULL;
+    off_t attrsize    = (EB_L_MAC3_FINFO_LEN + EB_MAX_OF_VARDATA);
+    char *compbuff    = NULL;
+    unsigned compsize = 0;
+    unsigned m3_compr;
+    Boolean compress_data = true;
+
+    Assert_it(z, "add_MAC3_ef","")
+
+    UserStop();  /* do event handling and let the user stop */
+
+    if( verbose ) {
+        print_extra_info();
+    }
+
+    /* allocate temporary buffer to collect the Mac extra field info */
+    attrbuff = (char *)malloc( (size_t)attrsize );
+    if( attrbuff == NULL ) {
+        return ZE_MEM;
+    }
+
+    /* fill the attribute buffer, to get its (uncompressed) size */
+    attrsize = make_extrafield_MAC3(attrbuff);
+
+    if (compress_data &&
+        ((compbuff = (char *)malloc((size_t)attrsize + MEMCOMPRESS_OVERHEAD))
+         != NULL))
+        {
+        /* Try compressing the data */
+        compsize = memcompress( compbuff,
+                                (size_t)attrsize + MEMCOMPRESS_OVERHEAD,
+                                attrbuff,
+                                (size_t)attrsize );
+#ifdef MAC_EXTRAFLD_UNCMPR
+        compsize = attrsize;
+#endif
+        }
+    else
+        {
+        compsize = attrsize;
+        }
+
+    if ((compsize) < attrsize) {
+        /* compression gained some space ... */
+        free(attrbuff);         /* no longer needed ... */
+        m3_compr = EB_M3_FL_COMPRESS;
+    } else {
+        /* compression does not help, store data in uncompressed mode */
+        if (compbuff != NULL) free(compbuff);
+        compbuff = attrbuff;
+        compsize = attrsize;
+        m3_compr = EB_M3_FL_UNCMPR;
+    }
+
+    /* Check to make sure we've got enough room in the extra fields. */
+    if( z->ext + (EB_L_MAC3_SIZE + compsize) > EXTRAFLD_MAX ||
+        z->cext + EB_C_MAC3_SIZE > EXTRAFLD_MAX ) {
+        if (compbuff != NULL) free(compbuff);
+        return ZE_MEM;
+    }
+
+    /* Allocate memory for the local extra fields. */
+    if( z->extra && z->ext != 0 ) {
+        l_ef = (char *)realloc( z->extra, z->ext +
+                                EB_L_MAC3_SIZE + compsize);
+    } else {
+        l_ef = (char *)malloc( EB_L_MAC3_SIZE + compsize);
+        z->ext = 0;
+    }
+    if( l_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->extra = l_ef;
+    l_ef += z->ext;
+
+    /* Allocate memory for the  central extra fields. */
+    if( z->cextra && z->cext != 0 ) {
+        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_MAC3_SIZE);
+    } else {
+        c_ef = (char *)malloc( EB_C_MAC3_SIZE );
+        z->cext = 0;
+    }
+    if( c_ef == NULL ) {
+        return ZE_MEM;
+    }
+    z->cextra = c_ef;
+    c_ef += z->cext;
+
+    /**
+    **  Now add the local version of the field.
+    **/
+    l_ef = make_EF_Head_MAC3(l_ef, compsize, (ulg)attrsize, m3_compr);
+    memcpy(l_ef, compbuff, (size_t)compsize);
+    l_ef += compsize;
+    z->ext += EB_L_MAC3_SIZE + compsize;
+    free(compbuff);
+    /* And the central version. */
+    c_ef = make_EF_Head_MAC3(c_ef, 0, (ulg)attrsize, m3_compr);
+    z->cext += EB_C_MAC3_SIZE;
+
+    return ZE_OK;
+}
+
+
+
+
+/*
+* Build the new mac local extra field header.
+* It's identical with the central extra field.
+* All native data are in Intel (=little-endian) format
+*/
+static char *make_EF_Head_MAC3(char *ef, unsigned compsize, ulg attrsize,
+                               unsigned flag)
+{
+    unsigned info_flag = flag;
+
+    Assert_it(ef, "make_EF_Head_MAC3","")
+
+    /*  the first four fields are in Intel little-endian format  */
+    *ef++ = 'M';         /* tag for this extra block               2 Bytes */
+    *ef++ = '3';
+
+                                  /* total data size this block    2 Bytes */
+    *ef++ = (char) (EB_MAC3_HLEN + compsize);
+    *ef++ = (char)((EB_MAC3_HLEN + compsize) >> 8);
+
+    *ef++ = (char)(attrsize);
+    *ef++ = (char)(attrsize >> 8);
+    *ef++ = (char)(attrsize >> 16);
+    *ef++ = (char)(attrsize >> 24);
+
+                                   /* info Bits  (flags)           2 Bytes */
+
+    if (MacZip.DataForkOnly)            info_flag |= (EB_M3_FL_DATFRK |
+                                                      EB_M3_FL_NOCHANGE);
+    if (MacZip.CurrentFork == DataFork) info_flag |= EB_M3_FL_DATFRK;
+    if (!MacZip.HaveGMToffset)          info_flag |= EB_M3_FL_NOUTC;
+
+    *ef++ = (char)info_flag;
+    *ef++ = (char)0x00;            /* reserved at the moment */
+
+ /* Note: Apple defined File-Type/-Creator as OSType ( =unsigned long,
+          see Universal Headers 3.1). However, File-Type/-Creator are a
+          unique four-character sequence. Therefore the byteorder of the
+          File-Type/-Creator are NOT changed. The native format is used.  */
+
+                                                       /* Type:    4 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 24);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 16);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType);
+
+                                                       /* Creator: 4 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 24);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 16);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator);
+
+    return ef;
+}
+
+
+
+
+
+/*
+* Build the new mac local extra field header.
+* All native data are in Intel (=little-endian) format
+*/
+unsigned make_extrafield_MAC3(char *ef)
+{
+    char *ef_m3_begin = ef;
+    char *temp_Pathname;
+    char tmp_buffer[NAME_MAX];
+    unsigned char comment[257];
+    unsigned short FLength = 0;
+    unsigned short CLength = 0;
+    short   tempFork;
+    OSErr       err;
+
+    Assert_it(ef, "make_extrafield_MAC3","")
+
+    if (MacZip.isMacStatValid == false)
+    {
+        fprintf(stderr,
+                "Internal Logic Error: [%d/%s] MacStat is out of sync !",
+                __LINE__, __FILE__);
+        exit(-1);
+    }
+
+    /* Start Macintosh Finder FInfo structure except Type/Creator
+       (see make_EF_Head_MAC3()) 8 Bytes overall */
+
+                                             /* file Finder Flags: 2 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags >> 8);
+
+                                    /* Finders Icon position of a file*/
+                                   /* V/Y-Position:                2 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v >> 8);
+
+                                   /* H/X-Position:                2 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h >> 8);
+
+                               /* fdFldr Folder containing file    2 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFldr);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFldr >> 8);
+
+                /* End Macintosh Finder FInfo structure */
+
+                                                    /*    8 Bytes so far ... */
+
+                /* Start Macintosh Finder FXInfo structure  16 Bytes overall */
+                                                    /* Icon ID:    2 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdIconID);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdIconID >> 8);
+
+                                                        /* unused: 6 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[0]);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[0] >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[1]);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[1] >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[2]);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[2] >> 8);
+                                                   /* Script flag: 1 Byte */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdScript);
+                                                /* More flag bits: 1 Byte */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdXFlags);
+                                                /* Comment ID      2 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdComment);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdComment >> 8);
+
+                                                   /* Home Dir ID: 4 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdPutAway);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdPutAway >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdPutAway >> 16);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdPutAway >> 24);
+                /* End Macintosh Finder FXInfo structure */
+
+                                                    /*   24 Bytes so far ... */
+
+                                            /* file version number 1 Byte */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFVersNum);
+
+                                        /* directory access rights 1 Byte */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioACUser);
+
+                                                 /* Creation-time  4 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat  >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 16);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 24);
+                                             /* Modification-time  4 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 16);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 24);
+                                                   /* Backup-time  4 Bytes */
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlBkDat);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlBkDat >> 8);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlBkDat >> 16);
+    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlBkDat >> 24);
+
+                                                    /*   38 Bytes so far ... */
+#ifdef USE_EF_UT_TIME
+    if (MacZip.HaveGMToffset) {
+                                              /* GMT-Offset times  12 Bytes */
+        *ef++ = (char)(MacZip.Cr_UTCoffs);
+        *ef++ = (char)(MacZip.Cr_UTCoffs >> 8);
+        *ef++ = (char)(MacZip.Cr_UTCoffs >> 16);
+        *ef++ = (char)(MacZip.Cr_UTCoffs >> 24);
+        *ef++ = (char)(MacZip.Md_UTCoffs);
+        *ef++ = (char)(MacZip.Md_UTCoffs >> 8);
+        *ef++ = (char)(MacZip.Md_UTCoffs >> 16);
+        *ef++ = (char)(MacZip.Md_UTCoffs >> 24);
+        *ef++ = (char)(MacZip.Bk_UTCoffs);
+        *ef++ = (char)(MacZip.Bk_UTCoffs >> 8);
+        *ef++ = (char)(MacZip.Bk_UTCoffs >> 16);
+        *ef++ = (char)(MacZip.Bk_UTCoffs >> 24);
+    }
+                                                    /*   50 Bytes so far ... */
+#endif
+
+                                  /* Text Encoding Base (charset)  2 Bytes */
+    *ef++ = (char)(MacZip.CurrTextEncodingBase);
+    *ef++ = (char)(MacZip.CurrTextEncodingBase >> 8);
+                                                    /*   52 Bytes so far ... */
+
+    /* MacZip.CurrentFork will be changed, so we have to save it  */
+    tempFork = MacZip.CurrentFork;
+    if (!MacZip.StoreFullPath)  {
+        temp_Pathname = StripPartialDir(tmp_buffer, MacZip.SearchDir,
+                                        MacZip.FullPath);
+    } else {
+        temp_Pathname = MacZip.FullPath;
+    }
+    MacZip.CurrentFork = tempFork;
+
+    FLength = strlen(temp_Pathname) + 1;
+    memcpy( ef, temp_Pathname, (size_t)FLength );
+    ef += FLength;          /* make room for the string -  variable length */
+
+    err = FSpLocationFromFullPath(strlen(MacZip.FullPath), MacZip.FullPath,
+                                  &MacZip.fileSpec);
+    printerr("FSpLocationFromFullPath:", err, err,
+             __LINE__, __FILE__, tmp_buffer);
+
+    err = FSpDTGetComment(&MacZip.fileSpec, comment);
+    printerr("FSpDTGetComment:", (err != -5012) && (err != 0), err,
+             __LINE__, __FILE__, "");
+    PToCCpy(comment,tmp_buffer);
+
+    CLength = strlen(tmp_buffer) + 1;
+    memcpy( ef, tmp_buffer, (size_t)CLength );
+    ef += CLength;          /* make room for the string -  variable length */
+
+    if (verbose) printf("\n comment: [%s]", tmp_buffer);
+
+    return (unsigned)(ef - ef_m3_begin);
+}
+
+
+
+
+
+
+/*
+* Print all native data of the new mac local extra field.
+* It's for debugging purposes and disabled by default.
+*/
+
+static void PrintFileInfo(void)
+{
+DateTimeRec  MacTime;
+
+printf("\n\n---------------------------------------------"\
+       "----------------------------------");
+printf("\n FullPath Name =                   [%s]",  MacZip.FullPath);
+printf("\n File Attributes =                  %s  0x%x  %d",
+          sBit2Str(MacZip.fpb.hFileInfo.ioFlAttrib),
+          MacZip.fpb.hFileInfo.ioFlAttrib,
+          MacZip.fpb.hFileInfo.ioFlAttrib);
+printf("\n Enclosing Folder ID# =             0x%x  %d",
+          MacZip.fpb.hFileInfo.ioFlParID,
+          MacZip.fpb.hFileInfo.ioFlParID);
+
+if (!MacZip.isDirectory)
+{
+printf("\n File Type =                        [%c%c%c%c]  0x%lx",
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 24,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 16,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 8,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType);
+
+printf("\n File Creator =                     [%c%c%c%c]  0x%lx",
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 24,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 16,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 8,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator);
+
+printf("\n Data Fork :" );
+printf("\n    Actual (Logical) Length =       %d  0x%x ",
+              MacZip.fpb.hFileInfo.ioFlLgLen,
+              MacZip.fpb.hFileInfo.ioFlLgLen);
+printf("\n    Allocated (Physical) Length =   %d  0x%x",
+              MacZip.fpb.hFileInfo.ioFlPyLen,
+              MacZip.fpb.hFileInfo.ioFlPyLen);
+printf("\n Resource Fork :" );
+printf("\n    Actual (Logical) Length =       %d  0x%x",
+              MacZip.fpb.hFileInfo.ioFlRLgLen,
+              MacZip.fpb.hFileInfo.ioFlRLgLen );
+printf("\n    Allocated (Physical) Length =   %d  0x%x",
+              MacZip.fpb.hFileInfo.ioFlRPyLen,
+              MacZip.fpb.hFileInfo.ioFlRPyLen );
+}
+
+printf("\n Dates :               ");
+
+SecondsToDate (MacZip.CreatDate, &MacTime);
+printf("\n    Created  =                       %4d/%2d/%2d %2d:%2d:%2d  ",
+    MacTime.year,
+    MacTime.month,
+    MacTime.day,
+    MacTime.hour,
+    MacTime.minute,
+    MacTime.second);
+
+SecondsToDate (MacZip.BackDate, &MacTime);
+printf("\n    Backup   =                       %4d/%2d/%2d %2d:%2d:%2d  ",
+    MacTime.year,
+    MacTime.month,
+    MacTime.day,
+    MacTime.hour,
+    MacTime.minute,
+    MacTime.second);
+
+SecondsToDate (MacZip.ModDate, &MacTime);
+printf("\n    Modified =                       %4d/%2d/%2d %2d:%2d:%2d  ",
+    MacTime.year,
+    MacTime.month,
+    MacTime.day,
+    MacTime.hour,
+    MacTime.minute,
+    MacTime.second);
+
+if (!MacZip.isDirectory)
+{
+printf("\n Finder Flags :                     %s  0x%x  %d",
+          sBit2Str(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags),
+          MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags,
+          MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags);
+printf("\n Finder Icon Position =          X: %d  0x%x ",
+          MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h,
+          MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h);
+printf("\n                                  Y: %d  0x%x ",
+          MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v,
+          MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v);
+}
+else
+{
+printf("\n Finder Flags :                     %s  0x%x  %d",
+          sBit2Str(MacZip.fpb.dirInfo.ioDrUsrWds.frFlags),
+          MacZip.fpb.dirInfo.ioDrUsrWds.frFlags,
+          MacZip.fpb.dirInfo.ioDrUsrWds.frFlags);
+printf("\n Finder Icon Position =          X: %d  0x%x ",
+          MacZip.fpb.dirInfo.ioDrUsrWds.frLocation.h,
+          MacZip.fpb.dirInfo.ioDrUsrWds.frLocation.h);
+printf("\n                                  Y: %d  0x%x ",
+          MacZip.fpb.dirInfo.ioDrUsrWds.frLocation.v,
+          MacZip.fpb.dirInfo.ioDrUsrWds.frLocation.v);
+}
+
+printf("\n----------------------------------------------------"\
+        "---------------------------\n");
+}
+
+
+
+/*
+* If the switch '-v' is used, print some more info.
+*/
+
+static void print_extra_info(void)
+{
+char Fork[20];
+
+if (MacZip.CurrentFork == DataFork) sstrcpy(Fork,"<DataFork>");
+else  sstrcpy(Fork,"<ResourceFork>");
+
+printf("\n%16s [%c%c%c%c]  [%c%c%c%c]",Fork,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 24,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 16,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 8,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType,
+
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 24,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 16,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 8,
+    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator);
+}
diff --git a/macos/source/getenv.c b/macos/source/getenv.c
new file mode 100644 (file)
index 0000000..586815d
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+
+This file implements the getenv() function.
+
+#  Background:
+#  Under Unix: Each Process (= running Program) has a set of
+#  associated variables. The variables are called enviroment
+#  variables and, together, constitute the process environment.
+#  These variables include the search path, the terminal type,
+#  and the user's login name.
+
+#  Unfortunatelly the MacOS has no equivalent. So we need
+#  a file to define the environment variables.
+#  Name of this file is "MacZip.Env". It can be placed
+#  in the current folder of MacZip or in the
+#  preference folder of the system disk.
+#  If MacZip founds the "MacZip.Env" file in the current
+#  the folder of MacZip the "MacZip.Env" file in the
+#  preference folder will be ignored.
+
+#  An environment variable has a name and a value:
+#  Name=Value
+#  Note: Spaces are significant:
+#  ZIPOPT=-r  and
+#  ZIPOPT = -r are different !!!
+
+
+ */
+
+/*****************************************************************************/
+/*  Includes                                                                 */
+/*****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unix.h>
+#include <Files.h>
+#include <Folders.h>
+
+#include "pathname.h"
+#include "helpers.h"
+
+/*****************************************************************************/
+/*  Module level Vars                                                        */
+/*****************************************************************************/
+
+static char ListAllKeyValues = 0;
+static unsigned LineNumber   = 0;
+static char CompletePath[NAME_MAX];
+Boolean IgnoreEnvironment    = false;  /* used by dialog.c and initfunc.c
+                                          of the Mainapp */
+
+/*****************************************************************************/
+/*  Macros, typedefs                                                         */
+/*****************************************************************************/
+
+typedef struct _EnviromentPair {
+    char *key;
+    char *value;
+} EnviromentPair;
+
+
+#define MAX_COMMAND 1024
+
+
+/*****************************************************************************/
+/*  Prototypes                                                               */
+/*****************************************************************************/
+
+
+int get_char(FILE *file);
+void unget_char(int ch,FILE *file);
+int get_string(char *string,int size, FILE *file, char *terms);
+void skip_comments(FILE *file);
+char *load_entry(FILE *file);
+char *getenv(const char *name);
+EnviromentPair *ParseLine(char *line);
+OSErr FSpFindFolder_Name(short vRefNum, OSType folderType,
+                         Boolean createFolder,FSSpec *spec, unsigned char *name);
+FILE * FSp_fopen(ConstFSSpecPtr spec, const char * open_mode);
+void ShowAllKeyValues(void);
+void Set_LineNum(unsigned ln);
+
+/*****************************************************************************/
+/*  Functions                                                                */
+/*****************************************************************************/
+
+
+/* get_string(str, max, file, termstr) : like fgets() but
+ *      (1) has terminator string which should include \n
+ *      (2) will always leave room for the null
+ *      (3) uses get_char() so LineNumber will be accurate
+ *      (4) returns EOF or terminating character, whichever
+ */
+int get_string(char *string, int size, FILE *file, char *terms)
+{
+    int ch;
+
+    while (EOF != (ch = get_char(file)) && !strchr(terms, ch)) {
+        if (size > 1) {
+            *string++ = (char) ch;
+            size--;
+        }
+    }
+
+    if (size > 0)
+        {
+        *string = '\0';
+        }
+
+    return ch;
+}
+
+
+
+
+void Set_LineNum(unsigned ln)
+{
+ LineNumber = ln;
+}
+
+
+
+/* get_char(file) : like getc() but increment LineNumber on newlines
+ */
+int get_char(FILE *file)
+{
+    int ch;
+
+    ch = getc(file);
+    if (ch == '\n')
+        {
+        Set_LineNum(LineNumber + 1);
+        }
+
+    return ch;
+}
+
+
+
+
+/* skip_comments(file) : read past comment (if any)
+ */
+void skip_comments(FILE *file)
+{
+    int ch;
+
+    while (EOF != (ch = get_char(file)))
+        {
+        /* ch is now the first character of a line.
+         */
+
+        while (ch == ' ' || ch == '\t')
+            {
+            ch = get_char(file);
+            }
+
+        if (ch == EOF)
+            {
+            break;
+            }
+
+        /* ch is now the first non-blank character of a line.
+         */
+
+        if (ch != '\n' && ch != '#')
+            {
+            break;
+            }
+
+        /* ch must be a newline or comment as first non-blank
+         * character on a line.
+         */
+
+        while (ch != '\n' && ch != EOF)
+            {
+            ch = get_char(file);
+            }
+
+        /* ch is now the newline of a line which we're going to
+         * ignore.
+         */
+    }
+
+    if (ch != EOF)
+        {
+        unget_char(ch, file);
+        }
+}
+
+
+
+
+/* unget_char(ch, file) : like ungetc but do LineNumber processing
+ */
+void unget_char(int ch, FILE *file)
+{
+    ungetc(ch, file);
+    if (ch == '\n')
+        {
+        Set_LineNum(LineNumber - 1);
+        }
+}
+
+
+/* this function reads one file entry -- the next -- from a file.
+*  it skips any leading blank lines, ignores comments, and returns
+*  NULL if for any reason the entry can't be read and parsed.
+*/
+
+char *load_entry(FILE *file)
+{
+    int ch;
+    static char cmd[MAX_COMMAND];
+
+    skip_comments(file);
+
+    ch = get_string(cmd, MAX_COMMAND, file, "\n");
+
+    if (ch == EOF)
+        {
+        return NULL;
+        }
+
+    return cmd;
+}
+
+
+
+
+
+EnviromentPair *ParseLine(char *line)
+{
+char *tmpPtr;
+static EnviromentPair *Env;
+unsigned short length = strlen(line);
+
+Env->key   = "";
+Env->value = "";
+
+for (tmpPtr = line; *tmpPtr; tmpPtr++)
+    {
+    if (*tmpPtr == '=')
+        {
+        *tmpPtr = 0;
+        Env->key = line;
+        if (strlen(Env->key) < length)
+            {
+            Env->value = ++tmpPtr;
+            }
+        return Env;
+        }
+    }
+return Env;
+}
+
+
+
+
+
+char *getenv(const char *name)
+{
+FILE *fp;
+char *LineStr = NULL;
+EnviromentPair *Env1;
+FSSpec spec;
+OSErr err;
+
+if (IgnoreEnvironment)
+    return NULL;  /* user wants to ignore the environment vars */
+
+if (name == NULL)
+    return NULL;
+
+GetCompletePath(CompletePath,"MacZip.Env",&spec,&err);
+
+/* try open the file in the current folder */
+fp = FSp_fopen(&spec,"r");
+if (fp == NULL)
+    { /* Okey, lets try open the file in the preference folder */
+    FSpFindFolder_Name(
+                   kOnSystemDisk,
+                   kPreferencesFolderType,
+                   kDontCreateFolder,
+                   &spec,
+                   "\pMacZip.Env");
+    fp = FSp_fopen(&spec,"r");
+    if (fp == NULL)
+        {
+        return NULL; /* there is no enviroment-file */
+        }
+    }
+
+LineStr = load_entry(fp);
+while (LineStr != NULL)
+    {   /* parse the file line by line */
+    Env1 = ParseLine(LineStr);
+    if (strlen(Env1->value) > 0)
+        {       /* we found a key/value pair */
+        if (ListAllKeyValues)
+            printf("\n   Line:%3d   [%s] = [%s]",LineNumber,Env1->key,Env1->value);
+        if (stricmp(name,Env1->key) == 0)
+            {   /* we found the value of a given key */
+            return Env1->value;
+            }
+        }
+    LineStr = load_entry(fp);  /* read next line */
+    }
+fclose(fp);
+
+return NULL;
+}
+
+
+
+
+
+OSErr FSpFindFolder_Name(
+    short vRefNum,          /* Volume reference number. */
+    OSType folderType,      /* Folder type taken by FindFolder. */
+    Boolean createFolder,   /* Should we create it if non-existant. */
+    FSSpec *spec,           /* Pointer to resulting directory. */
+    unsigned char *name)    /* Name of the file in the folder */
+{
+    short foundVRefNum;
+    long foundDirID;
+    OSErr err;
+
+    err = FindFolder(vRefNum, folderType, createFolder,
+                     &foundVRefNum, &foundDirID);
+    if (err != noErr)
+        {
+        return err;
+        }
+
+    err = FSMakeFSSpec(foundVRefNum, foundDirID, name, spec);
+    return err;
+}
+
+
+
+
+void ShowAllKeyValues(void)
+{
+OSErr err;
+FSSpec spec;
+Boolean tmpIgnoreEnvironment = IgnoreEnvironment;
+
+ListAllKeyValues = 1;
+IgnoreEnvironment = false;
+
+GetCompletePath(CompletePath,"MacZip.Env",&spec,&err);
+if (err != 0)
+    { /* Okey, lets try open the file in the preference folder */
+    FSpFindFolder_Name(
+                   kOnSystemDisk,
+                   kPreferencesFolderType,
+                   kDontCreateFolder,
+                   &spec,
+                   "\pMacZip.Env");
+    GetFullPathFromSpec(CompletePath,&spec, &err);
+    if (err != 0)
+        {
+        return; /* there is no enviroment-file */
+        }
+    }
+
+printf("\nLocation of the current \"MacZip.Env\" file:\n [%s]",CompletePath);
+
+printf("\n\nList of all environment variables\n");
+getenv(" ");
+printf("\n\nEnd\n\n");
+
+/* restore used variables */
+ListAllKeyValues = 0;
+LineNumber = 0;
+IgnoreEnvironment = tmpIgnoreEnvironment;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/macos/source/helpers.c b/macos/source/helpers.c
new file mode 100644 (file)
index 0000000..a7df558
--- /dev/null
@@ -0,0 +1,477 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+  helpers.c
+
+  Some useful functions Used by unzip and zip.
+
+  ---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/*  Includes                                                                 */
+/*****************************************************************************/
+
+#include "zip.h"
+#include <ctype.h>
+#include <time.h>
+#include <sound.h>
+
+#include "macstuff.h"
+#include "helpers.h"
+#include "pathname.h"
+
+
+/*****************************************************************************/
+/*  Global Vars                                                              */
+/*****************************************************************************/
+
+
+extern int noisy;
+extern char MacPathEnd;
+extern char *zipfile;   /* filename of the Zipfile */
+extern char *tempzip;   /* Temporary zip file name */
+extern ZCONST unsigned char MacRoman_to_WinCP1252[128];
+
+
+static char         argStr[1024];
+static char         *argv[MAX_ARGS + 1];
+
+
+
+/*****************************************************************************/
+/*  Functions                                                                */
+/*****************************************************************************/
+
+
+/*
+**  Copy a C string to a Pascal string
+**
+*/
+unsigned char *CToPCpy(unsigned char *pstr, char *cstr)
+{
+    register char *dptr;
+    register unsigned len;
+
+        len=0;
+        dptr=(char *)pstr+1;
+    while (len<255 && (*dptr++ = *cstr++)!='\0') ++len;
+    *pstr= (unsigned char)len;
+  return pstr;
+}
+
+
+
+/*
+**  Copy a Pascal string to a C string
+**
+*/
+
+char *PToCCpy(unsigned char *pstr, char *cstr)
+{
+strncpy(cstr, (char *) &pstr[1], *pstr);
+    cstr[pstr[0]] = '\0';  /* set endmarker for c-string */
+return cstr;
+}
+
+
+/*
+**  strcpy() and strcat() work-alikes which allow overlapping buffers.
+*/
+
+char *sstrcpy(char *to,const char *from)
+{
+    memmove(to, from, 1+strlen(from));
+    return to;
+}
+
+char *sstrcat(char *to,const char *from)
+{
+    sstrcpy(to + strlen(to), from);
+    return to;
+}
+
+
+
+/*
+**  Alloc memory and init it
+**
+*/
+char *StrCalloc(unsigned short size)
+{
+char *strPtr = NULL;
+
+if ((strPtr = calloc(size, sizeof(char))) == NULL)
+    printerr("StrCalloc failed:", -1, size, __LINE__, __FILE__, "");
+
+Assert_it(strPtr,"strPtr == NULL","")
+return strPtr;
+}
+
+
+
+/*
+**  Release only non NULL pointers
+**
+*/
+char *StrFree(char *strPtr)
+{
+
+if (strPtr != NULL)
+    {
+    free(strPtr);
+    }
+
+return NULL;
+}
+
+
+
+
+/*
+**  Return a value in a binary string
+**
+*/
+
+char *sBit2Str(unsigned short value)
+{
+  static char str[sizeof(value)*8];
+  int biz    = 16;
+  int strwid = 16;
+  int i, j;
+  char *tempPtr = str;
+
+      j = strwid - (biz + (biz >> 2)- (biz % 4 ? 0 : 1));
+
+      for (i = 0; i < j; i++) {
+            *tempPtr++ = ' ';
+      }
+      while (--biz >= 0)
+      {
+            *tempPtr++ = ((value >> biz) & 1) + '0';
+            if (!(biz % 4) && biz) {
+                  *tempPtr++ = ' ';
+            }
+      }
+      *tempPtr = '\0';
+
+  return str;
+}
+
+
+
+
+/*
+**  Parse commandline style arguments
+**
+*/
+
+int ParseArguments(char *s, char ***arg)
+{
+    int  n = 1, Quote = 0;
+    char *p = s, *p1, c;
+
+    argv[0] = GetAppName();
+
+    *arg = argv;
+
+    p1 = (char *) argStr;
+    while ((c = *p++) != 0) {
+        if (c==' ') continue;
+        argv[n++] = p1;
+        if (n > MAX_ARGS)
+            return (n-1);
+        do {
+            if (c=='\\' && *p++)
+                c = *p++;
+            else
+                if ((c=='"') || (c == '\'')) {
+                    if (!Quote) {
+                        Quote = c;
+                        continue;
+                    }
+                    if (c == Quote) {
+                        Quote = 0;
+                        continue;
+                    }
+                }
+            *p1++ = c;
+        } while (*p && ((c = *p++) != ' ' || Quote));
+        *p1++ = '\0';
+    }
+    return n;
+}
+
+
+
+/*
+**  Print commandline style arguments
+**
+*/
+
+void PrintArguments(int argc, char **argv)
+{
+
+printf("\n Arguments:");
+printf("\n --------------------------");
+
+while(--argc >= 0)
+    printf("\n argc: %d  argv: [%s]", argc, &*argv[argc]);
+
+printf("\n --------------------------\n\n");
+return;
+}
+
+
+
+/*
+**  return some error-msg on file-system
+**
+*/
+
+int PrintUserHFSerr(int cond, int err, char *msg2)
+{
+char *msg;
+
+if (cond != 0)
+    {
+    switch (err)
+        {
+         case -35:
+            msg = "No such Volume";
+         break;
+
+         case -56:
+            msg = "No such Drive";
+         break;
+
+         case -37:
+            msg = "Bad Volume Name";
+         break;
+
+         case -49:
+            msg = "File is already open for writing";
+         break;
+
+         case -43:
+            msg = "Directory/File not found";
+         break;
+
+         case -120:
+            msg = "Directory/File not found or incomplete pathname";
+         break;
+
+        default: return err;
+         }
+    fprintf(stderr, "\n\n Error: %s ->%s", msg, msg2);
+    exit(err);
+    }
+
+return 0;
+}
+
+
+
+/*
+**  Check mounted volumes and return number of volumes
+**  with the same name.
+*/
+
+short CheckMountedVolumes(char *FullPath)
+{
+FSSpec  volumes[50];        /* 50 Volumes should be enough */
+char VolumeName[257], volume[257];
+short actVolCount, volIndex = 1, VolCount = 0;
+OSErr err;
+int i;
+
+GetVolumeFromPath(FullPath, VolumeName);
+
+err = OnLine(volumes, 50, &actVolCount, &volIndex);
+printerr("OnLine:", (err != -35) && (err != 0), err, __LINE__, __FILE__, "");
+
+for (i=0; i < actVolCount; i++)
+    {
+    PToCCpy(volumes[i].name,volume);
+    if (stricmp(volume, VolumeName) == 0) VolCount++;
+    }
+printerr("OnLine: ", (VolCount == 0), VolCount, __LINE__, __FILE__, FullPath);
+
+return VolCount;
+}
+
+
+
+
+
+
+
+
+/*
+**  compares strings, ignoring differences in case
+**
+*/
+
+int stricmp(const char *p1, const char *p2)
+{
+int diff;
+
+while (*p1 && *p2)
+    {
+    if (*p1 != *p2)
+        {
+        if (isalpha(*p1) && isalpha(*p2))
+            {
+            diff = toupper(*p1) - toupper(*p2);
+            if (diff) return diff;
+            }
+            else break;
+        }
+        p1++;
+        p2++;
+    }
+return *p1 - *p2;
+}
+
+
+
+/*
+** Convert the MacOS-Strings (Filenames/Findercomments) to a most compatible.
+** These strings will be stored in the public area of the zip-archive.
+** Every foreign platform (outside macos) will access these strings
+** for extraction.
+*/
+
+void MakeCompatibleString(char *MacOS_Str,
+            const char SpcChar1, const char SpcChar2,
+            const char SpcChar3, const char SpcChar4,
+            short CurrTextEncodingBase)
+{
+    char *tmpPtr;
+    register uch curch;
+
+    Assert_it(MacOS_Str,"MakeCompatibleString MacOS_Str == NULL","")
+    for (tmpPtr = MacOS_Str; (curch = *tmpPtr) != '\0'; tmpPtr++)
+    {
+        if (curch == SpcChar1)
+            *tmpPtr = SpcChar2;
+        else
+        if (curch == SpcChar3)
+            *tmpPtr = SpcChar4;
+        else  /* default */
+        /* now convert from MacRoman to ISO-8859-1 */
+        /* but convert only if MacRoman is activ */
+            if ((CurrTextEncodingBase == kTextEncodingMacRoman) &&
+                (curch > 127))
+                   {
+                    *tmpPtr = (char)MacRoman_to_WinCP1252[curch - 128];
+                   }
+    }  /* end for */
+}
+
+
+
+
+Boolean CheckForSwitch(char *Switch, int argc, char **argv)
+{
+  char *p;              /* steps through option arguments */
+  int i;                /* arg counter, root directory flag */
+
+  for (i = 1; i < argc; i++)
+  {
+    if (argv[i][0] == '-')
+    {
+      if (argv[i][1])
+        {
+        for (p = argv[i]+1; *p; p++)
+            {
+            if (*p == Switch[0])
+                {
+                return true;
+                }
+            if ((Switch[1] != NULL) &&
+                ((*p == Switch[0]) && (*p == Switch[1])))
+                {
+                return true;
+                }
+            }
+         }
+     }
+  }
+
+return false;
+}
+
+
+
+
+
+
+
+#if (defined(USE_SIOUX) || defined(MACUNZIP_STANDALONE))
+
+/*
+**  checks the condition and returns an error-msg
+**  this function is for internal use only
+*/
+
+OSErr printerr(const char *msg, int cond, int err, int line, char *file,
+              const char *msg2)
+{
+
+if (cond != 0)
+    {
+    fprintf(stderr, "\nint err: %d: %s %d [%d/%s] {%s}\n", clock(), msg, err,
+            line, file, msg2);
+    }
+
+return cond;
+}
+
+
+/*
+fake-functions:
+Not Implemented for metrowerks SIOUX
+*/
+
+void leftStatusString(char *status)
+{
+status = status;
+}
+
+
+void rightStatusString(char *status)
+{
+status = status;
+}
+
+
+
+void DoWarnUserDupVol( char *FullPath )
+{
+  char VolName[257];
+  GetVolumeFromPath(FullPath,  VolName);
+
+  printf("\n There are more than one volume that has the same name !!\n");
+
+  printf("\n Volume: %s\n",VolName);
+
+  printf("\n This port has one weak point:");
+  printf("\n It is based on pathnames. As you may be already know:");
+  printf("\n Pathnames are not unique on a Mac !");
+  printf("\n MacZip has problems to find the correct location of");
+  printf("\n the archive or the files.\n");
+
+  printf("\n My (Big) recommendation:  Name all your volumes with an");
+  printf("\n unique name and MacZip will run without any problem.");
+}
+
+
+
+#endif
diff --git a/macos/source/helpers.h b/macos/source/helpers.h
new file mode 100644 (file)
index 0000000..86aa178
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef HELPERS_H
+#define HELPERS_H       1
+
+ /* Convert a C string to a Pascal string */
+unsigned char *CToPCpy(unsigned char *pstr, char *cstr);
+
+ /* Convert a Pascal string to a C string */
+char *PToCCpy(unsigned char *pstr, char *cstr);
+
+char *sstrcpy(char *to,const char *from);
+char *sstrcat(char *to,const char *from);
+
+char *StrCalloc(unsigned short size);
+char *StrFree(char *strPtr);
+
+char *sBit2Str(unsigned short value);
+
+void print_extra_info(void);
+
+int ParseArguments(char *s, char ***arg);
+void PrintArguments(int argc, char **argv);
+
+Boolean IsZipFile(char *name);
+OSErr printerr(const char *msg, int cond, int err, int line, char *file,
+               const char *msg2);
+int PrintUserHFSerr(int cond, int err, char *msg2);
+
+short CheckMountedVolumes(char *FullPath);
+void DoWarnUserDupVol(char *path);
+
+void PrintFileInfo(void);
+
+int stricmp(const char *p1, const char *p2);
+void leftStatusString(char *status);
+void rightStatusString(char *status);
+
+Boolean isZipFile(FSSpec *fileToOpen);
+
+unsigned long MacFileDate_to_UTime(unsigned long mactime);
+Boolean CheckForSwitch(char *Switch, int argc, char **argv);
+
+void MakeCompatibleString(char *MacOS_Str,
+            const char SpcChar1, const char SpcChar2,
+            const char SpcChar3, const char SpcChar4,
+            short CurrTextEncodingBase);
+
+#define     MAX_ARGS    25
+
+#endif   /*  HELPERS_H   */
diff --git a/macos/source/macglob.h b/macos/source/macglob.h
new file mode 100644 (file)
index 0000000..17415e1
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef _MACGLOBAL_
+#define _MACGLOBAL_
+
+#include <time.h>
+
+/*
+all my Global vars are defined here.
+*/
+
+#define ResourceFork    -1
+#define DataFork        1
+#define NoFork          0
+
+/*
+all my Global vars are defined here.
+*/
+typedef struct {
+    short       CurrentFork;
+    short       MacZipMode;
+
+    Boolean     isMacStatValid;
+    Boolean     HaveGMToffset;
+
+    short CurrTextEncodingBase;
+
+    /* info about the current file */
+    Boolean         isDirectory;
+    char            FullPath[NAME_MAX];
+    char            FileName[NAME_MAX];
+    FSSpec          fileSpec;
+
+    long            dirID;
+    CInfoPBRec      fpb;
+
+    /* time infos about the current file */
+    time_t          CreatDate;
+    time_t          ModDate;
+    time_t          BackDate;
+    long            Cr_UTCoffs; /* offset "local time - UTC" for CreatDate */
+    long            Md_UTCoffs; /* offset "local time - UTC" for ModDate */
+    long            Bk_UTCoffs; /* offset "local time - UTC" for BackDate */
+
+    /* some statistics over all*/
+    unsigned long   FoundFiles;
+    unsigned long   FoundDirectories;
+    unsigned long   RawCountOfItems;
+    unsigned long   BytesOfData;
+
+    unsigned long   attrsize;
+
+    /* some switches and user parameters */
+    Boolean         DataForkOnly;
+    Boolean         StoreFullPath;
+    Boolean         StoreFoldersAlso;  /* internal switch is true if '-r' is set */
+    unsigned short  SearchLevels;
+    char            Pattern[NAME_MAX];
+    Boolean         IncludeInvisible;
+    Boolean         StatingProgress;
+
+    char            SearchDir[NAME_MAX];
+    char            CurrentPath[NAME_MAX];
+
+    /* current zip / tempzip file info */
+    char            ZipFullPath[NAME_MAX];
+
+    FSSpec          ZipFileSpec;
+    unsigned long   ZipFileType;
+    char            TempZipFullPath[NAME_MAX];
+    FSSpec          TempZipFileSpec;
+
+} MacZipGlobals;
+
+
+
+void UserStop(void);
+
+
+#endif
diff --git a/macos/source/macopen.c b/macos/source/macopen.c
new file mode 100644 (file)
index 0000000..0f65741
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*** macopen.c; stuff only required for the Mac port ***/
+
+#include "zip.h"
+
+#include <string.h>
+#include <fcntl.h>
+#include <unix.h>
+#include <sound.h>
+
+#include "helpers.h"
+#include "pathname.h"
+#include "macopen.h"
+#include "macstuff.h"
+
+#ifdef MACZIP
+#include "macglob.h"
+
+extern char *zipfile;   /* filename of the Zipfile */
+extern char *tempzip;   /* Temporary zip file name */
+
+extern MacZipGlobals    MacZip;
+
+
+/* don't include "osdep.h" otherwise we will trap into endless loop */
+#undef open
+#undef fopen
+
+
+
+FILE *MacFopen(const char *path, const char *mode)
+{
+static char TruncPath[NAME_MAX];
+OSErr   err = 0;
+
+AssertStr(path,path)
+
+            /* open zipfile or tempzip */
+if (strcmp(zipfile,path) == 0)
+    {
+    GetCompletePath(MacZip.ZipFullPath,path,&MacZip.ZipFileSpec,&err);
+    err = PrintUserHFSerr((err != -43) && (err != 0), err, path);
+    printerr("GetCompletePath:",err,err,__LINE__,__FILE__,path);
+    if (CheckMountedVolumes(MacZip.ZipFullPath) > 1)
+        DoWarnUserDupVol(MacZip.ZipFullPath);
+
+    /* tempfile should appear in the same directory of the zipfile
+       -> save path of zipfile */
+    TruncFilename(TruncPath, MacZip.ZipFullPath);
+    return fopen(MacZip.ZipFullPath, mode);
+    }
+
+if (strcmp(tempzip,path) == 0)
+    {  /* add path of zipfile */
+    sstrcat(TruncPath,tempzip);
+    GetCompletePath(MacZip.TempZipFullPath,TruncPath,&MacZip.TempZipFileSpec,&err);
+    err = PrintUserHFSerr((err != -43) && (err != 0), err, path);
+    printerr("GetCompletePath:",err,err,__LINE__,__FILE__,path);
+
+    return fopen(MacZip.TempZipFullPath, mode);
+    }
+
+printerr("MacFopen:",err,err,__LINE__,__FILE__,path);
+return NULL;
+}
+
+
+
+
+int MacOpen(const char *path,int oflag, ...)
+{
+char RealFname[NAME_MAX];
+
+AssertStr(path,path)
+
+RfDfFilen2Real(RealFname,path, MacZip.MacZipMode, MacZip.DataForkOnly, &MacZip.CurrentFork);
+/* convert to real fname and init global var  MacZip.CurrentFork  !!  */
+
+switch (MacZip.CurrentFork)
+    {
+    case DataFork:
+        {
+        return my_open(RealFname, oflag);
+        break;
+        }
+    case ResourceFork:
+        {
+        return my_open( RealFname, oflag | O_RSRC);
+        break;
+        }
+    default:  /* for now (Zip ver 2.3b) MacOpen should never reach this point */
+        {     /* however, this may change in the future ... */
+        printerr("open: no resource / datafork ",-1,-1,__LINE__,__FILE__,path);
+        return -1;
+        }
+    }
+}
+
+
+#ifdef muell
+ /* file to delete */
+int destroy(char *path)
+{
+static char lastpath[NAME_MAX];
+char    currpath[NAME_MAX];
+static Boolean FirstCall = true;
+long rc;
+
+AssertStr(path,path)
+
+RfDfFilen2Real(currpath, path, MacZip.MacZipMode, MacZip.DataForkOnly, &MacZip.CurrentFork);
+
+if (FirstCall == true)
+    {
+    FirstCall = false;
+    rc = remove(currpath);
+    }
+else if (strcmp(currpath,lastpath) == 0) return 0; /* ignore, file is already deleted */
+        else rc = remove(currpath); /* we are removeing all the files only by their
+        pathname this is dangerous on a mac but there is no other way without
+         a complete rewrite of the port  */
+
+strcpy(lastpath,currpath);
+
+return rc;
+}
+#endif
+
+
+
+
+/* this function replaces the function "replace()" defined in fileio.c */
+int replace(char *new_f, char *temp_f)  /* destination and source file names */
+{
+OSErr   err = 0;
+char    newfname[NAME_MAX];
+
+AssertStr(new_f,new_f)
+AssertStr(temp_f,temp_f)
+
+UserStop();
+
+GetFilename(newfname, new_f);
+
+/* check zipfile name and tempfile name */
+/* we are using this function only for replacing the tempfile with the zipfile */
+if ((strcmp(zipfile,new_f) == 0) || (strcmp(tempzip,temp_f) == 0))
+    {
+    remove(MacZip.ZipFullPath);
+
+    /* rename the temp file to the zip file */
+    err = rename(MacZip.TempZipFullPath,MacZip.ZipFullPath);
+    printerr("rename:",err,err,__LINE__,__FILE__,MacZip.TempZipFullPath);
+if (err != 0) return ZE_CREAT;
+    else return ZE_OK;
+    }
+else return ZE_CREAT;
+}
+
+
+
+ /* file to delete */
+ /* we are removeing all the files only by their
+    pathname this is dangerous on a mac but there is no
+    other way without a complete rewrite of the port  */
+
+int destroy(char *path)
+{
+static char lastpath[NAME_MAX];
+static FSSpec  trashfolder;
+static Boolean FirstCall = true;
+static char Num = 0;
+static Boolean  Immediate_File_Deletion = false;
+char    currpath[NAME_MAX], *envptr;
+FSSpec  fileToDelete;
+OSErr   err;
+
+/* init this function */
+if ((path == NULL) ||
+    (strlen(path) == 0))
+    {
+    FirstCall = true;
+    Num = 0;
+    return -1;
+    }
+
+UserStop();
+
+RfDfFilen2Real(currpath, path, MacZip.MacZipMode,
+                MacZip.DataForkOnly, &MacZip.CurrentFork);
+GetCompletePath(currpath,currpath,&fileToDelete, &err);
+
+if (FirstCall == true)
+    {
+    FirstCall = false;
+    sstrcpy(lastpath,currpath);
+    err = FSpFindFolder(fileToDelete.vRefNum, kTrashFolderType,
+                      kDontCreateFolder,&trashfolder);
+    printerr("FSpFindFolder:",err,err,__LINE__,__FILE__,path);
+
+    envptr = getenv("Immediate_File_Deletion");
+    if (!(envptr == (char *)NULL || *envptr == '\0'))
+        {
+        if (stricmp(envptr,"yes") == 0)
+            Immediate_File_Deletion = true;
+        else
+            Immediate_File_Deletion = false;
+        }
+
+    if (Immediate_File_Deletion)
+        {
+        err = FSpDelete(&fileToDelete);
+        return err;
+        }
+
+    err = CatMove (fileToDelete.vRefNum, fileToDelete.parID,
+                   fileToDelete.name, trashfolder.parID, trashfolder.name);
+    return err;
+    }
+
+if (strcmp(currpath,lastpath) == 0)
+    {
+    return 0; /* ignore, file is already deleted */
+    }
+else
+    {
+
+    if (Immediate_File_Deletion)
+        {
+        err = FSpDelete(&fileToDelete);
+        sstrcpy(lastpath,path);
+        return err;
+        }
+
+    err = CatMove (fileToDelete.vRefNum, fileToDelete.parID,
+                   fileToDelete.name, trashfolder.parID, trashfolder.name);
+
+    /* -48 = file is already existing so we have to rename it before
+       moving the file */
+    if (err == -48)
+        {
+        Num++;
+        if (fileToDelete.name[0] >= 28) /* cut filename if to long */
+            fileToDelete.name[0] = 28;
+        P2CStr(fileToDelete.name);
+        sprintf(currpath,"%s~%d",(char *)fileToDelete.name,Num);
+        C2PStr(currpath);
+        C2PStr((char *)fileToDelete.name);
+        err = HRename (fileToDelete.vRefNum, fileToDelete.parID,
+                       fileToDelete.name, (unsigned char *) currpath);
+        err = CatMove (fileToDelete.vRefNum, fileToDelete.parID,
+                       (unsigned char *) currpath, trashfolder.parID,
+                       trashfolder.name);
+        }
+    }
+
+sstrcpy(lastpath,currpath);
+return err;
+}
+
+
+
+#endif  /* #ifdef MACZIP */
+
+
+
+
+/*
+ *  int open(const char *path, int oflag)
+ *
+ *      Opens a file stream.
+ */
+int my_open(char *path, int oflag)
+{
+    FSSpec          spec;
+    char            permission;
+    HParamBlockRec  hpb;
+    OSErr           err, errno;
+    Boolean targetIsFolder, wasAliased;
+
+    AssertStr(path,path)
+
+    /* Setup permission */
+    if ((oflag & 0x03) == O_RDWR)
+        permission = fsRdWrPerm;
+    else
+        permission = (oflag & O_RDONLY) ? fsRdPerm : 0 + (oflag & O_WRONLY) ? fsWrPerm : 0;
+
+        FSpLocationFromFullPath(strlen(path),path, &spec);
+        if ((oflag & (O_ALIAS | O_NRESOLVE)) == 0)
+            ResolveAliasFile(&spec, true, &targetIsFolder, &wasAliased);
+        hpb.fileParam.ioNamePtr = spec.name;
+        hpb.fileParam.ioVRefNum = spec.vRefNum;
+        hpb.fileParam.ioDirID = spec.parID;
+        hpb.ioParam.ioPermssn = permission;
+
+        if (oflag & O_RSRC)         /* open the resource fork of the file */
+            err = PBHOpenRFSync(&hpb);
+        else                        /* open the data fork of the file */
+            err = PBHOpenDFSync(&hpb);
+
+    if ((err == fnfErr) && (oflag & O_CREAT)) {
+        hpb.fileParam.ioFlVersNum = 0;
+        err = PBHCreateSync(&hpb);
+        if (err == noErr) {
+            /* Set the finder info */
+            unsigned long secs;
+            unsigned long isbinary = oflag & O_BINARY;
+
+            hpb.fileParam.ioFlFndrInfo.fdType = '\?\?\?\?';
+            hpb.fileParam.ioFlFndrInfo.fdCreator = '\?\?\?\?';
+            hpb.fileParam.ioFlFndrInfo.fdFlags = 0;
+            if (oflag & O_ALIAS)        /* set the alias bit */
+                hpb.fileParam.ioFlFndrInfo.fdFlags = kIsAlias;
+            else                                        /* clear all flags */
+                hpb.fileParam.ioFlFndrInfo.fdFlags = 0;
+
+            GetDateTime(&secs);
+            hpb.fileParam.ioFlCrDat = hpb.fileParam.ioFlMdDat = secs;
+            PBHSetFInfoSync(&hpb);
+        }
+
+        if (err && (err != dupFNErr)) {
+            errno = err; return -1;
+        }
+
+            if (oflag & O_RSRC)         /* open the resource fork of the file */
+                err = PBHOpenRFSync(&hpb);
+            else                        /* open the data fork of the file */
+                err = PBHOpenDFSync(&hpb);
+    }
+
+    if (err && (err != dupFNErr) && (err != opWrErr)) {
+        errno = err; return -1;
+    }
+
+    if (oflag & O_TRUNC) {
+        IOParam pb;
+
+        pb.ioRefNum = hpb.ioParam.ioRefNum;
+        pb.ioMisc = 0L;
+        err = PBSetEOFSync((ParmBlkPtr)&pb);
+        if (err != noErr) {
+            errno = err; return -1;
+        }
+    }
+
+    if (oflag & O_APPEND) lseek(hpb.ioParam.ioRefNum,0,SEEK_END);
+
+    return (hpb.ioParam.ioRefNum);
+}
+
+
+
+
+
diff --git a/macos/source/macopen.h b/macos/source/macopen.h
new file mode 100644 (file)
index 0000000..152bceb
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __MACOPEN_H__
+#define __MACOPEN_H__
+
+#include <stdio.h>
+#include <Files.h>
+
+
+FILE *MacFopen(const char *path, const char *mode);
+int MacOpen(const char *path, int oflag, ...);
+
+int my_open(char *path, int oflag);
+
+#endif /* __MACOPEN_H__  */
diff --git a/macos/source/macos.c b/macos/source/macos.c
new file mode 100644 (file)
index 0000000..3cfee7b
--- /dev/null
@@ -0,0 +1,1079 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+  macos.c
+
+  Macintosh-specific routines for use with Info-ZIP's Zip 2.3 and later.
+
+  ---------------------------------------------------------------------------*/
+
+
+/*****************************************************************************/
+/*  Includes                                                                 */
+/*****************************************************************************/
+
+#include "zip.h"
+
+#include "revision.h"
+#include "crypt.h"
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sound.h>
+
+#include <unistd.h>
+
+#include <Strings.h>
+#include <setjmp.h>
+
+/* #include "charmap.h" */
+#include "helpers.h"
+#include "macstuff.h"
+#include "pathname.h"
+#include "recurse.h"
+
+
+/*****************************************************************************/
+/*  Macros, typedefs                                                         */
+/*****************************************************************************/
+
+#define PATH_END   MacPathEnd
+
+/*****************************************************************************/
+/*  Global Vars                                                              */
+/*****************************************************************************/
+
+int error_level;   /* used only in ziperr() */
+
+
+/*  Note: sizeof() returns the size of this allusion
+          13 is current length of "XtraStuf.mac:"      */
+extern const char ResourceMark[13]; /* var is initialized in file pathname.c */
+
+
+extern jmp_buf EnvForExit;
+MacZipGlobals   MacZip;
+
+unsigned long count_of_Zippedfiles = 0;
+
+
+/*****************************************************************************/
+/*  Module level Vars                                                        */
+/*****************************************************************************/
+
+static const char MacPathEnd = ':';   /* the Macintosh dir separator */
+
+/*  Inform Progress vars */
+long    estTicksToFinish;
+long    createTime;
+long    updateTicks;
+
+static char *Time_Est_strings[] = {
+        "Zipping Files; Items done:",
+        "More than 24 hours",
+        "More than %s hours",
+        "About %s hours, %s minutes",
+        "About an hour",
+        "Less than an hour",
+        "About %s minutes, %s seconds",
+        "About a minute",
+        "Less than a minute",
+        "About %s seconds",
+        "About a second",
+        "About 1 minute, %s seconds"};
+
+
+
+/*****************************************************************************/
+/*  Prototypes                                                               */
+/*****************************************************************************/
+
+int DoCurrentDir(void);
+
+void DoAboutBox(void);
+void DoQuit(void);
+void DoEventLoop(void);
+
+void ZipInitAllVars(void);
+void UserStop(void);
+Boolean IsZipFile(char *name);
+
+static long EstimateCompletionTime(const long progressMax,
+                            const long progressSoFar, unsigned char percent);
+static void UpdateTimeToComplete(void);
+
+
+
+
+#ifdef USE_SIOUX
+#include <sioux.h>
+void DoWarnUserDupVol( char *FullPath );
+
+/*****************************************************************************/
+/*  Functions                                                                */
+/*****************************************************************************/
+
+/*
+** Standalone Unzip with Metrowerks SIOUX starts here
+**
+*/
+int main(int argc, char **argv)
+{
+    int return_code;
+
+    SIOUXSettings.asktosaveonclose = FALSE;
+    SIOUXSettings.showstatusline = TRUE;
+
+    SIOUXSettings.columns = 100;
+    SIOUXSettings.rows    = 40;
+
+    /* 30 = MacZip Johnny Lee's; 40 = new (my) MacZip */
+    MacZip.MacZipMode = NewZipMode_EF;
+
+    argc = ccommand(&argv);
+    if (verbose) PrintArguments(argc, argv);
+
+    ZipInitAllVars();
+
+    return_code = zipmain(argc, argv);
+
+    if (verbose) printf("\n\n Finish");
+    return return_code;
+}
+
+
+
+/*
+** SIOUX needs no extra event handling
+**
+*/
+
+void UserStop(void)
+{
+};
+
+
+
+
+/*
+** Password enter function '*' printed for each char
+**
+*/
+
+int macgetch(void)
+{
+    WindowPtr whichWindow;
+    EventRecord theEvent;
+    char c;                     /* one-byte buffer for read() to use */
+
+    do {
+        SystemTask();
+        if (!GetNextEvent(everyEvent, &theEvent))
+            theEvent.what = nullEvent;
+        else {
+            switch (theEvent.what) {
+            case keyDown:
+                c = theEvent.message & charCodeMask;
+                break;
+            case mouseDown:
+                if (FindWindow(theEvent.where, &whichWindow) ==
+                    inSysWindow)
+                    SystemClick(&theEvent, whichWindow);
+                break;
+            case updateEvt:
+                break;
+            }
+        }
+    } while (theEvent.what != keyDown);
+
+    printf("*");
+    fflush(stdout);
+
+    return (int)c;
+}
+
+#endif
+
+
+
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+/*
+** Print Compilers version and compile time/date
+**
+*/
+
+void version_local()
+{
+/* prints e.g:
+Compiled with  Metrowerks CodeWarrior version 2000 for  PowerPC Processor
+ compile time:  Feb  4 1998 17:49:49.
+*/
+
+static ZCONST char CompiledWith[] =
+                        "\n\nCompiled with %s %x for %s \n %s %s %s.\n\n";
+
+    printf(CompiledWith,
+
+
+#ifdef __MWERKS__
+      " Metrowerks CodeWarrior version", __MWERKS__,
+#endif
+
+
+#ifdef __MC68K__
+      " MC68K Processor",
+#else
+      " PowerPC Processor",
+#endif
+
+#ifdef __DATE__
+      "compile time: ", __DATE__, __TIME__
+#else
+      "", "", ""
+#endif
+    );
+} /* end function version_local() */
+
+
+
+
+
+/*
+** Deletes a dir if the switch '-m' is used
+**
+*/
+
+int deletedir(char *path)
+{
+static char     Num = 0;
+static FSSpec   trashfolder;
+static Boolean  FirstCall = true;
+static Boolean  Immediate_File_Deletion = false;
+OSErr           err;
+FSSpec          dirToDelete;
+char            currpath[NAME_MAX], *envptr;
+CInfoPBRec      fpb;
+
+/* init this function */
+if ((path == NULL) ||
+    (strlen(path) == 0))
+    {
+    Num = 0;
+    FirstCall = true;
+    return -1;
+    }
+
+UserStop();
+
+GetCompletePath(currpath,path,&dirToDelete, &err);
+
+if (FirstCall == true)
+    {
+    FirstCall = false;
+    envptr = getenv("Immediate_File_Deletion");
+    if (!(envptr == (char *)NULL || *envptr == '\0'))
+        {
+        if (stricmp(envptr,"yes") == 0)
+            Immediate_File_Deletion = true;
+        else
+            Immediate_File_Deletion = false;
+        }
+    err = FSpFindFolder(dirToDelete.vRefNum, kTrashFolderType,
+                      kDontCreateFolder,&trashfolder);
+    printerr("FSpFindFolder:",err,err,__LINE__,__FILE__,path);
+    }
+
+    fpb.dirInfo.ioNamePtr   = dirToDelete.name;
+    fpb.dirInfo.ioVRefNum   = dirToDelete.vRefNum;
+    fpb.dirInfo.ioDrDirID   = dirToDelete.parID;
+    fpb.dirInfo.ioFDirIndex = 0;
+
+    err = PBGetCatInfoSync(&fpb);
+    printerr("PBGetCatInfo deletedir ", err, err,
+             __LINE__, __FILE__, "");
+
+if (fpb.dirInfo.ioDrNmFls > 0)
+    {
+    return 0;  /* do not move / delete folders which are not empty */
+    }
+
+if (Immediate_File_Deletion)
+    {
+    err = FSpDelete(&dirToDelete);
+    return err;
+    }
+
+err = CatMove (dirToDelete.vRefNum, dirToDelete.parID,
+               dirToDelete.name, trashfolder.parID, trashfolder.name);
+
+/* -48 = file is already existing so we have to rename it before
+   moving the file */
+if (err == -48)
+    {
+    Num++;
+    if (dirToDelete.name[0] >= 28) /* cut foldername if to long */
+        dirToDelete.name[0] = 28;
+    P2CStr(dirToDelete.name);
+    sprintf(currpath,"%s~%d",(char *)dirToDelete.name,Num);
+    C2PStr(currpath);
+    C2PStr((char *)dirToDelete.name);
+    err = HRename (dirToDelete.vRefNum, dirToDelete.parID,
+                   dirToDelete.name, (unsigned char *) currpath);
+
+    err = CatMove (dirToDelete.vRefNum, dirToDelete.parID,
+                   (unsigned char *) currpath, trashfolder.parID,
+                   trashfolder.name);
+    }
+
+return err;
+}
+
+
+
+
+/*
+** Set the file-type so the archive will get the correct icon, type
+** and creator code.
+*/
+
+void setfiletype(char *new_f, unsigned long Creator, unsigned long Type)
+{
+OSErr   err;
+
+if (strcmp(zipfile, new_f) == 0)
+    err = FSpChangeCreatorType(&MacZip.ZipFileSpec, Creator, Type);
+printerr("FSpChangeCreatorType:", err, err, __LINE__, __FILE__, new_f);
+
+return;
+}
+
+
+
+
+
+/*
+** Convert the external (native) filename into Zip's internal Unix compatible
+** name space.
+*/
+
+char *ex2in(char *externalFilen, int isdir, int *pdosflag)
+/* char *externalFilen     external file name */
+/* int isdir               input: externalFilen is a directory */
+/* int *pdosflag           output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *internalFilen;              /* internal file name (malloc'ed) */
+  char *t;                          /* shortened name */
+  char *Pathname;
+  char buffer[NAME_MAX];
+  int dosflag;
+
+  AssertStr(externalFilen, externalFilen)
+  AssertBool(isdir,"")
+
+  dosflag = dosify;  /* default for non-DOS and non-OS/2 */
+
+  /* Find starting point in name before doing malloc */
+  for (t = externalFilen; *t == PATH_END; t++)
+      ;
+
+  if (!MacZip.StoreFullPath)
+        {
+        Pathname = StripPartialDir(buffer, MacZip.SearchDir,t);
+        }
+  else
+        {
+        Pathname = t;
+        }
+
+  /* Make changes, if any, to the copied name (leave original intact) */
+  if (!pathput)
+    {
+    t = last(Pathname, PATH_END);
+    }
+  else t = Pathname;
+
+  /* Malloc space for internal name and copy it */
+  if ((internalFilen = malloc(strlen(t) + 10 + strlen(ResourceMark) )) == NULL)
+    return NULL;
+
+  sstrcpy(internalFilen, t);
+
+    /* we have to eliminate illegal chars:
+     * The name space for Mac filenames and Zip filenames (unix style names)
+     * do both include all printable extended-ASCII characters.  The only
+     * difference we have to take care of is the single special character
+     * used as path delimiter:
+     * ':' on MacOS and '/' on Unix and '\' on Dos.
+     * So, to convert between Mac filenames and Unix filenames without any
+     * loss of information, we simply interchange ':' and '/'.  Additionally,
+     * we try to convert the coding of the extended-ASCII characters into
+     * InfoZip's standard ISO 8859-1 codepage table.
+     */
+  MakeCompatibleString(internalFilen, ':', '/', '/', ':',
+                       MacZip.CurrTextEncodingBase);
+
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+
+  if (isdir)
+    {
+    return internalFilen;      /* avoid warning on unused variable */
+    }
+
+  if (dosify)
+    {
+    msname(internalFilen);
+    printf("\n ex2in: %s",internalFilen);
+    }
+
+  return internalFilen;
+}
+
+
+
+/*
+** Collect all filenames. Go through all directories
+**
+*/
+
+int wild(char *Pathpat)
+                /* path/pattern to match */
+/* If not in exclude mode, expand the pattern based on the contents of the
+   file system.  Return an error code in the ZE_ class. */
+{
+FSSpec Spec;
+char fullpath[NAME_MAX];
+OSErr   err;
+
+AssertStr(Pathpat, Pathpat);
+
+if (noisy) printf("%s \n\n",GetZipVersionsInfo());
+
+if (extra_fields == 0)
+    {
+    MacZip.DataForkOnly = true;
+    }
+
+/* for switch '-R' -> '.' means current dir */
+if (strcmp(Pathpat,".") == 0) sstrcpy(Pathpat,"*");
+
+sstrcpy(MacZip.Pattern,Pathpat);
+
+if (recurse)
+    {
+    MacZip.StoreFoldersAlso = true;
+    MacZip.SearchLevels = 0; /* if 0 we aren't checking levels */
+    }
+else
+    {
+    MacZip.StoreFoldersAlso = false;
+    MacZip.SearchLevels = 1;
+    }
+
+/* make complete path */
+GetCompletePath(fullpath, MacZip.Pattern, &Spec,&err);
+err = PrintUserHFSerr((err != -43) && (err != 0), err, MacZip.Pattern);
+printerr("GetCompletePath:", err, err, __LINE__, __FILE__, fullpath);
+
+/* extract the filepattern */
+GetFilename(MacZip.Pattern, fullpath);
+
+/* extract Path and get FSSpec of search-path */
+/* get FSSpec of search-path  ; we need a dir to start
+   searching for filenames */
+TruncFilename(MacZip.SearchDir, fullpath);
+GetCompletePath(MacZip.SearchDir, MacZip.SearchDir, &Spec,&err);
+
+if (noisy) {
+    if (MacZip.SearchLevels == 0)
+        {
+        printf("\nSearch Pattern: [%s]   Levels: all", MacZip.Pattern);
+        }
+    else
+        {
+        printf("\nSearch Pattern: [%s]   Levels: %d", MacZip.Pattern,
+               MacZip.SearchLevels);
+        }
+    printf("\nSearch Path:    [%s]", MacZip.SearchDir);
+    printf("\nZip-File:       [%s] \n",MacZip.ZipFullPath);
+
+}
+
+/* we are working only with pathnames;
+ * this can cause big problems on a mac ...
+ */
+if (CheckMountedVolumes(MacZip.SearchDir) > 1)
+    DoWarnUserDupVol(MacZip.SearchDir);
+
+/* start getting all filenames */
+err = FSpRecurseDirectory(&Spec, MacZip.SearchLevels);
+printerr("FSpRecurseDirectory:", err, err, __LINE__, __FILE__, "");
+
+return ZE_OK;
+}
+
+
+
+/*
+** Convert the internal filename into a external (native).
+** The user will see this modified filename.
+** For more performance:
+** I do not completly switch back to the native macos filename.
+** The user will still see directory separator '/' and the converted
+** charset.
+*/
+
+char *in2ex(char *n)    /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+
+  AssertStr(n,n)
+
+  if ((x = malloc(strlen(n) + 1)) == NULL)
+    return NULL;
+
+  RfDfFilen2Real(x, n, MacZip.MacZipMode, MacZip.DataForkOnly,
+                 &MacZip.CurrentFork);
+
+  return x;
+}
+
+
+
+
+/*
+** Process on filenames. This function will be called to collect
+** the filenames.
+*/
+
+int procname(char *filename,         /* name to process */
+             int caseflag)           /* true to force case-sensitive match
+                                        (always false on a Mac) */
+/* Process a name .  Return
+   an error code in the ZE_ class. */
+{
+  int rc;                /* matched flag */
+
+AssertBool(caseflag,"caseflag")
+AssertStr(filename,filename)
+
+        /* add or remove name of file */
+rc = newname(filename, MacZip.isDirectory, caseflag);
+
+return rc;
+}
+
+
+
+
+ulg filetime(
+char *f,                /* name of file to get info on */
+ulg *a,                 /* return value: file attributes */
+long *n,                /* return value: file size */
+iztimes *t)             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+
+  AssertStr(f,f)
+
+  if (strlen(f) == 0) return 0;
+
+  if (SSTAT(f, &s) != 0)
+             /* Accept about any file kind including directories
+              * (stored with trailing : with -r option)
+              */
+    return 0;
+
+  if (a != NULL) {
+    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
+    if (MacZip.isDirectory) {
+      *a |= MSDOS_DIR_ATTR;
+    }
+  }
+  if (n != NULL)
+    *n = (s.st_mode & UNX_IFMT) == UNX_IFREG ? s.st_size : -1L;
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = s.st_ctime;   /* on Mac, st_ctime contains creation time! */
+  }
+
+  return unix2dostime(&s.st_mtime);
+}
+
+
+
+void stamp(char *f, ulg d)
+/* char *f;                name of file to change */
+/* ulg d;                  dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+  time_t u[2];          /* argument for utime() */
+
+f = f;
+
+  /* Convert DOS time to time_t format in u */
+
+  u[0] = u[1] = dos2unixtime(d);
+/*  utime(f, u);  */
+}
+
+
+
+
+/*
+**  return only the longest part of the path:
+**  second parameter: Volume:test folder:second folder:
+**  third parameter:  Volume:test folder:second folder:third folder:file
+**  result will be:   third folder:file
+**  first parameter:  contains string buffer that will be used to prepend
+**                    the "resource mark" part in front of the result when
+**                    a resource fork is processed in "M3" mode.
+**
+*/
+
+char *StripPartialDir(char *CompletePath,
+                      const char *PartialPath, const char *FullPath)
+{
+const char *tmpPtr1 = PartialPath;
+const char *tmpPtr2 = FullPath;
+int     result;
+
+Assert_it(CompletePath,"StripPartialDir","")
+AssertStrNoOverlap(FullPath,PartialPath,PartialPath)
+
+if (MacZip.DataForkOnly)
+        {
+        tmpPtr2 += strlen(tmpPtr1);
+        return (char *)tmpPtr2;
+        }
+
+switch (MacZip.MacZipMode)
+    {
+    case JohnnyLee_EF:
+        {
+        tmpPtr2 += strlen(tmpPtr1);
+        return (char *)tmpPtr2;
+        break;
+        }
+
+    case NewZipMode_EF:
+        {           /* determine Fork type */
+        result = strncmp(FullPath, ResourceMark, sizeof(ResourceMark)-2);
+        if (result != 0)
+            {                               /* data fork  */
+            MacZip.CurrentFork = DataFork;
+            tmpPtr2 += strlen(tmpPtr1);
+             return (char *)tmpPtr2;
+            }
+        else
+            {                                /* resource fork  */
+            MacZip.CurrentFork = ResourceFork;
+            sstrcpy(CompletePath, ResourceMark);
+            tmpPtr2 += strlen(tmpPtr1);
+            tmpPtr2 += sizeof(ResourceMark);
+            sstrcat(CompletePath, tmpPtr2);
+            return (char *)CompletePath;
+            }
+        break;
+        }
+    }
+
+ return NULL;    /* function should never reach this point */
+}
+
+
+
+
+/*
+** Init all global variables
+** Must be called for each zip-run
+*/
+
+void ZipInitAllVars(void)
+{
+getcwd(MacZip.CurrentPath, sizeof(MacZip.CurrentPath));
+/* MacZip.MacZipMode = JohnnyLee_EF;     */
+MacZip.MacZipMode = NewZipMode_EF;
+
+MacZip.DataForkOnly = false;
+MacZip.CurrentFork = NoFork;
+
+MacZip.StoreFoldersAlso = false;
+
+MacZip.FoundFiles = 0;
+MacZip.FoundDirectories = 0;
+MacZip.RawCountOfItems = 0;
+MacZip.BytesOfData = 0;
+
+MacZip.StoreFullPath = false;
+MacZip.StatingProgress = false;
+MacZip.IncludeInvisible = false;
+
+MacZip.isMacStatValid = false;
+
+MacZip.CurrTextEncodingBase = FontScript();
+
+MacZip.HaveGMToffset = false;
+
+createTime = TickCount();
+estTicksToFinish = -1;
+updateTicks = 0;
+
+/* init some functions */
+IsZipFile(NULL);
+
+destroy(NULL);
+deletedir(NULL);
+ShowCounter(true);
+
+extra_fields = 1;
+error_level = 0;
+count_of_Zippedfiles = 0;
+}
+
+
+
+
+/*
+** Get the findercomment and store it as file-comment in the Zip-file
+**
+*/
+char *GetComment(char *filename)
+{
+OSErr       err;
+static char buffer[NAME_MAX];
+char buffer2[NAME_MAX];
+char *tmpPtr;
+
+if (filename == NULL) return NULL;
+
+    /* now we can convert Unix-Path in HFS-Path */
+for (tmpPtr = filename; *tmpPtr; tmpPtr++)
+    if (*tmpPtr == '/')
+      *tmpPtr = ':';
+
+if (MacZip.StoreFullPath)
+    {  /* filename is already a fullpath */
+    sstrcpy(buffer,filename);
+    }
+else
+    {  /* make a fullpath */
+    sstrcpy(buffer,MacZip.SearchDir);
+    sstrcat(buffer,filename);
+    }
+
+/* make fullpath and get FSSpec */
+/* Unfortunately: I get only the converted filename here */
+/* so filenames with extended characters can not be found  */
+GetCompletePath(buffer2,buffer, &MacZip.fileSpec, &err);
+printerr("GetCompletePath:",(err != -43) && (err != -120) && (err != 0) ,
+          err,__LINE__,__FILE__,buffer);
+
+err = FSpDTGetComment(&MacZip.fileSpec, (unsigned char *) buffer);
+printerr("FSpDTGetComment:", (err != -5012) && (err != 0), err,
+         __LINE__, __FILE__, filename);
+P2CStr((unsigned char *) buffer);
+if (err == -5012) return NULL;  /* no finder-comments found */
+
+if (noisy) printf("\n%32s -> %s",filename, buffer);
+/*
+Beside the script change we need only to change 0x0d in 0x0a
+so the last two arguments are not needed and does nothing.
+*/
+MakeCompatibleString(buffer, 0x0d, 0x0a, ' ', ' ',
+                     MacZip.CurrTextEncodingBase);
+
+return buffer;
+}
+
+
+
+
+/*
+** Print a progress indicator for stating the files
+**
+*/
+
+void PrintStatProgress(char *msg)
+{
+
+if (!noisy) return;     /* do no output if noisy is false */
+
+MacZip.StatingProgress = true;
+
+if (strcmp(msg,"done") == 0)
+    {
+    MacZip.StatingProgress = false;
+    printf("\n ... done \n\n");
+    }
+else printf("\n %s",msg);
+
+}
+
+
+
+
+void InformProgress(const long progressMax, const long progressSoFar )
+{
+int curr_percent;
+char no_time[5] = "...";
+
+curr_percent = percent(progressMax, progressSoFar);
+
+if (curr_percent < 95)
+    {
+    estTicksToFinish = EstimateCompletionTime(progressMax,
+                                                  progressSoFar, curr_percent);
+    }
+else
+    {
+    rightStatusString(no_time);
+    leftStatusString(no_time);
+    }
+
+updateTicks = TickCount() + 60;
+return;
+}
+
+
+void ShowCounter(Boolean reset)
+{
+static char statusline[100];
+static unsigned long filecount = 0;
+
+if (reset)
+        {
+        filecount = 0;
+        return;
+        }
+
+if (noisy)
+    {
+    sprintf(statusline, "%6d", filecount++);
+    rightStatusString(statusline);
+    }
+}
+
+
+static long EstimateCompletionTime(const long progressMax,
+                                const long progressSoFar,
+                                unsigned char curr_percent)
+{
+    long  max = progressMax, value = progressSoFar;
+    static char buf[100];
+    unsigned long ticksTakenSoFar = TickCount() - createTime;
+    float currentRate = (float) ticksTakenSoFar / (float) value;
+    long  newEst = (long)( currentRate * (float)( max - value ));
+
+    sprintf(buf, "%d [%d%%]",progressSoFar, curr_percent);
+    rightStatusString(buf);
+
+    estTicksToFinish = newEst;
+
+    UpdateTimeToComplete();
+
+return estTicksToFinish;
+}
+
+
+
+
+
+static void UpdateTimeToComplete(void)
+{
+    short       days, hours, minutes, seconds;
+    char    estStr[255];
+    Str15   xx, yy;
+    short   idx = 0;
+
+    if ( estTicksToFinish == -1 )
+        return;
+
+    days    =   estTicksToFinish / 5184000L;
+    hours   = ( estTicksToFinish - ( days * 5184000L )) / 216000L;
+    minutes = ( estTicksToFinish - ( days * 5184000L ) -
+              ( hours * 216000L )) / 3600L;
+    seconds = ( estTicksToFinish - ( days * 5184000L ) -
+              ( hours * 216000L ) - ( minutes * 3600L )) / 60L;
+
+        xx[0] = 0;
+        yy[0] = 0;
+
+        if ( days )
+        {
+            /* "more than 24 hours" */
+
+            idx = 1;
+            goto setEstTimeStr;
+        }
+
+        if ( hours >= 8 )
+        {
+            /* "more than x hours" */
+
+            NumToString( hours, xx );
+            idx = 2;
+            goto setEstTimeStr;
+        }
+
+        if ( estTicksToFinish > 252000L  )      /* > 1hr, 10 minutes */
+        {
+            /* "about x hours, y minutes" */
+
+            NumToString( hours, xx );
+            NumToString( minutes, yy );
+            idx = 3;
+            goto setEstTimeStr;
+        }
+
+        if ( estTicksToFinish > 198000L )   /* > 55 minutes */
+        {
+            /* "about an hour" */
+            idx = 4;
+            goto setEstTimeStr;
+        }
+
+        if ( estTicksToFinish > 144000L )   /* > 40 minutes */
+        {
+            /* "less than an hour" */
+
+            idx = 5;
+            goto setEstTimeStr;
+        }
+
+        if ( estTicksToFinish > 4200L )     /* > 1 minute, 10 sec */
+        {
+            /* "about x minutes, y seconds */
+
+            NumToString( minutes, xx );
+            NumToString( seconds, yy );
+
+            if ( minutes == 1 )
+                idx = 11;
+            else
+                idx = 6;
+            goto setEstTimeStr;
+        }
+
+        if ( estTicksToFinish > 3000L )     /* > 50 seconds */
+        {
+            /* "about a minute" */
+
+            idx = 7;
+            goto setEstTimeStr;
+        }
+
+        if ( estTicksToFinish > 1500L )     /* > 25 seconds */
+        {
+            /* "less than a minute" */
+
+            idx = 8;
+            goto setEstTimeStr;
+        }
+
+        if ( estTicksToFinish > 120L )      /* > 2 seconds */
+        {
+            NumToString( seconds, xx );
+            idx = 9;
+            goto setEstTimeStr;
+        }
+
+        idx = 10;
+
+    setEstTimeStr:
+        sprintf(estStr,Time_Est_strings[idx],P2CStr(xx),P2CStr(yy));
+        leftStatusString((char *)estStr);
+}
+
+
+
+
+
+/*
+** Just return the zip version
+**
+*/
+
+char *GetZipVersionsInfo(void)
+{
+static char ZipVersion[100];
+
+sprintf(ZipVersion, "Zip Module\n%d.%d%d%s of %s", Z_MAJORVER, Z_MINORVER,
+        Z_PATCHLEVEL, Z_BETALEVEL, REVDATE);
+
+return ZipVersion;
+}
+
+
+
+
+#ifndef USE_SIOUX
+
+/*
+** Just return the copyright message
+**
+*/
+
+char *GetZipCopyright(void)
+{
+static char CopyR[300];
+
+sstrcpy(CopyR, copyright[0]);
+sstrcat(CopyR, copyright[1]);
+sstrcat(CopyR, "\r\rPlease send bug reports to the authors at\r"\
+              "Zip-Bugs@lists.wku.edu");
+
+return CopyR;
+}
+
+
+
+
+/*
+** Just return the compilers date/time
+**
+*/
+
+char *GetZipVersionLocal(void)
+{
+static char ZipVersionLocal[50];
+
+sprintf(ZipVersionLocal, "[%s %s]", __DATE__, __TIME__);
+
+return ZipVersionLocal;
+}
+
+#endif  /*   #ifndef USE_SIOUX  */
+
+
+
+
diff --git a/macos/source/macstuff.c b/macos/source/macstuff.c
new file mode 100644 (file)
index 0000000..0323607
--- /dev/null
@@ -0,0 +1,1724 @@
+/*
+These Functions were originally part of More Files version 1.4.8
+
+More Files fixes many of the broken or underfunctional
+parts of the file system.
+
+More Files
+
+A collection of File Manager and related routines
+
+by Jim Luther (Apple Macintosh Developer Technical Support Emeritus)
+with significant code contributions by Nitin Ganatra
+(Apple Macintosh Developer Technical Support Emeritus)
+Copyright  1992-1998 Apple Computer, Inc.
+Portions copyright  1995 Jim Luther
+All rights reserved.
+
+The Package "More Files" is distributed under the following
+license terms:
+
+         "You may incorporate this sample code into your
+          applications without restriction, though the
+          sample code has been provided "AS IS" and the
+          responsibility for its operation is 100% yours.
+          However, what you are not permitted to do is to
+          redistribute the source as "DSC Sample Code" after
+          having made changes. If you're going to
+          redistribute the source, we require that you make
+          it clear in the source that the code was descended
+          from Apple Sample Code, but that you've made
+          changes."
+
+
+The following changes are made by Info-ZIP:
+
+- The only changes are made by pasting the functions
+  (mostly found in MoreFilesExtras.c / MoreFiles.c)
+  directly into macstuff.c / macstuff.h and slightly
+  reformatting the text (replacement of TABs by spaces,
+  removal/replacement of non-ASCII characters).
+  The code itself is NOT changed.
+
+This file has been modified by Info-ZIP for use in MacZip.
+This file is NOT part of the original package More Files.
+
+More Files can be found on the MetroWerks CD and Developer CD from
+Apple. You can also download the latest version from:
+
+    http://members.aol.com/JumpLong/#MoreFiles
+
+Jim Luther's Home-page:
+    http://members.aol.com/JumpLong/
+
+
+*/
+
+#include <string.h>
+
+
+#include "macstuff.h"
+
+
+
+extern int errno;
+
+static  OSErr   GetCommentFromDesktopFile(short vRefNum,
+                                          long dirID,
+                                          ConstStr255Param name,
+                                          Str255 comment);
+
+static  OSErr   GetCommentID(short vRefNum,
+                             long dirID,
+                             ConstStr255Param name,
+                             short *commentID);
+
+static  OSErr   GetDesktopFileName(short vRefNum,
+                                   Str255 desktopName);
+
+
+enum
+{
+    kBNDLResType    = 'BNDL',
+    kFREFResType    = 'FREF',
+    kIconFamResType = 'ICN#',
+    kFCMTResType    = 'FCMT',
+    kAPPLResType    = 'APPL'
+};
+
+
+/*****************************************************************************/
+
+/*
+**  File Manager FSp calls
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   FSMakeFSSpecCompat(short vRefNum,
+                                   long dirID,
+                                   ConstStr255Param fileName,
+                                   FSSpec *spec)
+{
+    OSErr   result;
+
+#if !__MACOSSEVENORLATER
+    if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
+    {
+        Boolean isDirectory;
+
+        result = GetObjectLocation(vRefNum, dirID, fileName,
+                                    &(spec->vRefNum), &(spec->parID), spec->name,
+                                    &isDirectory);
+    }
+    else
+#endif  /* !__MACOSSEVENORLATER */
+    {
+     /* Let the file system create the FSSpec if it can since it does the job */
+     /* much more efficiently than I can. */
+        result = FSMakeFSSpec(vRefNum, dirID, fileName, spec);
+
+        /* Fix a bug in Macintosh PC Exchange's MakeFSSpec code where 0 is */
+        /* returned in the parID field when making an FSSpec to the volume's */
+        /* root directory by passing a full pathname in MakeFSSpec's */
+        /* fileName parameter. Fixed in Mac OS 8.1 */
+        if ( (result == noErr) && (spec->parID == 0) )
+            spec->parID = fsRtParID;
+    }
+    return ( result );
+}
+
+
+/*****************************************************************************/
+/* FSHasFSSpecCalls returns true if the file system provides FSSpec calls. */
+
+#if !__MACOSSEVENORLATER
+static  Boolean FSHasFSSpecCalls(void)
+{
+    long            response;
+#if !GENERATENODATA
+    static Boolean  tested = false;
+    static Boolean  result = false;
+#else
+    Boolean result = false;
+#endif
+
+#if !GENERATENODATA
+    if ( !tested )
+    {
+        tested = true;
+#endif
+        if ( Gestalt(gestaltFSAttr, &response) == noErr )
+        {
+            result = ((response & (1L << gestaltHasFSSpecCalls)) != 0);
+        }
+#if !GENERATENODATA
+    }
+#endif
+    return ( result );
+}
+#endif  /* !__MACOSSEVENORLATER */
+
+
+
+/*****************************************************************************/
+/* QTHasFSSpecCalls returns true if QuickTime provides FSSpec calls */
+/* except for FSpExchangeFiles. */
+
+#if !__MACOSSEVENORLATER
+static  Boolean QTHasFSSpecCalls(void)
+{
+    long            response;
+#if !GENERATENODATA
+    static Boolean  tested = false;
+    static Boolean  result = false;
+#else
+    Boolean result = false;
+#endif
+
+#if !GENERATENODATA
+    if ( !tested )
+    {
+        tested = true;
+#endif
+        result = (Gestalt(gestaltQuickTimeVersion, &response) == noErr);
+#if !GENERATENODATA
+    }
+#endif
+    return ( result );
+}
+#endif  /* !__MACOSSEVENORLATER */
+
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FSpGetDefaultDir --
+ *
+ *  This function gets the current default directory.
+ *
+ * Results:
+ *  The provided FSSpec is changed to point to the "default"
+ *  directory.  The function returns what ever errors
+ *  FSMakeFSSpecCompat may encounter.
+ *
+ * Side effects:
+ *  None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int FSpGetDefaultDir(FSSpecPtr dirSpec) /* On return the default directory. */
+{
+    OSErr err;
+    short vRefNum = 0;
+    long int dirID = 0;
+
+    err = HGetVol(NULL, &vRefNum, &dirID);
+
+    if (err == noErr) {
+    err = FSMakeFSSpecCompat(vRefNum, dirID, (ConstStr255Param) NULL,
+        dirSpec);
+    }
+
+    return err;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FSpSetDefaultDir --
+ *
+ *  This function sets the default directory to the directory
+ *  pointed to by the provided FSSpec.
+ *
+ * Results:
+ *  The function returns what ever errors HSetVol may encounter.
+ *
+ * Side effects:
+ *  None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int FSpSetDefaultDir(FSSpecPtr dirSpec) /* The new default directory. */
+{
+    OSErr err;
+
+    /*
+     * The following special case is needed to work around a bug
+     * in the Macintosh OS.  (Acutally PC Exchange.)
+     */
+
+    if (dirSpec->parID == fsRtParID) {
+    err = HSetVol(NULL, dirSpec->vRefNum, fsRtDirID);
+    } else {
+    err = HSetVol(dirSpec->name, dirSpec->vRefNum, dirSpec->parID);
+    }
+
+    return err;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FSpFindFolder --
+ *
+ *  This function is a version of the FindFolder function that
+ *  returns the result as a FSSpec rather than a vRefNum and dirID.
+ *
+ * Results:
+ *  Results will be simaler to that of the FindFolder function.
+ *
+ * Side effects:
+ *  None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+OSErr
+FSpFindFolder(
+    short vRefNum,      /* Volume reference number. */
+    OSType folderType,      /* Folder type taken by FindFolder. */
+    Boolean createFolder,   /* Should we create it if non-existant. */
+    FSSpec *spec)       /* Pointer to resulting directory. */
+{
+    short foundVRefNum;
+    long foundDirID;
+    OSErr err;
+
+    err = FindFolder(vRefNum, folderType, createFolder,
+        &foundVRefNum, &foundDirID);
+    if (err != noErr) {
+    return err;
+    }
+
+    err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, "\p", spec);
+    return err;
+}
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FSpPathFromLocation --
+ *
+ *  This function obtains a full path name for a given macintosh
+ *  FSSpec.  Unlike the More Files function FSpGetFullPath, this
+ *  function will return a C string in the Handle.  It also will
+ *  create paths for FSSpec that do not yet exist.
+ *
+ * Results:
+ *  OSErr code.
+ *
+ * Side effects:
+ *  None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+OSErr
+FSpPathFromLocation(
+    FSSpec *spec,       /* The location we want a path for. */
+    int *length,        /* Length of the resulting path. */
+    Handle *fullPath)       /* Handle to path. */
+{
+    OSErr err;
+    FSSpec tempSpec;
+    CInfoPBRec pb;
+
+    *fullPath = NULL;
+
+    /*
+     * Make a copy of the input FSSpec that can be modified.
+     */
+    BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
+
+    if (tempSpec.parID == fsRtParID) {
+    /*
+     * The object is a volume.  Add a colon to make it a full
+     * pathname.  Allocate a handle for it and we are done.
+     */
+    tempSpec.name[0] += 2;
+    tempSpec.name[tempSpec.name[0] - 1] = ':';
+    tempSpec.name[tempSpec.name[0]] = '\0';
+
+    err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
+    } else {
+    /*
+     * The object isn't a volume.  Is the object a file or a directory?
+     */
+    pb.dirInfo.ioNamePtr = tempSpec.name;
+    pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
+    pb.dirInfo.ioDrDirID = tempSpec.parID;
+    pb.dirInfo.ioFDirIndex = 0;
+    err = PBGetCatInfoSync(&pb);
+
+    if ((err == noErr) || (err == fnfErr)) {
+        /*
+         * If the file doesn't currently exist we start over.  If the
+         * directory exists everything will work just fine.  Otherwise we
+         * will just fail later.  If the object is a directory, append a
+         * colon so full pathname ends with colon.
+         */
+        if (err == fnfErr) {
+        BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
+        } else if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) {
+        tempSpec.name[0] += 1;
+        tempSpec.name[tempSpec.name[0]] = ':';
+        }
+
+        /*
+         * Create a new Handle for the object - make it a C string.
+         */
+        tempSpec.name[0] += 1;
+        tempSpec.name[tempSpec.name[0]] = '\0';
+        err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
+        if (err == noErr) {
+        /*
+         * Get the ancestor directory names - loop until we have an
+         * error or find the root directory.
+         */
+        pb.dirInfo.ioNamePtr = tempSpec.name;
+        pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
+        pb.dirInfo.ioDrParID = tempSpec.parID;
+        do {
+            pb.dirInfo.ioFDirIndex = -1;
+            pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
+            err = PBGetCatInfoSync(&pb);
+            if (err == noErr) {
+            /*
+             * Append colon to directory name and add
+             * directory name to beginning of fullPath.
+             */
+            ++tempSpec.name[0];
+            tempSpec.name[tempSpec.name[0]] = ':';
+
+            (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1],
+                tempSpec.name[0]);
+            err = MemError();
+            }
+        } while ( (err == noErr) &&
+            (pb.dirInfo.ioDrDirID != fsRtDirID) );
+        }
+    }
+    }
+
+    /*
+     * On error Dispose the handle, set it to NULL & return the err.
+     * Otherwise, set the length & return.
+     */
+    if (err == noErr) {
+    *length = GetHandleSize(*fullPath) - 1;
+    } else {
+    if ( *fullPath != NULL ) {
+        DisposeHandle(*fullPath);
+    }
+    *fullPath = NULL;
+    *length = 0;
+    }
+
+    return err;
+}
+
+
+
+/*****************************************************************************/
+
+pascal  OSErr   FSpGetDirectoryID(const FSSpec *spec,
+                                  long *theDirID,
+                                  Boolean *isDirectory)
+{
+    return ( GetDirectoryID(spec->vRefNum, spec->parID, spec->name,
+             theDirID, isDirectory) );
+}
+
+
+/*****************************************************************************/
+
+pascal  OSErr   GetDirectoryID(short vRefNum,
+                               long dirID,
+                               ConstStr255Param name,
+                               long *theDirID,
+                               Boolean *isDirectory)
+{
+    CInfoPBRec pb;
+    OSErr error;
+
+    error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
+    if ( error == noErr )
+    {
+        *isDirectory = (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0;
+        if ( *isDirectory )
+        {
+            *theDirID = pb.dirInfo.ioDrDirID;
+        }
+        else
+        {
+            *theDirID = pb.hFileInfo.ioFlParID;
+        }
+    }
+
+    return ( error );
+}
+
+
+/*****************************************************************************/
+
+pascal  OSErr GetCatInfoNoName(short vRefNum,
+                               long dirID,
+                               ConstStr255Param name,
+                               CInfoPBPtr pb)
+{
+    Str31 tempName;
+    OSErr error;
+
+    /* Protection against File Sharing problem */
+    if ( (name == NULL) || (name[0] == 0) )
+    {
+        tempName[0] = 0;
+        pb->dirInfo.ioNamePtr = tempName;
+        pb->dirInfo.ioFDirIndex = -1;   /* use ioDirID */
+    }
+    else
+    {
+        pb->dirInfo.ioNamePtr = (StringPtr)name;
+        pb->dirInfo.ioFDirIndex = 0;    /* use ioNamePtr and ioDirID */
+    }
+    pb->dirInfo.ioVRefNum = vRefNum;
+    pb->dirInfo.ioDrDirID = dirID;
+    error = PBGetCatInfoSync(pb);
+    pb->dirInfo.ioNamePtr = NULL;
+    return ( error );
+}
+
+
+
+/*****************************************************************************/
+
+pascal  OSErr   GetObjectLocation(short vRefNum,
+                                  long dirID,
+                                  ConstStr255Param pathname,
+                                  short *realVRefNum,
+                                  long *realParID,
+                                  Str255 realName,
+                                  Boolean *isDirectory)
+{
+    OSErr error;
+    CInfoPBRec pb;
+    Str255 tempPathname;
+
+    /* clear results */
+    *realVRefNum = 0;
+    *realParID = 0;
+    realName[0] = 0;
+
+    /*
+    **  Get the real vRefNum
+    */
+    error = DetermineVRefNum(pathname, vRefNum, realVRefNum);
+    if ( error == noErr )
+    {
+        /*
+        **  Determine if the object already exists and if so,
+        **  get the real parent directory ID if it's a file
+        */
+
+        /* Protection against File Sharing problem */
+        if ( (pathname == NULL) || (pathname[0] == 0) )
+        {
+            tempPathname[0] = 0;
+            pb.hFileInfo.ioNamePtr = tempPathname;
+            pb.hFileInfo.ioFDirIndex = -1;  /* use ioDirID */
+        }
+        else
+        {
+            pb.hFileInfo.ioNamePtr = (StringPtr)pathname;
+            pb.hFileInfo.ioFDirIndex = 0;   /* use ioNamePtr and ioDirID */
+        }
+        pb.hFileInfo.ioVRefNum = vRefNum;
+        pb.hFileInfo.ioDirID = dirID;
+        error = PBGetCatInfoSync(&pb);
+        if ( error == noErr )
+        {
+            /*
+            **  The file system object is present and we have the file's
+            **  real parID
+            */
+
+            /*  Is it a directory or a file? */
+            *isDirectory = (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0;
+            if ( *isDirectory )
+            {
+                /*
+                **  It's a directory, get its name and parent dirID, and then
+                **  we're done
+                */
+
+                pb.dirInfo.ioNamePtr = realName;
+                pb.dirInfo.ioVRefNum = *realVRefNum;
+                /* pb.dirInfo.ioDrDirID already contains the dirID of the
+                   directory object */
+                pb.dirInfo.ioFDirIndex = -1;    /* get information about ioDirID */
+                error = PBGetCatInfoSync(&pb);
+
+                /* get the parent ID here, because the file system can return the */
+                /* wrong parent ID from the last call. */
+                *realParID = pb.dirInfo.ioDrParID;
+            }
+            else
+            {
+                /*
+                **  It's a file - use the parent directory ID from the last call
+                **  to GetCatInfoparse, get the file name, and then we're done
+                */
+                *realParID = pb.hFileInfo.ioFlParID;
+                error = GetFilenameFromPathname(pathname, realName);
+            }
+        }
+        else if ( error == fnfErr )
+        {
+            /*
+            **  The file system object is not present - see if its parent is present
+            */
+
+            /*
+            **  Parse to get the object name from end of pathname
+            */
+            error = GetFilenameFromPathname(pathname, realName);
+
+            /* if we can't get the object name from the end, we can't continue */
+            if ( error == noErr )
+            {
+                /*
+                **  What we want now is the pathname minus the object name
+                **  for example:
+                **  if pathname is 'vol:dir:file' tempPathname becomes 'vol:dir:'
+                **  if pathname is 'vol:dir:file:' tempPathname becomes 'vol:dir:'
+                **  if pathname is ':dir:file' tempPathname becomes ':dir:'
+                **  if pathname is ':dir:file:' tempPathname becomes ':dir:'
+                **  if pathname is ':file' tempPathname becomes ':'
+                **  if pathname is 'file or file:' tempPathname becomes ''
+                */
+
+                /* get a copy of the pathname */
+                BlockMoveData(pathname, tempPathname, pathname[0] + 1);
+
+                /* remove the object name */
+                tempPathname[0] -= realName[0];
+                /* and the trailing colon (if any) */
+                if ( pathname[pathname[0]] == ':' )
+                {
+                    --tempPathname[0];
+                }
+
+                /* OK, now get the parent's directory ID */
+
+                /* Protection against File Sharing problem */
+                pb.hFileInfo.ioNamePtr = (StringPtr)tempPathname;
+                if ( tempPathname[0] != 0 )
+                {
+                    pb.hFileInfo.ioFDirIndex = 0;   /* use ioNamePtr and ioDirID */
+                }
+                else
+                {
+                    pb.hFileInfo.ioFDirIndex = -1;  /* use ioDirID */
+                }
+                pb.hFileInfo.ioVRefNum = vRefNum;
+                pb.hFileInfo.ioDirID = dirID;
+                error = PBGetCatInfoSync(&pb);
+                *realParID = pb.dirInfo.ioDrDirID;
+
+                *isDirectory = false;   /* we don't know what the object is
+                                           really going to be */
+            }
+
+            if ( error != noErr )
+            {
+                error = dirNFErr;   /* couldn't find parent directory */
+            }
+            else
+            {
+                error = fnfErr; /* we found the parent, but not the file */
+            }
+        }
+    }
+
+    return ( error );
+}
+
+
+
+/*****************************************************************************/
+
+pascal  OSErr   DetermineVRefNum(ConstStr255Param pathname,
+                                 short vRefNum,
+                                 short *realVRefNum)
+{
+    HParamBlockRec pb;
+    OSErr error;
+
+    error = GetVolumeInfoNoName(pathname,vRefNum, &pb);
+    if ( error == noErr )
+    {
+        *realVRefNum = pb.volumeParam.ioVRefNum;
+    }
+    return ( error );
+}
+
+
+/*****************************************************************************/
+
+pascal  OSErr   GetFilenameFromPathname(ConstStr255Param pathname,
+                                        Str255 filename)
+{
+    short   index;
+    short   nameEnd;
+    OSErr   error;
+
+    /* default to no filename */
+    filename[0] = 0;
+
+    /* check for no pathname */
+    if ( pathname != NULL )
+    {
+        /* get string length */
+        index = pathname[0];
+
+        /* check for empty string */
+        if ( index != 0 )
+        {
+            /* skip over last trailing colon (if any) */
+            if ( pathname[index] == ':' )
+            {
+                --index;
+            }
+
+            /* save the end of the string */
+            nameEnd = index;
+
+            /* if pathname ends with multiple colons, then this pathname refers */
+            /* to a directory, not a file */
+            if ( pathname[index] != ':' )
+            {
+                /* parse backwards until we find a colon or hit the beginning
+                   of the pathname */
+                while ( (index != 0) && (pathname[index] != ':') )
+                {
+                    --index;
+                }
+
+                /* if we parsed to the beginning of the pathname and the
+                   pathname ended */
+                /* with a colon, then pathname is a full pathname to a volume,
+                   not a file */
+                if ( (index != 0) || (pathname[pathname[0]] != ':') )
+                {
+                    /* get the filename and return noErr */
+                    filename[0] = (char)(nameEnd - index);
+                    BlockMoveData(&pathname[index+1], &filename[1], nameEnd - index);
+                    error = noErr;
+                }
+                else
+                {
+                    /* pathname to a volume, not a file */
+                    error = notAFileErr;
+                }
+            }
+            else
+            {
+                /* directory, not a file */
+                error = notAFileErr;
+            }
+        }
+        else
+        {
+            /* empty string isn't a file */
+            error = notAFileErr;
+        }
+    }
+    else
+    {
+        /* NULL pathname isn't a file */
+        error = notAFileErr;
+    }
+
+    return ( error );
+}
+
+
+
+/*****************************************************************************/
+
+/*
+**  GetVolumeInfoNoName uses pathname and vRefNum to call PBHGetVInfoSync
+**  in cases where the returned volume name is not needed by the caller.
+**  The pathname and vRefNum parameters are not touched, and the pb
+**  parameter is initialized by PBHGetVInfoSync except that ioNamePtr in
+**  the parameter block is always returned as NULL (since it might point
+**  to the local tempPathname).
+**
+**  I noticed using this code in several places, so here it is once.
+**  This reduces the code size of MoreFiles.
+*/
+pascal  OSErr   GetVolumeInfoNoName(ConstStr255Param pathname,
+                                    short vRefNum,
+                                    HParmBlkPtr pb)
+{
+    Str255 tempPathname;
+    OSErr error;
+
+    /* Make sure pb parameter is not NULL */
+    if ( pb != NULL )
+    {
+        pb->volumeParam.ioVRefNum = vRefNum;
+        if ( pathname == NULL )
+        {
+            pb->volumeParam.ioNamePtr = NULL;
+            pb->volumeParam.ioVolIndex = 0;     /* use ioVRefNum only */
+        }
+        else
+        {                                   /* make a copy of the string and */
+            BlockMoveData(pathname, tempPathname, pathname[0] + 1);
+                                    /* use the copy so original isn't trashed */
+            pb->volumeParam.ioNamePtr = (StringPtr)tempPathname;
+                                       /* use ioNamePtr/ioVRefNum combination */
+            pb->volumeParam.ioVolIndex = -1;
+        }
+        error = PBHGetVInfoSync(pb);
+        pb->volumeParam.ioNamePtr = NULL;   /* ioNamePtr may point to local
+                                            tempPathname, so don't return it */
+    }
+    else
+    {
+        error = paramErr;
+    }
+    return ( error );
+}
+
+
+
+
+/*****************************************************************************/
+
+pascal  OSErr   FSpGetFullPath(const FSSpec *spec,
+                               short *fullPathLength,
+                               Handle *fullPath)
+{
+    OSErr       result;
+    OSErr       realResult;
+    FSSpec      tempSpec;
+    CInfoPBRec  pb;
+
+    *fullPathLength = 0;
+    *fullPath = NULL;
+
+    /* Default to noErr */
+    realResult = noErr;
+
+    /* Make a copy of the input FSSpec that can be modified */
+    BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
+
+    if ( tempSpec.parID == fsRtParID )
+    {
+        /* The object is a volume */
+
+        /* Add a colon to make it a full pathname */
+        ++tempSpec.name[0];
+        tempSpec.name[tempSpec.name[0]] = ':';
+
+        /* We're done */
+        result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
+    }
+    else
+    {
+        /* The object isn't a volume */
+
+        /* Is the object a file or a directory? */
+        pb.dirInfo.ioNamePtr = tempSpec.name;
+        pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
+        pb.dirInfo.ioDrDirID = tempSpec.parID;
+        pb.dirInfo.ioFDirIndex = 0;
+        result = PBGetCatInfoSync(&pb);
+        /* Allow file/directory name at end of path to not exist. */
+        realResult = result;
+        if ( (result == noErr) || (result == fnfErr) )
+        {
+            /* if the object is a directory, append a colon so full pathname
+               ends with colon */
+            if ( (result == noErr) && (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
+            {
+                ++tempSpec.name[0];
+                tempSpec.name[tempSpec.name[0]] = ':';
+            }
+
+            /* Put the object name in first */
+            result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
+            if ( result == noErr )
+            {
+                /* Get the ancestor directory names */
+                pb.dirInfo.ioNamePtr = tempSpec.name;
+                pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
+                pb.dirInfo.ioDrParID = tempSpec.parID;
+                do  /* loop until we have an error or find the root directory */
+                {
+                    pb.dirInfo.ioFDirIndex = -1;
+                    pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
+                    result = PBGetCatInfoSync(&pb);
+                    if ( result == noErr )
+                    {
+                        /* Append colon to directory name */
+                        ++tempSpec.name[0];
+                        tempSpec.name[tempSpec.name[0]] = ':';
+
+                        /* Add directory name to beginning of fullPath */
+                        (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1],
+                                      tempSpec.name[0]);
+                        result = MemError();
+                    }
+                } while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );
+            }
+        }
+    }
+    if ( result == noErr )
+    {
+        /* Return the length */
+        *fullPathLength = InlineGetHandleSize(*fullPath);
+        result = realResult;    /* return realResult in case it was fnfErr */
+    }
+    else
+    {
+        /* Dispose of the handle and return NULL and zero length */
+        if ( *fullPath != NULL )
+        {
+            DisposeHandle(*fullPath);
+        }
+        *fullPath = NULL;
+        *fullPathLength = 0;
+    }
+
+    return ( result );
+}
+
+
+
+/*****************************************************************************/
+
+pascal OSErr FSpLocationFromFullPath(short fullPathLength,
+                                     const void *fullPath,
+                                     FSSpec *spec)
+{
+    AliasHandle alias;
+    OSErr       result;
+    Boolean     wasChanged;
+    Str32       nullString;
+
+    /* Create a minimal alias from the full pathname */
+    nullString[0] = 0;  /* null string to indicate no zone or server name */
+    result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString,
+                                         nullString, &alias);
+
+    if ( result == noErr )
+    {
+        /* Let the Alias Manager resolve the alias. */
+        result = ResolveAlias(NULL, alias, spec, &wasChanged);
+
+        DisposeHandle((Handle)alias);   /* Free up memory used */
+    }
+
+    return ( result );
+}
+
+
+
+/*****************************************************************************/
+
+pascal  OSErr   GetFullPath(short vRefNum,
+                            long dirID,
+                            ConstStr255Param name,
+                            short *fullPathLength,
+                            Handle *fullPath)
+{
+    OSErr       result;
+    FSSpec      spec;
+
+    *fullPathLength = 0;
+    *fullPath = NULL;
+
+    result = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);
+    if ( (result == noErr) || (result == fnfErr) )
+    {
+        result = FSpGetFullPath(&spec, fullPathLength, fullPath);
+    }
+
+    return ( result );
+}
+
+
+
+/*****************************************************************************/
+
+pascal  OSErr   ChangeCreatorType(short vRefNum,
+                                  long dirID,
+                                  ConstStr255Param name,
+                                  OSType creator,
+                                  OSType fileType)
+{
+    CInfoPBRec pb;
+    OSErr error;
+    short realVRefNum;
+    long parID;
+
+    pb.hFileInfo.ioNamePtr = (StringPtr)name;
+    pb.hFileInfo.ioVRefNum = vRefNum;
+    pb.hFileInfo.ioDirID = dirID;
+    pb.hFileInfo.ioFDirIndex = 0;   /* use ioNamePtr and ioDirID */
+    error = PBGetCatInfoSync(&pb);
+    if ( error == noErr )
+    {
+        if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) == 0 )   /* if file */
+        {                            /* save parent dirID for BumpDate call */
+            parID = pb.hFileInfo.ioFlParID;
+
+            /* If creator not 0x00000000, change creator */
+            if ( creator != (OSType)0x00000000 )
+            {
+                pb.hFileInfo.ioFlFndrInfo.fdCreator = creator;
+            }
+
+            /* If fileType not 0x00000000, change fileType */
+            if ( fileType != (OSType)0x00000000 )
+            {
+                pb.hFileInfo.ioFlFndrInfo.fdType = fileType;
+            }
+
+            pb.hFileInfo.ioDirID = dirID;
+            error = PBSetCatInfoSync(&pb);  /* now, save the new information
+                                               back to disk */
+
+            if ( (error == noErr) && (parID != fsRtParID) ) /* can't
+                                                            bump fsRtParID */
+            {
+                /* get the real vRefNum in case a full pathname was passed */
+                error = DetermineVRefNum(name, vRefNum, &realVRefNum);
+                if ( error == noErr )
+                {
+                    error = BumpDate(realVRefNum, parID, NULL);
+                        /* and bump the parent directory's mod date to wake
+                           up the Finder */
+                        /* to the change we just made */
+                }
+            }
+        }
+        else
+        {
+            /* it was a directory, not a file */
+            error = notAFileErr;
+        }
+    }
+
+    return ( error );
+}
+
+/*****************************************************************************/
+
+pascal  OSErr   FSpChangeCreatorType(const FSSpec *spec,
+                                     OSType creator,
+                                     OSType fileType)
+{
+    return ( ChangeCreatorType(spec->vRefNum, spec->parID, spec->name,
+             creator, fileType) );
+}
+
+/*****************************************************************************/
+
+pascal  OSErr   BumpDate(short vRefNum,
+                         long dirID,
+                         ConstStr255Param name)
+/* Given a file or directory, change its modification date to the
+   current date/time. */
+{
+    CInfoPBRec pb;
+    Str31 tempName;
+    OSErr error;
+    unsigned long secs;
+
+    /* Protection against File Sharing problem */
+    if ( (name == NULL) || (name[0] == 0) )
+    {
+        tempName[0] = 0;
+        pb.hFileInfo.ioNamePtr = tempName;
+        pb.hFileInfo.ioFDirIndex = -1;  /* use ioDirID */
+    }
+    else
+    {
+        pb.hFileInfo.ioNamePtr = (StringPtr)name;
+        pb.hFileInfo.ioFDirIndex = 0;   /* use ioNamePtr and ioDirID */
+    }
+    pb.hFileInfo.ioVRefNum = vRefNum;
+    pb.hFileInfo.ioDirID = dirID;
+    error = PBGetCatInfoSync(&pb);
+    if ( error == noErr )
+    {
+        GetDateTime(&secs);
+        /* set mod date to current date, or one second into the future
+            if mod date = current date */
+        pb.hFileInfo.ioFlMdDat =
+                          (secs == pb.hFileInfo.ioFlMdDat) ? (++secs) : (secs);
+        if ( pb.dirInfo.ioNamePtr == tempName )
+        {
+            pb.hFileInfo.ioDirID = pb.hFileInfo.ioFlParID;
+        }
+        else
+        {
+            pb.hFileInfo.ioDirID = dirID;
+        }
+        error = PBSetCatInfoSync(&pb);
+    }
+
+    return ( error );
+}
+
+/*****************************************************************************/
+
+pascal  OSErr   FSpBumpDate(const FSSpec *spec)
+{
+    return ( BumpDate(spec->vRefNum, spec->parID, spec->name) );
+}
+
+
+/*****************************************************************************/
+
+pascal  OSErr   OnLine(FSSpecPtr volumes,
+                       short reqVolCount,
+                       short *actVolCount,
+                       short *volIndex)
+{
+    HParamBlockRec pb;
+    OSErr error = noErr;
+    FSSpec *endVolArray;
+
+    if ( *volIndex > 0 )
+    {
+        *actVolCount = 0;
+        for ( endVolArray = volumes + reqVolCount;
+              (volumes < endVolArray) && (error == noErr); ++volumes )
+        {
+            pb.volumeParam.ioNamePtr = (StringPtr) & volumes->name;
+            pb.volumeParam.ioVolIndex = *volIndex;
+            error = PBHGetVInfoSync(&pb);
+            if ( error == noErr )
+            {
+                volumes->parID = fsRtParID;     /* the root directory's
+                                                   parent is 1 */
+                volumes->vRefNum = pb.volumeParam.ioVRefNum;
+                ++*volIndex;
+                ++*actVolCount;
+            }
+        }
+    }
+    else
+    {
+        error = paramErr;
+    }
+
+    return ( error );
+}
+
+
+/*****************************************************************************/
+
+pascal  OSErr   DTGetComment(short vRefNum,
+                             long dirID,
+                             ConstStr255Param name,
+                             Str255 comment)
+{
+    DTPBRec pb;
+    OSErr error;
+    short dtRefNum;
+    Boolean newDTDatabase;
+
+    if (comment != NULL)
+    {
+        comment[0] = 0; /* return nothing by default */
+
+        /* attempt to open the desktop database */
+        error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase);
+        if ( error == noErr )
+        {
+            /* There was a desktop database and it's now open */
+
+            if ( !newDTDatabase )
+            {
+                pb.ioDTRefNum = dtRefNum;
+                pb.ioNamePtr = (StringPtr)name;
+                pb.ioDirID = dirID;
+                pb.ioDTBuffer = (Ptr)&comment[1];
+                /*
+                **  IMPORTANT NOTE #1: Inside Macintosh says that comments
+                **  are up to 200 characters. While that may be correct for
+                **  the HFS file system's Desktop Manager, other file
+                **  systems (such as Apple Photo Access) return up to
+                **  255 characters. Make sure the comment buffer is a Str255
+                **  or you'll regret it.
+                **
+                **  IMPORTANT NOTE #2: Although Inside Macintosh doesn't
+                **  mention it, ioDTReqCount is a input field to
+                **  PBDTGetCommentSync. Some file systems (like HFS) ignore
+                **  ioDTReqCount and always return the full comment --
+                **  others (like AppleShare) respect ioDTReqCount and only
+                **  return up to ioDTReqCount characters of the comment.
+                */
+                pb.ioDTReqCount = sizeof(Str255) - 1;
+                error = PBDTGetCommentSync(&pb);
+                if (error == noErr)
+                {
+                    comment[0] = (unsigned char)pb.ioDTActCount;
+                }
+            }
+        }
+        else
+        {
+            /* There is no desktop database - try the Desktop file */
+            error = GetCommentFromDesktopFile(vRefNum, dirID, name, comment);
+            if ( error != noErr )
+            {
+                error = afpItemNotFound;    /* return an expected error */
+            }
+        }
+    }
+    else
+    {
+        error = paramErr;
+    }
+
+    return (error);
+}
+
+/*****************************************************************************/
+
+pascal  OSErr   FSpDTGetComment(const FSSpec *spec,
+                              Str255 comment)
+{
+    return (DTGetComment(spec->vRefNum, spec->parID, spec->name, comment));
+}
+
+
+/*****************************************************************************/
+
+pascal  OSErr   DTSetComment(short vRefNum,
+                             long dirID,
+                             ConstStr255Param name,
+                             ConstStr255Param comment)
+{
+    DTPBRec pb;
+    OSErr error;
+    short dtRefNum;
+    Boolean newDTDatabase;
+
+    error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase);
+    if ( error == noErr )
+    {
+        pb.ioDTRefNum = dtRefNum;
+        pb.ioNamePtr = (StringPtr)name;
+        pb.ioDirID = dirID;
+        pb.ioDTBuffer = (Ptr)&comment[1];
+        /* Truncate the comment to 200 characters just in case */
+        /* some file system doesn't range check */
+        if ( comment[0] <= 200 )
+        {
+            pb.ioDTReqCount = comment[0];
+        }
+        else
+        {
+            pb.ioDTReqCount = 200;
+        }
+        error = PBDTSetCommentSync(&pb);
+    }
+    return (error);
+}
+
+/*****************************************************************************/
+
+pascal  OSErr   FSpDTSetComment(const FSSpec *spec,
+                              ConstStr255Param comment)
+{
+    return (DTSetComment(spec->vRefNum, spec->parID, spec->name, comment));
+}
+
+
+/*****************************************************************************/
+
+pascal  OSErr   DTOpen(ConstStr255Param volName,
+                       short vRefNum,
+                       short *dtRefNum,
+                       Boolean *newDTDatabase)
+{
+    OSErr error;
+    GetVolParmsInfoBuffer volParmsInfo;
+    long infoSize;
+    DTPBRec pb;
+
+    /* Check for volume Desktop Manager support before calling */
+    infoSize = sizeof(GetVolParmsInfoBuffer);
+    error = HGetVolParms(volName, vRefNum, &volParmsInfo, &infoSize);
+    if ( error == noErr )
+    {
+        if ( hasDesktopMgr(volParmsInfo) )
+        {
+            pb.ioNamePtr = (StringPtr)volName;
+            pb.ioVRefNum = vRefNum;
+            error = PBDTOpenInform(&pb);
+            /* PBDTOpenInform informs us if the desktop was just created */
+            /* by leaving the low bit of ioTagInfo clear (0) */
+            *newDTDatabase = ((pb.ioTagInfo & 1L) == 0);
+            if ( error == paramErr )
+            {
+                error = PBDTGetPath(&pb);
+                /* PBDTGetPath doesn't tell us if the database is new */
+                /* so assume it is not new */
+                *newDTDatabase = false;
+            }
+            *dtRefNum = pb.ioDTRefNum;
+        }
+        else
+        {
+            error = paramErr;
+        }
+    }
+    return ( error );
+}
+
+/*****************************************************************************/
+
+/*
+**  GetCommentFromDesktopFile
+**
+**  Get a file or directory's Finder comment field (if any) from the
+**  Desktop file's 'FCMT' resources.
+*/
+static  OSErr   GetCommentFromDesktopFile(short vRefNum,
+                                          long dirID,
+                                          ConstStr255Param name,
+                                          Str255 comment)
+{
+    OSErr error;
+    short commentID;
+    short realVRefNum;
+    Str255 desktopName;
+    short savedResFile;
+    short dfRefNum;
+    StringHandle commentHandle;
+
+    /* Get the comment ID number */
+    error = GetCommentID(vRefNum, dirID, name, &commentID);
+    if ( error == noErr )
+    {
+        if ( commentID != 0 )   /* commentID == 0 means there's no comment */
+        {
+            error = DetermineVRefNum(name, vRefNum, &realVRefNum);
+            if ( error == noErr )
+            {
+                error = GetDesktopFileName(realVRefNum, desktopName);
+                if ( error == noErr )
+                {
+                    savedResFile = CurResFile();
+                    /*
+                    **  Open the 'Desktop' file in the root directory. (because
+                    **  opening the resource file could preload unwanted resources,
+                    **  bracket the call with SetResLoad(s))
+                    */
+                    SetResLoad(false);
+                    dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName,
+                                            fsRdPerm);
+                    SetResLoad(true);
+
+                    if ( dfRefNum != -1)
+                    {
+                        /* Get the comment resource */
+                        commentHandle = (StringHandle)Get1Resource(kFCMTResType,
+                                                                   commentID);
+                        if ( commentHandle != NULL )
+                        {
+                            if ( InlineGetHandleSize((Handle)commentHandle) > 0 )
+                            {
+                                BlockMoveData(*commentHandle, comment,
+                                              *commentHandle[0] + 1);
+                            }
+                            else
+                            {                       /* no comment available */
+                                error = afpItemNotFound;
+                            }
+                        }
+                        else
+                        {                           /* no comment available */
+                            error = afpItemNotFound;
+                        }
+
+                        /* restore the resource chain and close
+                           the Desktop file */
+                        UseResFile(savedResFile);
+                        CloseResFile(dfRefNum);
+                    }
+                    else
+                    {
+                        error = afpItemNotFound;
+                    }
+                }
+                else
+                {
+                    error = afpItemNotFound;
+                }
+            }
+        }
+        else
+        {
+            error = afpItemNotFound;    /* no comment available */
+        }
+    }
+
+    return ( error );
+}
+
+/*****************************************************************************/
+
+pascal  OSErr   HGetVolParms(ConstStr255Param volName,
+                             short vRefNum,
+                             GetVolParmsInfoBuffer *volParmsInfo,
+                             long *infoSize)
+{
+    HParamBlockRec pb;
+    OSErr error;
+
+    pb.ioParam.ioNamePtr = (StringPtr)volName;
+    pb.ioParam.ioVRefNum = vRefNum;
+    pb.ioParam.ioBuffer = (Ptr)volParmsInfo;
+    pb.ioParam.ioReqCount = *infoSize;
+    error = PBHGetVolParmsSync(&pb);
+    if ( error == noErr )
+    {
+        *infoSize = pb.ioParam.ioActCount;
+    }
+    return ( error );
+}
+
+/*****************************************************************************/
+/*
+**  GetCommentID
+**
+**  Get the comment ID number for the Desktop file's 'FCMT' resource ID from
+**  the file or folders fdComment (frComment) field.
+*/
+static  OSErr   GetCommentID(short vRefNum,
+                             long dirID,
+                             ConstStr255Param name,
+                             short *commentID)
+{
+    CInfoPBRec pb;
+    OSErr error;
+
+    error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
+    *commentID = pb.hFileInfo.ioFlXFndrInfo.fdComment;
+    return ( error );
+}
+
+/*****************************************************************************/
+
+/*
+**  GetDesktopFileName
+**
+**  Get the name of the Desktop file.
+*/
+static  OSErr   GetDesktopFileName(short vRefNum,
+                                   Str255 desktopName)
+{
+    OSErr           error;
+    HParamBlockRec  pb;
+    short           index;
+    Boolean         found;
+
+    pb.fileParam.ioNamePtr = desktopName;
+    pb.fileParam.ioVRefNum = vRefNum;
+    pb.fileParam.ioFVersNum = 0;
+    index = 1;
+    found = false;
+    do
+    {
+        pb.fileParam.ioDirID = fsRtDirID;
+        pb.fileParam.ioFDirIndex = index;
+        error = PBHGetFInfoSync(&pb);
+        if ( error == noErr )
+        {
+            if ( (pb.fileParam.ioFlFndrInfo.fdType == 'FNDR') &&
+                 (pb.fileParam.ioFlFndrInfo.fdCreator == 'ERIK') )
+            {
+                found = true;
+            }
+        }
+        ++index;
+    } while ( (error == noErr) && !found );
+
+    return ( error );
+}
+
+
+/*****************************************************************************/
+
+pascal  OSErr   XGetVInfo(short volReference,
+                          StringPtr volName,
+                          short *vRefNum,
+                          UnsignedWide *freeBytes,
+                          UnsignedWide *totalBytes)
+{
+    OSErr           result;
+    long            response;
+    XVolumeParam    pb;
+
+    /* See if large volume support is available */
+    if ( ( Gestalt(gestaltFSAttr, &response) == noErr ) && ((response & (1L << gestaltFSSupports2TBVols)) != 0) )
+    {
+        /* Large volume support is available */
+        pb.ioVRefNum = volReference;
+        pb.ioNamePtr = volName;
+        pb.ioXVersion = 0;  /* this XVolumeParam version (0) */
+        pb.ioVolIndex = 0;  /* use ioVRefNum only, return volume name */
+        result = PBXGetVolInfoSync(&pb);
+        if ( result == noErr )
+        {
+            /* The volume name was returned in volName (if not NULL) and */
+            /* we have the volume's vRefNum and allocation block size */
+            *vRefNum = pb.ioVRefNum;
+
+            /* return the freeBytes and totalBytes */
+            *totalBytes = pb.ioVTotalBytes;
+            *freeBytes = pb.ioVFreeBytes;
+        }
+    }
+    else
+    {
+        /* No large volume support */
+
+        /* Use HGetVInfo to get the results */
+        result = HGetVInfo(volReference, volName, vRefNum, &freeBytes->lo, &totalBytes->lo);
+        if ( result == noErr )
+        {
+            /* zero the high longs of totalBytes and freeBytes */
+            totalBytes->hi = 0;
+            freeBytes->hi = 0;
+        }
+    }
+    return ( result );
+}
+
+
+
+/*****************************************************************************/
+
+pascal  OSErr   HGetVInfo(short volReference,
+                          StringPtr volName,
+                          short *vRefNum,
+                          unsigned long *freeBytes,
+                          unsigned long *totalBytes)
+{
+    HParamBlockRec  pb;
+    unsigned long   allocationBlockSize;
+    unsigned short  numAllocationBlocks;
+    unsigned short  numFreeBlocks;
+    VCB             *theVCB;
+    Boolean         vcbFound;
+    OSErr           result;
+
+    /* Use the File Manager to get the real vRefNum */
+    pb.volumeParam.ioVRefNum = volReference;
+    pb.volumeParam.ioNamePtr = volName;
+    pb.volumeParam.ioVolIndex = 0;  /* use ioVRefNum only, return volume name */
+    result = PBHGetVInfoSync(&pb);
+
+    if ( result == noErr )
+    {
+        /* The volume name was returned in volName (if not NULL) and */
+        /* we have the volume's vRefNum and allocation block size */
+        *vRefNum = pb.volumeParam.ioVRefNum;
+        allocationBlockSize = (unsigned long)pb.volumeParam.ioVAlBlkSiz;
+
+        /* System 7.5 (and beyond) pins the number of allocation blocks and */
+        /* the number of free allocation blocks returned by PBHGetVInfo to */
+        /* a value so that when multiplied by the allocation block size, */
+        /* the volume will look like it has $7fffffff bytes or less. This */
+        /* was done so older applications that use signed math or that use */
+        /* the GetVInfo function (which uses signed math) will continue to work. */
+        /* However, the unpinned numbers (which we want) are always available */
+        /* in the volume's VCB so we'll get those values from the VCB if possible. */
+
+        /* Find the volume's VCB */
+        vcbFound = false;
+        theVCB = (VCB *)(GetVCBQHdr()->qHead);
+        while ( (theVCB != NULL) && !vcbFound )
+        {
+            /* Check VCB signature before using VCB. Don't have to check for */
+            /* MFS (0xd2d7) because they can't get big enough to be pinned */
+            if ( theVCB->vcbSigWord == 0x4244 )
+            {
+                if ( theVCB->vcbVRefNum == *vRefNum )
+                {
+                    vcbFound = true;
+                }
+            }
+
+            if ( !vcbFound )
+            {
+                theVCB = (VCB *)(theVCB->qLink);
+            }
+        }
+
+        if ( theVCB != NULL )
+        {
+            /* Found a VCB we can use. Get the un-pinned number of allocation blocks */
+            /* and the number of free blocks from the VCB. */
+            numAllocationBlocks = (unsigned short)theVCB->vcbNmAlBlks;
+            numFreeBlocks = (unsigned short)theVCB->vcbFreeBks;
+        }
+        else
+        {
+            /* Didn't find a VCB we can use. Return the number of allocation blocks */
+            /* and the number of free blocks returned by PBHGetVInfoSync. */
+            numAllocationBlocks = (unsigned short)pb.volumeParam.ioVNmAlBlks;
+            numFreeBlocks = (unsigned short)pb.volumeParam.ioVFrBlk;
+        }
+
+        /* Now, calculate freeBytes and totalBytes using unsigned values */
+        *freeBytes = numFreeBlocks * allocationBlockSize;
+        *totalBytes = numAllocationBlocks * allocationBlockSize;
+    }
+
+    return ( result );
+}
+
+
+/*
+**  PBXGetVolInfoSync is the glue code needed to make PBXGetVolInfoSync
+**  File Manager requests from CFM-based programs. At some point, Apple
+**  will get around to adding this to the standard libraries you link with
+**  and you'll get a duplicate symbol link error. At that time, just delete
+**  this code (or comment it out).
+**
+**  Non-CFM 68K programs don't needs this glue (and won't get it) because
+**  they instead use the inline assembly glue found in the Files.h interface
+**  file.
+*/
+
+#if __WANTPASCALELIMINATION
+#undef  pascal
+#endif
+
+#if GENERATINGCFM
+pascal OSErr PBXGetVolInfoSync(XVolumeParamPtr paramBlock)
+{
+    enum
+    {
+        kXGetVolInfoSelector = 0x0012,  /* Selector for XGetVolInfo */
+
+        uppFSDispatchProcInfo = kRegisterBased
+             | REGISTER_RESULT_LOCATION(kRegisterD0)
+             | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
+             | REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(long)))  /* trap word */
+             | REGISTER_ROUTINE_PARAMETER(2, kRegisterD0, SIZE_CODE(sizeof(long)))  /* selector */
+             | REGISTER_ROUTINE_PARAMETER(3, kRegisterA0, SIZE_CODE(sizeof(XVolumeParamPtr)))
+    };
+
+    return ( CallOSTrapUniversalProc(NGetTrapAddress(_FSDispatch, OSTrap),
+                                        uppFSDispatchProcInfo,
+                                        _FSDispatch,
+                                        kXGetVolInfoSelector,
+                                        paramBlock) );
+}
+#endif
+
+#if __WANTPASCALELIMINATION
+#define pascal
+#endif
+
+/*****************************************************************************/
+
+pascal  OSErr   GetDirName(short vRefNum,
+                           long dirID,
+                           Str31 name)
+{
+    CInfoPBRec pb;
+    OSErr error;
+
+    if ( name != NULL )
+    {
+        pb.dirInfo.ioNamePtr = name;
+        pb.dirInfo.ioVRefNum = vRefNum;
+        pb.dirInfo.ioDrDirID = dirID;
+        pb.dirInfo.ioFDirIndex = -1;    /* get information about ioDirID */
+        error = PBGetCatInfoSync(&pb);
+    }
+    else
+    {
+        error = paramErr;
+    }
+
+    return ( error );
+}
+
+
+/*****************************************************************************/
+
+pascal  OSErr   GetVolFileSystemID(ConstStr255Param pathname,
+                                   short vRefNum,
+                                   short *fileSystemID)
+{
+    HParamBlockRec pb;
+    OSErr error;
+
+    error = GetVolumeInfoNoName(pathname,vRefNum, &pb);
+    if ( error == noErr )
+    {
+        *fileSystemID = pb.volumeParam.ioVFSID;
+    }
+
+    return ( error );
+}
+
+/*****************************************************************************/
+
+pascal  OSErr GetDInfo(short vRefNum,
+                       long dirID,
+                       ConstStr255Param name,
+                       DInfo *fndrInfo)
+{
+    CInfoPBRec pb;
+    OSErr error;
+
+    error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
+    if ( error == noErr )
+    {
+        if ( (pb.dirInfo.ioFlAttrib & ioDirMask) != 0 )
+        {
+            /* it's a directory, return the DInfo */
+            *fndrInfo = pb.dirInfo.ioDrUsrWds;
+        }
+        else
+        {
+            /* oops, a file was passed */
+            error = dirNFErr;
+        }
+    }
+
+    return ( error );
+}
+
+/*****************************************************************************/
+
+pascal  OSErr FSpGetDInfo(const FSSpec *spec,
+                          DInfo *fndrInfo)
+{
+    return ( GetDInfo(spec->vRefNum, spec->parID, spec->name, fndrInfo) );
+}
+
+
diff --git a/macos/source/macstuff.h b/macos/source/macstuff.h
new file mode 100644 (file)
index 0000000..27c481d
--- /dev/null
@@ -0,0 +1,1108 @@
+#ifndef _MACSTUFF_H
+#define _MACSTUFF_H       1
+
+/*
+These Functions were originally part of More Files version 1.4.8
+
+More Files fixes many of the broken or underfunctional
+parts of the file system.
+
+More Files
+
+A collection of File Manager and related routines
+
+by Jim Luther (Apple Macintosh Developer Technical Support Emeritus)
+with significant code contributions by Nitin Ganatra
+(Apple Macintosh Developer Technical Support Emeritus)
+Copyright  1992-1998 Apple Computer, Inc.
+Portions copyright  1995 Jim Luther
+All rights reserved.
+
+The Package "More Files" is distributed under the following
+license terms:
+
+         "You may incorporate this sample code into your
+          applications without restriction, though the
+          sample code has been provided "AS IS" and the
+          responsibility for its operation is 100% yours.
+          However, what you are not permitted to do is to
+          redistribute the source as "DSC Sample Code" after
+          having made changes. If you're going to
+          redistribute the source, we require that you make
+          it clear in the source that the code was descended
+          from Apple Sample Code, but that you've made
+          changes."
+
+
+The following changes are made by Info-ZIP:
+
+- The only changes are made by pasting the functions
+  (mostly found in MoreFilesExtras.c / MoreFiles.c)
+  directly into macstuff.c / macstuff.h and slightly
+  reformatting the text (replacement of TABs by spaces,
+  removal/replacement of non-ASCII characters).
+  The code itself is NOT changed.
+
+This file has been modified by Info-ZIP for use in MacZip.
+This file is NOT part of the original package More Files.
+
+More Files can be found on the MetroWerks CD and Developer CD from
+Apple. You can also download the latest version from:
+
+    http://members.aol.com/JumpLong/#MoreFiles
+
+Jim Luther's Home-page:
+    http://members.aol.com/JumpLong/
+
+
+*/
+
+
+#define __MACOSSEVENFIVEONEORLATER 1
+#define __MACOSSEVENFIVEORLATER    1
+#define __MACOSSEVENORLATER        1
+
+#include <Errors.h>
+#include <Files.h>
+
+
+/*
+ * Like the MoreFiles routines these fix problems in the standard
+ * Mac calls.
+ */
+
+int     FSpLocationFromPath (int length,const char *path, FSSpecPtr theSpec);
+OSErr   FSpPathFromLocation (FSSpecPtr theSpec,int *length, Handle *fullPath);
+
+#define hasDesktopMgr(volParms) (((volParms).vMAttrib & (1L << bHasDesktopMgr)) != 0)
+
+/*
+ * The following routines are utility functions.  They are exported
+ * here because they are needed and they are not officially supported,
+ * however.  The first set are from the MoreFiles package.
+ */
+int             FSpGetDefaultDir (FSSpecPtr theSpec);
+int             FSpSetDefaultDir (FSSpecPtr dirSpec);
+pascal  OSErr   FSpGetDirectoryID(const FSSpec *spec,long *theDirID,
+                                  Boolean *isDirectory);
+pascal  short   FSpOpenResFileCompat(const FSSpec *spec, SignedByte permission);
+pascal  void    FSpCreateResFileCompat(const FSSpec *spec,OSType creator,
+                                       OSType fileType,
+                                       ScriptCode scriptTag);
+OSErr           FSpFindFolder (short vRefNum, OSType folderType,
+                               Boolean createFolder,
+                               FSSpec *spec);
+
+/*****************************************************************************/
+
+pascal  OSErr   GetVolumeInfoNoName(ConstStr255Param pathname,
+                                    short vRefNum,
+                                    HParmBlkPtr pb);
+/*   Call PBHGetVInfoSync ignoring returned name.
+    GetVolumeInfoNoName uses pathname and vRefNum to call PBHGetVInfoSync
+    in cases where the returned volume name is not needed by the caller.
+    The pathname and vRefNum parameters are not touched, and the pb
+    parameter is initialized by PBHGetVInfoSync except that ioNamePtr in
+    the parameter block is always returned as NULL (since it might point
+    to GetVolumeInfoNoName's local variable tempPathname).
+
+    I noticed using this code in several places, so here it is once.
+    This reduces the code size of MoreFiles.
+
+    pathName    input:  Pointer to a full pathname or nil.  If you pass in a
+                        partial pathname, it is ignored. A full pathname to a
+                        volume must end with a colon character (:).
+    vRefNum     input:  Volume specification (volume reference number, working
+                        directory number, drive number, or 0).
+    pb          input:  A pointer to HParamBlockRec.
+                output: The parameter block as filled in by PBHGetVInfoSync
+                        except that ioNamePtr will always be NULL.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        paramErr            -50     No default volume, or pb was NULL
+*/
+
+
+/*****************************************************************************/
+
+pascal  OSErr   GetFilenameFromPathname(ConstStr255Param pathname,
+                                        Str255 filename);
+/*   Get the object name from the end of a full or partial pathname.
+    The GetFilenameFromPathname function gets the file (or directory) name
+    from the end of a full or partial pathname. Returns notAFileErr if the
+    pathname is nil, the pathname is empty, or the pathname cannot refer to
+    a filename (with a noErr result, the pathname could still refer to a
+    directory).
+
+    pathname    input:  A full or partial pathname.
+    filename    output: The file (or directory) name.
+
+    Result Codes
+        noErr               0       No error
+        notAFileErr         -1302   The pathname is nil, the pathname
+                                    is empty, or the pathname cannot refer
+                                    to a filename
+
+    __________
+
+    See also:   GetObjectLocation.
+*/
+
+
+
+/*****************************************************************************/
+
+pascal  OSErr   FSMakeFSSpecCompat(short vRefNum, long dirID,
+                                   ConstStr255Param fileName,
+                                   FSSpec *spec);
+/*   Initialize a FSSpec record.
+    The FSMakeFSSpecCompat function fills in the fields of an FSSpec record.
+    If the file system can't create the FSSpec, then the compatibility code
+    creates a FSSpec that is exactly like an FSSpec except that spec.name
+    for a file may not have the same capitalization as the file's catalog
+    entry on the disk volume. That is because fileName is parsed to get the
+    name instead of getting the name back from the file system. This works
+    fine with System 6 where FSMakeSpec isn't available.
+
+    vRefNum     input:  Volume specification.
+    dirID       input:  Directory ID.
+    fileName    input:  Pointer to object name, or nil when dirID specifies
+                        a directory that's the object.
+    spec        output: A file system specification to be filled in by
+                        FSMakeFSSpecCompat.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     Volume doesnt exist
+        fnfErr              -43     File or directory does not exist
+                                    (FSSpec is still valid)
+*/
+
+
+#if !SystemSevenOrLater
+static  Boolean FSHasFSSpecCalls(void);
+
+static  Boolean QTHasFSSpecCalls(void);
+#endif  /* !SystemSevenOrLater */
+
+
+
+/*****************************************************************************/
+
+pascal  OSErr   GetObjectLocation(short vRefNum,
+                                  long dirID,
+                                  ConstStr255Param pathname,
+                                  short *realVRefNum,
+                                  long *realParID,
+                                  Str255 realName,
+                                  Boolean *isDirectory);
+/*   Get a file system object's location.
+    The GetObjectLocation function gets a file system object's location -
+    that is, its real volume reference number, real parent directory ID,
+    and name. While we're at it, determine if the object is a file or directory.
+    If GetObjectLocation returns fnfErr, then the location information
+    returned is valid, but it describes an object that doesn't exist.
+    You can use the location information for another operation, such as
+    creating a file or directory.
+
+    vRefNum     input:  Volume specification.
+    dirID       input:  Directory ID.
+    pathname    input:  Pointer to object name, or nil when dirID specifies
+                        a directory that's the object.
+    realVRefNum output: The real volume reference number.
+    realParID   output: The parent directory ID of the specified object.
+    realName    output: The name of the specified object (the case of the
+                        object name may not be the same as the object's
+                        catalog entry on disk - since the Macintosh file
+                        system is not case sensitive, it shouldn't matter).
+    isDirectory output: True if object is a directory; false if object
+                        is a file.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File not found
+        paramErr            -50     No default volume
+        dirNFErr            -120    Directory not found or incomplete pathname
+        notAFileErr         -1302   The pathname is nil, the pathname
+                                    is empty, or the pathname cannot refer
+                                    to a filename
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+
+    __________
+
+    See also:   FSMakeFSSpecCompat
+*/
+
+pascal  OSErr   FSpGetDirectoryID(const FSSpec *spec, long *theDirID,
+                                  Boolean *isDirectory);
+
+pascal  OSErr   GetDirectoryID(short vRefNum,long dirID,ConstStr255Param name,
+                               long *theDirID,Boolean *isDirectory);
+
+
+
+/*****************************************************************************/
+
+pascal  OSErr GetCatInfoNoName(short vRefNum,
+                               long dirID,
+                               ConstStr255Param name,
+                               CInfoPBPtr pb);
+/*   Call PBGetCatInfoSync ignoring returned name.
+    GetCatInfoNoName uses vRefNum, dirID and name to call PBGetCatInfoSync
+    in cases where the returned object is not needed by the caller.
+    The vRefNum, dirID and name parameters are not touched, and the pb
+    parameter is initialized by PBGetCatInfoSync except that ioNamePtr in
+    the parameter block is always returned as NULL (since it might point
+    to GetCatInfoNoName's local variable tempName).
+
+    I noticed using this code in several places, so here it is once.
+    This reduces the code size of MoreFiles.
+
+    vRefNum         input:  Volume specification.
+    dirID           input:  Directory ID.
+    name            input:  Pointer to object name, or nil when dirID
+                            specifies a directory that's the object.
+    pb              input:  A pointer to CInfoPBRec.
+                    output: The parameter block as filled in by
+                            PBGetCatInfoSync except that ioNamePtr will
+                            always be NULL.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File not found
+        paramErr            -50     No default volume
+        dirNFErr            -120    Directory not found or incomplete pathname
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+
+*/
+
+
+/*****************************************************************************/
+
+
+pascal  OSErr   DetermineVRefNum(ConstStr255Param pathname,
+                                 short vRefNum,
+                                 short *realVRefNum);
+/*   Determine the real volume reference number.
+    The DetermineVRefNum function determines the volume reference number of
+    a volume from a pathname, a volume specification, or a combination
+    of the two.
+    WARNING: Volume names on the Macintosh are *not* unique -- Multiple
+    mounted volumes can have the same name. For this reason, the use of a
+    volume name or full pathname to identify a specific volume may not
+    produce the results you expect.  If more than one volume has the same
+    name and a volume name or full pathname is used, the File Manager
+    currently uses the first volume it finds with a matching name in the
+    volume queue.
+
+    pathName    input:  Pointer to a full pathname or nil.  If you pass in a
+                        partial pathname, it is ignored. A full pathname to a
+                        volume must end with a colon character (:).
+    vRefNum     input:  Volume specification (volume reference number, working
+                        directory number, drive number, or 0).
+    realVRefNum output: The real volume reference number.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        paramErr            -50     No default volume
+*/
+
+
+/*****************************************************************************/
+
+pascal  OSErr   FSpGetFullPath(const FSSpec *spec,
+                               short *fullPathLength,
+                               Handle *fullPath);
+/*   Get a full pathname to a volume, directory or file.
+    The GetFullPath function builds a full pathname to the specified
+    object. The full pathname is returned in the newly created handle
+    fullPath and the length of the full pathname is returned in
+    fullPathLength. Your program is responsible for disposing of the
+    fullPath handle.
+
+    spec            input:  An FSSpec record specifying the object.
+    fullPathLength  output: The number of characters in the full pathname.
+                            If the function fails to create a full pathname,
+                            it sets fullPathLength to 0.
+    fullPath        output: A handle to the newly created full pathname
+                            buffer. If the function fails to create a
+                            full pathname, it sets fullPath to NULL.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File or directory does not exist
+        paramErr            -50     No default volume
+        memFullErr          -108    Not enough memory
+        dirNFErr            -120    Directory not found or incomplete pathname
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+
+    __________
+
+    See also:   GetFullPath
+*/
+
+/*****************************************************************************/
+
+pascal OSErr FSpLocationFromFullPath(short fullPathLength,
+                                     const void *fullPath,
+                                     FSSpec *spec);
+/*   Get a FSSpec from a full pathname.
+    The FSpLocationFromFullPath function returns a FSSpec to the object
+    specified by full pathname. This function requires the Alias Manager.
+
+    fullPathLength  input:  The number of characters in the full pathname
+                            of the target.
+    fullPath        input:  A pointer to a buffer that contains the full
+                            pathname of the target. The full pathname
+                            starts with the name of the volume, includes
+                            all of the directory names in the path to the
+                            target, and ends with the target name.
+    spec            output: An FSSpec record specifying the object.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     The volume is not mounted
+        fnfErr              -43     Target not found, but volume and parent
+                                    directory found
+        paramErr            -50     Parameter error
+        usrCanceledErr      -128    The user canceled the operation
+
+    __________
+
+    See also:   LocationFromFullPath
+*/
+
+
+/*****************************************************************************/
+
+pascal  OSErr   GetFullPath(short vRefNum,
+                            long dirID,
+                            ConstStr255Param name,
+                            short *fullPathLength,
+                            Handle *fullPath);
+/*   Get a full pathname to a volume, directory or file.
+    The GetFullPath function builds a full pathname to the specified
+    object. The full pathname is returned in the newly created handle
+    fullPath and the length of the full pathname is returned in
+    fullPathLength. Your program is responsible for disposing of the
+    fullPath handle.
+
+    Note that a full pathname can be made to a file/directory that does not
+    yet exist if all directories up to that file/directory exist. In this case,
+    GetFullPath will return a fnfErr.
+
+    vRefNum         input:  Volume specification.
+    dirID           input:  Directory ID.
+    name            input:  Pointer to object name, or nil when dirID
+                            specifies a directory that's the object.
+    fullPathLength  output: The number of characters in the full pathname.
+                            If the function fails to create a full
+                            pathname, it sets fullPathLength to 0.
+    fullPath        output: A handle to the newly created full pathname
+                            buffer. If the function fails to create a
+                            full pathname, it sets fullPath to NULL.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File or directory does not exist (fullPath
+                                    and fullPathLength are still valid)
+        paramErr            -50     No default volume
+        memFullErr          -108    Not enough memory
+        dirNFErr            -120    Directory not found or incomplete pathname
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+
+    __________
+
+    See also:   FSpGetFullPath
+*/
+
+
+
+/*****************************************************************************/
+
+pascal  OSErr   ChangeCreatorType(short vRefNum,
+                                  long dirID,
+                                  ConstStr255Param name,
+                                  OSType creator,
+                                  OSType fileType);
+/*   Change the creator or file type of a file.
+    The ChangeCreatorType function changes the creator or file type of a file.
+
+    vRefNum     input:  Volume specification.
+    dirID       input:  Directory ID.
+    name        input:  The name of the file.
+    creator     input:  The new creator type or 0x00000000 to leave
+                        the creator type alone.
+    fileType    input:  The new file type or 0x00000000 to leave the
+                        file type alone.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File not found
+        fLckdErr            -45     File is locked
+        vLckdErr            -46     Volume is locked or read-only
+        paramErr            -50     No default volume
+        dirNFErr            -120    Directory not found or incomplete pathname
+        notAFileErr         -1302   Name was not a file
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+
+    __________
+
+    See also:   FSpChangeCreatorType
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   FSpChangeCreatorType(const FSSpec *spec,
+                                     OSType creator,
+                                     OSType fileType);
+/*   Change the creator or file type of a file.
+    The FSpChangeCreatorType function changes the creator or file type of a file.
+
+    spec        input:  An FSSpec record specifying the file.
+    creator     input:  The new creator type or 0x00000000 to leave
+                        the creator type alone.
+    fileType    input:  The new file type or 0x00000000 to leave the
+                        file type alone.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File not found
+        fLckdErr            -45     File is locked
+        vLckdErr            -46     Volume is locked or read-only
+        paramErr            -50     No default volume
+        dirNFErr            -120    Directory not found or incomplete pathname
+        notAFileErr         -1302   Name was not a file
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+
+    __________
+
+    See also:   ChangeCreatorType
+*/
+
+
+/*****************************************************************************/
+
+pascal  OSErr   BumpDate(short vRefNum,
+                         long dirID,
+                         ConstStr255Param name);
+/*   Update the modification date of a file or directory.
+    The BumpDate function changes the modification date of a file or
+    directory to the current date/time.  If the modification date is already
+    equal to the current date/time, then add one second to the
+    modification date.
+
+    vRefNum input:  Volume specification.
+    dirID   input:  Directory ID.
+    name    input:  Pointer to object name, or nil when dirID specifies
+                    a directory that's the object.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File not found
+        fLckdErr            -45     File is locked
+        vLckdErr            -46     Volume is locked or read-only
+        paramErr            -50     No default volume
+        dirNFErr            -120    Directory not found or incomplete pathname
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+
+    __________
+
+    See also:   FSpBumpDate
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   FSpBumpDate(const FSSpec *spec);
+/*   Update the modification date of a file or directory.
+    The FSpBumpDate function changes the modification date of a file or
+    directory to the current date/time.  If the modification date is already
+    equal to the current date/time, then add one second to the
+    modification date.
+
+    spec    input:  An FSSpec record specifying the object.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File not found
+        fLckdErr            -45     File is locked
+        vLckdErr            -46     Volume is locked or read-only
+        paramErr            -50     No default volume
+        dirNFErr            -120    Directory not found or incomplete pathname
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+
+    __________
+
+    See also:   BumpDate
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   OnLine(FSSpecPtr volumes,
+                       short reqVolCount,
+                       short *actVolCount,
+                       short *volIndex);
+/*   Return the list of volumes currently mounted.
+    The OnLine function returns the list of volumes currently mounted in
+    an array of FSSpec records.
+
+    A noErr result indicates that the volumes array was filled
+    (actVolCount == reqVolCount) and there may be additional volumes
+    mounted. A nsvErr result indicates that the end of the volume list
+    was found and actVolCount volumes were actually found this time.
+
+    volumes     input:  Pointer to array of FSSpec where the volume list
+                        is returned.
+    reqVolCount input:  Maximum number of volumes to return (the number of
+                        elements in the volumes array).
+    actVolCount output: The number of volumes actually returned.
+    volIndex    input:  The current volume index position. Set to 1 to
+                        start with the first volume.
+                output: The volume index position to get the next volume.
+                        Pass this value the next time you call OnLine to
+                        start where you left off.
+
+    Result Codes
+        noErr               0       No error, but there are more volumes
+                                    to list
+        nsvErr              -35     No more volumes to be listed
+        paramErr            -50     volIndex was <= 0
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   DTGetComment(short vRefNum,
+                             long dirID,
+                             ConstStr255Param name,
+                             Str255 comment);
+/*   Get a file or directory's Finder comment field (if any).
+    The DTGetComment function gets a file or directory's Finder comment
+    field (if any) from the Desktop Manager or if the Desktop Manager is
+    not available, from the Finder's Desktop file.
+
+    IMPORTANT NOTE: Inside Macintosh says that comments are up to
+    200 characters. While that may be correct for the HFS file system's
+    Desktop Manager, other file systems (such as Apple Photo Access) return
+    up to 255 characters. Make sure the comment buffer is a Str255 or you'll
+    regret it.
+
+    vRefNum input:  Volume specification.
+    dirID   input:  Directory ID.
+    name    input:  Pointer to object name, or nil when dirID
+                    specifies a directory that's the object.
+    comment output: A Str255 where the comment is to be returned.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     Volume not found
+        ioErr               -36     I/O error
+        fnfErr              -43     File not found
+        paramErr            -50     Volume doesn't support this function
+        rfNumErr            -51     Reference number invalid
+        extFSErr            -58     External file system error - no file
+                                    system claimed this call.
+        desktopDamagedErr   -1305   The desktop database has become corrupted -
+                                    the Finder will fix this, but if your
+                                    application is not running with the
+                                    Finder, use PBDTReset or PBDTDelete
+        afpItemNotFound     -5012   Information not found
+
+    __________
+
+    Also see:   DTCopyComment, FSpDTCopyComment, DTSetComment, FSpDTSetComment,
+                FSpDTGetComment
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   FSpDTGetComment(const FSSpec *spec,
+                                Str255 comment);
+/*   Get a file or directory's Finder comment field (if any).
+    The FSpDTGetComment function gets a file or directory's Finder comment
+    field (if any) from the Desktop Manager or if the Desktop Manager is
+    not available, from the Finder's Desktop file.
+
+    IMPORTANT NOTE: Inside Macintosh says that comments are up to
+    200 characters. While that may be correct for the HFS file system's
+    Desktop Manager, other file systems (such as Apple Photo Access) return
+    up to 255 characters. Make sure the comment buffer is a Str255 or you'll
+    regret it.
+
+    spec    input:  An FSSpec record specifying the file or directory.
+    comment output: A Str255 where the comment is to be returned.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     Volume not found
+        ioErr               -36     I/O error
+        fnfErr              -43     File not found
+        paramErr            -50     Volume doesn't support this function
+        rfNumErr            -51     Reference number invalid
+        extFSErr            -58     External file system error - no file
+                                    system claimed this call.
+        desktopDamagedErr   -1305   The desktop database has become corrupted -
+                                    the Finder will fix this, but if your
+                                    application is not running with the
+                                    Finder, use PBDTReset or PBDTDelete
+        afpItemNotFound     -5012   Information not found
+
+    __________
+
+    Also see:   DTCopyComment, FSpDTCopyComment, DTSetComment, FSpDTSetComment,
+                DTGetComment
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   DTOpen(ConstStr255Param volName,
+                       short vRefNum,
+                       short *dtRefNum,
+                       Boolean *newDTDatabase);
+/*   Open a volume's desktop database and return the desktop database refNum.
+    The DTOpen function opens a volume's desktop database. It returns
+    the reference number of the desktop database and indicates if the
+    desktop database was created as a result of this call (if it was created,
+    then it is empty).
+
+    volName         input:  A pointer to the name of a mounted volume
+                            or nil.
+    vRefNum         input:  Volume specification.
+    dtRefNum        output: The reference number of Desktop Manager's
+                            desktop database on the specified volume.
+    newDTDatabase   output: true if the desktop database was created as a
+                            result of this call and thus empty.
+                            false if the desktop database was already created,
+                            or if it could not be determined if it was already
+                            created.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     Volume not found
+        ioErr               -36     I/O error
+        paramErr            -50     Volume doesn't support this function
+        extFSErr            -58     External file system error - no file
+                                    system claimed this call.
+        desktopDamagedErr   -1305   The desktop database has become corrupted -
+                                    the Finder will fix this, but if your
+                                    application is not running with the
+                                    Finder, use PBDTReset or PBDTDelete
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   HGetVolParms(ConstStr255Param volName,
+                             short vRefNum,
+                             GetVolParmsInfoBuffer *volParmsInfo,
+                             long *infoSize);
+/*   Determine the characteristics of a volume.
+    The HGetVolParms function returns information about the characteristics
+    of a volume. A result of paramErr usually just means the volume doesn't
+    support PBHGetVolParms and the feature you were going to check
+    for isn't available.
+
+    volName         input:  A pointer to the name of a mounted volume
+                            or nil.
+    vRefNum         input:  Volume specification.
+    volParmsInfo    input:  Pointer to GetVolParmsInfoBuffer where the
+                            volume attributes information is returned.
+                    output: Atributes information.
+    infoSize        input:  Size of buffer pointed to by volParmsInfo.
+                    output: Size of data actually returned.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     Volume not found
+        paramErr            -50     Volume doesn't support this function
+
+    __________
+
+    Also see the macros for checking attribute bits in MoreFilesExtras.h
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   DeleteDirectoryContents(short vRefNum,
+                                        long dirID,
+                                        ConstStr255Param name);
+/*   Delete the contents of a directory.
+    The DeleteDirectoryContents function deletes the contents of a directory.
+    All files and subdirectories in the specified directory are deleted.
+    If a locked file or directory is encountered, it is unlocked and then
+    deleted.  If any unexpected errors are encountered,
+    DeleteDirectoryContents quits and returns to the caller.
+
+    vRefNum input:  Volume specification.
+    dirID   input:  Directory ID.
+    name    input:  Pointer to directory name, or nil when dirID specifies
+                    a directory that's the object.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File not found
+        wPrErr              -44     Hardware volume lock
+        fLckdErr            -45     File is locked
+        vLckdErr            -46     Software volume lock
+        fBsyErr             -47     File busy, directory not empty, or working
+                                    directory control block open
+        paramErr            -50     No default volume
+        dirNFErr            -120    Directory not found or incomplete pathname
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+
+    __________
+
+    Also see:   DeleteDirectory
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   DeleteDirectory(short vRefNum,
+                                long dirID,
+                                ConstStr255Param name);
+/*   Delete a directory and its contents.
+    The DeleteDirectory function deletes a directory and its contents.
+    All files and subdirectories in the specified directory are deleted.
+    If a locked file or directory is encountered, it is unlocked and then
+    deleted.  After deleting the directories contents, the directory is
+    deleted. If any unexpected errors are encountered, DeleteDirectory
+    quits and returns to the caller.
+
+    vRefNum input:  Volume specification.
+    dirID   input:  Directory ID.
+    name    input:  Pointer to directory name, or nil when dirID specifies
+                    a directory that's the object.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File not found
+        wPrErr              -44     Hardware volume lock
+        fLckdErr            -45     File is locked
+        vLckdErr            -46     Software volume lock
+        fBsyErr             -47     File busy, directory not empty, or working
+                                    directory control block open
+        paramErr            -50     No default volume
+        dirNFErr            -120    Directory not found or incomplete pathname
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+
+    __________
+
+    Also see:   DeleteDirectoryContents
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   DTSetComment(short vRefNum,
+                             long dirID,
+                             ConstStr255Param name,
+                             ConstStr255Param comment);
+/*   Set a file or directory's Finder comment field.
+    The DTSetComment function sets a file or directory's Finder comment
+    field. The volume must support the Desktop Manager because you only
+    have read access to the Desktop file.
+
+    vRefNum input:  Volume specification.
+    dirID   input:  Directory ID.
+    name    input:  Pointer to object name, or nil when dirID
+                    specifies a directory that's the object.
+    comment input:  The comment to add. Comments are limited to 200 characters;
+                    longer comments are truncated.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     Volume not found
+        ioErr               -36     I/O error
+        fnfErr              -43     File or directory doesnt exist
+        paramErr            -50     Volume doesn't support this function
+        wPrErr              -44     Volume is locked through hardware
+        vLckdErr            -46     Volume is locked through software
+        rfNumErr            -51     Reference number invalid
+        extFSErr            -58     External file system error - no file
+                                    system claimed this call.
+        desktopDamagedErr   -1305   The desktop database has become corrupted -
+                                    the Finder will fix this, but if your
+                                    application is not running with the
+                                    Finder, use PBDTReset or PBDTDelete
+
+    __________
+
+    Also see:   DTCopyComment, FSpDTCopyComment, FSpDTSetComment, DTGetComment,
+                FSpDTGetComment
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   FSpDTSetComment(const FSSpec *spec,
+                                ConstStr255Param comment);
+/*   Set a file or directory's Finder comment field.
+    The FSpDTSetComment function sets a file or directory's Finder comment
+    field. The volume must support the Desktop Manager because you only
+    have read access to the Desktop file.
+
+    spec    input:  An FSSpec record specifying the file or directory.
+    comment input:  The comment to add. Comments are limited to 200 characters;
+                    longer comments are truncated.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     Volume not found
+        ioErr               -36     I/O error
+        fnfErr              -43     File or directory doesnt exist
+        wPrErr              -44     Volume is locked through hardware
+        vLckdErr            -46     Volume is locked through software
+        rfNumErr            -51     Reference number invalid
+        paramErr            -50     Volume doesn't support this function
+        extFSErr            -58     External file system error - no file
+                                    system claimed this call.
+        desktopDamagedErr   -1305   The desktop database has become corrupted -
+                                    the Finder will fix this, but if your
+                                    application is not running with the
+                                    Finder, use PBDTReset or PBDTDelete
+
+    __________
+
+    Also see:   DTCopyComment, FSpDTCopyComment, DTSetComment, DTGetComment,
+                FSpDTGetComment
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   XGetVInfo(short volReference,
+                          StringPtr volName,
+                          short *vRefNum,
+                          UnsignedWide *freeBytes,
+                          UnsignedWide *totalBytes);
+/*   Get extended information about a mounted volume.
+    The XGetVInfo function returns the name, volume reference number,
+    available space (in bytes), and total space (in bytes) for the
+    specified volume. You can specify the volume by providing its drive
+    number, volume reference number, or 0 for the default volume.
+    This routine is compatible with volumes up to 2 terabytes.
+
+    volReference    input:  The drive number, volume reference number,
+                            or 0 for the default volume.
+    volName         input:  A pointer to a buffer (minimum Str27) where
+                            the volume name is to be returned or must
+                            be nil.
+                    output: The volume name.
+    vRefNum         output: The volume reference number.
+    freeBytes       output: The number of free bytes on the volume.
+                            freeBytes is an UnsignedWide value.
+    totalBytes      output: The total number of bytes on the volume.
+                            totalBytes is an UnsignedWide value.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        paramErr            -50     No default volume
+
+    __________
+
+    Also see:   HGetVInfo
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   HGetVInfo(short volReference,
+                          StringPtr volName,
+                          short *vRefNum,
+                          unsigned long *freeBytes,
+                          unsigned long *totalBytes);
+/*   Get information about a mounted volume.
+    The HGetVInfo function returns the name, volume reference number,
+    available space (in bytes), and total space (in bytes) for the
+    specified volume. You can specify the volume by providing its drive
+    number, volume reference number, or 0 for the default volume.
+    This routine is compatible with volumes up to 4 gigabytes.
+
+    volReference    input:  The drive number, volume reference number,
+                            or 0 for the default volume.
+    volName         input:  A pointer to a buffer (minimum Str27) where
+                            the volume name is to be returned or must
+                            be nil.
+                    output: The volume name.
+    vRefNum         output: The volume reference number.
+    freeBytes       output: The number of free bytes on the volume.
+                            freeBytes is an unsigned long value.
+    totalBytes      output: The total number of bytes on the volume.
+                            totalBytes is an unsigned long value.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        paramErr            -50     No default volume
+
+    __________
+
+    Also see:   XGetVInfo
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   GetDirName(short vRefNum,
+                           long dirID,
+                           Str31 name);
+/*   Get the name of a directory from its directory ID.
+    The GetDirName function gets the name of a directory from its
+    directory ID.
+
+    vRefNum     input:  Volume specification.
+    dirID       input:  Directory ID.
+    name        output: Points to a Str31 where the directory name is to be
+                        returned.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File not found
+        paramErr            -50     No default volume or
+                                    name parameter was NULL
+        dirNFErr            -120    Directory not found or incomplete pathname
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+*/
+
+
+/*****************************************************************************/
+
+pascal  OSErr   GetVolFileSystemID(ConstStr255Param pathname,
+                                   short vRefNum,
+                                   short *fileSystemID);
+/*   Get a volume's file system ID.
+    The GetVolFileSystemID function returned the file system ID of
+    a mounted volume. The file system ID identifies the file system
+    that handles requests to a particular volume. Here's a partial list
+    of file system ID numbers (only Apple's file systems are listed):
+        FSID    File System
+        -----   -----------------------------------------------------
+        $0000   Macintosh HFS or MFS
+        $0100   ProDOS File System
+        $0101   PowerTalk Mail Enclosures
+        $4147   ISO 9660 File Access (through Foreign File Access)
+        $4242   High Sierra File Access (through Foreign File Access)
+        $464D   QuickTake File System (through Foreign File Access)
+        $4953   Macintosh PC Exchange (MS-DOS)
+        $4A48   Audio CD Access (through Foreign File Access)
+        $4D4B   Apple Photo Access (through Foreign File Access)
+
+    See the Technical Note "FL 35 - Determining Which File System
+    Is Active" and the "Guide to the File System Manager" for more
+    information.
+
+    pathName        input:  Pointer to a full pathname or nil.  If you pass
+                            in a partial pathname, it is ignored. A full
+                            pathname to a volume must contain at least
+                            one colon character (:) and must not start with
+                            a colon character.
+    vRefNum         input:  Volume specification (volume reference number,
+                            working directory number, drive number, or 0).
+    fileSystemID    output: The volume's file system ID.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        paramErr            -50     No default volume, or pb was NULL
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr GetDInfo(short vRefNum,
+                       long dirID,
+                       ConstStr255Param name,
+                       DInfo *fndrInfo);
+/*   Get the finder information for a directory.
+    The GetDInfo function gets the finder information for a directory.
+
+    vRefNum         input:  Volume specification.
+    dirID           input:  Directory ID.
+    name            input:  Pointer to object name, or nil when dirID
+                            specifies a directory that's the object.
+    fndrInfo        output: If the object is a directory, then its DInfo.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File not found
+        paramErr            -50     No default volume
+        dirNFErr            -120    Directory not found or incomplete pathname
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+
+    __________
+
+    Also see:   FSpGetDInfo, FSpGetFInfoCompat
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr FSpGetDInfo(const FSSpec *spec,
+                          DInfo *fndrInfo);
+/*   Get the finder information for a directory.
+    The FSpGetDInfo function gets the finder information for a directory.
+
+    spec        input:  An FSSpec record specifying the directory.
+    fndrInfo    output: If the object is a directory, then its DInfo.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File not found
+        paramErr            -50     No default volume
+        dirNFErr            -120    Directory not found or incomplete pathname
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+
+    __________
+
+    Also see:   FSpGetFInfoCompat, GetDInfo
+*/
+
+
+#endif    /*  _MACSTUFF_H  */
diff --git a/macos/source/mactime.c b/macos/source/mactime.c
new file mode 100644 (file)
index 0000000..fcdd440
--- /dev/null
@@ -0,0 +1,451 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.htmlhtml
+*/
+/* -----------------------------------------------------------------------------
+
+The original functions (Metrowerks Codewarrior pro 3.0) gmtime, localtime,
+mktime and time do not work correctly. The supplied link library mactime.c
+contains replacement functions for them.
+
+ *     Caveat: On a Mac, we only know the GMT and DST offsets for
+ *     the current time, not for the time in question.
+ *     Mac has no support for DST handling.
+ *     DST changeover is all manually set by the user.
+
+
+------------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/*  Includes                                                                 */
+/*****************************************************************************/
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <OSUtils.h>
+
+#include "mactime.h"
+
+
+/*
+The MacOS function GetDateTime returns  the
+number of seconds elapsed since midnight, January 1, 1904.
+*/
+const unsigned long MacOS_2_Unix = 2082844800L;
+
+
+/*****************************************************************************/
+/*  Macros, typedefs                                                         */
+/*****************************************************************************/
+
+
+#ifndef TEST_TIME_LIB
+#define my_gmtime    gmtime
+#define my_localtime localtime
+#define my_mktime    mktime
+#define my_time      time
+#endif
+
+
+/*****************************************************************************/
+/*  Prototypes                                                               */
+/*****************************************************************************/
+/* internal prototypes */
+static void clear_tm(struct tm * tm);
+static long GMTDelta(void);
+static Boolean DaylightSaving(void);
+static time_t GetTimeMac(void);
+static time_t Mactime(time_t *timer);
+static void   normalize(int *i,int *j,int norm);
+static struct tm *time2tm(const time_t *timer);
+static time_t tm2time(struct tm *tp);
+
+/* Because serial port and SLIP conflict with ReadXPram calls,
+   we cache the call here so we don't hang on calling ReadLocation()  */
+static void myReadLocation(MachineLocation * loc);
+
+
+/* prototypes for STD lib replacement functions */
+struct tm *my_gmtime(const time_t *t);
+struct tm *my_localtime(const time_t *t);
+time_t my_mktime(struct tm *tp);
+time_t my_time(time_t *t);
+
+
+/*****************************************************************************/
+/*  Functions                                                                */
+/*****************************************************************************/
+
+ /*
+ *  Mac file times are based on 1904 Jan 1 00:00 local time,
+ *  not 1970 Jan 1 00:00 UTC.
+ *  So we have to convert the time stamps into UNIX UTC
+ *  compatible values.
+ */
+time_t MacFtime2UnixFtime(unsigned long macftime)
+{
+    long UTCoffset;
+
+    GetGMToffsetMac(macftime, &UTCoffset);
+    MACOS_TO_UNIX(macftime);
+    macftime -= UTCoffset;
+
+    return macftime;
+}
+
+
+ /*
+ *  Mac file times are based on 1904 Jan 1 00:00 local time,
+ *  not 1970 Jan 1 00:00 UTC.
+ *  So we have to convert the time stamps into MacOS local
+ *  compatible values.
+ */
+unsigned long UnixFtime2MacFtime(time_t unxftime)
+{
+    long UTCoffset;
+    unsigned long macftime = unxftime;
+
+    UNIX_TO_MACOS(macftime);
+    GetGMToffsetMac(macftime, &UTCoffset);
+    macftime += UTCoffset;
+
+    return macftime;
+}
+
+
+
+
+
+/*
+* This function convert a file-localtime to an another
+* file-localtime.
+*/
+time_t AdjustForTZmoveMac(unsigned long macloctim, long s_gmtoffs)
+{
+    time_t MacGMTTime;
+    long UTCoffset;
+
+    /* convert macloctim into corresponding UTC value */
+    MacGMTTime = macloctim - s_gmtoffs;
+    GetGMToffsetMac(macloctim, &UTCoffset);
+
+    return (MacGMTTime + UTCoffset);
+} /* AdjustForTZmove() */
+
+
+
+
+/*
+ * This function calculates the difference between the supplied Mac
+ * ftime value (local time) and the corresponding UTC time in seconds.
+ */
+Boolean GetGMToffsetMac(unsigned long mactime, long *UTCoffset)
+{
+
+mactime = mactime;
+/*
+ *     Caveat: On a Mac, we only know the GMT and DST offsets for
+ *     the current time, not for the time in question.
+ *     Mac has no support for DST handling.
+ *     DST changeover is all manually set by the user.
+
+ May be later I can include a support of GMT offset calculation for the
+ time in question here.
+*/
+    *UTCoffset = GMTDelta();
+
+    return true;
+}
+
+
+
+
+
+
+
+/*****************************************************************************
+ *  Standard Library Replacement Functions
+ *  gmtime(), mktime(), localtime(), time()
+ *
+ *  The unix epoch is used here.
+ *  These functions gmtime(), mktime(), localtime() and time()
+ *  expects and returns unix times.
+ *
+ * At midnight Jan. 1, 1970 GMT, the local time was
+ *    midnight Jan. 1, 1970 + GMTDelta().
+ *
+ *
+ *****************************************************************************/
+
+
+struct tm *my_gmtime(const time_t *timer)
+{
+    return time2tm(timer);
+}
+
+
+
+
+struct tm *my_localtime(const time_t *timer)
+{
+    time_t maclocal;
+
+    maclocal = *timer;
+    maclocal += GMTDelta();
+
+    return time2tm(&maclocal);
+}
+
+
+
+
+time_t my_mktime(struct tm *tp)
+{
+    time_t maclocal;
+
+    maclocal = tm2time(tp);
+    maclocal -= GMTDelta();
+
+    return maclocal;
+}
+
+
+
+
+
+
+time_t my_time(time_t *time)
+{
+time_t tmp_time;
+
+GetDateTime(&tmp_time);
+
+MACOS_TO_UNIX(tmp_time);
+
+if (time)
+    {
+    *time = tmp_time;
+    }
+
+return tmp_time;
+}
+
+
+
+/*****************************************************************************/
+/*  static module level functions
+/*****************************************************************************/
+
+
+/*
+ * The geographic location and time zone information of a Mac
+ * are stored in extended parameter RAM.  The ReadLocation
+ * produdure uses the geographic location record, MachineLocation,
+ * to read the geographic location and time zone information in
+ * extended parameter RAM.
+ *
+ * Because serial port and SLIP conflict with ReadXPram calls,
+ * we cache the call here.
+ *
+ * Caveat: this caching will give the wrong result if a session
+ * extend across the DST changeover time, but
+ * this function resets itself every 2 hours.
+ */
+static void myReadLocation(MachineLocation * loc)
+{
+    static MachineLocation storedLoc;   /* InsideMac, OSUtilities, page 4-20  */
+    static time_t first_call = 0, last_call = 86400;
+
+    if ((last_call - first_call) > 7200)
+        {
+        GetDateTime(&first_call);
+        ReadLocation(&storedLoc);
+        }
+
+    GetDateTime(&last_call);
+    *loc = storedLoc;
+}
+
+
+
+
+static Boolean DaylightSaving(void)
+{
+    MachineLocation loc;
+    unsigned char dlsDelta;
+
+    myReadLocation(&loc);
+    dlsDelta =  loc.u.dlsDelta;
+
+    return (dlsDelta != 0);
+}
+
+
+
+
+/* current local time = GMTDelta() + GMT
+   GMT = local time - GMTDelta()    */
+static long GMTDelta(void)
+{
+    MachineLocation loc;
+    long gmtDelta;
+
+    myReadLocation(&loc);
+
+    /*
+     * On a Mac, the GMT value is in seconds east of GMT.  For example,
+     * San Francisco is at -28,800 seconds (8 hours * 3600 seconds per hour)
+     * east of GMT.  The gmtDelta field is a 3-byte value contained in a
+     * long word, so you must take care to get it properly.
+     */
+    gmtDelta = loc.u.gmtDelta & 0x00FFFFFF;
+    if ((gmtDelta & 0x00800000) != 0)
+        {
+        gmtDelta |= 0xFF000000;
+        }
+
+    return gmtDelta;
+}
+
+
+
+/* This routine simulates stdclib time(), time in seconds since 1.1.1970
+   The time is in GMT  */
+static time_t GetTimeMac(void)
+{
+    unsigned long maclocal;
+
+
+    /*
+     * Get the current time expressed as the number of seconds
+     * elapsed since the Mac epoch, midnight, Jan. 1, 1904 (local time).
+     * On a Mac, current time accuracy is up to a second.
+     */
+
+    GetDateTime(&maclocal);     /* Get Mac local time  */
+    maclocal -= GMTDelta();     /* Get Mac GMT  */
+    MACOS_TO_UNIX(maclocal);
+
+    return maclocal;            /* return unix GMT  */
+}
+
+
+
+
+/*
+ *  clear_tm - sets a broken-down time to the equivalent of 1970/1/1 00:00:00
+ */
+
+static void clear_tm(struct tm * tm)
+{
+    tm->tm_sec   =  0;
+    tm->tm_min   =  0;
+    tm->tm_hour  =  0;
+    tm->tm_mday  =  1;
+    tm->tm_mon   =  0;
+    tm->tm_year  =  0;
+    tm->tm_wday  =  1;
+    tm->tm_yday  =  0;
+    tm->tm_isdst = -1;
+}
+
+
+static void normalize(int *i,int *j,int norm)
+{
+  while(*i < 0)
+    {
+    *i += norm;
+    (*j)--;
+    }
+
+  while(*i >= norm)
+    {
+    *i -= norm;
+    (*j)++;
+    }
+}
+
+
+
+/*  Returns the GMT times  */
+static time_t Mactime(time_t *timer)
+{
+    time_t t = GetTimeMac();
+
+    if (timer != NULL)
+        *timer = t;
+
+    return t;
+}
+
+
+
+
+static struct tm *time2tm(const time_t *timer)
+{
+    DateTimeRec dtr;
+    MachineLocation loc;
+    time_t macLocal = *timer;
+
+    static struct tm statictime;
+    static const short monthday[12] =
+        {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+    UNIX_TO_MACOS(macLocal);
+    SecondsToDate(macLocal, &dtr);
+
+    statictime.tm_sec  = dtr.second;         /* second, from 0 to 59 */
+    statictime.tm_min  = dtr.minute;         /* minute, from 0 to 59 */
+    statictime.tm_hour = dtr.hour;           /* hour, from 0 to 23 */
+    statictime.tm_mday = dtr.day;            /* day of the month, from 1 to 31 */
+    statictime.tm_mon  = dtr.month     - 1;  /* month, 1= January and 12 = December */
+    statictime.tm_year = dtr.year   - 1900;  /* year, ranging from 1904 to 2040 */
+    statictime.tm_wday = dtr.dayOfWeek - 1;  /* day of the week, 1 = Sun, 7 = Sat */
+
+    statictime.tm_yday = monthday[statictime.tm_mon]
+                         + statictime.tm_mday - 1;
+
+    if (2 < statictime.tm_mon && !(statictime.tm_year & 3))
+        {
+        ++statictime.tm_yday;
+        }
+
+    myReadLocation(&loc);
+    statictime.tm_isdst = DaylightSaving();
+
+    return(&statictime);
+}
+
+
+
+
+
+static time_t tm2time(struct tm *tp)
+{
+time_t intMacTime;
+DateTimeRec  dtr;
+
+ normalize(&tp->tm_sec, &tp->tm_min, 60);
+ normalize(&tp->tm_min, &tp->tm_hour,60);
+ normalize(&tp->tm_hour,&tp->tm_mday,24);
+ normalize(&tp->tm_mon, &tp->tm_year,12);
+
+ dtr.year    = tp->tm_year + 1900;  /* years since 1900 */
+ dtr.month   = tp->tm_mon  +    1;  /* month, 0 = January and 11 = December */
+ dtr.day     = tp->tm_mday;         /* day of the month, from 1 to 31 */
+ dtr.hour    = tp->tm_hour;         /* hour, from 0 to 23 */
+ dtr.minute  = tp->tm_min;          /* minute, from 0 to 59 */
+ dtr.second  = tp->tm_sec;          /* second, from 0 to 59 */
+
+ DateToSeconds(&dtr, &intMacTime);
+
+ MACOS_TO_UNIX(intMacTime);
+
+ return intMacTime;
+}
diff --git a/macos/source/mactime.h b/macos/source/mactime.h
new file mode 100644 (file)
index 0000000..fa70c7f
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef _MACTIME_H_
+#define _MACTIME_H_
+/* -----------------------------------------------------------------------------
+
+The original functions (Metrowerks Codewarrior pro 3.0) gmtime, localtime,
+mktime and time do not work correctly. The supplied link library mactime.c
+contains replacement functions for them.
+
+ *     Caveat: On a Mac, we only know the GMT and DST offsets for
+ *     the current time, not for the time in question.
+ *     Mac has no support for DST handling.
+ *     DST changeover is all manually set by the user.
+
+
+------------------------------------------------------------------------------*/
+
+#include <time.h>
+#include <mactypes.h>
+
+/*****************************************************************************/
+/*  Macros, typedefs                                                         */
+/*****************************************************************************/
+
+
+  /*
+   * ARGH.  Mac times are based on 1904 Jan 1 00:00, not 1970 Jan 1 00:00.
+   *  So we have to diddle time_t's appropriately:  add or subtract 66 years'
+   *  worth of seconds == number of days times 86400 == (66*365 regular days +
+   *  17 leap days ) * 86400 == (24090 + 17) * 86400 == 2082844800L seconds.
+   *  We hope time_t is an unsigned long (ulg) on the Macintosh...
+   */
+/*
+This Offset is only used by MacFileDate_to_UTime()
+*/
+
+#define MACOS_TO_UNIX(x)  (x) -= (unsigned long)MacOS_2_Unix
+#define UNIX_TO_MACOS(x)  (x) += (unsigned long)MacOS_2_Unix
+
+/*
+The MacOS function GetDateTime returns  the
+number of seconds elapsed since midnight, January 1, 1904.
+*/
+extern const unsigned long MacOS_2_Unix;
+
+
+/* prototypes for public utility functions */
+time_t MacFtime2UnixFtime(unsigned long macftime);
+unsigned long UnixFtime2MacFtime(time_t unxftime);
+time_t  AdjustForTZmoveMac(unsigned long macloctim, long s_gmtoffs);
+Boolean GetGMToffsetMac(unsigned long macftime, long *UTCoffset);
+
+
+#endif
diff --git a/macos/source/pathname.c b/macos/source/pathname.c
new file mode 100644 (file)
index 0000000..166d872
--- /dev/null
@@ -0,0 +1,665 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.htmlhtml
+*/
+/*---------------------------------------------------------------------------
+
+  pathname.c
+
+  Function dealing with the pathname. Mostly C-string work.
+
+  ---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/*  Includes                                                                 */
+/*****************************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sound.h>
+
+#include "pathname.h"
+#include "helpers.h"
+#include "macstuff.h"
+
+
+/*****************************************************************************/
+/*  Global Vars                                                              */
+/*****************************************************************************/
+
+const char  ResourceMark[] = "XtraStuf.mac:";  /* see also macos.c */
+
+
+#include "zip.h"
+
+
+
+
+/*****************************************************************************/
+/*  Functions                                                                */
+/*****************************************************************************/
+
+
+
+
+/*
+**  return volumename from pathname
+**
+*/
+
+unsigned short GetVolumeFromPath(const char *FullPath, char *VolumeName)
+{
+const char *VolEnd, *tmpPtr1;
+char *tmpPtr2 = VolumeName;
+
+AssertStr(FullPath,"GetVolumeFromPath")
+
+for (VolEnd = FullPath; *VolEnd != '\0' && *VolEnd != ':'; VolEnd++)
+      ;
+if (*VolEnd == '\0') return 0;
+
+for (tmpPtr1 = FullPath; tmpPtr1 != VolEnd;)
+    {
+    *tmpPtr2++ = *tmpPtr1++;
+    }
+
+*tmpPtr2 = '\0';
+
+return (unsigned short) strlen(VolumeName);
+}
+
+
+
+/***********************************/
+/* Function FindNewExtractFolder() */
+/***********************************/
+
+char *FindNewExtractFolder(char *ExtractPath)
+{
+char buffer[NAME_MAX], *tmpPtr, *namePtr;
+short count = 0, folderCount = 0;
+OSErr err;
+FSSpec Spec;
+long theDirID;
+Boolean isDirectory;
+unsigned short namelen, pathlen = strlen(ExtractPath);
+
+AssertStr(ExtractPath,"FindNewExtractFolder ExtractPath == NULL")
+
+for (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++)
+    if (*tmpPtr == ':')
+        {
+        folderCount++;
+        namePtr = tmpPtr;
+        }
+
+if (folderCount > 1)
+    namelen = strlen(namePtr);
+else
+    namelen = strlen(ExtractPath);
+
+for (count = 0; count < 99; count++)
+    {
+    memset(buffer,0,sizeof(buffer));
+
+    if (namelen >= 28)
+        ExtractPath[pathlen-2] = 0x0;
+    else
+        ExtractPath[pathlen-1] = 0x0;
+
+    sprintf(buffer,"%s%d",ExtractPath,count);
+    GetCompletePath(ExtractPath, buffer, &Spec,&err);
+    err = FSpGetDirectoryID(&Spec, &theDirID, &isDirectory);
+    if (err == -43) break;
+    }
+
+/* Foldernames must always end with a colon  */
+sstrcat(ExtractPath,":");
+return ExtractPath;
+}
+
+
+
+/*
+**  creates an archive file name
+**
+*/
+
+void createArchiveName(char *thePath)
+{
+char *tmpPtr, *namePtr;
+short folderCount = 0;
+unsigned short namelen, pathlen = strlen(thePath);
+
+if (thePath[pathlen-1] == ':') thePath[pathlen-1] = 0x0;
+
+for (tmpPtr = thePath; *tmpPtr; tmpPtr++)
+    if (*tmpPtr == ':')
+        {
+        folderCount++;
+        namePtr = tmpPtr;
+        }
+
+namelen = strlen(namePtr);
+
+    /* we have to eliminate illegal chars:
+     * The name space for Mac filenames and Zip filenames (unix style names)
+     * do both include all printable extended-ASCII characters.  The only
+     * difference we have to take care of is the single special character
+     * used as path delimiter:
+     * ':' on MacOS and '/' on Unix and '\' on Dos.
+     * So, to convert between Mac filenames and Unix filenames without any
+     * loss of information, we simply interchange ':' and '/'.  Additionally,
+     * we try to convert the coding of the extended-ASCII characters into
+     * InfoZip's standard ISO 8859-1 codepage table.
+     */
+  MakeCompatibleString(namePtr, '/', '_', '.', '-', -1);
+
+ /* Avoid filenames like: "Archive..zip"  */
+if (thePath[pathlen-1] == '.')
+    {
+    thePath[pathlen-1] = 0;
+    }
+
+if (folderCount >= 1)
+    { /* path contains at least one folder */
+
+    if (namelen >= 28)
+        {
+        pathlen = pathlen-4;
+        }
+
+    thePath[pathlen]   = '.';
+    thePath[pathlen+1] = 'z';
+    thePath[pathlen+2] = 'i';
+    thePath[pathlen+3] = 'p';
+    thePath[pathlen+4] = 0x0;
+    return;
+    }
+else
+    {  /* path contains no folder */
+    FindDesktopFolder(thePath);
+    createArchiveName(thePath);
+    }
+}
+
+
+
+/*
+** finds the desktop-folder on a volume with
+** largest amount of free-space.
+*/
+
+void FindDesktopFolder(char *Path)
+{
+char buffer[255];
+FSSpec  volumes[50];        /* 50 Volumes should be enough */
+short   actVolCount, volIndex = 1, VolCount = 0;
+OSErr   err;
+short     i, foundVRefNum;
+FSSpec spec;
+UnsignedWide freeBytes;
+UnsignedWide totalBytes;
+UnsignedWide MaxFreeBytes;
+
+err = OnLine(volumes, 50, &actVolCount, &volIndex);
+printerr("OnLine:", (err != -35) && (err != 0), err, __LINE__, __FILE__, "");
+
+MaxFreeBytes.hi = 0;
+MaxFreeBytes.lo = 0;
+
+for (i=0; i < actVolCount; i++)
+    {
+    XGetVInfo(volumes[i].vRefNum,
+              volumes[i].name,
+              &volumes[i].vRefNum,
+              &freeBytes,
+              &totalBytes);
+
+    if (MaxFreeBytes.hi < freeBytes.hi) {
+        MaxFreeBytes.hi = freeBytes.hi;
+        MaxFreeBytes.lo = freeBytes.lo;
+        foundVRefNum = volumes[i].vRefNum;
+    }
+
+    if ((freeBytes.hi == 0) && (MaxFreeBytes.lo < freeBytes.lo)) {
+        MaxFreeBytes.hi = freeBytes.hi;
+        MaxFreeBytes.lo = freeBytes.lo;
+        foundVRefNum = volumes[i].vRefNum;
+    }
+
+}
+
+ FSpFindFolder(foundVRefNum, kDesktopFolderType,
+            kDontCreateFolder,&spec);
+
+ GetFullPathFromSpec(buffer, &spec , &err);
+ sstrcat(buffer,Path);
+ sstrcpy(Path,buffer);
+}
+
+
+/*
+**  return the path without the filename
+**
+*/
+
+char *TruncFilename(char *DirPath, const char *FilePath)
+{
+char *tmpPtr;
+char *dirPtr = NULL;
+
+AssertStr(DirPath,"TruncFilename")
+Assert_it(Spec,"TruncFilename","")
+
+sstrcpy(DirPath, FilePath);
+
+for (tmpPtr = DirPath; *tmpPtr; tmpPtr++)
+    if (*tmpPtr == ':')
+        dirPtr = tmpPtr;
+
+if (dirPtr)
+    *++dirPtr = '\0';
+else
+    printerr("TruncFilename: FilePath has no Folders", -1,
+         -1, __LINE__, __FILE__, FilePath);
+
+return DirPath;
+}
+
+
+
+/*
+**  return only filename
+**
+*/
+
+char *GetFilename(char *FileName, const char *FilePath)
+{
+const char *tmpPtr;
+const char *dirPtr = NULL;
+
+Assert_it(FileName,"GetFilename","")
+Assert_it(FilePath,"GetFilename","")
+
+for (tmpPtr = FilePath; *tmpPtr; tmpPtr++)
+    {
+    if (*tmpPtr == ':')
+        {
+        dirPtr = tmpPtr;
+        }
+    }
+
+if (dirPtr)
+    {
+    ++dirPtr;  /* jump over the ':' */
+    }
+else
+    {
+    return strcpy(FileName, FilePath); /* FilePath has no Folders */
+    }
+
+return strcpy(FileName, dirPtr);
+}
+
+
+
+/*
+**  return fullpathname from folder/dir-id
+**
+*/
+
+char *GetFullPathFromID(char *CompletePath, short vRefNum, long dirID,
+                        ConstStr255Param name, OSErr *err)
+{
+FSSpec      spec;
+
+    *err = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);
+    printerr("FSMakeFSSpecCompat:", (*err != -43) && (*err != 0), *err,
+             __LINE__, __FILE__, "");
+    if ( (*err == noErr) || (*err == fnfErr) )
+        {
+        return GetFullPathFromSpec(CompletePath, &spec, err);
+        }
+
+return NULL;
+}
+
+
+
+/*
+**  convert real-filename to archive-filename
+**
+*/
+
+char *Real2RfDfFilen(char *RfDfFilen, const char *RealPath,
+                    short CurrentFork, short MacZipMode, Boolean DataForkOnly)
+{
+
+AssertStr(RealPath,"Real2RfDfFilen")
+AssertStr(RfDfFilen,"Real2RfDfFilen")
+
+if (DataForkOnly) /* make no changes */
+    {
+    return sstrcpy(RfDfFilen, RealPath);
+    }
+
+switch (MacZipMode)
+    {
+    case JohnnyLee_EF:
+        {
+        sstrcpy(RfDfFilen, RealPath);
+        if (CurrentFork == DataFork)            /* data-fork  */
+            return sstrcat(RfDfFilen, "d");
+        if (CurrentFork == ResourceFork)        /* resource-fork */
+            return sstrcat(RfDfFilen, "r");
+        break;
+        }
+
+    case NewZipMode_EF:
+        {
+        switch (CurrentFork)
+            {
+            case DataFork:
+                {
+                sstrcpy(RfDfFilen, RealPath);
+                return RfDfFilen;  /* data-fork  */
+                break;
+                }
+            case ResourceFork:
+                {
+                sstrcpy(RfDfFilen, ResourceMark);
+                sstrcat(RfDfFilen, RealPath);  /* resource-fork */
+                return RfDfFilen;
+                break;
+                }
+            default:
+                {
+                printerr("Real2RfDfFilen:", -1, -1,
+                         __LINE__, __FILE__, RealPath);
+                return NULL;  /* function should never reach this point */
+                }
+            }
+        break;
+        }
+    default:
+        {
+        printerr("Real2RfDfFilen:", -1, -1, __LINE__, __FILE__, RealPath);
+        return NULL;  /* function should never reach this point */
+        }
+    }
+
+printerr("Real2RfDfFilen:", -1, -1, __LINE__, __FILE__, RealPath);
+return NULL;  /* function should never come reach this point */
+}
+
+
+
+/*
+**  convert archive-filename into a real filename
+**
+*/
+
+char *RfDfFilen2Real(char *RealFn, const char *RfDfFilen, short MacZipMode,
+                     Boolean DataForkOnly, short *CurrentFork)
+{
+short   length;
+int     result;
+
+AssertStr(RfDfFilen,"RfDfFilen2Real")
+
+if (DataForkOnly ||
+    (MacZipMode == UnKnown_EF) ||
+    (MacZipMode < JohnnyLee_EF))
+    {
+    *CurrentFork = DataFork;
+    return sstrcpy(RealFn,RfDfFilen);
+    }
+
+result = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2);
+if (result == 0)
+    {
+    MacZipMode = NewZipMode_EF;
+    }
+
+switch (MacZipMode)
+    {
+    case JohnnyLee_EF:
+        {
+        sstrcpy(RealFn, RfDfFilen);
+        length = strlen(RealFn);       /* determine Fork type */
+        if (RealFn[length-1] == 'd') *CurrentFork = DataFork;
+        else *CurrentFork = ResourceFork;
+        RealFn[length-1] = '\0';       /* simply cut one char  */
+        return RealFn;
+        break;
+        }
+
+    case NewZipMode_EF:
+        {                                   /* determine Fork type */
+        result = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2);
+        if (result != 0)
+            {
+            *CurrentFork = DataFork;
+            sstrcpy(RealFn, RfDfFilen);
+            return RealFn;  /* data-fork  */
+            }
+        else
+            {
+            *CurrentFork = ResourceFork;
+            if (strlen(RfDfFilen) > (sizeof(ResourceMark) - 1))
+                {
+                sstrcpy(RealFn, &RfDfFilen[sizeof(ResourceMark)-1]);
+                }
+            else RealFn[0] = '\0';
+            return RealFn;  /* resource-fork */
+            }
+        break;
+        }
+    default:
+        {
+        *CurrentFork = NoFork;
+        printerr("RfDfFilen2Real():", -1, MacZipMode,
+                 __LINE__, __FILE__, RfDfFilen);
+        return NULL;  /* function should never reach this point */
+        }
+    }
+
+printerr("RfDfFilen2Real():", -1, MacZipMode, __LINE__, __FILE__, RfDfFilen);
+return NULL;  /* function should never reach this point */
+}
+
+
+
+/*
+**  return the applications name (argv[0])
+**
+*/
+
+char *GetAppName(void)
+{
+ProcessSerialNumber psn;
+static Str255       AppName;
+ProcessInfoRec      pinfo;
+OSErr               err;
+
+GetCurrentProcess(&psn);
+pinfo.processName = AppName;
+pinfo.processInfoLength = sizeof(pinfo);
+pinfo.processAppSpec = NULL;
+
+err = GetProcessInformation(&psn,&pinfo);
+AppName[AppName[0]+1] = 0x00;
+
+return (char *)&AppName[1];
+}
+
+
+
+/*
+**  return fullpathname from FSSpec
+**
+*/
+
+char *GetFullPathFromSpec(char *FullPath, FSSpec *Spec, OSErr *err)
+{
+Handle hFullPath;
+short len;
+
+Assert_it(Spec,"GetFullPathFromSpec","")
+
+*err = FSpGetFullPath(Spec, &len, &hFullPath);
+printerr("FSpGetFullPath:", (*err != -43) && (*err != 0), *err,
+         __LINE__, __FILE__, "");
+
+memmove(FullPath, (Handle) *hFullPath, len);
+FullPath[len] = '\0';  /* make c-string */
+
+DisposeHandle((Handle)hFullPath);   /* we don't need it any more */
+
+printerr("Warning path length exceeds limit: ", len >= NAME_MAX, len,
+         __LINE__, __FILE__, " chars ");
+
+return FullPath;
+}
+
+
+
+
+/*
+* This function expands a given partial path to a complete path.
+* Path expansions are relative to the running app.
+* This function follows the notation:
+*   1. relative path:
+*       a: ":subfolder:filename"    -> ":current folder:subfolder:filename"
+*       b: "::folder2:filename"     -> folder2 is beside the current
+*                                      folder on the same level
+*       c: "filename"               -> in current folder
+*
+* An absolute path will be returned.
+
+The following characteristics of Macintosh pathnames should be noted:
+
+       A full pathname never begins with a colon, but must contain at
+       least one colon.
+       A partial pathname always begins with a colon separator except in
+       the case where the file partial pathname is a simple file or
+       directory name.
+       Single trailing separator colons in full or partial pathnames are
+       ignored except in the case of full pathnames to volumes.
+       In full pathnames to volumes, the trailing separator colon is required.
+       Consecutive separator colons can be used to ascend a level from a
+       directory to its parent directory. Two consecutive separator colons
+       will ascend one level, three consecutive separator colons will ascend
+       two levels, and so on. Ascending can only occur from a directory;
+       not a file.
+*/
+
+char *GetCompletePath(char *CompletePath, const char *name, FSSpec *Spec,
+                      OSErr *err)
+{
+Boolean hasDirName = false;
+char currentdir[NAME_MAX];
+char *tmpPtr;
+unsigned short pathlen;
+
+AssertStr(name,"GetCompletePath")
+Assert_it(Spec,"GetCompletePath","")
+Assert_it((CompletePath != name),"GetCompletePath","")
+
+for (tmpPtr = name; *tmpPtr; tmpPtr++)
+    if (*tmpPtr == ':') hasDirName = true;
+
+if (name[0] != ':')   /* case c: path including volume name or only filename */
+    {
+    if (hasDirName)
+        {   /* okey, starts with volume name, so it must be a complete path */
+        sstrcpy(CompletePath, name);
+        }
+    else
+        {   /* only filename: add cwd and return */
+        getcwd(currentdir, NAME_MAX);
+        sstrcat(currentdir, name);
+        sstrcpy(CompletePath, currentdir);
+        }
+    }
+else if (name[1] == ':')    /* it's case b: "::folder2:filename"  */
+    {
+    printerr("GetCompletePath ", -1, *err, __LINE__, __FILE__, "not implemented");
+            /* it's not yet implemented; do we really need this case ?*/
+    return NULL;
+    }
+else                        /* it's case a: ":subfolder:filename" */
+    {
+    getcwd(CompletePath, NAME_MAX);     /* we don't need a second colon */
+    CompletePath[strlen(CompletePath)-1] = '\0';
+    sstrcat(CompletePath, name);
+    }
+
+pathlen = strlen(CompletePath);
+*err = FSpLocationFromFullPath(pathlen, CompletePath, Spec);
+
+return CompletePath;
+}
+
+
+
+char *MakeFilenameShorter(const char *LongFilename)
+{
+static char filename[35];  /* contents should be never longer than 32 chars */
+static unsigned char Num = 0; /* change the number for every call */
+                              /* this var will rollover without a problem */
+char tempLongFilename[1024], charnum[5];
+char *last_dotpos         = tempLongFilename;
+unsigned long full_length = strlen(LongFilename);
+unsigned long ext_length  = 0;
+unsigned long num_to_cut  = 0;
+long firstpart_length;
+char *tmpPtr;
+short MaxLength = 31;
+
+if (full_length <= MaxLength) /* filename is not long */
+    {
+    return strcpy(filename,LongFilename);
+    }
+
+Num++;
+strcpy(tempLongFilename,LongFilename);
+
+/* Look for the last extension pos */
+for (tmpPtr = tempLongFilename; *tmpPtr; tmpPtr++)
+    if (*tmpPtr == '.') last_dotpos = tmpPtr;
+
+ext_length = strlen(last_dotpos);
+firstpart_length = last_dotpos - tempLongFilename;
+
+if (ext_length > 6)  /* up to 5 chars are treated as a */
+    {                /* normal extension like ".html" or ".class"  */
+    firstpart_length = 0;
+    }
+
+num_to_cut = full_length - MaxLength;
+
+/* number the files to make the names unique */
+sprintf(charnum,"~%x", Num);
+num_to_cut += strlen(charnum);
+
+if (firstpart_length == 0)
+    {
+    firstpart_length = full_length;
+    tempLongFilename[firstpart_length - num_to_cut] = 0;
+    sprintf(filename,"%s%s", tempLongFilename, charnum);
+    }
+else
+    {
+    tempLongFilename[firstpart_length - num_to_cut] = 0;
+    sprintf(filename,"%s%s%s", tempLongFilename, charnum, last_dotpos);
+    }
+
+return filename;
+}
diff --git a/macos/source/pathname.h b/macos/source/pathname.h
new file mode 100644 (file)
index 0000000..05a9078
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef PATHNAME_H
+#define PATHNAME_H 1
+
+
+char *StripPartialDir(char *CompletePath,
+                      const char *PartialPath, const char *FullPath);
+
+char *Real2RfDfFilen(char *RfDfFilen, const char *RealPath, short CurrentFork,
+                     short MacZipMode, Boolean DataForkOnly);
+char *RfDfFilen2Real(char *RealFn, const char *RfDfFilen, short MacZipMode,
+                     Boolean DataForkOnly, short *CurrentFork);
+
+unsigned short GetVolumeFromPath(const char *FullPath, char *VolumeName);
+char *GetCompletePath(char *CompletePath, const char *name, FSSpec *Spec,
+                      OSErr *err);
+char *TruncFilename(char *DirPath, const char *FilePath);
+char *GetFilename(char *CompletePath, const char *name);
+char *GetFullPathFromSpec(char *CompletePath, FSSpec *Spec, OSErr *err);
+char *GetFullPathFromID(char *CompletePath, short vRefNum, long dirID,
+                        ConstStr255Param name, OSErr *err);
+
+char *GetAppName(void);
+void createArchiveName(char *Path);
+void FindDesktopFolder(char *Path);
+char *FindNewExtractFolder(char *ExtractPath);
+
+char *MakeFilenameShorter(const char *LongFilename);
+
+/*
+Rule: UnKnown_EF should always be zero.
+      JohnnyLee_EF, NewZipMode_EF should always greater than all
+      other definitions
+*/
+#define UnKnown_EF           0
+#define TomBrownZipIt1_EF   10
+#define TomBrownZipIt2_EF   20
+#define JohnnyLee_EF        30
+#define NewZipMode_EF       40
+
+
+
+#define ResourceFork    -1
+#define DataFork        1
+#define NoFork          0
+
+
+#ifndef NAME_MAX
+#define NAME_MAX    1024
+#endif
+
+#endif   /*  PATHNAME_H  */
diff --git a/macos/source/recurse.c b/macos/source/recurse.c
new file mode 100644 (file)
index 0000000..e87db3c
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+These functions are based on Jim Luther's IterateDirectory() found in MoreFiles
+However, it's heavily modified by Dirk Haase
+*/
+
+/*
+**  IterateDirectory: File Manager directory iterator routines.
+**
+**  by Jim Luther
+**
+**  File:       IterateDirectory.c
+**
+**  Copyright (c) 1995-1998 Jim Luther and Apple Computer, Inc.
+**  All rights reserved.
+**
+**  You may incorporate this sample code into your applications without
+**  restriction, though the sample code has been provided "AS IS" and the
+**  responsibility for its operation is 100% yours.
+**
+**  IterateDirectory is designed to drop into the MoreFiles sample code
+**  library I wrote while in Apple Developer Technical Support
+*/
+
+/*****************************************************************************/
+/*  Includes                                                                 */
+/*****************************************************************************/
+
+#include <Types.h>
+#include <Errors.h>
+#include <Files.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#include "zip.h"
+#include "macstuff.h"
+#include "helpers.h"
+#include "recurse.h"
+#include "macglob.h"
+#include "pathname.h"
+
+
+
+
+/*****************************************************************************/
+/*  Macros, typedefs                                                         */
+/*****************************************************************************/
+
+/* The RecurseGlobals structure is used to minimize the amount of
+** stack space used when recursively calling RecurseDirectoryLevel
+** and to hold global information that might be needed at any time.
+*/
+struct RecurseGlobals
+{
+    short                   vRefNum;
+    CInfoPBRec              cPB;            /* the parameter block used for
+                                               PBGetCatInfo calls */
+    unsigned char           *itemName;      /* the name of the current item */
+    char                    *FullPath;
+    short                   FullPathLen;
+    OSErr                   result;         /* temporary holder of results -
+                                            saves 2 bytes of stack each level */
+    Boolean                 quitFlag;       /* set to true if filter wants to
+                                               kill interation */
+    unsigned short          maxLevels;      /* Maximum levels to
+                                               iterate through */
+    unsigned short          currentLevel;   /* The current level
+                                               IterateLevel is on */
+};
+
+typedef struct RecurseGlobals RecurseGlobals;
+typedef RecurseGlobals *RecurseGlobalsPtr;
+
+
+/*****************************************************************************/
+/*  Global Vars                                                              */
+/*****************************************************************************/
+
+extern MacZipGlobals    MacZip;
+extern const char ResourceMark[13]; /* "XtraStuf.mac:" var is initialized in file pathname.c */
+extern int extra_fields;            /* do not create extra fields if false */
+
+static RecurseGlobals theGlobals;
+
+static unsigned long    DirLevels = 0;
+static char *buffer;
+extern int verbose;        /* 1=report oddities in zip file structure */
+
+/*****************************************************************************/
+/*  Prototypes                                                               */
+/*****************************************************************************/
+
+int procname(char *filename, int caseflag);
+int MatchWild( char *pPat, char *pStr, int case_sens);
+Boolean IsZipFile(char *name);
+
+static  void    RecurseDirectoryLevel(long DirID, RecurseGlobals *Globals);
+static Boolean isRegularItem( RecurseGlobals *Globals);
+static void ProcessFiles(RecurseGlobals *Globals,
+                         Boolean hasDataFork, Boolean hasResourceFork);
+static void ProcessDirectory(RecurseGlobals *Globals,
+                             Boolean IncludeItem, long DirID);
+static void ProcessItem(RecurseGlobals *Globals, long DirID);
+
+/*****************************************************************************/
+/*  Functions                                                                */
+/*****************************************************************************/
+
+static  void    RecurseDirectoryLevel(long DirID, RecurseGlobals *Globals)
+{
+char buffer2[23];
+
+                 /* if maxLevels is zero, we aren't checking levels */
+    if ( (Globals->maxLevels == 0) ||
+                 /* if currentLevel < maxLevels, look at this level */
+         (Globals->currentLevel < Globals->maxLevels) )
+    {
+        short index = 1;
+
+        ++Globals->currentLevel;    /* go to next level */
+        if (DirLevels < Globals->currentLevel) DirLevels = Globals->currentLevel;
+        sprintf(buffer2,"Globals->currentLevel: %d",Globals->currentLevel);
+
+        do
+        {   /* Isn't C great... What I'd give for a "WITH
+                theGlobals DO" about now... */
+
+            /* Get next source item at the current directory level */
+            Globals->cPB.dirInfo.ioFDirIndex = index;
+            Globals->cPB.dirInfo.ioDrDirID = DirID;
+            Globals->result = PBGetCatInfoSync((CInfoPBPtr)&Globals->cPB);
+
+                        ShowCounter(false);
+
+            if ( Globals->result == noErr )
+                {
+                ProcessItem(Globals, DirID);
+                } /* if ( Globals->result == noErr ) */
+
+            ++index; /* prepare to get next item */
+                                         /* time to fall back a level? */
+        } while ( (Globals->result == noErr) && (!Globals->quitFlag) );
+
+        if ( (Globals->result == fnfErr) || /* fnfErr is OK -
+                                               it only means we hit
+                                               the end of this level */
+             (Globals->result == afpAccessDenied) ) /* afpAccessDenied is OK,
+                      too - it only means we cannot see inside a directory */
+        {
+            Globals->result = noErr;
+        }
+
+        --Globals->currentLevel;    /* return to previous level as we leave */
+    }
+}
+
+
+
+/*****************************************************************************/
+
+pascal  OSErr   RecurseDirectory(short vRefNum,
+                                 long thedirID,
+                                 ConstStr255Param name,
+                                 unsigned short maxLevels)
+{
+    OSErr           result;
+    short           theVRefNum;
+    Boolean         isDirectory;
+    long            DirID;
+
+        /* Get the real directory ID and make sure it is a directory */
+        result = GetDirectoryID(vRefNum, thedirID, name, &DirID, &isDirectory);
+        if ( result == noErr )
+        {
+            if ( isDirectory == true )
+            {
+                /* Get the real vRefNum */
+                result = DetermineVRefNum(name, vRefNum, &theVRefNum);
+                if ( result == noErr )
+                {
+                    /* Set up the globals we need to access from
+                       the recursive routine. */
+                    theGlobals.cPB.hFileInfo.ioNamePtr = theGlobals.itemName;
+                    theGlobals.cPB.hFileInfo.ioVRefNum = theVRefNum;
+                    theGlobals.itemName[0] = 0;
+                    theGlobals.result = noErr;
+                    theGlobals.quitFlag = false;
+                    theGlobals.maxLevels = maxLevels;
+                    theGlobals.currentLevel = 0;    /* start at level 0 */
+
+                    /* Here we go into recursion land... */
+                    RecurseDirectoryLevel(DirID, &theGlobals);
+
+                    result = theGlobals.result; /* set the result */
+                }
+            }
+            else
+            {
+                result = dirNFErr;  /* a file was passed instead
+                                       of a directory */
+            }
+        }
+
+    return ( result );
+}
+
+
+
+/*****************************************************************************/
+
+pascal  OSErr   FSpRecurseDirectory(const FSSpec *spec,
+                                    unsigned short maxLevels)
+{
+    OSErr rc;
+
+    theGlobals.vRefNum = spec->vRefNum;
+
+    /* make room for pathnames  */
+    theGlobals.itemName = (unsigned char *) StrCalloc(NAME_MAX);
+    theGlobals.FullPath = StrCalloc(NAME_MAX);
+    buffer = StrCalloc(NAME_MAX);
+
+
+    if ((noisy) && (MacZip.DataForkOnly))
+        printf("\n Warning: Datafork only \n");
+
+    /* reset the count to zero */
+    ShowCounter(true);
+
+    if (noisy) leftStatusString("Build File List; Items done:");
+    if (noisy) printf("\n Collecting Filenames ...");
+    rc = RecurseDirectory(spec->vRefNum, spec->parID, spec->name,maxLevels);
+    printerr("RecurseDirectory:",rc,rc,__LINE__,__FILE__,"");
+
+    if (noisy) printf("\n... done \n\n %6d matched files found  \n",
+                      MacZip.FoundFiles);
+    if (noisy) printf(" %6d folders found in %d Levels \n",
+                         MacZip.FoundDirectories,DirLevels);
+
+    if (MacZip.BytesOfData > (1024*1024))
+        if (noisy) printf(" %4.3f MBytes unzipped size\n\n",
+                            (float) MacZip.BytesOfData/(1024*1024));
+    else
+        if (noisy) printf(" %4.3f KBytes unzipped size\n\n",
+                           (float) MacZip.BytesOfData/1024);
+
+    /* free all memory of pathnames  */
+    theGlobals.itemName = (unsigned char *) StrFree((char *)theGlobals.itemName);
+    theGlobals.FullPath = StrFree(theGlobals.FullPath);
+    buffer = StrFree(buffer);
+
+    return rc;
+}
+
+
+
+
+/*
+* Return true if filename == zipfile
+* After the first match no further check will be done !
+*
+*/
+Boolean IsZipFile(char *filen)
+{
+static firstMatch = false;
+
+if (filen == NULL)
+    firstMatch = false;
+
+if (!firstMatch)
+    {
+    if (stricmp(filen, MacZip.ZipFullPath) == 0)
+        {
+        firstMatch = true;
+        return true;
+        }
+    }
+
+return false;
+}
+
+
+
+static Boolean isRegularItem( RecurseGlobals *Globals)
+{
+Boolean     isInvisible = false,
+            isAlias     = false,
+            isSystem    = false;
+
+isSystem    = !((Globals->cPB.hFileInfo.ioFlFndrInfo.fdFlags &
+              (1 << 12)) == 0 );
+isInvisible = !((Globals->cPB.hFileInfo.ioFlFndrInfo.fdFlags &
+              (1 << 14)) == 0 );
+isAlias     = !((Globals->cPB.hFileInfo.ioFlFndrInfo.fdFlags &
+              (1 << 15)) == 0);
+
+if (isAlias == true)
+    {
+    return false;
+    }
+
+if (MacZip.IncludeInvisible == true)
+    {
+    return true;
+    }
+
+if  ((isSystem == true) ||
+    (isInvisible == true))
+    {
+    return false;
+    }
+
+return true;
+}
+
+
+
+
+static void ProcessFiles(RecurseGlobals *Globals,
+                         Boolean hasDataFork, Boolean hasResourceFork)
+{
+ /* some file statistics */
+MacZip.FoundFiles++;
+
+if (hasDataFork == true)
+    {
+    MacZip.BytesOfData =
+                Globals->cPB.hFileInfo.ioFlLgLen +
+                MacZip.BytesOfData;
+    MacZip.CurrentFork = DataFork;
+    MacZip.RawCountOfItems++;
+
+    if (MacZip.DataForkOnly == true)
+        {
+        procname(Globals->FullPath, false);
+        hasResourceFork = false;
+        }
+        else
+        {
+        procname(Real2RfDfFilen(buffer,Globals->FullPath,
+                 DataFork, MacZip.MacZipMode,
+                 MacZip.DataForkOnly), false);
+        }
+    }
+
+if (hasResourceFork == true)
+    {
+    MacZip.BytesOfData =
+                Globals->cPB.hFileInfo.ioFlRLgLen +
+                MacZip.BytesOfData;
+    MacZip.CurrentFork = ResourceFork;
+    MacZip.RawCountOfItems++;
+
+    procname(Real2RfDfFilen(buffer, Globals->FullPath,
+             ResourceFork, MacZip.MacZipMode,
+             MacZip.DataForkOnly), false);
+    }
+}
+
+
+
+
+static void ProcessDirectory(RecurseGlobals *Globals,
+                             Boolean IncludeItem, long DirID)
+{
+OSErr       rc;
+
+MacZip.isDirectory = true;
+
+GetFullPathFromID(Globals->FullPath,Globals->vRefNum, DirID,
+                  Globals->itemName, &rc);
+
+MacZip.RawCountOfItems++;
+MacZip.FoundDirectories++;
+
+if  (MacZip.StoreFoldersAlso)
+    {
+    procname(Globals->FullPath, false);
+    }
+
+     /* We have a directory */
+    if ( !Globals->quitFlag && IncludeItem)
+    {
+   /* Dive again if the IterateFilterProc didn't say "quit" and dir is
+      not an alias */
+        RecurseDirectoryLevel(Globals->cPB.dirInfo.ioDrDirID,
+                              Globals);
+    }
+}
+
+
+
+static void ProcessItem(RecurseGlobals *Globals, long DirID)
+{
+OSErr rc;
+Boolean     IncludeItem = false, hasDataFork = false;
+Boolean     hasResourceFork = false;
+
+IncludeItem = isRegularItem(Globals);
+
+/* Is it a File? */
+if ( (Globals->cPB.hFileInfo.ioFlAttrib & ioDirMask) == 0 )
+    {
+    PToCCpy(Globals->itemName,MacZip.FileName);
+    MacZip.isDirectory = false;
+
+    hasDataFork     = (Globals->cPB.hFileInfo.ioFlLgLen != 0);
+    hasResourceFork = (Globals->cPB.hFileInfo.ioFlRLgLen != 0);
+
+    /* include also files with zero recource- and data-fork */
+    if ((hasDataFork == 0) && (hasResourceFork == 0))
+        hasDataFork = true;
+
+    if ((hasDataFork     == 0) &&
+        (hasResourceFork != 0) &&
+        (extra_fields    == false))
+        {
+        IncludeItem = false;
+        }
+
+    GetFullPathFromID(Globals->FullPath,Globals->vRefNum,
+                      DirID, Globals->itemName, &rc);
+    printerr("GetFullPathFromID:",rc,rc,__LINE__,
+              __FILE__,MacZip.FileName);
+
+    if  (IncludeItem  &&       /* don't include the zipfile itself */
+        (!IsZipFile(Globals->FullPath))   )
+        {
+        if (MATCH(MacZip.Pattern, MacZip.FileName, false) == true)
+            {
+            ProcessFiles(Globals, hasDataFork, hasResourceFork);
+            } /* if (MatchWild( MacZip.FileName,MacZip.Pattern ) ==
+                    true) */
+        }  /* if (!IsZipFile(Globals->FullPath)) */
+    } /* Is it a File? */
+
+/* Is it a directory? */
+if ( (Globals->cPB.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
+    {
+    ProcessDirectory(Globals,IncludeItem, DirID);
+    } /* Is it a directory? */
+}
diff --git a/macos/source/recurse.h b/macos/source/recurse.h
new file mode 100644 (file)
index 0000000..cfbc4b0
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+**  IterateDirectory: File Manager directory iterator routines.
+**
+**  by Jim Luther
+**
+**  File:       IterateDirectory.h
+**
+**  Copyright (c) 1995-1998 Jim Luther and Apple Computer, Inc.
+**  All rights reserved.
+**
+**  You may incorporate this sample code into your applications without
+**  restriction, though the sample code has been provided "AS IS" and the
+**  responsibility for its operation is 100% yours.
+**
+**  IterateDirectory is designed to drop into the MoreFiles sample code
+**  library I wrote while in Apple Developer Technical Support
+*/
+
+#ifndef __RECURSEDIRECTORY__
+#define __RECURSEDIRECTORY__
+
+#include <Types.h>
+#include <Files.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*****************************************************************************/
+
+pascal  OSErr   RecurseDirectory(short vRefNum,
+                                 long dirID,
+                                 ConstStr255Param name,
+                                 unsigned short maxLevels );
+/*   Iterate (scan) through a directory's content.
+    The IterateDirectory function performs a recursive iteration (scan) of
+    the specified directory and calls your IterateFilterProc function once
+    for each file and directory found.
+
+    The maxLevels parameter lets you control how deep the recursion goes.
+    If maxLevels is 1, IterateDirectory only scans the specified directory;
+    if maxLevels is 2, IterateDirectory scans the specified directory and
+    one subdirectory below the specified directory; etc. Set maxLevels to
+    zero to scan all levels.
+
+    The yourDataPtr parameter can point to whatever data structure you might
+    want to access from within the IterateFilterProc.
+
+    vRefNum         input:  Volume specification.
+    dirID           input:  Directory ID.
+    name            input:  Pointer to object name, or nil when dirID
+                            specifies a directory that's the object.
+    maxLevels       input:  Maximum number of directory levels to scan or
+                            zero to scan all directory levels.
+    iterateFilter   input:  A pointer to the routine you want called once
+                            for each file and directory found by
+                            IterateDirectory.
+    yourDataPtr     input:  A pointer to whatever data structure you might
+                            want to access from within the IterateFilterProc.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File not found
+        paramErr            -50     No default volume or iterateFilter was NULL
+        dirNFErr            -120    Directory not found or incomplete pathname
+                                    or a file was passed instead of a directory
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+
+    __________
+
+    See also:   RecurseFilterProcPtr, FSpRecurseDirectory
+*/
+
+/*****************************************************************************/
+
+pascal  OSErr   FSpRecurseDirectory(const FSSpec *spec,
+                                    unsigned short maxLevels);
+/*   Iterate (scan) through a directory's content.
+    The FSpIterateDirectory function performs a recursive iteration (scan)
+    of the specified directory and calls your IterateFilterProc function once
+    for each file and directory found.
+
+    The maxLevels parameter lets you control how deep the recursion goes.
+    If maxLevels is 1, FSpIterateDirectory only scans the specified directory;
+    if maxLevels is 2, FSpIterateDirectory scans the specified directory and
+    one subdirectory below the specified directory; etc. Set maxLevels to
+    zero to scan all levels.
+
+    The yourDataPtr parameter can point to whatever data structure you might
+    want to access from within the IterateFilterProc.
+
+    spec            input:  An FSSpec record specifying the directory to scan.
+    maxLevels       input:  Maximum number of directory levels to scan or
+                            zero to scan all directory levels.
+    iterateFilter   input:  A pointer to the routine you want called once
+                            for each file and directory found by
+                            FSpIterateDirectory.
+    yourDataPtr     input:  A pointer to whatever data structure you might
+                            want to access from within the IterateFilterProc.
+
+    Result Codes
+        noErr               0       No error
+        nsvErr              -35     No such volume
+        ioErr               -36     I/O error
+        bdNamErr            -37     Bad filename
+        fnfErr              -43     File not found
+        paramErr            -50     No default volume or iterateFilter was NULL
+        dirNFErr            -120    Directory not found or incomplete pathname
+        afpAccessDenied     -5000   User does not have the correct access
+        afpObjectTypeErr    -5025   Directory not found or incomplete pathname
+
+    __________
+
+    See also:   RecurseFilterProcPtr, RecurseDirectory
+*/
+
+
+
+/*****************************************************************************/
+
+
+
+#endif /* __RECURSEDIRECTORY__ */
diff --git a/macos/source/unixlike.c b/macos/source/unixlike.c
new file mode 100644 (file)
index 0000000..017d3fa
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+  unixlike.c
+
+  Macintosh-specific routines to emulate unixfunctions.
+
+  ---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/*  Includes                                                                 */
+/*****************************************************************************/
+
+#include "zip.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <sound.h>
+
+#include "unixlike.h"
+#include "helpers.h"
+#include "pathname.h"
+#include "macstuff.h"
+#include "macglob.h"
+#include "mactime.h"
+
+/*****************************************************************************/
+/*  Global Vars                                                              */
+/*****************************************************************************/
+
+extern MacZipGlobals    MacZip;
+extern int errno;
+
+
+/*****************************************************************************/
+/*  Prototypes                                                               */
+/*****************************************************************************/
+
+
+/*****************************************************************************/
+/*  Functions                                                                */
+/*****************************************************************************/
+
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MacStat --
+ *
+ *  This function replaces the library version of stat.  The stat
+ *  function provided by most Mac compiliers is rather broken and
+ *  incomplete.
+ *
+ * Results:
+ *  See stat documentation.
+ *
+ * Side effects:
+ *  See stat documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int Zmacstat(const char *Fname, struct stat *buf)
+{
+    OSErr           err, rc;
+    short           fullPathLength;
+    Handle          hFullPath;
+    char            path[NAME_MAX], path2[NAME_MAX];
+    HVolumeParam    vpb;
+    static unsigned long count_of_files = 0;
+
+    AssertStr(Fname,Fname)
+    Assert_it(buf,"","")
+
+    UserStop();
+
+    memset(buf, 0, sizeof(buf));    /* zero out all fields */
+
+    RfDfFilen2Real(path2, Fname, MacZip.MacZipMode, MacZip.DataForkOnly,
+                   &MacZip.CurrentFork);
+    GetCompletePath(path, path2, &MacZip.fileSpec, &err);
+    err = PrintUserHFSerr((err != -43) && (err != 0), err, path);
+    printerr("GetCompletePath:", err, err, __LINE__, __FILE__, path);
+
+    if (err != noErr) {
+        errno = err;
+        return -1;
+    }
+
+    /*  Collect here some more information, it's not related to Macstat.
+        (note: filespec gets changed later in this function) */
+    /* clear string-buffer */
+    memset(MacZip.FullPath, 0x00, sizeof(MacZip.FullPath));
+    rc = FSpGetFullPath(&MacZip.fileSpec, &fullPathLength, &hFullPath);
+    strncpy(MacZip.FullPath, *hFullPath, fullPathLength);
+    DisposeHandle(hFullPath);   /* we don't need it any more */
+    /*  Collect some more information not related to Macstat */
+
+
+    /*
+     * Fill the fpb & vpb struct up with info about file or directory.
+     */
+
+    FSpGetDirectoryID(&MacZip.fileSpec, &MacZip.dirID, &MacZip.isDirectory);
+    vpb.ioVRefNum = MacZip.fpb.hFileInfo.ioVRefNum =  MacZip.fileSpec.vRefNum;
+    vpb.ioNamePtr = MacZip.fpb.hFileInfo.ioNamePtr =  MacZip.fileSpec.name;
+
+    if (MacZip.isDirectory) {
+        MacZip.fpb.hFileInfo.ioDirID =  MacZip.fileSpec.parID;
+        /*
+         * Directories are executable by everyone.
+         */
+        buf->st_mode |= UNX_IXUSR | UNX_IXGRP | UNX_IXOTH | UNX_IFDIR;
+    } else {
+        MacZip.fpb.hFileInfo.ioDirID = MacZip.dirID;
+    }
+
+    MacZip.fpb.hFileInfo.ioFDirIndex = 0;
+    err = PBGetCatInfoSync((CInfoPBPtr)&MacZip.fpb);
+
+    if (err == noErr) {
+        vpb.ioVolIndex = 0;
+        err = PBHGetVInfoSync((HParmBlkPtr)&vpb);
+        if (err == noErr && buf != NULL) {
+            /*
+             * Files are always readable by everyone.
+             */
+            buf->st_mode |= UNX_IRUSR | UNX_IRGRP | UNX_IROTH;
+
+            /*
+             * Use the Volume Info & File Info to fill out stat buf.
+             */
+            if (MacZip.fpb.hFileInfo.ioFlAttrib & 0x10) {
+                buf->st_mode |= UNX_IFDIR;
+                buf->st_nlink = 2;
+            } else {
+                buf->st_nlink = 1;
+                if (MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) {
+                    buf->st_mode |= UNX_IFLNK;
+                } else {
+                    buf->st_mode |= UNX_IFREG;
+                }
+            }
+
+            if (MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType == 'APPL') {
+                /*
+                 * Applications are executable by everyone.
+                 */
+                buf->st_mode |= UNX_IXUSR | UNX_IXGRP | UNX_IXOTH;
+            }
+            if ((MacZip.fpb.hFileInfo.ioFlAttrib & 0x01) == 0){
+                /*
+                 * If not locked, then everyone has write acces.
+                 */
+                buf->st_mode |= UNX_IWUSR | UNX_IWGRP | UNX_IWOTH;
+            }
+
+            buf->st_ino = MacZip.fpb.hFileInfo.ioDirID;
+            buf->st_dev = MacZip.fpb.hFileInfo.ioVRefNum;
+            buf->st_uid = -1;
+            buf->st_gid = -1;
+            buf->st_rdev = 0;
+
+            if (MacZip.CurrentFork == ResourceFork)
+                buf->st_size = MacZip.fpb.hFileInfo.ioFlRLgLen;
+            else
+                buf->st_size = MacZip.fpb.hFileInfo.ioFlLgLen;
+
+            buf->st_blksize = vpb.ioVAlBlkSiz;
+            buf->st_blocks = (buf->st_size + buf->st_blksize - 1)
+                            / buf->st_blksize;
+
+            /*
+             * The times returned by the Mac file system are in the
+             * local time zone.  We convert them to GMT so that the
+             * epoch starts from GMT.  This is also consistent with
+             * what is returned from "clock seconds".
+             */
+            if (!MacZip.isDirectory) {
+                MacZip.CreatDate  = MacZip.fpb.hFileInfo.ioFlCrDat;
+                MacZip.ModDate    = MacZip.fpb.hFileInfo.ioFlMdDat;
+                MacZip.BackDate   = MacZip.fpb.hFileInfo.ioFlBkDat;
+            } else {
+                MacZip.CreatDate  = MacZip.fpb.dirInfo.ioDrCrDat;
+                MacZip.ModDate    = MacZip.fpb.dirInfo.ioDrMdDat;
+                MacZip.BackDate   = MacZip.fpb.dirInfo.ioDrBkDat;
+            }
+
+#ifdef IZ_CHECK_TZ
+            if (!zp_tz_is_valid)
+            {
+                MacZip.HaveGMToffset = false;
+                MacZip.Md_UTCoffs = 0L;
+                MacZip.Cr_UTCoffs = 0L;
+                MacZip.Bk_UTCoffs = 0L;
+            }
+            else
+#endif
+            {
+                /* Do not use GMT offsets when Md_UTCoffs calculation
+                 * fails, since this time stamp is used for time
+                 * comparisons in Zip and UnZip operations.
+                 * We do not bother when GMT offset calculation fails for
+                 * any other time stamp value. Instead we simply assume
+                 * a default value of 0.
+                 */
+                MacZip.HaveGMToffset =
+                    GetGMToffsetMac(MacZip.ModDate, &MacZip.Md_UTCoffs);
+                if (MacZip.HaveGMToffset) {
+                    GetGMToffsetMac(MacZip.CreatDate, &MacZip.Cr_UTCoffs);
+                    GetGMToffsetMac(MacZip.BackDate, &MacZip.Bk_UTCoffs);
+                } else {
+                    MacZip.Cr_UTCoffs = 0L;
+                    MacZip.Bk_UTCoffs = 0L;
+                }
+            }
+#ifdef DEBUG_TIME
+            {
+            printf("\nZmacstat:  MacZip.HaveGMToffset: %d",
+               MacZip.HaveGMToffset);
+            printf("\nZmacstat:  Mac modif: %lu local -> UTOffset: %d",
+              MacZip.ModDate, MacZip.Md_UTCoffs);
+            printf("\nZmacstat:  Mac creat: %lu local -> UTOffset: %d",
+              MacZip.CreatDate, MacZip.Cr_UTCoffs);
+            printf("\nZmacstat:  Mac  back: %lu local -> UTOffset: %d",
+              MacZip.BackDate, MacZip.Bk_UTCoffs);
+            }
+#endif /* DEBUG_TIME */
+
+
+            buf->st_mtime = MacFtime2UnixFtime(MacZip.ModDate);
+            buf->st_ctime = MacFtime2UnixFtime(MacZip.CreatDate);
+            buf->st_atime = buf->st_mtime;
+
+#ifdef DEBUG_TIME
+            {
+            printf("\nZmacstat:  Unix modif: %lu UTC; Mac: %lu local",
+              buf->st_mtime, MacZip.ModDate);
+            printf("\nZmacstat:  Unix creat: %lu UTC; Mac: %lu local\n",
+              buf->st_ctime, MacZip.CreatDate);
+            }
+#endif /* DEBUG_TIME */
+
+            if (noisy)
+            {
+                if (MacZip.StatingProgress)
+                {
+                    count_of_files++;
+                    InformProgress(MacZip.RawCountOfItems, count_of_files );
+                }
+                else
+                    count_of_files = 0;
+            }
+        }
+    }
+
+    if (err != noErr) {
+        errno = err;
+    }
+
+    MacZip.isMacStatValid = true;
+    return (err == noErr ? 0 : -1);
+}
+
+
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * chmod --
+ *
+ * Results:
+ *  See chmod documentation.
+ *
+ * Side effects:
+ *  See chmod documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int chmod(char *path, int mode)
+{
+    HParamBlockRec hpb;
+    OSErr err;
+
+    hpb.fileParam.ioNamePtr = C2PStr(path);
+    hpb.fileParam.ioVRefNum = 0;
+    hpb.fileParam.ioDirID = 0;
+
+    if (mode & 0200) {
+        err = PBHRstFLockSync(&hpb);
+    } else {
+        err = PBHSetFLockSync(&hpb);
+    }
+
+    if (err != noErr) {
+        errno = err;
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/macos/source/unixlike.h b/macos/source/unixlike.h
new file mode 100644 (file)
index 0000000..e61a354
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/*
+ *      Directory Operations for Mac based on BSD 4.3   <macdir.h>
+ *      By Jason Linhart, January 1997
+ */
+
+#ifndef _UNIXLIKE_H
+#define _UNIXLIKE_H       1
+
+#include <stat.h>
+
+#ifndef NAME_MAX
+#define NAME_MAX    2048
+#endif
+
+#define UNX_IFMT        0170000     /* Unix file type mask */
+#define UNX_IFSOCK      0140000     /* Unix socket (BSD, not SysV or Amiga) */
+#define UNX_IFLNK       0120000     /* Unix symbolic link (not SysV, Amiga) */
+#define UNX_IFREG       0100000     /* Unix regular file */
+#define UNX_IFBLK       0060000     /* Unix block special       (not Amiga) */
+#define UNX_IFDIR       0040000     /* Unix directory */
+#define UNX_IFCHR       0020000     /* Unix character special   (not Amiga) */
+#define UNX_IFIFO       0010000     /* Unix fifo    (BCC, not MSC or Amiga) */
+
+#define UNX_ISUID       04000       /* Unix set user id on execution */
+#define UNX_ISGID       02000       /* Unix set group id on execution */
+#define UNX_ISVTX       01000       /* Unix directory permissions control */
+#define UNX_ENFMT       UNX_ISGID   /* Unix record locking enforcement flag */
+
+#define UNX_IRWXU       00700       /* Unix read, write, execute: owner */
+#define UNX_IRUSR       00400       /* Unix read permission: owner */
+#define UNX_IWUSR       00200       /* Unix write permission: owner */
+#define UNX_IXUSR       00100       /* Unix execute permission: owner */
+
+#define UNX_IRWXG       00070       /* Unix read, write, execute: group */
+#define UNX_IRGRP       00040       /* Unix read permission: group */
+#define UNX_IWGRP       00020       /* Unix write permission: group */
+#define UNX_IXGRP       00010       /* Unix execute permission: group */
+
+#define UNX_IRWXO       00007       /* Unix read, write, execute: other */
+#define UNX_IROTH       00004       /* Unix read permission: other */
+#define UNX_IWOTH       00002       /* Unix write permission: other */
+#define UNX_IXOTH       00001       /* Unix execute permission: other */
+
+/* historical file modes */
+#define S_IREAD    0x100
+#define S_IWRITE   0x80
+#define S_IEXEC    0x40
+
+
+#define isatty(arg) 1
+
+
+#define EINVAL          22      /* Invalid argument */
+#define ENAMETOOLONG    63      /* File name too long */
+
+
+struct dirent {
+        char            d_name[NAME_MAX];
+};
+
+/*
+ * The following definitions are usually found in fcntl.h.
+ * However, MetroWerks has screwed that file up a couple of times
+ * and all we need are the defines.
+ */
+#define O_APPEND  0x0100    /* open the file in append mode */
+#define O_CREAT   0x0200    /* create the file if it doesn't exist */
+#define O_EXCL    0x0400    /* if the file exists don't create it again */
+#define O_TRUNC   0x0800    /* truncate the file after opening it */
+
+
+int Zmacstat (const char *path, struct stat *buf);
+int chmod(char *path, int mode);
+
+
+#include "macstuff.h"
+
+#endif /* _UNIXLIKE_H  */
diff --git a/macos/source/zip_rc.hqx b/macos/source/zip_rc.hqx
new file mode 100644 (file)
index 0000000..99e0d25
--- /dev/null
@@ -0,0 +1,43 @@
+(This file must be converted with BinHex 4.0)
+:#RTTF#jbBbjcDA3!8dP84&0*9#%!N!3([`#3"&(E8dP8)3!"!!!([h*-BA8#Q3#
+3!aDCQ3d!"RTTF#jbB`!!&[Bi"2[rG!"-5QS!N!1!!*!%"32,j+m2!*!Drj!%8P0
+53e*6483"",#mXHDaqlGG!!!GmJ#3"JFj!*!%6Mi!N!MGc!`!P@6pq1R*k4&+Z,d
+p"5$(b(-Upcc#j%EiHCfjPTq%8h+X8d)MR$`rF[b9Vh`pTLc2jqZ9r'RNq9VN1'&
+'MMmj6Sk6#5HFc0J4lN8iHFU2--,*K%Z1NIR+#1XNR("#bE-)2I+FF$*G@H6BL+`
+*!&6IV1ml1d+22#-$4UEm*#01"T`m*4`Ji(03ThM'$-EBilf-V8-e6Q8bXEVD@Xi
+2bilcmGEY"lV6QGjZrK)I1CKZ$BfR4pSbLD'f`F'qVPKb+*(-*V2CPLfaGj1CE+a
+Z+-$kpr4hpHrCf@d%f66E!A2P-rA6phmUj)QrdYP4r[6)H+cZF"hRV``NHSG5`b!
+F6-0YBZ$!JH&%#frIb,2TmH4`LVGN4c1(%U1Q8#cf)P44dU"#-`D)I($H4I5qc[j
+NJLI5)qpN5)Ic[S(-`-&1H(U2L*U'-H`1Y1p&qc#*YVk4(RNUbp(ae(#'R,B[d%B
+(Nd40$id1C`FhmUlKNBmbkAf$Sra8qpDYcm0,H%GIhbiej(!EESbmC+a*'3dqdlC
+j)%*H#+!,D!K4#J#3!$9H-J)mB*6L!50R"%"&hi6DD*61[-qq22%f1hkXPq@r)'`
+(1hjQJ19cKP'bY0#60RQ3!&kd,r))mj-X,LBCCa&CeiX#f`ibZ$9##+[1HUJ34G5
+584+#&@p9i[UDj-&PD2rAi0qYdMpMQ""M8FLBT`#FUMje-i6rVXl2qI`jK@XY#eH
++%JH[5(`6,qEcH@K,(FfA4rZDNG,4mp60fALH@TT,SC!!5Sf0$HHP31&mP"AfKN)
+K-!N[&XjM@##`1I,(a"V"#L%@#U9'*'lT-5CaU8GqpLTFkUP"%klmfMLJ1QpH5r2
+djNdfhIXJFIqqN!!&1QHe$jUlHF`jZ2I41X8k$@ZbKF1C2"Cq6YZaF(Z+5Yra&63
+"alCh62Vm6N(RqR90&)#m`cE3mILqV`@qBmcQkf0"9Ei%#**RRRpcS0DmV!N6DB-
+&#R112Ym4-1d)GJ(R0,i,0!TEJ!%$#Mj$SFqp80)XU4&"+j!!DmFJk)S2*[(KNMR
+mHApd)4Im@I2aqEBrpd,EVi3ehd@qETI[eprhmmlp0UGjqhe`q#[[Ljk#GDclAll
+[P91j$d[[ir`4X1LcbmVcI$8cCd49rY*`E2l+F1l-Uk0CV,edY8%d('d@pD*qVRk
+L@64FE9KlU9Q%E`3$i@+cD"BSp)'26f,8K%[iL[#3!$-h&aDPY5L2CJBBpF5Kh5k
++ASJVqckQ9kG`*C95rEka+29B5U+f"eYIqF&ZC()P-%GbHXQ44)a!l[Z9q3[c5Z!
+aN!!pGHT"X#q,IJ$8lG#i224dkNXMhd,#3I"ap4JkEk@YlrKEp1r14erRqIYVJY@
+RbX4G0GVTc4A5A20`[E`GcX60GGI#0@$KHMqfFB9BIV4&%kr6+kH*J`(FR3lKcJj
+pNqpN!JiZ-`'&1jQ!a*e-31RCQB$%R8c!dY1CJ19(C`+@AjGIa[qCCq8qH,K8FA%
+LH$LpGbZiFpp0ehUR[lZTL-[HU3T8q*FVkd5&AaDBjrX##ha2S$UImK6,r-Z9MDM
+#PaVqNfUH+VqmXplAGpG!G`k,I&I!i[ZC`J,Iba3@rEQC`J,Iba5@rFQGIhNq5h`
+r-lM2ArAJIYjp(jEjYX!5he+i`cIhZRrjYq)%rjNh@"K4Ej!!V8&p!,8@0C*$l3L
+bk#`f"%i9DMaRk,i*YC&aj0dFH6G(hXf4Gh2Nh4ajYp5aY(5[I@a#hBBDeh9E'*X
+Kq3q,)QS*99$0SCj&R68Va[9Ie6lJ9444KDk%dDE9%CrPQhJ,hbD#)RJ8936RJK1
+bjb%HMTILXr&#r&Um++SIZ#*1fAP1hM-c'CG*VekG*BkGApkj'DZA13GkPA1JPcN
+(iC4c%*m@1&[2l0@LLCK%pFUBG%kj4M@2,@pY&UjA+*Y2#Zil5%pF&GI[LBAVh-2
+$3I"aCG,5ekC[qL[MlZ1QRP32Ga5YQFY`Cf-[rZ!JX+GrCir-1R)J6J!jdY[ekRU
+IXFT6',*jNmH[B69Hq&&6$N-NlS3K8Xm03mM2+VTKb253!iSqNDRHIKqNq$hqV6$
+%pVF8KPMc@68N$0Q#[KXH1UJL$1P'',*PpB``C"5M'eXG)JbTfDal(BB!AfdN$-'
+cjq2P-%6bli8Kq,pej"NCErJr%NGk[[Pkpa44M+pBl4Mq$SC![ij'pZ[3j20d)N[
+i$qR%J5hSI`01r3hJcl+!m54`kMY9f'+N1PrYaRqe4SCq@E8Hr)$%dK,,5@`LdR2
+b$cBKPr+"5-q*AH`)BBm-4AUqlG-DHk"a9QQ`Yi"0+Beefb-pTlj6'Z(2`,ZS0"j
++!KY9'SpQ-0f,5U2Q'(Lr+Sd(h`3fV65DpX2VT0+)[!EHKdUMS4ABTdVMX4IJG8T
+T'*pJ6K'P8IXk0+iTMFB8I'L[i9r!Qp6c`!dlH9,2idGJTp9PD'b(MjH9AZ0cQ02
+TqYdI$#8c2*2-$Kr+**,r!`#3!dm4!!!:
diff --git a/macos/zipup.h b/macos/zipup.h
new file mode 100644 (file)
index 0000000..ce2af4a
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef O_RDONLY
+#  include <fcntl.h>
+#endif
+
+#define fhow            (O_RDONLY|O_BINARY)
+#define fbad            (-1)
+
+typedef int ftype;
+
+
+#define zopen(n,p)      MacOpen(n,p)
+#define zread(f,b,n)    read(f,b,n)
+#define zclose(f)       close(f)
+#define zerr(f)         (k == (extent)(-1L))
+#define zstdin          0
+
+
diff --git a/man/zip.1 b/man/zip.1
new file mode 100644 (file)
index 0000000..15814d4
--- /dev/null
+++ b/man/zip.1
@@ -0,0 +1,1318 @@
+.\" =========================================================================
+.\" Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+.\"
+.\" See the accompanying file LICENSE, version 2005-Feb-10 or later
+.\" (the contents of which are also included in zip.h) for terms of use.
+.\" If, for some reason, all these files are missing, the Info-ZIP license
+.\" also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+.\" ==========================================================================
+.\"
+.\" zip.1 by Mark Adler, Jean-loup Gailly and  R. P. C. Rodgers
+.\"
+.TH ZIP 1L "27 February 2005 (v2.31)" Info-ZIP
+.SH NAME
+zip, zipcloak, zipnote, zipsplit \- package and compress (archive) files
+.SH SYNOPSIS
+.B zip
+.RB [ \-aABcdDeEfFghjklLmoqrRSTuvVwXyz!@$ ]
+.RB [ \-b\ path ]
+.RB [ \-n\ suffixes ]
+.RB [ \-t\ mmddyyyy ]
+.RB [ \-tt\ mmddyyyy ]
+.I [ zipfile
+.I [ file1
+.IR file2 " .\|.\|." ]]
+.RB [ \-xi\ list ]
+.PP
+.B zipcloak
+.RB [ \-dhL ]
+.RB [ \-b\ path ]
+.I zipfile
+.PP
+.B zipnote
+.RB [ \-hwL ]
+.RB [ \-b\ path ]
+.I zipfile
+.PP
+.B zipsplit
+.RB [ \-hiLpst ]
+.RB [ \-n\ size ]
+.RB [ \-b\ path ]
+.I zipfile
+.SH DESCRIPTION
+.I zip
+is a compression and file packaging utility for Unix, VMS, MSDOS,
+OS/2, Windows NT, Minix, Atari and Macintosh, Amiga and Acorn RISC OS.
+.LP
+It is analogous to a combination of the UNIX commands
+.IR tar (1)
+and
+.IR compress (1)
+and is compatible with PKZIP (Phil Katz's ZIP for MSDOS systems).
+.LP
+A companion program
+.RI ( unzip (1L)),
+unpacks
+.I zip
+archives.
+The
+.I zip
+and
+.IR unzip (1L)
+programs can work with archives produced by PKZIP,
+and PKZIP and PKUNZIP can work with archives produced by
+.IR zip .
+.I zip
+version 2.31 is compatible with PKZIP 2.04.
+Note that PKUNZIP 1.10 cannot extract files produced by PKZIP 2.04
+or
+.I zip
+2.31. You must use PKUNZIP 2.04g or
+.I unzip
+5.0p1 (or later versions) to extract them.
+.PP
+For a brief help on
+.I zip
+and
+.I unzip,
+run each without specifying any parameters on the command line.
+.PP
+The program is useful for packaging a set of files for distribution;
+for archiving files;
+and for saving disk space by temporarily
+compressing unused files or directories.
+.LP
+The
+.I zip
+program puts one or more compressed files into a single
+.I zip
+archive,
+along with information about the files
+(name, path, date, time of last modification, protection,
+and check information to verify file integrity).
+An entire directory structure can be packed into a
+.I zip
+archive with a single command.
+Compression ratios of 2:1 to 3:1 are common for text files.
+.I zip
+has one compression method (deflation) and can also store files without
+compression.
+.I zip
+automatically chooses the better of the two for each file to be compressed.
+.LP
+When given the name of an existing
+.I zip
+archive,
+.I zip
+will replace identically named entries in the
+.I zip
+archive or add entries for new names.
+For example,
+if
+.I foo.zip
+exists and contains
+.I foo/file1
+and
+.IR foo/file2 ,
+and the directory
+.I foo
+contains the files
+.I foo/file1
+and
+.IR foo/file3 ,
+then:
+.IP
+\fCzip -r foo foo\fP
+.LP
+will replace
+.I foo/file1
+in
+.I foo.zip
+and add
+.I foo/file3
+to
+.IR foo.zip .
+After this,
+.I foo.zip
+contains
+.IR foo/file1 ,
+.IR foo/file2 ,
+and
+.IR foo/file3 ,
+with
+.I foo/file2
+unchanged from before.
+.LP
+If the file list is specified as
+.BR \-@ ,
+[Not on MacOS]
+.I zip
+takes the list of input files from standard input.
+Under UNIX,
+this option can be used to powerful effect in conjunction with the
+.IR find (1)
+command.
+For example,
+to archive all the C source files in the current directory and
+its subdirectories:
+.IP
+\fCfind . -name "*.[ch]" -print | zip source -@\fP
+.LP
+(note that the pattern must be quoted to keep the shell from expanding it).
+.I zip
+will also accept a single dash ("-") as the zip file name, in which case it
+will write the zip file to standard output, allowing the output to be piped
+to another program. For example:
+.IP
+\fCzip -r - . | dd of=/dev/nrst0 obs=16k\fP
+.LP
+would write the zip output directly to a tape with the specified block size
+for the purpose of backing up the current directory.
+.LP
+.I zip
+also accepts a single dash ("-") as the name of a file to be compressed, in
+which case it will read the file from standard input, allowing zip to take
+input from another program. For example:
+.IP
+\fCtar cf - . | zip backup -\fP
+.LP
+would compress the output of the tar command for the purpose of backing up
+the current directory. This generally produces better compression than
+the previous example using the
+.B \-r
+option, because
+.I zip
+can take advantage of redundancy between files. The backup can be restored
+using the command
+.IP
+\fCunzip -p backup | tar xf -\fP
+.LP
+When no zip file name is given and stdout is not a terminal,
+.I zip
+acts as a filter, compressing standard input to standard output.
+For example,
+.IP
+\fCtar cf - . | zip | dd of=/dev/nrst0 obs=16k\fP
+.LP
+is equivalent to
+.IP
+\fCtar cf - . | zip - - | dd of=/dev/nrst0 obs=16k\fP
+.LP
+.I zip
+archives created in this manner can be extracted with the program
+.I funzip
+which is provided in the
+.I unzip
+package, or by
+.I gunzip
+which is provided in the
+.I gzip
+package. For example:
+.IP
+\fCdd if=/dev/nrst0  ibs=16k | funzip | tar xvf -\fP
+.LP
+When changing an existing
+.I zip
+archive,
+.I zip
+will write a temporary file with the new contents,
+and only replace the old one when the process of creating the new version
+has been completed without error.
+.LP
+If the name of the
+.I zip
+archive does not contain an extension, the extension
+.IR .zip
+is added. If the name already contains an extension other than
+.IR .zip
+the existing extension is kept unchanged.
+.SH "OPTIONS"
+.TP
+.BI \-a
+[Systems using EBCDIC] Translate file to ASCII format.
+.TP
+.BI \-A
+Adjust self-extracting executable archive.
+A self-extracting executable archive is created by prepending
+the SFX stub to an existing archive. The
+.B \-A
+option tells
+.I zip
+to adjust the entry offsets stored
+in the archive to take into account this "preamble" data.
+.LP
+Note: self-extracting archives for the Amiga are a special case.
+At present, only the Amiga port of Zip is capable of adjusting
+or updating these without corrupting them.
+.B \-J
+can be used to remove the SFX stub if other updates need to be made.
+.TP
+.BI \-B
+[VM/CMS and MVS] force file to be read binary (default is text).
+.TP
+.BI \-Bn
+[TANDEM] set Edit/Enscribe formatting options with n defined as
+.RS
+bit  0: Don't add delimiter (Edit/Enscribe)
+.RE
+.RS
+bit 1: Use LF rather than CR/LF as delimiter (Edit/Enscribe)
+.RE
+.RS
+bit  2: Space fill record to maximum record length (Enscribe)
+.RE
+.RS
+bit  3: Trim trailing space (Enscribe)
+.RE
+.RS
+bit 8: Force 30K (Expand) large read for unstructured files
+.RE
+.TP
+.BI \-b\ path
+Use the specified
+.I path
+for the temporary
+.I zip
+archive. For example:
+.RS
+.IP
+\fCzip -b /tmp stuff *\fP
+.RE
+.IP
+will put the temporary
+.I zip
+archive in the directory
+.IR /tmp ,
+copying over
+.I stuff.zip
+to the current directory when done. This option is only useful when
+updating an existing archive, and the file system containing this
+old archive does not have enough space to hold both old and new archives
+at the same time.
+.TP
+.B \-c
+Add one-line comments for each file.
+File operations (adding, updating) are done first,
+and the user is then prompted for a one-line comment for each file.
+Enter the comment followed by return, or just return for no comment.
+.TP
+.B \-d
+Remove (delete) entries from a
+.I zip
+archive.
+For example:
+.RS
+.IP
+\fCzip -d foo foo/tom/junk foo/harry/\\* \\*.o\fP
+.RE
+.IP
+will remove the entry
+.IR foo/tom/junk ,
+all of the files that start with
+.IR foo/harry/ ,
+and all of the files that end with
+.I \&.o
+(in any path).
+Note that shell pathname expansion has been inhibited with backslashes,
+so that
+.I zip
+can see the asterisks,
+enabling
+.I zip
+to match on the contents of the
+.I zip
+archive instead of the contents of the current directory.
+.IP
+Under systems where the shell does not expand wildcards, such as MSDOS,
+the backslashes are not needed.  The above would then be
+.RS
+.IP
+\fCzip -d foo foo/tom/junk foo/harry/* *.o\fP
+.RE
+.IP
+Under MSDOS,
+.B \-d
+is case sensitive when it matches names in the
+.I zip
+archive.
+This requires that file names be entered in upper case if they were
+zipped by PKZIP on an MSDOS system.
+.TP
+.B \-df
+[MacOS] Include only data-fork of files zipped into the archive.
+Good for exporting files to foreign operating-systems.
+Resource-forks will be ignored at all.
+.TP
+.B \-D
+Do not create entries in the
+.I zip
+archive for directories.  Directory entries are created by default so that
+their attributes can be saved in the zip archive.
+The environment variable ZIPOPT can be used to change the default options. For
+example under Unix with sh:
+.RS
+.IP
+ZIPOPT="-D"; export ZIPOPT
+.RE
+.IP
+(The variable ZIPOPT can be used for any option except
+.B \-i
+and
+.B \-x
+and can include several options.) The option
+.B \-D
+is a shorthand
+for
+.B \-x
+"*/" but the latter cannot be set as default in the ZIPOPT environment
+variable.
+.TP
+.B \-e
+Encrypt the contents of the
+.I zip
+archive using a password which is entered on the terminal in response
+to a prompt
+(this will not be echoed; if standard error is not a tty,
+.I zip
+will exit with an error).
+The password prompt is repeated to save the user from typing errors.
+.TP
+.B \-E
+[OS/2] Use the .LONGNAME Extended Attribute (if found) as filename.
+.TP
+.B \-f
+Replace (freshen) an existing entry in the
+.I zip
+archive only if it has been modified more recently than the
+version already in the
+.I zip
+archive;
+unlike the update option
+.RB ( \-u )
+this will not add files that are not already in the
+.I zip
+archive.
+For example:
+.RS
+.IP
+\fCzip -f foo\fP
+.RE
+.IP
+This command should be run from the same directory from which the original
+.I zip
+command was run,
+since paths stored in
+.I zip
+archives are always relative.
+.IP
+Note that the timezone environment variable TZ should be set according to
+the local timezone in order for the
+.B \-f
+,
+.B \-u
+and
+.B \-o
+options to work correctly.
+.IP
+The reasons behind this are somewhat subtle but have to do with the differences
+between the Unix-format file times (always in GMT) and most of the other
+operating systems (always local time) and the necessity to compare the two.
+A typical TZ value is ``MET-1MEST'' (Middle European time with automatic
+adjustment for ``summertime'' or Daylight Savings Time).
+.TP
+.B \-F
+Fix the
+.I zip
+archive. This option can be used if some portions of the archive
+are missing. It is not guaranteed to work, so you MUST make a backup
+of the original archive first.
+.IP
+When doubled as in
+.B \-FF
+the compressed sizes given inside the damaged archive are not trusted
+and zip scans for special signatures to identify the limits between
+the archive members. The single
+.B \-F
+is more reliable if the archive is not too much damaged, for example
+if it has only been truncated, so try this option first.
+.IP
+Neither option will recover archives that have been incorrectly
+transferred in ascii mode instead of binary. After the repair, the
+.B \-t
+option of
+.I unzip
+may show that some files have a bad CRC. Such files cannot be recovered;
+you can remove them from the archive using the
+.B \-d
+option of
+.I zip.
+.TP
+.B \-g
+Grow (append to) the specified
+.I zip
+archive, instead of creating a new one. If this operation fails,
+.I zip
+attempts to restore the archive to its original state. If the restoration
+fails, the archive might become corrupted. This option is ignored when
+there's no existing archive or when at least one archive member must be
+updated or deleted.
+.TP
+.B \-h
+Display the
+.I zip
+help information (this also appears if
+.I zip
+is run with no arguments).
+.TP
+.BI \-i\ files
+Include only the specified files, as in:
+.RS
+.IP
+\fCzip -r foo . -i \\*.c\fP
+.RE
+.IP
+which will include only the files that end in
+.IR \& .c
+in the current directory and its subdirectories. (Note for PKZIP
+users: the equivalent command is
+.RS
+.IP
+\fCpkzip -rP foo *.c\fP
+.RE
+.IP
+PKZIP does not allow recursion in directories other than the current one.)
+The backslash avoids the shell filename substitution, so that the
+name matching is performed by
+.I zip
+at all directory levels.  Not escaping wildcards on shells that do
+wildcard substitution before zip gets the command line may seem to
+work but files in subdirectories matching the pattern will never be
+checked and so not matched.  For shells, such as Win32 command
+prompts, that do not replace file patterns containing wildcards
+with the respective file names,
+.I zip
+will do the recursion and escaping the wildcards is not needed.
+.IP
+Also possible:
+.RS
+.IP
+\fCzip -r foo  . -i@include.lst\fP
+.RE
+.IP
+which will only include the files in the current directory and its
+subdirectories that match the patterns in the file include.lst.
+.TP
+.B \-I
+[Acorn RISC OS] Don't scan through Image files.  When used,
+.I zip
+will not
+consider Image files (eg. DOS partitions or Spark archives when SparkFS
+is loaded) as directories but will store them as single files.
+.IP
+For example, if you have SparkFS loaded, zipping a Spark archive will result
+in a zipfile containing a directory (and its content) while using the 'I'
+option will result in a zipfile containing a Spark archive. Obviously this
+second case will also be obtained (without the 'I' option) if SparkFS isn't
+loaded.
+.TP
+.B \-j
+Store just the name of a saved file (junk the path), and do not store
+directory names. By default,
+.I zip
+will store the full path (relative to the current path).
+.TP
+.B \-jj
+[MacOS] record Fullpath (+ Volname). The complete path including
+volume will be stored. By default the relative path will be stored.
+.TP
+.B \-J
+Strip any prepended data (e.g. a SFX stub) from the archive.
+.TP
+.B \-k
+Attempt to convert the names and paths to conform to MSDOS,
+store only the MSDOS attribute (just the user write attribute from UNIX),
+and mark the entry as made under MSDOS (even though it was not);
+for compatibility with PKUNZIP under MSDOS which cannot handle certain
+names such as those with two dots.
+.TP
+.B \-l
+Translate the Unix end-of-line character LF into the
+MSDOS convention CR LF. This option should not be used on binary files.
+This option can be used on Unix if the zip file is intended for PKUNZIP
+under MSDOS. If the input files already contain CR LF, this option adds
+an extra CR. This ensures that
+.I unzip \-a
+on Unix will get back an exact copy of the original file,
+to undo the effect of
+.I zip \-l.
+See the note on binary detection for
+.B \-ll
+below.
+.TP
+.B \-ll
+Translate the MSDOS end-of-line CR LF into Unix LF.
+This option should not be used on binary files and a warning will be
+issued when a file is converted that later is detected to be binary.
+This option can be used on MSDOS if the zip file is intended for unzip
+under Unix.
+.IP
+In Zip 2.31 binary detection has been changed from a simple percentage
+of binary characters being considered binary to a more selective method
+that should consider files in many character sets, including \fIUTF-8\fP,
+that only include text characters in that character set to be text.
+This allows
+.I unzip -a
+to convert these files.
+.TP
+.B \-L
+Display the
+.I zip
+license.
+.TP
+.B \-m
+Move the specified files into the
+.I zip
+archive; actually,
+this deletes the target directories/files after making the specified
+.I zip
+archive. If a directory becomes empty after removal of the files, the
+directory is also removed. No deletions are done until
+.I zip
+has created the archive without error.
+This is useful for conserving disk space,
+but is potentially dangerous so it is recommended to use it in
+combination with
+.B \-T
+to test the archive before removing all input files.
+.TP
+.BI \-n\ suffixes
+Do not attempt to compress files named with the given
+.I suffixes.
+Such files are simply stored (0% compression) in the output zip file,
+so that
+.I zip
+doesn't waste its time trying to compress them.
+The suffixes are separated by
+either colons or semicolons.  For example:
+.RS
+.IP
+\fCzip -rn .Z:.zip:.tiff:.gif:.snd  foo foo\fP
+.RE
+.IP
+will copy everything from
+.I foo
+into
+.IR foo.zip ,
+but will store any files that end in
+.IR .Z ,
+.IR .zip ,
+.IR .tiff ,
+.IR .gif ,
+or
+.I .snd
+without trying to compress them
+(image and sound files often have their own specialized compression methods).
+By default,
+.I zip
+does not compress files with extensions in the list
+.I .Z:.zip:.zoo:.arc:.lzh:.arj.
+Such files are stored directly in the output archive.
+The environment variable ZIPOPT can be used to change the default options. For
+example under Unix with csh:
+.RS
+.IP
+\fCsetenv ZIPOPT "-n .gif:.zip"\fP
+.RE
+.IP
+To attempt compression on all files, use:
+.RS
+.IP
+\fCzip -n : foo\fP
+.RE
+.IP
+The maximum compression option
+.B \-9
+also attempts compression on all files regardless of extension.
+.IP
+On Acorn RISC OS systems the suffixes are actually filetypes (3 hex digit
+format). By default, zip does not compress files with filetypes in the list
+DDC:D96:68E (i.e. Archives, CFS files and PackDir files).
+.TP
+.B \-N
+[Amiga, MacOS] Save Amiga or MacOS filenotes as zipfile comments. They can be
+restored by using the
+.B \-N
+option of unzip. If
+.B \-c
+is used also, you are prompted for comments only for those files that do not
+have filenotes.
+.TP
+.B \-o
+Set the "last modified" time of the
+.I zip
+archive to the latest (oldest) "last modified" time
+found among the entries in the
+.I zip
+archive.
+This can be used without any other operations, if desired.
+For example:
+.RS
+.IP
+\fCzip -o foo\fP
+.RE
+.IP
+will change the last modified time of
+.I foo.zip
+to the latest time of the entries in
+.IR foo.zip .
+.TP
+\fB\-P\fP\ \fIpassword\fP
+use \fIpassword\fP to encrypt zipfile entries (if any).  \fBTHIS IS
+INSECURE!\fP  Many multi-user operating systems provide ways for any user to
+see the current command line of any other user; even on stand-alone systems
+there is always the threat of over-the-shoulder peeking.  Storing the plaintext
+password as part of a command line in an automated script is even worse.
+Whenever possible, use the non-echoing, interactive prompt to enter passwords.
+(And where security is truly important, use strong encryption such as Pretty
+Good Privacy instead of the relatively weak encryption provided by standard
+zipfile utilities.)
+.TP
+.B \-q
+Quiet mode;
+eliminate informational messages and comment prompts.
+(Useful, for example, in shell scripts and background tasks).
+.TP
+.BI \-Qn
+[QDOS] store information about the file in the file header with n defined as
+.RS
+bit  0: Don't add headers for any file
+.RE
+.RS
+bit  1: Add headers for all files
+.RE
+.RS
+bit  2: Don't wait for interactive key press on exit
+.RE
+.TP
+.B \-r
+Travel the directory structure recursively;
+for example:
+.RS
+.IP
+\fCzip -r foo foo\fP
+.RE
+.IP
+In this case, all the files and directories in
+.I foo
+are saved in a
+.I zip
+archive named
+.IR foo.zip ,
+including files with names starting with ".",
+since the recursion does not use the shell's file-name substitution mechanism.
+If you wish to include only a specific subset of the files in directory
+.I foo
+and its subdirectories, use the
+.B \-i
+option to specify the pattern of files to be included.
+You should not use
+.B \-r
+with the name ".*",
+since that matches ".."
+which will attempt to zip up the parent directory
+(probably not what was intended).
+.TP
+.B \-R
+Travel the directory structure recursively starting at the
+current directory;
+for example:
+.RS
+.IP
+\fCzip -R foo '*.c'\fP
+.RE
+.IP
+In this case, all the files matching *.c in the tree starting at the
+current directory are stored into a
+.I zip
+archive named
+.IR foo.zip .
+Note for PKZIP users: the equivalent command is
+.RS
+.IP
+\fCpkzip -rP foo *.c\fP
+.RE
+.TP
+.B \-S
+[MSDOS, OS/2, WIN32 and ATARI] Include system and hidden files.
+.RS
+[MacOS] Includes finder invisible files, which are ignored otherwise.
+.RE
+.TP
+.BI \-t\ mmddyyyy
+Do not operate on files modified prior to the specified date,
+where
+.I mm
+is the month (0-12),
+.I dd
+is the day of the month (1-31),
+and
+.I yyyy
+is the year.
+The
+.I ISO 8601
+date format
+.I yyyy-mm-dd
+is also accepted.
+For example:
+.RS
+.IP
+\fCzip -rt 12071991 infamy foo\fP
+.IP
+\fCzip -rt 1991-12-07 infamy foo\fP
+.RE
+.IP
+will add all the files in
+.I foo
+and its subdirectories that were last modified on or after 7 December 1991,
+to the
+.I zip
+archive
+.IR infamy.zip .
+.TP
+.BI \-tt\ mmddyyyy
+Do not operate on files modified after or at the specified date,
+where
+.I mm
+is the month (0-12),
+.I dd
+is the day of the month (1-31),
+and
+.I yyyy
+is the year.
+The
+.I ISO 8601
+date format
+.I yyyy-mm-dd
+is also accepted.
+For example:
+.RS
+.IP
+\fCzip -rtt 11301995 infamy foo\fP
+.IP
+\fCzip -rtt 1995-11-30 infamy foo\fP
+.RE
+.IP
+will add all the files in
+.I foo
+and its subdirectories that were last modified before the 30 November 1995,
+to the
+.I zip
+archive
+.IR infamy.zip .
+.TP
+.B \-T
+Test the integrity of the new zip file. If the check fails, the old zip file
+is unchanged and (with the
+.B \-m
+option) no input files are removed.
+.TP
+.B \-u
+Replace (update) an existing entry in the
+.I zip
+archive only if it has been modified more recently
+than the version already in the
+.I zip
+archive.
+For example:
+.RS
+.IP
+\fCzip -u stuff *\fP
+.RE
+.IP
+will add any new files in the current directory,
+and update any files which have been modified since the
+.I zip
+archive
+.I stuff.zip
+was last created/modified (note that
+.I zip
+will not try to pack
+.I stuff.zip
+into itself when you do this).
+.IP
+Note that the
+.B \-u
+option with no arguments acts like the
+.B \-f
+(freshen) option.
+.TP
+.B \-v
+Verbose mode or print diagnostic version info.
+.IP
+Normally, when applied to real operations, this option enables the display of a
+progress indicator during compression and requests verbose diagnostic
+info about zipfile structure oddities.
+.IP
+When
+.B \-v
+is the only command line argument, and either stdin or stdout is
+not redirected to a file,
+a diagnostic screen is printed. In addition to the help screen header
+with program name, version, and release date, some pointers to the Info-ZIP
+home and distribution sites are given. Then, it shows information about the
+target environment (compiler type and version, OS version, compilation date
+and the enabled optional features used to create the
+.I zip
+executable.
+.TP
+.B \-V
+[VMS] Save VMS file attributes and use portable form.
+.I zip
+archives created with this option are truncated at EOF but still may not be
+usable on other systems depending on the file types being zipped.
+.TP
+.B \-VV
+[VMS] Save VMS file attributes.
+.I zip
+archives created with this option include the entire file and should be able
+to recreate most VMS files on VMS systems but these archives will generally
+not be usable on other systems.
+.TP
+.B \-w
+[VMS] Append the version number of the files to the name,
+including multiple versions of files.  (default: use only
+the most recent version of a specified file).
+.TP
+.BI \-x\ files
+Explicitly exclude the specified files, as in:
+.RS
+.IP
+\fCzip -r foo foo -x \\*.o\fP
+.RE
+.IP
+which will include the contents of
+.I foo
+in
+.I foo.zip
+while excluding all the files that end in \fI.o\fP.
+The backslash avoids the shell filename substitution, so that the
+name matching is performed by
+.I zip
+at all directory levels.  If you do not escape wildcards in patterns
+it may seem to work but files in subdirectories will not be checked
+for matches.
+.IP
+Also possible:
+.RS
+.IP
+\fCzip -r foo foo -x@exclude.lst\fP
+.RE
+.IP
+which will include the contents of
+.I foo
+in
+.I foo.zip
+while excluding all the files that match the patterns in the file exclude.lst
+(each file pattern on a separate line).
+.TP
+.B \-X
+Do not save extra file attributes (Extended Attributes on OS/2, uid/gid
+and file times on Unix).
+.TP
+.B \-y
+Store symbolic links as such in the
+.I zip
+archive,
+instead of compressing and storing the file referred to by the link
+(UNIX only).
+.TP
+.B \-z
+Prompt for a multi-line comment for the entire
+.I zip
+archive.
+The comment is ended by a line containing just a period,
+or an end of file condition (^D on UNIX, ^Z on MSDOS, OS/2, and VAX/VMS).
+The comment can be taken from a file:
+.RS
+.IP
+\fCzip -z foo < foowhat\fP
+.RE
+.TP
+.BI \-#
+Regulate the speed of compression using the specified digit
+.IR # ,
+where
+.B \-0
+indicates no compression (store all files),
+.B \-1
+indicates the fastest compression method (less compression)
+and
+.B \-9
+indicates the slowest compression method (optimal compression, ignores
+the suffix list). The default compression level is
+.BR \-6.
+.TP
+.B \-!
+[WIN32] Use priviliges (if granted) to obtain all aspects of WinNT security.
+.TP
+.B \-@
+Take the list of input files from standard input. Only one filename per line.
+.TP
+.B \-$
+[MSDOS, OS/2, WIN32] Include the volume label for the drive holding
+the first file to be compressed.  If you want to include only the volume
+label or to force a specific drive, use the drive name as first file name,
+as in:
+.RS
+.IP
+\fCzip -$ foo a: c:bar\fP
+.RE
+.IP
+.SH "EXAMPLES"
+The simplest example:
+.IP
+\fCzip stuff *\fP
+.LP
+creates the archive
+.I stuff.zip
+(assuming it does not exist)
+and puts all the files in the current directory in it, in compressed form
+(the
+.I \&.zip
+suffix is added automatically,
+unless that archive name given contains a dot already;
+this allows the explicit specification of other suffixes).
+.LP
+Because of the way the shell does filename substitution,
+files starting with "." are not included;
+to include these as well:
+.IP
+\fCzip stuff .* *\fP
+.LP
+Even this will not include any subdirectories from the current directory.
+.LP
+To zip up an entire directory, the command:
+.IP
+\fCzip -r foo foo\fP
+.LP
+creates the archive
+.IR foo.zip ,
+containing all the files and directories in the directory
+.I foo
+that is contained within the current directory.
+.LP
+You may want to make a
+.I zip
+archive that contains the files in
+.IR foo ,
+without recording the directory name,
+.IR foo .
+You can use the
+.B \-j
+option to leave off the paths,
+as in:
+.IP
+\fCzip -j foo foo/*\fP
+.LP
+If you are short on disk space,
+you might not have enough room to hold both the original directory
+and the corresponding compressed
+.I zip
+archive.
+In this case, you can create the archive in steps using the
+.B \-m
+option.
+If
+.I foo
+contains the subdirectories
+.IR tom ,
+.IR dick ,
+and
+.IR harry ,
+you can:
+.IP
+\fCzip -rm foo foo/tom\fP
+.br
+\fCzip -rm foo foo/dick\fP
+.br
+\fCzip -rm foo foo/harry\fP
+.LP
+where the first command creates
+.IR foo.zip ,
+and the next two add to it.
+At the completion of each
+.I zip
+command,
+the last created archive is deleted,
+making room for the next
+.I zip
+command to function.
+.SH "PATTERN MATCHING"
+This section applies only to UNIX, though the ?, *, and [] special
+characters are implemented on other systems including MSDOS and Win32.
+Watch this space for details on MSDOS and VMS operation.
+.LP
+The UNIX shells
+.RI ( sh (1)
+and
+.IR csh (1))
+do filename substitution on command arguments.
+The special characters are:
+.TP
+.B ?
+match any single character
+.TP
+.B *
+match any number of characters (including none)
+.TP
+.B []
+match any character in the range indicated within the brackets
+(example: [a\-f], [0\-9]).
+.LP
+When these characters are encountered
+(without being escaped with a backslash or quotes),
+the shell will look for files relative to the current path
+that match the pattern,
+and replace the argument with a list of the names that matched.
+.LP
+The
+.I zip
+program can do the same matching on names that are in the
+.I zip
+archive being modified or,
+in the case of the
+.B \-x
+(exclude) or
+.B \-i
+(include) options, on the list of files to be operated on, by using
+backslashes or quotes to tell the shell not to do the name expansion.
+In general, when
+.I zip
+encounters a name in the list of files to do, it first looks for the name in
+the file system.  If it finds it, it then adds it to the list of files to do.
+If it does not find it, it looks for the name in the
+.I zip
+archive being modified (if it exists), using the pattern matching characters
+described above, if present.  For each match, it will add that name to the
+list of files to be processed, unless this name matches one given
+with the
+.B \-x
+option, or does not match any name given with the
+.B \-i
+option.
+.LP
+The pattern matching includes the path,
+and so patterns like \\*.o match names that end in ".o",
+no matter what the path prefix is.
+Note that the backslash must precede every special character (i.e. ?*[]),
+or the entire argument must be enclosed in double quotes ("").
+.LP
+In general, use backslash to make
+.I zip
+do the pattern matching with the
+.B \-f
+(freshen) and
+.B \-d
+(delete) options,
+and sometimes after the
+.B \-x
+(exclude) option when used with an appropriate operation (add,
+.BR \-u ,
+.BR \-f ,
+or
+.BR \-d ).
+.SH "ENVIRONMENT"
+.TP
+.B ZIPOPT
+contains default options that will be used when running
+.I zip
+.TP
+.B ZIP
+[Not on RISC OS and VMS] see ZIPOPT
+.TP
+.B Zip$Options
+[RISC OS] see ZIPOPT
+.TP
+.B Zip$Exts
+[RISC OS] contains extensions separated by a : that will cause
+native filenames with one of the specified extensions to
+be added to the zip file with basename and extension swapped.
+.I zip
+.TP
+.B ZIP_OPTS
+[VMS] see ZIPOPT
+.SH "SEE ALSO"
+compress(1),
+shar(1L),
+tar(1),
+unzip(1L),
+gzip(1L)
+.SH DIAGNOSTICS
+The exit status (or error level) approximates the exit codes defined by PKWARE
+and takes on the following values, except under VMS:
+.RS
+.IP 0
+normal; no errors or warnings detected.
+.IP 2
+unexpected end of zip file.
+.IP 3
+a generic error in the zipfile format was detected.  Processing may have
+completed successfully anyway; some broken zipfiles created by other
+archivers have simple work-arounds.
+.IP 4
+\fIzip\fP was unable to allocate memory for one or more buffers during
+program initialization.
+.IP 5
+a severe error in the zipfile format was detected.  Processing probably
+failed immediately.
+.IP 6
+entry too large to split (with \fIzipsplit\fP), read, or write
+.IP 7
+invalid comment format
+.IP 8
+.I zip \-T
+failed or out of memory
+.IP 9
+the user aborted \fIzip\fP prematurely with control-C (or similar)
+.IP 10
+\fIzip\fP encountered an error while using a temp file
+.IP 11
+read or seek error
+.IP 12
+\fIzip\fP has nothing to do
+.IP 13
+missing or empty zip file
+.IP 14
+error writing to a file
+.IP 15
+\fIzip\fP was unable to create a file to write to
+.IP 16
+bad command line parameters
+.IP 18
+\fIzip\fP could not open a specified file to read
+.RE
+.PP
+VMS interprets standard Unix (or PC) return values as other, scarier-looking
+things, so \fIzip\fP instead maps them into VMS-style status codes.  The
+current mapping is as follows:   1 (success) for normal exit,
+ and (0x7fff000? + 16*normal_zip_exit_status) for all errors, where the
+`?' is 0 (warning) for \fIzip\fP value 12, 2 (error) for the
+\fIzip\fP values 3, 6, 7, 9, 13, 16, 18,
+and 4 (fatal error) for the remaining ones.
+.PD
+.SH BUGS
+.I zip
+2.31 is not compatible with PKUNZIP 1.10. Use
+.I zip
+1.1 to produce
+.I zip
+files which can be extracted by PKUNZIP 1.10.
+.PP
+.I zip
+files produced by
+.I zip
+2.31 must not be
+.I updated
+by
+.I zip
+1.1 or PKZIP 1.10, if they contain
+encrypted members or if they have been produced in a pipe or on a non-seekable
+device. The old versions of
+.I zip
+or PKZIP would create an archive with an incorrect format.
+The old versions can list the contents of the zip file
+but cannot extract it anyway (because of the new compression algorithm).
+If you do not use encryption and use regular disk files, you do
+not have to care about this problem.
+.LP
+Under VMS,
+not all of the odd file formats are treated properly.
+Only stream-LF format
+.I zip
+files are expected to work with
+.IR zip .
+Others can be converted using Rahul Dhesi's BILF program.
+This version of
+.I zip
+handles some of the conversion internally.
+When using Kermit to transfer zip files from Vax to MSDOS, type "set
+file type block" on the Vax.  When transfering from MSDOS to Vax, type
+"set file type fixed" on the Vax.  In both cases, type "set file type
+binary" on MSDOS.
+.LP
+Under VMS, zip hangs for file specification that uses DECnet syntax
+.I foo::*.*.
+.LP
+On OS/2, zip cannot match some names, such as those including an
+exclamation mark or a hash sign.  This is a bug in OS/2 itself: the
+32-bit DosFindFirst/Next don't find such names.  Other programs such
+as GNU tar are also affected by this bug.
+.LP
+Under OS/2, the amount of Extended Attributes displayed by DIR is (for
+compatibility) the amount returned by the 16-bit version of
+DosQueryPathInfo(). Otherwise OS/2 1.3 and 2.0 would report different
+EA sizes when DIRing a file.
+However, the structure layout returned by the 32-bit DosQueryPathInfo()
+is a bit different, it uses extra padding bytes and link pointers (it's
+a linked list) to have all fields on 4-byte boundaries for portability
+to future RISC OS/2 versions. Therefore the value reported by
+.I zip
+(which uses this 32-bit-mode size) differs from that reported by DIR.
+.I zip
+stores the 32-bit format for portability, even the 16-bit
+MS-C-compiled version running on OS/2 1.3, so even this one shows the
+32-bit-mode size.
+.LP
+Development of Zip 3.0 is underway.  See that source distribution for
+many new features and the latest bug fixes.
+.SH AUTHORS
+Copyright (C) 1997-2005 Info-ZIP.
+.LP
+Copyright (C) 1990-1997 Mark Adler, Richard B. Wales, Jean-loup Gailly,
+Onno van der Linden, Kai Uwe Rommel, Igor Mandrichenko, John Bush and
+Paul Kienitz.
+Permission is granted to any individual or institution to use, copy, or
+redistribute this software so long as all of the original files are included,
+that it is not sold for profit, and that this copyright notice
+is retained.
+.LP
+LIKE ANYTHING ELSE THAT'S FREE, ZIP AND ITS ASSOCIATED UTILITIES ARE
+PROVIDED AS IS AND COME WITH NO WARRANTY OF ANY KIND, EITHER EXPRESSED OR
+IMPLIED. IN NO EVENT WILL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES
+RESULTING FROM THE USE OF THIS SOFTWARE.
+.LP
+Please send bug reports and comments to:
+.IR zip-bugs
+at
+.IR www.info-zip.org .
+For bug reports, please include the version of
+.IR zip
+(see \fIzip\ \-h\fP),
+the make options used to compile it (see \fIzip\ \-v\fP),
+the machine and operating system in use,
+and as much additional information as possible.
+.SH ACKNOWLEDGEMENTS
+Thanks to R. P. Byrne for his
+.I Shrink.Pas
+program, which inspired this project,
+and from which the shrink algorithm was stolen;
+to Phil Katz for placing in the public domain the
+.I zip
+file format, compression format, and .ZIP filename extension, and for
+accepting minor changes to the file format; to Steve Burg for
+clarifications on the deflate format; to Haruhiko Okumura and Leonid
+Broukhis for providing some useful ideas for the compression
+algorithm; to Keith Petersen, Rich Wales, Hunter Goatley and Mark
+Adler for providing a mailing list and
+.I ftp
+site for the Info-ZIP group to use; and most importantly, to the
+Info-ZIP group itself (listed in the file
+.IR infozip.who )
+without whose tireless testing and bug-fixing efforts a portable
+.I zip
+would not have been possible.
+Finally we should thank (blame) the first Info-ZIP moderator,
+David Kirschbaum,
+for getting us into this mess in the first place.
+The manual page was rewritten for UNIX by R. P. C. Rodgers.
+.\" end of file
diff --git a/match.S b/match.S
new file mode 100644 (file)
index 0000000..eb8f735
--- /dev/null
+++ b/match.S
@@ -0,0 +1,407 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+
+/*
+ * match.s by Jean-loup Gailly. Translated to 32 bit code by Kai Uwe Rommel.
+ * The 68020 version has been written by Francesco Potorti` <pot@cnuce.cnr.it>
+ * with adaptations by Carsten Steger <stegerc@informatik.tu-muenchen.de>,
+ * Andreas Schwab <schwab@lamothe.informatik.uni-dortmund.de> and
+ * Kristoffer Eriksson <ske@pkmab.se>
+ */
+
+/* This file is NOT used in conjunction with zlib. */
+#ifndef USE_ZLIB
+
+/* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix
+ * external symbols with an underline character '_'.
+ */
+#if defined(NO_UNDERLINE) || defined(__ELF__)
+#  define _prev             prev
+#  define _window           window
+#  define _match_start      match_start
+#  define _prev_length      prev_length
+#  define _good_match       good_match
+#  define _nice_match       nice_match
+#  define _strstart         strstart
+#  define _max_chain_length max_chain_length
+
+#  define _match_init       match_init
+#  define _longest_match    longest_match
+#endif
+
+#ifdef DYN_ALLOC
+  error: DYN_ALLOC not yet supported in match.s
+#endif
+
+/* Use 16-bytes alignment if your assembler supports it. Warning: gas
+ * uses a log(x) parameter (.align 4 means 16-bytes alignment). On SVR4
+ * the parameter is a number of bytes.
+ */
+#ifndef ALIGNMENT
+#  define ALIGNMENT 4
+#endif
+
+
+#ifndef WSIZE
+# define WSIZE          32768
+#endif
+#define MIN_MATCH       3
+#define MAX_MATCH       258
+#define MIN_LOOKAHEAD   (MAX_MATCH + MIN_MATCH + 1)
+#define MAX_DIST        (WSIZE - MIN_LOOKAHEAD)
+
+#if defined(i386) || defined(_I386) || defined(_i386) || defined(__i386)
+
+/* This version is for 386 Unix or OS/2 in 32 bit mode.
+ * Warning: it uses the AT&T syntax: mov source,dest
+ * This file is only optional. If you want to force the C version,
+ * add -DNO_ASM to CFLAGS in Makefile and set OBJA to an empty string.
+ * If you have reduced WSIZE in (g)zip.h, then make sure this is
+ * assembled with an equivalent -DWSIZE=<whatever>.
+ * This version assumes static allocation of the arrays (-DDYN_ALLOC not used).
+ */
+
+        .file   "match.S"
+
+        .globl  _match_init
+        .globl  _longest_match
+
+        .text
+
+_match_init:
+        ret
+
+/*-----------------------------------------------------------------------
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ */
+
+        .align  ALIGNMENT
+
+_longest_match: /* int longest_match(cur_match) */
+
+#define cur_match   20(%esp)
+     /* return address */               /* esp+16 */
+        push    %ebp                    /* esp+12 */
+        push    %edi                    /* esp+8  */
+        push    %esi                    /* esp+4  */
+        push    %ebx                    /* esp    */
+
+/*
+ *      match        equ esi
+ *      scan         equ edi
+ *      chain_length equ ebp
+ *      best_len     equ ebx
+ *      limit        equ edx
+ */
+        mov     cur_match,%esi
+        mov     _strstart,%edx
+        mov     _max_chain_length,%ebp /* chain_length = max_chain_length */
+        mov     %edx,%edi
+        sub     $(MAX_DIST),%edx       /* limit = strstart-MAX_DIST */
+        cld                            /* string ops increment si and di */
+        jae     limit_ok
+        sub     %edx,%edx              /* limit = NIL */
+limit_ok:
+        add     $2+_window,%edi        /* edi = offset(window+strstart+2) */
+        mov     _prev_length,%ebx      /* best_len = prev_length */
+        movw    -2(%edi),%cx           /* cx = scan[0..1] */
+        movw    -3(%ebx,%edi),%ax      /* ax = scan[best_len-1..best_len] */
+        cmp     _good_match,%ebx       /* do we have a good match already? */
+        jb      do_scan
+        shr     $2,%ebp                /* chain_length >>= 2 */
+        jmp     do_scan
+
+        .align  ALIGNMENT
+long_loop:
+/* at this point, edi == scan+2, esi == cur_match */
+        movw    -3(%ebx,%edi),%ax       /* ax = scan[best_len-1..best_len] */
+        movw     -2(%edi),%cx           /* cx = scan[0..1] */
+short_loop:
+/*
+ * at this point, di == scan+2, si == cur_match,
+ * ax = scan[best_len-1..best_len] and cx = scan[0..1]
+ */
+        and     $(WSIZE-1), %esi
+        dec     %ebp                    /* --chain_length */
+        movw    _prev(,%esi,2),%si      /* cur_match = prev[cur_match] */
+                                        /* top word of esi is still 0 */
+        jz      the_end
+        cmp     %edx,%esi               /* cur_match <= limit ? */
+        jbe     the_end
+do_scan:
+        cmpw    _window-1(%ebx,%esi),%ax/* check match at best_len-1 */
+        jne     short_loop
+        cmpw    _window(%esi),%cx       /* check min_match_length match */
+        jne     short_loop
+
+        add     $2+_window,%esi         /* si = match */
+        mov     $((MAX_MATCH>>1)-1),%ecx/* scan for at most MAX_MATCH bytes */
+        mov     %edi,%eax               /* ax = scan+2 */
+        repe;   cmpsw                   /* loop until mismatch */
+        je      maxmatch                /* match of length MAX_MATCH? */
+mismatch:
+        movb    -2(%edi),%cl        /* mismatch on first or second byte? */
+        xchg    %edi,%eax           /* edi = scan+2, eax = end of scan */
+        subb    -2(%esi),%cl        /* cl = 0 if first bytes equal */
+        sub     %edi,%eax           /* eax = len */
+        sub     $2+_window,%esi     /* esi = cur_match + len */
+        sub     %eax,%esi           /* esi = cur_match */
+        subb    $1,%cl              /* set carry if cl == 0 (cannot use DEC) */
+        adc     $0,%eax             /* eax = carry ? len+1 : len */
+        cmp     %ebx,%eax           /* len > best_len ? */
+        jle     long_loop
+        mov     %esi,_match_start       /* match_start = cur_match */
+        mov     %eax,%ebx               /* ebx = best_len = len */
+#ifdef FULL_SEARCH
+        cmp     $(MAX_MATCH),%eax       /* len >= MAX_MATCH ? */
+#else
+        cmp     _nice_match,%eax        /* len >= nice_match ? */
+#endif
+        jl      long_loop
+the_end:
+        mov     %ebx,%eax               /* result = eax = best_len */
+        pop     %ebx
+        pop     %esi
+        pop     %edi
+        pop     %ebp
+        ret
+        .align  ALIGNMENT
+maxmatch:
+        cmpsb
+        jmp     mismatch
+
+#else /* !(i386 || _I386 || _i386 || __i386) */
+
+/* ======================== 680x0 version ================================= */
+
+#if defined(m68k)||defined(mc68k)||defined(__mc68000__)||defined(__MC68000__)
+#  ifndef mc68000
+#    define mc68000
+#  endif
+#endif
+
+#if defined(__mc68020__) || defined(__MC68020__) || defined(sysV68)
+#  ifndef mc68020
+#    define mc68020
+#  endif
+#endif
+
+#if defined(mc68020) || defined(mc68000)
+
+#if (defined(mc68020) || defined(NeXT)) && !defined(UNALIGNED_OK)
+#  define UNALIGNED_OK
+#endif
+
+#ifdef sysV68  /* Try Motorola Delta style */
+
+#  define GLOBAL(symbol)        global  symbol
+#  define TEXT                  text
+#  define FILE(filename)        file    filename
+#  define invert_maybe(src,dst) dst,src
+#  define imm(data)             &data
+#  define reg(register)         %register
+
+#  define addl                  add.l
+#  define addql                 addq.l
+#  define blos                  blo.b
+#  define bhis                  bhi.b
+#  define bras                  bra.b
+#  define clrl                  clr.l
+#  define cmpmb                 cmpm.b
+#  define cmpw                  cmp.w
+#  define cmpl                  cmp.l
+#  define lslw                  lsl.w
+#  define lsrl                  lsr.l
+#  define movel                 move.l
+#  define movew                 move.w
+#  define moveb                 move.b
+#  define moveml                movem.l
+#  define subl                  sub.l
+#  define subw                  sub.w
+#  define subql                 subq.l
+
+#  define IndBase(bd,An)        (bd,An)
+#  define IndBaseNdxl(bd,An,Xn) (bd,An,Xn.l)
+#  define IndBaseNdxw(bd,An,Xn) (bd,An,Xn.w)
+#  define predec(An)            -(An)
+#  define postinc(An)           (An)+
+
+#else /* default style (Sun 3, NeXT, Amiga, Atari) */
+
+#  define GLOBAL(symbol)        .globl  symbol
+#  define TEXT                  .text
+#  define FILE(filename)        .even
+#  define invert_maybe(src,dst) src,dst
+#  if defined(sun) || defined(mc68k)
+#    define imm(data)           #data
+#  else
+#    define imm(data)           \#data
+#  endif
+#  define reg(register)         register
+
+#  define blos                  bcss
+#  if defined(sun) || defined(mc68k)
+#    define movel               movl
+#    define movew               movw
+#    define moveb               movb
+#  endif
+#  define IndBase(bd,An)        An@(bd)
+#  define IndBaseNdxl(bd,An,Xn) An@(bd,Xn:l)
+#  define IndBaseNdxw(bd,An,Xn) An@(bd,Xn:w)
+#  define predec(An)            An@-
+#  define postinc(An)           An@+
+
+#endif  /* styles */
+
+#define Best_Len        reg(d0)         /* unsigned */
+#define Cur_Match       reg(d1)         /* Ipos */
+#define Loop_Counter    reg(d2)         /* int */
+#define Scan_Start      reg(d3)         /* unsigned short */
+#define Scan_End        reg(d4)         /* unsigned short */
+#define Limit           reg(d5)         /* IPos */
+#define Chain_Length    reg(d6)         /* unsigned */
+#define Scan_Test       reg(d7)
+#define Scan            reg(a0)         /* *uch */
+#define Match           reg(a1)         /* *uch */
+#define Prev_Address    reg(a2)         /* *Pos */
+#define Scan_Ini        reg(a3)         /* *uch */
+#define Match_Ini       reg(a4)         /* *uch */
+#define Stack_Pointer   reg(sp)
+
+        GLOBAL  (_match_init)
+        GLOBAL  (_longest_match)
+
+        TEXT
+
+        FILE    ("match.S")
+
+_match_init:
+        rts
+
+/*-----------------------------------------------------------------------
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ */
+
+/* int longest_match (cur_match) */
+
+#ifdef UNALIGNED_OK
+#  define pushreg       15928           /* d2-d6/a2-a4 */
+#  define popreg        7292
+#else
+#  define pushreg       16184           /* d2-d7/a2-a4 */
+#  define popreg        7420
+#endif
+
+_longest_match:
+        movel   IndBase(4,Stack_Pointer),Cur_Match
+        moveml  imm(pushreg),predec(Stack_Pointer)
+        movel   _max_chain_length,Chain_Length
+        movel   _prev_length,Best_Len
+        movel   imm(_prev),Prev_Address
+        movel   imm(_window+MIN_MATCH),Match_Ini
+        movel   _strstart,Limit
+        movel   Match_Ini,Scan_Ini
+        addl    Limit,Scan_Ini
+        subw    imm(MAX_DIST),Limit
+        bhis    L__limit_ok
+        clrl    Limit
+L__limit_ok:
+        cmpl    invert_maybe(_good_match,Best_Len)
+        blos    L__length_ok
+        lsrl    imm(2),Chain_Length
+L__length_ok:
+        subql   imm(1),Chain_Length
+#ifdef UNALIGNED_OK
+        movew   IndBase(-MIN_MATCH,Scan_Ini),Scan_Start
+        movew   IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
+#else
+        moveb   IndBase(-MIN_MATCH,Scan_Ini),Scan_Start
+        lslw    imm(8),Scan_Start
+        moveb   IndBase(-MIN_MATCH+1,Scan_Ini),Scan_Start
+        moveb   IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
+        lslw    imm(8),Scan_End
+        moveb   IndBaseNdxw(-MIN_MATCH,Scan_Ini,Best_Len),Scan_End
+#endif
+        bras    L__do_scan
+
+L__long_loop:
+#ifdef UNALIGNED_OK
+        movew   IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
+#else
+        moveb   IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
+        lslw    imm(8),Scan_End
+        moveb   IndBaseNdxw(-MIN_MATCH,Scan_Ini,Best_Len),Scan_End
+#endif
+
+L__short_loop:
+        lslw    imm(1),Cur_Match
+        movew   IndBaseNdxl(0,Prev_Address,Cur_Match),Cur_Match
+        cmpw    invert_maybe(Limit,Cur_Match)
+        dbls    Chain_Length,L__do_scan
+        bras    L__return
+
+L__do_scan:
+        movel   Match_Ini,Match
+        addl    Cur_Match,Match
+#ifdef UNALIGNED_OK
+        cmpw    invert_maybe(IndBaseNdxw(-MIN_MATCH-1,Match,Best_Len),Scan_End)
+        bne     L__short_loop
+        cmpw    invert_maybe(IndBase(-MIN_MATCH,Match),Scan_Start)
+        bne     L__short_loop
+#else
+        moveb   IndBaseNdxw(-MIN_MATCH-1,Match,Best_Len),Scan_Test
+        lslw    imm(8),Scan_Test
+        moveb   IndBaseNdxw(-MIN_MATCH,Match,Best_Len),Scan_Test
+        cmpw    invert_maybe(Scan_Test,Scan_End)
+        bne     L__short_loop
+        moveb   IndBase(-MIN_MATCH,Match),Scan_Test
+        lslw    imm(8),Scan_Test
+        moveb   IndBase(-MIN_MATCH+1,Match),Scan_Test
+        cmpw    invert_maybe(Scan_Test,Scan_Start)
+        bne     L__short_loop
+#endif
+
+        movew   imm((MAX_MATCH-MIN_MATCH+1)-1),Loop_Counter
+        movel   Scan_Ini,Scan
+L__scan_loop:
+        cmpmb   postinc(Match),postinc(Scan)
+        dbne    Loop_Counter,L__scan_loop
+
+        subl    Scan_Ini,Scan
+        addql   imm(MIN_MATCH-1),Scan
+        cmpl    invert_maybe(Best_Len,Scan)
+        bls     L__short_loop
+        movel   Scan,Best_Len
+        movel   Cur_Match,_match_start
+#ifdef FULL_SEARCH
+        cmpl    invert_maybe(imm(MAX_MATCH),Best_Len)
+#else
+        cmpl    invert_maybe(_nice_match,Best_Len)
+#endif
+        blos    L__long_loop
+L__return:
+        moveml  postinc(Stack_Pointer),imm(popreg)
+        rts
+
+#else
+ error: this asm version is for 386 or 680x0 only
+#endif /* mc68000 || mc68020 */
+#endif /* i386 || _I386 || _i386 || __i386  */
+
+#endif /* !USE_ZLIB */
diff --git a/mktime.c b/mktime.c
new file mode 100644 (file)
index 0000000..0f1edc5
--- /dev/null
+++ b/mktime.c
@@ -0,0 +1,257 @@
+/* free mktime function
+   Copyright 1988, 1989 by David MacKenzie <djm@ai.mit.edu>
+   and Michael Haertel <mike@ai.mit.edu>
+   Unlimited distribution permitted provided this copyright notice is
+   retained and any functional modifications are prominently identified.  */
+
+/* Revised 1997 by Christian Spieler:
+   The code was changed to get more conformance with ANSI's (resp. modern
+   UNIX releases) definition for mktime():
+   - Added adjustment for out-of-range values in the fields of struct tm.
+   - Added iterations to get the correct UTC result for input values at
+     the gaps when daylight saving time is switched on or off.
+   - Allow forcing of DST "on" or DST "off" by setting `tm_isdst' field in
+     the tm struct to positive number resp. zero. The `tm_isdst' field must
+     be negative on entrance of mktime() to enable automatic determination
+     if DST is in effect for the requested local time.
+   - Added optional check for overflowing the time_t range.  */
+
+/* Note: This version of mktime is ignorant of the tzfile.
+   When the tm structure passed to mktime represents a local time that
+   is valid both as DST time and as standard time (= time value in the
+   gap when switching from DST back to standard time), the behaviour
+   for `tm_isdst < 0' depends on the current timezone: TZ east of GMT
+   assumes winter time, TZ west of GMT assumes summer time.
+   Although mktime() (resp. mkgmtime()) tries to adjust for invalid values
+   of struct tm members, this may fail for input values that are far away
+   from the valid ranges. The adjustment process does not check for overflows
+   or wrap arounds in the struct tm components.  */
+
+#ifndef OF
+#  ifdef __STDC__
+#    define OF(a) a
+#  else
+#    define OF(a) ()
+#  endif
+#endif
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+
+#include <time.h>
+
+time_t mkgmtime OF((struct tm *));
+time_t mktime OF((struct tm *));
+
+/* Return the equivalent in seconds past 12:00:00 a.m. Jan 1, 1970 GMT
+   of the local time and date in the exploded time structure `tm',
+   adjust out of range fields in `tm' and set `tm->tm_yday', `tm->tm_wday'.
+   If `tm->tm_isdst < 0' was passed to mktime(), the correct setting of
+   tm_isdst is determined and returned. Otherwise, mktime() assumes this
+   field as valid; its information is used when converting local time
+   to UTC.
+   Return -1 if time in `tm' cannot be represented as time_t value. */
+
+time_t
+mktime(tm)
+     struct tm *tm;
+{
+  struct tm *ltm;               /* Local time. */
+  time_t loctime;               /* The time_t value of local time. */
+  time_t then;                  /* The time to return. */
+  long tzoffset_adj;            /* timezone-adjustment `remainder' */
+  int bailout_cnt;              /* counter of tries for tz correction */
+  int save_isdst;               /* Copy of the tm->isdst input value */
+
+  save_isdst = tm->tm_isdst;
+  loctime = mkgmtime(tm);
+  if (loctime == -1) {
+    tm->tm_isdst = save_isdst;
+    return (time_t)-1;
+  }
+
+  /* Correct for the timezone and any daylight savings time.
+     The correction is verified and repeated when not correct, to
+     take into account the rare case that a change to or from daylight
+     savings time occurs between when it is the time in `tm' locally
+     and when it is that time in Greenwich. After the second correction,
+     the "timezone & daylight" offset should be correct in all cases. To
+     be sure, we allow a third try, but then the loop is stopped. */
+  bailout_cnt = 3;
+  then = loctime;
+  do {
+    ltm = localtime(&then);
+    if (ltm == (struct tm *)NULL ||
+        (tzoffset_adj = loctime - mkgmtime(ltm)) == 0L)
+      break;
+    then += tzoffset_adj;
+  } while (--bailout_cnt > 0);
+
+  if (ltm == (struct tm *)NULL || tzoffset_adj != 0L) {
+    /* Signal failure if timezone adjustment did not converge. */
+    tm->tm_isdst = save_isdst;
+    return (time_t)-1;
+  }
+
+  if (save_isdst >= 0) {
+    if (ltm->tm_isdst  && !save_isdst)
+    {
+      if (then + 3600 < then)
+        then = (time_t)-1;
+      else
+        then += 3600;
+    }
+    else if (!ltm->tm_isdst && save_isdst)
+    {
+      if (then - 3600 > then)
+        then = (time_t)-1;
+      else
+        then -= 3600;
+    }
+    ltm->tm_isdst = save_isdst;
+  }
+
+  if (tm != ltm)  /* `tm' may already point to localtime's internal storage */
+    *tm = *ltm;
+
+  return then;
+}
+
+
+#ifndef NO_TIME_T_MAX
+   /* Provide default values for the upper limit of the time_t range.
+      These are the result of the decomposition into a `struct tm' for
+      the time value 0xFFFFFFFEL ( = (time_t)-2 ).
+      Note: `(time_t)-1' is reserved for "invalid time"!  */
+#  ifndef TM_YEAR_MAX
+#    define TM_YEAR_MAX         2106
+#  endif
+#  ifndef TM_MON_MAX
+#    define TM_MON_MAX          1       /* February */
+#  endif
+#  ifndef TM_MDAY_MAX
+#    define TM_MDAY_MAX         7
+#  endif
+#  ifndef TM_HOUR_MAX
+#    define TM_HOUR_MAX         6
+#  endif
+#  ifndef TM_MIN_MAX
+#    define TM_MIN_MAX          28
+#  endif
+#  ifndef TM_SEC_MAX
+#    define TM_SEC_MAX          14
+#  endif
+#endif /* NO_TIME_T_MAX */
+
+/* Adjusts out-of-range values for `tm' field `tm_member'. */
+#define ADJUST_TM(tm_member, tm_carry, modulus) \
+  if ((tm_member) < 0) { \
+    tm_carry -= (1 - ((tm_member)+1) / (modulus)); \
+    tm_member = (modulus-1) + (((tm_member)+1) % (modulus)); \
+  } else if ((tm_member) >= (modulus)) { \
+    tm_carry += (tm_member) / (modulus); \
+    tm_member = (tm_member) % (modulus); \
+  }
+
+/* Nonzero if `y' is a leap year, else zero. */
+#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
+
+/* Number of leap years from 1970 to `y' (not including `y' itself). */
+#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
+
+/* Additional leapday in February of leap years. */
+#define leapday(m, y) ((m) == 1 && leap (y))
+
+/* Length of month `m' (0 .. 11) */
+#define monthlen(m, y) (ydays[(m)+1] - ydays[m] + leapday (m, y))
+
+/* Accumulated number of days from 01-Jan up to start of current month. */
+static ZCONST short ydays[] =
+{
+  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+};
+
+/* Return the equivalent in seconds past 12:00:00 a.m. Jan 1, 1970 GMT
+   of the Greenwich Mean time and date in the exploded time structure `tm'.
+   This function does always put back normalized values into the `tm' struct,
+   parameter, including the calculated numbers for `tm->tm_yday',
+   `tm->tm_wday', and `tm->tm_isdst'.
+   Returns -1 if the time in the `tm' parameter cannot be represented
+   as valid `time_t' number. */
+
+time_t
+mkgmtime(tm)
+     struct tm *tm;
+{
+  int years, months, days, hours, minutes, seconds;
+
+  years = tm->tm_year + 1900;   /* year - 1900 -> year */
+  months = tm->tm_mon;          /* 0..11 */
+  days = tm->tm_mday - 1;       /* 1..31 -> 0..30 */
+  hours = tm->tm_hour;          /* 0..23 */
+  minutes = tm->tm_min;         /* 0..59 */
+  seconds = tm->tm_sec;         /* 0..61 in ANSI C. */
+
+  ADJUST_TM(seconds, minutes, 60)
+  ADJUST_TM(minutes, hours, 60)
+  ADJUST_TM(hours, days, 24)
+  ADJUST_TM(months, years, 12)
+  if (days < 0)
+    do {
+      if (--months < 0) {
+        --years;
+        months = 11;
+      }
+      days += monthlen(months, years);
+    } while (days < 0);
+  else
+    while (days >= monthlen(months, years)) {
+      days -= monthlen(months, years);
+      if (++months >= 12) {
+        ++years;
+        months = 0;
+      }
+    }
+
+  /* Restore adjusted values in tm structure */
+  tm->tm_year = years - 1900;
+  tm->tm_mon = months;
+  tm->tm_mday = days + 1;
+  tm->tm_hour = hours;
+  tm->tm_min = minutes;
+  tm->tm_sec = seconds;
+
+  /* Set `days' to the number of days into the year. */
+  days += ydays[months] + (months > 1 && leap (years));
+  tm->tm_yday = days;
+
+  /* Now calculate `days' to the number of days since Jan 1, 1970. */
+  days = (unsigned)days + 365 * (unsigned)(years - 1970) +
+         (unsigned)(nleap (years));
+  tm->tm_wday = ((unsigned)days + 4) % 7; /* Jan 1, 1970 was Thursday. */
+  tm->tm_isdst = 0;
+
+  if (years < 1970)
+    return (time_t)-1;
+
+#if (defined(TM_YEAR_MAX) && defined(TM_MON_MAX) && defined(TM_MDAY_MAX))
+#if (defined(TM_HOUR_MAX) && defined(TM_MIN_MAX) && defined(TM_SEC_MAX))
+  if (years > TM_YEAR_MAX ||
+      (years == TM_YEAR_MAX &&
+       (tm->tm_yday > ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
+                      (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) ||
+        (tm->tm_yday == ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
+                        (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) &&
+         (hours > TM_HOUR_MAX ||
+          (hours == TM_HOUR_MAX &&
+           (minutes > TM_MIN_MAX ||
+            (minutes == TM_MIN_MAX && seconds > TM_SEC_MAX) )))))))
+    return (time_t)-1;
+#endif
+#endif
+
+  return (time_t)(86400L * (unsigned long)(unsigned)days +
+                  3600L * (unsigned long)hours +
+                  (unsigned long)(60 * minutes + seconds));
+}
diff --git a/msdos/README.DOS b/msdos/README.DOS
new file mode 100644 (file)
index 0000000..a9b5ccb
--- /dev/null
@@ -0,0 +1,155 @@
+README.DOS
+
+Some notes about the supplied MSDOS executables and their compilers:
+
+A) The 32-bit DOS executables "zip.exe" and the auxilary utilities
+   "zipnote.exe", "zipsplit.exe", "zipcloak.exe" (crypt-enabled distribution
+   only) were compiled with DJGPP v 2.03, using gcc 3.4.3 as compiler.
+   They require a DPMI server to run, e.g.: a DOS command prompt window
+   under WINDOWS 3.x or Windows 9x.  To use this program under plain DOS,
+   you should install the free (GPL'ed) DPMI server CWSDPMI.EXE.  Look
+   for "csdpmi5b.zip" under "simtelnet/gnu/djgpp/v2misc/" on the SimTelNet
+   home site "ftp.cdrom.com" or any mirror site of the SimtelNet archive.
+
+   We have decided to provide 32-bit rather than 16-bit executables of
+   the auxilary tools for the following reasons:
+   - Nowadays, it has become quite unlikely to find PC computers "in action"
+     that do not at least have an i386 CPU.
+   - the 32-bit versions do not impose additional archive handling limits
+     beyond those defined by the Zip archive format
+   - the 32-bit DJGPP executables can handle long filenames on systems running
+     Windows 95/98/Me and Windows 2K/XP/2K3.
+
+B) There are two 16-bit MSDOS executables provided in zip2?x.zip:
+     zip16.exe     regular Zip program, requires ca. 455 KBytes of contiguous
+                   free DOS memory or more.
+     zip16-sm.exe  a variant that was compiled with the SMALL_MEM option
+                   for minimal memory consumption; requires at minimum
+                   322 KBytes of contiguous free DOS memory.
+
+   The SMALL_MEM variant requires much less space for the compression
+   buffers, but at the cost of some compression efficiency.
+   Therefore, we recommend to use the "SMALL_MEM" 16-bit "zip16-sm.exe" only
+   in case of "out of memory" problems (DOS memory is low and/or very large
+   number of archive entries), when the 32-bit program cannot be used for
+   some reason (286 or older; no DPMI server; ...).
+
+C) Hard limits of the Zip archive format:
+   Number of entries in Zip archive:            64 k (2^16 - 1 entries)
+   Compressed size of archive entry:            4 GByte (2^32 - 1 Bytes)
+   Uncompressed size of entry:                  4 GByte (2^32 - 1 Bytes)
+   Size of single-volume Zip archive:           4 GByte (2^32 - 1 Bytes)
+   Per-volume size of multi-volume archives:    4 GByte (2^32 - 1 Bytes)
+   Number of parts for multi-volume archives:   64 k (1^16 - 1 parts)
+   Total size of multi-volume archive:          256 TByte (4G * 64k)
+
+   The number of archive entries and of multivolume parts are limited by
+   the structure of the "end-of-central-directory" record, where the these
+   numbers are stored in 2-Byte fields.
+
+   Some Zip and/or UnZip implementations (for example Info-ZIP's) allow
+   handling of archives with more than 64k entries.  (The information
+   from "number of entries" field in the "end-of-central-directory" record
+   is not really neccessary to retrieve the contents of a Zip archive;
+   it should rather be used for consistency checks.) Also note that the
+   latest Info-ZIP versions (currently in beta) now support Zip64 which
+   extends all these limits, though these versions require file system
+   support of large files.  MSDOS stores file sizes in 32-bit numbers
+   internally. So, for MSDOS, the Zip64 features extending file sizes
+   beyond the 32-bit barrier are not applicable.  It is possible to
+   support Zip64 archives (for listing/testing, but not fully for
+   creation/extraction to disk) on MSDOS using splits, but currently
+   we are not planning on doing it.  The Zip64 extensions concerning
+   "more than 64k archive entries" may be supported on MSDOS (at least
+   up to the limit of 2^32 - 1 entries), unless we decide to drop support
+   for the MSDOS port completely.
+
+   Length of an archive entry name:             64 kByte (2^16 - 1)
+   Length of archive member comment:            64 kByte (2^16 - 1)
+   Total length of "extra field":               64 kByte (2^16 - 1)
+   Length of a single e.f. block:               64 kByte (2^16 - 1)
+   Length of archive comment:                   64 KByte (2^16 - 1)
+
+   Additional limitation claimed by PKWARE:
+     Size of local-header structure (fixed fields of 30 Bytes + filename
+      local extra field):                     < 64 kByte
+     Size of central-directory structure (46 Bytes + filename +
+      central extra field + member comment):  < 64 kByte
+
+D) Implementation limits of the Zip executables:
+
+ 1. Size limits caused by file I/O and compression handling:
+   Size of Zip archive:                 2 GByte (2^31 - 1 Bytes)
+   Compressed size of archive entry:    2 GByte (2^31 - 1 Bytes)
+   Uncompressed size of entry:          2 GByte (2^31 - 1 Bytes),
+                                        (could/should be 4 GBytes...)
+   Multi-volume archive creation is not supported.
+
+ 2. Limits caused by handling of archive contents lists
+
+ 2.1. Number of archive entries (freshen, update, delete)
+     a) 16-bit executable:              64k (2^16 -1) or 32k (2^15 - 1),
+                                        (unsigned vs. signed type of size_t)
+     a1) 16-bit executable:             <16k ((2^16)/4)
+         (The smaller limit a1) results from the array size limit of
+         the "qsort()" function.)
+         32-bit executables             <1G ((2^32)/4)
+         (usual system limit of the "qsort()" function on 32-bit systems)
+
+     b) stack space needed by qsort to sort list of archive entries
+
+     NOTE: In the current executables, overflows of limits a) and b) are NOT
+           checked!
+
+     c) amount of free memory to hold "central directory information" of
+        all archive entries; one entry needs:
+        96 bytes (32-bit) resp. 80 bytes (16-bit)
+        + 3 * length of entry name
+        + length of zip entry comment (when present)
+        + length of extra field(s) (when present, e.g.: UT needs 9 bytes)
+        + some bytes for book-keeping of memory allocation
+
+   Conclusion:
+     For systems with limited memory space (MSDOS, small AMIGAs, other
+     environments without virtual memory), the number of archive entries
+     is most often limited by condition c).  For example, with approx.
+     100 kBytes of free memory after loading and initializing the program,
+     a 16-bit DOS Zip cannot process more than 600 to 1000 (+) archive
+     entries.  (For the 16-bit Windows DLL or the 16-bit OS/2 port, limit
+     c) is less important because Windows or OS/2 executables are not
+     restricted to the 1024k area of real mode memory.  These 16-bit ports
+     are limited by conditions a1) and b), say: at maximum approx. 16000
+     entries!)
+
+     Note that the Win32 versions in general support greater limits than
+     the MSDOS versions.  If you are using zip from the command line in
+     Windows then you are usually better off using the Win32 versions.
+     Also, we are currently working on betas for UnZip 6.00 and Zip 3.0
+     that support Zip64 which extends these limits. However, the Zip64
+     features (with exception of the "more than 64k archive entries"
+     extension) may never be supported on MSDOS (or any DOS emulation)
+     because of its hard file size limit at 4 GByte.  It is possible
+     to support some of the Zip64 features in split archives but we are
+     currently not planning to do it.
+
+
+ 2.2. Number of "new" entries (add operation)
+     In addition to the restrictions above (2.1.), the following limits
+     caused by the handling of the "new files" list apply:
+
+     a) 16-bit executable:              <16k ((2^64)/4)
+
+     b) stack size required for "qsort" operation on "new entries" list.
+
+     NOTE: In the current executables, the overflow checks for these limits
+           are missing!
+
+     c) amount of free memory to hold the directory info list for new entries;
+        one entry needs:
+        24 bytes (32-bit) resp. 22 bytes (16-bit)
+        + 3 * length of filename
+
+
+Please report any problems at:  www.info-zip.org
+
+Last updated:  19 February 2005
diff --git a/msdos/crc_i86.asm b/msdos/crc_i86.asm
new file mode 100644 (file)
index 0000000..12e85ee
--- /dev/null
@@ -0,0 +1,464 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; Created by Christian Spieler, last modified 24 Dec 1998.
+;
+        TITLE   crc_i86.asm
+        NAME    crc_i86
+;
+; Optimized 8086 assembler version of the CRC32 calculation loop, intended
+; for real mode Info-ZIP programs (Zip 2.1, UnZip 5.2, and later versions).
+; Supported compilers are Microsoft C (DOS real mode) and Borland C(++)
+; (Turbo C). Watcom C (16bit) should also work.
+; This module was inspired by a similar module for the Amiga (Paul Kienitz).
+;
+; It replaces the `ulg crc32(ulg crc, ZCONST uch *buf, extent len)' function
+; in crc32.c.
+;
+; In March/April 1997, the code has been revised to incorporate Rodney Brown's
+; ideas for optimized access to the data buffer. For 8086 real mode code,
+; the data buffer is now accessed by aligned word-wide read operations.
+; This new optimization may be turned off by defining the macro switch
+; NO_16_BIT_LOADS.
+;
+; In December 1998, the loop branch commands were changed from "loop dest"
+; into "dec cx; jnz dest". On modern systems (486 and newer), the latter
+; code is usually much faster (e.g. 1 clock cycle compared to 5 for "loop"
+; on Pentium MMX). For the 286, the penalty of "dec cx; jnz" is one clock
+; cycle (12 vs. 11 cycles); on an 8088 the cycle counts are 22 (dec cx; jnz)
+; vs. 18 (loop). I decided to optimize for newer CPU models by default, because
+; I expect that old 80286 or 8088 dinosaurier machines may be rarely used
+; nowadays. In case you want optimum performance for these old CPU models
+; you should define the OPTIMIZE_286_88 macro switch on the assembler's
+; command line.
+; Likewise, "jcxz" was replaced by "jz", because the latter is faster on
+; 486 and newer CPUs (without any penalty on 80286 and older CPU models).
+;
+; The code in this module should work with all kinds of C memory models
+; (except Borland's __HUGE__ model), as long as the following
+; restrictions are not violated:
+;
+; - The implementation assumes that the char buffer is confined to a
+;   64k segment. The pointer `s' to the buffer must be in a format that
+;   all bytes can be accessed by manipulating the offset part, only.
+;   This means:
+;   + no huge pointers
+;   + char buffer size < 64 kByte
+;
+; - Since the buffer size argument `n' is of type `size_t' (= unsigned short)
+;   for this routine, the char buffer size is limited to less than 64 kByte,
+;   anyway. So, the assumption above should be easily fulfilled.
+;
+;==============================================================================
+;
+; Do NOT assemble this source if external crc32 routine from zlib gets used.
+;
+ifndef USE_ZLIB
+;
+; Setup of amount of assemble time informational messages:
+;
+ifdef     DEBUG
+  VERBOSE_INFO EQU 1
+else
+  ifdef _AS_MSG_
+    VERBOSE_INFO EQU 1
+  else
+    VERBOSE_INFO EQU 0
+  endif
+endif
+;
+; Selection of memory model, and initialization of memory model
+; related macros:
+;
+ifndef __SMALL__
+  ifndef __COMPACT__
+    ifndef __MEDIUM__
+      ifndef __LARGE__
+        ifndef __HUGE__
+;         __SMALL__ EQU 1
+        endif
+      endif
+    endif
+  endif
+endif
+
+ifdef __HUGE__
+; .MODEL Huge
+   @CodeSize  EQU 1
+   @DataSize  EQU 1
+   Save_DS    EQU 1
+   if VERBOSE_INFO
+    if1
+      %out Assembling for C, Huge memory model
+    endif
+   endif
+else
+   ifdef __LARGE__
+;      .MODEL Large
+      @CodeSize  EQU 1
+      @DataSize  EQU 1
+      if VERBOSE_INFO
+       if1
+         %out Assembling for C, Large memory model
+       endif
+      endif
+   else
+      ifdef __COMPACT__
+;         .MODEL Compact
+         @CodeSize  EQU 0
+         @DataSize  EQU 1
+         if VERBOSE_INFO
+          if1
+            %out Assembling for C, Compact memory model
+          endif
+         endif
+      else
+         ifdef __MEDIUM__
+;            .MODEL Medium
+            @CodeSize  EQU 1
+            @DataSize  EQU 0
+            if VERBOSE_INFO
+             if1
+               %out Assembling for C, Medium memory model
+             endif
+            endif
+         else
+;            .MODEL Small
+            @CodeSize  EQU 0
+            @DataSize  EQU 0
+            if VERBOSE_INFO
+             if1
+               %out Assembling for C, Small memory model
+             endif
+            endif
+         endif
+      endif
+   endif
+endif
+
+if @CodeSize
+        LCOD_OFS        EQU     2
+else
+        LCOD_OFS        EQU     0
+endif
+
+IF @DataSize
+        LDAT_OFS        EQU     2
+else
+        LDAT_OFS        EQU     0
+endif
+
+ifdef Save_DS
+;                       (di,si,ds)+(size, return address)
+        SAVE_REGS       EQU     6+(4+LCOD_OFS)
+else
+;                       (di,si)+(size, return address)
+        SAVE_REGS       EQU     4+(4+LCOD_OFS)
+endif
+
+;
+; Selection of the supported CPU instruction set and initialization
+; of CPU type related macros:
+;
+ifdef __586
+        Use_286_code    EQU     1
+        Align_Size      EQU     4       ; dword alignment on Pentium
+        Alig_PARA       EQU     1       ; paragraph aligned code segment
+else
+ifdef __486
+        Use_286_code     EQU    1
+        Align_Size       EQU    4       ; dword alignment on 32 bit processors
+        Alig_PARA        EQU    1       ; paragraph aligned code segment
+else
+ifdef __386
+        Use_286_code    EQU     1
+        Align_Size      EQU     4       ; dword alignment on 32 bit processors
+        Alig_PARA       EQU     1       ; paragraph aligned code segment
+else
+ifdef __286
+        Use_286_code    EQU     1
+        Align_Size      EQU     2       ; word alignment on 16 bit processors
+        Alig_PARA       EQU     0       ; word aligned code segment
+else
+ifdef __186
+        Use_186_code    EQU     1
+        Align_Size      EQU     2       ; word alignment on 16 bit processors
+        Alig_PARA       EQU     0       ; word aligned code segment
+else
+        Align_Size      EQU     2       ; word alignment on 16 bit processors
+        Alig_PARA       EQU     0       ; word aligned code segment
+endif   ;?__186
+endif   ;?__286
+endif   ;?__386
+endif   ;?__486
+endif   ;?__586
+
+ifdef Use_286_code
+        .286
+        Have_80x86      EQU     1
+else
+ifdef Use_186_code
+        .186
+        Have_80x86      EQU     1
+else
+        .8086
+        Have_80x86      EQU     0
+endif   ;?Use_186_code
+endif   ;?Use_286_code
+
+;
+; Declare the segments used in this module:
+;
+if @CodeSize
+if Alig_PARA
+CRC32_TEXT      SEGMENT  PARA PUBLIC 'CODE'
+else
+CRC32_TEXT      SEGMENT  WORD PUBLIC 'CODE'
+endif
+CRC32_TEXT      ENDS
+else    ;!@CodeSize
+if Alig_PARA
+_TEXT   SEGMENT  PARA PUBLIC 'CODE'
+else
+_TEXT   SEGMENT  WORD PUBLIC 'CODE'
+endif
+_TEXT   ENDS
+endif   ;?@CodeSize
+_DATA   SEGMENT  WORD PUBLIC 'DATA'
+_DATA   ENDS
+_BSS    SEGMENT  WORD PUBLIC 'BSS'
+_BSS    ENDS
+DGROUP  GROUP   _BSS, _DATA
+if @DataSize
+        ASSUME  DS: nothing, SS: DGROUP
+else
+        ASSUME  DS: DGROUP, SS: DGROUP
+endif
+
+if @CodeSize
+EXTRN   _get_crc_table:FAR
+else
+EXTRN   _get_crc_table:NEAR
+endif
+
+
+Do_CRC  MACRO
+        mov     bl,al
+        sub     bh,bh
+if Have_80x86
+        shl     bx,2
+else
+        shl     bx,1
+        shl     bx,1
+endif
+        mov     al,ah
+        mov     ah,dl
+        mov     dl,dh
+        sub     dh,dh
+        xor     ax,WORD PTR [bx][si]
+        xor     dx,WORD PTR [bx+2][si]
+        ENDM
+;
+Do_1    MACRO
+if @DataSize
+        xor     al,BYTE PTR es:[di]
+else
+        xor     al,BYTE PTR [di]
+endif
+        inc     di
+        Do_CRC
+        ENDM
+;
+Do_2    MACRO
+ifndef NO_16_BIT_LOADS
+if @DataSize
+        xor     ax,WORD PTR es:[di]
+else
+        xor     ax,WORD PTR [di]
+endif
+        add     di,2
+        Do_CRC
+        Do_CRC
+else
+        Do_1
+        Do_1
+endif
+        ENDM
+;
+Do_4    MACRO
+        Do_2
+        Do_2
+        ENDM
+;
+
+IF @CodeSize
+CRC32_TEXT      SEGMENT
+        ASSUME  CS: CRC32_TEXT
+else
+_TEXT   SEGMENT
+        ASSUME  CS: _TEXT
+endif
+; Line 37
+
+;
+;ulg crc32(ulg crc,
+;    ZCONST uch *buf,
+;    extend len)
+;
+        PUBLIC  _crc32
+if @CodeSize
+_crc32  PROC FAR
+else
+_crc32  PROC NEAR
+endif
+if Have_80x86
+        enter   WORD PTR 0,0
+else
+        push    bp
+        mov     bp,sp
+endif
+        push    di
+        push    si
+if @DataSize
+;       crc = 4+LCOD_OFS        DWORD (unsigned long)
+;       buf = 8+LCOD_OFS        DWORD PTR BYTE (uch *)
+;       len = 12+LCOD_OFS       WORD (unsigned int)
+else
+;       crc = 4+LCOD_OFS        DWORD (unsigned long)
+;       buf = 8+LCOD_OFS        WORD PTR BYTE (uch *)
+;       len = 10+LCOD_OFS       WORD (unsigned int)
+endif
+;
+if @DataSize
+        mov     ax,WORD PTR [bp+8+LCOD_OFS]     ; buf
+        or      ax,WORD PTR [bp+10+LCOD_OFS]    ;     == NULL ?
+else
+        cmp     WORD PTR [bp+8+LCOD_OFS],0      ; buf == NULL ?
+endif
+        jne     crc_update
+        sub     ax,ax                           ; crc = 0
+        cwd
+ifndef NO_UNROLLED_LOOPS
+        jmp     fine
+else
+        jmp     SHORT fine
+endif
+;
+crc_update:
+        call     _get_crc_table
+;  When used with compilers that conform to the Microsoft/Borland standard
+;  C calling convention, model-dependent handling is not needed, because
+;   _get_crc_table returns NEAR pointer.
+;  But Watcom C is different and does not allow one to assume DS pointing to
+;  DGROUP. So, we load DS with DGROUP, to be safe.
+;if @DataSize
+;       push    ds
+;       mov     ds,dx
+;       ASSUME  DS: nothing
+;endif
+        mov     si,ax                           ;crc_table
+if @DataSize
+        push    ds
+        mov     ax,SEG DGROUP
+        mov     ds,ax
+        ASSUME  DS: DGROUP
+endif
+;
+        mov     ax,WORD PTR [bp+4+LCOD_OFS]     ;crc
+        mov     dx,WORD PTR [bp+6+LCOD_OFS]
+        not     ax
+        not     dx
+if @DataSize
+        les     di,DWORD PTR [bp+8+LCOD_OFS]    ;buf
+        mov     cx,WORD PTR [bp+12+LCOD_OFS]    ;len
+else
+        mov     di,WORD PTR [bp+8+LCOD_OFS]     ;buf
+        mov     cx,WORD PTR [bp+10+LCOD_OFS]    ;len
+endif
+;
+ifndef NO_UNROLLED_LOOPS
+ifndef NO_16_BIT_LOADS
+        test    cx,cx
+        jnz     start
+        jmp     done
+start:  test    di,1
+        jz      is_wordaligned
+        dec     cx
+        Do_1
+        mov     WORD PTR [bp+10+LDAT_OFS+LCOD_OFS],cx
+is_wordaligned:
+endif ; !NO_16_BIT_LOADS
+if Have_80x86
+        shr     cx,2
+else
+        shr     cx,1
+        shr     cx,1
+endif
+        jz      No_Fours
+;
+        align   Align_Size              ; align destination of branch
+Next_Four:
+        Do_4
+ifndef OPTIMIZE_286_88
+        dec     cx                      ; on 286, "loop Next_Four" needs 11
+        jnz     Next_Four               ;  clocks, one less than this code
+else
+        loop    Next_Four
+endif
+;
+No_Fours:
+if @DataSize
+        mov     cx,WORD PTR [bp+12+LCOD_OFS]    ;len
+else
+        mov     cx,WORD PTR [bp+10+LCOD_OFS]    ;len
+endif
+        and     cx,00003H
+endif ; !NO_UNROLLED_LOOPS
+        jz      done
+;
+        align   Align_Size              ; align destination of branch
+Next_Byte:
+        Do_1
+ifndef OPTIMIZE_286_88
+        dec     cx                      ; on 286, "loop Next_Four" needs 11
+        jnz     Next_Byte               ;  clocks, one less than this code
+else
+        loop    Next_Four
+endif
+;
+done:
+if @DataSize
+        pop     ds
+;       ASSUME  DS: DGROUP
+        ASSUME  DS: nothing
+endif
+        not     ax
+        not     dx
+;
+fine:
+        pop     si
+        pop     di
+if Have_80x86
+        leave
+else
+        mov     sp,bp
+        pop     bp
+endif
+        ret
+
+_crc32  ENDP
+
+if @CodeSize
+CRC32_TEXT      ENDS
+else
+_TEXT   ENDS
+endif
+;
+endif ;!USE_ZLIB
+;
+END
diff --git a/msdos/makefile.bor b/msdos/makefile.bor
new file mode 100644 (file)
index 0000000..0190ba0
--- /dev/null
@@ -0,0 +1,196 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for
+# Borland (Turbo) C++ 1.0 or 2.0.
+# Warning: this file is not suitable for Turbo C 2.0. Use makefile.tc instead.
+
+# To use, do "make -fmakefile.bor"
+
+# WARNING: the small model is not supported.
+# Add -DSMALL_MEM or -DMEDIUM_MEM to the LOC macro if you wish to reduce
+# the memory requirements.
+# Add -DNO_ASM to CFLAGS and comment out the ASMOBJS definition if
+# you do not have tasm.
+
+# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)
+# should be added to the environment via "set LOCAL_ZIP=-DFOO" or added
+# to the declaration of LOC here:
+LOC = -DDOS -DNO_SECURE_TESTS $(LOCAL_ZIP)
+
+# Zip requires compact or large memory model.
+# with 2.1, compact model exceeds 64k code segment; use large model
+ZIPMODEL=l     # large model for Zip and ZipUtils
+
+# name of Flag to select memory model for assembler compiles, supported
+# values are __SMALL__ , __MEDIUM__ , __COMPACT__ , __LARGE__ :
+ASMODEL=__LARGE__              # keep in sync with ZIPMODEL definition !!
+
+# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.
+CPU_TYP = 0
+
+# Uncomment the following macro to use the optimized assembler
+# routines in Zip:
+ASMOBJS = match.obj crc_i86.obj
+
+ASCPUFLAG = __$(CPU_TYP)86
+!if $(CPU_TYP) != 0
+CC_CPUFLG = -$(CPU_TYP)
+!endif
+
+VPATH=.;msdos
+# ------------- Turbo C++, Borland C++ -------------
+!if $(CC_REV) == 1
+CC = tcc
+!else
+! if !$(CC_REV)
+CC_REV = 3
+! endif
+CC = bcc
+!endif
+
+MODEL=-m$(ZIPMODEL)
+!if $(CC_REV) == 1
+CFLAGS=-w -w-eff -w-def -w-sig -w-cln -a -d -G -O -Z $(CC_CPUFLG) $(MODEL) $(LOC)
+!else
+CFLAGS=-w -w-cln -O2 -Z $(CC_CPUFLG) $(MODEL) $(LOC)
+!endif
+UTILFLAGS=-DUTIL $(CFLAGS) -o
+# for Turbo C++ 1.0, replace bcc with tcc and use the upper version of CFLAGS
+
+AS=tasm
+ASFLAGS=-ml -t -m2 -DDYN_ALLOC -DSS_NEQ_DS -D$(ASCPUFLAG) -D$(ASMODEL) $(LOC)
+
+LD=$(CC)
+LDFLAGS=$(MODEL)
+
+# ------------- Common declarations:
+STRIP=@rem
+#    If you don't have UPX, LZEXE, or PKLITE, get one of them. Then define:
+#    (NOTE: upx needs a 386 or higher system to run the exe compressor)
+#STRIP=upx --8086 --best
+#    or
+#STRIP=lzexe
+#    or (if you've registered PKLITE)
+#STRIP=pklite
+#    This makes a big difference in .exe size (and possibly load time)
+
+# ------------- Used by install rule
+# set BIN to the directory you want to install the executables to
+BIN = c:\util
+
+# variables
+OBJZ = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \
+       crc32.obj crctab.obj globals.obj
+
+OBJI = deflate.obj trees.obj $(ASMOBJS) msdos.obj
+
+OBJU = zipfile_.obj fileio_.obj util_.obj globals.obj msdos_.obj
+OBJN = zipnote.obj $(OBJU)
+OBJC = zipcloak.obj crctab.obj crypt_.obj ttyio.obj $(OBJU)
+OBJS = zipsplit.obj $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h msdos/osdep.h
+
+ZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zips:  $(ZIPS)
+
+zip.obj:       zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipfile.obj:   zipfile.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+zipup.obj:     zipup.c $(ZIP_H) revision.h crypt.h msdos/zipup.h
+       $(CC) -c $(CFLAGS) $*.c
+
+fileio.obj:    fileio.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+util.obj:      util.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+globals.obj:   globals.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+deflate.obj:   deflate.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+trees.obj:     trees.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crc32.obj:     crc32.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crctab.obj:    crctab.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crypt.obj:     crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+ttyio.obj:     ttyio.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+msdos.obj:     msdos/msdos.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) msdos/$*.c
+
+zipcloak.obj:  zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipnote.obj:   zipnote.c $(ZIP_H) revision.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipsplit.obj:  zipsplit.c $(ZIP_H) revision.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipfile_.obj:  zipfile.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS)$* zipfile.c
+
+fileio_.obj:   fileio.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS)$* fileio.c
+
+util_.obj:     util.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS)$* util.c
+
+crypt_.obj:    crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(UTILFLAGS)$* crypt.c
+
+msdos_.obj:    msdos/msdos.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS)$* msdos/msdos.c
+
+crc_i86.obj:   msdos/crc_i86.asm
+       $(AS) $(ASFLAGS) msdos\crc_i86.asm ;
+
+match.obj:     msdos/match.asm
+       $(AS) $(ASFLAGS) msdos\match.asm ;
+
+# we must cut the command line to fit in the MS/DOS 128 byte limit:
+zip.exe: $(OBJZ) $(OBJI)
+       echo $(OBJZ) > zip.rsp
+       echo $(OBJI) >> zip.rsp
+       $(LD) $(LDFLAGS) @zip.rsp
+       del zip.rsp
+       $(STRIP) zip.exe
+
+zipcloak.exe: $(OBJC)
+       echo $(OBJC) > zipc.rsp
+       $(LD) $(LDFLAGS) @zipc.rsp
+       del zipc.rsp
+       $(STRIP) zipcloak.exe
+
+zipnote.exe: $(OBJN)
+       echo $(OBJN) > zipn.rsp
+       $(LD) $(LDFLAGS) @zipn.rsp
+       del zipn.rsp
+       $(STRIP) zipnote.exe
+
+zipsplit.exe: $(OBJS)
+       echo $(OBJS) > zips.rsp
+       $(LD) $(LDFLAGS) @zips.rsp
+       del zips.rsp
+       $(STRIP) zipsplit.exe
+
+install:       $(ZIPS)
+       copy /b *.exe $(BIN)
+
+clean:
+       del *.obj
+       del *.exe
diff --git a/msdos/makefile.dj1 b/msdos/makefile.dj1
new file mode 100644 (file)
index 0000000..b513359
--- /dev/null
@@ -0,0 +1,125 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for
+# djgpp 1.x
+VPATH=.;msdos
+# ------------- djgpp -------------
+CPPFLAGS=-I. -DDOS -DASM_CRC $(LOCAL_ZIP)
+ASFLAGS=$(CPPFLAGS)
+CFLAGS=-Wall -O2 -m486 $(CPPFLAGS)
+UTILFLAGS=-c -DUTIL $(CFLAGS) -o
+CC=gcc
+LD=gcc
+LDFLAGS=-s
+
+STRIP=strip
+
+# Change the STUBIFY definition to the upper version if you want to create
+# executables which can be used without any external extender file.
+# >>> NOTE: Either copy the go32 extender into your build directory, or
+# >>>       edit the STUBIFY macro and add the correct path to "go32.exe".
+#STUBIFY=coff2exe -s go32.exe
+STUBIFY=coff2exe
+
+# variables
+
+#set CRC32 to crc_gcc.o or crc32.o, depending on whether ASM_CRC is defined:
+CRC32 = crc_gcc.o
+
+OBJZ = zip.o crypt.o ttyio.o zipfile.o zipup.o fileio.o util.o \
+       $(CRC32) crctab.o globals.o
+OBJI = deflate.o trees.o match.o msdos.o
+OBJU = zipfile_.o fileio_.o util_.o globals.o msdos_.o
+OBJN = zipnote.o $(OBJU)
+OBJC = zipcloak.o crctab.o crypt_.o ttyio.o $(OBJU)
+OBJS = zipsplit.o $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h msdos/osdep.h
+
+# rules
+
+.SUFFIXES:    # Delete make's default suffix list
+.SUFFIXES:    .exe .out .a .ln .o .c .cc .C .p .f .F .y .l .s .S .h
+
+.c.o:
+       $(CC) -c $(CFLAGS) $< -o $@
+
+zips:  zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zip.o:       zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+
+zipfile.o:    zipfile.c $(ZIP_H)
+
+zipup.o:      zipup.c $(ZIP_H) revision.h crypt.h msdos/zipup.h
+
+fileio.o:     fileio.c $(ZIP_H)
+
+util.o:       util.c $(ZIP_H)
+
+globals.o:    globals.c $(ZIP_H)
+
+deflate.o:    deflate.c $(ZIP_H)
+
+trees.o:      trees.c $(ZIP_H)
+
+crc_gcc.o:    crc_i386.S
+       $(CC) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S
+
+crc32.o:      crc32.c $(ZIP_H)
+
+crctab.o:     crctab.c $(ZIP_H)
+
+crypt.o:      crypt.c $(ZIP_H) crypt.h ttyio.h
+
+ttyio.o:      ttyio.c $(ZIP_H) crypt.h ttyio.h
+
+msdos.o:      msdos/msdos.c $(ZIP_H)
+
+zipcloak.o:   zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+
+zipnote.o:    zipnote.c $(ZIP_H) revision.h
+
+zipsplit.o:   zipsplit.c $(ZIP_H) revision.h
+
+zipfile_.o:   zipfile.c $(ZIP_H)
+       $(CC) $(UTILFLAGS) $@ zipfile.c
+
+fileio_.o:    fileio.c $(ZIP_H)
+       $(CC) $(UTILFLAGS) $@ fileio.c
+
+util_.o:      util.c $(ZIP_H)
+       $(CC) $(UTILFLAGS) $@ util.c
+
+crypt_.o:     crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) $(UTILFLAGS) $@ crypt.c
+
+msdos_.o:     msdos/msdos.c $(ZIP_H)
+       $(CC) $(UTILFLAGS) $@ msdos/msdos.c
+
+match.o:      match.S
+       $(CC) $(ASFLAGS) -x assembler-with-cpp -c -o $@ match.S
+
+zip.exe: $(OBJZ) $(OBJI)
+       echo $(OBJZ) > zip.rsp
+       echo $(OBJI) >> zip.rsp
+       $(LD) $(LDFLAGS) -o zip @zip.rsp
+       del zip.rsp
+       $(STRIP) zip
+       $(STUBIFY) zip
+       del zip
+
+zipcloak.exe: $(OBJC)
+       $(LD) $(LDFLAGS) $(OBJC) -o zipcloak
+       $(STRIP) zipcloak
+       $(STUBIFY) zipcloak
+       del zipcloak
+
+zipnote.exe: $(OBJN)
+       $(LD) $(LDFLAGS) $(OBJN) -o zipnote
+       $(STRIP) zipnote
+       $(STUBIFY) zipnote
+       del zipnote
+
+zipsplit.exe: $(OBJS)
+       $(LD) $(LDFLAGS) $(OBJS) -o zipsplit
+       $(STRIP) zipsplit
+       $(STUBIFY) zipsplit
+       del zipsplit
diff --git a/msdos/makefile.dj2 b/msdos/makefile.dj2
new file mode 100644 (file)
index 0000000..3ea98ae
--- /dev/null
@@ -0,0 +1,135 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for
+# djgpp 2.x
+VPATH=.;msdos
+# ------------- djgpp -------------
+CPPFLAGS=-I. -DDOS -DASM_CRC $(LOCAL_ZIP)
+ASFLAGS=$(CPPFLAGS)
+CFLAGS=-Wall -O2 $(CPPFLAGS)
+UTILFLAGS=-c -DUTIL $(CFLAGS) -o
+CC=gcc
+LD=gcc
+LDFLAGS=-s
+
+# ------------- file packer --------
+# Laszlo Molnar who wrote DJ Packer and Markus F. X. J. Oberhumer who wrote
+# the compression library used by the DJ Packer have collaborated on the
+# Ultimate Packer for eXecutables, which has recently been released.  Look
+# for upx???d.zip at     http://upx.sourceforge.net
+# As an alternative, look for "djp.exe", now two years old, in the archive
+# mlp107[b,s].zip, found in the same location as csdpmi?[b,s].zip (see below).
+# If you have got an executable packer in your PATH, you may reduce the
+# size of the disk image of the zip*.exe's by uncommenting the lines
+# containing $(DJP) below where the exe's are built.
+#DJP=djp -q
+DJP=upx -qq --best
+
+# variables
+
+#set CRC32 to crc_gcc.o or crc32.o, depending on whether ASM_CRC is defined:
+CRC32 = crc_gcc.o
+
+OBJZ = zip.o crypt.o ttyio.o zipfile.o zipup.o fileio.o util.o \
+       $(CRC32) crctab.o globals.o
+OBJI = deflate.o trees.o match.o msdos.o
+OBJU = zipfile_.o fileio_.o util_.o globals.o msdos_.o
+OBJN = zipnote.o $(OBJU)
+OBJC = zipcloak.o crctab.o crypt_.o ttyio.o $(OBJU)
+OBJS = zipsplit.o $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h msdos/osdep.h
+
+# rules
+
+.SUFFIXES:    # Delete make's default suffix list
+.SUFFIXES:    .exe .out .a .ln .o .c .cc .C .p .f .F .y .l .s .S .h
+
+.c.o:
+       $(CC) -c $(CFLAGS) $< -o $@
+
+zips:  zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zip.o:       zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+
+zipfile.o:    zipfile.c $(ZIP_H)
+
+zipup.o:      zipup.c $(ZIP_H) revision.h crypt.h msdos/zipup.h
+
+fileio.o:     fileio.c $(ZIP_H)
+
+util.o:       util.c $(ZIP_H)
+
+globals.o:    globals.c $(ZIP_H)
+
+deflate.o:    deflate.c $(ZIP_H)
+
+trees.o:      trees.c $(ZIP_H)
+
+crc_gcc.o:    crc_i386.S
+       $(CC) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S
+
+crc32.o:      crc32.c $(ZIP_H)
+
+crctab.o:     crctab.c $(ZIP_H)
+
+crypt.o:      crypt.c $(ZIP_H) crypt.h ttyio.h
+
+ttyio.o:      ttyio.c $(ZIP_H) crypt.h ttyio.h
+
+msdos.o:      msdos/msdos.c $(ZIP_H)
+
+zipcloak.o:   zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+
+zipnote.o:    zipnote.c $(ZIP_H) revision.h
+
+zipsplit.o:   zipsplit.c $(ZIP_H) revision.h
+
+zipfile_.o:   zipfile.c $(ZIP_H)
+       $(CC) $(UTILFLAGS) $@ zipfile.c
+
+fileio_.o:    fileio.c $(ZIP_H)
+       $(CC) $(UTILFLAGS) $@ fileio.c
+
+util_.o:      util.c $(ZIP_H)
+       $(CC) $(UTILFLAGS) $@ util.c
+
+crypt_.o:     crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) $(UTILFLAGS) $@ crypt.c
+
+msdos_.o:     msdos/msdos.c $(ZIP_H)
+       $(CC) $(UTILFLAGS) $@ msdos/msdos.c
+
+
+match.o:      match.S
+       $(CC) $(ASFLAGS) -x assembler-with-cpp -c -o $@ match.S
+
+zip.exe: $(OBJZ) $(OBJI)
+       echo $(OBJZ) > zip.rsp
+       echo $(OBJI) >> zip.rsp
+       $(LD) $(LDFLAGS) -o $@ @zip.rsp
+       del zip.rsp
+#      stubedit $@ dpmi=cwsdpmi.exe
+#      $(DJP) $@
+
+zipcloak.exe: $(OBJC)
+       $(LD) $(LDFLAGS) $(OBJC) -o $@
+#      stubedit $@ dpmi=cwsdpmi.exe
+#      $(DJP) $@
+
+zipnote.exe: $(OBJN)
+       $(LD) $(LDFLAGS) $(OBJN) -o $@
+#      stubedit $@ dpmi=cwsdpmi.exe
+#      $(DJP) $@
+
+zipsplit.exe: $(OBJS)
+       $(LD) $(LDFLAGS) $(OBJS) -o $@
+#      stubedit $@ dpmi=cwsdpmi.exe
+#      $(DJP) $@
+
+# These stand alone executables require dpmi services to run.  When
+# running in a DOS window under windows 3.1 or later, the dpmi server
+# is automatically present.  Under DOS, if a dpmi server is not installed,
+# by default the program will look for "cwsdpmi.exe." If found, it will
+# be loaded for the duration of the program.
+# cwsdpmi is a "free" dpmi server written by Charles W. Sandmann
+# (sandman@clio.rice.edu).  It may be found, among other sites, on SimTel
+# and its mirrors in the .../vendors/djgpp/v2misc directory.
diff --git a/msdos/makefile.emx b/msdos/makefile.emx
new file mode 100644 (file)
index 0000000..f66b31c
--- /dev/null
@@ -0,0 +1,167 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit
+# using emx 0.9c for DOS.
+# By Kai-Uwe Rommel, Chr. Spieler, E-Yen Tan (and others).
+# Last updated 30th June 1998.
+#
+# This Makefile is a stripped down version of win32/Makefile.emx that
+# builds executables applying the default MSDOS emx setup.  For variant
+# targets (using zlib), and cross-compilation for WIN32 or OS/2, take a
+# look into "win32/makefile.emx" resp. "os2/makefile.os2".
+#
+# Supported Make utilities:
+# - Microsoft/IBM nmake (e.g. from MSC 6.0 or newer)
+# - dmake 3.8 or higher
+# - GNU make, at least version 3.68 (GNUish 16-bit port, RSXNT Make 3.75 in a
+#   Win95/WinNT DOS box, DJGPP v1.12 Make 3.71, some versions of DJGPP v2.x
+#   32-bit Make; current DJGPP v2.01 Make 3.76.1 does NOT work)
+# - NOT watcom make
+# The "smart" Make utilities mentioned below are Christian Spieler's
+# enhanced version of GNUish 16-bit Make (3.74) and his adaption of these
+# GNU Make sources to EMX (32-bit).
+
+# Supported 32-bit C Compilers for MSDOS:
+# - GNU gcc (emx kit 0.9c or newer, 32-bit)
+
+# Supported Assemblers:
+# - GNU as with GNU gcc
+
+
+# To use, enter "make/nmake/dmake -f msdos/makefile.emx"
+# (this makefile depends on its name being "msdos/makefile.emx").
+
+# emx 0.9c, gcc, a.out format, for MS-DOS
+CC=gcc -O2 -m486 -Wall
+CFLAGS=-DDOS -DMSDOS -DASM_CRC
+AS=gcc
+ASFLAGS=-Di386
+LDFLAGS=-o ./
+LDFLAGS2=-s -Zsmall-conv
+OUT=-o
+OBJ=.o
+CRC32=crc_gcc
+OBJA=matchgcc.o
+OBJZS=msdos.o
+OBJUS=msdos_.o
+OSDEP_H=msdos/osdep.h
+ZIPUP_H=msdos/zipup.h
+
+#default settings for target dependent macros:
+DIRSEP = /
+AS_DIRSEP = /
+RM = del
+LOCAL_OPTS = $(LOCAL_ZIP)
+CCFLAGS = $(CFLAGS) $(LOCAL_OPTS)
+
+
+OBJZ1 = zip$(OBJ) zipfile$(OBJ) zipup$(OBJ) fileio$(OBJ) util$(OBJ) \
+       $(CRC32)$(OBJ) crctab$(OBJ)
+OBJZ2 = globals$(OBJ) deflate$(OBJ) trees$(OBJ) crypt$(OBJ) \
+       ttyio$(OBJ)
+OBJZ  = $(OBJZ1) $(OBJZ2) $(OBJZS) $(OBJA)
+
+OBJU1 = zipfile_$(OBJ) fileio_$(OBJ) util_$(OBJ) globals$(OBJ)
+OBJU  = $(OBJU1) $(OBJUS)
+
+OBJN  = zipnote$(OBJ) $(OBJU)
+OBJS  = zipsplit$(OBJ) $(OBJU)
+OBJC1 = zipcloak$(OBJ) crctab$(OBJ) crypt_$(OBJ) ttyio$(OBJ)
+OBJC  = $(OBJC1) $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h $(OSDEP_H)
+
+# rules
+
+.SUFFIXES: .c $(OBJ)
+
+.c$(OBJ):
+       $(CC) -c -I. $(CCFLAGS) $(OUT)$@ $<
+
+# targets
+
+all:    zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zip$(OBJ):      zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipfile$(OBJ):  zipfile.c $(ZIP_H)
+zipup$(OBJ):    zipup.c $(ZIP_H) revision.h crypt.h $(ZIPUP_H)
+fileio$(OBJ):   fileio.c $(ZIP_H)
+util$(OBJ):     util.c $(ZIP_H)
+globals$(OBJ):  globals.c $(ZIP_H)
+deflate$(OBJ):  deflate.c $(ZIP_H)
+trees$(OBJ):    trees.c $(ZIP_H)
+crc32$(OBJ):    crc32.c $(ZIP_H)
+crctab$(OBJ):   crctab.c $(ZIP_H)
+crypt$(OBJ):    crypt.c $(ZIP_H) crypt.h ttyio.h
+ttyio$(OBJ):    ttyio.c $(ZIP_H) crypt.h ttyio.h
+
+msdos$(OBJ):    msdos/msdos.c $(ZIP_H)
+       $(CC) -c -I. $(CCFLAGS) msdos$(DIRSEP)msdos.c
+
+win32zip$(OBJ): win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h
+       $(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)win32zip.c
+
+win32$(OBJ):    win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)win32.c
+
+nt$(OBJ):       win32/nt.c $(ZIP_H) win32/nt.h
+       $(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)nt.c
+
+crc_gcc$(OBJ):  crc_i386.S                                      # 32bit, GNU AS
+       $(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S
+
+matchgcc$(OBJ): match.S
+       $(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ match.S
+
+zipcloak$(OBJ): zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipnote$(OBJ):  zipnote.c $(ZIP_H) revision.h
+zipsplit$(OBJ): zipsplit.c $(ZIP_H) revision.h
+
+zipfile_$(OBJ): zipfile.c $(ZIP_H)
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ zipfile.c
+
+fileio_$(OBJ):  fileio.c $(ZIP_H)
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ fileio.c
+
+util_$(OBJ):    util.c $(ZIP_H)
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ util.c
+
+crypt_$(OBJ):   crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ crypt.c
+
+msdos_$(OBJ):   msdos/msdos.c $(ZIP_H)
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ msdos$(DIRSEP)msdos.c
+
+win32_$(OBJ):   win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ win32$(DIRSEP)win32.c
+
+# This next bit is nasty, but is needed to overcome the MS-DOS command
+# line limit as response files for emx's gcc seem to only work if each
+# file is on a different line. DJGPP doesn't do this (if you are at all
+# interested).
+
+zip.exe: $(OBJZ)
+# for DUMB make utilities, uncomment the following commands:
+       -@$(RM) zip.rsp
+       @for %%f in ($(OBJZ1)) do echo %%f >> zip.rsp
+       @for %%f in ($(OBJZ2)) do echo %%f >> zip.rsp
+       @for %%f in ($(OBJZS) $(OBJA)) do echo %%f >> zip.rsp
+       $(CC) $(LDFLAGS)$@ @zip.rsp $(LDFLAGS2)
+       @$(RM) zip.rsp
+# smart make utilities (like well done ports of GNU Make) can use this:
+#      $(CC) $(LDFLAGS)$@ $(OBJZ) $(LDFLAGS2)
+
+zipcloak.exe: $(OBJC)
+# for DUMB make utilities, uncomment the following commands:
+       -@$(RM) zipcloak.rsp
+       @for %%f in ($(OBJC1)) do echo %%f >> zipcloak.rsp
+       @for %%f in ($(OBJU1)) do echo %%f >> zipcloak.rsp
+       @for %%f in ($(OBJUS)) do echo %%f >> zipcloak.rsp
+       $(CC) $(LDFLAGS)$@ @zipcloak.rsp $(LDFLAGS2)
+       @$(RM) zipcloak.rsp
+# smart make utilities (like well done ports of GNU Make) can use this:
+#      $(CC) $(LDFLAGS)$@ $(OBJC) $(LDFLAGS2)
+
+zipnote.exe: $(OBJN)
+       $(CC) $(LDFLAGS)$@ $(OBJN) $(LDFLAGS2)
+
+zipsplit.exe: $(OBJS)
+       $(CC) $(LDFLAGS)$@ $(OBJS) $(LDFLAGS2)
diff --git a/msdos/makefile.msc b/msdos/makefile.msc
new file mode 100644 (file)
index 0000000..89f0d42
--- /dev/null
@@ -0,0 +1,205 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for
+# Microsoft C 5.1 and above.
+
+# To use, do "make makefile.msc"
+
+# Add -DSMALL_MEM or -DMEDIUM_MEM to the LOC macro if you wish to reduce
+# the memory requirements.
+# Add -DNO_ASM to CFLAGS and comment out the ASMOBJS definition if
+# you do not have masm.
+#
+# If you want link Zip against zlib to replace the built-in deflate routines,
+# the following changes are required:
+# - in the definition of "LOC", add "-DUSE_ZLIB" and remove "-DNO_SECURE_TESTS"
+# - comment out the "ASMOBJS" symbol definition
+# - modify the linking command blocks for zip and zipcloak according to
+#   the following scheme:
+#   add a command line "echo ,,,zlib_$(ZIPMODEL); >> zip[c].rsp" just
+#   before the "$(LD)..." line; and remove the semicolon character from the
+#   "echo ..." line immediately preceding the just inserted command
+
+
+# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)
+# should be added to the environment via "set LOCAL_ZIP=-DFOO" or added
+# to the declaration of LOC here:
+LOC = -DDOS -DDYN_ALLOC -DNO_SECURE_TESTS $(LOCAL_ZIP)
+
+# Zip requires compact or large memory model.
+# with 2.1, compact model exceeds 64k code segment; use large model
+ZIPMODEL=L     # large model for Zip and ZipUtils
+
+# name of Flag to select memory model for assembler compiles, supported
+# values are __SMALL__ , __MEDIUM__ , __COMPACT__ , __LARGE__ :
+ASMODEL=__LARGE__              # keep in sync with ZIPMODEL definition !!
+
+# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.
+CPU_TYP = 0
+
+# Uncomment the following macro to use the optimized assembler
+# routines in Zip:
+ASMOBJS = match.obj crc_i86.obj
+
+ASCPUFLAG = __$(CPU_TYP)86
+
+# ------------- Microsoft C 5.1, 6.0, 7.0 and VC++ Pro 1.0 -------------
+CC=cl
+MODEL=-A$(ZIPMODEL)
+FP=
+COMMON_CFLAGS=-nologo -I. $(MODEL) $(FP) -DMSC $(LOC) -W3 -G$(CPU_TYP)
+CFLAGS=$(COMMON_CFLAGS) -Ox
+SPECFLAGS=$(COMMON_CFLAGS) -Oaict -Gs
+# For MSC/C++ 7.0 and VC++ no special flags are needed:
+# SPECFLAGS=$(CFLAGS)
+UTILFLAGS=-DUTIL $(CFLAGS) -Fo
+
+AS=masm
+ASFLAGS=-ml -t -D$(ASCPUFLAG) -D$(ASMODEL) $(LOC)
+#     For MSC 6.0, use:
+#AS=ml
+#ASFLAGS=-c -D$(ASCPUFLAG) -D$(ASMODEL) $(LOC)
+# Supress -DDYN_ALLOC in ASFLAGS if you have suppressed it in CFLAGS
+
+LD=link
+LDFLAGS=/noi/farcall/packcode/e/st:0x1000/m
+#     If you use an exe packer as recommended below, remove /e from LDFLAGS
+
+# ------------- Common declarations:
+STRIP=rem
+#    If you don't have UPX, LZEXE, or PKLITE, get one of them. Then define:
+#    (NOTE: upx needs a 386 or higher system to run the exe compressor)
+#STRIP=upx --8086 --best
+#    or
+#STRIP=lzexe
+#    or (if you've registered PKLITE)
+#STRIP=pklite
+#    and remove /e from LDFLAGS.
+#    This makes a big difference in .exe size (and possibly load time)
+
+# ------------- Used by install rule
+# set BIN to the directory you want to install the executables to
+BIN = c:\util
+
+# variables
+OBJZ = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \
+       crc32.obj crctab.obj globals.obj
+
+OBJI = deflate.obj trees.obj $(ASMOBJS) msdos.obj
+
+OBJU = zipfile_.obj fileio_.obj util_.obj globals.obj msdos_.obj
+OBJN = zipnote.obj $(OBJU)
+OBJC = zipcloak.obj crctab.obj crypt_.obj ttyio.obj $(OBJU)
+OBJS = zipsplit.obj $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h msdos/osdep.h
+
+ZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zips:  $(ZIPS)
+
+zip.obj:       zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+# MSC 5.1 generates bad code on zipfile with -Ox
+zipfile.obj:   zipfile.c $(ZIP_H)
+       $(CC) -c $(SPECFLAGS) $*.c
+
+zipup.obj:     zipup.c $(ZIP_H) revision.h crypt.h msdos/zipup.h
+       $(CC) -c $(CFLAGS) $*.c
+
+fileio.obj:    fileio.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+util.obj:      util.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+globals.obj:   globals.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+deflate.obj:   deflate.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+trees.obj:     trees.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crc32.obj:     crc32.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crctab.obj:    crctab.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crypt.obj:     crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+ttyio.obj:     ttyio.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+msdos.obj:     msdos/msdos.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) msdos/$*.c
+
+zipcloak.obj:  zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipnote.obj:   zipnote.c $(ZIP_H) revision.h
+       $(CC) -c $(CFLAGS) $*.c
+
+# MSC 5.1 dies on zipsplit with -Ox
+zipsplit.obj:  zipsplit.c $(ZIP_H) revision.h
+       $(CC) -c $(SPECFLAGS) $*.c
+
+# MSC 5.1 generates bad code on zipfile with -Ox
+zipfile_.obj:  zipfile.c $(ZIP_H)
+       $(CC) -c $(SPECFLAGS) -DUTIL -Fo$@ zipfile.c
+
+fileio_.obj:   fileio.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS)$@ fileio.c
+
+util_.obj:     util.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS)$@ util.c
+
+crypt_.obj:    crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(UTILFLAGS)$@ crypt.c
+
+msdos_.obj:    msdos/msdos.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS)$@ msdos/msdos.c
+
+crc_i86.obj:   msdos/crc_i86.asm
+       $(AS) $(ASFLAGS) msdos\crc_i86.asm ;
+
+match.obj:     msdos/match.asm
+       $(AS) $(ASFLAGS) msdos\match.asm ;
+
+# we must cut the command line to fit in the MS/DOS 128 byte limit:
+zip.exe: $(OBJZ) $(OBJI)
+       echo $(OBJZ)+ > zip.rsp
+       echo $(OBJI); >> zip.rsp
+       $(LD) $(LDFLAGS) @zip.rsp
+       del zip.rsp
+       $(STRIP) zip.exe
+
+zipcloak.exe: $(OBJC)
+       echo $(OBJC); > zipc.rsp
+       $(LD) $(LDFLAGS) @zipc.rsp
+       del zipc.rsp
+       $(STRIP) zipcloak.exe
+
+zipnote.exe: $(OBJN)
+       echo $(OBJN); > zipn.rsp
+       $(LD) $(LDFLAGS) @zipn.rsp
+       del zipn.rsp
+       $(STRIP) zipnote.exe
+
+zipsplit.exe: $(OBJS)
+       echo $(OBJS); > zips.rsp
+       $(LD) $(LDFLAGS) @zips.rsp
+       del zips.rsp
+       $(STRIP) zipsplit.exe
+
+# No `install' and `clean' target possible as long as MSC's old MAKE utility
+# is supported (MSC 5.1 Make always tries to update ALL targets. The result
+# is that install and clean are always executed, unless an error occured.)
+#install:      $(ZIPS)
+#      copy /b *.exe $(BIN)
+#
+#clean:
+#      del *.obj
+#      del *.exe
diff --git a/msdos/makefile.tc b/msdos/makefile.tc
new file mode 100644 (file)
index 0000000..86d6b91
--- /dev/null
@@ -0,0 +1,177 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for
+# Turbo C 2.0. (Thanks to Andrew Cadach <kadach@isi.itfs.nsk.su>)
+
+# To use, do "make -fmakefile.tc"
+
+# WARNING: the small model is not supported. You must use the large model.
+# Add -DSMALL_MEM or -DMEDIUM_MEM to the LOC macro if you wish to reduce
+# the memory requirements.
+# Add -DNO_ASM to CFLAGS and comment out the ASMOBJS definition if
+# you do not have tasm.
+
+# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)
+# should be added to the environment via "set LOCAL_ZIP=-DFOO" or added
+# to the declaration of LOC here:
+LOC = -DDOS -DNO_SECURE_TESTS $(LOCAL_ZIP)
+
+# Zip requires compact or large memory model.
+# with 2.1, compact model exceeds 64k code segment; use large model
+ZIPMODEL=l     # large model for Zip and ZipUtils
+
+# name of Flag to select memory model for assembler compiles, supported
+# values are __SMALL__ , __MEDIUM__ , __COMPACT__ , __LARGE__ :
+ASMODEL=__LARGE__              # keep in sync with ZIPMODEL definition !!
+
+# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.
+CPU_TYP = 0
+
+# Uncomment the following macro to use the optimized assembler
+# routines in Zip:
+ASMOBJS = match.obj crc_i86.obj
+
+ASCPUFLAG = __$(CPU_TYP)86
+
+# ------------- Turbo C 2.0 -------------
+MODEL=-m$(ZIPMODEL)
+CFLAGS=-w -w-eff -w-def -w-sig -w-cln -a -d -G -O -Z $(MODEL) $(LOC)
+UTILFLAGS=-DUTIL $(CFLAGS) -o
+CC=tcc
+
+# Old versions of tasm (prior to 2.01) may not like the "-m2" option...
+AS=tasm
+ASFLAGS=-ml -t -m2 -DDYN_ALLOC -DSS_NEQ_DS -D$(ASCPUFLAG) -D$(ASMODEL) $(LOC)
+
+LD=tcc
+LDFLAGS=$(MODEL)
+
+# ------------- Common declarations:
+STRIP=rem
+#    If you don't have UPX, LZEXE, or PKLITE, get one of them. Then define:
+#    (NOTE: upx needs a 386 or higher system to run the exe compressor)
+#STRIP=upx --8086 --best
+#    or
+#STRIP=lzexe
+#    or (if you've registered PKLITE)
+#STRIP=pklite
+#    This makes a big difference in .exe size (and possibly load time)
+
+# ------------- Used by install rule
+# set BIN to the directory you want to install the executables to
+BIN = c:\util
+
+# variables
+OBJZ = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \
+       crc32.obj crctab.obj globals.obj
+
+OBJI = deflate.obj trees.obj $(ASMOBJS) msdos.obj
+
+OBJU = _zipfile.obj _fileio.obj _util.obj globals.obj _msdos.obj
+OBJN = zipnote.obj $(OBJU)
+OBJC = zipcloak.obj crctab.obj _crypt.obj ttyio.obj $(OBJU)
+OBJS = zipsplit.obj $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h msdos/osdep.h
+
+ZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zips:  $(ZIPS)
+
+zip.obj:       zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipfile.obj:   zipfile.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+zipup.obj:     zipup.c $(ZIP_H) revision.h crypt.h msdos/zipup.h
+       $(CC) -c $(CFLAGS) $*.c
+
+fileio.obj:    fileio.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+util.obj:      util.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+globals.obj:   globals.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+deflate.obj:   deflate.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+trees.obj:     trees.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crc32.obj:     crc32.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crctab.obj:    crctab.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crypt.obj:     crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+ttyio.obj:     ttyio.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+msdos.obj:     msdos/msdos.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) msdos/$*.c
+
+zipcloak.obj:  zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) -o$* $*.c
+
+zipnote.obj:   zipnote.c $(ZIP_H) revision.h
+       $(CC) -c $(CFLAGS) -o$* $*.c
+
+zipsplit.obj:  zipsplit.c $(ZIP_H) revision.h
+       $(CC) -c $(CFLAGS) -o$* $*.c
+
+_zipfile.obj:  zipfile.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS)$* zipfile.c
+
+_fileio.obj:   fileio.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS)$* fileio.c
+
+_util.obj:     util.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS)$* util.c
+
+_crypt.obj:    crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(UTILFLAGS)$* crypt.c
+
+_msdos.obj:    msdos/msdos.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS)$* msdos/msdos.c
+
+crc_i86.obj:   msdos/crc_i86.asm
+       $(AS) $(ASFLAGS) msdos\crc_i86.asm ;
+
+match.obj:     msdos/match.asm
+       $(AS) $(ASFLAGS) msdos\match.asm ;
+
+# make sure the command line fits in the MS/DOS 128 byte limit:
+zip.exe: $(OBJZ) $(OBJI)
+       rem   ignore any warnings in the following renaming commands:
+       ren _*.obj _*.ob
+       ren zipcloak.obj *.ob
+       ren zipnote.obj *.ob
+       ren zipsplit.obj *.ob
+       $(LD) $(LDFLAGS) -ezip.exe *.obj
+       ren _*.ob _*.obj
+       ren zip???*.ob *.obj
+       $(STRIP) zip.exe
+
+zipcloak.exe: $(OBJC)
+       $(LD) $(LDFLAGS) -ezipcloak.exe $(OBJC)
+       $(STRIP) zipcloak.exe
+
+zipnote.exe: $(OBJN)
+       $(LD) $(LDFLAGS) -ezipnote.exe $(OBJN)
+       $(STRIP) zipnote.exe
+
+zipsplit.exe: $(OBJS)
+       $(LD) $(LDFLAGS) -ezipsplit.exe $(OBJS)
+       $(STRIP) zipsplit.exe
+
+install:        $(ZIPS)
+       copy /b *.exe $(BIN)
+
+clean:
+       del *.obj
+       del *.exe
diff --git a/msdos/makefile.wat b/msdos/makefile.wat
new file mode 100644 (file)
index 0000000..d73fa7f
--- /dev/null
@@ -0,0 +1,253 @@
+# WMAKE makefile for 16 bit MSDOS or 32 bit DOS extender (PMODE/W or DOS/4GW)
+# using Watcom C/C++ v11.0+, by Paul Kienitz, last revised 17 Feb 2005.
+# Makes Zip.exe, ZipNote.exe, ZipCloak.exe, and ZipSplit.exe.
+#
+# Invoke from Zip source dir with "WMAKE -F MSDOS\MAKEFILE.WAT [targets]"
+# To build with debug info use "WMAKE DEBUG=1 ..."
+# To build with no assembly modules use "WMAKE NOASM=1 ..."
+# To make the PMODE/W version use "WMAKE PM=1 ..."
+# To make the DOS/4GW version use "WMAKE GW=1 ..." (overrides PM=1)
+#   Note: specifying PM or GW without NOASM requires that the win32 source
+#   directory be present, so it can access the 32 bit assembly sources.
+#   PMODE/W is recommended over DOS/4GW for best performance.
+# To create a low memory usage version of Zip, use "WMAKE WSIZE=8192 ..."
+#   (or whatever power of two less than 32768 you wish) -- this also causes
+#   SMALL_MEM to be defined.  Compression performance will be reduced.
+#   This currently is not supported with PM=1 or GW=1.
+#
+# Other options to be fed to the compiler and assembler can be specified in
+# an environment variable called LOCAL_ZIP.
+
+variation = $(%LOCAL_ZIP)
+
+# Stifle annoying "Delete this file?" questions when errors occur:
+.ERASE
+
+.EXTENSIONS:
+.EXTENSIONS: .exe .obj .c .h .asm
+
+# We maintain multiple sets of object files in different directories so that
+# we can compile msdos, dos/4gw or pmode/w, and win32 versions of Zip without
+# their object files interacting.  The following var must be a directory name
+# ending with a backslash.  All object file names must include this macro
+# at the beginning, for example "$(O)foo.obj".
+
+!ifdef GW
+PM = 1      # both protected mode formats use the same object files
+!endif
+
+!ifdef DEBUG
+!  ifdef PM
+OBDIR = od32d
+!  else
+!    ifdef WSIZE
+OBDIR = od16l
+size = -DWSIZE=$(WSIZE) -DSMALL_MEM
+!    else
+OBDIR = od16d
+size = -DMEDIUM_MEM
+!    endif
+!  endif
+!else
+!  ifdef PM
+OBDIR = ob32d
+!  else
+!    ifdef WSIZE
+OBDIR = ob16l
+size = -DWSIZE=$(WSIZE) -DSMALL_MEM
+!    else
+OBDIR = ob16d
+size = -DMEDIUM_MEM
+!    endif
+!  endif
+!endif
+O = $(OBDIR)\   # comment here so backslash won't continue the line
+
+# The assembly hot-spot code in crc_i[3]86.asm and match[32].asm is
+# optional.  This section controls its usage.
+
+!ifdef NOASM
+asmob = $(O)crc32.obj                       # C source
+cvars = $+$(cvars)$- -DDYN_ALLOC -DNO_ASM   # or ASM_CRC might default on!
+# "$+$(foo)$-" means expand foo as it has been defined up to now; normally,
+# this make defers inner expansion until the outer macro is expanded.
+!else  # !NOASM
+asmob = $(O)crc.obj $(O)match.obj
+!  ifdef PM
+cvars = $+$(cvars)$- -DASM_CRC -DASMV       # no DYN_ALLOC with match32.asm
+crc_s = win32\crc_i386.asm   # requires that the win32 directory be present
+mat_s = win32\match32.asm    # ditto
+!  else
+cvars = $+$(cvars)$- -DDYN_ALLOC -DASM_CRC -DASMV
+avars = $+$(avars)$- -DDYN_ALLOC
+crc_s = msdos\crc_i86.asm
+mat_s = msdos\match.asm
+!  endif
+!endif
+
+# Now we have to pick out the proper compiler and options for it.  This gets
+# pretty complicated with the PM, GW, DEBUG, and NOASM options...
+
+link   = wlink
+asm    = wasm
+
+!ifdef PM
+cc     = wcc386
+# Use Pentium Pro timings, register args, static strings in code:
+cflags = -bt=DOS -mf -6r -zt -zq
+aflags = -bt=DOS -mf -3 -zq
+cvars  = $+$(cvars)$- -DDOS $(variation)
+avars  = $+$(avars)$- $(variation)
+
+!  ifdef GW
+lflags = sys DOS4G
+!  else
+# THIS REQUIRES THAT PMODEW.EXE BE FINDABLE IN THE COMMAND PATH.
+# It does NOT require you to add a pmodew entry to wlink.lnk or wlsystem.lnk.
+defaultlibs = libpath %WATCOM%\lib386 libpath %WATCOM%\lib386\dos
+lflags = format os2 le op osname='PMODE/W' op stub=pmodew.exe $(defaultlibs)
+!  endif
+
+!else   # plain 16-bit DOS:
+
+cc     = wcc
+# Use plain 8086 instructions, large memory model, static strings in code:
+cflags = -bt=DOS -ml -0 -zt -zq
+aflags = -bt=DOS -ml -0 -zq
+cvars  = $+$(cvars)$- -DDOS $(size) $(variation)
+avars  = $+$(avars)$- $(size) $(variation)
+lflags = sys DOS
+!endif  # !PM
+
+# Specify optimizations, or a nonoptimized debugging version:
+
+!ifdef DEBUG
+cdebug = -od -d2
+ldebug = d w all op symf
+!else
+!  ifdef PM
+cdebug = -s -obhikl+rt -oe=100 -zp8
+# -oa helps slightly but might be dangerous.
+!  else
+cdebug = -s -oehiklrt
+!  endif
+ldebug = op el
+!endif
+
+# How to compile most sources:
+.c.obj:
+       $(cc) $(cdebug) $(cflags) $(cvars) $[@ -fo=$@
+
+# Our object files.  OBJZ is for Zip, OBJC is for ZipCloak, OBJN is for
+# ZipNote, and OBJS is for ZipSplit:
+
+OBJZ2 = $(O)zip.obj $(O)crypt.obj $(O)ttyio.obj $(O)zipfile.obj $(O)zipup.obj
+OBJZA = $(OBJZ2) $(O)util.obj $(O)fileio.obj $(O)deflate.obj
+OBJZB = $(O)trees.obj $(O)globals.obj $(O)crctab.obj $(asmob) $(O)msdos.obj
+
+OBJU2 = $(O)zipfile_.obj $(O)fileio_.obj $(O)util_.obj $(O)globals.obj
+OBJ_U = $(OBJU2) $(O)msdos_.obj
+
+OBJC  = $(O)zipcloak.obj $(O)crctab.obj $(O)crypt_.obj $(O)ttyio.obj $(OBJ_U)
+
+OBJN  = $(O)zipnote.obj $(OBJ_U)
+
+OBJS  = $(O)zipsplit.obj $(OBJ_U)
+
+# Common header files included by all C sources:
+
+ZIP_H = zip.h ziperr.h tailor.h msdos\osdep.h
+
+
+# HERE WE GO!  By default, make all targets:
+all: Zip.exe ZipNote.exe ZipCloak.exe ZipSplit.exe
+
+# Convenient shorthand options for single targets:
+z:   Zip.exe       .SYMBOLIC
+n:   ZipNote.exe   .SYMBOLIC
+c:   ZipCloak.exe  .SYMBOLIC
+s:   ZipSplit.exe  .SYMBOLIC
+
+Zip.exe:       $(OBDIR) $(OBJZA) $(OBJZB) $(OBJV)
+       set WLK_VA=file {$(OBJZA)}
+       set WLK_VB=file {$(OBJZB) $(OBJV)}
+       $(link) $(lflags) $(ldebug) name $@ @WLK_VA @WLK_VB
+       set WLK_VA=
+       set WLK_VB=
+# We use WLK_VA and WLK_VB to keep the size of each command under 256 chars.
+
+ZipNote.exe:   $(OBDIR) $(OBJN)
+       set WLK_VAR=file {$(OBJN)}
+       $(link) $(lflags) $(ldebug) name $@ @WLK_VAR
+       set WLK_VAR=
+
+ZipCloak.exe:  $(OBDIR) $(OBJC)
+       set WLK_VAR=file {$(OBJC)}
+       $(link) $(lflags) $(ldebug) name $@ @WLK_VAR
+       set WLK_VAR=
+
+ZipSplit.exe:  $(OBDIR) $(OBJS)
+       set WLK_VAR=file {$(OBJS)}
+       $(link) $(lflags) $(ldebug) name $@ @WLK_VAR
+       set WLK_VAR=
+
+# Source dependencies:
+
+$(O)crctab.obj:   crctab.c $(ZIP_H)
+$(O)crc32.obj:    crc32.c $(ZIP_H)              # only used if NOASM
+$(O)crypt.obj:    crypt.c $(ZIP_H) crypt.h ttyio.h
+$(O)deflate.obj:  deflate.c $(ZIP_H)
+$(O)fileio.obj:   fileio.c $(ZIP_H)
+$(O)globals.obj:  globals.c $(ZIP_H)
+$(O)trees.obj:    trees.c $(ZIP_H)
+$(O)ttyio.obj:    ttyio.c $(ZIP_H) crypt.h ttyio.h
+$(O)util.obj:     util.c $(ZIP_H)
+$(O)zip.obj:      zip.c $(ZIP_H) crypt.h revision.h ttyio.h
+$(O)zipfile.obj:  zipfile.c $(ZIP_H)
+$(O)zipup.obj:    zipup.c $(ZIP_H) revision.h crypt.h msdos\zipup.h
+$(O)zipnote.obj:  zipnote.c $(ZIP_H) revision.h
+$(O)zipcloak.obj: zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+$(O)zipsplit.obj: zipsplit.c $(ZIP_H) revision.h
+
+# Special case object files:
+
+$(O)msdos.obj:    msdos\msdos.c $(ZIP_H)
+       $(cc) $(cdebug) $(cflags) $(cvars) msdos\msdos.c -fo=$@
+
+$(O)match.obj:    $(mat_s)
+       $(asm) $(aflags) $(avars) $(mat_s) -fo=$@
+
+$(O)crc.obj:      $(crc_s)
+       $(asm) $(aflags) $(avars) $(crc_s) -fo=$@
+
+# Variant object files for ZipNote, ZipCloak, and ZipSplit:
+
+$(O)zipfile_.obj: zipfile.c $(ZIP_H)
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL zipfile.c -fo=$@
+
+$(O)fileio_.obj:  fileio.c $(ZIP_H)
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL fileio.c -fo=$@
+
+$(O)util_.obj:    util.c $(ZIP_H)
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL util.c -fo=$@
+
+$(O)crypt_.obj:   crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL crypt.c -fo=$@
+
+$(O)msdos_.obj:   msdos\msdos.c $(ZIP_H)
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL msdos\msdos.c -fo=$@
+
+# Creation of subdirectory for intermediate files
+$(OBDIR):
+       -mkdir $@
+
+# Unwanted file removal:
+
+clean:     .SYMBOLIC
+       del $(O)*.obj
+
+cleaner:   clean  .SYMBOLIC
+       del Zip.exe
+       del ZipNote.exe
+       del ZipCloak.exe
+       del ZipSplit.exe
diff --git a/msdos/match.asm b/msdos/match.asm
new file mode 100644 (file)
index 0000000..f126cd7
--- /dev/null
@@ -0,0 +1,457 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+;
+; match.asm by Jean-loup Gailly.
+
+; match.asm, optimized version of longest_match() in deflate.c
+; Must be assembled with masm -ml. To be used only with C compact model
+; or large model. (For large model, assemble with -D__LARGE__).
+; This file is only optional. If you don't have masm or tasm, use the
+; C version (add -DNO_ASM to CFLAGS in makefile.msc and remove match.obj
+; from OBJI). If you have reduced WSIZE in zip.h, then make sure this is
+; assembled with an equivalent -DWSIZE=<whatever>.
+;
+; The code has been prepared for two different C compiler calling conventions
+; and contains some support for dynamically allocated working space.
+; The different environments are selected by two conditional flags:
+;   DYN_ALLOC  : select support for malloc'ed working space
+;   SS_NEQ_DS  : relaxes assumption that stack and default data segments
+;                are identical
+; When SS_NEQ_DS is defined, the code segment is used to store some
+; local variables. This (bad) coding practice is very likely to break any
+; `segment protection scheme', it will most probably only work for real
+; mode programs.
+;
+; Turbo C 2.0 does not support static allocation of more than 64K bytes per
+; file, and does not have SS == DS. So TC and BC++ users must use:
+;   tasm -ml -DDYN_ALLOC -DSS_NEQ_DS match;
+;
+; To simplify the code, the option -DDYN_ALLOC is supported for OS/2
+; only if the arrays are guaranteed to have zero offset (allocated by
+; halloc). We also require SS==DS. This is satisfied for MSC but not Turbo C.
+;
+; Per default, test code is included to check if the above requirements are
+; fulfilled. This test code can be disabled by defining the compile time
+; option flag NO_SECURE_TESTS when compiling for a production executable.
+; This shortens the code size (but the performance gain is neglectable).
+; The security tests should remain enabled, when a new C compiler
+; and/or a new set of compilation options is tried.
+
+        name    match
+
+; Do NOT assemble this source if external crc32 routine from zlib gets used.
+;
+ifndef USE_ZLIB
+
+ifdef     DEBUG
+  VERBOSE_INFO EQU 1
+else
+  ifdef _AS_MSG_
+    VERBOSE_INFO EQU 1
+  else
+    VERBOSE_INFO EQU 0
+  endif
+endif
+
+ifndef __SMALL__
+  ifndef __COMPACT__
+    ifndef __MEDIUM__
+      ifndef __LARGE__
+        ifndef __HUGE__
+;         __SMALL__ EQU 1
+        endif
+      endif
+    endif
+  endif
+endif
+
+ifdef __HUGE__
+; .MODEL Huge
+   @CodeSize  EQU 1
+   @DataSize  EQU 1
+   Save_DS    EQU 1
+   if VERBOSE_INFO
+    if1
+      %out Assembling for C, Huge memory model
+    endif
+   endif
+else
+   ifdef __LARGE__
+;      .MODEL Large
+      @CodeSize  EQU 1
+      @DataSize  EQU 1
+      if VERBOSE_INFO
+       if1
+         %out Assembling for C, Large memory model
+       endif
+      endif
+   else
+      ifdef __COMPACT__
+;         .MODEL Compact
+         @CodeSize  EQU 0
+         @DataSize  EQU 1
+         if VERBOSE_INFO
+          if1
+            %out Assembling for C, Compact memory model
+          endif
+         endif
+      else
+         ifdef __MEDIUM__
+;            .MODEL Medium
+            @CodeSize  EQU 1
+            @DataSize  EQU 0
+            if VERBOSE_INFO
+             if1
+               %out Assembling for C, Medium memory model
+             endif
+            endif
+         else
+;            .MODEL Small
+            @CodeSize  EQU 0
+            @DataSize  EQU 0
+            if VERBOSE_INFO
+             if1
+               %out Assembling for C, Small memory model
+             endif
+            endif
+         endif
+      endif
+   endif
+endif
+
+if @CodeSize
+        LCOD_OFS        EQU     2
+else
+        LCOD_OFS        EQU     0
+endif
+
+IF @DataSize
+        LDAT_OFS        EQU     2
+else
+        LDAT_OFS        EQU     0
+endif
+
+ifdef Save_DS
+;                       (di,si,ds)+(size, return address)
+        SAVE_REGS       EQU     6+(4+LCOD_OFS)
+else
+;                       (di,si)+(size, return address)
+        SAVE_REGS       EQU     4+(4+LCOD_OFS)
+endif
+
+;
+; Selection of the supported CPU instruction set and initialization
+; of CPU type related macros:
+;
+ifdef __586
+        Use_286_code    EQU     1
+        Align_Size      EQU     16      ; paragraph alignment on Pentium
+        Alig_PARA       EQU     1       ; paragraph aligned code segment
+else
+ifdef __486
+        Use_286_code    EQU     1
+        Align_Size      EQU     4       ; dword alignment on 32 bit processors
+        Alig_PARA       EQU     1       ; paragraph aligned code segment
+else
+ifdef __386
+        Use_286_code    EQU     1
+        Align_Size      EQU     4       ; dword alignment on 32 bit processors
+        Alig_PARA       EQU     1       ; paragraph aligned code segment
+else
+ifdef __286
+        Use_286_code    EQU     1
+        Align_Size      EQU     2       ; word alignment on 16 bit processors
+        Alig_PARA       EQU     0       ; word aligned code segment
+else
+ifdef __186
+        Use_186_code    EQU     1
+        Align_Size      EQU     2       ; word alignment on 16 bit processors
+        Alig_PARA       EQU     0       ; word aligned code segment
+else
+        Align_Size      EQU     2       ; word alignment on 16 bit processors
+        Alig_PARA       EQU     0       ; word aligned code segment
+endif   ;?__186
+endif   ;?__286
+endif   ;?__386
+endif   ;?__486
+endif   ;?__586
+
+ifdef Use_286_code
+        .286
+        Have_80x86      EQU     1
+else
+ifdef Use_186_code
+        .186
+        Have_80x86      EQU     1
+else
+        .8086
+        Have_80x86      EQU     0
+endif   ;?Use_186_code
+endif   ;?Use_286_code
+
+ifndef DYN_ALLOC
+        extrn   _prev         : word
+        extrn   _window       : byte
+        prev    equ  _prev    ; offset part
+        window  equ  _window
+endif
+
+_DATA    segment  word public 'DATA'
+        extrn   _nice_match   : word
+        extrn   _match_start  : word
+        extrn   _prev_length  : word
+        extrn   _good_match   : word
+        extrn   _strstart     : word
+        extrn   _max_chain_length : word
+ifdef DYN_ALLOC
+        extrn   _prev         : word
+        extrn   _window       : word
+        prev    equ 0         ; offset forced to zero
+        window  equ 0
+        window_seg equ _window[2]
+        window_off equ 0
+else
+        wseg    dw seg _window
+        window_seg equ wseg
+        window_off equ offset _window
+endif
+_DATA    ends
+
+DGROUP  group _DATA
+
+if @CodeSize
+if Alig_PARA
+MATCH_TEXT      SEGMENT  PARA PUBLIC 'CODE'
+else
+MATCH_TEXT      SEGMENT  WORD PUBLIC 'CODE'
+endif
+        assume  cs: MATCH_TEXT, ds: DGROUP
+else    ;!@CodeSize
+if Alig_PARA
+_TEXT   segment para public 'CODE'
+else
+_TEXT   segment word public 'CODE'
+endif
+        assume  cs: _TEXT, ds: DGROUP
+endif   ;?@CodeSize
+
+        public  _match_init
+        public  _longest_match
+
+ifndef      WSIZE
+        WSIZE         equ 32768         ; keep in sync with zip.h !
+endif
+        MIN_MATCH     equ 3
+        MAX_MATCH     equ 258
+        MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
+        MAX_DIST      equ (WSIZE-MIN_LOOKAHEAD)
+
+ifdef DYN_ALLOC
+  ifdef SS_NEQ_DS
+    prev_ptr    dw  seg _prev           ; pointer to the prev array
+  endif
+else
+    prev_ptr    dw  seg _prev           ; pointer to the prev array
+endif
+ifdef SS_NEQ_DS
+    match_start dw  0                   ; copy of _match_start if SS != DS
+    nice_match  dw  0                   ; copy of _nice_match  if SS != DS
+endif
+
+; initialize or check the variables used in match.asm.
+
+if @CodeSize
+_match_init proc far                    ; 'proc far' for large model
+else
+_match_init proc near                   ; 'proc near' for compact model
+endif
+ifdef SS_NEQ_DS
+        ma_start equ cs:match_start     ; does not work on OS/2
+        nice     equ cs:nice_match
+else
+        assume ss: DGROUP
+        ma_start equ ss:_match_start
+        nice     equ ss:_nice_match
+  ifndef NO_SECURE_TESTS
+        mov     ax,ds
+        mov     bx,ss
+        cmp     ax,bx                   ; SS == DS?
+        jne     fatal_err
+  endif
+endif
+ifdef DYN_ALLOC
+  ifndef NO_SECURE_TESTS
+        cmp     _prev[0],0              ; verify zero offset
+        jne     fatal_err
+        cmp     _window[0],0
+        jne     fatal_err
+  endif
+  ifdef SS_NEQ_DS
+        mov     ax,_prev[2]             ; segment value
+        mov     cs:prev_ptr,ax          ; ugly write to code, crash on OS/2
+        prev_seg  equ cs:prev_ptr
+  else
+        prev_seg  equ ss:_prev[2]       ; works on OS/2 if SS == DS
+  endif
+else
+        prev_seg  equ cs:prev_ptr
+endif
+        ret
+ifndef NO_SECURE_TESTS
+if @CodeSize
+        extrn   _exit : far             ; 'far' for large model
+else
+        extrn   _exit : near            ; 'near' for compact model
+endif
+fatal_err:                              ; (quiet) emergency stop:
+        call    _exit                   ; incompatible "global vars interface"
+endif
+
+_match_init endp
+
+; -----------------------------------------------------------------------
+; Set match_start to the longest match starting at the given string and
+; return its length. Matches shorter or equal to prev_length are discarded,
+; in which case the result is equal to prev_length and match_start is
+; garbage.
+; IN assertions: cur_match is the head of the hash chain for the current
+;   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+
+; int longest_match(cur_match)
+
+        align   Align_Size
+
+if @CodeSize
+_longest_match  proc far                 ; 'proc far' for large model
+else
+_longest_match  proc near                ; 'proc near' for compact model
+endif
+        push    bp
+        mov     bp,sp
+        push    di
+        push    si
+        push    ds
+
+if @CodeSize
+        cur_match    equ word ptr [bp+6] ; [bp+6] for large model
+else
+        cur_match    equ word ptr [bp+4] ; [bp+4] for compact model
+endif
+
+;       window       equ es:window (es:0 for DYN_ALLOC)
+;       prev         equ ds:prev
+;       match        equ es:si
+;       scan         equ es:di
+;       chain_length equ bp
+;       best_len     equ bx
+;       limit        equ dx
+
+        mov     si,cur_match            ; use bp before it is destroyed
+ifdef SS_NEQ_DS
+        mov     ax,_nice_match
+        mov     nice,ax                 ; ugly write to code, crash on OS/2
+endif
+        mov     dx,_strstart
+        mov     bp,_max_chain_length    ; chain_length = max_chain_length
+        mov     di,dx
+        sub     dx,MAX_DIST             ; limit = strstart-MAX_DIST
+        cld                             ; string ops increment si and di
+        jae     limit_ok
+        sub     dx,dx                   ; limit = NIL
+limit_ok:
+        add     di,2+window_off         ; di = offset(window + strstart + 2)
+        mov     bx,_prev_length         ; best_len = prev_length
+        mov     es,window_seg
+        mov     ax,es:[bx+di-3]         ; ax = scan[best_len-1..best_len]
+        mov     cx,es:[di-2]            ; cx = scan[0..1]
+        cmp     bx,_good_match          ; do we have a good match already?
+        mov     ds,prev_seg             ; (does not destroy the flags)
+        assume  ds: nothing
+        jb      do_scan                 ; good match?
+if Have_80x86
+        shr     bp,2                    ; chain_length >>= 2
+else
+        shr     bp,1                    ; chain_length >>= 2
+        shr     bp,1
+endif
+        jmp     short do_scan
+
+        align   Align_Size              ; align destination of branch
+long_loop:
+; at this point, ds:di == scan+2, ds:si == cur_match
+        mov     ax,[bx+di-3]            ; ax = scan[best_len-1..best_len]
+        mov     cx,[di-2]               ; cx = scan[0..1]
+        mov     ds,prev_seg             ; reset ds to address the prev array
+short_loop:
+; at this point, di == scan+2, si = cur_match,
+; ax = scan[best_len-1..best_len] and cx = scan[0..1]
+if (WSIZE-32768)
+        and     si,WSIZE-1              ; not needed if WSIZE=32768
+endif
+        shl     si,1                    ; cur_match as word index
+        dec     bp                      ; --chain_length
+        mov     si,prev[si]             ; cur_match = prev[cur_match]
+        jz      the_end
+        cmp     si,dx                   ; cur_match <= limit ?
+        jbe     the_end
+do_scan:
+        cmp     ax,word ptr es:window[bx+si-1] ; check match at best_len-1
+        jne     short_loop
+        cmp     cx,word ptr es:window[si]      ; check min_match_length match
+        jne     short_loop
+
+        mov     cx,es
+        add     si,2+window_off         ; si = match
+        mov     ds,cx                   ; ds = es = window
+        mov     cx,(MAX_MATCH-2)/2      ; scan for at most MAX_MATCH bytes
+        mov     ax,di                   ; ax = scan+2
+        repe    cmpsw                   ; loop until mismatch
+        je      maxmatch                ; match of length MAX_MATCH?
+mismatch:
+        mov     cl,[di-2]               ; mismatch on first or second byte?
+        xchg    ax,di                   ; di = scan+2, ax = end of scan
+        sub     cl,[si-2]               ; cl = 0 if first bytes equal
+        sub     ax,di                   ; ax = len
+        sub     si,2+window_off         ; si = cur_match + len
+        sub     si,ax                   ; si = cur_match
+        sub     cl,1                    ; set carry if cl == 0 (can't use DEC)
+        adc     ax,0                    ; ax = carry ? len+1 : len
+        cmp     ax,bx                   ; len > best_len ?
+        jle     long_loop
+        mov     ma_start,si             ; match_start = cur_match
+        mov     bx,ax                   ; bx = best_len = len
+        cmp     ax,nice                 ; len >= nice_match ?
+        jl      long_loop
+the_end:
+        pop     ds
+        assume  ds: DGROUP
+ifdef SS_NEQ_DS
+        mov     ax,ma_start             ; garbage if no match found
+        mov     ds:_match_start,ax
+endif
+        pop     si
+        pop     di
+        pop     bp
+        mov     ax,bx                   ; result = ax = best_len
+        ret
+maxmatch:                               ; come here if maximum match
+        cmpsb                           ; increment si and di
+        jmp     mismatch                ; force match_length = MAX_LENGTH
+
+_longest_match  endp
+
+if @CodeSize
+MATCH_TEXT      ENDS
+else
+_TEXT   ENDS
+endif
+;
+endif ;!USE_ZLIB
+;
+end
diff --git a/msdos/msdos.c b/msdos/msdos.c
new file mode 100644 (file)
index 0000000..77094bf
--- /dev/null
@@ -0,0 +1,1059 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include "zip.h"
+
+#ifndef UTIL    /* little or no material in this file is used by UTIL */
+
+#include <dos.h>
+#include <time.h>
+
+
+#if defined(__GO32__) || defined(__TURBOC__)
+#  include <dir.h> /* prototypes of find*() */
+   typedef struct ffblk   ff_dir;
+#  define FATTR (hidden_files ? FA_HIDDEN+FA_SYSTEM+FA_DIREC : FA_DIREC)
+#  define FFIRST(n,d,a)   findfirst(n,(struct ffblk *)d,a)
+#  define FNEXT(d)        findnext((struct ffblk *)d)
+#  if (defined(__TURBOC__) || (defined(__DJGPP__) && (__DJGPP__ >=2)))
+#    if (defined(__DJGPP__) && (__DJGPP__ == 2) && (__DJGPP_MINOR__ == 0))
+#      include <libc/dosio.h>
+#    endif
+#    define GetFileMode(name) _chmod(name, 0)
+#    define SetFileMode(name, attr) _chmod(name, 1, attr)
+#  else /* DJGPP v1.x */
+#    define GetFileMode(name) bdosptr(0x43, (name), 0)
+#  endif
+#endif /* __GO32__ || __TURBOC__ */
+
+#if defined(MSC) || defined(__WATCOMC__)
+   typedef struct find_t  ff_dir;
+#  define FATTR (hidden_files ? _A_HIDDEN+_A_SYSTEM+_A_SUBDIR : _A_SUBDIR)
+#  ifndef FA_LABEL
+#    define FA_LABEL      _A_VOLID
+#  endif
+#  define FFIRST(n,d,a)   _dos_findfirst(n,a,(struct find_t *)d)
+#  define FNEXT(d)        _dos_findnext((struct find_t *)d)
+#  define ff_name         name
+#  define ff_fdate        wr_date
+#  define ff_ftime        wr_time
+#  define ff_attrib       attrib
+#endif /* MSC || __WATCOMC__ */
+
+#ifdef __EMX__
+#  ifdef EMX_OBSOLETE           /* emx 0.9b or earlier */
+#    define size_t xxx_size_t
+#    define wchar_t xxx_wchar_t
+#    define tm xxx_tm
+#    include <sys/emx.h>
+#    undef size_t
+#    undef wchar_t
+#    undef tm
+#  else /* !EMX_OBSOLETE */     /* emx 0.9c or newer */
+#    include <emx/syscalls.h>
+#  endif /* ?EMX_OBSOLETE */
+   typedef struct _find   ff_dir;
+#  define FATTR (hidden_files ? _A_HIDDEN+_A_SYSTEM+_A_SUBDIR : _A_SUBDIR)
+#  define FA_LABEL        _A_VOLID
+#  define FFIRST(n,d,a)   __findfirst(n,a,d)
+#  define FNEXT(d)        __findnext(d)
+#  define ff_name         name
+#  define ff_fdate        date
+#  define ff_ftime        time
+#  define ff_attrib       attr
+#  define GetFileMode(name) __chmod(name, 0, 0)
+#  define SetFileMode(name, attr) __chmod(name, 1, attr)
+#endif /* __EMX__ */
+
+#ifndef SetFileMode
+#  define SetFileMode(name, attr) _dos_setfileattr(name, attr)
+#endif
+
+
+#define PAD  0
+#define PATH_END '/'
+
+/* Library functions not in (most) header files */
+int rmdir OF((const char *));
+int utime OF((char *, ztimbuf *));
+
+/* Local functions */
+#ifndef GetFileMode
+int GetFileMode OF((char *name));
+#endif /* !GetFileMode */
+
+local int  initDirSearch OF((char *name, ff_dir *ff_context_p));
+local char *getVolumeLabel OF((int, ulg *, ulg *, time_t *));
+local int  wild_recurse OF((char *, char *));
+
+/* Module level variables */
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+/* Module level constants */
+local ZCONST char wild_match_all[] = "*.*";
+
+
+#ifndef GetFileMode
+int GetFileMode(char *name)
+{
+  unsigned int attr = 0;
+  return (_dos_getfileattr(name, &attr) ? -1 : attr);
+}
+#endif /* !GetFileMode */
+
+local int initDirSearch(name, ff_context_p)
+  char *name;                   /* name of directory to scan */
+  ff_dir *ff_context_p;         /* pointer to FFIRST/FNEXT context structure */
+{
+  int r;                        /* FFIRST return value */
+  char *p, *q;                  /* temporary copy of name, and aux pointer */
+
+  if ((p = malloc(strlen(name) + (2 + sizeof(wild_match_all)))) == NULL)
+    return ZE_MEM;
+
+  strcpy(p, name);
+  q = p + strlen(p);
+  if (q[-1] == ':')
+    *q++ = '.';
+  if ((q - p) > 0 && *(q - 1) != '/')
+    *q++ = '/';
+  strcpy(q, wild_match_all);
+  r = FFIRST(p, ff_context_p, FATTR);
+  free((zvoid *)p);
+
+  return (r ? ZE_MISS : ZE_OK);
+}
+
+local char *getVolumeLabel(drive, vtime, vmode, vutim)
+  int drive;    /* drive name: 'A' .. 'Z' or '\0' for current drive */
+  ulg *vtime;   /* volume label creation time (DOS format) */
+  ulg *vmode;   /* volume label file mode */
+  time_t *vutim;/* volume label creation time (UNIX format) */
+
+/* If a volume label exists for the given drive, return its name and
+   set its time and mode. The returned name must be static data. */
+{
+  static char vol[14];
+  ff_dir d;
+  char *p;
+
+  if (drive) {
+    vol[0] = (char)drive;
+    strcpy(vol+1, ":/");
+  } else {
+    strcpy(vol, "/");
+  }
+  strcat(vol, wild_match_all);
+  if (FFIRST(vol, &d, FA_LABEL) == 0) {
+    strncpy(vol, d.ff_name, sizeof(vol)-1);
+    vol[sizeof(vol)-1] = '\0';   /* just in case */
+    if ((p = strchr(vol, '.')) != NULL) /* remove dot, though PKZIP doesn't */
+      strcpy(p, p + 1);
+    *vtime = ((ulg)d.ff_fdate << 16) | ((ulg)d.ff_ftime & 0xffff);
+    *vmode = (ulg)d.ff_attrib;
+    *vutim = dos2unixtime(*vtime);
+    return vol;
+  }
+  return NULL;
+}
+
+
+#ifdef MSDOS16
+#define ONENAMELEN 12   /* no 16-bit compilers supports LFN */
+#else
+#define ONENAMELEN 255
+#endif
+
+/* whole is a pathname with wildcards, wildtail points somewhere in the  */
+/* middle of it.  All wildcards to be expanded must come AFTER wildtail. */
+
+local int wild_recurse(whole, wildtail)
+char *whole;
+char *wildtail;
+{
+    ff_dir dir;
+    char *subwild, *name, *newwhole = NULL, *glue = NULL, plug = 0, plug2;
+    ush newlen, amatch = 0;
+    int e = ZE_MISS;
+
+    if (!isshexp(wildtail)) {
+        struct stat s;                          /* dummy buffer for stat() */
+
+        if (!LSSTAT(whole, &s))                 /* file exists ? */
+            return procname(whole, 0);
+        else
+            return ZE_MISS;                     /* woops, no wildcards! */
+    }
+
+    /* back up thru path components till existing dir found */
+    do {
+        name = wildtail + strlen(wildtail) - 1;
+        for (;;)
+            if (name-- <= wildtail || *name == PATH_END) {
+                subwild = name + 1;
+                plug2 = *subwild;
+                *subwild = 0;
+                break;
+            }
+        if (glue)
+            *glue = plug;
+        glue = subwild;
+        plug = plug2;
+        e = initDirSearch(whole, &dir);
+    } while (e == ZE_MISS && subwild > wildtail);
+    wildtail = subwild;                 /* skip past non-wild components */
+    if (e != ZE_OK) {
+        if (glue)
+            *glue = plug;
+        goto ohforgetit;
+    }
+    subwild = strchr(wildtail + 1, PATH_END);
+    /* this "+ 1" dodges the  ^^^ hole left by *glue == 0 */
+    if (subwild != NULL) {
+        *(subwild++) = 0;               /* wildtail = one component pattern */
+        newlen = strlen(whole) + strlen(subwild) + (ONENAMELEN + 2);
+    } else
+        newlen = strlen(whole) + (ONENAMELEN + 1);
+    if ((newwhole = malloc(newlen)) == NULL) {
+        if (glue)
+            *glue = plug;
+        e = ZE_MEM;
+        goto ohforgetit;
+    }
+    strcpy(newwhole, whole);
+    newlen = strlen(newwhole);
+    if (glue)
+        *glue = plug;                           /* repair damage to whole */
+    if (!isshexp(wildtail)) {
+        e = ZE_MISS;                            /* non-wild name not found */
+        goto ohforgetit;
+    }
+
+    do {
+        if (strcmp(dir.ff_name, ".") && strcmp(dir.ff_name, "..")
+                                  && MATCH(wildtail, dir.ff_name, 0)) {
+            strcpy(newwhole + newlen, dir.ff_name);
+            if (subwild) {
+                name = newwhole + strlen(newwhole);
+                *(name++) = PATH_END;
+                strcpy(name, subwild);
+                e = wild_recurse(newwhole, name);
+            } else
+                e = procname(newwhole, 0);
+            newwhole[newlen] = 0;
+            if (e == ZE_OK)
+                amatch = 1;
+            else if (e != ZE_MISS)
+                break;
+        }
+    } while (FNEXT(&dir) == 0);
+
+  ohforgetit:
+    if (subwild)
+        *--subwild = PATH_END;
+    if (newwhole)
+        free(newwhole);
+    if (e == ZE_MISS && amatch)
+        e = ZE_OK;
+    return e;
+}
+
+int wild(w)
+char *w;                /* path/pattern to match */
+/* If not in exclude mode, expand the pattern based on the contents of the
+   file system.  Return an error code in the ZE_ class. */
+{
+    char *p;            /* path */
+    char *q;            /* diskless path */
+    int e;              /* result */
+
+    if (volume_label == 1) {
+      volume_label = 2;
+      label = getVolumeLabel((w != NULL && w[1] == ':') ? to_up(w[0]) : '\0',
+                             &label_time, &label_mode, &label_utim);
+      if (label != NULL)
+        (void)newname(label, 0, 0);
+      if (w == NULL || (w[1] == ':' && w[2] == '\0')) return ZE_OK;
+      /* "zip -$ foo a:" can be used to force drive name */
+    }
+    /* special handling of stdin request */
+    if (strcmp(w, "-") == 0)   /* if compressing stdin */
+        return newname(w, 0, 0);
+
+    /* Allocate and copy pattern, leaving room to add "." if needed */
+    if ((p = malloc(strlen(w) + 2)) == NULL)
+        return ZE_MEM;
+    strcpy(p, w);
+
+    /* Normalize path delimiter as '/' */
+    for (q = p; *q; q++)                  /* use / consistently */
+        if (*q == '\\')
+            *q = '/';
+
+    /* Separate the disk part of the path */
+    q = strchr(p, ':');
+    if (q != NULL) {
+        if (strchr(++q, ':'))     /* sanity check for safety of wild_recurse */
+            return ZE_MISS;
+    } else
+        q = p;
+
+    /* Normalize bare disk names */
+    if (q > p && !*q)
+        strcpy(q, ".");
+
+    /* Here we go */
+    e = wild_recurse(p, q);
+    free((zvoid *)p);
+    return e;
+}
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  char *a;              /* path and name for recursion */
+  ff_dir *d;            /* control structure for FFIRST/FNEXT */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  int ff_status;        /* return value of FFIRST/FNEXT */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+
+  if (n == NULL)        /* volume_label request in freshen|delete mode ?? */
+    return ZE_OK;
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (*n == '\0') return ZE_MISS;
+  else if (LSSTAT(n, &s)
+#ifdef __TURBOC__
+           /* For this compiler, stat() succeeds on wild card names! */
+           || isshexp(n)
+#endif
+          )
+  {
+    /* Not a file or directory--search for shell expression in zip file */
+    if (caseflag) {
+      p = malloc(strlen(n) + 1);
+      if (p != NULL)
+        strcpy(p, n);
+    } else
+      p = ex2in(n, 0, (int *)NULL);     /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (z->mark) z->dosflag = 1;    /* force DOS attribs for incl. names */
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+  for (p = n; *p; p++)          /* use / consistently */
+    if (*p == '\\')
+      *p = '/';
+  if ((s.st_mode & S_IFDIR) == 0)
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  } else {
+    /* Add trailing / to the directory name */
+    if ((p = malloc(strlen(n)+2)) == NULL)
+      return ZE_MEM;
+    if (strcmp(n, ".") == 0 || strcmp(n, "/.") == 0) {
+      *p = '\0';  /* avoid "./" prefix and do not create zip entry */
+    } else {
+      strcpy(p, n);
+      a = p + strlen(p);
+      if (a[-1] != '/')
+        strcpy(a, "/");
+      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+        free((zvoid *)p);
+        return m;
+      }
+    }
+    /* recurse into directory */
+    if (recurse)
+    {
+      if ((d = malloc(sizeof(ff_dir))) == NULL ||
+          (m = initDirSearch(n, d)) == ZE_MEM)
+      {
+        if (d != NULL)
+          free((zvoid *)d);
+        free((zvoid *)p);
+        return ZE_MEM;
+      }
+      for (e = d->ff_name, ff_status = m;
+           ff_status == 0;
+           ff_status = FNEXT(d))
+      {
+        if (strcmp(e, ".") && strcmp(e, ".."))
+        {
+          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+          {
+            free((zvoid *)d);
+            free((zvoid *)p);
+            return ZE_MEM;
+          }
+          strcat(strcpy(a, p), e);
+          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
+          {
+            if (m == ZE_MISS)
+              zipwarn("name not matched: ", a);
+            else
+              ziperr(m, a);
+          }
+          free((zvoid *)a);
+        }
+      }
+      free((zvoid *)d);
+    }
+    free((zvoid *)p);
+  } /* (s.st_mode & S_IFDIR) == 0) */
+  return ZE_OK;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t;              /* shortened name */
+  int dosflag;
+
+  dosflag = 1;
+
+  /* Find starting point in name before doing malloc */
+  /* Strip drive specification */
+  t = *x && *(x + 1) == ':' ? x + 2 : x;
+  /* Strip "//host/share/" part of a UNC name */
+  if ((!strncmp(x,"//",2) || !strncmp(x,"\\\\",2)) &&
+      (x[2] != '\0' && x[2] != '/' && x[2] != '\\')) {
+    n = x + 2;
+    while (*n != '\0' && *n != '/' && *n != '\\')
+      n++;              /* strip host name */
+    if (*n != '\0') {
+      n++;
+      while (*n != '\0' && *n != '/' && *n != '\\')
+        n++;            /* strip `share' name */
+    }
+    if (*n != '\0')
+      t = n + 1;
+  }
+  /* Strip leading "/" to convert an absolute path into a relative path */
+  while (*t == '/' || *t == '\\')
+    t++;
+  /* Skip leading "./" as well */
+  while (*t == '.' && (t[1] == '/' || t[1] == '\\'))
+    t += 2;
+
+  /* Make changes, if any, to the copied name (leave original intact) */
+  for (n = t; *n; n++)
+    if (*n == '\\')
+      *n = '/';
+
+  if (!pathput)
+    t = last(t, PATH_END);
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL)
+    return NULL;
+  strcpy(n, t);
+
+  if (isdir == 42) return n;      /* avoid warning on unused variable */
+
+  if (dosify)
+    msname(n);
+  else
+#if defined(__DJGPP__) && __DJGPP__ >= 2
+    if (_USE_LFN == 0)
+#endif
+      strlwr(n);
+  if (pdosflag)
+    *pdosflag = dosflag;
+  return n;
+}
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+
+  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+      return NULL;
+  strcpy(x, n);
+
+  return x;
+}
+
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+#if defined(__TURBOC__) || defined(__GO32__)
+  int h;                /* file handle */
+
+  if ((h = open(f, 0)) != -1)
+  {
+    setftime(h, (struct ftime *)(void *)&d);
+    close(h);
+  }
+#else /* !__TURBOC__ && !__GO32__ */
+  ztimbuf u;            /* argument for utime() */
+
+  /* Convert DOS time to time_t format in u.actime and u.modtime */
+  u.actime = u.modtime = dos2unixtime(d);
+
+  /* Set updated and accessed times of f */
+  utime(f, &u);
+#endif /* ?(__TURBOC__ || __GO32__) */
+}
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  char *name;
+  unsigned int len = strlen(f);
+  int isstdin = !strcmp(f, "-");
+
+  if (f == label) {
+    if (a != NULL)
+      *a = label_mode;
+    if (n != NULL)
+      *n = -2L; /* convention for a label name */
+    if (t != NULL)
+      t->atime = t->mtime = t->ctime = label_utim;
+    return label_time;
+  }
+
+  if ((name = malloc(len + 1)) == NULL) {
+    ZIPERR(ZE_MEM, "filetime");
+  }
+  strcpy(name, f);
+  if (name[len - 1] == '/')
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+
+  if (isstdin) {
+    if (fstat(fileno(stdin), &s) != 0) {
+      free(name);
+      error("fstat(stdin)");
+    }
+    time((time_t *)&s.st_mtime);       /* some fstat()s return time zero */
+  } else if (LSSTAT(name, &s) != 0) {
+             /* Accept about any file kind including directories
+              * (stored with trailing / with -r option)
+              */
+    free(name);
+    return 0;
+  }
+
+  if (a != NULL) {
+    *a = ((ulg)s.st_mode << 16) | (isstdin ? 0L : (ulg)GetFileMode(name));
+#if (S_IFREG != 0x8000)
+    /* kludge to work around non-standard S_IFREG flag used in DJGPP V2.x */
+    if ((s.st_mode & S_IFMT) == S_IFREG) *a |= 0x80000000L;
+#endif
+  }
+  if (n != NULL)
+    *n = (s.st_mode & S_IFREG) != 0 ? s.st_size : -1L;
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = s.st_ctime;
+  }
+
+  free(name);
+
+  return unix2dostime((time_t *)&s.st_mtime);
+}
+
+int deletedir(d)
+char *d;                /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+   Return the result of rmdir(), delete(), or system().
+ */
+{
+    return rmdir(d);
+}
+
+int set_extra_field(z, z_utim)
+  struct zlist far *z;
+  iztimes *z_utim;
+  /* create extra field and change z->att if desired */
+{
+#ifdef USE_EF_UT_TIME
+#ifdef IZ_CHECK_TZ
+  if (!zp_tz_is_valid) return ZE_OK;    /* skip silently if no valid TZ info */
+#endif
+
+  if ((z->extra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL)
+    return ZE_MEM;
+
+  z->extra[0]  = 'U';
+  z->extra[1]  = 'T';
+  z->extra[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */
+  z->extra[3]  = 0;
+  z->extra[4]  = EB_UT_FL_MTIME;
+  z->extra[5]  = (char)(z_utim->mtime);
+  z->extra[6]  = (char)(z_utim->mtime >> 8);
+  z->extra[7]  = (char)(z_utim->mtime >> 16);
+  z->extra[8]  = (char)(z_utim->mtime >> 24);
+
+  z->cext = z->ext = (EB_HEADSIZE+EB_UT_LEN(1));
+  z->cextra = z->extra;
+
+  return ZE_OK;
+#else /* !USE_EF_UT_TIME */
+  return (int)(z-z);
+#endif /* ?USE_EF_UT_TIME */
+}
+
+
+#ifdef MY_ZCALLOC       /* Special zcalloc function for MEMORY16 (MSDOS/OS2) */
+
+#if defined(__TURBOC__) && !defined(OS2)
+/* Small and medium model are for now limited to near allocation with
+ * reduced MAX_WBITS and MAX_MEM_LEVEL
+ */
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+    zvoid far *org_ptr;
+    zvoid far *new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+zvoid far *zcalloc (unsigned items, unsigned size)
+{
+    zvoid far *buf;
+    ulg bsize = (ulg)items*size;
+
+    if (bsize < (65536L-16L)) {
+        buf = farmalloc(bsize);
+        if (*(ush*)&buf != 0) return buf;
+    } else {
+        buf = farmalloc(bsize + 16L);
+    }
+    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+    table[next_ptr].org_ptr = buf;
+
+    /* Normalize the pointer to seg:0 */
+    *((ush*)&buf+1) += ((ush)((uch*)buf-NULL) + 15) >> 4;
+    *(ush*)&buf = 0;
+    table[next_ptr++].new_ptr = buf;
+    return buf;
+}
+
+zvoid zcfree (zvoid far *ptr)
+{
+    int n;
+    if (*(ush*)&ptr != 0) { /* object < 64K */
+        farfree(ptr);
+        return;
+    }
+    /* Find the original pointer */
+    for (n = next_ptr - 1; n >= 0; n--) {
+        if (ptr != table[n].new_ptr) continue;
+
+        farfree(table[n].org_ptr);
+        while (++n < next_ptr) {
+            table[n-1] = table[n];
+        }
+        next_ptr--;
+        return;
+    }
+    ziperr(ZE_MEM, "zcfree: ptr not found");
+}
+#endif /* __TURBOC__ */
+
+#if defined(MSC) || defined(__WATCOMC__)
+#if (!defined(_MSC_VER) || (_MSC_VER < 700))
+#  define _halloc  halloc
+#  define _hfree   hfree
+#endif
+
+zvoid far *zcalloc (unsigned items, unsigned size)
+{
+    return (zvoid far *)_halloc((long)items, size);
+}
+
+zvoid zcfree (zvoid far *ptr)
+{
+    _hfree((void huge *)ptr);
+}
+#endif /* MSC || __WATCOMC__ */
+
+#endif /* MY_ZCALLOC */
+
+#if (defined(__WATCOMC__) && defined(ASMV) && !defined(__386__))
+/* This is a hack to connect "call _exit" in match.asm to exit() */
+#pragma aux xit "_exit" parm caller []
+void xit(void)
+{
+    exit(20);
+}
+#endif
+
+#endif /* !UTIL */
+
+
+#ifndef WINDLL
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s.\n\n";
+                        /* At module level to keep Turbo C++ 1.0 happy !! */
+
+void version_local()
+{
+#if defined(__DJGPP__) || defined(__WATCOMC__) || \
+    (defined(_MSC_VER) && (_MSC_VER != 800))
+    char buf[80];
+#endif
+
+/* Define the compiler name and version strings */
+#if defined(__GNUC__)
+#  if defined(__DJGPP__)
+    sprintf(buf, "djgpp v%d.%02d / gcc ", __DJGPP__, __DJGPP_MINOR__);
+#    define COMPILER_NAME1      buf
+#  elif defined(__GO32__)         /* __GO32__ is defined as "1" only (sigh) */
+#    define COMPILER_NAME1      "djgpp v1.x / gcc "
+#  elif defined(__EMX__)          /* ...so is __EMX__ (double sigh) */
+#    define COMPILER_NAME1      "emx+gcc "
+#  else
+#    define COMPILER_NAME1      "gcc "
+#  endif
+#  define COMPILER_NAME2        __VERSION__
+#elif defined(__WATCOMC__)
+#  if (__WATCOMC__ % 10 > 0)
+/* We do this silly test because __WATCOMC__ gives two digits for the  */
+/* minor version, but Watcom packaging prefers to show only one digit. */
+    sprintf(buf, "Watcom C/C++ %d.%02d", __WATCOMC__ / 100,
+            __WATCOMC__ % 100);
+#  else
+    sprintf(buf, "Watcom C/C++ %d.%d", __WATCOMC__ / 100,
+            (__WATCOMC__ % 100) / 10);
+#  endif
+#  define COMPILER_NAME1        buf
+#  define COMPILER_NAME2        ""
+#elif defined(__TURBOC__)
+#  ifdef __BORLANDC__
+#    define COMPILER_NAME1      "Borland C++"
+#    if (__BORLANDC__ < 0x0200)
+#      define COMPILER_NAME2    " 1.0"
+#    elif (__BORLANDC__ == 0x0200)   /* James:  __TURBOC__ = 0x0297 */
+#      define COMPILER_NAME2    " 2.0"
+#    elif (__BORLANDC__ == 0x0400)
+#      define COMPILER_NAME2    " 3.0"
+#    elif (__BORLANDC__ == 0x0410)   /* __BCPLUSPLUS__ = 0x0310 */
+#      define COMPILER_NAME2    " 3.1"
+#    elif (__BORLANDC__ == 0x0452)   /* __BCPLUSPLUS__ = 0x0320 */
+#      define COMPILER_NAME2    " 4.0 or 4.02"
+#    elif (__BORLANDC__ == 0x0460)   /* __BCPLUSPLUS__ = 0x0340 */
+#      define COMPILER_NAME2    " 4.5"
+#    elif (__BORLANDC__ == 0x0500)   /* __TURBOC__ = 0x0500 */
+#      define COMPILER_NAME2    " 5.0"
+#    else
+#      define COMPILER_NAME2    " later than 5.0"
+#    endif
+#  else
+#    define COMPILER_NAME1      "Turbo C"
+#    if (__TURBOC__ > 0x0401)
+#      define COMPILER_NAME2    "++ later than 3.0"
+#    elif (__TURBOC__ == 0x0401)     /* Kevin:  3.0 -> 0x0401 */
+#      define COMPILER_NAME2    "++ 3.0"
+#    elif (__TURBOC__ == 0x0296)     /* [662] checked by SPC */
+#      define COMPILER_NAME2    "++ 1.01"
+#    elif (__TURBOC__ == 0x0295)     /* [661] vfy'd by Kevin */
+#      define COMPILER_NAME2    "++ 1.0"
+#    elif (__TURBOC__ == 0x0201)     /* Brian:  2.01 -> 0x0201 */
+#      define COMPILER_NAME2    " 2.01"
+#    elif ((__TURBOC__ >= 0x018d) && (__TURBOC__ <= 0x0200)) /* James: 0x0200 */
+#      define COMPILER_NAME2    " 2.0"
+#    elif (__TURBOC__ > 0x0100)
+#      define COMPILER_NAME2    " 1.5"          /* James:  0x0105? */
+#    else
+#      define COMPILER_NAME2    " 1.0"          /* James:  0x0100 */
+#    endif
+#  endif
+#elif defined(MSC)
+#  if defined(_QC) && !defined(_MSC_VER)
+#    define COMPILER_NAME1      "Microsoft Quick C"
+#    define COMPILER_NAME2      ""      /* _QC is defined as 1 */
+#  else
+#    define COMPILER_NAME1      "Microsoft C "
+#    ifdef _MSC_VER
+#      if (_MSC_VER == 800)
+#        define COMPILER_NAME2  "8.0/8.0c (Visual C++ 1.0/1.5)"
+#      else
+#        define COMPILER_NAME2 \
+           (sprintf(buf, "%d.%02d", _MSC_VER/100, _MSC_VER%100), buf)
+#      endif
+#    else
+#      define COMPILER_NAME2    "5.1 or earlier"
+#    endif
+#  endif
+#else
+#    define COMPILER_NAME1      "unknown compiler"
+#    define COMPILER_NAME2      ""
+#endif
+
+/* Define the OS name and memory environment strings */
+#if defined(__WATCOMC__) || defined(__TURBOC__) || defined(MSC) || \
+    defined(__GNUC__)
+#  define OS_NAME1      "\nMS-DOS"
+#else
+#  define OS_NAME1      "MS-DOS"
+#endif
+
+#if (defined(__GNUC__) || (defined(__WATCOMC__) && defined(__386__)))
+#  define OS_NAME2      " (32-bit)"
+#elif defined(M_I86HM) || defined(__HUGE__)
+#  define OS_NAME2      " (16-bit, huge)"
+#elif defined(M_I86LM) || defined(__LARGE__)
+#  define OS_NAME2      " (16-bit, large)"
+#elif defined(M_I86MM) || defined(__MEDIUM__)
+#  define OS_NAME2      " (16-bit, medium)"
+#elif defined(M_I86CM) || defined(__COMPACT__)
+#  define OS_NAME2      " (16-bit, compact)"
+#elif defined(M_I86SM) || defined(__SMALL__)
+#  define OS_NAME2      " (16-bit, small)"
+#elif defined(M_I86TM) || defined(__TINY__)
+#  define OS_NAME2      " (16-bit, tiny)"
+#else
+#  define OS_NAME2      " (16-bit)"
+#endif
+
+/* Define the compile date string */
+#ifdef __DATE__
+#  define COMPILE_DATE " on " __DATE__
+#else
+#  define COMPILE_DATE ""
+#endif
+
+    printf(CompiledWith, COMPILER_NAME1, COMPILER_NAME2,
+           OS_NAME1, OS_NAME2, COMPILE_DATE);
+
+} /* end function version_local() */
+#endif /* !WINDLL */
+
+
+#if 0 /* inserted here for future use (clearing of archive bits) */
+#if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2)))
+
+#include <errno.h>
+int volatile _doserrno;
+
+unsigned _dos_setfileattr(char *name, unsigned attr)
+{
+#if 0   /* stripping of trailing '/' is not needed for zip-internal use */
+    unsigned namlen = strlen(name);
+    char *i_name = alloca(namlen + 1);
+
+    strcpy(i_name, name);
+    if (namlen > 1 && i_name[namlen-1] == '/' && i_name[namlen-2] != ':')
+        i_name[namlen-1] = '\0';
+    asm("movl %0, %%edx": : "g" (i_name));
+#else
+    asm("movl %0, %%edx": : "g" (name));
+#endif
+    asm("movl %0, %%ecx": : "g" (attr));
+    asm("movl $0x4301, %eax");
+    asm("int $0x21": : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi");
+    _doserrno = 0;
+    asm("jnc 1f");
+    asm("movl %%eax, %0": "=m" (_doserrno));
+    switch (_doserrno) {
+    case 2:
+    case 3:
+           errno = ENOENT;
+           break;
+    case 5:
+           errno = EACCES;
+           break;
+    }
+    asm("1:");
+    return (unsigned)_doserrno;
+}
+
+#endif /* DJGPP v1.x */
+#endif /* never (not yet used) */
+
+
+#if (defined(__DJGPP__) && (__DJGPP__ >= 2))
+
+/* Disable determination of "x" bit in st_mode field for [f]stat() calls. */
+int _is_executable (const char *path, int fhandle, const char *ext)
+{
+    return 0;
+}
+
+/* Prevent globbing of filenames.  This gives the same functionality as
+ * "stubedit <program> globbing=no" did with DJGPP v1.
+ */
+#ifndef USE_DJGPP_GLOB
+char **__crt0_glob_function(char *_arg)
+{
+    return NULL;
+}
+#endif
+
+/* Reduce the size of the executable and remove the functionality to read
+ * the program's environment from whatever $DJGPP points to.
+ */
+#if !defined(USE_DJGPP_ENV) || defined(UTIL)
+void __crt0_load_environment_file(char *_app_name)
+{
+}
+#endif
+
+#endif /* __DJGPP__ >= 2 */
+
+
+#if defined(_MSC_VER) && _MSC_VER == 700
+
+/*
+ * ARGH.  MSC 7.0 libraries think times are based on 1899 Dec 31 00:00, not
+ *  1970 Jan 1 00:00.  So we have to diddle time_t's appropriately:  add
+ *  70 years' worth of seconds for localtime() wrapper function;
+ *  (70*365 regular days + 17 leap days + 1 1899 day) * 86400 ==
+ *  (25550 + 17 + 1) * 86400 == 2209075200 seconds.
+ *  Let time() and stat() return seconds since 1970 by using our own
+ *  _dtoxtime() which is the routine that is called by these two functions.
+ */
+
+
+#ifdef UTIL
+#  include <time.h>
+#endif
+
+#ifndef UTIL
+#undef localtime
+struct tm *localtime(const time_t *);
+
+struct tm *msc7_localtime(const time_t *clock)
+{
+   time_t t = *clock;
+
+   t += 2209075200L;
+   return localtime(&t);
+}
+#endif /* !UTIL */
+
+
+void __tzset(void);
+int _isindst(struct tm *);
+
+extern int _days[];
+
+/* Nonzero if `y' is a leap year, else zero. */
+#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
+
+/* Number of leap years from 1970 to `y' (not including `y' itself). */
+#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
+
+time_t _dtoxtime(year, month, mday, hour, min, sec)
+int year, month, mday, year, hour, min, sec;
+{
+   struct tm tm;
+   time_t t;
+   int days;
+
+   days = _days[month - 1] + mday;
+   year += 1980;
+   if (leap(year) && month > 2)
+     ++days;
+   tm.tm_yday = days;
+   tm.tm_mon = month - 1;
+   tm.tm_year = year - 1900;
+   tm.tm_hour = hour;
+   __tzset();
+   days += 365 * (year - 1970) + nleap (year);
+   t = 86400L * days + 3600L * hour + 60 * min + sec + _timezone;
+   if (_daylight && _isindst(&tm))
+      t -= 3600;
+   return t;
+}
+
+#endif /* _MSC_VER && _MSC_VER == 700 */
+
+
+#ifdef __WATCOMC__
+
+/* This papers over a bug in Watcom 10.6's standard library... sigh */
+/* Apparently it applies to both the DOS and Win32 stat()s.         */
+
+int stat_bandaid(const char *path, struct stat *buf)
+{
+  char newname[4];
+  if (!stat(path, buf))
+    return 0;
+  else if (!strcmp(path, ".") || (path[0] && !strcmp(path + 1, ":."))) {
+    strcpy(newname, path);
+    newname[strlen(path) - 1] = '\\';   /* stat(".") fails for root! */
+    return stat(newname, buf);
+  } else
+    return -1;
+}
+
+#endif
diff --git a/msdos/osdep.h b/msdos/osdep.h
new file mode 100644 (file)
index 0000000..380cd84
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.htmlhtml
+*/
+/* The symbol DOS is used throughout the Zip source to identify code portions
+ * specific to the MSDOS port.
+ * Just to make sure, we check that it is set.
+ * (Currently, this should should not be neccessary, since currently it has
+ * to be set on the compiler command line to get this file read in.)
+ */
+#ifndef DOS
+#  define DOS
+#endif
+
+/* The symbol MSDOS is consistently used in the generic source files
+ * to identify code to support for MSDOS (and MSDOS related) stuff.
+ * e.g: FAT or (FAT like) file systems,
+ *      '\\' as directory separator in paths,
+ *      "\r\n" as record (line) terminator in text files, ...
+ *
+ * IMPORTANT Note:
+ *  This symbol is not unique for the MSDOS port !!!!!!
+ *  It is also defined by ports to some other OS which are (to some extend)
+ *  considered DOS compatible.
+ *  Examples are: OS/2 (OS2), Windows NT and Windows 95 (WIN32).
+ *
+ */
+#ifndef MSDOS
+#  define MSDOS
+#endif
+
+/* Power C is similar to Turbo C */
+#ifdef __POWERC
+#  define __TURBOC__
+#endif /* __POWERC */
+
+/* Automatic setting of the common Microsoft C idenfifier MSC.
+ * NOTE: Watcom also defines M_I*86 !
+ */
+#if defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__))
+#  ifndef MSC
+#    define MSC                 /* This should work for older MSC, too!  */
+#  endif
+#endif
+
+#if !defined(__GO32__) && !defined(__EMX__)
+#  define NO_UNISTD_H
+#endif
+
+#if defined(__WATCOMC__) && defined(__386__)
+#  define WATCOMC_386
+#endif
+
+#ifdef WINDLL
+#  define MSWIN
+#  define MEMORY16
+#endif
+
+
+#if !defined(__EMX__) && !defined(__GO32__) && !defined(WATCOMC_386)
+#if !defined(WINDLL)
+#  define MSDOS16 /* 16 bit MSDOS only */
+#  define MEMORY16
+#endif
+#endif
+
+#if !defined(NO_ASM) && !defined(ASMV)
+#  define ASMV
+#endif
+
+/* enable creation of UTC time fields unless explicitely suppressed */
+#if !defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)
+#  define USE_EF_UT_TIME
+#endif
+
+/* check that TZ environment variable is defined before using UTC times */
+#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ))
+#  define IZ_CHECK_TZ
+#endif
+
+#ifdef MEMORY16
+#  ifndef NO_ASM
+#    define ASM_CRC 1
+#  endif /* ?NO_ASM */
+#  ifdef __TURBOC__
+#    include <alloc.h>
+#    if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
+#      if defined(DYNAMIC_CRC_TABLE) && defined(DYNALLOC_CRCTAB)
+        error: No dynamic CRC table allocation with Borland C far data models.
+#      endif /* DYNAMIC_CRC_TABLE */
+#    endif /* Turbo/Borland C far data memory models */
+#    define nearmalloc malloc
+#    define nearfree   free
+#    define DYN_ALLOC
+#  else /* !__TURBOC__ */
+#    include <malloc.h>
+#    define nearmalloc _nmalloc
+#    define nearfree   _nfree
+#    define farmalloc  _fmalloc
+#    define farfree    _ffree
+#  endif /* ?__TURBOC__ */
+#  define MY_ZCALLOC 1
+#  ifdef SMALL_MEM
+#    define CBSZ 2048
+#    define ZBSZ 2048
+#  endif
+#  ifdef MEDIUM_MEM
+#    define CBSZ 4096
+#    define ZBSZ 4096
+#  endif
+#  ifndef CBSZ
+#    define CBSZ 8192
+#    define ZBSZ 8192
+#  endif
+#endif /* MEMORY16 */
+
+
+#ifdef MATCH
+#  undef MATCH
+#endif
+#define MATCH dosmatch          /* use DOS style wildcard matching */
+
+#define USE_CASE_MAP
+
+#define ROUNDED_TIME(time)  (((time) + 1) & (~1))
+#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \
+                     procname(n, 1))
+
+#define FOPR "rb"
+#define FOPM "r+b"
+#define FOPW "wb"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+
+#ifdef ZCRYPT_INTERNAL
+#  ifdef WINDLL
+#    define ZCR_SEED2     (unsigned)3141592654L /* use PI as seed pattern */
+#  else
+#    ifndef __GO32__
+#      include <process.h>      /* getpid() declaration for srand seed */
+#    endif
+#  endif
+#endif
+
+/*
+ * djgpp 1.x did not declare these
+ */
+#if defined(__GO32__) && !defined(__DJGPP__)
+char *strlwr(char *);
+int setmode(int, int);
+#endif
+
+#ifdef __WATCOMC__
+#  define NO_MKTEMP
+#  define HAS_OPENDIR
+#  define SSTAT stat_bandaid
+   int stat_bandaid(const char *path, struct stat *buf);
+
+/* Get asm routines to link properly without using "__cdecl": */
+#  ifdef __386__
+#    ifdef ASMV
+#      pragma aux match_init    "_*" parm caller [] modify []
+#      pragma aux longest_match "_*" parm caller [] value [eax] \
+                                      modify [eax ecx edx]
+#    endif
+#    ifndef USE_ZLIB
+#      pragma aux crc32         "_*" parm caller [] value [eax] modify [eax]
+#      pragma aux get_crc_table "_*" parm caller [] value [eax] \
+                                      modify [eax ecx edx]
+#    endif /* !USE_ZLIB */
+#  else /* !__386__ */
+#    ifdef ASMV
+#      pragma aux match_init    "_*" parm caller [] loadds modify [ax bx]
+#      pragma aux longest_match "_*" parm caller [] loadds value [ax] \
+                                      modify [ax bx cx dx es]
+#    endif /* ASMV */
+#    ifndef USE_ZLIB
+#      pragma aux crc32         "_*" parm caller [] value [ax dx] \
+                                      modify [ax bx cx dx es]
+#      pragma aux get_crc_table "_*" parm caller [] value [ax] \
+                                      modify [ax bx cx dx]
+#    endif /* !USE_ZLIB */
+#  endif /* ?__386__ */
+#endif /* __WATCOMC__ */
+
+/*
+ * Wrapper function to get around the MSC7 00:00:00 31 Dec 1899 time base,
+ * see msdos.c for more info
+ */
+
+#if defined(_MSC_VER) && _MSC_VER == 700
+#  define localtime(t) msc7_localtime(t)
+#endif
+
+#if (defined(__TURBOC__) && !defined(__BORLANDC__) && __TURBOC__ <= 0x0201)
+#  ifndef NO_MKTIME
+#    define NO_MKTIME           /* TC 2.01 and earlier do not supply mktime() */
+#  endif
+#endif
diff --git a/msdos/zipup.h b/msdos/zipup.h
new file mode 100644 (file)
index 0000000..78b428a
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#define fhow         (O_RDONLY|O_BINARY)
+#define fbad         (-1)
+typedef int          ftype;
+#define zopen(n,p)   open(n,p)
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f)    close(f)
+#define zerr(f)      (k == (extent)(-1L))
+#define zstdin       0
diff --git a/os2/makefile.os2 b/os2/makefile.os2
new file mode 100644 (file)
index 0000000..8e5e7cf
--- /dev/null
@@ -0,0 +1,560 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit
+
+# Supported Make utilities:
+# - Microsoft/IBM nmake
+# - dmake 3.8 or higher
+# - GNU make, at least version 3.68
+# - NOT watcom make
+# For Microsoft and Watcom C, better use NMAKE,
+# otherwise it doesn't matter.
+
+# Supported 16-bit C Compilers (created programs run under OS/2 1.x and 2.x):
+# - Microsoft C 6.00A
+# - Watcom C/C++ 16-bit
+
+# Supported 32-bit C Compilers (created programs run under OS/2 2.x only):
+# - GNU gcc (emx kit 0.9c or newer)
+# - IBM C Set/2 or C Set++   - does not yet work with ASM code
+# - Watcom C/C++ 32-bit      - does not yet work with ASM code
+# - Borland C++              - no ASM code yet
+# - MetaWare High C/C++      - no ASM code yet
+
+# Supported Cross-Compilers for MS-DOS:
+# - Microsoft C 6.00A (16-bit)
+# - Watcom C/C++ (16- and 32-bit)
+# - GNU gcc (emx kit 0.9c or newer, 32-bit)
+
+# Supported Cross-Compilers for Win32 (WinNT/Win95):
+# - GNU gcc (emx kit 0.9c or newer, with RSXNT 1.4 or newer)
+
+# Supported Assemblers:
+# - Microsoft MASM 6.00 with Microsoft C, IBM C
+# - Watcom WASM with Watcom C/C++
+# - GNU as with GNU gcc
+
+# To use MASM 5.x instead of MASM 6.00:
+# - set AS="masm -T -Ml"
+# - set ASEOL=";"
+
+
+# To use, enter "make/nmake/dmake -f os2/makefile.os2"
+# (this makefile depends on its name being "os2/makefile.os2").
+
+# Add -DNO_ASM to CFLAGS and define OBJA to `nothing' if you do not have
+# masm or ml.
+# Add -DDYN_ALLOC to ASFLAGS if you have defined it in tailor.h or CFLAGS
+
+# Note: assembly language modules are really only supported for
+# Microsoft 16-bit and GNU gcc 32-bit compilation.
+
+# Notes on 16-bit (Microsoft C 6.00) compilation:
+
+#   The resulting programs can be used under OS/2 protected mode only.
+#   A larger stack has to be used for OS/2 because system calls
+#   use more stack than under DOS, 8k is recommended by Microsoft.
+#   Note that __STDC__ has to be defined explicitly with C 6.00 when -Ze
+#   is given, because Microsoft disables __STDC__ when their extensions
+#   are enabled. This is different from the C 5.10 behaviour.
+
+# Notes on 32-bit OS/2 compilation:
+
+#   The resulting programs can be used under OS/2 protected
+#   mode of OS/2 2.x only, not under 1.x and not under DOS.
+#   It makes no difference if __STDC__ is defined or not.
+#   Borland C++ works with DYN_ALLOC only.
+
+# Special Notes on IBM C/C++ compilation:
+
+#   The older C compiler (C Set/2) breaks, while optimizing, on deflate.c
+#   and trees.c (generates incorrect code). The newer C++ compiler (C Set++)
+#   doesn't but instead breaks on crypt.c in the initial version and up to
+#   CSD level 003. Starting with CSD level 004, it doesn't break any longer.
+
+# Notes on Watcom C/C++ compilation for DOS with the PMODE/W extender:
+#
+#   You need to add the following section to your \watcom\binb\wlsystem.lnk
+#   file and also need to copy pmodew.exe to the same directory:
+#
+#   system begin pmodew
+#       option osname='PMODE/W'
+#       libpath %WATCOM%\lib386
+#       libpath %WATCOM%\lib386\dos
+#       op stub=pmodew.exe
+#       format os2 le
+#   end
+#
+#   PMODE/W 1.16 or higher is required.
+
+
+default:
+       @echo "Enter $(MAKE) -f os2/makefile.os2 target"
+       @echo "where target is one of:"
+       @echo "   msc mscdos ibm ibmdyn ibmdebug ibmprof metaware borland"
+       @echo "   gcc gccdyn gcczlib gccdebug gccdos gccwin32 gccw32dyn"
+       @echo "   watcom watcom16 watcomdos watcom16dos pmodew"
+
+# MS C 6.00 for OS/2, 16-bit
+msc:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="cl -nologo -AL -Ocegit -Gs $(FP)" \
+       CFLAGS="-W1 -Zep -J -G2 -D__STDC__ -DOS2 -DASM_CRC" \
+       AS="ml -nologo -c -Zm -Cp" \
+       ASFLAGS="-D__LARGE__ -D__286" \
+       LDFLAGS="-F 2000 -Lp -Fe" \
+       LDFLAGS2="-link /noe /pm:vio" \
+       OUT="-Fo" \
+       OBJ=".obj" \
+       CRC32="crc_i86" \
+       OBJA="match.obj" \
+       DEF="os2\zip.def"
+
+# MS C 6.00 for OS/2, 16-bit, debug
+mscdebug:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="cl -nologo -AL -Zi -Od $(FP)" \
+       CFLAGS="-W1 -Zep -J -G2 -D__STDC__ -DOS2 -DASM_CRC" \
+       AS="ml -nologo -c -Zim -Cp" \
+       ASFLAGS="-D__LARGE__ -D__286" \
+       LDFLAGS="-F 2000 -Lp -Fe" \
+       LDFLAGS2="-link /noe /pm:vio" \
+       OUT="-Fo" \
+       OBJ=".obj" \
+       CRC32="crc_i86" \
+       OBJA="match.obj" \
+       DEF="os2\zip.def"
+
+# crosscompilation for MS-DOS with MS C 6.00
+mscdos:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="cl -nologo -AL -Ocegit -Gs $(FP)" \
+       CFLAGS="-W1 -Zep -J -D__STDC__ -DDOS -DASM_CRC -DDYN_ALLOC" \
+       AS="ml -nologo -c -Zm -Cp" \
+       ASFLAGS="-D__LARGE__ -DDYN_ALLOC" \
+       LDFLAGS="-F 2000 -Lr -Fe" \
+       LDFLAGS2="-link /noe /exe" \
+       OUT="-Fo" \
+       OBJ=".obj" \
+       CRC32="crc_i86" \
+       OBJA="match.obj" \
+       OBJ2="msdos.obj" OBJU2="msdos_.obj" \
+       OSDEP_H="msdos/osdep.h" ZIPUP_H="msdos/zipup.h"
+
+
+# IBM C Set/2, statically linked runtime
+ibm:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="icc -Q -O -Gs" \
+       CFLAGS="-Sm -Sp1 -DOS2 -DNO_ASM" \
+       AS="ml -nologo -c -Zm -Cp" \
+       ASFLAGS="" \
+       LDFLAGS="-B/ST:0x50000 -Fe" \
+       LDFLAGS2="" \
+       OUT="-Fo" \
+       OBJ=".obj" \
+       OBJA="" \
+       DEF="os2/zip.def"
+
+# IBM C Set/2, dynamically linked runtime
+ibmdyn:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="icc -Q -O -Gd -Gs" \
+       CFLAGS="-Sm -Sp1 -DOS2 -DNO_ASM" \
+       AS="ml -nologo -c -Zm -Cp" \
+       ASFLAGS="" \
+       LDFLAGS="-B/ST:0x50000 -Fe" \
+       LDFLAGS2="" \
+       OUT="-Fo" \
+       OBJ=".obj" \
+       OBJA="" \
+       DEF="os2/zip.def"
+
+# IBM C Set/2, debug version
+ibmdebug:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="icc -Q -Ti" \
+       CFLAGS="-Sm -Sp1 -DOS2 -DNO_ASM -Tm" \
+       AS="ml -nologo -c -Zim -Cp" \
+       ASFLAGS="" \
+       LDFLAGS="-B/ST:0x50000 -Fe" \
+       LDFLAGS2="" \
+       OUT="-Fo" \
+       OBJ=".obj" \
+       OBJA="" \
+       DEF="os2/zip.def"
+
+# IBM C Set/2, profiling version for PROFIT
+ibmprof:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="icc -Q -O -Gs -Gh -Ti" \
+       CFLAGS="-Sm -Sp1 -DOS2 -DNO_ASM" \
+       AS="ml -nologo -c -Zm -Cp" \
+       ASFLAGS="" \
+       LDFLAGS="-B/ST:0x50000 -Fe" \
+       LDFLAGS2="profit.obj" \
+       OUT="-Fo" \
+       OBJ=".obj" \
+       OBJA="" \
+       DEF="os2/zip.def"
+
+# Watcom C/386 9.0 or higher
+watcom:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="wcl386 -bt=os2v2 -zq -Ox -s" \
+       CFLAGS="-Zp1 -DOS2 -DNO_ASM" \
+       AS="wasm -bt=os2v2 -3p" \
+       ASFLAGS="" \
+       LDFLAGS="-k0x50000 -x -l=os2v2 -Fe=" \
+       LDFLAGS2="" \
+       OUT="-Fo" \
+       OBJ=".obj" \
+       OBJA="" \
+       DIRSEP="\\" \
+       AS_DIRSEP="\\"
+
+# Watcom C/286 9.0 or higher
+watcom16:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="wcl -bt=os2 -zq -ml -Ox -s" \
+       CFLAGS="-Zp1 -DOS2 -DNO_ASM" \
+       AS="wasm -bt=os2 -2p -ml" \
+       ASFLAGS="" \
+       LDFLAGS="/\"option newfiles\" -k0x3000 -x -l=os2 -Fe=" \
+       LDFLAGS2="" \
+       OUT="-Fo" \
+       OBJ=".obj" \
+       OBJA="" \
+       DIRSEP="\\" \
+       AS_DIRSEP="\\"
+
+# Watcom C/386 9.0 or higher, crosscompilation for DOS, DOS4GW extender
+watcomdos:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="wcl386 -bt=dos4g -zq -Ox -s" \
+       CFLAGS="-Zp1 -DDOS -DMSDOS -DNO_ASM" \
+       AS="wasm -bt=dos4g -3p" \
+       ASFLAGS="" \
+       LDFLAGS="-k0x50000 -x -l=dos4g -Fe=" \
+       LDFLAGS2="" \
+       OUT="-Fo" \
+       OBJ=".obj" \
+       OBJA="" \
+       OBJ2="msdos.obj" \
+       OBJU2="msdos_.obj" \
+       OSDEP_H="msdos/osdep.h" \
+       ZIPUP_H="msdos/zipup.h" \
+       DIRSEP="\\" \
+       AS_DIRSEP="\\"
+
+# Watcom C/386 9.0 or higher, crosscompilation for DOS, PMODE/W extender
+pmodew:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="wcl386 -bt=dos4g -zq -Ox -s" \
+       CFLAGS="-Zp1 -DDOS -DMSDOS -DASM_CRC" \
+       AS="wasm -bt=dos4g -3p" \
+       ASFLAGS="" \
+       LDFLAGS="-k0x50000 -x -l=pmodew -Fe=" \
+       LDFLAGS2="" \
+       OUT="-Fo" \
+       OBJ=".obj" \
+       CRC32="crc_i386" \
+       OBJA="match32.obj" \
+       OBJ2="msdos.obj" \
+       OBJU2="msdos_.obj" \
+       OSDEP_H="msdos/osdep.h" \
+       ZIPUP_H="msdos/zipup.h" \
+       DIRSEP="\\" \
+       AS_DIRSEP="\\"
+
+# Watcom C/286 9.0 or higher, crosscompilation for DOS
+watcom16dos:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="wcl -bt=dos -zq -ml -Ox -s" \
+       CFLAGS="-Zp1 -DDOS -DMSDOS -DDYN_ALLOC -DNO_ASM" \
+       AS="wasm -bt=dos -2p -ml" \
+       ASFLAGS="-DDYN_ALLOC" \
+       LDFLAGS="-k0x2000 -x -l=dos -Fe=" \
+       LDFLAGS2="" \
+       OUT="-Fo" \
+       OBJ=".obj" \
+       OBJA="" \
+       OBJ2="msdos.obj" \
+       OBJU2="msdos_.obj" \
+       OSDEP_H="msdos/osdep.h" \
+       ZIPUP_H="msdos/zipup.h" \
+       DIRSEP="\\" \
+       AS_DIRSEP="\\"
+
+# MetaWare High C/C++ 3.2
+metaware:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="hc -O2" \
+       CFLAGS="-D__32BIT__ -DOS2 -DNO_ASM" \
+       AS="ml -nologo -c -Zm -Cp" \
+       ASFLAGS="" \
+       LDFLAGS="-o " \
+       LDFLAGS2="" \
+       OUT="-o ./" \
+       OBJ=".obj" \
+       DEF="-Hdef=os2/zip.def"
+
+# Borland C++
+borland:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="bcc -O" \
+       CFLAGS="-w- -DOS2 -DDYN_ALLOC -DNO_ASM" \
+       AS="ml -nologo -c -Zm -Cp" \
+       ASFLAGS="" \
+       LDFLAGS="-e" \
+       LDFLAGS2="" \
+       OUT="-o" \
+       OBJ=".obj" \
+       OBJA="" \
+       DEF="-sDos2/zip.def"
+
+# emx 0.9c, gcc, OMF format, statically linked C runtime and emx
+gcc:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="gcc -Zomf -O -Wimplicit" \
+       CFLAGS="-DOS2 -DASM_CRC" \
+       AS="gcc -Zomf" \
+       ASFLAGS="-Di386" \
+       LDFLAGS="-o ./" \
+       LDFLAGS2="-Zsys -Zstack 320 -s -Zsmall-conv" \
+       OUT="-o" \
+       OBJ=".obj" \
+       CRC32="crc_gcc" \
+       OBJA="matchgcc.obj" \
+       DEF="os2/zip.def"
+
+# emx 0.9c, gcc, OMF format, dynamically linked C runtime and emx
+gccdyn:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="gcc -Zomf -O -Wimplicit" \
+       CFLAGS="-DOS2 -DASM_CRC" \
+       AS="gcc -Zomf" \
+       ASFLAGS="-Di386" \
+       LDFLAGS="-o ./" \
+       LDFLAGS2="-Zcrtdll -Zstack 320 -s" \
+       OUT="-o" \
+       OBJ=".obj" \
+       CRC32="crc_gcc" \
+       OBJA="matchgcc.obj" \
+       DEF="os2/zip.def"
+
+# emx 0.9c, gcc, OMF format, statically linked zlib, C runtime, and emx
+gcczlib:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="gcc -Zomf -O -Wimplicit" \
+       CFLAGS="-DOS2 -DUSE_ZLIB" \
+       AS="gcc -Zomf" \
+       ASFLAGS="-Di386 -DUSE_ZLIB" \
+       LDFLAGS="-o ./" \
+       LDFLAGS2="-L. -lzlib -Zsys -Zstack 320 -s -Zsmall-conv" \
+       OUT="-o" \
+       OBJ=".obj" \
+       CRC32="crc32" \
+       OBJA="" \
+       DEF="os2/zip.def"
+
+# emx 0.9c, gcc, a.out format, with debug info for gdb
+gccdebug:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="gcc -g -Wimplicit" \
+       CFLAGS="-DOS2 -DASM_CRC" \
+       AS="gcc" \
+       ASFLAGS="-Di386" \
+       LDFLAGS="-o ./" \
+       LDFLAGS2="" \
+       OUT="-o" \
+       OBJ=".o" \
+       CRC32="crc_gcc" \
+       OBJA="matchgcc.o" \
+       DEF="os2/zip.def"
+
+# emx 0.9c, gcc, a.out format, for MS-DOS
+gccdos:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="gcc -O -Wimplicit" \
+       CFLAGS="-DDOS -DMSDOS -DASM_CRC" \
+       AS="gcc" \
+       ASFLAGS="-Di386" \
+       LDFLAGS="-o ./" \
+       LDFLAGS2="-s -Zsmall-conv" \
+       OUT="-o" \
+       OBJ=".o" \
+       CRC32="crc_gcc" \
+       OBJA="matchgcc.o" \
+       OBJ2="msdos.o" \
+       OBJU2="msdos_.o" \
+       OSDEP_H="msdos/osdep.h" \
+       ZIPUP_H="msdos/zipup.h"
+
+# emx 0.9c, gcc, RSXNT 1.4, cross-compilation for Win32
+gccwin32:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="gcc -Zwin32 -O -m486 -Wall" \
+       CFLAGS="-DWIN32 -DASM_CRC" \
+       AS="gcc -Zwin32" \
+       ASFLAGS="-Di386" \
+       LDFLAGS="-o ./" \
+       LDFLAGS2="-ladvapi32 -Zsys -Zsmall-conv -s" \
+       OUT="-o" \
+       OBJ=".o" \
+       CRC32="crc_gcc" \
+       OBJA="matchgcc.o" \
+       OBJ2="win32zip.o win32.o nt.o" \
+       OBJU2="win32_.o" \
+       OSDEP_H="win32/osdep.h" \
+       ZIPUP_H="win32/zipup.h" \
+       DEF="win32/zip.def"
+
+# emx 0.9c, gcc, RSXNT 1.4, cross-compilation for Win32, use emx C rtl DLL
+gccw32dyn:
+       $(MAKE) -f os2/makefile.os2 zips \
+       CC="gcc -Zwin32 -Zcrtdll=crtrsxnt -O -m486 -Wall" \
+       CFLAGS="-DWIN32 -DASM_CRC" \
+       AS="gcc -Zwin32" \
+       ASFLAGS="-Di386" \
+       LDFLAGS="-o ./" \
+       LDFLAGS2="-ladvapi32 -s" \
+       OUT="-o" \
+       OBJ=".o" \
+       CRC32="crc_gcc" \
+       OBJA="matchgcc.o" \
+       OBJ2="win32zip.o win32.o nt.o" \
+       OBJU2="win32_.o" \
+       OSDEP_H="win32/osdep.h" \
+       ZIPUP_H="win32/zipup.h" \
+       DEF="win32/zip.def"
+
+# VPATH = .;os2
+
+# variables
+
+#default settings for target dependent macros:
+DIRSEP = /
+AS_DIRSEP = /
+# LOCAL_OPTS =
+CCFLAGS = $(CFLAGS) $(LOCAL_OPTS)
+
+OSDEP_H = os2/osdep.h
+ZIPUP_H = os2/os2zip.h os2/zipup.h
+CRC32   = crc32
+
+
+OBJZ =  zip$(OBJ) zipfile$(OBJ) zipup$(OBJ) fileio$(OBJ) util$(OBJ) \
+        $(CRC32)$(OBJ) crctab$(OBJ) globals$(OBJ) \
+       deflate$(OBJ) trees$(OBJ) crypt$(OBJ) ttyio$(OBJ)
+OBJ2 = os2zip$(OBJ) os2$(OBJ) os2acl$(OBJ)
+
+OBJU =  zipfile_$(OBJ) fileio_$(OBJ) util_$(OBJ) globals$(OBJ)
+OBJU2 = os2zip_$(OBJ)
+
+OBJN =  zipnote$(OBJ) $(OBJU) $(OBJU2)
+OBJS =  zipsplit$(OBJ) $(OBJU) $(OBJU2)
+OBJC =  zipcloak$(OBJ) crctab$(OBJ) crypt_$(OBJ) ttyio$(OBJ) $(OBJU) $(OBJU2)
+
+ZIP_H = zip.h ziperr.h tailor.h $(OSDEP_H)
+
+# rules
+
+.SUFFIXES: .c $(OBJ)
+
+.c$(OBJ):
+       $(CC) -c -I. $(CCFLAGS) $<
+
+.asm$(OBJ):
+       $(AS) $(ASFLAGS) $< $(ASEOL)
+
+# targets
+
+zips:  zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zip$(OBJ):     zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipfile$(OBJ): zipfile.c $(ZIP_H)
+zipup$(OBJ):   zipup.c $(ZIP_H) revision.h crypt.h $(ZIPUP_H)
+fileio$(OBJ):  fileio.c $(ZIP_H)
+util$(OBJ):    util.c $(ZIP_H)
+globals$(OBJ): globals.c $(ZIP_H)
+deflate$(OBJ): deflate.c $(ZIP_H)
+trees$(OBJ):   trees.c $(ZIP_H)
+crc32$(OBJ):   crc32.c $(ZIP_H)
+crctab$(OBJ):  crctab.c $(ZIP_H)
+crypt$(OBJ):   crypt.c $(ZIP_H) crypt.h ttyio.h
+ttyio$(OBJ):   ttyio.c $(ZIP_H) crypt.h ttyio.h
+
+os2zip$(OBJ):  os2/os2zip.c $(ZIP_H) os2/os2zip.h os2/os2acl.h
+       $(CC) -c -I. $(CCFLAGS) os2$(DIRSEP)os2zip.c
+
+os2$(OBJ):     os2/os2.c $(ZIP_H) os2/os2zip.h
+       $(CC) -c -I. $(CCFLAGS) os2$(DIRSEP)os2.c
+
+os2acl$(OBJ):  os2/os2acl.c os2/os2acl.h
+       $(CC) -c -I. $(CCFLAGS) os2$(DIRSEP)os2acl.c
+
+msdos$(OBJ):   msdos/msdos.c $(ZIP_H)
+       $(CC) -c -I. $(CCFLAGS) msdos$(DIRSEP)msdos.c
+
+win32zip$(OBJ):        win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h
+       $(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)win32zip.c
+
+win32$(OBJ):   win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)win32.c
+
+nt$(OBJ):      win32/nt.c win32/nt.h
+       $(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)nt.c
+
+crc_i86$(OBJ): msdos/crc_i86.asm                               # 16bit only
+       $(AS) $(ASFLAGS) msdos$(AS_DIRSEP)crc_i86.asm $(ASEOL)
+
+crc_i386$(OBJ):        win32/crc_i386.asm                              # 32bit, MASM
+       $(AS) $(ASFLAGS) win32$(AS_DIRSEP)crc_i386.asm $(ASEOL)
+
+crc_gcc$(OBJ): crc_i386.S                                      # 32bit, GNU AS
+       $(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S
+
+match$(OBJ):   msdos/match.asm
+       $(AS) $(ASFLAGS) msdos$(AS_DIRSEP)match.asm $(ASEOL)
+
+match32$(OBJ): win32/match32.asm
+       $(AS) $(ASFLAGS) win32$(AS_DIRSEP)match32.asm
+
+matchgcc$(OBJ):        match.S
+       $(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ match.S
+
+zipcloak$(OBJ):        zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipnote$(OBJ): zipnote.c $(ZIP_H) revision.h
+zipsplit$(OBJ): zipsplit.c $(ZIP_H) revision.h
+
+zipfile_$(OBJ):        zipfile.c $(ZIP_H)
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ zipfile.c
+
+fileio_$(OBJ): fileio.c $(ZIP_H)
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ fileio.c
+
+util_$(OBJ):   util.c $(ZIP_H) os2/os2zip.h
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ util.c
+
+crypt_$(OBJ):  crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ crypt.c
+
+os2zip_$(OBJ): os2/os2zip.c $(ZIP_H) os2/os2zip.h
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ os2$(DIRSEP)os2zip.c
+
+msdos_$(OBJ):  msdos/msdos.c $(ZIP_H)
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ msdos$(DIRSEP)msdos.c
+
+win32_$(OBJ):  win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ win32$(DIRSEP)win32.c
+
+zip.exe: $(OBJZ) $(OBJ2) $(OBJA)
+       $(CC) $(LDFLAGS)$@ $(DEF) $(OBJZ) $(OBJ2) $(OBJA) $(LDFLAGS2)
+
+zipcloak.exe: $(OBJC)
+       $(CC) $(LDFLAGS)$@ $(DEF) $(OBJC) $(LDFLAGS2)
+
+zipnote.exe: $(OBJN)
+       $(CC) $(LDFLAGS)$@ $(DEF) $(OBJN) $(LDFLAGS2)
+
+zipsplit.exe: $(OBJS)
+       $(CC) $(LDFLAGS)$@ $(DEF) $(OBJS) $(LDFLAGS2)
diff --git a/os2/match32.asm b/os2/match32.asm
new file mode 100644 (file)
index 0000000..ef9a541
--- /dev/null
@@ -0,0 +1,175 @@
+;===========================================================================
+;  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+;
+;  See the accompanying file LICENSE, version 2004-May-22 or later
+;  (the contents of which are also included in zip.h) for terms of use.
+;  If, for some reason, both of these files are missing, the Info-ZIP license
+;  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/licen; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;===========================================================================
+;
+; match32.asm by Jean-loup Gailly.
+
+; match32.asm, optimized version of longest_match() in deflate.c
+; To be used only with 32 bit flat model. To simplify the code, the option
+; -DDYN_ALLOC is not supported.
+; This file is only optional. If you don't have an assembler, use the
+; C version (add -DNO_ASM to CFLAGS in makefile and remove match.o
+; from OBJI). If you have reduced WSIZE in zip.h, then make sure this is
+; assembled with an equivalent -DWSIZE=<whatever>.
+
+; Caution: this module works for IBM's C/C++ compiler versions 2 and 3
+; and for Watcom's 32-bit C/C++ compiler. Both pass the first (and only)
+; argument for longest_match in the EAX register, not on the stack, with
+; the default calling conventions (_System would use the stack).
+;
+;==============================================================================
+;
+; Do NOT assemble this source if external crc32 routine from zlib gets used.
+;
+    IFNDEF USE_ZLIB
+;
+        .386
+
+        name    match
+
+BSS32   segment  dword USE32 public 'BSS'
+        extrn   window       : byte
+        extrn   prev         : word
+        extrn   prev_length  : dword
+        extrn   strstart     : dword
+        extrn   match_start  : dword
+        extrn   max_chain_length : dword
+        extrn   good_match   : dword
+        extrn   nice_match   : dword
+BSS32   ends
+
+CODE32  segment dword USE32 public 'CODE'
+        assume cs:CODE32, ds:FLAT, ss:FLAT
+
+        public  match_init
+        public  longest_match
+
+    ifndef      WSIZE
+        WSIZE         equ 32768         ; keep in sync with zip.h !
+    endif
+        MIN_MATCH     equ 3
+        MAX_MATCH     equ 258
+        MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
+        MAX_DIST      equ (WSIZE-MIN_LOOKAHEAD)
+
+; initialize or check the variables used in match.asm.
+
+match_init proc near
+        ret
+match_init endp
+
+; -----------------------------------------------------------------------
+; Set match_start to the longest match starting at the given string and
+; return its length. Matches shorter or equal to prev_length are discarded,
+; in which case the result is equal to prev_length and match_start is
+; garbage.
+; IN assertions: cur_match is the head of the hash chain for the current
+;   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+
+; int longest_match(cur_match)
+
+longest_match proc near
+
+        ; return address                ; esp+16
+        push    ebp                     ; esp+12
+        push    edi                     ; esp+8
+        push    esi                     ; esp+4
+
+        lea     ebx,window
+        add     ebx,2
+        window_off equ dword ptr [esp]
+        push    ebx                     ; esp
+
+;       match        equ esi
+;       scan         equ edi
+;       chain_length equ ebp
+;       best_len     equ ebx
+;       limit        equ edx
+
+        mov     esi,eax                 ; cur_match
+        mov     edx,strstart
+        mov     ebp,max_chain_length    ; chain_length = max_chain_length
+        mov     edi,edx
+        sub     edx,MAX_DIST            ; limit = strstart-MAX_DIST
+        cld                             ; string ops increment esi and edi
+        jae     short limit_ok
+        sub     edx,edx                 ; limit = NIL
+limit_ok:
+        add     edi,window_off          ; edi = offset(window + strstart + 2)
+        mov     ebx,prev_length         ; best_len = prev_length
+        mov     cx,[edi-2]              ; cx = scan[0..1]
+        mov     ax,[ebx+edi-3]          ; ax = scan[best_len-1..best_len]
+        cmp     ebx,good_match          ; do we have a good match already?
+        jb      do_scan
+        shr     ebp,2                   ; chain_length >>= 2
+        jmp     short do_scan
+
+        align   4                       ; align destination of branch
+long_loop:
+; at this point, edi == scan+2, esi == cur_match
+        mov     ax,[ebx+edi-3]          ; ax = scan[best_len-1..best_len]
+        mov     cx,[edi-2]              ; cx = scan[0..1]
+short_loop:
+; at this point, edi == scan+2, esi == cur_match,
+; ax = scan[best_len-1..best_len] and cx = scan[0..1]
+        and     esi,WSIZE-1             ; not needed if WSIZE=32768
+        dec     ebp                     ; --chain_length
+        shl     esi,1                   ; cur_match as word index
+        mov     si,prev[esi]            ; cur_match = prev[cur_match]
+                                        ; top word of esi is still 0
+        jz      the_end
+        cmp     esi,edx                 ; cur_match <= limit ?
+        jbe     short the_end
+do_scan:
+        cmp     ax,word ptr window[ebx+esi-1]   ; check match at best_len-1
+        jne     short_loop
+        cmp     cx,word ptr window[esi]         ; check min_match_length match
+        jne     short_loop
+
+        add     esi,window_off          ; esi = match
+        mov     ecx,(MAX_MATCH-2)/2     ; scan for at most MAX_MATCH bytes
+        mov     eax,edi                 ; eax = scan+2
+        repe    cmpsw                   ; loop until mismatch
+        je      maxmatch                ; match of length MAX_MATCH?
+mismatch:
+        mov     cl,[edi-2]              ; mismatch on first or second byte?
+        xchg    eax,edi                 ; edi = scan+2, eax = end of scan
+        sub     cl,[esi-2]              ; cl = 0 if first bytes equal
+        sub     eax,edi                 ; eax = len
+        sub     esi,window_off          ; esi = match - (2 + offset(window))
+        sub     esi,eax                 ; esi = cur_match (= match - len)
+        sub     cl,1                    ; set carry if cl == 0 (can't use DEC)
+        adc     eax,0                   ; eax = carry ? len+1 : len
+        cmp     eax,ebx                 ; len > best_len ?
+        jle     long_loop
+        mov     match_start,esi         ; match_start = cur_match
+        mov     ebx,eax                 ; ebx = best_len = len
+    ifdef FULL_SEARCH
+        cmp     eax,MAX_MATCH           ; len >= MAX_MATCH ?
+    else
+        cmp     eax,nice_match          ; len >= nice_match ?
+    endif
+        jl      long_loop
+the_end:
+        mov     eax,ebx                 ; result = eax = best_len
+        pop     ebx
+        pop     esi
+        pop     edi
+        pop     ebp
+        ret
+maxmatch:                               ; come here if maximum match
+        cmpsb                           ; increment esi and edi
+        jmp     mismatch                ; force match_length = MAX_LENGTH
+
+longest_match endp
+
+CODE32  ends
+;
+    ENDIF ; !USE_ZLIB
+;
+        end
diff --git a/os2/os2.c b/os2/os2.c
new file mode 100644 (file)
index 0000000..355eea8
--- /dev/null
+++ b/os2/os2.c
@@ -0,0 +1,481 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include "zip.h"
+
+#ifndef UTIL    /* the companion #endif is a bit of ways down ... */
+
+#include <time.h>
+#if defined(__IBMC__) || defined(MSC)
+#include <direct.h>
+#endif
+
+/* Extra malloc() space in names for cutpath() */
+#define PAD 0
+#define PATH_END '/'
+
+
+#include "os2zip.h"
+
+/* Library functions not in (most) header files */
+
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+/* Local functions */
+local char *readd OF((DIR *));
+
+
+local char *readd(d)
+DIR *d;                 /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+   no more entries or an error occurs. */
+{
+  struct dirent *e;
+
+  e = readdir(d);
+  return e == NULL ? (char *) NULL : e->d_name;
+}
+
+int wild(w)
+char *w;                /* path/pattern to match */
+/* If not in exclude mode, expand the pattern based on the contents of the
+   file system.  Return an error code in the ZE_ class. */
+{
+  DIR *d;               /* stream for reading directory */
+  char *e;              /* name found in directory */
+  int r;                /* temporary variable */
+  char *n;              /* constructed name from directory */
+  int f;                /* true if there was a match */
+  char *a;              /* alloc'ed space for name */
+  char *p;              /* path */
+  char *q;              /* name */
+  char v[5];            /* space for device current directory */
+
+  if (volume_label == 1) {
+    volume_label = 2;
+    label = getVolumeLabel((w != NULL && w[1] == ':') ? to_up(w[0]) : '\0',
+                           &label_time, &label_mode, &label_utim);
+    if (label != NULL) {
+       newname(label, 0, 0);
+    }
+    if (w == NULL || (w[1] == ':' && w[2] == '\0')) return ZE_OK;
+    /* "zip -$ foo a:" can be used to force drive name */
+  }
+
+  if (w == NULL)
+    return ZE_OK;
+
+  /* special handling of stdin request */
+  if (strcmp(w, "-") == 0)   /* if compressing stdin */
+    return newname(w, 0, 0);
+
+  /* Allocate and copy pattern */
+  if ((p = a = malloc(strlen(w) + 1)) == NULL)
+    return ZE_MEM;
+  strcpy(p, w);
+
+  /* catch special case: treat "*.*" as "*" for DOS-impaired people */
+  r = strlen(p);
+  if (strcmp(p + r - 3, "*.*") == 0)
+    p[r - 2] = '\0';
+
+  /* Normalize path delimiter as '/'. */
+  for (q = p; *q; q++)                  /* use / consistently */
+    if (*q == '\\')
+      *q = '/';
+
+  /* Only name can have special matching characters */
+  if ((q = isshexp(p)) != NULL &&
+      (strrchr(q, '/') != NULL || strrchr(q, ':') != NULL))
+  {
+    free((zvoid *)a);
+    return ZE_PARMS;
+  }
+
+  /* Separate path and name into p and q */
+  if ((q = strrchr(p, '/')) != NULL && (q == p || q[-1] != ':'))
+  {
+    *q++ = '\0';                        /* path/name -> path, name */
+    if (*p == '\0')                     /* path is just / */
+      p = strcpy(v, "/.");
+  }
+  else if ((q = strrchr(p, ':')) != NULL)
+  {                                     /* has device and no or root path */
+    *q++ = '\0';
+    p = strcat(strcpy(v, p), ":");      /* copy device as path */
+    if (*q == '/')                      /* -> device:/., name */
+    {
+      strcat(p, "/");
+      q++;
+    }
+    strcat(p, ".");
+  }
+  else if (recurse && (strcmp(p, ".") == 0 ||  strcmp(p, "..") == 0))
+  {                                    /* current or parent directory */
+    /* I can't understand Mark's code so I am adding a hack here to get
+     * "zip -r foo ." to work. Allow the dubious "zip -r foo .." but
+     * reject "zip -rm foo ..".
+     */
+    if (dispose && strcmp(p, "..") == 0)
+       ziperr(ZE_PARMS, "cannot remove parent directory");
+    q = "*";
+  }
+  else                                  /* no path or device */
+  {
+    q = p;
+    p = strcpy(v, ".");
+  }
+  if (recurse && *q == '\0') {
+    q = "*";
+  }
+  /* Search that level for matching names */
+  if ((d = opendir(p)) == NULL)
+  {
+    free((zvoid *)a);
+    return ZE_MISS;
+  }
+  if ((r = strlen(p)) > 1 &&
+      (strcmp(p + r - 2, ":.") == 0 || strcmp(p + r - 2, "/.") == 0))
+    *(p + r - 1) = '\0';
+  f = 0;
+  while ((e = readd(d)) != NULL) {
+    if (strcmp(e, ".") && strcmp(e, "..") && MATCH(q, e, 0))
+    {
+      f = 1;
+      if (strcmp(p, ".") == 0) {                /* path is . */
+        r = procname(e, 0);                     /* name is name */
+        if (r) {
+           f = 0;
+           break;
+        }
+      } else
+      {
+        if ((n = malloc(strlen(p) + strlen(e) + 2)) == NULL)
+        {
+          free((zvoid *)a);
+          closedir(d);
+          return ZE_MEM;
+        }
+        n = strcpy(n, p);
+        if (n[r = strlen(n) - 1] != '/' && n[r] != ':')
+          strcat(n, "/");
+        r = procname(strcat(n, e), 0);          /* name is path/name */
+        free((zvoid *)n);
+        if (r) {
+          f = 0;
+          break;
+        }
+      }
+    }
+  }
+  closedir(d);
+
+  /* Done */
+  free((zvoid *)a);
+  return f ? ZE_OK : ZE_MISS;
+}
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  char *a;              /* path and name for recursion */
+  DIR *d;               /* directory stream from opendir() */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+
+  if (n == NULL)        /* volume_label request in freshen|delete mode ?? */
+    return ZE_OK;
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (LSSTAT(n, &s)
+#if defined(__TURBOC__) || defined(__WATCOMC__)
+           /* For these 2 compilers, stat() succeeds on wild card names! */
+           || isshexp(n)
+#endif
+          )
+  {
+    /* Not a file or directory--search for shell expression in zip file */
+    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+  for (p = n; *p; p++)          /* use / consistently */
+    if (*p == '\\')
+      *p = '/';
+  if ((s.st_mode & S_IFDIR) == 0)
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  } else {
+    /* Add trailing / to the directory name */
+    if ((p = malloc(strlen(n)+2)) == NULL)
+      return ZE_MEM;
+    if (strcmp(n, ".") == 0 || strcmp(n, "/.") == 0) {
+      *p = '\0';  /* avoid "./" prefix and do not create zip entry */
+    } else {
+      strcpy(p, n);
+      a = p + strlen(p);
+      if (a[-1] != '/')
+        strcpy(a, "/");
+      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+        free((zvoid *)p);
+        return m;
+      }
+    }
+    /* recurse into directory */
+    if (recurse && (d = opendir(n)) != NULL)
+    {
+      while ((e = readd(d)) != NULL) {
+        if (strcmp(e, ".") && strcmp(e, ".."))
+        {
+          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+          {
+            closedir(d);
+            free((zvoid *)p);
+            return ZE_MEM;
+          }
+          strcat(strcpy(a, p), e);
+          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
+          {
+            if (m == ZE_MISS)
+              zipwarn("name not matched: ", a);
+            else
+              ziperr(m, a);
+          }
+          free((zvoid *)a);
+        }
+      }
+      closedir(d);
+    }
+    free((zvoid *)p);
+  } /* (s.st_mode & S_IFDIR) == 0) */
+  return ZE_OK;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t;              /* shortened name */
+  int dosflag;
+
+  dosflag = dosify || IsFileSystemFAT(x) || (x == label);
+  if (!dosify && use_longname_ea && (t = GetLongPathEA(x)) != NULL)
+  {
+    x = t;
+    dosflag = 0;
+  }
+
+  /* Find starting point in name before doing malloc */
+  /* Strip drive specification */
+  t = *x && *(x + 1) == ':' ? x + 2 : x;
+  /* Strip "//host/share/" part of a UNC name */
+  if ((!strncmp(x,"//",2) || !strncmp(x,"\\\\",2)) &&
+      (x[2] != '\0' && x[2] != '/' && x[2] != '\\')) {
+    n = x + 2;
+    while (*n != '\0' && *n != '/' && *n != '\\')
+      n++;              /* strip host name */
+    if (*n != '\0') {
+      n++;
+      while (*n != '\0' && *n != '/' && *n != '\\')
+        n++;            /* strip `share' name */
+    }
+    if (*n != '\0')
+      t = n + 1;
+  }
+  /* Strip leading "/" to convert an absolute path into a relative path */
+  while (*t == '/' || *t == '\\')
+    t++;
+  /* Strip leading "./" as well as drive letter */
+  while (*t == '.' && (t[1] == '/' || t[1] == '\\'))
+    t += 2;
+
+  /* Make changes, if any, to the copied name (leave original intact) */
+  for (n = t; *n; n++)
+    if (*n == '\\')
+      *n = '/';
+
+  if (!pathput)
+    t = last(t, PATH_END);
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL)
+    return NULL;
+  strcpy(n, t);
+
+  if (dosify)
+    msname(n);
+
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+  return n;
+}
+
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+
+  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+    return NULL;
+  strcpy(x, n);
+
+  return x;
+}
+
+
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+  SetFileTime(f, d);
+}
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  char *name;
+  ulg r;
+  unsigned int len = strlen(f);
+  int isstdin = !strcmp(f, "-");
+
+  if (f == label) {
+    if (a != NULL)
+      *a = label_mode;
+    if (n != NULL)
+      *n = -2L; /* convention for a label name */
+    if (t != NULL)
+      t->atime = t->mtime = t->ctime = label_utim;
+    return label_time;
+  }
+
+  if ((name = malloc(len + 1)) == NULL) {
+    ZIPERR(ZE_MEM, "filetime");
+  }
+  strcpy(name, f);
+  if (name[len - 1] == '/')
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+
+  if (isstdin) {
+    /* it is common for some PC based compilers to
+       fail with fstat() on devices or pipes */
+    if (fstat(fileno(stdin), &s) != 0) {
+      s.st_mode = S_IFREG; s.st_size = -1L;
+    }
+    time(&s.st_ctime);
+    s.st_atime = s.st_mtime = s.st_ctime;
+  } else if (LSSTAT(name, &s) != 0) {
+             /* Accept about any file kind including directories
+              * (stored with trailing / with -r option)
+              */
+    free(name);
+    return 0;
+  }
+
+  if (a != NULL) {
+    *a = ((ulg)s.st_mode << 16) | (isstdin ? 0L : (ulg)GetFileMode(name));
+  }
+  if (n != NULL)
+    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+#ifdef __WATCOMC__
+  /* of course, Watcom always has to make an exception */
+  if (s.st_atime == 312764400)
+    s.st_atime = s.st_mtime;
+  if (s.st_ctime == 312764400)
+    s.st_ctime = s.st_mtime;
+#endif
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = s.st_ctime;
+  }
+
+  r = GetFileTime(name);
+  free(name);
+
+  return r;
+}
+
+int deletedir(d)
+char *d;                /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+   Return the result of rmdir(), delete(), or system().
+ */
+{
+    return rmdir(d);
+}
+
+
+#if defined MY_ZCALLOC /* Special zcalloc function for MEMORY16 (MSDOS/OS2) */
+
+#ifdef MSC  /* Microsoft C */
+
+zvoid far *zcalloc (unsigned items, unsigned size)
+{
+    return (zvoid far *)halloc((long)items, size);
+}
+
+zvoid zcfree (zvoid far *ptr)
+{
+    hfree((void huge *)ptr);
+}
+
+#endif /* MSC */
+
+#endif /* MY_ZCALLOC */
+
+#endif /* !UTIL */
diff --git a/os2/os2acl.c b/os2/os2acl.c
new file mode 100644 (file)
index 0000000..7c5b1fd
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* os2acl.c - access to OS/2 (LAN Server) ACLs
+ *
+ * Author:  Kai Uwe Rommel <rommel@ars.de>
+ * Created: Mon Aug 08 1994
+ *
+ */
+
+/*
+ * supported 32-bit compilers:
+ * - emx+gcc
+ * - IBM C Set++ 2.1 or newer
+ * - Watcom C/C++ 10.0 or newer
+ *
+ * supported 16-bit compilers:
+ * - MS C 6.00A
+ * - Watcom C/C++ 10.0 or newer
+ *
+ * supported OS/2 LAN environments:
+ * - IBM LAN Server/Requester 3.0, 4.0 and 5.0 (Warp Server)
+ * - IBM Peer 1.0 (Warp Connect)
+ */
+
+#ifdef KUR
+   static char *rcsid =
+   "$Id: os2acl.c,v 1.3 1996/04/03 19:18:27 rommel Exp rommel $";
+   static char *rcsrev = "$Revision: 1.3 $";
+#endif
+
+/*
+ * $Log: os2acl.c,v $
+ * Revision 1.3  1996/04/03 19:18:27  rommel
+ * minor fixes
+ *
+ * Revision 1.2  1996/03/30 22:03:52  rommel
+ * avoid frequent dynamic allocation for every call
+ * streamlined code
+ *
+ * Revision 1.1  1996/03/30 09:35:00  rommel
+ * Initial revision
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <malloc.h>
+
+#define INCL_NOPM
+#define INCL_DOS
+#define INCL_DOSERRORS
+#include <os2.h>
+
+#include "os2/os2acl.h"
+
+#define UNLEN 20
+
+#if defined(__WATCOMC__) && defined(__386__) && !defined(__32BIT__)
+#define __32BIT__
+#endif
+
+#ifdef __32BIT__
+typedef ULONG U_INT;
+#ifdef __EMX__
+#define PSTR16 _far16ptr
+#define PTR16(x) _emx_32to16(x)
+#else /* other 32-bit */
+#define PSTR16 PCHAR16
+#define PTR16(x) ((PCHAR16)(x))
+#endif
+#else /* 16-bit */
+typedef USHORT U_INT;
+#define PSTR16 PSZ
+#define PTR16(x) (x)
+#endif
+
+typedef struct access_list
+{
+  char acl_ugname[UNLEN+1];
+  char acl_pad;
+  USHORT acl_access;
+}
+ACCLIST;
+
+typedef struct access_info
+{
+  PSTR16 acc_resource_name;
+  USHORT acc_attr;
+  USHORT acc_count;
+}
+ACCINFO;
+
+static ACCINFO *ai;
+static char *path, *data;
+
+#ifdef __32BIT__
+
+#ifdef __EMX__
+
+static USHORT (APIENTRY *_NetAccessGetInfo)(PSZ pszServer, PSZ pszResource,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail);
+static USHORT (APIENTRY *_NetAccessSetInfo)(PSZ pszServer, PSZ pszResource,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum);
+static USHORT (APIENTRY *_NetAccessAdd)(PSZ pszServer,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer);
+
+USHORT NetAccessGetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel,
+                        PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail)
+{
+  return (USHORT)
+          (_THUNK_PROLOG (4+4+2+4+2+4);
+           _THUNK_FLAT (pszServer);
+           _THUNK_FLAT (pszResource);
+           _THUNK_SHORT (sLevel);
+           _THUNK_FLAT (pbBuffer);
+           _THUNK_SHORT (cbBuffer);
+           _THUNK_FLAT (pcbTotalAvail);
+           _THUNK_CALLI (_emx_32to16(_NetAccessGetInfo)));
+}
+
+USHORT NetAccessSetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel,
+                        PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum)
+{
+  return (USHORT)
+          (_THUNK_PROLOG (4+4+2+4+2+2);
+           _THUNK_FLAT (pszServer);
+           _THUNK_FLAT (pszResource);
+           _THUNK_SHORT (sLevel);
+           _THUNK_FLAT (pbBuffer);
+           _THUNK_SHORT (cbBuffer);
+           _THUNK_SHORT (sParmNum);
+           _THUNK_CALLI (_emx_32to16(_NetAccessSetInfo)));
+}
+
+USHORT NetAccessAdd(PSZ pszServer, USHORT sLevel,
+                    PVOID pbBuffer, USHORT cbBuffer)
+{
+  return (USHORT)
+          (_THUNK_PROLOG (4+2+4+2);
+           _THUNK_FLAT (pszServer);
+           _THUNK_SHORT (sLevel);
+           _THUNK_FLAT (pbBuffer);
+           _THUNK_SHORT (cbBuffer);
+           _THUNK_CALLI (_emx_32to16(_NetAccessAdd)));
+}
+
+#else /* other 32-bit */
+
+APIRET16 (* APIENTRY16 NetAccessGetInfo)(PCHAR16 pszServer, PCHAR16 pszResource,
+  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, PVOID16 pcbTotalAvail);
+APIRET16 (* APIENTRY16 NetAccessSetInfo)(PCHAR16 pszServer, PCHAR16 pszResource,
+  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, USHORT sParmNum);
+APIRET16 (* APIENTRY16 NetAccessAdd)(PCHAR16 pszServer,
+  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer);
+
+#define _NetAccessGetInfo NetAccessGetInfo
+#define _NetAccessSetInfo NetAccessSetInfo
+#define _NetAccessAdd NetAccessAdd
+
+#if !defined(__IBMC__) || !defined(__TILED__)
+#define _tmalloc malloc
+#define _tfree free
+#endif
+
+#endif
+#else /* 16-bit */
+
+USHORT (APIENTRY *NetAccessGetInfo)(PSZ pszServer, PSZ pszResource,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail);
+USHORT (APIENTRY *NetAccessSetInfo)(PSZ pszServer, PSZ pszResource,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum);
+USHORT (APIENTRY *NetAccessAdd)(PSZ pszServer,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer);
+
+#define _NetAccessGetInfo NetAccessGetInfo
+#define _NetAccessSetInfo NetAccessSetInfo
+#define _NetAccessAdd NetAccessAdd
+
+#define _tmalloc malloc
+#define _tfree free
+
+#define DosQueryProcAddr(handle, ord, name, funcptr) \
+        DosGetProcAddr(handle, name, funcptr)
+#define DosQueryCurrentDir DosQCurDir
+#define DosQueryCurrentDisk DosQCurDisk
+
+#endif
+
+
+static BOOL acl_init(void)
+{
+  static BOOL initialized, netapi_avail;
+  HMODULE netapi;
+  char buf[256];
+
+  if (initialized)
+    return netapi_avail;
+
+  initialized = TRUE;
+
+  if (DosLoadModule(buf, sizeof(buf), "NETAPI", &netapi))
+    return FALSE;
+
+  if (DosQueryProcAddr(netapi, 0, "NETACCESSGETINFO", (PFN *) &_NetAccessGetInfo) ||
+      DosQueryProcAddr(netapi, 0, "NETACCESSSETINFO", (PFN *) &_NetAccessSetInfo) ||
+      DosQueryProcAddr(netapi, 0, "NETACCESSADD", (PFN *) &_NetAccessAdd))
+    return FALSE;
+
+#if defined(__WATCOMC__) && defined(__386__)
+  NetAccessGetInfo = (PVOID) (ULONG) (PVOID16) NetAccessGetInfo;
+  NetAccessSetInfo = (PVOID) (ULONG) (PVOID16) NetAccessSetInfo;
+  NetAccessAdd     = (PVOID) (ULONG) (PVOID16) NetAccessAdd;
+#endif
+
+  if ((path = _tmalloc(CCHMAXPATH)) == NULL)
+    return FALSE;
+  if ((data = _tmalloc(ACL_BUFFERSIZE)) == NULL)
+    return FALSE;
+  if ((ai = _tmalloc(sizeof(ACCINFO))) == NULL)
+    return -1;
+
+  netapi_avail = TRUE;
+
+  return netapi_avail;
+}
+
+static void acl_mkpath(char *buffer, const char *source)
+{
+  char *ptr;
+  static char cwd[CCHMAXPATH];
+  static U_INT cwdlen;
+  U_INT cdrive;
+  ULONG drivemap;
+
+  if (isalpha(source[0]) && source[1] == ':')
+    buffer[0] = 0; /* fully qualified names */
+  else
+  {
+    if (cwd[0] == 0)
+    {
+      DosQueryCurrentDisk(&cdrive, &drivemap);
+      cwd[0] = (char)(cdrive + '@');
+      cwd[1] = ':';
+      cwd[2] = '\\';
+      cwdlen = sizeof(cwd) - 3;
+      DosQueryCurrentDir(0, cwd + 3, &cwdlen);
+      cwdlen = strlen(cwd);
+    }
+
+    if (source[0] == '/' || source[0] == '\\')
+    {
+      if (source[1] == '/' || source[1] == '\\')
+        buffer[0] = 0; /* UNC names */
+      else
+      {
+        strncpy(buffer, cwd, 2);
+        buffer[2] = 0;
+      }
+    }
+    else
+    {
+      strcpy(buffer, cwd);
+      if (cwd[cwdlen - 1] != '\\' && cwd[cwdlen - 1] != '/')
+        strcat(buffer, "/");
+    }
+  }
+
+  strcat(buffer, source);
+
+  for (ptr = buffer; *ptr; ptr++)
+    if (*ptr == '/')
+      *ptr = '\\';
+
+  if (ptr[-1] == '\\')
+    ptr[-1] = 0;
+
+  strupr(buffer);
+}
+
+static int acl_bin2text(char *data, char *text)
+{
+  ACCINFO *ai;
+  ACCLIST *al;
+  U_INT cnt, offs;
+
+  ai = (ACCINFO *) data;
+  al = (ACCLIST *) (data + sizeof(ACCINFO));
+
+  offs = sprintf(text, "ACL1:%X,%d\n",
+                 ai -> acc_attr, ai -> acc_count);
+
+  for (cnt = 0; cnt < ai -> acc_count; cnt++)
+    offs += sprintf(text + offs, "%s,%X\n",
+                    al[cnt].acl_ugname, al[cnt].acl_access);
+
+  return strlen(text);
+}
+
+int acl_get(char *server, const char *resource, char *buffer)
+{
+  USHORT datalen;
+  PSZ srv = NULL;
+  int rc;
+
+  if (!acl_init())
+    return -1;
+
+  if (server)
+    srv = server;
+
+  acl_mkpath(path, resource);
+  datalen = 0;
+
+  rc = NetAccessGetInfo(srv, path, 1, data, ACL_BUFFERSIZE, &datalen);
+
+  if (rc == 0)
+    acl_bin2text(data, buffer);
+
+  return rc;
+}
+
+static int acl_text2bin(char *data, char *text, char *path)
+{
+  ACCINFO *ai;
+  ACCLIST *al;
+  char *ptr, *ptr2;
+  U_INT cnt;
+
+  ai = (ACCINFO *) data;
+  ai -> acc_resource_name = PTR16(path);
+
+  if (sscanf(text, "ACL1:%hX,%hd",
+             &ai -> acc_attr, &ai -> acc_count) != 2)
+    return ERROR_INVALID_PARAMETER;
+
+  al = (ACCLIST *) (data + sizeof(ACCINFO));
+  ptr = strchr(text, '\n') + 1;
+
+  for (cnt = 0; cnt < ai -> acc_count; cnt++)
+  {
+    ptr2 = strchr(ptr, ',');
+    strncpy(al[cnt].acl_ugname, ptr, ptr2 - ptr);
+    al[cnt].acl_ugname[ptr2 - ptr] = 0;
+    sscanf(ptr2 + 1, "%hx", &al[cnt].acl_access);
+    ptr = strchr(ptr, '\n') + 1;
+  }
+
+  return sizeof(ACCINFO) + ai -> acc_count * sizeof(ACCLIST);
+}
+
+int acl_set(char *server, const char *resource, char *buffer)
+{
+  USHORT datalen;
+  PSZ srv = NULL;
+
+  if (!acl_init())
+    return -1;
+
+  if (server)
+    srv = server;
+
+  acl_mkpath(path, resource);
+
+  ai -> acc_resource_name = PTR16(path);
+  ai -> acc_attr = 0;
+  ai -> acc_count = 0;
+
+  NetAccessAdd(srv, 1, ai, sizeof(ACCINFO));
+  /* Ignore any errors, most probably because ACL already exists. */
+  /* In any such case, try updating the existing ACL. */
+
+  datalen = acl_text2bin(data, buffer, path);
+
+  return NetAccessSetInfo(srv, path, 1, data, datalen, 0);
+}
+
+/* end of os2acl.c */
diff --git a/os2/os2acl.h b/os2/os2acl.h
new file mode 100644 (file)
index 0000000..dd34b2d
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, all these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* os2acl.h
+ *
+ * Author:  Kai Uwe Rommel <rommel@ars.de>
+ * Created: Fri Mar 29 1996
+ */
+
+/* $Id: os2acl.h,v 1.1 1996/03/30 09:35:00 rommel Exp rommel $ */
+
+/*
+ * $Log: os2acl.h,v $
+ * Revision 1.1  1996/03/30 09:35:00  rommel
+ * Initial revision
+ *
+ */
+
+#ifndef _OS2ACL_H
+#define _OS2ACL_H
+
+#define ACL_BUFFERSIZE 4096
+
+int acl_get(char *server, const char *resource, char *buffer);
+int acl_set(char *server, const char *resource, char *buffer);
+
+#endif /* _OS2ACL_H */
+
+/* end of os2acl.h */
diff --git a/os2/os2zip.c b/os2/os2zip.c
new file mode 100644 (file)
index 0000000..83bc3bc
--- /dev/null
@@ -0,0 +1,1213 @@
+/*
+ * @(#)dir.c 1.4 87/11/06 Public Domain.
+ *
+ *  A public domain implementation of BSD directory routines for
+ *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
+ *  August 1987
+ *
+ *  Ported to OS/2 by Kai Uwe Rommel
+ *  Addition of other OS/2 file system specific code
+ *  Placed into the public domain
+ */
+
+/* does also contain EA access code for use in ZIP */
+
+
+#ifdef OS2
+
+
+#if defined(__EMX__) && !defined(__32BIT__)
+#  define __32BIT__
+#endif
+
+#include "zip.h"
+
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#ifndef __BORLANDC__
+#include <malloc.h>
+#endif
+
+#define INCL_NOPM
+#define INCL_DOSNLS
+#define INCL_DOSERRORS
+#include <os2.h>
+
+#include "os2zip.h"
+#include "os2acl.h"
+
+
+#ifndef max
+#define max(a, b) ((a) < (b) ? (b) : (a))
+#endif
+
+
+#ifdef __32BIT__
+#define DosFindFirst(p1, p2, p3, p4, p5, p6) \
+        DosFindFirst(p1, p2, p3, p4, p5, p6, 1)
+#else
+#define DosQueryCurrentDisk DosQCurDisk
+#define DosQueryFSAttach(p1, p2, p3, p4, p5) \
+        DosQFSAttach(p1, p2, p3, p4, p5, 0)
+#define DosQueryFSInfo(d, l, b, s) \
+        DosQFSInfo(d, l, b, s)
+#define DosQueryPathInfo(p1, p2, p3, p4) \
+        DosQPathInfo(p1, p2, p3, p4, 0)
+#define DosSetPathInfo(p1, p2, p3, p4, p5) \
+        DosSetPathInfo(p1, p2, p3, p4, p5, 0)
+#define DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7) \
+        DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7, 0)
+#define DosFindFirst(p1, p2, p3, p4, p5, p6) \
+        DosFindFirst(p1, p2, p3, p4, p5, p6, 0)
+#define DosMapCase DosCaseMap
+#endif
+
+
+#ifndef UTIL
+
+extern int noisy;
+
+#ifndef S_IFMT
+#define S_IFMT 0xF000
+#endif
+
+static int attributes = _A_DIR | _A_HIDDEN | _A_SYSTEM;
+
+static char *getdirent(char *);
+static void free_dircontents(struct _dircontents *);
+
+#ifdef __32BIT__
+static HDIR hdir;
+static ULONG count;
+static FILEFINDBUF3 find;
+#else
+static HDIR hdir;
+static USHORT count;
+static FILEFINDBUF find;
+#endif
+
+DIR *opendir(const char *name)
+{
+  struct stat statb;
+  DIR *dirp;
+  char c;
+  char *s;
+  struct _dircontents *dp;
+  char nbuf[MAXPATHLEN + 1];
+  int len;
+
+  attributes = hidden_files ? (_A_DIR | _A_HIDDEN | _A_SYSTEM) : _A_DIR;
+
+  strcpy(nbuf, name);
+  if ((len = strlen(nbuf)) == 0)
+    return NULL;
+
+  if (((c = nbuf[len - 1]) == '\\' || c == '/') && (len > 1))
+  {
+    nbuf[len - 1] = 0;
+    --len;
+
+    if (nbuf[len - 1] == ':')
+    {
+      strcpy(nbuf+len, "\\.");
+      len += 2;
+    }
+  }
+  else
+    if (nbuf[len - 1] == ':')
+    {
+      strcpy(nbuf+len, ".");
+      ++len;
+    }
+
+#ifndef __BORLANDC__
+  /* when will we ever see a Borland compiler that can properly stat !!! */
+  if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
+    return NULL;
+#endif
+
+  if ((dirp = malloc(sizeof(DIR))) == NULL)
+    return NULL;
+
+  if (nbuf[len - 1] == '.' && (len == 1 || nbuf[len - 2] != '.'))
+    strcpy(nbuf+len-1, "*.*");
+  else
+    if (((c = nbuf[len - 1]) == '\\' || c == '/') && (len == 1))
+      strcpy(nbuf+len, "*");
+    else
+      strcpy(nbuf+len, "\\*");
+
+  /* len is no longer correct (but no longer needed) */
+
+  dirp -> dd_loc = 0;
+  dirp -> dd_contents = dirp -> dd_cp = NULL;
+
+  if ((s = getdirent(nbuf)) == NULL)
+    return dirp;
+
+  do
+  {
+    if (((dp = malloc(sizeof(struct _dircontents))) == NULL) ||
+        ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL)      )
+    {
+      if (dp)
+        free(dp);
+      free_dircontents(dirp -> dd_contents);
+
+      return NULL;
+    }
+
+    if (dirp -> dd_contents)
+    {
+      dirp -> dd_cp -> _d_next = dp;
+      dirp -> dd_cp = dirp -> dd_cp -> _d_next;
+    }
+    else
+      dirp -> dd_contents = dirp -> dd_cp = dp;
+
+    strcpy(dp -> _d_entry, s);
+    dp -> _d_next = NULL;
+
+    dp -> _d_size = find.cbFile;
+    dp -> _d_mode = find.attrFile;
+    dp -> _d_time = *(unsigned *) &(find.ftimeLastWrite);
+    dp -> _d_date = *(unsigned *) &(find.fdateLastWrite);
+  }
+  while ((s = getdirent(NULL)) != NULL);
+
+  dirp -> dd_cp = dirp -> dd_contents;
+
+  return dirp;
+}
+
+void closedir(DIR * dirp)
+{
+  free_dircontents(dirp -> dd_contents);
+  free(dirp);
+}
+
+struct dirent *readdir(DIR * dirp)
+{
+  static struct dirent dp;
+
+  if (dirp -> dd_cp == NULL)
+    return NULL;
+
+  dp.d_namlen = dp.d_reclen =
+    strlen(strcpy(dp.d_name, dirp -> dd_cp -> _d_entry));
+
+  dp.d_ino = 0;
+
+  dp.d_size = dirp -> dd_cp -> _d_size;
+  dp.d_mode = dirp -> dd_cp -> _d_mode;
+  dp.d_time = dirp -> dd_cp -> _d_time;
+  dp.d_date = dirp -> dd_cp -> _d_date;
+
+  dirp -> dd_cp = dirp -> dd_cp -> _d_next;
+  dirp -> dd_loc++;
+
+  return &dp;
+}
+
+void seekdir(DIR * dirp, long off)
+{
+  long i = off;
+  struct _dircontents *dp;
+
+  if (off >= 0)
+  {
+    for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next);
+
+    dirp -> dd_loc = off - (i + 1);
+    dirp -> dd_cp = dp;
+  }
+}
+
+long telldir(DIR * dirp)
+{
+  return dirp -> dd_loc;
+}
+
+static void free_dircontents(struct _dircontents * dp)
+{
+  struct _dircontents *odp;
+
+  while (dp)
+  {
+    if (dp -> _d_entry)
+      free(dp -> _d_entry);
+
+    dp = (odp = dp) -> _d_next;
+    free(odp);
+  }
+}
+
+static char *getdirent(char *dir)
+{
+  int done;
+  static int lower;
+
+  if (dir != NULL)
+  {                                    /* get first entry */
+    hdir = HDIR_SYSTEM;
+    count = 1;
+    done = DosFindFirst(dir, &hdir, attributes, &find, sizeof(find), &count);
+    lower = IsFileSystemFAT(dir);
+  }
+  else                                 /* get next entry */
+    done = DosFindNext(hdir, &find, sizeof(find), &count);
+
+  if (done == 0)
+  {
+    if (lower)
+      StringLower(find.achName);
+    return find.achName;
+  }
+  else
+  {
+    DosFindClose(hdir);
+    return NULL;
+  }
+}
+
+/* FAT / HPFS detection */
+
+int IsFileSystemFAT(char *dir)
+{
+  static USHORT nLastDrive = -1, nResult;
+  ULONG lMap;
+  BYTE bData[64];
+  char bName[3];
+#ifdef __32BIT__
+  ULONG nDrive, cbData;
+  PFSQBUFFER2 pData = (PFSQBUFFER2) bData;
+#else
+  USHORT nDrive, cbData;
+  PFSQBUFFER pData = (PFSQBUFFER) bData;
+#endif
+
+  /* We separate FAT and HPFS+other file systems here.
+     at the moment I consider other systems to be similar to HPFS,
+     i.e. support long file names and being case sensitive */
+
+  if (isalpha(dir[0]) && (dir[1] == ':'))
+    nDrive = to_up(dir[0]) - '@';
+  else
+    DosQueryCurrentDisk(&nDrive, &lMap);
+
+  if (nDrive == nLastDrive)
+    return nResult;
+
+  bName[0] = (char) (nDrive + '@');
+  bName[1] = ':';
+  bName[2] = 0;
+
+  nLastDrive = nDrive;
+  cbData = sizeof(bData);
+
+  if (!DosQueryFSAttach(bName, 0, FSAIL_QUERYNAME, (PVOID) pData, &cbData))
+    nResult = !strcmp((char *) pData -> szFSDName + pData -> cbName, "FAT");
+  else
+    nResult = FALSE;
+
+  /* End of this ugly code */
+  return nResult;
+}
+
+/* access mode bits and time stamp */
+
+int GetFileMode(char *name)
+{
+#ifdef __32BIT__
+  FILESTATUS3 fs;
+  return DosQueryPathInfo(name, 1, &fs, sizeof(fs)) ? -1 : fs.attrFile;
+#else
+  USHORT mode;
+  return DosQFileMode(name, &mode, 0L) ? -1 : mode;
+#endif
+}
+
+ulg GetFileTime(char *name)
+{
+#ifdef __32BIT__
+  FILESTATUS3 fs;
+#else
+  FILESTATUS fs;
+#endif
+  USHORT nDate, nTime;
+  DATETIME dtCurrent;
+
+  if (strcmp(name, "-") == 0)
+  {
+    DosGetDateTime(&dtCurrent);
+    fs.fdateLastWrite.day     = dtCurrent.day;
+    fs.fdateLastWrite.month   = dtCurrent.month;
+    fs.fdateLastWrite.year    = dtCurrent.year - 1980;
+    fs.ftimeLastWrite.hours   = dtCurrent.hours;
+    fs.ftimeLastWrite.minutes = dtCurrent.minutes;
+    fs.ftimeLastWrite.twosecs = dtCurrent.seconds / 2;
+  }
+  else
+    if (DosQueryPathInfo(name, 1, (PBYTE) &fs, sizeof(fs)))
+      return -1;
+
+  nDate = * (USHORT *) &fs.fdateLastWrite;
+  nTime = * (USHORT *) &fs.ftimeLastWrite;
+
+  return ((ULONG) nDate) << 16 | nTime;
+}
+
+void SetFileTime(char *path, ulg stamp)
+{
+  FILESTATUS fs;
+  USHORT fd, ft;
+
+  if (DosQueryPathInfo(path, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)))
+    return;
+
+  fd = (USHORT) (stamp >> 16);
+  ft = (USHORT) stamp;
+  fs.fdateLastWrite = fs.fdateCreation = * (FDATE *) &fd;
+  fs.ftimeLastWrite = fs.ftimeCreation = * (FTIME *) &ft;
+
+  DosSetPathInfo(path, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0);
+}
+
+/* read volume label */
+
+char *getVolumeLabel(int drive, unsigned long *vtime, unsigned long *vmode,
+                     time_t *utim)
+{
+  static FSINFO fi;
+
+  if (DosQueryFSInfo(drive ? drive - 'A' + 1 : 0,
+                     FSIL_VOLSER, (PBYTE) &fi, sizeof(fi)))
+    return NULL;
+
+  time(utim);
+  *vtime = unix2dostime(utim);
+  *vmode = _A_VOLID | _A_ARCHIVE;
+
+  return (fi.vol.cch > 0) ? fi.vol.szVolLabel : NULL;
+}
+
+/* FAT / HPFS name conversion stuff */
+
+int IsFileNameValid(char *name)
+{
+  HFILE hf;
+#ifdef __32BIT__
+  ULONG uAction;
+#else
+  USHORT uAction;
+#endif
+
+  switch(DosOpen(name, &hf, &uAction, 0, 0, FILE_OPEN,
+                 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0))
+  {
+  case ERROR_INVALID_NAME:
+  case ERROR_FILENAME_EXCED_RANGE:
+    return FALSE;
+  case NO_ERROR:
+    DosClose(hf);
+  default:
+    return TRUE;
+  }
+}
+
+void ChangeNameForFAT(char *name)
+{
+  char *src, *dst, *next, *ptr, *dot, *start;
+  static char invalid[] = ":;,=+\"[]<>| \t";
+
+  if (isalpha(name[0]) && (name[1] == ':'))
+    start = name + 2;
+  else
+    start = name;
+
+  src = dst = start;
+  if ((*src == '/') || (*src == '\\'))
+    src++, dst++;
+
+  while (*src)
+  {
+    for (next = src; *next && (*next != '/') && (*next != '\\'); next++);
+
+    for (ptr = src, dot = NULL; ptr < next; ptr++)
+      if (*ptr == '.')
+      {
+        dot = ptr; /* remember last dot */
+        *ptr = '_';
+      }
+
+    if (dot == NULL)
+      for (ptr = src; ptr < next; ptr++)
+        if (*ptr == '_')
+          dot = ptr; /* remember last _ as if it were a dot */
+
+    if (dot && (dot > src) &&
+        ((next - dot <= 4) ||
+         ((next - src > 8) && (dot - src > 3))))
+    {
+      if (dot)
+        *dot = '.';
+
+      for (ptr = src; (ptr < dot) && ((ptr - src) < 8); ptr++)
+        *dst++ = *ptr;
+
+      for (ptr = dot; (ptr < next) && ((ptr - dot) < 4); ptr++)
+        *dst++ = *ptr;
+    }
+    else
+    {
+      if (dot && (next - src == 1))
+        *dot = '.';           /* special case: "." as a path component */
+
+      for (ptr = src; (ptr < next) && ((ptr - src) < 8); ptr++)
+        *dst++ = *ptr;
+    }
+
+    *dst++ = *next; /* either '/' or 0 */
+
+    if (*next)
+    {
+      src = next + 1;
+
+      if (*src == 0) /* handle trailing '/' on dirs ! */
+        *dst = 0;
+    }
+    else
+      break;
+  }
+
+  for (src = start; *src != 0; ++src)
+    if ((strchr(invalid, *src) != NULL) || (*src == ' '))
+      *src = '_';
+}
+
+/* .LONGNAME EA code */
+
+typedef struct
+{
+  ULONG cbList;               /* length of value + 22 */
+#ifdef __32BIT__
+  ULONG oNext;
+#endif
+  BYTE fEA;                   /* 0 */
+  BYTE cbName;                /* length of ".LONGNAME" = 9 */
+  USHORT cbValue;             /* length of value + 4 */
+  BYTE szName[10];            /* ".LONGNAME" */
+  USHORT eaType;              /* 0xFFFD for length-preceded ASCII */
+  USHORT eaSize;              /* length of value */
+  BYTE szValue[CCHMAXPATH];
+}
+FEALST;
+
+typedef struct
+{
+  ULONG cbList;
+#ifdef __32BIT__
+  ULONG oNext;
+#endif
+  BYTE cbName;
+  BYTE szName[10];            /* ".LONGNAME" */
+}
+GEALST;
+
+char *GetLongNameEA(const char *name)
+{
+  EAOP eaop;
+  GEALST gealst;
+  static FEALST fealst;
+  char *ptr;
+
+  eaop.fpGEAList = (PGEALIST) &gealst;
+  eaop.fpFEAList = (PFEALIST) &fealst;
+  eaop.oError = 0;
+
+  strcpy((char *) gealst.szName, ".LONGNAME");
+  gealst.cbName  = (BYTE) strlen((char *) gealst.szName);
+#ifdef __32BIT__
+  gealst.oNext   = 0;
+#endif
+
+  gealst.cbList  = sizeof(gealst);
+  fealst.cbList  = sizeof(fealst);
+
+  if (DosQueryPathInfo(name, FIL_QUERYEASFROMLIST,
+                       (PBYTE) &eaop, sizeof(eaop)))
+    return NULL;
+
+  if (fealst.cbValue > 4 && fealst.eaType == 0xFFFD)
+  {
+    fealst.szValue[fealst.eaSize] = 0;
+
+    for (ptr = fealst.szValue; *ptr; ptr++)
+      if (*ptr == '/' || *ptr == '\\')
+        *ptr = '!';
+
+    return (char *) fealst.szValue;
+  }
+
+  return NULL;
+}
+
+char *GetLongPathEA(const char *name)
+{
+  static char nbuf[CCHMAXPATH + 1];
+  char tempbuf[CCHMAXPATH + 1];
+  char *comp, *next, *ea, sep;
+  BOOL bFound = FALSE;
+
+  nbuf[0] = 0;
+  strncpy(tempbuf, name, CCHMAXPATH);
+  tempbuf[CCHMAXPATH] = '\0';
+  next = tempbuf;
+
+  while (*next)
+  {
+    comp = next;
+
+    while (*next != '\\' && *next != '/' && *next != 0)
+      next++;
+
+    sep = *next;
+    *next = 0;
+
+    ea = GetLongNameEA(tempbuf);
+    strcat(nbuf, ea ? ea : comp);
+    bFound = bFound || (ea != NULL);
+
+    if (sep)
+    {
+      strcat(nbuf, "\\");
+      *next++ = sep;
+    }
+  }
+
+  return (nbuf[0] != 0) && bFound ? nbuf : NULL;
+}
+
+/* general EA code */
+
+typedef struct
+{
+  USHORT nID;
+  USHORT nSize;
+  ULONG lSize;
+}
+EFHEADER, *PEFHEADER;
+
+#ifdef __32BIT__
+
+/* Perhaps due to bugs in the current OS/2 2.0 kernel, the success or
+   failure of the DosEnumAttribute() and DosQueryPathInfo() system calls
+   depends on the area where the return buffers are allocated. This
+   differs for the various compilers, for some alloca() works, for some
+   malloc() works, for some, both work. We'll have to live with that. */
+
+/* The use of malloc() is not very convenient, because it requires
+   backtracking (i.e. free()) at error returns. We do that for system
+   calls that may fail, but not for malloc() calls, because they are VERY
+   unlikely to fail. If ever, we just leave some memory allocated
+   over the usually short lifetime of a zip process ... */
+
+#ifdef __GNUC__
+#define alloc(x) alloca(x)
+#define unalloc(x)
+#else
+#define alloc(x) malloc(x)
+#define unalloc(x) free(x)
+#endif
+
+void GetEAs(char *path, char **bufptr, size_t *size,
+                        char **cbufptr, size_t *csize)
+{
+  FILESTATUS4 fs;
+  PDENA2 pDENA, pFound;
+  EAOP2 eaop;
+  PGEA2 pGEA;
+  PGEA2LIST pGEAlist;
+  PFEA2LIST pFEAlist;
+  PEFHEADER pEAblock;
+  ULONG ulAttributes, ulMemoryBlock;
+  ULONG nLength;
+  ULONG nBlock;
+  char szName[CCHMAXPATH];
+
+  *size = *csize = 0;
+
+  strcpy(szName, path);
+  nLength = strlen(szName);
+  if (szName[nLength - 1] == '/')
+    szName[nLength - 1] = 0;
+
+  if (DosQueryPathInfo(szName, FIL_QUERYEASIZE, (PBYTE) &fs, sizeof(fs)))
+    return;
+  nBlock = max(fs.cbList, 65535);
+  if ((pDENA = alloc((size_t) nBlock)) == NULL)
+    return;
+
+  ulAttributes = -1;
+
+  if (DosEnumAttribute(ENUMEA_REFTYPE_PATH, szName, 1, pDENA, nBlock,
+                       &ulAttributes, ENUMEA_LEVEL_NO_VALUE)
+    || ulAttributes == 0
+    || (pGEAlist = alloc((size_t) nBlock)) == NULL)
+  {
+    unalloc(pDENA);
+    return;
+  }
+
+  pGEA = pGEAlist -> list;
+  memset(pGEAlist, 0, nBlock);
+  pFound = pDENA;
+
+  while (ulAttributes--)
+  {
+    if (!(strcmp(pFound -> szName, ".LONGNAME") == 0 && use_longname_ea))
+    {
+      pGEA -> cbName = pFound -> cbName;
+      strcpy(pGEA -> szName, pFound -> szName);
+
+      nLength = sizeof(GEA2) + strlen(pGEA -> szName);
+      nLength = ((nLength - 1) / sizeof(ULONG) + 1) * sizeof(ULONG);
+
+      pGEA -> oNextEntryOffset = ulAttributes ? nLength : 0;
+      pGEA   = (PGEA2)  ((PCH) pGEA + nLength);
+    }
+
+    pFound = (PDENA2) ((PCH) pFound + pFound -> oNextEntryOffset);
+  }
+
+  if (pGEA == pGEAlist -> list) /* no attributes to save */
+  {
+    unalloc(pDENA);
+    unalloc(pGEAlist);
+    return;
+  }
+
+  pGEAlist -> cbList = (PCH) pGEA - (PCH) pGEAlist;
+
+  pFEAlist = (PVOID) pDENA;  /* reuse buffer */
+  pFEAlist -> cbList = nBlock;
+
+  eaop.fpGEA2List = pGEAlist;
+  eaop.fpFEA2List = pFEAlist;
+  eaop.oError = 0;
+
+  if (DosQueryPathInfo(szName, FIL_QUERYEASFROMLIST,
+                       (PBYTE) &eaop, sizeof(eaop)))
+  {
+    unalloc(pDENA);
+    unalloc(pGEAlist);
+    return;
+  }
+
+  /* The maximum compressed size is (in case of STORE type) the
+     uncompressed size plus the size of the compression type field
+     plus the size of the CRC field + 2*5 deflate overhead bytes
+     for uncompressable data.
+     (5 bytes per 32Kb block, max compressed size = 2 blocks) */
+
+  ulAttributes = pFEAlist -> cbList;
+  ulMemoryBlock = ulAttributes +
+                  sizeof(USHORT) + sizeof(ULONG) + EB_DEFLAT_EXTRA;
+  pEAblock = (PEFHEADER) malloc(sizeof(EFHEADER) + ulMemoryBlock);
+
+  if (pEAblock == NULL)
+  {
+    unalloc(pDENA);
+    unalloc(pGEAlist);
+    return;
+  }
+
+  *bufptr = (char *) pEAblock;
+  *size = sizeof(EFHEADER);
+
+  pEAblock -> nID = EF_OS2EA;
+  pEAblock -> nSize = sizeof(pEAblock -> lSize);
+  pEAblock -> lSize = ulAttributes; /* uncompressed size */
+
+  nLength = memcompress((char *) (pEAblock + 1), ulMemoryBlock,
+                        (char *) pFEAlist, ulAttributes);
+  *size += nLength;
+  pEAblock -> nSize += nLength;
+
+  if ((pEAblock = (PEFHEADER) malloc(sizeof(EFHEADER))) == NULL)
+  {
+    unalloc(pDENA);
+    unalloc(pGEAlist);
+    return;
+  }
+
+  *cbufptr = (char *) pEAblock;
+  *csize = sizeof(EFHEADER);
+
+  pEAblock -> nID = EF_OS2EA;
+  pEAblock -> nSize = sizeof(pEAblock -> lSize);
+  pEAblock -> lSize = ulAttributes;
+
+  if (noisy)
+    printf(" (%ld bytes EA's)", ulAttributes);
+
+  unalloc(pDENA);
+  unalloc(pGEAlist);
+}
+
+#else /* !__32BIT__ */
+
+typedef struct
+{
+  ULONG oNextEntryOffset;
+  BYTE fEA;
+  BYTE cbName;
+  USHORT cbValue;
+  CHAR szName[1];
+}
+FEA2, *PFEA2;
+
+typedef struct
+{
+  ULONG cbList;
+  FEA2 list[1];
+}
+FEA2LIST, *PFEA2LIST;
+
+void GetEAs(char *path, char **bufptr, size_t *size,
+                        char **cbufptr, size_t *csize)
+{
+  FILESTATUS2 fs;
+  PDENA1 pDENA, pFound;
+  EAOP eaop;
+  PGEALIST pGEAlist;
+  PGEA pGEA;
+  PFEALIST pFEAlist;
+  PFEA pFEA;
+  PFEA2LIST pFEA2list;
+  PFEA2 pFEA2;
+  EFHEADER *pEAblock;
+  ULONG ulAttributes;
+  USHORT nLength, nMaxSize;
+  char szName[CCHMAXPATH];
+
+  *size = *csize = 0;
+
+  strcpy(szName, path);
+  nLength = strlen(szName);
+  if (szName[nLength - 1] == '/')
+    szName[nLength - 1] = 0;
+
+  if (DosQueryPathInfo(szName, FIL_QUERYEASIZE, (PBYTE) &fs, sizeof(fs))
+      || fs.cbList <= 2 * sizeof(ULONG))
+    return;
+
+  ulAttributes = -1;
+  nMaxSize = (USHORT) min(fs.cbList * 2, 65520L);
+
+  if ((pDENA = malloc((size_t) nMaxSize)) == NULL)
+    return;
+
+  if (DosEnumAttribute(ENUMEA_REFTYPE_PATH, szName, 1, pDENA, fs.cbList,
+                       &ulAttributes, ENUMEA_LEVEL_NO_VALUE)
+    || ulAttributes == 0
+    || (pGEAlist = malloc(nMaxSize)) == NULL)
+  {
+    free(pDENA);
+    return;
+  }
+
+  pGEA = pGEAlist -> list;
+  pFound = pDENA;
+
+  while (ulAttributes--)
+  {
+    nLength = strlen(pFound -> szName);
+
+    if (!(strcmp(pFound -> szName, ".LONGNAME") == 0 && use_longname_ea))
+    {
+      pGEA -> cbName = pFound -> cbName;
+      strcpy(pGEA -> szName, pFound -> szName);
+
+      pGEA++;
+      pGEA = (PGEA) (((PCH) pGEA) + nLength);
+    }
+
+    pFound++;
+    pFound = (PDENA1) (((PCH) pFound) + nLength);
+  }
+
+  if (pGEA == pGEAlist -> list)
+  {
+    free(pDENA);
+    free(pGEAlist);
+    return;
+  }
+
+  pGEAlist -> cbList = (PCH) pGEA - (PCH) pGEAlist;
+
+  pFEAlist = (PFEALIST) pDENA; /* reuse buffer */
+  pFEAlist -> cbList = fs.cbList;
+  pFEA = pFEAlist -> list;
+
+  eaop.fpGEAList = pGEAlist;
+  eaop.fpFEAList = pFEAlist;
+  eaop.oError = 0;
+
+  if (DosQueryPathInfo(szName, FIL_QUERYEASFROMLIST,
+                       (PBYTE) &eaop, sizeof(eaop)))
+  {
+    free(pDENA);
+    free(pGEAlist);
+    return;
+  }
+
+  /* now convert into new OS/2 2.0 32-bit format */
+
+  pFEA2list = (PFEA2LIST) pGEAlist;  /* reuse buffer */
+  pFEA2 = pFEA2list -> list;
+
+  while ((PCH) pFEA - (PCH) pFEAlist < pFEAlist -> cbList)
+  {
+    nLength = sizeof(FEA) + pFEA -> cbName + 1 + pFEA -> cbValue;
+    memcpy((PCH) pFEA2 + sizeof(pFEA2 -> oNextEntryOffset), pFEA, nLength);
+    memset((PCH) pFEA2 + sizeof(pFEA2 -> oNextEntryOffset) + nLength, 0, 3);
+    pFEA = (PFEA) ((PCH) pFEA + nLength);
+
+    nLength = sizeof(FEA2) + pFEA2 -> cbName + 1 + pFEA2 -> cbValue;
+    nLength = ((nLength - 1) / sizeof(ULONG) + 1) * sizeof(ULONG);
+    /* rounded up to 4-byte boundary */
+    pFEA2 -> oNextEntryOffset =
+      ((PCH) pFEA - (PCH) pFEAlist < pFEAlist -> cbList) ? nLength : 0;
+    pFEA2 = (PFEA2) ((PCH) pFEA2 + nLength);
+  }
+
+  pFEA2list -> cbList = (PCH) pFEA2 - (PCH) pFEA2list;
+  ulAttributes = pFEA2list -> cbList;
+
+  pEAblock = (PEFHEADER) pDENA; /* reuse buffer */
+
+  *bufptr = (char *) pEAblock;
+  *size = sizeof(EFHEADER);
+
+  pEAblock -> nID = EF_OS2EA;
+  pEAblock -> nSize = sizeof(pEAblock -> lSize);
+  pEAblock -> lSize = ulAttributes; /* uncompressed size */
+
+  nLength = (USHORT) memcompress((char *) (pEAblock + 1),
+    nMaxSize - sizeof(EFHEADER), (char *) pFEA2list, ulAttributes);
+
+  *size += nLength;
+  pEAblock -> nSize += nLength;
+
+  pEAblock = (PEFHEADER) pGEAlist;
+
+  *cbufptr = (char *) pEAblock;
+  *csize = sizeof(EFHEADER);
+
+  pEAblock -> nID = EF_OS2EA;
+  pEAblock -> nSize = sizeof(pEAblock -> lSize);
+  pEAblock -> lSize = ulAttributes;
+
+  if (noisy)
+    printf(" (%ld bytes EA's)", ulAttributes);
+}
+
+#endif /* __32BIT__ */
+
+void GetACL(char *path, char **bufptr, size_t *size,
+                        char **cbufptr, size_t *csize)
+{
+  static char *buffer;
+  char *cbuffer;
+  long bytes, cbytes;
+  PEFHEADER pACLblock;
+
+  if (buffer == NULL) /* avoid frequent allocation (for every file) */
+    if ((buffer = malloc(ACL_BUFFERSIZE)) == NULL)
+      return;
+
+  if (acl_get(NULL, path, buffer))
+    return; /* this will be the most likely case */
+
+  bytes = strlen(buffer);
+
+  /* The maximum compressed size is (in case of STORE type) the
+     uncompressed size plus the size of the compression type field
+     plus the size of the CRC field + 2*5 deflate overhead bytes
+     for uncompressable data.
+     (5 bytes per 32Kb block, max compressed size = 2 blocks) */
+
+  cbytes = bytes + sizeof(USHORT) + sizeof(ULONG) + EB_DEFLAT_EXTRA;
+  if ((*bufptr = realloc(*bufptr, *size + sizeof(EFHEADER) + cbytes)) == NULL)
+    return;
+
+  pACLblock = (PEFHEADER) (*bufptr + *size);
+
+  cbuffer = (char *) (pACLblock + 1);
+  cbytes = memcompress(cbuffer, cbytes, buffer, bytes);
+
+  *size += sizeof(EFHEADER) + cbytes;
+
+  pACLblock -> nID = EF_ACL;
+  pACLblock -> nSize = sizeof(pACLblock -> lSize) + cbytes;
+  pACLblock -> lSize = bytes; /* uncompressed size */
+
+  if ((*cbufptr = realloc(*cbufptr, *csize + sizeof(EFHEADER))) == NULL)
+    return;
+
+  pACLblock = (PEFHEADER) (*cbufptr + *csize);
+  *csize += sizeof(EFHEADER);
+
+  pACLblock -> nID = EF_ACL;
+  pACLblock -> nSize = sizeof(pACLblock -> lSize);
+  pACLblock -> lSize = bytes;
+
+  if (noisy)
+    printf(" (%ld bytes ACL)", bytes);
+}
+
+#ifdef USE_EF_UT_TIME
+
+int GetExtraTime(struct zlist far *z, iztimes *z_utim)
+{
+  int eb_c_size = EB_HEADSIZE + EB_UT_LEN(1);
+  int eb_l_size = eb_c_size;
+  char *eb_c_ptr;
+  char *eb_l_ptr;
+  unsigned long ultime;
+
+#ifdef IZ_CHECK_TZ
+  if (!zp_tz_is_valid) return ZE_OK;    /* skip silently no correct tz info */
+#endif
+
+  eb_c_ptr = realloc(z->cextra, (z->cext + eb_c_size));
+  if (eb_c_ptr == NULL)
+    return ZE_MEM;
+  z->cextra = eb_c_ptr;
+  eb_c_ptr += z->cext;
+  z->cext += eb_c_size;
+
+  eb_c_ptr[0]  = 'U';
+  eb_c_ptr[1]  = 'T';
+  eb_c_ptr[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */
+  eb_c_ptr[3]  = 0;
+  eb_c_ptr[4]  = EB_UT_FL_MTIME;
+  ultime = (unsigned long) z_utim->mtime;
+  eb_c_ptr[5]  = (char)(ultime);
+  eb_c_ptr[6]  = (char)(ultime >> 8);
+  eb_c_ptr[7]  = (char)(ultime >> 16);
+  eb_c_ptr[8]  = (char)(ultime >> 24);
+
+  if (z_utim->mtime != z_utim->atime || z_utim->mtime != z_utim->ctime)
+  {
+    eb_c_ptr[4]  = EB_UT_FL_MTIME | EB_UT_FL_ATIME | EB_UT_FL_CTIME;
+    eb_l_size = EB_HEADSIZE + EB_UT_LEN(3); /* only on HPFS they can differ */
+  /* so only then it makes sense to store all three time stamps */
+  }
+
+  eb_l_ptr = realloc(z->extra, (z->ext + eb_l_size));
+  if (eb_l_ptr == NULL)
+    return ZE_MEM;
+  z->extra = eb_l_ptr;
+  eb_l_ptr += z->ext;
+  z->ext += eb_l_size;
+
+  memcpy(eb_l_ptr, eb_c_ptr, eb_c_size);
+
+  if (eb_l_size > eb_c_size)
+  {
+    eb_l_ptr[2]  = EB_UT_LEN(3);
+    ultime = (unsigned long) z_utim->atime;
+    eb_l_ptr[9]  = (char)(ultime);
+    eb_l_ptr[10] = (char)(ultime >> 8);
+    eb_l_ptr[11] = (char)(ultime >> 16);
+    eb_l_ptr[12] = (char)(ultime >> 24);
+    ultime = (unsigned long) z_utim->ctime;
+    eb_l_ptr[13] = (char)(ultime);
+    eb_l_ptr[14] = (char)(ultime >> 8);
+    eb_l_ptr[15] = (char)(ultime >> 16);
+    eb_l_ptr[16] = (char)(ultime >> 24);
+  }
+
+  return ZE_OK;
+}
+
+#endif /* USE_EF_UT_TIME */
+
+int set_extra_field(struct zlist far *z, iztimes *z_utim)
+{
+  /* store EA data in local header, and size only in central headers */
+  GetEAs(z->name, &z->extra, &z->ext, &z->cextra, &z->cext);
+
+  /* store ACL data in local header, and size only in central headers */
+  GetACL(z->name, &z->extra, &z->ext, &z->cextra, &z->cext);
+
+#ifdef USE_EF_UT_TIME
+  /* store extended time stamps in both headers */
+  return GetExtraTime(z, z_utim);
+#else /* !USE_EF_UT_TIME */
+  return ZE_OK;
+#endif /* ?USE_EF_UT_TIME */
+}
+
+#endif /* !UTIL */
+
+/* Initialize the table of uppercase characters including handling of
+   country dependent characters. */
+
+void init_upper()
+{
+  COUNTRYCODE cc;
+  unsigned nCnt, nU;
+
+  for (nCnt = 0; nCnt < sizeof(upper); nCnt++)
+    upper[nCnt] = lower[nCnt] = (unsigned char) nCnt;
+
+  cc.country = cc.codepage = 0;
+  DosMapCase(sizeof(upper), &cc, (PCHAR) upper);
+
+  for (nCnt = 0; nCnt < 256; nCnt++)
+  {
+    nU = upper[nCnt];
+    if (nU != nCnt && lower[nU] == (unsigned char) nU)
+      lower[nU] = (unsigned char) nCnt;
+  }
+
+  for (nCnt = 'A'; nCnt <= 'Z'; nCnt++)
+    lower[nCnt] = (unsigned char) (nCnt - 'A' + 'a');
+}
+
+char *StringLower(char *szArg)
+{
+  unsigned char *szPtr;
+  for (szPtr = (unsigned char *) szArg; *szPtr; szPtr++)
+    *szPtr = lower[*szPtr];
+  return szArg;
+}
+
+#if defined(__IBMC__) && defined(__DEBUG_ALLOC__)
+void DebugMalloc(void)
+{
+  _dump_allocated(0); /* print out debug malloc memory statistics */
+}
+#endif
+
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+void version_local()
+{
+    static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
+#if defined(__IBMC__) || defined(__WATCOMC__) || defined(_MSC_VER)
+    char buf[80];
+#endif
+
+    printf(CompiledWith,
+
+#ifdef __GNUC__
+#  ifdef __EMX__  /* __EMX__ is defined as "1" only (sigh) */
+      "emx+gcc ", __VERSION__,
+#  else
+      "gcc/2 ", __VERSION__,
+#  endif
+#elif defined(__IBMC__)
+      "IBM ",
+#  if (__IBMC__ < 200)
+      (sprintf(buf, "C Set/2 %d.%02d", __IBMC__/100,__IBMC__%100), buf),
+#  elif (__IBMC__ < 300)
+      (sprintf(buf, "C Set++ %d.%02d", __IBMC__/100,__IBMC__%100), buf),
+#  else
+      (sprintf(buf, "Visual Age C++ %d.%02d", __IBMC__/100,__IBMC__%100), buf),
+#  endif
+#elif defined(__WATCOMC__)
+      "Watcom C", (sprintf(buf, " (__WATCOMC__ = %d)", __WATCOMC__), buf),
+#elif defined(__TURBOC__)
+#  ifdef __BORLANDC__
+      "Borland C++",
+#    if (__BORLANDC__ < 0x0460)
+        " 1.0",
+#    elif (__BORLANDC__ == 0x0460)
+        " 1.5",
+#    else
+        " 2.0",
+#    endif
+#  else
+      "Turbo C",
+#    if (__TURBOC__ >= 661)
+       "++ 1.0 or later",
+#    elif (__TURBOC__ == 661)
+       " 3.0?",
+#    elif (__TURBOC__ == 397)
+       " 2.0",
+#    else
+       " 1.0 or 1.5?",
+#    endif
+#  endif
+#elif defined(MSC)
+      "Microsoft C ",
+#  ifdef _MSC_VER
+      (sprintf(buf, "%d.%02d", _MSC_VER/100, _MSC_VER%100), buf),
+#  else
+      "5.1 or earlier",
+#  endif
+#else
+      "unknown compiler", "",
+#endif /* __GNUC__ */
+
+      "OS/2",
+
+/* GRR:  does IBM C/2 identify itself as IBM rather than Microsoft? */
+#if (defined(MSC) || (defined(__WATCOMC__) && !defined(__386__)))
+#  if defined(M_I86HM) || defined(__HUGE__)
+      " (16-bit, huge)",
+#  elif defined(M_I86LM) || defined(__LARGE__)
+      " (16-bit, large)",
+#  elif defined(M_I86MM) || defined(__MEDIUM__)
+      " (16-bit, medium)",
+#  elif defined(M_I86CM) || defined(__COMPACT__)
+      " (16-bit, compact)",
+#  elif defined(M_I86SM) || defined(__SMALL__)
+      " (16-bit, small)",
+#  elif defined(M_I86TM) || defined(__TINY__)
+      " (16-bit, tiny)",
+#  else
+      " (16-bit)",
+#  endif
+#else
+      " 2.x/3.x (32-bit)",
+#endif
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+    );
+
+    /* temporary debugging code for Borland compilers only */
+#ifdef __TURBOC__
+    printf("\t(__TURBOC__ = 0x%04x = %d)\n", __TURBOC__, __TURBOC__);
+#ifdef __BORLANDC__
+    printf("\t(__BORLANDC__ = 0x%04x)\n",__BORLANDC__);
+#else
+    printf("\tdebug(__BORLANDC__ not defined)\n");
+#endif
+#ifdef __TCPLUSPLUS__
+    printf("\t(__TCPLUSPLUS__ = 0x%04x)\n", __TCPLUSPLUS__);
+#else
+    printf("\tdebug(__TCPLUSPLUS__ not defined)\n");
+#endif
+#ifdef __BCPLUSPLUS__
+    printf("\t(__BCPLUSPLUS__ = 0x%04x)\n\n", __BCPLUSPLUS__);
+#else
+    printf("\tdebug(__BCPLUSPLUS__ not defined)\n\n");
+#endif
+#endif /* __TURBOC__ */
+
+} /* end function version_local() */
+
+#endif /* OS2 */
diff --git a/os2/os2zip.h b/os2/os2zip.h
new file mode 100644 (file)
index 0000000..06d0a02
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * @(#) dir.h 1.4 87/11/06   Public Domain.
+ *
+ *  A public domain implementation of BSD directory routines for
+ *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
+ *  August 1987
+ *
+ *  Ported to OS/2 by Kai Uwe Rommel
+ *  Addition of other OS/2 file system specific code
+ *  Placed into the public domain
+ */
+
+
+#define MAXNAMLEN  256
+#define MAXPATHLEN 256
+
+#define _A_RONLY    0x01
+#define _A_HIDDEN   0x02
+#define _A_SYSTEM   0x04
+#define _A_VOLID    0x08
+#define _A_DIR      0x10
+#define _A_ARCHIVE  0x20
+
+
+struct dirent
+{
+  ino_t    d_ino;                   /* a bit of a farce */
+  int      d_reclen;                /* more farce */
+  int      d_namlen;                /* length of d_name */
+  char     d_name[MAXNAMLEN + 1];   /* null terminated */
+  /* nonstandard fields */
+  long     d_size;                  /* size in bytes */
+  unsigned d_mode;                  /* DOS or OS/2 file attributes */
+  unsigned d_time;
+  unsigned d_date;
+};
+
+/* The fields d_size and d_mode are extensions by me (Kai Uwe Rommel).
+ * The find_first and find_next calls deliver this data without any extra cost.
+ * If this data is needed, these fields save a lot of extra calls to stat()
+ * (each stat() again performs a find_first call !).
+ */
+
+struct _dircontents
+{
+  char *_d_entry;
+  long _d_size;
+  unsigned _d_mode, _d_time, _d_date;
+  struct _dircontents *_d_next;
+};
+
+typedef struct _dirdesc
+{
+  int  dd_id;                   /* uniquely identify each open directory */
+  long dd_loc;                  /* where we are in directory entry is this */
+  struct _dircontents *dd_contents;   /* pointer to contents of dir */
+  struct _dircontents *dd_cp;         /* pointer to current position */
+}
+DIR;
+
+
+extern DIR *opendir(const char *);
+extern struct dirent *readdir(DIR *);
+extern void seekdir(DIR *, long);
+extern long telldir(DIR *);
+extern void closedir(DIR *);
+#define rewinddir(dirp) seekdir(dirp, 0L)
+
+int GetFileMode(char *name);
+ulg GetFileTime(char *name);
+void SetFileTime(char *path, ulg stamp);
+char *getVolumeLabel(int drive, unsigned long *time, unsigned long *mode,
+                     time_t *utim);
+
+int IsFileNameValid(char *name);
+int IsFileSystemFAT(char *dir);
+void ChangeNameForFAT(char *name);
+
+char *GetLongNameEA(const char *name);
+char *GetLongPathEA(const char *name);
+void GetEAs(char *name, char **bufptr, size_t *size,
+                        char **cbufptr, size_t *csize);
+
+char *StringLower(char *);
diff --git a/os2/osdep.h b/os2/osdep.h
new file mode 100644 (file)
index 0000000..ea2c3f9
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#if defined(__OS2__) && !defined(OS2)
+#  define OS2
+#endif
+
+/* Automatic setting of the common Microsoft C idenfifier MSC.
+ * NOTE: Watcom also defines M_I*86 !
+ */
+#if defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__))
+#  ifndef MSC
+#    define MSC                 /* This should work for older MSC, too!  */
+#  endif
+#endif
+
+#if defined(__WATCOMC__) && defined(__386__)
+#  define WATCOMC_386
+#endif
+
+#if defined(__EMX__) || defined(WATCOMC_386) || defined(__BORLANDC__)
+#  if (defined(OS2) && !defined(__32BIT__))
+#    define __32BIT__
+#  endif
+#endif
+
+#if defined(OS2) && !defined(__32BIT__)
+#  define MEMORY16
+#endif
+
+#ifndef NO_ASM
+#  define ASMV
+/* #  define ASM_CRC */
+#endif
+
+/* enable creation of UTC time fields unless explicitely suppressed */
+#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))
+#  define USE_EF_UT_TIME
+#endif
+
+/* check that TZ environment variable is defined before using UTC times */
+#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ))
+#  define IZ_CHECK_TZ
+#endif
+
+#ifndef ZP_NEED_MEMCOMPR
+#  define ZP_NEED_MEMCOMPR
+#endif
+
+#ifdef MEMORY16
+#  ifdef __TURBOC__
+#    include <alloc.h>
+#    if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
+#      if defined(DYNAMIC_CRC_TABLE) && defined(DYNALLOC_CRCTAB)
+        error: No dynamic CRC table allocation with Borland C far data models.
+#      endif /* DYNAMIC_CRC_TABLE */
+#    endif /* Turbo/Borland C far data memory models */
+#    define nearmalloc malloc
+#    define nearfree   free
+#    define DYN_ALLOC
+#  else /* !__TURBOC__ */
+#    include <malloc.h>
+#    define nearmalloc _nmalloc
+#    define nearfree   _nfree
+#    define farmalloc  _fmalloc
+#    define farfree    _ffree
+#  endif /* ?__TURBOC__ */
+#  define MY_ZCALLOC 1
+#endif /* MEMORY16 */
+
+
+/* The symbol MSDOS is consistently used in the generic source files
+ * to identify code to support for MSDOS (and MSDOS related) stuff.
+ * e.g: FAT or (FAT like) file systems,
+ *      '\\' as directory separator in paths,
+ *      "\r\n" as record (line) terminator in text files, ...
+ *
+ * MSDOS is defined anyway with MS C 16-bit. So the block above works.
+ * For the 32-bit compilers, MSDOS must not be defined in the block above.
+ */
+#if (defined(OS2) && !defined(MSDOS))
+#  define MSDOS
+/* inherit MS-DOS file system etc. stuff */
+#endif
+
+#define USE_CASE_MAP
+#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \
+                     procname(n, 1))
+
+/* time stamp resolution of file system is 2 seconds */
+#define ROUNDED_TIME(time)  ((time_t)(((unsigned long)(time) + 1) & (~1)))
+
+#define FOPR "rb"
+#define FOPM "r+b"
+#define FOPW "wb"
+
+#ifdef __32BIT__
+#  define CBSZ 0x40000
+#  define ZBSZ 0x40000
+#else
+#  define CBSZ 0xE000
+#  define ZBSZ 0x7F00 /* Some libraries do not allow a buffer size > 32K */
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+
+#ifdef ZCRYPT_INTERNAL
+#  ifndef __GO32__
+#    include <process.h>        /* getpid() declaration for srand seed */
+#  endif
+#endif
+
+/* for some (all ?) versions of IBM C Set/2 and IBM C Set++ */
+#ifndef S_IFMT
+#  define S_IFMT 0xF000
+#endif /* !S_IFMT */
+
+#ifdef MSC
+#  define NO_UNISTD_H
+#endif
+
+#ifdef __WATCOMC__
+#  define NO_MKTEMP
+/* Get asm routines to link properly without using "__cdecl": */
+#  ifdef __386__
+#    ifdef ASMV
+#      pragma aux window "*";
+#      pragma aux prev "*";
+#      pragma aux prev_length "*";
+#      pragma aux strstart "*";
+#      pragma aux match_start "*";
+#      pragma aux max_chain_length "*";
+#      pragma aux good_match "*";
+#      pragma aux nice_match "*";
+#      pragma aux match_init "*";
+#      pragma aux longest_match "*";
+#    endif
+#    ifndef USE_ZLIB
+#      pragma aux crc32         "_*" parm caller [] value [eax] modify [eax]
+#      pragma aux get_crc_table "_*" parm caller [] value [eax] \
+                                      modify [eax ecx edx]
+#    endif /* !USE_ZLIB */
+#  else /* !__386__ */
+#    if defined(ASMV) || defined(ASM_CRC)
+/*#      error 16 bit assembly modules currently DO NOT WORK with Watcom C. */
+#    endif
+#    ifdef ASMV
+#      pragma aux match_init    "_*" parm caller [] loadds modify [ax bx]
+#      pragma aux longest_match "_*" parm caller [] loadds value [ax] \
+                                      modify [ax bx cx dx es]
+#    endif
+#    ifndef USE_ZLIB
+#      pragma aux crc32         "_*" parm caller [] value [ax dx] \
+                                      modify [ax bx cx dx es]
+#      pragma aux get_crc_table "_*" parm caller [] value [ax] \
+                                      modify [ax bx cx dx]
+#    endif /* !USE_ZLIB */
+#  endif /* ?__386__ */
+#endif
+
+#ifdef __IBMC__
+#  define NO_UNISTD_H
+#  define NO_MKTEMP
+#  define timezone _timezone            /* (underscore names work with    */
+#  define tzset _tzset                  /*  all versions of C Set)        */
+#endif
diff --git a/os2/zip.def b/os2/zip.def
new file mode 100644 (file)
index 0000000..7404eee
--- /dev/null
@@ -0,0 +1,3 @@
+NAME WINDOWCOMPAT NEWFILES
+DESCRIPTION 'The world-famous zip utilities from Info-ZIP'
+; STACKSIZE 0x50000
diff --git a/os2/zipup.h b/os2/zipup.h
new file mode 100644 (file)
index 0000000..592cff8
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#define fhow (O_RDONLY|O_BINARY)
+#define fbad (-1)
+typedef int ftype;
+#define zopen(n,p) open(n,p)
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f) close(f)
+#define zerr(f) (k == (extent)(-1L))
+#define zstdin 0
diff --git a/packaging/exec-shield.patch b/packaging/exec-shield.patch
new file mode 100644 (file)
index 0000000..3d2a1eb
--- /dev/null
@@ -0,0 +1,19 @@
+diff -ur zip-2.3/crc_i386.S zip-2.3-lhh/crc_i386.S
+--- zip-2.3/crc_i386.S 1999-10-09 16:10:26.000000000 -0400
++++ zip-2.3-lhh/crc_i386.S     2003-10-24 16:15:52.000000000 -0400
+@@ -230,3 +230,6 @@
+ #endif /* i386 || _i386 || _I386 || __i386 */
+ #endif /* !USE_ZLIB */
++
++.section .note.GNU-stack, "", @progbits
++.previous
+diff -ur zip-2.3/match.S zip-2.3-lhh/match.S
+--- zip-2.3/match.S    1999-07-27 17:18:14.000000000 -0400
++++ zip-2.3-lhh/match.S        2003-10-24 16:15:38.000000000 -0400
+@@ -405,3 +405,5 @@
+ #endif /* i386 || _I386 || _i386 || __i386  */
+ #endif /* !USE_ZLIB */
++.section .note.GNU-stack, "", @progbits
++.previous
diff --git a/packaging/zcrypt29.tar.gz b/packaging/zcrypt29.tar.gz
new file mode 100644 (file)
index 0000000..44de3cf
Binary files /dev/null and b/packaging/zcrypt29.tar.gz differ
diff --git a/packaging/zip-2.3-currdir.patch b/packaging/zip-2.3-currdir.patch
new file mode 100644 (file)
index 0000000..1ff00f6
--- /dev/null
@@ -0,0 +1,11 @@
+--- zip-2.3/util.c.pom 1999-11-07 11:29:38.000000000 +0100
++++ zip-2.3/util.c     2005-01-17 13:46:26.165396792 +0100
+@@ -190,6 +190,8 @@
+ /* Compare the sh pattern p with the string s and return true if they match,
+    false if they don't or if there is a syntax error in the pattern. */
+ {
++  while (s[0] == '.' && s[1] == '/') 
++     s += 2;                /* strip redundant leading "./" sections */
+   return recmatch((ZCONST uch *) p, (ZCONST uch *) s, cs) == 1;
+ }
diff --git a/packaging/zip-2.31-configure.patch b/packaging/zip-2.31-configure.patch
new file mode 100644 (file)
index 0000000..00b09d1
--- /dev/null
@@ -0,0 +1,213 @@
+--- zip-2.31/unix/configure.lhh        2005-11-10 13:25:26.000000000 +0100
++++ zip-2.31/unix/configure    2005-11-10 13:40:44.311641648 +0100
+@@ -76,14 +76,20 @@
+   done
+ fi
+-echo Check for prototypes
++echo -n Check for prototypes...
+ echo "int main(int argc, char *argv[]) { return 0; }" > conftest.c
+ $CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null
+-[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_PROTO"
++if [ $? -ne 0 ]; then
++  echo no
++  CFLAGS="${CFLAGS} -DNO_PROTO"
++else
++  echo yes
++fi
++
+ # const check currently handles mips cc and non ANSI compilers.
+ # does it need more ?
+-echo Check the handling of const
++echo -n Check the handling of const...
+ cat > conftest.c << _EOF_
+ typedef int charset[2];
+ int main()
+@@ -94,9 +100,15 @@
+ }
+ _EOF_
+ $CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null
+-[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_CONST"
++if [ $? -ne 0 ]; then
++  echo no
++  CFLAGS="${CFLAGS} -DNO_CONST"
++else
++  echo yes
++fi
++
+-echo Check for time_t
++echo -n Check for time_t...
+ cat > conftest.c << _EOF_
+ #include <sys/types.h>
+ #include <time.h>
+@@ -107,9 +119,15 @@
+ }
+ _EOF_
+ $CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null
+-[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_TIME_T"
++if [ $? -ne 0 ]; then
++  echo no
++  CFLAGS="${CFLAGS} -DNO_TIME_T"
++else
++  echo yes
++fi
++
+-echo Check for size_t
++echo -n Check for size_t...
+ cat > conftest.c << _EOF_
+ #include <sys/types.h>
+ int main()
+@@ -119,7 +137,13 @@
+ }
+ _EOF_
+ $CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null
+-[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_SIZE_T"
++if [ $? -ne 0 ]; then
++  echo no
++  CFLAGS="${CFLAGS} -DNO_SIZE_T"
++else
++  echo yes
++fi
++
+ echo Check for gcc no-builtin flag
+ # -fno-builtin since version 2
+@@ -140,18 +164,29 @@
+ # add NO_'function_name' to flags if missing
+ for func in rmdir strchr strrchr rename mktemp mktime mkstemp
+ do
+-  echo Check for $func
+-  echo "int main(){ $func(); return 0; }" > conftest.c
++  echo -n Check for $func...
++  echo "char $func(void); int main(){ $func(); return 0; }" > conftest.c
+   $CC $BFLAG -o conftest conftest.c >/dev/null 2>/dev/null
+-  [ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_`echo $func | tr '[a-z]' '[A-Z]'`"
++  if [ $? -ne 0 ]; then
++    echo no
++    CFLAGS="${CFLAGS} -DNO_`echo $func | tr '[a-z]' '[A-Z]'`"
++  else
++    echo yes
++  fi
+ done
+-echo Check for memset
++echo -n Check for memset...
+ echo "int main(){ char k; memset(&k,0,0); return 0; }" > conftest.c
+ $CC -o conftest conftest.c >/dev/null 2>/dev/null
+-[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DZMEM"
++if [ $? -ne 0 ]; then
++  echo no
++  CFLAGS="${CFLAGS} -DZMEM"
++else
++  echo yes
++fi
++
+-echo Check for errno declaration
++echo -n Check for errno declaration...
+ cat > conftest.c << _EOF_
+ #include <errno.h>
+ main()
+@@ -161,9 +196,14 @@
+ }
+ _EOF_
+ $CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null
+-[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_ERRNO"
++if [ $? -ne 0 ]; then
++  echo no
++  CFLAGS="${CFLAGS} -DNO_ERRNO"
++else
++  echo yes
++fi
+-echo Check for directory libraries
++echo -n Check for directory libraries...
+ cat > conftest.c << _EOF_
+ int main() { return closedir(opendir(".")); }
+ _EOF_
+@@ -178,21 +218,30 @@
+   done
+   if [ ${OPT} ]; then
+     LFLAGS2="${LFLAGS2} ${OPT}"
++    echo yes, ${OPT}
+   else
+     CFLAGS="${CFLAGS} -DNO_DIR"
++    echo no
+   fi
+ fi
+ # Dynix/ptx 1.3 needed this
+-echo Check for readlink
++echo -n Check for readlink...
+ echo "int main(){ return readlink(); }" > conftest.c
+ $CC -o conftest conftest.c >/dev/null 2>/dev/null
+ if [ $? -ne 0 ]; then
+   $CC -o conftest conftest.c -lseq >/dev/null 2>/dev/null
+-  [ $? -eq 0 ] && LFLAGS2="${LFLAGS2} -lseq"
++  if [ $? -eq 0 ]; then
++    LFLAGS2="${LFLAGS2} -lseq"
++    echo yes, -lseq
++  else
++    echo no
++  fi
++else
++  echo yes
+ fi
+-echo Check for directory include file
++echo -n Check for directory include file...
+ OPT=""
+ for inc in dirent.h sys/ndir.h ndir.h sys/dir.h
+ do
+@@ -200,17 +249,19 @@
+    $CPP conftest.c > /dev/null 2>/dev/null
+    [ $? -eq 0 ] && OPT="-DHAVE_`echo $inc | tr '[a-z]./' '[A-Z]__'`" && break
+ done
++echo "${OPT}"
+ CFLAGS="${CFLAGS} ${OPT}"
+-echo Check for non existent include files
++echo -n Check for non existent include files...
+ for inc in stdlib.h stddef.h unistd.h fcntl.h string.h
+ do
+    echo "#include <$inc>" > conftest.c
+    $CPP conftest.c >/dev/null 2>/dev/null
+    [ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_`echo $inc | tr '[a-z]./' '[A-Z]__'`"
+ done
++echo ok
+-echo Check for terminal I/O include file
++echo -n Check for terminal I/O include file...
+ OPT=""
+ for inc in termios.h termio.h sgtty.h
+ do
+@@ -219,9 +270,10 @@
+    [ $? -eq 0 ] && OPT="-DHAVE_`echo $inc | tr '[a-z]./' '[A-Z]__'`" && break
+ done
+ CFLAGS="${CFLAGS} ${OPT}"
++echo $OPT
+ # needed for AIX (and others ?) when mmap is used
+-echo Check for valloc
++echo -n Check for valloc...
+ cat > conftest.c << _EOF_
+ main()
+ {
+@@ -231,7 +283,13 @@
+ }
+ _EOF_
+ $CC ${CFLAGS} conftest.c > /dev/null 2>/dev/null
+-[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_VALLOC"
++if [ $? -ne 0 ]; then
++  echo no
++  CFLAGS="${CFLAGS} -DNO_VALLOC"
++else
++  echo yes
++fi
++
+ echo Check for 64bit fseek
+ for func in fseeko fseek64
diff --git a/packaging/zip-2.31-install.patch b/packaging/zip-2.31-install.patch
new file mode 100644 (file)
index 0000000..7a1f69f
--- /dev/null
@@ -0,0 +1,11 @@
+--- zip-2.31/unix/Makefile.install     2005-02-28 08:33:50.000000000 +0100
++++ zip-2.31/unix/Makefile     2005-11-10 12:58:33.221425848 +0100
+@@ -129,7 +129,7 @@
+       $(INSTALL_PROGRAM) $(ZIPS) $(BINDIR)
+       -cd $(BINDIR); $(CHMOD) $(BINFLAGS) $(ZIPS)
+       -$(INSTALL_D) $(MANDIR)
+-      $(INSTALL) man/zip.1 $(MANDIR)/zip.$(manext)
++      $(INSTALL_PROGRAM) man/zip.1 $(MANDIR)/zip.$(manext)
+       $(CHMOD) $(MANFLAGS) $(MANDIR)/zip.$(manext)
+ uninstall:
diff --git a/packaging/zip-2.31-near-4GB.patch b/packaging/zip-2.31-near-4GB.patch
new file mode 100644 (file)
index 0000000..210b183
--- /dev/null
@@ -0,0 +1,293 @@
+--- zip-2.31/unix/zipup.h.4GB  2005-01-29 07:47:58.000000000 +0100
++++ zip-2.31/unix/zipup.h      2005-11-10 13:18:02.990593904 +0100
+@@ -6,13 +6,19 @@
+   If, for some reason, both of these files are missing, the Info-ZIP license
+   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+ */
++#include <features.h>
++#include <fcntl.h>
+ #ifndef O_RDONLY
+ #  define O_RDONLY 0
+ #endif
+ #ifndef O_BINARY
+ #  define O_BINARY 0
+ #endif
+-#define fhow (O_RDONLY|O_BINARY)
++#ifdef _LARGEFILE64_SOURCE
++#define fhow (O_RDONLY | O_LARGEFILE)
++#else
++#define fhow O_RDONLY
++#endif
+ #define fbad (-1)
+ typedef int ftype;
+ #define zopen(n,p) open(n,p)
+--- zip-2.31/unix/unix.c.4GB   2005-02-11 03:35:02.000000000 +0100
++++ zip-2.31/unix/unix.c       2005-11-10 13:24:19.573344624 +0100
+@@ -113,7 +113,11 @@
+   char *e;              /* pointer to name from readd() */
+   int m;                /* matched flag */
+   char *p;              /* path for recursion */
++#ifdef _LARGEFILE64_SOURCE
++  struct stat64 s;      /* result of stat() */
++#else
+   struct stat s;        /* result of stat() */
++#endif
+   struct zlist far *z;  /* steps through zfiles list */
+   if (strcmp(n, "-") == 0)   /* if compressing stdin */
+@@ -202,6 +206,15 @@
+   } /* (s.st_mode & S_IFDIR) */
+   else
+     zipwarn("ignoring special file: ", n);
++
++  /* Zip uses negative error codes (IIRC, to -3).  Make sure file size
++     doesn't collide with error values.  2^32 - 8193 should be plenty until
++     info-zip supports zip64. */
++  if (s.st_size > MAX_ZIP_SIZE) {
++    zipwarn("file too large: ", a);
++    return ZE_MISS;
++  }
++
+   return ZE_OK;
+ }
+@@ -321,7 +334,12 @@
+    If f is "-", use standard input as the file. If f is a device, return
+    a file size of -1 */
+ {
+-  struct stat s;        /* results of stat() */
++#ifdef _LARGEFILE64_SOURCE
++  struct stat64 s;        /* results of stat() */
++#else
++  struct stat s;
++#endif
++
+   /* converted to pointer from using FNMAX - 11/8/04 EG */
+   char *name;
+   int len = strlen(f);
+@@ -343,7 +361,11 @@
+     name[len - 1] = '\0';
+   /* not all systems allow stat'ing a file with / appended */
+   if (strcmp(f, "-") == 0) {
++#ifdef _LARGEFILE64_SOURCE
++    if (fstat64(fileno(stdin), &s) != 0) {
++#else
+     if (fstat(fileno(stdin), &s) != 0) {
++#endif
+       free(name);
+       error("fstat(stdin)");
+     }
+@@ -422,7 +444,11 @@
+   /* store full data in local header but just modification time stamp info
+      in central header */
+ {
++#ifdef _LARGEFILE64_SOURCE
++  struct stat64 s;
++#else
+   struct stat s;
++#endif
+   char *name;
+   int len = strlen(z->name);
+--- zip-2.31/unix/configure.4GB        2004-12-05 09:51:18.000000000 +0100
++++ zip-2.31/unix/configure    2005-11-10 13:12:47.010630160 +0100
+@@ -12,7 +12,7 @@
+ trap "rm -f conftest* core a.out; exit 1" 1 2 3 15
+ CC=${1-cc}
+-CFLAGS=${2-"-O2 -I. -DUNIX"}
++CFLAGS=${2-"-O2 -I. -DUNIX -g -D_LARGEFILE64_SOURCE"}
+ LFLAGS1=""
+ LN="ln -s"
+--- zip-2.31/fileio.c.4GB      2005-11-10 12:59:43.000000000 +0100
++++ zip-2.31/fileio.c  2005-11-10 13:07:13.190378552 +0100
+@@ -599,7 +599,11 @@
+    this will be done by setfileattr() later.
+  */
+ {
++#ifdef _LARGEFILE64_SOURCE
++  struct stat64 t;        /* results of stat64() */
++#else
+   struct stat t;        /* results of stat() */
++#endif
+ #if defined(CMS_MVS)
+   /* cmsmvs.h defines FOPW_TEMP as memory(hiperspace).  Since memory is
+    * lost at end of run, always do copy instead of rename.
+@@ -698,8 +702,11 @@
+   return _dos_files(&buf, f, 0xff) < 0 ? 0x20 : buf.atr;
+ #else
++#ifdef _LARGEFILE64_SOURCE
++  struct stat64 s;
++#else  
+   struct stat s;
+-
++#endif
+   return SSTAT(f, &s) == 0 ? (int) s.st_mode : 0;
+ #endif
+ }
+@@ -920,3 +927,108 @@
+ }
+ #endif /* NO_RENAME */
++
++/*
++   Wrapper functions for fopen/fseek/ftell for >2GB files.
++
++   So, what we do here is add support for 4GB seeks.  More appropriately,
++   2^32 - 8193 bytes.  This is tailored to the way zip uses fseek; it never
++   seeks backwards more than 8192 bytes.
++ */
++#ifdef _LARGEFILE64_SOURCE
++FILE *
++lfopen(const char *path, const char *mode)
++{
++  int fd;
++  FILE *f;
++  int flags;
++  int x;
++  char prev;
++
++  if (!path || !mode | !strlen(mode))
++    return NULL;
++
++  for (x = 0; x < strlen(mode); x++) {
++    switch (mode[x]) {
++    case 'r':
++      flags = O_RDONLY | O_LARGEFILE;
++      break;
++    case 'w':
++      flags = O_WRONLY | O_LARGEFILE | O_CREAT | O_TRUNC;
++      break;
++    case 'a':
++      flags = O_RDWR | O_LARGEFILE;
++      break;
++    case 'b': /* b has no effect */
++      continue;
++    case '+':
++      if (prev == 'r') {
++        flags = O_RDWR | O_LARGEFILE;
++      } else if (prev == 'w') {
++        flags = O_RDWR | O_LARGEFILE | O_CREAT |
++          O_TRUNC;
++      } else if (prev == 'a') {
++        flags = O_RDWR | O_LARGEFILE | O_CREAT;
++      } else
++        return NULL;
++      break;
++    }
++    prev = mode[x];
++  }
++  
++  fd = open(path, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
++  if (fd == -1)
++    return NULL;
++
++  f = fdopen(fd, mode);
++  return f;
++}
++
++int
++lfseek(FILE *f, ulg pos, int whence)
++{
++  struct stat64 sb;
++  ulg o, delta;
++  int ret;
++
++  /* Hurts performance */
++  fflush(f);
++
++  if (pos <= MAX_ZIP_SIZE) {
++    return (lseek64(fileno(f), pos, whence) == (off64_t)-1);
++  }
++
++  delta = ~((off64_t)pos - 1);
++  if (whence == SEEK_CUR) {
++    o = lseek64(fileno(f), 0, SEEK_CUR);
++    if (o < delta)
++      return -1;
++
++    o -= delta;
++    return (lseek64(fileno(f), o, SEEK_SET) == (off64_t)-1);
++  }
++
++  if (whence == SEEK_END) {
++    fstat64(fileno(f), &sb);
++
++    if ((ulg)sb.st_size < delta)
++      return -1;
++
++    o = (off64_t)((sb.st_size) - delta);
++    return (lseek64(fileno(f), o, SEEK_SET) == (off64_t)-1);
++  }
++
++  return -1;
++}
++
++
++ulg
++lftell(FILE *f)
++{
++  /* Hurts performance */
++  fflush(f);
++  return (ulg)lseek64(fileno(f), 0, SEEK_CUR);
++}
++
++#endif /* _LARGEFILE64_SOURCE */
++
+--- zip-2.31/zip.h.4GB 2005-11-10 12:59:43.000000000 +0100
++++ zip-2.31/zip.h     2005-11-10 13:18:57.653283912 +0100
+@@ -236,6 +236,7 @@
+ #define DOSTIME_MINIMUM         ((ulg)0x00210000L)
+ #define DOSTIME_2038_01_18      ((ulg)0x74320000L)
++#define MAX_ZIP_SIZE 0xffffdffe /* Max archive / archive member size */
+ /* Public globals */
+ extern uch upper[256];          /* Country dependent case map table */
+@@ -411,6 +412,11 @@
+ int putcentral OF((struct zlist far *, FILE *));
+ int putend OF((int, ulg, ulg, extent, char *, FILE *));
+ int zipcopy OF((struct zlist far *, FILE *, FILE *));
++#ifdef _LARGEFILE64_SOURCE
++int lfseek OF((FILE *, ulg, int));
++ulg lftell OF((FILE *));
++FILE *lfopen OF((const char *, const char *));
++#endif /* LF64 */
+         /* in fileio.c */
+ #ifndef UTIL
+--- zip-2.31/tailor.h.4GB      2005-03-04 08:45:26.000000000 +0100
++++ zip-2.31/tailor.h  2005-11-10 13:11:18.909023640 +0100
+@@ -368,12 +368,27 @@
+ #   define DYN_ALLOC
+ #endif
++#ifdef _LARGEFILE64_SOURCE
++#define fopen lfopen
++#define fseek lfseek
++#define ftell lftell
++#endif /* LF64 */
++
+ #ifndef SSTAT
+-#  define SSTAT      stat
++#  ifdef _LARGEFILE64_SOURCE
++#    define SSTAT      stat64
++#  else
++#    define SSTAT      stat
++#  endif /* LF64 */
+ #endif
+ #ifdef S_IFLNK
+-#  define LSTAT      lstat
+-#  define LSSTAT(n, s)  (linkput ? lstat((n), (s)) : SSTAT((n), (s)))
++#  ifdef _LARGEFILE64_SOURCE
++#    define LSTAT      lstat64
++#    define LSSTAT(n, s)  (linkput ? lstat64((n), (s)) : SSTAT((n), (s)))
++#  else
++#    define LSTAT      lstat64
++#    define LSSTAT(n, s)  (linkput ? lstat64((n), (s)) : SSTAT((n), (s)))
++#  endif /* LF64 */
+ #else
+ #  define LSTAT      SSTAT
+ #  define LSSTAT     SSTAT
diff --git a/packaging/zip.spec b/packaging/zip.spec
new file mode 100644 (file)
index 0000000..19846da
--- /dev/null
@@ -0,0 +1,180 @@
+Summary: A file compression and packaging utility compatible with PKZIP.
+Name: zip
+Version: 2.31
+Release: 1.2.2
+License: distributable
+Group: Applications/Archiving
+Source: http://ftp.info-zip.org/pub/infozip/src/zip-2.31.tar.gz
+Source1: ftp://ftp.freesoftware.com/pub/infozip/src/zcrypt29.tar.gz
+URL: http://www.info-zip.org/pub/infozip/Zip.html
+Patch0: zip23.patch
+Patch1: exec-shield.patch
+Patch2: zip23-umask.patch
+Patch5: zip-2.3-currdir.patch
+Patch6: zip-2.31-install.patch
+Patch7: zip-2.31-near-4GB.patch
+Patch8: zip-2.31-configure.patch
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+
+%description
+The zip program is a compression and file packaging utility.  Zip is
+analogous to a combination of the UNIX tar and compress commands and
+is compatible with PKZIP (a compression and file packaging utility for
+MS-DOS systems).
+
+Install the zip package if you need to compress files using the zip
+program.
+
+%prep
+%setup -q -a 1
+%patch0 -p1 -b .zip
+%patch1 -p1 -b .zip
+%patch2 -p1 -b .umask
+%patch5 -p1 -b .currdir
+%patch6 -p1 -b .install
+%patch7 -p1 -b .4gb
+%patch8 -p1 -b .lhh
+
+%build
+make -f unix/Makefile prefix=/usr "CFLAGS=$RPM_OPT_FLAGS -I. -DUNIX -D_LARGEFILE64_SOURCE" generic_gcc
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/usr/bin
+mkdir -p $RPM_BULD_ROOT%{_mandir}/man1
+
+make -f unix/Makefile prefix=$RPM_BUILD_ROOT/usr \
+       MANDIR=$RPM_BUILD_ROOT%{_mandir}/man1 install
+
+pushd $RPM_BUILD_ROOT
+for n in zipnote zipsplit zip zipcloak ; do
+    chmod 755 ./usr/bin/$n
+done
+popd
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc README BUGS CHANGES MANUAL TODO WHATSNEW WHERE LICENSE
+%doc proginfo/algorith.txt
+/usr/bin/zipnote
+/usr/bin/zipsplit
+/usr/bin/zip
+/usr/bin/zipcloak
+%{_mandir}/man1/zip.1*
+
+%changelog
+* Wed Jul 12 2006 Jesse Keating <jkeating@redhat.com> - 2.31-1.2.2
+- rebuild
+
+* Fri Feb 10 2006 Jesse Keating <jkeating@redhat.com> - 2.31-1.2.1
+- bump again for double-long bug on ppc(64)
+
+* Tue Feb 07 2006 Jesse Keating <jkeating@redhat.com> - 2.31-1.2
+- rebuilt for new gcc4.1 snapshot and glibc changes
+
+* Fri Dec 09 2005 Jesse Keating <jkeating@redhat.com>
+- rebuilt
+
+* Thu Nov 10 2005 Ivana Varekova <varekova@redhat.com> 2.31-1
+- update to 2.31
+
+* Mon Mar  7 2005 Ivana Varekova <varekova@redhat.com> 2.3-30
+- rebuilt
+
+* Mon Jan 17 2005 Ivana Varekova <varekova@redhat.com> 2.3-29
+- Fix bug #142237 - problem with -d and ./files containing archives
+
+* Mon Jun 21 2004 Lon Hohberger <lhh@redhat.com> 2.3-24
+- Extend max file/archive size to 2^32-8193 (4294959103) bytes
+- Include better debugging output for configure script
+
+* Tue Jun 15 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Fri Mar 19 2004 Lon Hohberger <lhh@redhat.com> 2.3-22
+- Fix typos
+
+* Tue Feb 17 2004 Lon Hohberger <lhh@redhat.com> 2.3-21
+- Include LICENSE file per bugzilla #116004
+
+* Fri Feb 13 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Mon Dec 22 2003 Lon Hohberger <lhh@redhat.com> 2.3-19
+- Make temp file have umask 0066 mode (#112516)
+
+* Fri Oct 24 2003 Lon Hohberger <lhh@redhat.com> 2.3-18
+- Incorporate Arjan's exec-shield patch for i386
+
+* Wed Jun 04 2003 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Wed Jan 22 2003 Tim Powers <timp@redhat.com>
+- rebuilt
+
+* Thu Dec 19 2002 Tim Powers <timp@redhat.com>
+- bump and rebuild
+
+* Fri Jun 21 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Thu May 23 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Tue Apr  2 2002 Trond Eivind Glomsrød <teg@redhat.com>
+- Don't strip explicitly
+
+* Wed Mar 13 2002 Trond Eivind Glomsrød <teg@redhat.com> 2.3-11
+- Add URL
+
+* Sun Jun 24 2001 Elliot Lee <sopwith@redhat.com>
+- Bump release + rebuild.
+
+* Thu Aug 25 2000 Bill Nottingham <notting@redhat.com>
+- add encryption code (#16878)
+
+* Thu Jul 13 2000 Prospector <bugzilla@redhat.com>
+- automatic rebuild
+
+* Sun Jun 11 2000 Bill Nottingham <notting@redhat.com>
+- rebuild in new environment
+
+* Mon Mar 13 2000 Bill Nottingham <notting@redhat.com>
+- spec file cleanups (#10143)
+
+* Mon Feb  7 2000 Bill Nottingham <notting@redhat.com>
+- fix some perms
+
+* Wed Feb 02 2000 Cristian Gafton <gafton@redhat.com>
+- fix description
+- man pages are compressed
+
+* Tue Jan 11 2000 Bill Nottingham <notting@redhat.com>
+- update to 2.3
+
+* Fri Jul 30 1999 Bill Nottingham <notting@redhat.com>
+- update to 2.2
+
+* Sun Mar 21 1999 Cristian Gafton <gafton@redhat.com> 
+- auto rebuild in the new build environment (release 8)
+
+* Thu Mar 18 1999 Cristian Gafton <gafton@redhat.com>
+- updated text in the spec file
+
+* Fri Jan 15 1999 Cristian Gafton <gafton@redhat.com>
+- patch top build on the arm
+
+* Mon Dec 21 1998 Michael Maher <mike@redhat.com>
+- built package for 6.0
+
+* Mon Aug 10 1998 Jeff Johnson <jbj@redhat.com>
+- build root
+
+* Fri May 08 1998 Prospector System <bugs@redhat.com>
+- translations modified for de, fr, tr
+
+* Thu Jul 10 1997 Erik Troan <ewt@redhat.com>
+- built against glibc
diff --git a/packaging/zip23-umask.patch b/packaging/zip23-umask.patch
new file mode 100644 (file)
index 0000000..7ab6005
--- /dev/null
@@ -0,0 +1,23 @@
+diff -ur zip-2.3/zip.c zip-2.3-lhh/zip.c
+--- zip-2.3/zip.c      1999-11-16 15:08:10.000000000 -0500
++++ zip-2.3-lhh/zip.c  2003-12-22 09:32:56.000000000 -0500
+@@ -849,6 +849,7 @@
+ /* Add, update, freshen, or delete zip entries in a zip file.  See the
+    command help in help() above. */
+ {
++  mode_t old_umask;   /* umask prior to temp file creation */
+   int a;                /* attributes of zip file */
+   ulg c;                /* start of central directory */
+   int d;                /* true if just adding to a zip file */
+@@ -1830,9 +1831,11 @@
+     if ((tempzip = tempname(zipfile)) == NULL) {
+       ZIPERR(ZE_MEM, "allocating temp filename");
+     }
++    old_umask = umask(0066);
+     if ((tempzf = y = fopen(tempzip, FOPW_TMP)) == NULL) {
+       ZIPERR(ZE_TEMP, tempzip);
+     }
++    umask(old_umask);
+   }
+ #if (!defined(VMS) && !defined(CMS_MVS))
diff --git a/packaging/zip23.patch b/packaging/zip23.patch
new file mode 100644 (file)
index 0000000..690630c
--- /dev/null
@@ -0,0 +1,93 @@
+--- zip-2.3/zip.h.zip  Mon Nov  8 14:36:51 1999
++++ zip-2.3/zip.h      Tue Jan 11 11:46:06 2000
+@@ -60,6 +60,7 @@
+ /* Set up portability */
+ #include "tailor.h"
++#include <strings.h>
+ #ifdef USE_ZLIB
+ #  include "zlib.h"
+@@ -433,12 +434,6 @@
+ int setfileattr OF((char *, int));
+ char *tempname OF((char *));
+ int fcopy OF((FILE *, FILE *, ulg));
+-
+-#ifdef ZMEM
+-   char *memset OF((char *, int, unsigned int));
+-   char *memcpy OF((char *, char *, unsigned int));
+-   int memcmp OF((char *, char *, unsigned int));
+-#endif /* ZMEM */
+         /* in system dependent fileio code (<system>.c) */
+ #ifndef UTIL
+--- zip-2.3/fileio.c.zip       Sun Nov  7 05:29:03 1999
++++ zip-2.3/fileio.c   Tue Jan 11 11:46:43 2000
+@@ -918,67 +918,3 @@
+ }
+ #endif /* NO_RENAME */
+-
+-
+-#ifdef ZMEM
+-
+-/************************/
+-/*  Function memset()   */
+-/************************/
+-
+-/*
+- * memset - for systems without it
+- *  bill davidsen - March 1990
+- */
+-
+-char *
+-memset(buf, init, len)
+-register char *buf;     /* buffer loc */
+-register int init;      /* initializer */
+-register unsigned int len;   /* length of the buffer */
+-{
+-    char *start;
+-
+-    start = buf;
+-    while (len--) *(buf++) = init;
+-    return(start);
+-}
+-
+-
+-/************************/
+-/*  Function memcpy()   */
+-/************************/
+-
+-char *
+-memcpy(dst,src,len)             /* v2.0f */
+-register char *dst, *src;
+-register unsigned int len;
+-{
+-    char *start;
+-
+-    start = dst;
+-    while (len--)
+-        *dst++ = *src++;
+-    return(start);
+-}
+-
+-
+-/************************/
+-/*  Function memcmp()   */
+-/************************/
+-
+-int
+-memcmp(b1,b2,len)                     /* jpd@usl.edu -- 11/16/90 */
+-register char *b1, *b2;
+-register unsigned int len;
+-{
+-
+-    if (len) do {       /* examine each byte (if any) */
+-      if (*b1++ != *b2++)
+-        return (*((uch *)b1-1) - *((uch *)b2-1));  /* exit when miscompare */
+-    } while (--len);
+-
+-    return(0);          /* no miscompares, yield 0 result */
+-}
+-
+-#endif  /* ZMEM */
diff --git a/proginfo/3rdparty.bug b/proginfo/3rdparty.bug
new file mode 100644 (file)
index 0000000..32e7823
--- /dev/null
@@ -0,0 +1,114 @@
+Known, current PKZIP bugs/limitations:
+-------------------------------------
+
+ - PKUNZIP 2.04g is reported to corrupt some files when compressing them with
+   the -ex option; when tested, the files fail the CRC check, and comparison
+   with the original file shows bogus data (6K in one case) embedded in the
+   middle.  PKWARE apparently characterized this as a "known problem."
+
+ - PKUNZIP 2.04g considers volume labels valid only if originated on a FAT
+   file system, but other OSes and file systems (e.g., Amiga and OS/2 HPFS)
+   support volume labels, too.
+
+ - PKUNZIP 2.04g can restore volume labels created by Zip 2.x but not by
+   PKZIP 2.04g (OS/2 DOS box only??).
+
+ - PKUNZIP 2.04g gives an error message for stored directory entries created
+   under other OSes (although it creates the directory anyway), and PKZIP -vt
+   does not report the directory attribute bit as being set, even if it is.
+
+ - PKZIP 2.04g mangles unknown extra fields (especially OS/2 extended attri-
+   butes) when adding new files to an existing zipfile [example:  Walnut Creek
+   Hobbes March 1995 CD-ROM, FILE_ID.DIZ additions].
+
+ - PKUNZIP 2.04g is unable to detect or deal with prepended junk in a zipfile,
+   reporting CRC errors in valid compressed data.
+
+ - PKUNZIP 2.04g (registered version) incorrectly updates/freshens the AV extra
+   field in authenticated archives.  The resultant extra block length and total
+   extra field length are inconsistent.
+
+ - [Windows version 2.01] Win95 long filenames (VFAT) are stored OK, but the
+   file system is always listed as ordinary DOS FAT.
+
+ - [Windows version 2.50] NT long filenames (NTFS) are stored OK, but the
+   file system is always listed as ordinary DOS FAT.
+
+ - PKZIP 2.04 for DOS encrypts using the OEM code page for 8-bit passwords,
+   while PKZIP 2.50 for Windows uses Latin-1 (ISO 8859-1).  This means an
+   archive encrypted with an 8-bit password with one of the two PKZIP versions
+   cannot be decrypted with the other version.
+
+ - PKZIP for Windows GUI (v 2.60), PKZIP for Windows command line (v 2.50) and
+   PKZIP for Unix (v 2.51) save the host's native file timestamps, but
+   only in a local extra field. Thus, timestamp-related selections (update
+   or freshen, both in extraction or archiving operations) use the DOS-format
+   localtime records in the Zip archives for comparisons. This may result
+   in wrong decisions of the program when updating archives that were
+   previously created in a different local time zone.
+
+ - PKZIP releases newer than PKZIP for DOS 2.04g (PKZIP for Windows, both
+   GUI v 2.60 and console v 2.50; PKZIP for Unix v 2.51; probably others too)
+   use different code pages for storing filenames in central (OEM Codepage)
+   and local (ANSI / ISO 8859-1 Codepage) headers. When a stored filename
+   contains extended-ASCII characters, the local and central filename fields
+   do not match. As a consequence, Info-ZIP's Zip program considers such
+   archives as being corrupt and does not allow to modify them. Beginning
+   with release 5.41, Info-ZIP's UnZip contains a workaround to list AND
+   extract such archives with the correct filenames.
+   Maybe PKWARE has implemented this "feature" to allow extraction of their
+   "made-by-PKZIP for Unix/Windows" archives using old (v5.2 and earlier)
+   versions of Info-ZIP's UnZip for Unix/WinNT ??? (UnZip versions before
+   v 5.3 assumed that all archive entries were encoded in the codepage of
+   the UnZip program's host system.)
+
+ - PKUNZIP 2.04g is reported to have problems with archives created on and/or
+   copied from Iomega ZIP drives (irony, eh?).
+
+Known, current WinZip bugs/limitations:
+--------------------------------------
+
+ - [16-bit version 6.1a] NT short filenames (FAT) are stored OK, but the
+   file system is always listed as NTFS.
+
+ - WinZip doesn't allow 8-bit passwords, which means it cannot decrypt an
+   archive created with an 8-bit password (by PKZIP or Info-ZIP's Zip).
+
+ - WinZip (at least Versions 6.3 PL1, 7.0 SR1) fails to remove old extra
+   fields when freshening existing archive entries. When updating archives
+   created by Info-ZIP's Zip that contain UT time stamp extra field blocks,
+   UnZip cannot display or restore the updated (DOS) time stamps of the
+   freshened archive members.
+
+Known, current other third-party Zip utils bugs/limitations:
+------------------------------------------------------------
+
+ - Asi's PKZip clones for Macintosh (versions 2.3 and 2.10d) are thoroughly
+   broken. They create invalid Zip archives!
+   a) For the first entry, both compressed size and uncompressed length
+      are recorded as 0, despite the fact that compressed data of non-zero
+      length has been added.
+   b) Their program creates extra fields with an (undocumented) internal
+      structure that violates the requirements of PKWARE's Zip format
+      specification document "appnote.txt": Their extra field seems to
+      contain pure data; the 4-byte block header consisting of block ID
+      and data length is missing.
+
+Possibly current PKZIP bugs:
+---------------------------
+
+ - PKZIP (2.04g?) can silently ignore read errors on network drives, storing
+   the correct CRC and compressed length but an incorrect and inconsistent
+   uncompressed length.
+
+ - PKZIP (2.04g?), when deleting files from within a zipfile on a Novell
+   drive, sometimes only zeros out the data while failing to shrink the
+   zipfile.
+
+Other limitations:
+-----------------
+
+ - PKZIP 1.x and 2.x encryption has been cracked (known-plaintext approach;
+   see http://www.cryptography.com/ for details).
+
+[many other bugs in PKZIP 1.0, 1.1, 1.93a, 2.04c and 2.04e]
diff --git a/proginfo/ZipPorts b/proginfo/ZipPorts
new file mode 100644 (file)
index 0000000..2d946d3
--- /dev/null
@@ -0,0 +1,285 @@
+__________________________________________________________________________
+
+  This is the Info-ZIP file ZipPorts, last updated on 17 February 1996.
+__________________________________________________________________________
+
+
+This document defines a set of rules and guidelines for those who wish to
+contribute patches to Zip and UnZip (or even entire ports to new operating
+systems).  The list below is something between a style sheet and a "Miss
+Manners" etiquette guide.  While Info-ZIP encourages contributions and
+fixes from anyone who finds something worth changing, we are also aware
+of the fact that no two programmers have the programming style and that
+unrestrained changes by a few dozen contributors would result in hideously
+ugly (and unmaintainable) Frankenstein code.  So consider the following an
+attempt by the maintainers to maintain sanity as well as useful code.
+
+(The first version of this document was called either "ZipRules" or the
+"No Feelthy ..." file and was compiled by David Kirschbaum in consulta-
+tion with Mark Adler, Cave McNewt and others.  The current incarnation
+expands upon the original with insights gained from a few more years of
+happy hacking...)
+
+
+Summary:
+
+  (0) The Platinum Rule:  DON'T BREAK EXISTING PORTS
+(0.1) The Golden Rule:    DO UNTO THE CODE AS OTHERS HAVE DONE BEFORE
+(0.2) The Silver Rule:    DO UNTO THE LATEST BETA CODE
+(0.3) The Bronze Rule:    NO FEELTHY PIGGYBACKS
+
+  (1) NO FEELTHY TABS
+  (2) NO FEELTHY CARRIAGE RETURNS
+  (3) NO FEELTHY 8-BIT CHARS
+  (4) NO FEELTHY LEFT-JUSTIFIED DASHES
+  (5) NO FEELTHY FANCY_FILENAMES
+  (6) NO FEELTHY NON-ZIPFILES AND NO FEELTHY E-MAIL BETAS
+  (7) NO FEELTHY E-MAIL BINARIES
+
+
+Explanations:
+
+  (0) The Platinum Rule:  DON'T BREAK EXISTING PORTS
+
+      No doubt about it, this is the one which really pisses us off and
+      pretty much guarantees that your port or patch will be ignored and/
+      or laughed at.  Examples range from the *really* severe cases which
+      "port" by ripping out all of the existing multi-OS code, to more
+      subtle oopers like relying on a local capability which doesn't exist
+      on other OSes or in older compilers (e.g., the use of ANSI "#elif"
+      or "#pragma" or "##" constructs, C++ comments, GNU extensions, etc.).
+      As to the former, use #ifdefs for your new code (see rule 0.3).  And
+      as to the latter, trust us--there are few things we'd like better
+      than to be able to use some of the elegant "new" features out there
+      (many of which have been around for a decade or more).  But our code
+      still compiles on machines dating back even longer, at least in spirit
+      --e.g., the AT&T 3B1 family and Dynix/ptx.  Until we say otherwise,
+      dinosaurs are supported.
+
+
+(0.1) The Golden Rule:  DO UNTO THE CODE AS OTHERS HAVE DONE BEFORE
+
+      In other words, try to fit into the local style of programming--no
+      matter how painful it may be.  This includes cosmetic aspects like
+      indenting the same amount (both in the main C code and in the in-
+      clude files), using braces and comments similarly, NO TABS (see rule
+      #1), etc.; but also more substantive things like (for UnZip) putting
+      character strings into static (far) variables and using the LoadFar-
+      String macros to avoid overflowing limited MS-DOS data segments, and
+      using the ugly Info() macro instead of the more usual *printf()
+      functions so that dynamic-link-library ports are simpler.  NEVER put
+      single-OS code (e.g., OS/2) of more than two or three lines into the
+      main (generic) modules; those are shared by everybody, and nobody else
+      cares about it or wants to see it.
+
+      Note that not only do Zip and UnZip differ in these respects, so do
+      individual parts of each program.  While it would be nice to have
+      global consistency, cosmetic changes are not a high priority; for
+      now we'll settle for local consistency--i.e., don't make things any
+      worse than they already are.
+
+      Exception (BIG exception):  single-letter variable names.  Despite
+      the prevailing practice in much of Zip and parts of UnZip, and de-
+      spite the fact that one-letter variables allow you to pack really
+      cool, compact and complicated expressions onto one line, they also
+      make the code very difficult to maintain and are therefore *strongly*
+      discouraged.  Don't ask us who is responsible in the first place;
+      while this sort of brain damage is not uncommon among former BASIC
+      programmers, it is nevertheless a lifelong embarrassment, and we do
+      try to pity the poor sod (that is, when we're not chasing bugs and
+      cursing him).  :-)
+
+
+(0.2) The Silver Rule:  DO UNTO THE LATEST BETA CODE
+
+      Few things are as annoying as receiving a large patch which obviously
+      represents a lot of time and careful work but which is relative to
+      an old version of Info-ZIP code.  As wonderful as Larry Wall's patch
+      program is at applying context diffs to modified code, we regularly
+      make near-global changes and/or reorganize big chunks of the sources
+      (particularly in UnZip), and "patch" can't work miracles--big changes
+      invariably break any patch which is relative to an old version of the
+      code.
+
+      Bottom line:  contact the Info-ZIP core team FIRST (via the zip-bugs
+      e-mail address) and get up to date with the latest code before begin-
+      ning a big new port.  And try to *stay* up to date while working on
+      your port--at least, as much as possible.
+
+
+(0.3) The Bronze Rule:  NO FEELTHY PIGGYBACKS
+
+      UnZip is currently ported to something like 12 operating systems
+      (a few more or less depending on how one counts), and each of these,
+      with the possible exception of VM/CMS, has a unique macro identifying
+      it:  AMIGA, ATARI_ST, __human68k__, MACOS, MSDOS, MVS, OS2, TOPS20,
+      UNIX, VMS, WIN32.  Zip is moving in the same direction.  New ports
+      should NOT piggyback one of the existing ports unless they are sub-
+      stantially similar--for example, Minix and Coherent are basically Unix
+      and therefore are included in the UNIX macro, but DOS djgpp ports and
+      OS/2 emx ports (both of which use the Unix-originated GNU C compiler
+      and often have "unix" defined by default) are obviously *not* Unix.
+      [The existing MTS port is a special exception; basically only one per-
+      son knows what MTS really is, and he's not telling.  Presumably it's
+      not very close to Unix, but it's not worth arguing about it now.]
+      Along the same lines, neither OS/2 nor Human68K is the same as (or
+      even close to) MS-DOS.  MVS and VM/CMS, on the other hand, are quite
+      similar to each other and are therefore combined in most places.
+
+      Bottom line:  when adding a new port (e.g., QDOS), create a new macro
+      for it ("QDOS"), a new subdirectory ("qdos") and a new source file for
+      OS-specific code ("qdos/qdos.c").  Use #ifdefs to fit any OS-specific
+      changes into the existing code (e.g., unzpriv.h).  If it's close enough
+      to an existing port that piggybacking is a temptation, define a new
+      "combination macro" (e.g., "CMS_MVS") and replace the old macros as
+      required.  (This last applies to UnZip, at least; the old preference
+      in Zip was fewer macros and long #ifdef lines, so talk to Onno or Jean-
+      loup about that.)  See also rule 0.1.
+
+      (Note that, for UnZip, new ports need not attempt to deal with all
+      features.  Among other things, the wildcard-zipfile code in do_wild()
+      may be replaced with a supplied dummy version, since opendir/readdir/
+      closedir() or the equivalent can be difficult to implement.)
+
+
+  (1) NO FEELTHY TABS
+
+      Some editors and e-mail systems either have no capability to use
+      and/or display tab characters (ASCII 9) correctly, or they use non-
+      standard or variable-width tab columns, or other horrors.  Some edi-
+      tors auto-convert spaces to tabs, after which the blind use of "diff
+      -c" results in a huge and mostly useless patch.  Yes, *we* know about
+      diff's "-b" option, but not everyone does.  And yes, we also know this
+      makes the source files bigger, even after compression; so be it.  If
+      we *really* cared that much about the size of the sources, we'd still
+      be writing Unix-only utilities.
+
+      Bottom line:  use spaces, not tabs.
+
+      Exception:  some of the makefiles (the Unix one in particular) require
+      tabs as part of the syntax.
+
+      Related utility programs:
+          Unix, OS/2 and MS-DOS:  expand, unexpand.
+          MS-DOS:  Buerg's TABS; Toad Hall's TOADSOFT.
+          And some editors have the conversion built-in.
+
+
+  (2) NO FEELTHY CARRIAGE RETURNS
+
+      All source, documentation and other text files shall have Unix style
+      line endings (LF only, a.k.a. ctrl-J), not the DOS/OS2/NT CR+LF or Mac
+      CR-only line endings.
+
+      Reason:  "real programmers" in any environment can convert back and
+      forth between Unix and DOS/Mac style.  All PC compilers but a few old
+      Borland versions can use either Unix or MS-DOS end-of-lines.  Buerg's
+      LIST (file-display utility) for MS-DOS can use Unix or MS-DOS EOLs.
+      Both Zip and UnZip can convert line-endings as appropriate.  But Unix
+      utilities like diff and patch die a horrible death (or produce horrible
+      output) if the target files have CRs.
+
+      Related utilities:  flip for Unix, OS/2 and MS-DOS; Unix "tr".
+
+      Exceptions:  documentation in pre-compiled binary distributions should
+      be in the local (target) format.
+
+
+  (3) NO FEELTHY 8-BIT CHARS
+
+      Do all your editing in a plain-text ASCII editor.  No WordPerfect, MS
+      Word, WordStar document mode, or other word processor files, thenkyew.
+      No desktop publishing.  *Especially* no EBCDIC.  No TIFFs, no GIFs, no
+      embedded pictures or dancing ladies (too bad, Cave Newt).  [Sigh... -CN]
+
+      Reason:  compatibility with different consoles.  My old XT clone is
+      the most limited!
+
+      Exceptions:  some Macintosh makefiles apparently require some 8-bit
+      characters; the Human68k port uses 8-bit characters for Kanji or Kana
+      comments (I think); etc.
+
+      Related utilities:  vi, emacs, EDLIN, Turbo C editor, other programmers'
+      editors, various word processor -> text conversion utilities.
+
+
+  (4) NO FEELTHY LEFT-JUSTIFIED DASHES
+
+      Always precede repeated dashes (------) with one or more leading non-
+      dash characters:  spaces, tabs, pound signs (#), comments (/*), what-
+      ever.
+
+      Reason:  sooner or later your source file will be e-mailed through an
+      undigestifier utility, most of which treat leading dashes as end-of-
+      message separators.  We'd rather not have your code broken up into a
+      dozen separate untitled messages, thank you.
+
+
+  (5) NO FEELTHY FANCY_FILENAMES
+
+      Assume the worst:  that someone on a brain-damaged DOS system has to
+      work with everything your magic fingers produced.  Keep the filenames
+      unimaginative and within MS-DOS limits (i.e., ordinary A..Z, 1..9,
+      "-$_!"-type characters, in the 8.3 "filename.ext" format).  Mac and
+      Unix users, giggle all you want, but no spaces or multiple dots.
+
+      Reason:  compatibility with different file systems.  MS-DOS FAT is the
+      most limited, with the exception of CompuServe (6.3, argh).
+
+      Exceptions:  slightly longer names are occasionally acceptable within
+      OS-specific subdirectories, but don't do that unless there's a good
+      reason for it.
+
+
+  (6) NO FEELTHY NON-ZIPFILES AND NO FEELTHY E-MAIL BETAS
+
+      Beta testers and developers are in general expected to have both
+      ftp capability and the ability to deal with zipfiles.  Those without
+      should either find a friend who does or else learn about ftp-mailers.
+
+      Reason:  the core development team barely has time to work on the
+      code, much less prepare oddball formats and/or mail betas out (and
+      the situation is getting worse, sigh).
+
+      Exceptions:  anyone seriously proposing to do a new port will be
+      given special treatment, particularly with respect to UnZip; we
+      obviously realize that bootstrapping a completely new port can be
+      quite difficult and have no desire to make it even harder due to
+      lack of access to the latest code (rule 0.2).
+
+      Public releases of UnZip, on the other hand, will be available in
+      two formats:  .tar.Z (16-bit compress'd tar) and .zip (either "plain"
+      or self-extracting).  Zip sources and executables will generally only
+      be distributed in .zip format, since Zip is pretty much useless without
+      UnZip.
+
+
+  (7) NO FEELTHY E-MAIL BINARIES
+
+      Binary files (e.g., executables, test zipfiles, etc.) should NEVER
+      be mailed raw.  Where possible, they should be uploaded via ftp in
+      BINARY mode; if that's impossible, Mark's "ship" ASCII-encoder should
+      be used; and if that's unavailable, uuencode or xxencode should be
+      used.  Weirdo NeXTmail, mailtool and MIME formats are also Right Out.
+
+      Files larger than 50KB may need to be broken into pieces for mailing
+      (be sure to label them in order!), unless "ship" is used (it can
+      auto-split, label and mail files if told to do so).  If Down Under
+      is involved, files must be broken into under-20KB chunks.
+
+      Reasons:  to prevent sounds of gagging mailers from resounding through-
+      out the land.  To be relatively efficient in the binary->ASCII conver-
+      sion.  (Yeah, yeah, I know, there's better conversions out there.  But
+      not as widely known, and they often break on BITNET gateways.)
+
+      Related utilities:  ship, uuencode, uudecode, uuxfer20, quux, others.
+      Just make sure they don't leave embedded or trailing spaces (that is,
+      they should use the "`" character in place of ASCII 32).  Otherwise
+      mailers are prone to truncate or whatever.
+
+
+Greg Roelofs (a.k.a. Cave Newt)
+Info-ZIP UnZip maintainer
+
+David Kirschbaum
+former Info-ZIP Coordinator
diff --git a/proginfo/algorith.txt b/proginfo/algorith.txt
new file mode 100644 (file)
index 0000000..867e30b
--- /dev/null
@@ -0,0 +1,68 @@
+Zip's deflation algorithm is a variation of LZ77 (Lempel-Ziv 1977, see
+reference below). It finds duplicated strings in the input data.  The
+second occurrence of a string is replaced by a pointer to the previous
+string, in the form of a pair (distance, length).  Distances are
+limited to 32K bytes, and lengths are limited to 258 bytes. When a
+string does not occur anywhere in the previous 32K bytes, it is
+emitted as a sequence of literal bytes.  (In this description,
+'string' must be taken as an arbitrary sequence of bytes, and is not
+restricted to printable characters.)
+
+Literals or match lengths are compressed with one Huffman tree, and
+match distances are compressed with another tree. The trees are stored
+in a compact form at the start of each block. The blocks can have any
+size (except that the compressed data for one block must fit in
+available memory). A block is terminated when zip determines that it
+would be useful to start another block with fresh trees. (This is
+somewhat similar to compress.)
+
+Duplicated strings are found using a hash table. All input strings of
+length 3 are inserted in the hash table. A hash index is computed for
+the next 3 bytes. If the hash chain for this index is not empty, all
+strings in the chain are compared with the current input string, and
+the longest match is selected.
+
+The hash chains are searched starting with the most recent strings, to
+favor small distances and thus take advantage of the Huffman encoding.
+The hash chains are singly linked. There are no deletions from the
+hash chains, the algorithm simply discards matches that are too old.
+
+To avoid a worst-case situation, very long hash chains are arbitrarily
+truncated at a certain length, determined by a runtime option (zip -1
+to -9). So zip does not always find the longest possible match but
+generally finds a match which is long enough.
+
+zip also defers the selection of matches with a lazy evaluation
+mechanism. After a match of length N has been found, zip searches for a
+longer match at the next input byte. If a longer match is found, the
+previous match is truncated to a length of one (thus producing a single
+literal byte) and the longer match is emitted afterwards.  Otherwise,
+the original match is kept, and the next match search is attempted only
+N steps later.
+
+The lazy match evaluation is also subject to a runtime parameter. If
+the current match is long enough, zip reduces the search for a longer
+match, thus speeding up the whole process. If compression ratio is more
+important than speed, zip attempts a complete second search even if
+the first match is already long enough.
+
+The lazy match evaluation is not performed for the fastest compression
+modes (speed options -1 to -3). For these fast modes, new strings
+are inserted in the hash table only when no match was found, or
+when the match is not too long. This degrades the compression ratio
+but saves time since there are both fewer insertions and fewer searches.
+
+Jean-loup Gailly
+jloup@chorus.fr
+
+References:
+
+[LZ77] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data
+Compression", IEEE Transactions on Information Theory", Vol. 23, No. 3,
+pp. 337-343.
+
+APPNOTE.TXT documentation file in PKZIP 1.93a. It is available by
+ftp in ftp.cso.uiuc.edu:/pc/exec-pc/pkz193a.exe [128.174.5.59]
+
+'Deflate' Compressed Data Format Specification:
+ftp://ftp.uu.net/pub/archiving/zip/doc/deflate-1.1.doc
diff --git a/proginfo/extra.fld b/proginfo/extra.fld
new file mode 100644 (file)
index 0000000..769fef1
--- /dev/null
@@ -0,0 +1,1441 @@
+The following are the known types of zipfile extra fields as of this
+writing.  Extra fields are documented in PKWARE's appnote.txt and are
+intended to allow for backward- and forward-compatible extensions to
+the zipfile format.  Multiple extra-field types may be chained together,
+provided that the total length of all extra-field data is less than 64KB.
+(In fact, PKWARE requires that the total length of the entire file header,
+including timestamp, file attributes, filename, comment, extra field, etc.,
+be no more than 64KB.)
+
+Each extra-field type (or subblock) must contain a four-byte header con-
+sisting of a two-byte header ID and a two-byte length (little-endian) for
+the remaining data in the subblock.  If there are additional subblocks
+within the extra field, the header for each one will appear immediately
+following the data for the previous subblock (i.e., with no padding for
+alignment).
+
+All integer fields in the descriptions below are in little-endian (Intel)
+format unless otherwise specified.  Note that "Short" means two bytes,
+"Long" means four bytes, and "Long-Long" means eight bytes, regardless
+of their native sizes.  Unless specifically noted, all integer fields should
+be interpreted as unsigned (non-negative) numbers.
+
+Christian Spieler, 20040507
+
+                        -------------------------
+
+          Header ID's of 0 thru 31 are reserved for use by PKWARE.
+          The remaining ID's can be used by third party vendors for
+          proprietary usage.
+
+          The current Header ID mappings defined by PKWARE are:
+
+          0x0001        ZIP64 extended information extra field
+          0x0007        AV Info
+          0x0008        Reserved for future Unicode file name data (PFS)
+          0x0009        OS/2 extended attributes      (also Info-ZIP)
+          0x000a        NTFS (Win9x/WinNT FileTimes)
+          0x000c        OpenVMS                       (also Info-ZIP)
+          0x000d        Unix
+          0x000e        Reserved for file stream and fork descriptors
+          0x000f        Patch Descriptor
+          0x0014        PKCS#7 Store for X.509 Certificates
+          0x0015        X.509 Certificate ID and Signature for
+                        individual file
+          0x0016        X.509 Certificate ID for Central Directory
+          0x0017        Strong Encryption Header
+          0x0018        Record Management Controls
+          0x0019        PKCS#7 Encryption Recipient Certificate List
+          0x0065        IBM S/390 (Z390), AS/400 (I400) attributes
+                        - uncompressed
+          0x0066        Reserved for IBM S/390 (Z390), AS/400 (I400)
+                        attributes - compressed
+
+          The Header ID mappings defined by Info-ZIP and third parties are:
+
+          0x07c8        Info-ZIP Macintosh (old, J. Lee)
+          0x2605        ZipIt Macintosh (first version)
+          0x2705        ZipIt Macintosh v 1.3.5 and newer (w/o full filename)
+          0x2805        ZipIt Macintosh 1.3.5+
+          0x334d        Info-ZIP Macintosh (new, D. Haase's 'Mac3' field)
+          0x4154        Tandem NSK
+          0x4341        Acorn/SparkFS (David Pilling)
+          0x4453        Windows NT security descriptor (binary ACL)
+          0x4704        VM/CMS
+          0x470f        MVS
+          0x4854        Theos, old inofficial port
+          0x4b46        FWKCS MD5 (see below)
+          0x4c41        OS/2 access control list (text ACL)
+          0x4d49        Info-ZIP OpenVMS (obsolete)
+          0x4d63        Macintosh SmartZIP, by Macro Bambini
+          0x4f4c        Xceed original location extra field
+          0x5356        AOS/VS (binary ACL)
+          0x5455        extended timestamp
+          0x554e        Xceed unicode extra field
+          0x5855        Info-ZIP Unix (original; also OS/2, NT, etc.)
+          0x6542        BeOS (BeBox, PowerMac, etc.)
+          0x6854        Theos
+          0x7441        AtheOS (AtheOS/Syllable attributes)
+          0x756e        ASi Unix
+          0x7855        Info-ZIP Unix (new)
+          0xfb4a        SMS/QDOS
+
+The following are detailed descriptions of the known extra-field block types:
+
+         -ZIP64 Extended Information Extra Field (0x0001):
+          ===============================================
+
+          The following is the layout of the ZIP64 extended
+          information "extra" block. If one of the size or
+          offset fields in the Local or Central directory
+          record is too small to hold the required data,
+          a ZIP64 extended information record is created.
+          The order of the fields in the ZIP64 extended
+          information record is fixed, but the fields will
+          only appear if the corresponding Local or Central
+          directory record field is set to 0xFFFF or 0xFFFFFFFF.
+
+          Note: all fields stored in Intel low-byte/high-byte order.
+
+          Value      Size       Description
+          -----      ----       -----------
+  (ZIP64) 0x0001     2 bytes    Tag for this "extra" block type
+          Size       2 bytes    Size of this "extra" block
+          Original
+          Size       8 bytes    Original uncompressed file size
+          Compressed
+          Size       8 bytes    Size of compressed data
+          Relative Header
+          Offset     8 bytes    Offset of local header record
+          Disk Start
+          Number     4 bytes    Number of the disk on which
+                                this file starts
+
+          This entry in the Local header must include BOTH original
+          and compressed file sizes.
+
+
+         -OS/2 Extended Attributes Extra Field (0x0009):
+          =============================================
+
+          The following is the layout of the OS/2 extended attributes "extra"
+          block.  (Last Revision 19960922)
+
+          Note: all fields stored in Intel low-byte/high-byte order.
+
+          Local-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (OS/2)  0x0009        Short       tag for this extra block type
+          TSize         Short       total data size for this block
+          BSize         Long        uncompressed EA data size
+          CType         Short       compression type
+          EACRC         Long        CRC value for uncompressed EA data
+          (var.)        variable    compressed EA data
+
+          Central-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (OS/2)  0x0009        Short       tag for this extra block type
+          TSize         Short       total data size for this block (4)
+          BSize         Long        size of uncompressed local EA data
+
+          The value of CType is interpreted according to the "compression
+          method" section above; i.e., 0 for stored, 8 for deflated, etc.
+
+          The OS/2 extended attribute structure (FEA2LIST) is
+          compressed and then stored in its entirety within this
+          structure.  There will only ever be one "block" of data in
+          the variable-length field.
+
+
+         -OS/2 Access Control List Extra Field:
+          ====================================
+
+          The following is the layout of the OS/2 ACL extra block.
+          (Last Revision 19960922)
+
+          Local-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (ACL)   0x4c41        Short       tag for this extra block type ("AL")
+          TSize         Short       total data size for this block
+          BSize         Long        uncompressed ACL data size
+          CType         Short       compression type
+          EACRC         Long        CRC value for uncompressed ACL data
+          (var.)        variable    compressed ACL data
+
+          Central-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (ACL)   0x4c41        Short       tag for this extra block type ("AL")
+          TSize         Short       total data size for this block (4)
+          BSize         Long        size of uncompressed local ACL data
+
+          The value of CType is interpreted according to the "compression
+          method" section above; i.e., 0 for stored, 8 for deflated, etc.
+
+          The uncompressed ACL data consist of a text header of the form
+          "ACL1:%hX,%hd\n", where the first field is the OS/2 ACCINFO acc_attr
+          member and the second is acc_count, followed by acc_count strings
+          of the form "%s,%hx\n", where the first field is acl_ugname (user
+          group name) and the second acl_access.  This block type will be
+          extended for other operating systems as needed.
+
+
+         -Windows NT Security Descriptor Extra Field (0x4453):
+          ===================================================
+
+          The following is the layout of the NT Security Descriptor (another
+          type of ACL) extra block.  (Last Revision 19960922)
+
+          Local-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (SD)    0x4453        Short       tag for this extra block type ("SD")
+          TSize         Short       total data size for this block
+          BSize         Long        uncompressed SD data size
+          Version       Byte        version of uncompressed SD data format
+          CType         Short       compression type
+          EACRC         Long        CRC value for uncompressed SD data
+          (var.)        variable    compressed SD data
+
+          Central-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (SD)    0x4453        Short       tag for this extra block type ("SD")
+          TSize         Short       total data size for this block (4)
+          BSize         Long        size of uncompressed local SD data
+
+          The value of CType is interpreted according to the "compression
+          method" section above; i.e., 0 for stored, 8 for deflated, etc.
+          Version specifies how the compressed data are to be interpreted
+          and allows for future expansion of this extra field type.  Currently
+          only version 0 is defined.
+
+          For version 0, the compressed data are to be interpreted as a single
+          valid Windows NT SECURITY_DESCRIPTOR data structure, in self-relative
+          format.
+
+
+         -PKWARE Win95/WinNT Extra Field (0x000a):
+          =======================================
+
+          The following description covers PKWARE's "NTFS" attributes
+          "extra" block, introduced with the release of PKZIP 2.50 for
+          Windows. (Last Revision 20001118)
+
+          (Note: At this time the Mtime, Atime and Ctime values may
+          be used on any WIN32 system.)
+         [Info-ZIP note: In the current implementations, this field has
+          a fixed total data size of 32 bytes and is only stored as local
+          extra field.]
+
+          Value         Size        Description
+          -----         ----        -----------
+  (NTFS)  0x000a        Short       Tag for this "extra" block type
+          TSize         Short       Total Data Size for this block
+          Reserved      Long        for future use
+          Tag1          Short       NTFS attribute tag value #1
+          Size1         Short       Size of attribute #1, in bytes
+          (var.)        SubSize1    Attribute #1 data
+          .
+          .
+          .
+          TagN          Short       NTFS attribute tag value #N
+          SizeN         Short       Size of attribute #N, in bytes
+          (var.)        SubSizeN    Attribute #N data
+
+          For NTFS, values for Tag1 through TagN are as follows:
+          (currently only one set of attributes is defined for NTFS)
+
+          Tag        Size       Description
+          -----      ----       -----------
+          0x0001     2 bytes    Tag for attribute #1
+          Size1      2 bytes    Size of attribute #1, in bytes (24)
+          Mtime      8 bytes    64-bit NTFS file last modification time
+          Atime      8 bytes    64-bit NTFS file last access time
+          Ctime      8 bytes    64-bit NTFS file creation time
+
+          The total length for this block is 28 bytes, resulting in a
+          fixed size value of 32 for the TSize field of the NTFS block.
+
+          The NTFS filetimes are 64-bit unsigned integers, stored in Intel
+          (least significant byte first) byte order. They determine the
+          number of 1.0E-07 seconds (1/10th microseconds!) past WinNT "epoch",
+          which is "01-Jan-1601 00:00:00 UTC".
+
+
+         -PKWARE OpenVMS Extra Field (0x000c):
+          ===================================
+
+          The following is the layout of PKWARE's OpenVMS attributes
+          "extra" block.  (Last Revision 12/17/91)
+
+          Note: all fields stored in Intel low-byte/high-byte order.
+
+          Value         Size        Description
+          -----         ----        -----------
+  (VMS)   0x000c        Short       Tag for this "extra" block type
+          TSize         Short       Total Data Size for this block
+          CRC           Long        32-bit CRC for remainder of the block
+          Tag1          Short       OpenVMS attribute tag value #1
+          Size1         Short       Size of attribute #1, in bytes
+          (var.)        Size1       Attribute #1 data
+          .
+          .
+          .
+          TagN          Short       OpenVMS attribute tage value #N
+          SizeN         Short       Size of attribute #N, in bytes
+          (var.)        SizeN       Attribute #N data
+
+          Rules:
+
+          1. There will be one or more of attributes present, which
+             will each be preceded by the above TagX & SizeX values.
+             These values are identical to the ATR$C_XXXX and
+             ATR$S_XXXX constants which are defined in ATR.H under
+             OpenVMS C.  Neither of these values will ever be zero.
+
+          2. No word alignment or padding is performed.
+
+          3. A well-behaved PKZIP/OpenVMS program should never produce
+             more than one sub-block with the same TagX value.  Also,
+             there will never be more than one "extra" block of type
+             0x000c in a particular directory record.
+
+
+         -Info-ZIP VMS Extra Field:
+          ========================
+
+          The following is the layout of Info-ZIP's VMS attributes extra
+          block for VAX or Alpha AXP.  The local-header and central-header
+          versions are identical.  (Last Revision 19960922)
+
+          Value         Size        Description
+          -----         ----        -----------
+  (VMS2)  0x4d49        Short       tag for this extra block type ("JM")
+          TSize         Short       total data size for this block
+          ID            Long        block ID
+          Flags         Short       info bytes
+          BSize         Short       uncompressed block size
+          Reserved      Long        (reserved)
+          (var.)        variable    compressed VMS file-attributes block
+
+          The block ID is one of the following unterminated strings:
+
+                "VFAB"          struct FAB
+                "VALL"          struct XABALL
+                "VFHC"          struct XABFHC
+                "VDAT"          struct XABDAT
+                "VRDT"          struct XABRDT
+                "VPRO"          struct XABPRO
+                "VKEY"          struct XABKEY
+                "VMSV"          version (e.g., "V6.1"; truncated at hyphen)
+                "VNAM"          reserved
+
+          The lower three bits of Flags indicate the compression method.  The
+          currently defined methods are:
+
+                0       stored (not compressed)
+                1       simple "RLE"
+                2       deflated
+
+          The "RLE" method simply replaces zero-valued bytes with zero-valued
+          bits and non-zero-valued bytes with a "1" bit followed by the byte
+          value.
+
+          The variable-length compressed data contains only the data corre-
+          sponding to the indicated structure or string.  Typically multiple
+          VMS2 extra fields are present (each with a unique block type).
+
+
+         -Info-ZIP Macintosh Extra Field:
+          ==============================
+
+          The following is the layout of the (old) Info-ZIP resource-fork extra
+          block for Macintosh.  The local-header and central-header versions
+          are identical.  (Last Revision 19960922)
+
+          Value         Size        Description
+          -----         ----        -----------
+  (Mac)   0x07c8        Short       tag for this extra block type
+          TSize         Short       total data size for this block
+          "JLEE"        beLong      extra-field signature
+          FInfo         16 bytes    Macintosh FInfo structure
+          CrDat         beLong      HParamBlockRec fileParam.ioFlCrDat
+          MdDat         beLong      HParamBlockRec fileParam.ioFlMdDat
+          Flags         beLong      info bits
+          DirID         beLong      HParamBlockRec fileParam.ioDirID
+          VolName       28 bytes    volume name (optional)
+
+          All fields but the first two are in native Macintosh format
+          (big-endian Motorola order, not little-endian Intel).  The least
+          significant bit of Flags is 1 if the file is a data fork, 0 other-
+          wise.  In addition, if this extra field is present, the filename
+          has an extra 'd' or 'r' appended to indicate data fork or resource
+          fork.  The 28-byte VolName field may be omitted.
+
+
+         -ZipIt Macintosh Extra Field (long):
+          ==================================
+
+          The following is the layout of the ZipIt extra block for Macintosh.
+          The local-header and central-header versions are identical.
+          (Last Revision 19970130)
+
+          Value         Size        Description
+          -----         ----        -----------
+  (Mac2)  0x2605        Short       tag for this extra block type
+          TSize         Short       total data size for this block
+          "ZPIT"        beLong      extra-field signature
+          FnLen         Byte        length of FileName
+          FileName      variable    full Macintosh filename
+          FileType      Byte[4]     four-byte Mac file type string
+          Creator       Byte[4]     four-byte Mac creator string
+
+
+         -ZipIt Macintosh Extra Field (short, for files):
+          ==============================================
+
+          The following is the layout of a shortened variant of the
+          ZipIt extra block for Macintosh (without "full name" entry).
+          This variant is used by ZipIt 1.3.5 and newer for entries of
+          files (not directories) that do not have a MacBinary encoded
+          file.  The local-header and central-header versions are identical.
+          (Last Revision 20030602)
+
+          Value         Size        Description
+          -----         ----        -----------
+  (Mac2b) 0x2705        Short       tag for this extra block type
+          TSize         Short       total data size for this block (min. 12)
+          "ZPIT"        beLong      extra-field signature
+          FileType      Byte[4]     four-byte Mac file type string
+          Creator       Byte[4]     four-byte Mac creator string
+          fdFlags       beShort     attributes from FInfo.frFlags,
+                                    may be omitted
+          0x0000        beShort     reserved, may be omitted
+
+
+         -ZipIt Macintosh Extra Field (short, for directories):
+          ====================================================
+
+          The following is the layout of a shortened variant of the
+          ZipIt extra block for Macintosh used only for directory
+          entries. This variant is used by ZipIt 1.3.5 and newer to
+          save some optional Mac-specific information about directories.
+          The local-header and central-header versions are identical.
+
+          Value         Size        Description
+          -----         ----        -----------
+  (Mac2c) 0x2805        Short       tag for this extra block type
+          TSize         Short       total data size for this block (12)
+          "ZPIT"        beLong      extra-field signature
+          frFlags       beShort     attributes from DInfo.frFlags, may
+                                    be omitted
+          View          beShort     ZipIt view flag, may be omitted
+
+
+          The View field specifies ZipIt-internal settings as follows:
+
+          Bits of the Flags:
+              bit 0           if set, the folder is shown expanded (open)
+                              when the archive contents are viewed in ZipIt.
+              bits 1-15       reserved, zero;
+
+
+         -Info-ZIP Macintosh Extra Field (new):
+          ====================================
+
+          The following is the layout of the (new) Info-ZIP extra
+          block for Macintosh, designed by Dirk Haase.
+          All values are in little-endian.
+          (Last Revision 19981005)
+
+          Local-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (Mac3)  0x334d        Short       tag for this extra block type ("M3")
+          TSize         Short       total data size for this block
+          BSize         Long        uncompressed finder attribute data size
+          Flags         Short       info bits
+          fdType        Byte[4]     Type of the File (4-byte string)
+          fdCreator     Byte[4]     Creator of the File (4-byte string)
+          (CType)       Short       compression type
+          (CRC)         Long        CRC value for uncompressed MacOS data
+          Attribs       variable    finder attribute data (see below)
+
+
+          Central-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (Mac3)  0x334d        Short       tag for this extra block type ("M3")
+          TSize         Short       total data size for this block
+          BSize         Long        uncompressed finder attribute data size
+          Flags         Short       info bits
+          fdType        Byte[4]     Type of the File (4-byte string)
+          fdCreator     Byte[4]     Creator of the File (4-byte string)
+
+          The third bit of Flags in both headers indicates whether
+          the LOCAL extra field is uncompressed (and therefore whether CType
+          and CRC are omitted):
+
+          Bits of the Flags:
+              bit 0           if set, file is a data fork; otherwise unset
+              bit 1           if set, filename will be not changed
+              bit 2           if set, Attribs is uncompressed (no CType, CRC)
+              bit 3           if set, date and times are in 64 bit
+                              if zero date and times are in 32 bit.
+              bit 4           if set, timezone offsets fields for the native
+                              Mac times are omitted (UTC support deactivated)
+              bits 5-15       reserved;
+
+
+          Attributes:
+
+          Attribs is a Mac-specific block of data in little-endian format with
+          the following structure (if compressed, uncompress it first):
+
+          Value         Size        Description
+          -----         ----        -----------
+          fdFlags       Short       Finder Flags
+          fdLocation.v  Short       Finder Icon Location
+          fdLocation.h  Short       Finder Icon Location
+          fdFldr        Short       Folder containing file
+
+          FXInfo        16 bytes    Macintosh FXInfo structure
+            FXInfo-Structure:
+                fdIconID        Short
+                fdUnused[3]     Short       unused but reserved 6 bytes
+                fdScript        Byte        Script flag and number
+                fdXFlags        Byte        More flag bits
+                fdComment       Short       Comment ID
+                fdPutAway       Long        Home Dir ID
+
+          FVersNum      Byte        file version number
+                                    may be not used by MacOS
+          ACUser        Byte        directory access rights
+
+          FlCrDat       ULong       date and time of creation
+          FlMdDat       ULong       date and time of last modification
+          FlBkDat       ULong       date and time of last backup
+            These time numbers are original Mac FileTime values (local time!).
+            Currently, date-time width is 32-bit, but future version may
+            support be 64-bit times (see flags)
+
+          CrGMTOffs     Long(signed!)   difference "local Creat. time - UTC"
+          MdGMTOffs     Long(signed!)   difference "local Modif. time - UTC"
+          BkGMTOffs     Long(signed!)   difference "local Backup time - UTC"
+            These "local time - UTC" differences (stored in seconds) may be
+            used to support timestamp adjustment after inter-timezone transfer.
+            These fields are optional; bit 4 of the flags word controls their
+            presence.
+
+          Charset       Short       TextEncodingBase (Charset)
+                                    valid for the following two fields
+
+          FullPath      variable    Path of the current file.
+                                    Zero terminated string (C-String)
+                                    Currently coded in the native Charset.
+
+          Comment       variable    Finder Comment of the current file.
+                                    Zero terminated string (C-String)
+                                    Currently coded in the native Charset.
+
+
+         -SmartZIP Macintosh Extra Field:
+          ====================================
+
+          The following is the layout of the SmartZIP extra
+          block for Macintosh, designed by Marco Bambini.
+
+          Local-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+          0x4d63        Short       tag for this extra block type ("cM")
+          TSize         Short       total data size for this block (64)
+          "dZip"        beLong      extra-field signature
+          fdType        Byte[4]     Type of the File (4-byte string)
+          fdCreator     Byte[4]     Creator of the File (4-byte string)
+          fdFlags       beShort     Finder Flags
+          fdLocation.v  beShort     Finder Icon Location
+          fdLocation.h  beShort     Finder Icon Location
+          fdFldr        beShort     Folder containing file
+          CrDat         beLong      HParamBlockRec fileParam.ioFlCrDat
+          MdDat         beLong      HParamBlockRec fileParam.ioFlMdDat
+          frScroll.v    Byte        vertical pos. of folder's scroll bar
+          fdScript      Byte        Script flag and number
+          frScroll.h    Byte        horizontal pos. of folder's scroll bar
+          fdXFlags      Byte        More flag bits
+          FileName      Byte[32]    full Macintosh filename (pascal string)
+
+          All fields but the first two are in native Macintosh format
+          (big-endian Motorola order, not little-endian Intel).
+          The extra field size is fixed to 64 bytes.
+          The local-header and central-header versions are identical.
+
+
+         -Acorn SparkFS Extra Field:
+          =========================
+
+          The following is the layout of David Pilling's SparkFS extra block
+          for Acorn RISC OS.  The local-header and central-header versions are
+          identical.  (Last Revision 19960922)
+
+          Value         Size        Description
+          -----         ----        -----------
+  (Acorn) 0x4341        Short       tag for this extra block type ("AC")
+          TSize         Short       total data size for this block (20)
+          "ARC0"        Long        extra-field signature
+          LoadAddr      Long        load address or file type
+          ExecAddr      Long        exec address
+          Attr          Long        file permissions
+          Zero          Long        reserved; always zero
+
+          The following bits of Attr are associated with the given file
+          permissions:
+
+                bit 0           user-writable ('W')
+                bit 1           user-readable ('R')
+                bit 2           reserved
+                bit 3           locked ('L')
+                bit 4           publicly writable ('w')
+                bit 5           publicly readable ('r')
+                bit 6           reserved
+                bit 7           reserved
+
+
+         -VM/CMS Extra Field:
+          ==================
+
+          The following is the layout of the file-attributes extra block for
+          VM/CMS.  The local-header and central-header versions are
+          identical.  (Last Revision 19960922)
+
+          Value         Size        Description
+          -----         ----        -----------
+ (VM/CMS) 0x4704        Short       tag for this extra block type
+          TSize         Short       total data size for this block
+          flData        variable    file attributes data
+
+          flData is an uncompressed fldata_t struct.
+
+
+         -MVS Extra Field:
+          ===============
+
+          The following is the layout of the file-attributes extra block for
+          MVS.  The local-header and central-header versions are identical.
+          (Last Revision 19960922)
+
+          Value         Size        Description
+          -----         ----        -----------
+  (MVS)   0x470f        Short       tag for this extra block type
+          TSize         Short       total data size for this block
+          flData        variable    file attributes data
+
+          flData is an uncompressed fldata_t struct.
+
+
+         -PKWARE Unix Extra Field (0x000d):
+          ================================
+
+          The following is the layout of PKWARE's Unix "extra" block.
+          It was introduced with the release of PKZIP for Unix 2.50.
+          Note: all fields are stored in Intel low-byte/high-byte order.
+          (Last Revision 19980901)
+
+          This field has a minimum data size of 12 bytes and is only stored
+          as local extra field.
+
+          Value         Size        Description
+          -----         ----        -----------
+ (Unix0)  0x000d        Short       Tag for this "extra" block type
+          TSize         Short       Total Data Size for this block
+          AcTime        Long        time of last access (UTC/GMT)
+          ModTime       Long        time of last modification (UTC/GMT)
+          UID           Short       Unix user ID
+          GID           Short       Unix group ID
+          (var)         variable    Variable length data field
+
+          The variable length data field will contain file type
+          specific data.  Currently the only values allowed are
+          the original "linked to" file names for hard or symbolic
+          links, and the major and minor device node numbers for
+          character and block device nodes.  Since device nodes
+          cannot be either symbolic or hard links, only one set of
+          variable length data is stored.  Link files will have the
+          name of the original file stored.  This name is NOT NULL
+          terminated.  Its size can be determined by checking TSize -
+          12.  Device entries will have eight bytes stored as two 4
+          byte entries (in little-endian format).  The first entry
+          will be the major device number, and the second the minor
+          device number.
+
+         [Info-ZIP note: The fixed part of this field has the same layout as
+          Info-ZIP's abandoned "Unix1 timestamps & owner ID info" extra field;
+          only the two tag bytes are different.]
+
+
+         -PATCH Descriptor Extra Field (0x000f):
+          =====================================
+
+          The following is the layout of the Patch Descriptor "extra"
+          block.
+
+          Note: all fields stored in Intel low-byte/high-byte order.
+
+          Value         Size        Description
+          -----         ----        -----------
+  (Patch) 0x000f        Short       Tag for this "extra" block type
+          TSize         Short       Size of the total "extra" block
+          Version       Short       Version of the descriptor
+          Flags         Long        Actions and reactions (see below)
+          OldSize       Long        Size of the file about to be patched
+          OldCRC        Long        32-bit CRC of the file about to be patched
+          NewSize       Long        Size of the resulting file
+          NewCRC        Long        32-bit CRC of the resulting file
+
+
+          Actions and reactions
+
+          Bits          Description
+          ----          ----------------
+          0             Use for auto detection
+          1             Treat as a self-patch
+          2-3           RESERVED
+          4-5           Action (see below)
+          6-7           RESERVED
+          8-9           Reaction (see below) to absent file
+          10-11         Reaction (see below) to newer file
+          12-13         Reaction (see below) to unknown file
+          14-15         RESERVED
+          16-31         RESERVED
+
+          Actions
+
+          Action       Value
+          ------       -----
+          none         0
+          add          1
+          delete       2
+          patch        3
+
+          Reactions
+
+          Reaction     Value
+          --------     -----
+          ask          0
+          skip         1
+          ignore       2
+          fail         3
+
+          Patch support is provided by PKPatchMaker(tm) technology and is
+          covered under U.S. Patents and Patents Pending.
+
+
+         -PKCS#7 Store for X.509 Certificates (0x0014):
+          ============================================
+
+          This field contains information about each of the certificates
+          files may be signed with.  When the Central Directory Encryption
+          feature is enabled for a ZIP file, this record will appear in
+          the Archive Extra Data Record, otherwise it will appear in the
+          first central directory record and will be ignored in any
+          other record.
+
+          Note: all fields stored in Intel low-byte/high-byte order.
+
+          Value     Size     Description
+          -----     ----     -----------
+  (Store) 0x0014    2 bytes  Tag for this "extra" block type
+          TSize     2 bytes  Size of the store data
+          SData     TSize    Data about the store
+
+          SData
+          Value     Size        Description
+          -----     ----        -----------
+          Version   2 bytes     Version number, 0x0001 for now
+          StoreD    (variable)  Actual store data
+
+          The StoreD member is suitable for passing as the pbData
+          member of a CRYPT_DATA_BLOB to the CertOpenStore() function
+          in Microsoft's CryptoAPI.  The SSize member above will be
+          cbData + 6, where cbData is the cbData member of the same
+          CRYPT_DATA_BLOB.  The encoding type to pass to
+          CertOpenStore() should be
+          PKCS_7_ANS_ENCODING | X509_ASN_ENCODING.
+
+
+         -X.509 Certificate ID and Signature for individual file (0x0015):
+          ===============================================================
+
+          This field contains the information about which certificate in
+          the PKCS#7 store was used to sign a particular file.  It also
+          contains the signature data.  This field can appear multiple
+          times, but can only appear once per certificate.
+
+          Note: all fields stored in Intel low-byte/high-byte order.
+
+          Value         Size        Description
+          -----         ----        -----------
+  (CID)   0x0015        2 bytes     Tag for this "extra" block type
+          CSize         2 bytes     Size of Method
+          Method        (variable)
+
+          Method
+          Value         Size        Description
+          -----         ----        -----------
+          Version       2 bytes     Version number, for now 0x0001
+          AlgID         2 bytes     Algorithm ID used for signing
+          IDSize        2 bytes     Size of Certificate ID data
+          CertID        (variable)  Certificate ID data
+          SigSize       2 bytes     Size of Signature data
+          Sig           (variable)  Signature data
+
+          CertID
+          Value         Size        Description
+          -----         ----        -----------
+          Size1         4 bytes     Size of CertID, should be (IDSize - 4)
+          Size1         4 bytes     A bug in version one causes this value
+                                    to appear twice.
+          IssSize       4 bytes     Issuer data size
+          Issuer        (variable)  Issuer data
+          SerSize       4 bytes     Serial Number size
+          Serial        (variable)  Serial Number data
+
+          The Issuer and IssSize members are suitable for creating a
+          CRYPT_DATA_BLOB to be the Issuer member of a CERT_INFO
+          struct. The Serial and SerSize members would be the
+          SerialNumber member of the same CERT_INFO struct.  This
+          struct would be used to find the certificate in the store
+          the file was signed with.  Those structures are from the MS
+          CryptoAPI.
+
+          Sig and SigSize are the actual signature data and size
+          generated by signing the file with the MS CryptoAPI using a
+          hash created with the given AlgID.
+
+
+         -X.509 Certificate ID and Signature for central directory (0x0016):
+          =================================================================
+
+          This field contains the information about which certificate in
+          the PKCS#7 store was used to sign the central directory structure.
+          When the Central Directory Encryption feature is enabled for a
+          ZIP file, this record will appear in the Archive Extra Data Record,
+          otherwise it will appear in the first central directory record,
+          along with the store.  The data structure is the
+          same as the CID, except that SigSize will be 0, and there
+          will be no Sig member.
+
+          This field is also kept after the last central directory
+          record, as the signature data (ID 0x05054b50, it looks like
+          a central directory record of a different type).  This
+          second copy of the data is the Signature Data member of the
+          record, and will have a SigSize that is non-zero, and will
+          have Sig data.
+
+          Note: all fields stored in Intel low-byte/high-byte order.
+
+          Value     Size     Description
+          -----     ----     -----------
+  (CDID)  0x0016    2 bytes  Tag for this "extra" block type
+          TSize     2 bytes  Size of data that follows
+          TData     TSize    Data
+
+
+         -Strong Encryption Header (0x0017) (EFS):
+          ===============================
+
+          Value     Size     Description
+          -----     ----     -----------
+          0x0017    2 bytes  Tag for this "extra" block type
+          TSize     2 bytes  Size of data that follows
+          Format    2 bytes  Format definition for this record
+          AlgID     2 bytes  Encryption algorithm identifier
+          Bitlen    2 bytes  Bit length of encryption key
+          Flags     2 bytes  Processing flags
+          CertData  TSize-8  Certificate decryption extra field data
+                             (refer to the explanation for CertData
+                              in the section describing the
+                              Certificate Processing Method under
+                              the Strong Encryption Specification)
+
+
+         -Record Management Controls (0x0018):
+          ===================================
+
+          Value     Size     Description
+          -----     ----     -----------
+(Rec-CTL) 0x0018    2 bytes  Tag for this "extra" block type
+          CSize     2 bytes  Size of total extra block data
+          Tag1      2 bytes  Record control attribute 1
+          Size1     2 bytes  Size of attribute 1, in bytes
+          Data1     Size1    Attribute 1 data
+            .
+            .
+            .
+          TagN      2 bytes  Record control attribute N
+          SizeN     2 bytes  Size of attribute N, in bytes
+          DataN     SizeN    Attribute N data
+
+
+         -PKCS#7 Encryption Recipient Certificate List (0x0019): (EFS)
+          =====================================================
+
+          This field contains the information about each of the certificates
+          that files may be encrypted with. This field should only appear
+          in the archive extra data record. This field is not required and
+          serves only to aide archive modifications by preserving public
+          encryption data. Individual security requirements may dictate
+          that this data be omitted to deter information exposure.
+
+          Note: all fields stored in Intel low-byte/high-byte order.
+
+          Value     Size     Description
+          -----     ----     -----------
+ (CStore) 0x0019    2 bytes  Tag for this "extra" block type
+          TSize     2 bytes  Size of the store data
+          TData     TSize    Data about the store
+
+          TData:
+
+          Value     Size     Description
+          -----     ----     -----------
+          Version   2 bytes  Format version number - must 0x0001 at this time
+          CStore    (var)    PKCS#7 data blob
+
+
+         -MVS Extra Field (PKWARE, 0x0065):
+          ================================
+
+          The following is the layout of the MVS "extra" block.
+          Note: Some fields are stored in Big Endian format.
+          All text is in EBCDIC format unless otherwise specified.
+
+          Value       Size          Description
+          -----       ----          -----------
+  (MVS)   0x0065      2 bytes       Tag for this "extra" block type
+          TSize       2 bytes       Size for the following data block
+          ID          4 bytes       EBCDIC "Z390" 0xE9F3F9F0 or
+                                    "T4MV" for TargetFour
+          (var)       TSize-4       Attribute data
+
+
+         -OS/400 Extra Field (0x0065):
+          ===========================
+
+          The following is the layout of the OS/400 "extra" block.
+          Note: Some fields are stored in Big Endian format.
+          All text is in EBCDIC format unless otherwise specified.
+
+          Value       Size          Description
+          -----       ----          -----------
+  (OS400) 0x0065      2 bytes       Tag for this "extra" block type
+          TSize       2 bytes       Size for the following data block
+          ID          4 bytes       EBCDIC "I400" 0xC9F4F0F0 or
+                                    "T4MV" for TargetFour
+          (var)       TSize-4       Attribute data
+
+
+         -Extended Timestamp Extra Field:
+          ==============================
+
+          The following is the layout of the extended-timestamp extra block.
+          (Last Revision 19970118)
+
+          Local-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (time)  0x5455        Short       tag for this extra block type ("UT")
+          TSize         Short       total data size for this block
+          Flags         Byte        info bits
+          (ModTime)     Long        time of last modification (UTC/GMT)
+          (AcTime)      Long        time of last access (UTC/GMT)
+          (CrTime)      Long        time of original creation (UTC/GMT)
+
+          Central-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (time)  0x5455        Short       tag for this extra block type ("UT")
+          TSize         Short       total data size for this block
+          Flags         Byte        info bits (refers to local header!)
+          (ModTime)     Long        time of last modification (UTC/GMT)
+
+          The central-header extra field contains the modification time only,
+          or no timestamp at all.  TSize is used to flag its presence or
+          absence.  But note:
+
+              If "Flags" indicates that Modtime is present in the local header
+              field, it MUST be present in the central header field, too!
+              This correspondence is required because the modification time
+              value may be used to support trans-timezone freshening and
+              updating operations with zip archives.
+
+          The time values are in standard Unix signed-long format, indicating
+          the number of seconds since 1 January 1970 00:00:00.  The times
+          are relative to Coordinated Universal Time (UTC), also sometimes
+          referred to as Greenwich Mean Time (GMT).  To convert to local time,
+          the software must know the local timezone offset from UTC/GMT.
+
+          The lower three bits of Flags in both headers indicate which time-
+          stamps are present in the LOCAL extra field:
+
+                bit 0           if set, modification time is present
+                bit 1           if set, access time is present
+                bit 2           if set, creation time is present
+                bits 3-7        reserved for additional timestamps; not set
+
+          Those times that are present will appear in the order indicated, but
+          any combination of times may be omitted.  (Creation time may be
+          present without access time, for example.)  TSize should equal
+          (1 + 4*(number of set bits in Flags)), as the block is currently
+          defined.  Other timestamps may be added in the future.
+
+
+         -Info-ZIP Unix Extra Field (type 1):
+          ==================================
+
+          The following is the layout of the old Info-ZIP extra block for
+          Unix.  It has been replaced by the extended-timestamp extra block
+          (0x5455) and the Unix type 2 extra block (0x7855).
+          (Last Revision 19970118)
+
+          Local-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (Unix1) 0x5855        Short       tag for this extra block type ("UX")
+          TSize         Short       total data size for this block
+          AcTime        Long        time of last access (UTC/GMT)
+          ModTime       Long        time of last modification (UTC/GMT)
+          UID           Short       Unix user ID (optional)
+          GID           Short       Unix group ID (optional)
+
+          Central-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (Unix1) 0x5855        Short       tag for this extra block type ("UX")
+          TSize         Short       total data size for this block
+          AcTime        Long        time of last access (GMT/UTC)
+          ModTime       Long        time of last modification (GMT/UTC)
+
+          The file access and modification times are in standard Unix signed-
+          long format, indicating the number of seconds since 1 January 1970
+          00:00:00.  The times are relative to Coordinated Universal Time
+          (UTC), also sometimes referred to as Greenwich Mean Time (GMT).  To
+          convert to local time, the software must know the local timezone
+          offset from UTC/GMT.  The modification time may be used by non-Unix
+          systems to support inter-timezone freshening and updating of zip
+          archives.
+
+          The local-header extra block may optionally contain UID and GID
+          info for the file.  The local-header TSize value is the only
+          indication of this.  Note that Unix UIDs and GIDs are usually
+          specific to a particular machine, and they generally require root
+          access to restore.
+
+          This extra field type is obsolete, but it has been in use since
+          mid-1994.  Therefore future archiving software should continue to
+          support it.  Some guidelines:
+
+              An archive member should either contain the old "Unix1"
+              extra field block or the new extra field types "time" and/or
+              "Unix2".
+
+              If both the old "Unix1" block type and one or both of the new
+              block types "time" and "Unix2" are found, the "Unix1" block
+              should be considered invalid and ignored.
+
+              Unarchiving software should recognize both old and new extra
+              field block types, but the info from new types overrides the
+              old "Unix1" field.
+
+              Archiving software should recognize "Unix1" extra fields for
+              timestamp comparison but never create it for updated, freshened
+              or new archive members.  When copying existing members to a new
+              archive, any "Unix1" extra field blocks should be converted to
+              the new "time" and/or "Unix2" types.
+
+
+         -Info-ZIP Unix Extra Field (type 2):
+          ==================================
+
+          The following is the layout of the new Info-ZIP extra block for
+          Unix.  (Last Revision 19960922)
+
+          Local-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (Unix2) 0x7855        Short       tag for this extra block type ("Ux")
+          TSize         Short       total data size for this block (4)
+          UID           Short       Unix user ID
+          GID           Short       Unix group ID
+
+          Central-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (Unix2) 0x7855        Short       tag for this extra block type ("Ux")
+          TSize         Short       total data size for this block (0)
+
+          The data size of the central-header version is zero; it is used
+          solely as a flag that UID/GID info is present in the local-header
+          extra field.  If additional fields are ever added to the local
+          version, the central version may be extended to indicate this.
+
+          Note that Unix UIDs and GIDs are usually specific to a particular
+          machine, and they generally require root access to restore.
+
+
+         -ASi Unix Extra Field:
+          ====================
+
+          The following is the layout of the ASi extra block for Unix.  The
+          local-header and central-header versions are identical.
+          (Last Revision 19960916)
+
+          Value         Size        Description
+          -----         ----        -----------
+  (Unix3) 0x756e        Short       tag for this extra block type ("nu")
+          TSize         Short       total data size for this block
+          CRC           Long        CRC-32 of the remaining data
+          Mode          Short       file permissions
+          SizDev        Long        symlink'd size OR major/minor dev num
+          UID           Short       user ID
+          GID           Short       group ID
+          (var.)        variable    symbolic link filename
+
+          Mode is the standard Unix st_mode field from struct stat, containing
+          user/group/other permissions, setuid/setgid and symlink info, etc.
+
+          If Mode indicates that this file is a symbolic link, SizDev is the
+          size of the file to which the link points.  Otherwise, if the file
+          is a device, SizDev contains the standard Unix st_rdev field from
+          struct stat (includes the major and minor numbers of the device).
+          SizDev is undefined in other cases.
+
+          If Mode indicates that the file is a symbolic link, the final field
+          will be the name of the file to which the link points.  The file-
+          name length can be inferred from TSize.
+
+          [Note that TSize may incorrectly refer to the data size not counting
+           the CRC; i.e., it may be four bytes too small.]
+
+
+         -BeOS Extra Field:
+          ================
+
+          The following is the layout of the file-attributes extra block for
+          BeOS.  (Last Revision 19970531)
+
+          Local-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (BeOS)  0x6542        Short       tag for this extra block type ("Be")
+          TSize         Short       total data size for this block
+          BSize         Long        uncompressed file attribute data size
+          Flags         Byte        info bits
+          (CType)       Short       compression type
+          (CRC)         Long        CRC value for uncompressed file attribs
+          Attribs       variable    file attribute data
+
+          Central-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (BeOS)  0x6542        Short       tag for this extra block type ("Be")
+          TSize         Short       total data size for this block (5)
+          BSize         Long        size of uncompr. local EF block data
+          Flags         Byte        info bits
+
+          The least significant bit of Flags in both headers indicates whether
+          the LOCAL extra field is uncompressed (and therefore whether CType
+          and CRC are omitted):
+
+                bit 0           if set, Attribs is uncompressed (no CType, CRC)
+                bits 1-7        reserved; if set, assume error or unknown data
+
+          Currently the only supported compression types are deflated (type 8)
+          and stored (type 0); the latter is not used by Info-ZIP's Zip but is
+          supported by UnZip.
+
+          Attribs is a BeOS-specific block of data in big-endian format with
+          the following structure (if compressed, uncompress it first):
+
+              Value     Size        Description
+              -----     ----        -----------
+              Name      variable    attribute name (null-terminated string)
+              Type      Long        attribute type (32-bit unsigned integer)
+              Size      Long Long   data size for this sub-block (64 bits)
+              Data      variable    attribute data
+
+          The attribute structure is repeated for every attribute.  The Data
+          field may contain anything--text, flags, bitmaps, etc.
+
+
+         -AtheOS Extra Field:
+          ==================
+
+          The following is the layout of the file-attributes extra block for
+          AtheOS.  This field is a very close spin-off from the BeOS e.f.
+          The only differences are:
+           - a new extra field signature
+           - numeric field in the attributes data are stored in little-endian
+             format ("i386" was initial hardware for AtheOS)
+          (Last Revision 20040908)
+
+          Local-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+ (AtheOS) 0x7441        Short       tag for this extra block type ("At")
+          TSize         Short       total data size for this block
+          BSize         Long        uncompressed file attribute data size
+          Flags         Byte        info bits
+          (CType)       Short       compression type
+          (CRC)         Long        CRC value for uncompressed file attribs
+          Attribs       variable    file attribute data
+
+          Central-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+ (AtheOS) 0x7441        Short       tag for this extra block type ("At")
+          TSize         Short       total data size for this block (5)
+          BSize         Long        size of uncompr. local EF block data
+          Flags         Byte        info bits
+
+          The least significant bit of Flags in both headers indicates whether
+          the LOCAL extra field is uncompressed (and therefore whether CType
+          and CRC are omitted):
+
+                bit 0           if set, Attribs is uncompressed (no CType, CRC)
+                bits 1-7        reserved; if set, assume error or unknown data
+
+          Currently the only supported compression types are deflated (type 8)
+          and stored (type 0); the latter is not used by Info-ZIP's Zip but is
+          supported by UnZip.
+
+          Attribs is a AtheOS-specific block of data in little-endian format
+          with the following structure (if compressed, uncompress it first):
+
+              Value     Size        Description
+              -----     ----        -----------
+              Name      variable    attribute name (null-terminated string)
+              Type      Long        attribute type (32-bit unsigned integer)
+              Size      Long Long   data size for this sub-block (64 bits)
+              Data      variable    attribute data
+
+          The attribute structure is repeated for every attribute.  The Data
+          field may contain anything--text, flags, bitmaps, etc.
+
+
+         -SMS/QDOS Extra Field:
+          ====================
+
+          The following is the layout of the file-attributes extra block for
+          SMS/QDOS.  The local-header and central-header versions are identical.
+          (Last Revision 19960929)
+
+          Value         Size        Description
+          -----         ----        -----------
+  (QDOS)  0xfb4a        Short       tag for this extra block type
+          TSize         Short       total data size for this block
+          LongID        Long        extra-field signature
+          (ExtraID)     Long        additional signature/flag bytes
+          QDirect       64 bytes    qdirect structure
+
+          LongID may be "QZHD" or "QDOS".  In the latter case, ExtraID will
+          be present.  Its first three bytes are "02\0"; the last byte is
+          currently undefined.
+
+          QDirect contains the file's uncompressed directory info (qdirect
+          struct).  Its elements are in native (big-endian) format:
+
+          d_length      beLong          file length
+          d_access      byte            file access type
+          d_type        byte            file type
+          d_datalen     beLong          data length
+          d_reserved    beLong          unused
+          d_szname      beShort         size of filename
+          d_name        36 bytes        filename
+          d_update      beLong          time of last update
+          d_refdate     beLong          file version number
+          d_backup      beLong          time of last backup (archive date)
+
+
+         -AOS/VS Extra Field:
+          ==================
+
+          The following is the layout of the extra block for Data General
+          AOS/VS.  The local-header and central-header versions are identical.
+          (Last Revision 19961125)
+
+          Value         Size        Description
+          -----         ----        -----------
+  (AOSVS) 0x5356        Short       tag for this extra block type ("VS")
+          TSize         Short       total data size for this block
+          "FCI\0"       Long        extra-field signature
+          Version       Byte        version of AOS/VS extra block (10 = 1.0)
+          Fstat         variable    fstat packet
+          AclBuf        variable    raw ACL data ($MXACL bytes)
+
+          Fstat contains the file's uncompressed fstat packet, which is one of
+          the following:
+
+                normal fstat packet             (P_FSTAT struct)
+                DIR/CPD fstat packet            (P_FSTAT_DIR struct)
+                unit (device) fstat packet      (P_FSTAT_UNIT struct)
+                IPC file fstat packet           (P_FSTAT_IPC struct)
+
+          AclBuf contains the raw ACL data; its length is $MXACL.
+
+
+         -Tandem NSK Extra Field:
+          ======================
+
+          The following is the layout of the file-attributes extra block for
+          Tandem NSK.  The local-header and central-header versions are
+          identical.  (Last Revision 19981221)
+
+          Value         Size        Description
+          -----         ----        -----------
+  (TA)    0x4154        Short       tag for this extra block type ("TA")
+          TSize         Short       total data size for this block (20)
+          NSKattrs      20 Bytes    NSK attributes
+
+
+         -THEOS Extra Field:
+          =================
+
+          The following is the layout of the file-attributes extra block for
+          Theos.  The local-header and central-header versions are identical.
+          (Last Revision 19990206)
+
+          Value         Size        Description
+          -----         ----        -----------
+  (Theos) 0x6854        Short       'Th' signature
+          size          Short       size of extra block
+          flags         Byte        reserved for future use
+          filesize      Long        file size
+          fileorg       Byte        type of file (see below)
+          keylen        Short       key length for indexed and keyed files,
+                                    data segment size for 16 bits programs
+          reclen        Short       record length for indexed,keyed and direct,
+                                    text segment size for 16 bits programs
+          filegrow      Byte        growing factor for indexed,keyed and direct
+          protect       Byte        protections (see below)
+          reserved      Short       reserved for future use
+
+            File types
+            ==========
+
+            0x80  library (keyed access list of files)
+            0x40  directory
+            0x10  stream file
+            0x08  direct file
+            0x04  keyed file
+            0x02  indexed file
+            0x0e  reserved
+            0x01  16 bits real mode program (obsolete)
+            0x21  16 bits protected mode program
+            0x41  32 bits protected mode program
+
+            Protection codes
+            ================
+
+            User protection
+            ---------------
+            0x01  non readable
+            0x02  non writable
+            0x04  non executable
+            0x08  non erasable
+
+            Other protection
+            ----------------
+            0x10  non readable
+            0x20  non writable
+            0x40  non executable Theos before 4.0
+            0x40  modified Theos 4.x
+            0x80  not hidden
+
+
+         -THEOS old inofficial Extra Field:
+          ================================
+
+          The following is the layout of an inoffical former version of a
+          Theos file-attributes extra blocks.  This layout was never published
+          and is no longer created. However, UnZip can optionally support it
+          when compiling with the option flag OLD_THEOS_EXTRA defined.
+          Both the local-header and central-header versions are identical.
+          (Last Revision 19990206)
+
+          Value         Size        Description
+          -----         ----        -----------
+  (THS0)  0x4854        Short       'TH' signature
+          size          Short       size of extra block
+          flags         Short       reserved for future use
+          filesize      Long        file size
+          reclen        Short       record length for indexed,keyed and direct,
+                                    text segment size for 16 bits programs
+          keylen        Short       key length for indexed and keyed files,
+                                    data segment size for 16 bits programs
+          filegrow      Byte        growing factor for indexed,keyed and direct
+          reserved      3 Bytes     reserved for future use
+
+
+         -FWKCS MD5 Extra Field (0x4b46):
+          ==============================
+
+          The FWKCS Contents_Signature System, used in automatically
+          identifying files independent of filename, optionally adds
+          and uses an extra field to support the rapid creation of
+          an enhanced contents_signature.
+          There is no local-header version; the following applies
+          only to the central header.  (Last Revision 19961207)
+
+          Central-header version:
+
+          Value         Size        Description
+          -----         ----        -----------
+  (MD5)   0x4b46        Short       tag for this extra block type ("FK")
+          TSize         Short       total data size for this block (19)
+          "MD5"         3 bytes     extra-field signature
+          MD5hash       16 bytes    128-bit MD5 hash of uncompressed data
+                                    (low byte first)
+
+          When FWKCS revises a .ZIP file central directory to add
+          this extra field for a file, it also replaces the
+          central directory entry for that file's uncompressed
+          file length with a measured value.
+
+          FWKCS provides an option to strip this extra field, if
+          present, from a .ZIP file central directory. In adding
+          this extra field, FWKCS preserves .ZIP file Authenticity
+          Verification; if stripping this extra field, FWKCS
+          preserves all versions of AV through PKZIP version 2.04g.
+
+          FWKCS, and FWKCS Contents_Signature System, are
+          trademarks of Frederick W. Kantor.
+
+          (1) R. Rivest, RFC1321.TXT, MIT Laboratory for Computer
+              Science and RSA Data Security, Inc., April 1992.
+              ll.76-77: "The MD5 algorithm is being placed in the
+              public domain for review and possible adoption as a
+              standard."
diff --git a/proginfo/fileinfo.cms b/proginfo/fileinfo.cms
new file mode 100644 (file)
index 0000000..9d21935
--- /dev/null
@@ -0,0 +1,231 @@
+[Quoting from a C/370 manual, courtesy of Carl Forde.]
+
+  C/370 supports three types of input and output: text streams, binary
+  streams, and record I/O.  Text and binary streams are both ANSI
+  standards; record I/O is a C/370 extension.
+
+[...]
+
+  Record I/O is a C/370 extension to the ANSI standard.  For files
+  opened in record format, C/370 reads and writes one record at a
+  time.  If you try to write more data to a record than the record
+  can hold, the data is truncated.  For record I/O, C/370 only allows
+  the use of fread() and fwrite() to read and write to the files.  Any
+  other functions (such as fprintf(), fscanf(), getc(), and putc())
+  fail.  For record-orientated files, records do not change size when
+  you update them.  If the new data has fewer characters than the
+  original record, the new data fills the first n characters, where
+  n is the number of characters of the new data.  The record will
+  remain the same size, and the old characters (those after) n are
+  left unchanged.  A subsequent update begins at the next boundary.
+  For example, if you have the string "abcdefgh":
+
+  abcdefgh
+
+  and you overwrite it with the string "1234", the record will look
+  like this:
+
+  1234efgh
+
+  C/370 record I/O is binary.  That is, it does not interpret any of
+  the data in a record file and therefore does not recognize control
+  characters.
+
+
+  The record model consists of:
+
+  * A record, which is the unit of data transmitted to and from a
+    program
+  * A block, which is the unit of data transmitted to and from a
+    device.  Each block may contain one or more records.
+
+  In the record model of I/O, records and blocks have the following
+  attributes:
+
+  RECFM   Specifies the format of the data or how the data is organized
+          on the physical device.
+  LRECL   Specifies the length of logical records (as opposed to
+          physical ones).
+
+  BLKSIZE Specifies the length of physical records (blocks on the
+          physical device).
+
+
+  Opening a File by Filename
+
+  The filename that you specify on the call to fopen() or freopen()
+  must be in the following format:
+
+  >> ----filename---- ----filetype--------------------
+                   |   |             |             |
+                   --.--             -- --filemode--
+                                     |   |
+                                     --.--
+  where
+
+  filename is a 1- to 8-character string of any of the characters,
+  A-Z, a-z, 0-9, and +, -, $, #, @, :, and _.  You can separate it
+  from the filetype with one or more spaces, or with a period.
+  [Further note:  filenames are fully case-sensitive, as in Unix.]
+
+  filetype is a 1- to 8-character string of any of the characters,
+  A-Z, a-z, 0-9, and +, -, $, #, @, :, and _.  You can separate it
+  from the filemode with one or more spaces, or with a period. The
+  separator between filetype and filemode must be the same as the
+  one between filename and filetype.
+
+  filemode is a 1- to 2-character string.  The first must be any of
+  the characters A-Z, a-z, or *.  If you use the asis parameter on
+  the fopen() or freopen() call, the first character of the filemode
+  must be a capital letter or an asterisk.  Otherwise, the function
+  call fails.  The second character of filemode is optional; if you
+  specify it, it must be any of the digits 0-6.  You cannot specify
+  the second character if you have specified * for the first one.
+
+  If you do not use periods as separators, there is no limit to how
+  much whitespace you can have before and after the filename, the
+  filetype, and filemode.
+
+
+  Opening a File without a File Mode Specified
+
+  If you omit the file mode or specify * for it, C/370 does one
+  of the following when you call fopen() or freopen():
+
+  * If you have specified a read mode, C/370 looks for the named file
+    on all the accessed readable disks, in order.  If it does not find
+    the file, the fopen() or freopen() call fails.
+  * If you have specified any of the write modes, C/370 writes the file
+    on the first writable disk you have accessed.  Specifying a write
+    mode on an fopen() or freopen() call that contains the filename of
+    an existing file destroys that file.  If you do not have any
+    writable disks accessed, the call fails.
+
+
+  fopen() and freopen() parameters
+
+  recfm
+     CMS supports only two RECFMs, V and F.  [note that MVS supports
+     27(!) different RECFMs.]  If you do not specify the RECFM for a
+     file, C/370 determines whether is is in fixed or variable format.
+
+  lrecl and blksize
+     For files in fixed format, CMS allows records to be read and
+     written in blocks.  To have a fixed format CMS file treated as a
+     fixed blocked CMS file, you can open the file with recfm=fb and
+     specify the lrecl and blksize.  If you do not specify a recfm on
+     the open, the blksize can be a multiple of the lrecl, and the
+     file is treated as if it were blocked.
+
+     For files in variable format, the CMS LRECL is different from the
+     LRECL for the record model.  In the record model, the LRECL is
+     equal to the data length plus 4 bytes (for the record descriptor
+     word), and the BLKSIZE  is equal to the LRECL plus 4 bytes (for
+     the block descriptor word).  In CMS, BDWs and RDWs do not exist,
+     but because CMS follows the record model, you must still account
+     for them.  When you specify V, you must still allocate the record
+     descriptor word and block descriptor word.  That is, if you want
+     a maximum of n bytes per record, you must specify a minimum LRECL
+     of n+4 and a minimum BLKSIZE of n+8.
+
+     When you are appending to V files, you can enlarge the record size
+     dynamically, but only if you have not specified LRECL or BLKSIZE
+     on the fopen() or freopen() command that opened the file.
+
+  type
+     If you specify this parameter, the only valid value for CMS disk
+     files is type =record. This opens a file for record I/O.
+
+  asis
+     If you use this parameter, you can open files with mixed-case
+     filenames such as JaMeS dAtA or pErCy.FILE.  If you specify this
+     parameter, the file mode that you specify must be a capital letter
+     (if it is not an asterisk); otherwise; the function call fails and
+     the value returned is NULL.
+
+
+  Reading from Record I/O Files
+     fread() is the only interface allowed for reading record I/O files.
+     Each time you call fread() for a record I/O file, fread() reads
+     one record from the system.  If you call fread() with a request for
+     less than a complete record, the requested bytes are copied to your
+     buffer, and the file position is set to the start fo the next
+     record.  If the request is for more bytes that are in the record,
+     one record is read and the position is set to the start of the next
+     record.  C/370 does not strip any blank characters or interpret any
+     data.
+
+     fread() returns the number of items read successfully, so if you
+     pass a size argument equal to 1 and a count argument equal to the
+     maximum expected length of the record, fread() returns the length,
+     in bytes, of the record read.  If you pass a size argument equal
+     to the maximum expected length of the record, and a count argument
+     equal to 1, fread() returns either 0 or 1, indicating whether a
+     record of length size read.  If a record is read successfully but
+     is less than size bytes long, fread() returns 0.
+
+
+  Writing to Record I/O Files
+     fwrite() is the only interface allowed for writing to a file
+     opened for record I/O.  Only one record is written at a time.  If
+     you attempt to write more new data than a full record can hold or
+     try to update a record with more data than it currently has, C/370
+     truncates your output at the record boundary.  When C/370 performs
+     a truncation, it sets errno and raises SIGIOERR, if SIGIOERR is not
+     set to SIG_IGN.
+
+     When you are writing new records to a fixed-record I/O file, if you
+     try to write a short record, C/370 pads the record with nulls out
+     to LRECL.
+
+     At the completion of an fwrite(), the file position is at the start
+     of the next record.  For new data, the block is flushed out to the
+     system as soon as it is full.
+
+
+  fldata() Behavior
+     When you call the fldata() function for an open CMS minidisk file,
+     it returns a data structure that looks like this:
+
+     struct __filedata {
+          unsigned int   __recfmF      : 1, /* fixed length records */
+                         __recfmV      : 1, /* variable length records */
+                         __recfmU      : 1, /* n/a */
+                         __recfmS      : 1, /* n/a */
+                         __recfmBlk    : 1, /* n/a */
+                         __recfmASA    : 1, /* text mode and ASA */
+                         __recfmM      : 1, /* n/a */
+                         __dsorgPO     : 1, /* n/a */
+                         __dsorgPDSmem : 1, /* n/a */
+                         __dsorgPDSdir : 1, /* n/a */
+                         __dsorgPS     : 1, /* sequential data set */
+                         __dsorgConcat : 1, /* n/a */
+                         __dsorgMem    : 1, /* n/a */
+                         __dsorgHiper  : 1, /* n/a */
+                         __dsorgTemp   : 1, /* created with tmpfile() */
+                         __dsorgVSAM   : 1, /* n/a */
+                         __reserve1    : 1, /* n/a */
+                         __openmode    : 2, /* see below 1 */
+                         __modeflag    : 4, /* see below 2 */
+                         __reserve2    : 9, /* n/a */
+
+          char           __device;  __DISK
+          unsigned long  __blksize,         /* see below 3 */
+                         __maxreclen;       /* see below 4 */
+          unsigned short __vsamtype;        /* n/a */
+          unsigned long  __vsamkeylen;      /* n/a */
+          unsigned long  __vsamRKP;         /* n/a */
+          char *         __dsname;          /* fname ftype fmode */
+          unsigned int   __reserve4;        /* n/a */
+
+          /* note 1: values are: __TEXT, __BINARY, __RECORD
+             note 2: values are: __READ, __WRITE, __APPEND, __UPDATE
+                     these values can be added together to determine
+                     the return value; for example, a file opened with
+                     a+ will have the value __READ + __APPEND.
+             note 3: total block size of the file, including ASA
+                     characters as well as RDW information
+             note 4: maximum record length of the data only (includes
+                     ASA characters but excludes RDW information).
+          */
+       };
diff --git a/proginfo/infozip.who b/proginfo/infozip.who
new file mode 100644 (file)
index 0000000..242cd95
--- /dev/null
@@ -0,0 +1,232 @@
+These members of the Info-ZIP group contributed to the development and
+testing of portable Zip.  They are responsible for whatever works in
+Zip.  Whatever doesn't work is solely the fault of the authors of Zip
+(Mark Adler, Rich Wales, Jean-loup Gailly, Kai Uwe Rommel, Igor Mandrichenko,
+Onno van der Linden, Christian Spieler, John Bush, Paul Kienitz, Sergio Monesi
+and Karl Davis). If you have contributed and your name
+has been forgotten, please send a reminder to the zip-bugs address given
+in the Readme file. The names are given here in alphabetical order,
+because it's impossible to classify them by importance of the
+contribution. Some have made a complete port to a new target, some
+have provided a one line fix. All are to be thanked.
+
+Mark Adler              madler@tybalt.caltech.edu       NeXT 2.x
+                        alan@spri.levels.unisa.edu.au   Linux
+Jeffrey Altman          jaltman@watsun.cc.columbia.edu  fseek bug on NT
+Glenn J. Andrews        oper1%drcv06.decnet@drcvax.af.mil       VAX VMS
+James Van Artsdalen     james@raid.dell.com             bug report
+Eric Backus             ericb@lsid.hp.com               bug report
+Quentin Barnes          qbarnes@urbana.css.mot.com      unix/Makefile mode of
+                                                        installed files
+Elmar Bartel            bartel@informatik.tu-muenchen.de
+Mark E. Becker          mbecker@cs.uml.edu              bug report
+Paul von Behren         Paul_von_Behren@stortek.com     OS/390 port
+Jon Bell                swy@wsdot.wa.gov                Intergraph/CLIX
+Michael Bernardi        mike@childsoc.demon.co.uk       RS6000
+Tom Betz                marob!upaya!tbetz@phri.nyu.edu  SCO Xenix 2.3.1
+James Birdsall          jwbirdsa@picarefy.com           AT&T 3B1
+George                  boer@fwi.uva.nl                 OS/2
+Michael Bolton          bolton@vaxc.erim.org            VAX/VMS
+Wim Bonner              27313853@WSUVM1.CSC.WSU.EDU     HP 9000/840a HPUX
+Paul Borman             prb@cray.com                    Cray-X/YMP,2 UNICOS 6-8
+Kurt Van den Branden    kvd2@bipsy.se.bel.alcatel.be    VAX VMS
+Scott Briggs            briggs@nashua.progress.com      Windows NT
+Leslie C. Brown         lbrown@BRL.MIL                  Pyramid MIS-4
+Ralf Brown              ralf@b.gp.cs.cmu.edu            Pyramid MIS-4
+Rodney Brown            rdb@cmutual.com.au              SunOS 4.1.3 DGUX OSF/1
+                                                        HP-UX  CRC optimization
+Jeremy Daniel Buhler    jbuhler@owlnet.rice.edu         BC++
+John Bush               john.bush@east.sun.com          Amiga (SAS/C)
+Pietro Caselli          zaphod@petruz.sublink.org       Minix 1.5.10
+Andrew A. Chernov       ache@astral.msk.su              FreeBSD
+Jeff Coffler            jeffcof@microsoft.com           Windows NT
+David Dachtera          David.Dachtera@advocatehealth.com  VMS
+                                                        link_zip.com bug
+Bill Davidsen           davidsen@crdos1.crd.ge.com      Xenix (on what?)
+Karl Davis              riscman@geko.com.au             Acorn
+Daniel Deimert          daniel@pkmab.se                 zeus3.21 Zilog S8000
+David Denholm           denholm@sotona.physics.southampton.ac.uk   VMS
+Harald Denker           harry@hal.westfalen.de          ATARI
+Matthew J. D'Errico     doc@magna.com                   Bull
+L. Peter Deutsch        ghost@aladdin.com               Linux
+Uwe Doering             gemini@geminix.in-berlin.de     386 Unix
+Jean-Michel Dubois      jmdubois@ibcfrance.fr           Theos support
+James P. Dugal          jpd@usl.edu                     Pyramid 90X OSx4.1
+"Evil Ed"               esaffle@gmuvax2.gmu.edu         Ultrix-32 V3.1 (Rev. 9)
+Patrick Ellis           pellis@aic.mdc.com              VMS zip -h appearance
+Thomas Esken            esken@uni-muenster.de           Acorn fix
+Dwight Estep            estep@dlo10.enet.dec.com        MSDOS
+David A. Feinleib       t-davefe@microsoft.com          Windows NT
+Joshua Felsteiner       joshua@phys1.technion.ac.il     Linux
+Greg Flint              afc@klaatu.cc.purdue.edu        ETA-10P* hybrid Sys V
+Carl Forde              cforde@bcsc02.gov.bc.ca         VM/CMS
+Jeff Foy                jfoy@glia.biostr.washington.edu IRIX Sys V Rel 3.3.1
+Mike Freeman            mikef@pacifier.com              Vax VMS
+Kevin M. Fritz          kmfritz@apgea.army.mil          Turbo C++ 1.0
+                                                        Pyramid
+Jean-loup Gailly        jloup@chorus.fr                 MS-DOS Microsoft C 5.1
+Scott D. Galloway       sgallowa@letterkenn-emh1.army.mil   Sperry 5000 SysV.3
+Rainer Gerling          gerling@faupt101.physik.uni-erlangen.de   HPUX, MSDOS
+Henry Gessau            henryg@kullmar.kullmar.se       Windows NT
+Ian E. Gorman           ian@iosphere.net                ported zip 2.2 to VM/CMS
+Wayne R. Graves         graves@csa2.lbl.gov             Vax VMS
+George Grimes           grimes@netcom.com               Apollo Domain SR10.4
+Hunter Goatley          goathunter@MadGoat.com          VMS (VAX & Alpha)
+Arnt Gulbrandsen        agulbra@pvv.unit.no             Linux
+David Gundlach          david@rolf.stat.uga.edu         Sun SS1+ SunOS 4.1
+Peter Gutmann           pgut1@cs.aukuni.ac.nz           bug report
+Dirk Haase              d_haase@sitec.de                MacOS port
+Mark Hanning-Lee        markhl@iris-355.jpl.nasa.gov    SGI
+Walter Haidinger        e9225662@student.tuwien.ac.at   Amiga and general fixes
+Charles Hannum          mycroft@ai.mit.edu              bug report
+Greg Hartwig            ghartwig@ix.netcom.com          VM/CMS cleanup
+Tanvir Hassan           tanvir.hassan@autodesk.com      NT
+Bob Hardy               hardy@lucid.com                 Power C on MSDOS
+Zachary Heilig          heilig@plains.nodak.edu         Turbo C++ 3.0
+Chris Herborth          chrish@pobox.com                BeOS port
+Jonathan Hudson         jrhudson@bigfoot.com            QDOS port
+Mark William Jacobs     mark@mensch.stanford.edu        MSDOS
+Aubrey Jaffer           jaffer@martigny.ai.mit.edu      Pixel
+Peter Jones             jones.peter@uqam.ca             MIPS UMIPS 4.0
+                                                        +Onolimit fix for HP-UX
+Kjetil W. J{\o}rgensen  jorgens@lise.unit.no            OSF/1, DJGPP v2
+Bruce Kahn              bkahn@archive.webo.dg.com       MS-DOS Microsoft C 5.1
+Jonathan I. Kamens      jik@pit-manager.mit.edu         ultrix on DECstation
+Dave Kapalko            d.kapalko@att.com               bug report
+Bob Kemp                Robert.V.Kemp@att.com           AT&T 3B2 SysV 3.2v2
+Vivek Khera             khera@cs.duke.edu               SunOS
+Earl Kiech              KIECH@utkvx.utk.edu             VAX VMS V5.4-1A
+Paul Kienitz            Paul.Kienitz@shelter.sf.ca.us   Amiga, Watcom C
+David Kirschbaum        kirsch@usasoc.soc.mil           He got us all in this
+                                                        mess in the first place
+Thomas Klausner         wiz@danbala.tuwien.ac.at        cygwin32 and -k fix
+D. Krumbholz            krumbh00@marvin.informatik.uni-dortmund.de
+                                                        Acorn filetype and
+                                                        timestamp bug report
+
+Bo Kullmar              bk@kullmar.se                   DNIX 5.3, SunOS 4.1
+Baden Kudrenecky        baden@unixg.ubc.ca              OS/2
+Giuseppe La Sala        lasala@mail.esa.esrin.it        VMS
+Jean-Marc Lasgouttes    jean-marc.lasgouttes@inria.fr   Bug report
+Harry Langenbacher      harry@neuron6.Jpl.Nasa.Gov      Sun SS1+ SunOS 4.1
+Michael D. Lawler       mdlawler@gwmicro.com            Mt.Xinu BSD 4.3 on VAX
+                                                        Borland C++ 4.51
+Johnny Lee              johnnyl@microsoft.com           Microsoft C 7.0
+Michael Lemke           michael@io.as.utexas.edu        VMS
+David Lemson            lemson@ux1.cso.uiuc.edu         Sequent Dynix 3.0.17
+Tai-Shan Lin            tlin@snakeyes.eecs.wsu.edu      OS/2
+Onno van der Linden     onno@simplex.nl                 NetBSD, Borland C++,
+                                                        MSC 7.0, DJGPP 2
+
+Michel                  loehden%mv13.decnet@vax.hrz.uni-marburg.de  VMS
+Warner Losh             imp@Solbourne.COM               packing algorithm help
+Dave Lovelace           davel@grex.cyberspace.org       DG AOS/VS
+Erik Luijten            erik@tntnhb3.tn.tudelft.nl      problem report
+John Lundin             lundin@urvax.urich.edu          VAX VMS
+Igor Mandrichenko       mandrichenko@m10.ihep.su        VAX VMS
+Cliff Manis             root@csoftec.csf.com            SCO 2.3.1 (386)
+Fulvio Marino           fulvio@iconet.ico.olivetti.it   X/OS 2.3 & 2.4
+Bill Marsh              bmarsh@cod.nosc.mil             SGI Iris 4D35
+Michael Mauch           mauch@gmx.de                    djgpp LFN attribute fix
+Peter Mauzey            ptm@mtdcr.mt.lucent.com         AT&T 6300, 7300
+Rafal Z. Maszkowski     rzm@mat.torun.edu.pl            Convex
+Robert McBroom (?)      rm3@ornl.gov                    DECsystem 5810
+Tom McConnell           tmcconne@sedona.intel.com       NCR SVR4
+Frank P. McIngvale      frankm@eng.auburn.edu           Bug report
+Conor McMenamin         C.S.McMenamin@sussex.ac.uk      MSDOS
+John Messenger          jlm@proteon.com                 Bug report
+Michael                 kuch@mailserv.zdv.uni-tuebingen.de SGI
+Dan Mick                dmick@pongo.west.sun.com        Solaris
+Alan Modra              alan@spri.levels.unisa.edu.au   Linux
+Laszlo Molnar           lmolnar@goliat.eik.bme.hu       DJGPP v2
+Jim Mollmann            jmq@nccibm1.bitnet              OS/2 & MVS
+Sergio Monesi           pel0015@cdc8g5.cdc.polimi.it    Acorn
+J. Mukherjee            jmukherj@ringer.cs.utsa.edu     OS/2
+Anthony Naggs           amn@ubik.demon.co.uk            bug report
+Matti Narkia            matti.narkia@ntc.nokia.com      VAX VMS
+Robert E. Newman Jr.    newmanr@ssl.msfc.nasa.gov       bug report
+Robert Nielsen          NielsenRJ@ems.com               2.2 -V VMS bug report
+Christian Michel        cmichel@de.ibm.com              2.2 check_dup OS/2 bug
+                                                        report
+Thomas S. Opheys        opheys@kirk.fmi.uni-passau.de   OS/2
+Humberto Ortiz-Zuazaga  zuazaga@ucunix.san.uc.edu       Linux
+James E. O'Dell         jim@fpr.com                     MacOS
+William O'Shaughnessy   williamo@hpcupt1.cup.hp.com     HPUX
+Neil Parks              neil.parks@pcohio.com           MSDOS
+Enrico Renato Palmerini palmer@vxscaq.cineca.it         UNISYS 7000 Sys 5 r2.3
+Geoff Pennington        Geoff.Pennington@sgcs.co.uk     -q output bug
+Keith Petersen          w8sdz@simtel20.army.mil         Pyramid UCB OSx4.4c
+George Petrov                                           VM/CMS, MVS
+Alan Phillips           postmaster@lancaster.ac.uk      Dynix/ptx 1.3
+Bruno Pillard           bp@chorus.fr                    SunOS 4.1
+Piet W. Plomp           piet@icce.rug.nl                MSC 7.0, SCO 3.2v4.0
+John Poltorak           j.poltorak@bradford.ac.uk       problem report
+Kenneth Porter          72420.2436@compuserve.com       OS/2
+Norbert Pueschel        pueschel@imsdd.meb.uni-bonn.de  Amiga time.lib
+Yuval Rakavy            yuval@cs.huji.ac.il             MSDOS
+David A Rasmussen       dave@convex.csd.uwm.edu         Convex C220 with 9.0 OS
+Eric Raymond            esr@snark.thyrsus.com           Unix
+Jim Read                74312.3103@compuserve.com       OS/2
+Michael Regoli          mr@cica.indiana.edu             Ultrix 3.1 VAX 8650
+                                                        BSD 4.3 IBM RT/125
+                                                        BSD 4.3 MicroVAX 3500
+                                                        SunOS 4.0.3 Sun 4/330
+Jochen Roderburg        roderburg@rrz.uni-koeln.de      Digital Unix with
+                                                        AFS/NFS converter
+Rick Rodgers            rodgers@maxwell.mmwb.ucsf.EDU   Unix man page
+Greg Roelofs            roe2@midway.uchicago.edu        SunOS 4.1.1,4.1.2 Sun 4
+                                                        Unicos 5.1--6.1.5 Cray
+                                                        OS/2 1.3 MS C 6.0
+                                                        Ultrix 4.1,4.2 DEC 5810
+                                                        VMS 5.2, 5.4 VAX 8600
+                                                        Irix 3.3.2, SGI Iris 4D
+                                                        UTS 1.2.4 Amdahl 5880
+Phil Ritzenthaler       phil@cgrg.ohio-state.edu        SYSV
+Kai Uwe Rommel          rommel@ars.de or rommel@leo.org OS/2
+Markus Ruppel           m.ruppel@imperial.ac.uk         OS/2
+Shimazaki Ryo           eririn@ma.mailbank.ne.jp        human68k
+Jon Saxton              jrs@panix.com                   Microsoft C 6.0
+Steve Salisbury         stevesa@msn.com                 Microsoft C 8.0
+Timo Salmi              ts@uwasa.fi                     bug report
+Darren Salt             ds@youmustbejoking.demon.co.uk  RISC OS
+NIIMI Satoshi           a01309@cfi.waseda.ac.jp         Human68K
+Tom Schmidt             tschmidt@micron.com             SCO 286
+Martin Schulz           martin.schulz@isltd.insignia.com Windows NT, Atari
+Dan Seyb                dseyb@halnet.com                AIX
+Mark Shadley            shadcat@catcher.com             unix fixes
+Timur Shaporev          tim@rd.relcom.msk.su            MSDOS
+W. T. Sidney            sidney@picard.med.ge.com        bug report
+Dave Sisson             daves@vtcosy.cns.vt.edu         AIX 1.1.1 PS/2 & 3090
+Dave Smith              smithdt@bp.com                  Tandem port
+Fred Smith              fredex@fcshome.stoneham.ma.us   Coherent
+Christian Spieler       spieler@ikp.tu-darmstadt.de     VMS, MSDOS, emx, djgpp,
+                                                        WIN32, Linux
+Ron Srodawa             srodawa@vela.acs.oakland.edu    SCO Xenix/386 2.3.3
+Adam Stanley            astanley@winternet.com          MSDOS
+Bertil Stenstr|m        stenis@heron.dafa.se            HP-UX 7.0 HP9000/835
+Carl Streeter           streeter@oshkoshw.bitnet        OS/2
+Reuben Sumner           rasumner@undergrad.math.uwaterloo.ca  Suggestions
+E-Yen Tan               e-yen.tan@brasenose.oxford.ac.uk Borland C++ win32
+Yoshioka Tsuneo         tsuneo-y@is.aist-nara.ac.jp     Multibyte charset
+                                                        support
+Paul Telles             paul@pubnet.com                 SCO Xenix
+Julian Thompson         jrt@oasis.icl.co.uk             bug report
+Christopher C. Tjon     tjon@plains.nodak.edu           bug report
+Robert F Tobler         rft@cs.stanford.edu             bug report
+Eric  Tomio             tomio@acri.fr                   bug report
+Cosmin Truta            cosmint@cs.ubbcluj.ro           win32 gcc based + asm
+Anthony R. Venson       cevens@unix1.sncc.lsu.edu       MSDOS/emx
+Antoine Verheijen       antoine@sysmail.ucs.ualberta.ca envargs fix
+Arjan de Vet            devet@info.win.tue.nl           SunOS 4.1, MSC 5.1
+Santiago Vila Doncel    sanvila@ba.unex.es              MSDOS
+Johan Vromans           jv@mh.nl                        bug report
+Rich Wales              wales@cs.ucla.edu               SunOS 4.0.3 Sun-3/50
+Scott Walton            scottw@io.com                   BSD/386
+Frank J. Wancho         wancho@wsmr-simtel20.army.mil   TOPS-20
+                        oyvind@stavanger.sgp.slb.com    Bug report.
+Takahiro Watanabe       wata@first.tsukuba.ac.jp        fixes for INSTALL
+Mike White              mwhite@pumatech.com             wizzip DLL
+Ray Wickert             wickert@dc-srv.pa-x.dec.com     MSDOS/DJGPP
+Winfried Winkler        willi@wap0109.chem.tu-berlin.de AIX
+Norman J. Wong          as219@freenet.carleton.ca       MSDOS
+Martin Zinser           m.zinser@gsi.de                 VMS 7.x
diff --git a/proginfo/nt.sd b/proginfo/nt.sd
new file mode 100644 (file)
index 0000000..8ac31ba
--- /dev/null
@@ -0,0 +1,111 @@
+Info-ZIP portable Zip/UnZip Windows NT security descriptor support
+==================================================================
+Scott Field (sfield@microsoft.com), 8 October 1996
+
+
+This version of Info-ZIP's Win32 code allows for processing of Windows
+NT security descriptors if they were saved in the .zip file using the
+appropriate Win32 Zip running under Windows NT.  This also requires
+that the file system that Zip/UnZip operates on supports persistent
+Acl storage.  When the operating system is not Windows NT and the
+target file system does not support persistent Acl storage, no security
+descriptor processing takes place.
+
+A Windows NT security descriptor consists of any combination of the
+following components:
+
+       an owner (Sid)
+       a primary group (Sid)
+       a discretionary ACL (Dacl)
+       a system ACL (Sacl)
+       qualifiers for the preceding items
+
+By default, Zip will save all aspects of the security descriptor except
+for the Sacl.  The Sacl contains information pertaining to auditing of
+the file, and requires a security privilege be granted to the calling
+user in addition to being enabled by the calling application.  In order
+to save the Sacl during Zip, the user must specify the -! switch on the
+Zip commandline.  The user must also be granted either the SeBackupPrivilege
+"Backup files and directories" or the SeSystemSecurityPrivilege "Manage
+auditing and security log".
+
+By default, UnZip will not restore any aspects of the security descriptor.
+If the -X option is specified to UnZip, the Dacl is restored to the file.
+The other items in the security descriptor on the new file will receive
+default values.  If the -XX option is specified to UnZip, as many aspects
+of the security descriptor as possible will be restored.  If the calling
+user is granted the SeRestorePrivilege "Restore files and directories",
+all aspects of the security descriptor will be restored.  If the calling
+user is only granted the SeSystemSecurityPrivilege "Manage auditing and
+security log", only the Dacl and Sacl will be restored to the new file.
+
+Note that when operating on files that reside on remote volumes, the
+privileges specified above must be granted to the calling user on that
+remote machine.  Currently, there is no way to directly test what privileges
+are present on a remote machine, so Zip and UnZip make a remote privilege
+determination based on an indirect method.
+
+UnZip considerations
+--------------------
+
+In order for file security to be processed correctly, any directory entries
+that have a security descriptor will be processed at the end of the unzip
+cycle.  This allows for unzip to process files within the newly created
+directory regardless of the security descriptor associated with the directory
+entry.  This also prevents security inheritance problems that can occur as
+a result of creating a new directory and then creating files in that directory
+that will inherit parent directory permissions; such inherited permissions may
+prevent the security descriptor taken from the zip file from being applied
+to the new file.
+
+If directories exist which match directory/extract paths in the .zip file,
+file security is not updated on the target directory.  It is assumed that if
+the target directory already exists, then appropriate security has already
+been applied to that directory.
+
+"unzip -t" will test the integrity of stored security descriptors when
+present and the operating system is Windows NT.
+
+ZipInfo (unzip -Z) will display information on stored security descriptor
+when "unzip -Zv" is specifed.
+
+
+Potential uses
+==============
+
+The obvious use for this new support is to better support backup and restore
+operations in a Windows NT environment where NTFS file security is utilized.
+This allows individuals and organizations to archive files in a portable
+fashion and transport these files across the organization.
+
+Another potential use of this support is setup and installation.  This
+allows for distribution of Windows NT based applications that have preset
+security on files and directories.  For example, prior to creation of the
+.zip file, the user can set file security via File Manager or Explorer on
+the files to be contained in the .zip file.  In many cases, it is appropriate
+to only grant Everyone Read access to .exe and .dll files, while granting
+Administrators Full control.  Using this support in conjunction with the
+unzipsfx.exe self-extractor stub can yield a useful and powerful way to
+install software with preset security (note that -X or -XX should be
+specified on the self-extractor commandline).
+
+When creating .zip files with security which are intended for transport
+across systems, it is important to take into account the relevance of
+access control entries and the associated Sid of each entry.  For example,
+if a .zip file is created on a Windows NT workstation, and file security
+references local workstation user accounts (like an account named Fred),
+this access entry will not be relevant if the .zip file is transported to
+another machine.  Where possible, take advantage of the built-in well-known
+groups, like Administrators, Everyone, Network, Guests, etc.  These groups
+have the same meaning on any Windows NT machine.  Note that the names of
+these groups may differ depending on the language of the installed Windows
+NT, but this isn't a problem since each name has well-known ID that, upon
+restore, translates to the correct group name regardless of locale.
+
+When access control entries contain Sid entries that reference Domain
+accounts, these entries will only be relevant on systems that recognize
+the referenced domain.  Generally speaking, the only side effects of
+irrelevant access control entries is wasted space in the stored security
+descriptor and loss of complete intended access control.  Such irrelevant
+access control entries will show up as "Account Unknown" when viewing file
+security with File Manager or Explorer.
diff --git a/proginfo/perform.dos b/proginfo/perform.dos
new file mode 100644 (file)
index 0000000..98744ee
--- /dev/null
@@ -0,0 +1,183 @@
+Date: Wed, 27 Mar 1996 01:31:50 CET +0100
+From: Christian Spieler (IKDA, THD, D-64289 Darmstadt)
+Subject: More detailed comparison of MSDOS Info-ZIP programs' performance
+
+Hello all,
+
+In response to some additional questions and requests concerning
+my previous message about DOS performance of 16/32-bit Info-ZIP programs,
+I have produced a more detailed comparison:
+
+System:
+Cx486DX-40, VL-bus, 8MB; IDE hard disk;
+DOS 6.2, HIMEM, EMM386 NOEMS NOVCPI, SMARTDRV 3MB, write back.
+
+I have used the main directory of UnZip 5.20p as source, including the
+objects and executable of an EMX compile for unzip.exe (to supply some
+binary test files).
+
+Tested programs were (my current updated sources!) Zip 2.0w and UnZip 5.20p
+- 16-bit MSC 5.1, compressed with LZEXE 0.91e
+- 32-bit Watcom C 10.5, as supplied by Kai Uwe Rommel (PMODE 1.22)
+- 32-bit EMX 0.9b
+- 32-bit DJGPP v2
+- 32-bit DJGPP v1.12m4
+
+The EMX and DJ1 (GO32) executables were bound with the full extender, to
+create standalone executables.
+
+A) Tests of Zip
+  Command :  "<system>\zip.exe -q<#> tes.zip unz/*"  (unz/*.* for Watcom!!)
+             where <#> was: 0, 1, 6, 9.
+             The test archive "tes.zip" was never deleted, this test
+             measured "time to update archive".
+
+  The following table contains average execution seconds (averaged over
+  at least 3 runs, with the first run discarted to fill disk cache);
+  numbers in parenteses specify the standard deviation of the last
+  digits.
+
+  cmpr level|      0     |      1     |      6     |      9
+ ===============================================================
+  EMX win95 |   7.77     |   7.97     |  12.82     |  22.31
+ ---------------------------------------------------------------
+  EMX       |   7.15(40) |   8.00(6)  |  12.52(25) |  20.93
+  DJ2       |  13.50(32) |  14.20(7)  |  19.05     |  28.48(9)
+  DJ1       |  13.56(30) |  14.48(3)  |  18.70     |  27.43(13)
+  WAT       |   6.94(22) |   8.93     |  15.73(34) |  30.25(6)
+  MSC       |   5.99(82) |   9.40(4)  |  13.59(9)  |  20.77(4)
+ ===============================================================
+
+ The "EMX win95" line was created for comparison, to check the performance
+ of emx 0.9 with the RSX extender in a DPMI environment. (This line was
+ produced by applying the "stubbed" EMX executable in a full screen DOS box.)
+
+
+B) Tests of UnZip
+  Commands :  <system>\unzip.exe -qt tes.zip         (testing performance)
+              <system>\unzip.exe -qo tes.zip -dtm    (extracting performance)
+
+  The tes.zip archive created by maximum compression with the Zip test
+  was used as example archive. Contents (archive size was 347783 bytes):
+   1028492 bytes uncompressed, 337235 bytes compressed, 67%, 85 files
+
+  The extraction directory tm was not deleted between the individual runs,
+  thus this measurement checks the "overwrite all" time.
+
+           |     testing               |          extracting
+  ===================================================================
+  EMX      |       1.98                |         6.43(8)
+  DJ2      |       2.09                |        11.85(39)
+  DJ1      |       2.09                |         7.46(9)
+  WAT      |       2.42                |         7.10(27)
+  MSC      |       4.94                |         9.57(31)
+
+Remarks:
+
+The executables compiled by me were generated with all "performance"
+options enabled (ASM_CRC, and ASMV for Zip), and with full crypt support.
+For DJ1 and DJ2, the GCC options were "-O2 -m486", for EMX "-O -m486".
+
+The Watcom UnZip was compiled with ASM_CRC code enabled as well,
+but the Watcom Zip example was made without any optional assembler code!
+
+
+
+Discussion of the results:
+
+In overall performance, the EMX executables clearly win.
+For UnZip, emx is by far the fastest program, and the Zip performance is
+comparable to the 16-bit "reference".
+
+Whenever "real" work including I/O is requested, the DJGPP versions
+lose badly because of poor I/O performance, this is the case especially
+for the "newer" DJGPP v2 !!!
+(I tried to tweak with the transfer buffer size, but without any success.)
+An interesting result is that DJ v1 UnZip works remarkably better than
+DJ v2 (in contrast to Zip, where both executables' performance is
+approximately equal).
+
+The Watcom C programs show a clear performance deficit in the "computational
+part" (Watcom C compiler produces code that is far from optimal), but
+the extender (which is mostly responsible for the I/O throughput) seems
+to be quite fast.
+
+The "natural" performance deficit of the 16-bit MSC code, which can be
+clearly seen in the "testing task" comparison for UnZip, is (mostly,
+for Zip more than) compensated by the better I/O throughput (due to the
+"direct interface" between "C RTL" and "DOS services", without any mode
+switching).
+
+But performance is only one aspect when choosing which compiler should
+be used for official distribution:
+
+Sizes of the executables:
+    |             Zip                ||           UnZip
+    | standalone           stub      || standalone    |     stub
+======================================================================
+EMX | 143,364  (1) |    94,212       ||  159,748  (1) |   110,596
+DJ2 | 118,272  (2) |       --        ||  124,928  (2) |      --
+DJ1 | 159,744      |    88,064       ||  177,152      |   105,472
+WAT | 140,073      |       --        ||  116,231      |      --
+MSC |  49,212  (3) |       --        ||   45,510  (3) |      --
+
+(1) does not run in "DPMI only" environment (Windows DOS box)
+(2) requires externally supplied DPMI server
+(3) compressed with LZexe 0.91
+
+Caveats/Bugs/Problems of the different extenders:
+
+EMX:
+- requires two different extenders to run in all DOS-compatible environments,
+  EMX for "raw/himem/vcpi" and RSX for "dpmi" (Windows).
+- does not properly support time zones (no daylight savings time)
+
+DJv2:
+- requires an external (freely available) DPMI extender when run on plain
+  DOS; this extender cannot (currently ??) be bound into the executable.
+
+DJv1:
+- uses up large amount of "low" dos memory (below 1M) when spawning
+  another program, each instance of a DJv1 program requires its private
+  GO32 extender copy in low dos memory (may be problem for the zip
+  "-T" feature)
+
+Watcom/PMODE:
+- extended memory is allocated statically (default: ALL available memory)
+  This means that a spawned program does not get any extended memory.
+  You can work around this problem by setting a hard limit on the amount
+  of extended memory available to the PMODE program, but this limit is
+  "hard" and restricts the allocatable memory for the program itself.
+  In detail:
+  The Watcom zip.exe as distributed did not allow the "zip -T" feature;
+  there was no extended memory left to spawn unzip.
+  I could work around this  problem by applying PMSETUP to change the
+  amount of allocated extended memory to 2.0 MByte (I had 4MB free extended
+  memory on my test system). But, this limit cannot be enlarged at
+  runtime, when zip needs more memory to store "header info" while
+  zipping up a huge drive, and on a system with less free memory, this
+  method is not applicable, either.
+
+Summary:
+
+For Zip:
+Use the 16-bit executable whenever possible (unless you need the
+larger memory capabilities when zipping up a huge amount of files)
+
+As 32-bit executable, we may distribute Watcom C (after we have confirmed
+that enabling ASMV and ASM_CRC give us some better computational
+performance.)
+The alternative for 32-bit remains DJGPP v1, which shows the least problems
+(to my knowledge); v2 and EMX cannot be used because of their lack of
+"universality".
+
+For UnZip:
+Here, the Watcom C 32-bit executable is probably the best compromise,
+but DJ v1 could be used as well.
+And, after all, the 16-bit version does not lose badly when doing
+"real" extraction! For the SFX stub, the 16-bit version remains first
+choice because of its much smaller size!
+
+Best regards
+
+Christian Spieler
diff --git a/proginfo/txtvsbin.txt b/proginfo/txtvsbin.txt
new file mode 100644 (file)
index 0000000..6ba2805
--- /dev/null
@@ -0,0 +1,112 @@
+A Fast Method of Identifying Plain Text Files
+=============================================
+
+
+Introduction
+------------
+
+Given a file coming from an unknown source, it is generally impossible
+to conclude automatically, and with 100% accuracy, whether that file is
+a plain text file, without performing a heavy-duty semantic analysis on
+the file contents.  It is, however, possible to obtain a fairly high
+degree of accuracy, by employing various simple heuristics.
+
+Previous versions of the zip tools were using a crude detection scheme,
+originally used by PKWare in its PKZip programs: if more than 80% (4/5)
+of the bytes are within the range [7..127], the file is labeled as plain
+text, otherwise it is labeled as binary.  A prominent limitation of this
+scheme is the restriction to Latin-based alphabets.  Other alphabets,
+like Greek, Cyrillic or Asian, make extensive use of the bytes within
+the range [128..255], and texts using these alphabets are most often
+mis-identified by this scheme; in other words, the rate of false
+negatives is sometimes too high, which means that the recall is low.
+Another weakness of this scheme is a reduced precision, due to the false
+positives that may occur when binary files containing a large amount of
+textual characters are mis-identified as plain text.
+
+In this article we propose a new detection scheme, with a much increased
+accuracy and precision, and a near-100% recall.  This scheme is designed
+to work on ASCII and ASCII-derived alphabets, and it handles single-byte
+alphabets (ISO-8859, OEM, KOI-8, etc.), and variable-sized alphabets
+(DBCS, UTF-8, etc.).  However, it cannot handle fixed-sized, multi-byte
+alphabets (UCS-2, UCS-4), nor UTF-16.  The principle used by this scheme
+can easily be adapted to non-ASCII alphabets like EBCDIC.
+
+
+The Algorithm
+-------------
+
+The algorithm works by dividing the set of bytes [0..255] into three
+categories:
+- The white list of textual bytecodes:
+  9 (TAB), 10 (LF), 13 (CR), 20 (SPACE) to 255
+- The gray list of tolerated bytecodes:
+  7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC)
+- The black list of undesired, non-textual bytecodes:
+  0 (NUL) to 6, 14 to 31.
+
+If a file contains at least one byte that belongs to the white list, and
+no byte that belongs to the black list, then the file is categorized as
+plain text.  Otherwise, it is categorized as binary.
+
+
+Rationale
+---------
+
+The idea behind this algorithm relies on two observations.
+
+The first observation is that, although the full range of 7-bit codes
+(0..127) is properly specified by the ASCII standard, most control
+characters in the range 0..31 are not used in practice.  The only
+widely-used, almost universally-portable control codes are 9 (TAB),
+10 (LF), and 13 (CR).  There are a few more control codes that are
+recognized on a reduced range of platforms and text viewers/editors:
+7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), and 27 (ESC); but these
+codes are rarely (if ever) used alone, without being accompanied by
+some printable text.  Even the newer, portable text formats, such as
+XML, avoid using control characters outside the list mentioned here.
+
+The second observation is that most of the binary files tend to contain
+control characters, especially 0 (NUL); even though the older text
+detection schemes observe the presence of non-ASCII codes from the range
+[128..255], the precision rarely has to suffer if this upper range is
+labeled as textual, because the files that are genuinely binary tend to
+contain both control characters, and codes from the upper range.  On the
+other hand, the upper range needs to be labeled as textual,  because it
+is being used by virtually all ASCII extensions.  In particular, this
+range is being heavily used to encode non-Latin scripts.
+
+Given the two observations, the plain text detection algorithm becomes
+straightforward.  There must be at least some printable material, or
+some portable whitespace such as TAB, CR or LF, otherwise the file is
+not labeled as plain text.  (The boundary case, when the file is empty,
+automatically falls into this category.)  However, there must be no
+non-portable control characters, otherwise it's very likely that the
+intended reader of that file is a machine, rather than a human.
+
+Since there is no counting involved, other than simply observing the
+presence or the absence of some byte values, the algorithm produces
+uniform results on any particular text file, no matter what alphabet
+encoding is being used for that text.  (In contrast, if counting were
+involved, it could be possible to obtain different results on a text
+encoded, say, using ISO-8859-2 versus UTF-8.)  There is the category
+of plain text files that are "polluted" with one or a few black-listed
+codes, either by mistake, or by peculiar design considerations.  In such
+cases, a scheme that tolerates a small percentage of black-listed codes
+would provide an increased recall (i.e. more true positives).  This,
+however, incurs a reduced precision, since false positives are also more
+likely to appear in binary files that contain large chunks of textual
+data.  "Polluted" plain text may, in fact, be regarded as binary, on
+which text conversions should not be performed.  Under this premise, it
+is safe to say that the detection method provides a near-100% recall.
+
+Experiments have been run on a large set of files of various categories,
+including plain old texts, system logs, source code, formatted office
+documents, compiled object code, etcetera.  The results confirm the
+optimistic assumptions about the high accuracy, precision and recall
+offered by this algorithm.
+
+
+--
+Cosmin Truta
+Last updated: 2005-Feb-27
diff --git a/proginfo/ziplimit.txt b/proginfo/ziplimit.txt
new file mode 100644 (file)
index 0000000..e72d917
--- /dev/null
@@ -0,0 +1,218 @@
+ziplimit.txt
+
+A) Hard limits of the Zip archive format:
+
+   Number of entries in Zip archive:            64 k (2^16 - 1 entries)
+   Compressed size of archive entry:            4 GByte (2^32 - 1 Bytes)
+   Uncompressed size of entry:                  4 GByte (2^32 - 1 Bytes)
+   Size of single-volume Zip archive:           4 GByte (2^32 - 1 Bytes)
+   Per-volume size of multi-volume archives:    4 GByte (2^32 - 1 Bytes)
+   Number of parts for multi-volume archives:   64 k (1^16 - 1 parts)
+   Total size of multi-volume archive:          256 TByte (4G * 64k)
+
+   The number of archive entries and of multivolume parts are limited by
+   the structure of the "end-of-central-directory" record, where the these
+   numbers are stored in 2-Byte fields.
+   Some Zip and/or UnZip implementations (for example Info-ZIP's) allow
+   handling of archives with more than 64k entries.  (The information
+   from "number of entries" field in the "end-of-central-directory" record
+   is not really neccessary to retrieve the contents of a Zip archive;
+   it should rather be used for consistency checks.)
+
+   Length of an archive entry name:             64 kByte (2^16 - 1)
+   Length of archive member comment:            64 kByte (2^16 - 1)
+   Total length of "extra field":               64 kByte (2^16 - 1)
+   Length of a single e.f. block:               64 kByte (2^16 - 1)
+   Length of archive comment:                   64 KByte (2^16 - 1)
+
+   Additional limitation claimed by PKWARE:
+     Size of local-header structure (fixed fields of 30 Bytes + filename
+      local extra field):                     < 64 kByte
+     Size of central-directory structure (46 Bytes + filename +
+      central extra field + member comment):  < 64 kByte
+
+   Note:
+   In 2001, PKWARE has published version 4.5 of the Zip format specification
+   (together with the release of PKZIP for Windows 4.5).  This specification
+   defines new extra field blocks that allow to break the size limits of the
+   standard zipfile structures.  In this extended "Zip64" format, the limits
+   on the size of zip entries and the size of the complete zip archive are
+   extended to (2^64 - 1) Bytes; the maximum number of archive entries and
+   split volumes are enlarged to (2^64 - 1) respective (2^32 - 1).
+   Currently, these extensions are not yet supported by the released Info-ZIP
+   software. However, new major releases (Zip 3.0 and UnZip 6.0) are under
+   development and will support Zip64 archives on selected environments.
+   (Beta releases are already available for Unix, VMS and Win32.)
+
+B) Implementation limits of UnZip:
+
+ 1. Size limits caused by file I/O and decompression handling:
+   Size of Zip archive:                 2 GByte (2^31 - 1 Bytes)
+   Compressed size of archive entry:    2 GByte (2^31 - 1 Bytes)
+
+   Note: On some systems, UnZip may support archive sizes up to 4 GByte.
+         To get this support, the target environment has to meet the following
+         requirements:
+         a) The compiler's intrinsic "long" data types must be able to hold
+            integer numbers of 2^32. In other words - the standard intrinsic
+            integer types "long" and "unsigned long" have to be wider than
+            32 bit.
+         b) The system has to supply a C runtime library that is compatible
+            with the more-than-32-bit-wide "long int" type of condition a)
+         c) The standard file positioning functions fseek(), ftell() (and/or
+            the Unix style lseek() and tell() functions) have to be capable
+            to move to absolute file offsets of up to 4 GByte from the file
+            start.
+         On 32-bit CPU hardware, you generally cannot expect that a C compiler
+         provides a "long int" type that is wider than 32-bit. So, many of the
+         most popular systems (i386, PowerPC, 680x0, et. al) are out of luck.
+         You may find environment that provide all requirements on systems
+         with 64-bit CPU hardware. Examples might be Cray number crunchers
+         or Compaq (former DEC) Alpha AXP machines.
+
+   The number of Zip archive entries is unlimited. The "number-of-entries"
+   field of the "end-of-central-dir" record is checked against the "number
+   of entries found in the central directory" modulus 64k (2^16).
+
+   Multi-volume archive extraction is not supported.
+
+   Memory requirements are mostly independent of the archive size
+   and archive contents.
+   In general, UnZip needs a fixed amount of internal buffer space
+   plus the size to hold the complete information of the currently
+   processed entry's local header. Here, a large extra field
+   (could be up to 64 kByte) may exceed the available memory
+   for MSDOS 16-bit executables (when they were compiled in small
+   or medium memory model, with a fixed 64kByte limit on data space).
+
+   The other exception where memory requirements scale with "larger"
+   archives is the "restore directory attributes" feature. Here, the
+   directory attributes info for each restored directory has to be held
+   in memory until the whole archive has been processed. So, the amount
+   of memory needed to keep this info scales with the number of restored
+   directories and may cause memory problems when a lot of directories
+   are restored in a single run.
+
+C) Implementation limits of the Zip executables:
+
+ 1. Size limits caused by file I/O and compression handling:
+   Size of Zip archive:                 2 GByte (2^31 - 1 Bytes)
+   Compressed size of archive entry:    2 GByte (2^31 - 1 Bytes)
+   Uncompressed size of entry:          2 GByte (2^31 - 1 Bytes),
+                                        (could/should be 4 GBytes...)
+   Multi-volume archive creation is not supported.
+
+ 2. Limits caused by handling of archive contents lists
+
+ 2.1. Number of archive entries (freshen, update, delete)
+     a) 16-bit executable:              64k (2^16 -1) or 32k (2^15 - 1),
+                                        (unsigned vs. signed type of size_t)
+     a1) 16-bit executable:             <16k ((2^16)/4)
+         (The smaller limit a1) results from the array size limit of
+         the "qsort()" function.)
+         32-bit executables             <1G ((2^32)/4)
+         (usual system limit of the "qsort()" function on 32-bit systems)
+
+     b) stack space needed by qsort to sort list of archive entries
+
+     NOTE: In the current executables, overflows of limits a) and b) are NOT
+           checked!
+
+     c) amount of free memory to hold "central directory information" of
+        all archive entries; one entry needs:
+        96 bytes (32-bit) resp. 80 bytes (16-bit)
+        + 3 * length of entry name
+        + length of zip entry comment (when present)
+        + length of extra field(s) (when present, e.g.: UT needs 9 bytes)
+        + some bytes for book-keeping of memory allocation
+
+   Conclusion:
+     For systems with limited memory space (MSDOS, small AMIGAs, other
+     environments without virtual memory), the number of archive entries
+     is most often limited by condition c).
+     For example, with approx. 100 kBytes of free memory after loading and
+     initializing the program, a 16-bit DOS Zip cannot process more than 600
+     to 1000 (+) archive entries.  (For the 16-bit Windows DLL or the 16-bit
+     OS/2 port, limit c) is less important because Windows or OS/2 executables
+     are not restricted to the 1024k area of real mode memory.  These 16-bit
+     ports are limited by conditions a1) and b), say: at maximum approx.
+     16000 entries!)
+
+
+ 2.2. Number of "new" entries (add operation)
+     In addition to the restrictions above (2.1.), the following limits
+     caused by the handling of the "new files" list apply:
+
+     a) 16-bit executable:              <16k ((2^64)/4)
+
+     b) stack size required for "qsort" operation on "new entries" list.
+
+     NOTE: In the current executables, the overflow checks for these limits
+           are missing!
+
+     c) amount of free memory to hold the directory info list for new entries;
+        one entry needs:
+        24 bytes (32-bit) resp. 22 bytes (16-bit)
+        + 3 * length of filename
+
+D) Some technical remarks:
+
+ 1. The 2GByte size limit on archive files is a consequence of the portable
+    C implementation of the Info-ZIP programs.
+    Zip archive processing requires random access to the archive file for
+    jumping between different parts of the archive's structure.
+    In standard C, this is done via stdio functions fseek()/ftell() resp.
+    unix-io functions lseek()/tell(). In many (most?) C implementations,
+    these functions use "signed long" variables to hold offset pointers
+    into sequential files. In most cases, this is a signed 32-bit number,
+    which is limited to ca. 2E+09. There may be specific C runtime library
+    implementations that interpret the offset numbers as unsigned, but for
+    us, this is not reliable in the context of portable programming.
+
+ 2. The 2GByte limit on the size of a single compressed archive member
+    is again a consequence of the implementation in C.
+    The variables used internally to count the size of the compressed
+    data stream are of type "long", which is guaranted to be at least
+    32-bit wide on all supported environments.
+
+    But, why do we use "signed" long and not "unsigned long"?
+
+    Throughout the I/O handling of the compressed data stream, the
+    sign bit of the "long" numbers is (mis-)used as a kind of overflow
+    detection. In the end, this is caused by the fact that standard C
+    lacks any overflow checking on integer arithmetics and does not
+    support access to the underlying hardware's overflow detection
+    (the status bits, especially "carry" and "overflow" of the CPU's
+    flags-register) in a system-independent manner.
+
+    So, we "misuse" the most-significant bit of the compressed data
+    size counters as carry bit for efficient overflow/underflow detection.
+    We could change the code to a different method of overflow detection,
+    by using a bunch of "sanity" comparisons (kind of "is the calculated
+    result plausible when compared with the operands"). But, this would
+    "blow up" the code of the "inner loop", with remarkable loss of
+    processing speed. Or, we could reduce the amount of consistency checks
+    of the compressed data (e.g. detection of premature end of stream) to
+    an absolute minimum, at the cost of the programs' stability when
+    processing corrupted data.
+
+    Summary: Changing the compression/decompression core routines to
+    be "unsigned safe" would require excessive recoding, with little
+    gain on maximum processable uncompressed size (a gain can only be
+    expected for hardly compressable data), but at severe costs on
+    performance, stability and maintainability.  Therefore, it is
+    quite unlikely that this will ever happen for Zip/UnZip.
+
+    The argumentation above is somewhat out-dated. The new releases
+    Zip 3 and UnZip 6 will support archive sizes larger than 4GB on
+    systems where the required underlying support for 64-bit file offsets
+    and file sizes is available from the OS (and the C runtime environment).
+    However, this new support will partially break compatibility with
+    older "legacy" systems.  And it should be expected that the portability
+    and readability of the UnZip and Zip code may be reduced due to the
+    extensive use of non-standard language extension needed for 64-bit
+    support on the major target systems.
+
+Please report any problems to:  Zip-Bugs at www.info-zip.org
+
+Last updated:  22 February 2005, Christian Spieler
diff --git a/qdos/IZREADME.SMS b/qdos/IZREADME.SMS
new file mode 100644 (file)
index 0000000..9ad1503
--- /dev/null
@@ -0,0 +1,600 @@
+IZREADME_SMS (IZREADME.SMS): Info-ZIP for SMS/QDOS,   last revised: 15-Jun-1998
+===============================================================================
+[was "InfoZIP_SMSQDOS_ReadMe" in J. Hudson's original ports, ca. 08/1995]
+
+Info-ZIP Programs
+=================
+
+Zip
+UnZip
+UnZipSFX
+fUnZip
+
+Introduction
+------------
+
+This archive is a result of frustrations with contemporary (August 95)
+versions of Zip and UnZip. While they use the same compression
+algorithms as the Info-ZIP programs, there the compatibility ends. If
+you just use Zip/UnZip only on SMS/QDOS, then perhaps this is not a
+problem (but I know for some users it still is); if you use Zip/UnZip
+to transport source code and data between diverse systems, then the
+disregard for Info-ZIP standards is inconvenient, particularly the
+fact that directories are not supported and files are always stored
+underscored.
+
+This release of Zip/UnZip offers:
+
+    o   zipfile/directory compatibility with all other supported
+        platforms
+
+    o   SMS/QDOS compatibility and back-compatible with earlier
+        versions.
+
+    o   Improved performance (Zip is typically 50% faster)
+
+    o   Command-line compatibility with Info-ZIP
+
+    o   Self-extracting archives (but not very elegantly)
+
+    o   Archives are marked as 'created by SMS/QDOS'.
+
+    o   Optional recursion into directories
+
+    o   Directory structure restored on unzip of Info-ZIP/PKZIP-
+        compatible archives.
+
+    o   Config'urable for listing and unpack formats (Info-ZIP (.) or
+        SMS/QDOS (_) and 'Press any key' timeouts. Override options
+        from command line.
+
+Info-ZIP Standards
+------------------
+
+This (rather long-winded and waffling) section discusses the
+conventions and standards used by Info-ZIP-compatible archivers and how
+"Info-ZIP for SMS/QDOS" achieves compatibility.
+
+Info-ZIP Zip/UnZip on all supported platforms (Unix, DOS, OS/2, NT,
+VAX/VMS, Amiga etc etc), works in a specific way. (Until now SMS/QDOS
+was neither 'supported' nor Info-ZIP-compliant.)
+
+    a. The zipfile directory is in (/.) (Unix) format.
+
+    b. When zips are listed, it is in 'zipfile' (Unix) format.
+
+    c. When files are added, they are defined in native format.
+
+    d. When files are added, this is shown in 'zipfile' format.
+
+    e. When files are unpacked, this is done to native format, but
+       selection is done in 'zipfile' format.
+
+Basically, the listing and stored format of a file is that of the
+destination.
+
+So, given a file structure at some arbitrary 'root' level.
+
+    Makefile
+    src (Dir)
+        afile.c
+        bfile.c
+        docs (Dir)
+             prog.txt
+    hdr (Dir)
+        cfile.h
+        dfile.h
+
+Then these would be in Unix (and Amiga) as
+
+     Makefile
+     src/afile.c
+     src/bfile.c
+     src/docs/prog.txt
+     hdr/cfile.h
+     hdr/dfile.h
+
+This is also how the zipfile directory appears.
+
+And in DOS/OS2/NT
+
+    Makefile
+    src\afile.c
+    src\docs\prog.txt
+    hdr\cfile.h         .. etc
+
+And in VMS      (we SHOUT in VMS and have a silly file system)
+
+    MAKEFILE
+    [SRC]AFILE.C
+    [SRC.DOC]PROG.TXT
+    [HDR]CFILE.H        .. etc
+                        (OK VMS purist, [.SRC] etc. Only an example)
+
+And in SMS/QDOS (quiet again, but slightly ludicrous !)
+
+    Makefile
+    src_afile_c
+    src_doc_prog_txt
+    hdr_cfile_h         .. etc
+
+The main problem regarding SMS/QDOS is not that of extensions - (after
+all, only VMS and DOS _really_ have extensions; Unix, AmigaDOS, NT and
+OS/2 (and Win95) allow multiple '.' in.long.file.names.
+
+The SMS/QDOS problem is that '_' is both a legal file name character
+and a directory separator. This creates the difficulties, as
+directories and files are somewhat different objects.
+
+It is the intention that these versions of SMS/QDOS Zip/UnZip will
+follow the Info-ZIP rules, thus providing compatibility with the other
+platforms. It is possible to zip the file structure described above on
+SMS/QDOS and unpack it on VMS and get the VMS structure as shown in the
+example (and vice-versa). [We only choose the most obtuse file
+systems for the examples].
+
+In order to achieve this, SMS/QDOS names are mapped into Unix-style
+ones when the zipfile is created and un-mapped when it is unpacked.
+There is an option to unpack in 'zipfile' format (i.e. with '.' rather
+than '_'), but there will be no option to pack to all '_'. That would
+contravene the standard.  However, a file
+
+        src_split_name_c        (which is src->split_name_c !)
+                                          src/split_name.c)
+
+where src is a hard directory, would be stored in the zip directory as
+
+      src/split_name.c
+
+It does handle '_' with a little intelligence.
+
+The default UnZip option will be to translate '.' to '_'; this is
+because there are still many QDOS/Minerva users that cannot handle '.'
+without quotes, which is immensely inconvenient. For many SMS users
+'_' is also the most natural and convenient option. It also means that
+SMS/QDOS <-> SMS/QDOS Zip - UnZip sequences are transparent.
+
+There will, however, be two ways around this in UnZip.
+
+      1. It is possible to Config the UnZip default to be '.'
+         translations (or not).
+
+      2.  The UnZip -Q1 option will toggle the default (Config'ed)
+          state.
+
+Examples:
+
+Given that we want/have
+
+     Makefile                   (Makefile)
+     src/afile.c                (src_afile_c)
+     src/bfile.c                (src_bfile_c)
+     src/docs/prog.txt          (src_docs_prog_txt)
+     hdr/cfile.h                (hdr_cfile_h)
+     hdr/dfile.h                (hdr_dfile_h)
+
+Then on SMS/QDOS we might have added the *.c files as
+
+     ex zip;'-r test *_c'
+
+(or VMS, just to do something different)
+
+    zip -r test [.src]*.c
+
+In both cases the file lists as above (left).
+
+To unpack on SMS/QDOS (just the _c/.c files)
+
+   ex unzip;'test src/*.c'
+
+   (and VMS, unzip test src/*.c)
+
+i.e. in both cases using the 'zipfile' format. As a concession to
+SMS/QDOS, you could also have:
+
+   ex unzip;'test src_*_c'
+
+        but not unzip test [.src]*.c on VMS !!!!! Sorry, dinosaurs.
+
+Both SMS/QDOS commands unpack to
+
+     src_afile_c etc, where src_ is a hard sub-directory.
+
+(and the VMS example would unpack to [.src]afile.c, (or to src\afile.c on
+DOS/NT/OS2 etc).
+
+Options & SMS/QDOS Features
+---------------------------
+
+The options supported by Zip/UnZip are basically those documented in
+the Info-ZIP documents and shown in on-line 'usage'. In particular, -r
+and -j work as intended.
+
+PLEASE NOTE: Previous SMS/QDOS zip/unzips have NOT followed these
+conventions, for example -r was not implemented and -j was reversed.
+
+A number of -Q (SMS/QDOS-specific) options (not yet in the current
+documents or usage screens) are implemented.
+
+The Zip 2.0.1 (and later) default is to add SMS/QDOS headers where
+file type = 1 (exe) or 2 (rel) or (type > 0 && != 255 and (filesize %
+64) != 0). Directories are included anyway, unless you zip -D.
+
+Where a header is added for an 'exe' file a '*' is displayed after the
+name in the zip display  (and '#' for 'rel' files).
+
+The -Q options for Zip are:
+
+    -Q1  Don't add headers for ANY files
+    -Q2  Add headers for all files
+    -Q4  Don't wait for interactive key press
+
+    (additive, so -Q5 => no headers, no wait, -Q6 all headers,
+     no wait etc)
+
+    (the default is exec/rel headers, 5 sec wait)
+
+Zip has rationalised the file header storage in zipfiles. The
+previous Zip used to store a QDOS header for each file. This was very
+wasteful, for example compressing a SMS/QDOS release of PGP in this
+way came to 730Kb, too large for a DD disk. Changing the Zip program
+just to add a header record for the single PGP exe and the zipfile
+size went down to around 690Kb.
+
+And for UnZip
+
+    -Q1 Toggle unpack format status ('.' <-> '_')
+    -Q2 Toggle listing format
+    -Q4 Don't wait for key press
+
+Files Types
+-----------
+
+The history of QDOS suffers from incompatible feature
+implementations. For example, Thor directories have file type 3, CST
+have type 4 and Level 2 have type 255. Some software writers (both
+amateur and otherwise) have used type 3 or 4 for other purposes
+(backward compatibility ?? who cares ??).
+
+In order to bypass problems cause by incompatible (inconsiderate ?)
+usage of file types, the file type denoting a directory is a
+Config'urable item. The default is set to -1 (65535 in Config terms),
+which means "determine directory type from the file header of the root
+directory". If this is appears unsuccessful on your system, the value
+can be Config'ed in the range 3-255.
+
+Zip assumes a file is a directory if:
+
+        ((type == CONFIGed_type) && (file_size % 64) == 0)
+
+If you are unfortunate enough have files of that pass this test but
+are not directories, then Zip will loop endless, as SMS/QDOS opens the
+root directory again !!! (recursion: see recursion etc).
+
+I suggest you refrain from zipping such files and contact the software
+supplier and point out the error of their ways.
+
+File Naming Issues
+------------------
+
+Zip will append a '_zip' suffix to the archive filename when the
+supplied name (i.e. excluding device/directory parts) does not
+contain a '_' or a '.'. This is broadly compatible with Info-ZIP,
+taking into account the '_' aberation.
+
+So
+        ex zip;'ram2_test ...'          >> ram2_test_zip
+
+        ex zip;'ram2_test.zip ...'      >> ram2_test.zip
+
+        ex zip;'ram2_test_rep ... '     >> ram2_test_rep
+
+        ex zip;'ram2_fdbbs.rep ... '    >> ram2_fdbbs.rep
+
+        ex zip;'ram2_test_rep.zip ...'  >> ram2_test_rep.zip
+
+This implies that if a file ram2_test.zip exists, and you do:
+
+        ex zip;'ram2_test ...'
+
+Then a new file (test_zip) is created, rather than 'test.zip' being
+updated.
+
+Zip supports extensive recursive wild-carding, again the fact that '_'
+can be a directory separator as well as part of a file name makes this
+a bit tricky, but given the example:
+
+     test1_bas
+     test2_bas
+     dir1->demo1_bas            where -> indicates a sub dir
+     dir2->demo2_bas
+
+     ex zip;'ram2_test *_bas'
+     just finds test1_bas, test2_bas
+
+     ex zip;'-r ram2_test *_bas'
+     recurses and finds all the files
+
+You might think that
+
+    ex zip;'-r ram2_test *_*_bas'
+
+would just find the files in the subdirectories--well yes, but it will
+also find very other sub-dir'ed _bas file on the disk too. This is
+a feature.
+
+The pattern matching supports Unix-style 'regex' so you could:
+
+        ex zip;'ram2_test dir?_*_bas'
+        or
+        ex zip;'ram2_test dir[12]_*_bas
+
+
+UnZip has now got a fixed -d option. This is used to specify the
+directory to unpack the zipfile into, it must follow immediately
+after the zip name.
+
+        ex unzip;'ram2_test_zip -d ram3_ *_txt'
+
+would unpack all *_txt files to ram3_ .
+
+It is not necessary to set the default directory to pack files, Zip
+will remove any device names (and store any hard directory names,
+unless you zip -j).
+
+        ex zip;'ram1_test flp1_*'
+
+                ----->
+                        adding: file.dat (deflated 50%)
+                        adding: menu.rext # (deflated xx%)
+                        adding: zip * (deflated yy%)
+                        adding: hard_one (stored 0%)
+                        adding: hard_one/stuff.bas (deflated ...)
+
+Due to the way the file-mapping is implemented, it is not supported
+over the nX_ type network device.
+
+Config Options
+--------------
+
+A limited number of SMS/QDOS specific functions can be set using the
+QJump Config program.
+
+      For Zip:
+
+      Timeout for interactive 'Press any key' prompt
+
+       65535                  Wait forever      (aka -1)
+       0                      No wait
+       n (1-32767)            Wait for 'n' clocks (1/50 sec)
+
+       Other values are unsupported. Note Config works on 'unsigned'
+       integer values (at least according to my manual).
+
+       Directory file type key.
+
+       Config will accept any value in the range 3-255, known useful
+       values are 3 (Thor), 4 (CST) and 255 (Level 2 devices). A value
+       of 65535 (aka -1) means "determine from device info".
+
+       For UnZip:
+
+       Timeout as above
+
+       Unpack mode (SMS/QOS ('_') or Info-ZIP ('.')
+
+       List format (Info-ZIP ('.') or SMS/QDOS ('_')
+
+
+When the 'Press a key' text is displayed, if you press ESC, then it
+waits until you press any other key, infinite timeout. This may be
+useful if you want (much) more time to study a listing etc.
+
+Defaults for timeout and directory type are 250 and -1 respectively.
+
+More Goodies
+------------
+
+Part of the Zip compression code is now in assembler; it runs
+noticably faster than the previous version. Compressing some arbitrary
+files with the previous Zip it took 251 seconds, with Zip 2.0.1 it
+took (a mere) 170 seconds (68008 QL).
+
+More good news is that SMS/QDOS is just another system option on top
+of standard Info-ZIP, unlike the previous ports that were much more
+SMS/QDOS specific. For example, compiling the standard source with c68
+(i.e. #define QDOS), then you get an SMS/QDOS version.
+
+Compile with Linux/gcc and get the standard Linux version. Now, here's
+the cool bit; compile with Linux/gcc and "-DQLZIP", and get a standard
+Linux Zip/UnZip with SMS/QDOS (header) extensions.
+
+so, on Linux:
+
+            zip -Q stuff.zip qtpi zip unzip
+
+the -Q tells Zip to look for XTc68/Lux68 cross-compiler data size
+blocks and produce a zipfile with SMS/QDOS headers in it (for exec
+type programs). This works for exec files produced by the XTc68/Lux68
+cross compilers and ANY SMS/QDOS files copied to a Unix or MS-DOS disk
+from an SMS/QDOS floppy using 'qltools v2.2' (or later).
+
+Self Extracting Archives
+------------------------
+
+Info-ZIP self-extracting archives (_sfx) are created in a rather
+'brute-force' way. The UnZipSFX program is prepended to a zipfile.
+
+i.e.          file_sfx = unzipsfx + file_zip
+              ex file_sfx
+
+Although the UnZipSFX program is a cut-down UnZip, it is still around
+30Kb - 50Kb, depending on platform.
+
+The success of this approach depends on how the operating system
+loader loads executable files. On most systems where the loader only
+loads the actual program part (Unix, VMS, DOS et al), the this is
+quite efficient; if you make, say, a 4Mb zipfile and prepend a 30Kb
+UnZipSFX image, then the system only loads the 30Kb program and the
+process is efficient as the zipped data part is still unpacked from
+disk. These systems also supply the running UnZipSFX program stub with
+the path name of the file it was loaded from, so the program knows
+what it has to unpack (so on Linux, for example):
+
+     cat /usr/bin/unzipsfx test.zip > test.sfx  # concatenate the files
+     chmod 755 test.sfx                         # make executable
+     test.sfx                                   # to extract, it
+                                                # 'knows' it is "test.sfx"
+
+Unfortunately, the more simplistic nature of SMS/QDOS makes this much
+more difficult and rather less efficient as: (see note 1)
+
+     a. The SMS/QDOS 'loader' loads the whole file into memory.
+
+     b. The SMS/DOS 'loader'/c68 run-time system does not return the
+        name of the file from which it was loaded.
+
+     c. You cannot so easily create a image file by concatenating two
+        files, it is also necessary to ensure the executable file
+        header is set correctly.
+
+     d. The show stopper. The data space required for the
+        self-extracting archive is required, as not easily maintained
+        during electronic transfer.
+
+
+If anyone is still interested, then the following support for UnZipSFX
+is provided.
+
+ o A program 'makesfx' will combine a stub (callstub), UnZipSFX image
+   and a zipfile to produce a sfx (self-extracting zip) file.
+
+ o A callable interface is supplied. The user calls the SFX file,
+   which creates the files necessary to do the extraction.
+
+The makesfx program concatenates the supplied files to standard
+output.
+
+So, to create a sfx of all the _c files in the default directory.
+
+ # 1st create a zipfile of the required files
+
+ ex zip;'ram1_test_zip *_c'
+
+ # Now create the sfx file (ram2_test_sfx)
+ # our UnZipSFX image is in 'win1_bin'
+ # as is the call stub.
+
+ex makesfx;'-o test_sfx -x win1_bin_unzipsfx -s win1_bin_callstub -z ram1_test_zip'
+
+The arguments to makesfx are:
+
+    -s stubfile
+    -x UnZipSFX_program
+    -z Zip_file
+    -o Output_file
+
+You can now unpack the _sfx file on any SMS/QDOS-compatible
+system.
+
+        f$ = "win2_tmp_test_sfx"
+        a = alchp(flen(\f$))
+        lbytes f$,a
+        call a
+        rechp(a)
+
+ZipInfo
+-------
+
+Given the above note concerning SMS/QDOS programs not knowing the name
+by which the program was invoked, then the usual symbolic-link-of-unzip-
+to-zipinfo trick is unavailable (presupposing there is some some SMS/QDOS
+trick to emulate symbolic links).
+
+ZipInfo functionality is only available via 'unzip -Z'. There is no
+separate ZipInfo program.
+
+Caveat ATP Users
+----------------
+
+ATP for SMS/QDOS users should pay particular attention to the
+Zip/UnZip options in their atprc and compare with Info-ZIP Zip/UnZip
+usage. Older versions of Zip/UnZip screwed up -j.
+
+
+        zip -jk
+        unzip -jo
+
+Distribution & Copyright
+------------------------
+
+This software is written by and largely copyrighted by the 'Info-ZIP'
+group whose members are noted in the accompanying documentation. This
+particular SMS/QDOS port plus 'makesfx' was written by, but is not
+copyrighted by, Jonathan R Hudson. The SMS/QDOS code in this release
+is written from scratch and is not dependent on previous SMS/QDOS
+releases, but is (largely) compatible.
+
+As a courtesy to the authors of this package, please ensure that the
+documentation is supplied when it is re-distributed.
+
+In particular, if this archive is split into Zip and UnZip components,
+ensure that this document ("IZREADME_SMS") is supplied in
+each component.
+
+SMS/QDOS version by:
+Jonathan R Hudson (jrhudson@bigfoot.com)
+
+I am grateful to Graham Goodwin for finding some most imaginative
+means of breaking the beta code.
+
+I'd also like to thank Thierry Godefroy for providing the 2.1/5.2
+source code and making the initial contact with the Info-ZIP group.
+
+And of course, many, many thanks to the Info-ZIP workers for making
+this code freely available.
+
+Note 1
+------
+
+The 'C' language FAQ ('frequently asked questions' [comp.lang.c])
+notes on the matter of obtaining the load file name of a 'C' program:
+
+16.5:   How can my program discover the complete pathname to the
+        executable file from which it was invoked?
+
+A:      argv[0] may contain all or part of the pathname, or it may
+        contain nothing.  You may be able to duplicate the command
+        language interpreter's search path logic to locate the
+        executable if the name in argv[0] is present but incomplete.
+        However, there is no guaranteed or portable solution.
+                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Note 2
+------
+
+NUL files for SMS2. There appears to be a conflict between SMS2/LBASIC
+compiled programs and c68 programs using nul as stdin.
+
+        EW zip,nul;'ram1_test *_bas'    # will not work
+
+                                        # This does work !
+        EW zip,#FOP_IN('nul');'ram2_test *_bas' : CLOSE
+
+Note 3
+------
+
+version number incremented to 2.0.1a and 5.12a to accomodate Erling
+Jacobsen's exit message requirements
+
+version number incremented to Zip 2.0.1b to fix bug on zipping files
+starting with leading underscore.
+
+version number incremented to UnZip 5.12b to fix UnZip problem on
+files zipped with leading './', and linked with revised (fixed) c68
+'utime' function (could corrupt level 1 files). (source code _only_ as
+IZQ004.zip).
+
+Ported Zip 2.1 and UnZip 5.2 (July 1996). Released as INZIP005.zip
+
+All later versions --- see Info-ZIP release notes and documentation.
diff --git a/qdos/Makefile.qdos b/qdos/Makefile.qdos
new file mode 100644 (file)
index 0000000..1028273
--- /dev/null
@@ -0,0 +1,143 @@
+include /etc/ql.mak
+
+# Makefile for Zip, ZipNote, ZipCloak and ZipSplit
+
+MAKE = make
+SHELL = /bin/sh
+
+#
+BIND = $(CC)
+
+# probably can change this to 'install' if you have it
+INSTALL = cp
+
+# target directories - where to install executables and man pages to
+BINDIR =
+manext=1
+MANDIR =
+ZIPMANUAL = MANUAL
+
+# flags
+#   CFLAGS    flags for C compile
+#   LFLAGS1   flags after output file spec, before obj file list
+#   LFLAGS2   flags after obj file list (libraries, etc)
+CFLAGS = -O -DASMV -DASM_CRC
+LFLAGS1 = -v
+#LFLAGS2 = -lutime
+
+all: zip
+
+# object file lists
+OBJZ = zip.o zipfile.o zipup.o fileio.o util.o globals.o crypt.o qdos.o ttyio.o
+OBJI = deflate.o trees.o qfileio.o crctab.o
+OBJA = config.o crc68.o match.o
+#  crc32.o
+OBJQ = qdos_.o config.o qfileio_.o
+OBJU = zipfile_.o zipup_.o fileio_.o util_.o globals.o $(OBJQ)
+OBJN = zipnote.o  $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt_.o
+OBJS = zipsplit.o $(OBJU)
+
+
+# suffix rules
+.SUFFIXES:
+.SUFFIXES: _.o .o .c .doc .1
+.c_.o:
+       rm -f $*_.c; ln $< $*_.c
+       $(CC) $(CFLAGS) -DUTIL -c $*_.c
+       rm -f $*_.c
+.c.o:
+       $(CC) $(CFLAGS) -c $<
+
+.1.doc:
+       nroff -man $< | col -b | uniq > $@
+
+# rules for zip, zipnote, zipcloak, zipsplit, and zip.doc.
+$(OBJZ): zip.h ziperr.h tailor.h
+$(OBJI): zip.h ziperr.h tailor.h
+$(OBJN): zip.h ziperr.h tailor.h
+$(OBJS): zip.h ziperr.h tailor.h
+$(OBJC): zip.h ziperr.h tailor.h
+zip.o zipup.o crypt.o zipup_.o zipcloak.o crypt_.o:  crypt.h
+
+qfileio.o: qdos/qfileio.c
+       cp qdos/qfileio.c qfileio.c
+       $(CC) $(CFLAGS) -c qfileio.c
+       rm -f qfileio.c
+
+qfileio_.o: qdos/qfileio.c
+       cp qdos/qfileio.c qfileio_.c
+       $(CC) $(CFLAGS) -DUTIL -c qfileio_.c
+       rm -f qfileio_.c
+
+match.o: qdos/match.s
+       cp qdos/match.s ./_match.s
+       $(AS) _match.s -o match.o
+       rm -f _match.s
+
+crc68.o: qdos/crc68.s
+       cp qdos/crc68.s ./crc68.s
+       $(AS) crc68.s -o crc68.o
+       rm -f crc68.s
+
+config.o: qdos/config.s
+       cp qdos/config.s ./config.x
+       $(CC) -c -DZIP config.x -o config.o
+       rm -f config.x
+
+ZIPS = zip$E zipnote$E zipsplit$E zipcloak$E
+
+zip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h
+zips: $(ZIPS)
+zipsman: $(ZIPS) $(ZIPMANUAL)
+
+qdos.o:   qdos/qdos.c
+       cp qdos/qdos.c .
+       $(CC) -c -oqdos.o qdos.c
+       rm -f qdos.c
+
+qdos_.o:  qdos/qdos.c
+       cp qdos/qdos.c ./qdos_.c
+       $(CC) -DUTIL -c -oqdos_.o qdos_.c
+       rm -f qdos_.c
+
+zip$E: $(OBJZ) $(OBJI) $(OBJA)
+       $(BIND) -o zip$E $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)
+zipnote$E: $(OBJN)
+       $(BIND) -o zipnote$E $(LFLAGS1) $(OBJN) $(LFLAGS2)
+zipcloak$E: $(OBJC)
+       $(BIND) -o zipcloak$E $(LFLAGS1) $(OBJC) $(LFLAGS2)
+zipsplit$E: $(OBJS)
+       $(BIND) -o zipsplit$E $(LFLAGS1) $(OBJS) $(LFLAGS2)
+
+$(ZIPMANUAL): man/zip.1
+       nroff -man man/zip.1 | col -b | uniq > $(ZIPMANUAL)
+
+# install
+install:        $(ZIPS)
+       $(INSTALL) $(ZIPS) $(BINDIR)
+       $(INSTALL) man/zip.1 $(MANDIR)/zip.$(manext)
+
+uninstall:
+       -cd $(BINDIR); rm -f $(ZIPS)
+       -cd $(MANDIR); rm -f zip.$(manext)
+
+flags:  configure
+       sh configure flags
+
+# These symbols, when #defined using -D have these effects on compilation:
+# ZMEM          - includes C language versions of memset(), memcpy(), and
+#                 memcmp() (util.c).
+# SYSV          - use <sys/dirent.h> and the library opendir()
+# DIRENT        - use <sys/dirent.h> and getdents() instead of <sys/dir.h>
+#                 and opendir(), etc. (fileio.c).
+# NODIR         - used for 3B1, which has neither getdents() nor opendir().
+# NDIR          - use "ndir.h" instead of <sys/dir.h> (fileio.c).
+# UTIL          - select routines for utilities (note, cloak, and split).
+# PROTO         - enable function prototypes.
+# RMDIR         - remove directories using a system("rmdir ...") call.
+# CONVEX        - for Convex make target.
+# AIX           - for AIX make target.
+# LINUX         - for linux make target.
+
+# end of Makefile
diff --git a/qdos/Makefile.qlzip b/qdos/Makefile.qlzip
new file mode 100644 (file)
index 0000000..e12f004
--- /dev/null
@@ -0,0 +1,139 @@
+# Makefile for Zip, ZipNote, ZipCloak and ZipSplit
+
+# what you can make ...
+all: zip
+
+#MAKE = make -f unix/Makefile
+SHELL = /bin/sh
+
+# (to use the Gnu compiler, change cc to gcc in CC and BIND)
+CC = cc
+BIND = $(CC)
+AS = $(CC) -c
+E =
+CPP = /lib/cpp
+
+# probably can change this to 'install' if you have it
+INSTALL = cp
+
+# target directories - where to install executables and man pages to
+prefix = /usr/local
+BINDIR = $(prefix)/bin
+manext=1
+MANDIR = $(prefix)/man/man$(manext)
+ZIPMANUAL = MANUAL
+
+# flags
+#   CFLAGS    flags for C compile
+#   LFLAGS1   flags after output file spec, before obj file list
+#   LFLAGS2   flags after obj file list (libraries, etc)
+CFLAGS = -O2 -fno-strength-reduce -I. -DUNIX -DQLZIP -DASM_CRC
+LFLAGS1 =
+LFLAGS2 = -s
+
+# object file lists
+OBJZ = zip.o zipfile.o zipup.o fileio.o util.o globals.o crypt.o ttyio.o \
+       unix.o crc_gcc.o crctab.o qdos.o
+OBJI = deflate.o trees.o
+OBJA =
+OBJU = zipfile_.o fileio_.o util_.o globals.o unix_.o
+OBJN = zipnote.o  $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt_.o ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h unix/osdep.h
+
+# suffix rules
+.SUFFIXES:
+.SUFFIXES: _.o .o .c .doc .1
+.c_.o:
+       rm -f $*_.c; ln $< $*_.c
+       $(CC) -c $(CFLAGS) -DUTIL $*_.c
+       rm -f $*_.c
+.c.o:
+       $(CC) -c $(CFLAGS) $<
+
+.1.doc:
+       nroff -man $< | col -b | uniq > $@
+
+# rules for zip, zipnote, zipcloak, zipsplit, and the Zip MANUAL.
+$(OBJZ): $(ZIP_H)
+$(OBJI): $(ZIP_H)
+$(OBJN): $(ZIP_H)
+$(OBJS): $(ZIP_H)
+$(OBJC): $(ZIP_H)
+zip.o zipup.o crypt.o ttyio.o zipcloak.o crypt_.o: crypt.h
+zip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h
+zip.o crypt.o ttyio.o zipcloak.o crypt_.o: ttyio.h
+zipup.o: unix/zipup.h
+
+match.o: match.S
+       $(CPP) match.S > _match.s
+       $(AS) _match.s
+       mv _match.o match.o
+       rm -f _match.s
+
+unix.o: unix/unix.c
+       $(CC) -c $(CFLAGS) unix/unix.c
+
+unix_.o: unix/unix.c
+       rm -f $*_.c; ln unix/unix.c $*_.c
+       $(CC) -c $(CFLAGS) -DUTIL $*_.c
+       rm -f $*_.c
+
+qdos.o: qdos/qdos.c
+       $(CC) -c $(CFLAGS) qdos/qdos.c
+
+crc_gcc.o: crc_i386.S                  # 32bit, GNU AS
+       gcc -O3 -I. -DASM_CRC -Di386 -x assembler-with-cpp -c -o $@ crc_i386.S
+
+ZIPS = zip$E zipnote$E zipsplit$E zipcloak$E
+
+zips: $(ZIPS)
+zipsman: $(ZIPS) $(ZIPMANUAL)
+
+zip$E: $(OBJZ) $(OBJI) $(OBJA)
+       $(BIND) -o qlzip$E $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)
+zipnote$E: $(OBJN)
+       $(BIND) -o zipnote$E $(LFLAGS1) $(OBJN) $(LFLAGS2)
+zipcloak$E: $(OBJC)
+       $(BIND) -o zipcloak$E $(LFLAGS1) $(OBJC) $(LFLAGS2)
+zipsplit$E: $(OBJS)
+       $(BIND) -o zipsplit$E $(LFLAGS1) $(OBJS) $(LFLAGS2)
+
+$(ZIPMANUAL): man/zip.1
+       nroff -man man/zip.1 | col -b | uniq > $(ZIPMANUAL)
+
+# install
+install:        $(ZIPS)
+       $(INSTALL) $(ZIPS) $(BINDIR)
+       $(INSTALL) man/zip.1 $(MANDIR)/zip.$(manext)
+
+uninstall:
+       -cd $(BINDIR); rm -f $(ZIPS)
+       -cd $(MANDIR); rm -f zip.$(manext)
+
+dist:
+       zip -u9T zip`sed -e '/VERSION/!d' -e 's/.*"\(.*\)".*/\1/' \
+                         -e s/[.]//g -e q revision.h` \
+         `awk '/^Makefile/,/vms_zip.rnh/ {print $$1}' < contents`
+
+flags:  unix/configure
+       sh unix/configure "${CC}" "${CFLAGS}"
+
+# These symbols, when #defined using -D have these effects on compilation:
+# ZMEM                  - includes C language versions of memset(), memcpy(),
+#                         and memcmp() (util.c).
+# HAVE_DIRENT_H         - use <dirent.h> instead of <sys/dir.h>
+# NODIR                 - for 3B1, which has neither getdents() nor opendir().
+# HAVE_NDIR_H           - use <ndir.h> (unix/unix.c).
+# HAVE_SYS_DIR_H        - use <sys/dir.h>
+# HAVE_SYS_NDIR_H       - use <sys/ndir.h>
+# UTIL                  - select routines for utilities (note, cloak, split)
+# NO_RMDIR              - remove directories using a system("rmdir ...") call.
+# NO_PROTO              - cannot handle ANSI prototypes
+# NO_CONST              - cannot handle ANSI const
+
+#               Generic targets:
+
+# end of Makefile
diff --git a/qdos/config.s b/qdos/config.s
new file mode 100644 (file)
index 0000000..56a2a85
--- /dev/null
@@ -0,0 +1,153 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+#
+.globl _qlflag
+.globl _qlwait
+#ifdef ZIP
+.globl _dtype
+#endif
+
+.data
+        ds.w    0
+        dc.b    '<<QCFX>>01'
+#ifdef ZIP
+        dc.w    8
+        dc.b    'Info-ZIP'
+*                12345678901234567890
+        ds.w    0
+        dc.w    4
+        dc.b    'qdos'
+        ds.w    0
+#else
+        dc.w    10
+        dc.b    'Info-UNZIP'
+*                12345678901234567890
+        ds.w    0
+        dc.w    4
+        dc.b    'qdos'
+        ds.w    0
+#endif
+        dc.b    10
+        dc.b    0
+l_4:    dc.w    _qlwait-l_4
+        dc.w    0
+        dc.w    0
+l_5:    dc.w    hpt-l_5
+l_6:    dc.w    hxx-l_6
+
+#ifdef ZIP
+        dc.b    10
+        dc.b    0
+d_4:    dc.w    _dtype-d_4
+        dc.w    0
+        dc.w    0
+d_5:    dc.w    dpt-d_5
+d_6:    dc.w    dxx-d_6
+
+#else
+        dc.b    4
+        dc.b    0
+l5:
+        dc.w    list1-l5
+        dc.w    0
+l5a:
+        dc.w    Postit-l5a              ; post proc
+l6:
+        dc.w    apt-l6
+l7:
+        dc.w    axx-l7
+* -------------------------------------
+        dc.b    4
+        dc.b    0
+l8:
+        dc.w    list2-l8
+        dc.w    0
+l8a:
+        dc.w    Postit-l8a              ; post proc
+l9:
+        dc.w    bpt-l9
+la:
+        dc.w    bxx-la
+* -------------------------------------
+#endif
+        dc.w    -1                          ; end
+
+_qlflag:
+        dc.w    0
+_qlwait:
+        dc.w    250
+_dtype:
+        dc.w    255
+
+hpt:    dc.w    10
+        dc.b    'Exit Delay'
+*                12345678901234567890
+        ds.w    0
+hxx:    dc.w    0
+        dc.w    $ffff
+        dc.w    -1
+#ifdef  ZIP
+dpt:    dc.w    14
+        dc.b    'Directory Type'
+*                12345678901234567890
+        ds.w    0
+dxx:    dc.w    3
+        dc.w    $ff
+        dc.w    -1
+#else
+
+list1:
+        dc.b    0
+list2:
+        dc.b    0
+
+apt:
+        dc.w    11
+        dc.b    'Unpack Mode'
+*                12345678901234567890
+.even
+axx:    dc.b    0
+        dc.b    0
+        dc.w    8
+        dc.b    'SMS/QDOS'
+.even
+        dc.b    1
+        dc.b    0
+        dc.w    7
+        dc.b    'Default'
+.even
+        dc.w    -1
+.even
+bpt:
+        dc.w    12
+        dc.b    'Listing Mode'
+*                12345678901234567890
+.even
+bxx:
+        dc.w    0
+        dc.w    7
+        dc.b    'Default'
+.even
+        dc.b    2
+        dc.b    0
+        dc.w    8
+        dc.b    'SMS/QDOS'
+*                12345678901234567890
+.even
+         dc.w    -1
+Postit:
+        lea.l   _qlflag,a0
+        move.b  list1,d0
+        move.b  d0,(a0)
+        move.b  list2,d0
+        or.b    d0,(a0)
+        moveq   #0,d0
+        rts
+#endif
+        end
diff --git a/qdos/crc68.s b/qdos/crc68.s
new file mode 100644 (file)
index 0000000..cf74e47
--- /dev/null
@@ -0,0 +1,99 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+.text
+
+.globl  _crc32          ; (ulg val, uch *buf, extent bufsize)
+.globl  _get_crc_table  ; ulg *get_crc_table(void)
+
+_crc32:
+        move.l  8(sp),d0
+        bne    valid
+        moveq  #0,d0
+        rts
+valid:  movem.l d2/d3,-(sp)
+        jsr     _get_crc_table
+        move.l  d0,a0
+        move.l  12(sp),d0
+        move.l  16(sp),a1
+        move.l  20(sp),d1
+        not.l   d0
+
+        move.l  d1,d2
+        lsr.l   #3,d1
+        bra     decr8
+loop8:  moveq  #0,d3
+        move.b (a1)+,d3
+        eor.b  d0,d3
+        lsl.w  #2,d3
+        move.l 0(a0,d3.w),d3
+        lsr.l  #8,d0
+        eor.l  d3,d0
+        moveq  #0,d3
+        move.b (a1)+,d3
+        eor.b  d0,d3
+        lsl.w  #2,d3
+        move.l 0(a0,d3.w),d3
+        lsr.l  #8,d0
+        eor.l  d3,d0
+        moveq  #0,d3
+        move.b (a1)+,d3
+        eor.b  d0,d3
+        lsl.w  #2,d3
+        move.l 0(a0,d3.w),d3
+        lsr.l  #8,d0
+        eor.l  d3,d0
+        moveq  #0,d3
+        move.b (a1)+,d3
+        eor.b  d0,d3
+        lsl.w  #2,d3
+        move.l 0(a0,d3.w),d3
+        lsr.l  #8,d0
+        eor.l  d3,d0
+        moveq  #0,d3
+        move.b (a1)+,d3
+        eor.b  d0,d3
+        lsl.w  #2,d3
+        move.l 0(a0,d3.w),d3
+        lsr.l  #8,d0
+        eor.l  d3,d0
+        moveq  #0,d3
+        move.b (a1)+,d3
+        eor.b  d0,d3
+        lsl.w  #2,d3
+        move.l 0(a0,d3.w),d3
+        lsr.l  #8,d0
+        eor.l  d3,d0
+        moveq  #0,d3
+        move.b (a1)+,d3
+        eor.b  d0,d3
+        lsl.w  #2,d3
+        move.l 0(a0,d3.w),d3
+        lsr.l  #8,d0
+        eor.l  d3,d0
+        moveq  #0,d3
+        move.b (a1)+,d3
+        eor.b  d0,d3
+        lsl.w  #2,d3
+        move.l 0(a0,d3.w),d3
+        lsr.l  #8,d0
+        eor.l  d3,d0
+decr8:  dbra   d1,loop8
+        and.w   #7,d2
+        bra     decr1
+loop1:  moveq  #0,d3
+        move.b (a1)+,d3
+        eor.b  d0,d3
+        lsl.w  #2,d3
+        move.l 0(a0,d3.w),d3
+        lsr.l  #8,d0
+        eor.l  d3,d0
+decr1:  dbra   d2,loop1
+done:   movem.l (sp)+,d2/d3
+        not.l   d0
+        rts
diff --git a/qdos/match.s b/qdos/match.s
new file mode 100644 (file)
index 0000000..53b3013
--- /dev/null
@@ -0,0 +1,138 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; match.a -- optional optimized asm version of longest match in deflate.c
+; Written by Jean-loup Gailly
+;
+; Adapted for the Amiga by Carsten Steger <stegerc@informatik.tu-muenchen.de>
+; using the code in match.S.
+; The major change in this code consists of removing all unaligned
+; word accesses, because they cause 68000-based Amigas to crash.
+; For maximum speed, UNALIGNED_OK can be defined in Makefile.sasc.
+; The program will then only run on 68020-based Amigas, though.
+;
+; This code will run with registerized parameters too, unless SAS
+; changes parameter passing conventions between new releases of SAS/C.
+
+
+;;Cur_Match      equr     d0      ; Must be in d0!
+;;Best_Len       equr     d1
+;;Loop_Counter   equr     d2
+;;Scan_Start     equr     d3
+;;Scan_End       equr     d4
+;;Limit          equr     d5
+;;Chain_Length   equr     d6
+;;Scan_Test      equr     d7
+;;Scan           equr     a0
+;;Match          equr     a1
+;;Prev_Address   equr     a2
+;;Scan_Ini       equr     a3
+;;Match_Ini      equr     a4
+
+MAX_MATCH       equ     258
+MIN_MATCH       equ     3
+WSIZE           equ     32768
+MAX_DIST        equ     WSIZE-MAX_MATCH-MIN_MATCH-1
+
+
+        .globl    _max_chain_length
+        .globl    _prev_length
+        .globl    _prev
+        .globl    _window
+        .globl    _strstart
+        .globl    _good_match
+        .globl    _match_start
+        .globl    _nice_match
+
+        .text
+        .globl   _match_init
+        .globl   _longest_match
+
+_match_init:
+        rts
+
+
+_longest_match:
+        move.l  4(sp),d0
+        movem.l d2-d7/a2-a4,-(sp)
+        move.l  _max_chain_length,d6
+        move.l  _prev_length,d1
+        lea     _prev,a2
+        lea     _window+MIN_MATCH,a4
+        move.l  _strstart,d5
+        move.l  a4,a3
+        add.l   d5,a3
+        subi.w  #MAX_DIST,d5
+        bhi     limit_ok
+        moveq   #0,d5
+limit_ok:
+        cmp.l   _good_match,d1
+        bcs     length_ok
+        lsr.l   #2,d6
+length_ok:
+        subq.l  #1,d6
+
+        move.b  -MIN_MATCH(a3),d3
+        lsl.w   #8,d3
+        move.b  -MIN_MATCH+1(a3),d3
+        move.b  -MIN_MATCH-1(a3,d1),d4
+        lsl.w   #8,d4
+        move.b  -MIN_MATCH(a3,d1),d4
+
+        bra     do_scan
+
+long_loop:
+
+        move.b  -MIN_MATCH-1(a3,d1),d4
+        lsl.w   #8,d4
+        move.b  -MIN_MATCH(a3,d1),d4
+
+short_loop:
+        lsl.w   #1,d0
+        move.w  0(a2,d0.l),d0
+        cmp.w   d5,d0
+        dbls    d6,do_scan
+        bra     return
+
+do_scan:
+        move.l  a4,a1
+        add.l   d0,a1
+
+        move.b  -MIN_MATCH-1(a1,d1),d7
+        lsl.w   #8,d7
+        move.b  -MIN_MATCH(a1,d1),d7
+        cmp.w   d7,d4
+        bne     short_loop
+        move.b  -MIN_MATCH(a1),d7
+        lsl.w   #8,d7
+        move.b  -MIN_MATCH+1(a1),d7
+        cmp.w   d7,d3
+        bne     short_loop
+
+        move.w  #(MAX_MATCH-MIN_MATCH),d2
+        move.l  a3,a0
+
+scan_loop:
+        cmpm.b  (a1)+,(a0)+
+        dbne    d2,scan_loop
+
+        sub.l   a3,a0
+        addq.l  #(MIN_MATCH-1),a0
+        cmp.l   d1,a0
+        bls     short_loop
+        move.l  a0,d1
+        move.l  d0,_match_start
+        cmp.l   _nice_match,d1
+        bcs     long_loop
+return:
+        move.l  d1,d0
+        movem.l (sp)+,d2-d7/a2-a4
+        rts
+        end
+
+
diff --git a/qdos/osdep.h b/qdos/osdep.h
new file mode 100644 (file)
index 0000000..72169c1
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef _QDOS_OPDEP
+#define _QDOS_OPDEP
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <ctype.h>
+
+char * ql2Unix(char *);
+char * Unix2ql(char *, char **);
+int wild (char *);
+char *LastDir(char *);
+void QDOSexit(void);
+short devlen(char *);
+
+/*
+ * XXX NO_RENAME instead of the following define ?
+ */
+#define link rename
+#define USE_CASE_MAP
+#define USE_EF_UT_TIME
+#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \
+                     procname(n, 1))
+#endif
diff --git a/qdos/qdos.c b/qdos/qdos.c
new file mode 100644 (file)
index 0000000..f07f56e
--- /dev/null
@@ -0,0 +1,877 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ * Yes this  file is necessary; the QDOS file system is the most
+ * ludicrous known to man (even more so than VMS!).
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include "zip.h"
+#include "crypt.h"
+#include "ttyio.h"
+
+#ifdef QDOS
+
+# include <qdos.h>
+
+#if CRYPT
+
+char *getp(m, p, n)
+    ZCONST char *m;              /* prompt for password */
+    char *p;                    /* return value: line input */
+    int n;                      /* bytes available in p[] */
+{
+    int c;                      /* one-byte buffer for read() to use */
+    int i;                      /* number of characters input */
+    char *w;                    /* warning on retry */
+
+    /* get password */
+    w = "";
+    sd_cure(getchid(0), -1);    /* enable cursor */
+    do {
+        fputs(w, stderr);       /* warning if back again */
+        fputs(m, stderr);       /* display prompt and flush */
+        fflush(stderr);
+        i = 0;
+        do {
+            c = getch();
+            if (c == 0xc2) {
+                if (i > 0) {
+                    i--; /* the `del' keys works */
+                    fputs("\b \b", stderr);
+                }
+            }
+            else if (i < n) {
+                p[i++] = c;     /* truncate past n */
+                if(c != '\n') putc('*', stderr);
+            }
+        } while (c != '\n');
+
+        putc('\n', stderr);  fflush(stderr);
+        w = "(line too long--try again)\n";
+    } while (p[i-1] != '\n');
+
+    p[i-1] = 0;                 /* terminate at newline */
+    sd_curs(getchid(0), -1);    /* suppress cursor */
+    return p;                   /* return pointer to password */
+
+} /* end function getp() */
+
+#endif /* CRYPT */
+
+
+#define __attribute__(p)
+
+int newname(char *, int, int);
+
+#else /* !QDOS */
+#define QDOS_FLMAX 36
+
+short qlflag = 0;
+
+struct qdirect  {
+    long            d_length __attribute__ ((packed));  /* file length */
+    unsigned char   d_access __attribute__ ((packed));  /* file access type */
+    unsigned char   d_type __attribute__ ((packed));    /* file type */
+    long            d_datalen __attribute__ ((packed)); /* data length */
+    long            d_reserved __attribute__ ((packed));/* Unused */
+    short           d_szname __attribute__ ((packed));  /* size of name */
+    char            d_name[QDOS_FLMAX] __attribute__ ((packed));/* name area */
+    long            d_update __attribute__ ((packed));  /* last update */
+    long            d_refdate __attribute__ ((packed));
+    long            d_backup __attribute__ ((packed));   /* EOD */
+    } ;
+#endif /* ?QDOS */
+
+#define SHORTID 0x4afb          /* in big-endian order !! */
+#define LONGID  "QDOS02"
+#define EXTRALEN (sizeof(struct qdirect) + 8)
+
+typedef struct
+{
+    unsigned short shortid __attribute__ ((packed));
+    struct
+    {
+        unsigned char lo __attribute__ ((packed));
+        unsigned char hi __attribute__ ((packed));
+    } len __attribute__ ((packed));
+    char        longid[8] __attribute__ ((packed));
+    struct      qdirect     header __attribute__ ((packed));
+} qdosextra;
+
+#ifdef USE_EF_UT_TIME
+local int GetExtraTime(struct zlist far *z, iztimes *z_utim, unsigned ut_flg);
+#endif
+
+#ifdef QDOS
+
+#define rev_short(x) (x)
+#define rev_long(x) (x)
+
+char _prog_name[] = "zip";
+char _copyright[] = "(c) Info-ZIP Group";
+long _stack = 16*1024;
+char *  _endmsg = NULL;
+
+extern void consetup_title(chanid_t,struct WINDOWDEF *);
+void (*_consetup)(chanid_t,struct WINDOWDEF *) = consetup_title;
+
+struct WINDOWDEF _condetails =
+{
+    2,
+    1,
+    0,
+    7,
+    500,
+    220,
+    2,
+    30
+};
+
+extern short qlwait;
+extern short dtype;
+
+#define CHECKDIR(p1) (((p1).d_type == dtype) && (((p1).d_length % 64) == 0))
+
+char * stpcpy (char *d, ZCONST char *s)
+{
+    while(*d++ = *s++)
+        ; /* Null loop */
+    return d-1;
+}
+
+static jobid_t chowner(chanid_t chan)
+{
+    extern char *_sys_var;
+    char *scht;
+    long *cdb;
+    long jid;
+
+    scht = *((char **)(_sys_var + 0x78));
+    cdb = *(long **)((long *)scht  + (chan & 0xffff));
+    jid = *(cdb + 2);
+    return jid;
+}
+
+void QDOSexit(void)
+{
+    jobid_t me,you;
+
+    me = getpid();
+    you = chowner(getchid(0));
+
+    if((me == you) && ((qlflag & 4) == 0))
+    {
+        if(isatty(0) && isatty(2) && qlwait)
+        {
+            char c = 0;
+            fputs("Press a key to exit", stderr);
+            if((io_fbyte(getchid(0), qlwait, &c) == 0) && c == 27)
+            {
+                io_fbyte(getchid(0), -1, &c);
+            }
+        }
+    }
+    exit(0);
+}
+
+/* Access seems to be *always* broken in c68 */
+/* Not accurate, just works */
+
+int access (char *f, int mode)
+{
+    struct stat st;
+    int fd;
+
+    if((fd = stat(f, &st)) == 0)
+    {
+        switch(fd)
+        {
+        case F_OK:
+            break;
+        case R_OK:
+            fd = (st.st_mode & 0444) == 0;
+            break;
+        case W_OK:
+            fd = (st.st_mode & 0222) == 0;
+            break;
+        case X_OK:
+            fd = (st.st_mode & 0111) == 0;
+            break;
+        default:
+            fd = -1;
+            break;
+        }
+    }
+    return fd;
+}
+
+/* Fixup a Mickey Mouse file naming system */
+
+char * Unix2ql (char *qlname, char **dot)
+{
+    static char path[64];
+    char name[64];
+    char *q, *r, *s;
+
+    strcpy(name, qlname);
+    if(*name == '~')
+    {
+        r = name+1;
+        getcwd(path, sizeof(path));
+        q = path + strlen(path);
+        if(*(q-1) != '_')
+        {
+            *q++ = '_';
+        }
+    }
+    else
+    {
+        q = path;
+        r = name;
+    }
+
+    if(*r == '/')
+    {
+        r++;
+    }
+
+    strcpy(q, r);
+
+    while (*q)
+    {
+        if(*q == '/' || *q == '.')
+        {
+            if(*q == '.' && dot)
+            {
+                *dot = name + (q - path);
+            }
+            *q = '_';
+        }
+
+        q++;
+    }
+    return path;
+}
+
+#if 0                                 /* Not used in ZIP */
+
+GuessAltName(char *name, char *dot)
+{
+    if(dot)
+    {
+        *dot = '.';
+    }
+    else
+    {
+        if((dot = strrchr(name, '_')))
+        {
+            *dot = '.';
+        }
+    }
+}
+
+#endif /* 0 */
+
+short devlen(char *p)
+{
+    char defpath[40];
+    short deflen = 0, ok = 0;
+
+    getcwd(defpath, sizeof(defpath));
+    deflen = strlen(defpath);
+    if(deflen)
+    {
+        if(strnicmp(p, defpath, deflen) == 0)
+        {
+            ok = 1;
+        }
+    }
+
+    if(!ok)
+    {
+        if(isdirdev(p))
+        {
+            deflen = 5;
+        }
+        else
+        {
+            deflen = 0;
+        }
+    }
+    return deflen;
+}
+
+char * ql2Unix (char *qlname)
+{
+    struct stat st;
+    int sts;
+    char *p, *r, *s, *ldp;
+    char *pnam = NULL;
+    static char path[64];
+    short  deflen;
+    char name[64];
+
+    strcpy(name, qlname);
+    strcpy(path, name);
+
+    deflen = devlen(qlname);
+
+    p = name + deflen;
+    pnam = path + deflen;
+
+    if(s = strrchr(p, '_'))
+    {
+        *s = 0;
+        sts = stat(name, &st);
+        if(deflen && sts ==0 && (st.st_mode & S_IFDIR))
+        {
+            *(path+(s-name)) = '/';
+        }
+        else
+        {
+            *(path+(s-name)) = '.';
+        }
+    }
+
+    ldp = p;
+    for(r = p; *r; r++)
+    {
+        if(r != ldp && *r == '_')
+        {
+            *r = 0;
+            if(deflen)
+            {
+                sts = stat(name, &st);
+            }
+            else
+                sts = -1;
+
+            if(sts ==0 && (st.st_mode & S_IFDIR))
+            {
+                *(path+(r-name)) = '/';
+                ldp = r + 1;
+            }
+            else
+            {
+                *(path+(r-name)) = '_';
+            }
+            *r = '_';
+        }
+    }
+    return pnam;
+}
+
+char *LastDir(char *ws)
+{
+    char *p;
+    char *q = ws;
+    struct stat s;
+
+    for(p = ws; *p; p++)
+    {
+        if(p != ws && *p == '_')
+        {
+            char c;
+
+            p++;
+            c = *p;
+            *p = 0;
+            if(stat(ws, &s) == 0 && S_ISDIR(s.st_mode))
+            {
+                q = p;
+            }
+            *p = c;
+        }
+    }
+    return q;
+}
+
+# ifndef UTIL
+
+static int add_dir(char * dnam)
+{
+    int e = ZE_OK;
+    char *p;
+    short nlen;
+
+    nlen = strlen(dnam);
+    if(p = malloc(nlen + 2))
+    {
+        strncpy (p, dnam, nlen);
+        if(*(p+nlen) != '_')
+        {
+            *(p+nlen) = '_';
+            *(p+nlen+1) = '\0';
+        }
+        if ((e = newname(p, 1, 0)) != ZE_OK)
+        {
+                free(p);
+        }
+    }
+    else
+    {
+        e = ZE_MEM;
+    }
+    return e;
+}
+
+int qlwild (char *dnam, short dorecurse, short l)
+{
+    static char match[40] = {0};
+    static char ddev[8] =  {0};
+    static short nc;
+    static short llen;
+    static char base[40];
+
+    int chid;
+    struct qdirect qd;
+    char *dp;
+    int e = ZE_MISS;
+
+    if (l == 0)
+    {
+        nc = 0;
+        *base = '\0';
+        if (isdirdev (dnam))
+        {
+            dp = dnam;
+            strncpy (ddev, dnam, 5);
+        }
+        else
+        {
+
+            char *p;
+            char temp[40];
+
+            getcwd (temp, 40);
+
+            llen = strlen(temp);
+            p = (temp + llen - 1);
+            if (*p != '_')
+            {
+                *p++ = '_';
+                *p = 0;
+            }
+
+            strncpy (ddev, temp, 5);
+            dp = base;
+            p = stpcpy (dp, temp);
+            strcpy (p, dnam);
+        }
+
+        {
+            char *q = isshexp (dp);
+            if(q)
+            {
+                strcpy (match, dp + 5);
+                if (q)
+                {
+                    while (q != dp && *q != '_')
+                    {
+                        q--;
+                    }
+                    *(++q) = '\0';
+                }
+            }
+            else
+            {
+                struct stat s;
+                if (stat(dp, &s) == 0)
+                {
+                    if (!(s.st_mode & S_IFDIR))
+                    {
+                        return procname(dp, 0);
+                    }
+                }
+                else
+                {
+                    return ZE_MISS;  /* woops, no wildcards! */
+                }
+            }
+
+        }
+    }
+    else
+    {
+        dp = dnam;
+    }
+
+    if ((chid = io_open (dp, 4L)) > 0)
+    {
+        int id = 0;
+        while (io_fstrg (chid, -1, &qd, 64) > 0)
+        {
+            short j;
+
+            if (qd.d_szname)
+            {
+                if (CHECKDIR(qd))
+                {
+                    if(dorecurse)
+                    {
+                        char fnam[256], *p;
+
+                        p = stpcpy (fnam, ddev);
+                        strncpy (p, qd.d_name, qd.d_szname);
+                        *(p + qd.d_szname) = 0;
+                        e = qlwild (fnam, dorecurse, l+1);
+                    }
+                    else
+                    {
+                        continue;
+                    }
+                }
+                else
+                {
+                    char nam[48];
+                    strcpy(nam, ddev);
+
+                    strncpy (nam + 5, qd.d_name, qd.d_szname);
+                    *(nam + 5 + qd.d_szname) = 0;
+
+                    if (MATCH (match, nam + 5, 0) == 1)
+                    {
+                        if(dirnames && l && id == 0)
+                        {
+                            id = 1;
+                            if((e = add_dir(dp)) != ZE_OK)
+                            {
+                                return e;
+                            }
+                        }
+
+                        if((e = procname(nam, 0)) == ZE_OK)
+                        {
+                            nc++;
+                        }
+                    }
+                }
+            }
+        }
+        io_close (chid);
+    }
+
+    if (l == 0)
+    {
+        *ddev = 0;
+        *match = 0;
+        e = (nc) ? ZE_OK : ZE_MISS;
+    }
+    return e;
+
+}
+
+int wild(char *p)
+{
+    return qlwild(p, recurse, 0);
+}
+# endif /* !UTIL */
+
+/*
+ * Return QDOS error, 0 if exec 1 if found but not exe or rel
+ */
+int qlstat(char *name, struct qdirect *qs, char *flag)
+{
+    int r;
+    r = qstat(name, qs);
+    if(r == 0)
+    {
+        if(qs->d_type == 0)
+        {
+            r = 1;
+        }
+        else if(CHECKDIR(*qs))
+        {
+            r = 255;
+        }
+    }
+    return r;
+}
+
+#else /* !QDOS */
+
+long rev_long (ulg l)
+{
+    uch cc[4];
+    cc[0] = (uch)(l >> 24);
+    cc[1] = (uch)((l >> 16) & 0xff);
+    cc[2] = (uch)((l >> 8) & 0xff);
+    cc[3] = (uch)(l & 0xff);
+    return *(ulg *)cc;
+}
+
+short rev_short (ush s)
+{
+    uch cc[2];
+    cc[0] = (uch)((s >> 8) & 0xff);
+    cc[1] = (uch)(s & 0xff);
+    return *(ush *)cc;
+}
+
+#define O_BINARY 0
+
+int qlstat(char *name, struct qdirect *qs, char *flag)
+{
+    int r = -1;
+    int n, fd;
+    struct stat s;
+    struct _ntc_
+    {
+        long id;
+        long dlen;
+    } ntc;
+
+    *flag = 0;
+    if((fd = open(name, O_RDONLY | O_BINARY)) > 0)
+    {
+        short nl;
+
+        fstat(fd, &s);
+        lseek(fd, -8, SEEK_END);
+        read(fd, &ntc, 8);
+        qs->d_length = rev_long(s.st_size);
+        qs->d_update = rev_long(s.st_ctime + 283996800);
+
+        nl = strlen(name);
+        if(nl > QDOS_FLMAX)
+        {
+            nl = QDOS_FLMAX;
+            *flag = 1;
+        }
+        qs->d_szname = rev_short(nl);
+        memcpy(qs->d_name, name, nl);
+
+        if(ntc.id == *(long *)"XTcc")
+        {
+            qs->d_datalen = ntc.dlen;    /* This is big endian */
+            qs->d_type = 1;
+            r = 0;
+        }
+        else
+        {
+            qs->d_type = 0;
+            qs->d_datalen = 0;
+            r = 1;
+        }
+        close(fd);
+        return r;
+    }
+    else
+    {
+        fprintf(stderr, "Fails %d\n", fd);
+        return r;
+    }
+}
+
+#endif /* ?QDOS */
+
+#ifdef USE_EF_UT_TIME
+
+#define EB_L_UT_SIZE    (EB_HEADSIZE + eb_l_ut_len)
+#define EB_C_UT_SIZE    (EB_HEADSIZE + eb_c_ut_len)
+
+#ifdef UNIX
+#define EB_L_UX2_SIZE     (EB_HEADSIZE + EB_UX2_MINLEN)
+#define EB_C_UX2_SIZE     EB_HEADSIZE
+#define EF_L_UT_UX2_SIZE  (EB_L_UT_SIZE + EB_L_UX2_SIZE)
+#define EF_C_UT_UX2_SIZE  (EB_C_UT_SIZE + EB_C_UX2_SIZE)
+#else
+#define EF_L_UT_UX2_SIZE  EB_L_UT_SIZE
+#define EF_C_UT_UX2_SIZE  EB_C_UT_SIZE
+#endif
+
+local int GetExtraTime(struct zlist far *z, iztimes *z_utim, unsigned ut_flg)
+{
+  char *eb_l_ptr;
+  char *eb_c_ptr;
+  char *eb_pt;
+  extent eb_l_ut_len = 0;
+  extent eb_c_ut_len = 0;
+
+#ifdef UNIX
+  struct stat s;
+
+  /* For the full sized UT local field including the UID/GID fields, we
+   * have to stat the file, again.  */
+  if (stat(z->name, &s))
+    return ZE_OPEN;
+  /* update times in z_utim, stat() call might have changed atime... */
+  z_utim->mtime = s.st_mtime;
+  z_utim->atime = s.st_atime;
+  z_utim->ctime = s.st_mtime;   /* best guess (st_ctime != creation time) */
+#endif /* UNIX */
+
+#ifdef IZ_CHECK_TZ
+  if (!zp_tz_is_valid)
+    ut_flg = 0;          /* disable UT e.f creation if no valid TZ info */
+#endif
+  if (ut_flg != 0) {
+    if (ut_flg & EB_UT_FL_MTIME)
+      eb_l_ut_len = eb_c_ut_len = 1;
+    if (ut_flg & EB_UT_FL_ATIME)
+      eb_l_ut_len++;
+    if (ut_flg & EB_UT_FL_CTIME)
+      eb_l_ut_len++;
+
+    eb_l_ut_len = EB_UT_LEN(eb_l_ut_len);
+    eb_c_ut_len = EB_UT_LEN(eb_c_ut_len);
+  }
+
+  if (EF_L_UT_UX2_SIZE > EB_HEADSIZE) {
+    if(z->ext)
+      eb_l_ptr = realloc(z->extra, (z->ext + EF_L_UT_UX2_SIZE));
+    else
+      eb_l_ptr = malloc(EF_L_UT_UX2_SIZE);
+
+    if (eb_l_ptr == NULL)
+      return ZE_MEM;
+
+    if(z->cext)
+      eb_c_ptr = realloc(z->cextra, (z->cext + EF_C_UT_UX2_SIZE));
+    else
+      eb_c_ptr = malloc(EF_C_UT_UX2_SIZE);
+
+    if (eb_c_ptr == NULL)
+      return ZE_MEM;
+
+    z->extra = eb_l_ptr;
+    eb_l_ptr += z->ext;
+    z->ext += EF_L_UT_UX2_SIZE;
+
+    if (ut_flg != 0) {
+      eb_l_ptr[0]  = 'U';
+      eb_l_ptr[1]  = 'T';
+      eb_l_ptr[2]  = eb_l_ut_len;       /* length of data part of e.f. */
+      eb_l_ptr[3]  = 0;
+      eb_l_ptr[4]  = ut_flg;
+      eb_pt = eb_l_ptr + 5;
+      if (ut_flg & EB_UT_FL_MTIME) {
+        *eb_pt++ = (char)(z_utim->mtime);
+        *eb_pt++ = (char)(z_utim->mtime >> 8);
+        *eb_pt++ = (char)(z_utim->mtime >> 16);
+        *eb_pt++ = (char)(z_utim->mtime >> 24);
+      }
+      if (ut_flg & EB_UT_FL_ATIME) {
+        *eb_pt++ = (char)(z_utim->atime);
+        *eb_pt++ = (char)(z_utim->atime >> 8);
+        *eb_pt++ = (char)(z_utim->atime >> 16);
+        *eb_pt++ = (char)(z_utim->atime >> 24);
+      }
+      if (ut_flg & EB_UT_FL_CTIME) {
+        *eb_pt++ = (char)(z_utim->ctime);
+        *eb_pt++ = (char)(z_utim->ctime >> 8);
+        *eb_pt++ = (char)(z_utim->ctime >> 16);
+        *eb_pt++ = (char)(z_utim->ctime >> 24);
+      }
+    }
+#ifdef UNIX
+    else {
+      eb_pt = eb_l_ptr;
+    }
+    *eb_pt++ = 'U';
+    *eb_pt++ = 'x';
+    *eb_pt++ = EB_UX2_MINLEN;            /* length of data part of local e.f. */
+    *eb_pt++  = 0;
+    *eb_pt++ = (char)(s.st_uid);
+    *eb_pt++ = (char)(s.st_uid >> 8);
+    *eb_pt++ = (char)(s.st_gid);
+    *eb_pt++ = (char)(s.st_gid >> 8);
+#endif /* UNIX */
+
+    z->cextra = eb_c_ptr;
+    eb_c_ptr += z->cext;
+    z->cext += EF_C_UT_UX2_SIZE;
+
+    if (ut_flg != 0) {
+      memcpy(eb_c_ptr, eb_l_ptr, EB_C_UT_SIZE);
+      eb_c_ptr[EB_LEN] = eb_c_ut_len;
+    }
+#ifdef UNIX
+    memcpy(eb_c_ptr+EB_C_UT_SIZE, eb_l_ptr+EB_L_UT_SIZE, EB_C_UX2_SIZE);
+    eb_c_ptr[EB_LEN+EB_C_UT_SIZE] = 0;
+#endif /* UNIX */
+  }
+
+  return ZE_OK;
+}
+
+#endif /* USE_EF_UT_TIME */
+
+
+int set_extra_field (struct zlist *z, iztimes *z_utim )
+{
+    int rv = 0;
+    int last_rv = 0;
+    char flag = 0;
+
+    if ((qlflag & 3) != 1)
+    {
+        qdosextra       *lq, *cq;
+        if ((lq = (qdosextra *) calloc(sizeof(qdosextra), 1)) == NULL)
+            return ZE_MEM;
+        if ((cq = (qdosextra *) calloc(sizeof(qdosextra), 1)) == NULL)
+            return ZE_MEM;
+
+        rv = qlstat(z->name, &(lq->header), &flag);
+
+        if (rv == 0 || (rv == 1 && (qlflag & 2)))
+        {
+            lq->shortid = rev_short((short) SHORTID);
+            lq->len.lo  = (unsigned char)(EXTRALEN & 0xff);
+            lq->len.hi  = (unsigned char)(EXTRALEN >> 8);
+            strcpy(lq->longid, LONGID);
+
+            memcpy(cq, lq, sizeof(qdosextra));
+
+            z->ext      =   sizeof(qdosextra);
+            z->cext     =   sizeof(qdosextra);
+            z->extra    =   (void *) lq;
+            z->cextra   =   (void *) cq;
+            fprintf (stderr, " %c",
+                     lq->header.d_datalen ? '*' : '#');
+        }
+        else if (rv == -1)
+        {
+            fprintf(stderr,
+                    "%s: warning: cannot stat %s, no file header added\n",
+                    "zip", z->name);
+        }
+        if(flag)
+        {
+            fputs (" !", stderr);
+        }
+     }
+    last_rv = (rv == -1 ? ZE_OPEN : ZE_OK);
+
+#ifdef USE_EF_UT_TIME
+# ifdef QDOS
+#   define IZ_UT_FLAGS EB_UT_FL_MTIME
+# endif
+# ifdef UNIX
+#   define IZ_UT_FLAGS (EB_UT_FL_MTIME | EB_UT_FL_ATIME)
+# endif
+# ifndef IZ_UT_FLAGS
+#   define IZ_UT_FLAGS EB_UT_FL_MTIME
+# endif
+
+    rv = GetExtraTime(z, z_utim, IZ_UT_FLAGS);
+    if (rv != ZE_OK)
+        last_rv = rv;
+#endif /* USE_EF_UT_TIME */
+
+    return last_rv;
+}
diff --git a/qdos/qfileio.c b/qdos/qfileio.c
new file mode 100644 (file)
index 0000000..07a6bd8
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include "zip.h"
+
+#ifndef UTIL    /* the companion #endif is a bit of ways down ... */
+
+#include <time.h>
+#include <utime.h>
+
+#include <errno.h>
+
+#ifdef S_IWRITE
+# undef S_IWRITE
+#endif /* S_IWRITE */
+#define S_IWRITE S_IWUSR
+
+
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+
+typedef time_t statime;
+#define PAD 0
+#define PATH_END '/'
+
+/* Local functions */
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  char *a;              /* path and name for recursion */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (SSTAT(n, &s) )
+  {
+    /* Not a file or directory--search for shell expression in zip file */
+    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
+
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free(p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+
+  if ((s.st_mode & S_IFDIR) == 0)
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  }
+  return ZE_OK;
+}
+
+
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t;              /* shortened name */
+  int dosflag;
+
+  t = ql2Unix(x);
+
+  dosflag = dosify; /* default for non-DOS and non-OS/2 */
+
+  /* Make changes, if any, to the copied name (leave original intact) */
+
+  if (!pathput)
+    t = last(t, PATH_END);
+
+  /* Discard directory names with zip -rj */
+  if (*t == '\0')
+    return t;
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL)
+    return NULL;
+  strcpy(n, t);
+
+  if (dosify)
+    msname(n);
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+  return n;
+}
+
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+
+  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+       return NULL;
+  strcpy(x, Unix2ql(n, NULL));
+  return x;
+}
+
+
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+  struct utimbuf u;     /* argument for utime()  const ?? */
+
+  /* Convert DOS time to time_t format in u */
+  u.actime = u.modtime = dos2unixtime(d);
+  utime(f, &u);
+}
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  char *name;
+  unsigned int len = strlen(f);
+
+  if (f == label) {
+    if (a != NULL)
+      *a = label_mode;
+    if (n != NULL)
+      *n = -2L; /* convention for a label name */
+    if (t != NULL)
+      t->atime = t->mtime = t->ctime = label_utim;
+    return label_time;
+  }
+
+  name = malloc(len+1);
+  if (!name)
+    return 0;  /* ideally, would like to report alloc-failure warning/error */
+
+  strcpy(name, f);
+  if (name[len - 1] == '/')
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+  if (strcmp(f, "-") == 0) {
+    if (fstat(fileno(stdin), &s) != 0) {
+      free(name);
+      error("fstat(stdin)");
+    }
+  } else if (LSSTAT(name, &s) != 0) {
+             /* Accept about any file kind including directories
+              * (stored with trailing / with -r option)
+              */
+    free(name);
+    return 0;
+  }
+
+  if (a != NULL) {
+    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
+    if ((s.st_mode & S_IFMT) == S_IFDIR) {
+      *a |= MSDOS_DIR_ATTR;
+    }
+  }
+  if (n != NULL)
+    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = s.st_ctime;
+  }
+
+  free(name);
+
+  return unix2dostime(&s.st_mtime);
+}
+
+
+int deletedir(d)
+char *d;                /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+   Return the result of rmdir(), delete(), or system().
+   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).
+ */
+{
+    return rmdir(d);
+}
+
+#endif /* !UTIL */
+
+
+void version_local()
+{
+    puts ("Compiled with c68 v4.2x on " __DATE__);
+}
diff --git a/qdos/zipup.h b/qdos/zipup.h
new file mode 100644 (file)
index 0000000..1de3f61
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef O_RDONLY
+#  define O_RDONLY 0
+#endif
+#define fhow O_RDONLY
+#define fbad (-1)
+typedef int ftype;
+#define zopen(n,p) open(n,p)
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f) close(f)
+#define zerr(f) (k == (extent)(-1L))
+#define zstdin 0
diff --git a/revision.h b/revision.h
new file mode 100644 (file)
index 0000000..d0f4353
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2005-Feb-10 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *  revision.h by Mark Adler.
+ */
+
+#ifndef __revision_h
+#define __revision_h 1
+
+/* For api version checking */
+#define Z_MAJORVER   2
+#define Z_MINORVER   3
+#define Z_PATCHLEVEL 1
+#define Z_BETALEVEL ""
+
+#define VERSION "2.31"
+#define REVDATE "March 8th 2005"
+
+#define DW_MAJORVER    Z_MAJORVER
+#define DW_MINORVER    Z_MINORVER
+#define DW_PATCHLEVEL  Z_PATCHLEVEL
+
+#ifndef WINDLL
+/* Copyright notice for binary executables--this notice only applies to
+ * those (zip, zipcloak, zipsplit, and zipnote), not to this file
+ * (revision.h).
+ */
+
+#ifndef DEFCPYRT                     /* copyright[] gets defined only once ! */
+extern ZCONST char *copyright[2];    /* keep array sizes in sync with number */
+extern ZCONST char *swlicense[50];   /*  of text line in definition below !! */
+extern ZCONST char *versinfolines[7];
+extern ZCONST char *cryptnote[7];
+
+#else /* DEFCPYRT */
+
+ZCONST char *copyright[] = {
+"Copyright (C) 1990-2005 Info-ZIP",
+"Type '%s \"-L\"' for software license."
+};
+
+ZCONST char *versinfolines[] = {
+"This is %s %s (%s), by Info-ZIP.",
+"Currently maintained by Onno van der Linden. Please send bug reports to",
+"the authors using http://www.info-zip.org/zip-bug.html; see README for details.",
+"",
+"Latest sources and executables are at ftp://ftp.info-zip.org/pub/infozip, as of",
+"above date; see http://www.info-zip.org for other sites.",
+""
+};
+
+/* new notice - 2/2/2005 EG */
+ZCONST char *cryptnote[] = {
+"Encryption notice:",
+"\tThe encryption code of this program is not copyrighted and is",
+"\tput in the public domain.  It was originally written in Europe",
+"\tand, to the best of our knowledge, can be freely distributed",
+"\tin both source and object forms from any country, including",
+"\tthe USA under License Exception TSU of the U.S. Export",
+"\tAdministration Regulations (section 740.13(e)) of 6 June 2002."
+};
+
+ZCONST char *swlicense[] = {
+"Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.",
+"",
+"For the purposes of this copyright and license, \"Info-ZIP\" is defined as",
+"the following set of individuals:",
+"",
+"   Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,",
+"   Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,",
+"   Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,",
+"   David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,",
+"   Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,",
+"   Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,",
+"   Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,",
+"   Rich Wales, Mike White",
+"",
+"This software is provided \"as is,\" without warranty of any kind, express",
+"or implied.  In no event shall Info-ZIP or its contributors be held liable",
+"for any direct, indirect, incidental, special or consequential damages",
+"arising out of the use of or inability to use this software.",
+"",
+"Permission is granted to anyone to use this software for any purpose,",
+"including commercial applications, and to alter it and redistribute it",
+"freely, subject to the following restrictions:",
+"",
+"    1. Redistributions of source code must retain the above copyright notice,",
+"       definition, disclaimer, and this list of conditions.",
+"",
+"    2. Redistributions in binary form (compiled executables) must reproduce",
+"       the above copyright notice, definition, disclaimer, and this list of",
+"       conditions in documentation and/or other materials provided with the",
+"       distribution.  The sole exception to this condition is redistribution",
+"       of a standard UnZipSFX binary (including SFXWiz) as part of a",
+"       self-extracting archive; that is permitted without inclusion of this",
+"       license, as long as the normal SFX banner has not been removed from",
+"       the binary or disabled.",
+"",
+"    3. Altered versions--including, but not limited to, ports to new operating",
+"       systems, existing ports with new graphical interfaces, and dynamic,",
+"       shared, or static library versions--must be plainly marked as such",
+"       and must not be misrepresented as being the original source.  Such",
+"       altered versions also must not be misrepresented as being Info-ZIP",
+"       releases--including, but not limited to, labeling of the altered",
+"       versions with the names \"Info-ZIP\" (or any variation thereof, including,",
+"       but not limited to, different capitalizations), \"Pocket UnZip,\" \"WiZ\"",
+"       or \"MacZip\" without the explicit permission of Info-ZIP.  Such altered",
+"       versions are further prohibited from misrepresentative use of the",
+"       Zip-Bugs or Info-ZIP e-mail addresses or of the Info-ZIP URL(s).",
+"",
+"    4. Info-ZIP retains the right to use the names \"Info-ZIP,\" \"Zip,\" \"UnZip,\"",
+"       \"UnZipSFX,\" \"WiZ,\" \"Pocket UnZip,\" \"Pocket Zip,\" and \"MacZip\" for its",
+"       own source and binary releases."
+};
+#endif /* DEFCPYRT */
+#endif /* !WINDLL */
+#endif /* !__revision_h */
diff --git a/tailor.h b/tailor.h
new file mode 100644 (file)
index 0000000..38afdcd
--- /dev/null
+++ b/tailor.h
@@ -0,0 +1,480 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#ifdef AMIGA
+#include "amiga/osdep.h"
+#endif
+
+#ifdef AOSVS
+#include "aosvs/osdep.h"
+#endif
+
+#ifdef ATARI
+#include "atari/osdep.h"
+#endif
+
+#ifdef __BEOS__
+#include "beos/osdep.h"
+#endif
+
+#ifdef __ATHEOS__
+#include "atheos/osdep.h"
+#endif
+
+#ifdef DOS
+#include "msdos/osdep.h"
+#endif
+
+#ifdef __human68k__
+#include "human68k/osdep.h"
+#endif
+
+#if ((defined(__MWERKS__) && defined(macintosh)) || defined(MACOS))
+#include "macos/osdep.h"
+#endif
+
+#ifdef OS2
+#include "os2/osdep.h"
+#endif
+
+#ifdef __riscos
+#include "acorn/osdep.h"
+#endif
+
+#ifdef QDOS
+#include "qdos/osdep.h"
+#endif
+
+#ifdef __TANDEM
+#include "tandem.h"
+#include "tanzip.h"
+#endif
+
+#ifdef UNIX
+#include "unix/osdep.h"
+#endif
+
+#if defined(__COMPILER_KCC__) || defined(TOPS20)
+#include "tops20/osdep.h"
+#endif
+
+#if defined(VMS) || defined(__VMS)
+#include "vms/osdep.h"
+#endif
+
+#if defined(__VM__) || defined(VM_CMS) || defined(MVS)
+#include "cmsmvs.h"
+#endif
+
+#ifdef WIN32
+#include "win32/osdep.h"
+#endif
+
+#ifdef THEOS
+#include "theos/osdep.h"
+#endif
+
+#if (defined(USE_ZLIB) && defined(ASM_CRC))
+#  undef ASM_CRC
+#endif
+
+#if (defined(USE_ZLIB) && defined(ASMV))
+#  undef ASMV
+#endif
+
+/* When "void" is an alias for "int", prototypes cannot be used. */
+#if (defined(NO_VOID) && !defined(NO_PROTO))
+#  define NO_PROTO
+#endif
+
+/* Used to remove arguments in function prototypes for non-ANSI C */
+#ifndef NO_PROTO
+#  define OF(a) a
+#else /* NO_PROTO */
+#  define OF(a) ()
+#endif /* ?NO_PROTO */
+
+/* If the compiler can't handle const define ZCONST in osdep.h */
+/* Define const itself in case the system include files are bonkers */
+#ifndef ZCONST
+#  ifdef NO_CONST
+#    define ZCONST
+#    define const
+#  else
+#    define ZCONST const
+#  endif
+#endif
+
+/*
+ * case mapping functions. case_map is used to ignore case in comparisons,
+ * to_up is used to force upper case even on Unix (for dosify option).
+ */
+#ifdef USE_CASE_MAP
+#  define case_map(c) upper[(c) & 0xff]
+#  define to_up(c)    upper[(c) & 0xff]
+#else
+#  define case_map(c) (c)
+#  define to_up(c)    ((c) >= 'a' && (c) <= 'z' ? (c)-'a'+'A' : (c))
+#endif /* USE_CASE_MAP */
+
+/* Define void, zvoid, and extent (size_t) */
+#include <stdio.h>
+
+#ifndef NO_STDDEF_H
+#  include <stddef.h>
+#endif /* !NO_STDDEF_H */
+
+#ifndef NO_STDLIB_H
+#  include <stdlib.h>
+#endif /* !NO_STDLIB_H */
+
+#ifndef NO_UNISTD_H
+#  include <unistd.h> /* usually defines _POSIX_VERSION */
+#endif /* !NO_UNISTD_H */
+
+#ifndef NO_FCNTL_H
+#  include <fcntl.h>
+#endif /* !NO_FNCTL_H */
+
+#ifndef NO_STRING_H
+#  include <string.h>
+#else
+#  include <strings.h>
+#endif /* NO_STRING_H */
+
+#ifdef NO_VOID
+#  define void int
+   typedef char zvoid;
+#else /* !NO_VOID */
+# ifdef NO_TYPEDEF_VOID
+#  define zvoid void
+# else
+   typedef void zvoid;
+# endif
+#endif /* ?NO_VOID */
+
+#ifdef NO_STRRCHR
+#  define strrchr rindex
+#endif
+
+#ifdef NO_STRCHR
+#  define strchr index
+#endif
+
+/*
+ * A couple of forward declarations that are needed on systems that do
+ * not supply C runtime library prototypes.
+ */
+#ifdef NO_PROTO
+char *strcpy();
+char *strcat();
+char *strrchr();
+/* XXX use !defined(ZMEM) && !defined(__hpux__) ? */
+#if !defined(ZMEM) && defined(NO_STRING_H)
+char *memset();
+char *memcpy();
+#endif /* !ZMEM && NO_STRING_H */
+
+/* XXX use !defined(__hpux__) ? */
+#ifdef NO_STDLIB_H
+char *calloc();
+char *malloc();
+char *getenv();
+long atol();
+#endif /* NO_STDLIB_H */
+
+#ifndef NO_MKTEMP
+char *mktemp();
+#endif /* !NO_MKTEMP */
+
+/* moved to include mktemp - Cosmin 2/18/05 */
+#endif /* NO_PROTO */
+
+/*
+ * SEEK_* macros, should be defined in stdio.h
+ */
+/* Define fseek() commands */
+#ifndef SEEK_SET
+#  define SEEK_SET 0
+#endif /* !SEEK_SET */
+
+#ifndef SEEK_CUR
+#  define SEEK_CUR 1
+#endif /* !SEEK_CUR */
+
+#ifndef FALSE
+#  define FALSE 0
+#endif
+
+#ifndef TRUE
+#  define TRUE 1
+#endif
+
+#ifdef NO_SIZE_T
+   typedef unsigned int extent;
+#else
+   typedef size_t extent;
+#endif
+
+#ifdef NO_TIME_T
+   typedef long time_t;
+#endif
+
+/* DBCS support for Info-ZIP's zip  (mainly for japanese (-: )
+ * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp)
+ * This code is public domain!   Date: 1998/12/20
+ */
+#ifdef _MBCS
+#   include <locale.h>
+
+    /* Multi Byte Character Set */
+    extern char *___tmp_ptr;
+    unsigned char *zmbschr OF((ZCONST unsigned char *, unsigned int));
+    unsigned char *zmbsrchr OF((ZCONST unsigned char *, unsigned int));
+#   define CLEN(ptr) mblen(ptr, MB_CUR_MAX)
+#   define PREINCSTR(ptr) (ptr += CLEN(ptr))
+#   define POSTINCSTR(ptr) (___tmp_ptr=(char *)ptr,ptr += CLEN(ptr),___tmp_ptr)
+    int lastchar OF((ZCONST char *ptr));
+#   define MBSCHR(str,c) (char *)zmbschr((ZCONST unsigned char *)(str), c)
+#   define MBSRCHR(str,c) (char *)zmbsrchr((ZCONST unsigned char *)(str), (c))
+#   define SETLOCALE(category, locale) setlocale(category, locale)
+#else /* !_MBCS */
+#   define CLEN(ptr) 1
+#   define PREINCSTR(ptr) (++(ptr))
+#   define POSTINCSTR(ptr) ((ptr)++)
+#   define lastchar(ptr) ((*(ptr)=='\0') ? '\0' : ptr[strlen(ptr)-1])
+#   define MBSCHR(str, c) strchr(str, c)
+#   define MBSRCHR(str, c) strrchr(str, c)
+#   define SETLOCALE(category, locale)
+#endif /* ?_MBCS */
+#define INCSTR(ptr) PREINCSTR(ptr)
+
+
+/* System independent replacement for "struct utimbuf", which is missing
+ * in many older OS environments.
+ */
+typedef struct ztimbuf {
+    time_t actime;              /* new access time */
+    time_t modtime;             /* new modification time */
+} ztimbuf;
+
+/* This macro round a time_t value to the OS specific resolution */
+#ifndef ROUNDED_TIME
+#  define ROUNDED_TIME(time)   (time)
+#endif
+
+/* Some systems define S_IFLNK but do not support symbolic links */
+#if defined (S_IFLNK) && defined(NO_SYMLINK)
+#  undef S_IFLNK
+#endif
+
+#ifndef FOPR    /* fallback default definitions for FOPR, FOPM, FOPW: */
+#  define FOPR "r"
+#  define FOPM "r+"
+#  define FOPW "w"
+#endif /* fallback definition */
+
+#ifndef FOPW_TMP    /* fallback default for opening writable temp files */
+#  define FOPW_TMP FOPW
+#endif
+
+/* Open the old zip file in exclusive mode if possible (to avoid adding
+ * zip file to itself).
+ */
+#ifdef OS2
+#  define FOPR_EX FOPM
+#else
+#  define FOPR_EX FOPR
+#endif
+
+
+/* MSDOS file or directory attributes */
+#define MSDOS_HIDDEN_ATTR 0x02
+#define MSDOS_DIR_ATTR 0x10
+
+
+/* Define this symbol if your target allows access to unaligned data.
+ * This is not mandatory, just a speed optimization. The compressed
+ * output is strictly identical.
+ */
+#if (defined(MSDOS) && !defined(WIN32)) || defined(i386)
+#    define UNALIGNED_OK
+#endif
+#if defined(mc68020) || defined(vax)
+#    define UNALIGNED_OK
+#endif
+
+#if (defined(SMALL_MEM) && !defined(CBSZ))
+#   define CBSZ 2048 /* buffer size for copying files */
+#   define ZBSZ 2048 /* buffer size for temporary zip file */
+#endif
+
+#if (defined(MEDIUM_MEM) && !defined(CBSZ))
+#  define CBSZ 8192
+#  define ZBSZ 8192
+#endif
+
+#ifndef CBSZ
+#  define CBSZ 16384
+#  define ZBSZ 16384
+#endif
+
+#ifndef SBSZ
+#  define SBSZ CBSZ     /* copy buf size for STORED entries, see zipup() */
+#endif
+
+#ifndef MEMORY16
+#  ifdef __WATCOMC__
+#    undef huge
+#    undef far
+#    undef near
+#  endif
+#  ifdef THEOS
+#    undef far
+#    undef near
+#  endif
+#  if (!defined(__IBMC__) || !defined(OS2))
+#    ifndef huge
+#      define huge
+#    endif
+#    ifndef far
+#      define far
+#    endif
+#    ifndef near
+#      define near
+#    endif
+#  endif
+#  define nearmalloc malloc
+#  define nearfree free
+#  define farmalloc malloc
+#  define farfree free
+#endif /* !MEMORY16 */
+
+#ifndef Far
+#  define Far far
+#endif
+
+/* MMAP and BIG_MEM cannot be used together -> let MMAP take precedence */
+#if (defined(MMAP) && defined(BIG_MEM))
+#  undef BIG_MEM
+#endif
+
+#if (defined(BIG_MEM) || defined(MMAP)) && !defined(DYN_ALLOC)
+#   define DYN_ALLOC
+#endif
+
+#ifndef SSTAT
+#  define SSTAT      stat
+#endif
+#ifdef S_IFLNK
+#  define LSTAT      lstat
+#  define LSSTAT(n, s)  (linkput ? lstat((n), (s)) : SSTAT((n), (s)))
+#else
+#  define LSTAT      SSTAT
+#  define LSSTAT     SSTAT
+#endif
+
+/* The following default definition of the second input for the crypthead()
+ * random seed computation can be used on most systems (all those that
+ * supply a UNIX compatible getpid() function).
+ */
+#ifdef ZCRYPT_INTERNAL
+#  ifndef ZCR_SEED2
+#    define ZCR_SEED2     (unsigned) getpid()   /* use PID as seed pattern */
+#  endif
+#endif /* ZCRYPT_INTERNAL */
+
+/* The following OS codes are defined in pkzip appnote.txt */
+#ifdef AMIGA
+#  define OS_CODE  0x100
+#endif
+#ifdef VMS
+#  define OS_CODE  0x200
+#endif
+/* unix    3 */
+#ifdef VM_CMS
+#  define OS_CODE  0x400
+#endif
+#ifdef ATARI
+#  define OS_CODE  0x500
+#endif
+#ifdef OS2
+#  define OS_CODE  0x600
+#endif
+#ifdef MACOS
+#  define OS_CODE  0x700
+#endif
+/* z system 8 */
+/* cp/m     9 */
+#ifdef TOPS20
+#  define OS_CODE  0xa00
+#endif
+#ifdef WIN32
+#  define OS_CODE  0xb00
+#endif
+#ifdef QDOS
+#  define OS_CODE  0xc00
+#endif
+#ifdef RISCOS
+#  define OS_CODE  0xd00
+#endif
+#ifdef VFAT
+#  define OS_CODE  0xe00
+#endif
+#ifdef MVS
+#  define OS_CODE  0xf00
+#endif
+#ifdef __BEOS__
+#  define OS_CODE  0x1000
+#endif
+#ifdef TANDEM
+#  define OS_CODE  0x1100
+#endif
+#ifdef THEOS
+#  define OS_CODE  0x1200
+#endif
+#ifdef __ATHEOS__
+#  define OS_CODE  0x1E00
+#endif
+
+#define NUM_HOSTS 31
+/* Number of operating systems. Should be updated when new ports are made */
+
+#if defined(DOS) && !defined(OS_CODE)
+#  define OS_CODE  0x000
+#endif
+
+#ifndef OS_CODE
+#  define OS_CODE  0x300  /* assume Unix */
+#endif
+
+/* can't use "return 0" from main() on VMS */
+#ifndef EXIT
+#  define EXIT  exit
+#endif
+#ifndef RETURN
+#  define RETURN return
+#endif
+
+#ifndef ZIPERR
+#  define ZIPERR ziperr
+#endif
+
+#if (defined(USE_ZLIB) && defined(MY_ZCALLOC))
+   /* special zcalloc function is not needed when linked against zlib */
+#  undef MY_ZCALLOC
+#endif
+
+#if (!defined(USE_ZLIB) && !defined(MY_ZCALLOC))
+   /* Any system without a special calloc function */
+#  define zcalloc(items,size) \
+          (zvoid far *)calloc((unsigned)(items), (unsigned)(size))
+#  define zcfree    free
+#endif /* !USE_ZLIB && !MY_ZCALLOC */
+
+/* end of tailor.h */
diff --git a/tandem/DOIT b/tandem/DOIT
new file mode 100644 (file)
index 0000000..901f879
--- /dev/null
@@ -0,0 +1,21 @@
+?tacl macro
+#frame
+#push zipfile
+#SET zipfile ZIP23
+
+unzip -a [zipfile] *.c  -x */*
+== Following not required
+RENAME apic    apicz
+RENAME mktimec mktimecz   == use Tandem mktime()
+
+unzip -a [zipfile] *.h -x */*
+== Following not required
+RENAME apih    apizh
+
+unzip -aj [zipfile] tandem/*.h
+
+unzip -aj [zipfile] tandem/*.c
+
+unzip -aj [zipfile] tandem/* -x tandem/*.*
+
+#unframe
diff --git a/tandem/HISTORY b/tandem/HISTORY
new file mode 100644 (file)
index 0000000..fc74776
--- /dev/null
@@ -0,0 +1,97 @@
+Tandem Port History
+===================
+
+Hi, I'm Dave Smith and I work at BP Oil UK, looking after their European card
+processing system since 1992.  We need to send lots of files via FTP to other
+BP machines (Novell, NT, Sun...). Sending large files was frowned upon, so the
+search for a zip product was on.
+
+We tried the GZIP product from Twinsoft Netherlands but it was complicated to
+use and it was not widely known by other arts of BP.
+
+What we really wanted was a PKZIP compatible product, as this is a widely known
+product.  By chance when surfing the web I discovered the Info-ZIP web site.
+This claimed PKZIP 2.04g compatibility and had a number of ports, was free, and
+even had source code, but unfortunately no Tandem version :-(
+
+Thus in the autumn 1996 I bit the bullet and took on the job of porting the
+code to Tandem NSK (Guardian).  This meant dusting off my circa 1985 'C'
+programming skills and firing up the Tandem 'C' compiler - not known for its
+ease of use, especially debugging 8-;  This was all on D30 by the way.
+
+To start this off I had to choose an existing port to base te Tandem one on.
+Nearest (?) was the VM-CMS/MVS port by George Petrov.  The main similarity
+being that these machines are record based, and have a similarish filing system
+to Guardian.
+
+First to be tackled was ZIP.  By the end of 1996 I had a version which compiled
+and ran (giving the program banner) - which seemed like a major acheivement at
+the time.
+
+In December 1996 I forwarded a version of ZIP to Info-ZIP which wor
+ked only on Edit files, and had no concept of directories.  Became ZIP 2.1
+
+By March 1997 I had improved ZIP so that it could cope with Unstructured files
+as well (Became ZIP 2.2).  I also had ported a version of UNZIP which could
+create Unstructured files (not Edit) - UNZIP 5.20
+
+At the start of September 1997 I sent UNZIP with Edit file support to Info-ZIP
+(incorporated into 5.32)
+
+In March 1998 I submitted file I/O improvements (SBB) for ZIP (2.3a)
+
+In August 1998 I added Tandem DEFINE processing for ZIP (2.3e).  This was a
+feature required by BP to allow them to store files with a different internal
+name than the physical file being zipped (without renaming it).
+Also added storing of proper UTC timestamps which allow for DST & timezone.
+
+Also in August I added the same file I/O improvements for UNZIP (5.33f)
+
+I then added the ability to update the unzipped files last modified and last
+open timestamps - this required help from TNSC to allow me access to the
+priviliged procedure call.  Also can give the files back to the original user
+by use of the '-X' flag.
+
+At the end of 1998 I was given the go ahead to add the zipping of Enscribe
+files.  This first version stores all Enscribe file attributes EXCEPT SQL, alt
+key and partition information.
+
+ZIP now uses its own Guardian I/O (rather than the 'C'library) for the reading
+of files to be zipped.
+
+Unstructured files use Large Transfer mode and READ (56K or 30K reads)
+Edit files use IOEdit routines
+Enscribe files use READ and SBB and add LF to the end of each record.
+
+UNZIP has the ability to update the filecode of files restored to ther original
+value (Unstructured only)
+
+
+To Do ZIP
+===========
+1. Change I/O to use NSK/Large Transfer mode in fwrite of ZIP file itself- this
+   will dramaticaly speed up updating an existing zipfile. When updating an
+   existing zipfile it copies it to a temporary file currently using only SBB.
+2. Add raw binary mode to allow storing of raw data in zip file - e.g. only to
+   be unzipped on Tandem !  This is simplest/fastest way to provide full
+   Enscribe support for Tandem platform - with no cross-platform support.
+3. Add SQL support !!
+
+To Do UNZIP
+===========
+1. Re-write the I/O routines to use NSK to recreate the original Enscribe file
+   structure.
+2. Use NSK Large Transfer mode I/O for reading/writing of ZIP file
+3. Add raw binary mode to allow restoration of Tandem file from previous raw
+   data ZIP (see above)
+4. Add SQL support !!
+
+
+
+Current Versions on Website
+===========================
+
+ZIP 2.2
+UNZIP 5.32
+
+As of December 21 1998
diff --git a/tandem/README b/tandem/README
new file mode 100644 (file)
index 0000000..54dd357
--- /dev/null
@@ -0,0 +1,94 @@
+Tandem Port of Info ZIP (zip)
+=======================
+
+History:
+1. Tidy up COMMACS/MACROS/MAKE
+2. Changes for version 5.32d affected files:
+- TANDEMC     (changes to stat() for UNZIP)
+- ZIPUPC      (changes to use REVISIOH rather than REVISEH)
+- ZIPFILEC    (don't add ".zip" to ZIP name)
+- FILEIOC     (cosmetic missing "*/")
+3. Fix to allow zipping of files called ZIP (e.g. DAVES.ZIP)
+03/08/98  2.3e   Process Tandem DEFINE names - use define name as internal name
+                 Remove BITSO from build of ZIPLIB
+                 New DOIT macro for extracting files from archive
+17/08/98  2.3e   Set USE_EF_UT_TIME to allow for timezone changes
+18/08/98  2.3e   Use define LICENSED to build object able to update timestamps
+30/11/98  2.3h   Updated mapname/chmod/in2ex, include licensing in MAKE
+21/12/98  2.3i   Add simple Enscribe file handling, consisting of:
+                 - storing Enscribe files as LF delimited text files
+                 - adding Tandem Extra Field, holding Enscribe file attributes
+                 Create ZIP file with Tandem File Code 1001
+                 Rationalised TANDEMH and TANDEMC wth UNZIP 5.40d
+12/01/99  2.3i   Correct bug stopping setting of last open timestamp
+25/01/99  2.3k   Add '-B' flag to zip Enscribe files with no record delimiters
+26/01/99  2.3k   Make CRLF the default delimiter for Structured and Text files
+01/02/99  2.3k   Use maximum size large transfer read (57344) as default, allow
+                 smaller value as option
+01/02/99  2.3k   Redefine -B flag for Edit/Enscribe files as in table below.
+                 Default (-B or -B0 or no flag) is add CR/LF
+
+                 -B<number> options at present are:
+                 Bit 0 -  Don't add delimiter (Edit/Enscribe)
+                 Bit 1 -  Use LF rather than CR/LF as delimiter (Edit/Enscribe)
+                 Bit 2 -  Space fill record to max record length (Enscribe)
+                 Bit 3 -  Trim trailing space (Edit/Enscribe)
+
+                 Bit 8 -  Force 30K (Expand) large read for Unstructured files
+
+06/02/99  2.3k   Attempt to catch Large Transfer mode failure (err 21) when
+                 attempting 56K reads, add substitute 30K reads (Expand files)
+24/03/99  2.3m   Split TANDEMC into TANDEMC/TANZIPC/TANUNZC
+24/03/99  2.3m   Added TANNSKH to allow for declarations which require
+                 structures defined in ZIPH after call to TANDEMH
+11/05/99  2.3m   Change zopen in TANZIPC to allow opening of files with
+                 missing alt keys (err 4)
+                 Assume not DST if can't resolve time (no DST table available)
+27/09/99  2.3o   Fixed bug in -B0 option causing files to be stored rather than
+                 deflated. Created TANZIPH
+
+A few notes about the files on this subvol
+
+COMMACS   -  used by MAKE (compiler)
+DOIT      -  macro to extract required Tandem files from archive and rename
+MACROS    -  used by MAKE (bind)
+MAKE      -  recompile ZIP code, attempts to only recompile changed code
+README    -  this file
+ZIPLIB    -  library of ZIP compiled routines, used by ZIP/ZIPNOTE etc
+ZIPL      -  ZIP object (bound using LARGE memory model)
+ZIPNOTE   -  ZIPNOTE object (bound using LARGE memory model)
+
+*C        -  Source file
+*H        -  Header files
+*O        -  Individual object files (when compiled by MAKE)
+
+Install Notes:
+==============
+Stage 1 - get ZIP object onto Tandem
+- download Tandem Zip executables archive from Web
+- using PC unzip program (e.g. pkunzip/WinZip) extract ZIP
+- copy ZIP from PC to Tandem in Binary mode s(FTP/IXF)
+- alter file code to 100
+- optionally place in $SYSTEM.SYSTEM to allow easy access from command line
+
+Stage 2 - (optional) compile source code (requires UNZIP on Tandem)
+- download ZIP source archive fwom web - contains all supported platforms
+- copy archive onto Tandem as Binary
+- extract Tandem DOIT macro ( UNZIP -j <archive> tandem/DOIT )
+- update DOIT macro to point at archive file
+- restore relevant files by running DOIT
+- NOTE that revision.h must be restored as REVISIOH
+- replace references to $T with a collector on your system
+- replace references to SUPER.DAVES with whatever user id you use
+- to compile run MAKE (compiles, accelerates, licences)
+- NOTE:  Always run the accelerated object on TNS/R systems, otherwise
+         it runs extremely slow.
+
+
+Additional Notes - LICENSE the object:
+======================================
+If you wish to be able to update the last modified time of the zip file
+(-o option) you need to add the line "#define LICENSED" to the TANDEMH file.
+If you set this option then you MUST FUP LICENSE the file as SUPER.SUPER.
+This is a Tandem restriction since we have to call a PRIV procedure to update
+the file label.  For ZIP the define is setup (default) in tandem.h
diff --git a/tandem/commacs b/tandem/commacs
new file mode 100644 (file)
index 0000000..1acb068
--- /dev/null
@@ -0,0 +1,85 @@
+?section CC ROUTINE
+#FRAME
+[#PUSH stem src obj htime file prev time stime otime
+       comp out options sup buf col locn group
+]
+
+[#IF [#ARGUMENT /VALUE src/ WORD /SPACE/ END]]
+[#IF [#EMPTYV src] |THEN|
+  #OUTPUT Syntax: CC <file> <collector> <comp-options>
+  #RESET FRAMES
+  #RETURN
+]
+
+[#IF NOT [#FILEINFO /EXISTENCE/ [src]]
+|THEN|
+  #OUTPUT [src] does not exist !
+  #RESET FRAMES
+  #RETURN
+]
+
+#SETV stem src
+#CHARDEL stem [#CHARCOUNT stem]
+#SET obj [stem]O
+
+[#IF [#ARGUMENT /VALUE out/ DEVICE END]]
+[#IF [#EMPTYV out] |THEN| #SET out $T.#C]
+
+#SETMANY col group, [#FILEINFO /VOLUME, SUBVOL/ [out]]
+#SET locn [group].[stem]
+#SET sup [#LOOKUPPROCESS /ANCESTOR/ [col]]
+
+
+#SET options [#REST]
+
+== Find newest Header file
+#SET htime 0
+#SET file [#FILENAMES /MAXIMUM 1/ *H]
+[#LOOP |WHILE| NOT [#EMPTYV file]
+|DO|
+  #SET time [#FILEINFO /MODIFICATION/ [file]]
+  [#IF time > htime |THEN| #SETV htime time]
+
+  #SETV prev file
+  #SET file [#FILENAMES /MAXIMUM 1, PREVIOUS [prev]/ *H]
+]
+
+#SET stime [#FILEINFO /MODIFICATION/ [src]]
+#SET otime [#FILEINFO /MODIFICATION/ [obj]]
+
+#SET comp 0
+
+[#IF otime < htime
+|THEN|
+  #OUTPUT Header file(s) changed since object [obj] compiled
+  #SET comp -1
+]
+
+[#IF otime < stime
+|THEN|
+  #OUTPUT Source file [src] changed since object [obj] compiled
+  #SET comp -1
+]
+
+[#IF comp
+|THEN|
+  SPOOLCOM /OUTV buf/ OPEN [sup];JOB (OWNER, LOC [locn]),STATUS,DELETE !
+  #OUTPUTV buf
+  #OUTPUT Compiling [src]... [options]
+  C /IN [src], OUT [out].[stem]/[obj];SYMBOLS,HIGHPIN [options]
+  [#CASE [tacl^completioncode]
+  | 0 |
+    #OUTPUT Compiled OK: [src]
+    SPOOLCOM /OUTV buf/ OPEN [sup];JOB (OWNER, LOC [locn]),STATUS,DELETE !
+    #SET _completion:completioncode 0
+  | 1 |
+    #OUTPUT [src]: Compile Warnings
+  |OTHERWISE|
+    #OUTPUT [src]: Compile FAILED !
+  ]
+|ELSE|
+  #OUTPUT Object file [obj] is up to date
+  #SET _completion:completioncode 0
+]
+
+#UNFRAME
diff --git a/tandem/macros b/tandem/macros
new file mode 100644 (file)
index 0000000..5db5a7d
--- /dev/null
@@ -0,0 +1,344 @@
+?section ADD^LIST routine
+[#IF [#ARGUMENT /VALUE item/ WORD/SPACE/]]
+#APPEND bin ADD * FROM [item]
+#SET itime [#FILEINFO /MODIFICATION/ [item]]
+[#IF itime > ntime |THEN| #SETV ntime itime]
+
+?section BBZIPLIB MACRO
+#FRAME
+#push bin item ntime itime libtime
+#SET ntime 0
+
+#OUTPUT Building [lib]
+#APPEND bin CLEAR
+add^list CRC32O
+add^list CRCTABO
+add^list CRYPTO
+add^list DEFLATEO
+add^list FILEIOO
+add^list GLOBALSO
+add^list TANDEMO
+add^list TANZIPO
+add^list TREESO
+add^list TTYIOO
+add^list UTILO
+add^list ZIPFILEO
+add^list ZIPUPO
+#APPEND bin INFO UNRESOLVED *
+#APPEND bin BUILD [lib] ! , LIST * OFF
+
+#SET libtime [#FILEINFO /MODIFICATION/ [lib]]
+[#IF libtime < ntime
+|THEN|
+  #OUTPUT [lib] needs re-building
+  BIND /NAME,INV BIN/
+  [#CASE [tacl^completioncode]
+  | 0         | #OUTPUT Bound [lib] OK
+  | 1         | #OUTPUT [lib]: BIND Failed with Warnings
+  | OTHERWISE | #OUTPUT [lib]: BIND Failed with ERRORS !
+  ]
+|ELSE|
+  #OUTPUT [lib] is up to date
+]
+
+#UNFRAME
+
+?section BBZIP MACRO
+#FRAME
+#push bin ziptime build
+#SET build 0
+#OUTPUT Building %1% with %2% memory model
+#APPEND bin CLEAR
+#APPEND bin ADD * FROM ZIPO
+#APPEND bin select search ($system.system.c%2%, [lib])
+#APPEND bin select runnable object on
+#APPEND bin select list * off
+#APPEND bin set heap 20 pages
+#APPEND bin set symbols on
+#APPEND bin set saveabend on
+#APPEND bin set inspect on
+#APPEND bin info unresolved *
+#APPEND bin BUILD %1%   !
+
+#SET ziptime [#FILEINFO /MODIFICATION/ %1%]
+[#IF ziptime < [#FILEINFO /MODIFICATION/ ZIPO] |THEN|
+  #OUTPUT %1% is older than ZIPO
+  #SET build -1
+]
+[#IF ziptime < [#FILEINFO /MODIFICATION/ [lib]] |THEN|
+  #OUTPUT %1% is older than [lib]
+  #SET build -1
+]
+[#IF build
+|THEN|
+  #OUTPUT %1% is out of date, re-building
+  BIND /NAME,INV BIN/
+  [#CASE [tacl^completioncode]
+  | 0         | #OUTPUT Bound %1% OK
+  | 1         | #OUTPUT %1%: BIND Failed with Warnings
+  | OTHERWISE | #OUTPUT %1%: BIND Failed with ERRORS !
+  ]
+|ELSE|
+  #OUTPUT %1% is up to date, no re-build required
+]
+
+#UNFRAME
+
+?section BBANY MACRO
+#FRAME
+#push bin memory anytime build
+#SET build 0
+#SETMANY memory, %2% LARGE
+#OUTPUT Building %1% with [memory] memory model
+#APPEND bin CLEAR
+#APPEND bin ADD * FROM %1%O
+#APPEND bin select search ($system.system.c[memory],[lib])
+#APPEND bin select runnable object on
+#APPEND bin select list * off
+#APPEND bin set heap 20 pages
+#APPEND bin set symbols on
+#APPEND bin set saveabend on
+#APPEND bin set inspect on
+#APPEND bin info unresolved *
+#APPEND bin BUILD %1%   !
+
+#SET anytime [#FILEINFO /MODIFICATION/ %1%]
+[#IF anytime < [#FILEINFO /MODIFICATION/ %1%O] |THEN|
+  #OUTPUT %1% is older than %1%O
+  #SET build -1
+]
+[#IF anytime < [#FILEINFO /MODIFICATION/ [lib]] |THEN|
+  #OUTPUT %1% is older than [lib]
+  #SET build -1
+]
+[#IF build
+|THEN|
+  #OUTPUT %1% is out of date, re-building
+  BIND /NAME,INV BIN/
+  [#CASE [tacl^completioncode]
+  | 0         | #OUTPUT Bound %1% OK
+  | 1         | #OUTPUT %1%: BIND Failed with Warnings
+  | OTHERWISE | #OUTPUT %1%: BIND Failed with ERRORS !
+  ]
+|ELSE|
+  #OUTPUT %1% is up to date, no re-build required
+]
+
+#UNFRAME
+
+
+?section BBUNZIPLIB MACRO
+#FRAME
+#push bin item ntime itime libtime
+#SET ntime 0
+
+#OUTPUT Building [lib]
+#APPEND bin CLEAR
+add^list CRC32O
+add^list CRCTABO
+add^list CRYPTO
+add^list ENVARGSO
+add^list EXPLODEO
+add^list EXTRACTO
+add^list FILEIOO
+add^list GLOBALSO
+add^list INFLATEO
+add^list LISTO
+add^list MATCHO
+add^list PROCESSO
+add^list TANDEMO
+add^list TANUNZO
+add^list TTYIOO
+add^list UNSHRINO
+add^list ZIPINFOO
+#APPEND bin INFO UNRESOLVED *
+#APPEND bin BUILD [lib] ! , LIST * OFF
+
+#SET libtime [#FILEINFO /MODIFICATION/ [lib]]
+[#IF libtime < ntime
+|THEN|
+  #OUTPUT [lib] needs re-building
+  BIND /NAME,INV BIN/
+  [#CASE [tacl^completioncode]
+  | 0         | #OUTPUT Bound [lib] OK
+  | 1         | #OUTPUT [lib]: BIND Failed with Warnings
+  | OTHERWISE | #OUTPUT [lib]: BIND Failed with ERRORS !
+  ]
+|ELSE|
+  #OUTPUT [lib] is up to date
+]
+
+#UNFRAME
+
+?section BBUNZIP MACRO
+#FRAME
+#push bin ziptime build
+#SET build 0
+#OUTPUT Building %1% with %2% memory model
+#APPEND bin CLEAR
+#APPEND bin ADD * FROM UNZIPO
+#APPEND bin select search ($system.system.c%2%,[lib])
+#APPEND bin select runnable object on
+#APPEND bin select list * off
+#APPEND bin set heap 20 pages
+#APPEND bin set symbols on
+#APPEND bin set saveabend on
+#APPEND bin set inspect on
+#APPEND bin info unresolved *
+#APPEND bin BUILD %1%   !
+
+#SET ziptime [#FILEINFO /MODIFICATION/ %1%]
+[#IF ziptime < [#FILEINFO /MODIFICATION/ UNZIPO] |THEN|
+  #OUTPUT %1% is older than UNZIPO
+  #SET build -1
+]
+[#IF ziptime < [#FILEINFO /MODIFICATION/ [lib]] |THEN|
+  #OUTPUT %1% is older than [lib]
+  #SET build -1
+]
+[#IF build
+|THEN|
+  #OUTPUT %1% is out of date, re-building
+  BIND /NAME,INV BIN/
+  [#CASE [tacl^completioncode]
+  | 0         | #OUTPUT Bound %1% OK
+  | 1         | #OUTPUT %1%: BIND Failed with Warnings
+  | OTHERWISE | #OUTPUT %1%: BIND Failed with ERRORS !
+  ]
+|ELSE|
+  #OUTPUT %1% is up to date, no re-build required
+]
+
+#UNFRAME
+
+?section BBSFXLIB MACRO
+#FRAME
+#push bin item ntime itime libtime
+#SET ntime 0
+
+#OUTPUT Building [lib]
+#APPEND bin CLEAR
+add^list CRC32O
+add^list CRCTABO
+add^list EXTRACTX
+add^list FILEIOO
+add^list GLOBALSO
+add^list INFLATEO
+add^list MATCHO
+add^list PROCESSX
+add^list TANDEMO
+add^list TANUNZX
+add^list TTYIOO
+#APPEND bin INFO UNRESOLVED *
+#APPEND bin BUILD [lib] ! , LIST * OFF
+
+#SET libtime [#FILEINFO /MODIFICATION/ [lib]]
+[#IF libtime < ntime
+|THEN|
+  #OUTPUT [lib] needs re-building
+  BIND /NAME,INV BIN/
+  [#CASE [tacl^completioncode]
+  | 0         | #OUTPUT Bound [lib] OK
+  | 1         | #OUTPUT [lib]: BIND Failed with Warnings
+  | OTHERWISE | #OUTPUT [lib]: BIND Failed with ERRORS !
+  ]
+|ELSE|
+  #OUTPUT [lib] is up to date
+]
+
+#UNFRAME
+
+?section BBSFX MACRO
+#FRAME
+#push bin ziptime build
+#SET build 0
+#OUTPUT Building %1% with %2% memory model
+#APPEND bin CLEAR
+#APPEND bin ADD * FROM UNZIPX
+#APPEND bin select search ($system.system.c%2%,[lib])
+#APPEND bin select runnable object on
+#APPEND bin select list * off
+#APPEND bin set heap 20 pages
+#APPEND bin set symbols on
+#APPEND bin set saveabend on
+#APPEND bin set inspect on
+#APPEND bin info unresolved *
+#APPEND bin BUILD %1%   !
+
+#SET ziptime [#FILEINFO /MODIFICATION/ %1%]
+[#IF ziptime < [#FILEINFO /MODIFICATION/ UNZIPX] |THEN|
+  #OUTPUT %1% is older than UNZIPX
+  #SET build -1
+]
+[#IF ziptime < [#FILEINFO /MODIFICATION/ [lib]] |THEN|
+  #OUTPUT %1% is older than [lib]
+  #SET build -1
+]
+[#IF build
+|THEN|
+  #OUTPUT %1% is out of date, re-building
+  BIND /NAME,INV BIN/
+  [#CASE [tacl^completioncode]
+  | 0         | #OUTPUT Bound %1% OK
+  | 1         | #OUTPUT %1%: BIND Failed with Warnings
+  | OTHERWISE | #OUTPUT %1%: BIND Failed with ERRORS !
+  ]
+|ELSE|
+  #OUTPUT %1% is up to date, no re-build required
+]
+
+#UNFRAME
+
+?section accel^file MACRO
+#FRAME
+#PUSH buf
+[#IF [#FILEINFO /MODIFICATION/ %1%]
+   > [#FILEINFO /MODIFICATION/ %2%]
+|THEN|
+  #OUTPUT %2% is older than %1%
+  #OUTPUT Accelerating %1% to %2%
+  AXCEL /IN [general_seg_subvol].DUMMY, OUTV buf/ %1%,%2%
+  #OUTPUTV buf
+  [#CASE [tacl^completioncode]
+  | 0         | #OUTPUT Accelerated %2% OK
+  | 1         | #OUTPUT %2%: AXCEL Failed with Warnings
+  | OTHERWISE | #OUTPUT %2%: AXCEL Failed with ERRORS !
+  ]
+|ELSE|
+  #OUTPUT %2% is up to date
+]
+
+#UNFRAME
+
+?section fup^license ROUTINE
+#FRAME
+#PUSH #DEFAULTS filename old^user current^user
+
+[#IF [#ARGUMENT /VALUE filename/ FILENAME]]
+
+#SET old^user [#USERNAME [#PROCESSINFO /PAID/]]
+#SETV current^user old^user
+[#LOOP |WHILE| current^user '<>' "SUPER.SUPER"
+               AND NOT [#INPUTEOF]
+|DO|
+  #OUTPUT Please log on as SUPER.SUPER (CTRL-Y aborts)
+  logon SUPER.SUPER
+  #SET current^user [#USERNAME [#PROCESSINFO /PAID/]]
+  #OUTPUT
+]
+
+[#IF current^user '=' "SUPER.SUPER" |THEN|
+  #OUTPUT Licensing [filename]
+  $SYSTEM.SYSTEM.FUP LICENSE [filename]
+]
+
+[#LOOP |WHILE| current^user '<>' old^user
+               AND NOT [#INPUTEOF]
+|DO|
+  #OUTPUT Please log on as [old^user] (CTRL-Y aborts)
+  logon [old^user]
+  #SET current^user [#USERNAME [#PROCESSINFO /PAID/]]
+  #OUTPUT
+]
+
+#UNFRAME
diff --git a/tandem/make b/tandem/make
new file mode 100644 (file)
index 0000000..f8a78ce
--- /dev/null
@@ -0,0 +1,110 @@
+?tacl routine
+#FRAME
+load /keep 1/ commacs
+
+#PUSH file prev memory OK model zip lib accel unlicensed licensed options
+#PUSH #DEFAULTS
+load /keep 1/ macros
+
+#SET OK -1
+
+[#IF [#ARGUMENT /VALUE memory/ KEYWORD /WORDLIST LARGE SMALL/ OTHERWISE ]]
+[#IF [#ARGUMENT /VALUE model/ KEYWORD /WORDLIST NOWIDE WIDE/ OTHERWISE ]]
+[#IF [#ARGUMENT /VALUE unlicensed/ KEYWORD /WORDLIST UNLICENSED/ OTHERWISE ]]
+
+[#IF [#EMPTYV memory] |THEN| #SET memory LARGE]
+[#IF [#EMPTYV model] |THEN| #SET model NOWIDE]
+
+[#IF model '=' "WIDE"
+|THEN|
+  #SET zip ZIPW
+|ELSE|
+  #SET zip ZIPL
+]
+#SET lib [zip]B
+#SET accel ZIP
+#SET options [options], [model]
+
+[#IF unlicensed '=' "UNLICENSED"
+|THEN|
+  #SET zip [zip]U
+  #SET accel [accel]U
+  #SET lib   [lib]U
+|ELSE|
+  #SET licensed LICENSED
+  #SET options [options], define [licensed]
+]
+
+#OUTPUT Pointer Model   : [model]
+#OUTPUT Memory Model    : [memory]
+#OUTPUT Axcel Object    : [accel]
+#OUTPUT Run Object      : [zip]
+#OUTPUT Library Object  : [lib]
+#OUTPUT Compile Options : [options]
+#OUTPUT
+
+#SET file [#FILENAMES /MAXIMUM 1/ *C]
+[#loop |while| NOT [#EMPTYV file]
+|do|
+  #SETV prev file
+  CC [file] $T.#ZIP [options]
+  [#IF [tacl^completioncode] > 1 |THEN| #set OK 0 ]
+  #SET file [#FILENAMES /MAXIMUM 1, PREVIOUS [prev]/ *C]
+]
+
+[#IF OK |THEN|
+  BBZIPLIB
+  [#IF [tacl^completioncode] > 0 |THEN| #SET OK 0]
+]
+
+#PUSH #PROCESSFILESECURITY
+VOLUME ,"NUNU"
+
+[#IF OK |THEN|
+  BBZIP [zip] [memory]
+  [#IF [tacl^completioncode] > 0 |THEN| #SET OK 0]
+]
+
+[#IF OK |THEN|
+  secure^file [accel] "UUUU" SUPER.DAVES
+  accel^file [zip] [accel]
+  [#IF [tacl^completioncode] > 0 |THEN| #SET OK 0]
+]
+
+[#IF OK
+  |THEN| #OUTPUT Successfully produced Accelerated Object [accel]
+         secure^file [accel] "UUUU" SUPER.DAVES
+         [#IF [#INTERACTIVE] |THEN|
+           [#IF licensed '=' "LICENSED" |THEN|
+             #OUTPUT [accel] will not run without being LICENSED
+             [#IF [#FILEINFO /LICENSED/ [accel]]
+             |THEN|
+               #OUTPUT [accel] already LICENSED
+             |ELSE|
+               [#IF [#MATCH Y* [#INPUT [accel] License [accel] ?]] |THEN|
+                 fup^license [accel]
+               ]
+             ]
+           ]
+         ]
+  |ELSE| #OUTPUT Failed to produce Accelerated Object [accel]
+]
+
+#OUTPUT Finished
+
+#OUTPUT Setting up additonal utilities
+== ZIPNOTE
+CC ZIPNOTEC $T.#ZIP [options]
+#SET zip ZIPNOTE
+#SET accel ZIPNOTE
+[#IF OK |THEN|
+  BBANY [zip] [memory]
+  [#IF [tacl^completioncode] > 0 |THEN| #SET OK 0]
+]
+[#IF OK |THEN|
+  secure^file [accel] "UUUU" SUPER.DAVES
+  accel^file [zip] [accel]
+  [#IF [tacl^completioncode] > 0 |THEN| #SET OK 0]
+]
+
+#UNFRAME
diff --git a/tandem/tandem.c b/tandem/tandem.c
new file mode 100644 (file)
index 0000000..291b9a0
--- /dev/null
@@ -0,0 +1,866 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ * routines common to TANDEM (ZIP and UNZIP)
+ */
+
+#include "zip.h"   /* This sets up ZIP / UNZIP define */
+
+#include <tal.h>
+#include "$system.zsysdefs.zsysc" nolist
+#include <cextdecs> nolist
+#include "tannsk.h"
+
+int isatty (fnum)
+int fnum;
+{
+  return 1;
+}
+
+/********************/
+/* Function in2ex() */
+/********************/
+
+char *in2ex(n)
+  char *n;              /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+  char *t;              /* pointer to internal */
+  char *p;              /* pointer to internal */
+  char *e;              /* pointer to internal */
+
+  if ((x = malloc(strlen(n) + 4)) == NULL)  /* + 4 for safety */
+    return NULL;
+  *x= '\0';
+
+  /* Junk pathname as requested */
+#ifdef UNZIP
+  if (uO.jflag && (t = strrchr(n, INTERNAL_DELIMITER)) != NULL)
+    ++t;
+  else
+    t = n;
+#endif /* UNZIP */
+#ifdef ZIP
+  if (!pathput)
+    t = last(n, INTERNAL_DELIMITER);
+  else
+    t = n;
+#endif /* ZIP */
+
+  while (*t != '\0') {  /* File part could be sys, vol, subvol or file */
+    if (*t == INTERNAL_DELIMITER) {    /* System, Volume or Subvol Name */
+      t++;
+      if (*t == INTERNAL_DELIMITER) {  /* System */
+        strcat(x, TANDEM_NODE_STR);
+        t++;
+      }
+      else
+        strcat(x, TANDEM_DELIMITER_STR);
+    }
+    p = strchr(t, INTERNAL_DELIMITER);
+    if (p == NULL)
+      break;
+    if ((e = strchr(t, DOS_EXTENSION)) == NULL)
+      e = p;
+    else
+      e = _min(e, p);
+    /* can't have Tandem name longer than 8 characters */
+    strncat(x, t, _min(MAXFILEPARTLEN, (e - t)));
+    t = p;
+  }
+
+  if ((e = strchr(t, DOS_EXTENSION)) == NULL)
+    strncat(x, t, _min(MAXFILEPARTLEN, strlen(t)));
+  else {
+    strncat(x, t, _min(MAXFILEPARTLEN, (e - t)));
+    strcat(x, TANDEM_EXTENSION_STR);
+    strcat(x, e+1);  /* no restriction on extension length as its virtual*/
+  }
+
+  return x;
+}
+
+void zexit(status)
+  int status;
+{
+  terminate_program (0,0,status,,,);   /* Exit(>0) creates saveabend files */
+}
+
+
+#ifdef fopen
+#  undef fopen
+#endif
+
+FILE *zipopen(fname, opt)
+const char *fname;
+const char *opt;
+{
+  int fdesc,fnum,err;
+
+#ifdef ZIP
+  #define alist_items 1
+  #define vlist_bytes 2
+  short alist[alist_items]={42};
+  unsigned short vlist[alist_items]={NSK_ZIPFILECODE};
+  short extra, *err_item=&extra;
+#endif /* ZIP */
+
+  if (strcmp(opt,FOPW) == 0)
+    if ((fdesc = creat(fname,,100,500)) != -1){
+      fnum = fdtogfn (fdesc);
+      err = (SETMODE (fnum, SET_FILE_BUFFERSIZE, TANDEM_BLOCKSIZE) != CCE);
+      err = (SETMODE (fnum, SET_FILE_BUFFERED, 0, 0) != CCE);
+      err = (SETMODE (fnum, SET_FILE_BUFFERED, 0, 1) != CCE);
+      err = close(fdesc);
+#ifdef ZIP
+      err = FILE_ALTERLIST_((char *)fname,
+                            (short)(strlen(fname)),
+                            alist,
+                            alist_items,
+                            vlist,
+                            vlist_bytes,
+                            ,
+                            err_item);
+#endif /* ZIP */
+    };
+
+  return fopen(fname,opt);
+}
+#define fopen zipopen
+
+#ifdef putc
+#  undef putc
+#endif
+
+int zputc(ch, fptr)
+  int ch;
+  FILE *fptr;
+{
+  int err;
+  err = putc(ch,fptr);
+  fflush(fptr);
+  return err;
+}
+#define putc zputc
+
+#ifdef LICENSED
+_tal _priv short FILE_CHANGELABEL_ (
+ short,          /* IN */
+ short,          /* IN */
+ const short _far *    /* IN */
+ );
+
+_c _callable int changelabel OF((short, const short *, const short *));
+
+_c _callable int changelabel(fnum, modtime, actime)
+  short fnum;
+  const short *modtime;
+  const short *actime;
+{
+  int err;
+
+  err = FILE_CHANGELABEL_(fnum, 16, modtime);
+  if (!err)
+    err = FILE_CHANGELABEL_(fnum, 17, actime);
+  return err;
+}
+
+int islicensed(void)
+{
+  #define plist_items 1
+  #define plist_size 10
+
+  short myphandle[ZSYS_VAL_PHANDLE_WLEN];
+  short licensetag[plist_items] = {37};
+  short licensed[plist_size];
+  short maxlen = plist_size;
+  short items = plist_items;
+  short resultlen[1], err;
+
+  err = PROCESSHANDLE_NULLIT_(myphandle);
+
+  if (!err)
+    err = PROCESS_GETINFO_(myphandle);
+
+  if (!err)
+    err = PROCESS_GETINFOLIST_(/*cpu*/,
+                               /*pin*/,
+                               /*nodename*/,
+                               /*nodenamelen*/,
+                               myphandle,
+                               licensetag,
+                               items,
+                               licensed,
+                               maxlen,
+                               resultlen
+                              );
+
+  if (err != 0)
+    return 0;
+  else
+    return licensed[0];
+}
+#endif /* LICENSED */
+
+int utime(file, time)
+  const char *file;
+  const ztimbuf *time;
+{
+#ifdef LICENSED
+  int result, err;
+  union timestamp_ov {
+    long long fulltime;
+    short wordtime[4];
+  };
+  union timestamp_ov lasttime, opentime;
+  struct tm *modt, *opent;
+  short datetime[8], errormask[1];
+  short len, fnum, access, exclus, options;
+  char fname[FILENAME_MAX + 1];
+  short extension;
+  char ext[EXTENSION_MAX + 1];
+
+  if (islicensed() ) {
+    /* Attempt to update file label */
+    modt = gmtime( &time->modtime );
+
+    datetime[0] = modt->tm_year + 1900;
+    datetime[1] = modt->tm_mon + 1;
+    datetime[2] = modt->tm_mday;
+    datetime[3] = modt->tm_hour;
+    datetime[4] = modt->tm_min;
+    datetime[5] = modt->tm_sec;
+    datetime[6] = datetime[7] = 0;
+    errormask[0] = 0;
+    lasttime.fulltime = COMPUTETIMESTAMP (datetime, errormask);
+
+    opent = gmtime( &time->actime );
+
+    datetime[0] = opent->tm_year + 1900;
+    datetime[1] = opent->tm_mon + 1;
+    datetime[2] = opent->tm_mday;
+    datetime[3] = opent->tm_hour;
+    datetime[4] = opent->tm_min;
+    datetime[5] = opent->tm_sec;
+    datetime[6] = datetime[7] = 0;
+    errormask[0] = 0;
+    opentime.fulltime = COMPUTETIMESTAMP (datetime, errormask);
+
+    /* Remove any (pseudo) file extension */
+    extension = parsename (file,fname,ext);
+    len = strlen(fname);
+
+    access = NSK_WRONLY;
+    exclus = NSK_SHARED;
+    options = NSK_NOUPDATEOPENTIME;
+
+    extension = parsename (file,fname,ext);
+    len = strlen(fname);
+
+    err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);
+    result = changelabel(fnum,lasttime.wordtime,opentime.wordtime);
+    err = FILE_CLOSE_(fnum);
+    return result;
+  }
+  return -1;
+#else  /* !LICENSED */
+  return 0;             /* "no error", to suppress annoying failure messages */
+#endif  /* ?LICENSED */
+}
+
+/* TANDEM version of chmod() function */
+
+int chmod(file, unix_sec)
+  const char *file;
+  mode_t unix_sec;
+{
+  FILE *stream;
+  struct nsk_sec_type {
+    unsigned progid : 1;
+    unsigned clear  : 1;
+    unsigned null   : 2;
+    unsigned read   : 3;
+    unsigned write  : 3;
+    unsigned execute: 3;
+    unsigned purge  : 3;
+  };
+  union nsk_sec_ov {
+    struct nsk_sec_type bit_ov;
+    short int_ov;
+  };
+  union nsk_sec_ov nsk_sec;
+  short fnum, err, nsk_sec_int;
+  short len, access, exclus, extension, options;
+  char fname[FILENAME_MAX + 1];
+  char ext[EXTENSION_MAX + 1];
+
+  nsk_sec.bit_ov.progid = 0;
+  nsk_sec.bit_ov.clear  = 0;
+  nsk_sec.bit_ov.null   = 0;
+
+  /*  4="N", 5="C", 6="U", 7="-"   */
+
+  if (unix_sec & S_IROTH) nsk_sec.bit_ov.read = 4;
+  else if (unix_sec & S_IRGRP) nsk_sec.bit_ov.read = 5;
+  else if (unix_sec & S_IRUSR) nsk_sec.bit_ov.read = 6;
+  else nsk_sec.bit_ov.read = 7;
+
+  if (unix_sec & S_IWOTH) nsk_sec.bit_ov.write = 4;
+  else if (unix_sec & S_IWGRP) nsk_sec.bit_ov.write = 5;
+  else if (unix_sec & S_IWUSR) nsk_sec.bit_ov.write = 6;
+  else nsk_sec.bit_ov.write = 7;
+
+  if (unix_sec & S_IXOTH) nsk_sec.bit_ov.execute = 4;
+  else if (unix_sec & S_IXGRP) nsk_sec.bit_ov.execute = 5;
+  else if (unix_sec & S_IXUSR) nsk_sec.bit_ov.execute = 6;
+  else nsk_sec.bit_ov.execute = 7;
+
+  nsk_sec.bit_ov.purge = nsk_sec.bit_ov.write;
+
+  nsk_sec_int = nsk_sec.int_ov;
+
+  access = NSK_RDONLY;
+  exclus = NSK_SHARED;
+  options = NSK_NOUPDATEOPENTIME;
+
+  extension = parsename (file,fname,ext);
+  len = strlen(fname);
+
+  err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);
+  err = (SETMODE(fnum, SET_FILE_SECURITY, nsk_sec_int) != CCE);
+  err = FILE_CLOSE_(fnum);
+
+  return (err != 0 ? -1 : 0);
+}
+
+/* TANDEM version of chown() function */
+
+int chown(file, uid, gid)
+  const char *file;
+  uid_t uid;
+  gid_t gid;
+{
+  FILE *stream;
+  struct nsk_own_type {
+    unsigned group  : 8;
+    unsigned user   : 8;
+  };
+  union nsk_own_ov {
+    struct nsk_own_type bit_ov;
+    short int_ov;
+  };
+  union nsk_own_ov nsk_own;
+  short fnum, err, nsk_own_int;
+  short len, access, exclus, extension, options;
+  char fname[FILENAME_MAX + 1];
+  char ext[EXTENSION_MAX + 1];
+
+  nsk_own.bit_ov.group = gid;
+  nsk_own.bit_ov.user  = uid;
+
+  nsk_own_int = nsk_own.int_ov;
+
+  access = NSK_RDONLY;
+  exclus = NSK_SHARED;
+  options = NSK_NOUPDATEOPENTIME;
+
+  extension = parsename (file,fname,ext);
+  len = strlen(fname);
+
+  err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);
+  err = (SETMODE(fnum, SET_FILE_OWNER, nsk_own_int) != CCE);
+  err = FILE_CLOSE_(fnum);
+  return (err != 0 ? -1 : 0);
+}
+
+/* TANDEM version of getch() - non-echo character reading */
+int zgetch(void)
+{
+  char ch;
+  int f,fnum,count, rlen,wlen, err;
+
+  rlen = 1;
+  wlen = 0;
+  f = fileno(stdin);
+  fnum = fdtogfn (f);
+  #define ECHO_MODE 20
+  err = (SETMODE(fnum, ECHO_MODE, 0) != CCE);
+  err = (READX(fnum, &ch, rlen, (short *) &count) != CCE);
+  err = (SETMODE(fnum, ECHO_MODE, 1) != CCE);
+
+  if (err)
+    if (err != 1)
+      return EOF;
+    else
+      ch = 'q';
+  else
+    if (count == 0)
+      ch = '\r';
+
+  return (int)ch;
+}
+
+/* TANDEM version of stat() function */
+
+time_t gmt_to_time_t (gmt)
+  long long *gmt;
+{
+  #define GMT_TO_LCT 0
+  #define GMT_TO_LST 1
+
+  struct tm temp_tm;
+  short  date_time[8];
+  long   julian_dayno;
+  long long lct, lst, itime;
+  short  err[1], type;
+
+  type = GMT_TO_LCT;
+  lct = CONVERTTIMESTAMP(*gmt, type,, err);
+
+  if (!err[0]) {
+    type = GMT_TO_LST;
+    lst = CONVERTTIMESTAMP(*gmt, type,, err);
+  }
+
+  itime = (err[0] ? *gmt : lct);
+  /* If we have no DST in force then make sure we give it a value,
+     else mktime screws up if we set the isdst flag to -1 */
+  temp_tm.tm_isdst = (err[0] ? 0 : ((lct == lst) ? 0 : 1));
+
+  julian_dayno = INTERPRETTIMESTAMP(itime, date_time);
+
+  temp_tm.tm_sec   = date_time[5];
+  temp_tm.tm_min   = date_time[4];
+  temp_tm.tm_hour  = date_time[3];
+  temp_tm.tm_mday  = date_time[2];
+  temp_tm.tm_mon   = date_time[1] - 1;     /* C's so sad */
+  temp_tm.tm_year  = date_time[0] - 1900;  /* it's almost funny */
+
+  return (mktime(&temp_tm));
+}
+
+short parsename(srce, fname, ext)
+  const char *srce;
+  char *fname;
+  char *ext;
+{
+  /* As a way of supporting DOS extensions from Tandem we look for a space
+     separated extension string after the Guardian filename
+     e.g. ZIP ZIPFILE "$DATA4.TESTING.INVOICE TXT"
+  */
+
+  char *fstart;
+  char *fptr;
+  short extension = 0;
+
+  *fname = *ext = '\0';  /* set to null string */
+
+  fstart = (char *) srce;
+
+  if ((fptr = strrchr(fstart, TANDEM_EXTENSION)) != NULL) {
+    extension = 1;
+
+    fptr++;
+    strncat(ext, fptr, _min(EXTENSION_MAX, strlen(fptr)));
+
+    fptr = strchr(fstart, TANDEM_EXTENSION);  /* End of filename */
+    strncat(fname, fstart, _min(FILENAME_MAX, (fptr - fstart)));
+  }
+  else {
+    /* just copy string */
+    strncat(fname, srce, _min(FILENAME_MAX, strlen(srce)));
+  }
+
+  return extension;
+}
+
+int stat(n, s)
+  const char *n;
+  struct stat *s;
+{
+  #define ilist_items 26
+  #define klist_items 4
+  #define slist_items 3
+  #define ulist_items 1
+  #define flist_size 100
+
+  short err, i, extension;
+  char fname[FILENAME_MAX + 1];
+  short fnamelen;
+  char ext[EXTENSION_MAX + 1];
+
+                         /* #0  #1  #2  #3  #4  #5  #6  #7  #8  #9 */
+  short ilist[ilist_items]={56,144, 54,142, 58, 62, 60, 41, 42, 44,
+                            50, 51, 52, 61, 63, 66, 67, 70, 72, 73,
+                            74, 75, 76, 77, 78, 79                 };
+  short ilen[ilist_items] ={ 4,  4,  4,  2,  1,  2,  1,  1,  1,  1,
+                             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+                             1,  1,  1,  1,  1,  1                 };
+  short ioff[ilist_items];
+
+                         /* #0  #1  #2  #3  #4  #5  #6  #7  #8  #9 */
+  short klist[klist_items]={45, 46, 68, 69                         };
+  short klen[klist_items] ={ 1,  1,  1,  1                         };
+  short koff[klist_items];
+
+                         /* #0  #1  #2  #3  #4  #5  #6  #7  #8  #9 */
+  short slist[slist_items]={43, 80, 90                             };
+  short slen[slist_items] ={ 1,  1,  1                             };
+  short soff[slist_items];
+
+                         /* #0  #1  #2  #3  #4  #5  #6  #7  #8  #9 */
+  short ulist[ulist_items]={65                                     };
+  short ulen[ulist_items] ={ 1                                     };
+  short uoff[ulist_items];
+
+  short flist[flist_size];
+  short extra[2];
+  short *rlen=&extra[0];
+  short *err_item=&extra[1];
+  unsigned short *fowner;
+  unsigned short *fprogid;
+  char *fsec;
+
+  nsk_stat_ov *nsk_ov;
+  nsk_file_attrs *nsk_attr;
+
+  short end, count, kind, level, options, searchid;
+  short info[5];
+
+  /* Initialise stat structure */
+  s->st_dev = _S_GUARDIANOBJECT;
+  s->st_ino = 0;
+  s->st_nlink = 0;
+  s->st_rdev = 0;
+  s->st_uid = s->st_gid = 0;
+  s->st_size = 0;
+  s->st_atime = s->st_ctime = s->st_mtime = 0;
+  s->st_reserved[0] = 0;
+  s->st_reserved[1] = 0;
+  s->st_reserved[2] = 0;
+  nsk_ov = (nsk_stat_ov *)&s->st_reserved[0];
+  nsk_attr = (nsk_file_attrs *)&nsk_ov->ov.nsk_ef_start;
+
+  /* Check to see if name contains a (pseudo) file extension */
+  extension = parsename (n,fname,ext);
+
+  fnamelen = strlen(fname);
+
+  options = 3; /* Allow Subvols and Templates */
+  err = FILENAME_SCAN_( fname,
+                        fnamelen,
+                        &count,
+                        &kind,
+                        &level,
+                        options
+                      );
+
+  /* allow kind == 2 (DEFINE names) */
+  if (err != 0) return -1;
+
+  if (kind == 1 || (kind == 0 && level < 2)) {
+    /* Pattern, Subvol Name or One part Filename - lets see if it exists */
+    err = FILENAME_FINDSTART_ ( &searchid,
+                                fname,
+                                fnamelen,
+                                ,
+                                DISK_DEVICE
+                              );
+
+    if (err != 0) {
+      end = FILENAME_FINDFINISH_ ( searchid );
+      return -1;
+    }
+
+    err = FILENAME_FINDNEXT_ ( searchid,
+                               fname,
+                               FILENAME_MAX,
+                               &fnamelen,
+                               info
+                              );
+    end = FILENAME_FINDFINISH_ ( searchid );
+
+    if (err != 0)
+      return -1;  /* Non existing template, subvol or file */
+
+    if (kind == 1 || info[2] == -1) {
+      s->st_mode = S_IFDIR;    /* Its an existing template or directory */
+      return 0;
+    }
+
+    /* Must be a real file so drop to code below to get info on it */
+  }
+
+  err = FILE_GETINFOLISTBYNAME_( fname,
+                                 fnamelen,
+                                 ilist,
+                                 ilist_items,
+                                 flist,
+                                 flist_size,
+                                 rlen,
+                                 err_item
+                               );
+  if (err != 0) return -1;
+
+  ioff[0] = 0;
+
+  /*  Build up table of offets into result list */
+  for (i=1; i < ilist_items; i++)
+    ioff[i] = ioff[i-1] + ilen[i-1];
+
+  /* Set up main stat fields */
+
+  /* Setup timestamps */
+  s->st_atime = gmt_to_time_t ((long long *)&flist[ioff[0]]);
+  s->st_mtime = s->st_ctime = gmt_to_time_t ((long long *)&flist[ioff[1]]);
+  nsk_ov->ov.creation_time = gmt_to_time_t ((long long *)&flist[ioff[2]]);
+
+  s->st_size = *(off_t *)&flist[ioff[3]];
+
+  fowner = (unsigned short *)&flist[ioff[4]];
+  s->st_uid = *fowner & 0x00ff;
+  s->st_gid = *fowner >> 8;
+
+  /* Note that Purge security (fsec[3]) in NSK has no relevance to stat() */
+  fsec = (char *)&flist[ioff[5]];
+  fprogid = (unsigned short *)&flist[ioff[6]];
+
+  s->st_mode = S_IFREG |  /* Regular File */
+  /*  Parse Read Flag */
+               ((fsec[0] & 0x03) == 0x00 ? S_IROTH : 0) |
+               ((fsec[0] & 0x02) == 0x00 ? S_IRGRP : 0) |
+               ((fsec[0] & 0x03) != 0x03 ? S_IRUSR : 0) |
+  /*  Parse Write Flag */
+               ((fsec[1] & 0x03) == 0x00 ? S_IWOTH : 0) |
+               ((fsec[1] & 0x02) == 0x00 ? S_IWGRP : 0) |
+               ((fsec[1] & 0x03) != 0x03 ? S_IWUSR : 0) |
+  /*  Parse Execute Flag */
+               ((fsec[2] & 0x03) == 0x00 ? S_IXOTH : 0) |
+               ((fsec[2] & 0x02) == 0x00 ? S_IXGRP : 0) |
+               ((fsec[2] & 0x03) != 0x03 ? S_IXUSR : 0) |
+  /*  Parse Progid */
+               (*fprogid == 1 ? (S_ISUID | S_ISGID) : 0) ;
+
+  /* Set up NSK additional stat fields */
+  nsk_attr->progid   = (unsigned) flist[ioff[6]];
+  nsk_attr->filetype = (unsigned) flist[ioff[7]];
+  nsk_attr->filecode = (unsigned) flist[ioff[8]];
+  nsk_attr->block    = (unsigned short) flist[ioff[9]];
+  nsk_attr->primext  = (unsigned short) flist[ioff[10]];
+  nsk_attr->secext   = (unsigned short) flist[ioff[11]];
+  nsk_attr->maxext   = (unsigned short) flist[ioff[12]];
+  nsk_attr->flags.clearonpurge = (unsigned) flist[ioff[13]];
+  nsk_attr->licensed     = (unsigned) flist[ioff[14]];
+  nsk_attr->flags.audited      = (unsigned) flist[ioff[15]];
+  nsk_attr->flags.acompress    = (unsigned) flist[ioff[16]];
+  nsk_attr->flags.refresheof   = (unsigned) flist[ioff[17]];
+  nsk_attr->flags.buffered     = (unsigned) (flist[ioff[18]] == 0 ? 1 : 0);
+  nsk_attr->flags.verified     = (unsigned) flist[ioff[19]];
+  nsk_attr->flags.serial       = (unsigned) flist[ioff[20]];
+  nsk_attr->flags.crashopen    = (unsigned) flist[ioff[22]];
+  nsk_attr->flags.rollforward  = (unsigned) flist[ioff[23]];
+  nsk_attr->flags.broken       = (unsigned) flist[ioff[24]];
+  nsk_attr->flags.corrupt      = (unsigned) flist[ioff[25]];
+  nsk_attr->fileopen     = (unsigned) flist[ioff[21]];
+
+
+  if (nsk_attr->filetype == NSK_UNSTRUCTURED) {
+    /* extra info for Unstructured files */
+    err = FILE_GETINFOLISTBYNAME_( fname,
+                                   fnamelen,
+                                   ulist,
+                                   ulist_items,
+                                   flist,
+                                   flist_size,
+                                   rlen,
+                                   err_item
+                                 );
+    if (err != 0) return -1;
+
+    uoff[0] = 0;
+
+    /*  Build up table of offets into result list */
+    for (i=1; i < ulist_items; i++)
+      uoff[i] = uoff[i-1] + ulen[i-1];
+  }
+  else {
+    /* extra info for Structured files */
+    err = FILE_GETINFOLISTBYNAME_( fname,
+                                   fnamelen,
+                                   slist,
+                                   slist_items,
+                                   flist,
+                                   flist_size,
+                                   rlen,
+                                   err_item
+                                 );
+    if (err != 0) return -1;
+
+    soff[0] = 0;
+
+    /*  Build up table of offets into result list */
+    for (i=1; i < slist_items; i++)
+      soff[i] = soff[i-1] + slen[i-1];
+
+    nsk_attr->reclen   = (unsigned) flist[soff[0]];
+    nsk_attr->flags.secpart   = (unsigned) flist[soff[1]];
+    nsk_attr->flags.primpart  = (unsigned)
+     ( (flist[soff[2]] > 0 && nsk_attr->flags.secpart == 0) ? 1 : 0 );
+
+    if (nsk_attr->filetype == NSK_KEYSEQUENCED) {
+      /* extra info for Key Sequenced files */
+      err = FILE_GETINFOLISTBYNAME_( fname,
+                                     fnamelen,
+                                     klist,
+                                     klist_items,
+                                     flist,
+                                     flist_size,
+                                     rlen,
+                                     err_item
+                                   );
+      if (err != 0) return -1;
+
+      koff[0] = 0;
+
+      /*  Build up table of offets into result list */
+      for (i=1; i < slist_items; i++)
+        koff[i] = koff[i-1] + klen[i-1];
+
+      nsk_attr->keyoff   = (unsigned) flist[koff[0]];
+      nsk_attr->keylen   = (unsigned) flist[koff[1]];
+      nsk_attr->flags.dcompress = (unsigned) flist[koff[2]];
+      nsk_attr->flags.icompress = (unsigned) flist[koff[3]];
+    }
+  }
+
+  return 0;
+}
+
+#ifndef SFX
+/* TANDEM Directory processing */
+
+DIR *opendir(const char *dirname)
+{
+   short i, resolve;
+   char sname[FILENAME_MAX + 1];
+   short snamelen;
+   char fname[FILENAME_MAX + 1];
+   short fnamelen;
+   char *p;
+   short searchid, err, end;
+   struct dirent *entry;
+   DIR *dirp;
+   char ext[EXTENSION_MAX + 1];
+   short extension;
+
+   extension = parsename(dirname, sname, ext);
+   snamelen = strlen(sname);
+
+   /*  First we work out how detailed the template is...
+    *  e.g. If the template is DAVES*.* we want the search result
+    *       in the same format
+    */
+
+   p = sname;
+   i = 0;
+   while ((p = strchr(p, TANDEM_DELIMITER)) != NULL){
+     i++;
+     p++;
+   };
+   resolve = 2 - i;
+
+   /*  Attempt to start a filename template */
+   err = FILENAME_FINDSTART_ ( &searchid,
+                               sname,
+                               snamelen,
+                               resolve,
+                               DISK_DEVICE
+                             );
+   if (err != 0) {
+     end = FILENAME_FINDFINISH_(searchid);
+     return NULL;
+   }
+
+   /* Create DIR structure */
+   if ((dirp = malloc(sizeof(DIR))) == NULL ) {
+     end = FILENAME_FINDFINISH_(searchid);
+     return NULL;
+   }
+   dirp->D_list = dirp->D_curpos = NULL;
+   strcpy(dirp->D_path, dirname);
+
+   while ((err = FILENAME_FINDNEXT_(searchid,
+                                    fname,
+                                    FILENAME_MAX,
+                                    &fnamelen
+                                   )
+           ) == 0 ){
+     /*  Create space for entry */
+     if ((entry = malloc (sizeof(struct dirent))) == NULL) {
+       end = FILENAME_FINDFINISH_(searchid);
+       return NULL;
+     }
+
+     /*  Link to last entry */
+     if (dirp->D_curpos == NULL)
+       dirp->D_list = dirp->D_curpos = entry;  /* First name */
+     else {
+       dirp->D_curpos->d_next = entry;         /* Link */
+       dirp->D_curpos = entry;
+     };
+     /* Add directory entry */
+     *dirp->D_curpos->d_name = '\0';
+     strncat(dirp->D_curpos->d_name,fname,fnamelen);
+     if (extension) {
+       strcat(dirp->D_curpos->d_name,TANDEM_EXTENSION_STR);
+       strcat(dirp->D_curpos->d_name,ext);
+     };
+     dirp->D_curpos->d_next = NULL;
+   };
+
+   end = FILENAME_FINDFINISH_(searchid);
+
+   if (err == 1) {  /*  Should return EOF at end of search */
+     dirp->D_curpos = dirp->D_list;        /* Set current pos to start */
+     return dirp;
+   }
+   else
+     return NULL;
+}
+
+struct dirent *readdir(DIR *dirp)
+{
+   struct dirent *cur;
+
+   cur = dirp->D_curpos;
+   dirp->D_curpos = dirp->D_curpos->d_next;
+   return cur;
+}
+
+void rewinddir(DIR *dirp)
+{
+   dirp->D_curpos = dirp->D_list;
+}
+
+int closedir(DIR *dirp)
+{
+   struct dirent *node;
+
+   while (dirp->D_list != NULL) {
+      node = dirp->D_list;
+      dirp->D_list = dirp->D_list->d_next;
+      free( node );
+   }
+   free( dirp );
+   return 0;
+}
+
+#endif /* !SFX */
diff --git a/tandem/tandem.h b/tandem/tandem.h
new file mode 100644 (file)
index 0000000..7868fdd
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __tandem_h   /* prevent multiple inclusions */
+#define __tandem_h
+
+#define TANDEM       /* better than __TANDEM */
+
+/* LICENSED define now supplied by compile time option (MAKE) */
+
+#define NO_UNISTD_H
+#define NO_RMDIR
+#define NO_MKTEMP
+#ifdef ZIP
+#  define USE_CASE_MAP
+#  define USE_EF_UT_TIME
+#endif /* ZIP */
+
+/* Include file for TANDEM */
+
+#ifndef NULL
+#  define NULL 0
+#endif
+
+#include <time.h>               /* the usual non-BSD time functions */
+#include <stdio.h>
+#include <sysstat.h>
+#include <unistd.h>
+#include <errno.h>
+
+#define PASSWD_FROM_STDIN
+                  /* Kludge until we know how to open a non-echo tty channel */
+
+#define NSK_UNSTRUCTURED   0
+#define NSK_RELATIVE       1
+#define NSK_ENTRYSEQUENCED 2
+#define NSK_KEYSEQUENCED   3
+#define NSK_OBJECTFILECODE 100
+#define NSK_EDITFILECODE   101
+#define NSK_ZIPFILECODE    1001
+#define TANDEM_BLOCKSIZE   4096
+#define MAX_NORMAL_READ    4096
+#define MAX_EDIT_READ      255
+#define MAX_LARGE_READ        57344
+#define MAX_LARGE_READ_EXPAND 30720
+
+#define MAXFILEPARTLEN     8
+#define MAXPATHLEN         128
+#define EXTENSION_MAX      3
+/* FILENAME_MAX is defined in stdio.h */
+
+#define EXIT zexit     /*  To stop creation of Abend files */
+#define RETURN zexit   /*  To stop creation of Abend files */
+#define fopen zipopen  /*  To allow us to set extent sizes */
+#define putc zputc     /*  To allow us to auto flush  */
+
+
+/* Prototype function declarations */
+
+void zexit (int);
+
+FILE *zipopen(
+const char *,
+const char *
+);
+
+int zputc(
+int,
+FILE *
+);
+
+int zgetch (void);
+
+short parsename(
+  const char *,
+  char *,
+  char *
+);
+
+int islicensed (void);
+
+time_t gmt_to_time_t (long long *);
+
+/* End of prototype function declarations */
+
+
+#define FOPR "rb"
+#define FOPM "r+"
+#define FOPW "wb"
+#define FOPWT "w"
+
+#define CBSZ 0x10000  /* Was used for both fcopy and file_read.        */
+                      /* Created separate define (SBSZ) for file_read  */
+                      /* fcopy param is type size_t (unsigned long)    */
+                      /* For Guardian we choose a multiple of 4K       */
+
+#define ZBSZ 0x10000  /* This is used in call to setvbuf, 64K seems to work  */
+                      /* in all memory models. Again it is an unsigned long  */
+                      /* For Guardian we choose a multiple of 4K             */
+
+#ifndef __INT32
+#define SBSZ 0x0e000  /* Maximum of size unsigned (int). Only used in STORE  */
+                      /* method.  We can use up to 56K bytes thanks to large */
+                      /* transfer mode.  Note WSIZE is limited to 32K, which */
+                      /* limits the DEFLATE read size to same value.         */
+#else
+#define SBSZ 0x10000  /* WIDE model so we can use 64K                        */
+#endif /* __INT32 */
+
+#define NAMELEN FILENAME_MAX+1+EXTENSION_MAX   /* allow for space extension */
+
+struct dirent {
+   struct dirent *d_next;
+   char   d_name[NAMELEN+1];
+};
+
+typedef struct _DIR {
+   struct  dirent *D_list;
+   struct  dirent *D_curpos;
+   char            D_path[NAMELEN+1];
+} DIR;
+
+DIR *          opendir(const char *dirname);
+struct dirent *readdir(DIR *dirp);
+void           rewinddir(DIR *dirp);
+int            closedir(DIR *dirp);
+char *         readd(DIR *dirp);
+
+#define DISK_DEVICE         3
+
+/* SETMODE Literals */
+#define SET_FILE_SECURITY   1
+#define SET_FILE_OWNER      2
+#define SET_FILE_BUFFERED   90
+#define SET_FILE_BUFFERSIZE 93
+#define SET_LARGE_TRANSFERS 141
+
+/* FILE_OPEN_ Literals */
+#define NSK_RDWR             0
+#define NSK_RDONLY           1
+#define NSK_WRONLY           2
+#define NSK_APPEND           3
+#define NSK_SHARED           0
+#define NSK_EXCLUSIVE        1
+#define NSK_PROCESSEXCLUSIVE 2
+#define NSK_PROTECTED        3
+#define NSK_UNSTRUCTUREDACCESS 0x8000
+#define NSK_NOUPDATEOPENTIME   0x2000
+
+#define NSK_NO_DELIMITER        0x0001
+#define NSK_USE_FF_DELIMITER    0x0002
+#define NSK_SPACE_FILL          0x0004
+#define NSK_TRIM_TRAILING_SPACE 0x0008
+#define NSK_LARGE_READ_EXPAND   0x0100     /* use smaller value for Expand */
+
+#define DOS_EXTENSION      '.'
+#define TANDEM_EXTENSION   ' '
+#define TANDEM_DELIMITER   '.'
+#define TANDEM_NODE        '\\'
+#define INTERNAL_DELIMITER '/'
+#define INTERNAL_NODE      '//'
+#define TANDEM_WILD_1      '*'
+#define TANDEM_WILD_2      '?'
+
+#define DOS_EXTENSION_STR      "."
+#define TANDEM_EXTENSION_STR   " "
+#define TANDEM_DELIMITER_STR   "."
+#define TANDEM_NODE_STR        "\\"
+#define INTERNAL_DELIMITER_STR "/"
+#define INTERNAL_NODE_STR      "//"
+
+/* Use 'spare' area at end of stat structure to hold additional Tandem/NSK
+   file details. Initially used to hold Creation time, now also holds most
+   Enscribe details */
+
+struct nsk_stat_reserved
+{
+  int64_t spare[3];
+};
+
+typedef struct
+{
+  unsigned group   : 8;
+  unsigned user    : 8;
+} nsk_owner;
+
+typedef struct
+{
+  unsigned buffered    : 1;
+  unsigned audited     : 1;
+  unsigned acompress   : 1;
+  unsigned icompress   : 1;
+  unsigned dcompress   : 1;
+  unsigned oddunstr    : 1;
+  unsigned verified    : 1;
+  unsigned serial      : 1;
+  unsigned refresheof  : 1;
+  unsigned broken      : 1;
+  unsigned corrupt     : 1;
+  unsigned primpart    : 1;
+  unsigned secpart     : 1;
+  unsigned crashopen   : 1;
+  unsigned rollforward : 1;
+  unsigned clearonpurge: 1;
+} nsk_file_flags;
+
+typedef struct
+{
+  unsigned short filecode;  /* 16 */
+  unsigned short block;     /* 16 */  /* Allow of block > 4096 one day ! */
+  nsk_file_flags flags;     /* 16 */
+  nsk_owner owner;          /* 16 */
+  unsigned short primext;   /* 16 */
+  unsigned short secext;    /* 16 */
+  unsigned maxext    : 10;
+  unsigned read      : 3;
+  unsigned write     : 3;
+  unsigned execute   : 3;
+  unsigned delete    : 3;
+  unsigned licensed  : 1;
+  unsigned progid    : 1;
+  unsigned keylen    : 8;
+  unsigned           : 5;
+  unsigned keyoff    : 11;
+  unsigned           : 1;
+  unsigned filetype  : 2;
+  unsigned fileopen  : 1;
+  unsigned reclen    : 12;
+} nsk_file_attrs;
+
+struct nsk_stat_overlay
+{
+  time_t creation_time;  /* 32 */
+  char   nsk_ef_start;   /* Start of ef region */
+};
+
+typedef union
+{
+  struct nsk_stat_reserved reserved;
+  struct nsk_stat_overlay  ov;
+} nsk_stat_ov;
+
+#endif /* !__tandem_h */
diff --git a/tandem/tannsk.h b/tandem/tannsk.h
new file mode 100644 (file)
index 0000000..122d8ed
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/*
+ *  Header declaration(s) which are forced to go after earlier includes
+ */
+
+#ifndef __tannsk_h   /* prevent multiple inclusions */
+#define __tannsk_h
+
+/* ztimbuf is declared in zip\tailor.h after include of tandem.h */
+int utime (const char *, const ztimbuf *);
+
+#endif /* !__tannsk_h */
diff --git a/tandem/tanzip.c b/tandem/tanzip.c
new file mode 100644 (file)
index 0000000..dbd7233
--- /dev/null
@@ -0,0 +1,637 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ * routines only used by TANDEM ZIP
+ */
+
+#include "zip.h"
+#include <tal.h>
+#include "$system.zsysdefs.zsysc" nolist
+#include <cextdecs> nolist
+#include "tannsk.h"
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+void version_local()
+{
+    static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
+#if 0
+    char buf[40];
+#endif
+
+    printf(CompiledWith,
+
+#ifdef __GNUC__
+      "gcc ", __VERSION__,
+#else
+#  if 0
+      "cc ", (sprintf(buf, " version %d", _RELEASE), buf),
+#  else
+      "unknown compiler", "",
+#  endif
+#endif
+
+      "Tandem/NSK", "",
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+      );
+
+} /* end function version_local() */
+
+  int Bflag = 0;            /* Special formatting options for Tandem        */
+                            /* Bit 0 = Add delimiter (0 = Yes, 1 = No)      */
+                            /* Bit 1 = Delimiter Type (0 = CR/LF, 1 = LF)   */
+                            /* Bit 2 = Space Fill records (0 = No, 1 = Yes) */
+                            /* Bit 3 = Trim trailing space(0 = No, 1 = Yes) */
+                            /* Thus, default is to add CR/LF, no padding    */
+                            /* Bit 8 = Use 'safe' large read size (Expand)  */
+  char nsk_delim[2] = {'\r', '\n'}; /* CR/LF */
+  int nsk_delim_len = 2;
+  int nsk_space_fill = 0;   /* 0 = No, 1 = Yes          */
+  int nsk_trim_space = 0;   /* 0 = No, 1 = Yes          */
+  unsigned short nsk_large_read = MAX_LARGE_READ;
+
+  /* Following holds details of file currently used by zopen & zread */
+  struct stat znsk_stat;
+  nsk_stat_ov *znsk_ov = (nsk_stat_ov *)&znsk_stat.st_reserved[0];
+  nsk_file_attrs *znsk_attr = (nsk_file_attrs *)
+                                ((char *) (&znsk_stat.st_reserved[0]) + 4);
+
+  /* Following items used by zread to avoid overwriting window */
+  char zreadbuf[MAX_LARGE_READ];       /* Buffer as large as biggest read */
+  char *zreadptr = (char *) zreadbuf;  /* pointer to start of buffer      */
+  char *zread_ovptr = NULL;            /* pointer to left overs           */
+  long zread_ovlen = 0;                /* size of remaining left overs    */
+
+  int zopen (filename, opt)
+    const char *filename;
+    int opt;
+  {
+    /* Currently ignore opt.  Choose method of I/O based on NSK file type */
+    short err, len, fnum, access, exclus, bufferlen, options;
+    long recnum;
+    char fname[FILENAME_MAX + 1];
+    short extension;
+    char ext[EXTENSION_MAX + 1];
+
+    /* Remove any (pseudo) file extension */
+    extension = parsename (filename,fname,ext);
+    len = strlen(fname);
+
+    fnum = 0;
+    access = NSK_RDONLY;
+    exclus = NSK_SHARED;
+
+    err = stat(fname, &znsk_stat); /* Setup global struct, used by zread */
+
+    if (znsk_attr->filetype == NSK_UNSTRUCTURED)
+      if (znsk_attr->filecode == NSK_EDITFILECODE) {
+        /* Edit File */
+        fnum = -1; /* Ask OPENEDIT_ to open the file for us */
+        err = OPENEDIT_ ((char *)fname, len, &fnum, access, exclus);
+        if (!err) {
+          recnum = -1; /* Position to first line */
+          err = POSITIONEDIT (fnum, recnum);
+        }
+      }
+      else {
+        /* Unstructured File */
+        options = NSK_UNSTRUCTUREDACCESS;
+        err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,
+                         ,,options,,,);
+        if (!err)
+          /* Ask for large transfer mode */
+          err = (SETMODE (fnum, SET_LARGE_TRANSFERS, 1) != CCE);
+      }
+    else {
+      /* Structured File */
+      bufferlen = 4096;  /* request SBB */
+      err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,
+                       ,,,, bufferlen ,);
+      if (err == 4)
+        err = 0;  /* Allow saving of files that have missing altkeys */
+    }
+
+    return (err == 0 ? (int)fnum : -1);
+  }
+
+  unsigned zread (fnum, buf, len)
+    int fnum;
+    char *buf;
+    unsigned len;
+  {
+    short err, trail;
+    long total, movelen;
+    unsigned short countread;
+    unsigned readlen;  /* typed to match incoming arg */
+    char *bufptr, *readptr;
+
+    total = err = 0;
+    bufptr = buf;
+
+    /* We use a separate buffer to read in data as it can be larger than
+       WSIZE, and hence would overwrite memory */
+
+    /* We always attempt to give the user the exact requested size
+       Hence we make use of an overfow buffer for previously truncated data */
+
+    /* see if we have some left over characters from last time */
+    if (zread_ovlen) {
+       movelen = _min(len,zread_ovlen);
+       memcpy(bufptr, zread_ovptr, movelen);
+       bufptr += movelen;
+       total += movelen;
+       zread_ovptr += movelen;
+       zread_ovlen -= movelen;
+    }
+
+    while (!err && (total < len)) {
+      readptr = zreadptr;
+
+      if (znsk_attr->filetype == NSK_UNSTRUCTURED)
+        if (znsk_attr->filecode == NSK_EDITFILECODE){
+          /* Edit File */
+          trail = 1;
+          readlen = MAX_EDIT_READ; /* guarantee it fits in buffer */
+
+          /* get line and preserve any trailing space characters */
+          err = READEDIT (fnum,, zreadptr, (short) readlen,
+                            (short *) &countread,,, trail);
+          /* if countread is ever negative then we will skip a line */
+
+          if (!err) {
+            readptr = zreadptr + countread;
+            /* Note it is possible for Edit files to hold trailing space */
+            if (nsk_trim_space)
+              while (*(readptr-1) == ' ') {
+                readptr--;
+                countread--;
+              }
+
+            if (nsk_delim_len) {
+              memcpy(readptr, nsk_delim, nsk_delim_len);
+              readptr += nsk_delim_len;
+              countread += nsk_delim_len;
+            }
+          }
+        }
+        else {
+          /* Unstructured File */
+
+          /* Using large transfer mode so we have to use 2K multiples
+             Use largest size possible and put remains in overflow    */
+
+          readlen = nsk_large_read; /* use largest read, overflow into buffer*/
+
+          err = (READX(fnum, zreadptr, readlen, (short *)&countread) != CCE);
+          if (err && (errno == EINVAL)) {
+            /* Read too big so scale back to smaller value */
+            readlen = nsk_large_read = MAX_LARGE_READ_EXPAND;
+            err = (READX(fnum, zreadptr, readlen, (short *)&countread) != CCE);
+          }
+          if (!err)
+            readptr = zreadptr + countread;
+        }
+      else {
+        /* Structured File */
+        readlen = znsk_attr->reclen;
+
+        err = (READX(fnum, zreadptr, readlen, (short *)&countread)!= CCE);
+
+        if (!err) {
+          readptr = zreadptr + countread;
+          if (nsk_space_fill)
+            while (countread < readlen) {
+              *readptr++ = ' ';
+              countread++;
+            }
+          else
+            if (nsk_trim_space)
+              while (*(readptr-1) == ' ') {
+                readptr--;
+                countread--;
+              }
+
+          if (nsk_delim_len) {
+            memcpy(readptr, nsk_delim, nsk_delim_len);
+            readptr += nsk_delim_len;
+            countread += nsk_delim_len;
+          }
+        }
+      }
+      if (!err) {
+         movelen = _min((len-total), countread);
+         memcpy(bufptr, zreadptr, movelen);
+         bufptr += movelen;
+         total += movelen;
+         if (movelen < countread) { /* still stuff in Read buffer */
+           zread_ovptr = zreadptr + movelen;   /* pointer to whats left */
+           zread_ovlen = countread - movelen;  /* how much is left      */
+         }
+      }
+    }
+
+    return ((unsigned)total);
+  }
+
+  int zclose (fnum)
+    int fnum;
+  {
+    short err;
+
+    if ((znsk_attr->filetype == NSK_UNSTRUCTURED)
+      && (znsk_attr->filecode == NSK_EDITFILECODE))
+      err = CLOSEEDIT_(fnum);
+    else
+      err = FILE_CLOSE_(fnum);
+
+    return (err != 0);
+  }
+
+void nskformatopt(p)
+char **p;
+{
+char *q;
+
+  /* set up formatting options for ZIP */
+
+  q = *p; /* make a note of where we are */
+
+  Bflag = 0; /* default option */
+
+  Bflag = strtoul((*p + 1), p, 10);
+
+  /* need to go back one character if we've got a result */
+  if (q != *p)
+    (*p)--;
+
+  if (Bflag & NSK_SPACE_FILL)
+    nsk_space_fill = 1;
+  else
+    nsk_space_fill = 0;
+
+  if (Bflag & NSK_TRIM_TRAILING_SPACE)
+    nsk_trim_space = 1;
+  else
+    nsk_trim_space = 0;
+
+  if (Bflag & NSK_NO_DELIMITER)
+    nsk_delim_len = 0;
+  else {
+    if (Bflag & NSK_USE_FF_DELIMITER) {
+      nsk_delim[0] = '\n';
+      nsk_delim_len = 1;
+    }
+    else {   /* CR/LF */
+      nsk_delim[0] = '\r';
+      nsk_delim[1] = '\n';
+      nsk_delim_len = 2;
+    }
+  }
+
+  if (Bflag & NSK_LARGE_READ_EXPAND)
+    nsk_large_read = MAX_LARGE_READ_EXPAND;
+  else
+    nsk_large_read = MAX_LARGE_READ;
+
+}
+
+
+  int deletedir(d)
+    char *d;                /* directory to delete */
+  /* Delete the directory *d if it is empty, do nothing otherwise.
+     Return the result of rmdir(), delete(), or system().
+     For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).
+   */
+  {
+      return rmdir(d);
+  }
+
+  local char *readd(d)
+    DIR *d;                 /* directory stream to read from */
+  /* Return a pointer to the next name in the directory stream d, or NULL if
+     no more entries or an error occurs. */
+  {
+    struct dirent *e;
+
+    e = readdir(d);
+    return e == NULL ? (char *) NULL : e->d_name;
+  }
+
+  int procname(n, caseflag)
+    char *n;                /* name to process */
+    int caseflag;           /* true to force case-sensitive match */
+  /* Process a name or sh expression to operate on (or exclude).  Return
+     an error code in the ZE_ class. */
+  {
+    char *a;              /* path and name for recursion */
+    DIR *d;               /* directory stream from opendir() */
+    char *e;              /* pointer to name from readd() */
+    int m;                /* matched flag */
+    char *p;              /* path for recursion */
+    struct stat s;        /* result of stat() */
+    struct zlist far *z;  /* steps through zfiles list */
+
+    if (strcmp(n, "-") == 0)   /* if compressing stdin */
+      return newname(n, 0, caseflag);
+    else if (stat(n, &s))
+    {
+      /* Not a file or directory--search for shell expression in zip file */
+      p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
+      m = 1;
+      for (z = zfiles; z != NULL; z = z->nxt) {
+        if (MATCH(p, z->zname, caseflag))
+        {
+          z->mark = pcount ? filter(z->zname, caseflag) : 1;
+          if (verbose)
+              fprintf(mesg, "zip diagnostic: %scluding %s\n",
+                 z->mark ? "in" : "ex", z->name);
+          m = 0;
+        }
+      }
+      free((zvoid *)p);
+      return m ? ZE_MISS : ZE_OK;
+    }
+
+    /* Live name--use if file, recurse if directory */
+    if ((s.st_mode & S_IFDIR) == 0)
+    {
+      /* add or remove name of file */
+      if ((m = newname(n, 0, caseflag)) != ZE_OK)
+        return m;
+    } else {
+      if ((p = malloc(strlen(n)+4)) == NULL)
+        return ZE_MEM;
+
+      strcpy(p, n);
+
+      /* No concept of directories on Tandem - so do not store them ...*/
+      /* code removed from which attempted to save dir name if dirnames set */
+
+      /*  Test for recurse being set removed, since Tandem has no dir concept*/
+      /*  recurse into template */
+      if ((d = opendir(n)) != NULL)
+      {
+        while ((e = readd(d)) != NULL) {
+          if ((m = procname(e, caseflag)) != ZE_OK)   /* recurse on name */
+          {
+            if (m == ZE_MISS)
+              zipwarn("name not matched: ", e);
+            else
+              ziperr(m, e);
+          }
+        }
+        closedir(d);
+      }
+      free((zvoid *)p);
+    } /* (s.st_mode & S_IFDIR) == 0) */
+    return ZE_OK;
+  }
+
+  char *ex2in(x, isdir, pdosflag)
+    char *x;                /* external file name */
+    int isdir;              /* input: x is a directory */
+    int *pdosflag;          /* output: force MSDOS file attributes? */
+  /* Convert the external file name to a zip file name, returning the malloc'ed
+     string or NULL if not enough memory. */
+  {
+    char *n;              /* internal file name (malloc'ed) */
+    char *t;              /* shortened name */
+    int dosflag;
+    char *p;               /* pointer to temp area */
+    char fname[FILENAME_MAX + 1]= ""; /* file name */
+    char ext[EXTENSION_MAX + 1] = ""; /* extension name */
+    short extension;    /* does the filename contain an extension */
+
+    dosflag = dosify;  /* default for non-DOS non-OS/2 */
+
+    /* Find starting point in name before doing malloc */
+    if (*x == '=')
+      t = x + 1;   /* store DEFINE names without the '=' */
+    else
+      t = x;
+
+    /* Make changes, if any, to the copied name (leave original intact) */
+
+    if (!pathput)
+      t = last(t, TANDEM_DELIMITER);
+
+    /* Malloc space for internal name and copy it */
+    if ((n = malloc(strlen(t) + 4)) == NULL) /* + 4 for safety */
+      return NULL;
+
+    extension = parsename(t,fname,ext);
+    t = fname;
+
+    *n= '\0';
+
+    while (*t != '\0') {  /* File part could be sys,vol,subvol or file */
+      if (*t == TANDEM_NODE) {    /* System Name */
+        strcat(n, INTERNAL_NODE_STR);
+        t++;
+      }
+      else if (*t == TANDEM_DELIMITER) {  /* Volume or Subvol */
+             strcat(n, INTERNAL_DELIMITER_STR);
+             t++;
+           };
+      p = strchr(t,TANDEM_DELIMITER);
+      if (p == NULL) break;
+      strncat(n,t,(p - t));
+      t = p;
+    }
+
+    strcat(n,t);  /* mop up any left over characters */
+
+    if (extension) {
+      strcat(n,DOS_EXTENSION_STR);
+      strcat(n,ext);
+    };
+
+    if (isdir == 42) return n;      /* avoid warning on unused variable */
+
+    if (dosify)
+      msname(n);
+
+    /* Returned malloc'ed name */
+    if (pdosflag)
+      *pdosflag = dosflag;
+
+    return n;
+  }
+
+  void stamp(f, d)
+    char *f;                /* name of file to change */
+    ulg d;                  /* dos-style time to change it to */
+  /* Set last updated and accessed time of file f to the DOS time d. */
+  {
+    ztimbuf u;            /* argument for utime() */
+
+    /* Convert DOS time to time_t format in u.actime and u.modtime */
+    u.actime = u.modtime = dos2unixtime(d);
+
+    utime(f, &u);
+  }
+
+  ulg filetime(f, a, n, t)
+    char *f;                /* name of file to get info on */
+    ulg *a;                 /* return value: file attributes */
+    long *n;                /* return value: file size */
+    iztimes *t;             /* return value: access and modification time */
+  {
+    struct stat s;
+    nsk_stat_ov *nsk_ov;
+
+    if (strcmp(f, "-") == 0) {    /* if compressing stdin */
+      if (n != NULL) {
+        *n = -1L;
+      }
+    }
+
+    if (stat(f, &s) != 0) return 0;
+
+    if (a!= NULL) {
+      *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWUSR);
+      if ((s.st_mode & S_IFMT) == S_IFDIR) {
+        *a |= MSDOS_DIR_ATTR;
+      }
+    }
+
+    if (n!= NULL)
+      *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+
+    if (t != NULL) {
+      t->atime = s.st_atime;
+      t->mtime = s.st_mtime;
+      nsk_ov = (nsk_stat_ov *)&s.st_reserved[0];
+      t->ctime = nsk_ov->ov.creation_time;
+    }
+
+    return unix2dostime(&s.st_mtime);
+  }
+
+  int set_extra_field(z, z_utim)
+    struct zlist far *z;
+    iztimes *z_utim;
+    /* create extra field and change z->att if desired */
+    /* store full data in local header but just modification time stamp info
+       in central header */
+  {
+    struct stat s;
+    nsk_stat_ov *nsk_ov = (nsk_stat_ov *)&s.st_reserved[0];
+    nsk_file_attrs *nsk_attr = (nsk_file_attrs *)&nsk_ov->ov.nsk_ef_start;
+    char *ext, *cext;
+    int lsize, csize;
+#ifdef USE_EF_UT_TIME
+    char *UTptr, *Uxptr;
+#endif /* USE_EF_UT_TIME */
+
+    /* For the Tandem and UT local field including the UID/GID fields, we
+       have to stat the file again. */
+    if (LSSTAT(z->name, &s))
+      return ZE_OPEN;
+
+    z->ext = z->cext = 0;
+
+  #define EB_TANDEM_SIZE 20
+  #define EF_TANDEM_SIZE (EB_HEADSIZE + EB_TANDEM_SIZE)
+
+    /* allocate size of buffers to allow Tandem field */
+    lsize = EF_TANDEM_SIZE;
+    csize = EF_TANDEM_SIZE;
+
+#ifdef USE_EF_UT_TIME
+
+  #define EB_L_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(3))
+  #define EB_C_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(1))
+  #define EB_L_UX2_SIZE   (EB_HEADSIZE + EB_UX2_MINLEN)
+  #define EB_C_UX2_SIZE   EB_HEADSIZE
+  #define EF_L_UNIX_SIZE  (EB_L_UT_SIZE + EB_L_UX2_SIZE)
+  #define EF_C_UNIX_SIZE  (EB_C_UT_SIZE + EB_C_UX2_SIZE)
+
+    /* resize to allow for UT fields */
+    lsize += EF_L_UNIX_SIZE;
+    csize += EF_C_UNIX_SIZE;
+
+#endif /* USE_EF_UT_TIME */
+
+    if ((z->extra = (char *)malloc(lsize)) == NULL)
+      return ZE_MEM;
+    ext = z->extra;
+
+    if ((z->cextra = (char *)malloc(csize)) == NULL)
+      return ZE_MEM;
+    cext = z->cextra;
+
+    /* Place Tandem field first so its on an even boundary */
+    *ext++ = *cext++ = 'T';
+    *ext++ = *cext++ = 'A';
+    *ext++ = *cext++ = (char)EB_TANDEM_SIZE;  /*length of data part of e.f.*/
+    *ext++ = *cext++  = 0;
+
+    /* Copy Tandem specific file information */
+    memcpy(ext, (char *)nsk_attr, EB_TANDEM_SIZE);
+    ext += EB_TANDEM_SIZE;
+    z->ext += EF_TANDEM_SIZE;
+
+    /* Copy same data to central field */
+    memcpy(cext, (char *)nsk_attr, EB_TANDEM_SIZE);
+    cext += EB_TANDEM_SIZE;
+    z->cext += EF_TANDEM_SIZE;
+
+#ifdef USE_EF_UT_TIME
+    UTptr = ext;
+    *ext++  = 'U';
+    *ext++  = 'T';
+    *ext++  = (char)EB_UT_LEN(3);    /* length of data part of local e.f. */
+    *ext++  = 0;
+    *ext++  = EB_UT_FL_MTIME | EB_UT_FL_ATIME | EB_UT_FL_CTIME;
+    *ext++  = (char)(s.st_mtime);
+    *ext++  = (char)(s.st_mtime >> 8);
+    *ext++  = (char)(s.st_mtime >> 16);
+    *ext++  = (char)(s.st_mtime >> 24);
+    *ext++  = (char)(s.st_atime);
+    *ext++ = (char)(s.st_atime >> 8);
+    *ext++ = (char)(s.st_atime >> 16);
+    *ext++ = (char)(s.st_atime >> 24);
+
+    *ext++ = (char)(nsk_ov->ov.creation_time);
+    *ext++ = (char)(nsk_ov->ov.creation_time >> 8);
+    *ext++ = (char)(nsk_ov->ov.creation_time >> 16);
+    *ext++ = (char)(nsk_ov->ov.creation_time >> 24);
+
+    Uxptr = ext;
+    *ext++ = 'U';
+    *ext++ = 'x';
+    *ext++ = (char)EB_UX2_MINLEN;   /* length of data part of local e.f. */
+    *ext++ = 0;
+    *ext++ = (char)(s.st_uid);
+    *ext++ = (char)(s.st_uid >> 8);
+    *ext++ = (char)(s.st_gid);
+    *ext++ = (char)(s.st_gid >> 8);
+
+    z->ext += EF_L_UNIX_SIZE;
+
+    memcpy(cext, UTptr, EB_C_UT_SIZE);
+    cext[EB_LEN] = (char)EB_UT_LEN(1);
+    memcpy(cext+EB_C_UT_SIZE, Uxptr, EB_C_UX2_SIZE);
+    cext[EB_LEN+EB_C_UT_SIZE] = 0;
+
+    z->cext += EF_C_UNIX_SIZE;
+    cext += EF_C_UNIX_SIZE;
+
+#endif /* USE_EF_UT_TIME */
+
+    return ZE_OK;
+  }
diff --git a/tandem/tanzip.h b/tandem/tanzip.h
new file mode 100644 (file)
index 0000000..f6cd6bb
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __tanzip_h   /* prevent multiple inclusions */
+#define __tanzip_h
+
+  int       zopen  (const char *, int);
+  int       zclose (int);
+  unsigned  zread (int, char *, unsigned);
+  void      nskformatopt(char **);
+
+#endif /* !__tanzip_h */
diff --git a/tandem/zipup.h b/tandem/zipup.h
new file mode 100644 (file)
index 0000000..dd7e24d
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef O_RDONLY
+#  define O_RDONLY 0
+#endif
+#define fhow O_RDONLY
+#define fbad (-1)
+typedef int ftype;
+
+/* Now we create Guardian versions of zopen, zread, zclose instead
+   moved prototypes to tandem.h as they are no coded in tandem.c
+   #define zopen(n,p) open(n,p)
+   #define zread(f,b,n) read(f,b,n)
+   #define zclose(f) close(f)
+*/
+
+
+#define zerr(f) (k == (extent)(-1L))
+#define zstdin 0
+
diff --git a/theos/Makefile b/theos/Makefile
new file mode 100644 (file)
index 0000000..cb3d6da
--- /dev/null
@@ -0,0 +1,135 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for
+# THEOS ANSI C
+# To use, do "make -f theos/makefile"
+# This make file uses cl, a C compiler and linker driver written by
+# Jean-Michel Dubois. Send a mail to jmdubois@ibcfrance.fr to get it for free.
+# MAINWA_BUG    Workaround argument expansion failure
+# LOCATE_BUG    Workaround stat, fopen and open failure on relative paths to
+#               root dir.
+
+CC=cl
+CFLAGS=-Zi -W3 -DDYN_ALLOC -DCRYPT -DMAINWA_BUG -DLOCATE_BUG
+LD=cl -o
+LDFLAGS=-m -Zi
+AS=cc
+ASFLAGS=
+
+UTILFLAGS=-DUTIL $(CFLAGS) -Fo
+
+# variables
+
+# object file lists
+OBJZ = zip.o zipfile.o zipup.o fileio.o util.o globals.o crypt.o ttyio.o \
+       theos.o crc32.o crctab.o _fprintf.o _stat.o _chmod.o _isatty.o \
+       _setargv.o _rename.o
+OBJI = deflate.o trees.o
+OBJA =
+OBJU = zipfile_.o fileio_.o util_.o globals.o theos_.o _rename.o _stat.o \
+       _chmod.o _fprintf.o
+OBJN = zipnote.o  $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt_.o ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+ZIPS = zip.command zipnote.command zipsplit.command zipcloak.command
+
+zips:  $(ZIPS)
+
+zip.o: zip.h theos/osdep.h ziperr.h tailor.h ttyio.h revision.h zip.c
+       $(CC) -c $(CFLAGS) $*.c
+
+zipfile.o:     zip.h theos/osdep.h ziperr.h tailor.h zipfile.c
+       $(CC) -c $(CFLAGS) $*.c
+
+zipup.o:       zip.h theos/osdep.h ziperr.h tailor.h revision.h zipup.c
+       $(CC) -c $(CFLAGS) $*.c
+
+fileio.o:      zip.h theos/osdep.h ziperr.h tailor.h fileio.c
+       $(CC) -c $(CFLAGS) $*.c
+
+util.o:        zip.h theos/osdep.h theos/charconv.h ziperr.h tailor.h util.c
+       $(CC) -c $(CFLAGS) $*.c
+
+globals.o:     zip.h theos/osdep.h ziperr.h tailor.h globals.c
+       $(CC) -c $(CFLAGS) $*.c
+
+crc32.o:       zip.h theos/osdep.h ziperr.h tailor.h crc32.c
+       $(CC) -c $(CFLAGS) $*.c
+
+crctab.o:      zip.h theos/osdep.h ziperr.h tailor.h crctab.c
+       $(CC) -c $(CFLAGS) $*.c
+
+deflate.o:     zip.h theos/osdep.h ziperr.h tailor.h deflate.c
+       $(CC) -c $(CFLAGS) $*.c
+
+trees.o:       zip.h theos/osdep.h ziperr.h tailor.h trees.c
+       $(CC) -c $(CFLAGS) $*.c
+
+crypt.o:       zip.h theos/osdep.h ziperr.h tailor.h crypt.c
+       $(CC) -c $(CFLAGS) $*.c
+
+theos.o:       zip.h theos/osdep.h ziperr.h tailor.h theos/theos.c
+       $(CC) -c $(CFLAGS) -Fo$@ theos/theos.c
+
+_fprintf.o:    theos/_fprintf.c
+       $(CC) -c $(CFLAGS) -Fo$@ theos/_fprintf.c
+
+_stat.o:       theos/_stat.c
+       $(CC) -c $(CFLAGS) -Fo$@ theos/_stat.c
+
+_chmod.o:      theos/_chmod.c
+       $(CC) -c $(CFLAGS) -Fo$@ theos/_chmod.c
+
+_isatty.o:     theos/_isatty.c
+       $(CC) -c $(CFLAGS) -Fo$@ theos/_isatty.c
+
+_rename.o:     theos/_rename.c
+       $(CC) -c $(CFLAGS) -Fo$@ theos/_rename.c
+
+_setargv.o:    theos/_setargv.c
+       $(CC) -c $(CFLAGS) -Fo$@ theos/_setargv.c
+
+ttyio.o:       zip.h theos/osdep.h ziperr.h tailor.h ttyio.h ttyio.c
+       $(CC) -c $(CFLAGS) $*.c
+
+zipcloak.o:    zip.h theos/osdep.h ziperr.h tailor.h ttyio.h revision.h zipcloak.c
+       $(CC) -c $(CFLAGS) $*.c
+
+zipnote.o:     zip.h theos/osdep.h ziperr.h tailor.h revision.h zipnote.c
+       $(CC) -c $(CFLAGS) $*.c
+
+zipsplit.o:    zipsplit.c zip.h theos/osdep.h ziperr.h tailor.h revision.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipfile_.o:    zipfile.c zip.h theos/osdep.h ziperr.h tailor.h
+       $(CC) -c $(UTILFLAGS)$@ zipfile.c
+
+fileio_.o:     fileio.c zip.h theos/osdep.h ziperr.h tailor.h
+       $(CC) -c $(UTILFLAGS)$@ fileio.c
+
+theos_.o:      zip.h theos/osdep.h ziperr.h tailor.h theos/theos.c
+       $(CC) -c $(UTILFLAGS)$@ theos/theos.c
+
+util_.o:       util.c zip.h theos/osdep.h ziperr.h tailor.h
+       $(CC) -c $(UTILFLAGS)$@ util.c
+
+crypt_.o:      zip.h theos/osdep.h ziperr.h tailor.h crypt.c
+       $(CC) -c $(UTILFLAGS)$@ crypt.c
+
+zip.command: $(OBJZ) $(OBJI)
+       $(LD) $@ $(OBJZ) $(OBJI) $(LDFLAGS)
+
+zipcloak.command: $(OBJC)
+       $(LD) $@ $(OBJC) $(LDFLAGS)
+
+zipnote.command: $(OBJN)
+       $(LD) $@ $(OBJN) $(LDFLAGS)
+
+zipsplit.command: $(OBJS)
+       $(LD) $@ $(OBJS) $(LDFLAGS)
+
+install:       $(ZIPS)
+       copy *.command /system.cmd32.=(rep noq not
+
+clean:
+       erase *.o(noq not
+       erase *.command(noq not
diff --git a/theos/README b/theos/README
new file mode 100644 (file)
index 0000000..1ec99d3
--- /dev/null
@@ -0,0 +1,34 @@
+This Theos port supports all the unusual features of Theos filesystem.
+
+Under Theos filesystem files are typed. Types include :
+- stream
+- relative
+- keyed
+- indexed (ISAM)
+- program (86 real mode, 16 bits protected mode, 32 bits protected mode)
+- directory
+- library (contains files of any other types librry and directory excepted).
+
+Most of the information on the type and on the structure of a file are not
+contained in the file itself but its in directory entry. For all types of
+files, directory and stream files excepted, this information is vital. If it
+is lost, the file can no longer be usable.
+
+In zip files the information is stored in an extra block with type "Th".
+
+A few years ago I ported ZIP for internal use and spreaded it a little around
+me. It was using a non portable extra block structure. Its type was "TH".
+For backward compatibility it is supported by UNZIP 5.4.0 port to Theos.
+ZIP archives created with ZIP 2.3 port MUST be unzipped with 5.4.0 or a later
+version.
+
+Also disk search sequence is supported. The disk name is not stored into
+the zip archive.
+
+Thanks to Bob Baker from Stockboy Services who spent his time to check this
+port under other conditions than mines.
+
+Jean-Michel Dubois
+IBC France / THEOS France
+jmdubois@ibcfrance.fr
+jean-michel-dubois@wanadoo.fr
diff --git a/theos/_chmod.c b/theos/_chmod.c
new file mode 100644 (file)
index 0000000..0937b45
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/* Change UNIX modes */
+
+#pragma library
+
+#include <sc.h>
+
+int _chmod(const char *fname, short mask)
+{
+    extern char _um2tm_(short);
+
+    return _filechange(fname,'p',(size_t) _um2tm_(mask)|0x80);
+}
+
diff --git a/theos/_fprintf.c b/theos/_fprintf.c
new file mode 100644 (file)
index 0000000..5c8c927
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#include <stdio.h>
+#include <stdarg.h>
+
+/* for Info and similar macroes. fprintf is already a macro and fprintf x
+ * fools the preprocessor
+ */
+
+int _fprintf(FILE* fp, const char* fmt, ...)
+{
+    va_list ap;
+    long n;
+
+    va_start(ap, fmt);
+    n = vfprintf(fp, fmt, (long*) ap);
+    va_end(ap);
+    return n;
+}
+
diff --git a/theos/_isatty.c b/theos/_isatty.c
new file mode 100644 (file)
index 0000000..26f177b
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/* replace standard library function who needs a FILE* */
+
+#pragma library
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sc.h>
+#include <lub.h>
+
+short _isatty(int fd)
+{
+    register short lub;
+
+    lub = (int) _fcntl(&stdin[fd], 5, (size_t) 0);
+    return (lub >= CONIN && lub <= CONOUT)
+        || (lub >= COM1 && lub <= COM4)
+        || (lub >= COM5 && lub <= COM16);
+}
diff --git a/theos/_rename.c b/theos/_rename.c
new file mode 100644 (file)
index 0000000..04eb204
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#define EXDEV 590
+
+#define _sys_rename()   _sc_140()
+extern unsigned short   _sys_rename(const char _far *oldfn, char *newfn);
+
+/* rename a file. Report an error on cross disk renames */
+
+static void _n_(const char* fn, char* bfn)
+{
+    if (*fn != '.' && *fn != '/')
+        strcpy(bfn, "./");
+    else
+        *bfn = '\0';
+    strcat(bfn, fn);
+}
+
+int _rename(const char* old, const char* new)
+{
+    char* p;
+    char* q;
+    char* r;
+    char olddrv, newdrv;
+    char dir[FILENAME_MAX];
+    short status;
+    char bold[FILENAME_MAX], bnew[FILENAME_MAX];
+
+    p = strrchr(old, ':');
+    q = strrchr(new, ':');
+
+    /* if at least one path includes a disk name, check for equality */
+    if (p != NULL || q != NULL) {
+        /* getcwd return a NULL pointer for /:S */
+        getcwd(dir, FILENAME_MAX);
+        r = strrchr(dir, ':');
+
+        if (p == NULL)
+            p = r;
+        olddrv = p ? p[1] : 'S';
+
+        if (q == NULL)
+            q = r;
+        newdrv = q ? q[1] : 'S';
+
+        /* return an error if uppercased disk names are not the same */
+        if ((old & ~0x20) != (new & ~0x20)) {
+            _errarg = NULL;
+            return errno = _errnum = EXDEV;
+        }
+    }
+    /* prepend ./ if there is no path to force rename to work on files
+     * in the current directory instead of default library
+     */
+    _n_(old, bold);
+    _n_(new, bnew);
+
+    status = _sys_rename(bold, bnew);
+    /* can be :
+     *  0 no error
+     * 19 "old" file not found
+     * 44 "new" file already exist
+     * 45 "new" filename missing
+     * 46 "old" file name missing
+     */
+    if (status) {
+        errno = _errnum = status;
+        _errarg = (status == 44 || status == 45) ? new : old;
+    }
+
+    return status;
+}
diff --git a/theos/_setargv.c b/theos/_setargv.c
new file mode 100644 (file)
index 0000000..d76f955
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/*
+ * __setargv.c - command argument expander
+ *
+ * Author  : Jean-Michel Dubois
+ * Date    : 09/26/92
+ *
+ * Function: Expands the command line arguments by replacing any filename
+ *           including wilcards by the sorted list of matching files name.
+ *           Strings beginning by a dash are considered as options and left
+ *           unchanged.
+ *
+ * Syntax  : void _setargv(int *argc, char ***argv);
+ *
+ * Returns : new argc. Caller's argc and argv are updated.
+ *           If a insufficient memory condition occurs, return 0 and errno
+ *           is set to ENOMEM.
+ *
+ * Example :
+ *              main(int argc, char **argv)
+ *              {
+ *                      if (_setargv(&argc, &argv)) {
+ *                              ...
+ */
+#pragma library
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <errno.h>
+#include <scr.h>
+#include <peek.h>
+
+/* Allocate argv array in 16 entries chunks */
+
+static int allocarg(int n, int l, char ***nargv, char *s)
+{
+    if ((n+1) > l) {    /* If array full */
+        l += 16;        /* increase size and reallocate */
+        if (!(*nargv = (char **) realloc(*nargv,l * sizeof (void *)))) {
+            errno = _errnum = ENOMEM;    /* Not enough memory */
+            return 0;
+        }
+    }
+    (*nargv)[n] = strdup(s);    /* Save argument */
+    return l;            /* Return new maxsize */
+}
+
+/* Comparison function for qsort */
+
+static int sortcmp(char **p, char **q)
+{
+    return stricmp(*p,*q);
+}
+
+/* Main body of the function */
+
+int _setargv(int *argc, char ***argv)
+{
+    register int nargc;     /* New arguments counter */
+    char **nargv;           /* New arguments pointers */
+    register int i, l, base;
+    char *p, *q, *r;
+    char path[FILENAME_MAX];
+
+    _errnum = 0;
+    nargc = 0;          /* Initialise counter, size counter */
+    l = *argc;          /* and new argument vector to the */
+                        /* current argv array size */
+
+    if ((nargv = (char **) calloc((size_t) *argc, sizeof (void *))) != NULL) {
+        /* For each initial argument */
+        for (i = 0; i < *argc; i++) {
+            q = (*argv)[i];
+            if (q[0] == '-' || ! testwild(q)) {
+                /* if it begins with a dash or doesnt include
+                 * wildcard simply add it to the new array
+                 */
+                if (! (l = allocarg(nargc, l, &nargv, q)))
+                    return 0;    /* Not enough memory */
+                nargc++;
+            } else {
+                /* else keep current counter for qsort */
+                base = nargc;
+                /* open directory with argument */
+                diropen(q);
+                while ((r = dirread()) != NULL) {
+                    /* reduce path to given one */
+                    if ((p = strrchr(q, '/')) != NULL) {
+                        strncpy(path, q, p-q+1);
+                        path[p-q+1] = '\0';
+                    } else
+                        path[0] = '\0';
+
+                    if ((p = strrchr(r, '/')) != NULL)
+                        strcat(path, p+1);
+                    else
+                        strcat(path, r);
+
+                    if (peekscr(&SCR->searchseq[1]) == 255
+                     && strchr(q, ':') == NULL) {
+                        *strchr(path, ':') = '\0';
+                    }
+                    /* and add each matching filename. */
+                    if (! (l = allocarg(nargc,l,&nargv,path)))
+                        return 0;/* Not enough memory */
+                    nargc++;
+                }
+                if (nargc == base) {
+                    /* if no match found include wild card name */
+                    if (! (l = allocarg(nargc, l, &nargv, q)))
+                        return 0;    /* Not enough memory */
+                    nargc++;
+                } else if ((nargc - base) > 1)
+                    /* If more than one file name matchs */
+                    /* sort arguments. */
+                    qsort(&(nargv[base]),(size_t)nargc-base,
+                        sizeof(void *),sortcmp);
+                dirclose();
+            }
+        }
+        /* Update caller's parameters */
+        *argc = nargc;
+        *argv = nargv;
+        /* and sign on success */
+        return nargc;
+    }
+
+    /* If it is not possible to allocate initial array, sign on error */
+    _errnum = ENOMEM;
+    return 0;
+}
diff --git a/theos/_stat.c b/theos/_stat.c
new file mode 100644 (file)
index 0000000..6855d28
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#pragma library
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sc.h>
+#include <peek.h>
+#include <lub.h>
+#include <fdb.h>
+#include <fsa.h>
+#include "theos/stat.h"
+
+/* replacement for standard library functions stat and fstat */
+
+int _stat_(struct stat* st, struct fdb* fdb);
+int _dstat_(struct stat* st);
+
+#define peekucb() peeknuc()
+
+/* map THEOS protection code to Unix modes */
+
+unsigned short _tm2um_(char protect)
+{
+    unsigned short umask = 0;
+
+    if (!(protect & _FDB_READ_PROTECT))
+        umask = S_IRUSR|S_IRGRP;
+
+    if (!(protect & _FDB_WRITE_PROTECT))
+        umask |= S_IWUSR|S_IWGRP;
+
+    if (!(protect & _FDB_EXECUTE_PROTECT))
+        umask |= S_IXUSR|S_IXGRP;
+
+    if (!(protect & _FDB_ERASE_PROTECT))
+        umask |= S_IEUSR|S_IEGRP;
+
+    if (!(protect & _FDB_SHARED_READ_PROTECT)) {
+        if (_osmajor > 3)
+            umask |= S_IROTH|S_IXOTH;
+        else
+            umask |= S_IROTH;
+    }
+
+    if (!(protect & _FDB_SHARED_WRITE_PROTECT))
+        umask |= S_IWOTH;
+
+    if (!(protect & _FDB_MODIFIED)) {
+        if (_osmajor > 3)
+            umask |= S_IMODF;
+        else
+            umask |= S_IXOTH;
+    }
+
+    if (protect & _FDB_NOT_HIDDEN)
+        umask |= S_INHID;
+
+    return umask;
+}
+
+/* map Unix modes to THEOS protections */
+
+char _um2tm_(unsigned short mask)
+{
+    char protect = 0;
+
+    if (!(mask & (S_IRUSR|S_IRGRP)))
+        protect |= _FDB_READ_PROTECT;
+
+    if (!(mask & (S_IWUSR|S_IWGRP)))
+        protect |= _FDB_WRITE_PROTECT;
+
+    if (!(mask & (S_IXUSR|S_IXGRP)))
+        protect |= _FDB_EXECUTE_PROTECT;
+
+    if (!(mask & (S_IEUSR|S_IEGRP)))
+        protect |= _FDB_ERASE_PROTECT;
+
+    if (_osmajor < 4) {
+        if (!(mask & S_IROTH))
+            protect |= _FDB_SHARED_READ_PROTECT;
+    } else {
+        if (!(mask & (S_IROTH|S_IXOTH)))
+            protect |= _FDB_SHARED_READ_PROTECT;
+    }
+
+    if (!(mask & S_IWOTH))
+        protect |= _FDB_SHARED_WRITE_PROTECT;
+
+    if (mask & S_IMODF && _osmajor > 3)
+        protect |= _FDB_MODIFIED;
+
+    if (mask & S_INHID && _osmajor > 3)
+        protect |= _FDB_NOT_HIDDEN;
+
+    return protect;
+}
+
+/* root directory stat */
+
+static int rdirstat(const char* fn, struct stat *st)
+{
+    register char* p = strchr(fn, ':');
+    char drive;
+
+    drive = p ? p[1] : 'S';
+
+    if (drive >= 'a' && drive <= 'Z')
+        drive -= 0x40;
+
+    memset(st, 0, sizeof(struct stat));
+
+    if (getlub(drive - 'A') != 255) {
+        st->st_org = _FDB_STAT_DIRECTORY;
+        st->st_mode = S_IFDIR|S_IRUSR|S_IWUSR|S_IROTH|S_IWOTH;
+        st->st_nlink = 1;
+        st->st_dev = st->st_rdev = drive - 'A';
+        st->st_uid = st->st_gid = getuid();
+        st->st_protect = _FDB_ERASE_PROTECT;
+        return 0;
+    }
+    errno = _errnum = ENOENT;
+    _errarg = fn;
+    return -1;
+}
+
+#ifdef LOCATE_BUG
+
+/* locate fails when stating a file in root dir from a directory with a
+ * relative path. Workaround by setting directory to root dir
+ * getting the file directory block, then restoring the current directory.
+ */
+
+struct fdb* __locate(const char* fn, char* buf, short* drv)
+{
+    struct fdb* fdb;
+    char buf2[FILENAME_MAX];
+    char cwd[FILENAME_MAX];
+    char drive[3];
+    char* p;
+    char* q;
+
+    /* return if file found */
+    if (fdb = _locate(fn, buf, drv))
+        return fdb;
+
+    /* if file name does not contain a path delimiter it really does not exist.
+     */
+    strcpy(buf2, fn);
+
+    if ((p = strrchr(buf2, '/')) == NULL)
+        return NULL;
+
+    /* get drive name from file path */
+    q = strrchr(buf2, ':');
+
+    /* cat drive name if any to directory path */
+    if (q) {
+        strncpy(drive, q, 2);
+        drive[2] = '\0';
+        strcpy(p, q);
+    } else
+        *p = '\0';
+    /* save current directory */
+    getcwd(cwd, FILENAME_MAX);
+    /* chdir to directory path */
+    chdir(buf2);
+    /* get File Directory Block */
+    p = strrchr(fn, '/');
+    fdb = _locate(p + 1, buf, drv);
+    /* restore current directory */
+    chdir(cwd);
+    return fdb;
+}
+
+#undef _locate
+#define _locate() __locate()
+
+/* same cause, same consequence for fopen and open.
+*/
+
+FILE* _fopen(const char* fn, const char* mode)
+{
+    FILE* fp;
+    char buf[FILENAME_MAX];
+    short drv;
+
+    /* prepend a path to current dir to avoid use of default library */
+    if (*fn != '.' && *fn != '/') {
+        strcpy(buf, "./");
+        strcat(buf, fn);
+        return fopen(buf, mode);
+    }
+
+    if (fp = fopen(fn, mode))
+        return fp;
+
+    /* see comment for _locate */
+    if (_locate(fn, buf, &drv)) {
+        fn = strrchr(fn, '/');
+        return fopen(fn, mode);
+    }
+    return NULL;
+}
+
+#undef open
+int open(const char*, int, ...);
+
+int __open(const char* fn, int mode)
+{
+    int fd;
+    char buf[FILENAME_MAX];
+    short drv;
+
+    /* prepend a path to current dir to avoid use of default library */
+    if (*fn != '.' && *fn != '/') {
+        strcpy(buf, "./");
+        strcat(buf, fn);
+        return open(buf, mode);
+    }
+
+    if ((fd = open(fn, mode)) != EOF)
+        return fd;
+
+    /* see comment for _locate */
+    if (_locate(fn, buf, &drv)) {
+        fn = strrchr(fn, '/');
+        if (fn)
+            return open(fn, mode);
+    }
+    return EOF;
+}
+#endif
+
+/* replacement for standard file stat */
+
+int _stat(const char *_fn, struct stat *st)
+{
+    char buf[FILENAME_MAX], buf2[FILENAME_MAX], buf3[FILENAME_MAX];
+    register struct fdb* fdb;
+    register char* p;
+    register char* fn;
+
+    fn = strcpy(buf3, _fn);
+
+    if (p = strrchr(fn, ':'))
+        *p = 0;
+
+    /* on current drive ./:d and .:m point to current dir
+     * on another drive to root directory, workaround to avoid it */
+
+    if (! strcmp(fn, "/") || ! strcmp(fn, ".") || ! strcmp(fn, "./")) {
+        if (p == NULL) {
+            /* current dir on current drive */
+            fn = getcwd(buf2, FILENAME_MAX);
+            /* getcwd returns NULL on root dir on drive S */
+            if (fn == NULL)
+                fn = strcpy(buf2, "/:S");
+            /* getcwd returns /:d on root dir on any other drive */
+            if (fn[1] == ':')
+                return rdirstat(fn, st);
+        } else {
+            *p = ':';
+            return rdirstat(fn, st);
+        }
+        if (p)
+            *p = ':';
+    } else {
+        if (p)
+            *p = ':';
+        if (*fn != '.' && *fn != '/') {
+            strcpy(buf2, "./");
+            fn = strcat(buf2, fn);
+        }
+    }
+
+    if (buf2 != fn)
+        strcpy(buf2, fn);
+    /* remove trailing slash before optional disk name */
+    if (p = strrchr(buf2, '/')) {
+        if (p[1] == ':') {
+            *p = p[1];
+            p[1] = p[2];
+            p[2] = p[3];
+        } else if (p[1] == '\0')
+            *p = '\0';
+    }
+    /* if fn is a file get file directory block structure and device */
+    if (fdb = _locate(buf2, buf, &st->st_dev)) {
+        /* is it a file from another user... */
+        if (strchr(buf2, '\\')
+        /* a public system file... */
+         || fdb->fileowner == 0
+        /* or a file from the current user account ? */
+         || fdb->fileowner == getuid())
+        /* yes, return stat */
+            return _stat_(st, fdb);
+        else {
+            /* no, say file doesn't exist */
+            errno = _errnum = ENOENT;
+            _errarg = fn;
+            return -1;
+        }
+    }
+    /* else should be a device, get device number from device name */
+    st->st_rdev = st->st_dev = _lub_name(*fn == ':' ? fn+1 : fn);
+    /* if it is really a device return device status */
+    if (st->st_dev != -1 && getlub(st->st_dev) != 255)
+        return _dstat_(st);
+    /* neither an existing file or a device name, return EOF */
+    st->st_rdev = st->st_dev = 0;
+    errno = _errnum = ENOENT;
+    _errarg = fn;
+    return -1;
+}
+
+/* replacement for fstat */
+
+int _fstat(int fd, struct stat *st)
+{
+    unsigned short fsanum;
+    struct fsa fsa;
+    register FILE *fp;
+    int status;
+    register int i;
+    register char *p;
+
+    if (fd < FOPEN_MAX) {
+        fp = &stdin[fd];
+        /* get File Save Area number */
+        if (_fcntl(fp,1,0) & 0x80) {
+            fsanum = (unsigned short) _fcntl(fp,83,0);
+            st->st_dev = (unsigned short) _fcntl(fp,5,0);
+
+            if (st->st_dev >= A_DISK && st->st_dev <= Z_DISK) {
+                /* if opened file is a disk file */
+                /* copy far fsa in protected segment to local fsa */
+                for (i = 0, fsanum *= sizeof(fsa), p = (char *) &fsa;
+                     i < (sizeof(fsa));
+                     i++, fsanum++, p++)
+                    *p = _peekfsa((char *) fsanum);
+                /* build stat structure from fsa */
+                status = _stat_(st, (struct fdb*) &fsa);
+                /* get blocksize */
+                if ((st->st_blksize = _fcntl(fp,817,0)) == 0)
+                    st->st_blksize = BUFSIZ;
+                return status;
+            }
+            /* return device status */
+            return _dstat_(st);
+        }
+    }
+    errno = _errnum = EBADF;
+    return -1;
+}
+
+static int _isprt(int dev)
+{
+    return IS_PRT_LUB(dev);
+}
+
+/* device stat */
+
+int _dstat_(st)
+register struct stat* st;
+{
+    register struct ucb* ucb;
+
+    ucb = getucb(st->st_dev);
+    st->st_ino = 0;
+    if (st->st_dev <= Z_DISK
+     || (st->st_dev >= TAPE1 && st->st_dev <= TAPE4)) {
+        st->st_mode = S_IFBLK | S_IWUSR | S_IRUSR;
+        if (peekucb(&ucb->devowner) == 255)
+            st->st_mode |= S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH;
+    } else {
+        st->st_mode = S_IFCHR | S_IWUSR;
+        if (_isprt(st->st_dev))
+            st->st_mode |= S_IRUSR;
+        if (peekucb(&ucb->devowner) == 255) {
+            st->st_mode |= S_IWGRP | S_IWOTH;
+            if (_isprt(st->st_dev))
+                st->st_mode |= S_IRGRP | S_IROTH;
+        }
+    }
+    st->st_nlink = 1;
+    st->st_uid = st->st_gid = getuid();
+    st->st_size = 0;
+    st->st_atime = st->st_mtime = st->st_ctime = 0;
+    st->st_rlen = 0;
+    st->st_klen = 0;
+    st->st_grow = 0;
+    st->st_blksize = 0;
+    return 0;
+}
+
+/* regular file stat */
+
+int _stat_(st, fdb)
+register struct stat* st;
+register struct fdb* fdb;
+{
+    st->st_rdev = st->st_dev;
+    st->st_ino = 0;
+    st->st_org = fdb->filestat;
+
+    /* map fdb file status to stat mode */
+    switch (fdb->filestat) {
+    case _FDB_STAT_LIBRARY:         st->st_mode = S_IFLIB;    break;
+    case _FDB_STAT_DIRECTORY:       st->st_mode = S_IFDIR;    break;
+    case _FDB_STAT_STREAM:          st->st_mode = S_IFREG;    break;
+    case _FDB_STAT_RELATIVE:        st->st_mode = S_IFREL;    break;
+    case _FDB_STAT_KEYED:           st->st_mode = S_IFKEY;    break;
+    case _FDB_STAT_INDEXED:         st->st_mode = S_IFIND;    break;
+    case _FDB_STAT_RANDOM:          st->st_mode = S_IFRND;    break;
+    case _FDB_STAT_PROGRAM:         st->st_mode = S_IFR16;    break;
+    case _FDB_STAT_16_BIT_PROGRAM:  st->st_mode = S_IFP16;    break;
+    case _FDB_STAT_32_BIT_PROGRAM:  st->st_mode = S_IFP32;    break;
+    }
+
+    /* map theos file protection codes to stat mode */
+    st->st_mode |= _tm2um_(st->st_protect = fdb->protect);
+    st->st_nlink = 1;
+    st->st_uid = st->st_gid = fdb->fileowner;
+    st->st_size = fdb->filesize;
+    st->st_atime = st->st_mtime = st->st_ctime = getfiledate(fdb);
+    st->st_blksize = 0;
+    /* specific theos information */
+    st->st_rlen = fdb->reclen;
+    st->st_klen = fdb->keylen;
+    st->st_grow = fdb->filegrow;
+    return 0;
+}
+
+#include <direct.h>
+
+/* standard diropen fails on path endung with a '/', workaround */
+
+struct dirent* _opendir(const char* dirpath)
+{
+    int l;
+    char dirp[FILENAME_MAX];
+    struct dirent* dir;
+
+    if (dirpath && (l = strlen(dirpath))) {
+        if (dirpath[l - 1] == '/') {
+            strcpy(dirp, dirpath);
+            dirp[l - 1] = '\0';
+            return opendir(dirp);
+        }
+    }
+    return opendir(dirpath);
+}
diff --git a/theos/charconv.h b/theos/charconv.h
new file mode 100644 (file)
index 0000000..a2d8dfa
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+
+#ifdef IZ_THS2ISO_ARRAY
+ZCONST uch Far ths2iso[] = {
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* 80 - 87 */
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* 88 - 8F */
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* 90 - 97 */
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* 98 - 9F */
+    0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,  /* A0 - A7 */
+    0x2B, 0x2D, 0x7C, 0x2B, 0x2B, 0x2B, 0x2B, 0x23,  /* A8 - AF */
+    0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,  /* B0 - B7 */
+    0x3D, 0x23, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,  /* B8 - BF */
+    0xC4, 0xE4, 0xE2, 0xE0, 0xE1, 0xC9, 0xEB, 0xEA,  /* C0 - C7 */
+    0xE8, 0xE9, 0xEF, 0xEE, 0xEC, 0xED, 0xD6, 0xF6,  /* C8 - CF */
+    0xF4, 0xF2, 0xF3, 0xDC, 0xFC, 0xFB, 0xF9, 0xFA,  /* D0 - D7 */
+    0xC7, 0xE7, 0xD1, 0xF1, 0xC6, 0xE6, 0xC5, 0xE5,  /* D8 - DF */
+    0xDF, 0xBF, 0xA1, 0xA2, 0xA3, 0xA5, 0xB5, 0xA4,  /* E0 - E7 */
+    0xBC, 0xBD, 0xFF, 0xA7, 0xB0, 0xB2, 0x20, 0x20,  /* E8 - EF */
+    0x20, 0xB1, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* F0 - F7 */
+    0x20, 0x20, 0xB7, 0x20, 0x20, 0x20, 0x20, 0x20   /* F8 - FF */
+};
+#endif /* IZ_THS2ISO_ARRAY */
+
+#ifdef IZ_THS2OEM_ARRAY
+ZCONST uch Far ths2oem[] = {
+    254,254,254,254, 254,254,134,135,   /* 80 - 87 */
+    136,137,138,139, 140,141,142,143,   /* 88 - 8F */
+    144,145,146,147, 148,149,150,151,   /* 90 - 97 */
+    152,153,154,155, 156,157,158,159,   /* 98 - 9F */
+    218,191,217,192, 197,195,180,194,   /* A0 - A7 */
+    193,196,179,218, 191,217,192,201,   /* A8 - AF */
+    183,188,200,206, 199,182,203,202,   /* B0 - B7 */
+    205,186,186,187, 188,189,190,191,   /* B8 - BF */
+    142,132,131,133, 160,144,137,136,   /* C0 - C7 */
+    138,130,139,140, 141,161,153,148,   /* C8 - CF */
+    147,149,162,154, 129,150,151,163,   /* D0 - D7 */
+    128,135,165,164, 146,145,143,134,   /* D8 - DF */
+    225,168,173,155, 156,157,158, 31,   /* E0 - E7 */
+    172,171,152, 21, 248,253,238,239,   /* E8 - EF */
+    240,241,242,243, 244,245,246,247,   /* F0 - F7 */
+    248,249,250,251, 252,253,254,255    /* F8 - FF */
+};
+#endif /* IZ_THS2OEM_ARRAY */
+
+#ifdef IZ_ISO2THS_ARRAY
+ZCONST uch Far iso2ths[] = {
+    0x3F, 0x3F, 0x27, 0x3F, 0x22, 0x2E, 0xA4, 0xB3,  /* 80 - 87 */
+    0x5E, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F,  /* 88 - 8F */
+    0x3F, 0x27, 0x27, 0x22, 0x22, 0x07, 0x2D, 0x2D,  /* 90 - 97 */
+    0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59,  /* 98 - 9F */
+    0x20, 0xE2, 0xE3, 0xE4, 0xE7, 0xE5, 0x7C, 0xEB,  /* A0 - A7 */
+    0x20, 0x20, 0x20, 0x22, 0x20, 0x2D, 0x20, 0x2D,  /* A8 - AF */
+    0xEC, 0xF1, 0xED, 0x20, 0x20, 0xE6, 0x20, 0xFA,  /* B0 - B7 */
+    0x20, 0x20, 0x20, 0x22, 0xE8, 0xE9, 0x20, 0xE1,  /* B8 - BF */
+    0xC3, 0xC4, 0xC2, 0x41, 0xC0, 0xDE, 0xDC, 0xD8,  /* C0 - C7 */
+    0xC8, 0xC5, 0xC7, 0xC6, 0xCC, 0xCD, 0xCB, 0xCA,  /* C8 - CF */
+    0x44, 0xDA, 0xD1, 0xD2, 0xD0, 0x4F, 0xCE, 0x78,  /* D0 - D7 */
+    0x4F, 0xD6, 0xD7, 0xD5, 0xD3, 0x59, 0x20, 0xE0,  /* D8 - DF */
+    0xC3, 0xC4, 0xC2, 0x61, 0xC1, 0xDF, 0xDD, 0xD9,  /* E0 - E7 */
+    0xC8, 0xC9, 0xC7, 0xC6, 0xCC, 0xCD, 0xCB, 0xCA,  /* E8 - EF */
+    0x64, 0xDB, 0xD1, 0xD2, 0xD0, 0x4F, 0xCF, 0xF1,  /* F0 - F7 */
+    0x6F, 0xD6, 0xD7, 0xD5, 0xD4, 0x79, 0x20, 0xEA   /* F8 - FF */
+};
+#endif /* IZ_ISO2THS_ARRAY */
+
+#ifdef IZ_OEM2THS_ARRAY
+ZCONST uch Far oem2ths[] = {
+    216,212,201,194, 193,195,223,217,   /* 80 - 87 */
+    199,198,200,202, 203,204,192,222,   /* 88 - 8F */
+    197,221,220,208, 207,209,213,214,   /* 90 - 97 */
+    234,206,211,227, 228,229,230,159,   /* 98 - 9F */
+    196,205,210,215, 219,218,254,254,   /* A0 - A7 */
+    225,254,254,233, 232,226, 34, 34,   /* A8 - AF */
+    254,254,254,170, 166,166,181,176,   /* B0 - B7 */
+    161,181,185,176, 177,177,162,161,   /* B8 - BF */
+    163,168,167,165, 169,164,165,180,   /* C0 - C7 */
+    178,175,183,182, 180,184,179,168,   /* C8 - CF */
+    183,167,182,178, 163,160,175,179,   /* D0 - D7 */
+    164,162,160,254, 254,254,254,254,   /* D8 - DF */
+    254,224,254,254, 254,254,254, 31,   /* E0 - E7 */
+    254,254,254, 21, 254,254,238,239,   /* E8 - EF */
+    240,241,242,243, 244,245,246,247,   /* F0 - F7 */
+    236,249,250,251, 252,237,254,255    /* F8 - FF */
+};
+#endif /* IZ_OEM2THS_ARRAY */
+
diff --git a/theos/osdep.h b/theos/osdep.h
new file mode 100644 (file)
index 0000000..4f4857e
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/*
+ * XXX this should somehow depend on the stuff in revision.h
+ */
+#pragma prog 2.3,0,0,0
+
+/* use argument expansion */
+#if !defined(UTIL) && !defined(MAINWA_BUG)
+#  pragma wild argv
+#endif
+
+#include <stdio.h>
+#include <malloc.h>
+#include <handle.h>
+#include <conio.h>>
+#include <locale.h>
+#include <sys/types.h>
+#include "theos/stat.h" /* use JMD's extended stat function */
+
+#define isatty() _isatty() /* THEOS isatty uses a FILE* instead of a fd */
+int _isatty(int fd);
+
+#define deletedir(d) rmdir(d)
+
+/* will come later */
+#if 0
+#define USE_EF_UT_TIME          /* Enable use of "UT" extra field time info */
+#endif
+
+#if DEBUG
+int _fprintf(FILE* fp, const char* fmt, ...);
+#endif
+
+/* for rename() replacement. Standard function is bugged */
+
+int _rename(const char* old, const char* new);
+#define rename(a,b) _rename(a,b)
+
+#ifdef LOCATE_BUG
+/* for fopen replacement. Standard function fails on relative path pointing
+ * to root directory.
+ */
+#undef _fopen
+#undef open
+#define fopen() _fopen()
+FILE* _fopen(const char*, const char*);
+#define open() __open()
+FILE* __open(const char*, int);
+#endif
+
+#define EXDEV   10000
diff --git a/theos/stat.h b/theos/stat.h
new file mode 100644 (file)
index 0000000..3a716f8
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __theos_stat_h
+#define __theos_stat_h
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+
+/* extended stat structure for stat, fstat, chmod */
+/* Written by Jean-Michel Dubois */
+
+#pragma field word
+struct stat {
+    unsigned short  st_mode;        /* file attributes */
+        #define S_IFMT      0xf000      /* file type mask */
+        #define S_IFIFO     0x1000      /* pipe */
+        #define S_IFCHR     0x2000      /* char device */
+        #define S_IFSOCK    0x3000      /* socket */
+        #define S_IFDIR     0x4000      /* directory */
+        #define S_IFLIB     0x5000      /* library */
+        #define S_IFBLK     0x6000      /* block device */
+        #define S_IFREG     0x8000      /* regular file */
+        #define S_IFREL     0x9000      /* relative (direct) */
+        #define S_IFKEY     0xA000      /* keyed */
+        #define S_IFIND     0xB000      /* indexed */
+        #define S_IFRND     0xC000      /* ???? */
+        #define S_IFR16     0xD000      /* 16 bit real mode program */
+        #define S_IFP16     0xE000      /* 16 bit protected mode prog */
+        #define S_IFP32     0xF000      /* 32 bit protected mode prog */
+
+        #define S_ISUID     0x0800      /* meaningless */
+        #define S_ISGID     0x0400      /* meaningless */
+        #define S_ISVTX     0x0200      /* meaningless */
+
+        #define S_IMODF     0x0800      /* modified */
+        #define S_INHID     0x0400      /* not hidden */
+
+        #define S_IRWXU     0x03c0      /* read,write,execute: owner */
+        #define S_IEUSR     0x0200      /* erase permission: owner */
+        #define S_IRUSR     0x0100      /* read permission: owner */
+        #define S_IWUSR     0x0080      /* write permission: owner */
+        #define S_IXUSR     0x0040      /* execute permission: owner */
+    /* group permissions */
+        #define S_IRWXG     0x0238
+        #define S_IEGRP     0x0200
+        #define S_IRGRP     0x0020
+        #define S_IWGRP     0x0010
+        #define S_IXGRP     0x0008
+    /* other never has erase permission */
+        #define S_IRWXO     0x0207      /* read,write,execute: other */
+        #define S_IROTH     0x0004      /* read permission: other */
+        #define S_IWOTH     0x0002      /* write permission: other */
+        #define S_IXOTH     0x0001      /* execute permission: other */
+
+        #define S_IREAD     0x0100      /* read permission, owner */
+        #define S_IEXEC     0x0040      /* execute permission, owner */
+        #define S_IWRITE    0x0080      /* write permission, owner */
+    short           st_ino;         /* not used */
+    short           st_dev;         /* not used */
+    short           st_rdev;        /* not used */
+    short           st_nlink;       /* not used */
+    short           st_uid;         /* owner id */
+    short           st_gid;         /* not used */
+    unsigned long   st_size;        /* size of file */
+    unsigned long   st_atime;       /* not used */
+    unsigned long   st_mtime;       /* date & time last modified */
+    unsigned long   st_ctime;       /* not used */
+    unsigned long   st_blksize;     /* buffer size */
+    unsigned short  st_org;         /* organization */
+    unsigned short  st_rlen;        /* record size */
+    unsigned short  st_klen;        /* key size */
+    char            st_grow;        /* growing factor */
+    char            st_protect;     /* native protections */
+};
+#pragma field
+
+#define S_ISREG(m)      (((m) & S_IFMT) >= S_IFREG)
+#define S_ISLIB(m)      (((m) & S_IFMT) == S_IFLIB)
+#define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
+#define S_ISCHR(m)      (((m) & S_IFMT) == S_IFCHR)
+#define S_ISBLK(m)      (((m) & S_IFMT) == S_IFBLK)
+
+#define S_ISSEQ(m)      (((m) & S_IFMT) == S_IFREG)
+#define S_ISREL(m)      (((m) & S_IFMT) == S_IFREL)
+#define S_ISKEY(m)      (((m) & S_IFMT) == S_IFKEY)
+#define S_ISIND(m)      (((m) & S_IFMT) == S_IFIND)
+#define S_ISPRG(m)      (((m) & S_IFMT) >= S_IFP16)
+#define S_ISLNK(m)      0
+
+/* avoid conflict with original THEOS functions */
+
+#define stat(a,b)       _stat(a,b)
+#define fstat(a,b)      _fstat(a,b)
+#define chmod(a,b)      _chmod(a,b)
+
+extern int _stat(const char *file, struct stat *statptr);
+extern int _fstat(int fd, struct stat *statptr);
+extern int _chmod(const char *file, short mask);
+
+#define _chstat(a,b)    ((int) _sc_168(a,'p',(size_t)(b)))
+extern unsigned short   _sc_168(const char _far *fn, int cmd, size_t value);
+
+#endif /* !__theos_stat_h */
diff --git a/theos/theos.c b/theos/theos.c
new file mode 100644 (file)
index 0000000..17db108
--- /dev/null
@@ -0,0 +1,558 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+  theos.c (zip)
+
+  Contribution by Jean-Michel Dubois. 20-Jun-1995, 20-Dec-98
+
+  THEOS specific extra informations
+
+  ---------------------------------------------------------------------------*/
+
+
+#include <stdio.h>
+
+#ifndef UTIL
+
+#include "zip.h"
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include <sc.h>
+#include <direct.h>
+#include <sys/utime.h>
+
+#define opendir(a) _opendir(a)
+extern struct dirent* _opendir(char* fname);
+
+#define PAD 0
+
+#define RET_ERROR 1
+#define RET_SUCCESS 0
+#define RET_EOF 0
+
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+/* match from Phase One Systems */
+
+int match(char *s, char *p)    /*S Returns non-zero if string matches
+                                   the literal mask */
+{
+  int matched, k;
+
+  if (!(*p))
+    return 1;
+  for(;;) {
+    if ( (!(*s)) && (!(*p)) )
+      return(1);
+    else if ( !(*p) )
+      return(0);
+    else if (*p == '*') {
+      if (!*(p+1))
+        return(1);
+      k=0;
+      do {
+        matched = match(s+k,p+1);
+        k++;
+      } while ( (!matched) && *(s+k));
+      return(matched);
+    } else if (*p == '@') {
+      if (!((*s >= 'a' && *s <= 'z')
+          ||(*s >= 'A' && *s <= 'Z')))
+        return(0);
+    } else if (*p == '#') {
+      if (*s < '0' || *s > '9')
+        return(0);
+    } else if (*p != '?') {
+      if (tolower(*s) != tolower(*p))
+        return(0);
+    }
+    s++; p++;
+  }
+}
+
+local char *readd(d)
+DIR *d; /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+   no more entries or an error occurs. */
+{
+  struct dirent *e;
+
+  e = readdir(d);
+  return e == NULL ? (char *) NULL : e->d_name;
+}
+
+/* check if file is a member of a library */
+
+int ismember(char* path)
+{
+    char* p;
+
+    if ((p = strrchr(path, '/')) == NULL)
+        p = path;
+    return ((p = strchr(p, '.')) && (p = strchr(p + 1, '.')));
+}
+
+/* extract library name from a file name */
+
+char* libname(char* path)
+{
+    char* p;
+    static char lib[FILENAME_MAX];
+    char drive[3];
+
+    strcpy(lib, path);
+    if (p = strrchr(lib, ':')) {
+        strncpy(drive, p, 2);
+        drive[2] = '\0';
+        *p = '\0' ;
+    } else
+        drive[0] = '\0';
+
+    if ((p = strrchr(lib, '/')) == NULL)
+        p = lib;
+
+    p = strchr(p, '.');
+    p = strchr(p + 1, '.');
+    *p = 0;
+    strcat(lib, drive);
+    return lib;
+}
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  char *a;              /* path and name for recursion */
+  DIR *d;               /* directory stream from opendir() */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist *z;      /* steps through zfiles list */
+  struct flist *f;      /* steps through files list */
+  char* path;           /* full name */
+  char drive[3];        /* drive name */
+  int recursion;        /* save recurse flag */
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (LSSTAT(n, &s)) {
+    /* Not a file or directory--search for shell expression in zip file */
+    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (match(z->iname, p))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory or library */
+  if (S_ISREG(s.st_mode)) {
+    if ((path = malloc(strlen(n) + 2)) == NULL)
+      return ZE_MEM;
+
+    strcpy(path, n);
+
+    /* if member name, include library name before any member name */
+    if (ismember(path)) {
+      strcpy(path, libname(path));
+      /* mask recursion flag to avoid endless loop recursion
+       * if -r is used with member names
+       */
+      recursion = recurse;
+      recurse = FALSE;
+      if ((m = procname(path, caseflag)) != ZE_OK)   /* recurse on name */
+      {
+        if (m == ZE_MISS)
+          zipwarn("name not matched: ", path);
+        else
+          ziperr(m, a);
+      }
+      /* restore recursion flag */
+      recurse = recursion;
+    }
+
+    strcpy(path, n);
+
+    if ((p = strchr(path, ':')) != NULL) {
+      p[2] = '\0';
+      strcpy(drive, p);
+    } else
+      drive[0] = '\0';
+
+    /* remove trailing dot in flat file name */
+    p = strend(path) - 1;
+    if (*p == '.')
+      *p = '\0';
+
+    strcat(path, drive);
+    /* add or remove name of file */
+    if ((m = newname(path, 0, caseflag)) != ZE_OK) {
+      free(path);
+      return m;
+    }
+    free(path);
+  } else if (S_ISLIB(s.st_mode)) {
+    if ((path = malloc(strlen(n) + 2)) == NULL)
+      return ZE_MEM;
+
+    strcpy(path, n);
+
+    if ((p = strchr(path, ':')) != NULL) {
+      p[2] = '\0';
+      strcpy(drive, p);
+    } else
+      drive[0] = '\0';
+
+    /* add a trailing dot in flat file name... */
+    p = strend(path) - 1;
+    if (*p != '/')
+      strcat(path, "/");
+    p = strend(path);
+    /* ... then add drive name */
+    strcpy(p, drive);
+
+    /* don't include the library name twice... or more */
+    for (f = found; f != NULL; f = f->nxt) {
+      if (! stricmp(path, f->name)) {
+        free(path);
+        return ZE_OK;
+      }
+    }
+    /* add or remove name of library */
+    if ((m = newname(path, 0, caseflag)) != ZE_OK) {
+      free(path);
+      return m;
+    }
+    /* recurse into library if required */
+    strcpy(p - 1, ".*");
+    strcat(p, drive);
+    if (recurse && diropen(path) == 0)
+    {
+      while ((e = dirread()) != NULL) {
+        if (strcmp(e, ".") && strcmp(e, ".."))
+        {
+          if (*drive == '\0')
+            *strchr(e, ':') = '\0';
+          if ((a = malloc(strlen(e) + 1)) == NULL)
+          {
+            dirclose();
+            free((zvoid *)p);
+            return ZE_MEM;
+          }
+          strcpy(a, e);
+          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
+          {
+            if (m == ZE_MISS)
+              zipwarn("name not matched: ", a);
+            else
+              ziperr(m, a);
+          }
+          free((zvoid *)a);
+        }
+      }
+      dirclose();
+    }
+    free(path);
+  } else {
+    /* Add trailing / to the directory name */
+    if ((p = malloc(strlen(n)+2)) == NULL)
+      return ZE_MEM;
+    if (strcmp(n, ".") == 0) {
+      *p = '\0';  /* avoid "./" prefix and do not create zip entry */
+    } else {
+      strcpy(p, n);
+      a = p + strlen(p);
+      if (a[-1] != '/')
+        strcpy(a, "/");
+      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+        free((zvoid *)p);
+        return m;
+      }
+    }
+    /* recurse into directory */
+    if (recurse && (d = opendir(n)) != NULL)
+    {
+      while ((e = readd(d)) != NULL) {
+        if (strcmp(e, ".") && strcmp(e, ".."))
+        {
+          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+          {
+            closedir(d);
+            free((zvoid *)p);
+            return ZE_MEM;
+          }
+          strcat(strcpy(a, p), e);
+          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
+          {
+            if (m == ZE_MISS)
+              zipwarn("name not matched: ", a);
+            else
+              ziperr(m, a);
+          }
+          free((zvoid *)a);
+        }
+      }
+      closedir(d);
+    }
+    free((zvoid *)p);
+  }
+  return ZE_OK;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t;              /* shortened name */
+  char *p;
+  int dosflag;
+
+  dosflag = dosify;  /* default for non-DOS and non-OS/2 */
+
+  /* Find starting point in name before doing malloc */
+  for (t = x; *t == '/'; t++)
+    ;
+
+  /* Make changes, if any, to the copied name (leave original intact) */
+  if (!pathput)
+    t = last(t, '/');
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL)
+    return NULL;
+
+  strcpy(n, t);
+  if (p = strchr(n, ':'))
+    *p = '\0';
+  for (p = n; *p = tolower(*p); p++);
+
+  if (isdir == 42) return n;      /* avoid warning on unused variable */
+
+  if (dosify)
+    msname(n);
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+  return n;
+}
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+
+  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+    return NULL;
+  strcpy(x, n);
+  return x;
+}
+
+/*
+ * XXX use ztimbuf in both POSIX and non POSIX cases ?
+ */
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+  struct utimbuf u;     /* argument for utime()  const ?? */
+
+  /* Convert DOS time to time_t format in u */
+  u.actime = u.modtime = dos2unixtime(d);
+  utime(f, &u);
+}
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes. Bits 8 to 15 contains native THEOS protection
+   code. If n is not NULL, store the file size there.  If t is not NULL,
+   the file's access, modification and creation times are stored there as
+   UNIX time_t values. If f is "-", use standard input as the file. If f is
+   a device, return a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  char *name;
+  unsigned int len = strlen(f);
+
+  if (f == label) {
+    if (a != NULL)
+      *a = label_mode;
+    if (n != NULL)
+      *n = -2L; /* convention for a label name */
+    if (t != NULL)
+      t->atime = t->mtime = t->ctime = label_utim;
+    return label_time;
+  }
+
+  if ((name = malloc(len + 1)) == NULL) {
+    ZIPERR(ZE_MEM, "filetime");
+  }
+  strcpy(name, f);
+
+  if (name[len - 1] == '/' || name[len - 1] == '.')
+    name[len - 1] = '\0';
+
+  /* not all systems allow stat'ing a file with / appended */
+  if (strcmp(f, "-") == 0) {
+    if (fstat(fileno(stdin), &s) != 0) {
+      free(name);
+      error("fstat(stdin)");
+    }
+  } else if (LSSTAT(name, &s) != 0) {
+    /* Accept about any file kind including directories
+     * (stored with trailing / with -r option)
+     */
+    free(name);
+    return 0;
+  }
+
+  if (a != NULL) {
+    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
+    if ((s.st_mode & S_IFMT) == S_IFDIR
+     || (s.st_mode & S_IFMT) == S_IFLIB) {
+      *a |= MSDOS_DIR_ATTR;
+    }
+    /* Map Theos' hidden attribute to DOS's hidden attribute */
+    if (!(st.st_protect & 0x80))
+      *a |= MSDOS_HIDDEN_ATTR;
+    *a |= ((ulg) s.st_protect) << 8;
+  }
+  if (n != NULL)
+    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = t->mtime;   /* best guess, (s.st_ctime: last status change!!) */
+  }
+
+  free(name);
+
+  return unix2dostime(&s.st_mtime);
+}
+/*
+ *      Get file THEOS attributes and store them into extent fields.
+ *      On error leave z intact.
+ */
+
+/*
+*   Extra record format
+*   ===================
+*   signature       (2 bytes)   = 'T','h'
+*   size            (2 bytes)
+*   flags           (1 byte)
+*   filesize        (4 bytes)
+*   keylen          (2 bytes)
+*   reclen          (2 bytes)
+*   filegrow        (1 byte)
+*   reserved        (4 bytes)
+*/
+
+#define EB_L_THSIZE     4
+#define EB_L_TH_SIZE    14
+
+int set_extra_field(z, z_utim)
+  struct zlist *z;
+  iztimes *z_utim;
+  /* store full data in local header but just modification time stamp info
+     in central header */
+{
+  char *extra = NULL;
+  char *p;
+  char c;
+  struct stat st;
+  int status;
+
+  if (status = stat(z->name, &st)) {
+    p = &z->name[strlen(z->name) - 1];
+    if (*p == '/' || *p == '.') {
+      c = *p;
+      *p = '\0';
+      status = stat(z->name, &st);
+      *p = c;
+    }
+#ifdef DEBUG
+    fprintf(stderr, "set_extra_field: stat for file %s:\n status = %d\n",
+        z->name, status);
+#endif
+    if (status)
+      return RET_ERROR;
+  }
+
+  if ((extra = malloc(EB_L_TH_SIZE)) == NULL ) {
+    fprintf(stderr, "set_extra_field: Insufficient memory.\n" );
+    return RET_ERROR;
+  }
+
+
+  extra[0] = 'T';
+  extra[1] = 'h';
+  extra[2] = EB_L_TH_SIZE;
+  extra[3] = EB_L_TH_SIZE >> 8;
+  extra[4] = 0;
+  extra[5] = st.st_size;
+  extra[6] = st.st_size >> 8;
+  extra[7] = st.st_size >> 16;
+  extra[8] = st.st_size >> 24;
+  extra[9] = st.st_org;
+  extra[10] = st.st_rlen;
+  extra[11] = st.st_rlen >> 8;
+  extra[12] = st.st_klen;
+  extra[13] = st.st_klen >> 8;
+  extra[14] = st.st_grow;
+  extra[15] = st.st_protect;
+  extra[16] = 0;
+  extra[17] = 0;
+  z->ext = z->cext = EB_L_TH_SIZE + EB_HEADSIZE;
+  z->extra = z->cextra = extra;
+  return RET_SUCCESS;
+}
+#endif
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+void version_local()
+{
+  printf("Compiled with THEOS C 5.28 for THEOS 4.x on %s %s.\n\n",
+    __DATE__, __TIME__);
+}
+
diff --git a/theos/zipup.h b/theos/zipup.h
new file mode 100644 (file)
index 0000000..1de3f61
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef O_RDONLY
+#  define O_RDONLY 0
+#endif
+#define fhow O_RDONLY
+#define fbad (-1)
+typedef int ftype;
+#define zopen(n,p) open(n,p)
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f) close(f)
+#define zerr(f) (k == (extent)(-1L))
+#define zstdin 0
diff --git a/tops20/make.mic b/tops20/make.mic
new file mode 100644 (file)
index 0000000..f93fa77
--- /dev/null
@@ -0,0 +1,36 @@
+@te no pau e
+@cc -c -q zip
+@cc -c -q zipfil
+@cc -c -q zipup
+@cc -c -q fileio
+@cc -c -q util
+@cc -c -q crc32
+@cc -c -q crctab
+@cc -c -q global
+@cc -c -q deflat
+@cc -c -q trees
+@cc -c -q crypt
+@cc -c -q ttyio
+@cc -c -q tops20
+@cc -i -o zip zip.rel zipfil.rel zipup.rel fileio.rel util.rel crc32.rel crctab.rel global.rel deflat.rel trees.rel crypt.rel ttyio.rel tops20.rel
+@cc -c -q zipnot
+@rename zipfil.c zipfix.c
+@rename fileio.c filiox.c
+@rename util.c utilx.c
+@rename tops20.c tops2x.c
+@cc -c -q -DUTIL zipfix
+@cc -c -q -DUTIL filiox
+@cc -c -q -DUTIL utilx
+@cc -c -q -DUTIL tops2x
+@rename zipfix.c zipfil.c
+@rename filiox.c fileio.c
+@rename utilx.c util.c
+@rename tops2x.c tops20.c
+@cc -i -o zipnot zipnot.rel zipfix.rel filiox.rel utilx.rel global.rel tops2x.rel
+@reset
+@rename zipnot.exe zipnote.exe
+@cc -c -q zipspl
+@cc -i -o zipspl zipspl.rel zipfix.rel filiox.rel utilx.rel global.rel tops2x.rel
+@reset
+@rename zipspl.exe zipsplit.exe
+@kmic
diff --git a/tops20/osdep.h b/tops20/osdep.h
new file mode 100644 (file)
index 0000000..1f84496
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef TOPS20
+#define TOPS20
+#endif
+
+#define NO_PROTO
+#define NO_SYMLINK
+#define NO_TERMIO
+#define DIRENT
+#define BIG_MEM
+#define REALLY_SHORT_SYMS
+#define window_size winsiz
+
+extern int isatty();
+
+#define FOPR "rb"
+#define FOPM "r+b"
+#define FOPW "w8"
+
+#define CBSZ 524288
+#define ZBSZ 524288
+
+#include <sys/types.h>
+#include <sys/stat.h>
diff --git a/tops20/rename.mic b/tops20/rename.mic
new file mode 100644 (file)
index 0000000..6a45d26
--- /dev/null
@@ -0,0 +1,6 @@
+@rename zipfile.c zipfil.c
+@rename globals.c global.c
+@rename deflate.c deflat.c
+@rename zipnote.c zipnot.c
+@rename zipsplit.c zipspl.c
+@kmic
diff --git a/tops20/tops20.c b/tops20/tops20.c
new file mode 100644 (file)
index 0000000..7230ed3
--- /dev/null
@@ -0,0 +1,576 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include "zip.h"
+
+#ifndef UTIL    /* the companion #endif is a bit of ways down ... */
+
+#include <time.h>
+
+#define PATH_START '<'
+#define PATH_END   '>'
+
+/* Extra malloc() space in names for cutpath() */
+#define PAD 5         /* may have to change .FOO] to ]FOO.DIR;1 */
+
+
+#define TRUE 1
+#define FALSE 0
+#define O_RDONLY (0)
+#define O_T20_WILD (1<<18)
+#include <monsym.h>    /* Get amazing monsym() macro */
+extern int jsys(), fstat();
+extern char *getcwd();
+extern int _gtjfn(), _rljfn();
+#define JSYS_CLASS    0070000000000
+#define FLD(val,mask) (((unsigned)(val)*((mask)&(-(mask))))&(mask))
+#define _DEFJS(name,class) (FLD(class, JSYS_CLASS) | (monsym(name)&0777777))
+#define JFNS  _DEFJS("JFNS%", 1)
+#define GNJFN _DEFJS("GNJFN%", 0)
+static int wfopen(), wfnext(), strlower(), strupper();
+static char *wfname();
+typedef struct {
+   int  wfjfn;
+   int  more;
+} DIR;
+
+/* Library functions not in (most) header files */
+
+extern int stat(), chmod(), toupper(), tolower();
+
+int utime OF((char *, ztimbuf *));
+
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+/* Local functions */
+local char *readd OF((DIR *));
+
+
+local DIR *opendir(n)
+char *n;                /* directory name to open */
+/* Open the directory *n, returning a pointer to an allocated DIR, or
+   NULL if error. */
+{
+    DIR *d;             /* pointer to malloc'ed directory stream */
+    char    *c;                         /* scans TOPS20 path */
+    int     m;                          /* length of name */
+    char    *p;                         /* temp string */
+
+    if (((d = (DIR *)malloc(sizeof(DIR))) == NULL) ||
+        ((p = (char *)malloc((m = strlen(n)) + 4)) == NULL)) {
+            return NULL;
+    }
+
+/* Directory may be in form "<DIR.SUB1.SUB2>" or "<DIR.SUB1>SUB2.DIRECTORY".
+** If latter, convert to former. */
+
+    if ((m > 0)  &&  (*(c = strcpy(p,n) + m-1) != '>')) {
+        c -= 10;
+        *c-- = '\0';        /* terminate at "DIRECTORY.1" */
+        *c = '>';           /* "." --> ">" */
+        while ((c > p)  &&  (*--c != '>'));
+        *c = '.';           /* ">" --> "." */
+    }
+    strcat(p, "*.*");
+    if ((d->wfjfn = wfopen(p)) == 0) {
+        free((zvoid *)d);
+        free((zvoid *)p);
+        return NULL;
+    }
+    free((zvoid *)p);
+    d->more = TRUE;
+    return (d);
+}
+
+local char *readd(d)
+DIR *d;                 /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+   no more entries or an error occurs. */
+{
+  char    *p;
+  if ((d->more == FALSE) || ((p = wfname(d->wfjfn)) == NULL)) {
+      return NULL;
+  }
+  if (wfnext(d->wfjfn) == 0) {
+      d->more = FALSE;
+  }
+  return p;
+}
+
+
+local void closedir(d)
+DIR *d;                 /* directory stream to close */
+/* Close the directory stream */
+{
+  free((zvoid *)d);
+}
+
+/* Wildcard filename routines */
+
+/* WFOPEN - open wild card filename
+**      Returns wild JFN for filespec, 0 if failure.
+*/
+static int
+wfopen(name)
+char *name;
+{
+    return (_gtjfn(name, (O_RDONLY | O_T20_WILD)));
+}
+
+/* WFNAME - Return filename for wild JFN
+**      Returns pointer to dynamically allocated filename string
+*/
+static char *
+wfname(jfn)
+int jfn;
+{
+    char *fp, fname[200];
+    int ablock[5];
+
+    ablock[1] = (int) (fname - 1);
+    ablock[2] = jfn & 0777777;  /* jfn, no flags */
+    ablock[3] = 0111110000001;  /* DEV+DIR+NAME+TYPE+GEN, punctuate */
+    if (!jsys(JFNS, ablock))
+        return NULL;            /* something bad happened */
+    if ((fp = (char *)malloc(strlen(fname) + 1)) == NULL) {
+        return NULL;
+    }
+    strcpy(fp, fname);          /* copy the file name here */
+    return fp;
+}
+
+/* WFNEXT - Make wild JFN point to next real file
+**      Returns success or failure (not JFN)
+*/
+static int
+wfnext(jfn)
+int jfn;
+{
+    int ablock[5];
+
+    ablock[1] = jfn;            /* save jfn and flags */
+    return jsys(GNJFN, ablock);
+}
+
+
+static int
+strupper(s)     /* Returns s in uppercase */
+char *s;        /* String to be uppercased */
+{
+    char    *p;
+
+    p = s;
+    for (; *p; p++)
+        *p = toupper (*p);
+}
+
+static int
+strlower(s)     /* Returns s in lowercase. */
+char *s;        /* String to be lowercased */
+{
+    char    *p;
+
+    p = s;
+    for (; *p; p++)
+        *p = tolower (*p);
+}
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  DIR *d;               /* directory stream from opendir() */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (LSSTAT(n, &s))
+  {
+    /* Not a file or directory--search for shell expression in zip file */
+    if (caseflag) {
+      p = malloc(strlen(n) + 1);
+      if (p != NULL)
+        strcpy(p, n);
+    } else
+      p = ex2in(n, 0, (int *)NULL);     /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+  if ((s.st_mode & S_IFDIR) == 0)
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  } else {
+    if (dirnames && (m = newname(n, 1, caseflag)) != ZE_OK) {
+      return m;
+    }
+    /* recurse into directory */
+    if (recurse && (d = opendir(n)) != NULL)
+    {
+      while ((e = readd(d)) != NULL) {
+        if ((m = procname(e, caseflag)) != ZE_OK)     /* recurse on name */
+        {
+          closedir(d);
+          return m;
+        }
+      }
+      closedir(d);
+    }
+  } /* (s.st_mode & S_IFDIR) == 0) */
+  return ZE_OK;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t;              /* shortened name */
+  int dosflag;
+
+  int jfn;
+  char *fp, fname[200];
+  int ablock[5];
+
+  jfn = _gtjfn(x, (O_RDONLY));
+  ablock[1] = (int) (fname - 1);
+  ablock[2] = jfn & 0777777;    /* jfn, no flags */
+  ablock[3] = 0111100000001;    /* DEV+DIR+NAME+TYPE, punctuate */
+  if (!jsys(JFNS, ablock)) {
+      _rljfn(jfn);
+      return NULL;              /* something bad happened */
+  }
+  _rljfn(jfn);
+  if ((fp = (char *)malloc(strlen(fname) + 1)) == NULL) {
+      return NULL;
+  }
+  strcpy(fp, fname);            /* copy the file name here */
+  x = fp;
+
+  dosflag = dosify; /* default for non-DOS and non-OS/2 */
+
+  /* Find starting point in name before doing malloc */
+  t = x;
+  if ((n = strrchr(t, ':')) != NULL)
+    t = n + 1;
+  if (*t == PATH_START && (n = strrchr(t, PATH_END)) != NULL)
+    if (*(++t) == '.')
+      /* path is relative to current directory, skip leading '.' */
+      t++;
+
+  /* Make changes, if any, to the copied name (leave original intact) */
+  if (!pathput)
+    t = last(t, PATH_END);
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL)
+    return NULL;
+  strcpy(n, t);
+
+  if ((t = strrchr(n, PATH_END)) != NULL)
+  {
+    *t = '/';
+    while (--t > n)
+      if (*t == '.')
+        *t = '/';
+  }
+
+  /* Fix from Greg Roelofs: */
+  /* Get current working directory and strip from n (t now = n) */
+  {
+    char cwd[256], *p, *q;
+    int c;
+
+    if (getcwd(cwd, 256) && ((p = strchr(cwd, PATH_START)) != NULL))
+    {
+      if (*(++p) == '.')
+        p++;
+      if ((q = strrchr(p, PATH_END)) != NULL)
+      {
+        *q = '/';
+        while (--q > p)
+          if (*q == '.')
+            *q = '/';
+
+        /* strip bogus path parts from n */
+        if (strncmp(n, p, (c=strlen(p))) == 0)
+        {
+          q = n + c;
+          while (*t++ = *q++)
+            ;
+        }
+      }
+    }
+  }
+  strlower(n);
+
+  if (isdir)
+  {
+    if (strcmp((t=n+strlen(n)-6), ".dir;1"))
+      error("directory not version 1");
+    else
+      strcpy(t, "/");
+  }
+
+  if ((t = strrchr(n, '.')) != NULL)
+  {
+    if ( t[1] == '\0')             /* "filename." -> "filename" */
+      *t = '\0';
+  }
+
+  if (dosify)
+    msname(n);
+
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+  return n;
+}
+
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+  char *t;              /* scans name */
+
+  if ((t = strrchr(n, '/')) == NULL)
+  {
+    if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+      return NULL;
+    strcpy(x, n);
+  }
+  else
+  {
+    if ((x = malloc(strlen(n) + 3 + PAD)) == NULL)
+      return NULL;
+    x[0] = PATH_START;
+    x[1] = '.';
+    strcpy(x + 2, n);
+    *(t = x + 2 + (t - n)) = PATH_END;
+    while (--t > x)
+      if (*t == '/')
+        *t = '.';
+  }
+  strupper(x);
+
+  return x;
+}
+
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+  ztimbuf u;            /* argument for utime() */
+
+  /* Convert DOS time to time_t format in u */
+  u.actime = u.modtime = dos2unixtime(d);
+
+  /* Set updated and accessed times of f */
+  utime(f, &u);
+}
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  char *name;
+  unsigned int len = strlen(f);
+
+  if (f == label) {
+    if (a != NULL)
+      *a = label_mode;
+    if (n != NULL)
+      *n = -2L; /* convention for a label name */
+    if (t != NULL)
+      t->atime = t->mtime = t->ctime = label_utim;
+    return label_time;
+  }
+
+  if ((name = malloc(len + 1)) == NULL) {
+    ZIPERR(ZE_MEM, "filetime");
+  }
+
+  strcpy(name, f);
+  if (name[len - 1] == '/')
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+
+  if (strcmp(f, "-") == 0) {
+    if (fstat(fileno(stdin), &s) != 0) {
+      free(name);
+      error("fstat(stdin)");
+    }
+  } else if (LSSTAT(name, &s) != 0)
+             /* Accept about any file kind including directories
+              * (stored with trailing / with -r option)
+              */
+    free(name);
+    return 0;
+  }
+
+  if (a != NULL) {
+    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
+    if ((s.st_mode & S_IFDIR) != 0) {
+      *a |= MSDOS_DIR_ATTR;
+    }
+  }
+  if (n != NULL)
+    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = s.st_ctime;
+  }
+
+  free(name);
+
+  return unix2dostime(&s.st_mtime);
+}
+
+#include <monsym.h>   /* Get amazing monsym() macro */
+#define       _FBBYV  monsym(".FBBYV")
+#define         FBBSZ_S       -24     /* Obsolete, replace by FLDGET! */
+#define         FBBSZ_M       077     /* ditto */
+
+extern int _gtjfn(), _rljfn(), _gtfdb(), stat();
+
+int set_extra_field(z, z_utim)
+  struct zlist far *z;
+  iztimes *z_utim;
+  /* create extra field and change z->att if desired */
+{
+  int jfn;
+
+  translate_eol = 0;
+  jfn = _gtjfn(z->name, O_RDONLY);
+  z->att = (((_gtfdb (jfn, _FBBYV) << FBBSZ_S) & FBBSZ_M) != 8) ?
+           ASCII :BINARY;
+  _rljfn(jfn);
+
+#ifdef USE_EF_UT_TIME
+  if ((z->extra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL)
+    return ZE_MEM;
+
+  z->extra[0]  = 'U';
+  z->extra[1]  = 'T';
+  z->extra[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */
+  z->extra[3]  = 0;
+  z->extra[4]  = EB_UT_FL_MTIME;
+  z->extra[5]  = (char)(z_utim->mtime);
+  z->extra[6]  = (char)(z_utim->mtime >> 8);
+  z->extra[7]  = (char)(z_utim->mtime >> 16);
+  z->extra[8]  = (char)(z_utim->mtime >> 24);
+
+  z->cext = z->ext = (EB_HEADSIZE+EB_UT_LEN(1));
+  z->cextra = z->extra;
+#endif /* USE_EF_UT_TIME */
+
+  return ZE_OK;
+}
+
+int deletedir(d)
+char *d;                /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+   Return the result of rmdir(), delete(), or system().
+   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).
+ */
+{
+    zipwarn("deletedir not implemented yet", "");
+    return 127;
+}
+
+#endif /* !UTIL */
+
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+void version_local()
+{
+    static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
+#if 0
+    char buf[40];
+#endif
+
+    printf(CompiledWith,
+
+#ifdef __GNUC__
+      "gcc ", __VERSION__,
+#else
+#  if 0
+      "cc ", (sprintf(buf, " version %d", _RELEASE), buf),
+#  else
+#  ifdef __COMPILER_KCC__
+      "KCC", "",
+#  else
+      "unknown compiler", "",
+#  endif
+#  endif
+#endif
+
+      "TOPS-20",
+
+#if defined(foobar) || defined(FOOBAR)
+      " (Foo BAR)",   /* OS version or hardware */
+#else
+      "",
+#endif /* Foo BAR */
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+      );
+
+} /* end function version_local() */
diff --git a/tops20/zipup.h b/tops20/zipup.h
new file mode 100644 (file)
index 0000000..47ec563
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#define O_RDONLY (0)
+#define O_UNCONVERTED     (0400) /* Forced NO conversion requested */
+#define fhow (O_RDONLY | O_UNCONVERTED)
+#define fbad (-1)
+typedef int ftype;
+#define zopen(n,p) open(n,p)
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f) close(f)
+#define zerr(f) (k == (extent)(-1L))
+#define zstdin 0
diff --git a/trees.c b/trees.c
new file mode 100644 (file)
index 0000000..094b2bf
--- /dev/null
+++ b/trees.c
@@ -0,0 +1,1401 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2005-February-10 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *  trees.c by Jean-loup Gailly
+ *
+ *  This is a new version of im_ctree.c originally written by Richard B. Wales
+ *  for the defunct implosion method.
+ *  The low level bit string handling routines from bits.c (originally
+ *  im_bits.c written by Richard B. Wales) have been merged into this version
+ *  of trees.c.
+ *
+ *  PURPOSE
+ *
+ *      Encode various sets of source values using variable-length
+ *      binary code trees.
+ *      Output the resulting variable-length bit strings.
+ *      Compression can be done to a file or to memory.
+ *
+ *  DISCUSSION
+ *
+ *      The PKZIP "deflation" process uses several Huffman trees. The more
+ *      common source values are represented by shorter bit sequences.
+ *
+ *      Each code tree is stored in the ZIP file in a compressed form
+ *      which is itself a Huffman encoding of the lengths of
+ *      all the code strings (in ascending order by source values).
+ *      The actual code strings are reconstructed from the lengths in
+ *      the UNZIP process, as described in the "application note"
+ *      (APPNOTE.TXT) distributed as part of PKWARE's PKZIP program.
+ *
+ *      The PKZIP "deflate" file format interprets compressed file data
+ *      as a sequence of bits.  Multi-bit strings in the file may cross
+ *      byte boundaries without restriction.
+ *      The first bit of each byte is the low-order bit.
+ *
+ *      The routines in this file allow a variable-length bit value to
+ *      be output right-to-left (useful for literal values). For
+ *      left-to-right output (useful for code strings from the tree routines),
+ *      the bits must have been reversed first with bi_reverse().
+ *
+ *      For in-memory compression, the compressed bit stream goes directly
+ *      into the requested output buffer. The buffer is limited to 64K on
+ *      16 bit machines; flushing of the output buffer during compression
+ *      process is not supported.
+ *      The input data is read in blocks by the (*read_buf)() function.
+ *
+ *      For more details about input to and output from the deflation routines,
+ *      see the actual input functions for (*read_buf)(), flush_outbuf(), and
+ *      the filecompress() resp. memcompress() wrapper functions which handle
+ *      the I/O setup.
+ *
+ *  REFERENCES
+ *
+ *      Lynch, Thomas J.
+ *          Data Compression:  Techniques and Applications, pp. 53-55.
+ *          Lifetime Learning Publications, 1985.  ISBN 0-534-03418-7.
+ *
+ *      Storer, James A.
+ *          Data Compression:  Methods and Theory, pp. 49-50.
+ *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
+ *
+ *      Sedgewick, R.
+ *          Algorithms, p290.
+ *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ *
+ *  INTERFACE
+ *
+ *      void ct_init (ush *attr, int *method)
+ *          Allocate the match buffer, initialize the various tables and save
+ *          the location of the internal file attribute (ascii/binary) and
+ *          method (DEFLATE/STORE)
+ *
+ *      void ct_tally (int dist, int lc);
+ *          Save the match info and tally the frequency counts.
+ *
+ *      ulg flush_block (char *buf, ulg stored_len, int eof)
+ *          Determine the best encoding for the current block: dynamic trees,
+ *          static trees or store, and output the encoded block to the zip
+ *          file. Returns the total compressed length for the file so far.
+ *
+ *      void bi_init (char *tgt_buf, unsigned tgt_size, int flsh_allowed)
+ *          Initialize the bit string routines.
+ *
+ *    Most of the bit string output functions are only used internally
+ *    in this source file, they are normally declared as "local" routines:
+ *
+ *      local void send_bits (int value, int length)
+ *          Write out a bit string, taking the source bits right to
+ *          left.
+ *
+ *      local unsigned bi_reverse (unsigned code, int len)
+ *          Reverse the bits of a bit string, taking the source bits left to
+ *          right and emitting them right to left.
+ *
+ *      local void bi_windup (void)
+ *          Write out any remaining bits in an incomplete byte.
+ *
+ *      local void copy_block(char *buf, unsigned len, int header)
+ *          Copy a stored block to the zip file, storing first the length and
+ *          its one's complement if requested.
+ *
+ *    All output that exceeds the bitstring output buffer size (as initialized
+ *    by bi_init() is fed through an externally provided transfer routine
+ *    which flushes the bitstring output buffer on request and resets the
+ *    buffer fill counter:
+ *
+ *      extern void flush_outbuf(char *o_buf, unsigned *o_idx);
+ *
+ */
+#define __TREES_C
+
+#include <ctype.h>
+#include "zip.h"
+
+#ifndef USE_ZLIB
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS  256
+/* number of literal bytes 0..255 */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES   30
+/* number of distance codes */
+
+#define BL_CODES  19
+/* number of codes used to transfer the bit lengths */
+
+
+local int near extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local int near extra_dbits[D_CODES] /* extra bits for each distance code */
+   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local int near extra_blbits[BL_CODES]/* extra bits for each bit length code */
+   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#ifndef LIT_BUFSIZE
+#  ifdef SMALL_MEM
+#    define LIT_BUFSIZE  0x2000
+#  else
+#  ifdef MEDIUM_MEM
+#    define LIT_BUFSIZE  0x4000
+#  else
+#    define LIT_BUFSIZE  0x8000
+#  endif
+#  endif
+#endif
+#define DIST_BUFSIZE  LIT_BUFSIZE
+/* Sizes of match buffers for literals/lengths and distances.  There are
+ * 4 reasons for limiting LIT_BUFSIZE to 64K:
+ *   - frequencies can be kept in 16 bit counters
+ *   - if compression is not successful for the first block, all input data is
+ *     still in the window so we can still emit a stored block even when input
+ *     comes from standard input.  (This can also be done for all blocks if
+ *     LIT_BUFSIZE is not greater than 32K.)
+ *   - if compression is not successful for a file smaller than 64K, we can
+ *     even emit a stored file instead of a stored block (saving 5 bytes).
+ *   - creating new Huffman trees less frequently may not provide fast
+ *     adaptation to changes in the input data statistics. (Take for
+ *     example a binary file with poorly compressible code followed by
+ *     a highly compressible string table.) Smaller buffer sizes give
+ *     fast adaptation but have of course the overhead of transmitting trees
+ *     more frequently.
+ *   - I can't count above 4
+ * The current code is general and allows DIST_BUFSIZE < LIT_BUFSIZE (to save
+ * memory at the expense of compression). Some optimizations would be possible
+ * if we rely on DIST_BUFSIZE == LIT_BUFSIZE.
+ */
+
+#define REP_3_6      16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10    17
+/* repeat a zero length 3-10 times  (3 bits of repeat count) */
+
+#define REPZ_11_138  18
+/* repeat a zero length 11-138 times  (7 bits of repeat count) */
+
+/* ===========================================================================
+ * Local data
+ */
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data {
+    union {
+        ush  freq;       /* frequency count */
+        ush  code;       /* bit string */
+    } fc;
+    union {
+        ush  dad;        /* father node in Huffman tree */
+        ush  len;        /* length of bit string */
+    } dl;
+} ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad  dl.dad
+#define Len  dl.len
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+local ct_data near dyn_ltree[HEAP_SIZE];   /* literal and length tree */
+local ct_data near dyn_dtree[2*D_CODES+1]; /* distance tree */
+
+local ct_data near static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see ct_init
+ * below).
+ */
+
+local ct_data near static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+local ct_data near bl_tree[2*BL_CODES+1];
+/* Huffman tree for the bit lengths */
+
+typedef struct tree_desc {
+    ct_data near *dyn_tree;      /* the dynamic tree */
+    ct_data near *static_tree;   /* corresponding static tree or NULL */
+    int     near *extra_bits;    /* extra bits for each code or NULL */
+    int     extra_base;          /* base index for extra_bits */
+    int     elems;               /* max number of elements in the tree */
+    int     max_length;          /* max bit length for the codes */
+    int     max_code;            /* largest code with non zero frequency */
+} tree_desc;
+
+local tree_desc near l_desc =
+{dyn_ltree, static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS, 0};
+
+local tree_desc near d_desc =
+{dyn_dtree, static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS, 0};
+
+local tree_desc near bl_desc =
+{bl_tree, NULL,       extra_blbits, 0,         BL_CODES, MAX_BL_BITS, 0};
+
+
+local ush near bl_count[MAX_BITS+1];
+/* number of codes at each bit length for an optimal tree */
+
+local uch near bl_order[BL_CODES]
+   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+local int near heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+local int heap_len;               /* number of elements in the heap */
+local int heap_max;               /* element of largest frequency */
+/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+local uch near depth[2*L_CODES+1];
+/* Depth of each subtree used as tie breaker for trees of equal frequency */
+
+local uch length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local uch dist_code[512];
+/* distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+local int near base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int near base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#ifndef DYN_ALLOC
+  local uch far l_buf[LIT_BUFSIZE];  /* buffer for literals/lengths */
+  local ush far d_buf[DIST_BUFSIZE]; /* buffer for distances */
+#else
+  local uch far *l_buf;
+  local ush far *d_buf;
+#endif
+
+local uch near flag_buf[(LIT_BUFSIZE/8)];
+/* flag_buf is a bit array distinguishing literals from lengths in
+ * l_buf, and thus indicating the presence or absence of a distance.
+ */
+
+local unsigned last_lit;    /* running index in l_buf */
+local unsigned last_dist;   /* running index in d_buf */
+local unsigned last_flags;  /* running index in flag_buf */
+local uch flags;            /* current flags not yet saved in flag_buf */
+local uch flag_bit;         /* current bit used in flags */
+/* bits are filled in flags starting at bit 0 (least significant).
+ * Note: these flags are overkill in the current code since we don't
+ * take advantage of DIST_BUFSIZE == LIT_BUFSIZE.
+ */
+
+local ulg opt_len;        /* bit length of current block with optimal trees */
+local ulg static_len;     /* bit length of current block with static trees */
+
+local ulg cmpr_bytelen;     /* total byte length of compressed file */
+local ulg cmpr_len_bits;    /* number of bits past 'cmpr_bytelen' */
+
+#ifdef DEBUG
+local ulg input_len;        /* total byte length of input file */
+/* input_len is for debugging only since we can get it by other means. */
+#endif
+
+local ush *file_type;       /* pointer to UNKNOWN, BINARY or ASCII */
+local int *file_method;     /* pointer to DEFLATE or STORE */
+
+/* ===========================================================================
+ * Local data used by the "bit string" routines.
+ */
+
+local int flush_flg;
+
+#if (!defined(ASMV) || !defined(RISCOS))
+local unsigned bi_buf;
+#else
+unsigned bi_buf;
+#endif
+/* Output buffer. bits are inserted starting at the bottom (least significant
+ * bits). The width of bi_buf must be at least 16 bits.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf may be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+#if (!defined(ASMV) || !defined(RISCOS))
+local int bi_valid;
+#else
+int bi_valid;
+#endif
+/* Number of valid bits in bi_buf.  All bits above the last valid bit
+ * are always zero.
+ */
+
+#if (!defined(ASMV) || !defined(RISCOS))
+local char *out_buf;
+#else
+char *out_buf;
+#endif
+/* Current output buffer. */
+
+#if (!defined(ASMV) || !defined(RISCOS))
+local unsigned out_offset;
+#else
+unsigned out_offset;
+#endif
+/* Current offset in output buffer.
+ * On 16 bit machines, the buffer is limited to 64K.
+ */
+
+#if !defined(ASMV) || !defined(RISCOS)
+local unsigned out_size;
+#else
+unsigned out_size;
+#endif
+/* Size of current output buffer */
+
+/* Output a 16 bit value to the bit stream, lower (oldest) byte first */
+#define PUTSHORT(w) \
+{ if (out_offset >= out_size-1) \
+    flush_outbuf(out_buf, &out_offset); \
+  out_buf[out_offset++] = (char) ((w) & 0xff); \
+  out_buf[out_offset++] = (char) ((ush)(w) >> 8); \
+}
+
+#define PUTBYTE(b) \
+{ if (out_offset >= out_size) \
+    flush_outbuf(out_buf, &out_offset); \
+  out_buf[out_offset++] = (char) (b); \
+}
+
+#ifdef DEBUG
+local ulg bits_sent;   /* bit length of the compressed data */
+extern ulg isize;      /* byte length of input file */
+#endif
+
+extern long block_start;       /* window offset of current block */
+extern unsigned near strstart; /* window offset of current string */
+
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void init_block     OF((void));
+local void pqdownheap     OF((ct_data near *tree, int k));
+local void gen_bitlen     OF((tree_desc near *desc));
+local void gen_codes      OF((ct_data near *tree, int max_code));
+local void build_tree     OF((tree_desc near *desc));
+local void scan_tree      OF((ct_data near *tree, int max_code));
+local void send_tree      OF((ct_data near *tree, int max_code));
+local int  build_bl_tree  OF((void));
+local void send_all_trees OF((int lcodes, int dcodes, int blcodes));
+local void compress_block OF((ct_data near *ltree, ct_data near *dtree));
+local void set_file_type  OF((void));
+#if (!defined(ASMV) || !defined(RISCOS))
+local void send_bits      OF((int value, int length));
+local unsigned bi_reverse OF((unsigned code, int len));
+#endif
+local void bi_windup      OF((void));
+local void copy_block     OF((char *buf, unsigned len, int header));
+
+
+#ifndef DEBUG
+#  define send_code(c, tree) send_bits(tree[c].Code, tree[c].Len)
+   /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+#  define send_code(c, tree) \
+     { if (verbose>1) fprintf(stderr,"\ncd %3d ",(c)); \
+       send_bits(tree[c].Code, tree[c].Len); }
+#endif
+
+#define d_code(dist) \
+   ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. dist_code[256] and dist_code[257] are never
+ * used.
+ */
+
+#define Max(a,b) (a >= b ? a : b)
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Allocate the match buffer, initialize the various tables and save the
+ * location of the internal file attribute (ascii/binary) and method
+ * (DEFLATE/STORE).
+ */
+void ct_init(attr, method)
+    ush  *attr;   /* pointer to internal file attribute */
+    int  *method; /* pointer to compression method */
+{
+    int n;        /* iterates over tree elements */
+    int bits;     /* bit counter */
+    int length;   /* length value */
+    int code;     /* code value */
+    int dist;     /* distance index */
+
+    file_type = attr;
+    file_method = method;
+    cmpr_bytelen = cmpr_len_bits = 0L;
+#ifdef DEBUG
+    input_len = 0L;
+#endif
+
+    if (static_dtree[0].Len != 0) return; /* ct_init already called */
+
+#ifdef DYN_ALLOC
+    d_buf = (ush far *) zcalloc(DIST_BUFSIZE, sizeof(ush));
+    l_buf = (uch far *) zcalloc(LIT_BUFSIZE/2, 2);
+    /* Avoid using the value 64K on 16 bit machines */
+    if (l_buf == NULL || d_buf == NULL)
+        ziperr(ZE_MEM, "ct_init: out of memory");
+#endif
+
+    /* Initialize the mapping length (0..255) -> length code (0..28) */
+    length = 0;
+    for (code = 0; code < LENGTH_CODES-1; code++) {
+        base_length[code] = length;
+        for (n = 0; n < (1<<extra_lbits[code]); n++) {
+            length_code[length++] = (uch)code;
+        }
+    }
+    Assert(length == 256, "ct_init: length != 256");
+    /* Note that the length 255 (match length 258) can be represented
+     * in two different ways: code 284 + 5 bits or code 285, so we
+     * overwrite length_code[255] to use the best encoding:
+     */
+    length_code[length-1] = (uch)code;
+
+    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+    dist = 0;
+    for (code = 0 ; code < 16; code++) {
+        base_dist[code] = dist;
+        for (n = 0; n < (1<<extra_dbits[code]); n++) {
+            dist_code[dist++] = (uch)code;
+        }
+    }
+    Assert(dist == 256, "ct_init: dist != 256");
+    dist >>= 7; /* from now on, all distances are divided by 128 */
+    for ( ; code < D_CODES; code++) {
+        base_dist[code] = dist << 7;
+        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+            dist_code[256 + dist++] = (uch)code;
+        }
+    }
+    Assert(dist == 256, "ct_init: 256+dist != 512");
+
+    /* Construct the codes of the static literal tree */
+    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+    n = 0;
+    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+    /* Codes 286 and 287 do not exist, but we must include them in the
+     * tree construction to get a canonical Huffman tree (longest code
+     * all ones)
+     */
+    gen_codes((ct_data near *)static_ltree, L_CODES+1);
+
+    /* The static distance tree is trivial: */
+    for (n = 0; n < D_CODES; n++) {
+        static_dtree[n].Len = 5;
+        static_dtree[n].Code = (ush)bi_reverse(n, 5);
+    }
+
+    /* Initialize the first block of the first file: */
+    init_block();
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block()
+{
+    int n; /* iterates over tree elements */
+
+    /* Initialize the trees. */
+    for (n = 0; n < L_CODES;  n++) dyn_ltree[n].Freq = 0;
+    for (n = 0; n < D_CODES;  n++) dyn_dtree[n].Freq = 0;
+    for (n = 0; n < BL_CODES; n++) bl_tree[n].Freq = 0;
+
+    dyn_ltree[END_BLOCK].Freq = 1;
+    opt_len = static_len = 0L;
+    last_lit = last_dist = last_flags = 0;
+    flags = 0; flag_bit = 1;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(tree, top) \
+{\
+    top = heap[SMALLEST]; \
+    heap[SMALLEST] = heap[heap_len--]; \
+    pqdownheap(tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m) \
+   (tree[n].Freq < tree[m].Freq || \
+   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(tree, k)
+    ct_data near *tree;  /* the tree to restore */
+    int k;               /* node to move down */
+{
+    int v = heap[k];
+    int j = k << 1;  /* left son of k */
+    int htemp;       /* required because of bug in SASC compiler */
+
+    while (j <= heap_len) {
+        /* Set j to the smallest of the two sons: */
+        if (j < heap_len && smaller(tree, heap[j+1], heap[j])) j++;
+
+        /* Exit if v is smaller than both sons */
+        htemp = heap[j];
+        if (smaller(tree, v, htemp)) break;
+
+        /* Exchange v with the smallest son */
+        heap[k] = htemp;
+        k = j;
+
+        /* And continue down the tree, setting j to the left son of k */
+        j <<= 1;
+    }
+    heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ *    above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ *     array bl_count contains the frequencies for each bit length.
+ *     The length opt_len is updated; static_len is also updated if stree is
+ *     not null.
+ */
+local void gen_bitlen(desc)
+    tree_desc near *desc; /* the tree descriptor */
+{
+    ct_data near *tree  = desc->dyn_tree;
+    int near *extra     = desc->extra_bits;
+    int base            = desc->extra_base;
+    int max_code        = desc->max_code;
+    int max_length      = desc->max_length;
+    ct_data near *stree = desc->static_tree;
+    int h;              /* heap index */
+    int n, m;           /* iterate over the tree elements */
+    int bits;           /* bit length */
+    int xbits;          /* extra bits */
+    ush f;              /* frequency */
+    int overflow = 0;   /* number of elements with bit length too large */
+
+    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+
+    /* In a first pass, compute the optimal bit lengths (which may
+     * overflow in the case of the bit length tree).
+     */
+    tree[heap[heap_max]].Len = 0; /* root of the heap */
+
+    for (h = heap_max+1; h < HEAP_SIZE; h++) {
+        n = heap[h];
+        bits = tree[tree[n].Dad].Len + 1;
+        if (bits > max_length) bits = max_length, overflow++;
+        tree[n].Len = (ush)bits;
+        /* We overwrite tree[n].Dad which is no longer needed */
+
+        if (n > max_code) continue; /* not a leaf node */
+
+        bl_count[bits]++;
+        xbits = 0;
+        if (n >= base) xbits = extra[n-base];
+        f = tree[n].Freq;
+        opt_len += (ulg)f * (bits + xbits);
+        if (stree) static_len += (ulg)f * (stree[n].Len + xbits);
+    }
+    if (overflow == 0) return;
+
+    Trace((stderr,"\nbit length overflow\n"));
+    /* This happens for example on obj2 and pic of the Calgary corpus */
+
+    /* Find the first bit length which could increase: */
+    do {
+        bits = max_length-1;
+        while (bl_count[bits] == 0) bits--;
+        bl_count[bits]--;           /* move one leaf down the tree */
+        bl_count[bits+1] += (ush)2; /* move one overflow item as its brother */
+        bl_count[max_length]--;
+        /* The brother of the overflow item also moves one step up,
+         * but this does not affect bl_count[max_length]
+         */
+        overflow -= 2;
+    } while (overflow > 0);
+
+    /* Now recompute all bit lengths, scanning in increasing frequency.
+     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+     * lengths instead of fixing only the wrong ones. This idea is taken
+     * from 'ar' written by Haruhiko Okumura.)
+     */
+    for (bits = max_length; bits != 0; bits--) {
+        n = bl_count[bits];
+        while (n != 0) {
+            m = heap[--h];
+            if (m > max_code) continue;
+            if (tree[m].Len != (ush)bits) {
+                Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+                opt_len += ((long)bits-(long)tree[m].Len)*(long)tree[m].Freq;
+                tree[m].Len = (ush)bits;
+            }
+            n--;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ *     zero code length.
+ */
+local void gen_codes (tree, max_code)
+    ct_data near *tree;        /* the tree to decorate */
+    int max_code;              /* largest code with non zero frequency */
+{
+    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+    ush code = 0;              /* running code value */
+    int bits;                  /* bit index */
+    int n;                     /* code index */
+
+    /* The distribution counts are first used to generate the code values
+     * without bit reversal.
+     */
+    for (bits = 1; bits <= MAX_BITS; bits++) {
+        next_code[bits] = code = (ush)((code + bl_count[bits-1]) << 1);
+    }
+    /* Check that the bit counts in bl_count are consistent. The last code
+     * must be all ones.
+     */
+    Assert(code + bl_count[MAX_BITS]-1 == (1<< ((ush) MAX_BITS)) - 1,
+            "inconsistent bit counts");
+    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+    for (n = 0;  n <= max_code; n++) {
+        int len = tree[n].Len;
+        if (len == 0) continue;
+        /* Now reverse the bits */
+        tree[n].Code = (ush)bi_reverse(next_code[len]++, len);
+
+        Tracec(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+    }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ *     and corresponding code. The length opt_len is updated; static_len is
+ *     also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(desc)
+    tree_desc near *desc; /* the tree descriptor */
+{
+    ct_data near *tree   = desc->dyn_tree;
+    ct_data near *stree  = desc->static_tree;
+    int elems            = desc->elems;
+    int n, m;          /* iterate over heap elements */
+    int max_code = -1; /* largest code with non zero frequency */
+    int node = elems;  /* next internal node of the tree */
+
+    /* Construct the initial heap, with least frequent element in
+     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+     * heap[0] is not used.
+     */
+    heap_len = 0, heap_max = HEAP_SIZE;
+
+    for (n = 0; n < elems; n++) {
+        if (tree[n].Freq != 0) {
+            heap[++heap_len] = max_code = n;
+            depth[n] = 0;
+        } else {
+            tree[n].Len = 0;
+        }
+    }
+
+    /* The pkzip format requires that at least one distance code exists,
+     * and that at least one bit should be sent even if there is only one
+     * possible code. So to avoid special checks later on we force at least
+     * two codes of non zero frequency.
+     */
+    while (heap_len < 2) {
+        int new = heap[++heap_len] = (max_code < 2 ? ++max_code : 0);
+        tree[new].Freq = 1;
+        depth[new] = 0;
+        opt_len--; if (stree) static_len -= stree[new].Len;
+        /* new is 0 or 1 so it does not have extra bits */
+    }
+    desc->max_code = max_code;
+
+    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+     * establish sub-heaps of increasing lengths:
+     */
+    for (n = heap_len/2; n >= 1; n--) pqdownheap(tree, n);
+
+    /* Construct the Huffman tree by repeatedly combining the least two
+     * frequent nodes.
+     */
+    do {
+        pqremove(tree, n);   /* n = node of least frequency */
+        m = heap[SMALLEST];  /* m = node of next least frequency */
+
+        heap[--heap_max] = n; /* keep the nodes sorted by frequency */
+        heap[--heap_max] = m;
+
+        /* Create a new node father of n and m */
+        tree[node].Freq = (ush)(tree[n].Freq + tree[m].Freq);
+        depth[node] = (uch) (Max(depth[n], depth[m]) + 1);
+        tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+        if (tree == bl_tree) {
+            fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+        }
+#endif
+        /* and insert the new node in the heap */
+        heap[SMALLEST] = node++;
+        pqdownheap(tree, SMALLEST);
+
+    } while (heap_len >= 2);
+
+    heap[--heap_max] = heap[SMALLEST];
+
+    /* At this point, the fields freq and dad are set. We can now
+     * generate the bit lengths.
+     */
+    gen_bitlen((tree_desc near *)desc);
+
+    /* The field len is now set, we can generate the bit codes */
+    gen_codes ((ct_data near *)tree, max_code);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree. Updates opt_len to take into account the repeat
+ * counts. (The contribution of the bit length codes will be added later
+ * during the construction of bl_tree.)
+ */
+local void scan_tree (tree, max_code)
+    ct_data near *tree; /* the tree to be scanned */
+    int max_code;       /* and its largest code of non zero frequency */
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    if (nextlen == 0) max_count = 138, min_count = 3;
+    tree[max_code+1].Len = (ush)-1; /* guard */
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            bl_tree[curlen].Freq += (ush)count;
+        } else if (curlen != 0) {
+            if (curlen != prevlen) bl_tree[curlen].Freq++;
+            bl_tree[REP_3_6].Freq++;
+        } else if (count <= 10) {
+            bl_tree[REPZ_3_10].Freq++;
+        } else {
+            bl_tree[REPZ_11_138].Freq++;
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (tree, max_code)
+    ct_data near *tree; /* the tree to be scanned */
+    int max_code;       /* and its largest code of non zero frequency */
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    /* tree[max_code+1].Len = -1; */  /* guard already set */
+    if (nextlen == 0) max_count = 138, min_count = 3;
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            do { send_code(curlen, bl_tree); } while (--count != 0);
+
+        } else if (curlen != 0) {
+            if (curlen != prevlen) {
+                send_code(curlen, bl_tree); count--;
+            }
+            Assert(count >= 3 && count <= 6, " 3_6?");
+            send_code(REP_3_6, bl_tree); send_bits(count-3, 2);
+
+        } else if (count <= 10) {
+            send_code(REPZ_3_10, bl_tree); send_bits(count-3, 3);
+
+        } else {
+            send_code(REPZ_11_138, bl_tree); send_bits(count-11, 7);
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree()
+{
+    int max_blindex;  /* index of last bit length code of non zero freq */
+
+    /* Determine the bit length frequencies for literal and distance trees */
+    scan_tree((ct_data near *)dyn_ltree, l_desc.max_code);
+    scan_tree((ct_data near *)dyn_dtree, d_desc.max_code);
+
+    /* Build the bit length tree: */
+    build_tree((tree_desc near *)(&bl_desc));
+    /* opt_len now includes the length of the tree representations, except
+     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+     */
+
+    /* Determine the number of bit length codes to send. The pkzip format
+     * requires that at least 4 bit length codes be sent. (appnote.txt says
+     * 3 but the actual value used is 4.)
+     */
+    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+        if (bl_tree[bl_order[max_blindex]].Len != 0) break;
+    }
+    /* Update opt_len to include the bit length tree and counts */
+    opt_len += 3*(max_blindex+1) + 5+5+4;
+    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", opt_len, static_len));
+
+    return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(lcodes, dcodes, blcodes)
+    int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+    int rank;                    /* index in bl_order */
+
+    Assert(lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+    Assert(lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+            "too many codes");
+    Tracev((stderr, "\nbl counts: "));
+    send_bits(lcodes-257, 5);
+    /* not +255 as stated in appnote.txt 1.93a or -256 in 2.04c */
+    send_bits(dcodes-1,   5);
+    send_bits(blcodes-4,  4); /* not -3 as stated in appnote.txt */
+    for (rank = 0; rank < blcodes; rank++) {
+        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+        send_bits(bl_tree[bl_order[rank]].Len, 3);
+    }
+    Tracev((stderr, "\nbl tree: sent %ld", bits_sent));
+
+    send_tree((ct_data near *)dyn_ltree, lcodes-1); /* send the literal tree */
+    Tracev((stderr, "\nlit tree: sent %ld", bits_sent));
+
+    send_tree((ct_data near *)dyn_dtree, dcodes-1); /* send the distance tree */
+    Tracev((stderr, "\ndist tree: sent %ld", bits_sent));
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file. This function
+ * returns the total compressed length (in bytes) for the file so far.
+ */
+ulg flush_block(buf, stored_len, eof)
+    char *buf;        /* input block, or NULL if too old */
+    ulg stored_len;   /* length of input block */
+    int eof;          /* true if this is the last block for a file */
+{
+    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+    int max_blindex;  /* index of last bit length code of non zero freq */
+
+    flag_buf[last_flags] = flags; /* Save the flags for the last 8 items */
+
+     /* Check if the file is ascii or binary */
+    if (*file_type == (ush)UNKNOWN) set_file_type();
+
+    /* Construct the literal and distance trees */
+    build_tree((tree_desc near *)(&l_desc));
+    Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len));
+
+    build_tree((tree_desc near *)(&d_desc));
+    Tracev((stderr, "\ndist data: dyn %ld, stat %ld", opt_len, static_len));
+    /* At this point, opt_len and static_len are the total bit lengths of
+     * the compressed block data, excluding the tree representations.
+     */
+
+    /* Build the bit length tree for the above two trees, and get the index
+     * in bl_order of the last bit length code to send.
+     */
+    max_blindex = build_bl_tree();
+
+    /* Determine the best encoding. Compute first the block length in bytes */
+    opt_lenb = (opt_len+3+7)>>3;
+    static_lenb = (static_len+3+7)>>3;
+#ifdef DEBUG
+    input_len += stored_len; /* for debugging only */
+#endif
+
+    Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",
+            opt_lenb, opt_len, static_lenb, static_len, stored_len,
+            last_lit, last_dist));
+
+    if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+#ifndef PGP /* PGP can't handle stored blocks */
+    /* If compression failed and this is the first and last block,
+     * the whole file is transformed into a stored file:
+     */
+#ifdef FORCE_METHOD
+    if (level == 1 && eof && file_method != NULL &&
+        cmpr_bytelen == 0L && cmpr_len_bits == 0L) { /* force stored file */
+#else
+    if (stored_len <= opt_lenb && eof && file_method != NULL &&
+        cmpr_bytelen == 0L && cmpr_len_bits == 0L && seekable()) {
+#endif
+        /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
+        if (buf == NULL) error ("block vanished");
+
+        copy_block(buf, (unsigned)stored_len, 0); /* without header */
+        cmpr_bytelen = stored_len;
+        *file_method = STORE;
+    } else
+#endif /* PGP */
+
+#ifdef FORCE_METHOD
+    if (level <= 2 && buf != (char*)NULL) { /* force stored block */
+#else
+    if (stored_len+4 <= opt_lenb && buf != (char*)NULL) {
+                       /* 4: two words for the lengths */
+#endif
+        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+         * Otherwise we can't have processed more than WSIZE input bytes since
+         * the last block flush, because compression would have been
+         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+         * transform a block into a stored block.
+         */
+        send_bits((STORED_BLOCK<<1)+eof, 3);  /* send block type */
+        cmpr_bytelen += ((cmpr_len_bits + 3 + 7) >> 3) + stored_len + 4;
+        cmpr_len_bits = 0L;
+
+        copy_block(buf, (unsigned)stored_len, 1); /* with header */
+
+#ifdef FORCE_METHOD
+    } else if (level == 3) { /* force static trees */
+#else
+    } else if (static_lenb == opt_lenb) {
+#endif
+        send_bits((STATIC_TREES<<1)+eof, 3);
+        compress_block((ct_data near *)static_ltree, (ct_data near *)static_dtree);
+        cmpr_len_bits += 3 + static_len;
+        cmpr_bytelen += cmpr_len_bits >> 3;
+        cmpr_len_bits &= 7L;
+    } else {
+        send_bits((DYN_TREES<<1)+eof, 3);
+        send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1);
+        compress_block((ct_data near *)dyn_ltree, (ct_data near *)dyn_dtree);
+        cmpr_len_bits += 3 + opt_len;
+        cmpr_bytelen += cmpr_len_bits >> 3;
+        cmpr_len_bits &= 7L;
+    }
+    Assert(((cmpr_bytelen << 3) + cmpr_len_bits) == bits_sent,
+            "bad compressed size");
+    init_block();
+
+    if (eof) {
+#if defined(PGP) && !defined(MMAP)
+        /* Wipe out sensitive data for pgp */
+# ifdef DYN_ALLOC
+        extern uch *window;
+# else
+        extern uch window[];
+# endif
+        memset(window, 0, (unsigned)(2*WSIZE-1)); /* -1 needed if WSIZE=32K */
+#else /* !PGP */
+        Assert(input_len == isize, "bad input size");
+#endif
+        bi_windup();
+        cmpr_len_bits += 7;  /* align on byte boundary */
+    }
+    Tracev((stderr,"\ncomprlen %lu(%lu) ", cmpr_bytelen + (cmpr_len_bits>>3),
+           (cmpr_bytelen << 3) + cmpr_len_bits - 7*eof));
+    Trace((stderr, "\n"));
+
+    return cmpr_bytelen + (cmpr_len_bits >> 3);
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int ct_tally (dist, lc)
+    int dist;  /* distance of matched string */
+    int lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+    l_buf[last_lit++] = (uch)lc;
+    if (dist == 0) {
+        /* lc is the unmatched char */
+        dyn_ltree[lc].Freq++;
+    } else {
+        /* Here, lc is the match length - MIN_MATCH */
+        dist--;             /* dist = match distance - 1 */
+        Assert((ush)dist < (ush)MAX_DIST &&
+               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+               (ush)d_code(dist) < (ush)D_CODES,  "ct_tally: bad match");
+
+        dyn_ltree[length_code[lc]+LITERALS+1].Freq++;
+        dyn_dtree[d_code(dist)].Freq++;
+
+        d_buf[last_dist++] = (ush)dist;
+        flags |= flag_bit;
+    }
+    flag_bit <<= 1;
+
+    /* Output the flags if they fill a byte: */
+    if ((last_lit & 7) == 0) {
+        flag_buf[last_flags++] = flags;
+        flags = 0, flag_bit = 1;
+    }
+    /* Try to guess if it is profitable to stop the current block here */
+    if (level > 2 && (last_lit & 0xfff) == 0) {
+        /* Compute an upper bound for the compressed length */
+        ulg out_length = (ulg)last_lit*8L;
+        ulg in_length = (ulg)strstart-block_start;
+        int dcode;
+        for (dcode = 0; dcode < D_CODES; dcode++) {
+            out_length += (ulg)dyn_dtree[dcode].Freq*(5L+extra_dbits[dcode]);
+        }
+        out_length >>= 3;
+        Trace((stderr,"\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ",
+               last_lit, last_dist, in_length, out_length,
+               100L - out_length*100L/in_length));
+        if (last_dist < last_lit/2 && out_length < in_length/2) return 1;
+    }
+    return (last_lit == LIT_BUFSIZE-1 || last_dist == DIST_BUFSIZE);
+    /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K
+     * on 16 bit machines and because stored blocks are restricted to
+     * 64K-1 bytes.
+     */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(ltree, dtree)
+    ct_data near *ltree; /* literal tree */
+    ct_data near *dtree; /* distance tree */
+{
+    unsigned dist;      /* distance of matched string */
+    int lc;             /* match length or unmatched char (if dist == 0) */
+    unsigned lx = 0;    /* running index in l_buf */
+    unsigned dx = 0;    /* running index in d_buf */
+    unsigned fx = 0;    /* running index in flag_buf */
+    uch flag = 0;       /* current flags */
+    unsigned code;      /* the code to send */
+    int extra;          /* number of extra bits to send */
+
+    if (last_lit != 0) do {
+        if ((lx & 7) == 0) flag = flag_buf[fx++];
+        lc = l_buf[lx++];
+        if ((flag & 1) == 0) {
+            send_code(lc, ltree); /* send a literal byte */
+            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+        } else {
+            /* Here, lc is the match length - MIN_MATCH */
+            code = length_code[lc];
+            send_code(code+LITERALS+1, ltree); /* send the length code */
+            extra = extra_lbits[code];
+            if (extra != 0) {
+                lc -= base_length[code];
+                send_bits(lc, extra);        /* send the extra length bits */
+            }
+            dist = d_buf[dx++];
+            /* Here, dist is the match distance - 1 */
+            code = d_code(dist);
+            Assert(code < D_CODES, "bad d_code");
+
+            send_code(code, dtree);       /* send the distance code */
+            extra = extra_dbits[code];
+            if (extra != 0) {
+                dist -= base_dist[code];
+                send_bits(dist, extra);   /* send the extra distance bits */
+            }
+        } /* literal or match pair ? */
+        flag >>= 1;
+    } while (lx < last_lit);
+
+    send_code(END_BLOCK, ltree);
+}
+
+/* ===========================================================================
+ * Set the file type to TEXT (ASCII) or BINARY, using following algorithm:
+ * - TEXT, either ASCII or an ASCII-compatible extension such as ISO-8859,
+ *   UTF-8, etc., when the following two conditions are satisfied:
+ *    a) There are no non-portable control characters belonging to the
+ *       "black list" (0..6, 14..25, 28..31).
+ *    b) There is at least one printable character belonging to the
+ *       "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * - BINARY otherwise.
+ *
+ * Note that the following partially-portable control characters form a
+ * "gray list" that is ignored in this detection algorithm:
+ * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
+ *
+ * Also note that, unlike in the previous 20% binary detection algorithm,
+ * any control characters in the black list will set the file type to
+ * BINARY.  If a text file contains a single accidental black character,
+ * the file will be flagged as BINARY in the archive.
+ *
+ * IN assertion: the fields freq of dyn_ltree are set.
+ */
+local void set_file_type()
+{
+    /* bit-mask of black-listed bytes
+     * bit is set if byte is black-listed
+     * set bits 0..6, 14..25, and 28..31
+     * 0xf3ffc07f = binary 11110011111111111100000001111111
+     */
+    unsigned long mask = 0xf3ffc07fUL;
+    int n;
+
+    /* Check for non-textual ("black-listed") bytes. */
+    for (n = 0; n <= 31; n++, mask >>= 1)
+        if ((mask & 1) && (dyn_ltree[n].Freq != 0))
+        {
+            *file_type = BINARY;
+            return;
+        }
+
+    /* Check for textual ("white-listed") bytes. */
+    *file_type = ASCII;
+    if (dyn_ltree[9].Freq != 0 || dyn_ltree[10].Freq != 0
+            || dyn_ltree[13].Freq != 0)
+        return;
+    for (n = 32; n < LITERALS; n++)
+        if (dyn_ltree[n].Freq != 0)
+            return;
+
+    /* This deflate stream is either empty, or
+     * it has tolerated ("gray-listed") bytes only.
+     */
+    *file_type = BINARY;
+}
+
+
+/* ===========================================================================
+ * Initialize the bit string routines.
+ */
+void bi_init (tgt_buf, tgt_size, flsh_allowed)
+    char *tgt_buf;
+    unsigned tgt_size;
+    int flsh_allowed;
+{
+    out_buf = tgt_buf;
+    out_size = tgt_size;
+    out_offset = 0;
+    flush_flg = flsh_allowed;
+
+    bi_buf = 0;
+    bi_valid = 0;
+#ifdef DEBUG
+    bits_sent = 0L;
+#endif
+}
+
+#if (!defined(ASMV) || !defined(RISCOS))
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+local void send_bits(value, length)
+    int value;  /* value to send */
+    int length; /* number of bits */
+{
+#ifdef DEBUG
+    Tracevv((stderr," l %2d v %4x ", length, value));
+    Assert(length > 0 && length <= 15, "invalid length");
+    bits_sent += (ulg)length;
+#endif
+    /* If not enough room in bi_buf, use (bi_valid) bits from bi_buf and
+     * (Buf_size - bi_valid) bits from value to flush the filled bi_buf,
+     * then fill in the rest of (value), leaving (length - (Buf_size-bi_valid))
+     * unused bits in bi_buf.
+     */
+    bi_buf |= (value << bi_valid);
+    bi_valid += length;
+    if (bi_valid > (int)Buf_size) {
+        PUTSHORT(bi_buf);
+        bi_valid -= Buf_size;
+        bi_buf = (unsigned)value >> (length - bi_valid);
+    }
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(code, len)
+    unsigned code; /* the value to invert */
+    int len;       /* its bit length */
+{
+    register unsigned res = 0;
+    do {
+        res |= code & 1;
+        code >>= 1, res <<= 1;
+    } while (--len > 0);
+    return res >> 1;
+}
+#endif /* !ASMV || !RISCOS */
+
+/* ===========================================================================
+ * Write out any remaining bits in an incomplete byte.
+ */
+local void bi_windup()
+{
+    if (bi_valid > 8) {
+        PUTSHORT(bi_buf);
+    } else if (bi_valid > 0) {
+        PUTBYTE(bi_buf);
+    }
+    if (flush_flg) {
+        flush_outbuf(out_buf, &out_offset);
+    }
+    bi_buf = 0;
+    bi_valid = 0;
+#ifdef DEBUG
+    bits_sent = (bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block to the zip file, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(block, len, header)
+    char *block;  /* the input data */
+    unsigned len; /* its length */
+    int header;   /* true if block header must be written */
+{
+    bi_windup();              /* align on byte boundary */
+
+    if (header) {
+        PUTSHORT((ush)len);
+        PUTSHORT((ush)~len);
+#ifdef DEBUG
+        bits_sent += 2*16;
+#endif
+    }
+    if (flush_flg) {
+        flush_outbuf(out_buf, &out_offset);
+        out_offset = len;
+        flush_outbuf(block, &out_offset);
+    } else if (out_offset + len > out_size) {
+        error("output buffer too small for in-memory compression");
+    } else {
+        memcpy(out_buf + out_offset, block, len);
+        out_offset += len;
+    }
+#ifdef DEBUG
+    bits_sent += (ulg)len<<3;
+#endif
+}
+
+#endif /* !USE_ZLIB */
diff --git a/ttyio.c b/ttyio.c
new file mode 100644 (file)
index 0000000..e40fade
--- /dev/null
+++ b/ttyio.c
@@ -0,0 +1,637 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+  ttyio.c
+
+  This file contains routines for doing console input/output, including code
+  for non-echoing input.  It is used by the encryption/decryption code but
+  does not contain any restricted code itself.  This file is shared between
+  Info-ZIP's Zip and UnZip.
+
+  Contains:  echo()         (VMS only)
+             Echon()        (Unix only)
+             Echoff()       (Unix only)
+             screenlines()  (Unix only)
+             zgetch()       (Unix and non-Unix versions)
+             getp()         ("PC," Unix/Atari/Be, VMS/VMCMS/MVS)
+
+  ---------------------------------------------------------------------------*/
+
+#define __TTYIO_C       /* identifies this source module */
+
+#include "zip.h"
+#include "crypt.h"
+
+#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP)))
+/* Non-echo console/keyboard input is needed for (en/de)cryption's password
+ * entry, and for UnZip(SFX)'s MORE and Pause features.
+ * (The corresponding #endif is found at the end of this module.)
+ */
+
+#include "ttyio.h"
+
+#ifndef PUTC
+#  define PUTC putc
+#endif
+
+#ifdef ZIP
+#  ifdef GLOBAL          /* used in Amiga system headers, maybe others too */
+#    undef GLOBAL
+#  endif
+#  define GLOBAL(g) g
+#else
+#  define GLOBAL(g) G.g
+#endif
+
+#ifdef __BEOS__                /* why yes, we do */
+#  define HAVE_TERMIOS_H
+#endif
+
+#ifdef __ATHEOS__
+#  define HAVE_TERMIOS_H
+#endif
+
+#ifdef _POSIX_VERSION
+#  ifndef USE_POSIX_TERMIOS
+#    define USE_POSIX_TERMIOS  /* use POSIX style termio (termios) */
+#  endif
+#  ifndef HAVE_TERMIOS_H
+#    define HAVE_TERMIOS_H     /* POSIX termios.h */
+#  endif
+#endif /* _POSIX_VERSION */
+
+#ifdef UNZIP            /* Zip handles this with the unix/configure script */
+#  ifndef _POSIX_VERSION
+#    if (defined(SYSV) || defined(CRAY)) &&  !defined(__MINT__)
+#      ifndef USE_SYSV_TERMIO
+#        define USE_SYSV_TERMIO
+#      endif
+#      ifdef COHERENT
+#        ifndef HAVE_TERMIO_H
+#          define HAVE_TERMIO_H
+#        endif
+#        ifdef HAVE_SYS_TERMIO_H
+#          undef HAVE_SYS_TERMIO_H
+#        endif
+#      else /* !COHERENT */
+#        ifdef HAVE_TERMIO_H
+#          undef HAVE_TERMIO_H
+#        endif
+#        ifndef HAVE_SYS_TERMIO_H
+#           define HAVE_SYS_TERMIO_H
+#        endif
+#      endif /* ?COHERENT */
+#    endif /* (SYSV || CRAY) && !__MINT__ */
+#  endif /* !_POSIX_VERSION */
+#  if !(defined(BSD4_4) || defined(SYSV) || defined(__convexc__))
+#    ifndef NO_FCNTL_H
+#      define NO_FCNTL_H
+#    endif
+#  endif /* !(BSD4_4 || SYSV || __convexc__) */
+#endif /* UNZIP */
+
+#ifdef HAVE_TERMIOS_H
+#  ifndef USE_POSIX_TERMIOS
+#    define USE_POSIX_TERMIOS
+#  endif
+#endif
+
+#if (defined(HAVE_TERMIO_H) || defined(HAVE_SYS_TERMIO_H))
+#  ifndef USE_SYSV_TERMIO
+#    define USE_SYSV_TERMIO
+#  endif
+#endif
+
+#if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE))
+#  include <sys/ioctl.h>
+#  define GOT_IOCTL_H
+   /* int ioctl OF((int, int, zvoid *));   GRR: may need for some systems */
+#endif
+
+#ifndef HAVE_WORKING_GETCH
+   /* include system support for switching of console echo */
+#  ifdef VMS
+#    include <descrip.h>
+#    include <iodef.h>
+#    include <ttdef.h>
+#    include <starlet.h>
+#    include <ssdef.h>
+#  else /* !VMS */
+#    ifdef HAVE_TERMIOS_H
+#      include <termios.h>
+#      define sgttyb termios
+#      define sg_flags c_lflag
+#      define GTTY(f, s) tcgetattr(f, (zvoid *) s)
+#      define STTY(f, s) tcsetattr(f, TCSAFLUSH, (zvoid *) s)
+#    else /* !HAVE_TERMIOS_H */
+#      ifdef USE_SYSV_TERMIO           /* Amdahl, Cray, all SysV? */
+#        ifdef HAVE_TERMIO_H
+#          include <termio.h>
+#        endif
+#        ifdef HAVE_SYS_TERMIO_H
+#          include <sys/termio.h>
+#        endif
+#        ifdef NEED_PTEM
+#          include <sys/stream.h>
+#          include <sys/ptem.h>
+#        endif
+#        define sgttyb termio
+#        define sg_flags c_lflag
+#        define GTTY(f,s) ioctl(f,TCGETA,(zvoid *)s)
+#        define STTY(f,s) ioctl(f,TCSETAW,(zvoid *)s)
+#      else /* !USE_SYSV_TERMIO */
+#        ifndef CMS_MVS
+#          if (!defined(MINIX) && !defined(GOT_IOCTL_H))
+#            include <sys/ioctl.h>
+#          endif
+#          include <sgtty.h>
+#          define GTTY gtty
+#          define STTY stty
+#          ifdef UNZIP
+             /*
+              * XXX : Are these declarations needed at all ????
+              */
+             /*
+              * GRR: let's find out...   Hmmm, appears not...
+             int gtty OF((int, struct sgttyb *));
+             int stty OF((int, struct sgttyb *));
+              */
+#          endif
+#        endif /* !CMS_MVS */
+#      endif /* ?USE_SYSV_TERMIO */
+#    endif /* ?HAVE_TERMIOS_H */
+#    ifndef NO_FCNTL_H
+#      ifndef UNZIP
+#        include <fcntl.h>
+#      endif
+#    else
+       char *ttyname OF((int));
+#    endif
+#  endif /* ?VMS */
+#endif /* !HAVE_WORKING_GETCH */
+
+
+
+#ifndef HAVE_WORKING_GETCH
+#ifdef VMS
+
+/*
+ * Turn keyboard echoing on or off (VMS).  Loosely based on VMSmunch.c
+ * and hence on Joe Meadows' file.c code.
+ */
+int echo(opt)
+    int opt;
+{
+    /*
+     * For VMS v5.x:
+     *   IO$_SENSEMODE/SETMODE info:  Programming, Vol. 7A, System Programming,
+     *     I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6
+     *   sys$assign(), sys$qio() info:  Programming, Vol. 4B, System Services,
+     *     System Services Reference Manual, pp. sys-23, sys-379
+     *   fixed-length descriptor info:  Programming, Vol. 3, System Services,
+     *     Intro to System Routines, sec. 2.9.2
+     * Greg Roelofs, 15 Aug 91
+     */
+
+    /* SKM: make global? */
+    static struct dsc$descriptor_s DevDesc =
+        {11, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$COMMAND"};
+     /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */
+    static short           DevChan, iosb[4];
+    static long            status;
+    static unsigned long   oldmode[2], newmode[2];   /* each = 8 bytes */
+
+
+    /* assign a channel to standard input */
+    status = sys$assign(&DevDesc, &DevChan, 0, 0);
+    if (!(status & 1))
+        return status;
+
+    /* use sys$qio and the IO$_SENSEMODE function to determine the current
+     * tty status (for password reading, could use IO$_READVBLK function
+     * instead, but echo on/off will be more general)
+     */
+    status = sys$qiow(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0,
+                     oldmode, 8, 0, 0, 0, 0);
+    if (!(status & 1))
+        return status;
+    status = iosb[0];
+    if (!(status & 1))
+        return status;
+
+    /* copy old mode into new-mode buffer, then modify to be either NOECHO or
+     * ECHO (depending on function argument opt)
+     */
+    newmode[0] = oldmode[0];
+    newmode[1] = oldmode[1];
+    if (opt == 0)   /* off */
+        newmode[1] |= TT$M_NOECHO;                      /* set NOECHO bit */
+    else
+        newmode[1] &= ~((unsigned long) TT$M_NOECHO);   /* clear NOECHO bit */
+
+    /* use the IO$_SETMODE function to change the tty status */
+    status = sys$qiow(0, DevChan, IO$_SETMODE, &iosb, 0, 0,
+                     newmode, 8, 0, 0, 0, 0);
+    if (!(status & 1))
+        return status;
+    status = iosb[0];
+    if (!(status & 1))
+        return status;
+
+    /* deassign the sys$input channel by way of clean-up */
+    status = sys$dassgn(DevChan);
+    if (!(status & 1))
+        return status;
+
+    return SS$_NORMAL;   /* we be happy */
+
+} /* end function echo() */
+
+
+#else /* !VMS:  basically Unix */
+
+
+/* For VM/CMS and MVS, non-echo terminal input is not (yet?) supported. */
+#ifndef CMS_MVS
+
+#ifdef ZIP                      /* moved to globals.h for UnZip */
+   static int echofd=(-1);      /* file descriptor whose echo is off */
+#endif
+
+/*
+ * Turn echo off for file descriptor f.  Assumes that f is a tty device.
+ */
+void Echoff(__G__ f)
+    __GDEF
+    int f;                    /* file descriptor for which to turn echo off */
+{
+    struct sgttyb sg;         /* tty device structure */
+
+    GLOBAL(echofd) = f;
+    GTTY(f, &sg);             /* get settings */
+    sg.sg_flags &= ~ECHO;     /* turn echo off */
+    STTY(f, &sg);
+}
+
+/*
+ * Turn echo back on for file descriptor echofd.
+ */
+void Echon(__G)
+    __GDEF
+{
+    struct sgttyb sg;         /* tty device structure */
+
+    if (GLOBAL(echofd) != -1) {
+        GTTY(GLOBAL(echofd), &sg);    /* get settings */
+        sg.sg_flags |= ECHO;  /* turn echo on */
+        STTY(GLOBAL(echofd), &sg);
+        GLOBAL(echofd) = -1;
+    }
+}
+
+#endif /* !CMS_MVS */
+#endif /* ?VMS */
+
+
+#if (defined(UNZIP) && !defined(FUNZIP))
+
+#if (defined(UNIX) || defined(__BEOS__) || defined(__ATHEOS__))
+#ifdef MORE
+
+/*
+ * Get the number of lines on the output terminal.  SCO Unix apparently
+ * defines TIOCGWINSZ but doesn't support it (!M_UNIX).
+ *
+ * GRR:  will need to know width of terminal someday, too, to account for
+ *       line-wrapping.
+ */
+
+#if (defined(TIOCGWINSZ) && !defined(M_UNIX))
+
+int screenlines()
+{
+    struct winsize wsz;
+#ifdef DEBUG_WINSZ
+    static int firsttime = TRUE;
+#endif
+
+    /* see termio(4) under, e.g., SunOS */
+    if (ioctl(1, TIOCGWINSZ, &wsz) == 0) {
+#ifdef DEBUG_WINSZ
+        if (firsttime) {
+            firsttime = FALSE;
+            fprintf(stderr, "ttyio.c screenlines():  ws_row = %d\n",
+              wsz.ws_row);
+        }
+#endif
+        /* number of columns = ws_col */
+        return (wsz.ws_row > 0)? wsz.ws_row : 24;   /* number of rows */
+
+    } else {         /* this happens when piping to more(1), for example */
+#ifdef DEBUG_WINSZ
+        if (firsttime) {
+            firsttime = FALSE;
+            fprintf(stderr,
+              "ttyio.c screenlines():  ioctl(TIOCGWINSZ) failed\n"));
+        }
+#endif
+        return 24;   /* VT-100 assumed to be minimal hardware */
+    }
+}
+
+#else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */
+
+int screenlines()
+{
+    char *envptr, *getenv();
+    int n;
+
+    /* GRR:  this is overly simplistic, but don't have access to stty/gtty
+     * system anymore
+     */
+    envptr = getenv("LINES");
+    if (envptr == (char *)NULL || (n = atoi(envptr)) < 5)
+        return 24;   /* VT-100 assumed to be minimal hardware */
+    else
+        return n;
+}
+
+#endif /* ?(TIOCGWINSZ && !M_UNIX) */
+#endif /* MORE */
+
+
+/*
+ * Get a character from the given file descriptor without echo or newline.
+ */
+int zgetch(__G__ f)
+    __GDEF
+    int f;                      /* file descriptor from which to read */
+{
+#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
+    char oldmin, oldtim;
+#endif
+    char c;
+    struct sgttyb sg;           /* tty device structure */
+
+    GTTY(f, &sg);               /* get settings */
+#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
+    oldmin = sg.c_cc[VMIN];     /* save old values */
+    oldtim = sg.c_cc[VTIME];
+    sg.c_cc[VMIN] = 1;          /* need only one char to return read() */
+    sg.c_cc[VTIME] = 0;         /* no timeout */
+    sg.sg_flags &= ~ICANON;     /* canonical mode off */
+#else
+    sg.sg_flags |= CBREAK;      /* cbreak mode on */
+#endif
+    sg.sg_flags &= ~ECHO;       /* turn echo off, too */
+    STTY(f, &sg);               /* set cbreak mode */
+    GLOBAL(echofd) = f;         /* in case ^C hit (not perfect: still CBREAK) */
+
+    read(f, &c, 1);             /* read our character */
+
+#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
+    sg.c_cc[VMIN] = oldmin;     /* restore old values */
+    sg.c_cc[VTIME] = oldtim;
+    sg.sg_flags |= ICANON;      /* canonical mode on */
+#else
+    sg.sg_flags &= ~CBREAK;     /* cbreak mode off */
+#endif
+    sg.sg_flags |= ECHO;        /* turn echo on */
+    STTY(f, &sg);               /* restore canonical mode */
+    GLOBAL(echofd) = -1;
+
+    return (int)c;
+}
+
+
+#else /* !UNIX && !__BEOS__ */
+
+
+int zgetch(__G__ f)
+    __GDEF
+    int f;    /* file descriptor from which to read (must be open already) */
+{
+    char c, c2;
+
+/*---------------------------------------------------------------------------
+    Get a character from the given file descriptor without echo; can't fake
+    CBREAK mode (i.e., newline required), but can get rid of all chars up to
+    and including newline.
+  ---------------------------------------------------------------------------*/
+
+    echoff(f);
+    read(f, &c, 1);
+    if (c != '\n')
+        do {
+            read(f, &c2, 1);   /* throw away all other chars up thru newline */
+        } while (c2 != '\n');
+    echon();
+    return (int)c;
+}
+
+#endif /* ?(UNIX || __BEOS__) */
+
+#endif /* UNZIP && !FUNZIP */
+#endif /* !HAVE_WORKING_GETCH */
+
+
+#if CRYPT                       /* getp() is only used with full encryption */
+
+/*
+ * Simple compile-time check for source compatibility between
+ * zcrypt and ttyio:
+ */
+#if (!defined(CR_MAJORVER) || (CR_MAJORVER < 2) || (CR_MINORVER < 7))
+   error:  This Info-ZIP tool requires zcrypt 2.7 or later.
+#endif
+
+/*
+ * Get a password of length n-1 or less into *p using the prompt *m.
+ * The entered password is not echoed.
+ */
+
+#ifdef HAVE_WORKING_GETCH
+/*
+ * For the AMIGA, getch() is defined as Agetch(), which is in
+ * amiga/filedate.c; SAS/C 6.x provides a getch(), but since Agetch()
+ * uses the infrastructure that is already in place in filedate.c, it is
+ * smaller.  With this function, echoff() and echon() are not needed.
+ *
+ * For the MAC, a non-echo macgetch() function is defined in the MacOS
+ * specific sources which uses the event handling mechanism of the
+ * desktop window manager to get a character from the keyboard.
+ *
+ * For the other systems in this section, a non-echo getch() function
+ * is either contained the C runtime library (conio package), or getch()
+ * is defined as an alias for a similar system specific RTL function.
+ */
+
+#ifndef WINDLL   /* WINDLL does not support a console interface */
+#ifndef QDOS     /* QDOS supplies a variant of this function */
+
+/* This is the getp() function for all systems (with TTY type user interface)
+ * that supply a working `non-echo' getch() function for "raw" console input.
+ */
+char *getp(__G__ m, p, n)
+    __GDEF
+    ZCONST char *m;             /* prompt for password */
+    char *p;                    /* return value: line input */
+    int n;                      /* bytes available in p[] */
+{
+    char c;                     /* one-byte buffer for read() to use */
+    int i;                      /* number of characters input */
+    char *w;                    /* warning on retry */
+
+    /* get password */
+    w = "";
+    do {
+        fputs(w, stderr);       /* warning if back again */
+        fputs(m, stderr);       /* display prompt and flush */
+        fflush(stderr);
+        i = 0;
+        do {                    /* read line, keeping first n characters */
+            if ((c = (char)getch()) == '\r')
+                c = '\n';       /* until user hits CR */
+            if (c == 8 || c == 127) {
+                if (i > 0) i--; /* the `backspace' and `del' keys works */
+            }
+            else if (i < n)
+                p[i++] = c;     /* truncate past n */
+        } while (c != '\n');
+        PUTC('\n', stderr);  fflush(stderr);
+        w = "(line too long--try again)\n";
+    } while (p[i-1] != '\n');
+    p[i-1] = 0;                 /* terminate at newline */
+
+    return p;                   /* return pointer to password */
+
+} /* end function getp() */
+
+#endif /* !QDOS */
+#endif /* !WINDLL */
+
+
+#else /* !HAVE_WORKING_GETCH */
+
+
+#if (defined(UNIX) || defined(__MINT__) || defined(__BEOS__) || defined(__ATHEOS__))
+
+#ifndef _PATH_TTY
+#  ifdef __MINT__
+#    define _PATH_TTY ttyname(2)
+#  else
+#    define _PATH_TTY "/dev/tty"
+#  endif
+#endif
+
+char *getp(__G__ m, p, n)
+    __GDEF
+    ZCONST char *m;             /* prompt for password */
+    char *p;                    /* return value: line input */
+    int n;                      /* bytes available in p[] */
+{
+    char c;                     /* one-byte buffer for read() to use */
+    int i;                      /* number of characters input */
+    char *w;                    /* warning on retry */
+    int f;                      /* file descriptor for tty device */
+
+#ifdef PASSWD_FROM_STDIN
+    /* Read from stdin. This is unsafe if the password is stored on disk. */
+    f = 0;
+#else
+    /* turn off echo on tty */
+
+    if ((f = open(_PATH_TTY, 0)) == -1)
+        return NULL;
+#endif
+    /* get password */
+    w = "";
+    do {
+        fputs(w, stderr);       /* warning if back again */
+        fputs(m, stderr);       /* prompt */
+        fflush(stderr);
+        i = 0;
+        echoff(f);
+        do {                    /* read line, keeping n */
+            read(f, &c, 1);
+            if (i < n)
+                p[i++] = c;
+        } while (c != '\n');
+        echon();
+        PUTC('\n', stderr);  fflush(stderr);
+        w = "(line too long--try again)\n";
+    } while (p[i-1] != '\n');
+    p[i-1] = 0;                 /* terminate at newline */
+
+#ifndef PASSWD_FROM_STDIN
+    close(f);
+#endif
+
+    return p;                   /* return pointer to password */
+
+} /* end function getp() */
+
+#endif /* UNIX || __MINT__ || __BEOS__ || __ATHEOS__ */
+
+
+
+#if (defined(VMS) || defined(CMS_MVS))
+
+char *getp(__G__ m, p, n)
+    __GDEF
+    ZCONST char *m;             /* prompt for password */
+    char *p;                    /* return value: line input */
+    int n;                      /* bytes available in p[] */
+{
+    char c;                     /* one-byte buffer for read() to use */
+    int i;                      /* number of characters input */
+    char *w;                    /* warning on retry */
+    FILE *f;                    /* file structure for SYS$COMMAND device */
+
+#ifdef PASSWD_FROM_STDIN
+    f = stdin;
+#else
+    if ((f = fopen(ctermid(NULL), "r")) == NULL)
+        return NULL;
+#endif
+
+    /* get password */
+    fflush(stdout);
+    w = "";
+    do {
+        if (*w)                 /* bug: VMS apparently adds \n to NULL fputs */
+            fputs(w, stderr);   /* warning if back again */
+        fputs(m, stderr);       /* prompt */
+        fflush(stderr);
+        i = 0;
+        echoff(f);
+        do {                    /* read line, keeping n */
+            if ((c = (char)getc(f)) == '\r')
+                c = '\n';
+            if (i < n)
+                p[i++] = c;
+        } while (c != '\n');
+        echon();
+        PUTC('\n', stderr);  fflush(stderr);
+        w = "(line too long--try again)\n";
+    } while (p[i-1] != '\n');
+    p[i-1] = 0;                 /* terminate at newline */
+#ifndef PASSWD_FROM_STDIN
+    fclose(f);
+#endif
+
+    return p;                   /* return pointer to password */
+
+} /* end function getp() */
+
+#endif /* VMS || CMS_MVS */
+#endif /* ?HAVE_WORKING_GETCH */
+#endif /* CRYPT */
+#endif /* CRYPT || (UNZIP && !FUNZIP) */
diff --git a/ttyio.h b/ttyio.h
new file mode 100644 (file)
index 0000000..ba281cf
--- /dev/null
+++ b/ttyio.h
@@ -0,0 +1,218 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+   ttyio.h
+ */
+
+#ifndef __ttyio_h   /* don't include more than once */
+#define __ttyio_h
+
+#ifndef __crypt_h
+#  include "crypt.h"  /* ensure that encryption header file has been seen */
+#endif
+
+#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP)))
+/*
+ * Non-echo keyboard/console input support is needed and enabled.
+ */
+
+#ifndef __G         /* UnZip only, for now (DLL stuff) */
+#  define __G
+#  define __G__
+#  define __GDEF
+#  define __GPRO    void
+#  define __GPRO__
+#endif
+
+#ifndef ZCONST      /* UnZip only (until have configure script like Zip) */
+#  define ZCONST const
+#endif
+
+#if (defined(MSDOS) || defined(OS2) || defined(WIN32))
+#  ifndef DOS_OS2_W32
+#    define DOS_OS2_W32
+#  endif
+#endif
+
+#if (defined(DOS_OS2_W32) || defined(__human68k__))
+#  ifndef DOS_H68_OS2_W32
+#    define DOS_H68_OS2_W32
+#  endif
+#endif
+
+#if (defined(DOS_OS2_W32) || defined(FLEXOS))
+#  ifndef DOS_FLX_OS2_W32
+#    define DOS_FLX_OS2_W32
+#  endif
+#endif
+
+#if (defined(DOS_H68_OS2_W32) || defined(FLEXOS))
+#  ifndef DOS_FLX_H68_OS2_W32
+#    define DOS_FLX_H68_OS2_W32
+#  endif
+#endif
+
+#if (defined(VM_CMS) || defined(MVS))
+#  ifndef CMS_MVS
+#    define CMS_MVS
+#  endif
+#endif
+
+
+/* Function prototypes */
+
+/* The following systems supply a `non-echo' character input function "getch()"
+ * (or an alias) and do not need the echoff() / echon() function pair.
+ */
+#ifdef AMIGA
+#  define echoff(f)
+#  define echon()
+#  define getch() Agetch()
+#  define HAVE_WORKING_GETCH
+#endif /* AMIGA */
+
+#ifdef ATARI
+#  define echoff(f)
+#  define echon()
+#  include <osbind.h>
+#  define getch() (Cnecin() & 0x000000ff)
+#  define HAVE_WORKING_GETCH
+#endif
+
+#ifdef MACOS
+#  define echoff(f)
+#  define echon()
+#  define getch() macgetch()
+#  define HAVE_WORKING_GETCH
+#endif
+
+#ifdef NLM
+#  define echoff(f)
+#  define echon()
+#  define HAVE_WORKING_GETCH
+#endif
+
+#ifdef QDOS
+#  define echoff(f)
+#  define echon()
+#  define HAVE_WORKING_GETCH
+#endif
+
+#ifdef RISCOS
+#  define echoff(f)
+#  define echon()
+#  define getch() SWI_OS_ReadC()
+#  define HAVE_WORKING_GETCH
+#endif
+
+#ifdef DOS_H68_OS2_W32
+#  define echoff(f)
+#  define echon()
+#  ifdef WIN32
+#    ifndef getch
+#      define getch() getch_win32()
+#    endif
+#  else /* !WIN32 */
+#    ifdef __EMX__
+#      ifndef getch
+#        define getch() _read_kbd(0, 1, 0)
+#      endif
+#    else /* !__EMX__ */
+#      ifdef __GO32__
+#        include <pc.h>
+#        define getch() getkey()
+#      else /* !__GO32__ */
+#        include <conio.h>
+#      endif /* ?__GO32__ */
+#    endif /* ?__EMX__ */
+#  endif /* ?WIN32 */
+#  define HAVE_WORKING_GETCH
+#endif /* DOS_H68_OS2_W32 */
+
+#ifdef FLEXOS
+#  define echoff(f)
+#  define echon()
+#  define getch() getchar() /* not correct, but may not be on a console */
+#  define HAVE_WORKING_GETCH
+#endif
+
+/* For VM/CMS and MVS, we do not (yet) have any support to switch terminal
+ * input echo on and off. The following "fake" definitions allow inclusion
+ * of crypt support and UnZip's "pause prompting" features, but without
+ * any echo suppression.
+ */
+#ifdef CMS_MVS
+#  define echoff(f)
+#  define echon()
+#endif
+
+#ifdef TANDEM
+#  define echoff(f)
+#  define echon()
+#  define getch() zgetch() /* defined in TANDEMC */
+#  define HAVE_WORKING_GETCH
+#endif
+
+/* The THEOS C runtime library supplies the function conmask() to toggle
+ * terminal input echo on (conmask("e")) and off (conmask("n")).  But,
+ * since THEOS C RTL also contains a working non-echo getch() function,
+ * the echo toggles are not needed.
+ */
+#ifdef THEOS
+#  define echoff(f)
+#  define echon()
+#  define HAVE_WORKING_GETCH
+#endif
+
+/* VMS has a single echo() function in ttyio.c to toggle terminal
+ * input echo on and off.
+ */
+#ifdef VMS
+#  define echoff(f)  echo(0)
+#  define echon()    echo(1)
+   int echo OF((int));
+#endif
+
+/* For all other systems, ttyio.c supplies the two functions Echoff() and
+ * Echon() for suppressing and (re)enabling console input echo.
+ */
+#ifndef echoff
+#  define echoff(f)  Echoff(__G__ f)
+#  define echon()    Echon(__G)
+   void Echoff OF((__GPRO__ int f));
+   void Echon OF((__GPRO));
+#endif
+
+/* this stuff is used by MORE and also now by the ctrl-S code; fileio.c only */
+#if (defined(UNZIP) && !defined(FUNZIP))
+#  ifdef HAVE_WORKING_GETCH
+#    define FGETCH(f)  getch()
+#  endif
+#  ifndef FGETCH
+     /* default for all systems where no getch()-like function is available */
+     int zgetch OF((__GPRO__ int f));
+#    define FGETCH(f)  zgetch(__G__ f)
+#  endif
+#endif /* UNZIP && !FUNZIP */
+
+#if (CRYPT && !defined(WINDLL))
+   char *getp OF((__GPRO__ ZCONST char *m, char *p, int n));
+#endif
+
+#else /* !(CRYPT || (UNZIP && !FUNZIP)) */
+
+/*
+ * No need for non-echo keyboard/console input; provide dummy definitions.
+ */
+#define echoff(f)
+#define echon()
+
+#endif /* ?(CRYPT || (UNZIP && !FUNZIP)) */
+
+#endif /* !__ttyio_h */
diff --git a/unix/Makefile b/unix/Makefile
new file mode 100644 (file)
index 0000000..e1780a0
--- /dev/null
@@ -0,0 +1,268 @@
+# Makefile for Zip, ZipNote, ZipCloak and ZipSplit
+
+# what you can make ...
+all:
+       @echo ''
+       @echo 'Make what?  You must say what system to make Zip for--e.g.'
+       @echo '"make generic".  Choices: generic, generic_gcc,'
+       @echo 'att6300nodir, coherent, cray_v3, cygwin, lynx, minix,'
+       @echo 'os390, qnx, qnxnto, solaris, solaris_gcc'
+       @echo 'See the files INSTALL and zip.txt for more information.'
+       @echo ''
+
+list:   all
+
+MAKE = make -f unix/Makefile
+SHELL = /bin/sh
+LN = ln -s
+
+# (to use the Gnu compiler, change cc to gcc in CC)
+CC = cc
+BIND = $(CC)
+AS = $(CC) -c
+CPP = /lib/cpp
+EXE =
+
+# probably can change this to 'install' if you have it
+INSTALL_PROGRAM = cp
+# probably can change this to 'install -d' if you have it
+# XXX NextStep 3.3 and Openstep 4.x don't know about -p !
+INSTALL_D = mkdir -p
+CHMOD = chmod
+BINFLAGS = 755
+MANFLAGS = 644
+
+# target directories - where to install executables and man pages to
+prefix = /usr/local
+BINDIR = $(prefix)/bin
+manext=1
+MANDIR = $(prefix)/man/man$(manext)
+ZIPMANUAL = MANUAL
+PKGDIR = IZzip
+VERSION = Version 2.31
+
+# flags
+#   CFLAGS    flags for C compile
+#   LFLAGS1   flags after output file spec, before obj file list
+#   LFLAGS2   flags after obj file list (libraries, etc)
+CFLAGS = -O2 -I. -DUNIX $(LOCAL_ZIP)
+LFLAGS1 =
+LFLAGS2 = -s
+
+# object file lists
+OBJZ = zip.o zipfile.o zipup.o fileio.o util.o globals.o crypt.o ttyio.o \
+       unix.o crc32.o crctab.o
+OBJI = deflate.o trees.o
+OBJA =
+OBJU = zipfile_.o fileio_.o util_.o globals.o unix_.o
+OBJN = zipnote.o  $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt_.o ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h unix/osdep.h
+
+# suffix rules
+.SUFFIXES:
+.SUFFIXES: _.o .o .c .doc .1
+.c_.o:
+       rm -f $*_.c; $(LN) $< $*_.c
+       $(CC) -c $(CFLAGS) -DUTIL $*_.c
+       rm -f $*_.c
+.c.o:
+       $(CC) -c $(CFLAGS) $<
+
+.1.doc:
+       nroff -man $< | col -bx | uniq > $@
+
+# rules for zip, zipnote, zipcloak, zipsplit, and the Zip MANUAL.
+$(OBJZ): $(ZIP_H)
+$(OBJI): $(ZIP_H)
+$(OBJN): $(ZIP_H)
+$(OBJS): $(ZIP_H)
+$(OBJC): $(ZIP_H)
+zip.o zipup.o crypt.o ttyio.o zipcloak.o crypt_.o: crypt.h
+zip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h
+zip.o crypt.o ttyio.o zipcloak.o crypt_.o: ttyio.h
+zipup.o: unix/zipup.h
+
+match.o: match.S
+       $(CPP) match.S > _match.s
+       $(AS) _match.s
+       mv _match.o match.o
+       rm -f _match.s
+
+crc_i386.o: crc_i386.S
+       $(CPP) crc_i386.S > _crc_i386.s
+       $(AS) _crc_i386.s
+       mv _crc_i386.o crc_i386.o
+       rm -f _crc_i386.s
+
+unix.o: unix/unix.c
+       $(CC) -c $(CFLAGS) unix/unix.c
+
+unix_.o: unix/unix.c
+       rm -f unix_.c; $(LN) unix/unix.c unix_.c
+       $(CC) -c $(CFLAGS) -DUTIL unix_.c
+       rm -f unix_.c
+
+ZIPS = zip$(EXE) zipnote$(EXE) zipsplit$(EXE) zipcloak$(EXE)
+
+zips: $(ZIPS)
+zipsman: $(ZIPS) $(ZIPMANUAL)
+
+zip$(EXE): $(OBJZ) $(OBJI) $(OBJA)
+       $(BIND) -o zip$(EXE) $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)
+zipnote$(EXE): $(OBJN)
+       $(BIND) -o zipnote$(EXE) $(LFLAGS1) $(OBJN) $(LFLAGS2)
+zipcloak$(EXE): $(OBJC)
+       $(BIND) -o zipcloak$(EXE) $(LFLAGS1) $(OBJC) $(LFLAGS2)
+zipsplit$(EXE): $(OBJS)
+       $(BIND) -o zipsplit$(EXE) $(LFLAGS1) $(OBJS) $(LFLAGS2)
+
+$(ZIPMANUAL): man/zip.1
+       nroff -man man/zip.1 | col -bx | uniq > $(ZIPMANUAL)
+
+
+# install
+install:        $(ZIPS)
+       -$(INSTALL_D) $(BINDIR)
+       $(INSTALL_PROGRAM) $(ZIPS) $(BINDIR)
+       -cd $(BINDIR); $(CHMOD) $(BINFLAGS) $(ZIPS)
+       -$(INSTALL_D) $(MANDIR)
+       $(INSTALL) man/zip.1 $(MANDIR)/zip.$(manext)
+       $(CHMOD) $(MANFLAGS) $(MANDIR)/zip.$(manext)
+
+uninstall:
+       -cd $(BINDIR); rm -f $(ZIPS)
+       -cd $(MANDIR); rm -f zip.$(manext)
+
+flags:  unix/configure
+       sh unix/configure "${CC}" "${CFLAGS}"
+
+# These symbols, when #defined using -D have these effects on compilation:
+# ZMEM                  - includes C language versions of memset(), memcpy(),
+#                         and memcmp() (util.c).
+# HAVE_DIRENT_H         - use <dirent.h> instead of <sys/dir.h>
+# NODIR                 - for 3B1, which has neither getdents() nor opendir().
+# HAVE_NDIR_H           - use <ndir.h> (unix/unix.c).
+# HAVE_SYS_DIR_H        - use <sys/dir.h>
+# HAVE_SYS_NDIR_H       - use <sys/ndir.h>
+# UTIL                  - select routines for utilities (note, cloak, split)
+# NO_RMDIR              - remove directories using a system("rmdir ...") call.
+# NO_PROTO              - cannot handle ANSI prototypes
+# NO_CONST              - cannot handle ANSI const
+
+#               Generic targets:
+
+generic: flags
+       eval $(MAKE) zips `cat flags`
+
+generic_gcc:
+       $(MAKE) generic CC=gcc CPP="gcc -E"
+
+# AT&T 6300 PLUS (don't know yet how to allocate 64K bytes):
+att6300nodir:
+       $(MAKE) zips LFLAGS1="-Ml -s" \
+       CFLAGS="-DUNIX -I. -O -Ml -DNO_RMDIR -DDYN_ALLOC -DMEDIUM_MEM \
+-DWSIZE=16384 -DNO_STDLIB_H -DNO_STDDEF_H -DNO_RENAME \
+-DNO_MKTIME -DNO_SIZE_T -DNO_VOID -DNO_PROTO -DNO_DIR \
+-DNO_CONST -DHAVE_TERMIO_H" \
+       "LFLAGS2="
+
+# Coherent (AS definition not needed for gcc)
+coherent:
+       $(MAKE) zips CFLAGS="-DUNIX -I. -O -DDIRENT -DASMV" AS="as -gx" \
+                    OBJA=match.o
+
+# Cray Unicos 6.1, Standard C compiler 3.0 (all routines except trees.c
+# may be compiled with vector3; internal compiler bug in 3.0.2.3 and
+# earlier requires vector2 for trees.c)
+cray_v3:
+       $(MAKE) zips CC="scc" \
+               CFLAGS="-DUNIX -I. -O -h vector2 -h scalar3 -DHAVE_DIRENT_H"
+
+# Cygwin
+cygwin:
+       $(MAKE) generic CC="gcc" CPP="gcc -E" EXE=".exe"
+
+# LynxOS
+lynx:
+       $(MAKE) generic CC=gcc CPP="gcc -E" CFLAGS="$(CFLAGS) -DNO_UNDERLINE -DLynx -DLYNX LFLAGS2="$LFLAGS2 -lc_p"
+
+# MINIX 1.5.10 with Bruce Evans 386 patches and gcc/GNU make
+minix:
+       $(MAKE) zips CFLAGS="-DUNIX -I. -O -DDIRENT -DMINIX" CC=gcc
+       chmem =262144 zip
+
+# IBM OS/390 (formerly MVS) compiled under "OpenEdition" shell
+# You can make the zip executable with IBM's make, but you will
+# get errors dealing with the _.o targets for the other executables
+# (zipcloak, etc).  GNU make will build all the executables.
+# If you have GNU make in your path as gmake, uncomment the following:
+#MAKE = gmake -f unix/Makefile
+os390:
+       ${MAKE} zips CFLAGS="$(CF) -I. -DUNIX -DOS390 -DEBCDIC -DSYSV \
+-DSYSV -DNO_PARAM_H" LFLAGS2=""
+
+# QNX is "special" because out /bin/sh is ksh and it doesn't grok the
+# configure script properly, generating a bad flags file.  D'oh! [cjh]
+#
+# QNX/Neutrino is "special" because you don't have any native development
+# tools yet.  Set ARCH to "x86", "ppcbe", "ppcle", "mipsbe", or "mipsle"
+# to produce x86, PowerPC (big- or little-endian) and MIPS (big-
+# or little-endian) using gcc. [cjh]
+qnx:
+       $(MAKE) zips LN=ln CC=cc CFLAGS="-DUNIX -I. -O -DHAVE_DIRENT_H \
+-DHAVE_TERMIOS_H -DNO_MKTEMP"
+
+qnxnto:
+       @if [ "$(ARCH)" = "" ] ; then \
+               echo "You didn't set ARCH; I'll assume you meant ARCH=x86..." ; \
+               echo "" ; \
+               $(MAKE) zips LN=ln CC="qcc -Vgcc_ntox86" \
+                       CFLAGS="-g -DUNIX -I. -O -DHAVE_DIRENT_H -DHAVE_TERMIOS_H -DNO_MKTEMP" \
+                       LFLAGS2=-g ; \
+       else \
+               echo "Making zip for $(ARCH)..." ; \
+               echo "" ; \
+               $(MAKE) zips LN=ln CC="qcc -Vgcc_nto$(ARCH)" \
+                       CFLAGS="-g -DUNIX -I. -O -DHAVE_DIRENT_H -DHAVE_TERMIOS_H -DNO_MKTEMP" \
+                       LFLAGS2=-g ; \
+       fi
+
+# Solaris:  Generic, plus generation of installable package.
+solaris:       generic svr4package
+
+# Solaris with GCC: generic_gcc, plus generation of installable package
+solaris_gcc:   generic_gcc svr4package
+
+# Package generation interface (by JBush). Originally tested under Sun Solaris.
+# Other SVr4s may be very similar, and could possibly use this.
+# Note:  Expects version info to be stored in VERSION macro variable.
+# See "README" under ./unix/Packaging
+svr4package:
+       @echo "Creating SVR4 package for Unix ..."
+       -@rm -rf ./$(PKGDIR) ./$(PKGDIR)_`uname -p`.pkg
+       -@sed -e "s/.VERSION./$(VERSION)/g" \
+             -e "s/.PSTAMP./$(LOGNAME)_`date | tr  ' ' '_'`/g" \
+             -e "s/.ARCH./Solaris_`uname -rp | tr ' ' ','`/g" \
+             ./unix/Packaging/pkginfo.in > ./unix/Packaging/pkginfo
+       -@sed -e "s/.ARCH./`uname -p`/g" \
+             ./unix/Packaging/preinstall.in > ./unix/Packaging/preinstall
+       /usr/bin/pkgmk -d . -b . -r . -f ./unix/Packaging/prototype $(PKGDIR)
+       /usr/bin/pkgtrans -o -s . $(PKGDIR)_`uname -p`.pkg $(PKGDIR)
+       @echo " "
+       @echo "To install, copy $(PKGDIR)_`uname -p`.pkg to the target system, and"
+       @echo "issue the command (as root):  pkgadd -d $(PKGDIR)_`uname -p`.pkg"
+       @echo " "
+
+# make a distribution
+dist:  $(ZIPMANUAL)
+       eval zip -r9 zip`sed -e '/VERSION/!d' -e 's/.*"\(.*\)".*/\1/' \
+                         -e 's/[.]//g' -e 's/ .*//g' -e q revision.h` *
+
+# clean up after making stuff and installing it
+clean:
+       rm -f *.o $(ZIPS) flags
+       rm -rf $(PKGDIR)
+
diff --git a/unix/Packaging/README b/unix/Packaging/README
new file mode 100644 (file)
index 0000000..6b2a451
--- /dev/null
@@ -0,0 +1,44 @@
+Solaris packaging
+-----------------
+
+To generate a Solaris package for Info-ZIP zip utilities,
+first see the top level INSTALL and README files.  Do a
+"make solaris", which will automatically build two Solaris
+installable package files for the package, IZzip.
+
+   IZzip     -- Solaris installable package in directory format.
+   IZzip_$(arch).pkg -- Solaris installable package in "stream" format.
+
+   Where:  $(arch) := system architecture, currently i386, sparc, or ppc.
+                      (use "uname -p" to determine)
+
+The ".pkg" file is a single file datastream that can be compressed
+and/or ftp'd.  This is the recommended form, because all required
+files are resident in the archive, and it is easily distributed.
+
+To install, simply:
+
+    1)  copy the package to the target system's /tmp directory.
+    2)  login or su to root
+    3)  pkgadd -d /tmp/IZzip_$(arch).pkg
+    4)  add /opt/Info-ZIP/IZzip/bin to PATH
+    5)  add /opt/Info-ZIP/IZzip/man to MANPATH
+
+This works for both SPARC and x86.
+
+Ongoing maintenance:
+
+  Keep the files, "prototype" and "pkginfo.in" up to date.
+  Observe variable substitutions made by "Makefile".
+  See manpages for pkginfo(1), pkginfo(4), pkgmk(1), pkgproto(1)
+
+Variations:
+
+  If you wish the base directory to be set to something other than
+  /opt/Info-ZIP, change the setting BASEDIR in pkginfo.in and
+  re-run the make.
+
+
+-John Bush (John.Bush@East.Sun.COM)
+ July 20, 1996
+
diff --git a/unix/Packaging/pkginfo.in b/unix/Packaging/pkginfo.in
new file mode 100644 (file)
index 0000000..875e144
--- /dev/null
@@ -0,0 +1,13 @@
+PKG=IZzip
+NAME=Info-ZIP Zip Utilities
+CATEGORY=application
+VENDOR=Info-ZIP
+EMAIL=Zip-Bugs@lists.wku.edu
+HOTLINE=Zip-Bugs@lists.wku.edu
+DESC=Copyrighted FREEWARE.  See README, WHERE, and docs in pkg's doc dir.
+CLASSES=none
+BASEDIR=/opt/Info-ZIP
+#BASEDIR=/usr/local
+VERSION=".VERSION."
+PSTAMP=".PSTAMP."
+ARCH=".ARCH."
diff --git a/unix/Packaging/postinstall b/unix/Packaging/postinstall
new file mode 100755 (executable)
index 0000000..030067d
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Post installation script (simply inform installer about PATH etc)
+#
+echo " "
+echo " "
+echo "Installation is complete.  Now, you should add the following"
+echo "(or equivalnet) commands to the appropriate initial user shell"
+echo "scripts (such as .profile, .login, etc) -- "
+echo " "
+echo " For korn or bourne shell:"
+echo "   PATH=\${PATH}:${BASEDIR}/${PKG}/bin"
+echo "   MANPATH=\${MANPATH}:${BASEDIR}/${PKG}/man"
+echo "   export PATH MANPATH"
+echo " "
+echo " For C shell:"
+echo "   set path=(\$path ${BASEDIR}/${PKG}/bin)"
+echo "   setenv MANPATH \$MANPATH:${BASEDIR}/${PKG}/man"
+echo " "
+echo " See the files under ${BASEDIR}/${PKG}/doc for more information."
+echo " "
+exit 0
diff --git a/unix/Packaging/preinstall.in b/unix/Packaging/preinstall.in
new file mode 100755 (executable)
index 0000000..86c4b93
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+echo " "
+echo "REPORT ALL BUGS, PROBLEMS, AND ACCOLADES TO:"
+echo " "
+echo "         Zip-Bugs@lists.wku.edu"
+echo " "
+echo "Checking architecture platform for .ARCH. ..."
+arch=`uname -p`
+if [ "arch_${arch}" != "arch_.ARCH." ]; then
+   echo " "
+   echo "This product MUST be installed on a Solaris .ARCH. platform."
+   echo "Your machine looks like it is a ${arch} platform."
+   echo "Please install the version for the .ARCH. architecture."
+   echo "Aborting the installation because of this. "
+   echo " "
+   returncode=1
+ else
+   echo " "
+   echo "This product works on .ARCH., which you happen to have!"
+   echo " "
+   returncode=0
+fi
+echo " "
+/usr/bin/sleep 4
+exit ${returncode:-1}
+#
diff --git a/unix/Packaging/prototype b/unix/Packaging/prototype
new file mode 100644 (file)
index 0000000..10e48d8
--- /dev/null
@@ -0,0 +1,24 @@
+d none $BASEDIR 0755 root bin
+d none $BASEDIR/$PKG 0755 root bin
+d none $PKG/doc 0755 root bin
+f none $PKG/doc/BUGS=BUGS 0644 root bin
+f none $PKG/doc/README=README 0644 root bin
+f none $PKG/doc/TODO=TODO 0644 root bin
+f none $PKG/doc/WHERE=WHERE 0644 root bin
+f none $PKG/doc/CHANGES=CHANGES 0644 root bin
+f none $PKG/doc/WHATSNEW=WHATSNEW 0644 root bin
+f none $PKG/doc/INSTALL=INSTALL 0644 root bin
+f none $PKG/doc/MANUAL=MANUAL 0644 root bin
+d none $PKG/man 0755 root bin
+d none $PKG/man/man1 0755 root bin
+f none $PKG/man/man1/zip.1=man/zip.1 0644 root bin
+d none $PKG/bin 0755 root bin
+f none $PKG/bin/zip=zip 0755 root bin
+f none $PKG/bin/zipnote=zipnote 0755 root bin
+f none $PKG/bin/zipsplit=zipsplit 0755 root bin
+f none $PKG/bin/zipcloak=zipcloak 0755 root bin
+i README
+i pkginfo
+i prototype
+i preinstall
+i postinstall
diff --git a/unix/README.OS390 b/unix/README.OS390
new file mode 100644 (file)
index 0000000..6fef92b
--- /dev/null
@@ -0,0 +1,85 @@
+
+OS/390 is IBM's follow-on to MVS and includes a POSIX, XOPEN,
+XPG4, build environment, a Unix-style filesystem (called HFS), and
+a POSIX (Born) shell.  This port uses this environment and is a fairly
+straight-forward port of ZIP's Unix port - but uses the existing EBCDIC
+code.  This port does not work with non-HFS (traditional MVS)
+filesystems.
+
+I believe all my changes are isolated with #ifdef's.
+
+Here's some text which might be useful for an OS390 README or
+the manual.
+
+ZIP for OS390 HFS datasets
+--------------------------
+Allows you to create ZIP archives from the OS/390 OpenEdition
+command prompt.  This port uses standard Unix-style I/O routines
+and only works with HFS files.
+
+Usage
+-----
+By default, ZIP does not perform character-set translation, but has
+options to make it easy to convert text files to be compatible with
+other systems
+  zip   zipfile list         # add the files in 'list' to archive 'zipfile'
+  zip -a zipfile list        # same as above, but translate files to ASCII
+  zip -al zipfile list       # same as above, translate linefeeds to DOS style
+  zip -all zipfile list      # same as '-a', translate linefeeds to UNIX style
+
+Build process
+-------------
+Assuming GNU make is available in your path and is called "gmake" (See
+the  notes on Makefile changes below) and a C compiler is available as
+"cc",  then type
+  gmake -f unix/Makefile MAKE=gmake os390
+
+If GNU make is not available, the existing makefile can create zip, but will
+error on the other executable (zipsplit, zipcloak, zipnote) if you type
+  make -f unix/Makefile os390
+
+Overview of Changes
+-------------------
+The OS/390 port is treated as a variant of the Unix port.  EBCDIC support
+was already implemented for CMS/MVS-batch ports.  The specific changes I
+made are summarized below.
+
+unix/Makefile - zip uses a unusual _.o target which IBM's make can't handle.
+Since the Makefile has a macro called MAKE that is used for a recursive
+call to make, I changed the MACRO to call "gmake" - GNU's make - which
+can handle the _.o target.  If you don't have GNU make, you can
+workaround by manually applying symlinks from whatever.c to whatever_.c.
+Alternatively, the whatever_.o files could be explicitely added for os390.
+
+I added an os390 target with appropriate defines.
+
+zipup.c - added code (#ifdef OS390) to convert test to ASCII if -a flag
+was set.
+
+zip.c - changed logic which always used DOS-style newlines when -a was
+set to be consistent with other port (DOS newlines if -l option)
+
+zipfile.c - miscellaneous changes to force storing file names and
+descriptions in ASCII in the zip directory. This makes zip files
+portable  across all platforms. This in turn meant names did not
+need to be translated when displaying messages.
+
+zip.h - strtoasc was missing a closing parenthesis.
+
+ebcdic.h - changed translation table to be consistent with current IBM
+recommendations - exact same changes to ebcdic.h as in my unzip port.
+
+tailor.h - define huge/far/near to be empty
+
+unix/unix.c - substantial changes to deal with mode flags.  Under
+the current XOPEN standards, some of the traditional unix file mode
+bits need not be in fixed locations, but standard access macros must be
+available to access the values.  The old unix.c code just picked up these
+values and saved them as-is where unzip interpreted them.  Existing
+Unix system provided the macros for XOPEN compliance, but left the flags
+in their traditional locations.  OS/390 has a brand new filesystem which
+is XOPEN compliant without revealing the positions of these flags.
+To create the bitmask in the same format unzip expects, the macros are
+tested one-by-one to set the appropriate bits.  This same logic should
+work on any XOPEN system, but takes more instructions (I did test this
+logic on Linux).
diff --git a/unix/configure b/unix/configure
new file mode 100755 (executable)
index 0000000..35ccbb7
--- /dev/null
@@ -0,0 +1,301 @@
+:
+#!/bin/sh
+# The above : is necessary on some buggy systems.
+
+# configure: Guess values for system-dependent variables
+# Output the flag definitions to the file "flags".
+# Parameters: $1 = $CC, $2 = $CFLAGS
+# To construct zip automatically using this file, type
+# "make -f unix/Makefile generic".
+# If this fails, then type "make list" to get a list of special targets.
+
+trap "rm -f conftest* core a.out; exit 1" 1 2 3 15
+
+CC=${1-cc}
+CFLAGS=${2-"-O2 -I. -DUNIX"}
+LFLAGS1=""
+LN="ln -s"
+
+echo Check for the C preprocessor
+# on SVR4, cc -E does not produce correct assembler files. Need /lib/cpp.
+CPP="${CC} -E"
+# solaris as(1) needs -P, maybe others as well ?
+[ -f /usr/ccs/lib/cpp ] && CPP="/usr/ccs/lib/cpp -P"
+[ -f /usr/lib/cpp ] && CPP=/usr/lib/cpp
+[ -f /lib/cpp ] && CPP=/lib/cpp
+[ -f /usr/bin/cpp ] && CPP=/usr/bin/cpp
+[ -f /xenix ] && CPP="${CC} -E"
+[ -f /lynx.os ] && CPP="${CC} -E"
+
+echo "#include <stdio.h>" > conftest.c
+$CPP conftest.c >/dev/null 2>/dev/null || CPP="${CC} -E"
+
+echo Check if we can use asm code
+OBJA=""
+if eval "$CPP match.S > _match.s 2>/dev/null"; then
+  if test ! -s _match.s || grep error < _match.s > /dev/null; then
+    :
+  elif eval "$CC -c _match.s >/dev/null 2>/dev/null" && [ -f _match.o ]; then
+    CFLAGS="${CFLAGS} -DASMV"
+    OBJA="match.o"
+    echo "int foo() { return 0;}" > conftest.c
+    $CC -c conftest.c >/dev/null 2>/dev/null
+    echo Check if compiler generates underlines
+    nm conftest.o | grep "(^|[^_])foo" >/dev/null 2>/dev/null
+    [ $? -eq 0 ] && CPP="${CPP} -DNO_UNDERLINE"
+    if eval "$CPP crc_i386.S > _crc_i386.s 2>/dev/null"; then
+      if eval "$CC -c _crc_i386.s >/dev/null 2>/dev/null" && [ -f _crc_i386.o ]
+      then
+        OBJA="$OBJA crc_i386.o"
+        CFLAGS="${CFLAGS} -DASM_CRC"
+      fi
+    fi
+  fi
+fi
+rm -f _match.s _match.o _crc_i386.s _crc_i386.o
+
+# ANSI options for compilers that don't have __STDC__ defined by default
+# Currently HPUX, pyramid, Dynix, AIX, OSF/1 and ultrix
+
+echo Check for ANSI options
+cat > conftest.c << _EOF_
+int main()
+{
+#ifndef __STDC__
+   forget it
+#endif
+   return 0;
+}
+_EOF_
+$CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null
+if [ $? -ne 0 ]; then
+  for OPT in "-Aa -D_HPUX_SOURCE" -Xa -qlanglvl=ansi -std1 -std
+  do
+    $CC $CFLAGS $OPT -c conftest.c > /dev/null 2>/dev/null
+    [ $? -eq 0 ] && CFLAGS="${CFLAGS} ${OPT}" && break
+  done
+fi
+
+echo Check for prototypes
+echo "int main(int argc, char *argv[]) { return 0; }" > conftest.c
+$CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null
+[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_PROTO"
+
+# const check currently handles mips cc and non ANSI compilers.
+# does it need more ?
+echo Check the handling of const
+cat > conftest.c << _EOF_
+typedef int charset[2];
+int main()
+{
+  const charset x;
+  const char *foo;
+  return 0;
+}
+_EOF_
+$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null
+[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_CONST"
+
+echo Check for time_t
+cat > conftest.c << _EOF_
+#include <sys/types.h>
+#include <time.h>
+int main()
+{
+  time_t t;
+  return 0;
+}
+_EOF_
+$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null
+[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_TIME_T"
+
+echo Check for size_t
+cat > conftest.c << _EOF_
+#include <sys/types.h>
+int main()
+{
+  size_t s;
+  return 0;
+}
+_EOF_
+$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null
+[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_SIZE_T"
+
+echo Check for gcc no-builtin flag
+# -fno-builtin since version 2
+cat > conftest.c << _EOF_
+int main()
+{
+#if __GNUC__ >= 2
+   return 0;
+#else
+   forget it
+#endif
+}
+_EOF_
+$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null
+[ $? -eq 0 ] && BFLAG="-fno-builtin"
+
+# Check for missing functions
+# add NO_'function_name' to flags if missing
+for func in rmdir strchr strrchr rename mktemp mktime mkstemp
+do
+  echo Check for $func
+  echo "int main(){ $func(); return 0; }" > conftest.c
+  $CC $BFLAG -o conftest conftest.c >/dev/null 2>/dev/null
+  [ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_`echo $func | tr '[a-z]' '[A-Z]'`"
+done
+
+echo Check for memset
+echo "int main(){ char k; memset(&k,0,0); return 0; }" > conftest.c
+$CC -o conftest conftest.c >/dev/null 2>/dev/null
+[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DZMEM"
+
+echo Check for errno declaration
+cat > conftest.c << _EOF_
+#include <errno.h>
+main()
+{
+  errno = 0;
+  return 0;
+}
+_EOF_
+$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null
+[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_ERRNO"
+
+echo Check for directory libraries
+cat > conftest.c << _EOF_
+int main() { return closedir(opendir(".")); }
+_EOF_
+
+$CC -o conftest conftest.c >/dev/null 2>/dev/null
+if [ $? -ne 0 ]; then
+  OPT=""
+  for lib in ndir dir ucb bsd BSD PW x dirent
+  do
+    $CC -o conftest conftest.c -l$lib >/dev/null 2>/dev/null
+    [ $? -eq 0 ] && OPT=-l$lib && break
+  done
+  if [ ${OPT} ]; then
+    LFLAGS2="${LFLAGS2} ${OPT}"
+  else
+    CFLAGS="${CFLAGS} -DNO_DIR"
+  fi
+fi
+
+# Dynix/ptx 1.3 needed this
+echo Check for readlink
+echo "int main(){ return readlink(); }" > conftest.c
+$CC -o conftest conftest.c >/dev/null 2>/dev/null
+if [ $? -ne 0 ]; then
+  $CC -o conftest conftest.c -lseq >/dev/null 2>/dev/null
+  [ $? -eq 0 ] && LFLAGS2="${LFLAGS2} -lseq"
+fi
+
+echo Check for directory include file
+OPT=""
+for inc in dirent.h sys/ndir.h ndir.h sys/dir.h
+do
+   echo "#include <$inc>" > conftest.c
+   $CPP conftest.c > /dev/null 2>/dev/null
+   [ $? -eq 0 ] && OPT="-DHAVE_`echo $inc | tr '[a-z]./' '[A-Z]__'`" && break
+done
+CFLAGS="${CFLAGS} ${OPT}"
+
+echo Check for non existent include files
+for inc in stdlib.h stddef.h unistd.h fcntl.h string.h
+do
+   echo "#include <$inc>" > conftest.c
+   $CPP conftest.c >/dev/null 2>/dev/null
+   [ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_`echo $inc | tr '[a-z]./' '[A-Z]__'`"
+done
+
+echo Check for terminal I/O include file
+OPT=""
+for inc in termios.h termio.h sgtty.h
+do
+   echo "#include <$inc>" > conftest.c
+   $CPP conftest.c > /dev/null 2>/dev/null
+   [ $? -eq 0 ] && OPT="-DHAVE_`echo $inc | tr '[a-z]./' '[A-Z]__'`" && break
+done
+CFLAGS="${CFLAGS} ${OPT}"
+
+# needed for AIX (and others ?) when mmap is used
+echo Check for valloc
+cat > conftest.c << _EOF_
+main()
+{
+#ifdef MMAP
+    valloc();
+#endif
+}
+_EOF_
+$CC ${CFLAGS} conftest.c > /dev/null 2>/dev/null
+[ $? -ne 0 ] && CFLAGS="${CFLAGS} -DNO_VALLOC"
+
+echo Check for 64bit fseek
+for func in fseeko fseek64
+do
+cat > conftest.c << _EOF_
+#include <stdio.h>
+main()
+{
+$func(stdin, 0, 0);
+}
+_EOF_
+$CC ${CFLAGS} conftest.c > /dev/null 2>/dev/null
+[ $? -eq 0 ] && OPT="-DHAVE_`echo $func | tr '[a-z]' '[A-Z]'`" && break
+done
+CFLAGS="${CFLAGS} ${OPT}"
+
+echo Check for /usr/local/bin and /usr/local/man
+BINDIR=$HOME/bin
+[ -d /usr/local/bin ] && BINDIR=/usr/local/bin
+
+MANDIR=manl
+[ -d /usr/man/manl ]       && MANDIR=/usr/man/manl
+[ -d /usr/local/man/manl ] && MANDIR=/usr/local/man/manl
+[ -d /usr/local/man/man1 ] && MANDIR=/usr/local/man/man1
+
+echo Check for OS-specific flags
+if [ -f /usr/bin/hostinfo ]; then
+  if /usr/bin/hostinfo | grep NeXT > /dev/null; then
+    CFLAGS="${CFLAGS} -posix"
+    LFLAGS1="${LFLAGS1} -posix -object"
+  fi
+# XXX ATT6300, Cray
+elif [ -f /xenix ]; then
+  if uname -p | grep 286 > /dev/null; then
+    CFLAGS="${CFLAGS} -LARGE -Mel2 -DMEDIUM_MEM -DWSIZE=16384 -DNO_VOID"
+    LFLAGS1="${LFLAGS1} -LARGE -Mel2"
+  fi
+elif uname -X >/dev/null 2>/dev/null; then
+# SCO shared library check
+  echo "int main() { return 0;}" > conftest.c
+  $CC -o conftest conftest.c -lc_s -nointl >/dev/null 2> /dev/null
+  [ $? -eq 0 ] && LFLAGS2="-lc_s -nointl"
+else
+  SYSTEM=`uname -s 2>/dev/null` || SYSTEM="unknown"
+  echo "int main() { return 0;}" > conftest.c
+  case $SYSTEM in
+     OSF1|ULTRIX)
+        echo Check for -Olimit option
+        $CC ${CFLAGS} -Olimit 1000 -o conftest conftest.c >/dev/null 2>/dev/null
+        [ $? -eq 0 ] && CFLAGS="${CFLAGS} -Olimit 1000"
+        ;;
+     HP-UX)
+        echo Check for +Onolimit option
+        $CC ${CFLAGS} +Onolimit -o conftest conftest.c >/dev/null 2>/dev/null
+        [ $? -eq 0 ] && CFLAGS="${CFLAGS} +Onolimit"
+        ;;
+  esac
+fi
+
+echo Check for symbolic links
+ln -s /dev/null null > /dev/null 2>/dev/null || LN=ln
+
+rm -f a.out conftest.c conftest.o conftest null
+
+echo CC=\"${CC}\" CFLAGS=\"${CFLAGS}\"  CPP=\"${CPP}\" OBJA=\"${OBJA}\" \
+       BINDIR=${BINDIR} MANDIR=${MANDIR} LFLAGS1=\"${LFLAGS1}\" \
+       LFLAGS2=\"${LFLAGS2}\" LN=\"${LN}\" > flags
diff --git a/unix/osdep.h b/unix/osdep.h
new file mode 100644 (file)
index 0000000..bfb5d4d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+#ifdef __CYGWIN__
+
+/* File operations:
+ *   use "b" for binary;
+ *   use "S" for sequential access on NT to prevent the NT file cache
+ *   eating up memory with large .zip files.
+ */
+#  define FOPR "rb"
+#  define FOPM "r+b"
+#  define FOPW "wbS"
+
+/* Cygwin is not Win32. */
+#  undef WIN32
+
+#endif /* ?__CYGWIN__ */
+
+
+/* Enable the "UT" extra field (time info) */
+#if !defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)
+#  define USE_EF_UT_TIME
+#endif
diff --git a/unix/unix.c b/unix/unix.c
new file mode 100644 (file)
index 0000000..024b735
--- /dev/null
@@ -0,0 +1,787 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include "zip.h"
+
+#ifndef UTIL    /* the companion #endif is a bit of ways down ... */
+
+#include <time.h>
+
+#if defined(MINIX) || defined(__mpexl)
+#  ifdef S_IWRITE
+#    undef S_IWRITE
+#  endif /* S_IWRITE */
+#  define S_IWRITE S_IWUSR
+#endif /* MINIX */
+
+#if (!defined(S_IWRITE) && defined(S_IWUSR))
+#  define S_IWRITE S_IWUSR
+#endif
+
+#if defined(HAVE_DIRENT_H) || defined(_POSIX_VERSION)
+#  include <dirent.h>
+#else /* !HAVE_DIRENT_H */
+#  ifdef HAVE_NDIR_H
+#    include <ndir.h>
+#  endif /* HAVE_NDIR_H */
+#  ifdef HAVE_SYS_NDIR_H
+#    include <sys/ndir.h>
+#  endif /* HAVE_SYS_NDIR_H */
+#  ifdef HAVE_SYS_DIR_H
+#    include <sys/dir.h>
+#  endif /* HAVE_SYS_DIR_H */
+#  ifndef dirent
+#    define dirent direct
+#  endif
+#endif /* HAVE_DIRENT_H || _POSIX_VERSION */
+
+#define PAD 0
+#define PATH_END '/'
+
+/* Library functions not in (most) header files */
+
+#ifdef _POSIX_VERSION
+#  include <utime.h>
+#else
+   int utime OF((char *, time_t *));
+#endif
+
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+/* Local functions */
+local char *readd OF((DIR *));
+
+
+#ifdef NO_DIR                    /* for AT&T 3B1 */
+#include <sys/dir.h>
+#ifndef dirent
+#  define dirent direct
+#endif
+typedef FILE DIR;
+/*
+**  Apparently originally by Rich Salz.
+**  Cleaned up and modified by James W. Birdsall.
+*/
+
+#define opendir(path) fopen(path, "r")
+
+struct dirent *readdir(dirp)
+DIR *dirp;
+{
+  static struct dirent entry;
+
+  if (dirp == NULL)
+    return NULL;
+  for (;;)
+    if (fread (&entry, sizeof (struct dirent), 1, dirp) == 0)
+      return NULL;
+    else if (entry.d_ino)
+      return (&entry);
+} /* end of readdir() */
+
+#define closedir(dirp) fclose(dirp)
+#endif /* NO_DIR */
+
+
+local char *readd(d)
+DIR *d;                 /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+   no more entries or an error occurs. */
+{
+  struct dirent *e;
+
+  e = readdir(d);
+  return e == NULL ? (char *) NULL : e->d_name;
+}
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  char *a;              /* path and name for recursion */
+  DIR *d;               /* directory stream from opendir() */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (LSSTAT(n, &s))
+  {
+    /* Not a file or directory--search for shell expression in zip file */
+    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+#ifdef OS390
+  if (S_ISREG(s.st_mode) || S_ISLNK(s.st_mode))
+#else
+#  ifdef S_IFLNK
+  if ((s.st_mode & S_IFREG) == S_IFREG || (s.st_mode & S_IFLNK) == S_IFLNK)
+#  else
+  if ((s.st_mode & S_IFREG) == S_IFREG)
+#  endif
+#endif
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  }
+#ifdef OS390
+  else if (S_ISDIR(s.st_mode))
+#else
+  else if ((s.st_mode & S_IFDIR) == S_IFDIR)
+#endif
+  {
+    /* Add trailing / to the directory name */
+    if ((p = malloc(strlen(n)+2)) == NULL)
+      return ZE_MEM;
+    if (strcmp(n, ".") == 0) {
+      *p = '\0';  /* avoid "./" prefix and do not create zip entry */
+    } else {
+      strcpy(p, n);
+      a = p + strlen(p);
+      if (a[-1] != '/')
+        strcpy(a, "/");
+      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+        free((zvoid *)p);
+        return m;
+      }
+    }
+    /* recurse into directory */
+    if (recurse && (d = opendir(n)) != NULL)
+    {
+      while ((e = readd(d)) != NULL) {
+        if (strcmp(e, ".") && strcmp(e, ".."))
+        {
+          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+          {
+            closedir(d);
+            free((zvoid *)p);
+            return ZE_MEM;
+          }
+          strcat(strcpy(a, p), e);
+          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
+          {
+            if (m == ZE_MISS)
+              zipwarn("name not matched: ", a);
+            else
+              ziperr(m, a);
+          }
+          free((zvoid *)a);
+        }
+      }
+      closedir(d);
+    }
+    free((zvoid *)p);
+  } /* (s.st_mode & S_IFDIR) */
+  else
+    zipwarn("ignoring special file: ", n);
+  return ZE_OK;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t = NULL;       /* shortened name */
+  int dosflag;
+
+  dosflag = dosify;  /* default for non-DOS and non-OS/2 */
+
+  /* Find starting point in name before doing malloc */
+  /* Strip "//host/share/" part of a UNC name */
+  if (!strncmp(x,"//",2) && (x[2] != '\0' && x[2] != '/')) {
+    n = x + 2;
+    while (*n != '\0' && *n != '/')
+      n++;              /* strip host name */
+    if (*n != '\0') {
+      n++;
+      while (*n != '\0' && *n != '/')
+        n++;            /* strip `share' name */
+    }
+    if (*n != '\0')
+      t = n + 1;
+  } else
+      t = x;
+  while (*t == '/')
+    t++;                /* strip leading '/' chars to get a relative path */
+  while (*t == '.' && t[1] == '/')
+    t += 2;             /* strip redundant leading "./" sections */
+
+  /* Make changes, if any, to the copied name (leave original intact) */
+  if (!pathput)
+    t = last(t, PATH_END);
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL)
+    return NULL;
+  strcpy(n, t);
+
+  if (isdir == 42) return n;    /* avoid warning on unused variable */
+
+  if (dosify)
+    msname(n);
+
+#ifdef EBCDIC
+  strtoasc(n, n);               /* here because msname() needs native coding */
+#endif
+
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+  return n;
+}
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+
+  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+    return NULL;
+#ifdef EBCDIC
+  strtoebc(x, n);
+#else
+  strcpy(x, n);
+#endif
+  return x;
+}
+
+/*
+ * XXX use ztimbuf in both POSIX and non POSIX cases ?
+ */
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+#ifdef _POSIX_VERSION
+  struct utimbuf u;     /* argument for utime()  const ?? */
+#else
+  time_t u[2];          /* argument for utime() */
+#endif
+
+  /* Convert DOS time to time_t format in u */
+#ifdef _POSIX_VERSION
+  u.actime = u.modtime = dos2unixtime(d);
+  utime(f, &u);
+#else
+  u[0] = u[1] = dos2unixtime(d);
+  utime(f, u);
+#endif
+
+}
+
+ulg filetime(f, a, n, t)
+  char *f;                /* name of file to get info on */
+  ulg *a;                 /* return value: file attributes */
+  long *n;              /* return value: file size */
+  iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  /* converted to pointer from using FNMAX - 11/8/04 EG */
+  char *name;
+  int len = strlen(f);
+
+  if (f == label) {
+    if (a != NULL)
+      *a = label_mode;
+    if (n != NULL)
+      *n = -2L; /* convention for a label name */
+    if (t != NULL)
+      t->atime = t->mtime = t->ctime = label_utim;
+    return label_time;
+  }
+  if ((name = malloc(len + 1)) == NULL) {
+    ZIPERR(ZE_MEM, "filetime");
+  }
+  strcpy(name, f);
+  if (name[len - 1] == '/')
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+  if (strcmp(f, "-") == 0) {
+    if (fstat(fileno(stdin), &s) != 0) {
+      free(name);
+      error("fstat(stdin)");
+    }
+  }
+  else if (LSSTAT(name, &s) != 0) {
+    /* Accept about any file kind including directories
+     * (stored with trailing / with -r option)
+     */
+    free(name);
+    return 0;
+  }
+  free(name);
+
+  if (a != NULL) {
+#ifndef OS390
+    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
+#else
+/*
+**  The following defines are copied from the unizip source and represent the
+**  legacy Unix mode flags.  These fixed bit masks are no longer required
+**  by XOPEN standards - the S_IS### macros being the new recommended method.
+**  The approach here of setting the legacy flags by testing the macros should
+**  work under any _XOPEN_SOURCE environment (and will just rebuild the same bit
+**  mask), but is required if the legacy bit flags differ from legacy Unix.
+*/
+#define UNX_IFDIR      0040000     /* Unix directory */
+#define UNX_IFREG      0100000     /* Unix regular file */
+#define UNX_IFSOCK     0140000     /* Unix socket (BSD, not SysV or Amiga) */
+#define UNX_IFLNK      0120000     /* Unix symbolic link (not SysV, Amiga) */
+#define UNX_IFBLK      0060000     /* Unix block special       (not Amiga) */
+#define UNX_IFCHR      0020000     /* Unix character special   (not Amiga) */
+#define UNX_IFIFO      0010000     /* Unix fifo    (BCC, not MSC or Amiga) */
+    {
+    mode_t legacy_modes;
+
+    /* Initialize with permission bits--which are not implementation-optional */
+    legacy_modes = s.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX);
+    if (S_ISDIR(s.st_mode))
+      legacy_modes |= UNX_IFDIR;
+    if (S_ISREG(s.st_mode))
+      legacy_modes |= UNX_IFREG;
+    if (S_ISLNK(s.st_mode))
+      legacy_modes |= UNX_IFLNK;
+    if (S_ISBLK(s.st_mode))
+      legacy_modes |= UNX_IFBLK;
+    if (S_ISCHR(s.st_mode))
+      legacy_modes |= UNX_IFCHR;
+    if (S_ISFIFO(s.st_mode))
+      legacy_modes |= UNX_IFIFO;
+    if (S_ISSOCK(s.st_mode))
+      legacy_modes |= UNX_IFSOCK;
+    *a = ((ulg)legacy_modes << 16) | !(s.st_mode & S_IWRITE);
+    }
+#endif
+    if ((s.st_mode & S_IFMT) == S_IFDIR) {
+      *a |= MSDOS_DIR_ATTR;
+    }
+  }
+  if (n != NULL)
+    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = t->mtime;   /* best guess, (s.st_ctime: last status change!!) */
+  }
+
+  return unix2dostime(&s.st_mtime);
+}
+
+
+#ifndef QLZIP /* QLZIP Unix2QDOS cross-Zip supplies an extended variant */
+
+int set_extra_field(z, z_utim)
+  struct zlist far *z;
+  iztimes *z_utim;
+  /* store full data in local header but just modification time stamp info
+     in central header */
+{
+  struct stat s;
+  char *name;
+  int len = strlen(z->name);
+
+  /* For the full sized UT local field including the UID/GID fields, we
+   * have to stat the file again. */
+
+  if ((name = malloc(len + 1)) == NULL) {
+    ZIPERR(ZE_MEM, "set_extra_field");
+  }
+  strcpy(name, z->name);
+  if (name[len - 1] == '/')
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+  if (LSSTAT(name, &s)) {
+    free(name);
+    return ZE_OPEN;
+  }
+  free(name);
+
+#define EB_L_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(2))
+#define EB_C_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(1))
+#define EB_L_UX2_SIZE   (EB_HEADSIZE + EB_UX2_MINLEN)
+#define EB_C_UX2_SIZE   EB_HEADSIZE
+#define EF_L_UNIX_SIZE  (EB_L_UT_SIZE + EB_L_UX2_SIZE)
+#define EF_C_UNIX_SIZE  (EB_C_UT_SIZE + EB_C_UX2_SIZE)
+
+  if ((z->extra = (char *)malloc(EF_L_UNIX_SIZE)) == NULL)
+    return ZE_MEM;
+  if ((z->cextra = (char *)malloc(EF_C_UNIX_SIZE)) == NULL)
+    return ZE_MEM;
+
+  z->extra[0]  = 'U';
+  z->extra[1]  = 'T';
+  z->extra[2]  = (char)EB_UT_LEN(2);    /* length of data part of local e.f. */
+  z->extra[3]  = 0;
+  z->extra[4]  = EB_UT_FL_MTIME | EB_UT_FL_ATIME;    /* st_ctime != creation */
+  z->extra[5]  = (char)(s.st_mtime);
+  z->extra[6]  = (char)(s.st_mtime >> 8);
+  z->extra[7]  = (char)(s.st_mtime >> 16);
+  z->extra[8]  = (char)(s.st_mtime >> 24);
+  z->extra[9]  = (char)(s.st_atime);
+  z->extra[10] = (char)(s.st_atime >> 8);
+  z->extra[11] = (char)(s.st_atime >> 16);
+  z->extra[12] = (char)(s.st_atime >> 24);
+  z->extra[13] = 'U';
+  z->extra[14] = 'x';
+  z->extra[15] = (char)EB_UX2_MINLEN;   /* length of data part of local e.f. */
+  z->extra[16] = 0;
+  z->extra[17] = (char)(s.st_uid);
+  z->extra[18] = (char)(s.st_uid >> 8);
+  z->extra[19] = (char)(s.st_gid);
+  z->extra[20] = (char)(s.st_gid >> 8);
+  z->ext = EF_L_UNIX_SIZE;
+
+  memcpy(z->cextra, z->extra, EB_C_UT_SIZE);
+  z->cextra[EB_LEN] = (char)EB_UT_LEN(1);
+  memcpy(z->cextra+EB_C_UT_SIZE, z->extra+EB_L_UT_SIZE, EB_C_UX2_SIZE);
+  z->cextra[EB_LEN+EB_C_UT_SIZE] = 0;
+  z->cext = EF_C_UNIX_SIZE;
+
+#if 0  /* UID/GID presence is now signaled by central EF_IZUNIX2 field ! */
+  /* lower-middle external-attribute byte (unused until now):
+   *   high bit        => (have GMT mod/acc times) >>> NO LONGER USED! <<<
+   *   second-high bit => have Unix UID/GID info
+   * NOTE: The high bit was NEVER used in any official Info-ZIP release,
+   *       but its future use should be avoided (if possible), since it
+   *       was used as "GMT mod/acc times local extra field" flags in Zip beta
+   *       versions 2.0j up to 2.0v, for about 1.5 years.
+   */
+  z->atx |= 0x4000;
+#endif /* never */
+  return ZE_OK;
+}
+
+#endif /* !QLZIP */
+
+
+int deletedir(d)
+char *d;                /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+   Return the result of rmdir(), delete(), or system().
+   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).
+ */
+{
+# ifdef NO_RMDIR
+    /* code from Greg Roelofs, who horked it from Mark Edwards (unzip) */
+    int r, len;
+    char *s;              /* malloc'd string for system command */
+
+    len = strlen(d);
+    if ((s = malloc(len + 34)) == NULL)
+      return 127;
+
+    sprintf(s, "IFS=\" \t\n\" /bin/rmdir %s 2>/dev/null", d);
+    r = system(s);
+    free(s);
+    return r;
+# else /* !NO_RMDIR */
+    return rmdir(d);
+# endif /* ?NO_RMDIR */
+}
+
+#endif /* !UTIL */
+
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__386BSD__) || \
+    defined(__OpenBSD__) || defined(__bsdi__)
+#include <sys/param.h> /* for the BSD define */
+/* if we have something newer than NET/2 we'll use uname(3) */
+#if (BSD > 199103)
+#include <sys/utsname.h>
+#endif /* BSD > 199103 */
+#endif /* __{Net,Free,Open,386}BSD__ || __bsdi__ */
+
+void version_local()
+{
+#ifdef __GNUC__
+#  ifdef NX_CURRENT_COMPILER_RELEASE
+    char compiler_name[80];
+#  endif
+#else
+#  if ((defined(CRAY) || defined(cray)) && defined(_RELEASE))
+    char compiler_name[40];
+#  endif
+#endif
+
+#ifdef BSD
+# if (BSD > 199103)
+    struct utsname u;
+    char os_name[40];
+# else
+# if defined(__NETBSD__))
+    static ZCONST char *netbsd[] = { "_ALPHA", "", "A", "B" };
+    char os_name[40];
+# endif /* __NETBSD__ */
+# endif /* BSD > 199103 */
+#else /* !BSD */
+#if ((defined(CRAY) || defined(cray)) && defined(_UNICOS))
+    char os_name[40];
+#endif /* (CRAY && defined(_UNICOS)) */
+#endif /* ?BSD */
+
+/* Define the compiler name and version string */
+#ifdef __GNUC__
+#  ifdef NX_CURRENT_COMPILER_RELEASE
+    sprintf(compiler_name, "NeXT DevKit %d.%02d (gcc " __VERSION__ ")",
+        NX_CURRENT_COMPILER_RELEASE/100, NX_CURRENT_COMPILER_RELEASE%100);
+#    define COMPILER_NAME compiler_name
+#  else
+#    define COMPILER_NAME "gcc " __VERSION__
+#  endif
+#else /* !__GNUC__ */
+#  if ((defined(CRAY) || defined(cray)) && defined(_RELEASE))
+    sprintf(compiler_name, "cc version %d", _RELEASE);
+#    define COMPILER_NAME compiler_name
+#  else
+#  ifdef __VERSION__
+#    define COMPILER_NAME "cc " __VERSION__
+#  else
+#    define COMPILER_NAME "cc "
+#  endif
+#  endif
+#endif /* ?__GNUC__ */
+
+
+/* Define the name to use for the OS we're compiling on */
+#if defined(sgi) || defined(__sgi)
+#  define OS_NAME "Silicon Graphics IRIX"
+#else
+#ifdef sun
+#  ifdef sparc
+#    ifdef __SVR4
+#      define OS_NAME "Sun Sparc/Solaris"
+#    else /* may or may not be SunOS */
+#      define OS_NAME "Sun Sparc"
+#    endif
+#  else
+#  if defined(sun386) || defined(i386)
+#    define OS_NAME "Sun 386i"
+#  else
+#  if defined(mc68020) || defined(__mc68020__)
+#    define OS_NAME "Sun 3"
+#  else /* mc68010 or mc68000:  Sun 2 or earlier */
+#    define OS_NAME "Sun 2"
+#  endif
+#  endif
+#  endif
+#else
+#ifdef __hpux
+#  define OS_NAME "HP/UX"
+#else
+#ifdef __osf__
+#  define OS_NAME "DEC OSF/1"
+#else
+#ifdef _AIX
+#  define OS_NAME "IBM AIX"
+#else
+#ifdef aiws
+#  define OS_NAME "IBM RT/AIX"
+#else
+#if defined(CRAY) || defined(cray)
+#  ifdef _UNICOS
+    sprintf(os_name, "Cray UNICOS release %d", _UNICOS);
+#    define OS_NAME os_name
+#  else
+#    define OS_NAME "Cray UNICOS"
+#  endif
+#else
+#if defined(uts) || defined(UTS)
+#  define OS_NAME "Amdahl UTS"
+#else
+#ifdef NeXT
+#  ifdef mc68000
+#    define OS_NAME "NeXTStep/black"
+#  else
+#    define OS_NAME "NeXTStep for Intel"
+#  endif
+#else
+#if defined(linux) || defined(__linux__)
+#  ifdef __ELF__
+#    define OS_NAME "Linux ELF"
+#  else
+#    define OS_NAME "Linux a.out"
+#  endif
+#else
+#ifdef MINIX
+#  define OS_NAME "Minix"
+#else
+#ifdef M_UNIX
+#  define OS_NAME "SCO Unix"
+#else
+#ifdef M_XENIX
+#  define OS_NAME "SCO Xenix"
+#else
+#ifdef BSD
+# if (BSD > 199103)
+#    define OS_NAME os_name
+    uname(&u);
+    sprintf(os_name, "%s %s", u.sysname, u.release);
+# else
+# ifdef __NetBSD__
+#   define OS_NAME os_name
+#   ifdef NetBSD0_8
+      sprintf(os_name, "NetBSD 0.8%s", netbsd[NetBSD0_8]);
+#   else
+#   ifdef NetBSD0_9
+      sprintf(os_name, "NetBSD 0.9%s", netbsd[NetBSD0_9]);
+#   else
+#   ifdef NetBSD1_0
+      sprintf(os_name, "NetBSD 1.0%s", netbsd[NetBSD1_0]);
+#   endif /* NetBSD1_0 */
+#   endif /* NetBSD0_9 */
+#   endif /* NetBSD0_8 */
+# else
+# ifdef __FreeBSD__
+#    define OS_NAME "FreeBSD 1.x"
+# else
+# ifdef __bsdi__
+#    define OS_NAME "BSD/386 1.0"
+# else
+# ifdef __386BSD__
+#    define OS_NAME "386BSD"
+# else
+#    define OS_NAME "Unknown BSD"
+# endif /* __386BSD__ */
+# endif /* __bsdi__ */
+# endif /* FreeBSD */
+# endif /* NetBSD */
+# endif /* BSD > 199103 */
+#else
+#ifdef __CYGWIN__
+#  define OS_NAME "Cygwin"
+#else
+#if defined(i686) || defined(__i686) || defined(__i686__)
+#  define OS_NAME "Intel 686"
+#else
+#if defined(i586) || defined(__i586) || defined(__i586__)
+#  define OS_NAME "Intel 586"
+#else
+#if defined(i486) || defined(__i486) || defined(__i486__)
+#  define OS_NAME "Intel 486"
+#else
+#if defined(i386) || defined(__i386) || defined(__i386__)
+#  define OS_NAME "Intel 386"
+#else
+#ifdef pyr
+#  define OS_NAME "Pyramid"
+#else
+#if defined(ultrix) || defined(__ultrix)
+#  if defined(mips) || defined(__mips)
+#    define OS_NAME "DEC/MIPS"
+#  else
+#  if defined(vax) || defined(__vax)
+#    define OS_NAME "DEC/VAX"
+#  else /* __alpha? */
+#    define OS_NAME "DEC/Alpha"
+#  endif
+#  endif
+#else
+#ifdef gould
+#  define OS_NAME "Gould"
+#else
+#ifdef MTS
+#  define OS_NAME "MTS"
+#else
+#ifdef __convexc__
+#  define OS_NAME "Convex"
+#else
+#ifdef __QNX__
+#  define OS_NAME "QNX 4"
+#else
+#ifdef __QNXNTO__
+#  define OS_NAME "QNX Neutrino"
+#else
+#ifdef __APPLE__
+#  define OS_NAME "Mac OS X"
+#else
+#  define OS_NAME "Unknown"
+#endif /* Apple */
+#endif /* QNX Neutrino */
+#endif /* QNX 4 */
+#endif /* Convex */
+#endif /* MTS */
+#endif /* Gould */
+#endif /* DEC */
+#endif /* Pyramid */
+#endif /* 386 */
+#endif /* 486 */
+#endif /* 586 */
+#endif /* 686 */
+#endif /* Cygwin */
+#endif /* BSD */
+#endif /* SCO Xenix */
+#endif /* SCO Unix */
+#endif /* Minix */
+#endif /* Linux */
+#endif /* NeXT */
+#endif /* Amdahl */
+#endif /* Cray */
+#endif /* RT/AIX */
+#endif /* AIX */
+#endif /* OSF/1 */
+#endif /* HP/UX */
+#endif /* Sun */
+#endif /* SGI */
+
+
+/* Define the compile date string */
+#ifdef __DATE__
+#  define COMPILE_DATE " on " __DATE__
+#else
+#  define COMPILE_DATE ""
+#endif
+
+    printf("Compiled with %s for Unix (%s)%s.\n\n",
+           COMPILER_NAME, OS_NAME, COMPILE_DATE);
+
+} /* end function version_local() */
diff --git a/unix/zipup.h b/unix/zipup.h
new file mode 100644 (file)
index 0000000..fbec842
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#ifndef O_RDONLY
+#  define O_RDONLY 0
+#endif
+#ifndef O_BINARY
+#  define O_BINARY 0
+#endif
+#define fhow (O_RDONLY|O_BINARY)
+#define fbad (-1)
+typedef int ftype;
+#define zopen(n,p) open(n,p)
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f) close(f)
+#define zerr(f) (k == (extent)(-1L))
+#define zstdin 0
diff --git a/util.c b/util.c
new file mode 100644 (file)
index 0000000..dca2eae
--- /dev/null
+++ b/util.c
@@ -0,0 +1,694 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *  util.c by Mark Adler.
+ */
+#define __UTIL_C
+
+#include "zip.h"
+#include "ebcdic.h"
+#include <ctype.h>
+
+#ifdef MSDOS16
+#  include <dos.h>
+#endif
+
+uch upper[256], lower[256];
+/* Country-dependent case map table */
+
+
+#ifndef UTIL /* UTIL picks out namecmp code (all utils) */
+
+/* Local functions */
+local int recmatch OF((ZCONST uch *, ZCONST uch *, int));
+local int count_args OF((char *s));
+
+#ifdef MSDOS16
+  local unsigned ident OF((unsigned chr));
+#endif
+
+#ifdef NO_MKTIME
+#include "mktime.c"
+#endif
+
+#ifndef HAVE_FSEEKABLE
+int fseekable(fp)
+FILE *fp;
+{
+    long x;
+
+    return (fp == NULL || (fseek(fp, -1L, SEEK_CUR) == 0 &&
+            (x = ftell(fp)) >= 0 &&
+            fseek(fp,  1L, SEEK_CUR) == 0 &&
+            ftell(fp) == x + 1));
+}
+#endif /* HAVE_FSEEKABLE */
+
+char *isshexp(p)
+char *p;                /* candidate sh expression */
+/* If p is a sh expression, a pointer to the first special character is
+   returned.  Otherwise, NULL is returned. */
+{
+  for (; *p; INCSTR(p))
+    if (*p == '\\' && *(p+1))
+      p++;
+#ifdef VMS
+    else if (*p == '%' || *p == '*')
+#else /* !VMS */
+# ifdef RISCOS
+    /* RISC OS uses # as its single-character wildcard */
+    else if (*p == '#' || *p == '*' || *p == '[')
+# else /* !RISC OS */
+    else if (*p == '?' || *p == '*' || *p == '[')
+# endif
+#endif /* ?VMS */
+      return p;
+  return NULL;
+}
+
+
+local int recmatch(p, s, cs)
+ZCONST uch *p;  /* sh pattern to match */
+ZCONST uch *s;  /* string to match it to */
+int cs;         /* flag: force case-sensitive matching */
+/* Recursively compare the sh pattern p with the string s and return 1 if
+   they match, and 0 or 2 if they don't or if there is a syntax error in the
+   pattern.  This routine recurses on itself no deeper than the number of
+   characters in the pattern. */
+{
+  unsigned int c;       /* pattern char or start of range in [-] loop */
+  /* Get first character, the pattern for new recmatch calls follows */
+  c = *POSTINCSTR(p);
+
+  /* If that was the end of the pattern, match if string empty too */
+  if (c == 0)
+    return *s == 0;
+
+  /* '?' (or '%' or '#') matches any character (but not an empty string) */
+#ifdef VMS
+  if (c == '%')
+#else /* !VMS */
+# ifdef RISCOS
+  if (c == '#')
+# else /* !RISC OS */
+  if (c == '?')
+# endif
+#endif /* ?VMS */
+#ifdef WILD_STOP_AT_DIR
+    return (*s && *s != '/') ? recmatch(p, s + CLEN(s), cs) : 0;
+#else
+    return *s ? recmatch(p, s + CLEN(s), cs) : 0;
+#endif
+
+  /* '*' matches any number of characters, including zero */
+#ifdef AMIGA
+  if (c == '#' && *p == '?')            /* "#?" is Amiga-ese for "*" */
+    c = '*', p++;
+#endif /* AMIGA */
+  if (c == '*')
+  {
+    if (*p == 0)
+      return 1;
+#ifdef WILD_STOP_AT_DIR
+    for (; *s && *s != '/'; INCSTR(s))
+      if ((c = recmatch(p, s, cs)) != 0)
+        return (int)c;
+    return (*p == '/' || (*p == '\\' && p[1] == '/'))
+      ? recmatch(p, s, cs) : 2;
+#else /* !WILD_STOP_AT_DIR */
+    for (; *s; INCSTR(s))
+      if ((c = recmatch(p, s, cs)) != 0)
+        return (int)c;
+    return 2;           /* 2 means give up--shmatch will return false */
+#endif /* ?WILD_STOP_AT_DIR */
+  }
+
+#ifndef VMS             /* No bracket matching in VMS */
+  /* Parse and process the list of characters and ranges in brackets */
+  if (c == '[')
+  {
+    int e;              /* flag true if next char to be taken literally */
+    ZCONST uch *q;      /* pointer to end of [-] group */
+    int r;              /* flag true to match anything but the range */
+
+    if (*s == 0)                        /* need a character to match */
+      return 0;
+    p += (r = (*p == '!' || *p == '^')); /* see if reverse */
+    for (q = p, e = 0; *q; q++)         /* find closing bracket */
+      if (e)
+        e = 0;
+      else
+        if (*q == '\\')
+          e = 1;
+        else if (*q == ']')
+          break;
+    if (*q != ']')                      /* nothing matches if bad syntax */
+      return 0;
+    for (c = 0, e = *p == '-'; p < q; p++)      /* go through the list */
+    {
+      if (e == 0 && *p == '\\')         /* set escape flag if \ */
+        e = 1;
+      else if (e == 0 && *p == '-')     /* set start of range if - */
+        c = *(p-1);
+      else
+      {
+        uch cc = (cs ? *s : case_map(*s));
+        if (*(p+1) != '-')
+          for (c = c ? c : (unsigned)*p; c <= (unsigned)*p; c++)
+            /* compare range */
+            if ((cs ? c : case_map(c)) == cc)
+              return r ? 0 : recmatch(q + CLEN(q), s + CLEN(s), cs);
+        c = e = 0;                      /* clear range, escape flags */
+      }
+    }
+    return r ? recmatch(q + CLEN(q), s + CLEN(s), cs) : 0;
+                                        /* bracket match failed */
+  }
+#endif /* !VMS */
+
+  /* If escape ('\'), just compare next character */
+  if (c == '\\')
+    if ((c = *p++) == '\0')             /* if \ at end, then syntax error */
+      return 0;
+
+  /* Just a character--compare it */
+  return (cs ? c == *s : case_map(c) == case_map(*s)) ?
+          recmatch(p, s + CLEN(s), cs) : 0;
+}
+
+
+int shmatch(p, s, cs)
+ZCONST char *p;         /* sh pattern to match */
+ZCONST char *s;         /* string to match it to */
+int cs;                 /* force case-sensitive match if TRUE */
+/* Compare the sh pattern p with the string s and return true if they match,
+   false if they don't or if there is a syntax error in the pattern. */
+{
+  return recmatch((ZCONST uch *) p, (ZCONST uch *) s, cs) == 1;
+}
+
+
+#if defined(DOS) || defined(WIN32)
+/* XXX  also suitable for OS2?  Atari?  Human68K?  TOPS-20?? */
+
+int dosmatch(p, s, cs)
+ZCONST char *p;         /* dos pattern to match    */
+ZCONST char *s;         /* string to match it to   */
+int cs;                 /* force case-sensitive match if TRUE */
+/* Treat filenames without periods as having an implicit trailing period */
+{
+  char *s1;             /* revised string to match */
+  int r;                /* result */
+
+  if ((s1 = malloc(strlen(s) + 2)) == NULL)
+    /* will usually be OK */
+    return recmatch((ZCONST uch *) p, (ZCONST uch *) s, cs) == 1;
+  strcpy(s1, s);
+  if (strchr(p, '.') && !strchr(s1, '.'))
+    strcat(s1, ".");
+  r = recmatch((ZCONST uch *)p, (ZCONST uch *)s1, cs);
+  free((zvoid *)s1);
+  return r == 1;
+}
+
+#endif /* DOS || WIN32 */
+
+zvoid far **search(b, a, n, cmp)
+ZCONST zvoid *b;        /* pointer to value to search for */
+ZCONST zvoid far **a;   /* table of pointers to values, sorted */
+extent n;               /* number of pointers in a[] */
+int (*cmp) OF((ZCONST zvoid *, ZCONST zvoid far *)); /* comparison function */
+
+/* Search for b in the pointer list a[0..n-1] using the compare function
+   cmp(b, c) where c is an element of a[i] and cmp() returns negative if
+   *b < *c, zero if *b == *c, or positive if *b > *c.  If *b is found,
+   search returns a pointer to the entry in a[], else search() returns
+   NULL.  The nature and size of *b and *c (they can be different) are
+   left up to the cmp() function.  A binary search is used, and it is
+   assumed that the list is sorted in ascending order. */
+{
+  ZCONST zvoid far **i; /* pointer to midpoint of current range */
+  ZCONST zvoid far **l; /* pointer to lower end of current range */
+  int r;                /* result of (*cmp)() call */
+  ZCONST zvoid far **u; /* pointer to upper end of current range */
+
+  l = (ZCONST zvoid far **)a;  u = l + (n-1);
+  while (u >= l) {
+    i = l + ((unsigned)(u - l) >> 1);
+    if ((r = (*cmp)(b, (ZCONST char far *)*(struct zlist far **)i)) < 0)
+      u = i - 1;
+    else if (r > 0)
+      l = i + 1;
+    else
+      return (zvoid far **)i;
+  }
+  return NULL;          /* If b were in list, it would belong at l */
+}
+
+#endif /* !UTIL */
+
+#ifdef MSDOS16
+
+local unsigned ident(unsigned chr)
+{
+   return chr; /* in al */
+}
+
+void init_upper()
+{
+  static struct country {
+    uch ignore[18];
+    int (far *casemap)(int);
+    uch filler[16];
+  } country_info;
+
+  struct country far *info = &country_info;
+  union REGS regs;
+  struct SREGS sregs;
+  unsigned int c;
+
+  regs.x.ax = 0x3800; /* get country info */
+  regs.x.dx = FP_OFF(info);
+  sregs.ds  = FP_SEG(info);
+  intdosx(&regs, &regs, &sregs);
+  for (c = 0; c < 128; c++) {
+    upper[c] = (uch) toupper(c);
+    lower[c] = (uch) c;
+  }
+  for (; c < sizeof(upper); c++) {
+    upper[c] = (uch) (*country_info.casemap)(ident(c));
+    /* ident() required because casemap takes its parameter in al */
+    lower[c] = (uch) c;
+  }
+  for (c = 0; c < sizeof(upper); c++ ) {
+    int u = upper[c];
+    if (u != c && lower[u] == (uch) u) {
+      lower[u] = (uch)c;
+    }
+  }
+  for (c = 'A'; c <= 'Z'; c++) {
+    lower[c] = (uch) (c - 'A' + 'a');
+  }
+}
+#else /* !MSDOS16 */
+#  ifndef OS2
+
+void init_upper()
+{
+  unsigned int c;
+#if defined(ATARI) || defined(CMS_MVS)
+#include <ctype.h>
+/* this should be valid for all other platforms too.   (HD 11/11/95) */
+  for (c = 0; c< sizeof(upper); c++) {
+    upper[c] = islower(c) ? toupper(c) : c;
+    lower[c] = isupper(c) ? tolower(c) : c;
+  }
+#else
+  for (c = 0; c < sizeof(upper); c++) upper[c] = lower[c] = (uch)c;
+  for (c = 'a'; c <= 'z';        c++) upper[c] = (uch)(c - 'a' + 'A');
+  for (c = 'A'; c <= 'Z';        c++) lower[c] = (uch)(c - 'A' + 'a');
+#endif
+}
+#  endif /* !OS2 */
+
+#endif /* ?MSDOS16 */
+
+int namecmp(string1, string2)
+  ZCONST char *string1, *string2;
+/* Compare the two strings ignoring case, and correctly taking into
+ * account national language characters. For operating systems with
+ * case sensitive file names, this function is equivalent to strcmp.
+ */
+{
+  int d;
+
+  for (;;)
+  {
+    d = (int) (uch) case_map(*string1)
+      - (int) (uch) case_map(*string2);
+
+    if (d || *string1 == 0 || *string2 == 0)
+      return d;
+
+    string1++;
+    string2++;
+  }
+}
+
+#ifdef EBCDIC
+char *strtoasc(char *str1, ZCONST char *str2)
+{
+  char *old;
+  old = str1;
+  while (*str1++ = (char)ascii[(uch)(*str2++)]);
+  return old;
+}
+
+char *strtoebc(char *str1, ZCONST char *str2)
+{
+  char *old;
+  old = str1;
+  while (*str1++ = (char)ebcdic[(uch)(*str2++)]);
+  return old;
+}
+
+char *memtoasc(char *mem1, ZCONST char *mem2, unsigned len)
+{
+  char *old;
+  old = mem1;
+  while (len--)
+     *mem1++ = (char)ascii[(uch)(*mem2++)];
+  return old;
+}
+
+char *memtoebc(char *mem1, ZCONST char *mem2, unsigned len)
+{
+  char *old;
+  old = mem1;
+  while (len--)
+     *mem1++ = (char)ebcdic[(uch)(*mem2++)];
+  return old;
+}
+#endif /* EBCDIC */
+
+#ifdef IZ_ISO2OEM_ARRAY
+char *str_iso_to_oem(dst, src)
+  ZCONST char *src;
+  char *dst;
+{
+  char *dest_start = dst;
+  while (*dst++ = (char)iso2oem[(uch)(*src++)]);
+  return dest_start;
+}
+#endif
+
+#ifdef IZ_OEM2ISO_ARRAY
+char *str_oem_to_iso(dst, src)
+  ZCONST char *src;
+  char *dst;
+{
+  char *dest_start = dst;
+  while (*dst++ = (char)oem2iso[(uch)(*src++)]);
+  return dest_start;
+}
+#endif
+
+
+
+/* DBCS support for Info-ZIP's zip  (mainly for japanese (-: )
+ * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp)
+ * This code is public domain!   Date: 1998/12/20
+ */
+#ifdef _MBCS
+
+char *___tmp_ptr;
+
+int lastchar(ptr)
+    ZCONST char *ptr;
+{
+    ZCONST char *oldptr = ptr;
+    while(*ptr != '\0'){
+        oldptr = ptr;
+        INCSTR(ptr);
+    }
+    return (int)(unsigned)*oldptr;
+}
+
+unsigned char *zmbschr(str, c)
+    ZCONST unsigned char *str;
+    unsigned int c;
+{
+    while(*str != '\0'){
+        if (*str == c) {return (char*)str;}
+        INCSTR(str);
+    }
+    return NULL;
+}
+
+unsigned char *zmbsrchr(str, c)
+    ZCONST unsigned char *str;
+    unsigned int c;
+{
+    unsigned char *match = NULL;
+    while(*str != '\0'){
+        if (*str == c) {match = (char*)str;}
+        INCSTR(str);
+    }
+    return match;
+}
+#endif /* _MBCS */
+
+
+
+#ifndef UTIL
+
+/*****************************************************************
+ | envargs - add default options from environment to command line
+ |----------------------------------------------------------------
+ | Author: Bill Davidsen, original 10/13/91, revised 23 Oct 1991.
+ | This program is in the public domain.
+ |----------------------------------------------------------------
+ | Minor program notes:
+ |  1. Yes, the indirection is a tad complex
+ |  2. Parenthesis were added where not needed in some cases
+ |     to make the action of the code less obscure.
+ ****************************************************************/
+
+void envargs(Pargc, Pargv, envstr, envstr2)
+    int *Pargc;
+    char ***Pargv;
+    char *envstr;
+    char *envstr2;
+{
+    char *envptr;                     /* value returned by getenv */
+    char *bufptr;                     /* copy of env info */
+    int argc;                         /* internal arg count */
+    register int ch;                  /* spare temp value */
+    char **argv;                      /* internal arg vector */
+    char **argvect;                   /* copy of vector address */
+
+    /* see if anything in the environment */
+    envptr = getenv(envstr);
+    if (envptr != NULL)                                /* usual var */
+        while (isspace((uch)*envptr))      /* we must discard leading spaces */
+            envptr++;
+    if (envptr == NULL || *envptr == '\0')
+        if ((envptr = getenv(envstr2)) != NULL)                 /* alternate */
+            while (isspace((uch)*envptr))
+                envptr++;
+    if (envptr == NULL || *envptr == '\0')
+        return;
+
+    /* count the args so we can allocate room for them */
+    argc = count_args(envptr);
+    bufptr = malloc(1 + strlen(envptr));
+    if (bufptr == NULL)
+        ziperr(ZE_MEM, "Can't get memory for arguments");
+    strcpy(bufptr, envptr);
+
+    /* allocate a vector large enough for all args */
+    argv = (char **)malloc((argc + *Pargc + 1) * sizeof(char *));
+    if (argv == NULL) {
+        free(bufptr);
+        ziperr(ZE_MEM, "Can't get memory for arguments");
+    }
+    argvect = argv;
+
+    /* copy the program name first, that's always true */
+    *(argv++) = *((*Pargv)++);
+
+    /* copy the environment args first, may be changed */
+    do {
+#if defined(AMIGA) || defined(UNIX)
+        if (*bufptr == '"') {
+            char *argstart = ++bufptr;
+            *(argv++) = argstart;
+            for (ch = *bufptr; ch != '\0' && ch != '\"';
+                 ch = *PREINCSTR(bufptr))
+                if (ch == '\\' && bufptr[1] != '\0')
+                    ++bufptr;               /* skip to char after backslash */
+            if (ch != '\0')                       /* overwrite trailing '"' */
+                *(bufptr++) = '\0';
+
+            /* remove escape characters */
+            while ((argstart = MBSCHR(argstart, '\\')) != NULL) {
+                strcpy(argstart, argstart + 1);
+                if (*argstart)
+                    ++argstart;
+            }
+        } else {
+            *(argv++) = bufptr;
+            while ((ch = *bufptr) != '\0' && !isspace((uch)ch)) INCSTR(bufptr);
+            if (ch != '\0') *(bufptr++) = '\0';
+        }
+#else
+#  ifdef WIN32
+        /* We do not support backslash-quoting of quotes in quoted */
+        /* strings under Win32, because backslashes are directory  */
+        /* separators and double quotes are illegal in filenames.  */
+        if (*bufptr == '"') {
+            *(argv++) = ++bufptr;
+            while ((ch = *bufptr) != '\0' && ch != '\"') INCSTR(bufptr);
+            if (ch != '\0') *(bufptr++) = '\0';
+        } else {
+            *(argv++) = bufptr;
+            while ((ch = *bufptr) != '\0' && !isspace((uch)ch)) INCSTR(bufptr);
+            if (ch != '\0') *(bufptr++) = '\0';
+        }
+#  else
+        *(argv++) = bufptr;
+        while ((ch = *bufptr) != '\0' && !isspace((uch)ch)) INCSTR(bufptr);
+        if (ch != '\0') *(bufptr++) = '\0';
+#  endif
+#endif /* ?(AMIGA || UNIX) */
+        while ((ch = *bufptr) != '\0' && isspace((uch)ch)) INCSTR(bufptr);
+    } while (ch);
+
+    /* now save old argc and copy in the old args */
+    argc += *Pargc;
+    while (--(*Pargc)) *(argv++) = *((*Pargv)++);
+
+    /* finally, add a NULL after the last arg, like UNIX */
+    *argv = NULL;
+
+    /* save the values and return */
+    *Pargv = argvect;
+    *Pargc = argc;
+}
+
+static int count_args(s)
+char *s;
+{
+    int count = 0;
+    char ch;
+
+    do {
+        /* count and skip args */
+        ++count;
+#if defined(AMIGA) || defined(UNIX)
+        if (*s == '\"') {
+            for (ch = *PREINCSTR(s); ch != '\0' && ch != '\"';
+                 ch = *PREINCSTR(s))
+                if (ch == '\\' && s[1] != '\0')
+                    INCSTR(s);
+            if (*s) INCSTR(s);  /* trailing quote */
+        } else
+            while ((ch = *s) != '\0' && !isspace((uch)ch)) INCSTR(s);
+#else
+#  ifdef WIN32
+        if (*s == '\"') {
+            ++s;                /* leading quote */
+            while ((ch = *s) != '\0' && ch != '\"') INCSTR(s);
+            if (*s) INCSTR(s);  /* trailing quote */
+        } else
+            while ((ch = *s) != '\0' && !isspace((uch)ch)) INCSTR(s);
+#  else
+        while ((ch = *s) != '\0' && !isspace((uch)ch)) INCSTR(s);
+#  endif
+#endif /* ?(AMIGA || UNIX) */
+        while ((ch = *s) != '\0' && isspace((uch)ch)) INCSTR(s);
+    } while (ch);
+
+    return(count);
+}
+
+
+
+/* Extended argument processing -- by Rich Wales
+ * This function currently deals only with the MKS shell, but could be
+ * extended later to understand other conventions.
+ *
+ * void expand_args(int *argcp, char ***argvp)
+ *
+ *    Substitutes the extended command line argument list produced by
+ *    the MKS Korn Shell in place of the command line info from DOS.
+ *
+ *    The MKS shell gets around DOS's 128-byte limit on the length of
+ *    a command line by passing the "real" command line in the envi-
+ *    ronment.  The "real" arguments are flagged by prepending a tilde
+ *    (~) to each one.
+ *
+ *    This "expand_args" routine creates a new argument list by scanning
+ *    the environment from the beginning, looking for strings begin-
+ *    ning with a tilde character.  The new list replaces the original
+ *    "argv" (pointed to by "argvp"), and the number of arguments
+ *    in the new list replaces the original "argc" (pointed to by
+ *    "argcp").
+ */
+void expand_args(argcp, argvp)
+      int *argcp;
+      char ***argvp;
+{
+#ifdef DOS
+
+/* Do NEVER include (re)definiton of `environ' variable with any version
+   of MSC or BORLAND/Turbo C. These compilers supply an incompatible
+   definition in <stdlib.h>.  */
+#if defined(__GO32__) || defined(__EMX__)
+      extern char **environ;          /* environment */
+#endif /* __GO32__ || __EMX__ */
+      char        **envp;             /* pointer into environment */
+      char        **newargv;          /* new argument list */
+      char        **argp;             /* pointer into new arg list */
+      int           newargc;          /* new argument count */
+
+      /* sanity check */
+      if (environ == NULL
+          || argcp == NULL
+          || argvp == NULL || *argvp == NULL)
+              return;
+      /* find out how many environment arguments there are */
+      for (envp = environ, newargc = 0;
+           *envp != NULL && (*envp)[0] == '~';
+           envp++, newargc++) ;
+      if (newargc == 0)
+              return;                 /* no environment arguments */
+      /* set up new argument list */
+      newargv = (char **) malloc(sizeof(char **) * (newargc+1));
+      if (newargv == NULL)
+              return;                 /* malloc failed */
+      for (argp = newargv, envp = environ;
+           *envp != NULL && (*envp)[0] == '~';
+           *argp++ = &(*envp++)[1]) ;
+      *argp = NULL;                   /* null-terminate the list */
+      /* substitute new argument list in place of old one */
+      *argcp = newargc;
+      *argvp = newargv;
+#else /* !DOS */
+      if (argcp || argvp) return;
+#endif /* ?DOS */
+}
+
+#endif /* UTIL */
+
+#ifdef DEBUGNAMES
+#undef free
+int Free(x)
+void *x;
+{
+    if (x == (void *) 0xdeadbeef)
+        exit(-1);
+    free(x);
+    return 0;
+}
+
+int printnames()
+{
+     struct zlist far *z;
+
+     for (z = zfiles; z != NULL; z = z->nxt)
+           fprintf(stderr, "%s %s %s %p %p %p %08x %08x %08x\n",
+                            z->name, z->zname, z->iname,
+                            z->name, z->zname, z->iname,
+                            *((int *) z->name), *((int *) z->zname),
+                            *((int *) z->iname));
+     return 0;
+}
+
+#endif /* DEBUGNAMES */
diff --git a/vms/00binary.vms b/vms/00binary.vms
new file mode 100644 (file)
index 0000000..aa0dc41
--- /dev/null
@@ -0,0 +1,87 @@
+First information about the binary distribution of VMS Zip 2.3
+--------------------------------------------------------------
+This archive comes in different variations:
+
+ "zip22x-vms-<cpu-compiler>-{obj|exe}.zip",
+
+ where <cpu-compiler> is "axp", "vax-decc", or "vax-vaxc", depending on
+ the environment used for creating the binaries.
+
+ ...-obj.zip denotes object library distributions which require
+ a link step on the local machine.
+
+ ...-exe.zip denotes "ready-to-run" executable distributions, that do
+ not require additional work but do not run on VMS versions which are
+ older than the system used for building the executables.
+
+Contents of the "vms" executables archives for Zip 2.3:
+
+a) common files (documentation etc.):
+  00binary.vms         this file
+  00readme.txt         additional VMS info about compiling Zip
+  readme               what Zip is; general information
+  changes              list of changes against the previous official version
+  algorith.txt         description of the deflation algorithm
+  infozip.who          list of contributors to the "portable Zip" project
+  manual               Zip manual page, human-readable format
+  whatsnew             list of important changes and new features
+  where                pointer to Zip/UnZip support archives
+  zip.hlp              VMS help module, for Zip's default command interface
+  zip_cli.hlp          VMS help module, for Zip's VMSCLI command interface
+
+b) object library distributions:
+  link_zip.com         command procedure for the linking step
+  vms/                 auxiliary directory, required for link step
+
+  zip.<cpu_compiler>_olb       object library for Zip (both command interfaces)
+  zipcli.<cpu_compiler>_olb    additional object library (Zip CLI interface)
+  zipcloak.<cpu_compiler>_obj  main object file for ZipCloak
+  zipnote.<cpu_compiler>_obj   main object file for ZipNote
+  zipsplit.<cpu_compiler>_obj  main object file for ZipSplit
+  ziputils.<cpu_compiler>_olb  object library for the Zip Utilities
+
+c) executable distributions:
+  zip.exe              Zip executable, default (UNIX style) command interface
+  zipcloak.exe         Utility for encrypting and decrypting zip archives
+  zipnote.exe          Utility for editing entry names and comments
+  zipsplit.exe         Utility for splitting large zip archives
+  zip_cli.exe          Zip executable, VMSCLI command interface
+
+
+In case you decided to fetch the object library distribution, you
+have to link the executables on your local site. This requires
+installed runtime support for the C runtime library, which may not be
+present on older VAX systems (prior to VMS 6).
+To create the executables, just invoke the "link_zip.com" command procedure.
+This will generate all executables (both zip with UNIX style command syntax
+and zip_cli with VMSCLI command interface), but note that the executable's
+extension is ".<cpu_compiler>_exe"!
+In case your are on a VAX and your current working directory carries
+both the DECC and the VAXC object distributions, you have to specify
+either "VAXC" or "DECC" to tell link_zip.com which binaries you want
+to build.
+
+Additionally, link_zip.com defines foreign commands for the just created
+executables, so you can test them straight ahead.
+If you want to use the default (UNIX like) command interface, you can
+proceed straight ahead after unpacking the distribution.
+When you rather prefer to use the VMSCLI interface, you have to specify
+the option "VMSCLI" (or just "CLI") to the command starting link_zip.com.
+
+The executables (object libraries) in this archive have been compiled
+with the following options enabled:
+ * VMS_PK_EXTRA      (this is the default option)
+ * [decription support]
+
+The environment used for compilation was:
+
+a)  On Alpha AXP :   OpenVMS(AXP) 6.2;  DEC C V 5.6-003
+b1) On VAX       :   OpenVMS(VAX) 6.2;  DEC C V 4.0
+b2)                       alternatively VAX C V 3.2
+
+One final note:
+The binary files of the distribution have been archived with "saving all VMS
+attributes" enabled. Please do not repack the binary part of the archives on
+a non-VMS system, to prevent corruption of the files.
+
+02-Feb-1999, Christian Spieler
diff --git a/vms/00readme.txt b/vms/00readme.txt
new file mode 100644 (file)
index 0000000..020d8ae
--- /dev/null
@@ -0,0 +1,126 @@
+*****************************************
+************ vms/00readme.txt ***********
+*****************************************
+
+Additional information for compiling Zip for VMS:
+
+A) Support for storing VMS specific file attributes
+   ================================================
+
+The current version of Zip comes with two different types of support
+to store VMS file attributes in extra blocks:
+
+  -- the traditional Info-ZIP format in vms/vms_im.c
+and
+
+  -- a new PKware (ASI) type extra field structure in vms/vms_pk.c
+
+Both versions should supply exactly the same functionality.
+Up to Zip 2.1, the default configuration was to use the traditional IM style,
+since it was well tested and known to be stable.
+==> NEW <==
+As of Zip 2.2, this default has been changed to use PK style extra field
+format. This change is needed to support indexed VMS files. The
+IM style code in UnZip (!!) has a known problem that prevents the correct
+restoring operation for some (but not all) indexed VMS files.
+
+IMPORTANT: To extract new PK style extra fields, Info-ZIP's
+           UnZip version 5.2 or newer is required, previous
+           versions will crash with an access violation !!!!
+
+If you want to use the old IM style support (to achieve compatibility
+with older versions of UnZip), the preprocessor symbol VMS_IM_EXTRA
+has to be defined at compile time.
+
+MMS (MMK) users have to edit vms/descrip.mms and add this symbol to
+the definition of the COMMON_DEFS macro; for example:
+
+COMMON_DEFS = VMS_IM_EXTRA,
+
+if VMS_IM_EXTRA is the only option. (NOTE the trailing comma!)
+
+Users of the DCL make procedure can select the PK style support by defining
+the DCL symbol LOCAL_ZIP as a list of user specific compilation options
+(do not forget the trailing comma!!). Example:
+$ LOCAL_ZIP == "VMS_IM_EXTRA,"
+
+
+B) Notes on the compiler switches used on VMS:
+   ===========================================
+
+The source has been successfully compiled on VMS 6.1 (VMS 6.2 for AXP), using
+ - DEC C 5.2 and 5.6 for Alpha AXP
+ - DEC C 4.0 for VMS VAX
+ - VAX C 3.2
+
+1. Discussion of the /STANDARD switch:
+
+With the exception of some few rough spots in the VMS specific sources,
+the code is fully compatible with the "RELAXED_ANSI" mode of the DEC C
+compilers. The problems found in vmsmunch.c and vms_pk.c are caused
+by incompatibles between the system include headers supplied for DEC C
+(AXP) and DEC C (VAX) which cannot get worked around. (Some system
+service structure members have type "unsigned int"  in the VAX version,
+but "pointer to [miscellanous]" in the AXP headers.)
+I consider the AXP headers to show the direction of `future developement'
+and have adapted the sources to match the AXP's header files.
+This means:
+On Alpha AXP, we can equally well use "/STANDARD=RELAXED" instead of
+"/STANDARD=VAXC" without getting any warnings.
+With the current release of DEC C on VAX, the /STANDARD=VAXC switch is
+required to suppress the "assignment to incompatible type" warnings.
+Beginning with the Zip 2.1 release, the compiler mode for Alpha AXP has
+been changed to "/STANDARD=RELAX", since the "ANSI mode" executables are
+slightly smaller.
+
+2. The /PREFIX_LIBRARY_ENTRIES switch:
+
+In (strict and relaxed) ANSI mode on Alpha AXP, only the standard ANSI
+RTL function names get prefixed with "DECC$" by the compiler per default.
+This results in unresolved references to such functions as "read()", "open()"
+"lseek()" at link step. (The same might be true for earlier releases of DEC C
+on VAX.) To resolve this problem, one has to explicitely request prefixing
+of all DEC C RTL function by applying the "/PREFIX=ALL" switch.
+Although this switch is not needed in "VAXC" mode, it does not hurt either.
+Therefore, "/PREFIX=ALL" is applied regardless of the compilation mode,
+to avoid any problems when switching over to ANSI standard mode in the future.
+
+C) Support for UT extra field UTC time stamps
+   ==========================================
+Beginning with Zip 2.1 and UnZip 5.2, the Info-ZIP compression utilities
+do principally support saving and restoring the modification time of
+Zipfile entries as UTC (GMT) universal time. This new information is
+stored in an "extra field" labeled "UT" (Unix style GMT modification/access
+times, ...).
+Previous version of Zip and UnZip used local time, stored in MSDOS compatible
+format (as specified by PKware for the Zip file format). This practice caused
+a lot of "time synchronization" trouble when transporting Zip archives world
+wide between largely different time zones.
+
+Unfortunately, VMS (and the VMS C runtime environment) up to VMS 6.x does not
+contain support for timezone handling and assumes "local time == UTC time".
+This has changed with the release of VMS 7.0, which does (finally) support
+the concept of "universal world time" that is required for time synchronization
+in intercontinental networks...
+
+For this reason, the UTC time stamp support is disabled in VMS Zip by default,
+otherwise users would experience annoying time stamp deviations when
+locally transfering Zip archives between VMS nodes and other (UNIX, OS/2,
+WinNT/Win95, MSDOS) systems.
+But when compiled on a VMS 7.x system, the UTC "UT extra field" support is
+automatically enabled.
+
+For users located in the GMT time zone (or a nearby timezone, like CET),
+it might be worthwhile to enable UTC support by hand.
+
+The default configuration can be overridden by defining one of the
+following preprocessor macro:
+
+  USE_EF_UT_TIME        includes "UT" time stamp support
+  NO_EF_UT_TIME         disables "UT" time stamp support
+
+When using MMS/MMK, you should add the appropiate symbol to the "COMMON_DEFS"
+list in vms/descrip.mms; if the command procedure is used for compiling,
+you can add the macro to the "LOCAL_ZIP" DCL symbol.
+
+14-Oct-1997 Christian Spieler
diff --git a/vms/cmdline.c b/vms/cmdline.c
new file mode 100644 (file)
index 0000000..cae91b3
--- /dev/null
@@ -0,0 +1,1010 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#define module_name VMS_ZIP_CMDLINE
+#define module_ident "02-006"
+/*
+**
+**  Facility:   ZIP
+**
+**  Module:     VMS_ZIP_CMDLINE
+**
+**  Author:     Hunter Goatley <goathunter@MadGoat.com>
+**
+**  Date:       July 30, 1993
+**
+**  Abstract:   Routines to handle a VMS CLI interface for Zip.  The CLI
+**              command line is parsed and a new argc/argv are built and
+**              returned to Zip.
+**
+**  Modified by:
+**
+**      02-006          Onno van der Linden,
+**                      Christian Spieler       07-JUL-1998 23:03
+**              Support GNU CC 2.8 on Alpha AXP (vers-num unchanged).
+**      02-006          Johnny Lee              25-JUN-1998 07:40
+**              Fixed typo (superfluous ';') (vers-num unchanged).
+**      02-006          Christian Spieler       12-SEP-1997 23:17
+**              Fixed bugs in /BEFORE and /SINCE handlers (vers-num unchanged).
+**      02-006          Christian Spieler       12-JUL-1997 02:05
+**              Complete revision of the argv strings construction.
+**              Added handling of "-P pwd", "-R", "-i@file", "-x@file" options.
+**      02-005          Patrick Ellis           09-MAY-1996 22:25
+**              Show UNIX style help screen when UNIX style options are used.
+**      02-004          Onno van der Linden,
+**                      Christian Spieler       13-APR-1996 20:05
+**              Removed /ENCRYPT=VERIFY ("-ee" option).
+**      02-003          Christian Spieler       11-FEB-1996 23:05
+**              Added handling of /EXTRAFIELDS qualifier ("-X" option).
+**      02-002          Christian Spieler       09-JAN-1996 22:25
+**              Added "#include crypt.h", corrected typo.
+**      02-001          Christian Spieler       04-DEC-1995 16:00
+**              Fixed compilation in DEC CC's ANSI mode.
+**      02-000          Christian Spieler       10-OCT-1995 17:54
+**              Modified for Zip v2.1, added several new options.
+**      01-000          Hunter Goatley          30-JUL-1993 07:54
+**              Original version (for Zip v1.9p1).
+**
+*/
+
+\f
+#if defined(__DECC) || defined(__GNUC__)
+#pragma module module_name module_ident
+#else
+#module module_name module_ident
+#endif
+
+#include "zip.h"
+#ifndef TEST
+#include "crypt.h"      /* for VMSCLI_help() */
+#include "revision.h"   /* for VMSCLI_help() */
+#endif /* !TEST */
+
+#include <ssdef.h>
+#include <descrip.h>
+#include <climsgdef.h>
+#include <clidef.h>
+#include <lib$routines.h>
+#include <ots$routines.h>
+#include <str$routines.h>
+
+#ifndef CLI$_COMMA
+globalvalue CLI$_COMMA;
+#endif
+
+/*
+**  "Macro" to initialize a dynamic string descriptor.
+*/
+#define init_dyndesc(dsc) {\
+        dsc.dsc$w_length = 0;\
+        dsc.dsc$b_dtype = DSC$K_DTYPE_T;\
+        dsc.dsc$b_class = DSC$K_CLASS_D;\
+        dsc.dsc$a_pointer = NULL;}
+
+/*
+**  Memory allocation step for argv string buffer.
+*/
+#define ARGBSIZE_UNIT 256
+
+/*
+**  Memory reallocation macro for argv string buffer.
+*/
+#define CHECK_BUFFER_ALLOCATION(buf, reserved, requested) { \
+    if ((requested) > (reserved)) { \
+        char *save_buf = (buf); \
+        (reserved) += ARGBSIZE_UNIT; \
+        if (((buf) = (char *) realloc((buf), (reserved))) == NULL) { \
+            if (save_buf != NULL) free(save_buf); \
+            return (SS$_INSFMEM); \
+        } \
+    } \
+}
+
+/*
+**  Define descriptors for all of the CLI parameters and qualifiers.
+*/
+$DESCRIPTOR(cli_delete,         "DELETE");              /* -d */
+$DESCRIPTOR(cli_freshen,        "FRESHEN");             /* -f */
+$DESCRIPTOR(cli_move,           "MOVE");                /* -m */
+$DESCRIPTOR(cli_update,         "UPDATE");              /* -u */
+$DESCRIPTOR(cli_exclude,        "EXCLUDE");             /* -x */
+$DESCRIPTOR(cli_include,        "INCLUDE");             /* -i */
+$DESCRIPTOR(cli_exlist,         "EXLIST");              /* -x@ */
+$DESCRIPTOR(cli_inlist,         "INLIST");              /* -i@ */
+$DESCRIPTOR(cli_adjust,         "ADJUST_OFFSETS");      /* -A */
+$DESCRIPTOR(cli_append,         "APPEND");              /* -g */
+$DESCRIPTOR(cli_batch,          "BATCH");               /* -@ */
+$DESCRIPTOR(cli_before,         "BEFORE");              /* -tt */
+$DESCRIPTOR(cli_comments,       "COMMENTS");            /* -c,-z */
+$DESCRIPTOR(cli_comment_zipfile,"COMMENTS.ZIP_FILE");   /* -z */
+$DESCRIPTOR(cli_comment_files,  "COMMENTS.FILES");      /* -c */
+$DESCRIPTOR(cli_dirnames,       "DIRNAMES");            /* -D */
+$DESCRIPTOR(cli_encrypt,        "ENCRYPT");             /* -e,-P */
+$DESCRIPTOR(cli_extra_fields,   "EXTRA_FIELDS");        /* -X */
+$DESCRIPTOR(cli_fix_archive,    "FIX_ARCHIVE");         /* -F[F] */
+$DESCRIPTOR(cli_fix_normal,     "FIX_ARCHIVE.NORMAL");  /* -F */
+$DESCRIPTOR(cli_fix_full,       "FIX_ARCHIVE.FULL");    /* -FF */
+$DESCRIPTOR(cli_full_path,      "FULL_PATH");           /* -p */
+$DESCRIPTOR(cli_help,           "HELP");                /* -h */
+$DESCRIPTOR(cli_junk,           "JUNK");                /* -j */
+$DESCRIPTOR(cli_keep_version,   "KEEP_VERSION");        /* -w */
+$DESCRIPTOR(cli_latest,         "LATEST");              /* -o */
+$DESCRIPTOR(cli_level,          "LEVEL");               /* -[0-9] */
+$DESCRIPTOR(cli_license,        "LICENSE");             /* -L */
+$DESCRIPTOR(cli_pkzip,          "PKZIP");               /* -k */
+$DESCRIPTOR(cli_quiet,          "QUIET");               /* -q */
+$DESCRIPTOR(cli_recurse,        "RECURSE");             /* -r,-R */
+$DESCRIPTOR(cli_recurse_path,   "RECURSE.PATH");        /* -r */
+$DESCRIPTOR(cli_recurse_fnames, "RECURSE.FILENAMES");   /* -R */
+$DESCRIPTOR(cli_since,          "SINCE");               /* -t */
+$DESCRIPTOR(cli_store_types,    "STORE_TYPES");         /* -n */
+$DESCRIPTOR(cli_temp_path,      "TEMP_PATH");           /* -b */
+$DESCRIPTOR(cli_test,           "TEST");                /* -T */
+$DESCRIPTOR(cli_translate_eol,  "TRANSLATE_EOL");       /* -l[l] */
+$DESCRIPTOR(cli_transl_eol_lf,  "TRANSLATE_EOL.LF");    /* -l */
+$DESCRIPTOR(cli_transl_eol_crlf,"TRANSLATE_EOL.CRLF");  /* -ll */
+$DESCRIPTOR(cli_unsfx,          "UNSFX");               /* -J */
+$DESCRIPTOR(cli_verbose,        "VERBOSE");             /* -v */
+$DESCRIPTOR(cli_verbose_more,   "VERBOSE.MORE");        /* -vv */
+$DESCRIPTOR(cli_verbose_debug,  "VERBOSE.DEBUG");       /* -vvv */
+$DESCRIPTOR(cli_vms,            "VMS");                 /* -V */
+$DESCRIPTOR(cli_vms_all,        "VMS.ALL");             /* -VV */
+
+$DESCRIPTOR(cli_yyz,            "YYZ_ZIP");
+
+$DESCRIPTOR(cli_zipfile,        "ZIPFILE");
+$DESCRIPTOR(cli_infile,         "INFILE");
+$DESCRIPTOR(zip_command,        "zip ");
+
+static int show_VMSCLI_help;
+
+#if (defined(__GNUC__) && !defined(zip_clitable))
+#  define zip_clitable ZIP_CLITABLE
+#endif
+#if defined(__DECC) || defined(__GNUC__)
+extern void *zip_clitable;
+#else
+globalref void *zip_clitable;
+#endif
+
+/* extern unsigned long LIB$GET_INPUT(void), LIB$SIG_TO_RET(void); */
+
+#ifndef __STARLET_LOADED
+#ifndef sys$bintim
+#  define sys$bintim SYS$BINTIM
+#endif
+#ifndef sys$numtim
+#  define sys$numtim SYS$NUMTIM
+#endif
+extern int sys$bintim ();
+extern int sys$numtim ();
+#endif /* !__STARLET_LOADED */
+#ifndef cli$dcl_parse
+#  define cli$dcl_parse CLI$DCL_PARSE
+#endif
+#ifndef cli$present
+#  define cli$present CLI$PRESENT
+#endif
+#ifndef cli$get_value
+#  define cli$get_value CLI$GET_VALUE
+#endif
+extern unsigned long cli$dcl_parse ();
+extern unsigned long cli$present ();
+extern unsigned long cli$get_value ();
+
+unsigned long vms_zip_cmdline (int *, char ***);
+static unsigned long get_list (struct dsc$descriptor_s *,
+                               struct dsc$descriptor_d *, int,
+                               char **, unsigned long *, unsigned long *);
+static unsigned long get_time (struct dsc$descriptor_s *qual, char *timearg);
+static unsigned long check_cli (struct dsc$descriptor_s *);
+
+\f
+#ifdef TEST
+int
+main(int argc, char **argv)
+{
+    return (vms_zip_cmdline(&argc, &argv));
+}
+#endif /* TEST */
+
+\f
+unsigned long
+vms_zip_cmdline (int *argc_p, char ***argv_p)
+{
+/*
+**  Routine:    vms_zip_cmdline
+**
+**  Function:
+**
+**      Parse the DCL command line and create a fake argv array to be
+**      handed off to Zip.
+**
+**      NOTE: the argv[] is built as we go, so all the parameters are
+**      checked in the appropriate order!!
+**
+**  Formal parameters:
+**
+**      argc_p          - Address of int to receive the new argc
+**      argv_p          - Address of char ** to receive the argv address
+**
+**  Calling sequence:
+**
+**      status = vms_zip_cmdline (&argc, &argv);
+**
+**  Returns:
+**
+**      SS$_NORMAL      - Success.
+**      SS$_INSFMEM     - A malloc() or realloc() failed
+**      SS$_ABORT       - Bad time value
+**
+*/
+    register unsigned long status;
+    char options[48];
+    char *the_cmd_line;                 /* buffer for argv strings */
+    unsigned long cmdl_size;            /* allocated size of buffer */
+    unsigned long cmdl_len;             /* used size of buffer */
+    char *ptr;
+    int  x, len;
+
+    int new_argc;
+    char **new_argv;
+
+    struct dsc$descriptor_d work_str;
+    struct dsc$descriptor_d foreign_cmdline;
+
+    init_dyndesc(work_str);
+    init_dyndesc(foreign_cmdline);
+
+    /*
+    **  See if the program was invoked by the CLI (SET COMMAND) or by
+    **  a foreign command definition.  Check for /YYZ_ZIP, which is a
+    **  valid default qualifier solely for this test.
+    */
+    show_VMSCLI_help = TRUE;
+    status = check_cli(&cli_yyz);
+    if (!(status & 1)) {
+        lib$get_foreign(&foreign_cmdline);
+        /*
+        **  If nothing was returned or the first character is a "-", then
+        **  assume it's a UNIX-style command and return.
+        */
+        if (foreign_cmdline.dsc$w_length == 0)
+            return (SS$_NORMAL);
+        if ((*(foreign_cmdline.dsc$a_pointer) == '-') ||
+            ((foreign_cmdline.dsc$w_length > 1) &&
+             (*(foreign_cmdline.dsc$a_pointer) == '"') &&
+             (*(foreign_cmdline.dsc$a_pointer + 1) == '-'))) {
+            show_VMSCLI_help = FALSE;
+            return (SS$_NORMAL);
+        }
+
+        str$concat(&work_str, &zip_command, &foreign_cmdline);
+        status = cli$dcl_parse(&work_str, &zip_clitable, lib$get_input,
+                        lib$get_input, 0);
+        if (!(status & 1)) return (status);
+    }
+
+    /*
+    **  There's always going to be a new_argv[] because of the image name.
+    */
+    if ((the_cmd_line = (char *) malloc(cmdl_size = ARGBSIZE_UNIT)) == NULL)
+        return (SS$_INSFMEM);
+
+    strcpy(the_cmd_line, "zip");
+    cmdl_len = sizeof("zip");
+
+    /*
+    **  First, check to see if any of the regular options were specified.
+    */
+
+    options[0] = '-';
+    ptr = &options[1];          /* Point to temporary buffer */
+
+    /*
+    **  Delete the specified files from the zip file?
+    */
+    status = cli$present(&cli_delete);
+    if (status & 1)
+        *ptr++ = 'd';
+
+    /*
+    **  Freshen (only changed files).
+    */
+    status = cli$present(&cli_freshen);
+    if (status & 1)
+        *ptr++ = 'f';
+
+    /*
+    **  Delete the files once they've been added to the zip file.
+    */
+    status = cli$present(&cli_move);
+    if (status & 1)
+        *ptr++ = 'm';
+
+    /*
+    **  Add changed and new files.
+    */
+    status = cli$present(&cli_update);
+    if (status & 1)
+        *ptr++ = 'u';
+
+    /*
+    **  Check for the compression level (-0 through -9).
+    */
+    status = cli$present(&cli_level);
+    if (status & 1) {
+
+        unsigned long binval;
+
+        status = cli$get_value(&cli_level, &work_str);
+        status = ots$cvt_tu_l(&work_str, &binval);
+        if (!(status & 1) || (binval > 9)) {
+           return (SS$_ABORT);
+        }
+        *ptr++ = binval + '0';
+    }
+
+    /*
+    **  Adjust offsets of zip archive entries.
+    */
+    status = cli$present(&cli_adjust);
+    if (status & 1)
+        *ptr++ = 'A';
+
+    /*
+    **  Add comments?
+    */
+    status = cli$present(&cli_comments);
+    if (status & 1) {
+/*        while ((status = cli$get_value(&cli_comments, &work_str)) & 1) {
+            if (strncmp(work_str.dsc$a_pointer,"ZIP",3) == 0)
+                *ptr++ = 'z';
+            if (strncmp(work_str.dsc$a_pointer,"FIL",3) == 0)
+                *ptr++ = 'c';
+        } */
+        if ((status = cli$present(&cli_comment_zipfile)) & 1)
+            *ptr++ = 'z';
+        if ((status = cli$present(&cli_comment_files)) & 1)
+            *ptr++ = 'c';
+    }
+
+    /*
+    **  Do not add/modify directory entries.
+    */
+    status = cli$present(&cli_dirnames);
+    if (!(status & 1))
+        *ptr++ = 'D';
+
+    /*
+    **  Encrypt?
+    */
+    status = cli$present(&cli_encrypt);
+    if (status & 1)
+        if ((status = cli$get_value(&cli_encrypt, &work_str)) & 1) {
+            x = cmdl_len;
+            cmdl_len += work_str.dsc$w_length + 4;
+            CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
+            strcpy(&the_cmd_line[x], "-P");
+            strncpy(&the_cmd_line[x+3], work_str.dsc$a_pointer,
+                    work_str.dsc$w_length);
+            the_cmd_line[cmdl_len-1] = '\0';
+        } else {
+            *ptr++ = 'e';
+        }
+
+    /*
+    **  Fix the zip archive structure.
+    */
+    status = cli$present(&cli_fix_archive);
+    if (status & 1) {
+        *ptr++ = 'F';
+        if ((status = cli$present(&cli_fix_full)) & 1) {
+            *ptr++ = 'F';
+        }
+    }
+
+    /*
+    **  Append (allow growing of existing zip file).
+    */
+    status = cli$present(&cli_append);
+    if (status & 1)
+        *ptr++ = 'g';
+
+    /*
+    **  Show the help.
+    */
+    status = cli$present(&cli_help);
+    if (status & 1)
+        *ptr++ = 'h';
+
+    /*
+    **  Junk path names (directory specs).
+    */
+    status = cli$present(&cli_junk);
+    if (status & 1)
+        *ptr++ = 'j';
+
+    /*
+    **  Simulate zip file made by PKZIP.
+    */
+    status = cli$present(&cli_pkzip);
+    if (status & 1)
+        *ptr++ = 'k';
+
+    /*
+    **  Translate end-of-line.
+    */
+    status = cli$present(&cli_translate_eol);
+    if (status & 1) {
+        *ptr++ = 'l';
+        if ((status = cli$present(&cli_transl_eol_crlf)) & 1) {
+            *ptr++ = 'l';
+        }
+    }
+
+    /*
+    **  Show the software license.
+    */
+    status = cli$present(&cli_license);
+    if (status & 1)
+        *ptr++ = 'L';
+
+    /*
+    **  Set zip file time to time of latest file in it.
+    */
+    status = cli$present(&cli_latest);
+    if (status & 1)
+        *ptr++ = 'o';
+
+    /*
+    **  Store full path (default).
+    */
+    status = cli$present(&cli_full_path);
+    if (status == CLI$_PRESENT)
+        *ptr++ = 'p';
+    else if (status == CLI$_NEGATED)
+        *ptr++ = 'j';
+
+    /*
+    **  Junk Zipfile prefix (SFX stub etc.).
+    */
+    status = cli$present(&cli_unsfx);
+    if (status & 1)
+        *ptr++ = 'J';
+
+    /*
+    **  Recurse through subdirectories.
+    */
+    status = cli$present(&cli_recurse);
+    if (status & 1) {
+        if ((status = cli$present(&cli_recurse_fnames)) & 1)
+            *ptr++ = 'R';
+        else
+            *ptr++ = 'r';
+    }
+
+    /*
+    **  Be verbose.
+    */
+    status = cli$present(&cli_verbose);
+    if (status & 1) {
+        *ptr++ = 'v';
+        if ((status = cli$present(&cli_verbose_more)) & 1)
+            *ptr++ = 'v';
+        if ((status = cli$present(&cli_verbose_debug)) & 1) {
+            *ptr++ = 'v';
+            *ptr++ = 'v';
+        }
+    }
+
+    /*
+    **  Quiet mode.
+    **  (Quiet mode is processed after verbose, because a "-v" modifier
+    **  resets "noisy" to 1.)
+    */
+    status = cli$present(&cli_quiet);
+    if (status & 1)
+        *ptr++ = 'q';
+
+    /*
+    **  Suppress creation of any extra field.
+    */
+    status = cli$present(&cli_extra_fields);
+    if (!(status & 1))
+        *ptr++ = 'X';
+
+    /*
+    **  Save the VMS file attributes (and all allocated blocks?).
+    */
+    status = cli$present(&cli_vms);
+    if (status & 1) {
+        /* /VMS */
+        *ptr++ = 'V';
+        if ((status = cli$present(&cli_vms_all)) & 1) {
+            /* /VMS = ALL */
+            *ptr++ = 'V';
+        }
+    }
+
+    /*
+    **  Keep the VMS version number as part of the file name when stored.
+    */
+    status = cli$present(&cli_keep_version);
+    if (status & 1)
+        *ptr++ = 'w';
+
+    /*
+    **  `Batch' processing: read filenames to archive from stdin
+    **  or the specified file.
+    */
+    status = cli$present(&cli_batch);
+    if (status & 1) {
+        status = cli$get_value(&cli_batch, &work_str);
+        if (status & 1) {
+            work_str.dsc$a_pointer[work_str.dsc$w_length] = '\0';
+            if ((stdin = freopen(work_str.dsc$a_pointer, "r", stdin)) == NULL)
+            {
+                sprintf(errbuf, "could not open list file: %s",
+                        work_str.dsc$a_pointer);
+                ziperr(ZE_PARMS, errbuf);
+            }
+        }
+        *ptr++ = '@';
+    }
+
+    /*
+    **  Now copy the final options string to the_cmd_line.
+    */
+    len = ptr - &options[0];
+    if (len > 1) {
+        options[len] = '\0';
+        x = cmdl_len;
+        cmdl_len += len + 1;
+        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
+        strcpy(&the_cmd_line[x], options);
+    }
+
+    /*
+    **
+    **  OK.  We've done all the regular options, so check for -b (temporary
+    **  file path), -t (exclude before time), -n (special suffixes), zipfile,
+    **  files to zip, and exclude list.
+    **
+    */
+    status = cli$present(&cli_temp_path);
+    if (status & 1) {
+        status = cli$get_value(&cli_temp_path, &work_str);
+        x = cmdl_len;
+        cmdl_len += work_str.dsc$w_length + 4;
+        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
+        strcpy(&the_cmd_line[x], "-b");
+        strncpy(&the_cmd_line[x+3], work_str.dsc$a_pointer,
+                work_str.dsc$w_length);
+        the_cmd_line[cmdl_len-1] = '\0';
+    }
+
+    /*
+    **  Handle "-t mmddyyyy".
+    */
+    status = cli$present(&cli_since);
+    if (status & 1) {
+        char since_time[9];
+
+        status = get_time(&cli_since, &since_time[0]);
+        if (!(status & 1)) return (status);
+
+        /*
+        **  Now let's add the option "-t mmddyyyy" to the new command line.
+        */
+        x = cmdl_len;
+        cmdl_len += (3 + 9);
+        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
+        strcpy(&the_cmd_line[x], "-t");
+        strcpy(&the_cmd_line[x+3], since_time);
+    }
+
+    /*
+    **  Handle "-tt mmddyyyy".
+    */
+    status = cli$present(&cli_before);
+    if (status & 1) {
+        char before_time[9];
+
+        status = get_time(&cli_before, &before_time[0]);
+        if (!(status & 1)) return (status);
+
+        /*
+        **  Now let's add the option "-tt mmddyyyy" to the new command line.
+        */
+        x = cmdl_len;
+        cmdl_len += (4 + 9);
+        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
+        strcpy(&the_cmd_line[x], "-tt");
+        strcpy(&the_cmd_line[x+4], before_time);
+    }
+
+    /*
+    **  Handle "-n suffix:suffix:...".  (File types to store only.)
+    */
+    status = cli$present(&cli_store_types);
+    if (status & 1) {
+        x = cmdl_len;
+        cmdl_len += 3;
+        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
+        strcpy(&the_cmd_line[x], "-n");
+
+        status = get_list(&cli_store_types, &foreign_cmdline, ':',
+                          &the_cmd_line, &cmdl_size, &cmdl_len);
+        if (!(status & 1)) return (status);
+    }
+
+    /*
+    **  Now get the specified zip file name.
+    */
+    status = cli$present(&cli_zipfile);
+    if (status & 1) {
+        status = cli$get_value(&cli_zipfile, &work_str);
+
+        x = cmdl_len;
+        cmdl_len += work_str.dsc$w_length + 1;
+        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
+        strncpy(&the_cmd_line[x], work_str.dsc$a_pointer,
+                work_str.dsc$w_length);
+        the_cmd_line[cmdl_len-1] = '\0';
+
+    }
+
+    /*
+    **  Run through the list of input files.
+    */
+    status = cli$present(&cli_infile);
+    if (status & 1) {
+        status = get_list(&cli_infile, &foreign_cmdline, '\0',
+                          &the_cmd_line, &cmdl_size, &cmdl_len);
+        if (!(status & 1)) return (status);
+    }
+
+    /*
+    **  List file containing exclude patterns present? ("-x@exclude.lst")
+    */
+    status = cli$present(&cli_exlist);
+    if (status & 1) {
+        status = cli$get_value(&cli_exlist, &work_str);
+        x = cmdl_len;
+        cmdl_len += work_str.dsc$w_length + 4;
+        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
+        strncpy(&the_cmd_line[x], "-x@", 3);
+        strncpy(&the_cmd_line[x+3], work_str.dsc$a_pointer,
+                work_str.dsc$w_length);
+        the_cmd_line[cmdl_len-1] = '\0';
+    }
+
+    /*
+    **  Any files to exclude? ("-x file file")
+    */
+    status = cli$present(&cli_exclude);
+    if (status & 1) {
+        x = cmdl_len;
+        cmdl_len += 3;
+        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
+        strcpy(&the_cmd_line[x], "-x");
+
+        status = get_list(&cli_exclude, &foreign_cmdline, '\0',
+                          &the_cmd_line, &cmdl_size, &cmdl_len);
+        if (!(status & 1)) return (status);
+    }
+
+    /*
+    **  List file containing include patterns present? ("-x@exclude.lst")
+    */
+    status = cli$present(&cli_inlist);
+    if (status & 1) {
+        status = cli$get_value(&cli_inlist, &work_str);
+        x = cmdl_len;
+        cmdl_len += work_str.dsc$w_length + 4;
+        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
+        strncpy(&the_cmd_line[x], "-i@", 3);
+        strncpy(&the_cmd_line[x+3], work_str.dsc$a_pointer,
+                work_str.dsc$w_length);
+        the_cmd_line[cmdl_len-1] = '\0';
+    }
+
+    /*
+    **  Any files to include? ("-i file file")
+    */
+    status = cli$present(&cli_include);
+    if (status & 1) {
+        x = cmdl_len;
+        cmdl_len += 3;
+        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
+        strcpy(&the_cmd_line[x], "-i");
+
+        status = get_list(&cli_exclude, &foreign_cmdline, '\0',
+                          &the_cmd_line, &cmdl_size, &cmdl_len);
+        if (!(status & 1)) return (status);
+    }
+
+
+    /*
+    **  We have finished collecting the strings for the argv vector,
+    **  release unused space.
+    */
+    if ((the_cmd_line = (char *) realloc(the_cmd_line, cmdl_len)) == NULL)
+        return (SS$_INSFMEM);
+
+    /*
+    **  Now that we've built our new UNIX-like command line, count the
+    **  number of args and build an argv array.
+    */
+    for (new_argc = 0, x = 0; x < cmdl_len; x++)
+        if (the_cmd_line[x] == '\0')
+            new_argc++;
+
+    /*
+    **  Allocate memory for the new argv[].  The last element of argv[]
+    **  is supposed to be NULL, so allocate enough for new_argc+1.
+    */
+    if ((new_argv = (char **) calloc(new_argc+1, sizeof(char *))) == NULL)
+        return (SS$_INSFMEM);
+
+    /*
+    **  For each option, store the address in new_argv[] and convert the
+    **  separating blanks to nulls so each argv[] string is terminated.
+    */
+    for (ptr = the_cmd_line, x = 0; x < new_argc; x++) {
+        new_argv[x] = ptr;
+        ptr += strlen(ptr) + 1;
+    }
+    new_argv[new_argc] = NULL;
+
+#if defined(TEST) || defined(DEBUG)
+    printf("new_argc    = %d\n", new_argc);
+    for (x = 0; x < new_argc; x++)
+        printf("new_argv[%d] = %s\n", x, new_argv[x]);
+#endif /* TEST || DEBUG */
+
+    /*
+    **  All finished.  Return the new argc and argv[] addresses to Zip.
+    */
+    *argc_p = new_argc;
+    *argv_p = new_argv;
+
+    return (SS$_NORMAL);
+}
+
+
+\f
+static unsigned long
+get_list (struct dsc$descriptor_s *qual, struct dsc$descriptor_d *rawtail,
+          int delim, char **p_str, unsigned long *p_size, unsigned long *p_end)
+{
+/*
+**  Routine:    get_list
+**
+**  Function:   This routine runs through a comma-separated CLI list
+**              and copies the strings to the argv buffer.  The
+**              specified separation character is used to separate
+**              the strings in the argv buffer.
+**
+**              All unquoted strings are converted to lower-case.
+**
+**  Formal parameters:
+**
+**      qual    - Address of descriptor for the qualifier name
+**      rawtail - Address of descriptor for the full command line tail
+**      delim   - Character to use to separate the list items
+**      p_str   - Address of pointer pointing to output buffer (argv strings)
+**      p_size  - Address of number containing allocated size for output string
+**      p_end   - Address of number containing used length in output buf
+**
+*/
+
+    register unsigned long status;
+    struct dsc$descriptor_d work_str;
+
+    init_dyndesc(work_str);
+
+    status = cli$present(qual);
+    if (status & 1) {
+
+        unsigned long len, old_len;
+        long ind, sind;
+        int keep_case;
+        char *src, *dst; int x;
+
+        /*
+        **  Just in case the string doesn't exist yet, though it does.
+        */
+        if (*p_str == NULL) {
+            *p_size = ARGBSIZE_UNIT;
+            if ((*p_str = (char *) malloc(*p_size)) == NULL)
+                return (SS$_INSFMEM);
+            len = 0;
+        } else {
+            len = *p_end;
+        }
+
+        while ((status = cli$get_value(qual, &work_str)) & 1) {
+            old_len = len;
+            len += work_str.dsc$w_length + 1;
+            CHECK_BUFFER_ALLOCATION(*p_str, *p_size, len)
+
+            /*
+            **  Look for the filename in the original foreign command
+            **  line to see if it was originally quoted.  If so, then
+            **  don't convert it to lowercase.
+            */
+            keep_case = FALSE;
+            str$find_first_substring(rawtail, &ind, &sind, &work_str);
+            if ((ind > 1 && *(rawtail->dsc$a_pointer + ind - 2) == '"') ||
+                (ind == 0))
+                keep_case = TRUE;
+
+            /*
+            **  Copy the string to the buffer, converting to lowercase.
+            */
+            src = work_str.dsc$a_pointer;
+            dst = *p_str+old_len;
+            for (x = 0; x < work_str.dsc$w_length; x++) {
+                if (!keep_case && ((*src >= 'A') && (*src <= 'Z')))
+                    *dst++ = *src++ + 32;
+                else
+                    *dst++ = *src++;
+            }
+            if (status == CLI$_COMMA)
+                (*p_str)[len-1] = (char)delim;
+            else
+                (*p_str)[len-1] = '\0';
+        }
+        *p_end = len;
+    }
+
+    return (SS$_NORMAL);
+
+}
+
+\f
+static unsigned long
+get_time (struct dsc$descriptor_s *qual, char *timearg)
+{
+/*
+**  Routine:    get_time
+**
+**  Function:   This routine reads the argument string of the qualifier
+**              "qual" that should be a VMS syntax date-time string.  The
+**              date-time string is converted into the standard format
+**              "mmddyyyy", specifying an absolute date.  The converted
+**              string is written into the 9 bytes wide buffer "timearg".
+**
+**  Formal parameters:
+**
+**      qual    - Address of descriptor for the qualifier name
+**      timearg - Address of a buffer carrying the 8-char time string returned
+**
+*/
+
+    register unsigned long status;
+    struct dsc$descriptor_d time_str;
+    struct quadword {
+        long high;
+        long low;
+    } bintimbuf = {0,0};
+#ifdef __DECC
+#pragma member_alignment save
+#pragma nomember_alignment
+#endif  /* __DECC */
+    struct tim {
+        short year;
+        short month;
+        short day;
+        short hour;
+        short minute;
+        short second;
+        short hundred;
+    } numtimbuf;
+#ifdef __DECC
+#pragma member_alignment restore
+#endif
+
+    init_dyndesc(time_str);
+
+    status = cli$get_value(qual, &time_str);
+    /*
+    **  If a date is given, convert it to 64-bit binary.
+    */
+    if (time_str.dsc$w_length) {
+        status = sys$bintim(&time_str, &bintimbuf);
+        if (!(status & 1)) return (status);
+        str$free1_dx(&time_str);
+    }
+    /*
+    **  Now call $NUMTIM to get the month, day, and year.
+    */
+    status = sys$numtim(&numtimbuf, (bintimbuf.low ? &bintimbuf : NULL));
+    /*
+    **  Write the "mmddyyyy" string to the return buffer.
+    */
+    if (!(status & 1)) {
+        *timearg = '\0';
+    } else {
+        sprintf(timearg, "%02d%02d%04d", numtimbuf.month,
+                numtimbuf.day, numtimbuf.year);
+    }
+    return (status);
+}
+
+\f
+static unsigned long
+check_cli (struct dsc$descriptor_s *qual)
+{
+/*
+**  Routine:    check_cli
+**
+**  Function:   Check to see if a CLD was used to invoke the program.
+**
+**  Formal parameters:
+**
+**      qual    - Address of descriptor for qualifier name to check.
+**
+*/
+    lib$establish(lib$sig_to_ret);      /* Establish condition handler */
+    return (cli$present(qual));         /* Just see if something was given */
+}
+
+\f
+#ifndef TEST
+
+void VMSCLI_help(void)  /* VMSCLI version */
+/* Print help (along with license info) to stdout. */
+{
+  extent i;             /* counter for help array */
+
+  /* help array */
+  static char *text[] = {
+"Zip %s (%s). Usage: zip==\"$disk:[dir]zip.exe\"",
+"zip zipfile[.zip] [list] [/EXCL=(xlist)] /options /modifiers",
+"  The default action is to add or replace zipfile entries from list, except",
+"  those in xlist. The include file list may contain the special name - to",
+"  compress standard input.  If both zipfile and list are omitted, zip",
+"  compresses stdin to stdout.",
+"  Type zip -h for Unix style flags.",
+"  Major options include:",
+"    /FRESHEN, /UPDATE, /DELETE, /[NO]MOVE, /COMMENTS[={ZIP_FILE|FILES}],",
+"    /LATEST, /TEST, /ADJUST_OFFSETS, /FIX_ARCHIVE[=FULL], /UNSFX",
+"  Modifiers include:",
+"    /EXCLUDE=(file list), /INCLUDE=(file list), /SINCE=\"creation time\",",
+#if CRYPT
+"\
+    /QUIET,/VERBOSE[=MORE],/[NO]RECURSE,/[NO]DIRNAMES,/JUNK,/ENCRYPT[=\"pwd\"],\
+",
+#else /* !CRYPT */
+"    /QUIET, /VERBOSE[=MORE], /[NO]RECURSE, /[NO]DIRNAMES, /JUNK,",
+#endif /* ?CRYPT */
+"    /[NO]KEEP_VERSION, /[NO]VMS, /[NO]PKZIP, /TRANSLATE_EOL[={LF|CRLF}],",
+"    /[NO]EXTRA_FIELDS /LEVEL=[0-9], /TEMP_PATH=directory, /BATCH[=list file]"
+  };
+
+  if (!show_VMSCLI_help) {
+     help();
+     return;
+  }
+
+  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
+  {
+    printf(copyright[i], "zip");
+    putchar('\n');
+  }
+  for (i = 0; i < sizeof(text)/sizeof(char *); i++)
+  {
+    printf(text[i], VERSION, REVDATE);
+    putchar('\n');
+  }
+} /* end function VMSCLI_help() */
+
+#endif /* !TEST */
diff --git a/vms/cvthelp.tpu b/vms/cvthelp.tpu
new file mode 100644 (file)
index 0000000..2324d60
--- /dev/null
@@ -0,0 +1,176 @@
+!       TITLE   CVTHELP.TPU
+!       IDENT   01-000
+!
+!++
+! Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+!
+! See the accompanying file LICENSE, version 1999-Oct-05 or later
+! (the contents of which are also included in zip.h) for terms of use.
+! If, for some reason, both of these files are missing, the Info-ZIP license
+! also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+!
+!++
+!
+!  Program:     CVTHELP.TPU
+!
+!  Author:      Hunter Goatley
+!
+!  Date:        January 12, 1992
+!
+!  Purpose:     Convert .HELP files to RUNOFF .RNH files.  Substitutes
+!               RUNOFF commands for tags imbedded in the .HELP file.
+!
+!  Calling sequence:
+!
+!       $ EDIT/TPU/NOJOURNAL/NODISPLAY/COMMAND=CVTHELP file.HELP
+!
+!  Modified by:
+!
+!       01-000          Hunter Goatley           12-JAN-1992 15:15
+!               Original version.
+!
+!--
+Procedure eve_convert_help
+Local   temp
+        ,x
+        ;
+
+   qualifier_level := 0;
+   hg$substitute_topic(current_buffer, "<MAIN>", ".indent-3", "1");
+   hg$substitute_topic(current_buffer, "<QUALIFIER>", ".sk;.indent-3", "");
+   hg$substitute_topic(current_buffer, "<TOPIC>", ".indent-3", "2");
+   hg$substitute_topic(current_buffer, "<SUBTOPIC>", ".indent-3", "3");
+   hg$substitute_topic(current_buffer, "<SUBSUBTOPIC>", ".indent-3", "4");
+   hg$substitute_comment(current_buffer,"<QUALIFIERS>",".indent-3;2 Qualifiers");
+   hg$substitute_comment(current_buffer,"<PARAMETER>",".indent-2");
+   hg$substitute_comment(current_buffer,"<PTEXT>",".lm+3");
+   hg$substitute_comment(current_buffer,"<TXETP>",".lm-3");
+   hg$substitute_comment(current_buffer,"<ETEXT>",".lm+4");
+   hg$substitute_comment(current_buffer,"<TXETE>",".lm-4");
+   hg$substitute_comment(current_buffer,"<INIT>",".noflags;.lm3;.rm70");
+   hg$substitute_comment(current_buffer,"<LITERAL>",".lm+4;.literal");
+   hg$substitute_comment(current_buffer,"<LARETIL>",".end literal;.lm-4");
+   hg$substitute_comment(current_buffer,"<DOT1LIST>",'.list 1,"o"');
+   hg$substitute_comment(current_buffer,"<DOT0LIST>",'.list 0,"o"');
+   hg$substitute_comment(current_buffer,"<ENTRY>",".le");
+   hg$substitute_comment(current_buffer,"<TSIL>",".end list");
+   hg$substitute_comment(current_buffer,"<CENTER>",".center");
+   hg$substitute_comment(current_buffer,"<FORMAT>",".sk;.indent2");
+   hg$substitute_comment(current_buffer,"<NOTE>",".note");
+   hg$substitute_comment(current_buffer,"<ETON>",".end note");
+   hg$substitute_comment(current_buffer, LINE_BEGIN & LINE_END,".sk");
+   hg$substitute_comment(current_buffer, LINE_BEGIN & "|", "");
+
+EndProcedure;           ! eve_convert_help
+
+Procedure hg$substitute_comment (the_buffer, target, new)
+Local   temp
+        ,save_pos
+        ,x
+        ;
+  on_error;
+  endon_error;
+
+  save_pos := mark(none);
+  position(beginning_of(the_buffer));
+  loop
+        x := search(target, forward);
+        exitif x = 0;
+        position (x);
+        erase_character(length(x));
+        copy_text(new);
+  endloop;
+
+  position(save_pos);
+
+EndProcedure;           ! hg$substitute_comment
+
+Procedure hg$substitute_topic (the_buffer, target, new, level)
+Local   temp
+        ,save_pos
+        ,x
+        ;
+  on_error;
+  endon_error;
+
+  save_pos := mark(none);
+  position(beginning_of(the_buffer));
+  loop
+        x := search(target, forward);
+        exitif x = 0;
+        position (x);
+        erase_character(length(x));
+        move_vertical(-1);
+        if (length(current_line) = 0)
+        then copy_text("|");
+        endif;
+        move_vertical(1);
+        copy_text(".!------------------------------------------------------");
+        split_line;
+        copy_text(new);
+        move_horizontal(-current_offset);
+        move_vertical(1);
+        if level <> "" then
+                copy_text(level + " ");
+!       else
+!           if qualifier_level = 0
+!           then
+!               copy_text("2 Qualifiers");
+!               split_line; split_line;
+!               copy_text(new); split_line;
+!               qualifier_level := 1;
+!           endif;
+        endif;
+        move_horizontal(-current_offset);
+        move_vertical(1);
+        if length(current_line) = 0
+        then
+            if (target = "<MAIN>") OR (target = "<TOPIC>")
+                OR (target = "<SUBTOPIC>") or (target = "<SUBSUBTOPIC>")
+            then copy_text(".br");
+            else copy_text(".sk");
+            endif;
+        endif;
+  endloop;
+
+  position(save_pos);
+
+EndProcedure;           ! hg$substitute_topic
+
+!===============================================================================
+Procedure tpu$init_procedure
+Local   temp
+        ,orig_filespec
+        ,f
+        ;
+
+   on_error
+   endon_error;
+
+ !Prompt user for information
+
+  orig_filespec := get_info(command_line, "file_name");
+  if orig_filespec = ""
+  then
+        message("No .HELP file given");
+        quit;
+  endif;
+  f := file_parse(orig_filespec, ".HELP");              !Add .LIS ending
+
+    ! Create a buffer and window for editing
+
+  main_buf := create_buffer ("MAIN",f);
+  set (eob_text, main_buf, "[End of buffer]");
+
+  position (beginning_of(main_buf));
+
+  eve_convert_help;
+
+  f := file_parse(orig_filespec,"","",NAME);
+
+  write_file (main_buf, f+".RNH");
+
+ quit;
+EndProcedure;           !TPU$INIT_PROCEDURE
+
+tpu$init_procedure;
diff --git a/vms/descrip.mms b/vms/descrip.mms
new file mode 100644 (file)
index 0000000..b44c413
--- /dev/null
@@ -0,0 +1,315 @@
+# VMS Makefile for Zip, ZipNote, ZipCloak and ZipSplit
+
+#
+#  Modified to support both AXP and VAX by Hunter Goatley, 10-SEP-1993 06:43
+#  Modified (DECC VAX, Zip 2.1) by Christian Spieler, 16-SEP-1995
+#  Modified (Addition of VMS CLI) by Christian Spieler, 10-OCT-1995
+#  Modified (fixed VAXC, changed compiler opts) by C. Spieler, 10-DEC-1995
+#  Modified (removed zipup_.obj from Zip utils) by C. Spieler, 08-JAN-1996
+#  Modified (cmdline$O depends on crypt.h) by C. Spieler, 09-JAN-1996
+#  Modified (split crypt -> crypt, ttyio) by C. Spieler, 16-JAN-1996
+#  Modified (modified VMSCLI compilation) by C. Spieler, 25-JUL-1997
+#  Modified (comment concerning online help) by C. Spieler, 14-OCT-1997
+#  Last modified (removed bits.c source file) by C. Spieler, 25-JUN-1998
+#
+#  To build Zip and the Ziputils, use one of the following commands,
+#  depending on your system:
+#
+#      $ MMS/MACRO=(__ALPHA__=1)               ! Alpha AXP, (DEC C)
+#      $ MMS/MACRO=(__DECC__=1)                ! VAX, using DEC C
+#      $ MMS/MACRO=(__FORCE_VAXC__=1)          ! VAX, prefering VAXC over DECC
+#      $ MMS/MACRO=(__VAXC__=1)                ! VAX, where VAXC is default
+#      $ MMS/MACRO=(__GNUC__=1)                ! VAX, using GNU C
+#
+#  Other MMS macros intended for use on the MMS' command line are:
+#      __DEBUG__=1                             ! compile for debugging
+#  For some discussion on the compiler switches used, see documentation
+#  in 00readme.vms.
+#
+.IFDEF __ALPHA__
+E = .AXP_EXE
+O = .AXP_OBJ
+A = .AXP_OLB
+.ELSE
+.IFDEF __DECC__
+E = .VAX_DECC_EXE
+O = .VAX_DECC_OBJ
+A = .VAX_DECC_OLB
+.ENDIF
+.IFDEF __FORCE_VAXC__
+__VAXC__ = 1
+.ENDIF
+.IFDEF __VAXC__
+E = .VAX_VAXC_EXE
+O = .VAX_VAXC_OBJ
+A = .VAX_VAXC_OLB
+.ENDIF
+.IFDEF __GNUC__
+E = .VAX_GNUC_EXE
+O = .VAX_GNUC_OBJ
+A = .VAX_GNUC_OLB
+.ENDIF
+.ENDIF
+.IFDEF O
+.ELSE
+!If EXE and OBJ extensions aren't defined, define them
+E = .EXE
+O = .OBJ
+A = .OLB
+.ENDIF
+
+!The following preprocessor macros are set to enable the VMS CLI$ interface:
+CLI_DEFS = VMSCLI,
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!! USER CUSTOMIZATION !!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! add any other optional preprocessor flags (macros) except VMSCLI to the
+! following line for a custom version (do not forget a trailing comma!!):
+COMMON_DEFS =
+!
+! WARNING: Do not use VMSCLI here!! The creation of a Zip executable
+!          utilizing the VMS CLI$ command interface is handled differently.
+!!!!!!!!!!!!!!!!!!!!!!!! END OF USER CUSTOMIZATION !!!!!!!!!!!!!!!!!!!!!!!!
+
+.IFDEF __GNUC__
+CC = gcc
+LIBS = ,GNU_CC:[000000]GCCLIB.OLB/LIB
+.ELSE
+CC = cc
+LIBS =
+.ENDIF
+
+CFLAGS = /NOLIST/INCL=(SYS$DISK:[])
+
+OPTFILE = sys$disk:[.vms]vaxcshr.opt
+
+.IFDEF __ALPHA__               !Under OpenVMS AXP, we must use /PREFIX=ALL
+CFLG_ARCH = /STANDARD=RELAX/PREFIX=ALL/ANSI_ALIAS
+OPTFILE_LIST =
+OPTIONS = $(LIBS)
+.ELSE
+.IFDEF __DECC__                        !Under DECC VAX, we must use /PREFIX=ALL
+CFLG_ARCH = /DECC/STANDARD=VAXC/PREFIX=ALL
+OPTFILE_LIST =
+OPTIONS = $(LIBS)
+.ELSE                          !VAXC, or GNU C on VAX
+.IFDEF __FORCE_VAXC__          !Select VAXC on systems where DEC C exists
+CFLG_ARCH = /VAXC
+.ELSE                          !No flag allowed/needed on a pure VAXC system
+CFLG_ARCH =
+.ENDIF
+OPTFILE_LIST = ,$(OPTFILE)
+OPTIONS = $(LIBS),$(OPTFILE)/OPT
+.ENDIF
+.ENDIF
+
+.IFDEF __DEBUG__
+CDEB = /DEBUG/NOOPTIMIZE
+LDEB = /DEBUG
+.ELSE
+CDEB =
+LDEB = /NOTRACE
+.ENDIF
+
+CFLAGS_ALL  = $(CFLG_ARCH) $(CFLAGS) $(CDEB) -
+       /def=($(COMMON_DEFS) VMS)
+CFLAGS_CLI  = $(CFLG_ARCH) $(CFLAGS) $(CDEB) -
+       /def=($(COMMON_DEFS) $(CLI_DEFS) VMS)
+CFLAGS_UTIL = $(CFLG_ARCH) $(CFLAGS) $(CDEB) -
+       /def=($(COMMON_DEFS) UTIL, VMS)
+
+LINKFLAGS = $(LDEB)
+
+
+OBJM = zip$(O), zipcli$(O)
+OBJZ = crc32$(O), crctab$(O), crypt$(O), ttyio$(O), -
+       zipfile$(O), zipup$(O), fileio$(O), globals$(O), util$(O)
+OBJV = vmszip$(O), vms$(O), vmsmunch$(O)
+OBJI = deflate$(O), trees$(O)
+OBJU = ZIPFILE=zipfile_$(O), FILEIO=fileio_$(O), globals$(O), -
+       UTIL=util_$(O), VMS=vms_$(O), vmsmunch$(O)
+OBJR = crctab$(O), CRYPT=crypt_$(O), ttyio$(O)
+OBJC = zipcloak$(O)
+OBJN = zipnote$(O)
+OBJS = zipsplit$(O)
+
+ZIPX_UNX = zip
+ZIPX_CLI = zip_cli
+OBJSZIPLIB = $(OBJZ), $(OBJI), $(OBJV)
+OBJSZIP = zip$(O), $(OBJSZIPLIB)
+OBJSCLI = ZIP=zipcli$(O), -
+       ZIP_CLITABLE=zip_cli$(O), VMS_ZIP_CMDLINE=cmdline$(O)
+ZIPHELP_UNX_RNH = [.vms]vms_zip.rnh
+ZIPHELP_CLI_RNH = [.vms]zip_cli.rnh
+
+OLBZIP = zip$(A)
+OLBCLI = zipcli$(A)
+OLBUTI = ziputils$(A)
+
+ZIP_H =        zip.h,ziperr.h,tailor.h,[.vms]osdep.h
+
+ZIPS = $(ZIPX_UNX)$(E), $(ZIPX_CLI)$(E),-
+       zipcloak$(E), zipnote$(E), zipsplit$(E)
+ZIPHELPS = $(ZIPX_UNX).hlp, $(ZIPX_CLI).hlp
+
+#
+#  Define our new suffixes list
+#
+.SUFFIXES :
+.SUFFIXES :    $(E) $(A) $(O) .C .MAR .CLD .HLP .RNH
+
+$(O)$(E) :
+       $(LINK) $(LINKFLAGS) /EXE=$(MMS$TARGET) $(MMS$SOURCE)
+
+$(O)$(A) :
+       If "''F$Search("$(MMS$TARGET)")'" .EQS. "" Then $(LIBR)/Create $(MMS$TARGET)
+       $(LIBR)$(LIBRFLAGS) $(MMS$TARGET) $(MMS$SOURCE)
+
+.CLD$(O) :
+       SET COMMAND /OBJECT=$(MMS$TARGET) $(CLDFLAGS) $(MMS$SOURCE)
+
+.c$(O) :
+       $(CC) $(CFLAGS_ALL) /OBJ=$(MMS$TARGET) $(MMS$SOURCE)
+
+.RNH.HLP :
+       runoff /out=$@ $<
+
+
+# rules for zip, zipnote, zipsplit, and VMS online help file.
+
+default :      $(ZIPS), $(ZIPHELPS)
+       @ !
+
+vmszip$(O)   : [.vms]vmszip.c
+vmsmunch$(O) : [.vms]vmsmunch.c
+vms$(O)      : [.vms]vms.c [.vms]vms_im.c [.vms]vms_pk.c [.vms]vms.h
+zipcli$(O)   : zip.c
+       $(CC) $(CFLAGS_CLI) /OBJ=$(MMS$TARGET) $<
+cmdline$(O)  : [.vms]cmdline.c $(ZIP_H) crypt.h revision.h
+       $(CC) $(CFLAGS_CLI) /OBJ=$(MMS$TARGET) $<
+zip_cli$(O)  : [.vms]zip_cli.cld
+
+
+zipfile_$(O) : zipfile.c,[.vms]vmsmunch.h,[.vms]vmsdefs.h
+       $(CC) $(CFLAGS_UTIL) /OBJECT=$(MMS$TARGET) $<
+fileio_$(O)  : fileio.c
+       $(CC) $(CFLAGS_UTIL) /OBJECT=$(MMS$TARGET) $<
+util_$(O)    : util.c
+       $(CC) $(CFLAGS_UTIL) /OBJECT=$(MMS$TARGET) $<
+crypt_$(O)   : crypt.c,crypt.h,ttyio.h
+       $(CC) $(CFLAGS_UTIL) /OBJECT=$(MMS$TARGET) $<
+vms_$(O)     : [.vms]vms.c,[.vms]vms_im.c,[.vms]vms_pk.c, -
+               [.vms]vms.h,[.vms]vmsdefs.h
+       $(CC) $(CFLAGS_UTIL) /OBJECT=$(MMS$TARGET) $<
+
+$(OBJM),zipcloak$(O),zipnote$(O),zipsplit$(O),zipup$(O) : revision.h
+
+$(OBJM),zipcloak$(O),zipup$(O),crypt$(O),ttyio$(O) : crypt.h
+
+$(OBJM),zipcloak$(O),crypt$(O),ttyio$(O) : ttyio.h
+
+zipup$(O) : [.vms]zipup.h
+
+$(OBJM), zipfile$(O), vmszip$(O), vmsmunch$(O) : [.vms]vmsmunch.h
+
+zipfile$(O), vms$(O), vmsmunch$(O) : [.vms]vmsdefs.h
+
+$(OBJM) : $(ZIP_H)
+$(OBJZ) : $(ZIP_H)
+$(OBJV) : $(ZIP_H)
+$(OBJI) : $(ZIP_H)
+$(OBJU) : $(ZIP_H)
+$(OBJR) : $(ZIP_H)
+$(OBJC) : $(ZIP_H)
+$(OBJN) : $(ZIP_H)
+$(OBJS) : $(ZIP_H)
+
+
+$(ZIPX_UNX)$(E) : $(OLBZIP)($(OBJSZIP))$(OPTFILE_LIST)
+       $(LINK)$(LINKFLAGS) /EXE=$@ -
+       $(OLBZIP)/inc=(zip,globals)/lib$(OPTIONS)
+
+$(ZIPX_CLI)$(E) : $(OLBCLI)($(OBJSCLI)),$(OLBZIP)($(OBJSZIPLIB))$(OPTFILE_LIST)
+       $(LINK)$(LINKFLAGS) /EXE=$@ -
+       $(OLBCLI)/inc=(zip)/lib, $(OLBZIP)/inc=(globals)/lib$(OPTIONS)
+
+zipcloak$(E) : $(OBJC),$(OLBUTI)($(OBJR),$(OBJU))$(OPTFILE_LIST)
+       $(LINK)$(LINKFLAGS) /EXE=$@ $<, -
+       $(OLBUTI)/inc=(globals)/lib$(OPTIONS)
+
+zipnote$(E) : $(OBJN),$(OLBUTI)($(OBJU))$(OPTFILE_LIST)
+       $(LINK)$(LINKFLAGS) /EXE=$@ $<, -
+       $(OLBUTI)/inc=(globals)/lib$(OPTIONS)
+
+zipsplit$(E) : $(OBJS),$(OLBUTI)($(OBJU))$(OPTFILE_LIST)
+       $(LINK)$(LINKFLAGS) /EXE=$@ $<, -
+       $(OLBUTI)/inc=(globals)/lib$(OPTIONS)
+
+$(OPTFILE) :
+       @ open/write tmp $(OPTFILE)
+       @ write tmp "SYS$SHARE:VAXCRTL.EXE/SHARE"
+       @ close tmp
+
+$(ZIPHELP_CLI_RNH) : [.vms]zip_cli.help
+       @ set default [.vms]
+       edit/tpu/nosection/nodisplay/command=cvthelp.tpu zip_cli.help
+       @ set default [-]
+
+$(ZIPX_UNX).hlp : $(ZIPHELP_UNX_RNH)
+       runoff /out=$@ $<
+
+$(ZIPX_CLI).hlp : $(ZIPHELP_CLI_RNH)
+
+clean.com :
+       @ open/write tmp $(MMS$TARGET)
+       @ write tmp "$!"
+       @ write tmp "$! Clean.com --    procedure to delete files. It always returns success"
+       @ write tmp "$!                 status despite any error or warnings. Also it extracts"
+       @ write tmp "$!                 filename from MMS ""module=file"" format."
+       @ write tmp "$!"
+       @ write tmp "$ on control_y then goto ctly"
+       @ write tmp "$ if p1.eqs."""" then exit 1"
+       @ write tmp "$ i = -1"
+       @ write tmp "$scan_list:"
+       @ write tmp "$  i = i+1"
+       @ write tmp "$  item = f$elem(i,"","",p1)"
+       @ write tmp "$  if item.eqs."""" then goto scan_list"
+       @ write tmp "$  if item.eqs."","" then goto done                ! End of list"
+       @ write tmp "$  item = f$edit(item,""trim"")            ! Clean of blanks"
+       @ write tmp "$  wild = f$elem(1,""="",item)"
+       @ write tmp "$  show sym wild"
+       @ write tmp "$  if wild.eqs.""="" then wild = f$elem(0,""="",item)"
+       @ write tmp "$  vers = f$parse(wild,,,""version"",""syntax_only"")"
+       @ write tmp "$  if vers.eqs."";"" then wild = wild - "";"" + "";*"""
+       @ write tmp "$scan:"
+       @ write tmp "$          f = f$search(wild)"
+       @ write tmp "$          if f.eqs."""" then goto scan_list"
+       @ write tmp "$          on error then goto err"
+       @ write tmp "$          on warning then goto warn"
+       @ write tmp "$          delete/log 'f'"
+       @ write tmp "$warn:"
+       @ write tmp "$err:"
+       @ write tmp "$          goto scan"
+       @ write tmp "$done:"
+       @ write tmp "$ctly:"
+       @ write tmp "$  exit 1"
+       @ close tmp
+
+clean : clean.com
+       @clean "$(OBJM)"
+       @clean "$(OBJZ)"
+       @clean "$(OBJI)"
+       @clean "$(OBJV)"
+       @clean "$(OBJU)"
+       @clean "$(OBJR)"
+       @clean "$(OBJN)"
+       @clean "$(OBJS)"
+       @clean "$(OBJC)"
+       @clean "$(OBJSCLI)"
+       @clean "$(OLBZIP)"
+       @clean "$(OLBCLI)"
+       @clean "$(OLBUTI)"
+       @clean "$(OPTFILE)"
+       @clean "$(ZIPS)"
+       @clean "$(ZIPHELP_CLI_RNH)"
+       @clean "$(ZIPHELPS)"
+       - delete/noconfirm/nolog clean.com;*
diff --git a/vms/link_zip.com b/vms/link_zip.com
new file mode 100755 (executable)
index 0000000..54149a3
--- /dev/null
@@ -0,0 +1,204 @@
+$ ! LINK_ZIP.COM
+$ !
+$ !     Command procedure to (re)link the VMS versions of
+$ !     Zip, ZipCloak, ZipNote, and ZipSplit
+$ !
+$ !     Command args:
+$ !     - select compiler environment: "VAXC", "DECC", "GNUC"
+$ !     - select installation of CLI interface version of zip:
+$ !       "VMSCLI" or "CLI"
+$ !     - force installation of UNIX interface version of zip
+$ !       (override LOCAL_ZIP environment): "NOVMSCLI" or "NOCLI"
+$ !
+$ on error then goto error
+$ on control_y then goto error
+$ OLD_VERIFY = f$verify(0)
+$!
+$ say := write sys$output
+$!##################### Read settings from environment ########################
+$!
+$ if f$type(LOCAL_ZIP).eqs.""
+$ then
+$       local_zip = ""
+$ else  ! Trim blanks and append comma if missing
+$       local_zip = f$edit(local_zip, "TRIM")
+$       if f$extract(f$length(local_zip)-1, 1, local_zip).nes."," then -
+                local_zip = local_zip + ","
+$ endif
+$! Check for the presence of "VMSCLI" in local_zip. If yes, we will define
+$! the foreign command for "zip" to use the executable containing the
+$! CLI interface.
+$ pos_cli = f$locate("VMSCLI",local_zip)
+$ len_local_zip = f$length(local_zip)
+$ if pos_cli.ne.len_local_zip
+$ then
+$   CLI_IS_DEFAULT = 1
+$   ! Remove "VMSCLI" macro from local_zip. The Zip executable including
+$   ! the CLI interface is now created unconditionally.
+$   local_zip = f$extract(0, pos_cli, local_zip) + -
+$               f$extract(pos_cli+7, len_local_zip-(pos_cli+7), local_zip)
+$ else
+$   CLI_IS_DEFAULT = 0
+$ endif
+$ delete/symbol/local pos_cli
+$ delete/symbol/local len_local_zip
+$!##################### Customizing section #############################
+$!
+$ zipx_unx = "zip"
+$ zipx_cli = "zip_cli"
+$!
+$ MAY_USE_DECC = 1      ! Use DEC C when its presence is detected
+$ MAY_USE_GNUC = 0      ! Do not prefer GNUC over DEC or VAX C
+$!
+$! Process command line parameters requesting optional features:
+$ arg_cnt = 1
+$ argloop:
+$  current_arg_name = "P''arg_cnt'"
+$  curr_arg = f$edit('current_arg_name',"UPCASE")
+$  IF curr_arg .eqs. "" THEN GOTO argloop_out
+$  IF curr_arg .eqs. "VAXC"
+$  THEN MAY_USE_DECC = 0
+$    MAY_USE_GNUC = 0
+$  ENDIF
+$  IF curr_arg .eqs. "DECC"
+$  THEN MAY_USE_DECC = 1
+$    MAY_USE_GNUC = 0
+$  ENDIF
+$  IF curr_arg .eqs. "GNUC"
+$  THEN MAY_USE_DECC = 0
+$    MAY_USE_GNUC = 1
+$  ENDIF
+$  IF (curr_arg .eqs. "VMSCLI") .or. (curr_arg .eqs. "CLI")
+$  THEN
+$    CLI_IS_DEFAULT = 1
+$  ENDIF
+$  IF (curr_arg .eqs. "NOVMSCLI") .or. (curr_arg .eqs. "NOCLI")
+$  THEN
+$    CLI_IS_DEFAULT = 0
+$  ENDIF
+$  arg_cnt = arg_cnt + 1
+$ GOTO argloop
+$ argloop_out:
+$!
+$ if CLI_IS_DEFAULT
+$ then
+$       ZIPEXEC = zipx_cli
+$ else
+$       ZIPEXEC = zipx_unx
+$ endif
+$!
+$!#######################################################################
+$!
+$ ! Find out current disk, directory, compiler and options
+$ !
+$ my_name = f$env("procedure")
+$ workdir = f$env("default")
+$ here = f$parse(workdir,,,"device") + f$parse(workdir,,,"directory")
+$ axp = f$getsyi("HW_MODEL").ge.1024
+$ if axp
+$ then
+$       ! Alpha AXP
+$       ARCH_NAME == "Alpha"
+$       ARCH_PREF = "AXP_"
+$       HAVE_DECC_VAX = 0
+$       USE_DECC_VAX = 0
+$       IF (f$search("SYS$DISK:[]ZIP.''ARCH_PREF'OLB").eqs."")
+$       THEN
+$         say "Cannot find any AXP object library for Zip."
+$         say "  You must keep all binary files of the object distribution"
+$         say "  in the current directory !"
+$         goto error
+$       ENDIF
+$       if MAY_USE_GNUC
+$       then say "Up to now, the GNU C ports available on OpenVMS AXP"
+$            say "contain so many nasty bugs and lack support for a number of"
+$            say "required VMS specific features."
+$            say "These design flaws make it impossible to compile Zip
+$            say "using GCC, sorry."
+$            goto error
+$       endif
+$       ARCH_CC_P = ARCH_PREF
+$       opts = ""
+$       say "Linking on AXP using DEC C"
+$ else
+$       ! VAX
+$       ARCH_NAME == "VAX"
+$       ARCH_PREF = "VAX_"
+$       ! check which object libraries are present:
+$       HAVE_DECC_VAX =(f$search("SYS$DISK:[]ZIP.''ARCH_PREF'DECC_OLB").nes."")
+$       HAVE_VAXC_VAX =(f$search("SYS$DISK:[]ZIP.''ARCH_PREF'VAXC_OLB").nes."")
+$       HAVE_GNUC_VAX =(f$search("SYS$DISK:[]ZIP.''ARCH_PREF'GNUC_OLB").nes."")
+$       IF .not.HAVE_DECC_VAX .and. .not.HAVE_VAXC_VAX .and. .not.HAVE_GNUC_VAX
+$       THEN
+$         say "Cannot find any VAX object library for Zip."
+$         say "  You must keep all binary files of the object distribution"
+$         say "  in the current directory !"
+$         goto error
+$       ENDIF
+$       IF HAVE_DECC_VAX .AND. MAY_USE_DECC
+$       THEN
+$         ! We use DECC:
+$         USE_DECC_VAX = 1
+$         ARCH_CC_P = "''ARCH_PREF'DECC_"
+$         opts = ""
+$         say "Linking on VAX using DEC C"
+$       ELSE
+$         ! We use VAXC (or GNU C):
+$         USE_DECC_VAX = 0
+$         opts = ",SYS$DISK:[.VMS]VAXCSHR.OPT/OPTIONS"
+$         if HAVE_GNUC_VAX .and. (.not.HAVE_VAXC_VAX .or. MAY_USE_GNUC)
+$         then
+$               ARCH_CC_P = "''ARCH_PREF'GNUC_"
+$               opts = ",GNU_CC:[000000]GCCLIB.OLB/LIB ''opts'"
+$               say "Linking on VAX using GNU C"
+$         else
+$               ARCH_CC_P = "''ARCH_PREF'VAXC_"
+$               say "Linking on VAX using VAX C"
+$         endif
+$       ENDIF
+$ endif
+$ LFLAGS = "/notrace"
+$ if (opts .nes. "") .and. -
+     (f$locate("VAXCSHR",f$edit(opts,"UPCASE")) .lt. f$length(opts)) .and. -
+     (f$search("[.vms]vaxcshr.opt") .eqs. "")
+$ then  create [.vms]vaxcshr.opt
+$       open/append tmp [.vms]vaxcshr.opt
+$       write tmp "SYS$SHARE:VAXCRTL.EXE/SHARE"
+$       close tmp
+$ endif
+$ set verify    ! like "echo on", eh?
+$ !
+$ !------------------------------- Zip section --------------------------------
+$ !
+$ link'LFLAGS'/exe='zipx_unx'.'ARCH_CC_P'exe -
+        zip.'ARCH_CC_P'olb;/incl=(zip,globals)/lib 'opts'
+$ !
+$ !------------------------ Zip (CLI interface) section -----------------------
+$ !
+$ link'LFLAGS'/exe='zipx_cli'.'ARCH_CC_P'exe -
+        zipcli.'ARCH_CC_P'olb;/incl=(zip)/lib, -
+        zip.'ARCH_CC_P'olb;/incl=(globals)/lib 'opts'
+$ !
+$ !-------------------------- Zip utilities section ---------------------------
+$ !
+$ link'LFLAGS'/exe=zipcloak.'ARCH_CC_P'exe zipcloak.'ARCH_CC_P'obj, -
+        ziputils.'ARCH_CC_P'olb;/incl=(globals)/lib 'opts'
+$ link'LFLAGS'/exe=zipnote.'ARCH_CC_P'exe zipnote.'ARCH_CC_P'obj, -
+        ziputils.'ARCH_CC_P'olb;/incl=(globals)/lib 'opts'
+$ link'LFLAGS'/exe=zipsplit.'ARCH_CC_P'exe zipsplit.'ARCH_CC_P'obj, -
+        ziputils.'ARCH_CC_P'olb;/incl=(globals)/lib 'opts'
+$ !
+$ !----------------------------- Symbols section ------------------------------
+$ !
+$ ! Set up symbols for the various executables.  Edit the example below,
+$ ! changing "disk:[directory]" as appropriate.
+$ !
+$ zip           == "$''here'''ZIPEXEC'.''ARCH_CC_P'exe"
+$ zipcloak      == "$''here'zipcloak.''ARCH_CC_P'exe"
+$ zipnote       == "$''here'zipnote.''ARCH_CC_P'exe"
+$ zipsplit      == "$''here'zipsplit.''ARCH_CC_P'exe"
+$ !
+$error:
+$ if here .nes. "" then set default 'here'
+$ dummy = f$verify(OLD_VERIFY)
+$ exit
diff --git a/vms/make_zip.com b/vms/make_zip.com
new file mode 100755 (executable)
index 0000000..cb7358b
--- /dev/null
@@ -0,0 +1,287 @@
+$ ! MAKE_ZIP.COM
+$ !
+$ !     "Makefile" for VMS versions of Zip, ZipCloak, ZipNote,
+$ !     and ZipSplit (stolen from Unzip)
+$ !
+$ !     Command args:
+$ !     - select compiler environment: "VAXC", "DECC", "GNUC"
+$ !     - select installation of CLI interface version of zip:
+$ !       "VMSCLI" or "CLI"
+$ !     - force installation of UNIX interface version of zip
+$ !       (override LOCAL_ZIP environment): "NOVMSCLI" or "NOCLI"
+$ !
+$ !     To define additional options, define the global symbol
+$ !     LOCAL_ZIP prior to executing MAKE_ZIP.COM, e.g.:
+$ !
+$ !             $ LOCAL_ZIP == "VMS_IM_EXTRA,"
+$ !             $ @MAKE_ZIP
+$ !
+$ !     The trailing "," may be omitted.  Valid VMS-specific options
+$ !     include VMS_PK_EXTRA and VMS_IM_EXTRA; see the INSTALL file
+$ !     for other options.
+$ !     NOTE: This command procedure does always generate both the
+$ !           "default" Zip containing the UNIX style command interface
+$ !           and the "VMSCLI" Zip containing the CLI compatible command
+$ !           interface. There is no need to add "VMSCLI" to the LOCAL_ZIP
+$ !           symbol. (The only effect of "VMSCLI" is now the selection of the
+$ !           CLI style Zip executable in the foreign command definition.)
+$ !
+$ !
+$ on error then goto error
+$ on control_y then goto error
+$ OLD_VERIFY = f$verify(0)
+$!
+$ edit := edit                  ! override customized edit commands
+$ say := write sys$output
+$!##################### Read settings from environment ########################
+$!
+$ if f$type(LOCAL_ZIP).eqs.""
+$ then
+$       local_zip = ""
+$ else  ! Trim blanks and append comma if missing
+$       local_zip = f$edit(local_zip, "TRIM")
+$       if f$extract(f$length(local_zip)-1, 1, local_zip).nes."," then -
+                local_zip = local_zip + ","
+$ endif
+$! Check for the presence of "VMSCLI" in local_zip. If yes, we will define
+$! the foreign command for "zip" to use the executable containing the
+$! CLI interface.
+$ pos_cli = f$locate("VMSCLI",local_zip)
+$ len_local_zip = f$length(local_zip)
+$ if pos_cli.ne.len_local_zip
+$ then
+$   CLI_IS_DEFAULT = 1
+$   ! Remove "VMSCLI" macro from local_zip. The Zip executable including
+$   ! the CLI interface is now created unconditionally.
+$   local_zip = f$extract(0, pos_cli, local_zip) + -
+$               f$extract(pos_cli+7, len_local_zip-(pos_cli+7), local_zip)
+$ else
+$   CLI_IS_DEFAULT = 0
+$ endif
+$ delete/symbol/local pos_cli
+$ delete/symbol/local len_local_zip
+$!##################### Customizing section #############################
+$!
+$ zipx_unx = "zip"
+$ zipx_cli = "zip_cli"
+$!
+$ MAY_USE_DECC = 1      ! Use DEC C when its presence is detected
+$ MAY_USE_GNUC = 0      ! Do not prefer GNUC over DEC or VAX C
+$!
+$! Process command line parameters requesting optional features:
+$ arg_cnt = 1
+$ argloop:
+$  current_arg_name = "P''arg_cnt'"
+$  curr_arg = f$edit('current_arg_name',"UPCASE")
+$  IF curr_arg .eqs. "" THEN GOTO argloop_out
+$  IF curr_arg .eqs. "VAXC"
+$  THEN MAY_USE_DECC = 0
+$    MAY_USE_GNUC = 0
+$  ENDIF
+$  IF curr_arg .eqs. "DECC"
+$  THEN MAY_USE_DECC = 1
+$    MAY_USE_GNUC = 0
+$  ENDIF
+$  IF curr_arg .eqs. "GNUC"
+$  THEN MAY_USE_DECC = 0
+$    MAY_USE_GNUC = 1
+$  ENDIF
+$  IF (curr_arg .eqs. "VMSCLI") .or. (curr_arg .eqs. "CLI")
+$  THEN
+$    CLI_IS_DEFAULT = 1
+$  ENDIF
+$  IF (curr_arg .eqs. "NOVMSCLI") .or. (curr_arg .eqs. "NOCLI")
+$  THEN
+$    CLI_IS_DEFAULT = 0
+$  ENDIF
+$  arg_cnt = arg_cnt + 1
+$ GOTO argloop
+$ argloop_out:
+$!
+$ if CLI_IS_DEFAULT
+$ then
+$       ZIPEXEC = zipx_cli
+$ else
+$       ZIPEXEC = zipx_unx
+$ endif
+$!
+$!#######################################################################
+$!
+$ ! Find out current disk, directory, compiler and options
+$ !
+$ my_name = f$env("procedure")
+$ workdir = f$env("default")
+$ here = f$parse(workdir,,,"device") + f$parse(workdir,,,"directory")
+$ axp = f$getsyi("HW_MODEL").ge.1024
+$ if axp
+$ then
+$       ! Alpha AXP
+$       ARCH_NAME == "Alpha"
+$       ARCH_PREF = "AXP_"
+$       HAVE_DECC_VAX = 0
+$       USE_DECC_VAX = 0
+$       HAVE_DECC_AXP = (f$search("SYS$SYSTEM:DECC$COMPILER.EXE").nes."")
+$       MAY_HAVE_GNUC = (f$trnlnm("GNU_CC_VERSION").nes."")
+$       IF (.not.HAVE_DECC_AXP .and. MAY_HAVE_GNUC) .or. (MAY_USE_GNUC)
+$       THEN say "Up to now, the GNU C ports available on OpenVMS AXP"
+$            say "contain so many nasty bugs and lack support for a number of"
+$            say "required VMS specific features."
+$            say "These design flaws make it impossible to compile Zip
+$            say "using GCC, sorry."
+$            goto error
+$       ENDIF
+$       ! We use DECC:
+$       USE_DECC_AXP = 1
+$       ARCH_CC_P = ARCH_PREF
+$       cc = "cc/standard=relax/prefix=all/ansi"
+$       defs = "''local_zip'VMS"
+$       opts = ""
+$       say "Compiling on AXP using DEC C"
+$ else
+$       ! VAX
+$       ARCH_NAME == "VAX"
+$       ARCH_PREF = "VAX_"
+$       HAVE_DECC_VAX = (f$search("SYS$SYSTEM:DECC$COMPILER.EXE").nes."")
+$       HAVE_VAXC_VAX = (f$search("SYS$SYSTEM:VAXC.EXE").nes."")
+$       MAY_HAVE_GNUC = (f$trnlnm("GNU_CC").nes."")
+$       IF HAVE_DECC_VAX .AND. MAY_USE_DECC
+$       THEN
+$         ! We use DECC:
+$         USE_DECC_VAX = 1
+$         cc = "cc/decc/standard=vaxc/prefix=all"
+$         ARCH_CC_P = "''ARCH_PREF'DECC_"
+$         defs = "''local_zip'VMS"
+$         opts = ""
+$         say "Compiling on VAX using DEC C"
+$       ELSE
+$         ! We use VAXC (or GNU C):
+$         USE_DECC_VAX = 0
+$         defs = "''local_zip'VMS"
+$         opts = ",SYS$DISK:[.VMS]VAXCSHR.OPT/OPTIONS"
+$         if (.not.HAVE_VAXC_VAX .and. MAY_HAVE_GNUC) .or. (MAY_USE_GNUC)
+$         then
+$               ARCH_CC_P = "''ARCH_PREF'GNUC_"
+$               cc = "gcc"
+$               opts = ",GNU_CC:[000000]GCCLIB.OLB/LIB ''opts'"
+$               say "Compiling on VAX using GNU C"
+$         else
+$               ARCH_CC_P = "''ARCH_PREF'VAXC_"
+$               if HAVE_DECC_VAX
+$               then
+$                   cc = "cc/vaxc"
+$               else
+$                   cc = "cc"
+$               endif
+$               say "Compiling on VAX using VAX C"
+$         endif
+$       ENDIF
+$ endif
+$ DEF_UNX = "/def=(''DEFS')"
+$ DEF_CLI = "/def=(''DEFS',VMSCLI)"
+$ DEF_UTIL = "/def=(''DEFS',UTIL)"
+$ LFLAGS = "/notrace"
+$ if (opts .nes. "") .and. -
+     (f$locate("VAXCSHR",f$edit(opts,"UPCASE")) .lt. f$length(opts)) .and. -
+     (f$search("[.vms]vaxcshr.opt") .eqs. "")
+$ then  create [.vms]vaxcshr.opt
+$       open/append tmp [.vms]vaxcshr.opt
+$       write tmp "SYS$SHARE:VAXCRTL.EXE/SHARE"
+$       close tmp
+$ endif
+$ set verify    ! like "echo on", eh?
+$ !
+$ !------------------------------- Zip section --------------------------------
+$ !
+$ runoff/out=zip.hlp [.vms]vms_zip.rnh
+$ !
+$ cc 'DEF_UNX' /obj=zip.'ARCH_CC_P'obj zip.c
+$ cc 'DEF_UNX' /obj=crc32.'ARCH_CC_P'obj crc32.c
+$ cc 'DEF_UNX' /obj=crctab.'ARCH_CC_P'obj crctab.c
+$ cc 'DEF_UNX' /obj=crypt.'ARCH_CC_P'obj crypt.c
+$ cc 'DEF_UNX' /obj=ttyio.'ARCH_CC_P'obj ttyio.c
+$ cc 'DEF_UNX' /obj=zipfile.'ARCH_CC_P'obj zipfile.c
+$ cc 'DEF_UNX' /obj=zipup.'ARCH_CC_P'obj zipup.c
+$ cc 'DEF_UNX' /obj=fileio.'ARCH_CC_P'obj fileio.c
+$ cc 'DEF_UNX' /obj=globals.'ARCH_CC_P'obj globals.c
+$ cc 'DEF_UNX' /obj=util.'ARCH_CC_P'obj util.c
+$ cc 'DEF_UNX' /obj=deflate.'ARCH_CC_P'obj deflate.c
+$ cc 'DEF_UNX' /obj=trees.'ARCH_CC_P'obj trees.c
+$ cc 'DEF_UNX' /obj=vmszip.'ARCH_CC_P'obj/inc=SYS$DISK:[] [.vms]vmszip.c
+$ cc 'DEF_UNX' /obj=vms.'ARCH_CC_P'obj/inc=SYS$DISK:[] [.vms]vms.c
+$ cc 'DEF_UNX' /obj=vmsmunch.'ARCH_CC_P'obj/inc=SYS$DISK:[] [.vms]vmsmunch.c
+$ !
+$ if f$search("zip.''ARCH_CC_P'olb") .eqs. "" then -
+        lib/obj/create zip.'ARCH_CC_P'olb
+$ lib/obj/replace zip.'ARCH_CC_P'olb -
+        zip.'ARCH_CC_P'obj;, -
+        crc32.'ARCH_CC_P'obj;, crctab.'ARCH_CC_P'obj;, -
+        crypt.'ARCH_CC_P'obj;, ttyio.'ARCH_CC_P'obj;, -
+        zipfile.'ARCH_CC_P'obj;, zipup.'ARCH_CC_P'obj;, -
+        fileio.'ARCH_CC_P'obj;, util.'ARCH_CC_P'obj;, globals.'ARCH_CC_P'obj;,-
+        deflate.'ARCH_CC_P'obj;, trees.'ARCH_CC_P'obj;, -
+        vmszip.'ARCH_CC_P'obj;, vms.'ARCH_CC_P'obj;, -
+        vmsmunch.'ARCH_CC_P'obj;
+$ !
+$ link'LFLAGS'/exe='zipx_unx'.'ARCH_CC_P'exe -
+        zip.'ARCH_CC_P'olb;/incl=(zip,globals)/lib 'opts'
+$ !
+$ !------------------------ Zip (CLI interface) section -----------------------
+$ !
+$ set default [.vms]
+$ edit/tpu/nosection/nodisplay/command=cvthelp.tpu zip_cli.help
+$ set default [-]
+$ runoff/out=zip_cli.hlp [.vms]zip_cli.rnh
+$ !
+$ cc 'DEF_CLI' /obj=zipcli.'ARCH_CC_P'obj zip.c
+$ cc 'DEF_CLI'/INCLUDE=SYS$DISK:[] /OBJ=cmdline.'ARCH_CC_P'obj -
+        [.vms]cmdline.c
+$ set command/obj=zip_cli.'ARCH_CC_P'obj [.vms]zip_cli.cld
+$ !
+$ if f$search("zipcli.''ARCH_CC_P'olb") .eqs. "" then -
+        lib/obj/create zipcli.'ARCH_CC_P'olb
+$ lib/obj/replace zipcli.'ARCH_CC_P'olb -
+        zipcli.'ARCH_CC_P'obj;, -
+        cmdline.'ARCH_CC_P'obj;, zip_cli.'ARCH_CC_P'obj;
+$ !
+$ link'LFLAGS'/exe='zipx_cli'.'ARCH_CC_P'exe -
+        zipcli.'ARCH_CC_P'olb;/incl=(zip)/lib, -
+        zip.'ARCH_CC_P'olb;/incl=(globals)/lib 'opts'
+$ !
+$ !-------------------------- Zip utilities section ---------------------------
+$ !
+$ cc 'DEF_UTIL' /obj=zipfile_.'ARCH_CC_P'obj zipfile.c
+$ cc 'DEF_UTIL' /obj=fileio_.'ARCH_CC_P'obj fileio.c
+$ cc 'DEF_UTIL' /obj=util_.'ARCH_CC_P'obj util.c
+$ cc 'DEF_UTIL' /obj=crypt_.'ARCH_CC_P'obj crypt.c
+$ cc 'DEF_UTIL'/incl=SYS$DISK:[] /obj=vms_.'ARCH_CC_P'obj [.vms]vms.c
+$ if f$search("ziputils.''ARCH_CC_P'olb") .eqs. "" then -
+        lib/obj/create ziputils.'ARCH_CC_P'olb
+$ lib/obj/replace ziputils.'ARCH_CC_P'olb -
+        zipfile_.'ARCH_CC_P'obj;, fileio_.'ARCH_CC_P'obj;, -
+        util_.'ARCH_CC_P'obj;, globals.'ARCH_CC_P'obj;, -
+        crctab.'ARCH_CC_P'obj;, crypt_.'ARCH_CC_P'obj;, ttyio.'ARCH_CC_P'obj;,-
+        vms_.'ARCH_CC_P'obj;, vmsmunch.'ARCH_CC_P'obj;
+$ cc 'DEF_UNX' /obj=zipcloak.'ARCH_CC_P'obj zipcloak.c
+$ cc 'DEF_UNX' /obj=zipnote.'ARCH_CC_P'obj zipnote.c
+$ cc 'DEF_UNX' /obj=zipsplit.'ARCH_CC_P'obj zipsplit.c
+$ link'LFLAGS'/exe=zipcloak.'ARCH_CC_P'exe zipcloak.'ARCH_CC_P'obj, -
+        ziputils.'ARCH_CC_P'olb;/incl=(globals)/lib 'opts'
+$ link'LFLAGS'/exe=zipnote.'ARCH_CC_P'exe zipnote.'ARCH_CC_P'obj, -
+        ziputils.'ARCH_CC_P'olb;/incl=(globals)/lib 'opts'
+$ link'LFLAGS'/exe=zipsplit.'ARCH_CC_P'exe zipsplit.'ARCH_CC_P'obj, -
+        ziputils.'ARCH_CC_P'olb;/incl=(globals)/lib 'opts'
+$ !
+$ !----------------------------- Symbols section ------------------------------
+$ !
+$ ! Set up symbols for the various executables.  Edit the example below,
+$ ! changing "disk:[directory]" as appropriate.
+$ !
+$ zip           == "$''here'''ZIPEXEC'.''ARCH_CC_P'exe"
+$ zipcloak      == "$''here'zipcloak.''ARCH_CC_P'exe"
+$ zipnote       == "$''here'zipnote.''ARCH_CC_P'exe"
+$ zipsplit      == "$''here'zipsplit.''ARCH_CC_P'exe"
+$ !
+$error:
+$ if here .nes. "" then set default 'here'
+$ dummy = f$verify(OLD_VERIFY)
+$ exit
diff --git a/vms/makefile.vms b/vms/makefile.vms
new file mode 100644 (file)
index 0000000..99eb179
--- /dev/null
@@ -0,0 +1,251 @@
+#============================================================================
+# Makefile for VMS Zip, ZipCloak, ZipNote  and ZipSplit          Greg Roelofs
+# Version:  2.0 [for use with Todd Aven's MAKE/VMS 3.4]          25-JUN-1998
+#============================================================================
+
+# ChangeLog:  10-SEP-1993 08:53 by Hunter Goatley (add AXP support)
+#             15-OCT-1995 22:40 by Chr. Spieler (Zip 2.1)
+#             11-DEC-1995 12:09 by Chr. Spieler (AXP uses RELAXED_ANSI mode)
+#             08-JAN-1996 19:08 by Chr. Spieler (updated header dependencies)
+#             16-JAN-1996 19:08 by Chr. Spieler (crypt -> crypt & ttyio)
+#             25-JUL-1997 22:25 by Chr. Spieler (syncronized with descrip.mms)
+#             25-JUN-1998 23:53 by Chr. Spieler (removed bits.c source)
+
+
+########################### USER CUSTOMIZATION ############################
+# add any optional preprocessor flags (macros) to the following line
+# for a custom version (do not forget a trailing comma##):
+COMMON_DEFS =
+######################## END OF USER CUSTOMIZATION ########################
+
+#####################
+# MACRO DEFINITIONS #
+#####################
+
+CFLAGS = /NOLIST/INCL=(SYS$DISK:[])
+CC = cc
+LIB =
+# Define the macro __GNUC__ to use the GNU compiler (also add /undef=__STDC__
+# to CFLAGS, and possibly replace /obj=$@ [below] with copy/rename/delete
+# setup).  NOT TESTED.
+
+OPTFILE = sys$disk:[.vms]vaxcshr.opt
+
+%IFDEF __ALPHA
+CC = CC/STANDARD=RELAX/PREFIX=ALL/ANSI
+E = .AXP_EXE
+O = .AXP_OBJ
+OPTFILE_LIST =
+OPTIONS =
+%ELSE
+%IFDEF __DECC__
+CC = CC/DECC/STANDARD=VAXC/PREFIX=ALL
+E = .VAX_DECC_exe
+O = .VAX_DECC_obj
+OPTFILE_LIST =
+OPTIONS =
+%ELSE
+%IFDEF __GNUC__
+CC = gcc
+E = .VAX_GNUC_exe
+O = .VAX_GNUC_obj
+LIB = gnu_cc:[000000]gcclib.olb/lib,
+%ELSE
+E = .VAX_VAXC_exe
+O = .VAX_VAXC_obj
+%ENDIF
+OPTFILE_LIST = ,$(OPTFILE)
+OPTIONS = ,$(OPTFILE)/OPTIONS
+%ENDIF
+%ENDIF
+
+CFLAGS_ALL  = $(CFLAGS) /def=($(COMMON_DEFS) VMS)
+CFLAGS_CLI  = $(CFLAGS) /def=($(COMMON_DEFS) VMSCLI, VMS)
+CFLAGS_UTIL = $(CFLAGS) /def=($(COMMON_DEFS) UTIL, VMS)
+LD = LINK
+LDFLAGS = /NOTRACE
+
+# object file lists
+OBJM = zip$O, zipcli$O
+OBJZ = crc32$O, crctab$O, crypt$O, ttyio$O,-
+       zipfile$O, zipup$O, fileio$O, globals$O, util$O
+OBJV = vmszip$O, vms$O, vmsmunch$O
+OBJI = deflate$O, trees$O
+OBJU = zipfile_$O, fileio_$O, globals$O,-
+       util_$O, vms_$O, vmsmunch$O
+OBJR =  crctab$O, crypt_$O, ttyio$O
+OBJC = zipcloak$O, $(OBJR), $(OBJU)
+OBJN = zipnote$O, $(OBJU)
+OBJS = zipsplit$O, $(OBJU)
+
+ZIPX_UNX = zip
+ZIPX_CLI = zip_cli
+OBJSZIPLIB = $(OBJZ), $(OBJI), $(OBJV)
+OBJSZIP = zip$O, $(OBJSZIPLIB)
+OBJSCLI = zipcli$O, zip_cli$O, cmdline$O
+OBJSZIP_CLI = $(OBJSCLI), $(OBJSZIPLIB)
+ZIPHELP_UNX_RNH = [.vms]vms_zip.rnh
+ZIPHELP_CLI_RNH = [.vms]zip_cli.rnh
+
+ZIP_H =        zip.h ziperr.h tailor.h [.vms]osdep.h
+
+ZIPS = $(ZIPX_UNX)$E $(ZIPX_CLI)$E zipcloak$E zipnote$E zipsplit$E
+ZIPHELPS = $(ZIPX_UNX).hlp $(ZIPX_CLI).hlp
+
+###############################################
+# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES #
+###############################################
+
+default :      $(ZIPS) $(ZIPHELPS)
+
+
+# suffix rules
+*$O:   *.c                             # `*.c' necessary?
+       $(CC)$(CFLAGS_ALL)/OBJECT=$@ $<
+
+*.hlp: *.rnh
+       runoff /out=$@ $<
+
+
+# executables makerules (trailing `$' makes line a data line)
+$(ZIPX_UNX)$E :        $(OBJSZIP) $(OPTFILE_LIST)
+       $(LD) $(LDFLAGS)/EXEC=$(ZIPX_UNX)$E $(OBJSZIP) $(LIB) $(OPTIONS)
+
+$(ZIPX_CLI)$E :        $(OBJSZIP_CLI) $(OPTFILE_LIST)
+       $(LD) $(LDFLAGS)/EXEC=$(ZIPX_CLI)$E $(OBJSZIP_CLI) $(LIB) $(OPTIONS)
+
+zipcloak$E :   $(OBJC) $(OPTFILE_LIST)
+       $(LD) $(LDFLAGS)/EXEC=ZIPCLOAK$E $(OBJC) $(LIB) $(OPTIONS)
+
+zipnote$E :    $(OBJN) $(OPTFILE_LIST)
+       $(LD) $(LDFLAGS)/EXEC=ZIPNOTE$E $(OBJN) $(LIB) $(OPTIONS)
+
+zipsplit$E :   $(OBJS) $(OPTFILE_LIST)
+       $(LD) $(LDFLAGS)/EXEC=ZIPSPLIT$E $(OBJS) $(LIB) $(OPTIONS)
+
+$(OPTFILE) :
+       open/write tmp $(OPTFILE)
+       write tmp "SYS$SHARE:VAXCRTL.EXE/SHARE"
+       close tmp
+
+$(ZIPHELP_CLI_RNH)     : [.vms]zip_cli.help
+       set default [.vms]
+       edit/tpu/nosection/nodisplay/command=cvthelp.tpu zip_cli.help
+       set default [-]
+
+$(ZIPX_UNX).hlp : $(ZIPHELP_UNX_RNH)
+       runoff /out=$@ $<
+
+$(ZIPX_CLI).hlp : $(ZIPHELP_CLI_RNH)
+
+# dependencies for zip, zipnote, zipcloak, and zipsplit
+vmszip$O :     [.vms]vmszip.c [.vms]vmsmunch.h
+       $(CC)$(CFLAGS_ALL)/OBJECT=vmszip$O [.vms]vmszip.c
+vms$O :                [.vms]vms.c [.vms]vms_im.c [.vms]vms_pk.c \
+       [.vms]vms.h [.vms]vmsdefs.h
+       $(CC)$(CFLAGS_ALL)/OBJECT=vms$O [.vms]vms.c
+vmsmunch$O :   [.vms]vmsmunch.c [.vms]vmsmunch.h [.vms]vmsdefs.h
+       $(CC)$(CFLAGS_ALL)/OBJECT=vmsmunch$O [.vms]vmsmunch.c
+zipcli$O : zip.c [.vms]vmsmunch.h
+       $(CC) $(CFLAGS_CLI) /OBJ=$(MMS$TARGET) $<
+cmdline$O : [.vms]cmdline.c $(ZIP_H) crypt.h revision.h
+       $(CC) $(CFLAGS_CLI) /OBJ=$(MMS$TARGET) $<
+zip_cli$O : [.vms]zip_cli.cld
+
+crypt_$O :     crypt.c crypt.h ttyio.h
+       $(CC)$(CFLAGS_UTIL)/OBJECT=crypt_$O crypt.c
+zipfile_$O :   zipfile.c [.vms]vmsmunch.h [.vms]vmsdefs.h
+       $(CC)$(CFLAGS_UTIL)/OBJECT=zipfile_$O zipfile.c
+fileio_$O :    fileio.c
+       $(CC)$(CFLAGS_UTIL)/OBJECT=fileio_$O fileio.c
+util_$O :      util.c
+       $(CC)$(CFLAGS_UTIL)/OBJECT=util_$O util.c
+vms_$O :       [.vms]vms.c [.vms]vms_im.c [.vms]vms_pk.c \
+       [.vms]vms.h [.vms]vmsdefs.h
+       $(CC)$(CFLAGS_UTIL)/OBJECT=vms_$O [.vms]vms.c
+
+$(OBJM) zipcloak$O zipnote$O zipsplit$O zipup$O : revision.h
+$(OBJM) zipcloak$O zipup$O crypt$O ttyio$O : crypt.h
+$(OBJM) zipcloak$O crypt$O ttyio$O : ttyio.h
+zipup$O :      [.vms]zipup.h
+zipfile$O :    [.vms]vmsmunch.h [.vms]vmsdefs.h
+zip$O :                [.vms]vmsmunch.h
+$(OBJM) :      $(ZIP_H)
+$(OBJZ) :      $(ZIP_H)
+$(OBJI) :      $(ZIP_H)
+$(OBJN) :      $(ZIP_H)
+$(OBJS) :      $(ZIP_H)
+$(OBJC) :      $(ZIP_H)
+
+clean.com :
+       @ open/write tmp $@
+       @ write tmp "$!"
+       @ write tmp "$! Clean.com --    procedure to delete files. It always returns success"
+       @ write tmp "$!                 status despite any error or warnings. Also it extracts"
+       @ write tmp "$!                 filename from MMS ""module=file"" format."
+       @ write tmp "$!"
+       @ write tmp "$ on control_y then goto ctly"
+       @ write tmp "$ if p1.eqs."""" then exit 1"
+       @ write tmp "$ i = -1"
+       @ write tmp "$scan_list:"
+       @ write tmp "$  i = i+1"
+       @ write tmp "$  item = f$elem(i,"","",p1)"
+       @ write tmp "$  if item.eqs."""" then goto scan_list"
+       @ write tmp "$  if item.eqs."","" then goto done                ! End of list"
+       @ write tmp "$  item = f$edit(item,""trim"")            ! Clean of blanks"
+       @ write tmp "$  wild = f$elem(1,""="",item)"
+       @ write tmp "$  show sym wild"
+       @ write tmp "$  if wild.eqs.""="" then wild = f$elem(0,""="",item)"
+       @ write tmp "$  vers = f$parse(wild,,,""version"",""syntax_only"")"
+       @ write tmp "$  if vers.eqs."";"" then wild = wild - "";"" + "";*"""
+       @ write tmp "$scan:"
+       @ write tmp "$          f = f$search(wild)"
+       @ write tmp "$          if f.eqs."""" then goto scan_list"
+       @ write tmp "$          on error then goto err"
+       @ write tmp "$          on warning then goto warn"
+       @ write tmp "$          delete/log 'f'"
+       @ write tmp "$warn:"
+       @ write tmp "$err:"
+       @ write tmp "$          goto scan"
+       @ write tmp "$done:"
+       @ write tmp "$ctly:"
+       @ write tmp "$  exit 1"
+       @ close tmp
+
+clean : clean.com
+       @clean "$(OBJM)"
+       @clean "$(OBJZ)"
+       @clean "$(OBJI)"
+       @clean "$(OBJV)"
+       @clean "$(OBJU)"
+       @clean "$(OBJR)"
+       @clean "$(OBJN)"
+       @clean "$(OBJS)"
+       @clean "$(OBJC)"
+       @clean "$(ZIPS)"
+       @clean "$(ZIPHELP_CLI_RNH)"
+       @clean "$(ZIPHELPS)"
+       - delete/noconfirm/nolog clean.com;*
+
+
+# the backslash '\' is the continuation character if it occurs as
+# the last non-white character on the line.
+# the hyphen '-' is the DCL continuation character, so if it occurs
+# as the last non-white character on the line, the next line will
+# not have the dollar sign '$' prepended.
+
+
+################################
+# INDIVIDUAL MACHINE MAKERULES #
+################################
+
+generic :      default         # first try if unknown
+generic2 :     default         # second try if unknown
+vax :          default
+vms :          default
+
+all :          $(ZIPS)
+zip :          zip$E
+zipcloak :     zipcloak$E
+zipnote :      zipnote$E
+zipsplit :     zipsplit$E
diff --git a/vms/osdep.h b/vms/osdep.h
new file mode 100644 (file)
index 0000000..77aee44
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#ifndef VMS
+#  define VMS 1
+#endif
+
+#if (defined(__VMS_VER) && !defined(__CRTL_VER))
+#  define __CRTL_VER __VMS_VER
+#endif
+
+#if (defined(__VMS_VERSION) && !defined(VMS_VERSION))
+#  define VMS_VERSION __VMS_VERSION
+#endif
+
+#if !(defined(__DECC) || defined(__DECCXX) || defined(__GNUC__))
+     /* VAX C does not properly support the void keyword. (Only functions
+        are allowed to have the type "void".)  */
+#  ifndef NO_TYPEDEF_VOID
+#    define NO_TYPEDEF_VOID
+#  endif
+#  define NO_FCNTL_H        /* VAXC does not supply fcntl.h. */
+#endif /* VAX C */
+
+#define NO_UNISTD_H
+
+#define USE_CASE_MAP
+#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \
+                     procname(n, 1))
+
+#include <types.h>
+#include <stat.h>
+#include <unixio.h>
+
+#if defined(__GNUC__) && !defined(ZCRYPT_INTERNAL)
+#  include <unixlib.h>          /* ctermid() declaration needed in ttyio.c */
+#endif
+#ifdef ZCRYPT_INTERNAL
+#  include <unixlib.h>          /* getpid() declaration for srand seed */
+#endif
+
+#if defined(_MBCS)
+#  undef _MBCS                 /* Zip on VMS does not support MBCS */
+#endif
+
+#if !defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)
+#  if (defined(__CRTL_VER) && (__CRTL_VER >= 70000000))
+#    define USE_EF_UT_TIME
+#  endif
+#endif
+
+#if defined(VMS_PK_EXTRA) && defined(VMS_IM_EXTRA)
+#  undef VMS_IM_EXTRA                 /* PK style takes precedence */
+#endif
+#if !defined(VMS_PK_EXTRA) && !defined(VMS_IM_EXTRA)
+#  define VMS_PK_EXTRA 1              /* PK style VMS support is default */
+#endif
+
+#define unlink delete
+#define NO_SYMLINK
+#define SSTAT vms_stat
+#define EXIT(exit_code) vms_exit(exit_code)
+#define RETURN(exit_code) return (vms_exit(exit_code), 1)
+
+#ifdef __DECC
+
+/* File open callback ID values. */
+
+#  define FOPM_ID 1
+#  define FOPR_ID 2
+#  define FOPW_ID 3
+
+/* File open callback ID storage. */
+
+extern int fopm_id;
+extern int fopr_id;
+extern int fopw_id;
+
+/* File open callback ID function. */
+
+extern int acc_cb();
+
+/* Option macros for zfopen().
+ * General: Stream access
+ * Output: fixed-length, 512-byte records.
+ *
+ * Callback function (DEC C only) sets deq, mbc, mbf, rah, wbh, ...
+ */
+
+#  define FOPM "r+b", "ctx=stm", "rfm=fix", "mrs=512", "acc", acc_cb, &fopm_id
+#  define FOPR "rb",  "ctx=stm", "acc", acc_cb, &fopr_id
+#  define FOPW "wb",  "ctx=stm", "rfm=fix", "mrs=512", "acc", acc_cb, &fopw_id
+
+#else /* def __DECC */ /* (So, GNU C, VAX C, ...)*/
+
+#  define FOPM "r+b", "ctx=stm", "rfm=fix", "mrs=512"
+#  define FOPR "rb",  "ctx=stm"
+#  define FOPW "wb",  "ctx=stm", "rfm=fix", "mrs=512"
+
+#endif /* def __DECC */
+
diff --git a/vms/vms.c b/vms/vms.c
new file mode 100644 (file)
index 0000000..440b866
--- /dev/null
+++ b/vms/vms.c
@@ -0,0 +1,807 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *  vms.c (zip) by Igor Mandrichenko    Version 2.2-2
+ *
+ *  Revision history:
+ *  ...
+ *  2.2-2       18-jan-1993     I.Mandrichenko
+ *      vms_stat() added - version of stat() that handles special
+ *      case when end-of-file-block == 0
+ *
+ *  2.3.1       11-oct-2004     SMS
+ *      It would be nice to know why vms_stat() is needed.  If EOF can't
+ *      be trusted for a zero-length file, why trust it for any file?
+ *      Anyway, I removed the (int) cast on ->st_size, which may now be
+ *      bigger than an int, just in case this code ever does get used.
+ *      (A true zero-length file should still report zero length, even
+ *      after the long fight with RMS.)
+ *      Moved the VMS_PK_EXTRA test(s) into VMS_IM.C and VMS_PK.C to
+ *      allow more general automatic dependency generation.
+ */
+
+#ifdef VMS                      /* For VMS only ! */
+
+#define NO_ZIPUP_H              /* prevent inclusion of vms/zipup.h */
+
+#include "zip.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <jpidef.h>
+#include <fab.h>                /* Needed only in old environments. */
+#include <nam.h>                /* Needed only in old environments. */
+#include <starlet.h>
+#include <stsdef.h>
+
+/* On VAX, define Goofy VAX Type-Cast to obviate /standard = vaxc.
+   Otherwise, lame system headers on VAX cause compiler warnings.
+   (GNU C may define vax but not __VAX.)
+*/
+#ifdef vax
+# define __VAX 1
+#endif /* def vax */
+
+#ifdef __VAX
+# define GVTC (unsigned int)
+#else /* def __VAX */
+# define GVTC
+#endif /* def __VAX */
+
+
+#ifdef UTIL
+
+/* For utilities, include only vms.h, as either of the vms_XX.c files
+ * would do.
+ */
+
+# include "vms.h"
+
+#else /* def UTIL */
+
+/* Include the `VMS attributes' preserving file-io code. We distinguish
+   between two incompatible flavours of storing VMS attributes in the
+   Zip archive:
+   a) The "PKware" style follows the extra field specification for
+      PKware's VMS Zip.
+   b) The "IM (Info-ZIP)" flavour was defined from scratch by
+      Igor Mandrichenko. This version has be used in official Info-ZIP
+      releases for several years and is known to work well.
+ */
+
+/* Note that only one of these #include directives will include any
+ * active code, depending on VMS_PK_EXTRA.  Both are included here (and
+ * tested there) to allow more general automatic dependency generation.
+ */
+
+#include "vms_pk.c"
+#include "vms_im.c"
+
+#endif /* def UTIL */
+
+#ifndef ERR
+#define ERR(x) (((x)&1)==0)
+#endif
+
+#ifndef NULL
+#define NULL (void*)(0L)
+#endif
+
+int vms_stat(file,s)
+char *file;
+stat_t *s;
+{
+    int status;
+    int staterr;
+    struct FAB fab;
+    struct XABFHC fhc;
+
+    /*
+     *  In simplest case when stat() returns "ok" and file size is
+     *  nonzero or this is directory, finish with this
+     */
+
+    if( (staterr=stat(file,s)) == 0
+        && ( s->st_size >= 0                      /* Size - ok */
+             || (s->st_mode & S_IFREG) == 0       /* Not a plain file */
+           )
+    ) return staterr;
+
+    /*
+     *  Get here to handle the special case when stat() returns
+     *  invalid file size. Use RMS to compute the size.
+     *  When EOF block is zero, set file size to its physical size.
+     *  One more case to get here is when this is remote file accessed
+     *  via DECnet.
+     */
+
+    fab = cc$rms_fab;
+    fhc = cc$rms_xabfhc;
+    fab.fab$l_fna = file;
+    fab.fab$b_fns = strlen(file);
+    fab.fab$l_xab = (char*)(&fhc);
+
+    fab.fab$b_fac = FAB$M_GET;
+
+    status = sys$open(&fab);
+    fab.fab$l_xab = (char*)0L;
+    sys$close(&fab);
+
+    if( !ERR(status) )
+    {
+        if( fhc.xab$l_ebk > 0 )
+            s->st_size = ( fhc.xab$l_ebk-1 ) * 512 + fhc.xab$w_ffb;
+        else if( fab.fab$b_org == FAB$C_IDX
+                 || fab.fab$b_org == FAB$C_REL
+                 || fab.fab$b_org == FAB$C_HSH )
+                /* Special case, when ebk=0: save entire allocated space */
+                    s->st_size = fhc.xab$l_hbk * 512;
+        else
+            s->st_size = fhc.xab$w_ffb;
+        return 0; /* stat() success code */
+    }
+    else
+        return status;
+}
+
+void vms_exit(e)
+   int e;
+{
+/*---------------------------------------------------------------------------
+    Return an intelligent status/severity level if RETURN_SEVERITY defined:
+
+    $STATUS          $SEVERITY = $STATUS & 7
+    31 .. 16 15 .. 3   2 1 0
+                       -----
+    VMS                0 0 0  0    Warning
+    FACILITY           0 0 1  1    Success
+    Number             0 1 0  2    Error
+             MESSAGE   0 1 1  3    Information
+             Number    1 0 0  4    Severe (fatal) error
+
+    0x7FFF0000 was chosen (by experimentation) to be outside the range of
+    VMS FACILITYs that have dedicated message numbers.  Hopefully this will
+    always result in silent exits--it does on VMS 5.4.  Note that the C li-
+    brary translates exit arguments of zero to a $STATUS value of 1 (i.e.,
+    exit is both silent and has a $SEVERITY of "success").
+  ---------------------------------------------------------------------------*/
+  {
+    int severity;
+
+    switch (e) {                        /* $SEVERITY: */
+      case ZE_NONE:
+          severity = 0; break;          /*   warning  */
+      case ZE_FORM:
+      case ZE_BIG:
+      case ZE_NOTE:
+      case ZE_ABORT:
+      case ZE_NAME:
+      case ZE_PARMS:
+      case ZE_OPEN:
+          severity = 2; break;          /*   error    */
+      default:
+          severity = 4; break;          /*   fatal    */
+    }
+
+    exit(                                       /* $SEVERITY:              */
+         (e == ZE_OK) ? 1 :                     /*   success               */
+         (0x7FFF0000 | (e << 4) | severity)     /*   warning, error, fatal */
+        );
+   }
+}
+
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+void version_local()
+{
+    static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
+#ifdef VMS_VERSION
+    char *chrp1;
+    char *chrp2;
+    char buf[40];
+    char vms_vers[16];
+    int ver_maj;
+#endif
+#ifdef __DECC_VER
+    char buf2[40];
+    int  vtyp;
+#endif
+
+#ifdef VMS_VERSION
+    /* Truncate the version string at the first (trailing) space. */
+    strncpy( vms_vers, VMS_VERSION, sizeof( vms_vers));
+    chrp1 = strchr( vms_vers, ' ');
+    if (chrp1 != NULL)
+        *chrp1 = '\0';
+
+    /* Determine the major version number. */
+    ver_maj = 0;
+    chrp1 = strchr( &vms_vers[1], '.');
+    for (chrp2 = &vms_vers[1];
+         chrp2 < chrp1;
+         ver_maj = ver_maj * 10 + *(chrp2++) - '0');
+
+#endif /* def VMS_VERSION */
+
+/*  DEC C in ANSI mode does not like "#ifdef MACRO" inside another
+    macro when MACRO is equated to a value (by "#define MACRO 1").   */
+
+    printf(CompiledWith,
+
+#ifdef __GNUC__
+      "gcc ", __VERSION__,
+#else
+#  if defined(DECC) || defined(__DECC) || defined (__DECC__)
+      "DEC C",
+#    ifdef __DECC_VER
+      (sprintf(buf2, " %c%d.%d-%03d",
+               ((vtyp = (__DECC_VER / 10000) % 10) == 6 ? 'T' :
+                (vtyp == 8 ? 'S' : 'V')),
+               __DECC_VER / 10000000,
+               (__DECC_VER % 10000000) / 100000, __DECC_VER % 1000), buf2),
+#    else
+      "",
+#    endif
+#  else
+#  ifdef VAXC
+      "VAX C", "",
+#  else
+      "unknown compiler", "",
+#  endif
+#  endif
+#endif
+
+#ifdef VMS_VERSION
+#  if defined( __alpha)
+      "OpenVMS",
+      (sprintf( buf, " (%s Alpha)", vms_vers), buf),
+#  elif defined( __IA64) /* defined( __alpha) */
+      "OpenVMS",
+      (sprintf( buf, " (%s IA64)", vms_vers), buf),
+#  else /* defined( __alpha) */
+      (ver_maj >= 6) ? "OpenVMS" : "VMS",
+      (sprintf( buf, " (%s VAX)", vms_vers), buf),
+#  endif /* defined( __alpha) */
+#else
+      "VMS",
+      "",
+#endif /* def VMS_VERSION */
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+      );
+
+} /* end function version_local() */
+
+/* 2004-10-08 SMS.
+ *
+ *       tempname() for VMS.
+ *
+ *    Generate a temporary Zip archive file name, near the actual
+ *    destination Zip archive file, or at "tempath", if specified.
+ *
+ *    Using sys$parse() is probably more work than it's worth, but it
+ *    should also be ODS5-safe.
+ *
+ *    Note that the generic method using tmpnam() (in FILEIO.C)
+ *    produces "ziXXXXXX", where "XXXXXX" is the low six digits of the
+ *    decimal representation of the process ID.  This method produces
+ *    "ZIxxxxxxxx", where "xxxxxxxx" is the (whole) eight-digit
+ *    hexadecimal representation of the process ID.  More important, it
+ *    actually uses the directory part of the argument or "tempath".
+ */
+
+/* Define macros for use with either NAM or NAML. */
+
+#ifdef NAML$C_MAXRSS            /* NAML is available.  Use it. */
+
+#define NAM_STRUCT NAML
+
+#define CC_RMS_NAM cc$rms_naml
+#define FAB_NAM fab$l_naml
+#define NAME nam
+#define NAME_DNA naml$l_long_defname
+#define NAME_DNS naml$l_long_defname_size
+#define NAME_FNA naml$l_long_filename
+#define NAME_FNS naml$l_long_filename_size
+#define NAM_ESA naml$l_long_expand
+#define NAM_ESL naml$l_long_expand_size
+#define NAM_ESS naml$l_long_expand_alloc
+#define NAM_MAXRSS NAML$C_MAXRSS
+#define NAM_NOP naml$b_nop
+#define NAM_TYPE naml$l_long_type
+#define NAM_M_SYNCHK NAML$M_SYNCHK
+
+#else /* def NAML$C_MAXRSS */   /* NAML is not available.  Use NAM. */
+
+#define NAM_STRUCT NAM
+
+#define CC_RMS_NAM cc$rms_nam
+#define FAB_NAM fab$l_nam
+#define NAME fab
+#define NAME_DNA fab$l_dna
+#define NAME_DNS fab$b_dns
+#define NAME_FNA fab$l_fna
+#define NAME_FNS fab$b_fns
+#define NAM_ESA nam$l_esa
+#define NAM_ESL nam$l_esl
+#define NAM_ESS nam$b_ess
+#define NAM_MAXRSS NAM$C_MAXRSS
+#define NAM_NOP nam$b_nop
+#define NAM_TYPE nam$l_type
+#define NAM_M_SYNCHK NAM$M_SYNCHK
+
+#endif /* def NAML$C_MAXRSS */
+
+
+char *tempname( zip)
+char *zip;                      /* Path name of Zip archive. */
+{
+    char *temp_name;            /* Return value. */
+    int sts;                    /* System service status. */
+
+    static int pid;             /* Process ID. */
+    static int pid_len;         /* Returned size of process ID. */
+
+    struct                      /* Item list for GETJPIW. */
+    {
+        short buf_len;          /* Buffer length. */
+        short itm_cod;          /* Item code. */
+        int *buf;               /* Buffer address. */
+        int *ret_len;           /* Returned length. */
+        int term;               /* Item list terminator. */
+    } jpi_itm_lst = { sizeof( pid), JPI$_PID, &pid, &pid_len };
+
+    /* ZI<UNIQUE> name storage. */
+    static char zip_tmp_nam[16] = "ZI<unique>.;";
+
+    struct FAB fab;             /* FAB structure. */
+    struct NAM_STRUCT nam;      /* NAM[L] structure. */
+
+    char exp_str[ NAM_MAXRSS + 1];   /* Expanded name storage. */
+
+#ifdef VMS_UNIQUE_TEMP_BY_TIME
+
+    /* Use alternate time-based scheme to generate a unique temporary name. */
+    sprintf( &zip_tmp_nam[2], "%08X", time( NULL));
+
+#else /* def VMS_UNIQUE_TEMP_BY_TIME */
+
+    /* Use the process ID to generate a unique temporary name. */
+    sts = sys$getjpiw( 0, 0, 0, &jpi_itm_lst, 0, 0, 0);
+    sprintf( &zip_tmp_nam[2], "%08X", pid);
+
+#endif /* def VMS_UNIQUE_TEMP_BY_TIME */
+
+    /* Smoosh the unique temporary name against the actual Zip archive
+       name (or "tempath") to create the full temporary path name.
+       (Truncate it at the file type to remove any file type.)
+    */
+    if (tempath != NULL)        /* Use "tempath", if it's been specified. */
+        zip = tempath;
+
+    /* Initialize the FAB and NAM[L], and link the NAM[L] to the FAB. */
+    fab = cc$rms_fab;
+    nam = CC_RMS_NAM;
+    fab.FAB_NAM = &nam;
+
+    /* Point the FAB/NAM[L] fields to the actual name and default name. */
+
+#ifdef NAML$C_MAXRSS
+
+    fab.fab$l_dna = (char *) -1;    /* Using NAML for default name. */
+    fab.fab$l_fna = (char *) -1;    /* Using NAML for file name. */
+
+#endif /* def NAML$C_MAXRSS */
+
+    NAME.NAME_DNA = zip;            /* Default name = Zip archive name. */
+    NAME.NAME_DNS = strlen( NAME.NAME_DNA);
+
+    NAME.NAME_FNA = zip_tmp_nam;    /* File name = "ZI<unique>,;". */
+    NAME.NAME_FNS = strlen( NAME.NAME_FNA);
+
+    nam.NAM_ESA = exp_str;      /* Expanded name (result) storage. */
+    nam.NAM_ESS = NAM_MAXRSS;   /* Size of expanded name storage. */
+
+    nam.NAM_NOP = NAM_M_SYNCHK; /* Syntax-only analysis. */
+
+    temp_name = NULL;           /* Prepare for failure (unlikely). */
+    sts = sys$parse( &fab, 0, 0);       /* Parse the name(s). */
+
+    if ((sts& STS$M_SEVERITY) == STS$M_SUCCESS)
+    {
+        /* Overlay any resulting file type (typically ".ZIP") with none. */
+        strcpy( nam.NAM_TYPE, ".;");
+
+        /* Allocate temp name storage (as caller expects), and copy the
+           (truncated) temp name into the new location.
+        */
+        temp_name = malloc( strlen( nam.NAM_ESA) + 1);
+
+        if (temp_name != NULL)
+        {
+            strcpy( temp_name, nam.NAM_ESA);
+        }
+    }
+    return temp_name;
+} /* tempname() for VMS */
+
+
+/* 2004-11-23 SMS.
+ *
+ *       get_rms_defaults().
+ *
+ *    Get user-specified values from (DCL) SET RMS_DEFAULT.  FAB/RAB
+ *    items of particular interest are:
+ *
+ *       fab$w_deq         default extension quantity (blocks) (write).
+ *       rab$b_mbc         multi-block count.
+ *       rab$b_mbf         multi-buffer count (used with rah and wbh).
+ */
+
+#define DIAG_FLAG verbose
+
+/* Default RMS parameter values. */
+
+#define RMS_DEQ_DEFAULT 16384   /* About 1/4 the max (65535 blocks). */
+#define RMS_MBC_DEFAULT 127     /* The max, */
+#define RMS_MBF_DEFAULT 2       /* Enough to enable rah and wbh. */
+
+/* GETJPI item descriptor structure. */
+typedef struct
+    {
+    short buf_len;
+    short itm_cod;
+    void *buf;
+    int *ret_len;
+    } jpi_item_t;
+
+/* Durable storage */
+
+static int rms_defaults_known = 0;
+
+/* JPI item buffers. */
+static unsigned short rms_ext;
+static char rms_mbc;
+static unsigned char rms_mbf;
+
+/* Active RMS item values. */
+unsigned short rms_ext_active;
+char rms_mbc_active;
+unsigned char rms_mbf_active;
+
+/* GETJPI item lengths. */
+static int rms_ext_len;         /* Should come back 2. */
+static int rms_mbc_len;         /* Should come back 1. */
+static int rms_mbf_len;         /* Should come back 1. */
+
+/* Desperation attempts to define unknown macros.  Probably doomed.
+ * If these get used, expect sys$getjpiw() to return %x00000014 =
+ * %SYSTEM-F-BADPARAM, bad parameter value.
+ * They keep compilers with old header files quiet, though.
+ */
+#ifndef JPI$_RMS_EXTEND_SIZE
+#  define JPI$_RMS_EXTEND_SIZE 542
+#endif /* ndef JPI$_RMS_EXTEND_SIZE */
+
+#ifndef JPI$_RMS_DFMBC
+#  define JPI$_RMS_DFMBC 535
+#endif /* ndef JPI$_RMS_DFMBC */
+
+#ifndef JPI$_RMS_DFMBFSDK
+#  define JPI$_RMS_DFMBFSDK 536
+#endif /* ndef JPI$_RMS_DFMBFSDK */
+
+/* GETJPI item descriptor set. */
+
+struct
+    {
+    jpi_item_t rms_ext_itm;
+    jpi_item_t rms_mbc_itm;
+    jpi_item_t rms_mbf_itm;
+    int term;
+    } jpi_itm_lst =
+     { { 2, JPI$_RMS_EXTEND_SIZE, &rms_ext, &rms_ext_len },
+       { 1, JPI$_RMS_DFMBC, &rms_mbc, &rms_mbc_len },
+       { 1, JPI$_RMS_DFMBFSDK, &rms_mbf, &rms_mbf_len },
+       0
+     };
+
+int get_rms_defaults()
+{
+int sts;
+
+/* Get process RMS_DEFAULT values. */
+
+sts = sys$getjpiw( 0, 0, 0, &jpi_itm_lst, 0, 0, 0);
+if ((sts& STS$M_SEVERITY) != STS$M_SUCCESS)
+    {
+    /* Failed.  Don't try again. */
+    rms_defaults_known = -1;
+    }
+else
+    {
+    /* Fine, but don't come back. */
+    rms_defaults_known = 1;
+    }
+
+/* Limit the active values according to the RMS_DEFAULT values. */
+
+if (rms_defaults_known > 0)
+    {
+    /* Set the default values. */
+
+    rms_ext_active = RMS_DEQ_DEFAULT;
+    rms_mbc_active = RMS_MBC_DEFAULT;
+    rms_mbf_active = RMS_MBF_DEFAULT;
+
+    /* Default extend quantity.  Use the user value, if set. */
+    if (rms_ext > 0)
+        {
+        rms_ext_active = rms_ext;
+        }
+
+    /* Default multi-block count.  Use the user value, if set. */
+    if (rms_mbc > 0)
+        {
+        rms_mbc_active = rms_mbc;
+        }
+
+    /* Default multi-buffer count.  Use the user value, if set. */
+    if (rms_mbf > 0)
+        {
+        rms_mbf_active = rms_mbf;
+        }
+    }
+
+if (DIAG_FLAG)
+    {
+    fprintf( stderr,
+     "Get RMS defaults.  getjpi sts = %%x%08x.\n",
+     sts);
+
+    if (rms_defaults_known > 0)
+        {
+        fprintf( stderr,
+         "               Default: deq = %6d, mbc = %3d, mbf = %3d.\n",
+         rms_ext, rms_mbc, rms_mbf);
+        }
+    }
+return sts;
+}
+
+#ifdef __DECC
+
+/* 2004-11-23 SMS.
+ *
+ *       acc_cb(), access callback function for DEC C zfopen().
+ *
+ *    Set some RMS FAB/RAB items, with consideration of user-specified
+ * values from (DCL) SET RMS_DEFAULT.  Items of particular interest are:
+ *
+ *       fab$w_deq         default extension quantity (blocks).
+ *       rab$b_mbc         multi-block count.
+ *       rab$b_mbf         multi-buffer count (used with rah and wbh).
+ *
+ *    See also the FOP* macros in OSDEP.H.  Currently, no notice is
+ * taken of the caller-ID value, but options could be set differently
+ * for read versus write access.  (I assume that specifying fab$w_deq,
+ * for example, for a read-only file has no ill effects.)
+ */
+
+/* Global storage. */
+
+int fopm_id = FOPM_ID;          /* Callback id storage, modify. */
+int fopr_id = FOPR_ID;          /* Callback id storage, read. */
+int fopw_id = FOPW_ID;          /* Callback id storage, write. */
+
+/* acc_cb() */
+
+int acc_cb( int *id_arg, struct FAB *fab, struct RAB *rab)
+{
+int sts;
+
+/* Get process RMS_DEFAULT values, if not already done. */
+if (rms_defaults_known == 0)
+    {
+    get_rms_defaults();
+    }
+
+/* If RMS_DEFAULT (and adjusted active) values are available, then set
+ * the FAB/RAB parameters.  If RMS_DEFAULT values are not available,
+ * suffer with the default parameters.
+ */
+if (rms_defaults_known > 0)
+    {
+    /* Set the FAB/RAB parameters accordingly. */
+    fab-> fab$w_deq = rms_ext_active;
+    rab-> rab$b_mbc = rms_mbc_active;
+    rab-> rab$b_mbf = rms_mbf_active;
+
+    /* Truncate at EOF on close, as we'll probably over-extend. */
+    fab-> fab$v_tef = 1;
+
+    /* If using multiple buffers, enable read-ahead and write-behind. */
+    if (rms_mbf_active > 1)
+        {
+        rab-> rab$v_rah = 1;
+        rab-> rab$v_wbh = 1;
+        }
+
+    if (DIAG_FLAG)
+        {
+        fprintf( mesg,
+         "Open callback.  ID = %d, deq = %6d, mbc = %3d, mbf = %3d.\n",
+         *id_arg, fab-> fab$w_deq, rab-> rab$b_mbc, rab-> rab$b_mbf);
+        }
+    }
+
+/* Declare success. */
+return 0;
+}
+
+#endif /* def __DECC */
+
+/*
+ * 2004-09-19 SMS.
+ *
+ *----------------------------------------------------------------------
+ *
+ *       decc_init()
+ *
+ *    On non-VAX systems, uses LIB$INITIALIZE to set a collection of C
+ *    RTL features without using the DECC$* logical name method.
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef __DECC
+
+#ifdef __CRTL_VER
+
+#if !defined( __VAX) && (__CRTL_VER >= 70301000)
+
+#include <unixlib.h>
+
+/*--------------------------------------------------------------------*/
+
+/* Global storage. */
+
+/*    Flag to sense if decc_init() was called. */
+
+int decc_init_done = -1;
+
+/*--------------------------------------------------------------------*/
+
+/* decc_init()
+
+      Uses LIB$INITIALIZE to set a collection of C RTL features without
+      requiring the user to define the corresponding logical names.
+*/
+
+/* Structure to hold a DECC$* feature name and its desired value. */
+
+typedef struct
+   {
+   char *name;
+   int value;
+   } decc_feat_t;
+
+/* Array of DECC$* feature names and their desired values. */
+
+decc_feat_t decc_feat_array[] = {
+
+   /* Preserve command-line case with SET PROCESS/PARSE_STYLE=EXTENDED */
+ { "DECC$ARGV_PARSE_STYLE", 1 },
+
+#if 0  /* Possibly useful in the future. */
+
+   /* Preserve case for file names on ODS5 disks. */
+ { "DECC$EFS_CASE_PRESERVE", 1 },
+
+   /* Enable multiple dots (and most characters) in ODS5 file names,
+      while preserving VMS-ness of ";version". */
+ { "DECC$EFS_CHARSET", 1 },
+
+#endif /* 0 */
+
+   /* List terminator. */
+ { (char *)NULL, 0 } };
+
+/* LIB$INITIALIZE initialization function. */
+
+static void decc_init( void)
+{
+int feat_index;
+int feat_value;
+int feat_value_max;
+int feat_value_min;
+int i;
+int sts;
+
+/* Set the global flag to indicate that LIB$INITIALIZE worked. */
+
+decc_init_done = 1;
+
+/* Loop through all items in the decc_feat_array[]. */
+
+for (i = 0; decc_feat_array[i].name != NULL; i++)
+   {
+   /* Get the feature index. */
+   feat_index = decc$feature_get_index( decc_feat_array[i].name);
+   if (feat_index >= 0)
+      {
+      /* Valid item.  Collect its properties. */
+      feat_value = decc$feature_get_value( feat_index, 1);
+      feat_value_min = decc$feature_get_value( feat_index, 2);
+      feat_value_max = decc$feature_get_value( feat_index, 3);
+
+      if ((decc_feat_array[i].value >= feat_value_min) &&
+          (decc_feat_array[i].value <= feat_value_max))
+         {
+         /* Valid value.  Set it if necessary. */
+         if (feat_value != decc_feat_array[i].value)
+            {
+            sts = decc$feature_set_value( feat_index,
+             1,
+             decc_feat_array[i].value);
+            }
+         }
+      else
+         {
+         /* Invalid DECC feature value. */
+         printf( " INVALID DECC FEATURE VALUE, %d: %d <= %s <= %d.\n",
+                 feat_value,
+                 feat_value_min, decc_feat_array[i].name, feat_value_max);
+         }
+      }
+   else
+      {
+      /* Invalid DECC feature name. */
+      printf( " UNKNOWN DECC FEATURE: %s.\n", decc_feat_array[i].name);
+      }
+   }
+}
+
+/* Get "decc_init()" into a valid, loaded LIB$INITIALIZE PSECT. */
+
+#pragma nostandard
+
+/* Establish the LIB$INITIALIZE PSECT, with proper alignment and
+   attributes.
+*/
+globaldef { "LIB$INITIALIZ" } readonly _align (LONGWORD)
+   int spare[8] = { 0 };
+globaldef { "LIB$INITIALIZE" } readonly _align (LONGWORD)
+   void (*x_decc_init)() = decc_init;
+
+/* Fake reference to ensure loading the LIB$INITIALIZE PSECT. */
+
+#pragma extern_model save
+int lib$initialize(void);
+#pragma extern_model strict_refdef
+int dmy_lib$initialize = (int) lib$initialize;
+#pragma extern_model restore
+
+#pragma standard
+
+#endif /* !defined( __VAX) && (__CRTL_VER >= 70301000) */
+
+#endif /* def __CRTL_VER */
+
+#endif /* def __DECC */
+
+#endif /* VMS */
diff --git a/vms/vms.h b/vms/vms.h
new file mode 100644 (file)
index 0000000..778f616
--- /dev/null
+++ b/vms/vms.h
@@ -0,0 +1,271 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+  vms.h
+
+  Generic VMS header file for Info-ZIP's Zip and UnZip.
+
+  ---------------------------------------------------------------------------*/
+
+#ifndef __vms_h
+#define __vms_h 1
+
+#ifndef __DESCRIP_LOADED
+#include <descrip.h>
+#endif
+#ifndef __STARLET_LOADED
+#include <starlet.h>
+#endif
+#ifndef __SYIDEF_LOADED
+#include <syidef.h>
+#endif
+#ifndef __ATRDEF_LOADED
+#include <atrdef.h>
+#endif
+#ifndef __FIBDEF_LOADED
+#include <fibdef.h>
+#endif
+#ifndef __IODEF_LOADED
+#include <iodef.h>
+#endif
+#if !defined(_RMS_H) && !defined(__RMS_LOADED)
+#include <rms.h>
+#endif
+
+#define ERR(s) !((s) & 1)       /* VMS system error */
+
+#ifndef SYI$_VERSION
+#define SYI$_VERSION 4096       /* VMS 5.4 definition */
+#endif
+
+/*
+ *  Under Alpha (DEC C in VAXC mode) and under `good old' VAXC, the FIB unions
+ *  are declared as variant_unions.  DEC C (Alpha) in ANSI modes and third
+ *  party compilers which do not support `variant_union' define preprocessor
+ *  symbols to `hide' the "intermediate union/struct" names from the
+ *  programmer's API.
+ *  We check the presence of these defines and for DEC's FIBDEF.H defining
+ *  __union as variant_union to make sure we access the structure correctly.
+ */
+#define variant_union 1
+#if defined(fib$w_did) || (defined(__union) && (__union == variant_union))
+#  define FIB$W_DID     fib$w_did
+#  define FIB$W_FID     fib$w_fid
+#  define FIB$L_ACCTL   fib$l_acctl
+#  define FIB$W_EXCTL   fib$w_exctl
+#else
+#  define FIB$W_DID     fib$r_did_overlay.fib$w_did
+#  define FIB$W_FID     fib$r_fid_overlay.fib$w_fid
+#  define FIB$L_ACCTL   fib$r_acctl_overlay.fib$l_acctl
+#  define FIB$W_EXCTL   fib$r_exctl_overlay.fib$w_exctl
+#endif
+#undef variant_union
+
+
+struct EB_header    /* Common header of extra block */
+{   ush tag;
+    ush size;
+    uch data[1];
+};
+
+#ifndef EB_HEADSIZE
+#  define EB_HEADSIZE 4
+#endif
+
+/*------ Old style Info-ZIP extra field definitions -----*/
+
+#if (!defined(VAXC) && !defined(_RMS_H) && !defined(__RMS_LOADED))
+
+struct XAB {                    /* This definition may be skipped */
+    unsigned char xab$b_cod;
+    unsigned char xab$b_bln;
+    short int xabdef$$_fill_1;
+    char *xab$l_nxt;
+};
+
+#endif /* !VAXC && !_RMS_H && !__RMS_LOADED */
+
+#ifndef EB_IZVMS_BCMASK
+#  define EB_IZVMS_BCMASK   07  /* 3 bits for compression type */
+#endif
+#ifndef EB_IZVMS_BCSTOR
+#  define EB_IZVMS_BCSTOR   0   /*  Stored */
+#endif
+#ifndef EB_IZVMS_BC00
+#  define EB_IZVMS_BC00     1   /*  0byte -> 0bit compression */
+#endif
+#ifndef EB_IZVMS_BCDEFL
+#  define EB_IZVMS_BCDEFL   2   /*  Deflated */
+#endif
+
+/*
+ *  Extra record format
+ *  ===================
+ *  signature       (2 bytes)   = 'I','M'
+ *  size            (2 bytes)
+ *  block signature (4 bytes)
+ *  flags           (2 bytes)
+ *  uncomprssed size(2 bytes)
+ *  reserved        (4 bytes)
+ *  data            ((size-12) bytes)
+ *  ....
+ */
+
+struct IZ_block                 /* Extra field block header structure */
+{
+    ush sig;
+    ush size;
+    ulg bid;
+    ush flags;
+    ush length;
+    ulg reserved;
+    uch body[1];                /* The actual size is unknown */
+};
+
+/*
+ *   Extra field signature and block signatures
+ */
+
+#define IZ_SIGNATURE "IM"
+#define FABSIG  "VFAB"
+#define XALLSIG "VALL"
+#define XFHCSIG "VFHC"
+#define XDATSIG "VDAT"
+#define XRDTSIG "VRDT"
+#define XPROSIG "VPRO"
+#define XKEYSIG "VKEY"
+#define XNAMSIG "VNAM"
+#define VERSIG  "VMSV"
+
+/*
+ *   Block sizes
+ */
+
+#define FABL    (cc$rms_fab.fab$b_bln)
+#define RABL    (cc$rms_rab.rab$b_bln)
+#define XALLL   (cc$rms_xaball.xab$b_bln)
+#define XDATL   (cc$rms_xabdat.xab$b_bln)
+#define XFHCL   (cc$rms_xabfhc.xab$b_bln)
+#define XKEYL   (cc$rms_xabkey.xab$b_bln)
+#define XPROL   (cc$rms_xabpro.xab$b_bln)
+#define XRDTL   (cc$rms_xabrdt.xab$b_bln)
+#define XSUML   (cc$rms_xabsum.xab$b_bln)
+#define EXTBSL  4               /* Block signature length */
+#define RESL    8               /* Reserved 8 bytes */
+#define EXTHL   (EB_HEADSIZE+EXTBSL+RESL)
+
+typedef unsigned char byte;
+
+struct iosb
+{
+    ush status;
+    ush count;
+    ulg spec;
+};
+
+/*------------ PKWARE extra block definitions ----------*/
+
+/* Structure of PKWARE extra header */
+
+#ifdef VMS_ZIP
+
+#if defined(__DECC) || defined(__DECCXX)
+#pragma __nostandard
+#endif /* __DECC || __DECCXX */
+
+#if defined(__DECC) || defined(__DECCXX)
+#pragma __member_alignment __save
+#pragma __nomember_alignment
+#endif /* __DECC || __DECCXX */
+
+#ifdef VMS_ORIGINAL_PK_LAYOUT
+/*  The original order of ATR fields in the PKZIP VMS-extra field leads
+ *  to unaligned fields in the PK_info structure representing the
+ *  extra field layout.  When compiled for Alpha AXP, this results in
+ *  some performance (and code size) penalty.  It is not allowed to
+ *  apply structure padding, since this is explicitely forbidden in
+ *  the specification (APPNOTE.TXT) for the PK VMS extra field.
+ */
+typedef struct
+{
+    ush tag_ra; ush len_ra;     byte ra[ATR$S_RECATTR];
+    ush tag_uc; ush len_uc;     byte uc[ATR$S_UCHAR];
+    ush tag_jr; ush len_jr;     byte jr[ATR$S_JOURNAL];
+    ush tag_cd; ush len_cd;     byte cd[ATR$S_CREDATE];
+    ush tag_rd; ush len_rd;     byte rd[ATR$S_REVDATE];
+    ush tag_ed; ush len_ed;     byte ed[ATR$S_EXPDATE];
+    ush tag_bd; ush len_bd;     byte bd[ATR$S_BAKDATE];
+    ush tag_rn; ush len_rn;     ush  rn;
+    ush tag_ui; ush len_ui;     byte ui[ATR$S_UIC];
+    ush tag_fp; ush len_fp;     byte fp[ATR$S_FPRO];
+    ush tag_rp; ush len_rp;     byte rp[ATR$S_RPRO];
+} PK_info_t;
+#else /* !VMS_ORIGINAL_PK_LAYOUT */
+/*  The Info-ZIP support for the PK VMS extra field uses a reordered
+ *  field layout to achieve ``natural alignment'' of the PK_info structure
+ *  members whenever possible.  This rearrangement does not violate the
+ *  PK's VMS extra field specification and should not break any ``well
+ *  behaving'' (PK)Unzip utility. (`Well behaving' means that (PK)Unzip
+ *  should use the field tag to identify the ATR$ field rather than
+ *  assuming a fixed order of ATR$ fields in the PK VMS extra field.)
+ */
+typedef struct
+{
+    ush tag_ra; ush len_ra;     byte ra[ATR$S_RECATTR];
+    ush tag_uc; ush len_uc;     byte uc[ATR$S_UCHAR];
+    ush tag_cd; ush len_cd;     byte cd[ATR$S_CREDATE];
+    ush tag_rd; ush len_rd;     byte rd[ATR$S_REVDATE];
+    ush tag_ed; ush len_ed;     byte ed[ATR$S_EXPDATE];
+    ush tag_bd; ush len_bd;     byte bd[ATR$S_BAKDATE];
+    ush tag_rn; ush len_rn;     ush  rn;
+    ush tag_ui; ush len_ui;     byte ui[ATR$S_UIC];
+    ush tag_fp; ush len_fp;     byte fp[ATR$S_FPRO];
+    ush tag_rp; ush len_rp;     byte rp[ATR$S_RPRO];
+    ush tag_jr; ush len_jr;     byte jr[ATR$S_JOURNAL];
+} PK_info_t;
+#endif /* ?VMS_ORIGINAL_PK_LAYOUT */
+
+#if defined(__DECC) || defined(__DECCXX)
+#pragma __member_alignment __restore
+#endif /* __DECC || __DECCXX */
+
+#if defined(__DECC) || defined(__DECCXX)
+#pragma __standard
+#endif /* __DECC || __DECCXX */
+
+#endif /* VMS_ZIP */
+
+/* PKWARE "VMS" tag */
+#define PK_SIGNATURE        0x000C
+
+/* Total number of attributes to be saved */
+#define VMS_ATTR_COUNT  11
+#define VMS_MAX_ATRCNT  20
+
+struct PK_field
+{
+    ush         tag;
+    ush         size;
+    byte        value[1];
+};
+
+#define PK_FLDHDR_SIZE  4
+
+struct PK_header
+{
+    ush tag;
+    ush size;
+    ulg crc32;
+    byte data[1];
+};
+
+#define PK_HEADER_SIZE  8
+
+#endif /* !__vms_h */
diff --git a/vms/vms_im.c b/vms/vms_im.c
new file mode 100644 (file)
index 0000000..da84945
--- /dev/null
@@ -0,0 +1,850 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *  vms_im.c (zip) by Igor Mandrichenko    Version 2.2-2
+ *
+ *  Revision history:
+ *  ...
+ *  2.1-1       16-feb-1993     I.Mandrichenko
+ *      Get file size from XABFHC and check bytes rest in file before
+ *      reading.
+ *  2.1-2       2-mar-1993      I.Mandrichenko
+ *      Make code more standard
+ *  2.2         21-jun-1993     I.Mandrichenko
+ *      Free all allocated space, use more static storage.
+ *      Use memcompress() from bits.c (deflation) for block compression.
+ *      To revert to old compression method #define OLD_COMPRESS
+ *  2.2-2       28-sep-1995     C.Spieler
+ *      Reorganized code for easier maintance of the two incompatible
+ *      flavours (IM style and PK style) VMS attribute support.
+ *      Generic functions (common to both flavours) are now collected
+ *      in a `wrapper' source file that includes one of the VMS attribute
+ *      handlers.
+ *  3.0         23-Oct-2004     Steven Schweda
+ *      Changed to maintain compatibility with VMS_PK.C.  Note that
+ *      reading with sys$read() prevents getting any data past EOF,
+ *      regardless of appearances.  Moved the VMS_PK_EXTRA test into
+ *      here from VMS.C to allow more general automatic dependency
+ *      generation.
+ */
+
+#ifdef VMS                      /* For VMS only ! */
+
+#ifndef VMS_PK_EXTRA
+
+#define OLD_COMPRESS            /*To use old compression method define it.*/
+
+#ifdef VMS_ZIP
+#undef VMS_ZIP                  /* do NOT include PK style Zip definitions */
+#endif
+
+#include "vms.h"
+
+#ifndef __LIB$ROUTINES_LOADED
+#include <lib$routines.h>
+#endif
+
+#ifndef UTIL
+
+#define RET_ERROR 1
+#define RET_SUCCESS 0
+#define RET_EOF 0
+
+#define Kbyte 1024
+
+typedef struct XAB *xabptr;
+
+/*
+ *   Block sizes
+ */
+
+#define EXTL0   ((FABL + EXTHL)+        \
+                (XFHCL + EXTHL)+        \
+                (XPROL + EXTHL)+        \
+                (XDATL + EXTHL)+        \
+                (XRDTL + EXTHL))
+
+#ifdef OLD_COMPRESS
+#define PAD     sizeof(uch)
+#else
+#define PAD     10*sizeof(ush)          /* Two extra bytes for compr. header */
+#endif
+
+#define PAD0    (5*PAD)                 /* Reserve space for the case when
+                                         *  compression fails */
+static int _compress(uch *from, uch *to, int size);
+#ifdef DEBUG
+static void dump_rms_block(uch *p);
+#endif /* DEBUG */
+
+/********************************
+ *   Function set_extra_field   *
+ ********************************/
+/*
+ |   2004-11-11 SMS.
+ |   Changed to use separate storage for ->extra and ->cextra.  Zip64
+ |   processing may move (reallocate) one and not the other.
+ */
+
+static uch *_compress_block(register struct IZ_block *to,
+                            uch *from, int size, char *sig);
+static int get_vms_version(char *verbuf, int len);
+
+int set_extra_field(z, z_utim)
+  struct zlist far *z;
+  iztimes *z_utim;
+/*
+ *      Get file VMS file attributes and store them into extent fields.
+ *      Store VMS version also.
+ *      On error leave z intact.
+ */
+{
+    int status;
+    uch *xtra;
+    uch *cxtra;
+    uch *scan;
+    extent extra_l;
+    static struct FAB fab;
+    static struct XABSUM xabsum;
+    static struct XABFHC xabfhc;
+    static struct XABDAT xabdat;
+    static struct XABPRO xabpro;
+    static struct XABRDT xabrdt;
+    xabptr x = (xabptr)NULL, xab_chain = (xabptr)NULL, last_xab = (xabptr)NULL;
+    int nk, na;
+    int i;
+    int rc=RET_ERROR;
+    char verbuf[80];
+    int verlen = 0;
+
+    if (!vms_native)
+    {
+#ifdef USE_EF_UT_TIME
+       /*
+        *  A `portable' zipfile entry is created. Create an "UT" extra block
+        *  containing UNIX style modification time stamp in UTC, which helps
+        *  maintaining the `real' "last modified" time when the archive is
+        *  transfered across time zone boundaries.
+        */
+#  ifdef IZ_CHECK_TZ
+        if (!zp_tz_is_valid)
+            return ZE_OK;       /* skip silently if no valid TZ info */
+#  endif
+        if ((xtra = (uch *) malloc( EB_HEADSIZE+ EB_UT_LEN( 1))) == NULL)
+            return ZE_MEM;
+
+        if ((cxtra = (uch *) malloc( EB_HEADSIZE+ EB_UT_LEN( 1))) == NULL)
+            return ZE_MEM;
+
+        /* Fill xtra[] with data. */
+        xtra[ 0] = 'U';
+        xtra[ 1] = 'T';
+        xtra[ 2] = EB_UT_LEN(1);        /* length of data part of e.f. */
+        xtra[ 3] = 0;
+        xtra[ 4] = EB_UT_FL_MTIME;
+        xtra[ 5] = (uch) (z_utim->mtime);
+        xtra[ 6] = (uch) (z_utim->mtime >> 8);
+        xtra[ 7] = (uch) (z_utim->mtime >> 16);
+        xtra[ 8] = (uch) (z_utim->mtime >> 24);
+
+        /* Copy xtra[] data into cxtra[]. */
+        memcpy( cxtra, xtra, (EB_HEADSIZE+ EB_UT_LEN( 1)));
+
+        /* Set sizes and pointers. */
+        z->cext = z->ext = (EB_HEADSIZE+ EB_UT_LEN( 1));
+        z->extra = (char *) xtra;
+        z->cextra = (char *) cxtra;
+
+#endif /* USE_EF_UT_TIME */
+
+        return RET_SUCCESS;
+    }
+
+    /*
+     *  Initialize RMS control blocks and link them
+     */
+
+    fab =    cc$rms_fab;
+    xabsum = cc$rms_xabsum;
+    xabdat = cc$rms_xabdat;
+    xabfhc = cc$rms_xabfhc;
+    xabpro = cc$rms_xabpro;
+    xabrdt = cc$rms_xabrdt;
+
+
+    fab.fab$l_xab = (char*)&xabsum;
+    /*
+     *  Open the file and read summary information.
+     */
+    fab.fab$b_fns = strlen(z->name);
+    fab.fab$l_fna = z->name;
+
+    status = sys$open(&fab);
+    if (ERR(status))
+    {
+#ifdef DEBUG
+        printf("set_extra_field: sys$open for file %s:\n  error status = %d\n",
+               z->name, status);
+#endif
+        goto err_exit;
+    }
+
+    nk = xabsum.xab$b_nok;
+    na = xabsum.xab$b_noa;
+#ifdef DEBUG
+    printf("%d keys, %d alls\n", nk, na);
+#endif
+
+    /*
+     *  Allocate XABKEY and XABALL blocks and link them
+     */
+
+    xabfhc.xab$l_nxt = (char*)&xabdat;
+    xabdat.xab$l_nxt = (char*)&xabpro;
+    xabpro.xab$l_nxt = (char*)&xabrdt;
+    xabrdt.xab$l_nxt = NULL;
+
+    xab_chain = (xabptr)(&xabfhc);
+    last_xab  = (xabptr)(&xabrdt);
+
+#define INIT(ptr,size,type,init)     \
+        if ( (ptr = (type *)malloc(size)) == NULL )     \
+        {                                               \
+              printf( "set_extra_field: Insufficient memory.\n" );   \
+                      goto err_exit;                    \
+        }                                               \
+        *(ptr) = (init);
+    /*
+     *  Allocate and initialize all needed XABKEYs and XABALLs
+     */
+    for (i = 0; i < nk; i++)
+    {
+        struct XABKEY *k;
+        INIT(k, XKEYL, struct XABKEY, cc$rms_xabkey);
+        k->xab$b_ref = i;
+        if (last_xab != NULL)
+            last_xab->xab$l_nxt = (char*)k;
+        last_xab = (xabptr)k;
+    }
+    for (i = 0; i < na; i++)
+    {
+        struct XABALL *a;
+        INIT(a, XALLL, struct XABALL, cc$rms_xaball);
+        a->xab$b_aid = i;
+        if (last_xab != NULL)
+            last_xab->xab$l_nxt = (char*)a;
+        last_xab = (xabptr)a;
+    }
+
+    fab.fab$l_xab = (char*)xab_chain;
+#ifdef DEBUG
+    printf("Dump of XAB chain before $DISPLAY:\n");
+    for (x = xab_chain; x != NULL; x = x->xab$l_nxt)
+        dump_rms_block((uch *)x);
+#endif
+    /*
+     *  Get information on the file structure etc.
+     */
+    status = sys$display(&fab, 0, 0);
+    if (ERR(status))
+    {
+#ifdef DEBUG
+        printf("set_extra_field: sys$display for file %s:\n  error status = %d\n",
+               z->name, status);
+#endif
+        goto err_exit;
+    }
+
+#ifdef DEBUG
+    printf("\nDump of XAB chain after $DISPLAY:\n");
+    for (x = xab_chain; x != NULL; x = x->xab$l_nxt)
+        dump_rms_block((uch *)x);
+#endif
+
+    fab.fab$l_xab = NULL;  /* Keep XABs */
+    status = sys$close(&fab);
+    if (ERR(status))
+    {
+#ifdef DEBUG
+        printf("set_extra_field: sys$close for file %s:\n  error status = %d\n",
+               z->name, status);
+#endif
+        goto err_exit;
+    }
+
+    extra_l = EXTL0 + nk * (XKEYL + EXTHL) + na * (XALLL + EXTHL);
+#ifndef OLD_COMPRESS
+    extra_l += PAD0 + (nk+na) * PAD;
+#endif
+
+    if ( (verlen = get_vms_version(verbuf, sizeof(verbuf))) > 0 )
+    {
+        extra_l += verlen + EXTHL;
+#ifndef OLD_COMPRESS
+        extra_l += PAD;
+#endif
+    }
+
+    if ((scan = xtra = (uch *) malloc( extra_l)) == (uch*)NULL)
+    {
+#ifdef DEBUG
+        printf(
+         "set_extra_field: Insufficient memory to allocate extra L buffer\n");
+#endif
+        goto err_exit;
+    }
+
+    if ((cxtra = (uch *) malloc( extra_l)) == (uch*)NULL)
+    {
+#ifdef DEBUG
+        printf(
+         "set_extra_field: Insufficient memory to allocate extra C buffer\n");
+#endif
+        goto err_exit;
+    }
+
+    if (verlen > 0)
+        scan = _compress_block((struct IZ_block *)scan, (uch *)verbuf,
+                               verlen, VERSIG);
+
+    /*
+     *  Zero all unusable fields to improve compression
+     */
+    fab.fab$b_fns = fab.fab$b_shr = fab.fab$b_dns = fab.fab$b_fac = 0;
+    fab.fab$w_ifi = 0;
+    fab.fab$l_stv = fab.fab$l_sts = fab.fab$l_ctx = 0;
+    fab.fab$l_fna = NULL;
+    fab.fab$l_nam = NULL;
+    fab.fab$l_xab = NULL;
+    fab.fab$l_dna = NULL;
+
+#ifdef DEBUG
+    dump_rms_block( (uch *)&fab );
+#endif
+    scan = _compress_block((struct IZ_block *)scan, (uch *)&fab, FABL, FABSIG);
+    for (x = xab_chain; x != NULL;)
+    {
+        int bln;
+        char *sig;
+        xabptr next;
+
+        next = (xabptr)(x->xab$l_nxt);
+        x->xab$l_nxt = 0;
+
+        switch (x->xab$b_cod)
+        {
+            case XAB$C_ALL:
+                bln = XALLL;
+                sig = XALLSIG;
+                break;
+            case XAB$C_KEY:
+                bln = XKEYL;
+                sig = XKEYSIG;
+                break;
+            case XAB$C_PRO:
+                bln = XPROL;
+                sig = XPROSIG;
+                break;
+            case XAB$C_FHC:
+                bln = XFHCL;
+                sig = XFHCSIG;
+                break;
+            case XAB$C_DAT:
+                bln = XDATL;
+                sig = XDATSIG;
+                break;
+            case XAB$C_RDT:
+                bln = XRDTL;
+                sig = XRDTSIG;
+                break;
+            default:
+                bln = 0;
+                sig = 0L;
+                break;
+        }
+        if (bln > 0)
+            scan = _compress_block((struct IZ_block *)scan, (uch *)x,
+                                   bln, sig);
+        x = next;
+    }
+
+    /* Copy xtra[] data into cxtra[]. */
+    memcpy( cxtra, xtra, (scan - xtra));
+
+    /* Set sizes and pointers. */
+    z->cext = z->ext = scan - xtra;
+    z->extra = (char*) xtra;
+    z->cextra = (char*) cxtra;
+
+    rc = RET_SUCCESS;
+
+err_exit:
+    /*
+     *  Give up all allocated blocks
+     */
+    for (x = (struct XAB *)xab_chain; x != NULL; )
+    {
+        struct XAB *next;
+        next = (xabptr)(x->xab$l_nxt);
+        if (x->xab$b_cod == XAB$C_ALL || x->xab$b_cod == XAB$C_KEY)
+            free(x);
+        x = next;
+    }
+    return rc;
+}
+
+static int get_vms_version(verbuf, len)
+char *verbuf;
+int len;
+{
+    int i = SYI$_VERSION;
+    int verlen = 0;
+    struct dsc$descriptor version;
+    char *m;
+
+    version.dsc$a_pointer = verbuf;
+    version.dsc$w_length  = len - 1;
+    version.dsc$b_dtype   = DSC$K_DTYPE_B;
+    version.dsc$b_class   = DSC$K_CLASS_S;
+
+    if (ERR(lib$getsyi(&i, 0, &version, &verlen, 0, 0)) || verlen == 0)
+        return 0;
+
+    /* Cut out trailing spaces "V5.4-3   " -> "V5.4-3" */
+    for (m = verbuf + verlen, i = verlen - 1; i > 0 && verbuf[i] == ' '; --i)
+        --m;
+    *m = 0;
+
+    /* Cut out release number "V5.4-3" -> "V5.4" */
+    if ((m = strrchr(verbuf, '-')) != NULL)
+        *m = 0;
+    return strlen(verbuf) + 1;  /* Transmit ending 0 too */
+}
+
+#define CTXSIG ((ulg)('CtXx'))
+
+typedef struct user_context
+{
+    ulg sig;
+    struct FAB *fab;
+    struct RAB *rab;
+    unsigned int size;
+    unsigned int rest;
+    int status;
+} Ctx, *Ctxptr;
+
+Ctx init_ctx =
+{
+        CTXSIG,
+        NULL,
+        NULL,
+        0L,
+        0L,
+        0
+};
+
+#define CTXL    sizeof(Ctx)
+#define CHECK_RAB(_r) ( (_r) != NULL &&                         \
+                        (_r) -> rab$b_bid == RAB$C_BID &&       \
+                        (_r) -> rab$b_bln == RAB$C_BLN &&       \
+                        (_r) -> rab$l_ctx != 0         &&       \
+                        (_r) -> rab$l_fab != NULL )
+
+
+#define BLOCK_BYTES 512
+
+/**************************
+ *   Function vms_open    *
+ **************************/
+struct RAB *vms_open(name)
+    char *name;
+{
+    struct RAB *rab;
+    struct FAB *fab;
+    struct XABFHC *fhc;
+    Ctxptr ctx;
+
+    if ((fab = (struct FAB *) malloc(FABL)) == (struct FAB *)NULL)
+        return NULL;
+    if ((rab = (struct RAB *) malloc(RABL)) == (struct RAB *)NULL)
+    {
+        free(fab);
+        return (struct RAB *)NULL;
+    }
+    if ((fhc = (struct XABFHC *) malloc(XFHCL)) == (struct XABFHC *)NULL)
+    {
+        free(rab);
+        free(fab);
+        return (struct RAB *)NULL;
+    }
+    if ((ctx = (Ctxptr) malloc(CTXL)) == (Ctxptr)NULL)
+    {
+        free(fhc);
+        free(fab);
+        free(rab);
+        return (struct RAB *)NULL;
+    }
+    *fab = cc$rms_fab;
+    *rab = cc$rms_rab;
+    *fhc = cc$rms_xabfhc;
+
+    fab->fab$l_fna = name;
+    fab->fab$b_fns = strlen(name);
+    fab->fab$b_fac = FAB$M_GET | FAB$M_BIO;
+    fab->fab$l_xab = (char*)fhc;
+
+    if (ERR(sys$open(fab)))
+    {
+        sys$close(fab);
+        free(fhc);
+        free(fab);
+        free(rab);
+        free(ctx);
+        return (struct RAB *)NULL;
+    }
+
+    rab->rab$l_fab = fab;
+    rab->rab$l_rop = RAB$M_BIO;
+
+    if (ERR(sys$connect(rab)))
+    {
+        sys$close(fab);
+        free(fab);
+        free(rab);
+        free(ctx);
+        return (struct RAB *)NULL;
+    }
+
+    *ctx = init_ctx;
+    ctx->rab = rab;
+    ctx->fab = fab;
+
+    if (fhc->xab$l_ebk == 0)
+    {
+        /* Only known size is all allocated blocks.
+           (This occurs with a zero-length file, for example.)
+        */
+        ctx->size =
+        ctx->rest = (fhc->xab$l_hbk) * BLOCK_BYTES;
+    }
+    else
+    {
+        /* Store normal (used) size in ->size.
+           If only one -V, store normal (used) size in ->rest.
+           If -VV, store allocated-blocks size in ->rest.
+        */
+        ctx->size =
+         ((fhc->xab$l_ebk)- 1) * BLOCK_BYTES + fhc->xab$w_ffb;
+        if (vms_native < 2)
+            ctx->rest = ctx->size;
+        else
+            ctx->rest = (fhc->xab$l_hbk) * BLOCK_BYTES;
+    }
+
+    free(fhc);
+    fab->fab$l_xab = NULL;
+    rab->rab$l_ctx = (unsigned) ctx;
+    return rab;
+}
+
+/**************************
+ *   Function vms_close   *
+ **************************/
+int vms_close(rab)
+    struct RAB *rab;
+{
+    struct FAB *fab;
+    Ctxptr ctx;
+
+    if (!CHECK_RAB(rab))
+        return RET_ERROR;
+    fab = (ctx = (Ctxptr)(rab->rab$l_ctx))->fab;
+    sys$close(fab);
+
+    free(fab);
+    free(rab);
+    free(ctx);
+
+    return RET_SUCCESS;
+}
+
+/**************************
+ *   Function vms_rewind  *
+ **************************/
+int vms_rewind(rab)
+    struct RAB *rab;
+{
+    Ctxptr ctx;
+
+    int status;
+    if (!CHECK_RAB(rab))
+        return RET_ERROR;
+
+    ctx = (Ctxptr) (rab->rab$l_ctx);
+    if (ERR(status = sys$rewind(rab)))
+    {
+        ctx->status = status;
+        return RET_ERROR;
+    }
+
+    ctx->status = 0;
+    ctx->rest = ctx->size;
+
+    return RET_SUCCESS;
+}
+
+
+#define KByte (2 * BLOCK_BYTES)
+#define MAX_READ_BYTES (32 * KByte)
+
+/**************************
+ *   Function vms_read    *
+ **************************/
+size_t vms_read(rab, buf, size)
+struct RAB *rab;
+char *buf;
+size_t size;
+/*
+ *      size must be greater or equal to 512 !
+ */
+{
+    int status;
+    Ctxptr ctx;
+
+    ctx = (Ctxptr)rab->rab$l_ctx;
+
+    if (!CHECK_RAB(rab))
+        return 0;
+
+    if (ctx -> rest == 0)
+        return 0;               /* Eof */
+
+    /* If request is smaller than a whole block, fail.
+       This really should never happen.  (assert()?)
+    */
+    if (size < BLOCK_BYTES)
+        return 0;
+
+    /* 2004-09-27 SMS.
+       Code here now resembles low-level QIO code in VMS_PK.C, but I
+       doubt that sys$read() will actually get past the official EOF.
+    */
+
+    /* Adjust request size as appropriate. */
+    if (size > MAX_READ_BYTES)
+    {
+        /* Restrict request to MAX_READ_BYTES. */
+        size = MAX_READ_BYTES;
+    }
+    else
+    {
+        /* Round odd-ball request up to the next whole block.
+           This really should never happen.  (assert()?)
+        */
+        size = (size + BLOCK_BYTES - 1)& ~(BLOCK_BYTES - 1);
+    }
+
+    /* Reduce "size" when next (last) read would overrun the EOF,
+       but never below one byte (so we'll always get a nice EOF).
+    */
+    if (size > ctx->rest)
+        size = ctx->rest;
+    if (size == 0)
+        size = 1;
+
+    rab->rab$l_ubf = buf;
+    rab->rab$w_usz = size;
+    status = sys$read(rab);
+
+    if (!ERR(status) && rab->rab$w_rsz > 0)
+    {
+        ctx -> status = 0;
+        ctx -> rest -= rab->rab$w_rsz;
+        return rab->rab$w_rsz;
+    }
+    else
+    {
+        ctx->status = (status==RMS$_EOF ? 0:status);
+        if (status == RMS$_EOF)
+                ctx -> rest = 0;
+        return 0;
+    }
+}
+
+/**************************
+ *   Function vms_error   *
+ **************************/
+int vms_error(rab)
+    struct RAB *rab;
+{
+    if (!CHECK_RAB(rab))
+        return RET_ERROR;
+    return ((Ctxptr) (rab->rab$l_ctx))->status;
+}
+
+
+#ifdef DEBUG
+static void dump_rms_block(p)
+    uch *p;
+{
+    uch bid, len;
+    int err;
+    char *type;
+    char buf[132];
+    int i;
+
+    err = 0;
+    bid = p[0];
+    len = p[1];
+    switch (bid)
+    {
+        case FAB$C_BID:
+            type = "FAB";
+            break;
+        case XAB$C_ALL:
+            type = "xabALL";
+            break;
+        case XAB$C_KEY:
+            type = "xabKEY";
+            break;
+        case XAB$C_DAT:
+            type = "xabDAT";
+            break;
+        case XAB$C_RDT:
+            type = "xabRDT";
+            break;
+        case XAB$C_FHC:
+            type = "xabFHC";
+            break;
+        case XAB$C_PRO:
+            type = "xabPRO";
+            break;
+        default:
+            type = "Unknown";
+            err = 1;
+            break;
+    }
+    printf("Block @%08X of type %s (%d).", p, type, bid);
+    if (err)
+    {
+        printf("\n");
+        return;
+    }
+    printf(" Size = %d\n", len);
+    printf(" Offset - Hex - Dec\n");
+    for (i = 0; i < len; i += 8)
+    {
+        int j;
+
+        printf("%3d - ", i);
+        for (j = 0; j < 8; j++)
+            if (i + j < len)
+                printf("%02X ", p[i + j]);
+            else
+                printf("   ");
+        printf(" - ");
+        for (j = 0; j < 8; j++)
+            if (i + j < len)
+                printf("%03d ", p[i + j]);
+            else
+                printf("    ");
+        printf("\n");
+    }
+}
+#endif /* DEBUG */
+
+#ifdef OLD_COMPRESS
+# define BC_METHOD      EB_IZVMS_BC00
+# define        COMP_BLK(to,tos,from,froms) _compress( from,to,froms )
+#else
+# define BC_METHOD      EB_IZVMS_BCDEFL
+# define        COMP_BLK(to,tos,from,froms) memcompress(to,tos,from,froms)
+#endif
+
+static uch *_compress_block(to,from,size,sig)
+register struct IZ_block *to;
+uch *from;
+int size;
+char *sig;
+{
+        ulg cl;
+        to -> sig =  *(ush*)IZ_SIGNATURE;
+        to -> bid =       *(ulg*)(sig);
+        to -> flags =           BC_METHOD;
+        to -> length =  size;
+#ifdef DEBUG
+        printf("\nmemcompr(%d,%d,%d,%d)\n",&(to->body[0]),size+PAD,from,size);
+#endif
+        cl = COMP_BLK( &(to->body[0]), size+PAD, from, size );
+#ifdef DEBUG
+        printf("Compressed to %d\n",cl);
+#endif
+        if (cl >= size)
+        {
+                memcpy(&(to->body[0]), from, size);
+                to->flags = EB_IZVMS_BCSTOR;
+                cl = size;
+#ifdef DEBUG
+                printf("Storing block...\n");
+#endif
+        }
+        return (uch*)(to) + (to->size = cl + EXTBSL + RESL) + EB_HEADSIZE;
+}
+
+#define NBITS 32
+
+static int _compress(from,to,size)
+uch *from,*to;
+int size;
+{
+    int off=0;
+    ulg bitbuf=0;
+    int bitcnt=0;
+    int i;
+
+#define _BIT(val,len)   {                       \
+        if (bitcnt + (len) > NBITS)             \
+            while(bitcnt >= 8)                  \
+            {                                   \
+                to[off++] = (uch)bitbuf;        \
+                bitbuf >>= 8;                   \
+                bitcnt -= 8;                    \
+            }                                   \
+        bitbuf |= ((ulg)(val))<<bitcnt;         \
+        bitcnt += len;                          \
+    }
+
+#define _FLUSH  {                               \
+            while(bitcnt>0)                     \
+            {                                   \
+                to[off++] = (uch)bitbuf;        \
+                bitbuf >>= 8;                   \
+                bitcnt -= 8;                    \
+            }                                   \
+        }
+
+    for (i=0; i<size; i++)
+    {
+        if (from[i])
+        {
+                _BIT(1,1);
+                _BIT(from[i],8);
+        }
+        else
+            _BIT(0,1);
+    }
+    _FLUSH;
+    return off;
+}
+
+#endif /* !UTIL */
+
+#endif /* ndef VMS_PK_EXTRA */
+
+#endif /* VMS */
diff --git a/vms/vms_pk.c b/vms/vms_pk.c
new file mode 100644 (file)
index 0000000..d1467d3
--- /dev/null
@@ -0,0 +1,550 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *    vms_pk.c  by Igor Mandrichenko
+ *
+ *    version 2.0       20-Mar-1993
+ *                      Generates PKWARE version of VMS attributes
+ *                      extra field according to appnote 2.0.
+ *                      Uses low level QIO-ACP interface.
+ *    version 2.0-1     10-Apr-1993
+ *                      Save ACLs
+ *    version 2.1       24-Aug-1993
+ *                      By default produce 0x010C extra record ID instead of
+ *                      PKWARE's 0x000C. The format is mostly compatible with
+ *                      PKWARE.
+ *                      Incompatibility (?): zip produces multiple ACE
+ *                      fields.
+ *    version 2.1-1     Clean extra fields in vms_get_attributes().
+ *                      Fixed bug with EOF.
+ *    version 2.1-2     15-Sep-1995, Chr. Spieler
+ *                      Removed extra fields cleanup from vms_get_attributes().
+ *                      This is now done in zipup.c
+ *                      Modified (according to UnZip's vms.[ch]) the fib stuff
+ *                      for DEC C (AXP,VAX) support.
+ *    version 2.2       28-Sep-1995, Chr. Spieler
+ *                      Reorganized code for easier maintance of the two
+ *                      incompatible flavours (IM style and PK style) VMS
+ *                      attribute support.  Generic functions (common to
+ *                      both flavours) are now collected in a `wrapper'
+ *                      source file that includes one of the VMS attribute
+ *                      handlers.
+ *                      Made extra block header conforming to PKware's
+ *                      specification (extra block header has a length
+ *                      of four bytes, two bytes for a signature, and two
+ *                      bytes for the length of the block excluding this
+ *                      header.
+ *    version 2.2-1     19-Oct-1995, Chr. Spieler
+ *                      Fixed bug in CRC calculation.
+ *                      Use official PK VMS extra field id.
+ *    version 2.2-2     21-Nov-1997, Chr. Spieler
+ *                      Fixed bug in vms_get_attributes() for directory
+ *                      entries (access to uninitialized ioctx record).
+ *                      Removed unused second arg for vms_open().
+ *    version 2.2-3     04-Apr-1999, Chr. Spieler
+ *                      Changed calling interface of vms_get_attributes()
+ *                      to accept a void pointer as first argument.
+ *    version 2.2-4     26-Jan-2002, Chr. Spieler
+ *                      Modified vms_read() to handle files larger than 2GByte
+ *                      (up to size limit of "unsigned long", resp. 4GByte).
+ *    version 2.3.1     20-Oct-2004, Steven Schweda.
+ *                      Changed vms_read() to read all the allocated
+ *                      blocks in a file, for sure.  Changed the default
+ *                      chunk size from 16K to 32K.  Changed to use the
+ *                      new typedef for the ioctx structure.  Moved the
+ *                      VMS_PK_EXTRA test into here from VMS.C to allow
+ *                      more general automatic dependency generation.
+ */
+
+#ifdef VMS                      /* For VMS only ! */
+
+#ifdef VMS_PK_EXTRA
+
+#include <ssdef.h>
+
+#ifndef VMS_ZIP
+#define VMS_ZIP
+#endif
+
+#include "vms.h"
+#include "vmsdefs.h"
+
+#ifndef ERR
+#define ERR(x) (((x)&1)==0)
+#endif
+
+#ifndef NULL
+#define NULL (void*)(0L)
+#endif
+
+#ifndef UTIL
+
+static PK_info_t PK_def_info =
+{
+        ATR$C_RECATTR,  ATR$S_RECATTR,  {0},
+        ATR$C_UCHAR,    ATR$S_UCHAR,    {0},
+        ATR$C_CREDATE,  ATR$S_CREDATE,  {0},
+        ATR$C_REVDATE,  ATR$S_REVDATE,  {0},
+        ATR$C_EXPDATE,  ATR$S_EXPDATE,  {0},
+        ATR$C_BAKDATE,  ATR$S_BAKDATE,  {0},
+        ATR$C_ASCDATES, sizeof(ush),    0,
+        ATR$C_UIC,      ATR$S_UIC,      {0},
+        ATR$C_FPRO,     ATR$S_FPRO,     {0},
+        ATR$C_RPRO,     ATR$S_RPRO,     {0},
+        ATR$C_JOURNAL,  ATR$S_JOURNAL,  {0}
+};
+
+/* File description structure for Zip low level I/O */
+typedef struct
+{
+    struct iosb         iosb;
+    long                vbn;
+    unsigned int        size;
+    unsigned int        rest;
+    int                 status;
+    ush                 chan;
+    ush                 chan_pad;       /* alignment member */
+    long                acllen;
+    uch                 aclbuf[ATR$S_READACL];
+    PK_info_t           PKi;
+} ioctx_t;
+
+
+/* Forward declarations of public functions: */
+ioctx_t *vms_open(char *file);
+size_t  vms_read(register ioctx_t *ctx,
+                 register char *buf, register size_t size);
+int  vms_error(ioctx_t *ctx);
+int  vms_rewind(ioctx_t *ctx);
+int  vms_get_attributes(ioctx_t *ctx, struct zlist far *z,
+                        iztimes *z_utim);
+int  vms_close(ioctx_t *ctx);
+
+
+#define BLOCK_BYTES 512
+
+
+/*---------------*
+ |  vms_open()   |
+ *---------------*
+ |  This routine opens file for reading fetching its attributes.
+ |  Returns pointer to file description structure.
+ */
+
+ioctx_t *vms_open(file)
+char *file;
+{
+    static struct atrdef        Atr[VMS_MAX_ATRCNT+1];
+    static struct NAM           Nam;
+    static struct fibdef        Fib;
+    static struct dsc$descriptor FibDesc =
+        {sizeof(Fib),DSC$K_DTYPE_Z,DSC$K_CLASS_S,(char *)&Fib};
+    static struct dsc$descriptor_s DevDesc =
+        {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,&Nam.nam$t_dvi[1]};
+    static struct dsc$descriptor_s FileName =
+        {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
+    static char EName[NAM$C_MAXRSS];
+    static char RName[NAM$C_MAXRSS];
+
+    struct FAB  Fab;
+    register ioctx_t *ctx;
+    register struct fatdef *fat;
+    int status;
+    int i;
+    ulg efblk, hiblk;
+
+    if ( (ctx=(ioctx_t *)malloc(sizeof(ioctx_t))) == NULL )
+        return NULL;
+    ctx -> PKi = PK_def_info;
+
+#define FILL_REQ(ix,id,b)   {       \
+    Atr[ix].atr$l_addr = GVTC &(b);      \
+    Atr[ix].atr$w_type = (id);      \
+    Atr[ix].atr$w_size = sizeof(b); \
+}
+
+    FILL_REQ(0, ATR$C_RECATTR,  ctx->PKi.ra);
+    FILL_REQ(1, ATR$C_UCHAR,    ctx->PKi.uc);
+    FILL_REQ(2, ATR$C_REVDATE,  ctx->PKi.rd);
+    FILL_REQ(3, ATR$C_EXPDATE,  ctx->PKi.ed);
+    FILL_REQ(4, ATR$C_CREDATE,  ctx->PKi.cd);
+    FILL_REQ(5, ATR$C_BAKDATE,  ctx->PKi.bd);
+    FILL_REQ(6, ATR$C_ASCDATES, ctx->PKi.rn);
+    FILL_REQ(7, ATR$C_JOURNAL,  ctx->PKi.jr);
+    FILL_REQ(8, ATR$C_RPRO,     ctx->PKi.rp);
+    FILL_REQ(9, ATR$C_FPRO,     ctx->PKi.fp);
+    FILL_REQ(10,ATR$C_UIC,      ctx->PKi.ui);
+    FILL_REQ(11,ATR$C_ACLLENGTH,ctx->acllen);
+    FILL_REQ(12,ATR$C_READACL,  ctx->aclbuf);
+
+    Atr[13].atr$w_type = 0;     /* End of ATR list */
+    Atr[13].atr$w_size = 0;
+    Atr[13].atr$l_addr = GVTC NULL;
+
+    /* initialize RMS structures, we need a NAM to retrieve the FID */
+    Fab = cc$rms_fab;
+    Fab.fab$l_fna = file ; /* name of file */
+    Fab.fab$b_fns = strlen(file);
+    Fab.fab$l_nam = &Nam; /* FAB has an associated NAM */
+    Nam = cc$rms_nam;
+    Nam.nam$l_esa = EName; /* expanded filename */
+    Nam.nam$b_ess = sizeof(EName);
+    Nam.nam$l_rsa = RName; /* resultant filename */
+    Nam.nam$b_rss = sizeof(RName);
+
+    /* do $PARSE and $SEARCH here */
+    status = sys$parse(&Fab);
+    if (!(status & 1)) return NULL;
+
+    /* search for the first file.. If none signal error */
+    status = sys$search(&Fab);
+    if (!(status & 1)) return NULL;
+
+    /* initialize Device name length, note that this points into the NAM
+         to get the device name filled in by the $PARSE, $SEARCH services */
+    DevDesc.dsc$w_length = Nam.nam$t_dvi[0];
+
+    status = sys$assign(&DevDesc,&ctx->chan,0,0);
+    if (!(status & 1)) return NULL;
+
+    FileName.dsc$a_pointer = Nam.nam$l_name;
+    FileName.dsc$w_length = Nam.nam$b_name+Nam.nam$b_type+Nam.nam$b_ver;
+
+    /* Initialize the FIB */
+    Fib.FIB$L_ACCTL = FIB$M_NOWRITE;
+    for (i=0;i<3;i++)
+        Fib.FIB$W_FID[i]=Nam.nam$w_fid[i];
+    for (i=0;i<3;i++)
+        Fib.FIB$W_DID[i]=Nam.nam$w_did[i];
+
+    /* Use the IO$_ACCESS function to return info about the file */
+    status = sys$qiow( 0, ctx->chan, (IO$_ACCESS| IO$M_ACCESS),
+                       &ctx->iosb, 0, 0, &FibDesc, &FileName, 0, 0,
+                       Atr, 0);
+
+    if (ERR(status) || ERR(status = ctx->iosb.status))
+    {
+        vms_close(ctx);
+        return NULL;
+    }
+
+    fat = (struct fatdef *)&(ctx -> PKi.ra);
+
+#define SWAPW(x)        ( (((x)>>16)&0xFFFF) + ((x)<<16) )
+
+    efblk = SWAPW(fat->fat$l_efblk);
+    hiblk = SWAPW(fat->fat$l_hiblk);
+
+    if (efblk == 0)
+    {
+        /* Only known size is all allocated blocks.
+           (This occurs with a zero-length file, for example.)
+        */
+        ctx -> size =
+        ctx -> rest = hiblk * BLOCK_BYTES;
+    }
+    else
+    {
+        /* Store normal (used) size in ->size.
+           If only one -V, store normal (used) size in ->rest.
+           If multiple -V, store allocated-blocks size in ->rest.
+        */
+        ctx -> size =
+         ((efblk) - 1) * BLOCK_BYTES + fat -> fat$w_ffbyte;
+
+        if (vms_native < 2)
+            ctx -> rest = ctx -> size;
+        else
+            ctx -> rest = hiblk * BLOCK_BYTES;
+    }
+
+    ctx -> status = SS$_NORMAL;
+    ctx -> vbn = 1;
+    return ctx;
+}
+
+
+#define KByte (2 * BLOCK_BYTES)
+#define MAX_READ_BYTES (32 * KByte)
+
+/*----------------*
+ |   vms_read()   |
+ *----------------*
+ |   Reads file in (multi-)block-sized chunks into the buffer.
+ |   Stops on EOF. Returns number of bytes actually read.
+ |   Note: This function makes no sense (and will error) if the buffer
+ |   size ("size") is not a multiple of the disk block size (512).
+ */
+
+size_t vms_read( ctx, buf, size)
+ioctx_t *ctx;
+char *buf;
+size_t size;
+{
+    int act_cnt;
+    int rest_rndup;
+    int status;
+    unsigned int bytes_read = 0;
+
+    /* If previous read hit EOF, fail early. */
+    if (ctx -> status == SS$_ENDOFFILE)
+        return 0;               /* EOF. */
+
+    /* If no more expected to be read, fail early. */
+    if (ctx -> rest == 0)
+        return 0;               /* Effective EOF. */
+
+    /* If request is smaller than a whole block, fail.
+       This really should never happen.  (assert()?)
+    */
+    if (size < BLOCK_BYTES)
+        return 0;
+
+    /* Note that on old VMS VAX versions (like V5.5-2), QIO[W] may fail
+       with status %x0000034c (= %SYSTEM-F-IVBUFLEN, invalid buffer
+       length) when size is not a multiple of 512.  Thus the requested
+       size is boosted as needed, but the IOSB byte count returned is
+       reduced when it exceeds the actual bytes remaining (->rest).
+    */
+
+    /* Adjust request size as appropriate. */
+    if (size > MAX_READ_BYTES)
+    {
+        /* Restrict request to MAX_READ_BYTES. */
+        size = MAX_READ_BYTES;
+    }
+    else
+    {
+        /* Round odd-ball request up to the next whole block.
+           This really should never happen.  (assert()?)
+        */
+        size = (size+ BLOCK_BYTES- 1)& ~(BLOCK_BYTES- 1);
+    }
+    rest_rndup = (ctx -> rest+ BLOCK_BYTES- 1)& ~(BLOCK_BYTES- 1);
+
+    /* Read (QIOW) until error or "size" bytes have been read. */
+    do
+    {
+        /* Reduce "size" when next (last) read would overrun the EOF,
+           but never below one block (so we'll always get a nice EOF).
+        */
+        if (size > rest_rndup)
+            size = rest_rndup;
+
+        status = sys$qiow( 0, ctx->chan, IO$_READVBLK,
+            &ctx->iosb, 0, 0,
+            buf, size, ctx->vbn, 0, 0, 0);
+
+        /* If initial status was good, use final status. */
+        if ( !ERR(status) )
+                status = ctx->iosb.status;
+
+        if ( !ERR(status) || status == SS$_ENDOFFILE )
+        {
+            act_cnt = ctx->iosb.count;
+            /* Ignore whole-block boost when remainder is smaller. */
+            if (act_cnt > ctx->rest)
+            {
+                act_cnt = ctx->rest;
+                status = SS$_ENDOFFILE;
+            }
+            /* Adjust counters/pointers according to delivered bytes. */
+            size -= act_cnt;
+            buf += act_cnt;
+            bytes_read += act_cnt;
+            ctx->vbn += ctx->iosb.count/ BLOCK_BYTES;
+        }
+
+    } while ( !ERR(status) && (size > 0) );
+
+    if (!ERR(status))
+    {
+        /* Record any successful status as SS$_NORMAL. */
+        ctx -> status = SS$_NORMAL;
+    }
+    else if (status == SS$_ENDOFFILE)
+    {
+        /* Record EOF as SS$_ENDOFFILE.  (Ignore error status codes?) */
+        ctx -> status = SS$_ENDOFFILE;
+    }
+
+    /* Decrement bytes-to-read.  Return the total bytes read. */
+    ctx -> rest -= bytes_read;
+
+    return bytes_read;
+}
+
+/*-----------------*
+ |   vms_error()   |
+ *-----------------*
+ |   Returns whether last operation on the file caused an error
+ */
+
+int vms_error(ctx)
+ioctx_t *ctx;
+{   /* EOF is not actual error */
+    return ERR(ctx->status) && (ctx->status != SS$_ENDOFFILE);
+}
+
+/*------------------*
+ |   vms_rewind()   |
+ *------------------*
+ |   Rewinds file to the beginning for the next vms_read().
+ */
+
+int vms_rewind(ctx)
+ioctx_t *ctx;
+{
+    ctx -> vbn = 1;
+    ctx -> rest = ctx -> size;
+    return 0;
+}
+
+/*--------------------------*
+ |   vms_get_attributes()   |
+ *--------------------------*
+ |   Malloc a PKWARE extra field and fill with file attributes. Returns
+ |   error number of the ZE_??? class.
+ |   If the passed ioctx record "FILE *" pointer is NULL, vms_open() is
+ |   called to fetch the file attributes.
+ |   When `vms_native' is not set, a generic "UT" type timestamp extra
+ |   field is generated instead.
+ |
+ |   2004-11-11 SMS.
+ |   Changed to use separate storage for ->extra and ->cextra.  Zip64
+ |   processing may move (reallocate) one and not the other.
+ */
+
+int vms_get_attributes(ctx, z, z_utim)
+ioctx_t *ctx;           /* Internal file control structure. */
+struct zlist far *z;    /* Zip entry to compress. */
+iztimes *z_utim;
+{
+    byte    *p;
+    byte    *xtra;
+    byte    *cxtra;
+    struct  PK_header    *h;
+    extent  l;
+    int     notopened;
+
+    if ( !vms_native )
+    {
+#ifdef USE_EF_UT_TIME
+        /*
+         *  A `portable' zipfile entry is created. Create an "UT" extra block
+         *  containing UNIX style modification time stamp in UTC, which helps
+         *  maintaining the `real' "last modified" time when the archive is
+         *  transfered across time zone boundaries.
+         */
+#  ifdef IZ_CHECK_TZ
+        if (!zp_tz_is_valid)
+            return ZE_OK;       /* skip silently if no valid TZ info */
+#  endif
+
+        if ((xtra = (uch *) malloc( EB_HEADSIZE + EB_UT_LEN( 1))) == NULL)
+            return ZE_MEM;
+
+        if ((cxtra = (uch *) malloc( EB_HEADSIZE + EB_UT_LEN( 1))) == NULL)
+            return ZE_MEM;
+        /* Fill xtra[] with data. */
+        xtra[ 0] = 'U';
+        xtra[ 1] = 'T';
+        xtra[ 2] = EB_UT_LEN(1);        /* length of data part of e.f. */
+        xtra[ 3] = 0;
+        xtra[ 4] = EB_UT_FL_MTIME;
+        xtra[ 5] = (byte) (z_utim->mtime);
+        xtra[ 6] = (byte) (z_utim->mtime >> 8);
+        xtra[ 7] = (byte) (z_utim->mtime >> 16);
+        xtra[ 8] = (byte) (z_utim->mtime >> 24);
+
+        /* Copy xtra[] data into cxtra[]. */
+        memcpy( cxtra, xtra, (EB_HEADSIZE + EB_UT_LEN( 1)));
+
+        /* Set sizes and pointers. */
+        z->cext = z->ext = (EB_HEADSIZE + EB_UT_LEN( 1));
+        z->extra = (char*) xtra;
+        z->cextra = (char*) cxtra;
+
+#endif /* USE_EF_UT_TIME */
+
+        return ZE_OK;
+    }
+
+    notopened = (ctx == NULL);
+    if ( notopened && ((ctx = vms_open(z->name)) == NULL) )
+        return ZE_OPEN;
+
+    l = PK_HEADER_SIZE + sizeof(ctx->PKi);
+    if (ctx->acllen > 0)
+        l += PK_FLDHDR_SIZE + ctx->acllen;
+
+    if ((xtra = (uch *) malloc(l)) == NULL)
+        return ZE_MEM;
+
+    if ((cxtra = (uch *) malloc(l)) == NULL)
+        return ZE_MEM;
+
+    /* Fill xtra[] with data. */
+
+    h = (struct PK_header *) xtra;
+    h->tag = PK_SIGNATURE;
+    h->size = l - EB_HEADSIZE;
+    p = (h->data);
+
+    /* Copy default set of attributes */
+    memcpy(h->data, (char*)&(ctx->PKi), sizeof(ctx->PKi));
+    p += sizeof(ctx->PKi);
+
+    if ( ctx->acllen > 0 )
+    {
+        struct PK_field *f;
+
+        if (dosify)
+            zipwarn("file has ACL, may be incompatible with PKUNZIP","");
+
+        f = (struct PK_field *)p;
+        f->tag = ATR$C_ADDACLENT;
+        f->size = ctx->acllen;
+        memcpy((char *)&(f->value[0]), ctx->aclbuf, ctx->acllen);
+        p += PK_FLDHDR_SIZE + ctx->acllen;
+    }
+
+
+    h->crc32 = CRCVAL_INITIAL;                  /* Init CRC register */
+    h->crc32 = crc32(h->crc32, (uch *)(h->data), l - PK_HEADER_SIZE);
+
+    /* Copy xtra[] data into cxtra[]. */
+    memcpy( cxtra, xtra, l);
+
+    /* Set sizes and pointers. */
+    z->ext = z->cext = l;
+    z->extra = (char *) xtra;
+    z->cextra = (char *) cxtra;
+
+    if (notopened)              /* close "ctx", if we have opened it here */
+        vms_close(ctx);
+
+    return ZE_OK;
+}
+
+
+int vms_close(ctx)
+ioctx_t *ctx;
+{
+        sys$dassgn(ctx->chan);
+        free(ctx);
+        return 0;
+}
+
+#endif /* !_UTIL */
+
+#endif /* def VMS_PK_EXTRA */
+
+#endif /* VMS */
diff --git a/vms/vms_zip.rnh b/vms/vms_zip.rnh
new file mode 100644 (file)
index 0000000..c9599b0
--- /dev/null
@@ -0,0 +1,548 @@
+.!
+.!  File:       ZIP.RNH
+.!
+.!  Author:     Hunter Goatley
+.!
+.!  Date:       October 22, 1991
+.!
+.!  Description:
+.!
+.!      RUNOFF source file for portable ZIP on-line help for VMS.
+.!      Adapted from MANUAL, distributed with ZIP.
+.!
+.!      To build:       $ RUNOFF ZIP.RNH
+.!                      $ LIBR/HELP/INSERT libr ZIP
+.!
+.!  Modification history:
+.!
+.!      Hunter Goatley          22-OCT-1991 20:45
+.!              Genesis.
+.!      Jean-loup Gailly        25 March 92
+.!              Adaptation to zip 1.6.
+.!      Igor Mandrichenko       9-JUN-1992
+.!              Added explanation of -V option.
+.!      Jean-loup Gailly        14 June 92
+.!              Adaptation to zip 1.8.
+.!      Jean-loup Gailly        20 Aug 92
+.!              Adaptation to zip 1.9.
+.!      Jean-loup Gailly        31 Aug 93
+.!              Adaptation to zip 2.0.
+.!      Christian Spieler       20 Sep 93
+.!              Adaptation to zip 2.0 and OpenVMS completed.
+.!      Christian Spieler       05 Dec 95
+.!              Adaptation to zip 2.1, new options.
+.!      Christian Spieler       20 Jan 96
+.!              Changed -L and -v descriptions.
+.!      Christian Spieler       11 Feb 96
+.!              Added -X option.
+.!      Onno van der Linden,
+.!      Christian Spieler       13 Mar 96
+.!              Removed -ee option.
+.!      Christian Spieler       09 Feb 96
+.!              Updated copyright notice, Zip version.
+.!      Christian Spieler       21 Jul 97
+.!              Added -P, -R, -i@, -x@ and -tt options, modified for Zip 2.2.
+.!      Christian Spieler       14 Oct 97
+.!              unified spelling of "Info-ZIP", final cleanups for 2.2.
+.!
+.noflags
+.lm4 .rm72
+.indent -4
+1 ZIP
+.br
+Zip is a compression and file packaging utility for Unix, MSDOS, OS/2, and
+VMS.  It is analogous to a combination of tar and compress and is
+compatible with PKZIP (Phil Katz ZIP) for MSDOS systems.
+.sk
+There is a companion to Zip called UnZip (of course).  Zip and UnZip can
+work with files produced by PKZIP under MSDOS, and PKZIP and PKUNZIP can
+work with files produced by Zip.
+.sk
+Zip 2.2 is compatible with PKZIP 2.04.
+Note that PKUNZIP 1.10 cannot extract files produced by PKZIP 2.04
+or zip 2.2. You must use PKZIP 2.04g or unzip 5.0p1 (or later versions)
+to extract them.
+.sk
+For a brief help on Zip and Unzip, run each without specifying any
+parameters on the command line.
+.sk
+The program is useful for packaging a set of files for  distribution;
+for archiving files; and for saving disk space by temporarily compressing
+unused files or directories.
+.sk
+Zip puts one or more compressed files into a single "zip file", along with
+information about the files (name, path, date and time of last modification,
+protection, and check information to verify file integrity).  Zip can pack
+an entire directory structure in a zip file with a single command.
+Compression ratios of 2:1 to 3:1 are common for text files.  Zip has
+one compression method (deflation) and can also store files without
+compression.  It automatically chooses the better of the two for each file
+to be compressed.
+.sk
+Format:
+.sk;.lm+1;.literal
+ZIP [-options] [-b path] [-n suffixes] [-t mmddyyyy] [-tt mmddyyyy]
+    zipfile file(s) [-x list] [-i list]
+.end literal;.lm-1
+.!------------------------------------------------------------------------------
+.indent -4
+2 Options
+.br
+The default action of Zip is to add or replace zipfile entries from list, which
+can include the special name -@ to read names from SYS$INPUT.  The following
+list of options was taken from the on-line help generated when Zip is run
+without any command-line parameters:
+.sk
+.literal
+  -A   adjust self-extracting exe
+  -b   use "path" for temp files
+  -c   add one-line comments
+  -d   delete entries in zipfile
+  -D   do not add directory entries
+  -e   encrypt
+  -f   freshen: only changed files
+  -F   fix zipfile (-FF try harder)
+  -g   allow growing existing zipfile (unless updating or deleting)
+  -h   show the zip help screen
+  -i   include only names matching the following patterns
+  -i@  include only names matching the patterns in "file"
+  -j   junk (don't record) directory names
+  -J   junk (remove) prepended (SFX) stub
+  -k   simulate PKZIP made zipfile
+  -l   translate end-of-lines (LF -> CRLF)
+  -ll  translate end-of-lines (CRLF -> LF)
+  -L   show software license
+  -m   move into zipfile (delete files)
+  -n   don't compress theses suffixes
+  -o   make zipfile as old as latest entry
+  -P   encrypt with supplied "password" string
+  -q   quiet operation
+  -r   recurse into directories from specified path patterns
+  -R   recurse into subdirs from current dir, match filenames only
+  -t   only do files after "mmddyyyy"
+  -tt  only do files before "mmddyyyy"
+  -T   test zip file integrity (calls unzip)
+  -u   update: only changed or new files
+  -v   verbose messages/print version info
+  -V   save VMS file attributes
+  -w   append the VMS version number to name stored in zip file
+  -x   exclude all names matching the following patterns
+  -x@  exclude all names matching the patterns in "file"
+  -X   suppress storing of any extra file attributes
+  -z   add zipfile comment
+  -0   store only
+  -1   compress faster
+  -9   compress better
+  -@   read list of input files from SYS$INPUT
+.end literal
+.!------------------------------------------------------------------------------
+.indent -4
+2 How_To_Use_Zip
+.br
+The simplest use of Zip is as follows:
+.sk;.indent 10;$ zip stuff *
+.sk
+This will create the file "STUFF.ZIP" (assuming it does not exist) and put
+all the files in the current directory in STUFF.ZIP in a compressed form.
+The .ZIP suffix is added automatically, unless the zipfile name given
+contains a dot already.  This allows specifying suffixes other than ".ZIP".
+.sk
+To zip up an entire directory, the command:
+.sk;.indent 10
+$ zip -r foo *.*
+.sk
+will create the file "FOO.ZIP" containing all the files and directories in
+the in the current directory.  The "r" option means recurse through the
+directory structure. If you wish to recurse through the subdirectory [x.y]
+use the following syntax:
+.sk;.indent 10
+zip -r foo [x]y.dir
+.sk
+You may want to make a zip file that contains the files in [.FOO], but not
+record the directory name, FOO.  You can use the -j (junk path) option to
+leave off the path:
+.sk;.indent 10
+$ zip -j foo [.foo]*.*
+.sk
+You might be zipping to save disk space, in which case you could:
+.sk;.indent 10
+$ zip -rm foo *.txt
+.sk
+where the "m" option means "move".  This will delete all files matching
+*.txt after making FOO.ZIP.  No deletions will be done until the zip has
+completed with no errors.  This option is obviously more dangerous and
+should be used with care.
+.sk
+If the zip file already exists, these commands will replace existing or add
+new entries to the zip file.  For example, if you were really short on disk
+space, you might not have enough room simultaneously to hold the directory
+[.FOO] and the compressed FOO.ZIP.  In this case, you could do it in steps.
+If [.FOO] contained the subdirectories [.TOM], [.DICK], and [.HARRY], then
+you could:
+.sk;
+.indent 10;$ zip -rm foo [.foo.tom]
+.indent 10;$ zip -rm foo [.foo.dick]
+.indent 10;$ zip -rm foo [.foo.harry]
+.sk
+where the first command would create FOO.ZIP, and the next two would add to
+it.  At the completion of each zip command, the files in the directory just
+zipped would be deleted, making room in which the next Zip command could
+work.
+.!------------------------------------------------------------------------------
+.indent -4
+2 Modifying_Existing_Zip_Files
+.br
+When given the name of an existing zip file with the above commands, Zip
+will replace identically named entries in the Zip file or add entries for
+new names.  For example, if FOO.ZIP exists and contains foo/file1 and
+foo/file2, and the directory [.FOO] contains the files foo/file1 and
+foo/file3, then:
+.sk;.indent 10
+$ zip -r foo [.foo]
+.sk
+will replace foo/file1 in foo.zip and add foo/file3 to FOO.ZIP.  After
+this, FOO.ZIP contains foo/file1, foo/file2, and foo/file3, with foo/file2
+unchanged from before.
+.sk
+When changing an existing zip file, Zip will write a temporary file with
+the new contents, and only replace the old one when the zip has completed
+with no errors. You can use
+the -b option to specify a different path (usually a different dev- ice) to
+put the temporary files in.  For example:
+.sk;.indent 10
+$ zip -b scratch$:[tmp] stuff *
+.sk
+will put the temporary zip file and the temporary compression files in the
+directory "SCRATCH$:[TMP]", copying over STUFF.ZIP in the current directory
+when done.
+.sk
+If you are only adding entries to a zip file, not replacing, and the -g
+option is given, then Zip grows (appends to) the file instead of copying
+it.  The danger of this is that if the operation fails, the original zip
+file is corrupted and lost.
+.sk
+There are two other ways to change or add entries in a zip file that are
+restrictions of simple addition or replacement.  The first is -u (update)
+which will add new entries to the zip file as before but will replace
+existing entries only if the modified date of the file is more recent than
+the date recorded for that name in the zip file.  For example:
+.sk;.indent 10
+$ zip -u stuff *
+.sk
+will add any new files in the current directory, and update any changed
+files in the zip file STUFF.ZIP.  Note that Zip will not try to pack
+STUFF.ZIP into itself when you do this. Zip will always exclude the zip
+file from the files on which to be operated.
+.sk
+The second restriction is -f (freshen) which, like update, will only
+replace entries with newer files; unlike update, will not add files that
+are not already in the zip file. For this option, you may want to simply
+freshen all of the files that are in the specified zip file.  To do this
+you would simply:
+.sk;.indent 10
+$ zip -f foo
+.sk
+Note that the -f option with no arguments freshens all the entries in the
+zip file.  The same is true of -u, and hence "zip -u foo" and "zip -f foo"
+both do the same thing.
+.sk
+This command should be run from the same directory from which the original
+zip command was run, since paths stored in zip files are always relative.
+.sk
+Another restriction that can be used with adding, updating, or freshening
+is -t (time), which will not operate on files modified earlier than the
+specified date.  For example:
+.sk;.indent 10
+$ zip -rt 12071991 infamy [.FOO]*.*
+.sk
+will add all the files in [.FOO] and its subdirectories that were last
+modified on December 7, 1991, or later to the zip file INFAMY.ZIP.
+.sk
+Also, files can be explicitly excluded using the -x option:
+.sk;.indent 10
+$ zip -r foo [.FOO] -x *.obj
+.sk
+which will zip up the contents of [.FOO] into FOO.ZIP but exclude all the
+files that end in ".OBJ".
+.sk
+The last operation is -d (delete) which will remove entries from a zip
+file.  An example might be:
+.sk;.indent 10
+$ zip -d foo foo/harry/*.* *.obj
+.sk
+which will remove all of the files that start with "foo/harry/" and all of
+the files that end with ".OBJ" (in any path).
+.sk
+Under VMS, -d is case sensitive when it matches names in the zip file.
+This allows deleting names that were zipped on other systems, but requires
+that the names be entered in upper case if they were zipped on an MSDOS
+system (by PKZIP or in PKZIP compatibility mode), so that the names can be
+found in the zip file and deleted.
+.!------------------------------------------------------------------------------
+.indent -4
+2 More_Options
+.br
+As mentioned before, Zip will use the best of two methods: deflate or store.
+The option -0 will force Zip to use store on all files. For example:
+.sk;.indent 10
+zip -r0 foo foo.dir
+.sk
+will zip up the directory foo into foo.zip using only store.
+.sk
+The speed of deflation can also be controlled with options -1 (fastest
+method but less compression) to -9 (best compression but slower). The
+default value is -6. For example:
+.sk;.indent 10
+zip -r8 foo foo.dir
+.sk
+In nearly all cases, a file that is already compressed cannot be compressed
+further by Zip, or if it can, the effect is minimal.  The -n option
+prevents Zip from trying to compress files that have the
+given suffixes.  Such files are simply stored (0%
+compression) in the
+output zip file, so that Zip doesn't waste its time trying to compress
+them. The suffixes are separated by
+either colons or semicolons.  For example, in DCL:
+.sk
+.indent 10;$ zip -rn ".Z:.zip:.tiff:.gif:.snd" foo [.FOO]*.*
+.sk
+will put everything in [.FOO] into FOO.ZIP, but will store any files that end
+in .Z, .ZIP, .TIFF, .GIF, or .SND without trying to compress them.  (Image and
+sound files often have their own specialized compression methods.)
+The default suffix list is ".Z:.zip;.zoo:.arc:.lzh:.arj".
+The environment variable ZIPOPT can be used to change this default. For
+example:
+.sk
+.indent 10;$ ZIPOPT == "-n .Z:.zip:.tiff:.gif:.snd"
+.sk
+The variable ZIPOPT can be used for any option (except -i and -x)
+and can include several options.
+.sk
+For VMS Zip, the alternatively environment variable name ZIP_OPTS may
+be used, if a more "VMS-like" name is prefered. If both ZIPOPT and
+ZIP_OPTS are present (and do not equate to whitespace only),
+the content of ZIPOPT takes precedence and ZIP_OPTS is ignored.
+.sk
+Under Unix, Zip will store the full path (relative to the current path)
+and name of the file (or just the name if -j is specified) in the zip
+file along with the Unix attributes, and it will mark the entry as made
+under Unix.  If the zip file is intended for PKUNZIP under MSDOS, then
+the -k (Katz) option should be used to attempt to convert the names and
+paths to conform to MSDOS, store only the MSDOS attribute (just the
+user write attribute from Unix), and mark the entry as made under MSDOS
+(even though it wasn't).
+.sk
+The -o (older) option will set the "last modified" time of the zip file to
+the latest "last modified" time of the entries in the zip file.  This can
+be used without any other operations, if desired.  For example:
+.sk;.indent 10
+$ zip -o foo
+.sk
+will change the last modified time of FOO.ZIP to the latest time of the
+entries in FOO.ZIP.
+.sk
+The -e and -c options operate on all files updated or added to the zip
+file.  Encryption (-e) will prompt for a password on the terminal and will
+not echo the password as it is typed (if SYS$COMMAND is not a TTY, Zip will
+exit with an error). New zip entries will be encrypted using that password.
+For added peace of mind, Zip will prompt for the password a second time,
+checking that the two inputs are the same before using it.
+.sk
+One-line comments can be added for each file with the -c option.  The zip
+file operations (adding or updating) will be done first, and you will then
+be prompted for a one-line comment for each file.  You can then enter the
+comment followed by return, or just return for no comment.
+.sk
+The -z option will prompt you for a multi-line comment for the entire zip
+file.  This option can be used by itself, or in combination with other
+options.  The comment is ended by a line containing just a period, or an
+end of file condition (^D on Unix, ^Z on MSDOS, OS/2, and OpenVMS).
+.sk
+The -q (quiet) option eliminates the informational messages and comment
+prompts while Zip is operating.  This might be used in shell scripts, for
+example, or if the zip operation is being performed as a background task
+("$ spawn/nowait zip -q foo *.c").
+.sk
+Zip can take a list of file names to operate on from SYS$INPUT using the
+"-@"
+option.
+.!  In Unix, this option can be used with the find command to extend
+.!greatly the functionality of Zip. For example, to zip up all the C source
+.!files in the current directory and its subdirectories, you can:
+.!.sk
+.!find . -type f -name "*.[ch]" -print | zip source -@
+.!.sk
+.!Note that the pattern must be quoted to keep the shell from expanding it.
+.sk
+The -X option (remember to quote it!) suppresses saving of additional
+"extra file attributes" in the zipfile. Its effect is to disable the
+VMS only -V option (see below), and prevent storing of UNIX compatible
+GMT modification time stamps. These UNIX compatible GMT time stamps
+-- which are quite useful when transporting Zip archives world wide (but
+are only recognized by Info-ZIP's UnZip 5.20 or later) --
+are included in the zipfile unless -X or -V is specified (in case your
+version of Zip has the USE_EF_UT_TIME option compiled in).
+.sk
+Under VMS only, the -w option will append the version number of the files
+to the name and zip up multiple versions of files.  Without -w, Zip will
+only use the most recent version of the specified file(s).
+.sk
+One more option that valid only under VMS is -V option. This option saves
+all (hopefully) file attributes needed to make EXACT copy of the
+file after extraction from archive. To extract a file with saved attributes,
+use UnZip version 5.20 or later. Note that to specify this option you should
+quote it ("-V"). Be carefull: it's rather hard (if possible at all) to extract
+a file archived on VMS with this option specified on other systems. See
+documentation on UnZip for further information.
+.sk
+The -l option translates the Unix end-of-line character LF into the
+MSDOS convention CR LF. This option should not be used on binary files.
+This option can be used on Unix or VMS if the zip file is intended for
+PKUNZIP under MSDOS.
+.sk
+If Zip is run with the -h option, or with no arguments and standard output is
+a terminal, the license and the command-argument and option help is shown.
+.sk
+The -L option shows the Zip license.
+.sk
+The -v option, when given as the only command line argument, directs Zip to
+display diagnostic information that shows when and how the executable was
+built and set up. This includes info on used compiler and compiler version
+(if available) as well as any optional compile time feature flags.
+Additionally, the content of the environment variables
+(logical names) read by Zip for runtime configuration are shown. This
+information is especially valuable when reporting problems or bugs.
+.!------------------------------------------------------------------------------
+.indent -4
+2 Diagnostics
+.br
+       On VMS, Zip's UNIX style exit values are mapped into proper
+       VMS status codes:
+.literal
+   1                                  (success)  normal exit,
+   (0x7fff0000 + 16*Zip_error_level)  warnings
+   (0x7fff0002 + 16*Zip_error_level)  normal errors
+   (0x7fff0004 + 16*Zip_error_level)  fatal errors
+.end literal
+
+       The Zip error level (or exit code) approximates the exit
+       codes defined by PKWARE and takes on the following values:
+.literal
+
+  VMS        Zip      Type of error
+  severity   errcode
+    -          0      normal; no errors or warnings detected.
+    F          2      unexpected end of zip file.
+    E          3      a generic error in the  zipfile  format  was
+                      detected.   Processing  may  have  completed
+                      successfully anyway;  some  broken  zipfiles
+                      created by other archivers have simple work-
+                      arounds.
+    F          4      zip was unable to allocate memory for one or
+                      more  buffers during program initialization.
+    F          5      a severe error in  the  zipfile  format  was
+                      detected.   Processing probably failed imme-
+                      diately.
+    E          6      entry too large to be split with zipsplit
+    E          7      invalid comment format
+    F          8      zip -T failed or out of memory
+    E          9      the user aborted zip prematurely  with  con-
+                      trol-C (or similar)
+    F          10     zip  encountered an error while using a temp
+                      file
+    F          11     read or seek error
+    W          12     zip has nothing to do
+    E          13     missing or empty zip file
+    F          14     error writing to a file
+    F          15     zip was unable to create a file to write to
+    E          16     bad command line parameters
+    E          18     zip could not open a specified file to read
+.end literal
+.!------------------------------------------------------------------------------
+.indent -4
+2 Copyright
+.br
+     Copyright (C) 1990-1997 Mark Adler, Richard B. Wales, Jean-loup Gailly,
+     Onno van der Linden, Christian Spieler and Igor Mandrichenko.
+     Permission is granted to any individual or institution to use, copy, or
+     redistribute this software so long as all of the original files are
+     included, that it is not sold for profit, and that this copyright
+     notice is retained.
+.sk
+     LIKE ANYTHING ELSE THAT'S FREE, ZIP AND ITS ASSOCIATED UTILITIES
+     ARE PROVIDED AS IS AND COME WITH NO WARRANTY OF ANY KIND, EITHER
+     EXPRESSED OR IMPLIED. IN NO EVENT WILL THE COPYRIGHT HOLDERS BE
+     LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE.
+.sk
+     Please send bug reports or comments by email to:
+     Zip-Bugs@lists.wku.edu.  For bug reports, please include
+     the version of Zip (see zip -h), the make options you used to
+     compile it (see zip -v), the machine and operating system you are using,
+     and as much additional information as possible.
+     Thank you for your support.
+.!------------------------------------------------------------------------------
+.indent -4
+2 Acknowledgements
+.br
+     Thanks to R. P. Byrne  for  his  Shrink.Pas  program,  which
+     inspired  this  project, and from which the shrink algorithm
+     was stolen; to Phil Katz for placing in  the  public  domain
+     the  zip  file format, compression format, and .ZIP filename
+     extension, and for accepting minor changes to the file  for-
+     mat; to Steve Burg for clarifications on the deflate format;
+     to Keith Petersen, Rich Wales, Hunter Goatley and Mark Adler
+     for  providing  a mailing list and ftp site for the Info-ZIP
+     group to use; and most importantly, to  the  Info-ZIP  group
+     itself  (listed in the file infozip.who) without whose tire-
+     less testing and bug-fixing efforts a portable zip would not
+     have  been  possible.   Finally  we should thank (blame) the
+     first Info-ZIP moderator, David Kirschbaum, for  getting  us
+     into  this  mess  in  the  first place.
+.!------------------------------------------------------------------------------
+.indent -4
+2 Bugs
+.sk
+     Zip 2.2 is not compatible with PKUNZIP 1.10. Use Zip 1.1 instead
+     to produce zip archives which can be extracted by PKUNZIP 1.10.
+.sk
+     WARNING: zip files produced by this version of zip must not be
+     *updated* by zip 1.0 or PKZIP 1.10 or PKZIP 1.93a, if they contain
+     encrypted members, or if they have been produced in a pipe or on a non
+     seekable device. The old versions of zip or pkzip would destroy the
+     zip structure. The old versions can list the contents of the zip file
+     but cannot extract it anyway (because of the new compression algorithm).
+     If you do not use encryption and use regular disk files, you do
+     not have to care about this problem.
+.sk
+     Under VMS, not all of the odd file formats are treated properly.
+     Only zip files of format stream-LF and fixed length 512 byte are
+     expected to work with Zip.  Others can be converted using Rahul
+     Dhesi's BILF program.  This version of Zip handles some of the
+     conversion internally.  The use of the "-V" option to save the
+     VMS attributes should work without problem for at least all types
+     of sequential files.  Beginning with Zip 2.2, the "-V" option uses
+     a new format to store the VMS attributes that should now allow
+     proper restoration of all sorts of indexed files. It has been
+     approved that there are problems with VMS UnZip to restore some
+     indexed files which were saved with previous versions of Zip.
+.sk
+     When using Kermit to transfer zip files from VMS to MSDOS, type "set
+     file type block" on the VMS side.  When transfering from MSDOS to VMS,
+     type "set file type fixed" on the VMS machine.  In both cases, type
+     "set file type binary" on MSDOS.
+.sk
+     Under VMS, zip hangs for file specification that uses DECnet
+     syntax (foo::*.*).
+.sk
+     LIKE ANYTHING ELSE THAT'S FREE, ZIP AND ITS ASSOCIATED UTILITIES
+     ARE PROVIDED AS IS AND COME WITH NO WARRANTY OF ANY KIND, EITHER
+     EXPRESSED OR IMPLIED. IN NO EVENT WILL THE COPYRIGHT HOLDERS BE
+     LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE.
+.sk
+     That having been said, please send any problems or comments
+     via email to the Internet address Zip-Bugs@lists.wku.edu.  For
+     bug reports, please include the version of Zip, the make
+     options you used to compile it, the machine and operating
+     system you are using, and as much additional information as
+     possible.  Thank you for your support.
+.!------------------------------------------------------------------------------
diff --git a/vms/vmsdefs.h b/vms/vmsdefs.h
new file mode 100644 (file)
index 0000000..d5ca610
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+  vmsdefs.h
+
+  Contents of three header files from Joe
+  Meadows' FILE program.  Used by vmsmunch
+
+        06-Apr-1994     Jamie Hanrahan  jeh@cmkrnl.com
+                        Moved "contents of three header files" from
+                        VMSmunch.h to VMSdefs.h .
+
+        16-Sep-1995     Christian Spieler
+                        Added #pragma (no)member_alignment directives
+                        to achieve compatibility with DEC C and Alpha AXP
+
+        05-Oct-1995     Christian Spieler
+                        Revised fatdef, fchdef, fjndef to achieve closer
+                        compatibility with DEC's system include header files
+                        supplied with C version 4.0 and newer.
+
+        10-Oct-1995     Christian Spieler
+                        Use lowercase filenames for vms specific sources
+                        (VMSmunch.? -> vmsmunch.?, VMSdefs.h -> vmsdefs.h)
+
+        15-Dec-1995     Christian Spieler
+                        Removed the last "tabs" from the source.
+
+        24-Jun-1997     Onno van der Linden / Chr. Spieler
+                        Modifications to support the VMS port of GNU C 2.x.
+
+        27-Jul-1999     Chr. Spieler
+                        Added Info-ZIP copyright note for identification.
+
+  ---------------------------------------------------------------------------*/
+
+#ifndef __vmsdefs_h
+#define __vmsdefs_h 1
+
+#if defined(__DECC) || defined(__DECCXX)
+#pragma __nostandard
+#endif /* __DECC || __DECCXX */
+
+#if defined(__DECC) || defined(__DECCXX)
+#pragma __member_alignment __save
+#pragma __nomember_alignment
+#endif /* __DECC || __DECCXX */
+
+#if !(defined(__VAXC) || defined(VAXC)) || defined(__GNUC__)
+#define __struct struct
+#define __union union
+#else
+#define __struct variant_struct
+#define __union variant_union
+#endif /* !(__VAXC || VAXC) || __GNUC__ */
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+/*---------------------------------------------------------------------------
+    fatdef.h
+  ---------------------------------------------------------------------------*/
+
+/* This header file was created by Joe Meadows, and is not copyrighted
+   in any way. No guarantee is made as to the accuracy of the contents
+   of this header file. This header file was last modified on Sep. 22th,
+   1987. (Modified to include this statement) */
+
+#define FAT$K_LENGTH 32
+#define FAT$C_LENGTH 32
+#define FAT$S_FATDEF 32
+
+struct fatdef {
+  __union  {
+    unsigned char fat$b_rtype;          /* record type                      */
+    __struct  {
+      unsigned fat$v_rtype : 4;         /* record type subfield             */
+      unsigned fat$v_fileorg : 4;       /* file organization                */
+    } fat$r_rtype_bits;
+  } fat$r_rtype_overlay;
+# define FAT$S_RTYPE 4
+# define FAT$V_RTYPE 0
+#   define FAT$C_UNDEFINED 0
+#   define FAT$C_FIXED 1
+#   define FAT$C_VARIABLE 2
+#   define FAT$C_VFC 3
+#   define FAT$C_STREAM 4
+#   define FAT$C_STREAMLF 5
+#   define FAT$C_STREAMCR 6
+# define FAT$S_FILEORG 4
+# define FAT$V_FILEORG 4
+#   define FAT$C_SEQUENTIAL 0
+#   define FAT$C_RELATIVE 1
+#   define FAT$C_INDEXED 2
+#   define FAT$C_DIRECT 3
+  __union  {
+    unsigned char fat$b_rattrib;        /* record attributes                */
+    __struct  {
+      unsigned fat$v_fortrancc : 1;
+      unsigned fat$v_impliedcc : 1;
+      unsigned fat$v_printcc : 1;
+      unsigned fat$v_nospan : 1;
+      unsigned fat$v_msbrcw : 1;
+    } fat$r_rattrib_bits;
+  } fat$r_rattrib_overlay;
+#   define FAT$V_FORTRANCC 0
+#   define FAT$M_FORTRANCC 1
+#   define FAT$V_IMPLIEDCC 1
+#   define FAT$M_IMPLIEDCC 2
+#   define FAT$V_PRINTCC 2
+#   define FAT$M_PRINTCC 4
+#   define FAT$V_NOSPAN 3
+#   define FAT$M_NOSPAN 8
+#   define FAT$V_MSBRCW 4
+#   define FAT$M_MSBRCW 16
+  unsigned short int fat$w_rsize;       /* record size in bytes             */
+  __union
+  {
+    unsigned long int fat$l_hiblk;      /* highest allocated VBN            */
+    __struct
+    {
+      unsigned short int fat$w_hiblkh;  /* high order word                  */
+      unsigned short int fat$w_hiblkl;  /* low order word                   */
+    } fat$r_hiblk_fields;
+  } fat$r_hiblk_overlay;
+  __union
+  {
+    unsigned long int fat$l_efblk;      /* end of file VBN                  */
+    __struct
+    {
+      unsigned short int fat$w_efblkh;  /* high order word                  */
+      unsigned short int fat$w_efblkl;  /* low order word                   */
+    } fat$r_efblk_fields;
+  } fat$r_efblk_overlay;
+  unsigned short int fat$w_ffbyte;      /* first free byte in EFBLK         */
+  unsigned char fat$b_bktsize;          /* bucket size in blocks            */
+  unsigned char fat$b_vfcsize;          /* # of control bytes in VFC record */
+  unsigned short int fat$w_maxrec;      /* maximum record size in bytes     */
+  unsigned short int fat$w_defext;      /* default extend quantity          */
+  unsigned short int fat$w_gbc;         /* global buffer count              */
+  char fat$fill[8];
+  unsigned short int fat$w_versions;
+};
+
+#if !(defined(__VAXC) || defined(VAXC)) || defined(__GNUC__)
+#define fat$b_rtype fat$r_rtype_overlay.fat$b_rtype
+#define fat$v_rtype fat$r_rtype_overlay.fat$r_rtype_bits.fat$v_rtype
+#define fat$v_fileorg fat$r_rtype_overlay.fat$r_rtype_bits.fat$v_fileorg
+#define fat$b_rattrib fat$r_rattrib_overlay.fat$b_rattrib
+#define fat$v_fortrancc fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_fortrancc
+#define fat$v_impliedcc fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_impliedcc
+#define fat$v_printcc fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_printcc
+#define fat$v_nospan fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_nospan
+#define fat$v_msbrcw fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_msbrcw
+#define fat$l_hiblk fat$r_hiblk_overlay.fat$l_hiblk
+#define fat$w_hiblkh fat$r_hiblk_overlay.fat$r_hiblk_fields.fat$w_hiblkh
+#define fat$w_hiblkl fat$r_hiblk_overlay.fat$r_hiblk_fields.fat$w_hiblkl
+#define fat$l_efblk fat$r_efblk_overlay.fat$l_efblk
+#define fat$w_efblkh fat$r_efblk_overlay.fat$r_efblk_fields.fat$w_efblkh
+#define fat$w_efblkl fat$r_efblk_overlay.fat$r_efblk_fields.fat$w_efblkl
+#endif /* !(__VAXC || VAXC) || __GNUC__ */
+
+#define __FATDEF_LOADED 1       /* prevent inclusion of DECC's fatdef.h */
+
+/*---------------------------------------------------------------------------
+    fchdef.h
+  ---------------------------------------------------------------------------*/
+
+/* This header file was created by Joe Meadows, and is not copyrighted
+   in any way. No guarantee is made as to the accuracy of the contents
+   of this header file. This header file was last modified on Sep. 22th,
+   1987. (Modified to include this statement) */
+
+#define FCH$V_BADACL 0x00B
+#define FCH$M_BADACL (1 << FCH$V_BADACL)
+#define FCH$V_BADBLOCK 0x00E
+#define FCH$M_BADBLOCK (1 << FCH$V_BADBLOCK)
+#define FCH$V_CONTIG 0x007
+#define FCH$M_CONTIG (1 << FCH$V_CONTIG)
+#define FCH$V_CONTIGB 0x005
+#define FCH$M_CONTIGB (1 << FCH$V_CONTIGB)
+#define FCH$V_DIRECTORY 0x00D
+#define FCH$M_DIRECTORY (1 << FCH$V_DIRECTORY)
+#define FCH$V_ERASE 0x011
+#define FCH$M_ERASE (1 << FCH$V_ERASE)
+#define FCH$V_LOCKED 0x006
+#define FCH$M_LOCKED (1 << FCH$V_LOCKED)
+#define FCH$V_MARKDEL 0x00F
+#define FCH$M_MARKDEL (1 << FCH$V_MARKDEL)
+#define FCH$V_NOBACKUP 0x001
+#define FCH$M_NOBACKUP (1 << FCH$V_NOBACKUP)
+#define FCH$V_NOCHARGE 0x010
+#define FCH$M_NOCHARGE (1 << FCH$V_NOCHARGE)
+#define FCH$V_READCHECK 0x003
+#define FCH$M_READCHECK (1 << FCH$V_READCHECK)
+#define FCH$V_SPOOL 0x00C
+#define FCH$M_SPOOL (1 << FCH$V_SPOOL)
+#define FCH$V_WRITCHECK 0x004
+#define FCH$M_WRITCHECK (1 << FCH$V_WRITCHECK)
+#define FCH$V_WRITEBACK 0x002
+#define FCH$M_WRITEBACK (1 << FCH$V_WRITEBACK)
+
+struct fchdef  {
+  __union  {
+    int fch$$_fill_1;
+    __struct  {
+      unsigned fch$$_fill_31 : 8;
+      unsigned fch$v_vcc_state : 3;    /* VCC state bits              */
+      unsigned fch$$_fill_32 : 7;
+      unsigned fch$$_alm_state : 2;
+      unsigned fch$v_associated : 1;   /* ISO 9660 Associated file    */
+      unsigned fch$v_existence : 1;    /* ISO 9660 Existence file     */
+      unsigned fch$v_fill_6 : 2;
+    } fch$r_fill_1_chunks;
+    __struct  {
+      unsigned fch$v_wascontig : 1;
+      unsigned fch$v_nobackup : 1 ;
+      unsigned fch$v_writeback : 1;
+      unsigned fch$v_readcheck : 1;
+      unsigned fch$v_writcheck : 1;
+      unsigned fch$v_contigb : 1;
+      unsigned fch$v_locked : 1;
+      unsigned fch$v_contig : 1;
+      unsigned fch$$_fill_3 : 3;
+      unsigned fch$v_badacl : 1;
+      unsigned fch$v_spool : 1;
+      unsigned fch$v_directory : 1;
+      unsigned fch$v_badblock : 1;
+      unsigned fch$v_markdel : 1;
+      unsigned fch$v_nocharge : 1;
+      unsigned fch$v_erase : 1;
+      unsigned fch$$_fill_4 : 1;
+      unsigned fch$v_shelved : 1;
+      unsigned fch$v_scratch : 1;
+      unsigned fch$v_nomove : 1;
+      unsigned fch$v_noshelvable : 1;
+    } fch$r_fill_1_bits;
+  } fch$r_fch_union;
+};
+
+#if !(defined(__VAXC) || defined(VAXC)) || defined(__GNUC__)
+#define fch$v_vcc_state fch$r_fch_union.fch$r_fill_1_chunks.fch$v_vcc_state
+#define fch$v_associated fch$r_fch_union.fch$r_fill_1_chunks.fch$v_associated
+#define fch$v_existence fch$r_fch_union.fch$r_fill_1_chunks.fch$v_existence
+#define fch$v_wascontig fch$r_fch_union.fch$r_fill_1_bits.fch$v_wascontig
+#define fch$v_nobackup fch$r_fch_union.fch$r_fill_1_bits.fch$v_nobackup
+#define fch$v_writeback fch$r_fch_union.fch$r_fill_1_bits.fch$v_writeback
+#define fch$v_readcheck fch$r_fch_union.fch$r_fill_1_bits.fch$v_readcheck
+#define fch$v_writcheck fch$r_fch_union.fch$r_fill_1_bits.fch$v_writcheck
+#define fch$v_contigb fch$r_fch_union.fch$r_fill_1_bits.fch$v_contigb
+#define fch$v_locked fch$r_fch_union.fch$r_fill_1_bits.fch$v_locked
+#define fch$v_contig fch$r_fch_union.fch$r_fill_1_bits.fch$v_contig
+#define fch$v_badacl fch$r_fch_union.fch$r_fill_1_bits.fch$v_badacl
+#define fch$v_spool fch$r_fch_union.fch$r_fill_1_bits.fch$v_spool
+#define fch$v_directory fch$r_fch_union.fch$r_fill_1_bits.fch$v_directory
+#define fch$v_badblock fch$r_fch_union.fch$r_fill_1_bits.fch$v_badblock
+#define fch$v_markdel fch$r_fch_union.fch$r_fill_1_bits.fch$v_markdel
+#define fch$v_nocharge fch$r_fch_union.fch$r_fill_1_bits.fch$v_nocharge
+#define fch$v_erase fch$r_fch_union.fch$r_fill_1_bits.fch$v_erase
+#define fch$v_shelved fch$r_fch_union.fch$r_fill_1_bits.fch$v_shelved
+#define fch$v_scratch fch$r_fch_union.fch$r_fill_1_bits.fch$v_scratch
+#define fch$v_nomove fch$r_fch_union.fch$r_fill_1_bits.fch$v_nomove
+#define fch$v_noshelvable fch$r_fch_union.fch$r_fill_1_bits.fch$v_noshelvable
+#endif /* !(__VAXC || VAXC) || __GNUC__ */
+
+#define __FCHDEF_LOADED 1       /* prevent inclusion of DECC's fchdef.h */
+
+/*---------------------------------------------------------------------------
+    fjndef.h
+  ---------------------------------------------------------------------------*/
+
+/* This header file was created by Joe Meadows, and is not copyrighted
+   in any way. No guarantee is made as to the accuracy of the contents
+   of this header file. This header file was last modified on Sep. 22th,
+   1987. (Modified to include this statement) */
+
+#define FJN$M_ONLY_RU 1
+#define FJN$M_RUJNL 2
+#define FJN$M_BIJNL 4
+#define FJN$M_AIJNL 8
+#define FJN$M_ATJNL 16
+#define FJN$M_NEVER_RU 32
+#define FJN$M_JOURNAL_FILE 64
+#define FJN$S_FJNDEF 1
+struct fjndef  {
+  unsigned fjn$v_only_ru : 1;
+  unsigned fjn$v_rujnl : 1;
+  unsigned fjn$v_bijnl : 1;
+  unsigned fjn$v_aijnl : 1;
+  unsigned fjn$v_atjnl : 1;
+  unsigned fjn$v_never_ru : 1;
+  unsigned fjn$v_journal_file : 1;
+  unsigned fjn$v_fill_7 : 1;
+} ;
+
+#define __FJNDEF_LOADED 1       /* prevent inclusion of DECC's fjndef.h */
+
+/*---------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+    }
+#endif
+
+#if defined(__DECC) || defined(__DECCXX)
+#pragma __member_alignment __restore
+#endif /* __DECC || __DECCXX */
+
+#if defined(__DECC) || defined(__DECCXX)
+#pragma __standard
+#endif /* __DECC || __DECCXX */
+
+#endif /* !__vmsdefs_h */
diff --git a/vms/vmsmunch.c b/vms/vmsmunch.c
new file mode 100644 (file)
index 0000000..b40ef45
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#define module_name     VMSMUNCH
+#define module_version  "V1.3-4"
+/*
+ *  Modified by:
+ *
+ *    v1.3.1        O.v.d.Linden, C. Spieler            04-JUL-1998 14:35
+ *            Modified check that decides on the type of definitions for
+ *            FIB$W_FID etc. to support GNU C.
+ *
+ *    v1.3          Hunter Goatley                      14-SEP-1992 08:51
+ *            Added definitions of FIB$W_FID, FIB$W_DID, and
+ *            FIB$L_ACCTL to allow for the fact that fibdef
+ *            contains variant_unions under Alpha.
+ */
+/*---------------------------------------------------------------------------
+
+  vmsmunch.c                    version 1.2                     28 Apr 1992
+
+  This routine is a blatant and unrepentent appropriation of all the nasty
+  and difficult-to-do and complicated VMS shenanigans which Joe Meadows has
+  so magnificently captured in his FILE utility.  Not only that, it's even
+  allowed! (see below).  But let it be clear at the outset that Joe did all
+  the work; yea, verily, he is truly a godlike unit.
+
+  The appropriations and modifications herein were performed primarily by
+  him known as "Cave Newt," although the Info-ZIP working group probably had
+  their fingers in it somewhere along the line.  The idea is to put the raw
+  power of Joe's original routine at the disposal of various routines used
+  by UnZip (and Zip, possibly), not least among them the utime() function.
+  Read on for details...
+
+        01-SEP-1994     Richard Levitte <levitte@e.kth.se>
+                        If one of the fields given to VMSmunch are NULL,
+                        do not update the corresponding daytime.
+
+        18-JUL-1994     Hunter Goatley <goathunter@WKU.EDU>
+                        Fixed IO$_ACCESS call.
+
+        18-Jul-1994     Richard Levitte levitte@e.kth.se
+                        Changed VMSmunch() to deassign the channel before
+                        returning when an error has occured.
+
+        02-Apr-1994     Jamie Hanrahan  jeh@cmkrnl.com
+                        Moved definition of VMStimbuf struct from here
+                        to vmsmunch.h
+  ---------------------------------------------------------------------------
+
+  Usage (i.e., "interface," in geek-speak):
+
+     int VMSmunch( char *filename, int action, char *ptr );
+
+     filename   the name of the file on which to be operated, obviously
+     action     an integer which specifies what action to take
+     ptr        pointer to any extra item which may be needed (else NULL)
+
+  The possible values for the action argument are as follows:
+
+     GET_TIMES      get the creation and revision dates of filename; ptr
+                    must point to an empty VMStimbuf struct, as defined
+                    in vmsmunch.h
+                    (with room for at least 24 characters, including term.)
+     SET_TIMES      set the creation and revision dates of filename (utime
+                    option); ptr must point to a valid VMStimbuf struct,
+                    as defined in vmsmunch.h
+     GET_RTYPE      get the record type of filename; ptr must point to an
+                    integer which, on return, is set to the type (as defined
+                    in vmsdefs.h:  FAT$C_* defines)
+     CHANGE_RTYPE   change the record type to that specified by the integer
+                    to which ptr points; save the old record type (later
+                    saves overwrite earlier ones)
+     RESTORE_RTYPE  restore the record type to the previously saved value;
+                    or, if none, set it to "fixed-length, 512-byte" record
+                    format (ptr not used)
+
+  ---------------------------------------------------------------------------
+
+  Comments from FILE.C, a utility to modify file characteristics:
+
+     Written by Joe Meadows Jr, at the Fred Hutchinson Cancer Research Center
+     BITNET: JOE@FHCRCVAX
+     PHONE: (206) 467-4970
+
+     There are no restrictions on this code, you may sell it, include it
+     with any commercial package, or feed it to a whale.. However, I would
+     appreciate it if you kept this comment in the source code so that anyone
+     receiving this code knows who to contact in case of problems. Note that
+     I do not demand this condition..
+
+  ---------------------------------------------------------------------------*/
+
+
+
+#if defined(__DECC) || defined(__GNUC__)
+#pragma module module_name module_version
+#else
+#module module_name module_version
+#endif
+
+/*****************************/
+/*  Includes, Defines, etc.  */
+/*****************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <descrip.h>
+#include <rms.h>
+#include <iodef.h>
+#include <starlet.h>
+#include <atrdef.h>   /* this gets created with the c3.0 compiler */
+#include <fibdef.h>   /* this gets created with the c3.0 compiler */
+
+/*
+ *  Under Alpha (DEC C in VAXC mode) and under `good old' VAXC, the FIB unions
+ *  are declared as variant_unions.  DEC C (Alpha) in ANSI modes and third
+ *  party compilers which do not support `variant_union' define preprocessor
+ *  symbols to `hide' the "intermediate union/struct" names from the
+ *  programmer's API.
+ *  We check the presence of these defines and for DEC's FIBDEF.H defining
+ *  __union as variant_union to make sure we access the structure correctly.
+ */
+#if defined(fib$w_did) || (defined(__union) && (__union == variant_union))
+#  define FIB$W_DID     fib$w_did
+#  define FIB$W_FID     fib$w_fid
+#  define FIB$L_ACCTL   fib$l_acctl
+#else
+#  define FIB$W_DID     fib$r_did_overlay.fib$w_did
+#  define FIB$W_FID     fib$r_fid_overlay.fib$w_fid
+#  define FIB$L_ACCTL   fib$r_acctl_overlay.fib$l_acctl
+#endif
+
+#include "vmsmunch.h"  /* GET/SET_TIMES, RTYPE, etc. */
+#include "vmsdefs.h"   /* fatdef.h, etc. */
+
+static void asctim(char *time, long int binval[2]);
+static void bintim(char *time, long int binval[2]);
+
+/* from <ssdef.h> */
+#ifndef SS$_NORMAL
+#  define SS$_NORMAL    1
+#  define SS$_BADPARAM  20
+#endif
+
+
+/* On VAX, define Goofy VAX Type-Cast to obviate /standard = vaxc.
+   Otherwise, lame system headers on VAX cause compiler warnings.
+   (GNU C may define vax but not __VAX.)
+*/
+#ifdef vax
+# define __VAX 1
+#endif /* def vax */
+
+#ifdef __VAX
+# define GVTC (unsigned int)
+#else /* def __VAX */
+# define GVTC
+#endif /* def __VAX */
+
+
+
+/*************************/
+/*  Function VMSmunch()  */
+/*************************/
+
+int VMSmunch(
+    char  *filename,
+    int   action,
+    char  *ptr )
+{
+
+    /* original file.c variables */
+
+    static struct FAB Fab;
+    static struct NAM Nam;
+    static struct fibdef Fib; /* short fib */
+
+    static struct dsc$descriptor FibDesc =
+      {sizeof(Fib),DSC$K_DTYPE_Z,DSC$K_CLASS_S,(char *)&Fib};
+    static struct dsc$descriptor_s DevDesc =
+      {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,&Nam.nam$t_dvi[1]};
+    static struct fatdef Fat;
+    static union {
+      struct fchdef fch;
+      long int dummy;
+    } uchar;
+    static struct fjndef jnl;
+    static long int Cdate[2],Rdate[2],Edate[2],Bdate[2];
+    static short int revisions;
+    static unsigned long uic;
+#if defined(__DECC) || defined(__DECCXX)
+#pragma __member_alignment __save
+#pragma __nomember_alignment
+#endif /* __DECC || __DECCXX */
+    static union {
+      unsigned short int value;
+      struct {
+        unsigned system : 4;
+        unsigned owner : 4;
+        unsigned group : 4;
+        unsigned world : 4;
+      } bits;
+    } prot;
+#if defined(__DECC) || defined(__DECCXX)
+#pragma __member_alignment __restore
+#endif /* __DECC || __DECCXX */
+
+    static struct atrdef Atr[] = {
+      {sizeof(Fat),ATR$C_RECATTR, GVTC &Fat},          /* record attributes */
+      {sizeof(uchar),ATR$C_UCHAR, GVTC &uchar},    /* File characteristics */
+      {sizeof(Cdate),ATR$C_CREDATE, GVTC &Cdate[0]},   /* Creation date */
+      {sizeof(Rdate),ATR$C_REVDATE, GVTC &Rdate[0]},   /* Revision date */
+      {sizeof(Edate),ATR$C_EXPDATE, GVTC &Edate[0]},   /* Expiration date */
+      {sizeof(Bdate),ATR$C_BAKDATE, GVTC &Bdate[0]},   /* Backup date */
+      {sizeof(revisions),ATR$C_ASCDATES, GVTC &revisions}, /* number of revs */
+      {sizeof(prot),ATR$C_FPRO, GVTC &prot},           /* file protection  */
+      {sizeof(uic),ATR$C_UIC, GVTC &uic},              /* file owner */
+      {sizeof(jnl),ATR$C_JOURNAL, GVTC &jnl},          /* journal flags */
+      {0,0,0}
+    } ;
+
+    static char EName[NAM$C_MAXRSS];
+    static char RName[NAM$C_MAXRSS];
+    static struct dsc$descriptor_s FileName =
+      {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
+    static struct dsc$descriptor_s string = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
+    static short int DevChan;
+    static short int iosb[4];
+
+    static long int i,status;
+/*  static char *retval;  */
+
+
+    /* new VMSmunch variables */
+
+    static int  old_rtype=FAT$C_FIXED;   /* storage for record type */
+
+
+
+/*---------------------------------------------------------------------------
+    Initialize attribute blocks, parse filename, resolve any wildcards, and
+    get the file info.
+  ---------------------------------------------------------------------------*/
+
+    /* initialize RMS structures, we need a NAM to retrieve the FID */
+    Fab = cc$rms_fab;
+    Fab.fab$l_fna = filename;
+    Fab.fab$b_fns = strlen(filename);
+    Fab.fab$l_nam = &Nam; /* FAB has an associated NAM */
+    Nam = cc$rms_nam;
+    Nam.nam$l_esa = EName; /* expanded filename */
+    Nam.nam$b_ess = sizeof(EName);
+    Nam.nam$l_rsa = RName; /* resultant filename */
+    Nam.nam$b_rss = sizeof(RName);
+
+    /* do $PARSE and $SEARCH here */
+    status = sys$parse(&Fab);
+    if (!(status & 1)) return(status);
+
+    /* search for the first file.. If none signal error */
+    status = sys$search(&Fab);
+    if (!(status & 1)) return(status);
+
+    while (status & 1) {
+        /* initialize Device name length, note that this points into the NAM
+           to get the device name filled in by the $PARSE, $SEARCH services */
+        DevDesc.dsc$w_length = Nam.nam$t_dvi[0];
+
+        status = sys$assign(&DevDesc,&DevChan,0,0);
+        if (!(status & 1)) return(status);
+
+        FileName.dsc$a_pointer = Nam.nam$l_name;
+        FileName.dsc$w_length = Nam.nam$b_name+Nam.nam$b_type+Nam.nam$b_ver;
+
+        /* Initialize the FIB */
+        for (i=0;i<3;i++) {
+            Fib.FIB$W_FID[i]=Nam.nam$w_fid[i];
+            Fib.FIB$W_DID[i]=Nam.nam$w_did[i];
+        }
+
+        /* Use the IO$_ACCESS function to return info about the file */
+        /* Note, used this way, the file is not opened, and the expiration */
+        /* and revision dates are not modified */
+        status = sys$qiow(0,DevChan,IO$_ACCESS,&iosb,0,0,
+                          &FibDesc,&FileName,0,0,&Atr,0);
+        if (!(status & 1) || !((status = iosb[0]) & 1)) {
+            sys$dassgn(DevChan);
+            return(status);
+        }
+
+    /*-----------------------------------------------------------------------
+        We have the current information from the file:  now see what user
+        wants done with it.
+      -----------------------------------------------------------------------*/
+
+        switch (action) {
+
+          case GET_TIMES:   /* non-modifying */
+              asctim(((struct VMStimbuf *)ptr)->modtime, Cdate);
+              asctim(((struct VMStimbuf *)ptr)->actime, Rdate);
+              sys$dassgn(DevChan);
+              return RMS$_NORMAL;     /* return to user */
+              break;
+
+          case SET_TIMES:
+              if (((struct VMStimbuf *)ptr)->modtime != (char *)NULL)
+                  bintim(((struct VMStimbuf *)ptr)->modtime, Cdate);
+              if (((struct VMStimbuf *)ptr)->actime != (char *)NULL)
+                  bintim(((struct VMStimbuf *)ptr)->actime, Rdate);
+              break;
+
+          case GET_RTYPE:   /* non-modifying */
+              *(int *)ptr = Fat.fat$v_rtype;
+              sys$dassgn(DevChan);
+              return RMS$_NORMAL;     /* return to user */
+              break;
+
+          case CHANGE_RTYPE:
+              old_rtype = Fat.fat$v_rtype;              /* save current one */
+              if ((*(int *)ptr < FAT$C_UNDEFINED) ||
+                  (*(int *)ptr > FAT$C_STREAMCR))
+                  Fat.fat$v_rtype = FAT$C_STREAMLF;       /* Unix I/O happy */
+              else
+                  Fat.fat$v_rtype = *(int *)ptr;
+              break;
+
+          case RESTORE_RTYPE:
+              Fat.fat$v_rtype = old_rtype;
+              break;
+
+          default:
+              sys$dassgn(DevChan);
+              return SS$_BADPARAM;   /* anything better? */
+        }
+
+    /*-----------------------------------------------------------------------
+        Go back and write modified data to the file header.
+      -----------------------------------------------------------------------*/
+
+        /* note, part of the FIB was cleared by earlier QIOW, so reset it */
+        Fib.FIB$L_ACCTL = FIB$M_NORECORD;
+        for (i=0;i<3;i++) {
+            Fib.FIB$W_FID[i]=Nam.nam$w_fid[i];
+            Fib.FIB$W_DID[i]=Nam.nam$w_did[i];
+        }
+
+        /* Use the IO$_MODIFY function to change info about the file */
+        /* Note, used this way, the file is not opened, however this would */
+        /* normally cause the expiration and revision dates to be modified. */
+        /* Using FIB$M_NORECORD prohibits this from happening. */
+        status = sys$qiow(0,DevChan,IO$_MODIFY,&iosb,0,0,
+                          &FibDesc,&FileName,0,0,&Atr,0);
+        if (!(status & 1) || !((status = iosb[0]) & 1)) {
+            sys$dassgn(DevChan);
+            return(status);
+        }
+
+        status = sys$dassgn(DevChan);
+        if (!(status & 1)) return(status);
+
+        /* look for next file, if none, no big deal.. */
+        status = sys$search(&Fab);
+    }
+    return(status);
+} /* end function VMSmunch() */
+
+
+
+
+
+/***********************/
+/*  Function asctim()  */
+/***********************/
+
+static void asctim(        /* convert 64-bit binval to string, put in time */
+    char *time,
+    long int binval[2] )
+{
+    static struct dsc$descriptor date_str={23,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
+      /* dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer */
+
+    date_str.dsc$a_pointer = time;
+    sys$asctim(0, &date_str, binval, 0);
+    time[23] = '\0';
+}
+
+
+
+
+
+/***********************/
+/*  Function bintim()  */
+/***********************/
+
+static void bintim(        /* convert time string to 64 bits, put in binval */
+    char *time,
+    long int binval[2] )
+{
+    static struct dsc$descriptor date_str={0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
+
+    date_str.dsc$w_length = strlen(time);
+    date_str.dsc$a_pointer = time;
+    sys$bintim(&date_str, binval);
+}
diff --git a/vms/vmsmunch.h b/vms/vmsmunch.h
new file mode 100644 (file)
index 0000000..53d77b4
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*---------------------------------------------------------------------------
+
+  vmsmunch.h
+
+  A few handy #defines, plus the contents of three header files from Joe
+  Meadows' FILE program.  Used by VMSmunch and by various routines which
+  call VMSmunch (e.g., in Zip and UnZip).
+
+        02-Apr-1994     Jamie Hanrahan  jeh@cmkrnl.com
+                        Moved definition of VMStimbuf struct from vmsmunch.c
+                        to here.
+
+        06-Apr-1994     Jamie Hanrahan  jeh@cmkrnl.com
+                        Moved "contents of three header files" (not needed by
+                        callers of vmsmunch) to VMSdefs.h .
+
+        07-Apr-1994     Richard Levitte levitte@e.kth.se
+                        Inserted a forward declaration of VMSmunch.
+
+        17-Sep-1995     Chr. Spieler    spieler@linac.ikp.physik.th-darmstadt.de
+                        Added wrapper to prevent multiple loading of this file.
+
+        10-Oct-1995     Chr. Spieler    spieler@linac.ikp.physik.th-darmstadt.de
+                        Use lowercase names for all VMS specific source files
+
+        15-Dec-1995     Chr. Spieler    spieler@linac.ikp.physik.th-darmstadt.de
+                        Removed ALL "tabs" from source file.
+
+  ---------------------------------------------------------------------------*/
+
+#ifndef __vmsmunch_h
+#define __vmsmunch_h 1
+
+#define GET_TIMES       4
+#define SET_TIMES       0
+#define GET_RTYPE       1
+#define CHANGE_RTYPE    2
+#define RESTORE_RTYPE   3
+
+struct VMStimbuf {      /* VMSmunch */
+    char *actime;       /* VMS revision date, ASCII format */
+    char *modtime;      /* VMS creation date, ASCII format */
+};
+
+extern int VMSmunch(char *filename, int action, char *ptr);
+
+#endif /* !__vmsmunch_h */
diff --git a/vms/vmszip.c b/vms/vmszip.c
new file mode 100644 (file)
index 0000000..2221644
--- /dev/null
@@ -0,0 +1,703 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+
+/* 2004-09-25 SMS.
+   Added case-insensitive file name comparisons, with the option of
+   preserving case in file names.  Defining VMS_PRESERVE_CASE will cause
+   incompatibility with Zip 2.3 and earlier.
+*/
+
+/* #define VMS_PRESERVE_CASE */  /* Not for general use. */
+
+#include "zip.h"
+
+#include <ctype.h>
+#include <time.h>
+#include <unixlib.h>
+
+/* Judge availability of str[n]casecmp() in C RTL.
+   (Note: This must follow a "#include <decc$types.h>" in something to
+   ensure that __CRTL_VER is as defined as it will ever be.  DEC C on
+   VAX may not define it itself.)
+*/
+#ifdef __CRTL_VER
+#if __CRTL_VER >= 70000000
+#define HAVE_STRCASECMP
+#endif /* __CRTL_VER >= 70000000 */
+#endif /* def __CRTL_VER */
+
+#ifdef HAVE_STRCASECMP
+#include <strings.h>    /* str[n]casecmp() */
+#endif /* def HAVE_STRCASECMP */
+
+#include <descrip.h>
+#include <rms.h>
+#include <ssdef.h>
+#include <starlet.h>
+
+#define PATH_START '['
+#define PATH_END ']'
+#define PATH_START2 '<'
+#define PATH_END2 '>'
+#include "vms/vmsmunch.h"
+
+/* Extra malloc() space in names for cutpath() */
+#define PAD 5         /* may have to change .FOO] to ]FOO.DIR;1 */
+
+
+#ifndef UTIL    /* the companion #endif is a bit of ways down ... */
+
+/* The C RTL from OpenVMS 7.0 and newer supplies POSIX compatible versions of
+ * opendir() et al. Thus, we have to use other names in our private code for
+ * directory scanning to prevent symbol name conflicts at link time.
+ * For now, we do not use the library supplied "dirent.h" functions, since
+ * our private implementation provides some functionality which may not be
+ * present in the library versions.  For example:
+ * ==> zopendir("DISK:[DIR.SUB1]SUB2.DIR") scans "DISK:[DIR.SUB1.SUB2]".
+ */
+
+typedef struct zdirent {
+  int d_wild;                /* flag for wildcard vs. non-wild */
+  struct FAB fab;
+  struct NAM nam;
+  char d_qualwildname[NAM$C_MAXRSS + 1];
+  char d_name[NAM$C_MAXRSS + 1];
+} zDIR;
+
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+/* Local functions */
+local void vms_wild OF((char *, zDIR *));
+local zDIR *zopendir OF((ZCONST char *));
+local char *readd OF((zDIR *));
+local char *strlower OF((char *));
+local char *strupper OF((char *));
+
+/* 2004-09-25 SMS.
+   str[n]casecmp() replacement for old C RTL.
+   Assumes a prehistorically incompetent toupper().
+*/
+#ifndef HAVE_STRCASECMP
+
+int strncasecmp( s1, s2, n)
+char *s1;
+char *s2;
+size_t n;
+{
+  /* Initialization prepares for n == 0. */
+  char c1 = '\0';
+  char c2 = '\0';
+
+  while (n-- > 0)
+  {
+    /* Set c1 and c2.  Convert lower-case characters to upper-case. */
+    if (islower( c1 = *s1))
+      c1 = toupper( c1);
+
+    if (islower( c2 = *s2))
+      c2 = toupper( c2);
+
+    /* Quit at inequality or NUL. */
+    if ((c1 != c2) || (c1 == '\0'))
+      break;
+
+    s1++;
+    s2++;
+  }
+return ((unsigned int)c1 - (unsigned int)c2);
+}
+
+#ifndef UINT_MAX
+#define UINT_MAX 4294967295U
+#endif
+
+#define strcasecmp( s1, s2) strncasecmp( s1, s2, UINT_MAX)
+
+#endif /* ndef HAVE_STRCASECMP */
+
+
+/* 2004-09-27 SMS.
+   eat_carets().
+   Delete ODS5 extended file name escape characters ("^") in the
+   original buffer.
+   Note that the current scheme handles only simple EFN cases, but it
+   could be made more complicated.
+*/
+
+local void eat_carets( str)
+char *str;      /* Source pointer. */
+{
+  char *strd;   /* Destination pointer. */
+
+  /* Skip ahead to the first "^", if any. */
+  while ((*str != '\0') && (*str != '^'))
+     str++;
+
+  /* If no caret was found, quit early. */
+  if (*str != '\0')
+  {
+    /* Shift characters leftward as carets are found. */
+    strd = str;
+    while (*str != '\0')
+    {
+      if (*str == '^')
+      {
+        /* Found a caret.  Skip it, and take the next character. */
+        *strd = *(++str);
+      }
+      else
+      {
+        /* Found a non-caret.  Take it. */
+        *strd = *str;
+      }
+
+      /* Advance destination and source pointers. */
+      strd++;
+      str++;
+    }
+    /* Terminate the destination string. */
+    *strd = '\0';
+  }
+}
+
+/*---------------------------------------------------------------------------
+
+    _vms_findfirst() and _vms_findnext(), based on public-domain DECUS C
+    fwild() and fnext() routines (originally written by Martin Minow, poss-
+    ibly modified by Jerry Leichter for bintnxvms.c), were written by Greg
+    Roelofs and are still in the public domain.  Routines approximate the
+    behavior of MS-DOS (MSC and Turbo C) findfirst and findnext functions.
+
+  ---------------------------------------------------------------------------*/
+
+static char wild_version_part[10]="\0";
+
+local void vms_wild(p, d)
+char *p;
+zDIR *d;
+{
+  /*
+   * Do wildcard setup
+   */
+  /* set up the FAB and NAM blocks. */
+  d->fab = cc$rms_fab;             /* initialize fab */
+  d->nam = cc$rms_nam;             /* initialize nam */
+
+  d->fab.fab$l_nam = &d->nam;           /* fab -> nam */
+  d->fab.fab$l_fna = p;                 /* argument wild name */
+  d->fab.fab$b_fns = strlen(p);         /* length */
+
+  d->fab.fab$l_dna = "sys$disk:[]";     /* Default fspec */
+  d->fab.fab$b_dns = sizeof("sys$disk:[]")-1;
+
+  d->nam.nam$l_esa = d->d_qualwildname; /* qualified wild name */
+  d->nam.nam$b_ess = NAM$C_MAXRSS;      /* max length */
+  d->nam.nam$l_rsa = d->d_name;         /* matching file name */
+  d->nam.nam$b_rss = NAM$C_MAXRSS;      /* max length */
+
+  /* parse the file name */
+  if (sys$parse(&d->fab) != RMS$_NORMAL)
+    return;
+  /* Does this replace d->fab.fab$l_fna with a new string in its own space?
+     I sure hope so, since p is free'ed before this routine returns. */
+
+  /* have qualified wild name (i.e., disk:[dir.subdir]*.*); null-terminate
+   * and set wild-flag */
+  d->d_qualwildname[d->nam.nam$b_esl] = '\0';
+  d->d_wild = (d->nam.nam$l_fnb & NAM$M_WILDCARD)? 1 : 0;   /* not used... */
+#ifdef DEBUG
+  fprintf(mesg, "  incoming wildname:  %s\n", p);
+  fprintf(mesg, "  qualified wildname:  %s\n", d->d_qualwildname);
+#endif /* DEBUG */
+}
+
+local zDIR *zopendir(n)
+ZCONST char *n;         /* directory to open */
+/* Start searching for files in the VMS directory n */
+{
+  char *c;              /* scans VMS path */
+  zDIR *d;              /* malloc'd return value */
+  int m;                /* length of name */
+  char *p;              /* malloc'd temporary string */
+
+  if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL ||
+      (p = malloc((m = strlen(n)) + 4)) == NULL) {
+    if (d != NULL) free((zvoid *)d);
+    return NULL;
+  }
+  /* Directory may be in form "[DIR.SUB1.SUB2]" or "[DIR.SUB1]SUB2.DIR;1".
+     If latter, convert to former. */
+  if (m > 0  &&  *(c = strcpy(p,n)+m-1) != ']')
+  {
+    while (--c > p  &&  *c != ';')
+      ;
+    if ((c- p < 5)  ||  strncasecmp( (c- 4), ".DIR", 4))
+    {
+      free((zvoid *)d);  free((zvoid *)p);
+      return NULL;
+    }
+    c -= 3;
+    *c-- = '\0';        /* terminate at "DIR;#" */
+    *c = ']';           /* "." --> "]" */
+    while (c > p  &&  *--c != ']')
+      ;
+    *c = '.';           /* "]" --> "." */
+  }
+  strcat(p, "*.*");
+  strcat(p, wild_version_part);
+  vms_wild(p, d);       /* set up wildcard */
+  free((zvoid *)p);
+  return d;
+}
+
+local char *readd(d)
+zDIR *d;                /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+   no more entries or an error occurs. */
+{
+  int r;                /* return code */
+
+  do {
+    d->fab.fab$w_ifi = 0;       /* internal file index:  what does this do? */
+
+    /* get next match to possible wildcard */
+    if ((r = sys$search(&d->fab)) == RMS$_NORMAL)
+    {
+        d->d_name[d->nam.nam$b_rsl] = '\0';   /* null terminate */
+        return (char *)d->d_name;   /* OK */
+    }
+  } while (r == RMS$_PRV);
+  return NULL;
+}
+
+int wild(p)
+char *p;                /* path/pattern to match */
+/* Expand the pattern based on the contents of the file system.  Return an
+   error code in the ZE_ class. */
+{
+  zDIR *d;              /* stream for reading directory */
+  char *e;              /* name found in directory */
+  int f;                /* true if there was a match */
+
+  /* special handling of stdin request */
+  if (strcmp(p, "-") == 0)   /* if compressing stdin */
+    return newname(p, 0, 0);
+
+  /* Search given pattern for matching names */
+  if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL)
+    return ZE_MEM;
+  vms_wild(p, d);       /* pattern may be more than just directory name */
+
+  /*
+   * Save version specified by user to use in recursive drops into
+   * subdirectories.
+   */
+  strncpy(wild_version_part,d->nam.nam$l_ver,d->nam.nam$b_ver);
+  wild_version_part[d->nam.nam$b_ver] = '\0';
+
+  f = 0;
+  while ((e = readd(d)) != NULL)        /* "dosmatch" is already built in */
+    if (procname(e, 0) == ZE_OK)
+      f = 1;
+  free(d);
+
+  /* Done */
+  return f ? ZE_OK : ZE_MISS;
+}
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  zDIR *d;              /* directory stream from zopendir() */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (LSSTAT(n, &s)
+#if defined(__TURBOC__) || defined(VMS) || defined(__WATCOMC__)
+           /* For these 3 compilers, stat() succeeds on wild card names! */
+           || isshexp(n)
+#endif
+          )
+  {
+    /* Not a file or directory--search for shell expression in zip file */
+    if (caseflag) {
+      p = malloc(strlen(n) + 1);
+      if (p != NULL)
+        strcpy(p, n);
+    } else
+      p = ex2in(n, 0, (int *)NULL);     /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+  if ((s.st_mode & S_IFDIR) == 0)
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  } else {
+    if (dirnames && (m = newname(n, 1, caseflag)) != ZE_OK) {
+      return m;
+    }
+    /* recurse into directory */
+    if (recurse && (d = zopendir(n)) != NULL)
+    {
+      while ((e = readd(d)) != NULL) {
+        if ((m = procname(e, caseflag)) != ZE_OK)     /* recurse on name */
+        {
+          free(d);
+          return m;
+        }
+      }
+      free(d);
+    }
+  } /* (s.st_mode & S_IFDIR) == 0) */
+  return ZE_OK;
+}
+
+/* 2004-09-24 SMS.
+   Cuter strlower() and strupper() functions.
+*/
+
+local char *strlower( s)
+char *s;
+/* Convert all uppercase letters to lowercase in string s */
+{
+  for ( ; *s != '\0'; s++)
+    if (isupper( *s))
+      *s = tolower( *s);
+
+  return s;
+}
+
+local char *strupper( s)
+char *s;
+/* Convert all lowercase letters to uppercase in string s */
+{
+  for ( ; *s != '\0'; s++)
+    if (islower( *s))
+      *s = toupper( *s);
+
+  return s;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t;              /* shortened name */
+  int dosflag;
+
+  dosflag = dosify; /* default for non-DOS and non-OS/2 */
+
+  /* Find starting point in name before doing malloc */
+  t = x;
+  if ((n = strrchr(t, ':')) != NULL)
+    t = n + 1;
+  if ( (*t == PATH_START && (n = strrchr(t, PATH_END)) != NULL)
+      || (*t == PATH_START2 && (n = strrchr(t, PATH_END2)) != NULL) )
+    /* external name contains valid VMS path specification */
+    if (*(++t) == '.')
+      /* path is relative to current directory, skip leading '.' */
+      t++;
+
+  if (!pathput)
+    t = last(last(t, PATH_END), PATH_END2);
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL)
+    return NULL;
+  strcpy(n, t);
+
+  if (((t = strrchr(n, PATH_END)) != NULL) ||
+       (t = strrchr(n, PATH_END2)) != NULL)
+  {
+    *t = '/';
+    while (--t > n)
+      if (*t == '.')
+        *t = '/';
+  }
+
+  /* Fix from Greg Roelofs: */
+  /* Get current working directory and strip from n (t now = n) */
+  {
+    char cwd[256], *p, *q;
+    int c;
+
+    q = getcwd( cwd, 256);
+
+    /* 2004-09-24 SMS.
+       With SET PROCESSS /PARSE = EXTENDED, getcwd() can return a
+       mixed-case result, confounding the comparisons below with an
+       all-uppercase name in "n".  Always use a case-insensitive
+       comparison around here.
+    */
+
+#if 0 /* fix by Igor */
+    if ((q != NULL) && ((p = strchr(cwd, '.')) != NULL))
+#else
+    if ((q != NULL) && ((p = strchr(cwd, PATH_START)) != NULL ||
+                        (p = strchr(cwd, PATH_START2)) != NULL))
+#endif
+    {
+      if (*(++p) == '.')
+        p++;
+      if ((q = strrchr(p, PATH_END)) != NULL ||
+          (q = strrchr(p, PATH_END2)) != NULL)
+      {
+        *q = '/';
+        while (--q > p)
+          if (*q == '.')
+            *q = '/';
+
+        /* strip bogus path parts from n */
+        if (strncasecmp( n, p, (c = strlen( p))) == 0)
+        {
+          q = n + c;
+          while (*t++ = *q++)
+            ;
+        }
+      }
+    }
+  }
+
+#ifndef VMS_PRESERVE_CASE
+  strlower( n);
+#endif /* ndef VMS_PRESERVE_CASE */
+
+  /* Remove simple ODS5 extended file name escape characters. */
+  eat_carets( n);
+
+  if (isdir)
+  {
+    if (strcasecmp( (t = n + strlen( n) - 6), ".DIR;1"))
+      error("directory not version 1");
+    else
+      if (pathput)
+        strcpy(t, "/");
+      else
+        *n = '\0';              /* directories are discarded with zip -rj */
+  }
+  else if (!vmsver)
+    if ((t = strrchr(n, ';')) != NULL)
+      *t = '\0';
+
+  if ((t = strrchr(n, '.')) != NULL)
+  {
+    if ( t[1] == '\0')          /* "filename." -> "filename" */
+      *t = '\0';
+    else if (t[1] == ';')       /* "filename.;vvv" -> "filename;vvv" */
+    {
+      char *f = t+1;
+      while (*t++ = *f++) ;
+    }
+  }
+
+  if (dosify)
+    msname(n);
+
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+  return n;
+}
+
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+  char *t;              /* scans name */
+
+  if ((t = strrchr(n, '/')) == NULL)
+  {
+    if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+      return NULL;
+    strcpy(x, n);
+  }
+  else
+  {
+    if ((x = malloc(strlen(n) + 3 + PAD)) == NULL)
+      return NULL;
+    x[0] = PATH_START;
+    x[1] = '.';
+    strcpy(x + 2, n);
+    *(t = x + 2 + (t - n)) = PATH_END;
+    while (--t > x)
+      if (*t == '/')
+        *t = '.';
+  }
+
+#ifndef VMS_PRESERVE_CASE
+  strupper( x);
+#endif /* ndef VMS_PRESERVE_CASE */
+
+  return x;
+}
+
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+  int tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year;
+  char timbuf[24];
+  static ZCONST char *month[] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
+                                 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
+  struct VMStimbuf {
+      char *actime;           /* VMS revision date, ASCII format */
+      char *modtime;          /* VMS creation date, ASCII format */
+  } ascii_times;
+
+  ascii_times.actime = ascii_times.modtime = timbuf;
+
+  /* Convert DOS time to ASCII format for VMSmunch */
+  tm_sec = (int)(d << 1) & 0x3e;
+  tm_min = (int)(d >> 5) & 0x3f;
+  tm_hour = (int)(d >> 11) & 0x1f;
+  tm_mday = (int)(d >> 16) & 0x1f;
+  tm_mon = ((int)(d >> 21) & 0xf) - 1;
+  tm_year = ((int)(d >> 25) & 0x7f) + 1980;
+  sprintf(timbuf, "%02d-%3s-%04d %02d:%02d:%02d.00", tm_mday, month[tm_mon],
+    tm_year, tm_hour, tm_min, tm_sec);
+
+  /* Set updated and accessed times of f */
+  if (VMSmunch(f, SET_TIMES, (char *)&ascii_times) != RMS$_NMF)
+    zipwarn("can't set zipfile time: ", f);
+}
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  /* malloc name so not dependent on FNMAX - 11/8/04 EG */
+  char *name;
+  int len = strlen(f);
+
+  if (f == label) {
+    if (a != NULL)
+      *a = label_mode;
+    if (n != NULL)
+      *n = -2; /* convention for a label name */
+    if (t != NULL)
+      t->atime = t->mtime = t->ctime = label_utim;
+    return label_time;
+  }
+  if ((name = malloc(len + 1)) == NULL) {
+    ZIPERR(ZE_MEM, "filetime");
+  }
+  strcpy(name, f);
+  if (name[len - 1] == '/')
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+
+  if (strcmp(f, "-") == 0) {
+    if (fstat(fileno(stdin), &s) != 0) {
+      free(name);
+      error("fstat(stdin)");
+    }
+  } else if (LSSTAT(name, &s) != 0) {
+             /* Accept about any file kind including directories
+              * (stored with trailing / with -r option)
+              */
+    free(name);
+    return 0;
+  }
+  free(name);
+
+  if (a != NULL) {
+    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
+    if ((s.st_mode & S_IFDIR) != 0) {
+      *a |= MSDOS_DIR_ATTR;
+    }
+  }
+  if (n != NULL)
+    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1;
+  if (t != NULL) {
+    t->atime = s.st_mtime;
+#ifdef USE_MTIME
+    t->mtime = s.st_mtime;            /* Use modification time in VMS */
+#else
+    t->mtime = s.st_ctime;            /* Use creation time in VMS */
+#endif
+    t->ctime = s.st_ctime;
+  }
+
+#ifdef USE_MTIME
+  return unix2dostime((time_t *)&s.st_mtime); /* Use modification time in VMS */
+#else
+  return unix2dostime((time_t *)&s.st_ctime); /* Use creation time in VMS */
+#endif
+}
+
+int deletedir(d)
+char *d;                /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+   Return the result of rmdir(), delete(), or system().
+   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).
+ */
+{
+    /* code from Greg Roelofs, who horked it from Mark Edwards (unzip) */
+    int r, len;
+    char *s;              /* malloc'd string for system command */
+
+    len = strlen(d);
+    if ((s = malloc(len + 34)) == NULL)
+      return 127;
+
+    system(strcat(strcpy(s, "set prot=(o:rwed) "), d));
+    r = delete(d);
+    free(s);
+    return r;
+}
+
+#endif /* !UTIL */
diff --git a/vms/zip_cli.cld b/vms/zip_cli.cld
new file mode 100644 (file)
index 0000000..714b23c
--- /dev/null
@@ -0,0 +1,73 @@
+       Module          ZIP_CLITABLE
+       Ident           "02-006"
+
+Define Verb            ZIP
+       Parameter       P1, Label=ZIPFILE, Prompt="Zip file"
+       Parameter       P2, Label=INFILE, VALUE(list), Prompt="Files to Zip"
+       Qualifier       DELETE, NonNegatable
+       Qualifier       FRESHEN, NonNegatable
+       Qualifier       MOVE, NonNegatable
+       Qualifier       UPDATE, NonNegatable
+       Qualifier       EXCLUDE, NonNegatable, VALUE(required,list)
+       Qualifier       INCLUDE, NonNegatable, VALUE(required,list)
+       Qualifier       EXLIST, NonNegatable, VALUE(type=$FILE,required)
+       Qualifier       INLIST, NonNegatable, VALUE(type=$FILE,required)
+       Qualifier       ADJUST_OFFSETS, NonNegatable
+       Qualifier       APPEND, NonNegatable
+       Qualifier       BATCH, NonNegatable, VALUE(type=$FILE)
+       Qualifier       BEFORE, NonNegatable, VALUE(type=$DATETIME)
+       Qualifier       COMMENTS, NonNegatable,
+                       VALUE(type=COMMENTS_KEYWORDS)
+       Qualifier       DIRNAMES, Negatable, Default
+       Qualifier       ENCRYPT, Negatable, VALUE
+       Qualifier       EXTRA_FIELDS, Negatable, Default
+       Qualifier       FIX_ARCHIVE, NonNegatable, VALUE(type=FIX_OPTIONS)
+       Qualifier       FULL_PATH, Negatable, Default
+       Qualifier       HELP, NonNegatable
+       Qualifier       JUNK, NonNegatable
+       Qualifier       KEEP_VERSION, Negatable
+       Qualifier       LATEST, NonNegatable
+       Qualifier       LEVEL, VALUE(type=$NUMBER,required)
+       Qualifier       LICENSE, NonNegatable
+       Qualifier       PKZIP, Negatable
+       Qualifier       QUIET, NonNegatable
+       Qualifier       RECURSE, Negatable, VALUE(type=RECURSE_OPTS)
+       Qualifier       SINCE, NonNegatable, VALUE(type=$DATETIME)
+       Qualifier       STORE_TYPES, NonNegatable, VALUE(required,list)
+       Qualifier       TEMP_PATH, VALUE(required,type=$FILE)
+       Qualifier       TEST, NonNegatable
+       Qualifier       TRANSLATE_EOL, NonNegatable,
+                       VALUE(type=EOL_KEYWORDS)
+       Qualifier       UNSFX, NonNegatable
+       Qualifier       VERBOSE, NonNegatable, VALUE(type=VERBOSE_OPTS)
+       Qualifier       VMS, NonNegatable, VALUE(type=VMS_OPTS)
+       Qualifier       YYZ_ZIP, NonNegatable, Default
+
+       Disallow        FIX_ARCHIVE.NORMAL and FIX_ARCHIVE.FULL
+       Disallow        TRANSLATE_EOL.LF and TRANSLATE_EOL.CRLF
+       Disallow        FULL_PATH and JUNK
+       Disallow        RECURSE.PATH and RECURSE.FILENAMES
+
+Define Type            COMMENTS_KEYWORDS
+       Keyword         ZIP_FILE, DEFAULT
+       Keyword         FILES
+
+Define Type            FIX_OPTIONS
+       Keyword         NORMAL, DEFAULT
+       Keyword         FULL
+
+Define Type            EOL_KEYWORDS
+       Keyword         LF, DEFAULT
+       Keyword         CRLF
+
+Define Type            RECURSE_OPTS
+       Keyword         PATH, DEFAULT
+       Keyword         FILENAMES
+
+Define Type            VERBOSE_OPTS
+       Keyword         MORE
+       Keyword         DEBUG
+
+Define Type            VMS_OPTS
+       Keyword         ALL
+
diff --git a/vms/zip_cli.help b/vms/zip_cli.help
new file mode 100644 (file)
index 0000000..3236e48
--- /dev/null
@@ -0,0 +1,617 @@
+.!
+.!  File:       ZIP_CLI.HELP
+.!
+.!  Author:     Christian Spieler
+.!
+.!  Date:       05 Dec 95 (orig. ZIP.RNH, 22 Oct 91)
+.!
+.!  Description:
+.!
+.!      TPU-processable source file to produce VMS on-line help for
+.!      portable Zip.  Adapted from ZIP.RNH, originally based on
+.!      ZIP.MAN (now MANUAL).
+.!
+.!      To build:
+.!          $ EDIT /TPU/NOSECTION/NODISPLAY/COMMAND=CVTHELP.TPU ZIP_CLI.HELP
+.!          $ RUNOFF /OUT=ZIP_CLI.HLP ZIP_CLI.RNH
+.!          $ LIBR /HELP/INSERT libr ZIP_CLI
+.!
+.!  Modification history:
+.!
+.!      01-001          Christian Spieler       05-DEC-1995 02:02
+.!              Genesis.
+.!      01-002          Christian Spieler       20-JAN-1996 03:09
+.!              Modified /LICENSE and /VERBOSE descriptions.
+.!      01-003          Christian Spieler       11-FEB-1996 23:09
+.!              Added /[NO]EXTRA_FIELDS description.
+.!      01-004          Christian Spieler       11-MAR-1996 20:08
+.!              Removed /ENCRYPT=VERIFY option.
+.!      01-005          Christian Spieler       11-MAY-1996 23:08
+.!              Corrected/enhanced info about how to get help on UNIX options.
+.!      01-006          Christian Spieler       21-JUL-1997 22:26
+.!              Updated for new options of Zip 2.2.
+.!      01-006          Christian Spieler       14-OCT-1997 22:04
+.!              Cleanups for Zip 2.2 release (no version change).
+.!
+<INIT>
+<MAIN>
+ZIP
+
+Zip is a compression and file packaging utility for Unix, MSDOS, OS/2, and
+VMS.  It is analogous to a combination of tar and compress and is
+compatible with PKZIP (Phil Katz ZIP) for MSDOS systems.
+
+There is a companion to Zip called UnZip (of course).  Zip and UnZip can
+work with files produced by PKZIP under MSDOS, and PKZIP and PKUNZIP can
+work with files produced by Zip.
+
+Zip 2.2 is compatible with PKZIP 2.04.
+Note that PKUNZIP 1.10 cannot extract files produced by PKZIP 2.04
+or zip 2.2. You must use PKZIP 2.04g or unzip 5.0p1 (or later versions)
+to extract them.
+
+For a brief help on Zip and Unzip, run each without specifying any
+parameters on the command line. If you want to get the help screen
+describing the alternate UNIX style command interface, you must
+specify the -h option.
+
+Zip puts one or more compressed files into a single "zip file" along with
+information about the files, including the name, path if requested, date
+and time last modified, protection, and check information to verify the
+fidelity of each entry.  Zip can pack an entire directory structure in a
+zip file with a single command.  Compression ratios of 2:1 to 3:1 are
+common for text files.  Zip has has one compression method (deflation) and
+can also store files without compression. It automatically chooses the better
+of the two for each file to be compressed.
+
+Zip is useful for packaging a set of files to send to someone or for
+distribution; for archiving or backing up files; and for saving disk space
+by temporarily compressing unused files or directories.
+
+
+<FORMAT>
+ZIP zipfile [file[,...]] [/qualifiers]
+
+.!\f
+<TOPIC>
+Parameters
+
+<PARAMETER>
+zipfile
+
+<PTEXT>
+File specification for the ZIP archive. Zip will perform the requested action
+for every zipfile matching the specification.
+The default file specification is SYS$DISK:[].ZIP.
+
+Note that self-extracting ZIP files are supported; just specify the .EXE
+suffix yourself.
+<TXETP>
+
+<PARAMETER>
+file
+
+<PTEXT>
+An optional comma-separated list of files to be added or replaced in the
+zipfile. For unconditional add / replacement actions, a list must be
+specified. For the freshening operation, all archive members are processed
+per default; the optional file list restricts processing to the specified
+archive members.
+Expressions may be used to match multiple members.  For add/update operations,
+wildcard expressions are interpreted in  VMS wildcard syntax to match
+external files. In contrast, for freshening/deletion operation, wildcard
+expressions are interpreted in UNIX compatible syntax to match the
+internal names of archive members in the zipfile.
+<TXETP>
+
+<QUALIFIERS>
+<QUALIFIER>
+/ADJUST_OFFSETS
+
+/ADJUST_OFFSETS
+
+Adjust internal offsets of the Zip archive members after some data
+(e.g. a SFX executable stub) has been prepended to the archive file.
+<QUALIFIER>
+/APPEND
+
+/APPEND
+
+Try to work with the existing Zip archive. This option is ignored when
+any existing entry in the Zip archive gets updated or deleted.
+Without the /APPEND qualifier, Zip always creates a backup copy when
+modifying the archive. This is slower, but prevents corruption of the
+old archive in case of a fatal problem (power failures, program crash...).
+<QUALIFIER>
+/BATCH
+
+/BATCH[=listfile]
+
+Read list of files to add/update to the Zip archive from the listfile.
+The listfile defaults to SYS$INPUT.
+<QUALIFIER>
+/BEFORE
+
+/BEFORE=(VMS time specification)
+
+Only handle files that are older than the specified date and time.
+The specified time is compared with the files' RMS creation time.
+<QUALIFIER>
+/COMMENT
+
+/COMMENT[=KEYWORD[,KEYWORD]]
+
+Add comments to the Zip archive.
+<LITERAL>
+|  ZIP_FILE  Add/replace the multi-line archive comment. (default)
+|  FILES     Add file comment to each updated/added archive member.
+<LARETIL>
+
+The Zip program prompts for each comment to be added; this requires Zip
+to be run in interactive mode.
+
+The one-line archive member comments are terminated by typing RETURN.
+To skip a file comment, just type RETURN without entering any further
+characters.
+
+The zip archive comment may be multi-line. The comment is ended by a line
+containing just a period, or by supplying a ^Z.
+<QUALIFIER>
+/DELETE
+
+/DELETE
+
+Delete entries from zip file.
+<QUALIFIER>
+/DIRNAMES
+
+/DIRNAMES (default)
+/NODIRNAMES
+
+Store directory entries in the archive.
+<QUALIFIER>
+/ENCRYPT
+
+/ENCRYPT[="password"]
+
+Encrypt added and updated archive entries.
+
+You may specify the password on the command line, although we do not
+recommend it since THIS IS INSECURE. Remember to enclose the password
+string with quotes, to prevent automatic conversion to upper case or
+misinterpretation of punctuation characters by DCL.
+
+When the password was not specified, Zip prompts for it on SYS$COMMAND.
+For typing the password, terminal echo is suspended. For added user
+security, the password prompt appears twice and the two user inputs are
+checked for identity before using the password.
+<QUALIFIER>
+/EXCLUDE
+
+/EXCLUDE=(file[,...])
+
+A comma-separated list of files to exclude when deleting, updating or
+adding files in the archive.
+If multiple files are specified, the list should be included in
+parentheses.
+<QUALIFIER>
+/EXLIST
+
+/EXLIST=listfile
+
+The files matching the filename patterns listed in "listfile" are
+excluded when deleting, updating or adding files in the archive.
+The "listfile" is a normal text file with one filename pattern entry per
+line. The name pattern entries are recognized exactly as found in
+"listfile", including leading, embedding and trailing whitespace or most
+control characters (with exception of LineFeed and probably CarriageReturn).
+<QUALIFIER>
+/EXTRA_FIELDS
+
+/EXTRA_FIELDS (default)
+/NOEXTRA_FIELDS
+
+Allows inclusion of extra file attributes information in the zipfile's
+entry headers.
+Examples are: the VMS attributes (enabled by the /VMS qualifier), or
+additional GMT time stamps. These GMT time stamps are quite useful when
+transporting a Zip archive world wide, but they are only recognized
+by Info-ZIP's UnZip version 5.20 and later, and take up some additional
+space.
+When /EXTRA_FIELDS is negated, the /VMS qualifier to request saving of the
+VMS RMS file attributes is ignored, too!
+<QUALIFIER>
+/FRESHEN
+
+/FRESHEN
+
+Freshen existing zipfile entries; replace if newer.  Does not cause any new
+files to be added to the archive.
+<QUALIFIER>
+/FULL_PATH
+
+/FULL_PATH  (default)
+/NOFULL_PATH
+
+Directs Zip to store the directory part of the file names (relative to
+the current working directory) in the Zip archive.
+<QUALIFIER>
+/HELP
+
+/HELP
+
+Display Zip's help screen, including the version message.
+<QUALIFIER>
+/INCLUDE
+
+/INCLUDE=(file[,...])
+
+A comma-separated list of files to include when deleting, updating or
+adding files in the archive.
+If multiple files are specified, the list should be included in
+parentheses.
+<QUALIFIER>
+/INLIST
+
+/INLIST=listfile
+
+The files matching the filename patterns listed in "listfile" are
+included when deleting, updating or adding files in the archive.
+The "listfile" is a normal text file with one filename pattern entry per
+line. The name pattern entries are recognized exactly as found in
+"listfile", including leading, embedding and trailing whitespace or most
+control characters (with exception of LineFeed and probably CarriageReturn).
+<QUALIFIER>
+/JUNK
+
+/JUNK
+/NOJUNK (default)
+
+Junk the directory part of the file names for added entries (do not
+not save the directory structure). The /JUNK qualifier is an alias for
+/NOFULL_PATH.
+<QUALIFIER>
+/KEEP_VERSION
+
+/KEEP_VERSION
+/NOKEEP_VERSION (default)
+
+Directs Zip to include the version number appendix in the stored file names.
+This allows to store multiple version of the same file in a single Zip
+archive.
+
+The normal behaviour of Zip without /KEEP_VERSION is to use only the most
+recent version of a specified file and strip of the version number from
+the stored file name. This behaviour ensures better compatibility when
+transfering a Zip archive to non VMS systems.
+<QUALIFIER>
+/LATEST
+
+/LATEST
+
+The archive's creation and modification time is set to the latest
+modification time of all archive members.
+<QUALIFIER>
+/LEVEL
+
+/LEVEL=number
+
+Specifies the compression level:
+<LITERAL>
+|  0      Store
+|  1      Fastest compression (Defl:F)
+|  ...
+|  9      Best compression    (Defl:X)
+<LARETIL>
+
+The default level is 6.
+<QUALIFIER>
+/LICENSE
+
+/LICENSE
+
+Displays the Zip license.
+<QUALIFIER>
+/MOVE
+
+/MOVE
+
+Move the specified files into the Zip archive.
+Entries which have been added (or freshened) to the zip file get removed from
+the file system. If a directory is empty afterwards, it is also removed.
+<QUALIFIER>
+/PKZIP
+
+/PKZIP
+/NOPKZIP (default)
+
+Create PKZIP compatible archive entries.
+The file names are truncated and converted to upper case to match the
+MSDOS 8+3 file name syntax. Only the MSDOS compatible attributes are stored;
+the file owner's write permission is mapped to the "readonly" attribute.
+The archive entry is marked as being made under MSDOS regardless of the true
+host system of Zip.
+<QUALIFIER>
+/QUIET
+
+/QUIET
+
+Perform operations quietly.
+<QUALIFIER>
+/RECURSE
+
+/RECURSE[=KEYWORD]
+/NORECURSE (default)
+
+Directs Zip to recurse into subdirectories.
+The optional keywords recognized are:
+<LITERAL>
+|  PATH      take patterns as full path specifiers (-r) (default)
+|  FILENAMES start from current dir;
+|            only use filename part of file patterns (-R)
+<LARETIL>
+The new FILENAMES optional keyword modifies the recursion algorithm to
+be (almost) compatible to PKZIP's behaviour on subdirectory recursion.
+
+On VMS, this behaviour can be alternatively archived by using
+the "subdirectory recursing wildcard" [...] in the "include files" parameter
+list.
+<QUALIFIER>
+/SINCE
+
+/SINCE=(VMS time specification)
+
+Only handle files that are newer than the specified date and time.
+The specified time is compared with the files' RMS creation time.
+<QUALIFIER>
+/STORETYPES
+
+/STORETYPES=(.ext1,.ext2,... )
+
+For files with the specified extensions, Zip does not try to compress the
+data but stores them verbatim.  This speeds up operation on files that
+have already been compressed and where a second compression step usually
+does not gain much space.
+The default list of extensions where compression is suppressed is
+(.Z,.zip,.zoo,.arc,.arj).
+
+But note: when maximum level of compression is requested (/LEVEL=9), the
+STORETYPES heuristic is not used. In this case, Zip tries to compress ALL
+files.
+<QUALIFIER>
+/TEMP_PATH
+
+/TEMP_PATH=dirspec
+
+Specifies an alternate directory where Zip creates its temporary files.
+When this qualifier is not given, Zip attempts to write to the current
+working directory.
+<QUALIFIER>
+/TEST
+
+/TEST
+
+Test archive integrity.
+<QUALIFIER>
+/TRANSLATE_EOL
+
+/TRANSLATE_EOL[=KEYWORD]
+
+Selects conversion of the end-of-line markers in text files.
+The optional keywords recognized are:
+<LITERAL>
+|  LF        convert LF -> CRLF (UNIX to DOS) (default)
+|  CRLF      convert CRLF -> LF, strip trailing CTRL-Z's (DOS to UNIX)
+<LARETIL>
+
+This option should only be used with text files. The second option CRLF
+is only useful when a DOS text file has been transfered to a VMS disk
+in stream (or stream_lf) format.
+<QUALIFIER>
+/UNSFX
+
+/UNSFX
+
+Strip any prepended data from the Zip archive, for example a self-extracting
+executable stub.
+<QUALIFIER>
+/UPDATE
+
+/UPDATE
+
+Freshen existing archive entries; create new ones if needed.
+<QUALIFIER>
+/VERBOSE
+
+/VERBOSE[=MORE|DEBUG]
+
+Switch on verbose messages. This includes diagnostics on discovered
+oddities in the zipfile's structure, and a progress indicator during
+compression operation.
+
+When this qualifier is the only command line argument given, it has a special
+meaning. In this case a screen of diagnostic information about the program
+version is displayed. This display includes the Zip version number and
+release date, and it shows some information to determine when and how
+the executable was built and set up. This includes info on the used compiler's
+name and version, the date of the build (if available), and some optional
+compile time feature flags. Additionally, the contents of the environment
+variables (=logical names on VMS) that are read by Zip for runtime
+configuration are shown.
+This information is especially valuable when reporting problems or bugs.
+
+<QUALIFIER>
+/VMS
+
+/VMS[=ALL]
+
+Store VMS file attributes in Zip archive.
+
+When the optional keyword ALL is specified, all allocated blocks in a
+file are stored in the Zip archive, including data beyond the
+End-of-File (EOF) marker.
+
+/VMS provides good fidelity for well-formed files (no data past EOF)
+when unpacked on a VMS system.  Also, some types of file (notably
+Stream_LF text files) will be unpacked as expected on a non-VMS system.
+
+/VMS=ALL provides good fidelity, even for files with data past EOF, when
+unpacked on a VMS system.  However, the data from beyond the EOF marker
+will typically cause a file to appear corrupted when unpacked on a
+non-VMS system.
+<TOPIC>
+Authors
+
+Info-ZIP; currently maintained by Onno van der Linden.  VMS support maintained
+by Igor Mandrichenko, Christian Spieler, and Hunter Goatley.  Originally based
+on a program by Samuel H. Smith.
+
+VMS on-line help ported from Zip's MANUAL by Christian Spieler, using
+Hunter Goatley's work for UnZip.
+
+<TOPIC>
+Exit_Codes
+
+On VMS, Zip's UNIX style exit values are mapped into proper
+VMS status codes:
+<LITERAL>
+|   1                                  (success)  normal exit,
+|   (0x7fff0000 + 16*Zip_error_level)  warnings
+|   (0x7fff0002 + 16*Zip_error_level)  normal errors
+|   (0x7fff0004 + 16*Zip_error_level)  fatal errors
+<LARETIL>
+
+The Zip error level (or exit code) approximates the exit
+codes defined by PKWARE and takes on the following values:
+<LITERAL>
+|  VMS       Zip      Type of error
+|  severity  errcode
+|    -         0      normal; no errors or warnings detected.
+|    F         2      unexpected end of zip file.
+|    E         3      a generic error in the  zipfile  format  was
+|                     detected.   Processing  may  have  completed
+|                     successfully anyway;  some  broken  zipfiles
+|                     created by other archivers have simple work-
+|                     arounds.
+|    F         4      zip was unable to allocate memory for one or
+|                     more  buffers during program initialization.
+|    F         5      a severe error in  the  zipfile  format  was
+|                     detected.   Processing probably failed imme-
+|                     diately.
+|    E         6      entry too large to be split with zipsplit
+|    E         7      invalid comment format
+|    F         8      zip -T failed, or out of memory
+|    E         9      the user aborted zip prematurely  with  con-
+|                     trol-C (or similar)
+|    F         10     zip  encountered an error while using a temp
+|                     file
+|    F         11     read or seek error
+|    W         12     zip has nothing to do
+|    E         13     missing or empty zip file
+|    F         14     error writing to a file
+|    F         15     zip was unable to create a file for writing
+|    E         16     bad command line parameters
+|    E         18     zip could not open a specified file to read
+<LARETIL>
+
+<TOPIC>
+Logical_Names
+
+Zip scans its process environment for the logical name ZIP_OPTS, which
+can be used to specify a string of default options to modify Zip's
+behaviour. For the syntax, see help topic UNIX_Options.
+With the exception of "-i" and "-x", all recognized UNIX style options
+can be used within the ZIP_OPTS equivalence string.
+
+For example, the following will cause Zip to skip directories, include
+VMS attribute information perform all operations at quiet-level 1 by default:
+
+<LITERAL>
+|  $ define ZIP_OPTS "-qDV"
+<LARETIL>
+
+Note that the quotation marks here are required to preserve lowercase options
+(opposite of the command-line behavior).
+
+ZIP_OPTS may be defined as a symbol rather than a logical, but if both
+are defined, the logical is used.
+
+The alternative logical name ZIPOPT (more UNIX-like naming convention)
+is recognized as well. If both ZIPOPT and ZIP_OPTS are present (and do
+not equate to whitespace only), the content of ZIPOPT takes precedence
+and ZIP_OPTS is ignored.
+
+<TOPIC>
+UNIX_Options
+
+The default action of Zip is to add or replace zipfile entries from list, which
+can include the special name -@ to read names from SYS$INPUT.  The following
+list of options was taken from the on-line help generated when Zip is run
+with the -h command-line option:
+
+<LITERAL>
+|  -A   adjust self-extracting exe
+|  -b   use "path" for temp files
+|  -c   add one-line comments
+|  -d   delete entries in zipfile
+|  -D   do not add directory entries
+|  -e   encrypt
+|  -f   freshen: only changed files
+|  -F   fix zipfile (-FF try harder)
+|  -g   allow growing existing zipfile (unless updating or deleting)
+|  -h   show this help
+|  -i   include only names matching the following patterns
+|  -i@  include only names matching the patterns listed in "file"
+|  -j   junk (don't record) directory names
+|  -J   junk (remove) prepended (SFX) stub
+|  -k   simulate PKZIP made zipfile
+|  -l   translate end-of-lines (LF -> CRLF)
+|  -ll  translate end-of-lines (CRLF -> LF)
+|  -L   show software license
+|  -m   move into zipfile (delete files)
+|  -n   don't compress theses suffixes
+|  -o   make zipfile as old as latest entry
+|  -P   encrypt with specified "password"
+|  -q   quiet operation
+|  -r   recurse into subdirs, match against specified paths
+|  -R   recurse into subdirs of current dir, match filenames only
+|  -t   only do files after "mmddyyyy"
+|  -tt  only do files before "mmddyyyy"
+|  -T   test zip file integrity (calls unzip)
+|  -u   update: only changed or new files
+|  -v   verbose messages/print version info
+|  -V   save VMS file attributes
+|  -w   append the VMS version number to name stored in zip file
+|  -x   exclude names matching the following patterns
+|  -x@  exclude names matching the patterns listed in "file"
+|  -X   suppress storing of any extra file attributes
+|  -z   add zipfile comment
+|  -0   store only
+|  -1   compress faster
+|  -9   compress better
+|  -@   read list of files to process from SYS$INPUT
+<LARETIL>
+
+Note that uppercase options such as -A, -D, -L, -T and -V must be specified
+in quotes.  For example:
+
+<LITERAL>
+|  $ zip "-VD" -a zipfile
+<LARETIL>
+
+To negate a default option on the command line, add one or more minus signs
+before the option letter, in addition to the leading switch character `-':
+
+<LITERAL>
+|  $ zip --ql zipfile
+<LARETIL>
+
+or
+
+<LITERAL>
+|  $ zip -l-q zipfile
+<LARETIL>
+
+At present it is not possible to decrement an option below zero--that is,
+more than a few minuses have no effect.
+===
diff --git a/vms/zipup.h b/vms/zipup.h
new file mode 100644 (file)
index 0000000..eea74b6
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#define fhow "r","mbc=60"
+#define fbad NULL
+typedef void *ftype;
+#define zopen(n,p)   (vms_native?vms_open(n)    :(ftype)fopen((n), p))
+#define zread(f,b,n) (vms_native?vms_read(f,b,n):fread((b),1,(n),(FILE*)(f)))
+#define zclose(f)    (vms_native?vms_close(f)   :fclose((FILE*)(f)))
+#define zerr(f)      (vms_native?vms_error(f)   :ferror((FILE*)(f)))
+#define zstdin stdin
+
+ftype vms_open OF((char *));
+size_t vms_read OF((ftype, char *, size_t));
+int vms_close OF((ftype));
+int vms_error OF((ftype));
+#ifdef VMS_PK_EXTRA
+int vms_get_attributes OF((ftype, struct zlist far *, iztimes *));
+#endif
diff --git a/win32/README.NT b/win32/README.NT
new file mode 100644 (file)
index 0000000..d2b31f7
--- /dev/null
@@ -0,0 +1,17 @@
+From: Michael Tibbott <tibbott@classifieds2000.com>
+Subject: Zip on Windows NT problem - here's the answer
+Date: Wed, 10 Dec 1997 15:24:29 -0800
+
+If you're running NT Server (I am not sure about NT Workstation) then you
+should do the following to prevent zip/unzip from page swapping itself to
+death. And as an added bonus, the zip was about 6% faster.
+
+- open the network control panel
+
+- Click on the services tab
+
+- double-click on the server item to open its properties
+
+- Click the "maximize throughput for network applications" radio button
+
+- save and reboot
diff --git a/win32/README.TZ b/win32/README.TZ
new file mode 100644 (file)
index 0000000..ddce3f8
--- /dev/null
@@ -0,0 +1,7 @@
+From: paul.kienitz@shelter.sf.ca.us (Paul Kienitz)
+> It looks like I don't have to create a tzset() kluge for Watcom to check
+> the win32 API timezone information after all -- their new 10.6 release has
+> corrected this oversight.  The TZ variable overrides the API.  So the only
+> win32-related patch I want to make for Zip is just to use USE_EF_UT_TIME
+> unconditionally.  With this in place, timezone stuff is working flawlessly
+> with or without TZ being set.
diff --git a/win32/crc_i386.asm b/win32/crc_i386.asm
new file mode 100644 (file)
index 0000000..7693d75
--- /dev/null
@@ -0,0 +1,241 @@
+;===========================================================================
+; Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 2004-May-22 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, all these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+;===========================================================================
+; crc_i386.asm, optimized CRC calculation function for Zip and UnZip,
+; created by Paul Kienitz and Christian Spieler.
+;
+; Revised 06-Oct-96, Scott Field (sfield@microsoft.com)
+;   fixed to assemble with masm by not using .model directive which makes
+;   assumptions about segment alignment.  Also,
+;   avoid using loop, and j[e]cxz where possible.  Use mov + inc, rather
+;   than lodsb, and other misc. changes resulting in the following performance
+;   increases:
+;
+;      unrolled loops                NO_UNROLLED_LOOPS
+;      *8    >8      <8              *8      >8      <8
+;
+;      +54%  +42%    +35%            +82%    +52%    +25%
+;
+;   first item in each table is input buffer length, even multiple of 8
+;   second item in each table is input buffer length, > 8
+;   third item in each table is input buffer length, < 8
+;
+; Revised 02-Apr-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)
+;   Incorporated Rodney Brown's 32-bit-reads optimization as found in the
+;   UNIX AS source crc_i386.S. This new code can be disabled by defining
+;   the macro symbol NO_32_BIT_LOADS.
+;
+; Revised 12-Oct-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)
+;   Incorporated Rodney Brown's additional tweaks for 32-bit-optimized CPUs
+;   (like the Pentium Pro, Pentium II, and probably some Pentium clones).
+;   This optimization is controlled by the macro symbol __686 and is disabled
+;   by default. (This default is based on the assumption that most users
+;   do not yet work on a Pentium Pro or Pentium II machine ...)
+;
+; Revised 25-Mar-98, Cosmin Truta (cosmint@cs.ubbcluj.ro)
+;   Working without .model directive caused tasm32 version 5.0 to produce
+;   bad object code. The optimized alignments can be optionally disabled
+;   by defining NO_ALIGN, thus allowing to use .model flat. There is no need
+;   to define this macro if using other versions of tasm.
+;
+; Revised 16-Jan-2005, Cosmin Truta (cosmint@cs.ubbcluj.ro)
+;   Enabled the 686 build by default, because there are hardly any pre-686 CPUs
+;   in serious use nowadays. (See the 12-Oct-97 note above.)
+;
+; FLAT memory model assumed.
+;
+; Loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.
+; This results in shorter code at the expense of reduced performance.
+;
+;==============================================================================
+;
+; Do NOT assemble this source if external crc32 routine from zlib gets used.
+;
+    IFNDEF USE_ZLIB
+;
+        .386p
+        name    crc_i386
+
+    IFDEF NO_ALIGN
+        .model flat
+    ENDIF
+
+    IFNDEF PRE_686
+    IFNDEF __686
+__686   EQU     1 ; optimize for Pentium Pro, Pentium II and compatible CPUs
+    ENDIF
+    ENDIF
+
+extrn   _get_crc_table:near    ; ZCONST ulg near *get_crc_table(void);
+
+;
+    IFNDEF NO_STD_STACKFRAME
+        ; Use a `standard' stack frame setup on routine entry and exit.
+        ; Actually, this option is set as default, because it results
+        ; in smaller code !!
+STD_ENTRY       MACRO
+                push    ebp
+                mov     ebp,esp
+        ENDM
+
+        Arg1    EQU     08H[ebp]
+        Arg2    EQU     0CH[ebp]
+        Arg3    EQU     10H[ebp]
+
+STD_LEAVE       MACRO
+                pop     ebp
+        ENDM
+
+    ELSE  ; NO_STD_STACKFRAME
+
+STD_ENTRY       MACRO
+        ENDM
+
+        Arg1    EQU     18H[esp]
+        Arg2    EQU     1CH[esp]
+        Arg3    EQU     20H[esp]
+
+STD_LEAVE       MACRO
+        ENDM
+
+    ENDIF ; ?NO_STD_STACKFRAME
+
+; These two (three) macros make up the loop body of the CRC32 cruncher.
+; registers modified:
+;   eax  : crc value "c"
+;   esi  : pointer to next data byte (or dword) "buf++"
+; registers read:
+;   edi  : pointer to base of crc_table array
+; scratch registers:
+;   ebx  : index into crc_table array
+;          (requires upper three bytes = 0 when __686 is undefined)
+    IFNDEF  __686 ; optimize for 386, 486, Pentium
+Do_CRC  MACRO
+                mov     bl,al                ; tmp = c & 0xFF
+                shr     eax,8                ; c = (c >> 8)
+                xor     eax,[edi+ebx*4]      ;  ^ table[tmp]
+        ENDM
+    ELSE ; __686 : optimize for Pentium Pro, Pentium II and compatible CPUs
+Do_CRC  MACRO
+                movzx   ebx,al               ; tmp = c & 0xFF
+                shr     eax,8                ; c = (c >> 8)
+                xor     eax,[edi+ebx*4]      ;  ^ table[tmp]
+        ENDM
+    ENDIF ; ?__686
+Do_CRC_byte     MACRO
+                xor     al, byte ptr [esi]   ; c ^= *buf
+                inc     esi                  ; buf++
+                Do_CRC                       ; c = (c >> 8) ^ table[c & 0xFF]
+        ENDM
+    IFNDEF  NO_32_BIT_LOADS
+Do_CRC_dword    MACRO
+                xor     eax, dword ptr [esi] ; c ^= *(ulg *)buf
+                add     esi, 4               ; ((ulg *)buf)++
+                Do_CRC
+                Do_CRC
+                Do_CRC
+                Do_CRC
+        ENDM
+    ENDIF ; !NO_32_BIT_LOADS
+
+    IFNDEF NO_ALIGN
+_TEXT   segment use32 para public 'CODE'
+    ELSE
+_TEXT   segment use32
+    ENDIF
+        assume  CS: _TEXT
+
+        public  _crc32
+_crc32          proc    near  ; ulg crc32(ulg crc, ZCONST uch *buf, extent len)
+                STD_ENTRY
+                push    edi
+                push    esi
+                push    ebx
+                push    edx
+                push    ecx
+
+                mov     esi,Arg2             ; 2nd arg: uch *buf
+                sub     eax,eax              ;> if (!buf)
+                test    esi,esi              ;>   return 0;
+                jz      fine                 ;> else {
+
+                call    _get_crc_table
+                mov     edi,eax
+                mov     eax,Arg1             ; 1st arg: ulg crc
+    IFNDEF __686
+                sub     ebx,ebx              ; ebx=0; make bl usable as a dword
+    ENDIF
+                mov     ecx,Arg3             ; 3rd arg: extent len
+                not     eax                  ;>   c = ~crc;
+
+                test    ecx,ecx
+    IFNDEF  NO_UNROLLED_LOOPS
+                jz      bail
+    IFNDEF  NO_32_BIT_LOADS
+align_loop:
+                test    esi,3                ; align buf pointer on next
+                jz      SHORT aligned_now    ;  dword boundary
+                Do_CRC_byte
+                dec     ecx
+                jnz     align_loop
+aligned_now:
+    ENDIF ; !NO_32_BIT_LOADS
+                mov     edx,ecx              ; save len in edx
+                shr     ecx,3                ; ecx = len / 8
+                jz      SHORT No_Eights
+    IFNDEF NO_ALIGN
+; align loop head at start of 486 internal cache line !!
+                align   16
+    ENDIF
+Next_Eight:
+    IFNDEF  NO_32_BIT_LOADS
+                Do_CRC_dword
+                Do_CRC_dword
+    ELSE ; NO_32_BIT_LOADS
+                Do_CRC_byte
+                Do_CRC_byte
+                Do_CRC_byte
+                Do_CRC_byte
+                Do_CRC_byte
+                Do_CRC_byte
+                Do_CRC_byte
+                Do_CRC_byte
+    ENDIF ; ?NO_32_BIT_LOADS
+                dec     ecx
+                jnz     Next_Eight
+No_Eights:
+                mov     ecx,edx
+                and     ecx,000000007H       ; ecx = len % 8
+    ENDIF ; !NO_UNROLLED_LOOPS
+                jz      SHORT bail           ;>   if (len)
+    IFNDEF NO_ALIGN
+; align loop head at start of 486 internal cache line !!
+                align   16
+    ENDIF
+loupe:                                       ;>     do {
+                Do_CRC_byte                  ;        c = CRC32(c, *buf++);
+                dec     ecx                  ;>     } while (--len);
+                jnz     loupe
+
+bail:                                        ;> }
+                not     eax                  ;> return ~c;
+fine:
+                pop     ecx
+                pop     edx
+                pop     ebx
+                pop     esi
+                pop     edi
+                STD_LEAVE
+                ret
+_crc32          endp
+
+_TEXT   ends
+;
+    ENDIF ; !USE_ZLIB
+;
+end
diff --git a/win32/crc_i386.c b/win32/crc_i386.c
new file mode 100644 (file)
index 0000000..e8a2faf
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* crc_i386.c -- Microsoft 32-bit C/C++ adaptation of crc_i386.asm
+ * Created by Rodney Brown from crc_i386.asm, modified by Chr. Spieler.
+ *
+ * Original coded (in crc_i386.asm) and put into the public domain
+ * by Paul Kienitz and Christian Spieler.
+ *
+ * Revised 06-Oct-96, Scott Field (sfield@microsoft.com)
+ *   fixed to assemble with masm by not using .model directive which makes
+ *   assumptions about segment alignment.  Also,
+ *   avoid using loop, and j[e]cxz where possible.  Use mov + inc, rather
+ *   than lodsb, and other misc. changes resulting in the following performance
+ *   increases:
+ *
+ *      unrolled loops                NO_UNROLLED_LOOPS
+ *      *8    >8      <8              *8      >8      <8
+ *
+ *      +54%  +42%    +35%            +82%    +52%    +25%
+ *
+ *   first item in each table is input buffer length, even multiple of 8
+ *   second item in each table is input buffer length, > 8
+ *   third item in each table is input buffer length, < 8
+ *
+ * Revised 02-Apr-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)
+ *   Incorporated Rodney Brown's 32-bit-reads optimization as found in the
+ *   UNIX AS source crc_i386.S. This new code can be disabled by defining
+ *   the macro symbol NO_32_BIT_LOADS.
+ *
+ * Revised 12-Oct-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)
+ *   Incorporated Rodney Brown's additional tweaks for 32-bit-optimized CPUs
+ *   (like the Pentium Pro, Pentium II, and probably some Pentium clones).
+ *   This optimization is controlled by the macro symbol __686 and is disabled
+ *   by default. (This default is based on the assumption that most users
+ *   do not yet work on a Pentium Pro or Pentium II machine ...)
+ *
+ * Revised 16-Nov-97, Chr. Spieler: Made code compatible with Borland C++
+ *   32-bit, removed unneeded kludge for potentially unknown movzx mnemonic,
+ *   confirmed correct working with MS VC++ (32-bit).
+ *
+ * Revised 22-May-98, Peter Kunath, Chr. Spieler: The 16-Nov-97 revision broke
+ *   MSVC 5.0. Inside preprocessor macros, each instruction is enclosed in its
+ *   own __asm {...} construct.  For MSVC, a "#pragma warning" was added to
+ *   shut up the "no return value" warning message.
+ *
+ * Revised 13-Dec-98, Chr. Spieler: Modified path to "zip.h" header file.
+ *
+ * Revised 16-Jan-2005, Cosmin Truta: Added the ASM_CRC guard, for easier
+ *   switching between ASM vs. non-ASM builds, when handling makefiles.
+ *   Also enabled the 686 build by default, because there are hardly any
+ *   pre-686 CPUs in serious use nowadays. (See the 12-Oct-97 note above.)
+ *
+ * FLAT memory model assumed.
+ *
+ * Loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.
+ * This results in shorter code at the expense of reduced performance.
+ *
+ */
+
+#include "../zip.h"
+
+#if defined(ASM_CRC) && !defined(USE_ZLIB)
+
+#if !defined(PRE_686) && !defined(__686)
+#  define __686
+#endif
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+
+/* Select wether the following inline-assember code is supported. */
+#if (defined(_MSC_VER) && _MSC_VER >= 700)
+#if (defined(_M_IX86) && _M_IX86 >= 300)
+#  define MSC_INLINE_ASM_32BIT_SUPPORT
+   /* Disable warning for no return value, typical of asm functions */
+#  pragma warning( disable : 4035 )
+#endif
+#endif
+
+#if (defined(__BORLANDC__) && __BORLANDC__ >= 452)
+#  define MSC_INLINE_ASM_32BIT_SUPPORT
+#endif
+
+#ifdef MSC_INLINE_ASM_32BIT_SUPPORT
+/* This code is intended for Microsoft C/C++ (32-bit) compatible compilers. */
+
+/*
+ * These two (three) macros make up the loop body of the CRC32 cruncher.
+ * registers modified:
+ *   eax  : crc value "c"
+ *   esi  : pointer to next data byte (or dword) "buf++"
+ * registers read:
+ *   edi  : pointer to base of crc_table array
+ * scratch registers:
+ *   ebx  : index into crc_table array
+ *          (requires upper three bytes = 0 when __686 is undefined)
+ */
+#ifndef __686
+#define Do_CRC { \
+  __asm { mov   bl, al }; \
+  __asm { shr   eax, 8 }; \
+  __asm { xor   eax, [edi+ebx*4] }; }
+#else /* __686 */
+#define Do_CRC { \
+  __asm { movzx ebx, al }; \
+  __asm { shr   eax, 8  }; \
+  __asm { xor   eax, [edi+ebx*4] }; }
+#endif /* ?__686 */
+
+#define Do_CRC_byte { \
+  __asm { xor   al, byte ptr [esi] }; \
+  __asm { inc   esi }; \
+  Do_CRC; }
+
+#ifndef NO_32_BIT_LOADS
+#define Do_CRC_dword { \
+  __asm { xor   eax, dword ptr [esi] }; \
+  __asm { add   esi, 4 }; \
+  Do_CRC; \
+  Do_CRC; \
+  Do_CRC; \
+  Do_CRC; }
+#endif /* !NO_32_BIT_LOADS */
+
+/* ========================================================================= */
+ulg crc32(crc, buf, len)
+    ulg crc;                    /* crc shift register */
+    ZCONST uch *buf;            /* pointer to bytes to pump through */
+    extent len;                 /* number of bytes in buf[] */
+/* Run a set of bytes through the crc shift register.  If buf is a NULL
+   pointer, then initialize the crc shift register contents instead.
+   Return the current crc in either case. */
+{
+    __asm {
+                push    edx
+                push    ecx
+
+                mov     esi,buf         ;/* 2nd arg: uch *buf              */
+                sub     eax,eax         ;/*> if (!buf)                     */
+                test    esi,esi         ;/*>   return 0;                   */
+                jz      fine            ;/*> else {                        */
+
+                call    get_crc_table
+                mov     edi,eax
+                mov     eax,crc         ;/* 1st arg: ulg crc               */
+#ifndef __686
+                sub     ebx,ebx         ;/* ebx=0; => bl usable as a dword */
+#endif
+                mov     ecx,len         ;/* 3rd arg: extent len            */
+                not     eax             ;/*>   c = ~crc;                   */
+
+                test    ecx,ecx
+#ifndef NO_UNROLLED_LOOPS
+                jz      bail
+#  ifndef NO_32_BIT_LOADS
+align_loop:
+                test    esi,3           ;/* align buf pointer on next      */
+                jz      aligned_now     ;/*  dword boundary                */
+    }
+                Do_CRC_byte             ;
+    __asm {
+                dec     ecx
+                jnz     align_loop
+aligned_now:
+#  endif /* !NO_32_BIT_LOADS */
+                mov     edx,ecx         ;/* save len in edx  */
+                shr     ecx,3           ;/* ecx = len / 8    */
+                jz      No_Eights
+; align loop head at start of 486 internal cache line !!
+                align   16
+Next_Eight:
+    }
+#  ifndef NO_32_BIT_LOADS
+                Do_CRC_dword ;
+                Do_CRC_dword ;
+#  else /* NO_32_BIT_LOADS */
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+#  endif /* ?NO_32_BIT_LOADS */
+    __asm {
+                dec     ecx
+                jnz     Next_Eight
+No_Eights:
+                mov     ecx,edx
+                and     ecx,000000007H  ;/* ecx = len % 8    */
+
+#endif /* !NO_UNROLLED_LOOPS */
+                jz      bail            ;/*>  if (len)                     */
+; align loop head at start of 486 internal cache line !!
+                align   16
+loupe:                                  ;/*>    do { */
+    }
+                Do_CRC_byte             ;/*       c = CRC32(c, *buf++);    */
+    __asm {
+                dec     ecx             ;/*>    } while (--len);           */
+                jnz     loupe
+
+bail:                                   ;/*> }                             */
+                not     eax             ;/*> return ~c;                    */
+fine:
+                pop     ecx
+                pop     edx
+    }
+#ifdef NEED_RETURN
+    return _EAX;
+#endif
+}
+#endif /* MSC_INLINE_ASM_32BIT_SUPPORT */
+#if (defined(_MSC_VER) && _MSC_VER >= 700)
+#if (defined(_M_IX86) && _M_IX86 >= 300)
+   /* Reenable missing return value warning */
+#  pragma warning( default : 4035 )
+#endif
+#endif
+#endif /* ASM_CRC && !USE_ZLIB */
diff --git a/win32/crc_lcc.asm b/win32/crc_lcc.asm
new file mode 100644 (file)
index 0000000..3c7a41c
--- /dev/null
@@ -0,0 +1,119 @@
+;===========================================================================
+; Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 2004-May-22 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/licen; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+;===========================================================================
+; crc_lcc.asm, optimized CRC calculation function for Zip and UnZip,
+; created by Paul Kienitz and Christian Spieler.  Last revised 24 Dec 98.
+;
+; The code in this file has been copied verbatim from crc_i386.{asm|S};
+; only the assembler syntax and metacommands have been adapted to
+; the habits of the free LCC-Win32 C compiler package.
+; This version of the code uses the "optimized for i686" variant of
+; crc_i386.{asm|S}.
+; IMPORTANT NOTE to the Info-ZIP editors:
+; The TAB characters in this source file are required by the parser of
+; the LCC-Win32 assembler program and MUST NOT be removed!!
+;
+; For more information (and a revision log), look into the original
+; source files.
+;
+       .text
+       .file "crc32.c"
+       .text
+       .type   _crc32,function
+_crc32:
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ecx
+       pushl   %ebx
+       pushl   %esi
+       pushl   %edi
+       .line   34
+       .line   37
+       movl    12(%ebp),%esi
+       subl    %eax,%eax
+       testl   %esi,%esi
+       jz      _$3
+       .line   39
+       call    _get_crc_table
+       movl    %eax,%edi
+       .line   41
+       movl    8(%ebp),%eax
+       movl    16(%ebp),%ecx
+       notl    %eax
+       testl   %ecx,%ecx
+       jz      _$4
+_$5:
+       testl   $3,%esi
+       jz      _$6
+       xorb    (%esi),%al
+       incl    %esi
+       movzbl  %al,%ebx
+       shrl    $8,%eax
+       xorl    (%edi,%ebx,4),%eax
+       decl    %ecx
+       jnz     _$5
+_$6:
+       movl    %ecx,%edx
+       shrl    $3,%ecx
+       jz      _$8
+_$7:
+       xorl    (%esi),%eax
+       addl    $4,%esi
+       movzbl  %al,%ebx
+       shrl    $8,%eax
+       xorl    (%edi,%ebx,4),%eax
+       movzbl  %al,%ebx
+       shrl    $8,%eax
+       xorl    (%edi,%ebx,4),%eax
+       movzbl  %al,%ebx
+       shrl    $8,%eax
+       xorl    (%edi,%ebx,4),%eax
+       movzbl  %al,%ebx
+       shrl    $8,%eax
+       xorl    (%edi,%ebx,4),%eax
+       xorl    (%esi),%eax
+       addl    $4,%esi
+       movzbl  %al,%ebx
+       shrl    $8,%eax
+       xorl    (%edi,%ebx,4),%eax
+       movzbl  %al,%ebx
+       shrl    $8,%eax
+       xorl    (%edi,%ebx,4),%eax
+       movzbl  %al,%ebx
+       shrl    $8,%eax
+       xorl    (%edi,%ebx,4),%eax
+       movzbl  %al,%ebx
+       shrl    $8,%eax
+       xorl    (%edi,%ebx,4),%eax
+       decl    %ecx
+       jnz     _$7
+_$8:
+       movl    %edx,%ecx
+       andl    $7,%ecx
+       jz      _$4
+_$9:
+       xorb    (%esi),%al
+       incl    %esi
+       movzbl  %al,%ebx
+       shrl    $8,%eax
+       xorl    (%edi,%ebx,4),%eax
+       decl    %ecx
+       jnz     _$9
+_$4:
+       xorl    $0xffffffff,%eax
+_$3:
+       .line   52
+       popl    %edi
+       popl    %esi
+       popl    %ebx
+       leave
+       ret
+_$34:
+       .size   _crc32,_$34-_crc32
+       .globl  _crc32
+       .extern _get_crc_table
diff --git a/win32/gvmat64.asm b/win32/gvmat64.asm
new file mode 100644 (file)
index 0000000..4b5aa4d
--- /dev/null
@@ -0,0 +1,513 @@
+;uInt longest_match_x64(
+;    deflate_state *s,
+;    IPos cur_match);                             /* current match */
+
+; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86
+; Copyright (C) 1995-2005 Jean-loup Gailly, Brian Raiter and Gilles Vollant.
+;
+; File written by Gilles Vollant, by converting to assembly the longest_match
+;  from Jean-loup Gailly in deflate.c of zLib and infoZip zip.
+;
+;  and by taking inspiration on asm686 with masm, optimised assembly code 
+;        from Brian Raiter, written 1998
+;
+;         http://www.zlib.net
+;         http://www.winimage.com/zLibDll
+;         http://www.muppetlabs.com/~breadbox/software/assembly.html
+;
+; to compile this file for infozip Zip, I use option:
+;   ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm
+;
+; to compile this file for zLib, I use option:
+;   ml64.exe /Flgvmat64 /c /Zi gvmat64.asm
+; Be carrefull to adapt zlib1222add below to your version of zLib
+;   (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change
+;    value of zlib1222add later)
+;
+; This file compile with Microsoft Macro Assembler (x64) for AMD64
+;
+;   ml64.exe is given with Visual Studio 2005 and Windows 2003 server DDK
+;
+;   (you can get Windows 2003 server DDK with ml64 and cl for AMD64 from
+;      http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
+;
+
+
+;uInt longest_match(s, cur_match)
+;    deflate_state *s;
+;    IPos cur_match;                             /* current match */
+.code
+longest_match PROC
+
+
+;LocalVarsSize   equ 88
+ LocalVarsSize   equ 72
+
+; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12
+; free register :  r14,r15
+; register can be saved : rsp
+
+ chainlenwmask   equ  rsp + 8 - LocalVarsSize    ; high word: current chain len
+                                                 ; low word: s->wmask
+;window          equ  rsp + xx - LocalVarsSize   ; local copy of s->window ; stored in r10
+;windowbestlen   equ  rsp + xx - LocalVarsSize   ; s->window + bestlen , use r10+r11
+;scanstart       equ  rsp + xx - LocalVarsSize   ; first two bytes of string ; stored in r12w
+;scanend         equ  rsp + xx - LocalVarsSize   ; last two bytes of string use ebx
+;scanalign       equ  rsp + xx - LocalVarsSize   ; dword-misalignment of string r13
+;bestlen         equ  rsp + xx - LocalVarsSize   ; size of best match so far -> r11d
+;scan            equ  rsp + xx - LocalVarsSize   ; ptr to string wanting match -> r9
+IFDEF INFOZIP
+ELSE
+ nicematch       equ  (rsp + 16 - LocalVarsSize) ; a good enough match size
+ENDIF
+
+save_rdi        equ  rsp + 24 - LocalVarsSize
+save_rsi        equ  rsp + 32 - LocalVarsSize
+save_rbx        equ  rsp + 40 - LocalVarsSize
+save_rbp        equ  rsp + 48 - LocalVarsSize
+save_r12        equ  rsp + 56 - LocalVarsSize
+save_r13        equ  rsp + 64 - LocalVarsSize
+;save_r14        equ  rsp + 72 - LocalVarsSize
+;save_r15        equ  rsp + 80 - LocalVarsSize
+
+
+
+;  all the +4 offsets are due to the addition of pending_buf_size (in zlib
+;  in the deflate_state structure since the asm code was first written
+;  (if you compile with zlib 1.0.4 or older, remove the +4).
+;  Note : these value are good with a 8 bytes boundary pack structure
+
+
+    MAX_MATCH           equ     258
+    MIN_MATCH           equ     3
+    MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)
+
+
+;;; Offsets for fields in the deflate_state structure. These numbers
+;;; are calculated from the definition of deflate_state, with the
+;;; assumption that the compiler will dword-align the fields. (Thus,
+;;; changing the definition of deflate_state could easily cause this
+;;; program to crash horribly, without so much as a warning at
+;;; compile time. Sigh.)
+
+;  all the +zlib1222add offsets are due to the addition of fields
+;  in zlib in the deflate_state structure since the asm code was first written
+;  (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
+;  (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
+;  if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
+
+
+IFDEF INFOZIP
+
+_DATA   SEGMENT
+COMM    window_size:DWORD
+; WMask ; 7fff
+COMM    window:BYTE:010040H
+COMM    prev:WORD:08000H
+; MatchLen : unused
+; PrevMatch : unused
+COMM    strstart:DWORD
+COMM    match_start:DWORD
+; Lookahead : ignore
+COMM    prev_length:DWORD ; PrevLen
+COMM    max_chain_length:DWORD
+COMM    good_match:DWORD
+COMM    nice_match:DWORD
+prev_ad equ OFFSET prev
+window_ad equ OFFSET window
+nicematch equ nice_match
+_DATA ENDS
+WMask equ 07fffh
+
+ELSE
+
+  IFNDEF zlib1222add
+    zlib1222add equ 0
+  ENDIF
+dsWSize         equ 56+zlib1222add+(zlib1222add/2)
+dsWMask         equ 64+zlib1222add+(zlib1222add/2)
+dsWindow        equ 72+zlib1222add
+dsPrev          equ 88+zlib1222add
+dsMatchLen      equ 128+zlib1222add
+dsPrevMatch     equ 132+zlib1222add
+dsStrStart      equ 140+zlib1222add
+dsMatchStart    equ 144+zlib1222add
+dsLookahead     equ 148+zlib1222add
+dsPrevLen       equ 152+zlib1222add
+dsMaxChainLen   equ 156+zlib1222add
+dsGoodMatch     equ 172+zlib1222add
+dsNiceMatch     equ 176+zlib1222add
+
+window_size     equ [ rcx + dsWSize]
+WMask           equ [ rcx + dsWMask]
+window_ad       equ [ rcx + dsWindow]
+prev_ad         equ [ rcx + dsPrev]
+strstart        equ [ rcx + dsStrStart]
+match_start     equ [ rcx + dsMatchStart]
+Lookahead       equ [ rcx + dsLookahead] ; 0ffffffffh on infozip
+prev_length     equ [ rcx + dsPrevLen]
+max_chain_length equ [ rcx + dsMaxChainLen]
+good_match      equ [ rcx + dsGoodMatch]
+nice_match      equ [ rcx + dsNiceMatch]
+ENDIF
+
+; parameter 1 in r8(deflate state s), param 2 in rdx (cur match)
+
+; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and
+; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp
+;
+; All registers must be preserved across the call, except for
+;   rax, rcx, rdx, r8, r9, r10, and r11, which are scratch.
+
+
+
+;;; Save registers that the compiler may be using, and adjust esp to
+;;; make room for our stack frame.
+
+
+;;; Retrieve the function arguments. r8d will hold cur_match
+;;; throughout the entire function. edx will hold the pointer to the
+;;; deflate_state structure during the function's setup (before
+;;; entering the main loop.
+
+; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match)
+
+; this clear high 32 bits of r8, which can be garbage in both r8 and rdx
+
+        mov [save_rdi],rdi
+        mov [save_rsi],rsi
+        mov [save_rbx],rbx
+        mov [save_rbp],rbp
+IFDEF INFOZIP
+        mov r8d,ecx
+ELSE
+        mov r8d,edx
+ENDIF
+        mov [save_r12],r12
+        mov [save_r13],r13
+;        mov [save_r14],r14
+;        mov [save_r15],r15
+
+
+;;; uInt wmask = s->w_mask;
+;;; unsigned chain_length = s->max_chain_length;
+;;; if (s->prev_length >= s->good_match) {
+;;;     chain_length >>= 2;
+;;; }
+
+        mov edi, prev_length
+        mov esi, good_match
+        mov eax, WMask
+        mov ebx, max_chain_length
+        cmp edi, esi
+        jl  LastMatchGood
+        shr ebx, 2
+LastMatchGood:
+
+;;; chainlen is decremented once beforehand so that the function can
+;;; use the sign flag instead of the zero flag for the exit test.
+;;; It is then shifted into the high word, to make room for the wmask
+;;; value, which it will always accompany.
+
+        dec ebx
+        shl ebx, 16
+        or  ebx, eax
+
+;;; on zlib only
+;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+IFDEF INFOZIP
+        mov [chainlenwmask], ebx
+; on infozip nice_match = [nice_match]
+ELSE
+        mov eax, nice_match
+        mov [chainlenwmask], ebx
+        mov r10d, Lookahead
+        cmp r10d, eax
+        cmovnl r10d, eax
+        mov [nicematch],r10d
+ENDIF
+
+;;; register Bytef *scan = s->window + s->strstart;
+        mov r10, window_ad
+        mov ebp, strstart
+        lea r13, [r10 + rbp]
+
+;;; Determine how many bytes the scan ptr is off from being
+;;; dword-aligned.
+
+         mov r9,r13
+         neg r13
+         and r13,3
+
+;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;
+IFDEF INFOZIP
+        mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1))
+ELSE
+        mov eax, window_size
+        sub eax, MIN_LOOKAHEAD
+ENDIF
+        xor edi,edi
+        sub ebp, eax
+
+        mov r11d, prev_length
+
+        cmovng ebp,edi
+
+;;; int best_len = s->prev_length;
+
+
+;;; Store the sum of s->window + best_len in esi locally, and in esi.
+
+       lea  rsi,[r10+r11]
+
+;;; register ush scan_start = *(ushf*)scan;
+;;; register ush scan_end   = *(ushf*)(scan+best_len-1);
+;;; Posf *prev = s->prev;
+
+        movzx r12d,word ptr [r9]
+        movzx ebx, word ptr [r9 + r11 - 1]
+
+        mov rdi, prev_ad
+
+;;; Jump into the main loop.
+
+        mov edx, [chainlenwmask]
+
+        cmp bx,word ptr [rsi + r8 - 1]
+        jz  LookupLoopIsZero
+
+LookupLoop1:
+        and r8d, edx
+
+        movzx   r8d, word ptr [rdi + r8*2]
+        cmp r8d, ebp
+        jbe LeaveNow
+        sub edx, 00010000h
+        js  LeaveNow
+
+LoopEntry1:
+        cmp bx,word ptr [rsi + r8 - 1]
+        jz  LookupLoopIsZero
+
+LookupLoop2:
+        and r8d, edx
+
+        movzx   r8d, word ptr [rdi + r8*2]
+        cmp r8d, ebp
+        jbe LeaveNow
+        sub edx, 00010000h
+        js  LeaveNow
+
+LoopEntry2:
+        cmp bx,word ptr [rsi + r8 - 1]
+        jz  LookupLoopIsZero
+
+LookupLoop4:
+        and r8d, edx
+
+        movzx   r8d, word ptr [rdi + r8*2]
+        cmp r8d, ebp
+        jbe LeaveNow
+        sub edx, 00010000h
+        js  LeaveNow
+
+LoopEntry4:
+
+        cmp bx,word ptr [rsi + r8 - 1]
+        jnz LookupLoop1
+        jmp LookupLoopIsZero
+
+
+;;; do {
+;;;     match = s->window + cur_match;
+;;;     if (*(ushf*)(match+best_len-1) != scan_end ||
+;;;         *(ushf*)match != scan_start) continue;
+;;;     [...]
+;;; } while ((cur_match = prev[cur_match & wmask]) > limit
+;;;          && --chain_length != 0);
+;;;
+;;; Here is the inner loop of the function. The function will spend the
+;;; majority of its time in this loop, and majority of that time will
+;;; be spent in the first ten instructions.
+;;;
+;;; Within this loop:
+;;; ebx = scanend
+;;; r8d = curmatch
+;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
+;;; esi = windowbestlen - i.e., (window + bestlen)
+;;; edi = prev
+;;; ebp = limit
+
+LookupLoop:
+        and r8d, edx
+
+        movzx   r8d, word ptr [rdi + r8*2]
+        cmp r8d, ebp
+        jbe LeaveNow
+        sub edx, 00010000h
+        js  LeaveNow
+
+LoopEntry:
+
+        cmp bx,word ptr [rsi + r8 - 1]
+        jnz LookupLoop1
+LookupLoopIsZero:
+        cmp     r12w, word ptr [r10 + r8]
+        jnz LookupLoop1
+
+
+;;; Store the current value of chainlen.
+        mov [chainlenwmask], edx
+
+;;; Point edi to the string under scrutiny, and esi to the string we
+;;; are hoping to match it up with. In actuality, esi and edi are
+;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
+;;; initialized to -(MAX_MATCH_8 - scanalign).
+
+        lea rsi,[r8+r10]
+        mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8)
+        lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8]
+        lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8]
+
+        prefetcht1 [rsi+rdx]
+        prefetcht1 [rdi+rdx]
+        
+     
+;;; Test the strings for equality, 8 bytes at a time. At the end,
+;;; adjust rdx so that it is offset to the exact byte that mismatched.
+;;;
+;;; We already know at this point that the first three bytes of the
+;;; strings match each other, and they can be safely passed over before
+;;; starting the compare loop. So what this code does is skip over 0-3
+;;; bytes, as much as necessary in order to dword-align the edi
+;;; pointer. (rsi will still be misaligned three times out of four.)
+;;;
+;;; It should be confessed that this loop usually does not represent
+;;; much of the total running time. Replacing it with a more
+;;; straightforward "rep cmpsb" would not drastically degrade
+;;; performance.
+
+
+LoopCmps:
+        mov rax, [rsi + rdx]
+        xor rax, [rdi + rdx]
+        jnz LeaveLoopCmps
+
+        mov rax, [rsi + rdx + 8]
+        xor rax, [rdi + rdx + 8]
+        jnz LeaveLoopCmps8
+
+
+        mov rax, [rsi + rdx + 8+8]
+        xor rax, [rdi + rdx + 8+8]
+        jnz LeaveLoopCmps16
+
+        add rdx,8+8+8
+
+        jmp short LoopCmps
+LeaveLoopCmps16: add rdx,8
+LeaveLoopCmps8: add rdx,8
+LeaveLoopCmps:
+
+        test    eax, 0000FFFFh
+        jnz LenLower
+
+        test eax,0ffffffffh
+
+        jnz LenLower32
+
+        add rdx,4
+        shr rax,32
+        or ax,ax
+        jnz LenLower
+
+LenLower32:
+        shr eax,16
+        add rdx,2
+LenLower:   sub al, 1
+        adc rdx, 0
+;;; Calculate the length of the match. If it is longer than MAX_MATCH,
+;;; then automatically accept it as the best possible match and leave.
+
+        lea rax, [rdi + rdx]
+        sub rax, r9
+        cmp eax, MAX_MATCH
+        jge LenMaximum
+
+;;; If the length of the match is not longer than the best match we
+;;; have so far, then forget it and return to the lookup loop.
+;///////////////////////////////////
+
+        cmp eax, r11d
+        jg  LongerMatch
+
+        lea rsi,[r10+r11]
+
+        mov rdi, prev_ad
+        mov edx, [chainlenwmask]
+        jmp LookupLoop
+
+;;;         s->match_start = cur_match;
+;;;         best_len = len;
+;;;         if (len >= nice_match) break;
+;;;         scan_end = *(ushf*)(scan+best_len-1);
+
+LongerMatch:
+        mov r11d, eax
+        mov match_start, r8d
+        cmp eax, [nicematch]
+        jge LeaveNow
+
+        lea rsi,[r10+rax]
+
+        movzx   ebx, word ptr [r9 + rax - 1]
+        mov rdi, prev_ad
+        mov edx, [chainlenwmask]
+        jmp LookupLoop
+
+;;; Accept the current string, with the maximum possible length.
+
+LenMaximum:
+        mov r11d,MAX_MATCH
+        mov match_start, r8d
+
+;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+;;; return s->lookahead;
+
+LeaveNow:
+IFDEF INFOZIP
+        mov eax,r11d
+ELSE
+        mov eax, Lookahead
+        cmp r11d, eax
+        cmovng eax, r11d
+ENDIF
+
+;;; Restore the stack and return from whence we came.
+
+
+        mov rsi,[save_rsi]
+        mov rdi,[save_rdi]
+        mov rbx,[save_rbx]
+        mov rbp,[save_rbp]
+        mov r12,[save_r12]
+        mov r13,[save_r13]
+;        mov r14,[save_r14]
+;        mov r15,[save_r15]
+
+
+        ret 0
+; please don't remove this string !
+; Your can freely use gvmat64 in any free or commercial app
+; but it is far better don't remove the string in the binary!
+    db     0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0
+longest_match   ENDP
+
+match_init PROC
+  ret 0
+match_init ENDP
+
+
+END
diff --git a/win32/lm32_lcc.asm b/win32/lm32_lcc.asm
new file mode 100644 (file)
index 0000000..2fde1a4
--- /dev/null
@@ -0,0 +1,174 @@
+;===========================================================================
+; Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 2004-May-22 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+;===========================================================================
+; match32.asm by Jean-loup Gailly.
+
+; match32.asm, optimized version of longest_match() in deflate.c
+; To be used only with 32 bit flat model. To simplify the code, the option
+; -DDYN_ALLOC is not supported.
+; This file is only optional. If you don't have an assembler, use the
+; C version (add -DNO_ASM to CFLAGS in makefile and remove match.o
+; from OBJI). If you have reduced WSIZE in zip.h, then make sure this is
+; assembled with an equivalent -DWSIZE=<whatever>.
+;
+; Win32 (Windows NT) version - 1994/04/13 by Steve Salisbury
+; * works with Microsoft MASM 6.1X and Microsoft Visual C++ / 32-bit edition
+;
+; The code in this file has been copied verbatim from match32.{asm|S};
+; only the assembler syntax and metacommands have been adapted to
+; the habits of the free LCC-Win32 C compiler package.
+; IMPORTANT NOTE to the Info-ZIP editors:
+; The TAB characters in this source file are required by the parser of
+; the LCC-Win32 assembler program and MUST NOT be removed!!
+;
+;==============================================================================
+;
+; Do NOT assemble this source if external crc32 routine from zlib gets used.
+;
+
+
+;/* This version is for 386 Unix or OS/2 in 32 bit mode.
+; * Warning: it uses the AT&T syntax: mov source,dest
+; * This file is only optional. If you want to force the C version,
+; * add -DNO_ASM to CFLAGS in Makefile and set OBJA to an empty string.
+; * If you have reduced WSIZE in (g)zip.h, then make sure this is
+; * assembled with an equivalent -DWSIZE=<whatever>.
+; * This version assumes static allocation of the arrays (-DDYN_ALLOC not used).
+; */
+
+        .text
+        .file  "match.S"
+
+
+        .text
+        .type  _match_init,function
+
+_match_init:
+        ret
+_$98:
+        .size  _match_init,_$98-_match_init
+        .globl _match_init
+
+;/*-----------------------------------------------------------------------
+; * Set match_start to the longest match starting at the given string and
+; * return its length. Matches shorter or equal to prev_length are discarded,
+; * in which case the result is equal to prev_length and match_start is
+; * garbage.
+; * IN assertions: cur_match is the head of the hash chain for the current
+; *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+; */
+
+        .align 4
+        .type  _longest_match,function
+
+_longest_match: ;/* int longest_match(cur_match) */
+
+;       cur_match     equ 20(%esp)
+;     /* return address */               /* esp+16 */
+        push    %ebp
+        push    %edi
+;/* esp+8  */
+        push    %esi
+;/* esp+4  */
+        push    %ebx
+;/* esp    */
+
+;/*
+; *      match        equ esi
+; *      scan         equ edi
+; *      chain_length equ ebp
+; *      best_len     equ ebx
+; *      limit        equ edx
+; */
+        mov     20(%esp),%esi
+        mov     _strstart,%edx
+        mov     _max_chain_length,%ebp
+        mov     %edx,%edi
+        sub     $(32768-262),%edx
+        cld
+        jae     limit_ok
+        sub     %edx,%edx
+limit_ok:
+        add     $2+_window,%edi
+        mov     _prev_length,%ebx
+        movw    -2(%edi),%cx
+        movw    -3(%ebx,%edi),%ax
+        cmp     _good_match,%ebx
+        jb      do_scan
+        shr     $2,%ebp
+        jmp     do_scan
+
+        .align 4
+long_loop:
+;/* at this point, edi == scan+2, esi == cur_match */
+        movw    -3(%ebx,%edi),%ax
+        movw     -2(%edi),%cx
+short_loop:
+;/*
+; * at this point, di == scan+2, si == cur_match,
+; * ax = scan[best_len-1..best_len] and cx = scan[0..1]
+; */
+        and     $(32768-1), %esi
+        dec     %ebp
+        movw    _prev(,%esi,2),%si
+        jz      the_end
+        cmp     %edx,%esi
+        jbe     the_end
+do_scan:
+        cmpw    _window-1(%ebx,%esi),%ax
+        jne     short_loop
+        cmpw    _window(%esi),%cx
+        jne     short_loop
+
+        add     $2+_window,%esi
+        mov     $((258>>1)-1),%ecx
+        mov     %edi,%eax
+        repe;   cmpsw
+;/* loop until mismatch */
+        je      maxmatch
+;/* match of length MAX_MATCH? */
+mismatch:
+        movb    -2(%edi),%cl
+        xchg    %edi,%eax
+        subb    -2(%esi),%cl
+        sub     %edi,%eax
+        sub     $2+_window,%esi
+        sub     %eax,%esi
+        subb    $1,%cl
+        adc     $0,%eax
+        cmp     %ebx,%eax
+        jle     long_loop
+        mov     %esi,_match_start
+        mov     %eax,%ebx
+        cmp     _nice_match,%eax
+; /* len >= nice_match ? */
+        jl      long_loop
+the_end:
+        mov     %ebx,%eax
+        pop     %ebx
+        pop     %esi
+        pop     %edi
+        pop     %ebp
+        ret
+        .align 4
+maxmatch:
+        cmpsb
+        jmp     mismatch
+_$99:
+
+        .size  _longest_match,_$99-_longest_match
+        .globl _longest_match
+
+        .extern        _nice_match
+        .extern        _good_match
+        .extern        _max_chain_length
+        .extern        _match_start
+        .extern        _strstart
+        .extern        _prev_length
+        .extern        _prev
+        .extern        _window
diff --git a/win32/makefile.a64 b/win32/makefile.a64
new file mode 100644 (file)
index 0000000..521950e
--- /dev/null
@@ -0,0 +1,134 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for
+# 32-bit Microsoft Visual C++
+
+# To use, do "nmake -f makefile.w32"
+
+# Add -DNO_ASM to CFLAGS and comment out the ASMOBJS definition if
+# you do not have masm 6.1X.
+
+# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)
+# should be added to the environment via "set LOCAL_ZIP=-DFOO" or added
+# to the declaration of LOC here:
+LOC = $(LOCAL_ZIP)
+
+# Uncomment the following macro to use the optimized assembler
+# routines in Zip:
+ASMOBJS = gvmat64.obj
+
+# ------------- 32-bit Microsoft Visual C++ -------------
+CC=cl -nologo
+CFLAGS=-W3 -O2 -DNO_ASM_CRC -DASMV -DWIN32 $(LOC) 
+UTILFLAGS=$(CFLAGS) -DUTIL -Fo$@
+
+# Remove "-coff" from ASFLAGS if you do not have MASM 6.11.
+
+AS=ml64 -nologo
+ASFLAGS= /c /Zi /DINFOZIP
+
+# If you build 16-bit executables with MS Visual C++ v1.0/1.5 and link them
+# with the /KNOWEAS switch, you can build dual-mode MS-DOS/Win32 executables
+# by passing the -stub switch to the 32-bit linker to specify the 16-bit part.
+
+LD=link -nologo
+LDFLAGS=advapi32.lib
+
+# variables
+OBJZ = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \
+    crc32.obj crctab.obj globals.obj
+
+OBJI = deflate.obj trees.obj $(ASMOBJS) win32.obj win32zip.obj nt.obj
+
+OBJU = zipfile_.obj fileio_.obj util_.obj globals.obj win32_.obj
+OBJN = zipnote.obj $(OBJU)
+OBJC = zipcloak.obj crctab.obj crypt_.obj ttyio.obj $(OBJU)
+OBJS = zipsplit.obj $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h win32/osdep.h
+
+ZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zips:   $(ZIPS)
+
+zip.obj:        zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+    $(CC) -c $(CFLAGS) $*.c
+
+zipfile.obj:    zipfile.c $(ZIP_H)
+    $(CC) -c $(CFLAGS) $*.c
+
+zipup.obj:      zipup.c $(ZIP_H) revision.h crypt.h win32/zipup.h
+    $(CC) -c $(CFLAGS) $*.c
+
+fileio.obj:     fileio.c $(ZIP_H)
+    $(CC) -c $(CFLAGS) $*.c
+
+util.obj:       util.c $(ZIP_H)
+    $(CC) -c $(CFLAGS) $*.c
+
+globals.obj:    globals.c $(ZIP_H)
+    $(CC) -c $(CFLAGS) $*.c
+
+deflate.obj:    deflate.c $(ZIP_H)
+    $(CC) -c $(CFLAGS) $*.c
+
+trees.obj:      trees.c $(ZIP_H)
+    $(CC) -c $(CFLAGS) $*.c
+
+crc32.obj:      crc32.c $(ZIP_H)
+    $(CC) -c $(CFLAGS) $*.c
+
+crctab.obj:     crctab.c $(ZIP_H)
+    $(CC) -c $(CFLAGS) $*.c
+
+crypt.obj:      crypt.c $(ZIP_H) crypt.h ttyio.h
+    $(CC) -c $(CFLAGS) $*.c
+
+ttyio.obj:      ttyio.c $(ZIP_H) crypt.h ttyio.h
+    $(CC) -c $(CFLAGS) $*.c
+
+win32zip.obj:   win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h
+    $(CC) -c $(CFLAGS) -I. win32/win32zip.c
+
+win32.obj:      win32/win32.c $(ZIP_H) win32/win32zip.h
+    $(CC) -c $(CFLAGS) -I. win32/win32.c
+
+nt.obj:         win32/nt.c $(ZIP_H) win32/nt.h
+    $(CC) -c $(CFLAGS) -I. win32/nt.c
+
+zipcloak.obj:   zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+    $(CC) -c $(CFLAGS) $*.c
+
+zipnote.obj:    zipnote.c $(ZIP_H) revision.h
+    $(CC) -c $(CFLAGS) $*.c
+
+zipsplit.obj:   zipsplit.c $(ZIP_H) revision.h
+    $(CC) -c $(CFLAGS) $*.c
+
+zipfile_.obj:   zipfile.c $(ZIP_H)
+    $(CC) -c $(UTILFLAGS) zipfile.c
+
+fileio_.obj:    fileio.c $(ZIP_H)
+    $(CC) -c $(UTILFLAGS) fileio.c
+
+util_.obj:      util.c $(ZIP_H)
+    $(CC) -c $(UTILFLAGS) util.c
+
+crypt_.obj:     crypt.c $(ZIP_H) crypt.h ttyio.h
+    $(CC) -c $(UTILFLAGS) crypt.c
+
+win32_.obj:     win32/win32.c $(ZIP_H) win32/win32zip.h
+    $(CC) -c $(UTILFLAGS) -I. win32/win32.c
+
+gvmat64.obj:    win32/gvmat64.asm
+    $(AS) $(ASFLAGS) win32\gvmat64.asm
+
+zip.exe: $(OBJZ) $(OBJI)
+    $(LD) $(LDFLAGS) $(OBJZ) $(OBJI)
+
+zipcloak.exe: $(OBJC)
+    $(LD) $(LDFLAGS) $(OBJC)
+
+zipnote.exe: $(OBJN)
+    $(LD) $(LDFLAGS) $(OBJN)
+
+zipsplit.exe: $(OBJS)
+    $(LD) $(LDFLAGS) $(OBJS)
diff --git a/win32/makefile.bor b/win32/makefile.bor
new file mode 100644 (file)
index 0000000..5f70b81
--- /dev/null
@@ -0,0 +1,179 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for
+# Borland C++ for Windows 9x/NT
+# By E-Yen Tan. Last updated on 24 Jan 2005.
+
+# To use, do "make -fwin32\makefile.bor"
+
+# Add -DNO_ASM to LOC and comment out the ASMOBJS definition below
+# if you do not have tasm32.
+
+# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)
+# should be added to the environment via "set LOCAL_ZIP=-DFOO" or added
+# to the declaration of LOC here:
+!IF $(USEASM)
+LOC = $(LOCAL_ZIP)
+!ELSE
+LOC = -DNO_ASM $(LOCAL_ZIP)
+!ENDIF
+
+# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.
+CPU_TYP = 6
+
+# Uncomment the following macro to use the optimized assembler
+# routines in Zip:
+!IF $(USEASM)
+ASMOBJS = match32.obj crc_i386.obj
+!ENDIF
+
+ASCPUFLAG = __$(CPU_TYP)86
+
+VPATH=.;win32
+CC = bcc32
+CFLAGS=-w -w-aus -w-ccc -w-par -w-sig -O2 -I. -DWIN32 $(LOC)
+UTILFLAGS=-DUTIL $(CFLAGS) -o
+
+!ifdef USETASM16
+AS=tasm
+!else
+AS=tasm32
+!endif
+ASFLAGS=-ml -t -m2 -D$(ASCPUFLAG) $(LOC)
+
+LD=$(CC)
+LDFLAGS=
+
+# variables
+OBJZ1 = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \
+       crc32.obj crctab.obj globals.obj
+OBJZ2 = deflate.obj trees.obj $(ASMOBJS)
+OBJZS = win32zip.obj win32.obj nt.obj
+OBJZ  = $(OBJZ1) $(OBJZ2) $(OBJZS)
+
+OBJU  = zipfile_.obj fileio_.obj util_.obj globals.obj win32_.obj
+OBJN  = zipnote.obj $(OBJU)
+OBJC  = zipcloak.obj crctab.obj crypt_.obj ttyio.obj $(OBJU)
+OBJS  = zipsplit.obj $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h win32/osdep.h
+
+ZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zips: $(ZIPS)
+
+zip.obj:        zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipfile.obj:    zipfile.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+zipup.obj:      zipup.c $(ZIP_H) revision.h crypt.h win32/zipup.h
+       $(CC) -c $(CFLAGS) $*.c
+
+fileio.obj:     fileio.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+util.obj:       util.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+globals.obj:    globals.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+deflate.obj:    deflate.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+trees.obj:      trees.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crc32.obj:      crc32.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crctab.obj:     crctab.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crypt.obj:      crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+ttyio.obj:      ttyio.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+win32zip.obj:   win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h
+    $(CC) -c $(CFLAGS) win32/$*.c
+
+win32.obj:      win32/win32.c $(ZIP_H) win32/win32zip.h
+    $(CC) -c $(CFLAGS) win32/$*.c
+
+nt.obj:         win32/nt.c $(ZIP_H) win32/nt.h
+    $(CC) -c $(CFLAGS) win32/$*.c
+
+zipcloak.obj:   zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipnote.obj:    zipnote.c $(ZIP_H) revision.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipsplit.obj:   zipsplit.c $(ZIP_H) revision.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipfile_.obj:   zipfile.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS)$* zipfile.c
+
+fileio_.obj:    fileio.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS)$* fileio.c
+
+util_.obj:      util.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS)$* util.c
+
+crypt_.obj:     crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(UTILFLAGS)$* crypt.c
+
+win32_.obj:     win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c $(UTILFLAGS)$* win32/win32.c
+
+!ifdef USEMASM
+crc_i386.obj:   win32/crc_i386.asm
+       masm -ml win32/crc_i386.asm,$@;
+!else
+!ifndef ASMOVERBCC32
+crc_i386.obj:   win32/crc_i386.asm
+       $(AS) $(ASFLAGS) win32\crc_i386.asm, $@ ;
+!else
+crc_i386.obj:  win32/crc_i386.c
+       $(CC) -c $(CFLAGS) -o$@ win32/crc_i386.c
+!endif
+!endif
+
+!ifdef USEMASM
+match32.obj:    win32/match32.asm
+       masm -ml win32/match32.asm,$@;
+!else
+match32.obj:    win32/match32.asm
+    $(AS) $(ASFLAGS) win32\match32.asm, $@ ;
+!endif
+
+# we must cut the command line to fit in the MS/DOS 128 byte limit:
+zip.exe: $(OBJZ)
+       echo $(OBJZ1) > zip.rsp
+       echo $(OBJZ2) >> zip.rsp
+       echo $(OBJZS) >> zip.rsp
+       $(LD) $(LDFLAGS) @zip.rsp
+       del zip.rsp
+
+zipcloak.exe: $(OBJC)
+       echo $(OBJC) > zipc.rsp
+       $(LD) $(LDFLAGS) @zipc.rsp
+       del zipc.rsp
+
+zipnote.exe: $(OBJN)
+       echo $(OBJN) > zipn.rsp
+       $(LD) $(LDFLAGS) @zipn.rsp
+       del zipn.rsp
+
+zipsplit.exe: $(OBJS)
+       echo $(OBJS) > zips.rsp
+       $(LD) $(LDFLAGS) @zips.rsp
+       del zips.rsp
+
+clean:
+       del *.obj
+       del *.exe
+       del *.tds
diff --git a/win32/makefile.dj b/win32/makefile.dj
new file mode 100644 (file)
index 0000000..ead72e0
--- /dev/null
@@ -0,0 +1,110 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit
+# for djgpp 2.01 and RSXNTDJ 1.3.1 under Windows 95 / Windows NT
+# Derived from makefile.os2 by E-Yen Tan. Last updated 22 May 1998.
+
+CC = gcc -O2 -m486 -Wall -Zwin32
+CFLAGS = -DWIN32 -DASM_CRC $(LOCAL_ZIP)
+AS = gcc
+ASFLAGS = -Di386
+LDFLAGS = -o ./
+LDFLAGS2 =
+OBJ=.o
+
+CRC32=crc_gcc
+OBJA    = matchgcc.o
+OBJZS   = win32.o win32zip.o nt.o
+OBJUS   = win32_.o
+OSDEP_H = win32/osdep.h
+
+ADVAPI32 = adv32
+ADVAPI32LIB = lib$(ADVAPI32).a
+L_ADVAPI32 = -l$(ADVAPI32)
+
+OBJZ1 = zip$(OBJ) zipfile$(OBJ) zipup$(OBJ) fileio$(OBJ) util$(OBJ) \
+       $(CRC32)$(OBJ) crctab$(OBJ)
+OBJZ2 = globals$(OBJ) deflate$(OBJ) trees$(OBJ) crypt$(OBJ) \
+       ttyio$(OBJ)
+OBJZ  = $(OBJZ1) $(OBJZ2) $(OBJZS) $(OBJA)
+
+OBJU1 = zipfile_$(OBJ) fileio_$(OBJ) util_$(OBJ) globals$(OBJ)
+OBJU  = $(OBJU1) $(OBJUS)
+
+OBJN =  zipnote$(OBJ) $(OBJU)
+OBJS =  zipsplit$(OBJ) $(OBJU)
+OBJC =  zipcloak$(OBJ) crctab$(OBJ) crypt_$(OBJ) ttyio$(OBJ) $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h $(OSDEP_H)
+
+# rules
+
+.SUFFIXES: .c $(OBJ)
+
+.c$(OBJ):
+       $(CC) -c -I. $(CFLAGS) $<
+
+.asm$(OBJ):
+       $(AS) $(ASFLAGS) $<
+
+all:    zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zip$(OBJ):      zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipfile$(OBJ):  zipfile.c $(ZIP_H)
+zipup$(OBJ):    zipup.c $(ZIP_H) revision.h crypt.h win32/zipup.h
+fileio$(OBJ):   fileio.c $(ZIP_H)
+util$(OBJ):     util.c $(ZIP_H)
+globals$(OBJ):  globals.c $(ZIP_H)
+deflate$(OBJ):  deflate.c $(ZIP_H)
+trees$(OBJ):    trees.c $(ZIP_H)
+crc32$(OBJ):    crc32.c $(ZIP_H)
+crctab$(OBJ):   crctab.c $(ZIP_H)
+crypt$(OBJ):    crypt.c $(ZIP_H) crypt.h ttyio.h
+ttyio$(OBJ):    ttyio.c $(ZIP_H) crypt.h ttyio.h
+
+win32zip$(OBJ): win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h
+       $(CC) -c -I. $(CFLAGS) win32/win32zip.c
+
+win32$(OBJ):    win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c -I. $(CFLAGS) win32/win32.c
+
+nt$(OBJ):       win32/nt.c $(ZIP_H) win32/nt.h
+       $(CC) -c -I. $(CFLAGS) win32/nt.c
+
+crc_gcc$(OBJ):  crc_i386.S                                      # 32bit, GNU AS
+       $(AS) $(ASFLAGS) -x assembler-with-cpp -c -o$@ crc_i386.S
+
+matchgcc$(OBJ): match.S
+       $(AS) $(ASFLAGS) -x assembler-with-cpp -c -o$@ match.S
+
+zipcloak$(OBJ): zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipnote$(OBJ):  zipnote.c $(ZIP_H) revision.h
+zipsplit$(OBJ): zipsplit.c $(ZIP_H) revision.h
+
+zipfile_$(OBJ): zipfile.c $(ZIP_H)
+       $(CC) -c -I. $(CFLAGS) -DUTIL -o$@ zipfile.c
+
+fileio_$(OBJ):  fileio.c $(ZIP_H)
+       $(CC) -c -I. $(CFLAGS) -DUTIL -o$@ fileio.c
+
+util_$(OBJ):    util.c $(ZIP_H) os2/os2zip.h
+       $(CC) -c -I. $(CFLAGS) -DUTIL -o$@ util.c
+
+crypt_$(OBJ):   crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c -I. $(CFLAGS) -DUTIL -o$@ crypt.c
+
+win32_$(OBJ):   win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c -I. $(CFLAGS) -DUTIL -o$@ win32/win32.c
+
+$(ADVAPI32LIB):
+       makelib "$(windir)/system/advapi32.dll" -o ./$@
+
+zip.exe: $(OBJZ) $(ADVAPI32LIB)
+       $(CC) $(LDFLAGS)$@ $(OBJZ) $(L_ADVAPI32) $(LDFLAGS2)
+
+zipcloak.exe: $(OBJC)
+       $(CC) $(LDFLAGS)$@ $(OBJC) $(LDFLAGS2)
+
+zipnote.exe: $(OBJN)
+       $(CC) $(LDFLAGS)$@ $(OBJN) $(LDFLAGS2)
+
+zipsplit.exe: $(OBJS)
+       $(CC) $(LDFLAGS)$@ $(OBJS) $(LDFLAGS2)
diff --git a/win32/makefile.emx b/win32/makefile.emx
new file mode 100644 (file)
index 0000000..197a8ea
--- /dev/null
@@ -0,0 +1,291 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit
+# using emx 0.9c+rsxnt for Windows 95/98 and Windows NT and emx 0.9c for DOS.
+# By Kai-Uwe Rommel, Chr. Spieler, E-Yen Tan (and others).
+# Last updated 30th June 1998.
+#
+# Supported Make utilities:
+# - Microsoft/IBM nmake (e.g. from MSC 6.0 or newer)
+# - dmake 3.8 or higher
+# - GNU make, at least version 3.68 (GNUish 16-bit port, RSXNT Make 3.75,
+#   DJGPP v1.12 Make 3.71, some versions of DJGPP v2.x 32-bit Make;
+#   current DJGPP v2.01 Make 3.76.1 does NOT work)
+# - NOT watcom make
+# The "smart" Make utilities mentioned below are Christian Spieler's
+# enhanced version of GNUish 16-bit Make (3.74) and his adaption of these
+# GNU Make sources to EMX (32-bit).
+
+# Supported 32-bit C Compilers (created programs run under WinNT/Win95 only):
+# - GNU gcc (emx/rsxnt kit 0.9c or newer)
+
+# Supported Cross-Compilers for MS-DOS:
+# - GNU gcc (emx kit 0.9c or newer, 32-bit)
+
+# Supported Assemblers:
+# - GNU as with GNU gcc
+
+
+# To use, enter "make/nmake/dmake -f win32/makefile.emx"
+# (this makefile depends on its name being "win32/makefile.emx").
+
+# Add -DDYN_ALLOC to ASFLAGS if you have defined it in tailor.h or CFLAGS
+
+# Note: assembly language modules are really only supported for
+# GNU gcc 32-bit compilation.
+
+
+default:
+       @echo "Enter $(MAKE) -f win32/makefile.emx target"
+       @echo "where target is one of:"
+       @echo "   gcc gccso gccdyn gccdebug gcczl gccdos gccdoszl"
+       @echo "   -----------------------------------------------"
+       @echo "Or, specify a specific target for a partial build,"
+       @echo "This uses >gcc< setup (win32 statically linked binary)"
+
+# emx 0.9c, gcc, PE format, statically linked C runtime and rsxnt.dll
+gcc:   all
+
+# emx 0.9c, gcc, PE format, statically linked C runtime, standalone
+gccso:
+       $(MAKE) -f win32/makefile.emx all \
+       CC="gcc -Zwin32 -Zsys -O2 -m486 -Wall" \
+       CFLAGS="-DWIN32 -DASM_CRC" \
+       AS="gcc -Zwin32" \
+       ASFLAGS="-Di386" \
+       LDFLAGS="-o ./" \
+       LDFLAGS2="-ladvapi32 -s" \
+       OUT="-o" \
+       OBJ=".o" \
+       CRC32="crc_gcc" \
+       OBJA="matchgcc.o" \
+       DEF="win32/zip.def"
+
+# emx 0.9c, gcc, PE format, dynamically linked C runtime and rsxnt.dll
+gccdyn:
+       $(MAKE) -f win32/makefile.emx all \
+       CC="gcc -Zwin32 -Zcrtdll=crtrsxnt -O2 -m486 -Wall" \
+       CFLAGS="-DWIN32 -DASM_CRC" \
+       AS="gcc -Zwin32" \
+       ASFLAGS="-Di386" \
+       LDFLAGS="-o ./" \
+       LDFLAGS2="-ladvapi32 -s" \
+       OUT="-o" \
+       OBJ=".o" \
+       CRC32="crc_gcc" \
+       OBJA="matchgcc.o" \
+       DEF="win32/zip.def"
+
+# emx 0.9c, gcc, PE format, with debug info for gdb
+gccdebug:
+       $(MAKE) -f win32/makefile.emx all \
+       CC="gcc -Zwin32 -O2 -g -Wall" \
+       CFLAGS="-DWIN32 -DASM_CRC" \
+       AS="gcc -Zwin32" \
+       ASFLAGS="-Di386" \
+       LDFLAGS="-o ./" \
+       LDFLAGS2="-ladvapi32 -Zsmall-conv" \
+       OUT="-o" \
+       OBJ=".o" \
+       CRC32="crc_gcc" \
+       OBJA="matchgcc.o" \
+       DEF="win32/zip.def"
+
+# emx 0.9c, gcc, PE format,, statically linked zlib, C runtime, and rsxnt.dll
+gcczl:
+       $(MAKE) -f win32/makefile.emx all \
+       CC="gcc -Zwin32 -O2 -m486 -Wall" \
+       CFLAGS="-DWIN32 -DUSE_ZLIB" \
+       AS="gcc -Zwin32" \
+       ASFLAGS="-Di386 -DUSE_ZLIB" \
+       LDFLAGS="-o ./" \
+       LDFLAGS2="-L. -lzlib -ladvapi32 -s" \
+       OUT="-o" \
+       OBJ=".o" \
+       CRC32="crc32" \
+       OBJA="" \
+       DEF="win32/zip.def"
+
+# emx 0.9c, gcc, a.out format, for MS-DOS
+gccdos:
+       $(MAKE) -f win32/makefile.emx all \
+       CC="gcc -O2 -m486 -Wall" \
+       CFLAGS="-DDOS -DMSDOS -DASM_CRC" \
+       AS="gcc" \
+       ASFLAGS="-Di386" \
+       LDFLAGS="-o ./" \
+       LDFLAGS2="-s -Zsmall-conv" \
+       OUT="-o" \
+       OBJ=".o" \
+       CRC32="crc_gcc" \
+       OBJA="matchgcc.o" \
+       OBJZS="msdos.o" \
+       OBJUS="msdos_.o" \
+       OSDEP_H="msdos/osdep.h" \
+       ZIPUP_H="msdos/zipup.h"
+
+# emx 0.9c, gcc, a.out format, for MS-DOS, using zlib
+gccdoszl:
+       $(MAKE) -f win32/makefile.emx all \
+       CC="gcc -O2 -m486 -Wall" \
+       CFLAGS="-DDOS -DMSDOS -DUSE_ZLIB" \
+       AS="gcc" \
+       ASFLAGS="-Di386 -DUSE_ZLIB" \
+       LDFLAGS="-o ./" \
+       LDFLAGS2="-L. -lzlib -s -Zsmall-conv" \
+       OUT="-o" \
+       OBJ=".o" \
+       CRC32="crc32" \
+       OBJA="" \
+       OBJZS="msdos.o" \
+       OBJUS="msdos_.o" \
+       OSDEP_H="msdos/osdep.h" \
+       ZIPUP_H="msdos/zipup.h"
+
+# VPATH = .;win32
+
+# variables
+
+#default settings for target dependent macros:
+
+# the "gcc" (statically linked Win32 executables) target:
+CC=gcc -Zwin32 -O2 -m486 -Wall
+CFLAGS=-DWIN32 -DASM_CRC
+AS=gcc -Zwin32
+ASFLAGS=-Di386
+LDFLAGS=-o ./
+LDFLAGS2=-ladvapi32 -s -Zsmall-conv
+OUT=-o
+OBJ=.o
+CRC32=crc_gcc
+OBJA=matchgcc.o
+OSDEP_H=win32/osdep.h
+ZIPUP_H=win32/zipup.h
+DEF=win32/zip.def
+
+DIRSEP = /
+AS_DIRSEP = /
+RM = del
+LOCAL_OPTS = $(LOCAL_ZIP)
+CCFLAGS = $(CFLAGS) $(LOCAL_OPTS)
+
+
+OBJZ1 = zip$(OBJ) zipfile$(OBJ) zipup$(OBJ) fileio$(OBJ) util$(OBJ) \
+       $(CRC32)$(OBJ) crctab$(OBJ)
+OBJZ2 = globals$(OBJ) deflate$(OBJ) trees$(OBJ) crypt$(OBJ) \
+       ttyio$(OBJ)
+OBJZS =        win32zip$(OBJ) win32$(OBJ) nt$(OBJ)
+OBJZ  = $(OBJZ1) $(OBJZ2) $(OBJZS) $(OBJA)
+
+OBJU1 = zipfile_$(OBJ) fileio_$(OBJ) util_$(OBJ) globals$(OBJ)
+OBJUS = win32_$(OBJ)
+OBJU  = $(OBJU1) $(OBJUS)
+
+OBJN  = zipnote$(OBJ) $(OBJU)
+OBJS  = zipsplit$(OBJ) $(OBJU)
+OBJC1 = zipcloak$(OBJ) crctab$(OBJ) crypt_$(OBJ) ttyio$(OBJ)
+OBJC  = $(OBJC1) $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h $(OSDEP_H)
+
+# rules
+
+.SUFFIXES: .c $(OBJ)
+
+.c$(OBJ):
+       $(CC) -c -I. $(CCFLAGS) $(OUT)$@ $<
+
+# targets
+
+all:   zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zip$(OBJ):     zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipfile$(OBJ): zipfile.c $(ZIP_H)
+zipup$(OBJ):   zipup.c $(ZIP_H) revision.h crypt.h $(ZIPUP_H)
+fileio$(OBJ):  fileio.c $(ZIP_H)
+util$(OBJ):    util.c $(ZIP_H)
+globals$(OBJ): globals.c $(ZIP_H)
+deflate$(OBJ): deflate.c $(ZIP_H)
+trees$(OBJ):   trees.c $(ZIP_H)
+crc32$(OBJ):   crc32.c $(ZIP_H)
+crctab$(OBJ):  crctab.c $(ZIP_H)
+crypt$(OBJ):   crypt.c $(ZIP_H) crypt.h ttyio.h
+ttyio$(OBJ):   ttyio.c $(ZIP_H) crypt.h ttyio.h
+
+msdos$(OBJ):   msdos/msdos.c $(ZIP_H)
+       $(CC) -c -I. $(CCFLAGS) msdos$(DIRSEP)msdos.c
+
+win32zip$(OBJ):        win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h
+       $(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)win32zip.c
+
+win32$(OBJ):   win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)win32.c
+
+nt$(OBJ):      win32/nt.c $(ZIP_H) win32/nt.h
+       $(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)nt.c
+
+crc_gcc$(OBJ): crc_i386.S                                      # 32bit, GNU AS
+       $(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S
+
+matchgcc$(OBJ):        match.S
+       $(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ match.S
+
+zipcloak$(OBJ):        zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipnote$(OBJ): zipnote.c $(ZIP_H) revision.h
+zipsplit$(OBJ): zipsplit.c $(ZIP_H) revision.h
+
+zipfile_$(OBJ):        zipfile.c $(ZIP_H)
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ zipfile.c
+
+fileio_$(OBJ): fileio.c $(ZIP_H)
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ fileio.c
+
+util_$(OBJ):   util.c $(ZIP_H)
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ util.c
+
+crypt_$(OBJ):  crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ crypt.c
+
+msdos_$(OBJ):  msdos/msdos.c $(ZIP_H)
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ msdos$(DIRSEP)msdos.c
+
+win32_$(OBJ):  win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ win32$(DIRSEP)win32.c
+
+zip.exe: $(OBJZ)
+# for DUMB make utilities, uncomment the following commands:
+       -@$(RM) zip.rsp
+       @for %%f in ($(OBJZ1)) do echo %%f >> zip.rsp
+       @for %%f in ($(OBJZ2)) do echo %%f >> zip.rsp
+       @for %%f in ($(OBJZS) $(OBJA)) do echo %%f >> zip.rsp
+       $(CC) $(LDFLAGS)$@ @zip.rsp $(LDFLAGS2)
+       @$(RM) zip.rsp
+# smart make utilities (like well done ports of GNU Make) can use this:
+#      $(CC) $(LDFLAGS)$@ $(OBJZ) $(LDFLAGS2)
+
+zipcloak.exe: $(OBJC)
+# for DUMB make utilities, uncomment the following commands:
+       -@$(RM) zipcloak.rsp
+       @for %%f in ($(OBJC1)) do echo %%f >> zipcloak.rsp
+       @for %%f in ($(OBJU1)) do echo %%f >> zipcloak.rsp
+       @for %%f in ($(OBJUS)) do echo %%f >> zipcloak.rsp
+       $(CC) $(LDFLAGS)$@ @zipcloak.rsp $(LDFLAGS2)
+       @$(RM) zipcloak.rsp
+# smart make utilities (like well done ports of GNU Make) can use this:
+#      $(CC) $(LDFLAGS)$@ $(OBJC) $(LDFLAGS2)
+
+zipnote.exe: $(OBJN)
+# for DUMB make utilities, uncomment the following commands:
+       -@$(RM) zipnote.rsp
+       @for %%f in ($(OBJN)) do echo %%f >> zipnote.rsp
+       $(CC) $(LDFLAGS)$@ @zipnote.rsp $(LDFLAGS2)
+       @$(RM) zipnote.rsp
+# smart make utilities (like well done ports of GNU Make) can use this:
+#      $(CC) $(LDFLAGS)$@ $(OBJN) $(LDFLAGS2)
+
+zipsplit.exe: $(OBJS)
+# for DUMB make utilities, uncomment the following commands:
+       -@$(RM) zipsplit.rsp
+       @for %%f in ($(OBJN)) do echo %%f >> zipsplit.rsp
+       $(CC) $(LDFLAGS)$@ @zipsplit.rsp $(LDFLAGS2)
+       @$(RM) zipsplit.rsp
+# smart make utilities (like well done ports of GNU Make) can use this:
+#      $(CC) $(LDFLAGS)$@ $(OBJS) $(LDFLAGS2)
diff --git a/win32/makefile.gcc b/win32/makefile.gcc
new file mode 100644 (file)
index 0000000..6e924ad
--- /dev/null
@@ -0,0 +1,142 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for port of gcc producing
+# native Win32-Intel binaries. Derived from makefile.w32.
+# Currently supported implementations: Cygwin and MinGW.
+# Authors: Cosmin Truta, Christian Spieler, and possibly others.
+# Last updated: 2005-Jan-24.
+#
+# To use, do "make -f win32/makefile.gcc".
+
+# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)
+# should be added to the environment via "set LOCAL_ZIP=-DFOO" or added
+# to the declaration of LOC here:
+LOC = $(LOCAL_ZIP)
+
+# ------------ GNU C ------------
+CC=gcc
+ifndef USEZLIB
+CFLAGS=-O2 -Wall -DWIN32
+else
+CFLAGS=-O2 -Wall -DWIN32 -DUSE_ZLIB
+endif
+CCFLAGS=$(CFLAGS) $(LOC)
+UTILFLAGS=$(CCFLAGS) -DUTIL -o$@
+
+#AS=as
+AS=$(CC)
+ifndef USEZLIB
+ASDEFS=
+else
+ASDEFS=-DUSE_ZLIB
+endif
+ASFLAGS=-c $(ASDEFS) $(LOC)
+
+LD=$(CC)
+LDFLAGS=-o$@ -s
+ifndef USEZLIB
+LIBS=-luser32 -ladvapi32
+else
+LIBS=-L. -lz -luser32 -ladvapi32
+endif
+
+OSDEP_H = win32/osdep.h
+ZIPUP_H = win32/zipup.h
+
+# variables
+ifndef USEZLIB
+OBJA  = match.o crc_i386.o
+else
+OBJA  =
+endif
+#use second definition for linking against libz
+
+OBJZ1 = zip.o crypt.o ttyio.o zipfile.o zipup.o fileio.o util.o \
+       crc32.o crctab.o globals.o
+OBJZ2 = deflate.o trees.o $(OBJA)
+OBJZS = win32.o win32zip.o nt.o
+OBJZ  = $(OBJZ1) $(OBJZ2) $(OBJZS)
+
+OBJU1 = zipfile_.o fileio_.o util_.o globals.o
+OBJUS = win32_.o
+OBJU  = $(OBJU1) $(OBJUS)
+
+OBJN  = zipnote.o $(OBJU)
+OBJS  = zipsplit.o $(OBJU)
+OBJC1 = zipcloak.o crctab.o crypt_.o ttyio.o
+OBJC  = $(OBJC1) $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h $(OSDEP_H)
+
+ZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+# rules
+
+.SUFFIXES: .c .o
+
+.c.o:
+       $(CC) -c $(CCFLAGS) -I. -o$@ $<
+
+# targets
+
+zips: $(ZIPS)
+
+zip.o: zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipfile.o: zipfile.c $(ZIP_H)
+zipup.o: zipup.c $(ZIP_H) revision.h crypt.h $(ZIPUP_H)
+fileio.o: fileio.c $(ZIP_H)
+util.o: util.c $(ZIP_H)
+globals.o: globals.c $(ZIP_H)
+deflate.o: deflate.c $(ZIP_H)
+trees.o: trees.c $(ZIP_H)
+crc32.o: crc32.c $(ZIP_H)
+crctab.o: crctab.c $(ZIP_H)
+crypt.o: crypt.c $(ZIP_H) crypt.h ttyio.h
+ttyio.o: ttyio.c $(ZIP_H) crypt.h ttyio.h
+
+win32zip.o: win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h
+       $(CC) -c $(CCFLAGS) -I. win32/win32zip.c
+
+win32.o: win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c $(CCFLAGS) -I. win32/win32.c
+
+nt.o: win32/nt.c $(ZIP_H) win32/nt.h
+       $(CC) -c $(CCFLAGS) -I. win32/nt.c
+
+zipcloak.o: zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipnote.o: zipnote.c $(ZIP_H) revision.h
+zipsplit.o: zipsplit.c $(ZIP_H) revision.h
+
+zipfile_.o: zipfile.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS) zipfile.c
+
+fileio_.o: fileio.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS) fileio.c
+
+util_.o: util.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS) util.c
+
+crypt_.o: crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(UTILFLAGS) crypt.c
+
+win32_.o: win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c $(UTILFLAGS) -I. win32/win32.c
+
+match.o: match.S
+       $(AS) $(ASFLAGS) match.S
+
+crc_i386.o: crc_i386.S
+       $(AS) $(ASFLAGS) crc_i386.S
+
+zip.exe: $(OBJZ)
+       $(LD) $(LDFLAGS) $(OBJZ) $(LIBS)
+
+zipcloak.exe: $(OBJC)
+       $(LD) $(LDFLAGS) $(OBJC) $(LIBS)
+
+zipnote.exe: $(OBJN)
+       $(LD) $(LDFLAGS) $(OBJN)
+
+zipsplit.exe: $(OBJS)
+       $(LD) $(LDFLAGS) $(OBJS)
+
+clean:
+       rm -f *.o $(ZIPS)
diff --git a/win32/makefile.ibm b/win32/makefile.ibm
new file mode 100644 (file)
index 0000000..74acfd9
--- /dev/null
@@ -0,0 +1,123 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for
+# 32-bit IBM Visual Age C++
+
+# To use, do "nmake -f win32\makefile.ibm"
+
+# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)
+# should be added to the environment via "set LOCAL_ZIP=-DFOO" or added
+# to the declaration of LOC here:
+LOC = $(LOCAL_ZIP)
+
+# Uncomment the following macro to use the optimized assembler
+# routines in Zip:
+# ASMOBJS = match32.obj
+
+# ------------- 32-bit IBM Visual Age C++ -------------
+CC=icc -q -O
+CFLAGS=-W0 -DWIN32 -Sm -DNO_ASM -DNO_MKTEMP $(LOC)
+UTILFLAGS=$(CFLAGS) -DUTIL -Fo$@
+LDFLAGS=
+LIBS=advapi32.lib
+AS=ml -nologo
+ASFLAGS=-c -Cx
+
+# variables
+OBJZ = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \
+       crc32.obj crctab.obj globals.obj
+
+OBJI = deflate.obj trees.obj $(ASMOBJS) win32.obj win32zip.obj nt.obj
+
+OBJU = zipfile_.obj fileio_.obj util_.obj globals.obj win32_.obj
+OBJN = zipnote.obj $(OBJU)
+OBJC = zipcloak.obj crctab.obj crypt_.obj ttyio.obj $(OBJU)
+OBJS = zipsplit.obj $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h win32/osdep.h
+
+ZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zips:   $(ZIPS)
+
+zip.obj:        zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipfile.obj:    zipfile.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+zipup.obj:      zipup.c $(ZIP_H) revision.h crypt.h win32/zipup.h
+       $(CC) -c $(CFLAGS) $*.c
+
+fileio.obj:     fileio.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+util.obj:       util.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+globals.obj:    globals.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+deflate.obj:    deflate.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+trees.obj:      trees.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crc32.obj:      crc32.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crctab.obj:     crctab.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crypt.obj:      crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+ttyio.obj:      ttyio.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+win32zip.obj:   win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h
+       $(CC) -c $(CFLAGS) -I. win32/win32zip.c
+
+win32.obj:      win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c $(CFLAGS) -I. win32/win32.c
+
+nt.obj:         win32/nt.c $(ZIP_H) win32/nt.h
+       $(CC) -c $(CFLAGS) -I. win32/nt.c
+
+zipcloak.obj:   zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipnote.obj:    zipnote.c $(ZIP_H) revision.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipsplit.obj:   zipsplit.c $(ZIP_H) revision.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipfile_.obj:   zipfile.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS) zipfile.c
+
+fileio_.obj:    fileio.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS) fileio.c
+
+util_.obj:      util.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS) util.c
+
+crypt_.obj:     crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(UTILFLAGS) crypt.c
+
+win32_.obj:     win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c $(UTILFLAGS) -I. win32/win32.c
+
+match32.obj:    win32/match32.asm
+       $(AS) $(ASFLAGS) win32\match32.asm
+
+zip.exe: $(OBJZ) $(OBJI)
+       $(CC) -Fe $@ $(LDFLAGS) $(OBJZ) $(OBJI) $(LIBS)
+
+zipcloak.exe: $(OBJC)
+       $(CC) -Fe $@ $(LDFLAGS) $(OBJC) $(LIBS)
+
+zipnote.exe: $(OBJN)
+       $(CC) -Fe $@ $(LDFLAGS) $(OBJN) $(LIBS)
+
+zipsplit.exe: $(OBJS)
+       $(CC) -Fe $@ $(LDFLAGS) $(OBJS) $(LIBS)
diff --git a/win32/makefile.lcc b/win32/makefile.lcc
new file mode 100644 (file)
index 0000000..b40e77c
--- /dev/null
@@ -0,0 +1,123 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit using LCC-Win32.
+# By E-Yen Tan (3 June 1998).
+# Last updated 21 December 1998 (Christian Spieler).
+
+# This compiler evaluates #include locations relative to current working dir,
+# not relative to the location of the file containing the #include directive.
+# As a consequence, a "-Iwin32" option is required to allow compilation of
+# the WIN32 specific sources.
+
+CC = lcc
+# -O caused a segmentation violation with previous versions of lcc, but
+# now the optimizer seems to be fixed.
+CCFLAGS = -zp8 -O -DWIN32
+AS = lcc
+ASFLAGS =
+LD = lcclnk
+LDFLAGS = -s
+
+# Optional macros should be declared below.
+# LCC's Make will not read the LOCAL_ZIP environment variable.
+LOC = $(ASMFLG)
+
+# Options to select optimized assembler code for CRC32 calculation.
+#ifdef USEASM
+CRC32 = crc_lcc
+OBJA = lm32_lcc.obj
+ASMFLG = -DASM_CRC -DASMV
+#else
+#CRC32 = crc32
+#OBJA =
+#ASMFLG = -DNO_ASM
+#endif
+
+CFLAGS = $(CCFLAGS) $(LOC)
+
+OBJZS = win32.obj win32zip.obj nt.obj $(OBJA)
+OBJUS = win32_.obj
+
+OBJZ1 = zip.obj zipfile.obj zipup.obj fileio.obj util.obj
+OBJZ2 = $(CRC32).obj crctab.obj globals.obj
+OBJZ3 = deflate.obj trees.obj crypt.obj ttyio.obj
+OBJZ  = $(OBJZ1) $(OBJZ2) $(OBJZ3) $(OBJZS)
+
+OBJU1 = zipfile_.obj fileio_.obj util_.obj globals.obj
+OBJU  = $(OBJU1) $(OBJUS)
+
+OBJN =  zipnote.obj $(OBJU)
+OBJS =  zipsplit.obj $(OBJU)
+OBJK =  zipcloak.obj crctab.obj crypt_.obj ttyio.obj
+OBJC =  $(OBJK) $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h win32/osdep.h
+
+# rules
+
+.SUFFIXES: .c .obj
+
+.c.obj:
+       $(CC) $(CFLAGS) $<
+
+.asm.obj:
+       $(AS) $(ASFLAGS) $<
+
+all:    zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zip.obj:      zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipfile.obj:  zipfile.c $(ZIP_H)
+zipup.obj:    zipup.c $(ZIP_H) revision.h crypt.h win32/zipup.h
+fileio.obj:   fileio.c $(ZIP_H)
+util.obj:     util.c $(ZIP_H)
+globals.obj:  globals.c $(ZIP_H)
+deflate.obj:  deflate.c $(ZIP_H)
+trees.obj:    trees.c $(ZIP_H)
+crc32.obj:    crc32.c $(ZIP_H)
+crctab.obj:   crctab.c $(ZIP_H)
+crypt.obj:    crypt.c $(ZIP_H) crypt.h ttyio.h
+ttyio.obj:    ttyio.c $(ZIP_H) crypt.h ttyio.h
+
+win32.obj:    win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) $(CFLAGS) -Iwin32 -Fo$@ win32/win32.c
+
+win32zip.obj: win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h
+       $(CC) $(CFLAGS) -Iwin32 -Fo$@ win32/win32zip.c
+
+nt.obj:       win32/nt.c $(ZIP_H) win32/nt.h
+       $(CC) $(CFLAGS) -Iwin32 -Fo$@ win32/nt.c
+
+crc_lcc.obj:   win32/crc_lcc.asm
+       $(AS) $(ASFLAGS) -Fo$@ win32/crc_lcc.asm
+
+lm32_lcc.obj:  win32/lm32_lcc.asm
+       $(AS) $(ASFLAGS) -Fo$@ win32/lm32_lcc.asm
+
+zipcloak.obj: zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipnote.obj:  zipnote.c $(ZIP_H) revision.h
+zipsplit.obj: zipsplit.c $(ZIP_H) revision.h
+
+zipfile_.obj: zipfile.c $(ZIP_H)
+       $(CC) $(CFLAGS) -DUTIL -Fo$@ zipfile.c
+
+fileio_.obj:  fileio.c $(ZIP_H)
+       $(CC) $(CFLAGS) -DUTIL -Fo$@ fileio.c
+
+util_.obj:    util.c $(ZIP_H)
+       $(CC) $(CFLAGS) -DUTIL -Fo$@ util.c
+
+crypt_.obj:   crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) $(CFLAGS) -DUTIL -Fo$@ crypt.c
+
+win32_.obj:    win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) $(CFLAGS) -DUTIL -Iwin32 -Fo$@ win32/win32.c
+
+zip.exe: $(OBJZ)
+       $(LD) $(LDFLAGS) -o $@ $(OBJZ)
+
+zipcloak.exe: $(OBJC)
+       $(LD) $(LDFLAGS) -o $@ $(OBJC)
+
+zipnote.exe: $(OBJN)
+       $(LD) $(LDFLAGS) -o $@ $(OBJN)
+
+zipsplit.exe: $(OBJS)
+       $(LD) $(LDFLAGS) -o $@ $(OBJS)
diff --git a/win32/makefile.w10 b/win32/makefile.w10
new file mode 100644 (file)
index 0000000..b5244fc
--- /dev/null
@@ -0,0 +1,181 @@
+# WMAKE makefile for Windows 95 and Windows NT (Intel only)
+# using Watcom C/C++ v10.5+, by Paul Kienitz, last revised 22 Feb 05.
+# Makes Zip.exe, ZipNote.exe, ZipCloak.exe, and ZipSplit.exe.
+#
+# Invoke from Zip source dir with "WMAKE -F WIN32\MAKEFILE.WAT [targets]"
+# To build with debug info use "WMAKE DEBUG=1 ..."
+# To build without any assembly modules use "WMAKE NOASM=1 ..."
+#
+# Other options to be fed to the compiler can be specified in an environment
+# variable called LOCAL_ZIP.  One possibility "-DDYN_ALLOC", but currently
+# this is not supported unless NOASM is also used.
+
+variation = $(%LOCAL_ZIP)
+
+# Stifle annoying "Delete this file?" questions when errors occur:
+.ERASE
+
+.EXTENSIONS:
+.EXTENSIONS: .exe .obj .c .h .asm
+
+# We maintain multiple sets of object files in different directories so that
+# we can compile msdos, dos/4gw, and win32 versions of Zip without their
+# object files interacting.  The following var must be a directory name
+# ending with a backslash.  All object file names must include this macro
+# at the beginning, for example "$(O)foo.obj".
+
+!ifdef DEBUG
+OBDIR = od32w
+!else
+OBDIR = ob32w
+!endif
+O = $(OBDIR)\   # comment here so backslash won't continue the line
+
+# The assembly hot-spot code in crc_i386.asm and match32.asm is optional.
+# This section controls its usage.
+
+!ifdef NOASM
+asmob = $(O)crc32.obj           # C source
+cvars = $+$(cvars)$- -DNO_ASM   # otherwise ASM_CRC might default on!
+# "$+$(foo)$-" means expand foo as it has been defined up to now; normally,
+# this make defers inner expansion until the outer macro is expanded.
+!else  # !NOASM
+asmob = $(O)match32.obj $(O)crc_i386.obj
+cvars = $+$(cvars)$- -DASMV -DASM_CRC
+!endif
+
+# Our object files.  OBJZ is for Zip, OBJC is for ZipCloak, OBJN is for
+# ZipNote, and OBJS is for ZipSplit:
+
+OBJZ3 = $(O)zip.obj $(O)crypt.obj $(O)ttyio.obj $(O)trees.obj $(O)zipup.obj
+OBJZ2 = $(OBJZ3) $(O)util.obj $(O)zipfile.obj $(O)fileio.obj $(O)deflate.obj
+OBJZ1 = $(OBJZ2) $(O)globals.obj $(O)crctab.obj $(asmob)
+OBJZ  = $(OBJZ1) $(O)win32zip.obj $(O)win32.obj $(O)nt.obj
+
+OBJU1 = $(O)zipfile_.obj $(O)fileio_.obj $(O)util_.obj $(O)globals.obj
+OBJ_U = $(OBJU1) $(O)win32_.obj
+
+OBJC  = $(O)zipcloak.obj $(O)crctab.obj $(O)crypt_.obj $(O)ttyio.obj $(OBJ_U)
+
+OBJN  = $(O)zipnote.obj $(OBJ_U)
+
+OBJS  = $(O)zipsplit.obj $(OBJ_U)
+
+# Common header files included by all C sources:
+
+ZIP_H = zip.h ziperr.h tailor.h win32\osdep.h
+
+# Now we have to pick out the proper compiler and options for it.
+
+cc     = wcc386
+link   = wlink
+asm    = wasm
+# Use Pentium timings, register args, static strings in code:
+cflags = -bt=NT -5r -zt -zq
+aflags = -bt=NT -mf -3 -zq
+lflags = sys NT
+cvars  = $+$(cvars)$- -DWIN32 $(variation)
+avars  = $+$(avars)$- $(variation)
+
+# Specify optimizations, or a nonoptimized debugging version:
+
+!ifdef DEBUG
+cdebug = -od -d2
+ldebug = d w all op symf
+!else
+cdebug = -s -oeilrt -zp4
+# note: -ol+ does not help.  -oa helps slightly but might be dangerous.
+ldebug = op el
+!endif
+
+# How to compile sources:
+.c.obj:
+       $(cc) $(cdebug) $(cflags) $(cvars) $< -fo=$@
+
+# Here we go!  By default, make all targets:
+all: Zip.exe ZipNote.exe ZipCloak.exe ZipSplit.exe
+
+# Convenient shorthand options for single targets:
+z:   Zip.exe       .SYMBOLIC
+n:   ZipNote.exe   .SYMBOLIC
+c:   ZipCloak.exe  .SYMBOLIC
+s:   ZipSplit.exe  .SYMBOLIC
+
+Zip.exe:       $(OBDIR) $(OBJZ)
+       $(link) $(lflags) $(ldebug) name $@ file {$(OBJZ)}
+
+ZipNote.exe:   $(OBDIR) $(OBJN)
+       $(link) $(lflags) $(ldebug) name $@ file {$(OBJN)}
+
+ZipCloak.exe:  $(OBDIR) $(OBJC)
+       $(link) $(lflags) $(ldebug) name $@ file {$(OBJC)}
+
+ZipSplit.exe:  $(OBDIR) $(OBJS)
+       $(link) $(lflags) $(ldebug) name $@ file {$(OBJS)}
+
+# Source dependencies:
+
+$(O)crctab.obj:   crctab.c $(ZIP_H)
+$(O)crc32.obj:    crc32.c $(ZIP_H)          # only used if NOASM
+$(O)crypt.obj:    crypt.c $(ZIP_H) crypt.h ttyio.h
+$(O)deflate.obj:  deflate.c $(ZIP_H)
+$(O)fileio.obj:   fileio.c $(ZIP_H)
+$(O)globals.obj:  globals.c $(ZIP_H)
+$(O)trees.obj:    trees.c $(ZIP_H)
+$(O)ttyio.obj:    ttyio.c $(ZIP_H) crypt.h ttyio.h
+$(O)util.obj:     util.c $(ZIP_H)
+$(O)zip.obj:      zip.c $(ZIP_H) crypt.h revision.h ttyio.h
+$(O)zipfile.obj:  zipfile.c $(ZIP_H)
+$(O)zipup.obj:    zipup.c $(ZIP_H) revision.h crypt.h win32\zipup.h
+$(O)zipnote.obj:  zipnote.c $(ZIP_H) revision.h
+$(O)zipcloak.obj: zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+$(O)zipsplit.obj: zipsplit.c $(ZIP_H) revision.h
+
+# Special case object files:
+
+$(O)win32.obj:    win32\win32.c $(ZIP_H) win32\win32zip.h
+       $(cc) $(cdebug) $(cflags) $(cvars) win32\win32.c -fo=$@
+
+$(O)win32zip.obj: win32\win32zip.c $(ZIP_H) win32\win32zip.h win32\nt.h
+       $(cc) $(cdebug) $(cflags) $(cvars) win32\win32zip.c -fo=$@
+
+$(O)nt.obj:       win32\nt.c $(ZIP_H) win32\nt.h
+       $(cc) $(cdebug) $(cflags) $(cvars) win32\nt.c -fo=$@
+
+$(O)match32.obj:  win32\match32.asm
+       $(asm) $(aflags) $(avars) win32\match32.asm -fo=$@
+
+$(O)crc_i386.obj: win32\crc_i386.asm
+       $(asm) $(aflags) $(avars) win32\crc_i386.asm -fo=$@
+
+# Variant object files for ZipNote, ZipCloak, and ZipSplit:
+
+$(O)zipfile_.obj: zipfile.c $(ZIP_H)
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL zipfile.c -fo=$@
+
+$(O)fileio_.obj:  fileio.c $(ZIP_H)
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL fileio.c -fo=$@
+
+$(O)util_.obj:    util.c $(ZIP_H)
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL util.c -fo=$@
+
+$(O)crypt_.obj:   crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL crypt.c -fo=$@
+
+$(O)win32_.obj:   win32\win32.c $(ZIP_H) win32\win32zip.h
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL win32\win32.c -fo=$@
+
+# Creation of subdirectory for intermediate files
+$(OBDIR):
+       -mkdir $@
+
+# Unwanted file removal:
+
+clean:     .SYMBOLIC
+       del $(O)*.obj
+
+cleaner:   clean  .SYMBOLIC
+       del Zip.exe
+       del ZipNote.exe
+       del ZipCloak.exe
+       del ZipSplit.exe
diff --git a/win32/makefile.w32 b/win32/makefile.w32
new file mode 100644 (file)
index 0000000..538a614
--- /dev/null
@@ -0,0 +1,147 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for
+# 32-bit Microsoft Visual C++
+
+# To use, do "nmake -f makefile.w32"
+
+# Add -DNO_ASM to CFLAGS and comment out the ASMOBJS definition if
+# you do not have masm 6.1X.
+
+# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)
+# should be added to the environment via "set LOCAL_ZIP=-DFOO" or added
+# to the declaration of LOC here:
+LOC = $(LOCAL_ZIP)
+
+# To avoid using the optimized assembler routines in Zip, comment
+# out the ASMOBJS macro below, and add -DNO_ASM to LOC above.
+ASMOBJS = match32.obj crc_i386.obj
+
+# ------------- 32-bit Microsoft Visual C++ -------------
+CC=cl -nologo
+CFLAGS=-W3 -O2 -DWIN32 $(LOC)
+UTILFLAGS=$(CFLAGS) -DUTIL -Fo$@
+
+# Remove "-coff" from ASFLAGS if you do not have MASM 6.11.
+
+AS=ml -nologo
+ASFLAGS=-c -coff -Cx
+
+# If you build 16-bit executables with MS Visual C++ v1.0/1.5 and link them
+# with the /KNOWEAS switch, you can build dual-mode MS-DOS/Win32 executables
+# by passing the -stub switch to the 32-bit linker to specify the 16-bit part.
+
+LD=link -nologo
+#LDFLAGS=-stub:zipdos.exe
+LDFLAGS=
+
+# variables
+OBJZ = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \
+       crc32.obj crctab.obj globals.obj
+
+OBJI = deflate.obj trees.obj $(ASMOBJS) win32.obj win32zip.obj nt.obj
+
+OBJU = zipfile_.obj fileio_.obj util_.obj globals.obj win32_.obj
+OBJN = zipnote.obj $(OBJU)
+OBJC = zipcloak.obj crctab.obj crypt_.obj ttyio.obj $(OBJU)
+OBJS = zipsplit.obj $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h win32/osdep.h
+
+LIBS = advapi32.lib
+
+ZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zips:   $(ZIPS)
+
+zip.obj:        zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipfile.obj:    zipfile.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+zipup.obj:      zipup.c $(ZIP_H) revision.h crypt.h win32/zipup.h
+       $(CC) -c $(CFLAGS) $*.c
+
+fileio.obj:     fileio.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+util.obj:       util.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+globals.obj:    globals.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+deflate.obj:    deflate.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+trees.obj:      trees.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crc32.obj:      crc32.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crctab.obj:     crctab.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) $*.c
+
+crypt.obj:      crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+ttyio.obj:      ttyio.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+win32zip.obj:   win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h
+       $(CC) -c $(CFLAGS) -I. win32/win32zip.c
+
+win32.obj:      win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c $(CFLAGS) -I. win32/win32.c
+
+nt.obj:         win32/nt.c $(ZIP_H) win32/nt.h
+       $(CC) -c $(CFLAGS) -I. win32/nt.c
+
+zipcloak.obj:   zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipnote.obj:    zipnote.c $(ZIP_H) revision.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipsplit.obj:   zipsplit.c $(ZIP_H) revision.h
+       $(CC) -c $(CFLAGS) $*.c
+
+zipfile_.obj:   zipfile.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS) zipfile.c
+
+fileio_.obj:    fileio.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS) fileio.c
+
+util_.obj:      util.c $(ZIP_H)
+       $(CC) -c $(UTILFLAGS) util.c
+
+crypt_.obj:     crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(CC) -c $(UTILFLAGS) crypt.c
+
+win32_.obj:     win32/win32.c $(ZIP_H) win32/win32zip.h
+       $(CC) -c $(UTILFLAGS) -I. win32/win32.c
+
+crci386c.obj:   win32/crc_i386.c $(ZIP_H)
+       $(CC) -c $(CFLAGS) -I. -Fo$@ win32/crc_i386.c
+       
+crc_i386.obj:   win32/crc_i386.c $(ZIP_H)
+       $(AS) $(ASFLAGS) win32\crc_i386.asm
+       
+match32.obj:    win32/match32.asm
+       $(AS) $(ASFLAGS) win32\match32.asm
+
+zip.exe: $(OBJZ) $(OBJI)
+       $(LD) $(LDFLAGS) $(OBJZ) $(OBJI) $(LIBS)
+
+zipcloak.exe: $(OBJC)
+       $(LD) $(LDFLAGS) $(OBJC) $(LIBS)
+
+zipnote.exe: $(OBJN)
+       $(LD) $(LDFLAGS) $(OBJN) $(LIBS)
+
+zipsplit.exe: $(OBJS)
+       $(LD) $(LDFLAGS) $(OBJS) $(LIBS)
+
+clean:
+       del *.obj
+       del *.exe
diff --git a/win32/makefile.wat b/win32/makefile.wat
new file mode 100644 (file)
index 0000000..93b41e0
--- /dev/null
@@ -0,0 +1,181 @@
+# WMAKE makefile for Windows 95 and Windows NT (Intel only)
+# using Watcom C/C++ v11.0+, by Paul Kienitz, last revised 22 Feb 05.
+# Makes Zip.exe, ZipNote.exe, ZipCloak.exe, and ZipSplit.exe.
+#
+# Invoke from Zip source dir with "WMAKE -F WIN32\MAKEFILE.WAT [targets]"
+# To build with debug info use "WMAKE DEBUG=1 ..."
+# To build without any assembly modules use "WMAKE NOASM=1 ..."
+#
+# Other options to be fed to the compiler can be specified in an environment
+# variable called LOCAL_ZIP.  One possibility "-DDYN_ALLOC", but currently
+# this is not supported unless NOASM is also used.
+
+variation = $(%LOCAL_ZIP)
+
+# Stifle annoying "Delete this file?" questions when errors occur:
+.ERASE
+
+.EXTENSIONS:
+.EXTENSIONS: .exe .obj .c .h .asm
+
+# We maintain multiple sets of object files in different directories so that
+# we can compile msdos, dos/4gw, and win32 versions of Zip without their
+# object files interacting.  The following var must be a directory name
+# ending with a backslash.  All object file names must include this macro
+# at the beginning, for example "$(O)foo.obj".
+
+!ifdef DEBUG
+OBDIR = od32w
+!else
+OBDIR = ob32w
+!endif
+O = $(OBDIR)\   # comment here so backslash won't continue the line
+
+# The assembly hot-spot code in crc_i386.asm and match32.asm is optional.
+# This section controls its usage.
+
+!ifdef NOASM
+asmob = $(O)crc32.obj           # C source
+cvars = $+$(cvars)$- -DNO_ASM   # otherwise ASM_CRC might default on!
+# "$+$(foo)$-" means expand foo as it has been defined up to now; normally,
+# this make defers inner expansion until the outer macro is expanded.
+!else  # !NOASM
+asmob = $(O)match32.obj $(O)crc_i386.obj
+cvars = $+$(cvars)$- -DASMV -DASM_CRC
+!endif
+
+# Our object files.  OBJZ is for Zip, OBJC is for ZipCloak, OBJN is for
+# ZipNote, and OBJS is for ZipSplit:
+
+OBJZ3 = $(O)zip.obj $(O)crypt.obj $(O)ttyio.obj $(O)trees.obj $(O)zipup.obj
+OBJZ2 = $(OBJZ3) $(O)util.obj $(O)zipfile.obj $(O)fileio.obj $(O)deflate.obj
+OBJZ1 = $(OBJZ2) $(O)globals.obj $(O)crctab.obj $(asmob)
+OBJZ  = $(OBJZ1) $(O)win32zip.obj $(O)win32.obj $(O)nt.obj
+
+OBJU1 = $(O)zipfile_.obj $(O)fileio_.obj $(O)util_.obj $(O)globals.obj
+OBJ_U = $(OBJU1) $(O)win32_.obj
+
+OBJC  = $(O)zipcloak.obj $(O)crctab.obj $(O)crypt_.obj $(O)ttyio.obj $(OBJ_U)
+
+OBJN  = $(O)zipnote.obj $(OBJ_U)
+
+OBJS  = $(O)zipsplit.obj $(OBJ_U)
+
+# Common header files included by all C sources:
+
+ZIP_H = zip.h ziperr.h tailor.h win32\osdep.h
+
+# Now we have to pick out the proper compiler and options for it.
+
+cc     = wcc386
+link   = wlink
+asm    = wasm
+# Use Pentium Pro timings, register args, static strings in code:
+cflags = -bt=NT -6r -zt -zq
+aflags = -bt=NT -mf -3 -zq
+lflags = sys NT
+cvars  = $+$(cvars)$- -DWIN32 $(variation)
+avars  = $+$(avars)$- $(variation)
+
+# Specify optimizations, or a nonoptimized debugging version:
+
+!ifdef DEBUG
+cdebug = -od -d2
+ldebug = d w all op symf
+!else
+cdebug = -s -obhikl+rt -oe=100 -zp8
+# -oa helps slightly but might be dangerous.
+ldebug = op el
+!endif
+
+# How to compile sources:
+.c.obj:
+       $(cc) $(cdebug) $(cflags) $(cvars) $[@ -fo=$@
+
+# Here we go!  By default, make all targets:
+all: Zip.exe ZipNote.exe ZipCloak.exe ZipSplit.exe
+
+# Convenient shorthand options for single targets:
+z:   Zip.exe       .SYMBOLIC
+n:   ZipNote.exe   .SYMBOLIC
+c:   ZipCloak.exe  .SYMBOLIC
+s:   ZipSplit.exe  .SYMBOLIC
+
+Zip.exe:       $(OBDIR) $(OBJZ)
+       $(link) $(lflags) $(ldebug) name $@ file {$(OBJZ)}
+
+ZipNote.exe:   $(OBDIR) $(OBJN)
+       $(link) $(lflags) $(ldebug) name $@ file {$(OBJN)}
+
+ZipCloak.exe:  $(OBDIR) $(OBJC)
+       $(link) $(lflags) $(ldebug) name $@ file {$(OBJC)}
+
+ZipSplit.exe:  $(OBDIR) $(OBJS)
+       $(link) $(lflags) $(ldebug) name $@ file {$(OBJS)}
+
+# Source dependencies:
+
+$(O)crctab.obj:   crctab.c $(ZIP_H)
+$(O)crc32.obj:    crc32.c $(ZIP_H)          # only used if NOASM
+$(O)crypt.obj:    crypt.c $(ZIP_H) crypt.h ttyio.h
+$(O)deflate.obj:  deflate.c $(ZIP_H)
+$(O)fileio.obj:   fileio.c $(ZIP_H)
+$(O)globals.obj:  globals.c $(ZIP_H)
+$(O)trees.obj:    trees.c $(ZIP_H)
+$(O)ttyio.obj:    ttyio.c $(ZIP_H) crypt.h ttyio.h
+$(O)util.obj:     util.c $(ZIP_H)
+$(O)zip.obj:      zip.c $(ZIP_H) crypt.h revision.h ttyio.h
+$(O)zipfile.obj:  zipfile.c $(ZIP_H)
+$(O)zipup.obj:    zipup.c $(ZIP_H) revision.h crypt.h win32\zipup.h
+$(O)zipnote.obj:  zipnote.c $(ZIP_H) revision.h
+$(O)zipcloak.obj: zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+$(O)zipsplit.obj: zipsplit.c $(ZIP_H) revision.h
+
+# Special case object files:
+
+$(O)win32.obj:    win32\win32.c $(ZIP_H) win32\win32zip.h
+       $(cc) $(cdebug) $(cflags) $(cvars) win32\win32.c -fo=$@
+
+$(O)win32zip.obj: win32\win32zip.c $(ZIP_H) win32\win32zip.h win32\nt.h
+       $(cc) $(cdebug) $(cflags) $(cvars) win32\win32zip.c -fo=$@
+
+$(O)nt.obj:       win32\nt.c $(ZIP_H) win32\nt.h
+       $(cc) $(cdebug) $(cflags) $(cvars) win32\nt.c -fo=$@
+
+$(O)match32.obj:  win32\match32.asm
+       $(asm) $(aflags) $(avars) win32\match32.asm -fo=$@
+
+$(O)crc_i386.obj: win32\crc_i386.asm
+       $(asm) $(aflags) $(avars) win32\crc_i386.asm -fo=$@
+
+# Variant object files for ZipNote, ZipCloak, and ZipSplit:
+
+$(O)zipfile_.obj: zipfile.c $(ZIP_H)
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL zipfile.c -fo=$@
+
+$(O)fileio_.obj:  fileio.c $(ZIP_H)
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL fileio.c -fo=$@
+
+$(O)util_.obj:    util.c $(ZIP_H)
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL util.c -fo=$@
+
+$(O)crypt_.obj:   crypt.c $(ZIP_H) crypt.h ttyio.h
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL crypt.c -fo=$@
+
+$(O)win32_.obj:   win32\win32.c $(ZIP_H) win32\win32zip.h
+       $(cc) $(cdebug) $(cflags) $(cvars) -DUTIL win32\win32.c -fo=$@
+
+# Creation of subdirectory for intermediate files
+$(OBDIR):
+       -mkdir $@
+
+# Unwanted file removal:
+
+clean:     .SYMBOLIC
+       del $(O)*.obj
+
+cleaner:   clean  .SYMBOLIC
+       del Zip.exe
+       del ZipNote.exe
+       del ZipCloak.exe
+       del ZipSplit.exe
diff --git a/win32/match32.asm b/win32/match32.asm
new file mode 100644 (file)
index 0000000..5d4e8b5
--- /dev/null
@@ -0,0 +1,184 @@
+;===========================================================================
+; Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+;
+; See the accompanying file LICENSE, version 2004-May-22 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+;===========================================================================
+;
+; match32.asm by Jean-loup Gailly.
+
+; match32.asm, optimized version of longest_match() in deflate.c
+; To be used only with 32 bit flat model. To simplify the code, the option
+; -DDYN_ALLOC is not supported.
+; This file is only optional. If you don't have an assembler, use the
+; C version (add -DNO_ASM to CFLAGS in makefile and remove match.o
+; from OBJI). If you have reduced WSIZE in zip.h, then make sure this is
+; assembled with an equivalent -DWSIZE=<whatever>.
+;
+; Win32 (Windows NT) version - 1994/04/13 by Steve Salisbury
+; * works with Microsoft MASM 6.1X and Microsoft Visual C++ / 32-bit edition
+;
+; Adapted to work with Borland Turbo Assembler 5.0 by Cosmin Truta, 1997
+;
+;==============================================================================
+;
+; Do NOT assemble this source if external crc32 routine from zlib gets used.
+;
+    IFNDEF USE_ZLIB
+;
+        .386p
+    ifdef ASM_NEW
+        .MODEL  FLAT
+    endif
+
+        name    match
+
+    ifdef ASM_NEW
+_BSS    segment public use32
+    else
+_BSS    segment public use32 'DATA'
+    endif
+        extrn   _match_start  : dword
+        extrn   _prev_length  : dword
+        extrn   _good_match   : dword
+    ifndef FULL_SEARCH
+        extrn   _nice_match   : dword
+    endif
+        extrn   _strstart     : dword
+        extrn   _max_chain_length : dword
+        extrn   _prev         : word
+        extrn   _window       : byte
+_BSS    ends
+
+   ifdef ASM_NEW
+_TEXT   segment public use32
+   else
+_TEXT   segment para public use32 'CODE'
+   endif
+        assume CS: _TEXT
+        assume DS: _BSS, ES: _BSS, FS: _BSS
+        public  _match_init
+        public  _longest_match
+
+    ifndef      WSIZE
+        WSIZE         equ 32768         ; keep in sync with zip.h !
+    endif
+        MIN_MATCH     equ 3
+        MAX_MATCH     equ 258
+        MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
+        MAX_DIST      equ (WSIZE-MIN_LOOKAHEAD)
+
+; initialize or check the variables used in match.asm.
+
+_match_init proc near
+        ret
+_match_init endp
+
+; -----------------------------------------------------------------------
+; Set match_start to the longest match starting at the given string and
+; return its length. Matches shorter or equal to prev_length are discarded,
+; in which case the result is equal to prev_length and match_start is
+; garbage.
+; IN assertions: cur_match is the head of the hash chain for the current
+;   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+
+; int longest_match(cur_match)
+
+_longest_match proc near
+
+        cur_match    equ dword ptr [esp+20]
+        ; return address                ; esp+16
+        push    ebp                     ; esp+12
+        push    edi                     ; esp+8
+        push    esi                     ; esp+4
+        push    ebx                     ; esp
+
+;       match        equ esi
+;       scan         equ edi
+;       chain_length equ ebp
+;       best_len     equ ebx
+;       limit        equ edx
+
+        mov     esi,cur_match
+        mov     edx,_strstart
+        mov     ebp,_max_chain_length   ; chain_length = max_chain_length
+        mov     edi,edx
+        sub     edx,MAX_DIST            ; limit = strstart-MAX_DIST
+        cld                             ; string ops increment esi and edi
+        jae     short limit_ok
+        sub     edx,edx                 ; limit = NIL
+limit_ok:
+        add     edi,2+offset _window    ; edi = offset(window + strstart + 2)
+        mov     ebx,_prev_length        ; best_len = prev_length
+        mov     cx,[edi-2]              ; cx = scan[0..1]
+        mov     ax,[ebx+edi-3]          ; ax = scan[best_len-1..best_len]
+        cmp     ebx,_good_match         ; do we have a good match already?
+        jb      short do_scan
+        shr     ebp,2                   ; chain_length >>= 2
+        jmp     short do_scan
+
+        align   4                       ; align destination of branch
+long_loop:
+; at this point, edi == scan+2, esi == cur_match
+        mov     ax,[ebx+edi-3]          ; ax = scan[best_len-1..best_len]
+        mov     cx,[edi-2]              ; cx = scan[0..1]
+short_loop:
+; at this point, edi == scan+2, esi == cur_match,
+; ax = scan[best_len-1..best_len] and cx = scan[0..1]
+        and     esi,WSIZE-1
+        dec     ebp                     ; --chain_length
+        mov     si,_prev[esi+esi]       ; cur_match = prev[cur_match]
+                                        ; top word of esi is still 0
+        jz      short the_end
+        cmp     esi,edx                 ; cur_match <= limit ?
+        jbe     short the_end
+do_scan:
+        cmp     ax,word ptr _window[ebx+esi-1]   ; check match at best_len-1
+        jne     short_loop
+        cmp     cx,word ptr _window[esi]         ; check min_match_length match
+        jne     short_loop
+
+        lea     esi,_window[esi+2]      ; esi = match
+        mov     ecx,(MAX_MATCH-2)/2     ; scan for at most MAX_MATCH bytes
+        mov     eax,edi                 ; eax = scan+2
+        repe    cmpsw                   ; loop until mismatch
+        je      short maxmatch          ; match of length MAX_MATCH?
+mismatch:
+        mov     cl,[edi-2]              ; mismatch on first or second byte?
+        xchg    eax,edi                 ; edi = scan+2, eax = end of scan
+        sub     cl,[esi-2]              ; cl = 0 if first bytes equal
+        sub     eax,edi                 ; eax = len
+        sub     esi,2+offset _window    ; esi = match - (2 + offset(window))
+        sub     esi,eax                 ; esi = cur_match (= match - len)
+        sub     cl,1                    ; set carry if cl == 0 (can't use DEC)
+        adc     eax,0                   ; eax = carry ? len+1 : len
+        cmp     eax,ebx                 ; len > best_len ?
+        jle     long_loop
+        mov     _match_start,esi        ; match_start = cur_match
+        mov     ebx,eax                 ; ebx = best_len = len
+    ifdef FULL_SEARCH
+        cmp     eax,MAX_MATCH           ; len >= MAX_MATCH ?
+    else
+        cmp     eax,_nice_match         ; len >= nice_match ?
+    endif
+        jl      long_loop
+the_end:
+        mov     eax,ebx                 ; result = eax = best_len
+        pop     ebx
+        pop     esi
+        pop     edi
+        pop     ebp
+        ret
+maxmatch:                               ; come here if maximum match
+        cmpsb                           ; increment esi and edi
+        jmp     mismatch                ; force match_length = MAX_LENGTH
+
+_longest_match endp
+
+_TEXT   ends
+;
+    ENDIF ; !USE_ZLIB
+;
+end
diff --git a/win32/nt.c b/win32/nt.c
new file mode 100644 (file)
index 0000000..6a757b8
--- /dev/null
@@ -0,0 +1,482 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*++
+
+Copyright (c) 1996  Scott Field
+
+Module Name:
+
+    nt.c (formerly nt_zip.c)
+
+Abstract:
+
+    This module implements WinNT security descriptor operations for the
+    Win32 Info-ZIP project.  Operation such as querying file security,
+    using/querying local and remote privileges.  The contents of this module
+    are only relevant when the code is running on Windows NT, and the target
+    volume supports persistent Acl storage.
+
+    User privileges that allow accessing certain privileged aspects of the
+    security descriptor (such as the Sacl) are only used if the user specified
+    to do so.
+
+    In the future, this module may be expanded to support storage of
+    OS/2 EA data, Macintosh resource forks, and hard links, which are all
+    supported by NTFS.
+
+Author:
+
+    Scott Field (sfield@microsoft.com)  27-Sep-96
+
+--*/
+
+#include "../zip.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#ifdef __RSXNT__
+#  include "../win32/rsxntwin.h"
+#endif
+#include "../win32/nt.h"
+
+#ifdef NTSD_EAS         /* This file is only needed for NTSD handling */
+
+/* Borland C++ does not define FILE_SHARE_DELETE. Others also? */
+#ifndef FILE_SHARE_DELETE
+#  define FILE_SHARE_DELETE 0x00000004
+#endif
+
+/* private prototypes */
+
+static BOOL Initialize(VOID);
+#if 0   /* currently unused */
+static BOOL Shutdown(VOID);
+#endif
+static VOID GetRemotePrivilegesGet(CHAR *FileName, PDWORD dwRemotePrivileges);
+static VOID InitLocalPrivileges(VOID);
+
+
+BOOL bZipInitialized = FALSE;  /* module level stuff initialized? */
+HANDLE hZipInitMutex = NULL;   /* prevent multiple initialization */
+
+BOOL g_bBackupPrivilege = FALSE;    /* for local get file security override */
+BOOL g_bZipSaclPrivilege = FALSE;      /* for local get sacl operations, only when
+                                       backup privilege not present */
+
+/* our single cached volume capabilities structure that describes the last
+   volume root we encountered.  A single entry like this works well in the
+   zip/unzip scenario for a number of reasons:
+   1. typically one extraction path during unzip.
+   2. typically process one volume at a time during zip, and then move
+      on to the next.
+   3. no cleanup code required and no memory leaks.
+   4. simple code.
+
+   This approach should be reworked to a linked list approach if we expect to
+   be called by many threads which are processing a variety of input/output
+   volumes, since lock contention and stale data may become a bottleneck. */
+
+VOLUMECAPS g_VolumeCaps;
+CRITICAL_SECTION VolumeCapsLock;
+
+
+static BOOL Initialize(VOID)
+{
+    HANDLE hMutex;
+    HANDLE hOldMutex;
+
+    if(bZipInitialized) return TRUE;
+
+    hMutex = CreateMutex(NULL, TRUE, NULL);
+    if(hMutex == NULL) return FALSE;
+
+    hOldMutex = (HANDLE)InterlockedExchange((LPLONG)&hZipInitMutex, (LONG)hMutex);
+
+    if(hOldMutex != NULL) {
+        /* somebody setup the mutex already */
+        InterlockedExchange((LPLONG)&hZipInitMutex, (LONG)hOldMutex);
+
+        CloseHandle(hMutex); /* close new, un-needed mutex */
+
+        /* wait for initialization to complete and return status */
+        WaitForSingleObject(hOldMutex, INFINITE);
+        ReleaseMutex(hOldMutex);
+
+        return bZipInitialized;
+    }
+
+    /* initialize module level resources */
+
+    InitializeCriticalSection( &VolumeCapsLock );
+    memset(&g_VolumeCaps, 0, sizeof(VOLUMECAPS));
+
+    InitLocalPrivileges();
+
+    bZipInitialized = TRUE;
+
+    ReleaseMutex(hMutex); /* release correct mutex */
+
+    return TRUE;
+}
+
+#if 0   /* currently not used ! */
+static BOOL Shutdown(VOID)
+{
+    /* really need to free critical sections, disable enabled privilges, etc,
+       but doing so brings up possibility of race conditions if those resources
+       are about to be used.  The easiest way to handle this is let these
+       resources be freed when the process terminates... */
+
+    return TRUE;
+}
+#endif /* never */
+
+
+static VOID GetRemotePrivilegesGet(char *FileName, PDWORD dwRemotePrivileges)
+{
+    HANDLE hFile;
+
+    *dwRemotePrivileges = 0;
+
+    /* see if we have the SeBackupPrivilege */
+
+    hFile = CreateFileA(
+        FileName,
+        ACCESS_SYSTEM_SECURITY | GENERIC_READ | READ_CONTROL,
+        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+        NULL,
+        OPEN_EXISTING,
+        FILE_FLAG_BACKUP_SEMANTICS,
+        NULL
+        );
+
+    if(hFile != INVALID_HANDLE_VALUE) {
+        /* no remote way to determine SeBackupPrivilege -- just try a read
+           to simulate it */
+        SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
+        PSECURITY_DESCRIPTOR sd;
+        DWORD cbBuf = 0;
+
+        GetKernelObjectSecurity(hFile, si, NULL, cbBuf, &cbBuf);
+
+        if(ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
+            if((sd = HeapAlloc(GetProcessHeap(), 0, cbBuf)) != NULL) {
+                if(GetKernelObjectSecurity(hFile, si, sd, cbBuf, &cbBuf)) {
+                    *dwRemotePrivileges |= OVERRIDE_BACKUP;
+                }
+                HeapFree(GetProcessHeap(), 0, sd);
+            }
+        }
+
+        CloseHandle(hFile);
+    } else {
+
+        /* see if we have the SeSecurityPrivilege */
+        /* note we don't need this if we have SeBackupPrivilege */
+
+        hFile = CreateFileA(
+            FileName,
+            ACCESS_SYSTEM_SECURITY,
+            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* maximum sharing */
+            NULL,
+            OPEN_EXISTING,
+            0,
+            NULL
+            );
+
+        if(hFile != INVALID_HANDLE_VALUE) {
+            CloseHandle(hFile);
+            *dwRemotePrivileges |= OVERRIDE_SACL;
+        }
+    }
+}
+
+
+BOOL ZipGetVolumeCaps(
+    char *rootpath,         /* filepath, or NULL */
+    char *name,             /* filename associated with rootpath */
+    PVOLUMECAPS VolumeCaps  /* result structure describing capabilities */
+    )
+{
+    char TempRootPath[MAX_PATH + 1];
+    DWORD cchTempRootPath = 0;
+    BOOL bSuccess = TRUE;   /* assume success until told otherwise */
+
+    if(!bZipInitialized) if(!Initialize()) return FALSE;
+
+    /* process the input path to produce a consistent path suitable for
+       compare operations and also suitable for certain picky Win32 API
+       that don't like forward slashes */
+
+    if(rootpath != NULL && rootpath[0] != '\0') {
+        DWORD i;
+
+        cchTempRootPath = lstrlen(rootpath);
+        if(cchTempRootPath > MAX_PATH) return FALSE;
+
+        /* copy input, converting forward slashes to back slashes as we go */
+
+        for(i = 0 ; i <= cchTempRootPath ; i++) {
+            if(rootpath[i] == '/') TempRootPath[i] = '\\';
+            else TempRootPath[i] = rootpath[i];
+        }
+
+        /* check for UNC and Null terminate or append trailing \ as appropriate */
+
+        /* possible valid UNCs we are passed follow:
+           \\machine\foo\bar (path is \\machine\foo\)
+           \\machine\foo     (path is \\machine\foo\)
+           \\machine\foo\
+           \\.\c$\           (FIXFIX: Win32API doesn't like this - GetComputerName())
+           LATERLATER: handling mounted DFS drives in the future will require
+                       slightly different logic which isn't available today.
+                       This is required because directories can point at
+                       different servers which have differing capabilities.
+         */
+
+        if(TempRootPath[0] == '\\' && TempRootPath[1] == '\\') {
+            DWORD slash = 0;
+
+            for(i = 2 ; i < cchTempRootPath ; i++) {
+                if(TempRootPath[i] == '\\') {
+                    slash++;
+
+                    if(slash == 2) {
+                        i++;
+                        TempRootPath[i] = '\0';
+                        cchTempRootPath = i;
+                        break;
+                    }
+                }
+            }
+
+            /* if there was only one slash found, just tack another onto the end */
+
+            if(slash == 1 && TempRootPath[cchTempRootPath] != '\\') {
+                TempRootPath[cchTempRootPath] = TempRootPath[0]; /* '\' */
+                TempRootPath[cchTempRootPath+1] = '\0';
+                cchTempRootPath++;
+            }
+
+        } else {
+
+            if(TempRootPath[1] == ':') {
+
+                /* drive letter specified, truncate to root */
+                TempRootPath[2] = '\\';
+                TempRootPath[3] = '\0';
+                cchTempRootPath = 3;
+            } else {
+
+                /* must be file on current drive */
+                TempRootPath[0] = '\0';
+                cchTempRootPath = 0;
+            }
+
+        }
+
+    } /* if path != NULL */
+
+    /* grab lock protecting cached entry */
+    EnterCriticalSection( &VolumeCapsLock );
+
+    if(!g_VolumeCaps.bValid || lstrcmpi(g_VolumeCaps.RootPath, TempRootPath) != 0) {
+
+        /* no match found, build up new entry */
+
+        DWORD dwFileSystemFlags;
+        DWORD dwRemotePrivileges = 0;
+        BOOL bRemote = FALSE;
+
+        /* release lock during expensive operations */
+        LeaveCriticalSection( &VolumeCapsLock );
+
+        bSuccess = GetVolumeInformation(
+            (TempRootPath[0] == '\0') ? NULL : TempRootPath,
+            NULL, 0,
+            NULL, NULL,
+            &dwFileSystemFlags,
+            NULL, 0);
+
+        /* only if target volume supports Acls, and we were told to use
+           privileges do we need to go out and test for the remote case */
+
+        if(bSuccess && (dwFileSystemFlags & FS_PERSISTENT_ACLS) && VolumeCaps->bUsePrivileges) {
+            if(GetDriveType( (TempRootPath[0] == '\0') ? NULL : TempRootPath ) == DRIVE_REMOTE) {
+                bRemote = TRUE;
+
+                /* make a determination about our remote capabilities */
+
+                GetRemotePrivilegesGet(name, &dwRemotePrivileges);
+            }
+        }
+
+        /* always take the lock again, since we release it below */
+        EnterCriticalSection( &VolumeCapsLock );
+
+        /* replace the existing data if successful */
+        if(bSuccess) {
+
+            lstrcpynA(g_VolumeCaps.RootPath, TempRootPath, cchTempRootPath+1);
+            g_VolumeCaps.bProcessDefer = FALSE;
+            g_VolumeCaps.dwFileSystemFlags = dwFileSystemFlags;
+            g_VolumeCaps.bRemote = bRemote;
+            g_VolumeCaps.dwRemotePrivileges = dwRemotePrivileges;
+            g_VolumeCaps.bValid = TRUE;
+        }
+    }
+
+    if(bSuccess) {
+        /* copy input elements */
+        g_VolumeCaps.bUsePrivileges = VolumeCaps->bUsePrivileges;
+        g_VolumeCaps.dwFileAttributes = VolumeCaps->dwFileAttributes;
+
+        /* give caller results */
+        memcpy(VolumeCaps, &g_VolumeCaps, sizeof(VOLUMECAPS));
+    } else {
+        g_VolumeCaps.bValid = FALSE;
+    }
+
+    LeaveCriticalSection( &VolumeCapsLock ); /* release lock */
+
+    return bSuccess;
+}
+
+BOOL SecurityGet(
+    char *resource,
+    PVOLUMECAPS VolumeCaps,
+    unsigned char *buffer,
+    DWORD *cbBuffer
+    )
+{
+    HANDLE hFile;
+    DWORD dwDesiredAccess;
+    DWORD dwFlags;
+    PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)buffer;
+    SECURITY_INFORMATION RequestedInfo;
+    BOOL bBackupPrivilege = FALSE;
+    BOOL bSaclPrivilege = FALSE;
+    BOOL bSuccess = FALSE;
+
+    DWORD cchResourceLen;
+
+    if(!bZipInitialized) if(!Initialize()) return FALSE;
+
+    /* see if we are dealing with a directory */
+    /* rely on the fact resource has a trailing [back]slash, rather
+       than calling expensive GetFileAttributes() */
+
+    cchResourceLen = lstrlenA(resource);
+
+    if(resource[cchResourceLen-1] == '/' || resource[cchResourceLen-1] == '\\')
+        VolumeCaps->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
+
+    /* setup privilege usage based on if told we can use privileges, and if so,
+       what privileges we have */
+
+    if(VolumeCaps->bUsePrivileges) {
+        if(VolumeCaps->bRemote) {
+            /* use remotely determined privileges */
+            if(VolumeCaps->dwRemotePrivileges & OVERRIDE_BACKUP)
+                bBackupPrivilege = TRUE;
+
+            if(VolumeCaps->dwRemotePrivileges & OVERRIDE_SACL)
+                bSaclPrivilege = TRUE;
+        } else {
+            /* use local privileges */
+            bBackupPrivilege = g_bBackupPrivilege;
+            bSaclPrivilege = g_bZipSaclPrivilege;
+        }
+    }
+
+    /* always try to read the basic security information:  Dacl, Owner, Group */
+
+    dwDesiredAccess = READ_CONTROL;
+
+    RequestedInfo = OWNER_SECURITY_INFORMATION |
+                    GROUP_SECURITY_INFORMATION |
+                    DACL_SECURITY_INFORMATION;
+
+    /* if we have the SeBackupPrivilege or SeSystemSecurityPrivilege, read
+       the Sacl, too */
+
+    if(bBackupPrivilege || bSaclPrivilege) {
+        dwDesiredAccess |= ACCESS_SYSTEM_SECURITY;
+        RequestedInfo |= SACL_SECURITY_INFORMATION;
+    }
+
+    dwFlags = 0;
+
+    /* if we have the backup privilege, specify that */
+    /* opening a directory requires FILE_FLAG_BACKUP_SEMANTICS */
+
+    if(bBackupPrivilege || (VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+        dwFlags |= FILE_FLAG_BACKUP_SEMANTICS;
+
+    hFile = CreateFileA(
+        resource,
+        dwDesiredAccess,
+        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* maximum sharing */
+        NULL,
+        OPEN_EXISTING,
+        dwFlags,
+        NULL
+        );
+
+    if(hFile == INVALID_HANDLE_VALUE) return FALSE;
+
+    if(GetKernelObjectSecurity(hFile, RequestedInfo, sd, *cbBuffer, cbBuffer)) {
+        *cbBuffer = GetSecurityDescriptorLength( sd );
+        bSuccess = TRUE;
+    }
+
+    CloseHandle(hFile);
+
+    return bSuccess;
+}
+
+static VOID InitLocalPrivileges(VOID)
+{
+    HANDLE hToken;
+    TOKEN_PRIVILEGES tp;
+
+    /* try to enable some interesting privileges that give us the ability
+       to get some security information that we normally cannot.
+
+       note that enabling privileges is only relevant on the local machine;
+       when accessing files that are on a remote machine, any privileges
+       that are present on the remote machine get enabled by default. */
+
+    if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
+        return;
+
+    tp.PrivilegeCount = 1;
+    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+    /* try to enable SeBackupPrivilege.
+       if this succeeds, we can read all aspects of the security descriptor */
+
+    if(LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &tp.Privileges[0].Luid)) {
+        if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) &&
+           GetLastError() == ERROR_SUCCESS) g_bBackupPrivilege = TRUE;
+    }
+
+    /* try to enable SeSystemSecurityPrivilege if SeBackupPrivilege not present.
+       if this succeeds, we can read the Sacl */
+
+    if(!g_bBackupPrivilege &&
+        LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid)) {
+
+        if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) &&
+           GetLastError() == ERROR_SUCCESS) g_bZipSaclPrivilege = TRUE;
+    }
+
+    CloseHandle(hToken);
+}
+#endif /* NTSD_EAS */
diff --git a/win32/nt.h b/win32/nt.h
new file mode 100644 (file)
index 0000000..72b83af
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#ifndef _NT_ZIP_H
+#define _NT_ZIP_H
+
+/* central header for EF_NTSD "SD" extra field */
+
+#define EF_NTSD_MAX_VER_SUPPORT (0)
+                        /* describes maximum ver# we know how to handle */
+
+typedef struct
+{
+  USHORT nID;
+  USHORT nSize;
+  ULONG lSize;
+}
+EF_NTSD_C_HEADER, *PEF_NTSD_C_HEADER;
+
+#define EF_NTSD_C_LEN (sizeof(EF_NTSD_C_HEADER))
+
+/* local header for EF_NTSD "SD" extra field */
+
+#pragma pack(1) /* bytes following structure immediately follow BYTE Version */
+
+typedef struct
+{
+  USHORT nID;   /* tag for this extra block type */
+  USHORT nSize; /* total data size for this block */
+  ULONG lSize;  /* uncompressed security descriptor data size */
+  BYTE Version; /* Version of uncompressed security descriptor data format */
+}
+IZ_PACKED EF_NTSD_L_HEADER, *PEF_NTSD_L_HEADER;
+
+#pragma pack()
+
+/*  ...followed by... */
+/*  SHORT CType;  compression type */
+/*  ULONG EACRC;  CRC value for uncompressed security descriptor data */
+/*  <var.> Variable length data */
+
+
+#define EF_NTSD_L_LEN (EF_NTSD_C_LEN + sizeof(BYTE))
+                                /* avoid alignment size computation */
+
+#define NTSD_BUFFERSIZE (1024)  /* threshold to cause malloc() */
+
+#define OVERRIDE_BACKUP     1   /* we have SeBackupPrivilege on remote */
+#define OVERRIDE_RESTORE    2   /* we have SeRestorePrivilege on remote */
+#define OVERRIDE_SACL       4   /* we have SeSystemSecurityPrivilege on remote */
+
+typedef struct {
+    BOOL bValid;                /* are our contents valid? */
+    BOOL bProcessDefer;         /* process deferred entry yet? */
+    BOOL bUsePrivileges;        /* use privilege overrides? */
+    DWORD dwFileSystemFlags;    /* describes target file system */
+    BOOL bRemote;               /* is volume remote? */
+    DWORD dwRemotePrivileges;   /* relevant only on remote volumes */
+    DWORD dwFileAttributes;
+    char RootPath[MAX_PATH+1];  /* path to network / filesystem */
+} VOLUMECAPS, *PVOLUMECAPS, *LPVOLUMECAPS;
+
+BOOL SecurityGet(char *resource, PVOLUMECAPS VolumeCaps, unsigned char *buffer,
+                 DWORD *cbBuffer);
+BOOL ZipGetVolumeCaps(char *rootpath, char *name, PVOLUMECAPS VolumeCaps);
+
+#endif /* _NT_ZIP_H */
+
diff --git a/win32/osdep.h b/win32/osdep.h
new file mode 100644 (file)
index 0000000..a867088
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* Automatic setting of the common Microsoft C idenfifier MSC.
+ * NOTE: Watcom also defines M_I*86 !
+ */
+#if defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__))
+#  ifndef MSC
+#    define MSC                 /* This should work for older MSC, too!  */
+#  endif
+#endif
+
+#if defined(__WATCOMC__) && defined(__386__)
+#  define WATCOMC_386
+#endif
+
+#if (defined(__CYGWIN32__) && !defined(__CYGWIN__))
+#  define __CYGWIN__            /* compatibility for CygWin B19 and older */
+#endif
+
+/* enable multibyte character set support by default */
+#ifndef _MBCS
+#  define _MBCS
+#endif
+#if defined(__CYGWIN__)
+#  undef _MBCS
+#endif
+
+#ifndef MSDOS
+/*
+ * Windows 95 (and Windows NT) file systems are (to some extend)
+ * extensions of MSDOS. Common features include for example:
+ *      FAT or (FAT like) file systems,
+ *      '\\' as directory separator in paths,
+ *      "\r\n" as record (line) terminator in text files, ...
+ */
+#  define MSDOS
+/* inherit MS-DOS file system etc. stuff */
+#endif
+
+#define USE_CASE_MAP
+#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \
+                     procname(n, 1))
+#define BROKEN_FSEEK
+#ifndef __RSXNT__
+#  define HAVE_FSEEKABLE
+#endif
+
+/* File operations--use "b" for binary if allowed or fixed length 512 on VMS
+ *                  use "S" for sequential access on NT to prevent the NT
+ *                  file cache eating up memory with large .zip files
+ */
+#define FOPR "rb"
+#define FOPM "r+b"
+#define FOPW "wbS"
+
+#if (defined(__CYGWIN__) && !defined(NO_MKTIME))
+#  define NO_MKTIME             /* Cygnus' mktime() implementation is buggy */
+#endif
+#if (!defined(NT_TZBUG_WORKAROUND) && !defined(NO_NT_TZBUG_WORKAROUND))
+#  define NT_TZBUG_WORKAROUND
+#endif
+#if (defined(UTIL) && defined(NT_TZBUG_WORKAROUND))
+#  undef NT_TZBUG_WORKAROUND    /* the Zip utilities do not use time-stamps */
+#endif
+#if !defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)
+#  define USE_EF_UT_TIME
+#endif
+#if (!defined(NO_NTSD_EAS) && !defined(NTSD_EAS))
+#  define NTSD_EAS
+#endif
+
+#if (defined(NTSD_EAS) && !defined(ZP_NEED_MEMCOMPR))
+#  define ZP_NEED_MEMCOMPR
+#endif
+
+#ifdef WINDLL
+# ifndef NO_ASM
+#   define NO_ASM
+# endif
+# ifndef MSWIN
+#   define MSWIN
+# endif
+# ifndef REENTRANT
+#   define REENTRANT
+# endif
+#endif /* WINDLL */
+
+/* Enable use of optimized x86 assembler version of longest_match() for
+   MSDOS, WIN32 and OS2 per default.  */
+#if !defined(NO_ASM) && !defined(ASMV)
+#  define ASMV
+#endif
+
+/* Enable use of optimized x86 assembler version of crc32() for
+   MSDOS, WIN32 and OS2 per default.  */
+#if !defined(NO_ASM) && !defined(ASM_CRC)  && !defined(NO_ASM_CRC)
+#  define ASM_CRC
+#endif
+
+#if !defined(__GO32__) && !defined(__EMX__) && !defined(__CYGWIN__)
+#  define NO_UNISTD_H
+#endif
+
+/* the following definitions are considered as "obsolete" by Microsoft and
+ * might be missing in some versions of <windows.h>
+ */
+#ifndef AnsiToOem
+#  define AnsiToOem CharToOemA
+#endif
+#ifndef OemToAnsi
+#  define OemToAnsi OemToCharA
+#endif
+
+#if (defined(__RSXNT__) && defined(__CRTRSXNT__))
+#  include <crtrsxnt.h>
+#endif
+
+/* Get types and stat */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#ifdef _MBCS
+#  if (!defined(__EMX__) && !defined(__MINGW32__) && !defined(__CYGWIN__))
+#    include <stdlib.h>
+#    include <mbstring.h>
+#  endif
+#  if (defined(__MINGW32__) && !defined(MB_CUR_MAX))
+#    ifdef __MSVCRT__
+       extern int *__p___mb_cur_max(void);
+#      define MB_CUR_MAX (*__p___mb_cur_max())
+#    else
+       extern int *_imp____mb_cur_max_dll;
+#      define MB_CUR_MAX (*_imp____mb_cur_max_dll)
+#    endif
+#  endif
+#  if (defined(__LCC__) && !defined(MB_CUR_MAX))
+     extern int *_imp____mb_cur_max;
+#    define MB_CUR_MAX (*_imp____mb_cur_max)
+#  endif
+#endif
+
+#ifdef __LCC__
+#  include <time.h>
+#  ifndef tzset
+#    define tzset _tzset
+#  endif
+#  ifndef utime
+#    define utime _utime
+#  endif
+#endif
+#ifdef __MINGW32__
+   extern void _tzset(void);            /* this is missing in <time.h> */
+#  ifndef tzset
+#    define tzset _tzset
+#  endif
+#endif
+#if (defined(__RSXNT__) || defined(__EMX__)) && !defined(tzset)
+#  define tzset _tzset
+#endif
+#ifdef W32_USE_IZ_TIMEZONE
+#  ifdef __BORLANDC__
+#    define tzname tzname
+#    define IZTZ_DEFINESTDGLOBALS
+#  endif
+#  ifndef tzset
+#    define tzset _tzset
+#  endif
+#  ifndef timezone
+#    define timezone _timezone
+#  endif
+#  ifndef daylight
+#    define daylight _daylight
+#  endif
+#  ifndef tzname
+#    define tzname _tzname
+#  endif
+#  if (!defined(NEED__ISINDST) && !defined(__BORLANDC__))
+#    define NEED__ISINDST
+#  endif
+#  ifdef IZTZ_GETLOCALETZINFO
+#    undef IZTZ_GETLOCALETZINFO
+#  endif
+#  define IZTZ_GETLOCALETZINFO GetPlatformLocalTimezone
+#endif /* W32_USE_IZ_TIMEZONE */
+
+#ifdef MATCH
+#  undef MATCH
+#endif
+#define MATCH dosmatch          /* use DOS style wildcard matching */
+
+#ifdef ZCRYPT_INTERNAL
+#  ifdef WINDLL
+#    define ZCR_SEED2     (unsigned)3141592654L /* use PI as seed pattern */
+#  else
+#    include <process.h>        /* getpid() declaration for srand seed */
+#  endif
+#endif
+
+/* Up to now, all versions of Microsoft C runtime libraries lack the support
+ * for customized (non-US) switching rules between daylight saving time and
+ * standard time in the TZ environment variable string.
+ * But non-US timezone rules are correctly supported when timezone information
+ * is read from the OS system settings in the Win32 registry.
+ * The following work-around deletes any TZ environment setting from
+ * the process environment.  This results in a fallback of the RTL time
+ * handling code to the (correctly interpretable) OS system settings, read
+ * from the registry.
+ */
+#ifdef USE_EF_UT_TIME
+# if (defined(__WATCOMC__) || defined(W32_USE_IZ_TIMEZONE))
+#   define iz_w32_prepareTZenv()
+# else
+#   define iz_w32_prepareTZenv()        putenv("TZ=")
+# endif
+#endif
+
+/* This patch of stat() is useful for at least three compilers.  It is   */
+/* difficult to take a stat() of a root directory under Windows95, so  */
+/* zstat_zipwin32() detects that case and fills in suitable values.    */
+#ifndef __RSXNT__
+#  ifndef W32_STATROOT_FIX
+#    define W32_STATROOT_FIX
+#  endif
+#endif /* !__RSXNT__ */
+
+#if (defined(NT_TZBUG_WORKAROUND) || defined(W32_STATROOT_FIX))
+#  define W32_STAT_BANDAID
+   int zstat_zipwin32(const char *path, struct stat *buf);
+#  ifdef SSTAT
+#    undef SSTAT
+#  endif
+#  define SSTAT zstat_zipwin32
+#endif /* NT_TZBUG_WORKAROUND || W32_STATROOT_FIX */
+
+int getch_win32(void);
+
+#ifdef __GNUC__
+# define IZ_PACKED      __attribute__((packed))
+#else
+# define IZ_PACKED
+#endif
+
+/* for some (all ?) versions of IBM C Set/2 and IBM C Set++ */
+#ifndef S_IFMT
+#  define S_IFMT 0xF000
+#endif /* !S_IFMT */
+
+#ifdef __WATCOMC__
+#  include <stdio.h>    /* PATH_MAX is defined here */
+#  define NO_MKTEMP
+
+/* Get asm routines to link properly without using "__cdecl": */
+#  ifdef __386__
+#    ifdef ASMV
+#      pragma aux match_init    "_*" parm caller [] modify []
+#      pragma aux longest_match "_*" parm caller [] value [eax] \
+                                      modify [eax ecx edx]
+#    endif
+#    if defined(ASM_CRC) && !defined(USE_ZLIB)
+#      pragma aux crc32         "_*" parm caller [] value [eax] modify [eax]
+#      pragma aux get_crc_table "_*" parm caller [] value [eax] \
+                                      modify [eax ecx edx]
+#    endif /* ASM_CRC && !USE_ZLIB */
+#  endif /* __386__ */
+#endif /* __WATCOMC__ */
diff --git a/win32/readme.a64 b/win32/readme.a64
new file mode 100644 (file)
index 0000000..54b2750
--- /dev/null
@@ -0,0 +1,42 @@
+readme.x64
+==========
+
+[Note - the gvmat64.asm longest_match routine in Windows 64-bit assembler
+and makefile.a64 used to compile it were provided at the last minute and
+are currently untested by Info-ZIP.  They are provided to allow testing of
+this optimization which is planned for inclusion in Zip 3.0.
+USE AT YOUR OWN RISK.  That said, thanks Gilles for providing this
+optimization and we plan to better support it in Zip 3.0.  2/28/2005 EG]
+
+makefile.asm64 is a makefile for 64 bits optimized version of zip for 
+Microsoft Windows running on AMD64 (Athlon64/Opteron) and Intel EM64T
+(the Pentium 4 and Xeon with 64 bits extension)
+
+makefile.asm64 contain a makefile for 64 Microsoft C++ for Windows 64 bits,
+extended edition (for both AMD64 and Intel EM64T), included in Visual
+Studio 2005
+
+to compile it, start the C++ AMD64 build environnement prompt,
+go to the zip source directory and start
+
+   nmake -a -f makefile.a64
+
+This makefile uses gvmat64.asm, which is the optimized longest_match written
+in assembly code for AMD64/Intel EM64T
+
+gvmat64.asm was tested by Gilles Vollant on AMD64 with infozip, and also tested
+with a lot of file with zLib 1.2.2 on both AMD64 and Intel EM64T processor.
+
+It was written by Gilles Vollant, by modifiying the longest_match
+from Jean-loup Gailly in deflate.c of zLib and infoZip zip.
+and modifying asm686 (1998), optimised assembly code from Brian Raiter,
+(see http://www.muppetlabs.com/~breadbox/software/assembly.html)
+
+
+Gilles Vollant
+info@winimage.com
+
+http://www.winimage.com
+http://www.winimage.com/zLibdll
+
+
diff --git a/win32/rsxntwin.h b/win32/rsxntwin.h
new file mode 100644 (file)
index 0000000..3df30e8
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* rsxntwin.h
+ *
+ * fills some gaps in the rsxnt 1.3 win32 header files (<windows.h>) that are
+ * required for compiling Info-ZIP sources for Win NT / Win 95
+ */
+
+#ifdef __RSXNT__
+#if !defined (_RSXNTWIN_H)
+#define _RSXNTWIN_H
+
+#ifdef TFUNCT   /* TFUNCT is undefined when MSSDK headers are used */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PASCAL __stdcall
+
+#define ANYSIZE_ARRAY 1
+
+#ifndef TIME_ZONE_ID_UNKNOWN
+#  define TIME_ZONE_ID_UNKNOWN  0
+#endif
+#ifndef TIME_ZONE_ID_INVALID
+#  define TIME_ZONE_ID_INVALID  (DWORD)0xFFFFFFFFL
+#endif
+
+#define FILE_ATTRIBUTE_HIDDEN   0x00000002
+#define FILE_ATTRIBUTE_SYSTEM   0x00000004
+
+#define FILE_SHARE_DELETE       0x00000004
+
+#define FILE_PERSISTENT_ACLS    0x00000008
+
+#define HFILE_ERROR        ((HFILE)-1)
+
+#define FS_PERSISTENT_ACLS      FILE_PERSISTENT_ACLS
+
+
+BOOL WINAPI DosDateTimeToFileTime(WORD, WORD, LPFILETIME);
+
+
+#ifndef SetVolumeLabel
+#define SetVolumeLabel TFUNCT(SetVolumeLabel)
+#endif
+BOOL WINAPI SetVolumeLabel(LPCTSTR, LPCTSTR);
+
+
+#ifndef GetDriveType
+#define GetDriveType TFUNCT(GetDriveType)
+#endif
+DWORD GetDriveType(LPCTSTR);
+
+#define DRIVE_UNKNOWN     0
+#define DRIVE_REMOVABLE   2
+#define DRIVE_FIXED       3
+#define DRIVE_REMOTE      4
+#define DRIVE_CDROM       5
+#define DRIVE_RAMDISK     6
+
+#ifndef SearchPath
+#define SearchPath TFUNCT(SearchPath)
+#endif
+BOOL WINAPI SearchPath(LPCTSTR, LPCTSTR, LPCTSTR, UINT, LPTSTR, LPTSTR *);
+
+#define ERROR_SUCCESS                   0
+#define ERROR_INSUFFICIENT_BUFFER       122
+
+LONG WINAPI InterlockedExchange(LPLONG, LONG);
+
+#define ACCESS_SYSTEM_SECURITY          0x01000000L
+
+typedef PVOID PSECURITY_DESCRIPTOR;
+typedef PVOID PSID;
+typedef struct _ACL {
+    BYTE  AclRevision;
+    BYTE  Sbz1;
+    WORD   AclSize;
+    WORD   AceCount;
+    WORD   Sbz2;
+} ACL;
+typedef ACL *PACL;
+
+typedef struct _LUID {
+    DWORD LowPart;
+    LONG HighPart;
+} LUID, *PLUID;
+
+typedef struct _LUID_AND_ATTRIBUTES {
+    LUID Luid;
+    DWORD Attributes;
+    } LUID_AND_ATTRIBUTES, * PLUID_AND_ATTRIBUTES;
+
+typedef struct _TOKEN_PRIVILEGES {
+    DWORD PrivilegeCount;
+    LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
+} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
+
+#define TOKEN_QUERY             0x0008
+#define TOKEN_ADJUST_PRIVILEGES 0x0020
+
+BOOL WINAPI OpenProcessToken(HANDLE, DWORD, PHANDLE);
+BOOL WINAPI AdjustTokenPrivileges(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD,
+                PTOKEN_PRIVILEGES, PDWORD);
+
+#ifndef LookupPrivilegeValue
+#define LookupPrivilegeValue TFUNCT(LookupPrivilegeValue)
+#endif
+BOOL WINAPI LookupPrivilegeValue(LPCTSTR, LPCTSTR, PLUID);
+
+typedef DWORD SECURITY_INFORMATION, *PSECURITY_INFORMATION;
+#define OWNER_SECURITY_INFORMATION      0x00000001L
+#define GROUP_SECURITY_INFORMATION      0x00000002L
+#define DACL_SECURITY_INFORMATION       0x00000004L
+#define SACL_SECURITY_INFORMATION       0x00000008L
+
+typedef WORD SECURITY_DESCRIPTOR_CONTROL, *PSECURITY_DESCRIPTOR_CONTROL;
+#define SE_DACL_PRESENT         0x0004
+#define SE_SACL_PRESENT         0x0010
+
+#define SE_PRIVILEGE_ENABLED    0x00000002L
+
+#define SE_SECURITY_NAME                  TEXT("SeSecurityPrivilege")
+#define SE_BACKUP_NAME                    TEXT("SeBackupPrivilege")
+#define SE_RESTORE_NAME                   TEXT("SeRestorePrivilege")
+
+BOOL WINAPI GetKernelObjectSecurity(HANDLE, SECURITY_INFORMATION,
+                PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
+BOOL WINAPI SetKernelObjectSecurity(HANDLE, SECURITY_INFORMATION,
+                PSECURITY_DESCRIPTOR);
+BOOL WINAPI IsValidSid(PSID);
+BOOL WINAPI IsValidAcl(PACL);
+BOOL WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR);
+BOOL WINAPI IsValidSecurityDescriptor(PSECURITY_DESCRIPTOR);
+DWORD WINAPI GetSecurityDescriptorLength(PSECURITY_DESCRIPTOR);
+BOOL WINAPI GetSecurityDescriptorControl(PSECURITY_DESCRIPTOR,
+                PSECURITY_DESCRIPTOR_CONTROL, LPDWORD);
+BOOL WINAPI SetSecurityDescriptorControl(PSECURITY_DESCRIPTOR,
+                SECURITY_DESCRIPTOR_CONTROL, SECURITY_DESCRIPTOR_CONTROL);
+BOOL WINAPI GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR,
+                                      LPBOOL, PACL *, LPBOOL);
+BOOL WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR, BOOL, PACL, BOOL);
+BOOL WINAPI GetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR,
+                                      LPBOOL, PACL *, LPBOOL);
+BOOL WINAPI SetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR, BOOL, PACL, BOOL);
+BOOL WINAPI GetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR, PSID *, LPBOOL);
+BOOL WINAPI SetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR, PSID, BOOL);
+BOOL WINAPI GetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR, PSID *, LPBOOL);
+BOOL WINAPI SetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR, PSID, BOOL);
+VOID WINAPI InitializeCriticalSection();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TFUNCT */
+#endif /* !defined (_RSXNTWIN_H) */
+#endif /* __RSXNT__ */
diff --git a/win32/vc6/zip.dsp b/win32/vc6/zip.dsp
new file mode 100644 (file)
index 0000000..f82b335
--- /dev/null
@@ -0,0 +1,328 @@
+# Microsoft Developer Studio Project File - Name="zip" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=zip - Win32 ASM Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "zip.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "zip.mak" CFG="zip - Win32 ASM Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "zip - Win32 ASM Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "zip - Win32 ASM Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "zip - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "zip - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "zip - Win32 ASM Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "zip___Win32_ASM_Release"\r
+# PROP BASE Intermediate_Dir "zip___Win32_ASM_Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "zip___Win32_ASM_Release"\r
+# PROP Intermediate_Dir "zip___Win32_ASM_Release"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /FD /c\r
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "ASM_CRC" /D "ASMV" /FD /c\r
+# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+\r
+!ELSEIF  "$(CFG)" == "zip - Win32 ASM Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "zip___Win32_ASM_Debug"\r
+# PROP BASE Intermediate_Dir "zip___Win32_ASM_Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "zip___Win32_ASM_Debug"\r
+# PROP Intermediate_Dir "zip___Win32_ASM_Debug"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /FD /GZ /c\r
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "ASM_CRC" /D "ASMV" /FD /GZ /c\r
+# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+\r
+!ELSEIF  "$(CFG)" == "zip - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "zip___Win32_Release"\r
+# PROP BASE Intermediate_Dir "zip___Win32_Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "zip___Win32_Release"\r
+# PROP Intermediate_Dir "zip___Win32_Release"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /FD /c\r
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NO_ASM" /FD /c\r
+# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+\r
+!ELSEIF  "$(CFG)" == "zip - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "zip___Win32_Debug"\r
+# PROP BASE Intermediate_Dir "zip___Win32_Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "zip___Win32_Debug"\r
+# PROP Intermediate_Dir "zip___Win32_Debug"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /FD /GZ /c\r
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "NO_ASM" /FD /GZ /c\r
+# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "zip - Win32 ASM Release"\r
+# Name "zip - Win32 ASM Debug"\r
+# Name "zip - Win32 Release"\r
+# Name "zip - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=..\..\crc32.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\crctab.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\crypt.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\deflate.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\fileio.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\globals.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\nt.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\trees.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ttyio.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\util.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\win32.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\win32zip.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\zip.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\zipfile.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\zipup.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=..\..\crypt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ebcdic.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\nt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\osdep.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\revision.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\tailor.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ttyio.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\win32zip.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\zip.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ziperr.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\zipup.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Assembler Files"\r
+\r
+# PROP Default_Filter "asm;obj"\r
+# Begin Source File\r
+\r
+SOURCE=..\crc_i386.asm\r
+\r
+!IF  "$(CFG)" == "zip - Win32 ASM Release"\r
+\r
+# Begin Custom Build - Assembling...\r
+IntDir=.\zip___Win32_ASM_Release\r
+InputPath=..\crc_i386.asm\r
+InputName=crc_i386\r
+\r
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"\r
+\r
+# End Custom Build\r
+\r
+!ELSEIF  "$(CFG)" == "zip - Win32 ASM Debug"\r
+\r
+# Begin Custom Build - Assembling...\r
+IntDir=.\zip___Win32_ASM_Debug\r
+InputPath=..\crc_i386.asm\r
+InputName=crc_i386\r
+\r
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"\r
+\r
+!ELSEIF  "$(CFG)" == "zip - Win32 Release"\r
+\r
+# PROP Exclude_From_Build 1\r
+\r
+!ELSEIF  "$(CFG)" == "zip - Win32 Debug"\r
+\r
+# PROP Exclude_From_Build 1\r
+\r
+# End Custom Build\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\match32.asm\r
+\r
+!IF  "$(CFG)" == "zip - Win32 ASM Release"\r
+\r
+# Begin Custom Build - Assembling...\r
+IntDir=.\zip___Win32_ASM_Release\r
+InputPath=..\match32.asm\r
+InputName=match32\r
+\r
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"\r
+\r
+# End Custom Build\r
+\r
+!ELSEIF  "$(CFG)" == "zip - Win32 ASM Debug"\r
+\r
+# Begin Custom Build - Assembling...\r
+IntDir=.\zip___Win32_ASM_Debug\r
+InputPath=..\match32.asm\r
+InputName=match32\r
+\r
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"\r
+\r
+!ELSEIF  "$(CFG)" == "zip - Win32 Release"\r
+\r
+# PROP Exclude_From_Build 1\r
+\r
+!ELSEIF  "$(CFG)" == "zip - Win32 Debug"\r
+\r
+# PROP Exclude_From_Build 1\r
+\r
+# End Custom Build\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/win32/vc6/zip.dsw b/win32/vc6/zip.dsw
new file mode 100644 (file)
index 0000000..681d183
--- /dev/null
@@ -0,0 +1,65 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "zip"=".\zip.dsp" - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Project: "zipcloak"=".\zipcloak.dsp" - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Project: "zipnote"=".\zipnote.dsp" - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Project: "zipsplit"=".\zipsplit.dsp" - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/win32/vc6/zipcloak.dsp b/win32/vc6/zipcloak.dsp
new file mode 100644 (file)
index 0000000..dac83fa
--- /dev/null
@@ -0,0 +1,164 @@
+# Microsoft Developer Studio Project File - Name="zipcloak" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=zipcloak - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "zipcloak.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "zipcloak.mak" CFG="zipcloak - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "zipcloak - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "zipcloak - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "zipcloak - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "zipcloak___Win32_Release"\r
+# PROP BASE Intermediate_Dir "zipcloak___Win32_Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "zipcloak___Win32_Release"\r
+# PROP Intermediate_Dir "zipcloak___Win32_Release"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /FD /c\r
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "UTIL" /FD /c\r
+# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+\r
+!ELSEIF  "$(CFG)" == "zipcloak - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "zipcloak___Win32_Debug"\r
+# PROP BASE Intermediate_Dir "zipcloak___Win32_Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "zipcloak___Win32_Debug"\r
+# PROP Intermediate_Dir "zipcloak___Win32_Debug"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /FD /GZ /c\r
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "UTIL" /FD /GZ /c\r
+# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "zipcloak - Win32 Release"\r
+# Name "zipcloak - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=..\..\crctab.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\crypt.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\fileio.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\globals.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ttyio.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\util.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\win32.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\zipcloak.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\zipfile.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=..\..\crypt.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ebcdic.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\osdep.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\revision.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\tailor.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ttyio.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\win32zip.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\zip.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ziperr.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/win32/vc6/zipnote.dsp b/win32/vc6/zipnote.dsp
new file mode 100644 (file)
index 0000000..e32e2f1
--- /dev/null
@@ -0,0 +1,144 @@
+# Microsoft Developer Studio Project File - Name="zipnote" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=zipnote - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "zipnote.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "zipnote.mak" CFG="zipnote - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "zipnote - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "zipnote - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "zipnote - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "zipnote___Win32_Release"\r
+# PROP BASE Intermediate_Dir "zipnote___Win32_Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "zipnote___Win32_Release"\r
+# PROP Intermediate_Dir "zipnote___Win32_Release"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /FD /c\r
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "UTIL" /FD /c\r
+# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+\r
+!ELSEIF  "$(CFG)" == "zipnote - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "zipnote___Win32_Debug"\r
+# PROP BASE Intermediate_Dir "zipnote___Win32_Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "zipnote___Win32_Debug"\r
+# PROP Intermediate_Dir "zipnote___Win32_Debug"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /FD /GZ /c\r
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "UTIL" /FD /GZ /c\r
+# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "zipnote - Win32 Release"\r
+# Name "zipnote - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=..\..\fileio.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\globals.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\util.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\win32.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\zipfile.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\zipnote.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ebcdic.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\osdep.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\revision.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\tailor.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\win32zip.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\zip.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ziperr.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/win32/vc6/zipsplit.dsp b/win32/vc6/zipsplit.dsp
new file mode 100644 (file)
index 0000000..aec7139
--- /dev/null
@@ -0,0 +1,144 @@
+# Microsoft Developer Studio Project File - Name="zipsplit" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=zipsplit - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "zipsplit.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "zipsplit.mak" CFG="zipsplit - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "zipsplit - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "zipsplit - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "zipsplit - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "zipsplit___Win32_Release"\r
+# PROP BASE Intermediate_Dir "zipsplit___Win32_Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "zipsplit___Win32_Release"\r
+# PROP Intermediate_Dir "zipsplit___Win32_Release"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /FD /c\r
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "UTIL" /FD /c\r
+# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+\r
+!ELSEIF  "$(CFG)" == "zipsplit - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "zipsplit___Win32_Debug"\r
+# PROP BASE Intermediate_Dir "zipsplit___Win32_Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "zipsplit___Win32_Debug"\r
+# PROP Intermediate_Dir "zipsplit___Win32_Debug"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /FD /GZ /c\r
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "UTIL" /FD /GZ /c\r
+# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "zipsplit - Win32 Release"\r
+# Name "zipsplit - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=..\..\fileio.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\globals.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\util.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\win32.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\zipfile.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\zipsplit.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ebcdic.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\osdep.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\revision.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\tailor.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\win32zip.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\zip.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\ziperr.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/win32/win32.c b/win32/win32.c
new file mode 100644 (file)
index 0000000..88bd565
--- /dev/null
@@ -0,0 +1,989 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ * WIN32 specific functions for ZIP.
+ *
+ * The WIN32 version of ZIP heavily relies on the MSDOS and OS2 versions,
+ * since we have to do similar things to switch between NTFS, HPFS and FAT.
+ */
+
+
+#include "../zip.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <time.h>
+#include <ctype.h>
+#include <windows.h>
+#ifdef __RSXNT__
+#  include <alloca.h>
+#  include "../win32/rsxntwin.h"
+#endif
+#include "../win32/win32zip.h"
+
+#define A_RONLY    0x01
+#define A_HIDDEN   0x02
+#define A_SYSTEM   0x04
+#define A_LABEL    0x08
+#define A_DIR      0x10
+#define A_ARCHIVE  0x20
+
+
+#define EAID     0x0009
+
+
+#ifndef UTIL
+
+extern int noisy;
+
+#ifdef NT_TZBUG_WORKAROUND
+local int FSusesLocalTime(const char *path);
+#endif
+#if (defined(USE_EF_UT_TIME) || \
+     (defined(NT_TZBUG_WORKAROUND) && !defined(NO_W32TIMES_IZFIX)))
+local int NtfsFileTime2utime(const FILETIME *pft, time_t *ut);
+#endif
+#if (defined(NT_TZBUG_WORKAROUND) && defined(W32_STAT_BANDAID))
+local int VFatFileTime2utime(const FILETIME *pft, time_t *ut);
+#endif
+
+
+/* FAT / HPFS detection */
+
+int IsFileSystemOldFAT(const char *dir)
+{
+  char root[4];
+  char vname[128];
+  DWORD vnamesize = sizeof(vname);
+  DWORD vserial;
+  DWORD vfnsize;
+  DWORD vfsflags;
+  char vfsname[128];
+  DWORD vfsnamesize = sizeof(vfsname);
+
+    /*
+     * We separate FAT and HPFS+other file systems here.
+     * I consider other systems to be similar to HPFS/NTFS, i.e.
+     * support for long file names and being case sensitive to some extent.
+     */
+
+    strncpy(root, dir, 3);
+    if ( isalpha((uch)root[0]) && (root[1] == ':') ) {
+      root[0] = to_up(dir[0]);
+      root[2] = '\\';
+      root[3] = 0;
+    }
+    else {
+      root[0] = '\\';
+      root[1] = 0;
+    }
+
+    if ( !GetVolumeInformation(root, vname, vnamesize,
+                         &vserial, &vfnsize, &vfsflags,
+                         vfsname, vfsnamesize)) {
+        fprintf(mesg, "zip diagnostic: GetVolumeInformation failed\n");
+        return(FALSE);
+    }
+
+    return vfnsize <= 12;
+}
+
+
+/* access mode bits and time stamp */
+
+int GetFileMode(const char *name)
+{
+DWORD dwAttr;
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+  char *ansi_name = (char *)alloca(strlen(name) + 1);
+
+  OemToAnsi(name, ansi_name);
+  name = (const char *)ansi_name;
+#endif
+
+  dwAttr = GetFileAttributes(name);
+  if ( dwAttr == 0xFFFFFFFF ) {
+    fprintf(mesg, "zip diagnostic: GetFileAttributes failed\n");
+    return(0x20); /* the most likely, though why the error? security? */
+  }
+  return(
+          (dwAttr&FILE_ATTRIBUTE_READONLY  ? A_RONLY   :0)
+        | (dwAttr&FILE_ATTRIBUTE_HIDDEN    ? A_HIDDEN  :0)
+        | (dwAttr&FILE_ATTRIBUTE_SYSTEM    ? A_SYSTEM  :0)
+        | (dwAttr&FILE_ATTRIBUTE_DIRECTORY ? A_DIR     :0)
+        | (dwAttr&FILE_ATTRIBUTE_ARCHIVE   ? A_ARCHIVE :0));
+}
+
+
+#ifdef NT_TZBUG_WORKAROUND
+local int FSusesLocalTime(const char *path)
+{
+    char  *tmp0;
+    char   rootPathName[4];
+    char   tmp1[MAX_PATH], tmp2[MAX_PATH];
+    DWORD  volSerNo, maxCompLen, fileSysFlags;
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+    char *ansi_path = (char *)alloca(strlen(path) + 1);
+
+    OemToAnsi(path, ansi_path);
+    path = (const char *)ansi_path;
+#endif
+
+    if (isalpha((uch)path[0]) && (path[1] == ':'))
+        tmp0 = (char *)path;
+    else
+    {
+        GetFullPathName(path, MAX_PATH, tmp1, &tmp0);
+        tmp0 = &tmp1[0];
+    }
+    strncpy(rootPathName, tmp0, 3);   /* Build the root path name, */
+    rootPathName[3] = '\0';           /* e.g. "A:/"                */
+
+    GetVolumeInformation((LPCTSTR)rootPathName, (LPTSTR)tmp1, (DWORD)MAX_PATH,
+                         &volSerNo, &maxCompLen, &fileSysFlags,
+                         (LPTSTR)tmp2, (DWORD)MAX_PATH);
+
+    /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in
+     * local time!
+     */
+    return !strncmp(strupr(tmp2), "FAT", 3) ||
+           !strncmp(tmp2, "VFAT", 4) ||
+           !strncmp(tmp2, "HPFS", 4);
+
+} /* end function FSusesLocalTime() */
+#endif /* NT_TZBUG_WORKAROUND */
+
+
+#if (defined(USE_EF_UT_TIME) || \
+     (defined(NT_TZBUG_WORKAROUND) && !defined(NO_W32TIMES_IZFIX)))
+
+#if (defined(__GNUC__) || defined(ULONG_LONG_MAX))
+   typedef long long            LLONG64;
+   typedef unsigned long long   ULLNG64;
+#elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100))
+   typedef __int64              LLONG64;
+   typedef unsigned __int64     ULLNG64;
+#elif (defined(_MSC_VER) && (_MSC_VER >= 1100))
+   typedef __int64              LLONG64;
+   typedef unsigned __int64     ULLNG64;
+#elif (defined(__IBMC__) && (__IBMC__ >= 350))
+   typedef __int64              LLONG64;
+   typedef unsigned __int64     ULLNG64;
+#else
+#  define NO_INT64
+#endif
+
+/* scale factor and offset for conversion time_t -> FILETIME */
+#  define NT_QUANTA_PER_UNIX 10000000L
+#  define FTQUANTA_PER_UT_L  (NT_QUANTA_PER_UNIX & 0xFFFF)
+#  define FTQUANTA_PER_UT_H  (NT_QUANTA_PER_UNIX >> 16)
+#  define UNIX_TIME_ZERO_HI  0x019DB1DEUL
+#  define UNIX_TIME_ZERO_LO  0xD53E8000UL
+/* special FILETIME values for bound-checks */
+#  define UNIX_TIME_UMAX_HI  0x0236485EUL
+#  define UNIX_TIME_UMAX_LO  0xD4A5E980UL
+#  define UNIX_TIME_SMIN_HI  0x0151669EUL
+#  define UNIX_TIME_SMIN_LO  0xD53E8000UL
+#  define UNIX_TIME_SMAX_HI  0x01E9FD1EUL
+#  define UNIX_TIME_SMAX_LO  0xD4A5E980UL
+
+local int NtfsFileTime2utime(const FILETIME *pft, time_t *ut)
+{
+#ifndef NO_INT64
+    ULLNG64 NTtime;
+
+    NTtime = ((ULLNG64)pft->dwLowDateTime +
+              ((ULLNG64)pft->dwHighDateTime << 32));
+
+    /* underflow and overflow handling */
+#ifdef CHECK_UTIME_SIGNED_UNSIGNED
+    if ((time_t)0x80000000L < (time_t)0L)
+    {
+        if (NTtime < ((ULLNG64)UNIX_TIME_SMIN_LO +
+                      ((ULLNG64)UNIX_TIME_SMIN_HI << 32))) {
+            *ut = (time_t)LONG_MIN;
+            return FALSE;
+        }
+        if (NTtime > ((ULLNG64)UNIX_TIME_SMAX_LO +
+                      ((ULLNG64)UNIX_TIME_SMAX_HI << 32))) {
+            *ut = (time_t)LONG_MAX;
+            return FALSE;
+        }
+    }
+    else
+#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
+    {
+        if (NTtime < ((ULLNG64)UNIX_TIME_ZERO_LO +
+                      ((ULLNG64)UNIX_TIME_ZERO_HI << 32))) {
+            *ut = (time_t)0;
+            return FALSE;
+        }
+        if (NTtime > ((ULLNG64)UNIX_TIME_UMAX_LO +
+                      ((ULLNG64)UNIX_TIME_UMAX_HI << 32))) {
+            *ut = (time_t)ULONG_MAX;
+            return FALSE;
+        }
+    }
+
+    NTtime -= ((ULLNG64)UNIX_TIME_ZERO_LO +
+               ((ULLNG64)UNIX_TIME_ZERO_HI << 32));
+    *ut = (time_t)(NTtime / (unsigned long)NT_QUANTA_PER_UNIX);
+    return TRUE;
+#else /* NO_INT64 (64-bit integer arithmetics may not be supported) */
+    /* nonzero if `y' is a leap year, else zero */
+#   define leap(y) (((y)%4 == 0 && (y)%100 != 0) || (y)%400 == 0)
+    /* number of leap years from 1970 to `y' (not including `y' itself) */
+#   define nleap(y) (((y)-1969)/4 - ((y)-1901)/100 + ((y)-1601)/400)
+    /* daycount at the end of month[m-1] */
+    static ZCONST ush ydays[] =
+      { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+
+    time_t days;
+    SYSTEMTIME w32tm;
+
+    /* underflow and overflow handling */
+#ifdef CHECK_UTIME_SIGNED_UNSIGNED
+    if ((time_t)0x80000000L < (time_t)0L)
+    {
+        if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&
+             (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {
+            *ut = (time_t)LONG_MIN;
+            return FALSE;
+        if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&
+             (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {
+            *ut = (time_t)LONG_MAX;
+            return FALSE;
+        }
+    }
+    else
+#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
+    {
+        if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&
+             (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {
+            *ut = (time_t)0;
+            return FALSE;
+        }
+        if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&
+             (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {
+            *ut = (time_t)ULONG_MAX;
+            return FALSE;
+        }
+    }
+
+    FileTimeToSystemTime(pft, &w32tm);
+
+    /* set `days' to the number of days into the year */
+    days = w32tm.wDay - 1 + ydays[w32tm.wMonth-1] +
+           (w32tm.wMonth > 2 && leap (w32tm.wYear));
+
+    /* now set `days' to the number of days since 1 Jan 1970 */
+    days += 365 * (time_t)(w32tm.wYear - 1970) +
+            (time_t)(nleap(w32tm.wYear));
+
+    *ut = (time_t)(86400L * days + 3600L * (time_t)w32tm.wHour +
+                   (time_t)(60 * w32tm.wMinute + w32tm.wSecond));
+    return TRUE;
+#endif /* ?NO_INT64 */
+} /* end function NtfsFileTime2utime() */
+#endif /* USE_EF_UT_TIME || (NT_TZBUG_WORKAROUND && !NO_W32TIMES_IZFIX) */
+
+
+#if (defined(NT_TZBUG_WORKAROUND) && defined(W32_STAT_BANDAID))
+
+local int VFatFileTime2utime(const FILETIME *pft, time_t *ut)
+{
+    FILETIME lft;
+    SYSTEMTIME w32tm;
+    struct tm ltm;
+
+    if (!FileTimeToLocalFileTime(pft, &lft)) {
+        /* if pft cannot be converted to local time, return current time */
+        return time(NULL);
+    }
+    FileTimeToSystemTime(&lft, &w32tm);
+    /* underflow and overflow handling */
+    /* TODO: The range checks are not accurate, the actual limits may
+     *       be off by one daylight-saving-time shift (typically 1 hour),
+     *       depending on the current state of "is_dst".
+     */
+#ifdef CHECK_UTIME_SIGNED_UNSIGNED
+    if ((time_t)0x80000000L < (time_t)0L)
+    {
+        if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&
+             (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {
+            *ut = (time_t)LONG_MIN;
+            return FALSE;
+        if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&
+             (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {
+            *ut = (time_t)LONG_MAX;
+            return FALSE;
+        }
+    }
+    else
+#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
+    {
+        if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&
+             (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {
+            *ut = (time_t)0;
+            return FALSE;
+        }
+        if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&
+             (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {
+            *ut = (time_t)ULONG_MAX;
+            return FALSE;
+        }
+    }
+    ltm.tm_year = w32tm.wYear - 1900;
+    ltm.tm_mon = w32tm.wMonth - 1;
+    ltm.tm_mday = w32tm.wDay;
+    ltm.tm_hour = w32tm.wHour;
+    ltm.tm_min = w32tm.wMinute;
+    ltm.tm_sec = w32tm.wSecond;
+    ltm.tm_isdst = -1;  /* let mktime determine if DST is in effect */
+    *ut = mktime(&ltm);
+
+    /* a cheap error check: mktime returns "(time_t)-1L" on conversion errors.
+     * Normally, we would have to apply a consistency check because "-1"
+     * could also be a valid time. But, it is quite unlikely to read back odd
+     * time numbers from file systems that store time stamps in DOS format.
+     * (The only known exception is creation time on VFAT partitions.)
+     */
+    return (*ut != (time_t)-1L);
+
+} /* end function VFatFileTime2utime() */
+#endif /* NT_TZBUG_WORKAROUND && W32_STAT_BANDAID */
+
+
+#if 0           /* Currently, this is not used at all */
+
+long GetTheFileTime(const char *name, iztimes *z_ut)
+{
+  HANDLE h;
+  FILETIME Modft, Accft, Creft, lft;
+  WORD dh, dl;
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+  char *ansi_name = (char *)alloca(strlen(name) + 1);
+
+  OemToAnsi(name, ansi_name);
+  name = ansi_name;
+#endif
+
+  h = CreateFile(name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+  if ( h != INVALID_HANDLE_VALUE ) {
+    BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);
+    CloseHandle(h);
+#ifdef USE_EF_UT_TIME
+    if (ftOK && (z_ut != NULL)) {
+      NtfsFileTime2utime(&Modft, &(z_ut->mtime));
+      if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
+          NtfsFileTime2utime(&Accft, &(z_ut->atime));
+      else
+          z_ut->atime = z_ut->mtime;
+      if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
+          NtfsFileTime2utime(&Creft, &(z_ut->ctime));
+      else
+          z_ut->ctime = z_ut->mtime;
+    }
+#endif
+    FileTimeToLocalFileTime(&ft, &lft);
+    FileTimeToDosDateTime(&lft, &dh, &dl);
+    return(dh<<16) | dl;
+  }
+  else
+    return 0L;
+}
+
+#endif /* never */
+
+
+void ChangeNameForFAT(char *name)
+{
+  char *src, *dst, *next, *ptr, *dot, *start;
+  static char invalid[] = ":;,=+\"[]<>| \t";
+
+  if ( isalpha((uch)name[0]) && (name[1] == ':') )
+    start = name + 2;
+  else
+    start = name;
+
+  src = dst = start;
+  if ( (*src == '/') || (*src == '\\') )
+    src++, dst++;
+
+  while ( *src )
+  {
+    for ( next = src; *next && (*next != '/') && (*next != '\\'); next++ );
+
+    for ( ptr = src, dot = NULL; ptr < next; ptr++ )
+      if ( *ptr == '.' )
+      {
+        dot = ptr; /* remember last dot */
+        *ptr = '_';
+      }
+
+    if ( dot == NULL )
+      for ( ptr = src; ptr < next; ptr++ )
+        if ( *ptr == '_' )
+          dot = ptr; /* remember last _ as if it were a dot */
+
+    if ( dot && (dot > src) &&
+         ((next - dot <= 4) ||
+          ((next - src > 8) && (dot - src > 3))) )
+    {
+      if ( dot )
+        *dot = '.';
+
+      for ( ptr = src; (ptr < dot) && ((ptr - src) < 8); ptr++ )
+        *dst++ = *ptr;
+
+      for ( ptr = dot; (ptr < next) && ((ptr - dot) < 4); ptr++ )
+        *dst++ = *ptr;
+    }
+    else
+    {
+      if ( dot && (next - src == 1) )
+        *dot = '.';           /* special case: "." as a path component */
+
+      for ( ptr = src; (ptr < next) && ((ptr - src) < 8); ptr++ )
+        *dst++ = *ptr;
+    }
+
+    *dst++ = *next; /* either '/' or 0 */
+
+    if ( *next )
+    {
+      src = next + 1;
+
+      if ( *src == 0 ) /* handle trailing '/' on dirs ! */
+        *dst = 0;
+    }
+    else
+      break;
+  }
+
+  for ( src = start; *src != 0; ++src )
+    if ( (strchr(invalid, *src) != NULL) || (*src == ' ') )
+      *src = '_';
+}
+
+char *GetLongPathEA(const char *name)
+{
+    return(NULL); /* volunteers ? */
+}
+
+int IsFileNameValid(x)
+const char *x;
+{
+    WIN32_FIND_DATA fd;
+    HANDLE h;
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+    char *ansi_name = (char *)alloca(strlen(x) + 1);
+
+    OemToAnsi(x, ansi_name);
+    x = (const char *)ansi_name;
+#endif
+
+    if ((h = FindFirstFile(x, &fd)) == INVALID_HANDLE_VALUE)
+        return FALSE;
+    FindClose(h);
+    return TRUE;
+}
+
+char *getVolumeLabel(drive, vtime, vmode, vutim)
+  int drive;    /* drive name: 'A' .. 'Z' or '\0' for current drive */
+  ulg *vtime;   /* volume label creation time (DOS format) */
+  ulg *vmode;   /* volume label file mode */
+  time_t *vutim;/* volume label creationtime (UNIX format) */
+
+/* If a volume label exists for the given drive, return its name and
+   pretend to set its time and mode. The returned name is static data. */
+{
+  char rootpath[4];
+  static char vol[14];
+  DWORD fnlen, flags;
+
+  *vmode = A_ARCHIVE | A_LABEL;           /* this is what msdos returns */
+  *vtime = dostime(1980, 1, 1, 0, 0, 0);  /* no true date info available */
+  *vutim = dos2unixtime(*vtime);
+  strcpy(rootpath, "x:\\");
+  rootpath[0] = (char)drive;
+  if (GetVolumeInformation(drive ? rootpath : NULL, vol, 13, NULL,
+                           &fnlen, &flags, NULL, 0))
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+    return (AnsiToOem(vol, vol), vol);
+#else
+    return vol;
+#endif
+  else
+    return NULL;
+}
+
+#endif /* !UTIL */
+
+
+
+int ZipIsWinNT(void)    /* returns TRUE if real NT, FALSE if Win95 or Win32s */
+{
+    static DWORD g_PlatformId = 0xFFFFFFFF; /* saved platform indicator */
+
+    if (g_PlatformId == 0xFFFFFFFF) {
+        /* note: GetVersionEx() doesn't exist on WinNT 3.1 */
+        if (GetVersion() < 0x80000000)
+            g_PlatformId = TRUE;
+        else
+            g_PlatformId = FALSE;
+    }
+    return (int)g_PlatformId;
+}
+
+
+#ifndef UTIL
+#ifdef __WATCOMC__
+#  include <io.h>
+#  define _get_osfhandle _os_handle
+/* gaah -- Watcom's docs claim that _get_osfhandle exists, but it doesn't.  */
+#endif
+
+#ifdef HAVE_FSEEKABLE
+/*
+ * return TRUE if file is seekable
+ */
+int fseekable(fp)
+FILE *fp;
+{
+    return GetFileType((HANDLE)_get_osfhandle(fileno(fp))) == FILE_TYPE_DISK;
+}
+#endif /* HAVE_FSEEKABLE */
+#endif /* !UTIL */
+
+
+#if 0 /* seems to be never used; try it out... */
+char *StringLower(char *szArg)
+{
+  char *szPtr;
+/*  unsigned char *szPtr; */
+  for ( szPtr = szArg; *szPtr; szPtr++ )
+    *szPtr = lower[*szPtr];
+  return szArg;
+}
+#endif /* never */
+
+
+
+#ifdef W32_STAT_BANDAID
+
+/* All currently known variants of WIN32 operating systems (Windows 95/98,
+ * WinNT 3.x, 4.0, 5.x) have a nasty bug in the OS kernel concerning
+ * conversions between UTC and local time: In the time conversion functions
+ * of the Win32 API, the timezone offset (including seasonal daylight saving
+ * shift) between UTC and local time evaluation is erratically based on the
+ * current system time. The correct evaluation must determine the offset
+ * value as it {was/is/will be} for the actual time to be converted.
+ *
+ * Newer versions of MS C runtime lib's stat() returns utc time-stamps so
+ * that localtime(timestamp) corresponds to the (potentially false) local
+ * time shown by the OS' system programs (Explorer, command shell dir, etc.)
+ * The RSXNT port follows the same strategy, but fails to recognize the
+ * access-time attribute.
+ *
+ * For the NTFS file system (and other filesystems that store time-stamps
+ * as UTC values), this results in st_mtime (, st_{c|a}time) fields which
+ * are not stable but vary according to the seasonal change of "daylight
+ * saving time in effect / not in effect".
+ *
+ * Other C runtime libs (CygWin, or the crtdll.dll supplied with Win9x/NT
+ * return the unix-time equivalent of the UTC FILETIME values as got back
+ * from the Win32 API call. This time, return values from NTFS are correct
+ * whereas utimes from files on (V)FAT volumes vary according to the DST
+ * switches.
+ *
+ * To achieve timestamp consistency of UTC (UT extra field) values in
+ * Zip archives, the Info-ZIP programs require work-around code for
+ * proper time handling in stat() (and other time handling routines).
+ *
+ * However, nowadays most other programs on Windows systems use the
+ * time conversion strategy of Microsofts C runtime lib "msvcrt.dll".
+ * To improve interoperability in environments where a "consistent" (but
+ * false) "UTC<-->LocalTime" conversion is preferred over "stable" time
+ * stamps, the Info-ZIP specific time conversion handling can be
+ * deactivated by defining the preprocessor flag NO_W32TIMES_IZFIX.
+ */
+/* stat() functions under Windows95 tend to fail for root directories.   *
+ * Watcom and Borland, at least, are affected by this bug.  Watcom made  *
+ * a partial fix for 11.0 but still missed some cases.  This substitute  *
+ * detects the case and fills in reasonable values.  Otherwise we get    *
+ * effects like failure to extract to a root dir because it's not found. */
+
+int zstat_zipwin32(const char *path, struct stat *buf)
+{
+    if (!stat(path, buf))
+    {
+#if (!defined(UTIL) && defined(NT_TZBUG_WORKAROUND))
+        /* stat was successful, now redo the time-stamp fetches */
+#ifndef NO_W32TIMES_IZFIX
+        int fs_uses_loctime = FSusesLocalTime(path);
+#endif
+        HANDLE h;
+        FILETIME Modft, Accft, Creft;
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+        char *ansi_path = (char *)alloca(strlen(path) + 1);
+
+        OemToAnsi(path, ansi_path);
+#       define Ansi_Path  ansi_path
+#else
+#       define Ansi_Path  path
+#endif
+
+        Trace((stdout, "stat(%s) finds modtime %08lx\n", path, buf->st_mtime));
+        h = CreateFile(Ansi_Path, GENERIC_READ,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+                       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+        if (h != INVALID_HANDLE_VALUE) {
+            BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);
+            CloseHandle(h);
+
+            if (ftOK) {
+#ifndef NO_W32TIMES_IZFIX
+                if (!fs_uses_loctime) {
+                    /*  On a filesystem that stores UTC timestamps, we refill
+                     *  the time fields of the struct stat buffer by directly
+                     *  using the UTC values as returned by the Win32
+                     *  GetFileTime() API call.
+                     */
+                    NtfsFileTime2utime(&Modft, &(buf->st_mtime));
+                    if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
+                        NtfsFileTime2utime(&Accft, &(buf->st_atime));
+                    else
+                        buf->st_atime = buf->st_mtime;
+                    if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
+                        NtfsFileTime2utime(&Creft, &(buf->st_ctime));
+                    else
+                        buf->st_ctime = buf->st_mtime;
+                    Tracev((stdout,"NTFS, recalculated modtime %08lx\n",
+                            buf->st_mtime));
+                } else
+#endif /* NO_W32TIMES_IZFIX */
+                {
+                    /*  On VFAT and FAT-like filesystems, the FILETIME values
+                     *  are converted back to the stable local time before
+                     *  converting them to UTC unix time-stamps.
+                     */
+                    VFatFileTime2utime(&Modft, &(buf->st_mtime));
+                    if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
+                        VFatFileTime2utime(&Accft, &(buf->st_atime));
+                    else
+                        buf->st_atime = buf->st_mtime;
+                    if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
+                        VFatFileTime2utime(&Creft, &(buf->st_ctime));
+                    else
+                        buf->st_ctime = buf->st_mtime;
+                    Tracev((stdout, "VFAT, recalculated modtime %08lx\n",
+                            buf->st_mtime));
+                }
+            }
+        }
+#       undef Ansi_Path
+#endif /* !UTIL && NT_TZBUG_WORKAROUND */
+        return 0;
+    }
+#ifdef W32_STATROOT_FIX
+    else
+    {
+        DWORD flags;
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+        char *ansi_path = (char *)alloca(strlen(path) + 1);
+
+        OemToAnsi(path, ansi_path);
+#       define Ansi_Path  ansi_path
+#else
+#       define Ansi_Path  path
+#endif
+
+        flags = GetFileAttributes(Ansi_Path);
+        if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) {
+            Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n",
+                   path));
+            memset(buf, 0, sizeof(struct stat));
+            buf->st_atime = buf->st_ctime = buf->st_mtime =
+              dos2unixtime(DOSTIME_MINIMUM);
+            /* !!!   you MUST NOT add a cast to the type of "st_mode" here;
+             * !!!   different compilers do not agree on the "st_mode" size!
+             * !!!   (And, some compiler may not declare the "mode_t" type
+             * !!!   identifier, so you cannot use it, either.)
+             */
+            buf->st_mode = S_IFDIR | S_IREAD |
+                           ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE);
+            return 0;
+        } /* assumes: stat() won't fail on non-dirs without good reason */
+#       undef Ansi_Path
+    }
+#endif /* W32_STATROOT_FIX */
+    return -1;
+}
+
+#endif /* W32_STAT_BANDAID */
+
+
+
+#ifdef W32_USE_IZ_TIMEZONE
+#include "timezone.h"
+#define SECSPERMIN      60
+#define MINSPERHOUR     60
+#define SECSPERHOUR     (SECSPERMIN * MINSPERHOUR)
+static void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule);
+
+static void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule)
+{
+    if (lpw32tm->wYear != 0) {
+        ptrule->r_type = JULIAN_DAY;
+        ptrule->r_day = ydays[lpw32tm->wMonth - 1] + lpw32tm->wDay;
+    } else {
+        ptrule->r_type = MONTH_NTH_DAY_OF_WEEK;
+        ptrule->r_mon = lpw32tm->wMonth;
+        ptrule->r_day = lpw32tm->wDayOfWeek;
+        ptrule->r_week = lpw32tm->wDay;
+    }
+    ptrule->r_time = (long)lpw32tm->wHour * SECSPERHOUR +
+                     (long)(lpw32tm->wMinute * SECSPERMIN) +
+                     (long)lpw32tm->wSecond;
+}
+
+int GetPlatformLocalTimezone(register struct state * ZCONST sp,
+        void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res,
+                                        ZCONST struct rule * ZCONST start,
+                                        ZCONST struct rule * ZCONST end))
+{
+    TIME_ZONE_INFORMATION tzinfo;
+    DWORD res;
+
+    /* read current timezone settings from registry if TZ envvar missing */
+    res = GetTimeZoneInformation(&tzinfo);
+    if (res != TIME_ZONE_ID_INVALID)
+    {
+        struct rule startrule, stoprule;
+
+        conv_to_rule(&(tzinfo.StandardDate), &stoprule);
+        conv_to_rule(&(tzinfo.DaylightDate), &startrule);
+        sp->timecnt = 0;
+        sp->ttis[0].tt_abbrind = 0;
+        if ((sp->charcnt =
+             WideCharToMultiByte(CP_ACP, 0, tzinfo.StandardName, -1,
+                                 sp->chars, sizeof(sp->chars), NULL, NULL))
+            == 0)
+            sp->chars[sp->charcnt++] = '\0';
+        sp->ttis[1].tt_abbrind = sp->charcnt;
+        sp->charcnt +=
+            WideCharToMultiByte(CP_ACP, 0, tzinfo.DaylightName, -1,
+                                sp->chars + sp->charcnt,
+                                sizeof(sp->chars) - sp->charcnt, NULL, NULL);
+        if ((sp->charcnt - sp->ttis[1].tt_abbrind) == 0)
+            sp->chars[sp->charcnt++] = '\0';
+        sp->ttis[0].tt_gmtoff = - (tzinfo.Bias + tzinfo.StandardBias)
+                                * MINSPERHOUR;
+        sp->ttis[1].tt_gmtoff = - (tzinfo.Bias + tzinfo.DaylightBias)
+                                * MINSPERHOUR;
+        sp->ttis[0].tt_isdst = 0;
+        sp->ttis[1].tt_isdst = 1;
+        sp->typecnt = (startrule.r_mon == 0 && stoprule.r_mon == 0) ? 1 : 2;
+
+        if (sp->typecnt > 1)
+            (*fill_tzstate_from_rules)(sp, &startrule, &stoprule);
+        return TRUE;
+    }
+    return FALSE;
+}
+#endif /* W32_USE_IZ_TIMEZONE */
+
+
+
+#ifndef WINDLL
+/* This replacement getch() function was originally created for Watcom C
+ * and then additionally used with CYGWIN. Since UnZip 5.4, all other Win32
+ * ports apply this replacement rather that their supplied getch() (or
+ * alike) function.  There are problems with unabsorbed LF characters left
+ * over in the keyboard buffer under Win95 (and 98) when ENTER was pressed.
+ * (Under Win95, ENTER returns two(!!) characters: CR-LF.)  This problem
+ * does not appear when run on a WinNT console prompt!
+ */
+
+/* Watcom 10.6's getch() does not handle Alt+<digit><digit><digit>. */
+/* Note that if PASSWD_FROM_STDIN is defined, the file containing   */
+/* the password must have a carriage return after the word, not a   */
+/* Unix-style newline (linefeed only).  This discards linefeeds.    */
+
+int getch_win32(void)
+{
+  HANDLE stin;
+  DWORD rc;
+  unsigned char buf[2];
+  int ret = -1;
+  DWORD odemode = ~(DWORD)0;
+
+#  ifdef PASSWD_FROM_STDIN
+  stin = GetStdHandle(STD_INPUT_HANDLE);
+#  else
+  stin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
+                    FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+  if (stin == INVALID_HANDLE_VALUE)
+    return -1;
+#  endif
+  if (GetConsoleMode(stin, &odemode))
+    SetConsoleMode(stin, ENABLE_PROCESSED_INPUT);  /* raw except ^C noticed */
+  if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)
+    ret = buf[0];
+  /* when the user hits return we get CR LF.  We discard the LF, not the CR,
+   * because when we call this for the first time after a previous input
+   * such as the one for "replace foo? [y]es, ..." the LF may still be in
+   * the input stream before whatever the user types at our prompt. */
+  if (ret == '\n')
+    if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)
+      ret = buf[0];
+  if (odemode != ~(DWORD)0)
+    SetConsoleMode(stin, odemode);
+#  ifndef PASSWD_FROM_STDIN
+  CloseHandle(stin);
+#  endif
+  return ret;
+}
+
+
+
+/******************************/
+/*  Function version_local()  */
+/******************************/
+
+void version_local()
+{
+    static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s.\n\n";
+#if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DJGPP__))
+    char buf[80];
+#if (defined(_MSC_VER) && (_MSC_VER > 900))
+    char buf2[80];
+#endif
+#endif
+
+/* Define the compiler name and version strings */
+#if defined(_MSC_VER)  /* MSC == MSVC++, including the SDK compiler */
+    sprintf(buf, "Microsoft C %d.%02d ", _MSC_VER/100, _MSC_VER%100);
+#  define COMPILER_NAME1        buf
+#  if (_MSC_VER == 800)
+#    define COMPILER_NAME2      "(Visual C++ v1.1)"
+#  elif (_MSC_VER == 850)
+#    define COMPILER_NAME2      "(Windows NT v3.5 SDK)"
+#  elif (_MSC_VER == 900)
+#    define COMPILER_NAME2      "(Visual C++ v2.x)"
+#  elif (_MSC_VER > 900)
+    sprintf(buf2, "(Visual C++ v%d.%d)", _MSC_VER/100 - 6, _MSC_VER%100/10);
+#    define COMPILER_NAME2      buf2
+#  else
+#    define COMPILER_NAME2      "(bad version)"
+#  endif
+#elif defined(__WATCOMC__)
+#  if (__WATCOMC__ % 10 > 0)
+/* We do this silly test because __WATCOMC__ gives two digits for the  */
+/* minor version, but Watcom packaging prefers to show only one digit. */
+    sprintf(buf, "Watcom C/C++ %d.%02d", __WATCOMC__ / 100,
+            __WATCOMC__ % 100);
+#  else
+    sprintf(buf, "Watcom C/C++ %d.%d", __WATCOMC__ / 100,
+            (__WATCOMC__ % 100) / 10);
+#  endif /* __WATCOMC__ % 10 > 0 */
+#  define COMPILER_NAME1        buf
+#  define COMPILER_NAME2        ""
+#elif defined(__TURBOC__)
+#  ifdef __BORLANDC__
+#    define COMPILER_NAME1      "Borland C++"
+#    if (__BORLANDC__ == 0x0452)   /* __BCPLUSPLUS__ = 0x0320 */
+#      define COMPILER_NAME2    " 4.0 or 4.02"
+#    elif (__BORLANDC__ == 0x0460)   /* __BCPLUSPLUS__ = 0x0340 */
+#      define COMPILER_NAME2    " 4.5"
+#    elif (__BORLANDC__ == 0x0500)   /* __TURBOC__ = 0x0500 */
+#      define COMPILER_NAME2    " 5.0"
+#    elif (__BORLANDC__ == 0x0520)   /* __TURBOC__ = 0x0520 */
+#      define COMPILER_NAME2    " 5.2 (C++ Builder 1.0)"
+#    elif (__BORLANDC__ == 0x0530)   /* __BCPLUSPLUS__ = 0x0530 */
+#      define COMPILER_NAME2    " 5.3 (C++ Builder 3.0)"
+#    elif (__BORLANDC__ == 0x0540)   /* __BCPLUSPLUS__ = 0x0540 */
+#      define COMPILER_NAME2    " 5.4 (C++ Builder 4.0)"
+#    elif (__BORLANDC__ == 0x0550)   /* __BCPLUSPLUS__ = 0x0550 */
+#      define COMPILER_NAME2    " 5.5 (C++ Builder 5.0)"
+#    elif (__BORLANDC__ == 0x0551)   /* __BCPLUSPLUS__ = 0x0551 */
+#      define COMPILER_NAME2    " 5.5.1 (C++ Builder 5.0.1)"
+#    elif (__BORLANDC__ == 0x0560)   /* __BCPLUSPLUS__ = 0x0560 */
+#      define COMPILER_NAME2    " 5.6 (C++ Builder 6)"
+#    else
+#      define COMPILER_NAME2    " later than 5.6"
+#    endif
+#  else /* !__BORLANDC__ */
+#    define COMPILER_NAME1      "Turbo C"
+#    if (__TURBOC__ >= 0x0400)     /* Kevin:  3.0 -> 0x0401 */
+#      define COMPILER_NAME2    "++ 3.0 or later"
+#    elif (__TURBOC__ == 0x0295)     /* [661] vfy'd by Kevin */
+#      define COMPILER_NAME2    "++ 1.0"
+#    endif
+#  endif /* __BORLANDC__ */
+#elif defined(__GNUC__)
+#  ifdef __RSXNT__
+#    if (defined(__DJGPP__) && !defined(__EMX__))
+    sprintf(buf, "rsxnt(djgpp v%d.%02d) / gcc ",
+            __DJGPP__, __DJGPP_MINOR__);
+#      define COMPILER_NAME1    buf
+#    elif defined(__DJGPP__)
+    sprintf(buf, "rsxnt(emx+djgpp v%d.%02d) / gcc ",
+            __DJGPP__, __DJGPP_MINOR__);
+#      define COMPILER_NAME1    buf
+#    elif (defined(__GO32__) && !defined(__EMX__))
+#      define COMPILER_NAME1    "rsxnt(djgpp v1.x) / gcc "
+#    elif defined(__GO32__)
+#      define COMPILER_NAME1    "rsxnt(emx + djgpp v1.x) / gcc "
+#    elif defined(__EMX__)
+#      define COMPILER_NAME1    "rsxnt(emx)+gcc "
+#    else
+#      define COMPILER_NAME1    "rsxnt(unknown) / gcc "
+#    endif
+#  elif defined(__CYGWIN__)
+#      define COMPILER_NAME1    "Cygnus win32 / gcc "
+#  elif defined(__MINGW32__)
+#      define COMPILER_NAME1    "mingw32 / gcc "
+#  else
+#      define COMPILER_NAME1    "gcc "
+#  endif
+#  define COMPILER_NAME2        __VERSION__
+#elif defined(__LCC__)
+#  define COMPILER_NAME1        "LCC-Win32"
+#  define COMPILER_NAME2        ""
+#else
+#  define COMPILER_NAME1        "unknown compiler (SDK?)"
+#  define COMPILER_NAME2        ""
+#endif
+
+/* Define the compile date string */
+#ifdef __DATE__
+#  define COMPILE_DATE " on " __DATE__
+#else
+#  define COMPILE_DATE ""
+#endif
+
+    printf(CompiledWith, COMPILER_NAME1, COMPILER_NAME2,
+           "\nWindows 9x / Windows NT/2K/XP/2K3", " (32-bit)", COMPILE_DATE);
+
+    return;
+
+} /* end function version_local() */
+#endif /* !WINDLL */
diff --git a/win32/win32zip.c b/win32/win32zip.c
new file mode 100644 (file)
index 0000000..b9d5e2d
--- /dev/null
@@ -0,0 +1,782 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#ifndef UTIL    /* this file contains nothing used by UTIL */
+
+#include "../zip.h"
+
+#include <ctype.h>
+#if !defined(__EMX__) && !defined(__CYGWIN__)
+#include <direct.h>     /* for rmdir() */
+#endif
+#include <time.h>
+
+#ifndef __BORLANDC__
+#include <sys/utime.h>
+#else
+#include <utime.h>
+#endif
+#include <windows.h> /* for findfirst/findnext stuff */
+#ifdef __RSXNT__
+#  include "../win32/rsxntwin.h"
+#endif
+
+#include <io.h>
+
+#define PAD           0
+#define PATH_END      '/'
+#define HIDD_SYS_BITS (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)
+
+
+typedef struct zdirent {
+  ush    d_date, d_time;
+  ulg    d_size;
+  char   d_attr;
+  char   d_name[MAX_PATH];
+  int    d_first;
+  HANDLE d_hFindFile;
+} zDIR;
+
+#include "../win32/win32zip.h"
+#include "../win32/nt.h"
+
+/* Local functions */
+local zDIR           *Opendir      OF((ZCONST char *n));
+local struct zdirent *Readdir      OF((zDIR *d));
+local void            Closedir     OF((zDIR *d));
+
+local char           *readd        OF((zDIR *));
+local int             wild_recurse OF((char *, char *));
+#ifdef NTSD_EAS
+   local void GetSD OF((char *path, char **bufptr, size_t *size,
+                        char **cbufptr, size_t *csize));
+#endif
+#ifdef USE_EF_UT_TIME
+   local int GetExtraTime OF((struct zlist far *z, iztimes *z_utim));
+#endif
+
+/* Module level variables */
+extern char *label /* = NULL */ ;       /* defined in fileio.c */
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+/* Module level constants */
+local ZCONST char wild_match_all[] = "*.*";
+
+local zDIR *Opendir(n)
+ZCONST char *n;          /* directory to open */
+/* Start searching for files in the MSDOS directory n */
+{
+  zDIR *d;              /* malloc'd return value */
+  char *p;              /* malloc'd temporary string */
+  char *q;
+  WIN32_FIND_DATA fd;
+
+  if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL ||
+      (p = malloc(strlen(n) + (2 + sizeof(wild_match_all)))) == NULL) {
+    if (d != NULL) free((zvoid *)d);
+    return NULL;
+  }
+  strcpy(p, n);
+  q = p + strlen(p);
+  if ((q - p) > 0 && MBSRCHR(p, ':') == (q - 1))
+      *q++ = '.';
+  if ((q - p) > 0 && MBSRCHR(p, '/') != (q - 1))
+    *q++ = '/';
+  strcpy(q, wild_match_all);
+
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+  OemToAnsi(p, p);
+#endif
+  d->d_hFindFile = FindFirstFile(p, &fd);
+  free((zvoid *)p);
+
+  if (d->d_hFindFile == INVALID_HANDLE_VALUE)
+  {
+    free((zvoid *)d);
+    return NULL;
+  }
+
+  strcpy(d->d_name, fd.cFileName);
+  d->d_attr = (unsigned char) fd.dwFileAttributes;
+  d->d_first = 1;
+  return d;
+}
+
+local struct zdirent *Readdir(d)
+zDIR *d;                /* directory stream to read from */
+/* Return pointer to first or next directory entry, or NULL if end. */
+{
+  if (d->d_first)
+    d->d_first = 0;
+  else
+  {
+    WIN32_FIND_DATA fd;
+
+    if (!FindNextFile(d->d_hFindFile, &fd))
+        return NULL;
+    strcpy(d->d_name, fd.cFileName);
+    d->d_attr = (unsigned char) fd.dwFileAttributes;
+  }
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+  AnsiToOem(d->d_name, d->d_name);
+#endif
+  return (struct zdirent *)d;
+}
+
+local void Closedir(d)
+zDIR *d;                /* directory stream to close */
+{
+  FindClose(d->d_hFindFile);
+  free((zvoid *)d);
+}
+
+
+local char *readd(d)
+zDIR *d;                /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+   no more entries or an error occurs. */
+{
+  struct zdirent *e;
+
+  do
+    e = Readdir(d);
+  while (!hidden_files && e && e->d_attr & HIDD_SYS_BITS);
+  return e == NULL ? (char *) NULL : e->d_name;
+}
+
+
+#define ONENAMELEN 255
+
+/* whole is a pathname with wildcards, wildtail points somewhere in the  */
+/* middle of it.  All wildcards to be expanded must come AFTER wildtail. */
+
+local int wild_recurse(whole, wildtail)
+char *whole;
+char *wildtail;
+{
+    zDIR *dir;
+    char *subwild, *name, *newwhole = NULL, *glue = NULL, plug = 0, plug2;
+    extent newlen;
+    int amatch = 0, e = ZE_MISS;
+
+    if (!isshexp(wildtail)) {
+        if (GetFileAttributes(whole) != 0xFFFFFFFF) {    /* file exists? */
+#ifdef __RSXNT__  /* RSXNT/EMX C rtl uses OEM charset */
+            AnsiToOem(whole, whole);
+#endif
+            return procname(whole, 0);
+        }
+        else
+            return ZE_MISS;                     /* woops, no wildcards! */
+    }
+
+    /* back up thru path components till existing dir found */
+    do {
+        name = wildtail + strlen(wildtail) - 1;
+        for (;;)
+            if (name-- <= wildtail || *name == PATH_END) {
+                subwild = name + 1;
+                plug2 = *subwild;
+                *subwild = 0;
+                break;
+            }
+        if (glue)
+            *glue = plug;
+        glue = subwild;
+        plug = plug2;
+        dir = Opendir(whole);
+    } while (!dir && subwild > wildtail);
+    wildtail = subwild;                 /* skip past non-wild components */
+
+    if ((subwild = MBSCHR(wildtail + 1, PATH_END)) != NULL) {
+        /* this "+ 1" dodges the   ^^^ hole left by *glue == 0 */
+        *(subwild++) = 0;               /* wildtail = one component pattern */
+        newlen = strlen(whole) + strlen(subwild) + (ONENAMELEN + 2);
+    } else
+        newlen = strlen(whole) + (ONENAMELEN + 1);
+    if (!dir || ((newwhole = malloc(newlen)) == NULL)) {
+        if (glue)
+            *glue = plug;
+        e = dir ? ZE_MEM : ZE_MISS;
+        goto ohforgetit;
+    }
+    strcpy(newwhole, whole);
+    newlen = strlen(newwhole);
+    if (glue)
+        *glue = plug;                           /* repair damage to whole */
+    if (!isshexp(wildtail)) {
+        e = ZE_MISS;                            /* non-wild name not found */
+        goto ohforgetit;
+    }
+
+    while ((name = readd(dir)) != NULL) {
+        if (strcmp(name, ".") && strcmp(name, "..") &&
+            MATCH(wildtail, name, 0)) {
+            strcpy(newwhole + newlen, name);
+            if (subwild) {
+                name = newwhole + strlen(newwhole);
+                *(name++) = PATH_END;
+                strcpy(name, subwild);
+                e = wild_recurse(newwhole, name);
+            } else
+                e = procname(newwhole, 0);
+            newwhole[newlen] = 0;
+            if (e == ZE_OK)
+                amatch = 1;
+            else if (e != ZE_MISS)
+                break;
+        }
+    }
+
+  ohforgetit:
+    if (dir) Closedir(dir);
+    if (subwild) *--subwild = PATH_END;
+    if (newwhole) free(newwhole);
+    if (e == ZE_MISS && amatch)
+        e = ZE_OK;
+    return e;
+}
+
+int wild(w)
+char *w;                /* path/pattern to match */
+/* If not in exclude mode, expand the pattern based on the contents of the
+   file system.  Return an error code in the ZE_ class. */
+{
+    char *p;              /* path */
+    char *q;              /* diskless path */
+    int e;                /* result */
+
+    if (volume_label == 1) {
+      volume_label = 2;
+      label = getVolumeLabel((w != NULL && isascii((uch)w[0]) && w[1] == ':')
+                             ? to_up(w[0]) : '\0',
+                             &label_time, &label_mode, &label_utim);
+      if (label != NULL)
+        (void)newname(label, 0, 0);
+      if (w == NULL || (isascii((uch)w[0]) && w[1] == ':' && w[2] == '\0'))
+        return ZE_OK;
+      /* "zip -$ foo a:" can be used to force drive name */
+    }
+    /* special handling of stdin request */
+    if (strcmp(w, "-") == 0)   /* if compressing stdin */
+        return newname(w, 0, 0);
+
+    /* Allocate and copy pattern, leaving room to add "." if needed */
+    if ((p = malloc(strlen(w) + 2)) == NULL)
+        return ZE_MEM;
+    strcpy(p, w);
+
+    /* Normalize path delimiter as '/' */
+    for (q = p; *q; INCSTR(q))            /* use / consistently */
+        if (*q == '\\')
+            *q = '/';
+
+    /* Separate the disk part of the path */
+    if ((q = MBSCHR(p, ':')) != NULL) {
+        if (MBSCHR(++q, ':'))     /* sanity check for safety of wild_recurse */
+            return ZE_MISS;
+    } else
+        q = p;
+
+    /* Normalize bare disk names */
+    if (q > p && !*q)
+        strcpy(q, ".");
+
+    /* Here we go */
+    e = wild_recurse(p, q);
+    free((zvoid *)p);
+    return e;
+}
+
+int procname(n, caseflag)
+char *n;                /* name to process */
+int caseflag;           /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude).  Return
+   an error code in the ZE_ class. */
+{
+  char *a;              /* path and name for recursion */
+  zDIR *d;              /* directory stream from opendir() */
+  char *e;              /* pointer to name from readd() */
+  int m;                /* matched flag */
+  char *p;              /* path for recursion */
+  struct stat s;        /* result of stat() */
+  struct zlist far *z;  /* steps through zfiles list */
+
+  if (strcmp(n, "-") == 0)   /* if compressing stdin */
+    return newname(n, 0, caseflag);
+  else if (LSSTAT(n, &s)
+#ifdef __TURBOC__
+           /* For this compiler, stat() succeeds on wild card names! */
+           /* Unfortunately, this causes failure on names containing */
+           /* square bracket characters, which are legal in win32.   */
+           || isshexp(n)
+#endif
+          )
+  {
+    /* Not a file or directory--search for shell expression in zip file */
+    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */
+    m = 1;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (MATCH(p, z->iname, caseflag))
+      {
+        z->mark = pcount ? filter(z->zname, caseflag) : 1;
+        if (verbose)
+            fprintf(mesg, "zip diagnostic: %scluding %s\n",
+               z->mark ? "in" : "ex", z->name);
+        m = 0;
+      }
+    }
+    free((zvoid *)p);
+    return m ? ZE_MISS : ZE_OK;
+  }
+
+  /* Live name--use if file, recurse if directory */
+  for (p = n; *p; INCSTR(p))    /* use / consistently */
+    if (*p == '\\')
+      *p = '/';
+  if ((s.st_mode & S_IFDIR) == 0)
+  {
+    /* add or remove name of file */
+    if ((m = newname(n, 0, caseflag)) != ZE_OK)
+      return m;
+  } else {
+    /* Add trailing / to the directory name */
+    if ((p = malloc(strlen(n)+2)) == NULL)
+      return ZE_MEM;
+    if (strcmp(n, ".") == 0 || strcmp(n, "/.") == 0) {
+      *p = '\0';  /* avoid "./" prefix and do not create zip entry */
+    } else {
+      strcpy(p, n);
+      a = p + strlen(p);
+      if (lastchar(p) != '/')
+        strcpy(a, "/");
+      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+        free((zvoid *)p);
+        return m;
+      }
+    }
+    /* recurse into directory */
+    if (recurse && (d = Opendir(n)) != NULL)
+    {
+      while ((e = readd(d)) != NULL) {
+        if (strcmp(e, ".") && strcmp(e, ".."))
+        {
+          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+          {
+            Closedir(d);
+            free((zvoid *)p);
+            return ZE_MEM;
+          }
+          strcat(strcpy(a, p), e);
+          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */
+          {
+            if (m == ZE_MISS)
+              zipwarn("name not matched: ", a);
+            else
+              ziperr(m, a);
+          }
+          free((zvoid *)a);
+        }
+      }
+      Closedir(d);
+    }
+    free((zvoid *)p);
+  } /* (s.st_mode & S_IFDIR) == 0) */
+  return ZE_OK;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x;                /* external file name */
+int isdir;              /* input: x is a directory */
+int *pdosflag;          /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *n;              /* internal file name (malloc'ed) */
+  char *t;              /* shortened name */
+  int dosflag;
+
+
+  dosflag = dosify || IsFileSystemOldFAT(x);
+  if (!dosify && use_longname_ea && (t = GetLongPathEA(x)) != NULL)
+  {
+    x = t;
+    dosflag = 0;
+  }
+
+  /* Find starting point in name before doing malloc */
+  /* Strip drive specification */
+  t = *x && isascii((uch)*x) && *(x + 1) == ':' ? x + 2 : x;
+  /* Strip "//host/share/" part of a UNC name */
+  if ((!strncmp(x,"//",2) || !strncmp(x,"\\\\",2)) &&
+      (x[2] != '\0' && x[2] != '/' && x[2] != '\\')) {
+    n = x + 2;
+    while (*n != '\0' && *n != '/' && *n != '\\')
+      INCSTR(n);        /* strip host name */
+    if (*n != '\0') {
+      INCSTR(n);
+      while (*n != '\0' && *n != '/' && *n != '\\')
+        INCSTR(n);      /* strip `share' name */
+    }
+    if (*n != '\0')
+      t = n + CLEN(n);
+  }
+  /* Strip leading "/" to convert an absolute path into a relative path */
+  while (*t == '/' || *t == '\\')
+    t++;
+  /* Strip leading "./" as well as drive letter */
+  while (*t == '.' && (t[1] == '/' || t[1] == '\\'))
+    t += 2;
+
+  /* Make changes, if any, to the copied name (leave original intact) */
+  for (n = t; *n; INCSTR(n))
+    if (*n == '\\')
+      *n = '/';
+
+  if (!pathput)
+    t = last(t, PATH_END);
+
+  /* Malloc space for internal name and copy it */
+  if ((n = malloc(strlen(t) + 1)) == NULL)
+    return NULL;
+  strcpy(n, t);
+
+  if (dosify)
+    msname(n);
+
+  /* Returned malloc'ed name */
+  if (pdosflag)
+    *pdosflag = dosflag;
+#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
+  OemToAnsi(n, n);
+#endif
+  return n;
+}
+
+
+char *in2ex(n)
+char *n;                /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+   string or NULL if not enough memory. */
+{
+  char *x;              /* external file name */
+
+  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+    return NULL;
+  strcpy(x, n);
+#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */
+  AnsiToOem(x, x);
+#endif
+  return x;
+}
+
+
+void stamp(f, d)
+char *f;                /* name of file to change */
+ulg d;                  /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+#if defined(__TURBOC__) && !defined(__BORLANDC__)
+  int h;                /* file handle */
+
+  if ((h = open(f, 0)) != -1)
+  {
+    setftime(h, (struct ftime *)&d);
+    close(h);
+  }
+#else /* !__TURBOC__ */
+
+  struct utimbuf u;     /* argument for utime() */
+
+  /* Convert DOS time to time_t format in u.actime and u.modtime */
+  u.actime = u.modtime = dos2unixtime(d);
+
+  /* Set updated and accessed times of f */
+  utime(f, &u);
+#endif /* ?__TURBOC__ */
+}
+
+
+ulg filetime(f, a, n, t)
+char *f;                /* name of file to get info on */
+ulg *a;                 /* return value: file attributes */
+long *n;                /* return value: file size */
+iztimes *t;             /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0.  Else, return the file's last
+   modified date and time as an MSDOS date and time.  The date and
+   time is returned in a long with the date most significant to allow
+   unsigned integer comparison of absolute times.  Also, if a is not
+   a NULL pointer, store the file attributes there, with the high two
+   bytes being the Unix attributes, and the low byte being a mapping
+   of that to DOS attributes.  If n is not NULL, store the file size
+   there.  If t is not NULL, the file's access, modification and creation
+   times are stored there as UNIX time_t values.
+   If f is "-", use standard input as the file. If f is a device, return
+   a file size of -1 */
+{
+  struct stat s;        /* results of stat() */
+  char *name;
+  unsigned int len = strlen(f);
+  int isstdin = !strcmp(f, "-");
+
+  if (f == label) {
+    if (a != NULL)
+      *a = label_mode;
+    if (n != NULL)
+      *n = -2L; /* convention for a label name */
+    if (t != NULL)
+      t->atime = t->mtime = t->ctime = label_utim;
+    return label_time;
+  }
+
+  if ((name = malloc(len + 1)) == NULL) {
+    ZIPERR(ZE_MEM, "filetime");
+  }
+  strcpy(name, f);
+  if (MBSRCHR(name, '/') == (name + len - 1))
+    name[len - 1] = '\0';
+  /* not all systems allow stat'ing a file with / appended */
+
+  if (isstdin) {
+    if (fstat(fileno(stdin), &s) != 0) {
+      free(name);
+      error("fstat(stdin)");
+    }
+    time((time_t *)&s.st_mtime);       /* some fstat()s return time zero */
+  } else if (LSSTAT(name, &s) != 0) {
+             /* Accept about any file kind including directories
+              * (stored with trailing / with -r option)
+              */
+    free(name);
+    return 0;
+  }
+
+  if (a != NULL) {
+    *a = ((ulg)s.st_mode << 16) | (isstdin ? 0L : (ulg)GetFileMode(name));
+  }
+  if (n != NULL)
+    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+  if (t != NULL) {
+    t->atime = s.st_atime;
+    t->mtime = s.st_mtime;
+    t->ctime = s.st_ctime;
+  }
+
+  free(name);
+
+  return unix2dostime((time_t *)&s.st_mtime);
+}
+
+
+#ifdef NTSD_EAS
+
+local void GetSD(char *path, char **bufptr, size_t *size,
+                        char **cbufptr, size_t *csize)
+{
+  unsigned char stackbuffer[NTSD_BUFFERSIZE];
+  unsigned long bytes = NTSD_BUFFERSIZE;
+  unsigned char *buffer = stackbuffer;
+  unsigned char *DynBuffer = NULL;
+  long cbytes;
+  PEF_NTSD_L_HEADER pLocalHeader;
+  PEF_NTSD_C_HEADER pCentralHeader;
+  VOLUMECAPS VolumeCaps;
+
+  /* check target volume capabilities */
+  if (!ZipGetVolumeCaps(path, path, &VolumeCaps) ||
+     !(VolumeCaps.dwFileSystemFlags & FS_PERSISTENT_ACLS)) {
+    return;
+  }
+
+  VolumeCaps.bUsePrivileges = use_privileges;
+  VolumeCaps.dwFileAttributes = 0;
+  /* should set to file attributes, if possible */
+
+  if (!SecurityGet(path, &VolumeCaps, buffer, (LPDWORD)&bytes)) {
+
+    /* try to malloc the buffer if appropriate */
+    if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+        DynBuffer = malloc(bytes);
+        if(DynBuffer == NULL) return;
+
+        buffer = DynBuffer; /* switch to the new buffer and try again */
+
+        if(!SecurityGet(path, &VolumeCaps, buffer, (LPDWORD)&bytes)) {
+            free(DynBuffer);
+            return;
+        }
+
+    } else {
+        return; /* bail */
+    }
+  }
+
+  /* # bytes to compress: compress type, CRC, data bytes */
+  cbytes = (2 + 4 + EB_DEFLAT_EXTRA) + bytes;
+
+
+  /* our two possible failure points.  don't allow trashing of any data
+     if either fails - notice that *size and *csize don't get updated.
+     *bufptr leaks if malloc() was used and *cbufptr alloc fails - this
+     isn't relevant because it's probably indicative of a bigger problem. */
+
+  if(*size)
+    *bufptr = realloc(*bufptr, *size + EF_NTSD_L_LEN + cbytes);
+  else
+    *bufptr = malloc(EF_NTSD_L_LEN + cbytes);
+
+  if(*csize)
+    *cbufptr = realloc(*cbufptr, *csize + EF_NTSD_C_LEN);
+  else
+    *cbufptr = malloc(EF_NTSD_C_LEN);
+
+  if(*bufptr == NULL || *cbufptr == NULL) {
+    if(DynBuffer) free(DynBuffer);
+    return;
+  }
+
+  /* local header */
+
+  pLocalHeader = (PEF_NTSD_L_HEADER) (*bufptr + *size);
+
+  cbytes = memcompress(((char *)pLocalHeader + EF_NTSD_L_LEN), cbytes,
+                       (char *)buffer, bytes);
+
+  *size += EF_NTSD_L_LEN + cbytes;
+
+  pLocalHeader->nID = EF_NTSD;
+  pLocalHeader->nSize = (USHORT)(EF_NTSD_L_LEN - EB_HEADSIZE
+                                 + cbytes);
+  pLocalHeader->lSize = bytes; /* uncompressed size */
+  pLocalHeader->Version = 0;
+
+  /* central header */
+
+  pCentralHeader = (PEF_NTSD_C_HEADER) (*cbufptr + *csize);
+  *csize += EF_NTSD_C_LEN;
+
+  pCentralHeader->nID = EF_NTSD;
+  pCentralHeader->nSize = EF_NTSD_C_LEN - EB_HEADSIZE;  /* sbz */
+  pCentralHeader->lSize = bytes;
+
+  if (noisy)
+    printf(" (%ld bytes security)", bytes);
+
+  if(DynBuffer) free(DynBuffer);
+}
+#endif /* NTSD_EAS */
+
+
+#ifdef USE_EF_UT_TIME
+
+#define EB_L_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(3))
+#define EB_C_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(1))
+
+local int GetExtraTime(struct zlist far *z, iztimes *z_utim)
+{
+  char *eb_l_ptr;
+  char *eb_c_ptr;
+  ulg ultime;
+  /* brain-dead IBM compiler defines time_t as "double", so we have to convert
+   * it into unsigned long integer number...
+   */
+
+#ifdef IZ_CHECK_TZ
+  if (!zp_tz_is_valid) return ZE_OK;    /* skip silently if no valid TZ info */
+#endif
+
+  if(z->ext)
+    eb_l_ptr = realloc(z->extra, (z->ext + EB_L_UT_SIZE));
+  else
+    eb_l_ptr = malloc(EB_L_UT_SIZE);
+
+  if (eb_l_ptr == NULL)
+    return ZE_MEM;
+
+  if(z->cext)
+    eb_c_ptr = realloc(z->cextra, (z->cext + EB_C_UT_SIZE));
+  else
+    eb_c_ptr = malloc(EB_C_UT_SIZE);
+
+  if (eb_c_ptr == NULL)
+    return ZE_MEM;
+
+  z->extra = eb_l_ptr;
+  eb_l_ptr += z->ext;
+  z->ext += EB_L_UT_SIZE;
+
+  eb_l_ptr[0]  = 'U';
+  eb_l_ptr[1]  = 'T';
+  eb_l_ptr[2]  = EB_UT_LEN(3);          /* length of data part of e.f. */
+  eb_l_ptr[3]  = 0;
+  eb_l_ptr[4]  = EB_UT_FL_MTIME | EB_UT_FL_ATIME | EB_UT_FL_CTIME;
+  ultime = (ulg)z_utim->mtime;
+  eb_l_ptr[5]  = (char)(ultime);
+  eb_l_ptr[6]  = (char)(ultime >> 8);
+  eb_l_ptr[7]  = (char)(ultime >> 16);
+  eb_l_ptr[8]  = (char)(ultime >> 24);
+  ultime = (ulg)z_utim->atime;
+  eb_l_ptr[9]  = (char)(ultime);
+  eb_l_ptr[10] = (char)(ultime >> 8);
+  eb_l_ptr[11] = (char)(ultime >> 16);
+  eb_l_ptr[12] = (char)(ultime >> 24);
+  ultime = (ulg)z_utim->ctime;
+  eb_l_ptr[13] = (char)(ultime);
+  eb_l_ptr[14] = (char)(ultime >> 8);
+  eb_l_ptr[15] = (char)(ultime >> 16);
+  eb_l_ptr[16] = (char)(ultime >> 24);
+
+  z->cextra = eb_c_ptr;
+  eb_c_ptr += z->cext;
+  z->cext += EB_C_UT_SIZE;
+
+  memcpy(eb_c_ptr, eb_l_ptr, EB_C_UT_SIZE);
+  eb_c_ptr[EB_LEN] = EB_UT_LEN(1);
+
+  return ZE_OK;
+}
+
+#endif /* USE_EF_UT_TIME */
+
+
+
+int set_extra_field(z, z_utim)
+  struct zlist far *z;
+  iztimes *z_utim;
+  /* create extra field and change z->att if desired */
+{
+
+#ifdef NTSD_EAS
+  if(ZipIsWinNT()) {
+    /* store SECURITY_DECRIPTOR data in local header,
+       and size only in central headers */
+    GetSD(z->name, &z->extra, &z->ext, &z->cextra, &z->cext);
+  }
+#endif /* NTSD_EAS */
+
+#ifdef USE_EF_UT_TIME
+  /* store extended time stamps in both headers */
+  return GetExtraTime(z, z_utim);
+#else /* !USE_EF_UT_TIME */
+  return ZE_OK;
+#endif /* ?USE_EF_UT_TIME */
+}
+
+int deletedir(d)
+char *d;                /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+   Return the result of rmdir(), delete(), or system().
+   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).
+ */
+{
+    return rmdir(d);
+}
+
+#endif /* !UTIL */
diff --git a/win32/win32zip.h b/win32/win32zip.h
new file mode 100644 (file)
index 0000000..8ecb74c
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#ifndef _WIN32ZIP_H
+#define _WIN32ZIP_H
+
+/*
+ * NT specific functions for ZIP.
+ */
+
+int GetFileMode(const char *name);
+#if 0 /* never used */
+long GetTheFileTime(const char *name, iztimes *z_times);
+#endif
+
+int IsFileNameValid(const char *name);
+int IsFileSystemOldFAT(const char *dir);
+void ChangeNameForFAT(char *name);
+
+char *getVolumeLabel(int drive, ulg *vtime, ulg *vmode, time_t *vutim);
+
+#if 0 /* never used ?? */
+char *StringLower(char *);
+#endif
+
+char *GetLongPathEA(const char *name);
+
+#endif /* _WIN32ZIP_H */
diff --git a/win32/zip.def b/win32/zip.def
new file mode 100644 (file)
index 0000000..105e4b9
--- /dev/null
@@ -0,0 +1,4 @@
+;module-definition file for Windows Zip DLL -- used by link.exe
+DESCRIPTION 'The world-famous zip utilities from Info-ZIP'
+
+
diff --git a/win32/zipup.h b/win32/zipup.h
new file mode 100644 (file)
index 0000000..f65c41e
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#ifndef __CYGWIN__
+#  include <share.h>
+#endif
+#ifndef O_RDONLY
+#  define O_RDONLY   0
+#endif
+#ifndef O_BINARY
+#  define O_BINARY   0
+#endif
+#if (defined(_SH_DENYNO) && !defined(SH_DENYNO))
+#  define SH_DENYNO _SH_DENYNO
+#endif
+#if (defined(SH_DENYNO) && !defined(_SH_DENYNO))
+#  define _SH_DENYNO SH_DENYNO
+#endif
+#define fhow         (O_RDONLY|O_BINARY)
+#define fbad         (-1)
+typedef int          ftype;
+#if defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__EMX__)
+#  define zopen(n,p) sopen(n,p,SH_DENYNO)
+#elif defined(__CYGWIN__) || defined(__IBMC__)
+#  define zopen(n,p) open(n,p)
+#else
+#  define zopen(n,p) _sopen(n,p,_SH_DENYNO)
+#endif
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f)    close(f)
+#define zerr(f)      (k == (extent)(-1L))
+#define zstdin       0
diff --git a/windll/contents b/windll/contents
new file mode 100644 (file)
index 0000000..c063c26
--- /dev/null
@@ -0,0 +1,37 @@
+Contents of the "windll" sub-archive for Zip 2.31 and later:
+
+  contents       this file
+  windll16.def   definition file for 16-bit Zip DLL
+  windll32.def   definition file for 32-bit Zip DLL
+  windll.c       Contains the entry point for the DLL, "fake" printing,
+                 and password functions.
+  windll.h       header file for both 16 and 32-bit DLLs.
+  zipver.h       versioning information for resource file, and also
+                 used by WiZ application itself.
+  windll.rc      resource file for both 16 and 32-bit DLLs
+  windll.txt     simplistic explanation of how to use DLL.
+  structs.h      header file used by both the dll and by WiZ which defines
+                 several structures passed to the dll.
+  example.c      a very simplistic example of how to load the dll, and make
+                 a call into it.
+  example.h      header file for example.c
+
+  visualc\dll <dir> contains Visual C++ 6.0 project and make files for
+                    zip32 dll.
+  visualc\lib <dir> contains Visual C++ 6.0 project and make files for
+                    zip32 static library.
+  vb-orig     <dir> contains old version of a Visual Basic frontend example
+                    using zip32.dll
+  vb          <dir> new version of the Visual Basic dll frontend example,
+                    many bugfixes and enhancements
+
+The dll and static library port was developed and tested under Microsoft
+Visual C++ 6.0.  The former support for the Borland C++ compilers has been
+discontinued; bcc-compiled DLLs are not universally usable because of their
+requirements for special Borland runtime libs (and probably some calling
+convention specialities).
+Compilation for 16-bit Windows 3.x is no longer supported.
+
+Last updated February 22, 2005
+
+Mike White, Christian Spieler
diff --git a/windll/example.c b/windll/example.c
new file mode 100644 (file)
index 0000000..05939af
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ A very simplistic example of how to load the zip dll and make a call into it.
+ Note that none of the command line options are implemented in this example.
+
+ */
+
+#ifndef WIN32
+#  define WIN32
+#endif
+#define API
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <string.h>
+#ifdef __BORLANDC__
+#include <dir.h>
+#else
+#include <direct.h>
+#endif
+#include "example.h"
+#include "zipver.h"
+
+#ifdef WIN32
+#include <commctrl.h>
+#include <winver.h>
+#else
+#include <ver.h>
+#endif
+
+#ifdef WIN32
+#define ZIP_DLL_NAME "ZIP32.DLL\0"
+#else
+#define ZIP_DLL_NAME "ZIP16.DLL\0"
+#endif
+
+#define DLL_WARNING "Cannot find %s."\
+            " The Dll must be in the application directory, the path, "\
+            "the Windows directory or the Windows System directory."
+#define DLL_VERSION_WARNING "%s has the wrong version number."\
+            " Insure that you have the correct dll's installed, and that "\
+            "an older dll is not in your path or Windows System directory."
+
+int hFile;              /* file handle */
+
+ZCL ZpZCL;
+LPZIPUSERFUNCTIONS lpZipUserFunctions;
+HANDLE hZUF = (HANDLE)NULL;
+HINSTANCE hUnzipDll;
+HANDLE hFileList;
+ZPOPT ZpOpt;
+#ifdef WIN32
+DWORD dwPlatformId = 0xFFFFFFFF;
+#endif
+HINSTANCE hZipDll;
+
+
+/* Forward References */
+_DLL_ZIP ZipArchive;
+_ZIP_USER_FUNCTIONS ZipInit;
+ZIPSETOPTIONS ZipSetOptions;
+
+void FreeUpMemory(void);
+int WINAPI DummyPassword(LPSTR, int, LPCSTR, LPCSTR);
+int WINAPI DummyPrint(char far *, unsigned long);
+int WINAPI WINAPI DummyComment(char far *);
+
+#ifdef WIN32
+BOOL IsNT(VOID);
+#endif
+
+/****************************************************************************
+
+    FUNCTION: Main(int argc, char **argv)
+
+****************************************************************************/
+#ifdef __BORLANDC__
+#  ifdef WIN32
+#pragma argsused
+#  endif
+#endif
+int main(int argc, char **argv)
+{
+LPSTR szFileList;
+char **index, *sz;
+int retcode, i, cc;
+DWORD dwVerInfoSize;
+DWORD dwVerHnd;
+char szFullPath[PATH_MAX];
+#ifdef WIN32
+char *ptr;
+#else
+HFILE hfile;
+OFSTRUCT ofs;
+#endif
+HANDLE  hMem;         /* handle to mem alloc'ed */
+
+if (argc < 3)
+   return 0;           /* Exits if not proper number of arguments */
+
+hZUF = GlobalAlloc( GPTR, (DWORD)sizeof(ZIPUSERFUNCTIONS));
+if (!hZUF)
+   {
+   return 0;
+   }
+lpZipUserFunctions = (LPZIPUSERFUNCTIONS)GlobalLock(hZUF);
+
+if (!lpZipUserFunctions)
+   {
+   GlobalFree(hZUF);
+   return 0;
+   }
+
+lpZipUserFunctions->print = DummyPrint;
+lpZipUserFunctions->password = DummyPassword;
+lpZipUserFunctions->comment = DummyComment;
+
+/* Let's go find the dll */
+#ifdef WIN32
+if (SearchPath(
+    NULL,               /* address of search path               */
+    ZIP_DLL_NAME,       /* address of filename                  */
+    NULL,               /* address of extension                 */
+    PATH_MAX,           /* size, in characters, of buffer       */
+    szFullPath,         /* address of buffer for found filename */
+    &ptr                /* address of pointer to file component */
+   ) == 0)
+#else
+hfile = OpenFile(ZIP_DLL_NAME,  &ofs, OF_SEARCH);
+if (hfile == HFILE_ERROR)
+#endif
+   {
+   char str[256];
+   wsprintf (str, DLL_WARNING, ZIP_DLL_NAME);
+   printf("%s\n", str);
+   FreeUpMemory();
+   return 0;
+   }
+#ifndef WIN32
+else
+   lstrcpy(szFullPath, ofs.szPathName);
+_lclose(hfile);
+#endif
+
+/* Now we'll check the zip dll version information */
+dwVerInfoSize =
+    GetFileVersionInfoSize(szFullPath, &dwVerHnd);
+
+if (dwVerInfoSize)
+   {
+   BOOL  fRet, fRetName;
+   char str[256];
+   LPSTR   lpstrVffInfo; /* Pointer to block to hold info */
+   LPSTR lszVer = NULL;
+   LPSTR lszVerName = NULL;
+   UINT  cchVer = 0;
+
+   /* Get a block big enough to hold the version information */
+   hMem          = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
+   lpstrVffInfo  = GlobalLock(hMem);
+
+   /* Get the version information */
+   GetFileVersionInfo(szFullPath, 0L, dwVerInfoSize, lpstrVffInfo);
+   fRet = VerQueryValue(lpstrVffInfo,
+              TEXT("\\StringFileInfo\\040904E4\\FileVersion"),
+               (LPVOID)&lszVer,
+               &cchVer);
+   fRetName = VerQueryValue(lpstrVffInfo,
+               TEXT("\\StringFileInfo\\040904E4\\CompanyName"),
+              (LPVOID)&lszVerName,
+              &cchVer);
+   if (!fRet || !fRetName ||
+      (lstrcmpi(lszVer, ZIP_DLL_VERSION) != 0) ||
+      (lstrcmpi(lszVerName, COMPANY_NAME) != 0))
+      {
+      wsprintf (str, DLL_VERSION_WARNING, ZIP_DLL_NAME);
+      printf("%s\n", str);
+      FreeUpMemory();
+      return 0;
+      }
+   /* free memory */
+   GlobalUnlock(hMem);
+   GlobalFree(hMem);
+   }
+else
+   {
+   char str[256];
+   wsprintf (str, DLL_VERSION_WARNING, ZIP_DLL_NAME);
+   printf("%s\n", str);
+   FreeUpMemory();
+   return 0;
+   }
+/* Okay, now we know that the dll exists, and has the proper version
+ * information in it. We can go ahead and load it.
+ */
+hZipDll = LoadLibrary(ZIP_DLL_NAME);
+#ifndef WIN32
+if (hZipDll > HINSTANCE_ERROR)
+#else
+if (hZipDll != NULL)
+#endif
+   {
+   (_DLL_ZIP)ZipArchive = (_DLL_ZIP)GetProcAddress(hZipDll, "ZpArchive");
+   (ZIPSETOPTIONS)ZipSetOptions = (ZIPSETOPTIONS)GetProcAddress(hZipDll, "ZpSetOptions");
+   if (!ZipArchive || !ZipSetOptions)
+      {
+      char str[256];
+      wsprintf (str, "Could not get entry point to %s", ZIP_DLL_NAME);
+      MessageBox((HWND)NULL, str, "Info-ZIP Example", MB_ICONSTOP | MB_OK);
+      FreeUpMemory();
+      return 0;
+      }
+   }
+else
+   {
+   char str[256];
+   wsprintf (str, "Could not load %s", ZIP_DLL_NAME);
+   printf("%s\n", str);
+   FreeUpMemory();
+   return 0;
+   }
+
+(_ZIP_USER_FUNCTIONS)ZipInit = (_ZIP_USER_FUNCTIONS)GetProcAddress(hZipDll, "ZpInit");
+if (!ZipInit)
+   {
+   printf("Cannot get address of ZpInit in Zip dll. Terminating...");
+   FreeLibrary(hZipDll);
+   FreeUpMemory();
+   return 0;
+   }
+if (!(*ZipInit)(lpZipUserFunctions))
+   {
+   printf("Application functions not set up properly. Terminating...");
+   FreeLibrary(hZipDll);
+   FreeUpMemory();
+   return 0;
+   }
+
+/* Here is where the action starts */
+ZpOpt.fSuffix = FALSE;        /* include suffixes (not yet implemented) */
+ZpOpt.fEncrypt = FALSE;       /* true if encryption wanted */
+ZpOpt.fSystem = FALSE;        /* true to include system/hidden files */
+ZpOpt.fVolume = FALSE;        /* true if storing volume label */
+ZpOpt.fExtra = FALSE;         /* true if including extra attributes */
+ZpOpt.fNoDirEntries = FALSE;  /* true if ignoring directory entries */
+ZpOpt.fVerbose = FALSE;       /* true if full messages wanted */
+ZpOpt.fQuiet = FALSE;         /* true if minimum messages wanted */
+ZpOpt.fCRLF_LF = FALSE;       /* true if translate CR/LF to LF */
+ZpOpt.fLF_CRLF = FALSE;       /* true if translate LF to CR/LF */
+ZpOpt.fJunkDir = FALSE;       /* true if junking directory names */
+ZpOpt.fGrow = FALSE;          /* true if allow appending to zip file */
+ZpOpt.fForce = FALSE;         /* true if making entries using DOS names */
+ZpOpt.fMove = FALSE;          /* true if deleting files added or updated */
+ZpOpt.fUpdate = FALSE;        /* true if updating zip file--overwrite only
+                                  if newer */
+ZpOpt.fFreshen = FALSE;       /* true if freshening zip file--overwrite only */
+ZpOpt.fJunkSFX = FALSE;       /* true if junking sfx prefix*/
+ZpOpt.fLatestTime = FALSE;    /* true if setting zip file time to time of
+                                  latest file in archive */
+ZpOpt.fComment = FALSE;       /* true if putting comment in zip file */
+ZpOpt.fOffsets = FALSE;       /* true if updating archive offsets for sfx
+                                  files */
+ZpOpt.fDeleteEntries = FALSE; /* true if deleting files from archive */
+ZpOpt.fRecurse = 0;           /* subdir recursing mode: 1 = "-r", 2 = "-R" */
+ZpOpt.fRepair = 0;            /* archive repair mode: 1 = "-F", 2 = "-FF" */
+ZpOpt.Date = NULL;            /* Not using, set to NULL pointer */
+getcwd(szFullPath, PATH_MAX); /* Set directory to current directory */
+ZpOpt.szRootDir = szFullPath;
+
+ZpZCL.argc = argc - 2;        /* number of files to archive - adjust for the
+                                  actual number of file names to be added */
+ZpZCL.lpszZipFN = argv[1];    /* archive to be created/updated */
+
+/* Copy over the appropriate portions of argv, basically stripping out argv[0]
+   (name of the executable) and argv[1] (name of the archive file)
+ */
+hFileList = GlobalAlloc( GPTR, 0x10000L);
+if ( hFileList )
+   {
+   szFileList = (char far *)GlobalLock(hFileList);
+   }
+index = (char **)szFileList;
+cc = (sizeof(char *) * ZpZCL.argc);
+sz = szFileList + cc;
+
+for (i = 0; i < ZpZCL.argc; i++)
+    {
+    cc = lstrlen(argv[i+2]);
+    lstrcpy(sz, argv[i+2]);
+    index[i] = sz;
+    sz += (cc + 1);
+    }
+ZpZCL.FNV = (char **)szFileList;  /* list of files to archive */
+
+/* Set the options */
+ZipSetOptions(&ZpOpt);
+
+/* Go zip 'em up */
+retcode = ZipArchive(ZpZCL);
+if (retcode != 0)
+   printf("Error in archiving\n");
+
+GlobalUnlock(hFileList);
+GlobalFree(hFileList);
+FreeUpMemory();
+FreeLibrary(hZipDll);
+return 1;
+}
+
+void FreeUpMemory(void)
+{
+if (hZUF)
+   {
+   GlobalUnlock(hZUF);
+   GlobalFree(hZUF);
+   }
+}
+
+#ifdef WIN32
+/* This simply determines if we are running on NT */
+BOOL IsNT(VOID)
+{
+if(dwPlatformId != 0xFFFFFFFF)
+   return dwPlatformId;
+else
+/* note: GetVersionEx() doesn't exist on WinNT 3.1 */
+   {
+   if(GetVersion() < 0x80000000)
+      {
+      (BOOL)dwPlatformId = TRUE;
+      }
+   else
+      {
+      (BOOL)dwPlatformId = FALSE;
+      }
+    }
+return dwPlatformId;
+}
+#endif
+
+/* Password entry routine - see password.c in the wiz directory for how
+   this is actually implemented in Wiz. If you have an encrypted file,
+   this will probably give you great pain. Note that none of the
+   parameters are being used here, and this will give you warnings.
+ */
+int WINAPI DummyPassword(LPSTR p, int n, LPCSTR m, LPCSTR name)
+{
+return 1;
+}
+
+/* Dummy "print" routine that simply outputs what is sent from the dll */
+int WINAPI DummyPrint(char far *buf, unsigned long size)
+{
+printf("%s", buf);
+return (unsigned int) size;
+}
+
+
+/* Dummy "comment" routine. See comment.c in the wiz directory for how
+   this is actually implemented in Wiz. This will probably cause you
+   great pain if you ever actually make a call into it.
+ */
+int WINAPI DummyComment(char far *szBuf)
+{
+szBuf[0] = '\0';
+return TRUE;
+}
diff --git a/windll/example.h b/windll/example.h
new file mode 100644 (file)
index 0000000..0061d5e
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ Example header file
+*/
+#ifndef _EXAMPLE_H
+#define _EXAMPLE_H
+
+#include <windows.h>
+#include <assert.h>    /* required for all Windows applications */
+#include <stdlib.h>
+#include <stdio.h>
+#include <commdlg.h>
+#include <dlgs.h>
+#include <windowsx.h>
+
+#ifndef EXPENTRY
+#define EXPENTRY WINAPI
+#endif
+
+#include "structs.h"
+
+/* Defines */
+#ifndef MSWIN
+#define MSWIN
+#endif
+
+typedef int (WINAPI * _DLL_ZIP)(ZCL);
+typedef int (WINAPI * _ZIP_USER_FUNCTIONS)(LPZIPUSERFUNCTIONS);
+typedef BOOL (WINAPI * ZIPSETOPTIONS)(LPZPOPT);
+
+/* Global variables */
+
+extern LPZIPUSERFUNCTIONS lpZipUserFunctions;
+
+extern HINSTANCE hZipDll;
+
+extern int hFile;                 /* file handle             */
+
+/* Global functions */
+
+int WINAPI DisplayBuf(char far *, unsigned long int);
+extern _DLL_ZIP ZipArchive;
+extern _ZIP_USER_FUNCTIONS ZipInit;
+extern ZIPSETOPTIONS ZipSetOptions;
+
+#endif /* _EXAMPLE_H */
+
diff --git a/windll/resource.h b/windll/resource.h
new file mode 100644 (file)
index 0000000..be10954
--- /dev/null
@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by windll.rc
+//
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC                     1
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/windll/structs.h b/windll/structs.h
new file mode 100644 (file)
index 0000000..f3c11a5
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#ifndef _ZIP_STRUCTS_H
+#define _ZIP_STRUCTS_H
+
+#ifndef Far
+#  define Far far
+#endif
+
+/* Porting definations between Win 3.1x and Win32 */
+#ifdef WIN32
+#  define far
+#  define _far
+#  define __far
+#  define near
+#  define _near
+#  define __near
+#endif
+
+#include "../api.h"
+
+#endif /* _ZIP_STRUCTS_H */
diff --git a/windll/vb/VBZIP.vbw b/windll/vb/VBZIP.vbw
new file mode 100644 (file)
index 0000000..907a008
--- /dev/null
@@ -0,0 +1,2 @@
+Form1 = 22, 22, 668, 535, , 22, 22, 456, 360, C\r
+VBZipBas = 68, 5, 691, 512, \r
diff --git a/windll/vb/VBZipBas.bas b/windll/vb/VBZipBas.bas
new file mode 100644 (file)
index 0000000..18ec77a
--- /dev/null
@@ -0,0 +1,455 @@
+Attribute VB_Name = "VBZipBas"\r
+\r
+Option Explicit\r
+\r
+'---------------------------------------------------------------\r
+'-- Please Do Not Remove These Comments!!!\r
+'---------------------------------------------------------------\r
+'-- Sample VB 5 code to drive zip32.dll\r
+'-- Contributed to the Info-ZIP project by Mike Le Voi\r
+'--\r
+'-- Contact me at: mlevoi@modemss.brisnet.org.au\r
+'--\r
+'-- Visit my home page at: http://modemss.brisnet.org.au/~mlevoi\r
+'--\r
+'-- Use this code at your own risk. Nothing implied or warranted\r
+'-- to work on your machine :-)\r
+'---------------------------------------------------------------\r
+'--\r
+'-- The Source Code Is Freely Available From Info-ZIP At:\r
+'-- http://www.cdrom.com/pub/infozip/infozip.html\r
+'--\r
+'-- A Very Special Thanks To Mr. Mike Le Voi\r
+'-- And Mr. Mike White Of The Info-ZIP\r
+'-- For Letting Me Use And Modify His Orginal\r
+'-- Visual Basic 5.0 Code! Thank You Mike Le Voi.\r
+'---------------------------------------------------------------\r
+'--\r
+'-- Contributed To The Info-ZIP Project By Raymond L. King\r
+'-- Modified June 21, 1998\r
+'-- By Raymond L. King\r
+'-- Custom Software Designers\r
+'--\r
+'-- Contact Me At: king@ntplx.net\r
+'-- ICQ 434355\r
+'-- Or Visit Our Home Page At: http://www.ntplx.net/~king\r
+'--\r
+'---------------------------------------------------------------\r
+'\r
+' This is the original example with some small changes. Only\r
+' use with the original Zip32.dll (Zip 2.3).  Do not use this VB\r
+' example with Zip32z64.dll (Zip 3.0).\r
+'\r
+' 4/29/2004 Ed Gordon\r
+\r
+'---------------------------------------------------------------\r
+' Usage notes:\r
+'\r
+' This code uses Zip32.dll.  You DO NOT need to register the\r
+' DLL to use it.  You also DO NOT need to reference it in your\r
+' VB project.  You DO have to copy the DLL to your SYSTEM\r
+' directory, your VB project directory, or place it in a directory\r
+' on your command PATH.\r
+'\r
+' A bug has been found in the Zip32.dll when called from VB.  If\r
+' you try to pass any values other than NULL in the ZPOPT strings\r
+' Date, szRootDir, or szTempDir they get converted from the\r
+' VB internal wide character format to temporary byte strings by\r
+' the calling interface as they are supposed to.  However when\r
+' ZpSetOptions returns the passed strings are deallocated unless the\r
+' VB debugger prevents it by a break between ZpSetOptions and\r
+' ZpArchive.  When Zip32.dll uses these pointers later it\r
+' can result in unpredictable behavior.  A kluge is available\r
+' for Zip32.dll, just replacing api.c in Zip 2.3, but better to just\r
+' use the new Zip32z64.dll where these bugs are fixed.  However,\r
+' the kluge has been added to Zip 2.31.  To determine the version\r
+' of the dll you have right click on it, select the Version tab,\r
+' and verify the Product Version is at least 2.31.\r
+'\r
+' Another bug is where -R is used with some other options and can\r
+' crash the dll.  This is a bug in how zip processes the command\r
+' line and should be mostly fixed in Zip 2.31.  If you run into\r
+' problems try using -r instead for recursion.  The bug is fixed\r
+' in Zip 3.0 but note that Zip 3.0 creates dll zip32z64.dll and\r
+' it is not compatible with older VB including this example.  See\r
+' the new VB example code included with Zip 3.0 for calling\r
+' interface changes.\r
+'\r
+' Note that Zip32 is probably not thread safe.  It may be made\r
+' thread safe in a later version, but for now only one thread in\r
+' one program should use the DLL at a time.  Unlike Zip, UnZip is\r
+' probably thread safe, but an exception to this has been\r
+' found.  See the UnZip documentation for the latest on this.\r
+'\r
+' All code in this VB project is provided under the Info-Zip license.\r
+'\r
+' If you have any questions please contact Info-Zip at\r
+' http://www.info-zip.org.\r
+'\r
+' 4/29/2004 EG (Updated 3/1/2005 EG)\r
+'\r
+'---------------------------------------------------------------\r
+\r
+\r
+'-- C Style argv\r
+'-- Holds The Zip Archive Filenames\r
+' Max for this just over 8000 as each pointer takes up 4 bytes and\r
+' VB only allows 32 kB of local variables and that includes function\r
+' parameters.  - 3/19/2004 EG\r
+'\r
+Public Type ZIPnames\r
+  zFiles(0 To 99) As String\r
+End Type\r
+\r
+'-- Call Back "String"\r
+Public Type ZipCBChar\r
+  ch(4096) As Byte\r
+End Type\r
+\r
+'-- ZPOPT Is Used To Set The Options In The ZIP32.DLL\r
+Public Type ZPOPT\r
+  Date           As String ' US Date (8 Bytes Long) "12/31/98"?\r
+  szRootDir      As String ' Root Directory Pathname (Up To 256 Bytes Long)\r
+  szTempDir      As String ' Temp Directory Pathname (Up To 256 Bytes Long)\r
+  fTemp          As Long   ' 1 If Temp dir Wanted, Else 0\r
+  fSuffix        As Long   ' Include Suffixes (Not Yet Implemented!)\r
+  fEncrypt       As Long   ' 1 If Encryption Wanted, Else 0\r
+  fSystem        As Long   ' 1 To Include System/Hidden Files, Else 0\r
+  fVolume        As Long   ' 1 If Storing Volume Label, Else 0\r
+  fExtra         As Long   ' 1 If Excluding Extra Attributes, Else 0\r
+  fNoDirEntries  As Long   ' 1 If Ignoring Directory Entries, Else 0\r
+  fExcludeDate   As Long   ' 1 If Excluding Files Earlier Than Specified Date, Else 0\r
+  fIncludeDate   As Long   ' 1 If Including Files Earlier Than Specified Date, Else 0\r
+  fVerbose       As Long   ' 1 If Full Messages Wanted, Else 0\r
+  fQuiet         As Long   ' 1 If Minimum Messages Wanted, Else 0\r
+  fCRLF_LF       As Long   ' 1 If Translate CR/LF To LF, Else 0\r
+  fLF_CRLF       As Long   ' 1 If Translate LF To CR/LF, Else 0\r
+  fJunkDir       As Long   ' 1 If Junking Directory Names, Else 0\r
+  fGrow          As Long   ' 1 If Allow Appending To Zip File, Else 0\r
+  fForce         As Long   ' 1 If Making Entries Using DOS File Names, Else 0\r
+  fMove          As Long   ' 1 If Deleting Files Added Or Updated, Else 0\r
+  fDeleteEntries As Long   ' 1 If Files Passed Have To Be Deleted, Else 0\r
+  fUpdate        As Long   ' 1 If Updating Zip File-Overwrite Only If Newer, Else 0\r
+  fFreshen       As Long   ' 1 If Freshing Zip File-Overwrite Only, Else 0\r
+  fJunkSFX       As Long   ' 1 If Junking SFX Prefix, Else 0\r
+  fLatestTime    As Long   ' 1 If Setting Zip File Time To Time Of Latest File In Archive, Else 0\r
+  fComment       As Long   ' 1 If Putting Comment In Zip File, Else 0\r
+  fOffsets       As Long   ' 1 If Updating Archive Offsets For SFX Files, Else 0\r
+  fPrivilege     As Long   ' 1 If Not Saving Privileges, Else 0\r
+  fEncryption    As Long   ' Read Only Property!!!\r
+  fRecurse       As Long   ' 1 (-r), 2 (-R) If Recursing Into Sub-Directories, Else 0\r
+  fRepair        As Long   ' 1 = Fix Archive, 2 = Try Harder To Fix, Else 0\r
+  flevel         As Byte   ' Compression Level - 0 = Stored 6 = Default 9 = Max\r
+End Type\r
+\r
+'-- This Structure Is Used For The ZIP32.DLL Function Callbacks\r
+Public Type ZIPUSERFUNCTIONS\r
+  ZDLLPrnt     As Long        ' Callback ZIP32.DLL Print Function\r
+  ZDLLCOMMENT  As Long        ' Callback ZIP32.DLL Comment Function\r
+  ZDLLPASSWORD As Long        ' Callback ZIP32.DLL Password Function\r
+  ZDLLSERVICE  As Long        ' Callback ZIP32.DLL Service Function\r
+End Type\r
+\r
+'-- Local Declarations\r
+Public ZOPT  As ZPOPT\r
+Public ZUSER As ZIPUSERFUNCTIONS\r
+\r
+'-- This Assumes ZIP32.DLL Is In Your \Windows\System Directory!\r
+'-- (alternatively, a copy of ZIP32.DLL needs to be located in the program\r
+'-- directory or in some other directory listed in PATH.)\r
+Private Declare Function ZpInit Lib "zip32.dll" _\r
+  (ByRef Zipfun As ZIPUSERFUNCTIONS) As Long '-- Set Zip Callbacks\r
+\r
+Private Declare Function ZpSetOptions Lib "zip32.dll" _\r
+  (ByRef Opts As ZPOPT) As Long '-- Set Zip Options\r
+\r
+Private Declare Function ZpGetOptions Lib "zip32.dll" _\r
+  () As ZPOPT '-- Used To Check Encryption Flag Only\r
+\r
+Private Declare Function ZpArchive Lib "zip32.dll" _\r
+  (ByVal argc As Long, ByVal funame As String, _\r
+   ByRef argv As ZIPnames) As Long '-- Real Zipping Action\r
+\r
+'-------------------------------------------------------\r
+'-- Public Variables For Setting The ZPOPT Structure...\r
+'-- (WARNING!!!) You Must Set The Options That You\r
+'-- Want The ZIP32.DLL To Do!\r
+'-- Before Calling VBZip32!\r
+'--\r
+'-- NOTE: See The Above ZPOPT Structure Or The VBZip32\r
+'--       Function, For The Meaning Of These Variables\r
+'--       And How To Use And Set Them!!!\r
+'-- These Parameters Must Be Set Before The Actual Call\r
+'-- To The VBZip32 Function!\r
+'-------------------------------------------------------\r
+Public zDate         As String\r
+Public zRootDir      As String\r
+Public zTempDir      As String\r
+Public zSuffix       As Integer\r
+Public zEncrypt      As Integer\r
+Public zSystem       As Integer\r
+Public zVolume       As Integer\r
+Public zExtra        As Integer\r
+Public zNoDirEntries As Integer\r
+Public zExcludeDate  As Integer\r
+Public zIncludeDate  As Integer\r
+Public zVerbose      As Integer\r
+Public zQuiet        As Integer\r
+Public zCRLF_LF      As Integer\r
+Public zLF_CRLF      As Integer\r
+Public zJunkDir      As Integer\r
+Public zRecurse      As Integer\r
+Public zGrow         As Integer\r
+Public zForce        As Integer\r
+Public zMove         As Integer\r
+Public zDelEntries   As Integer\r
+Public zUpdate       As Integer\r
+Public zFreshen      As Integer\r
+Public zJunkSFX      As Integer\r
+Public zLatestTime   As Integer\r
+Public zComment      As Integer\r
+Public zOffsets      As Integer\r
+Public zPrivilege    As Integer\r
+Public zEncryption   As Integer\r
+Public zRepair       As Integer\r
+Public zLevel        As Integer\r
+\r
+'-- Public Program Variables\r
+Public zArgc         As Integer     ' Number Of Files To Zip Up\r
+Public zZipFileName  As String      ' The Zip File Name ie: Myzip.zip\r
+Public zZipFileNames As ZIPnames    ' File Names To Zip Up\r
+Public zZipInfo      As String      ' Holds The Zip File Information\r
+\r
+'-- Public Constants\r
+'-- For Zip & UnZip Error Codes!\r
+Public Const ZE_OK = 0              ' Success (No Error)\r
+Public Const ZE_EOF = 2             ' Unexpected End Of Zip File Error\r
+Public Const ZE_FORM = 3            ' Zip File Structure Error\r
+Public Const ZE_MEM = 4             ' Out Of Memory Error\r
+Public Const ZE_LOGIC = 5           ' Internal Logic Error\r
+Public Const ZE_BIG = 6             ' Entry Too Large To Split Error\r
+Public Const ZE_NOTE = 7            ' Invalid Comment Format Error\r
+Public Const ZE_TEST = 8            ' Zip Test (-T) Failed Or Out Of Memory Error\r
+Public Const ZE_ABORT = 9           ' User Interrupted Or Termination Error\r
+Public Const ZE_TEMP = 10           ' Error Using A Temp File\r
+Public Const ZE_READ = 11           ' Read Or Seek Error\r
+Public Const ZE_NONE = 12           ' Nothing To Do Error\r
+Public Const ZE_NAME = 13           ' Missing Or Empty Zip File Error\r
+Public Const ZE_WRITE = 14          ' Error Writing To A File\r
+Public Const ZE_CREAT = 15          ' Could't Open To Write Error\r
+Public Const ZE_PARMS = 16          ' Bad Command Line Argument Error\r
+Public Const ZE_OPEN = 18           ' Could Not Open A Specified File To Read Error\r
+\r
+'-- These Functions Are For The ZIP32.DLL\r
+'--\r
+'-- Puts A Function Pointer In A Structure\r
+'-- For Use With Callbacks...\r
+Public Function FnPtr(ByVal lp As Long) As Long\r
+    \r
+  FnPtr = lp\r
+\r
+End Function\r
+\r
+'-- Callback For ZIP32.DLL - DLL Print Function\r
+Public Function ZDLLPrnt(ByRef fname As ZipCBChar, ByVal x As Long) As Long\r
+    \r
+  Dim s0 As String\r
+  Dim xx As Long\r
+    \r
+  '-- Always Put This In Callback Routines!\r
+  On Error Resume Next\r
+    \r
+  s0 = ""\r
+    \r
+  '-- Get Zip32.DLL Message For processing\r
+  For xx = 0 To x\r
+    If fname.ch(xx) = 0 Then\r
+      Exit For\r
+    Else\r
+      s0 = s0 + Chr(fname.ch(xx))\r
+    End If\r
+  Next\r
+    \r
+  '----------------------------------------------\r
+  '-- This Is Where The DLL Passes Back Messages\r
+  '-- To You! You Can Change The Message Printing\r
+  '-- Below Here!\r
+  '----------------------------------------------\r
+  \r
+  '-- Display Zip File Information\r
+  '-- zZipInfo = zZipInfo & s0\r
+  Form1.Print s0;\r
+    \r
+  DoEvents\r
+    \r
+  ZDLLPrnt = 0\r
+\r
+End Function\r
+\r
+'-- Callback For ZIP32.DLL - DLL Service Function\r
+Public Function ZDLLServ(ByRef mname As ZipCBChar, ByVal x As Long) As Long\r
+\r
+    ' x is the size of the file\r
+    \r
+    Dim s0 As String\r
+    Dim xx As Long\r
+    \r
+    '-- Always Put This In Callback Routines!\r
+    On Error Resume Next\r
+    \r
+    s0 = ""\r
+    '-- Get Zip32.DLL Message For processing\r
+    For xx = 0 To 4096\r
+    If mname.ch(xx) = 0 Then\r
+        Exit For\r
+    Else\r
+        s0 = s0 + Chr(mname.ch(xx))\r
+    End If\r
+    Next\r
+    ' Form1.Print "-- " & s0 & " - " & x & " bytes"\r
+    \r
+    ' This is called for each zip entry.\r
+    ' mname is usually the null terminated file name and x the file size.\r
+    ' s0 has trimmed file name as VB string.\r
+\r
+    ' At this point, s0 contains the message passed from the DLL\r
+    ' It is up to the developer to code something useful here :)\r
+    ZDLLServ = 0 ' Setting this to 1 will abort the zip!\r
+    \r
+End Function\r
+\r
+'-- Callback For ZIP32.DLL - DLL Password Function\r
+Public Function ZDLLPass(ByRef p As ZipCBChar, _\r
+  ByVal n As Long, ByRef m As ZipCBChar, _\r
+  ByRef Name As ZipCBChar) As Integer\r
+  \r
+  Dim prompt     As String\r
+  Dim xx         As Integer\r
+  Dim szpassword As String\r
+  \r
+  '-- Always Put This In Callback Routines!\r
+  On Error Resume Next\r
+    \r
+  ZDLLPass = 1\r
+  \r
+  '-- If There Is A Password Have The User Enter It!\r
+  '-- This Can Be Changed\r
+  szpassword = InputBox("Please Enter The Password!")\r
+  \r
+  '-- The User Did Not Enter A Password So Exit The Function\r
+  If szpassword = "" Then Exit Function\r
+  \r
+  '-- User Entered A Password So Proccess It\r
+  For xx = 0 To 255\r
+    If m.ch(xx) = 0 Then\r
+      Exit For\r
+    Else\r
+      prompt = prompt & Chr(m.ch(xx))\r
+    End If\r
+  Next\r
+  \r
+  For xx = 0 To n - 1\r
+    p.ch(xx) = 0\r
+  Next\r
+  \r
+  For xx = 0 To Len(szpassword) - 1\r
+    p.ch(xx) = Asc(Mid(szpassword, xx + 1, 1))\r
+  Next\r
+  \r
+  p.ch(xx) = Chr(0) ' Put Null Terminator For C\r
+  \r
+  ZDLLPass = 0\r
+    \r
+End Function\r
+\r
+'-- Callback For ZIP32.DLL - DLL Comment Function\r
+Public Function ZDLLComm(ByRef s1 As ZipCBChar) As Integer\r
+    \r
+    Dim xx%, szcomment$\r
+    \r
+    '-- Always Put This In Callback Routines!\r
+    On Error Resume Next\r
+    \r
+    ZDLLComm = 1\r
+    szcomment = InputBox("Enter the comment")\r
+    If szcomment = "" Then Exit Function\r
+    For xx = 0 To Len(szcomment) - 1\r
+        s1.ch(xx) = Asc(Mid$(szcomment, xx + 1, 1))\r
+    Next xx\r
+    s1.ch(xx) = Chr(0) ' Put null terminator for C\r
+\r
+End Function\r
+\r
+'-- Main ZIP32.DLL Subroutine.\r
+'-- This Is Where It All Happens!!!\r
+'--\r
+'-- (WARNING!) Do Not Change This Function!!!\r
+'--\r
+Public Function VBZip32() As Long\r
+    \r
+  Dim retcode As Long\r
+    \r
+  On Error Resume Next '-- Nothing Will Go Wrong :-)\r
+    \r
+  retcode = 0\r
+    \r
+  '-- Set Address Of ZIP32.DLL Callback Functions\r
+  '-- (WARNING!) Do Not Change!!!\r
+  ZUSER.ZDLLPrnt = FnPtr(AddressOf ZDLLPrnt)\r
+  ZUSER.ZDLLPASSWORD = FnPtr(AddressOf ZDLLPass)\r
+  ZUSER.ZDLLCOMMENT = FnPtr(AddressOf ZDLLComm)\r
+  ZUSER.ZDLLSERVICE = FnPtr(AddressOf ZDLLServ)\r
+    \r
+  '-- Set ZIP32.DLL Callbacks\r
+  retcode = ZpInit(ZUSER)\r
+  If retcode = 0 Then\r
+    MsgBox "Zip32.dll did not initialize.  Is it in the current directory " & _\r
+                "or on the command path?", vbOKOnly, "VB Zip"\r
+    Exit Function\r
+  End If\r
+    \r
+  '-- Setup ZIP32 Options\r
+  '-- (WARNING!) Do Not Change!\r
+  ZOPT.Date = zDate                  ' "12/31/79"? US Date?\r
+  ZOPT.szRootDir = zRootDir          ' Root Directory Pathname\r
+  ZOPT.szTempDir = zTempDir          ' Temp Directory Pathname\r
+  ZOPT.fSuffix = zSuffix             ' Include Suffixes (Not Yet Implemented)\r
+  ZOPT.fEncrypt = zEncrypt           ' 1 If Encryption Wanted\r
+  ZOPT.fSystem = zSystem             ' 1 To Include System/Hidden Files\r
+  ZOPT.fVolume = zVolume             ' 1 If Storing Volume Label\r
+  ZOPT.fExtra = zExtra               ' 1 If Including Extra Attributes\r
+  ZOPT.fNoDirEntries = zNoDirEntries ' 1 If Ignoring Directory Entries\r
+  ZOPT.fExcludeDate = zExcludeDate   ' 1 If Excluding Files Earlier Than A Specified Date\r
+  ZOPT.fIncludeDate = zIncludeDate   ' 1 If Including Files Earlier Than A Specified Date\r
+  ZOPT.fVerbose = zVerbose           ' 1 If Full Messages Wanted\r
+  ZOPT.fQuiet = zQuiet               ' 1 If Minimum Messages Wanted\r
+  ZOPT.fCRLF_LF = zCRLF_LF           ' 1 If Translate CR/LF To LF\r
+  ZOPT.fLF_CRLF = zLF_CRLF           ' 1 If Translate LF To CR/LF\r
+  ZOPT.fJunkDir = zJunkDir           ' 1 If Junking Directory Names\r
+  ZOPT.fGrow = zGrow                 ' 1 If Allow Appending To Zip File\r
+  ZOPT.fForce = zForce               ' 1 If Making Entries Using DOS Names\r
+  ZOPT.fMove = zMove                 ' 1 If Deleting Files Added Or Updated\r
+  ZOPT.fDeleteEntries = zDelEntries  ' 1 If Files Passed Have To Be Deleted\r
+  ZOPT.fUpdate = zUpdate             ' 1 If Updating Zip File-Overwrite Only If Newer\r
+  ZOPT.fFreshen = zFreshen           ' 1 If Freshening Zip File-Overwrite Only\r
+  ZOPT.fJunkSFX = zJunkSFX           ' 1 If Junking SFX Prefix\r
+  ZOPT.fLatestTime = zLatestTime     ' 1 If Setting Zip File Time To Time Of Latest File In Archive\r
+  ZOPT.fComment = zComment           ' 1 If Putting Comment In Zip File\r
+  ZOPT.fOffsets = zOffsets           ' 1 If Updating Archive Offsets For SFX Files\r
+  ZOPT.fPrivilege = zPrivilege       ' 1 If Not Saving Privelages\r
+  ZOPT.fEncryption = zEncryption     ' Read Only Property!\r
+  ZOPT.fRecurse = zRecurse           ' 1 or 2 If Recursing Into Subdirectories\r
+  ZOPT.fRepair = zRepair             ' 1 = Fix Archive, 2 = Try Harder To Fix\r
+  ZOPT.flevel = zLevel               ' Compression Level - (0 To 9) Should Be 0!!!\r
+    \r
+  '-- Set ZIP32.DLL Options\r
+  retcode = ZpSetOptions(ZOPT)\r
+    \r
+  '-- Go Zip It Them Up!\r
+  retcode = ZpArchive(zArgc, zZipFileName, zZipFileNames)\r
+  \r
+  '-- Return The Function Code\r
+  VBZip32 = retcode\r
+\r
+End Function\r
+\r
diff --git a/windll/vb/Vbzip.vbp b/windll/vb/Vbzip.vbp
new file mode 100644 (file)
index 0000000..b5e5827
--- /dev/null
@@ -0,0 +1,34 @@
+Type=Exe\r
+Form=Vbzipfrm.frm\r
+Module=VBZipBas; VBZipBas.bas\r
+IconForm="Form1"\r
+Startup="Form1"\r
+HelpFile=""\r
+Title="VBZIP"\r
+ExeName32="VBZIP.exe"\r
+Path32="..\..\.."\r
+Command32=""\r
+Name="Project1"\r
+HelpContextID="0"\r
+CompatibleMode="0"\r
+MajorVer=1\r
+MinorVer=0\r
+RevisionVer=0\r
+AutoIncrementVer=0\r
+ServerSupportFiles=0\r
+VersionCompanyName="Mike"\r
+CompilationType=-1\r
+OptimizationType=0\r
+FavorPentiumPro(tm)=0\r
+CodeViewDebugInfo=0\r
+NoAliasing=0\r
+BoundsCheck=0\r
+OverflowCheck=0\r
+FlPointCheck=0\r
+FDIVCheck=0\r
+UnroundedFP=0\r
+StartMode=0\r
+Unattended=0\r
+Retained=0\r
+ThreadPerObject=0\r
+MaxNumberOfThreads=1\r
diff --git a/windll/vb/Vbzipfrm.frm b/windll/vb/Vbzipfrm.frm
new file mode 100644 (file)
index 0000000..de323cd
--- /dev/null
@@ -0,0 +1,130 @@
+VERSION 5.00\r
+Begin VB.Form Form1 \r
+   AutoRedraw      =   -1  'True\r
+   Caption         =   "Form1"\r
+   ClientHeight    =   3150\r
+   ClientLeft      =   60\r
+   ClientTop       =   345\r
+   ClientWidth     =   6570\r
+   BeginProperty Font \r
+      Name            =   "MS Sans Serif"\r
+      Size            =   9.75\r
+      Charset         =   0\r
+      Weight          =   700\r
+      Underline       =   0   'False\r
+      Italic          =   0   'False\r
+      Strikethrough   =   0   'False\r
+   EndProperty\r
+   LinkTopic       =   "Form1"\r
+   ScaleHeight     =   3150\r
+   ScaleWidth      =   6570\r
+   StartUpPosition =   1  'CenterOwner\r
+End\r
+Attribute VB_Name = "Form1"\r
+Attribute VB_GlobalNameSpace = False\r
+Attribute VB_Creatable = False\r
+Attribute VB_PredeclaredId = True\r
+Attribute VB_Exposed = False\r
+\r
+Option Explicit\r
+\r
+'---------------------------------------------------------------\r
+'-- Please Do Not Remove These Comments!!!\r
+'---------------------------------------------------------------\r
+'-- Sample VB 5 code to drive zip32.dll\r
+'-- Contributed to the Info-ZIP project by Mike Le Voi\r
+'--\r
+'-- Contact me at: mlevoi@modemss.brisnet.org.au\r
+'--\r
+'-- Visit my home page at: http://modemss.brisnet.org.au/~mlevoi\r
+'--\r
+'-- Use this code at your own risk. Nothing implied or warranted\r
+'-- to work on your machine :-)\r
+'---------------------------------------------------------------\r
+'--\r
+'-- The Source Code Is Freely Available From Info-ZIP At:\r
+'-- http://www.cdrom.com/pub/infozip/infozip.html\r
+'--\r
+'-- A Very Special Thanks To Mr. Mike Le Voi\r
+'-- And Mr. Mike White Of The Info-ZIP project\r
+'-- For Letting Me Use And Modify His Orginal\r
+'-- Visual Basic 5.0 Code! Thank You Mike Le Voi.\r
+'---------------------------------------------------------------\r
+'--\r
+'-- Contributed To The Info-ZIP Project By Raymond L. King\r
+'-- Modified June 21, 1998\r
+'-- By Raymond L. King\r
+'-- Custom Software Designers\r
+'--\r
+'-- Contact Me At: king@ntplx.net\r
+'-- ICQ 434355\r
+'-- Or Visit Our Home Page At: http://www.ntplx.net/~king\r
+'--\r
+'---------------------------------------------------------------\r
+' This is the original VB example (with some changes) for use\r
+' with Zip32.dll (Zip 2.31) but not Zip32z64.dll (Zip 3.0).\r
+'\r
+' Minor changes to use current directory and VB project files\r
+' for the example and to turn off encryption.\r
+'\r
+' The VB example provided with Zip 3.0 is more extensive.  Even\r
+' if you plan to use the updated zip32.dll instead of the new\r
+' zip32z64.dll (Zip 3.0), there may be some things you might find\r
+' useful in the VB example there.\r
+'\r
+' 2/27/2005 Ed Gordon\r
+'---------------------------------------------------------------\r
+\r
+Private Sub Form_Click()\r
+\r
+  Dim retcode As Integer  ' For Return Code From ZIP32.DLL\r
+\r
+  Cls\r
+\r
+  '-- Set Options - Only The Common Ones Are Shown Here\r
+  '-- These Must Be Set Before Calling The VBZip32 Function\r
+  zDate = vbNullString\r
+  'zDate = "2005-1-31"\r
+  'zExcludeDate = 1\r
+  'zIncludeDate = 0\r
+  zJunkDir = 0     ' 1 = Throw Away Path Names\r
+  zRecurse = 0     ' 1 = Recurse -r 2 = Recurse -R 2 = Most Useful :)\r
+  zUpdate = 0      ' 1 = Update Only If Newer\r
+  zFreshen = 0     ' 1 = Freshen - Overwrite Only\r
+  zLevel = Asc(9)  ' Compression Level (0 - 9)\r
+  zEncrypt = 0     ' Encryption = 1 For Password Else 0\r
+  zComment = 0     ' Comment = 1 if required\r
+\r
+  '-- Select Some Files - Wildcards Are Supported\r
+  '-- Change The Paths Here To Your Directory\r
+  '-- And Files!!!\r
+  ' Change ZIPnames in VBZipBas.bas if need more than 100 files\r
+  zArgc = 2           ' Number Of Elements Of mynames Array\r
+  zZipFileName = "MyFirst.zip"\r
+  zZipFileNames.zFiles(0) = "vbzipfrm.frm"\r
+  zZipFileNames.zFiles(1) = "vbzip.vbp"\r
+  zRootDir = ""    ' This Affects The Stored Path Name\r
+  \r
+  ' Older versions of Zip32.dll do not handle setting\r
+  ' zRootDir to anything other than "".  If you need to\r
+  ' change root directory an alternative is to just change\r
+  ' directory.  This requires Zip32.dll to be on the command\r
+  ' path.  This should be fixed in Zip 2.31.  1/31/2005 EG\r
+\r
+  ' ChDir "a"\r
+\r
+  '-- Go Zip Them Up!\r
+  retcode = VBZip32\r
+\r
+  '-- Display The Returned Code Or Error!\r
+  Print "Return code:" & Str(retcode)\r
+\r
+End Sub\r
+\r
+Private Sub Form_Load()\r
+\r
+  Me.Show\r
+\r
+  Print "Click me!"\r
+\r
+End Sub\r
diff --git a/windll/vb/readmeVB.txt b/windll/vb/readmeVB.txt
new file mode 100644 (file)
index 0000000..f1fc19f
--- /dev/null
@@ -0,0 +1,35 @@
+On Windows open this file in WordPad.
+
+Contents of the "windll/vb" sub-archive
+
+This directory contains a Visual Basic project example for
+using the zip32.dll library.  This project updates the Zip 2.3 VB
+project example and includes some bug fixes and many additional notes
+but is still compatible with zip32.dll.  See the comments in the form
+and project files for details.  It has been tested on VB 5 and VB6.
+
+Zip 2.31 itself has bug fixes as well, including some related to the
+dll, and you should now use a version of zip32.dll from that.  This
+dll includes a fix for the VB dll bug where Date, szRootDir, and
+szTempDir were not passed in correctly and setting these to anything
+but NULL could impact the dll and maybe crash it.  You can tell which
+version you have by right clicking on zip32.dll in a file listing,
+looking at properties, selecting the Version tab, and verifying the
+Product Version is at least 2.31.
+
+A new dll is available as part of the new Zip 3.0 beta.  A new
+VB project included with that release now supports Zip64 and large
+files and it fixes even more bugs but is not backward compatible
+with zip32.dll.  You will need the new dll zip32z64.dll to use that
+VB project, which can be compiled from the Zip 3.0 source.  See
+windll/VBz64 in that release for details.
+
+Note that the files may saved in unix format with carriage returns
+stripped.  These must be restored before the project can be successfully
+used.  This can be done by using the -a option to unzip.  Another way to
+do this is to open each file in WordPad, select and cut a line, paste
+the line back, and save the file.  This will force WordPad to format
+the entire file.
+
+Ed Gordon
+3/1/2005
diff --git a/windll/visualc/dll/zip32.dsp b/windll/visualc/dll/zip32.dsp
new file mode 100644 (file)
index 0000000..91d01d8
--- /dev/null
@@ -0,0 +1,168 @@
+# Microsoft Developer Studio Project File - Name="zip32" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
+\r
+CFG=zip32 - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "zip32.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "zip32.mak" CFG="zip32 - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "zip32 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE "zip32 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+MTL=midl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "zip32 - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "..\Release\app"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "_WINDOWS" /D "WIN32" /YX /FD /c\r
+# ADD CPP /nologo /Zp4 /MT /W3 /GX /O2 /I "..\..\.." /I "..\..\..\WINDLL" /I "..\..\..\WIN32" /D "NDEBUG" /D "_WINDOWS" /D "WIN32" /D "NO_ASM" /D "WINDLL" /D "MSDOS" /D "USE_ZIPMAIN" /YX /FD /c\r
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32\r
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32\r
+# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG" /d "WIN32"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386\r
+# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386\r
+\r
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "..\Debug\app"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "_WINDOWS" /D "WIN32" /YX /FD /c\r
+# ADD CPP /nologo /Zp4 /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\ZIP" /I "..\..\..\WINDLL" /I "..\..\..\WIN32" /D "_DEBUG" /D "_WINDOWS" /D "WIN32" /D "NO_ASM" /D "WINDLL" /D "MSDOS" /D "USE_ZIPMAIN" /FR /YX /FD /c\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32\r
+# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG" /d "WIN32"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept\r
+# SUBTRACT LINK32 /map\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "zip32 - Win32 Release"\r
+# Name "zip32 - Win32 Debug"\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\api.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\crc32.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\crctab.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\crypt.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\deflate.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\fileio.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\globals.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\win32\nt.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\trees.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\ttyio.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\util.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\win32\win32.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\win32\win32zip.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\windll\windll.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\windll\windll.rc\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\windll\windll32.def\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\zip.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\zipfile.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\zipup.c\r
+# End Source File\r
+# End Target\r
+# End Project\r
diff --git a/windll/visualc/dll/zip32.dsw b/windll/visualc/dll/zip32.dsw
new file mode 100644 (file)
index 0000000..cb9248d
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "zip32"=.\zip32.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/windll/visualc/dll/zip32.mak b/windll/visualc/dll/zip32.mak
new file mode 100644 (file)
index 0000000..c3e33a6
--- /dev/null
@@ -0,0 +1,858 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on zip32.dsp
+!IF "$(CFG)" == ""
+CFG=zip32 - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to zip32 - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "zip32 - Win32 Release" && "$(CFG)" != "zip32 - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "zip32.mak" CFG="zip32 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zip32 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "zip32 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+OUTDIR=.\..\Release\app
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\..\Release\app
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\zip32.dll"
+
+!ELSE
+
+ALL : "$(OUTDIR)\zip32.dll"
+
+!ENDIF
+
+CLEAN :
+       -@erase "$(INTDIR)\api.obj"
+       -@erase "$(INTDIR)\crc32.obj"
+       -@erase "$(INTDIR)\crctab.obj"
+       -@erase "$(INTDIR)\crypt.obj"
+       -@erase "$(INTDIR)\deflate.obj"
+       -@erase "$(INTDIR)\fileio.obj"
+       -@erase "$(INTDIR)\globals.obj"
+       -@erase "$(INTDIR)\nt.obj"
+       -@erase "$(INTDIR)\trees.obj"
+       -@erase "$(INTDIR)\ttyio.obj"
+       -@erase "$(INTDIR)\util.obj"
+       -@erase "$(INTDIR)\vc50.idb"
+       -@erase "$(INTDIR)\win32.obj"
+       -@erase "$(INTDIR)\win32zip.obj"
+       -@erase "$(INTDIR)\windll.obj"
+       -@erase "$(INTDIR)\windll.res"
+       -@erase "$(INTDIR)\zip.obj"
+       -@erase "$(INTDIR)\zipfile.obj"
+       -@erase "$(INTDIR)\zipup.obj"
+       -@erase "$(OUTDIR)\zip32.dll"
+       -@erase "$(OUTDIR)\zip32.exp"
+       -@erase "$(OUTDIR)\zip32.lib"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+"$(INTDIR)" :
+    if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /Zp4 /MT /W3 /GX /O2 /I "..\..\.." /I "..\..\..\WINDLL" /I "..\..\..\WIN32" /D "NDEBUG" /D "_WINDOWS" /D "WIN32" /D "NO_ASM" /D "WINDLL" /D\
+ "MSDOS" /D "USE_ZIPMAIN" /Fp"$(INTDIR)\zip32.pch" /YX\
+ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+CPP_OBJS=.\Release/
+CPP_SBRS=.
+
+.c{$(CPP_OBJS)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_OBJS)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_OBJS)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.c{$(CPP_SBRS)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_SBRS)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_SBRS)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\windll.res" /d "NDEBUG" /d "WIN32"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\zip32.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib advapi32.lib\
+ /nologo /subsystem:windows /dll /incremental:no\
+ /pdb:"$(OUTDIR)\zip32.pdb" /machine:I386\
+ /def:"..\..\..\windll\windll32.def" /out:"$(OUTDIR)\zip32.dll"\
+ /implib:"$(OUTDIR)\zip32.lib"
+DEF_FILE= \
+       "..\..\..\windll\windll32.def"
+LINK32_OBJS= \
+       "$(INTDIR)\api.obj" \
+       "$(INTDIR)\crc32.obj" \
+       "$(INTDIR)\crctab.obj" \
+       "$(INTDIR)\crypt.obj" \
+       "$(INTDIR)\deflate.obj" \
+       "$(INTDIR)\fileio.obj" \
+       "$(INTDIR)\globals.obj" \
+       "$(INTDIR)\nt.obj" \
+       "$(INTDIR)\trees.obj" \
+       "$(INTDIR)\ttyio.obj" \
+       "$(INTDIR)\util.obj" \
+       "$(INTDIR)\win32.obj" \
+       "$(INTDIR)\win32zip.obj" \
+       "$(INTDIR)\windll.obj" \
+       "$(INTDIR)\windll.res" \
+       "$(INTDIR)\zip.obj" \
+       "$(INTDIR)\zipfile.obj" \
+       "$(INTDIR)\zipup.obj"
+
+"$(OUTDIR)\zip32.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+OUTDIR=.\..\Debug\app
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\..\Debug\app
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\zip32.dll"
+
+!ELSE
+
+ALL : "$(OUTDIR)\zip32.dll"
+
+!ENDIF
+
+CLEAN :
+       -@erase "$(INTDIR)\api.obj"
+       -@erase "$(INTDIR)\crc32.obj"
+       -@erase "$(INTDIR)\crctab.obj"
+       -@erase "$(INTDIR)\crypt.obj"
+       -@erase "$(INTDIR)\deflate.obj"
+       -@erase "$(INTDIR)\fileio.obj"
+       -@erase "$(INTDIR)\globals.obj"
+       -@erase "$(INTDIR)\nt.obj"
+       -@erase "$(INTDIR)\trees.obj"
+       -@erase "$(INTDIR)\ttyio.obj"
+       -@erase "$(INTDIR)\util.obj"
+       -@erase "$(INTDIR)\vc50.idb"
+       -@erase "$(INTDIR)\vc50.pdb"
+       -@erase "$(INTDIR)\win32.obj"
+       -@erase "$(INTDIR)\win32zip.obj"
+       -@erase "$(INTDIR)\windll.obj"
+       -@erase "$(INTDIR)\windll.res"
+       -@erase "$(INTDIR)\zip.obj"
+       -@erase "$(INTDIR)\zipfile.obj"
+       -@erase "$(INTDIR)\zipup.obj"
+       -@erase "$(OUTDIR)\zip32.dll"
+       -@erase "$(OUTDIR)\zip32.exp"
+       -@erase "$(OUTDIR)\zip32.ilk"
+       -@erase "$(OUTDIR)\zip32.lib"
+       -@erase "$(OUTDIR)\zip32.pdb"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+"$(INTDIR)" :
+    if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /Zp4 /MTd /W3 /Gm /GX /Zi /Od /I "..\..\.." /I\
+ "..\..\..\WINDLL" /I "..\..\..\WIN32" /D "_DEBUG" /D "_WINDOWS" /D "WIN32" /D\
+ "NO_ASM" /D "WINDLL" /D "MSDOS" /D "USE_ZIPMAIN"\
+ /Fp"$(INTDIR)\zip32.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+CPP_OBJS=.\Debug/
+CPP_SBRS=.
+
+.c{$(CPP_OBJS)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_OBJS)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_OBJS)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.c{$(CPP_SBRS)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_SBRS)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_SBRS)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+RSC=rc.exe
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\windll.res" /d "_DEBUG" /d "WIN32"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\zip32.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib advapi32.lib\
+ /nologo /subsystem:windows /dll /incremental:yes\
+ /pdb:"$(OUTDIR)\zip32.pdb" /debug /machine:I386\
+ /def:"..\..\..\windll\windll32.def" /out:"$(OUTDIR)\zip32.dll"\
+ /implib:"$(OUTDIR)\zip32.lib" /pdbtype:sept
+DEF_FILE= \
+       "..\..\..\windll\windll32.def"
+LINK32_OBJS= \
+       "$(INTDIR)\api.obj" \
+       "$(INTDIR)\crc32.obj" \
+       "$(INTDIR)\crctab.obj" \
+       "$(INTDIR)\crypt.obj" \
+       "$(INTDIR)\deflate.obj" \
+       "$(INTDIR)\fileio.obj" \
+       "$(INTDIR)\globals.obj" \
+       "$(INTDIR)\nt.obj" \
+       "$(INTDIR)\trees.obj" \
+       "$(INTDIR)\ttyio.obj" \
+       "$(INTDIR)\util.obj" \
+       "$(INTDIR)\win32.obj" \
+       "$(INTDIR)\win32zip.obj" \
+       "$(INTDIR)\windll.obj" \
+       "$(INTDIR)\windll.res" \
+       "$(INTDIR)\zip.obj" \
+       "$(INTDIR)\zipfile.obj" \
+       "$(INTDIR)\zipup.obj"
+
+"$(OUTDIR)\zip32.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(CFG)" == "zip32 - Win32 Release" || "$(CFG)" == "zip32 - Win32 Debug"
+SOURCE=D:\wiz\zip\api.c
+DEP_CPP_API_C=\
+       "..\..\..\api.h"\
+       "..\..\..\crypt.h"\
+       "..\..\..\revision.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\windll\structs.h"\
+       "..\..\..\windll\windll.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\api.obj" : $(SOURCE) $(DEP_CPP_API_C) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=D:\wiz\zip\crc32.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_CRC32=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\crc32.obj" : $(SOURCE) $(DEP_CPP_CRC32) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_CRC32=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\crc32.obj" : $(SOURCE) $(DEP_CPP_CRC32) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\crctab.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_CRCTA=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\crctab.obj" : $(SOURCE) $(DEP_CPP_CRCTA) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_CRCTA=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\crctab.obj" : $(SOURCE) $(DEP_CPP_CRCTA) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\crypt.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_CRYPT=\
+       "..\..\..\api.h"\
+       "..\..\..\crypt.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\ttyio.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\crypt.obj" : $(SOURCE) $(DEP_CPP_CRYPT) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_CRYPT=\
+       "..\..\..\api.h"\
+       "..\..\..\crypt.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\ttyio.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\crypt.obj" : $(SOURCE) $(DEP_CPP_CRYPT) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\deflate.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_DEFLA=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\deflate.obj" : $(SOURCE) $(DEP_CPP_DEFLA) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_DEFLA=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\deflate.obj" : $(SOURCE) $(DEP_CPP_DEFLA) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\fileio.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_FILEI=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\fileio.obj" : $(SOURCE) $(DEP_CPP_FILEI) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_FILEI=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\fileio.obj" : $(SOURCE) $(DEP_CPP_FILEI) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\globals.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_GLOBA=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\globals.obj" : $(SOURCE) $(DEP_CPP_GLOBA) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_GLOBA=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\globals.obj" : $(SOURCE) $(DEP_CPP_GLOBA) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\Win32\nt.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_NT_C10=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\nt.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\nt.obj" : $(SOURCE) $(DEP_CPP_NT_C10) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_NT_C10=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\nt.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\nt.obj" : $(SOURCE) $(DEP_CPP_NT_C10) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\trees.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_TREES=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\trees.obj" : $(SOURCE) $(DEP_CPP_TREES) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_TREES=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\trees.obj" : $(SOURCE) $(DEP_CPP_TREES) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\ttyio.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_TTYIO=\
+       "..\..\..\api.h"\
+       "..\..\..\crypt.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\ttyio.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\ttyio.obj" : $(SOURCE) $(DEP_CPP_TTYIO) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_TTYIO=\
+       "..\..\..\api.h"\
+       "..\..\..\crypt.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\ttyio.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\ttyio.obj" : $(SOURCE) $(DEP_CPP_TTYIO) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\util.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_UTIL_=\
+       "..\..\..\api.h"\
+       "..\..\..\ebcdic.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\util.obj" : $(SOURCE) $(DEP_CPP_UTIL_) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_UTIL_=\
+       "..\..\..\api.h"\
+       "..\..\..\ebcdic.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\util.obj" : $(SOURCE) $(DEP_CPP_UTIL_) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\Win32\win32.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_WIN32=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\win32\win32zip.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\win32.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_WIN32=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\win32\win32zip.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\win32.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\Win32\win32zip.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_WIN32Z=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\nt.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\win32\win32zip.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\win32zip.obj" : $(SOURCE) $(DEP_CPP_WIN32Z) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_WIN32Z=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\nt.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\win32\win32zip.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\win32zip.obj" : $(SOURCE) $(DEP_CPP_WIN32Z) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\windll\windll.c
+DEP_CPP_WINDL=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\windll\structs.h"\
+       "..\..\..\windll\windll.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\windll.obj" : $(SOURCE) $(DEP_CPP_WINDL) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=D:\wiz\zip\windll\windll.rc
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+
+"$(INTDIR)\windll.res" : $(SOURCE) "$(INTDIR)"
+       $(RSC) /l 0x409 /fo"$(INTDIR)\windll.res" /i "\wiz\zip\windll" /d "NDEBUG" /d\
+ "WIN32" $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+
+"$(INTDIR)\windll.res" : $(SOURCE) "$(INTDIR)"
+       $(RSC) /l 0x409 /fo"$(INTDIR)\windll.res" /i "\wiz\zip\windll" /d "_DEBUG" /d\
+ "WIN32" $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\zip.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_ZIP_C=\
+       "..\..\..\api.h"\
+       "..\..\..\crypt.h"\
+       "..\..\..\revision.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\ttyio.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\windll\structs.h"\
+       "..\..\..\windll\windll.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\zip.obj" : $(SOURCE) $(DEP_CPP_ZIP_C) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_ZIP_C=\
+       "..\..\..\api.h"\
+       "..\..\..\crypt.h"\
+       "..\..\..\revision.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\ttyio.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\windll\structs.h"\
+       "..\..\..\windll\windll.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\zip.obj" : $(SOURCE) $(DEP_CPP_ZIP_C) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\zipfile.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_ZIPFI=\
+       "..\..\..\api.h"\
+       "..\..\..\revision.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\zipfile.obj" : $(SOURCE) $(DEP_CPP_ZIPFI) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_ZIPFI=\
+       "..\..\..\api.h"\
+       "..\..\..\revision.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\zipfile.obj" : $(SOURCE) $(DEP_CPP_ZIPFI) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=D:\wiz\zip\zipup.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_ZIPUP=\
+       "..\..\..\api.h"\
+       "..\..\..\crypt.h"\
+       "..\..\..\revision.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\win32\zipup.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\zipup.obj" : $(SOURCE) $(DEP_CPP_ZIPUP) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_ZIPUP=\
+       "..\..\..\api.h"\
+       "..\..\..\crypt.h"\
+       "..\..\..\revision.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\win32\zipup.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\zipup.obj" : $(SOURCE) $(DEP_CPP_ZIPUP) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
diff --git a/windll/visualc/lib/zip32.dsp b/windll/visualc/lib/zip32.dsp
new file mode 100644 (file)
index 0000000..d23896c
--- /dev/null
@@ -0,0 +1,162 @@
+# Microsoft Developer Studio Project File - Name="zip32" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Static Library" 0x0104\r
+\r
+CFG=zip32 - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "zip32.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "zip32.mak" CFG="zip32 - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "zip32 - Win32 Release" (based on "Win32 (x86) Static Library")\r
+!MESSAGE "zip32 - Win32 Debug" (based on "Win32 (x86) Static Library")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "zip32 - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "..\Release\libs"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "_WINDOWS" /D "WIN32" /YX /FD /c\r
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\.." /I "..\..\..\win32" /I "..\..\..\windll" /D "NDEBUG" /D "_WINDOWS" /D "WIN32" /D "NO_ASM" /D "WINDLL" /D "MSDOS" /D "USE_ZIPMAIN" /D "ZIPLIB" /FD /c\r
+# SUBTRACT CPP /YX\r
+# ADD BASE RSC /l 0x409\r
+# ADD RSC /l 0x409\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LIB32=link.exe -lib\r
+# ADD BASE LIB32 /nologo\r
+# ADD LIB32 /nologo\r
+\r
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug"\r
+# PROP BASE Intermediate_Dir "Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "..\Debug\libs"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "_DEBUG" /D "_WINDOWS" /D "WIN32" /YX /FD /c\r
+# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\.." /I "..\..\..\win32" /I "..\..\..\windll" /D "_DEBUG" /D "_WINDOWS" /D "WIN32" /D "NO_ASM" /D "WINDLL" /D "MSDOS" /D "USE_ZIPMAIN" /D "ZIPLIB" /FD /c\r
+# SUBTRACT CPP /YX\r
+# ADD BASE RSC /l 0x409\r
+# ADD RSC /l 0x409\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LIB32=link.exe -lib\r
+# ADD BASE LIB32 /nologo\r
+# ADD LIB32 /nologo\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "zip32 - Win32 Release"\r
+# Name "zip32 - Win32 Debug"\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\api.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\crc32.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\crctab.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\crypt.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\deflate.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\fileio.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\globals.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\win32\nt.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\trees.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\ttyio.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\util.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\win32\win32.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\win32\win32zip.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\windll\windll.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\windll\windll.rc\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\zip.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\zipfile.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\windll\ziplib.def\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\zipup.c\r
+# End Source File\r
+# End Target\r
+# End Project\r
diff --git a/windll/visualc/lib/zip32.dsw b/windll/visualc/lib/zip32.dsw
new file mode 100644 (file)
index 0000000..cb9248d
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "zip32"=.\zip32.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/windll/visualc/lib/zip32.mak b/windll/visualc/lib/zip32.mak
new file mode 100644 (file)
index 0000000..4ea7923
--- /dev/null
@@ -0,0 +1,586 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on zip32.dsp
+!IF "$(CFG)" == ""
+CFG=zip32 - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to zip32 - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "zip32 - Win32 Release" && "$(CFG)" != "zip32 - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "zip32.mak" CFG="zip32 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zip32 - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "zip32 - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+OUTDIR=.\..\Release\libs
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\..\Release\libs
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\zip32.lib"
+
+!ELSE
+
+ALL : "$(OUTDIR)\zip32.lib"
+
+!ENDIF
+
+CLEAN :
+       -@erase "$(INTDIR)\api.obj"
+       -@erase "$(INTDIR)\crc32.obj"
+       -@erase "$(INTDIR)\crctab.obj"
+       -@erase "$(INTDIR)\crypt.obj"
+       -@erase "$(INTDIR)\deflate.obj"
+       -@erase "$(INTDIR)\fileio.obj"
+       -@erase "$(INTDIR)\globals.obj"
+       -@erase "$(INTDIR)\nt.obj"
+       -@erase "$(INTDIR)\trees.obj"
+       -@erase "$(INTDIR)\ttyio.obj"
+       -@erase "$(INTDIR)\util.obj"
+       -@erase "$(INTDIR)\vc50.idb"
+       -@erase "$(INTDIR)\win32.obj"
+       -@erase "$(INTDIR)\win32zip.obj"
+       -@erase "$(INTDIR)\windll.obj"
+       -@erase "$(INTDIR)\zip.obj"
+       -@erase "$(INTDIR)\zipfile.obj"
+       -@erase "$(INTDIR)\zipup.obj"
+       -@erase "$(OUTDIR)\zip32.lib"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+"$(INTDIR)" :
+    if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "..\..\.." /I "..\..\..\WIN32" /I\
+ "..\..\..\WINDLL" /D "NDEBUG" /D "_WINDOWS" /D "WIN32" /D "NO_ASM" /D\
+ "WINDLL" /D "MSDOS" /D "USE_ZIPMAIN" /D "ZIPLIB"\
+ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+CPP_OBJS=.\Release/
+CPP_SBRS=.
+
+.c{$(CPP_OBJS)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_OBJS)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_OBJS)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.c{$(CPP_SBRS)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_SBRS)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_SBRS)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\zip32.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\zip32.lib"
+LIB32_OBJS= \
+       "$(INTDIR)\api.obj" \
+       "$(INTDIR)\crc32.obj" \
+       "$(INTDIR)\crctab.obj" \
+       "$(INTDIR)\crypt.obj" \
+       "$(INTDIR)\deflate.obj" \
+       "$(INTDIR)\fileio.obj" \
+       "$(INTDIR)\globals.obj" \
+       "$(INTDIR)\nt.obj" \
+       "$(INTDIR)\trees.obj" \
+       "$(INTDIR)\ttyio.obj" \
+       "$(INTDIR)\util.obj" \
+       "$(INTDIR)\win32.obj" \
+       "$(INTDIR)\win32zip.obj" \
+       "$(INTDIR)\windll.obj" \
+       "$(INTDIR)\zip.obj" \
+       "$(INTDIR)\zipfile.obj" \
+       "$(INTDIR)\zipup.obj"
+
+"$(OUTDIR)\zip32.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+    $(LIB32) @<<
+  $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+OUTDIR=.\..\Debug\libs
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\..\Debug\libs
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "$(OUTDIR)\zip32.lib"
+
+!ELSE
+
+ALL : "$(OUTDIR)\zip32.lib"
+
+!ENDIF
+
+CLEAN :
+       -@erase "$(INTDIR)\api.obj"
+       -@erase "$(INTDIR)\crc32.obj"
+       -@erase "$(INTDIR)\crctab.obj"
+       -@erase "$(INTDIR)\crypt.obj"
+       -@erase "$(INTDIR)\deflate.obj"
+       -@erase "$(INTDIR)\fileio.obj"
+       -@erase "$(INTDIR)\globals.obj"
+       -@erase "$(INTDIR)\nt.obj"
+       -@erase "$(INTDIR)\trees.obj"
+       -@erase "$(INTDIR)\ttyio.obj"
+       -@erase "$(INTDIR)\util.obj"
+       -@erase "$(INTDIR)\vc50.idb"
+       -@erase "$(INTDIR)\win32.obj"
+       -@erase "$(INTDIR)\win32zip.obj"
+       -@erase "$(INTDIR)\windll.obj"
+       -@erase "$(INTDIR)\zip.obj"
+       -@erase "$(INTDIR)\zipfile.obj"
+       -@erase "$(INTDIR)\zipup.obj"
+       -@erase "$(OUTDIR)\zip32.lib"
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+"$(INTDIR)" :
+    if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MLd /W3 /GX /Z7 /Od /I "..\..\.." /I "..\..\..\WIN32" /I\
+ "..\..\..\WINDLL" /D "_DEBUG" /D "_WINDOWS" /D "WIN32" /D "NO_ASM" /D\
+ "WINDLL" /D "MSDOS" /D "USE_ZIPMAIN" /D "ZIPLIB"\
+ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+CPP_OBJS=.\Debug/
+CPP_SBRS=.
+
+.c{$(CPP_OBJS)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_OBJS)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_OBJS)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.c{$(CPP_SBRS)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cpp{$(CPP_SBRS)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+.cxx{$(CPP_SBRS)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $<
+<<
+
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\zip32.bsc"
+BSC32_SBRS= \
+
+LIB32=link.exe -lib
+LIB32_FLAGS=/nologo /out:"$(OUTDIR)\zip32.lib"
+LIB32_OBJS= \
+       "$(INTDIR)\api.obj" \
+       "$(INTDIR)\crc32.obj" \
+       "$(INTDIR)\crctab.obj" \
+       "$(INTDIR)\crypt.obj" \
+       "$(INTDIR)\deflate.obj" \
+       "$(INTDIR)\fileio.obj" \
+       "$(INTDIR)\globals.obj" \
+       "$(INTDIR)\nt.obj" \
+       "$(INTDIR)\trees.obj" \
+       "$(INTDIR)\ttyio.obj" \
+       "$(INTDIR)\util.obj" \
+       "$(INTDIR)\win32.obj" \
+       "$(INTDIR)\win32zip.obj" \
+       "$(INTDIR)\windll.obj" \
+       "$(INTDIR)\zip.obj" \
+       "$(INTDIR)\zipfile.obj" \
+       "$(INTDIR)\zipup.obj"
+
+"$(OUTDIR)\zip32.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
+    $(LIB32) @<<
+  $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
+<<
+
+!ENDIF
+
+
+!IF "$(CFG)" == "zip32 - Win32 Release" || "$(CFG)" == "zip32 - Win32 Debug"
+SOURCE=..\..\..\api.c
+DEP_CPP_API_C=\
+       "..\..\..\api.h"\
+       "..\..\..\crypt.h"\
+       "..\..\..\revision.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\windll\structs.h"\
+       "..\..\..\windll\windll.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\api.obj" : $(SOURCE) $(DEP_CPP_API_C) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\..\crc32.c
+DEP_CPP_CRC32=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\crc32.obj" : $(SOURCE) $(DEP_CPP_CRC32) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\..\crctab.c
+DEP_CPP_CRCTA=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\crctab.obj" : $(SOURCE) $(DEP_CPP_CRCTA) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\..\crypt.c
+DEP_CPP_CRYPT=\
+       "..\..\..\api.h"\
+       "..\..\..\crypt.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\ttyio.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\crypt.obj" : $(SOURCE) $(DEP_CPP_CRYPT) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\..\deflate.c
+DEP_CPP_DEFLA=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\deflate.obj" : $(SOURCE) $(DEP_CPP_DEFLA) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\..\fileio.c
+DEP_CPP_FILEI=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\fileio.obj" : $(SOURCE) $(DEP_CPP_FILEI) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\..\globals.c
+DEP_CPP_GLOBA=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\globals.obj" : $(SOURCE) $(DEP_CPP_GLOBA) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\..\Win32\nt.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_NT_C10=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\nt.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\nt.obj" : $(SOURCE) $(DEP_CPP_NT_C10) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_NT_C10=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\nt.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\nt.obj" : $(SOURCE) $(DEP_CPP_NT_C10) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\..\..\trees.c
+DEP_CPP_TREES=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\trees.obj" : $(SOURCE) $(DEP_CPP_TREES) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\..\ttyio.c
+DEP_CPP_TTYIO=\
+       "..\..\..\api.h"\
+       "..\..\..\crypt.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\ttyio.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\ttyio.obj" : $(SOURCE) $(DEP_CPP_TTYIO) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\..\util.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_UTIL_=\
+       "..\..\..\api.h"\
+       "..\..\..\ebcdic.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\util.obj" : $(SOURCE) $(DEP_CPP_UTIL_) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_UTIL_=\
+       "..\..\..\api.h"\
+       "..\..\..\ebcdic.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\util.obj" : $(SOURCE) $(DEP_CPP_UTIL_) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\..\..\Win32\win32.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_WIN32=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\win32\win32zip.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\win32.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_WIN32=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\win32\win32zip.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\win32.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\..\..\Win32\win32zip.c
+
+!IF  "$(CFG)" == "zip32 - Win32 Release"
+
+DEP_CPP_WIN32Z=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\nt.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\win32\win32zip.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\win32zip.obj" : $(SOURCE) $(DEP_CPP_WIN32Z) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "zip32 - Win32 Debug"
+
+DEP_CPP_WIN32Z=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\nt.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\win32\win32zip.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\win32zip.obj" : $(SOURCE) $(DEP_CPP_WIN32Z) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\..\..\windll\windll.c
+DEP_CPP_WINDL=\
+       "..\..\..\api.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\windll\structs.h"\
+       "..\..\..\windll\windll.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\windll.obj" : $(SOURCE) $(DEP_CPP_WINDL) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\..\zip.c
+DEP_CPP_ZIP_C=\
+       "..\..\..\api.h"\
+       "..\..\..\crypt.h"\
+       "..\..\..\revision.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\ttyio.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\windll\structs.h"\
+       "..\..\..\windll\windll.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\zip.obj" : $(SOURCE) $(DEP_CPP_ZIP_C) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\..\zipfile.c
+DEP_CPP_ZIPFI=\
+       "..\..\..\api.h"\
+       "..\..\..\revision.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\zipfile.obj" : $(SOURCE) $(DEP_CPP_ZIPFI) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE=..\..\..\zipup.c
+DEP_CPP_ZIPUP=\
+       "..\..\..\api.h"\
+       "..\..\..\crypt.h"\
+       "..\..\..\revision.h"\
+       "..\..\..\tailor.h"\
+       "..\..\..\win32\osdep.h"\
+       "..\..\..\win32\zipup.h"\
+       "..\..\..\zip.h"\
+       "..\..\..\ziperr.h"\
+
+
+"$(INTDIR)\zipup.obj" : $(SOURCE) $(DEP_CPP_ZIPUP) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
diff --git a/windll/windll.c b/windll/windll.c
new file mode 100644 (file)
index 0000000..7da7304
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/*
+ *  windll.c by Mike White loosly based on Mark Adler's zip.c
+ */
+#include <windows.h>
+#include <process.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include "../zip.h"
+#include "windll.h"
+
+HINSTANCE hCurrentInst;
+#ifdef ZIPLIB
+/*  DLL Entry Point */
+#ifdef __BORLANDC__
+#pragma argsused
+/* Borland seems to want DllEntryPoint instead of DllMain like MSVC */
+#define DllMain DllEntryPoint
+#endif
+#ifdef WIN32
+BOOL WINAPI DllMain( HINSTANCE hInstance,
+                     DWORD dwReason,
+                     LPVOID plvReserved)
+#else
+int WINAPI LibMain( HINSTANCE hInstance,
+                        WORD wDataSegment,
+                        WORD wHeapSize,
+                        LPSTR lpszCmdLine )
+#endif
+{
+#ifndef WIN32
+/* The startup code for the DLL initializes the local heap(if there is one)
+ with a call to LocalInit which locks the data segment. */
+
+if ( wHeapSize != 0 )
+   {
+   UnlockData( 0 );
+   }
+hCurrentInst = hInstance;
+return 1;   /* Indicate that the DLL was initialized successfully. */
+#else
+BOOL rc = TRUE;
+switch( dwReason )
+   {
+   case DLL_PROCESS_ATTACH:
+      // DLL is loaded. Do your initialization here.
+      // If cannot init, set rc to FALSE.
+      hCurrentInst = hInstance;
+      break;
+
+   case DLL_PROCESS_DETACH:
+      // DLL is unloaded. Do your cleanup here.
+      break;
+   default:
+      break;
+   }
+return rc;
+#endif
+}
+
+#ifdef __BORLANDC__
+#pragma argsused
+#endif
+int FAR PASCAL WEP ( int bSystemExit )
+{
+return 1;
+}
+#endif /* ZIPLIB */
+
+LPSTR szCommentBuf;
+HANDLE hStr;
+
+void comment(unsigned int comlen)
+{
+unsigned int i;
+if (comlen > 65534L)
+   comlen = (unsigned int) 65534L;
+hStr = GlobalAlloc( GPTR, (DWORD)65535L);
+if ( !hStr )
+   {
+   hStr = GlobalAlloc( GPTR, (DWORD) 2);
+   szCommentBuf = GlobalLock(hStr);
+   szCommentBuf[0] = '\0';
+   return;
+   }
+
+szCommentBuf = GlobalLock(hStr);
+if (comlen)
+   {
+   for (i = 0; i < comlen; i++)
+       szCommentBuf[i] = zcomment[i];
+   szCommentBuf[comlen] = '\0';
+   }
+else
+   szCommentBuf[0] = '\0';
+free(zcomment);
+zcomment = malloc(1);
+*zcomment = 0;
+lpZipUserFunctions->comment(szCommentBuf);
+return;
+}
+
+#define STDIO_BUF_SIZE 16384
+
+int __far __cdecl printf(const char *format, ...)
+{
+va_list argptr;
+HANDLE hMemory;
+LPSTR pszBuffer;
+int len;
+
+va_start(argptr, format);
+hMemory = GlobalAlloc(GMEM_MOVEABLE, STDIO_BUF_SIZE);
+WinAssert(hMemory);
+if (!hMemory)
+   {
+   return 0;
+   }
+pszBuffer = (LPSTR)GlobalLock(hMemory);
+WinAssert(pszBuffer);
+len = wvsprintf(pszBuffer, format, argptr);
+va_end(argptr);
+WinAssert(strlen(pszBuffer) < STDIO_BUF_SIZE);
+len = lpZipUserFunctions->print(pszBuffer, len);
+GlobalUnlock(hMemory);
+GlobalFree(hMemory);
+return len;
+}
+
+/* fprintf clone for code in zip.c, etc. */
+int __far __cdecl fprintf(FILE *file, const char *format, ...)
+{
+va_list argptr;
+HANDLE hMemory;
+LPSTR pszBuffer;
+int len;
+
+va_start(argptr, format);
+hMemory = GlobalAlloc(GMEM_MOVEABLE, STDIO_BUF_SIZE);
+WinAssert(hMemory);
+if (!hMemory)
+   {
+   return 0;
+   }
+pszBuffer = GlobalLock(hMemory);
+WinAssert(pszBuffer);
+len = wvsprintf(pszBuffer, format, argptr);
+va_end(argptr);
+WinAssert(strlen(pszBuffer) < STDIO_BUF_SIZE);
+if ((file == stderr) || (file == stdout))
+   {
+   len = lpZipUserFunctions->print(pszBuffer, len);
+   }
+else
+   len = write(fileno(file),(char far *)(pszBuffer), len);
+GlobalUnlock(hMemory);
+GlobalFree(hMemory);
+return len;
+}
+
+void __far __cdecl perror(const char *parm1)
+{
+printf(parm1);
+}
+
+
diff --git a/windll/windll.h b/windll/windll.h
new file mode 100644 (file)
index 0000000..fc20027
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 1999-Oct-05 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+/*
+ WiZ 1.0 header file for zip dll
+*/
+#ifndef _WINDLL_H
+#define _WINDLL_H
+
+#include "structs.h"
+
+#ifndef MSWIN
+#define MSWIN
+#endif
+
+#ifndef USE_ZIPMAIN
+#   define USE_ZIPMAIN
+#endif
+
+#ifndef NDEBUG
+#  define WinAssert(exp) \
+        {\
+        if (!(exp))\
+            {\
+            char szBuffer[40];\
+            sprintf(szBuffer, "File %s, Line %d",\
+                    __FILE__, __LINE__) ;\
+            if (IDABORT == MessageBox((HWND)NULL, szBuffer,\
+                "Assertion Error",\
+                MB_ABORTRETRYIGNORE|MB_ICONSTOP))\
+                    FatalExit(-1);\
+            }\
+        }
+
+#else
+#  define WinAssert(exp)
+#endif
+
+#define cchFilesMax 4096
+
+extern int WINAPI ZpArchive(ZCL C);
+extern HWND hGetFilesDlg;
+extern char szFilesToAdd[80];
+extern char rgszFiles[cchFilesMax];
+BOOL WINAPI CommentBoxProc(HWND hwndDlg, WORD wMessage, WPARAM wParam, LPARAM lParam);
+BOOL PasswordProc(HWND, WORD, WPARAM, LPARAM);
+void CenterDialog(HWND hwndParent, HWND hwndDlg);
+void comment(unsigned int);
+
+extern LPSTR szCommentBuf;
+extern HANDLE hStr;
+extern HWND hWndMain;
+void __far __cdecl perror(const char *);
+
+#endif /* _WINDLL_H */
+
diff --git a/windll/windll.rc b/windll/windll.rc
new file mode 100644 (file)
index 0000000..23adef4
--- /dev/null
@@ -0,0 +1,115 @@
+//Microsoft Developer Studio generated resource script.\r
+//\r
+#include "resource.h"\r
+\r
+#define APSTUDIO_READONLY_SYMBOLS\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 2 resource.\r
+//\r
+#define APSTUDIO_HIDDEN_SYMBOLS\r
+#include "windows.h"\r
+#undef APSTUDIO_HIDDEN_SYMBOLS\r
+#include "zipver.h"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#undef APSTUDIO_READONLY_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.S.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+#ifndef _MAC\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Version\r
+//\r
+\r
+VS_VERSION_INFO VERSIONINFO\r
+ FILEVERSION 1,1,0,0\r
+ PRODUCTVERSION 2,3,1,0\r
+ FILEFLAGSMASK 0x3L\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x1L\r
+#else\r
+ FILEFLAGS 0x0L\r
+#endif\r
+ FILEOS 0x1L\r
+ FILETYPE 0x2L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+    BLOCK "StringFileInfo"\r
+    BEGIN\r
+        BLOCK "040904e4"\r
+        BEGIN\r
+            VALUE "Comments", "\0"\r
+            VALUE "CompanyName", "Info-ZIP\0"\r
+            VALUE "FileDescription", "Info-ZIP's Zip dll\0"\r
+            VALUE "FileVersion", "2.31\0"\r
+            VALUE "InternalName", "Zip32\0"\r
+            VALUE "LegalCopyright", "Info-ZIP 2005\0"\r
+            VALUE "LegalTrademarks", "\0"\r
+            VALUE "OriginalFilename", "ZIP32.DLL\0"\r
+            VALUE "PrivateBuild", "\0"\r
+            VALUE "ProductName", "Info-ZIP's WiZ\0"\r
+            VALUE "ProductVersion", "2.31\0"\r
+            VALUE "SpecialBuild", "\0"\r
+        END\r
+    END\r
+    BLOCK "VarFileInfo"\r
+    BEGIN\r
+        VALUE "Translation", 0x409, 1252\r
+    END\r
+END\r
+\r
+#endif    // !_MAC\r
+\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// TEXTINCLUDE\r
+//\r
+\r
+1 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+    "resource.h\0"\r
+END\r
+\r
+2 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+    "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"\r
+    "#include ""windows.h""\r\n"\r
+    "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"\r
+    "#include ""zipver.h""\r\n"\r
+    "\0"\r
+END\r
+\r
+3 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+    "\r\n"\r
+    "\0"\r
+END\r
+\r
+#endif    // APSTUDIO_INVOKED\r
+\r
+#endif    // English (U.S.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#ifndef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 3 resource.\r
+//\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif    // not APSTUDIO_INVOKED\r
+\r
diff --git a/windll/windll.txt b/windll/windll.txt
new file mode 100644 (file)
index 0000000..2166412
--- /dev/null
@@ -0,0 +1,132 @@
+The code set out below is not intended to be compiled, but is only intended as
+a very simplistic pointer to how to load and call the dll. You will have to
+look in the files referenced below for actual, working code.
+
+There are two entry points that use the structure shown below:
+
+BOOL WINAPI ZpSetOptions(ZPOPT) and
+ZPOPT WINAPI ZpGetOptions(void)
+
+typedef struct {
+LPSTR Date;             /* Date to include after */
+LPSTR szRootDir;        /* Directory to use as base for zipping */
+LPSTR szTempDir;        /* Temporary directory used during zipping */
+BOOL fTemp;             /* Use temporary directory '-b' during zipping */
+BOOL fSuffix;           /* include suffixes (not implemented in WiZ) */
+BOOL fEncrypt;          /* encrypt files */
+BOOL fSystem;           /* include system and hidden files */
+BOOL fVolume;           /* Include volume label */
+BOOL fExtra;            /* Exclude extra attributes */
+BOOL fNoDirEntries;     /* Do not add directory entries */
+BOOL fExcludeDate;      /* Exclude files earlier than specified date */
+BOOL fIncludeDate;      /* Include only files earlier than specified date */
+BOOL fVerbose;          /* Mention oddities in zip file structure */
+BOOL fQuiet;            /* Quiet operation */
+BOOL fCRLF_LF;          /* Translate CR/LF to LF */
+BOOL fLF_CRLF;          /* Translate LF to CR/LF */
+BOOL fJunkDir;          /* Junk directory names */
+BOOL fGrow;             /* Allow appending to a zip file */
+BOOL fForce;            /* Make entries using DOS names (k for Katz) */
+BOOL fMove;             /* Delete files added or updated in zip file */
+BOOL fDeleteEntries;    /* Delete files from zip file */
+BOOL fUpdate;           /* Update zip file--overwrite only if newer */
+BOOL fFreshen;          /* Freshen zip file--overwrite only */
+BOOL fJunkSFX;          /* Junk SFX prefix */
+BOOL fLatestTime;       /* Set zip file time to time of latest file in it */
+BOOL fComment;          /* Put comment in zip file */
+BOOL fOffsets;          /* Update archive offsets for SFX files */
+BOOL fPrivilege;        /* Use privileges (WIN32 only) */
+BOOL fEncryption;       /* TRUE if encryption supported, else FALSE.
+                           this is a read-only flag */
+int  fRecurse;          /* Recurse into subdirectories. 1 => -r, 2 => -R */
+int  fRepair;           /* Repair archive. 1 => -F, 2 => -FF */
+char fLevel;            /* Compression level (0 - 9) */
+} ZPOPT, _far *LPZPOPT;
+
+BOOL WINAPI ZpSetOptions(ZPOPT);
+
+This call will simply set the options in the zip dll until such time as
+another call to this function is made. This must be made before the initial
+call to make or update an archive.
+
+ZPOPT WINAPI ZpGetOptions(void);
+
+The call will return the above structure from the dll, with the fEncryption
+flag set to the appropriate value based on whether encryption is supported
+in this dll or not. It is currently used in WiZ only to determine if
+encryption is actually supported.
+
+The main entry point is ZpArchive(ZCL) where the structure shown below
+is passed to the DLL when it is called.
+
+typedef struct {
+int  argc;              = Count of files to zip
+LPSTR lpszZipFN;        = Archive file name
+char **FNV;             = file names to zip up. Think of this an argv
+} ZCL, _far *LPZCL;
+
+
+For examples of how the actual calls to the dll were set up in WiZ, look in
+the file makezip.c in the WiZ source directory.
+
+For examples of how the actual loading and unloading of the dll's themselves
+was done, look in wizmain.c in the WiZ source directory. Note that WiZ looks
+specifically for a particular version number of the dll, and also expects to
+find the company name to be Info-ZIP. This is to protect from getting different
+versions of the dll loaded, with resulting unknown behavior.
+
+There is a very simplistic example of how to load and call into the dll in
+example.c and example.h. Note that this example does not implement any
+command line switches at all, and is merely intended as a guide for those
+brave enough to enter a new world.
+
+There are four additional (at the moment) entry points:
+
+ZpInit, defined as
+
+int WINAPI ZpInit(ZIPUSERFUNCTIONS far * lpZipUserFunc);
+
+where ZIPUSERFUNCTIONS is defined as below.
+
+ZpVersion, defined as
+
+ZpVer * ZpVersion(void);
+
+where ZpVer is defined as:
+
+typedef struct _ZpVer {
+    ulg structlen;          /* length of the struct being passed */
+    ulg flag;               /* bit 0: is_beta   bit 1: uses_zlib */
+    char *betalevel;        /* e.g., "g BETA" or "" */
+    char *date;             /* e.g., "4 Sep 95" (beta) or "4 September 1995" */
+    char *zlib_version;     /* e.g., "0.95" or NULL */
+    _zip_version_type zip;
+    _zip_version_type os2dll;
+    _zip_version_type windll;
+} ZpVer;
+
+See api.c for exactly what ZpVersion does, but the short version of
+what it does is return the unzip and dll versions in the ZpVer structure.
+The structure typedef's are in api.h
+
+The typedef's for the function pointers in the structure ZIPUSERFUNCTIONS
+are shown immediately below.
+
+typedef int (WINAPI DLLPRNT) (LPSTR, unsigned long);
+typedef int (WINAPI DLLPASSWORD) (LPSTR, int, LPCSTR, LPCSTR);
+typedef int (WINAPI DLLSERVICE) (LPCSTR, unsigned long);
+typedef int (WINAPI DLLCOMMENT) (LPSTR);
+
+typedef struct {
+DLLPRNT *print;          = pointer to application's print function.
+DLLCOMMENT *comment;     = pointer to application's function for processing
+                           comments.
+DLLPASSWORD *password;   = pointer to application's function for processing
+                           passwords.
+DLLSERVICE *ServiceApplication; = Optional callback function for processing
+                                  messages, relaying information.
+} ZIPUSERFUNCTIONS, far * LPZIPUSERFUNCTIONS;
+
+Last revised January 5, 1999.
+
+Mike White
diff --git a/windll/windll16.def b/windll/windll16.def
new file mode 100644 (file)
index 0000000..1173b5f
--- /dev/null
@@ -0,0 +1,15 @@
+;module-definition file for Windows Zip DLL -- used by link.exe
+LIBRARY ZIP16 ; Library module name
+DESCRIPTION 'Windows Info-ZIP Zip DLL 1.01 by Info-ZIP, Mike White 1996'
+
+CODE  PRELOAD FIXED
+
+DATA  PRELOAD MOVEABLE
+
+EXPORTS
+     ZpArchive
+     ZpVersion
+     ZpInit
+     ZpSetOptions
+     ZpGetOptions
+
diff --git a/windll/windll32.def b/windll/windll32.def
new file mode 100644 (file)
index 0000000..cd2e021
--- /dev/null
@@ -0,0 +1,15 @@
+;module-definition file for Windows Zip DLL -- used by link.exe
+LIBRARY ZIP32 ; Library module name
+DESCRIPTION 'Windows Info-ZIP Zip DLL 1.01 by Info-ZIP, Mike White 1997'
+
+;CODE  PRELOAD FIXED
+
+;DATA  PRELOAD MOVEABLE
+
+EXPORTS
+     ZpArchive
+     ZpVersion
+     ZpInit
+     ZpSetOptions
+     ZpGetOptions
+
diff --git a/windll/ziplib.def b/windll/ziplib.def
new file mode 100644 (file)
index 0000000..0fcd139
--- /dev/null
@@ -0,0 +1,15 @@
+;module-definition file for Windows Zip DLL -- used by link.exe
+LIBRARY ZIP32 ; Library module name
+DESCRIPTION 'Windows Info-ZIP Zip Library 1.02 by Info-ZIP, Mike White 1997'
+
+CODE  PRELOAD FIXED
+
+DATA  PRELOAD MOVEABLE
+
+EXPORTS
+     ZpArchive
+     ZpVersion
+     ZpInit
+     ZpSetOptions
+     ZpGetOptions
+
diff --git a/windll/zipver.h b/windll/zipver.h
new file mode 100644 (file)
index 0000000..c4b41f6
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#ifndef __zipver_h   /* prevent multiple inclusions */
+#define __zipver_h
+
+#define ZIP_DLL_VERSION "2.31\0"
+#define COMPANY_NAME "Info-ZIP\0"
+
+#endif /* __zipver_h */
diff --git a/zip.c b/zip.c
new file mode 100644 (file)
index 0000000..159fb23
--- /dev/null
+++ b/zip.c
@@ -0,0 +1,2326 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2005-Feb-10 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *  zip.c by Mark Adler.
+ */
+#define __ZIP_C
+
+#include "zip.h"
+#include <time.h>       /* for tzset() declaration */
+#ifdef WINDLL
+#  include <windows.h>
+#  include <setjmp.h>
+#  include "windll/windll.h"
+#endif
+#define DEFCPYRT        /* main module: enable copyright string defines! */
+#include "revision.h"
+#include "crypt.h"
+#include "ttyio.h"
+#ifdef VMS
+#  include "vms/vmsmunch.h"
+#endif
+
+#ifdef MACOS
+#  include "macglob.h"
+   extern MacZipGlobals MacZip;
+   extern int error_level;
+#endif
+
+#if (defined(MSDOS) && !defined(__GO32__)) || defined(__human68k__)
+#  include <process.h>
+#  if (!defined(P_WAIT) && defined(_P_WAIT))
+#    define P_WAIT _P_WAIT
+#  endif
+#endif
+
+#include <signal.h>
+
+#define MAXCOM 256      /* Maximum one-line comment size */
+
+
+/* Local option flags */
+#ifndef DELETE
+#define DELETE  0
+#endif
+#define ADD     1
+#define UPDATE  2
+#define FRESHEN 3
+local int action = ADD; /* one of ADD, UPDATE, FRESHEN, or DELETE */
+local int comadd = 0;   /* 1=add comments for new files */
+local int zipedit = 0;  /* 1=edit zip comment and all file comments */
+local int latest = 0;   /* 1=set zip file time to time of latest file */
+local ulg before = 0;   /* 0=ignore, else exclude files before this time */
+local ulg after = 0;    /* 0=ignore, else exclude files newer than this time */
+local int test = 0;     /* 1=test zip file with unzip -t */
+local int tempdir = 0;  /* 1=use temp directory (-b) */
+local int junk_sfx = 0; /* 1=junk the sfx prefix */
+#if defined(AMIGA) || defined(MACOS)
+local int filenotes = 0; /* 1=take comments from AmigaDOS/MACOS filenotes */
+#endif
+
+#ifdef EBCDIC
+int aflag = __EBCDIC;   /* Convert EBCDIC to ASCII or stay EBCDIC ? */
+#endif
+#ifdef CMS_MVS
+int bflag = 0;          /* Use text mode as default */
+#endif
+
+#ifdef QDOS
+char _version[] = VERSION;
+#endif
+
+#ifdef WINDLL
+jmp_buf zipdll_error_return;
+#endif
+
+/* Temporary zip file name and file pointer */
+#ifndef MACOS
+local char *tempzip;
+local FILE *tempzf;
+#else
+char *tempzip;
+FILE *tempzf;
+#endif
+
+#if CRYPT
+/* Pointer to crc_table, needed in crypt.c */
+# if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
+ZCONST ulg near *crc_32_tab;
+# else
+ZCONST uLongf *crc_32_tab;
+# endif
+#endif /* CRYPT */
+
+/* Local functions */
+
+local void freeup  OF((void));
+local int  finish  OF((int));
+#if (!defined(MACOS) && !defined(WINDLL))
+local void handler OF((int));
+local void license OF((void));
+#ifndef VMSCLI
+local void help    OF((void));
+#endif /* !VMSCLI */
+#endif /* !MACOS && !WINDLL */
+local int get_filters OF((int argc, char **argv));
+#if (!defined(MACOS) && !defined(WINDLL))
+local void check_zipfile OF((char *zipname, char *zippath));
+local void version_info OF((void));
+local void zipstdout OF((void));
+#endif /* !MACOS && !WINDLL */
+
+local void freeup()
+/* Free all allocations in the 'found' list, the 'zfiles' list and
+   the 'patterns' list. */
+{
+  struct flist far *f;  /* steps through found list */
+  struct zlist far *z;  /* pointer to next entry in zfiles list */
+
+  for (f = found; f != NULL; f = fexpel(f))
+    ;
+  while (zfiles != NULL)
+  {
+    z = zfiles->nxt;
+    if (zfiles->zname && zfiles->zname != zfiles->name)
+      free((zvoid *)(zfiles->zname));
+    if (zfiles->name)
+      free((zvoid *)(zfiles->name));
+    if (zfiles->iname)
+      free((zvoid *)(zfiles->iname));
+    if (zfiles->cext && zfiles->cextra && zfiles->cextra != zfiles->extra)
+      free((zvoid *)(zfiles->cextra));
+    if (zfiles->ext && zfiles->extra)
+      free((zvoid *)(zfiles->extra));
+    if (zfiles->com && zfiles->comment)
+      free((zvoid *)(zfiles->comment));
+    farfree((zvoid far *)zfiles);
+    zfiles = z;
+    zcount--;
+  }
+
+  if (patterns != NULL) {
+    while (pcount-- > 0) {
+      if (patterns[pcount].zname != NULL)
+        free((zvoid *)(patterns[pcount].zname));
+    }
+    free((zvoid *)patterns);
+    patterns = NULL;
+  }
+}
+
+local int finish(e)
+int e;                  /* exit code */
+/* Process -o and -m options (if specified), free up malloc'ed stuff, and
+   exit with the code e. */
+{
+  int r;                /* return value from trash() */
+  ulg t;                /* latest time in zip file */
+  struct zlist far *z;  /* pointer into zfile list */
+
+  /* If latest, set time to zip file to latest file in zip file */
+  if (latest && zipfile && strcmp(zipfile, "-"))
+  {
+    diag("changing time of zip file to time of latest file in it");
+    /* find latest time in zip file */
+    if (zfiles == NULL)
+       zipwarn("zip file is empty, can't make it as old as latest entry", "");
+    else {
+      t = 0;
+      for (z = zfiles; z != NULL; z = z->nxt)
+        /* Ignore directories in time comparisons */
+#ifdef USE_EF_UT_TIME
+        if (z->iname[z->nam-1] != (char)0x2f)   /* ascii '/' */
+        {
+          iztimes z_utim;
+          ulg z_tim;
+
+          z_tim = ((get_ef_ut_ztime(z, &z_utim) & EB_UT_FL_MTIME) ?
+                   unix2dostime(&z_utim.mtime) : z->tim);
+          if (t < z_tim)
+            t = z_tim;
+        }
+#else /* !USE_EF_UT_TIME */
+        if (z->iname[z->nam-1] != (char)0x2f    /* ascii '/' */
+            && t < z->tim)
+          t = z->tim;
+#endif /* ?USE_EF_UT_TIME */
+      /* set modified time of zip file to that time */
+      if (t != 0)
+        stamp(zipfile, t);
+      else
+        zipwarn(
+         "zip file has only directories, can't make it as old as latest entry",
+         "");
+    }
+  }
+  if (tempath != NULL)
+  {
+    free((zvoid *)tempath);
+    tempath = NULL;
+  }
+  if (zipfile != NULL)
+  {
+    free((zvoid *)zipfile);
+    zipfile = NULL;
+  }
+  if (zcomment != NULL)
+  {
+    free((zvoid *)zcomment);
+    zcomment = NULL;
+  }
+
+
+  /* If dispose, delete all files in the zfiles list that are marked */
+  if (dispose)
+  {
+    diag("deleting files that were added to zip file");
+    if ((r = trash()) != ZE_OK)
+      ZIPERR(r, "was deleting moved files and directories");
+  }
+
+
+  /* Done! */
+  freeup();
+  return e;
+}
+
+void ziperr(c, h)
+int c;                  /* error code from the ZE_ class */
+ZCONST char *h;         /* message about how it happened */
+/* Issue a message for the error, clean up files and memory, and exit. */
+{
+#ifndef WINDLL
+#ifndef MACOS
+  static int error_level = 0;
+#endif
+
+  if (error_level++ > 0)
+     EXIT(0);  /* avoid recursive ziperr() */
+#endif /* !WINDLL */
+
+  if (h != NULL) {
+    if (PERR(c))
+      perror("zip I/O error");
+    fflush(mesg);
+    fprintf(stderr, "\nzip error: %s (%s)\n", ziperrors[c-1], h);
+  }
+  if (tempzip != NULL)
+  {
+    if (tempzip != zipfile) {
+      if (tempzf != NULL)
+        fclose(tempzf);
+#ifndef DEBUG
+      destroy(tempzip);
+#endif
+      free((zvoid *)tempzip);
+    } else {
+      /* -g option, attempt to restore the old file */
+      int k = 0;                        /* keep count for end header */
+      ulg cb = cenbeg;                  /* get start of central */
+      struct zlist far *z;  /* steps through zfiles linked list */
+
+      fprintf(stderr, "attempting to restore %s to its previous state\n",
+         zipfile);
+      fseek(tempzf, cenbeg, SEEK_SET);
+      tempzn = cenbeg;
+      for (z = zfiles; z != NULL; z = z->nxt)
+      {
+        putcentral(z, tempzf);
+        tempzn += 4 + CENHEAD + z->nam + z->cext + z->com;
+        k++;
+      }
+      putend(k, tempzn - cb, cb, zcomlen, zcomment, tempzf);
+      fclose(tempzf);
+      tempzf = NULL;
+    }
+  }
+  if (key != NULL) {
+    free((zvoid *)key);
+    key = NULL;
+  }
+  if (tempath != NULL) {
+    free((zvoid *)tempath);
+    tempath = NULL;
+  }
+  if (zipfile != NULL) {
+    free((zvoid *)zipfile);
+    zipfile = NULL;
+  }
+  if (zcomment != NULL) {
+    free((zvoid *)zcomment);
+    zcomment = NULL;
+  }
+  freeup();
+#ifndef WINDLL
+  EXIT(c);
+#else
+  longjmp(zipdll_error_return, c);
+#endif
+}
+
+
+void error(h)
+  ZCONST char *h;
+/* Internal error, should never happen */
+{
+  ziperr(ZE_LOGIC, h);
+}
+
+#if (!defined(MACOS) && !defined(WINDLL))
+local void handler(s)
+int s;                  /* signal number (ignored) */
+/* Upon getting a user interrupt, turn echo back on for tty and abort
+   cleanly using ziperr(). */
+{
+#if defined(AMIGA) && defined(__SASC)
+   _abort();
+#else
+#if !defined(MSDOS) && !defined(__human68k__) && !defined(RISCOS)
+  echon();
+  putc('\n', stderr);
+#endif /* !MSDOS */
+#endif /* AMIGA && __SASC */
+  ziperr(ZE_ABORT, "aborting");
+  s++;                                  /* keep some compilers happy */
+}
+#endif /* !MACOS && !WINDLL */
+
+void zipwarn(a, b)
+ZCONST char *a, *b;     /* message strings juxtaposed in output */
+/* Print a warning message to stderr and return. */
+{
+  if (noisy) fprintf(stderr, "\tzip warning: %s%s\n", a, b);
+}
+
+#ifndef WINDLL
+local void license()
+/* Print license information to stdout. */
+{
+  extent i;             /* counter for copyright array */
+
+#if 0
+  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++) {
+    printf(copyright[i], "zip");
+    putchar('\n');
+  }
+#endif
+  for (i = 0; i < sizeof(swlicense)/sizeof(char *); i++)
+    puts(swlicense[i]);
+}
+
+#ifdef VMSCLI
+void help()
+#else
+local void help()
+#endif
+/* Print help (along with license info) to stdout. */
+{
+  extent i;             /* counter for help array */
+
+  /* help array */
+  static ZCONST char *text[] = {
+#ifdef VMS
+"Zip %s (%s). Usage: zip==\"$disk:[dir]zip.exe\"",
+#else
+"Zip %s (%s). Usage:",
+#endif
+#ifdef MACOS
+"zip [-options] [-b fm] [-t mmddyyyy] [-n suffixes] [zipfile list] [-xi list]",
+"  The default action is to add or replace zipfile entries from list.",
+" ",
+"  -f   freshen: only changed files  -u   update: only changed or new files",
+"  -d   delete entries in zipfile    -m   move into zipfile (delete files)",
+"  -r   recurse into directories     -j   junk (don't record) directory names",
+"  -0   store only                   -l   convert LF to CR LF (-ll CR LF to LF)",
+"  -1   compress faster              -9   compress better",
+"  -q   quiet operation              -v   verbose operation/print version info",
+"  -c   add one-line comments        -z   add zipfile comment",
+"                                    -o   make zipfile as old as latest entry",
+"  -F   fix zipfile (-FF try harder) -D   do not add directory entries",
+"  -T   test zipfile integrity       -X   eXclude eXtra file attributes",
+#  if CRYPT
+"  -e   encrypt                      -n   don't compress these suffixes"
+#  else
+"  -h   show this help               -n   don't compress these suffixes"
+#  endif
+," ",
+"  Macintosh specific:",
+"  -jj  record Fullpath (+ Volname)  -N store finder-comments as comments",
+"  -df  zip only datafork of a file  -S include finder invisible/system files"
+#else /* !MACOS */
+#ifdef VM_CMS
+"zip [-options] [-b fm] [-t mmddyyyy] [-n suffixes] [zipfile list] [-xi list]",
+#else  /* !VM_CMS */
+"zip [-options] [-b path] [-t mmddyyyy] [-n suffixes] [zipfile list] [-xi list]",
+#endif /* ?VM_CMS */
+"  The default action is to add or replace zipfile entries from list, which",
+"  can include the special name - to compress standard input.",
+"  If zipfile and list are omitted, zip compresses stdin to stdout.",
+"  -f   freshen: only changed files  -u   update: only changed or new files",
+"  -d   delete entries in zipfile    -m   move into zipfile (delete files)",
+"  -r   recurse into directories     -j   junk (don't record) directory names",
+#ifdef THEOS
+"  -0   store only                   -l   convert CR to CR LF (-ll CR LF to CR)",
+#else
+"  -0   store only                   -l   convert LF to CR LF (-ll CR LF to LF)",
+#endif
+"  -1   compress faster              -9   compress better",
+"  -q   quiet operation              -v   verbose operation/print version info",
+"  -c   add one-line comments        -z   add zipfile comment",
+"  -@   read names from stdin        -o   make zipfile as old as latest entry",
+"  -x   exclude the following names  -i   include only the following names",
+#ifdef EBCDIC
+#ifdef CMS_MVS
+"  -a   translate to ASCII           -B   force binary read (text is default)",
+#else  /* !CMS_MVS */
+"  -a   translate to ASCII",
+#endif /* ?CMS_MVS */
+#endif /* EBCDIC */
+#ifdef TANDEM
+"                                    -Bn  set Enscribe formatting options",
+#endif
+#ifdef VMS
+" \"-F\"  fix zipfile(\"-FF\" try harder) \"-D\"  do not add directory entries",
+" \"-A\"  adjust self-extracting exe  \"-J\"  junk zipfile prefix (unzipsfx)",
+" \"-T\"  test zipfile integrity      \"-X\"  eXclude eXtra file attributes",
+" \"-V\"  save VMS file attributes     -w   append version number to stored name",
+#else /* !VMS */
+"  -F   fix zipfile (-FF try harder) -D   do not add directory entries",
+"  -A   adjust self-extracting exe   -J   junk zipfile prefix (unzipsfx)",
+"  -T   test zipfile integrity       -X   eXclude eXtra file attributes",
+#endif /* ?VMS */
+#ifdef NTSD_EAS
+"  -!   use privileges (if granted) to obtain all aspects of WinNT security",
+#endif /* NTSD_EAS */
+#ifdef OS2
+"  -E   use the .LONGNAME Extended attribute (if found) as filename",
+#endif /* OS2 */
+#ifdef S_IFLNK
+"  -y   store symbolic links as the link instead of the referenced file",
+#endif /* !S_IFLNK */
+"  -R   PKZIP recursion (see manual)",
+#if defined(MSDOS) || defined(OS2)
+"  -$   include volume label         -S   include system and hidden files",
+#endif
+#ifdef AMIGA
+#  if CRYPT
+"  -N   store filenotes as comments  -e   encrypt",
+"  -h   show this help               -n   don't compress these suffixes"
+#  else
+"  -N   store filenotes as comments  -n   don't compress these suffixes"
+#  endif
+#else /* !AMIGA */
+#  if CRYPT
+"  -e   encrypt                      -n   don't compress these suffixes"
+#  else
+"  -h   show this help               -n   don't compress these suffixes"
+#  endif
+#endif /* ?AMIGA */
+#ifdef RISCOS
+,"  -I   don't scan through Image files"
+#endif
+#endif /* ?MACOS */
+  };
+
+  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
+  {
+    printf(copyright[i], "zip");
+    putchar('\n');
+  }
+  for (i = 0; i < sizeof(text)/sizeof(char *); i++)
+  {
+    printf(text[i], VERSION, REVDATE);
+    putchar('\n');
+  }
+}
+
+/*
+ * XXX version_info() in a separate file
+ */
+local void version_info()
+/* Print verbose info about program version and compile time options
+   to stdout. */
+{
+  extent i;             /* counter in text arrays */
+  char *envptr;
+
+  /* Options info array */
+  static ZCONST char *comp_opts[] = {
+#ifdef ASM_CRC
+    "ASM_CRC",
+#endif
+#ifdef ASMV
+    "ASMV",
+#endif
+#ifdef DYN_ALLOC
+    "DYN_ALLOC",
+#endif
+#ifdef MMAP
+    "MMAP",
+#endif
+#ifdef BIG_MEM
+    "BIG_MEM",
+#endif
+#ifdef MEDIUM_MEM
+    "MEDIUM_MEM",
+#endif
+#ifdef SMALL_MEM
+    "SMALL_MEM",
+#endif
+#ifdef DEBUG
+    "DEBUG",
+#endif
+#ifdef USE_EF_UT_TIME
+    "USE_EF_UT_TIME",
+#endif
+#ifdef NTSD_EAS
+    "NTSD_EAS",
+#endif
+#if defined(WIN32) && defined(NO_W32TIMES_IZFIX)
+    "NO_W32TIMES_IZFIX",
+#endif
+#ifdef VMS
+#ifdef VMSCLI
+    "VMSCLI",
+#endif
+#ifdef VMS_IM_EXTRA
+    "VMS_IM_EXTRA",
+#endif
+#ifdef VMS_PK_EXTRA
+    "VMS_PK_EXTRA",
+#endif
+#endif /* VMS */
+#ifdef WILD_STOP_AT_DIR
+    "WILD_STOP_AT_DIR",
+#endif
+#if CRYPT && defined(PASSWD_FROM_STDIN)
+    "PASSWD_FROM_STDIN",
+#endif /* CRYPT & PASSWD_FROM_STDIN */
+    NULL
+  };
+
+  static ZCONST char *zipenv_names[] = {
+#ifndef VMS
+#  ifndef RISCOS
+    "ZIP"
+#  else /* RISCOS */
+    "Zip$Options"
+#  endif /* ?RISCOS */
+#else /* VMS */
+    "ZIP_OPTS"
+#endif /* ?VMS */
+    ,"ZIPOPT"
+#ifdef AZTEC_C
+    ,     /* extremely lame compiler bug workaround */
+#endif
+#ifndef __RSXNT__
+# ifdef __EMX__
+    ,"EMX"
+    ,"EMXOPT"
+# endif
+# if (defined(__GO32__) && (!defined(__DJGPP__) || __DJGPP__ < 2))
+    ,"GO32"
+    ,"GO32TMP"
+# endif
+# if (defined(__DJGPP__) && __DJGPP__ >= 2)
+    ,"TMPDIR"
+# endif
+#endif /* !__RSXNT__ */
+#ifdef RISCOS
+    ,"Zip$Exts"
+#endif
+  };
+
+  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
+  {
+    printf(copyright[i], "zip");
+    putchar('\n');
+  }
+
+  for (i = 0; i < sizeof(versinfolines)/sizeof(char *); i++)
+  {
+    printf(versinfolines[i], "Zip", VERSION, REVDATE);
+    putchar('\n');
+  }
+
+  version_local();
+
+  puts("Zip special compilation options:");
+#if WSIZE != 0x8000
+  printf("\tWSIZE=%u\n", WSIZE);
+#endif
+  for (i = 0; (int)i < (int)(sizeof(comp_opts)/sizeof(char *) - 1); i++)
+  {
+    printf("\t%s\n",comp_opts[i]);
+  }
+#ifdef USE_ZLIB
+  if (strcmp(ZLIB_VERSION, zlibVersion()) == 0)
+    printf("\tUSE_ZLIB [zlib version %s]\n", ZLIB_VERSION);
+  else
+    printf("\tUSE_ZLIB [compiled with version %s, using version %s]\n",
+      ZLIB_VERSION, zlibVersion());
+  i++;  /* zlib use means there IS at least one compilation option */
+#endif
+#if CRYPT
+  printf("\t[encryption, version %d.%d%s of %s]\n",
+            CR_MAJORVER, CR_MINORVER, CR_BETA_VER, CR_VERSION_DATE);
+  for (i = 0; i < sizeof(cryptnote)/sizeof(char *); i++)
+  {
+    printf(cryptnote[i]);
+    putchar('\n');
+  }
+  ++i;  /* crypt support means there IS at least one compilation option */
+#endif
+  if (i == 0)
+      puts("\t[none]");
+
+  puts("\nZip environment options:");
+  for (i = 0; i < sizeof(zipenv_names)/sizeof(char *); i++)
+  {
+    envptr = getenv(zipenv_names[i]);
+    printf("%16s:  %s\n", zipenv_names[i],
+           ((envptr == (char *)NULL || *envptr == 0) ? "[none]" : envptr));
+  }
+}
+#endif /* !WINDLL */
+
+
+#ifndef PROCNAME
+#  define PROCNAME(n) procname(n, (action == DELETE || action == FRESHEN))
+#endif /* PROCNAME */
+
+#ifndef WINDLL
+#ifndef MACOS
+local void zipstdout()
+/* setup for writing zip file on stdout */
+{
+  int r;
+  mesg = stderr;
+  if (isatty(1))
+    ziperr(ZE_PARMS, "cannot write zip file to terminal");
+  if ((zipfile = malloc(4)) == NULL)
+    ziperr(ZE_MEM, "was processing arguments");
+  strcpy(zipfile, "-");
+  if ((r = readzipfile()) != ZE_OK)
+    ziperr(r, zipfile);
+}
+#endif /* !MACOS */
+
+local void check_zipfile(zipname, zippath)
+  char *zipname;
+  char *zippath;
+  /* Invoke unzip -t on the given zip file */
+{
+#if (defined(MSDOS) && !defined(__GO32__)) || defined(__human68k__)
+   int status, len;
+   char *path, *p;
+
+   status = spawnlp(P_WAIT, "unzip", "unzip", verbose ? "-t" : "-tqq",
+                    zipname, NULL);
+#ifdef __human68k__
+   if (status == -1)
+     perror("unzip");
+#else
+/*
+ * unzip isn't in PATH range, assume an absolute path to zip in argv[0]
+ * and hope that unzip is in the same directory.
+ */
+   if (status == -1) {
+     p = MBSRCHR(zippath, '\\');
+     path = MBSRCHR((p == NULL ? zippath : p), '/');
+     if (path != NULL)
+       p = path;
+     if (p != NULL) {
+       len = (int)(p - zippath) + 1;
+       if ((path = malloc(len + sizeof("unzip.exe"))) == NULL)
+         ziperr(ZE_MEM, "was creating unzip path");
+       memcpy(path, zippath, len);
+       strcpy(&path[len], "unzip.exe");
+       status = spawnlp(P_WAIT, path, "unzip", verbose ? "-t" : "-tqq",
+                        zipname, NULL);
+       free(path);
+     }
+     if (status == -1)
+       perror("unzip");
+   }
+#endif /* ?__human68k__ */
+   if (status != 0) {
+#else /* (MSDOS && !__GO32__) || __human68k__ */
+   char cmd[FNMAX+16];
+
+   /* Tell picky compilers to shut up about unused variables */
+   zippath = zippath;
+
+   strcpy(cmd, "unzip -t ");
+#ifdef QDOS
+   strcat(cmd, "-Q4 ");
+#endif
+   if (!verbose) strcat(cmd, "-qq ");
+   if ((int)strlen(zipname) > FNMAX) {
+     error("zip filename too long");
+   }
+# ifdef UNIX
+   strcat(cmd, "'");    /* accept space or $ in name */
+   strcat(cmd, zipname);
+   strcat(cmd, "'");
+# else
+   strcat(cmd, zipname);
+# endif
+# ifdef VMS
+   if (!system(cmd)) {
+# else
+   if (system(cmd)) {
+# endif
+#endif /* ?((MSDOS && !__GO32__) || __human68k__) */
+     fprintf(mesg, "test of %s FAILED\n", zipfile);
+     ziperr(ZE_TEST, "original files unmodified");
+   }
+   if (noisy)
+     fprintf(mesg, "test of %s OK\n", zipfile);
+}
+#endif /* !WINDLL */
+
+local int get_filters(argc, argv)
+  int argc;               /* number of tokens in command line */
+  char **argv;            /* command line tokens */
+/* Counts number of -i or -x patterns, sets patterns and pcount */
+{
+  int i;
+  int flag = 0, archive_seen = 0;
+  char *iname, *p = NULL;
+  FILE *fp;
+
+  pcount = 0;
+  for (i = 1; i < argc; i++) {
+    if (argv[i][0] == '-') {
+      p = argv[i];
+      while (*(++p) != '\0') {
+        if (*p == 'i' || *p == 'x')
+          break;
+      }
+      if (*p != '\0') {
+        flag = *p;
+        p = p[1] == '@' ? p + 2 : NULL;
+        if (p != NULL && patterns == NULL) {
+          fp = fopen(p, "r");
+          if (fp == NULL) {
+            ZIPERR(ZE_OPEN, p);
+          }
+          while (fgets(errbuf, FNMAX, fp) != NULL)
+            pcount++;
+          fclose(fp);
+        }
+      } else if (MBSRCHR(argv[i], 'R') != NULL) {
+        p = NULL;
+        flag = 'R';
+      } else if (flag != 'R') {
+        flag = 0;
+      }
+    }
+    if (flag && (archive_seen || p != NULL)) {
+      if (patterns != NULL) {
+        /* second pass: create pattern entry */
+        if (p != NULL) {
+          fp = fopen(p, "r");
+          if (fp == NULL) {
+            ZIPERR(ZE_OPEN, p);
+          }
+          while ((p = getnam(errbuf, fp)) != NULL) {
+            iname = ex2in(p, 0, (int *)NULL);
+            if (iname != NULL) {
+              patterns[pcount].zname = in2ex(iname);
+              free(iname);
+            } else {
+              patterns[pcount].zname = NULL;
+            }
+            patterns[pcount].select = flag;
+            if (flag != 'x')
+              icount++;
+            pcount++;
+          }
+          fclose(fp);
+          flag = 0;
+          p = NULL;
+        }
+        else if (argv[i][0] != '-') {
+          iname = ex2in(argv[i], 0, (int *)NULL);
+          patterns[pcount].zname = (iname != NULL ? in2ex(iname) : NULL);
+          if (iname != NULL)
+            free(iname);
+          patterns[pcount].select = flag;
+          if (flag != 'x')
+            icount++;
+          pcount++;
+        }
+      }
+      else if (p == NULL)
+        pcount++;
+      else
+        flag = 0;
+    } else {
+      if (flag != 'R')
+        flag = 0;               /* only 'R' is allowed before zipfile arg */
+      if (argv[i][0] != '-') {
+        archive_seen = 1;       /* first non-flag arg is archive name */
+      }
+    }
+  }
+  if (pcount == 0 || patterns != NULL) return ZE_OK;
+  /* first pass and pattern count > 0: allocate space for pattern list */
+  patterns = (struct plist*) malloc(pcount * sizeof(struct plist));
+  if (patterns == NULL) {
+    ZIPERR(ZE_MEM, "was creating pattern list");
+  }
+  /* recall this function for second pass, filling the pattern list */
+  return get_filters(argc, argv);
+}
+
+#if CRYPT
+#ifndef WINDLL
+int encr_passwd(modeflag, pwbuf, size, zfn)
+int modeflag;
+char *pwbuf;
+int size;
+ZCONST char *zfn;
+{
+    char *prompt;
+
+    /* Tell picky compilers to shut up about unused variables */
+    zfn = zfn;
+
+    prompt = (modeflag == ZP_PW_VERIFY) ?
+              "Verify password: " : "Enter password: ";
+
+    if (getp(prompt, pwbuf, size) == NULL) {
+      ziperr(ZE_PARMS, "stderr is not a tty");
+    }
+    return IZ_PW_ENTERED;
+}
+#endif /* !WINDLL */
+#else /* !CRYPT */
+int encr_passwd(modeflag, pwbuf, size, zfn)
+int modeflag;
+char *pwbuf;
+int size;
+ZCONST char *zfn;
+{
+    /* Tell picky compilers to shut up about unused variables */
+    modeflag = modeflag; pwbuf = pwbuf; size = size; zfn = zfn;
+
+    return ZE_LOGIC;    /* This function should never be called! */
+}
+#endif /* CRYPT */
+
+#ifndef USE_ZIPMAIN
+int main(argc, argv)
+#else
+int zipmain(argc, argv)
+#endif
+int argc;               /* number of tokens in command line */
+char **argv;            /* command line tokens */
+/* Add, update, freshen, or delete zip entries in a zip file.  See the
+   command help in help() above. */
+{
+  int a;                /* attributes of zip file */
+  ulg c;                /* start of central directory */
+  int d;                /* true if just adding to a zip file */
+  char *e;              /* malloc'd comment buffer */
+  struct flist far *f;  /* steps through found linked list */
+  int i;                /* arg counter, root directory flag */
+  int k;                /* next argument type, marked counter,
+                           comment size, entry count */
+  ulg n;                /* total of entry len's */
+  int o;                /* true if there were any ZE_OPEN errors */
+  char *p;              /* steps through option arguments */
+  char *pp;             /* temporary pointer */
+  ulg *cmptime = NULL;  /* pointer to 'before' or 'after' */
+  int r;                /* temporary variable */
+  int s;                /* flag to read names from stdin */
+  ulg t;                /* file time, length of central directory */
+  int first_listarg = 0;/* index of first arg of "process these files" list */
+  struct zlist far *v;  /* temporary variable */
+  struct zlist far * far *w;    /* pointer to last link in zfiles list */
+  FILE *x, *y;          /* input and output zip files */
+  struct zlist far *z;  /* steps through zfiles linked list */
+#ifdef WINDLL
+  int retcode;          /* return code for dll */
+#endif
+#if (!defined(VMS) && !defined(CMS_MVS))
+  char *zipbuf;         /* stdio buffer for the zip file */
+#endif /* !VMS && !CMS_MVS */
+  FILE *comment_stream; /* set to stderr if anything is read from stdin */
+
+#ifdef THEOS
+  /* the argument expansion from the standard library is full of bugs */
+  /* use mine instead */
+  _setargv(&argc, &argv);
+  setlocale(LC_CTYPE,"I");
+#else
+  SETLOCALE(LC_CTYPE,"");
+#endif
+
+#if defined(__IBMC__) && defined(__DEBUG_ALLOC__)
+  {
+    extern void DebugMalloc(void);
+    atexit(DebugMalloc);
+  }
+#endif
+
+#ifdef QDOS
+  {
+    extern void QDOSexit(void);
+    atexit(QDOSexit);
+  }
+#endif
+
+#ifdef RISCOS
+  set_prefix();
+#endif
+
+#ifdef __human68k__
+  fflush(stderr);
+  setbuf(stderr, NULL);
+#endif
+
+/* Re-initialize global variables to make the zip dll re-entrant. It is
+ * possible that we could get away with not re-initializing all of these
+ * but better safe than sorry.
+ */
+#if defined(MACOS) || defined(WINDLL)
+  action = ADD; /* one of ADD, UPDATE, FRESHEN, or DELETE */
+  comadd = 0;   /* 1=add comments for new files */
+  zipedit = 0;  /* 1=edit zip comment and all file comments */
+  latest = 0;   /* 1=set zip file time to time of latest file */
+  before = 0;   /* 0=ignore, else exclude files before this time */
+  after = 0;    /* 0=ignore, else exclude files newer than this time */
+  test = 0;     /* 1=test zip file with unzip -t */
+  tempdir = 0;  /* 1=use temp directory (-b) */
+  junk_sfx = 0; /* 1=junk the sfx prefix */
+#if defined(AMIGA) || defined(MACOS)
+  filenotes = 0;/* 1=take comments from AmigaDOS/MACOS filenotes */
+#endif
+  zipstate = -1;
+  tempzip = NULL;
+  fcount = 0;
+  recurse = 0;         /* 1=recurse into directories; 2=match filenames */
+  dispose = 0;         /* 1=remove files after put in zip file */
+  pathput = 1;         /* 1=store path with name */
+  method = BEST;       /* one of BEST, DEFLATE (only), or STORE (only) */
+  dosify = 0;          /* 1=make new entries look like MSDOS */
+  verbose = 0;         /* 1=report oddities in zip file structure */
+  fix = 0;             /* 1=fix the zip file */
+  adjust = 0;          /* 1=adjust offsets for sfx'd file (keep preamble) */
+  level = 6;           /* 0=fastest compression, 9=best compression */
+  translate_eol = 0;   /* Translate end-of-line LF -> CR LF */
+#if defined(OS2) || defined(WIN32)
+  use_longname_ea = 0; /* 1=use the .LONGNAME EA as the file's name */
+#endif
+#ifdef NTSD_EAS
+  use_privileges = 0;  /* 1=use security privileges overrides */
+#endif
+  hidden_files = 0;    /* process hidden and system files */
+  volume_label = 0;    /* add volume label */
+  dirnames = 1;        /* include directory entries by default */
+  linkput = 0;         /* 1=store symbolic links as such */
+  noisy = 1;           /* 0=quiet operation */
+  extra_fields = 1;    /* 0=do not create extra fields */
+  special = ".Z:.zip:.zoo:.arc:.lzh:.arj"; /* List of special suffixes */
+  key = NULL;          /* Scramble password if scrambling */
+  tempath = NULL;      /* Path for temporary files */
+  found = NULL;        /* where in found, or new found entry */
+  fnxt = &found;
+  patterns = NULL;     /* List of patterns to be matched */
+  pcount = 0;          /* number of patterns */
+  icount = 0;          /* number of include only patterns */
+
+#ifndef MACOS
+  retcode = setjmp(zipdll_error_return);
+  if (retcode) {
+    return retcode;
+  }
+#endif /* !MACOS */
+#endif /* MACOS || WINDLL */
+
+  mesg = (FILE *) stdout; /* cannot be made at link time for VMS */
+  comment_stream = (FILE *)stdin;
+
+  init_upper();           /* build case map table */
+
+#if (defined(WIN32) && defined(USE_EF_UT_TIME))
+  /* For the Win32 environment, we may have to "prepare" the environment
+     prior to the tzset() call, to work around tzset() implementation bugs.
+   */
+  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
+  zp_tz_is_valid = VALID_TIMEZONE(p);
+#if (defined(AMIGA) || defined(DOS))
+  if (!zp_tz_is_valid)
+    extra_fields = 0;     /* disable storing "UT" time stamps */
+#endif /* AMIGA || DOS */
+#endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */
+
+/* For systems that do not have tzset() but supply this function using another
+   name (_tzset() or something similar), an appropiate "#define tzset ..."
+   should be added to the system specifc configuration section.  */
+#if (!defined(TOPS20) && !defined(VMS))
+#if (!defined(RISCOS) && !defined(MACOS) && !defined(QDOS))
+#if (!defined(BSD) && !defined(MTS) && !defined(CMS_MVS) && !defined(TANDEM))
+  tzset();
+#endif
+#endif
+#endif
+
+#ifdef VMSCLI
+    {
+        ulg status = vms_zip_cmdline(&argc, &argv);
+        if (!(status & 1))
+            return status;
+    }
+#endif /* VMSCLI */
+
+  /* extract extended argument list from environment */
+  expand_args(&argc, &argv);
+
+
+#ifndef WINDLL
+  /* Process arguments */
+  diag("processing arguments");
+  /* First, check if just the help or version screen should be displayed */
+  if (argc == 1 && isatty(1))   /* no arguments, and output screen available */
+  {                             /* show help screen */
+#ifdef VMSCLI
+    VMSCLI_help();
+#else
+    help();
+#endif
+    EXIT(0);
+  }
+  else if (argc == 2 && strcmp(argv[1], "-v") == 0 &&
+           /* only "-v" as argument, and */
+           (isatty(1) || isatty(0)))
+           /* stdout or stdin is connected to console device */
+  {                             /* show diagnostic version info */
+    version_info();
+    EXIT(0);
+  }
+#ifndef VMS
+#  ifndef RISCOS
+  envargs(&argc, &argv, "ZIPOPT", "ZIP");  /* get options from environment */
+#  else /* RISCOS */
+  envargs(&argc, &argv, "ZIPOPT", "Zip$Options");  /* get options from environment */
+  getRISCOSexts("Zip$Exts");        /* get the extensions to swap from environment */
+#  endif /* ? RISCOS */
+#else /* VMS */
+  envargs(&argc, &argv, "ZIPOPT", "ZIP_OPTS");  /* 4th arg for unzip compat. */
+#endif /* ?VMS */
+#endif /* !WINDLL */
+
+  zipfile = tempzip = NULL;
+  tempzf = NULL;
+  d = 0;                        /* disallow adding to a zip file */
+#if (!defined(MACOS) && !defined(WINDLL))
+  signal(SIGINT, handler);
+#ifdef SIGTERM                  /* AMIGADOS and others have no SIGTERM */
+  signal(SIGTERM, handler);
+#endif
+#endif /* !MACOS && !WINDLL */
+  k = 0;                        /* Next non-option argument type */
+  s = 0;                        /* set by -@ if -@ is early */
+
+  r = get_filters(argc, argv);      /* scan first the -x and -i patterns */
+#ifdef WINDLL
+  if (r != ZE_OK)
+    return r;
+#endif
+
+  for (i = 1; i < argc; i++)
+  {
+    if (argv[i][0] == '-')
+    {
+      if (argv[i][1])
+        for (p = argv[i]+1; *p; p++)
+          switch (*p)
+          {
+#ifdef EBCDIC
+            case 'a':
+              aflag = ASCII;
+              printf("Translating to ASCII...\n");
+              break;
+#endif /* EBCDIC */
+#ifdef CMS_MVS
+            case 'B':
+              bflag = 1;
+              printf("Using binary mode...\n");
+              break;
+#endif /* CMS_MVS */
+#ifdef TANDEM
+            case 'B':
+              nskformatopt(&p);
+              break;
+#endif
+            case '0':
+              method = STORE; level = 0; break;
+            case '1':  case '2':  case '3':  case '4':
+            case '5':  case '6':  case '7':  case '8':  case '9':
+                        /* Set the compression efficacy */
+              level = *p - '0';  break;
+            case 'A':   /* Adjust unzipsfx'd zipfile:  adjust offsets only */
+              adjust = 1; break;
+            case 'b':   /* Specify path for temporary file */
+              tempdir = 1;
+              if (k != 0) {
+                ZIPERR(ZE_PARMS, "use -b before zip file name");
+              }
+              else
+                k = 1;          /* Next non-option is path */
+              break;
+            case 'c':   /* Add comments for new files in zip file */
+              comadd = 1;  break;
+            case 'd':   /* Delete files from zip file */
+#ifdef MACOS
+              if (p[1] == 'f') {
+                ++p;
+                MacZip.DataForkOnly = true;
+              } else
+#endif /* MACOS */
+              {
+                if (action != ADD) {
+                  ZIPERR(ZE_PARMS, "specify just one action");
+                }
+                action = DELETE;
+                break;
+              }
+            case 'D':   /* Do not add directory entries */
+              dirnames = 0; break;
+            case 'e':   /* Encrypt */
+#if !CRYPT
+              ZIPERR(ZE_PARMS, "encryption not supported");
+#else /* CRYPT */
+              if (key == NULL) {
+                if ((key = malloc(IZ_PWLEN+1)) == NULL) {
+                  ZIPERR(ZE_MEM, "was getting encryption password");
+                }
+                r = encr_passwd(ZP_PW_ENTER, key, IZ_PWLEN+1, zipfile);
+                if (r != IZ_PW_ENTERED) {
+                  if (r < IZ_PW_ENTERED)
+                    r = ZE_PARMS;
+                  ZIPERR(r, "was getting encryption password");
+                }
+                if (*key == '\0') {
+                  ZIPERR(ZE_PARMS, "zero length password not allowed");
+                }
+                if ((e = malloc(IZ_PWLEN+1)) == NULL) {
+                  ZIPERR(ZE_MEM, "was verifying encryption password");
+                }
+                r = encr_passwd(ZP_PW_VERIFY, e, IZ_PWLEN+1, zipfile);
+                if (r != IZ_PW_ENTERED && r != IZ_PW_SKIPVERIFY) {
+                  free((zvoid *)e);
+                  if (r < ZE_OK) r = ZE_PARMS;
+                  ZIPERR(r, "was verifying encryption password");
+                }
+                r = ((r == IZ_PW_SKIPVERIFY) ? 0 : strcmp(key, e));
+                free((zvoid *)e);
+                if (r) {
+                  ZIPERR(ZE_PARMS, "password verification failed");
+                }
+              }
+#endif /* !CRYPT */
+              break;
+            case 'F':   /* fix the zip file */
+              fix++; break;
+            case 'f':   /* Freshen zip file--overwrite only */
+              if (action != ADD) {
+                ZIPERR(ZE_PARMS, "specify just one action");
+              }
+              action = FRESHEN;
+              break;
+            case 'g':   /* Allow appending to a zip file */
+              d = 1;  break;
+#ifndef WINDLL
+            case 'h': case 'H': case '?':  /* Help */
+#ifdef VMSCLI
+              VMSCLI_help();
+#else
+              help();
+#endif
+              RETURN(finish(ZE_OK));
+#endif /* !WINDLL */
+
+#ifdef RISCOS
+            case 'I':   /* Don't scan through Image files */
+              scanimage = 0;
+              break;
+#endif
+#ifdef MACOS
+            case 'j':   /* Junk path / Store absolute path */
+              if (p[1] == 'j') {    /* store absolute path including volname */
+                ++p;
+                MacZip.StoreFullPath = true;
+              } else {              /* junk directory names */
+                pathput = 0;  break;
+              }
+#else /* !MACOS */
+            case 'j':   /* Junk directory names */
+              pathput = 0;  break;
+#endif /* ?MACOS */
+            case 'J':   /* Junk sfx prefix */
+              junk_sfx = 1;  break;
+            case 'k':   /* Make entries using DOS names (k for Katz) */
+              dosify = 1;  break;
+            case 'l':   /* Translate end-of-line */
+              translate_eol++; break;
+#ifndef WINDLL
+            case 'L':   /* Show license */
+              license();
+              RETURN(finish(ZE_OK));
+#endif
+            case 'm':   /* Delete files added or updated in zip file */
+              dispose = 1;  break;
+            case 'n':   /* Don't compress files with a special suffix */
+              special = NULL; /* will be set at next argument */
+              break;
+#if defined(AMIGA) || defined(MACOS)
+            case 'N':   /* Get zipfile comments from AmigaDOS/MACOS filenotes */
+              filenotes = 1; break;
+#endif
+            case 'o':   /* Set zip file time to time of latest file in it */
+              latest = 1;  break;
+            case 'p':   /* Store path with name */
+              break;            /* (do nothing as annoyance avoidance) */
+            case 'P':   /* password for encryption */
+              if (k != 0) {
+                ZIPERR(ZE_PARMS, "use -P before zip file name");
+              }
+              if (key != NULL) {
+                ZIPERR(ZE_PARMS, "can only have one -P");
+              }
+#if CRYPT
+              k = 7;
+#else
+              ZIPERR(ZE_PARMS, "encryption not supported");
+#endif /* CRYPT */
+              break;
+#if defined(QDOS) || defined(QLZIP)
+            case 'Q':
+              qlflag  = strtol((p+1), &p, 10);
+              if (qlflag == 0) qlflag = 4;
+              p--;
+              break;
+#endif
+            case 'q':   /* Quiet operation */
+              noisy = 0;
+#ifdef MACOS
+              MacZip.MacZip_Noisy = false;
+#endif  /* MACOS */
+              if (verbose) verbose--;
+              break;
+            case 'r':   /* Recurse into subdirectories, match full path */
+              if (recurse == 2) {
+                ZIPERR(ZE_PARMS, "do not specify both -r and -R");
+              }
+              recurse = 1;  break;
+            case 'R':   /* Recurse into subdirectories, match filename */
+              if (recurse == 1) {
+                ZIPERR(ZE_PARMS, "do not specify both -r and -R");
+              }
+              recurse = 2;  break;
+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(ATARI)
+            case 'S':
+              hidden_files = 1; break;
+#endif /* MSDOS || OS2 || WIN32 || ATARI */
+#ifdef MACOS
+            case 'S':
+              MacZip.IncludeInvisible = true; break;
+#endif /* MACOS */
+            case 't':   /* Exclude files earlier than specified date */
+              if (p[1] == 't') {
+                ++p;
+                cmptime = &after;
+              } else {
+                cmptime = &before;
+              }
+              if (*cmptime) {
+                ZIPERR(ZE_PARMS, (cmptime == &after ?
+                       "can only have one -tt" : "can only have one -t"));
+              }
+              k = 2;  break;
+            case 'T':   /* test zip file */
+              test = 1; break;
+            case 'u':   /* Update zip file--overwrite only if newer */
+              if (action != ADD) {
+                ZIPERR(ZE_PARMS, "specify just one action");
+              }
+              action = UPDATE;
+              break;
+            case 'v':   /* Mention oddities in zip file structure */
+              noisy = 1;
+              verbose++;
+              break;
+#ifdef VMS
+            case 'V':   /* Store in VMS format.  (Record multiples.) */
+              vms_native++; break;
+            case 'w':   /* Append the VMS version number */
+              vmsver = 1;  break;
+#endif /* VMS */
+            case 'i':   /* Include only the following files */
+            case 'x':   /* Exclude following files */
+              if (p[1] == '@' && p[2] != '\0') {
+                goto nextarg;
+              }
+              if (zipfile == NULL) {
+                ZIPERR(ZE_PARMS, "use -x or -i after name of zipfile");
+              }
+              k = 5;
+              break;
+#ifdef S_IFLNK
+            case 'y':   /* Store symbolic links as such */
+              linkput = 1;  break;
+#endif /* S_IFLNK */
+            case 'z':   /* Edit zip file comment */
+              zipedit = 1;  break;
+#if defined(MSDOS) || defined(OS2)
+            case '$':   /* Include volume label */
+              volume_label = 1; break;
+#endif
+#ifndef MACOS
+            case '@':   /* read file names from stdin */
+              comment_stream = NULL;
+              if (k < 3)        /* zip file not read yet */
+                s = 1;          /* defer -@ until after zipfile read */
+              else              /* zip file read--do it now */
+                while ((pp = getnam(errbuf, stdin)) != NULL)
+                {
+                  k = 4;
+                  if ((r = PROCNAME(pp)) != ZE_OK)
+                  {
+                    if (r == ZE_MISS)
+                      zipwarn("name not matched: ", pp);
+                    else {
+                      ZIPERR(r, pp);
+                    }
+                  }
+                }
+              break;
+#endif /* !MACOS */
+            case 'X':
+              extra_fields = 0;
+              break;
+#ifdef OS2
+            case 'E':
+              /* use the .LONGNAME EA (if any) as the file's name. */
+              use_longname_ea = 1;
+              break;
+#endif
+#ifdef NTSD_EAS
+            case '!':
+              /* use security privilege overrides */
+              use_privileges = 1;
+              break;
+#endif
+            default:
+            {
+              sprintf(errbuf, "no such option: %c", *p);
+              ZIPERR(ZE_PARMS, errbuf);
+            }
+          }
+      else              /* just a dash */
+        switch (k)
+        {
+#if (!defined(MACOS) && !defined(WINDLL))
+        case 0:
+          zipstdout();
+          k = 3;
+          break;
+#endif /* !MACOS && !WINDLL */
+        case 1:
+          ZIPERR(ZE_PARMS, "invalid path");
+          /* not reached */
+        case 2:
+          ZIPERR(ZE_PARMS, "invalid time");
+          /* not reached */
+        case 3:  case 4:
+          comment_stream = NULL;
+          if ((r = PROCNAME(argv[i])) != ZE_OK) {
+            if (r == ZE_MISS)
+              zipwarn("name not matched: ", argv[i]);
+            else {
+              ZIPERR(r, argv[i]);
+            }
+          }
+          if (k == 3) {
+            first_listarg = i;
+            k = 4;
+          }
+        }
+    }
+    else                /* not an option */
+    {
+      if (special == NULL)
+        special = argv[i];
+      else if (k == 5)
+        break; /* -i and -x arguments already scanned */
+      else if (k == 6) {
+#ifdef AMIGA
+        if ((r = PROCNAME("")) != ZE_OK) {
+#else
+        if ((r = PROCNAME(".")) != ZE_OK) {
+#endif
+          if (r == ZE_MISS)
+            zipwarn("name not matched: ", argv[i]);
+          else {
+            ZIPERR(r, argv[i]);
+          }
+        }
+        if (first_listarg == 0)
+          first_listarg = i;
+        break;
+      }
+      else switch (k)
+      {
+        case 0:
+          if ((zipfile = ziptyp(argv[i])) == NULL) {
+            ZIPERR(ZE_MEM, "was processing arguments");
+          }
+          if ((r = readzipfile()) != ZE_OK) {
+            ZIPERR(r, zipfile);
+          }
+          k = 3;
+          if (recurse == 2)
+            k = 6;
+          break;
+        case 1:
+          if ((tempath = malloc(strlen(argv[i]) + 1)) == NULL) {
+            ZIPERR(ZE_MEM, "was processing arguments");
+          }
+          strcpy(tempath, argv[i]);
+          k = (zipfile != NULL ? (first_listarg > 0 ? 4 : 3) : 0);
+          break;
+        case 2:
+        {
+          int yyyy, mm, dd;       /* results of sscanf() */
+
+          /* Support ISO 8601 & American dates */
+          if ((sscanf(argv[i], "%4d-%2d-%2d", &yyyy, &mm, &dd) != 3 &&
+               sscanf(argv[i], "%2d%2d%4d", &mm, &dd, &yyyy) != 3) ||
+              mm < 1 || mm > 12 || dd < 1 || dd > 31) {
+            ZIPERR(ZE_PARMS, (cmptime == &after ?
+                   "invalid date entered for -tt option" :
+                   "invalid date entered for -t option"));
+          }
+          *cmptime = dostime(yyyy, mm, dd, 0, 0, 0);
+          k = (zipfile != NULL ? (first_listarg > 0 ? 4 : 3) : 0);
+          break;
+        }
+        case 3:  case 4:
+          if ((r = PROCNAME(argv[i])) != ZE_OK) {
+            if (r == ZE_MISS)
+              zipwarn("name not matched: ", argv[i]);
+            else {
+              ZIPERR(r, argv[i]);
+            }
+          }
+          if (k == 3) {
+            first_listarg = i;
+            k = 4;
+          }
+          break;
+        case 7:
+          if ((key = malloc(strlen(argv[i]) + 1)) == NULL) {
+            ZIPERR(ZE_MEM, "was processing arguments");
+          }
+          strcpy(key, argv[i]);
+          k = (zipfile != NULL ? (first_listarg > 0 ? 4 : 3) : 0);
+      }
+    }
+    if ((k == 3 || k == 6) && (s))
+    {
+      while ((pp = getnam(errbuf, stdin)) != NULL)
+      {
+        first_listarg = i + 1;
+        k = 4;
+        if ((r = PROCNAME(pp)) != ZE_OK) {
+          if (r == ZE_MISS)
+            zipwarn("name not matched: ", pp);
+          else {
+            ZIPERR(r, pp);
+          }
+        }
+      }
+      s = 0;
+      if (recurse == 2) k = 6;
+    }
+nextarg: ;
+  }
+  if (k == 7 || k == 1) {
+    ZIPERR(ZE_PARMS, "missing argument for -b or -P");
+  }
+
+#if (defined(MSDOS) || defined(OS2)) && !defined(WIN32)
+  if ((k == 3 || k == 4) && volume_label == 1) {
+    PROCNAME(NULL);
+    k = 4;
+  }
+#endif
+
+  if (pcount && first_listarg == 0 &&
+      (k < 3 || (action != UPDATE && action != FRESHEN))) {
+    ZIPERR(ZE_PARMS, "nothing to select from");
+  }
+
+#if (!defined(MACOS) && !defined(WINDLL))
+  if (k < 3) {               /* zip used as filter */
+    zipstdout();
+    comment_stream = NULL;
+    if ((r = procname("-", 0)) != ZE_OK) {
+      if (r == ZE_MISS)
+        zipwarn("name not matched: ", "-");
+      else {
+        ZIPERR(r, "-");
+      }
+    }
+    k = 4;
+    if (s) {
+      ZIPERR(ZE_PARMS, "can't use - and -@ together");
+    }
+  }
+#endif /* !MACOS && !WINDLL */
+
+  /* Clean up selections ("3 <= k <= 5" now) */
+  if (k != 4 && first_listarg == 0 &&
+      (action == UPDATE || action == FRESHEN)) {
+    /* if -u or -f with no args, do all, but, when present, apply filters */
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      z->mark = pcount ? filter(z->zname, 0) : 1;
+#ifdef DOS
+      if (z->mark) z->dosflag = 1;      /* force DOS attribs for incl. names */
+#endif
+    }
+  }
+  if ((r = check_dup()) != ZE_OK) {     /* remove duplicates in found list */
+    if (r == ZE_PARMS) {
+      ZIPERR(r, "cannot repeat names in zip file");
+    }
+    else {
+      ZIPERR(r, "was processing list of files");
+    }
+  }
+
+  if (zcount)
+    free((zvoid *)zsort);
+
+  /* Check option combinations */
+  if (special == NULL) {
+    ZIPERR(ZE_PARMS, "missing suffix list");
+  }
+  if (level == 9 || !strcmp(special, ";") || !strcmp(special, ":"))
+    special = NULL; /* compress everything */
+
+  if (action == DELETE && (method != BEST || dispose || recurse ||
+      key != NULL || comadd || zipedit)) {
+    zipwarn("invalid option(s) used with -d; ignored.","");
+    /* reset flags - needed? */
+    method  = BEST;
+    dispose = 0;
+    recurse = 0;
+    if (key != NULL) {
+      free((zvoid *)key);
+      key   = NULL;
+    }
+    comadd  = 0;
+    zipedit = 0;
+  }
+  if (linkput && dosify)
+    {
+      zipwarn("can't use -y with -k, -y ignored", "");
+      linkput = 0;
+    }
+  if (fix && adjust)
+    {
+      zipwarn("can't use -F with -A, -F ignored", "");
+    }
+  if (test && !strcmp(zipfile, "-")) {
+    test = 0;
+    zipwarn("can't use -T on stdout, -T ignored", "");
+  }
+  if ((action != ADD || d) && !strcmp(zipfile, "-")) {
+    ZIPERR(ZE_PARMS, "can't use -d,-f,-u or -g on stdout\n");
+  }
+#if defined(EBCDIC)  && !defined(OS390)
+  if (aflag==ASCII && !translate_eol) {
+    /* Translation to ASCII implies EOL translation!
+     * (on OS390, consistent EOL translation is controlled separately)
+     * The default translation mode is "UNIX" mode (single LF terminators).
+     */
+    translate_eol = 2;
+  }
+#endif
+#ifdef CMS_MVS
+  if (aflag==ASCII && bflag)
+    ZIPERR(ZE_PARMS, "can't use -a with -B");
+#endif
+#ifdef VMS
+  if (!extra_fields && vms_native)
+    {
+      zipwarn("can't use -V with -X, -V ignored", "");
+      vms_native = 0;
+    }
+  if (vms_native && translate_eol)
+    ZIPERR(ZE_PARMS, "can't use -V with -l or -ll");
+#endif
+  if (zcount == 0 && (action != ADD || d)) {
+    zipwarn(zipfile, " not found or empty");
+  }
+
+/*
+ * XXX make some kind of mktemppath() function for each OS.
+ */
+
+#ifndef VM_CMS
+/* For CMS, leave tempath NULL.  A-disk will be used as default. */
+  /* If -b not specified, make temporary path the same as the zip file */
+#if defined(MSDOS) || defined(__human68k__) || defined(AMIGA)
+  if (tempath == NULL && ((p = MBSRCHR(zipfile, '/')) != NULL ||
+#  ifdef MSDOS
+                          (p = MBSRCHR(zipfile, '\\')) != NULL ||
+#  endif /* MSDOS */
+                          (p = MBSRCHR(zipfile, ':')) != NULL))
+  {
+    if (*p == ':')
+      p++;
+#else
+#ifdef RISCOS
+  if (tempath == NULL && (p = MBSRCHR(zipfile, '.')) != NULL)
+  {
+#else
+#ifdef QDOS
+  if (tempath == NULL && (p = LastDir(zipfile)) != NULL)
+  {
+#else
+  if (tempath == NULL && (p = MBSRCHR(zipfile, '/')) != NULL)
+  {
+#endif /* QDOS */
+#endif /* RISCOS */
+#endif /* MSDOS || __human68k__ || AMIGA */
+    if ((tempath = malloc((int)(p - zipfile) + 1)) == NULL) {
+      ZIPERR(ZE_MEM, "was processing arguments");
+    }
+    r = *p;  *p = 0;
+    strcpy(tempath, zipfile);
+    *p = (char)r;
+  }
+#endif /* VM_CMS */
+
+#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
+  if (!zp_tz_is_valid && action != DELETE) {
+    zipwarn("TZ environment variable not found, cannot use UTC times!!","");
+  }
+#endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */
+
+  /* For each marked entry, if not deleting, check if it exists, and if
+     updating or freshening, compare date with entry in old zip file.
+     Unmark if it doesn't exist or is too old, else update marked count. */
+#ifdef MACOS
+  PrintStatProgress("Getting file information ...");
+#endif
+  diag("stating marked entries");
+  k = 0;                        /* Initialize marked count */
+  for (z = zfiles; z != NULL; z = z->nxt)
+    if (z->mark) {
+#ifdef USE_EF_UT_TIME
+      iztimes f_utim, z_utim;
+#endif /* USE_EF_UT_TIME */
+      Trace((stderr, "zip diagnostics: marked file=%s\n", z->zname));
+
+      if (action != DELETE &&
+#ifdef USE_EF_UT_TIME
+          ((t = filetime(z->name, (ulg *)NULL, (long *)NULL, &f_utim))
+#else /* !USE_EF_UT_TIME */
+          ((t = filetime(z->name, (ulg *)NULL, (long *)NULL, (iztimes *)NULL))
+#endif /* ?USE_EF_UT_TIME */
+              == 0 ||
+           t < before || (after && t >= after) ||
+           ((action == UPDATE || action == FRESHEN) &&
+#ifdef USE_EF_UT_TIME
+            ((get_ef_ut_ztime(z, &z_utim) & EB_UT_FL_MTIME) ?
+             f_utim.mtime <= ROUNDED_TIME(z_utim.mtime) : t <= z->tim)
+#else /* !USE_EF_UT_TIME */
+            t <= z->tim
+#endif /* ?USE_EF_UT_TIME */
+           )))
+      {
+        z->mark = comadd ? 2 : 0;
+        z->trash = t && t >= before &&
+                   (after == 0 || t < after);   /* delete if -um or -fm */
+        if (verbose) {
+          fprintf(mesg, "zip diagnostic: %s %s\n", z->zname,
+                 z->trash ? "up to date" : "missing or early");
+        }
+      }
+      else
+        k++;
+    }
+
+  /* Remove entries from found list that do not exist or are too old */
+  diag("stating new entries");
+  Trace((stderr, "zip diagnostic: fcount=%u\n", (unsigned)fcount));
+  for (f = found; f != NULL;) {
+    Trace((stderr, "zip diagnostic: new file=%s\n", f->zname));
+    if (action == DELETE || action == FRESHEN ||
+        (t = filetime(f->name, (ulg *)NULL, (long *)NULL, (iztimes *)NULL))
+           == 0 ||
+        t < before || (after && t >= after) ||
+        (namecmp(f->zname, zipfile) == 0 && strcmp(zipfile, "-")))
+      f = fexpel(f);
+    else
+      f = f->nxt;
+  }
+#ifdef MACOS
+  PrintStatProgress("done");
+#endif
+
+  /* Make sure there's something left to do */
+  if (k == 0 && found == NULL &&
+      !(zfiles != NULL &&
+        (latest || fix || adjust || junk_sfx || comadd || zipedit))) {
+    if (test && (zfiles != NULL || zipbeg != 0)) {
+#ifndef WINDLL
+      check_zipfile(zipfile, argv[0]);
+#endif
+      RETURN(finish(ZE_OK));
+    }
+    if (action == UPDATE || action == FRESHEN) {
+      RETURN(finish(ZE_NONE));
+    }
+    else if (zfiles == NULL && (latest || fix || adjust || junk_sfx)) {
+      ZIPERR(ZE_NAME, zipfile);
+    }
+#ifndef WINDLL
+    else if (recurse && (pcount == 0) && (first_listarg > 0)) {
+#ifdef VMS
+      strcpy(errbuf, "try: zip \"");
+      for (i = 1; i < (first_listarg - 1); i++)
+        strcat(strcat(errbuf, argv[i]), "\" ");
+      strcat(strcat(errbuf, argv[i]), " *.* -i");
+#else /* !VMS */
+      strcpy(errbuf, "try: zip");
+      for (i = 1; i < first_listarg; i++)
+        strcat(strcat(errbuf, " "), argv[i]);
+#  ifdef AMIGA
+      strcat(errbuf, " \"\" -i");
+#  else
+      strcat(errbuf, " . -i");
+#  endif
+#endif /* ?VMS */
+      for (i = first_listarg; i < argc; i++)
+        strcat(strcat(errbuf, " "), argv[i]);
+      ZIPERR(ZE_NONE, errbuf);
+    }
+#endif /* !WINDLL */
+    else {
+      ZIPERR(ZE_NONE, zipfile);
+    }
+  }
+  d = (d && k == 0 && (zipbeg || zfiles != NULL)); /* d true if appending */
+
+#if CRYPT
+  /* Initialize the crc_32_tab pointer, when encryption was requested. */
+  if (key != NULL) {
+    crc_32_tab = get_crc_table();
+#ifdef EBCDIC
+    /* convert encryption key to ASCII (ISO variant for 8-bit ASCII chars) */
+    strtoasc(key, key);
+#endif /* EBCDIC */
+  }
+#endif /* CRYPT */
+
+  /* Before we get carried away, make sure zip file is writeable. This
+   * has the undesired side effect of leaving one empty junk file on a WORM,
+   * so when the zipfile does not exist already and when -b is specified,
+   * the writability check is made in replace().
+   */
+  if (strcmp(zipfile, "-"))
+  {
+    if (tempdir && zfiles == NULL && zipbeg == 0) {
+      a = 0;
+    } else {
+       x = zfiles == NULL && zipbeg == 0 ? fopen(zipfile, FOPW) :
+                                           fopen(zipfile, FOPM);
+      /* Note: FOPW and FOPM expand to several parameters for VMS */
+      if (x == NULL) {
+        ZIPERR(ZE_CREAT, zipfile);
+      }
+      fclose(x);
+      a = getfileattr(zipfile);
+      if (zfiles == NULL && zipbeg == 0)
+        destroy(zipfile);
+    }
+  }
+  else
+    a = 0;
+
+  /* Throw away the garbage in front of the zip file for -J */
+  if (junk_sfx) zipbeg = 0;
+
+  /* Open zip file and temporary output file */
+  diag("opening zip file and creating temporary zip file");
+  x = NULL;
+  tempzn = 0;
+  if (strcmp(zipfile, "-") == 0)
+  {
+#ifdef MSDOS
+    /* It is nonsense to emit the binary data stream of a zipfile to
+     * the (text mode) console.  This case should already have been caught
+     * in a call to zipstdout() far above.  Therefore, if the following
+     * failsafe check detects a console attached to stdout, zip is stopped
+     * with an "internal logic error"!  */
+    if (isatty(fileno(stdout)))
+      ZIPERR(ZE_LOGIC, "tried to write binary zipfile data to console!");
+    /* Set stdout mode to binary for MSDOS systems */
+#  ifdef __HIGHC__
+    setmode(stdout, _BINARY);
+#  else
+    setmode(fileno(stdout), O_BINARY);
+#  endif
+    tempzf = y = fdopen(fileno(stdout), FOPW);
+#else
+    tempzf = y = stdout;
+#endif
+    /* tempzip must be malloced so a later free won't barf */
+    tempzip = malloc(4);
+    if (tempzip == NULL) {
+      ZIPERR(ZE_MEM, "allocating temp filename");
+    }
+    strcpy(tempzip, "-");
+  }
+  else if (d) /* d true if just appending (-g) */
+  {
+    if ((y = fopen(zipfile, FOPM)) == NULL) {
+      ZIPERR(ZE_NAME, zipfile);
+    }
+    tempzip = zipfile;
+    tempzf = y;
+    if (fseek(y, cenbeg, SEEK_SET)) {
+      ZIPERR(ferror(y) ? ZE_READ : ZE_EOF, zipfile);
+    }
+    tempzn = cenbeg;
+  }
+  else
+  {
+    if ((zfiles != NULL || zipbeg) && (x = fopen(zipfile, FOPR_EX)) == NULL) {
+      ZIPERR(ZE_NAME, zipfile);
+    }
+    if ((tempzip = tempname(zipfile)) == NULL) {
+      ZIPERR(ZE_MEM, "allocating temp filename");
+    }
+    if ((tempzf = y = fopen(tempzip, FOPW_TMP)) == NULL) {
+      ZIPERR(ZE_TEMP, tempzip);
+    }
+  }
+
+#if (!defined(VMS) && !defined(CMS_MVS))
+  /* Use large buffer to speed up stdio: */
+#if (defined(_IOFBF) || !defined(BUFSIZ))
+  zipbuf = (char *)malloc(ZBSZ);
+#else
+  zipbuf = (char *)malloc(BUFSIZ);
+#endif
+  if (zipbuf == NULL) {
+    ZIPERR(ZE_MEM, tempzip);
+  }
+# ifdef _IOFBF
+  setvbuf(y, zipbuf, _IOFBF, ZBSZ);
+# else
+  setbuf(y, zipbuf);
+# endif /* _IOBUF */
+#endif /* !VMS  && !CMS_MVS */
+
+  if (strcmp(zipfile, "-") != 0 && !d)  /* this must go *after* set[v]buf */
+  {
+    if (zipbeg && (r = fcopy(x, y, zipbeg)) != ZE_OK) {
+      ZIPERR(r, r == ZE_TEMP ? tempzip : zipfile);
+      }
+    tempzn = zipbeg;
+  }
+
+  o = 0;                                /* no ZE_OPEN errors yet */
+
+
+  /* Process zip file, updating marked files */
+#ifdef DEBUG
+  if (zfiles != NULL)
+    diag("going through old zip file");
+#endif
+  w = &zfiles;
+  while ((z = *w) != NULL) {
+    if (z->mark == 1)
+    {
+      /* if not deleting, zip it up */
+      if (action != DELETE)
+      {
+        if (noisy)
+        {
+          if (action == FRESHEN)
+             fprintf(mesg, "freshening: %s", z->zname);
+          else
+             fprintf(mesg, "updating: %s", z->zname);
+          fflush(mesg);
+        }
+        if ((r = zipup(z, y)) != ZE_OK && r != ZE_OPEN && r != ZE_MISS)
+        {
+          if (noisy)
+          {
+#if (!defined(MACOS) && !defined(WINDLL))
+            putc('\n', mesg);
+            fflush(mesg);
+#else
+            fprintf(stdout, "\n");
+#endif
+          }
+          sprintf(errbuf, "was zipping %s", z->name);
+          ZIPERR(r, errbuf);
+        }
+        if (r == ZE_OPEN || r == ZE_MISS)
+        {
+          o = 1;
+          if (noisy)
+          {
+#if (!defined(MACOS) && !defined(WINDLL))
+            putc('\n', mesg);
+            fflush(mesg);
+#else
+            fprintf(stdout, "\n");
+#endif
+          }
+          if (r == ZE_OPEN) {
+            perror(z->zname);
+            zipwarn("could not open for reading: ", z->zname);
+          } else {
+            zipwarn("file and directory with the same name: ", z->zname);
+          }
+          zipwarn("will just copy entry over: ", z->zname);
+          if ((r = zipcopy(z, x, y)) != ZE_OK)
+          {
+            sprintf(errbuf, "was copying %s", z->zname);
+            ZIPERR(r, errbuf);
+          }
+          z->mark = 0;
+        }
+        w = &z->nxt;
+      }
+      else
+      {
+        if (noisy)
+        {
+          fprintf(mesg, "deleting: %s\n", z->zname);
+          fflush(mesg);
+        }
+#ifdef WINDLL
+        if (lpZipUserFunctions->ServiceApplication != NULL) {
+          if ((*lpZipUserFunctions->ServiceApplication)(z->zname, 0))
+            ZIPERR(ZE_ABORT, "User terminated operation");
+        }
+#endif
+        v = z->nxt;                     /* delete entry from list */
+        free((zvoid *)(z->iname));
+        free((zvoid *)(z->zname));
+        if (z->ext)
+          free((zvoid *)(z->extra));
+        if (z->cext && z->cextra != z->extra)
+          free((zvoid *)(z->cextra));
+        if (z->com)
+          free((zvoid *)(z->comment));
+        farfree((zvoid far *)z);
+        *w = v;
+        zcount--;
+      }
+    }
+    else
+    {
+      /* copy the original entry verbatim */
+      if (!d && (r = zipcopy(z, x, y)) != ZE_OK)
+      {
+        sprintf(errbuf, "was copying %s", z->zname);
+        ZIPERR(r, errbuf);
+      }
+      w = &z->nxt;
+    }
+  }
+
+
+  /* Process the edited found list, adding them to the zip file */
+  diag("zipping up new entries, if any");
+  Trace((stderr, "zip diagnostic: fcount=%u\n", (unsigned)fcount));
+  for (f = found; f != NULL; f = fexpel(f))
+  {
+    /* add a new zfiles entry and set the name */
+    if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL) {
+      ZIPERR(ZE_MEM, "was adding files to zip file");
+    }
+    z->nxt = NULL;
+    z->name = f->name;
+    f->name = NULL;
+    z->iname = f->iname;
+    f->iname = NULL;
+    z->zname = f->zname;
+    f->zname = NULL;
+    z->ext = z->cext = z->com = 0;
+    z->extra = z->cextra = NULL;
+    z->mark = 1;
+    z->dosflag = f->dosflag;
+    /* zip it up */
+    if (noisy)
+    {
+      fprintf(mesg, "  adding: %s", z->zname);
+      fflush(mesg);
+    }
+    if ((r = zipup(z, y)) != ZE_OK  && r != ZE_OPEN && r != ZE_MISS)
+    {
+      if (noisy)
+      {
+#if (!defined(MACOS) && !defined(WINDLL))
+        putc('\n', mesg);
+        fflush(mesg);
+#else
+        fprintf(stdout, "\n");
+#endif
+      }
+      sprintf(errbuf, "was zipping %s", z->zname);
+      ZIPERR(r, errbuf);
+    }
+    if (r == ZE_OPEN || r == ZE_MISS)
+    {
+      o = 1;
+      if (noisy)
+      {
+#if (!defined(MACOS) && !defined(WINDLL))
+        putc('\n', mesg);
+        fflush(mesg);
+#else
+        fprintf(stdout, "\n");
+#endif
+      }
+      if (r == ZE_OPEN) {
+        perror("zip warning");
+        zipwarn("could not open for reading: ", z->zname);
+      } else {
+        zipwarn("file and directory with the same name: ", z->zname);
+      }
+      free((zvoid *)(z->name));
+      free((zvoid *)(z->iname));
+      free((zvoid *)(z->zname));
+      farfree((zvoid far *)z);
+    }
+    else
+    {
+      *w = z;
+      w = &z->nxt;
+      zcount++;
+    }
+  }
+  if (key != NULL)
+  {
+    free((zvoid *)key);
+    key = NULL;
+  }
+
+
+  /* Get one line comment for each new entry */
+#if defined(AMIGA) || defined(MACOS)
+  if (comadd || filenotes)
+  {
+    if (comadd)
+#else
+  if (comadd)
+  {
+#endif
+    {
+      if (comment_stream == NULL) {
+#ifndef RISCOS
+        comment_stream = (FILE*)fdopen(fileno(stderr), "r");
+#else
+        comment_stream = stderr;
+#endif
+      }
+      if ((e = malloc(MAXCOM + 1)) == NULL) {
+        ZIPERR(ZE_MEM, "was reading comment lines");
+      }
+    }
+#ifdef __human68k__
+    setmode(fileno(comment_stream), O_TEXT);
+#endif
+#ifdef MACOS
+    if (noisy) fprintf(mesg, "\nStart commenting files ...\n");
+#endif
+    for (z = zfiles; z != NULL; z = z->nxt)
+      if (z->mark)
+#if defined(AMIGA) || defined(MACOS)
+        if (filenotes && (p = GetComment(z->zname)))
+        {
+          if (z->comment = malloc(k = strlen(p)+1))
+          {
+            z->com = k;
+            strcpy(z->comment, p);
+          }
+          else
+          {
+            free((zvoid *)e);
+            ZIPERR(ZE_MEM, "was reading filenotes");
+          }
+        }
+        else if (comadd)
+#endif /* AMIGA || MACOS */
+        {
+          if (noisy)
+            fprintf(mesg, "Enter comment for %s:\n", z->zname);
+          if (fgets(e, MAXCOM+1, comment_stream) != NULL)
+          {
+            if ((p = malloc((k = strlen(e))+1)) == NULL)
+            {
+              free((zvoid *)e);
+              ZIPERR(ZE_MEM, "was reading comment lines");
+            }
+            strcpy(p, e);
+            if (p[k-1] == '\n')
+              p[--k] = 0;
+            z->comment = p;
+            z->com = k;
+          }
+        }
+#ifdef MACOS
+    if (noisy) fprintf(mesg, "\n...done");
+#endif
+#if defined(AMIGA) || defined(MACOS)
+    if (comadd)
+      free((zvoid *)e);
+    GetComment(NULL);           /* makes it free its internal storage */
+#else
+    free((zvoid *)e);
+#endif
+  }
+
+  /* Get multi-line comment for the zip file */
+  if (zipedit)
+  {
+#ifndef WINDLL
+    if (comment_stream == NULL) {
+#ifndef RISCOS
+      comment_stream = (FILE*)fdopen(fileno(stderr), "r");
+#else
+      comment_stream = stderr;
+#endif
+    }
+    if ((e = malloc(MAXCOM + 1)) == NULL) {
+      ZIPERR(ZE_MEM, "was reading comment lines");
+    }
+    if (noisy && zcomlen)
+    {
+      fputs("current zip file comment is:\n", mesg);
+      fwrite(zcomment, 1, zcomlen, mesg);
+      if (zcomment[zcomlen-1] != '\n')
+        putc('\n', mesg);
+      free((zvoid *)zcomment);
+    }
+    if ((zcomment = malloc(1)) == NULL)
+      ZIPERR(ZE_MEM, "was setting comments to null");
+    zcomment[0] = '\0';
+    if (noisy)
+      fputs("enter new zip file comment (end with .):\n", mesg);
+#if (defined(AMIGA) && (defined(LATTICE)||defined(__SASC)))
+    flushall();  /* tty input/output is out of sync here */
+#endif
+#ifdef __human68k__
+    setmode(fileno(comment_stream), O_TEXT);
+#endif
+#ifdef MACOS
+    printf("\n enter new zip file comment \n");
+    if (fgets(e, MAXCOM+1, comment_stream) != NULL) {
+        if ((p = malloc((k = strlen(e))+1)) == NULL) {
+            free((zvoid *)e);
+            ZIPERR(ZE_MEM, "was reading comment lines");
+        }
+        strcpy(p, e);
+        if (p[k-1] == '\n') p[--k] = 0;
+        zcomment = p;
+    }
+#else /* !MACOS */
+    while (fgets(e, MAXCOM+1, comment_stream) != NULL && strcmp(e, ".\n"))
+    {
+      if (e[(r = strlen(e)) - 1] == '\n')
+        e[--r] = 0;
+      if ((p = malloc((*zcomment ? strlen(zcomment) + 3 : 1) + r)) == NULL)
+      {
+        free((zvoid *)e);
+        ZIPERR(ZE_MEM, "was reading comment lines");
+      }
+      if (*zcomment)
+        strcat(strcat(strcpy(p, zcomment), "\r\n"), e);
+      else
+        strcpy(p, *e ? e : "\r\n");
+      free((zvoid *)zcomment);
+      zcomment = p;
+    }
+#endif /* ?MACOS */
+    free((zvoid *)e);
+#else /* WINDLL */
+    comment(zcomlen);
+    if ((p = malloc(strlen(szCommentBuf)+1)) == NULL) {
+      ZIPERR(ZE_MEM, "was setting comments to null");
+    }
+    if (szCommentBuf[0] != '\0')
+       lstrcpy(p, szCommentBuf);
+    else
+       p[0] = '\0';
+    free((zvoid *)zcomment);
+    GlobalUnlock(hStr);
+    GlobalFree(hStr);
+    zcomment = p;
+#endif /* WINDLL */
+    zcomlen = strlen(zcomment);
+  }
+
+
+  /* Write central directory and end header to temporary zip */
+  diag("writing central directory");
+  k = 0;                        /* keep count for end header */
+  c = tempzn;                   /* get start of central */
+  n = t = 0;
+  for (z = zfiles; z != NULL; z = z->nxt)
+  {
+    if ((r = putcentral(z, y)) != ZE_OK) {
+      ZIPERR(r, tempzip);
+    }
+    tempzn += 4 + CENHEAD + z->nam + z->cext + z->com;
+    n += z->len;
+    t += z->siz;
+    k++;
+  }
+  if (k == 0)
+    zipwarn("zip file empty", "");
+  if (verbose)
+    fprintf(mesg, "total bytes=%lu, compressed=%lu -> %d%% savings\n",
+           n, t, percent(n, t));
+  t = tempzn - c;               /* compute length of central */
+  diag("writing end of central directory");
+  if ((r = putend(k, t, c, zcomlen, zcomment, y)) != ZE_OK) {
+    ZIPERR(r, tempzip);
+  }
+  tempzf = NULL;
+  if (fclose(y)) {
+    ZIPERR(d ? ZE_WRITE : ZE_TEMP, tempzip);
+  }
+  if (x != NULL)
+    fclose(x);
+
+  /* Free some memory before spawning unzip */
+#ifdef USE_ZLIB
+  zl_deflate_free();
+#else
+  lm_free();
+#endif
+
+#ifndef WINDLL
+  /* Test new zip file before overwriting old one or removing input files */
+  if (test)
+    check_zipfile(tempzip, argv[0]);
+#endif
+  /* Replace old zip file with new zip file, leaving only the new one */
+  if (strcmp(zipfile, "-") && !d)
+  {
+    diag("replacing old zip file with new zip file");
+    if ((r = replace(zipfile, tempzip)) != ZE_OK)
+    {
+      zipwarn("new zip file left as: ", tempzip);
+      free((zvoid *)tempzip);
+      tempzip = NULL;
+      ZIPERR(r, "was replacing the original zip file");
+    }
+    free((zvoid *)tempzip);
+  }
+  tempzip = NULL;
+  if (a && strcmp(zipfile, "-")) {
+    setfileattr(zipfile, a);
+#ifdef VMS
+    /* If the zip file existed previously, restore its record format: */
+    if (x != NULL)
+      (void)VMSmunch(zipfile, RESTORE_RTYPE, NULL);
+#endif
+  }
+
+#ifdef __BEOS__
+  /* Set the filetype of the zipfile to "application/zip" */
+  setfiletype( zipfile, "application/zip" );
+#endif
+
+#ifdef __ATHEOS__
+  /* Set the filetype of the zipfile to "application/x-zip" */
+  setfiletype(zipfile, "application/x-zip");
+#endif
+
+#ifdef MACOS
+  /* Set the Creator/Type of the zipfile to 'IZip' and 'ZIP ' */
+  setfiletype(zipfile, 'IZip', 'ZIP ');
+#endif
+
+#ifdef RISCOS
+  /* Set the filetype of the zipfile to &DDC */
+  setfiletype(zipfile, 0xDDC);
+#endif
+
+  /* Finish up (process -o, -m, clean up).  Exit code depends on o. */
+#if (!defined(VMS) && !defined(CMS_MVS))
+  free((zvoid *) zipbuf);
+#endif /* !VMS && !CMS_MVS */
+  RETURN(finish(o ? ZE_OPEN : ZE_OK));
+}
diff --git a/zip.h b/zip.h
new file mode 100644 (file)
index 0000000..e8b3e30
--- /dev/null
+++ b/zip.h
@@ -0,0 +1,567 @@
+/*
+This is version 2005-Feb-10 of the Info-ZIP copyright and license.
+The definitive version of this document should be available at
+ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely.
+
+
+Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+For the purposes of this copyright and license, "Info-ZIP" is defined as
+the following set of individuals:
+
+   Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,
+   Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,
+   Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,
+   David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,
+   Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,
+   Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,
+   Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,
+   Rich Wales, Mike White
+
+This software is provided "as is," without warranty of any kind, express
+or implied.  In no event shall Info-ZIP or its contributors be held liable
+for any direct, indirect, incidental, special or consequential damages
+arising out of the use of or inability to use this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+    1. Redistributions of source code must retain the above copyright notice,
+       definition, disclaimer, and this list of conditions.
+
+    2. Redistributions in binary form (compiled executables) must reproduce
+       the above copyright notice, definition, disclaimer, and this list of
+       conditions in documentation and/or other materials provided with the
+       distribution.  The sole exception to this condition is redistribution
+       of a standard UnZipSFX binary (including SFXWiz) as part of a
+       self-extracting archive; that is permitted without inclusion of this
+       license, as long as the normal SFX banner has not been removed from
+       the binary or disabled.
+
+    3. Altered versions--including, but not limited to, ports to new operating
+       systems, existing ports with new graphical interfaces, and dynamic,
+       shared, or static library versions--must be plainly marked as such
+       and must not be misrepresented as being the original source.  Such
+       altered versions also must not be misrepresented as being Info-ZIP
+       releases--including, but not limited to, labeling of the altered
+       versions with the names "Info-ZIP" (or any variation thereof, including,
+       but not limited to, different capitalizations), "Pocket UnZip," "WiZ"
+       or "MacZip" without the explicit permission of Info-ZIP.  Such altered
+       versions are further prohibited from misrepresentative use of the
+       Zip-Bugs or Info-ZIP e-mail addresses or of the Info-ZIP URL(s).
+
+    4. Info-ZIP retains the right to use the names "Info-ZIP," "Zip," "UnZip,"
+       "UnZipSFX," "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip" for its
+       own source and binary releases.
+*/
+
+/*
+ *  zip.h by Mark Adler
+ */
+#ifndef __zip_h
+#define __zip_h 1
+
+#define ZIP   /* for crypt.c:  include zip password functions, not unzip */
+
+/* Set up portability */
+#include "tailor.h"
+
+#ifdef USE_ZLIB
+#  include "zlib.h"
+#endif
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#ifndef WSIZE
+#  define WSIZE  (0x8000)
+#endif
+/* Maximum window size = 32K. If you are really short of memory, compile
+ * with a smaller WSIZE but this reduces the compression ratio for files
+ * of size > WSIZE. WSIZE must be a power of two in the current implementation.
+ */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST  (WSIZE-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+/* Forget FILENAME_MAX (incorrectly = 14 on some System V) */
+#ifdef DOS
+#  define FNMAX 256
+#else
+#  define FNMAX 1024
+#endif
+
+#ifndef MATCH
+#  define MATCH shmatch         /* Default for pattern matching: UNIX style */
+#endif
+
+/* Types centralized here for easy modification */
+#define local static            /* More meaningful outside functions */
+typedef unsigned char uch;      /* unsigned 8-bit value */
+typedef unsigned short ush;     /* unsigned 16-bit value */
+typedef unsigned long ulg;      /* unsigned 32-bit value */
+
+
+/* Structure carrying extended timestamp information */
+typedef struct iztimes {
+   time_t atime;                /* new access time */
+   time_t mtime;                /* new modification time */
+   time_t ctime;                /* new creation time (!= Unix st.ctime) */
+} iztimes;
+
+/* Lengths of headers after signatures in bytes */
+#define LOCHEAD 26
+#define CENHEAD 42
+#define ENDHEAD 18
+
+/* Structures for in-memory file information */
+struct zlist {
+  /* See central header in zipfile.c for what vem..off are */
+  ush vem, ver, flg, how;
+  ulg tim, crc, siz, len;
+  extent nam, ext, cext, com;   /* offset of ext must be >= LOCHEAD */
+  ush dsk, att, lflg;           /* offset of lflg must be >= LOCHEAD */
+  ulg atx, off;
+  char *name;                   /* File name in zip file */
+  char *extra;                  /* Extra field (set only if ext != 0) */
+  char *cextra;                 /* Extra in central (set only if cext != 0) */
+  char *comment;                /* Comment (set only if com != 0) */
+  char *iname;                  /* Internal file name after cleanup */
+  char *zname;                  /* External version of internal name */
+  int mark;                     /* Marker for files to operate on */
+  int trash;                    /* Marker for files to delete */
+  int dosflag;                  /* Set to force MSDOS file attributes */
+  struct zlist far *nxt;        /* Pointer to next header in list */
+};
+struct flist {
+  char *name;                   /* Raw internal file name */
+  char *iname;                  /* Internal file name after cleanup */
+  char *zname;                  /* External version of internal name */
+  int dosflag;                  /* Set to force MSDOS file attributes */
+  struct flist far *far *lst;   /* Pointer to link pointing here */
+  struct flist far *nxt;        /* Link to next name */
+};
+struct plist {
+  char *zname;                  /* External version of internal name */
+  int select;                   /* Selection flag ('i' or 'x') */
+};
+
+/* internal file attribute */
+#define UNKNOWN (-1)
+#define BINARY  0
+#define ASCII   1
+#define __EBCDIC 2
+
+/* extra field definitions */
+#define EF_VMCMS     0x4704   /* VM/CMS Extra Field ID ("G")*/
+#define EF_MVS       0x470f   /* MVS Extra Field ID ("G")   */
+#define EF_IZUNIX    0x5855   /* UNIX Extra Field ID ("UX") */
+#define EF_IZUNIX2   0x7855   /* Info-ZIP's new Unix ("Ux") */
+#define EF_TIME      0x5455   /* universal timestamp ("UT") */
+#define EF_OS2EA     0x0009   /* OS/2 Extra Field ID (extended attributes) */
+#define EF_ACL       0x4C41   /* ACL Extra Field ID (access control list, "AL") */
+#define EF_NTSD      0x4453   /* NT Security Descriptor Extra Field ID, ("SD") */
+#define EF_BEOS      0x6542   /* BeOS Extra Field ID ("Be") */
+#define EF_ATHEOS    0x7441   /* AtheOS Extra Field ID ("At") */
+#define EF_QDOS      0xfb4a   /* SMS/QDOS ("J\373") */
+#define EF_AOSVS     0x5356   /* AOS/VS ("VS") */
+#define EF_SPARK     0x4341   /* David Pilling's Acorn/SparkFS ("AC") */
+#define EF_THEOS     0x6854   /* THEOS ("Th") */
+#define EF_TANDEM    0x4154   /* Tandem NSK ("TA") */
+
+/* Definitions for extra field handling: */
+#define EF_SIZE_MAX  ((unsigned)0xFFFF) /* hard limit of total e.f. length */
+#define EB_HEADSIZE       4     /* length of a extra field block header */
+#define EB_ID             0     /* offset of block ID in header */
+#define EB_LEN            2     /* offset of data length field in header */
+#define EB_MEMCMPR_HSIZ   6     /* header length for memcompressed data */
+#define EB_DEFLAT_EXTRA  10     /* overhead for 64kByte "undeflatable" data */
+
+#define EB_UX_MINLEN      8     /* minimal "UX" field contains atime, mtime */
+#define EB_UX_ATIME       0     /* offset of atime in "UX" extra field data */
+#define EB_UX_MTIME       4     /* offset of mtime in "UX" extra field data */
+
+#define EB_UX_FULLSIZE    12    /* full "UX" field (atime, mtime, uid, gid) */
+#define EB_UX_UID         8     /* byte offset of UID in "UX" field data */
+#define EB_UX_GID         10    /* byte offset of GID in "UX" field data */
+
+#define EB_UT_MINLEN      1     /* minimal UT field contains Flags byte */
+#define EB_UT_FLAGS       0     /* byte offset of Flags field */
+#define EB_UT_TIME1       1     /* byte offset of 1st time value */
+#define EB_UT_FL_MTIME    (1 << 0)      /* mtime present */
+#define EB_UT_FL_ATIME    (1 << 1)      /* atime present */
+#define EB_UT_FL_CTIME    (1 << 2)      /* ctime present */
+#define EB_UT_LEN(n)      (EB_UT_MINLEN + 4 * (n))
+
+#define EB_UX2_MINLEN     4     /* minimal Ux field contains UID/GID */
+#define EB_UX2_UID        0     /* byte offset of UID in "Ux" field data */
+#define EB_UX2_GID        2     /* byte offset of GID in "Ux" field data */
+#define EB_UX2_VALID      (1 << 8)      /* UID/GID present */
+
+/* ASCII definitions for line terminators in text files: */
+#define LF     10        /* '\n' on ASCII machines; must be 10 due to EBCDIC */
+#define CR     13        /* '\r' on ASCII machines; must be 13 due to EBCDIC */
+#define CTRLZ  26        /* DOS & OS/2 EOF marker (used in fileio.c, vms.c) */
+
+/* return codes of password fetches (negative: user abort; positive: error) */
+#define IZ_PW_ENTERED   0       /* got some PWD string, use/try it */
+#define IZ_PW_CANCEL    -1      /* no password available (for this entry) */
+#define IZ_PW_CANCELALL -2      /* no password, skip any further PWD request */
+#define IZ_PW_ERROR     5       /* = PK_MEM2 : failure (no mem, no tty, ...) */
+#define IZ_PW_SKIPVERIFY IZ_PW_CANCEL   /* skip encrypt. passwd verification */
+
+/* mode flag values of password prompting function */
+#define ZP_PW_ENTER     0       /* request for encryption password */
+#define ZP_PW_VERIFY    1       /* request for reentering password */
+
+/* Error return codes and PERR macro */
+#include "ziperr.h"
+
+#if 0            /* Optimization: use the (const) result of crc32(0L,NULL,0) */
+#  define CRCVAL_INITIAL  crc32(0L, (uch *)NULL, 0)
+#else
+#  define CRCVAL_INITIAL  0L
+#endif
+
+#define DOSTIME_MINIMUM         ((ulg)0x00210000L)
+#define DOSTIME_2038_01_18      ((ulg)0x74320000L)
+
+
+/* Public globals */
+extern uch upper[256];          /* Country dependent case map table */
+extern uch lower[256];
+#ifdef EBCDIC
+extern ZCONST uch ascii[256];   /* EBCDIC <--> ASCII translation tables */
+extern ZCONST uch ebcdic[256];
+#endif /* EBCDIC */
+#ifdef IZ_ISO2OEM_ARRAY         /* ISO 8859-1 (Win CP 1252) --> OEM CP 850 */
+extern ZCONST uch Far iso2oem[128];
+#endif
+#ifdef IZ_OEM2ISO_ARRAY         /* OEM CP 850 --> ISO 8859-1 (Win CP 1252) */
+extern ZCONST uch Far oem2iso[128];
+#endif
+extern char errbuf[FNMAX+81];   /* Handy place to build error messages */
+extern int recurse;             /* Recurse into directories encountered */
+extern int dispose;             /* Remove files after put in zip file */
+extern int pathput;             /* Store path with name */
+
+#ifdef RISCOS
+extern int scanimage;           /* Scan through image files */
+#endif
+
+#define BEST -1                 /* Use best method (deflation or store) */
+#define STORE 0                 /* Store method */
+#define DEFLATE 8               /* Deflation method*/
+extern int method;              /* Restriction on compression method */
+
+extern int dosify;              /* Make new entries look like MSDOS */
+extern char *special;           /* Don't compress special suffixes */
+extern int verbose;             /* Report oddities in zip file structure */
+extern int fix;                 /* Fix the zip file */
+extern int adjust;              /* Adjust the unzipsfx'd zip file */
+extern int level;               /* Compression level */
+extern int translate_eol;       /* Translate end-of-line LF -> CR LF */
+#ifdef VMS
+   extern int vmsver;           /* Append VMS version number to file names */
+   extern int vms_native;       /* Store in VMS format */
+#endif /* VMS */
+#if defined(OS2) || defined(WIN32)
+   extern int use_longname_ea;   /* use the .LONGNAME EA as the file's name */
+#endif
+#if defined (QDOS) || defined(QLZIP)
+extern short qlflag;
+#endif
+extern int hidden_files;        /* process hidden and system files */
+extern int volume_label;        /* add volume label */
+extern int dirnames;            /* include directory names */
+extern int linkput;             /* Store symbolic links as such */
+extern int noisy;               /* False for quiet operation */
+extern int extra_fields;        /* do not create extra fields */
+#ifdef NTSD_EAS
+    extern int use_privileges;  /* use security privilege overrides */
+#endif
+extern char *key;               /* Scramble password or NULL */
+extern char *tempath;           /* Path for temporary files */
+extern FILE *mesg;              /* Where informational output goes */
+extern char *zipfile;           /* New or existing zip archive (zip file) */
+extern ulg zipbeg;              /* Starting offset of zip structures */
+extern ulg cenbeg;              /* Starting offset of central directory */
+extern struct zlist far *zfiles;/* Pointer to list of files in zip file */
+extern extent zcount;           /* Number of files in zip file */
+extern extent zcomlen;          /* Length of zip file comment */
+extern char *zcomment;          /* Zip file comment (not zero-terminated) */
+extern struct zlist far **zsort;/* List of files sorted by name */
+extern ulg tempzn;              /* Count of bytes written to output zip file */
+extern struct flist far *found; /* List of names found */
+extern struct flist far *far *fnxt;     /* Where to put next in found list */
+extern extent fcount;           /* Count of names in found list */
+
+extern struct plist *patterns;  /* List of patterns to be matched */
+extern unsigned pcount;         /* number of patterns */
+extern unsigned icount;         /* number of include only patterns */
+
+#ifdef IZ_CHECK_TZ
+extern int zp_tz_is_valid;      /* signals "timezone info is available" */
+#endif
+#if (defined(MACOS) || defined(WINDLL))
+extern int zipstate;            /* flag "zipfile has been stat()'ed */
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+# ifdef MSDOS
+#  undef  stderr
+#  define stderr stdout
+# endif
+#  define diag(where) fprintf(stderr, "zip diagnostic: %s\n", where)
+#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+# ifdef THEOS
+#  define Trace(x) _fprintf x
+#  define Tracev(x) {if (verbose) _fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) _fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) _fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) _fprintf x ;}
+# else
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+# endif
+#else
+#  define diag(where)
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+#ifdef DEBUGNAMES
+#  define free(x) { int *v;Free(x); v=x;*v=0xdeadbeef;x=(void *)0xdeadbeef; }
+#endif
+
+/* Public function prototypes */
+
+#ifndef UTIL
+#ifdef USE_ZIPMAIN
+int zipmain OF((int, char **));
+#else
+int main OF((int, char **));
+#endif /* USE_ZIPMAIN */
+#endif
+
+#ifdef EBCDIC
+extern int aflag;
+#endif /* EBCDIC */
+#ifdef CMS_MVS
+extern int bflag;
+#endif /* CMS_MVS */
+void zipwarn  OF((ZCONST char *, ZCONST char *));
+void ziperr   OF((int, ZCONST char *));
+#ifdef UTIL
+#  define error(msg)    ziperr(ZE_LOGIC, msg)
+#else
+   void error OF((ZCONST char *));
+#  ifdef VMSCLI
+     void help OF((void));
+#  endif
+   int encr_passwd OF((int, char *, int, ZCONST char *));
+#endif
+
+        /* in zipup.c */
+#ifndef UTIL
+   int percent OF((ulg, ulg));
+   int zipup OF((struct zlist far *, FILE *));
+#  ifdef USE_ZLIB
+     void zl_deflate_free OF((void));
+#  else
+     void flush_outbuf OF((char *, unsigned *));
+     int seekable OF((void));
+     extern unsigned (*read_buf) OF((char *, unsigned int));
+#  endif /* !USE_ZLIB */
+#  ifdef ZP_NEED_MEMCOMPR
+     ulg memcompress OF((char *, ulg, char *, ulg));
+#  endif
+#endif /* !UTIL */
+
+        /* in zipfile.c */
+#ifndef UTIL
+   struct zlist far *zsearch OF((ZCONST char *));
+#  ifdef USE_EF_UT_TIME
+     int get_ef_ut_ztime OF((struct zlist far *, iztimes *));
+#  endif /* USE_EF_UT_TIME */
+   int trash OF((void));
+#endif /* !UTIL */
+char *ziptyp OF((char *));
+int readzipfile OF((void));
+int putlocal OF((struct zlist far *, FILE *));
+int putextended OF((struct zlist far *, FILE *));
+int putcentral OF((struct zlist far *, FILE *));
+int putend OF((int, ulg, ulg, extent, char *, FILE *));
+int zipcopy OF((struct zlist far *, FILE *, FILE *));
+
+        /* in fileio.c */
+#ifndef UTIL
+   char *getnam OF((char *, FILE *));
+   struct flist far *fexpel OF((struct flist far *));
+   char *last OF((char *, int));
+   char *msname OF((char *));
+   int check_dup OF((void));
+   int filter OF((char *, int));
+   int newname OF((char *, int, int));
+#endif /* !UTIL */
+#if (!defined(UTIL) || defined(W32_STATROOT_FIX))
+   time_t dos2unixtime OF((ulg));
+#endif
+#ifndef UTIL
+   ulg dostime OF((int, int, int, int, int, int));
+   ulg unix2dostime OF((time_t *));
+   int issymlnk OF((ulg a));
+#  ifdef S_IFLNK
+#    define rdsymlnk(p,b,n) readlink(p,b,n)
+/*   extern int readlink OF((char *, char *, int)); */
+#  else /* !S_IFLNK */
+#    define rdsymlnk(p,b,n) (0)
+#  endif /* !S_IFLNK */
+#endif /* !UTIL */
+
+int destroy OF((char *));
+int replace OF((char *, char *));
+int getfileattr OF((char *));
+int setfileattr OF((char *, int));
+char *tempname OF((char *));
+int fcopy OF((FILE *, FILE *, ulg));
+
+#ifdef ZMEM
+   char *memset OF((char *, int, unsigned int));
+   char *memcpy OF((char *, char *, unsigned int));
+   int memcmp OF((char *, char *, unsigned int));
+#endif /* ZMEM */
+
+        /* in system dependent fileio code (<system>.c) */
+#ifndef UTIL
+#  ifdef PROCNAME
+     int wild OF((char *));
+#  endif
+   char *in2ex OF((char *));
+   char *ex2in OF((char *, int, int *));
+   int procname OF((char *, int));
+   void stamp OF((char *, ulg));
+   ulg filetime OF((char *, ulg *, long *, iztimes *));
+#if !(defined(VMS) && defined(VMS_PK_EXTRA))
+   int set_extra_field OF((struct zlist far *, iztimes *));
+#endif /* ?(VMS && VMS_PK_EXTRA) */
+   int deletedir OF((char *));
+#ifdef MY_ZCALLOC
+     zvoid far *zcalloc OF((unsigned int, unsigned int));
+     zvoid zcfree       OF((zvoid far *));
+#endif /* MY_ZCALLOC */
+#endif /* !UTIL */
+void version_local OF((void));
+
+        /* in util.c */
+#ifndef UTIL
+int   fseekable    OF((FILE *));
+char *isshexp      OF((char *));
+int   shmatch      OF((ZCONST char *, ZCONST char *, int));
+#if defined(DOS) || defined(WIN32)
+   int dosmatch    OF((ZCONST char *, ZCONST char *, int));
+#endif /* DOS || WIN32 */
+#endif /* !UTIL */
+void init_upper    OF((void));
+int  namecmp       OF((ZCONST char *string1, ZCONST char *string2));
+
+#ifdef EBCDIC
+char *strtoasc     OF((char *str1, ZCONST char *str2));
+char *strtoebc     OF((char *str1, ZCONST char *str2));
+char *memtoasc     OF((char *mem1, ZCONST char *mem2, unsigned len));
+char *memtoebc     OF((char *mem1, ZCONST char *mem2, unsigned len));
+#endif /* EBCDIC */
+#ifdef IZ_ISO2OEM_ARRAY
+char *str_iso_to_oem    OF((char *dst, ZCONST char *src));
+#endif
+#ifdef IZ_OEM2ISO_ARRAY
+char *str_oem_to_iso    OF((char *dst, ZCONST char *src));
+#endif
+
+zvoid far **search OF((ZCONST zvoid *, ZCONST zvoid far **, extent,
+                       int (*)(ZCONST zvoid *, ZCONST zvoid far *)));
+void envargs       OF((int *, char ***, char *, char *));
+void expand_args   OF((int *, char ***));
+
+#ifndef USE_ZLIB
+#ifndef UTIL
+        /* in crc32.c */
+ulg  crc32         OF((ulg, ZCONST uch *, extent));
+#endif /* !UTIL */
+
+        /* in crctab.c */
+ZCONST ulg near *get_crc_table OF((void));
+#ifdef DYNALLOC_CRCTAB
+void free_crc_table OF((void));
+#endif
+#endif /* !USE_ZLIB */
+
+#ifndef UTIL
+#ifndef USE_ZLIB
+        /* in deflate.c */
+void lm_init OF((int, ush *));
+void lm_free OF((void));
+ulg  deflate OF((void));
+
+        /* in trees.c */
+void     ct_init      OF((ush *, int *));
+int      ct_tally     OF((int, int));
+ulg      flush_block  OF((char far *, ulg, int));
+void     bi_init      OF((char *, unsigned int, int));
+#endif /* !USE_ZLIB */
+#endif /* !UTIL */
+
+        /* in system specific assembler code, replacing C code in trees.c */
+#if defined(ASMV) && defined(RISCOS)
+  void     send_bits    OF((int, int));
+  unsigned bi_reverse   OF((unsigned int, int));
+#endif /* ASMV && RISCOS */
+
+/*---------------------------------------------------------------------------
+    VMS-only functions:
+  ---------------------------------------------------------------------------*/
+#ifdef VMS
+   int    vms_stat        OF((char *, stat_t *));              /* vms.c */
+   void   vms_exit        OF((int));                           /* vms.c */
+#ifndef UTIL
+#ifdef VMSCLI
+   ulg    vms_zip_cmdline OF((int *, char ***));                /* cmdline.c */
+   void   VMSCLI_help     OF((void));                           /* cmdline.c */
+#endif /* VMSCLI */
+#endif /* !UTIL */
+#endif /* VMS */
+
+
+/*---------------------------------------------------------------------------
+    WIN32-only functions:
+  ---------------------------------------------------------------------------*/
+#ifdef WIN32
+   int    ZipIsWinNT         OF((void));                         /* win32.c */
+#endif /* WIN32 */
+
+#if (defined(WINDLL) || defined(DLL_ZIPAPI))
+/*---------------------------------------------------------------------------
+    Prototypes for public Zip API (DLL) functions.
+  ---------------------------------------------------------------------------*/
+#include "api.h"
+#endif /* WINDLL || DLL_ZIPAPI */
+
+#endif /* !__zip_h */
+/* end of zip.h */
diff --git a/zipcloak.c b/zipcloak.c
new file mode 100644 (file)
index 0000000..4b0b9e7
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2005-Feb-10 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#define __ZIPCLOAK_C
+
+#ifndef UTIL
+#define UTIL
+#endif
+#include "zip.h"
+#define DEFCPYRT        /* main module: enable copyright string defines! */
+#include "revision.h"
+#include "crypt.h"
+#include "ttyio.h"
+#include <signal.h>
+#ifndef NO_STDLIB_H
+#  include <stdlib.h>
+#endif
+
+#if CRYPT       /* defined (as TRUE or FALSE) in crypt.h */
+
+int main OF((int argc, char **argv));
+
+local void handler OF((int sig));
+local void license OF((void));
+local void help OF((void));
+local void version_info OF((void));
+
+/* Temporary zip file name and file pointer */
+local char *tempzip;
+local FILE *tempzf;
+
+/* Pointer to CRC-32 table (used for decryption/encryption) */
+#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
+ZCONST ulg near *crc_32_tab;
+#else
+ZCONST uLongf *crc_32_tab;
+#endif
+
+/***********************************************************************
+ * Issue a message for the error, clean up files and memory, and exit.
+ */
+void ziperr(code, msg)
+    int code;               /* error code from the ZE_ class */
+    ZCONST char *msg;       /* message about how it happened */
+{
+    if (PERR(code)) perror("zipcloak error");
+    fprintf(stderr, "zipcloak error: %s (%s)\n", ziperrors[code-1], msg);
+    if (tempzf != NULL) fclose(tempzf);
+    if (tempzip != NULL) {
+        destroy(tempzip);
+        free((zvoid *)tempzip);
+    }
+    if (zipfile != NULL) free((zvoid *)zipfile);
+    EXIT(code);
+}
+
+/***********************************************************************
+ * Print a warning message to stderr and return.
+ */
+void zipwarn(msg1, msg2)
+    ZCONST char *msg1, *msg2;   /* message strings juxtaposed in output */
+{
+    fprintf(stderr, "zipcloak warning: %s%s\n", msg1, msg2);
+}
+
+
+/***********************************************************************
+ * Upon getting a user interrupt, turn echo back on for tty and abort
+ * cleanly using ziperr().
+ */
+local void handler(sig)
+    int sig;                  /* signal number (ignored) */
+{
+#if (!defined(MSDOS) && !defined(__human68k__) && !defined(RISCOS))
+    echon();
+    putc('\n', stderr);
+#endif
+    ziperr(ZE_ABORT +sig-sig, "aborting");
+    /* dummy usage of sig to avoid compiler warnings */
+}
+
+
+/***********************************************************************
+ * Print license information to stdout.
+ */
+local void license()
+{
+    extent i;
+
+    for (i = 0; i < sizeof(swlicense)/sizeof(char *); i++)
+        puts(swlicense[i]);
+    putchar('\n');
+}
+
+
+static ZCONST char *help_info[] = {
+"",
+"ZipCloak %s (%s)",
+#ifdef VM_CMS
+"Usage:  zipcloak [-d] [-b fm] zipfile",
+#else
+"Usage:  zipcloak [-d] [-b path] zipfile",
+#endif
+"  the default action is to encrypt all unencrypted entries in the zip file",
+"  -d   decrypt--decrypt encrypted entries (copy if given wrong password)",
+#ifdef VM_CMS
+"  -b   use \"fm\" as the filemode for the temporary zip file",
+#else
+"  -b   use \"path\" for the temporary zip file",
+#endif
+"  -h   show this help    -v   show version info    -L   show software license"
+  };
+
+/***********************************************************************
+ * Print help (along with license info) to stdout.
+ */
+local void help()
+{
+    extent i;             /* counter for help array */
+
+    for (i = 0; i < sizeof(help_info)/sizeof(char *); i++) {
+        printf(help_info[i], VERSION, REVDATE);
+        putchar('\n');
+    }
+}
+
+
+local void version_info()
+/* Print verbose info about program version and compile time options
+   to stdout. */
+{
+  extent i;             /* counter in text arrays */
+
+  /* Options info array */
+  static ZCONST char *comp_opts[] = {
+#ifdef DEBUG
+    "DEBUG",
+#endif
+#if CRYPT && defined(PASSWD_FROM_STDIN)
+    "PASSWD_FROM_STDIN",
+#endif /* CRYPT && PASSWD_FROM_STDIN */
+    NULL
+  };
+
+  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
+  {
+    printf(copyright[i], "zipcloak");
+    putchar('\n');
+  }
+
+  for (i = 0; i < sizeof(versinfolines)/sizeof(char *); i++)
+  {
+    printf(versinfolines[i], "ZipCloak", VERSION, REVDATE);
+    putchar('\n');
+  }
+
+  version_local();
+
+  puts("ZipCloak special compilation options:");
+  for (i = 0; (int)i < (int)(sizeof(comp_opts)/sizeof(char *) - 1); i++)
+  {
+    printf("\t%s\n",comp_opts[i]);
+  }
+  printf("\t[encryption, version %d.%d%s of %s]\n",
+            CR_MAJORVER, CR_MINORVER, CR_BETA_VER, CR_VERSION_DATE);
+
+  for (i = 0; i < sizeof(cryptnote)/sizeof(char *); i++)
+      puts(cryptnote[i]);
+}
+
+
+/***********************************************************************
+ * Encrypt or decrypt all of the entries in a zip file.  See the command
+ * help in help() above.
+ */
+
+int main(argc, argv)
+    int argc;                   /* number of tokens in command line */
+    char **argv;                /* command line tokens */
+{
+    int attr;                   /* attributes of zip file */
+    ulg start_offset;           /* start of central directory */
+    int decrypt;                /* decryption flag */
+    int temp_path;              /* 1 if next argument is path for temp files */
+    char passwd[IZ_PWLEN+1];    /* password for encryption or decryption */
+    char verify[IZ_PWLEN+1];    /* password for encryption or decryption */
+    char *q;                    /* steps through option arguments */
+    int r;                      /* arg counter */
+    int res;                    /* result code */
+    ulg length;                 /* length of central directory */
+    FILE *inzip, *outzip;       /* input and output zip files */
+    struct zlist far *z;        /* steps through zfiles linked list */
+
+#ifdef THEOS
+    setlocale(LC_CTYPE, "I");
+#endif
+
+    /* If no args, show help */
+    if (argc == 1) {
+        help();
+        EXIT(0);
+    }
+
+    init_upper();               /* build case map table */
+
+    crc_32_tab = get_crc_table();
+                                /* initialize crc table for crypt */
+
+    /* Go through args */
+    zipfile = tempzip = NULL;
+    tempzf = NULL;
+#ifdef SIGINT
+    signal(SIGINT, handler);
+#endif
+#ifdef SIGTERM                  /* Some don't have SIGTERM */
+    signal(SIGTERM, handler);
+#endif
+    temp_path = decrypt = 0;
+    for (r = 1; r < argc; r++) {
+        if (*argv[r] == '-') {
+            if (!argv[r][1]) ziperr(ZE_PARMS, "zip file cannot be stdin");
+            for (q = argv[r]+1; *q; q++) {
+                switch (*q) {
+                case 'b':   /* Specify path for temporary file */
+                    if (temp_path) {
+                        ziperr(ZE_PARMS, "use -b before zip file name");
+                    }
+                    temp_path = 1;          /* Next non-option is path */
+                    break;
+                case 'd':
+                    decrypt = 1;  break;
+                case 'h':   /* Show help */
+                    help();
+                    EXIT(0);
+                case 'l': case 'L':  /* Show copyright and disclaimer */
+                    license();
+                    EXIT(0);
+                case 'v':   /* Show version info */
+                    version_info();
+                    EXIT(0);
+                default:
+                    ziperr(ZE_PARMS, "unknown option");
+                } /* switch */
+            } /* for */
+
+        } else if (temp_path == 0) {
+            if (zipfile != NULL) {
+                ziperr(ZE_PARMS, "can only specify one zip file");
+
+            } else if ((zipfile = ziptyp(argv[r])) == NULL) {
+                ziperr(ZE_MEM, "was processing arguments");
+            }
+        } else {
+            tempath = argv[r];
+            temp_path = 0;
+        } /* if */
+    } /* for */
+
+    if (zipfile == NULL) ziperr(ZE_PARMS, "need to specify zip file");
+
+    /* Read zip file */
+    if ((res = readzipfile()) != ZE_OK) ziperr(res, zipfile);
+    if (zfiles == NULL) ziperr(ZE_NAME, zipfile);
+
+    /* Check for something to do */
+    for (z = zfiles; z != NULL; z = z->nxt) {
+        if (decrypt ? z->flg & 1 : !(z->flg & 1)) break;
+    }
+    if (z == NULL) {
+        ziperr(ZE_NONE, decrypt ? "no encrypted files"
+                       : "all files encrypted already");
+    }
+
+    /* Before we get carried away, make sure zip file is writeable */
+    if ((inzip = fopen(zipfile, "a")) == NULL) ziperr(ZE_CREAT, zipfile);
+    fclose(inzip);
+    attr = getfileattr(zipfile);
+
+    /* Open output zip file for writing */
+    if ((tempzf = outzip = fopen(tempzip = tempname(zipfile), FOPW)) == NULL) {
+        ziperr(ZE_TEMP, tempzip);
+    }
+
+    /* Get password */
+    if (getp("Enter password: ", passwd, IZ_PWLEN+1) == NULL)
+        ziperr(ZE_PARMS,
+               "stderr is not a tty (you may never see this message!)");
+
+    if (decrypt == 0) {
+        if (getp("Verify password: ", verify, IZ_PWLEN+1) == NULL)
+               ziperr(ZE_PARMS,
+                      "stderr is not a tty (you may never see this message!)");
+
+        if (strcmp(passwd, verify))
+               ziperr(ZE_PARMS, "password verification failed");
+
+        if (*passwd == '\0')
+               ziperr(ZE_PARMS, "zero length password not allowed");
+    }
+
+    /* Open input zip file again, copy preamble if any */
+    if ((inzip = fopen(zipfile, FOPR)) == NULL) ziperr(ZE_NAME, zipfile);
+
+    if (zipbeg && (res = fcopy(inzip, outzip, zipbeg)) != ZE_OK) {
+        ziperr(res, res == ZE_TEMP ? tempzip : zipfile);
+    }
+    tempzn = zipbeg;
+
+    /* Go through local entries, copying, encrypting, or decrypting */
+    for (z = zfiles; z != NULL; z = z->nxt) {
+        if (decrypt && (z->flg & 1)) {
+            printf("decrypting: %s", z->zname);
+            fflush(stdout);
+            if ((res = zipbare(z, inzip, outzip, passwd)) != ZE_OK) {
+                if (res != ZE_MISS) ziperr(res, "was decrypting an entry");
+                printf(" (wrong password--just copying)");
+            }
+            putchar('\n');
+
+        } else if ((!decrypt) && !(z->flg & 1)) {
+            printf("encrypting: %s\n", z->zname);
+            fflush(stdout);
+            if ((res = zipcloak(z, inzip, outzip, passwd)) != ZE_OK) {
+                ziperr(res, "was encrypting an entry");
+            }
+        } else {
+            printf("   copying: %s\n", z->zname);
+            fflush(stdout);
+            if ((res = zipcopy(z, inzip, outzip)) != ZE_OK) {
+                ziperr(res, "was copying an entry");
+            }
+        } /* if */
+    } /* for */
+    fclose(inzip);
+
+    /* Write central directory and end of central directory */
+
+    /* get start of central */
+    if ((start_offset = (ulg)ftell(outzip)) == (ulg)-1L)
+        ziperr(ZE_TEMP, tempzip);
+
+    for (z = zfiles; z != NULL; z = z->nxt) {
+        if ((res = putcentral(z, outzip)) != ZE_OK) ziperr(res, tempzip);
+    }
+
+    /* get end of central */
+    if ((length = (ulg)ftell(outzip)) == (ulg)-1L)
+        ziperr(ZE_TEMP, tempzip);
+
+    length -= start_offset;               /* compute length of central */
+    if ((res = putend((int)zcount, length, start_offset, zcomlen,
+                       zcomment, outzip)) != ZE_OK) {
+        ziperr(res, tempzip);
+    }
+    tempzf = NULL;
+    if (fclose(outzip)) ziperr(ZE_TEMP, tempzip);
+    if ((res = replace(zipfile, tempzip)) != ZE_OK) {
+        zipwarn("new zip file left as: ", tempzip);
+        free((zvoid *)tempzip);
+        tempzip = NULL;
+        ziperr(res, "was replacing the original zip file");
+    }
+    free((zvoid *)tempzip);
+    tempzip = NULL;
+    setfileattr(zipfile, attr);
+#ifdef RISCOS
+    /* Set the filetype of the zipfile to &DDC */
+    setfiletype(zipfile, 0xDDC);
+#endif
+    free((zvoid *)zipfile);
+    zipfile = NULL;
+
+    /* Done! */
+    RETURN(0);
+}
+#else /* !CRYPT */
+
+int main OF((void));
+
+void zipwarn(msg1, msg2)
+ZCONST char  *msg1, *msg2;
+{
+    /* Tell picky compilers to shut up about unused variables */
+    msg1 = msg1; msg2 = msg2;
+}
+
+void ziperr(c, h)
+int  c;
+ZCONST char *h;
+{
+    /* Tell picky compilers to shut up about unused variables */
+    c = c; h = h;
+}
+
+int main()
+{
+    fprintf(stderr, "\
+This version of ZipCloak does not support encryption.  Get the current Zip\n\
+source distribution and recompile ZipCloak after you have added an option to\n\
+define the symbol USE_CRYPT to the C compiler's command arguments.\n");
+    RETURN(1);
+}
+
+#endif /* ?CRYPT */
diff --git a/ziperr.h b/ziperr.h
new file mode 100644 (file)
index 0000000..1f2ce37
--- /dev/null
+++ b/ziperr.h
@@ -0,0 +1,67 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2005-Feb-10 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *  ziperr.h by Mark Adler
+ */
+
+/* Error return values.  The values 0..4 and 12..18 follow the conventions
+   of PKZIP.   The values 4..10 are all assigned to "insufficient memory"
+   by PKZIP, so the codes 5..10 are used here for other purposes. */
+#define ZE_MISS         -1      /* used by procname(), zipbare() */
+#define ZE_OK           0       /* success */
+#define ZE_EOF          2       /* unexpected end of zip file */
+#define ZE_FORM         3       /* zip file structure error */
+#define ZE_MEM          4       /* out of memory */
+#define ZE_LOGIC        5       /* internal logic error */
+#define ZE_BIG          6       /* entry too large to split, read, or write */
+#define ZE_NOTE         7       /* invalid comment format */
+#define ZE_TEST         8       /* zip test (-T) failed or out of memory */
+#define ZE_ABORT        9       /* user interrupt or termination */
+#define ZE_TEMP         10      /* error using a temp file */
+#define ZE_READ         11      /* read or seek error */
+#define ZE_NONE         12      /* nothing to do */
+#define ZE_NAME         13      /* missing or empty zip file */
+#define ZE_WRITE        14      /* error writing to a file */
+#define ZE_CREAT        15      /* couldn't open to write */
+#define ZE_PARMS        16      /* bad command line */
+#define ZE_OPEN         18      /* could not open a specified file to read */
+
+#define ZE_MAXERR       18      /* the highest error number */
+
+/* Macro to determine whether to call perror() or not */
+#define PERR(e) (e==ZE_READ||e==ZE_WRITE||e==ZE_CREAT||e==ZE_TEMP||e==ZE_OPEN)
+
+#ifdef GLOBALS
+/* Error messages for the ziperr() function in the zip programs */
+char *ziperrors[ZE_MAXERR] = {
+/*  1 */  "",
+/*  2 */  "Unexpected end of zip file",
+/*  3 */  "Zip file structure invalid",
+/*  4 */  "Out of memory",
+/*  5 */  "Internal logic error",
+/*  6 */  "Entry too big to split, read, or write",
+/*  7 */  "Invalid comment format",
+/*  8 */  "Zip file invalid or could not spawn unzip",
+/*  9 */  "Interrupted",
+/* 10 */  "Temporary file failure",
+/* 11 */  "Input file read failure",
+/* 12 */  "Nothing to do!",
+/* 13 */  "Missing or empty zip file",
+/* 14 */  "Output file write failure",
+/* 15 */  "Could not create output file",
+/* 16 */  "Invalid command arguments",
+/* 17 */  "",
+/* 18 */  "File not found or no read permission"
+#  ifdef AZTEC_C
+          ,     /* extremely lame compiler bug workaround */
+#  endif
+};
+#else /* !GLOBALS */
+extern char *ziperrors[ZE_MAXERR]; /* Error messages for ziperr() */
+#endif /* ?GLOBALS */
diff --git a/zipfile.c b/zipfile.c
new file mode 100644 (file)
index 0000000..647c31f
--- /dev/null
+++ b/zipfile.c
@@ -0,0 +1,1565 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *  zipfile.c by Mark Adler.
+ */
+#define __ZIPFILE_C
+
+#include "zip.h"
+#include "revision.h"
+
+#ifdef VMS
+#  include <rms.h>
+#  include <starlet.h>
+#  include "vms/vmsmunch.h"
+#  include "vms/vmsdefs.h"
+#endif
+
+#ifdef __RSXNT__
+#  include <windows.h>
+#endif
+
+/*
+ * XXX start of zipfile.h
+ */
+#ifdef THEOS
+/* Macros cause stack overflow in compiler */
+ush SH(uch* p) { return ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)); }
+ulg LG(uch* p) { return ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)); }
+#else /* !THEOS */
+/* Macros for converting integers in little-endian to machine format */
+#define SH(a) ((ush)(((ush)(uch)(a)[0]) | (((ush)(uch)(a)[1]) << 8)))
+#define LG(a) ((ulg)SH(a) | ((ulg)SH((a)+2) << 16))
+#endif /* ?THEOS */
+
+/* Macros for writing machine integers to little-endian format */
+#define PUTSH(a,f) {putc((char)((a) & 0xff),(f)); putc((char)((a) >> 8),(f));}
+#define PUTLG(a,f) {PUTSH((a) & 0xffff,(f)) PUTSH((a) >> 16,(f))}
+
+
+/* -- Structure of a ZIP file -- */
+
+/* Signatures for zip file information headers */
+#define LOCSIG     0x04034b50L
+#define CENSIG     0x02014b50L
+#define ENDSIG     0x06054b50L
+#define EXTLOCSIG  0x08074b50L
+
+/* Offsets of values in headers */
+#define LOCVER  0               /* version needed to extract */
+#define LOCFLG  2               /* encrypt, deflate flags */
+#define LOCHOW  4               /* compression method */
+#define LOCTIM  6               /* last modified file time, DOS format */
+#define LOCDAT  8               /* last modified file date, DOS format */
+#define LOCCRC  10              /* uncompressed crc-32 for file */
+#define LOCSIZ  14              /* compressed size in zip file */
+#define LOCLEN  18              /* uncompressed size */
+#define LOCNAM  22              /* length of filename */
+#define LOCEXT  24              /* length of extra field */
+
+#define EXTCRC  0               /* uncompressed crc-32 for file */
+#define EXTSIZ  4               /* compressed size in zip file */
+#define EXTLEN  8               /* uncompressed size */
+
+#define CENVEM  0               /* version made by */
+#define CENVER  2               /* version needed to extract */
+#define CENFLG  4               /* encrypt, deflate flags */
+#define CENHOW  6               /* compression method */
+#define CENTIM  8               /* last modified file time, DOS format */
+#define CENDAT  10              /* last modified file date, DOS format */
+#define CENCRC  12              /* uncompressed crc-32 for file */
+#define CENSIZ  16              /* compressed size in zip file */
+#define CENLEN  20              /* uncompressed size */
+#define CENNAM  24              /* length of filename */
+#define CENEXT  26              /* length of extra field */
+#define CENCOM  28              /* file comment length */
+#define CENDSK  30              /* disk number start */
+#define CENATT  32              /* internal file attributes */
+#define CENATX  34              /* external file attributes */
+#define CENOFF  38              /* relative offset of local header */
+
+#define ENDDSK  0               /* number of this disk */
+#define ENDBEG  2               /* number of the starting disk */
+#define ENDSUB  4               /* entries on this disk */
+#define ENDTOT  6               /* total number of entries */
+#define ENDSIZ  8               /* size of entire central directory */
+#define ENDOFF  12              /* offset of central on starting disk */
+#define ENDCOM  16              /* length of zip file comment */
+
+
+
+/* Local functions */
+
+local int zqcmp OF((ZCONST zvoid *, ZCONST zvoid *));
+local int scanzipf_reg OF((FILE *f));
+#ifndef UTIL
+   local int rqcmp OF((ZCONST zvoid *, ZCONST zvoid *));
+   local int zbcmp OF((ZCONST zvoid *, ZCONST zvoid far *));
+   local void zipoddities OF((struct zlist far *));
+   local int scanzipf_fix OF((FILE *f));
+#  ifdef USE_EF_UT_TIME
+     local int ef_scan_ut_time OF((char *ef_buf, extent ef_len, int ef_is_cent,
+                                   iztimes *z_utim));
+#  endif /* USE_EF_UT_TIME */
+   local void cutpath OF((char *p, int delim));
+#endif /* !UTIL */
+
+/*
+ * XXX end of zipfile.h
+ */
+
+/* Local data */
+
+#ifdef HANDLE_AMIGA_SFX
+   ulg amiga_sfx_offset;        /* place where size field needs updating */
+#endif
+
+
+local int zqcmp(a, b)
+ZCONST zvoid *a, *b;          /* pointers to pointers to zip entries */
+/* Used by qsort() to compare entries in the zfile list.
+ * Compares the internal names z->iname */
+{
+  return namecmp((*(struct zlist far **)a)->iname,
+                 (*(struct zlist far **)b)->iname);
+}
+
+#ifndef UTIL
+
+local int rqcmp(a, b)
+ZCONST zvoid *a, *b;          /* pointers to pointers to zip entries */
+/* Used by qsort() to compare entries in the zfile list.
+ * Compare the internal names z->iname, but in reverse order. */
+{
+  return namecmp((*(struct zlist far **)b)->iname,
+                 (*(struct zlist far **)a)->iname);
+}
+
+
+local int zbcmp(n, z)
+ZCONST zvoid *n;        /* string to search for */
+ZCONST zvoid far *z;    /* pointer to a pointer to a zip entry */
+/* Used by search() to compare a target to an entry in the zfile list. */
+{
+  return namecmp((char *)n, ((struct zlist far *)z)->zname);
+}
+
+
+struct zlist far *zsearch(n)
+ZCONST char *n;         /* name to find */
+/* Return a pointer to the entry in zfile with the name n, or NULL if
+   not found. */
+{
+  zvoid far **p;        /* result of search() */
+
+  if (zcount &&
+      (p = search(n, (ZCONST zvoid far **)zsort, zcount, zbcmp)) != NULL)
+    return *(struct zlist far **)p;
+  else
+    return NULL;
+}
+
+#endif /* !UTIL */
+
+#ifndef VMS
+#  ifndef PATHCUT
+#    define PATHCUT '/'
+#  endif
+
+char *ziptyp(s)
+char *s;                /* file name to force to zip */
+/* If the file name *s has a dot (other than the first char), or if
+   the -A option is used (adjust self-extracting file) then return
+   the name, otherwise append .zip to the name.  Allocate the space for
+   the name in either case.  Return a pointer to the new name, or NULL
+   if malloc() fails. */
+{
+  char *q;              /* temporary pointer */
+  char *t;              /* pointer to malloc'ed string */
+#ifdef THEOS
+  char *r;              /* temporary pointer */
+  char *disk;
+#endif
+
+  if ((t = malloc(strlen(s) + 5)) == NULL)
+    return NULL;
+  strcpy(t, s);
+#ifdef __human68k__
+  _toslash(t);
+#endif
+#ifdef MSDOS
+  for (q = t; *q; INCSTR(q))
+    if (*q == '\\')
+      *q = '/';
+#endif /* MSDOS */
+#ifdef __RSXNT__   /* RSXNT/EMX C rtl uses OEM charset */
+  AnsiToOem(t, t);
+#endif
+  if (adjust) return t;
+#ifndef RISCOS
+# ifndef QDOS
+#  ifdef AMIGA
+  if ((q = MBSRCHR(t, '/')) == NULL)
+    q = MBSRCHR(t, ':');
+  if (MBSRCHR((q ? q + 1 : t), '.') == NULL)
+#  else /* !AMIGA */
+#    ifdef THEOS
+  /* the argument expansion add a dot to the end of file names when
+   * there is no extension and at least one of a argument has wild cards.
+   * So check for at least one character in the extension if there is a dot
+   * in file name */
+  if ((q = MBSRCHR((q = MBSRCHR(t, PATHCUT)) == NULL ? t : q + 1, '.')) == NULL
+    || q[1] == '\0') {
+#    else /* !THEOS */
+#      ifdef TANDEM
+  if (MBSRCHR((q = MBSRCHR(t, '.')) == NULL ? t : q + 1, ' ') == NULL)
+#      else /* !TANDEM */
+  if (MBSRCHR((q = MBSRCHR(t, PATHCUT)) == NULL ? t : q + 1, '.') == NULL)
+#      endif /* ?TANDEM */
+#    endif /* ?THEOS */
+#  endif /* ?AMIGA */
+#  ifdef CMS_MVS
+    if (strncmp(t,"dd:",3) != 0 && strncmp(t,"DD:",3) != 0)
+#  endif /* CMS_MVS */
+#  ifdef THEOS
+    /* insert .zip extension before disk name */
+    if ((r = MBSRCHR(t, ':')) != NULL) {
+        /* save disk name */
+        if ((disk = strdup(r)) == NULL)
+            return NULL;
+        strcpy(r[-1] == '.' ? r - 1 : r, ".zip");
+        strcat(t, disk);
+        free(disk);
+    } else {
+        if (q != NULL && *q == '.')
+          strcpy(q, ".zip");
+        else
+          strcat(t, ".zip");
+    }
+  }
+#  else /* !THEOS */
+#    ifdef TANDEM     /*  Tandem can't cope with extensions */
+    strcat(t, " ZIP");
+#    else /* !TANDEM */
+    strcat(t, ".zip");
+#    endif /* ?TANDEM */
+#  endif /* ?THEOS */
+# else /* QDOS */
+  q = LastDir(t);
+  if(MBSRCHR(q, '_') == NULL && MBSRCHR(q, '.') == NULL)
+  {
+      strcat(t, "_zip");
+  }
+# endif /* QDOS */
+#endif /* !RISCOS */
+  return t;
+}
+
+#else /* VMS */
+
+# define PATHCUT ']'
+
+char *ziptyp(s)
+char *s;
+{   int status;
+    struct FAB fab;
+    struct NAM nam;
+    static char zero=0;
+    char result[NAM$C_MAXRSS+1],exp[NAM$C_MAXRSS+1];
+    char *p;
+
+    fab = cc$rms_fab;
+    nam = cc$rms_nam;
+
+    fab.fab$l_fna = s;
+    fab.fab$b_fns = strlen(fab.fab$l_fna);
+
+    fab.fab$l_dna = "sys$disk:[].zip";          /* Default fspec */
+    fab.fab$b_dns = strlen(fab.fab$l_dna);
+
+    fab.fab$l_nam = &nam;
+
+    nam.nam$l_rsa = result;                     /* Put resultant name of */
+    nam.nam$b_rss = sizeof(result)-1;           /* existing zipfile here */
+
+    nam.nam$l_esa = exp;                        /* For full spec of */
+    nam.nam$b_ess = sizeof(exp)-1;              /* file to create */
+
+    status = sys$parse(&fab);
+    if( (status & 1) == 0 )
+        return &zero;
+
+    status = sys$search(&fab);
+    if( status & 1 )
+    {               /* Existing ZIP file */
+        int l;
+        if( (p=malloc( (l=nam.nam$b_rsl) + 1 )) != NULL )
+        {       result[l] = 0;
+                strcpy(p,result);
+        }
+    }
+    else
+    {               /* New ZIP file */
+        int l;
+        if( (p=malloc( (l=nam.nam$b_esl) + 1 )) != NULL )
+        {       exp[l] = 0;
+                strcpy(p,exp);
+        }
+    }
+    return p;
+}
+
+#endif  /* VMS */
+
+#ifndef UTIL
+
+local void zipoddities(z)
+struct zlist far *z;
+{
+    if ((z->vem >> 8) >= NUM_HOSTS)
+    {
+        sprintf(errbuf, "made by version %d.%d on system type %d: ",
+                (ush)(z->vem & 0xff) / (ush)10, (ush)(z->vem & 0xff) % (ush)10,
+                z->vem >> 8);
+        zipwarn(errbuf, z->zname);
+    }
+    if (z->ver != 10 && z->ver != 11 && z->ver != 20)
+    {
+        sprintf(errbuf, "needs unzip %d.%d on system type %d: ",
+                (ush)(z->ver & 0xff) / (ush)10,
+                (ush)(z->ver & 0xff) % (ush)10, z->ver >> 8);
+        zipwarn(errbuf, z->zname);
+    }
+    if (z->flg != z->lflg)
+    {
+        sprintf(errbuf, "local flags = 0x%04x, central = 0x%04x: ",
+                z->lflg, z->flg);
+        zipwarn(errbuf, z->zname);
+    }
+    else if (z->flg & ~0xf)
+    {
+        sprintf(errbuf, "undefined bits used in flags = 0x%04x: ", z->flg);
+        zipwarn(errbuf, z->zname);
+    }
+    if (z->how > DEFLATE)
+    {
+        sprintf(errbuf, "unknown compression method %u: ", z->how);
+        zipwarn(errbuf, z->zname);
+    }
+    if (z->dsk)
+    {
+        sprintf(errbuf, "starts on disk %u: ", z->dsk);
+        zipwarn(errbuf, z->zname);
+    }
+    if (z->att!=ASCII && z->att!=BINARY && z->att!=__EBCDIC)
+    {
+        sprintf(errbuf, "unknown internal attributes = 0x%04x: ", z->att);
+        zipwarn(errbuf, z->zname);
+    }
+#if 0
+/* This test is ridiculous, it produces an error message for almost every */
+/* platform of origin other than MS-DOS, Unix, VMS, and Acorn!  Perhaps   */
+/* we could test "if (z->dosflag && z->atx & ~0xffL)", but what for?      */
+    if (((n = z->vem >> 8) != 3) && n != 2 && n != 13 && z->atx & ~0xffL)
+    {
+        sprintf(errbuf, "unknown external attributes = 0x%08lx: ", z->atx);
+        zipwarn(errbuf, z->zname);
+    }
+#endif
+    if (z->ext || z->cext)
+    {
+        if (z->ext && z->cext && z->extra != z->cextra)
+        {
+          sprintf(errbuf,
+                  "local extra (%ld bytes) != central extra (%ld bytes): ",
+                  (ulg)z->ext, (ulg)z->cext);
+          if (noisy) fprintf(stderr, "\tzip info: %s%s\n", errbuf, z->zname);
+        }
+#if (!defined(RISCOS) && !defined(CMS_MVS))
+        /* in noisy mode, extra field sizes are always reported */
+        else if (noisy)
+#else /* RISCOS || CMS_MVS */
+/* avoid warnings for zipfiles created on the same type of OS system! */
+/* or, was this warning really intended (eg. OS/2)? */
+        /* Only give info if extra bytes were added by another system */
+        else if (noisy && ((z->vem >> 8) != (OS_CODE >> 8)))
+#endif /* ?(RISCOS || CMS_MVS) */
+        {
+            fprintf(stderr, "zip info: %s has %ld bytes of %sextra data\n",
+                    z->zname, z->ext ? (ulg)z->ext : (ulg)z->cext,
+                    z->ext ? (z->cext ? "" : "local ") : "central ");
+        }
+    }
+}
+
+/*
+ * scanzipf_fix is called with zip -F or zip -FF
+ * read the file from front to back and pick up the pieces
+ * NOTE: there are still checks missing to see if the header
+ *       that was found is *VALID*
+ */
+local int scanzipf_fix(f)
+  FILE *f;                      /* zip file */
+/*
+   The name of the zip file is pointed to by the global "zipfile".  The globals
+   zipbeg, cenbeg, zfiles, zcount, zcomlen, zcomment, and zsort are filled in.
+   Return an error code in the ZE_ class.
+*/
+{
+    ulg a = 0L;                 /* attributes returned by filetime() */
+    char b[CENHEAD];            /* buffer for central headers */
+    ush flg;                    /* general purpose bit flag */
+    int m;                      /* mismatch flag */
+    extent n;                   /* length of name */
+    ulg p;                      /* current file offset */
+    ulg s;                      /* size of data, start of central */
+    struct zlist far * far *x;  /* pointer last entry's link */
+    struct zlist far *z;        /* current zip entry structure */
+
+    /* Get any file attribute valid for this OS, to set in the central
+     * directory when fixing the archive:
+     */
+#ifndef UTIL
+    filetime(zipfile, &a, (long*)&s, NULL);
+#endif
+    x = &zfiles;                        /* first link */
+    p = 0;                              /* starting file offset */
+#ifdef HANDLE_AMIGA_SFX
+    amiga_sfx_offset = 0L;
+#endif
+
+    /* Find start of zip structures */
+    for (;;) {
+      while ((m = getc(f)) != EOF && m != 0x50)    /* 0x50 == 'P' */
+      {
+#ifdef HANDLE_AMIGA_SFX
+        if (p == 0 && m == 0)
+          amiga_sfx_offset = 1L;
+        else if (amiga_sfx_offset) {
+          if ((p == 1 && m != 0) || (p == 2 && m != 3)
+                                 || (p == 3 && (uch) m != 0xF3))
+            amiga_sfx_offset = 0L;
+        }
+#endif /* HANDLE_AMIGA_SFX */
+        p++;
+      }
+      b[0] = (char) m;
+      if (fread(b+1, 3, 1, f) != 1 || (s = LG(b)) == LOCSIG || s == ENDSIG)
+        break;
+      if (fseek(f, -3L, SEEK_CUR))
+        return ferror(f) ? ZE_READ : ZE_EOF;
+      p++;
+    }
+    zipbeg = p;
+#ifdef HANDLE_AMIGA_SFX
+    if (amiga_sfx_offset && zipbeg >= 12 && (zipbeg & 3) == 0
+        && fseek(f, -12L, SEEK_CUR) == 0 && fread(b, 12, 1, f) == 1
+        && LG(b + 4) == 0xF1030000 /* 1009 in Motorola byte order */)
+      amiga_sfx_offset = zipbeg - 4;
+    else
+      amiga_sfx_offset = 0L;
+#endif /* HANDLE_AMIGA_SFX */
+
+    /* Read local headers */
+    while (LG(b) == LOCSIG)
+    {
+      if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL ||
+          zcount + 1 < zcount)
+        return ZE_MEM;
+      if (fread(b, LOCHEAD, 1, f) != 1) {
+          farfree((zvoid far *)z);
+          break;
+      }
+
+      z->ver = SH(LOCVER + b);
+      z->vem = (ush)(dosify ? 20 : OS_CODE + Z_MAJORVER * 10 + Z_MINORVER);
+      z->dosflag = dosify;
+      flg = z->flg = z->lflg = SH(LOCFLG + b);
+      z->how = SH(LOCHOW + b);
+      z->tim = LG(LOCTIM + b);          /* time and date into one long */
+      z->crc = LG(LOCCRC + b);
+      z->siz = LG(LOCSIZ + b);
+      z->len = LG(LOCLEN + b);
+      n = z->nam = SH(LOCNAM + b);
+      z->cext = z->ext = SH(LOCEXT + b);
+
+      z->com = 0;
+      z->dsk = 0;
+      z->att = 0;
+      z->atx = dosify ? a & 0xff : a;     /* Attributes from filetime() */
+      z->mark = 0;
+      z->trash = 0;
+
+      s = fix > 1 ? 0L : z->siz; /* discard compressed size with -FF */
+
+      /* Initialize all fields pointing to malloced data to NULL */
+      z->zname = z->name = z->iname = z->extra = z->cextra = z->comment = NULL;
+
+      /* Link into list */
+      *x = z;
+      z->nxt = NULL;
+      x = &z->nxt;
+
+      /* Read file name and extra field and skip data */
+      if (n == 0)
+      {
+        sprintf(errbuf, "%lu", (ulg)zcount + 1);
+        zipwarn("zero-length name for entry #", errbuf);
+#ifndef DEBUG
+        return ZE_FORM;
+#endif
+      }
+      if ((z->iname = malloc(n+1)) ==  NULL ||
+          (z->ext && (z->extra = malloc(z->ext)) == NULL))
+        return ZE_MEM;
+      if (fread(z->iname, n, 1, f) != 1 ||
+          (z->ext && fread(z->extra, z->ext, 1, f) != 1) ||
+          (s && fseek(f, (long)s, SEEK_CUR)))
+        return ferror(f) ? ZE_READ : ZE_EOF;
+      /* If there is an extended local header, s is either 0 or
+       * the correct compressed size.
+       */
+      z->iname[n] = '\0';               /* terminate name */
+      z->zname = in2ex(z->iname);       /* convert to external name */
+      if (z->zname == NULL)
+        return ZE_MEM;
+      z->name = z->zname;
+      z->cextra = z->extra;
+      if (noisy) fprintf(mesg, "zip: reading %s\n", z->zname);
+
+      /* Save offset, update for next header */
+      z->off = p;
+      p += 4 + LOCHEAD + n + z->ext + s;
+      zcount++;
+
+      /* Skip extended local header if there is one */
+      if ((flg & 8) != 0) {
+        /* Skip the compressed data if compressed size is unknown.
+         * For safety, we should use the central directory.
+         */
+        if (s == 0) {
+          for (;;) {
+            while ((m = getc(f)) != EOF && m != 0x50) ;  /* 0x50 == 'P' */
+            b[0] = (char) m;
+            if (fread(b+1, 15, 1, f) != 1 || LG(b) == EXTLOCSIG)
+              break;
+            if (fseek(f, -15L, SEEK_CUR))
+              return ferror(f) ? ZE_READ : ZE_EOF;
+          }
+          s = LG(4 + EXTSIZ + b);
+          p += s;
+          if ((ulg) ftell(f) != p+16L) {
+            zipwarn("bad extended local header for ", z->zname);
+            return ZE_FORM;
+          }
+        } else {
+          /* compressed size non-zero, assume that it is valid: */
+          Assert(p == ftell(f), "bad compressed size with extended header");
+
+          if (fseek(f, p, SEEK_SET) || fread(b, 16, 1, f) != 1)
+            return ferror(f) ? ZE_READ : ZE_EOF;
+          if (LG(b) != EXTLOCSIG) {
+            zipwarn("extended local header not found for ", z->zname);
+            return ZE_FORM;
+          }
+        }
+        /* overwrite the unknown values of the local header: */
+
+        /* already in host format */
+        z->crc = LG(4 + EXTCRC + b);
+        z->siz = s;
+        z->len = LG(4 + EXTLEN + b);
+
+        p += 16L;
+      }
+      else if (fix > 1) {
+        /* Don't trust the compressed size */
+        for (;;) {
+          while ((m = getc(f)) != EOF && m != 0x50) p++; /* 0x50 == 'P' */
+          b[0] = (char) m;
+          if (fread(b+1, 3, 1, f) != 1 || (s = LG(b)) == LOCSIG || s == CENSIG)
+            break;
+          if (fseek(f, -3L, SEEK_CUR))
+            return ferror(f) ? ZE_READ : ZE_EOF;
+          p++;
+        }
+        s = p - (z->off + 4 + LOCHEAD + n + z->ext);
+        if (s != z->siz) {
+          fprintf(mesg, " compressed size %ld, actual size %ld for %s\n",
+                  z->siz, s, z->zname);
+          z->siz = s;
+        }
+        /* next LOCSIG already read at this point, don't read it again: */
+        continue;
+      }
+
+      /* Read next signature */
+      if (fread(b, 4, 1, f) != 1)
+          break;
+    }
+
+    s = p;                              /* save start of central */
+
+    if (LG(b) != CENSIG && noisy) {
+      fprintf(mesg, "zip warning: %s %s truncated.\n", zipfile,
+              fix > 1 ? "has been" : "would be");
+
+      if (fix == 1) {
+        fprintf(mesg,
+   "Retry with option -qF to truncate, with -FF to attempt full recovery\n");
+        ZIPERR(ZE_FORM, NULL);
+      }
+    }
+
+    cenbeg = s;
+
+    if (zipbeg && noisy)
+      fprintf(mesg, "%s: adjusting offsets for a preamble of %lu bytes\n",
+              zipfile, zipbeg);
+
+    return ZE_OK;
+}
+
+#endif /* !UTIL */
+
+/*
+ * scanzipf_reg starts searching for the End Signature at the end of the file
+ * The End Signature points to the Central Directory Signature which points
+ * to the Local Directory Signature
+ * XXX probably some more consistency checks are needed
+ */
+local int scanzipf_reg(f)
+  FILE *f;                      /* zip file */
+/*
+   The name of the zip file is pointed to by the global "zipfile".  The globals
+   zipbeg, cenbeg, zfiles, zcount, zcomlen, zcomment, and zsort are filled in.
+   Return an error code in the ZE_ class.
+*/
+{
+    char b[CENHEAD];            /* buffer for central headers */
+    ush flg;                    /* general purpose bit flag */
+    int m;                      /* mismatch flag */
+    extent n;                   /* length of name */
+    struct zlist far * far *x;  /* pointer last entry's link */
+    struct zlist far *z;        /* current zip entry structure */
+    char *t;                    /* temporary pointer */
+    char far *u;                /* temporary variable */
+    int found;
+    char *buf;                  /* temp buffer for reading zipfile */
+    long deltaoff;
+
+    buf = malloc(4096 + 4);
+    if (buf == NULL)
+      return ZE_MEM;
+
+#ifdef HANDLE_AMIGA_SFX
+    amiga_sfx_offset = (fread(buf, 1, 4, f) == 4 && LG(buf) == 0xF3030000);
+    /* == 1 if this file is an Amiga executable (presumably UnZipSFX) */
+#endif
+    found = 0;
+    t = &buf[4096];
+    t[1] = '\0';
+    t[2] = '\0';
+    t[3] = '\0';
+    if (fseek(f, -4096L, SEEK_END) == 0) {
+      zipbeg = (ulg) (ftell(f) + 4096L);
+      while (!found && zipbeg >= 4096) {
+        zipbeg -= 4096L;
+        buf[4096] = t[1];
+        buf[4097] = t[2];
+        buf[4098] = t[3];
+/*
+ * XXX error check ??
+ */
+        fread(buf, 1, 4096, f);
+        fseek(f, -8192L, SEEK_CUR);
+        t = &buf[4095];
+/*
+ * XXX far pointer arithmetic in DOS
+ */
+        while (t >= buf) {
+          /* Check for ENDSIG the End Of Central Directory Record signature
+             ("PK\5\6" in ASCII) */
+          if (LG(t) == ENDSIG) {
+            found = 1;
+/*
+ * XXX error check ??
+ * XXX far pointer arithmetic in DOS
+ */
+            zipbeg += (ulg) (t - buf);
+            fseek(f, (long) zipbeg + 4L, SEEK_SET);
+            break;
+          }
+          --t;
+        }
+      }
+    }
+    else
+       zipbeg = 4096L;
+/*
+ * XXX warn: garbage at the end of the file ignored
+ */
+    if (!found && zipbeg > 0) {
+      size_t s;
+
+      fseek(f, 0L, SEEK_SET);
+      clearerr(f);
+      s = fread(buf, 1, (size_t) zipbeg, f);
+      buf[s] = t[1];
+      buf[s + 1] = t[2];
+      buf[s + 2] = t[3];
+      t = &buf[s - 1];
+/*
+ * XXX far pointer comparison in DOS
+ */
+      while (t >= buf) {
+        /* Check for ENDSIG ("PK\5\6" in ASCII) */
+        if (LG(t) == ENDSIG) {
+          found = 1;
+/*
+ * XXX far pointer arithmetic in DOS
+ */
+          zipbeg = (ulg) (t - buf);
+          fseek(f, (long) zipbeg + 4L, SEEK_SET);
+          break;
+        }
+        --t;
+      }
+    }
+    free(buf);
+    if (!found) {
+      zipwarn("missing end signature--probably not a zip file (did you", "");
+      zipwarn("remember to use binary mode when you transferred it?)", "");
+      return ZE_FORM;
+    }
+
+/*
+ * Read the End Of Central Directory Record
+ */
+    /* Read end header */
+    if (fread(b, ENDHEAD, 1, f) != 1)
+      return ferror(f) ? ZE_READ : ZE_EOF;
+    if (SH(ENDDSK + b) || SH(ENDBEG + b) ||
+        SH(ENDSUB + b) != SH(ENDTOT + b))
+      zipwarn("multiple disk information ignored", "");
+    zcomlen = SH(ENDCOM + b);
+    if (zcomlen)
+    {
+      if ((zcomment = malloc(zcomlen)) == NULL)
+        return ZE_MEM;
+      if (fread(zcomment, zcomlen, 1, f) != 1)
+      {
+        free((zvoid *)zcomment);
+        zcomment = NULL;
+        return ferror(f) ? ZE_READ : ZE_EOF;
+      }
+#ifdef EBCDIC
+      if (zcomment)
+         memtoebc(zcomment, zcomment, zcomlen);
+#endif /* EBCDIC */
+    }
+/*
+ * XXX assumes central header immediately precedes end header
+ */
+    cenbeg = zipbeg - LG(ENDSIZ + b);
+    deltaoff = adjust ? cenbeg - LG(b + ENDOFF) : 0L;
+    if (fseek(f, cenbeg, SEEK_SET) != 0) {
+        perror("fseek");
+        return ZE_FORM; /* XXX */
+    }
+
+    x = &zfiles;                        /* first link */
+
+    if (fread(b, 4, 1, f) != 1)
+      return ferror(f) ? ZE_READ : ZE_EOF;
+
+    while (LG(b) == CENSIG) {
+      /* Read central header. The portion of the central header that should
+         be in common with local header is read raw, for later comparison.
+         (this requires that the offset of ext in the zlist structure
+         be greater than or equal to LOCHEAD) */
+      if (fread(b, CENHEAD, 1, f) != 1)
+        return ferror(f) ? ZE_READ : ZE_EOF;
+      if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL)
+        return ZE_MEM;
+      z->vem = SH(CENVEM + b);
+      for (u = (char far *)(&(z->ver)), n = 0; n < (CENNAM-CENVER); n++)
+        u[n] = b[CENVER + n];
+      z->nam = SH(CENNAM + b);          /* used before comparing cen vs. loc */
+      z->cext = SH(CENEXT + b);         /* may be different from z->ext */
+      z->com = SH(CENCOM + b);
+      z->dsk = SH(CENDSK + b);
+      z->att = SH(CENATT + b);
+      z->atx = LG(CENATX + b);
+      z->off = LG(CENOFF + b) + deltaoff;
+      z->dosflag = (z->vem & 0xff00) == 0;
+
+      /* Initialize all fields pointing to malloced data to NULL */
+      z->zname = z->name = z->iname = z->extra = z->cextra = z->comment = NULL;
+
+      /* Link into list */
+      *x = z;
+      z->nxt = NULL;
+      x = &z->nxt;
+
+      /* Read file name, extra field and comment field */
+      if (z->nam == 0)
+      {
+        sprintf(errbuf, "%lu", (ulg)zcount + 1);
+        zipwarn("zero-length name for entry #", errbuf);
+#ifndef DEBUG
+        farfree((zvoid far *)z);
+        return ZE_FORM;
+#endif
+      }
+      if ((z->iname = malloc(z->nam+1)) ==  NULL ||
+          (z->cext && (z->cextra = malloc(z->cext)) == NULL) ||
+          (z->com && (z->comment = malloc(z->com)) == NULL))
+        return ZE_MEM;
+      if (fread(z->iname, z->nam, 1, f) != 1 ||
+          (z->cext && fread(z->cextra, z->cext, 1, f) != 1) ||
+          (z->com && fread(z->comment, z->com, 1, f) != 1))
+        return ferror(f) ? ZE_READ : ZE_EOF;
+      z->iname[z->nam] = '\0';                  /* terminate name */
+#ifdef EBCDIC
+      if (z->com)
+         memtoebc(z->comment, z->comment, z->com);
+#endif /* EBCDIC */
+      /* Update zipbeg offset, prepare for next header */
+      if (z->off < zipbeg)
+         zipbeg = z->off;
+      zcount++;
+      /* Read next signature */
+      if (fread(b, 4, 1, f) != 1)
+          return ferror(f) ? ZE_READ : ZE_EOF;
+    }
+
+    /* Point to start of header list and read local headers */
+    z = zfiles;
+    while (z != NULL) {
+      /* Read next signature */
+      if (fseek(f, z->off, SEEK_SET) != 0 || fread(b, 4, 1, f) != 1)
+        return ferror(f) ? ZE_READ : ZE_EOF;
+      if (LG(b) == LOCSIG) {
+        if (fread(b, LOCHEAD, 1, f) != 1)
+            return ferror(f) ? ZE_READ : ZE_EOF;
+        z->lflg = SH(LOCFLG + b);
+        n = SH(LOCNAM + b);
+        z->ext = SH(LOCEXT + b);
+
+        /* Compare name and extra fields */
+        if (n != z->nam)
+        {
+#ifdef EBCDIC
+          strtoebc(z->iname, z->iname);
+#endif
+          zipwarn("name lengths in local and central differ for ", z->iname);
+          return ZE_FORM;
+        }
+        if ((t = malloc(z->nam)) == NULL)
+          return ZE_MEM;
+        if (fread(t, z->nam, 1, f) != 1)
+        {
+          free((zvoid *)t);
+          return ferror(f) ? ZE_READ : ZE_EOF;
+        }
+        if (memcmp(t, z->iname, z->nam))
+        {
+          free((zvoid *)t);
+#ifdef EBCDIC
+          strtoebc(z->iname, z->iname);
+#endif
+          zipwarn("names in local and central differ for ", z->iname);
+          return ZE_FORM;
+        }
+        free((zvoid *)t);
+        if (z->ext)
+        {
+          if ((z->extra = malloc(z->ext)) == NULL)
+            return ZE_MEM;
+          if (fread(z->extra, z->ext, 1, f) != 1)
+          {
+            free((zvoid *)(z->extra));
+            return ferror(f) ? ZE_READ : ZE_EOF;
+          }
+          if (z->ext == z->cext && memcmp(z->extra, z->cextra, z->ext) == 0)
+          {
+            free((zvoid *)(z->extra));
+            z->extra = z->cextra;
+          }
+        }
+
+        /* Check extended local header if there is one */
+        if ((z->lflg & 8) != 0)
+        {
+          char buf2[16];
+          ulg s;                        /* size of compressed data */
+
+          s = LG(LOCSIZ + b);
+          if (s == 0)
+            s = LG((CENSIZ-CENVER) + (char far *)(&(z->ver)));
+          if (fseek(f, (z->off + (4+LOCHEAD) + z->nam + z->ext + s), SEEK_SET)
+              || (fread(buf2, 16, 1, f) != 1))
+            return ferror(f) ? ZE_READ : ZE_EOF;
+          if (LG(buf2) != EXTLOCSIG)
+          {
+#ifdef EBCDIC
+            strtoebc(z->iname, z->iname);
+#endif
+            zipwarn("extended local header not found for ", z->iname);
+            return ZE_FORM;
+          }
+          /* overwrite the unknown values of the local header: */
+          for (n = 0; n < 12; n++)
+            b[LOCCRC+n] = buf2[4+n];
+        }
+
+        /* Compare local header with that part of central header (except
+           for the reserved bits in the general purpose flags and except
+           for the already checked entry name length */
+        u = (char far *)(&(z->ver));
+        flg = SH((CENFLG-CENVER) + u);          /* Save central flags word */
+        u[CENFLG-CENVER+1] &= 0x1f;             /* Mask reserved flag bits */
+        b[LOCFLG+1] &= 0x1f;
+        for (m = 0, n = 0; n < LOCNAM; n++)
+          if (b[n] != u[n])
+          {
+            if (!m)
+            {
+              zipwarn("local and central headers differ for ", z->zname);
+              m = 1;
+            }
+            if (noisy)
+            {
+              sprintf(errbuf, " offset %u--local = %02x, central = %02x",
+                      (unsigned)n, (uch)b[n], (uch)u[n]);
+              zipwarn(errbuf, "");
+            }
+          }
+        if (m && !adjust)
+          return ZE_FORM;
+
+        /* Complete the setup of the zlist entry by translating the remaining
+         * central header fields in memory, starting with the fields with
+         * highest offset. This order of the conversion commands takes into
+         * account potential buffer overlaps caused by structure padding.
+         */
+        z->len = LG((CENLEN-CENVER) + u);
+        z->siz = LG((CENSIZ-CENVER) + u);
+        z->crc = LG((CENCRC-CENVER) + u);
+        z->tim = LG((CENTIM-CENVER) + u);   /* time and date into one long */
+        z->how = SH((CENHOW-CENVER) + u);
+        z->flg = flg;                       /* may be different from z->lflg */
+        z->ver = SH((CENVER-CENVER) + u);
+
+        /* Clear actions */
+        z->mark = 0;
+        z->trash = 0;
+#ifdef UTIL
+/* We only need z->iname in the utils */
+        z->name = z->iname;
+#ifdef EBCDIC
+/* z->zname is used for printing and must be coded in native charset */
+        if ((z->zname = malloc(z->nam+1)) ==  NULL)
+          return ZE_MEM;
+        strtoebc(z->zname, z->iname);
+#else
+        z->zname = z->iname;
+#endif
+#else /* !UTIL */
+        z->zname = in2ex(z->iname);       /* convert to external name */
+        if (z->zname == NULL)
+          return ZE_MEM;
+        z->name = z->zname;
+#endif /* ?UTIL */
+      }
+      else {
+#ifdef EBCDIC
+        strtoebc(z->iname, z->iname);
+#endif
+        zipwarn("local header not found for ", z->iname);
+        return ZE_FORM;
+      }
+#ifndef UTIL
+      if (verbose)
+        zipoddities(z);
+#endif
+      z = z->nxt;
+    }
+
+    if (zipbeg && noisy)
+      fprintf(mesg, "%s: %s a preamble of %lu bytes\n",
+              zipfile, adjust ? "adjusting offsets for" : "found", zipbeg);
+
+#ifdef HANDLE_AMIGA_SFX
+    if (zipbeg < 12 || (zipbeg & 3) != 0 /* must be longword aligned */)
+      amiga_sfx_offset = 0;
+    else if (amiga_sfx_offset) {
+      char buf2[16];
+      if (!fseek(f, zipbeg - 12, SEEK_SET) && fread(buf2, 12, 1, f) == 1) {
+        if (LG(buf2 + 4) == 0xF1030000 /* 1009 in Motorola byte order */)
+          /* could also check if LG(buf2) == 0xF2030000... no for now */
+          amiga_sfx_offset = zipbeg - 4;
+        else
+          amiga_sfx_offset = 0L;
+      }
+    }
+#endif /* HANDLE_AMIGA_SFX */
+    return ZE_OK;
+}
+
+
+/*
+ * readzipfile initializes the global variables that hold the zipfile
+ * directory info and opens the zipfile. For the actual zipfile scan,
+ * the subroutine scanzipf_reg() or scanzipf_fix() is called,
+ * depending on the mode of operation (regular processing, or zipfix mode).
+ */
+int readzipfile()
+/*
+   The name of the zip file is pointed to by the global "zipfile".
+   The globals zipbeg, zfiles, zcount, and zcomlen are initialized.
+   Return an error code in the ZE_ class.
+*/
+{
+  FILE *f;              /* zip file */
+  int retval;           /* return code */
+  int readable;         /* 1 if zipfile exists and is readable */
+
+  /* Initialize zip file info */
+  zipbeg = 0;
+  zfiles = NULL;                        /* Points to first header */
+  zcount = 0;                           /* number of files */
+  zcomlen = 0;                          /* zip file comment length */
+  retval = ZE_OK;
+  f = NULL;                             /* shut up some compilers */
+
+  /* If zip file exists, read headers and check structure */
+#ifdef VMS
+  if (zipfile == NULL || !(*zipfile) || !strcmp(zipfile, "-"))
+    return ZE_OK;
+  {
+    int rtype;
+
+    if ((VMSmunch(zipfile, GET_RTYPE, (char *)&rtype) == RMS$_NORMAL) &&
+        (rtype == FAT$C_VARIABLE)) {
+      fprintf(stderr,
+     "\n     Error:  zipfile is in variable-length record format.  Please\n\
+     run \"bilf b %s\" to convert the zipfile to fixed-length\n\
+     record format.\n\n", zipfile);
+      return ZE_FORM;
+    }
+  }
+  readable = ((f = fopen(zipfile, FOPR)) != NULL);
+#else /* !VMS */
+  readable = (zipfile != NULL && *zipfile && strcmp(zipfile, "-") &&
+              (f = fopen(zipfile, FOPR)) != NULL);
+#endif /* ?VMS */
+#ifdef MVS
+  /* Very nasty special case for MVS.  Just because the zipfile has been
+   * opened for reading does not mean that we can actually read the data.
+   * Typical JCL to create a zipfile is
+   *
+   * //ZIPFILE  DD  DISP=(NEW,CATLG),DSN=prefix.ZIP,
+   * //             SPACE=(CYL,(10,10))
+   *
+   * That creates a VTOC entry with an end of file marker (DS1LSTAR) of zero.
+   * Alas the VTOC end of file marker is only used when the file is opened in
+   * append mode.  When a file is opened in read mode, the "other" end of file
+   * marker is used, a zero length data block signals end of file when reading.
+   * With a brand new file which has not been written to yet, it is undefined
+   * what you read off the disk.  In fact you read whatever data was in the same
+   * disk tracks before the zipfile was allocated.  You would be amazed at the
+   * number of application programmers who still do not understand this.  Makes
+   * for interesting and semi-random errors, GIGO.
+   *
+   * Newer versions of SMS will automatically write a zero length block when a
+   * file is allocated.  However not all sites run SMS or they run older levels
+   * so we cannot rely on that.  The only safe thing to do is close the file,
+   * open in append mode (we already know that the file exists), close it again,
+   * reopen in read mode and try to read a data block.  Opening and closing in
+   * append mode will write a zero length block where DS1LSTAR points, making
+   * sure that the VTOC and internal end of file markers are in sync.  Then it
+   * is safe to read data.  If we cannot read one byte of data after all that,
+   * it is a brand new zipfile and must not be read.
+   */
+  if (readable)
+  {
+    char c;
+    fclose(f);
+    /* append mode */
+    if ((f = fopen(zipfile, "ab")) == NULL) {
+      ZIPERR(ZE_OPEN, zipfile);
+    }
+    fclose(f);
+    /* read mode again */
+    if ((f = fopen(zipfile, FOPR)) == NULL) {
+      ZIPERR(ZE_OPEN, zipfile);
+    }
+    if (fread(&c, 1, 1, f) != 1) {
+      /* no actual data */
+      readable = 0;
+      fclose(f);
+    }
+    else{
+      fseek(f, 0, SEEK_SET);  /* at least one byte in zipfile, back to the start */
+    }
+  }
+#endif /* MVS */
+  if (readable)
+  {
+#ifndef UTIL
+    retval = (fix && !adjust) ? scanzipf_fix(f) : scanzipf_reg(f);
+#else
+    retval = scanzipf_reg(f);
+#endif
+
+    /* Done with zip file for now */
+    fclose(f);
+
+    /* If one or more files, sort by name */
+    if (zcount)
+    {
+      struct zlist far * far *x;    /* pointer into zsort array */
+      struct zlist far *z;          /* pointer into zfiles linked list */
+      extent zl_size = zcount * sizeof(struct zlist far *);
+
+      if (zl_size / sizeof(struct zlist far *) != zcount ||
+          (x = zsort = (struct zlist far **)malloc(zl_size)) == NULL)
+        return ZE_MEM;
+      for (z = zfiles; z != NULL; z = z->nxt)
+        *x++ = z;
+      qsort((char *)zsort, zcount, sizeof(struct zlist far *), zqcmp);
+    }
+  }
+  return retval;
+}
+
+
+int putlocal(z, f)
+struct zlist far *z;    /* zip entry to write local header for */
+FILE *f;                /* file to write to */
+/* Write a local header described by *z to file *f.  Return an error code
+   in the ZE_ class. */
+{
+  PUTLG(LOCSIG, f);
+  PUTSH(z->ver, f);
+  PUTSH(z->lflg, f);
+  PUTSH(z->how, f);
+  PUTLG(z->tim, f);
+  PUTLG(z->crc, f);
+  PUTLG(z->siz, f);
+  PUTLG(z->len, f);
+  PUTSH(z->nam, f);
+  PUTSH(z->ext, f);
+  if (fwrite(z->iname, 1, z->nam, f) != z->nam ||
+      (z->ext && fwrite(z->extra, 1, z->ext, f) != z->ext))
+    return ZE_TEMP;
+  return ZE_OK;
+}
+
+int putextended(z, f)
+struct zlist far *z;    /* zip entry to write local header for */
+FILE *f;                /* file to write to */
+/* Write an extended local header described by *z to file *f.
+ * Return an error code in the ZE_ class. */
+{
+  PUTLG(EXTLOCSIG, f);
+  PUTLG(z->crc, f);
+  PUTLG(z->siz, f);
+  PUTLG(z->len, f);
+  return ZE_OK;
+}
+
+int putcentral(z, f)
+struct zlist far *z;    /* zip entry to write central header for */
+FILE *f;                /* file to write to */
+/* Write a central header described by *z to file *f.  Return an error code
+   in the ZE_ class. */
+{
+  PUTLG(CENSIG, f);
+  PUTSH(z->vem, f);
+  PUTSH(z->ver, f);
+  PUTSH(z->flg, f);
+  PUTSH(z->how, f);
+  PUTLG(z->tim, f);
+  PUTLG(z->crc, f);
+  PUTLG(z->siz, f);
+  PUTLG(z->len, f);
+  PUTSH(z->nam, f);
+  PUTSH(z->cext, f);
+  PUTSH(z->com, f);
+  PUTSH(z->dsk, f);
+  PUTSH(z->att, f);
+  PUTLG(z->atx, f);
+  PUTLG(z->off, f);
+#ifdef EBCDIC
+  if (z->com)
+    memtoasc(z->comment, z->comment, z->com);
+#endif /* EBCDIC */
+  if (fwrite(z->iname, 1, z->nam, f) != z->nam ||
+      (z->cext && fwrite(z->cextra, 1, z->cext, f) != z->cext) ||
+      (z->com && fwrite(z->comment, 1, z->com, f) != z->com))
+    return ZE_TEMP;
+  return ZE_OK;
+}
+
+
+int putend(n, s, c, m, z, f)
+int n;                  /* number of entries in central directory */
+ulg s;                  /* size of central directory */
+ulg c;                  /* offset of central directory */
+extent m;               /* length of zip file comment (0 if none) */
+char *z;                /* zip file comment if m != 0 */
+FILE *f;                /* file to write to */
+/* Write the end of central directory data to file *f.  Return an error code
+   in the ZE_ class. */
+{
+  PUTLG(ENDSIG, f);
+  PUTSH(0, f);
+  PUTSH(0, f);
+  PUTSH(n, f);
+  PUTSH(n, f);
+  PUTLG(s, f);
+  PUTLG(c, f);
+  PUTSH(m, f);
+/* Write the comment, if any */
+#ifdef EBCDIC
+  memtoasc(z, z, m);
+#endif
+  if (m && fwrite(z, 1, m, f) != m)
+    return ZE_TEMP;
+
+#ifdef HANDLE_AMIGA_SFX
+  if (amiga_sfx_offset && zipbeg /* -J zeroes this */) {
+    s = ftell(f);
+    while (s & 3) s++, putc(0, f);   /* final marker must be longword aligned */
+    PUTLG(0xF2030000 /* 1010 in Motorola byte order */, f);
+    c = (s - amiga_sfx_offset - 4) / 4;  /* size of archive part in longwords */
+    if (fseek(f, amiga_sfx_offset, SEEK_SET) != 0)
+      return ZE_TEMP;
+    c = ((c >> 24) & 0xFF) | ((c >> 8) & 0xFF00)
+         | ((c & 0xFF00) << 8) | ((c & 0xFF) << 24);     /* invert byte order */
+    PUTLG(c, f);
+    fseek(f, 0, SEEK_END);                                    /* just in case */
+  }
+#endif
+  return ZE_OK;
+}
+
+
+/* Note: a zip "entry" includes a local header (which includes the file
+   name), an encryption header if encrypting, the compressed data
+   and possibly an extended local header. */
+
+int zipcopy(z, x, y)
+struct zlist far *z;    /* zip entry to copy */
+FILE *x, *y;            /* source and destination files */
+/* Copy the zip entry described by *z from file *x to file *y.  Return an
+   error code in the ZE_ class.  Also update tempzn by the number of bytes
+   copied. */
+{
+  ulg n;                /* holds local header offset */
+
+  Trace((stderr, "zipcopy %s\n", z->zname));
+  n = (ulg)(4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext;
+
+  if (fix > 1) {
+    if (fseek(x, z->off + n, SEEK_SET)) /* seek to compressed data */
+      return ferror(x) ? ZE_READ : ZE_EOF;
+
+    if (fix > 2) {
+      /* Update length of entry's name, it may have been changed.  This is
+         needed to support the ZipNote ability to rename archive entries. */
+      z->nam = strlen(z->iname);
+      n = (ulg)(4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext;
+    }
+
+    /* do not trust the old compressed size */
+    if (putlocal(z, y) != ZE_OK)
+      return ZE_TEMP;
+
+    z->off = tempzn;
+    tempzn += n;
+    n = z->siz;
+  } else {
+    if (fseek(x, z->off, SEEK_SET))     /* seek to local header */
+      return ferror(x) ? ZE_READ : ZE_EOF;
+
+    z->off = tempzn;
+    n += z->siz;
+  }
+  /* copy the compressed data and the extended local header if there is one */
+  if (z->lflg & 8) n += 16;
+  tempzn += n;
+  return fcopy(x, y, n);
+}
+
+
+#ifndef UTIL
+
+#ifdef USE_EF_UT_TIME
+
+local int ef_scan_ut_time(ef_buf, ef_len, ef_is_cent, z_utim)
+char *ef_buf;                   /* buffer containing extra field */
+extent ef_len;                  /* total length of extra field */
+int ef_is_cent;                 /* flag indicating "is central extra field" */
+iztimes *z_utim;                /* return storage: atime, mtime, ctime */
+/* This function scans the extra field for EF_TIME or EF_IZUNIX blocks
+ * containing Unix style time_t (GMT) values for the entry's access, creation
+ * and modification time.
+ * If a valid block is found, all time stamps are copied to the iztimes
+ * structure.
+ * The presence of an EF_TIME or EF_IZUNIX2 block results in ignoring
+ * all data from probably present obsolete EF_IZUNIX blocks.
+ * If multiple blocks of the same type are found, only the information from
+ * the last block is used.
+ * The return value is the EF_TIME Flags field (simulated in case of an
+ * EF_IZUNIX block) or 0 in case of failure.
+ */
+{
+  int flags = 0;
+  unsigned eb_id;
+  extent eb_len;
+  int have_new_type_eb = FALSE;
+
+  if (ef_len == 0 || ef_buf == NULL)
+    return 0;
+
+  Trace((stderr,"\nef_scan_ut_time: scanning extra field of length %u\n",
+         ef_len));
+  while (ef_len >= EB_HEADSIZE) {
+    eb_id = SH(EB_ID + ef_buf);
+    eb_len = SH(EB_LEN + ef_buf);
+
+    if (eb_len > (ef_len - EB_HEADSIZE)) {
+      /* Discovered some extra field inconsistency! */
+      Trace((stderr,"ef_scan_ut_time: block length %u > rest ef_size %u\n",
+             eb_len, ef_len - EB_HEADSIZE));
+      break;
+    }
+
+    switch (eb_id) {
+      case EF_TIME:
+        flags &= ~0x00ff;       /* ignore previous IZUNIX or EF_TIME fields */
+        have_new_type_eb = TRUE;
+        if ( eb_len >= EB_UT_MINLEN && z_utim != NULL) {
+           unsigned eb_idx = EB_UT_TIME1;
+           Trace((stderr,"ef_scan_ut_time: Found TIME extra field\n"));
+           flags |= (ef_buf[EB_HEADSIZE+EB_UT_FLAGS] & 0x00ff);
+           if ((flags & EB_UT_FL_MTIME)) {
+              if ((eb_idx+4) <= eb_len) {
+                 z_utim->mtime = LG((EB_HEADSIZE+eb_idx) + ef_buf);
+                 eb_idx += 4;
+                 Trace((stderr,"  Unix EF modtime = %ld\n", z_utim->mtime));
+              } else {
+                 flags &= ~EB_UT_FL_MTIME;
+                 Trace((stderr,"  Unix EF truncated, no modtime\n"));
+              }
+           }
+           if (ef_is_cent) {
+              break;            /* central version of TIME field ends here */
+           }
+           if (flags & EB_UT_FL_ATIME) {
+              if ((eb_idx+4) <= eb_len) {
+                 z_utim->atime = LG((EB_HEADSIZE+eb_idx) + ef_buf);
+                 eb_idx += 4;
+                 Trace((stderr,"  Unix EF acctime = %ld\n", z_utim->atime));
+              } else {
+                 flags &= ~EB_UT_FL_ATIME;
+              }
+           }
+           if (flags & EB_UT_FL_CTIME) {
+              if ((eb_idx+4) <= eb_len) {
+                 z_utim->ctime = LG((EB_HEADSIZE+eb_idx) + ef_buf);
+                 /* eb_idx += 4; */  /* superfluous for now ... */
+                 Trace((stderr,"  Unix EF cretime = %ld\n", z_utim->ctime));
+              } else {
+                 flags &= ~EB_UT_FL_CTIME;
+              }
+           }
+        }
+        break;
+
+      case EF_IZUNIX2:
+        if (!have_new_type_eb) {
+           flags &= ~0x00ff;    /* ignore any previous IZUNIX field */
+           have_new_type_eb = TRUE;
+        }
+        break;
+
+      case EF_IZUNIX:
+        if (eb_len >= EB_UX_MINLEN) {
+           Trace((stderr,"ef_scan_ut_time: Found IZUNIX extra field\n"));
+           if (have_new_type_eb) {
+              break;            /* Ignore IZUNIX extra field block ! */
+           }
+           z_utim->atime = LG((EB_HEADSIZE+EB_UX_ATIME) + ef_buf);
+           z_utim->mtime = LG((EB_HEADSIZE+EB_UX_MTIME) + ef_buf);
+           Trace((stderr,"  Unix EF access time = %ld\n",z_utim->atime));
+           Trace((stderr,"  Unix EF modif. time = %ld\n",z_utim->mtime));
+           flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME);  /* signal success */
+        }
+        break;
+
+      case EF_THEOS:
+/*      printf("Not implemented yet\n"); */
+        break;
+
+      default:
+        break;
+    }
+    /* Skip this extra field block */
+    ef_buf += (eb_len + EB_HEADSIZE);
+    ef_len -= (eb_len + EB_HEADSIZE);
+  }
+
+  return flags;
+}
+
+int get_ef_ut_ztime(z, z_utim)
+struct zlist far *z;
+iztimes *z_utim;
+{
+  int r;
+
+#ifdef IZ_CHECK_TZ
+  if (!zp_tz_is_valid) return 0;
+#endif
+
+  /* First, scan local extra field. */
+  r = ef_scan_ut_time(z->extra, z->ext, FALSE, z_utim);
+
+  /* If this was not successful, try central extra field, but only if
+     it is really different. */
+  if (!r && z->cext > 0 && z->cextra != z->extra)
+    r = ef_scan_ut_time(z->cextra, z->cext, TRUE, z_utim);
+
+  return r;
+}
+
+#endif /* USE_EF_UT_TIME */
+
+
+local void cutpath(p, delim)
+char *p;                /* path string */
+int delim;              /* path component separator char */
+/* Cut the last path component off the name *p in place.
+ * This should work on both internal and external names.
+ */
+{
+  char *r;              /* pointer to last path delimiter */
+
+#ifdef VMS                      /* change [w.x.y]z to [w.x]y.DIR */
+  if ((r = MBSRCHR(p, ']')) != NULL)
+  {
+    *r = 0;
+    if ((r = MBSRCHR(p, '.')) != NULL)
+    {
+      *r = ']';
+      strcat(r, ".DIR;1");     /* this assumes a little padding--see PAD */
+    } else {
+      *p = 0;
+    }
+  } else {
+    if ((r = MBSRCHR(p, delim)) != NULL)
+      *r = 0;
+    else
+      *p = 0;
+  }
+#else /* !VMS */
+  if ((r = MBSRCHR(p, delim)) != NULL)
+    *r = 0;
+  else
+    *p = 0;
+#endif /* ?VMS */
+}
+
+int trash()
+/* Delete the compressed files and the directories that contained the deleted
+   files, if empty.  Return an error code in the ZE_ class.  Failure of
+   destroy() or deletedir() is ignored. */
+{
+  extent i;             /* counter on deleted names */
+  extent n;             /* number of directories to delete */
+  struct zlist far **s; /* table of zip entries to handle, sorted */
+  struct zlist far *z;  /* current zip entry */
+
+  /* Delete marked names and count directories */
+  n = 0;
+  for (z = zfiles; z != NULL; z = z->nxt)
+    if (z->mark == 1 || z->trash)
+    {
+      z->mark = 1;
+      if (z->iname[z->nam - 1] != (char)0x2f) { /* don't unlink directory */
+        if (verbose)
+          fprintf(mesg, "zip diagnostic: deleting file %s\n", z->name);
+        if (destroy(z->name)) {
+          zipwarn("error deleting ", z->name);
+        }
+        /* Try to delete all paths that lead up to marked names. This is
+         * necessary only with the -D option.
+         */
+        if (!dirnames) {
+          cutpath(z->name, '/');  /* XXX wrong ??? */
+          cutpath(z->iname, 0x2f); /* 0x2f = ascii['/'] */
+          z->nam = strlen(z->iname);
+          if (z->nam > 0) {
+            z->iname[z->nam - 1] = (char)0x2f;
+            z->iname[z->nam++] = '\0';
+          }
+          if (z->nam > 0) n++;
+        }
+      } else {
+        n++;
+      }
+    }
+
+  /* Construct the list of all marked directories. Some may be duplicated
+   * if -D was used.
+   */
+  if (n)
+  {
+    if ((s = (struct zlist far **)malloc(n*sizeof(struct zlist far *))) ==
+        NULL)
+      return ZE_MEM;
+    n = 0;
+    for (z = zfiles; z != NULL; z = z->nxt) {
+      if (z->mark && z->nam > 0 && z->iname[z->nam - 1] == (char)0x2f /* '/' */
+          && (n == 0 || strcmp(z->name, s[n-1]->name) != 0)) {
+        s[n++] = z;
+      }
+    }
+    /* Sort the files in reverse order to get subdirectories first.
+     * To avoid problems with strange naming conventions as in VMS,
+     * we sort on the internal names, so x/y/z will always be removed
+     * before x/y. On VMS, x/y/z > x/y but [x.y.z] < [x.y]
+     */
+    qsort((char *)s, n, sizeof(struct zlist far *), rqcmp);
+
+    for (i = 0; i < n; i++) {
+      char *p = s[i]->name;
+      if (*p == '\0') continue;
+      if (p[strlen(p) - 1] == '/') { /* keep VMS [x.y]z.dir;1 intact */
+        p[strlen(p) - 1] = '\0';
+      }
+      if (i == 0 || strcmp(s[i]->name, s[i-1]->name) != 0) {
+        if (verbose) {
+          fprintf(mesg, "deleting directory %s (if empty)                \n",
+                  s[i]->name);
+        }
+        deletedir(s[i]->name);
+      }
+    }
+    free((zvoid *)s);
+  }
+  return ZE_OK;
+}
+
+#endif /* !UTIL */
diff --git a/zipnote.c b/zipnote.c
new file mode 100644 (file)
index 0000000..963fe3d
--- /dev/null
+++ b/zipnote.c
@@ -0,0 +1,505 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2005-Feb-10 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *  zipnote.c by Mark Adler.
+ */
+#define __ZIPNOTE_C
+
+#ifndef UTIL
+#define UTIL
+#endif
+#include "zip.h"
+#define DEFCPYRT        /* main module: enable copyright string defines! */
+#include "revision.h"
+#include <signal.h>
+
+/* Calculate size of static line buffer used in write (-w) mode. */
+#define WRBUFSIZ 2047
+/* The line buffer size should be at least as large as FNMAX. */
+#if FNMAX > WRBUFSIZ
+#  undef WRBUFSIZ
+#  define WRBUFSIZ FNMAX
+#endif
+
+/* Character to mark zip entry names in the comment file */
+#define MARK '@'
+#define MARKE " (comment above this line)"
+#define MARKZ " (zip file comment below this line)"
+
+/* Temporary zip file name and file pointer */
+local char *tempzip;
+local FILE *tempzf;
+
+
+/* Local functions */
+local void handler OF((int));
+local void license OF((void));
+local void help OF((void));
+local void version_info OF((void));
+local void putclean OF((char *, extent));
+/* getline name conflicts with GNU getline() function */
+local char *_getline OF((char *, extent));
+local int catalloc OF((char * far *, char *));
+int main OF((int, char **));
+
+#ifdef MACOS
+#define ziperr(c, h)    zipnoteerr(c, h)
+#define zipwarn(a, b)   zipnotewarn(a, b)
+
+void zipnoteerr(int c, ZCONST char *h);
+void zipnotewarn(ZCONST char *a, ZCONST char *b);
+#endif
+
+#ifdef QDOS
+#define exit(p1) QDOSexit()
+#endif
+
+void ziperr(c, h)
+int c;                  /* error code from the ZE_ class */
+ZCONST char *h;         /* message about how it happened */
+/* Issue a message for the error, clean up files and memory, and exit. */
+{
+  if (PERR(c))
+    perror("zipnote error");
+  fprintf(stderr, "zipnote error: %s (%s)\n", ziperrors[c-1], h);
+  if (tempzf != NULL)
+    fclose(tempzf);
+  if (tempzip != NULL)
+  {
+    destroy(tempzip);
+    free((zvoid *)tempzip);
+  }
+  if (zipfile != NULL)
+    free((zvoid *)zipfile);
+  EXIT(c);
+}
+
+
+local void handler(s)
+int s;                  /* signal number (ignored) */
+/* Upon getting a user interrupt, abort cleanly using ziperr(). */
+{
+#ifndef MSDOS
+  putc('\n', stderr);
+#endif /* !MSDOS */
+  ziperr(ZE_ABORT, "aborting");
+  s++;                                  /* keep some compilers happy */
+}
+
+
+void zipwarn(a, b)
+ZCONST char *a, *b;     /* message strings juxtaposed in output */
+/* Print a warning message to stderr and return. */
+{
+  fprintf(stderr, "zipnote warning: %s%s\n", a, b);
+}
+
+
+local void license()
+/* Print license information to stdout. */
+{
+  extent i;             /* counter for copyright array */
+
+  for (i = 0; i < sizeof(swlicense)/sizeof(char *); i++)
+    puts(swlicense[i]);
+}
+
+
+local void help()
+/* Print help (along with license info) to stdout. */
+{
+  extent i;             /* counter for help array */
+
+  /* help array */
+  static ZCONST char *text[] = {
+"",
+"ZipNote %s (%s)",
+#ifdef VM_CMS
+"Usage:  zipnote [-w] [-b fm] zipfile",
+#else
+"Usage:  zipnote [-w] [-b path] zipfile",
+#endif
+"  the default action is to write the comments in zipfile to stdout",
+"  -w   write the zipfile comments from stdin",
+#ifdef VM_CMS
+"  -b   use \"fm\" as the filemode for the temporary zip file",
+#else
+"  -b   use \"path\" for the temporary zip file",
+#endif
+"  -h   show this help    -v   show version info    -L   show software license",
+"",
+"Example:",
+#ifdef VMS
+"     define/user sys$output foo.tmp",
+"     zipnote foo.zip",
+"     edit foo.tmp",
+"     ... then you edit the comments, save, and exit ...",
+"     define/user sys$input foo.tmp",
+"     zipnote -w foo.zip",
+#else
+#ifdef RISCOS
+"     zipnote foo/zip > foo/tmp",
+"     <!Edit> foo/tmp",
+"     ... then you edit the comments, save, and exit ...",
+"     zipnote -w foo/zip < foo/tmp",
+#else
+#ifdef VM_CMS
+"     zipnote foo.zip > foo.tmp",
+"     xedit foo tmp",
+"     ... then you edit the comments, save, and exit ...",
+"     zipnote -w foo.zip < foo.tmp",
+#else
+"     zipnote foo.zip > foo.tmp",
+"     ed foo.tmp",
+"     ... then you edit the comments, save, and exit ...",
+"     zipnote -w foo.zip < foo.tmp",
+#endif /* VM_CMS */
+#endif /* RISCOS */
+#endif /* VMS */
+"",
+"  \"@ name\" can be followed by an \"@=newname\" line to change the name"
+  };
+
+  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++) {
+    printf(copyright[i], "zipnote");
+    putchar('\n');
+  }
+  for (i = 0; i < sizeof(text)/sizeof(char *); i++)
+  {
+    printf(text[i], VERSION, REVDATE);
+    putchar('\n');
+  }
+}
+
+/*
+ * XXX put this in version.c
+ */
+
+local void version_info()
+/* Print verbose info about program version and compile time options
+   to stdout. */
+{
+  extent i;             /* counter in text arrays */
+
+  /* Options info array */
+  static ZCONST char *comp_opts[] = {
+#ifdef DEBUG
+    "DEBUG",
+#endif
+    NULL
+  };
+
+  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
+  {
+    printf(copyright[i], "zipnote");
+    putchar('\n');
+  }
+
+  for (i = 0; i < sizeof(versinfolines)/sizeof(char *); i++)
+  {
+    printf(versinfolines[i], "ZipNote", VERSION, REVDATE);
+    putchar('\n');
+  }
+
+  version_local();
+
+  puts("ZipNote special compilation options:");
+  for (i = 0; (int)i < (int)(sizeof(comp_opts)/sizeof(char *) - 1); i++)
+  {
+    printf("\t%s\n",comp_opts[i]);
+  }
+  if (i == 0)
+      puts("\t[none]");
+}
+
+
+local void putclean(s, n)
+char *s;                /* string to write to stdout */
+extent n;               /* length of string */
+/* Write the string s to stdout, filtering out control characters that are
+   not tab or newline (mainly to remove carriage returns), and prefix MARK's
+   and backslashes with a backslash.  Also, terminate with a newline if
+   needed. */
+{
+  int c;                /* next character in string */
+  int e;                /* last character written */
+
+  e = '\n';                     /* if empty, write nothing */
+  while (n--)
+  {
+    c = *(uch *)s++;
+    if (c == MARK || c == '\\')
+      putchar('\\');
+    if (c >= ' ' || c == '\t' || c == '\n')
+      { e=c; putchar(e); }
+  }
+  if (e != '\n')
+    putchar('\n');
+}
+
+
+local char *_getline(buf, size)
+char *buf;
+extent size;
+/* Read a line of text from stdin into string buffer 'buf' of size 'size'.
+   In case of buffer overflow or EOF, a NULL pointer is returned. */
+{
+    char *line;
+    unsigned len;
+
+    line = fgets(buf, size, stdin);
+    if (line != NULL && (len = strlen(line)) > 0) {
+        if (len == size-1 && line[len-1] != '\n') {
+            /* buffer is full and record delimiter not seen -> overflow */
+            line = NULL;
+        } else {
+            /* delete trailing record delimiter */
+            if (line[len-1] == '\n') line[len-1] = '\0';
+        }
+    }
+    return line;
+}
+
+
+local int catalloc(a, s)
+char * far *a;          /* pointer to a pointer to a malloc'ed string */
+char *s;                /* string to concatenate on a */
+/* Concatentate the string s to the malloc'ed string pointed to by a.
+   Preprocess s by removing backslash escape characters. */
+{
+  char *p;              /* temporary pointer */
+  char *q;              /* temporary pointer */
+
+  for (p = q = s; *q; *p++ = *q++)
+    if (*q == '\\' && *(q+1))
+      q++;
+  *p = 0;
+  if ((p = malloc(strlen(*a) + strlen(s) + 3)) == NULL)
+    return ZE_MEM;
+  strcat(strcat(strcpy(p, *a), **a ? "\r\n" : ""), s);
+  free((zvoid *)*a);
+  *a = p;
+  return ZE_OK;
+}
+
+
+#ifndef USE_ZIPNOTEMAIN
+int main(argc, argv)
+#else
+int zipnotemain(argc, argv)
+#endif
+int argc;               /* number of tokens in command line */
+char **argv;            /* command line tokens */
+/* Write the comments in the zipfile to stdout, or read them from stdin. */
+{
+  char a[WRBUFSIZ+1];   /* input line buffer */
+  ulg c;                /* start of central directory */
+  int k;                /* next argument type */
+  char *q;              /* steps through option arguments */
+  int r;                /* arg counter, temporary variable */
+  ulg s;                /* length of central directory */
+  int t;                /* attributes of zip file */
+  int w;                /* true if updating zip file from stdin */
+  FILE *x, *y;          /* input and output zip files */
+  struct zlist far *z;  /* steps through zfiles linked list */
+
+#ifdef THEOS
+  setlocale(LC_CTYPE, "I");
+#endif
+
+  /* If no args, show help */
+  if (argc == 1)
+  {
+    help();
+    EXIT(0);
+  }
+
+  init_upper();           /* build case map table */
+
+  /* Go through args */
+  zipfile = tempzip = NULL;
+  tempzf = NULL;
+  signal(SIGINT, handler);
+#ifdef SIGTERM              /* AMIGA has no SIGTERM */
+  signal(SIGTERM, handler);
+#endif
+  k = w = 0;
+  for (r = 1; r < argc; r++)
+    if (*argv[r] == '-') {
+      if (argv[r][1])
+        for (q = argv[r]+1; *q; q++)
+          switch (*q)
+          {
+            case 'b':   /* Specify path for temporary file */
+              if (k)
+                ziperr(ZE_PARMS, "use -b before zip file name");
+              else
+                k = 1;          /* Next non-option is path */
+              break;
+            case 'h':   /* Show help */
+              help();  EXIT(0);
+            case 'l':  case 'L':  /* Show copyright and disclaimer */
+              license();  EXIT(0);
+            case 'v':   /* Show version info */
+              version_info();  EXIT(0);
+            case 'w':
+              w = 1;  break;
+            default:
+              ziperr(ZE_PARMS, "unknown option");
+          }
+      else
+        ziperr(ZE_PARMS, "zip file cannot be stdin");
+    } else
+      if (k == 0)
+      {
+        if (zipfile == NULL)
+        {
+          if ((zipfile = ziptyp(argv[r])) == NULL)
+            ziperr(ZE_MEM, "was processing arguments");
+        }
+        else
+          ziperr(ZE_PARMS, "can only specify one zip file");
+      }
+      else
+      {
+        tempath = argv[r];
+        k = 0;
+      }
+  if (zipfile == NULL)
+    ziperr(ZE_PARMS, "need to specify zip file");
+
+  /* Read zip file */
+  if ((r = readzipfile()) != ZE_OK)
+    ziperr(r, zipfile);
+  if (zfiles == NULL)
+    ziperr(ZE_NAME, zipfile);
+
+  /* Put comments to stdout, if not -w */
+  if (!w)
+  {
+    for (z = zfiles; z != NULL; z = z->nxt)
+    {
+      printf("%c %s\n", MARK, z->zname);
+      putclean(z->comment, z->com);
+      printf("%c%s\n", MARK, MARKE);
+    }
+    printf("%c%s\n", MARK, MARKZ);
+    putclean(zcomment, zcomlen);
+    EXIT(ZE_OK);
+  }
+
+  /* If updating comments, make sure zip file is writeable */
+  if ((x = fopen(zipfile, "a")) == NULL)
+    ziperr(ZE_CREAT, zipfile);
+  fclose(x);
+  t = getfileattr(zipfile);
+
+  /* Process stdin, replacing comments */
+  z = zfiles;
+  while (_getline(a, WRBUFSIZ+1) != NULL &&
+         (a[0] != MARK || strcmp(a + 1, MARKZ)))
+  {                                     /* while input and not file comment */
+    if (a[0] != MARK || a[1] != ' ')    /* better be "@ name" */
+      ziperr(ZE_NOTE, "unexpected input");
+    while (z != NULL && strcmp(a + 2, z->zname))
+      z = z->nxt;                       /* allow missing entries in order */
+    if (z == NULL)
+      ziperr(ZE_NOTE, "unknown entry name");
+    if (_getline(a, WRBUFSIZ+1) != NULL && a[0] == MARK && a[1] == '=')
+    {
+      if (z->name != z->iname)
+        free((zvoid *)z->iname);
+      if ((z->iname = malloc(strlen(a+1))) == NULL)
+        ziperr(ZE_MEM, "was changing name");
+#ifdef EBCDIC
+      strtoasc(z->iname, a+2);
+#else
+      strcpy(z->iname, a+2);
+#endif
+
+/*
+ * Don't update z->nam here, we need the old value a little later.....
+ * The update is handled in zipcopy().
+ */
+      _getline(a, WRBUFSIZ+1);
+    }
+    if (z->com)                         /* change zip entry comment */
+      free((zvoid *)z->comment);
+    z->comment = malloc(1);  *(z->comment) = 0;
+    while (a != NULL && *a != MARK)
+    {
+      if ((r = catalloc(&(z->comment), a)) != ZE_OK)
+        ziperr(r, "was building new comments");
+      _getline(a, WRBUFSIZ+1);
+    }
+    z->com = strlen(z->comment);
+    z = z->nxt;                         /* point to next entry */
+  }
+  if (a != NULL)                        /* change zip file comment */
+  {
+    zcomment = malloc(1);  *zcomment = 0;
+    while (_getline(a, WRBUFSIZ+1) != NULL)
+      if ((r = catalloc(&zcomment, a)) != ZE_OK)
+        ziperr(r, "was building new comments");
+    zcomlen = strlen(zcomment);
+  }
+
+  /* Open output zip file for writing */
+  if ((tempzf = y = fopen(tempzip = tempname(zipfile), FOPW)) == NULL)
+    ziperr(ZE_TEMP, tempzip);
+
+  /* Open input zip file again, copy preamble if any */
+  if ((x = fopen(zipfile, FOPR)) == NULL)
+    ziperr(ZE_NAME, zipfile);
+  if (zipbeg && (r = fcopy(x, y, zipbeg)) != ZE_OK)
+    ziperr(r, r == ZE_TEMP ? tempzip : zipfile);
+  tempzn = zipbeg;
+
+  /* Go through local entries, copying them over as is */
+  fix = 3; /* needed for zipcopy if name changed */
+  for (z = zfiles; z != NULL; z = z->nxt) {
+    if ((r = zipcopy(z, x, y)) != ZE_OK)
+      ziperr(r, "was copying an entry");
+  }
+  fclose(x);
+
+  /* Write central directory and end of central directory with new comments */
+  if ((c = ftell(y)) == (ulg)(-1L))    /* get start of central */
+    ziperr(ZE_TEMP, tempzip);
+  for (z = zfiles; z != NULL; z = z->nxt)
+    if ((r = putcentral(z, y)) != ZE_OK)
+      ziperr(r, tempzip);
+  if ((s = ftell(y)) == (ulg)-1L)    /* get end of central */
+    ziperr(ZE_TEMP, tempzip);
+  s -= c;                       /* compute length of central */
+  if ((r = putend((int)zcount, s, c, zcomlen, zcomment, y)) != ZE_OK)
+    ziperr(r, tempzip);
+  tempzf = NULL;
+  if (fclose(y))
+    ziperr(ZE_TEMP, tempzip);
+  if ((r = replace(zipfile, tempzip)) != ZE_OK)
+  {
+    zipwarn("new zip file left as: ", tempzip);
+    free((zvoid *)tempzip);
+    tempzip = NULL;
+    ziperr(r, "was replacing the original zip file");
+  }
+  free((zvoid *)tempzip);
+  tempzip = NULL;
+  setfileattr(zipfile, t);
+#ifdef RISCOS
+  /* Set the filetype of the zipfile to &DDC */
+  setfiletype(zipfile,0xDDC);
+#endif
+  free((zvoid *)zipfile);
+  zipfile = NULL;
+
+  /* Done! */
+  RETURN(0);
+}
diff --git a/zipsplit.c b/zipsplit.c
new file mode 100644 (file)
index 0000000..da38705
--- /dev/null
@@ -0,0 +1,804 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2005-Feb-10 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *  zipsplit.c by Mark Adler.
+ */
+#define __ZIPSPLIT_C
+
+#ifndef UTIL
+#define UTIL
+#endif
+#include "zip.h"
+#define DEFCPYRT        /* main module: enable copyright string defines! */
+#include "revision.h"
+#include <signal.h>
+
+#define DEFSIZ 36000L   /* Default split size (change in help() too) */
+#ifdef MSDOS
+#  define NL 2          /* Number of bytes written for a \n */
+#else /* !MSDOS */
+#  define NL 1          /* Number of bytes written for a \n */
+#endif /* ?MSDOS */
+#ifdef RISCOS
+#  define INDEX "zipspl/idx"      /* Name of index file */
+#  define TEMPL_FMT "%%0%dld"
+#  define TEMPL_SIZ 13
+#  define ZPATH_SEP '.'
+#else
+#ifdef QDOS
+#  define ZPATH_SEP '_'
+#  define INDEX "zipsplit_idx"    /* Name of index file */
+#  define TEMPL_FMT "%%0%dld_zip"
+#  define TEMPL_SIZ 17
+#  define exit(p1) QDOSexit()
+#else
+#ifdef VM_CMS
+#  define INDEX "zipsplit.idx"    /* Name of index file */
+#  define TEMPL_FMT "%%0%dld.zip"
+#  define TEMPL_SIZ 21
+#  define ZPATH_SEP '.'
+#else
+#  define INDEX "zipsplit.idx"    /* Name of index file */
+#  define TEMPL_FMT "%%0%dld.zip"
+#  define TEMPL_SIZ 17
+#  define ZPATH_SEP '.'
+#endif /* VM_CMS */
+#endif /* QDOS */
+#endif /* RISCOS */
+
+#ifdef MACOS
+#define ziperr(c, h)    zipspliterr(c, h)
+#define zipwarn(a, b)   zipsplitwarn(a, b)
+void zipsplitwarn(ZCONST char *a, ZCONST char *b);
+void zipspliterr(int c, ZCONST char *h);
+#endif /* MACOS */
+
+/* Local functions */
+local zvoid *talloc OF((extent));
+local void tfree OF((zvoid *));
+local void tfreeall OF((void));
+local void handler OF((int));
+local void license OF((void));
+local void help OF((void));
+local void version_info OF((void));
+local extent simple OF((ulg *, extent, ulg, ulg));
+local int descmp OF((ZCONST zvoid *, ZCONST zvoid *));
+local extent greedy OF((ulg *, extent, ulg, ulg));
+local int retry OF((void));
+int main OF((int, char **));
+
+
+/* Output zip files */
+local char template[TEMPL_SIZ]; /* name template for output files */
+local int zipsmade = 0;         /* number of zip files made */
+local int indexmade = 0;        /* true if index file made */
+local char *path = NULL;        /* space for full name */
+local char *name;               /* where name goes in path[] */
+
+
+/* The talloc() and tree() routines extend malloc() and free() to keep
+   track of all allocated memory.  Then the tfreeall() routine uses this
+   information to free all allocated memory before exiting. */
+
+#define TMAX 6          /* set intelligently by examining the code */
+zvoid *talls[TMAX];     /* malloc'ed pointers to track */
+int talln = 0;          /* number of entries in talls[] */
+
+
+local zvoid *talloc(s)
+extent s;
+/* does a malloc() and saves the pointer to free later (does not check
+   for an overflow of the talls[] list) */
+{
+  zvoid *p;
+
+  if ((p = (zvoid *)malloc(s)) != NULL)
+    talls[talln++] = p;
+  return p;
+}
+
+
+local void tfree(p)
+zvoid *p;
+/* does a free() and also removes the pointer from the talloc() list */
+{
+  int i;
+
+  free(p);
+  i = talln;
+  while (i--)
+    if (talls[i] == p)
+      break;
+  if (i >= 0)
+  {
+    while (++i < talln)
+      talls[i - 1] = talls[i];
+    talln--;
+  }
+}
+
+
+local void tfreeall()
+/* free everything talloc'ed and not tfree'd */
+{
+  while (talln)
+    free(talls[--talln]);
+}
+
+
+void ziperr(c, h)
+int c;                  /* error code from the ZE_ class */
+ZCONST char *h;         /* message about how it happened */
+/* Issue a message for the error, clean up files and memory, and exit. */
+{
+  if (PERR(c))
+    perror("zipsplit error");
+  fprintf(stderr, "zipsplit error: %s (%s)\n", ziperrors[c-1], h);
+  if (indexmade)
+  {
+    strcpy(name, INDEX);
+    destroy(path);
+  }
+  for (; zipsmade; zipsmade--)
+  {
+    sprintf(name, template, zipsmade);
+    destroy(path);
+  }
+  tfreeall();
+  if (zipfile != NULL)
+    free((zvoid *)zipfile);
+  EXIT(c);
+}
+
+
+local void handler(s)
+int s;                  /* signal number (ignored) */
+/* Upon getting a user interrupt, abort cleanly using ziperr(). */
+{
+#ifndef MSDOS
+  putc('\n', stderr);
+#endif /* !MSDOS */
+  ziperr(ZE_ABORT, "aborting");
+  s++;                                  /* keep some compilers happy */
+}
+
+
+void zipwarn(a, b)
+ZCONST char *a, *b;     /* message strings juxtaposed in output */
+/* Print a warning message to stderr and return. */
+{
+  fprintf(stderr, "zipsplit warning: %s%s\n", a, b);
+}
+
+
+local void license()
+/* Print license information to stdout. */
+{
+  extent i;             /* counter for copyright array */
+
+  for (i = 0; i < sizeof(swlicense)/sizeof(char *); i++)
+    puts(swlicense[i]);
+}
+
+
+local void help()
+/* Print help (along with license info) to stdout. */
+{
+  extent i;             /* counter for help array */
+
+  /* help array */
+  static ZCONST char *text[] = {
+"",
+"ZipSplit %s (%s)",
+#ifdef VM_CMS
+"Usage:  zipsplit [-tips] [-n size] [-r room] [-b fm] zipfile",
+#else
+"Usage:  zipsplit [-tips] [-n size] [-r room] [-b path] zipfile",
+#endif
+"  -t   report how many files it will take, but don't make them",
+#ifdef RISCOS
+"  -i   make index (" INDEX ") and count its size against first zip file",
+#else
+"  -i   make index (zipsplit.idx) and count its size against first zip file",
+#endif
+"  -n   make zip files no larger than \"size\" (default = 36000)",
+"  -r   leave room for \"room\" bytes on the first disk (default = 0)",
+#ifdef VM_CMS
+"  -b   use \"fm\" as the filemode for the output zip files",
+#else
+"  -b   use \"path\" for the output zip files",
+#endif
+"  -p   pause between output zip files",
+"  -s   do a sequential split even if it takes more zip files",
+"  -h   show this help    -v   show version info    -L   show software license"
+  };
+
+  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++) {
+    printf(copyright[i], "zipsplit");
+    putchar('\n');
+  }
+  for (i = 0; i < sizeof(text)/sizeof(char *); i++)
+  {
+    printf(text[i], VERSION, REVDATE);
+    putchar('\n');
+  }
+}
+
+
+local void version_info()
+/* Print verbose info about program version and compile time options
+   to stdout. */
+{
+  extent i;             /* counter in text arrays */
+
+  /* Options info array */
+  static ZCONST char *comp_opts[] = {
+#ifdef DEBUG
+    "DEBUG",
+#endif
+    NULL
+  };
+
+  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
+  {
+    printf(copyright[i], "zipsplit");
+    putchar('\n');
+  }
+
+  for (i = 0; i < sizeof(versinfolines)/sizeof(char *); i++)
+  {
+    printf(versinfolines[i], "ZipSplit", VERSION, REVDATE);
+    putchar('\n');
+  }
+
+  version_local();
+
+  puts("ZipSplit special compilation options:");
+  for (i = 0; (int)i < (int)(sizeof(comp_opts)/sizeof(char *) - 1); i++)
+  {
+    printf("\t%s\n",comp_opts[i]);
+  }
+  if (i == 0)
+      puts("\t[none]");
+}
+
+
+local extent simple(a, n, c, d)
+ulg *a;         /* items to put in bins, return value: destination bins */
+extent n;       /* number of items */
+ulg c;          /* capacity of each bin */
+ulg d;          /* amount to deduct from first bin */
+/* Return the number of bins of capacity c that are needed to contain the
+   integers in a[0..n-1] placed sequentially into the bins.  The value d
+   is deducted initially from the first bin (space for index).  The entries
+   in a[] are replaced by the destination bins. */
+{
+  extent k;     /* current bin number */
+  ulg t;        /* space used in current bin */
+
+  t = k = 0;
+  while (n--)
+  {
+    if (*a + t > c - (k == 0 ? d : 0))
+    {
+      k++;
+      t = 0;
+    }
+    t += *a;
+    *(ulg huge *)a++ = k;
+  }
+  return k + 1;
+}
+
+
+local int descmp(a, b)
+ZCONST zvoid *a, *b;          /* pointers to pointers to ulg's to compare */
+/* Used by qsort() in greedy() to do a descending sort. */
+{
+  return **(ulg **)a < **(ulg **)b ? 1 : (**(ulg **)a > **(ulg **)b ? -1 : 0);
+}
+
+
+local extent greedy(a, n, c, d)
+ulg *a;         /* items to put in bins, return value: destination bins */
+extent n;       /* number of items */
+ulg c;          /* capacity of each bin */
+ulg d;          /* amount to deduct from first bin */
+/* Return the number of bins of capacity c that are needed to contain the
+   items with sizes a[0..n-1] placed non-sequentially into the bins.  The
+   value d is deducted initially from the first bin (space for index).
+   The entries in a[] are replaced by the destination bins. */
+{
+  ulg *b;       /* space left in each bin (malloc'ed for each m) */
+  ulg *e;       /* copy of argument a[] (malloc'ed) */
+  extent i;     /* steps through items */
+  extent j;     /* steps through bins */
+  extent k;     /* best bin to put current item in */
+  extent m;     /* current number of bins */
+  ulg **s;      /* pointers to e[], sorted descending (malloc'ed) */
+  ulg t;        /* space left in best bin (index k) */
+
+  /* Algorithm:
+     1. Copy a[] to e[] and sort pointers to e[0..n-1] (in s[]), in
+        descending order.
+     2. Compute total of s[] and set m to the smallest number of bins of
+        capacity c that can hold the total.
+     3. Allocate m bins.
+     4. For each item in s[], starting with the largest, put it in the
+        bin with the smallest current capacity greater than or equal to the
+        item's size.  If no bin has enough room, increment m and go to step 4.
+     5. Else, all items ended up in a bin--return m.
+  */
+
+  /* Copy a[] to e[], put pointers to e[] in s[], and sort s[].  Also compute
+     the initial number of bins (minus 1). */
+  if ((e = (ulg *)malloc(n * sizeof(ulg))) == NULL ||
+      (s = (ulg **)malloc(n * sizeof(ulg *))) == NULL)
+  {
+    if (e != NULL)
+      free((zvoid *)e);
+    ziperr(ZE_MEM, "was trying a smart split");
+    return 0;                           /* only to make compiler happy */
+  }
+  memcpy((char *)e, (char *)a, n * sizeof(ulg));
+  for (t = i = 0; i < n; i++)
+    t += *(s[i] = e + i);
+  m = (extent)((t + c - 1) / c) - 1;    /* pre-decrement for loop */
+  qsort((char *)s, n, sizeof(ulg *), descmp);
+
+  /* Stuff bins until successful */
+  do {
+    /* Increment the number of bins, allocate and initialize bins */
+    if ((b = (ulg *)malloc(++m * sizeof(ulg))) == NULL)
+    {
+      free((zvoid *)s);
+      free((zvoid *)e);
+      ziperr(ZE_MEM, "was trying a smart split");
+    }
+    b[0] = c - d;                       /* leave space in first bin */
+    for (j = 1; j < m; j++)
+      b[j] = c;
+
+    /* Fill the bins greedily */
+    for (i = 0; i < n; i++)
+    {
+      /* Find smallest bin that will hold item i (size s[i]) */
+      t = c + 1;
+      for (k = j = 0; j < m; j++)
+        if (*s[i] <= b[j] && b[j] < t)
+          t = b[k = j];
+
+      /* If no bins big enough for *s[i], try next m */
+      if (t == c + 1)
+        break;
+
+      /* Diminish that bin and save where it goes */
+      b[k] -= *s[i];
+      a[(int)((ulg huge *)(s[i]) - (ulg huge *)e)] = k;
+    }
+
+    /* Clean up */
+    free((zvoid *)b);
+
+    /* Do until all items put in a bin */
+  } while (i < n);
+
+  /* Done--clean up and return the number of bins needed */
+  free((zvoid *)s);
+  free((zvoid *)e);
+  return m;
+}
+
+
+local int retry()
+{
+  char m[10];
+  fputs("Error writing to disk--redo entire disk? ", stderr);
+  fgets(m, 10, stdin);
+  return *m == 'y' || *m == 'Y';
+}
+
+
+#ifndef USE_ZIPSPLITMAIN
+int main(argc, argv)
+#else
+int zipsplitmain(argc, argv)
+#endif
+
+int argc;               /* number of tokens in command line */
+char **argv;            /* command line tokens */
+/* Split a zip file into several zip files less than a specified size.  See
+   the command help in help() above. */
+{
+  ulg *a;               /* malloc'ed list of sizes, dest bins */
+  extent *b;            /* heads of bin linked lists (malloc'ed) */
+  ulg c;                /* bin capacity, start of central directory */
+  int d;                /* if true, just report the number of disks */
+  FILE *e;              /* input zip file */
+  FILE *f;              /* output index and zip files */
+  extent g;             /* number of bins from greedy(), entry to write */
+  int h;                /* how to split--true means simple split, counter */
+  ulg i = 0;            /* size of index file plus room to leave */
+  extent j;             /* steps through zip entries, bins */
+  int k;                /* next argument type */
+  extent *n = NULL;     /* next item in bin list (heads in b) */
+  ulg *p;               /* malloc'ed list of sizes, dest bins for greedy() */
+  char *q;              /* steps through option characters */
+  int r;                /* temporary variable, counter */
+  extent s;             /* number of bins needed */
+  ulg t;                /* total of sizes, end of central directory */
+  int u;                /* flag to wait for user on output files */
+  struct zlist far **w; /* malloc'ed table for zfiles linked list */
+  int x;                /* if true, make an index file */
+  struct zlist far *z;  /* steps through zfiles linked list */
+#ifdef AMIGA
+  char tailchar;         /* temporary variable used in name generation below */
+#endif
+
+#ifdef THEOS
+  setlocale(LC_CTYPE, "I");
+#endif
+
+  /* If no args, show help */
+  if (argc == 1)
+  {
+    help();
+    EXIT(0);
+  }
+
+  init_upper();           /* build case map table */
+
+  /* Go through args */
+  signal(SIGINT, handler);
+#ifdef SIGTERM                 /* Amiga has no SIGTERM */
+  signal(SIGTERM, handler);
+#endif
+  k = h = x = d = u = 0;
+  c = DEFSIZ;
+  for (r = 1; r < argc; r++)
+    if (*argv[r] == '-')
+    {
+      if (argv[r][1])
+        for (q = argv[r]+1; *q; q++)
+          switch (*q)
+          {
+            case 'b':   /* Specify path for output files */
+              if (k)
+                ziperr(ZE_PARMS, "options are separate and precede zip file");
+              else
+                k = 1;          /* Next non-option is path */
+              break;
+            case 'h':   /* Show help */
+              help();  EXIT(0);
+            case 'i':   /* Make an index file */
+              x = 1;
+              break;
+            case 'l': case 'L':  /* Show copyright and disclaimer */
+              license();  EXIT(0);
+            case 'n':   /* Specify maximum size of resulting zip files */
+              if (k)
+                ziperr(ZE_PARMS, "options are separate and precede zip file");
+              else
+                k = 2;          /* Next non-option is size */
+              break;
+            case 'p':
+              u = 1;
+              break;
+            case 'r':
+              if (k)
+                ziperr(ZE_PARMS, "options are separate and precede zip file");
+              else
+                k = 3;          /* Next non-option is room to leave */
+              break;
+            case 's':
+              h = 1;    /* Only try simple */
+              break;
+            case 't':   /* Just report number of disks */
+              d = 1;
+              break;
+            case 'v':   /* Show version info */
+              version_info();  EXIT(0);
+            default:
+              ziperr(ZE_PARMS, "Use option -h for help.");
+          }
+      else
+        ziperr(ZE_PARMS, "zip file cannot be stdin");
+    }
+    else
+      switch (k)
+      {
+        case 0:
+          if (zipfile == NULL)
+          {
+            if ((zipfile = ziptyp(argv[r])) == NULL)
+              ziperr(ZE_MEM, "was processing arguments");
+          }
+          else
+            ziperr(ZE_PARMS, "can only specify one zip file");
+          break;
+        case 1:
+          tempath = argv[r];
+          k = 0;
+          break;
+        case 2:
+          if ((c = (ulg)atol(argv[r])) < 100)   /* 100 is smallest zip file */
+            ziperr(ZE_PARMS, "invalid size given. Use option -h for help.");
+          k = 0;
+          break;
+        default:        /* k must be 3 */
+          i = (ulg)atol(argv[r]);
+          k = 0;
+          break;
+      }
+  if (zipfile == NULL)
+    ziperr(ZE_PARMS, "need to specify zip file");
+
+
+  /* Read zip file */
+  if ((r = readzipfile()) != ZE_OK)
+    ziperr(r, zipfile);
+  if (zfiles == NULL)
+    ziperr(ZE_NAME, zipfile);
+
+  /* Make a list of sizes and check against capacity.  Also compute the
+     size of the index file. */
+  c -= ENDHEAD + 4;                     /* subtract overhead/zipfile */
+  if ((a = (ulg *)talloc(zcount * sizeof(ulg))) == NULL ||
+      (w = (struct zlist far **)talloc(zcount * sizeof(struct zlist far *))) ==
+       NULL)
+  {
+    ziperr(ZE_MEM, "was computing split");
+    return 1;
+  }
+  t = 0;
+  for (j = 0, z = zfiles; j < zcount; j++, z = z->nxt)
+  {
+    w[j] = z;
+    if (x)
+      i += z->nam + 6 + NL;
+    t += a[j] = 8 + LOCHEAD + CENHEAD +
+           2 * (ulg)z->nam + 2 * (ulg)z->ext + z->com + z->siz;
+    if (a[j] > c)
+      ziperr(ZE_BIG, z->zname);
+  }
+
+  /* Decide on split to use, report number of files */
+  if (h)
+    s = simple(a, zcount, c, i);
+  else
+  {
+    if ((p = (ulg *)talloc(zcount * sizeof(ulg))) == NULL)
+      ziperr(ZE_MEM, "was computing split");
+    memcpy((char *)p, (char *)a, zcount * sizeof(ulg));
+    s = simple(a, zcount, c, i);
+    g = greedy(p, zcount, c, i);
+    if (s <= g)
+      tfree((zvoid *)p);
+    else
+    {
+      tfree((zvoid *)a);
+      a = p;
+      s = g;
+    }
+  }
+  printf("%ld zip files w%s be made (%ld%% efficiency)\n",
+         (ulg)s, d ? "ould" : "ill", ((200 * ((t + c - 1)/c)) / s + 1) >> 1);
+  if (d)
+  {
+    tfreeall();
+    free((zvoid *)zipfile);
+    zipfile = NULL;
+    EXIT(0);
+  }
+
+  /* Set up path for output files */
+  /* Point "name" past the path, where the filename should go */
+  if ((path = (char *)talloc(tempath == NULL ? 13 : strlen(tempath) + 14)) ==
+      NULL)
+    ziperr(ZE_MEM, "was making output file names");
+  if (tempath == NULL)
+     name = path;
+  else
+  {
+#ifndef VM_CMS
+    /* Copy the output path to the target */
+    strcpy(path, tempath);
+#endif
+#ifdef AMIGA
+    tailchar = path[strlen(path) - 1];  /* last character */
+    if (path[0] && (tailchar != '/') && (tailchar != ':'))
+      strcat(path, "/");
+#else
+#  ifdef RISCOS
+    if (path[0] && path[strlen(path) - 1] != '.')
+      strcat(path, ".");
+#  else /* !RISCOS */
+#   ifdef QDOS
+    if (path[0] && path[strlen(path) - 1] != '_')
+      strcat(path, "_");
+#   else
+    if (path[0] && path[strlen(path) - 1] != '/')
+      strcat(path, "/");
+#   endif
+#  endif
+#endif /* ?AMIGA */
+    name = path + strlen(path);
+  }
+
+  /* Make linked lists of results */
+  if ((b = (extent *)talloc(s * sizeof(extent))) == NULL ||
+      (n = (extent *)talloc(zcount * sizeof(extent))) == NULL)
+    ziperr(ZE_MEM, "was computing split");
+  for (j = 0; j < s; j++)
+    b[j] = (extent)-1;
+  j = zcount;
+  while (j--)
+  {
+    g = (extent)a[j];
+    n[j] = b[g];
+    b[g] = j;
+  }
+
+  /* Make a name template for the zip files that is eight or less characters
+     before the .zip, and that will not overwrite the original zip file. */
+  for (k = 1, j = s; j >= 10; j /= 10)
+    k++;
+  if (k > 7)
+    ziperr(ZE_PARMS, "way too many zip files must be made");
+/*
+ * XXX, ugly ....
+ */
+/* Find the final "path" separator character */
+#ifdef QDOS
+  q = LastDir(zipfile);
+#else
+#ifdef VMS
+  if ((q = strrchr(zipfile, ']')) != NULL)
+#else
+#ifdef AMIGA
+  if (((q = strrchr(zipfile, '/')) != NULL)
+                       || ((q = strrchr(zipfile, ':'))) != NULL)
+#else
+#ifdef RISCOS
+  if ((q = strrchr(zipfile, '.')) != NULL)
+#else
+#ifdef MVS
+  if ((q = strrchr(zipfile, '.')) != NULL)
+#else
+  if ((q = strrchr(zipfile, '/')) != NULL)
+#endif /* MVS */
+#endif /* RISCOS */
+#endif /* AMIGA */
+#endif /* VMS */
+    q++;
+  else
+    q = zipfile;
+#endif /* QDOS */
+
+  r = 0;
+  while ((g = *q++) != '\0' && g != ZPATH_SEP && r < 8 - k)
+    template[r++] = (char)g;
+  if (r == 0)
+    template[r++] = '_';
+  else if (g >= '0' && g <= '9')
+    template[r - 1] = (char)(template[r - 1] == '_' ? '-' : '_');
+  sprintf(template + r, TEMPL_FMT, k);
+#ifdef VM_CMS
+  /* For CMS, add the "path" as the filemode at the end */
+  if (tempath)
+  {
+     strcat(template,".");
+     strcat(template,tempath);
+  }
+#endif
+
+  /* Make the zip files from the linked lists of entry numbers */
+  if ((e = fopen(zipfile, FOPR)) == NULL)
+    ziperr(ZE_NAME, zipfile);
+  free((zvoid *)zipfile);
+  zipfile = NULL;
+  for (j = 0; j < s; j++)
+  {
+    /* jump here on a disk retry */
+   redobin:
+
+    /* prompt if requested */
+    if (u)
+    {
+      char m[10];
+      fprintf(stderr, "Insert disk #%ld of %ld and hit return: ",
+              (ulg)j + 1, (ulg)s);
+      fgets(m, 10, stdin);
+    }
+
+    /* write index file on first disk if requested */
+    if (j == 0 && x)
+    {
+      strcpy(name, INDEX);
+      printf("creating: %s\n", path);
+      indexmade = 1;
+      if ((f = fopen(path, "w")) == NULL)
+      {
+        if (u && retry()) goto redobin;
+        ziperr(ZE_CREAT, path);
+      }
+      for (j = 0; j < zcount; j++)
+        fprintf(f, "%5ld %s\n", a[j] + 1, w[j]->zname);
+      if ((j = ferror(f)) != 0 || fclose(f))
+      {
+        if (j)
+          fclose(f);
+        if (u && retry()) goto redobin;
+        ziperr(ZE_WRITE, path);
+      }
+    }
+
+    /* create output zip file j */
+    sprintf(name, template, j + 1L);
+    printf("creating: %s\n", path);
+    zipsmade = j + 1;
+    if ((f = fopen(path, FOPW)) == NULL)
+    {
+      if (u && retry()) goto redobin;
+      ziperr(ZE_CREAT, path);
+    }
+    tempzn = 0;
+
+    /* write local headers and copy compressed data */
+    for (g = b[j]; g != (extent)-1; g = (extent)n[g])
+    {
+      if (fseek(e, w[g]->off, SEEK_SET))
+        ziperr(ferror(e) ? ZE_READ : ZE_EOF, zipfile);
+      if ((r = zipcopy(w[g], e, f)) != ZE_OK)
+      {
+        if (r == ZE_TEMP)
+        {
+          if (u && retry()) goto redobin;
+          ziperr(ZE_WRITE, path);
+        }
+        else
+          ziperr(r, zipfile);
+      }
+    }
+
+    /* write central headers */
+    if ((c = ftell(f)) == (ulg)(-1L))
+    {
+      if (u && retry()) goto redobin;
+      ziperr(ZE_WRITE, path);
+    }
+    for (g = b[j], k = 0; g != (extent)-1; g = n[g], k++)
+      if ((r = putcentral(w[g], f)) != ZE_OK)
+      {
+        if (u && retry()) goto redobin;
+        ziperr(ZE_WRITE, path);
+      }
+
+    /* write end-of-central header */
+    if ((t = ftell(f)) == (ulg)(-1L) ||
+        (r = putend(k, t - c, c, (extent)0, (char *)NULL, f)) != ZE_OK ||
+        ferror(f) || fclose(f))
+    {
+      if (u && retry()) goto redobin;
+      ziperr(ZE_WRITE, path);
+    }
+#ifdef RISCOS
+    /* Set the filetype to &DDC */
+    setfiletype(path,0xDDC);
+#endif
+  }
+  fclose(e);
+
+  /* Done! */
+  if (u)
+    fputs("Done.\n", stderr);
+  tfreeall();
+
+  RETURN(0);
+}
diff --git a/zipup.c b/zipup.c
new file mode 100644 (file)
index 0000000..c6883f7
--- /dev/null
+++ b/zipup.c
@@ -0,0 +1,1186 @@
+/*
+  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
+
+  See the accompanying file LICENSE, version 2004-May-22 or later
+  (the contents of which are also included in zip.h) for terms of use.
+  If, for some reason, both of these files are missing, the Info-ZIP license
+  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/*
+ *  zipup.c by Mark Adler and Jean-loup Gailly.
+ */
+#define __ZIPUP_C
+
+#include <ctype.h>
+#include "zip.h"
+
+#ifndef UTIL            /* This module contains no code for Zip Utilities */
+
+#include "revision.h"
+#include "crypt.h"
+#ifdef USE_ZLIB
+#  include "zlib.h"
+#endif
+
+#ifdef OS2
+#  include "os2/os2zip.h"
+#endif
+
+#if defined(MMAP)
+#  include <sys/mman.h>
+#  ifndef PAGESIZE   /* used to be SYSV, what about pagesize on SVR3 ? */
+#    define PAGESIZE getpagesize()
+#  endif
+#  if defined(NO_VALLOC) && !defined(valloc)
+#    define valloc malloc
+#  endif
+#endif
+
+/* Use the raw functions for MSDOS and Unix to save on buffer space.
+   They're not used for VMS since it doesn't work (raw is weird on VMS).
+ */
+
+#ifdef AMIGA
+#  include "amiga/zipup.h"
+#endif /* AMIGA */
+
+#ifdef AOSVS
+#  include "aosvs/zipup.h"
+#endif /* AOSVS */
+
+#ifdef ATARI
+#  include "atari/zipup.h"
+#endif
+
+#ifdef __BEOS__
+#  include "beos/zipup.h"
+#endif
+
+#ifdef __ATHEOS__
+#  include "atheos/zipup.h"
+#endif /* __ATHEOS__ */
+
+#ifdef __human68k__
+#  include "human68k/zipup.h"
+#endif /* __human68k__ */
+
+#ifdef MACOS
+#  include "macos/zipup.h"
+#endif
+
+#ifdef DOS
+#  include "msdos/zipup.h"
+#endif /* DOS */
+
+#ifdef OS2
+#  include "os2/zipup.h"
+#endif /* OS2 */
+
+#ifdef RISCOS
+#  include "acorn/zipup.h"
+#endif
+
+#ifdef TOPS20
+#  include "tops20/zipup.h"
+#endif
+
+#ifdef UNIX
+#  include "unix/zipup.h"
+#endif
+
+#ifdef CMS_MVS
+#  include "zipup.h"
+#endif /* CMS_MVS */
+
+#ifdef TANDEM
+#  include "zipup.h"
+#endif /* TANDEM */
+
+#ifdef VMS
+#  include "vms/zipup.h"
+#endif /* VMS */
+
+#ifdef QDOS
+#  include "qdos/zipup.h"
+#endif /* QDOS */
+
+#ifdef WIN32
+#  include "win32/zipup.h"
+#endif
+
+#ifdef THEOS
+#  include "theos/zipup.h"
+#endif
+
+/* Local functions */
+#ifndef RISCOS
+   local int suffixes OF((char *, char *));
+#else
+   local int filetypes OF((char *, char *));
+#endif
+local unsigned file_read OF((char *buf, unsigned size));
+#ifdef USE_ZLIB
+  local int zl_deflate_init OF((int pack_level));
+#else /* !USE_ZLIB */
+# ifdef ZP_NEED_MEMCOMPR
+    local unsigned mem_read OF((char *buf, unsigned size));
+# endif
+#endif /* ?USE_ZLIB */
+local ulg filecompress OF((struct zlist far *z_entry, FILE *zipfile,
+                           int *cmpr_method));
+
+/* Deflate "internal" global data (currently not in zip.h) */
+#if defined(MMAP) || defined(BIG_MEM)
+# ifdef USE_ZLIB
+    local uch *window = NULL;   /* Used to read all input file at once */
+    local ulg window_size;      /* size of said window */
+# else /* !USE_ZLIB */
+    extern uch *window;         /* Used to read all input file at once */
+#endif /* ?USE_ZLIB */
+#endif /* MMAP || BIG_MEM */
+#ifndef USE_ZLIB
+  extern ulg window_size;       /* size of said window */
+
+  unsigned (*read_buf) OF((char *buf, unsigned size)) = file_read;
+  /* Current input function. Set to mem_read for in-memory compression */
+#endif /* !USE_ZLIB */
+
+
+/* Local data */
+local ulg crc;          /* crc on uncompressed file data */
+local ftype ifile;      /* file to compress */
+#if defined(MMAP) || defined(BIG_MEM)
+  local ulg remain;
+  /* window bytes not yet processed.
+   *  special value "(ulg)-1L" reserved to signal normal reads.
+   */
+#endif /* MMAP || BIG_MEM */
+#ifdef USE_ZLIB
+  local int deflInit;           /* flag: zlib deflate is initialized */
+  local z_stream zstrm;         /* zlib's data interface structure */
+  local char *f_ibuf = NULL;
+  local char *f_obuf = NULL;
+#else /* !USE_ZLIB */
+  local FILE *zfile;            /* output zip file */
+  local char file_outbuf[1024]; /* output buffer for compression to file */
+
+# ifdef ZP_NEED_MEMCOMPR
+    local char *in_buf;
+    /* Current input buffer, in_buf is used only for in-memory compression. */
+    local unsigned in_offset;
+    /* Current offset in input buffer. in_offset is used only for in-memory
+     * compression. On 16 bit machines, the buffer is limited to 64K.
+     */
+    local unsigned in_size;
+    /* size of current input buffer */
+# endif /* ZP_NEED_MEMCOMPR */
+#endif /* ?USE_ZLIB */
+
+#ifdef DEBUG
+  ulg isize;           /* input file size. global only for debugging */
+#else /* !DEBUG */
+  local ulg isize;     /* input file size. */
+#endif /* ?DEBUG */
+
+
+int percent(n, m)
+ulg n;
+ulg m;               /* n is the original size, m is the new size */
+/* Return the percentage compression from n to m using only integer
+   operations */
+{
+  if (n > 0xffffffL)            /* If n >= 16M */
+  {                             /*  then divide n and m by 256 */
+    n += 0x80;  n >>= 8;
+    m += 0x80;  m >>= 8;
+  }
+  return n > m ? (int)(1 + (200 * (n - m)/n)) / 2 : 0;
+}
+
+#ifndef RISCOS
+
+local int suffixes(a, s)
+char *a;                /* name to check suffix of */
+char *s;                /* list of suffixes separated by : or ; */
+/* Return true if a ends in any of the suffixes in the list s. */
+{
+  int m;                /* true if suffix matches so far */
+  char *p;              /* pointer into special */
+  char *q;              /* pointer into name a */
+
+#ifdef QDOS
+  short dlen = devlen(a);
+  a = a + dlen;
+#endif
+
+  m = 1;
+#ifdef VMS
+  if( (q = strrchr(a,';')) != NULL )    /* Cut out VMS file version */
+    --q;
+  else
+    q = a + strlen(a) - 1;
+#else /* !VMS */
+  q = a + strlen(a) - 1;
+#endif /* ?VMS */
+  for (p = s + strlen(s) - 1; p >= s; p--)
+    if (*p == ':' || *p == ';')
+    {
+      if (m)
+        return 1;
+      else
+      {
+        m = 1;
+#ifdef VMS
+        if( (q = strrchr(a,';')) != NULL )      /* Cut out VMS file version */
+          --q;
+        else
+          q = a + strlen(a) - 1;
+#else /* !VMS */
+        q = a + strlen(a) - 1;
+#endif /* ?VMS */
+      }
+    }
+    else
+    {
+      m = m && q >= a && case_map(*p) == case_map(*q);
+      q--;
+    }
+  return m;
+}
+
+#else /* RISCOS */
+
+local int filetypes(a, s)
+char *a;                /* extra field of file to check filetype of */
+char *s;                /* list of filetypes separated by : or ; */
+/* Return true if a is any of the filetypes in the list s. */
+{
+ char *p;              /* pointer into special */
+ char typestr[4];     /* filetype hex string taken from a */
+
+ if ((((unsigned*)a)[2] & 0xFFF00000) != 0xFFF00000) {
+ /* The file is not filestamped, always try to compress it */
+   return 0;
+ }
+
+ sprintf(typestr,"%.3X",(((unsigned*)a)[2] & 0x000FFF00) >> 8);
+
+ for (p=s;p<=s+strlen(s)-3;p+=3) { /* p+=3 to skip 3 hex type */
+   while (*p==':' || *p==';')
+     p++;
+
+   if (typestr[0]==toupper(p[0]) && typestr[1]==toupper(p[1]) && typestr[2]==toupper(p[2]))
+     return 1;
+ }
+ return 0;
+}
+#endif /* ?RISCOS */
+
+
+
+/* Note: a zip "entry" includes a local header (which includes the file
+   name), an encryption header if encrypting, the compressed data
+   and possibly an extended local header. */
+
+int zipup(z, y)
+struct zlist far *z;    /* zip entry to compress */
+FILE *y;                /* output file */
+/* Compress the file z->name into the zip entry described by *z and write
+   it to the file *y. Encrypt if requested.  Return an error code in the
+   ZE_ class.  Also, update tempzn by the number of bytes written. */
+{
+  iztimes f_utim;       /* UNIX GMT timestamps, filled by filetime() */
+  ulg tim;              /* time returned by filetime() */
+  ulg a = 0L;           /* attributes returned by filetime() */
+  char *b;              /* malloc'ed file buffer */
+  extent k = 0;         /* result of zread */
+  int l = 0;            /* true if this file is a symbolic link */
+  int m;                /* method for this entry */
+  ulg o, p;             /* offsets in zip file */
+  long q = -3L;         /* size returned by filetime */
+  int r;                /* temporary variable */
+  ulg s = 0L;           /* size of compressed data */
+  int isdir;            /* set for a directory name */
+  int set_type = 0;     /* set if file type (ascii/binary) unknown */
+
+  z->nam = strlen(z->iname);
+  isdir = z->iname[z->nam-1] == (char)0x2f; /* ascii[(unsigned)('/')] */
+
+  if ((tim = filetime(z->name, &a, &q, &f_utim)) == 0 || q == -3L)
+    return ZE_OPEN;
+
+  /* q is set to -1 if the input file is a device, -2 for a volume label */
+  if (q == -2L) {
+     isdir = 1;
+     q = 0;
+  } else if (isdir != ((a & MSDOS_DIR_ATTR) != 0)) {
+     /* don't overwrite a directory with a file and vice-versa */
+     return ZE_MISS;
+  }
+  z->att = (ush)UNKNOWN; /* will be changed later */
+  z->atx = 0; /* may be changed by set_extra_field() */
+
+  /* Free the old extra fields which are probably obsolete */
+  if (z->ext) {
+    free((zvoid *)(z->extra));
+  }
+  if (z->cext && z->extra != z->cextra) {
+    free((zvoid *)(z->cextra));
+  }
+  z->extra = z->cextra = NULL;
+  z->ext = z->cext = 0;
+
+#if defined(MMAP) || defined(BIG_MEM)
+  remain = (ulg)-1L; /* changed only for MMAP or BIG_MEM */
+#endif /* MMAP || BIG_MEM */
+#if (!defined(USE_ZLIB) || defined(MMAP) || defined(BIG_MEM))
+  window_size = 0L;
+#endif /* !USE_ZLIB || MMAP || BIG_MEM */
+
+  /* Select method based on the suffix and the global method */
+#ifndef RISCOS
+  m = special != NULL && suffixes(z->name, special) ? STORE : method;
+#else /* RISCOS  must set m after setting extra field */
+  m = method;
+#endif /* ?RISCOS */
+
+  /* Open file to zip up unless it is stdin */
+  if (strcmp(z->name, "-") == 0)
+  {
+    ifile = (ftype)zstdin;
+#if defined(MSDOS) || defined(__human68k__)
+    if (isatty(zstdin) == 0)  /* keep default mode if stdin is a terminal */
+      setmode(zstdin, O_BINARY);
+#endif
+    z->tim = tim;
+  }
+  else
+  {
+#if !(defined(VMS) && defined(VMS_PK_EXTRA))
+    if (extra_fields) {
+      /* create extra field and change z->att and z->atx if desired */
+      set_extra_field(z, &f_utim);
+#ifdef QLZIP
+      if(qlflag)
+          a |= (S_IXUSR) << 16;   /* Cross compilers don't set this */
+#endif
+#ifdef RISCOS
+      m = special != NULL && filetypes(z->extra, special) ? STORE : method;
+#endif /* RISCOS */
+    }
+#endif /* !(VMS && VMS_PK_EXTRA) */
+    l = issymlnk(a);
+    if (l) {
+      ifile = fbad;
+      m = STORE;
+    }
+    else if (isdir) { /* directory */
+      ifile = fbad;
+      m = STORE;
+      q = 0;
+    }
+#ifdef THEOS
+    else if (((a >> 16) & S_IFMT) == S_IFLIB) {   /* library */
+      ifile = fbad;
+      m = STORE;
+      q = 0;
+    }
+#endif
+    else {
+#ifdef CMS_MVS
+      if (bflag) {
+        if ((ifile = zopen(z->name, fhowb)) == fbad)
+           return ZE_OPEN;
+      }
+      else
+#endif /* CMS_MVS */
+      if ((ifile = zopen(z->name, fhow)) == fbad)
+         return ZE_OPEN;
+    }
+
+    z->tim = tim;
+
+#if defined(VMS) && defined(VMS_PK_EXTRA)
+    /* vms_get_attributes must be called after vms_open() */
+    if (extra_fields) {
+      /* create extra field and change z->att and z->atx if desired */
+      vms_get_attributes(ifile, z, &f_utim);
+    }
+#endif /* VMS && VMS_PK_EXTRA */
+
+#if defined(MMAP) || defined(BIG_MEM)
+    /* Map ordinary files but not devices. This code should go in fileio.c */
+    if (!translate_eol && m != STORE && q != -1L && (ulg)q > 0 &&
+        (ulg)q + MIN_LOOKAHEAD > (ulg)q) {
+# ifdef MMAP
+      /* Map the whole input file in memory */
+      if (window != NULL)
+        free(window);  /* window can't be a mapped file here */
+      window_size = (ulg)q + MIN_LOOKAHEAD;
+      remain = window_size & (PAGESIZE-1);
+      /* If we can't touch the page beyond the end of file, we must
+       * allocate an extra page.
+       */
+      if (remain > MIN_LOOKAHEAD) {
+        window = (uch*)mmap(0, window_size, PROT_READ, MAP_PRIVATE, ifile, 0);
+      } else {
+        window = (uch*)valloc(window_size - remain + PAGESIZE);
+        if (window != NULL) {
+          window = (uch*)mmap((char*)window, window_size - remain, PROT_READ,
+                        MAP_PRIVATE | MAP_FIXED, ifile, 0);
+        } else {
+          window = (uch*)(-1);
+        }
+      }
+      if (window == (uch*)(-1)) {
+        Trace((mesg, " mmap failure on %s\n", z->name));
+        window = NULL;
+        window_size = 0L;
+        remain = (ulg)-1L;
+      } else {
+        remain = (ulg)q;
+      }
+# else /* !MMAP, must be BIG_MEM */
+      /* Read the whole input file at once */
+      window_size = (ulg)q + MIN_LOOKAHEAD;
+      window = window ? (uch*) realloc(window, (unsigned)window_size)
+                      : (uch*) malloc((unsigned)window_size);
+      /* Just use normal code if big malloc or realloc fails: */
+      if (window != NULL) {
+        remain = (ulg)zread(ifile, (char*)window, q+1);
+        if (remain != (ulg)q) {
+          fprintf(mesg, " q=%lu, remain=%lu ", (ulg)q, remain);
+          error("can't read whole file at once");
+        }
+      } else {
+        window_size = 0L;
+      }
+# endif /* ?MMAP */
+    }
+#endif /* MMAP || BIG_MEM */
+
+  } /* strcmp(z->name, "-") == 0 */
+
+  if (q == 0)
+    m = STORE;
+  if (m == BEST)
+    m = DEFLATE;
+
+  /* Do not create STORED files with extended local headers if the
+   * input size is not known, because such files could not be extracted.
+   * So if the zip file is not seekable and the input file is not
+   * on disk, obey the -0 option by forcing deflation with stored block.
+   * Note however that using "zip -0" as filter is not very useful...
+   * ??? to be done.
+   */
+
+  /* Fill in header information and write local header to zip file.
+   * This header will later be re-written since compressed length and
+   * crc are not yet known.
+   */
+
+  /* (Assume ext, cext, com, and zname already filled in.) */
+#if defined(OS2) || defined(WIN32)
+  z->vem = (ush)(z->dosflag ? (dosify ? 20 : /* Made under MSDOS by PKZIP 2.0 */
+                               (0 + Z_MAJORVER * 10 + Z_MINORVER))
+                 : OS_CODE + Z_MAJORVER * 10 + Z_MINORVER);
+  /* For a FAT file system, we cheat and pretend that the file
+   * was not made on OS2/WIN32 but under DOS. unzip is confused otherwise.
+   */
+#else /* !(OS2 || WIN32) */
+  z->vem = (ush)(dosify ? 20 : OS_CODE + Z_MAJORVER * 10 + Z_MINORVER);
+#endif /* ?(OS2 || WIN32) */
+
+  z->ver = (ush)(m == STORE ? 10 : 20); /* Need PKUNZIP 2.0 except for store */
+  z->crc = 0;  /* to be updated later */
+  /* Assume first that we will need an extended local header: */
+  z->flg = 8;  /* to be updated later */
+#if CRYPT
+  if (key != NULL) {
+    z->flg |= 1;
+    /* Since we do not yet know the crc here, we pretend that the crc
+     * is the modification time:
+     */
+    z->crc = z->tim << 16;
+  }
+#endif /* CRYPT */
+  z->lflg = z->flg;
+  z->how = (ush)m;                              /* may be changed later  */
+  z->siz = (ulg)(m == STORE && q >= 0 ? q : 0); /* will be changed later */
+  z->len = (ulg)(q != -1L ? q : 0);             /* may be changed later  */
+  z->dsk = 0;
+  if (z->att == (ush)UNKNOWN) {
+      z->att = BINARY;                    /* set sensible value in header */
+      set_type = 1;
+  }
+  /* Attributes from filetime(), flag bits from set_extra_field(): */
+#if defined(DOS) || defined(OS2) || defined(WIN32)
+  z->atx = z->dosflag ? a & 0xff : a | (z->atx & 0x0000ff00);
+#else
+  z->atx = dosify ? a & 0xff : a | (z->atx & 0x0000ff00);
+#endif /* DOS || OS2 || WIN32 */
+  z->off = tempzn;
+  if ((r = putlocal(z, y)) != ZE_OK) {
+    if (ifile != fbad)
+      zclose(ifile);
+    return r;
+  }
+  tempzn += 4 + LOCHEAD + z->nam + z->ext;
+
+#if CRYPT
+  if (key != NULL) {
+    crypthead(key, z->crc, y);
+    z->siz += RAND_HEAD_LEN;  /* to be updated later */
+    tempzn += RAND_HEAD_LEN;
+  }
+#endif /* CRYPT */
+  if (ferror(y)) {
+    if (ifile != fbad)
+      zclose(ifile);
+    ZIPERR(ZE_WRITE, "unexpected error on zip file");
+  }
+
+  o = ftell(y); /* for debugging only, ftell can fail on pipes */
+  if (ferror(y))
+    clearerr(y);
+
+  /* Write stored or deflated file to zip file */
+  isize = 0L;
+  crc = CRCVAL_INITIAL;
+
+  if (m == DEFLATE) {
+    if (set_type) z->att = (ush)UNKNOWN; /* is finally set in filecompress() */
+    s = filecompress(z, y, &m);
+#ifndef PGP
+    if (z->att == (ush)BINARY && translate_eol) {
+        zipwarn("-l used on binary file", "");
+    }
+#endif
+  }
+  else if (!isdir)
+  {
+    if ((b = malloc(SBSZ)) == NULL)
+       return ZE_MEM;
+
+    if (l) {
+      k = rdsymlnk(z->name, b, SBSZ);
+/*
+ * compute crc first because zfwrite will alter the buffer b points to !!
+ */
+      crc = crc32(crc, (uch *) b, k);
+      if (zfwrite(b, 1, k, y) != k)
+      {
+        free((zvoid *)b);
+        return ZE_TEMP;
+      }
+      isize = k;
+
+#ifdef MINIX
+      q = k;
+#endif /* MINIX */
+    }
+    else
+    {
+      while ((k = file_read(b, SBSZ)) > 0 && k != (extent) EOF)
+      {
+        if (zfwrite(b, 1, k, y) != k)
+        {
+          if (ifile != fbad)
+            zclose(ifile);
+          free((zvoid *)b);
+          return ZE_TEMP;
+        }
+#ifndef WINDLL
+        if (verbose) putc('.', stderr);
+#else
+        if (verbose) fprintf(stdout,"%c",'.');
+#endif
+      }
+    }
+    free((zvoid *)b);
+    s = isize;
+  }
+  if (ifile != fbad && zerr(ifile)) {
+    perror("\nzip warning");
+    zipwarn("could not read input file: ", z->zname);
+  }
+  if (ifile != fbad)
+    zclose(ifile);
+#ifdef MMAP
+  if (remain != (ulg)-1L) {
+    munmap((caddr_t) window, window_size);
+    window = NULL;
+  }
+#endif /*MMAP */
+
+  tempzn += s;
+  p = tempzn; /* save for future fseek() */
+
+#if (!defined(MSDOS) || defined(OS2))
+#if !defined(VMS) && !defined(CMS_MVS) && !defined(__mpexl)
+  /* Check input size (but not in VMS -- variable record lengths mess it up)
+   * and not on MSDOS -- diet in TSR mode reports an incorrect file size)
+   */
+#ifndef TANDEM /* Tandem EOF does not match byte count unless Unstructured */
+  if (!translate_eol && q != -1L && isize != (ulg)q)
+  {
+    Trace((mesg, " i=%lu, q=%lu ", isize, q));
+    zipwarn(" file size changed while zipping ", z->name);
+  }
+#endif /* !TANDEM */
+#endif /* !VMS && !CMS_MVS && !__mpexl */
+#endif /* (!MSDOS || OS2) */
+
+  /* Try to rewrite the local header with correct information */
+  z->crc = crc;
+  z->siz = s;
+#if CRYPT
+  if (key != NULL)
+    z->siz += RAND_HEAD_LEN;
+#endif /* CRYPT */
+  z->len = isize;
+#ifdef BROKEN_FSEEK
+  if (!fseekable(y) || fseek(y, z->off, SEEK_SET))
+#else
+  if (fseek(y, z->off, SEEK_SET))
+#endif
+  {
+    if (z->how != (ush) m)
+       error("can't rewrite method");
+    if (m == STORE && q < 0)
+       ZIPERR(ZE_PARMS, "zip -0 not supported for I/O on pipes or devices");
+    if ((r = putextended(z, y)) != ZE_OK)
+      return r;
+    tempzn += 16L;
+    z->flg = z->lflg; /* if flg modified by inflate */
+  } else {
+     /* seek ok, ftell() should work, check compressed size */
+#if !defined(VMS) && !defined(CMS_MVS)
+    if (p - o != s) {
+      fprintf(mesg, " s=%ld, actual=%ld ", s, p-o);
+      error("incorrect compressed size");
+    }
+#endif /* !VMS && !CMS_MVS */
+    z->how = (ush)m;
+    z->ver = (ush)(m == STORE ? 10 : 20);  /* Need PKUNZIP 2.0 unless STORED */
+    if ((z->flg & 1) == 0)
+      z->flg &= ~8; /* clear the extended local header flag */
+    z->lflg = z->flg;
+    /* rewrite the local header: */
+    if ((r = putlocal(z, y)) != ZE_OK)
+      return r;
+    if (fseek(y, p, SEEK_SET))
+      return ZE_READ;
+    if ((z->flg & 1) != 0) {
+      /* encrypted file, extended header still required */
+      if ((r = putextended(z, y)) != ZE_OK)
+        return r;
+      tempzn += 16L;
+    }
+  }
+  /* Free the local extra field which is no longer needed */
+  if (z->ext) {
+    if (z->extra != z->cextra) {
+      free((zvoid *)(z->extra));
+      z->extra = NULL;
+    }
+    z->ext = 0;
+  }
+
+  /* Display statistics */
+  if (noisy)
+  {
+    if (verbose)
+      fprintf(mesg, "\t(in=%lu) (out=%lu)", isize, s);
+    if (m == DEFLATE)
+      fprintf(mesg, " (deflated %d%%)\n", percent(isize, s));
+    else
+      fprintf(mesg, " (stored 0%%)\n");
+    fflush(mesg);
+  }
+#ifdef WINDLL
+  if (lpZipUserFunctions->ServiceApplication != NULL)
+     {
+     if ((*lpZipUserFunctions->ServiceApplication)(z->zname, isize))
+        {
+        ZIPERR(ZE_ABORT, "User terminated operation");
+        }
+     }
+#endif
+  return ZE_OK;
+}
+
+
+local unsigned file_read(buf, size)
+  char *buf;
+  unsigned size;
+/* Read a new buffer from the current input file, perform end-of-line
+ * translation, and update the crc and input file size.
+ * IN assertion: size >= 2 (for end-of-line translation)
+ */
+{
+  unsigned len;
+  char *b;
+
+#if defined(MMAP) || defined(BIG_MEM)
+  if (remain == 0L) {
+    return 0;
+  } else if (remain != (ulg)-1L) {
+    /* The window data is already in place. We still compute the crc
+     * by 32K blocks instead of once on whole file to keep a certain
+     * locality of reference.
+     */
+    Assert(buf == (char*)window + isize, "are you lost?");
+    if ((ulg)size > remain) size = (unsigned)remain;
+    if (size > WSIZE) size = WSIZE; /* don't touch all pages at once */
+    remain -= (ulg)size;
+    len = size;
+  } else
+#endif /* MMAP || BIG_MEM */
+  if (translate_eol == 0) {
+    len = zread(ifile, buf, size);
+    if (len == (unsigned)EOF || len == 0) return len;
+#ifdef OS390
+    b = buf;
+    if (aflag == ASCII) {
+      while (*b != '\0') {
+        *b = (char)ascii[(uch)*b];
+        b++;
+      }
+    }
+#endif
+  } else if (translate_eol == 1) {
+    /* Transform LF to CR LF */
+    size >>= 1;
+    b = buf+size;
+    size = len = zread(ifile, b, size);
+    if (len == (unsigned)EOF || len == 0) return len;
+#ifdef EBCDIC
+    if (aflag == ASCII)
+    {
+       do {
+          char c;
+
+          if ((c = *b++) == '\n') {
+             *buf++ = CR; *buf++ = LF; len++;
+          } else {
+            *buf++ = (char)ascii[(uch)c];
+          }
+       } while (--size != 0);
+    }
+    else
+#endif /* EBCDIC */
+    {
+       do {
+          if ((*buf++ = *b++) == '\n') *(buf-1) = CR, *buf++ = LF, len++;
+       } while (--size != 0);
+    }
+    buf -= len;
+
+  } else {
+    /* Transform CR LF to LF and suppress final ^Z */
+    b = buf;
+    size = len = zread(ifile, buf, size-1);
+    if (len == (unsigned)EOF || len == 0) return len;
+    buf[len] = '\n'; /* I should check if next char is really a \n */
+#ifdef EBCDIC
+    if (aflag == ASCII)
+    {
+       do {
+          char c;
+
+          if ((c = *b++) == '\r' && *b == '\n') {
+             len--;
+          } else {
+             *buf++ = (char)(c == '\n' ? LF : ascii[(uch)c]);
+          }
+       } while (--size != 0);
+    }
+    else
+#endif /* EBCDIC */
+    {
+       do {
+          if (( *buf++ = *b++) == CR && *b == LF) buf--, len--;
+       } while (--size != 0);
+    }
+    if (len == 0) {
+       zread(ifile, buf, 1); len = 1; /* keep single \r if EOF */
+#ifdef EBCDIC
+       if (aflag == ASCII) {
+          *buf = (char)(*buf == '\n' ? LF : ascii[(uch)(*buf)]);
+       }
+#endif
+    } else {
+       buf -= len;
+       if (buf[len-1] == CTRLZ) len--; /* suppress final ^Z */
+    }
+  }
+  crc = crc32(crc, (uch *) buf, len);
+  isize += (ulg)len;
+  /* added check for file size - 2/20/05 */
+  if ((isize & (ulg)0xffffffffL) < (ulg)len) {
+    /* fatal error: file size exceeds Zip limit */
+    ZIPERR(ZE_BIG, "file exceeds Zip's 4GB uncompressed size limit");
+  }
+  return len;
+}
+
+
+#ifdef USE_ZLIB
+
+local int zl_deflate_init(pack_level)
+    int pack_level;
+{
+    unsigned i;
+    int windowBits;
+    int err = Z_OK;
+    int zp_err = ZE_OK;
+
+    if (zlib_version[0] != ZLIB_VERSION[0]) {
+        sprintf(errbuf, "incompatible zlib version (expected %s, found %s)",
+              ZLIB_VERSION, zlib_version);
+        zp_err = ZE_LOGIC;
+    } else if (strcmp(zlib_version, ZLIB_VERSION) != 0) {
+        fprintf(stderr,
+                "\twarning:  different zlib version (expected %s, using %s)\n",
+                ZLIB_VERSION, zlib_version);
+    }
+
+    /* windowBits = log2(WSIZE) */
+    for (i = ((unsigned)WSIZE), windowBits = 0; i != 1; i >>= 1, ++windowBits);
+
+    zstrm.zalloc = (alloc_func)Z_NULL;
+    zstrm.zfree = (free_func)Z_NULL;
+
+    Trace((stderr, "initializing deflate()\n"));
+    err = deflateInit2(&zstrm, pack_level, Z_DEFLATED, -windowBits, 8, 0);
+
+    if (err == Z_MEM_ERROR) {
+        sprintf(errbuf, "cannot initialize zlib deflate");
+        zp_err = ZE_MEM;
+    } else if (err != Z_OK) {
+        sprintf(errbuf, "zlib deflateInit failure (%d)", err);
+        zp_err = ZE_LOGIC;
+    }
+
+    deflInit = TRUE;
+    return zp_err;
+}
+
+
+void zl_deflate_free()
+{
+    int err;
+
+    if (f_obuf != NULL) {
+        free(f_obuf);
+        f_obuf = NULL;
+    }
+    if (f_ibuf != NULL) {
+        free(f_ibuf);
+        f_ibuf = NULL;
+    }
+    if (deflInit) {
+        err = deflateEnd(&zstrm);
+        if (err != Z_OK && err !=Z_DATA_ERROR) {
+            ziperr(ZE_LOGIC, "zlib deflateEnd failed");
+        }
+    }
+}
+
+#else /* !USE_ZLIB */
+
+#ifdef ZP_NEED_MEMCOMPR
+/* ===========================================================================
+ * In-memory read function. As opposed to file_read(), this function
+ * does not perform end-of-line translation, and does not update the
+ * crc and input size.
+ *    Note that the size of the entire input buffer is an unsigned long,
+ * but the size used in mem_read() is only an unsigned int. This makes a
+ * difference on 16 bit machines. mem_read() may be called several
+ * times for an in-memory compression.
+ */
+local unsigned mem_read(b, bsize)
+     char *b;
+     unsigned bsize;
+{
+    if (in_offset < in_size) {
+        ulg block_size = in_size - in_offset;
+        if (block_size > (ulg)bsize) block_size = (ulg)bsize;
+        memcpy(b, in_buf + in_offset, (unsigned)block_size);
+        in_offset += (unsigned)block_size;
+        return (unsigned)block_size;
+    } else {
+        return 0; /* end of input */
+    }
+}
+#endif /* ZP_NEED_MEMCOMPR */
+
+
+/* ===========================================================================
+ * Flush the current output buffer.
+ */
+void flush_outbuf(o_buf, o_idx)
+    char *o_buf;
+    unsigned *o_idx;
+{
+    if (zfile == NULL) {
+        error("output buffer too small for in-memory compression");
+    }
+    /* Encrypt and write the output buffer: */
+    if (*o_idx != 0) {
+        zfwrite(o_buf, 1, (extent)*o_idx, zfile);
+        if (ferror(zfile)) ziperr(ZE_WRITE, "write error on zip file");
+    }
+    *o_idx = 0;
+}
+
+/* ===========================================================================
+ * Return true if the zip file can be seeked. This is used to check if
+ * the local header can be re-rewritten. This function always returns
+ * true for in-memory compression.
+ * IN assertion: the local header has already been written (ftell() > 0).
+ */
+int seekable()
+{
+    return fseekable(zfile);
+}
+#endif /* ?USE_ZLIB */
+
+
+/* ===========================================================================
+ * Compression to archive file.
+ */
+
+local ulg filecompress(z_entry, zipfile, cmpr_method)
+    struct zlist far *z_entry;
+    FILE *zipfile;
+    int *cmpr_method;
+{
+#ifdef USE_ZLIB
+    int err = Z_OK;
+    unsigned mrk_cnt = 1;
+    int maybe_stored = FALSE;
+    ulg cmpr_size;
+#if defined(MMAP) || defined(BIG_MEM)
+    unsigned ibuf_sz = (unsigned)SBSZ;
+#else
+#   define ibuf_sz ((unsigned)SBSZ)
+#endif
+#ifndef OBUF_SZ
+#  define OBUF_SZ ZBSZ
+#endif
+
+#if defined(MMAP) || defined(BIG_MEM)
+    if (remain == (ulg)-1L && f_ibuf == NULL)
+#else /* !(MMAP || BIG_MEM */
+    if (f_ibuf == NULL)
+#endif /* MMAP || BIG_MEM */
+        f_ibuf = (char *)malloc(SBSZ);
+    if (f_obuf == NULL)
+        f_obuf = (char *)malloc(OBUF_SZ);
+#if defined(MMAP) || defined(BIG_MEM)
+    if ((remain == (ulg)-1L && f_ibuf == NULL) || f_obuf == NULL)
+#else /* !(MMAP || BIG_MEM */
+    if (f_ibuf == NULL || f_obuf == NULL)
+#endif /* MMAP || BIG_MEM */
+        ziperr(ZE_MEM, "allocating zlib file-I/O buffers");
+
+    if (!deflInit) {
+        err = zl_deflate_init(level);
+        if (err != ZE_OK)
+            ziperr(err, errbuf);
+    }
+
+    if (level <= 2) {
+        z_entry->flg |= 4;
+    } else if (level >= 8) {
+        z_entry->flg |= 2;
+    }
+#if defined(MMAP) || defined(BIG_MEM)
+    if (remain != (ulg)-1L) {
+        zstrm.next_in = (Bytef *)window;
+        ibuf_sz = (unsigned)WSIZE;
+    } else
+#endif /* MMAP || BIG_MEM */
+    {
+        zstrm.next_in = (Bytef *)f_ibuf;
+    }
+    zstrm.avail_in = file_read(zstrm.next_in, ibuf_sz);
+    if (zstrm.avail_in < ibuf_sz) {
+        unsigned more = file_read(zstrm.next_in + zstrm.avail_in,
+                                  (ibuf_sz - zstrm.avail_in));
+        if (more == EOF || more == 0) {
+            maybe_stored = TRUE;
+        } else {
+            zstrm.avail_in += more;
+        }
+    }
+    zstrm.next_out = (Bytef *)f_obuf;
+    zstrm.avail_out = OBUF_SZ;
+
+    if (!maybe_stored) while (zstrm.avail_in != 0 && zstrm.avail_in != EOF) {
+        err = deflate(&zstrm, Z_NO_FLUSH);
+        if (err != Z_OK && err != Z_STREAM_END) {
+            sprintf(errbuf, "unexpected zlib deflate error %d", err);
+            ziperr(ZE_LOGIC, errbuf);
+        }
+        if (zstrm.avail_out == 0) {
+            if (zfwrite(f_obuf, 1, OBUF_SZ, zipfile) != OBUF_SZ) {
+                ziperr(ZE_TEMP, "error writing to zipfile");
+            }
+            zstrm.next_out = (Bytef *)f_obuf;
+            zstrm.avail_out = OBUF_SZ;
+        }
+        if (zstrm.avail_in == 0) {
+            if (verbose)
+                while((unsigned)(zstrm.total_in / (uLong)WSIZE) > mrk_cnt) {
+                    mrk_cnt++;
+#ifndef WINDLL
+                    putc('.', stderr);
+#else
+                    fprintf(stdout,"%c",'.');
+#endif
+                }
+#if defined(MMAP) || defined(BIG_MEM)
+            if (remain == (ulg)-1L)
+                zstrm.next_in = (Bytef *)f_ibuf;
+#else
+            zstrm.next_in = (Bytef *)f_ibuf;
+#endif
+            zstrm.avail_in = file_read(zstrm.next_in, ibuf_sz);
+        }
+    }
+
+    do {
+        err = deflate(&zstrm, Z_FINISH);
+        if (maybe_stored) {
+            if (err == Z_STREAM_END && zstrm.total_out >= zstrm.total_in &&
+                fseekable(zipfile)) {
+                /* deflation does not reduce size, switch to STORE method */
+                unsigned len_out = (unsigned)zstrm.total_in;
+                if (zfwrite(f_ibuf, 1, len_out, zipfile) != len_out) {
+                    ziperr(ZE_TEMP, "error writing to zipfile");
+                }
+                zstrm.total_out = (uLong)len_out;
+                *cmpr_method = STORE;
+                break;
+            } else {
+                maybe_stored = FALSE;
+            }
+        }
+        if (zstrm.avail_out < OBUF_SZ) {
+            unsigned len_out = OBUF_SZ - zstrm.avail_out;
+            if (zfwrite(f_obuf, 1, len_out, zipfile) != len_out) {
+                ziperr(ZE_TEMP, "error writing to zipfile");
+            }
+            zstrm.next_out = (Bytef *)f_obuf;
+            zstrm.avail_out = OBUF_SZ;
+        }
+    } while (err == Z_OK);
+
+    if (err != Z_STREAM_END) {
+        sprintf(errbuf, "unexpected zlib deflate error %d", err);
+        ziperr(ZE_LOGIC, errbuf);
+    }
+
+    if (z_entry->att == (ush)UNKNOWN)
+        z_entry->att = (ush)(zstrm.data_type == Z_ASCII ? ASCII : BINARY);
+    cmpr_size = (ulg)zstrm.total_out;
+
+    if ((err = deflateReset(&zstrm)) != Z_OK)
+        ziperr(ZE_LOGIC, "zlib deflateReset failed");
+    return cmpr_size;
+#else /* !USE_ZLIB */
+
+    /* Set the defaults for file compression. */
+    zfile = zipfile;
+    read_buf = file_read;
+
+    /* Initialize deflate's internals and execute file compression. */
+    bi_init(file_outbuf, sizeof(file_outbuf), TRUE);
+    ct_init(&z_entry->att, cmpr_method);
+    lm_init(level, &z_entry->flg);
+    return deflate();
+#endif /* ?USE_ZLIB */
+}
+
+#ifdef ZP_NEED_MEMCOMPR
+/* ===========================================================================
+ * In-memory compression. This version can be used only if the entire input
+ * fits in one memory buffer. The compression is then done in a single
+ * call of memcompress(). (An extension to allow repeated calls would be
+ * possible but is not needed here.)
+ * The first two bytes of the compressed output are set to a short with the
+ * method used (DEFLATE or STORE). The following four bytes contain the CRC.
+ * The values are stored in little-endian order on all machines.
+ * This function returns the byte size of the compressed output, including
+ * the first six bytes (method and crc).
+ */
+
+ulg memcompress(tgt, tgtsize, src, srcsize)
+    char *tgt, *src;       /* target and source buffers */
+    ulg tgtsize, srcsize;  /* target and source sizes */
+{
+    ulg crc;
+    unsigned out_total;
+    int method   = DEFLATE;
+#ifdef USE_ZLIB
+    int err      = Z_OK;
+#else
+    ush att      = (ush)UNKNOWN;
+    ush flags    = 0;
+#endif
+
+    if (tgtsize <= (ulg)6L) error("target buffer too small");
+    out_total = 2 + 4;
+
+#ifdef USE_ZLIB
+    if (!deflInit) {
+        err = zl_deflate_init(level);
+        if (err != ZE_OK)
+            ziperr(err, errbuf);
+    }
+
+    zstrm.next_in = (Bytef *)src;
+    zstrm.avail_in = (uInt)srcsize;
+    zstrm.next_out = (Bytef *)(tgt + out_total);
+    zstrm.avail_out = (uInt)tgtsize - (uInt)out_total;
+
+    err = deflate(&zstrm, Z_FINISH);
+    if (err != Z_STREAM_END)
+        error("output buffer too small for in-memory compression");
+    out_total += (unsigned)zstrm.total_out;
+
+    if ((err = deflateReset(&zstrm)) != Z_OK)
+        error("zlib deflateReset failed");
+#else /* !USE_ZLIB */
+    zfile     = NULL;
+    read_buf  = mem_read;
+    in_buf    = src;
+    in_size   = (unsigned)srcsize;
+    in_offset = 0;
+    window_size = 0L;
+
+    bi_init(tgt + (2 + 4), (unsigned)(tgtsize - (2 + 4)), FALSE);
+    ct_init(&att, &method);
+    lm_init((level != 0 ? level : 1), &flags);
+    out_total += (unsigned)deflate();
+    window_size = 0L; /* was updated by lm_init() */
+#endif /* ?USE_ZLIB */
+
+    crc = CRCVAL_INITIAL;
+    crc = crc32(crc, (uch *)src, (extent)srcsize);
+
+    /* For portability, force little-endian order on all machines: */
+    tgt[0] = (char)(method & 0xff);
+    tgt[1] = (char)((method >> 8) & 0xff);
+    tgt[2] = (char)(crc & 0xff);
+    tgt[3] = (char)((crc >> 8) & 0xff);
+    tgt[4] = (char)((crc >> 16) & 0xff);
+    tgt[5] = (char)((crc >> 24) & 0xff);
+
+    return (ulg)out_total;
+}
+#endif /* ZP_NEED_MEMCOMPR */
+#endif /* !UTIL */