diff options
326 files changed, 84828 insertions, 0 deletions
@@ -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. @@ -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) @@ -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. @@ -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. @@ -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) @@ -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.) @@ -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 @@ -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 Binary files differnew file mode 100644 index 0000000..7bd6119 --- /dev/null +++ b/acorn/srcrename 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 @@ -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; +} @@ -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(<ime); + if (t != NULL) + t->atime = t->mtime = t->ctime = ltime; + + /* Set attributes (always a file) */ + if (a != NULL) + *a = 0; + + return unix2dostime(<ime); +} + + + +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 @@ -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 */ @@ -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 */ @@ -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 @@ -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 Binary files differnew file mode 100644 index 0000000..44de3cf --- /dev/null +++ b/packaging/zcrypt29.tar.gz 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 @@ -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 */ @@ -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) */ @@ -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 @@ -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(®s, ®s, &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(<m); + + /* 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 */ @@ -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)); +} @@ -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); +} @@ -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 */ |