diff options
author | Lorry <lorry@roadtrain.codethink.co.uk> | 2012-07-20 19:30:57 +0100 |
---|---|---|
committer | Lorry <lorry@roadtrain.codethink.co.uk> | 2012-07-20 19:30:57 +0100 |
commit | 04664087ad66f5614f82a2cfba3ae4eda15e792b (patch) | |
tree | 332090b15fd2db1b93abf40dccf06211d9aba297 /macos | |
download | zip-04664087ad66f5614f82a2cfba3ae4eda15e792b.tar.gz |
Tarball conversion
Diffstat (limited to 'macos')
30 files changed, 10088 insertions, 0 deletions
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..3a14a02 --- /dev/null +++ b/macos/HISTORY.TXT @@ -0,0 +1,600 @@ +A free 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 +================================ + + + + + +Release MacZip ver1.07 beta 1 +22. Februray 2001 +----------------- + +1) CHG: {unzip} switch to latest final release + unzip 5.42 + +2) CHG: {zip} switch to latest beta release + zip 2.40a + + + + + +Release MacZip ver1.06 final +22. Februray 2001 +----------------- + +1) CHG: {unzip} switch to latest final release + unzip 5.42 + +2) CHG: switch to latest release of Apples + Universal Interfaces 3.3.2 + +3) CHG: switch to latest release of + Morefiles 1.5 + + + + +Release MacZip ver1.06 beta 2 +02. August 2000 +--------------- + +1) CHG: {unzip} switch to latest beta release + unzip 5.42d + + + + + +Release MacZip ver1.06 beta 1 +27. July 2000 +------------- + +1) CHG: {zip} switch to latest beta release + unzip 2.30 + +2) CHG: {unzip} switch to latest beta release + unzip 5.42c + + + + + +Release MacZip ver1.05 final +27. July 2000 +------------- + +1) CHG: {unzip} switch to latest final release + unzip 5.41 + +2) FIX: {unzip} Fixed "unique unzip folder" foldername handling + +3) FIX: {unzip} added prototype crc32() in macbin3.c + +4) CHG: {unzip/zip} added exported Codewarrior project-file in xml-format + +5) ADD: {unzip} added extra-field recognition for Mac SmartZip in + zipinfo.c and unzpriv.h. + + + + + +Release MacZip ver1.04 final +25. January 2000 +---------------- + + +Final release of MacZip. All parts now +in final release state !! + +1) Switch to MW Codewarrior pro 5.3 + +2) CHG: {zip} switch (back) to latest final release + unzip 2.30 + +3) CHG: {unzip} switch (back) to latest final release + unzip 5.40 + + + + +Release MacZip ver1.04 beta 3 +05. October 1999 +---------------- + +1) CHG: {zip} switch to latest source level + unzip 2.30o beta release + +2) CHG: {unzip} switch to latest source level + unzip 5.41c beta release + +3) ADD: {console} added menu to print the license + + + + +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..839658d --- /dev/null +++ b/macos/README.TXT @@ -0,0 +1,569 @@ +A free 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 produced by PKZIP, and PKZIP and PKUNZIP +can work with archives produced by zip. Zip version 2.2 is +compatible with PKZIP 2.04. + +If you are new to MacZip please read first the file +"ReadMe.1st". + + + +License: +-------- + Copyright (c) 1990-2001 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in unzip.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 + + + +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 +b) using the Dialog box (Menu: File -> Zip/Unzip): + +Please read the file "ReadMe.1st" +for the description of the items a and b. + +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", 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 Footnotes: 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 6 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. + + - Aladdin DropZip 1999, This is Shareware. Aladdin chose + the format of ZipIt. Therefore, it has the some drawbacks + like ZipIt. + Creator/Type: 'SITx' / 'ZIP ' + + - SmartZip 1.0 1999 - by Marco Bambini Vampire Software. + This is Shareware. SmartZip compresses Macintosh files using the + Mac Binary. Therefore, it has the same drawbacks like ZipIt. + Creator/Type: 'dZIP' / 'ZIP ' + +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.txt). 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.06 and is based on the zip code version 2.3 and unzip code +version 5.42. 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..5a69033 --- /dev/null +++ b/macos/osdep.h @@ -0,0 +1,118 @@ +/* + Copyright (c) 1990-2007 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2007-Mar-4 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 __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_SYMLINKS 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..6182756 --- /dev/null +++ b/macos/readme.1st @@ -0,0 +1,16 @@ +This port is for Mac versions before Mac OS X. As Mac OS X is build on Unix, +use the Unix port for Mac OS X. - 7 June 2008 + + +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..5656b63 --- /dev/null +++ b/macos/source/charmap.h @@ -0,0 +1,380 @@ +/* + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 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 __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..a2efcdb --- /dev/null +++ b/macos/source/extrafld.c @@ -0,0 +1,920 @@ +/* + Copyright (c) 1990-2002 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 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 +*/ +/*--------------------------------------------------------------------------- + + 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) + +/* 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) + +#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 > EF_SIZE_MAX || + z->cext + EB_C_UT_SIZE > EF_SIZE_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 > EF_SIZE_MAX || + z->cext + EB_C_JLEE_SIZE > EF_SIZE_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) > EF_SIZE_MAX || + z->cext + EB_C_MAC3_SIZE > EF_SIZE_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..3b22327 --- /dev/null +++ b/macos/source/getenv.c @@ -0,0 +1,398 @@ +/* + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 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 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..36b5bef --- /dev/null +++ b/macos/source/helpers.c @@ -0,0 +1,479 @@ +/* + Copyright (c) 1990-2001 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 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 +*/ +/*--------------------------------------------------------------------------- + + 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..a9df5d8 --- /dev/null +++ b/macos/source/helpers.h @@ -0,0 +1,57 @@ +/* + Copyright (c) 1990-2001 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 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 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..9e18730 --- /dev/null +++ b/macos/source/macopen.c @@ -0,0 +1,363 @@ +/* + 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 +*/ +/*** 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..935c9a1 --- /dev/null +++ b/macos/source/macos.c @@ -0,0 +1,1079 @@ +/* + 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 +*/ +/*--------------------------------------------------------------------------- + + 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..9e92dce --- /dev/null +++ b/macos/source/macstuff.h @@ -0,0 +1,18 @@ +/* + Copyright (c) 1990-2001 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 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 _MACSTUFF_H +#define _MACSTUFF_H 1 + +#include "MoreFilesExtras.h" +#include "MoreDesktopMgr.h" +#include "MoreFiles.h" +#include "FSpCompat.h" +#include "FullPath.h" + +#endif /* _MACSTUFF_H */ diff --git a/macos/source/mactime.c b/macos/source/mactime.c new file mode 100644 index 0000000..af9ad5e --- /dev/null +++ b/macos/source/mactime.c @@ -0,0 +1,451 @@ +/* + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 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 +*/ +/* ----------------------------------------------------------------------------- + +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..cb76aa4 --- /dev/null +++ b/macos/source/mactime.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 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 _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..6bf1003 --- /dev/null +++ b/macos/source/pathname.c @@ -0,0 +1,726 @@ +/* + Copyright (c) 1990-2003 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 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 +*/ +/*--------------------------------------------------------------------------- + + 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 */ +/*****************************************************************************/ + + +/* + *---------------------------------------------------------------------- + * + * 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; +} + + +/* +** 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, Boolean uniqueFolder) +{ +char buffer[NAME_MAX], *tmpPtr, *namePtr; +char *last_dotpos = ExtractPath; +short count = 0, folderCount = 0; +OSErr err; +FSSpec Spec; +long theDirID; +Boolean isDirectory; +unsigned short namelen, pathlen = strlen(ExtractPath); +unsigned long ext_length = 0; +unsigned long num_to_cut = 0; +long firstpart_length = pathlen; + +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); +} + +if (uniqueFolder) { + 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; + } +} else { + /* Look for the last extension pos */ + for (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++) + if (*tmpPtr == '.') last_dotpos = tmpPtr; + + ext_length = strlen(last_dotpos); + + if (ext_length < 6) { /* up to 5 chars are treated as a */ + /* normal extension like ".html" or ".class" */ + int nameLength = last_dotpos - ExtractPath; + if (nameLength > 1) { + ExtractPath[nameLength] = 0x0; + } else { + ExtractPath[pathlen-1] = 0x0; + } + } else { + ExtractPath[pathlen-1] = 0x0; + } + + GetCompletePath(ExtractPath, ExtractPath, &Spec,&err); +} + +/* 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; +UInt64 freeBytes; +UInt64 totalBytes; +UInt64 MaxFreeBytes; + +err = OnLine(volumes, 50, &actVolCount, &volIndex); +printerr("OnLine:", (err != -35) && (err != 0), err, __LINE__, __FILE__, ""); + +MaxFreeBytes = 0; + +for (i=0; i < actVolCount; i++) + { + XGetVInfo(volumes[i].vRefNum, + volumes[i].name, + &volumes[i].vRefNum, + &freeBytes, + &totalBytes); + + if (MaxFreeBytes < freeBytes) { + MaxFreeBytes = freeBytes; + foundVRefNum = volumes[i].vRefNum; + } + + if ((freeBytes == 0) && (MaxFreeBytes < freeBytes)) { + MaxFreeBytes = freeBytes; + 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..1a39ed3 --- /dev/null +++ b/macos/source/pathname.h @@ -0,0 +1,64 @@ +/* + Copyright (c) 1990-2001 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 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 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, Boolean uniqueFolder); +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. */ + +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..4eb55da --- /dev/null +++ b/macos/source/unixlike.c @@ -0,0 +1,313 @@ +/* + 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 +*/ +/*--------------------------------------------------------------------------- + + 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 + + |