summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHyungKyu Song <hk76.song@samsung.com>2013-02-16 00:51:52 +0900
committerHyungKyu Song <hk76.song@samsung.com>2013-02-16 00:51:52 +0900
commit49807896eda1a7081cce1a7a134fb0071f5e7eeb (patch)
treeaef757b2abf225284bf0ccb0df3a7b7aab6765aa
parent3101b2a7be8f0e3cc6ff469ce2597945c862264b (diff)
downloadzip-accepted/tizen_2.0/20130215.202531.tar.gz
zip-accepted/tizen_2.0/20130215.202531.tar.bz2
zip-accepted/tizen_2.0/20130215.202531.zip
-rw-r--r--BUGS6
-rw-r--r--CHANGES1013
-rw-r--r--INSTALL188
-rw-r--r--LICENSE55
-rw-r--r--MANUAL804
-rw-r--r--README155
-rw-r--r--README.CR115
-rw-r--r--TODO72
-rw-r--r--USexport.msg75
-rw-r--r--WHATSNEW51
-rw-r--r--WHERE258
-rw-r--r--acorn/GMakefile130
-rw-r--r--acorn/ReadMe85
-rw-r--r--acorn/ReadMe.GMakefile14
-rw-r--r--acorn/RunMe1st23
-rw-r--r--acorn/acornzip.c593
-rw-r--r--acorn/makefile111
-rw-r--r--acorn/match.s217
-rw-r--r--acorn/osdep.h28
-rw-r--r--acorn/riscos.c394
-rw-r--r--acorn/riscos.h119
-rw-r--r--acorn/sendbits.s105
-rw-r--r--acorn/srcrenamebin0 -> 6175 bytes
-rw-r--r--acorn/swiven.h59
-rw-r--r--acorn/swiven.s276
-rw-r--r--acorn/zipup.h16
-rw-r--r--amiga/LMKfile116
-rw-r--r--amiga/README1
-rw-r--r--amiga/amiga.c143
-rw-r--r--amiga/amiga.h54
-rw-r--r--amiga/amigazip.c510
-rw-r--r--amiga/crc_68.a144
-rw-r--r--amiga/deflate.a1053
-rw-r--r--amiga/filedate.c636
-rw-r--r--amiga/makefile.azt282
-rw-r--r--amiga/match.a182
-rw-r--r--amiga/match_68.a273
-rw-r--r--amiga/osdep.h109
-rw-r--r--amiga/smakefile671
-rw-r--r--amiga/stat.c293
-rw-r--r--amiga/time_lib.c541
-rw-r--r--amiga/timezone.doc85
-rw-r--r--amiga/z-stat.h95
-rw-r--r--amiga/z-time.h76
-rw-r--r--amiga/zipup.h25
-rw-r--r--aosvs/aosvs.c662
-rw-r--r--aosvs/make.cli5
-rw-r--r--api.c494
-rw-r--r--api.h152
-rw-r--r--atari/Makefile109
-rw-r--r--atari/README5
-rw-r--r--atari/atari.c682
-rw-r--r--atari/make_all.mup7
-rw-r--r--atari/make_zip.mup7
-rw-r--r--atari/osdep.h20
-rw-r--r--atari/zipup.h19
-rw-r--r--atheos/Contents11
-rw-r--r--atheos/Makefile144
-rw-r--r--atheos/README23
-rw-r--r--atheos/atheos.c885
-rw-r--r--atheos/osdep.h63
-rw-r--r--atheos/zipup.h24
-rw-r--r--beos/Contents14
-rw-r--r--beos/Makefile180
-rw-r--r--beos/README31
-rw-r--r--beos/beos.c946
-rw-r--r--beos/osdep.h59
-rw-r--r--beos/zipup.h19
-rw-r--r--cmsmvs/README.CMS434
-rw-r--r--cmsmvs/README.MVS92
-rw-r--r--cmsmvs/README.MVS.LE286
-rw-r--r--cmsmvs/cczip.exec124
-rw-r--r--cmsmvs/cms.c34
-rw-r--r--cmsmvs/cmsmvs.c442
-rw-r--r--cmsmvs/cmsmvs.h134
-rw-r--r--cmsmvs/cstat.h53
-rw-r--r--cmsmvs/mc.exec95
-rw-r--r--cmsmvs/mvs.c221
-rw-r--r--cmsmvs/mvs.h40
-rw-r--r--cmsmvs/mvs.mki128
-rw-r--r--cmsmvs/pipzip.rexx27
-rw-r--r--cmsmvs/zip.exec66
-rw-r--r--cmsmvs/zip.makefile22
-rw-r--r--cmsmvs/zipcloak.exec66
-rw-r--r--cmsmvs/zipmvsc.job95
-rw-r--r--cmsmvs/zipname.conven200
-rw-r--r--cmsmvs/zipnote.exec66
-rw-r--r--cmsmvs/zipsplit.exec66
-rw-r--r--cmsmvs/zipup.h18
-rw-r--r--cmsmvs/zipvmc.exec50
-rw-r--r--crc32.c64
-rw-r--r--crc_i386.S240
-rw-r--r--crctab.c227
-rw-r--r--crypt.c584
-rw-r--r--crypt.h175
-rw-r--r--deflate.c902
-rw-r--r--ebcdic.h284
-rw-r--r--file_id.diz15
-rw-r--r--fileio.c986
-rw-r--r--globals.c96
-rw-r--r--human68k/Makefile93
-rw-r--r--human68k/Makefile.gcc76
-rw-r--r--human68k/crc_68.s144
-rw-r--r--human68k/deflate.s1076
-rw-r--r--human68k/human68k.c362
-rw-r--r--human68k/match.s163
-rw-r--r--human68k/osdep.h28
-rw-r--r--human68k/zipup.h16
-rw-r--r--macos/Contents63
-rw-r--r--macos/HISTORY.TXT489
-rw-r--r--macos/README.TXT560
-rw-r--r--macos/ZipLib.h166
-rw-r--r--macos/ZipSx.h167
-rw-r--r--macos/ZpPrj.hqx455
-rw-r--r--macos/osdep.h118
-rw-r--r--macos/readme.1st12
-rw-r--r--macos/source/VolWarn.h69
-rw-r--r--macos/source/charmap.h380
-rw-r--r--macos/source/extrafld.c920
-rw-r--r--macos/source/getenv.c398
-rw-r--r--macos/source/helpers.c477
-rw-r--r--macos/source/helpers.h57
-rw-r--r--macos/source/macglob.h86
-rw-r--r--macos/source/macopen.c363
-rw-r--r--macos/source/macopen.h21
-rw-r--r--macos/source/macos.c1079
-rw-r--r--macos/source/macstuff.c1724
-rw-r--r--macos/source/macstuff.h1108
-rw-r--r--macos/source/mactime.c451
-rw-r--r--macos/source/mactime.h61
-rw-r--r--macos/source/pathname.c665
-rw-r--r--macos/source/pathname.h59
-rw-r--r--macos/source/recurse.c442
-rw-r--r--macos/source/recurse.h129
-rw-r--r--macos/source/unixlike.c313
-rw-r--r--macos/source/unixlike.h86
-rw-r--r--macos/source/zip_rc.hqx43
-rw-r--r--macos/zipup.h25
-rw-r--r--man/zip.11318
-rw-r--r--match.S407
-rw-r--r--mktime.c257
-rw-r--r--msdos/README.DOS155
-rw-r--r--msdos/crc_i86.asm464
-rw-r--r--msdos/makefile.bor196
-rw-r--r--msdos/makefile.dj1125
-rw-r--r--msdos/makefile.dj2135
-rw-r--r--msdos/makefile.emx167
-rw-r--r--msdos/makefile.msc205
-rw-r--r--msdos/makefile.tc177
-rw-r--r--msdos/makefile.wat253
-rw-r--r--msdos/match.asm457
-rw-r--r--msdos/msdos.c1059
-rw-r--r--msdos/osdep.h205
-rw-r--r--msdos/zipup.h16
-rw-r--r--os2/makefile.os2560
-rw-r--r--os2/match32.asm175
-rw-r--r--os2/os2.c481
-rw-r--r--os2/os2acl.c385
-rw-r--r--os2/os2acl.h34
-rw-r--r--os2/os2zip.c1213
-rw-r--r--os2/os2zip.h84
-rw-r--r--os2/osdep.h173
-rw-r--r--os2/zip.def3
-rw-r--r--os2/zipup.h16
-rw-r--r--packaging/exec-shield.patch19
-rw-r--r--packaging/zcrypt29.tar.gzbin0 -> 17484 bytes
-rw-r--r--packaging/zip-2.3-currdir.patch11
-rw-r--r--packaging/zip-2.31-configure.patch213
-rw-r--r--packaging/zip-2.31-install.patch11
-rw-r--r--packaging/zip-2.31-near-4GB.patch293
-rw-r--r--packaging/zip.spec180
-rw-r--r--packaging/zip23-umask.patch23
-rw-r--r--packaging/zip23.patch93
-rw-r--r--proginfo/3rdparty.bug114
-rw-r--r--proginfo/ZipPorts285
-rw-r--r--proginfo/algorith.txt68
-rw-r--r--proginfo/extra.fld1441
-rw-r--r--proginfo/fileinfo.cms231
-rw-r--r--proginfo/infozip.who232
-rw-r--r--proginfo/nt.sd111
-rw-r--r--proginfo/perform.dos183
-rw-r--r--proginfo/txtvsbin.txt112
-rw-r--r--proginfo/ziplimit.txt218
-rw-r--r--qdos/IZREADME.SMS600
-rw-r--r--qdos/Makefile.qdos143
-rw-r--r--qdos/Makefile.qlzip139
-rw-r--r--qdos/config.s153
-rw-r--r--qdos/crc68.s99
-rw-r--r--qdos/match.s138
-rw-r--r--qdos/osdep.h33
-rw-r--r--qdos/qdos.c877
-rw-r--r--qdos/qfileio.c235
-rw-r--r--qdos/zipup.h19
-rw-r--r--revision.h123
-rw-r--r--tailor.h480
-rw-r--r--tandem/DOIT21
-rw-r--r--tandem/HISTORY97
-rw-r--r--tandem/README94
-rw-r--r--tandem/commacs85
-rw-r--r--tandem/macros344
-rw-r--r--tandem/make110
-rw-r--r--tandem/tandem.c866
-rw-r--r--tandem/tandem.h248
-rw-r--r--tandem/tannsk.h19
-rw-r--r--tandem/tanzip.c637
-rw-r--r--tandem/tanzip.h17
-rw-r--r--tandem/zipup.h26
-rw-r--r--theos/Makefile135
-rw-r--r--theos/README34
-rw-r--r--theos/_chmod.c21
-rw-r--r--theos/_fprintf.c26
-rw-r--r--theos/_isatty.c26
-rw-r--r--theos/_rename.c83
-rw-r--r--theos/_setargv.c140
-rw-r--r--theos/_stat.c461
-rw-r--r--theos/charconv.h93
-rw-r--r--theos/osdep.h58
-rw-r--r--theos/stat.h106
-rw-r--r--theos/theos.c558
-rw-r--r--theos/zipup.h19
-rw-r--r--tops20/make.mic36
-rw-r--r--tops20/osdep.h31
-rw-r--r--tops20/rename.mic6
-rw-r--r--tops20/tops20.c576
-rw-r--r--tops20/zipup.h18
-rw-r--r--trees.c1401
-rw-r--r--ttyio.c637
-rw-r--r--ttyio.h218
-rw-r--r--unix/Makefile268
-rw-r--r--unix/Packaging/README44
-rw-r--r--unix/Packaging/pkginfo.in13
-rwxr-xr-xunix/Packaging/postinstall22
-rwxr-xr-xunix/Packaging/preinstall.in26
-rw-r--r--unix/Packaging/prototype24
-rw-r--r--unix/README.OS39085
-rwxr-xr-xunix/configure301
-rw-r--r--unix/osdep.h33
-rw-r--r--unix/unix.c787
-rw-r--r--unix/zipup.h22
-rw-r--r--util.c694
-rw-r--r--vms/00binary.vms87
-rw-r--r--vms/00readme.txt126
-rw-r--r--vms/cmdline.c1010
-rw-r--r--vms/cvthelp.tpu176
-rw-r--r--vms/descrip.mms315
-rwxr-xr-xvms/link_zip.com204
-rwxr-xr-xvms/make_zip.com287
-rw-r--r--vms/makefile.vms251
-rw-r--r--vms/osdep.h106
-rw-r--r--vms/vms.c807
-rw-r--r--vms/vms.h271
-rw-r--r--vms/vms_im.c850
-rw-r--r--vms/vms_pk.c550
-rw-r--r--vms/vms_zip.rnh548
-rw-r--r--vms/vmsdefs.h320
-rw-r--r--vms/vmsmunch.c410
-rw-r--r--vms/vmsmunch.h55
-rw-r--r--vms/vmszip.c703
-rw-r--r--vms/zip_cli.cld73
-rw-r--r--vms/zip_cli.help617
-rw-r--r--vms/zipup.h24
-rw-r--r--win32/README.NT17
-rw-r--r--win32/README.TZ7
-rw-r--r--win32/crc_i386.asm241
-rw-r--r--win32/crc_i386.c228
-rw-r--r--win32/crc_lcc.asm119
-rw-r--r--win32/gvmat64.asm513
-rw-r--r--win32/lm32_lcc.asm174
-rw-r--r--win32/makefile.a64134
-rw-r--r--win32/makefile.bor179
-rw-r--r--win32/makefile.dj110
-rw-r--r--win32/makefile.emx291
-rw-r--r--win32/makefile.gcc142
-rw-r--r--win32/makefile.ibm123
-rw-r--r--win32/makefile.lcc123
-rw-r--r--win32/makefile.w10181
-rw-r--r--win32/makefile.w32147
-rw-r--r--win32/makefile.wat181
-rw-r--r--win32/match32.asm184
-rw-r--r--win32/nt.c482
-rw-r--r--win32/nt.h73
-rw-r--r--win32/osdep.h271
-rw-r--r--win32/readme.a6442
-rw-r--r--win32/rsxntwin.h166
-rw-r--r--win32/vc6/zip.dsp328
-rw-r--r--win32/vc6/zip.dsw65
-rw-r--r--win32/vc6/zipcloak.dsp164
-rw-r--r--win32/vc6/zipnote.dsp144
-rw-r--r--win32/vc6/zipsplit.dsp144
-rw-r--r--win32/win32.c989
-rw-r--r--win32/win32zip.c782
-rw-r--r--win32/win32zip.h33
-rw-r--r--win32/zip.def4
-rw-r--r--win32/zipup.h37
-rw-r--r--windll/contents37
-rw-r--r--windll/example.c375
-rw-r--r--windll/example.h54
-rw-r--r--windll/resource.h16
-rw-r--r--windll/structs.h28
-rw-r--r--windll/vb/VBZIP.vbw2
-rw-r--r--windll/vb/VBZipBas.bas455
-rw-r--r--windll/vb/Vbzip.vbp34
-rw-r--r--windll/vb/Vbzipfrm.frm130
-rw-r--r--windll/vb/readmeVB.txt35
-rw-r--r--windll/visualc/dll/zip32.dsp168
-rw-r--r--windll/visualc/dll/zip32.dsw29
-rw-r--r--windll/visualc/dll/zip32.mak858
-rw-r--r--windll/visualc/lib/zip32.dsp162
-rw-r--r--windll/visualc/lib/zip32.dsw29
-rw-r--r--windll/visualc/lib/zip32.mak586
-rw-r--r--windll/windll.c174
-rw-r--r--windll/windll.h61
-rw-r--r--windll/windll.rc115
-rw-r--r--windll/windll.txt132
-rw-r--r--windll/windll16.def15
-rw-r--r--windll/windll32.def15
-rw-r--r--windll/ziplib.def15
-rw-r--r--windll/zipver.h15
-rw-r--r--zip.c2326
-rw-r--r--zip.h567
-rw-r--r--zipcloak.c409
-rw-r--r--ziperr.h67
-rw-r--r--zipfile.c1565
-rw-r--r--zipnote.c505
-rw-r--r--zipsplit.c804
-rw-r--r--zipup.c1186
326 files changed, 84828 insertions, 0 deletions
diff --git a/BUGS b/BUGS
new file mode 100644
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
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
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
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
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
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
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
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
index 0000000..068aa9f
--- /dev/null
+++ b/USexport.msg
@@ -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
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
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
index 0000000..e9f02bc
--- /dev/null
+++ b/acorn/GMakefile
@@ -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
index 0000000..41c37a5
--- /dev/null
+++ b/acorn/ReadMe
@@ -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
index 0000000..714fe2d
--- /dev/null
+++ b/acorn/ReadMe.GMakefile
@@ -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
index 0000000..a330adb
--- /dev/null
+++ b/acorn/RunMe1st
@@ -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
index 0000000..8de308c
--- /dev/null
+++ b/acorn/acornzip.c
@@ -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
index 0000000..5aa1c5c
--- /dev/null
+++ b/acorn/makefile
@@ -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
index 0000000..ee68ce6
--- /dev/null
+++ b/acorn/match.s
@@ -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
index 0000000..ea002ef
--- /dev/null
+++ b/acorn/osdep.h
@@ -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
index 0000000..eb1b897
--- /dev/null
+++ b/acorn/riscos.c
@@ -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
index 0000000..2bbd72e
--- /dev/null
+++ b/acorn/riscos.h
@@ -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
index 0000000..f12921a
--- /dev/null
+++ b/acorn/sendbits.s
@@ -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
index 0000000..7bd6119
--- /dev/null
+++ b/acorn/srcrename
Binary files differ
diff --git a/acorn/swiven.h b/acorn/swiven.h
new file mode 100644
index 0000000..c860d7d
--- /dev/null
+++ b/acorn/swiven.h
@@ -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
index 0000000..1630124
--- /dev/null
+++ b/acorn/swiven.s
@@ -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
index 0000000..47c3536
--- /dev/null
+++ b/acorn/zipup.h
@@ -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
index 0000000..6b6aa40
--- /dev/null
+++ b/amiga/LMKfile
@@ -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
index 0000000..861ff85
--- /dev/null
+++ b/amiga/README
@@ -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
index 0000000..93bd495
--- /dev/null
+++ b/amiga/amiga.c
@@ -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
index 0000000..a1461d8
--- /dev/null
+++ b/amiga/amiga.h
@@ -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
index 0000000..f72f27d
--- /dev/null
+++ b/amiga/amigazip.c
@@ -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
index 0000000..809a0ba
--- /dev/null
+++ b/amiga/crc_68.a
@@ -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
index 0000000..b21adae
--- /dev/null
+++ b/amiga/deflate.a
@@ -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
index 0000000..84c7bed
--- /dev/null
+++ b/amiga/filedate.c
@@ -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
index 0000000..08f1cee
--- /dev/null
+++ b/amiga/makefile.azt
@@ -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
index 0000000..ec5bcf0
--- /dev/null
+++ b/amiga/match.a
@@ -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
index 0000000..d1a6c39
--- /dev/null
+++ b/amiga/match_68.a
@@ -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
index 0000000..a5851e3
--- /dev/null
+++ b/amiga/osdep.h
@@ -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
index 0000000..a772fcb
--- /dev/null
+++ b/amiga/smakefile
@@ -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
index 0000000..c453273
--- /dev/null
+++ b/amiga/stat.c
@@ -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
index 0000000..2804c05
--- /dev/null
+++ b/amiga/time_lib.c
@@ -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
index 0000000..7868093
--- /dev/null
+++ b/amiga/timezone.doc
@@ -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
index 0000000..bb33b34
--- /dev/null
+++ b/amiga/z-stat.h
@@ -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
index 0000000..53c01bf
--- /dev/null
+++ b/amiga/z-time.h
@@ -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
index 0000000..c9316f4
--- /dev/null
+++ b/amiga/zipup.h
@@ -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
index 0000000..3add126
--- /dev/null
+++ b/aosvs/aosvs.c
@@ -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
index 0000000..304e799
--- /dev/null
+++ b/aosvs/make.cli
@@ -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
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
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
index 0000000..96b6ff5
--- /dev/null
+++ b/atari/Makefile
@@ -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
index 0000000..cce4206
--- /dev/null
+++ b/atari/README
@@ -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
index 0000000..9bfb5d1
--- /dev/null
+++ b/atari/atari.c
@@ -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
index 0000000..5f8c4dc
--- /dev/null
+++ b/atari/make_all.mup
@@ -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
index 0000000..4ea4c31
--- /dev/null
+++ b/atari/make_zip.mup
@@ -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
index 0000000..46387b6
--- /dev/null
+++ b/atari/osdep.h
@@ -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
index 0000000..1de3f61
--- /dev/null
+++ b/atari/zipup.h
@@ -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
index 0000000..3ffaba6
--- /dev/null
+++ b/atheos/Contents
@@ -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
index 0000000..265ff42
--- /dev/null
+++ b/atheos/Makefile
@@ -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
index 0000000..e9731fe
--- /dev/null
+++ b/atheos/README
@@ -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
index 0000000..dac3ef8
--- /dev/null
+++ b/atheos/atheos.c
@@ -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
index 0000000..69fd5b2
--- /dev/null
+++ b/atheos/osdep.h
@@ -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
index 0000000..6cbc806
--- /dev/null
+++ b/atheos/zipup.h
@@ -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
index 0000000..939a535
--- /dev/null
+++ b/beos/Contents
@@ -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
index 0000000..0dc31e1
--- /dev/null
+++ b/beos/Makefile
@@ -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
index 0000000..b985ea0
--- /dev/null
+++ b/beos/README
@@ -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
index 0000000..d64cbb3
--- /dev/null
+++ b/beos/beos.c
@@ -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
index 0000000..0197903
--- /dev/null
+++ b/beos/osdep.h
@@ -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
index 0000000..40c79eb
--- /dev/null
+++ b/beos/zipup.h
@@ -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
index 0000000..a4425da
--- /dev/null
+++ b/cmsmvs/README.CMS
@@ -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
index 0000000..4d451db
--- /dev/null
+++ b/cmsmvs/README.MVS
@@ -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
index 0000000..f7dcb8a
--- /dev/null
+++ b/cmsmvs/README.MVS.LE
@@ -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
index 0000000..afa97d0
--- /dev/null
+++ b/cmsmvs/cczip.exec
@@ -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
index 0000000..e8dfa34
--- /dev/null
+++ b/cmsmvs/cms.c
@@ -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
index 0000000..5297908
--- /dev/null
+++ b/cmsmvs/cmsmvs.c
@@ -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
index 0000000..8fca61b
--- /dev/null
+++ b/cmsmvs/cmsmvs.h
@@ -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
index 0000000..f02a5c3
--- /dev/null
+++ b/cmsmvs/cstat.h
@@ -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
index 0000000..ca22a18
--- /dev/null
+++ b/cmsmvs/mc.exec
@@ -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
index 0000000..fabc4f0
--- /dev/null
+++ b/cmsmvs/mvs.c
@@ -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
index 0000000..b2f9760
--- /dev/null
+++ b/cmsmvs/mvs.h
@@ -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
index 0000000..7990902
--- /dev/null
+++ b/cmsmvs/mvs.mki
@@ -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
index 0000000..4249ded
--- /dev/null
+++ b/cmsmvs/pipzip.rexx
@@ -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
index 0000000..0b9de97
--- /dev/null
+++ b/cmsmvs/zip.exec
@@ -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
index 0000000..b183367
--- /dev/null
+++ b/cmsmvs/zip.makefile
@@ -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
index 0000000..0b9de97
--- /dev/null
+++ b/cmsmvs/zipcloak.exec
@@ -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
index 0000000..6b4b1ca
--- /dev/null
+++ b/cmsmvs/zipmvsc.job
@@ -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
index 0000000..e17fe9c
--- /dev/null
+++ b/cmsmvs/zipname.conven
@@ -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
index 0000000..0b9de97
--- /dev/null
+++ b/cmsmvs/zipnote.exec
@@ -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
index 0000000..0b9de97
--- /dev/null
+++ b/cmsmvs/zipsplit.exec
@@ -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
index 0000000..0ea8962
--- /dev/null
+++ b/cmsmvs/zipup.h
@@ -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
index 0000000..3232649
--- /dev/null
+++ b/cmsmvs/zipvmc.exec
@@ -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
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
index 0000000..d23967b
--- /dev/null
+++ b/crc_i386.S
@@ -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
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
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
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
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
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
index 0000000..5420e59
--- /dev/null
+++ b/file_id.diz
@@ -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
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
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
index 0000000..e50e429
--- /dev/null
+++ b/human68k/Makefile
@@ -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
index 0000000..07864bb
--- /dev/null
+++ b/human68k/Makefile.gcc
@@ -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
index 0000000..cc7c36c
--- /dev/null
+++ b/human68k/crc_68.s
@@ -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
index 0000000..246962c
--- /dev/null
+++ b/human68k/deflate.s
@@ -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
index 0000000..5e489e1
--- /dev/null
+++ b/human68k/human68k.c
@@ -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
index 0000000..4e6bc1c
--- /dev/null
+++ b/human68k/match.s
@@ -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
index 0000000..088a9ac
--- /dev/null
+++ b/human68k/osdep.h
@@ -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
index 0000000..592cff8
--- /dev/null
+++ b/human68k/zipup.h
@@ -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
index 0000000..3aec069
--- /dev/null
+++ b/macos/Contents
@@ -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
index 0000000..2720e55
--- /dev/null
+++ b/macos/HISTORY.TXT
@@ -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
index 0000000..bd69b3d
--- /dev/null
+++ b/macos/README.TXT
@@ -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
index 0000000..e3dacf3
--- /dev/null
+++ b/macos/ZipLib.h
@@ -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
index 0000000..d2b9ae8
--- /dev/null
+++ b/macos/ZipSx.h
@@ -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
index 0000000..5bb3da0
--- /dev/null
+++ b/macos/ZpPrj.hqx
@@ -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
index 0000000..3627016
--- /dev/null
+++ b/macos/osdep.h
@@ -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
index 0000000..012d512
--- /dev/null
+++ b/macos/readme.1st
@@ -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
index 0000000..2d921eb
--- /dev/null
+++ b/macos/source/VolWarn.h
@@ -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
index 0000000..70f041d
--- /dev/null
+++ b/macos/source/charmap.h
@@ -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
index 0000000..83e00a3
--- /dev/null
+++ b/macos/source/extrafld.c
@@ -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
index 0000000..586815d
--- /dev/null
+++ b/macos/source/getenv.c
@@ -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
index 0000000..a7df558
--- /dev/null
+++ b/macos/source/helpers.c
@@ -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
index 0000000..86aa178
--- /dev/null
+++ b/macos/source/helpers.h
@@ -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
index 0000000..17415e1
--- /dev/null
+++ b/macos/source/macglob.h
@@ -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
index 0000000..0f65741
--- /dev/null
+++ b/macos/source/macopen.c
@@ -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
index 0000000..152bceb
--- /dev/null
+++ b/macos/source/macopen.h
@@ -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
index 0000000..3cfee7b
--- /dev/null
+++ b/macos/source/macos.c
@@ -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
index 0000000..0323607
--- /dev/null
+++ b/macos/source/macstuff.c
@@ -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
index 0000000..27c481d
--- /dev/null
+++ b/macos/source/macstuff.h
@@ -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
index 0000000..fcdd440
--- /dev/null
+++ b/macos/source/mactime.c
@@ -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
index 0000000..fa70c7f
--- /dev/null
+++ b/macos/source/mactime.h
@@ -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
index 0000000..166d872
--- /dev/null
+++ b/macos/source/pathname.c
@@ -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
index 0000000..05a9078
--- /dev/null
+++ b/macos/source/pathname.h
@@ -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
index 0000000..e87db3c
--- /dev/null
+++ b/macos/source/recurse.c
@@ -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
index 0000000..cfbc4b0
--- /dev/null
+++ b/macos/source/recurse.h
@@ -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
index 0000000..017d3fa
--- /dev/null
+++ b/macos/source/unixlike.c
@@ -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
index 0000000..e61a354
--- /dev/null
+++ b/macos/source/unixlike.h
@@ -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
index 0000000..99e0d25
--- /dev/null
+++ b/macos/source/zip_rc.hqx
@@ -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
index 0000000..ce2af4a
--- /dev/null
+++ b/macos/zipup.h
@@ -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
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
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
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
index 0000000..a9b5ccb
--- /dev/null
+++ b/msdos/README.DOS
@@ -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
index 0000000..12e85ee
--- /dev/null
+++ b/msdos/crc_i86.asm
@@ -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
index 0000000..0190ba0
--- /dev/null
+++ b/msdos/makefile.bor
@@ -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
index 0000000..b513359
--- /dev/null
+++ b/msdos/makefile.dj1
@@ -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
index 0000000..3ea98ae
--- /dev/null
+++ b/msdos/makefile.dj2
@@ -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
index 0000000..f66b31c
--- /dev/null
+++ b/msdos/makefile.emx
@@ -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
index 0000000..89f0d42
--- /dev/null
+++ b/msdos/makefile.msc
@@ -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
index 0000000..86d6b91
--- /dev/null
+++ b/msdos/makefile.tc
@@ -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
index 0000000..d73fa7f
--- /dev/null
+++ b/msdos/makefile.wat
@@ -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
index 0000000..f126cd7
--- /dev/null
+++ b/msdos/match.asm
@@ -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
index 0000000..77094bf
--- /dev/null
+++ b/msdos/msdos.c
@@ -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
index 0000000..380cd84
--- /dev/null
+++ b/msdos/osdep.h
@@ -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
index 0000000..78b428a
--- /dev/null
+++ b/msdos/zipup.h
@@ -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
index 0000000..8e5e7cf
--- /dev/null
+++ b/os2/makefile.os2
@@ -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
index 0000000..ef9a541
--- /dev/null
+++ b/os2/match32.asm
@@ -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
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
index 0000000..7c5b1fd
--- /dev/null
+++ b/os2/os2acl.c
@@ -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
index 0000000..dd34b2d
--- /dev/null
+++ b/os2/os2acl.h
@@ -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
index 0000000..83bc3bc
--- /dev/null
+++ b/os2/os2zip.c
@@ -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
index 0000000..06d0a02
--- /dev/null
+++ b/os2/os2zip.h
@@ -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
index 0000000..ea2c3f9
--- /dev/null
+++ b/os2/osdep.h
@@ -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
index 0000000..7404eee
--- /dev/null
+++ b/os2/zip.def
@@ -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
index 0000000..592cff8
--- /dev/null
+++ b/os2/zipup.h
@@ -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
index 0000000..3d2a1eb
--- /dev/null
+++ b/packaging/exec-shield.patch
@@ -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
index 0000000..44de3cf
--- /dev/null
+++ b/packaging/zcrypt29.tar.gz
Binary files differ
diff --git a/packaging/zip-2.3-currdir.patch b/packaging/zip-2.3-currdir.patch
new file mode 100644
index 0000000..1ff00f6
--- /dev/null
+++ b/packaging/zip-2.3-currdir.patch
@@ -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
index 0000000..00b09d1
--- /dev/null
+++ b/packaging/zip-2.31-configure.patch
@@ -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
index 0000000..7a1f69f
--- /dev/null
+++ b/packaging/zip-2.31-install.patch
@@ -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
index 0000000..210b183
--- /dev/null
+++ b/packaging/zip-2.31-near-4GB.patch
@@ -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
index 0000000..19846da
--- /dev/null
+++ b/packaging/zip.spec
@@ -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
index 0000000..7ab6005
--- /dev/null
+++ b/packaging/zip23-umask.patch
@@ -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
index 0000000..690630c
--- /dev/null
+++ b/packaging/zip23.patch
@@ -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
index 0000000..32e7823
--- /dev/null
+++ b/proginfo/3rdparty.bug
@@ -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
index 0000000..2d946d3
--- /dev/null
+++ b/proginfo/ZipPorts
@@ -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
index 0000000..867e30b
--- /dev/null
+++ b/proginfo/algorith.txt
@@ -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
index 0000000..769fef1
--- /dev/null
+++ b/proginfo/extra.fld
@@ -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
index 0000000..9d21935
--- /dev/null
+++ b/proginfo/fileinfo.cms
@@ -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
index 0000000..242cd95
--- /dev/null
+++ b/proginfo/infozip.who
@@ -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
index 0000000..8ac31ba
--- /dev/null
+++ b/proginfo/nt.sd
@@ -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
index 0000000..98744ee
--- /dev/null
+++ b/proginfo/perform.dos
@@ -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
index 0000000..6ba2805
--- /dev/null
+++ b/proginfo/txtvsbin.txt
@@ -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
index 0000000..e72d917
--- /dev/null
+++ b/proginfo/ziplimit.txt
@@ -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
index 0000000..9ad1503
--- /dev/null
+++ b/qdos/IZREADME.SMS
@@ -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
index 0000000..1028273
--- /dev/null
+++ b/qdos/Makefile.qdos
@@ -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
index 0000000..e12f004
--- /dev/null
+++ b/qdos/Makefile.qlzip
@@ -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
index 0000000..56a2a85
--- /dev/null
+++ b/qdos/config.s
@@ -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
index 0000000..cf74e47
--- /dev/null
+++ b/qdos/crc68.s
@@ -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
index 0000000..53b3013
--- /dev/null
+++ b/qdos/match.s
@@ -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
index 0000000..72169c1
--- /dev/null
+++ b/qdos/osdep.h
@@ -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
index 0000000..f07f56e
--- /dev/null
+++ b/qdos/qdos.c
@@ -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
index 0000000..07a6bd8
--- /dev/null
+++ b/qdos/qfileio.c
@@ -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
index 0000000..1de3f61
--- /dev/null
+++ b/qdos/zipup.h
@@ -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
index 0000000..d0f4353
--- /dev/null
+++ b/revision.h
@@ -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
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
index 0000000..901f879
--- /dev/null
+++ b/tandem/DOIT
@@ -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
index 0000000..fc74776
--- /dev/null
+++ b/tandem/HISTORY
@@ -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
index 0000000..54dd357
--- /dev/null
+++ b/tandem/README
@@ -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
index 0000000..1acb068
--- /dev/null
+++ b/tandem/commacs
@@ -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
index 0000000..5db5a7d
--- /dev/null
+++ b/tandem/macros
@@ -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
index 0000000..f8a78ce
--- /dev/null
+++ b/tandem/make
@@ -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
index 0000000..291b9a0
--- /dev/null
+++ b/tandem/tandem.c
@@ -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
index 0000000..7868fdd
--- /dev/null
+++ b/tandem/tandem.h
@@ -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
index 0000000..122d8ed
--- /dev/null
+++ b/tandem/tannsk.h
@@ -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
index 0000000..dbd7233
--- /dev/null
+++ b/tandem/tanzip.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
+*/
+/*
+ * 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
index 0000000..f6cd6bb
--- /dev/null
+++ b/tandem/tanzip.h
@@ -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
index 0000000..dd7e24d
--- /dev/null
+++ b/tandem/zipup.h
@@ -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
index 0000000..cb3d6da
--- /dev/null
+++ b/theos/Makefile
@@ -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
index 0000000..1ec99d3
--- /dev/null
+++ b/theos/README
@@ -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
index 0000000..0937b45
--- /dev/null
+++ b/theos/_chmod.c
@@ -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
index 0000000..5c8c927
--- /dev/null
+++ b/theos/_fprintf.c
@@ -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
index 0000000..26f177b
--- /dev/null
+++ b/theos/_isatty.c
@@ -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
index 0000000..04eb204
--- /dev/null
+++ b/theos/_rename.c
@@ -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
index 0000000..d76f955
--- /dev/null
+++ b/theos/_setargv.c
@@ -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
index 0000000..6855d28
--- /dev/null
+++ b/theos/_stat.c
@@ -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
index 0000000..a2d8dfa
--- /dev/null
+++ b/theos/charconv.h
@@ -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
index 0000000..4f4857e
--- /dev/null
+++ b/theos/osdep.h
@@ -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
index 0000000..3a716f8
--- /dev/null
+++ b/theos/stat.h
@@ -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
index 0000000..17db108
--- /dev/null
+++ b/theos/theos.c
@@ -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
index 0000000..1de3f61
--- /dev/null
+++ b/theos/zipup.h
@@ -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
index 0000000..f93fa77
--- /dev/null
+++ b/tops20/make.mic
@@ -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
index 0000000..1f84496
--- /dev/null
+++ b/tops20/osdep.h
@@ -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
index 0000000..6a45d26
--- /dev/null
+++ b/tops20/rename.mic
@@ -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
index 0000000..7230ed3
--- /dev/null
+++ b/tops20/tops20.c
@@ -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
index 0000000..47ec563
--- /dev/null
+++ b/tops20/zipup.h
@@ -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
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
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
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
index 0000000..e1780a0
--- /dev/null
+++ b/unix/Makefile
@@ -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
index 0000000..6b2a451
--- /dev/null
+++ b/unix/Packaging/README
@@ -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
index 0000000..875e144
--- /dev/null
+++ b/unix/Packaging/pkginfo.in
@@ -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
index 0000000..030067d
--- /dev/null
+++ b/unix/Packaging/postinstall
@@ -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
index 0000000..86c4b93
--- /dev/null
+++ b/unix/Packaging/preinstall.in
@@ -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
index 0000000..10e48d8
--- /dev/null
+++ b/unix/Packaging/prototype
@@ -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
index 0000000..6fef92b
--- /dev/null
+++ b/unix/README.OS390
@@ -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
index 0000000..35ccbb7
--- /dev/null
+++ b/unix/configure
@@ -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
index 0000000..bfb5d4d
--- /dev/null
+++ b/unix/osdep.h
@@ -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
index 0000000..024b735
--- /dev/null
+++ b/unix/unix.c
@@ -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
index 0000000..fbec842
--- /dev/null
+++ b/unix/zipup.h
@@ -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
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
index 0000000..aa0dc41
--- /dev/null
+++ b/vms/00binary.vms
@@ -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
index 0000000..020d8ae
--- /dev/null
+++ b/vms/00readme.txt
@@ -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
index 0000000..cae91b3
--- /dev/null
+++ b/vms/cmdline.c
@@ -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).
+**
+*/
+
+
+#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 *);
+
+
+#ifdef TEST
+int
+main(int argc, char **argv)
+{
+ return (vms_zip_cmdline(&argc, &argv));
+}
+#endif /* TEST */
+
+
+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);
+}
+
+
+
+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);
+
+}
+
+
+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);
+}
+
+
+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 */
+}
+
+
+#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
index 0000000..2324d60
--- /dev/null
+++ b/vms/cvthelp.tpu
@@ -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
index 0000000..b44c413
--- /dev/null
+++ b/vms/descrip.mms
@@ -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
index 0000000..54149a3
--- /dev/null
+++ b/vms/link_zip.com
@@ -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
index 0000000..cb7358b
--- /dev/null
+++ b/vms/make_zip.com
@@ -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
index 0000000..99eb179
--- /dev/null
+++ b/vms/makefile.vms
@@ -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
index 0000000..77aee44
--- /dev/null
+++ b/vms/osdep.h
@@ -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
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
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
index 0000000..da84945
--- /dev/null
+++ b/vms/vms_im.c
@@ -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
index 0000000..d1467d3
--- /dev/null
+++ b/vms/vms_pk.c
@@ -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
index 0000000..c9599b0
--- /dev/null
+++ b/vms/vms_zip.rnh
@@ -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
index 0000000..d5ca610
--- /dev/null
+++ b/vms/vmsdefs.h
@@ -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
index 0000000..b40ef45
--- /dev/null
+++ b/vms/vmsmunch.c
@@ -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
index 0000000..53d77b4
--- /dev/null
+++ b/vms/vmsmunch.h
@@ -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
index 0000000..2221644
--- /dev/null
+++ b/vms/vmszip.c
@@ -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
index 0000000..714b23c
--- /dev/null
+++ b/vms/zip_cli.cld
@@ -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
index 0000000..3236e48
--- /dev/null
+++ b/vms/zip_cli.help
@@ -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]
+
+.!
+<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
index 0000000..eea74b6
--- /dev/null
+++ b/vms/zipup.h
@@ -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
index 0000000..d2b31f7
--- /dev/null
+++ b/win32/README.NT
@@ -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
index 0000000..ddce3f8
--- /dev/null
+++ b/win32/README.TZ
@@ -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
index 0000000..7693d75
--- /dev/null
+++ b/win32/crc_i386.asm
@@ -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
index 0000000..e8a2faf
--- /dev/null
+++ b/win32/crc_i386.c
@@ -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
index 0000000..3c7a41c
--- /dev/null
+++ b/win32/crc_lcc.asm
@@ -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
index 0000000..4b5aa4d
--- /dev/null
+++ b/win32/gvmat64.asm
@@ -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
index 0000000..2fde1a4
--- /dev/null
+++ b/win32/lm32_lcc.asm
@@ -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
index 0000000..521950e
--- /dev/null
+++ b/win32/makefile.a64
@@ -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
index 0000000..5f70b81
--- /dev/null
+++ b/win32/makefile.bor
@@ -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
index 0000000..ead72e0
--- /dev/null
+++ b/win32/makefile.dj
@@ -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
index 0000000..197a8ea
--- /dev/null
+++ b/win32/makefile.emx
@@ -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
index 0000000..6e924ad
--- /dev/null
+++ b/win32/makefile.gcc
@@ -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
index 0000000..74acfd9
--- /dev/null
+++ b/win32/makefile.ibm
@@ -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
index 0000000..b40e77c
--- /dev/null
+++ b/win32/makefile.lcc
@@ -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
index 0000000..b5244fc
--- /dev/null
+++ b/win32/makefile.w10
@@ -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
index 0000000..538a614
--- /dev/null
+++ b/win32/makefile.w32
@@ -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
index 0000000..93b41e0
--- /dev/null
+++ b/win32/makefile.wat
@@ -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
index 0000000..5d4e8b5
--- /dev/null
+++ b/win32/match32.asm
@@ -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
index 0000000..6a757b8
--- /dev/null
+++ b/win32/nt.c
@@ -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
index 0000000..72b83af
--- /dev/null
+++ b/win32/nt.h
@@ -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
index 0000000..a867088
--- /dev/null
+++ b/win32/osdep.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
+*/
+/* 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
index 0000000..54b2750
--- /dev/null
+++ b/win32/readme.a64
@@ -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
index 0000000..3df30e8
--- /dev/null
+++ b/win32/rsxntwin.h
@@ -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
index 0000000..f82b335
--- /dev/null
+++ b/win32/vc6/zip.dsp
@@ -0,0 +1,328 @@
+# Microsoft Developer Studio Project File - Name="zip" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=zip - Win32 ASM Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zip.mak".
+!MESSAGE
+!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 "zip.mak" CFG="zip - Win32 ASM Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zip - Win32 ASM Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "zip - Win32 ASM Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "zip - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "zip - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "zip - Win32 ASM Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "zip___Win32_ASM_Release"
+# PROP BASE Intermediate_Dir "zip___Win32_ASM_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "zip___Win32_ASM_Release"
+# PROP Intermediate_Dir "zip___Win32_ASM_Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "ASM_CRC" /D "ASMV" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# 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
+# 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
+
+!ELSEIF "$(CFG)" == "zip - Win32 ASM Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "zip___Win32_ASM_Debug"
+# PROP BASE Intermediate_Dir "zip___Win32_ASM_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "zip___Win32_ASM_Debug"
+# PROP Intermediate_Dir "zip___Win32_ASM_Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "ASM_CRC" /D "ASMV" /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# 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
+# 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
+
+!ELSEIF "$(CFG)" == "zip - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "zip___Win32_Release"
+# PROP BASE Intermediate_Dir "zip___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "zip___Win32_Release"
+# PROP Intermediate_Dir "zip___Win32_Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NO_ASM" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# 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
+# 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
+
+!ELSEIF "$(CFG)" == "zip - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "zip___Win32_Debug"
+# PROP BASE Intermediate_Dir "zip___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "zip___Win32_Debug"
+# PROP Intermediate_Dir "zip___Win32_Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "NO_ASM" /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# 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
+# 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
+
+!ENDIF
+
+# Begin Target
+
+# Name "zip - Win32 ASM Release"
+# Name "zip - Win32 ASM Debug"
+# Name "zip - Win32 Release"
+# Name "zip - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\crc32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\crctab.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\crypt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\deflate.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\fileio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\globals.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\nt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\trees.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\ttyio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\util.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\win32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\win32zip.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zip.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zipfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zipup.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\crypt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\ebcdic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\nt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\osdep.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\revision.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\tailor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\ttyio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\win32zip.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zip.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\ziperr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\zipup.h
+# End Source File
+# End Group
+# Begin Group "Assembler Files"
+
+# PROP Default_Filter "asm;obj"
+# Begin Source File
+
+SOURCE=..\crc_i386.asm
+
+!IF "$(CFG)" == "zip - Win32 ASM Release"
+
+# Begin Custom Build - Assembling...
+IntDir=.\zip___Win32_ASM_Release
+InputPath=..\crc_i386.asm
+InputName=crc_i386
+
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "zip - Win32 ASM Debug"
+
+# Begin Custom Build - Assembling...
+IntDir=.\zip___Win32_ASM_Debug
+InputPath=..\crc_i386.asm
+InputName=crc_i386
+
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
+
+!ELSEIF "$(CFG)" == "zip - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF "$(CFG)" == "zip - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\match32.asm
+
+!IF "$(CFG)" == "zip - Win32 ASM Release"
+
+# Begin Custom Build - Assembling...
+IntDir=.\zip___Win32_ASM_Release
+InputPath=..\match32.asm
+InputName=match32
+
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "zip - Win32 ASM Debug"
+
+# Begin Custom Build - Assembling...
+IntDir=.\zip___Win32_ASM_Debug
+InputPath=..\match32.asm
+InputName=match32
+
+"$(IntDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ ml /nologo /c /Cx /coff /Zi /Fo"$(IntDir)\$(InputName).obj" "$(InputPath)"
+
+!ELSEIF "$(CFG)" == "zip - Win32 Release"
+
+# PROP Exclude_From_Build 1
+
+!ELSEIF "$(CFG)" == "zip - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/win32/vc6/zip.dsw b/win32/vc6/zip.dsw
new file mode 100644
index 0000000..681d183
--- /dev/null
+++ b/win32/vc6/zip.dsw
@@ -0,0 +1,65 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "zip"=".\zip.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "zipcloak"=".\zipcloak.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "zipnote"=".\zipnote.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "zipsplit"=".\zipsplit.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/win32/vc6/zipcloak.dsp b/win32/vc6/zipcloak.dsp
new file mode 100644
index 0000000..dac83fa
--- /dev/null
+++ b/win32/vc6/zipcloak.dsp
@@ -0,0 +1,164 @@
+# Microsoft Developer Studio Project File - Name="zipcloak" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=zipcloak - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zipcloak.mak".
+!MESSAGE
+!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 "zipcloak.mak" CFG="zipcloak - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zipcloak - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "zipcloak - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "zipcloak - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "zipcloak___Win32_Release"
+# PROP BASE Intermediate_Dir "zipcloak___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "zipcloak___Win32_Release"
+# PROP Intermediate_Dir "zipcloak___Win32_Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "UTIL" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# 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
+# 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
+
+!ELSEIF "$(CFG)" == "zipcloak - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "zipcloak___Win32_Debug"
+# PROP BASE Intermediate_Dir "zipcloak___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "zipcloak___Win32_Debug"
+# PROP Intermediate_Dir "zipcloak___Win32_Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "UTIL" /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# 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
+# 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
+
+!ENDIF
+
+# Begin Target
+
+# Name "zipcloak - Win32 Release"
+# Name "zipcloak - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\crctab.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\crypt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\fileio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\globals.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\ttyio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\util.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\win32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zipcloak.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zipfile.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\crypt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\ebcdic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\osdep.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\revision.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\tailor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\ttyio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\win32zip.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zip.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\ziperr.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/win32/vc6/zipnote.dsp b/win32/vc6/zipnote.dsp
new file mode 100644
index 0000000..e32e2f1
--- /dev/null
+++ b/win32/vc6/zipnote.dsp
@@ -0,0 +1,144 @@
+# Microsoft Developer Studio Project File - Name="zipnote" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=zipnote - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zipnote.mak".
+!MESSAGE
+!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 "zipnote.mak" CFG="zipnote - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zipnote - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "zipnote - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "zipnote - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "zipnote___Win32_Release"
+# PROP BASE Intermediate_Dir "zipnote___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "zipnote___Win32_Release"
+# PROP Intermediate_Dir "zipnote___Win32_Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "UTIL" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# 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
+# 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
+
+!ELSEIF "$(CFG)" == "zipnote - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "zipnote___Win32_Debug"
+# PROP BASE Intermediate_Dir "zipnote___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "zipnote___Win32_Debug"
+# PROP Intermediate_Dir "zipnote___Win32_Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "UTIL" /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# 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
+# 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
+
+!ENDIF
+
+# Begin Target
+
+# Name "zipnote - Win32 Release"
+# Name "zipnote - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\fileio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\globals.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\util.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\win32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zipfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zipnote.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\ebcdic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\osdep.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\revision.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\tailor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\win32zip.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zip.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\ziperr.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/win32/vc6/zipsplit.dsp b/win32/vc6/zipsplit.dsp
new file mode 100644
index 0000000..aec7139
--- /dev/null
+++ b/win32/vc6/zipsplit.dsp
@@ -0,0 +1,144 @@
+# Microsoft Developer Studio Project File - Name="zipsplit" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=zipsplit - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zipsplit.mak".
+!MESSAGE
+!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 "zipsplit.mak" CFG="zipsplit - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "zipsplit - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "zipsplit - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "zipsplit - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "zipsplit___Win32_Release"
+# PROP BASE Intermediate_Dir "zipsplit___Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "zipsplit___Win32_Release"
+# PROP Intermediate_Dir "zipsplit___Win32_Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "UTIL" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# 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
+# 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
+
+!ELSEIF "$(CFG)" == "zipsplit - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "zipsplit___Win32_Debug"
+# PROP BASE Intermediate_Dir "zipsplit___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "zipsplit___Win32_Debug"
+# PROP Intermediate_Dir "zipsplit___Win32_Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "UTIL" /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# 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
+# 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
+
+!ENDIF
+
+# Begin Target
+
+# Name "zipsplit - Win32 Release"
+# Name "zipsplit - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\fileio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\globals.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\util.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\win32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zipfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zipsplit.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\ebcdic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\osdep.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\revision.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\tailor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\win32zip.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\zip.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\ziperr.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/win32/win32.c b/win32/win32.c
new file mode 100644
index 0000000..88bd565
--- /dev/null
+++ b/win32/win32.c
@@ -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
index 0000000..b9d5e2d
--- /dev/null
+++ b/win32/win32zip.c
@@ -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
index 0000000..8ecb74c
--- /dev/null
+++ b/win32/win32zip.h
@@ -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
index 0000000..105e4b9
--- /dev/null
+++ b/win32/zip.def
@@ -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
index 0000000..f65c41e
--- /dev/null
+++ b/win32/zipup.h
@@ -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
index 0000000..c063c26
--- /dev/null
+++ b/windll/contents
@@ -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
index 0000000..05939af
--- /dev/null
+++ b/windll/example.c
@@ -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
index 0000000..0061d5e
--- /dev/null
+++ b/windll/example.h
@@ -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
index 0000000..be10954
--- /dev/null
+++ b/windll/resource.h
@@ -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
index 0000000..f3c11a5
--- /dev/null
+++ b/windll/structs.h
@@ -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
index 0000000..907a008
--- /dev/null
+++ b/windll/vb/VBZIP.vbw
@@ -0,0 +1,2 @@
+Form1 = 22, 22, 668, 535, , 22, 22, 456, 360, C
+VBZipBas = 68, 5, 691, 512,
diff --git a/windll/vb/VBZipBas.bas b/windll/vb/VBZipBas.bas
new file mode 100644
index 0000000..18ec77a
--- /dev/null
+++ b/windll/vb/VBZipBas.bas
@@ -0,0 +1,455 @@
+Attribute VB_Name = "VBZipBas"
+
+Option Explicit
+
+'---------------------------------------------------------------
+'-- Please Do Not Remove These Comments!!!
+'---------------------------------------------------------------
+'-- Sample VB 5 code to drive zip32.dll
+'-- Contributed to the Info-ZIP project by Mike Le Voi
+'--
+'-- Contact me at: mlevoi@modemss.brisnet.org.au
+'--
+'-- Visit my home page at: http://modemss.brisnet.org.au/~mlevoi
+'--
+'-- Use this code at your own risk. Nothing implied or warranted
+'-- to work on your machine :-)
+'---------------------------------------------------------------
+'--
+'-- The Source Code Is Freely Available From Info-ZIP At:
+'-- http://www.cdrom.com/pub/infozip/infozip.html
+'--
+'-- A Very Special Thanks To Mr. Mike Le Voi
+'-- And Mr. Mike White Of The Info-ZIP
+'-- For Letting Me Use And Modify His Orginal
+'-- Visual Basic 5.0 Code! Thank You Mike Le Voi.
+'---------------------------------------------------------------
+'--
+'-- Contributed To The Info-ZIP Project By Raymond L. King
+'-- Modified June 21, 1998
+'-- By Raymond L. King
+'-- Custom Software Designers
+'--
+'-- Contact Me At: king@ntplx.net
+'-- ICQ 434355
+'-- Or Visit Our Home Page At: http://www.ntplx.net/~king
+'--
+'---------------------------------------------------------------
+'
+' This is the original example with some small changes. Only
+' use with the original Zip32.dll (Zip 2.3). Do not use this VB
+' example with Zip32z64.dll (Zip 3.0).
+'
+' 4/29/2004 Ed Gordon
+
+'---------------------------------------------------------------
+' Usage notes:
+'
+' This code uses Zip32.dll. You DO NOT need to register the
+' DLL to use it. You also DO NOT need to reference it in your
+' VB project. You DO have to copy the DLL to your SYSTEM
+' directory, your VB project directory, or place it in a directory
+' on your command PATH.
+'
+' A bug has been found in the Zip32.dll when called from VB. If
+' you try to pass any values other than NULL in the ZPOPT strings
+' Date, szRootDir, or szTempDir they get converted from the
+' VB internal wide character format to temporary byte strings by
+' the calling interface as they are supposed to. However when
+' ZpSetOptions returns the passed strings are deallocated unless the
+' VB debugger prevents it by a break between ZpSetOptions and
+' ZpArchive. When Zip32.dll uses these pointers later it
+' can result in unpredictable behavior. A kluge is available
+' for Zip32.dll, just replacing api.c in Zip 2.3, but better to just
+' use the new Zip32z64.dll where these bugs are fixed. However,
+' the kluge has been added to Zip 2.31. To determine the version
+' of the dll you have right click on it, select the Version tab,
+' and verify the Product Version is at least 2.31.
+'
+' Another bug is where -R is used with some other options and can
+' crash the dll. This is a bug in how zip processes the command
+' line and should be mostly fixed in Zip 2.31. If you run into
+' problems try using -r instead for recursion. The bug is fixed
+' in Zip 3.0 but note that Zip 3.0 creates dll zip32z64.dll and
+' it is not compatible with older VB including this example. See
+' the new VB example code included with Zip 3.0 for calling
+' interface changes.
+'
+' Note that Zip32 is probably not thread safe. It may be made
+' thread safe in a later version, but for now only one thread in
+' one program should use the DLL at a time. Unlike Zip, UnZip is
+' probably thread safe, but an exception to this has been
+' found. See the UnZip documentation for the latest on this.
+'
+' All code in this VB project is provided under the Info-Zip license.
+'
+' If you have any questions please contact Info-Zip at
+' http://www.info-zip.org.
+'
+' 4/29/2004 EG (Updated 3/1/2005 EG)
+'
+'---------------------------------------------------------------
+
+
+'-- C Style argv
+'-- Holds The Zip Archive Filenames
+' Max for this just over 8000 as each pointer takes up 4 bytes and
+' VB only allows 32 kB of local variables and that includes function
+' parameters. - 3/19/2004 EG
+'
+Public Type ZIPnames
+ zFiles(0 To 99) As String
+End Type
+
+'-- Call Back "String"
+Public Type ZipCBChar
+ ch(4096) As Byte
+End Type
+
+'-- ZPOPT Is Used To Set The Options In The ZIP32.DLL
+Public Type ZPOPT
+ Date As String ' US Date (8 Bytes Long) "12/31/98"?
+ szRootDir As String ' Root Directory Pathname (Up To 256 Bytes Long)
+ szTempDir As String ' Temp Directory Pathname (Up To 256 Bytes Long)
+ fTemp As Long ' 1 If Temp dir Wanted, Else 0
+ fSuffix As Long ' Include Suffixes (Not Yet Implemented!)
+ fEncrypt As Long ' 1 If Encryption Wanted, Else 0
+ fSystem As Long ' 1 To Include System/Hidden Files, Else 0
+ fVolume As Long ' 1 If Storing Volume Label, Else 0
+ fExtra As Long ' 1 If Excluding Extra Attributes, Else 0
+ fNoDirEntries As Long ' 1 If Ignoring Directory Entries, Else 0
+ fExcludeDate As Long ' 1 If Excluding Files Earlier Than Specified Date, Else 0
+ fIncludeDate As Long ' 1 If Including Files Earlier Than Specified Date, Else 0
+ fVerbose As Long ' 1 If Full Messages Wanted, Else 0
+ fQuiet As Long ' 1 If Minimum Messages Wanted, Else 0
+ fCRLF_LF As Long ' 1 If Translate CR/LF To LF, Else 0
+ fLF_CRLF As Long ' 1 If Translate LF To CR/LF, Else 0
+ fJunkDir As Long ' 1 If Junking Directory Names, Else 0
+ fGrow As Long ' 1 If Allow Appending To Zip File, Else 0
+ fForce As Long ' 1 If Making Entries Using DOS File Names, Else 0
+ fMove As Long ' 1 If Deleting Files Added Or Updated, Else 0
+ fDeleteEntries As Long ' 1 If Files Passed Have To Be Deleted, Else 0
+ fUpdate As Long ' 1 If Updating Zip File-Overwrite Only If Newer, Else 0
+ fFreshen As Long ' 1 If Freshing Zip File-Overwrite Only, Else 0
+ fJunkSFX As Long ' 1 If Junking SFX Prefix, Else 0
+ fLatestTime As Long ' 1 If Setting Zip File Time To Time Of Latest File In Archive, Else 0
+ fComment As Long ' 1 If Putting Comment In Zip File, Else 0
+ fOffsets As Long ' 1 If Updating Archive Offsets For SFX Files, Else 0
+ fPrivilege As Long ' 1 If Not Saving Privileges, Else 0
+ fEncryption As Long ' Read Only Property!!!
+ fRecurse As Long ' 1 (-r), 2 (-R) If Recursing Into Sub-Directories, Else 0
+ fRepair As Long ' 1 = Fix Archive, 2 = Try Harder To Fix, Else 0
+ flevel As Byte ' Compression Level - 0 = Stored 6 = Default 9 = Max
+End Type
+
+'-- This Structure Is Used For The ZIP32.DLL Function Callbacks
+Public Type ZIPUSERFUNCTIONS
+ ZDLLPrnt As Long ' Callback ZIP32.DLL Print Function
+ ZDLLCOMMENT As Long ' Callback ZIP32.DLL Comment Function
+ ZDLLPASSWORD As Long ' Callback ZIP32.DLL Password Function
+ ZDLLSERVICE As Long ' Callback ZIP32.DLL Service Function
+End Type
+
+'-- Local Declarations
+Public ZOPT As ZPOPT
+Public ZUSER As ZIPUSERFUNCTIONS
+
+'-- This Assumes ZIP32.DLL Is In Your \Windows\System Directory!
+'-- (alternatively, a copy of ZIP32.DLL needs to be located in the program
+'-- directory or in some other directory listed in PATH.)
+Private Declare Function ZpInit Lib "zip32.dll" _
+ (ByRef Zipfun As ZIPUSERFUNCTIONS) As Long '-- Set Zip Callbacks
+
+Private Declare Function ZpSetOptions Lib "zip32.dll" _
+ (ByRef Opts As ZPOPT) As Long '-- Set Zip Options
+
+Private Declare Function ZpGetOptions Lib "zip32.dll" _
+ () As ZPOPT '-- Used To Check Encryption Flag Only
+
+Private Declare Function ZpArchive Lib "zip32.dll" _
+ (ByVal argc As Long, ByVal funame As String, _
+ ByRef argv As ZIPnames) As Long '-- Real Zipping Action
+
+'-------------------------------------------------------
+'-- Public Variables For Setting The ZPOPT Structure...
+'-- (WARNING!!!) You Must Set The Options That You
+'-- Want The ZIP32.DLL To Do!
+'-- Before Calling VBZip32!
+'--
+'-- NOTE: See The Above ZPOPT Structure Or The VBZip32
+'-- Function, For The Meaning Of These Variables
+'-- And How To Use And Set Them!!!
+'-- These Parameters Must Be Set Before The Actual Call
+'-- To The VBZip32 Function!
+'-------------------------------------------------------
+Public zDate As String
+Public zRootDir As String
+Public zTempDir As String
+Public zSuffix As Integer
+Public zEncrypt As Integer
+Public zSystem As Integer
+Public zVolume As Integer
+Public zExtra As Integer
+Public zNoDirEntries As Integer
+Public zExcludeDate As Integer
+Public zIncludeDate As Integer
+Public zVerbose As Integer
+Public zQuiet As Integer
+Public zCRLF_LF As Integer
+Public zLF_CRLF As Integer
+Public zJunkDir As Integer
+Public zRecurse As Integer
+Public zGrow As Integer
+Public zForce As Integer
+Public zMove As Integer
+Public zDelEntries As Integer
+Public zUpdate As Integer
+Public zFreshen As Integer
+Public zJunkSFX As Integer
+Public zLatestTime As Integer
+Public zComment As Integer
+Public zOffsets As Integer
+Public zPrivilege As Integer
+Public zEncryption As Integer
+Public zRepair As Integer
+Public zLevel As Integer
+
+'-- Public Program Variables
+Public zArgc As Integer ' Number Of Files To Zip Up
+Public zZipFileName As String ' The Zip File Name ie: Myzip.zip
+Public zZipFileNames As ZIPnames ' File Names To Zip Up
+Public zZipInfo As String ' Holds The Zip File Information
+
+'-- Public Constants
+'-- For Zip & UnZip Error Codes!
+Public Const ZE_OK = 0 ' Success (No Error)
+Public Const ZE_EOF = 2 ' Unexpected End Of Zip File Error
+Public Const ZE_FORM = 3 ' Zip File Structure Error
+Public Const ZE_MEM = 4 ' Out Of Memory Error
+Public Const ZE_LOGIC = 5 ' Internal Logic Error
+Public Const ZE_BIG = 6 ' Entry Too Large To Split Error
+Public Const ZE_NOTE = 7 ' Invalid Comment Format Error
+Public Const ZE_TEST = 8 ' Zip Test (-T) Failed Or Out Of Memory Error
+Public Const ZE_ABORT = 9 ' User Interrupted Or Termination Error
+Public Const ZE_TEMP = 10 ' Error Using A Temp File
+Public Const ZE_READ = 11 ' Read Or Seek Error
+Public Const ZE_NONE = 12 ' Nothing To Do Error
+Public Const ZE_NAME = 13 ' Missing Or Empty Zip File Error
+Public Const ZE_WRITE = 14 ' Error Writing To A File
+Public Const ZE_CREAT = 15 ' Could't Open To Write Error
+Public Const ZE_PARMS = 16 ' Bad Command Line Argument Error
+Public Const ZE_OPEN = 18 ' Could Not Open A Specified File To Read Error
+
+'-- These Functions Are For The ZIP32.DLL
+'--
+'-- Puts A Function Pointer In A Structure
+'-- For Use With Callbacks...
+Public Function FnPtr(ByVal lp As Long) As Long
+
+ FnPtr = lp
+
+End Function
+
+'-- Callback For ZIP32.DLL - DLL Print Function
+Public Function ZDLLPrnt(ByRef fname As ZipCBChar, ByVal x As Long) As Long
+
+ Dim s0 As String
+ Dim xx As Long
+
+ '-- Always Put This In Callback Routines!
+ On Error Resume Next
+
+ s0 = ""
+
+ '-- Get Zip32.DLL Message For processing
+ For xx = 0 To x
+ If fname.ch(xx) = 0 Then
+ Exit For
+ Else
+ s0 = s0 + Chr(fname.ch(xx))
+ End If
+ Next
+
+ '----------------------------------------------
+ '-- This Is Where The DLL Passes Back Messages
+ '-- To You! You Can Change The Message Printing
+ '-- Below Here!
+ '----------------------------------------------
+
+ '-- Display Zip File Information
+ '-- zZipInfo = zZipInfo & s0
+ Form1.Print s0;
+
+ DoEvents
+
+ ZDLLPrnt = 0
+
+End Function
+
+'-- Callback For ZIP32.DLL - DLL Service Function
+Public Function ZDLLServ(ByRef mname As ZipCBChar, ByVal x As Long) As Long
+
+ ' x is the size of the file
+
+ Dim s0 As String
+ Dim xx As Long
+
+ '-- Always Put This In Callback Routines!
+ On Error Resume Next
+
+ s0 = ""
+ '-- Get Zip32.DLL Message For processing
+ For xx = 0 To 4096
+ If mname.ch(xx) = 0 Then
+ Exit For
+ Else
+ s0 = s0 + Chr(mname.ch(xx))
+ End If
+ Next
+ ' Form1.Print "-- " & s0 & " - " & x & " bytes"
+
+ ' This is called for each zip entry.
+ ' mname is usually the null terminated file name and x the file size.
+ ' s0 has trimmed file name as VB string.
+
+ ' At this point, s0 contains the message passed from the DLL
+ ' It is up to the developer to code something useful here :)
+ ZDLLServ = 0 ' Setting this to 1 will abort the zip!
+
+End Function
+
+'-- Callback For ZIP32.DLL - DLL Password Function
+Public Function ZDLLPass(ByRef p As ZipCBChar, _
+ ByVal n As Long, ByRef m As ZipCBChar, _
+ ByRef Name As ZipCBChar) As Integer
+
+ Dim prompt As String
+ Dim xx As Integer
+ Dim szpassword As String
+
+ '-- Always Put This In Callback Routines!
+ On Error Resume Next
+
+ ZDLLPass = 1
+
+ '-- If There Is A Password Have The User Enter It!
+ '-- This Can Be Changed
+ szpassword = InputBox("Please Enter The Password!")
+
+ '-- The User Did Not Enter A Password So Exit The Function
+ If szpassword = "" Then Exit Function
+
+ '-- User Entered A Password So Proccess It
+ For xx = 0 To 255
+ If m.ch(xx) = 0 Then
+ Exit For
+ Else
+ prompt = prompt & Chr(m.ch(xx))
+ End If
+ Next
+
+ For xx = 0 To n - 1
+ p.ch(xx) = 0
+ Next
+
+ For xx = 0 To Len(szpassword) - 1
+ p.ch(xx) = Asc(Mid(szpassword, xx + 1, 1))
+ Next
+
+ p.ch(xx) = Chr(0) ' Put Null Terminator For C
+
+ ZDLLPass = 0
+
+End Function
+
+'-- Callback For ZIP32.DLL - DLL Comment Function
+Public Function ZDLLComm(ByRef s1 As ZipCBChar) As Integer
+
+ Dim xx%, szcomment$
+
+ '-- Always Put This In Callback Routines!
+ On Error Resume Next
+
+ ZDLLComm = 1
+ szcomment = InputBox("Enter the comment")
+ If szcomment = "" Then Exit Function
+ For xx = 0 To Len(szcomment) - 1
+ s1.ch(xx) = Asc(Mid$(szcomment, xx + 1, 1))
+ Next xx
+ s1.ch(xx) = Chr(0) ' Put null terminator for C
+
+End Function
+
+'-- Main ZIP32.DLL Subroutine.
+'-- This Is Where It All Happens!!!
+'--
+'-- (WARNING!) Do Not Change This Function!!!
+'--
+Public Function VBZip32() As Long
+
+ Dim retcode As Long
+
+ On Error Resume Next '-- Nothing Will Go Wrong :-)
+
+ retcode = 0
+
+ '-- Set Address Of ZIP32.DLL Callback Functions
+ '-- (WARNING!) Do Not Change!!!
+ ZUSER.ZDLLPrnt = FnPtr(AddressOf ZDLLPrnt)
+ ZUSER.ZDLLPASSWORD = FnPtr(AddressOf ZDLLPass)
+ ZUSER.ZDLLCOMMENT = FnPtr(AddressOf ZDLLComm)
+ ZUSER.ZDLLSERVICE = FnPtr(AddressOf ZDLLServ)
+
+ '-- Set ZIP32.DLL Callbacks
+ retcode = ZpInit(ZUSER)
+ If retcode = 0 Then
+ MsgBox "Zip32.dll did not initialize. Is it in the current directory " & _
+ "or on the command path?", vbOKOnly, "VB Zip"
+ Exit Function
+ End If
+
+ '-- Setup ZIP32 Options
+ '-- (WARNING!) Do Not Change!
+ ZOPT.Date = zDate ' "12/31/79"? US Date?
+ ZOPT.szRootDir = zRootDir ' Root Directory Pathname
+ ZOPT.szTempDir = zTempDir ' Temp Directory Pathname
+ ZOPT.fSuffix = zSuffix ' Include Suffixes (Not Yet Implemented)
+ ZOPT.fEncrypt = zEncrypt ' 1 If Encryption Wanted
+ ZOPT.fSystem = zSystem ' 1 To Include System/Hidden Files
+ ZOPT.fVolume = zVolume ' 1 If Storing Volume Label
+ ZOPT.fExtra = zExtra ' 1 If Including Extra Attributes
+ ZOPT.fNoDirEntries = zNoDirEntries ' 1 If Ignoring Directory Entries
+ ZOPT.fExcludeDate = zExcludeDate ' 1 If Excluding Files Earlier Than A Specified Date
+ ZOPT.fIncludeDate = zIncludeDate ' 1 If Including Files Earlier Than A Specified Date
+ ZOPT.fVerbose = zVerbose ' 1 If Full Messages Wanted
+ ZOPT.fQuiet = zQuiet ' 1 If Minimum Messages Wanted
+ ZOPT.fCRLF_LF = zCRLF_LF ' 1 If Translate CR/LF To LF
+ ZOPT.fLF_CRLF = zLF_CRLF ' 1 If Translate LF To CR/LF
+ ZOPT.fJunkDir = zJunkDir ' 1 If Junking Directory Names
+ ZOPT.fGrow = zGrow ' 1 If Allow Appending To Zip File
+ ZOPT.fForce = zForce ' 1 If Making Entries Using DOS Names
+ ZOPT.fMove = zMove ' 1 If Deleting Files Added Or Updated
+ ZOPT.fDeleteEntries = zDelEntries ' 1 If Files Passed Have To Be Deleted
+ ZOPT.fUpdate = zUpdate ' 1 If Updating Zip File-Overwrite Only If Newer
+ ZOPT.fFreshen = zFreshen ' 1 If Freshening Zip File-Overwrite Only
+ ZOPT.fJunkSFX = zJunkSFX ' 1 If Junking SFX Prefix
+ ZOPT.fLatestTime = zLatestTime ' 1 If Setting Zip File Time To Time Of Latest File In Archive
+ ZOPT.fComment = zComment ' 1 If Putting Comment In Zip File
+ ZOPT.fOffsets = zOffsets ' 1 If Updating Archive Offsets For SFX Files
+ ZOPT.fPrivilege = zPrivilege ' 1 If Not Saving Privelages
+ ZOPT.fEncryption = zEncryption ' Read Only Property!
+ ZOPT.fRecurse = zRecurse ' 1 or 2 If Recursing Into Subdirectories
+ ZOPT.fRepair = zRepair ' 1 = Fix Archive, 2 = Try Harder To Fix
+ ZOPT.flevel = zLevel ' Compression Level - (0 To 9) Should Be 0!!!
+
+ '-- Set ZIP32.DLL Options
+ retcode = ZpSetOptions(ZOPT)
+
+ '-- Go Zip It Them Up!
+ retcode = ZpArchive(zArgc, zZipFileName, zZipFileNames)
+
+ '-- Return The Function Code
+ VBZip32 = retcode
+
+End Function
+
diff --git a/windll/vb/Vbzip.vbp b/windll/vb/Vbzip.vbp
new file mode 100644
index 0000000..b5e5827
--- /dev/null
+++ b/windll/vb/Vbzip.vbp
@@ -0,0 +1,34 @@
+Type=Exe
+Form=Vbzipfrm.frm
+Module=VBZipBas; VBZipBas.bas
+IconForm="Form1"
+Startup="Form1"
+HelpFile=""
+Title="VBZIP"
+ExeName32="VBZIP.exe"
+Path32="..\..\.."
+Command32=""
+Name="Project1"
+HelpContextID="0"
+CompatibleMode="0"
+MajorVer=1
+MinorVer=0
+RevisionVer=0
+AutoIncrementVer=0
+ServerSupportFiles=0
+VersionCompanyName="Mike"
+CompilationType=-1
+OptimizationType=0
+FavorPentiumPro(tm)=0
+CodeViewDebugInfo=0
+NoAliasing=0
+BoundsCheck=0
+OverflowCheck=0
+FlPointCheck=0
+FDIVCheck=0
+UnroundedFP=0
+StartMode=0
+Unattended=0
+Retained=0
+ThreadPerObject=0
+MaxNumberOfThreads=1
diff --git a/windll/vb/Vbzipfrm.frm b/windll/vb/Vbzipfrm.frm
new file mode 100644
index 0000000..de323cd
--- /dev/null
+++ b/windll/vb/Vbzipfrm.frm
@@ -0,0 +1,130 @@
+VERSION 5.00
+Begin VB.Form Form1
+ AutoRedraw = -1 'True
+ Caption = "Form1"
+ ClientHeight = 3150
+ ClientLeft = 60
+ ClientTop = 345
+ ClientWidth = 6570
+ BeginProperty Font
+ Name = "MS Sans Serif"
+ Size = 9.75
+ Charset = 0
+ Weight = 700
+ Underline = 0 'False
+ Italic = 0 'False
+ Strikethrough = 0 'False
+ EndProperty
+ LinkTopic = "Form1"
+ ScaleHeight = 3150
+ ScaleWidth = 6570
+ StartUpPosition = 1 'CenterOwner
+End
+Attribute VB_Name = "Form1"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+
+Option Explicit
+
+'---------------------------------------------------------------
+'-- Please Do Not Remove These Comments!!!
+'---------------------------------------------------------------
+'-- Sample VB 5 code to drive zip32.dll
+'-- Contributed to the Info-ZIP project by Mike Le Voi
+'--
+'-- Contact me at: mlevoi@modemss.brisnet.org.au
+'--
+'-- Visit my home page at: http://modemss.brisnet.org.au/~mlevoi
+'--
+'-- Use this code at your own risk. Nothing implied or warranted
+'-- to work on your machine :-)
+'---------------------------------------------------------------
+'--
+'-- The Source Code Is Freely Available From Info-ZIP At:
+'-- http://www.cdrom.com/pub/infozip/infozip.html
+'--
+'-- A Very Special Thanks To Mr. Mike Le Voi
+'-- And Mr. Mike White Of The Info-ZIP project
+'-- For Letting Me Use And Modify His Orginal
+'-- Visual Basic 5.0 Code! Thank You Mike Le Voi.
+'---------------------------------------------------------------
+'--
+'-- Contributed To The Info-ZIP Project By Raymond L. King
+'-- Modified June 21, 1998
+'-- By Raymond L. King
+'-- Custom Software Designers
+'--
+'-- Contact Me At: king@ntplx.net
+'-- ICQ 434355
+'-- Or Visit Our Home Page At: http://www.ntplx.net/~king
+'--
+'---------------------------------------------------------------
+' This is the original VB example (with some changes) for use
+' with Zip32.dll (Zip 2.31) but not Zip32z64.dll (Zip 3.0).
+'
+' Minor changes to use current directory and VB project files
+' for the example and to turn off encryption.
+'
+' The VB example provided with Zip 3.0 is more extensive. Even
+' if you plan to use the updated zip32.dll instead of the new
+' zip32z64.dll (Zip 3.0), there may be some things you might find
+' useful in the VB example there.
+'
+' 2/27/2005 Ed Gordon
+'---------------------------------------------------------------
+
+Private Sub Form_Click()
+
+ Dim retcode As Integer ' For Return Code From ZIP32.DLL
+
+ Cls
+
+ '-- Set Options - Only The Common Ones Are Shown Here
+ '-- These Must Be Set Before Calling The VBZip32 Function
+ zDate = vbNullString
+ 'zDate = "2005-1-31"
+ 'zExcludeDate = 1
+ 'zIncludeDate = 0
+ zJunkDir = 0 ' 1 = Throw Away Path Names
+ zRecurse = 0 ' 1 = Recurse -r 2 = Recurse -R 2 = Most Useful :)
+ zUpdate = 0 ' 1 = Update Only If Newer
+ zFreshen = 0 ' 1 = Freshen - Overwrite Only
+ zLevel = Asc(9) ' Compression Level (0 - 9)
+ zEncrypt = 0 ' Encryption = 1 For Password Else 0
+ zComment = 0 ' Comment = 1 if required
+
+ '-- Select Some Files - Wildcards Are Supported
+ '-- Change The Paths Here To Your Directory
+ '-- And Files!!!
+ ' Change ZIPnames in VBZipBas.bas if need more than 100 files
+ zArgc = 2 ' Number Of Elements Of mynames Array
+ zZipFileName = "MyFirst.zip"
+ zZipFileNames.zFiles(0) = "vbzipfrm.frm"
+ zZipFileNames.zFiles(1) = "vbzip.vbp"
+ zRootDir = "" ' This Affects The Stored Path Name
+
+ ' Older versions of Zip32.dll do not handle setting
+ ' zRootDir to anything other than "". If you need to
+ ' change root directory an alternative is to just change
+ ' directory. This requires Zip32.dll to be on the command
+ ' path. This should be fixed in Zip 2.31. 1/31/2005 EG
+
+ ' ChDir "a"
+
+ '-- Go Zip Them Up!
+ retcode = VBZip32
+
+ '-- Display The Returned Code Or Error!
+ Print "Return code:" & Str(retcode)
+
+End Sub
+
+Private Sub Form_Load()
+
+ Me.Show
+
+ Print "Click me!"
+
+End Sub
diff --git a/windll/vb/readmeVB.txt b/windll/vb/readmeVB.txt
new file mode 100644
index 0000000..f1fc19f
--- /dev/null
+++ b/windll/vb/readmeVB.txt
@@ -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
index 0000000..91d01d8
--- /dev/null
+++ b/windll/visualc/dll/zip32.dsp
@@ -0,0 +1,168 @@
+# Microsoft Developer Studio Project File - Name="zip32" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=zip32 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zip32.mak".
+!MESSAGE
+!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
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "zip32 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\Release\app"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "_WINDOWS" /D "WIN32" /YX /FD /c
+# 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
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG" /d "WIN32"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386
+
+!ELSEIF "$(CFG)" == "zip32 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\Debug\app"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "_WINDOWS" /D "WIN32" /YX /FD /c
+# 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
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG" /d "WIN32"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# SUBTRACT LINK32 /map
+
+!ENDIF
+
+# Begin Target
+
+# Name "zip32 - Win32 Release"
+# Name "zip32 - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\..\api.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\crc32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\crctab.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\crypt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\deflate.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\fileio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\globals.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\win32\nt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\trees.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\ttyio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\util.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\win32\win32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\win32\win32zip.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\windll\windll.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\windll\windll.rc
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\windll\windll32.def
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\zip.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\zipfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\zipup.c
+# End Source File
+# End Target
+# End Project
diff --git a/windll/visualc/dll/zip32.dsw b/windll/visualc/dll/zip32.dsw
new file mode 100644
index 0000000..cb9248d
--- /dev/null
+++ b/windll/visualc/dll/zip32.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "zip32"=.\zip32.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/windll/visualc/dll/zip32.mak b/windll/visualc/dll/zip32.mak
new file mode 100644
index 0000000..c3e33a6
--- /dev/null
+++ b/windll/visualc/dll/zip32.mak
@@ -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
index 0000000..d23896c
--- /dev/null
+++ b/windll/visualc/lib/zip32.dsp
@@ -0,0 +1,162 @@
+# Microsoft Developer Studio Project File - Name="zip32" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=zip32 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "zip32.mak".
+!MESSAGE
+!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
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "zip32 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\Release\libs"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "_WINDOWS" /D "WIN32" /YX /FD /c
+# 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
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "zip32 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\Debug\libs"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "_DEBUG" /D "_WINDOWS" /D "WIN32" /YX /FD /c
+# 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
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "zip32 - Win32 Release"
+# Name "zip32 - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\..\api.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\crc32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\crctab.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\crypt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\deflate.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\fileio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\globals.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\win32\nt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\trees.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\ttyio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\util.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\win32\win32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\win32\win32zip.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\windll\windll.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\windll\windll.rc
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\zip.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\zipfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\windll\ziplib.def
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\zipup.c
+# End Source File
+# End Target
+# End Project
diff --git a/windll/visualc/lib/zip32.dsw b/windll/visualc/lib/zip32.dsw
new file mode 100644
index 0000000..cb9248d
--- /dev/null
+++ b/windll/visualc/lib/zip32.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "zip32"=.\zip32.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/windll/visualc/lib/zip32.mak b/windll/visualc/lib/zip32.mak
new file mode 100644
index 0000000..4ea7923
--- /dev/null
+++ b/windll/visualc/lib/zip32.mak
@@ -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
index 0000000..7da7304
--- /dev/null
+++ b/windll/windll.c
@@ -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
index 0000000..fc20027
--- /dev/null
+++ b/windll/windll.h
@@ -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
index 0000000..23adef4
--- /dev/null
+++ b/windll/windll.rc
@@ -0,0 +1,115 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+#include "zipver.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,1,0,0
+ PRODUCTVERSION 2,3,1,0
+ FILEFLAGSMASK 0x3L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x1L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "Comments", "\0"
+ VALUE "CompanyName", "Info-ZIP\0"
+ VALUE "FileDescription", "Info-ZIP's Zip dll\0"
+ VALUE "FileVersion", "2.31\0"
+ VALUE "InternalName", "Zip32\0"
+ VALUE "LegalCopyright", "Info-ZIP 2005\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "ZIP32.DLL\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "Info-ZIP's WiZ\0"
+ VALUE "ProductVersion", "2.31\0"
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+
+#endif // !_MAC
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""windows.h""\r\n"
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""zipver.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/windll/windll.txt b/windll/windll.txt
new file mode 100644
index 0000000..2166412
--- /dev/null
+++ b/windll/windll.txt
@@ -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
index 0000000..1173b5f
--- /dev/null
+++ b/windll/windll16.def
@@ -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
index 0000000..cd2e021
--- /dev/null
+++ b/windll/windll32.def
@@ -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
index 0000000..0fcd139
--- /dev/null
+++ b/windll/ziplib.def
@@ -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
index 0000000..c4b41f6
--- /dev/null
+++ b/windll/zipver.h
@@ -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
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
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
index 0000000..4b0b9e7
--- /dev/null
+++ b/zipcloak.c
@@ -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
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
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
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
index 0000000..da38705
--- /dev/null
+++ b/zipsplit.c
@@ -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
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 */