From: Kim Kibum Date: Mon, 21 May 2012 08:50:24 +0000 (+0900) Subject: Upload Tizen:Base source X-Git-Tag: 2.0_alpha~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3e42e7fc9c149c0677813d7bb29ce014036c6d84;p=toolchains%2Funzip.git Upload Tizen:Base source --- diff --git a/BUGS b/BUGS new file mode 100644 index 0000000..0ee3946 --- /dev/null +++ b/BUGS @@ -0,0 +1,82 @@ +Bogus bugs (not our fault!): +--------------------------- + + By far THE BIGGEST source of bug reports to Info-ZIP/zip-bugs is the + incorrect transfer of zipfiles (or of the UnZip executable itself). + ALWAYS TRANSFER IN BINARY MODE! This includes ftp transfers and *both* + ends of a Kermit connection ("set file type binary"). If your copy + isn't exactly the same size as the original, you made a mistake. + + Another common source of errors such as "compression method 8 not sup- + ported" is the existence of an old version of UnZip somewhere in your + path. Make sure you're using the version you think you're using; give + the full path explicitly if necessary. Executing "unzip" without any + options will print a help screen, at the top of which is the UnZip + version number and release date; and executing "unzip -v" without any + zipfile or other options will give information about what compiler was + used, the target operating system, any special UnZip options, and the + date of compilation--only for version 5.11 and later, though! (Also, + under Unix C shell and some Bourne shells, "which unzip" will print + the path of the unzip you're actually using. Under OS/2 and MS-DOS, + whch21gr.zip [on Simtel mirror sites] will do the same thing; in addi- + tion, "which -a unzip" will show *all* copies of "unzip" in your path.) + + +Bugs (real and/or imagined): +--------------------------- + + - [OS/2 DLL] when trying to use the REXX function UzUnZipToStem to extract a + file with `&' in its name, the DLL crashes (but UzUnZipToVar still works) + [Daniel H, 961215] + - UnZip has problems with archives bigger than 2GB; it may print "note: didn't + find end-of-central-dir signature at end of central dir" (harmless) or + may not be able to seek to member files [James Lemley 970107, Iris Spaniol + 970206, ...] + + Fixed with Zip64 support in UnZip 6.0 + + - fix overwrite behavior: hidden/system problems?; etc. + - 32-bit DOS UnZip still unable to set volume labels? + - 32-bit DOS UnZip under OS/2 doesn't extract all wildcard zipfiles? + [DOS box: unzip386 (ver 5.12) x:\32bit\unix\emx09a\*.zip, Hobbes 3/95] + - 32-bit DOS UnZip under OS/2 doesn't set timestamp when overwriting files + on HPFS partition? (go32 and pmode/w both; emx/rsx OK) [Eberhard Mattes + 950726] + - USE_FWRITE still causes occasional CRC errors when extracting on Pyramid? + [Kevin Fritz 931102] + - still NT/W95 bug with "unzip -v d:*.zip" not matching properly? [Steve S + 940527] + 980427: bug no longer exists, Opendir() must have been corrected by someone + + - when ^Z received in no-echo mode, echo is not restored (works OK if + resume, however) + - signal() handler disabled after first use with one of BSD/SysV? + - MKS Korn shell: unzip assumes the MKS-style command-line environment + options are relevant to it, but this is not the case if unzip was called + by another program (e.g., from a .BAT file). A fix for this exists for + Borland compilers but not for MSC, Watcom, djgpp, etc. + - OS/2: for paths with one long component, the .LONGNAME EA may be saved for + all components (waste of disk space): how to check?? + - VMS: for extracting to other directories, only the VMS-style "-d [.foo]" + format is accepted; "-d foo" should also be allowed. Long filenames are + not automatically truncated to 39.39. + - Novell Netware: Netware drives may clear the archive bit on extracted + files under OS/2 and/or MS-DOS. UnZip always *tries* to set the archive + bit, however. [pynq@uchicago, 940527] + - DEC Ultrix: on long zipfiles, unzip will sometimes fail (bad CRC, not always + reproducible); this is apparently due either to a hardware bug (cache mem) + or OS bug (page faults?) [Igor, Jean-loup, bottom of BUGS.long] + - funzip/more/decryption/no-echo bug: race condition(?) causes terminal to + be "reset" to no-echo state + - Macintosh (100200), Atari (020000) external file attributes not interpreted + correctly (both unzip and zipinfo) + - pkbug error: zipfile with incorrect csize and/or ucsize--check for end of + compressed (csize) data in uncompression routines: + unreduce.c: while (((outpos + outcnt) < ucsize) && (!zipeof)) { + [James Birdsall, Mark, bottom of BUGS.long] + - OS/2: directory EAs not restored if directory exists [Kai Uwe, KG27515@uark] + (subsequent note: no way to determine which EAs are newer ==> cannot + restore without user input) + (update: as of UnZip 5.30, option -o forces restoring of directory EAs) + - MS-DOS: Borland executables don't allow other than 80-column, 25/43/50-line + screen modes (Borland bug) [Michael Stillwell] diff --git a/COPYING.OLD b/COPYING.OLD new file mode 100644 index 0000000..16eaccc --- /dev/null +++ b/COPYING.OLD @@ -0,0 +1,212 @@ +__________________________________________________________________________ + + This is the Info-ZIP file COPYING (for UnZip), last updated 17 Jul 2000. +__________________________________________________________________________ + + FIRST NOTE: + This file contains some details about the copyright history of + contributions to the UnZip project. + Additionally, it summarises some exceptions to the general BSD-like + copyright found in LICENSE that covers our generic code and most of + the system specific ports. + Please read LICENSE first to find out what is allowed to do with + Info-ZIP's UnZip code. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + There are currently two explicit copyrights on portions of UnZip + code (at least, of which Info-ZIP is aware): + Jim Luther's Mac OS File Manager interface code; and Christopher Evans' + MacBinaryIII coding code (for the MacOS port).. These copyrights + are discussed in more detail below. + + All remaining code is now (starting with UnZip version 5.41) covered + by the new Info-ZIP license. For details, please read the acompaning + file LICENSE. The terms and conditions in this license supersede the + copyright conditions of the contributions by Igor Mandrichenko + (vms/vms.c), Greg Roelofs (zipinfo.c, new version of unshrink.c), + Mike White (Windows DLL code in "windll/*"), Steve P. Miller (Pocket + UnZip GUI "wince/*"), and Mark Adler (inflate/explode decompresseion + core routines, previously put into the public domain). All these + Info-ZIP contributors (or "primary" authors) have permitted us to + replace their copyright notes by the Info-ZIP License. + + Frequently Asked Questions regarding (re)distribution of Zip and UnZip + are near the end of this file. + + There are no known patents on any of the code in UnZip. Unisys + claims a patent on LZW encoding and on LZW decoding _in an apparatus + that performs LZW encoding_, but the patent appears to exempt a stand- + alone decoder (as in UnZip's unshrink.c). Unisys has publicly claimed + otherwise, but the issue has never been tested in court. Since this + point is unclear, unshrinking is not enabled by default. It is the + responsibility of the user to make his or her peace with Unisys and + its licensing requirements. (unshrink.c may be removed from future + releases altogether.) +__________________________________________________________________________ + + The original unzip source code has been extensively modified and + almost entirely rewritten (changes include random zipfile access + rather than sequential; replacement of unimplode() with explode(); + replacement of old unshrink() with new (unrelated) unshrink(); re- + placement of output routines; addition of inflate(), wildcards, + filename-mapping, text translation, ...; etc.). As far as we can + tell, only the core code of the unreduce method remained substantially + similar to Mr. Smith's original source. As of UnZip 5.42, the complete + core code is now covered by the Info-ZIP Licence. Therefore, support + for the reduce method has been removed. + The drop of the reduce method should only affect some test archives, + reducing was never used in any publically distributed Zip program. + For pathologic cases where support for reduced archive entries is + needed, the unreduce code copyrighted by Samuel H. Smith is available + as a separate distribution (the restricted copyright of this code is + cited below in the "historical" section). + + The following copyright applies to the Mac OS File Manager interface code + (macos/source/macstuff.[ch]), distributed with UnZip 5.4 and later: + + * MoreFiles + * + * 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 usage terms of this copyright note are compatible with the + Info-ZIP license, they do not add further restrictions. + + + The following copyright applies to the Mac OS "macbin3" decoding code + (extra field compatibility with ZipIt): + + * MacBinaryIII.h + * + * Copyright 1997 Christopher Evans (cevans@poppybank.com) + * + * Basic encoding and decoding of Macintosh files to the + * MacBinary III spec. + * ---------------------------------------------------------------------- + * This source is copyrighted by Christopher Evans (cevans@poppybank.com) + * (available at ftp://ftp.lazerware.com/MacBinaryIII_src_C.sit + * homepage of Leonard Rosenthol leonardr@netcom.com) + + This copyright note does not contain any usage terms. So, we assume + that this code is freely reusable until we are proved wrong... + +-------------------------------------------------------------------------- + + The remaining copyright notes have been superseeded by the new + Info-ZIP license, with explicit permission from the respective + original authors. They are cited here for historical reasons, + only: + + The following copyright applies to the full-featured unreduce.c + (now distributed separately): + + * Copyright 1989 Samuel H. Smith; All rights reserved + * + * Do not distribute modified versions without my permission. + * Do not remove or alter this notice or any other copyright notice. + * If you use this in your own program you must distribute source code. + * Do not use any of this in a commercial product. + + Regarding the first stipulation, Mr. Smith was tracked down in southern + California some years back [Samuel H. Smith, The Tool Shop; as of mid- + May 1994, (213) 851-9969 (voice), (213) 887-2127(?) (subscription BBS), + 71150.2731@compuserve.com]: + + "He says that he thought that whoever contacted him understood that + he has no objection to the Info-ZIP group's inclusion of his code. + His primary concern is that it remain freely distributable, he said." + + Despite the fact that our "normal" code has been entirely rewritten + and by default no longer contains any of Mr. Smith's code, Info-ZIP + remains indebted and grateful to him. We hope he finds our contribu- + tions as useful as we have his. + + Note that the third and fourth stipulations still apply to any com- + pany that wishes to incorporate the unreduce code into its products; + if you wish to do so, you must contact Mr. Smith directly regarding + licensing. + + ----- + + The following copyright applied to most of the VMS code in vms.c, + distributed with UnZip version 4.2 and later: + + * Copyright (c) 1992-93 Igor Mandrichenko. + * Permission is granted to any individual or institution to use, copy, + * or redistribute this software so long as all of the original files + * are included unmodified and that this copyright notice is retained. + + ----- + + The following copyright applied to the new version of unshrink.c, + distributed with UnZip version 5.2 and later: + + * Copyright (c) 1994 Greg Roelofs. + * Permission is granted to any individual/institution/corporate + * entity to use, copy, redistribute or modify this software for + * any purpose whatsoever, subject to the conditions noted in the + * Frequently Asked Questions section below, plus one additional + * condition: namely, that my name not be removed from the source + * code. (Other names may, of course, be added as modifications + * are made.) Corporate legal staff (like at IBM :-) ) who have + * problems understanding this can contact me through Zip-Bugs... + + ----- + + The following copyright applied to the Windows DLL code (windll/*), + distributed with UnZip version 5.2 and later: + + * Copyright (c) 1996 Mike White. + * Permission is granted to any individual or institution to use, + * copy, or redistribute this software so long as all of the original + * files are included, that it is not sold for profit, and that this + * copyright notice is retained. + + ----- + + The following copyright applied to the Windows CE GUI port, ``Pocket + UnZip,'' distributed with UnZip version 5.3 and later: + + * All the source files for Pocket UnZip, except for components + * written by the Info-ZIP group, are copyrighted 1997 by Steve P. + * Miller. The product "Pocket UnZip" itself is property of the + * author and cannot be altered in any way without written consent + * from Steve P. Miller. + + ----- + + The remaining code was written by many people associated with the + Info-ZIP group, with large contributions from (but not limited to): + Greg Roelofs (overall program logic, ZipInfo, unshrink, filename + mapping/portability, etc.), Mark Adler (inflate, explode, funzip), + Kai Uwe Rommel (OS/2), John Bush and Paul Kienitz (Amiga), Antoine + Verheijen (Macintosh), Hunter Goatley (more VMS), Mike White (Windows + DLLs), Christian Spieler (overall logic, optimization, VMS, etc.) and + others. See the file CONTRIBS in the source distribution for a much + more complete list of contributors. + The decompression core code for the deflate method (inflate.[ch], + explode.c) was originally written by Mark Adler who submitted it + as public domain code. + +-------------------------------------------------------------------------- diff --git a/Contents b/Contents new file mode 100644 index 0000000..ec85c82 --- /dev/null +++ b/Contents @@ -0,0 +1,84 @@ +Contents of the UnZip 6.00 source archive. The OS-specific subdirectories +at the end contain their own Contents listings: + + Contents this file + README what UnZip is; general information + LICENSE Info-ZIP license; terms for using and distributing UnZip + COPYING.OLD historic copyrights and distribution policy (obsolete) + INSTALL how to compile and install UnZip and related utilities + WHERE where Zip/UnZip and encryption/decryption support can be found + History.600 new features and fixes of the last major release + ToDo rough priority list of new features to be added in next release + BUGS known bugs, problems, and (possible) other features to be added + unzip.txt UnZip manual page, human-readable format + unzipsfx.txt UnZipSFX manual page, human-readable format + zipinfo.txt ZipInfo manual page, human-readable format + zipgrep.txt ZipGrep manual page, human-readable format + funzip.txt fUnZip manual page, human-readable format + file_id.diz BBS-oriented file describing this archive + testmake.zip test archive for checking whether newly compiled UnZip works + api.c generic DLL entry points, support functions (required for DLLs) + apihelp.c API help text for DLL versions (currently OS/2 only) + consts.h global, initialized variables that never change (required) + crc32.c code for calculation 32bit CRC of a string buffer (required*) + crc32.h declarations for the crc-32 code (required*) + crc_i386.S fast assembler replacement for crc32() (Intel 386 and newer) + crypt.c de-/encryption routines (required*) + crypt.h de-/encryption header file (required*) + ebcdic.h static lookup table for ASCII <-> EBCDIC translation (required) + envargs.c code to read options from environment variables (required) + explode.c code for exploding (required) + extract.c high-level extraction and decryption code (required) + fileio.c file manipulation and password code (required) + funzip.c filter unzip: extracts in a pipe from stdin to stdout + gbloffs.c helper program to retrieve offsets of globals struct members + globals.c code to support global variables with reentrancy (required) + globals.h definition of global structure G (required) + inflate.c code for inflating (required*) + inflate.h header file for inflating (required*) + list.c UnZip listing routines, non-ZipInfo mode (required) + match.c pattern-matching code for filename wildcards (required) + process.c zipfile headers code (required) + timezone.c timezone and timestamp functions (required) + timezone.h header file for interface to "internal" tz functions (required) + ttyio.c code for handling nonecho tty input: password, pager (required) + ttyio.h header file for nonecho tty input: password, pager (required) + ubz2err.c callback handler for fatal bzip2 errors (bzip2 support only) + unreduce.c code for unreducing (required) + unshrink.c code for unshrinking (required) + unzip.c UnZip main(), usage and options code (required) + unzip.h public half of main UnZip header file (required*) + unzipstb.c minimal UnZip "stub" file demonstrating use of DLL versions + unzpriv.h private (internal) half of main UnZip header file (required*) + unzvers.h header with UnZip/UnZipSFX and ZipInfo version info (required) + zip.h dummy header for use with crypt.c (required*) + zipinfo.c UnZip listing routines, ZipInfo mode (required) + acorn/ support files for compiling under Acorn RISC OS + amiga/ support files for compiling under AmigaDOS + aosvs/ support files for compiling under Data General AOS/VS + atari/ support files for compiling under Atari TOS + atheos/ support files for compiling under AtheOS/Syllable + beos/ support files for compiling under BeOS + cmsmvs/ support files for compiling under VM/CMS and MVS + flexos/ support files for compiling under FlexOS + human68k/ support files for compiling under X68000/Human68K + macos/ support files for compiling under Macintosh OS + msdos/ support files for compiling under MS-DOS + netware/ support files for compiling for Novell Netware NLM + os2/ support files for compiling under OS/2 (includes DLL stuff) + qdos/ support files for compiling under SMS/QDOS + tandem/ support files for compiling under Tandem NSK + theos/ support files for compiling under Theos + tops20/ support files for compiling under TOPS-20 + unix/ support files for compiling under Unix + vms/ support files for compiling under VMS + win32/ support files for compiling under Windows 9x and Windows NT + wince/ support files for compiling under Windows CE (GUI version) + windll/ support files for compiling Windows 3.x/9x/NT DLLs + bzip2/ subfolder for source of externally supplied bzip2 extension + man/ nroff man-page sources for the main user documentation + proginfo/ programming docs, additional technical info, contributor list + +Files marked "required*" are also needed to compile fUnZip. The normal +UnZip makefile targets now make both UnZipSFX and fUnZip, except in a few +cases; ZipInfo is now incorporated into UnZip (see zipinfo.txt for usage). diff --git a/History.600 b/History.600 new file mode 100644 index 0000000..7ebef49 --- /dev/null +++ b/History.600 @@ -0,0 +1,1117 @@ +UnZip, version 6.00, 20 April 2009 + +Features added (or removed): + +6.00a (): + - Many changes by Myles + +6.00b (12 Nov 04): + - Added dll changes from Mike White. [Mike White (MW), Ed Gordon (EG)] + - Added Unix Large File Support but must be enabled manually. [EG] + - Humble beginnings of adding configure script to Unix port to + autoconfigure large file support. [EG] + - VMS changes, including large file support, better handling of + -V and new -VV options, revised build procedures, and + documentation updates. [Steven Schweda (SMS)] + - file_size added to process.c to handle files sizes larger + than 2 GiB more cleanly when no large file support. [SMS] + - Large file debugging on Unix and VMS. [SMS, EG] + - Split w32i64.h with large file includes for dll [EG] + +6.00c (1 Feb 05): + - Various Amiga and Win32 changes (see files). [Paul Kienitz (PK)] + - Add NOSHARE compile option for VMS. [SMS] + - Updates to windll (list.c, structs.h, uzexampl.c, uzexampl.h, windll.aps, + windll.c, windll.h, windll.rc, windll.txt, sfxwiz.c) to add VB support + for Zip64 to dll [MW] + +6.00c (14 Feb 05): + - Added ODS5 extended file name support for VMS. (Eight-bit-only, no + Unicode.) Zip name character "?" is mapped to VMS name character + "/". ODS2 file names are now explicitly upper-case. [SMC] + - New VMS option, -2 (/ODS2), forces ODS2-compatible file names even + when the destination file system is ODS5. [SMC] + - New VMS option, -Y (/DOT_VERSION), causes archived file name endings + of ".nnn" (where "nnn" is a decimal number) to be treated as if they + were VMS version numbers (";nnn"). Example: "a.b.3" -> "a.b;3". [SMC] + +6.00c8 (08 May 05): + - Added optional BZIP2 support, using the free BZIP2 library. Enabled + by defining the compile time option USE_BZIP2. [Johnny Lee] + - Revised optional ZLIB support to use the new zlib 1.2.x callback interface + when available (significant performance gain, now faster than UnZip's + built-in decompression code) [Christian Spieler] + - Added interface into zlib's unsupported "inflate9" callback code (a contri- + buted extension in zlib 1.2.x), for extracting Deflate64 entries. Enabled + by defining the compile time option HAVE_ZL_INFLAT64. [Christian Spieler] + - windll: added separate entry point Wiz_SingleEntryUnzipList for VB support, + changed Wiz_SingleEntryUnzip back to 5.x version [Christian Spieler] + +6.00c9 (15 May 05): + - NO feature changes. + +6.00c10 (21 May 05): + - WinCE port: Adapted PocketUnzip to UnZip6 code and enabled Zip64 support + for the WIN32 (non-WinCE) targets. [Chr. Spieler] + +6.00c11 (23 May 05): + - NO feature changes. + +6.00c12 (15 Aug 05): + - windll/csharp: new example project for .NET framework 1.1, written in C#. + (currently unsupported by the Info-ZIP group) [Adrian Maull] + - MSDOS port: added warning message when used in an (32/64-bit) Windows + virtual MSDOS process; currently only shown when an error or warning + occured. [Johnny Lee, Chr. Spieler] + +6.00c13 (02 Oct 05), 6.00c14 (15 Nov 05), 6.00c15(17 Nov 05): + - NO feature changes. + +6.00c (19 Nov 05): + - NO feature changes. + +6.00d01 (04 Mar 07): + - unix/unix.c: when extracting directory entries, keep a SGID attribute + inherited from the parent dir (to allow content created in these new + directories to inherit the parent's GID), unless the directory entry was + created on UNIX, and UnZip was requested to restore UID/GID or SUID/SGID. + [Matthew Seitz, Chr. Spieler] + - process.c, modified info message handling for timestamping operation mode + to be more consistent with message handling of other operations: suppress + summary message only when qflag > 1 in process_zipfiles(); added time-stamp + success message to do_seekable() in non-quiet mode; moved message strings + to Far string constants. [Steven M. Schweda, Chr. Spieler] + - process.c - process_zipfiles(): suppress the "cannot find any wildcard + match ..." warning message for (qflag >= 3). [Chr. Spieler] + - vms/vms.c: added support for delayed restoration of directory attributes + [Steven M. Schweda] + - vms/vms.c - return_VMS(): implemented official HP-assigned facility code + in the calculation of UnZip's (non-success) VMS exit status codes. + [Steven M. Schweda] + - vms/vms.c, vms/cmdline.c vms/unz_cli.cld, unzip.c, unzip.h: added "-S" + option to change output record format into Stream-LF for text files when + extracted in "convert text-files" mode. [Steven M. Schweda] + - unzpriv.h, extract.c, unix/unix.c, atari/atari.c, atheos/atheos.c, + beos/beos.c: added separate pInfo flag to record symlink entries, moved + symlink detection code into mapattr(), added VMS to the list of hosts known + to support symbolic links. [Steven M. Schweda, Christian Spieler] + - VMS: added support to extract "symlink" entries as symbolic links (requires + up-to-date version of OpenVMS). [Steven M. Schweda, Chr. Spieler] + - unzip.1: added description of new VMS-specific "-S" option. [Chr. Spieler] + - unzip_cli.help, unzip_def.rnh: updated exit codes documentation, added new + option (-S resp. /TEXT=STMLF). [Steven M. Schweda, Chr. Spieler] + - unzip_cli.help, unzip_def.rnh: completed resp. added description of new + VMS-specific options (-Y, -2). [Chr. Spieler] + - process.c: added preliminary (alpha-state) support for reading of Unicode + Path extra field that now sets globals unipath_filename and + unipath_escapedfilename (not yet functional). [EG] + +6.00d02 (08 Mar 07), 6.00d03 (10 Mar 07), 6.00d04 (11 Mar 07): + - NO feature changes. + +6.00d05 (31 Mar 07): + - win32/vc6: added VC6 project files for compiling UnZip with support for + bzip2 decompression. [Chr. Spieler] + - INSTALL, unix/Makefile, unix/configure: support compiling of UnZip with + integrated bzip2 decompression capability, added check for presence of + bzip2 library sources to configure script, updated bzip2-related + documentation in INSTALL. [Chr. Spieler] + +6.00d06 (02 Dec 07): + - VMS: added support for displaying UnZip exit code error messages through + the VMS built-in message facility; new vms/UNZIP_MSG.MSG message string + source, modified vms/descrip.mms makefile. [Steven M. Schweda] + - UNIX: added new "-^" command line option that switches off the control + character filter for extracted filenames. [Chr. Spieler] + - UNIX: added support for restoring attributes and UID/GID for symbolic + links when appropiate OS support is provided. [Chr. Spieler] + +6.00d07 (26 Dec 07): + - New "-D" option which allows skipping of timestamp restoration for extracted + directory entry or for all files ("-DD"). [Chr. Spieler] + - windll: added support for new -D (-DD) option to dll interface, updated + the documentation. [Chr. Spieler] + +6.00d08 (29 Dec 07): + - On VMS, the default is now to not restore directory timestamps (consistent + with BACKUP); "-D" skips all timestamp restorations, "--D" enables + timestamp restoration for all entries. [Chr. Spieler, Steven M. Schweda] + +6.00d09 (06 Jan 08): + - NO feature changes. + +6.00d10 (10 Feb 08): + - partial integration of Ed Gordon's UNICODE_SUPPORT code (W9x-ANSI mode only + for now) seems to be finished. [Ed Gordon, C. Spieler] + - zipinfo.c: added support for "UTF-8 path" extra field display to zi_long(). + [Chr. Spieler] + +6.00d11 (16 Feb 08): + - ATheOS, BeOS, Tandem, Unix: experimental extension of "Ux" extra field to + allow restoration of 32-bit UID & GID values (affected generic sources: + unzpriv.h and process.c). [Chr. Spieler] + +6.00d (17 Feb 08): + - NO feature changes. + +6.00e01 (21 Feb 08): + - NO feature changes. + +6.00e02 (08 Mar 08): + - ATheOS, BeOS, Tandem, Unix: removed experimental 32-bit extension of "Ux" + extra field (affected generic sources: process.c). [Chr. Spieler] + +6.00e03 (29 Mar 08): + - general (ebcdic.h, process.c, unpriv.h): modified infrastructure to make + OEM<-->ISO translation configurable at runtime. [Chr. Spieler] + - MSDOS (doscfg.h, msdos.c): OEM<-->ISO configured at runtime, depending on + system codepage (enabled for 437, 850, 858; disabled for 932, 936, 949, + 950, 874, 1258; currently also disabled for all other OEM codepages because + of missing translation tables). [Chr. Spieler] + +6.00e04 (27 Apr 08): + - NO feature changes. + +6.00e05 (09 Sep 08): + - unzip.c: added framework for verbose multi-page online help, called by + option "-hh". [Ed Gordon] + - process.c, unzpriv.h, unix/unix.c: added support for new IZUNIX3 extra field + providing 32-bit UID/GID data. [Ed Gordon, Chr. Spieler] + - unzip.c - uz_opts(): do not exit immediately after recognizing help screen + request; this allows to specify the pager option after the explicit help + request. [Chr. Spieler] + +6.00e06 (13 Sep 08): + - NO feature changes. + +6.00e (04 Jan 09): + - unzip.h: enable -B option for Unix, OS/2, and Win32. [EG, Chr. Spieler] + +6.00f (11 Jan 09): + - NO feature changes. + +6.00g01 (08 Jan 09), 6.00g02 (25 Jan 09), 6.00g03 (10 Feb 09), +6.00g04 (16 Feb 09), 6.00g (28 Feb 09), +6.00h01 (09 Mar 09), 6.00h02 (16 Apr 09), 6.00h03 (17 Apr 09), +6.00 (20 Apr 09): + - NO feature changes. + +Bugs fixed: + +6.00b (12 Nov 04): + - Output bug fixes to account for sizes > 2 GiB and < 4 GiB. [EG] + - Bug fixes in ZipInfo. [EG] + - Reverted unix.c to an older version to make + calls to defer_dir_attribs compatible. Also needed to rework + win32.c to make compatible. Probably broke NT but haven't tested. + Need to trace out and fix. [EG] + +6.00c (1 Feb 05): + - Various bug fixes (see files gbloffs.c, process.c, unzpriv.h, amiga/amiga.h, + amiga/filedate.c, amiga/flate.a, amiga/makefile.azt, and win32/w32cfg.h). + [PK] + - Some type changes in globals.h. [SMS] + +6.00c (14 Feb 05): + - Disambiguated some identical VMS error messages. [SMC] + +6.00c8 (08 May 05): + - extract.c, unzip.c, unzpriv.h: Some tweaks and corrections to the optional + BZIP2 support [Christian Spieler] + - VMS, cmdline.c unz_cli.cld: fixed the completely broken addition of + the /ODS2 and /DOT_VERSION options [Christian Spieler] + - Merged in all additions and fixes of the UnZip 5.5x code tree from + UnZip 5.50i up to UnZip 5.52 release. Removed History.5?? files. + Removed all History.600 entries that have been covered by fixes from + the UnZip 5.5x code. + For detailed ChangeLog see History.550, History.551, and History.552, + as found in unzip552.zip source distribution and the UnZipHist.zip + ChangeLog archive. [Christian Spieler] + - crypt.[ch]: updated to 2.10 (synchronized with zip 2.31) [Christian Spieler] + - envargs.c: do not declare getenv() for "modern" compilers [Cosmin Truta] + - extract.c: better echo message for CR or LF at overwrite prompt [Cosmin?] + - fileio.c: added specific message for SIGILL in handler() [Chr. Spieler] + - process.c: fixed code of optional USE_STRM_INPUT variant [Chr. Spieler] + - VMS, vms.c: requires "-vv" instead of only "-v" to enable VMS diagnostic + output (enable DIAG_FLAG for vflag >= 3, only; DIAG output is not available + for the unzip modi "extract to disk" and "zipinfo") [Christian Spieler] + - VMS cli interface: added (undocumented) option modified /FULL=DIAGNOSTICS to + control "-vv" diagnostic messages [Steven M Schweda, Christian Spieler] + - WIN32/MSDOS (maybe others): fixed abort exception handling for CTRL-BREAK + [Christian Spieler] + - revised ecrec64 search logic: ecrec64 need not be present when one of + the ecrec fields is filled with all 1's. [Christian Spieler] + - added user-defined types for 8-byte and 4-byte Zip archive (unsigned) + quantities [Christian Spieler] + - MSDOS 32-bit port revitalized [Christian Spieler] + - windll: changed interface definition to be independent of compile/feature + configuration [Christian Spieler] + - man/unzip.1: Typo corrections [anonymous DEBIAN contribution, Santiago Vila] + - man/unzip.1: removed duplicated quotes from VMS example in environment + variable section [Steven M. Schweda] + +6.00c9 (15 May 05): + - zipinfo.c, list.c: fix the structure check for correct end-of-central dir + to be aware of Zip64 extensions [Christian Spieler] + - windll, sfxgui: synchronize function definitions with changed windll + interface [Mike White] + - extract.c, fileio.c, process.c: fixed USE_STRM_INPUT variant of file + position seeking [Christian Spieler] + - process.c - file_size(): changed scope into static; added non-USE_STRM_INPUT + variant that uses zlseek instead of zfseeko and zftello; do not include in + SFX stub; do not compile function definition when not used [Chr. Spieler] + - unzpriv.h: revised and cleaned up setup definitions for zstat, zfstat and + other 64-bit configuration macros [Christian Spieler] + - win32/w32cfg.h: revised automatic ZIP64 support enabling logic and compiler- + specific configuration; turned off ZIP64 support for lcc and BorlandC + because of missing LARGE_FILE support; verified LARGE_FILE support for + Watcom C and MinGW [Chr. Spieler] + - win32/win32.c: fixed type specification in zstat_win32() [Chr. Spieler] + - win32/win32i64.c: do not include seek replacement functions when not needed + [Christian Spieler] + - zipinfo.c: adapted verbose printouts to longer number printings of Zip64- + enabled UnZip; fixed extra-space detection in zi_long() by moving the + extra-field read in front of the offset comparison [Christian Spieler] + +6.00c10 (21 May 05): + - zipinfo.c - zi_long(): fixed expression for detecting 64-bit local entry + offset [Chr. Spieler] + - process.c - find_ecrec64(): added type-casts to shut up conversion warnings, + removed code that clobbered the ecrec signature "pseudo-constant" by + overwriting it with the ecrec64 signature (this bug broke the reentrancy + of the dll code) [Chr. Spieler] + - win32/win32.c, unzpriv.h: adapted SetFileSize for 64-bit offsets[C. Spieler] + - extract.c, fileio.c, process.c: removed unneeded (FILE *) type-casts in + calls to zfseeko() and zftello() [Chr. Spieler] + - extract.c, list.c, zipinfo.c, unzpriv.h: use symbolic constants for the + 16-bit and 64-bit masks in the checks for zip entry count consistency + [Steven M. Schweda, Chr. Spieler] + - process.c: reorganized the extended Zip filesize-checking code (for > 2GB + detection) by moving it behind the open_infile () call and using the + already opened global zipfile handle [Steven M. Schweda, Chr. Spieler] + - fileio.c: allow output redirection to memory when ZIP64_SUPPORT is enabled + [Chr. Spieler] + - windll: synchronized uzexampl.c and uzexampl.h with current windll interface + declarations [Chr. Spieler] + +6.00c11 (23 May 05): + - process.c: fixed bugs in last filesize-checking revision (added missing + semi-colon, synchronized file_size() call with its prototype declaration + [Steven M. Schweda, Chr. Spieler] + +6.00c12 (15 Aug 05): + - VMS port: updated the dependency build routines (*.mms, *.com) and the VMS + install documentation (INSTALL) [Steven M. Schweda] + - api.c - redirect_outfile(): initialize check_conversion variable in the + non-textmode case [Chr. Spieler] + - process.c, extract.c: moved the crctab initialization and check of the + extraction root dir from do_seekable() further down the call tree into + extract_or_test_files() [Chr. Spieler] + - extract.c - extract_or_test_entrylist(): moved central-vs-local consistency + checks behind the local Zip64-e.f. code [Chr. Spieler] + - fileio.c - do_string() bugfix: do not call getZip64Data() when previous + allocation of extra field buffer has failed [Chr. Spieler] + - inflate.c - inflate_dynamic(): free table-decoding huft-tree when exiting + prematurely from the literal/distance tree data reading because of invalid + compressed data [Rudolf Lechleitner, Chr. Spieler] + - unzip.c - uz_opts(): local variable "error" should only take boolean values, + no PK error codes (cosmetic correction) [Chr. Spieler] + - vms/vms.c, process.c: modified handling of VMS do_wild() lookup errors to + give more helpful messages to the end user [Steven M. Schweda] + - unix/zipgrep: fixed security hole by handling shell metacharacters like '|' + and '&' properly when they occurred in input file names [Greg Roelofs] + - match.c: copied and adapted optimization for "*fixedstring" patterns from + the Zip code into recmatch(); provided two local helper functions isshexp() + and namecmp() for this optimization [Johnny Lee, Chr. Spieler] + - Where: used the newer version from UnZip 5.52 [Chr. Spieler] + +6.00c13 (02 Oct 05): + - AOS/VS, Atari, AtheOS, BeOS, UNIX: fixed symlink code by avoiding fclose() + on NULL handle in extract.c [Dan Yefimov] + - AOS/VS, Atari, AtheOS, BeOS, UNIX (and unzpriv.h, fileio.c): modified the + symlink code to use the opened outfile handle for re-reading the symlink + target data; modified open_outfile to allow read access on outfile handle + (security fix against "ToCToU" vulnerability) [Chr. Spieler] + - UNIX (unix.c, Makefile, configure): fixed "ToCToU" security vulnerability + in close_outfile by using fchown() & fchmod() instead of chown() & chmod() + (only when available); added check for function existence to configure + [Dan Yefimov, Matthias Scheler, Chr. Spieler] + - fileio.c - open_outfile(): deny access for group&world to currently open + outfile on all systems that support umask() (AOS/VS, Atari, AtheOS, BeOS, + QDOS, Tandem, UNIX) [Chr. Spieler] + - unzpriv.h, fileio.c - open_outfile(): open outfile in "write update" mode + when supporting symlinks or QLZIP extensions; these features require the + ability to reread the opened outfile [Chr. Spieler] + - fileio.c: added WriteTxtErr() macro to allow differenciating between + text-mode write function calls (in UzpMessagePrnt()) and binary write calls + (everywhere else) [Chr. Spieler] + - fileio.c, VMS only: use fprintf() instead of (f)write in WriteTxtErr(), to + work around RMS record handling problem (e.g. when using PIPE to redirect + messages) [Steven M. Schweda] + - UNIX port: revised unix/configure and unix/Makefile for better integration + of automatic configuration in the build procedure [Chr. Spieler] + +6.00c14 (15 Nov 05): + - VMS, descrip.mms: repaired CLEAN_ALL target which did not always delete + all expected files [Steven M. Schweda] + - unzip.c, fixes for online help screen: corrected "-v" description and moved + it from modifier section into options section, added description of "-T" + option, removed the "DLL && API_DOC"-only description of the "-A extended + API help" option [Chr. Spieler, Steven M. Schweda] + - man/unzip.1: minor corrections in wording of "-v" option description + [Chr. Spieler, Steven M. Schweda] + +6.00c15 (17 Nov 05): + - vms/vms.c: fixed do_wild() logic error introduced in August 2005, + sys$search fails (at least on VAX) when not preceeded by a sys$parse + call with "syntax-check-only" flag cleared [Steven M. Schweda] + - process.c: cosmetic change in process_zipfiles() to shut-up gcc warning + on non-UNIX (non-QDOS) systems [Chr. Spieler] + +6.00c (19 Nov 05): + - extract.c, bzip2 support: fixed missing ";" error (was only a problem + when enabling BZIP2 support without LARGE_FILE support); added some + (cosmetic) typecasts to shut up compiler warnings [Steven M. Schweda] + - VMS support for BZIP2 decompression: updated make procedures and scripts, + added "find_bzip2_dir" helper script and bzlib.h include file wrapper + [Steven M. Schweda] + +6.00d01 (04 Mar 07): + - extract.c: replaced local wsize variable (DLL only) by reference to the + "global" variable G._wsize [Chr. Spieler] + - unzpriv.h: use fputs() instead of fprintf() as output function in the + FUNZIP variant of the Info() macro, to prevent misinterpreting format + specifiers in the sprintf() output. [Martin Pitt, ubuntu] + - unix/unix.c: added detailed compiler version info for SunPro cc, HP cc, + DEC cc. [Steven M. Schweda] + - vms/descrip.mms: added support for architecture detection macro symbols + built into newer versions of MMK (a MMS clone). [Steven M. Schweda] + - fileio.c - is_vms_varlen_txt(): commented out the currently unused code for + determining the VMS fileorg setting. [Steven M. Schweda] + - extract.c - extract_or_test_files(): the "back at endsig" checking code + is not used for the SFX stub. [Steven M. Schweda] + - win32: changed all Win32-API calls with string parameters to explicitely use + the ANSI variant; this removes the dependency on the UNICODE and _UNICODE + compile flags being undefined. [NN, Chr. Spieler] + - zipinfo.c: on WIN32, archive filename display must be fed through codepage + translation. [Chr. Spieler] + - zipinfo.c - zipinfo(): repaired several memory leaks when the listing loop + is stopped prematurely because of inner errors. [Chr. Spieler] + - crc32.c, crc32.h, crc_i386.S, crc_i386.asm, crc_i386.c: comprehensive + revision of crc32 calculation, implementing the optimized algorithms from + the zlib source code which depend on specific machine architecture + characteristics (removed crctab.c, added crc32.h). [Chr. Spieler] + - crypt.c, crypt.h: adapted to the modifications of crc32. [Chr. Spieler] + - msdos, win32, vms, unix: enabled optimized crc32 algorithms on i386, VAX, + and AXP architectures. [Chr. Spieler] + - win32/nt.c: tried to fix mutex handle leak in Initialize(). + [Johnny Lee, Chr. Spieler] + - vms/vms.c - check_format(): added system error message to sys$open failure + message. [Steven M. Schweda] + - wince/intrface.cpp - checkdir(): corrected typo ('0' should be '\0') + [Shawn Carey] + - wince/wcemain.c - WinMain(): correct the removal code for enclosing argument + quotes. [Shawn Carey, Chr. Spieler] + - os2, win32 - checkdir(): fixed buffer overflow security bug for FAT-style + buildpath, optimized code by removing overflow checks inside the copy loops + [Johnny Lee, Chr. Spieler] + - win32/win32.c - VFatFileTime2utime(): fixed return data generation in error + branch for the "input time stamp cannot be converted to local time" case + [Steve Youngs] + - added new compression methods and e.f. IDs from PKWARE Appnote 6.3.0 as of + 2006-09-29 [Chr. Spieler] + - extract.c - extract_or_test_files(): remove dead branch in the code section + handling archive test summary messages. [Chr. Spieler] + - fileio.c - zstrnicmp(): added (uch) typecasts to comparison, to improve + "compatibility" with "extended ASCII characters". [Chr. Spieler] + - vms: use CRTL-supplied function strncasecmp() for STRNICMP() when available. + [Steven M. Schweda, Chr. Spieler] + - vms/vms.c, vms/vms.h: for better synchronisation with upcoming UnZip 6 code, + the macros for masking the "ODS2 vs. ODS5" support differences have been + cleanded up and ported back to the 5.5x VMS code. [Chr. Spieler] + - ubz2err.c: new source file to isolate the bzip2 "fatal error" callback + routine in its own module; this allows easy replacement of this routine + when the UnZip package is used as a static library (e.g. for WiZ with + bzip2 support). [Chr. Spieler] + - general: added new ubz2err.c module to the make procedures of ports that + (might) support bzip2. [Chr. Spieler] + - crypt.c: optimized crypt-keys handling for Big-Endian systems using the + optimized CRC32 code by introducing a local copy of the crc32 table + containing byte-swapped values. [Chr. Spieler] + - extract.c, unzpriv.h: modified calling interface of find_compr_idx() to + use unsigned instead of ush. [Steven M. Schweda, Chr. Spieler] + - vms/vms.c: added missing include of crc32.h header, added missing fab, nam + variable declarations to checkdir(). [Steven M. Schweda] + - vms/make_unz.com, vms/link_unz.com: avoid link problems with sticky + dev:[dir] spec from externally supplied bzip2 lib. [Steven M. Schweda] + - vms/vms.[ch]: changed "ODS2 vs. ODS5" masking macros back to pre-5.53d + style. [Steven M. Schweda] + - vms: updated/corrected build procedures to handle modified bzip2 support. + [Steven M. Schweda] + - typo correction "explicitly" in various files. [Steven M. Schweda] + - cosmetic documentation change: use the "bzip" name all-lowercase when + applied to the "library". [Steven M. Schweda, Chr. Spieler] + - vms/vms.c - return_VMS(): corrected mapping of PK_WARN to VMS status code + severity level "Warning" (fixed regression bug introduced in UnZip 5.32). + [Steven M. Schweda] + - process.c: preliminary fixed Zip64 support to match 4.5 AppNote, removing + the 76 byte error [EG] + +6.00d02 (08 Mar 07): + - extract.c: corrected typo (missing ";") in SYMLINKS code. [Steven M.Schweda] + - VMS: updated MMS/MMK scripts (adapt for case-sensitive ODS5 and changed/new + source/header files). [Steven M. Schweda] + - vms/vms.c: provide RMS resp. QIO re-read functionality for SYMLINKS support. + [Steven M. Schweda] + - vms/vms.c: revised SYMLINKS support (no special symlinks handling in -c, -p + piping output mode, fixed buffer overflow security holes, moved symlink + post-processing from close_outfile into the mode-specific subroutines, + for "-V archived" entries the symlink target spec is only read back when + needed for informational display purpose). [Christian Spieler] + +6.00d03 (10 Mar 07): + - vms/vms.c: modified style of static function declarations into "independent" + lines (on request of Steven M. Schweda). [Chr. Spieler] + - vms/vms.c: checked compilation, removed typos and wrong-named variables + [Chr. Spieler] + +6.00d04 (11 Mar 07): + - vms/vms.c: used "better self-documenting" names for qio status structures, + corrected/enhanced some error messages (unified formatting, specified + "location" in code). [Steven M. Schweda] + - unix/Makefile: added some (preliminary) support for compiling with optional + bzip2 decompression capability (mostly copied from msdos/Makefile.dj2, + is not yet tested). [Chr. Spieler] + - process.c: added additional consistency checks to find_ecrec64(). + - extract.c, list.c, zipinfo.c: reviewed the "central dir processing complete" + check to take into account the new status semantics from find_ecrec64(). + [Chr. Spieler] + +6.00d05 (31 Mar 07): + - Win32 port: added VC6 project files for "minimal" bz2lib and unzip with + bzip2 support. [Chr. Spieler] + - list.c: added missing "PPMd" entry to array of known compression methods. + [Chr. Spieler] + - vms/vms.c: close a potential buffer overflow hole in symlinks handling code. + [Chr. Spieler] + - inflate.c - inflate_dynamic(): fixed erroneous huft_free() calls for + unallocated memory when processing invalid data. [Chr. Spieler] + - crc32.[ch], crc_i386.S: added updated files that were accidentally missed + in update 6.0d01. [Chr. Spieler] + - bz2lib renamed to bzip2 at request from Ed Gordon and Steven M. Schweda, + updated affected makefiles (MS-DOS, Unix, Win32). [Chr. Spieler] + - renamed "Novell" port to "Netware" for clarity. [Chr. Spieler] + - win32.c - close_outfile(): on WinNT, truncate outfile to actual bytes + written before close; otherwise, preallocated disk space does not get freed + when extraction failed or was interrupted. [Chr. Spieler] + - process.c: corrected bugs in ecloc64 and ecrec64 recognition code. + [Ed Gordon] + - process.c: some cleanup in debugging code (changed TTrace() to Trace() in + non-timestamp-related code portions. [Chr. Spieler] + - unzip.h: updated license text to last version of License. [Chr. Spieler] + +6.00d06 (02 Dec 07): + - bzip2/makbz2iz.msc, bzip2/makbz2iz.wat: hide individual commands of the + `clean' target. [Chr. Spieler] + - extract.c: corrected "extracted" message for bzipped entries to "bunzipped" + [Steven M. Schweda] + - unzpriv.h: removed "suspicious" explicit mask from Zip64 version of + MASK_ZUCN64 preprocessor constant. [Steven M. Schweda] + - extract.c - fnfilter(): added check against internal buffer overflow. + [Chr. Spieler] + - unzpriv.h, fileio.c, win32/w32cfg.h, wince/wcecfg.h: repaired the MBCS + definition for the CLEN() macro; this macro is assumed to return a strictly + positive byte count. [Kazuki Matsuda, Chr. Spieler] + - unix/zipgrep: return the correct exit code from egrep even in cases where + the egrep output is further piped through sed. [Niklas Klein] + - vms/vms.c: corrected case of the "__ia64" predefined preprocessor symbol. + [Steven M. Schweda] + - bzip2/descrbz2.mms: added make Info-ZIP specific VMS make script, as a + starting point for integrated bzip2 compilation support in a similar + way to other OS (Win32, Unix). (not yet working, requires more work to + get completed and debugged...). [Chr. Spieler] + - win32/makefile.bc, win32/makefile.gcc, win32/makefile.wat: completed clean + target functionality. [Chr. Spieler] + - win32, wince: added workaround to keep Visual Studio 2005 C compiler quiet. + [N.N.] + - unzpriv.h, extract.c, list.c, zipinfo.c: added "WavPack" (supported by + WinZip 11+) to list of recognized compression types. [Christian Spieler] + - win32/nt.c: prevent calling IsValidAcl() with a NULL Acl pointer, to fix + false 'EA security check' failures. [Will Menninger] + - renamed proginfo/extra.fld into proginfo/extrafld.txt, to synchronize with + Zip3. [Chr. Spieler] + - process.c: added second try to find the EOCD64 record, to compensate for + (SFX-stub) bytes prepended to the archive without adjustment of the offset + records in the Zip file structures. [Will Menninger, Ed Gordon] + - fileio.c, process.c: replaced spurious use of Z_OFF_T by zoff_t. + [Chr. Spieler] + - win32/win32.c - utime2VFatFileTime(): initialize the wMillisecond field of + the SYSTEMTIME structure to 0 to ensure deterministic time conversion. + [N.N.] + - explode.c: corrected type for data stream size variables from zoff_t into + zusz_t. [Chr. Spieler] + - unix/configure, unix/Makefile: made automatic detection & compilation of + bzip2 support working for the 'generic' target. [Chr. Spieler] + +6.00d07 (26 Dec 07): + - fileio.c: old-style function head for fzofft(). [Steven M. Schweda] + - acorn/makefile: updated to support bzip2 decompression (change was missed + for 6.00d06). [Chr. Spieler] + - unix/configure: added/modified cc optimization checks [Steven M. Schweda] + - unix/unix.c: added detailed IBM C version reporting to version(). + [Steven M. Schweda] + - unix/unxcfg.h: use __hpux instead of __HP_cc to determine UTIMEBUF + configuration [Steven M. Schweda] + - unzip.h, unzip.c: removed IZ_COMPERR runtime error code. This code was only + used in compile-time assertions of development code and did never get into + a production environment. [Chr. Spieler] + - vms/vms.c, vms/UNZIP_MSG.MSG, vms/unzip_def.rnh, vms/unzip_cli.help: removed + IZ_COMPERR support and documentation; debugging code should not be + mentioned in end-user documentation. [Chr. Spieler] + - unzpriv.h: use __hpux instead of __HP_cc to determine support of "long long" + type for HP (bundled ??) compiler. [Steven M. Schweda] + >>> This change may be wrong?? "long long" support is a compiler feature, + not a runtime library feature! [Chr. Spieler] <<< + - VMS: added message file build to make procedures (missed change from + 6.00d06). [Steven M. Schweda] + - wince/wcemain.c: added missing modifications from unz553d beta (25 Dec 06), + see also "wince/wcemain.c" changelog entry for 6.00d01. [Chr. Spieler] + - fileio.c - uzmbclen(): corrected return type definition. [Chr. Spieler] + - win32/nt.c: added some typecasts in Initialize() to get newer gcc quiet. + [Chr. Spieler] + - win32/win32.c: added some superfluous variable initializations to prevent + gcc compiler warnings. [Chr. Spieler] + - bzip2/descrbz2.mms: made MMS description file work (at least on OpenVMS 8.3 + IA64 testdrive account). [Chr. Spieler] + - vms/descrip_src.mms: modified bzip2 support so that it works with the + library created by bzip2/descrbz2.mms, using the original bzip2 1.0.4 + sources. [Chr. Spieler] + +6.00d08 (29 Dec 07): + - bzip2/descrbz2.mms: modified compile options to create a library which is + binary compatible with the results of the SMS-specific deviated bzip2 + distribution for VMS. [Chr. Spieler] + - bzip2/buildbz2.com: new VMS DCL build script for the bzip2 "BZ_NO_STDIO" + library used by the bzip2 support in UnZip. [Chr. Spieler] + - vms/descrip.mms, vms/descrip_src.mms: changed back so that the SMS-specific + deviated bzip2 source package works again; added/completed support for + standalone bzip2-included build using bzip2/descrbz2.mms. [Chr. Spieler] + - vms/make_unz.com, vms/link_unz.com: removed these obsolete files, they have + been replaced by vms/build_unzip.com. [Chr. Spieler] + - vms/build_unzip.com: added support for compiling bzip2-enabled programs + in "standalone" source setup, using bzip2/buildbz2.com for creating the + bz2 object library. [Chr. Spieler] + - updated the UNICODE_SUPPORT code from Ed Gordon's work (6.00d05t, excluding + the win32-wide specific code). This code is unfinished, besides other + issues there is a memory leak to be fixed. [Ed Gordon, Chr. Spieler] + - unzip.c: Added "static" to test_buf definition in the "NEXTBYTE operation + test" code block of main function unzip(). [SMS] + - unzpriv.h: Added -related stuff from 6.00d05t (SMS), with some + corrections. [Steven M. Schweda, Chr. Spieler] + +6.00d09 (06 Jan 08): + - unzip.c: corrected parser code for "negated -D" option. [Steven M. Schweda] + - man/unzip.1: extended explanation of the VMS-specific differences in the + "-D" option behaviour for clarity. [Steven M. Schweda] + - vms/unzip_cli.cld, vms/cmdline.c: corrections and refinements applied to + the CLI parsing code for the new "-D" option. [Steven M. Schweda] + - vms/INSTALL.VMS: added/updated build description aspects concerning optional + bzip2 support. [Steven M. Schweda] + - vms/unzip_cli.help: clarified description of the changed and extended + /RESTORE qualifier. [Steven M. Schweda] + - vms/vms.c, vms/vms.h, vms/cmdline.c, ttyio.c: Added defines to translate all + used system routine names to uppercase, to allow using /NAMES=AS_IS with + the broken header files of older DECC distributions. [Steven M. Schweda] + +6.00d10 (10 Feb 08): + - globals.h, process.c, fileio.c: fix memory leak concerning filename_full + handling (UNICODE_SUPPORT code). [Chr. Spieler] + - ubz2err.c: renamed formal parameter "errcode" into "bzerrcode" to work + around a bug in MS Visual C++ 9.0 (2008). [Chr. Spieler] + - VMS: small cleanups to CLI code. [Steven Schweda, Chr. Spieler] + - vms/vmscfg.h: added missing cma$tis_errno_get_addr uppercase define for + broken compiler distributions. [Steven Schweda, Chr. Spieler] + - vms/descrip_mkdeps.com: Added CLEAN and CLEAN_ALL targets. [Steven Schweda] + - win32, windll: added MS VC++ 8.0 project files. [Chr. Spieler] + - win32/Makefile: removed dependency on ntwin32.mak, for better compatibility + with VC++ 8.0 Express Edition. [Chr. Spieler] + - api.c: moved include down behind "unzip.h" include to shut up + "depreciation" warnings with VC++ 8.0 and newer. [Chr. Spieler] + - windll/struct.h: added D_flag support to option structure. [Chr. Spieler] + - windll/vb/vbunzip.bas: corrected UZDLLPAss callback function interface, + adapted to recent DLL interface changes. [Johnny Lee, Chr. Spieler] + - windll: removed "DESCRIPTION" clause from all module definition files; + newest VC++ version does no longer tolerate it. [Chr. Spieler] + - unzip.h: enable H_flag and U_flag for UNIX, VMS, WIN32 (those systems that + are currently supposed to support UTF8 names); unzip.h must not depend on + internal configuration settings like UNICODE_SUPPORT. [Chr. Spieler] + +6.00d11 (16 Feb 08): + - vms/cmdline.c: canceled name-change for local variable 'restore_date' + (was incomplete in 6.00d10 and broke compilation). [Chr. Spieler] + - unzpriv.h: removed "fixed" allocation of space for the two string + delimiters from the definition of type slinkentry. [Steven M. Schweda] + - unix/unix.c - set_symlnk_attribs(): modified usage of typecasts to remove + some compiler warnings. [Steven M. Schweda] + - aosvs, atari, atheos, beos, unix, vms - close_outfile(): Increased the + allocation size for the slnk_entry structure by 2 for the two '\0' + end-of-string markers. [Chr. Spieler] + - unix/Makefile: modified bzip2 lib target to be only applicable to the + bzip2 subdir of the UnZip distribution. [Chr. Spieler] + - unix/configure: extended bzip2 support check from Zip's configure to better + support "externally" supplied bzip2 libraries. [St. Schweda, Chr. Spieler] + - vms/descrip_src.mms, bzip2/descrbz2.mms: cleaned up VMS MMS support for + integrated build of bzip2-enabled UnZip executables. [Chr. Spieler] + - msdos, unix, vms, win32: at request from SMS, changed all occurrences of + "DIR_BZ2LIB" symbol in build scripts for the directory of the bzip2 library + sources (and often also binaries) into "IZ_BZIP2", for synchronization + with Zip. [Chr. Spieler] + +6.00d (17 Feb 08): + - win32/Makefile: fixed configuration variations of bzip2 support when using + non-standard build options regarding rtl linking; added documentation + section for the supported build variant flags on the nmake command line. + [Chr. Spieler] + +6.00e01 (17 Feb 08): + - unzpriv.h: re-added "fixed" allocation of space for the first of two string + delimiters from the definition of type slinkentry, the "buf[]" structure + member is not accepted by some older compilers. [Chr. Spieler] + - aosvs, atari, atheos, beos, unix, vms - close_outfile(): Reduced the + allocation size for the slnk_entry structure by 1, one of the two '\0' + end-of-string markers is again part of the structure. [Chr. Spieler] + - unix/configure: export CC and IZ_BZIP2 symbols to flags, to feed their + current settings to the child make process without having to use special + make command qualifiers. [Steven M. Schweda, Chr. Spieler] + +6.00e02 (08 Mar 08): + - unix/unix.c - close_outfile(): added missing semicolon in the SYMLINKS code + for the non-SET_SYMLINK_ATTRIBS case. [Steven M. Schweda] + - unzip.c: removed extra "credit to Myles Bennet" note from startup screen + for space considerations; added credit note to README and referenced + Myles Bennet in proginfo/CONTRIBS. [Chr. Spieler] + - vms/vms.c: fixed dir separator find logic in vms_path_fixdown() for cases + where directory name contains a '.' or '[' itself. [Steven M. Schweda] + - crc32.h: replaced explicit inclusion of zip.h by a note that this header + should be read after zip.h resp. unzip.h. [Steven M. Schweda, C. Spieler] + - unix/configure, unix/Makefile: cleaned up auto-configured build procedure. + * pass the "configure"-selected C optimizations to the bzip2 build process. + * clean only affects the unzip-specific bzip2 subdirectory. + * let make display the bzip2 clean subprocess call. + [Steven M. Schweda] + - unzip.c, unzip.h, zipinfo.c, fileio.c - UNICODE_SUPPORT, revised the + options to control UTF-8 handling: + * removed the -H option + * modified -U option syntax: -U forces to escape all non-ASCII UTF-8 chars, + -UU must be used now to entirely disable UTF-8 support. + [Chr. Spieler] + - windll/windll.{c|txt}: added U_flag to option stucture. [Chr. Spieler] + - man/unzip.1, man/zipinfo.1: added description of the new UTF-8 related + syntax for the -U option. [Chr. Spieler] + - win32/w32cfg.h, wince/wcecfg.h: enabled UNICODE_SUPPORT by default. + [Chr. Spieler] + - win32/Makefile: adapted to modified UNICODE_SUPPORT default. [Chr. Spieler] + - wince/intrface.cpp - close_outfile(): moved local (wide string) copy of + filename outside of conditional "set timestamps" block. [Chr. Spieler] + - unzpriv.h: do never include here for the wince port (_WIN32_WCE or + POCKET_UNZIP), this must be handled elsewhere for C++. [Chr. Spieler] + - unzip.c: removed the -U option description from the introductory screen for + WIN32 because of lacking space. Maybe, these "debugging" options should not + be shown there at all. [Chr. Spieler] + +6.00e03 (29 Mar 08): + - unix/configure: corrected detection of ANSI C vs. bundled C compiler on + HP-UX. [Steven M. Schweda] + - VMS, unzip.c: help screen extended to show correct "-D" semantics for the + special VMS defaults. [Steven M. Schweda] + - unix/Makefile: added "generic_gcc" target, using auto-configuration with + GNU compiler. [Steven M. Schweda] + - unzip.c: renamed error message constant for clarity. [Chr. Spieler] + - unshrink.c: revision to fix long-standing decompression bug, added boundary + checks to detect invalid compressed data. [Santiago Vila, Chr. Spieler] + - extract.c: added error message handling for "invalid data" errors from + unshrink(). [Chr. Spieler] + - process.c, unzpriv.h: disabled compilation of unused UNICODE_SUPPORT helper + function. [Chr. Spieler] + - process.c, win32/win32.c: added special win32-only version of the + wide_to_local_string() helper function to work around "ANSI vs. OEM" + codepage problems with non-Microsoft C-runtime libraries. [Chr. Spieler] + - zipinfo.c - zipinfo(): corrected "back at end-of-cdir" check (synchronized + it with the corresponding list_files() code). [Chr. Spieler] + - fileio.c - do_string(): closed UNICODE_SUPPORT related memory leaks + (free allocated utf8 buffers when no longer used). [Chr. Spieler] + - vms/vms.c - set_direc_attribs(): do not restore any size info from the + (PK-style) extra field record attributes settings. The new directory + created during extraction may contain fewer (restored) entries than the + original source folder, so that the old non-matching size data would + result in corrupted interal directory structures. [Steven M. Schweda] + +6.00e04 (27 Apr 08): + - vms/vms.c - set_direc_attribs(): fixed NAM[L] initialization for the + "normal" non-VMS-attributes case. [Steven M. Schweda] + - vms/NOTES.TXT updated (version copied from zip30h05). [Steven M. Schweda] + - unzip.c, vms/NOTES.TXT: added SYMLINKS to the special compilation options + reported by show_version_info(); updated Symbolic Links section in + NOTES.TXT. [Chr. Spieler] + - INSTALL: added documentation for the new UNICODE_SUPPORT related options. + [Chr. Spieler] + - README: added anouncement of the new UTF-8 coded entry names support. + [Chr. Spieler] + - fileio.c, process.c, unzip.c, globals.h, unzpriv.h, win32/w32cfg.h, + wince/wcecfg.h : revised the UNICODE_SUPPORT code, added direct support for + UTF-8 being the native MBCS char encoding, allowed separate activation of + the "UTF-8 is native character coding" and the "translate UTF-8 <==> native + extended-ASCII via Unicoded wchar_t" support methods. [Chr. Spieler] + - unix/configure, unix/Makefile: extended configure script to support + automatic selection of UNICODE_SUPPORT support on capable systems, + completed configuration support for the linking step. [Chr. Spieler] + - unix/unxcfg.h: changed interdependency rules of LARGE_FILE_SUPPORT and + ZIP64_SUPPORT to prevent unsupported symbol combinations. [Chr. Spieler] + - man/unzip.1: extended description of -U option to mention the #Lxxxxxx + escape format for characters beyond the basic unicode page. [Chr. Spieler] + - proginfo/extrafld.txt: updated wording and line wrapping of Info-ZIP + Unicode extra fields. [Chr. Spieler] + +6.00e05 (09 Sep 08): + - unix/unix.c - version(): added OS info support for Mac OS X (including a + note for the recognized CPU architecture). [Steven M. Schweda] + - unix/configure: check for Mac OS X special linker options is only executed + on systems that have been identified as Mac OS X. [Steven M. Schweda] + - unix/Makefile: moved "solaris" targets into new "autoconfig generic" group + of machine target aliases. [Steven M. Schweda, Chr. Spieler] + - extract.c, fileio.c: use "sizeof(G.answerbuf)" as length argument in fgets() + calls, for better robustness and "in-code" documentation. [Chr. Spieler] + - extract.c - extract_or_test_entrylist(): fixed handling of \n in response + to "overwrite (y/n/r)" prompt. [Steven M. Schweda, Chr. Spieler] + - extract.c, special version of "replace file" prompt for VMS to take into + account that VMS normally created a new version instead of overwriting + an existing file. [Steven M. Schweda] + - unzpriv.h: for VMS, undefine the PATH_MAX definition provided by , + because it does not take into account long name support of ODS-5 volumes. + [Steven M. Schweda] + - VMS: added zlib.h and infback9.h jacket headers for support of using zlib + as inflate decompression code; revised build procedures for zlib support + (build_unzip.com, descrip.mms, descrip_src.mms). [Steven M. Schweda] + - inflate.c: corrected condition when to include "infback9.h" for Deflate64 + support with zlib 1.2.x. [Chr. Spieler] + - extract.c: standardized wording of error messages in SET_DIR_ATTRIBS code. + [Steven M. Schweda] + - vms/vms.c - set_direc_attribs(): ensure that the FAB block used is properly + initialized. [Steven M. Schweda] + - aosvs, atari, atheos, beos, unix - mapname(): for all "unix-like" ports, the + reserved file names "." and ".." are mapped to "_" resp. "__". + [Steven M. Schweda, Chr. Spieler] + - list.c - changed listing layout to emit four-digit years for file + date-time-stamps. [Ed Gordon, Chr. Spieler] + - process.c - find_ecrec(): fixed zipfile comment handling within the Zip64- + compatible end-of-central-dir records scanning, to take into account that + the file pointer is no longer at the zipfile end when the eocdrec scanning + has finished. [Chr. Spieler] + - process.c, zipinfo.c: revised and reorganized zipinfo log header output; + the zip archive comment has to be reported before all of the eocdir info + could be collected. [Chr. Spieler] + - man/unzipsfx.1 - Debian patches 4461_002 and 5293_009 fixing text errors; + correct spelling of similarly and additional per debian patch; correct + wrong formatting command \P to \fP. [sanvila] + - vms/build_unzip.com: fixed integrated bzlib build support. [Chr. Spieler] + +6.00e06 (13 Sep 08): + - unix/unix.c - set_symlnk_attribs(): removed erronous surplus line with only + "if" on it. [Steven M. Schweda] + - vms/descrip_deps.mms: restored correct file which was accidentally + overwritten by vms/descrip_src.mms. [Steven M. Schweda] + - vms/build_unzip.com: optimized the distinction between "compile destination + subdir" for integrated BZIP2 compilation (should distinguish between the + different compilers supported for VAX) and "external library dir" for + user-supplied BZIP2 (and ZLIB) libraries (user-supplied library is expected + to work with any supported compiler on VAX, so no dependency on the + specific compiler used). [Steven M. Schweda] + - unzip.c: replaced tab characters in output messages by appropiate number of + spaces (assuming standard tab spacing of 8 chars), to prevent mis-formatted + output on terminals with non-standard tabstop settings. [S. M. Schweda] + - unix/unix.c + * set_symlnk_attribs(): fixed uid/gid size check before calling lchown(); + * set_direc_attribs(): repared wrongly inserted patch and fixed uid/gid + size check before calling chown(). [Chr. Spieler] + - vms/vms.c: fixed user-query code for existing files on VMS when extracting + in "-V" mode (retaining version numbers); fixed some problems with exotic + extended ODS5 file names, and files named ".". [Steven M. Schweda] + - vms/cmdline.c, vms/unz_cli.cld: extended CLI to support the new extended + meaning of the -o flag (-oo => "overwrite ALL existing" when retaining + version numbers ("-V") and extracting archive members with attached version + number (new /EXISTING option). [Steven M. Schweda] + - extract.c - extract_or_test_entrylist(): added code to skip the generic user + query "overwrite (y/n/r)?" when extracting an entry with attached version + number in "-V" (keep version number) mode. [Steven M. Schweda, C. Spieler] + - vms/unzip_cli.help, vms/unzip_hlp.rnh: updated documentation to reflect the + UI extension to handle VMS-specific "overwrite or new version" settings. + [Steven M. Schweda] + - unzip.c: added VMS specific -n and -o (-oo) option description sections + to online help screen definitions. [Steven M. Schweda] + - vms/cmdline.c: corrected some small formatting issues in online help output. + [Chr. Spieler] + - vms/unzip_cli.help, vms/unzip_hlp.rnh: corrected a few typos and updated the + help screen for the "unix-style" commands in the CLI help. [Chr. Spieler] + - vms/vms.c, extract.c, unzpriv.h: fixed the the error handling of the VMS- + specific "newver/overwrite/skip" query by extending the return code range + of open_output() for VMS, without any new global data. [Chr. Spieler] + +6.00e (04 Jan 09): + - fileio.c: changed tmpstat from struct stat to z_stat. [EG] + - unzip.c: expanded extended help to include unzip and zipinfo options. [EG] + - man/unzip.1: updated multi-part archive information; minor additions + to authors activities list. [EG] + - fileio.c: added strerror(errno) output to CannotCreateFile message. [SMS] + - unix/unix.c: add more detailed error message using strerror() when a + file error occurs. [SMS] + - unix/zipgrep - add additional information to top. Clean up some lines and + add commments. Added code to handle backslashes in archive file names, + and shell-special characters in the pattern. Changed to use "sed" for all + escaping of shell-special characters. Tried to get the exit status to + follow the status of egrep in the complex (default) situation, using only + standard Bourne shell features, and to exit early if egrep returns + status 2 (error). [SMS] + - vms/unzip_cli.help - VMS help updates. [SMS] + - vms/unzip_def.rnh - synchronized option description with unzip_cli.help. + [Chr. Spieler] + - fileio.c: extend backup number range from 65535 to 99999 on 32-bit systems; + fixed limit detection on 16-bit systems. [Chr. Spieler] + - zipinfo.c: changed date layout of "short" (one-line) zipinfo modes to always + use ISO-style YMD order. [Chr. Spieler] + - unix/configure: added a simple compiler test to check for a working C + compiler setup. [Steven M. Schweda] + - cmsmvs/vmmvs.h: removed __EBCDIC preprocessor symbol definition (not used + anywhere in UnZip, breaks compilation on Z-OS). ["Lutz", Chr. Spieler] + - unix/makefile - moved -L link option earlier in unzip$E rule. [Lutz] + - unzip.c - Remove "s" from "permits" in SYMLINKS feature message. [SMS] + - vms/vms.c: simplified the scheme to escape non-last dots, for compatibility + with modifications in Zip 3.1. [SMS] + - vms/vms.c, vms/vms.h, function create_qio_output(): revised NMCTL flag + handling ("overwrite or create-new" code) to be VAXC compatible. [SMS] + - extract.c - extract_or_test_entrylist(): removed '\n in middle of WINDLL + "file exists ... skipping" message to get it displayed on one line. [EG] + - man/unzip.1, INSTALL: updated/corrected documentation for the UNIXBACKUP + feature and the description of its -B qualifier. [Chr. Spieler] + - proginfo/ziplimits.txt: updated discussion of program implementation limits + to the state of "released" Zip 3.0 and UnZip 6.0. [EG, Chr. Spieler] + - README, Bugs, ToDo: updated and syncronized documentation for release + candidate. [Chr. Spieler] + - windll/structs.h: added structure version id field at the "top" of the + "DCL" options struct. [EG] + - windll/structs.h: added UZ_DCL_STRUCTVER preprocessor symbol, holding the + currently valid version id of the DCL structure definition. [Chr. Spieler] + - windll/windll.c - Wiz_SetOpts(): exit function if version id of passed in + "DCL" structure is not equal to the expected setting. [EG, Chr. Spieler] + - windll/unexampl.c: synchronized with recent WinDLL option structure + addition. [EG, Chr. Spieler] + - windll/vc?/exampl/c_dll_ex.[dsp|vcproj]: new Visual Studio project files + for building the WinDLL C usage example uzexampl.exe. [EG, Chr. Spieler] + - windll/vb/vbunzip.bas: changed DLL interface to use UZxxx_I32 variants of + callback functions that split 64-bit values into high and low part 32-bit + integers that can be handled by VB(A)5/6. Inside the VB code, low and + high parts are added up in Currency type variables. Converted \ to / in + duplicate file message. Fixed MsgBox flags concatenation. Added support + for new OverwriteAll checkbox. [EG] + - windll/vb/vbunzip.frm: added OverwriteAll checkbox, added resizing to + txtMsgOut output box. [EG] + - windll/vb/vbunzip.frm, windll/vb/vbunzip.bas: cleaned up and completed the + recent modifications, resynchronized with WinDLL interface with UnZip 6.0 + master source, removed all modification incompatible with VB5, fixed the + UZDLLServ_I32() callback calling interface, used Double instead of + Currency as Int64 summation type to prevent potential numeric overflow + issues. [Chr. Spieler] + +6.00f (11 Jan 09): + - INSTALL: added notes on the difference between "old" Macintosh OS and + current Apple Mac OS/X, which is supported as a BSD Unix port . [EG] + - unzip.c - help_extended(): added some documentation about funzip and + unzipsfx stub. [EG] + - windll/csharp/: updated C# example to match the current Zip64-compatible + WinDLL API, revised string parameter marshalling, initialized/resetted + job statistic counters, added OverwriteAll checkbox. [Chr. Spieler] + - win32/Makefile: the DLL example frontend is now compiled with the same + runtime library settings as the DLL binary. [Chr. Spieler] + - LICENSE: updated to version 2009-Jan-2, which removes the requirement to + provide the LICENSE in documentation with distribution of binaries when + the redistributed programs support display of the LICENSE by some command + line option. [EG] + - vms/vms.h, vms/vms.c: moved "lowercase to uppercase mapping" define of + sys$setdfprot from vms.c into vms.h in front of the starlet.h include, + where all the other name case mappings are located. [Steven M. Schweda] + - vms/vms.c: made the declaration of sys$setdfprot() always active when + the SETDFPROT symbol is defined. [Chr. Spieler] + - unix/unix.c: added strerror(errno) output to various "Cannot..." I/O error + messages (in checkdir(), close_outfile(), set_symlnk_attribs()). + [Steven M. Schweda, Chr. Spieler] + - fileio.c - open_outfile(): added strerror(errno) output to the error + messages "cannot rename ..." and "cannot delete ...". [Chr. Spieler] + - fileio.c - do_string(): corrected string length passed to win_fprintf() + (comment string may get shortened by CRLF->LF translation). [Chr. Spieler] + - beos/beos.c, beos/beocfg.h, aosvs/aosvs.c, win32/win32.c: extended various + "Cannot..." I/O error messages with strerror(errno) output, to synchronize + code with current state of the Unix port. [Chr. Spieler] + - unzip.c, unzpriv.h, unix/configure: added better check for UTF-8 codeset + using nl_langinfo() function, as suggested on the sourceforge.net forum; + added nl_langinfo() to the "function existence" checks in the configure + script. [Chr. Spieler] + - wince/intrface.cpp: added missing wide_to_local_string() function from + win32.c (is [currently] needed in process.c). [Chr. Spieler] + +6.00g01 (18 Jan 09): + - extract.c, windll/structs.h, windll/windll.txt: added a bufsize parameter + to the "replace()" callback function, updated UZ_DCL_STRUCTVER setting to + 0x600. [Chr. Spieler] + - windll/uzexampl.c, windll/csharp/Unzip.cs, windll/vb/vbunzip.bas, + windll/guisfx/sfxwiz.c, wince/intrface.cpp: adapted frontend code to the + "replace()" callback function signature change; updated DCL.StructVersID + setting to reflect the change in the DLL code; added check against password + buffer overflow (not in uzexampl.c). [Chr. Spieler] + - windll/vb/vbunzip.frm: removed obsolete comment. [EG] + - windll/csharp/ReadMeCS.txt: added note on problem with Visual Studio 8.0 + and 9.0 when used with unzip32.dll that was linked against the Visual + Studio version of the MS C runtime dll. [Chr. Spieler] + - unix/Makefile: consistent use of "$E" for executable filename extension; + fixed dependency of binary builds on system specific config header; added + dependency of autoconfigured "generic" builds on the configure result. + [Chr. Spieler] + - unzip.c: added hint to "unzip -hh" extended help display to the short help + screen. [Chr. Spieler] + - unzip.c - help_extended(): removed superfluous "]", corrected availability + info for the "-B" option. [EG, Chr. Spieler] + - man/unzip.1, unzip.c, vms/unzip_def.rnh, vms/unzip_cli.help - modified + description of -X option for VMS to emphasize that this option controls + restoration of ACL protection info, whereas the standard S/O/G/W access + restrictions get always restored. [SMS, H. Goatley, Chr. Spieler] + - unzip.h, api.c, unzipstb.c, unzvers.h, windll/windll.txt, + windll/vb/vbunzip.bas: + revised and extended the "version info retrieve" function calls, added + version identifier for the "last incompatible API change", fixed version + structure size handling, updated API documentation. [Chr. Spieler] + - windll/windll.c - UnzipAllocMemory(): fixed operator precedence bug by + adding explicit parenteses. [Chr. Spieler] + - win32/Makefile.wat: added missing rule for crc32f.obj. [Chr. Spieler] + - unzip.c - uz_opts(): corrected parameter list for call of help_extended(). + [Chr. Spieler] + - unix/Makefile: adapted linux_shlib and linux_shlibz targets to work with + the changed organisation of the assembler CRC code. [Chr. Spieler] + +6.00g02 (25 Jan 09): + - History.600, unzpriv.h, unix/unix.c: corrected/unified spelling of + "dependent" and "dependence". [Steven M. Schweda] + - api.c - UzpVersion2(): added forgotten setting of dllapimin version info + (similar to UzpVersion()). [Chr. Spieler] + - unzipstb.c, windll/uzexampl.c, windll/uzexampl.h: extended DLL version + display to report the new "DLL API" version info; added compatibility + checks for version of loaded dll, using the recently added additional + API version info. [Chr. Spieler] + - windll/uzexampl.c: changed program return values to follow common usage + (0 for no error, -1 for fatal abort, unzipdll return code otherwise). + [Chr. Spieler] + - windll/vb/VBReadMe.txt, windll/vb/vbunzip.bas: revised and extended + documentation of unzip32.dll search process flow, added warning note + explaining the unexpected "dll not found" errors when running the VB code + inside the VB IDE. [Chr. Spieler] + - windll/vb/vbunzip.bas: added version/api compatibility checks for the + loaded unzip32.dll, aborting the program in case of any detected + incompatibility. [Chr. Spieler] + +6.00g03 (10 Feb 09): + - README, History.600: documented support for new 32-bit UID/GID extra field + on Unix. [Ed Gordon, Chr. Spieler] + - unzip.h: added "old lib swprintf" compatibility clause for Pocket-UnZip + (WinCE) to support current Visual Studio versions 8 and 9. [Chr. Spieler] + - wince/wcecfg.h: switched off UNIX_BACKUP for WinCE (rename() function not + available on Windows CE); moved the (none-WCE) configuration setup for + Zip64 support to the end (behind all header includes). [Chr. Spieler] + - wince/wince.h: added guard against redefinition of isalpha() macro. + [Chr. Spieler] + - wince/intrface.cpp - win_fprintf(): reordered local loop counter variable + declaration to achieve compatibility with standard C++ (without breaking + the non-standard MS VC++ 6.0 variant). [Chr. Spieler] + - extract.c, list.c, process.c, zipinfo.c: replaced strncmp() by memcmp() + when comparing against "binary" signatures. [Chr. Spieler] + - process.c - wide_to_escape_string(): fixed a "write to unallocated memory" + bug. [Chr. Spieler] + +6.00g04 (16 Feb 09): + - unzpriv.h: mapped zfseeko and zftello to C rtl supplied functions for MS + C runtime of VC 8.0 or newer. [Chr. Spieler] + - win32/win32i64.c: revised zfseeko() code to correctly clear the eof state + (and for "MSVC 6.0 or newer" rtl environments: manipulate internal flag + to prevent clearing a ferror() state). [Chr. Spieler] + - windll/vc5/, windll/vc6/, windll/vc8/: added "link against static C rtl" + configurations to the unzip32 dll and c_example projects. [Chr. Spieler] + - win32/vc8/, windll/vc8/: removed "UpdateFromVC600" property sheet settings, + they are not needed. [Chr. Spieler] + - windll/guisfx/sfxwiz.c: added compatiblity preprocessor switches to shut up + MS VC 8 (and newer) complaining about depreciated standard C functions. + [Chr. Spieler] + - INSTALL, windll/Contents: added notes about different runtime configurations + (linking against C rtl dll vs. static C rtl lib) when building the UnZip + DLL. [Chr. Spieler] + +6.00g (28 Feb 09): + - unzip.c: cleaned up the UTF-8 check according to the code found in the + latest Zip 3.1 beta, removed the "switch to UTF-8 codeset" code because + it proved to not work as expected. [Ed Gordon, Chr. Spieler] + - win32/w32cfg.h: use rtl-provided MBCS functions for MinGW32 when compiled + and linked against msvcrt.dll. [Chr. Spieler] + - extract.c - fnfilter(): added "enhanced" non-printable charcode filtering + when a locale-aware isprint() implementation is available (controlled by + the preprocessor symbol HAVE_WORKING_ISPRINT). [Chr. Spieler] + - win32: enabled "enhanced" fnfilter() filtering for compiler environments + using MSVC 6.0 (or newer) runtime, and for Borland C. [Chr. Spieler] + - vms: enabled "enhanced" fnfilter() filtering using isprint(), may get + disabled by defining the NO_WORKING_ISPRINT symbol. [Chr. Spieler] + - unix/unxcfg.h: enabled "enhanced" fnfilter() filtering when setlocale() is + available (NO_SETLOCALE is not defined). [Chr. Spieler] + - unix/configure: added NO_SETLOCALE define when setlocale() check fails. + [Chr. Spieler] + - INSTALL: added documentation of NO_SETLOCALE and HAVE_WORKING_ISPRINT resp. + NO_WORKING_ISPRINT symbols. [Chr. Spieler] + - general: unified spelling of "wildcard". [Chr. Spieler] + +6.00h01 (09 Mar 09): + - vms/vms.c: added missing case-translation define for sys$getdvi(), for + support of /NAMES=AS_IS with older DECC distributions. [Steven M. Schweda] + - vms/build_unzip.com, vms/descrip.mms, vms/descrip_src.mms: resolved a + /NAME=AS_IS case issue by changing the linking command for bzip2-enabled + builds to read the unzip code library twice (before and after the bzip2 + object library) to resolve the bzip2 error callback, instead of explicitely + loading the callback function. [Steven M. Schweda] + - vms/NOTES.TXT: cleaned up wording of the Symbolic Links section. [SMS] + - extract.c, fileio.c, process.c, unzpriv.h: fixed recognition of "native + UTF-8" general purpose flag bit 11 when processing local header, added + check against mismatching central vs. local GPFlag bit 11 (not for SFX) + with warning display (suppressible by -q command qualifier). [C. Spieler] + +6.00h02 (16 Apr 09): + - extract.c: fixed evaluation sequence of check expression by adding correct + pairs of parentheses. [EG, SMS] + - unix/configure: added working check for lchmod. [SMS] + - unzip.c: added compile option display for MBCS support. [Chr. Spieler] + - unzpriv.h, unix/unxcfg.h, win32/w32cfg.h: the new preprocessor symbol + NO_MBCS allows to explicitely disable MBCS support. [Chr. Spieler] + - INSTALL: documented _MBCS and NO_MBCS preprocessor symbols. [Chr. Spieler] + - unix/configure: added checks for MBCS support. [Chr. Spieler] + +6.00h03 (17 Apr 09): + - unzpriv.h: added missing OF() macro to uzmbclen() prototype. [SMS] + - man/*.1: changed revision info to intended release date. [Chr. Spieler] + +6.00 (20 Apr 09): + - unzpriv.h, fileio.c: removed superfluous "define indirection" zlstat, + link attributes do never ever need 64-bit treatment. [Chr. Spieler] + - man/unzip.1, ToDo: added remark to DECRYPTION section on still missing + support for UTF-8 encoded passwords on systems like Windows, that are + Unicode-aware without using UTF-8 as native character encoding; added + ToDo note about fixing UTF-8 password handling in the next release. + [Chr. Spieler] + - updated release dates (History.600, README, unzvers.h, all man pages), + changed all relevant files from BETA into release state. [Chr. Spieler] + +================== + +These changes occurred in beta versions 6.00a to 6.00. This list may have +left out some bugfixes and even some features...void where prohibited, your +mileage may vary, etc., etc. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..1b14255 --- /dev/null +++ b/INSTALL @@ -0,0 +1,861 @@ +__________________________________________________________________________ + + This is the Info-ZIP file INSTALL (for UnZip), last updated 16 Apr 2009. +__________________________________________________________________________ + + Yes, this is a rather long file, but don't be intimidated: much of its + length is due to coverage of multiple operating systems and of optional + customization features, large portions of which may be skipped. +__________________________________________________________________________ + + + +To compile UnZip, UnZipSFX and/or fUnZip (quick-start instructions): +======================================== + +(1) Unpack everything into a work directory somewhere, and make sure you're + in the main UnZip directory (the one with this file in it). + * (See note below concerning line termination format used in the source + distribution) + +(2) Copy the appropriate makefile into the current directory, except under + OS/2. + +(3) Run your "make" utility on the makefile (e.g., "nmake -f makefile.msc"). + +(4) Try out your new UnZip the way you would any new utility: read the + docs first. + + Ah ha ha ha!! Oh, that kills me. But seriously... For VMS, see the + Install section below or [.vms]README. for details. + + For DOS and other OSes without explicit timezone support (i.e., everybody + but Unix, Windows 95 and NT), make sure the "TZ" environment variable is + set to a valid and reasonable value; see your compiler docs for details. + +(*) The unzip sources as well as other Info-ZIP source archives are packaged + in Unix format. All text files use single LF (Ascii 0x0a) characters as + line terminators. On systems that use different conventions for plain text + files (e.g.:DOS,Win9x,WinNT,OS/2 -> combined CR+LF; MacOS -> single CR), + some utilities (editors, compilers, etc.) may not accept source files + with LF line terminators. + For these systems, we recommend to use Info-ZIP's UnZip utility for + extraction of our distribution archives, applying the command option + "-a" (= translate text files to native format) in the extraction command. + In case this procedure is not applicable, an appropiate third-party + conversion utility may be used to achieve the desired line termination + style (examples: "flip", available for Unix, DOS, OS/2; or "tr" on Unix). + + +To compile UnZip, UnZipSFX and/or fUnZip (detailed instructions): +======================================== + +(1) Unpack *.c and *.h (the actual source files), preserving the directory + structure (e.g., ./unix/unix.c). The sole exception is TOPS-20, where + tops20/* should be unpacked into the current directory, but TOPS-20 + is no longer fully supported anyway. + + As of UnZip 5.41, full decryption support has been integrated in the + UnZip source distribution. If you wish to compile binaries without + decryption support, you must define the preprocessor flag NO_CRYPT. + For many environments, you may add this flag to the custom compilation + flags supplied by the environment variable LOCAL_UNZIP. For more + details, see the make procedures and accompanied documentation for your + particular target OS. + + As of UnZip 5.53, support for the bzip2 compression algorithm has been + added to UnZip. However, this support requires the original sources of + the bzip2 compression library which have to be aquired separately; + see "http://www.bzip.org/" for further reference. + + +(2) Choose the appropriate makefile based on the description in the Con- + tents file for your OS (that is, there's only one for Unix or OS/2, but + MS-DOS and several other OSes have several, depending on the compiler). + Copy it into the current directory and rename if necessary or desired. + (Some makefiles can be invoked in place; see (5) below.) + + Don't be afraid to read the makefile! Many options will be explained only + in the comments contained therein. The defaults may not quite suit your + system. When making changes, remember that some "make" utilities expect + tabs as part of the makefile syntax. Failure with cryptic error messages + will result if your editor quietly replaces those tabs with spaces. + + Special point of confusion: some non-MSDOS makefiles contain MS-DOS + targets (useful for cross-compilations). An example is the OS/2 makefile + os2/makefile.os2 that contains the gccdos target for DOS emx+gcc and + some more DOS related targets for Watcom C and MSC. But since version 5.3, + the msdos subdirectory contains makefiles for all supported DOS compilers. + [The old djgpp, djgpp1 and gcc_dos targets in unix/Makefile have been + removed in 5.3; use msdos/makefile.dj* instead.] + + Extra-special point of confusion: makefile.os2 expects to remain in + the os2 subdirectory. Invoke it via "nmake -f os2/makefile.os2 gcc", + for example. + + +(3) If you want a non-standard version of UnZip, define one or more of the + following optional macros, either by adding them to the LOCAL_UNZIP + environment variable or by editing your makefile as appropriate. The + syntax differs from compiler to compiler, but macros are often defined + via "-DMACRO_NAME" or similar (for one called MACRO_NAME). Note that + some of these may not be fully supported in future releases (or even + in the current release). Note also that very short command lines in + MS-DOS (128 characters) may place severe limits on how many of these + can be used; if need be, the definitions can be placed at the top of + unzip.h instead (it is included in all source files)--for example, + "#define MACRO_NAME", one macro per line. + + DOSWILD (MS-DOS only) + Treat trailing "*.*" like Unix "*" (i.e., matches anything); treat + trailing "*." as match for files without a dot (i.e., matches any- + thing, as long as no dots in name). Special treatment only occurs + if patterns are at end of arguments; i.e., "a*.*" matches all files + starting with "a", but "*.*c" matches all files ending in "c" *only* + if they have a dot somewhere before the "c". [The default method of + specifying files without a dot would be "* -x *.*", making use of + UnZip's exclude-files option.] The matching is actually the same as + Unix, if you assume that undotted filenames really have an invisible + dot at the end, which is how DOS and related systems treat filenames + in general. All other regular expressions (including "?" and + "[range_of_chars]") retain their Unix-like behavior. + + WILD_STOP_AT_DIR (incompatible with WINDLL!) + Enables an additional option "-W". When this qualifier is specified, + the pattern matching routine is modified so that both '?' (single-char + wildcard) and '*' (multi-char wildcard) do not match the directory + separator character '/'. Examples: + "*.c" matches "foo.c" but not "mydir/foo.c" + "*/*.c" matches "bar/foo.c" but not "baz/bar/foo.c" + "??*/*" matches "ab/foo" and "abc/foo" but not "a/foo" or "a/b/foo" + To enable matching across directory separator chars, two consecutive + multi-char wildcards "**" should be specified. + This modified behaviour is equivalent to the pattern matching style + used by the shells of some of UnZip's supported target OSs (one + example is Acorn RISC OS). + + VMSWILD (VMS only) + Use parentheses rather than brackets to delimit sets (ranges), and + use '%' instead of '?' as the single-character wildcard for internal + filename matching. (External matching of zipfile names always uses + the standard VMS wildcard facilities; character sets are disallowed.) + + VMSCLI (VMS only) + Use VMS-style "slash options" (/FOOBAR) instead of the default Unix- + style hyphenated options (-f). This capability does not affect options + stored in environment variables (UNZIP_OPTS or ZIPINFO_OPTS); those use + the Unix style regardless. Beginning with UnZip 5.32, the supplied + VMS build methods generate both VMS-style and default "UNIX-style" + executables; you should NOT add VMSCLI to the custom options. + + CHECK_VERSIONS (VMS only) + UnZip "extra fields" are used to store VMS (RMS) filesystem info, + and the format of this information may differ in various versions + of VMS. Defining this option will enable UnZip warnings when the + stored extra-field VMS version(s) do(es) not match the version of + VMS currently being used. This is a common occurrence in zipfiles + received from other sites, but since the format of the filesystem + does not seem to have changed in years (including on Alpha and + IA64 systems), the warnings are not enabled by default. + + RETURN_CODES (VMS only) + VMS interprets return codes according to a rigid set of guidelines, + which means it misinterprets normal UnZip return codes as all sorts + of really nasty errors. Therefore VMS UnZip returns an alternate set + of return codes; since these may be difficult to interpret, define + RETURN_CODES for human-readable explanations. + + VMS_TEXT_CONV (everybody except VMS) + VMS Stream_LF-format text files archived with the "-V" option + (/VMS), but NOT with -VV (/VMS=ALL), should be fine when extracted + on other systems. Stream_LF-files archived with -VV should be + readable as well, but they may get some junk appended. + Text files with other formats (like the default VFC, with its + embedded byte counts) may be only semi-readable at best when + extracted on other systems. Defining this option enables UnZip's + -aa option to detect and convert VMS VFC-record text files into + native text format. Non-VMS UnZips now use a rudimentary VMS extra + field analyser to relyably determine such text files. (Earlier + versions of UnZip applied some heuristics instead.) + Therefore this option is now enabled by default for the main program + (but not the SFX stub), because it can be extremely useful on those + rare occasions when a VMS text file must be extracted as normal text. + + USE_DJGPP_ENV (MS-DOS DJGPP 2.0x only) + Regular DJGPP v2.0x compiled programs which use ENVIRONMENT are + able to read from the file "djgpp.env" as well as those set in the + environment. This adds about 1KB to the size of the executable. + This option is disabled by default in Info-ZIP source. If you are + able to use "djgpp.env" and don't like to clutter the environment + with many special purpose variables, you may want to compile with + this option set. + + USE_DJGPP_GLOB (MS-DOS DJGPP 2.0x only) + If you like to get UnZip binaries that handle command line arguments + similar to Unix tools which are run in an Unix shell, you might want + to set this compilation option. This option enables the support for + globbing command line arguments containing wildcards that is built + into the DJGPP startup code. When using a binary compiled with this + option, you may have to enclose wildcard arguments in double quotes + to get them passed to the program unmodified. Enabling this option + is not recommended, because it results in Info-Zip binaries that do + not behave as expected for MS-DOS programs. + + USE_VFAT (MS-DOS only, for using same executable under DOS and Win95/NT) + djgpp 2.x and emx/gcc+RSX 5.1 can detect when they are running under a + Win32 DOS box and will accordingly enable long-filename support. For + now only djgpp 2.x and emx/gcc with RSX 5.1 or later have this feature + (and it is defined by default in msdos/makefile.dj2 and makefile.emx), + but if/when other compilers build in similar support, define this + macro to enable its use. See also msdos/doscfg.h. [Note that djgpp + 2.0's LFN support is flaky; users should upgrade to 2.01 or later.] + + NO_W32TIMES_IZFIX (Win32 including WinDLL, and WinCE) + By specifying this option, you can disable Info-ZIP's special timestamp + adjustment to get stable time stamps on NTFS disks that do not change + depending on the current time being normal vs. daylight saving time. + When this option is set, UnZip behaves exactly like other programs; + file timestamps on NTFS partitions are created so that their >current< + local time representation displayed by directory listings (cmd.exe + "dir" command or Windows Explorer listings) is the same as shown by + UnZip's listing. But the actual UTC timestamp values stored in the + NTFS file attributes vary depending on whether extraction is done + at summer or winter time. + This option is not recommended because it sacrifies the timestamp + comparison checks when extracting or modifying archives in "update + only newer" mode. + However, for environments where consistency of >displayed< dates + of files extracted to NTFS vs. FAT disks is considered more important + than correctly working update/freshen tasks of Zip&UnZip, this + option may be used. + >> DO NOT DISTRIBUTE OR PUBLISH executables that were compiled with + this option! << + + NOTIMESTAMP + This option disables the -T option, which basically does exactly what + Zip's -go options do (i.e., set the timestamp of the zipfile to that of + the newest file in the archive without rewriting the archive). Unlike + Zip, however, UnZip supports wildcard specifications for the archive + name; for example, "unzip -T *.zip" will set the dates of all zipfiles + in the current directory. (UnZip's option is also much faster.) + + DATE_FORMAT=DF_DMY or DF_MDY or DF_YMD + This option controls the order in which date components are printed + in non-ZipInfo-mode listings: day-month-year or month-day-year or + year-month-day. + For DOS, FlexOS, OS2, Theos and Win32, the format is automatically + obtained from the operating system; most others default to DF_MDY. + + DATE_SEPCHAR='-' or '.' or '/' etc. + This option controls the character that separates the date components + shown in (non-ZipInfo-mode) listings. The Win32 port obtains the + separator automatically from the operating system's locale settings; + all others default to '-'. + + ACORN_FTYPE_NFS (needs support for long filenames with embedded commas) + This option enables a -F option that instructs UnZip to interpret the + filetype information extracted from Acorn RiscOS extra field blocks. + The filetype IDs are translated into "NFS filetype extensions" and + appended to the names of the extracted files. This feature facilitates + maintenance of Unix-based NFS volumes that are exported to Acorn RiscOS + systems. + + QLZIP (Unix only) + Add some support for QDOS extra fields. This option enables Unix + UnZip to append "datalen info" to QDOS exec type files in the same + format as used by QDOS cross-compilers on Unix or the qltools v2.2(+). + + UNIXBACKUP (default on OS/2, Unix, Win32) + This option enables a -B option that instructs UnZip to rename files + that would normally be overwritten. The renamed files are given a + tilde suffix and a unique sequence number (`~#####'). Note that + previously renamed files may be overwritten without notice, even + if the -n option is given. + On target ports where UNIXBACKUP is enabled by default, the negated + option NO_UNIXBACKUP may be used to disable this feature. + + OS2_EAS + List the sizes of OS/2 EAs and ACLs for each file as two extra columns + in "unzip -l" output. This is primarily useful for OS/2 systems, but + because zipfiles are portable, OS2_EAS can be defined for any system. + (May be extended someday to show sizes of Mac resource forks, RISCOS + and VMS file info, etc.) + + DELETE_IF_FULL (anybody with unlink() function) + If a write error is encountered (most likely due to a full disk), + enabling this option will cause the incomplete file to be deleted + instead of closed normally. This is particularly useful for the + Windows CE port, which must generally contend with extremely limited + resources. + + ASM_CRC (Amiga/Aztec C; many x86 systems: DOS, OS/2, Win32, Unix) + Use an assembler routine to calculate the CRC for each file (speed). + + ASM_INFLATECODES (Amiga/Aztec C only, for now) + Use an assembler version of inflate_codes() for speed. + + OLD_EXDIR + No longer supported. + + SFX_EXDIR + Enable the "-d " option for UnZipSFX. This is now + enabled by default (since UnZip 5.5) to facilitate use with + automated installation scripts and the like. For disabling + this feature, see the NO_SFX_EXDIR option. + + NO_SFX_EXDIR + Disables the "-d " option for UnZipSFX to generate the + smallest possible executable stub. (Prior to the UnZip 5.5 release, + this was the default.) + + CHEAP_SFX_AUTORUN + Enable a simple "run command after extraction" feature for + the (command line) UnZipSFX stub. This feature is currently + incompatible with the "-d " command line option, + therefore CHEAP_SFX_AUTORUN implicitely sets the NO_SFX_EXDIR + option. + + NO_ZIPINFO + Compile without ZipInfo mode (-Z) enabled; makes a smaller executable + because many text strings are left out. Automatically enabled for + some small-model compiles under MS-DOS and OS/2, so ordinarily there + is no need to specify this explicitly. (Note that even with this + defined, the resulting executable may still be too big to extract + some zipfiles correctly, if compiled with the small memory model.) + + USE_DEFLATE64 (default for UnZip and fUnZip) + NO_DEFLATE64 (default for UnZipSFX stub) + The "deflate64" algorithm from PKZIP 4.0 (or newer) is an enhanced + variant of the deflate algorithm that achieves slightly better + compression ratios on highly redundant data. Normally, UnZip should + be compiled with support for this compression algorithm enabled. + However, this results in significantly larger memory requirements + to run the program. For 16-bit executables (DOS and OS/2), the + special memory management to support the 64k history buffer results + in a slight performance (= speed) penalty. And for the SFX stub, + "deflate64" support might be unnessessary as long as the Info-ZIP + Zip utility does not support it (quite likely, this will never + get implemented). So, the NO_DEFLATE64 option is provided to allow + exclusion of the deflate64 support. + + USE_BZIP2 (requires additional external code distribution) + UnZip can optionally support the "bzip2" compression algorithm for + most ports on 32-bit (or higher) platforms. Currently, this support + is integrated in the Make procedures of MSDOS 32-bit (DJGPP), VMS, + Win32, and many Unix systems. + Prerequisites: + You have to obtain the bzip2 source distribution (version 1.03 or + higher) and extract it into the "bzip2" subdirectory. + Compilation: + - MSDOS, Win32: You have to supply the symbol definition + "USEBZ2=1" on the command line when you invoke the make program. + - Unix: The target "generic" automatically activates bzip2 support + when its configure script detects the presence of the bzip2 sources. + For other targets, there are two options: + a) Use the command + "make -f unix/Makefile D_USE_BZ2=-DUSE_BZIP2 L_BZ2=-lbz2 \ + LIBBZ2=bzip2/libbz2.a YourTarget" + (Do not use the continuation line and replace YourTarget with + the appropiate target name.) + b) Edit the Makefile and remove the comment signs from the lines + that define the macros D_USE_BZ2, L_BZ2, and LIBBZ2 (at about + line 84 ff.). + - VMS: The MMS/MMK build program should automatically activate the + bzip2 support when it detects the presence of the bzip2 sources. + + MULT_VOLUME (experimental for 5.5x, do NOT use in production versions!) + NO_MULT_VOLUME (default) + The symbol MULT_VOLUME is used to flag code portions needed for + support of multi-volume archives. For now, this flag MUST NOT be + used to compile a production versions of UnZip. This flag has been + introduced to allow integration of experimental code for multi-volume + support in the master source tree. This feature will become a default + option in the future 6.1 release of UnZip. + + LZW_CLEAN + USE_UNSHRINK (now default, as of January 2005) + The "shrinking" algorithm from PKZIP 1.0 is an LZW variant. Unisys + patented the Lempel-Ziv-Welch algorithm in 1985 and has publicly + claimed that decompression is covered by it. (IBM also patented the + same thing in a filing 3 weeks prior to Unisys's.) In 2004, the + Unisys and IBM patents expired worldwide, so unshrinking is now + enabled again by default. If you do not wish to include the LZW + method, you may still disable it by defining LZW_CLEAN. + (Unshrinking was used by PKZIP 1.0 and 1.1, and Zip 1.0 and 1.1. + All newer archives use only the deflation method.) + + COPYRIGHT_CLEAN (now default) + USE_SMITH_CODE + The last chunk of code in UnZip that was blatantly derived from Sam + Smith's unzip 2.0 (as in, "substantially similar") is in unreduce.c. + Since reducing was only used by very early PKZIP beta versions (0.9x), + support for it is now omitted by default (COPYRIGHT_CLEAN). To in- + clude unreducing capability, define USE_SMITH_CODE and replace the + stub unreduce.c source file by the separatly distributed full source + code module. Note that this subjects UnZip to any and all restrictions + in Smith's copyright; see the UnZip COPYING.OLD file for details. + + USE_CRYPT + Enable decryption support for all binaries. The default setting + is to disable decryption support for the SFX stub to keep its size + as small as possible. For other binaries of the UnZip distribution, + decryption support is enabled by default. + + NO_CRYPT + Disable decryption support for all binaries. + + PASSWD_FROM_STDIN (with full crypt sources only; Unix, VMS only) + Used to allow the password on encrypted files to be read from stdin + rather than the default stderr. This was useful for those who wished + to automate the testing or decoding of encrypted archives (say, in a + shell script via ``echo "password" | unzip -tq archive''), but as of + version 5.3, UnZip has a -P option for passing a password directly to + the program. PASSWD_FROM_STDIN will therefore probably be phased out + in future versions. Note that the same security warnings given in the + description of the -P option apply here as well. + + UNICODE_SUPPORT + Enable restoring from UTF-8 encoded paths. These paths are stored + in extra fields in a backward-compatible way so that archives with + UTF-8 paths still work on zips and unzips that don't support Unicode. + This support follows the recent additions to the PKWare AppNote for + Unicode support, except that Unicode comments on systems where UTF-8 + is not the current character set is not implemented in this release. + + Internally, Unicode support can be achieved by three methods: + a) The charset encoding used by the system is already UTF-8, so + the program just has to select the UTF-8 versions of the stored + filenames for file name handling. + This method is enabled by setting the symbol UTF8_MAYBE_NATIVE; + this activates code to check for native UTF-8 encoding in the + locale settings. + b) The operating system and the compilation environment support + "wide character" data in Unicode encoding (UCS-2/UTF-16 or UCS-4), + which are used to translate between UTF-8 and the native + extended-ASCII character encoding. + The code for this method is activated by setting the preprocessor + symbol UNICODE_WCHAR. + It may be activated together with UTF8_MAYBE_NATIVE to provide + more versatile Unicode support and additional "debugging" options + for checking the correct recognition of non-ASCII Unicode + characters. + c) The operating system and the compilation environment allow to use + unicode-encoded "wide character" data for native text strings + support. + Complete support for this method requires a throughout revision + of the UnZip code. All internal string handling and text output + needs to be ported to use wchar_t character storage. + This porting is still in an experimental stage and not ready + for general distribution. + + On some ports UNICODE_SUPPORT is set automatically: + - WIN32 (and WinCE) use method b) by defining UNICODE_SUPPORT and + UNICODE_WCHAR. + - On Unix, the automatic configuration script enables UNICODE_WCHAR + if ISO-10646 compatible wide characters are supported and + UTF8_MAYBE_NATIVE if the locale detection call is available. + For these ports, setting NO_UNICODE_SUPPORT forces deactivation of + the Unicode support. + + NO_SETLOCALE (for Unix) + On Unix, it is now assumed that and the setlocale function + are available, to setup locale-aware filtering of displayed filenames. + The option NO_SETLOCALE allows to disable the dependency on + and setlocale() on systems where this assumption is invalid (and the + auto-configuring make target "generic" cannot be used for capabilities + detection). + + _MBCS + NO_MBCS + Enable multi-byte character set support. This is the default for the + Human68k system (originated from Japan) and for Win32 (here only DBCS + "double-byte character set" support). The MBCS support should also be + enabled on systems which are capable of using UTF-8 as native charset. + For MBCS support, the C runtime library must supply implementations + for the mblen() function and the MB_CUR_MAX runtime macro/function. + The NO_MBCS symbol allows to explicitely disable MBCS support for + testing purpose, or when MBCS support does not work as expected. + + HAVE_WORKING_ISPRINT + NO_WORKING_ISPRINT + The symbol HAVE_WORKING_ISPRINT enables enhanced non-printable chars + filtering for filenames in the fnfilter() function. On some systems + (Unix, VMS, some Win32 compilers), this setting is enabled by default. + In cases where isprint() flags printable extended characters as + unprintable, defining NO_WORKING_ISPRINT allows to disable the enhanced + filtering capability in fnfilter(). (The ASCII control codes 0x01 to + 0x1f are always escaped on ASCII systems.) + + DEBUG + Used for debugging purposes; enables Trace() statements. Generally + it's best to compile only one or two modules this way. + + DEBUG_TIME + Used for debugging the timezone code in fileio.c; enables TTrace() + statements. This code is only used for the freshen/update options + (-f and -u), and non-Unix compilers often get it wrong. + + +(4) If you regularly compile new versions of UnZip and always want the same + non-standard option(s), you may wish to add it (them) to the LOCAL_UNZIP + environment variable (assuming it's supported in your makefile). Under + MS-DOS, for example, add this to AUTOEXEC.BAT: + + set LOCAL_UNZIP=-DDOSWILD -DDATE_FORMAT=DF_DMY + + You can also use the variable to hold special compiler options (e.g., + -FPi87 for Microsoft C, if the x87 libraries are the only ones on your + disk and they follow Microsoft's default naming conventions; MSC also + supports the CL environment variable, however). + + +(5) Run the make utility on your chosen makefile: + + Unix + For most systems it's possible to invoke the makefile in place, at + the possible cost of an ignorable warning; do "make -f unix/Makefile + list" to get a list of possible system targets, and then "make -f + unix/Makefile target" for your chosen target. The "generic" target + works for most systems, but if it fails with a message about ftime() + unresolved or timezone redefined, do "make clean", "make help", and + then either "make generic2" or "make generic3" as instructed. If all + else fails, read the makefile itself; it contains numerous comments. + (One of these days we'll make a configure script that automates this + procedure better.) + + VMS (OpenVMS): + On VMS, two build methods are provided: a command procedure, and + description files for MMS or MMK. Both methods must be run from + the main directory, not the [.VMS] subdirectory. + + A simple build using the command procedure looks like this: + @ [.VMS]BUILD_UNZIP.COM + + A simple build using MMS or MMK looks like this: + MMS /DESCRIP = [.VMS]DESCRIP.MMS ! Or, with MMK, ... + MMK /DESCRIP = [.VMS]DESCRIP.MMS + + Various options for each build method are explained in comments in + the main builder file, either BUILD_UNZIP.COM or DESCRIP.MMS. + + Here are some more complex build examples: + + o Build with the large-file option enabled (non-VAX only): + + @ [.VMS]BUILD_UNZIP LARGE + or: + MMS /DESC = [.VMS] /MACRO = LARGE=1 + + o Re-link the executables (small-file and large-file): + + @ [.VMS]BUILD_UNZIP LINK + @ [.VMS]BUILD_UNZIP LARGE LINK + or + MMK /DESC = [.VMS] CLEAN_EXE ! Deletes existing executables. + MMK /DESC = [.VMS] ! Builds new executables. + MMK /DESC = [.VMS] /MACRO = LARGE=1 CLEAN_EXE + MMK /DESC = [.VMS] /MACRO = LARGE=1 + + o Build a large-file product from scratch, for debug, getting + compiler listings and link maps: + + mms /desc = [.vms] clean + mms /desc = [.vms] /macro = (DBG=1, LARGE=1. LIST=1) + + On VAX, the builders attempt to cope with the various available C + compilers: DEC/Compaq/HP C, VAX C, or GNU C. If DEC/Compaq/HP C is + not available or not desired, comments in the relevant builder file + explain the command-line options used to select a different + compiler. + + System-architecture-specific files (like objects and executables) + are placed in separate directories, such as [.ALPHA], [.IA64], or + [.VAX]. Large-file products get their own directories, [.ALPHAL] + or [.IA64L]. On VAX, VAX C products are placed in [.VAXV], GNU C + products in [.VAXG]. Each product builder announces what the + destination directory will be when it is run. + + Common files, such as the help libraries (UNZIP.HLP for the + default UNIX-like command-line interface, UNZIP_CLI.HLP for the + VMS-like command-line interface), are placed in the main + directory. With a mixed-architecture VMS cluster, the same main + directory on a shared disk may may be used by all system types. + (Using the NOHELP option with BUILD_UNZIP.COM can keep it from + making the same help files repeatedly.) + + Some further information may be found in the files + [.VMS]README. and [.VMS]00BINARY.VMS, though much of what's + there is now obsolete. + + MS-DOS + See the msdos\Contents file for notes regarding which makefile(s) to + use with which compiler. In summary: pick one of msdos\makefile.* + as appropriate, or (as noted above) use the OS/2 gccdos target for + emx+gcc. There is also an mscdos cross-compilation target in + os2\makefile.os2 and a sco_dos cross-compilation target in the Unix + makefile. For Watcom 16-bit or 32-bit versions, see the comments in + the OS/2 section below. + + After choosing the appropriate makefile and editing as necessary or + desired, invoke the corresponding make utility. Microsoft's NMAKE + and the free dmake and GNU make utilities are generally the most + versatile. The makefiles in the msdos directory can be invoked in + place ("nmake -f msdos\makefile.msc", for example). + + OS/2 + Either GNU make, nmake or dmake may be used with the OS/2 makefile; + all are freely available on the net. Do "nmake -f os2\makefile.os2", + for example, to get a list of supported targets. More generally, + read the comments at the top of the makefile for an explanation of + the differences between some of the same-compiler targets. + + Win32 (WinNT or Win9x) + For creating Win32 executables, the Microsoft Visual C++ compiler + platforms from version 2.x up to 8.0 (Visual Studio .Net C++ 2005) + are supported. Recent build test have been run on VC++ 6.0, 7.1 + and 8.0. The linker of newer Microsoft Visual C++ versions (beginning + with Visual C++ 2008 - [VC++ 9.0]) create executables that are marked + to run on Windows 2000 and newer, only. Although these Visual C++ + environments may succeed in building Win32 Info-ZIP executables, + they cannot (and must not) be used to create binaries for public + distribution. + Alternative compilers for the Intel platforms are OpenWatcom C++, + GNU C (preferably the mingw32 port, CygWin and emx/rsxnt may also + work), Borland C++, or lcc-win32. + DEC C/C++ for NT/Alpha may or may not still work. + For the Watcom compiler, use WMAKE and win32\makefile.wat; for the + Microsoft compilers, use NMAKE and win32\Makefile; for mingw32 and + CygWin, GNU Make and win32\Makefile.gcc should do the job. + With emx+gcc, a good choice is GNUMake 3.75 (or higher) from the + djgpp V2 distribution used on win32\Makefile.emx. + + The unzip32.dll WinDLL executables can be built using the appropiate + Makefile in the win32\ subdirectory, or by using the Microsoft Visual + C++ project files supplied below the windll subdirectory. Besides the + MSC compilers, gcc-mingw32, Watcom C and Borland C allow to build the + Windows UnZip DLL. By default, the Makefiles for compilers that use + the Microsoft C runtime are configured to link against the shared + multithreading C runtime DLL. Depending on the intended usage for + unzip32.dll, a statically linked dll might be more suitable. The + make scripts for MSC support build variants with static linking; you + should look up the configuration switch DLLSTANDALONE in the MSC + Makefile or the "Static..." build configurations in the Visual Studio + project files. + + WinCE (WinCE or WinNT) + Only Microsoft Visual C++ 5.0, 6.0 or Visual C++ embedded 3.0 or later + are supported. Use the appropiate version of the included project + files and check wince\README for details. + + AmigaDOS + SAS/Lattice C and Manx Aztec C are supported. For SAS C 6.x do "smake + -f amiga/smakefile all"; for Aztec C do "make -f amiga/makefile.azt + all". The Aztec C version supports assembly-language versions of two + routines; these are enabled by default. + + Atari TOS + Turbo C is no longer supported; use gcc and the MiNT libraries, and + do "make". Note that all versions of gcc prior to 2.5.8 have a bug + affecting 68000-based machines (optimizer adds 68020 instructions). + See atari\README for comments on using other compilers. + + Macintosh + Metrowerks CodeWarrior Pro 4 with Universal Interfaces 3.1 is the only + currently supported compiler, although the Mac Programmer's Workbench + (MPW) and Think C were supported at one time and still have some hooks. + Other Compilers may work too, no compiler specific instructions + (pragma, header, macros, ...) were used in the code. + For CodeWarrior Pro 4, un-BinHex the CodeWarrior project file and + UnZip resource file (using Stuffit Expander or BinHex 4.0 or later), + then open the project and click on the compile button. + See ":macos:Contents" for the possible project targets. + Link order of the standard libraries is very important: Link all + sources first and all standard libraries last. + + Acorn (RISC OS) + Extract the files from the archive and place in standard 'Acorn' C + form (i.e., *.c, *.h and *.s become c.*, h.* and s.*, respectively), + either using the UNZIP$EXTS environment variable and a pre-built UnZip + binary, or using Spark[FS] and doing it manually. Then copy the + Acorn.Makefile to the main UnZip directory and either type 'amu' or + use the desktop make utility. + + VM/CMS + Unpack all the files and transfer them with ASCII -> EBCDIC conver- + sion to an appropriate directory/minidisk/whatever, then execute + UNZVMC to compile and link all the sources. This may require C/370 + version 2.1 or later and certain `nucleus extensions,' although + UnZip 5.3 has been reported to compile fine with the `ADCYCLE C/370 + v1.2 compiler.' Note that it will abend without access to the C/370 + runtime library. See the README.CMS file for more details. + + MVS + Unpack all the files and transfer them to an appropriate PDS with + ASCII -> EBCDIC conversion enabled, then edit UNZMVSC.JOB as required, + and execute it to compile and link all the sources. C/370 2.1 or + later is required. See README.MVS for further details. [This is a + new port and may need a little more work even to compile.] + + Human68K + [This is a Japanese machine and OS.] It appears that GNU make and + gcc are required; presumably just do "gmake -f human68k/Makefile.gcc" + to build everything. This port has not been tested since the 5.12 + release. + + TOPS-20 + [No longer fully supported due to new, unported features, although + patches are always accepted.] Unpack all files into the current + directory only (including those in the zipfile's tops20 directory), + then use make.mic and "do make". + + BeOS + You can run the BeOS makefile in place by typing "make -f + beos/Makefile". In fact, this is how the author tests it. + + Running the appropriate make utility should produce three executables on + most systems, one for UnZip/ZipInfo, one for UnZipSFX, and one for fUnZip. + (VMS is one prominent exception: fUnZip makes no sense on it. The Amiga + produces a fourth executable called MakeSFX, which is necessary because + Amiga self-extracting archives cannot be created by simple concatenation. + If necessary the source amiga/makesfx.c can be compiled on other systems.) + Read any OS-specific README files for notes on setting things up for + normal use (especially for VMS) and for warnings about known quirks and + bugs in various compilers (especially for MS-DOS). + + Also note that many OSes require a timezone variable to be set correctly + (often "TZ"); Unix and VMS generally do so by default, Win95/NT do if set + up properly, but other OSes generally do not. See the discussion of the + -f and -u options in the UnZip man page (or unzip.txt). BeOS doesn't + currently support timezone information at all, but this will probably be + added soon. + + Then test your new UnZip on a few archives and let us know if there are + problems (but *please* first make certain that the archives aren't actu- + ally corrupted and that you didn't make one of the silly mistakes dis- + cussed in the documentation). If possible, double-check any problems + with PKUNZIP or with a previous version of UnZip prior to reporting a + "bug." The zipfile itself may be damaged. + + + +To install: +=========== + +Unix + The default prefix for the installation location is /usr/local (things + go into the bin and man/man1 subdirectories beneath the prefix), and + the default man-page extension is "1" (corresponding to man/man1, above). + To install as per the defaults, do "make install"; otherwise do "make + prefix=/your/path manext=your_extension install". (For Intel Unix flavors + where the assembler CRC routines were used [ASM_CRC], use the install_asm + target instead of the regular install target.) For example, to install + in your home directory with "l" as the man-page extension (for "local"), + do "make prefix=$HOME manext=l install". Permissions will be 755 for the + executables and 644 for the man pages. In general root must perform in- + stallation into a public directory. Do "rehash" if your shell requires + it in order to find the new executables. + +VMS + To complete the installation, the executables may be left in place, + or moved (or copied) to a convenient place. While other methods + (like DCL$PATH) exist, most users define symbols to make the UnZip + executables available as foreign commands. These symbol definitions + may be placed in a user's SYS$LOGIN:LOGIN.COM, or in a more central + location, like SYS$MANAGER:SYLOGIN.COM. Typical symbol definitions + might look like these: + + UNZIP :== $ dev:[dir]UNZIP.EXE ! UNIX-like command line. + or: + UNZIP :== $ dev:[dir]UNZIP_CLI.EXE ! VMS-like command line. + + For convenience, a ZIPINFO symbol could also be defined, so: + + ZIPINFO :== $ dev:[dir]UNZIP.EXE """-Z""" + + On a non-VAX system, different symbols could be defined for the + small-file and large-file programs. For example: + + UNZIPS :== $ dev:[dir.ALPHA]UNZIP.EXE ! UNZIPS = small-file UnZip. + UNZIP*L :== $ dev:[dir.ALPHAL]UNZIP.EXE ! UNZIP[L] = large-file UnZip. + + The builders create help text files, UNZIP.HLP and UNZIP_CLI.HLP. + These may be incorporated into an existing help library, or a separate + UnZip help library may be created using commands like these, using + either UNZIP.HLP (as shown) or UNZIP_CLI.HLP: + + $ LIBRARY /HELP dev:[dir]existing_library.HLB UNZIP.HLP + + $ LIBRARY /CREATE /HELP UNZIP.HLB UNZIP.HLP + + UnZip help may then be accessed from a separate UnZip help library + using a command like: + + $ HELP /LIBRARY = device:[directory]UNZIP.HLB + + For greater ease, the user (or system manager) may define a + HLP$LIBRARY logical name to allow the HELP utility to find the UnZip + help library automatically. See HELP HELP /USERLIBRARY for more + details. The command procedure HLP_LIB_NEXT.COM may be used to + determine the next available HLP$LIBRARY logical name, and could be + adapted to define a HLP$LIBRARY logical name for an UnZip help library. + + The kit includes MAKESFX.COM, a command procedure intended to simplify + creating a self-extracting archive. It may be helpful to install this + procedure near the UnZip executables. MAKESFX.COM expects another + symbol definition, like one of these: + + UNZIPSFX :== $ dev:[dir]UNZIPSFX.EXE ! UNIX-like command line. + or: + UNZIPSFX :== $ dev:[dir]UNZIPSFX_CLI.EXE ! VMS-like command line. + + Again here, on a non-VAX system, either a small-file or a large-file + UNZIPSFX program may be used. (MAKESFX.COM could be modified to allow + a run-time choice to be made.) + +OS/2, MS-DOS, NT, Atari, Amiga + Move or copy unzip.exe (or unzip.ttp, or UnZip, or whatever) to a direc- + tory in your path; also possibly copy the UnZip executable to zipinfo.exe + (or ii.exe), or else create an alias or a batch/command file for ZipInfo + ("@unzip -Z %1 %2 %3 %4 %5 %6 %7 %8 %9" under MS-DOS). The latter is only + relevant if NO_ZIPINFO was *not* defined, obviously... Under djgpp 2.x, + zipinfo.exe is a 2K stub symbolically linked to unzip.exe. + +Acorn RISC OS + Copy the executables unzip, funzip and zipinfo to somewhere in your + Run$Path. See your Welcome manual if you don't know about Run$Path. + +BeOS + The default prefix for the installation location is /boot/usr/local + (things go into the bin and man/man1 subdirectories beneath the prefix), + and the default man-page extension is "1" (corresponding to the man/man1, + above). Of course, these Unix man-pages aren't useful until someone ports + something that can format them... plain text versions are also installed + with an extension of ".txt". To install, do a "make install", or to + change the prefix, do "make prefix=/your/path install". For example, to + install in /boot/bin, do "make prefix=/boot/bin install". + +Macintosh + (This port is for Macintosh OS before Mac OS X. See Unix Apple below for + Mac OS X and later.) + 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 (MacZip) is distributed as a combination of zip and unzip + in one program. The offical release is a fat binary with both regular 68K + and native PowerPC versions included. + 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. + This port supports also Apple-event.So you can install it in your + WWW-Browser as a helper-app. + Look into "macos/README.TXT" (or ":macos:README.TXT" on Mac) for further + info. + +Macintosh OS X (Unix Apple) + Mac OS X and later are based on BSD Unix and are supported by the Unix + port. See the Unix port for details. Though support is currently + minimal, we plan to support additional Mac OS X features, such as resource + forks, in future releases. + +Human68K, TOPS-20, AOS/VS, MVS, VM/CMS, etc. + Dunno, sorry... diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..81411a1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,62 @@ +This is version 2009-Jan-02 of the Info-ZIP license. +The definitive version of this document should be available at +ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and +a copy at http://www.info-zip.org/pub/infozip/license.html. + + +Copyright (c) 1990-2009 Info-ZIP. All rights reserved. + +For the purposes of this copyright and license, "Info-ZIP" is defined as +the following set of individuals: + + Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois, + Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth, + Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz, + David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko, + Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs, + Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda, + Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren, + Rich Wales, Mike White. + +This software is provided "as is," without warranty of any kind, express +or implied. In no event shall Info-ZIP or its contributors be held liable +for any direct, indirect, incidental, special or consequential damages +arising out of the use of or inability to use this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the above disclaimer and the following restrictions: + + 1. Redistributions of source code (in whole or in part) must retain + the above copyright notice, definition, disclaimer, and this list + of conditions. + + 2. Redistributions in binary form (compiled executables and libraries) + must reproduce the above copyright notice, definition, disclaimer, + and this list of conditions in documentation and/or other materials + provided with the distribution. Additional documentation is not needed + for executables where a command line license option provides these and + a note regarding this option is in the executable's startup banner. The + sole exception to this condition is redistribution of a standard + UnZipSFX binary (including SFXWiz) as part of a self-extracting archive; + that is permitted without inclusion of this license, as long as the + normal SFX banner has not been removed from the binary or disabled. + + 3. Altered versions--including, but not limited to, ports to new operating + systems, existing ports with new graphical interfaces, versions with + modified or added functionality, and dynamic, shared, or static library + versions not from Info-ZIP--must be plainly marked as such and must not + be misrepresented as being the original source or, if binaries, + compiled from the original source. Such altered versions also must not + be misrepresented as being Info-ZIP releases--including, but not + limited to, labeling of the altered versions with the names "Info-ZIP" + (or any variation thereof, including, but not limited to, different + capitalizations), "Pocket UnZip," "WiZ" or "MacZip" without the + explicit permission of Info-ZIP. Such altered versions are further + prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP + e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP + will provide support for the altered versions. + + 4. Info-ZIP retains the right to use the names "Info-ZIP," "Zip," "UnZip," + "UnZipSFX," "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip" for its + own source and binary releases. diff --git a/README b/README new file mode 100644 index 0000000..09245f7 --- /dev/null +++ b/README @@ -0,0 +1,347 @@ +This is the README file for the 20 April 2009 public release of the +Info-ZIP group's portable UnZip zipfile-extraction program (and related +utilities). + +unzip60.zip portable UnZip, version 6.0, source code distribution +unzip60.tar.Z same as above, but compress'd tar format +unzip60.tar.gz same as above, but gzip'd tar format + +__________________________________________________________________________ + +BEFORE YOU ASK: UnZip, its companion utility Zip, and related utilities +and support files can be found in many places; read the file "WHERE" for +further details. To contact the authors with suggestions, bug reports, +or fixes, continue reading this file (README) and, if this is part of a +source distribution, the file "ZipPorts" in the proginfo directory. Also +in source distributions: read "BUGS" for a list of known bugs, non-bugs +and possible future bugs; INSTALL for instructions on how to build UnZip; +and "Contents" for a commented listing of all the distributed files. +__________________________________________________________________________ + + +GENERAL INFO +------------ +UnZip is an extraction utility for archives compressed in .zip format (also +called "zipfiles"). Although highly compatible both with PKWARE's PKZIP +and PKUNZIP utilities for MS-DOS and with Info-ZIP's own Zip program, our +primary objectives have been portability and non-MSDOS functionality. + +This version of UnZip has been ported to a stupendous array of hardware-- +from micros to supercomputers--and operating systems: Unix (many flavors), +VMS, OS/2 (including DLL version), Windows NT and Windows 95 (including DLL +version), Windows CE (GUI version), Windows 3.x (including DLL version), +MS-DOS, AmigaDOS, Atari TOS, Acorn RISC OS, BeOS, Macintosh (GUI version), +SMS/QDOS, MVS, VM/CMS, FlexOS, Tandem NSK, Human68k (mostly), AOS/VS (partly) +and TOPS-20 (partly). UnZip features not found in PKUNZIP include source +code; default extraction of directory trees (with a switch to defeat this, +rather than the reverse); system-specific extended file attributes; and, of +course, the ability to run under most of your favorite operating systems. +Plus, it's free. :-) + +For source distributions, see the main Contents file for a list of what's +included, and read INSTALL for instructions on compiling (including OS- +specific comments). The individual operating systems' Contents files (for +example, vms/Contents) may list important compilation info in addition to +explaining what files are what, so be sure to read them. Some of the ports +have their own, special README files, so be sure to look for those, too. + +See unzip.1 or unzip.txt for usage (or the corresponding UnZipSFX, ZipInfo, +fUnZip and ZipGrep docs). For VMS, unzip_def.rnh or unzip_cli.help may be +compiled into unzip.hlp and installed as a normal VMS help entry; see +vms/descrip.mms. + + +CHANGES AND NEW FEATURES +------------------------ +UnZip 6.0 finally supports nowadays "large" files of sizes > 2 GiB! +This is the first release containing support for the PKWARE Zip64 +enhancements. +Major changes are: + - Support PKWARE ZIP64 extensions, allowing Zip archives and Zip archive + entries larger than 4 GiBytes and more than 65536 entries within a single + Zip archive. This support is currently only available for Unix, + OpenVMS and Win32/Win64. + - Support for bzip2 compression method. + - Support for UTF-8 encoded entry names, both through PKWARE's "General + Purpose Flags Bit 11" indicator and Info-ZIP's new "up" unicode path + extra field. (Currently, on Windows the UTF-8 handling is limited to + the character subset contained in the configured non-unicode "system + code page".) + - Added "wrong implementation used" warning to error messages of the MSDOS + port when used under Win32, in an attempt to reduce false bug reports. + - Fixed "Time of Creation/Time of Use" vulnerability when setting attributes + of extracted files, for Unix and Unix-like ports. + - Fixed memory leak when processing invalid deflated data. + - Fixed long-standing bug in unshrink (partial_clear), added boundary checks + against invalid compressed data. + - On Unix, keep inherited SGID attribute bit for extracted directories + unless restoration of owner/group id or SUID/SGID/Tacky attributes was + requested. + - On Unix, allow extracted filenames to contain embedded control characters + when explicitly requested by specifying the new command line option "-^". + - On Unix, support restoration of symbolic link attributes. + - On Unix, support restoration of 32-bit UID/GID data using the new "ux" + IZUNIX3 extra field introduced with Zip 3.0. + - Support for ODS5 extended filename syntax on new OpenVMS systems. + - Support symbolic links zipped up on VMS. + - On VMS (only 8.x or better), support symbolic link creation. + - On VMS, support option to create converted text files in Stream_LF format. + - New -D option to suppress restoration of timestamps for extracted + directory entries (on those ports that support setting of directory + timestamps). By specifying "-DD", this new option also allows to suppress + timestamp restoration for ALL extracted files on all UnZip ports which + support restoration of timestamps. + On VMS, the default behaviour is now to skip restoration of directory + timestamps; here, "--D" restores ALL timestamps, "-D" restores none. + - On OS/2, Win32, and Unix, the (previously optional) feature UNIXBACKUP + to allow saving backup copies of overwritten files on extraction is now + enabled by default. + +For the UnZip 6.0 release, we want to give special credit to Myles Bennet, +who started the job of supporting ZIP64 extensions and Large-File (> 2GiB) +and provided a first (alpha-state) port. + +The 5.52 maintenance release fixes a few minor problems found in the 5.51 +release, closes some more security holes, adds a new AtheOS port, and +contains a Win32 extra-field code cleanup that was not finished earlier. +The most important changes are: + + - (re)enabled unshrinking support by default, the LZW patents have expired + - fixed an extraction size bug for encrypted stored entries (12 excess bytes + were written with 5.51) + - fixed false "uncompressed size mismatch" messages when extracting + encrypted archive entries + - do not restore SUID/SGID/Tacky attribute bits on Unix (BeOS, AtheOS) + unless explicitely requested by new "-K" command line qualifier + - optional support for "-W" qualifier to modify the pattern matching syntax + (with -W: "*" stops at directory delimiter, "**" matches unlimited) + - prevent buffer overflow caused by bogus extra-long Zipfile specification + - performance enhancements for VMS port + - fixed windll interface handling of its extraction mode qualifiers + nfflag, ExtractOnlyNewer, noflag, PromptToOverwrite; added detailed + explanation of their meanings and interactions to the windll documentation + +The 5.51 maintenance release adds a command-line CE port, intended for +batch processing. With the integration of this port, the pUnZip port +has been revised and "revitalized". +The most important changes for the general public are a number of +bug fixes, mostly related to security issues: + + - repair a serious bug in the textmode output conversion code for the 16-bit + ports (16-bit MSDOS, OS/2 1.x, some variants of AMIGA, possibly others) + which was introduced by the Deflate64 support of release 5.5 + - fix a long standing bug in the the inflate decompression method that + prevented correct extraction in some rare cases + - fixed holes in parent dir traversal security code (e.g.: ".^C." slipped + through the previous version of the check code) + - fixed security hole: check naming consistency in local and central header + - fixed security hole: prevent extracted symlinks from redirecting file + extraction paths + +The main addition in the 5.5 release is support for PKWARE's new Deflate64(tm) +algorithm, which appeared first in PKZIP 4.0 (published November 2000). +As usual, some other bugfixes and clean-ups have been integrated: + + - support for Deflate64 (Zip compression method #9) + - support for extracting VMS variable length record text files on + any system + - optional "cheap autorun" feature for the SFX stub + - security fixes: + * strip leading slash from stored pathspecs, + * remove "../" parent dir path components from extracted file names + - new option "-:" to allow verbatim extraction of file names containing + "../" parent dir path specs + - fixed file handle leak for the DLL code + - repaired OS2 & WinNT ACL extraction which was broken in 5.42 + +The 5.42 maintenance release fixes more bugs and cleans up the redistribution +conditions: + + - removal of unreduce.c and amiga/timelib.c code to get rid of the last + distribution restrictions beyond the BSD-like Info-ZIP LICENSE + - new generic timelib replacement (currently used by AMIGA port) + - more reasonable mapping rules of UNIX "leading-dot" filenames to the + DOS 8.3 name convention + - repaired screensize detection in MORE paging code + (was broken for DOS/OS2/WIN32 in 5.41) + +The 5.41 maintenance release adds another new port and fixes some bugs. + + - new BSD-like LICENSE + - new Novell Netware NLM port + - supports extraction of archives with more than 64k entries + - attribute handling of VMS port was broken in UnZip 5.4 + - decryption support integrated in the main source distribution + +The 5.4 release adds new ports, again. Other important items are changes +to the listing format, new supplemental features and several bug fixes +(especially concerning time-stamp handling...): + + - new IBM OS/390 port, a UNIX derivate (POSIX with EBCDIC charset) + - complete revision of the MacOS port + - changed listing formats to enlarge the file size fields for more digits + - added capability to restore directory attributes on MSDOS, OS/2, WIN32 + - enabled support of symbolic links on BeOS + - Unix: optional Acorn filetype support, useful for volumes exported via NFS + - several changes/additions to the DLL API + - GUI SFX stub for Win16 (Windows 3.1) and Win32 (Windows 9x, Windows NT) + - new free GCC compiler environments supported on WIN32 + - many time-zone handling bug fixes for WIN32, AMIGA, ... + +The 5.32 release adds two new ports and a fix for at least one relatively +serious bug: + + - new FlexOS port + - new Tandem NSK port + - new Visual BASIC support (compatibility with the Windows DLLs) + - new -T option (set zipfile timestamp) for virtually all ports + - fix for timestamps beyond 2038 (e.g., 2097; crashed under DOS/Win95/NT) + - fix for undetected "dangling" symbolic links (i.e., no pointee) + - fix for VMS indexed-file extraction problem (stored with Zip 2.0 or 2.1) + - further performance optimizations + +The 5.31 release included nothing but small bug-fixes and typo corrections, +with the exception of some minor performance tweaks. + +The 5.3 release added still more ports and more cross-platform portability +features: + + - new BeOS port + - new SMS/QDOS port + - new Windows CE graphical port + - VM/CMS port fully updated and tested + - MVS port fully updated and tested + - updated Windows DLL port, with WiZ GUI spun off to a separate package + - full Universal Time (UTC or GMT) support for trans-timezone consistency + - cross-platform support for 8-bit characters (ISO Latin-1, OEM code pages) + - support for NT security descriptors (ACLs) + - support for overwriting OS/2 directory EAs if -o option given + - updated Solaris/SVR4 package facility + +What is (still!) not added is multi-part archive support (a.k.a. "diskette +spanning", though we really mean archive splitting and not the old diskette +spanning) and a unified and more powerful DLL interface. These are the two +highest priorities for the 6.x releases. Work on the former is almost +certain to have commenced by the time you read this. This time we mean it! +You betcha. :-) + +Although the DLLs are still basically a mess, the Windows DLLs (16- and 32- +bit) now have some documentation and a small example application. Note that +they should now be compatible with C/C++, Visual BASIC and Delphi. Weirder +languages (FoxBase, etc.) are probably Right Out. + + +INTERNET RESOURCES +------------------ + +Info-ZIP's web site is at http://www.info-zip.org/pub/infozip/ +and contains the most up-to-date information about coming releases, +links to binaries, and common problems. +(See http://www.info-zip.org/pub/infozip/FAQ.html for the latter.) +Files may also be retrieved via ftp://ftp.info-zip.org/pub/infozip/ . +Thanks to LEO (Munich, Germany) for previously hosting our primary site. + + +DISTRIBUTION +------------ +If you have a question regarding redistribution of Info-ZIP software, either +as is, as packaging for a commercial product, or as an integral part of a +commercial product, please read the Frequently Asked Questions (FAQ) section +of the included COPYING file. All Info-ZIP releases are now covered by +the Info-ZIP license. See the file LICENSE. The most current license +should be available at http://www.info-zip.org/license.html and +ftp://ftp.info-zip.org/pub/infozip/license.html. + +Insofar as C compilers are rare on some platforms and the authors only have +direct access to a subset of the supported systems, others may wish to pro- +vide ready-to-run executables for new systems. In general there is no prob- +lem with this; we require only that such distributions include this README +file, the WHERE file, the LICENSE file (contains copyright/redistribution +information), and the appropriate documentation files (unzip.txt and/or +unzip.1 for UnZip, etc.). If the local system provides a way to make self- +extracting archives in which both the executables and text files can be +stored together, that's best (in particular, use UnZipSFX if at all possible, +even if it's a few kilobytes bigger than the alternatives); otherwise we +suggest a bare UnZip executable and a separate zipfile containing the re- +maining text and binary files. If another archiving method is in common +use on the target system (for example, Zoo or LHa), that may also be used. + + +BUGS AND NEW PORTS: CONTACTING INFO-ZIP +---------------------------------------- +All bug reports and patches (context diffs only, please!) should be +submitted either through the new Info-ZIP Discussion Forum at +http://www.info-zip.org/board/board.pl or through the Info-ZIP SourceForge +site at http://sourceforge.net/projects/infozip/. The forum allows file +attachments while SourceForge provides a place to post patches. The old +Zip-Bugs@lists.wku.edu e-mail address for the Info-ZIP authors was +discontinued after heavy continuous spam, as was the QuickTopic discussion +forum. The above methods are public, but we also can be reached directly +using the web reply page at http://www.info-zip.org/zip-bug.html. If you +need to send us files privately, contact us first for instructions. + +"Dumb questions" that aren't adequately answered in the documentation +should also be directed to Zip-Bugs rather than to a global forum such +as Usenet. (Kindly make certain that your question *isn't* answered by +the documentation, however--a great deal of effort has gone into making +it clear and complete.) + +Suggestions for new features can be discussed on the new Discussion Forum. +A new mailing list for Info-ZIP beta testers and interested parties may +be created someday, but for now any issues found in the betas should use +the forum. We make no promises to act on all suggestions or even all +patches, but if it is something that is manifestly useful, sending the +required patches to Zip-Bugs directly (as per the instructions in the +ZipPorts file) is likely to produce a quicker response than asking us to +do it--the authors are always ridiculously short on time. (Please do +NOT send patches or encoded zipfiles to the Info-ZIP list. Please DO +read the ZipPorts file before sending any large patch. It would be +difficult to over-emphasize this point...) + +If you are considering a port, not only should you read the ZipPorts file, +but also please check in with Zip-Bugs BEFORE getting started, since the +code is constantly being updated behind the scenes. (For example, VxWorks, +VMOS and Netware ports were once claimed to be under construction, although +we have yet to see any up-to-date patches.) We will arrange to send you the +latest sources. The alternative is the possibility that your hard work will +be tucked away in a subdirectory and mostly ignored, or completely ignored +if someone else has already done the port (and you'd be surprised how often +this has happened). + + +BETA TESTING: JOINING INFO-ZIP +------------------------------- +If you'd like to keep up to date with our UnZip (and companion Zip utility) +development, join the ranks of beta testers, add your own thoughts and +contributions, or simply lurk, you may join one of our mailing lists. +There is an announcements-only list (Info-ZIP-announce) and a general +discussion/testing list (Info-ZIP). You must be a subscriber to post, and +you can subscribe via the links on our Frequently Asked Questions page: + + http://www.info-zip.org/pub/infozip/FAQ.html#lists + +(Please note that as of late May 2004, the lists are unavailable pending +a move to a new site; we hope to have them restored shortly. In the +interim ...) Feel free to use our bug-reporting web page for bug reports +and to ask questions not answered on the FAQ page above: + + http://www.info-zip.org/zip-bug.html + +For now the best option is to monitor and contribute to the various threads +on the new discussion forum site at: + + http://www.info-zip.org/board/board.pl + +The second best way to contribute is through the various features at +SourceForge, such as the bug posting areas. + +There is also a closed mailing list for internal discussions of our core +development team. This list is now kept secret to prevent us from being +flooded with spam messages. + + +-- Greg Roelofs (sometimes known as Cave Newt), principal UnZip developer + guy, with inspiration from David Kirschbaum, was Author of this text. + +-- Christian Spieler (shorthand: SPC), current UnZip maintenance coordinator, + applied the most recent changes, with Ed Gordon providing a few additions. diff --git a/ToDo b/ToDo new file mode 100644 index 0000000..519c90e --- /dev/null +++ b/ToDo @@ -0,0 +1,226 @@ +================================ +For UnZip 6.1/who knows: +================================ + + o add extraction support for other compression algorithms used by new + PKZIP, WinZIP, 7-Zip versions + - LZMA, compression type 14 (most important, because of its efficiency) + - PPMd, compression type 98 (maybe, less important) + - WavPacked, compression type 97 (maybe, less important) + + LZMA is first-level priority for 6.1, other formats may be taken + into consideration + + o add support for reading AES encrypted archives + - WinZIP format (priority 1) + - PKZip format (priority 2) + + top level item for 6.1 + + o add multi-part zipfile handling + + major feature for 6.x! + + could happen for 6.1 + + o better support for multilingual uses and different codepages; + support unicode (UTF-8 coded) filenames and comment texts + + a requested feature getting more and more important, + - partially done for the Windows port in 6.0 + (support restricted for chars of the current system codepage) + - partially done (beta state) for Unix + (requires native codepage to be UTF-8) + + o complete support for UTF-8 coded entry names (and comments) + - add new "win32_wide" port to extend unicode support on Windows + beyond the restrictions of the current (ANSI) system codepage + - revise/extend the WinDLL interface to allow passing of "wide" + string argument data + - add simple built-in character translation between UTF-8 and the + old (ISO-8851-1 / IBM850) code pages to allow old systems without + standard UTF-8 support to read UTF-8 encoded archives. + - extend the built-in translation tables to support other language + regions besides "Western_Latin1" (e.g. Russian-kyrillic, Japanese, + Chinese) + - streamline the multilingual codepage and UTF-8 support for the UNIX + port (standard codepage translation facility?, like WideChar<->AnsiCP + translation functions under MS Windows) + + should happen for 6.1 + (there is internal alpha-state code for better "wide" support on + Windows available at the time of the 6.0 release) + + o revise the "extended charcodes" handling in decryption password to + support UTF-8 encoding on Unicode-aware systems where the "native" + character coding is NOT UTF-8 (e.g. Windows). + + o revise the command line interface for more compatibility with Zip' + command parser + - implement the versatile command parser from Zip 3.0. + - add "long option" definitions for all existing options; revise + the UnZip user manual to document the long-option alternatives. + - add support for reading the "process these entries" and the "skip + these entries" pattern lists from a file (or from separate files ?). + - add a (long) option to switch off UnZip's internal pattern matching + on filename arguments. + + probably in 6.1, + (first prototype of the revised command parser was available at the + time of the 6.0 release) + + o add command line options for miscellaneous features requested by users + and/or development team members: + - display the Info-ZIP software license + - more fine-tuning for file attributes set/restored at extraction, like: + set/clear archive attribute on DOS/OS2/WIN32; + apply/skip standard or user-defined umask filter on UNIX (& Unix-alike) + - additional time-stamp related processing filters + - more listing display modifications + - overriding the default date-time display style + - ... + + All these options are of minor importance and/or would collide with + existing "one-character" options. The current UnZip maintainer does not + want to reserve any of the few not-yet-occupied short option characters. + for one of these features. So, any implementation effort for items + of this feature wish-list has to be delayed until the "long option" + support of the revised command line parser becomes available. + + some option may get implemented in 6.1 + + o support for + and/or development team members: + + o add new low-level, binary API; rewrite "normal" (command-line) UnZip + to use it + + maybe soon (maybe 6.1) + + o MSDOS/WIN32/others: detection of "reserved" names (= names of character + devices, or system extensions that look like a characters device driver) + at runtime; with the goal of emitting "meaningful" error messages and/or + rename queries. + (Currently, these reserved names are catched as "non-deletable files". + On MSDOS and WIN32, when the RTL stat() function allows to identify + character devices, the "reserved" names are automatically prefixed with + an underscore.) + + o redesign "file exists -- is newer/older -- overwrite/skip/rename" + logic in extract.c and the corresponding system specific mapname() + services; to prevent superfluous decryption key prompts for entry + that will be skipped, later. + + o rewrite to use fread/fseek/etc. [eventually: test + write(bytes) vs. fwrite(words), especially on Crays/Alphas] + + soon (probably in conjunction with multi-part handling) + + o incorporate new backfill version of inflate() + + wait for zlib version + + o check NEXTBYTE for EOF in crypt.c, funzip.c and explode.c, too + + whenever + + o add option to force completely non-interactive operation (no queries + for overwrite/rename, password, etc.); also allow some sort of non- + interactive password provision? (file? command-line? env. variable?) + + someday? + + o add testing of extra fields (if have CRC) + + later + + o rewrite to allow use as a filter + + way, way later... + + o add Unix hard-link support? + + way, way later... + + o add ".ini" file support as a (more elaborate) alternative to the presently + supported preconfiguring abilities via special environment variables + (UNZIP on many systems...)? + + way, way later (if ever)... + + o add option to search zipfile contents for a string and print the + results? ("zipgrep" option--e.g., unzip -g or unzip -S) (easy for + fixed strings, hard for wildcards/true regex's) + + way, way later, if at all...probably use libregex + + o add -y "display symlinks" option to zipinfo? various sorting options? + (-St date/time, -Sn name)? + + who knows + + o add "in-depth" option to zipinfo? (check local headers against + central, etc.)--make it a better debugging tool (or just create + zipfix) + + who knows (zip -F, -FF already exist) + +Some maintenance or OS specific topics for 6.0 release: + + * add "unix-style-path -> partitioned-dataset filename" conversion + to MVS port + + * should we add support for (null) entry names (empty entry name field), to + conform to the PKWARE specification? + + +======================================= + +Requested features: + + - extract or exclude on basis of UID [Armin Bub, Armin.Bub@bk.bosch.de, 970904] + +======================================= + + o miscellaneous little stuff: whenever + -------------------------- + + - change DOS -f/-u stuff to use DOS API for getting filetimes, not stat() + + - add (-N?) option to lose all user input and/or switch to "(*input)()" + function, replaceable by UzpAltMain() param + - add -@ option to read from stdin (zip) or from file (PKZIP)? (go32 built-in) + - add -oo option to overwrite OS/2 and DOS system and hidden files, too + - add option to compute MD5 checksum on files and/or on entire zipfile? + + - decide whether to use WinGUI "skipping" diagnostics in extract.c + - combine "y/n/A/N" query/response stuff into unified section with query + function(s) (InputFn?) + - disable ^V code in remaining mapname() routines + + - change filename-matching logic so case-insensitive if case-sensitive fails? + + - allow multiple dir creation with -d option? [Bob Maynard] + + - use gcc -pg, gprof to do profiling on unzip + + - Doug Patriarche (doug.patriarche.bvdhp01@nt.com) Northern Telecom Canada Ltd. + "I need to do a port of zip/unzip for Wind River Systems' VxWorks OS" + [GRR: 15 March 95 -> "early June"] + + +Features from old BUGS file (mostly duplicates of other entries above): + + - ignore case for internal filename match on non-Unix systems, unless file- + specs enclosed in single quotes + - modify to decompress input stream if part of a pipe, but continue using + central directory if not (BIG job!)--extended local header capability + - add zipinfo option(s) to sort alphabetically, by date/time, in reverse, etc. + - when listing filenames, use '?' for non-printables? [Thomas Wolff, 92.6.1] + - add zipinfo "in-depth" option? (check local vs. central filenames, etc.) + - create zipcat program to concatenate zipfiles + - add -oo option (overwrite and override)? no user queries (if bad password, + skip file; if disk full, take default action; if VMS special on non-VMS, + unpack anyway; etc.) + - add -Q[Q[Q]] option (quiet mode on comments, cautions, warnings and errors)? + forget -oo, or make synonym? Default level -Q? diff --git a/WHERE b/WHERE new file mode 100644 index 0000000..3f39910 --- /dev/null +++ b/WHERE @@ -0,0 +1,266 @@ +__________________________________________________________________________ + + This is the Info-ZIP file ``WHERE,'' last updated on 29 March 2008. +__________________________________________________________________________ + + The latest version of this file can be found online at: + + ftp://ftp.info-zip.org/pub/infozip/doc/WHERE + + Note that some ftp sites may not yet have the latest versions of Zip + and UnZip when you read this. The latest versions always appear in + ftp://ftp.info-zip.org/pub/infozip/ (and subdirectories thereof) first, + except for encryption binaries, which always appear in + ftp://ftp.icce.rug.nl/infozip/ (and subdirectories) first. + + IF YOU FIND AN ERROR: please let us know! We don't have time to + check each and every site personally (or even collectively), so any + number of the sites listed below may have moved or disappeared en- + tirely. E-mail to Zip-Bugs@lists.wku.edu and we'll update this file. +__________________________________________________________________________ + + +Info-ZIP's home WWW site is listed on Yahoo and is at: + + ftp://ftp.info-zip.org/pub/infozip/Info-ZIP.html (master version) + http://ftp.info-zip.org/pub/infozip/ (master version) + http://www.info-zip.org/ + +Note that the old sites at http://www.cdrom.com/pub/infozip/ and +http://www.freesoftware.com/pub/infozip are PERMANENTLY BROKEN. They +cannot be updated or removed, apparently. + +The Zip and UnZip pages have links to most known mirror sites carrying our +source and/or binary distributions, and they generally are more up-to-date +and have better information than what you are reading: + + ftp://ftp.info-zip.org/pub/infozip/Zip.html + ftp://ftp.info-zip.org/pub/infozip/UnZip.html + +The related zlib package by Info-ZIP's Jean-loup Gailly and Mark Adler is at: + + http://www.zlib.net/ + +Source-code archives for Info-ZIP's portable Zip, UnZip, and related +utilities: + + zip30.zip Zip 3.0 (deflation, bzip2, ZIP64 large archives, multi- + volume splits; includes zipnote/zipsplit/zipcloak) + zip30.tar.Z ditto, compress'd tar format + + zip232.zip Zip 2.32 (deflation; includes zipnote/zipsplit/zipcloak) + zip232.tar.Z ditto, compress'd tar format + + zip11.zip Zip 1.1 (shrinking, implosion; compatible w. PKUNZIP 1.1) + zip11.tar.Z ditto, compress'd tar format + + unzip60.zip UnZip 6.0 (all methods[*]; unzip/funzip/unzipsfx/zipgrep) + unzip60.tar.gz ditto, gzip'd tar format + unzip60.tar.Z ditto, compress'd tar format + + unred60.zip UnZip 6.0 add-on, contains copyrighted unreduce support + + zcrypt29.zip encryption support for Zip 2.3[**] + zcrypt10.zip encryption support for Zip 1.1 + + MacZip106src.zip contains all the GUI stuff and the project files to build + the MacZip main-app. To build MacZip successfully, both + the Zip 3.0 and UnZip 6.0 sources are required, too. + + wiz601.zip WiZ 6.01, Windows 9x/NT GUI front-end for Info-ZIP's DLLs, + as well as the source code and project files for the DLLs, + and static libraries. + +[*] Unreducing is disabled by default, but is available as add-on. + As of July 2004, Unisys's LZW patent was expired worldwide, and + unshrinking is turned on by default since the release of UnZip 5.52. + See UnZip's INSTALL file for details. + +[**] As of January 2000, US export regulations were amended to allow export + of free encryption source code from the US. As of June 2002, these + regulations were further relaxed to allow export of encryption binaries + associated with free encryption source code. The Zip 2.31, UnZip 5.52 + and Wiz 5.02 archives now include full crypto source code. As of the + Zip 2.31 release, all official binaries include encryption support; the + former "zcr" archives ceased to exist. + (Note that restrictions may still exist in other countries, of course.) + +Executables archives (and related files) for Info-ZIP's software; not all +of these will be immediately available due to lack of access to appropriate +systems on the part of Info-ZIP members. + + zip###x.zip MSDOS executables and docs + zip###x1.zip OS/2 1.x (16-bit) executables and docs + zip###x2.zip OS/2 2/3/4.x (32-bit) executables and docs + zip###xA.zip Amiga executables and docs + zip###xB.zip BeOS executables and docs + zip###xC.zip VM/CMS executable and docs + zip###xK.zip Tandem NSK executables and docs + zip###xM.xmit MVS classic executable + zip###xM-docs.zip MVS classic port, docs only + zip###dN.zip WinNT/Win9x (Intel) DLL, header files, docs + zip###xN.zip WinNT/Win9x (Intel) executables and docs + zip###xN-axp.zip WinNT (Alpha AXP) executables and docs + zip###xN-mip.zip WinNT (MIPS R4000) executables and docs + zip###xN-ppc.zip WinNT (PowerPC) executables and docs + zip###xO.zip IBM OS/390 Open Edition binaries and docs + zip###xQ.zip SMS/QDOS executables and docs + zip###xR.zip Acorn RISC OS executables and docs + zip###xT.zip Atari TOS executables and docs + zip###-vms-axp-obj.zip + VMS (Alpha AXP) object libs, link procedure and docs + zip###-vms-axp-exe.zip + VMS (Alpha AXP) executables for VMS 6.1 or later and docs + zip###-vms-vax-decc-obj.zip + VMS (VAX) object libs (new DEC C), link procedure and docs + zip###-vms-vax-decc-exe.zip + VMS (VAX) executables (DEC C) for VMS 6.1 or later; docs + zip###-vms-vax-vaxc-obj.zip + VMS (VAX) object libs (old VAX C), link procedure and docs + zip###x.hqx Macintosh BinHex'd executables and docs + + unz###x.exe MSDOS self-extracting executable (16-bit unzip, ..., docs) + unz###x3.exe MSDOS self-extracting executable (16-, 32-bit unzip, docs) + unz###x1.exe OS/2 1.x (16-bit) self-extracting executables and docs + unz###x2.exe OS/2 2/3/4.x (32-bit) self-extracting executables and docs + unz###d2.zip OS/2 2/3/4.x (32-bit) DLL, header file, demo exe and docs + unz###xA.ami Amiga self-extracting executables and docs + unz###xA.lha Amiga executables and docs, LHa archive + unz###xB.sfx BeOS self-extracting executables and docs + unz###xB.tar.gz BeOS executables and docs, gzip'd tar archive + unz###xC.mod VM/CMS executable module in "packed" format + unz###xC-docs.zip VM/CMS docs, only + unz###xF.zip FlexOS executable and docs + unz###xK.zip Tandem NSK executable and docs + unz###xM.xmit MVS classic executable + unz###xM-docs.zip MVS classic port, docs only + unz###dN.zip NT4/W2K/XP/2K3/W9x (32-bit Intel) DLL, header files, docs + unz###xN.exe NT/2K/XP/2K3/W9x self-extracting i386 executables and docs + unz###xN-axp.exe WinNT (Alpha AXP) self-extracting executables and docs + unz###xN-mip.exe WinNT (MIPS R4000) self-extracting executables and docs + unz###xN-ppc.exe WinNT (PowerPC) self-extracting executables and docs + unz###xQ.sfx SMS/QDOS self-extracting executables and docs + unz###xO.tar.Z IBM OS/390 Open edition (Unix-like), exes and docs + unz###xR.exe Acorn RISC OS self-extracting executables and docs + unz###xR.spk Acorn RISC OS Spark'd executables and docs + unz###xT.tos Atari TOS self-extracting executables and docs + unz###x-vms-axp-obj.bck VMS backup saveset, + contains UnZip (Alpha) obj libs, link procedure, docs + unz###x-vms-axp-obj.exe VMS (Alpha AXP) SFX archive (statically linked), + contains UnZip (Alpha) obj libs, link procedure, docs + unz###x-vms-axp-exe.exe VMS (Alpha AXP) SFX archive (dynamically linked), + contains UnZip (Alpha AXP, DEC C) executables and docs, + smaller than object archive, but requires VMS 6.1 + unz###x-vms-vax-decc-obj.bck VMS backup saveset, + contains UnZip (new DEC C) obj libs, link procedure, docs + unz###x-vms-vax-decc-obj.exe VMS (VAX) SFX archive (statically linked), + contains UnZip (new DEC C) obj libs, link procedure, docs + unz###x-vms-vax-decc-exe.exe VMS (VAX) SFX archive (dynamically linked), + contains UnZip (new DEC C) executables and docs, + smaller than object archive, but requires VMS 6.1 + unz###x-vms-vax-vaxc-obj.bck VMS backup saveset, + contains UnZip (old VAX C) obj libs, link procedure, docs + unz###x-vms-vax-vaxc-obj.exe VMS (VAX) SFX archive (statically linked), + contains UnZip (old VAX C) obj libs, link procedure, docs + unz###x.hqx Macintosh BinHex'd executables and docs for unzip + (unz###x.tar.{Z,gz} Unix exes/docs for Solaris 2.x, SCO Unix, Linux, etc., + depending on directory/location; generally only provided + in cases where the OS does *not* ship with a bundled C + compiler) + + MacZip106nc.hqx Macintosh combined Zip&UnZip application with GUI, + executables and docs (no encryption) + MacZip106c.hqx Macintosh combined Zip&UnZip application with GUI, + executables and docs (with encryption) + + wiz###xN.exe WiZ #.## 32-bit (Win9x/NT/2K/XP/2K3) app+docs (self-extr.) + + UnzpHist.zip complete changes-history of UnZip and its precursors + ZipHist.zip complete changes-history of Zip + +ftp/web sites for the US-exportable sources and executables: + + NOTE: Look for the Info-ZIP file names given above (not PKWARE or third- + party stuff) in the following locations. Some sites like to use slightly + different names, such as zip-#.##.tar.gz instead of zip###.tar.Z. + + http://sourceforge.net/project/showfiles.php?group_id=118012 + [THE INFO-ZIP SOURCES HOME SITE] + + ftp://ftp.info-zip.org/pub/infozip/ [THE INFO-ZIP HOME SITE] + ftp://sunsite.doc.ic.ac.uk/packages/zip/ [MIRRORS THE INFO-ZIP HOME SITE] + ftp://unix.hensa.ac.uk/mirrors/uunet/pub/archiving/zip/ + + ftp://ftp.cmdl.noaa.gov/aerosol/doc/archiver/{all,dos,os2,mac,vax_alpha}/ + ftp://garbo.uwasa.fi/pc/arcers/ [AND OTHER GARBO MIRRORS] + ftp://garbo.uwasa.fi/unix/arcers/ [AND OTHER GARBO MIRRORS] + ftp://ftp.elf.stuba.sk/pub/pc/pack/ [AND OTHER STUBA MIRRORS] + ftp://ftp-os2.cdrom.com/pub/os2/archiver/ + ftp://ftp-os2.nmsu.edu/os2/archiver/ + ftp://ftp.informatik.tu-muenchen.de/pub/comp/os/os2/archiver/ + ftp://sumex-aim.stanford.edu/info-mac/cmp/ + ftp://ftp.wustl.edu/pub/aminet/util/arc/ [AND OTHER AMINET MIRRORS] + ftp://atari.archive.umich.edu/pub/Archivers/ [AND OTHER UMICH MIRRORS] + http://www.umich.edu/~archive/atari/Archivers/ + ftp://jake.educom.com.au/pub/infozip/acorn/ [Acorn RISC OS] + http://www.sitec.net/maczip/ [MacZip port] + +ftp/web sites for the encryption and decryption sources and/or executables: + + Outside the US: + ftp://ftp.info-zip.org/pub/infozip/ [THE INFO-ZIP HOME SITE] + ftp://ftp.icce.rug.nl/infozip/ [THE INFO-ZIP ENCRYPTION HOME SITE] + ftp://ftp.elf.stuba.sk/pub/pc/pack/ + ftp://garbo.uwasa.fi/pc/arcers/ + ftp://ftp.inria.fr/system/arch-compr/ + ftp://ftp.leo.org/pub/comp/os/os2/leo/archiver/ + (mail server at ftp-mailer@ftp.leo.org) + + ftp://ftp.win.tue.nl/pub/compression/zip/ + ftp://ftp.uni-erlangen.de/pub/pc/msdos/arc-utils/zip/ + + +The primary distribution site for the MacZip port can be found at: + + http://www.sitec.net/maczip/ + +ftp sites for VMS-format Zip and UnZip packages (sources, object files and +executables, no encryption/decryption--see also "Mail servers" section below): + + ftp.spc.edu [192.107.46.27] and ftp.wku.edu: + + [.MACRO32]AAAREADME.TXT + [.MACRO32.SAVESETS]UNZIP.BCK or UNZIP.ZIP (if already have older version) + [.MACRO32.SAVESETS]ZIP.ZIP + +To find other ftp/web sites: + + The "archie" ftp database utility can be used to find an ftp site near + you (although the command-line versions always seem to find old ver- + sions...the `FTPsearch' server at http://ftpsearch.ntnu.no/ftpsearch + --formerly `Archie 95'--is quite up-to-date, however). Or check a stan- + dard WWW search engine like AltaVista (http://www.altavista.digital.com/) + or Yahoo (http://www.yahoo.com/). If you don't know how to use these, + DON'T ASK US--read the web sites' help pages or check the Usenet groups + news.announce.newusers or news.answers or some such, or ask your system + administrator. + +Mail servers: + + To get the encryption sources by e-mail, send the following commands + to ftp-mailer@informatik.tu-muenchen.de: + + get /pub/comp/os/os2/archiver/zcrypt29.zip + quit + + To get the VMS Zip/UnZip package by e-mail, send the following + commands in the body of a mail message to fileserv@wku.edu (the + "HELP" command is also accepted): + + SEND FILESERV_TOOLS + SEND UNZIP + SEND ZIP + + To get Atari executables by e-mail, send a message to + atari@atari.archive.umich.edu for information about the mail server. +__________________________________________________________________________ diff --git a/acorn/Contents b/acorn/Contents new file mode 100644 index 0000000..d803c49 --- /dev/null +++ b/acorn/Contents @@ -0,0 +1,26 @@ +Contents of the "acorn" subdirectory for UnZip 5.4 and later: + + acorn.c.acorn Acorn-specific resources + acorn.c.riscos mainly file-handling routines for FileCore-based filesystems + acorn.Contents this file + acorn.GMakeFile Makefile for gcc + acorn.h.riscos + acorn.h.swiven + acorn.makefile Makefile script for default Acorn C compiler + acorn.README notes about Acorn-specific features + acorn.RunMe1st Obey file to move files into suitable place for compilation + on RISC OS machines + acorn.s.swiven SWI veneers + acorn.srcrename small executable that converts files from Unix style to + RISC OS style, used by RunMe1st + +Notes: + + Use the "RunMe1st" file (it is an Obey file) to convert all the files from + "filename/[chs]" to "[chs].filename" (so that UnZip could be easily compiled + under RISC OS). It will also set the correct makefile. + + To compile just set the CSD to the main UnZip directory and run 'amu'. + + Currently only the Acorn C V5 compiler has been tested but probably also + Acorn C V4 and the Acorn Assembler V2 will be able to compile UnZip. diff --git a/acorn/GMakefile b/acorn/GMakefile new file mode 100644 index 0000000..48f8a33 --- /dev/null +++ b/acorn/GMakefile @@ -0,0 +1,138 @@ +# Makefile for UnZip, UnZipSFX, ZipInfo and fUnZip (5.53 or later) +# using gcc 2.95.4 (or later). +# You may look at for an up-to-date +# gcc port. + +CC = gcc -mlibscl +BIND = $(CC) +AS = $(CC) -c +ASM = as +SQUEEZE = squeeze -v +E = + +# flags +# CFLAGS flags for C compile +# LFLAGS1 flags after output file spec, before obj file list +# LFLAGS2 flags after obj file list (libraries, etc) +# +LIB = +CFLAGS = -O2 -mthrowback -DNO_STRNICMP +ASMFLAGS = -throwback -objasm -upper +LFLAGS1 = +LFLAGS2 = $(LIB) + +# object file lists +OBJS1 = o.unzip o.crc32 o.crypt o.envargs o.explode +OBJS2 = o.extract o.fileio o.globals o.inflate o.list o.match +OBJS3 = o.process o.ttyio o.unreduce o.unshrink o.zipinfo +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) o.riscos o.swiven o.acorn +OBJF = o.funzip o.crc32 o.cryptf o.globalsf o.inflatef o.ttyiof \ + o.riscos o.swiven +OBJX = o.unzipsfx o.crc32 o.crypt_ o.extract_ o.fileio_ o.globals_ \ + o.inflate_ o.match_ o.process_ o.ttyio_ o.acorn_ o.swiven o.riscos_ + +UNZIP_H = h.unzip h.unzpriv h.globals acorn.h.riscos acorn.h.swiven + +all: unzip funzip unzipsfx + + +install: unzip funzip unzipsfx + $(SQUEEZE) unzip %.unzip + $(SQUEEZE) funzip %.funzip + $(SQUEEZE) unzipsfx unzipsfx + copy %.unzip %.zipinfo ~CVF + +# rules for unzip and funzip +o.crc32: c.crc32 $(UNZIP_H) h.zip h.crc32 + $(CC) $(CFLAGS) -c c.crc32 -o o.crc32 +o.crypt: c.crypt $(UNZIP_H) h.zip h.crypt h.crc32 h.ttyio + $(CC) $(CFLAGS) -c c.crypt -o o.crypt +o.envargs: c.envargs $(UNZIP_H) + $(CC) $(CFLAGS) -c c.envargs -o o.envargs +o.explode: c.explode $(UNZIP_H) + $(CC) $(CFLAGS) -c c.explode -o o.explode +o.extract: c.extract $(UNZIP_H) h.crc32 h.crypt + $(CC) $(CFLAGS) -c c.extract -o o.extract +o.fileio: c.fileio $(UNZIP_H) h.crc32 h.crypt h.ttyio h.ebcdic + $(CC) $(CFLAGS) -c c.fileio -o o.fileio +o.funzip: c.funzip $(UNZIP_H) h.crc32 h.crypt h.ttyio + $(CC) $(CFLAGS) -c c.funzip -o o.funzip +o.globals: c.globals $(UNZIP_H) + $(CC) $(CFLAGS) -c c.globals -o o.globals +o.inflate: c.inflate h.inflate $(UNZIP_H) + $(CC) $(CFLAGS) -c c.inflate -o o.inflate +o.list: c.list $(UNZIP_H) + $(CC) $(CFLAGS) -c c.list -o o.list +o.match: c.match $(UNZIP_H) + $(CC) $(CFLAGS) -c c.match -o o.match +o.process: c.process $(UNZIP_H) h.crc32 + $(CC) $(CFLAGS) -c c.process -o o.process +o.ttyio: c.ttyio $(UNZIP_H) h.zip h.crypt h.ttyio + $(CC) $(CFLAGS) -c c.ttyio -o o.ttyio +o.unreduce: c.unreduce $(UNZIP_H) + $(CC) $(CFLAGS) -c c.unreduce -o o.unreduce +o.unshrink: c.unshrink $(UNZIP_H) + $(CC) $(CFLAGS) -c c.unshrink -o o.unshrink +o.unzip: c.unzip $(UNZIP_H) h.crypt h.unzvers h.consts + $(CC) $(CFLAGS) -c c.unzip -o o.unzip +o.zipinfo: c.zipinfo $(UNZIP_H) + $(CC) $(CFLAGS) -c c.zipinfo -o o.zipinfo + +o.crypt_: c.crypt $(UNZIP_H) h.zip h.crypt h.crc32 h.ttyio + $(CC) $(CFLAGS) -DSFX -c c.crypt -o o.crypt_ +o.extract_: c.extract $(UNZIP_H) h.crc32 h.crypt + $(CC) $(CFLAGS) -DSFX -c c.extract -o o.extract_ +o.fileio_: c.fileio $(UNZIP_H) h.crc32 h.crypt h.ttyio h.ebcdic + $(CC) $(CFLAGS) -DSFX -c c.fileio -o o.fileio_ +o.globals_: c.globals $(UNZIP_H) + $(CC) $(CFLAGS) -DSFX -c c.globals -o o.globals_ +o.inflate_: c.inflate h.inflate $(UNZIP_H) h.crypt + $(CC) $(CFLAGS) -DSFX -c c.inflate -o o.inflate_ +o.match_: c.match $(UNZIP_H) + $(CC) $(CFLAGS) -DSFX -c c.match -o o.match_ +o.process_: c.process $(UNZIP_H) h.crc32 + $(CC) $(CFLAGS) -DSFX -c c.process -o o.process_ +o.ttyio_: c.ttyio $(UNZIP_H) h.zip h.crypt h.ttyio + $(CC) $(CFLAGS) -DSFX -c c.ttyio -o o.ttyio_ + +o.unzipsfx: c.unzip $(UNZIP_H) h.crypt h.unzvers h.consts + $(CC) $(CFLAGS) -DSFX -c c.unzip -o o.unzipsfx + +o.cryptf: c.crypt $(UNZIP_H) h.zip h.crypt h.crc32 h.ttyio + $(CC) $(CFLAGS) -DFUNZIP -c c.crypt -o o.cryptf +o.globalsf: c.globals $(UNZIP_H) + $(CC) $(CFLAGS) -DFUNZIP -c c.globals -o o.globalsf +o.inflatef: c.inflate h.inflate $(UNZIP_H) h.crypt + $(CC) $(CFLAGS) -DFUNZIP -c c.inflate -o o.inflatef +o.ttyiof: c.ttyio $(UNZIP_H) h.zip h.crypt h.ttyio + $(CC) $(CFLAGS) -DFUNZIP -c c.ttyio -o o.ttyiof + +o.acorn: acorn.c.acorn $(UNZIP_H) + $(CC) $(CFLAGS) -I@ -c acorn.c.acorn +o.acorn_: acorn.c.acorn $(UNZIP_H) + $(CC) $(CFLAGS) -I@ -c -DSFX -DSFX_EXDIR -o o.acorn_ acorn.c.acorn + +o.riscos: acorn.c.riscos $(UNZIP_H) + $(CC) $(CFLAGS) -I@ -c acorn.c.riscos +o.riscos_: acorn.c.riscos $(UNZIP_H) + $(CC) $(CFLAGS) -I@ -c -DSFX -DSFX_EXDIR -o o.riscos_ acorn.c.riscos + +o.swiven: acorn.s.swiven + $(ASM) $(ASMFLAGS) acorn.s.swiven -o o.swiven + +unzip: $(OBJS) + $(BIND) -o unzip$(E) $(LFLAGS1) $(OBJS) $(LFLAGS2) +funzip: $(OBJF) + $(BIND) -o funzip$(E) $(LFLAGS1) $(OBJF) $(LFLAGS2) +unzipsfx: $(OBJX) + $(BIND) -o unzipsfx$(E) $(LFLAGS1) $(OBJX) $(LFLAGS2) + +clean: + remove unzip + remove funzip + remove zipinfo + remove unzipsfx + create o.!fake! 0 + wipe o.* ~cf + +# end of Makefile diff --git a/acorn/ReadMe b/acorn/ReadMe new file mode 100644 index 0000000..8768d07 --- /dev/null +++ b/acorn/ReadMe @@ -0,0 +1,69 @@ +Acorn-specific usage instructions +--------------------------------- + +As zipfiles can come from a variety of sources apart from Acorn machines, +consideration had to be given to the handling of dot-extensions, e.g. +"DOSFILE.TXT", "unix-filename.tar.gz". These are extracted as "DOSFILE/TXT" +and "unix-filename/tar/gz"; their names may or may not be truncated, +depending on where the files are being created: what filing system and, for +Filecore-based filing systems such as ADFS or an IDEFS or SCSIFS, which +disk/partition format (names will not be truncated if you're using E+ or F+). + +Where truncation occurs, you must be REALLY careful about extracting files +from archives. The files + + dummy_source.c and dummy_source.h + +will both be extracted as + + dummy_sour + +UnZip will prompt you for confirmation of the over-writing of these files, +but you must be really careful unless you wish to lose files! Also, because +UnZip is a unix-ported program, the filenames are CASE SENSITIVE. + + *unzip new/zip newfile + +will extract 'newfile', but not 'NewFile', 'NEWFILE' or any other +combinations. However, you can use the -C option to force operations to +disregard the case of filenames. + +The Acorn UnZip port has an additional feature to cope with the extraction of +files containing 'c' code. As you may be aware, Acorn Desktop C requires all +files called "foo.c" to be renamed to "c.foo", ie "foo" in a directory called +"c". + +There are two ways of using this feature. + +- The old way: use a colon-separated environment variable named "Unzip$Exts". + + Any extensions found in this variable will be extracted to directories + named after the extension, with the extension stripped. For example: + + *Set Unzip$Exts "c:h:o:s" + *unzip foo/zip + +- The new way: use the -/ option. For example: + + Any extensions found in the parameter for this option will be extracted to + directories named after the extension, with the extension stripped. For + example: + + *unzip -/c:h:o:s foo/zip + +If foo/zip contains a file named "foo.c", this file will be written as "foo" +in directory "c". This can be used to include "c:h:o:s:txt" to pull all the +text files out to a separate directory. + +UnZip fully supports SparkFS Extra Field. This means that zipfiles created +with SparkFS or Zip (on RISC OS) will be correctly unzipped, including +filetypes. + +UnZipSFX can be used to create self-extracting archives. To use it, just +create a common zipfile using Zip (or SparkFS), then load the UnZipSFX +executable into an editor (eg. Edit, Zap), go with the caret the end of the +file (using CTRL-CursorDown) and drag the zipfile to the editor window (in +other words, append the zipfile to the UnZipSFX executable). Now, saving the +resulting file (with filetype Absolute (&FF8)), you have a self-extracting +archive (ie. double-clicking on it will unzip the contents of the original +zipfile to the currently selected directory). diff --git a/acorn/RunMe1st b/acorn/RunMe1st new file mode 100644 index 0000000..aaad22d --- /dev/null +++ b/acorn/RunMe1st @@ -0,0 +1,17 @@ +| This Obey file prepares the UnZip port for a Desktop C re-compile. +| Run it and it will copy all the needed files into the correct +| place. + +| Set the correct type of 'srcrename' so that the only requirement +| for the user is to set 'RunMe1st' to Obey +SetType .srcrename FF8 + +| Run 'srcrename' on the main UnZip directory with recursion enabled +/.srcrename -r -e c:h:s:o .^ + +| Create the 'o' directory +CDir .^.o + +| Put the Makefile in its correct place and set the correct filetype +SetType .makefile FE1 +Copy .makefile .^.makefile ~C ~V F diff --git a/acorn/acorn.c b/acorn/acorn.c new file mode 100644 index 0000000..2557f25 --- /dev/null +++ b/acorn/acorn.c @@ -0,0 +1,994 @@ +/* + Copyright (c) 1990-2007 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 +*/ +/*--------------------------------------------------------------------------- + + acorn.c + + RISCOS-specific routines for use with Info-ZIP's UnZip 5.2 and later. + + Contains: do_wild() <-- generic enough to put in fileio.c? + mapattr() + mapname() + checkdir() + mkdir() + setRISCOSexfield() + printRISCOSexfield() + close_outfile() + stamp_file() + version() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "^.unzip.h" +#include "riscos.h" + +#define FTYPE_FFF (1<<17) /* set filetype to &FFF when extracting */ + +#ifdef WILD_STOP_AT_DIR +# define WESEP , (oU.W_flag ? '.' : '\0') +#else +# define WESEP +#endif + +static int created_dir; /* used in mapname(), checkdir() */ +static int renamed_fullpath; /* ditto */ +static int has_mimemap = -1; /* used in mimemap() */ + +extern int mkdir(const char *path, int mode); +static int has_NFS_ext(const char *name); +static void setRISCOSexfield(ZCONST char *path, ZCONST void *ef_spark); +#ifdef DEBUG +static void printRISCOSexfield(int isdir, ZCONST void *extra_field); +#endif +static int uxtime2acornftime(unsigned *pexadr, unsigned *pldadr, time_t ut); +static int mimemap(const char *name); + + +#ifndef SFX + +/**********************/ +/* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ +/**********************/ + +char *do_wild(__G__ wildspec) + __GDEF + ZCONST char *wildspec; /* only used first time on a given dir */ +{ + static DIR *wild_dir = (DIR *)NULL; + static ZCONST char *wildname; + static char *dirname, matchname[FILNAMSIZ]; + static int notfirstcall=FALSE, have_dirname, dirnamelen; + struct dirent *file; + + /* Even when we're just returning wildspec, we *always* do so in + * matchname[]--calling routine is allowed to append four characters + * to the returned string, and wildspec may be a pointer to argv[]. + */ + if (!notfirstcall) { /* first call: must initialize everything */ + notfirstcall = TRUE; + + /* break the wildspec into a directory part and a wildcard filename */ + if ((wildname = (ZCONST char *)strrchr(wildspec, '.')) == + (ZCONST char *)NULL) + { + dirname = "."; + dirnamelen = 1; + have_dirname = FALSE; + wildname = wildspec; + } else { + ++wildname; /* point at character after '/' */ + dirnamelen = wildname - wildspec; + if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) { + Info(slide, 0x201, ((char *)slide, + "warning: cannot allocate wildcard buffers\n")); + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; /* but maybe filespec was not a wildcard */ + } + strncpy(dirname, wildspec, dirnamelen); + dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ + have_dirname = TRUE; + } + + if ((wild_dir = opendir(dirname)) != (DIR *)NULL) { + while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { + if (file->d_name[0] == '/' && wildname[0] != '/') + continue; /* Unix: '*' and '?' do not match leading dot */ + if (match(file->d_name, wildname, 0 WESEP)) { /* 0=case sens.*/ + if (have_dirname) { + strcpy(matchname, dirname); + strcpy(matchname+dirnamelen, file->d_name); + } else + strcpy(matchname, file->d_name); + return matchname; + } + } + /* if we get to here directory is exhausted, so close it */ + closedir(wild_dir); + wild_dir = (DIR *)NULL; + } + + /* return the raw wildspec in case that works (e.g., directory not + * searchable, but filespec was not wild and file is readable) */ + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (wild_dir == (DIR *)NULL) { + notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + } + + /* If we've gotten this far, we've read and matched at least one entry + * successfully (in a previous call), so dirname has been copied into + * matchname already. + */ + while ((file = readdir(wild_dir)) != (struct dirent *)NULL) + if (match(file->d_name, wildname, 0 WESEP)) { /* 0 == case sens. */ + if (have_dirname) { + /* strcpy(matchname, dirname); */ + strcpy(matchname+dirnamelen, file->d_name); + } else + strcpy(matchname, file->d_name); + return matchname; + } + + closedir(wild_dir); /* have read at least one dir entry; nothing left */ + wild_dir = (DIR *)NULL; + notfirstcall = FALSE; /* reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + +} /* end function do_wild() */ + +#endif /* !SFX */ + + + +/**************************/ +/* Function has_NFS_ext() */ +/**************************/ + +static int has_NFS_ext(const char* name) +{ + int i = strlen(name) - 4; + + return (i >= 0 && name[i] == ',' && (i > 0 || name[i-1]=='/') && + isxdigit(name[i+1]) && isxdigit(name[i+2]) && isxdigit(name[i+3])); +} /* end function has_NFS_ext() */ + + + +/**********************/ +/* Function mapattr() */ +/**********************/ + +int mapattr(__G) + __GDEF +{ + ulg tmp = G.crec.external_file_attributes; + + switch (G.pInfo->hostnum) { + case AMIGA_: + tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */ + G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp); + break; + case THEOS_: + tmp &= 0xF1FFFFFFL; + if ((tmp & 0xF0000000L) != 0x40000000L) + tmp &= 0x01FFFFFFL; /* not a dir, mask all ftype bits */ + else + tmp &= 0x41FFFFFFL; /* leave directory bit as set */ + /* fall through! */ + case ACORN_: + case UNIX_: + case VMS_: + case ATARI_: + case ATHEOS_: + case BEOS_: + case QDOS_: + case TANDEM_: + G.pInfo->file_attr = (unsigned)(tmp >> 16); + if (G.pInfo->file_attr != 0 || !G.extra_field) { + break; + } else { + /* Some (non-Info-ZIP) implementations of Zip for Unix and + VMS (and probably others ??) leave 0 in the upper 16-bit + part of the external_file_attributes field. Instead, they + store file permission attributes in some extra field. + As a work-around, we search for the presence of one of + these extra fields and fall back to the MSDOS compatible + part of external_file_attributes if one of the known + e.f. types has been detected. + Later, we might implement extraction of the permission + bits from the VMS extra field. But for now, the work-around + should be sufficient to provide "readable" extracted files. + (For ASI Unix e.f., an experimental remap of the e.f. + mode value IS already provided!) + */ + ush ebID; + unsigned ebLen; + uch *ef = G.extra_field; + unsigned ef_len = G.crec.extra_field_length; + int r = FALSE; + + while (!r && ef_len >= EB_HEADSIZE) { + ebID = makeword(ef); + ebLen = (unsigned)makeword(ef+EB_LEN); + if (ebLen > (ef_len - EB_HEADSIZE)) + /* discoverd some e.f. inconsistency! */ + break; + switch (ebID) { + case EF_ASIUNIX: + if (ebLen >= (EB_ASI_MODE+2)) { + G.pInfo->file_attr = + (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE)); + /* force stop of loop: */ + ef_len = (ebLen + EB_HEADSIZE); + break; + } + /* else: fall through! */ + case EF_PKVMS: + /* "found nondecypherable e.f. with perm. attr" */ + r = TRUE; + default: + break; + } + ef_len -= (ebLen + EB_HEADSIZE); + ef += (ebLen + EB_HEADSIZE); + } + if (!r) + break; + } + /* fall through! */ + /* all remaining cases: expand MSDOS read-only bit into write perms */ + case FS_FAT_: + /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the + * Unix attributes in the upper 16 bits of the external attributes + * field, just like Info-ZIP's Zip for Unix. We try to use that + * value, after a check for consistency with the MSDOS attribute + * bits (see below). + */ + G.pInfo->file_attr = (unsigned)(tmp >> 16); + /* fall through! */ + case FS_HPFS_: + case FS_NTFS_: + case MAC_: + case TOPS20_: + default: + /* Ensure that DOS subdir bit is set when the entry's name ends + * in a '/'. Some third-party Zip programs fail to set the subdir + * bit for directory entries. + */ + if ((tmp & 0x10) == 0) { + extent fnlen = strlen(G.filename); + if (fnlen > 0 && G.filename[fnlen-1] == '/') + tmp |= 0x10; + } + /* read-only bit --> write perms; subdir bit --> dir exec bit */ + tmp = !(tmp & 1) << 1 | (tmp & 0x10) >> 4; + if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) + /* keep previous G.pInfo->file_attr setting, when its "owner" + * part appears to be consistent with DOS attribute flags! + */ + break; + G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp); + break; + } /* end switch (host-OS-created-by) */ + + G.pInfo->file_attr&=0xFFFF; + + G.pInfo->file_attr|=(0xFFDu<<20); + + if (has_NFS_ext(G.filename)) { + int ftype=strtol(G.filename+strlen(G.filename)-3,NULL,16)&0xFFF; + + G.pInfo->file_attr = (G.pInfo->file_attr & 0x000FFFFF) | (ftype<<20); + } else { + int type = mimemap(G.filename); + if (type == -1) + type = (G.crec.internal_file_attributes & 1) ? 0xFFF : 0xFFD; + G.pInfo->file_attr = (G.pInfo->file_attr & 0x000FFFFF) | (type<<20); + } + + return 0; + +} /* end function mapattr() */ + + + +/************************/ +/* Function mimemap() */ +/************************/ + +static int mimemap(const char *name) +{ + const char *ext = name; + int type; + + if (has_mimemap < 0) + has_mimemap = + !(SWI_OS_CLI("%RMEnsure MimeMap 0.05 RMLoad System:Modules.Network.MimeMap") + || SWI_OS_CLI("%RMEnsure MimeMap 0.05")); + + if (!has_mimemap) + return -1; /* no MimeMap module; fall back on text flag test */ + + do { + while (*ext && *ext!='.') + ext++; + if (!*ext) + return -1; /* no suitable extension; fallback */ + type = SWI_MimeMap_Translate(ext++); + } while (type == -1); + + return type; +} + + + +/************************/ +/* Function mapname() */ +/************************/ + +int mapname(__G__ renamed) + __GDEF + int renamed; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - caution (truncated filename) + * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) + * MPN_ERR_SKIP - error -> skip entry + * MPN_ERR_TOOLONG - error -> path is too long + * MPN_NOMEM - error (memory allocation failed) -> skip entry + * [also MPN_VOL_LABEL, MPN_CREATED_DIR] + */ +{ + char pathcomp[FILNAMSIZ]; /* path-component buffer */ + char *pp, *cp=(char *)NULL; /* character pointers */ + char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ + int error = MPN_OK; + register unsigned workch; /* hold the character being tested */ + char *checkswap=NULL; /* pointer the the extension to check */ + + +/*--------------------------------------------------------------------------- + Initialize various pointers and counters and stuff. + ---------------------------------------------------------------------------*/ + + if (G.pInfo->vollabel) + return MPN_VOL_LABEL; /* can't set disk volume labels in RISCOS */ + + /* can create path as long as not just freshening, or if user told us */ + G.create_dirs = (!uO.fflag || renamed); + + created_dir = FALSE; /* not yet */ + + /* user gave full pathname: don't prepend rootpath */ + renamed_fullpath = (renamed && (*G.filename == '/')); + + if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM) + return MPN_NOMEM; /* initialize path buffer, unless no memory */ + + *pathcomp = '\0'; /* initialize translation buffer */ + pp = pathcomp; /* point to translation buffer */ + if (uO.jflag) /* junking directories */ + cp = (char *)strrchr(G.filename, '/'); + if (cp == (char *)NULL) /* no '/' or not junking dirs */ + cp = G.filename; /* point to internal zipfile-member pathname */ + else + ++cp; /* point to start of last component of path */ + +/*--------------------------------------------------------------------------- + Begin main loop through characters in filename. + ---------------------------------------------------------------------------*/ + + while ((workch = (uch)*cp++) != 0) { + + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + if (((error = checkdir(__G__ pathcomp, APPEND_DIR)) + & MPN_MASK) > MPN_INF_TRUNC) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ + checkswap=NULL; /* reset checking at start of new leafname */ + break; + + case '.': + *pp++ = '/'; + checkswap=pp; + break; + + case ';': /* VMS version (or DEC-20 attrib?) */ + lastsemi = pp; + *pp++ = ';'; /* keep for now; remove VMS ";##" */ + break; /* later, if requested */ + + case ' ': /* change spaces to hard-spaces */ + *pp++ = 160; /* (ISO 8859-1 Latin-1 codepage) */ + break; + + /* The following substitutions, unless stated otherwise, follow + * those for DOSFS. They translate special symbols into other + * characters which have no special meaning to RISC OS. */ + case '#': *pp++ = '?'; break; /* single-char wildcard */ + case '&': *pp++ = '+'; break; + case '@': *pp++ = '='; break; + case '%': *pp++ = ';'; break; + case '$': *pp++ = '<'; break; + case '^': *pp++ = '>'; break; /* parent-dir reference */ + + /* The following substitutions deal with the remaining special + * symbols. ('.' is handled above.) */ + case '*': *pp++ = 0xD7; break; /* Latin-1 'multiply' */ + case '"': *pp++ = '~'; break; + case ':': *pp++ = ';'; break; + case '\\': *pp++ = '/'; break; + case '|': *pp++ = 0xA6; break; /* Latin-1 'broken bar' */ + + default: + /* allow European characters in filenames: */ + if (isprint(workch) || (128 <= workch && workch <= 254)) + *pp++ = (char)workch; + } /* end switch */ + + } /* end while loop */ + +/*--------------------------------------------------------------------------- + Report if directory was created (and no file to create: filename ended + in '/'), check name to be sure it exists, and combine path and name be- + fore exiting. + ---------------------------------------------------------------------------*/ + + if (G.filename[strlen(G.filename) - 1] == '/') { + checkdir(__G__ G.filename, GETPATH); + if (created_dir) { + if (QCOND2) { + Info(slide, 0, ((char *)slide, " creating: %s\n", + FnFilter1(G.filename))); + } + /* set dir time (note trailing '/') */ + return (error & ~MPN_MASK) | MPN_CREATED_DIR; + } + /* dir existed already; don't look for data to extract */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + *pp = '\0'; /* done with pathcomp: terminate it */ + + /* if not saving them, remove VMS version numbers (appended ";###") */ + if (!uO.V_flag && lastsemi) { + pp = lastsemi + 1; + while (isdigit((uch)(*pp))) + ++pp; + if (*pp == '\0') /* only digits between ';' and end: nuke */ + *lastsemi = '\0'; + } + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", + FnFilter1(G.filename))); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + + if (checkswap!=NULL) { + if (checkext(checkswap)) { + if ((error = checkdir(__G__ checkswap, APPEND_DIR)) > 1) + return error; + *(checkswap-1)=0; /* remove extension from pathcomp */ + } + } + + if (!uO.acorn_nfs_ext && has_NFS_ext(pathcomp)) { + /* remove the filetype extension unless requested otherwise */ + /* the filetype should be already set by mapattr() */ + pathcomp[strlen(pathcomp)-4]=0; + } + + checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ + checkdir(__G__ G.filename, GETPATH); + + return error; + +} /* end function mapname() */ + + + + +/***********************/ +/* Function checkdir() */ +/***********************/ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename + * MPN_INF_SKIP - path doesn't exist, not allowed to create + * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path + * exists and is not a directory, but is supposed to be + * MPN_ERR_TOOLONG - path is too long + * MPN_NOMEM - can't allocate memory for filename buffers + */ +{ + static int rootlen = 0; /* length of rootpath */ + static char *rootpath; /* user's "extract-to" directory */ + static char *buildpath; /* full path (so far) to extracted file */ + static char *end; /* pointer to end of buildpath ('\0') */ + +# define FN_MASK 7 +# define FUNCTION (flag & FN_MASK) + + +/*--------------------------------------------------------------------------- + APPEND_DIR: append the path component to the path being built and check + for its existence. If doesn't exist and we are creating directories, do + so for this one; else signal success or error as appropriate. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_DIR) { + int too_long = FALSE; +#ifdef SHORT_NAMES + char *old_end = end; +#endif + + Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') + ++end; +#ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ + if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ + *(end = old_end + FILENAME_MAX) = '\0'; +#endif + + /* GRR: could do better check, see if overrunning buffer as we go: + * check end-buildpath after each append, set warning variable if + * within 20 of FILNAMSIZ; then if var set, do careful check when + * appending. Clear variable when begin new path. */ + + /* next check: need to append '/', at least one-char name, '\0' */ + if ((end-buildpath) > FILNAMSIZ-3) + too_long = TRUE; /* check if extracting dir? */ + if (stat(buildpath, &G.statbuf)) { /* path doesn't exist */ + if (!G.create_dirs) { /* told not to create (freshening) */ + free(buildpath); + return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", + FnFilter1(buildpath))); + fflush(stderr); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + if (mkdir(buildpath, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, + "checkdir error: cannot create %s\n\ + unable to process %s.\n", + FnFilter2(buildpath), FnFilter1(G.filename))); + free(buildpath); + /* path didn't exist, tried to create, failed */ + return MPN_ERR_SKIP; + } + created_dir = TRUE; + } else if (!S_ISDIR(G.statbuf.st_mode)) { + Info(slide, 1, ((char *)slide, + "checkdir error: %s exists but is not directory\n\ + unable to process %s.\n", + FnFilter2(buildpath), FnFilter1(G.filename))); + free(buildpath); + /* path existed but wasn't dir */ + return MPN_ERR_SKIP; + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + *end++ = '.'; /************* was '/' *************/ + *end = '\0'; + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + return MPN_OK; + + } /* end if (FUNCTION == APPEND_DIR) */ + +/*--------------------------------------------------------------------------- + GETPATH: copy full path to the string pointed at by pathcomp, and free + buildpath. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == GETPATH) { + strcpy(pathcomp, buildpath); + Trace((stderr, "getting and freeing path [%s]\n", + FnFilter1(pathcomp))); + free(buildpath); + buildpath = end = (char *)NULL; + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + APPEND_NAME: assume the path component is the filename; append it and + return without checking for existence. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_NAME) { +#ifdef SHORT_NAMES + char *old_end = end; +#endif + + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') { + ++end; +#ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ + if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ + *(end = old_end + FILENAME_MAX) = '\0'; +#endif + if ((end-buildpath) >= FILNAMSIZ) { + *--end = '\0'; + Info(slide, 0x201, ((char *)slide, + "checkdir warning: path too long; truncating\n\ + %s\n -> %s\n", + FnFilter1(G.filename), FnFilter2(buildpath))); + return MPN_INF_TRUNC; /* filename truncated */ + } + } + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + /* could check for existence here, prompt for new name... */ + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + INIT: allocate and initialize buffer space for the file currently being + extracted. If file was renamed with an absolute path, don't prepend the + extract-to path. + ---------------------------------------------------------------------------*/ + +/* GRR: for VMS and TOPS-20, add up to 13 to strlen */ + + if (FUNCTION == INIT) { + Trace((stderr, "initializing buildpath to ")); + if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1)) + == (char *)NULL) + return MPN_NOMEM; + if ((rootlen > 0) && !renamed_fullpath) { + strcpy(buildpath, rootpath); + end = buildpath + rootlen; + } else { + *buildpath = '\0'; + end = buildpath; + } + Trace((stderr, "[%s]\n", FnFilter1(buildpath))); + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + ROOT: if appropriate, store the path in rootpath and create it if + necessary; else assume it's a zipfile member and return. This path + segment gets used in extracting all members from every zipfile specified + on the command line. + ---------------------------------------------------------------------------*/ + +#if (!defined(SFX) || defined(SFX_EXDIR)) + if (FUNCTION == ROOT) { + Trace((stderr, "initializing root path to [%s]\n", + FnFilter1(pathcomp))); + if (pathcomp == (char *)NULL) { + rootlen = 0; + return MPN_OK; + } + if (rootlen > 0) /* rootpath was already set, nothing to do */ + return MPN_OK; + if ((rootlen = strlen(pathcomp)) > 0) { + char *tmproot; + + if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) { + rootlen = 0; + return MPN_NOMEM; + } + strcpy(tmproot, pathcomp); + if (tmproot[rootlen-1] == '.') { /****** was '/' ********/ + tmproot[--rootlen] = '\0'; + } + if (rootlen > 0 && (SSTAT(tmproot, &G.statbuf) || + !S_ISDIR(G.statbuf.st_mode))) + { /* path does not exist */ + if (!G.create_dirs /* || isshexp(tmproot) */ ) { + free(tmproot); + rootlen = 0; + /* skip (or treat as stored file) */ + return MPN_INF_SKIP; + } + /* create the directory (could add loop here scanning tmproot + * to create more than one level, but why really necessary?) */ + if (mkdir(tmproot, 0777) == -1) { + Info(slide, 1, ((char *)slide, + "checkdir: cannot create extraction directory: %s\n", + FnFilter1(tmproot))); + free(tmproot); + rootlen = 0; + /* path didn't exist, tried to create, and failed: */ + /* file exists, or 2+ subdir levels required */ + return MPN_ERR_SKIP; + } + } + tmproot[rootlen++] = '.'; /*********** was '/' *************/ + tmproot[rootlen] = '\0'; + if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { + free(tmproot); + rootlen = 0; + return MPN_NOMEM; + } + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath))); + } + return MPN_OK; + } +#endif /* !SFX || SFX_EXDIR */ + +/*--------------------------------------------------------------------------- + END: free rootpath, immediately prior to program exit. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == END) { + Trace((stderr, "freeing rootpath\n")); + if (rootlen > 0) { + free(rootpath); + rootlen = 0; + } + return MPN_OK; + } + + return MPN_INVALID; /* should never reach */ + +} /* end function checkdir() */ + + + + + +/********************/ +/* Function mkdir() */ +/********************/ + +int mkdir(path, mode) + const char *path; + int mode; /* ignored */ +/* + * returns: 0 - successful + * -1 - failed (errno not set, however) + */ +{ + return (SWI_OS_File_8((char *)path) == NULL)? 0 : -1; +} + + + + +/*********************************/ +/* extra_field-related functions */ +/*********************************/ + +static void setRISCOSexfield(ZCONST char *path, ZCONST void *ef_spark) +{ + if (ef_spark!=NULL) { + extra_block *block=(extra_block *)ef_spark; + SWI_OS_File_1((char *)path,block->loadaddr,block->execaddr,block->attr); + } +} + +#ifdef DEBUG +static void printRISCOSexfield(int isdir, ZCONST void *extra_field) +{ + extra_block *block=(extra_block *)extra_field; + printf("\n This file has RISC OS file informations in the local extra field.\n"); + + if (isdir) { +/* I prefer not to print this string... should change later... */ +/* printf(" The file is a directory.\n");*/ + } else if ((block->loadaddr & 0xFFF00000) != 0xFFF00000) { + printf(" Load address: %.8X\n",block->loadaddr); + printf(" Exec address: %.8X\n",block->execaddr); + } else { + /************* should change this to use OS_FSControl 18 to get filetype string ************/ + char tmpstr[16]; + char ftypestr[32]; + int flen; + sprintf(tmpstr,"File$Type_%03x",(block->loadaddr & 0x000FFF00) >> 8); + if (SWI_OS_ReadVarVal(tmpstr,ftypestr,32,&flen)==NULL) { + ftypestr[flen]=0; + printf(" Filetype: %s (&%.3X)\n",ftypestr,(block->loadaddr & 0x000FFF00) >> 8); + } else { + printf(" Filetype: &%.3X\n",(block->loadaddr & 0x000FFF00) >> 8); + } + } + printf(" Access: "); + if (block->attr & (1<<3)) + printf("L"); + if (block->attr & (1<<0)) + printf("W"); + if (block->attr & (1<<1)) + printf("R"); + printf("/"); + if (block->attr & (1<<4)) + printf("w"); + if (block->attr & (1<<5)) + printf("r"); + printf("\n\n"); +} +#endif /* DEBUG */ + + +/**********************************************/ +/* internal help function for time conversion */ +/**********************************************/ +static int uxtime2acornftime(unsigned *pexadr, unsigned *pldadr, time_t ut) +{ + unsigned timlo; /* 3 lower bytes of acorn file-time plus carry byte */ + unsigned timhi; /* 2 high bytes of acorn file-time */ + + timlo = ((unsigned)ut & 0x00ffffffU) * 100 + 0x00996a00U; + timhi = ((unsigned)ut >> 24); + timhi = timhi * 100 + 0x0000336eU + (timlo >> 24); + if (timhi & 0xffff0000U) + return 1; /* calculation overflow, do not change time */ + + /* insert the five time bytes into loadaddr and execaddr variables */ + *pexadr = (timlo & 0x00ffffffU) | ((timhi & 0x000000ffU) << 24); + *pldadr = (*pldadr & 0xffffff00U) | ((timhi >> 8) & 0x000000ffU); + + return 0; /* subject to future extension to signal overflow */ +} + + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) + __GDEF +{ + zvoid *spark_ef; + + fclose(G.outfile); + + if ((spark_ef = getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) + != NULL) { + setRISCOSexfield(G.filename, spark_ef); + } else { + unsigned int loadaddr, execaddr; + int attr; + int mode=G.pInfo->file_attr&0xffff; /* chmod equivalent mode */ + + time_t m_time; +#ifdef USE_EF_UT_TIME + iztimes z_utime; +#endif + + /* skip restoring time stamps on user's request */ + if (uO.D_flag <= 1) { +#ifdef USE_EF_UT_TIME + if (G.extra_field && +#ifdef IZ_CHECK_TZ + G.tz_is_valid && +#endif + (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, + G.lrec.last_mod_dos_datetime, &z_utime, NULL) + & EB_UT_FL_MTIME)) + { + TTrace((stderr, "close_outfile: Unix e.f. modif. time = %ld\n", + z_utime.mtime)); + m_time = z_utime.mtime; + } else +#endif /* USE_EF_UT_TIME */ + m_time = dos_to_unix_time(G.lrec.last_mod_dos_datetime); + } + + /* set the file's time-stamp and attributes */ + SWI_OS_File_5(G.filename, NULL, &loadaddr, NULL, NULL, &attr); + + if (uO.D_flag <= 1) + /* set the file's modification time */ + uxtime2acornftime(&execaddr, &loadaddr, m_time); + + loadaddr = (loadaddr & 0xfff000ffU) | + ((G.pInfo->file_attr&0xfff00000) >> 12); + + attr=(attr&0xffffff00) | ((mode&0400) >> 8) | ((mode&0200) >> 6) | + ((mode&0004) << 2) | ((mode&0002) << 4); + + SWI_OS_File_1(G.filename, loadaddr, execaddr, attr); + } + +} /* end function close_outfile() */ + + + + +#ifdef TIMESTAMP + +/***************************/ +/* Function stamp_file() */ +/***************************/ + +int stamp_file(fname, modtime) + ZCONST char *fname; + time_t modtime; +{ + unsigned int loadaddr, execaddr; + int attr; + + /* set the file's modification time */ + if (SWI_OS_File_5((char *)fname, NULL, &loadaddr, NULL, NULL, &attr) + != NULL) + return -1; + + if (uxtime2acornftime(&execaddr, &loadaddr, modtime) != 0) + return -1; + + return (SWI_OS_File_1((char *)fname, loadaddr, execaddr, attr) == NULL) ? + 0 : -1; + +} /* end function stamp_file() */ + +#endif /* TIMESTAMP */ + + + + +#ifndef SFX + +/************************/ +/* Function version() */ +/************************/ + +void version(__G) + __GDEF +{ + sprintf((char *)slide, LoadFarString(CompiledWith), +#ifdef __GNUC__ + "gcc ", __VERSION__, +#else +# ifdef __CC_NORCROFT + "Norcroft ", "cc", +# else + "cc", "", +# endif +#endif + + "RISC OS", + + " (Acorn Computers Ltd)", + +#ifdef __DATE__ + " on ", __DATE__ +#else + "", "" +#endif + ); + + (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0); + +} /* end function version() */ + +#endif /* !SFX */ diff --git a/acorn/makefile b/acorn/makefile new file mode 100644 index 0000000..bdda29d --- /dev/null +++ b/acorn/makefile @@ -0,0 +1,128 @@ +# Makefile for UnZip, UnZipSFX, ZipInfo and fUnZip (5.53 or later) +# last modified: 25 Dec 2006 + +# add -g to CC to debug +# add -d to BIND to debug +CC = cc +BIND = link +AS = $(CC) -c +ASM = objasm +SQUEEZE = squeeze -v +E = + +# flags +# CFLAGS flags for C compile +# LFLAGS1 flags after output file spec, before obj file list +# LFLAGS2 flags after obj file list (libraries, etc) +# +LIB = +CBASE = -throwback -wn -DNO_STRNICMP +CFLAGS = $(CBASE) -IC:,@. +ASMFLAGS = -Throwback -Stamp -NoCache -CloseExec -quit +LFLAGS1 = +LFLAGS2 = $(LIB) C:o.Stubs + +# object file lists +OBJS1 = unzip.o crc32.o crypt.o envargs.o explode.o +OBJS2 = extract.o fileio.o globals.o inflate.o list.o match.o +OBJS3 = process.o ttyio.o ubz2err.o unreduce.o unshrink.o zipinfo.o +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) riscos.o swiven.o acorn.o +OBJF = funzip.o crc32.o cryptf.o globalsf.o inflatef.o ttyiof.o \ + riscos.o swiven.o +OBJX = unzipsfx.o crc32.o crypt_.o extract_.o fileio_.o globals.o \ + inflate.o match.o process_.o ttyio.o ubz2err_.o \ + acorn_.o swiven.o riscos_.o + +UNZIP_H = unzip.h unzpriv.h globals.h acorn/riscos.h acorn/swiven.h + +all: unzip funzip unzipsfx + + +install: unzip funzip unzipsfx + $(SQUEEZE) unzip %.unzip + $(SQUEEZE) funzip %.funzip + $(SQUEEZE) unzipsfx unzipsfx + copy %.unzip %.zipinfo ~CVF + +# suffix rules +.SUFFIXES: .o .c +.c.o: + $(CC) $(CFLAGS) -c $< +.s.o: + $(ASM) $(ASMFLAGS) -from @*.s -to @*.o + +# rules for unzip and funzip +crc32.o: crc32.c $(UNZIP_H) zip.h crc32.h +crypt.o: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +envargs.o: envargs.c $(UNZIP_H) +explode.o: explode.c $(UNZIP_H) +extract.o: extract.c $(UNZIP_H) crc32.h crypt.h +fileio.o: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +funzip.o: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h +globals.o: globals.c $(UNZIP_H) +inflate.o: inflate.c inflate.h $(UNZIP_H) +list.o: list.c $(UNZIP_H) +match.o: match.c $(UNZIP_H) +process.o: process.c $(UNZIP_H) crc32.h +ttyio.o: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ubz2err.o: ubz2err.c $(UNZIP_H) +unreduce.o: unreduce.c $(UNZIP_H) +unshrink.o: unshrink.c $(UNZIP_H) +unzip.o: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +zipinfo.o: zipinfo.c $(UNZIP_H) + +crypt_.o: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CC) $(CFLAGS) -DSFX -c c.crypt -o o.crypt_ +extract_.o: extract.c $(UNZIP_H) crc32.h crypt.h + $(CC) $(CFLAGS) -DSFX -c c.extract -o o.extract_ +fileio_.o: fileio.c $(UNZIP_H) crc32.h crypt.h + $(CC) $(CFLAGS) -DSFX -c c.fileio -o o.fileio_ +globals_.o: globals.c $(UNZIP_H) + $(CC) $(CFLAGS) -DFUNZIP -c c.globals -o o.globals_ +inflate_.o: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CC) $(CFLAGS) -DFUNZIP -c c.inflate -o o.inflate_ +process_.o: process.c $(UNZIP_H) crc32.h + $(CC) $(CFLAGS) -DSFX -c c.process -o o.process_ +ttyio_.o: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CC) $(CFLAGS) -DFUNZIP -c c.ttyio -o o.ttyio_ +ubz2err_.o: ubz2err.c $(UNZIP_H) + $(CC) $(CFLAGS) -DSFX -c c.ubz2err -o o.ubz2err_ + +unzipsfx.o: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h + $(CC) $(CFLAGS) -DSFX -c c.unzip -o o.unzipsfx + +o.cryptf: c.crypt $(UNZIP_H) h.zip h.crypt h.crc32 h.ttyio + $(CC) $(CFLAGS) -DFUNZIP -c c.crypt -o o.cryptf +o.globalsf: c.globals $(UNZIP_H) + $(CC) $(CFLAGS) -DFUNZIP -c c.globals -o o.globalsf +o.inflatef: c.inflate h.inflate $(UNZIP_H) h.crypt + $(CC) $(CFLAGS) -DFUNZIP -c c.inflate -o o.inflatef +o.ttyiof: c.ttyio $(UNZIP_H) h.zip h.crypt h.ttyio + $(CC) $(CFLAGS) -DFUNZIP -c c.ttyio -o o.ttyiof + +acorn.o: acorn/acorn.c $(UNZIP_H) + $(CC) $(CFLAGS) -c acorn/acorn.c +acorn_.o: acorn/acorn.c $(UNZIP_H) + $(CC) $(CFLAGS) -c -DSFX -DSFX_EXDIR -o acorn_.o acorn/acorn.c + +riscos.o: acorn/riscos.c $(UNZIP_H) + $(CC) $(CFLAGS) -c acorn/riscos.c +riscos_.o: acorn/riscos.c $(UNZIP_H) + $(CC) $(CFLAGS) -c -DSFX -DSFX_EXDIR -o riscos_.o acorn/riscos.c + +swiven.o: acorn/swiven.s + $(ASM) $(ASMFLAGS) -from acorn.s.swiven -to o.swiven + +unzip: $(OBJS) + $(BIND) -o unzip$(E) $(LFLAGS1) $(OBJS) $(LFLAGS2) +funzip: $(OBJF) + $(BIND) -o funzip$(E) $(LFLAGS1) $(OBJF) $(LFLAGS2) +unzipsfx: $(OBJX) + $(BIND) -o unzipsfx$(E) $(LFLAGS1) $(OBJX) $(LFLAGS2) + +clean: ;remove unzip; remove funzip; + remove zipinfo; remove unzipsfx; + create o.!fake! 0 + wipe o.* ~cf + +# end of Makefile diff --git a/acorn/riscos.c b/acorn/riscos.c new file mode 100644 index 0000000..c640083 --- /dev/null +++ b/acorn/riscos.c @@ -0,0 +1,364 @@ +/* + 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 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 +*/ +/* riscos.c */ + +#include +#include +#include + +/* #define NO_UNZIPH_STUFF */ +#define UNZIP_INTERNAL +#include "unzip.h" +#include "riscos.h" + +#define MAXEXT 16 + +char *exts2swap = NULL; /* Extensions to swap (actually, directory names) */ + +int stat(char *filename,struct stat *res) +{ + int attr; /* object attributes */ + unsigned int load; /* load address */ + unsigned int exec; /* exec address */ + int type; /* type: 0 not found, 1 file, 2 dir, 3 image */ + + if (!res) + return -1; + + if (SWI_OS_File_5(filename,&type,&load,&exec,(int *)&res->st_size,&attr)!=NULL) + return -1; + + if (type==0) + return -1; + + res->st_dev=0; + res->st_ino=0; + res->st_nlink=0; + res->st_uid=1; + res->st_gid=1; + res->st_rdev=0; + res->st_blksize=1024; + + res->st_mode = ((attr & 0001) << 8) | ((attr & 0002) << 6) | + ((attr & 0020) >> 2) | ((attr & 0040) >> 4); + + switch (type) { + case 1: /* File */ + res->st_mode |= S_IFREG; + break; + case 2: /* Directory */ + res->st_mode |= S_IFDIR | 0700; + break; + case 3: /* Image file */ + if (uO.scanimage) + res->st_mode |= S_IFDIR | 0700; + else + res->st_mode |= S_IFREG; + break; + } + + if ((((unsigned int) load) >> 20) == 0xfff) { /* date stamped file */ + register unsigned int t1, t2, tc; + + t1 = (unsigned int) (exec); + t2 = (unsigned int) (load & 0xff); + + tc = 0x6e996a00U; + if (t1 < tc) + t2--; + t1 -= tc; + t2 -= 0x33; /* 00:00:00 Jan. 1 1970 = 0x336e996a00 */ + + t1 = (t1 / 100) + (t2 * 42949673U); /* 0x100000000 / 100 = 42949672.96 */ + t1 -= (t2 / 25); /* compensate for .04 error */ + + res->st_atime = res->st_mtime = res->st_ctime = t1; + } + else + res->st_atime = res->st_mtime = res->st_ctime = 0; + + return 0; +} + +#ifndef SFX + +DIR *opendir(char *dirname) +{ + DIR *thisdir; + int type; + int attr; + os_error *er; + + thisdir=(DIR *)malloc(sizeof(DIR)); + if (thisdir==NULL) + return NULL; + + thisdir->dirname=(char *)malloc(strlen(dirname)+1); + if (thisdir->dirname==NULL) { + free(thisdir); + return NULL; + } + + strcpy(thisdir->dirname,dirname); + if (thisdir->dirname[strlen(thisdir->dirname)-1]=='.') + thisdir->dirname[strlen(thisdir->dirname)-1]=0; + + if (er=SWI_OS_File_5(thisdir->dirname,&type,NULL,NULL,NULL,&attr),er!=NULL || + type<=1 || (type==3 && !uO.scanimage)) + { + free(thisdir->dirname); + free(thisdir); + return NULL; + } + + thisdir->buf=malloc(DIR_BUFSIZE); + if (thisdir->buf==NULL) { + free(thisdir->dirname); + free(thisdir); + return NULL; + } + + thisdir->size=DIR_BUFSIZE; + thisdir->offset=0; + thisdir->read=0; + + return thisdir; +} + +struct dirent *readdir(DIR *d) +{ + static struct dirent dent; + + if (d->read==0) { /* no more objects read in the buffer */ + if (d->offset==-1) { /* no more objects to read */ + return NULL; + } + + d->read=255; + if (SWI_OS_GBPB_9(d->dirname,d->buf,&d->read,&d->offset,DIR_BUFSIZE,NULL)!=NULL) + return NULL; + + if (d->read==0) { + d->offset=-1; + return NULL; + } + d->read--; + d->act=(char *)d->buf; + } + else { /* some object is ready in buffer */ + d->read--; + d->act=(char *)(d->act+strlen(d->act)+1); + } + + strcpy(dent.d_name,d->act); + dent.d_namlen=strlen(dent.d_name); + + /* If we're returning the last item, check if there are any more. + * If there are, nothing will happen; if not, then d->offset = -1 */ + if (!d->read) + SWI_OS_GBPB_9(d->dirname,d->buf,&d->read,&d->offset,0,NULL); + + return &dent; +} + +void closedir(DIR *d) +{ + if (d->buf!=NULL) + free(d->buf); + if (d->dirname!=NULL) + free(d->dirname); + free(d); +} + +int unlink(f) +char *f; /* file to delete */ +/* Delete the file *f, returning non-zero on failure. */ +{ + os_error *er; + char canon[256]; + int size=255; + + er=SWI_OS_FSControl_37(f,canon,&size); + if (er==NULL) { + er=SWI_OS_FSControl_27(canon,0x100); + } + else { + er=SWI_OS_FSControl_27(f,0x100); + } + return (int)er; +} + +int rmdir(char *d) +{ + int objtype; + char *s; + int len; + + len = strlen(d); + if ((s = malloc(len + 1)) == NULL) + return -1; + + strcpy(s,d); + if (s[len-1]=='.') + s[len-1]=0; + + if (SWI_OS_File_5(s,&objtype,NULL,NULL,NULL,NULL)!=NULL) { + free(s); + return -1; + } + if (objtype<2 || (!uO.scanimage && objtype==3)) { +/* this is a file or it doesn't exist */ + free(s); + return -1; + } + if (SWI_OS_File_6(s)!=NULL) { + free(s); + return -1; + } + free(s); + return 0; +} + +#endif /* !SFX */ + +int chmod(char *file, int mode) +{ +/*************** NOT YET IMPLEMENTED!!!!!! ******************/ +/* I don't know if this will be needed or not... */ + file=file; + mode=mode; + return 0; +} + +void setfiletype(char *fname,int ftype) +{ + char str[256]; + sprintf(str,"SetType %s &%3.3X",fname,ftype); + SWI_OS_CLI(str); +} + +void getRISCOSexts(char *envstr) +{ + char *envptr; /* value returned by getenv */ + + envptr = getenv(envstr); + if (envptr == NULL || *envptr == 0) return; + + exts2swap=malloc(1+strlen(envptr)); + if (exts2swap == NULL) + return; + + strcpy(exts2swap, envptr); +} + +int checkext(char *suff) +{ + register char *extptr = exts2swap ? exts2swap : ""; + register char *suffptr; + register int e,s; + + while(*extptr) { + suffptr=suff; + e=*extptr; s=*suffptr; + while (e && e!=':' && s && s!='.' && s!='/' && e==s) { + e=*++extptr; s=*++suffptr; + } + if (e==':') e=0; + if (s=='.' || s=='/') s=0; + if (!e && !s) { + return 1; + } + while(*extptr!=':' && *extptr!='\0') /* skip to next extension */ + extptr++; + if (*extptr!='\0') + extptr++; + } + return 0; +} + +void swapext(char *name, char *exptr) +{ + char ext[MAXEXT]; + register char *p1=exptr+1; + register char *p2=ext; + int extchar=*exptr; + + while(*p1 && *p1!='.' && *p1!='/') + *p2++=*p1++; + *p2=0; + p2=exptr-1; + p1--; + while(p2 >= name) + *p1--=*p2--; + p1=name; + p2=ext; + while(*p2) + *p1++=*p2++; + *p1=(extchar=='/'?'.':'/'); +} + +void remove_prefix(void) +{ + SWI_DDEUtils_Prefix(NULL); +} + +void set_prefix(void) +{ + char *pref; + int size=0; + + if (SWI_OS_FSControl_37("@",pref,&size)!=NULL) + return; + + size=1-size; + + if (pref=malloc(size),pref!=NULL) { + if (SWI_OS_FSControl_37("@",pref,&size)!=NULL) { + free(pref); + return; + } + + if (SWI_DDEUtils_Prefix(pref)==NULL) { + atexit(remove_prefix); + } + + free(pref); + } +} + +#ifdef localtime +# undef localtime +#endif + +#ifdef gmtime +# undef gmtime +#endif + +/* Acorn's implementation of localtime() and gmtime() + * doesn't consider the timezone offset, so we have to + * add it before calling the library functions + */ + +struct tm *riscos_localtime(const time_t *timer) +{ + time_t localt=*timer; + + localt+=SWI_Read_Timezone()/100; + + return localtime(&localt); +} + +struct tm *riscos_gmtime(const time_t *timer) +{ + time_t localt=*timer; + + localt+=SWI_Read_Timezone()/100; + + return gmtime(&localt); +} diff --git a/acorn/riscos.h b/acorn/riscos.h new file mode 100644 index 0000000..6aa8c33 --- /dev/null +++ b/acorn/riscos.h @@ -0,0 +1,136 @@ +/* + 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 +*/ +/* riscos.h */ + +#ifndef __riscos_h +#define __riscos_h + +#include + +typedef struct { + int errnum; + char errmess[252]; +} os_error; + +#ifndef __swiven_h +# include "swiven.h" +#endif + +#define MAXPATHLEN 256 +#define MAXFILENAMELEN 64 /* should be 11 for ADFS, 13 for DOS, 64 seems a sensible value... */ +#define DIR_BUFSIZE 1024 /* this should be enough to read a whole E-Format directory */ + +struct stat { + unsigned int st_dev; + int st_ino; + unsigned int st_mode; + int st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned int st_rdev; + unsigned int st_size; + unsigned int st_blksize; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +}; + +typedef struct { + char *dirname; + void *buf; + int size; + char *act; + int offset; + int read; +} DIR; + + +struct dirent { + unsigned int d_off; /* offset of next disk directory entry */ + int d_fileno; /* file number of entry */ + size_t d_reclen; /* length of this record */ + size_t d_namlen; /* length of d_name */ + char d_name[MAXFILENAMELEN]; /* name */ +}; + +typedef struct { + unsigned int load_addr; + unsigned int exec_addr; + int lenght; + int attrib; + int objtype; + char name[13]; +} riscos_direntry; + +typedef struct { + short ID; + short size; + int ID_2; + unsigned int loadaddr; + unsigned int execaddr; + int attr; + int zero; +} extra_block; + + +#define S_IFMT 0770000 + +#define S_IFDIR 0040000 +#define S_IFREG 0100000 /* 0200000 in UnixLib !?!?!?!? */ + +#ifndef S_IEXEC +# define S_IEXEC 0000100 +# define S_IWRITE 0000200 +# define S_IREAD 0000400 +#endif + +#ifndef NO_UNZIPH_STUFF +# include +# if (!defined(HAVE_STRNICMP) & !defined(NO_STRNICMP)) +# define NO_STRNICMP +# endif +# ifndef DATE_FORMAT +# define DATE_FORMAT DF_DMY +# endif +# define lenEOL 1 +# define PutNativeEOL *q++ = native(LF); +# define USE_STRM_INPUT +# define USE_FWRITE +# define PIPE_ERROR (errno == 9999) /* always false */ +# define isatty(x) (TRUE) /* used in funzip.c to find if stdin redirected: + should find a better way, now just work as if stdin never redirected */ +# define USE_EF_UT_TIME +# if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) +# define TIMESTAMP +# endif +# define localtime riscos_localtime +# define gmtime riscos_gmtime +#endif /* !NO_UNZIPH_STUFF */ + +#define _raw_getc() SWI_OS_ReadC() + +extern char *exts2swap; /* Extensions to swap */ + +int stat(char *filename,struct stat *res); +DIR *opendir(char *dirname); +struct dirent *readdir(DIR *d); +void closedir(DIR *d); +int unlink(char *f); +int rmdir(char *d); +int chmod(char *file, int mode); +void setfiletype(char *fname,int ftype); +void getRISCOSexts(char *envstr); +int checkext(char *suff); +void swapext(char *name, char *exptr); +void remove_prefix(void); +void set_prefix(void); +struct tm *riscos_localtime(const time_t *timer); +struct tm *riscos_gmtime(const time_t *timer); + +#endif /* !__riscos_h */ diff --git a/acorn/srcrename b/acorn/srcrename new file mode 100644 index 0000000..936a408 Binary files /dev/null and b/acorn/srcrename differ diff --git a/acorn/swiven.h b/acorn/swiven.h new file mode 100644 index 0000000..1136aa3 --- /dev/null +++ b/acorn/swiven.h @@ -0,0 +1,69 @@ +/* + 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 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 +*/ +/* swiven.h */ + +#ifndef __swiven_h +#define __swiven_h + +os_error *SWI_OS_FSControl_26(char *source, char *dest, int actionmask); +/* copy */ + +os_error *SWI_OS_FSControl_27(char *filename, int actionmask); +/* wipe */ + +os_error *SWI_OS_GBPB_9(char *dirname, void *buf, int *number, + int *offset, int size, char *match); +/* read dir */ + +os_error *SWI_OS_File_1(char *filename, unsigned int loadaddr, + unsigned int execaddr, int attrib); +/* write file attributes */ + +os_error *SWI_OS_File_5(char *filename, int *objtype, unsigned int *loadaddr, + unsigned int *execaddr, int *length, int *attrib); +/* read file info */ + +os_error *SWI_OS_File_6(char *filename); +/* delete */ + +os_error *SWI_OS_File_7(char *filename, int loadaddr, int execaddr, int size); +/* create an empty file */ + +os_error *SWI_OS_File_8(char *dirname); +/* create a directory */ + +os_error *SWI_OS_File_18(char *filename, int filetype); +/* set a file's type */ + +os_error *SWI_OS_CLI(char *cmd); +/* execute a command */ + +int SWI_OS_ReadC(void); +/* get a key from the keyboard buffer */ + +os_error *SWI_OS_ReadVarVal(char *var, char *buf, int len, int *bytesused); +/* reads an OS varibale */ + +os_error *SWI_OS_FSControl_54(char *buffer, int dir, char *fsname, int *size); +/* reads the path of a specified directory */ + +os_error *SWI_OS_FSControl_37(char *pathname, char *buffer, int *size); +/* canonicalise path */ + +os_error *SWI_DDEUtils_Prefix(char *dir); +/* sets the 'prefix' directory */ + +int SWI_Read_Timezone(void); +/* returns the timezone offset (centiseconds) */ + +int SWI_MimeMap_Translate(const char *ext); +/* given a filename extn, returns the filetype (or -1 if no match). + * Uses the MimeMap module */ + +#endif /* !__swiven_h */ diff --git a/acorn/swiven.s b/acorn/swiven.s new file mode 100644 index 0000000..da55ba8 --- /dev/null +++ b/acorn/swiven.s @@ -0,0 +1,316 @@ +;=========================================================================== +; 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 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 +;=========================================================================== +; SWI veneers used by Zip/Unzip +; + +r0 RN 0 +r1 RN 1 +r2 RN 2 +r3 RN 3 +r4 RN 4 +r5 RN 5 +r6 RN 6 +r7 RN 7 +r8 RN 8 +r9 RN 9 +r10 RN 10 +r11 RN 11 +r12 RN 12 +sp RN 13 +lr RN 14 +pc RN 15 + +sl RN 10 +fp RN 11 +ip RN 12 + + +XOS_Bit EQU &020000 + +OS_GBPB EQU &00000C +OS_File EQU &000008 +OS_FSControl EQU &000029 +OS_CLI EQU &000005 +OS_ReadC EQU &000004 +OS_ReadVarVal EQU &000023 +DDEUtils_Prefix EQU &042580 +Territory_ReadCurrentTimeZone EQU &043048 +MimeMap_Translate EQU &050B00 + + MACRO + STARTCODE $name + EXPORT $name +$name + MEND + + + AREA |C$$code|, CODE, READONLY + +; os_error *SWI_OS_FSControl_26(char *source, char *dest, int actionmask); + + STARTCODE SWI_OS_FSControl_26 + + MOV ip, lr + + MOV r3, r2 + MOV r2, r1 + MOV r1, r0 + MOV r0, #26 + + SWI OS_FSControl + XOS_Bit + + MOVVC r0, #0 + + MOVS pc, ip + + +; os_error *SWI_OS_FSControl_27(char *filename, int actionmask); + + STARTCODE SWI_OS_FSControl_27 + + MOV ip, lr + + MOV r3, r1 + MOV r1, r0 + MOV r0, #27 + + SWI OS_FSControl + XOS_Bit + + MOVVC r0, #0 + + MOVS pc, ip + + +; os_error *SWI_OS_GBPB_9(char *dirname, void *buf, int *number, +; int *offset, int size, char *match); + + STARTCODE SWI_OS_GBPB_9 + + MOV ip, sp + STMFD sp!, {r2-r6,lr} + LDMIA ip, {r5,r6} + LDR r4, [r3] + LDR r3, [r2] + MOV r2, r1 + MOV r1, r0 + MOV r0, #9 + SWI OS_GBPB + XOS_Bit + LDMVSFD sp!, {r2-r6,pc}^ + MOV r0, #0 + LDMFD sp, {r5,r6} + STR r3, [r5] + STR r4, [r6] + LDMFD sp!, {r2-r6,pc}^ + + +; os_error *SWI_OS_File_1(char *filename, int loadaddr, int execaddr, int attrib); + + STARTCODE SWI_OS_File_1 + + STMFD sp!, {r5,lr} + MOV r5, r3 + MOV r3, r2 + MOV r2, r1 + MOV r1, r0 + MOV r0, #1 + SWI OS_File + XOS_Bit + MOVVC r0, #0 + LDMFD sp!, {r5,pc}^ + + + +; os_error *SWI_OS_File_5(char *filename, int *objtype, int *loadaddr, +; int *execaddr, int *length, int *attrib); + + STARTCODE SWI_OS_File_5 + + STMFD sp!, {r1-r5,lr} + MOV r1, r0 + MOV r0, #5 + SWI OS_File + XOS_Bit + LDMVSFD sp!, {r1-r5,pc}^ + LDR lr, [sp] + TEQ lr, #0 + STRNE r0, [lr] + LDR lr, [sp, #4] + TEQ lr ,#0 + STRNE r2, [lr] + LDR lr, [sp, #8] + TEQ lr, #0 + STRNE r3, [lr] + LDR lr, [sp ,#24] + TEQ lr, #0 + STRNE r4, [lr] + LDR lr, [sp ,#28] + TEQ lr, #0 + STRNE r5, [lr] + MOV r0, #0 + LDMFD sp!, {r1-r5,pc}^ + + +; os_error *SWI_OS_File_6(char *filename); + + STARTCODE SWI_OS_File_6 + + STMFD sp!, {r4-r5,lr} + MOV r1, r0 + MOV r0, #6 + SWI OS_File + XOS_Bit + MOVVC r0, #0 + LDMFD sp!, {r4-r5,pc}^ + + +; os_error *SWI_OS_File_7(char *filename, int loadaddr, int execaddr, int size); + + STARTCODE SWI_OS_File_7 + + STMFD sp!, {r4-r5,lr} + MOV r5, r3 + MOV r4, #0 + MOV r3, r2 + MOV r2, r1 + MOV r1, r0 + MOV r0, #7 + SWI OS_File + XOS_Bit + MOVVC r0, #0 + LDMFD sp!, {r4-r5,pc}^ + + +; os_error *SWI_OS_File_8(char *dirname); + + STARTCODE SWI_OS_File_8 + + STMFD sp!, {r4,lr} + MOV r1, r0 + MOV r4, #0 + MOV r0, #8 + SWI OS_File + XOS_Bit + MOVVC r0, #0 + LDMFD sp!, {r4,pc}^ + + +; os_error *SWI_OS_File_18(char *filename, int filetype); + + STARTCODE SWI_OS_File_18 + + STMFD sp!, {r4-r5,lr} + MOV r2, r1 + MOV r1, r0 + MOV r0, #18 + SWI OS_File + XOS_Bit + MOVVC r0, #0 + LDMFD sp!, {r4-r5,pc}^ + + +; os_error *SWI_OS_CLI(char *cmd); + + STARTCODE SWI_OS_CLI + + MOV ip, lr + SWI OS_CLI + XOS_Bit + MOVVC r0, #0 + MOVS pc, ip + + +; int SWI_OS_ReadC(void); + + STARTCODE SWI_OS_ReadC + + MOV ip, lr + SWI OS_ReadC + XOS_Bit + MOVS pc, ip + + +; os_error *SWI_OS_ReadVarVal(char *var, char *buf, int len, int *bytesused); + + STARTCODE SWI_OS_ReadVarVal + + STMFD sp!, {r4,lr} + MOV ip, r3 + MOV r3, #0 + MOV r4, #0 + SWI OS_ReadVarVal + XOS_Bit + LDMVSFD sp!, {r4,pc}^ + TEQ ip, #0 + STRNE r2, [ip] + MOV r0, #0 + LDMFD sp!, {r4,pc}^ + + +; os_error *SWI_OS_FSControl_54(char *buffer, int dir, char *fsname, int *size); + + STARTCODE SWI_OS_FSControl_54 + + STMFD sp!, {r3-r6,lr} + LDR r5, [r3] + MOV r3, r2 + MOV r2, r1 + MOV r1, r0 + MOV r0, #54 + SWI OS_FSControl + XOS_Bit + LDMVSFD sp!, {r3-r6,pc}^ + MOV r0, #0 + LDMFD sp!, {r3} + STR r5, [r3] + LDMFD sp!, {r4-r6,pc}^ + + +; os_error *SWI_OS_FSControl_37(char *pathname, char *buffer, int *size); + + STARTCODE SWI_OS_FSControl_37 + + STMFD sp!, {r2,r3-r5,lr} + LDR r5, [r2] + MOV r3, #0 + MOV r4, #0 + MOV r2, r1 + MOV r1, r0 + MOV r0, #37 + SWI OS_FSControl + XOS_Bit + LDMVSFD sp!, {r2,r3-r5,pc}^ + MOV r0, #0 + LDMFD sp!, {r2} + STR r5, [r2] + LDMFD sp!, {r3-r5,pc}^ + + +; os_error *SWI_DDEUtils_Prefix(char *dir); + + STARTCODE SWI_DDEUtils_Prefix + + MOV ip, lr + SWI DDEUtils_Prefix + XOS_Bit + MOVVC r0, #0 + MOVS pc, ip + +; int SWI_Read_Timezone(void); + + STARTCODE SWI_Read_Timezone + + MOV ip, lr + SWI Territory_ReadCurrentTimeZone + XOS_Bit + MOVVC r0, r1 + MOVVS r0, #0 + MOVS pc, ip + + +; int SWI_MimeMap_Translate(char *ext); + + STARTCODE SWI_MimeMap_Translate + MOV ip,lr + MOV r1, r0 + MOV r0, #3 + MOV r2, #0 + SWI MimeMap_Translate + XOS_Bit + MOVVC r0, r3 + MVNVS r0, #0 ; return -1 on error + MOVS pc, ip + + + END diff --git a/amiga/Contents b/amiga/Contents new file mode 100644 index 0000000..90b7e0e --- /dev/null +++ b/amiga/Contents @@ -0,0 +1,32 @@ +Contents of the "amiga" directory for UnZip 5.5 and later: + + Contents this file + amiga.c Amiga-specific file I/O routines + amiga.h Amiga-specific header file + filedate.c SetFileDate clone for OS 1.3, and other low-level resources + + smakefile SAS/C makefile for UnZip, fUnZip, and UnZipSFX + + makefile.azt Aztec C makefile for UnZip, fUnZip, and UnZipSFX + stat.c stat() emulation for Aztec, along with opendir()/readdir()/etc + z-stat.h replacement stat.h header file for use with stat.c + crc_68.a assembler version of crc32.c + flate.a assembler version of inflate_codes() (define ASM_INFLATECODES) + + makesfx.c source for MakeSFX, without which UnZipSFX is not usable + +Notes: + + The crc_68.a source file is not currently used by the SAS/C makefile, + nor is flate.a; as of UnZip 5.2 neither of these wants args in + registers. + + The DICE makefile has been removed since no one is supporting that + compiler anymore. + + As of UnZip 5.2, if you have AmigaDOS 2.1 or newer and have set your + timezone in the Locale preferences editor, this will be an adequate + substitute for setting TZ. If you do not set TZ to your current timezone, + files will be restored with times corrsponding to "EST5EDT", U.S. Eastern + time. See ../proginfo/timezone.txt for directions on how to set the + TZ variable. diff --git a/amiga/amiga.c b/amiga/amiga.c new file mode 100644 index 0000000..06af5db --- /dev/null +++ b/amiga/amiga.c @@ -0,0 +1,1034 @@ +/* + Copyright (c) 1990-2007 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 +*/ +/*------------------------------------------------------------------------ + + amiga.c + + Amiga-specific routines for use with Info-ZIP's UnZip 5.1 and later. + See History.5xx for revision history. + + Contents: do_wild() + mapattr() + mapname() + checkdir() + close_outfile() + stamp_file() + _abort() (Aztec C only) + [dateformat()] (currently not used) + screensize() + version() + + ------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#ifdef AZTEC_C +# define NO_FCNTL_H +#endif +#include "unzip.h" +#include "unzvers.h" + +/* Globular varibundus -- now declared in SYSTEM_SPECIFIC_GLOBALS in amiga.h */ + +/* static int created_dir; */ /* used in mapname(), checkdir() */ +/* static int renamed_fullpath; */ /* ditto */ + +#define PERMS 0777 +#define MKDIR(path,mode) mkdir(path) + +#ifndef S_ISCRIPT /* not having one implies you have none */ +# define S_IARCHIVE 0020 /* not modified since this bit was last set */ +# define S_IREAD 0010 /* can be opened for reading */ +# define S_IWRITE 0004 /* can be opened for writing */ +# define S_IDELETE 0001 /* can be deleted */ +#endif /* S_ISCRIPT */ + +#ifndef S_IRWD +# define S_IRWD 0015 /* useful combo of Amiga privileges */ +#endif /* !S_IRWD */ + +#ifndef S_IHIDDEN +# define S_IHIDDEN 0200 /* hidden supported in future AmigaDOS (someday) */ +#endif /* !S_HIDDEN */ + +#ifndef SFX +/* Make sure the number here matches unzvers.h in the *EXACT* form */ +/* UZ_MAJORVER "." UZ_MINORVER UZ_PATCHLEVEL vvvv No non-digits! */ +const char version_id[] = "\0$VER: UnZip " UZ_VER_STRING " (" +#include "env:VersionDate" + ")\r\n"; +#endif /* SFX */ + + +static int ispattern(ZCONST char *p) +{ + register char c; + while (c = *p++) + if (c == '\\') { + if (!*++p) + return FALSE; + } else if (c == '?' || c == '*') + return TRUE; + else if (c == '[') { + for (;;) { + if (!(c = *p++)) + return FALSE; + else if (c == '\\') { + if (!*++p) + return FALSE; + } else if (c == ']') + return TRUE; + } + } + return FALSE; +} + +/**********************/ +/* Function do_wild() */ +/**********************/ + +char *do_wild(__G__ wildspec) + __GDEF + ZCONST char *wildspec; /* only used first time on a given dir */ +{ +/* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in amiga.h: + static DIR *wild_dir = NULL; + static ZCONST char *wildname; + static char *dirname, matchname[FILNAMSIZ]; + static int notfirstcall = FALSE, dirnamelen; +*/ + struct dirent *file; + BPTR lok = 0; + + /* Even when we're just returning wildspec, we *always* do so in + * matchname[]--calling routine is allowed to append four characters + * to the returned string, and wildspec may be a pointer to argv[]. + */ + if (!G.notfirstcall) { /* first call: must initialize everything */ + G.notfirstcall = TRUE; + + /* avoid needless readdir() scans: */ + if (!ispattern(wildspec) || + (lok = Lock((char *)wildspec, ACCESS_READ))) { + if (lok) UnLock(lok); /* ^^ we ignore wildcard chars if */ + G.dirnamelen = 0; /* the name matches a real file */ + strncpy(G.matchname, wildspec, FILNAMSIZ); + G.matchname[FILNAMSIZ-1] = '\0'; + return G.matchname; + } + + /* break the wildspec into a directory part and a wildcard filename */ + if ((G.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL && + (G.wildname = (ZCONST char *)strrchr(wildspec, ':')) == NULL) { + G.dirname = ""; /* current dir */ + G.dirnamelen = 0; + G.wildname = wildspec; + } else { + ++G.wildname; /* point at character after '/' or ':' */ + G.dirnamelen = G.wildname - wildspec; + if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == NULL) { + Info(slide, 1, ((char *)slide, + "warning: cannot allocate wildcard buffers\n")); + strncpy(G.matchname, wildspec, FILNAMSIZ); + G.matchname[FILNAMSIZ-1] = '\0'; + return G.matchname; /* but maybe filespec was not a wildcard */ + } + strncpy(G.dirname, wildspec, G.dirnamelen); + G.dirname[G.dirnamelen] = '\0'; + } + + if ((G.wild_dir = opendir(G.dirname)) != NULL) { + while ((file = readdir(G.wild_dir)) != NULL) { + if (match(file->d_name, G.wildname, 1 WISEP)) {/* ignore case */ + strcpy(G.matchname, G.dirname); + strcpy(G.matchname + G.dirnamelen, file->d_name); + return G.matchname; + } + } + /* if we get to here directory is exhausted, so close it */ + closedir(G.wild_dir); + G.wild_dir = NULL; + } + + /* return the raw wildspec in case that works (e.g., directory not + * searchable, but filespec was not wild and file is readable) */ + strncpy(G.matchname, wildspec, FILNAMSIZ); + G.matchname[FILNAMSIZ-1] = '\0'; + return G.matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (G.wild_dir == NULL) { + G.notfirstcall = FALSE; /* nothing left to try -- reset */ + if (G.dirnamelen > 0) + free(G.dirname); + return (char *)NULL; + } + + /* If we've gotten this far, we've read and matched at least one entry + * successfully (in a previous call), so dirname has been copied into + * matchname already. + */ + while ((file = readdir(G.wild_dir)) != NULL) + if (match(file->d_name, G.wildname, 1 WISEP)) { /* 1 == ignore case */ + /* strcpy(G.matchname, dirname); */ + strcpy(G.matchname + G.dirnamelen, file->d_name); + return G.matchname; + } + + closedir(G.wild_dir); /* have read at least one dir entry; nothing left */ + G.wild_dir = NULL; + G.notfirstcall = FALSE; /* reset for new wildspec */ + if (G.dirnamelen > 0) + free(G.dirname); + return (char *)NULL; + +} /* end function do_wild() */ + + + + +/**********************/ +/* Function mapattr() */ +/**********************/ + +int mapattr(__G) /* Amiga version */ + __GDEF +{ + ulg tmp = G.crec.external_file_attributes; + + + /* Amiga attributes = hsparwed = hidden, script, pure, archive, + * read, write, execute, delete */ + + switch (G.pInfo->hostnum) { + case AMIGA_: + if ((tmp & 1) == (tmp>>18 & 1)) + tmp ^= 0x000F0000; /* PKAZip compatibility kluge */ + /* turn off archive bit for restored Amiga files */ + G.pInfo->file_attr = (unsigned)((tmp>>16) & (~S_IARCHIVE)); + break; + + case UNIX_: /* preserve read, write, execute: use logical-OR of */ + case VMS_: /* user, group, and other; if writable, set delete bit */ + case ACORN_: + case ATARI_: + case ATHEOS_: + case BEOS_: + case QDOS_: + case TANDEM_: + { + unsigned uxattr = (unsigned)(tmp >> 16); + int r = FALSE; + + if (uxattr == 0 && G.extra_field) { + /* Some (non-Info-ZIP) implementations of Zip for Unix and + VMS (and probably others ??) leave 0 in the upper 16-bit + part of the external_file_attributes field. Instead, they + store file permission attributes in some extra field. + As a work-around, we search for the presence of one of + these extra fields and fall back to the MSDOS compatible + part of external_file_attributes if one of the known + e.f. types has been detected. + Later, we might implement extraction of the permission + bits from the VMS extra field. But for now, the work-around + should be sufficient to provide "readable" extracted files. + (For ASI Unix e.f., an experimental remap of the e.f. + mode value IS already provided!) + */ + ush ebID; + unsigned ebLen; + uch *ef = G.extra_field; + unsigned ef_len = G.crec.extra_field_length; + + while (!r && ef_len >= EB_HEADSIZE) { + ebID = makeword(ef); + ebLen = (unsigned)makeword(ef+EB_LEN); + if (ebLen > (ef_len - EB_HEADSIZE)) + /* discoverd some e.f. inconsistency! */ + break; + switch (ebID) { + case EF_ASIUNIX: + if (ebLen >= (EB_ASI_MODE+2)) { + uxattr = + (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE)); + /* force stop of loop: */ + ef_len = (ebLen + EB_HEADSIZE); + break; + } + /* else: fall through! */ + case EF_PKVMS: + /* "found nondecypherable e.f. with perm. attr" */ + r = TRUE; + default: + break; + } + ef_len -= (ebLen + EB_HEADSIZE); + ef += (ebLen + EB_HEADSIZE); + } + } + if (!r) { + uxattr = (( uxattr>>6 | uxattr>>3 | uxattr) & 07) << 1; + G.pInfo->file_attr = (unsigned)(uxattr&S_IWRITE ? + uxattr|S_IDELETE : uxattr); + break; + } + } + /* fall through! */ + + /* all other platforms: assume read-only bit in DOS half of attribute + * word is set correctly ==> will become READ or READ+WRITE+DELETE */ + case FS_FAT_: + case FS_HPFS_: /* can add S_IHIDDEN check to MSDOS/OS2/NT eventually */ + case FS_NTFS_: + case MAC_: + case TOPS20_: + default: + G.pInfo->file_attr = (unsigned)(tmp&1? S_IREAD : S_IRWD); + break; + + } /* end switch (host-OS-created-by) */ + + G.pInfo->file_attr &= 0xff; /* mask off all but lower eight bits */ + return 0; + +} /* end function mapattr() */ + + + + +/************************/ +/* Function mapname() */ +/************************/ + +int mapname(__G__ renamed) + __GDEF + int renamed; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - caution (truncated filename) + * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) + * MPN_ERR_SKIP - error -> skip entry + * MPN_ERR_TOOLONG - error -> path is too long + * MPN_NOMEM - error (memory allocation failed) -> skip entry + * [also MPN_VOL_LABEL, MPN_CREATED_DIR] + */ +{ + char pathcomp[FILNAMSIZ]; /* path-component buffer */ + char *pp, *cp=NULL; /* character pointers */ + char *lastsemi = NULL; /* pointer to last semi-colon in pathcomp */ + int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ + int error = MPN_OK; + register unsigned workch; /* hold the character being tested */ + + +/*--------------------------------------------------------------------------- + Initialize various pointers and counters and stuff. + ---------------------------------------------------------------------------*/ + + if (G.pInfo->vollabel) + return MPN_VOL_LABEL; /* can't set disk volume labels in AmigaDOS */ + + /* can create path as long as not just freshening, or if user told us */ + G.create_dirs = (!uO.fflag || renamed); + + G.created_dir = FALSE; /* not yet */ + + /* user gave full pathname: don't prepend G.rootpath */ +#ifndef OLD_AMIGA_RENAMED + G.renamed_fullpath = (renamed && + (*G.filename == '/' || *G.filename == ':')); +#else + /* supress G.rootpath even when user gave a relative pathname */ +# if 1 + G.renamed_fullpath = (renamed && strpbrk(G.filename, ":/"); +# else + G.renamed_fullpath = (renamed && + (strchr(G.filename, ':') || strchr(G.filename, '/'))); +# endif +#endif + + if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM) + return MPN_NOMEM; /* initialize path buffer, unless no memory */ + + *pathcomp = '\0'; /* initialize translation buffer */ + pp = pathcomp; /* point to translation buffer */ + if (uO.jflag) /* junking directories */ + cp = (char *)strrchr(G.filename, '/'); + if (cp == (char *)NULL) /* no '/' or not junking dirs */ + cp = G.filename; /* point to internal zipfile-member pathname */ + else + ++cp; /* point to start of last component of path */ + +/*--------------------------------------------------------------------------- + Begin main loop through characters in filename. + ---------------------------------------------------------------------------*/ + + while ((workch = (uch)*cp++) != 0) { + + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + if (strcmp(pathcomp, ".") == 0) { + /* don't bother appending "./" to the path */ + *pathcomp = '\0'; + } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { + /* "../" dir traversal detected, skip over it */ + *pathcomp = '\0'; + killed_ddot = TRUE; /* set "show message" flag */ + } + /* when path component is not empty, append it now */ + if (*pathcomp != '\0' && + ((error = checkdir(__G__ pathcomp, APPEND_DIR)) + & MPN_MASK) > MPN_INF_TRUNC) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ + break; + + case ';': /* VMS version (or DEC-20 attrib?) */ + lastsemi = pp; /* keep for now; remove VMS ";##" */ + *pp++ = (char)workch; /* later, if requested */ + break; + + default: + /* allow ISO European characters in filenames: */ + if (isprint(workch) || (160 <= workch && workch <= 255)) + *pp++ = (char)workch; + } /* end switch */ + + } /* end while loop */ + + /* Show warning when stripping insecure "parent dir" path components */ + if (killed_ddot && QCOND2) { + Info(slide, 0, ((char *)slide, + "warning: skipped \"../\" path component(s) in %s\n", + FnFilter1(G.filename))); + if (!(error & ~MPN_MASK)) + error = (error & MPN_MASK) | PK_WARN; + } + +/*--------------------------------------------------------------------------- + Report if directory was created (and no file to create: filename ended + in '/'), check name to be sure it exists, and combine path and name be- + fore exiting. + ---------------------------------------------------------------------------*/ + + if (G.filename[strlen(G.filename) - 1] == '/') { + checkdir(__G__ G.filename, GETPATH); + if (G.created_dir) { + if (QCOND2) { + Info(slide, 0, ((char *)slide, " creating: %s\n", + FnFilter1(G.filename))); + } + /* set dir time (note trailing '/') */ + return (error & ~MPN_MASK) | MPN_CREATED_DIR; + } + /* dir existed already; don't look for data to extract */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + *pp = '\0'; /* done with pathcomp: terminate it */ + + /* if not saving them, remove VMS version numbers (appended ";###") */ + if (!uO.V_flag && lastsemi) { + pp = lastsemi + 1; + while (isdigit((uch)(*pp))) + ++pp; + if (*pp == '\0') /* only digits between ';' and end: nuke */ + *lastsemi = '\0'; + } + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", + FnFilter1(G.filename))); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + + error = (error & ~MPN_MASK) | checkdir(__G__ pathcomp, APPEND_NAME); + if ((error & MPN_MASK) == MPN_INF_TRUNC) { + /* GRR: OK if truncated here: warn and continue */ + /* (warn in checkdir?) */ + } + checkdir(__G__ G.filename, GETPATH); + + return error; + +} /* end function mapname() */ + + + + +/***********************/ +/* Function checkdir() */ +/***********************/ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename + * MPN_INF_SKIP - path doesn't exist, not allowed to create + * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path + * exists and is not a directory, but is supposed to be + * MPN_ERR_TOOLONG - path is too long + * MPN_NOMEM - can't allocate memory for filename buffers + */ +{ +/* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in amiga.h: */ +/* static int rootlen = 0; */ /* length of rootpath */ +/* static char *rootpath; */ /* user's "extract-to" directory */ +/* static char *buildpath; */ /* full path (so far) to extracted file */ +/* static char *end; */ /* pointer to end of buildpath ('\0') */ + +# define FN_MASK 7 +# define FUNCTION (flag & FN_MASK) + + +/*--------------------------------------------------------------------------- + APPEND_DIR: append the path component to the path being built and check + for its existence. If doesn't exist and we are creating directories, do + so for this one; else signal success or error as appropriate. + ---------------------------------------------------------------------------*/ + +/* GRR: check path length after each segment: warn about truncation */ + + if (FUNCTION == APPEND_DIR) { + int too_long = FALSE; + + Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); + while ((*G.build_end = *pathcomp++) != '\0') + ++G.build_end; + /* Truncate components over 30 chars? Nah, the filesystem handles it. */ + if ((G.build_end-G.buildpath) > FILNAMSIZ-3) /* room for "/a\0" */ + too_long = TRUE; /* check if extracting dir? */ + if (SSTAT(G.buildpath, &G.statbuf)) { /* path doesn't exist */ + if (!G.create_dirs) { /* told not to create (freshening) */ + free(G.buildpath); + return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", + FnFilter1(G.buildpath))); + free(G.buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + if (MKDIR(G.buildpath, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, + "checkdir error: cannot create %s\n\ + unable to process %s.\n", + FnFilter2(G.buildpath), FnFilter1(G.filename))); + free(G.buildpath); + /* path didn't exist, tried to create, failed */ + return MPN_ERR_SKIP; + } + G.created_dir = TRUE; + } else if (!S_ISDIR(G.statbuf.st_mode)) { + Info(slide, 1, ((char *)slide, + "checkdir error: %s exists but is not directory\n\ + unable to process %s.\n", + FnFilter2(G.buildpath), FnFilter1(G.filename))); + free(G.buildpath); + /* path existed but wasn't dir */ + return MPN_ERR_SKIP; + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", FnFilter1(G.buildpath))); + free(G.buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + *G.build_end++ = '/'; + *G.build_end = '\0'; + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); + return MPN_OK; + + } /* end if (FUNCTION == APPEND_DIR) */ + +/*--------------------------------------------------------------------------- + GETPATH: copy full path to the string pointed at by pathcomp, and free + G.buildpath. Not our responsibility to worry whether pathcomp has room. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == GETPATH) { + strcpy(pathcomp, G.buildpath); + Trace((stderr, "getting and freeing path [%s]\n", + FnFilter1(pathcomp))); + free(G.buildpath); + G.buildpath = G.build_end = (char *)NULL; + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + APPEND_NAME: assume the path component is the filename; append it and + return without checking for existence. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_NAME) { + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); + while ((*G.build_end = *pathcomp++) != '\0') { + ++G.build_end; + if ((G.build_end-G.buildpath) >= FILNAMSIZ) { + *--G.build_end = '\0'; + Info(slide, 0x201, ((char *)slide, + "checkdir warning: path too long; truncating\n\ + %s\n -> %s\n", + FnFilter1(G.filename), FnFilter2(G.buildpath))); + return MPN_INF_TRUNC; /* filename truncated */ + } + } + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); + /* could check for existence here, prompt for new name... */ + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + INIT: allocate and initialize buffer space for the file currently being + extracted. If file was renamed with an absolute path, don't prepend the + extract-to path. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == INIT) { + Trace((stderr, "initializing buildpath to ")); + if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1)) + == (char *)NULL) + return MPN_NOMEM; + if ((G.rootlen > 0) && !G.renamed_fullpath) { + strcpy(G.buildpath, G.rootpath); + G.build_end = G.buildpath + G.rootlen; + } else { + *G.buildpath = '\0'; + G.build_end = G.buildpath; + } + Trace((stderr, "[%s]\n", FnFilter1(G.buildpath))); + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + ROOT: if appropriate, store the path in G.rootpath and create it if + necessary; else assume it's a zipfile member and return. This path + segment gets used in extracting all members from every zipfile specified + on the command line. + ---------------------------------------------------------------------------*/ + +#if (!defined(SFX) || defined(SFX_EXDIR)) + if (FUNCTION == ROOT) { + Trace((stderr, "initializing root path to [%s]\n", + FnFilter1(pathcomp))); + if (pathcomp == (char *)NULL) { + G.rootlen = 0; + return MPN_OK; + } + if (G.rootlen > 0) /* rootpath was already set, nothing to do */ + return MPN_OK; + if ((G.rootlen = strlen(pathcomp)) > 0) { + if (stat(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) { + /* path does not exist */ + if (!G.create_dirs) { + G.rootlen = 0; + /* skip (or treat as stored file) */ + return MPN_INF_SKIP; + } + /* create the directory (could add loop here scanning pathcomp + * to create more than one level, but why really necessary?) */ + if (MKDIR(pathcomp, 0777) == -1) { + Info(slide, 1, ((char *)slide, + "checkdir: cannot create extraction directory: %s\n", + FnFilter1(pathcomp))); + G.rootlen = 0; + /* path didn't exist, tried to create, and failed: */ + /* file exists, or 2+ subdir levels required */ + return MPN_ERR_SKIP; + } + } + if ((G.rootpath = (char *)malloc(G.rootlen+2)) == NULL) { + G.rootlen = 0; + return MPN_NOMEM; + } + strcpy(G.rootpath, pathcomp); + if (G.rootpath[G.rootlen-1] != ':' && G.rootpath[G.rootlen-1] != '/') + G.rootpath[G.rootlen++] = '/'; + G.rootpath[G.rootlen] = '\0'; + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath))); + } + return MPN_OK; + } +#endif /* !SFX || SFX_EXDIR */ + +/*--------------------------------------------------------------------------- + END: free G.rootpath, immediately prior to program exit. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == END) { + Trace((stderr, "freeing rootpath\n")); + if (G.rootlen > 0) { + free(G.rootpath); + G.rootlen = 0; + } + return MPN_OK; + } + + return MPN_INVALID; /* should never reach */ + +} /* end function checkdir() */ + + + + + +/**************************************/ +/* Function close_outfile() */ +/**************************************/ +/* this part differs slightly with Zip */ +/*-------------------------------------*/ + +void close_outfile(__G) + __GDEF +{ + time_t m_time; +#ifdef USE_EF_UT_TIME + iztimes z_utime; +#endif + LONG FileDate(); + + if (uO.cflag) /* can't set time or filenote on stdout */ + return; + + /* close the file *before* setting its time under AmigaDOS */ + + fclose(G.outfile); + + /* skip restoring time stamps on user's request */ + if (uO.D_flag <= 1) { +#ifdef USE_EF_UT_TIME + if (G.extra_field && +#ifdef IZ_CHECK_TZ + G.tz_is_valid && +#endif + (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, + G.lrec.last_mod_dos_datetime, &z_utime, NULL) + & EB_UT_FL_MTIME)) + { + TTrace((stderr, "close_outfile: Unix e.f. modif. time = %ld\n", + z_utime.mtime)); + m_time = z_utime.mtime; + } else { + /* Convert DOS time to time_t format */ + m_time = dos_to_unix_time(G.lrec.last_mod_dos_datetime); + } +#else /* !USE_EF_UT_TIME */ + /* Convert DOS time to time_t format */ + m_time = dos_to_unix_time(G.lrec.last_mod_dos_datetime); +#endif /* ?USE_EF_UT_TIME */ + +#ifdef DEBUG + Info(slide, 1, ((char *)slide, "\nclose_outfile(): m_time=%s\n", + ctime(&m_time))); +#endif + + if (!FileDate(G.filename, &m_time)) + Info(slide, 1, ((char *)slide, + "warning: cannot set the time for %s\n", G.filename)); + } + + /* set file perms after closing (not done at creation)--see mapattr() */ + + chmod(G.filename, G.pInfo->file_attr); + + /* give it a filenote from the zipfile comment, if appropriate */ + + if (uO.N_flag && G.filenotes[G.filenote_slot]) { + SetComment(G.filename, G.filenotes[G.filenote_slot]); + free(G.filenotes[G.filenote_slot]); + G.filenotes[G.filenote_slot] = NULL; + } + +} /* end function close_outfile() */ + + +#ifdef TIMESTAMP + +/*************************/ +/* Function stamp_file() */ +/*************************/ + +int stamp_file(fname, modtime) + ZCONST char *fname; + time_t modtime; +{ + time_t m_time; + LONG FileDate(); + + m_time = modtime; + return (FileDate((char *)fname, &m_time)); + +} /* end function stamp_file() */ + +#endif /* TIMESTAMP */ + + +#ifndef __SASC +/********************************************************************/ +/* Load filedate as a separate external file; it's used by Zip, too.*/ +/* */ +# include "amiga/filedate.c" /* */ +/* */ +/********************************************************************/ + +/********************* do linewise with stat.c **********************/ + +# include "amiga/stat.c" +/* this is the exact same stat.c used by Zip */ +#endif /* !__SASC */ +/* SAS/C makes separate object modules of these; there is less */ +/* trouble that way when redefining standard library functions. */ + +#include + +void _abort(void) /* called when ^C is pressed */ +{ + /* echon(); */ + close_leftover_open_dirs(); + fflush(stdout); + fputs("\n^C\n", stderr); + exit(1); +} + + +/************************************************************/ +/* function screensize() -- uses sendpkt() from filedate.c: */ +/************************************************************/ + +#include +#include +#include +#include + +extern long sendpkt(struct MsgPort *pid, long action, long *args, long nargs); + +int screensize(int *ttrows, int *ttcols) +{ + BPTR fh = Output(); + if (fh && IsInteractive(fh)) { + struct ConUnit *conunit = NULL; + void *conp = ((struct FileHandle *) (fh << 2))->fh_Type; + struct InfoData *ind = AllocMem(sizeof(*ind), MEMF_PUBLIC); + long argp = ((unsigned long) ind) >> 2; + + if (ind && conp && sendpkt(conp, ACTION_DISK_INFO, &argp, 1)) + conunit = (void *) ((struct IOStdReq *) ind->id_InUse)->io_Unit; + if (ind) + FreeMem(ind, sizeof(*ind)); + if (conunit) { + if (ttrows) *ttrows = conunit->cu_YMax + 1; + if (ttcols) *ttcols = conunit->cu_XMax + 1; + return 0; /* success */ + } + } + if (ttrows) *ttrows = INT_MAX; + if (ttcols) *ttcols = INT_MAX; + return 1; /* failure */ +} + + +#ifdef AMIGA_VOLUME_LABELS +/* This function is for if we someday implement -$ on the Amiga. */ +# include +# include +# include + +BOOL is_floppy(ZCONST char *path) +{ + BOOL okay = FALSE; + char devname[32], *debna; + ushort i; + BPTR lok = Lock((char *)path, ACCESS_READ), pok; + struct FileSysStartupMsg *fart; + struct DeviceNode *debb, devlist = (void *) BADDR((struct DosInfo *) + BADDR(DOSBase->dl_Root->rn_Info)->di_DevInfo); + if (!lok) + return FALSE; /* should not happen */ + if (pok = ParentDir((char *)path)) { + UnLock(lok); + UnLock(pok); + return FALSE; /* it's not a root directory path */ + } + Forbid(); + for (debb = devlist; debb; debb = BADDR(debb->dn_Next)) + if (debb->dn_Type == DLT_DEVICE && (debb->dn_Task == lick->fl_Task)) + if (fart = BADDR(debb->dn_Startup)) { + debna = (char *) BADDR(fart->fssm_Device) + 1; + if ((i = debna[-1]) > 31) i = 30; + strncpy(devname, debna, i); + devname[i] = 0; + okay = !strcmp(devname, "trackdisk.device") + || !strcmp(devname, "mfm.device") + || !strcmp(devname, "messydisk.device"); + break; /* We only support obvious floppy drives, not tricky */ + } /* things like removable cartrige hard drives, or */ + Permit(); /* any unusual kind of floppy device driver. */ + return okay; +} +#endif /* AMIGA_VOLUME_LABELS */ + + +#ifndef SFX + +# if 0 +/* As far as I can tell, all the locales AmigaDOS 2.1 knows about all */ +/* happen to use DF_MDY ordering, so there's no point in using this. */ + +/*************************/ +/* Function dateformat() */ +/*************************/ + +#include +#ifdef AZTEC_C +# include +#endif + +int dateformat() +{ +/*--------------------------------------------------------------------------- + For those operating systems which support it, this function returns a + value which tells how national convention says that numeric dates are + displayed. Return values are DF_YMD, DF_DMY and DF_MDY (the meanings + should be fairly obvious). + ---------------------------------------------------------------------------*/ + struct Library *LocaleBase; + struct Locale *ll; + int result = DF_MDY; /* the default */ + + if ((LocaleBase = OpenLibrary("locale.library", 0))) { + if (ll = OpenLocale(NULL)) { + uch *f = ll->loc_ShortDateFormat; + /* In this string, %y|%Y is year, %b|%B|%h|%m is month, */ + /* %d|%e is day day, and %D|%x is short for mo/da/yr. */ + if (!strstr(f, "%D") && !strstr(f, "%x")) { + uch *da, *mo, *yr; + if (!(mo = strstr(f, "%b")) && !(mo = strstr(f, "%B")) + && !(mo = strstr(f, "%h"))) + mo = strstr(f, "%m"); + if (!(da = strstr(f, "%d"))) + da = strstr(f, "%e"); + if (!(yr = strstr(f, "%y"))) + yr = strstr(f, "%Y"); + if (yr && yr < mo) + result = DF_YMD; + else if (da && da < mo) + result = DF_DMY; + } + CloseLocale(ll); + } + CloseLibrary(LocaleBase); + } + return result; +} + +# endif /* 0 */ + + +/************************/ +/* Function version() */ +/************************/ + + +/* NOTE: the following include depends upon the environment + * variable $Workbench to be set correctly. (Set by + * default, by kickstart during startup) + */ +int WBversion = (int) +#include "ENV:Workbench" +; + +void version(__G) + __GDEF +{ +/* Define buffers. */ + + char buf1[16]; /* compiler name */ + char buf2[16]; /* revstamp */ + char buf3[16]; /* OS */ + char buf4[16]; /* Date */ +/* char buf5[16]; /* Time */ + +/* format "with" name strings */ + +#ifdef AMIGA +# ifdef __SASC + strcpy(buf1,"SAS/C "); +# else +# ifdef LATTICE + strcpy(buf1,"Lattice C "); +# else +# ifdef AZTEC_C + strcpy(buf1,"Manx Aztec C "); +# else + strcpy(buf1,"UNKNOWN "); +# endif +# endif +# endif +/* "under" */ + sprintf(buf3,"AmigaDOS v%d",WBversion); +#else + strcpy(buf1,"Unknown compiler "); + strcpy(buf3,"Unknown OS"); +#endif + +/* Define revision, date, and time strings. + * NOTE: Do not calculate run time, be sure to use time compiled. + * Pass these strings via your makefile if undefined. + */ + +#if defined(__VERSION__) && defined(__REVISION__) + sprintf(buf2,"version %d.%d",__VERSION__,__REVISION__); +#else +# ifdef __VERSION__ + sprintf(buf2,"version %d",__VERSION__); +# else + sprintf(buf2,"unknown version"); +# endif +#endif + +#ifdef __DATE__ + sprintf(buf4," on %s",__DATE__); +#else + strcpy(buf4," unknown date"); +#endif + +/****** +#ifdef __TIME__ + sprintf(buf5," at %s",__TIME__); +#else + strcpy(buf5," unknown time"); +#endif +******/ + +/* Print strings using "CompiledWith" mask defined in unzip.c (used by all). + * ("Compiled with %s%s for %s%s%s%s.") + */ + + printf(LoadFarString(CompiledWith), + buf1, + buf2, + buf3, + buf4, + "", /* buf5 not used */ + "" ); /* buf6 not used */ + +} /* end function version() */ + +#endif /* !SFX */ diff --git a/amiga/amiga.h b/amiga/amiga.h new file mode 100644 index 0000000..5cecab8 --- /dev/null +++ b/amiga/amiga.h @@ -0,0 +1,190 @@ +/* + Copyright (c) 1990-2005 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 +*/ +/* amiga.h + * + * Globular definitions that affect all of AmigaDom. + * + * Originally included in unzip.h, extracted for simplicity and eeze of + * maintenance by John Bush. + * + * THIS FILE IS #INCLUDE'd by unzpriv.h + * + */ + +#ifndef __amiga_amiga_h +#define __amiga_amiga_h + +#include "amiga/z-stat.h" /* substitute for and */ +#include +#ifndef NO_FCNTL_H +# include +#else + int mkdir(const char *_name); +#endif + +/* we only have dinky old-sk00l 32 bit filesystems */ +#ifdef LARGE_FILE_SUPPORT +# undef LARGE_FILE_SUPPORT +#endif + +typedef long zoff_t; +#define ZOFF_T_DEFINED +typedef struct stat z_stat; +#define Z_STAT_DEFINED + +#ifdef AZTEC_C /* Manx Aztec C, 5.0 or newer only */ +# include +# include /* do inline dos.library calls */ +# define O_BINARY 0 +# define direct dirent + +# ifndef IZTZ_DEFINESTDGLOBALS +# define IZTZ_DEFINESTDGLOBALS +# endif + +# define DECLARE_TIMEZONE +# define ASM_INFLATECODES +# define ASM_CRC + + /* This compiler environment supplies a flat 32-bit address space */ + /* where C rtl functions are capable of handling large (32-bit-wide) */ + /* allocations and I/O. But, for speed on old 68000 CPUs, standard */ + /* ints are 16-bits wide per default. ("size_t" is defined as */ + /* "unsigned long" in this case.) The Deflate64 support requires */ + /* the variables for handling the decompression buffer to hold */ + /* 32-bit wide integers. The INT_16BIT symbol defined below forces */ + /* the declarations of these variables to use "unsigned long" type. */ +# ifndef _INT32 +# define INT_16BIT /* or deflate64 stuff will fail */ +# endif + +/* Note that defining REENTRANT will not eliminate all global/static */ +/* variables. The functions we use from c.lib, including stdio, are */ +/* not reentrant. Neither are the stuff in amiga/stat.c or the time */ +/* functions in amiga/filedate.c, because they just augment c.lib. */ +/* If you want a fully reentrant and reexecutable "pure" UnZip with */ +/* Aztec C, assemble and link in the startup module purify.a by Paul */ +/* Kienitz. REENTRANT should be used just to reduce memory waste. */ +#endif /* AZTEC_C */ + + +#ifdef __SASC +/* NOTE: SAS/C COMPILATION HAS BEEN UNSUPPORTED THROUGH MANY UNZIP VERSIONS. */ +/* (Which is too bad, because it would probably perform better than Aztec.) */ + +/* includes */ +# include +# include +# include +# include +# include +# if (defined(_M68020) && (!defined(__USE_SYSBASE))) + /* on 68020 or higher processors it is faster */ +# define __USE_SYSBASE /* to use the pragma libcall instead of syscall */ +# endif /* to access functions of the exec.library */ +# include /* see SAS/C manual:part 2,chapter 2,pages 6-7 */ +# include +# include + +# ifdef DEBUG +# include /* profiler header file */ +# endif +# if ( (!defined(O_BINARY)) && defined(O_RAW)) +# define O_BINARY O_RAW +# endif +# if (defined(_SHORTINT) && !defined(USE_FWRITE)) +# define USE_FWRITE /* define if write() returns 16-bit int */ +# endif +# if (!defined(REENTRANT) && !defined(FUNZIP)) +# define REENTRANT /* define if unzip is going to be pure */ +# endif +# if defined(REENTRANT) && defined(DYNALLOC_CRCTAB) +# undef DYNALLOC_CRCTAB +# endif +# ifdef MWDEBUG +# include /* both stdio.h and stdlib.h must be included */ +# include /* before memwatch.h */ +# include "memwatch.h" +# undef getenv +# endif /* MWDEBUG */ +# ifndef IZTZ_SETLOCALTZINFO + /* XXX !! We have really got to find a way to operate without these. */ +# define IZTZ_SETLOCALTZINFO +# endif +#endif /* SASC */ + + +#define MALLOC_WORK +#define USE_EF_UT_TIME +#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) +# define TIMESTAMP +#endif + +#ifndef IZTZ_GETLOCALETZINFO +# define IZTZ_GETLOCALETZINFO GetPlatformLocalTimezone +#endif +/* the amiga port uses Info-ZIP's own timezone library, which includes + * a "working" mktime() implementation + */ +#ifndef HAVE_MKTIME +# define HAVE_MKTIME +#endif + +/* check that TZ environment variable is defined before using UTC times */ +#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ)) +# define IZ_CHECK_TZ +#endif + +#define AMIGA_FILENOTELEN 80 +#ifndef DATE_FORMAT +# define DATE_FORMAT DF_MDY +#endif +#define lenEOL 1 +#define PutNativeEOL *q++ = native(LF); +#define PIPE_ERROR 0 + +#ifdef GLOBAL /* crypt.c usage conflicts with AmigaDOS headers */ +# undef GLOBAL +#endif + +/* Funkshine Prough Toe Taipes */ + +extern int real_timezone_is_set; +void tzset(void); +#define VALID_TIMEZONE(tempvar) (tzset(), real_timezone_is_set) + +int Agetch(void); /* getch() like function, in amiga/filedate.c */ +LONG FileDate(char *, time_t[]); +int screensize(int *ttrows, int *ttcols); +void _abort(void); /* ctrl-C trap */ + +#define SCREENSIZE(ttrows, ttcols) screensize(ttrows, ttcols) +#define SCREENWIDTH 80 +#define SCREENLWRAP 1 +#define TABSIZE 8 + +/* Static variables that we have to add to Uz_Globs: */ +#define SYSTEM_SPECIFIC_GLOBALS \ + int filenote_slot;\ + char *(filenotes[DIR_BLKSIZ]);\ + int created_dir, renamed_fullpath, rootlen;\ + char *rootpath, *buildpath, *build_end;\ + DIR *wild_dir;\ + ZCONST char *wildname;\ + char *dirname, matchname[FILNAMSIZ];\ + int dirnamelen, notfirstcall; + +/* filenotes[] and filenote_slot are for the -N option that restores */ +/* comments of Zip archive entries as AmigaDOS filenotes. The others */ +/* are used by functions in amiga/amiga.c only. */ +/* created_dir and renamed_fullpath are used by mapname() and checkdir(). */ +/* rootlen, rootpath, buildpath, and build_end are used by checkdir(). */ +/* wild_dir, dirname, wildname, matchname[], dirnamelen and notfirstcall */ +/* are used by do_wild(). */ +#endif /* __amiga_amiga_h */ diff --git a/amiga/crc_68.a b/amiga/crc_68.a new file mode 100644 index 0000000..4cc2a25 --- /dev/null +++ b/amiga/crc_68.a @@ -0,0 +1,144 @@ +;=========================================================================== +; 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 +;=========================================================================== +; crc_68 created by Paul Kienitz, last modified 04 Jan 96. +; +; Return an updated 32 bit CRC value, given the old value and a block of data. +; The CRC table used to compute the value is gotten by calling get_crc_table(). +; This replaces the older updcrc() function used in Zip and fUnZip. The +; prototype of the function is: +; +; ulg crc32(ulg crcval, uch *text, extent textlen); +; +; On the Amiga, type extent is always unsigned long, not unsigned int, because +; int can be short or long at whim, but size_t is long. +; +; If using this source on a non-Amiga 680x0 system, note that we treat +; a0/a1/d0/d1 as scratch registers not preserved across function calls. +; We do not bother to support registerized arguments for crc32() -- the +; textlen parm is usually large enough so that savings outside the loop +; are pointless. +; +; Define NO_UNROLLED_LOOPS to use a simple short loop which might be more +; efficient on certain machines with dinky instruction caches ('020?), or for +; processing short strings. If loops are unrolled, the textlen parm must be +; less than 512K; if not unrolled, it must be less than 64K. + + xdef _crc32 ; (ulg val, uch *buf, extent bufsize) + +DO_CRC0 MACRO + moveq #0,ltemp + move.b (textbuf)+,ltemp + eor.b crcval,ltemp + lsl.w #2,ltemp + move.l (crc_table,ltemp.w),ltemp + lsr.l #8,crcval + eor.l ltemp,crcval + ENDM + + machine mc68020 + +DO_CRC2 MACRO + move.b (textbuf)+,btemp + eor.b crcval,btemp + lsr.l #8,crcval + move.l (crc_table,btemp.w*4),ltemp + eor.l ltemp,crcval + ENDM + +crc_table equr a0 array of unsigned long +crcval equr d0 unsigned long initial value +textbuf equr a1 array of unsigned char +textbufsize equr d1 unsigned long (count of bytes in textbuf) +btemp equr d2 +ltemp equr d3 + + + xref _get_crc_table ; ulg *get_crc_table(void) + + NOLIST + INCLUDE 'exec/execbase.i' + LIST + xref _SysBase ; struct ExecBase * + + +_crc32: + move.l 8(sp),d0 + bne.s valid + moveq #0,d0 + rts +valid: movem.l btemp/ltemp,-(sp) + jsr _get_crc_table + move.l d0,ltemp + move.l 12(sp),crcval + move.l 16(sp),textbuf + move.l 20(sp),textbufsize + not.l crcval + move.l _SysBase,crc_table + move.w AttnFlags(crc_table),btemp + move.l ltemp,crc_table + btst #AFB_68020,btemp + bne twenty + + IFD NO_UNROLLED_LOOPS + + bra.s decr +loop: DO_CRC0 +decr: dbra textbufsize,loop + bra.s done + +twenty: moveq #0,btemp + bra.s decr2 +loop2: DO_CRC2 +decr2: dbra textbufsize,loop2 + + ELSE ; !NO_UNROLLED_LOOPS + + move.l textbufsize,btemp + lsr.l #3,textbufsize + bra decr8 +loop8: DO_CRC0 + DO_CRC0 + DO_CRC0 + DO_CRC0 + DO_CRC0 + DO_CRC0 + DO_CRC0 + DO_CRC0 +decr8: dbra textbufsize,loop8 + and.w #7,btemp + bra.s decr1 +loop1: DO_CRC0 +decr1: dbra btemp,loop1 + bra done + +twenty: moveq #0,btemp + move.l textbufsize,-(sp) + lsr.l #3,textbufsize + bra decr82 +loop82: DO_CRC2 + DO_CRC2 + DO_CRC2 + DO_CRC2 + DO_CRC2 + DO_CRC2 + DO_CRC2 + DO_CRC2 +decr82: dbra textbufsize,loop82 + move.l (sp)+,textbufsize + and.w #7,textbufsize + bra.s decr12 +loop12: DO_CRC2 +decr12: dbra textbufsize,loop12 + + ENDC ; ?NO_UNROLLED_LOOPS + +done: movem.l (sp)+,btemp/ltemp + not.l crcval +;;;;; move.l crcval,d0 ; crcval already is d0 + rts diff --git a/amiga/filedate.c b/amiga/filedate.c new file mode 100644 index 0000000..9ccbdda --- /dev/null +++ b/amiga/filedate.c @@ -0,0 +1,599 @@ +/* + 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 +*/ +/* Low-level Amiga routines shared between Zip and UnZip. + * + * Contains: FileDate() + * getenv() [replaces inadequate standard library version] + * setenv() [SAS/C only, replaces standard library version] + * set_TZ() [SAS/C only] + * GetPlatformLocalTimezone() [callback from timezone.c tzset()] + * time() + * sendpkt() + * Agetch() + * + * The first five are used by most Info-ZIP programs except fUnZip. + * The last two are used by all except the non-CRYPT version of fUnZip. + * Probably some of the stuff in here is unused by ZipNote and ZipSplit too... + * sendpkt() is used by Agetch() and FileDate(), and by screensize() in + * amiga/amiga.c (UnZip); time() is used only by Zip. + */ + + +/* HISTORY/CHANGES + * 2 Sep 92, Greg Roelofs, Original coding. + * 6 Sep 92, John Bush, Incorporated into UnZip 5.1 + * 6 Sep 92, John Bush, Interlude "FileDate()" defined, which calls or + * redefines SetFileDate() depending upon AMIGADOS2 definition. + * 11 Oct 92, John Bush, Eliminated AMIGADOS2 switch by determining + * revision via OpenLibrary() call. Now only one version of + * the program runs on both platforms (1.3.x vs. 2.x) + * 11 Oct 92, John Bush, Merged with Zip version and changed arg passing + * to take time_t input instead of struct DateStamp. + * Arg passing made to conform with utime(). + * 22 Nov 92, Paul Kienitz, fixed includes for Aztec and cleaned up some + * lint-ish errors; simplified test for AmigaDOS version. + * 11 Nov 95, Paul Kienitz, added Agetch() for crypt password input and + * UnZip's "More" prompt -- simplifies crypt.h and avoids + * use of library code redundant with sendpkt(). Made it + * available to fUnZip, which does not use FileDate(). + * 22 Nov 95, Paul Kienitz, created a new tzset() that gets the current + * timezone from the Locale preferences. These exist only under + * AmigaDOS 2.1 and up, but it is probably correctly set on more + * Amigas than the TZ environment variable is. We check that + * only if TZ is not validly set. We do not parse daylight + * savings syntax except to check for presence vs. absence of a + * DST part; United States rules are assumed. This is better + * than the tzset()s in the Amiga compilers' libraries do. + * 15 Jan 96, Chr. Spieler, corrected the logic when to select low level + * sendpkt() (when FileDate(), Agetch() or windowheight() is used), + * and AMIGA's Agetch() (CRYPT, and UnZip(SFX)'s UzpMorePause()). + * 10 Feb 96, Paul Kienitz, re-fiddled that selection logic again, moved + * stuff around for clarity. + * 16 Mar 96, Paul Kienitz, created a replacement localtime() to go with the + * new tzset(), because Aztec's is hopelessly broken. Also + * gmtime(), which localtime() calls. + * 12 Apr 96, Paul Kienitz, daylight savings was being handled incorrectly. + * 21 Apr 96, Paul Kienitz, had to replace time() as well, Aztec's returns + * local time instead of GMT. That's why their localtime() was bad, + * because it assumed time_t was already local, and gmtime() was + * the one that checked TZ. + * 23 Apr 96, Chr. Spieler, deactivated time() replacement for UnZip stuff. + * Currently, the UnZip sources do not make use of time() (and do + * not supply the working mktime() replacement, either!). + * 29 Apr 96, Paul Kienitz, created a replacement getenv() out of code that + * was previously embedded in tzset(), for reliable global test + * of whether TZ is set or not. + * 19 Jun 96, Haidinger Walter, re-adapted for current SAS/C compiler. + * 7 Jul 96, Paul Kienitz, smoothed together compiler-related changes. + * 4 Feb 97, Haidinger Walter, added set_TZ() for SAS/C. + * 23 Apr 97, Paul Kienitz, corrected Unix->Amiga DST error by adding + * mkgmtime() so localtime() could be used. + * 28 Apr 97, Christian Spieler, deactivated mkgmtime() definition for ZIP; + * the Zip sources supply this function as part of util.c. + * 24 May 97, Haidinger Walter, added time_lib support for SAS/C and moved + * set_TZ() to time_lib.c. + * 12 Jul 97, Paul Kienitz, adapted time_lib stuff for Aztec. + * 26 Jul 97, Chr. Spieler, old mkgmtime() fixed (ydays[] def, sign vs unsign). + * 30 Dec 97, Haidinger Walter, adaptation for SAS/C using z-stat.h functions. + * 19 Feb 98, Haidinger Walter, removed alloc_remember, more SAS.C fixes. + * 23 Apr 98, Chr. Spieler, removed mkgmtime(), changed FileDate to convert to + * Amiga file-time directly. + * 24 Apr 98, Paul Kienitz, clip Unix dates earlier than 1978 in FileDate(). + * 02 Sep 98, Paul Kienitz, C. Spieler, always include zip.h to get a defined + * header inclusion sequence that resolves all header dependencies. + * 06 Jun 00, Paul Kienitz, removed time_lib.c due to its incompatible license, + * moved set_TZ() back here, replaced minimal tzset() and localtime() + * with new versions derived from GNU glibc source. Gave locale_TZ() + * reasonable European defaults for daylight savings. + * 17 Jun 00, Paul Kienitz, threw out GNU code because of objections to the GPL + * virus, replaced with similar functions based on the public domain + * timezone code at ftp://elsie.nci.nih.gov/pub. As with the GNU + * stuff, support for timezone files and leap seconds was removed. + * 23 Aug 00, Paul Kienitz, moved timezone code out from here into separate + * platform-independent module 'timezone.c'. + * 31 Dec 00, Christian Spieler, moved system-specific timezone help funcions + * back in here, from 'timezone.c'. + * 07 Jan 01, Paul Kienitz, Chr. Spieler, added missing #include "timezone.h" + * and "symbolic" preprocessor constants for time calculations. + * 15 Jan 02, Paul Kienitz, excluded all time handling code from compilation + * for Zip utilities (when "defined(UTIL)") + */ + +#ifndef __amiga_filedate_c +#define __amiga_filedate_c + + +#include "zip.h" +#include +#include + +#include +#include +#include +#include + +#ifdef AZTEC_C +# include +# include +# include +# include +# include +# include +# include +# include +# define ESRCH ENOENT +# define EOSERR EIO +#endif + +#ifdef __SASC +# include +# if (defined(_M68020) && (!defined(__USE_SYSBASE))) + /* on 68020 or higher processors it is faster */ +# define __USE_SYSBASE /* to use the pragma libcall instead of syscall */ +# endif /* to access functions of the exec.library */ +# include /* see SAS/C manual:part 2,chapter 2,pages 6-7 */ +# include +# include +# ifdef DEBUG +# include +# endif +# ifdef MWDEBUG +# include /* include both before memwatch.h again just */ +# include /* to be safe */ +# include "memwatch.h" +# endif /* MWDEBUG */ +#endif /* __SASC */ + +#include "crypt.h" /* just so we can tell if CRYPT is supported */ + + +#if (!defined(FUNZIP) && !defined(UTIL)) + +#include "timezone.h" /* for AMIGA-specific timezone callbacks */ + +#ifndef SUCCESS +# define SUCCESS (-1L) +# define FAILURE 0L +#endif + +#define ReqVers 36L /* required library version for SetFileDate() */ +#define ENVSIZE 100 /* max space allowed for an environment var */ + +extern struct ExecBase *SysBase; + +#ifndef min +# define min(a, b) ((a) < (b) ? (a) : (b)) +# define max(a, b) ((a) < (b) ? (b) : (a)) +#endif + +#if defined(ZIP) || defined(HAVE_MKTIME) +static const unsigned short ydays[] = + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; +#else +extern const unsigned short ydays[]; /* in unzip's fileio.c */ +#endif + +#define LEAP(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0) +#define YDAYS(m, y) (ydays[m] + (m > 1 && LEAP(y))) +/* Number of leap years from 1978 to `y' (not including `y' itself). */ +#define ANLEAP(y) (((y) - 1977) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400) +#define SECSPERMIN 60 +#define MINSPERHOUR 60 +#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) +#define SECSPERDAY 86400L + +/* prototypes */ +char *getenv(const char *var); +#ifdef __SASC +/* XXX !! We have really got to find a way to operate without these. */ +int setenv(const char *var, const char *value, int overwrite); +void set_TZ(long time_zone, int day_light); +#endif + +LONG FileDate(char *filename, time_t u[]); +LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs); +int Agetch(void); + +/* =============================================================== */ + +/***********************/ +/* Function filedate() */ +/***********************/ + +/* FileDate() (originally utime.c), by Paul Wells. Modified by John Bush + * and others (see also sendpkt() comments, below); NewtWare SetFileDate() + * clone cheaply ripped off from utime(). + */ + +/* DESCRIPTION + * This routine chooses between 2 methods to set the file date on AMIGA. + * Since AmigaDOS 2.x came out, SetFileDate() was available in ROM (v.36 + * and higher). Under AmigaDOS 1.3.x (less than v.36 ROM), SetFileDate() + * must be accomplished by constructing a message packet and sending it + * to the file system handler of the file to be stamped. + * + * The system's ROM version is extracted from the external system Library + * base. + * + * NOTE: although argument passing conforms with utime(), note the + * following differences: + * - Return value is boolean success/failure. + * - If a structure or array is passed, only the first value + * is used, which *may* correspond to date accessed and not + * date modified. + */ + +LONG FileDate(filename, u) + char *filename; + time_t u[]; +{ + LONG SetFileDate(UBYTE *filename, struct DateStamp *pDate); + LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs); + struct MsgPort *taskport; + BPTR dirlock, lock; + struct FileInfoBlock *fib; + LONG pktargs[4]; + UBYTE *ptr; + long ret; + + struct DateStamp pDate; + struct tm *ltm; + int years; + + tzset(); + /* Amiga file date is based on 01-Jan-1978 00:00:00 (local time): + * 8 years and 2 leapdays difference from Unix time. + */ + ltm = localtime(&u[0]); + years = ltm->tm_year + 1900; + if (years < 1978) + pDate.ds_Days = pDate.ds_Minute = pDate.ds_Tick = 0; + else { + pDate.ds_Days = (years - 1978) * 365L + (ANLEAP(years)) + + YDAYS(ltm->tm_mon, years) + (ltm->tm_mday - 1); + pDate.ds_Minute = ltm->tm_hour * 60 + ltm->tm_min; + pDate.ds_Tick = ltm->tm_sec * TICKS_PER_SECOND; + } + + if (SysBase->LibNode.lib_Version >= ReqVers) + { + return (SetFileDate(filename,&pDate)); /* native routine at 2.0+ */ + } + else /* !(SysBase->lib_Version >=ReqVers) */ + { + if( !(taskport = (struct MsgPort *)DeviceProc(filename)) ) + { + errno = ESRCH; /* no such process */ + return FAILURE; + } + + if( !(lock = Lock(filename,SHARED_LOCK)) ) + { + errno = ENOENT; /* no such file */ + return FAILURE; + } + + if( !(fib = (struct FileInfoBlock *)AllocMem( + (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) ) + { + errno = ENOMEM; /* insufficient memory */ + UnLock(lock); + return FAILURE; + } + + if( Examine(lock,fib)==FAILURE ) + { + errno = EOSERR; /* operating system error */ + UnLock(lock); + FreeMem(fib,(long)sizeof(*fib)); + return FAILURE; + } + + dirlock = ParentDir(lock); + ptr = (UBYTE *)AllocMem(64L,MEMF_PUBLIC); + strcpy((ptr+1),fib->fib_FileName); + *ptr = strlen(fib->fib_FileName); + FreeMem(fib,(long)sizeof(*fib)); + UnLock(lock); + + /* now fill in argument array */ + + pktargs[0] = 0; + pktargs[1] = (LONG)dirlock; + pktargs[2] = (LONG)&ptr[0] >> 2; + pktargs[3] = (LONG)&pDate; + + errno = ret = sendpkt(taskport,ACTION_SET_DATE,pktargs,4L); + + FreeMem(ptr,64L); + UnLock(dirlock); + + return SUCCESS; + } /* ?(SysBase->lib_Version >= ReqVers) */ +} /* FileDate() */ + + +char *getenv(const char *var) /* not reentrant! */ +{ + static char space[ENVSIZE]; + struct Process *me = (void *) FindTask(NULL); + void *old_window = me->pr_WindowPtr; + char *ret = NULL; + + me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */ + if (SysBase->LibNode.lib_Version >= ReqVers) { + if (GetVar((char *) var, space, ENVSIZE - 1, /*GVF_GLOBAL_ONLY*/ 0) > 0) + ret = space; + } else { /* early AmigaDOS, get env var the crude way */ + BPTR hand, foot, spine; + int z = 0; + if (foot = Lock("ENV:", ACCESS_READ)) { + spine = CurrentDir(foot); + if (hand = Open((char *) var, MODE_OLDFILE)) { + z = Read(hand, space, ENVSIZE - 1); + Close(hand); + } + UnLock(CurrentDir(spine)); + } + if (z > 0) { + space[z] = '\0'; + ret = space; + } + } + me->pr_WindowPtr = old_window; + return ret; +} + +#ifdef __SASC +int setenv(const char *var, const char *value, int overwrite) +{ + struct Process *me = (void *) FindTask(NULL); + void *old_window = me->pr_WindowPtr; + int ret = -1; + + me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */ + if (SysBase->LibNode.lib_Version >= ReqVers) + ret = !SetVar((char *)var, (char *)value, -1, GVF_GLOBAL_ONLY | LV_VAR); + else { + BPTR hand, foot, spine; + long len = value ? strlen(value) : 0; + if (foot = Lock("ENV:", ACCESS_READ)) { + spine = CurrentDir(foot); + if (len) { + if (hand = Open((char *) var, MODE_NEWFILE)) { + ret = Write(hand, (char *) value, len + 1) >= len; + Close(hand); + } + } else + ret = DeleteFile((char *) var); + UnLock(CurrentDir(spine)); + } + } + me->pr_WindowPtr = old_window; + return ret; +} + +/* Stores data from timezone and daylight to ENV:TZ. */ +/* ENV:TZ is required to exist by some other SAS/C library functions, */ +/* like stat() or fstat(). */ +void set_TZ(long time_zone, int day_light) +{ + char put_tz[MAXTIMEZONELEN]; /* string for putenv: "TZ=aaabbb:bb:bbccc" */ + int offset; + void *exists; /* dummy ptr to see if global envvar TZ already exists */ + exists = (void *)getenv(TZ_ENVVAR); + /* see if there is already an envvar TZ_ENVVAR. If not, create it */ + if (exists == NULL) { + /* create TZ string by pieces: */ + sprintf(put_tz, "GMT%+ld", time_zone / 3600L); + if (time_zone % 3600L) { + offset = (int) labs(time_zone % 3600L); + sprintf(put_tz + strlen(put_tz), ":%02d", offset / 60); + if (offset % 60) + sprintf(put_tz + strlen(put_tz), ":%02d", offset % 60); + } + if (day_light) + strcat(put_tz,"DST"); + setenv(TZ_ENVVAR, put_tz, 1); + } +} +#endif /* __SASC */ + +/* set state as well as possible from settings found in locale.library */ +int GetPlatformLocalTimezone(sp, fill_tzstate_from_rules) + register struct state * ZCONST sp; + void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res, + ZCONST struct rule * ZCONST start, + ZCONST struct rule * ZCONST end); +{ + struct Library *LocaleBase; + struct Locale *ll; + struct Process *me = (void *) FindTask(NULL); + void *old_window = me->pr_WindowPtr; + BPTR eh; + int z, valid = FALSE; + + /* read timezone from locale.library if TZ envvar missing */ + me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */ + if (LocaleBase = OpenLibrary("locale.library", 0)) { + if (ll = OpenLocale(NULL)) { + z = ll->loc_GMTOffset; /* in minutes */ + if (z == -300) { + if (eh = Lock("ENV:sys/locale.prefs", ACCESS_READ)) { + UnLock(eh); + valid = TRUE; + } else + z = 300; /* bug: locale not initialized, default bogus! */ + } else + valid = TRUE; + if (valid) { + struct rule startrule, stoprule; + + sp->timecnt = 0; + sp->typecnt = 1; + sp->charcnt = 2; + sp->chars[0] = sp->chars[1] = '\0'; + sp->ttis[0].tt_abbrind = 0; + sp->ttis[1].tt_abbrind = 1; + sp->ttis[0].tt_gmtoff = -z * MINSPERHOUR; + sp->ttis[1].tt_gmtoff = -z * MINSPERHOUR + SECSPERHOUR; + sp->ttis[0].tt_isdst = 0; + sp->ttis[1].tt_isdst = 1; + stoprule.r_type = MONTH_NTH_DAY_OF_WEEK; + stoprule.r_day = 0; + stoprule.r_week = 5; + stoprule.r_mon = 10; + stoprule.r_time = 2 * SECSPERHOUR; + startrule = stoprule; + startrule.r_mon = 4; + startrule.r_week = 1; + if (z >= -180 && z < 150) { + /* At this point we make a really gratuitous assumption: */ + /* if the time zone could be Europe, we use the European */ + /* Union rules without checking what country we're in. */ + /* The AmigaDOS locale country codes do not, at least in */ + /* 2.x versions of the OS, recognize very many countries */ + /* outside of Europe and North America. */ + sp->typecnt = 2; + startrule.r_mon = 3; /* one week earlier than US DST */ + startrule.r_week = 5; + } else if (z >= 150 && z <= 480 && + /* no DST in alaska, hawaii */ + (ll->loc_CountryCode == 0x55534100 /*"USA"*/ || + ll->loc_CountryCode == 0x43414E00 /*"CAN"*/)) + sp->typecnt = 2; + /* We check the country code for U.S. or Canada because */ + /* most of Latin America has no DST. Even in these two */ + /* countries there are some exceptions... */ + /* else if... Feel free to add more cases here! */ + + if (sp->typecnt > 1) + (*fill_tzstate_from_rules)(sp, &startrule, &stoprule); + } + CloseLocale(ll); + } + CloseLibrary(LocaleBase); + } + me->pr_WindowPtr = old_window; + return valid; +} + +#ifdef ZIP +time_t time(time_t *tp) +{ + time_t t; + struct DateStamp ds; + DateStamp(&ds); + t = ds.ds_Tick / TICKS_PER_SECOND + ds.ds_Minute * 60 + + (ds.ds_Days + 2922) * SECSPERDAY; + t = mktime(gmtime(&t)); + /* gmtime leaves ds in the local timezone, mktime converts it to GMT */ + if (tp) *tp = t; + return t; +} +#endif /* ZIP */ + +#endif /* !FUNZIP && !UTIL */ + + +#if CRYPT || !defined(FUNZIP) + +/* sendpkt.c + * by A. Finkel, P. Lindsay, C. Sheppner + * returns Res1 of the reply packet + */ +/* +#include +#include +#include +#include +#include +#include +*/ + +LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs); + +LONG sendpkt(pid,action,args,nargs) +struct MsgPort *pid; /* process identifier (handler message port) */ +LONG action, /* packet type (desired action) */ + *args, /* a pointer to argument list */ + nargs; /* number of arguments in list */ +{ + + struct MsgPort *replyport, *CreatePort(UBYTE *, long); + void DeletePort(struct MsgPort *); + struct StandardPacket *packet; + LONG count, *pargs, res1; + + replyport = CreatePort(NULL,0L); + if( !replyport ) return(0); + + packet = (struct StandardPacket *)AllocMem( + (long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR); + if( !packet ) + { + DeletePort(replyport); + return(0); + } + + packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt); + packet->sp_Pkt.dp_Link = &(packet->sp_Msg); + packet->sp_Pkt.dp_Port = replyport; + packet->sp_Pkt.dp_Type = action; + + /* copy the args into the packet */ + pargs = &(packet->sp_Pkt.dp_Arg1); /* address of 1st argument */ + for( count=0; countsp_Pkt.dp_Res1; + + FreeMem((char *)packet,(long)sizeof(*packet)); + DeletePort(replyport); + + return(res1); + +} /* sendpkt() */ + +#endif /* CRYPT || !FUNZIP */ + + +#if CRYPT || (defined(UNZIP) && !defined(FUNZIP)) + +/* Agetch() reads one raw keystroke -- uses sendpkt() */ + +int Agetch(void) +{ + LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs); + struct Task *me = FindTask(NULL); + struct CommandLineInterface *cli = BADDR(((struct Process *) me)->pr_CLI); + BPTR fh = cli->cli_StandardInput; /* this is immune to < redirection */ + void *conp = ((struct FileHandle *) BADDR(fh))->fh_Type; + char longspace[8]; + long *flag = (long *) ((ULONG) &longspace[4] & ~3); /* LONGWORD ALIGNED! */ + UBYTE c; + + *flag = 1; + sendpkt(conp, ACTION_SCREEN_MODE, flag, 1); /* assume success */ + Read(fh, &c, 1); + *flag = 0; + sendpkt(conp, ACTION_SCREEN_MODE, flag, 1); + if (c == 3) /* ^C in input */ + Signal(me, SIGBREAKF_CTRL_C); + return c; +} + +#endif /* CRYPT || (UNZIP && !FUNZIP) */ + +#endif /* __amiga_filedate_c*/ diff --git a/amiga/flate.a b/amiga/flate.a new file mode 100644 index 0000000..a11bcca --- /dev/null +++ b/amiga/flate.a @@ -0,0 +1,513 @@ +;=========================================================================== +; Copyright (c) 1990-2005 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 +;=========================================================================== +; flate.a created by Paul Kienitz, 20 June 94. Last modified 30 Dec 2005. +; +; 68000 assembly language version of inflate_codes(), for Amiga. Prototype: +; +; int inflate_codes(__GPRO__ struct huft *tl, struct huft *td, +; unsigned bl, unsigned bd); +; +; Where __GPRO__ expands to "Uz_Globs *G," if REENTRANT is defined, +; otherwise to nothing. In the latter case G is a global variable. +; +; Define AZTEC to use the Aztec C macro version of getc() instead of the +; library getc() with FUNZIP. AZTEC is ignored if FUNZIP is not defined. +; +; Define NO_CHECK_EOF to not use the fancy paranoid version of NEEDBITS -- +; this is equivalent to removing the #define CHECK_EOF from inflate.c. +; +; Define INT16 if ints are short, otherwise it assumes ints are long. +; +; Define USE_DEFLATE64 if we're supporting Deflate64 decompression. +; +; Do NOT define WSIZE; it is always 32K or 64K depending on USE_DEFLATE64. +; You also do not need to define FUNZIP or SFX, if you create t:G_offs.a +; correctly (see below). +; +; ------ +; +; The following include file is generated from globals.h just before this +; is compiled, and gives us equates that give the offsets in Uz_Globs of +; the fields we use, which are: +; ulg bb +; unsigned int bk, wp +; (either array of unsigned char, or pointer to unsigned char) redirslide +; For regular UnZip but not fUnZip: +; int incnt, mem_mode +; uch *inptr +; For fUnZip: +; FILE *in +; It also defines a value SIZEOF_slide, which tells us whether the appropriate +; slide field in G (either area.Slide or redirect_pointer) is a pointer or an +; array instance. It is 4 in the former case and a large value in the latter. +; Lastly, this include will define CRYPT as 1 if appropriate and supply flag +; definitions for major compile options that may affect the layout of the +; globals structure and the functionality of the core decompression routines +; (currently FUNZIP, SFX, REENTRANT, DLL, NO_SLIDE_REDIR, USE_DEFLATE64). + + INCLUDE "t:G_offs.a" + +; struct huft is defined as follows: +; +; struct huft { +; uch e; /* number of extra bits or operation */ +; uch b; /* number of bits in this code or subcode */ +; union { +; ush n; /* literal, length base, or distance base */ +; struct huft *t; /* pointer to next level of table */ +; } v; +; }; /* sizeof(struct huft) == 6, or 8 if padded */ +; +; The G_offs include defines offsets h_e, h_b, h_v_n, and h_v_t in this +; struct, plus SIZEOF_huft. + + IFD REENTRANT + IFND FUNZIP +REENT_G equ 1 + ENDC + ENDC + +; These macros allow us to deal uniformly with short or long ints: + + IFD INT16 +MOVINT MACRO + move.w \1,\2 + ENDM +INTSIZE equ 2 + ELSE ; !INT16 +MOVINT MACRO + move.l \1,\2 + ENDM +INTSIZE equ 4 + ENDC + +; G.bb is the global buffer that holds bits from the huffman code stream, which +; we cache in the register variable b. G.bk is the number of valid bits in it, +; which we cache in k. The macros NEEDBITS(n) and DUMPBITS(n) have side effects +; on b and k. + + IFD REENT_G +G_SIZE equ 4 +G_PUSH MACRO ; this macro passes "__G__" to functions + move.l G,-(sp) + ENDM + ELSE + xref _G ; Uz_Globs +G_SIZE equ 0 +G_PUSH MACRO + ds.b 0 ; does nothing; the assembler dislikes MACRO ENDM + ENDM + ENDC ; REENT_G + +;; xref _mask_bits ; const unsigned mask_bits[17]; + IFD FUNZIP + IF CRYPT + xref _encrypted ; int -- boolean flag + xref _update_keys ; int update_keys(__GPRO__ int) + xref _decrypt_byte ; int decrypt_byte(__GPRO) + ENDC ; CRYPT + ELSE ; !FUNZIP + xref _memflush ; int memflush(__GPRO__ uch *, ulg) + xref _readbyte ; int readbyte(__GPRO) + ENDC ; FUNZIP + + xref _flush ; if FUNZIP: int flush(__GPRO__ ulg) + ; else: int flush(__GPRO__ uch *, ulg, int) + +; Here are our register variables. + +b equr d2 ; unsigned long +k equr d3 ; unsigned short <= 32 +e equr d4 ; unsigned int, mostly used as unsigned char +w equr d5 ; unsigned long (was short before deflate64) +n equr d6 ; unsigned long (was short before deflate64) +d equr d7 ; unsigned int, used as unsigned short + +t equr a2 ; struct huft * +lmask equr a3 ; ulg * +G equr a6 ; Uz_Globs * + +; Couple other items we need: + +savregs reg d2-d7/a2/a3/a6 + IFD USE_DEFLATE64 +WSIZE equ $10000 ; 64K... be careful not to treat as short! + ELSE +WSIZE equ $08000 ; 32K... be careful not to treat as negative! + ENDC +EOF equ -1 +INVALID equ 99 + +; inflate_codes() returns one of the following status codes: +; 0 OK +; 1 internal inflate error or EOF on input stream +; the following return codes are passed through from FLUSH() errors +; 50 (PK_DISK) "overflow of output space" +; 80 (IZ_CTRLC) "canceled by user's request" + +RET_OK equ 0 +RET_ERR equ 1 + + IFD FUNZIP +; This does getc(in). Aztec version is based on #define getc(fp) in stdio.h + + IFD AZTEC + xref __filbuf +GETC MACRO + move.l in(G),a0 + move.l (a0),a1 ; in->_bp + cmp.l 4(a0),a1 ; in->_bend + blo.s gci\@ + move.l a0,-(sp) + jsr __filbuf + addq #4,sp + bra.s gce\@ +gci\@: moveq #0,d0 ; must be valid as longword + move.b (a1)+,d0 + move.l a1,(a0) +gce\@: + ENDM + ELSE ; !AZTEC +GETC MACRO + xref _getc + move.l in(G),-(sp) + jsr _getc + addq #4,sp + ENDM + ENDC ; AZTEC + ENDC ; FUNZIP + +; Input depends on the NEXTBYTE macro. This exists in three different forms. +; The first two are for fUnZip, with and without decryption. The last is for +; regular UnZip with or without decryption. The resulting byte is returned +; in d0 as a longword, and d1, a0, and a1 are clobbered. + +; FLUSH also has different forms for UnZip and fUnZip. Arg must be a longword. +; The same scratch registers are trashed. + + IFD FUNZIP + +NEXTBYTE MACRO + GETC + IF CRYPT + tst.w _encrypted+INTSIZE-2 ; test low word if long + beq.s nbe\@ + MOVINT d0,-(sp) ; save thru next call + G_PUSH + jsr _decrypt_byte + eor.w d0,G_SIZE+INTSIZE-2(sp) ; becomes arg to update_keys + jsr _update_keys + addq #INTSIZE+G_SIZE,sp +nbe\@: + ENDC ; !CRYPT + IFGT 4-INTSIZE + ext.l d0 ; assert -1 <= d0 <= 255 + ENDC + ENDM + +FLUSH MACRO + move.l \1,-(sp) + G_PUSH + jsr _flush + addq #4+G_SIZE,sp + ENDM + + ELSE ; !FUNZIP + +NEXTBYTE MACRO + subq.w #1,incnt+INTSIZE-2(G) ; treat as short + bge.s nbs\@ + G_PUSH + jsr _readbyte + IFNE G_SIZE + addq #G_SIZE,sp + ENDC + IFGT 4-INTSIZE + ext.l d0 ; assert -1 <= d0 <= 255 + ENDC + bra.s nbe\@ +nbs\@: moveq #0,d0 + move.l inptr(G),a0 ; alt vers: move.b inptr(G),d0 + move.b (a0)+,d0 ; addq #1,inptr(G) + move.l a0,inptr(G) +nbe\@: + ENDM + +FLUSH MACRO + MOVINT #0,-(sp) ; unshrink flag: always false + move.l \1,-(sp) ; length + IFGT SIZEOF_slide-4 + pea redirslide(G) ; buffer to flush + ELSE + move.l redirslide(G),-(sp) + ENDC + G_PUSH + tst.w mem_mode+INTSIZE-2(G) ; test lower word if long + beq.s fm\@ + jsr _memflush ; ignores the unshrink flag + bra.s fe\@ +fm\@: jsr _flush +fe\@: lea 8+INTSIZE+G_SIZE(sp),sp + ENDM + + ENDC ; ?FUNZIP + +; Here are the two bit-grabbing macros, which in their NO_CHECK_EOF form are: +; +; #define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<>=(n);k-=(n);} +; +; Without NO_CHECK_EOF, NEEDBITS reads like this: +; +; {while((int)k<(int)(n)){\ +; int c=NEXTBYTE;if(c==EOF){\ +; if((int)k>=0)break;\ +; retval=1;goto cleanup_and_exit;}\ +; b|=((ulg)c)<= 0 +dspin: move.b (a1)+,(a0)+ + dbra d0,dspin + add.l e,w + add.l e,d + cmp.l #WSIZE,w + blo.s dnfl + FLUSH w + ext.l d0 ; does a test as it casts to long + bne return + moveq #0,w +dnfl: tst.l n ; need to do more sub-blocks? + bne docopy ; yes + moveq #0,e ; restore zeroness in upper bytes of e + bra main_loop ; break (newtop loop) + +nonleng: cmp.w #INVALID,e ; bottom of newtop loop -- misc. code + bne.s tailgo ; invalid code? + moveq #RET_ERR,d0 ; then fail + bra return +tailgo: and.w #$001F,e + NEEDBITS e + move.w e,d0 + asl.w #2,d0 + and.l (lmask,d0.w),d1 + IFNE SIZEOF_huft-8 + mulu #SIZEOF_huft,d1 + ELSE + asl.l #3,d1 + ENDC + move.l h_v_t(t),t + add.l d1,t + bra newtop + +finish: MOVINT w,wp(G) ; done: restore cached globals + MOVINT k,bk(G) + move.l b,bb(G) + moveq #RET_OK,d0 ; return "no error" +return: movem.l (sp)+,savregs + unlk a5 + rts diff --git a/amiga/makefile.azt b/amiga/makefile.azt new file mode 100644 index 0000000..c61a7cf --- /dev/null +++ b/amiga/makefile.azt @@ -0,0 +1,257 @@ +# Makefile for UnZip 5.53 using Manx Aztec C 5.2, last revised 25 Dec 06. +# Define EXTRA=xxx on the Make command line for e.g. -dUSE_UNSHRINK. + +EXTRA = + +DEFINES = -d AMIGA $(EXTRA) +VERNUMS = -d __VERSION__=5 -d __REVISION__=2 + +CC = cc +LD = ln + +LDLIBS = -lc16 + +# release version: +# ---------------- +CFLAGS = -ps -wcpr0u -sabfmnpu $(DEFINES) +# -ps means short ints, -wcpr0u is type checking, -sabfmnpu is optimizations.. +# Option flags MORE and ASM_* are now set in the Aztec section of amiga/amiga.h; +# it's cleaner, and that way any changes forces a recompile. +LDFLAGS = +q -m +# Linker arg -m suppresses warnings about overriding c.lib functions. + +# debug version: +# -------------- +CFLAGD = -ps -wcpr0u -bs -s0f0n $(DEFINES) +# -bs is include source debugging info, -s0f0n is avoid hard-to-debug optimizations +LDFLAGD = +q -m -g -w +# -g activates source-level debugging (a .dbg file), -w saves assembly-level symbols + +# the directory for object files: +O = obA/ + +OBJS = $(O)unzip.o $(O)envargs.o $(O)process.o $(O)extract.o \ + $(O)explode.o $(O)ubz2err.o $(O)unshrink.o $(O)unreduce.o \ + $(O)inflate.o $(O)match.o $(O)zipinfo.o $(O)list.o $(O)globals.o \ + $(O)crypt.o $(O)ttyio.o $(O)fileio.o $(O)crc32.o $(O)timezone.o \ + $(O)amiga.o $(O)crc_68.o $(O)flate.o + +XOBJS = $(O)unzip.xo $(O)process.xo $(O)extract.xo $(O)ubz2err.xo \ + $(O)inflate.xo $(O)match.xo $(O)globals.xo $(O)crypt.xo \ + $(O)ttyio.xo $(O)fileio.xo $(O)crc32.xo $(O)timezone.xo \ + $(O)amiga.xo $(O)crc_68.o $(O)flate.xo + +FOBJS = $(O)funzip.o $(O)inflate.fo $(O)crypt.fo $(O)ttyio.fo $(O)globals.fo \ + $(O)crc32.fo $(O)filedate.fo $(O)crc_68.o $(O)flate.fo + +DBJS = $(O)unzip.od $(O)envargs.od $(O)process.od \ + $(O)extract.od $(O)explode.od $(O)unshrink.od $(O)unreduce.od \ + $(O)inflate.od $(O)match.od $(O)zipinfo.od $(O)list.od $(O)globals.od \ + $(O)crypt.od $(O)ttyio.od $(O)fileio.od $(O)crc32.od $(O)timezone.od \ + $(O)amiga.od $(O)crc_68.o $(O)flate.o + +XDBJS = $(O)unzip.xd $(O)process.xd $(O)extract.xd \ + $(O)inflate.xd $(O)match.xd $(O)globals.xd $(O)crypt.xd \ + $(O)ttyio.xd $(O)fileio.xd $(O)crc32.xd $(O)timezone.xd \ + $(O)amiga.xd $(O)crc_68.o $(O)flate.xo + +FDBJS = $(O)funzip.od $(O)inflate.fd $(O)crypt.fd $(O)ttyio.fd $(O)globals.fd \ + $(O)crc32.fd $(O)filedate.fd $(O)crc_68.o $(O)flate.fo + + +.c.o : + $(CC) -o $@ $(CFLAGS) $*.c + +.c.xo: + $(CC) -o $@ -d SFX $(CFLAGS) $*.c + +.c.fo: + $(CC) -o $@ -d FUNZIP $(CFLAGS) $*.c + +.c.od : + $(CC) -o $@ $(CFLAGD) $*.c + +.c.xd: + $(CC) -o $@ -d SFX $(CFLAGD) $*.c + +.c.fd: + $(CC) -o $@ -d FUNZIP $(CFLAGD) $*.c + +# HERE WE GO: + +all : Unzip UnzipSFX fUnzip MakeSFX + +u : Unzip + +f : fUnzip + +x : UnzipSFX + +m : MakeSFX + +dall: Unzip.dbg UnzipSFX.dbg fUnzip.dbg MakeSFX.dbg + +ud : Unzip.dbg + +fd : fUnzip.dbg + +xd : UnzipSFX.dbg + +md : MakeSFX.dbg + + +Unzip : $(OBJS) + $(LD) $(LDFLAGS) -o Unzip $(OBJS) $(LDLIBS) + -@delete Unzip.dbg + +UnzipSFX : $(XOBJS) MakeSFX + $(LD) $(LDFLAGS) -o UnzipSFX $(XOBJS) $(LDLIBS) + -@delete UnzipSFX.dbg + +fUnzip : $(FOBJS) + $(LD) $(LDFLAGS) -o fUnzip $(FOBJS) $(LDLIBS) + -@delete fUnzip.dbg + +MakeSFX : amiga/makesfx.c + $(CC) $(CFLAGS) -o t:makesfx.o amiga/makesfx.c + $(LD) $(LDFLAGS) -o MakeSFX t:makesfx.o $(LDLIBS) + -@delete MakeSFX.dbg + -@delete t:makesfx.o + + +Unzip.dbg : $(DBJS) + $(LD) $(LDFLAGD) -o Unzip $(DBJS) $(LDLIBS) + +UnzipSFX.dbg : $(XDBJS) MakeSFX.dbg + $(LD) $(LDFLAGD) -o UnzipSFX $(XDBJS) $(LDLIBS) + +fUnzip.dbg : $(FDBJS) + $(LD) $(LDFLAGD) -o fUnzip $(FDBJS) $(LDLIBS) + +MakeSFX.dbg : amiga/makesfx.c + $(CC) $(CFLAGD) -o t:makesfx.o amiga/makesfx.c + $(LD) $(LDFLAGD) -o MakeSFX t:makesfx.o $(LDLIBS) + -@delete t:makesfx.o + + +clean : + -delete $(OBJS) + -delete $(XOBJS) + -delete $(FOBJS) + -delete $(DBJS) + -delete $(XDBJS) + -delete $(FDBJS) + -delete amiga/gbloffs amiga/Fgbloffs amiga/Xgbloffs + +cleaner : clean + -delete UnZip fUnZip UnZipSFX MakeSFX *.dbg + +# header dependencies: + +$(OBJS) $(XOBJS) $(FOBJS) : unzip.h unzpriv.h globals.h \ + amiga/amiga.h amiga/z-stat.h +$(DBJS) $(XDBJS) $(FDBJS) : unzip.h unzpriv.h globals.h \ + amiga/amiga.h amiga/z-stat.h + +$(O)crypt.o $(O)crypt.fo $(O)timezone.o $(O)ttyio.o $(O)ttyio.fo : zip.h +$(O)crypt.od $(O)crypt.fd $(O)timezone.od $(O)ttyio.od $(O)ttyio.fd : zip.h + +$(O)inflate.o $(O)inflate.fo $(O)inflate.od $(O)inflate.fd : inflate.h + +$(O)fileio.o $(O)fileio.od : ebcdic.h + +$(O)funzip.o $(O)funzip.od : crc32.h +$(O)crc32.o $(O)crc32.fo $(O)crc32.xo : crc32.h +$(O)crc32.od $(O)crc32.fd $(O)crc32.xd : crc32.h +$(O)crypt.o $(O)crypt.fo $(O)crypt.xo : crc32.h +$(O)crypt.od $(O)crypt.fd $(O)crypt.xd : crc32.h +$(O)extract.o $(O)extract.xo $(O)extract.od $(O)extract.xd : crc32.h +$(O)fileio.o $(O)fileio.xo $(O)fileio.od $(O)fileio.xd : crc32.h +$(O)process.o $(O)process.xo $(O)process.od $(O)process.xd : crc32.h + +$(O)crypt.o $(O)crypt.fo $(O)crypt.xo : crypt.h +$(O)crypt.od $(O)crypt.fd $(O)crypt.xd : crypt.h +$(O)ttyio.o $(O)ttyio.fo $(O)ttyio.xo : crypt.h +$(O)ttyio.od $(O)ttyio.fd $(O)ttyio.xd : crypt.h +$(O)unzip.o $(O)unzip.xo $(O)funzip.o : crypt.h +$(O)unzip.od $(O)unzip.xd $(O)funzip.od : crypt.h +$(O)fileio.o $(O)fileio.xo $(O)extract.o $(O)extract.xo : crypt.h +$(O)fileio.od $(O)fileio.xd $(O)extract.od $(O)extract.xd : crypt.h +$(O)inflate.o $(O)inflate.fo $(O)inflate.xo $(O)filedate.fo : crypt.h +$(O)inflate.od $(O)inflate.fd $(O)inflate.xd $(O)filedate.fd : crypt.h +amiga/gbloffs amiga/Fgbloffs amiga/Xgbloffs : crypt.h + +$(O)crypt.o $(O)crypt.fo $(O)crypt.xo : ttyio.h +$(O)crypt.od $(O)crypt.fd $(O)crypt.xd : ttyio.h +$(O)ttyio.o $(O)ttyio.fo $(O)ttyio.xo : ttyio.h +$(O)ttyio.od $(O)ttyio.fd $(O)ttyio.xd : ttyio.h +$(O)funzip.o $(O)fileio.o $(O)fileio.xo : ttyio.h +$(O)funzip.od $(O)fileio.od $(O)fileio.xd : ttyio.h + +$(O)timezone.o $(O)timezone.xo $(O)amiga.o $(O)amiga.xo : timezone.h +$(O)timezone.od $(O)timezone.xd $(O)amiga.od $(O)amiga.xd : timezone.h + +$(O)unzip.o $(O)unzip.xo $(O)unzip.od $(O)unzip.xd : unzvers.h consts.h + + +# Special case object files: + +$(O)amiga.o : amiga/filedate.c amiga/stat.c amiga/amiga.c unzvers.h + rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'" + $(CC) -o $(O)amiga.o $(CFLAGS) $(VERNUMS) amiga/amiga.c + +$(O)amiga.xo : amiga/filedate.c amiga/stat.c amiga/amiga.c unzvers.h + $(CC) -o $(O)amiga.xo $(CFLAGS) $(VERNUMS) -d SFX amiga/amiga.c + +$(O)amiga.od : amiga/filedate.c amiga/stat.c amiga/amiga.c unzvers.h + rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'" + $(CC) -o $(O)amiga.od $(CFLAGD) $(VERNUMS) amiga/amiga.c + +$(O)amiga.xd : amiga/filedate.c amiga/stat.c amiga/amiga.c unzvers.h + $(CC) -o $(O)amiga.xd $(CFLAGD) $(VERNUMS) -d SFX amiga/amiga.c + +$(O)crc_68.o : amiga/crc_68.a + as -n -o $(O)crc_68.o amiga/crc_68.a +# no debug version of crc_68 + +$(O)filedate.fo : amiga/filedate.c + $(CC) -o $(O)filedate.fo -d FUNZIP $(CFLAGS) amiga/filedate.c + +$(O)filedate.fd : amiga/filedate.c + $(CC) -o $(O)filedate.fd -d FUNZIP $(CFLAGD) amiga/filedate.c + +# The file t:G_offs.a is generated on the fly by programs we compile +# and then run, and then it's included into amiga/flate.a to provide +# definitions for it. There are no debug versions of flate.o. + +$(O)flate.o : amiga/flate.a amiga/gbloffs + amiga/gbloffs > t:G_offs.a + as -n -o $(O)flate.o -eINT16 amiga/flate.a + -@delete t:G_offs.a + +$(O)flate.fo : amiga/flate.a amiga/Fgbloffs + amiga/Fgbloffs > t:G_offs.a + as -n -o $(O)flate.fo -eINT16 -eFUNZIP -eAZTEC amiga/flate.a + -@delete t:G_offs.a + +$(O)flate.xo : amiga/flate.a amiga/Xgbloffs + amiga/Xgbloffs > t:G_offs.a + as -n -o $(O)flate.xo -eINT16 -eSFX amiga/flate.a + -@delete t:G_offs.a + +# Here are the programs that generate different versions of G_offs.a: + +amiga/gbloffs : gbloffs.c unzip.h unzpriv.h globals.h amiga/amiga.h crypt.h + $(CC) -o t:gbloffs.o $(CFLAGS) gbloffs.c + $(LD) $(LDFLAGS) -o amiga/gbloffs t:gbloffs.o $(LDLIBS) + -@delete t:gbloffs.o + +amiga/Fgbloffs : gbloffs.c unzip.h unzpriv.h globals.h amiga/amiga.h crypt.h + $(CC) -o t:gbloffs.o $(CFLAGS) -d FUNZIP gbloffs.c + $(LD) $(LDFLAGS) -o amiga/Fgbloffs t:gbloffs.o $(LDLIBS) + -@delete t:gbloffs.o + +amiga/Xgbloffs : gbloffs.c unzip.h unzpriv.h globals.h amiga/amiga.h crypt.h + $(CC) -o t:gbloffs.o $(CFLAGS) -d SFX gbloffs.c + $(LD) $(LDFLAGS) -o amiga/Xgbloffs t:gbloffs.o $(LDLIBS) + -@delete t:gbloffs.o diff --git a/amiga/makesfx.c b/amiga/makesfx.c new file mode 100644 index 0000000..ab591b2 --- /dev/null +++ b/amiga/makesfx.c @@ -0,0 +1,184 @@ +/* + 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 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 +*/ +/* MakeSFX: join UnZipSFX and a .zip archive into a single self-extracting */ +/* Amiga program. On most systems simple concatenation does the job but for */ +/* the Amiga a special tool is needed. By Paul Kienitz, no rights reserved. */ +/* This program is written portably, so if anyone really wants to they can */ +/* produce Amiga self-extracting programs on a non-Amiga. We are careful */ +/* not to mix Motorola-format longwords read from files with native long */ +/* integers. Not necessarily limited to use with only the Zip format -- */ +/* just combine any archive with any self-extractor program that is capable */ +/* of reading a HUNK_DEBUG section at the end as an archive. */ + +#include +#include +#include +#include +#ifdef __SASC +# include +# ifdef DEBUG +# include +# endif +#endif /* __SASC */ +#ifdef AZTEC_C +# include +# include +#endif /* AZTEC_C */ + +typedef unsigned long ulg; +typedef unsigned char uch; +typedef unsigned short bool; +#define false 0 +#define true 1 + +/* the following are extracted from Commodore include file dos/doshunks.h: */ +#define HUNK_NAME 1000L +#define HUNK_CODE 1001L +#define HUNK_DATA 1002L +#define HUNK_BSS 1003L +#define HUNK_RELOC32 1004L +#define HUNK_SYMBOL 1008L +#define HUNK_DEBUG 1009L +#define HUNK_END 1010L +#define HUNK_HEADER 1011L +#define HUNK_OVERLAY 1013L +#define HUNK_BREAK 1014L + +/* Convert a big-endian (Motorola) sequence of four bytes to a longword: */ +#define CHARS2LONG(b) (((ulg)(b)[0] << 24) | ((ulg)(b)[1] << 16) | \ + ((ulg)(b)[2] << 8) | ((ulg)(b)[3])) +/* b must be (uch *) in each of these. Now the reverse: */ +#define LONG2CHARS(b,l) ((b)[0] = (uch)((l) >> 24), (b)[1] = (uch)((l) >> 16),\ + (b)[2] = (uch)((l) >> 8), (b)[3] = (uch)(l)) + +#define COPYBUFFER 16384 + +ulg totalwritten = 0; + + +bool CopyData(FILE *out, FILE *inn, ulg archivesize, + char *outname, char *inname) +{ + static uch buf[COPYBUFFER]; + ulg written; + size_t chunk; + + if (archivesize) { + LONG2CHARS(buf, HUNK_DEBUG); + written = (archivesize + 3) / 4; + LONG2CHARS(buf + 4, written); + if (fwrite(buf, 1, 8, out) < 8) { + printf("Error writing in-between data to %s\n", outname); + return false; + } + totalwritten += 8; + } + written = 0; + do { + chunk = fread(buf, 1, COPYBUFFER, inn); + if (ferror(inn)) { + printf("Error reading data from %s\n", inname); + return false; + } + if (!archivesize && !written) { /* true only for first block read */ + if (CHARS2LONG(buf) != HUNK_HEADER) { + printf("%s is not an Amiga executable.\n", inname); + return false; + } + } + if (fwrite(buf, 1, chunk, out) < chunk) { + printf("Error writing %s to %s\n", archivesize ? "archive data" : + "self-extractor code", outname); + return false; + } + written += chunk; + totalwritten += chunk; + } while (!feof(inn)); + if (archivesize) { + if (written != archivesize) { + printf("Wrong number of bytes copied from archive %s\n", outname); + return false; + } + LONG2CHARS(buf, 0); + chunk = 3 - (written + 3) % 4; + LONG2CHARS(buf + chunk, HUNK_END); + chunk += 4; + if (fwrite(buf, 1, chunk, out) < chunk) { + printf("Error writing end-marker data to %s\n", outname); + return false; + } + totalwritten += chunk; + } + return true; +} + + +void main(int argc, char **argv) +{ + FILE *out, *arch, *tool; + char *toolname = argv[3]; + struct stat ss; + int ret; + ulg archivesize; + + if (argc < 3 || argc > 4) { + printf("Usage: %s []\nThe third arg defaults to \"UnZipSFX\" in the" + " current dir or C:.\n", argv[0]); + exit(20); + } + if (!(arch = fopen(argv[2], "rb"))) { + printf("Could not find archive file %s\n", argv[2]); + exit(10); + } + if (stat(argv[2], &ss) || !(archivesize = ss.st_size)) { + fclose(arch); + printf("Could not check size of archive %s, or file is empty.\n", + argv[2]); + exit(10); + } + if (argc < 4) + toolname = "UnZipSFX"; + if (!(tool = fopen(toolname, "rb"))) { + BPTR lk = Lock("C:", ACCESS_READ); + BPTR ocd = lk ? CurrentDir(lk) : 0; + if (!(tool = fopen(toolname, "rb"))) { + fclose(arch); + printf("Could not find self-extractor program %s\n", toolname); + if (lk) + UnLock(CurrentDir(ocd)); + exit(10); + } + if (lk) + UnLock(CurrentDir(ocd)); + } + if (!(out = fopen(argv[1], "wb"))) { + fclose(arch); + fclose(tool); + printf("Could not create output file %s\n", argv[1]); + exit(10); + } + ret = CopyData(out, tool, 0, argv[1], toolname) + && CopyData(out, arch, archivesize, argv[1], argv[2]) ? 0 : 10; + fclose(out); + fclose(arch); + fclose(tool); + if (ret) { + printf("Deleting %s\n", argv[1]); + remove(argv[1]); + } else + printf("%s successfully written, size %lu bytes.\n", + argv[1], totalwritten); + exit(ret); +} + + +#if (defined(AZTEC_C) && defined(MCH_AMIGA)) +void _wb_parse(void) { } /* avoid unneeded infrastructure */ +#endif diff --git a/amiga/smakefile b/amiga/smakefile new file mode 100644 index 0000000..48818f9 --- /dev/null +++ b/amiga/smakefile @@ -0,0 +1,629 @@ +#=========================================================================== +# Makefile for UnZip, ZipInfo, fUnZip, MakeSFX AMIGA SAS/C Version 6.58 +# Version: 5.53 last revised: 25 Dec 06 +#=========================================================================== +# from John Bush +# or: + +# updated for SAS/C Version 6.56+ and AmigaDOS 3.1 (V40) +# by Haidinger Walter + +# additional supplements and maintenance by Paul Kienitz + +# This makefile should work with at least AmigaDOS 2.04 (V37) (not tested) +# and will probably not work with AmigaDOS 1.3 (V34) + +# If you have any improvements, critics or else please feel free to mail. +# Any response is appreciated. Haidinger Walter + +# Available targets: +# all builds all executables below +# unzip builds unzip executable +# unzipsfx builds unzipsfx executable +# funzip builds funzip executable +# makesfx builds makesfx executable +# clean remove all files created by the compilation +# spotless like clean target but removes binaries too + + +########################## +# USER MACRO DEFINITIONS # +########################## + +# Set the processor to generate code for UnZip and fUnZip. Specify one of: +# ANY 68000 68010 68020 68030 68040 68060 (Default: ANY or 68000) + +# Use of the assembly versions is not supported yet since some of the asm +# source file do not assemble with 68000 instructions. +# Any help is appreciated of course. + +CUSECPU = ANY + +# Uncomment both CUTIL and LUTIL to make use of utility.library of OS 2.04+ +# The utility.library is *not* used for UnZipSFX to ensure maximum portability +# between the different Amiga systems (minimal config: 68000 and OS 1.2). +# You can change this by adding the $(LUTIL) macro in the UnZipSFX linking +# rules (See below: Final output targets, UnZipSFX:). +# WARNINGS when using the utility library: +# 1. All Executables will *only* work with AmigaDOS 2.04 (v37) or higher. +# 2. You *need not* compile/link with short-integers using the +# utility.library. It will crash your machine. See Libraries below. +# +# Default: commented (not used) +# +#CUTIL = UTILLIB DEFINE=_UTILLIB +#LUTIL = WITH SC:LIB/utillib.with # include necessary linker defines + + +# Choose one stack-handling method (default=faster) +# StackExtend: Dynamic runtime stack extension. You won't notice stack overflows. +# StackCheck: On a stack overflow a requester appears which allows you to exit. +# Note that either stack watching will slow down your executable because of the +# extra code run on each function entry. On the other hand, you won't crash +# anymore due to stack overflows. However, you should not have *any* stack +# problems with info-zip if you raise your stack to 20000 (which I'd +# recommend as a minimum default stack for all applications) or more using the +# shell stack command. Type 'Stack 20000' or add it to your S:Shell-Startup. +# BTW: Typing 'Stack' prints your current stack size. +# +CSTACK = NOSTACKCHECK STACKEXTEND # slow, but always works +#CSTACK = STACKCHECK NOSTACKEXTEND # slow, requester & graceful exit +#CSTACK = NOSTACKCHECK NOSTACKEXTEND # faster but relies on larger stack (>=10K) + +# +# LIBRARIES +# --------- + +# Choose one DATAOPTS , SASLIB and LSTARTUP +# Always comment/uncomment all macros of a set. + +# Library to use with near data and 2-byte integers +# Notes: o slower than 4-byte integers with 68000 cpu +# o *not* recommended due to poor overall performance +# o see comment in amiga/osdep.h +#DATAOPTS = DATA=NEAR SHORTINTEGERS DEF=_NEAR_DATA +#SASLIB = scs +#LSTARTUP = cres.o + +# Library to use with near data and 4-byte integers (DEFAULT) +# *** use this with the utility.library *** +DATAOPTS = DATA=NEAR DEF=_NEAR_DATA +SASLIB = sc +LSTARTUP = cres.o + +# Library to use with far data and 2-byte integers +# use if DYN_ALLOC is not defined +# old default - far data always works but is slower +#DATAOPTS = DATA=FAR SHORTINTEGERS DEF=_FAR_DATA +#SASLIB = scsnb +#LSTARTUP = c.o + +# Library to use with far data and 4-byte integers +# if everything else fails: try this +#DATAOPTS = DATA=FAR DEF=_FAR_DATA +#SASLIB = scnb +#LSTARTUP = c.o + + +# +# DEBUGGING +# --------- + +# Default: No debugging information added. +# The two macros below will be overwritten if you choose to add +# debug info, therefore need to comment. +CDBG = NODEBUG NOPROFILE NOCOVERAGE # default: no debug info +LDBG = STRIPDEBUG # default: no debug info + +# Compiler and loader debug flags. Uncomment as needed. Recomment when done. +# Optimization disabled for faster compilation (by using NOOPT) +#CDBG1 = DEF=DEBUG DEF=DEBUG_TIME # enables Info-ZIP's debug output + +# Enable profiling and coverage when desired. Option COVERAGE commented +# seperately because running coverage may corrupt your drive in case of a +# system crash since a file 'cover.dat' is created in your working directory. +# Note that the use of COVERAGE forces the use of the c.o startup module. +#CDBG2 = PROFILE +#CDBG3 = COVERAGE # must use c.o startup code: +#LSTARTUP = c.o # Uncomment *only* when you use COVERAGE + +# *Uncomment* _HERE_ macros CDBG and LDBG to include debugging information +#CDBG = $(CDBG1) $(CDBG2) $(CDBG3) ADDSYM DEBUG=FULLFLUSH STACKCHECK NOOPT +#LDBG = ADDSYM +# Optional use of memwatch.library which can be found in your +# sc:extras/memlib directory. Please read the short docs (memlib.doc). +# Note that memlib has a small bug: MWTerm() displays always the first entry. +# Get the latest version from aminet (dev/debug/memlib.lha) or +# contact me to get the patch. Uncomment all macros to use. +#CMEMLIB = DEFINE=MWDEBUG=1 # define to enable library +#LMEMLIB = SC:LIB/memwatch.lib # path to library +#LSTARTUP = c.o # must use c.o with memlib! + + +# +# MAPPING +# ------- + +# Map filenames used when mapping (no need to comment) +# +MAPFS = unzip.map # UnZip map filename +MAPFX = unzipsfx.map # UnZipSFX map filename +MAPFF = funzip.map # fUnZip map filename +MAPFM = makesfx.map # MakeSFX map filename + +# Map file output: Uncomment to highlight and bold headings. +# +#MAPFSTYLE = FANCY + +# Map flags for each EXECUTABLE. Uncomment to enable mapping. +# For map options please refer to: +# SAS/C v6 manual, volume 1: user's guide, chapter 8, page 136: map +# Default: all options enabled: f,h,l,o,s,x +# |-> options start here +#LMAPS = $(MAPFSTYLE) MAP $(MAPFS) f,h,l,o,s,x # UnZip maps +#LMAPX = $(MAPFSTYLE) MAP $(MAPFX) f,h,l,o,s,x # UnZipSFX maps +#LMAPF = $(MAPFSTYLE) MAP $(MAPFF) f,h,l,o,s,x # fUnZip maps +#LMAPM = $(MAPFSTYLE) MAP $(MAPFM) f,h,l,o,s,x # MakeSFX maps + + +# +# LISTINGS +# -------- + +# Listfile-extensions for each executable (enter *with* dot) +# +LISTEXTS = .lst # extension for UnZip and MakeSFX listfiles +LISTEXTX = .xlst # extension for UnZipSFX listfiles +LISTEXTF = .flst # extension for fUnZip listfiles + + +# List files and cross references for each OBJECT. +# Add/remove flags as needed. All listed by default. +# Use LISTINCLUDES only to determine the dependencies for smake +# +CLISTOPT = LISTHEADERS LISTMACROS # LISTSYSTEM LISTINCLUDES +CXREFOPT = XHEAD XSYS +# +# Uncomment to enable listing (default: commented) +# *** WARNING: List files require *lots* of disk space! +# +#CLIST = LIST $(CLISTOPT) +#CXREF = XREF $(CXREFOPT) + + +# +# SUPPRESSED COMPILER WARNINGS +# ---------------------------- + +# Compiler warnings to ignore +# +# Warning 105 : module does not define any externally-known symbols +# Warning 304 : Dead assignment eliminated... +# Note 306 : ...function inlined... +# Warning 317 : possibly uninitialized variable... +# Comment to enable. +# +CIGNORE = IGNORE=105,304,306,317 + + +# +# OBJECT EXTENSIONS +# + +# Extensions used for objects of each executeable. +# Transformation rules require unique extensions. +# Enter *with* dot. +# +O = .o # general extension for objects +OX = .xo # extension for special UnZipSFX objects +OF = .fo # extension for special fUnZip objects + + +# Filename used to store converted options from environment variable +# LOCAL_UNZIP. Default: scoptions_local_unzip +# +CWITHOPT = scoptions_local_unzip + + +# Filenames to store compiler options to prevent command line overflow +# +# Options file for UnZip and fUnZip +CFILEC = scoptions-unzip +# Options file for UnZipSFX +CFILEX = scoptions-unzipsfx +# Special options for MakeSFX +CFILEM = scoptions-makesfx + + +# Temp filenames for object lists to load using linker "WITH" command. +# +OBJLISTS = unzip_objlist.with # UnZip object list +OBJLISTX = unzipsfx_objlist.with # UnZipSFX object list +OBJLISTF = funzip_objlist.with # fUnZip object list +OBJLISTM = makesfx_objlist.with # MakeSFX object list + + +# Filenames to store linker options +# +LWITHS = unzip.lnk # UnZip linker options +LWITHX = unzipsfx.lnk # UnZipSFX linker options +LWITHF = funzip.lnk # fUnZip linker options +LWITHM = makesfx.lnk # MakeSFX linker options + + +###################################### +# NOTHING TO CHANGE BEYOND HERE ... # +###################################### + + +# Compiler definitions +# +CC = sc +# +# Optimizer flags +# +OPTPASSES = 6 # set number of global optimizer passes +# +OPT1 = OPT OPTINL OPTINLOCAL OPTTIME OPTLOOP OPTSCHED +OPT2 = OPTCOMP=$(OPTPASSES) OPTDEP=$(OPTPASSES) OPTRDEP=$(OPTPASSES) +OPT = $(OPT1) $(OPT2) + +# Compiler flags +# +# cpu flags for UnZip and fUnZip +CCPUOPTSF = CPU=$(CUSECPU) $(CUTIL) +# cpu flags for UnzipSFX and MakeSFX (ensures portability to all Amigas) +CCPUOPTXM = CPU=ANY + +CDEFINES = $(CMEMLIB) $(CDEFINES) DEF=AMIGA DEF=PROTO +COPTIONS = CODE=NEAR NMINC VERBOSE STRINGMERGE PARAMETERS=BOTH +COPTIONS = $(COPTIONS) ERRORREXX NOERRORCONSOLE MEMSIZE=HUGE $(CLIST) $(CXREF) +COPTIONS = $(COPTIONS) $(CSTACK) STRICT UNSCHAR NOICONS +COPTIONS = $(COPTIONS) $(CIGNORE) $(OPT) $(CDBG) +# common compiler flags +CFLAGSC = $(CDEFINES) $(DATAOPTS) $(COPTIONS) +# special compiler flags with $(DATAOPTS) excluded +CFLAGSS = $(CDEFINES) $(COPTIONS) + +# Linker definitions +# See SASLIB definition above +# +LD = slink +# special linker flags for UnZip to create pure (i.e. resident) binary. +LDFLAGSS = FROM SC:LIB/$(LSTARTUP) +# common linker flags for all other executeables +LDFLAGSC = FROM SC:LIB/c.o + +LDFLAGS2 = NOICONS $(LDBG) +# special linker flags to select library set above +LIBFLAGSS = LIB $(LMEMLIB) SC:LIB/$(SASLIB).lib SC:LIB/amiga.lib +# common linker flags +LIBFLAGSC = LIB $(LMEMLIB) SC:LIB/sc.lib SC:LIB/amiga.lib + + +################## +# TARGET OBJECTS # +################## + + +# UnZip Objects +OBJS1 = unzip$(O) crc32$(O) crypt$(O) envargs$(O) explode$(O) +OBJS2 = extract$(O) fileio$(O) globals$(O) list$(O) inflate$(O) match$(O) +OBJS3 = process$(O) ttyio$(O) ubz2err$(O) unreduce$(O) unshrink$(O) zipinfo$(O) +OBJSA = amiga$(O) timezone$(O) +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJSA) + +# UnZipSFX Objects +OBJX1 = unzip$(OX) extract$(OX) inflate$(OX) match$(OX) process$(OX) +OBJXI = crypt$(OX) crc32$(OX) fileio$(OX) globals$(OX) ttyio$(OX) ubz2err$(OX) +OBJXA = amiga$(OX) timezone$(OX) +OBJX = $(OBJX1) $(OBJXI) $(OBJXA) + +# fUnZip Objects +OBJF1 = funzip$(O) +OBJF2 = crc32$(OF) crypt$(OF) globals$(OF) inflate$(OF) ttyio$(OF) +OBJFA = filedate$(OF) stat$(O) +OBJF = $(OBJF1) $(OBJF2) $(OBJFA) + +# MakeSFX Objects +OBJM = makesfx$(O) + +# Common header files +UNZIP_H1 = unzip.h unzpriv.h globals.h +UNZIP_HA = amiga/amiga.h amiga/z-stat.h +UNZIP_H = $(UNZIP_H1) $(UNZIP_HA) + +# Output targets +UNZIPS = UnZip UnZipSFX fUnZip MakeSFX + + +####################################### +# DEFAULT TARGET AND PROCESSING RULES # +####################################### + +all: request flush $(UNZIPS) + +# UnZip transformation rules +# +.c$(O) : + $(CC) WITH=$(CFILEC) LISTFILE=$>$(LISTEXTS) OBJNAME=$@ $*.c + +# UnZipSFX transformation rules +# +.c$(OX): + $(CC) DEF=SFX WITH=$(CFILEC) LISTFILE=$>$(LISTEXTX) OBJNAME=$@ $*.c + +# fUnZip transformation rules +# +.c$(OF): + $(CC) DEF=FUNZIP WITH=$(CFILEC) LISTFILE=$>$(LISTEXTF) OBJNAME=$@ $*.c + + +######################### +# Final output targets. # +######################### + +unzip: local_unzip CommonFlags $(OBJS) + @Echo "$(OBJS)" >$(OBJLISTS) + Type $(OBJLISTS) +# ----- +# Note: Change $(LDFLAGSS) to $(LDFLAGSC) if DYN_ALLOC is *not* defined. +# ----- + @Echo "$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTS) $(LIBFLAGSS) " \ + "$(LDFLAGS2) $(LMAPS)" >$(LWITHS) + Type $(LWITHS) + $(LD) TO UnZip WITH $(LWITHS) + +funzip: local_unzip CommonFlags $(OBJF) + @Echo "$(OBJF)" >$(OBJLISTF) + Type $(OBJLISTF) + @Echo "$(LDFLAGSC) $(LUTIL) WITH $(OBJLISTF) $(LIBFLAGSS) " \ + "$(LDFLAGS2) $(LMAPF)" >$(LWITHF) + Type $(LWITHF) + $(LD) TO fUnZip WITH $(LWITHF) + +unzipsfx: local_unzip SFXFlags $(OBJX) + @Echo "$(OBJX)" >$(OBJLISTX) + Type $(OBJLISTX) +# ---- +# Note: Insert $(LUTIL) here, to use utility library with UnZipSFX. +# ----- vvvvvvv + @Echo "$(LDFLAGSC) WITH $(OBJLISTX) $(LIBFLAGSS) " \ + "$(LDFLAGS2) $(LMAPX)" >$(LWITHX) + Type $(LWITHX) + $(LD) TO UnZipSFX WITH $(LWITHX) + + +makesfx: MakeSFXFlags $(OBJM) + @Echo "$(OBJM)" >$(OBJLISTM) + Type $(OBJLISTM) + @Echo "$(LDFLAGSC) $(LUTIL) WITH $(OBJLISTM) $(LIBFLAGSC) " \ + "$(LDFLAGS2) $(LMAPM)" >$(LWITHM) + Type $(LWITHM) + # never use short-integers with MakeSFX ! + $(LD) TO MakeSFX WITH $(LWITHM) + +clean: + -Delete >nil: $(OBJS) quiet + -Delete >nil: $(OBJX) quiet + -Delete >nil: $(OBJF) quiet + -Delete >nil: $(OBJM) quiet + -Delete >nil: $(OBJLISTS) $(OBJLISTX) $(OBJLISTF) $(OBJLISTM) quiet + -Delete >nil: $(MAPFS) $(MAPFX) $(MAPFF) $(MAPFM) quiet + -Delete >nil: \#?$(LISTEXTS) \#?$(LISTEXTX) \#?$(LISTEXTF) quiet + -Delete >nil: $(CWITHOPT) $(CFILEC) $(CFILEX) $(CFILEM) quiet + -Delete >nil: SCOPTIONS SASCOPTS quiet + -Delete >nil: $(LWITHS) $(LWITHX) $(LWITHF) $(LWITHM) quiet + -Delete >nil: \#?.q.?? \#?.tmp \#?.cov quiet + +spotless: clean + -Delete >nil: $(UNZIPS) quiet + + +# UnZip dependencies: +# (objects not needed by Amiga port are commented) + +# special rule for adding Amiga internal version number to UnZip +amiga$(O): amiga/amiga.c amiga/filedate.c amiga/stat.c $(UNZIP_H) crypt.h timezone.h env:Workbench +stat$(O): amiga/stat.c amiga/z-stat.h +filedate$(O): amiga/filedate.c crypt.h timezone.h +api$(O): api.c $(UNZIP_H) unzvers.h #zlib.h +apihelp$(O): apihelp.c $(UNZIP_H) unzvers.h +crc32$(O): crc32.c $(UNZIP_H) zip.h crc32.h +crypt$(O): crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +envargs$(O): envargs.c $(UNZIP_H) +explode$(O): explode.c $(UNZIP_H) +extract$(O): extract.c $(UNZIP_H) crc32.h crypt.h +fileio$(O): fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +globals$(O): globals.c $(UNZIP_H) +inflate$(O): inflate.c $(UNZIP_H) inflate.h #zlib.h +list$(O): list.c $(UNZIP_H) +match$(O): match.c $(UNZIP_H) +process$(O): process.c $(UNZIP_H) crc32.h +timezone$(O): timezone.c $(UNZIP_H) zip.h timezone.h +ttyio$(O): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ubz2err$(O): ubz2err.c $(UNZIP_H) +unreduce$(O): unreduce.c $(UNZIP_H) +unshrink$(O): unshrink.c $(UNZIP_H) +unzip$(O): unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h #zlib.h +#unzipstb$(O): unzipstb.c $(UNZIP_H) unzvers.h +zipinfo$(O): zipinfo.c $(UNZIP_H) + + +# UnZipSFX dependencies: +# +# special rule for adding Amiga internal version number to UnZipSFX +amiga$(OX): amiga/amiga.c amiga/filedate.c amiga/stat.c $(UNZIP_H) crypt.h timezone.h +unzip$(OX): unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +crc32$(OX): crc32.c $(UNZIP_H) zip.h crc32.h +crypt$(OX): crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +extract$(OX): extract.c $(UNZIP_H) crc32.h crypt.h +fileio$(OX): fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +globals$(OX): globals.c $(UNZIP_H) +inflate$(OX): inflate.c $(UNZIP_H) inflate.h #zlib.h +match$(OX): match.c $(UNZIP_H) +process$(OX): process.c $(UNZIP_H) crc32.h +timezone$(OX): timezone.c $(UNZIP_H) zip.h timezone.h +ttyio$(OX): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ubz2err$(OX): ubz2err.c $(UNZIP_H) + + +# fUnZip dependencies: +# +funzip$(O): funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h +crc32$(OF): crc32.c $(UNZIP_H) zip.h crc32.h +crypt$(OF): crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +globals$(OF): globals.c $(UNZIP_H) +inflate$(OF): inflate.c $(UNZIP_H) inflate.h crypt.h #zlib.h +ttyio$(OF): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +filedate$(OF): amiga/filedate.c crypt.h + + +# MakeSFX dependencies +# +# special transformation rules to never use shortintegers: +makesfx$(O): amiga/makesfx.c + $(CC) WITH=$(CFILEM) LISTFILE=$>$(LISTEXTS) OBJNAME=$@ $*.c + + +######################## +# DEPENDECIES END HERE # +######################## + +# flush all libraries to provide more mem for compilation +flush: + @Avail flush >nil: + +# write common compiler flags to file and echo to user +CommonFlags: + @Echo "$(CFLAGSC)" "$(CCPUOPTSF)" >$(CFILEC) + @Type "$(CWITHOPT)" >>$(CFILEC) + -Type $(CFILEC) + +SFXFlags: + @Echo "$(CFLAGSC)" "$(CCPUOPTXM)" >$(CFILEX) + @Type "$(CWITHOPT)" >>$(CFILEX) + -Type $(CFILEX) + +# write special MakeSFX flags +MakeSFXFlags: + @Echo "$(CFLAGSS) $(CCPUOPTXM) DATA=NEAR NOSHORTINTEGERS" >$(CFILEM) + # not really needed but if someday used: + @Type "$(CWITHOPT)" >>$(CFILEM) + -Type $(CFILEM) + + +# special rule for adding Amiga internal version number to amiga.c +amiga$(O): + rx > env:VersionDate "say '""'translate(date('E'),'.','/')'""'" + $(CC) WITH=$(CFILEC) LISTFILE=$>$(LISTEXTS) OBJNAME=$@ $*.c + -Delete env:VersionDate + + +# needed in amiga/amiga.c +# should be set in startup-sequence, but just in case: +# (only works with OS 2.04 and above) + +env\:WorkBench: + @Execute < < (Workbench_smk.tmp) + FailAt 21 + If not exists ENV:Workbench + Version >nil: + SetEnv Workbench $$Workbench + Endif + < + + +# ################# +# ### LOCAL_UNZIP ### +# ################# +# +# Read environment variable LOCAL_UNZIP and convert options from old Lattice +# v5 to new SAS/C v6 format. You may also use the new DEFINE= syntax but +# be sure not to mix v5 and v6 options, otherwise lctosc will be confused. +# +# e.g.: to define FOO_ONE and FOO_TWO enter: +# +# SetEnv LOCAL_UNZIP "-DFOO_ONE -DFOO_TWO" +# +# To make this permanent, i.e. survive an reboot, put the statement into +# your startup-sequence or (for AmigaDOS 2.0 or higher only) make sure +# LOCAL_UNZIP is stored in the ENVARC: directory too. To do this, simply +# copy the file from ENV: to ENVARC: +# Copy ENV:LOCAL_UNZIP ENVARC: +# +# For a list of all valid non-standard compilation options see the INSTALL +# file in the root zip tree. Please read the notes there before using the +# non-standard options. +# +# e.g.: To use the non-standard timezone environment variable "INFOZIP_TZ" +# (or another arbitary name) instead of "TZ", type in your shell: +# +# Setenv LOCAL_UNZIP "-DTZ_ENVVAR=*"INFOZIP_TZ*"" +# +# Note that you need to escape the quotes of INFOZIP_TZ with leading stars. +# To verify that LOCAL_UNZIP has been saved correctly, use the Getenv command: +# +# Getenv LOCAL_UNZIP +# +# ...should display: +# +# -DTZ_ENVVAR="INFOZIP_TZ" +# + +local_unzip: + @Execute < < (Local_UnZip_smk.tmp) + Failat 21 + Echo "" + If exists ENV:LOCAL_UNZIP + Echo "Using environment variable LOCAL_UNZIP !" + Echo "LOCAL_UNZIP: " NOLINE + GetEnv LOCAL_UNZIP + Copy >NIL: ENV:LOCAL_UNZIP SASCOPTS + Else + Echo "You could use envvar LOCAL_UNZIP to set your special compilation options." + Echo "See the makefile for more information (LOCAL_UNZIP section)." + Delete >nil: SASCOPTS quiet + Endif + Echo "" + ; Do not remove the lctosc command! If LOCAL_UNZIP is unset, an + ; empty file is created which needed by CommonFlags ! + ; Moreover, lctosc also accepts new v6 options, i.e. only changes + ; known v5 options. Try `lctosc -Dfoo' and `lctosc DEFINE=foo'. + ; However, you *must not* mix v5 and v6 options! + lctosc > $(CWITHOPT) + ; Now make sure that env:sc/scoptions are NOT used + ; we just create an empty file. The options are stored elsewhere. + Echo > SCOPTIONS "" NOLINE + < + + + +# Echo request to the user +# +request: + @Echo "" + @Echo " This makefile is for use with SAS/C version 6.58." + @Echo " If you still have an older version, please upgrade!" + @Echo " Patches are available on the Aminet under biz/patch/sc\#?." + @Echo "" + @Echo " Just a simple request..." + @Echo " Please give me a mail that you compiled whether you encounter any errors" + @Echo " or not. I'd just like to know how many Amiga users actually make use of" + @Echo " this makefile." + @Echo " If you mail me, I'll put you on my mailing-list and notify you whenever" + @Echo " new versions of Info-Zip are released." + @Echo " Have a look at the makefile for changes like CPU type, UtilLib, Stack, etc." + @Echo " Feel free to mail comments, suggestions, critics..." + @Echo " Enjoy Info-Zip !" + @Echo " Haidinger Walter, " + @Echo "" + +# Echo help in case of an error +# +.ONERROR: + @Echo "" + @Echo "[sigh] An error running this makefile was detected." + @Echo "This message may also appear if you interrupted smake by pressing CTRL-C." + @Echo "Contact Info-ZIP authors at Zip-Bugs@lists.wku.edu or me for help." + @Echo "Haidinger Walter, " diff --git a/amiga/stat.c b/amiga/stat.c new file mode 100644 index 0000000..6075c21 --- /dev/null +++ b/amiga/stat.c @@ -0,0 +1,293 @@ +/* + 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 +*/ +/* Here we have a handmade stat() function because Aztec's c.lib stat() */ +/* does not support an st_mode field, which we need... also a chmod(). */ + +/* This stat() is by Paul Wells, modified by Paul Kienitz. */ +/* Originally for use with Aztec C >= 5.0 and Lattice C <= 4.01 */ +/* Adapted for SAS/C 6.5x by Haidinger Walter */ + +/* POLICY DECISION: We will not attempt to remove global variables from */ +/* this source file for Aztec C. These routines are essentially just */ +/* augmentations of Aztec's c.lib, which is itself not reentrant. If */ +/* we want to produce a fully reentrant UnZip, we will have to use a */ +/* suitable startup module, such as purify.a for Aztec by Paul Kienitz. */ + +#ifndef __amiga_stat_c +#define __amiga_stat_c + +#include +#include +#include "amiga/z-stat.h" /* fake version of stat.h */ +#include + +#ifdef AZTEC_C +# include +# include +# include +# include +# include +# include +#endif +#ifdef __SASC +# include /* SAS/C dir function prototypes */ +# include +# include +# include +#endif + +#ifndef SUCCESS +# define SUCCESS (-1) +# define FAILURE (0) +#endif + + +void close_leftover_open_dirs(void); /* prototype */ + +static DIR *dir_cleanup_list = NULL; /* for resource tracking */ + +/* CALL THIS WHEN HANDLING CTRL-C OR OTHER UNEXPECTED EXIT! */ +void close_leftover_open_dirs(void) +{ + while (dir_cleanup_list) + closedir(dir_cleanup_list); +} + + +unsigned short disk_not_mounted; + +extern int stat(const char *file, struct stat *buf); + +stat(file,buf) +const char *file; +struct stat *buf; +{ + + struct FileInfoBlock *inf; + BPTR lock; + time_t ftime; + struct tm local_tm; + + if( (lock = Lock((char *)file,SHARED_LOCK))==0 ) + /* file not found */ + return(-1); + + if( !(inf = (struct FileInfoBlock *)AllocMem( + (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) ) + { + UnLock(lock); + return(-1); + } + + if( Examine(lock,inf)==FAILURE ) + { + FreeMem((char *)inf,(long)sizeof(*inf)); + UnLock(lock); + return(-1); + } + + /* fill in buf */ + buf->st_dev = + buf->st_nlink = + buf->st_uid = + buf->st_gid = + buf->st_rdev = 0; + buf->st_ino = inf->fib_DiskKey; + buf->st_blocks = inf->fib_NumBlocks; + buf->st_size = inf->fib_Size; + + /* now the date. AmigaDOS has weird datestamps--- + * ds_Days is the number of days since 1-1-1978; + * however, as Unix wants date since 1-1-1970... + */ + + ftime = + (inf->fib_Date.ds_Days * 86400 ) + + (inf->fib_Date.ds_Minute * 60 ) + + (inf->fib_Date.ds_Tick / TICKS_PER_SECOND ) + + (86400 * 8 * 365 ) + + (86400 * 2 ); /* two leap years */ + + /* tzset(); */ /* this should be handled by mktime(), instead */ + /* ftime += timezone; */ + local_tm = *gmtime(&ftime); + local_tm.tm_isdst = -1; + ftime = mktime(&local_tm); + + buf->st_ctime = + buf->st_atime = + buf->st_mtime = ftime; + + buf->st_mode = (inf->fib_DirEntryType < 0 ? S_IFREG : S_IFDIR); + + /* lastly, throw in the protection bits */ + buf->st_mode |= ((inf->fib_Protection ^ 0xF) & 0xFF); + + FreeMem((char *)inf, (long)sizeof(*inf)); + UnLock((BPTR)lock); + + return(0); + +} + +int fstat(int handle, struct stat *buf) +{ + /* fake some reasonable values for stdin */ + buf->st_mode = (S_IREAD|S_IWRITE|S_IFREG); + buf->st_size = -1; + buf->st_mtime = time(&buf->st_mtime); + return 0; +} + + +/* opendir(), readdir(), closedir(), rmdir(), and chmod() by Paul Kienitz. */ + +DIR *opendir(const char *path) +{ + DIR *dd = AllocMem(sizeof(DIR), MEMF_PUBLIC); + if (!dd) return NULL; + if (!(dd->d_parentlock = Lock((char *)path, MODE_OLDFILE))) { + disk_not_mounted = IoErr() == ERROR_DEVICE_NOT_MOUNTED; + FreeMem(dd, sizeof(DIR)); + return NULL; + } else + disk_not_mounted = 0; + if (!Examine(dd->d_parentlock, &dd->d_fib) || dd->d_fib.fib_EntryType < 0) { + UnLock(dd->d_parentlock); + FreeMem(dd, sizeof(DIR)); + return NULL; + } + dd->d_cleanuplink = dir_cleanup_list; /* track them resources */ + if (dir_cleanup_list) + dir_cleanup_list->d_cleanupparent = &dd->d_cleanuplink; + dd->d_cleanupparent = &dir_cleanup_list; + dir_cleanup_list = dd; + return dd; +} + +void closedir(DIR *dd) +{ + if (dd) { + if (dd->d_cleanuplink) + dd->d_cleanuplink->d_cleanupparent = dd->d_cleanupparent; + *(dd->d_cleanupparent) = dd->d_cleanuplink; + if (dd->d_parentlock) + UnLock(dd->d_parentlock); + FreeMem(dd, sizeof(DIR)); + } +} + +struct dirent *readdir(DIR *dd) +{ + return (ExNext(dd->d_parentlock, &dd->d_fib) ? (struct dirent *)dd : NULL); +} + + +#ifdef AZTEC_C + +int rmdir(const char *path) +{ + return (DeleteFile((char *)path) ? 0 : IoErr()); +} + +int chmod(const char *filename, int bits) /* bits are as for st_mode */ +{ + long protmask = (bits & 0xFF) ^ 0xF; + return !SetProtection((char *)filename, protmask); +} + + +/* This here removes unnecessary bulk from the executable with Aztec: */ +void _wb_parse(void) { } + +/* fake a unix function that does not apply to amigados: */ +int umask(void) { return 0; } + + +# include + +/* C library signal() messes up debugging yet adds no actual usefulness */ +typedef void (*__signal_return_type)(int); +__signal_return_type signal() { return SIG_ERR; } + + +/* The following replaces Aztec's argv-parsing function for compatibility with +Unix-like syntax used on other platforms. It also fixes the problem the +standard _cli_parse() has of accepting only lower-ascii characters. */ + +int _argc, _arg_len; +char **_argv, *_arg_lin; + +void _cli_parse(struct Process *pp, long alen, register UBYTE *aptr) +{ + register UBYTE *cp; + register struct CommandLineInterface *cli; + register short c; + register short starred = 0; +# ifdef PRESTART_HOOK + void Prestart_Hook(void); +# endif + + cli = (struct CommandLineInterface *) (pp->pr_CLI << 2); + cp = (UBYTE *) (cli->cli_CommandName << 2); + _arg_len = cp[0] + alen + 2; + if (!(_arg_lin = AllocMem((long) _arg_len, 0L))) + return; + c = cp[0]; + strncpy(_arg_lin, cp + 1, c); + _arg_lin[c] = 0; + for (cp = _arg_lin + c + 1; alen && (*aptr < '\n' || *aptr > '\r'); alen--) + *cp++ = *aptr++; + *cp = 0; + aptr = cp = _arg_lin + c + 1; + for (_argc = 1; ; _argc++) { + while (*cp == ' ' || *cp == '\t') + cp++; + if (!*cp) + break; + if (*cp == '"') { + cp++; + while (c = *cp++) { + if (c == '"' && !starred) { + *aptr++ = 0; + starred = 0; + break; + } else if (c == '\\' && !starred) + starred = 1; + else { + *aptr++ = c; + starred = 0; + } + } + } else { + while ((c = *cp++) && c != ' ' && c != '\t') + *aptr++ = c; + *aptr++ = 0; + } + if (c == 0) + --cp; + } + *aptr = 0; + if (!(_argv = AllocMem((_argc + 1) * sizeof(*_argv), 0L))) { + _argc = 0; + return; + } + for (c = 0, cp = _arg_lin; c < _argc; c++) { + _argv[c] = cp; + cp += strlen(cp) + 1; + } + _argv[c] = NULL; +# ifdef PRESTART_HOOK + Prestart_Hook(); +# endif +} + +#endif /* AZTEC_C */ + +#endif /* __amiga_stat_c */ diff --git a/amiga/z-stat.h b/amiga/z-stat.h new file mode 100644 index 0000000..53d6cd1 --- /dev/null +++ b/amiga/z-stat.h @@ -0,0 +1,95 @@ +/* + 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 __amiga_z_stat_h +#define __amiga_z_stat_h + +/* Since older versions of the Lattice C compiler for Amiga, and all current */ +/* versions of the Manx Aztec C compiler for Amiga, either provide no stat() */ +/* function or provide one inadequate for unzip (Aztec's has no st_mode */ +/* field), we provide our own stat() function in stat.c by Paul Wells, and */ +/* this fake stat.h file by Paul Kienitz. Paul Wells originally used the */ +/* Lattice stat.h but that does not work for Aztec and is not distributable */ +/* with this package, so I made a separate one. This has to be pulled into */ +/* unzip.h when compiling an Amiga version, as "amiga/z-stat.h". */ + +/* We also provide here a "struct dirent" for use with opendir() & readdir() */ +/* functions included in amiga/stat.c. If you use amiga/stat.c, this must */ +/* be included wherever you use either readdir() or stat(). */ + +#ifdef AZTEC_C +# define __STAT_H +#else /* __SASC */ +/* do not include the following header, replacement definitions are here */ +# define _STAT_H /* do not include SAS/C */ +# define _DIRENT_H /* do not include SAS/C */ +# define _SYS_DIR_H /* do not include SAS/C */ +# define _COMMIFMT_H /* do not include SAS/C */ +# include +#endif +#include +#include + + +struct stat { + unsigned short st_mode; + time_t st_ctime, st_atime, st_mtime; + long st_size; + long st_ino; + long st_blocks; + short st_attr, st_dev, st_nlink, st_uid, st_gid, st_rdev; +}; + +#define S_IFDIR (1<<11) +#define S_IFREG (1<<10) + +#if 0 + /* these values here are totally random: */ +# define S_IFLNK (1<<14) +# define S_IFSOCK (1<<13) +# define S_IFCHR (1<<8) +# define S_IFIFO (1<<7) +# define S_IFMT (S_IFDIR|S_IFREG|S_IFCHR|S_IFLNK) +#else +# define S_IFMT (S_IFDIR|S_IFREG) +#endif + +#define S_IHIDDEN (1<<7) +#define S_ISCRIPT (1<<6) +#define S_IPURE (1<<5) +#define S_IARCHIVE (1<<4) +#define S_IREAD (1<<3) +#define S_IWRITE (1<<2) +#define S_IEXECUTE (1<<1) +#define S_IDELETE (1<<0) + +int stat(const char *name, struct stat *buf); +int fstat(int handle, struct stat *buf); /* returns dummy values */ + +typedef struct dirent { + struct dirent *d_cleanuplink, + **d_cleanupparent; + BPTR d_parentlock; + struct FileInfoBlock d_fib; +} DIR; +#define d_name d_fib.fib_FileName + +extern unsigned short disk_not_mounted; /* flag set by opendir() */ + +DIR *opendir(const char *); +void closedir(DIR *); +void close_leftover_open_dirs(void); /* call this if aborted in mid-run */ +struct dirent *readdir(DIR *); +int umask(void); + +#ifdef AZTEC_C +int rmdir(const char *); +int chmod(const char *filename, int bits); +#endif + +#endif /* __amiga_z_stat_h */ diff --git a/aosvs/Contents b/aosvs/Contents new file mode 100644 index 0000000..5696512 --- /dev/null +++ b/aosvs/Contents @@ -0,0 +1,7 @@ +Contents of the "aosvs" subdirectory for UnZip 5.3 and later: + + Contents this file + README compilation notes, history, etc. + make_unz.cli command script to make UnZip only (not UnZipSFX or fUnZip) + aosvs.c AOS/VS-specific support routines + aosvs.h AOS/VS-specific typedefs and header stuff diff --git a/aosvs/README b/aosvs/README new file mode 100644 index 0000000..fdfc917 --- /dev/null +++ b/aosvs/README @@ -0,0 +1,145 @@ +[e-mail excerpt from Dave Lovelace explaining AOS/VS port, compiler, etc.] + +> From: Dave Lovelace +> Subject: Re: zip on Data General AOS/VS +> Date: Wed, 17 May 1995 11:02:03 -0400 (EDT) +> +> The diffs for zip & unzip are both in the same file. I've also included the +> extra source files which I wrote, the CLI macros which I used to compile +> & link the things, & my own history of what I did. Note that some of the +> changes I made reversed earlier changes, & this was written for my own +> use (or for others here if I leave or die or something). I hope it will help. +> +> This was compiled using DG's C compiler for AOS/VS, rev 4.10. It has been +> compiled only on an MV-5500 running AOS/VS rev 7.70, but the resulting +> programs have been distributed & run on several different MVs running various +> versions of AOS/VS, so it should be fairly independent of at least minor rev +> variations. To the best of my knowledge it has *not* been tested under +> AOS/VS II, & I really don't know anything about that environment; possibly +> the special AOS/VS file info I'm storing in the extra field will have some +> different format there. + + + +[README/history info from Dave Lovelace] + +In modifying this for use on AOS/VS, I found only a few changes +were needed for DG C 4.10: + +2. There was a bug in the inflate() code, because memset() + was being called with a non-char pointer. Pretty obviously + the other systems where this was used do not have char pointers + different from other pointers. IT IS QUITE POSSIBLE THAT OTHER + BUGS OF THIS SORT EXIST. Testing did not uncover any. +3. In fileio.c, it appears that utime() is being called correctly, + but it does not set the file's time and always returns failure. + Since the AOS/VS tar and cpio programs provided by DG also suffer + from the fault of not setting file times, I must conclude that + this is by design. At any rate, I modified the code (with + compilation conditional on a macro AOS_VS) to not say "error" + when this occurs. + +One change which I think would be desirable: if the filename isn't +already a relative or absolute pathname (specifying a unique location), +the program follows the searchlist under AOS/VS. It will unexpectedly +replace files anywhere in your searchlist. (If you don't use the +-o option, it will ask you first, but not tell you where the file +to be replaced resides.) I suspect this could be handled by prepending +./ to any filenames which don't already begin with /. (I haven't +checked how this would work inside the program. Possibly this +could be done in every case - I don't think PKZIP ever stores an +absolute pathname.) + +To see the compile options I used, look at the file MAKE.AOS_VS.CLI +You may of course need to change the searchlist to use that macro. + + ------------------------------------------------------------------ +15-dec-93 +I fixed some of the above things, introducing new problems. It now +won't follow the searchlist - but the logic prevents it from creating +directories (if they aren't explicitly in the ZIP, anyway). But +UNZIP now sets the creation time to the time stored in the ZIP, and +ZIP now stores that instead of the TLM. I had to introduce an +extra module, with some code of my own and some other public domain +code, to accomplish this. + + ------------------------------------------------------------------ + 1-jun-94 +I found an additional bug: the header was causing void to be #define'd +as int, and prototypes weren't being used. I changed UNZIP.H and +added a define of PROTO to the MAKE.AOS_VS.CLI and REMAKE.CLI macros. + +I found and fixed the bug that prevented the (creation) times from +being set on files with explicit paths. (The Unix-style paths didn't +work as inputs to the AOS/VS ?CREATE system call.) + +Additional known bugs: + +1. I have not yet located the source of the bug that prevents the + date/time from being set (also ACLs etc.) when an existing file + is overwritten. For some reason the call to delete & recreate + the file is not being reached. + +2. We need to do something in ZIP to store (as comments?) the file's + type and ACL, and then here in UNZIP extract these and apply + them. This is not going to be trivial to make foolproof, but + it's badly needed. + + ------------------------------------------------------------------ + 2-jun-94 +I fixed #1 above. The compiler was checking whether UNIX was defined, +and it wasn't. It appears that *some* of the places UNIX is used are +things we can't get along with, so I changed the code to check for +AOS_VS as well. It seems to work just fine. + +I also introduced a function zvs_credir() to create a directory +(as opposed to a CPD, though it can create CPDs to with the proper +file-type parameter). Directories in a path which are being created +will now be directories instead of CPDs. + +The big change that's needed now is to have ZIP store (somehow) +the file's ACL and file type, and then to have UNZIP use this +information to recreate the file as it was before ZIPping. Ideally, +ZIP should also store links and CPD max-block info as well. Planned +strategy: either in the name field but after the name, or in a comment, +store the packet returned by ?FSTAT (using sys_fstat()), and then +use this packet for the ?CREATE call in zvs_create(). + + ------------------------------------------------------------------ +22-Jul-94 +The changes to use the extra-field field for AOS/VS file info are in +place. In general, if a ZIPfile was created with the current rev of +ZIP.PR, the files should be restored with file type, ACL, etc. OK. +I didn't test to make sure element size & max index levels come +through OK, but I think they should. + +Unix symbolic links are now UNZIPped OK, but ZIP.PR isn't yet able +to ZIP links. When it is, UNZIP should be ready. + +In general UNZIP now ignores the searchlist fairly well, but not +perfectly. If the directory of a file you're UNZIPping can be +referenced elsewhere in the searchlist, UNZIP will find the file +there. (For example, if the file UDD/BBASIC/ZZPGSUBSET.SR is in +the ZIPfile, and : is in your searchlist, then UDD and UDD:BBASIC +will be created under your current directory, but UNZIP will still +find :UDD:BBASIC:ZZPGSUBSET.SR instead of =UDD:BBASIC:ZZPGSUBSET.SR. + +Filenames (which are now stored in uppercase by ZIP.PR) must be +matched exactly if specified. This applies to Unix path structure +as well as case. + + ------------------------------------------------------------------ + 4-Aug-94 +I fixed a bug which caused (for links only) the Unix pathname to +be put through ux_to_vs_name twice. The result was that a path +such as dir1/dir2/fname went first to :dir1:dir2:fname and +then to dir1?dir2?fname. + +I also added the /NOSEA switch to the cc/link lines in the macros +MAKE.AOS_VS.CLI and REMAKE.CLI. This should prevent any confusion +over whether a file exists somewhere other than relative to the current +dir. This would disable calls to system() from using the searchlist, +but in this program I think they're all useless & hopefully inactive +anyway. + + ------------------------------------------------------------------ diff --git a/aosvs/aosvs.c b/aosvs/aosvs.c new file mode 100644 index 0000000..7f88f3f --- /dev/null +++ b/aosvs/aosvs.c @@ -0,0 +1,1585 @@ +/* + Copyright (c) 1990-2009 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2009-Jan-02 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 +*/ +/*--------------------------------------------------------------------------- + + aosvs.c + + AOS/VS-specific routines for use with Info-ZIP's UnZip 5.2 and later. +[GRR: copied from unix.c -> undoubtedly has unnecessary stuff: delete at will] + + Contains: readdir() + do_wild() + open_outfile() + mapattr() + mapname() + checkdir() + close_outfile() + version() <-- GRR: needs work! (Unix, not AOS/VS) + zvs_create() + zvs_credir() + ux_to_vs_name() + dgdate() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" +#include "aosvs/aosvs.h" +#include +#include +#include + +#define symlink(resname,linkname) \ + zvs_create(linkname,-1L,-1L,-1L,ux_to_vs_name(vs_resname,resname),$FLNK,-1,-1) + * file type */ + +#ifdef DIRENT +# include +#else +# ifdef SYSV +# ifdef SYSNDIR +# include +# else +# include +# endif +# else /* !SYSV */ +# ifndef NO_SYSDIR +# include +# endif +# endif /* ?SYSV */ +# ifndef dirent +# define dirent direct +# endif +#endif /* ?DIRENT */ + +static int created_dir; /* used in mapname(), checkdir() */ +static int renamed_fullpath; /* ditto */ + +static ZEXTRAFLD zzextrafld; /* buffer for extra field containing + * ?FSTAT packet & ACL buffer */ +static char vs_resname[2*$MXPL]; +static char vs_path[2*$MXPL]; /* buf for AOS/VS pathname */ +static char Vs_path[512]; /* should be big enough [GRR: ?] */ +static P_CTIM zztimeblock; /* time block for file creation */ +static ZVSCREATE_STRU zzcreatepacket; /* packet for sys_create(), any + + +/***************************/ +/* Strings used in aosvs.c */ +/***************************/ + +static ZCONST char Far CannotDeleteOldFile[] = + "error: cannot delete old %s\n"; +static ZCONST char Far CannotCreateFile[] = "error: cannot create %s\n"; + + +#ifndef SFX +#ifdef NO_DIR /* for AT&T 3B1 */ + +#define opendir(path) fopen(path,"r") +#define closedir(dir) fclose(dir) +typedef FILE DIR; + +/* + * Apparently originally by Rich Salz. + * Cleaned up and modified by James W. Birdsall. + */ +struct dirent *readdir(dirp) + DIR *dirp; +{ + static struct dirent entry; + + if (dirp == NULL) + return NULL; + + for (;;) + if (fread(&entry, sizeof (struct dirent), 1, dirp) == 0) + return (struct dirent *)NULL; + else if (entry.d_ino) + return &entry; + +} /* end function readdir() */ + +#endif /* NO_DIR */ + + +/**********************/ +/* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ +/**********************/ + +char *do_wild(__G__ wildspec) + __GDEF + ZCONST char *wildspec; /* only used first time on a given dir */ +{ + static DIR *wild_dir = (DIR *)NULL; + static ZCONST char *wildname; + static char *dirname, matchname[FILNAMSIZ]; + static int notfirstcall=FALSE, have_dirname, dirnamelen; + struct dirent *file; + + /* Even when we're just returning wildspec, we *always* do so in + * matchname[]--calling routine is allowed to append four characters + * to the returned string, and wildspec may be a pointer to argv[]. + */ + if (!notfirstcall) { /* first call: must initialize everything */ + notfirstcall = TRUE; + + if (!iswild(wildspec)) { + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + have_dirname = FALSE; + dir = NULL; + return matchname; + } + + /* break the wildspec into a directory part and a wildcard filename */ + if ((wildname = strrchr(wildspec, '/')) == (ZCONST char *)NULL) { + dirname = "."; + dirnamelen = 1; + have_dirname = FALSE; + wildname = wildspec; + } else { + ++wildname; /* point at character after '/' */ + dirnamelen = wildname - wildspec; + if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) { + Info(slide, 0x201, ((char *)slide, + "warning: cannot allocate wildcard buffers\n")); + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; /* but maybe filespec was not a wildcard */ + } + strncpy(dirname, wildspec, dirnamelen); + dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ + have_dirname = TRUE; + } + + if ((wild_dir = opendir(dirname)) != (DIR *)NULL) { + while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + if (file->d_name[0] == '.' && wildname[0] != '.') + continue; /* Unix: '*' and '?' do not match leading dot */ + if (match(file->d_name, wildname, 0 WISEP) && /* 0=case sens.*/ + /* skip "." and ".." directory entries */ + strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) { + Trace((stderr, "do_wild: match() succeeds\n")); + if (have_dirname) { + strcpy(matchname, dirname); + strcpy(matchname+dirnamelen, file->d_name); + } else + strcpy(matchname, file->d_name); + return matchname; + } + } + /* if we get to here directory is exhausted, so close it */ + closedir(wild_dir); + wild_dir = (DIR *)NULL; + } + + /* return the raw wildspec in case that works (e.g., directory not + * searchable, but filespec was not wild and file is readable) */ + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (wild_dir == (DIR *)NULL) { + notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + } + + /* If we've gotten this far, we've read and matched at least one entry + * successfully (in a previous call), so dirname has been copied into + * matchname already. + */ + while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + if (file->d_name[0] == '.' && wildname[0] != '.') + continue; /* Unix: '*' and '?' do not match leading dot */ + if (match(file->d_name, wildname, 0 WISEP)) { /* 0 == case sens. */ + Trace((stderr, "do_wild: match() succeeds\n")); + if (have_dirname) { + /* strcpy(matchname, dirname); */ + strcpy(matchname+dirnamelen, file->d_name); + } else + strcpy(matchname, file->d_name); + return matchname; + } + } + + closedir(wild_dir); /* have read at least one entry; nothing left */ + wild_dir = (DIR *)NULL; + notfirstcall = FALSE; /* reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + +} /* end function do_wild() */ + +#endif /* !SFX */ + + + + + +/***************************/ +/* Function open_outfile() */ +/***************************/ + +int open_outfile(__G) /* return 1 if fail */ + __GDEF +{ + int errc = 1; /* init to show no success with AOS/VS info */ + long dmm, ddd, dyy, dhh, dmin, dss; + + +#ifdef DLL + if (G.redirect_data) + return redirect_outfile(__G)==FALSE; +#endif + + if (stat(G.filename, &G.statbuf) == 0 && unlink(G.filename) < 0) { + Info(slide, 0x401, ((char *)slide, LoadFarString(CannotDeleteOldFile), + FnFilter1(G.filename))); + return 1; + } + +/*--------------------------------------------------------------------------- + If the file didn't already exist, we created it earlier. But we just + deleted it, which we still had to do in case we are overwriting an exis- + ting file. So we must create it now, again, to set the creation time + properly. (The creation time is the best functional approximation of + the Unix mtime. Really!) + + If we stored this with an AOS/VS Zip that set the extra field to contain + the ?FSTAT packet and the ACL, we should use info from the ?FSTAT call + now. Otherwise (or if that fails), we should create anyway as best we + can from the normal Zip info. + + In theory, we should look through an entire series of extra fields that + might exist for the same file, but we're not going to bother. If we set + up other types of extra fields, or if other environments we run into may + add their own stuff to existing entries in Zip files, we'll have to. + + Note that all the packet types for sys_fstat() are the same size & mostly + have the same structure, with some fields being unused, etc. Ditto for + sys_create(). Thus, we assume a normal one here, not a dir/cpd or device + or IPC file, & make little adjustments as necessary. We will set ACLs + later (to reduce the chance of lacking access to what we create now); note + that for links the resolution name should be stored in the ACL field (once + we get Zip recognizing links OK). + ---------------------------------------------------------------------------*/ + + if (G.extra_field != NULL) { + memcpy((char *) &zzextrafld, G.extra_field, sizeof(zzextrafld)); + if (!memcmp(ZEXTRA_HEADID, zzextrafld.extra_header_id, + sizeof(zzextrafld.extra_header_id)) && + !memcmp(ZEXTRA_SENTINEL, zzextrafld.extra_sentinel), + sizeof(zzextrafld.extra_sentinel)) + { + zzcreatepacket.norm_create_packet.cftyp_format = + zzextrafld.fstat_packet.norm_fstat_packet.styp_format; + zzcreatepacket.norm_create_packet.cftyp_entry = + zzextrafld.fstat_packet.norm_fstat_packet.styp_type; + + /* for DIRS/CPDs, the next one will give the hash frame size; for + * IPCs it will give the port number */ + zzcreatepacket.norm_create_packet.ccps = + zzextrafld.fstat_packet.norm_fstat_packet.scps; + + zzcreatepacket.norm_create_packet.ctim = &zztimeblock; + zztimeblock.tcth = zzextrafld.fstat_packet.norm_fstat_packet.stch; + + /* access & modification times default to current */ + zztimeblock.tath.long_time = zztimeblock.tmth.long_time = -1; + + /* give it current process's ACL unless link; then give it + * resolution name */ + zzcreatepacket.norm_create_packet.cacp = (char *)(-1); + + if (zzcreatepacket.norm_create_packet.cftyp_entry == $FLNK) + zzcreatepacket.norm_create_packet.cacp = zzextrafld.aclbuf; + + zzcreatepacket.dir_create_packet.cmsh = + zzextrafld.fstat_packet.dir_fstat_packet.scsh; + if (zzcreatepacket.norm_create_packet.cftyp_entry != $FCPD) { + /* element size for normal files */ + zzcreatepacket.norm_create_packet.cdel = + zzextrafld.fstat_packet.norm_fstat_packet.sdeh; + } + zzcreatepacket.norm_create_packet.cmil = + zzextrafld.fstat_packet.norm_fstat_packet.smil; + + if ((errc = sys_create(ux_to_vs_name(vs_path, G.filename), + &zzcreatepacket)) != 0) + Info(slide, 0x201, ((char *)slide, + "error creating %s with AOS/VS info -\n\ + will try again with ordinary Zip info\n", + FnFilter1(G.filename))); + } + } + + /* do it the hard way if no AOS/VS info was stored or if we had problems */ + if (errc) { + /* skip restoring time stamps on user's request */ + if (uO.D_flag <= 1) { + dyy = (G.lrec.last_mod_dos_datetime >> 25) + 1980; + dmm = (G.lrec.last_mod_dos_datetime >> 21) & 0x0f; + ddd = (G.lrec.last_mod_dos_datetime >> 16) & 0x1f; + dhh = (G.lrec.last_mod_dos_datetime >> 11) & 0x1f; + dmin = (G.lrec.last_mod_dos_datetime >> 5) & 0x3f; + dss = (G.lrec.last_mod_dos_datetime << 1) & 0x3e; + } + + if (zvs_create(G.filename, + (uO.D_flag <= 1 + ? (((ulg)dgdate(dmm, ddd, dyy)) << 16) | + (dhh*1800L + dmin*30L + dss/2L) + : -1L), + -1L, -1L, (char *) -1, -1, -1, -1)) + { + Info(slide, 0x201, ((char *)slide, "error: %s: cannot create\n", + FnFilter1(G.filename))); + return 1; + } + } + + Trace((stderr, "open_outfile: doing fopen(%s) for writing\n", + FnFilter1(G.filename))); + if ((G.outfile = fopen(G.filename, FOPW)) == (FILE *)NULL) { + Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile), + FnFilter1(G.filename))); + return 1; + } + Trace((stderr, "open_outfile: fopen(%s) for writing succeeded\n", + FnFilter1(G.filename))); + +#ifdef USE_FWRITE +#ifdef _IOFBF /* make output fully buffered (works just about like write()) */ + setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE); +#else + setbuf(G.outfile, (char *)slide); +#endif +#endif /* USE_FWRITE */ + return 0; + +} /* end function open_outfile() */ + + + + + +/**********************/ +/* Function mapattr() */ +/**********************/ + +int mapattr(__G) + __GDEF +{ + ulg tmp = G.crec.external_file_attributes; + + G.pInfo->file_attr = 0; + /* initialized to 0 for check in "default" branch below... */ + + switch (G.pInfo->hostnum) { + case AMIGA_: + tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */ + G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp); + break; + case THEOS_: + tmp &= 0xF1FFFFFFL; + if ((tmp & 0xF0000000L) != 0x40000000L) + tmp &= 0x01FFFFFFL; /* not a dir, mask all ftype bits */ + else + tmp &= 0x41FFFFFFL; /* leave directory bit as set */ + /* fall through! */ + case UNIX_: + case VMS_: + case ACORN_: + case ATARI_: + case ATHEOS_: + case BEOS_: + case QDOS_: + case TANDEM_: + G.pInfo->file_attr = (unsigned)(tmp >> 16); + if (G.pInfo->file_attr != 0 || !G.extra_field) { + return 0; + } else { + /* Some (non-Info-ZIP) implementations of Zip for Unix and + * VMS (and probably others ??) leave 0 in the upper 16-bit + * part of the external_file_attributes field. Instead, they + * store file permission attributes in some extra field. + * As a work-around, we search for the presence of one of + * these extra fields and fall back to the MSDOS compatible + * part of external_file_attributes if one of the known + * e.f. types has been detected. + * Later, we might implement extraction of the permission + * bits from the VMS extra field. But for now, the work-around + * should be sufficient to provide "readable" extracted files. + * (For ASI Unix e.f., an experimental remap from the e.f. + * mode value IS already provided!) + */ + ush ebID; + unsigned ebLen; + uch *ef = G.extra_field; + unsigned ef_len = G.crec.extra_field_length; + int r = FALSE; + + while (!r && ef_len >= EB_HEADSIZE) { + ebID = makeword(ef); + ebLen = (unsigned)makeword(ef+EB_LEN); + if (ebLen > (ef_len - EB_HEADSIZE)) + /* discoverd some e.f. inconsistency! */ + break; + switch (ebID) { + case EF_ASIUNIX: + if (ebLen >= (EB_ASI_MODE+2)) { + G.pInfo->file_attr = + (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE)); + /* force stop of loop: */ + ef_len = (ebLen + EB_HEADSIZE); + break; + } + /* else: fall through! */ + case EF_PKVMS: + /* "found nondecypherable e.f. with perm. attr" */ + r = TRUE; + default: + break; + } + ef_len -= (ebLen + EB_HEADSIZE); + ef += (ebLen + EB_HEADSIZE); + } + if (!r) + return 0; + } + /* fall through! */ + /* all remaining cases: expand MSDOS read-only bit into write perms */ + case FS_FAT_: + /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the + * Unix attributes in the upper 16 bits of the external attributes + * field, just like Info-ZIP's Zip for Unix. We try to use that + * value, after a check for consistency with the MSDOS attribute + * bits (see below). + */ + G.pInfo->file_attr = (unsigned)(tmp >> 16); + /* fall through! */ + case FS_HPFS_: + case FS_NTFS_: + case MAC_: + case TOPS20_: + default: + /* Ensure that DOS subdir bit is set when the entry's name ends + * in a '/'. Some third-party Zip programs fail to set the subdir + * bit for directory entries. + */ + if ((tmp & 0x10) == 0) { + extent fnlen = strlen(G.filename); + if (fnlen > 0 && G.filename[fnlen-1] == '/') + tmp |= 0x10; + } + /* read-only bit --> write perms; subdir bit --> dir exec bit */ + tmp = !(tmp & 1) << 1 | (tmp & 0x10) >> 4; + if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) + /* keep previous G.pInfo->file_attr setting, when its "owner" + * part appears to be consistent with DOS attribute flags! + */ + return 0; + G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp); + break; + } /* end switch (host-OS-created-by) */ + + /* for originating systems with no concept of "group," "other," "system": */ + umask( (int)(tmp=umask(0)) ); /* apply mask to expanded r/w(/x) perms */ + G.pInfo->file_attr &= ~tmp; + + return 0; + +} /* end function mapattr() */ + + + + + +/************************/ +/* Function mapname() */ +/************************/ + +int mapname(__G__ renamed) + __GDEF + int renamed; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - caution (truncated filename) + * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) + * MPN_ERR_SKIP - error -> skip entry + * MPN_ERR_TOOLONG - error -> path is too long + * MPN_NOMEM - error (memory allocation failed) -> skip entry + * [also MPN_VOL_LABEL, MPN_CREATED_DIR] + */ +{ + char pathcomp[FILNAMSIZ]; /* path-component buffer */ + char *pp, *cp=(char *)NULL; /* character pointers */ + char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ +#ifdef ACORN_FTYPE_NFS + char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ + RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */ +#endif + int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ + int error = MPN_OK; + register unsigned workch; /* hold the character being tested */ + + +/*--------------------------------------------------------------------------- + Initialize various pointers and counters and stuff. + ---------------------------------------------------------------------------*/ + + if (G.pInfo->vollabel) + return MPN_VOL_LABEL; /* can't set disk volume labels in Unix */ + + /* can create path as long as not just freshening, or if user told us */ + G.create_dirs = (!uO.fflag || renamed); + + created_dir = FALSE; /* not yet */ + + /* user gave full pathname: don't prepend rootpath */ + renamed_fullpath = (renamed && (*G.filename == '/')); + + if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM) + return MPN_NOMEM; /* initialize path buffer, unless no memory */ + + *pathcomp = '\0'; /* initialize translation buffer */ + pp = pathcomp; /* point to translation buffer */ + if (uO.jflag) /* junking directories */ + cp = (char *)strrchr(G.filename, '/'); + if (cp == (char *)NULL) /* no '/' or not junking dirs */ + cp = G.filename; /* point to internal zipfile-member pathname */ + else + ++cp; /* point to start of last component of path */ + +/*--------------------------------------------------------------------------- + Begin main loop through characters in filename. + ---------------------------------------------------------------------------*/ + + while ((workch = (uch)*cp++) != 0) { + + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + if (strcmp(pathcomp, ".") == 0) { + /* don't bother appending "./" to the path */ + *pathcomp = '\0'; + } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { + /* "../" dir traversal detected, skip over it */ + *pathcomp = '\0'; + killed_ddot = TRUE; /* set "show message" flag */ + } + /* when path component is not empty, append it now */ + if (*pathcomp != '\0' && + ((error = checkdir(__G__ pathcomp, APPEND_DIR)) + & MPN_MASK) > MPN_INF_TRUNC) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ + break; + + case ';': /* VMS version (or DEC-20 attrib?) */ + lastsemi = pp; + *pp++ = ';'; /* keep for now; remove VMS ";##" */ + break; /* later, if requested */ + +#ifdef ACORN_FTYPE_NFS + case ',': /* NFS filetype extension */ + lastcomma = pp; + *pp++ = ','; /* keep for now; may need to remove */ + break; /* later, if requested */ +#endif + +#ifdef MTS + case ' ': /* change spaces to underscore under */ + *pp++ = '_'; /* MTS; leave as spaces under Unix */ + break; +#endif + + default: + /* allow European characters in filenames: */ + if (isprint(workch) || (128 <= workch && workch <= 254)) + *pp++ = (char)workch; + } /* end switch */ + + } /* end while loop */ + + /* Show warning when stripping insecure "parent dir" path components */ + if (killed_ddot && QCOND2) { + Info(slide, 0, ((char *)slide, + "warning: skipped \"../\" path component(s) in %s\n", + FnFilter1(G.filename))); + if (!(error & ~MPN_MASK)) + error = (error & MPN_MASK) | PK_WARN; + } + +/*--------------------------------------------------------------------------- + Report if directory was created (and no file to create: filename ended + in '/'), check name to be sure it exists, and combine path and name be- + fore exiting. + ---------------------------------------------------------------------------*/ + + if (G.filename[strlen(G.filename) - 1] == '/') { + checkdir(__G__ G.filename, GETPATH); + if (created_dir) { + if (QCOND2) { + Info(slide, 0, ((char *)slide, " creating: %s\n", + FnFilter1(G.filename))); + } + /* set dir time (note trailing '/') */ + return (error & ~MPN_MASK) | MPN_CREATED_DIR; + } + /* dir existed already; don't look for data to extract */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + *pp = '\0'; /* done with pathcomp: terminate it */ + + /* if not saving them, remove VMS version numbers (appended ";###") */ + if (!uO.V_flag && lastsemi) { + pp = lastsemi + 1; + while (isdigit((uch)(*pp))) + ++pp; + if (*pp == '\0') /* only digits between ';' and end: nuke */ + *lastsemi = '\0'; + } + + /* On UNIX (and compatible systems), "." and ".." are reserved for + * directory navigation and cannot be used as regular file names. + * These reserved one-dot and two-dot names are mapped to "_" and "__". + */ + if (strcmp(pathcomp, ".") == 0) + *pathcomp = '_'; + else if (strcmp(pathcomp, "..") == 0) + strcpy(pathcomp, "__"); + +#ifdef ACORN_FTYPE_NFS + /* translate Acorn filetype information if asked to do so */ + if (uO.acorn_nfs_ext && + (ef_spark = (RO_extra_block *) + getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) + != (RO_extra_block *)NULL) + { + /* file *must* have a RISC OS extra field */ + long ft = (long)makelong(ef_spark->loadaddr); + /*32-bit*/ + if (lastcomma) { + pp = lastcomma + 1; + while (isxdigit((uch)(*pp))) ++pp; + if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */ + } + if ((ft & 1<<31)==0) ft=0x000FFD00; + sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF); + } +#endif /* ACORN_FTYPE_NFS */ + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", + FnFilter1(G.filename))); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + + checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ + checkdir(__G__ G.filename, GETPATH); + + return error; + +} /* end function mapname() */ + + + + +#if 0 /*========== NOTES ==========*/ + + extract-to dir: a:path/ + buildpath: path1/path2/ ... (NULL-terminated) + pathcomp: filename + + mapname(): + loop over chars in zipfile member name + checkdir(path component, COMPONENT | CREATEDIR) --> map as required? + (d:/tmp/unzip/) (disk:[tmp.unzip.) + (d:/tmp/unzip/jj/) (disk:[tmp.unzip.jj.) + (d:/tmp/unzip/jj/temp/) (disk:[tmp.unzip.jj.temp.) + finally add filename itself and check for existence? (could use with rename) + (d:/tmp/unzip/jj/temp/msg.outdir) (disk:[tmp.unzip.jj.temp]msg.outdir) + checkdir(name, GETPATH) --> copy path to name and free space + +#endif /* 0 */ + + + + +/***********************/ +/* Function checkdir() */ +/***********************/ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename + * MPN_INF_SKIP - path doesn't exist, not allowed to create + * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path + * exists and is not a directory, but is supposed to be + * MPN_ERR_TOOLONG - path is too long + * MPN_NOMEM - can't allocate memory for filename buffers + */ +{ + static int rootlen = 0; /* length of rootpath */ + static char *rootpath; /* user's "extract-to" directory */ + static char *buildpath; /* full path (so far) to extracted file */ + static char *end; /* pointer to end of buildpath ('\0') */ + +# define FN_MASK 7 +# define FUNCTION (flag & FN_MASK) + + + +/*--------------------------------------------------------------------------- + APPEND_DIR: append the path component to the path being built and check + for its existence. If doesn't exist and we are creating directories, do + so for this one; else signal success or error as appropriate. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_DIR) { + int too_long = FALSE; +#ifdef SHORT_NAMES + char *old_end = end; +#endif + + Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') + ++end; +#ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ + if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ + *(end = old_end + FILENAME_MAX) = '\0'; +#endif + + /* GRR: could do better check, see if overrunning buffer as we go: + * check end-buildpath after each append, set warning variable if + * within 20 of FILNAMSIZ; then if var set, do careful check when + * appending. Clear variable when begin new path. */ + + /* next check: need to append '/', at least one-char name, '\0' */ + if ((end-buildpath) > FILNAMSIZ-3) + too_long = TRUE; /* check if extracting dir? */ + /* for AOS/VS, try to create so as to not use searchlist: */ + if ( /*SSTAT(buildpath, &G.statbuf)*/ 1) { + if (!G.create_dirs) { /* told not to create (freshening) */ + free(buildpath); + return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", + FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + /* create the directory */ + if (zvs_credir(buildpath,-1L,-1L,-1L,(char *) -1,-1,0L,-1,-1) == -1) + { + Info(slide, 1, ((char *)slide, + "checkdir error: cannot create %s\n\ + %s\n\ + unable to process %s.\n", + FnFilter2(buildpath), + strerror(errno), + FnFilter1(G.filename))); + free(buildpath); + /* path didn't exist, tried to create, failed */ + return MPN_ERR_SKIP; + } + created_dir = TRUE; + } else if (!S_ISDIR(G.statbuf.st_mode)) { + Info(slide, 1, ((char *)slide, + "checkdir error: %s exists but is not directory\n\ + unable to process %s.\n", + FnFilter2(buildpath), FnFilter1(G.filename))); + free(buildpath); + /* path existed but wasn't dir */ + return MPN_ERR_SKIP; + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + *end++ = '/'; + *end = '\0'; + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + return MPN_OK; + + } /* end if (FUNCTION == APPEND_DIR) */ + +/*--------------------------------------------------------------------------- + GETPATH: copy full path to the string pointed at by pathcomp, and free + buildpath. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == GETPATH) { + strcpy(pathcomp, buildpath); + Trace((stderr, "getting and freeing path [%s]\n", + FnFilter1(pathcomp))); + free(buildpath); + buildpath = end = (char *)NULL; + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + APPEND_NAME: assume the path component is the filename; append it and + return without checking for existence. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_NAME) { +#ifdef SHORT_NAMES + char *old_end = end; +#endif + + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') { + ++end; +#ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ + if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ + *(end = old_end + FILENAME_MAX) = '\0'; +#endif + if ((end-buildpath) >= FILNAMSIZ) { + *--end = '\0'; + Info(slide, 1, ((char *)slide, + "checkdir warning: path too long; truncating\n\ + %s\n -> %s\n", + FnFilter1(G.filename), FnFilter2(buildpath))); + return MPN_INF_TRUNC; /* filename truncated */ + } + } + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + /* could check for existence here, prompt for new name... */ + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + INIT: allocate and initialize buffer space for the file currently being + extracted. If file was renamed with an absolute path, don't prepend the + extract-to path. + ---------------------------------------------------------------------------*/ + +/* GRR: for VMS and TOPS-20, add up to 13 to strlen */ + + if (FUNCTION == INIT) { + Trace((stderr, "initializing buildpath to ")); + if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1)) + == (char *)NULL) + return MPN_NOMEM; + if ((rootlen > 0) && !renamed_fullpath) { + strcpy(buildpath, rootpath); + end = buildpath + rootlen; + } else { + *buildpath = '\0'; + end = buildpath; + } + Trace((stderr, "[%s]\n", FnFilter1(buildpath))); + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + ROOT: if appropriate, store the path in rootpath and create it if + necessary; else assume it's a zipfile member and return. This path + segment gets used in extracting all members from every zipfile specified + on the command line. + ---------------------------------------------------------------------------*/ + +#if (!defined(SFX) || defined(SFX_EXDIR)) + if (FUNCTION == ROOT) { + Trace((stderr, "initializing root path to [%s]\n", + FnFilter1(pathcomp))); + if (pathcomp == (char *)NULL) { + rootlen = 0; + return MPN_OK; + } + if (rootlen > 0) /* rootpath was already set, nothing to do */ + return MPN_OK; + if ((rootlen = strlen(pathcomp)) > 0) { + char *tmproot; + + if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) { + rootlen = 0; + return MPN_NOMEM; + } + strcpy(tmproot, pathcomp); + if (tmproot[rootlen-1] == '/') { + tmproot[--rootlen] = '\0'; + } + if (rootlen > 0 && (SSTAT(tmproot, &G.statbuf) || + !S_ISDIR(G.statbuf.st_mode))) + { /* path does not exist */ + if (!G.create_dirs /* || iswild(tmproot) */ ) { + free(tmproot); + rootlen = 0; + /* skip (or treat as stored file) */ + return MPN_INF_SKIP; + } + /* create the directory (could add loop here scanning tmproot + * to create more than one level, but why really necessary?) */ + if (zvs_credir(tmproot,-1L,-1L,-1L,(char *) -1,-1,0L,-1,-1) + == -1) + { + Info(slide, 1, ((char *)slide, + "checkdir: cannot create extraction directory: %s\n\ + %s\n", + FnFilter1(tmproot), strerror(errno))); + free(tmproot); + rootlen = 0; + /* path didn't exist, tried to create, and failed: */ + /* file exists, or 2+ subdir levels required */ + return MPN_ERR_SKIP; + } + } + tmproot[rootlen++] = '/'; + tmproot[rootlen] = '\0'; + if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { + free(tmproot); + rootlen = 0; + return MPN_NOMEM; + } + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath))); + } + return MPN_OK; + } +#endif /* !SFX || SFX_EXDIR */ + +/*--------------------------------------------------------------------------- + END: free rootpath, immediately prior to program exit. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == END) { + Trace((stderr, "freeing rootpath\n")); + if (rootlen > 0) { + free(rootpath); + rootlen = 0; + } + return MPN_OK; + } + + return MPN_INVALID; /* should never reach */ + +} /* end function checkdir() */ + + + + + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) /* GRR: change to return PK-style warning level */ + __GDEF +{ + +/*--------------------------------------------------------------------------- + If symbolic links are supported, allocate storage for a symlink control + structure, put the uncompressed "data" and other required info in it, and + add the structure to the "deferred symlinks" chain. Since we know it's a + symbolic link to start with, we shouldn't have to worry about overflowing + unsigned ints with unsigned longs. + ---------------------------------------------------------------------------*/ + +#ifdef SYMLINKS + if (G.symlnk) { + extent ucsize = (extent)G.lrec.ucsize; + /* size of the symlink entry is the sum of + * (struct size (includes 1st '\0') + 1 additional trailing '\0'), + * system specific attribute data size (might be 0), + * and the lengths of name and link target. + */ + extent slnk_entrysize = (sizeof(slinkentry) + 1) + + ucsize + strlen(G.filename); + slinkentry *slnk_entry; + + if (slnk_entrysize < ucsize) { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed: mem alloc overflow\n", + FnFilter1(G.filename))); + fclose(G.outfile); + return; + } + + if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed: no mem\n", + FnFilter1(G.filename))); + fclose(G.outfile); + return; + } + slnk_entry->next = NULL; + slnk_entry->targetlen = ucsize; + slnk_entry->attriblen = 0; /* don't set attributes for symlinks */ + slnk_entry->target = slnk_entry->buf; + slnk_entry->fname = slnk_entry->target + ucsize + 1; + strcpy(slnk_entry->fname, G.filename); + + /* move back to the start of the file to re-read the "link data" */ + rewind(G.outfile); + + if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize) + { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed\n", + FnFilter1(G.filename))); + free(slnk_entry); + fclose(G.outfile); + return; + } + fclose(G.outfile); /* close "link" file for good... */ + slnk_entry->target[ucsize] = '\0'; + if (QCOND2) + Info(slide, 0, ((char *)slide, "-> %s ", + FnFilter1(slnk_entry->target))); + /* add this symlink record to the list of deferred symlinks */ + if (G.slink_last != NULL) + G.slink_last->next = slnk_entry; + else + G.slink_head = slnk_entry; + G.slink_last = slnk_entry; + return; + } +#endif /* SYMLINKS */ + + fclose(G.outfile); + +/*--------------------------------------------------------------------------- + Change the file permissions from default ones to those stored in the + zipfile. + ---------------------------------------------------------------------------*/ + +#ifndef NO_CHMOD + if (chmod(G.filename, 0xffff & G.pInfo->file_attr)) + perror("chmod (file attributes) error"); +#endif + +/*--------------------------------------------------------------------------- + AOS/VS only allows setting file times at creation but has its own permis- + sions scheme which is better invoked here if the necessary information + was in fact stored. In theory, we should look through an entire series + of extra fields that might exist for the same file, but we're not going + to bother. If we set up other types of extra fields, or if we run into + other environments that add their own stuff to existing entries in ZIP + files, we'll have to. NOTE: already copied extra-field stuff into + zzextrafld structure when file was created. + ---------------------------------------------------------------------------*/ + + if (G.extra_field != NULL) { + if (!memcmp(ZEXTRA_HEADID, zzextrafld.extra_header_id, + sizeof(zzextrafld.extra_header_id)) && + !memcmp(ZEXTRA_SENTINEL, zzextrafld.extra_sentinel, + sizeof(zzextrafld.extra_sentinel)) && + zzextrafld.fstat_packet.norm_fstat_packet.styp_type != $FLNK) + /* (AOS/VS links don't have ACLs) */ + { + /* vs_path was set (in this case) when we created the file */ + if (sys_sacl(vs_path, zzextrafld.aclbuf)) { + Info(slide, 0x201, ((char *)slide, + "error: cannot set ACL for %s\n", FnFilter1(G.filename))); + perror("sys_sacl()"); + } + } + } +} /* end function close_outfile() */ + + + + +#ifndef SFX + +/************************/ +/* Function version() */ +/************************/ + +void version(__G) + __GDEF +{ +#if (defined(__GNUC__) && defined(NX_CURRENT_COMPILER_RELEASE)) + char cc_namebuf[40]; + char cc_versbuf[40]; +#else +#if (defined(CRAY) && defined(_RELEASE)) + char cc_versbuf[40]; +#endif +#endif +#if ((defined(CRAY) || defined(cray)) && defined(_UNICOS)) + char os_namebuf[40]; +#else +#if defined(__NetBSD__) + char os_namebuf[40]; +#endif +#endif + + /* Pyramid, NeXT have problems with huge macro expansion, too: no Info() */ + sprintf((char *)slide, LoadFarString(CompiledWith), + +#ifdef __GNUC__ +# ifdef NX_CURRENT_COMPILER_RELEASE + (sprintf(cc_namebuf, "NeXT DevKit %d.%02d ", + NX_CURRENT_COMPILER_RELEASE/100, NX_CURRENT_COMPILER_RELEASE%100), + cc_namebuf), + (strlen(__VERSION__) > 8)? "(gcc)" : + (sprintf(cc_versbuf, "(gcc %s)", __VERSION__), cc_versbuf), +# else + "gcc ", __VERSION__, +# endif +#else +# if defined(CRAY) && defined(_RELEASE) + "cc ", (sprintf(cc_versbuf, "version %d", _RELEASE), cc_versbuf), +# else +# ifdef __VERSION__ +# ifndef IZ_CC_NAME +# define IZ_CC_NAME "cc " +# endif + IZ_CC_NAME, __VERSION__ +# else +# ifndef IZ_CC_NAME +# define IZ_CC_NAME "cc" +# endif + IZ_CC_NAME, "", +# endif +# endif +#endif /* ?__GNUC__ */ + +#ifndef IZ_OS_NAME +# define IZ_OS_NAME "Unix" +#endif + IZ_OS_NAME, + +#if defined(sgi) || defined(__sgi) + " (Silicon Graphics IRIX)", +#else +#ifdef sun +# ifdef sparc +# ifdef __SVR4 + " (Sun SPARC/Solaris)", +# else /* may or may not be SunOS */ + " (Sun SPARC)", +# endif +# else +# if defined(sun386) || defined(i386) + " (Sun 386i)", +# else +# if defined(mc68020) || defined(__mc68020__) + " (Sun 3)", +# else /* mc68010 or mc68000: Sun 2 or earlier */ + " (Sun 2)", +# endif +# endif +# endif +#else +#ifdef __hpux + " (HP/UX)", +#else +#ifdef __osf__ + " (DEC OSF/1)", +#else +#ifdef _AIX + " (IBM AIX)", +#else +#ifdef aiws + " (IBM RT/AIX)", +#else +#if defined(CRAY) || defined(cray) +# ifdef _UNICOS + (sprintf(os_namebuf, " (Cray UNICOS release %d)", _UNICOS), os_namebuf), +# else + " (Cray UNICOS)", +# endif +#else +#if defined(uts) || defined(UTS) + " (Amdahl UTS)", +#else +#ifdef NeXT +# ifdef mc68000 + " (NeXTStep/black)", +# else + " (NeXTStep for Intel)", +# endif +#else /* the next dozen or so are somewhat order-dependent */ +#ifdef LINUX +# ifdef __ELF__ + " (Linux ELF)", +# else + " (Linux a.out)", +# endif +#else +#ifdef MINIX + " (Minix)", +#else +#ifdef M_UNIX + " (SCO Unix)", +#else +#ifdef M_XENIX + " (SCO Xenix)", +#else +#ifdef __NetBSD__ +# ifdef NetBSD0_8 + (sprintf(os_namebuf, " (NetBSD 0.8%c)", (char)(NetBSD0_8 - 1 + 'A')), + os_namebuf), +# else +# ifdef NetBSD0_9 + (sprintf(os_namebuf, " (NetBSD 0.9%c)", (char)(NetBSD0_9 - 1 + 'A')), + os_namebuf), +# else +# ifdef NetBSD1_0 + (sprintf(os_namebuf, " (NetBSD 1.0%c)", (char)(NetBSD1_0 - 1 + 'A')), + os_namebuf), +# else + (BSD4_4 == 0.5)? " (NetBSD before 0.9)" : " (NetBSD 1.1 or later)", +# endif +# endif +# endif +#else +#ifdef __FreeBSD__ + (BSD4_4 == 0.5)? " (FreeBSD 1.x)" : " (FreeBSD 2.0 or later)", +#else +#ifdef __bsdi__ + (BSD4_4 == 0.5)? " (BSD/386 1.0)" : " (BSD/386 1.1 or later)", +#else +#ifdef __386BSD__ + (BSD4_4 == 1)? " (386BSD, post-4.4 release)" : " (386BSD)", +#else +#if defined(i486) || defined(__i486) || defined(__i486__) + " (Intel 486)", +#else +#if defined(i386) || defined(__i386) || defined(__i386__) + " (Intel 386)", +#else +#ifdef pyr + " (Pyramid)", +#else +#ifdef ultrix +# ifdef mips + " (DEC/MIPS)", +# else +# ifdef vax + " (DEC/VAX)", +# else /* __alpha? */ + " (DEC/Alpha)", +# endif +# endif +#else +#ifdef gould + " (Gould)", +#else +#ifdef MTS + " (MTS)", +#else +#ifdef __convexc__ + " (Convex)", +#else + "", +#endif /* Convex */ +#endif /* MTS */ +#endif /* Gould */ +#endif /* DEC */ +#endif /* Pyramid */ +#endif /* 386 */ +#endif /* 486 */ +#endif /* 386BSD */ +#endif /* BSDI BSD/386 */ +#endif /* NetBSD */ +#endif /* FreeBSD */ +#endif /* SCO Xenix */ +#endif /* SCO Unix */ +#endif /* Minix */ +#endif /* Linux */ +#endif /* NeXT */ +#endif /* Amdahl */ +#endif /* Cray */ +#endif /* RT/AIX */ +#endif /* AIX */ +#endif /* OSF/1 */ +#endif /* HP/UX */ +#endif /* Sun */ +#endif /* SGI */ + +#ifdef __DATE__ + " on ", __DATE__ +#else + "", "" +#endif + ); + + (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0); + +} /* end function version() */ + +#endif /* !SFX */ + + + + + +/* =================================================================== + * ZVS_CREATE() + * Function to create a file with specified times. The times should be sent + * as long ints in DG time format; use -1 to set to the current times. You + * may also specify a pointer to the ACL, the file type (see PARU.H, and do + * not specify dirs or links), the element size, and the max index level. + * For all of these parameters you may use -1 to specify the default. + * + * Returns 0 if no error, or the error code returned by ?CREATE. + * + * HISTORY: + * 15-dec-93 dbl + * 31-may-94 dbl: added call to convert pathname to AOS/VS + * + * + */ + +int zvs_create(ZCONST char *fname, long cretim, long modtim, long acctim, + char *pacl, int ftyp, int eltsize, int maxindlev) +{ + P_CREATE pcr_stru; + P_CTIM pct_stru; + + pcr_stru.cftyp_format = 0; /* unspecified record format */ + if (ftyp == -1) /* default file type to UNX */ + pcr_stru.cftyp_entry = $FUNX; + else + pcr_stru.cftyp_entry = ftyp; + pcr_stru.ctim = &pct_stru; + pcr_stru.cacp = pacl; + pcr_stru.cdel = eltsize; + pcr_stru.cmil = maxindlev; + + pct_stru.tcth.long_time = cretim; + pct_stru.tath.long_time = acctim; + pct_stru.tmth.long_time = modtim; + + return (sys_create(ux_to_vs_name(Vs_path, fname), &pcr_stru)); + +} /* end zvs_create() */ + + + +/* =================================================================== + * ZVS_CREDIR() + * Function to create a dir as specified. The times should be sent + * as long ints in DG time format; use -1 to set to the current times. You + * may also specify a pointer to the ACL, the file type (either $FDIR or $FCPD; see PARU.H), + * the max # blocks (if a CPD), the hash frame size, and the max index level. + * For all of these parameters (except for the CPD's maximum blocks), + * you may use -1 to specify the default. + * + * (The System Call Dictionary says both that you may specify a + * maximum-index-level value up to the maximum, with 0 for a contiguous + * directory, and that 3 is always used for this whatever you specify.) + * + * If you specify anything other than CPD for the file type, DIR will + * be used. + * + * Returns 0 if no error, or the error code returned by ?CREATE. + * + * HISTORY: + * 1-jun-94 dbl + * + * + */ + +int zvs_credir(ZCONST char *dname, long cretim, long modtim, long acctim, + char *pacl, int ftyp, long maxblocks, int hashfsize, + int maxindlev) +{ + P_CREATE_DIR pcr_stru; + P_CTIM pct_stru; + + if (ftyp != $FCPD) /* default file type to UNX */ + pcr_stru.cftyp_entry = $FDIR; + else + { + pcr_stru.cftyp_entry = ftyp; + pcr_stru.cmsh = maxblocks; + } + + pcr_stru.ctim = &pct_stru; + pcr_stru.cacp = pacl; + pcr_stru.chfs = hashfsize; + pcr_stru.cmil = maxindlev; + + pct_stru.tcth.long_time = cretim; + pct_stru.tath.long_time = acctim; + pct_stru.tmth.long_time = modtim; + + return (sys_create(ux_to_vs_name(Vs_path, dname), &pcr_stru)); + +} /* end zvs_credir() */ + + + +/* =================================================================== + * UX_TO_VS_NAME() - makes a somewhat dumb pass at converting a Unix + * filename to an AOS/VS filename. This should + * be just about adequate to handle the results + * of similarly-simple AOS/VS-to-Unix conversions + * in the ZIP program. It does not guarantee a + * legal AOS/VS filename for every Unix filename; + * conspicuous examples would be names with + * embedded ./ and ../ (which will receive no + * special treatment). + * + * RETURNS: pointer to the result (which is an input parameter) + * + * NOTE: calling code is responsible for making sure + * the output buffer is big enough! + * + * HISTORY: + * 31-may-94 dbl + * + */ +char *ux_to_vs_name(char *outname, ZCONST char *inname) +{ + ZCONST char *ip=inname, *op=outname; + + + if (ip[0] == '.') { + if (ip[1] == '/') { + *(op++) = '='; + ip += 2; + } else if (ip[1] == '.' && ip[2] == '/') { + *(op++) = '^'; + ip += 3; + } + } + + do { + if (*ip == '/') + *(op++) = ':'; + else if (strchr( + "0123456789_$?.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + *ip) != NULL) + { + *(op++) = *ip; + } else + *(op++) = '?'; + + } while (*(ip++) != '\0'); + + return outname; + +} /* end ux_to_vs_name() */ + + + +/* =================================================================== */ + +/* DGDATE + Two functions do encode/decode dates in DG system format. + + Usage: + long value,year,month,day; + + value=dgdate(month,day,year); + undgdate(value,&month,&day,&year); [GRR: not used in UnZip: removed] + + Notes: + + 1. DG date functions only work on dates within the range + Jan 1, 1968 through Dec 31, 2099. I have tested these + functions through the same range with exact agreement. + For dates outside of that range, the DG system calls + may return different values than these functions. + + 2. dgundate() accepts values between 0 and 48213 inclusive. + These correspond to 12/31/1967 and 12/31/2099. + + 3. Both functions assume the data is in the native OS byte + order. So if you're reading or writing these fields from + a file that has been passed between AOS/VS and PC-DOS you + will need to swap byte order. + + 4. With reference to byte order, the entire range of values + supported by these functions will fit into an unsigned + short int. In most cases the input or output will be + in that variable type. You are better off casting the + value to/from unsigned short so you only need to concern + yourself with swapping two bytes instead of four. + + Written by: Stanley J. Gula + US&T, Inc. + 529 Main Street, Suite 1 + Indian Orchard, MA 01151 + (413)-543-3672 + Copyright (c) 1990 US&T, Inc. + All rights reserved. + + I hereby release these functions into the public + domain. You may use these routines freely as long + as the US&T copyright remains intact in the source + code. + + Stanley J. Gula July 24, 1990 +*/ + +long motable[13]={0,31,59,90,120,151,181,212,243,273,304,334,365}; + +long yrtable[132]={ + 366, 731, 1096, 1461, 1827, 2192, 2557, 2922, 3288, 3653, + 4018, 4383, 4749, 5114, 5479, 5844, 6210, 6575, 6940, 7305, + 7671, 8036, 8401, 8766, 9132, 9497, 9862,10227,10593,10958, + 11323,11688,12054,12419,12784,13149,13515,13880,14245,14610, + 14976,15341,15706,16071,16437,16802,17167,17532,17898,18263, + 18628,18993,19359,19724,20089,20454,20820,21185,21550,21915, + 22281,22646,23011,23376,23742,24107,24472,24837,25203,25568, + 25933,26298,26664,27029,27394,27759,28125,28490,28855,29220, + 29586,29951,30316,30681,31047,31412,31777,32142,32508,32873, + 33238,33603,33969,34334,34699,35064,35430,35795,36160,36525, + 36891,37256,37621,37986,38352,38717,39082,39447,39813,40178, + 40543,40908,41274,41639,42004,42369,42735,43100,43465,43830, + 44196,44561,44926,45291,45657,46022,46387,46752,47118,47483, + 47848,48213}; + +/* Given y,m,d return # of days since 12/31/67 */ +long int dgdate(short mm, short dd, short yy) +{ + long int temp; + short ytmp; + + if (mm<1 || mm>12 || dd<1 || dd>31 || yy<1968 || yy>2099) + return 0L; + + /* Figure in whole years since 1968 + whole months plus days */ + temp=365L*(long)(yy-1968) + motable[mm-1] + (long)dd; + + /* Adjust for leap years - note we don't account for skipped leap + year in years divisible by 1000 but not by 4000. We're correct + through the year 2099 */ + temp+=(yy-1965)/4; + + /* Correct for this year */ + /* In leap years, if date is 3/1 or later, bump */ + if ((yy%4==0) && (mm>2)) + temp++; + + return temp; +} diff --git a/aosvs/aosvs.h b/aosvs/aosvs.h new file mode 100644 index 0000000..27944ec --- /dev/null +++ b/aosvs/aosvs.h @@ -0,0 +1,66 @@ +/* + 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 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 +*/ +/*--------------------------------------------------------------------------- + + aosvs.h + + AOS/VS-specific header file for use with Info-ZIP's UnZip 5.2 and later. + + ---------------------------------------------------------------------------*/ + + +/* stuff to set up for system calls (?FSTAT & ?SACL) and the extra field */ + +#include /* parameter definitions */ +#include /* AOS/VS ?FSTAT packet defs */ +#include /* AOS/VS ?CREATE packet defs */ +#include /* AOS/VS system call interface */ + +#define ZEXTRA_HEADID "VS" +#define ZEXTRA_SENTINEL "FCI" +#define ZEXTRA_REV ((uch)10) /* change/use this in later revs */ + + +/* functions defined in zvs_create.c */ + +extern int zvs_create(ZCONST char *fname, long cretim, long modtim, + long acctim, char *pacl, int ftyp, int eltsize, + int maxindlev); +extern int zvs_credir(ZCONST char *dname, long cretim, long modtim, + long acctim, char *pacl, int ftyp, long maxblocks, + int hashfsize, int maxindlev); +extern long dgdate(short mm, short dd, short yy); +extern char *ux_to_vs_name(char *outname, ZCONST char *inname); + + +/* could probably avoid the unions - all elements in each one are the same + * size, and we're going to assume this */ + +typedef union zvsfstat_stru { + P_FSTAT norm_fstat_packet; /* normal fstat packet */ + P_FSTAT_DIR dir_fstat_packet; /* DIR/CPD fstat packet */ + P_FSTAT_UNIT unit_fstat_packet; /* unit (device) fstat packet */ + P_FSTAT_IPC ipc_fstat_packet; /* IPC file fstat packet */ +} ZVSFSTAT_STRU; + +typedef union zvscreate_stru { + P_CREATE norm_create_packet; /* normal create packet */ + P_CREATE_DIR dir_create_packet; /* DIR/CPD create packet */ + P_CREATE_IPC ipc_create_packet; /* IPC file create packet */ +} ZVSCREATE_STRU; + + +typedef struct zextrafld { + char extra_header_id[2]; /* set to VS - in theory, an int */ + char extra_data_size[2]; /* size of rest (little-endian) */ + char extra_sentinel[4]; /* set to FCI w/ trailing null */ + uch extra_rev; /* set to 10 for rev 1.0 */ + ZVSFSTAT_STRU fstat_packet; /* the fstat packet */ + char aclbuf[$MXACL]; /* the raw ACL */ +} ZEXTRAFLD; diff --git a/aosvs/make_unz.cli b/aosvs/make_unz.cli new file mode 100644 index 0000000..8daf91e --- /dev/null +++ b/aosvs/make_unz.cli @@ -0,0 +1,5 @@ +push +prompt pop +searchlist :c_4.10 :c_4.10:lang_rt [!searchlist] +cc/link/NOUNX/NOSEA SYSV/DEFINE TERMIO/DEFINE AOS_VS/DEFINE=1 PROTO/DEFINE S_IFLNK/DEFINE=0120000 TIME.H/INCLUDE .c +pop diff --git a/api.c b/api.c new file mode 100644 index 0000000..a2dcf9a --- /dev/null +++ b/api.c @@ -0,0 +1,714 @@ +/* + Copyright (c) 1990-2009 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2009-Jan-02 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 +*/ +/*--------------------------------------------------------------------------- + + api.c + + This module supplies an UnZip engine for use directly from C/C++ + programs. The functions are: + + ZCONST UzpVer *UzpVersion(void); + unsigned UzpVersion2(UzpVer2 *version) + int UzpMain(int argc, char *argv[]); + int UzpAltMain(int argc, char *argv[], UzpInit *init); + int UzpValidate(char *archive, int AllCodes); + void UzpFreeMemBuffer(UzpBuffer *retstr); + int UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs, + UzpCB *UsrFuncts, UzpBuffer *retstr); + + non-WINDLL only (a special WINDLL variant is defined in windll/windll.c): + int UzpGrep(char *archive, char *file, char *pattern, int cmd, int SkipBin, + UzpCB *UsrFuncts); + + OS/2 only (for now): + int UzpFileTree(char *name, cbList(callBack), char *cpInclude[], + char *cpExclude[]); + + You must define `DLL' in order to include the API extensions. + + ---------------------------------------------------------------------------*/ + + +#ifdef OS2 +# define INCL_DOSMEMMGR +# include +#endif + +#define UNZIP_INTERNAL +#include "unzip.h" +#ifdef WINDLL +# ifdef POCKET_UNZIP +# include "wince/intrface.h" +# else +# include "windll/windll.h" +# endif +#endif +#include "unzvers.h" +#include + +#ifdef DLL /* This source file supplies DLL-only interface code. */ + +#ifndef POCKET_UNZIP /* WinCE pUnZip defines this elsewhere. */ +jmp_buf dll_error_return; +#endif + +/*--------------------------------------------------------------------------- + Documented API entry points + ---------------------------------------------------------------------------*/ + + +ZCONST UzpVer * UZ_EXP UzpVersion() /* returns pointer to const struct */ +{ + static ZCONST UzpVer version = { /* doesn't change between calls */ + /* structure size */ + UZPVER_LEN, + /* version flags */ +#ifdef BETA +# ifdef ZLIB_VERSION + 3, +# else + 1, +# endif +#else +# ifdef ZLIB_VERSION + 2, +# else + 0, +# endif +#endif + /* betalevel and date strings */ + UZ_BETALEVEL, UZ_VERSION_DATE, + /* zlib_version string */ +#ifdef ZLIB_VERSION + ZLIB_VERSION, +#else + NULL, +#endif + /*== someday each of these may have a separate patchlevel: ==*/ + /* unzip version */ + {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0}, + /* zipinfo version */ + {ZI_MAJORVER, ZI_MINORVER, UZ_PATCHLEVEL, 0}, + /* os2dll version (retained for backward compatibility) */ + {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0}, + /* windll version (retained for backward compatibility)*/ + {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0}, +#ifdef OS2DLL + /* os2dll API minimum compatible version*/ + {UZ_OS2API_COMP_MAJOR, UZ_OS2API_COMP_MINOR, UZ_OS2API_COMP_REVIS, 0} +#else /* !OS2DLL */ +#ifdef WINDLL + /* windll API minimum compatible version*/ + {UZ_WINAPI_COMP_MAJOR, UZ_WINAPI_COMP_MINOR, UZ_WINAPI_COMP_REVIS, 0} +#else /* !WINDLL */ + /* generic DLL API minimum compatible version*/ + {UZ_GENAPI_COMP_MAJOR, UZ_GENAPI_COMP_MINOR, UZ_GENAPI_COMP_REVIS, 0} +#endif /* ?WINDLL */ +#endif /* ?OS2DLL */ + }; + + return &version; +} + +unsigned UZ_EXP UzpVersion2(UzpVer2 *version) +{ + + if (version->structlen != sizeof(UzpVer2)) + return sizeof(UzpVer2); + +#ifdef BETA + version->flag = 1; +#else + version->flag = 0; +#endif + strcpy(version->betalevel, UZ_BETALEVEL); + strcpy(version->date, UZ_VERSION_DATE); + +#ifdef ZLIB_VERSION + /* Although ZLIB_VERSION is a compile-time constant, we implement an + "overrun-safe" copy because its actual value is not under our control. + */ + strncpy(version->zlib_version, ZLIB_VERSION, + sizeof(version->zlib_version) - 1); + version->zlib_version[sizeof(version->zlib_version) - 1] = '\0'; + version->flag |= 2; +#else + version->zlib_version[0] = '\0'; +#endif + + /* someday each of these may have a separate patchlevel: */ + version->unzip.major = UZ_MAJORVER; + version->unzip.minor = UZ_MINORVER; + version->unzip.patchlevel = UZ_PATCHLEVEL; + + version->zipinfo.major = ZI_MAJORVER; + version->zipinfo.minor = ZI_MINORVER; + version->zipinfo.patchlevel = UZ_PATCHLEVEL; + + /* these are retained for backward compatibility only: */ + version->os2dll.major = UZ_MAJORVER; + version->os2dll.minor = UZ_MINORVER; + version->os2dll.patchlevel = UZ_PATCHLEVEL; + + version->windll.major = UZ_MAJORVER; + version->windll.minor = UZ_MINORVER; + version->windll.patchlevel = UZ_PATCHLEVEL; + +#ifdef OS2DLL + /* os2dll API minimum compatible version*/ + version->dllapimin.major = UZ_OS2API_COMP_MAJOR; + version->dllapimin.minor = UZ_OS2API_COMP_MINOR; + version->dllapimin.patchlevel = UZ_OS2API_COMP_REVIS; +#else /* !OS2DLL */ +#ifdef WINDLL + /* windll API minimum compatible version*/ + version->dllapimin.major = UZ_WINAPI_COMP_MAJOR; + version->dllapimin.minor = UZ_WINAPI_COMP_MINOR; + version->dllapimin.patchlevel = UZ_WINAPI_COMP_REVIS; +#else /* !WINDLL */ + /* generic DLL API minimum compatible version*/ + version->dllapimin.major = UZ_GENAPI_COMP_MAJOR; + version->dllapimin.minor = UZ_GENAPI_COMP_MINOR; + version->dllapimin.patchlevel = UZ_GENAPI_COMP_REVIS; +#endif /* ?WINDLL */ +#endif /* ?OS2DLL */ + return 0; +} + + + + + +#ifndef SFX +#ifndef WINDLL + +int UZ_EXP UzpAltMain(int argc, char *argv[], UzpInit *init) +{ + int r, (*dummyfn)(); + + + CONSTRUCTGLOBALS(); + + if (init->structlen >= (sizeof(ulg) + sizeof(dummyfn)) && init->msgfn) + G.message = init->msgfn; + + if (init->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) && init->inputfn) + G.input = init->inputfn; + + if (init->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) && init->pausefn) + G.mpause = init->pausefn; + + if (init->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) && init->userfn) + (*init->userfn)(); /* allow void* arg? */ + + r = unzip(__G__ argc, argv); + DESTROYGLOBALS(); + RETURN(r); +} + +#endif /* !WINDLL */ + + + + +#ifndef __16BIT__ + +void UZ_EXP UzpFreeMemBuffer(UzpBuffer *retstr) +{ + if (retstr != NULL && retstr->strptr != NULL) { + free(retstr->strptr); + retstr->strptr = NULL; + retstr->strlength = 0; + } +} + + + + +#ifndef WINDLL + +static int UzpDLL_Init OF((zvoid *pG, UzpCB *UsrFuncts)); + +static int UzpDLL_Init(pG, UsrFuncts) +zvoid *pG; +UzpCB *UsrFuncts; +{ + int (*dummyfn)(); + + if (UsrFuncts->structlen >= (sizeof(ulg) + sizeof(dummyfn)) && + UsrFuncts->msgfn) + ((Uz_Globs *)pG)->message = UsrFuncts->msgfn; + else + return FALSE; + + if (UsrFuncts->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) && + UsrFuncts->inputfn) + ((Uz_Globs *)pG)->input = UsrFuncts->inputfn; + + if (UsrFuncts->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) && + UsrFuncts->pausefn) + ((Uz_Globs *)pG)->mpause = UsrFuncts->pausefn; + + if (UsrFuncts->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) && + UsrFuncts->passwdfn) + ((Uz_Globs *)pG)->decr_passwd = UsrFuncts->passwdfn; + + if (UsrFuncts->structlen >= (sizeof(ulg) + 5*sizeof(dummyfn)) && + UsrFuncts->statrepfn) + ((Uz_Globs *)pG)->statreportcb = UsrFuncts->statrepfn; + + return TRUE; +} + + +int UZ_EXP UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs, + UzpCB *UsrFuncts, UzpBuffer *retstr) +{ + int r; +#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO)) + char *intern_zip, *intern_file; +#endif + + CONSTRUCTGLOBALS(); +#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO)) + intern_zip = (char *)malloc(strlen(zip)+1); + if (intern_zip == NULL) { + DESTROYGLOBALS(); + return PK_MEM; + } + intern_file = (char *)malloc(strlen(file)+1); + if (intern_file == NULL) { + DESTROYGLOBALS(); + free(intern_zip); + return PK_MEM; + } + ISO_TO_INTERN(zip, intern_zip); + ISO_TO_INTERN(file, intern_file); +# define zip intern_zip +# define file intern_file +#endif + /* Copy those options that are meaningful for UzpUnzipToMemory, instead of + * a simple "memcpy(G.UzO, optflgs, sizeof(UzpOpts));" + */ + uO.pwdarg = optflgs->pwdarg; + uO.aflag = optflgs->aflag; + uO.C_flag = optflgs->C_flag; + uO.qflag = optflgs->qflag; /* currently, overridden in unzipToMemory */ + + if (!UzpDLL_Init((zvoid *)&G, UsrFuncts)) { + DESTROYGLOBALS(); + return PK_BADERR; + } + G.redirect_data = 1; + + r = (unzipToMemory(__G__ zip, file, retstr) <= PK_WARN); + + DESTROYGLOBALS(); +#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO)) +# undef file +# undef zip + free(intern_file); + free(intern_zip); +#endif + if (!r && retstr->strlength) { + free(retstr->strptr); + retstr->strptr = NULL; + } + return r; +} +#endif /* !WINDLL */ +#endif /* !__16BIT__ */ + + + + + +#ifdef OS2DLL + +int UZ_EXP UzpFileTree(char *name, cbList(callBack), char *cpInclude[], + char *cpExclude[]) +{ + int r; + + CONSTRUCTGLOBALS(); + uO.qflag = 2; + uO.vflag = 1; + uO.C_flag = 1; + G.wildzipfn = name; + G.process_all_files = TRUE; + if (cpInclude) { + char **ptr = cpInclude; + + while (*ptr != NULL) ptr++; + G.filespecs = ptr - cpInclude; + G.pfnames = cpInclude, G.process_all_files = FALSE; + } + if (cpExclude) { + char **ptr = cpExclude; + + while (*ptr != NULL) ptr++; + G.xfilespecs = ptr - cpExclude; + G.pxnames = cpExclude, G.process_all_files = FALSE; + } + + G.processExternally = callBack; + r = process_zipfiles(__G)==0; + DESTROYGLOBALS(); + return r; +} + +#endif /* OS2DLL */ +#endif /* !SFX */ + + + + +/*--------------------------------------------------------------------------- + Helper functions + ---------------------------------------------------------------------------*/ + + +void setFileNotFound(__G) + __GDEF +{ + G.filenotfound++; +} + + +#ifndef SFX + +int unzipToMemory(__GPRO__ char *zip, char *file, UzpBuffer *retstr) +{ + int r; + char *incname[2]; + + if ((zip == NULL) || (strlen(zip) > ((WSIZE>>2) - 160))) + return PK_PARAM; + if ((file == NULL) || (strlen(file) > ((WSIZE>>2) - 160))) + return PK_PARAM; + + G.process_all_files = FALSE; + G.extract_flag = TRUE; + uO.qflag = 2; + G.wildzipfn = zip; + + G.pfnames = incname; + incname[0] = file; + incname[1] = NULL; + G.filespecs = 1; + + r = process_zipfiles(__G); + if (retstr) { + retstr->strptr = (char *)G.redirect_buffer; + retstr->strlength = G.redirect_size; + } + return r; /* returns `PK_???' error values */ +} + +#endif /* !SFX */ + +/* + With the advent of 64 bit support, for now I am assuming that + if the size of the file is greater than an unsigned long, there + will simply not be enough memory to handle it, and am returning + FALSE. +*/ +int redirect_outfile(__G) + __GDEF +{ +#ifdef ZIP64_SUPPORT + __int64 check_conversion; +#endif + + if (G.redirect_size != 0 || G.redirect_buffer != NULL) + return FALSE; + +#ifndef NO_SLIDE_REDIR + G.redirect_slide = !G.pInfo->textmode; +#endif +#if (lenEOL != 1) + if (G.pInfo->textmode) { + G.redirect_size = (ulg)(G.lrec.ucsize * lenEOL); + if (G.redirect_size < G.lrec.ucsize) + G.redirect_size = (ulg)((G.lrec.ucsize > (ulg)-2L) ? + G.lrec.ucsize : -2L); +#ifdef ZIP64_SUPPORT + check_conversion = G.lrec.ucsize * lenEOL; +#endif + } else +#endif + { + G.redirect_size = (ulg)G.lrec.ucsize; +#ifdef ZIP64_SUPPORT + check_conversion = (__int64)G.lrec.ucsize; +#endif + } + +#ifdef ZIP64_SUPPORT + if ((__int64)G.redirect_size != check_conversion) + return FALSE; +#endif + +#ifdef __16BIT__ + if ((ulg)((extent)G.redirect_size) != G.redirect_size) + return FALSE; +#endif +#ifdef OS2 + DosAllocMem((void **)&G.redirect_buffer, G.redirect_size+1, + PAG_READ|PAG_WRITE|PAG_COMMIT); + G.redirect_pointer = G.redirect_buffer; +#else + G.redirect_pointer = + G.redirect_buffer = malloc((extent)(G.redirect_size+1)); +#endif + if (!G.redirect_buffer) + return FALSE; + G.redirect_pointer[G.redirect_size] = '\0'; + return TRUE; +} + + + +int writeToMemory(__GPRO__ ZCONST uch *rawbuf, extent size) +{ + int errflg = FALSE; + + if ((uch *)rawbuf != G.redirect_pointer) { + extent redir_avail = (G.redirect_buffer + G.redirect_size) - + G.redirect_pointer; + + /* Check for output buffer overflow */ + if (size > redir_avail) { + /* limit transfer data to available space, set error return flag */ + size = redir_avail; + errflg = TRUE; + } + memcpy(G.redirect_pointer, rawbuf, size); + } + G.redirect_pointer += size; + return errflg; +} + + + + +int close_redirect(__G) + __GDEF +{ + if (G.pInfo->textmode) { + *G.redirect_pointer = '\0'; + G.redirect_size = (ulg)(G.redirect_pointer - G.redirect_buffer); + if ((G.redirect_buffer = + realloc(G.redirect_buffer, G.redirect_size + 1)) == NULL) { + G.redirect_size = 0; + return EOF; + } + } + return 0; +} + + + + +#ifndef SFX +#ifndef __16BIT__ +#ifndef WINDLL + +/* Purpose: Determine if file in archive contains the string szSearch + + Parameters: archive = archive name + file = file contained in the archive. This cannot be + a wildcard to be meaningful + pattern = string to search for + cmd = 0 - case-insensitive search + 1 - case-sensitve search + 2 - case-insensitive, whole words only + 3 - case-sensitive, whole words only + SkipBin = if true, skip any files that have control + characters other than CR, LF, or tab in the first + 100 characters. + + Returns: TRUE if a match is found + FALSE if no match is found + -1 on error + + Comments: This does not pretend to be as useful as the standard + Unix grep, which returns the strings associated with a + particular pattern, nor does it search past the first + matching occurrence of the pattern. + */ + +int UZ_EXP UzpGrep(char *archive, char *file, char *pattern, int cmd, + int SkipBin, UzpCB *UsrFuncts) +{ + int retcode = FALSE, compare; + ulg i, j, patternLen, buflen; + char * sz, *p; + UzpOpts flgopts; + UzpBuffer retstr; + + memzero(&flgopts, sizeof(UzpOpts)); /* no special options */ + + if (!UzpUnzipToMemory(archive, file, &flgopts, UsrFuncts, &retstr)) { + return -1; /* not enough memory, file not found, or other error */ + } + + if (SkipBin) { + if (retstr.strlength < 100) + buflen = retstr.strlength; + else + buflen = 100; + for (i = 0; i < buflen; i++) { + if (iscntrl(retstr.strptr[i])) { + if ((retstr.strptr[i] != 0x0A) && + (retstr.strptr[i] != 0x0D) && + (retstr.strptr[i] != 0x09)) + { + /* OK, we now think we have a binary file of some sort */ + free(retstr.strptr); + return FALSE; + } + } + } + } + + patternLen = strlen(pattern); + + if (retstr.strlength < patternLen) { + free(retstr.strptr); + return FALSE; + } + + sz = malloc(patternLen + 3); /* add two in case doing whole words only */ + if (cmd > 1) { + strcpy(sz, " "); + strcat(sz, pattern); + strcat(sz, " "); + } else + strcpy(sz, pattern); + + if ((cmd == 0) || (cmd == 2)) { + for (i = 0; i < strlen(sz); i++) + sz[i] = toupper(sz[i]); + for (i = 0; i < retstr.strlength; i++) + retstr.strptr[i] = toupper(retstr.strptr[i]); + } + + for (i = 0; i < (retstr.strlength - patternLen); i++) { + p = &retstr.strptr[i]; + compare = TRUE; + for (j = 0; j < patternLen; j++) { + /* We cannot do strncmp here, as we may be dealing with a + * "binary" file, such as a word processing file, or perhaps + * even a true executable of some sort. */ + if (p[j] != sz[j]) { + compare = FALSE; + break; + } + } + if (compare == TRUE) { + retcode = TRUE; + break; + } + } + + free(sz); + free(retstr.strptr); + + return retcode; +} +#endif /* !WINDLL */ +#endif /* !__16BIT__ */ + + + +int UZ_EXP UzpValidate(char *archive, int AllCodes) +{ + int retcode; + CONSTRUCTGLOBALS(); + + uO.jflag = 1; + uO.tflag = 1; + uO.overwrite_none = 0; + G.extract_flag = (!uO.zipinfo_mode && + !uO.cflag && !uO.tflag && !uO.vflag && !uO.zflag +#ifdef TIMESTAMP + && !uO.T_flag +#endif + ); + + uO.qflag = 2; /* turn off all messages */ + G.fValidate = TRUE; + G.pfnames = (char **)&fnames[0]; /* assign default filename vector */ + + if (archive == NULL) { /* something is screwed up: no filename */ + DESTROYGLOBALS(); + retcode = PK_NOZIP; + goto exit_retcode; + } + + if (strlen(archive) >= FILNAMSIZ) { + /* length of supplied archive name exceed the system's filename limit */ + DESTROYGLOBALS(); + retcode = PK_PARAM; + goto exit_retcode; + } + + G.wildzipfn = (char *)malloc(FILNAMSIZ); + strcpy(G.wildzipfn, archive); +#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO)) + _ISO_INTERN(G.wildzipfn); +#endif + +#ifdef WINDLL + Wiz_NoPrinting(TRUE); +#endif + + G.process_all_files = TRUE; /* for speed */ + + if (setjmp(dll_error_return) != 0) { +#ifdef WINDLL + Wiz_NoPrinting(FALSE); +#endif + free(G.wildzipfn); + DESTROYGLOBALS(); + retcode = PK_BADERR; + goto exit_retcode; + } + + retcode = process_zipfiles(__G); + + free(G.wildzipfn); +#ifdef WINDLL + Wiz_NoPrinting(FALSE); +#endif + DESTROYGLOBALS(); + + /* PK_WARN == 1 and PK_FIND == 11. When we are just looking at an + archive, we should still be able to see the files inside it, + even if we can't decode them for some reason. + + We also still want to be able to get at files even if there is + something odd about the zip archive, hence allow PK_WARN, + PK_FIND, IZ_UNSUP as well as PK_ERR + */ + +exit_retcode: + if (AllCodes) + return retcode; + + if ((retcode == PK_OK) || (retcode == PK_WARN) || (retcode == PK_ERR) || + (retcode == IZ_UNSUP) || (retcode == PK_FIND)) + return TRUE; + else + return FALSE; +} + +#endif /* !SFX */ +#endif /* DLL */ diff --git a/apihelp.c b/apihelp.c new file mode 100644 index 0000000..de39cee --- /dev/null +++ b/apihelp.c @@ -0,0 +1,155 @@ +/* + 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 +*/ +/* apihelp.c */ + +#ifdef API_DOC + +#define UNZIP_INTERNAL +#include "unzip.h" +#include "unzvers.h" + + +APIDocStruct APIDoc[] = { + { + "UZPVERSION" , "UzpVersion" , + "UzpVer *UzpVersion(void);", + "Get version numbers of the API and the underlying UnZip code.\n\n" + "\t\tThis is used for comparing the version numbers of the run-time\n" + "\t\tDLL code with those expected from the unzip.h at compile time.\n" + "\t\tIf the version numbers do not match, there may be compatibility\n" + "\t\tproblems with further use of the DLL.\n\n" + " Example:\t/* Check the major version number of the DLL code. */\n" + "\t\tUzpVer *pVersion;\n" + "\t\tpVersion = UzpVersion();\n" + "\t\tif (pVersion->unzip.major != UZ_MAJORVER)\n" + "\t\t fprintf(stderr, \"error: using wrong version of DLL\\n\");\n\n" + "\t\tSee unzip.h for details and unzipstb.c for an example.\n" + }, + + { + "UZPMAIN" , "UzpMain" , + "int UzpMain(int argc, char *argv[]);", + "Provide a direct entry point to the command line interface.\n\n" + "\t\tThis is used by the UnZip stub but you can use it in your\n" + "\t\town program as well. Output is sent to stdout.\n" + "\t\t0 on return indicates success.\n\n" + " Example:\t/* Extract 'test.zip' silently, junking paths. */\n" + "\t\tchar *argv[] = { \"-q\", \"-j\", \"test.zip\" };\n" + "\t\tint argc = 3;\n" + "\t\tif (UzpMain(argc,argv))\n" + "\t\t printf(\"error: unzip failed\\n\");\n\n" + "\t\tSee unzip.h for details.\n" + }, + + { + "UZPALTMAIN" , "UzpAltMain" , + "int UzpAltMain(int argc, char *argv[], UzpInit *init);", + "Provide a direct entry point to the command line interface,\n" + "optionally installing replacement I/O handler functions.\n\n" + "\t\tAs with UzpMain(), output is sent to stdout by default.\n" + "\t\t`InputFn *inputfn' is not yet implemented. 0 on return\n" + "\t\tindicates success.\n\n" + " Example:\t/* Replace normal output and `more' functions. */\n" + "\t\tchar *argv[] = { \"-q\", \"-j\", \"test.zip\" };\n" + "\t\tint argc = 3;\n" + "\t\tUzpInit init = { 16, MyMessageFn, NULL, MyPauseFn };\n" + "\t\tif (UzpAltMain(argc,argv,&init))\n" + "\t\t printf(\"error: unzip failed\\n\");\n\n" + "\t\tSee unzip.h for details.\n" + }, + + { + "UZPUNZIPTOMEMORY", "UzpUnzipToMemory", + "int UzpUnzipToMemory(char *zip, char *file, UzpBuffer *retstr);", + "Pass the name of the zip file and the name of the file\n" + "\t\tyou wish to extract. UzpUnzipToMemory will create a\n" + "\t\tbuffer and return it in *retstr; 0 on return indicates\n" + "\t\tfailure.\n\n" + "\t\tSee unzip.h for details.\n" + }, + + { + "UZPFILETREE", "UzpFileTree", + "int UzpFileTree(char *name, cbList(callBack),\n" + "\t\t\tchar *cpInclude[], char *cpExclude[]);", + "Pass the name of the zip file, a callback function, an\n" + "\t\tinclude and exclude file list. UzpFileTree calls the\n" + "\t\tcallback for each valid file found in the zip file.\n" + "\t\t0 on return indicates failure.\n\n" + "\t\tSee unzip.h for details.\n" + }, + + { 0 } +}; + + +static int function_help OF((__GPRO__ APIDocStruct *doc, char *fname)); + + + +static int function_help(__G__ doc, fname) + __GDEF + APIDocStruct *doc; + char *fname; +{ + strcpy(slide, fname); + /* strupr(slide); non-standard */ + while (doc->compare && STRNICMP(doc->compare,slide,strlen(fname))) + doc++; + if (!doc->compare) + return 0; + else + Info(slide, 0, ((char *)slide, + " Function:\t%s\n\n Syntax:\t%s\n\n Purpose:\t%s", + doc->function, doc->syntax, doc->purpose)); + + return 1; +} + + + +void APIhelp(__G__ argc, argv) + __GDEF + int argc; + char **argv; +{ + if (argc > 1) { + struct APIDocStruct *doc; + + if (function_help(__G__ APIDoc, argv[1])) + return; +#ifdef SYSTEM_API_DETAILS + if (function_help(__G__ SYSTEM_API_DETAILS, argv[1])) + return; +#endif + Info(slide, 0, ((char *)slide, + "%s is not a documented command.\n\n", argv[1])); + } + + Info(slide, 0, ((char *)slide, "\ +This API provides a number of external C and REXX functions for handling\n\ +zipfiles in OS/2. Programmers are encouraged to expand this API.\n\ +\n\ +C functions: -- See unzip.h for details\n\ + UzpVer *UzpVersion(void);\n\ + int UzpMain(int argc, char *argv[]);\n\ + int UzpAltMain(int argc, char *argv[], UzpInit *init);\n\ + int UzpUnzipToMemory(char *zip, char *file, UzpBuffer *retstr);\n\ + int UzpFileTree(char *name, cbList(callBack),\n\ + char *cpInclude[], char *cpExclude[]);\n\n")); + +#ifdef SYSTEM_API_BRIEF + Info(slide, 0, ((char *)slide, SYSTEM_API_BRIEF)); +#endif + + Info(slide, 0, ((char *)slide, + "\nFor more information, type 'unzip -A '\n")); +} + +#endif /* API_DOC */ diff --git a/atari/Contents b/atari/Contents new file mode 100644 index 0000000..1f7a7c5 --- /dev/null +++ b/atari/Contents @@ -0,0 +1,12 @@ +Contents of the "atari" sub-archive for UnZip 5.3 and later: + + Contents this file + README.old old notes on compiling UnZip, from author of Atari port + Makefile.old makefile for GNU C compiler and MiNT libraries + Makefile newer, Unix-based makefile (lots of unnecessary baggage :-( ) + make_unz.mup script file for invoking makefile(s)? + atari.c Atari-specific routines + +The maintainers of the Atari port have fallen behind in their duties; the +code *probably* compiles, but it has not been tested recently. Feel free +to send zip-bugs e-mail about this sorry state of affairs. diff --git a/atari/Makefile b/atari/Makefile new file mode 100644 index 0000000..90de0c1 --- /dev/null +++ b/atari/Makefile @@ -0,0 +1,304 @@ +#============================================================================== +# Makefile for UnZip, UnZipSFX and fUnZip: Atari ("real" makes only) +# Version: 5.53 25 December 2006 +#============================================================================== + + +# INSTRUCTIONS (such as they are): +# +# "make" -- makes UnZip on a generic Atari +# +# CF are flags for the C compiler. LF are flags for the loader. LF2 are more +# flags for the loader, if they need to be at the end of the line instead of at +# the beginning (for example, some libraries). FL and FL2 are the corre- +# sponding flags for fUnZip. LOCAL_UNZIP is an environment variable that can +# be used to add default C flags to your compile without editing the Makefile +# (e.g., -DDEBUG_STRUC, or -FPi87 on PCs using Microsoft C). +# +# Be sure to test your new UnZip (and UnZipSFX and fUnZip); successful compila- +# tion does not always imply a working program. + + +##################### +# MACRO DEFINITIONS # +##################### + +# Defaults most systems use (use LOCAL_UNZIP in environment to add flags, +# such as -DDOSWILD). + +# UnZip flags +CC = gcc# try using "gcc" target rather than changing this (if you do, +LD = $(CC)# you MUST change LD, too--else "unresolved symbol: ___main") +LOC = $(LOCAL_UNZIP) +CF = $(CFLAGS) $(LOC) +LF = -o unzip$E +LF2 = -s + +# UnZipSFX flags +SL = -o unzipsfx$E +SL2 = $(LF2) + +# fUnZip flags +FL = -o funzip$E +FL2 = $(LF2) + +# general-purpose stuff +CP = ln -s +LN = ln +RM = rm -f +CHMOD = chmod +STRIP = strip +E = .ttp +O = .o +M = atari +SHELL = /bin/sh + +# object files +OBJS1 = unzip$O crc32$O crypt$O envargs$O explode$O +OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O +OBJS3 = process$O ttyio$O ubz2err$O unreduce$O unshrink$O zipinfo$O +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O +LOBJS = $(OBJS) +OBJSDLL = $(OBJS) api$O +OBJX = unzipsfx$O crc32$O crypt_$O extract_$O fileio_$O \ + globals_$O inflate_$O match_$O process_$O ttyio_$O ubz2err_$O $M_$O +LOBJX = $(OBJX) +OBJF = funzip$O crc32$O cryptf$O globalsf$O inflatef$O ttyiof$O +#OBJS_OS2 = $(OBJS1:.o=.obj) $(OBJS2:.o=.obj) os2.obj +#OBJF_OS2 = $(OBJF:.o=.obj) + +UNZIP_H = unzip.h unzpriv.h globals.h + +# installation +INSTALL = cp# probably can change this to 'install' if you have it +# on some systems, manext=l and MANDIR=/usr/man/man$(manext) may be appropriate +manext = 1 +prefix = /usr/local +BINDIR = $(prefix)/bin# where to install executables +MANDIR = $(prefix)/man/man$(manext)# where to install man pages +INSTALLEDBIN = $(BINDIR)/funzip$E $(BINDIR)/zipinfo$E $(BINDIR)/unzipsfx$E \ + $(BINDIR)/unzip$E +INSTALLEDMAN = $(MANDIR)/unzip.$(manext) $(MANDIR)/funzip.$(manext) \ + $(MANDIR)/unzipsfx.$(manext) $(MANDIR)/zipinfo.$(manext) +# +UNZIPS = unzip$E funzip$E unzipsfx$E +# this is a little ugly...well, no, it's a lot ugly: +MANS = man/unzip.1 man/unzipsfx.1 man/zipinfo.1 man/funzip.1 +DOCS = unzip.txt unzipsfx.txt zipinfo.txt funzip.txt + + +############################################### +# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES # +############################################### + +# this is for GNU make; comment out and notify zip-bugs if it causes errors +.SUFFIXES: .c .o .obj + +# yes, we should be able to use the $O macro to combine these two, but it +# fails on some brain-damaged makes (e.g., AIX's)...no big deal +.c.o: + $(CC) -c $(CF) $*.c + +.c.obj: + $(CC) -c $(CF) $*.c + + +#################### +# DEFAULT HANDLING # +#################### + + +all: unzips +unzips: $(UNZIPS) +docs: $(DOCS) +unzipsman: unzips docs +unzipsdocs: unzips docs + + +unzip$E: $(OBJS) + $(LD) $(LF) $(LOBJS) $(LF2) + +unzipsfx$E: $(OBJX) + $(LD) $(SL) $(LOBJX) $(SL2) + +funzip$E: $(OBJF) + $(LD) $(FL) $(OBJF) $(FL2) + + +crc32$O: crc32.c $(UNZIP_H) zip.h crc32.h +crypt$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +envargs$O: envargs.c $(UNZIP_H) +explode$O: explode.c $(UNZIP_H) +extract$O: extract.c $(UNZIP_H) crc32.h crypt.h +fileio$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +funzip$O: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h +globals$O: globals.c $(UNZIP_H) +inflate$O: inflate.c inflate.h $(UNZIP_H) +list$O: list.c $(UNZIP_H) +match$O: match.c $(UNZIP_H) +process$O: process.c $(UNZIP_H) crc32.h +ttyio$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ubz2err$O: ubz2err.c $(UNZIP_H) +unreduce$O: unreduce.c $(UNZIP_H) +unshrink$O: unshrink.c $(UNZIP_H) +unzip$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +zipinfo$O: zipinfo.c $(UNZIP_H) + +# unzipsfx only +crypt_$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CP) crypt.c crypt_.c + $(CC) -c $(CF) -DSFX crypt_.c + $(RM) crypt_.c + +extract_$O: extract.c $(UNZIP_H) crc32.h crypt.h + $(CP) extract.c extract_.c + $(CC) -c $(CF) -DSFX extract_.c + $(RM) extract_.c + +fileio_$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h + $(CP) fileio.c fileio_.c + $(CC) -c $(CF) -DSFX fileio_.c + $(RM) fileio_.c + +globals_$O: globals.c $(UNZIP_H) + $(CP) globals.c globals_.c + $(CC) -c $(CF) -DSFX globals_.c + $(RM) globals_.c + +inflate_$O: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CP) inflate.c inflate_.c + $(CC) -c $(CF) -DSFX inflate_.c + $(RM) inflate_.c + +match_$O: match.c $(UNZIP_H) + $(CP) match.c match_.c + $(CC) -c $(CF) -DSFX match_.c + $(RM) match_.c + +process_$O: process.c $(UNZIP_H) crc32.h + $(CP) process.c process_.c + $(CC) -c $(CF) -DSFX process_.c + $(RM) process_.c + +ttyio_$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CP) ttyio.c ttyio_.c + $(CC) -c $(CF) -DSFX ttyio_.c + $(RM) ttyio_.c + +ubz2err$O: ubz2err.c $(UNZIP_H) + $(CP) ubz2err.c ubz2err_.c + $(CC) -c $(CF) -DSFX ubz2err_.c + $(RM) ubz2err_.c + +unzipsfx$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h + $(CP) unzip.c unzipsfx.c + $(CC) -c $(CF) -DSFX unzipsfx.c + $(RM) unzipsfx.c + + +# funzip only +cryptf$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CP) crypt.c cryptf.c + $(CC) -c $(CF) -DFUNZIP cryptf.c + $(RM) cryptf.c + +globalsf$O: globals.c $(UNZIP_H) + $(CP) globals.c globalsf.c + $(CC) -c $(CF) -DFUNZIP globalsf.c + $(RM) globalsf.c + +inflatef$O: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CP) inflate.c inflatef.c + $(CC) -c $(CF) -DFUNZIP inflatef.c + $(RM) inflatef.c + +ttyiof$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CP) ttyio.c ttyiof.c + $(CC) -c $(CF) -DFUNZIP ttyiof.c + $(RM) ttyiof.c + + +# system-specific code +atari$O: atari/atari.c $(UNZIP_H) + $(CC) -c $(CF) atari/atari.c + +atari_$O: atari/atari.c $(UNZIP_H) + $(CP) atari/atari.c atari_.c + $(CC) -c $(CF) -DSFX atari_.c + $(RM) atari_.c + + +# this really only works for Unix targets, unless specify E and O on cmd line +clean: + @echo "" + @echo ' This is a Unix-specific target. (Just so you know.)' + @echo "" + rm -f $(OBJS) api$O apihelp$O unzipstb$O $(OBJF) $(OBJX) $(UNZIPS) + +install: $(UNZIPS) $(MANS) + $(INSTALL) $(UNZIPS) $(BINDIR) + $(RM) $(BINDIR)/zipinfo$E + $(LN) $(BINDIR)/unzip$E $(BINDIR)/zipinfo$E + $(INSTALL) man/unzip.1 $(MANDIR)/unzip.$(manext) + $(INSTALL) man/unzipsfx.1 $(MANDIR)/unzipsfx.$(manext) + $(INSTALL) man/zipinfo.1 $(MANDIR)/zipinfo.$(manext) + $(INSTALL) man/funzip.1 $(MANDIR)/funzip.$(manext) + $(CHMOD) 755 $(INSTALLEDBIN) + $(CHMOD) 644 $(INSTALLEDMAN) + +# alternatively, could use zip method: -cd $(BINDIR); rm -f $(UNZIPS) [etc.] +uninstall: + rm -f $(INSTALLEDBIN) $(INSTALLEDMAN) + + +TESTZIP = testmake.zip # the test zipfile + +# test some basic features of the build +test: check + +check: unzips + @echo ' This is a Unix-specific target. (Just so you know.)' + if test ! -f $(TESTZIP); then \ + echo " error: can't find test file $(TESTZIP)"; exit 1; fi +# + echo " testing extraction" + ./unzip -b $(TESTZIP) testmake.zipinfo + if test $? ; then \ + echo " error: file extraction from $(TESTZIP) failed"; exit 1; fi +# + echo ' testing zipinfo (unzip -Z)' + ./unzip -Z $(TESTZIP) > testmake.unzip-Z + if diff testmake.unzip-Z testmake.zipinfo; then ;; else \ + echo ' error: zipinfo output doesn't match stored version'; fi + $(RM) testmake.unzip-Z testmake.zipinfo +# + echo ' testing unzip -d exdir option' + ./unzip -b $(TESTZIP) -d testun + cat testun/notes +# + echo ' testing unzip -o and funzip (ignore funzip warning)' + ./unzip -boq $(TESTZIP) notes -d testun + ./funzip < $(TESTZIP) > testun/notes2 + if diff testun/notes testun/notes2; then ;; else \ + echo 'error: funzip output disagrees with unzip'; fi +# + echo ' testing unzipsfx (self-extractor)' + cat unzipsfx $(TESTZIP) > testsfx + $(CHMOD) 0700 testsfx + ./testsfx -b notes + if diff notes testun/notes; then ;; else \ + echo ' error: unzipsfx file disagrees with unzip'; fi + $(RM) testsfx notes testun/notes testun/notes2 + rmdir testun +# + echo ' testing complete.' + + +################################ +# INDIVIDUAL MACHINE MAKERULES # +################################ + +# these are left over for backward compatibility/convenience + +generic: unzips +atari: unzips diff --git a/atari/Makefile.old b/atari/Makefile.old new file mode 100644 index 0000000..e45f145 --- /dev/null +++ b/atari/Makefile.old @@ -0,0 +1,229 @@ +#============================================================================== +# Makefile for UnZip, UnZipSFX and fUnZip: Atari ST Chris Herborth +# Version: UnZip 5.20+, MiNT, GNU C 25 December 2006 +#============================================================================== + +# Based on the original unix Makefile and modified by Chris Herborth +# (cherborth@semprini.waterloo-rdp.on.ca), Nov.13/93. + +# Be sure to test your new UnZip (and UnZipSFX and fUnZip); successful com- +# pilation does not always imply a working program. + + +##################### +# MACRO DEFINITIONS # +##################### + +# Defaults most systems use (use LOCAL_UNZIP in environment to add flags, +# such as -DDOSWILD). + +# UnZip flags +# NOTE: 'cgcc' is my cross-compiler; you'll probably use 'gcc' instead. +CC = cgcc +LD = cgcc +LOC = $(LOCAL_UNZIP) -ansi -D__MINT__ -U__STRICT_ANSI__ + +CF = -mbaserel -mpcrel -O2 -fomit-frame-pointer -I. $(LOC) +# CF = -O -I. $(LOC) +# CF = -mbaserel -O -I. $(LOC) +LF = -mbaserel -mpcrel -o unzip.ttp +LF2 = -s -lbiio + +# UnZipSFX flags +XC = -DSFX +XL = -mbaserel -mpcrel -o unzipsfx.ttp +XL2 = $(LF2) + +# fUnZip flags +FC = -DFUNZIP +FL = -mbaserel -mpcrel -o funzip.ttp +FL2 = $(LF2) + +# general-purpose stuff +CP = cp +LN = ln -s +RM = rm -f +E = .ttp +O = .o +M = atari +SHELL = /bin/sh + +# object files +OBJS1 = unzip$O crc32$O crypt$O envargs$O explode$O +OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O +OBJS3 = process$O ttyio$O ubz2err$O unreduce$O unshrink$O zipinfo$O +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O +LOBJS = $(OBJS) +OBJX = unzipsfx$O crc32$O crypt_$O extract_$O fileio_$O \ + globals_$O inflate_$O match_$O process_$O ttyio_$O ubz2err_$O $M_$O +OBJF = funzip$O crc32$O cryptf$O globalsf$O inflatef$O ttyiof$O + +UNZIP_H = unzip.h unzpriv.h globals.h + +# installation +INSTALL = cp# probably can change this to 'install' if you have it +# on some systems, manext=l and MANDIR=/usr/man/man$(manext) may be appropriate +manext = 1 +MANDIR = /usr/local/man/man$(manext)# where to install man pages +BINDIR = /usr/local/bin# where to install executables +# +UNZIPS = unzip$E funzip$E unzipsfx$E zipinfo$E +MANS = unzip.$(manext) unzipsfx.$(manext) zipinfo.$(manext) funzip.$(manext) +DOCS = unzip.txt unzipsfx.txt zipinfo.txt funzip.txt +# this is a little ugly... +INSTALLED = $(BINDIR)/unzip$E $(BINDIR)/zipinfo$E $(BINDIR)/funzip$E \ + $(BINDIR)/unzipsfx$E $(MANDIR)/unzipsfx.$(manext) \ + $(MANDIR)/unzip.$(manext) $(MANDIR)/zipinfo.$(manext) \ + $(MANDIR)/funzip.$(manext) + +############################################### +# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES # +############################################### + +.c$O: + $(CC) -c $(CF) $*.c + + +all: unzips +unzips: $(UNZIPS) +docs: $(DOCS) +unzipsman: unzips docs +unzipsdocs: unzips docs + + +clean: + rm -f $(OBJS) $(OBJF) $(OBJX) $(UNZIPS) + +install: $(UNZIPS) $(MANS) + $(INSTALL) $(UNZIPS) $(BINDIR) + $(LN) $(BINDIR)/unzip$E $(BINDIR)/zipinfo$E + $(INSTALL) man/unzip.1 $(MANDIR)/unzip.$(manext) + $(INSTALL) man/unzipsfx.1 $(MANDIR)/unzipsfx.$(manext) + $(INSTALL) man/zipinfo.1 $(MANDIR)/zipinfo.$(manext) + $(INSTALL) man/funzip.1 $(MANDIR)/funzip.$(manext) + +# alternatively, could use zip method: -cd $(BINDIR); rm -f $(UNZIPS) [etc.] +uninstall: + rm -f $(INSTALLED) + + +unzip$E: $(OBJS) # add `&' if parallel makes supported + $(LD) $(LF) $(LOBJS) $(LF2) + +unzipsfx$E: $(OBJX) # add `&' if parallel makes supported + $(LD) $(XL) $(OBJX) $(XL2) + +funzip$E: $(OBJF) # add `&' if parallel makes supported + $(LD) $(FL) $(OBJF) $(FL2) + +zipinfo$E: unzip$E + @echo\ + ' This is a Unix-inspired target. If your filesystem does not support' + @echo\ + ' symbolic links, copy unzip.ttp to zipinfo.ttp rather than linking it,' + @echo\ + ' or else invoke as "unzip -Z".' + $(LN) unzip$E zipinfo$E + + +crc32$O: crc32.c $(UNZIP_H) zip.h crc32.h +crypt$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +envargs$O: envargs.c $(UNZIP_H) +explode$O: explode.c $(UNZIP_H) +extract$O: extract.c $(UNZIP_H) crc32.h crypt.h +fileio$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +funzip$O: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h +globals$O: globals.c $(UNZIP_H) +inflate$O: inflate.c inflate.h $(UNZIP_H) +list$O: list.c $(UNZIP_H) +match$O: match.c $(UNZIP_H) +process$O: process.c $(UNZIP_H) crc32.h +ttyio$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ubz2err$O: ubz2err.c $(UNZIP_H) +unreduce$O: unreduce.c $(UNZIP_H) +unshrink$O: unshrink.c $(UNZIP_H) +unzip$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +zipinfo$O: zipinfo.c $(UNZIP_H) + +# unzipsfx only +crypt_$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CP) crypt.c crypt_.c + $(CC) -c $(CF) $(XC) crypt_.c + $(RM) crypt_.c + +extract_$O: extract.c $(UNZIP_H) crc32.h crypt.h + $(CP) extract.c extract_.c + $(CC) -c $(CF) $(XC) extract_.c + $(RM) extract_.c + +fileio_$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h + $(CP) fileio.c fileio_.c + $(CC) -c $(CF) $(XC) fileio_.c + $(RM) fileio_.c + +globals_$O: globals.c $(UNZIP_H) + $(CP) globals.c globals_.c + $(CC) -c $(CF) $(XC) globals_.c + $(RM) globals_.c + +inflate_$O: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CP) inflate.c inflate_.c + $(CC) -c $(CF) $(XC) inflate_.c + $(RM) inflate_.c + +match_$O: match.c $(UNZIP_H) + $(CP) match.c match_.c + $(CC) -c $(CF) $(XC) match_.c + $(RM) match_.c + +process_$O: process.c $(UNZIP_H) crc32.h + $(CP) process.c process_.c + $(CC) -c $(CF) $(XC) process_.c + $(RM) process_.c + +ttyio_$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CP) ttyio.c ttyio_.c + $(CC) -c $(CF) $(XC) ttyio_.c + $(RM) ttyio_.c + +ubz2err_$O: ubz2err.c $(UNZIP_H) + $(CP) ubz2err.c ubz2err_.c + $(CC) -c $(CF) $(XC) ubz2err_.c + $(RM) ubz2err_.c + +unzipsfx$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h + $(CP) unzip.c unzip_.c + $(CC) -c $(CF) $(XC) unzip_.c + $(RM) unzip_.c + + +# funzip only +cryptf$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CP) crypt.c cryptf.c + $(CC) -c $(CF) $(FC) cryptf.c + $(RM) cryptf.c + +globalsf$O: globals.c $(UNZIP_H) + $(CP) globals.c globalsf.c + $(CC) -c $(CF) $(FC) globalsf.c + $(RM) globalsf.c + +inflatef$O: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CP) inflate.c inflatef.c + $(CC) -c $(CF) $(FC) inflatef.c + $(RM) inflatef.c + +ttyiof$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CP) ttyio.c ttyiof.c + $(CC) -c $(CF) $(FC) ttyiof.c + $(RM) ttyiof.c + + +# system-specific code +atari$O: atari/atari.c $(UNZIP_H) # Atari only + $(CC) -c $(CF) atari/atari.c + +atari_$O: atari/atari.c $(UNZIP_H) # unzipsfx only + $(CP) atari/atari.c atari_.c + $(CC) -c $(CF) $(XC) atari_.c + $(RM) atari_.c diff --git a/atari/README.old b/atari/README.old new file mode 100644 index 0000000..d4d5386 --- /dev/null +++ b/atari/README.old @@ -0,0 +1,43 @@ +Here it is... the UnZip 5.1 port for the Atari ST/TT/Falcon! + +This took me longer than I expected thanks to a difference between the +MiNT library and most UNIX libraries... symlinks are 0x16000 +instead of 0xa000... I'm told this isn't even defined in POSIX, so I +can't really complain. At least we've got a filesystem that can use +symlinks! + +This port requires GNU C and allows you to build an unzip/zipinfo/funzip +that supports long filenames (on appropriate filesystems, thanks to the +MiNT library), as well as symlinks. It also does "proper" (ie, DOS-style) +translation of text-file end-of-line characters. The programs also build +as shared-text binaries, so you can start unzipping several files at once +in the background and only a small part of unzip will be duplicated in +memory. + +I build unzip with the MiNT library, GNU C 2.5.8 (2.5.7 and lower have a +rather sever problem in the optimiser that affects 68000 code only; it +adds 68020-only instructions to the 68000 code). Oh, and I tested it +extensively under MiNT's minix filesystem as well as the bogus DOS +filesystem that "normal" Atari partitions have. + +The Makefile won't need any editing if you want to built unzip et al. on +a minix filesystem; if you want to install it on a DOS filesystem, use +"cp" instead of "ln" for zipinfo. [Or, to save disk space, make a script/ +command-file which invokes "unzip -Z ...". --CN] This is such a good +idea that I'm annoyed that Greg thought of it and I didn't... ;-) If +you're using a shell worth your while, you can alias zipinfo to +'unzip -Z' and then forget all about this paragraph. + +If you want to compile this using Turbo C (aka Pure C in North America) +you're on your own... That's ok, I'll make a nice binary version of +unzip available as soon as the official 5.1 version is released (give or +take a few days). + +Enjoy! Cave Newt should be given kudos for keeping this monster easy to +port... ;-) [Hah! But thanks anyway. :-) --CN] + +PLEASE email me to tell me if you've uploaded the source or binary +versions of Unzip 5.x to any BBS systems or commercial online systems so +we can update the WHERE file! + +-Chris Herborth- diff --git a/atari/atari.c b/atari/atari.c new file mode 100644 index 0000000..5651b43 --- /dev/null +++ b/atari/atari.c @@ -0,0 +1,1019 @@ +/* + Copyright (c) 1990-2008 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 +*/ +/*--------------------------------------------------------------------------- + + atari.c + + Atari-specific routines for use with Info-ZIP's UnZip 5.1 and later. + + Contains: readdir() + do_wild() <-- generic enough to put in fileio.c? + mapattr() + mapname() + checkdir() + mkdir() + close_outfile() + stamp_file() [optional feature] + version() + + Due to the amazing MiNT library being very, very close to BSD unix's + library, I'm using the unix.c as a base for this. Note: If you're not + going to compile this with the MiNT libraries (for GNU C, Turbo C, Pure C, + Lattice C, or Heat & Serve C), you're going to be in for some nasty work. + Most of the modifications in this file were made by Chris Herborth + (cherborth@semprini.waterloo-rdp.on.ca) and /should/ be marked with [cjh]. + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" +#include /* MiNTlibs has dirent [cjh] */ + +static int created_dir; /* used in mapname(), checkdir() */ +static int renamed_fullpath; /* ditto */ + + +#ifndef SFX + +/**********************/ +/* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ +/**********************/ + +char *do_wild(__G__ wildspec) + __GDEF + ZCONST char *wildspec; /* only used first time on a given dir */ +{ + static DIR *wild_dir = (DIR *)NULL; + static ZCONST char *wildname; + static char *dirname, matchname[FILNAMSIZ]; + static int notfirstcall=FALSE, have_dirname, dirnamelen; + struct dirent *file; + + /* Even when we're just returning wildspec, we *always* do so in + * matchname[]--calling routine is allowed to append four characters + * to the returned string, and wildspec may be a pointer to argv[]. + */ + if (!notfirstcall) { /* first call: must initialize everything */ + notfirstcall = TRUE; + + if (!iswild(wildspec)) { + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + have_dirname = FALSE; + dir = NULL; + return matchname; + } + + /* break the wildspec into a directory part and a wildcard filename */ + if ((wildname = strrchr(wildspec, '/')) == (ZCONST char *)NULL) { + dirname = "."; + dirnamelen = 1; + have_dirname = FALSE; + wildname = wildspec; + } else { + ++wildname; /* point at character after '/' */ + dirnamelen = wildname - wildspec; + if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) { + Info(slide, 0x201, ((char *)slide, + "warning: cannot allocate wildcard buffers\n")); + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; /* but maybe filespec was not a wildcard */ + } + strncpy(dirname, wildspec, dirnamelen); + dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ + have_dirname = TRUE; + } + + if ((wild_dir = opendir(dirname)) != (DIR *)NULL) { + while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", file->d_name)); + if (file->d_name[0] == '.' && wildname[0] != '.') + continue; /* Unix: '*' and '?' do not match leading dot */ + /* Need something here for TOS filesystem? [cjh] */ + if (match(file->d_name, wildname, 0 WISEP) && /* 0=case sens.*/ + /* skip "." and ".." directory entries */ + strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) { + Trace((stderr, "do_wild: match() succeeds\n")); + if (have_dirname) { + strcpy(matchname, dirname); + strcpy(matchname+dirnamelen, file->d_name); + } else + strcpy(matchname, file->d_name); + return matchname; + } + } + /* if we get to here directory is exhausted, so close it */ + closedir(wild_dir); + wild_dir = (DIR *)NULL; + } + + /* return the raw wildspec in case that works (e.g., directory not + * searchable, but filespec was not wild and file is readable) */ + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (wild_dir == (DIR *)NULL) { + notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + } + + /* If we've gotten this far, we've read and matched at least one entry + * successfully (in a previous call), so dirname has been copied into + * matchname already. + */ + while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { + /* May need special TOS handling here. [cjh] */ + Trace((stderr, "do_wild: readdir returns %s\n", file->d_name)); + if (file->d_name[0] == '.' && wildname[0] != '.') + continue; /* Unix: '*' and '?' do not match leading dot */ + if (match(file->d_name, wildname, 0 WISEP)) { /* 0 = case sens. */ + Trace((stderr, "do_wild: match() succeeds\n")); + if (have_dirname) { + /* strcpy(matchname, dirname); */ + strcpy(matchname+dirnamelen, file->d_name); + } else + strcpy(matchname, file->d_name); + return matchname; + } + } + + closedir(wild_dir); /* have read at least one entry; nothing left */ + wild_dir = (DIR *)NULL; + notfirstcall = FALSE; /* reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + +} /* end function do_wild() */ + +#endif /* !SFX */ + + + + + +/**********************/ +/* Function mapattr() */ +/**********************/ + +int mapattr(__G) + __GDEF +{ + int r; + ulg tmp = G.crec.external_file_attributes; + + G.pInfo->file_attr = 0; + /* initialized to 0 for check in "default" branch below... */ + + switch (G.pInfo->hostnum) { + case AMIGA_: + tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */ + G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp); + break; + case THEOS_: + tmp &= 0xF1FFFFFFL; + if ((tmp & 0xF0000000L) != 0x40000000L) + tmp &= 0x01FFFFFFL; /* not a dir, mask all ftype bits */ + else + tmp &= 0x41FFFFFFL; /* leave directory bit as set */ + /* fall through! */ + case UNIX_: + case VMS_: + case ACORN_: + case ATARI_: + case ATHEOS_: + case BEOS_: + case QDOS_: + case TANDEM_: + r = FALSE; + G.pInfo->file_attr = (unsigned)(tmp >> 16); + if (G.pInfo->file_attr == 0 && G.extra_field) { + /* Some (non-Info-ZIP) implementations of Zip for Unix and + * VMS (and probably others ??) leave 0 in the upper 16-bit + * part of the external_file_attributes field. Instead, they + * store file permission attributes in some extra field. + * As a work-around, we search for the presence of one of + * these extra fields and fall back to the MSDOS compatible + * part of external_file_attributes if one of the known + * e.f. types has been detected. + * Later, we might implement extraction of the permission + * bits from the VMS extra field. But for now, the work-around + * should be sufficient to provide "readable" extracted files. + * (For ASI Unix e.f., an experimental remap of the e.f. + * mode value IS already provided!) + */ + ush ebID; + unsigned ebLen; + uch *ef = G.extra_field; + unsigned ef_len = G.crec.extra_field_length; + + while (!r && ef_len >= EB_HEADSIZE) { + ebID = makeword(ef); + ebLen = (unsigned)makeword(ef+EB_LEN); + if (ebLen > (ef_len - EB_HEADSIZE)) + /* discoverd some e.f. inconsistency! */ + break; + switch (ebID) { + case EF_ASIUNIX: + if (ebLen >= (EB_ASI_MODE+2)) { + G.pInfo->file_attr = + (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE)); + /* force stop of loop: */ + ef_len = (ebLen + EB_HEADSIZE); + break; + } + /* else: fall through! */ + case EF_PKVMS: + /* "found nondecypherable e.f. with perm. attr" */ + r = TRUE; + default: + break; + } + ef_len -= (ebLen + EB_HEADSIZE); + ef += (ebLen + EB_HEADSIZE); + } + } + if (!r) { +#ifdef SYMLINKS + /* Check if the file is a (POSIX-compatible) symbolic link. + * We restrict symlink support to those "made-by" hosts that + * are known to support symbolic links. + */ + G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) && + SYMLINK_HOST(G.pInfo->hostnum); +#endif + return 0; + } + /* fall through! */ + /* all remaining cases: expand MSDOS read-only bit into write perms */ + case FS_FAT_: + /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the + * Unix attributes in the upper 16 bits of the external attributes + * field, just like Info-ZIP's Zip for Unix. We try to use that + * value, after a check for consistency with the MSDOS attribute + * bits (see below). + */ + G.pInfo->file_attr = (unsigned)(tmp >> 16); + /* fall through! */ + case FS_HPFS_: + case FS_NTFS_: + case MAC_: + case TOPS20_: + default: + /* Ensure that DOS subdir bit is set when the entry's name ends + * in a '/'. Some third-party Zip programs fail to set the subdir + * bit for directory entries. + */ + if ((tmp & 0x10) == 0) { + extent fnlen = strlen(G.filename); + if (fnlen > 0 && G.filename[fnlen-1] == '/') + tmp |= 0x10; + } + /* read-only bit --> write perms; subdir bit --> dir exec bit */ + tmp = !(tmp & 1) << 1 | (tmp & 0x10) >> 4; + if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) { + /* keep previous G.pInfo->file_attr setting, when its "owner" + * part appears to be consistent with DOS attribute flags! + */ +#ifdef SYMLINKS + /* Entries "made by FS_FAT_" could have been zipped on a + * system that supports POSIX-style symbolic links. + */ + G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) && + (G.pInfo->hostnum == FS_FAT_); +#endif + return 0; + } + G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp); + break; + } /* end switch (host-OS-created-by) */ + + /* for originating systems with no concept of "group," "other," "system": */ + umask( (int)(tmp=umask(0)) ); /* apply mask to expanded r/w(/x) perms */ + G.pInfo->file_attr &= ~tmp; + + return 0; + +} /* end function mapattr() */ + + + + + +/************************/ +/* Function mapname() */ +/************************/ + +int mapname(__G__ renamed) + __GDEF + int renamed; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - caution (truncated filename) + * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) + * MPN_ERR_SKIP - error -> skip entry + * MPN_ERR_TOOLONG - error -> path is too long + * MPN_NOMEM - error (memory allocation failed) -> skip entry + * [also MPN_VOL_LABEL, MPN_CREATED_DIR] + */ +{ + char pathcomp[FILNAMSIZ]; /* path-component buffer */ + char *pp, *cp=(char *)NULL; /* character pointers */ + char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ +#ifdef ACORN_FTYPE_NFS + char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ + RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */ +#endif + int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ + int error = MPN_OK; + register unsigned workch; /* hold the character being tested */ + + +/*--------------------------------------------------------------------------- + Initialize various pointers and counters and stuff. + ---------------------------------------------------------------------------*/ + + if (G.pInfo->vollabel) + return MPN_VOL_LABEL; /* can't set disk volume labels on Atari */ + + /* can create path as long as not just freshening, or if user told us */ + G.create_dirs = (!uO.fflag || renamed); + + created_dir = FALSE; /* not yet */ + + /* user gave full pathname: don't prepend rootpath */ + renamed_fullpath = (renamed && (*G.filename == '/')); + + if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM) + return MPN_NOMEM; /* initialize path buffer, unless no memory */ + + *pathcomp = '\0'; /* initialize translation buffer */ + pp = pathcomp; /* point to translation buffer */ + if (uO.jflag) /* junking directories */ + cp = (char *)strrchr(G.filename, '/'); + if (cp == (char *)NULL) /* no '/' or not junking dirs */ + cp = G.filename; /* point to internal zipfile-member pathname */ + else + ++cp; /* point to start of last component of path */ + +/*--------------------------------------------------------------------------- + Begin main loop through characters in filename. + ---------------------------------------------------------------------------*/ + + while ((workch = (uch)*cp++) != 0) { + + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + if (strcmp(pathcomp, ".") == 0) { + /* don't bother appending "./" to the path */ + *pathcomp = '\0'; + } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { + /* "../" dir traversal detected, skip over it */ + *pathcomp = '\0'; + killed_ddot = TRUE; /* set "show message" flag */ + } + /* when path component is not empty, append it now */ + if (*pathcomp != '\0' && + ((error = checkdir(__G__ pathcomp, APPEND_DIR)) + & MPN_MASK) > MPN_INF_TRUNC) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ + break; + + case ';': /* VMS version (or DEC-20 attrib?) */ + lastsemi = pp; + *pp++ = ';'; /* keep for now; remove VMS ";##" */ + break; /* later, if requested */ + +#ifdef ACORN_FTYPE_NFS + case ',': /* NFS filetype extension */ + lastcomma = pp; + *pp++ = ','; /* keep for now; may need to remove */ + break; /* later, if requested */ +#endif + +#ifdef MTS + case ' ': /* change spaces to underscore under */ + *pp++ = '_'; /* MTS; leave as spaces under Unix */ + break; +#endif + + default: + /* allow European characters in filenames: */ + if (isprint(workch) || (128 <= workch && workch <= 254)) + *pp++ = (char)workch; + } /* end switch */ + + } /* end while loop */ + + /* Show warning when stripping insecure "parent dir" path components */ + if (killed_ddot && QCOND2) { + Info(slide, 0, ((char *)slide, + "warning: skipped \"../\" path component(s) in %s\n", + FnFilter1(G.filename))); + if (!(error & ~MPN_MASK)) + error = (error & MPN_MASK) | PK_WARN; + } + +/*--------------------------------------------------------------------------- + Report if directory was created (and no file to create: filename ended + in '/'), check name to be sure it exists, and combine path and name be- + fore exiting. + ---------------------------------------------------------------------------*/ + + if (G.filename[strlen(G.filename) - 1] == '/') { + checkdir(__G__ G.filename, GETPATH); + if (created_dir) { + if (QCOND2) { + Info(slide, 0, ((char *)slide, " creating: %s\n", + FnFilter1(G.filename))); + } + /* set dir time (note trailing '/') */ + return (error & ~MPN_MASK) | MPN_CREATED_DIR; + } + /* dir existed already; don't look for data to extract */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + *pp = '\0'; /* done with pathcomp: terminate it */ + + /* if not saving them, remove VMS version numbers (appended ";###") */ + if (!uO.V_flag && lastsemi) { + pp = lastsemi + 1; + while (isdigit((uch)(*pp))) + ++pp; + if (*pp == '\0') /* only digits between ';' and end: nuke */ + *lastsemi = '\0'; + } + + /* On UNIX (and compatible systems), "." and ".." are reserved for + * directory navigation and cannot be used as regular file names. + * These reserved one-dot and two-dot names are mapped to "_" and "__". + */ + if (strcmp(pathcomp, ".") == 0) + *pathcomp = '_'; + else if (strcmp(pathcomp, "..") == 0) + strcpy(pathcomp, "__"); + +#ifdef ACORN_FTYPE_NFS + /* translate Acorn filetype information if asked to do so */ + if (uO.acorn_nfs_ext && + (ef_spark = (RO_extra_block *) + getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) + != (RO_extra_block *)NULL) + { + /* file *must* have a RISC OS extra field */ + long ft = (long)makelong(ef_spark->loadaddr); + /*32-bit*/ + if (lastcomma) { + pp = lastcomma + 1; + while (isxdigit((uch)(*pp))) ++pp; + if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */ + } + if ((ft & 1<<31)==0) ft=0x000FFD00; + sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF); + } +#endif /* ACORN_FTYPE_NFS */ + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", + FnFilter1(G.filename))); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + + checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ + checkdir(__G__ G.filename, GETPATH); + + return error; + +} /* end function mapname() */ + + + + +#if 0 /*========== NOTES ==========*/ + + extract-to dir: a:path/ + buildpath: path1/path2/ ... (NULL-terminated) + pathcomp: filename + + mapname(): + loop over chars in zipfile member name + checkdir(path component, COMPONENT | CREATEDIR) --> map as required? + (d:/tmp/unzip/) (disk:[tmp.unzip.) + (d:/tmp/unzip/jj/) (disk:[tmp.unzip.jj.) + (d:/tmp/unzip/jj/temp/) (disk:[tmp.unzip.jj.temp.) + finally add filename itself and check for existence? (could use with rename) + (d:/tmp/unzip/jj/temp/msg.outdir) (disk:[tmp.unzip.jj.temp]msg.outdir) + checkdir(name, GETPATH) --> copy path to name and free space + +#endif /* 0 */ + + + + +/***********************/ +/* Function checkdir() */ +/***********************/ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename + * MPN_INF_SKIP - path doesn't exist, not allowed to create + * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path + * exists and is not a directory, but is supposed to be + * MPN_ERR_TOOLONG - path is too long + * MPN_NOMEM - can't allocate memory for filename buffers + */ +{ + static int rootlen = 0; /* length of rootpath */ + static char *rootpath; /* user's "extract-to" directory */ + static char *buildpath; /* full path (so far) to extracted file */ + static char *end; /* pointer to end of buildpath ('\0') */ + +# define FN_MASK 7 +# define FUNCTION (flag & FN_MASK) + + +/*--------------------------------------------------------------------------- + APPEND_DIR: append the path component to the path being built and check + for its existence. If doesn't exist and we are creating directories, do + so for this one; else signal success or error as appropriate. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_DIR) { + int too_long = FALSE; +/* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */ +#ifdef SHORT_NAMES + char *old_end = end; +#endif + + Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') + ++end; +/* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */ +#ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ + if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ + *(end = old_end + FILENAME_MAX) = '\0'; +#endif + + /* GRR: could do better check, see if overrunning buffer as we go: + * check end-buildpath after each append, set warning variable if + * within 20 of FILNAMSIZ; then if var set, do careful check when + * appending. Clear variable when begin new path. */ + + if ((end-buildpath) > FILNAMSIZ-3) /* need '/', one-char name, '\0' */ + too_long = TRUE; /* check if extracting directory? */ + if (stat(buildpath, &G.statbuf)) { /* path doesn't exist */ + if (!G.create_dirs) { /* told not to create (freshening) */ + free(buildpath); + return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", + FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + if (mkdir(buildpath, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, + "checkdir error: cannot create %s\n\ + unable to process %s.\n", + FnFilter2(buildpath), FnFilter1(G.filename))); + free(buildpath); + /* path didn't exist, tried to create, failed */ + return MPN_ERR_SKIP; + } + created_dir = TRUE; + } else if (!S_ISDIR(G.statbuf.st_mode)) { + Info(slide, 1, ((char *)slide, + "checkdir error: %s exists but is not directory\n\ + unable to process %s.\n", + FnFilter2(buildpath), FnFilter(G.filename))); + free(buildpath); + /* path existed but wasn't dir */ + return MPN_ERR_SKIP; + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + *end++ = '/'; + *end = '\0'; + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + return MPN_OK; + + } /* end if (FUNCTION == APPEND_DIR) */ + +/*--------------------------------------------------------------------------- + GETPATH: copy full path to the string pointed at by pathcomp, and free + buildpath. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == GETPATH) { + strcpy(pathcomp, buildpath); + Trace((stderr, "getting and freeing path [%s]\n", + FnFilter1(pathcomp))); + free(buildpath); + buildpath = end = (char *)NULL; + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + APPEND_NAME: assume the path component is the filename; append it and + return without checking for existence. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_NAME) { +/* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */ +#ifdef SHORT_NAMES + char *old_end = end; +#endif + + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') { + ++end; +/* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */ +#ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ + if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ + *(end = old_end + FILENAME_MAX) = '\0'; +#endif + if ((end-buildpath) >= FILNAMSIZ) { + *--end = '\0'; + Info(slide, 0x201, ((char *)slide, + "checkdir warning: path too long; truncating\n\ + %s\n -> %s\n", + FnFilter1(G.filename), FnFilter2(buildpath))); + return MPN_INF_TRUNC; /* filename truncated */ + } + } + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + /* could check for existence here, prompt for new name... */ + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + INIT: allocate and initialize buffer space for the file currently being + extracted. If file was renamed with an absolute path, don't prepend the + extract-to path. + ---------------------------------------------------------------------------*/ + +/* GRR: for VMS and TOPS-20, add up to 13 to strlen */ + + if (FUNCTION == INIT) { + Trace((stderr, "initializing buildpath to ")); +#ifdef ACORN_FTYPE_NFS + if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+ + (uO.acorn_nfs_ext ? 5 : 1))) +#else + if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1)) +#endif + == (char *)NULL) + return MPN_NOMEM; + if ((rootlen > 0) && !renamed_fullpath) { + strcpy(buildpath, rootpath); + end = buildpath + rootlen; + } else { + *buildpath = '\0'; + end = buildpath; + } + Trace((stderr, "[%s]\n", FnFilter1(buildpath))); + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + ROOT: if appropriate, store the path in rootpath and create it if + necessary; else assume it's a zipfile member and return. This path + segment gets used in extracting all members from every zipfile specified + on the command line. + ---------------------------------------------------------------------------*/ + +#if (!defined(SFX) || defined(SFX_EXDIR)) + if (FUNCTION == ROOT) { + Trace((stderr, "initializing root path to [%s]\n", pathcomp)); + if (pathcomp == (char *)NULL) { + rootlen = 0; + return MPN_OK; + } + if (rootlen > 0) /* rootpath was already set, nothing to do */ + return MPN_OK; + if ((rootlen = strlen(pathcomp)) > 0) { + char *tmproot; + + if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) { + rootlen = 0; + return MPN_NOMEM; + } + strcpy(tmproot, pathcomp); + if (tmproot[rootlen-1] == '/') { + tmproot[--rootlen] = '\0'; + } + if (rootlen > 0 && (stat(tmproot, &G.statbuf) || + !S_ISDIR(G.statbuf.st_mode))) + { /* path does not exist */ + if (!G.create_dirs /* || iswild(tmproot) */ ) { + free(tmproot); + rootlen = 0; + /* skip (or treat as stored file) */ + return MPN_INF_SKIP; + } + /* create the directory (could add loop here scanning tmproot + * to create more than one level, but why really necessary?) */ + if (mkdir(tmproot, 0777) == -1) { + Info(slide, 1, ((char *)slide, + "checkdir: cannot create extraction directory: %s\n", + FnFilter1(tmproot))); + free(tmproot); + rootlen = 0; + /* path didn't exist, tried to create, and failed: */ + /* file exists, or 2+ subdir levels required */ + return MPN_ERR_SKIP; + } + } + tmproot[rootlen++] = '/'; + tmproot[rootlen] = '\0'; + if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { + free(tmproot); + rootlen = 0; + return MPN_NOMEM; + } + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath))); + } + return MPN_OK; + } +#endif /* !SFX || SFX_EXDIR */ + +/*--------------------------------------------------------------------------- + END: free rootpath, immediately prior to program exit. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == END) { + Trace((stderr, "freeing rootpath\n")); + if (rootlen > 0) { + free(rootpath); + rootlen = 0; + } + return MPN_OK; + } + + return MPN_INVALID; /* should never reach */ + +} /* end function checkdir() */ + + + + + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) /* GRR: change to return PK-style warning level */ + __GDEF +{ +#ifdef USE_EF_UT_TIME + unsigned eb_izux_flg; + iztimes zt; +#endif + ztimbuf tp; + +/*--------------------------------------------------------------------------- + If symbolic links are supported, allocate storage for a symlink control + structure, put the uncompressed "data" and other required info in it, and + add the structure to the "deferred symlinks" chain. Since we know it's a + symbolic link to start with, we shouldn't have to worry about overflowing + unsigned ints with unsigned longs. + ---------------------------------------------------------------------------*/ + + /* symlinks allowed on minix filesystems [cjh] + * Hopefully this will work properly... We won't bother to try if + * MiNT isn't present; the symlink should fail if we're on a TOS + * filesystem. + * BUG: should we copy the original file to the "symlink" if the + * link fails? + */ + if (G.symlnk) { + extent ucsize = (extent)G.lrec.ucsize; + /* size of the symlink entry is the sum of + * (struct size (includes 1st '\0') + 1 additional trailing '\0'), + * system specific attribute data size (might be 0), + * and the lengths of name and link target. + */ + extent slnk_entrysize = (sizeof(slinkentry) + 1) + + ucsize + strlen(G.filename); + slinkentry *slnk_entry; + + if (slnk_entrysize < ucsize) { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed: mem alloc overflow\n", + FnFilter1(G.filename))); + fclose(G.outfile); + return; + } + + if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed: no mem\n", + FnFilter1(G.filename))); + fclose(G.outfile); + return; + } + slnk_entry->next = NULL; + slnk_entry->targetlen = ucsize; + slnk_entry->attriblen = 0; /* don't set attributes for symlinks */ + slnk_entry->target = slnk_entry->buf; + slnk_entry->fname = slnk_entry->target + ucsize + 1; + strcpy(slnk_entry->fname, G.filename); + + /* move back to the start of the file to re-read the "link data" */ + rewind(G.outfile); + + if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize) + { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed\n", + FnFilter1(G.filename))); + free(slnk_entry); + fclose(G.outfile); + return; + } + fclose(G.outfile); /* close "link" file for good... */ + slnk_entry->target[ucsize] = '\0'; + if (QCOND2) + Info(slide, 0, ((char *)slide, "-> %s ", + FnFilter1(slnk_entry->target))); + /* add this symlink record to the list of deferred symlinks */ + if (G.slink_last != NULL) + G.slink_last->next = slnk_entry; + else + G.slink_head = slnk_entry; + G.slink_last = slnk_entry; + return; + } + + fclose(G.outfile); + +/*--------------------------------------------------------------------------- + Convert from MSDOS-format local time and date to Unix-format 32-bit GMT + time: adjust base year from 1980 to 1970, do usual conversions from + yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day- + light savings time differences. + ---------------------------------------------------------------------------*/ + + /* skip restoring time stamps on user's request */ + if (uO.D_flag <= 1) { +#ifdef USE_EF_UT_TIME + eb_izux_flg = (G.extra_field +#ifdef IZ_CHECK_TZ + && G.tz_is_valid +#endif + ? ef_scan_for_izux(G.extra_field, + G.lrec.extra_field_length, 0, + G.lrec.last_mod_dos_datetime, &zt, NULL) + : 0); + if (eb_izux_flg & EB_UT_FL_MTIME) { + tp.modtime = zt.mtime; + TTrace((stderr, + "\nclose_outfile: Unix e.f. modif. time = %ld\n", + tp.modtime)); + } else { + tp.modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); + } + if (eb_izux_flg & EB_UT_FL_ATIME) { + tp.actime = zt.atime; + TTrace((stderr, + "close_outfile: Unix e.f. access time = %ld\n", + tp.actime)); + } else { + tp.actime = tp.modtime; + TTrace((stderr, + "\nclose_outfile: modification/access times = %ld\n", + tp.modtime)); + } +#else /* !USE_EF_UT_TIME */ + tp.actime = tp.modtime + = dos_to_unix_time(G.lrec.last_mod_dos_datetime); + + TTrace((stderr, "\nclose_outfile: modification/access times = %ld\n", + tp.modtime)); +#endif /* ?USE_EF_UT_TIME */ + + /* set the file's access and modification times */ + if (utime(G.filename, &tp)) + Info(slide, 0x201, ((char *)slide, + "warning: cannot set the time for %s\n", + FnFilter1(G.filename))); + } + +/*--------------------------------------------------------------------------- + Change the file permissions from default ones to those stored in the + zipfile. + ---------------------------------------------------------------------------*/ + +#ifndef NO_CHMOD + if (chmod(G.filename, 0xffff & G.pInfo->file_attr)) + perror("chmod (file attributes) error"); +#endif + +} /* end function close_outfile() */ + + + + +#ifdef TIMESTAMP + +/***************************/ +/* Function stamp_file() */ +/***************************/ + +int stamp_file(fname, modtime) + ZCONST char *fname; + time_t modtime; +{ + ztimbuf tp; + + tp.modtime = tp.actime = modtime; + return (utime(fname, &tp)); + +} /* end function stamp_file() */ + +#endif /* TIMESTAMP */ + + + + +#ifndef SFX + +/************************/ +/* Function version() */ +/************************/ + +void version(__G) + __GDEF +{ +#ifdef __TURBOC__ + char buf[40]; +#endif + + sprintf((char *)slide, LoadFarString(CompiledWith), + +#ifdef __GNUC__ + "gcc ", __VERSION__, +#else +# if 0 + "cc ", (sprintf(buf, " version %d", _RELEASE), buf), +# else +# ifdef __TURBOC__ + "Turbo C", (sprintf(buf, " (0x%04x = %d)", __TURBOC__, __TURBOC__), buf), +# else + "unknown compiler", "", +# endif +# endif +#endif + +#ifdef __MINT__ + "Atari TOS/MiNT", +#else + "Atari TOS", +#endif + + " (Atari ST/TT/Falcon030)", + +#ifdef __DATE__ + " on ", __DATE__ +#else + "", "" +#endif + ); + + (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0); + +} /* end function version() */ + +#endif /* !SFX */ diff --git a/atari/make_unz.mup b/atari/make_unz.mup new file mode 100644 index 0000000..9ab2543 --- /dev/null +++ b/atari/make_unz.mup @@ -0,0 +1,8 @@ +#rm -f *.o *.ttp *.sym +#make370 SHELL=/bin/mupfel.ttp CFLAGS=" -O -DATARI" unzips +make370 SHELL=/bin/mupfel.ttp CFLAGS="-g -D__NO_INLINE__ -DATARI" E=.ttp unzip.ttp LF2= +make370 SHELL=/bin/mupfel.ttp CFLAGS="-g -D__NO_INLINE__ -DATARI" E=.sym unzip.sym LF2="-B/bin/sym-" +#make370 SHELL=/bin/mupfel.ttp CFLAGS="-O -DATARI" -n unzips > make_all.mup +#fixstk 32K pgp.ttp +prgflags 017 007 *.ttp + diff --git a/atheos/Contents b/atheos/Contents new file mode 100644 index 0000000..3068255 --- /dev/null +++ b/atheos/Contents @@ -0,0 +1,10 @@ +Contents of the "atheos" sub-directory for UnZip 5.52 and later: + + Contents this file + README notes from the author of the AtheOS port + Makefile makefile for building UnZip + athcfg.h AtheOS-specific configuration settings + atheos.c AtheOS-specific routines (similar to the BeOS/Unix ones) + atheos.h structures for the AtheOS extra field + +- Ruslan Nickolaev (nruslan@hotbox.ru) diff --git a/atheos/Makefile b/atheos/Makefile new file mode 100644 index 0000000..1eac334 --- /dev/null +++ b/atheos/Makefile @@ -0,0 +1,322 @@ +###################################################################### +# +# Makefile for Info-ZIP's unzip, unzipsfx, and funzip on AtheOS +# Version 5.53 +# +# Copyright (C) 1998-2006 Info-ZIP +# Chris Herborth (chrish@qnx.com) +# Copyright (C) 2004 Nikolaev Ruslan (nruslan@hotbox.ru) +# +# To automatically install the fresh new unzip, use the "install" target: +# make -f atheos/Makefile install +###################################################################### +SHELL = /bin/bash + +# Punish those of you not running on SMP hardware... +MAKE = make -j 4 -f atheos/Makefile + +# UnZipSFX flags +SL = -o unzipsfx +SL2 = $(LF2) + +# fUnZip flags +FL = -o funzip +FL2 = $(LF2) + +# general-purpose stuff +CP = cp +AS = as +RM = rm -f +LN = ln -sf +CHMOD = chmod +E = +O = .o +M = atheos + +OSDEP_H = atheos/athcfg.h + +# define + +# object files +OBJS1 = unzip$O crc32$O crc_i386$O crypt$O envargs$O explode$O +OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O +OBJS3 = process$O ttyio$O ubz2err$O unreduce$O unshrink$O zipinfo$O +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O +LOBJS = $(OBJS) +OBJSDLL = $(OBJS) api$O +OBJX = unzipsfx$O crc32_$O crc_i386$O crypt_$O extract_$O fileio_$O globals_$O inflate_$O match_$O process_$O ttyio_$O ubz2err_$O $M_$O +LOBJX = $(OBJX) +OBJF = funzip$O crc32f$O crc_i386$O cryptf$O globalsf$O inflatef$O ttyiof$O +UNZIP_H = unzip.h unzpriv.h globals.h $(OSDEP_H) + +# installation +INSTALL = install +manext = 1 +prefix = /usr +BINDIR = $(prefix)/bin +MANDIR = $(prefix)/man/man$(manext) +INSTALLEDBIN = $(BINDIR)/funzip$E $(BINDIR)/zipinfo$E $(BINDIR)/unzipsfx$E $(BINDIR)/unzip$E +INSTALLEDMAN = $(MANDIR)/unzip.$(manext) $(MANDIR)/funzip.$(manext) $(MANDIR)/unzipsfx.$(manext) $(MANDIR)/zipinfo.$(manext) +# +UNZIPS = unzip$E funzip$E unzipsfx$E zipinfo$E +# this is a little ugly...well, no, it's a lot ugly: +MANS = man/unzip.1 man/unzipsfx.1 man/zipinfo.1 man/funzip.1 man/zipgrep.1 + +###################################################################### +CC=gcc +LD=gcc +CF=-O3 -march=i586 -Wall -I. -DPASSWD_FROM_STDIN -DASM_CRC -DUSE_UNSHRINK $(LOCAL_UNZIP) +LF=-o unzip +LF2= +TARGET=$(UNZIPS) +###################################################################### +# Helpful targets +all: + @echo 'TARGET = $(TARGET)' + @echo 'CC = $(CC)' + if [ -n "$(TARGET)" ] ; then \ + $(MAKE) CC=$(CC) CF="$(CF)" LD="$(LD)" \ + LF="$(LF)" LF2="$(LF2)" CCPP="$(CC)" CPPF="$(CF)" \ + OBJS="$(OBJS)" LOBJS="$(LOBJS)" OBJX="$(OBJX)" \ + LOBJX="$(LOBJX)" $(TARGET) ; \ + else \ + $(MAKE) help ; \ + fi + +help: + @echo '' + @echo "This Makefile lets you build Info-ZIP's zip." + @echo '' + @echo 'To build zip for this computer using the default compiler, just do:' + @echo '' + @echo ' make -f atheos/Makefile' + @echo '' + +###################################################################### +# Basic compile instructions and dependencies + +# this is for GNU make; comment out and notify zip-bugs if it causes errors +.SUFFIXES: .c .o + +# default for compiling C files +.c.o: + $(CC) -c $(CF) $*.c + + +unzips: $(UNZIPS) +objs: $(OBJS) +objsdll: $(OBJSDLL) +unzipsman: unzips + + +unzip$E: $(OBJS) + $(LD) $(LF) $(LOBJS) $(LF2) + $(CHMOD) +x unzip$E + +unzipsfx$E: $(OBJX) + $(LD) $(SL) $(LOBJX) $(SL2) + $(CHMOD) +x unzipsfx$E + +funzip$E: $(OBJF) + $(LD) $(FL) $(OBJF) $(FL2) + $(CHMOD) +x funzip$E + +zipinfo$E: unzip$E + $(LN) unzip$E zipinfo$E + +crc32$O: crc32.c $(UNZIP_H) zip.h crc32.h +crypt$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +envargs$O: envargs.c $(UNZIP_H) +explode$O: explode.c $(UNZIP_H) +extract$O: extract.c $(UNZIP_H) crc32.h crypt.h +fileio$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +funzip$O: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h +globals$O: globals.c $(UNZIP_H) +inflate$O: inflate.c inflate.h $(UNZIP_H) +list$O: list.c $(UNZIP_H) +match$O: match.c $(UNZIP_H) +process$O: process.c $(UNZIP_H) crc32.h +ttyio$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ubz2err$O: ubz2err.c $(UNZIP_H) +unreduce$O: unreduce.c $(UNZIP_H) +unshrink$O: unshrink.c $(UNZIP_H) +unzip$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +zipinfo$O: zipinfo.c $(UNZIP_H) + +crc_i386$O: crc_i386.S + $(CC) -E crc_i386.S > crc_i386s.s + $(AS) -o $@ crc_i386s.s + $(RM) crc_i386s.s + +# unzipsfx only +unzipsfx$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h + $(CP) unzip.c unzipsfx.c + $(CC) -c $(CF) -DSFX unzipsfx.c + $(RM) unzipsfx.c + +crc32_$O: crc32.c $(UNZIP_H) zip.h crc32.h + $(CP) crc32.c crc32_.c + $(CC) -c $(CF) -DSFX crc32_.c + $(RM) crc32_.c + +crypt_$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CP) crypt.c crypt_.c + $(CC) -c $(CF) -DSFX crypt_.c + $(RM) crypt_.c + +extract_$O: extract.c $(UNZIP_H) crc32.h crypt.h + $(CP) extract.c extract_.c + $(CC) -c $(CF) -DSFX extract_.c + $(RM) extract_.c + +fileio_$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h + $(CP) fileio.c fileio_.c + $(CC) -c $(CF) -DSFX fileio_.c + $(RM) fileio_.c + +globals_$O: globals.c $(UNZIP_H) + $(CP) globals.c globals_.c + $(CC) -c $(CF) -DSFX globals_.c + $(RM) globals_.c + +inflate_$O: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CP) inflate.c inflate_.c + $(CC) -c $(CF) -DSFX inflate_.c + $(RM) inflate_.c + +match_$O: match.c + $(CP) match.c match_.c + $(CC) -c $(CF) -DSFX match_.c + $(RM) match_.c + +process_$O: process.c $(UNZIP_H) crc32.h + $(CP) process.c process_.c + $(CC) -c $(CF) -DSFX process_.c + $(RM) process_.c + +ttyio_$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CP) ttyio.c ttyio_.c + $(CC) -c $(CF) -DSFX ttyio_.c + $(RM) ttyio_.c + +ubz2err$O: ubz2err.c $(UNZIP_H) + $(CP) ubz2err.c ubz2err_.c + $(CC) -c $(CF) -DSFX ubz2err_.c + $(RM) ubz2err_.c + +# funzip only +crc32f$O: crc32.c $(UNZIP_H) zip.h crc32.h + $(CP) crc32.c crc32f.c + $(CC) -c $(CF) -DFUNZIP crc32f.c + $(RM) crc32f.c + +cryptf$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CP) crypt.c cryptf.c + $(CC) -c $(CF) -DFUNZIP cryptf.c + $(RM) cryptf.c + +globalsf$O: globals.c $(UNZIP_H) + $(CP) globals.c globalsf.c + $(CC) -c $(CF) -DFUNZIP globalsf.c + $(RM) globalsf.c + +inflatef$O: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CP) inflate.c inflatef.c + $(CC) -c $(CF) -DFUNZIP inflatef.c + $(RM) inflatef.c + +ttyiof$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CP) ttyio.c ttyiof.c + $(CC) -c $(CF) -DFUNZIP ttyiof.c + $(RM) ttyiof.c + +# AtheOS specific code +atheos$O: atheos/atheos.c $(UNZIP_H) unzvers.h atheos/atheos.h + $(CC) -c $(CF) atheos/atheos.c + +# version() not used by unzipsfx, so no unzvers.h dependency +atheos_$O: atheos/atheos.c $(UNZIP_H) atheos/atheos.h # unzipsfx only + $(CP) atheos/atheos.c atheos_.c + $(CC) -c $(CF) -Iatheos -DSFX atheos_.c + $(RM) atheos_.c + +# this really only works for Unix targets, unless E and O specified on cmd line +clean: + $(RM) $(UNZIPS) $(OBJS) $(OBJF) $(OBJX) api$O apihelp$O crc_gcc$O unzipstb$O + +install: all + $(INSTALL) -m 755 $(UNZIPS) $(BINDIR) + $(RM) $(BINDIR)/zipinfo$E + $(LN) unzip$E $(BINDIR)/zipinfo$E + $(RM) $(BINDIR)/zipgrep$E + $(INSTALL) -m 755 unix/zipgrep $(BINDIR)/zipgrep$E + $(INSTALL) -m 644 man/unzip.1 $(MANDIR)/unzip.$(manext) + $(INSTALL) -m 644 man/unzipsfx.1 $(MANDIR)/unzipsfx.$(manext) + $(INSTALL) -m 644 man/zipinfo.1 $(MANDIR)/zipinfo.$(manext) + $(INSTALL) -m 644 man/funzip.1 $(MANDIR)/funzip.$(manext) + $(INSTALL) -m 644 man/zipgrep.1 $(MANDIR)/zipgrep.$(manext) + +# alternatively, could use zip method: -cd $(BINDIR); $(RM) $(UNZIPS) [etc.] +uninstall: + $(RM) $(INSTALLEDBIN) $(INSTALLEDMAN) + + +TESTZIP = testmake.zip # the test zipfile + +# test some basic features of the build +test: check + +check: + @echo '##### This is a Unix-specific target. (Just so you know.)' + @echo '##### Make sure unzip, funzip and unzipsfx are compiled and' + @echo '##### in this directory.' + @if test ! -f ./unzip; then \ + echo "##### ERROR: can't find ./unzip"; exit 1; fi + @if test ! -f ./funzip; then \ + echo "##### ERROR: can't find ./funzip"; exit 1; fi + @if test ! -f ./unzipsfx; then \ + echo "##### ERROR: can't find ./unzipsfx"; exit 1; fi +# + @if test ! -f $(TESTZIP); then \ + echo "##### ERROR: can't find test file $(TESTZIP)"; exit 1; fi +# + @echo "##### testing extraction" + @./unzip -bo $(TESTZIP) testmake.zipinfo + @if test ! -f testmake.zipinfo ; then \ + echo "##### ERROR: file extraction from $(TESTZIP) failed"; \ + exit 1; fi +# + @echo '##### testing zipinfo (unzip -Z)' + @./unzip -Z $(TESTZIP) > testmake.unzip-Z + @if diff testmake.unzip-Z testmake.zipinfo; then echo "OK."; else \ + echo "##### WARNING: zipinfo output doesn't match stored version"; \ + echo '##### (If the only difference is the file times, compare your'; \ + echo '##### timezone with the Central European timezone, which is one'; \ + echo '##### hour east of Greenwich but effectively 2 hours east'; \ + echo '##### during summer Daylight Savings Time. The upper two'; \ + echo '##### lines should correspond to your local time when the'; \ + echo '##### files were created, on 19 November 1998 at 10:46pm CET.'; \ + echo '##### If the times are consistent, please ignore this warning.)'; \ + fi + @$(RM) testmake.unzip-Z testmake.zipinfo +# + @echo '##### testing unzip -d exdir option' + @./unzip -bo $(TESTZIP) -d testun notes + @cat testun/notes +# + @echo '##### testing unzip -o and funzip (ignore funzip warning)' + @./unzip -boq $(TESTZIP) notes -d testun + @./funzip < $(TESTZIP) > testun/notes2 + @if diff testun/notes testun/notes2; then true; else \ + echo '##### ERROR: funzip output disagrees with unzip'; fi +# + @echo '##### testing unzipsfx (self-extractor)' + @cat unzipsfx $(TESTZIP) > testsfx + @$(CHMOD) 0700 testsfx + @./testsfx -bo notes + @if diff notes testun/notes; then true; else \ + echo '##### ERROR: unzipsfx file disagrees with unzip'; fi + @$(RM) testsfx notes testun/notes testun/notes2 + @rmdir testun +# + @echo '##### testing complete.' diff --git a/atheos/README b/atheos/README new file mode 100644 index 0000000..0a42840 --- /dev/null +++ b/atheos/README @@ -0,0 +1,16 @@ +UnZip 5.51 for AtheOS/Syllable + +This port is based on both BeOS and UNIX versions. +As BeOS version it can extract specific file attributes. + +TODO +---- +There is only one thing to be fixed: + write_attr() should return count of bytes written. However that's a bug + related with AFS only. + +Please report any bugs to Zip-Bugs@lists.wku.edu. +If this bug related with AtheOS/Syllable only, you can mail me directly: + nruslan@hotbox.ru. +- Ruslan Nickolaev (nruslan@hotbox.ru) + Sep 06/2004 diff --git a/atheos/athcfg.h b/atheos/athcfg.h new file mode 100644 index 0000000..d5dc01c --- /dev/null +++ b/atheos/athcfg.h @@ -0,0 +1,70 @@ +/* + Copyright (c) 1990-2004 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 +*/ +/*--------------------------------------------------------------------------- + AtheOS/Syllable specific configuration section: + ---------------------------------------------------------------------------*/ + +#ifndef __athcfg_h +#define __athcfg_h + + /* ensure that Unix-specific code portions are excluded */ +#ifdef UNIX +# undef UNIX +#endif +#include /* off_t, time_t, dev_t, ... */ +#include +#include +#include /* O_BINARY for open() w/o CR/LF translation */ +#include +#include +#include +#include + +#define GOT_UTIMBUF +#define DIRENT +#if (!defined(HAVE_STRNICMP) & !defined(NO_STRNICMP)) +# define NO_STRNICMP +#endif +#define INT_SPRINTF +#define SYMLINKS + +#ifndef DATE_FORMAT +# define DATE_FORMAT DF_MDY /* GRR: customize with locale.h somehow? */ +#endif +#define lenEOL 1 +#define PutNativeEOL *q++ = native(LF); +#define SCREENSIZE(ttrows, ttcols) screensize(ttrows, ttcols) +#define SCREENWIDTH 80 +#define SCREENLWRAP 1 +#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)) +# define USE_EF_UT_TIME +#endif +#define SET_SYMLINK_ATTRIBS +#define SET_DIR_ATTRIB +#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) +# define TIMESTAMP +#endif +#define RESTORE_UIDGID + +/* Static variables that we have to add to Uz_Globs: */ +#define SYSTEM_SPECIFIC_GLOBALS \ + int created_dir, renamed_fullpath;\ + char *rootpath, *buildpath, *end;\ + ZCONST char *wildname;\ + char *dirname, matchname[FILNAMSIZ];\ + int rootlen, have_dirname, dirnamelen, notfirstcall;\ + zvoid *wild_dir; + +/* created_dir, and renamed_fullpath are used by both mapname() and */ +/* checkdir(). */ +/* rootlen, rootpath, buildpath and end are used by checkdir(). */ +/* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */ +/* and notfirstcall are used by do_wild(). */ + +#endif /* !__athcfg_h */ diff --git a/atheos/atheos.c b/atheos/atheos.c new file mode 100644 index 0000000..de76ddb --- /dev/null +++ b/atheos/atheos.c @@ -0,0 +1,1415 @@ +/* + Copyright (c) 1990-2008 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 +*/ +/*--------------------------------------------------------------------------- + + atheos.c by Ruslan Nickolaev (nruslan@hotbox.ru) + + AtheOS-specific routines for use with Info-ZIP's UnZip 5.51 and later. + (based on beos/beos.c and unix/unix.c) + + Contains: do_wild() <-- generic enough to put in fileio.c? + mapattr() + mapname() + checkdir() + close_outfile() + defer_dir_attribs() + set_direc_attribs() + stamp_file() + version() + scanAtheOSexfield() + set_file_attrs() + setAtheOSexfield() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" + +#include "atheos.h" +#include /* Just make sure we've got a few things... */ +#include +#include +#include +#include + +static unsigned filtattr OF((__GPRO__ unsigned perms)); +static uch *scanAtheOSexfield OF((const uch *ef_ptr, unsigned ef_len)); +static int set_file_attrs( const char *, const unsigned char *, const off_t ); +static void setAtheOSexfield OF((const char *path, uch *extra_field)); + +#ifdef SET_DIR_ATTRIB +typedef struct uxdirattr { /* struct for holding unix style directory */ + struct uxdirattr *next; /* info until can be sorted and set at end */ + char *fn; /* filename of directory */ + union { + iztimes t3; /* mtime, atime, ctime */ + ztimbuf t2; /* modtime, actime */ + } u; + unsigned perms; /* same as min_info.file_attr */ + int have_uidgid; /* flag */ + ulg uidgid[2]; + char fnbuf[1]; /* buffer stub for directory name */ +} uxdirattr; +#define UxAtt(d) ((uxdirattr *)d) /* typecast shortcut */ +#endif /* SET_DIR_ATTRIB */ + +#ifdef ACORN_FTYPE_NFS +/* Acorn bits for NFS filetyping */ +typedef struct { + uch ID[2]; + uch size[2]; + uch ID_2[4]; + uch loadaddr[4]; + uch execaddr[4]; + uch attr[4]; +} RO_extra_block; + +#endif /* ACORN_FTYPE_NFS */ + +/* static int created_dir; */ /* used in mapname(), checkdir() */ +/* static int renamed_fullpath; */ /* ditto */ + +#ifndef SFX + +/**********************/ +/* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ +/**********************/ + +char *do_wild(__G__ wildspec) + __GDEF + ZCONST char *wildspec; /* only used first time on a given dir */ +{ +/* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in athcfg.h: + static DIR *wild_dir = (DIR *)NULL; + static ZCONST char *wildname; + static char *dirname, matchname[FILNAMSIZ]; + static int notfirstcall=FALSE, have_dirname, dirnamelen; +*/ + struct dirent *file; + + /* Even when we're just returning wildspec, we *always* do so in + * matchname[]--calling routine is allowed to append four characters + * to the returned string, and wildspec may be a pointer to argv[]. + */ + if (!G.notfirstcall) { /* first call: must initialize everything */ + G.notfirstcall = TRUE; + + if (!iswild(wildspec)) { + strncpy(G.matchname, wildspec, FILNAMSIZ); + G.matchname[FILNAMSIZ-1] = '\0'; + G.have_dirname = FALSE; + G.wild_dir = NULL; + return G.matchname; + } + + /* break the wildspec into a directory part and a wildcard filename */ + if ((G.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL) { + G.dirname = "."; + G.dirnamelen = 1; + G.have_dirname = FALSE; + G.wildname = wildspec; + } else { + ++G.wildname; /* point at character after '/' */ + G.dirnamelen = G.wildname - wildspec; + if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == (char *)NULL) { + Info(slide, 0x201, ((char *)slide, + "warning: cannot allocate wildcard buffers\n")); + strncpy(G.matchname, wildspec, FILNAMSIZ); + G.matchname[FILNAMSIZ-1] = '\0'; + return G.matchname; /* but maybe filespec was not a wildcard */ + } + strncpy(G.dirname, wildspec, G.dirnamelen); + G.dirname[G.dirnamelen] = '\0'; /* terminate for strcpy below */ + G.have_dirname = TRUE; + } + + if ((G.wild_dir = (zvoid *)opendir(G.dirname)) != (zvoid *)NULL) { + while ((file = readdir((DIR *)G.wild_dir)) != + (struct dirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + if (file->d_name[0] == '.' && G.wildname[0] != '.') + continue; /* Unix: '*' and '?' do not match leading dot */ + if (match(file->d_name, G.wildname, 0 WISEP) &&/*0=case sens.*/ + /* skip "." and ".." directory entries */ + strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) { + Trace((stderr, "do_wild: match() succeeds\n")); + if (G.have_dirname) { + strcpy(G.matchname, G.dirname); + strcpy(G.matchname+G.dirnamelen, file->d_name); + } else + strcpy(G.matchname, file->d_name); + return G.matchname; + } + } + /* if we get to here directory is exhausted, so close it */ + closedir((DIR *)G.wild_dir); + G.wild_dir = (zvoid *)NULL; + } + Trace((stderr, "do_wild: opendir(%s) returns NULL\n", + FnFilter1(G.dirname))); + + /* return the raw wildspec in case that works (e.g., directory not + * searchable, but filespec was not wild and file is readable) */ + strncpy(G.matchname, wildspec, FILNAMSIZ); + G.matchname[FILNAMSIZ-1] = '\0'; + return G.matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if ((DIR *)G.wild_dir == (DIR *)NULL) { + G.notfirstcall = FALSE; /* nothing left--reset for new wildspec */ + if (G.have_dirname) + free(G.dirname); + return (char *)NULL; + } + + /* If we've gotten this far, we've read and matched at least one entry + * successfully (in a previous call), so dirname has been copied into + * matchname already. + */ + while ((file = readdir((DIR *)G.wild_dir)) != (struct dirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + if (file->d_name[0] == '.' && G.wildname[0] != '.') + continue; /* Unix: '*' and '?' do not match leading dot */ + if (match(file->d_name, G.wildname, 0 WISEP)) { /* 0 == case sens. */ + Trace((stderr, "do_wild: match() succeeds\n")); + if (G.have_dirname) { + /* strcpy(G.matchname, G.dirname); */ + strcpy(G.matchname+G.dirnamelen, file->d_name); + } else + strcpy(G.matchname, file->d_name); + return G.matchname; + } + } + + closedir((DIR *)G.wild_dir); /* at least one entry read; nothing left */ + G.wild_dir = (zvoid *)NULL; + G.notfirstcall = FALSE; /* reset for new wildspec */ + if (G.have_dirname) + free(G.dirname); + return (char *)NULL; + +} /* end function do_wild() */ + +#endif /* !SFX */ + + + + +#ifndef S_ISUID +# define S_ISUID 0004000 /* set user id on execution */ +#endif +#ifndef S_ISGID +# define S_ISGID 0002000 /* set group id on execution */ +#endif +#ifndef S_ISVTX +# define S_ISVTX 0001000 /* save swapped text even after use */ +#endif + +/************************/ +/* Function filtattr() */ +/************************/ +/* This is used to clear or keep the SUID and GID bits on file permissions. + * It's possible that a file in an archive could have one of these bits set + * and, unknown to the person unzipping, could allow others to execute the + * file as the user or group. The new option -K bypasses this check. + */ + +static unsigned filtattr(__G__ perms) + __GDEF + unsigned perms; +{ + /* keep setuid/setgid/tacky perms? */ + if (!uO.K_flag) + perms &= ~(S_ISUID | S_ISGID | S_ISVTX); + + return (0xffff & perms); +} /* end function filtattr() */ + + + + + +/**********************/ +/* Function mapattr() */ +/**********************/ + +int mapattr(__G) + __GDEF +{ + int r; + ulg tmp = G.crec.external_file_attributes; + + G.pInfo->file_attr = 0; + /* initialized to 0 for check in "default" branch below... */ + + switch (G.pInfo->hostnum) { + case AMIGA_: + tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */ + G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp); + break; + case THEOS_: + tmp &= 0xF1FFFFFFL; + if ((tmp & 0xF0000000L) != 0x40000000L) + tmp &= 0x01FFFFFFL; /* not a dir, mask all ftype bits */ + else + tmp &= 0x41FFFFFFL; /* leave directory bit as set */ + /* fall through! */ + case ATHEOS_: + case UNIX_: + case VMS_: + case ACORN_: + case ATARI_: + case BEOS_: + case QDOS_: + case TANDEM_: + r = FALSE; + G.pInfo->file_attr = (unsigned)(tmp >> 16); + if (G.pInfo->file_attr == 0 && G.extra_field) { + /* Some (non-Info-ZIP) implementations of Zip for Unix and + * VMS (and probably others ??) leave 0 in the upper 16-bit + * part of the external_file_attributes field. Instead, they + * store file permission attributes in some extra field. + * As a work-around, we search for the presence of one of + * these extra fields and fall back to the MSDOS compatible + * part of external_file_attributes if one of the known + * e.f. types has been detected. + * Later, we might implement extraction of the permission + * bits from the VMS extra field. But for now, the work-around + * should be sufficient to provide "readable" extracted files. + * (For ASI Unix e.f., an experimental remap of the e.f. + * mode value IS already provided!) + */ + ush ebID; + unsigned ebLen; + uch *ef = G.extra_field; + unsigned ef_len = G.crec.extra_field_length; + + while (!r && ef_len >= EB_HEADSIZE) { + ebID = makeword(ef); + ebLen = (unsigned)makeword(ef+EB_LEN); + if (ebLen > (ef_len - EB_HEADSIZE)) + /* discoverd some e.f. inconsistency! */ + break; + switch (ebID) { + case EF_ASIUNIX: + if (ebLen >= (EB_ASI_MODE+2)) { + G.pInfo->file_attr = + (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE)); + /* force stop of loop: */ + ef_len = (ebLen + EB_HEADSIZE); + break; + } + /* else: fall through! */ + case EF_PKVMS: + /* "found nondecypherable e.f. with perm. attr" */ + r = TRUE; + default: + break; + } + ef_len -= (ebLen + EB_HEADSIZE); + ef += (ebLen + EB_HEADSIZE); + } + } + if (!r) { +#ifdef SYMLINKS + /* Check if the file is a (POSIX-compatible) symbolic link. + * We restrict symlink support to those "made-by" hosts that + * are known to support symbolic links. + */ + G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) && + SYMLINK_HOST(G.pInfo->hostnum); +#endif + return 0; + } + /* fall through! */ + /* all remaining cases: expand MSDOS read-only bit into write perms */ + case FS_FAT_: + /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the + * Unix attributes in the upper 16 bits of the external attributes + * field, just like Info-ZIP's Zip for Unix. We try to use that + * value, after a check for consistency with the MSDOS attribute + * bits (see below). + */ + G.pInfo->file_attr = (unsigned)(tmp >> 16); + /* fall through! */ + case FS_HPFS_: + case FS_NTFS_: + case MAC_: + case TOPS20_: + default: + /* Ensure that DOS subdir bit is set when the entry's name ends + * in a '/'. Some third-party Zip programs fail to set the subdir + * bit for directory entries. + */ + if ((tmp & 0x10) == 0) { + extent fnlen = strlen(G.filename); + if (fnlen > 0 && G.filename[fnlen-1] == '/') + tmp |= 0x10; + } + /* read-only bit --> write perms; subdir bit --> dir exec bit */ + tmp = !(tmp & 1) << 1 | (tmp & 0x10) >> 4; + if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) { + /* keep previous G.pInfo->file_attr setting, when its "owner" + * part appears to be consistent with DOS attribute flags! + */ +#ifdef SYMLINKS + /* Entries "made by FS_FAT_" could have been zipped on a + * system that supports POSIX-style symbolic links. + */ + G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) && + (G.pInfo->hostnum == FS_FAT_); +#endif + return 0; + } + G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp); + break; + } /* end switch (host-OS-created-by) */ + + /* for originating systems with no concept of "group," "other," "system": */ + umask( (int)(tmp=umask(0)) ); /* apply mask to expanded r/w(/x) perms */ + G.pInfo->file_attr &= ~tmp; + + return 0; + +} /* end function mapattr() */ + + + + + +/************************/ +/* Function mapname() */ +/************************/ + +int mapname(__G__ renamed) + __GDEF + int renamed; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - caution (truncated filename) + * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) + * MPN_ERR_SKIP - error -> skip entry + * MPN_ERR_TOOLONG - error -> path is too long + * MPN_NOMEM - error (memory allocation failed) -> skip entry + * [also MPN_VOL_LABEL, MPN_CREATED_DIR] + */ +{ + char pathcomp[FILNAMSIZ]; /* path-component buffer */ + char *pp, *cp=(char *)NULL; /* character pointers */ + char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ +#ifdef ACORN_FTYPE_NFS + char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ + RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */ +#endif + int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ + int error = MPN_OK; + register unsigned workch; /* hold the character being tested */ + + +/*--------------------------------------------------------------------------- + Initialize various pointers and counters and stuff. + ---------------------------------------------------------------------------*/ + + if (G.pInfo->vollabel) + return MPN_VOL_LABEL; /* can't set disk volume labels in AtheOS */ + + /* can create path as long as not just freshening, or if user told us */ + G.create_dirs = (!uO.fflag || renamed); + + G.created_dir = FALSE; /* not yet */ + + /* user gave full pathname: don't prepend rootpath */ + G.renamed_fullpath = (renamed && (*G.filename == '/')); + + if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM) + return MPN_NOMEM; /* initialize path buffer, unless no memory */ + + *pathcomp = '\0'; /* initialize translation buffer */ + pp = pathcomp; /* point to translation buffer */ + if (uO.jflag) /* junking directories */ + cp = (char *)strrchr(G.filename, '/'); + if (cp == (char *)NULL) /* no '/' or not junking dirs */ + cp = G.filename; /* point to internal zipfile-member pathname */ + else + ++cp; /* point to start of last component of path */ + +/*--------------------------------------------------------------------------- + Begin main loop through characters in filename. + ---------------------------------------------------------------------------*/ + + while ((workch = (uch)*cp++) != 0) { + + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + if (strcmp(pathcomp, ".") == 0) { + /* don't bother appending "./" to the path */ + *pathcomp = '\0'; + } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { + /* "../" dir traversal detected, skip over it */ + *pathcomp = '\0'; + killed_ddot = TRUE; /* set "show message" flag */ + } + /* when path component is not empty, append it now */ + if (*pathcomp != '\0' && + ((error = checkdir(__G__ pathcomp, APPEND_DIR)) + & MPN_MASK) > MPN_INF_TRUNC) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ + break; + + case ';': /* VMS version (or DEC-20 attrib?) */ + lastsemi = pp; + *pp++ = ';'; /* keep for now; remove VMS ";##" */ + break; /* later, if requested */ + +#ifdef ACORN_FTYPE_NFS + case ',': /* NFS filetype extension */ + lastcomma = pp; + *pp++ = ','; /* keep for now; may need to remove */ + break; /* later, if requested */ +#endif + + default: + /* allow European characters in filenames: */ + if (isprint(workch) || (128 <= workch && workch <= 254)) + *pp++ = (char)workch; + } /* end switch */ + + } /* end while loop */ + + /* Show warning when stripping insecure "parent dir" path components */ + if (killed_ddot && QCOND2) { + Info(slide, 0, ((char *)slide, + "warning: skipped \"../\" path component(s) in %s\n", + FnFilter1(G.filename))); + if (!(error & ~MPN_MASK)) + error = (error & MPN_MASK) | PK_WARN; + } + +/*--------------------------------------------------------------------------- + Report if directory was created (and no file to create: filename ended + in '/'), check name to be sure it exists, and combine path and name be- + fore exiting. + ---------------------------------------------------------------------------*/ + + if (G.filename[strlen(G.filename) - 1] == '/') { + checkdir(__G__ G.filename, GETPATH); + if (G.created_dir) { + if (QCOND2) { + Info(slide, 0, ((char *)slide, " creating: %s\n", + FnFilter1(G.filename))); + } + + if (!uO.J_flag) { /* Handle the AtheOS extra field if present. */ + void *ptr = scanAtheOSexfield(G.extra_field, + G.lrec.extra_field_length); + if (ptr) { + setAtheOSexfield( G.filename, ptr ); + } + } + +#ifndef NO_CHMOD + /* set approx. dir perms (make sure can still read/write in dir) */ + if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr) | 0700)) + perror("chmod (directory attributes) error"); +#endif + + /* set dir time (note trailing '/') */ + return (error & ~MPN_MASK) | MPN_CREATED_DIR; + } + if (!uO.J_flag) { /* Handle the AtheOS extra field if present. */ + void *ptr = scanAtheOSexfield(G.extra_field, + G.lrec.extra_field_length); + if (ptr) { + setAtheOSexfield(G.filename, ptr); + } + } + + /* dir existed already; don't look for data to extract */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + *pp = '\0'; /* done with pathcomp: terminate it */ + + /* if not saving them, remove VMS version numbers (appended ";###") */ + if (!uO.V_flag && lastsemi) { + pp = lastsemi + 1; + while (isdigit((uch)(*pp))) + ++pp; + if (*pp == '\0') /* only digits between ';' and end: nuke */ + *lastsemi = '\0'; + } + + /* On UNIX (and compatible systems), "." and ".." are reserved for + * directory navigation and cannot be used as regular file names. + * These reserved one-dot and two-dot names are mapped to "_" and "__". + */ + if (strcmp(pathcomp, ".") == 0) + *pathcomp = '_'; + else if (strcmp(pathcomp, "..") == 0) + strcpy(pathcomp, "__"); + +#ifdef ACORN_FTYPE_NFS + /* translate Acorn filetype information if asked to do so */ + if (uO.acorn_nfs_ext && + (ef_spark = (RO_extra_block *) + getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) + != (RO_extra_block *)NULL) + { + /* file *must* have a RISC OS extra field */ + long ft = (long)makelong(ef_spark->loadaddr); + /*32-bit*/ + if (lastcomma) { + pp = lastcomma + 1; + while (isxdigit((uch)(*pp))) ++pp; + if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */ + } + if ((ft & 1<<31)==0) ft=0x000FFD00; + sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF); + } +#endif /* ACORN_FTYPE_NFS */ + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", + FnFilter1(G.filename))); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + + checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ + checkdir(__G__ G.filename, GETPATH); + + return error; + +} /* end function mapname() */ + + + + +/***********************/ +/* Function checkdir() */ +/***********************/ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename + * MPN_INF_SKIP - path doesn't exist, not allowed to create + * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path + * exists and is not a directory, but is supposed to be + * MPN_ERR_TOOLONG - path is too long + * MPN_NOMEM - can't allocate memory for filename buffers + */ +{ + /* static int rootlen = 0; */ /* length of rootpath */ + /* static char *rootpath; */ /* user's "extract-to" directory */ + /* static char *buildpath; */ /* full path (so far) to extracted file */ + /* static char *end; */ /* pointer to end of buildpath ('\0') */ + +# define FN_MASK 7 +# define FUNCTION (flag & FN_MASK) + + + +/*--------------------------------------------------------------------------- + APPEND_DIR: append the path component to the path being built and check + for its existence. If doesn't exist and we are creating directories, do + so for this one; else signal success or error as appropriate. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_DIR) { + int too_long = FALSE; +#ifdef SHORT_NAMES + char *old_end = end; +#endif + + Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); + while ((*G.end = *pathcomp++) != '\0') + ++G.end; +#ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ + if ((G.end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ + *(G.end = old_end + FILENAME_MAX) = '\0'; +#endif + + /* GRR: could do better check, see if overrunning buffer as we go: + * check end-buildpath after each append, set warning variable if + * within 20 of FILNAMSIZ; then if var set, do careful check when + * appending. Clear variable when begin new path. */ + + /* next check: need to append '/', at least one-char name, '\0' */ + if ((G.end-G.buildpath) > FILNAMSIZ-3) + too_long = TRUE; /* check if extracting dir? */ + if (SSTAT(G.buildpath, &G.statbuf)) { /* path doesn't exist */ + if (!G.create_dirs) { /* told not to create (freshening) */ + free(G.buildpath); + return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", + FnFilter1(G.buildpath))); + free(G.buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + if (mkdir(G.buildpath, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, + "checkdir error: cannot create %s\n\ + unable to process %s.\n", + FnFilter2(G.buildpath), FnFilter1(G.filename))); + free(G.buildpath); + /* path didn't exist, tried to create, failed */ + return MPN_ERR_SKIP; + } + G.created_dir = TRUE; + } else if (!S_ISDIR(G.statbuf.st_mode)) { + Info(slide, 1, ((char *)slide, + "checkdir error: %s exists but is not directory\n\ + unable to process %s.\n", + FnFilter2(G.buildpath), FnFilter1(G.filename))); + free(G.buildpath); + /* path existed but wasn't dir */ + return MPN_ERR_SKIP; + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", FnFilter1(G.buildpath))); + free(G.buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + *G.end++ = '/'; + *G.end = '\0'; + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); + return MPN_OK; + + } /* end if (FUNCTION == APPEND_DIR) */ + +/*--------------------------------------------------------------------------- + GETPATH: copy full path to the string pointed at by pathcomp, and free + G.buildpath. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == GETPATH) { + strcpy(pathcomp, G.buildpath); + Trace((stderr, "getting and freeing path [%s]\n", + FnFilter1(pathcomp))); + free(G.buildpath); + G.buildpath = G.end = (char *)NULL; + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + APPEND_NAME: assume the path component is the filename; append it and + return without checking for existence. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_NAME) { +#ifdef SHORT_NAMES + char *old_end = end; +#endif + + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); + while ((*G.end = *pathcomp++) != '\0') { + ++G.end; +#ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ + if ((G.end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ + *(G.end = old_end + FILENAME_MAX) = '\0'; +#endif + if ((G.end-G.buildpath) >= FILNAMSIZ) { + *--G.end = '\0'; + Info(slide, 0x201, ((char *)slide, + "checkdir warning: path too long; truncating\n\ + %s\n -> %s\n", + FnFilter1(G.filename), FnFilter2(G.buildpath))); + return MPN_INF_TRUNC; /* filename truncated */ + } + } + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); + /* could check for existence here, prompt for new name... */ + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + INIT: allocate and initialize buffer space for the file currently being + extracted. If file was renamed with an absolute path, don't prepend the + extract-to path. + ---------------------------------------------------------------------------*/ + +/* GRR: for VMS and TOPS-20, add up to 13 to strlen */ + + if (FUNCTION == INIT) { + Trace((stderr, "initializing buildpath to ")); +#ifdef ACORN_FTYPE_NFS + if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+ + (uO.acorn_nfs_ext ? 5 : 1))) +#else + if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1)) +#endif + == (char *)NULL) + return MPN_NOMEM; + if ((G.rootlen > 0) && !G.renamed_fullpath) { + strcpy(G.buildpath, G.rootpath); + G.end = G.buildpath + G.rootlen; + } else { + *G.buildpath = '\0'; + G.end = G.buildpath; + } + Trace((stderr, "[%s]\n", FnFilter1(G.buildpath))); + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + ROOT: if appropriate, store the path in rootpath and create it if + necessary; else assume it's a zipfile member and return. This path + segment gets used in extracting all members from every zipfile specified + on the command line. + ---------------------------------------------------------------------------*/ + +#if (!defined(SFX) || defined(SFX_EXDIR)) + if (FUNCTION == ROOT) { + Trace((stderr, "initializing root path to [%s]\n", + FnFilter1(pathcomp))); + if (pathcomp == (char *)NULL) { + G.rootlen = 0; + return MPN_OK; + } + if (G.rootlen > 0) /* rootpath was already set, nothing to do */ + return MPN_OK; + if ((G.rootlen = strlen(pathcomp)) > 0) { + char *tmproot; + + if ((tmproot = (char *)malloc(G.rootlen+2)) == (char *)NULL) { + G.rootlen = 0; + return MPN_NOMEM; + } + strcpy(tmproot, pathcomp); + if (tmproot[G.rootlen-1] == '/') { + tmproot[--G.rootlen] = '\0'; + } + if (G.rootlen > 0 && (SSTAT(tmproot, &G.statbuf) || + !S_ISDIR(G.statbuf.st_mode))) + { /* path does not exist */ + if (!G.create_dirs /* || iswild(tmproot) */ ) { + free(tmproot); + G.rootlen = 0; + /* skip (or treat as stored file) */ + return MPN_INF_SKIP; + } + /* create the directory (could add loop here scanning tmproot + * to create more than one level, but why really necessary?) */ + if (mkdir(tmproot, 0777) == -1) { + Info(slide, 1, ((char *)slide, + "checkdir: cannot create extraction directory: %s\n", + FnFilter1(tmproot))); + free(tmproot); + G.rootlen = 0; + /* path didn't exist, tried to create, and failed: */ + /* file exists, or 2+ subdir levels required */ + return MPN_ERR_SKIP; + } + } + tmproot[G.rootlen++] = '/'; + tmproot[G.rootlen] = '\0'; + if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) { + free(tmproot); + G.rootlen = 0; + return MPN_NOMEM; + } + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath))); + } + return MPN_OK; + } +#endif /* !SFX || SFX_EXDIR */ + +/*--------------------------------------------------------------------------- + END: free rootpath, immediately prior to program exit. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == END) { + Trace((stderr, "freeing rootpath\n")); + if (G.rootlen > 0) { + free(G.rootpath); + G.rootlen = 0; + } + return MPN_OK; + } + + return MPN_INVALID; /* should never reach */ + +} /* end function checkdir() */ + + + + +static int get_extattribs OF((__GPRO__ iztimes *pzt, ulg z_uidgid[2])); + +static int get_extattribs(__G__ pzt, z_uidgid) + __GDEF + iztimes *pzt; + ulg z_uidgid[2]; +{ +/*--------------------------------------------------------------------------- + Convert from MSDOS-format local time and date to Unix-format 32-bit GMT + time: adjust base year from 1980 to 1970, do usual conversions from + yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day- + light savings time differences. If we have a Unix extra field, however, + we're laughing: both mtime and atime are ours. On the other hand, we + then have to check for restoration of UID/GID. + ---------------------------------------------------------------------------*/ + int have_uidgid_flg; + unsigned eb_izux_flg; + + eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field, + G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, +#ifdef IZ_CHECK_TZ + (G.tz_is_valid ? pzt : NULL), +#else + pzt, +#endif + z_uidgid) : 0); + if (eb_izux_flg & EB_UT_FL_MTIME) { + TTrace((stderr, "\nget_extattribs: Unix e.f. modif. time = %ld\n", + pzt->mtime)); + } else { + pzt->mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); + } + if (eb_izux_flg & EB_UT_FL_ATIME) { + TTrace((stderr, "get_extattribs: Unix e.f. access time = %ld\n", + pzt->atime)); + } else { + pzt->atime = pzt->mtime; + TTrace((stderr, "\nget_extattribs: modification/access times = %ld\n", + pzt->mtime)); + } + + /* if -X option was specified and we have UID/GID info, restore it */ + have_uidgid_flg = +#ifdef RESTORE_UIDGID + (uO.X_flag && (eb_izux_flg & EB_UX2_VALID)); +#else + 0; +#endif + return have_uidgid_flg; +} + + + + + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) /* GRR: change to return PK-style warning level */ + __GDEF +{ + union { + iztimes t3; /* mtime, atime, ctime */ + struct utimbuf t2; /* modtime, actime */ + } zt; + ulg z_uidgid[2]; + int have_uidgid_flg; + +/*--------------------------------------------------------------------------- + If symbolic links are supported, allocate storage for a symlink control + structure, put the uncompressed "data" and other required info in it, and + add the structure to the "deferred symlinks" chain. Since we know it's a + symbolic link to start with, we shouldn't have to worry about overflowing + unsigned ints with unsigned longs. + ---------------------------------------------------------------------------*/ + +#ifdef SYMLINKS + if (G.symlnk) { + extent ucsize = (extent)G.lrec.ucsize; + unsigned AtheOSef_len = 0; + extent slnk_entrysize; + uch *AtheOS_exfld = NULL; + slinkentry *slnk_entry; + + if (!uO.J_flag) { + /* attributes for symlinks are supported too */ + AtheOS_exfld = scanAtheOSexfield(G.extra_field, + G.lrec.extra_field_length); + if (AtheOS_exfld) { + AtheOSef_len = makeword(EB_LEN + AtheOS_exfld) + EB_HEADSIZE; + } + } + + /* size of the symlink entry is the sum of + * (struct size (includes 1st '\0') + 1 additional trailing '\0'), + * system specific attribute data size (might be 0), + * and the lengths of name and link target. + */ + slnk_entrysize = (sizeof(slinkentry) + 1) + AtheOSef_len + + ucsize + strlen(G.filename); + + if (slnk_entrysize < ucsize) { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed: mem alloc overflow\n", + FnFilter1(G.filename))); + fclose(G.outfile); + return; + } + + if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed: no mem\n", + FnFilter1(G.filename))); + fclose(G.outfile); + return; + } + slnk_entry->next = NULL; + slnk_entry->targetlen = ucsize; + slnk_entry->attriblen = AtheOSef_len; + slnk_entry->target = slnk_entry->buf + AtheOSef_len; + slnk_entry->fname = slnk_entry->target + ucsize + 1; + strcpy(slnk_entry->fname, G.filename); + if (AtheOSef_len > 0) + /* AtheOS_exfld should not be NULL because AtheOSef_len > 0 */ + memcpy(slnk_entry->buf, AtheOS_exfld, AtheOSef_len); + + /* move back to the start of the file to re-read the "link data" */ + rewind(G.outfile); + + if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize) + { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed\n", + FnFilter1(G.filename))); + free(slnk_entry); + fclose(G.outfile); + return; + } + fclose(G.outfile); /* close "link" file for good... */ + slnk_entry->target[ucsize] = '\0'; + if (QCOND2) + Info(slide, 0, ((char *)slide, "-> %s ", + FnFilter1(slnk_entry->target))); + /* add this symlink record to the list of deferred symlinks */ + if (G.slink_last != NULL) + G.slink_last->next = slnk_entry; + else + G.slink_head = slnk_entry; + G.slink_last = slnk_entry; + return; + } +#endif /* SYMLINKS */ + + fclose(G.outfile); + + /* handle the AtheOS extra field if present */ + if (!uO.J_flag) { + void *ptr = scanAtheOSexfield(G.extra_field, + G.lrec.extra_field_length); + + if (ptr) { + setAtheOSexfield(G.filename, ptr); + } + } + + have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid); + + /* if -X option was specified and we have UID/GID info, restore it */ + if (have_uidgid_flg) { + TTrace((stderr, "close_outfile: restoring Unix UID/GID info\n")); + if (chown(G.filename, (uid_t)z_uidgid[0], (gid_t)z_uidgid[1])) + { + if (uO.qflag) + Info(slide, 0x201, ((char *)slide, + "warning: cannot set UID %lu and/or GID %lu for %s\n", + z_uidgid[0], z_uidgid[1], FnFilter1(G.filename))); + else + Info(slide, 0x201, ((char *)slide, + " (warning) cannot set UID %lu and/or GID %lu", + z_uidgid[0], z_uidgid[1])); + } + } + + /* skip restoring time stamps on user's request */ + if (uO.D_flag <= 1) { + /* set the file's access and modification times */ + if (utime(G.filename, &(zt.t2))) { + if (uO.qflag) + Info(slide, 0x201, ((char *)slide, + "warning: cannot set times for %s\n", + FnFilter1(G.filename))); + else + Info(slide, 0x201, ((char *)slide, + " (warning) cannot set times")); + } + } + +/*--------------------------------------------------------------------------- + Change the file permissions from default ones to those stored in the + zipfile. + ---------------------------------------------------------------------------*/ + +#ifndef NO_CHMOD + if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr))) + perror("chmod (file attributes) error"); +#endif + +} /* end function close_outfile() */ + + + + +#ifdef SYMLINKS +int set_symlnk_attribs(__G__ slnk_entry) + __GDEF + slinkentry *slnk_entry; +{ + if (slnk_entry->attriblen > 0) + setAtheOSexfield(slnk_entry->fname, (uch *)slnk_entry->buf); + /* currently, no error propagation... */ + return PK_OK; +} +#endif /* SYMLINKS */ + + + + +#ifdef SET_DIR_ATTRIB +/* messages of code for setting directory attributes */ +static ZCONST char Far DirlistUidGidFailed[] = + "warning: cannot set UID %lu and/or GID %lu for %s\n"; +static ZCONST char Far DirlistUtimeFailed[] = + "warning: cannot set modification, access times for %s\n"; +# ifndef NO_CHMOD + static ZCONST char Far DirlistChmodFailed[] = + "warning: cannot set permissions for %s\n"; +# endif + + +int defer_dir_attribs(__G__ pd) + __GDEF + direntry **pd; +{ + uxdirattr *d_entry; + + d_entry = (uxdirattr *)malloc(sizeof(uxdirattr) + strlen(G.filename)); + *pd = (direntry *)d_entry; + if (d_entry == (uxdirattr *)NULL) { + return PK_MEM; + } + d_entry->fn = d_entry->fnbuf; + strcpy(d_entry->fn, G.filename); + + d_entry->perms = G.pInfo->file_attr; + + d_entry->have_uidgid = get_extattribs(__G__ &(d_entry->u.t3), + d_entry->uidgid); + return PK_OK; +} /* end function defer_dir_attribs() */ + + +int set_direc_attribs(__G__ d) + __GDEF + direntry *d; +{ + int errval = PK_OK; + + if (UxAtt(d)->have_uidgid && + chown(UxAtt(d)->fn, (uid_t)UxAtt(d)->uidgid[0], + (gid_t)UxAtt(d)->uidgid[1])) + { + Info(slide, 0x201, ((char *)slide, + LoadFarString(DirlistUidGidFailed), + UxAtt(d)->uidgid[0], UxAtt(d)->uidgid[1], FnFilter1(d->fn))); + if (!errval) + errval = PK_WARN; + } + /* Skip restoring directory time stamps on user' request. */ + if (uO.D_flag <= 0) { + /* restore directory timestamps */ + if (utime(d->fn, &UxAtt(d)->u.t2)) { + Info(slide, 0x201, ((char *)slide, + LoadFarString(DirlistUtimeFailed), FnFilter1(d->fn))); + if (!errval) + errval = PK_WARN; + } + } +#ifndef NO_CHMOD + if (chmod(d->fn, filtattr(__G__ UxAtt(d)->perms))) { + Info(slide, 0x201, ((char *)slide, + LoadFarString(DirlistChmodFailed), FnFilter1(d->fn))); + /* perror("chmod (file attributes) error"); */ + if (!errval) + errval = PK_WARN; + } +#endif /* !NO_CHMOD */ + return errval; +} /* end function set_direc_attribs() */ + +#endif /* SET_DIR_ATTRIB */ + + + + +#ifdef TIMESTAMP + +/***************************/ +/* Function stamp_file() */ +/***************************/ + +int stamp_file(fname, modtime) + ZCONST char *fname; + time_t modtime; +{ + ztimbuf tp; + + tp.modtime = tp.actime = modtime; + return (utime(fname, &tp)); + +} /* end function stamp_file() */ + +#endif /* TIMESTAMP */ + + + + +#ifndef SFX + +/************************/ +/* Function version() */ +/************************/ + +void version(__G) + __GDEF +{ + sprintf((char *)slide, LoadFarString(CompiledWith), +#ifdef __GNUC__ + "gcc ", __VERSION__, +#else + "(unknown compiler) ","", +#endif + "Syllable", + +#if defined(i486) || defined(__i486) || defined(__i486__) || defined(i386) || defined(__i386) || defined(__i386__) + " (x86)", +#else + " (unknown platform)", +#endif + +#ifdef __DATE__ + " on ", __DATE__ +#else + "", "" +#endif + ); + + (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0); + +} /* end function version() */ + +#endif /* !SFX */ + + + +/*********************************/ +/* AtheOS extra field functions */ +/*********************************/ + +/* +** Scan the extra fields in extra_field, and look for a AtheOS EF; return a +** pointer to that EF, or NULL if it's not there. +*/ +static uch *scanAtheOSexfield(const uch *ef_ptr, unsigned ef_len) +{ + while( ef_ptr != NULL && ef_len >= EB_HEADSIZE ) { + unsigned eb_id = makeword(EB_ID + ef_ptr); + unsigned eb_len = makeword(EB_LEN + ef_ptr); + + if (eb_len > (ef_len - EB_HEADSIZE)) { + Trace((stderr, + "scanAtheOSexfield: block length %u > rest ef_size %u\n", eb_len, + ef_len - EB_HEADSIZE)); + break; + } + + if (eb_id == EF_ATHEOS && eb_len >= EB_BEOS_HLEN) { + return (uch *)ef_ptr; + } + + ef_ptr += (eb_len + EB_HEADSIZE); + ef_len -= (eb_len + EB_HEADSIZE); + } + + return NULL; +} + +/* Used by setAtheOSexfield(): + +Set a file/directory's attributes to the attributes passed in. + +If set_file_attrs() fails, an error will be returned: + + EOK - no errors occurred + +(other values will be whatever the failed function returned; no docs +yet, or I'd list a few) +*/ +static int set_file_attrs( const char *name, + const unsigned char *attr_buff, + const off_t attr_size ) +{ + int retval = EOK; + unsigned char *ptr; + const unsigned char *guard; + int fd; + + ptr = (unsigned char *)attr_buff; + guard = ptr + attr_size; + + fd = open(name, O_RDWR | O_NOTRAVERSE); + if (fd < 0) { + return errno; /* should it be -fd ? */ + } + + while (ptr < guard) { + ssize_t nError; + struct attr_info fa_info; + const char *attr_name; + unsigned char *attr_data; + + attr_name = (char *)&(ptr[0]); + ptr += strlen(attr_name) + 1; + + /* The attr_info data is stored in little-endian format because the */ + /* Intel i386 port was here first. */ + memcpy(&fa_info, ptr, sizeof(struct attr_info)); + ptr += sizeof(struct attr_info); + + if (fa_info.ai_size < 0LL) { + Info(slide, 0x201, ((char *)slide, + "warning: skipping attribute with invalid length (%Ld)\n", + fa_info.ai_size)); + break; + } + + attr_data = ptr; + ptr += fa_info.ai_size; + + if (ptr > guard) { + /* We've got a truncated attribute. */ + Info(slide, 0x201, ((char *)slide, + "warning: truncated attribute\n")); + break; + } + + /* write_attr() doesn't return count of written bytes now (Syllable 0.5.3)... */ + nError = write_attr(fd, attr_name, O_TRUNC, fa_info.ai_type, + attr_data, 0, fa_info.ai_size); + if (nError < 0) { + Info(slide, 0x201, ((char *)slide, + "warning: error writing file attribute\n")); + } + } + + close(fd); + return retval; +} + +static void setAtheOSexfield(const char *path, uch *extra_field) +{ + uch *ptr = extra_field; + ush id = 0; + ush size = 0; + ulg full_size = 0; + uch flags = 0; + uch *attrbuff = NULL; + int retval; + + if( extra_field == NULL ) { + return; + } + + /* Collect the data from the extra field buffer. */ + id = makeword(ptr); ptr += 2; /* we don't use this... */ + size = makeword(ptr); ptr += 2; + full_size = makelong(ptr); ptr += 4; + flags = *ptr; ptr++; + + /* Do a little sanity checking. */ + if (flags & EB_BE_FL_BADBITS) { + /* corrupted or unsupported */ + Info(slide, 0x201, ((char *)slide, + "Unsupported flags set for this AtheOS extra field, skipping.\n")); + return; + } + if (size <= EB_BEOS_HLEN) { + /* corrupted, unsupported, or truncated */ + Info(slide, 0x201, ((char *)slide, + "AtheOS extra field is %d bytes, should be at least %d.\n", size, + EB_BEOS_HLEN)); + return; + } + if (full_size < (size - EB_BEOS_HLEN)) { + Info(slide, 0x201, ((char *)slide, + "Skipping attributes: AtheOS extra field is %d bytes, " + "data size is %ld.\n", size - EB_BEOS_HLEN, full_size)); + return; + } + + /* Find the AtheOS file attribute data. */ + if (flags & EB_BE_FL_UNCMPR) { + /* Uncompressed data */ + attrbuff = ptr; + } else { + /* Compressed data */ + attrbuff = (uch *)malloc( full_size ); + if (attrbuff == NULL) { + /* No memory to uncompress attributes */ + Info(slide, 0x201, ((char *)slide, + "Can't allocate memory to uncompress file attributes.\n")); + return; + } + + retval = memextract(__G__ attrbuff, full_size, + ptr, size - EB_BEOS_HLEN); + if( retval != PK_OK ) { + /* error uncompressing attributes */ + Info(slide, 0x201, ((char *)slide, + "Error uncompressing file attributes.\n")); + + /* Some errors here might not be so bad; we should expect */ + /* some truncated data, for example. If the data was */ + /* corrupt, we should _not_ attempt to restore the attrs */ + /* for this file... there's no way to detect what attrs */ + /* are good and which are bad. */ + free (attrbuff); + return; + } + } + + /* Now attempt to set the file attributes on the extracted file. */ + retval = set_file_attrs(path, attrbuff, (off_t)full_size); + if (retval != EOK) { + Info(slide, 0x201, ((char *)slide, + "Error writing file attributes.\n")); + } + + /* Clean up, if necessary */ + if (attrbuff != ptr) { + free(attrbuff); + } + + return; +} diff --git a/atheos/atheos.h b/atheos/atheos.h new file mode 100644 index 0000000..29fca9c --- /dev/null +++ b/atheos/atheos.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 1990-2004 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 +*/ +/* atheos.h -- A few handy things for the AtheOS port + * + * (c) 1997 Chris Herborth (chrish@qnx.com) - BeOS port + * (c) 2004 Ruslan Nickolaev (nruslan@hotbox.ru) - AtheOS port + * + * This is covered under the usual Info-ZIP copyright + */ + +#ifndef _ATHEOS_H_ +#define _ATHEOS_H_ + +#define EB_BE_FL_BADBITS 0xfe /* bits currently undefined */ + +/* +AtheOS 'At' extra-field layout: +(same structure as the BeOS 'Be' e.f. layout, only signature and internal +conventions of the file attribute data are different...) + +'At' - signature +ef_size - size of data in this EF (little-endian unsigned short) +full_size - uncompressed data size (little-endian unsigned long) +flag - flags (byte) + flags & EB_BE_FL_UNCMPR = the data is not compressed + flags & EB_BE_FL_BADBITS = the data is corrupted or we + can't handle it properly +data - compressed or uncompressed file attribute data + +If flag & EB_BE_FL_UNCMPR, the data is not compressed; this optimisation is +necessary to prevent wasted space for files with small attributes. In this +case, there should be (ef_size - EB_BEOS_HLEN) bytes of data, and full_size +should equal (ef_size - EB_BEOS_HLEN). + +If the data is compressed, there will be (ef_size - EB_BEOS_HLEN) bytes of +compressed data, and full_size bytes of uncompressed data. + +If a file has absolutely no attributes, there will not be a 'At' extra field. + +The uncompressed data is arranged like this: + +attr_name\0 - C string +struct attr_info (fields in little-endian format) +attr_data (length in attr_info.ai_size) +*/ + +#endif /* _ATHEOS_H_ */ diff --git a/beos/Contents b/beos/Contents new file mode 100644 index 0000000..d2309c8 --- /dev/null +++ b/beos/Contents @@ -0,0 +1,15 @@ +Contents of the "beos" sub-directory for UnZip 5.52 and later: + + Contents this file + README notes from the author of the BeOS port + Makefile makefile for building UnZip (sorry, no project files) + beocfg.h BeOS-specific configuration settings + beos.c BeOS-specific routines (similar to the Unix ones) + beos.h structures for the BeOS extra field + beosmain.cpp BeOS-specific C++ routines + unzip.rsc BeOS resources for UnZip + unzipsfx.rsc BeOS resources for UnZipSFX + +This port supports both Metrowerks CodeWarrior (PowerPC and x86) and GNU C. + +- Chris Herborth (chrish@qnx.com) diff --git a/beos/Makefile b/beos/Makefile new file mode 100644 index 0000000..7885042 --- /dev/null +++ b/beos/Makefile @@ -0,0 +1,427 @@ +###################################################################### +# +# Makefile for Info-ZIP's unzip, unzipsfx, and funzip on BeOS +# +# Copyright (c) 1998-2006 Info-ZIP +# Chris Herborth (chrish@qnx.com) +# +# This is the new New and Improved Makefile for BeOS; it will: +# +# 1) automatically detect your platform (PowerPC or x86) if none is +# specified; the default compiler is CodeWarrior for PowerPC, or +# gcc for x86 +# +# 2) let you cross-compile for the other platform (PowerPC or x86), in +# theory +# +# 3) let you use Metrowerks CodeWarrior (default) or GNU C to build with +# for either platfor, in theory +# +# To choose a specific architecture, define the ARCH environment +# variable on the make command-line: +# +# ARCH=what make -f beos/Makefile +# +# where "what" can be "powerpc" or "x86". +# +# To choose a specific compiler, define the CC environment variable on +# the make command-line: +# +# CC=compiler make -f beos/Makefile +# +# where "compiler" can be "mwcc" or "x86". +# +# Of course, you can combine these two: +# +# ARCH=powerpc CC=mwcc make -f beos/Makefile +# +# or: +# +# CC=gcc ARCH=x86 make -f beos/Makefile +# +# To automatically install the fresh new unzip, use the "install" target: +# +# make -f beos/Makefile install + +###################################################################### +# Things that don't change: + +SHELL = /bin/sh + +# Punish those of you not running on SMP hardware... +MAKE = make -j 4 -f beos/Makefile + +LOC=$(LOCAL_UNZIP) -DPASSWD_FROM_STDIN +AF=$(LOC) + +# UnZipSfx flags +SL = -o unzipsfx +SL2 = $(LF2) + +# fUnZip flags +FL = -o funzip +FL2 = $(LF2) + +# general-purpose stuff +CP = cp +RM = rm -f +LN = ln -sf +E = +O = .o +M = beos + +# defaults for crc32 stuff and system-dependent headers +CRCA_O = +OSDEP_H = beos/beocfg.h + +# object files +OBJS1 = unzip$O crc32$O crypt$O envargs$O explode$O +OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O +OBJS3 = process$O ttyio$O ubz2err$O unreduce$O unshrink$O zipinfo$O +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O $(BEOS_MAIN) +LOBJS = $(OBJS) +OBJSDLL = $(OBJS) api$O +OBJX = unzipsfx$O crc32_$O crypt_$O extract_$O fileio_$O globals_$O \ + inflate_$O match_$O process_$O ttyio_$O ubz2err_$O $M_$O $(BEOS_MAIN) +LOBJX = $(OBJX) +OBJF = funzip$O crc32f$O cryptf$O globalsf$O inflatef$O ttyiof$O +UNZIP_H = unzip.h unzpriv.h globals.h $(OSDEP_H) + +# installation +INSTALL = install +# on some systems, manext=l and MANDIR=/usr/man/man$(manext) may be appropriate +manext = 1 +prefix = /boot/home/config +BINDIR = $(prefix)/bin# where to install executables +MANDIR = $(prefix)/man/man$(manext)# where to install man pages +INSTALLEDBIN = $(BINDIR)/funzip$E $(BINDIR)/zipinfo$E $(BINDIR)/unzipsfx$E \ + $(BINDIR)/unzip$E +INSTALLEDMAN = $(MANDIR)/unzip.$(manext) $(MANDIR)/funzip.$(manext) \ + $(MANDIR)/unzipsfx.$(manext) $(MANDIR)/zipinfo.$(manext) +# +UNZIPS = unzip$E funzip$E unzipsfx$E zipinfo$E +# this is a little ugly...well, no, it's a lot ugly: +MANS = man/unzip.1 man/unzipsfx.1 man/zipinfo.1 man/funzip.1 man/zipgrep.1 +DOCS = unzip.txt unzipsfx.txt zipinfo.txt funzip.txt zipgrep.txt + +###################################################################### +# Things that change: + +# Select an architecture: +ifndef ARCH +MACHINE=$(shell uname -m) +ifeq "$(MACHINE)" "BePC" +ARCH=x86 +CC=gcc +else +ARCH=powerpc +CC=mwcc +endif +endif + +# Now select compiler flags and whatnot based on the ARCH and CC: +WHAT=$(ARCH)-$(CC) + +ifeq "$(WHAT)" "powerpc-mwcc" +CC=mwccppc +LD=mwccppc +CF=-w9 -O7 -opt schedule604 -rostr -I. $(LOC) +LF=-o unzip +LF2=-warn -L/boot/develop/lib/ppc -lbe -lroot +BEOS_MAIN=beosmain$O +TARGET=$(UNZIPS) +endif + +ifeq "$(WHAT)" "powerpc-gcc" +CC=gcc +LD=gcc +CF=-O3 -mcpu=604 -Wall -ansi -I. -I/boot/develop/headers/be/support \ + -I/boot/develop/headers/be/storage $(LOC) +LF=-o unzip +LF2=-L/boot/develop/lib/ppc -lbe -lroot +BEOS_MAIN=beosmain$O +TARGET=$(UNZIPS) +endif + +# This isn't likely to happen for R4 or later... +ifeq "$(WHAT)" "x86-mwcc" +CC=mwccx86 +LD=mwccx86 +CF=-O2 -w9 -I. $(LOC) +LF=-o unzip +LF2=-warn -L/boot/develop/lib/x86 -lbe -lroot +BEOS_MAIN=beosmain$O +TARGET=$(UNZIPS) +endif + +ifeq "$(WHAT)" "x86-gcc" +CC=gcc +LD=gcc +CF=-O3 -mpentiumpro \ + -Wall -Wno-multichar -Wno-trigraphs \ + -ansi -I. -I/boot/develop/headers/be/support \ + -I/boot/develop/headers/be/storage $(LOC) +LF=-o unzip +LF2=-L/boot/develop/lib/x86 -lbe -lroot +BEOS_MAIN=beosmain$O +TARGET=$(UNZIPS) +endif + +ifndef TARGET +TARGET=help +endif + +###################################################################### +# Helpful targets +all: + @echo 'TARGET = $(TARGET)' + @echo 'ARCH = $(ARCH)' + @echo 'CC = $(CC)' + if [ -n "$(TARGET)" ] ; then \ + $(MAKE) CC=$(CC) CF="$(CF)" LD="$(LD)" \ + LF="$(LF)" LF2="$(LF2)" CCPP="$(CC)" CPPF="$(CF)" \ + OBJS="$(OBJS)" LOBJS="$(LOBJS)" OBJX="$(OBJX)" \ + LOBJX="$(LOBJX)" $(TARGET) ; \ + else \ + $(MAKE) help ; \ + fi + +help: + @echo '' + @echo "This Makefile lets you build Info-ZIP's zip." + @echo '' + @echo 'To build zip for this computer using the default compiler, just do:' + @echo '' + @echo ' make -f beos/Makefile' + @echo '' + @echo 'To build zip for a specific architecture using a specific' + @echo 'compiler, do:' + @echo '' + @echo ' ARCH=cpu CC=compiler make -f beos/Makefile' + @echo '' + @echo 'Where:' + @echo ' cpu is either "powerpc" or "x86"' + @echo ' compiler is either "mwcc" or "gcc"' + @echo '' + +###################################################################### +# Basic compile instructions and dependencies + +# this is for GNU make; comment out and notify zip-bugs if it causes errors +.SUFFIXES: .c .o + +# default for compiling C files +.c.o: + $(CC) -c $(CF) $*.c + + +unzips: $(UNZIPS) +objs: $(OBJS) +objsdll: $(OBJSDLL) +docs: $(DOCS) +unzipsman: unzips docs +unzipsdocs: unzips docs + + +unzip$E: $(OBJS) beos/unzip.rsc + $(LD) $(LF) $(LOBJS) $(LF2) + chmod +x unzip$E + xres -o unzip$E beos/unzip.rsc + mimeset -f -all unzip$E + +unzipsfx$E: $(OBJX) beos/unzipsfx.rsc + $(LD) $(SL) $(LOBJX) $(SL2) + chmod +x unzipsfx$E + xres -o unzipsfx$E beos/unzipsfx.rsc + mimeset -f -all unzipsfx + +funzip$E: $(OBJF) + $(LD) $(FL) $(OBJF) $(FL2) + chmod +x funzip$E + +zipinfo$E: unzip$E + $(LN) unzip$E zipinfo$E + + +crc32$O: crc32.c $(UNZIP_H) zip.h crc32.h +crypt$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +envargs$O: envargs.c $(UNZIP_H) +explode$O: explode.c $(UNZIP_H) +extract$O: extract.c $(UNZIP_H) crc32.h crypt.h +fileio$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +funzip$O: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h +globals$O: globals.c $(UNZIP_H) +inflate$O: inflate.c inflate.h $(UNZIP_H) +list$O: list.c $(UNZIP_H) +match$O: match.c $(UNZIP_H) +process$O: process.c $(UNZIP_H) +ttyio$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ubz2err$O: ubz2err.c $(UNZIP_H) +unreduce$O: unreduce.c $(UNZIP_H) +unshrink$O: unshrink.c $(UNZIP_H) +unzip$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +zipinfo$O: zipinfo.c $(UNZIP_H) + +# unzipsfx compilation section +unzipsfx$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h + $(CP) unzip.c unzipsfx.c + $(CC) -c $(CF) -DSFX unzipsfx.c + $(RM) unzipsfx.c + +crc32_$O: crc32.c $(UNZIP_H) zip.h crc32.h + $(CP) crc32.c crc32_.c + $(CC) -c $(CF) -DSFX crc32_.c + $(RM) crc32_.c + +crypt_$O: crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CP) crypt.c crypt_.c + $(CC) -c $(CF) -DSFX crypt_.c + $(RM) crypt_.c + +extract_$O: extract.c $(UNZIP_H) crc32.h crypt.h + $(CP) extract.c extract_.c + $(CC) -c $(CF) -DSFX extract_.c + $(RM) extract_.c + +fileio_$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h + $(CP) fileio.c fileio_.c + $(CC) -c $(CF) -DSFX fileio_.c + $(RM) fileio_.c + +globals_$O: globals.c $(UNZIP_H) + $(CP) globals.c globals_.c + $(CC) -c $(CF) -DSFX globals_.c + $(RM) globals_.c + +inflate_$O: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CP) inflate.c inflate_.c + $(CC) -c $(CF) -DSFX inflate_.c + $(RM) inflate_.c + +process_$O: process.c $(UNZIP_H) crc32.h + $(CP) process.c process_.c + $(CC) -c $(CF) -DSFX process_.c + $(RM) process_.c + +ttyio_$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CP) ttyio.c ttyio_.c + $(CC) -c $(CF) -DSFX ttyio_.c + $(RM) ttyio_.c + +ubz2err$O: ubz2err.c $(UNZIP_H) + $(CP) ubz2err.c ubz2err_.c + $(CC) -c $(CF) -DSFX ubz2err_.c + $(RM) ubz2err_.c + +# funzip compilation section +crc32f$O: crc32.c $(UNZIP_H) zip.h crc32.h + $(CP) crc32.c crc32f.c + $(CC) -c $(CF) -DFUNZIP crc32f.c + $(RM) crc32f.c + +cryptf$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CP) crypt.c cryptf.c + $(CC) -c $(CF) -DFUNZIP cryptf.c + $(RM) cryptf.c + +globalsf$O: globals.c $(UNZIP_H) + $(CP) globals.c globalsf.c + $(CC) -c $(CF) -DFUNZIP globalsf.c + $(RM) globalsf.c + +inflatef$O: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CP) inflate.c inflatef.c + $(CC) -c $(CF) -DFUNZIP inflatef.c + $(RM) inflatef.c + +ttyiof$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CP) ttyio.c ttyiof.c + $(CC) -c $(CF) -DFUNZIP ttyiof.c + $(RM) ttyiof.c + +# BeOS specific code +beos$O: beos/beos.c $(UNZIP_H) unzvers.h beos/beos.h + $(CC) -c $(CF) beos/beos.c + +beosmain$O: beos/beosmain.cpp $(UNZIP_H) unzvers.h + $(CCPP) -c $(CPPF) beos/beosmain.cpp + +# version() not used by unzipsfx, so no unzvers.h dependency +beos_$O: beos/beos.c $(UNZIP_H) beos/beos.h # unzipsfx only + $(CP) beos/beos.c beos_.c + $(CC) -c $(CF) -Ibeos -DSFX beos_.c + $(RM) beos_.c + +beosmain_$O: beos/beosmain.cpp $(UNZIP_H) # unzipsfx only + $(CP) beos/beosmain.cpp beosmain_.cpp + $(CCPP) -c $(CPPF) -Ibeos -DSFX beosmain_.cpp + $(RM) beosmain_.cpp + + +# this really only works for Unix targets, unless E and O specified on cmd line +clean: + -rm -f $(UNZIPS) $(OBJS) $(OBJF) $(OBJX) api$O apihelp$O crc_gcc$O \ + unzipstb$O beosmain.o beosmain_.o + +install: all + $(INSTALL) -m 755 $(UNZIPS) $(BINDIR) + mimeset -f -all $(BINDIR)/unzip + mimeset -f -all $(BINDIR)/unzipsfx + $(RM) $(BINDIR)/zipinfo$E + $(LN) unzip$E $(BINDIR)/zipinfo$E + $(RM) $(BINDIR)/zipgrep$E + $(INSTALL) -m 755 unix/zipgrep $(BINDIR)/zipgrep$E + $(INSTALL) -m 644 man/unzip.1 $(MANDIR)/unzip.$(manext) + $(INSTALL) -m 644 man/unzipsfx.1 $(MANDIR)/unzipsfx.$(manext) + $(INSTALL) -m 644 man/zipinfo.1 $(MANDIR)/zipinfo.$(manext) + $(INSTALL) -m 644 man/funzip.1 $(MANDIR)/funzip.$(manext) + $(INSTALL) -m 644 man/zipgrep.1 $(MANDIR)/zipgrep.$(manext) + $(INSTALL) -m 644 $(DOCS) $(MANDIR) + +# alternatively, could use zip method: -cd $(BINDIR); rm -f $(UNZIPS) [etc.] +uninstall: + rm -f $(INSTALLEDBIN) $(INSTALLEDMAN) + + +TESTZIP = testmake.zip # the test zipfile + +# test some basic features of the build +test: check + +check: unzips + @echo ' This is a Unix-specific target. (Just so you know.)' + @echo ' (Should work ok on BeOS... [cjh])' + if test ! -f $(TESTZIP); then \ + echo " error: can't find test file $(TESTZIP)"; exit 1; fi +# + echo " testing extraction" + ./unzip -b $(TESTZIP) testmake.zipinfo + if test $? ; then \ + echo " error: file extraction from $(TESTZIP) failed"; exit 1; fi +# + echo ' testing zipinfo (unzip -Z)' + ./unzip -Z $(TESTZIP) > testmake.unzip-Z + if diff testmake.unzip-Z testmake.zipinfo; then ;; else \ + echo ' error: zipinfo output doesn't match stored version'; fi + $(RM) testmake.unzip-Z testmake.zipinfo +# + echo ' testing unzip -d exdir option' + ./unzip -b $(TESTZIP) -d testun + cat testun/notes +# + echo ' testing unzip -o and funzip (ignore funzip warning)' + ./unzip -boq $(TESTZIP) notes -d testun + ./funzip < $(TESTZIP) > testun/notes2 + if diff testun/notes testun/notes2; then ;; else \ + echo 'error: funzip output disagrees with unzip'; fi +# + echo ' testing unzipsfx (self-extractor)' + cat unzipsfx $(TESTZIP) > testsfx + $(CHMOD) 0700 testsfx + ./testsfx -b notes + if diff notes testun/notes; then ;; else \ + echo ' error: unzipsfx file disagrees with unzip'; fi + $(RM) testsfx notes testun/notes testun/notes2 + rmdir testun +# + echo ' testing complete.' diff --git a/beos/README b/beos/README new file mode 100644 index 0000000..f097e4f --- /dev/null +++ b/beos/README @@ -0,0 +1,77 @@ +UnZip 5.4 for BeOS + +NOTE: + +If you want to build UnZip 5.4 or later from the source, you'll need to +have the "xres" tool installed (unless you remove the "xres" lines in the +beos/Makefile). This will cease to be a problem when BeOS R4 ships this +fall. Until then, you can get xres from +ftp://ftp.be.com/pub/experimental/tools/xres-102.zip. + +HISTORY + +UnZip 5.30 was the first official release of Info-ZIP's UnZip to support +the filesystem in BeOS. + +UnZip 5.31 added support for the new filesystem that appeared in the +Advanced Access Preview (aka DR9) Release of BeOS. + +UnZip 5.32 added several important bug fixes. + +UnZip 5.4: + +- supports BeOS on x86 hardware (and cross-compiling, if a compiler is + present) + +- ask the Registrar to assign a file type to files that don't have one + +- adds a new -J option on BeOS; this lets you extract the data for a file + without restoring its file attributes (handy if you stumble on really + old BeOS ZIP archives... from before BeOS Preview Release) + +- will restore attributes properly on symbolic links (you'll need + zip 2.21 or later to create ZIP files that store attributes for + symbolic links) + +*** WARNING *** +You may find some extremely old BeOS zip archives that store their +file attributes differently; these will be from DR8 and earlier (when +BeOS copied the MacOS type/creator fields instead of using the current +extremely flexible scheme). + +You can still unpack the _data_ in older zip files, but you won't be +able to recover the file attributes in those archives. Use the -J option +with these files or you'll get "compressed EA data missing" and "zipfile +probably corrupt" errors, even though the data is intact! + +The new scheme makes handling BeOS file attributes much more robust, and +allows for possible future expansion without another round of +incompatibilities. + +That's life on the edge! +*** WARNING *** + +The new filesystem allows for huge files (up to several terabytes!) with +huge amounts of meta-data (up to several terabytes!). The existing ZIP +format was designed when this much data on a personal computer was +science fiction; as a result, it's quite possible that large amounts of file +attributes (more than maybe 100+K bytes) could be truncated. Zip and UnZip +try to deal with this in a fairly sensible way, working on the assumption +that the data in the file is more important than the data in the file +attributes. + +One way to run into this problem is to mount an HFS volume and zip +some Mac files that have large resources attached to them. This +happens more often than you'd expect; I've seen several 0-byte files that +had over four megabytes of resources. Even more stupid, these resources +were _data_ (sound for a game), and could have been easily stored as +data... + +KNOWN BUGS + +None! Yahoo! + +Please report any bugs to Zip-Bugs@lists.wku.edu. + +- Chris Herborth (chrish@qnx.com) + November 2/1998 diff --git a/beos/beocfg.h b/beos/beocfg.h new file mode 100644 index 0000000..7683078 --- /dev/null +++ b/beos/beocfg.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 1990-2009 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2009-Jan-02 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 +*/ +/*--------------------------------------------------------------------------- + BeOS specific configuration section: + ---------------------------------------------------------------------------*/ + +#ifndef __beocfg_h +#define __beocfg_h + +#include /* [cjh]: This is pretty much a generic */ +#include /* POSIX 1003.1 system; see beos/ for */ +#include /* extra code to deal with our extra file */ +#include /* attributes. */ +#include +#include +#define GOT_UTIMBUF +#define DIRENT +#include +#ifndef DATE_FORMAT +# define DATE_FORMAT DF_MDY /* GRR: customize with locale.h somehow? */ +#endif +#define lenEOL 1 +#define PutNativeEOL *q++ = native(LF); +#define SCREENSIZE(ttrows, ttcols) screensize(ttrows, ttcols) +#define SCREENWIDTH 80 +#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)) +# define USE_EF_UT_TIME +#endif +#define SET_SYMLINK_ATTRIBS +#define SET_DIR_ATTRIB +#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) +# define TIMESTAMP +#endif +#define RESTORE_UIDGID +#define NO_STRNICMP /* not in the x86 headers at least */ +#define INT_SPRINTF +#define SYMLINKS +#define MAIN main_stub /* now that we're using a wrapper... */ + +/* Static variables that we have to add to Uz_Globs: */ +#define SYSTEM_SPECIFIC_GLOBALS \ + int created_dir, renamed_fullpath;\ + char *rootpath, *buildpath, *end;\ + ZCONST char *wildname;\ + char *dirname, matchname[FILNAMSIZ];\ + int rootlen, have_dirname, dirnamelen, notfirstcall;\ + zvoid *wild_dir; + +/* created_dir, and renamed_fullpath are used by both mapname() and */ +/* checkdir(). */ +/* rootlen, rootpath, buildpath and end are used by checkdir(). */ +/* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */ +/* and notfirstcall are used by do_wild(). */ + +#endif /* !__beocfg_h */ diff --git a/beos/beos.c b/beos/beos.c new file mode 100644 index 0000000..96da6fd --- /dev/null +++ b/beos/beos.c @@ -0,0 +1,1544 @@ +/* + Copyright (c) 1990-2009 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2009-Jan-02 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 +*/ +/*--------------------------------------------------------------------------- + + beos.c + + BeOS-specific routines for use with Info-ZIP's UnZip 5.30 and later. + (based on unix/unix.c) + + Contains: do_wild() <-- generic enough to put in fileio.c? + mapattr() + mapname() + checkdir() + close_outfile() + defer_dir_attribs() + set_direc_attribs() + stamp_file() + version() + scanBeOSexfield() + set_file_attrs() + setBeOSexfield() + printBeOSexfield() + assign_MIME() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" + +#include "beos.h" +#include /* Just make sure we've got a few things... */ +#include +#include +#include + +#include + +/* For the new post-DR8 file attributes */ +#include +#include +#include + +static unsigned filtattr OF((__GPRO__ unsigned perms)); +static uch *scanBeOSexfield OF((const uch *ef_ptr, unsigned ef_len)); +static int set_file_attrs( const char *, const unsigned char *, const off_t ); +static void setBeOSexfield OF((const char *path, uch *extra_field)); +#ifdef BEOS_USE_PRINTEXFIELD +static void printBeOSexfield OF((int isdir, uch *extra_field)); +#endif +#ifdef BEOS_ASSIGN_FILETYPE +static void assign_MIME( const char * ); +#endif + +#ifdef SET_DIR_ATTRIB +typedef struct uxdirattr { /* struct for holding unix style directory */ + struct uxdirattr *next; /* info until can be sorted and set at end */ + char *fn; /* filename of directory */ + union { + iztimes t3; /* mtime, atime, ctime */ + ztimbuf t2; /* modtime, actime */ + } u; + unsigned perms; /* same as min_info.file_attr */ + int have_uidgid; /* flag */ + ulg uidgid[2]; + char fnbuf[1]; /* buffer stub for directory name */ +} uxdirattr; +#define UxAtt(d) ((uxdirattr *)d) /* typecast shortcut */ +#endif /* SET_DIR_ATTRIB */ + +#ifdef ACORN_FTYPE_NFS +/* Acorn bits for NFS filetyping */ +typedef struct { + uch ID[2]; + uch size[2]; + uch ID_2[4]; + uch loadaddr[4]; + uch execaddr[4]; + uch attr[4]; +} RO_extra_block; + +#endif /* ACORN_FTYPE_NFS */ + +/* static int created_dir; */ /* used in mapname(), checkdir() */ +/* static int renamed_fullpath; */ /* ditto */ + + +/*****************************/ +/* Strings used multiple */ +/* times in beos.c */ +/*****************************/ + +/* messages of code for setting file/directory attributes */ +static ZCONST char CannotSetItemUidGid[] = + "warning: cannot set UID %lu and/or GID %lu for %s\n %s\n"; +static ZCONST char CannotSetUidGid[] = + " (warning) cannot set UID %lu and/or GID %lu\n %s"; +static ZCONST char CannotSetItemTimestamps[] = + "warning: cannot set modif./access times for %s\n %s\n"; +static ZCONST char CannotSetTimestamps[] = + " (warning) cannot set modif./access times\n %s"; + + +#ifndef SFX + +/**********************/ +/* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ +/**********************/ + +char *do_wild(__G__ wildspec) + __GDEF + ZCONST char *wildspec; /* only used first time on a given dir */ +{ +/* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in beocfg.h: + static DIR *wild_dir = (DIR *)NULL; + static ZCONST char *wildname; + static char *dirname, matchname[FILNAMSIZ]; + static int notfirstcall=FALSE, have_dirname, dirnamelen; +*/ + struct dirent *file; + + /* Even when we're just returning wildspec, we *always* do so in + * matchname[]--calling routine is allowed to append four characters + * to the returned string, and wildspec may be a pointer to argv[]. + */ + if (!G.notfirstcall) { /* first call: must initialize everything */ + G.notfirstcall = TRUE; + + if (!iswild(wildspec)) { + strncpy(G.matchname, wildspec, FILNAMSIZ); + G.matchname[FILNAMSIZ-1] = '\0'; + G.have_dirname = FALSE; + G.wild_dir = NULL; + return G.matchname; + } + + /* break the wildspec into a directory part and a wildcard filename */ + if ((G.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL) { + G.dirname = "."; + G.dirnamelen = 1; + G.have_dirname = FALSE; + G.wildname = wildspec; + } else { + ++G.wildname; /* point at character after '/' */ + G.dirnamelen = G.wildname - wildspec; + if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == (char *)NULL) { + Info(slide, 0x201, ((char *)slide, + "warning: cannot allocate wildcard buffers\n")); + strncpy(G.matchname, wildspec, FILNAMSIZ); + G.matchname[FILNAMSIZ-1] = '\0'; + return G.matchname; /* but maybe filespec was not a wildcard */ + } + strncpy(G.dirname, wildspec, G.dirnamelen); + G.dirname[G.dirnamelen] = '\0'; /* terminate for strcpy below */ + G.have_dirname = TRUE; + } + + if ((G.wild_dir = (zvoid *)opendir(G.dirname)) != (zvoid *)NULL) { + while ((file = readdir((DIR *)G.wild_dir)) != + (struct dirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + if (file->d_name[0] == '.' && G.wildname[0] != '.') + continue; /* Unix: '*' and '?' do not match leading dot */ + if (match(file->d_name, G.wildname, 0 WISEP) &&/*0=case sens.*/ + /* skip "." and ".." directory entries */ + strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) { + Trace((stderr, "do_wild: match() succeeds\n")); + if (G.have_dirname) { + strcpy(G.matchname, G.dirname); + strcpy(G.matchname+G.dirnamelen, file->d_name); + } else + strcpy(G.matchname, file->d_name); + return G.matchname; + } + } + /* if we get to here directory is exhausted, so close it */ + closedir((DIR *)G.wild_dir); + G.wild_dir = (zvoid *)NULL; + } + Trace((stderr, "do_wild: opendir(%s) returns NULL\n", + FnFilter1(G.dirname))); + + /* return the raw wildspec in case that works (e.g., directory not + * searchable, but filespec was not wild and file is readable) */ + strncpy(G.matchname, wildspec, FILNAMSIZ); + G.matchname[FILNAMSIZ-1] = '\0'; + return G.matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if ((DIR *)G.wild_dir == (DIR *)NULL) { + G.notfirstcall = FALSE; /* nothing left--reset for new wildspec */ + if (G.have_dirname) + free(G.dirname); + return (char *)NULL; + } + + /* If we've gotten this far, we've read and matched at least one entry + * successfully (in a previous call), so dirname has been copied into + * matchname already. + */ + while ((file = readdir((DIR *)G.wild_dir)) != (struct dirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + if (file->d_name[0] == '.' && G.wildname[0] != '.') + continue; /* Unix: '*' and '?' do not match leading dot */ + if (match(file->d_name, G.wildname, 0 WISEP)) { /* 0 == case sens. */ + Trace((stderr, "do_wild: match() succeeds\n")); + if (G.have_dirname) { + /* strcpy(G.matchname, G.dirname); */ + strcpy(G.matchname+G.dirnamelen, file->d_name); + } else + strcpy(G.matchname, file->d_name); + return G.matchname; + } + } + + closedir((DIR *)G.wild_dir); /* at least one entry read; nothing left */ + G.wild_dir = (zvoid *)NULL; + G.notfirstcall = FALSE; /* reset for new wildspec */ + if (G.have_dirname) + free(G.dirname); + return (char *)NULL; + +} /* end function do_wild() */ + +#endif /* !SFX */ + + + + +#ifndef S_ISUID +# define S_ISUID 0004000 /* set user id on execution */ +#endif +#ifndef S_ISGID +# define S_ISGID 0002000 /* set group id on execution */ +#endif +#ifndef S_ISVTX +# define S_ISVTX 0001000 /* save swapped text even after use */ +#endif + +/************************/ +/* Function filtattr() */ +/************************/ +/* This is used to clear or keep the SUID and SGID bits on file permissions. + * It's possible that a file in an archive could have one of these bits set + * and, unknown to the person unzipping, could allow others to execute the + * file as the user or group. The new option -K bypasses this check. + */ + +static unsigned filtattr(__G__ perms) + __GDEF + unsigned perms; +{ + /* keep setuid/setgid/tacky perms? */ + if (!uO.K_flag) + perms &= ~(S_ISUID | S_ISGID | S_ISVTX); + + return (0xffff & perms); +} /* end function filtattr() */ + + + + + +/**********************/ +/* Function mapattr() */ +/**********************/ + +int mapattr(__G) + __GDEF +{ + int r; + ulg tmp = G.crec.external_file_attributes; + + G.pInfo->file_attr = 0; + /* initialized to 0 for check in "default" branch below... */ + + switch (G.pInfo->hostnum) { + case AMIGA_: + tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */ + G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp); + break; + case THEOS_: + tmp &= 0xF1FFFFFFL; + if ((tmp & 0xF0000000L) != 0x40000000L) + tmp &= 0x01FFFFFFL; /* not a dir, mask all ftype bits */ + else + tmp &= 0x41FFFFFFL; /* leave directory bit as set */ + /* fall through! */ + case BEOS_: + case UNIX_: + case VMS_: + case ACORN_: + case ATARI_: + case ATHEOS_: + case QDOS_: + case TANDEM_: + r = FALSE; + G.pInfo->file_attr = (unsigned)(tmp >> 16); + if (G.pInfo->file_attr == 0 && G.extra_field) { + /* Some (non-Info-ZIP) implementations of Zip for Unix and + * VMS (and probably others ??) leave 0 in the upper 16-bit + * part of the external_file_attributes field. Instead, they + * store file permission attributes in some extra field. + * As a work-around, we search for the presence of one of + * these extra fields and fall back to the MSDOS compatible + * part of external_file_attributes if one of the known + * e.f. types has been detected. + * Later, we might implement extraction of the permission + * bits from the VMS extra field. But for now, the work-around + * should be sufficient to provide "readable" extracted files. + * (For ASI Unix e.f., an experimental remap of the e.f. + * mode value IS already provided!) + */ + ush ebID; + unsigned ebLen; + uch *ef = G.extra_field; + unsigned ef_len = G.crec.extra_field_length; + + while (!r && ef_len >= EB_HEADSIZE) { + ebID = makeword(ef); + ebLen = (unsigned)makeword(ef+EB_LEN); + if (ebLen > (ef_len - EB_HEADSIZE)) + /* discoverd some e.f. inconsistency! */ + break; + switch (ebID) { + case EF_ASIUNIX: + if (ebLen >= (EB_ASI_MODE+2)) { + G.pInfo->file_attr = + (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE)); + /* force stop of loop: */ + ef_len = (ebLen + EB_HEADSIZE); + break; + } + /* else: fall through! */ + case EF_PKVMS: + /* "found nondecypherable e.f. with perm. attr" */ + r = TRUE; + default: + break; + } + ef_len -= (ebLen + EB_HEADSIZE); + ef += (ebLen + EB_HEADSIZE); + } + } + if (!r) { +#ifdef SYMLINKS + /* Check if the file is a (POSIX-compatible) symbolic link. + * We restrict symlink support to those "made-by" hosts that + * are known to support symbolic links. + */ + G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) && + SYMLINK_HOST(G.pInfo->hostnum); +#endif + return 0; + } + /* fall through! */ + /* all remaining cases: expand MSDOS read-only bit into write perms */ + case FS_FAT_: + /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the + * Unix attributes in the upper 16 bits of the external attributes + * field, just like Info-ZIP's Zip for Unix. We try to use that + * value, after a check for consistency with the MSDOS attribute + * bits (see below). + */ + G.pInfo->file_attr = (unsigned)(tmp >> 16); + /* fall through! */ + case FS_HPFS_: + case FS_NTFS_: + case MAC_: + case TOPS20_: + default: + /* Ensure that DOS subdir bit is set when the entry's name ends + * in a '/'. Some third-party Zip programs fail to set the subdir + * bit for directory entries. + */ + if ((tmp & 0x10) == 0) { + extent fnlen = strlen(G.filename); + if (fnlen > 0 && G.filename[fnlen-1] == '/') + tmp |= 0x10; + } + /* read-only bit --> write perms; subdir bit --> dir exec bit */ + tmp = !(tmp & 1) << 1 | (tmp & 0x10) >> 4; + if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) { + /* keep previous G.pInfo->file_attr setting, when its "owner" + * part appears to be consistent with DOS attribute flags! + */ +#ifdef SYMLINKS + /* Entries "made by FS_FAT_" could have been zipped on a + * system that supports POSIX-style symbolic links. + */ + G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) && + (G.pInfo->hostnum == FS_FAT_); +#endif + return 0; + } + G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp); + break; + } /* end switch (host-OS-created-by) */ + + /* for originating systems with no concept of "group," "other," "system": */ + umask( (int)(tmp=umask(0)) ); /* apply mask to expanded r/w(/x) perms */ + G.pInfo->file_attr &= ~tmp; + + return 0; + +} /* end function mapattr() */ + + + + + +/************************/ +/* Function mapname() */ +/************************/ + +int mapname(__G__ renamed) + __GDEF + int renamed; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - caution (truncated filename) + * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) + * MPN_ERR_SKIP - error -> skip entry + * MPN_ERR_TOOLONG - error -> path is too long + * MPN_NOMEM - error (memory allocation failed) -> skip entry + * [also MPN_VOL_LABEL, MPN_CREATED_DIR] + */ +{ + char pathcomp[FILNAMSIZ]; /* path-component buffer */ + char *pp, *cp=(char *)NULL; /* character pointers */ + char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ +#ifdef ACORN_FTYPE_NFS + char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ + RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */ +#endif + int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ + int error = MPN_OK; + register unsigned workch; /* hold the character being tested */ + + +/*--------------------------------------------------------------------------- + Initialize various pointers and counters and stuff. + ---------------------------------------------------------------------------*/ + + if (G.pInfo->vollabel) + return MPN_VOL_LABEL; /* can't set disk volume labels in BeOS */ + + /* can create path as long as not just freshening, or if user told us */ + G.create_dirs = (!uO.fflag || renamed); + + G.created_dir = FALSE; /* not yet */ + + /* user gave full pathname: don't prepend rootpath */ + G.renamed_fullpath = (renamed && (*G.filename == '/')); + + if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM) + return MPN_NOMEM; /* initialize path buffer, unless no memory */ + + *pathcomp = '\0'; /* initialize translation buffer */ + pp = pathcomp; /* point to translation buffer */ + if (uO.jflag) /* junking directories */ + cp = (char *)strrchr(G.filename, '/'); + if (cp == (char *)NULL) /* no '/' or not junking dirs */ + cp = G.filename; /* point to internal zipfile-member pathname */ + else + ++cp; /* point to start of last component of path */ + +/*--------------------------------------------------------------------------- + Begin main loop through characters in filename. + ---------------------------------------------------------------------------*/ + + while ((workch = (uch)*cp++) != 0) { + + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + if (strcmp(pathcomp, ".") == 0) { + /* don't bother appending "./" to the path */ + *pathcomp = '\0'; + } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { + /* "../" dir traversal detected, skip over it */ + *pathcomp = '\0'; + killed_ddot = TRUE; /* set "show message" flag */ + } + /* when path component is not empty, append it now */ + if (*pathcomp != '\0' && + ((error = checkdir(__G__ pathcomp, APPEND_DIR)) + & MPN_MASK) > MPN_INF_TRUNC) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ + break; + + case ';': /* VMS version (or DEC-20 attrib?) */ + lastsemi = pp; + *pp++ = ';'; /* keep for now; remove VMS ";##" */ + break; /* later, if requested */ + +#ifdef ACORN_FTYPE_NFS + case ',': /* NFS filetype extension */ + lastcomma = pp; + *pp++ = ','; /* keep for now; may need to remove */ + break; /* later, if requested */ +#endif + + default: + /* allow European characters in filenames: */ + if (isprint(workch) || (128 <= workch && workch <= 254)) + *pp++ = (char)workch; + } /* end switch */ + + } /* end while loop */ + + /* Show warning when stripping insecure "parent dir" path components */ + if (killed_ddot && QCOND2) { + Info(slide, 0, ((char *)slide, + "warning: skipped \"../\" path component(s) in %s\n", + FnFilter1(G.filename))); + if (!(error & ~MPN_MASK)) + error = (error & MPN_MASK) | PK_WARN; + } + +/*--------------------------------------------------------------------------- + Report if directory was created (and no file to create: filename ended + in '/'), check name to be sure it exists, and combine path and name be- + fore exiting. + ---------------------------------------------------------------------------*/ + + if (G.filename[strlen(G.filename) - 1] == '/') { + checkdir(__G__ G.filename, GETPATH); + if (G.created_dir) { + if (QCOND2) { + Info(slide, 0, ((char *)slide, " creating: %s\n", + FnFilter1(G.filename))); + } + + if (!uO.J_flag) { /* Handle the BeOS extra field if present. */ + void *ptr = scanBeOSexfield(G.extra_field, + G.lrec.extra_field_length); + if (ptr) { + setBeOSexfield(G.filename, ptr); + } + } + +#ifndef NO_CHMOD + /* set approx. dir perms (make sure can still read/write in dir) */ + if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr) | 0700)) + perror("chmod (directory attributes) error"); +#endif + + /* set dir time (note trailing '/') */ + return (error & ~MPN_MASK) | MPN_CREATED_DIR; + } + /* TODO: should we re-write the BeOS extra field data in case it's */ + /* changed? The answer is yes. [Sept 1999 - cjh] */ + if (!uO.J_flag) { /* Handle the BeOS extra field if present. */ + void *ptr = scanBeOSexfield(G.extra_field, + G.lrec.extra_field_length); + if (ptr) { + setBeOSexfield(G.filename, ptr); + } + } + + /* dir existed already; don't look for data to extract */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + *pp = '\0'; /* done with pathcomp: terminate it */ + + /* if not saving them, remove VMS version numbers (appended ";###") */ + if (!uO.V_flag && lastsemi) { + pp = lastsemi + 1; + while (isdigit((uch)(*pp))) + ++pp; + if (*pp == '\0') /* only digits between ';' and end: nuke */ + *lastsemi = '\0'; + } + + /* On UNIX (and compatible systems), "." and ".." are reserved for + * directory navigation and cannot be used as regular file names. + * These reserved one-dot and two-dot names are mapped to "_" and "__". + */ + if (strcmp(pathcomp, ".") == 0) + *pathcomp = '_'; + else if (strcmp(pathcomp, "..") == 0) + strcpy(pathcomp, "__"); + +#ifdef ACORN_FTYPE_NFS + /* translate Acorn filetype information if asked to do so */ + if (uO.acorn_nfs_ext && + (ef_spark = (RO_extra_block *) + getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) + != (RO_extra_block *)NULL) + { + /* file *must* have a RISC OS extra field */ + long ft = (long)makelong(ef_spark->loadaddr); + /*32-bit*/ + if (lastcomma) { + pp = lastcomma + 1; + while (isxdigit((uch)(*pp))) ++pp; + if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */ + } + if ((ft & 1<<31)==0) ft=0x000FFD00; + sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF); + } +#endif /* ACORN_FTYPE_NFS */ + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", + FnFilter1(G.filename))); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + + checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ + checkdir(__G__ G.filename, GETPATH); + + return error; + +} /* end function mapname() */ + + + + +/***********************/ +/* Function checkdir() */ +/***********************/ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename + * MPN_INF_SKIP - path doesn't exist, not allowed to create + * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path + * exists and is not a directory, but is supposed to be + * MPN_ERR_TOOLONG - path is too long + * MPN_NOMEM - can't allocate memory for filename buffers + */ +{ + /* static int rootlen = 0; */ /* length of rootpath */ + /* static char *rootpath; */ /* user's "extract-to" directory */ + /* static char *buildpath; */ /* full path (so far) to extracted file */ + /* static char *end; */ /* pointer to end of buildpath ('\0') */ + +# define FN_MASK 7 +# define FUNCTION (flag & FN_MASK) + + + +/*--------------------------------------------------------------------------- + APPEND_DIR: append the path component to the path being built and check + for its existence. If doesn't exist and we are creating directories, do + so for this one; else signal success or error as appropriate. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_DIR) { + int too_long = FALSE; +#ifdef SHORT_NAMES + char *old_end = end; +#endif + + Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); + while ((*G.end = *pathcomp++) != '\0') + ++G.end; +#ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ + if ((G.end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ + *(G.end = old_end + FILENAME_MAX) = '\0'; +#endif + + /* GRR: could do better check, see if overrunning buffer as we go: + * check end-buildpath after each append, set warning variable if + * within 20 of FILNAMSIZ; then if var set, do careful check when + * appending. Clear variable when begin new path. */ + + /* next check: need to append '/', at least one-char name, '\0' */ + if ((G.end-G.buildpath) > FILNAMSIZ-3) + too_long = TRUE; /* check if extracting dir? */ + if (SSTAT(G.buildpath, &G.statbuf)) { /* path doesn't exist */ + if (!G.create_dirs) { /* told not to create (freshening) */ + free(G.buildpath); + return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", + FnFilter1(G.buildpath))); + free(G.buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + if (mkdir(G.buildpath, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, + "checkdir error: cannot create %s\n\ + %s\n\ + unable to process %s.\n", + FnFilter2(G.buildpath), + strerror(errno), + FnFilter1(G.filename))); + free(G.buildpath); + /* path didn't exist, tried to create, failed */ + return MPN_ERR_SKIP; + } + G.created_dir = TRUE; + } else if (!S_ISDIR(G.statbuf.st_mode)) { + Info(slide, 1, ((char *)slide, + "checkdir error: %s exists but is not directory\n\ + unable to process %s.\n", + FnFilter2(G.buildpath), FnFilter1(G.filename))); + free(G.buildpath); + /* path existed but wasn't dir */ + return MPN_ERR_SKIP; + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", FnFilter1(G.buildpath))); + free(G.buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + *G.end++ = '/'; + *G.end = '\0'; + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); + return MPN_OK; + + } /* end if (FUNCTION == APPEND_DIR) */ + +/*--------------------------------------------------------------------------- + GETPATH: copy full path to the string pointed at by pathcomp, and free + G.buildpath. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == GETPATH) { + strcpy(pathcomp, G.buildpath); + Trace((stderr, "getting and freeing path [%s]\n", + FnFilter1(pathcomp))); + free(G.buildpath); + G.buildpath = G.end = (char *)NULL; + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + APPEND_NAME: assume the path component is the filename; append it and + return without checking for existence. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_NAME) { +#ifdef SHORT_NAMES + char *old_end = end; +#endif + + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); + while ((*G.end = *pathcomp++) != '\0') { + ++G.end; +#ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ + if ((G.end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ + *(G.end = old_end + FILENAME_MAX) = '\0'; +#endif + if ((G.end-G.buildpath) >= FILNAMSIZ) { + *--G.end = '\0'; + Info(slide, 0x201, ((char *)slide, + "checkdir warning: path too long; truncating\n\ + %s\n -> %s\n", + FnFilter1(G.filename), FnFilter2(G.buildpath))); + return MPN_INF_TRUNC; /* filename truncated */ + } + } + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); + /* could check for existence here, prompt for new name... */ + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + INIT: allocate and initialize buffer space for the file currently being + extracted. If file was renamed with an absolute path, don't prepend the + extract-to path. + ---------------------------------------------------------------------------*/ + +/* GRR: for VMS and TOPS-20, add up to 13 to strlen */ + + if (FUNCTION == INIT) { + Trace((stderr, "initializing buildpath to ")); +#ifdef ACORN_FTYPE_NFS + if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+ + (uO.acorn_nfs_ext ? 5 : 1))) +#else + if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1)) +#endif + == (char *)NULL) + return MPN_NOMEM; + if ((G.rootlen > 0) && !G.renamed_fullpath) { + strcpy(G.buildpath, G.rootpath); + G.end = G.buildpath + G.rootlen; + } else { + *G.buildpath = '\0'; + G.end = G.buildpath; + } + Trace((stderr, "[%s]\n", FnFilter1(G.buildpath))); + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + ROOT: if appropriate, store the path in rootpath and create it if + necessary; else assume it's a zipfile member and return. This path + segment gets used in extracting all members from every zipfile specified + on the command line. + ---------------------------------------------------------------------------*/ + +#if (!defined(SFX) || defined(SFX_EXDIR)) + if (FUNCTION == ROOT) { + Trace((stderr, "initializing root path to [%s]\n", + FnFilter1(pathcomp))); + if (pathcomp == (char *)NULL) { + G.rootlen = 0; + return MPN_OK; + } + if (G.rootlen > 0) /* rootpath was already set, nothing to do */ + return MPN_OK; + if ((G.rootlen = strlen(pathcomp)) > 0) { + char *tmproot; + + if ((tmproot = (char *)malloc(G.rootlen+2)) == (char *)NULL) { + G.rootlen = 0; + return MPN_NOMEM; + } + strcpy(tmproot, pathcomp); + if (tmproot[G.rootlen-1] == '/') { + tmproot[--G.rootlen] = '\0'; + } + if (G.rootlen > 0 && (SSTAT(tmproot, &G.statbuf) || + !S_ISDIR(G.statbuf.st_mode))) + { /* path does not exist */ + if (!G.create_dirs /* || iswild(tmproot) */ ) { + free(tmproot); + G.rootlen = 0; + /* skip (or treat as stored file) */ + return MPN_INF_SKIP; + } + /* create the directory (could add loop here scanning tmproot + * to create more than one level, but why really necessary?) */ + if (mkdir(tmproot, 0777) == -1) { + Info(slide, 1, ((char *)slide, + "checkdir: cannot create extraction directory: %s\n\ + %s\n", + FnFilter1(tmproot), strerror(errno))); + free(tmproot); + G.rootlen = 0; + /* path didn't exist, tried to create, and failed: */ + /* file exists, or 2+ subdir levels required */ + return MPN_ERR_SKIP; + } + } + tmproot[G.rootlen++] = '/'; + tmproot[G.rootlen] = '\0'; + if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) { + free(tmproot); + G.rootlen = 0; + return MPN_NOMEM; + } + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath))); + } + return MPN_OK; + } +#endif /* !SFX || SFX_EXDIR */ + +/*--------------------------------------------------------------------------- + END: free rootpath, immediately prior to program exit. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == END) { + Trace((stderr, "freeing rootpath\n")); + if (G.rootlen > 0) { + free(G.rootpath); + G.rootlen = 0; + } + return MPN_OK; + } + + return MPN_INVALID; /* should never reach */ + +} /* end function checkdir() */ + + + + + +static int get_extattribs OF((__GPRO__ iztimes *pzt, ulg z_uidgid[2])); + +static int get_extattribs(__G__ pzt, z_uidgid) + __GDEF + iztimes *pzt; + ulg z_uidgid[2]; +{ +/*--------------------------------------------------------------------------- + Convert from MSDOS-format local time and date to Unix-format 32-bit GMT + time: adjust base year from 1980 to 1970, do usual conversions from + yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day- + light savings time differences. If we have a Unix extra field, however, + we're laughing: both mtime and atime are ours. On the other hand, we + then have to check for restoration of UID/GID. + ---------------------------------------------------------------------------*/ + int have_uidgid_flg; + unsigned eb_izux_flg; + + eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field, + G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, +#ifdef IZ_CHECK_TZ + (G.tz_is_valid ? pzt : NULL), +#else + pzt, +#endif + z_uidgid) : 0); + if (eb_izux_flg & EB_UT_FL_MTIME) { + TTrace((stderr, "\nget_extattribs: Unix e.f. modif. time = %ld\n", + pzt->mtime)); + } else { + pzt->mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); + } + if (eb_izux_flg & EB_UT_FL_ATIME) { + TTrace((stderr, "get_extattribs: Unix e.f. access time = %ld\n", + pzt->atime)); + } else { + pzt->atime = pzt->mtime; + TTrace((stderr, "\nget_extattribs: modification/access times = %ld\n", + pzt->mtime)); + } + + /* if -X option was specified and we have UID/GID info, restore it */ + have_uidgid_flg = +#ifdef RESTORE_UIDGID + (uO.X_flag && (eb_izux_flg & EB_UX2_VALID)); +#else + 0; +#endif + return have_uidgid_flg; +} + + + + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) /* GRR: change to return PK-style warning level */ + __GDEF +{ + union { + iztimes t3; /* mtime, atime, ctime */ + ztimbuf t2; /* modtime, actime */ + } zt; + ulg z_uidgid[2]; + int have_uidgid_flg; + + have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid); + +/*--------------------------------------------------------------------------- + If symbolic links are supported, allocate storage for a symlink control + structure, put the uncompressed "data" and other required info in it, and + add the structure to the "deferred symlinks" chain. Since we know it's a + symbolic link to start with, we shouldn't have to worry about overflowing + unsigned ints with unsigned longs. + ---------------------------------------------------------------------------*/ + +#ifdef SYMLINKS + if (G.symlnk) { + extent ucsize = (extent)G.lrec.ucsize; + unsigned BeOSef_len = 0; + extent slnk_entrysize; + uch *BeOS_exfld; + slinkentry *slnk_entry; + + if (!uO.J_flag) { + /* Symlinks can have attributes, too. */ + BeOS_exfld = scanBeOSexfield(G.extra_field, + G.lrec.extra_field_length); + if (BeOS_exfld) { + BeOSef_len = makeword(EB_LEN + BeOS_exfld) + EB_HEADSIZE; + } + } + + /* size of the symlink entry is the sum of + * (struct size (includes 1st '\0') + 1 additional trailing '\0'), + * system specific attribute data size (might be 0), + * and the lengths of name and link target. + */ + slnk_entrysize = (sizeof(slinkentry) + 1) + BeOSef_len + + ucsize + strlen(G.filename); + + if (slnk_entrysize < ucsize) { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed: mem alloc overflow\n", + FnFilter1(G.filename))); + fclose(G.outfile); + return; + } + + if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed: no mem\n", + FnFilter1(G.filename))); + fclose(G.outfile); + return; + } + slnk_entry->next = NULL; + slnk_entry->targetlen = ucsize; + slnk_entry->attriblen = BeOSef_len; + slnk_entry->target = slnk_entry->buf + BeOSef_len; + slnk_entry->fname = slnk_entry->target + ucsize + 1; + strcpy(slnk_entry->fname, G.filename); + if (BeOSef_len > 0) + memcpy(slnk_entry->buf, BeOS_exfld, BeOSef_len); + + /* move back to the start of the file to re-read the "link data" */ + rewind(G.outfile); + + if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize) + { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed\n", + FnFilter1(G.filename))); + free(slnk_entry); + fclose(G.outfile); + return; + } + fclose(G.outfile); /* close "link" file for good... */ + slnk_entry->target[ucsize] = '\0'; + if (QCOND2) + Info(slide, 0, ((char *)slide, "-> %s ", + FnFilter1(slnk_entry->target))); + /* add this symlink record to the list of deferred symlinks */ + if (G.slink_last != NULL) + G.slink_last->next = slnk_entry; + else + G.slink_head = slnk_entry; + G.slink_last = slnk_entry; + return; + } +#endif /* SYMLINKS */ + + fclose(G.outfile); + + /* handle the BeOS extra field if present */ + if (!uO.J_flag) { + void *ptr = scanBeOSexfield(G.extra_field, + G.lrec.extra_field_length); + + if (ptr) { + setBeOSexfield(G.filename, ptr); +#ifdef BEOS_ASSIGN_FILETYPE + } else { + /* Otherwise, ask the system to try assigning a MIME type. */ + assign_MIME( G.filename ); +#endif + } + } + +/*--------------------------------------------------------------------------- + Change the file permissions from default ones to those stored in the + zipfile. + ---------------------------------------------------------------------------*/ + +#ifndef NO_CHMOD + if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr))) + perror("chmod (file attributes) error"); +#endif + + /* if -X option was specified and we have UID/GID info, restore it */ + if (have_uidgid_flg + /* check that both uid and gid values fit into their data sizes */ + && ((ulg)(uid_t)(z_uidgid[0]) == z_uidgid[0]) + && ((ulg)(gid_t)(z_uidgid[1]) == z_uidgid[1])) { + TTrace((stderr, "close_outfile: restoring Unix UID/GID info\n")); + if (chown(G.filename, (uid_t)z_uidgid[0], (gid_t)z_uidgid[1])) + { + if (uO.qflag) + Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid, + z_uidgid[0], z_uidgid[1], FnFilter1(G.filename), + strerror(errno))); + else + Info(slide, 0x201, ((char *)slide, CannotSetUidGid, + z_uidgid[0], z_uidgid[1], strerror(errno))); + } + } + + /* skip restoring time stamps on user's request */ + if (uO.D_flag <= 1) { + /* set the file's access and modification times */ + if (utime(G.filename, &(zt.t2))) { + if (uO.qflag) + Info(slide, 0x201, ((char *)slide, CannotSetItemTimestamps, + FnFilter1(G.filename), strerror(errno))); + else + Info(slide, 0x201, ((char *)slide, CannotSetTimestamps, + strerror(errno))); + } + } + +} /* end function close_outfile() */ + + + + +#ifdef SYMLINKS +int set_symlnk_attribs(__G__ slnk_entry) + __GDEF + slinkentry *slnk_entry; +{ + if (slnk_entry->attriblen > 0) + setBeOSexfield(slnk_entry->fname, (uch *)slnk_entry->buf); + /* currently, no error propagation... */ + return PK_OK; +} /* end function set_symlnk_attribs() */ +#endif /* SYMLINKS */ + + + + +#ifdef SET_DIR_ATTRIB +/* messages of code for setting directory attributes */ +# ifndef NO_CHMOD + static ZCONST char DirlistChmodFailed[] = + "warning: cannot set permissions for %s\n %s\n"; +# endif + + +int defer_dir_attribs(__G__ pd) + __GDEF + direntry **pd; +{ + uxdirattr *d_entry; + + d_entry = (uxdirattr *)malloc(sizeof(uxdirattr) + strlen(G.filename)); + *pd = (direntry *)d_entry; + if (d_entry == (uxdirattr *)NULL) { + return PK_MEM; + } + d_entry->fn = d_entry->fnbuf; + strcpy(d_entry->fn, G.filename); + + d_entry->perms = G.pInfo->file_attr; + + d_entry->have_uidgid = get_extattribs(__G__ &(d_entry->u.t3), + d_entry->uidgid); + return PK_OK; +} /* end function defer_dir_attribs() */ + + +int set_direc_attribs(__G__ d) + __GDEF + direntry *d; +{ + int errval = PK_OK; + + if (UxAtt(d)->have_uidgid && + /* check that both uid and gid values fit into their data sizes */ + ((ulg)(uid_t)(UxAtt(d)->uidgid[0]) == UxAtt(d)->uidgid[0]) && + ((ulg)(gid_t)(UxAtt(d)->uidgid[1]) == UxAtt(d)->uidgid[1]) && + chown(UxAtt(d)->fn, (uid_t)UxAtt(d)->uidgid[0], + (gid_t)UxAtt(d)->uidgid[1])) + { + Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid, + UxAtt(d)->uidgid[0], UxAtt(d)->uidgid[1], FnFilter1(d->fn), + strerror(errno))); + if (!errval) + errval = PK_WARN; + } + /* Skip restoring directory time stamps on user' request. */ + if (uO.D_flag <= 0) { + /* restore directory timestamps */ + if (utime(d->fn, (const struct utimbuf *)&UxAtt(d)->u.t2)) { + Info(slide, 0x201, ((char *)slide, CannotSetItemTimestamps, + FnFilter1(d->fn), strerror(errno))); + if (!errval) + errval = PK_WARN; + } + } +#ifndef NO_CHMOD + if (chmod(d->fn, filtattr(__G__ UxAtt(d)->perms))) { + Info(slide, 0x201, ((char *)slide, DirlistChmodFailed, + FnFilter1(d->fn), strerror(errno))); + if (!errval) + errval = PK_WARN; + } +#endif /* !NO_CHMOD */ + return errval; +} /* end function set_direc_attribs() */ + +#endif /* SET_DIR_ATTRIB */ + + + + +#ifdef TIMESTAMP + +/***************************/ +/* Function stamp_file() */ +/***************************/ + +int stamp_file(fname, modtime) + ZCONST char *fname; + time_t modtime; +{ + struct utimbuf tp; + + tp.modtime = tp.actime = modtime; + return (utime(fname, &tp)); + +} /* end function stamp_file() */ + +#endif /* TIMESTAMP */ + + + + +#ifndef SFX + +/************************/ +/* Function version() */ +/************************/ + +void version(__G) + __GDEF +{ + sprintf((char *)slide, LoadFarString(CompiledWith), +#if defined(__MWERKS__) + "Metrowerks CodeWarrior", "", +#elif defined(__GNUC__) + "GNU C ", __VERSION__, +#else + "(unknown compiler) ","", +#endif + "BeOS ", + +#ifdef __POWERPC__ + "(PowerPC)", +#else +# ifdef __INTEL__ + "(x86)", +# else + "(unknown)", /* someday we may have other architectures... */ +# endif +#endif + +#ifdef __DATE__ + " on ", __DATE__ +#else + "", "" +#endif + ); + + (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0); + +} /* end function version() */ + +#endif /* !SFX */ + + + +/******************************/ +/* Extra field functions */ +/******************************/ + +/* +** Scan the extra fields in extra_field, and look for a BeOS EF; return a +** pointer to that EF, or NULL if it's not there. +*/ +static uch *scanBeOSexfield(const uch *ef_ptr, unsigned ef_len) +{ + while( ef_ptr != NULL && ef_len >= EB_HEADSIZE ) { + unsigned eb_id = makeword(EB_ID + ef_ptr); + unsigned eb_len = makeword(EB_LEN + ef_ptr); + + if (eb_len > (ef_len - EB_HEADSIZE)) { + Trace((stderr, + "scanBeOSexfield: block length %u > rest ef_size %u\n", eb_len, + ef_len - EB_HEADSIZE)); + break; + } + + if (eb_id == EF_BEOS && eb_len >= EB_BEOS_HLEN) { + return (uch *)ef_ptr; + } + + ef_ptr += (eb_len + EB_HEADSIZE); + ef_len -= (eb_len + EB_HEADSIZE); + } + + return NULL; +} + +/* Used by setBeOSexfield(): + +Set a file/directory's attributes to the attributes passed in. + +If set_file_attrs() fails, an error will be returned: + + EOK - no errors occurred + +(other values will be whatever the failed function returned; no docs +yet, or I'd list a few) +*/ +static int set_file_attrs( const char *name, + const unsigned char *attr_buff, + const off_t attr_size ) +{ + int retval = EOK; + unsigned char *ptr; + const unsigned char *guard; + int fd; + + ptr = (unsigned char *)attr_buff; + guard = ptr + attr_size; + + fd = open(name, O_RDWR | O_NOTRAVERSE); + if (fd < 0) { + return errno; /* should it be -fd ? */ + } + + while (ptr < guard) { + ssize_t wrote_bytes; + struct attr_info fa_info; + const char *attr_name; + unsigned char *attr_data; + + attr_name = (char *)&(ptr[0]); + ptr += strlen(attr_name) + 1; + + /* The attr_info data is stored in big-endian format because the */ + /* PowerPC port was here first. */ + memcpy(&fa_info, ptr, sizeof(struct attr_info)); + fa_info.type = (uint32)B_BENDIAN_TO_HOST_INT32( fa_info.type ); + fa_info.size = (off_t)B_BENDIAN_TO_HOST_INT64( fa_info.size ); + ptr += sizeof(struct attr_info); + + if (fa_info.size < 0LL) { + Info(slide, 0x201, ((char *)slide, + "warning: skipping attribute with invalid length (%Ld)\n", + fa_info.size)); + break; + } + + attr_data = ptr; + ptr += fa_info.size; + + if (ptr > guard) { + /* We've got a truncated attribute. */ + Info(slide, 0x201, ((char *)slide, + "warning: truncated attribute\n")); + break; + } + + /* Wave the magic wand... this will swap Be-known types properly. */ + (void)swap_data( fa_info.type, attr_data, fa_info.size, + B_SWAP_BENDIAN_TO_HOST ); + + wrote_bytes = fs_write_attr(fd, attr_name, fa_info.type, 0, + attr_data, fa_info.size); + if (wrote_bytes != fa_info.size) { + Info(slide, 0x201, ((char *)slide, + "warning: wrote %ld attribute bytes of %ld\n", + (unsigned long)wrote_bytes,(unsigned long)fa_info.size)); + } + } + + close(fd); + + return retval; +} + +static void setBeOSexfield(const char *path, uch *extra_field) +{ + uch *ptr = extra_field; + ush id = 0; + ush size = 0; + ulg full_size = 0; + uch flags = 0; + uch *attrbuff = NULL; + int retval; + + if( extra_field == NULL ) { + return; + } + + /* Collect the data from the extra field buffer. */ + id = makeword(ptr); ptr += 2; /* we don't use this... */ + size = makeword(ptr); ptr += 2; + full_size = makelong(ptr); ptr += 4; + flags = *ptr; ptr++; + + /* Do a little sanity checking. */ + if (flags & EB_BE_FL_BADBITS) { + /* corrupted or unsupported */ + Info(slide, 0x201, ((char *)slide, + "Unsupported flags set for this BeOS extra field, skipping.\n")); + return; + } + if (size <= EB_BEOS_HLEN) { + /* corrupted, unsupported, or truncated */ + Info(slide, 0x201, ((char *)slide, + "BeOS extra field is %d bytes, should be at least %d.\n", size, + EB_BEOS_HLEN)); + return; + } + if (full_size < (size - EB_BEOS_HLEN)) { + /* possible old archive? will this screw up on valid archives? */ + Info(slide, 0x201, ((char *)slide, + "Skipping attributes: BeOS extra field is %d bytes, " + "data size is %ld.\n", size - EB_BEOS_HLEN, full_size)); + return; + } + + /* Find the BeOS file attribute data. */ + if (flags & EB_BE_FL_UNCMPR) { + /* Uncompressed data */ + attrbuff = ptr; + } else { + /* Compressed data */ + attrbuff = (uch *)malloc( full_size ); + if (attrbuff == NULL) { + /* No memory to uncompress attributes */ + Info(slide, 0x201, ((char *)slide, + "Can't allocate memory to uncompress file attributes.\n")); + return; + } + + retval = memextract(__G__ attrbuff, full_size, + ptr, size - EB_BEOS_HLEN); + if( retval != PK_OK ) { + /* error uncompressing attributes */ + Info(slide, 0x201, ((char *)slide, + "Error uncompressing file attributes.\n")); + + /* Some errors here might not be so bad; we should expect */ + /* some truncated data, for example. If the data was */ + /* corrupt, we should _not_ attempt to restore the attrs */ + /* for this file... there's no way to detect what attrs */ + /* are good and which are bad. */ + free (attrbuff); + return; + } + } + + /* Now attempt to set the file attributes on the extracted file. */ + retval = set_file_attrs(path, attrbuff, (off_t)full_size); + if (retval != EOK) { + Info(slide, 0x201, ((char *)slide, + "Error writing file attributes.\n")); + } + + /* Clean up, if necessary */ + if (attrbuff != ptr) { + free(attrbuff); + } + + return; +} + +#ifdef BEOS_USE_PRINTEXFIELD +static void printBeOSexfield( int isdir, uch *extra_field ) +{ + uch *ptr = extra_field; + ush id = 0; + ush size = 0; + ulg full_size = 0; + uch flags = 0; + + /* Tell picky compilers to be quiet. */ + isdir = isdir; + + if( extra_field == NULL ) { + return; + } + + /* Collect the data from the buffer. */ + id = makeword( ptr ); ptr += 2; + size = makeword( ptr ); ptr += 2; + full_size = makelong( ptr ); ptr += 4; + flags = *ptr; ptr++; + + if( id != EF_BEOS ) { + /* not a 'Be' field */ + printf("\t*** Unknown field type (0x%04x, '%c%c')\n", id, + (char)(id >> 8), (char)id); + } + + if( flags & EB_BE_FL_BADBITS ) { + /* corrupted or unsupported */ + printf("\t*** Corrupted BeOS extra field:\n"); + printf("\t*** unknown bits set in the flags\n"); + printf("\t*** (Possibly created by an old version of zip for BeOS.\n"); + } + + if( size <= EB_BEOS_HLEN ) { + /* corrupted, unsupported, or truncated */ + printf("\t*** Corrupted BeOS extra field:\n"); + printf("\t*** size is %d, should be larger than %d\n", size, + EB_BEOS_HLEN ); + } + + if( flags & EB_BE_FL_UNCMPR ) { + /* Uncompressed data */ + printf("\tBeOS extra field data (uncompressed):\n"); + printf("\t\t%ld data bytes\n", full_size); + } else { + /* Compressed data */ + printf("\tBeOS extra field data (compressed):\n"); + printf("\t\t%d compressed bytes\n", size - EB_BEOS_HLEN); + printf("\t\t%ld uncompressed bytes\n", full_size); + } +} +#endif + +#ifdef BEOS_ASSIGN_FILETYPE +/* Note: This will no longer be necessary in BeOS PR4; update_mime_info() */ +/* will be updated to build its own absolute pathname if it's not given one. */ +static void assign_MIME( const char *file ) +{ + char *fullname; + char buff[PATH_MAX], cwd_buff[PATH_MAX]; + int retval; + + if( file[0] == '/' ) { + fullname = (char *)file; + } else { + sprintf( buff, "%s/%s", getcwd( cwd_buff, PATH_MAX ), file ); + fullname = buff; + } + + retval = update_mime_info( fullname, FALSE, TRUE, TRUE ); +} +#endif diff --git a/beos/beos.h b/beos/beos.h new file mode 100644 index 0000000..909ebc4 --- /dev/null +++ b/beos/beos.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 1990-2004 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 +*/ +/* beos.h -- A few handy things for the BeOS port. */ +/* (c) 1997 Chris Herborth (chrish@qnx.com) */ +/* This is covered under the usual Info-ZIP copyright. */ + +/* "#define EF_BE_FL_UNCMPR 0x01" has been moved into unzpriv.h */ +#define EB_BE_FL_BADBITS 0xfe /* bits currently undefined */ + +#define BEOS_ASSIGN_FILETYPE 1 /* call update_mime_info() */ + +/* +DR9 'Be' extra-field layout: + +'Be' - signature +ef_size - size of data in this EF (little-endian unsigned short) +full_size - uncompressed data size (little-endian unsigned long) +flag - flags (byte) + flags & EB_BE_FL_UNCMPR = the data is not compressed + flags & EB_BE_FL_BADBITS = the data is corrupted or we + can't handle it properly +data - compressed or uncompressed file attribute data + +If flag & EB_BE_FL_UNCMPR, the data is not compressed; this optimisation is +necessary to prevent wasted space for files with small attributes (which +appears to be quite common on the Advanced Access DR9 release). In this +case, there should be ( ef_size - EB_BEOS_HLEN ) bytes of data, and full_size +should equal ( ef_size - EB_BEOS_HLEN ). + +If the data is compressed, there will be ( ef_size - EB_BEOS_HLEN ) bytes of +compressed data, and full_size bytes of uncompressed data. + +If a file has absolutely no attributes, there will not be a 'Be' extra field. + +The uncompressed data is arranged like this: + +attr_name\0 - C string +struct attr_info (fields in big-endian format) +attr_data (length in attr_info.size) +*/ diff --git a/beos/beosmain.cpp b/beos/beosmain.cpp new file mode 100644 index 0000000..290c612 --- /dev/null +++ b/beos/beosmain.cpp @@ -0,0 +1,44 @@ +// -*- C++ -*- +/* + 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 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 +*/ +// +// WARNING: This is C++, not C! GNU C is not supported here! +// +// beos_init.cpp +// +// BeOS-specific C++ routines for use with Info-ZIP's UnZip 5.30 or later. +// +// This is necessary because we need to have an app_server connection to be +// able to ask the system to assign a MIME type to an un-typed file. Strange +// but true (the update_mime_info() call needs to send/receive messages). +// +// If you're writing your own Zip application, you probably DO NOT want to +// include this file! + +#include + +#ifdef SFX +const static char *unzip_signature = "application/x-vnd.Info-ZIP.UnZipSFX"; +#else +const static char *unzip_signature = "application/x-vnd.Info-ZIP.UnZip"; +#endif + +extern "C" int main_stub( int argc, char *argv[] ); + +int main( int argc, char **argv ) +{ + BApplication app( unzip_signature ); + + int retval = main_stub( argc, argv ); + + app.PostMessage( B_QUIT_REQUESTED ); + app.Run(); + + return retval; +} diff --git a/beos/unzip.rsc b/beos/unzip.rsc new file mode 100644 index 0000000..1640b8b Binary files /dev/null and b/beos/unzip.rsc differ diff --git a/beos/unzipsfx.rsc b/beos/unzipsfx.rsc new file mode 100644 index 0000000..ff3b030 Binary files /dev/null and b/beos/unzipsfx.rsc differ diff --git a/bzip2/00README.IZ b/bzip2/00README.IZ new file mode 100644 index 0000000..0bae2e2 --- /dev/null +++ b/bzip2/00README.IZ @@ -0,0 +1,9 @@ +This folder is the root folder for the externally supplied bzip2 source code. +Additionally, this folder contains the following Info-ZIP-specific files: + + 00README.IZ this file + Makebz2.iz "generic" make script for the base bzip2 lib used in UnZip + makbz2iz.msc make script for the bzip2 support, win32 port, MS VC++ + makbz2iz.wat make script for bzip2 support, msdos & win32, OpenWatcom C++ + descrbz2.mms MMS/MMK make script for OpenVMS + buildbz2.com OpenVMS DCL procedure to build the base bz2 lib used in UnZip diff --git a/bzip2/Makebz2.iz b/bzip2/Makebz2.iz new file mode 100644 index 0000000..e03c38a --- /dev/null +++ b/bzip2/Makebz2.iz @@ -0,0 +1,54 @@ +# Makefile for UnZip's bzip2 support library +# Unix, and other ports using sufficiently unix-compatible +# library naming conventions (e.g. misc. GCC ports) +# +# (c) 2006-2007 Info-ZIP +# Last revision: Christian Spieler, 2007-Mar-31 +# +# This Makefile is intended to be called from UnZip's main make procedure. + +SHELL=/bin/sh + +# To assist in cross-compiling +CC=gcc +AR=ar +RANLIB=ranlib +RM=rm -f +LDFLAGS= +O=.o + +CFLAGS=-Wall -Winline -O2 -g +CCBZ2DEFS=-DBZ_NO_STDIO + + +OBJS= blocksort$(O) \ + huffman$(O) \ + crctable$(O) \ + randtable$(O) \ + compress$(O) \ + decompress$(O) \ + bzlib$(O) + +# How to compile sources +.c$(O): + $(CC) $(CFLAGS) $(CCBZ2DEFS) -o $@ -c $< + +all: libbz2.a + +libbz2.a: $(OBJS) + -@$(RM) libbz2.a + $(AR) cq libbz2.a $(OBJS) + -$(RANLIB) libbz2.a + +clean: + $(RM) $(OBJS) libbz2.a + +$(OBJS): bzlib.h bzlib_private.h + +blocksort$(O): blocksort.c +huffman$(O): huffman.c +crctable$(O): crctable.c +randtable$(O): randtable.c +compress$(O): compress.c +decompress$(O): decompress.c +bzlib$(O): bzlib.c diff --git a/bzip2/buildbz2.com b/bzip2/buildbz2.com new file mode 100644 index 0000000..55115b5 --- /dev/null +++ b/bzip2/buildbz2.com @@ -0,0 +1,277 @@ +$! BUILDBZ2.COM +$! +$! Build procedure for LIBBZ2_NS support library used with the +$! VMS versions of UnZip/ZipInfo and UnZipSFX +$! +$! Last revised: 2007-12-29 CS. +$! +$! Command args: +$! - select compiler environment: "VAXC", "DECC", "GNUC" +$! - select compiler listings: "LIST" Note that the whole argument +$! is added to the compiler command, so more elaborate options +$! like "LIST/SHOW=ALL" (quoted or space-free) may be specified. +$! - supply additional compiler options: "CCOPTS=xxx" Allows the +$! user to add compiler command options like /ARCHITECTURE or +$! /[NO]OPTIMIZE. For example, CCOPTS=/ARCH=HOST/OPTI=TUNE=HOST +$! or CCOPTS=/DEBUG/NOOPTI. These options must be quoted or +$! space-free. +$! +$! To specify additional options, define the symbol LOCAL_BZIP2 +$! as a comma-separated list of the C macros to be defined, and +$! then run BUILDBZ2.COM. For example: +$! +$! $ LOCAL_BZIP2 = "RETURN_CODES" +$! $ @ []BUILDBZ2.COM +$! +$! If you edit this procedure to set LOCAL_BZIP2 here, be sure to +$! use only one "=", to avoid affecting other procedures. +$! +$! +$ on error then goto error +$ on control_y then goto error +$ OLD_VERIFY = f$verify(0) +$! +$ edit := edit ! override customized edit commands +$ say := write sys$output +$! +$!##################### Read settings from environment ######################## +$! +$ if (f$type(LOCAL_BZIP2) .eqs. "") +$ then +$ local_bzip2 = "" +$ else ! Trim blanks and append comma if missing +$ local_bzip2 = f$edit(local_bzip2, "TRIM") +$ if (f$extract((f$length(local_bzip2) - 1), 1, local_bzip2) .nes. ",") +$ then +$ local_bzip2 = local_bzip2 + ", " +$ endif +$ endif +$! +$!##################### Customizing section ############################# +$! +$ unzx_unx = "UNZIP" +$ unzx_cli = "UNZIP_CLI" +$ unzsfx_unx = "UNZIPSFX" +$ unzsfx_cli = "UNZIPSFX_CLI" +$! +$ CCOPTS = "" +$ LINKOPTS = "/notraceback" +$ LISTING = " /nolist" +$ MAY_USE_DECC = 1 +$ MAY_USE_GNUC = 0 +$! +$! Process command line parameters requesting optional features. +$! +$ arg_cnt = 1 +$ argloop: +$ current_arg_name = "P''arg_cnt'" +$ curr_arg = f$edit( 'current_arg_name', "UPCASE") +$ if (curr_arg .eqs. "") then goto argloop_out +$! +$ if (f$extract( 0, 5, curr_arg) .eqs. "CCOPT") +$ then +$ opts = f$edit( curr_arg, "COLLAPSE") +$ eq = f$locate( "=", opts) +$ CCOPTS = f$extract( (eq+ 1), 1000, opts) +$ goto argloop_end +$ endif +$! +$ if (f$extract( 0, 4, curr_arg) .eqs. "LIST") +$ then +$ LISTING = "/''curr_arg'" ! But see below for mods. +$ goto argloop_end +$ endif +$! +$ if (curr_arg .eqs. "VAXC") +$ then +$ MAY_USE_DECC = 0 +$ MAY_USE_GNUC = 0 +$ goto argloop_end +$ endif +$! +$ if (curr_arg .eqs. "DECC") +$ then +$ MAY_USE_DECC = 1 +$ MAY_USE_GNUC = 0 +$ goto argloop_end +$ endif +$! +$ if (curr_arg .eqs. "GNUC") +$ then +$ MAY_USE_DECC = 0 +$ MAY_USE_GNUC = 1 +$ goto argloop_end +$ endif +$! +$ say "Unrecognized command-line option: ''curr_arg'" +$ goto error +$! +$ argloop_end: +$ arg_cnt = arg_cnt + 1 +$ goto argloop +$ argloop_out: +$! +$!####################################################################### +$! +$! Find out current disk, directory, compiler and options +$! +$ workdir = f$environment("default") +$ here = f$parse(workdir, , , "device") + f$parse(workdir, , , "directory") +$! +$! Sense the host architecture (Alpha, Itanium, or VAX). +$! +$ if (f$getsyi("HW_MODEL") .lt. 1024) +$ then +$ arch = "VAX" +$ else +$ if (f$getsyi("ARCH_TYPE") .eq. 2) +$ then +$ arch = "ALPHA" +$ else +$ if (f$getsyi("ARCH_TYPE") .eq. 3) +$ then +$ arch = "IA64" +$ else +$ arch = "unknown_arch" +$ endif +$ endif +$ endif +$! +$ dest = arch +$ cmpl = "DEC/Compaq/HP C" +$ opts = "" +$ if (arch .nes. "VAX") +$ then +$ HAVE_DECC_VAX = 0 +$ USE_DECC_VAX = 0 +$! +$ if (MAY_USE_GNUC) +$ then +$ say "GNU C is not supported for ''arch'." +$ say "You must use DEC/Compaq/HP C to build UnZip." +$ goto error +$ endif +$! +$ if (.not. MAY_USE_DECC) +$ then +$ say "VAX C is not supported for ''arch'." +$ say "You must use DEC/Compaq/HP C to build UnZip." +$ goto error +$ endif +$! +$ cc = "cc /standard=relax /prefix=all /ansi /names=(as_is)" +$ defs = "''local_bzip2'" +$ else +$ HAVE_DECC_VAX = (f$search("SYS$SYSTEM:DECC$COMPILER.EXE") .nes. "") +$ HAVE_VAXC_VAX = (f$search("SYS$SYSTEM:VAXC.EXE") .nes. "") +$ MAY_HAVE_GNUC = (f$trnlnm("GNU_CC") .nes. "") +$ if (HAVE_DECC_VAX .and. MAY_USE_DECC) +$ then +$ ! We use DECC: +$ USE_DECC_VAX = 1 +$ cc = "cc /decc /prefix=all /names=(as_is)" +$ defs = "''local_bzip2'" +$ else +$ ! We use VAXC (or GNU C): +$ USE_DECC_VAX = 0 +$ defs = "''local_bzip2'" +$ if ((.not. HAVE_VAXC_VAX .and. MAY_HAVE_GNUC) .or. MAY_USE_GNUC) +$ then +$ cc = "gcc" +$ dest = "''dest'G" +$ cmpl = "GNU C" +$ opts = "GNU_CC:[000000]GCCLIB.OLB /LIBRARY," +$ else +$ if (HAVE_DECC_VAX) +$ then +$ cc = "cc /vaxc" +$ else +$ cc = "cc" +$ endif +$ dest = "''dest'V" +$ cmpl = "VAX C" +$ endif +$ endif +$ endif +$! +$! Reveal the plan. If compiling, set some compiler options. +$! +$ say "Compiling bzip2 on ''arch' using ''cmpl'." +$! +$ DEF_NS = "/define = (''defs'BZ_NO_STDIO, VMS)" +$! +$! If [.'dest'] does not exist, either complain (link-only) or make it. +$! +$ if (f$search("''dest'.dir;1") .eqs. "") +$ then +$ create /directory [.'dest'] +$ endif +$! +$! Arrange to get arch-specific list file placement, if listing, and if +$! the user didn't specify a particular "/LIST =" destination. +$! +$ L = f$edit(LISTING, "COLLAPSE") +$ if ((f$extract(0, 5, L) .eqs. "/LIST") .and. - + (f$extract(4, 1, L) .nes. "=")) +$ then +$ LISTING = " /LIST = [.''dest']" + f$extract(5, 1000, LISTING) +$ endif +$! +$! Define compiler command. +$! +$ cc = cc + " /include = ([])" + LISTING + CCOPTS +$! +$! Show interesting facts. +$! +$ say " architecture = ''arch' (destination = [.''dest'])" +$ say " cc = ''cc'" +$ say "" +$! +$ tmp = f$verify( 1) ! Turn echo on to see what's happening. +$! +$!------------------------------- BZip2 section ------------------------------ +$! +$! Compile the sources. +$! +$ cc 'DEF_NS' /object = [.'dest']blocksort.OBJ blocksort.c +$ cc 'DEF_NS' /object = [.'dest']huffman.OBJ huffman.c +$ cc 'DEF_NS' /object = [.'dest']crctable.OBJ crctable.c +$ cc 'DEF_NS' /object = [.'dest']randtable.OBJ randtable.c +$ cc 'DEF_NS' /object = [.'dest']compress.OBJ compress.c +$ cc 'DEF_NS' /object = [.'dest']decompress.OBJ decompress.c +$ cc 'DEF_NS' /object = [.'dest']bzlib.OBJ bzlib.c +$! +$! Create the object library. +$! +$ if (f$search( "[.''dest']LIBBZ2_NS.OLB") .eqs. "") then - + libr /object /create [.'dest']LIBBZ2_NS.OLB +$! +$ libr /object /replace [.'dest']LIBBZ2_NS.OLB - + [.'dest']blocksort.OBJ, - + [.'dest']huffman.OBJ, - + [.'dest']crctable.OBJ, - + [.'dest']randtable.OBJ, - + [.'dest']compress.OBJ, - + [.'dest']decompress.OBJ, - + [.'dest']bzlib.OBJ +$! +$! Restore the original default directory, deassign the temporary +$! logical names, and restore the DCL verify status. +$! +$ error: +$! +$ if (f$type(here) .nes. "") +$ then +$ if (here .nes. "") +$ then +$ set default 'here' +$ endif +$ endif +$! +$ if (f$type(OLD_VERIFY) .nes. "") +$ then +$ tmp = f$verify(OLD_VERIFY) +$ endif +$! +$ exit +$! diff --git a/bzip2/descrbz2.mms b/bzip2/descrbz2.mms new file mode 100644 index 0000000..28bb986 --- /dev/null +++ b/bzip2/descrbz2.mms @@ -0,0 +1,285 @@ +!========================================================================== +! MMS description file for bzip2 support in UnZip 6 2008-02-16 +!========================================================================== +! +! To build the LIBBZ2_NS library, edit the USER CUSTOMIZATION +! lines below to taste, then do +! mms +! or +! mmk +! if you use Matt's Make (free MMS-compatible make utility). +! +! In all other cases where you want to explicitly specify a makefile target, +! you have to specify your compiling environment, too. These are: +! +! $ MMS/MACRO=(__ALPHA__=1) ! Alpha AXP, (DEC C) +! $ MMS/MACRO=(__IA64__=1) ! IA64, (DEC C) +! $ MMS/MACRO=(__DECC__=1) ! VAX, using DEC C +! $ MMS/MACRO=(__FORCE_VAXC__=1) ! VAX, prefering VAXC over DECC +! $ MMS/MACRO=(__VAXC__=1) ! VAX, where VAXC is default +! $ MMS/MACRO=(__GNUC__=1) ! VAX, using GNU C +! + +! To delete all .OBJ, .OLB, .EXE and .HLP files, +! mms clean + +## The "DO_THE_BUILD" target does no longer work with current +## releases of the MMS tool, sigh. +#DO_THE_BUILD : +# @ decc = f$search("SYS$SYSTEM:DECC$COMPILER.EXE").nes."" +# @ axp = (f$getsyi("HW_MODEL") .ge. 1024) .and. - +# (f$getsyi("HW_MODEL") .lt. 4096) +# @ i64 = f$getsyi("HW_MODEL") .ge. 4096 +# @ macro = "/MACRO=(" +#.IFDEF CCOPTS +# @ macro = macro + """CCOPTS=$(CCOPTS)""," +#.ENDIF +# @ if decc then macro = macro + "__DECC__=1," +# @ if axp then macro = macro + "__ALPHA__=1," +# @ if i64 then macro = macro + "__IA64__=1," +# @ if .not.(axp .or. i64 .or. decc) then macro = macro + "__VAXC__=1," +# @ macro = f$extract(0,f$length(macro)-1,macro)+ ")" +# $(MMS)$(MMSQUALIFIERS)'macro' DEFAULT + +# Define MMK architecture macros when using MMS. + +.IFDEF __MMK__ # __MMK__ +.ELSE # __MMK__ +ALPHA_X_ALPHA = 1 +IA64_X_IA64 = 1 +VAX_X_VAX = 1 +.IFDEF $(MMS$ARCH_NAME)_X_ALPHA # $(MMS$ARCH_NAME)_X_ALPHA +__ALPHA__ = 1 +.ENDIF # $(MMS$ARCH_NAME)_X_ALPHA +.IFDEF $(MMS$ARCH_NAME)_X_IA64 # $(MMS$ARCH_NAME)_X_IA64 +__IA64__ = 1 +.ENDIF # $(MMS$ARCH_NAME)_X_IA64 +.IFDEF $(MMS$ARCH_NAME)_X_VAX # $(MMS$ARCH_NAME)_X_VAX +__VAX__ = 1 +.ENDIF # $(MMS$ARCH_NAME)_X_VAX +.ENDIF # __MMK__ + +.IFDEF __ALPHA__ # __ALPHA__ +DEST = ALPHA +#E = .AXP_EXE +#O = .AXP_OBJ +#A = .AXP_OLB +.ELSE # __ALPHA__ +.IFDEF __IA64__ # __IA64__ +DEST = IA64 +#E = .I64_EXE +#O = .I64_OBJ +#A = .I64_OLB +.ELSE # __IA64__ +.IFDEF __DECC__ # __DECC__ +DEST = VAX +#E = .VAX_DECC_EXE +#O = .VAX_DECC_OBJ +#A = .VAX_DECC_OLB +.ENDIF # __DECC__ +.IFDEF __FORCE_VAXC__ # __FORCE_VAXC__ +__VAXC__ = 1 +.ENDIF # __FORCE_VAXC__ +.IFDEF __VAXC__ # __VAXC__ +DEST = VAXV +#E = .VAX_VAXC_EXE +#O = .VAX_VAXC_OBJ +#A = .VAX_VAXC_OLB +.ENDIF # __VAXC__ +.IFDEF __GNUC__ # __GNUC__ +DEST = VAXG +#E = .VAX_GNUC_EXE +#O = .VAX_GNUC_OBJ +#A = .VAX_GNUC_OLB +.ENDIF # __GNUC__ +.ENDIF # __IA64__ +.ENDIF # __ALPHA__ +.IFDEF O # O +.ELSE # O +!If EXE and OBJ extensions aren't defined, define them +E = .EXE +O = .OBJ +A = .OLB +.ENDIF # O + +.IFDEF SRCDIR +.ELSE +SRCDIR = [] +.ENDIF +.IFDEF DSTDIR # DSTDIR +.ELSE # DSTDIR +.IFDEF DEST # DEST +DSTDIR = [.$(DEST)] +.ELSE # DEST +DSTDIR = [] +.ENDIF # DEST +.ENDIF # DSTDIR + +!!!!!!!!!!!!!!!!!!!!!!!!!!! USER CUSTOMIZATION !!!!!!!!!!!!!!!!!!!!!!!!!!!! +! add any common optional preprocessor flags (macros) here +! (do not forget a trailing comma!!): +COMMON_DEFS = +!!!!!!!!!!!!!!!!!!!!!!!! END OF USER CUSTOMIZATION !!!!!!!!!!!!!!!!!!!!!!!! + +.IFDEF __GNUC__ +CC = gcc +LIBS = ,GNU_CC:[000000]GCCLIB.OLB/LIB +.ELSE +CC = cc +LIBS = +.ENDIF + +CFLAGS = /NOLIST + +OPTFILE = sys$disk:[.vms]vaxcshr.opt + +.IFDEF __ALPHA__ # __ALPHA__ +CC_OPTIONS = /STANDARD=RELAX/PREFIX=ALL/ANSI/NAMES=(AS_IS) +CC_DEFS = +.ELSE # __ALPHA__ +.IFDEF __IA64__ # __IA64__ +CC_OPTIONS = /STANDARD=RELAX/PREFIX=ALL/ANSI/NAMES=(AS_IS) +CC_DEFS = +.ELSE # __IA64__ +.IFDEF __DECC__ # __DECC__ +CC_OPTIONS = /DECC/STANDARD=RELAX/PREFIX=ALL/NAMES=(AS_IS) +CC_DEFS = +.ELSE # __DECC__ +.IFDEF __FORCE_VAXC__ # __FORCE_VAXC__ +!Select VAXC on systems where DEC C exists +CC_OPTIONS = /VAXC +.ELSE # __FORCE_VAXC__ +!No flag allowed/needed on a pure VAXC system +CC_OPTIONS = +.ENDIF # __FORCE_VAXC__ +CC_DEFS = +.ENDIF # __DECC__ +.ENDIF # __IA64__ +.ENDIF # __ALPHA__ + +! +! The .FIRST target is needed only if we're serious about building, +! and then, only if BZIP2 support was requested. +! +.IFDEF MMSTARGETS # MMSTARGETS +.FIRST + @ write sys$output " Destination: $(DSTDIR)" + @ write sys$output "" + if ("$(DEST)" .nes. "") then - + if (f$search("$(DEST).DIR;1") .eqs. "") then - + create /directory $(DSTDIR) +.ENDIF # MMSTARGETS +CC_DEFS2 = +CFLAGS_INCL = /INCLUDE = [] + +.IFDEF __DEBUG__ +CDEB = /DEBUG/NOOPTIMIZE +.ELSE +CDEB = +.ENDIF + +CFLAGS_ALL = $(CC_OPTIONS) $(CFLAGS) $(CDEB) $(CFLAGS_INCL) - + /def=($(CC_DEFS) $(COMMON_DEFS) BZ_NO_STDIO, VMS) - + $(CCOPTS) + + +OBJBZ2LIB = \ + $(DSTDIR)blocksort$(O), \ + $(DSTDIR)huffman$(O), \ + $(DSTDIR)crctable$(O), \ + $(DSTDIR)randtable$(O), \ + $(DSTDIR)compress$(O), \ + $(DSTDIR)decompress$(O), \ + $(DSTDIR)bzlib$(O) + +OLBBZ2 = $(DSTDIR)LIBBZ2_NS$(A) + +BZIP2_H = $(SRCDIR)bzlib.h $(SRCDIR)bzlib_private.h + +!!!!!!!!!!!!!!!!!!! override default rules: !!!!!!!!!!!!!!!!!!! +.suffixes : +.suffixes : .ANL $(E) $(A) .MLB .HLB .TLB .FLB $(O) - + .FORM .BLI .B32 .C .c .COB - + .FOR .BAS .B16 .PLI .PEN .PAS .MAC .MAR .M64 .CLD .MSG .COR .DBL - + .RPG .SCN .IFDL .RBA .RC .RCO .RFO .RPA .SC .SCO .SFO .SPA .SPL - + .SQLADA .SQLMOD .RGK .RGC .MEM .RNO .HLP .RNH .L32 .REQ .R32 - + .L16 .R16 .TXT .H .FRM .MMS .DDL .COM .DAT .OPT .CDO .SDML .ADF - + .GDF .LDF .MDF .RDF .TDF + +$(O)$(A) : + If "''F$Search("$(MMS$TARGET)")'" .EQS. "" Then $(LIBR)/Create $(MMS$TARGET) + $(LIBR)$(LIBRFLAGS) $(MMS$TARGET) $(MMS$SOURCE) + +.c$(O) : + $(CC) $(CFLAGS_ALL) /OBJ=$(MMS$TARGET) $(MMS$SOURCE) + +!!!!!!!!!!!!!!!!!! here starts the bzip2 specific part !!!!!!!!!!! + +DEFAULT default : CHK_DESTDIR $(OLBBZ2) + @ ! Do nothing. + +CLEAN.COM clean.com : + @ open/write tmp $(MMS$TARGET) + @ write tmp "$!" + @ write tmp "$! Clean.com -- procedure to delete files. It always returns success" + @ write tmp "$! status despite any error or warnings. Also it extracts" + @ write tmp "$! filename from MMS ""module=file"" format." + @ write tmp "$!" + @ write tmp "$ on control_y then goto ctly" + @ write tmp "$ if p1.eqs."""" then exit 1" + @ write tmp "$ i = -1" + @ write tmp "$scan_list:" + @ write tmp "$ i = i+1" + @ write tmp "$ item = f$elem(i,"","",p1)" + @ write tmp "$ if item.eqs."""" then goto scan_list" + @ write tmp "$ if item.eqs."","" then goto done ! End of list" + @ write tmp "$ item = f$edit(item,""trim"") ! Clean of blanks" + @ write tmp "$ wild = f$elem(1,""="",item)" + @ write tmp "$ show sym wild" + @ write tmp "$ if wild.eqs.""="" then wild = f$elem(0,""="",item)" + @ write tmp "$ vers = f$parse(wild,,,""version"",""syntax_only"")" + @ write tmp "$ if vers.eqs."";"" then wild = wild - "";"" + "";*""" + @ write tmp "$scan:" + @ write tmp "$ f = f$search(wild)" + @ write tmp "$ if f.eqs."""" then goto scan_list" + @ write tmp "$ on error then goto err" + @ write tmp "$ on warning then goto warn" + @ write tmp "$ delete/log 'f'" + @ write tmp "$warn:" + @ write tmp "$err:" + @ write tmp "$ goto scan" + @ write tmp "$done:" + @ write tmp "$ctly:" + @ write tmp "$ exit 1" + @ close tmp + +CLEAN clean : clean.com + @clean "$(OBJBZ2LIB)" + @clean "$(OLBBZ2)" + @- delete/noconfirm/nolog clean.com;* + @- if ("$(DEST).dir" .nes. "") then - + if (f$search("$(DEST).dir") .nes. "") then - + set protect=w:d $(DEST).dir;* + @- if ("$(DEST).dir" .nes. "") then - + if (f$search("$(DEST).dir") .nes. "") then - + delete/noconfirm $(DEST).dir;* + +CHK_DESTDIR chk_destdir : + @ If ("$(DEST)" .NES. "") Then - + If "''F$Search("$(DEST).DIR;1")'" .EQS. "" Then - + Create /directory $(DSTDIR) + +$(OLBBZ2) : $(OBJBZ2LIB) + If "''F$Search("$(MMS$TARGET)")'" .EQS. "" Then $(LIBR)/Create $(MMS$TARGET) + $(LIBR)$(LIBRFLAGS) $(MMS$TARGET) $(MMS$CHANGED_LIST) + @ write sys$output "$(MMS$TARGET) updated." + +$(OBJBZ2LIB) : $(BZIP2_H) + +$(DSTDIR)blocksort$(O) : $(SRCDIR)blocksort.c +$(DSTDIR)huffman$(O) : $(SRCDIR)huffman.c +$(DSTDIR)crctable$(O) : $(SRCDIR)crctable.c +$(DSTDIR)randtable$(O) : $(SRCDIR)randtable.c +$(DSTDIR)compress$(O) : $(SRCDIR)compress.c +$(DSTDIR)decompress$(O) : $(SRCDIR)decompress.c +$(DSTDIR)bzlib$(O) : $(SRCDIR)bzlib.c diff --git a/bzip2/makbz2iz.msc b/bzip2/makbz2iz.msc new file mode 100644 index 0000000..daf3663 --- /dev/null +++ b/bzip2/makbz2iz.msc @@ -0,0 +1,62 @@ +# Makefile for UnZip's bzip2 support library +# Win32 port, using Microsoft Visual C++ 6.0 +# +# (c) 2006-2007 Info-ZIP +# Last revision: Christian Spieler, 2007-Apr-03 +# +# This Makefile is intended to be called from UnZip's main make procedure. + +CC=cl +AR=link -lib +CFLSYS = -ML -O2 -nologo +CFLAGS= -D_WIN32 -DBZ_NO_STDIO $(CFLSYS) +!ifndef BZROOTDIR +BZROOTDIR=. +!endif +BZROOT=$(BZROOTDIR)/ +!ifndef BZOBDIR +BZOBDIR=. +!endif +BZOB=$(BZOBDIR)/ +O=.obj + + +OBJS= $(BZOB)blocksort$(O) \ + $(BZOB)huffman$(O) \ + $(BZOB)crctable$(O) \ + $(BZOB)randtable$(O) \ + $(BZOB)compress$(O) \ + $(BZOB)decompress$(O) \ + $(BZOB)bzlib$(O) + +izlib: $(BZOBDIR) $(BZOB)bz2.lib + +$(BZOBDIR) : + -mkdir $@ + +$(BZOB)bz2.lib: $(OBJS) + $(AR) $(OBJS) -out:$(BZOB)bz2.lib + +clean: + -del $(BZOBDIR)\*$(O) + -del $(BZOBDIR)\bz2.lib + +.c$(O): + $(CC) $(CFLAGS) -c -Fo$@ $< + +$(OBJS) : $(BZROOT)bzlib.h $(BZROOT)bzlib_private.h + +$(BZOB)blocksort$(O) : $(BZROOT)blocksort.c + $(CC) $(CFLAGS) -c -Fo$@ $(BZROOT)blocksort.c +$(BZOB)huffman$(O) : $(BZROOT)huffman.c + $(CC) $(CFLAGS) -c -Fo$@ $(BZROOT)huffman.c +$(BZOB)crctable$(O) : $(BZROOT)crctable.c + $(CC) $(CFLAGS) -c -Fo$@ $(BZROOT)crctable.c +$(BZOB)randtable$(O) : $(BZROOT)randtable.c + $(CC) $(CFLAGS) -c -Fo$@ $(BZROOT)randtable.c +$(BZOB)compress$(O) : $(BZROOT)compress.c + $(CC) $(CFLAGS) -c -Fo$@ $(BZROOT)compress.c +$(BZOB)decompress$(O) : $(BZROOT)decompress.c + $(CC) $(CFLAGS) -c -Fo$@ $(BZROOT)decompress.c +$(BZOB)bzlib$(O) : $(BZROOT)bzlib.c + $(CC) $(CFLAGS) -c -Fo$@ $(BZROOT)bzlib.c diff --git a/bzip2/makbz2iz.wat b/bzip2/makbz2iz.wat new file mode 100644 index 0000000..9653830 --- /dev/null +++ b/bzip2/makbz2iz.wat @@ -0,0 +1,62 @@ +# Makefile for UnZip's bzip2 support library +# MSDOS & Win32 ports, using OpenWatcom C++ +# +# (c) 2006-2007 Info-ZIP +# Last revision: Christian Spieler, 2007-Apr-03 +# +# This Makefile is intended to be called from UnZip's main make procedure. + +CC=wcc386 +AR=lib386 +CFLSYS = -6r -zt -zq -wx -s -obhikl+rt -oe100 -zp8 -q +CFLAGS= $(CFLSYS) -DBZ_NO_STDIO +!ifndef BZROOTDIR +BZROOTDIR=. +!endif +BZROOT=$(BZROOTDIR)\ +!ifndef BZOBDIR +BZOBDIR=. +!endif +BZOB=$(BZOBDIR)/ +O=.obj + + +OBJS= $(BZOB)blocksort$(O) & + $(BZOB)huffman$(O) & + $(BZOB)crctable$(O) & + $(BZOB)randtable$(O) & + $(BZOB)compress$(O) & + $(BZOB)decompress$(O) & + $(BZOB)bzlib$(O) + +izlib: $(BZOBDIR) $(BZOB)bz2.lib + +$(BZOBDIR) : + -mkdir $@ + +$(BZOB)bz2.lib: $(OBJS) + $(AR) -nologo $(OBJS) -out:$(BZOB)bz2.lib + +clean: .SYMBOLIC + -del $(BZOBDIR)\*$(O) + -del $(BZOBDIR)\bz2.lib + +.c$(O): + $(CC) $(CFLAGS) -fo=$@ $< + +$(OBJS) : $(BZROOT)bzlib.h $(BZROOT)bzlib_private.h + +$(BZOB)blocksort$(O) : $(BZROOT)blocksort.c + $(CC) $(CFLAGS) -Fo=$@ $(BZROOT)blocksort.c +$(BZOB)huffman$(O) : $(BZROOT)huffman.c + $(CC) $(CFLAGS) -Fo=$@ $(BZROOT)huffman.c +$(BZOB)crctable$(O) : $(BZROOT)crctable.c + $(CC) $(CFLAGS) -Fo=$@ $(BZROOT)crctable.c +$(BZOB)randtable$(O) : $(BZROOT)randtable.c + $(CC) $(CFLAGS) -Fo=$@ $(BZROOT)randtable.c +$(BZOB)compress$(O) : $(BZROOT)compress.c + $(CC) $(CFLAGS) -Fo=$@ $(BZROOT)compress.c +$(BZOB)decompress$(O) : $(BZROOT)decompress.c + $(CC) $(CFLAGS) -Fo=$@ $(BZROOT)decompress.c +$(BZOB)bzlib$(O) : $(BZROOT)bzlib.c + $(CC) $(CFLAGS) -Fo=$@ $(BZROOT)bzlib.c diff --git a/cmsmvs/INSTALL.CMS b/cmsmvs/INSTALL.CMS new file mode 100644 index 0000000..75ed6dd --- /dev/null +++ b/cmsmvs/INSTALL.CMS @@ -0,0 +1,159 @@ +----------------------------------------------------------------------- +[Installation notes for VM/CMS port of UNZIP 5.32 and ZIP 2.2] +Additional notes from Ian E. Gorman (4/98): + +I have not fully tested ZIP and UNZIP in VM (for example, I have not +tried all the options), so ZIP 2.2 for VM and UNZIP 5.32 for VM +should be regarded as beta versions. Try them out before you decide +that you can depend on them. + +Most of the work for the VM port has been done by others, but I have +made some changes and compiled on a more recent version of VM/CMS. It +is possible that I have introduced new problems or undone some of the +solutions found by previous authors. + + +Installation +============ + +The executables are stored in CMS "PACK" format instead of being +stored in ZIP archives. This format takes a little longer to +download, but installation is slightly simpler. + + +Installing UNZIP +---------------- + +The UNZIP executable is supplied as the binary file UNZIP.MOD, in the +CMS "PACK" format. + +You must get the UNZIP.MOD file on to your system as a binary file in +fixed recording mode, block size 1024. + +If you are using FTP in CMS, you can get the file in the correct +format with the LOCSITE and BINARY commands. Assuming that the UNZIP +executable is stored on the remote site as unz532vm.mod, you could +issue the following commands + + FTP where.ever.com + + BINARY + LOCSITE FIX 1024 + GET unz532vm.mod + QUIT + +If you are using a 3270 terminal session to upload from a PC, you can +upload the file in the correct format with the SEND command: + + SEND unz532vm.mod A: unz532vm mod a1 (RECFM F LRECL 1024 + +If your 3270 emulator does not have the SEND command, but is a GUI +application, it may allow you to upload from the menu bar. If so, +set your options to binary, VM/CMS, fixed record length, and a length +of 1024 before you upload. + +When you get the PACKed file on your CMS minidisk, you convert it to +an executable module by using the COPY command with the UNPACK option: + + COPY unz532vm mod a unzip module a1 (UNPACK OLDDATE REPLACE + +You can omit the OLDDATE and REPLACE options if you want to. + + +Installing ZIP +-------------- + +The ZIP executable is supplied as the binary file ZIP.MOD, in the CMS +"PACK" format. + +You must get the ZIP.MOD file on to your system as a binary file in +fixed recording mode, block size 1024. Assuming that the file is +stored as zip22vm.mod, you can get the file the same way you got the +UNZIP.MOD file: + + Using FTP: + + FTP where.ever.com + + BINARY + LOCSITE FIX 1024 + GET zip22vm.mod + QUIT + + Using 3270 file transfer: + + SEND unz532vm.mod A: unz532vm mod a1 (RECFM F LRECL 1024 + +When you get the PACKed file on your CMS minidisk, you convert it to +an executable module by using the COPY command with the UNPACK option: + + COPY zip22vm mod a zip module a1 (UNPACK OLDDATE REPLACE + + +Installing Documentation +------------------------ + +Once you have UNZIP running, you can use it to extract documentation +from ZIP archives. + +You can transfer the ZIP archives to VMV/CMS as a binary file with any +record length. A record length of 1 will work fine: + + via FTP: + + FTP where.ever.com + + BINARY + LOCSITE FIX 1 + GET zip22vm.zip zipdoc.zip + GET unz532vm.zip unzipdoc.zip + QUIT + + via 3270 session: + + SEND zip22vm.zip A: unzipdoc zip a1 (RECFM F LRECL 1 + SEND unz532vm.zip A: zipdoc zip a1 (RECFM F LRECL 1 + +Once you have the ZIP archives, extract the documentation to the minidisk of +your choice by using the -d option: + + unzip -a -d A2 unzipdoc.zip + unzip -a -d A2 zipdoc.zip + +The "-a" option is required because the documents are archived as +ASCII text files, but they must be converted to EBCDIC to read them +in VM/CMS. + + +Notes +===== + +Different EBCDIC Character Sets +------------------------------- + +The documentation may look strange on your system, because UNZIP +translates from ASCII to "Open Systems" EBCDIC (IBM-1047). Unless +you are a software developer, you are probably using a different +kind of EBCDIC (like US EBCDIC, IBM-037). This causes some character +codes to display as different characters. For example, the character +codes that display as square brackets in IBM-1047 will display as +e-acute and a-grave in IBM-037. + +You can use the IBM ICONV utility to translate documents from one +character set to another: + + ICONV old doc a new doc a1 (FROMCODE IBM-1047 TOCODE IBM-037 + + +IND$FILE protocol +----------------- + +This is the method by which files are transferred via 3270 sessions +between PC and mainframe. + +If you know how to transfer files via 3270 session between PC and +mainframe, you know as much as you need to know about IND$FILE. + +If your mainframe has IND$FILE, and your 3270 emulator does file +transfers, you can use your emulator to transfer files between PC +and mainframe. diff --git a/cmsmvs/README.CMS b/cmsmvs/README.CMS new file mode 100644 index 0000000..a4425da --- /dev/null +++ b/cmsmvs/README.CMS @@ -0,0 +1,434 @@ +Using ZIP and UNZIP on VM/CMS +============================= + + +Installing executables +---------------------- + +The following CMS MODULEs are available: + ZIP + ZIPNOTE + ZIPCLOAK + ZIPSPLIT + UNZIP + +In addition to these, each MODULE file also has an EXEC with the same +name. These EXECs are front-ends to the MODULES that will attempt to +set up the required runtime libraries before running the MODULE. +All the EXECs are identical. Only their names are different. +They are stored as plain text files. + +The CMS MODULE files have been packed using the COPYFILE command to +allow their file format to be properly restored, since variable length +binary files will not currently unzip properly (see below for details). +The MODULEs are shipped with a filetype or extension of CMO (for CMS +MODULE). Their names may vary on the distribution disk to indicate +their level, etc. + +To restore them to executable MODULEs on CMS, do the following: + 1. Upload them to CMS with a Fixed record length with LRECL 1024. + Example, from a DOS or OS/2 window, type this: + SEND unzip.cmo A:unzip module a (RECFM F LRECL 1024 + + Example, using FTP from CMS, type this: + BINARY FIXED 1024 + GET unzip.cmo unzip.module.a + + Note: Replace "unzip.cmo" with the actual name. + + 2. Use COPYFILE to unpack the file. + Example, in CMS type this: + COPYFILE UNZIP MODULE A (UNPACK REPLACE OLDDATE + + 3. Repeat steps 1-2 for each of the programs. + + 4. Build the ZIPINFO module by typing this: + COPYFILE UNZIP MODULE A ZIPINFO MODULE A (OLDDATE + + 5. Upload the EXECs to CMS as text files (with ASCII-to-EBCDIC + translation). + Example, from a DOS or OS/2 window, type this: + SEND unzip.exc A:unzip exec a (CRLF + + Example, using FTP from CMS, type this: + GET unzip.exc unzip.exec.a + + 6. Repeat steps 4 for each of the EXECs. + + +Preparing the environment +------------------------- + +The executables provided were compiled with IBM C 3.1.0 and +require the the Language Environment (LE) runtime libraries. + +To provide access to the runtime libraries: + 1. Link to the disk containing the Language Environment files, + if necessary. + + 2. Use the command "GLOBAL LOADLIB SCEERUN" + + These commands can be placed in your PROFILE EXEC. + + Note: EXECs have been provided called ZIP, UNZIP, etc. that + issue the GLOBAL LOADLIB statement. This was done to alleviate + frustration of users that don't have the GLOBAL LOADLIB statement + in their PROFILE EXEC. These EXECs may require changing for + your system. + + Unfortunately, there is no way, using IBM C, to produce a MODULE + that doesn't require a runtime library. + + +Testing +------- + +To test the MODULEs, just type ZIP or UNZIP. They should +show help information on using the commands. + +If you see something like this: + DMSLIO201W The following names are undefined: + CEEEV003 + DMSABE155T User abend 4093 called from 00DCD298 reason code 000003EB + +Then you don't have access to the proper runtime libraries, as +described above. + +Here is additional information on the ZIP and UNZIP programs that +may assist support personnel: + - Compiled with IBM C V3R1M0 on VM/ESA 2.2.0 with + CMS level 13 Service Level 702. + + - Require the SCEERUN LOADLIB runtime library. This is + part of the Language Environment (LE). + + - Linked with options RMODE ANY AMODE ANY RLDSAVE. + +If you continue to have trouble, report the problem to Zip-Bugs +(see the bottom of this document). + + + +Compiling the source on VM/CMS +------------------------------ + +The source has been successfully compiled previously using +C/370 2.1 and 2.2. The source has been recently compiled using +IBM C 3.1.0 on VM/ESA 2.2.0 with CMS level 13. I don't have +access to an MVS system so the code hasn't been tested there +in a while. + + 1. Unzip the source files required for CMS. The root-level files + inside the ZIP file and the files in the CMSMVS subdirectory are + needed. Example (use both commands): + unzip -aj zip23.zip -x */* -dc + unzip -aj zip23.zip cmsmvs/* -dc + + This example unzips the files to the C-disk, while translating + character data and ignoring paths. + + If you don't already have a working UNZIP MODULE on CMS you will + have to unzip the files on another system and transport them + to CMS. All the required files are plain text so they can + be transferred with ASCII-to-EBCDIC translations. + + 2. Repeat step 1 with the zip file containing the UNZIP code. + Unzip the files to a different disk than the disk used for the ZIP + code. + + 3. To compile the ZIP code, run the supplied CCZIP EXEC. + To compile the UNZIP code, run the supplied CCUNZIP EXEC. + +NOTE: +Some of the ZIP and UNZIP source files have the same name. It is +recommended that you keep the source from each on separate disks and +move the disk you are building from ahead of the other in the search +order. + +For example, you may have a 192 disk with the ZIP source code and +a 193 disk with the UNZIP source code. To compile ZIP, access +the 192 disk as B, then run CCZIP. This will create the following +modules: ZIP, ZIPNOTE, ZIPSPLIT, ZIPCLOAK. + +To compile UNZIP, access 193 as B, then run CCUNZIP. This will create +the following modules: UNZIP, ZIPINFO (a copy of UNZIP). + + +========================================================================= + + +Using ZIP/UNZIP +--------------- + +Documentation for the commands is in MANUAL NONAME (for ZIP) and in +UNZIP DOC UNZIP. INFOZIP DOC describes the use of the -Z option of +UNZIP. + +The rest of this section explains special notes concerning the VM/CMS +version of ZIP and UNZIP. + + +Filenames and directories +------------------------- + + 1. Specifying filenames + + a. When specifying CMS files, use filename.filetype.filemode format + (separate the three parts of the name with a period and use no + spaces). Example: profile.exec.a + + Unfortunately, this prevents you from using ZIP from + FILELIST. To unzip a zip file, however, you can type something + like this next to it in FILELIST: + unzip /n -d c + + This will unzip the contents of the current file to a C-disk. + + b. It is possible to use DD names with ZIP and UNZIP on CMS, though + it can be cumbersome. Example: + filedef out disk myzip zip a + zip dd:out file1.txt file2.txt + + While you can also use a DD name for the input files, ZIP + currently does not correctly resolve the filename and will + store something like "dd:in" inside the ZIP file. A file stored + in this manor cannot easily be unzipped, as "dd:in" is an invalid + filename. + + c. In places where a directory name would be used on a PC, such as + for the ZIP -b (work path) option or the UNZIP -d (destination + path) options, use a filemode letter for CMS. For example, + to unzip files onto a C-disk, you might type something like this: + unzip myzip.zip -d c + + Currently, ZIP uses the A-disk for work files. When zipping + large files, you may want to specify a larger disk for work files. + This example will use a C-disk for work files. + zip -b C myzip.zip.c test.dat.a + + + 2. Filename conversions + + a. Filemode letters are never stored into the zip file or take from + a zip file. Only the filename and filetype are used. + ZIP removes the filemode when storing the filename into the + zip file. UNZIP assumes "A" for the filemode unless the -d + option is used. + + b. When unzipping, any path names are removed from the fileid + and the last two period-separated words are used as the + filename and filetype. These are truncated to a maximum of + eight characters, if necessary. If the filetype (extension) + is missing, then UNZIP uses "NONAME" for the filetype. + Any '(' or ')' characters are removed from the fileid. + + c. All files are created in upper-case. Files in mixed-case + cannot currently be stored into a ZIP file. + + d. Shared File System (SFS) directories are not supported. + Files are always accessed by fn.ft.fm. To use an SFS disk, + Assign it a filemode, then it can be used. + + + 3. Wildcards in file names + + a. Wildcards are not supported in the zip filename. The full + filename of the zip file must be given (but the .zip is not + necessary). So, you can't do this: + unzip -t *.zip + + b. Wildcards CAN be used with UNZIP to select (or exclude) files + inside a zip file. Examples: + unzip myzip *.c - Unzip all .c files. + unzip myzip *.c -x z*.c - Unzip all .c files but those + starting with Z. + + c. Wildcards cannot currently be used to select files with ZIP. + So, you can't do this: + zip -a myzip *.exec + + I expect to fix this for CMS in the future. + + + 4. File timestamps + + a. The dates and times of files being zipped or unzipped are not + currently read or set. When a file is zipped, the timestamp + inside the zip file will always be the current system date and + time. Likewise, when unzipping, the date and time of files + being unzipped will always be the current system date/time. + + b. Existing files are assumed to be newer than files inside a zip + file when using the -f freshen option of UNZIP. This will prevent + overwriting files that may be newer than the files inside the + zip file, but also effectively prevents the -f option from working. + + + 5. ASCII, EBCDIC, and binary data + + Background + ---------- + Most systems create data files as just a stream of bytes. Record + breaks happen when certain characters (new line and/or carriage + return characters) are encountered in the data. How to interpret + the data in a file is up to the user. The system must be told + to either notice new line characters in the data or to assume + that the data in the file is binary data and should be read or + written as-is. + + CMS and MVS are record-based systems. All files are composed + of data records. These can be stored in fixed-length files or + in variable length files. With fixed-length files, each record + is the same length. The record breaks are implied by the + LRECL (logical record length) attribute associated with the file. + With variable-length files, each record contains the length of + that record. The separation of records are not part of the + data, but part of the file structure. + + This means you can store any type of data in either type of file + structure without having to worry about the data being interpreted + as a record break. Fixed-length files may have padding at the + end of the file to make up a full record. Variable-length files + have no padding, but require extra record length data be stored + with the file data. + + Storing fixed-length files into a zip file is simple, because all + the data can just be dumped into the zip file and the record + format (RECFM) and logical record length (LRECL) can be stored + in the extra data area of the zip file so they can be restored + when UNZIP is used. + + Storing variable-length data is harder. There is no place to put + the record length data needed for each record of the file. This + data could be written to the zip file as the first two bytes of + each record and interpreted that way by UNZIP. That would make + the data unusable on systems other than CMS and MVS, though. + + Currently, there isn't a solution to this problem. Each record is + written to the zip file and the record length information is + discarded. Binary data stored in variable-length files can't be put + into a zip file then later unzipped back into the proper records. + This is fine for binary data that will be read as a stream of bytes + but not OK where the records matter, such as with CMS MODULEs. + + If the data is text (character data), there is a solution. + This data can be converted into ASCII when it's stored into + a zip file. The end of each record is now marked in the file + by new line characters. Another advantage of this method is + that the data is now accessible to non-EBCDIC systems. When + the data is unzipped on CMS or MVS, it is converted back into + EBCDIC and the records are recreated into a variable-length file. + + + So, here's what we have... + + a. To store readable text data into a zip file that can be used + on other platforms, use the -a option with ZIP to convert the + data to ASCII. These files will unzip into variable-length + files on CMS and should not contain binary data or corruption + may occur. + + b. Files that were zipped on an ASCII-based system will be + automatically translated to EBCDIC when unzipped. To prevent + this (to unzip binary data on CMS that was sent from an + ASCII-based system), use the -B option with UNZIP to force Binary + mode. To zip binary files on CMS, use the -B option with ZIP to + force Binary mode. This will prevent any data conversions from + taking place. + + c. When using the ZIP program without specifying the "-a" or "-B" + option, ZIP defaults to "native" (EBCDIC) mode and tries to + preserve the file information (RECFM, LRECL, and BLKSIZE). So + when you unzip a file zipped with ZIP under CMS or MVS, UNZIP + restores the file info. The output will be fixed-length if the + original was fixed and variable-length if the original was + variable. + + If UNZIP gives a "write error (disk full?)" message, you may be + trying to unzip a binary file that was zipped as a text file + (without using the -B option) + + + Summary + ------- + Here's how to ZIP the different types of files. + + RECFM F text + Use the -a option with ZIP to convert to ASCII for use with other + platforms or no options for use on EBCDIC systems only. + + RECFM V text + Use the -a option with ZIP to convert to ASCII for use with other + platforms or no options for use on EBCDIC systems only. + + + RECFM F binary + Use the -B option with ZIP (upper-case "B"). + + RECFM V binary + Use the -B option with ZIP. Can be zipped OK but the record + structure is destroyed when unzipped. This is OK for data files + read as binary streams but not OK for files such as CMS MODULEs. + + + 6. Character Sets + + If you are used to running UNZIP on systems like UNIX, DOS, OS/2 or + Windows, you will may have some problems with differences in the + character set. + + There are a number of different EBCDIC code pages, like there are a + number of different ASCII code pages. For example, there is a US + EBCDIC, a German EBCDIC, and a Swedish EBCDIC. As long as you are + working with other people who use the same EBCDIC code page, you + will have no trouble. If you work with people who use ASCII, or who + use a different EBCDIC code page, you may need to do some + translation. + + UNZIP translates ASCII text files to and from Open Systems EBCDIC + (IBM-1047), which may not be the EBCDIC that you are using. For + example, US EBCDIC (IBM-037) uses different character codes for + square brackets. In such cases, you can use the ICONV utility + (supplied with IBM C) to translate between your EBCDIC character set + and IBM-1047. + + If your installation does not use IBM-1047 EBCDIC, messages from + UNZIP may look a little odd. For example, in a US EBCDIC + installation, an opening square bracket will become an i-acute and a + closing square bracket will become a u-grave. + + The supplied ZIP and UNZIP EXECs attempt to correct this by setting + CMS INPUT and OUTPUT translations to adjust the display of left and + right brackets. You may need to change this if brackets don't + display correctly on your system. + + + 7. You can unzip using VM/CMS PIPELINES so unzip can be used as + a pipeline filter. Example: + 'PIPE COMMAND UNZIP -p test.zip george.test | Count Lines | Cons' + + + + +Please report all bugs and problems to: + Zip-Bugs@lists.wku.edu + + +----------------------------------------------------------------------- +Original CMS/MVS port by George Petrov. +e-mail: c888090@nlevdpsb.snads.philips.nl +tel: +31-40-781155 + +Philips C&P +Eindhoven +The Netherlands + +----------------------------------------------------------------------- +Additional fixes and README re-write (4/98) by Greg Hartwig. +e-mail: ghartwig@ix.netcom.com + ghartwig@vnet.ibm.com + +----------------------------------------------------------------------- +Additional notes from Ian E. Gorman. +e-mail: ian@iosphere.net + diff --git a/cmsmvs/README.MVS b/cmsmvs/README.MVS new file mode 100644 index 0000000..89019af --- /dev/null +++ b/cmsmvs/README.MVS @@ -0,0 +1,169 @@ +Thank you for trying this port of UNZIP for VM/CMS and MVS! + + Using under MVS: + ------------------------- + +1. To use the Info-ZIP's UNZIP under MVS you need: + + - C/370 ver 2.1 compiler or another compatible compiler supporting + long names for function/variable names. + +2. To compile the program under MVS do : + + - unzip all the files from unz54vm.zip file. They are stored as + ASCII format so you have to unzip them first on PC or other + system that already have UNZIP, and then upload them to the + mainframe with ASCII to EBCDIC conversion. + + - Copy all the .C files in the PDS called USERID.UNZIP.C + + - Copy all the .H files in the PDS called USERID.UNZIP.H + + - adjust the job UNZMVSC.JOB to work on your site. Change USERID + to your userid. You might need to change the CEE dataset names + to match your OS/390 system. + + - Preallocate PDS datasets named: USERID.UNZIP.OBJ and + USERID.UNZIP.LOAD + + - execute the job UNZMVSC to compile and link all the sources. + + - if everything is ok you will get an UNZIP MODULE + +3. Using UNZIP + + - Just read the UNZIP.TXT + + - A few exceptions concerning MVS + + 3.0. There are different ways to invoke UNZIP. + + - allocating UNZIP.LOAD dataset to your ISPLLIB if you + want to invoke UNZIP under ISPF. + Then just type UNZIP ...parms... to get it work + + - You can also call it directly with : + TSO CALL 'userid.UNZIP.LOAD(UNZIP)' '...parms...' + (notice to quotes!) + + - You can even call it from a batch job like: + + //MYZIP JOB (account) + //STEP1 EXEC PGM=UNZIP,PARM='-l mytestz.zip *.c' + //STEPLIB DD DSN=userid.UNZIP.LOAD,DISP=SHR + //SYSPRINT DD SYSOUT=* + + This will list all the .c files from the zip file mytestz.zip + + 3.1. If the ZIP file has been zipped on an ASCII based system + it will be automatically translated to EBCDIC + ( I hope I got all those translation tables OK :-). + You can force ASCII to EBCDIC conversion with the -a flag. + + 3.2. The date/time of the output files is set to the + current system date/time - not according the date/time in + the zip file. + + 3.3. You can even unzip using TSO/E PIPELINES + so unzip can be used as pipeline filter: + + 'pipe cms unzip -p test.zip george.test | count lines | cons' + ( we do also a lot of pipethinking here ;-) + + 3.4. If you got also the ZIP program (see ZIP21VM.ZIP) you can + do zipping and unzipping without translating to ASCII + the ZIP also preserves the file informations (LRECL,BLKSIZE..) + So when you UNZIP a file zipped with ZIP under MVS it + restores the file info. + + There currently some problems with file with RECFM=V* + I don't save the length of each record yet :-) + + 3.5. No wildcards are supported in the input zip name you have + to give the real name (.zip is not necessary) + + So you CAN'T use things like: unzip -t *.zip + + 3.6. But you CAN use wildcards as filename selection like: + unzip -t myzip *.c - OK or even + unzip -t myzip *.c -x z*.c - to exclude all files matching + z*.c + + 3.7. You can unzip to a PDS using the -d parameter, + for example: + + unzip -dmyzip myzip *.c + + This will unzip all .c files that are in the zip file in a + PDS directory called MYZIP.C + + BE AWARE that the extension of every files is being placed as + last identifier on the PDS name, so if you have a file in the + zipfile called 'testp.doc' and you use '-d mypds' the PDS + name will become 'mypds.doc(testp)' + + Depending on which options IBM chose for C this week, unzip + may or may not prefix output files with your userid and/or + TSO prefix. To prevent this, quote the filename to -d, for + example + + //UNZIP EXEC PGM=UNZIP, + // PARM='/-a -o ''userid.zip'' -d ''hlq.test'' *' + //STEPLIB DD DSN=USERID.UNZIP.LOAD,DISP=SHR + //SYSPRINT DD SYSOUT=* + //SYSOUT DD SYSOUT=* + + The above JCL converts from ASCII to EBCDIC (-a), always + overwrites existing members (-o), extracts from 'userid.zip', + writes to files starting with 'hlq.test', all members (*). + Note the double quotes because PARM= requires single quotes. + + 3.8. The rules for output DCBs are a little messy. If the output + file already exists (remember the -d option) then unzip uses + the existing DCB and space values. + + If the output file does not exist and the input zip came from + MVS then unzip makes its best attempt at preserving the + original DCB. However there is not enough information stored + in the zip file to do this correctly for all file types, some + file types may be corrupted. + + If the output file does not exist and the input zip does not + contain MVS DCB information then unzip uses RECFM=U, + LRECL=32760 for binary data, RECFM=V, LRECL=133 for text. + Text includes ASCII to EBCDIC conversion. As soon as the + output file is created, unzip uses the same output DCB for + all following members, even if the input is a mixture of text + and binary. + + In all cases, unzip has no built in parameters for space. + For a preallocated file this is not a problem. If unzip + creates an output file you get a default space allocation + which is site dependent. + + It is far better to preallocate the output files with the + correct space and DCB values then use the -d option to point + to those files. + + 3.9. All '+','_' or '-' signs are skipped from the filenames + + +Please repport all bugs and problems to : + Zip-Bugs@lists.wku.edu + +That's all for now. + +Have fun! + + +George Petrov +e-mail: c888090@nlevdpsb.snads.philips.nl +tel: +31-40-781155 + +Philips C&P +Eindhoven +The Netherlands + +Updated by: + +Keith Owens diff --git a/cmsmvs/WHATSNEW.CMS b/cmsmvs/WHATSNEW.CMS new file mode 100644 index 0000000..edbf350 --- /dev/null +++ b/cmsmvs/WHATSNEW.CMS @@ -0,0 +1,27 @@ +Important Changes made for ZIP 2.3b and UNZIP 5.33c executables: + +1. WARNING: These executables have been compiled for the + Language Environment (LE). You must now have access to the file + SCEERUN LOADLIB in order to run ZIP and UNZIP on CMS. You no longer + need access to EDCLINK LOADLIB. The provided ZIP and UNZIP EXECs + have been changed to issue a new GLOBAL LOADLIB command. You may + need to modify these EXECs for your installation. You may want to + change any GLOBAL LOADLIB command you may have in your PROFILE EXEC. + + Versions could be made available for the older EDCLINK LOADLIB + runtimes upon request. + +2. ZIP files will now be variable length files rather than fixed + length files. + +3. Help information for ZIP and UNZIP has been changed to show + "fm" rather than "path" on CMS with certain options. + +4. README CMS has been entirely rewritten. It now contains all + information for ZIP and UNZIP. + +----------------------------------------------------------------------- +Greg Hartwig, April 1998. +e-mail: ghartwig@ix.netcom.com + ghartwig@vnet.ibm.com + diff --git a/cmsmvs/ccunzip.exec b/cmsmvs/ccunzip.exec new file mode 100644 index 0000000..b0771de --- /dev/null +++ b/cmsmvs/ccunzip.exec @@ -0,0 +1,77 @@ +/* CCUNZIP EXEC Compile unzip 5.4 for VM/CMS */ +/* Author: George Petrov, 11 Apr 1995 (VMCOMPIL EXEC) */ +/* Modified for IBM C V3R1 by Ian E. Gorman, 2 Nov 1998 + Facilities for compiling and testing were provided by + OmniMark Technologies Corporation, Ottawa, Canada +*/ +Address Command +Signal On Error + +/* Allow longnames, compile re-entrant code. + global.c and vmmvs.c require EXTENDED features */ +CCopts = 'LONGNAME RENT LANGLVL(EXTENDED) NOEXECOPS' + +/* UNZIP options -- VM_CMS, REENTRANT */ +CCopts = CCopts 'DEFINE(VM_CMS,REENTRANT)' + +/* Link the load module to run in more or less than 16MB memory */ +LINKopts = 'AMODE ANY RMODE ANY RLDSAVE' + + +'GLOBAL TXTLIB SCEELKED CMSLIB' +'GLOBAL LOADLIB SCEERUN' + + +/* produce the TEXT (object) files */ +linklist='' +modname='UNZIP' +Say 'Building' modname 'MODULE...' +Call Compile 'UNZIP' +Call Compile 'CRC32' +Call Compile 'CRYPT' +Call Compile 'ENVARGS' +Call Compile 'EXPLODE' +Call Compile 'EXTRACT' +Call Compile 'FILEIO' +Call Compile 'GLOBALS' +Call Compile 'INFLATE' +Call Compile 'PROCESS' +Call Compile 'LIST' +Call Compile 'MATCH' +Call Compile 'TTYIO' +Call Compile 'UNREDUCE' +Call Compile 'UNSHRINK' +Call Compile 'ZIPINFO' +Call Compile 'VMMVS' + +Say 'Linking...' +'EXEC CMOD' linklist '(MODNAME' modname LINKopts +Say modname 'built successfully.' + + +/* Make ZIPINFO from UNZIP */ +modname = 'ZIPINFO' +'COPYFILE UNZIP MODULE A ZIPINFO MODULE A (OLDDATE REPLACE' +Say modname 'built successfully.' +Say 'Done.' + +Exit rc + + + +error: +Say 'Error' rc 'during compilation!' +Say 'Error in line' sigl':' +Say ' 'Sourceline(sigl) +Exit rc + + + +Compile: Procedure Expose CCopts LINKopts linklist +Parse arg filename filetype filemode . +If filetype='' Then filetype='C' +linklist = linklist filename + +Say 'Compiling' filename filetype filemode '...' +'EXEC CC' filename filetype filemode '('CCopts +Return rc diff --git a/cmsmvs/mc.exec b/cmsmvs/mc.exec new file mode 100644 index 0000000..afd9496 --- /dev/null +++ b/cmsmvs/mc.exec @@ -0,0 +1,85 @@ +/* MAKECPIP EXEC Make program to build a C/370 module */ +/* Author: George Petrov, 29 Sep 1994 */ + +arg fn . '(' cparms /* Filter name */ +'pipe (end ?) < 'fn' makefile', /* get all source files from */ + '| frlab GLOBALS:'||, + '| drop', + '| strip', + '| var globals' +cparms = cparms globals +say '' +say 'Compile options : 'cparms +say '' +if pos('REB',cparms) > 0 then do +parse var cparms cp1 'REB' . ' ' cp2 /* REBuild options specified ? */ +cparms = cp1||cp2 +pipe1=, +'pipe (end ?) < 'fn' makefile', /* get all source files from */ + '| nfind *'||, /* the makefile and compile */ + '| frlab TEXT:'||, /* only the those who are */ + '| r: tolab MODULE:'||, /* changed or never compiled */ + '| drop', + '| o: fanout', + '| chop before str /(/', + '| statew', + '| c: fanout', /* compiled */ + '| specs /Compiling / 1 w1-3 n / .../ n', + '| cons' +end +else do +pipe1=, +'pipe (end ?) < 'fn' makefile', /* get all source files from */ + '| nfind *'||, /* the makefile and compile */ + '| frlab TEXT:'||, /* only the those who are */ + '| r: tolab MODULE:'||, /* changed or never compiled */ + '| drop', + '| o: fanout', + '| specs w1 1 /C/ nw w3 nw write w1 1 /TEXT A/ nw', + '| chop before str /(/', + '| statew', + '| change (57 66) / /0/', + '| sort 1.8 d', /* sort the date and time */ + '| uniq 1-17 singles', /* if the first is a source */ + '| sort 1.8 d 64.2 d 57.2 d 60.2 d 66.8 d', /* sort the date */ + '| uniq 1-8 first', /* if the first is a source */ + '| locate 9.8 /C /', /* program then it has to be */ + '| c: fanout', /* compiled */ + '| specs /Compiling / 1 w1-3 n / .../ n', + '| cons' +end +pipe2= '?', + 'r:', + '| drop', + '| specs w1 1', /* save the module name in var */ + '| var module', + '?', + 'o:', + '| specs w1 1', + '| join * / /', + '| var texts', /* save all the text file names */ + '?', /* for later include */ + 'c:', + '| specs /CC / 1 w1-3 n /(NOTERM 'cparms'/ nw', /* compile! */ + '| err: cms | cons', + '?', + 'err:', + '| nfind 0'||, + '| var err', + '| specs /----> Errors found! RC=/ 1 1-* n', + '| cons' +/* '| g: gate'*/ +pipe1 pipe2 +say '' +if symbol('err') = 'VAR' & err ^= 0 then do + say 'Errors found in source files - link aborted! RC = 'err + exit err +end +say 'Generating module 'module +'pipe cms cmod' fn texts' | > 'fn' LINK A' +exit rc +error: +say 'Error in REXX detected!' +Say 'Syntax error on line' Sigl':' Sourceline(Sigl) +Say 'Error was:' Errortext(RC) +return rc diff --git a/cmsmvs/mvs.mki b/cmsmvs/mvs.mki new file mode 100644 index 0000000..233f509 --- /dev/null +++ b/cmsmvs/mvs.mki @@ -0,0 +1,151 @@ +# Makefile for the MVS (OS/390 Base) version of UNZIP 5.4 +# Produced for C/C++ V3R2 in OS/390 1.2.0 by Ian E. Gorman, 2 Nov 1998 +# Facilities for compiling and testing were made available by +# OmniMark Technologies Corporation, Ottawa, Canada + +# NOTES +# +# The only tabs in this file are in the first character of each recipe +# line, where they are required by make. +# +# Run this makefile in OpenMVS (OS/390 POSIX) using source files in the +# HFS file system. You can write the load module to either HFS file +# system or to a PDS in the native MVS file system. The PDS must have +# sufficient free space to hold the load module. +# +# To compile to a member of a PDS: +# make +# or +# make unzip.mvs +# +# To compile a test version into the HFS file system: +# make hfs + +# UNZIP options -- MVS, REENTRANT +ZIPOPTS=-DMVS + +# directories + +# generic source code +SRC=.. +SRC_P=$(SRC)/ + +# source code for MVS +CMSMVS=../cmsmvs +CMSMVS_P=$(CMSMVS)/ + +# include files +INCLS=-I$(SRC) -I$(CMSMVS) + +# object files and load modules +BLD_P=../mvs/ + +# Other options + +# Suffixes (E and O must be different) +E= +O=.o + +# Need EXTENDED features for global.c and vmvms.c, so not using c89 +CC=cc +CFLAGS=-D_OPEN_SYS $(ZIPOPTS) $(INCLS) + +LD=cc +LDFLAGS= + +# Files + +# object (TEXT) files +OBJECTS= $(BLD_P)unzip$(O) $(BLD_P)crc32$(O) \ + $(BLD_P)crypt$(O) $(BLD_P)envargs$(O) $(BLD_P)explode$(O) \ + $(BLD_P)extract$(O) $(BLD_P)fileio$(O) $(BLD_P)globals$(O) \ + $(BLD_P)inflate$(O) $(BLD_P)process$(O) $(BLD_P)list$(O) \ + $(BLD_P)match$(O) $(BLD_P)ttyio$(O) $(BLD_P)unreduce$(O) \ + $(BLD_P)unshrink$(O) $(BLD_P)zipinfo$(O) $(BLD_P)vmmvs$(O) + +# Header files +HFILES= $(SRC_P)consts.h $(SRC_P)crypt.h $(SRC_P)ebcdic.h \ + $(SRC_P)globals.h $(SRC_P)inflate.h \ + $(SRC_P)ttyio.h $(SRC_P)unzip.h $(SRC_P)unzpriv.h \ + $(SRC_P)unzvers.h $(SRC_P)zip.h $(CMSMVS_P)vmmvs.h \ + $(CMSMVS_P)vmstat.h + +# Rules + +all: $(BLD_P)unzip.mvs$(E) +hfs: $(BLD_P)unzip$(E) + +# link + +$(BLD_P)unzip.mvs$(E): $(OBJECTS) + $(LD) -o "//INFOZIP.LOAD(UNZIP)" $(LDFLAGS) $^ + echo "tso call \"infozip(unzip)\" \"'\"\"""$$""@""\"\"'\"" > $% + chmod a+x $% + +$(BLD_P)unzip$(E): $(OBJECTS) + $(LD) -o $% $(LDFLAGS) $^ + +# compile + +$(BLD_P)api$(O): $(SRC_P)api.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)api.c + +$(BLD_P)apihelp$(O): $(SRC_P)apihelp.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)apihelp.c + +$(BLD_P)crc32$(O): $(SRC_P)crc32.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)crc32.c + +$(BLD_P)crypt$(O): $(SRC_P)crypt.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)crypt.c + +$(BLD_P)envargs$(O): $(SRC_P)envargs.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)envargs.c + +$(BLD_P)explode$(O): $(SRC_P)explode.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)explode.c + +$(BLD_P)extract$(O): $(SRC_P)extract.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)extract.c + +$(BLD_P)fileio$(O): $(SRC_P)fileio.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)fileio.c + +$(BLD_P)funzip$(O): $(SRC_P)funzip.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)funzip.c + +$(BLD_P)globals$(O): $(SRC_P)globals.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)globals.c + +$(BLD_P)inflate$(O): $(SRC_P)inflate.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)inflate.c + +$(BLD_P)list$(O): $(SRC_P)list.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)list.c + +$(BLD_P)match$(O): $(SRC_P)match.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)match.c + +$(BLD_P)process$(O): $(SRC_P)process.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)process.c + +$(BLD_P)ttyio$(O): $(SRC_P)ttyio.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)ttyio.c + +$(BLD_P)unreduce$(O): $(SRC_P)unreduce.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)unreduce.c + +$(BLD_P)unshrink$(O): $(SRC_P)unshrink.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)unshrink.c + +$(BLD_P)unzip$(O): $(SRC_P)unzip.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)unzip.c + +$(BLD_P)unzipstb$(O): $(SRC_P)unzipstb.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)unzipstb.c + +$(BLD_P)zipinfo$(O): $(SRC_P)zipinfo.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(SRC_P)zipinfo.c + +$(BLD_P)vmmvs$(O): $(CMSMVS_P)vmmvs.c $(HFILES) + $(CC) -c -o $% $(CFLAGS) $(CMSMVS_P)vmmvs.c diff --git a/cmsmvs/unzip.exec b/cmsmvs/unzip.exec new file mode 100644 index 0000000..0b9de97 --- /dev/null +++ b/cmsmvs/unzip.exec @@ -0,0 +1,66 @@ +/***********************************************************************/ +/* */ +/* Front-end EXEC to set up linkage to the C runtime libraries */ +/* before executing a MODULE generated from C code. */ +/* */ +/* Copy this file as an EXEC with a filename matching the C MODULE. */ +/* */ +/* Greg Hartwig (ghartwig@vnet.ibm.com) 7/31/97, 4/24/98. */ +/* */ +/***********************************************************************/ +Address Command +Parse Arg argstring +Parse Source . . myname . + +/* Set output and input character translation so brackets show up */ +'SET OUTPUT AD' 'BA'x +'SET OUTPUT BD' 'BB'x +'SET INPUT BA AD' +'SET INPUT BB BD' + +Call CLIB +If rc<>0 Then Do + Say 'The required C runtime libraries don''t appear to be available.' + Say myname 'can not run.' + Exit 12 +End + +/* Run the command */ +myname argstring +Exit rc + + + + +/* Contents of the CLIB EXEC, modified for RC checking. */ +/* Removed TXTLIB setting. Only LOADLIB needed for execution. */ +CLIB: +/***************************************************/ +/* SET UP LIBRARIES FOR LE for MVS & VM */ +/***************************************************/ +Address COMMAND + +loadlib ='EDCLINK' /* C/370 runtime */ +loadlib ='SCEERUN' /* LE runtime */ + + +theirs=queued() /* old stack contentsM068*/ + 'QUERY LOADLIB ( LIFO' /* old setting M068*/ + LoadlibList='' /* init list M068*/ +rc=0 + Do while queued()^=theirs /* all lines from cmdM068*/ + Parse upper pull 'LOADLIB' '=' Ltemp /* get one line M068*/ + LoadlibList= Ltemp Loadliblist /* was stacked LIFO M068*/ + End /*M068*/ + If loadlibList='NONE' , + Then Do + 'GLOBAL LOADLIB' Loadlib /* enforce what we need */ + End + Else Do + Do xx=1 to Words(loadlib) + If Find(loadliblist,word(loadlib,xx)) = 0 , + then loadliblist = loadliblist word(loadlib,xx) + End + 'GLOBAL LOADLIB' loadliblist /* enforce what we need */ + End +Return diff --git a/cmsmvs/unzip.makefile b/cmsmvs/unzip.makefile new file mode 100644 index 0000000..278d96c --- /dev/null +++ b/cmsmvs/unzip.makefile @@ -0,0 +1,25 @@ +* This is a comment +* this makefile compiles filter UNZIP + +GLOBALS: + long def(VM_CMS) +TEXT: + unzip c + crc32 c + crypt c + envargs c + explode c + extract c + fileio c + globals c + inflate c + list c + match c + process c + ttyio c + unreduce c + unshrink c + zipinfo c + vmmvs c +MODULE: + unzip module diff --git a/cmsmvs/unzmvsc.job b/cmsmvs/unzmvsc.job new file mode 100644 index 0000000..154f9a4 --- /dev/null +++ b/cmsmvs/unzmvsc.job @@ -0,0 +1,130 @@ +//* +//* LE COMPILE FOR UNZIP541. +//* ALL STEPS SHOULD GET COND CODE 0 EXCEPT FOR PLINK.PLKED WHICH GETS 4. +//* +//CBC JCLLIB ORDER=CBC.SCBCPRC +//UNZIP EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(UNZIP)', +// OUTFILE='USERID.UNZIP.OBJ(UNZIP),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//CRC32 EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(CRC32)', +// OUTFILE='USERID.UNZIP.OBJ(CRC32),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//CRYPT EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(CRYPT)', +// OUTFILE='USERID.UNZIP.OBJ(CRYPT),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//ENVARGS EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(ENVARGS)', +// OUTFILE='USERID.UNZIP.OBJ(ENVARGS),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//EXPLODE EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(EXPLODE)', +// OUTFILE='USERID.UNZIP.OBJ(EXPLODE),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//EXTRACT EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(EXTRACT)', +// OUTFILE='USERID.UNZIP.OBJ(EXTRACT),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//FILEIO EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(FILEIO)', +// OUTFILE='USERID.UNZIP.OBJ(FILEIO),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//GLOBALS EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(GLOBALS)', +// OUTFILE='USERID.UNZIP.OBJ(GLOBALS),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//INFLATE EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(INFLATE)', +// OUTFILE='USERID.UNZIP.OBJ(INFLATE),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//LIST EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(LIST)', +// OUTFILE='USERID.UNZIP.OBJ(LIST),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//MATCH EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(MATCH)', +// OUTFILE='USERID.UNZIP.OBJ(MATCH),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//PROCESS EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(PROCESS)', +// OUTFILE='USERID.UNZIP.OBJ(PROCESS),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//TTYIO EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(TTYIO)', +// OUTFILE='USERID.UNZIP.OBJ(TTYIO),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//UNREDUCE EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(UNREDUCE)', +// OUTFILE='USERID.UNZIP.OBJ(UNREDUCE),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//UNSHRINK EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(UNSHRINK)', +// OUTFILE='USERID.UNZIP.OBJ(UNSHRINK),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//ZIPINFO EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(ZIPINFO)', +// OUTFILE='USERID.UNZIP.OBJ(ZIPINFO),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//VMMVS EXEC EDCC,COND=(0,NE),CREGSIZ='0M', +// INFILE='USERID.UNZIP.C(VMMVS)', +// OUTFILE='USERID.UNZIP.OBJ(VMMVS),DISP=SHR', +// CPARM='LONG,NOTERM,LIST,XREF,SOURCE', +// CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT' +//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR +//PLINK EXEC PROC=EDCPL,COND=(4,LT), +// OUTFILE='USERID.UNZIP.LOAD(UNZIP),DISP=SHR', +// PPARM='NONCAL,MAP,MEMORY', +// LPARM='LIST,MAP,XREF' +//SYSPRINT DD SYSOUT=* +//PLKED.SYSIN DD DSN=USERID.UNZIP.OBJ(UNZIP),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(CRC32),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(CRYPT),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(ENVARGS),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(EXPLODE),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(EXTRACT),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(FILEIO),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(GLOBALS),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(INFLATE),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(LIST),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(MATCH),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(PROCESS),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(TTYIO),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(UNREDUCE),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(UNSHRINK),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(ZIPINFO),DISP=SHR +// DD DSN=USERID.UNZIP.OBJ(VMMVS),DISP=SHR +//LKED.SYSLIB DD DISP=SHR,DSN=CEE.SCEELKED diff --git a/cmsmvs/unzvmc.exec b/cmsmvs/unzvmc.exec new file mode 100644 index 0000000..51f1da2 --- /dev/null +++ b/cmsmvs/unzvmc.exec @@ -0,0 +1,56 @@ +/* VMCOMPIL EXEC Unzip compile for VM/CMS */ +/* Author : George Petrov, 11 Apr 1995 */ + +signal on error + +parms = '(long def(VM_CMS)' +/* Add local options */ +/* "TARGET(COMPAT)" is required for V2.2 compiler */ +parms = parms 'TARGET(COMPAT) SOURCE' + + +say 'Compiling UNZIP C...' +'cc unzip c 'parms +say 'Compiling CRC32 C...' +'cc crc32 c 'parms +say 'Compiling CRYPT C...' +'cc crypt c 'parms +say 'Compiling ENVARGS C...' +'cc envargs c 'parms +say 'Compiling EXPLODE C...' +'cc explode c 'parms +say 'Compiling EXTRACT C...' +'cc extract c 'parms +say 'Compiling FILEIO C...' +'cc fileio c 'parms +say 'Compiling GLOBALS C...' +'cc globals c 'parms +say 'Compiling INFLATE C...' +'cc inflate c 'parms +say 'Compiling PROCESS C...' +'cc process c 'parms +say 'Compiling LIST C...' +'cc list c 'parms +say 'Compiling MATCH C...' +'cc match c 'parms +say 'Compiling TTYIO C...' +'cc ttyio c 'parms +say 'Compiling UNREDUCE C...' +'cc unreduce c 'parms +say 'Compiling UNSHRINK C...' +'cc unshrink c 'parms +say 'Compiling ZIPINFO C...' +'cc zipinfo c 'parms +say 'Compiling VMMVS C...' +'cc vmmvs c 'parms + +say 'Linking all files...' +'cmod unzip unzip crc32 crypt envargs explode extract fileio globals', + 'inflate list match process ttyio unreduce unshrink zipinfo vmmvs' +say 'All Done!' +say "To run enter : UNZIP parms" +exit rc + +error: +say 'Error during compilation!' +exit rc diff --git a/cmsmvs/vmmvs.c b/cmsmvs/vmmvs.c new file mode 100644 index 0000000..8416ce8 --- /dev/null +++ b/cmsmvs/vmmvs.c @@ -0,0 +1,683 @@ +/* + Copyright (c) 1990-2005 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 +*/ +/*--------------------------------------------------------------------------- + + vmmvs.c (for both VM/CMS and MVS) + + Contains: vmmvs_open_infile() + open_outfile() + close_outfile() + close_infile() + getVMMVSexfield() + do_wild() + mapattr() + mapname() + checkdir() + check_for_newer() + stat() + version() + + ---------------------------------------------------------------------------*/ + + +#define __VMMVS_C /* identifies this source module */ +#define UNZIP_INTERNAL +#include "unzip.h" + + +/********************************/ +/* Function vmmvs_open_infile() */ +/********************************/ + +FILE *vmmvs_open_infile(__G) + __GDEF +{ + FILE *fzip; + + G.tempfn = NULL; + + fzip = fopen(G.zipfn, FOPR); + +#if 0 + /* Let's try it without the convert for a while -- RG Hartwig */ + + if ((fzip = fopen(G.zipfn,"rb,recfm=fb")) == NULL) { + size_t cnt; + char *buf; + FILE *in, *out; + + if ((buf = (char *)malloc(32768)) == NULL) return NULL; + if ((G.tempfn = tmpnam(NULL)) == NULL) return NULL; + if ((in = fopen(G.zipfn,"rb")) != NULL && + (out = fopen(G.tempfn,"wb,recfm=fb,lrecl=1")) != NULL) { + Trace((stdout,"Converting ZIP file to fixed record format...\n")); + while (!feof(in)) { + cnt = fread(buf,1,32768,in); + if (cnt) fwrite(buf,1,cnt,out); + } + } + else { + free(buf); + fclose(out); + fclose(in); + return NULL; + } + free(buf); + fclose(out); + fclose(in); + + fzip = fopen(G.tempfn,"rb,recfm=fb"); + if (fzip == NULL) return NULL; + + /* Update the G.ziplen value since it might have changed after + the reformatting copy. */ + fseek(fzip,0L,SEEK_SET); + fseek(fzip,0L,SEEK_END); + G.ziplen = ftell(fzip); + } + +#endif + + return fzip; +} + + +/***************************/ +/* Function open_outfile() */ +/***************************/ + +int open_outfile(__G) /* return 1 if fail */ + __GDEF +{ + char type[100]; + char *mode = NULL; +#ifdef MVS + /* Check if the output file already exists and do not overwrite its DCB */ + char basefilename[PATH_MAX], *p; + FILE *exists; + + /* Get the base file name, without any member name */ + strcpy(basefilename, G.filename); + if ((p = strchr(basefilename, '(')) != NULL) { + if (basefilename[0] == '\'') + *p++ = '\''; + *p = '\0'; + } + exists = fopen(basefilename, FOPR); + if (exists) { + if (G.pInfo->textmode) + mode = FOPWTE; /* Text file, existing */ + else + mode = FOPWE; /* Binary file, existing */ + fclose(exists); + } + else /* continued on next line */ +#endif /* MVS */ + if (G.pInfo->textmode) { + if (mode == NULL) + mode = FOPWT; + } else if (G.lrec.extra_field_length > 0 && G.extra_field != NULL) { + unsigned lef_len = (unsigned)(G.lrec.extra_field_length); + uch *lef_buf = G.extra_field; + + while (lef_len > EB_HEADSIZE) { + unsigned eb_id = makeword(&lef_buf[EB_ID]); + unsigned eb_dlen = makeword(&lef_buf[EB_LEN]); + + if (eb_dlen > (lef_len - EB_HEADSIZE)) { + /* Discovered some extra field inconsistency! */ + TTrace((stderr, + "open_outfile: block length %u > rest lef_size %u\n", + eb_dlen, lef_len - EB_HEADSIZE)); + break; + } + + if ((eb_id == EF_VMCMS || eb_id == EF_MVS) && + (getVMMVSexfield(type, lef_buf, eb_dlen) > 0)) { + mode = type; + break; + } + + /* Skip this extra field block */ + lef_buf += (eb_dlen + EB_HEADSIZE); + lef_len -= (eb_dlen + EB_HEADSIZE); + } + } + if (mode == NULL) mode = FOPW; + + Trace((stderr, "Output file='%s' opening with '%s'\n", G.filename, mode)); + if ((G.outfile = fopen(G.filename, mode)) == NULL) { + Info(slide, 0x401, ((char *)slide, "\nerror: cannot create %s\n", + FnFilter1(G.filename))); + Trace((stderr, "error %d: '%s'\n", errno, strerror(errno))); + return 1; + } + return 0; +} /* end function open_outfile() */ + + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) + __GDEF +{ + fclose(G.outfile); +} /* end function close_outfile() */ + + +/***************************/ +/* Function close_infile() */ +/***************************/ + +void close_infile(__G) + __GDEF +{ + fclose(G.zipfd); + + /* If we're working from a temp file, erase it now */ + if (G.tempfn) + remove(G.tempfn); + +} /* end function close_infile() */ + + + +/******************************/ +/* Function getVMMVSexfield() */ +/******************************/ + +extent getVMMVSexfield(type, ef_block, datalen) + char *type; + uch *ef_block; + unsigned datalen; +{ + fldata_t *fdata = (fldata_t *) &ef_block[4]; + + if (datalen < sizeof(fldata_t)) + return 0; + + strcpy(type, "w"); + strcat(type, fdata->__openmode == __TEXT ? "" + :fdata->__openmode == __BINARY ? "b" + :fdata->__openmode == __RECORD ? "b,type=record" + : ""); + strcat(type, ",recfm="); + strcat(type, fdata->__recfmF? "F" + :fdata->__recfmV? "V" + :fdata->__recfmU? "U" + : "?"); + if (fdata->__recfmBlk) strcat(type, "B"); + if (fdata->__recfmS) strcat(type, "S"); + if (fdata->__recfmASA) strcat(type, "A"); + if (fdata->__recfmM) strcat(type, "M"); + sprintf(type+strlen(type), ",lrecl=%ld", fdata->__recfmV + ? fdata->__maxreclen+4 + : fdata->__maxreclen); +#ifdef VM_CMS + /* For CMS, use blocksize for FB files only */ + if (fdata->__recfmBlk) + sprintf(type+strlen(type), ",blksize=%ld", fdata->__blksize); +#else + /* For MVS, always use blocksize */ + sprintf(type+strlen(type), ",blksize=%ld", fdata->__blksize); +#endif + + return strlen(type); +} /* end function getVMMVSexfield() */ + + + +#ifndef SFX + +/**********************/ +/* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ +/**********************/ + +char *do_wild(__G__ wld) + __GDEF + ZCONST char *wld; /* only used first time on a given dir */ +{ + static int First = 0; + static char filename[256]; + + if (First == 0) { + First = 1; + strncpy(filename, wld, sizeof(filename)); + filename[sizeof(filename)-1] = '\0'; + return filename; + } + else + return (char *)NULL; + +} /* end function do_wild() */ + +#endif /* !SFX */ + + + +/************************/ +/* Function mapattr() */ +/************************/ + +int mapattr(__G) + __GDEF +{ + return 0; +} + +/************************/ +/* Function mapname() */ +/************************/ + +int mapname(__G__ renamed) + __GDEF + int renamed; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - caution (truncated filename) + * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) + * MPN_ERR_SKIP - error -> skip entry + * MPN_ERR_TOOLONG - error -> path is too long + * MPN_NOMEM - error (memory allocation failed) -> skip entry + * [also MPN_VOL_LABEL, MPN_CREATED_DIR] + */ +{ + char newname[FILNAMSIZ], *lbar; +#ifdef MVS + char *pmember; +#endif + int name_changed = MPN_OK; + + if (G.pInfo->vollabel) + return MPN_VOL_LABEL; /* can't set disk volume labels in CMS_MVS */ + +#ifdef MVS + /* Remove bad characters for MVS from the filename */ + while ((lbar = strpbrk(G.filename, "_+-")) != NULL) { + /* Must use memmove() here because data overlaps. */ + /* strcpy() gives undefined behavior in this case. */ + memmove(lbar, lbar+1, strlen(lbar)); + name_changed = MPN_INF_TRUNC; + } +#endif + + /* Remove bad characters for MVS/CMS from the filename */ + while ((lbar = strpbrk(G.filename, "()")) != NULL) { + memmove(lbar, lbar+1, strlen(lbar)); + name_changed = MPN_INF_TRUNC; + } + +#ifdef VM_CMS + if ((lbar = strrchr(G.filename, '/')) != NULL) { + strcpy(newname, lbar+1); + Trace((stderr, "File '%s' renamed to '%s'\n", G.filename, newname)); + strcpy(G.filename, newname); + name_changed = MPN_INF_TRUNC; + } +#else /* MVS */ + if ((pmember = strrchr(G.filename, '/')) == NULL) + pmember = G.filename; + else + pmember++; + + /* search for extension in file name */ + if ((lbar = strrchr(pmember, '.')) != NULL) { + *lbar++ = '\0'; + strcpy(newname, pmember); + strcpy(pmember, lbar); + strcat(pmember, "("); + strcat(pmember, newname); + strcat(pmember, ")"); + } + + /* Remove all 'internal' dots '.', to prevent false consideration as + * MVS path delimiters! */ + while ((lbar = strrchr(G.filename, '.')) != NULL) { + memmove(lbar, lbar+1, strlen(lbar)); + name_changed = MPN_INF_TRUNC; + } + + /* Finally, convert path delimiters from internal '/' to external '.' */ + while ((lbar = strchr(G.filename, '/')) != NULL) + *lbar = '.'; +#endif /* ?VM_CMS */ + +#ifndef MVS + if ((lbar = strchr(G.filename, '.')) == NULL) { + printf("WARNING: file '%s' has no extension - renamed to '%s.NONAME'\n"\ + ,G.filename, G.filename); + strcat(G.filename, ".NONAME"); + name_changed = MPN_INF_TRUNC; + } +#endif + checkdir(__G__ G.filename, GETPATH); + + return name_changed; + +} /* end function mapname() */ + + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename + * MPN_INF_SKIP - path doesn't exist, not allowed to create + * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path + * exists and is not a directory, but is supposed to be + * MPN_ERR_TOOLONG - path is too long + * MPN_NOMEM - can't allocate memory for filename buffers + */ +{ + static int rootlen = 0; /* length of rootpath */ + static char *rootpath; /* user's "extract-to" directory */ + +# define FN_MASK 7 +# define FUNCTION (flag & FN_MASK) + + +/*--------------------------------------------------------------------------- + ROOT: if appropriate, store the path in rootpath and create it if neces- + sary; else assume it's a zipfile member and return. This path segment + gets used in extracting all members from every zipfile specified on the + command line. Note that under OS/2 and MS-DOS, if a candidate extract-to + directory specification includes a drive letter (leading "x:"), it is + treated just as if it had a trailing '/'--that is, one directory level + will be created if the path doesn't exist, unless this is otherwise pro- + hibited (e.g., freshening). + ---------------------------------------------------------------------------*/ + +#if (!defined(SFX) || defined(SFX_EXDIR)) + if (FUNCTION == ROOT) { + Trace((stderr, "initializing root path to [%s]\n", + FnFilter1(pathcomp))); + if (pathcomp == (char *)NULL) { + rootlen = 0; + } + else if ((rootlen = strlen(pathcomp)) > 0) { + if ((rootpath = (char *)malloc(rootlen+1)) == NULL) { + rootlen = 0; + return MPN_NOMEM; + } + strcpy(rootpath, pathcomp); + Trace((stderr, "rootpath now = [%s]\n", rootpath)); + } + return MPN_OK; + } +#endif /* !SFX || SFX_EXDIR */ + +/*--------------------------------------------------------------------------- + GETPATH: copy full path to the string pointed at by pathcomp, and free + buildpath. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == GETPATH) { + if (rootlen > 0) { +#ifdef VM_CMS /* put the exdir after the filename */ + strcat(pathcomp, "."); /* used as minidisk to be save on */ + strcat(pathcomp, rootpath); +#else /* MVS */ + char newfilename[PATH_MAX]; + char *start_fname; + int quoted = 0; + + strcpy(newfilename, rootpath); + if (newfilename[0] == '\'') { + quoted = strlen(newfilename) - 1; + if (newfilename[quoted] == '\'') + newfilename[quoted] = '\0'; + else + quoted = 0; + } + if (strchr(pathcomp, '(') == NULL) { + if ((start_fname = strrchr(pathcomp, '.')) == NULL) { + start_fname = pathcomp; + } + else { + *start_fname++ = '\0'; + strcat(newfilename, "."); + strcat(newfilename, pathcomp); + } + strcat(newfilename, "("); + strcat(newfilename, start_fname); + strcat(newfilename, ")"); + } + else { + strcat(newfilename, "."); + strcat(newfilename, pathcomp); + } + if (quoted) + strcat(newfilename, "'"); + Trace((stdout, "new dataset : %s\n", newfilename)); + strcpy(pathcomp, newfilename); +#endif /* ?VM_CMS */ + } + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + END: free rootpath, immediately prior to program exit. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == END) { + Trace((stderr, "freeing rootpath\n")); + if (rootlen > 0) { + free(rootpath); + rootlen = 0; + } + return MPN_OK; + } + + return MPN_INVALID; /* should never reach */ + +} /* end function checkdir() */ + + + + +/******************************/ +/* Function check_for_newer() */ /* used for overwriting/freshening/updating */ +/******************************/ + +int check_for_newer(__G__ filename) /* return 1 if existing file is newer */ + __GDEF /* or equal; 0 if older; -1 if doesn't */ + char *filename; /* exist yet */ +{ + FILE *stream; + + if ((stream = fopen(filename, FOPR)) != NULL) { + fclose(stream); + /* File exists, assume it is "newer" than archive entry. */ + return EXISTS_AND_NEWER; + } + /* File does not exist. */ + return DOES_NOT_EXIST; +} /* end function check_for_newer() */ + + +/*********************/ +/* Function stat() */ +/*********************/ + +int stat(const char *path, struct stat *buf) +{ + FILE *fp; + char fname[PATH_MAX]; + time_t ltime; + + if ((fp = fopen(path, FOPR)) != NULL) { + fldata_t fdata; + if (fldata( fp, fname, &fdata ) == 0) { + buf->st_dev = fdata.__device; + buf->st_mode = *(short *)(&fdata); + } + + /* Determine file size by seeking to EOF */ + fseek(fp,0L,SEEK_END); + buf->st_size = ftell(fp); + fclose(fp); + + /* set time fields in stat buf to current time. */ + time(<ime); + buf->st_atime = + buf->st_mtime = + buf->st_ctime = ltime; + + /* File exists, return success */ + return 0; + } + return 1; +} + + + +#ifdef STAND_ALONE +/***************************/ +/* Function main_vmmvs() */ +/***************************/ + +/* This function is called as main() to parse arguments */ +/* into argc and argv. This is required for stand-alone */ +/* execution. This calls the "real" main() when done. */ + +int MAIN_VMMVS(void) + { + int argc=0; + char *argv[50]; + + int iArgLen; + char argstr[256]; + char **pEPLIST, *pCmdStart, *pArgStart, *pArgEnd; + + /* Get address of extended parameter list from S/370 Register 0 */ + pEPLIST = (char **)__xregs(0); + + /* Null-terminate the argument string */ + pCmdStart = *(pEPLIST+0); + pArgStart = *(pEPLIST+1); + pArgEnd = *(pEPLIST+2); + iArgLen = pArgEnd - pCmdStart + 1; + + /* Make a copy of the command string */ + memcpy(argstr, pCmdStart, iArgLen); + argstr[iArgLen] = '\0'; /* Null-terminate */ + + /* Store first token (cmd) */ + argv[argc++] = strtok(argstr, " "); + + /* Store the rest (args) */ + while (argv[argc-1]) + argv[argc++] = strtok(NULL, " "); + argc--; /* Back off last NULL entry */ + + /* Call "real" main() function */ + return MAIN(argc, argv); +} +#endif /* STAND_ALONE */ + + + +#ifndef SFX + +/************************/ +/* Function version() */ +/************************/ + +void version(__G) + __GDEF +{ + int len; + char liblvlmsg [50+1]; + char *compiler = "?"; + char *platform = "?"; + char complevel[64]; + + /* Map the runtime library level information */ + union { + unsigned int iVRM; + struct { + unsigned int pd:4; /* Product designation */ + unsigned int vv:4; /* Version */ + unsigned int rr:8; /* Release */ + unsigned int mm:16; /* Modification level */ + } xVRM; + } VRM; + + + /* Break down the runtime library level */ + VRM.iVRM = __librel(); + sprintf(liblvlmsg, "Using runtime library level %s V%dR%dM%d", + (VRM.xVRM.pd==1 ? "LE" : "CE"), + VRM.xVRM.vv, VRM.xVRM.rr, VRM.xVRM.mm); + /* Note: LE = Language Environment, CE = Common Env. (C/370). */ + /* This refers ONLY to the current runtimes, not the compiler. */ + + +#ifdef VM_CMS + platform = "VM/CMS"; + #ifdef __IBMC__ + compiler = "IBM C"; + #else + compiler = "C/370"; + #endif +#endif + +#ifdef MVS + platform = "MVS"; + #ifdef __IBMC__ + compiler = "IBM C/C++"; + #else + compiler = "C/370"; + #endif +#endif + +#ifdef __COMPILER_VER__ + VRM.iVRM = __COMPILER_VER__; + sprintf(complevel," V%dR%dM%d", + VRM.xVRM.vv, VRM.xVRM.rr, VRM.xVRM.mm); +#else +#ifdef __IBMC__ + sprintf(complevel," V%dR%d", __IBMC__ / 100, (__IBMC__ % 100)/10); +#else + complevel[0] = '\0'; +#endif +#endif + + + /* Output is in the form "Compiled with %s%s for %s%s%s%s." */ + len = sprintf((char *)slide, LoadFarString(CompiledWith), + + /* Add compiler name and level */ + compiler, complevel, + + /* Add compile environment */ + platform, + + /* Add timestamp */ +#ifdef __DATE__ + " on " __DATE__ +#ifdef __TIME__ + " at " __TIME__ +#endif +#endif + ".\n", "", + liblvlmsg + ); + + (*G.message)((zvoid *)&G, slide, (ulg)len, 0); + +} /* end function version() */ + +#endif /* !SFX */ diff --git a/cmsmvs/vmmvs.h b/cmsmvs/vmmvs.h new file mode 100644 index 0000000..6e616da --- /dev/null +++ b/cmsmvs/vmmvs.h @@ -0,0 +1,96 @@ +/* + Copyright (c) 1990-2008 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2007-Mar-04 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 +*/ +/* vmmvs.h: include file for both VM/CMS and MVS ports of UnZip */ +#ifndef __vmmvs_h /* prevent multiple inclusions */ +#define __vmmvs_h + +#ifndef NULL +# define NULL (zvoid *)0 +#endif + +#ifdef MVS +# define _POSIX_SOURCE /* tell MVS we want full definitions */ +# define NO_STRNICMP /* MVS has no strnicmp() */ +# include + /* MVS complains if a function has the same name as a csect. */ +# if defined(__UNZIP_C) +# pragma csect(STATIC,"unzip_s") +# elif defined(__CRC32_C) +# pragma csect(STATIC,"crc32_s") +# elif defined(__ENVARGS_C) +# pragma csect(STATIC,"envarg_s") +# elif defined(__EXPLODE_C) +# pragma csect(STATIC,"explod_s") +# elif defined(__INFLATE_C) +# pragma csect(STATIC,"inflat_s") +# elif defined(__MATCH_C) +# pragma csect(STATIC,"match_s") +# elif defined(__UNREDUCE_C) +# pragma csect(STATIC,"unredu_s") +# elif defined(__UNSHRINK_C) +# pragma csect(STATIC,"unshri_s") +# elif defined(__ZIPINFO_C) +# pragma csect(STATIC,"zipinf_s") +# endif +#endif /* MVS */ + +#include /* the usual non-BSD time functions */ +#ifdef VM_CMS +# include "vmstat.h" +#endif +#ifdef MVS +# include +#endif + +#define PASSWD_FROM_STDIN + /* Kludge until we know how to open a non-echo tty channel */ + +#define EBCDIC +/* In the context of Info-ZIP, a portable "text" mode file implies the use of + an ASCII-compatible (ISO 8859-1, or other extended ASCII) code page. */ + +#ifdef MORE +# undef MORE +#endif + +/* Workarounds for missing RTL functionality */ +#define isatty(t) 1 + +#ifdef UNZIP /* definitions for UNZIP */ + +#define INBUFSIZ 8192 + +#define USE_STRM_INPUT +#define USE_FWRITE + +#define PATH_MAX 128 + +#ifndef QUERY_TRNEWLN +# define QUERY_TRNEWLN /* terminate interaction queries with '\n' */ +#endif + +#ifndef DATE_FORMAT +# define DATE_FORMAT DF_MDY +#endif +#define lenEOL 1 +/* The use of "ebcdic[LF]" is not reliable; VM/CMS C/370 uses the + * EBCDIC specific "NL" ('NewLine') control character (and not the EBCDIC + * equivalent of the ASCII "LF" ('LineFeed')) as line terminator! + * To work around this problem, we explicitely emit the C compiler's native + * '\n' line terminator. + */ +#if 0 +#define PutNativeEOL *q++ = native(LF); +#else +#define PutNativeEOL *q++ = '\n'; +#endif + +#endif /* UNZIP */ + +#endif /* !__vmmvs_h */ diff --git a/cmsmvs/vmstat.h b/cmsmvs/vmstat.h new file mode 100644 index 0000000..fb2f3d9 --- /dev/null +++ b/cmsmvs/vmstat.h @@ -0,0 +1,57 @@ +/* + 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 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 +*/ +#ifndef __vmstat_h +#define __vmstat_h + +/* stat.h definitions */ + +#ifndef _INO_T_DEFINED +typedef unsigned short ino_t; /* i-node number (not used on DOS) */ +#define _INO_T_DEFINED +#endif + +#ifndef _DEV_T_DEFINED +typedef short dev_t; /* device code */ +#define _DEV_T_DEFINED +#endif + +#ifndef _OFF_T_DEFINED +typedef long off_t; /* file offset value */ +#define _OFF_T_DEFINED +#endif + +#ifndef _STAT_DEFINED +struct stat { + dev_t st_dev; + ino_t st_ino; + short st_mode; + short st_nlink; + int st_uid; + int st_gid; + off_t st_size; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +}; +#define _STAT_DEFINED +#endif + +int stat(const char *path, struct stat *buf); +int fstat(int fd, struct stat *buf); + +#define S_IFMT 0xFFFF +#define _FLDATA(m) (*(fldata_t *) &m) +#define S_ISDIR(m) (_FLDATA(m).__dsorgPDSdir) +#define S_ISREG(m) (_FLDATA(m).__dsorgPO | \ + _FLDATA(m).__dsorgPDSmem | \ + _FLDATA(m).__dsorgPS) +#define S_ISBLK(m) (_FLDATA(m).__recfmBlk) +#define S_ISMEM(m) (_FLDATA(m).__dsorgMem) + +#endif /* __vmstat_h */ diff --git a/cmsmvs/zipinfo.exec b/cmsmvs/zipinfo.exec new file mode 100644 index 0000000..0b9de97 --- /dev/null +++ b/cmsmvs/zipinfo.exec @@ -0,0 +1,66 @@ +/***********************************************************************/ +/* */ +/* Front-end EXEC to set up linkage to the C runtime libraries */ +/* before executing a MODULE generated from C code. */ +/* */ +/* Copy this file as an EXEC with a filename matching the C MODULE. */ +/* */ +/* Greg Hartwig (ghartwig@vnet.ibm.com) 7/31/97, 4/24/98. */ +/* */ +/***********************************************************************/ +Address Command +Parse Arg argstring +Parse Source . . myname . + +/* Set output and input character translation so brackets show up */ +'SET OUTPUT AD' 'BA'x +'SET OUTPUT BD' 'BB'x +'SET INPUT BA AD' +'SET INPUT BB BD' + +Call CLIB +If rc<>0 Then Do + Say 'The required C runtime libraries don''t appear to be available.' + Say myname 'can not run.' + Exit 12 +End + +/* Run the command */ +myname argstring +Exit rc + + + + +/* Contents of the CLIB EXEC, modified for RC checking. */ +/* Removed TXTLIB setting. Only LOADLIB needed for execution. */ +CLIB: +/***************************************************/ +/* SET UP LIBRARIES FOR LE for MVS & VM */ +/***************************************************/ +Address COMMAND + +loadlib ='EDCLINK' /* C/370 runtime */ +loadlib ='SCEERUN' /* LE runtime */ + + +theirs=queued() /* old stack contentsM068*/ + 'QUERY LOADLIB ( LIFO' /* old setting M068*/ + LoadlibList='' /* init list M068*/ +rc=0 + Do while queued()^=theirs /* all lines from cmdM068*/ + Parse upper pull 'LOADLIB' '=' Ltemp /* get one line M068*/ + LoadlibList= Ltemp Loadliblist /* was stacked LIFO M068*/ + End /*M068*/ + If loadlibList='NONE' , + Then Do + 'GLOBAL LOADLIB' Loadlib /* enforce what we need */ + End + Else Do + Do xx=1 to Words(loadlib) + If Find(loadliblist,word(loadlib,xx)) = 0 , + then loadliblist = loadliblist word(loadlib,xx) + End + 'GLOBAL LOADLIB' loadliblist /* enforce what we need */ + End +Return diff --git a/consts.h b/consts.h new file mode 100644 index 0000000..5dfc0a0 --- /dev/null +++ b/consts.h @@ -0,0 +1,54 @@ +/* + 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 +*/ +/*--------------------------------------------------------------------------- + + consts.h + + This file contains global, initialized variables that never change. It is + included by unzip.c and windll/windll.c. + + ---------------------------------------------------------------------------*/ + + +/* And'ing with mask_bits[n] masks the lower n bits */ +ZCONST unsigned near mask_bits[17] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + +ZCONST char Far VersionDate[] = UZ_VERSION_DATE; /* now defined in unzvers.h */ + +#ifndef SFX + ZCONST char Far EndSigMsg[] = + "\nnote: didn't find end-of-central-dir signature at end of central dir.\n"; +#endif + +ZCONST char Far CentSigMsg[] = + "error: expected central file header signature not found (file #%lu).\n"; +ZCONST char Far SeekMsg[] = + "error [%s]: attempt to seek before beginning of zipfile\n%s"; +ZCONST char Far FilenameNotMatched[] = "caution: filename not matched: %s\n"; +ZCONST char Far ExclFilenameNotMatched[] = + "caution: excluded filename not matched: %s\n"; + +#ifdef VMS + ZCONST char Far ReportMsg[] = "\ + (please check that you have transferred or created the zipfile in the\n\ + appropriate BINARY mode--this includes ftp, Kermit, AND unzip'd zipfiles)\n"; +#else + ZCONST char Far ReportMsg[] = "\ + (please check that you have transferred or created the zipfile in the\n\ + appropriate BINARY mode and that you have compiled UnZip properly)\n"; +#endif + +#ifndef SFX + ZCONST char Far Zipnfo[] = "zipinfo"; + ZCONST char Far CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n"; +#endif diff --git a/crc32.c b/crc32.c new file mode 100644 index 0000000..02f504d --- /dev/null +++ b/crc32.c @@ -0,0 +1,732 @@ +/* + Copyright (c) 1990-2007 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2005-Feb-10 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html +*/ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results about a factor + * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* $Id: crc32.c,v 2.0 2007/01/07 05:20:36 spc Exp $ */ + +#define __CRC32_C /* identifies this source module */ + +#include "zip.h" + +#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) + +#ifndef ZCONST +# define ZCONST const +#endif + +#include "crc32.h" + +/* When only the table of precomputed CRC values is needed, only the basic + system-independent table containing 256 entries is created; any support + for "unfolding" optimization is disabled. + */ +#if (defined(USE_ZLIB) || defined(CRC_TABLE_ONLY)) +# ifdef IZ_CRCOPTIM_UNFOLDTBL +# undef IZ_CRCOPTIM_UNFOLDTBL +# endif +#endif /* (USE_ZLIB || CRC_TABLE_ONLY) */ + +#if defined(IZ_CRCOPTIM_UNFOLDTBL) +# define CRC_TBLS 4 +#else +# define CRC_TBLS 1 +#endif + + +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first (or only) table is simply the CRC of all possible eight bit values. + This is all the information needed to generate CRC's on data a byte-at-a-time + for all combinations of CRC register values and incoming bytes. + The remaining 3 tables (if IZ_CRCOPTIM_UNFOLDTBL is enabled) allow for + word-at-a-time CRC calculation, where a word is four bytes. +*/ + +#ifdef DYNAMIC_CRC_TABLE + +/* ========================================================================= + * Make the crc table. This function is needed only if you want to compute + * the table dynamically. + */ + +local void make_crc_table OF((void)); + +#if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT)) + error: Dynamic allocation of CRC table not safe with reentrant code. +#endif /* DYNALLOC_CRCTAB && REENTRANT */ + +#ifdef DYNALLOC_CRCTAB + local ulg near *crc_table = NULL; +# if 0 /* not used, since sizeof("near *") <= sizeof(int) */ + /* Use this section when access to a "local int" is faster than access to + a "local pointer" (e.g.: i86 16bit code with far pointers). */ + local int crc_table_empty = 1; +# define CRC_TABLE_IS_EMPTY (crc_table_empty != 0) +# define MARK_CRCTAB_FILLED crc_table_empty = 0 +# define MARK_CRCTAB_EMPTY crc_table_empty = 1 +# else + /* Use this section on systems where the size of pointers and ints is + equal (e.g.: all 32bit systems). */ +# define CRC_TABLE_IS_EMPTY (crc_table == NULL) +# define MARK_CRCTAB_FILLED crc_table = crctab_p +# define MARK_CRCTAB_EMPTY crc_table = NULL +# endif +#else /* !DYNALLOC_CRCTAB */ + local ulg near crc_table[CRC_TBLS*256]; + local int crc_table_empty = 1; +# define CRC_TABLE_IS_EMPTY (crc_table_empty != 0) +# define MARK_CRCTAB_FILLED crc_table_empty = 0 +#endif /* ?DYNALLOC_CRCTAB */ + + +local void make_crc_table() +{ + ulg c; /* crc shift register */ + int n; /* counter for all possible eight bit values */ + int k; /* byte being shifted into crc apparatus */ +#ifdef DYNALLOC_CRCTAB + ulg near *crctab_p; /* temporary pointer to allocated crc_table area */ +#else /* !DYNALLOC_CRCTAB */ +# define crctab_p crc_table +#endif /* DYNALLOC_CRCTAB */ + +#ifdef COMPUTE_XOR_PATTERN + /* This piece of code has been left here to explain how the XOR pattern + * used in the creation of the crc_table values can be recomputed. + * For production versions of this function, it is more efficient to + * supply the resultant pattern at compile time. + */ + ulg xor; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static ZCONST uch p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320L) */ + xor = 0L; + for (n = 0; n < sizeof(p)/sizeof(uch); n++) + xor |= 1L << (31 - p[n]); +#else +# define xor 0xedb88320L +#endif + +#ifdef DYNALLOC_CRCTAB + crctab_p = (ulg near *) nearmalloc (CRC_TBLS*256*sizeof(ulg)); + if (crctab_p == NULL) { + ziperr(ZE_MEM, "crc_table allocation"); + } +#endif /* DYNALLOC_CRCTAB */ + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (ulg)n; + for (k = 8; k; k--) + c = c & 1 ? xor ^ (c >> 1) : c >> 1; + crctab_p[n] = REV_BE(c); + } + +#ifdef IZ_CRCOPTIM_UNFOLDTBL + /* generate crc for each value followed by one, two, and three zeros */ + for (n = 0; n < 256; n++) { + c = crctab_p[n]; + for (k = 1; k < 4; k++) { + c = CRC32(c, 0, crctab_p); + crctab_p[k*256+n] = c; + } + } +#endif /* IZ_CRCOPTIM_UNFOLDTBL */ + + MARK_CRCTAB_FILLED; +} + +#else /* !DYNAMIC_CRC_TABLE */ + +#ifdef DYNALLOC_CRCTAB + error: Inconsistent flags, DYNALLOC_CRCTAB without DYNAMIC_CRC_TABLE. +#endif + +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +local ZCONST ulg near crc_table[CRC_TBLS*256] = { +# ifdef IZ_CRC_BE_OPTIMIZ + 0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L, + 0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L, + 0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L, + 0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L, + 0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L, + 0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L, + 0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L, + 0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L, + 0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L, + 0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L, + 0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL, + 0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L, + 0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L, + 0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L, + 0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L, + 0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L, + 0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL, + 0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L, + 0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL, + 0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L, + 0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L, + 0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L, + 0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL, + 0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL, + 0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L, + 0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL, + 0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L, + 0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL, + 0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L, + 0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L, + 0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L, + 0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L, + 0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L, + 0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL, + 0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L, + 0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L, + 0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L, + 0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L, + 0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L, + 0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L, + 0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L, + 0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L, + 0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL, + 0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L, + 0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L, + 0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L, + 0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L, + 0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L, + 0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL, + 0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L, + 0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL, + 0x8def022dL +# ifdef IZ_CRCOPTIM_UNFOLDTBL + , + 0x00000000L, 0x41311b19L, 0x82623632L, 0xc3532d2bL, 0x04c56c64L, + 0x45f4777dL, 0x86a75a56L, 0xc796414fL, 0x088ad9c8L, 0x49bbc2d1L, + 0x8ae8effaL, 0xcbd9f4e3L, 0x0c4fb5acL, 0x4d7eaeb5L, 0x8e2d839eL, + 0xcf1c9887L, 0x5112c24aL, 0x1023d953L, 0xd370f478L, 0x9241ef61L, + 0x55d7ae2eL, 0x14e6b537L, 0xd7b5981cL, 0x96848305L, 0x59981b82L, + 0x18a9009bL, 0xdbfa2db0L, 0x9acb36a9L, 0x5d5d77e6L, 0x1c6c6cffL, + 0xdf3f41d4L, 0x9e0e5acdL, 0xa2248495L, 0xe3159f8cL, 0x2046b2a7L, + 0x6177a9beL, 0xa6e1e8f1L, 0xe7d0f3e8L, 0x2483dec3L, 0x65b2c5daL, + 0xaaae5d5dL, 0xeb9f4644L, 0x28cc6b6fL, 0x69fd7076L, 0xae6b3139L, + 0xef5a2a20L, 0x2c09070bL, 0x6d381c12L, 0xf33646dfL, 0xb2075dc6L, + 0x715470edL, 0x30656bf4L, 0xf7f32abbL, 0xb6c231a2L, 0x75911c89L, + 0x34a00790L, 0xfbbc9f17L, 0xba8d840eL, 0x79dea925L, 0x38efb23cL, + 0xff79f373L, 0xbe48e86aL, 0x7d1bc541L, 0x3c2ade58L, 0x054f79f0L, + 0x447e62e9L, 0x872d4fc2L, 0xc61c54dbL, 0x018a1594L, 0x40bb0e8dL, + 0x83e823a6L, 0xc2d938bfL, 0x0dc5a038L, 0x4cf4bb21L, 0x8fa7960aL, + 0xce968d13L, 0x0900cc5cL, 0x4831d745L, 0x8b62fa6eL, 0xca53e177L, + 0x545dbbbaL, 0x156ca0a3L, 0xd63f8d88L, 0x970e9691L, 0x5098d7deL, + 0x11a9ccc7L, 0xd2fae1ecL, 0x93cbfaf5L, 0x5cd76272L, 0x1de6796bL, + 0xdeb55440L, 0x9f844f59L, 0x58120e16L, 0x1923150fL, 0xda703824L, + 0x9b41233dL, 0xa76bfd65L, 0xe65ae67cL, 0x2509cb57L, 0x6438d04eL, + 0xa3ae9101L, 0xe29f8a18L, 0x21cca733L, 0x60fdbc2aL, 0xafe124adL, + 0xeed03fb4L, 0x2d83129fL, 0x6cb20986L, 0xab2448c9L, 0xea1553d0L, + 0x29467efbL, 0x687765e2L, 0xf6793f2fL, 0xb7482436L, 0x741b091dL, + 0x352a1204L, 0xf2bc534bL, 0xb38d4852L, 0x70de6579L, 0x31ef7e60L, + 0xfef3e6e7L, 0xbfc2fdfeL, 0x7c91d0d5L, 0x3da0cbccL, 0xfa368a83L, + 0xbb07919aL, 0x7854bcb1L, 0x3965a7a8L, 0x4b98833bL, 0x0aa99822L, + 0xc9fab509L, 0x88cbae10L, 0x4f5def5fL, 0x0e6cf446L, 0xcd3fd96dL, + 0x8c0ec274L, 0x43125af3L, 0x022341eaL, 0xc1706cc1L, 0x804177d8L, + 0x47d73697L, 0x06e62d8eL, 0xc5b500a5L, 0x84841bbcL, 0x1a8a4171L, + 0x5bbb5a68L, 0x98e87743L, 0xd9d96c5aL, 0x1e4f2d15L, 0x5f7e360cL, + 0x9c2d1b27L, 0xdd1c003eL, 0x120098b9L, 0x533183a0L, 0x9062ae8bL, + 0xd153b592L, 0x16c5f4ddL, 0x57f4efc4L, 0x94a7c2efL, 0xd596d9f6L, + 0xe9bc07aeL, 0xa88d1cb7L, 0x6bde319cL, 0x2aef2a85L, 0xed796bcaL, + 0xac4870d3L, 0x6f1b5df8L, 0x2e2a46e1L, 0xe136de66L, 0xa007c57fL, + 0x6354e854L, 0x2265f34dL, 0xe5f3b202L, 0xa4c2a91bL, 0x67918430L, + 0x26a09f29L, 0xb8aec5e4L, 0xf99fdefdL, 0x3accf3d6L, 0x7bfde8cfL, + 0xbc6ba980L, 0xfd5ab299L, 0x3e099fb2L, 0x7f3884abL, 0xb0241c2cL, + 0xf1150735L, 0x32462a1eL, 0x73773107L, 0xb4e17048L, 0xf5d06b51L, + 0x3683467aL, 0x77b25d63L, 0x4ed7facbL, 0x0fe6e1d2L, 0xccb5ccf9L, + 0x8d84d7e0L, 0x4a1296afL, 0x0b238db6L, 0xc870a09dL, 0x8941bb84L, + 0x465d2303L, 0x076c381aL, 0xc43f1531L, 0x850e0e28L, 0x42984f67L, + 0x03a9547eL, 0xc0fa7955L, 0x81cb624cL, 0x1fc53881L, 0x5ef42398L, + 0x9da70eb3L, 0xdc9615aaL, 0x1b0054e5L, 0x5a314ffcL, 0x996262d7L, + 0xd85379ceL, 0x174fe149L, 0x567efa50L, 0x952dd77bL, 0xd41ccc62L, + 0x138a8d2dL, 0x52bb9634L, 0x91e8bb1fL, 0xd0d9a006L, 0xecf37e5eL, + 0xadc26547L, 0x6e91486cL, 0x2fa05375L, 0xe836123aL, 0xa9070923L, + 0x6a542408L, 0x2b653f11L, 0xe479a796L, 0xa548bc8fL, 0x661b91a4L, + 0x272a8abdL, 0xe0bccbf2L, 0xa18dd0ebL, 0x62defdc0L, 0x23efe6d9L, + 0xbde1bc14L, 0xfcd0a70dL, 0x3f838a26L, 0x7eb2913fL, 0xb924d070L, + 0xf815cb69L, 0x3b46e642L, 0x7a77fd5bL, 0xb56b65dcL, 0xf45a7ec5L, + 0x370953eeL, 0x763848f7L, 0xb1ae09b8L, 0xf09f12a1L, 0x33cc3f8aL, + 0x72fd2493L + , + 0x00000000L, 0x376ac201L, 0x6ed48403L, 0x59be4602L, 0xdca80907L, + 0xebc2cb06L, 0xb27c8d04L, 0x85164f05L, 0xb851130eL, 0x8f3bd10fL, + 0xd685970dL, 0xe1ef550cL, 0x64f91a09L, 0x5393d808L, 0x0a2d9e0aL, + 0x3d475c0bL, 0x70a3261cL, 0x47c9e41dL, 0x1e77a21fL, 0x291d601eL, + 0xac0b2f1bL, 0x9b61ed1aL, 0xc2dfab18L, 0xf5b56919L, 0xc8f23512L, + 0xff98f713L, 0xa626b111L, 0x914c7310L, 0x145a3c15L, 0x2330fe14L, + 0x7a8eb816L, 0x4de47a17L, 0xe0464d38L, 0xd72c8f39L, 0x8e92c93bL, + 0xb9f80b3aL, 0x3cee443fL, 0x0b84863eL, 0x523ac03cL, 0x6550023dL, + 0x58175e36L, 0x6f7d9c37L, 0x36c3da35L, 0x01a91834L, 0x84bf5731L, + 0xb3d59530L, 0xea6bd332L, 0xdd011133L, 0x90e56b24L, 0xa78fa925L, + 0xfe31ef27L, 0xc95b2d26L, 0x4c4d6223L, 0x7b27a022L, 0x2299e620L, + 0x15f32421L, 0x28b4782aL, 0x1fdeba2bL, 0x4660fc29L, 0x710a3e28L, + 0xf41c712dL, 0xc376b32cL, 0x9ac8f52eL, 0xada2372fL, 0xc08d9a70L, + 0xf7e75871L, 0xae591e73L, 0x9933dc72L, 0x1c259377L, 0x2b4f5176L, + 0x72f11774L, 0x459bd575L, 0x78dc897eL, 0x4fb64b7fL, 0x16080d7dL, + 0x2162cf7cL, 0xa4748079L, 0x931e4278L, 0xcaa0047aL, 0xfdcac67bL, + 0xb02ebc6cL, 0x87447e6dL, 0xdefa386fL, 0xe990fa6eL, 0x6c86b56bL, + 0x5bec776aL, 0x02523168L, 0x3538f369L, 0x087faf62L, 0x3f156d63L, + 0x66ab2b61L, 0x51c1e960L, 0xd4d7a665L, 0xe3bd6464L, 0xba032266L, + 0x8d69e067L, 0x20cbd748L, 0x17a11549L, 0x4e1f534bL, 0x7975914aL, + 0xfc63de4fL, 0xcb091c4eL, 0x92b75a4cL, 0xa5dd984dL, 0x989ac446L, + 0xaff00647L, 0xf64e4045L, 0xc1248244L, 0x4432cd41L, 0x73580f40L, + 0x2ae64942L, 0x1d8c8b43L, 0x5068f154L, 0x67023355L, 0x3ebc7557L, + 0x09d6b756L, 0x8cc0f853L, 0xbbaa3a52L, 0xe2147c50L, 0xd57ebe51L, + 0xe839e25aL, 0xdf53205bL, 0x86ed6659L, 0xb187a458L, 0x3491eb5dL, + 0x03fb295cL, 0x5a456f5eL, 0x6d2fad5fL, 0x801b35e1L, 0xb771f7e0L, + 0xeecfb1e2L, 0xd9a573e3L, 0x5cb33ce6L, 0x6bd9fee7L, 0x3267b8e5L, + 0x050d7ae4L, 0x384a26efL, 0x0f20e4eeL, 0x569ea2ecL, 0x61f460edL, + 0xe4e22fe8L, 0xd388ede9L, 0x8a36abebL, 0xbd5c69eaL, 0xf0b813fdL, + 0xc7d2d1fcL, 0x9e6c97feL, 0xa90655ffL, 0x2c101afaL, 0x1b7ad8fbL, + 0x42c49ef9L, 0x75ae5cf8L, 0x48e900f3L, 0x7f83c2f2L, 0x263d84f0L, + 0x115746f1L, 0x944109f4L, 0xa32bcbf5L, 0xfa958df7L, 0xcdff4ff6L, + 0x605d78d9L, 0x5737bad8L, 0x0e89fcdaL, 0x39e33edbL, 0xbcf571deL, + 0x8b9fb3dfL, 0xd221f5ddL, 0xe54b37dcL, 0xd80c6bd7L, 0xef66a9d6L, + 0xb6d8efd4L, 0x81b22dd5L, 0x04a462d0L, 0x33cea0d1L, 0x6a70e6d3L, + 0x5d1a24d2L, 0x10fe5ec5L, 0x27949cc4L, 0x7e2adac6L, 0x494018c7L, + 0xcc5657c2L, 0xfb3c95c3L, 0xa282d3c1L, 0x95e811c0L, 0xa8af4dcbL, + 0x9fc58fcaL, 0xc67bc9c8L, 0xf1110bc9L, 0x740744ccL, 0x436d86cdL, + 0x1ad3c0cfL, 0x2db902ceL, 0x4096af91L, 0x77fc6d90L, 0x2e422b92L, + 0x1928e993L, 0x9c3ea696L, 0xab546497L, 0xf2ea2295L, 0xc580e094L, + 0xf8c7bc9fL, 0xcfad7e9eL, 0x9613389cL, 0xa179fa9dL, 0x246fb598L, + 0x13057799L, 0x4abb319bL, 0x7dd1f39aL, 0x3035898dL, 0x075f4b8cL, + 0x5ee10d8eL, 0x698bcf8fL, 0xec9d808aL, 0xdbf7428bL, 0x82490489L, + 0xb523c688L, 0x88649a83L, 0xbf0e5882L, 0xe6b01e80L, 0xd1dadc81L, + 0x54cc9384L, 0x63a65185L, 0x3a181787L, 0x0d72d586L, 0xa0d0e2a9L, + 0x97ba20a8L, 0xce0466aaL, 0xf96ea4abL, 0x7c78ebaeL, 0x4b1229afL, + 0x12ac6fadL, 0x25c6adacL, 0x1881f1a7L, 0x2feb33a6L, 0x765575a4L, + 0x413fb7a5L, 0xc429f8a0L, 0xf3433aa1L, 0xaafd7ca3L, 0x9d97bea2L, + 0xd073c4b5L, 0xe71906b4L, 0xbea740b6L, 0x89cd82b7L, 0x0cdbcdb2L, + 0x3bb10fb3L, 0x620f49b1L, 0x55658bb0L, 0x6822d7bbL, 0x5f4815baL, + 0x06f653b8L, 0x319c91b9L, 0xb48adebcL, 0x83e01cbdL, 0xda5e5abfL, + 0xed3498beL + , + 0x00000000L, 0x6567bcb8L, 0x8bc809aaL, 0xeeafb512L, 0x5797628fL, + 0x32f0de37L, 0xdc5f6b25L, 0xb938d79dL, 0xef28b4c5L, 0x8a4f087dL, + 0x64e0bd6fL, 0x018701d7L, 0xb8bfd64aL, 0xddd86af2L, 0x3377dfe0L, + 0x56106358L, 0x9f571950L, 0xfa30a5e8L, 0x149f10faL, 0x71f8ac42L, + 0xc8c07bdfL, 0xada7c767L, 0x43087275L, 0x266fcecdL, 0x707fad95L, + 0x1518112dL, 0xfbb7a43fL, 0x9ed01887L, 0x27e8cf1aL, 0x428f73a2L, + 0xac20c6b0L, 0xc9477a08L, 0x3eaf32a0L, 0x5bc88e18L, 0xb5673b0aL, + 0xd00087b2L, 0x6938502fL, 0x0c5fec97L, 0xe2f05985L, 0x8797e53dL, + 0xd1878665L, 0xb4e03addL, 0x5a4f8fcfL, 0x3f283377L, 0x8610e4eaL, + 0xe3775852L, 0x0dd8ed40L, 0x68bf51f8L, 0xa1f82bf0L, 0xc49f9748L, + 0x2a30225aL, 0x4f579ee2L, 0xf66f497fL, 0x9308f5c7L, 0x7da740d5L, + 0x18c0fc6dL, 0x4ed09f35L, 0x2bb7238dL, 0xc518969fL, 0xa07f2a27L, + 0x1947fdbaL, 0x7c204102L, 0x928ff410L, 0xf7e848a8L, 0x3d58149bL, + 0x583fa823L, 0xb6901d31L, 0xd3f7a189L, 0x6acf7614L, 0x0fa8caacL, + 0xe1077fbeL, 0x8460c306L, 0xd270a05eL, 0xb7171ce6L, 0x59b8a9f4L, + 0x3cdf154cL, 0x85e7c2d1L, 0xe0807e69L, 0x0e2fcb7bL, 0x6b4877c3L, + 0xa20f0dcbL, 0xc768b173L, 0x29c70461L, 0x4ca0b8d9L, 0xf5986f44L, + 0x90ffd3fcL, 0x7e5066eeL, 0x1b37da56L, 0x4d27b90eL, 0x284005b6L, + 0xc6efb0a4L, 0xa3880c1cL, 0x1ab0db81L, 0x7fd76739L, 0x9178d22bL, + 0xf41f6e93L, 0x03f7263bL, 0x66909a83L, 0x883f2f91L, 0xed589329L, + 0x546044b4L, 0x3107f80cL, 0xdfa84d1eL, 0xbacff1a6L, 0xecdf92feL, + 0x89b82e46L, 0x67179b54L, 0x027027ecL, 0xbb48f071L, 0xde2f4cc9L, + 0x3080f9dbL, 0x55e74563L, 0x9ca03f6bL, 0xf9c783d3L, 0x176836c1L, + 0x720f8a79L, 0xcb375de4L, 0xae50e15cL, 0x40ff544eL, 0x2598e8f6L, + 0x73888baeL, 0x16ef3716L, 0xf8408204L, 0x9d273ebcL, 0x241fe921L, + 0x41785599L, 0xafd7e08bL, 0xcab05c33L, 0x3bb659edL, 0x5ed1e555L, + 0xb07e5047L, 0xd519ecffL, 0x6c213b62L, 0x094687daL, 0xe7e932c8L, + 0x828e8e70L, 0xd49eed28L, 0xb1f95190L, 0x5f56e482L, 0x3a31583aL, + 0x83098fa7L, 0xe66e331fL, 0x08c1860dL, 0x6da63ab5L, 0xa4e140bdL, + 0xc186fc05L, 0x2f294917L, 0x4a4ef5afL, 0xf3762232L, 0x96119e8aL, + 0x78be2b98L, 0x1dd99720L, 0x4bc9f478L, 0x2eae48c0L, 0xc001fdd2L, + 0xa566416aL, 0x1c5e96f7L, 0x79392a4fL, 0x97969f5dL, 0xf2f123e5L, + 0x05196b4dL, 0x607ed7f5L, 0x8ed162e7L, 0xebb6de5fL, 0x528e09c2L, + 0x37e9b57aL, 0xd9460068L, 0xbc21bcd0L, 0xea31df88L, 0x8f566330L, + 0x61f9d622L, 0x049e6a9aL, 0xbda6bd07L, 0xd8c101bfL, 0x366eb4adL, + 0x53090815L, 0x9a4e721dL, 0xff29cea5L, 0x11867bb7L, 0x74e1c70fL, + 0xcdd91092L, 0xa8beac2aL, 0x46111938L, 0x2376a580L, 0x7566c6d8L, + 0x10017a60L, 0xfeaecf72L, 0x9bc973caL, 0x22f1a457L, 0x479618efL, + 0xa939adfdL, 0xcc5e1145L, 0x06ee4d76L, 0x6389f1ceL, 0x8d2644dcL, + 0xe841f864L, 0x51792ff9L, 0x341e9341L, 0xdab12653L, 0xbfd69aebL, + 0xe9c6f9b3L, 0x8ca1450bL, 0x620ef019L, 0x07694ca1L, 0xbe519b3cL, + 0xdb362784L, 0x35999296L, 0x50fe2e2eL, 0x99b95426L, 0xfcdee89eL, + 0x12715d8cL, 0x7716e134L, 0xce2e36a9L, 0xab498a11L, 0x45e63f03L, + 0x208183bbL, 0x7691e0e3L, 0x13f65c5bL, 0xfd59e949L, 0x983e55f1L, + 0x2106826cL, 0x44613ed4L, 0xaace8bc6L, 0xcfa9377eL, 0x38417fd6L, + 0x5d26c36eL, 0xb389767cL, 0xd6eecac4L, 0x6fd61d59L, 0x0ab1a1e1L, + 0xe41e14f3L, 0x8179a84bL, 0xd769cb13L, 0xb20e77abL, 0x5ca1c2b9L, + 0x39c67e01L, 0x80fea99cL, 0xe5991524L, 0x0b36a036L, 0x6e511c8eL, + 0xa7166686L, 0xc271da3eL, 0x2cde6f2cL, 0x49b9d394L, 0xf0810409L, + 0x95e6b8b1L, 0x7b490da3L, 0x1e2eb11bL, 0x483ed243L, 0x2d596efbL, + 0xc3f6dbe9L, 0xa6916751L, 0x1fa9b0ccL, 0x7ace0c74L, 0x9461b966L, + 0xf10605deL +# endif /* IZ_CRCOPTIM_UNFOLDTBL */ +# else /* !IZ_CRC_BE_OPTIMIZ */ + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +# ifdef IZ_CRCOPTIM_UNFOLDTBL + , + 0x00000000L, 0x191b3141L, 0x32366282L, 0x2b2d53c3L, 0x646cc504L, + 0x7d77f445L, 0x565aa786L, 0x4f4196c7L, 0xc8d98a08L, 0xd1c2bb49L, + 0xfaefe88aL, 0xe3f4d9cbL, 0xacb54f0cL, 0xb5ae7e4dL, 0x9e832d8eL, + 0x87981ccfL, 0x4ac21251L, 0x53d92310L, 0x78f470d3L, 0x61ef4192L, + 0x2eaed755L, 0x37b5e614L, 0x1c98b5d7L, 0x05838496L, 0x821b9859L, + 0x9b00a918L, 0xb02dfadbL, 0xa936cb9aL, 0xe6775d5dL, 0xff6c6c1cL, + 0xd4413fdfL, 0xcd5a0e9eL, 0x958424a2L, 0x8c9f15e3L, 0xa7b24620L, + 0xbea97761L, 0xf1e8e1a6L, 0xe8f3d0e7L, 0xc3de8324L, 0xdac5b265L, + 0x5d5daeaaL, 0x44469febL, 0x6f6bcc28L, 0x7670fd69L, 0x39316baeL, + 0x202a5aefL, 0x0b07092cL, 0x121c386dL, 0xdf4636f3L, 0xc65d07b2L, + 0xed705471L, 0xf46b6530L, 0xbb2af3f7L, 0xa231c2b6L, 0x891c9175L, + 0x9007a034L, 0x179fbcfbL, 0x0e848dbaL, 0x25a9de79L, 0x3cb2ef38L, + 0x73f379ffL, 0x6ae848beL, 0x41c51b7dL, 0x58de2a3cL, 0xf0794f05L, + 0xe9627e44L, 0xc24f2d87L, 0xdb541cc6L, 0x94158a01L, 0x8d0ebb40L, + 0xa623e883L, 0xbf38d9c2L, 0x38a0c50dL, 0x21bbf44cL, 0x0a96a78fL, + 0x138d96ceL, 0x5ccc0009L, 0x45d73148L, 0x6efa628bL, 0x77e153caL, + 0xbabb5d54L, 0xa3a06c15L, 0x888d3fd6L, 0x91960e97L, 0xded79850L, + 0xc7cca911L, 0xece1fad2L, 0xf5facb93L, 0x7262d75cL, 0x6b79e61dL, + 0x4054b5deL, 0x594f849fL, 0x160e1258L, 0x0f152319L, 0x243870daL, + 0x3d23419bL, 0x65fd6ba7L, 0x7ce65ae6L, 0x57cb0925L, 0x4ed03864L, + 0x0191aea3L, 0x188a9fe2L, 0x33a7cc21L, 0x2abcfd60L, 0xad24e1afL, + 0xb43fd0eeL, 0x9f12832dL, 0x8609b26cL, 0xc94824abL, 0xd05315eaL, + 0xfb7e4629L, 0xe2657768L, 0x2f3f79f6L, 0x362448b7L, 0x1d091b74L, + 0x04122a35L, 0x4b53bcf2L, 0x52488db3L, 0x7965de70L, 0x607eef31L, + 0xe7e6f3feL, 0xfefdc2bfL, 0xd5d0917cL, 0xcccba03dL, 0x838a36faL, + 0x9a9107bbL, 0xb1bc5478L, 0xa8a76539L, 0x3b83984bL, 0x2298a90aL, + 0x09b5fac9L, 0x10aecb88L, 0x5fef5d4fL, 0x46f46c0eL, 0x6dd93fcdL, + 0x74c20e8cL, 0xf35a1243L, 0xea412302L, 0xc16c70c1L, 0xd8774180L, + 0x9736d747L, 0x8e2de606L, 0xa500b5c5L, 0xbc1b8484L, 0x71418a1aL, + 0x685abb5bL, 0x4377e898L, 0x5a6cd9d9L, 0x152d4f1eL, 0x0c367e5fL, + 0x271b2d9cL, 0x3e001cddL, 0xb9980012L, 0xa0833153L, 0x8bae6290L, + 0x92b553d1L, 0xddf4c516L, 0xc4eff457L, 0xefc2a794L, 0xf6d996d5L, + 0xae07bce9L, 0xb71c8da8L, 0x9c31de6bL, 0x852aef2aL, 0xca6b79edL, + 0xd37048acL, 0xf85d1b6fL, 0xe1462a2eL, 0x66de36e1L, 0x7fc507a0L, + 0x54e85463L, 0x4df36522L, 0x02b2f3e5L, 0x1ba9c2a4L, 0x30849167L, + 0x299fa026L, 0xe4c5aeb8L, 0xfdde9ff9L, 0xd6f3cc3aL, 0xcfe8fd7bL, + 0x80a96bbcL, 0x99b25afdL, 0xb29f093eL, 0xab84387fL, 0x2c1c24b0L, + 0x350715f1L, 0x1e2a4632L, 0x07317773L, 0x4870e1b4L, 0x516bd0f5L, + 0x7a468336L, 0x635db277L, 0xcbfad74eL, 0xd2e1e60fL, 0xf9ccb5ccL, + 0xe0d7848dL, 0xaf96124aL, 0xb68d230bL, 0x9da070c8L, 0x84bb4189L, + 0x03235d46L, 0x1a386c07L, 0x31153fc4L, 0x280e0e85L, 0x674f9842L, + 0x7e54a903L, 0x5579fac0L, 0x4c62cb81L, 0x8138c51fL, 0x9823f45eL, + 0xb30ea79dL, 0xaa1596dcL, 0xe554001bL, 0xfc4f315aL, 0xd7626299L, + 0xce7953d8L, 0x49e14f17L, 0x50fa7e56L, 0x7bd72d95L, 0x62cc1cd4L, + 0x2d8d8a13L, 0x3496bb52L, 0x1fbbe891L, 0x06a0d9d0L, 0x5e7ef3ecL, + 0x4765c2adL, 0x6c48916eL, 0x7553a02fL, 0x3a1236e8L, 0x230907a9L, + 0x0824546aL, 0x113f652bL, 0x96a779e4L, 0x8fbc48a5L, 0xa4911b66L, + 0xbd8a2a27L, 0xf2cbbce0L, 0xebd08da1L, 0xc0fdde62L, 0xd9e6ef23L, + 0x14bce1bdL, 0x0da7d0fcL, 0x268a833fL, 0x3f91b27eL, 0x70d024b9L, + 0x69cb15f8L, 0x42e6463bL, 0x5bfd777aL, 0xdc656bb5L, 0xc57e5af4L, + 0xee530937L, 0xf7483876L, 0xb809aeb1L, 0xa1129ff0L, 0x8a3fcc33L, + 0x9324fd72L + , + 0x00000000L, 0x01c26a37L, 0x0384d46eL, 0x0246be59L, 0x0709a8dcL, + 0x06cbc2ebL, 0x048d7cb2L, 0x054f1685L, 0x0e1351b8L, 0x0fd13b8fL, + 0x0d9785d6L, 0x0c55efe1L, 0x091af964L, 0x08d89353L, 0x0a9e2d0aL, + 0x0b5c473dL, 0x1c26a370L, 0x1de4c947L, 0x1fa2771eL, 0x1e601d29L, + 0x1b2f0bacL, 0x1aed619bL, 0x18abdfc2L, 0x1969b5f5L, 0x1235f2c8L, + 0x13f798ffL, 0x11b126a6L, 0x10734c91L, 0x153c5a14L, 0x14fe3023L, + 0x16b88e7aL, 0x177ae44dL, 0x384d46e0L, 0x398f2cd7L, 0x3bc9928eL, + 0x3a0bf8b9L, 0x3f44ee3cL, 0x3e86840bL, 0x3cc03a52L, 0x3d025065L, + 0x365e1758L, 0x379c7d6fL, 0x35dac336L, 0x3418a901L, 0x3157bf84L, + 0x3095d5b3L, 0x32d36beaL, 0x331101ddL, 0x246be590L, 0x25a98fa7L, + 0x27ef31feL, 0x262d5bc9L, 0x23624d4cL, 0x22a0277bL, 0x20e69922L, + 0x2124f315L, 0x2a78b428L, 0x2bbade1fL, 0x29fc6046L, 0x283e0a71L, + 0x2d711cf4L, 0x2cb376c3L, 0x2ef5c89aL, 0x2f37a2adL, 0x709a8dc0L, + 0x7158e7f7L, 0x731e59aeL, 0x72dc3399L, 0x7793251cL, 0x76514f2bL, + 0x7417f172L, 0x75d59b45L, 0x7e89dc78L, 0x7f4bb64fL, 0x7d0d0816L, + 0x7ccf6221L, 0x798074a4L, 0x78421e93L, 0x7a04a0caL, 0x7bc6cafdL, + 0x6cbc2eb0L, 0x6d7e4487L, 0x6f38fadeL, 0x6efa90e9L, 0x6bb5866cL, + 0x6a77ec5bL, 0x68315202L, 0x69f33835L, 0x62af7f08L, 0x636d153fL, + 0x612bab66L, 0x60e9c151L, 0x65a6d7d4L, 0x6464bde3L, 0x662203baL, + 0x67e0698dL, 0x48d7cb20L, 0x4915a117L, 0x4b531f4eL, 0x4a917579L, + 0x4fde63fcL, 0x4e1c09cbL, 0x4c5ab792L, 0x4d98dda5L, 0x46c49a98L, + 0x4706f0afL, 0x45404ef6L, 0x448224c1L, 0x41cd3244L, 0x400f5873L, + 0x4249e62aL, 0x438b8c1dL, 0x54f16850L, 0x55330267L, 0x5775bc3eL, + 0x56b7d609L, 0x53f8c08cL, 0x523aaabbL, 0x507c14e2L, 0x51be7ed5L, + 0x5ae239e8L, 0x5b2053dfL, 0x5966ed86L, 0x58a487b1L, 0x5deb9134L, + 0x5c29fb03L, 0x5e6f455aL, 0x5fad2f6dL, 0xe1351b80L, 0xe0f771b7L, + 0xe2b1cfeeL, 0xe373a5d9L, 0xe63cb35cL, 0xe7fed96bL, 0xe5b86732L, + 0xe47a0d05L, 0xef264a38L, 0xeee4200fL, 0xeca29e56L, 0xed60f461L, + 0xe82fe2e4L, 0xe9ed88d3L, 0xebab368aL, 0xea695cbdL, 0xfd13b8f0L, + 0xfcd1d2c7L, 0xfe976c9eL, 0xff5506a9L, 0xfa1a102cL, 0xfbd87a1bL, + 0xf99ec442L, 0xf85cae75L, 0xf300e948L, 0xf2c2837fL, 0xf0843d26L, + 0xf1465711L, 0xf4094194L, 0xf5cb2ba3L, 0xf78d95faL, 0xf64fffcdL, + 0xd9785d60L, 0xd8ba3757L, 0xdafc890eL, 0xdb3ee339L, 0xde71f5bcL, + 0xdfb39f8bL, 0xddf521d2L, 0xdc374be5L, 0xd76b0cd8L, 0xd6a966efL, + 0xd4efd8b6L, 0xd52db281L, 0xd062a404L, 0xd1a0ce33L, 0xd3e6706aL, + 0xd2241a5dL, 0xc55efe10L, 0xc49c9427L, 0xc6da2a7eL, 0xc7184049L, + 0xc25756ccL, 0xc3953cfbL, 0xc1d382a2L, 0xc011e895L, 0xcb4dafa8L, + 0xca8fc59fL, 0xc8c97bc6L, 0xc90b11f1L, 0xcc440774L, 0xcd866d43L, + 0xcfc0d31aL, 0xce02b92dL, 0x91af9640L, 0x906dfc77L, 0x922b422eL, + 0x93e92819L, 0x96a63e9cL, 0x976454abL, 0x9522eaf2L, 0x94e080c5L, + 0x9fbcc7f8L, 0x9e7eadcfL, 0x9c381396L, 0x9dfa79a1L, 0x98b56f24L, + 0x99770513L, 0x9b31bb4aL, 0x9af3d17dL, 0x8d893530L, 0x8c4b5f07L, + 0x8e0de15eL, 0x8fcf8b69L, 0x8a809decL, 0x8b42f7dbL, 0x89044982L, + 0x88c623b5L, 0x839a6488L, 0x82580ebfL, 0x801eb0e6L, 0x81dcdad1L, + 0x8493cc54L, 0x8551a663L, 0x8717183aL, 0x86d5720dL, 0xa9e2d0a0L, + 0xa820ba97L, 0xaa6604ceL, 0xaba46ef9L, 0xaeeb787cL, 0xaf29124bL, + 0xad6fac12L, 0xacadc625L, 0xa7f18118L, 0xa633eb2fL, 0xa4755576L, + 0xa5b73f41L, 0xa0f829c4L, 0xa13a43f3L, 0xa37cfdaaL, 0xa2be979dL, + 0xb5c473d0L, 0xb40619e7L, 0xb640a7beL, 0xb782cd89L, 0xb2cddb0cL, + 0xb30fb13bL, 0xb1490f62L, 0xb08b6555L, 0xbbd72268L, 0xba15485fL, + 0xb853f606L, 0xb9919c31L, 0xbcde8ab4L, 0xbd1ce083L, 0xbf5a5edaL, + 0xbe9834edL + , + 0x00000000L, 0xb8bc6765L, 0xaa09c88bL, 0x12b5afeeL, 0x8f629757L, + 0x37def032L, 0x256b5fdcL, 0x9dd738b9L, 0xc5b428efL, 0x7d084f8aL, + 0x6fbde064L, 0xd7018701L, 0x4ad6bfb8L, 0xf26ad8ddL, 0xe0df7733L, + 0x58631056L, 0x5019579fL, 0xe8a530faL, 0xfa109f14L, 0x42acf871L, + 0xdf7bc0c8L, 0x67c7a7adL, 0x75720843L, 0xcdce6f26L, 0x95ad7f70L, + 0x2d111815L, 0x3fa4b7fbL, 0x8718d09eL, 0x1acfe827L, 0xa2738f42L, + 0xb0c620acL, 0x087a47c9L, 0xa032af3eL, 0x188ec85bL, 0x0a3b67b5L, + 0xb28700d0L, 0x2f503869L, 0x97ec5f0cL, 0x8559f0e2L, 0x3de59787L, + 0x658687d1L, 0xdd3ae0b4L, 0xcf8f4f5aL, 0x7733283fL, 0xeae41086L, + 0x525877e3L, 0x40edd80dL, 0xf851bf68L, 0xf02bf8a1L, 0x48979fc4L, + 0x5a22302aL, 0xe29e574fL, 0x7f496ff6L, 0xc7f50893L, 0xd540a77dL, + 0x6dfcc018L, 0x359fd04eL, 0x8d23b72bL, 0x9f9618c5L, 0x272a7fa0L, + 0xbafd4719L, 0x0241207cL, 0x10f48f92L, 0xa848e8f7L, 0x9b14583dL, + 0x23a83f58L, 0x311d90b6L, 0x89a1f7d3L, 0x1476cf6aL, 0xaccaa80fL, + 0xbe7f07e1L, 0x06c36084L, 0x5ea070d2L, 0xe61c17b7L, 0xf4a9b859L, + 0x4c15df3cL, 0xd1c2e785L, 0x697e80e0L, 0x7bcb2f0eL, 0xc377486bL, + 0xcb0d0fa2L, 0x73b168c7L, 0x6104c729L, 0xd9b8a04cL, 0x446f98f5L, + 0xfcd3ff90L, 0xee66507eL, 0x56da371bL, 0x0eb9274dL, 0xb6054028L, + 0xa4b0efc6L, 0x1c0c88a3L, 0x81dbb01aL, 0x3967d77fL, 0x2bd27891L, + 0x936e1ff4L, 0x3b26f703L, 0x839a9066L, 0x912f3f88L, 0x299358edL, + 0xb4446054L, 0x0cf80731L, 0x1e4da8dfL, 0xa6f1cfbaL, 0xfe92dfecL, + 0x462eb889L, 0x549b1767L, 0xec277002L, 0x71f048bbL, 0xc94c2fdeL, + 0xdbf98030L, 0x6345e755L, 0x6b3fa09cL, 0xd383c7f9L, 0xc1366817L, + 0x798a0f72L, 0xe45d37cbL, 0x5ce150aeL, 0x4e54ff40L, 0xf6e89825L, + 0xae8b8873L, 0x1637ef16L, 0x048240f8L, 0xbc3e279dL, 0x21e91f24L, + 0x99557841L, 0x8be0d7afL, 0x335cb0caL, 0xed59b63bL, 0x55e5d15eL, + 0x47507eb0L, 0xffec19d5L, 0x623b216cL, 0xda874609L, 0xc832e9e7L, + 0x708e8e82L, 0x28ed9ed4L, 0x9051f9b1L, 0x82e4565fL, 0x3a58313aL, + 0xa78f0983L, 0x1f336ee6L, 0x0d86c108L, 0xb53aa66dL, 0xbd40e1a4L, + 0x05fc86c1L, 0x1749292fL, 0xaff54e4aL, 0x322276f3L, 0x8a9e1196L, + 0x982bbe78L, 0x2097d91dL, 0x78f4c94bL, 0xc048ae2eL, 0xd2fd01c0L, + 0x6a4166a5L, 0xf7965e1cL, 0x4f2a3979L, 0x5d9f9697L, 0xe523f1f2L, + 0x4d6b1905L, 0xf5d77e60L, 0xe762d18eL, 0x5fdeb6ebL, 0xc2098e52L, + 0x7ab5e937L, 0x680046d9L, 0xd0bc21bcL, 0x88df31eaL, 0x3063568fL, + 0x22d6f961L, 0x9a6a9e04L, 0x07bda6bdL, 0xbf01c1d8L, 0xadb46e36L, + 0x15080953L, 0x1d724e9aL, 0xa5ce29ffL, 0xb77b8611L, 0x0fc7e174L, + 0x9210d9cdL, 0x2aacbea8L, 0x38191146L, 0x80a57623L, 0xd8c66675L, + 0x607a0110L, 0x72cfaefeL, 0xca73c99bL, 0x57a4f122L, 0xef189647L, + 0xfdad39a9L, 0x45115eccL, 0x764dee06L, 0xcef18963L, 0xdc44268dL, + 0x64f841e8L, 0xf92f7951L, 0x41931e34L, 0x5326b1daL, 0xeb9ad6bfL, + 0xb3f9c6e9L, 0x0b45a18cL, 0x19f00e62L, 0xa14c6907L, 0x3c9b51beL, + 0x842736dbL, 0x96929935L, 0x2e2efe50L, 0x2654b999L, 0x9ee8defcL, + 0x8c5d7112L, 0x34e11677L, 0xa9362eceL, 0x118a49abL, 0x033fe645L, + 0xbb838120L, 0xe3e09176L, 0x5b5cf613L, 0x49e959fdL, 0xf1553e98L, + 0x6c820621L, 0xd43e6144L, 0xc68bceaaL, 0x7e37a9cfL, 0xd67f4138L, + 0x6ec3265dL, 0x7c7689b3L, 0xc4caeed6L, 0x591dd66fL, 0xe1a1b10aL, + 0xf3141ee4L, 0x4ba87981L, 0x13cb69d7L, 0xab770eb2L, 0xb9c2a15cL, + 0x017ec639L, 0x9ca9fe80L, 0x241599e5L, 0x36a0360bL, 0x8e1c516eL, + 0x866616a7L, 0x3eda71c2L, 0x2c6fde2cL, 0x94d3b949L, 0x090481f0L, + 0xb1b8e695L, 0xa30d497bL, 0x1bb12e1eL, 0x43d23e48L, 0xfb6e592dL, + 0xe9dbf6c3L, 0x516791a6L, 0xccb0a91fL, 0x740cce7aL, 0x66b96194L, + 0xde0506f1L +# endif /* IZ_CRCOPTIM_UNFOLDTBL */ +# endif /* ? IZ_CRC_BE_OPTIMIZ */ +}; +#endif /* ?DYNAMIC_CRC_TABLE */ + +/* use "OF((void))" here to work around a Borland TC++ 1.0 problem */ +#ifdef USE_ZLIB +ZCONST uLongf *get_crc_table OF((void)) +#else +ZCONST ulg near *get_crc_table OF((void)) +#endif +{ +#ifdef DYNAMIC_CRC_TABLE + if (CRC_TABLE_IS_EMPTY) + make_crc_table(); +#endif +#ifdef USE_ZLIB + return (ZCONST uLongf *)crc_table; +#else + return crc_table; +#endif +} + +#ifdef DYNALLOC_CRCTAB +void free_crc_table() +{ + if (!CRC_TABLE_IS_EMPTY) + { + nearfree((ulg near *)crc_table); + MARK_CRCTAB_EMPTY; + } +} +#endif + +#ifndef USE_ZLIB +#ifndef CRC_TABLE_ONLY +#ifndef ASM_CRC + +#define DO1(crc, buf) crc = CRC32(crc, *buf++, crc_32_tab) +#define DO2(crc, buf) DO1(crc, buf); DO1(crc, buf) +#define DO4(crc, buf) DO2(crc, buf); DO2(crc, buf) +#define DO8(crc, buf) DO4(crc, buf); DO4(crc, buf) + +#if (defined(IZ_CRC_BE_OPTIMIZ) || defined(IZ_CRC_LE_OPTIMIZ)) + +# ifdef IZ_CRCOPTIM_UNFOLDTBL +# ifdef IZ_CRC_BE_OPTIMIZ +# define DO_OPT4(c, buf4) c ^= *(buf4)++; \ + c = crc_32_tab[c & 0xff] ^ crc_32_tab[256+((c>>8) & 0xff)] ^ \ + crc_32_tab[2*256+((c>>16) & 0xff)] ^ crc_32_tab[3*256+(c>>24)] +# else /* !IZ_CRC_BE_OPTIMIZ */ +# define DO_OPT4(c, buf4) c ^= *(buf4)++; \ + c = crc_32_tab[3*256+(c & 0xff)] ^ crc_32_tab[2*256+((c>>8) & 0xff)] \ + ^ crc_32_tab[256+((c>>16) & 0xff)] ^ crc_32_tab[c>>24] +# endif /* ?IZ_CRC_BE_OPTIMIZ */ +# else /* !IZ_CRCOPTIM_UNFOLDTBL */ +# define DO_OPT4(c, buf4) c ^= *(buf4)++; \ + c = CRC32UPD(c, crc_32_tab); \ + c = CRC32UPD(c, crc_32_tab); \ + c = CRC32UPD(c, crc_32_tab); \ + c = CRC32UPD(c, crc_32_tab) +# endif /* ?IZ_CRCOPTIM_UNFOLDTBL */ + +# define DO_OPT16(crc, buf4) DO_OPT4(crc, buf4); DO_OPT4(crc, buf4); \ + DO_OPT4(crc, buf4); DO_OPT4(crc, buf4); + +#endif /* (IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */ + + +/* ========================================================================= */ +ulg crc32(crc, buf, len) + ulg crc; /* crc shift register */ + register ZCONST uch *buf; /* pointer to bytes to pump through */ + extent len; /* number of bytes in buf[] */ +/* Run a set of bytes through the crc shift register. If buf is a NULL + pointer, then initialize the crc shift register contents instead. + Return the current crc in either case. */ +{ + register z_uint4 c; + register ZCONST ulg near *crc_32_tab; + + if (buf == NULL) return 0L; + + crc_32_tab = get_crc_table(); + + c = (REV_BE((z_uint4)crc) ^ 0xffffffffL); + +#if (defined(IZ_CRC_BE_OPTIMIZ) || defined(IZ_CRC_LE_OPTIMIZ)) + /* Align buf pointer to next DWORD boundary. */ + while (len && ((ptrdiff_t)buf & 3)) { + DO1(c, buf); + len--; + } + { + ZCONST z_uint4 *buf4 = (ZCONST z_uint4 *)buf; + while (len >= 16) { + DO_OPT16(c, buf4); + len -= 16; + } + while (len >= 4) { + DO_OPT4(c, buf4); + len -= 4; + } + buf = (ZCONST uch *)buf4; + } +#else /* !(IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */ +#ifndef NO_UNROLLED_LOOPS + while (len >= 8) { + DO8(c, buf); + len -= 8; + } +#endif /* !NO_UNROLLED_LOOPS */ +#endif /* ?(IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */ + if (len) do { + DO1(c, buf); + } while (--len); + + return REV_BE(c) ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ +} +#endif /* !ASM_CRC */ +#endif /* !CRC_TABLE_ONLY */ +#endif /* !USE_ZLIB */ +#endif /* !USE_ZLIB || USE_OWN_CRCTAB */ diff --git a/crc32.h b/crc32.h new file mode 100644 index 0000000..83af240 --- /dev/null +++ b/crc32.h @@ -0,0 +1,60 @@ +/* + Copyright (c) 1990-2008 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 +*/ +/* crc32.h -- compute the CRC-32 of a data stream + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef __crc32_h +#define __crc32_h /* identifies this source module */ + +/* This header should be read AFTER zip.h resp. unzip.h + * (the latter with UNZIP_INTERNAL defined...). + */ + +#ifndef OF +# define OF(a) a +#endif +#ifndef ZCONST +# define ZCONST const +#endif + +#ifdef DYNALLOC_CRCTAB + void free_crc_table OF((void)); +#endif +#ifndef USE_ZLIB + ZCONST ulg near *get_crc_table OF((void)); +#endif +#if (defined(USE_ZLIB) || defined(CRC_TABLE_ONLY)) +# ifdef IZ_CRC_BE_OPTIMIZ +# undef IZ_CRC_BE_OPTIMIZ +# endif +#else /* !(USE_ZLIB || CRC_TABLE_ONLY) */ + ulg crc32 OF((ulg crc, ZCONST uch *buf, extent len)); +#endif /* ?(USE_ZLIB || CRC_TABLE_ONLY) */ + +#ifndef CRC_32_TAB +# define CRC_32_TAB crc_32_tab +#endif + +#ifdef CRC32 +# undef CRC32 +#endif +#ifdef IZ_CRC_BE_OPTIMIZ +# define CRC32UPD(c, crctab) (crctab[((c) >> 24)] ^ ((c) << 8)) +# define CRC32(c, b, crctab) (crctab[(((int)(c) >> 24) ^ (b))] ^ ((c) << 8)) +# define REV_BE(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) +#else +# define CRC32UPD(c, crctab) (crctab[((int)(c)) & 0xff] ^ ((c) >> 8)) +# define CRC32(c, b, crctab) (crctab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) +# define REV_BE(w) w +#endif + +#endif /* !__crc32_h */ diff --git a/crc_i386.S b/crc_i386.S new file mode 100644 index 0000000..38dbc86 --- /dev/null +++ b/crc_i386.S @@ -0,0 +1,304 @@ +/* + Copyright (c) 1990-2007 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 +*/ +/* + * crc_i386.S, optimized CRC calculation function for Zip and UnZip, + * created by Paul Kienitz and Christian Spieler. Last revised 07 Jan 2007. + * + * GRR 961110: incorporated Scott Field optimizations from win32/crc_i386.asm + * => overall 6% speedup in "unzip -tq" on 9MB zipfile (486-66) + * + * SPC 970402: revised for Rodney Brown's optimizations (32-bit-wide + * aligned reads for most of the data from buffer), can be + * disabled by defining the macro NO_32_BIT_LOADS + * + * SPC 971012: added Rodney Brown's additional tweaks for 32-bit-optimized + * CPUs (like the Pentium Pro, Pentium II, and probably some + * Pentium clones). This optimization is controlled by the + * preprocessor switch "__686" and is disabled by default. + * (This default is based on the assumption that most users + * do not yet work on a Pentium Pro or Pentium II machine ...) + * + * COS 050116: Enabled the 686 build by default, because there are hardly any + * pre-686 CPUs in serious use nowadays. (See SPC 970402 above.) + * + * SPC 060103: Updated code to incorporate newer optimizations found in zlib. + * + * SPC 070107: Added conditional switch to deactivate crc32() compilation. + * + * FLAT memory model assumed. Calling interface: + * - args are pushed onto the stack from right to left, + * - return value is given in the EAX register, + * - all other registers (with exception of EFLAGS) are preserved. (With + * GNU C 2.7.x, %edx and %ecx are `scratch' registers, but preserving + * them nevertheless adds only 4 single byte instructions.) + * + * This source generates the function + * ulg crc32(ulg crc, ZCONST uch *buf, extent len). + * + * Loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS. + * This results in shorter code at the expense of reduced performance. + */ + +/* This file is NOT used in conjunction with zlib, or when only creation of + * the basic CRC_32_Table (for other purpose) is requested. + */ +#if !defined(USE_ZLIB) && !defined(CRC_TABLE_ONLY) + +/* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix + * external symbols with an underline character '_'. + */ +#if defined(NO_UNDERLINE) || defined(__ELF__) +# define _crc32 crc32 +# define _get_crc_table get_crc_table +#endif +/* Use 16-byte alignment if your assembler supports it. Warning: gas + * uses a log(x) parameter (.align 4 means 16-byte alignment). On SVR4 + * the parameter is a number of bytes. + */ +#ifndef ALIGNMENT +# define ALIGNMENT .align 4,0x90 +#endif + +#if defined(i386) || defined(_i386) || defined(_I386) || defined(__i386) + +/* This version is for 386 Unix, OS/2, MSDOS in 32 bit mode (gcc & gas). + * Warning: it uses the AT&T syntax: mov source,dest + * This file is only optional. If you want to use the C version, + * remove -DASM_CRC from CFLAGS in Makefile and set OBJA to an empty string. + */ + + .file "crc_i386.S" + +#if !defined(PRE_686) && !defined(__686) + /* Optimize for Pentium Pro and compatible CPUs by default. */ +# define __686 +#endif + +#if defined(NO_STD_STACKFRAME) && defined(USE_STD_STACKFRAME) +# undef USE_STACKFRAME +#else + /* The default is to use standard stack frame entry, because it + * results in smaller code! + */ +# ifndef USE_STD_STACKFRAME +# define USE_STD_STACKFRAME +# endif +#endif + +#ifdef USE_STD_STACKFRAME +# define _STD_ENTRY pushl %ebp ; movl %esp,%ebp +# define arg1 8(%ebp) +# define arg2 12(%ebp) +# define arg3 16(%ebp) +# define _STD_LEAVE popl %ebp +#else /* !USE_STD_STACKFRAME */ +# define _STD_ENTRY +# define arg1 24(%esp) +# define arg2 28(%esp) +# define arg3 32(%esp) +# define _STD_LEAVE +#endif /* ?USE_STD_STACKFRAME */ + +/* + * These two (three) macros make up the loop body of the CRC32 cruncher. + * registers modified: + * eax : crc value "c" + * esi : pointer to next data byte (or lword) "buf++" + * registers read: + * edi : pointer to base of crc_table array + * scratch registers: + * ebx : index into crc_table array + * (requires upper three bytes = 0 when __686 is undefined) + */ +#ifndef __686 /* optimize for 386, 486, Pentium */ +#define Do_CRC /* c = (c >> 8) ^ table[c & 0xFF] */\ + movb %al, %bl ;/* tmp = c & 0xFF */\ + shrl $8, %eax ;/* c = (c >> 8) */\ + xorl (%edi, %ebx, 4), %eax ;/* c ^= table[tmp] */ +#else /* __686 : optimize for Pentium Pro and compatible CPUs */ +#define Do_CRC /* c = (c >> 8) ^ table[c & 0xFF] */\ + movzbl %al, %ebx ;/* tmp = c & 0xFF */\ + shrl $8, %eax ;/* c = (c >> 8) */\ + xorl (%edi, %ebx, 4), %eax ;/* c ^=table[tmp] */ +#endif /* ?__686 */ + +#define Do_CRC_byte /* c = (c >> 8) ^ table[(c^*buf++)&0xFF] */\ + xorb (%esi), %al ;/* c ^= *buf */\ + incl %esi ;/* buf++ */\ + Do_CRC + +#define Do_CRC_byteof(ofs) /* c = (c >> 8) ^ table[(c^*buf++)&0xFF] */\ + xorb ofs(%esi), %al ;/* c ^= *buf */\ + incl %esi ;/* buf++ */\ + Do_CRC + +#ifndef NO_32_BIT_LOADS +# ifdef IZ_CRCOPTIM_UNFOLDTBL + /* the edx register is needed in crc calculation */ +# define SavLen arg3 +# define UpdCRC_lword \ + movzbl %al, %ebx ; \ + movl 3072(%edi,%ebx,4), %edx ; \ + movzbl %ah, %ebx ; \ + shrl $16, %eax ; \ + xor 2048(%edi,%ebx,4), %edx ; \ + movzbl %al, %ebx ; \ + shrl $8,%eax ; \ + xorl 1024(%edi,%ebx,4), %edx ; \ + movl (%edi,%eax,4), %eax ; \ + xorl %edx,%eax ; +# define UpdCRC_lword_sh(dwPtrIncr) \ + movzbl %al, %ebx ; \ + movl 3072(%edi,%ebx,4), %edx ; \ + movzbl %ah, %ebx ; \ + shrl $16, %eax ; \ + xor 2048(%edi,%ebx,4), %edx ; \ + movzbl %al, %ebx ; \ + addl $4*(dwPtrIncr), %esi ;/* ((ulg *)buf)+=dwPtrIncr */\ + shrl $8,%eax ; \ + xorl 1024(%edi,%ebx,4), %edx ; \ + movl (%edi,%eax,4),%eax ; \ + xorl %edx,%eax ; +# else /* !IZ_CRCOPTIM_UNFOLDTBL */ + /* the edx register is not needed anywhere else */ +# define SavLen %edx +# define UpdCRC_lword \ + Do_CRC \ + Do_CRC \ + Do_CRC \ + Do_CRC +# define UpdCRC_lword_sh(dwPtrIncr) \ + Do_CRC \ + Do_CRC \ + addl $4*(dwPtrIncr), %esi ;/* ((ulg *)buf)++ */\ + Do_CRC \ + Do_CRC +# endif /* ?IZ_CRCOPTIM_UNFOLDTBL */ +#define Do_CRC_lword \ + xorl (%esi), %eax ;/* c ^= *(ulg *)buf */\ + UpdCRC_lword_sh(1) /* ... ((ulg *)buf)++ */ +#define Do_CRC_4lword \ + xorl (%esi), %eax ;/* c ^= *(ulg *)buf */\ + UpdCRC_lword \ + xorl 4(%esi), %eax ;/* c ^= *((ulg *)buf+1) */\ + UpdCRC_lword \ + xorl 8(%esi), %eax ;/* c ^= *((ulg *)buf+2) */\ + UpdCRC_lword \ + xorl 12(%esi), %eax ;/* c ^= *((ulg *)buf]+3 */\ + UpdCRC_lword_sh(4) /* ... ((ulg *)buf)+=4 */ +#endif /* !NO_32_BIT_LOADS */ + + + .text + + .globl _crc32 + +_crc32: /* ulg crc32(ulg crc, uch *buf, extent len) */ + _STD_ENTRY + pushl %edi + pushl %esi + pushl %ebx + pushl %edx + pushl %ecx + + movl arg2, %esi /* 2nd arg: uch *buf */ + subl %eax, %eax /* > if (!buf) */ + testl %esi, %esi /* > return 0; */ + jz .L_fine /* > else { */ + call _get_crc_table + movl %eax, %edi + movl arg1, %eax /* 1st arg: ulg crc */ +#ifndef __686 + subl %ebx, %ebx /* ebx=0; bl usable as dword */ +#endif + movl arg3, %ecx /* 3rd arg: extent len */ + notl %eax /* > c = ~crc; */ + + testl %ecx, %ecx +#ifndef NO_UNROLLED_LOOPS + jz .L_bail +# ifndef NO_32_BIT_LOADS + /* Assert now have positive length */ +.L_align_loop: + testl $3, %esi /* Align buf on lword boundary */ + jz .L_aligned_now + Do_CRC_byte + decl %ecx + jnz .L_align_loop +.L_aligned_now: +# endif /* !NO_32_BIT_LOADS */ + movl %ecx, SavLen /* save current value of len */ + shrl $4, %ecx /* ecx = len / 16 */ + jz .L_No_Sixteens +/* align loop head at start of 486 internal cache line !! */ + ALIGNMENT +.L_Next_Sixteen: +# ifndef NO_32_BIT_LOADS + Do_CRC_4lword +# else /* NO_32_BIT_LOADS */ + Do_CRC_byteof(0) + Do_CRC_byteof(1) + Do_CRC_byteof(2) + Do_CRC_byteof(3) + Do_CRC_byteof(4) + Do_CRC_byteof(5) + Do_CRC_byteof(6) + Do_CRC_byteof(7) + Do_CRC_byteof(8) + Do_CRC_byteof(9) + Do_CRC_byteof(10) + Do_CRC_byteof(11) + Do_CRC_byteof(12) + Do_CRC_byteof(13) + Do_CRC_byteof(14) + Do_CRC_byteof(15) + addl $16,%esi ;/* buf += 16 */ +# endif /* ?NO_32_BIT_LOADS */ + decl %ecx + jnz .L_Next_Sixteen + +.L_No_Sixteens: + movl SavLen, %ecx + andl $15, %ecx /* ecx = len % 16 */ +# ifndef NO_32_BIT_LOADS + shrl $2,%ecx /* ecx = len / 4 */ + jz .L_No_Fours +.L_Next_Four: + Do_CRC_lword + decl %ecx + jnz .L_Next_Four +.L_No_Fours: + movl SavLen,%ecx + andl $3,%ecx /* ecx = len % 4 */ +# endif /* !NO_32_BIT_LOADS */ +#endif /* !NO_UNROLLED_LOOPS */ + jz .L_bail /* > if (len) */ +/* align loop head at start of 486 internal cache line !! */ + ALIGNMENT +.L_loupe: /* > do { */ + Do_CRC_byte /* c = CRC32(c,*buf++,crctab);*/ + decl %ecx /* > } while (--len); */ + jnz .L_loupe + +.L_bail: /* > } */ + notl %eax /* > return ~c; */ +.L_fine: + popl %ecx + popl %edx + popl %ebx + popl %esi + popl %edi + _STD_LEAVE + ret + +#else + error: this asm version is for 386 only +#endif /* i386 || _i386 || _I386 || __i386 */ + +#endif /* !USE_ZLIB && !CRC_TABLE_ONLY */ diff --git a/crypt.c b/crypt.c new file mode 100644 index 0000000..784e411 --- /dev/null +++ b/crypt.c @@ -0,0 +1,653 @@ +/* + Copyright (c) 1990-2007 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2005-Feb-10 or later + (the contents of which are also included in (un)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 +*/ +/* + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The main encryption/decryption source code for Info-Zip software was + originally written in Europe. To the best of our knowledge, it can + be freely distributed in both source and object forms from any country, + including the USA under License Exception TSU of the U.S. Export + Administration Regulations (section 740.13(e)) of 6 June 2002. + + NOTE on copyright history: + Previous versions of this source package (up to version 2.8) were + not copyrighted and put in the public domain. If you cannot comply + with the Info-Zip LICENSE, you may want to look for one of those + public domain versions. + */ + +/* + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + */ + +#define ZCRYPT_INTERNAL +#include "zip.h" +#include "crypt.h" +#include "ttyio.h" + +#if CRYPT + +#ifndef FALSE +# define FALSE 0 +#endif + +#ifdef ZIP + /* For the encoding task used in Zip (and ZipCloak), we want to initialize + the crypt algorithm with some reasonably unpredictable bytes, see + the crypthead() function. The standard rand() library function is + used to supply these `random' bytes, which in turn is initialized by + a srand() call. The srand() function takes an "unsigned" (at least 16bit) + seed value as argument to determine the starting point of the rand() + pseudo-random number generator. + This seed number is constructed as "Seed = Seed1 .XOR. Seed2" with + Seed1 supplied by the current time (= "(unsigned)time()") and Seed2 + as some (hopefully) nondeterministic bitmask. On many (most) systems, + we use some "process specific" number, as the PID or something similar, + but when nothing unpredictable is available, a fixed number may be + sufficient. + NOTE: + 1.) This implementation requires the availability of the following + standard UNIX C runtime library functions: time(), rand(), srand(). + On systems where some of them are missing, the environment that + incorporates the crypt routines must supply suitable replacement + functions. + 2.) It is a very bad idea to use a second call to time() to set the + "Seed2" number! In this case, both "Seed1" and "Seed2" would be + (almost) identical, resulting in a (mostly) "zero" constant seed + number passed to srand(). + + The implementation environment defined in the "zip.h" header should + supply a reasonable definition for ZCR_SEED2 (an unsigned number; for + most implementations of rand() and srand(), only the lower 16 bits are + significant!). An example that works on many systems would be + "#define ZCR_SEED2 (unsigned)getpid()". + The default definition for ZCR_SEED2 supplied below should be regarded + as a fallback to allow successful compilation in "beta state" + environments. + */ +# include /* time() function supplies first part of crypt seed */ + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 (unsigned)3141592654L /* use PI as default pattern */ +# endif +# ifdef GLOBAL /* used in Amiga system headers, maybe others too */ +# undef GLOBAL +# endif +# define GLOBAL(g) g +#else /* !ZIP */ +# define GLOBAL(g) G.g +#endif /* ?ZIP */ + + +#ifdef UNZIP + /* char *key = (char *)NULL; moved to globals.h */ +# ifndef FUNZIP + local int testp OF((__GPRO__ ZCONST uch *h)); + local int testkey OF((__GPRO__ ZCONST uch *h, ZCONST char *key)); +# endif +#endif /* UNZIP */ + +#ifndef UNZIP /* moved to globals.h for UnZip */ +# ifndef Z_UINT4_DEFINED +# if !defined(NO_LIMITS_H) +# if (defined(UINT_MAX) && (UINT_MAX == 0xffffffffUL)) + typedef unsigned int z_uint4; +# define Z_UINT4_DEFINED +# else +# if (defined(ULONG_MAX) && (ULONG_MAX == 0xffffffffUL)) + typedef unsigned long z_uint4; +# define Z_UINT4_DEFINED +# else +# if (defined(USHRT_MAX) && (USHRT_MAX == 0xffffffffUL)) + typedef unsigned short z_uint4; +# define Z_UINT4_DEFINED +# endif +# endif +# endif +# endif /* !NO_LIMITS_H */ +# endif /* !Z_UINT4_DEFINED */ +# ifndef Z_UINT4_DEFINED + typedef ulg z_uint4; +# define Z_UINT4_DEFINED +# endif + local z_uint4 keys[3]; /* keys defining the pseudo-random sequence */ +#endif /* !UNZIP */ + +#ifndef Trace +# ifdef CRYPT_DEBUG +# define Trace(x) fprintf x +# else +# define Trace(x) +# endif +#endif + +#include "crc32.h" + +#ifdef IZ_CRC_BE_OPTIMIZ + local z_uint4 near crycrctab[256]; + local z_uint4 near *cry_crctb_p = NULL; + local z_uint4 near *crytab_init OF((__GPRO)); +# define CRY_CRC_TAB cry_crctb_p +# undef CRC32 +# define CRC32(c, b, crctab) (crctab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) +#else +# define CRY_CRC_TAB CRC_32_TAB +#endif /* ?IZ_CRC_BE_OPTIMIZ */ + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +int decrypt_byte(__G) + __GDEF +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)GLOBAL(keys[2]) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +int update_keys(__G__ c) + __GDEF + int c; /* byte of plain text */ +{ + GLOBAL(keys[0]) = CRC32(GLOBAL(keys[0]), c, CRY_CRC_TAB); + GLOBAL(keys[1]) = (GLOBAL(keys[1]) + + (GLOBAL(keys[0]) & 0xff)) + * 134775813L + 1; + { + register int keyshift = (int)(GLOBAL(keys[1]) >> 24); + GLOBAL(keys[2]) = CRC32(GLOBAL(keys[2]), keyshift, CRY_CRC_TAB); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +void init_keys(__G__ passwd) + __GDEF + ZCONST char *passwd; /* password string with which to modify keys */ +{ +#ifdef IZ_CRC_BE_OPTIMIZ + if (cry_crctb_p == NULL) { + cry_crctb_p = crytab_init(__G); + } +#endif + GLOBAL(keys[0]) = 305419896L; + GLOBAL(keys[1]) = 591751049L; + GLOBAL(keys[2]) = 878082192L; + while (*passwd != '\0') { + update_keys(__G__ (int)*passwd); + passwd++; + } +} + + +/*********************************************************************** + * Initialize the local copy of the table of precomputed crc32 values. + * Whereas the public crc32-table is optimized for crc32 calculations + * on arrays of bytes, the crypt code needs the crc32 values in an + * byte-order-independent form as 32-bit unsigned numbers. On systems + * with Big-Endian byte order using the optimized crc32 code, this + * requires inverting the byte-order of the values in the + * crypt-crc32-table. + */ +#ifdef IZ_CRC_BE_OPTIMIZ +local z_uint4 near *crytab_init(__G) + __GDEF +{ + int i; + + for (i = 0; i < 256; i++) { + crycrctab[i] = REV_BE(CRC_32_TAB[i]); + } + return crycrctab; +} +#endif + + +#ifdef ZIP + +/*********************************************************************** + * Write encryption header to file zfile using the password passwd + * and the cyclic redundancy check crc. + */ +void crypthead(passwd, crc, zfile) + ZCONST char *passwd; /* password string */ + ulg crc; /* crc of file being encrypted */ + FILE *zfile; /* where to write header */ +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + uch header[RAND_HEAD_LEN]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the + * output of rand() to get less predictability, since rand() is + * often poorly implemented. + */ + if (++calls == 1) { + srand((unsigned)time(NULL) ^ ZCR_SEED2); + } + init_keys(passwd); + for (n = 0; n < RAND_HEAD_LEN-2; n++) { + c = (rand() >> 7) & 0xff; + header[n] = (uch)zencode(c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd); + for (n = 0; n < RAND_HEAD_LEN-2; n++) { + header[n] = (uch)zencode(header[n], t); + } + header[RAND_HEAD_LEN-2] = (uch)zencode((int)(crc >> 16) & 0xff, t); + header[RAND_HEAD_LEN-1] = (uch)zencode((int)(crc >> 24) & 0xff, t); + fwrite(header, 1, RAND_HEAD_LEN, f); +} + + +#ifdef UTIL + +/*********************************************************************** + * Encrypt the zip entry described by z from file source to file dest + * using the password passwd. Return an error code in the ZE_ class. + */ +int zipcloak(z, source, dest, passwd) + struct zlist far *z; /* zip entry to encrypt */ + FILE *source, *dest; /* source and destination files */ + ZCONST char *passwd; /* password string */ +{ + int c; /* input byte */ + int res; /* result code */ + ulg n; /* holds offset and counts size */ + ush flag; /* previous flags */ + int t; /* temporary */ + int ztemp; /* temporary storage for zencode value */ + + /* Set encrypted bit, clear extended local header bit and write local + header to output file */ + if ((n = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; + z->off = n; + flag = z->flg; + z->flg |= 1, z->flg &= ~8; + z->lflg |= 1, z->lflg &= ~8; + z->siz += RAND_HEAD_LEN; + if ((res = putlocal(z, dest)) != ZE_OK) return res; + + /* Initialize keys with password and write random header */ + crypthead(passwd, z->crc, dest); + + /* Skip local header in input file */ + if (fseek(source, (long)((4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext), + SEEK_CUR)) { + return ferror(source) ? ZE_READ : ZE_EOF; + } + + /* Encrypt data */ + for (n = z->siz - RAND_HEAD_LEN; n; n--) { + if ((c = getc(source)) == EOF) { + return ferror(source) ? ZE_READ : ZE_EOF; + } + ztemp = zencode(c, t); + putc(ztemp, dest); + } + /* Skip extended local header in input file if there is one */ + if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { + return ferror(source) ? ZE_READ : ZE_EOF; + } + if (fflush(dest) == EOF) return ZE_TEMP; + + /* Update number of bytes written to output file */ + tempzn += (4 + LOCHEAD) + z->nam + z->ext + z->siz; + + return ZE_OK; +} + +/*********************************************************************** + * Decrypt the zip entry described by z from file source to file dest + * using the password passwd. Return an error code in the ZE_ class. + */ +int zipbare(z, source, dest, passwd) + struct zlist far *z; /* zip entry to encrypt */ + FILE *source, *dest; /* source and destination files */ + ZCONST char *passwd; /* password string */ +{ +#ifdef ZIP10 + int c0 /* byte preceding the last input byte */ +#endif + int c1; /* last input byte */ + ulg offset; /* used for file offsets */ + ulg size; /* size of input data */ + int r; /* size of encryption header */ + int res; /* return code */ + ush flag; /* previous flags */ + + /* Save position and skip local header in input file */ + if ((offset = (ulg)ftell(source)) == (ulg)-1L || + fseek(source, (long)((4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext), + SEEK_CUR)) { + return ferror(source) ? ZE_READ : ZE_EOF; + } + /* Initialize keys with password */ + init_keys(passwd); + + /* Decrypt encryption header, save last two bytes */ + c1 = 0; + for (r = RAND_HEAD_LEN; r; r--) { +#ifdef ZIP10 + c0 = c1; +#endif + if ((c1 = getc(source)) == EOF) { + return ferror(source) ? ZE_READ : ZE_EOF; + } + Trace((stdout, " (%02x)", c1)); + zdecode(c1); + Trace((stdout, " %02x", c1)); + } + Trace((stdout, "\n")); + + /* If last two bytes of header don't match crc (or file time in the + * case of an extended local header), back up and just copy. For + * pkzip 2.0, the check has been reduced to one byte only. + */ +#ifdef ZIP10 + if ((ush)(c0 | (c1<<8)) != + (z->flg & 8 ? (ush) z->tim & 0xffff : (ush)(z->crc >> 16))) { +#else + if ((ush)c1 != (z->flg & 8 ? (ush) z->tim >> 8 : (ush)(z->crc >> 24))) { +#endif + if (fseek(source, offset, SEEK_SET)) { + return ferror(source) ? ZE_READ : ZE_EOF; + } + if ((res = zipcopy(z, source, dest)) != ZE_OK) return res; + return ZE_MISS; + } + + /* Clear encrypted bit and local header bit, and write local header to + output file */ + if ((offset = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; + z->off = offset; + flag = z->flg; + z->flg &= ~9; + z->lflg &= ~9; + z->siz -= RAND_HEAD_LEN; + if ((res = putlocal(z, dest)) != ZE_OK) return res; + + /* Decrypt data */ + for (size = z->siz; size; size--) { + if ((c1 = getc(source)) == EOF) { + return ferror(source) ? ZE_READ : ZE_EOF; + } + zdecode(c1); + putc(c1, dest); + } + /* Skip extended local header in input file if there is one */ + if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { + return ferror(source) ? ZE_READ : ZE_EOF; + } + if (fflush(dest) == EOF) return ZE_TEMP; + + /* Update number of bytes written to output file */ + tempzn += (4 + LOCHEAD) + z->nam + z->ext + z->siz; + + return ZE_OK; +} + + +#else /* !UTIL */ + +/*********************************************************************** + * If requested, encrypt the data in buf, and in any case call fwrite() + * with the arguments to zfwrite(). Return what fwrite() returns. + * + * A bug has been found when encrypting large files. See trees.c + * for details and the fix. + */ +unsigned zfwrite(buf, item_size, nb, f) + zvoid *buf; /* data buffer */ + extent item_size; /* size of each item in bytes */ + extent nb; /* number of items */ + FILE *f; /* file to write to */ +{ + int t; /* temporary */ + + if (key != (char *)NULL) { /* key is the global password pointer */ + ulg size; /* buffer size */ + char *p = (char*)buf; /* steps through buffer */ + + /* Encrypt data in buffer */ + for (size = item_size*(ulg)nb; size != 0; p++, size--) { + *p = (char)zencode(*p, t); + } + } + /* Write the buffer out */ + return fwrite(buf, item_size, nb, f); +} + +#endif /* ?UTIL */ +#endif /* ZIP */ + + +#if (defined(UNZIP) && !defined(FUNZIP)) + +/*********************************************************************** + * Get the password and set up keys for current zipfile member. + * Return PK_ class error. + */ +int decrypt(__G__ passwrd) + __GDEF + ZCONST char *passwrd; +{ + ush b; + int n, r; + uch h[RAND_HEAD_LEN]; + + Trace((stdout, "\n[incnt = %d]: ", GLOBAL(incnt))); + + /* get header once (turn off "encrypted" flag temporarily so we don't + * try to decrypt the same data twice) */ + GLOBAL(pInfo->encrypted) = FALSE; + defer_leftover_input(__G); + for (n = 0; n < RAND_HEAD_LEN; n++) { + b = NEXTBYTE; + h[n] = (uch)b; + Trace((stdout, " (%02x)", h[n])); + } + undefer_input(__G); + GLOBAL(pInfo->encrypted) = TRUE; + + if (GLOBAL(newzip)) { /* this is first encrypted member in this zipfile */ + GLOBAL(newzip) = FALSE; + if (passwrd != (char *)NULL) { /* user gave password on command line */ + if (!GLOBAL(key)) { + if ((GLOBAL(key) = (char *)malloc(strlen(passwrd)+1)) == + (char *)NULL) + return PK_MEM2; + strcpy(GLOBAL(key), passwrd); + GLOBAL(nopwd) = TRUE; /* inhibit password prompting! */ + } + } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */ + free(GLOBAL(key)); + GLOBAL(key) = (char *)NULL; + } + } + + /* if have key already, test it; else allocate memory for it */ + if (GLOBAL(key)) { + if (!testp(__G__ h)) + return PK_COOL; /* existing password OK (else prompt for new) */ + else if (GLOBAL(nopwd)) + return PK_WARN; /* user indicated no more prompting */ + } else if ((GLOBAL(key) = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL) + return PK_MEM2; + + /* try a few keys */ + n = 0; + do { + r = (*G.decr_passwd)((zvoid *)&G, &n, GLOBAL(key), IZ_PWLEN+1, + GLOBAL(zipfn), GLOBAL(filename)); + if (r == IZ_PW_ERROR) { /* internal error in fetch of PW */ + free (GLOBAL(key)); + GLOBAL(key) = NULL; + return PK_MEM2; + } + if (r != IZ_PW_ENTERED) { /* user replied "skip" or "skip all" */ + *GLOBAL(key) = '\0'; /* We try the NIL password, ... */ + n = 0; /* and cancel fetch for this item. */ + } + if (!testp(__G__ h)) + return PK_COOL; + if (r == IZ_PW_CANCELALL) /* User replied "Skip all" */ + GLOBAL(nopwd) = TRUE; /* inhibit any further PW prompt! */ + } while (n > 0); + + return PK_WARN; + +} /* end function decrypt() */ + + + +/*********************************************************************** + * Test the password. Return -1 if bad, 0 if OK. + */ +local int testp(__G__ h) + __GDEF + ZCONST uch *h; +{ + int r; + char *key_translated; + + /* On systems with "obscure" native character coding (e.g., EBCDIC), + * the first test translates the password to the "main standard" + * character coding. */ + +#ifdef STR_TO_CP1 + /* allocate buffer for translated password */ + if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) + return -1; + /* first try, test password translated "standard" charset */ + r = testkey(__G__ h, STR_TO_CP1(key_translated, GLOBAL(key))); +#else /* !STR_TO_CP1 */ + /* first try, test password as supplied on the extractor's host */ + r = testkey(__G__ h, GLOBAL(key)); +#endif /* ?STR_TO_CP1 */ + +#ifdef STR_TO_CP2 + if (r != 0) { +#ifndef STR_TO_CP1 + /* now prepare for second (and maybe third) test with translated pwd */ + if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) + return -1; +#endif + /* second try, password translated to alternate ("standard") charset */ + r = testkey(__G__ h, STR_TO_CP2(key_translated, GLOBAL(key))); +#ifdef STR_TO_CP3 + if (r != 0) + /* third try, password translated to another "standard" charset */ + r = testkey(__G__ h, STR_TO_CP3(key_translated, GLOBAL(key))); +#endif +#ifndef STR_TO_CP1 + free(key_translated); +#endif + } +#endif /* STR_TO_CP2 */ + +#ifdef STR_TO_CP1 + free(key_translated); + if (r != 0) { + /* last resort, test password as supplied on the extractor's host */ + r = testkey(__G__ h, GLOBAL(key)); + } +#endif /* STR_TO_CP1 */ + + return r; + +} /* end function testp() */ + + +local int testkey(__G__ h, key) + __GDEF + ZCONST uch *h; /* decrypted header */ + ZCONST char *key; /* decryption password to test */ +{ + ush b; +#ifdef ZIP10 + ush c; +#endif + int n; + uch *p; + uch hh[RAND_HEAD_LEN]; /* decrypted header */ + + /* set keys and save the encrypted header */ + init_keys(__G__ key); + memcpy(hh, h, RAND_HEAD_LEN); + + /* check password */ + for (n = 0; n < RAND_HEAD_LEN; n++) { + zdecode(hh[n]); + Trace((stdout, " %02x", hh[n])); + } + + Trace((stdout, + "\n lrec.crc= %08lx crec.crc= %08lx pInfo->ExtLocHdr= %s\n", + GLOBAL(lrec.crc32), GLOBAL(pInfo->crc), + GLOBAL(pInfo->ExtLocHdr) ? "true":"false")); + Trace((stdout, " incnt = %d unzip offset into zipfile = %ld\n", + GLOBAL(incnt), + GLOBAL(cur_zipfile_bufstart)+(GLOBAL(inptr)-GLOBAL(inbuf)))); + + /* same test as in zipbare(): */ + +#ifdef ZIP10 /* check two bytes */ + c = hh[RAND_HEAD_LEN-2], b = hh[RAND_HEAD_LEN-1]; + Trace((stdout, + " (c | (b<<8)) = %04x (crc >> 16) = %04x lrec.time = %04x\n", + (ush)(c | (b<<8)), (ush)(GLOBAL(lrec.crc32) >> 16), + ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff)))); + if ((ush)(c | (b<<8)) != (GLOBAL(pInfo->ExtLocHdr) ? + ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff) : + (ush)(GLOBAL(lrec.crc32) >> 16))) + return -1; /* bad */ +#else + b = hh[RAND_HEAD_LEN-1]; + Trace((stdout, " b = %02x (crc >> 24) = %02x (lrec.time >> 8) = %02x\n", + b, (ush)(GLOBAL(lrec.crc32) >> 24), + ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff)); + if (b != (GLOBAL(pInfo->ExtLocHdr) ? + ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff : + (ush)(GLOBAL(lrec.crc32) >> 24))) + return -1; /* bad */ +#endif + /* password OK: decrypt current buffer contents before leaving */ + for (n = (long)GLOBAL(incnt) > GLOBAL(csize) ? + (int)GLOBAL(csize) : GLOBAL(incnt), + p = GLOBAL(inptr); n--; p++) + zdecode(*p); + return 0; /* OK */ + +} /* end function testkey() */ + +#endif /* UNZIP && !FUNZIP */ + +#else /* !CRYPT */ + +/* something "externally visible" to shut up compiler/linker warnings */ +int zcr_dummy; + +#endif /* ?CRYPT */ diff --git a/crypt.h b/crypt.h new file mode 100644 index 0000000..0c533e9 --- /dev/null +++ b/crypt.h @@ -0,0 +1,169 @@ +/* + Copyright (c) 1990-2007 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2005-Feb-10 or later + (the contents of which are also included in (un)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 +*/ +/* + crypt.h (full version) by Info-ZIP. Last revised: [see CR_VERSION_DATE] + + The main encryption/decryption source code for Info-Zip software was + originally written in Europe. To the best of our knowledge, it can + be freely distributed in both source and object forms from any country, + including the USA under License Exception TSU of the U.S. Export + Administration Regulations (section 740.13(e)) of 6 June 2002. + + NOTE on copyright history: + Previous versions of this source package (up to version 2.8) were + not copyrighted and put in the public domain. If you cannot comply + with the Info-Zip LICENSE, you may want to look for one of those + public domain versions. + */ + +#ifndef __crypt_h /* don't include more than once */ +#define __crypt_h + +#ifdef CRYPT +# undef CRYPT +#endif +/* + Logic of selecting "full crypt" code: + a) default behaviour: + - dummy crypt code when compiling UnZipSFX stub, to minimize size + - full crypt code when used to compile Zip, UnZip and fUnZip + b) USE_CRYPT defined: + - always full crypt code + c) NO_CRYPT defined: + - never full crypt code + NO_CRYPT takes precedence over USE_CRYPT + */ +#if defined(NO_CRYPT) +# define CRYPT 0 /* dummy version */ +#else +#if defined(USE_CRYPT) +# define CRYPT 1 /* full version */ +#else +#if !defined(SFX) +# define CRYPT 1 /* full version for zip and main unzip */ +#else +# define CRYPT 0 /* dummy version for unzip sfx */ +#endif +#endif /* ?USE_CRYPT */ +#endif /* ?NO_CRYPT */ + +#if CRYPT +/* full version */ + +#ifdef CR_BETA +# undef CR_BETA /* this is not a beta release */ +#endif + +#define CR_MAJORVER 2 +#define CR_MINORVER 11 +#ifdef CR_BETA +# define CR_BETA_VER "c BETA" +# define CR_VERSION_DATE "05 Jan 2007" /* last real code change */ +#else +# define CR_BETA_VER "" +# define CR_VERSION_DATE "05 Jan 2007" /* last public release date */ +# define CR_RELEASE +#endif + +#ifndef __G /* UnZip only, for now (DLL stuff) */ +# define __G +# define __G__ +# define __GDEF +# define __GPRO void +# define __GPRO__ +#endif + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) +# ifndef DOS_OS2_W32 +# define DOS_OS2_W32 +# endif +#endif + +#if defined(DOS_OS2_W32) || defined(__human68k__) +# ifndef DOS_H68_OS2_W32 +# define DOS_H68_OS2_W32 +# endif +#endif + +#if defined(VM_CMS) || defined(MVS) +# ifndef CMS_MVS +# define CMS_MVS +# endif +#endif + +/* To allow combining of Zip and UnZip static libraries in a single binary, + * the Zip and UnZip versions of the crypt core functions have to be named + * differently. + */ +#ifdef ZIP +# ifdef REALLY_SHORT_SYMS +# define decrypt_byte zdcrby +# else +# define decrypt_byte zp_decrypt_byte +# endif +# define update_keys zp_update_keys +# define init_keys zp_init_keys +#else /* !ZIP */ +# ifdef REALLY_SHORT_SYMS +# define decrypt_byte dcrbyt +# endif +#endif /* ?ZIP */ + +#define IZ_PWLEN 80 /* input buffer size for reading encryption key */ +#ifndef PWLEN /* for compatibility with previous zcrypt release... */ +# define PWLEN IZ_PWLEN +#endif +#define RAND_HEAD_LEN 12 /* length of encryption random header */ + +/* the crc_32_tab array has to be provided externally for the crypt calculus */ + +/* encode byte c, using temp t. Warning: c must not have side effects. */ +#define zencode(c,t) (t=decrypt_byte(__G), update_keys(c), t^(c)) + +/* decode byte c in place */ +#define zdecode(c) update_keys(__G__ c ^= decrypt_byte(__G)) + +int decrypt_byte OF((__GPRO)); +int update_keys OF((__GPRO__ int c)); +void init_keys OF((__GPRO__ ZCONST char *passwd)); + +#ifdef ZIP + void crypthead OF((ZCONST char *, ulg, FILE *)); +# ifdef UTIL + int zipcloak OF((struct zlist far *, FILE *, FILE *, ZCONST char *)); + int zipbare OF((struct zlist far *, FILE *, FILE *, ZCONST char *)); +# else + unsigned zfwrite OF((zvoid *, extent, extent, FILE *)); + extern char *key; +# endif +#endif /* ZIP */ + +#if (defined(UNZIP) && !defined(FUNZIP)) + int decrypt OF((__GPRO__ ZCONST char *passwrd)); +#endif + +#ifdef FUNZIP + extern int encrypted; +# ifdef NEXTBYTE +# undef NEXTBYTE +# endif +# define NEXTBYTE \ + (encrypted? update_keys(__G__ getc(G.in)^decrypt_byte(__G)) : getc(G.in)) +#endif /* FUNZIP */ + +#else /* !CRYPT */ +/* dummy version */ + +#define zencode +#define zdecode + +#define zfwrite fwrite + +#endif /* ?CRYPT */ +#endif /* !__crypt_h */ diff --git a/ebcdic.h b/ebcdic.h new file mode 100644 index 0000000..3aa587e --- /dev/null +++ b/ebcdic.h @@ -0,0 +1,301 @@ +/* + Copyright (c) 1990-2008 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 +*/ +/*--------------------------------------------------------------------------- + + ebcdic.h + + The CECP 1047 (Extended de-facto EBCDIC) <-> ISO 8859-1 conversion tables, + from ftp://aix1.segi.ulg.ac.be/pub/docs/iso8859/iso8859.networking + + NOTES: + (OS/390 port 12/97) + These table no longer represent the standard mappings (for example in the + OS/390 iconv utility). In order to follow current standards I remapped + ebcdic x0a to ascii x15 and + ebcdic x85 to ascii x25 (and vice-versa) + Without these changes, newlines in auto-convert text files appeared + as literal \045. + I'm not sure what effect this remap would have on the MVS and CMS ports, so + I ifdef'd these changes. Hopefully these ifdef's can be removed when the + MVS/CMS folks test the new mappings. + + Christian Spieler , 27-Apr-1998 + The problem mentioned by Paul von Behren was already observed previously + on VM/CMS, during the preparation of the CMS&MVS port of UnZip 5.20 in + 1996. At that point, the ebcdic tables were not changed since they seemed + to be an adopted standard (to my knowledge, these tables are still used + as presented in mainfraime KERMIT). Instead, the "end-of-line" conversion + feature of Zip's and UnZip's "text-translation" mode was used to force + correct mappings between ASCII and EBCDIC newline markers. + Before interchanging the ASCII mappings of the EBCDIC control characters + "NL" 0x25 and "LF" 0x15 according to the OS/390 setting, we have to + make sure that EBCDIC 0x15 is never used as line termination. + + ---------------------------------------------------------------------------*/ + +#ifndef __ebcdic_h /* prevent multiple inclusions */ +#define __ebcdic_h + + +#ifndef ZCONST +# define ZCONST const +#endif + +#ifdef EBCDIC +#ifndef MTS /* MTS uses a slightly "special" EBCDIC code page */ + +ZCONST uch ebcdic[] = { + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, /* 00 - 07 */ +#ifdef OS390 + 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ +#else + 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ +#endif + 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, /* 10 - 17 */ + 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ + 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, /* 20 - 27 */ + 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, /* 28 - 2F */ + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, /* 30 - 37 */ + 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, /* 38 - 3F */ + 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, /* 40 - 47 */ + 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, /* 48 - 4F */ + 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, /* 50 - 57 */ + 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, /* 58 - 5F */ + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 60 - 67 */ + 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* 68 - 6F */ + 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, /* 70 - 77 */ + 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, /* 78 - 7F */ +#ifdef OS390 + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17, /* 80 - 87 */ +#else + 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, /* 80 - 87 */ +#endif + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B, /* 88 - 8F */ + 0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08, /* 90 - 97 */ + 0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF, /* 98 - 9F */ + 0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5, /* A0 - A7 */ + 0xBB, 0xB4, 0x9A, 0x8A, 0xB0, 0xCA, 0xAF, 0xBC, /* A8 - AF */ + 0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3, /* B0 - B7 */ + 0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB, /* B8 - BF */ + 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68, /* C0 - C7 */ + 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* C8 - CF */ + 0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF, /* D0 - D7 */ + 0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xBA, 0xAE, 0x59, /* D8 - DF */ + 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48, /* E0 - E7 */ + 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* E8 - EF */ + 0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1, /* F0 - F7 */ + 0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF /* F8 - FF */ +}; + +#if (defined(ZIP) || CRYPT) +ZCONST uch ascii[] = { + 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, /* 00 - 07 */ + 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ +#ifdef OS390 + 0x10, 0x11, 0x12, 0x13, 0x9D, 0x0A, 0x08, 0x87, /* 10 - 17 */ +#else + 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, /* 10 - 17 */ +#endif + 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ +#ifdef OS390 + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1B, /* 20 - 27 */ +#else + 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, /* 20 - 27 */ +#endif + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, /* 28 - 2F */ + 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30 - 37 */ + 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, /* 38 - 3F */ + 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, /* 40 - 47 */ + 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, /* 48 - 4F */ + 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, /* 50 - 57 */ + 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E, /* 58 - 5F */ + 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, /* 60 - 67 */ + 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, /* 68 - 6F */ + 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, /* 70 - 77 */ + 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, /* 78 - 7F */ + 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80 - 87 */ + 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1, /* 88 - 8F */ + 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, /* 90 - 97 */ + 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4, /* 98 - 9F */ + 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* A0 - A7 */ + 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE, /* A8 - AF */ + 0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, /* B0 - B7 */ + 0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7, /* B8 - BF */ + 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* C0 - C7 */ + 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, /* C8 - CF */ + 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, /* D0 - D7 */ + 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF, /* D8 - DF */ + 0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* E0 - E7 */ + 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5, /* E8 - EF */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* F0 - F7 */ + 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F /* F8 - FF */ +}; +#endif /* ZIP || CRYPT */ + +#else /* MTS */ + +/* + * This is the MTS ASCII->EBCDIC translation table. It provides a 1-1 + * translation from ISO 8859/1 8-bit ASCII to IBM Code Page 37 EBCDIC. + */ + +ZCONST uch ebcdic[] = { + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, /* 00 - 07 */ + 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ + 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, /* 10 - 17 */ + 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ + 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, /* 20 - 27 */ + 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, /* 28 - 2F */ + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, /* 30 - 37 */ + 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, /* 38 - 3F */ + 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, /* 40 - 47 */ + 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, /* 48 - 4F */ + 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, /* 50 - 57 */ + 0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D, /* 58 - 5F */ + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 60 - 67 */ + 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* 68 - 6F */ + 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, /* 70 - 77 */ + 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, /* 78 - 7F */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, /* 80 - 87 */ + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B, /* 88 - 8F */ + 0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08, /* 90 - 97 */ + 0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF, /* 98 - 9F */ + 0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5, /* A0 - A7 */ + 0xBD, 0xB4, 0x9A, 0x8A, 0x5F, 0xCA, 0xAF, 0xBC, /* A8 - AF */ + 0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3, /* B0 - B7 */ + 0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB, /* B8 - BF */ + 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68, /* C0 - C7 */ + 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77, /* C8 - CF */ + 0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF, /* D0 - D7 */ + 0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xAD, 0xAE, 0x59, /* D8 - DF */ + 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48, /* E0 - E7 */ + 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57, /* E8 - EF */ + 0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1, /* F0 - F7 */ + 0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF /* F8 - FF */ +}; + +#if (defined(ZIP) || CRYPT) +ZCONST uch ascii[] = { + 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, /* 00 - 07 */ + 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 08 - 0F */ + 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, /* 10 - 17 */ + 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, /* 18 - 1F */ + 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, /* 20 - 27 */ + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, /* 28 - 2F */ + 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, /* 30 - 37 */ + 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, /* 38 - 3F */ + 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5, /* 40 - 47 */ + 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, /* 48 - 4F */ + 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, /* 50 - 57 */ + 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC, /* 58 - 5F */ + 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5, /* 60 - 67 */ + 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, /* 68 - 6F */ + 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, /* 70 - 77 */ + 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, /* 78 - 7F */ + 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 80 - 87 */ + 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1, /* 88 - 8F */ + 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, /* 90 - 97 */ + 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4, /* 98 - 9F */ + 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /* A0 - A7 */ + 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE, /* A8 - AF */ + 0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC, /* B0 - B7 */ + 0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7, /* B8 - BF */ + 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* C0 - C7 */ + 0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, /* C8 - CF */ + 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, /* D0 - D7 */ + 0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF, /* D8 - DF */ + 0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, /* E0 - E7 */ + 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5, /* E8 - EF */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* F0 - F7 */ + 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F /* F8 - FF */ +}; +#endif /* ZIP || CRYPT */ + +#endif /* ?MTS */ +#endif /* EBCDIC */ + +/*--------------------------------------------------------------------------- + + The following conversion tables translate between IBM PC CP 850 + (OEM codepage) and the "Western Europe & America" Windows codepage 1252. + The Windows codepage 1252 contains the ISO 8859-1 "Latin 1" codepage, + with some additional printable characters in the range (0x80 - 0x9F), + that is reserved to control codes in the ISO 8859-1 character table. + + The ISO <--> OEM conversion tables were constructed with the help + of the WIN32 (Win16?) API's OemToAnsi() and AnsiToOem() conversion + functions and have been checked against the CP850 and LATIN1 tables + provided in the MS-Kermit 3.14 distribution. + + ---------------------------------------------------------------------------*/ + +#ifdef IZ_ISO2OEM_ARRAY +ZCONST uch Far iso2oem_850[] = { + 0x3F, 0x3F, 0x27, 0x9F, 0x22, 0x2E, 0xC5, 0xCE, /* 80 - 87 */ + 0x5E, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F, /* 88 - 8F */ + 0x3F, 0x27, 0x27, 0x22, 0x22, 0x07, 0x2D, 0x2D, /* 90 - 97 */ + 0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59, /* 98 - 9F */ + 0xFF, 0xAD, 0xBD, 0x9C, 0xCF, 0xBE, 0xDD, 0xF5, /* A0 - A7 */ + 0xF9, 0xB8, 0xA6, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE, /* A8 - AF */ + 0xF8, 0xF1, 0xFD, 0xFC, 0xEF, 0xE6, 0xF4, 0xFA, /* B0 - B7 */ + 0xF7, 0xFB, 0xA7, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8, /* B8 - BF */ + 0xB7, 0xB5, 0xB6, 0xC7, 0x8E, 0x8F, 0x92, 0x80, /* C0 - C7 */ + 0xD4, 0x90, 0xD2, 0xD3, 0xDE, 0xD6, 0xD7, 0xD8, /* C8 - CF */ + 0xD1, 0xA5, 0xE3, 0xE0, 0xE2, 0xE5, 0x99, 0x9E, /* D0 - D7 */ + 0x9D, 0xEB, 0xE9, 0xEA, 0x9A, 0xED, 0xE8, 0xE1, /* D8 - DF */ + 0x85, 0xA0, 0x83, 0xC6, 0x84, 0x86, 0x91, 0x87, /* E0 - E7 */ + 0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B, /* E8 - EF */ + 0xD0, 0xA4, 0x95, 0xA2, 0x93, 0xE4, 0x94, 0xF6, /* F0 - F7 */ + 0x9B, 0x97, 0xA3, 0x96, 0x81, 0xEC, 0xE7, 0x98 /* F8 - FF */ +}; +#endif /* IZ_ISO2OEM_ARRAY */ + +#ifdef IZ_OEM2ISO_ARRAY +ZCONST uch Far oem2iso_850[] = { + 0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7, /* 80 - 87 */ + 0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5, /* 88 - 8F */ + 0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9, /* 90 - 97 */ + 0xFF, 0xD6, 0xDC, 0xF8, 0xA3, 0xD8, 0xD7, 0x83, /* 98 - 9F */ + 0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA, /* A0 - A7 */ + 0xBF, 0xAE, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB, /* A8 - AF */ + 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xC1, 0xC2, 0xC0, /* B0 - B7 */ + 0xA9, 0xA6, 0xA6, 0x2B, 0x2B, 0xA2, 0xA5, 0x2B, /* B8 - BF */ + 0x2B, 0x2D, 0x2D, 0x2B, 0x2D, 0x2B, 0xE3, 0xC3, /* C0 - C7 */ + 0x2B, 0x2B, 0x2D, 0x2D, 0xA6, 0x2D, 0x2B, 0xA4, /* C8 - CF */ + 0xF0, 0xD0, 0xCA, 0xCB, 0xC8, 0x69, 0xCD, 0xCE, /* D0 - D7 */ + 0xCF, 0x2B, 0x2B, 0xA6, 0x5F, 0xA6, 0xCC, 0xAF, /* D8 - DF */ + 0xD3, 0xDF, 0xD4, 0xD2, 0xF5, 0xD5, 0xB5, 0xFE, /* E0 - E7 */ + 0xDE, 0xDA, 0xDB, 0xD9, 0xFD, 0xDD, 0xAF, 0xB4, /* E8 - EF */ + 0xAD, 0xB1, 0x3D, 0xBE, 0xB6, 0xA7, 0xF7, 0xB8, /* F0 - F7 */ + 0xB0, 0xA8, 0xB7, 0xB9, 0xB3, 0xB2, 0xA6, 0xA0 /* F8 - FF */ +}; +#endif /* IZ_OEM2ISO_ARRAY */ + +/* The following pointers to the OEM<-->ISO translation tables are used + by the translation code portions. They may get initialized at program + startup to point to the matching static translation tables, or to NULL + to disable OEM-ISO translation. + The compile-time initialization used here provides the backward compatible + setting, as can be found in UnZip 5.52 and earlier. + In case this mechanism will ever get used on a multithreading system that + allows different codepage setups for concurrently running threads, these + pointers should get moved into UnZip's thread-safe global data structure. + */ +#ifdef IZ_ISO2OEM_ARRAY +ZCONST uch Far *iso2oem = iso2oem_850; /* backward compatibility default */ +#endif /* IZ_ISO2OEM_ARRAY */ +#ifdef IZ_OEM2ISO_ARRAY +ZCONST uch Far *oem2iso = oem2iso_850; /* backward compatibility default */ +#endif /* IZ_OEM2ISO_ARRAY */ + +#if defined(THEOS) || defined(THEOS_SUPPORT) +# include "theos/charconv.h" +#endif + +#endif /* __ebcdic_h */ diff --git a/envargs.c b/envargs.c new file mode 100644 index 0000000..f0a230d --- /dev/null +++ b/envargs.c @@ -0,0 +1,317 @@ +/* + Copyright (c) 1990-2005 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 +*/ +/*----------------------------------------------------------------* + | envargs - add default options from environment to command line + |---------------------------------------------------------------- + | Author: Bill Davidsen, original 10/13/91, revised 23 Oct 1991. + | This program is in the public domain. + |---------------------------------------------------------------- + | Minor program notes: + | 1. Yes, the indirection is a tad complex + | 2. Parentheses were added where not needed in some cases + | to make the action of the code less obscure. + |---------------------------------------------------------------- + | UnZip notes: 24 May 92 ("v1.4"): + | 1. #include "unzip.h" for prototypes (24 May 92) + | 2. changed ch to type char (24 May 92) + | 3. added an ifdef to avoid Borland warnings (24 May 92) + | 4. included Rich Wales' mksargs() routine (for MS-DOS, maybe + | OS/2? NT?) (4 Dec 93) + | 5. added alternate-variable string envstr2 (21 Apr 94) + | 6. added support for quoted arguments (6 Jul 96) + *----------------------------------------------------------------*/ + + +#define __ENVARGS_C /* identifies this source module */ +#define UNZIP_INTERNAL +#include "unzip.h" + +#ifdef __EMX__ /* emx isspace() returns TRUE on extended ASCII !! */ +# define ISspace(c) ((c) & 0x80 ? 0 : isspace((unsigned)c)) +#else +# define ISspace(c) isspace((unsigned)c) +#endif /* ?__EMX__ */ + +#if (!defined(RISCOS) && (!defined(MODERN) || defined(NO_STDLIB_H))) +extern char *getenv(); +#endif +static int count_args OF((ZCONST char *)); + + +/* envargs() returns PK-style error code */ + +int envargs(Pargc, Pargv, envstr, envstr2) + int *Pargc; + char ***Pargv; + ZCONST char *envstr, *envstr2; +{ + char *envptr; /* value returned by getenv */ + char *bufptr; /* copy of env info */ + int argc = 0; /* internal arg count */ + register int ch; /* spare temp value */ + char **argv; /* internal arg vector */ + char **argvect; /* copy of vector address */ + + /* see if anything in the environment */ + if ((envptr = getenv(envstr)) != (char *)NULL) /* usual var */ + while (ISspace(*envptr)) /* must discard leading spaces */ + envptr++; + if (envptr == (char *)NULL || *envptr == '\0') + if ((envptr = getenv(envstr2)) != (char *)NULL) /* alternate var */ + while (ISspace(*envptr)) + envptr++; + if (envptr == (char *)NULL || *envptr == '\0') + return PK_OK; + + bufptr = malloc(1 + strlen(envptr)); + if (bufptr == (char *)NULL) + return PK_MEM; +#if ((defined(WIN32) || defined(WINDLL)) && !defined(_WIN32_WCE)) +# ifdef WIN32 + if (IsWinNT()) { + /* SPC: don't know codepage of 'real' WinNT console */ + strcpy(bufptr, envptr); + } else { + /* Win95 environment is DOS and uses OEM character coding */ + OEM_TO_INTERN(envptr, bufptr); + } +# else /* !WIN32 */ + /* DOS (Win 3.x) environment uses OEM codepage */ + OEM_TO_INTERN(envptr, bufptr); +# endif +#else /* !((WIN32 || WINDLL) && !_WIN32_WCE) */ + strcpy(bufptr, envptr); +#endif /* ?((WIN32 || WINDLL) && !_WIN32_WCE) */ + + /* count the args so we can allocate room for them */ + argc = count_args(bufptr); + /* allocate a vector large enough for all args */ + argv = (char **)malloc((argc + *Pargc + 1) * sizeof(char *)); + if (argv == (char **)NULL) { + free(bufptr); + return PK_MEM; + } + argvect = argv; + + /* copy the program name first, that's always true */ + *(argv++) = *((*Pargv)++); + + /* copy the environment args next, may be changed */ + do { +#if defined(AMIGA) || defined(UNIX) + if (*bufptr == '"') { + char *argstart = ++bufptr; + + *(argv++) = argstart; + for (ch = *bufptr; ch != '\0' && ch != '\"'; + ch = *PREINCSTR(bufptr)) + if (ch == '\\' && bufptr[1] != '\0') + ++bufptr; /* advance to char after backslash */ + if (ch != '\0') + *(bufptr++) = '\0'; /* overwrite trailing " */ + + /* remove escape characters */ + while ((argstart = MBSCHR(argstart, '\\')) != (char *)NULL) { + strcpy(argstart, argstart + 1); + if (*argstart) + ++argstart; + } + } else { + *(argv++) = bufptr; + while ((ch = *bufptr) != '\0' && !ISspace(ch)) + INCSTR(bufptr); + if (ch != '\0') + *(bufptr++) = '\0'; + } +#else +#ifdef DOS_FLX_NLM_OS2_W32 + /* we do not support backslash-quoting of quotes in quoted + * strings under DOS_FLX_NLM_OS2_W32, because backslashes are + * directory separators and double quotes are illegal in filenames */ + if (*bufptr == '"') { + *(argv++) = ++bufptr; + while ((ch = *bufptr) != '\0' && ch != '\"') + INCSTR(bufptr); + if (ch != '\0') + *(bufptr++) = '\0'; + } else { + *(argv++) = bufptr; + while ((ch = *bufptr) != '\0' && !ISspace(ch)) + INCSTR(bufptr); + if (ch != '\0') + *(bufptr++) = '\0'; + } +#else + *(argv++) = bufptr; + while ((ch = *bufptr) != '\0' && !ISspace(ch)) + INCSTR(bufptr); + if (ch != '\0') + *(bufptr++) = '\0'; +#endif /* ?DOS_FLX_NLM_OS2_W32 */ +#endif /* ?(AMIGA || UNIX) */ + while ((ch = *bufptr) != '\0' && ISspace(ch)) + INCSTR(bufptr); + } while (ch); + + /* now save old argc and copy in the old args */ + argc += *Pargc; + while (--(*Pargc)) + *(argv++) = *((*Pargv)++); + + /* finally, add a NULL after the last arg, like Unix */ + *argv = (char *)NULL; + + /* save the values and return, indicating succes */ + *Pargv = argvect; + *Pargc = argc; + + return PK_OK; +} + + + +static int count_args(s) + ZCONST char *s; +{ + int count = 0; + char ch; + + do { + /* count and skip args */ + ++count; +#if defined(AMIGA) || defined(UNIX) + if (*s == '\"') { + for (ch = *PREINCSTR(s); ch != '\0' && ch != '\"'; + ch = *PREINCSTR(s)) + if (ch == '\\' && s[1] != '\0') + ++s; + if (*s) + ++s; /* trailing quote */ + } else +#else +#ifdef DOS_FLX_NLM_OS2_W32 + if (*s == '\"') { + ++s; /* leading quote */ + while ((ch = *s) != '\0' && ch != '\"') + INCSTR(s); + if (*s) + ++s; /* trailing quote */ + } else +#endif /* DOS_FLX_NLM_OS2_W32 */ +#endif /* ?(AMIGA || UNIX) */ + while ((ch = *s) != '\0' && !ISspace(ch)) /* note else-clauses above */ + INCSTR(s); + while ((ch = *s) != '\0' && ISspace(ch)) + INCSTR(s); + } while (ch); + + return count; +} + + + +#ifdef TEST + +int main(argc, argv) + int argc; + char **argv; +{ + int err; + + printf("Orig argv: %p\n", argv); + dump_args(argc, argv); + if ((err = envargs(&argc, &argv, "ENVTEST")) != PK_OK) { + perror("envargs: cannot get memory for arguments"); + EXIT(err); + } + printf(" New argv: %p\n", argv); + dump_args(argc, argv); +} + + + +void dump_args(argc, argv) + int argc; + char *argv[]; +{ + int i; + + printf("\nDump %d args:\n", argc); + for (i = 0; i < argc; ++i) + printf("%3d %s\n", i, argv[i]); +} + +#endif /* TEST */ + + + +#ifdef MSDOS /* DOS_OS2? DOS_OS2_W32? */ + +/* + * void mksargs(int *argcp, char ***argvp) + * + * Substitutes the extended command line argument list produced by + * the MKS Korn Shell in place of the command line info from DOS. + * + * The MKS shell gets around DOS's 128-byte limit on the length of + * a command line by passing the "real" command line in the envi- + * ronment. The "real" arguments are flagged by prepending a tilde + * (~) to each one. + * + * This "mksargs" routine creates a new argument list by scanning + * the environment from the beginning, looking for strings begin- + * ning with a tilde character. The new list replaces the original + * "argv" (pointed to by "argvp"), and the number of arguments + * in the new list replaces the original "argc" (pointed to by + * "argcp"). + * + * Rich Wales + */ +void mksargs(argcp, argvp) + int *argcp; + char ***argvp; +{ +#ifndef MSC /* declared differently in MSC 7.0 headers, at least */ +#ifndef __WATCOMC__ + extern char **environ; /* environment */ +#endif +#endif + char **envp; /* pointer into environment */ + char **newargv; /* new argument list */ + char **argp; /* pointer into new arg list */ + int newargc; /* new argument count */ + + /* sanity check */ + if (environ == NULL || argcp == NULL || argvp == NULL || *argvp == NULL) + return; + + /* find out how many environment arguments there are */ + for (envp = environ, newargc = 0; + *envp != NULL && (*envp)[0] == '~'; + envp++, newargc++) + ; + if (newargc == 0) + return; /* no environment arguments */ + + /* set up new argument list */ + newargv = (char **) malloc(sizeof(char **) * (newargc+1)); + if (newargv == NULL) + return; /* malloc failed */ + + for (argp = newargv, envp = environ; *envp != NULL && (*envp)[0] == '~'; + *argp++ = &(*envp++)[1]) + ; + *argp = NULL; /* null-terminate the list */ + + /* substitute new argument list in place of old one */ + *argcp = newargc; + *argvp = newargv; +} + +#endif /* MSDOS */ diff --git a/explode.c b/explode.c new file mode 100644 index 0000000..3b558c2 --- /dev/null +++ b/explode.c @@ -0,0 +1,618 @@ +/* + Copyright (c) 1990-2007 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2007-Mar-04 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 +*/ +/* explode.c -- by Mark Adler + version c17d, 01 December 2007 */ + + +/* Copyright history: + - Starting with UnZip 5.41 of 16-April-2000, this source file + is covered by the Info-Zip LICENSE cited above. + - Prior versions of this source file, found in UnZip source packages + up to UnZip 5.40, were put in the public domain. + The original copyright note by Mark Adler was: + "You can do whatever you like with this source file, + though I would prefer that if you modify it and + redistribute it that you include comments to that effect + with your name and the date. Thank you." + + History: + vers date who what + ---- --------- -------------- ------------------------------------ + c1 30 Mar 92 M. Adler explode that uses huft_build from inflate + (this gives over a 70% speed improvement + over the original unimplode.c, which + decoded a bit at a time) + c2 4 Apr 92 M. Adler fixed bug for file sizes a multiple of 32k. + c3 10 Apr 92 M. Adler added a little memory tracking if DEBUG + c4 11 Apr 92 M. Adler added NOMEMCPY do kill use of memcpy() + c5 21 Apr 92 M. Adler added the WSIZE #define to allow reducing + the 32K window size for specialized + applications. + c6 31 May 92 M. Adler added typecasts to eliminate some warnings + c7 27 Jun 92 G. Roelofs added more typecasts. + c8 17 Oct 92 G. Roelofs changed ULONG/UWORD/byte to ulg/ush/uch. + c9 19 Jul 93 J. Bush added more typecasts (to return values); + made l[256] array static for Amiga. + c10 8 Oct 93 G. Roelofs added used_csize for diagnostics; added + buf and unshrink arguments to flush(); + undef'd various macros at end for Turbo C; + removed NEXTBYTE macro (now in unzip.h) + and bytebuf variable (not used); changed + memset() to memzero(). + c11 9 Jan 94 M. Adler fixed incorrect used_csize calculation. + c12 9 Apr 94 G. Roelofs fixed split comments on preprocessor lines + to avoid bug in Encore compiler. + c13 25 Aug 94 M. Adler fixed distance-length comment (orig c9 fix) + c14 22 Nov 95 S. Maxwell removed unnecessary "static" on auto array + c15 6 Jul 96 W. Haidinger added ulg typecasts to flush() calls. + c16 8 Feb 98 C. Spieler added ZCONST modifiers to const tables + and #ifdef DEBUG around debugging code. + c16b 25 Mar 98 C. Spieler modified DLL code for slide redirection. + c16d 05 Jul 99 C. Spieler take care of flush() return values and + stop processing in case of errors + c17 04 Feb 01 C. Spieler reorganized code to reduce repetitions + of large code parts; adapted huft decoding + to the changes in inflate's huft_build() + due to support of deflate64; fixed memory + leaks (huft tables were not free'd when + get_tree() failed). + c17b 16 Feb 02 C. Spieler changed type of the "extra lengths" array + "extra" from ush into uch (to save space) + c17c 10 Aug 04 NN file sizes use zoff_t. + c17d 01 Dec 07 C. Spieler type for file sizes changed from zoff_t + into zusz_t. + */ + + +/* + Explode imploded (PKZIP method 6 compressed) data. This compression + method searches for as much of the current string of bytes (up to a length + of ~320) in the previous 4K or 8K bytes. If it doesn't find any matches + (of at least length 2 or 3), it codes the next byte. Otherwise, it codes + the length of the matched string and its distance backwards from the + current position. Single bytes ("literals") are preceded by a one (a + single bit) and are either uncoded (the eight bits go directly into the + compressed stream for a total of nine bits) or Huffman coded with a + supplied literal code tree. If literals are coded, then the minimum match + length is three, otherwise it is two. + + There are therefore four kinds of imploded streams: 8K search with coded + literals (min match = 3), 4K search with coded literals (min match = 3), + 8K with uncoded literals (min match = 2), and 4K with uncoded literals + (min match = 2). The kind of stream is identified in two bits of a + general purpose bit flag that is outside of the compressed stream. + + Distance-length pairs for matched strings are preceded by a zero bit (to + distinguish them from literals) and are always coded. The distance comes + first and is either the low six (4K) or low seven (8K) bits of the + distance (uncoded), followed by the high six bits of the distance coded. + Then the length is six bits coded (0..63 + min match length), and if the + maximum such length is coded, then it's followed by another eight bits + (uncoded) to be added to the coded length. This gives a match length + range of 2..320 or 3..321 bytes. + + The literal, length, and distance codes are all represented in a slightly + compressed form themselves. What is sent are the lengths of the codes for + each value, which is sufficient to construct the codes. Each byte of the + code representation is the code length (the low four bits representing + 1..16), and the number of values sequentially with that length (the high + four bits also representing 1..16). There are 256 literal code values (if + literals are coded), 64 length code values, and 64 distance code values, + in that order at the beginning of the compressed stream. Each set of code + values is preceded (redundantly) with a byte indicating how many bytes are + in the code description that follows, in the range 1..256. + + The codes themselves are decoded using tables made by huft_build() from + the bit lengths. That routine and its comments are in the inflate.c + module. + */ + +#define __EXPLODE_C /* identifies this source module */ +#define UNZIP_INTERNAL +#include "unzip.h" /* must supply slide[] (uch) array and NEXTBYTE macro */ + +#ifndef WSIZE +# define WSIZE 0x8000 /* window size--must be a power of two, and */ +#endif /* at least 8K for zip's implode method */ + +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) +# define wszimpl (unsigned)(G._wsize) +#else +# if defined(USE_DEFLATE64) && defined(INT_16BIT) +# define wszimpl (unsigned)(WSIZE>>1) +# else /* !(USE_DEFLATE64 && INT_16BIT) */ +# define wszimpl WSIZE +# endif /* !(USE_DEFLATE64 && INT_16BIT) */ +#endif + +/* routines here */ +static int get_tree OF((__GPRO__ unsigned *l, unsigned n)); +static int explode_lit OF((__GPRO__ struct huft *tb, struct huft *tl, + struct huft *td, unsigned bb, unsigned bl, + unsigned bd, unsigned bdl)); +static int explode_nolit OF((__GPRO__ struct huft *tl, struct huft *td, + unsigned bl, unsigned bd, unsigned bdl)); +int explode OF((__GPRO)); + + +/* The implode algorithm uses a sliding 4K or 8K byte window on the + uncompressed stream to find repeated byte strings. This is implemented + here as a circular buffer. The index is updated simply by incrementing + and then and'ing with 0x0fff (4K-1) or 0x1fff (8K-1). Here, the 32K + buffer of inflate is used, and it works just as well to always have + a 32K circular buffer, so the index is anded with 0x7fff. This is + done to allow the window to also be used as the output buffer. */ +/* This must be supplied in an external module useable like "uch slide[8192];" + or "uch *slide;", where the latter would be malloc'ed. In unzip, slide[] + is actually a 32K area for use by inflate, which uses a 32K sliding window. + */ + + +#define INVALID_CODE 99 +#define IS_INVALID_CODE(c) ((c) == INVALID_CODE) + +/* Tables for length and distance */ +static ZCONST ush cplen2[] = + {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65}; +static ZCONST ush cplen3[] = + {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66}; +static ZCONST uch extra[] = + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8}; +static ZCONST ush cpdist4[] = + {1, 65, 129, 193, 257, 321, 385, 449, 513, 577, 641, 705, + 769, 833, 897, 961, 1025, 1089, 1153, 1217, 1281, 1345, 1409, 1473, + 1537, 1601, 1665, 1729, 1793, 1857, 1921, 1985, 2049, 2113, 2177, + 2241, 2305, 2369, 2433, 2497, 2561, 2625, 2689, 2753, 2817, 2881, + 2945, 3009, 3073, 3137, 3201, 3265, 3329, 3393, 3457, 3521, 3585, + 3649, 3713, 3777, 3841, 3905, 3969, 4033}; +static ZCONST ush cpdist8[] = + {1, 129, 257, 385, 513, 641, 769, 897, 1025, 1153, 1281, + 1409, 1537, 1665, 1793, 1921, 2049, 2177, 2305, 2433, 2561, 2689, + 2817, 2945, 3073, 3201, 3329, 3457, 3585, 3713, 3841, 3969, 4097, + 4225, 4353, 4481, 4609, 4737, 4865, 4993, 5121, 5249, 5377, 5505, + 5633, 5761, 5889, 6017, 6145, 6273, 6401, 6529, 6657, 6785, 6913, + 7041, 7169, 7297, 7425, 7553, 7681, 7809, 7937, 8065}; + + +/* Macros for inflate() bit peeking and grabbing. + The usage is: + + NEEDBITS(j) + x = b & mask_bits[j]; + DUMPBITS(j) + + where NEEDBITS makes sure that b has at least j bits in it, and + DUMPBITS removes the bits from b. The macros use the variable k + for the number of bits in b. Normally, b and k are register + variables for speed. + */ + +#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<>=(n);k-=(n);} + +#define DECODEHUFT(htab, bits, mask) {\ + NEEDBITS((unsigned)(bits))\ + t = (htab) + ((~(unsigned)b)&(mask));\ + while (1) {\ + DUMPBITS(t->b)\ + if ((e=t->e) <= 32) break;\ + if (IS_INVALID_CODE(e)) return 1;\ + e &= 31;\ + NEEDBITS(e)\ + t = t->v.t + ((~(unsigned)b)&mask_bits[e]);\ + }\ +} + + +static int get_tree(__G__ l, n) + __GDEF +unsigned *l; /* bit lengths */ +unsigned n; /* number expected */ +/* Get the bit lengths for a code representation from the compressed + stream. If get_tree() returns 4, then there is an error in the data. + Otherwise zero is returned. */ +{ + unsigned i; /* bytes remaining in list */ + unsigned k; /* lengths entered */ + unsigned j; /* number of codes */ + unsigned b; /* bit length for those codes */ + + + /* get bit lengths */ + i = NEXTBYTE + 1; /* length/count pairs to read */ + k = 0; /* next code */ + do { + b = ((j = NEXTBYTE) & 0xf) + 1; /* bits in code (1..16) */ + j = ((j & 0xf0) >> 4) + 1; /* codes with those bits (1..16) */ + if (k + j > n) + return 4; /* don't overflow l[] */ + do { + l[k++] = b; + } while (--j); + } while (--i); + return k != n ? 4 : 0; /* should have read n of them */ +} + + + +static int explode_lit(__G__ tb, tl, td, bb, bl, bd, bdl) + __GDEF +struct huft *tb, *tl, *td; /* literal, length, and distance tables */ +unsigned bb, bl, bd; /* number of bits decoded by those */ +unsigned bdl; /* number of distance low bits */ +/* Decompress the imploded data using coded literals and a sliding + window (of size 2^(6+bdl) bytes). */ +{ + zusz_t s; /* bytes to decompress */ + register unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + struct huft *t; /* pointer to table entry */ + unsigned mb, ml, md; /* masks for bb, bl, and bd bits */ + unsigned mdl; /* mask for bdl (distance lower) bits */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + unsigned u; /* true if unflushed */ + int retval = 0; /* error code returned: initialized to "no error" */ + + + /* explode the coded data */ + b = k = w = 0; /* initialize bit buffer, window */ + u = 1; /* buffer unflushed */ + mb = mask_bits[bb]; /* precompute masks for speed */ + ml = mask_bits[bl]; + md = mask_bits[bd]; + mdl = mask_bits[bdl]; + s = G.lrec.ucsize; + while (s > 0) /* do until ucsize bytes uncompressed */ + { + NEEDBITS(1) + if (b & 1) /* then literal--decode it */ + { + DUMPBITS(1) + s--; + DECODEHUFT(tb, bb, mb) /* get coded literal */ + redirSlide[w++] = (uch)t->v.n; + if (w == wszimpl) + { + if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) + return retval; + w = u = 0; + } + } + else /* else distance/length */ + { + DUMPBITS(1) + NEEDBITS(bdl) /* get distance low bits */ + d = (unsigned)b & mdl; + DUMPBITS(bdl) + DECODEHUFT(td, bd, md) /* get coded distance high bits */ + d = w - d - t->v.n; /* construct offset */ + DECODEHUFT(tl, bl, ml) /* get coded length */ + n = t->v.n; + if (e) /* get length extra bits */ + { + NEEDBITS(8) + n += (unsigned)b & 0xff; + DUMPBITS(8) + } + + /* do the copy */ + s = (s > (zusz_t)n ? s - (zusz_t)n : 0); + do { +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) { + /* &= w/ wszimpl not needed and wrong if redirect */ + if (d >= wszimpl) + return 1; + e = wszimpl - (d > w ? d : w); + } else +#endif + e = wszimpl - ((d &= wszimpl-1) > w ? d : w); + if (e > n) e = n; + n -= e; + if (u && w <= d) + { + memzero(redirSlide + w, e); + w += e; + d += e; + } + else +#ifndef NOMEMCPY + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(redirSlide + w, redirSlide + d, e); + w += e; + d += e; + } + else /* do it slow to avoid memcpy() overlap */ +#endif /* !NOMEMCPY */ + do { + redirSlide[w++] = redirSlide[d++]; + } while (--e); + if (w == wszimpl) + { + if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) + return retval; + w = u = 0; + } + } while (n); + } + } + + /* flush out redirSlide */ + if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) + return retval; + if (G.csize + G.incnt + (k >> 3)) /* should have read csize bytes, but */ + { /* sometimes read one too many: k>>3 compensates */ + G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3); + return 5; + } + return 0; +} + + + +static int explode_nolit(__G__ tl, td, bl, bd, bdl) + __GDEF +struct huft *tl, *td; /* length and distance decoder tables */ +unsigned bl, bd; /* number of bits decoded by tl[] and td[] */ +unsigned bdl; /* number of distance low bits */ +/* Decompress the imploded data using uncoded literals and a sliding + window (of size 2^(6+bdl) bytes). */ +{ + zusz_t s; /* bytes to decompress */ + register unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + struct huft *t; /* pointer to table entry */ + unsigned ml, md; /* masks for bl and bd bits */ + unsigned mdl; /* mask for bdl (distance lower) bits */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + unsigned u; /* true if unflushed */ + int retval = 0; /* error code returned: initialized to "no error" */ + + + /* explode the coded data */ + b = k = w = 0; /* initialize bit buffer, window */ + u = 1; /* buffer unflushed */ + ml = mask_bits[bl]; /* precompute masks for speed */ + md = mask_bits[bd]; + mdl = mask_bits[bdl]; + s = G.lrec.ucsize; + while (s > 0) /* do until ucsize bytes uncompressed */ + { + NEEDBITS(1) + if (b & 1) /* then literal--get eight bits */ + { + DUMPBITS(1) + s--; + NEEDBITS(8) + redirSlide[w++] = (uch)b; + if (w == wszimpl) + { + if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) + return retval; + w = u = 0; + } + DUMPBITS(8) + } + else /* else distance/length */ + { + DUMPBITS(1) + NEEDBITS(bdl) /* get distance low bits */ + d = (unsigned)b & mdl; + DUMPBITS(bdl) + DECODEHUFT(td, bd, md) /* get coded distance high bits */ + d = w - d - t->v.n; /* construct offset */ + DECODEHUFT(tl, bl, ml) /* get coded length */ + n = t->v.n; + if (e) /* get length extra bits */ + { + NEEDBITS(8) + n += (unsigned)b & 0xff; + DUMPBITS(8) + } + + /* do the copy */ + s = (s > (zusz_t)n ? s - (zusz_t)n : 0); + do { +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) { + /* &= w/ wszimpl not needed and wrong if redirect */ + if (d >= wszimpl) + return 1; + e = wszimpl - (d > w ? d : w); + } else +#endif + e = wszimpl - ((d &= wszimpl-1) > w ? d : w); + if (e > n) e = n; + n -= e; + if (u && w <= d) + { + memzero(redirSlide + w, e); + w += e; + d += e; + } + else +#ifndef NOMEMCPY + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(redirSlide + w, redirSlide + d, e); + w += e; + d += e; + } + else /* do it slow to avoid memcpy() overlap */ +#endif /* !NOMEMCPY */ + do { + redirSlide[w++] = redirSlide[d++]; + } while (--e); + if (w == wszimpl) + { + if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) + return retval; + w = u = 0; + } + } while (n); + } + } + + /* flush out redirSlide */ + if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0) + return retval; + if (G.csize + G.incnt + (k >> 3)) /* should have read csize bytes, but */ + { /* sometimes read one too many: k>>3 compensates */ + G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3); + return 5; + } + return 0; +} + + + +int explode(__G) + __GDEF +/* Explode an imploded compressed stream. Based on the general purpose + bit flag, decide on coded or uncoded literals, and an 8K or 4K sliding + window. Construct the literal (if any), length, and distance codes and + the tables needed to decode them (using huft_build() from inflate.c), + and call the appropriate routine for the type of data in the remainder + of the stream. The four routines are nearly identical, differing only + in whether the literal is decoded or simply read in, and in how many + bits are read in, uncoded, for the low distance bits. */ +{ + unsigned r; /* return codes */ + struct huft *tb; /* literal code table */ + struct huft *tl; /* length code table */ + struct huft *td; /* distance code table */ + unsigned bb; /* bits for tb */ + unsigned bl; /* bits for tl */ + unsigned bd; /* bits for td */ + unsigned bdl; /* number of uncoded lower distance bits */ + unsigned l[256]; /* bit lengths for codes */ + +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) + /* For 16-bit systems, it has already been checked at DLL entrance that + * the buffer size in G.redirect_size does not exceed unsigned range. + */ + G._wsize = G.redirect_size, redirSlide = G.redirect_buffer; + else +#if defined(USE_DEFLATE64) && defined(INT_16BIT) + /* For systems using 16-bit ints, reduce the used buffer size below + * the limit of "unsigned int" numbers range. + */ + G._wsize = WSIZE>>1, redirSlide = slide; +#else /* !(USE_DEFLATE64 && INT_16BIT) */ + G._wsize = WSIZE, redirSlide = slide; +#endif /* !(USE_DEFLATE64 && INT_16BIT) */ +#endif /* DLL && !NO_SLIDE_REDIR */ + + /* Tune base table sizes. Note: I thought that to truly optimize speed, + I would have to select different bl, bd, and bb values for different + compressed file sizes. I was surprised to find out that the values of + 7, 7, and 9 worked best over a very wide range of sizes, except that + bd = 8 worked marginally better for large compressed sizes. */ + bl = 7; + bd = (G.csize + G.incnt) > 200000L ? 8 : 7; + +#ifdef DEBUG + G.hufts = 0; /* initialize huft's malloc'ed */ +#endif + + if (G.lrec.general_purpose_bit_flag & 4) + /* With literal tree--minimum match length is 3 */ + { + bb = 9; /* base table size for literals */ + if ((r = get_tree(__G__ l, 256)) != 0) + return (int)r; + if ((r = huft_build(__G__ l, 256, 256, NULL, NULL, &tb, &bb)) != 0) + { + if (r == 1) + huft_free(tb); + return (int)r; + } + if ((r = get_tree(__G__ l, 64)) != 0) { + huft_free(tb); + return (int)r; + } + if ((r = huft_build(__G__ l, 64, 0, cplen3, extra, &tl, &bl)) != 0) + { + if (r == 1) + huft_free(tl); + huft_free(tb); + return (int)r; + } + } + else + /* No literal tree--minimum match length is 2 */ + { + tb = (struct huft *)NULL; + if ((r = get_tree(__G__ l, 64)) != 0) + return (int)r; + if ((r = huft_build(__G__ l, 64, 0, cplen2, extra, &tl, &bl)) != 0) + { + if (r == 1) + huft_free(tl); + return (int)r; + } + } + + if ((r = get_tree(__G__ l, 64)) != 0) { + huft_free(tl); + if (tb != (struct huft *)NULL) huft_free(tb); + return (int)r; + } + if (G.lrec.general_purpose_bit_flag & 2) /* true if 8K */ + { + bdl = 7; + r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd); + } + else /* else 4K */ + { + bdl = 6; + r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd); + } + if (r != 0) + { + if (r == 1) + huft_free(td); + huft_free(tl); + if (tb != (struct huft *)NULL) huft_free(tb); + return (int)r; + } + + if (tb != NULL) { + r = explode_lit(__G__ tb, tl, td, bb, bl, bd, bdl); + huft_free(tb); + } else { + r = explode_nolit(__G__ tl, td, bl, bd, bdl); + } + + huft_free(td); + huft_free(tl); + Trace((stderr, "<%u > ", G.hufts)); + return (int)r; +} + +/* so explode.c and inflate.c can be compiled together into one object: */ +#undef DECODEHUFT +#undef NEEDBITS +#undef DUMPBITS +#undef wszimpl diff --git a/extract.c b/extract.c new file mode 100644 index 0000000..1acd769 --- /dev/null +++ b/extract.c @@ -0,0 +1,2820 @@ +/* + Copyright (c) 1990-2009 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2009-Jan-02 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 +*/ +/*--------------------------------------------------------------------------- + + extract.c + + This file contains the high-level routines ("driver routines") for extrac- + ting and testing zipfile members. It calls the low-level routines in files + explode.c, inflate.c, unreduce.c and unshrink.c. + + Contains: extract_or_test_files() + store_info() + find_compr_idx() + extract_or_test_entrylist() + extract_or_test_member() + TestExtraField() + test_compr_eb() + memextract() + memflush() + extract_izvms_block() (VMS or VMS_TEXT_CONV) + set_deferred_symlink() (SYMLINKS only) + fnfilter() + dircomp() (SET_DIR_ATTRIB only) + UZbunzip2() (USE_BZIP2 only) + + ---------------------------------------------------------------------------*/ + + +#define __EXTRACT_C /* identifies this source module */ +#define UNZIP_INTERNAL +#include "unzip.h" +#ifdef WINDLL +# ifdef POCKET_UNZIP +# include "wince/intrface.h" +# else +# include "windll/windll.h" +# endif +#endif +#include "crc32.h" +#include "crypt.h" + +#define GRRDUMP(buf,len) { \ + int i, j; \ + \ + for (j = 0; j < (len)/16; ++j) { \ + printf(" "); \ + for (i = 0; i < 16; ++i) \ + printf("%02x ", (uch)(buf)[i+(j<<4)]); \ + printf("\n "); \ + for (i = 0; i < 16; ++i) { \ + char c = (char)(buf)[i+(j<<4)]; \ + \ + if (c == '\n') \ + printf("\\n "); \ + else if (c == '\r') \ + printf("\\r "); \ + else \ + printf(" %c ", c); \ + } \ + printf("\n"); \ + } \ + if ((len) % 16) { \ + printf(" "); \ + for (i = j<<4; i < (len); ++i) \ + printf("%02x ", (uch)(buf)[i]); \ + printf("\n "); \ + for (i = j<<4; i < (len); ++i) { \ + char c = (char)(buf)[i]; \ + \ + if (c == '\n') \ + printf("\\n "); \ + else if (c == '\r') \ + printf("\\r "); \ + else \ + printf(" %c ", c); \ + } \ + printf("\n"); \ + } \ +} + +static int store_info OF((__GPRO)); +#ifdef SET_DIR_ATTRIB +static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk, + ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes, + unsigned *pnum_dirs, direntry **pdirlist, + int error_in_archive)); +#else +static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk, + ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes, + int error_in_archive)); +#endif +static int extract_or_test_member OF((__GPRO)); +#ifndef SFX + static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len)); + static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size, + unsigned compr_offset, + int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size, + uch *eb_ucptr, ulg eb_ucsize))); +#endif +#if (defined(VMS) || defined(VMS_TEXT_CONV)) + static void decompress_bits OF((uch *outptr, unsigned needlen, + ZCONST uch *bitptr)); +#endif +#ifdef SYMLINKS + static void set_deferred_symlink OF((__GPRO__ slinkentry *slnk_entry)); +#endif +#ifdef SET_DIR_ATTRIB + static int Cdecl dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b)); +#endif + + + +/*******************************/ +/* Strings used in extract.c */ +/*******************************/ + +static ZCONST char Far VersionMsg[] = + " skipping: %-22s need %s compat. v%u.%u (can do v%u.%u)\n"; +static ZCONST char Far ComprMsgNum[] = + " skipping: %-22s unsupported compression method %u\n"; +#ifndef SFX + static ZCONST char Far ComprMsgName[] = + " skipping: %-22s `%s' method not supported\n"; + static ZCONST char Far CmprNone[] = "store"; + static ZCONST char Far CmprShrink[] = "shrink"; + static ZCONST char Far CmprReduce[] = "reduce"; + static ZCONST char Far CmprImplode[] = "implode"; + static ZCONST char Far CmprTokenize[] = "tokenize"; + static ZCONST char Far CmprDeflate[] = "deflate"; + static ZCONST char Far CmprDeflat64[] = "deflate64"; + static ZCONST char Far CmprDCLImplode[] = "DCL implode"; + static ZCONST char Far CmprBzip[] = "bzip2"; + static ZCONST char Far CmprLZMA[] = "LZMA"; + static ZCONST char Far CmprIBMTerse[] = "IBM/Terse"; + static ZCONST char Far CmprIBMLZ77[] = "IBM LZ77"; + static ZCONST char Far CmprWavPack[] = "WavPack"; + static ZCONST char Far CmprPPMd[] = "PPMd"; + static ZCONST char Far *ComprNames[NUM_METHODS] = { + CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce, + CmprImplode, CmprTokenize, CmprDeflate, CmprDeflat64, CmprDCLImplode, + CmprBzip, CmprLZMA, CmprIBMTerse, CmprIBMLZ77, CmprWavPack, CmprPPMd + }; + static ZCONST unsigned ComprIDs[NUM_METHODS] = { + STORED, SHRUNK, REDUCED1, REDUCED2, REDUCED3, REDUCED4, + IMPLODED, TOKENIZED, DEFLATED, ENHDEFLATED, DCLIMPLODED, + BZIPPED, LZMAED, IBMTERSED, IBMLZ77ED, WAVPACKED, PPMDED + }; +#endif /* !SFX */ +static ZCONST char Far FilNamMsg[] = + "%s: bad filename length (%s)\n"; +#ifndef SFX + static ZCONST char Far WarnNoMemCFName[] = + "%s: warning, no memory for comparison with local header\n"; + static ZCONST char Far LvsCFNamMsg[] = + "%s: mismatching \"local\" filename (%s),\n\ + continuing with \"central\" filename version\n"; +#endif /* !SFX */ +#if (!defined(SFX) && defined(UNICODE_SUPPORT)) + static ZCONST char Far GP11FlagsDiffer[] = + "file #%lu (%s):\n\ + mismatch between local and central GPF bit 11 (\"UTF-8\"),\n\ + continuing with central flag (IsUTF8 = %d)\n"; +#endif /* !SFX && UNICODE_SUPPORT */ +static ZCONST char Far WrnStorUCSizCSizDiff[] = + "%s: ucsize %s <> csize %s for STORED entry\n\ + continuing with \"compressed\" size value\n"; +static ZCONST char Far ExtFieldMsg[] = + "%s: bad extra field length (%s)\n"; +static ZCONST char Far OffsetMsg[] = + "file #%lu: bad zipfile offset (%s): %ld\n"; +static ZCONST char Far ExtractMsg[] = + "%8sing: %-22s %s%s"; +#ifndef SFX + static ZCONST char Far LengthMsg[] = + "%s %s: %s bytes required to uncompress to %s bytes;\n %s\ + supposed to require %s bytes%s%s%s\n"; +#endif + +static ZCONST char Far BadFileCommLength[] = "%s: bad file comment length\n"; +static ZCONST char Far LocalHdrSig[] = "local header sig"; +static ZCONST char Far BadLocalHdr[] = "file #%lu: bad local header\n"; +static ZCONST char Far AttemptRecompensate[] = + " (attempting to re-compensate)\n"; +#ifndef SFX + static ZCONST char Far BackslashPathSep[] = + "warning: %s appears to use backslashes as path separators\n"; +#endif +static ZCONST char Far AbsolutePathWarning[] = + "warning: stripped absolute path spec from %s\n"; +static ZCONST char Far SkipVolumeLabel[] = + " skipping: %-22s %svolume label\n"; + +#ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */ + static ZCONST char Far DirlistEntryNoMem[] = + "warning: cannot alloc memory for dir times/permissions/UID/GID\n"; + static ZCONST char Far DirlistSortNoMem[] = + "warning: cannot alloc memory to sort dir times/perms/etc.\n"; + static ZCONST char Far DirlistSetAttrFailed[] = + "warning: set times/attribs failed for %s\n"; + static ZCONST char Far DirlistFailAttrSum[] = + " failed setting times/attribs for %lu dir entries"; +#endif + +#ifdef SYMLINKS /* messages of the deferred symlinks handler */ + static ZCONST char Far SymLnkWarnNoMem[] = + "warning: deferred symlink (%s) failed:\n\ + out of memory\n"; + static ZCONST char Far SymLnkWarnInvalid[] = + "warning: deferred symlink (%s) failed:\n\ + invalid placeholder file\n"; + static ZCONST char Far SymLnkDeferred[] = + "finishing deferred symbolic links:\n"; + static ZCONST char Far SymLnkFinish[] = + " %-22s -> %s\n"; +#endif + +#ifndef WINDLL + static ZCONST char Far ReplaceQuery[] = +# ifdef VMS + "new version of %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: "; +# else + "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: "; +# endif + static ZCONST char Far AssumeNone[] = + " NULL\n(EOF or read error, treating as \"[N]one\" ...)\n"; + static ZCONST char Far NewNameQuery[] = "new name: "; + static ZCONST char Far InvalidResponse[] = + "error: invalid response [%s]\n"; +#endif /* !WINDLL */ + +static ZCONST char Far ErrorInArchive[] = + "At least one %serror was detected in %s.\n"; +static ZCONST char Far ZeroFilesTested[] = + "Caution: zero files tested in %s.\n"; + +#ifndef VMS + static ZCONST char Far VMSFormatQuery[] = + "\n%s: stored in VMS format. Extract anyway? (y/n) "; +#endif + +#if CRYPT + static ZCONST char Far SkipCannotGetPasswd[] = + " skipping: %-22s unable to get password\n"; + static ZCONST char Far SkipIncorrectPasswd[] = + " skipping: %-22s incorrect password\n"; + static ZCONST char Far FilesSkipBadPasswd[] = + "%lu file%s skipped because of incorrect password.\n"; + static ZCONST char Far MaybeBadPasswd[] = + " (may instead be incorrect password)\n"; +#else + static ZCONST char Far SkipEncrypted[] = + " skipping: %-22s encrypted (not supported)\n"; +#endif + +static ZCONST char Far NoErrInCompData[] = + "No errors detected in compressed data of %s.\n"; +static ZCONST char Far NoErrInTestedFiles[] = + "No errors detected in %s for the %lu file%s tested.\n"; +static ZCONST char Far FilesSkipped[] = + "%lu file%s skipped because of unsupported compression or encoding.\n"; + +static ZCONST char Far ErrUnzipFile[] = " error: %s%s %s\n"; +static ZCONST char Far ErrUnzipNoFile[] = "\n error: %s%s\n"; +static ZCONST char Far NotEnoughMem[] = "not enough memory to "; +static ZCONST char Far InvalidComprData[] = "invalid compressed data to "; +static ZCONST char Far Inflate[] = "inflate"; +#ifdef USE_BZIP2 + static ZCONST char Far BUnzip[] = "bunzip"; +#endif + +#ifndef SFX + static ZCONST char Far Explode[] = "explode"; +#ifndef LZW_CLEAN + static ZCONST char Far Unshrink[] = "unshrink"; +#endif +#endif + +#if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK)) + static ZCONST char Far FileTruncated[] = + "warning: %s is probably truncated\n"; +#endif + +static ZCONST char Far FileUnknownCompMethod[] = + "%s: unknown compression method\n"; +static ZCONST char Far BadCRC[] = " bad CRC %08lx (should be %08lx)\n"; + + /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */ +char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s"; +char ZCONST Far TruncNTSD[] = + " compressed WinNT security data missing (%d bytes)%s"; + +#ifndef SFX + static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \ + EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n"; + static ZCONST char Far InvalidComprDataEAs[] = + " invalid compressed data for EAs\n"; +# if (defined(WIN32) && defined(NTSD_EAS)) + static ZCONST char Far InvalidSecurityEAs[] = + " EAs fail security check\n"; +# endif + static ZCONST char Far UnsuppNTSDVersEAs[] = + " unsupported NTSD EAs version %d\n"; + static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributes\n"; + static ZCONST char Far UnknComprMethodEAs[] = + " unknown compression method for EAs (%u)\n"; + static ZCONST char Far NotEnoughMemEAs[] = + " out of memory while inflating EAs\n"; + static ZCONST char Far UnknErrorEAs[] = + " unknown error on extended attributes\n"; +#endif /* !SFX */ + +static ZCONST char Far UnsupportedExtraField[] = + "\nerror: unsupported extra-field compression type (%u)--skipping\n"; +static ZCONST char Far BadExtraFieldCRC[] = + "error [%s]: bad extra-field CRC %08lx (should be %08lx)\n"; + + + + + +/**************************************/ +/* Function extract_or_test_files() */ +/**************************************/ + +int extract_or_test_files(__G) /* return PK-type error code */ + __GDEF +{ + unsigned i, j; + zoff_t cd_bufstart; + uch *cd_inptr; + int cd_incnt; + ulg filnum=0L, blknum=0L; + int reached_end; +#ifndef SFX + int no_endsig_found; +#endif + int error, error_in_archive=PK_COOL; + int *fn_matched=NULL, *xn_matched=NULL; + zucn_t members_processed; + ulg num_skipped=0L, num_bad_pwd=0L; + zoff_t old_extra_bytes = 0L; +#ifdef SET_DIR_ATTRIB + unsigned num_dirs=0; + direntry *dirlist=(direntry *)NULL, **sorted_dirlist=(direntry **)NULL; +#endif + + /* + * First, two general initializations are applied. These have been moved + * here from process_zipfiles() because they are only needed for accessing + * and/or extracting the data content of the zip archive. + */ + + /* a) initialize the CRC table pointer (once) */ + if (CRC_32_TAB == NULL) { + if ((CRC_32_TAB = get_crc_table()) == NULL) { + return PK_MEM; + } + } + +#if (!defined(SFX) || defined(SFX_EXDIR)) + /* b) check out if specified extraction root directory exists */ + if (uO.exdir != (char *)NULL && G.extract_flag) { + G.create_dirs = !uO.fflag; + if ((error = checkdir(__G__ uO.exdir, ROOT)) > MPN_INF_SKIP) { + /* out of memory, or file in way */ + return (error == MPN_NOMEM ? PK_MEM : PK_ERR); + } + } +#endif /* !SFX || SFX_EXDIR */ + +/*--------------------------------------------------------------------------- + The basic idea of this function is as follows. Since the central di- + rectory lies at the end of the zipfile and the member files lie at the + beginning or middle or wherever, it is not very desirable to simply + read a central directory entry, jump to the member and extract it, and + then jump back to the central directory. In the case of a large zipfile + this would lead to a whole lot of disk-grinding, especially if each mem- + ber file is small. Instead, we read from the central directory the per- + tinent information for a block of files, then go extract/test the whole + block. Thus this routine contains two small(er) loops within a very + large outer loop: the first of the small ones reads a block of files + from the central directory; the second extracts or tests each file; and + the outer one loops over blocks. There's some file-pointer positioning + stuff in between, but that's about it. Btw, it's because of this jump- + ing around that we can afford to be lenient if an error occurs in one of + the member files: we should still be able to go find the other members, + since we know the offset of each from the beginning of the zipfile. + ---------------------------------------------------------------------------*/ + + G.pInfo = G.info; + +#if CRYPT + G.newzip = TRUE; +#endif +#ifndef SFX + G.reported_backslash = FALSE; +#endif + + /* malloc space for check on unmatched filespecs (OK if one or both NULL) */ + if (G.filespecs > 0 && + (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL) + for (i = 0; i < G.filespecs; ++i) + fn_matched[i] = FALSE; + if (G.xfilespecs > 0 && + (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL) + for (i = 0; i < G.xfilespecs; ++i) + xn_matched[i] = FALSE; + +/*--------------------------------------------------------------------------- + Begin main loop over blocks of member files. We know the entire central + directory is on this disk: we would not have any of this information un- + less the end-of-central-directory record was on this disk, and we would + not have gotten to this routine unless this is also the disk on which + the central directory starts. In practice, this had better be the ONLY + disk in the archive, but we'll add multi-disk support soon. + ---------------------------------------------------------------------------*/ + + members_processed = 0; +#ifndef SFX + no_endsig_found = FALSE; +#endif + reached_end = FALSE; + while (!reached_end) { + j = 0; +#ifdef AMIGA + memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *)); +#endif + + /* + * Loop through files in central directory, storing offsets, file + * attributes, case-conversion and text-conversion flags until block + * size is reached. + */ + + while ((j < DIR_BLKSIZ)) { + G.pInfo = &G.info[j]; + + if (readbuf(__G__ G.sig, 4) == 0) { + error_in_archive = PK_EOF; + reached_end = TRUE; /* ...so no more left to do */ + break; + } + if (memcmp(G.sig, central_hdr_sig, 4)) { /* is it a new entry? */ + /* no new central directory entry + * -> is the number of processed entries compatible with the + * number of entries as stored in the end_central record? + */ + if ((members_processed + & (G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16)) + == G.ecrec.total_entries_central_dir) { +#ifndef SFX + /* yes, so look if we ARE back at the end_central record + */ + no_endsig_found = + ( (memcmp(G.sig, + (G.ecrec.have_ecr64 ? + end_central64_sig : end_central_sig), + 4) != 0) + && (!G.ecrec.is_zip64_archive) + && (memcmp(G.sig, end_central_sig, 4) != 0) + ); +#endif /* !SFX */ + } else { + /* no; we have found an error in the central directory + * -> report it and stop searching for more Zip entries + */ + Info(slide, 0x401, ((char *)slide, + LoadFarString(CentSigMsg), j + blknum*DIR_BLKSIZ + 1)); + Info(slide, 0x401, ((char *)slide, + LoadFarString(ReportMsg))); + error_in_archive = PK_BADERR; + } + reached_end = TRUE; /* ...so no more left to do */ + break; + } + /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */ + if ((error = process_cdir_file_hdr(__G)) != PK_COOL) { + error_in_archive = error; /* only PK_EOF defined */ + reached_end = TRUE; /* ...so no more left to do */ + break; + } + if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != + PK_COOL) + { + if (error > error_in_archive) + error_in_archive = error; + if (error > PK_WARN) { /* fatal: no more left to do */ + Info(slide, 0x401, ((char *)slide, + LoadFarString(FilNamMsg), + FnFilter1(G.filename), "central")); + reached_end = TRUE; + break; + } + } + if ((error = do_string(__G__ G.crec.extra_field_length, + EXTRA_FIELD)) != 0) + { + if (error > error_in_archive) + error_in_archive = error; + if (error > PK_WARN) { /* fatal */ + Info(slide, 0x401, ((char *)slide, + LoadFarString(ExtFieldMsg), + FnFilter1(G.filename), "central")); + reached_end = TRUE; + break; + } + } +#ifdef AMIGA + G.filenote_slot = j; + if ((error = do_string(__G__ G.crec.file_comment_length, + uO.N_flag ? FILENOTE : SKIP)) != PK_COOL) +#else + if ((error = do_string(__G__ G.crec.file_comment_length, SKIP)) + != PK_COOL) +#endif + { + if (error > error_in_archive) + error_in_archive = error; + if (error > PK_WARN) { /* fatal */ + Info(slide, 0x421, ((char *)slide, + LoadFarString(BadFileCommLength), + FnFilter1(G.filename))); + reached_end = TRUE; + break; + } + } + if (G.process_all_files) { + if (store_info(__G)) + ++j; /* file is OK; info[] stored; continue with next */ + else + ++num_skipped; + } else { + int do_this_file; + + if (G.filespecs == 0) + do_this_file = TRUE; + else { /* check if this entry matches an `include' argument */ + do_this_file = FALSE; + for (i = 0; i < G.filespecs; i++) + if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) { + do_this_file = TRUE; /* ^-- ignore case or not? */ + if (fn_matched) + fn_matched[i] = TRUE; + break; /* found match, so stop looping */ + } + } + if (do_this_file) { /* check if this is an excluded file */ + for (i = 0; i < G.xfilespecs; i++) + if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) { + do_this_file = FALSE; /* ^-- ignore case or not? */ + if (xn_matched) + xn_matched[i] = TRUE; + break; + } + } + if (do_this_file) { + if (store_info(__G)) + ++j; /* file is OK */ + else + ++num_skipped; /* unsupp. compression or encryption */ + } + } /* end if (process_all_files) */ + + members_processed++; + + } /* end while-loop (adding files to current block) */ + + /* save position in central directory so can come back later */ + cd_bufstart = G.cur_zipfile_bufstart; + cd_inptr = G.inptr; + cd_incnt = G.incnt; + + /*----------------------------------------------------------------------- + Second loop: process files in current block, extracting or testing + each one. + -----------------------------------------------------------------------*/ + + error = extract_or_test_entrylist(__G__ j, + &filnum, &num_bad_pwd, &old_extra_bytes, +#ifdef SET_DIR_ATTRIB + &num_dirs, &dirlist, +#endif + error_in_archive); + if (error != PK_COOL) { + if (error > error_in_archive) + error_in_archive = error; + /* ...and keep going (unless disk full or user break) */ + if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) { + /* clear reached_end to signal premature stop ... */ + reached_end = FALSE; + /* ... and cancel scanning the central directory */ + break; + } + } + + + /* + * Jump back to where we were in the central directory, then go and do + * the next batch of files. + */ + +#ifdef USE_STRM_INPUT + zfseeko(G.zipfd, cd_bufstart, SEEK_SET); + G.cur_zipfile_bufstart = zftello(G.zipfd); +#else /* !USE_STRM_INPUT */ + G.cur_zipfile_bufstart = + zlseek(G.zipfd, cd_bufstart, SEEK_SET); +#endif /* ?USE_STRM_INPUT */ + read(G.zipfd, (char *)G.inbuf, INBUFSIZ); /* been here before... */ + G.inptr = cd_inptr; + G.incnt = cd_incnt; + ++blknum; + +#ifdef TEST + printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart); + printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart, + cur_zipfile_bufstart); + printf("inptr-inbuf = %d\n", G.inptr-G.inbuf); + printf("incnt = %d\n\n", G.incnt); +#endif + + } /* end while-loop (blocks of files in central directory) */ + +/*--------------------------------------------------------------------------- + Process the list of deferred symlink extractions and finish up + the symbolic links. + ---------------------------------------------------------------------------*/ + +#ifdef SYMLINKS + if (G.slink_last != NULL) { + if (QCOND2) + Info(slide, 0, ((char *)slide, LoadFarString(SymLnkDeferred))); + while (G.slink_head != NULL) { + set_deferred_symlink(__G__ G.slink_head); + /* remove the processed entry from the chain and free its memory */ + G.slink_last = G.slink_head; + G.slink_head = G.slink_last->next; + free(G.slink_last); + } + G.slink_last = NULL; + } +#endif /* SYMLINKS */ + +/*--------------------------------------------------------------------------- + Go back through saved list of directories, sort and set times/perms/UIDs + and GIDs from the deepest level on up. + ---------------------------------------------------------------------------*/ + +#ifdef SET_DIR_ATTRIB + if (num_dirs > 0) { + sorted_dirlist = (direntry **)malloc(num_dirs*sizeof(direntry *)); + if (sorted_dirlist == (direntry **)NULL) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(DirlistSortNoMem))); + while (dirlist != (direntry *)NULL) { + direntry *d = dirlist; + + dirlist = dirlist->next; + free(d); + } + } else { + ulg ndirs_fail = 0; + + if (num_dirs == 1) + sorted_dirlist[0] = dirlist; + else { + for (i = 0; i < num_dirs; ++i) { + sorted_dirlist[i] = dirlist; + dirlist = dirlist->next; + } + qsort((char *)sorted_dirlist, num_dirs, sizeof(direntry *), + dircomp); + } + + Trace((stderr, "setting directory times/perms/attributes\n")); + for (i = 0; i < num_dirs; ++i) { + direntry *d = sorted_dirlist[i]; + + Trace((stderr, "dir = %s\n", d->fn)); + if ((error = set_direc_attribs(__G__ d)) != PK_OK) { + ndirs_fail++; + Info(slide, 0x201, ((char *)slide, + LoadFarString(DirlistSetAttrFailed), d->fn)); + if (!error_in_archive) + error_in_archive = error; + } + free(d); + } + free(sorted_dirlist); + if (!uO.tflag && QCOND2) { + if (ndirs_fail > 0) + Info(slide, 0, ((char *)slide, + LoadFarString(DirlistFailAttrSum), ndirs_fail)); + } + } + } +#endif /* SET_DIR_ATTRIB */ + +/*--------------------------------------------------------------------------- + Check for unmatched filespecs on command line and print warning if any + found. Free allocated memory. (But suppress check when central dir + scan was interrupted prematurely.) + ---------------------------------------------------------------------------*/ + + if (fn_matched) { + if (reached_end) for (i = 0; i < G.filespecs; ++i) + if (!fn_matched[i]) { +#ifdef DLL + if (!G.redirect_data && !G.redirect_text) + Info(slide, 0x401, ((char *)slide, + LoadFarString(FilenameNotMatched), G.pfnames[i])); + else + setFileNotFound(__G); +#else + Info(slide, 1, ((char *)slide, + LoadFarString(FilenameNotMatched), G.pfnames[i])); +#endif + if (error_in_archive <= PK_WARN) + error_in_archive = PK_FIND; /* some files not found */ + } + free((zvoid *)fn_matched); + } + if (xn_matched) { + if (reached_end) for (i = 0; i < G.xfilespecs; ++i) + if (!xn_matched[i]) + Info(slide, 0x401, ((char *)slide, + LoadFarString(ExclFilenameNotMatched), G.pxnames[i])); + free((zvoid *)xn_matched); + } + +/*--------------------------------------------------------------------------- + Now, all locally allocated memory has been released. When the central + directory processing has been interrupted prematurely, it is safe to + return immediately. All completeness checks and summary messages are + skipped in this case. + ---------------------------------------------------------------------------*/ + if (!reached_end) + return error_in_archive; + +/*--------------------------------------------------------------------------- + Double-check that we're back at the end-of-central-directory record, and + print quick summary of results, if we were just testing the archive. We + send the summary to stdout so that people doing the testing in the back- + ground and redirecting to a file can just do a "tail" on the output file. + ---------------------------------------------------------------------------*/ + +#ifndef SFX + if (no_endsig_found) { /* just to make sure */ + Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); + Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); + if (!error_in_archive) /* don't overwrite stronger error */ + error_in_archive = PK_WARN; + } +#endif /* !SFX */ + if (uO.tflag) { + ulg num = filnum - num_bad_pwd; + + if (uO.qflag < 2) { /* GRR 930710: was (uO.qflag == 1) */ + if (error_in_archive) + Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive), + (error_in_archive == PK_WARN)? "warning-" : "", G.zipfn)); + else if (num == 0L) + Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested), + G.zipfn)); + else if (G.process_all_files && (num_skipped+num_bad_pwd == 0L)) + Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData), + G.zipfn)); + else + Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles) + , G.zipfn, num, (num==1L)? "":"s")); + if (num_skipped > 0L) + Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped), + num_skipped, (num_skipped==1L)? "":"s")); +#if CRYPT + if (num_bad_pwd > 0L) + Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd) + , num_bad_pwd, (num_bad_pwd==1L)? "":"s")); +#endif /* CRYPT */ + } + } + + /* give warning if files not tested or extracted (first condition can still + * happen if zipfile is empty and no files specified on command line) */ + + if ((filnum == 0) && error_in_archive <= PK_WARN) { + if (num_skipped > 0L) + error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */ + else + error_in_archive = PK_FIND; /* no files found at all */ + } +#if CRYPT + else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN) + error_in_archive = IZ_BADPWD; /* bad passwd => all files skipped */ +#endif + else if ((num_skipped > 0L) && error_in_archive <= PK_WARN) + error_in_archive = IZ_UNSUP; /* was PK_WARN; Jean-loup complained */ +#if CRYPT + else if ((num_bad_pwd > 0L) && !error_in_archive) + error_in_archive = PK_WARN; +#endif + + return error_in_archive; + +} /* end function extract_or_test_files() */ + + + + + +/***************************/ +/* Function store_info() */ +/***************************/ + +static int store_info(__G) /* return 0 if skipping, 1 if OK */ + __GDEF +{ +#ifdef USE_BZIP2 +# define UNKN_BZ2 (G.crec.compression_method!=BZIPPED) +#else +# define UNKN_BZ2 TRUE /* bzip2 unknown */ +#endif + +#ifdef USE_LZMA +# define UNKN_LZMA (G.crec.compression_method!=LZMAED) +#else +# define UNKN_LZMA TRUE /* LZMA unknown */ +#endif + +#ifdef USE_WAVP +# define UNKN_WAVP (G.crec.compression_method!=WAVPACKED) +#else +# define UNKN_WAVP TRUE /* WavPack unknown */ +#endif + +#ifdef USE_PPMD +# define UNKN_PPMD (G.crec.compression_method!=PPMDED) +#else +# define UNKN_PPMD TRUE /* PPMd unknown */ +#endif + +#ifdef SFX +# ifdef USE_DEFLATE64 +# define UNKN_COMPR \ + (G.crec.compression_method!=STORED && G.crec.compression_methodENHDEFLATED \ + && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD) +# else +# define UNKN_COMPR \ + (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED\ + && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD) +# endif +#else +# ifdef COPYRIGHT_CLEAN /* no reduced files */ +# define UNKN_RED (G.crec.compression_method >= REDUCED1 && \ + G.crec.compression_method <= REDUCED4) +# else +# define UNKN_RED FALSE /* reducing not unknown */ +# endif +# ifdef LZW_CLEAN /* no shrunk files */ +# define UNKN_SHR (G.crec.compression_method == SHRUNK) +# else +# define UNKN_SHR FALSE /* unshrinking not unknown */ +# endif +# ifdef USE_DEFLATE64 +# define UNKN_COMPR (UNKN_RED || UNKN_SHR || \ + G.crec.compression_method==TOKENIZED || \ + (G.crec.compression_method>ENHDEFLATED && UNKN_BZ2 && UNKN_LZMA \ + && UNKN_WAVP && UNKN_PPMD)) +# else +# define UNKN_COMPR (UNKN_RED || UNKN_SHR || \ + G.crec.compression_method==TOKENIZED || \ + (G.crec.compression_method>DEFLATED && UNKN_BZ2 && UNKN_LZMA \ + && UNKN_WAVP && UNKN_PPMD)) +# endif +#endif + +#if (defined(USE_BZIP2) && (UNZIP_VERSION < UNZIP_BZ2VERS)) + int unzvers_support = (UNKN_BZ2 ? UNZIP_VERSION : UNZIP_BZ2VERS); +# define UNZVERS_SUPPORT unzvers_support +#else +# define UNZVERS_SUPPORT UNZIP_VERSION +#endif + +/*--------------------------------------------------------------------------- + Check central directory info for version/compatibility requirements. + ---------------------------------------------------------------------------*/ + + G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1; /* bit field */ + G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8; /* bit */ + G.pInfo->textfile = G.crec.internal_file_attributes & 1; /* bit field */ + G.pInfo->crc = G.crec.crc32; + G.pInfo->compr_size = G.crec.csize; + G.pInfo->uncompr_size = G.crec.ucsize; + + switch (uO.aflag) { + case 0: + G.pInfo->textmode = FALSE; /* bit field */ + break; + case 1: + G.pInfo->textmode = G.pInfo->textfile; /* auto-convert mode */ + break; + default: /* case 2: */ + G.pInfo->textmode = TRUE; + break; + } + + if (G.crec.version_needed_to_extract[1] == VMS_) { + if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) { + if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) + Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg), + FnFilter1(G.filename), "VMS", + G.crec.version_needed_to_extract[0] / 10, + G.crec.version_needed_to_extract[0] % 10, + VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10)); + return 0; + } +#ifndef VMS /* won't be able to use extra field, but still have data */ + else if (!uO.tflag && !IS_OVERWRT_ALL) { /* if -o, extract anyway */ + Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery), + FnFilter1(G.filename))); + fgets(G.answerbuf, sizeof(G.answerbuf), stdin); + if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y')) + return 0; + } +#endif /* !VMS */ + /* usual file type: don't need VMS to extract */ + } else if (G.crec.version_needed_to_extract[0] > UNZVERS_SUPPORT) { + if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) + Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg), + FnFilter1(G.filename), "PK", + G.crec.version_needed_to_extract[0] / 10, + G.crec.version_needed_to_extract[0] % 10, + UNZVERS_SUPPORT / 10, UNZVERS_SUPPORT % 10)); + return 0; + } + + if (UNKN_COMPR) { + if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) { +#ifndef SFX + unsigned cmpridx; + + if ((cmpridx = find_compr_idx(G.crec.compression_method)) + < NUM_METHODS) + Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName), + FnFilter1(G.filename), + LoadFarStringSmall(ComprNames[cmpridx]))); + else +#endif + Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum), + FnFilter1(G.filename), + G.crec.compression_method)); + } + return 0; + } +#if (!CRYPT) + if (G.pInfo->encrypted) { + if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) + Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted), + FnFilter1(G.filename))); + return 0; + } +#endif /* !CRYPT */ + +#ifndef SFX + /* store a copy of the central header filename for later comparison */ + if ((G.pInfo->cfilname = zfmalloc(strlen(G.filename) + 1)) == NULL) { + Info(slide, 0x401, ((char *)slide, LoadFarString(WarnNoMemCFName), + FnFilter1(G.filename))); + } else + zfstrcpy(G.pInfo->cfilname, G.filename); +#endif /* !SFX */ + + /* map whatever file attributes we have into the local format */ + mapattr(__G); /* GRR: worry about return value later */ + + G.pInfo->diskstart = G.crec.disk_number_start; + G.pInfo->offset = (zoff_t)G.crec.relative_offset_local_header; + return 1; + +} /* end function store_info() */ + + + + + +#ifndef SFX +/*******************************/ +/* Function find_compr_idx() */ +/*******************************/ + +unsigned find_compr_idx(compr_methodnum) + unsigned compr_methodnum; +{ + unsigned i; + + for (i = 0; i < NUM_METHODS; i++) { + if (ComprIDs[i] == compr_methodnum) break; + } + return i; +} +#endif /* !SFX */ + + + + + +/******************************************/ +/* Function extract_or_test_entrylist() */ +/******************************************/ + +static int extract_or_test_entrylist(__G__ numchunk, + pfilnum, pnum_bad_pwd, pold_extra_bytes, +#ifdef SET_DIR_ATTRIB + pnum_dirs, pdirlist, +#endif + error_in_archive) /* return PK-type error code */ + __GDEF + unsigned numchunk; + ulg *pfilnum; + ulg *pnum_bad_pwd; + zoff_t *pold_extra_bytes; +#ifdef SET_DIR_ATTRIB + unsigned *pnum_dirs; + direntry **pdirlist; +#endif + int error_in_archive; +{ + unsigned i; + int renamed, query; + int skip_entry; + zoff_t bufstart, inbuf_offset, request; + int error, errcode; + +/* possible values for local skip_entry flag: */ +#define SKIP_NO 0 /* do not skip this entry */ +#define SKIP_Y_EXISTING 1 /* skip this entry, do not overwrite file */ +#define SKIP_Y_NONEXIST 2 /* skip this entry, do not create new file */ + + /*----------------------------------------------------------------------- + Second loop: process files in current block, extracting or testing + each one. + -----------------------------------------------------------------------*/ + + for (i = 0; i < numchunk; ++i) { + (*pfilnum)++; /* *pfilnum = i + blknum*DIR_BLKSIZ + 1; */ + G.pInfo = &G.info[i]; +#ifdef NOVELL_BUG_FAILSAFE + G.dne = FALSE; /* assume file exists until stat() says otherwise */ +#endif + + /* if the target position is not within the current input buffer + * (either haven't yet read far enough, or (maybe) skipping back- + * ward), skip to the target position and reset readbuf(). */ + + /* seek_zipf(__G__ pInfo->offset); */ + request = G.pInfo->offset + G.extra_bytes; + inbuf_offset = request % INBUFSIZ; + bufstart = request - inbuf_offset; + + Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n", + (long)request, (long)inbuf_offset)); + Trace((stderr, + "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", + (long)bufstart, (long)G.cur_zipfile_bufstart)); + if (request < 0) { + Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg), + G.zipfn, LoadFarString(ReportMsg))); + error_in_archive = PK_ERR; + if (*pfilnum == 1 && G.extra_bytes != 0L) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(AttemptRecompensate))); + *pold_extra_bytes = G.extra_bytes; + G.extra_bytes = 0L; + request = G.pInfo->offset; /* could also check if != 0 */ + inbuf_offset = request % INBUFSIZ; + bufstart = request - inbuf_offset; + Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n", + (long)request, (long)inbuf_offset)); + Trace((stderr, + "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", + (long)bufstart, (long)G.cur_zipfile_bufstart)); + /* try again */ + if (request < 0) { + Trace((stderr, + "debug: recompensated request still < 0\n")); + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall(SeekMsg), + G.zipfn, LoadFarString(ReportMsg))); + error_in_archive = PK_BADERR; + continue; + } + } else { + error_in_archive = PK_BADERR; + continue; /* this one hosed; try next */ + } + } + + if (bufstart != G.cur_zipfile_bufstart) { + Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n")); +#ifdef USE_STRM_INPUT + zfseeko(G.zipfd, bufstart, SEEK_SET); + G.cur_zipfile_bufstart = zftello(G.zipfd); +#else /* !USE_STRM_INPUT */ + G.cur_zipfile_bufstart = + zlseek(G.zipfd, bufstart, SEEK_SET); +#endif /* ?USE_STRM_INPUT */ + if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) + { + Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), + *pfilnum, "lseek", (long)bufstart)); + error_in_archive = PK_BADERR; + continue; /* can still do next file */ + } + G.inptr = G.inbuf + (int)inbuf_offset; + G.incnt -= (int)inbuf_offset; + } else { + G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset; + G.inptr = G.inbuf + (int)inbuf_offset; + } + + /* should be in proper position now, so check for sig */ + if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */ + Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), + *pfilnum, "EOF", (long)request)); + error_in_archive = PK_BADERR; + continue; /* but can still try next one */ + } + if (memcmp(G.sig, local_hdr_sig, 4)) { + Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), + *pfilnum, LoadFarStringSmall(LocalHdrSig), (long)request)); + /* + GRRDUMP(G.sig, 4) + GRRDUMP(local_hdr_sig, 4) + */ + error_in_archive = PK_ERR; + if ((*pfilnum == 1 && G.extra_bytes != 0L) || + (G.extra_bytes == 0L && *pold_extra_bytes != 0L)) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(AttemptRecompensate))); + if (G.extra_bytes) { + *pold_extra_bytes = G.extra_bytes; + G.extra_bytes = 0L; + } else + G.extra_bytes = *pold_extra_bytes; /* third attempt */ + if (((error = seek_zipf(__G__ G.pInfo->offset)) != PK_OK) || + (readbuf(__G__ G.sig, 4) == 0)) { /* bad offset */ + if (error != PK_BADERR) + Info(slide, 0x401, ((char *)slide, + LoadFarString(OffsetMsg), *pfilnum, "EOF", + (long)request)); + error_in_archive = PK_BADERR; + continue; /* but can still try next one */ + } + if (memcmp(G.sig, local_hdr_sig, 4)) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(OffsetMsg), *pfilnum, + LoadFarStringSmall(LocalHdrSig), (long)request)); + error_in_archive = PK_BADERR; + continue; + } + } else + continue; /* this one hosed; try next */ + } + if ((error = process_local_file_hdr(__G)) != PK_COOL) { + Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr), + *pfilnum)); + error_in_archive = error; /* only PK_EOF defined */ + continue; /* can still try next one */ + } +#if (!defined(SFX) && defined(UNICODE_SUPPORT)) + if (((G.lrec.general_purpose_bit_flag & (1 << 11)) == (1 << 11)) + != (G.pInfo->GPFIsUTF8 != 0)) { + if (QCOND2) { +# ifdef SMALL_MEM + char *temp_cfilnam = slide + (7 * (WSIZE>>3)); + + zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname); +# define cFile_PrintBuf temp_cfilnam +# else +# define cFile_PrintBuf G.pInfo->cfilname +# endif + Info(slide, 0x421, ((char *)slide, + LoadFarStringSmall2(GP11FlagsDiffer), + *pfilnum, FnFilter1(cFile_PrintBuf), G.pInfo->GPFIsUTF8)); +# undef cFile_PrintBuf + } + if (error_in_archive < PK_WARN) + error_in_archive = PK_WARN; + } +#endif /* !SFX && UNICODE_SUPPORT */ + if ((error = do_string(__G__ G.lrec.filename_length, DS_FN_L)) != + PK_COOL) + { + if (error > error_in_archive) + error_in_archive = error; + if (error > PK_WARN) { + Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg), + FnFilter1(G.filename), "local")); + continue; /* go on to next one */ + } + } + if (G.extra_field != (uch *)NULL) { + free(G.extra_field); + G.extra_field = (uch *)NULL; + } + if ((error = + do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0) + { + if (error > error_in_archive) + error_in_archive = error; + if (error > PK_WARN) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(ExtFieldMsg), + FnFilter1(G.filename), "local")); + continue; /* go on */ + } + } +#ifndef SFX + /* Filename consistency checks must come after reading in the local + * extra field, so that a UTF-8 entry name e.f. block has already + * been processed. + */ + if (G.pInfo->cfilname != (char Far *)NULL) { + if (zfstrcmp(G.pInfo->cfilname, G.filename) != 0) { +# ifdef SMALL_MEM + char *temp_cfilnam = slide + (7 * (WSIZE>>3)); + + zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname); +# define cFile_PrintBuf temp_cfilnam +# else +# define cFile_PrintBuf G.pInfo->cfilname +# endif + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall2(LvsCFNamMsg), + FnFilter2(cFile_PrintBuf), FnFilter1(G.filename))); +# undef cFile_PrintBuf + zfstrcpy(G.filename, G.pInfo->cfilname); + if (error_in_archive < PK_WARN) + error_in_archive = PK_WARN; + } + zffree(G.pInfo->cfilname); + G.pInfo->cfilname = (char Far *)NULL; + } +#endif /* !SFX */ + /* Size consistency checks must come after reading in the local extra + * field, so that any Zip64 extension local e.f. block has already + * been processed. + */ + if (G.lrec.compression_method == STORED) { + zusz_t csiz_decrypted = G.lrec.csize; + + if (G.pInfo->encrypted) + csiz_decrypted -= 12; + if (G.lrec.ucsize != csiz_decrypted) { + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall2(WrnStorUCSizCSizDiff), + FnFilter1(G.filename), + FmZofft(G.lrec.ucsize, NULL, "u"), + FmZofft(csiz_decrypted, NULL, "u"))); + G.lrec.ucsize = csiz_decrypted; + if (error_in_archive < PK_WARN) + error_in_archive = PK_WARN; + } + } + +#if CRYPT + if (G.pInfo->encrypted && + (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) { + if (error == PK_WARN) { + if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) + Info(slide, 0x401, ((char *)slide, + LoadFarString(SkipIncorrectPasswd), + FnFilter1(G.filename))); + ++(*pnum_bad_pwd); + } else { /* (error > PK_WARN) */ + if (error > error_in_archive) + error_in_archive = error; + Info(slide, 0x401, ((char *)slide, + LoadFarString(SkipCannotGetPasswd), + FnFilter1(G.filename))); + } + continue; /* go on to next file */ + } +#endif /* CRYPT */ + + /* + * just about to extract file: if extracting to disk, check if + * already exists, and if so, take appropriate action according to + * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper + * loop because we don't store the possibly renamed filename[] in + * info[]) + */ +#ifdef DLL + if (!uO.tflag && !uO.cflag && !G.redirect_data) +#else + if (!uO.tflag && !uO.cflag) +#endif + { + renamed = FALSE; /* user hasn't renamed output file yet */ + +startover: + query = FALSE; + skip_entry = SKIP_NO; + /* for files from DOS FAT, check for use of backslash instead + * of slash as directory separator (bug in some zipper(s); so + * far, not a problem in HPFS, NTFS or VFAT systems) + */ +#ifndef SFX + if (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/')) { + char *p=G.filename; + + if (*p) do { + if (*p == '\\') { + if (!G.reported_backslash) { + Info(slide, 0x21, ((char *)slide, + LoadFarString(BackslashPathSep), G.zipfn)); + G.reported_backslash = TRUE; + if (!error_in_archive) + error_in_archive = PK_WARN; + } + *p = '/'; + } + } while (*PREINCSTR(p)); + } +#endif /* !SFX */ + + if (!renamed) { + /* remove absolute path specs */ + if (G.filename[0] == '/') { + Info(slide, 0x401, ((char *)slide, + LoadFarString(AbsolutePathWarning), + FnFilter1(G.filename))); + if (!error_in_archive) + error_in_archive = PK_WARN; + do { + char *p = G.filename + 1; + do { + *(p-1) = *p; + } while (*p++ != '\0'); + } while (G.filename[0] == '/'); + } + } + + /* mapname can create dirs if not freshening or if renamed */ + error = mapname(__G__ renamed); + if ((errcode = error & ~MPN_MASK) != PK_OK && + error_in_archive < errcode) + error_in_archive = errcode; + if ((errcode = error & MPN_MASK) > MPN_INF_TRUNC) { + if (errcode == MPN_CREATED_DIR) { +#ifdef SET_DIR_ATTRIB + direntry *d_entry; + + error = defer_dir_attribs(__G__ &d_entry); + if (d_entry == (direntry *)NULL) { + /* There may be no dir_attribs info available, or + * we have encountered a mem allocation error. + * In case of an error, report it and set program + * error state to warning level. + */ + if (error) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(DirlistEntryNoMem))); + if (!error_in_archive) + error_in_archive = PK_WARN; + } + } else { + d_entry->next = (*pdirlist); + (*pdirlist) = d_entry; + ++(*pnum_dirs); + } +#endif /* SET_DIR_ATTRIB */ + } else if (errcode == MPN_VOL_LABEL) { +#ifdef DOS_OS2_W32 + Info(slide, 0x401, ((char *)slide, + LoadFarString(SkipVolumeLabel), + FnFilter1(G.filename), + uO.volflag? "hard disk " : "")); +#else + Info(slide, 1, ((char *)slide, + LoadFarString(SkipVolumeLabel), + FnFilter1(G.filename), "")); +#endif + } else if (errcode > MPN_INF_SKIP && + error_in_archive < PK_ERR) + error_in_archive = PK_ERR; + Trace((stderr, "mapname(%s) returns error code = %d\n", + FnFilter1(G.filename), error)); + continue; /* go on to next file */ + } + +#ifdef QDOS + QFilename(__G__ G.filename); +#endif + switch (check_for_newer(__G__ G.filename)) { + case DOES_NOT_EXIST: +#ifdef NOVELL_BUG_FAILSAFE + G.dne = TRUE; /* stat() says file DOES NOT EXIST */ +#endif + /* freshen (no new files): skip unless just renamed */ + if (uO.fflag && !renamed) + skip_entry = SKIP_Y_NONEXIST; + break; + case EXISTS_AND_OLDER: +#ifdef UNIXBACKUP + if (!uO.B_flag) +#endif + { + if (IS_OVERWRT_NONE) + /* never overwrite: skip file */ + skip_entry = SKIP_Y_EXISTING; + else if (!IS_OVERWRT_ALL) + query = TRUE; + } + break; + case EXISTS_AND_NEWER: /* (or equal) */ +#ifdef UNIXBACKUP + if ((!uO.B_flag && IS_OVERWRT_NONE) || +#else + if (IS_OVERWRT_NONE || +#endif + (uO.uflag && !renamed)) { + /* skip if update/freshen & orig name */ + skip_entry = SKIP_Y_EXISTING; + } else { +#ifdef UNIXBACKUP + if (!IS_OVERWRT_ALL && !uO.B_flag) +#else + if (!IS_OVERWRT_ALL) +#endif + query = TRUE; + } + break; + } +#ifdef VMS + /* 2008-07-24 SMS. + * On VMS, if the file name includes a version number, + * and "-V" ("retain VMS version numbers", V_flag) is in + * effect, then the VMS-specific code will handle any + * conflicts with an existing file, making this query + * redundant. (Implicit "y" response here.) + */ + if (query && uO.V_flag) { + /* Not discarding file versions. Look for one. */ + int cndx = strlen(G.filename) - 1; + + while ((cndx > 0) && (isdigit(G.filename[cndx]))) + cndx--; + if (G.filename[cndx] == ';') + /* File version found; skip the generic query, + * proceeding with its default response "y". + */ + query = FALSE; + } +#endif /* VMS */ + if (query) { +#ifdef WINDLL + switch (G.lpUserFunctions->replace != NULL ? + (*G.lpUserFunctions->replace)(G.filename, FILNAMSIZ) : + IDM_REPLACE_NONE) { + case IDM_REPLACE_RENAME: + _ISO_INTERN(G.filename); + renamed = TRUE; + goto startover; + case IDM_REPLACE_ALL: + G.overwrite_mode = OVERWRT_ALWAYS; + /* FALL THROUGH, extract */ + case IDM_REPLACE_YES: + break; + case IDM_REPLACE_NONE: + G.overwrite_mode = OVERWRT_NEVER; + /* FALL THROUGH, skip */ + case IDM_REPLACE_NO: + skip_entry = SKIP_Y_EXISTING; + break; + } +#else /* !WINDLL */ + extent fnlen; +reprompt: + Info(slide, 0x81, ((char *)slide, + LoadFarString(ReplaceQuery), + FnFilter1(G.filename))); + if (fgets(G.answerbuf, sizeof(G.answerbuf), stdin) + == (char *)NULL) { + Info(slide, 1, ((char *)slide, + LoadFarString(AssumeNone))); + *G.answerbuf = 'N'; + if (!error_in_archive) + error_in_archive = 1; /* not extracted: warning */ + } + switch (*G.answerbuf) { + case 'r': + case 'R': + do { + Info(slide, 0x81, ((char *)slide, + LoadFarString(NewNameQuery))); + fgets(G.filename, FILNAMSIZ, stdin); + /* usually get \n here: better check for it */ + fnlen = strlen(G.filename); + if (lastchar(G.filename, fnlen) == '\n') + G.filename[--fnlen] = '\0'; + } while (fnlen == 0); +#ifdef WIN32 /* WIN32 fgets( ... , stdin) returns OEM coded strings */ + _OEM_INTERN(G.filename); +#endif + renamed = TRUE; + goto startover; /* sorry for a goto */ + case 'A': /* dangerous option: force caps */ + G.overwrite_mode = OVERWRT_ALWAYS; + /* FALL THROUGH, extract */ + case 'y': + case 'Y': + break; + case 'N': + G.overwrite_mode = OVERWRT_NEVER; + /* FALL THROUGH, skip */ + case 'n': + /* skip file */ + skip_entry = SKIP_Y_EXISTING; + break; + case '\n': + case '\r': + /* Improve echo of '\n' and/or '\r' + (sizeof(G.answerbuf) == 10 (see globals.h), so + there is enough space for the provided text...) */ + strcpy(G.answerbuf, "{ENTER}"); + /* fall through ... */ + default: + /* usually get \n here: remove it for nice display + (fnlen can be re-used here, we are outside the + "enter new filename" loop) */ + fnlen = strlen(G.answerbuf); + if (lastchar(G.answerbuf, fnlen) == '\n') + G.answerbuf[--fnlen] = '\0'; + Info(slide, 1, ((char *)slide, + LoadFarString(InvalidResponse), G.answerbuf)); + goto reprompt; /* yet another goto? */ + } /* end switch (*answerbuf) */ +#endif /* ?WINDLL */ + } /* end if (query) */ + if (skip_entry != SKIP_NO) { +#ifdef WINDLL + if (skip_entry == SKIP_Y_EXISTING) { + /* report skipping of an existing entry */ + Info(slide, 0, ((char *)slide, + ((IS_OVERWRT_NONE || !uO.uflag || renamed) ? + "Target file exists. Skipping %s\n" : + "Target file newer. Skipping %s\n"), + FnFilter1(G.filename))); + } +#endif /* WINDLL */ + continue; + } + } /* end if (extracting to disk) */ + +#ifdef DLL + if ((G.statreportcb != NULL) && + (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn, + G.filename, NULL)) { + return IZ_CTRLC; /* cancel operation by user request */ + } +#endif +#ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ + UserStop(); +#endif +#ifdef AMIGA + G.filenote_slot = i; +#endif + G.disk_full = 0; + if ((error = extract_or_test_member(__G)) != PK_COOL) { + if (error > error_in_archive) + error_in_archive = error; /* ...and keep going */ +#ifdef DLL + if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) { +#else + if (G.disk_full > 1) { +#endif + return error_in_archive; /* (unless disk full) */ + } + } +#ifdef DLL + if ((G.statreportcb != NULL) && + (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn, + G.filename, (zvoid *)&G.lrec.ucsize)) { + return IZ_CTRLC; /* cancel operation by user request */ + } +#endif +#ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ + UserStop(); +#endif + } /* end for-loop (i: files in current block) */ + + return error_in_archive; + +} /* end function extract_or_test_entrylist() */ + + + + + +/* wsize is used in extract_or_test_member() and UZbunzip2() */ +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) +# define wsize G._wsize /* wsize is a variable */ +#else +# define wsize WSIZE /* wsize is a constant */ +#endif + +/***************************************/ +/* Function extract_or_test_member() */ +/***************************************/ + +static int extract_or_test_member(__G) /* return PK-type error code */ + __GDEF +{ + char *nul="[empty] ", *txt="[text] ", *bin="[binary]"; +#ifdef CMS_MVS + char *ebc="[ebcdic]"; +#endif + register int b; + int r, error=PK_COOL; + + +/*--------------------------------------------------------------------------- + Initialize variables, buffers, etc. + ---------------------------------------------------------------------------*/ + + G.bits_left = 0; + G.bitbuf = 0L; /* unreduce and unshrink only */ + G.zipeof = 0; + G.newfile = TRUE; + G.crc32val = CRCVAL_INITIAL; + +#ifdef SYMLINKS + /* If file is a (POSIX-compatible) symbolic link and we are extracting + * to disk, prepare to restore the link. */ + G.symlnk = (G.pInfo->symlink && + !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0)); +#endif /* SYMLINKS */ + + if (uO.tflag) { + if (!uO.qflag) + Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test", + FnFilter1(G.filename), "", "")); + } else { +#ifdef DLL + if (uO.cflag && !G.redirect_data) +#else + if (uO.cflag) +#endif + { +#if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200)) + G.outfile = freopen("", "wb", stdout); /* VAC++ ignores setmode */ +#else + G.outfile = stdout; +#endif +#ifdef DOS_FLX_NLM_OS2_W32 +#if (defined(__HIGHC__) && !defined(FLEXOS)) + setmode(G.outfile, _BINARY); +#else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */ + setmode(fileno(G.outfile), O_BINARY); +#endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */ +# define NEWLINE "\r\n" +#else /* !DOS_FLX_NLM_OS2_W32 */ +# define NEWLINE "\n" +#endif /* ?DOS_FLX_NLM_OS2_W32 */ +#ifdef VMS + /* VMS: required even for stdout! */ + if ((r = open_outfile(__G)) != 0) + switch (r) { + case OPENOUT_SKIPOK: + return PK_OK; + case OPENOUT_SKIPWARN: + return PK_WARN; + default: + return PK_DISK; + } + } else if ((r = open_outfile(__G)) != 0) + switch (r) { + case OPENOUT_SKIPOK: + return PK_OK; + case OPENOUT_SKIPWARN: + return PK_WARN; + default: + return PK_DISK; + } +#else /* !VMS */ + } else if (open_outfile(__G)) + return PK_DISK; +#endif /* ?VMS */ + } + +/*--------------------------------------------------------------------------- + Unpack the file. + ---------------------------------------------------------------------------*/ + + defer_leftover_input(__G); /* so NEXTBYTE bounds check will work */ + switch (G.lrec.compression_method) { + case STORED: + if (!uO.tflag && QCOND2) { +#ifdef SYMLINKS + if (G.symlnk) /* can also be deflated, but rarer... */ + Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), + "link", FnFilter1(G.filename), "", "")); + else +#endif /* SYMLINKS */ + Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), + "extract", FnFilter1(G.filename), + (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? + "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt : + bin)), uO.cflag? NEWLINE : "")); + } +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) { + wsize = G.redirect_size; redirSlide = G.redirect_buffer; + } else { + wsize = WSIZE; redirSlide = slide; + } +#endif + G.outptr = redirSlide; + G.outcnt = 0L; + while ((b = NEXTBYTE) != EOF) { + *G.outptr++ = (uch)b; + if (++G.outcnt == wsize) { + error = flush(__G__ redirSlide, G.outcnt, 0); + G.outptr = redirSlide; + G.outcnt = 0L; + if (error != PK_COOL || G.disk_full) break; + } + } + if (G.outcnt) { /* flush final (partial) buffer */ + r = flush(__G__ redirSlide, G.outcnt, 0); + if (error < r) error = r; + } + break; + +#ifndef SFX +#ifndef LZW_CLEAN + case SHRUNK: + if (!uO.tflag && QCOND2) { + Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), + LoadFarStringSmall(Unshrink), FnFilter1(G.filename), + (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? + "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); + } + if ((r = unshrink(__G)) != PK_COOL) { + if (r < PK_DISK) { + if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall(ErrUnzipFile), r == PK_MEM3 ? + LoadFarString(NotEnoughMem) : + LoadFarString(InvalidComprData), + LoadFarStringSmall2(Unshrink), + FnFilter1(G.filename))); + else + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall(ErrUnzipNoFile), r == PK_MEM3 ? + LoadFarString(NotEnoughMem) : + LoadFarString(InvalidComprData), + LoadFarStringSmall2(Unshrink))); + } + error = r; + } + break; +#endif /* !LZW_CLEAN */ + +#ifndef COPYRIGHT_CLEAN + case REDUCED1: + case REDUCED2: + case REDUCED3: + case REDUCED4: + if (!uO.tflag && QCOND2) { + Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), + "unreduc", FnFilter1(G.filename), + (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? + "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); + } + if ((r = unreduce(__G)) != PK_COOL) { + /* unreduce() returns only PK_COOL, PK_DISK, or IZ_CTRLC */ + error = r; + } + break; +#endif /* !COPYRIGHT_CLEAN */ + + case IMPLODED: + if (!uO.tflag && QCOND2) { + Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), + "explod", FnFilter1(G.filename), + (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? + "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); + } + if ((r = explode(__G)) != 0) { + if (r == 5) { /* treat 5 specially */ + int warning = ((zusz_t)G.used_csize <= G.lrec.csize); + + if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) + Info(slide, 0x401, ((char *)slide, + LoadFarString(LengthMsg), + "", warning ? "warning" : "error", + FmZofft(G.used_csize, NULL, NULL), + FmZofft(G.lrec.ucsize, NULL, "u"), + warning ? " " : "", + FmZofft(G.lrec.csize, NULL, "u"), + " [", FnFilter1(G.filename), "]")); + else + Info(slide, 0x401, ((char *)slide, + LoadFarString(LengthMsg), + "\n", warning ? "warning" : "error", + FmZofft(G.used_csize, NULL, NULL), + FmZofft(G.lrec.ucsize, NULL, "u"), + warning ? " " : "", + FmZofft(G.lrec.csize, NULL, "u"), + "", "", ".")); + error = warning ? PK_WARN : PK_ERR; + } else if (r < PK_DISK) { + if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall(ErrUnzipFile), r == 3? + LoadFarString(NotEnoughMem) : + LoadFarString(InvalidComprData), + LoadFarStringSmall2(Explode), + FnFilter1(G.filename))); + else + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall(ErrUnzipNoFile), r == 3? + LoadFarString(NotEnoughMem) : + LoadFarString(InvalidComprData), + LoadFarStringSmall2(Explode))); + error = ((r == 3) ? PK_MEM3 : PK_ERR); + } else { + error = r; + } + } + break; +#endif /* !SFX */ + + case DEFLATED: +#ifdef USE_DEFLATE64 + case ENHDEFLATED: +#endif + if (!uO.tflag && QCOND2) { + Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), + "inflat", FnFilter1(G.filename), + (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? + "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); + } +#ifndef USE_ZLIB /* zlib's function is called inflate(), too */ +# define UZinflate inflate +#endif + if ((r = UZinflate(__G__ + (G.lrec.compression_method == ENHDEFLATED))) + != 0) { + if (r < PK_DISK) { + if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall(ErrUnzipFile), r == 3? + LoadFarString(NotEnoughMem) : + LoadFarString(InvalidComprData), + LoadFarStringSmall2(Inflate), + FnFilter1(G.filename))); + else + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall(ErrUnzipNoFile), r == 3? + LoadFarString(NotEnoughMem) : + LoadFarString(InvalidComprData), + LoadFarStringSmall2(Inflate))); + error = ((r == 3) ? PK_MEM3 : PK_ERR); + } else { + error = r; + } + } + break; + +#ifdef USE_BZIP2 + case BZIPPED: + if (!uO.tflag && QCOND2) { + Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), + "bunzipp", FnFilter1(G.filename), + (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? + "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); + } + if ((r = UZbunzip2(__G)) != 0) { + if (r < PK_DISK) { + if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall(ErrUnzipFile), r == 3? + LoadFarString(NotEnoughMem) : + LoadFarString(InvalidComprData), + LoadFarStringSmall2(BUnzip), + FnFilter1(G.filename))); + else + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall(ErrUnzipNoFile), r == 3? + LoadFarString(NotEnoughMem) : + LoadFarString(InvalidComprData), + LoadFarStringSmall2(BUnzip))); + error = ((r == 3) ? PK_MEM3 : PK_ERR); + } else { + error = r; + } + } + break; +#endif /* USE_BZIP2 */ + + default: /* should never get to this point */ + Info(slide, 0x401, ((char *)slide, + LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename))); + /* close and delete file before return? */ + undefer_input(__G); + return PK_WARN; + + } /* end switch (compression method) */ + +/*--------------------------------------------------------------------------- + Close the file and set its date and time (not necessarily in that order), + and make sure the CRC checked out OK. Logical-AND the CRC for 64-bit + machines (redundant on 32-bit machines). + ---------------------------------------------------------------------------*/ + +#ifdef VMS /* VMS: required even for stdout! (final flush) */ + if (!uO.tflag) /* don't close NULL file */ + close_outfile(__G); +#else +#ifdef DLL + if (!uO.tflag && (!uO.cflag || G.redirect_data)) { + if (G.redirect_data) + FINISH_REDIRECT(); + else + close_outfile(__G); + } +#else + if (!uO.tflag && !uO.cflag) /* don't close NULL file or stdout */ + close_outfile(__G); +#endif +#endif /* VMS */ + + /* GRR: CONVERT close_outfile() TO NON-VOID: CHECK FOR ERRORS! */ + + + if (G.disk_full) { /* set by flush() */ + if (G.disk_full > 1) { +#if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK)) + /* delete the incomplete file if we can */ + if (unlink(G.filename) != 0) + Trace((stderr, "extract.c: could not delete %s\n", + FnFilter1(G.filename))); +#else + /* warn user about the incomplete file */ + Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated), + FnFilter1(G.filename))); +#endif + error = PK_DISK; + } else { + error = PK_WARN; + } + } + + if (error > PK_WARN) {/* don't print redundant CRC error if error already */ + undefer_input(__G); + return error; + } + if (G.crc32val != G.lrec.crc32) { + /* if quiet enough, we haven't output the filename yet: do it */ + if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) + Info(slide, 0x401, ((char *)slide, "%-22s ", + FnFilter1(G.filename))); + Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val, + G.lrec.crc32)); +#if CRYPT + if (G.pInfo->encrypted) + Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd))); +#endif + error = PK_ERR; + } else if (uO.tflag) { +#ifndef SFX + if (G.extra_field) { + if ((r = TestExtraField(__G__ G.extra_field, + G.lrec.extra_field_length)) > error) + error = r; + } else +#endif /* !SFX */ + if (!uO.qflag) + Info(slide, 0, ((char *)slide, " OK\n")); + } else { + if (QCOND2 && !error) /* GRR: is stdout reset to text mode yet? */ + Info(slide, 0, ((char *)slide, "\n")); + } + + undefer_input(__G); + return error; + +} /* end function extract_or_test_member() */ + + + + + +#ifndef SFX + +/*******************************/ +/* Function TestExtraField() */ +/*******************************/ + +static int TestExtraField(__G__ ef, ef_len) + __GDEF + uch *ef; + unsigned ef_len; +{ + ush ebID; + unsigned ebLen; + unsigned eb_cmpr_offs = 0; + int r; + + /* we know the regular compressed file data tested out OK, or else we + * wouldn't be here ==> print filename if any extra-field errors found + */ + while (ef_len >= EB_HEADSIZE) { + ebID = makeword(ef); + ebLen = (unsigned)makeword(ef+EB_LEN); + + if (ebLen > (ef_len - EB_HEADSIZE)) { + /* Discovered some extra field inconsistency! */ + if (uO.qflag) + Info(slide, 1, ((char *)slide, "%-22s ", + FnFilter1(G.filename))); + Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength), + ebLen, (ef_len - EB_HEADSIZE))); + return PK_ERR; + } + + switch (ebID) { + case EF_OS2: + case EF_ACL: + case EF_MAC3: + case EF_BEOS: + case EF_ATHEOS: + switch (ebID) { + case EF_OS2: + case EF_ACL: + eb_cmpr_offs = EB_OS2_HLEN; + break; + case EF_MAC3: + if (ebLen >= EB_MAC3_HLEN && + (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) + & EB_M3_FL_UNCMPR) && + (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN)) + eb_cmpr_offs = 0; + else + eb_cmpr_offs = EB_MAC3_HLEN; + break; + case EF_BEOS: + case EF_ATHEOS: + if (ebLen >= EB_BEOS_HLEN && + (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) && + (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN)) + eb_cmpr_offs = 0; + else + eb_cmpr_offs = EB_BEOS_HLEN; + break; + } + if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL)) + != PK_OK) { + if (uO.qflag) + Info(slide, 1, ((char *)slide, "%-22s ", + FnFilter1(G.filename))); + switch (r) { + case IZ_EF_TRUNC: + Info(slide, 1, ((char *)slide, + LoadFarString(TruncEAs), + ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "\n")); + break; + case PK_ERR: + Info(slide, 1, ((char *)slide, + LoadFarString(InvalidComprDataEAs))); + break; + case PK_MEM3: + case PK_MEM4: + Info(slide, 1, ((char *)slide, + LoadFarString(NotEnoughMemEAs))); + break; + default: + if ((r & 0xff) != PK_ERR) + Info(slide, 1, ((char *)slide, + LoadFarString(UnknErrorEAs))); + else { + ush m = (ush)(r >> 8); + if (m == DEFLATED) /* GRR KLUDGE! */ + Info(slide, 1, ((char *)slide, + LoadFarString(BadCRC_EAs))); + else + Info(slide, 1, ((char *)slide, + LoadFarString(UnknComprMethodEAs), m)); + } + break; + } + return r; + } + break; + + case EF_NTSD: + Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen)); + r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC : + ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ? + (PK_WARN | 0x4000) : + test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD)); + if (r != PK_OK) { + if (uO.qflag) + Info(slide, 1, ((char *)slide, "%-22s ", + FnFilter1(G.filename))); + switch (r) { + case IZ_EF_TRUNC: + Info(slide, 1, ((char *)slide, + LoadFarString(TruncNTSD), + ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n")); + break; +#if (defined(WIN32) && defined(NTSD_EAS)) + case PK_WARN: + Info(slide, 1, ((char *)slide, + LoadFarString(InvalidSecurityEAs))); + break; +#endif + case PK_ERR: + Info(slide, 1, ((char *)slide, + LoadFarString(InvalidComprDataEAs))); + break; + case PK_MEM3: + case PK_MEM4: + Info(slide, 1, ((char *)slide, + LoadFarString(NotEnoughMemEAs))); + break; + case (PK_WARN | 0x4000): + Info(slide, 1, ((char *)slide, + LoadFarString(UnsuppNTSDVersEAs), + (int)ef[EB_HEADSIZE+EB_NTSD_VERSION])); + r = PK_WARN; + break; + default: + if ((r & 0xff) != PK_ERR) + Info(slide, 1, ((char *)slide, + LoadFarString(UnknErrorEAs))); + else { + ush m = (ush)(r >> 8); + if (m == DEFLATED) /* GRR KLUDGE! */ + Info(slide, 1, ((char *)slide, + LoadFarString(BadCRC_EAs))); + else + Info(slide, 1, ((char *)slide, + LoadFarString(UnknComprMethodEAs), m)); + } + break; + } + return r; + } + break; + case EF_PKVMS: + if (makelong(ef+EB_HEADSIZE) != + crc32(CRCVAL_INITIAL, ef+(EB_HEADSIZE+4), + (extent)(ebLen-4))) + Info(slide, 1, ((char *)slide, + LoadFarString(BadCRC_EAs))); + break; + case EF_PKW32: + case EF_PKUNIX: + case EF_ASIUNIX: + case EF_IZVMS: + case EF_IZUNIX: + case EF_VMCMS: + case EF_MVS: + case EF_SPARK: + case EF_TANDEM: + case EF_THEOS: + case EF_AV: + default: + break; + } + ef_len -= (ebLen + EB_HEADSIZE); + ef += (ebLen + EB_HEADSIZE); + } + + if (!uO.qflag) + Info(slide, 0, ((char *)slide, " OK\n")); + + return PK_COOL; + +} /* end function TestExtraField() */ + + + + + +/******************************/ +/* Function test_compr_eb() */ +/******************************/ + +#ifdef PROTO +static int test_compr_eb( + __GPRO__ + uch *eb, + unsigned eb_size, + unsigned compr_offset, + int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size, + uch *eb_ucptr, ulg eb_ucsize)) +#else /* !PROTO */ +static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata) + __GDEF + uch *eb; + unsigned eb_size; + unsigned compr_offset; + int (*test_uc_ebdata)(); +#endif /* ?PROTO */ +{ + ulg eb_ucsize; + uch *eb_ucptr; + int r; + + if (compr_offset < 4) /* field is not compressed: */ + return PK_OK; /* do nothing and signal OK */ + + if ((eb_size < (EB_UCSIZE_P + 4)) || + ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L && + eb_size <= (compr_offset + EB_CMPRHEADLEN))) + return IZ_EF_TRUNC; /* no compressed data! */ + + if ( +#ifdef INT_16BIT + (((ulg)(extent)eb_ucsize) != eb_ucsize) || +#endif + (eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL) + return PK_MEM4; + + r = memextract(__G__ eb_ucptr, eb_ucsize, + eb + (EB_HEADSIZE + compr_offset), + (ulg)(eb_size - compr_offset)); + + if (r == PK_OK && test_uc_ebdata != NULL) + r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize); + + free(eb_ucptr); + return r; + +} /* end function test_compr_eb() */ + +#endif /* !SFX */ + + + + + +/***************************/ +/* Function memextract() */ +/***************************/ + +int memextract(__G__ tgt, tgtsize, src, srcsize) /* extract compressed */ + __GDEF /* extra field block; */ + uch *tgt; /* return PK-type error */ + ulg tgtsize; /* level */ + ZCONST uch *src; + ulg srcsize; +{ + zoff_t old_csize=G.csize; + uch *old_inptr=G.inptr; + int old_incnt=G.incnt; + int r, error=PK_OK; + ush method; + ulg extra_field_crc; + + + method = makeword(src); + extra_field_crc = makelong(src+2); + + /* compressed extra field exists completely in memory at this location: */ + G.inptr = (uch *)src + (2 + 4); /* method and extra_field_crc */ + G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4))); + G.mem_mode = TRUE; + G.outbufptr = tgt; + G.outsize = tgtsize; + + switch (method) { + case STORED: + memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt); + G.outcnt = (ulg)G.csize; /* for CRC calculation */ + break; + case DEFLATED: +#ifdef USE_DEFLATE64 + case ENHDEFLATED: +#endif + G.outcnt = 0L; + if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) { + if (!uO.tflag) + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall(ErrUnzipNoFile), r == 3? + LoadFarString(NotEnoughMem) : + LoadFarString(InvalidComprData), + LoadFarStringSmall2(Inflate))); + error = (r == 3)? PK_MEM3 : PK_ERR; + } + if (G.outcnt == 0L) /* inflate's final FLUSH sets outcnt */ + break; + break; + default: + if (uO.tflag) + error = PK_ERR | ((int)method << 8); + else { + Info(slide, 0x401, ((char *)slide, + LoadFarString(UnsupportedExtraField), method)); + error = PK_ERR; /* GRR: should be passed on up via SetEAs() */ + } + break; + } + + G.inptr = old_inptr; + G.incnt = old_incnt; + G.csize = old_csize; + G.mem_mode = FALSE; + + if (!error) { + register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt); + + if (crcval != extra_field_crc) { + if (uO.tflag) + error = PK_ERR | (DEFLATED << 8); /* kludge for now */ + else { + Info(slide, 0x401, ((char *)slide, + LoadFarString(BadExtraFieldCRC), G.zipfn, crcval, + extra_field_crc)); + error = PK_ERR; + } + } + } + return error; + +} /* end function memextract() */ + + + + + +/*************************/ +/* Function memflush() */ +/*************************/ + +int memflush(__G__ rawbuf, size) + __GDEF + ZCONST uch *rawbuf; + ulg size; +{ + if (size > G.outsize) + /* Here, PK_DISK is a bit off-topic, but in the sense of marking + "overflow of output space", its use may be tolerated. */ + return PK_DISK; /* more data than output buffer can hold */ + + + + memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size); + G.outbufptr += (unsigned int)size; + G.outsize -= size; + G.outcnt += size; + + return 0; + +} /* end function memflush() */ + + + + + +#if (defined(VMS) || defined(VMS_TEXT_CONV)) + +/************************************/ +/* Function extract_izvms_block() */ +/************************************/ + +/* + * Extracts block from p. If resulting length is less than needed, fill + * extra space with corresponding bytes from 'init'. + * Currently understands 3 formats of block compression: + * - Simple storing + * - Compression of zero bytes to zero bits + * - Deflation (see memextract()) + * The IZVMS block data is returned in malloc'd space. + */ +uch *extract_izvms_block(__G__ ebdata, size, retlen, init, needlen) + __GDEF + ZCONST uch *ebdata; + unsigned size; + unsigned *retlen; + ZCONST uch *init; + unsigned needlen; +{ + uch *ucdata; /* Pointer to block allocated */ + int cmptype; + unsigned usiz, csiz; + + cmptype = (makeword(ebdata+EB_IZVMS_FLGS) & EB_IZVMS_BCMASK); + csiz = size - EB_IZVMS_HLEN; + usiz = (cmptype == EB_IZVMS_BCSTOR ? + csiz : makeword(ebdata+EB_IZVMS_UCSIZ)); + + if (retlen) + *retlen = usiz; + + if ((ucdata = (uch *)malloc(MAX(needlen, usiz))) == NULL) + return NULL; + + if (init && (usiz < needlen)) + memcpy((char *)ucdata, (ZCONST char *)init, needlen); + + switch (cmptype) + { + case EB_IZVMS_BCSTOR: /* The simplest case */ + memcpy(ucdata, ebdata+EB_IZVMS_HLEN, usiz); + break; + case EB_IZVMS_BC00: + decompress_bits(ucdata, usiz, ebdata+EB_IZVMS_HLEN); + break; + case EB_IZVMS_BCDEFL: + memextract(__G__ ucdata, (ulg)usiz, + ebdata+EB_IZVMS_HLEN, (ulg)csiz); + break; + default: + free(ucdata); + ucdata = NULL; + } + return ucdata; + +} /* end of extract_izvms_block */ + + + + + +/********************************/ +/* Function decompress_bits() */ +/********************************/ +/* + * Simple uncompression routine. The compression uses bit stream. + * Compression scheme: + * + * if (byte!=0) + * putbit(1),putbyte(byte) + * else + * putbit(0) + */ +static void decompress_bits(outptr, needlen, bitptr) + uch *outptr; /* Pointer into output block */ + unsigned needlen; /* Size of uncompressed block */ + ZCONST uch *bitptr; /* Pointer into compressed data */ +{ + ulg bitbuf = 0; + int bitcnt = 0; + +#define _FILL { bitbuf |= (*bitptr++) << bitcnt;\ + bitcnt += 8; \ + } + + while (needlen--) + { + if (bitcnt <= 0) + _FILL; + + if (bitbuf & 1) + { + bitbuf >>= 1; + if ((bitcnt -= 1) < 8) + _FILL; + *outptr++ = (uch)bitbuf; + bitcnt -= 8; + bitbuf >>= 8; + } + else + { + *outptr++ = '\0'; + bitcnt -= 1; + bitbuf >>= 1; + } + } +} /* end function decompress_bits() */ + +#endif /* VMS || VMS_TEXT_CONV */ + + + + + +#ifdef SYMLINKS +/***********************************/ +/* Function set_deferred_symlink() */ +/***********************************/ + +static void set_deferred_symlink(__G__ slnk_entry) + __GDEF + slinkentry *slnk_entry; +{ + extent ucsize = slnk_entry->targetlen; + char *linkfname = slnk_entry->fname; + char *linktarget = (char *)malloc(ucsize+1); + + if (!linktarget) { + Info(slide, 0x201, ((char *)slide, + LoadFarString(SymLnkWarnNoMem), FnFilter1(linkfname))); + return; + } + linktarget[ucsize] = '\0'; + G.outfile = zfopen(linkfname, FOPR); /* open link placeholder for reading */ + /* Check that the following conditions are all fulfilled: + * a) the placeholder file exists, + * b) the placeholder file contains exactly "ucsize" bytes + * (read the expected placeholder content length + 1 extra byte, this + * should return the expected content length), + * c) the placeholder content matches the link target specification as + * stored in the symlink control structure. + */ + if (!G.outfile || + fread(linktarget, 1, ucsize+1, G.outfile) != ucsize || + strcmp(slnk_entry->target, linktarget)) + { + Info(slide, 0x201, ((char *)slide, + LoadFarString(SymLnkWarnInvalid), FnFilter1(linkfname))); + free(linktarget); + if (G.outfile) + fclose(G.outfile); + return; + } + fclose(G.outfile); /* close "data" file for good... */ + unlink(linkfname); /* ...and delete it */ + if (QCOND2) + Info(slide, 0, ((char *)slide, LoadFarString(SymLnkFinish), + FnFilter1(linkfname), FnFilter2(linktarget))); + if (symlink(linktarget, linkfname)) /* create the real link */ + perror("symlink error"); + free(linktarget); +#ifdef SET_SYMLINK_ATTRIBS + set_symlnk_attribs(__G__ slnk_entry); +#endif + return; /* can't set time on symlinks */ + +} /* end function set_deferred_symlink() */ +#endif /* SYMLINKS */ + + + + +/*************************/ +/* Function fnfilter() */ /* here instead of in list.c for SFX */ +/*************************/ + +char *fnfilter(raw, space, size) /* convert name to safely printable form */ + ZCONST char *raw; + uch *space; + extent size; +{ +#ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */ + ZCONST uch *r=(ZCONST uch *)raw; + uch *s=space; + uch *slim=NULL; + uch *se=NULL; + int have_overflow = FALSE; + + if (size > 0) { + slim = space + size +#ifdef _MBCS + - (MB_CUR_MAX - 1) +#endif + - 4; + } + while (*r) { + if (size > 0 && s >= slim && se == NULL) { + se = s; + } +#ifdef QDOS + if (qlflag & 2) { + if (*r == '/' || *r == '.') { + if (se != NULL && (s > (space + (size-3)))) { + have_overflow = TRUE; + break; + } + ++r; + *s++ = '_'; + continue; + } + } else +#endif +#ifdef HAVE_WORKING_ISPRINT +# ifndef UZ_FNFILTER_REPLACECHAR + /* A convenient choice for the replacement of unprintable char codes is + * the "single char wildcard", as this character is quite unlikely to + * appear in filenames by itself. The following default definition + * sets the replacement char to a question mark as the most common + * "single char wildcard"; this setting should be overridden in the + * appropiate system-specific configuration header when needed. + */ +# define UZ_FNFILTER_REPLACECHAR '?' +# endif + if (!isprint(*r)) { + if (*r < 32) { + /* ASCII control codes are escaped as "^{letter}". */ + if (se != NULL && (s > (space + (size-4)))) { + have_overflow = TRUE; + break; + } + *s++ = '^', *s++ = (uch)(64 + *r++); + } else { + /* Other unprintable codes are replaced by the + * placeholder character. */ + if (se != NULL && (s > (space + (size-3)))) { + have_overflow = TRUE; + break; + } + *s++ = UZ_FNFILTER_REPLACECHAR; + INCSTR(r); + } +#else /* !HAVE_WORKING_ISPRINT */ + if (*r < 32) { + /* ASCII control codes are escaped as "^{letter}". */ + if (se != NULL && (s > (space + (size-4)))) { + have_overflow = TRUE; + break; + } + *s++ = '^', *s++ = (uch)(64 + *r++); +#endif /* ?HAVE_WORKING_ISPRINT */ + } else { +#ifdef _MBCS + unsigned i = CLEN(r); + if (se != NULL && (s > (space + (size-i-2)))) { + have_overflow = TRUE; + break; + } + for (; i > 0; i--) + *s++ = *r++; +#else + if (se != NULL && (s > (space + (size-3)))) { + have_overflow = TRUE; + break; + } + *s++ = *r++; +#endif + } + } + if (have_overflow) { + strcpy((char *)se, "..."); + } else { + *s = '\0'; + } + +#ifdef WINDLL + INTERN_TO_ISO((char *)space, (char *)space); /* translate to ANSI */ +#else +#if (defined(WIN32) && !defined(_WIN32_WCE)) + /* Win9x console always uses OEM character coding, and + WinNT console is set to OEM charset by default, too */ + INTERN_TO_OEM((char *)space, (char *)space); +#endif /* (WIN32 && !_WIN32_WCE) */ +#endif /* ?WINDLL */ + + return (char *)space; + +#else /* NATIVE: EBCDIC or whatever */ + return (char *)raw; +#endif + +} /* end function fnfilter() */ + + + + +#ifdef SET_DIR_ATTRIB +/* must sort saved directories so can set perms from bottom up */ + +/************************/ +/* Function dircomp() */ +/************************/ + +static int Cdecl dircomp(a, b) /* used by qsort(); swiped from Zip */ + ZCONST zvoid *a, *b; +{ + /* order is significant: this sorts in reverse order (deepest first) */ + return strcmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); + /* return namecmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); */ +} + +#endif /* SET_DIR_ATTRIB */ + + +#ifdef USE_BZIP2 + +/**************************/ +/* Function UZbunzip2() */ +/**************************/ + +int UZbunzip2(__G) +__GDEF +/* decompress a bzipped entry using the libbz2 routines */ +{ + int retval = 0; /* return code: 0 = "no error" */ + int err=BZ_OK; + int repeated_buf_err; + bz_stream bstrm; + +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) + wsize = G.redirect_size, redirSlide = G.redirect_buffer; + else + wsize = WSIZE, redirSlide = slide; +#endif + + bstrm.next_out = (char *)redirSlide; + bstrm.avail_out = wsize; + + bstrm.next_in = (char *)G.inptr; + bstrm.avail_in = G.incnt; + + { + /* local buffer for efficiency */ + /* $TODO Check for BZIP LIB version? */ + + bstrm.bzalloc = NULL; + bstrm.bzfree = NULL; + bstrm.opaque = NULL; + + Trace((stderr, "initializing bzlib()\n")); + err = BZ2_bzDecompressInit(&bstrm, 0, 0); + + if (err == BZ_MEM_ERROR) + return 3; + else if (err != BZ_OK) + Trace((stderr, "oops! (BZ2_bzDecompressInit() err = %d)\n", err)); + } + +#ifdef FUNZIP + while (err != BZ_STREAM_END) { +#else /* !FUNZIP */ + while (G.csize > 0) { + Trace((stderr, "first loop: G.csize = %ld\n", G.csize)); +#endif /* ?FUNZIP */ + while (bstrm.avail_out > 0) { + err = BZ2_bzDecompress(&bstrm); + + if (err == BZ_DATA_ERROR) { + retval = 2; goto uzbunzip_cleanup_exit; + } else if (err == BZ_MEM_ERROR) { + retval = 3; goto uzbunzip_cleanup_exit; + } else if (err != BZ_OK && err != BZ_STREAM_END) + Trace((stderr, "oops! (bzip(first loop) err = %d)\n", err)); + +#ifdef FUNZIP + if (err == BZ_STREAM_END) /* "END-of-entry-condition" ? */ +#else /* !FUNZIP */ + if (G.csize <= 0L) /* "END-of-entry-condition" ? */ +#endif /* ?FUNZIP */ + break; + + if (bstrm.avail_in == 0) { + if (fillinbuf(__G) == 0) { + /* no "END-condition" yet, but no more data */ + retval = 2; goto uzbunzip_cleanup_exit; + } + + bstrm.next_in = (char *)G.inptr; + bstrm.avail_in = G.incnt; + } + Trace((stderr, " avail_in = %u\n", bstrm.avail_in)); + } + /* flush slide[] */ + if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0) + goto uzbunzip_cleanup_exit; + Trace((stderr, "inside loop: flushing %ld bytes (ptr diff = %ld)\n", + (long)(wsize - bstrm.avail_out), + (long)(bstrm.next_out-(char *)redirSlide))); + bstrm.next_out = (char *)redirSlide; + bstrm.avail_out = wsize; + } + + /* no more input, so loop until we have all output */ + Trace((stderr, "beginning final loop: err = %d\n", err)); + repeated_buf_err = FALSE; + while (err != BZ_STREAM_END) { + err = BZ2_bzDecompress(&bstrm); + if (err == BZ_DATA_ERROR) { + retval = 2; goto uzbunzip_cleanup_exit; + } else if (err == BZ_MEM_ERROR) { + retval = 3; goto uzbunzip_cleanup_exit; + } else if (err != BZ_OK && err != BZ_STREAM_END) { + Trace((stderr, "oops! (bzip(final loop) err = %d)\n", err)); + DESTROYGLOBALS(); + EXIT(PK_MEM3); + } + /* final flush of slide[] */ + if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0) + goto uzbunzip_cleanup_exit; + Trace((stderr, "final loop: flushing %ld bytes (ptr diff = %ld)\n", + (long)(wsize - bstrm.avail_out), + (long)(bstrm.next_out-(char *)redirSlide))); + bstrm.next_out = (char *)redirSlide; + bstrm.avail_out = wsize; + } +#ifdef LARGE_FILE_SUPPORT + Trace((stderr, "total in = %llu, total out = %llu\n", + (zusz_t)(bstrm.total_in_lo32) + ((zusz_t)(bstrm.total_in_hi32))<<32, + (zusz_t)(bstrm.total_out_lo32) + ((zusz_t)(bstrm.total_out_hi32))<<32)); +#else + Trace((stderr, "total in = %lu, total out = %lu\n", bstrm.total_in_lo32, + bstrm.total_out_lo32)); +#endif + + G.inptr = (uch *)bstrm.next_in; + G.incnt = (G.inbuf + INBUFSIZ) - G.inptr; /* reset for other routines */ + +uzbunzip_cleanup_exit: + err = BZ2_bzDecompressEnd(&bstrm); + if (err != BZ_OK) + Trace((stderr, "oops! (BZ2_bzDecompressEnd() err = %d)\n", err)); + + return retval; +} /* end function UZbunzip2() */ +#endif /* USE_BZIP2 */ diff --git a/file_id.diz b/file_id.diz new file mode 100644 index 0000000..af244ec --- /dev/null +++ b/file_id.diz @@ -0,0 +1,10 @@ +Info-ZIP's UnZip 6.0: generic C sources + Complete C source code for Info-ZIP's + PKUNZIP-compatible .zip extractor, for + all supported compilers and platforms + (Unix, OS/2, MS-DOS, NT, VMS, Amiga, + Atari, Mac, Acorn, VM/CMS, etc.), plus + lots of pretty decent documentation. +This is FREE (but copyrighted) software. +See LICENSE for details on distribution +and reuse. diff --git a/fileio.c b/fileio.c new file mode 100644 index 0000000..ba0a1d0 --- /dev/null +++ b/fileio.c @@ -0,0 +1,2855 @@ +/* + Copyright (c) 1990-2009 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2009-Jan-02 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 +*/ +/*--------------------------------------------------------------------------- + + fileio.c + + This file contains routines for doing direct but relatively generic input/ + output, file-related sorts of things, plus some miscellaneous stuff. Most + of the stuff has to do with opening, closing, reading and/or writing files. + + Contains: open_input_file() + open_outfile() (not: VMS, AOS/VS, CMSMVS, MACOS, TANDEM) + undefer_input() + defer_leftover_input() + readbuf() + readbyte() + fillinbuf() + seek_zipf() + flush() (non-VMS) + is_vms_varlen_txt() (non-VMS, VMS_TEXT_CONV only) + disk_error() (non-VMS) + UzpMessagePrnt() + UzpMessageNull() (DLL only) + UzpInput() + UzpMorePause() + UzpPassword() (non-WINDLL) + handler() + dos_to_unix_time() (non-VMS, non-VM/CMS, non-MVS) + check_for_newer() (non-VMS, non-OS/2, non-VM/CMS, non-MVS) + do_string() + makeword() + makelong() + makeint64() + fzofft() + str2iso() (CRYPT && NEED_STR2ISO, only) + str2oem() (CRYPT && NEED_STR2OEM, only) + memset() (ZMEM only) + memcpy() (ZMEM only) + zstrnicmp() (NO_STRNICMP only) + zstat() (REGULUS only) + plastchar() (_MBCS only) + uzmbclen() (_MBCS && NEED_UZMBCLEN, only) + uzmbschr() (_MBCS && NEED_UZMBSCHR, only) + uzmbsrchr() (_MBCS && NEED_UZMBSRCHR, only) + fLoadFarString() (SMALL_MEM only) + fLoadFarStringSmall() (SMALL_MEM only) + fLoadFarStringSmall2() (SMALL_MEM only) + zfstrcpy() (SMALL_MEM only) + zfstrcmp() (SMALL_MEM && !(SFX || FUNZIP) only) + + ---------------------------------------------------------------------------*/ + + +#define __FILEIO_C /* identifies this source module */ +#define UNZIP_INTERNAL +#include "unzip.h" +#ifdef WINDLL +# ifdef POCKET_UNZIP +# include "wince/intrface.h" +# else +# include "windll/windll.h" +# endif +# include +#endif +#include "crc32.h" +#include "crypt.h" +#include "ttyio.h" + +/* setup of codepage conversion for decryption passwords */ +#if CRYPT +# if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY)) +# define IZ_ISO2OEM_ARRAY /* pull in iso2oem[] table */ +# endif +# if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY)) +# define IZ_OEM2ISO_ARRAY /* pull in oem2iso[] table */ +# endif +#endif +#include "ebcdic.h" /* definition/initialization of ebcdic[] */ + + +/* + Note: Under Windows, the maximum size of the buffer that can be used + with any of the *printf calls is 16,384, so win_fprintf was used to + feed the fprintf clone no more than 16K chunks at a time. This should + be valid for anything up to 64K (and probably beyond, assuming your + buffers are that big). +*/ +#ifdef WINDLL +# define WriteError(buf,len,strm) \ + (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len)) +#else /* !WINDLL */ +# ifdef USE_FWRITE +# define WriteError(buf,len,strm) \ + ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len)) +# else +# define WriteError(buf,len,strm) \ + ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len)) +# endif +#endif /* ?WINDLL */ + +/* + 2005-09-16 SMS. + On VMS, when output is redirected to a file, as in a command like + "PIPE UNZIP -v > X.OUT", the output file is created with VFC record + format, and multiple calls to write() or fwrite() will produce multiple + records, even when there's no newline terminator in the buffer. + The result is unsightly output with spurious newlines. Using fprintf() + instead of write() here, and disabling a fflush(stdout) in UzpMessagePrnt() + below, together seem to solve the problem. + + According to the C RTL manual, "The write and decc$record_write + functions always generate at least one record." Also, "[T]he fwrite + function always generates at least records." So, + "fwrite(buf, len, 1, strm)" is much better ("1" record) than + "fwrite(buf, 1, len, strm)" ("len" (1-character) records, _really_ + ugly), but neither is better than write(). Similarly, "The fflush + function always generates a record if there is unwritten data in the + buffer." Apparently fprintf() buffers the stuff somewhere, and puts + out a record (only) when it sees a newline. +*/ +#ifdef VMS +# define WriteTxtErr(buf,len,strm) \ + ((extent)fprintf(strm, "%.*s", len, buf) != (extent)(len)) +#else +# define WriteTxtErr(buf,len,strm) WriteError(buf,len,strm) +#endif + +#if (defined(USE_DEFLATE64) && defined(__16BIT__)) +static int partflush OF((__GPRO__ uch *rawbuf, ulg size, int unshrink)); +#endif +#ifdef VMS_TEXT_CONV +static int is_vms_varlen_txt OF((__GPRO__ uch *ef_buf, unsigned ef_len)); +#endif +static int disk_error OF((__GPRO)); + + +/****************************/ +/* Strings used in fileio.c */ +/****************************/ + +static ZCONST char Far CannotOpenZipfile[] = + "error: cannot open zipfile [ %s ]\n %s\n"; + +#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) +#if (!defined(TANDEM)) +#if (defined(ATH_BEO_THS_UNX) || defined(DOS_FLX_NLM_OS2_W32)) + static ZCONST char Far CannotDeleteOldFile[] = + "error: cannot delete old %s\n %s\n"; +#ifdef UNIXBACKUP + static ZCONST char Far CannotRenameOldFile[] = + "error: cannot rename old %s\n %s\n"; + static ZCONST char Far BackupSuffix[] = "~"; +#endif +#endif /* ATH_BEO_THS_UNX || DOS_FLX_NLM_OS2_W32 */ +#ifdef NOVELL_BUG_FAILSAFE + static ZCONST char Far NovellBug[] = + "error: %s: stat() says does not exist, but fopen() found anyway\n"; +#endif + static ZCONST char Far CannotCreateFile[] = + "error: cannot create %s\n %s\n"; +#endif /* !TANDEM */ +#endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */ + +static ZCONST char Far ReadError[] = "error: zipfile read error\n"; +static ZCONST char Far FilenameTooLongTrunc[] = + "warning: filename too long--truncating.\n"; +#ifdef UNICODE_SUPPORT + static ZCONST char Far UFilenameTooLongTrunc[] = + "warning: Converted unicode filename too long--truncating.\n"; +#endif +static ZCONST char Far ExtraFieldTooLong[] = + "warning: extra field too long (%d). Ignoring...\n"; + +#ifdef WINDLL + static ZCONST char Far DiskFullQuery[] = + "%s: write error (disk full?).\n"; +#else + static ZCONST char Far DiskFullQuery[] = + "%s: write error (disk full?). Continue? (y/n/^C) "; + static ZCONST char Far ZipfileCorrupt[] = + "error: zipfile probably corrupt (%s)\n"; +# ifdef SYMLINKS + static ZCONST char Far FileIsSymLink[] = + "%s exists and is a symbolic link%s.\n"; +# endif +# ifdef MORE + static ZCONST char Far MorePrompt[] = "--More--(%lu)"; +# endif + static ZCONST char Far QuitPrompt[] = + "--- Press `Q' to quit, or any other key to continue ---"; + static ZCONST char Far HidePrompt[] = /* "\r \r"; */ + "\r \r"; +# if CRYPT +# ifdef MACOS + /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */ + static ZCONST char Far PasswPrompt[] = "[%s]\n %s password: "; +# else + static ZCONST char Far PasswPrompt[] = "[%s] %s password: "; +# endif + static ZCONST char Far PasswPrompt2[] = "Enter password: "; + static ZCONST char Far PasswRetry[] = "password incorrect--reenter: "; +# endif /* CRYPT */ +#endif /* !WINDLL */ + + + + + +/******************************/ +/* Function open_input_file() */ +/******************************/ + +int open_input_file(__G) /* return 1 if open failed */ + __GDEF +{ + /* + * open the zipfile for reading and in BINARY mode to prevent cr/lf + * translation, which would corrupt the bitstreams + */ + +#ifdef VMS + G.zipfd = open(G.zipfn, O_RDONLY, 0, OPNZIP_RMS_ARGS); +#else /* !VMS */ +#ifdef MACOS + G.zipfd = open(G.zipfn, 0); +#else /* !MACOS */ +#ifdef CMS_MVS + G.zipfd = vmmvs_open_infile(__G); +#else /* !CMS_MVS */ +#ifdef USE_STRM_INPUT + G.zipfd = fopen(G.zipfn, FOPR); +#else /* !USE_STRM_INPUT */ + G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY); +#endif /* ?USE_STRM_INPUT */ +#endif /* ?CMS_MVS */ +#endif /* ?MACOS */ +#endif /* ?VMS */ + +#ifdef USE_STRM_INPUT + if (G.zipfd == NULL) +#else + /* if (G.zipfd < 0) */ /* no good for Windows CE port */ + if (G.zipfd == -1) +#endif + { + Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile), + G.zipfn, strerror(errno))); + return 1; + } + return 0; + +} /* end function open_input_file() */ + + + + +#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) +#if (!defined(TANDEM)) + +/***************************/ +/* Function open_outfile() */ +/***************************/ + +int open_outfile(__G) /* return 1 if fail */ + __GDEF +{ +#ifdef DLL + if (G.redirect_data) + return (redirect_outfile(__G) == FALSE); +#endif +#ifdef QDOS + QFilename(__G__ G.filename); +#endif +#if (defined(DOS_FLX_NLM_OS2_W32) || defined(ATH_BEO_THS_UNX)) +#ifdef BORLAND_STAT_BUG + /* Borland 5.0's stat() barfs if the filename has no extension and the + * file doesn't exist. */ + if (access(G.filename, 0) == -1) { + FILE *tmp = fopen(G.filename, "wb+"); + + /* file doesn't exist, so create a dummy file to keep stat() from + * failing (will be over-written anyway) */ + fputc('0', tmp); /* just to have something in the file */ + fclose(tmp); + } +#endif /* BORLAND_STAT_BUG */ +#ifdef SYMLINKS + if (SSTAT(G.filename, &G.statbuf) == 0 || + lstat(G.filename, &G.statbuf) == 0) +#else + if (SSTAT(G.filename, &G.statbuf) == 0) +#endif /* ?SYMLINKS */ + { + Trace((stderr, "open_outfile: stat(%s) returns 0: file exists\n", + FnFilter1(G.filename))); +#ifdef UNIXBACKUP + if (uO.B_flag) { /* do backup */ + char *tname; + z_stat tmpstat; + int blen, flen, tlen; + + blen = strlen(BackupSuffix); + flen = strlen(G.filename); + tlen = flen + blen + 6; /* includes space for 5 digits */ + if (tlen >= FILNAMSIZ) { /* in case name is too long, truncate */ + tname = (char *)malloc(FILNAMSIZ); + if (tname == NULL) + return 1; /* in case we run out of space */ + tlen = FILNAMSIZ - 1 - blen; + strcpy(tname, G.filename); /* make backup name */ + tname[tlen] = '\0'; + if (flen > tlen) flen = tlen; + tlen = FILNAMSIZ; + } else { + tname = (char *)malloc(tlen); + if (tname == NULL) + return 1; /* in case we run out of space */ + strcpy(tname, G.filename); /* make backup name */ + } + strcpy(tname+flen, BackupSuffix); + + if (IS_OVERWRT_ALL) { + /* If there is a previous backup file, delete it, + * otherwise the following rename operation may fail. + */ + if (SSTAT(tname, &tmpstat) == 0) + unlink(tname); + } else { + /* Check if backupname exists, and, if it's true, try + * appending numbers of up to 5 digits (or the maximum + * "unsigned int" number on 16-bit systems) to the + * BackupSuffix, until an unused name is found. + */ + unsigned maxtail, i; + char *numtail = tname + flen + blen; + + /* take account of the "unsigned" limit on 16-bit systems: */ + maxtail = ( ((~0) >= 99999L) ? 99999 : (~0) ); + switch (tlen - flen - blen - 1) { + case 4: maxtail = 9999; break; + case 3: maxtail = 999; break; + case 2: maxtail = 99; break; + case 1: maxtail = 9; break; + case 0: maxtail = 0; break; + } + /* while filename exists */ + for (i = 0; (i < maxtail) && (SSTAT(tname, &tmpstat) == 0);) + sprintf(numtail,"%u", ++i); + } + + if (rename(G.filename, tname) != 0) { /* move file */ + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotRenameOldFile), + FnFilter1(G.filename), strerror(errno))); + free(tname); + return 1; + } + Trace((stderr, "open_outfile: %s now renamed into %s\n", + FnFilter1(G.filename), FnFilter2(tname))); + free(tname); + } else +#endif /* UNIXBACKUP */ + { +#ifdef DOS_FLX_OS2_W32 + if (!(G.statbuf.st_mode & S_IWRITE)) { + Trace((stderr, + "open_outfile: existing file %s is read-only\n", + FnFilter1(G.filename))); + chmod(G.filename, S_IREAD | S_IWRITE); + Trace((stderr, "open_outfile: %s now writable\n", + FnFilter1(G.filename))); + } +#endif /* DOS_FLX_OS2_W32 */ +#ifdef NLM + /* Give the file read/write permission (non-POSIX shortcut) */ + chmod(G.filename, 0); +#endif /* NLM */ + if (unlink(G.filename) != 0) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotDeleteOldFile), + FnFilter1(G.filename), strerror(errno))); + return 1; + } + Trace((stderr, "open_outfile: %s now deleted\n", + FnFilter1(G.filename))); + } + } +#endif /* DOS_FLX_NLM_OS2_W32 || ATH_BEO_THS_UNX */ +#ifdef RISCOS + if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) { + Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), + FnFilter1(G.filename), strerror(errno))); + return 1; + } +#endif /* RISCOS */ +#ifdef TOPS20 + char *tfilnam; + + if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL) + return 1; + strcpy(tfilnam, G.filename); + upper(tfilnam); + enquote(tfilnam); + if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) { + Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), + tfilnam, strerror(errno))); + free(tfilnam); + return 1; + } + free(tfilnam); +#else /* !TOPS20 */ +#ifdef MTS + if (uO.aflag) + G.outfile = zfopen(G.filename, FOPWT); + else + G.outfile = zfopen(G.filename, FOPW); + if (G.outfile == (FILE *)NULL) { + Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), + FnFilter1(G.filename), strerror(errno))); + return 1; + } +#else /* !MTS */ +#ifdef DEBUG + Info(slide, 1, ((char *)slide, + "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G.filename))); + if ((G.outfile = zfopen(G.filename, FOPR)) == (FILE *)NULL) + Info(slide, 1, ((char *)slide, + "open_outfile: fopen(%s) for reading failed: does not exist\n", + FnFilter1(G.filename))); + else { + Info(slide, 1, ((char *)slide, + "open_outfile: fopen(%s) for reading succeeded: file exists\n", + FnFilter1(G.filename))); + fclose(G.outfile); + } +#endif /* DEBUG */ +#ifdef NOVELL_BUG_FAILSAFE + if (G.dne && ((G.outfile = zfopen(G.filename, FOPR)) != (FILE *)NULL)) { + Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug), + FnFilter1(G.filename))); + fclose(G.outfile); + return 1; /* with "./" fix in checkdir(), should never reach here */ + } +#endif /* NOVELL_BUG_FAILSAFE */ + Trace((stderr, "open_outfile: doing fopen(%s) for writing\n", + FnFilter1(G.filename))); + { +#if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM) + mode_t umask_sav = umask(0077); +#endif +#if defined(SYMLINKS) || defined(QLZIP) + /* These features require the ability to re-read extracted data from + the output files. Output files are created with Read&Write access. + */ + G.outfile = zfopen(G.filename, FOPWR); +#else + G.outfile = zfopen(G.filename, FOPW); +#endif +#if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM) + umask(umask_sav); +#endif + } + if (G.outfile == (FILE *)NULL) { + Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile), + FnFilter1(G.filename), strerror(errno))); + return 1; + } + Trace((stderr, "open_outfile: fopen(%s) for writing succeeded\n", + FnFilter1(G.filename))); +#endif /* !MTS */ +#endif /* !TOPS20 */ + +#ifdef USE_FWRITE +#ifdef DOS_NLM_OS2_W32 + /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */ + setbuf(G.outfile, (char *)NULL); /* make output unbuffered */ +#else /* !DOS_NLM_OS2_W32 */ +#ifndef RISCOS +#ifdef _IOFBF /* make output fully buffered (works just about like write()) */ + setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE); +#else + setbuf(G.outfile, (char *)slide); +#endif +#endif /* !RISCOS */ +#endif /* ?DOS_NLM_OS2_W32 */ +#endif /* USE_FWRITE */ +#ifdef OS2_W32 + /* preallocate the final file size to prevent file fragmentation */ + SetFileSize(G.outfile, G.lrec.ucsize); +#endif + return 0; + +} /* end function open_outfile() */ + +#endif /* !TANDEM */ +#endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */ + + + + + +/* + * These functions allow NEXTBYTE to function without needing two bounds + * checks. Call defer_leftover_input() if you ever have filled G.inbuf + * by some means other than readbyte(), and you then want to start using + * NEXTBYTE. When going back to processing bytes without NEXTBYTE, call + * undefer_input(). For example, extract_or_test_member brackets its + * central section that does the decompression with these two functions. + * If you need to check the number of bytes remaining in the current + * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize. + */ + +/****************************/ +/* function undefer_input() */ +/****************************/ + +void undefer_input(__G) + __GDEF +{ + if (G.incnt > 0) + G.csize += G.incnt; + if (G.incnt_leftover > 0) { + /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int: + * This condition was checked when G.incnt_leftover was set > 0 in + * defer_leftover_input(), and it is NOT allowed to touch G.csize + * before calling undefer_input() when (G.incnt_leftover > 0) + * (single exception: see read_byte()'s "G.csize <= 0" handling) !! + */ + G.incnt = G.incnt_leftover + (int)G.csize; + G.inptr = G.inptr_leftover - (int)G.csize; + G.incnt_leftover = 0; + } else if (G.incnt < 0) + G.incnt = 0; +} /* end function undefer_input() */ + + + + + +/***********************************/ +/* function defer_leftover_input() */ +/***********************************/ + +void defer_leftover_input(__G) + __GDEF +{ + if ((zoff_t)G.incnt > G.csize) { + /* (G.csize < MAXINT), we can safely cast it to int !! */ + if (G.csize < 0L) + G.csize = 0L; + G.inptr_leftover = G.inptr + (int)G.csize; + G.incnt_leftover = G.incnt - (int)G.csize; + G.incnt = (int)G.csize; + } else + G.incnt_leftover = 0; + G.csize -= G.incnt; +} /* end function defer_leftover_input() */ + + + + + +/**********************/ +/* Function readbuf() */ +/**********************/ + +unsigned readbuf(__G__ buf, size) /* return number of bytes read into buf */ + __GDEF + char *buf; + register unsigned size; +{ + register unsigned count; + unsigned n; + + n = size; + while (size) { + if (G.incnt <= 0) { + if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) + return (n-size); + else if (G.incnt < 0) { + /* another hack, but no real harm copying same thing twice */ + (*G.message)((zvoid *)&G, + (uch *)LoadFarString(ReadError), /* CANNOT use slide */ + (ulg)strlen(LoadFarString(ReadError)), 0x401); + return 0; /* discarding some data; better than lock-up */ + } + /* buffer ALWAYS starts on a block boundary: */ + G.cur_zipfile_bufstart += INBUFSIZ; + G.inptr = G.inbuf; + } + count = MIN(size, (unsigned)G.incnt); + memcpy(buf, G.inptr, count); + buf += count; + G.inptr += count; + G.incnt -= count; + size -= count; + } + return n; + +} /* end function readbuf() */ + + + + + +/***********************/ +/* Function readbyte() */ +/***********************/ + +int readbyte(__G) /* refill inbuf and return a byte if available, else EOF */ + __GDEF +{ + if (G.mem_mode) + return EOF; + if (G.csize <= 0) { + G.csize--; /* for tests done after exploding */ + G.incnt = 0; + return EOF; + } + if (G.incnt <= 0) { + if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) { + return EOF; + } else if (G.incnt < 0) { /* "fail" (abort, retry, ...) returns this */ + /* another hack, but no real harm copying same thing twice */ + (*G.message)((zvoid *)&G, + (uch *)LoadFarString(ReadError), + (ulg)strlen(LoadFarString(ReadError)), 0x401); + echon(); +#ifdef WINDLL + longjmp(dll_error_return, 1); +#else + DESTROYGLOBALS(); + EXIT(PK_BADERR); /* totally bailing; better than lock-up */ +#endif + } + G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */ + G.inptr = G.inbuf; + defer_leftover_input(__G); /* decrements G.csize */ + } + +#if CRYPT + if (G.pInfo->encrypted) { + uch *p; + int n; + + /* This was previously set to decrypt one byte beyond G.csize, when + * incnt reached that far. GRR said, "but it's required: why?" This + * was a bug in fillinbuf() -- was it also a bug here? + */ + for (n = G.incnt, p = G.inptr; n--; p++) + zdecode(*p); + } +#endif /* CRYPT */ + + --G.incnt; + return *G.inptr++; + +} /* end function readbyte() */ + + + + + +#if defined(USE_ZLIB) || defined(USE_BZIP2) + +/************************/ +/* Function fillinbuf() */ +/************************/ + +int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */ + __GDEF +{ + if (G.mem_mode || + (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) + return 0; + G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on a block boundary */ + G.inptr = G.inbuf; + defer_leftover_input(__G); /* decrements G.csize */ + +#if CRYPT + if (G.pInfo->encrypted) { + uch *p; + int n; + + for (n = G.incnt, p = G.inptr; n--; p++) + zdecode(*p); + } +#endif /* CRYPT */ + + return G.incnt; + +} /* end function fillinbuf() */ + +#endif /* USE_ZLIB || USE_BZIP2 */ + + + + + +/************************/ +/* Function seek_zipf() */ +/************************/ + +int seek_zipf(__G__ abs_offset) + __GDEF + zoff_t abs_offset; +{ +/* + * Seek to the block boundary of the block which includes abs_offset, + * then read block into input buffer and set pointers appropriately. + * If block is already in the buffer, just set the pointers. This function + * is used by do_seekable (process.c), extract_or_test_entrylist (extract.c) + * and do_string (fileio.c). Also, a slightly modified version is embedded + * within extract_or_test_entrylist (extract.c). readbyte() and readbuf() + * (fileio.c) are compatible. NOTE THAT abs_offset is intended to be the + * "proper offset" (i.e., if there were no extra bytes prepended); + * cur_zipfile_bufstart contains the corrected offset. + * + * Since seek_zipf() is never used during decompression, it is safe to + * use the slide[] buffer for the error message. + * + * returns PK error codes: + * PK_BADERR if effective offset in zipfile is negative + * PK_EOF if seeking past end of zipfile + * PK_OK when seek was successful + */ + zoff_t request = abs_offset + G.extra_bytes; + zoff_t inbuf_offset = request % INBUFSIZ; + zoff_t bufstart = request - inbuf_offset; + + if (request < 0) { + Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg), + G.zipfn, LoadFarString(ReportMsg))); + return(PK_BADERR); + } else if (bufstart != G.cur_zipfile_bufstart) { + Trace((stderr, + "fpos_zip: abs_offset = %s, G.extra_bytes = %s\n", + FmZofft(abs_offset, NULL, NULL), + FmZofft(G.extra_bytes, NULL, NULL))); +#ifdef USE_STRM_INPUT + zfseeko(G.zipfd, bufstart, SEEK_SET); + G.cur_zipfile_bufstart = zftello(G.zipfd); +#else /* !USE_STRM_INPUT */ + G.cur_zipfile_bufstart = zlseek(G.zipfd, bufstart, SEEK_SET); +#endif /* ?USE_STRM_INPUT */ + Trace((stderr, + " request = %s, (abs+extra) = %s, inbuf_offset = %s\n", + FmZofft(request, NULL, NULL), + FmZofft((abs_offset+G.extra_bytes), NULL, NULL), + FmZofft(inbuf_offset, NULL, NULL))); + Trace((stderr, " bufstart = %s, cur_zipfile_bufstart = %s\n", + FmZofft(bufstart, NULL, NULL), + FmZofft(G.cur_zipfile_bufstart, NULL, NULL))); + if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) + return(PK_EOF); + G.incnt -= (int)inbuf_offset; + G.inptr = G.inbuf + (int)inbuf_offset; + } else { + G.incnt += (G.inptr-G.inbuf) - (int)inbuf_offset; + G.inptr = G.inbuf + (int)inbuf_offset; + } + return(PK_OK); +} /* end function seek_zipf() */ + + + + + +#ifndef VMS /* for VMS use code in vms.c */ + +/********************/ +/* Function flush() */ /* returns PK error codes: */ +/********************/ /* if tflag => always 0; PK_DISK if write error */ + +int flush(__G__ rawbuf, size, unshrink) + __GDEF + uch *rawbuf; + ulg size; + int unshrink; +#if (defined(USE_DEFLATE64) && defined(__16BIT__)) +{ + int ret; + + /* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions + * cannot handle writes of 64k blocks at once. For these systems, the + * blocks to flush are split into pieces of 32k or less. + */ + while (size > 0x8000L) { + ret = partflush(__G__ rawbuf, 0x8000L, unshrink); + if (ret != PK_OK) + return ret; + size -= 0x8000L; + rawbuf += (extent)0x8000; + } + return partflush(__G__ rawbuf, size, unshrink); +} /* end function flush() */ + + +/************************/ +/* Function partflush() */ /* returns PK error codes: */ +/************************/ /* if tflag => always 0; PK_DISK if write error */ + +static int partflush(__G__ rawbuf, size, unshrink) + __GDEF + uch *rawbuf; /* cannot be ZCONST, gets passed to (*G.message)() */ + ulg size; + int unshrink; +#endif /* USE_DEFLATE64 && __16BIT__ */ +{ + register uch *p; + register uch *q; + uch *transbuf; +#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) + ulg transbufsiz; +#endif + /* static int didCRlast = FALSE; moved to globals.h */ + + +/*--------------------------------------------------------------------------- + Compute the CRC first; if testing or if disk is full, that's it. + ---------------------------------------------------------------------------*/ + + G.crc32val = crc32(G.crc32val, rawbuf, (extent)size); + +#ifdef DLL + if ((G.statreportcb != NULL) && + (*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL)) + return IZ_CTRLC; /* cancel operation by user request */ +#endif + + if (uO.tflag || size == 0L) /* testing or nothing to write: all done */ + return PK_OK; + + if (G.disk_full) + return PK_DISK; /* disk already full: ignore rest of file */ + +/*--------------------------------------------------------------------------- + Write the bytes rawbuf[0..size-1] to the output device, first converting + end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT + defined, outbuf is assumed to be at least as large as rawbuf and is not + necessarily checked for overflow. + ---------------------------------------------------------------------------*/ + + if (!G.pInfo->textmode) { /* write raw binary data */ + /* GRR: note that for standard MS-DOS compilers, size argument to + * fwrite() can never be more than 65534, so WriteError macro will + * have to be rewritten if size can ever be that large. For now, + * never more than 32K. Also note that write() returns an int, which + * doesn't necessarily limit size to 32767 bytes if write() is used + * on 16-bit systems but does make it more of a pain; however, because + * at least MSC 5.1 has a lousy implementation of fwrite() (as does + * DEC Ultrix cc), write() is used anyway. + */ +#ifdef DLL + if (G.redirect_data) { +#ifdef NO_SLIDE_REDIR + if (writeToMemory(__G__ rawbuf, (extent)size)) return PK_ERR; +#else + writeToMemory(__G__ rawbuf, (extent)size); +#endif + } else +#endif + if (!uO.cflag && WriteError(rawbuf, size, G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0)) + return PK_OK; + } else { /* textmode: aflag is true */ + if (unshrink) { + /* rawbuf = outbuf */ + transbuf = G.outbuf2; +#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) + transbufsiz = TRANSBUFSIZ; +#endif + } else { + /* rawbuf = slide */ + transbuf = G.outbuf; +#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) + transbufsiz = OUTBUFSIZ; + Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n", + (unsigned)OUTBUFSIZ)); +#endif + } + if (G.newfile) { +#ifdef VMS_TEXT_CONV + if (G.pInfo->hostnum == VMS_ && G.extra_field && + is_vms_varlen_txt(__G__ G.extra_field, + G.lrec.extra_field_length)) + G.VMS_line_state = 0; /* 0: ready to read line length */ + else + G.VMS_line_state = -1; /* -1: don't treat as VMS text */ +#endif + G.didCRlast = FALSE; /* no previous buffers written */ + G.newfile = FALSE; + } + +#ifdef VMS_TEXT_CONV + if (G.VMS_line_state >= 0) + { + p = rawbuf; + q = transbuf; + while ((extent)(p-rawbuf) < (extent)size) { + switch (G.VMS_line_state) { + + /* 0: ready to read line length */ + case 0: + G.VMS_line_length = 0; + if ((extent)(p-rawbuf) == (extent)size-1) { + /* last char */ + G.VMS_line_length = (unsigned)(*p++); + G.VMS_line_state = 1; + } else { + G.VMS_line_length = makeword(p); + p += 2; + G.VMS_line_state = 2; + } + G.VMS_line_pad = + ((G.VMS_line_length & 1) != 0); /* odd */ + break; + + /* 1: read one byte of length, need second */ + case 1: + G.VMS_line_length += ((unsigned)(*p++) << 8); + G.VMS_line_state = 2; + break; + + /* 2: ready to read VMS_line_length chars */ + case 2: + { + extent remaining = (extent)size+(rawbuf-p); + extent outroom; + + if (G.VMS_line_length < remaining) { + remaining = G.VMS_line_length; + G.VMS_line_state = 3; + } + + outroom = transbuf+(extent)transbufsiz-q; + if (remaining >= outroom) { + remaining -= outroom; + for (;outroom > 0; p++, outroom--) + *q++ = native(*p); +#ifdef DLL + if (G.redirect_data) { + if (writeToMemory(__G__ transbuf, + (extent)(q-transbuf))) return PK_ERR; + } else +#endif + if (!uO.cflag && WriteError(transbuf, + (extent)(q-transbuf), G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, + transbuf, (ulg)(q-transbuf), 0)) + return PK_OK; + q = transbuf; + /* fall through to normal case */ + } + G.VMS_line_length -= remaining; + for (;remaining > 0; p++, remaining--) + *q++ = native(*p); + } + break; + + /* 3: ready to PutNativeEOL */ + case 3: + if (q > transbuf+(extent)transbufsiz-lenEOL) { +#ifdef DLL + if (G.redirect_data) { + if (writeToMemory(__G__ transbuf, + (extent)(q-transbuf))) return PK_ERR; + } else +#endif + if (!uO.cflag && + WriteError(transbuf, (extent)(q-transbuf), + G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, + transbuf, (ulg)(q-transbuf), 0)) + return PK_OK; + q = transbuf; + } + PutNativeEOL + G.VMS_line_state = G.VMS_line_pad ? 4 : 0; + break; + + /* 4: ready to read pad byte */ + case 4: + ++p; + G.VMS_line_state = 0; + break; + } + } /* end while */ + + } else +#endif /* VMS_TEXT_CONV */ + + /*----------------------------------------------------------------------- + Algorithm: CR/LF => native; lone CR => native; lone LF => native. + This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e., + stream-oriented files, not record-oriented). + -----------------------------------------------------------------------*/ + + /* else not VMS text */ { + p = rawbuf; + if (*p == LF && G.didCRlast) + ++p; + G.didCRlast = FALSE; + for (q = transbuf; (extent)(p-rawbuf) < (extent)size; ++p) { + if (*p == CR) { /* lone CR or CR/LF: treat as EOL */ + PutNativeEOL + if ((extent)(p-rawbuf) == (extent)size-1) + /* last char in buffer */ + G.didCRlast = TRUE; + else if (p[1] == LF) /* get rid of accompanying LF */ + ++p; + } else if (*p == LF) /* lone LF */ + PutNativeEOL + else +#ifndef DOS_FLX_OS2_W32 + if (*p != CTRLZ) /* lose all ^Z's */ +#endif + *q++ = native(*p); + +#if (defined(SMALL_MEM) || defined(MED_MEM)) +# if (lenEOL == 1) /* don't check unshrink: both buffers small but equal */ + if (!unshrink) +# endif + /* check for danger of buffer overflow and flush */ + if (q > transbuf+(extent)transbufsiz-lenEOL) { + Trace((stderr, + "p - rawbuf = %u q-transbuf = %u size = %lu\n", + (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size)); + if (!uO.cflag && WriteError(transbuf, + (extent)(q-transbuf), G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, + transbuf, (ulg)(q-transbuf), 0)) + return PK_OK; + q = transbuf; + continue; + } +#endif /* SMALL_MEM || MED_MEM */ + } + } + + /*----------------------------------------------------------------------- + Done translating: write whatever we've got to file (or screen). + -----------------------------------------------------------------------*/ + + Trace((stderr, "p - rawbuf = %u q-transbuf = %u size = %lu\n", + (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size)); + if (q > transbuf) { +#ifdef DLL + if (G.redirect_data) { + if (writeToMemory(__G__ transbuf, (extent)(q-transbuf))) + return PK_ERR; + } else +#endif + if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf), + G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, + (ulg)(q-transbuf), 0)) + return PK_OK; + } + } + + return PK_OK; + +} /* end function flush() [resp. partflush() for 16-bit Deflate64 support] */ + + + + + +#ifdef VMS_TEXT_CONV + +/********************************/ +/* Function is_vms_varlen_txt() */ +/********************************/ + +static int is_vms_varlen_txt(__G__ ef_buf, ef_len) + __GDEF + uch *ef_buf; /* buffer containing extra field */ + unsigned ef_len; /* total length of extra field */ +{ + unsigned eb_id; + unsigned eb_len; + uch *eb_data; + unsigned eb_datlen; +#define VMSREC_C_UNDEF 0 +#define VMSREC_C_VAR 2 + uch vms_rectype = VMSREC_C_UNDEF; + /* uch vms_fileorg = 0; */ /* currently, fileorg is not used... */ + +#define VMSPK_ITEMID 0 +#define VMSPK_ITEMLEN 2 +#define VMSPK_ITEMHEADSZ 4 + +#define VMSATR_C_RECATTR 4 +#define VMS_FABSIG 0x42414656 /* "VFAB" */ +/* offsets of interesting fields in VMS fabdef structure */ +#define VMSFAB_B_RFM 31 /* record format byte */ +#define VMSFAB_B_ORG 29 /* file organization byte */ + + if (ef_len == 0 || ef_buf == NULL) + return FALSE; + + while (ef_len >= EB_HEADSIZE) { + eb_id = makeword(EB_ID + ef_buf); + eb_len = makeword(EB_LEN + ef_buf); + + if (eb_len > (ef_len - EB_HEADSIZE)) { + /* discovered some extra field inconsistency! */ + Trace((stderr, + "is_vms_varlen_txt: block length %u > rest ef_size %u\n", eb_len, + ef_len - EB_HEADSIZE)); + break; + } + + switch (eb_id) { + case EF_PKVMS: + /* The PKVMS e.f. raw data part consists of: + * a) 4 bytes CRC checksum + * b) list of uncompressed variable-length data items + * Each data item is introduced by a fixed header + * - 2 bytes data type ID + * - 2 bytes of data + * - bytes of actual attribute data + */ + + /* get pointer to start of data and its total length */ + eb_data = ef_buf+(EB_HEADSIZE+4); + eb_datlen = eb_len-4; + + /* test the CRC checksum */ + if (makelong(ef_buf+EB_HEADSIZE) != + crc32(CRCVAL_INITIAL, eb_data, (extent)eb_datlen)) + { + Info(slide, 1, ((char *)slide, + "[Warning: CRC error, discarding PKWARE extra field]\n")); + /* skip over the data analysis code */ + break; + } + + /* scan through the attribute data items */ + while (eb_datlen > 4) + { + unsigned fldsize = makeword(&eb_data[VMSPK_ITEMLEN]); + + /* check the item type word */ + switch (makeword(&eb_data[VMSPK_ITEMID])) { + case VMSATR_C_RECATTR: + /* we have found the (currently only) interesting + * data item */ + if (fldsize >= 1) { + vms_rectype = eb_data[VMSPK_ITEMHEADSZ] & 15; + /* vms_fileorg = eb_data[VMSPK_ITEMHEADSZ] >> 4; */ + } + break; + default: + break; + } + /* skip to next data item */ + eb_datlen -= fldsize + VMSPK_ITEMHEADSZ; + eb_data += fldsize + VMSPK_ITEMHEADSZ; + } + break; + + case EF_IZVMS: + if (makelong(ef_buf+EB_HEADSIZE) == VMS_FABSIG) { + if ((eb_data = extract_izvms_block(__G__ + ef_buf+EB_HEADSIZE, eb_len, + &eb_datlen, NULL, 0)) + != NULL) + { + if (eb_datlen >= VMSFAB_B_RFM+1) { + vms_rectype = eb_data[VMSFAB_B_RFM] & 15; + /* vms_fileorg = eb_data[VMSFAB_B_ORG] >> 4; */ + } + free(eb_data); + } + } + break; + + default: + break; + } + + /* Skip this extra field block */ + ef_buf += (eb_len + EB_HEADSIZE); + ef_len -= (eb_len + EB_HEADSIZE); + } + + return (vms_rectype == VMSREC_C_VAR); + +} /* end function is_vms_varlen_txtfile() */ + +#endif /* VMS_TEXT_CONV */ + + + + +/*************************/ +/* Function disk_error() */ +/*************************/ + +static int disk_error(__G) + __GDEF +{ + /* OK to use slide[] here because this file is finished regardless */ + Info(slide, 0x4a1, ((char *)slide, LoadFarString(DiskFullQuery), + FnFilter1(G.filename))); + +#ifndef WINDLL + fgets(G.answerbuf, sizeof(G.answerbuf), stdin); + if (*G.answerbuf == 'y') /* stop writing to this file */ + G.disk_full = 1; /* (outfile bad?), but new OK */ + else +#endif + G.disk_full = 2; /* no: exit program */ + + return PK_DISK; + +} /* end function disk_error() */ + +#endif /* !VMS */ + + + + + +/*****************************/ +/* Function UzpMessagePrnt() */ +/*****************************/ + +int UZ_EXP UzpMessagePrnt(pG, buf, size, flag) + zvoid *pG; /* globals struct: always passed */ + uch *buf; /* preformatted string to be printed */ + ulg size; /* length of string (may include nulls) */ + int flag; /* flag bits */ +{ + /* IMPORTANT NOTE: + * The name of the first parameter of UzpMessagePrnt(), which passes + * the "Uz_Globs" address, >>> MUST <<< be identical to the string + * expansion of the __G__ macro in the REENTRANT case (see globals.h). + * This name identity is mandatory for the LoadFarString() macro + * (in the SMALL_MEM case) !!! + */ + int error; + uch *q=buf, *endbuf=buf+(unsigned)size; +#ifdef MORE + uch *p=buf; +#if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) + int islinefeed = FALSE; +#endif +#endif + FILE *outfp; + + +/*--------------------------------------------------------------------------- + These tests are here to allow fine-tuning of UnZip's output messages, + but none of them will do anything without setting the appropriate bit + in the flag argument of every Info() statement which is to be turned + *off*. That is, all messages are currently turned on for all ports. + To turn off *all* messages, use the UzpMessageNull() function instead + of this one. + ---------------------------------------------------------------------------*/ + +#if (defined(OS2) && defined(DLL)) + if (MSG_NO_DLL2(flag)) /* if OS/2 DLL bit is set, do NOT print this msg */ + return 0; +#endif +#ifdef WINDLL + if (MSG_NO_WDLL(flag)) + return 0; +#endif +#ifdef WINDLL + if (MSG_NO_WGUI(flag)) + return 0; +#endif +/* +#ifdef ACORN_GUI + if (MSG_NO_AGUI(flag)) + return 0; +#endif + */ +#ifdef DLL /* don't display message if data is redirected */ + if (((Uz_Globs *)pG)->redirect_data && + !((Uz_Globs *)pG)->redirect_text) + return 0; +#endif + + if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag) + outfp = (FILE *)stderr; + else + outfp = (FILE *)stdout; + +#ifdef QUERY_TRNEWLN + /* some systems require termination of query prompts with '\n' to force + * immediate display */ + if (MSG_MNEWLN(flag)) { /* assumes writable buffer (e.g., slide[]) */ + *endbuf++ = '\n'; /* with room for one more char at end of buf */ + ++size; /* (safe assumption: only used for four */ + } /* short queries in extract.c and fileio.c) */ +#endif + + if (MSG_TNEWLN(flag)) { /* again assumes writable buffer: fragile... */ + if ((!size && !((Uz_Globs *)pG)->sol) || + (size && (endbuf[-1] != '\n'))) + { + *endbuf++ = '\n'; + ++size; + } + } + +#ifdef MORE +# ifdef SCREENSIZE + /* room for --More-- and one line of overlap: */ +# if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) + SCREENSIZE(&((Uz_Globs *)pG)->height, &((Uz_Globs *)pG)->width); +# else + SCREENSIZE(&((Uz_Globs *)pG)->height, (int *)NULL); +# endif + ((Uz_Globs *)pG)->height -= 2; +# else + /* room for --More-- and one line of overlap: */ + ((Uz_Globs *)pG)->height = SCREENLINES - 2; +# if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) + ((Uz_Globs *)pG)->width = SCREENWIDTH; +# endif +# endif +#endif /* MORE */ + + if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) { + /* not at start of line: want newline */ +#ifdef OS2DLL + if (!((Uz_Globs *)pG)->redirect_text) { +#endif + putc('\n', outfp); + fflush(outfp); +#ifdef MORE + if (((Uz_Globs *)pG)->M_flag) + { +#if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) + ((Uz_Globs *)pG)->chars = 0; +#endif + ++((Uz_Globs *)pG)->numlines; + ++((Uz_Globs *)pG)->lines; + if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height) + (*((Uz_Globs *)pG)->mpause)((zvoid *)pG, + LoadFarString(MorePrompt), 1); + } +#endif /* MORE */ + if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag && + !isatty(1) && isatty(2)) + { + /* error output from testing redirected: also send to stderr */ + putc('\n', stderr); + fflush(stderr); + } +#ifdef OS2DLL + } else + REDIRECTC('\n'); +#endif + ((Uz_Globs *)pG)->sol = TRUE; + } + + /* put zipfile name, filename and/or error/warning keywords here */ + +#ifdef MORE + if (((Uz_Globs *)pG)->M_flag +#ifdef OS2DLL + && !((Uz_Globs *)pG)->redirect_text +#endif + ) + { + while (p < endbuf) { + if (*p == '\n') { +#if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) + islinefeed = TRUE; + } else if (SCREENLWRAP) { + if (*p == '\r') { + ((Uz_Globs *)pG)->chars = 0; + } else { +# ifdef TABSIZE + if (*p == '\t') + ((Uz_Globs *)pG)->chars += + (TABSIZE - (((Uz_Globs *)pG)->chars % TABSIZE)); + else +# endif + ++((Uz_Globs *)pG)->chars; + + if (((Uz_Globs *)pG)->chars >= ((Uz_Globs *)pG)->width) + islinefeed = TRUE; + } + } + if (islinefeed) { + islinefeed = FALSE; + ((Uz_Globs *)pG)->chars = 0; +#endif /* (SCREENWIDTH && SCREEN_LWRAP) */ + ++((Uz_Globs *)pG)->numlines; + ++((Uz_Globs *)pG)->lines; + if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height) + { + if ((error = WriteTxtErr(q, p-q+1, outfp)) != 0) + return error; + fflush(outfp); + ((Uz_Globs *)pG)->sol = TRUE; + q = p + 1; + (*((Uz_Globs *)pG)->mpause)((zvoid *)pG, + LoadFarString(MorePrompt), 1); + } + } + INCSTR(p); + } /* end while */ + size = (ulg)(p - q); /* remaining text */ + } +#endif /* MORE */ + + if (size) { +#ifdef OS2DLL + if (!((Uz_Globs *)pG)->redirect_text) { +#endif + if ((error = WriteTxtErr(q, size, outfp)) != 0) + return error; +#ifndef VMS /* 2005-09-16 SMS. See note at "WriteTxtErr()", above. */ + fflush(outfp); +#endif + if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag && + !isatty(1) && isatty(2)) + { + /* error output from testing redirected: also send to stderr */ + if ((error = WriteTxtErr(q, size, stderr)) != 0) + return error; + fflush(stderr); + } +#ifdef OS2DLL + } else { /* GRR: this is ugly: hide with macro */ + if ((error = REDIRECTPRINT(q, size)) != 0) + return error; + } +#endif /* OS2DLL */ + ((Uz_Globs *)pG)->sol = (endbuf[-1] == '\n'); + } + return 0; + +} /* end function UzpMessagePrnt() */ + + + + + +#ifdef DLL + +/*****************************/ +/* Function UzpMessageNull() */ /* convenience routine for no output at all */ +/*****************************/ + +int UZ_EXP UzpMessageNull(pG, buf, size, flag) + zvoid *pG; /* globals struct: always passed */ + uch *buf; /* preformatted string to be printed */ + ulg size; /* length of string (may include nulls) */ + int flag; /* flag bits */ +{ + return 0; + +} /* end function UzpMessageNull() */ + +#endif /* DLL */ + + + + + +/***********************/ +/* Function UzpInput() */ /* GRR: this is a placeholder for now */ +/***********************/ + +int UZ_EXP UzpInput(pG, buf, size, flag) + zvoid *pG; /* globals struct: always passed */ + uch *buf; /* preformatted string to be printed */ + int *size; /* (address of) size of buf and of returned string */ + int flag; /* flag bits (bit 0: no echo) */ +{ + /* tell picky compilers to shut up about "unused variable" warnings */ + pG = pG; buf = buf; flag = flag; + + *size = 0; + return 0; + +} /* end function UzpInput() */ + + + + + +#if (!defined(WINDLL) && !defined(MACOS)) + +/***************************/ +/* Function UzpMorePause() */ +/***************************/ + +void UZ_EXP UzpMorePause(pG, prompt, flag) + zvoid *pG; /* globals struct: always passed */ + ZCONST char *prompt; /* "--More--" prompt */ + int flag; /* 0 = any char OK; 1 = accept only '\n', ' ', q */ +{ + uch c; + +/*--------------------------------------------------------------------------- + Print a prompt and wait for the user to press a key, then erase prompt + if possible. + ---------------------------------------------------------------------------*/ + + if (!((Uz_Globs *)pG)->sol) + fprintf(stderr, "\n"); + /* numlines may or may not be used: */ + fprintf(stderr, prompt, ((Uz_Globs *)pG)->numlines); + fflush(stderr); + if (flag & 1) { + do { + c = (uch)FGETCH(0); + } while ( +#ifdef THEOS + c != 17 && /* standard QUIT key */ +#endif + c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q'); + } else + c = (uch)FGETCH(0); + + /* newline was not echoed, so cover up prompt line */ + fprintf(stderr, LoadFarString(HidePrompt)); + fflush(stderr); + + if ( +#ifdef THEOS + (c == 17) || /* standard QUIT key */ +#endif + (ToLower(c) == 'q')) { + DESTROYGLOBALS(); + EXIT(PK_COOL); + } + + ((Uz_Globs *)pG)->sol = TRUE; + +#ifdef MORE + /* space for another screen, enter for another line. */ + if ((flag & 1) && c == ' ') + ((Uz_Globs *)pG)->lines = 0; +#endif /* MORE */ + +} /* end function UzpMorePause() */ + +#endif /* !WINDLL && !MACOS */ + + + + +#ifndef WINDLL + +/**************************/ +/* Function UzpPassword() */ +/**************************/ + +int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn) + zvoid *pG; /* pointer to UnZip's internal global vars */ + int *rcnt; /* retry counter */ + char *pwbuf; /* buffer for password */ + int size; /* size of password buffer */ + ZCONST char *zfn; /* name of zip archive */ + ZCONST char *efn; /* name of archive entry being processed */ +{ +#if CRYPT + int r = IZ_PW_ENTERED; + char *m; + char *prompt; + +#ifndef REENTRANT + /* tell picky compilers to shut up about "unused variable" warnings */ + pG = pG; +#endif + + if (*rcnt == 0) { /* First call for current entry */ + *rcnt = 2; + if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) { + sprintf(prompt, LoadFarString(PasswPrompt), + FnFilter1(zfn), FnFilter2(efn)); + m = prompt; + } else + m = (char *)LoadFarString(PasswPrompt2); + } else { /* Retry call, previous password was wrong */ + (*rcnt)--; + prompt = NULL; + m = (char *)LoadFarString(PasswRetry); + } + + m = getp(__G__ m, pwbuf, size); + if (prompt != (char *)NULL) { + free(prompt); + } + if (m == (char *)NULL) { + r = IZ_PW_ERROR; + } + else if (*pwbuf == '\0') { + r = IZ_PW_CANCELALL; + } + return r; + +#else /* !CRYPT */ + /* tell picky compilers to shut up about "unused variable" warnings */ + pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn; + + return IZ_PW_ERROR; /* internal error; function should never get called */ +#endif /* ?CRYPT */ + +} /* end function UzpPassword() */ + + + + + +/**********************/ +/* Function handler() */ +/**********************/ + +void handler(signal) /* upon interrupt, turn on echo and exit cleanly */ + int signal; +{ + GETGLOBALS(); + +#if !(defined(SIGBUS) || defined(SIGSEGV)) /* add a newline if not at */ + (*G.message)((zvoid *)&G, slide, 0L, 0x41); /* start of line (to stderr; */ +#endif /* slide[] should be safe) */ + + echon(); + +#ifdef SIGBUS + if (signal == SIGBUS) { + Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), + "bus error")); + DESTROYGLOBALS(); + EXIT(PK_BADERR); + } +#endif /* SIGBUS */ + +#ifdef SIGILL + if (signal == SIGILL) { + Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), + "illegal instruction")); + DESTROYGLOBALS(); + EXIT(PK_BADERR); + } +#endif /* SIGILL */ + +#ifdef SIGSEGV + if (signal == SIGSEGV) { + Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), + "segmentation violation")); + DESTROYGLOBALS(); + EXIT(PK_BADERR); + } +#endif /* SIGSEGV */ + + /* probably ctrl-C */ + DESTROYGLOBALS(); +#if defined(AMIGA) && defined(__SASC) + _abort(); +#endif + EXIT(IZ_CTRLC); /* was EXIT(0), then EXIT(PK_ERR) */ +} + +#endif /* !WINDLL */ + + + + +#if (!defined(VMS) && !defined(CMS_MVS)) +#if (!defined(OS2) || defined(TIMESTAMP)) + +#if (!defined(HAVE_MKTIME) || defined(WIN32)) +/* also used in amiga/filedate.c and win32/win32.c */ +ZCONST ush ydays[] = + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; +#endif + +/*******************************/ +/* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */ +/*******************************/ + +time_t dos_to_unix_time(dosdatetime) + ulg dosdatetime; +{ + time_t m_time; + +#ifdef HAVE_MKTIME + + ZCONST time_t now = time(NULL); + struct tm *tm; +# define YRBASE 1900 + + tm = localtime(&now); + tm->tm_isdst = -1; /* let mktime determine if DST is in effect */ + + /* dissect date */ + tm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE); + tm->tm_mon = ((int)(dosdatetime >> 21) & 0x0f) - 1; + tm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f); + + /* dissect time */ + tm->tm_hour = (int)((unsigned)dosdatetime >> 11) & 0x1f; + tm->tm_min = (int)((unsigned)dosdatetime >> 5) & 0x3f; + tm->tm_sec = (int)((unsigned)dosdatetime << 1) & 0x3e; + + m_time = mktime(tm); + NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */ + TTrace((stderr, " final m_time = %lu\n", (ulg)m_time)); + +#else /* !HAVE_MKTIME */ + + int yr, mo, dy, hh, mm, ss; +#ifdef TOPS20 +# define YRBASE 1900 + struct tmx *tmx; + char temp[20]; +#else /* !TOPS20 */ +# define YRBASE 1970 + int leap; + unsigned days; + struct tm *tm; +#if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM)) +#ifdef WIN32 + TIME_ZONE_INFORMATION tzinfo; + DWORD res; +#else /* ! WIN32 */ +#ifndef BSD4_4 /* GRR: change to !defined(MODERN) ? */ +#if (defined(BSD) || defined(MTS) || defined(__GO32__)) + struct timeb tbp; +#else /* !(BSD || MTS || __GO32__) */ +#ifdef DECLARE_TIMEZONE + extern time_t timezone; +#endif +#endif /* ?(BSD || MTS || __GO32__) */ +#endif /* !BSD4_4 */ +#endif /* ?WIN32 */ +#endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */ +#endif /* ?TOPS20 */ + + + /* dissect date */ + yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE); + mo = ((int)(dosdatetime >> 21) & 0x0f) - 1; + dy = ((int)(dosdatetime >> 16) & 0x1f) - 1; + + /* dissect time */ + hh = (int)((unsigned)dosdatetime >> 11) & 0x1f; + mm = (int)((unsigned)dosdatetime >> 5) & 0x3f; + ss = (int)((unsigned)dosdatetime & 0x1f) * 2; + +#ifdef TOPS20 + tmx = (struct tmx *)malloc(sizeof(struct tmx)); + sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss); + time_parse(temp, tmx, (char *)0); + m_time = time_make(tmx); + free(tmx); + +#else /* !TOPS20 */ + +/*--------------------------------------------------------------------------- + Calculate the number of seconds since the epoch, usually 1 January 1970. + ---------------------------------------------------------------------------*/ + + /* leap = # of leap yrs from YRBASE up to but not including current year */ + leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */ + + /* calculate days from BASE to this year and add expired days this year */ + days = (yr * 365) + (leap - 492) + ydays[mo]; + + /* if year is a leap year and month is after February, add another day */ + if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100)) + ++days; /* OK through 2199 */ + + /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */ + m_time = (time_t)((unsigned long)(days + dy) * 86400L + + (unsigned long)hh * 3600L + + (unsigned long)(mm * 60 + ss)); + /* - 1; MS-DOS times always rounded up to nearest even second */ + TTrace((stderr, "dos_to_unix_time:\n")); + TTrace((stderr, " m_time before timezone = %lu\n", (ulg)m_time)); + +/*--------------------------------------------------------------------------- + Adjust for local standard timezone offset. + ---------------------------------------------------------------------------*/ + +#if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM)) +#ifdef WIN32 + /* account for timezone differences */ + res = GetTimeZoneInformation(&tzinfo); + if (res != TIME_ZONE_ID_INVALID) + { + m_time += 60*(tzinfo.Bias); +#else /* !WIN32 */ +#if (defined(BSD) || defined(MTS) || defined(__GO32__)) +#ifdef BSD4_4 + if ( (dosdatetime >= DOSTIME_2038_01_18) && + (m_time < (time_t)0x70000000L) ) + m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ + if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ + m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ + if ((tm = localtime(&m_time)) != (struct tm *)NULL) + m_time -= tm->tm_gmtoff; /* sec. EAST of GMT: subtr. */ +#else /* !(BSD4_4 */ + ftime(&tbp); /* get `timezone' */ + m_time += tbp.timezone * 60L; /* seconds WEST of GMT: add */ +#endif /* ?(BSD4_4 || __EMX__) */ +#else /* !(BSD || MTS || __GO32__) */ + /* tzset was already called at start of process_zipfiles() */ + /* tzset(); */ /* set `timezone' variable */ +#ifndef __BEOS__ /* BeOS DR8 has no timezones... */ + m_time += timezone; /* seconds WEST of GMT: add */ +#endif +#endif /* ?(BSD || MTS || __GO32__) */ +#endif /* ?WIN32 */ + TTrace((stderr, " m_time after timezone = %lu\n", (ulg)m_time)); + +/*--------------------------------------------------------------------------- + Adjust for local daylight savings (summer) time. + ---------------------------------------------------------------------------*/ + +#ifndef BSD4_4 /* (DST already added to tm_gmtoff, so skip tm_isdst) */ + if ( (dosdatetime >= DOSTIME_2038_01_18) && + (m_time < (time_t)0x70000000L) ) + m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ + if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ + m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ + TIMET_TO_NATIVE(m_time) /* NOP unless MSC 7.0 or Macintosh */ + if (((tm = localtime((time_t *)&m_time)) != NULL) && tm->tm_isdst) +#ifdef WIN32 + m_time += 60L * tzinfo.DaylightBias; /* adjust with DST bias */ + else + m_time += 60L * tzinfo.StandardBias; /* add StdBias (normally 0) */ +#else + m_time -= 60L * 60L; /* adjust for daylight savings time */ +#endif + NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */ + TTrace((stderr, " m_time after DST = %lu\n", (ulg)m_time)); +#endif /* !BSD4_4 */ +#ifdef WIN32 + } +#endif +#endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */ +#endif /* ?TOPS20 */ + +#endif /* ?HAVE_MKTIME */ + + if ( (dosdatetime >= DOSTIME_2038_01_18) && + (m_time < (time_t)0x70000000L) ) + m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ + if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ + m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ + + return m_time; + +} /* end function dos_to_unix_time() */ + +#endif /* !OS2 || TIMESTAMP */ +#endif /* !VMS && !CMS_MVS */ + + + +#if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS)) + +/******************************/ +/* Function check_for_newer() */ /* used for overwriting/freshening/updating */ +/******************************/ + +int check_for_newer(__G__ filename) /* return 1 if existing file is newer */ + __GDEF /* or equal; 0 if older; -1 if doesn't */ + char *filename; /* exist yet */ +{ + time_t existing, archive; +#ifdef USE_EF_UT_TIME + iztimes z_utime; +#endif +#ifdef AOS_VS + long dyy, dmm, ddd, dhh, dmin, dss; + + + dyy = (lrec.last_mod_dos_datetime >> 25) + 1980; + dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f; + ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f; + dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f; + dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f; + dss = (lrec.last_mod_dos_datetime & 0x1f) * 2; + + /* under AOS/VS, file times can only be set at creation time, + * with the info in a special DG format. Make sure we can create + * it here - we delete it later & re-create it, whether or not + * it exists now. + */ + if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) | + (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1)) + return DOES_NOT_EXIST; +#endif /* AOS_VS */ + + Trace((stderr, "check_for_newer: doing stat(%s)\n", FnFilter1(filename))); + if (SSTAT(filename, &G.statbuf)) { + Trace((stderr, + "check_for_newer: stat(%s) returns %d: file does not exist\n", + FnFilter1(filename), SSTAT(filename, &G.statbuf))); +#ifdef SYMLINKS + Trace((stderr, "check_for_newer: doing lstat(%s)\n", + FnFilter1(filename))); + /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */ + if (lstat(filename, &G.statbuf) == 0) { + Trace((stderr, + "check_for_newer: lstat(%s) returns 0: symlink does exist\n", + FnFilter1(filename))); + if (QCOND2 && !IS_OVERWRT_ALL) + Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink), + FnFilter1(filename), " with no real file")); + return EXISTS_AND_OLDER; /* symlink dates are meaningless */ + } +#endif /* SYMLINKS */ + return DOES_NOT_EXIST; + } + Trace((stderr, "check_for_newer: stat(%s) returns 0: file exists\n", + FnFilter1(filename))); + +#ifdef SYMLINKS + /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */ + if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) { + Trace((stderr, "check_for_newer: %s is a symbolic link\n", + FnFilter1(filename))); + if (QCOND2 && !IS_OVERWRT_ALL) + Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink), + FnFilter1(filename), "")); + return EXISTS_AND_OLDER; /* symlink dates are meaningless */ + } +#endif /* SYMLINKS */ + + NATIVE_TO_TIMET(G.statbuf.st_mtime) /* NOP unless MSC 7.0 or Macintosh */ + +#ifdef USE_EF_UT_TIME + /* The `Unix extra field mtime' should be used for comparison with the + * time stamp of the existing file >>>ONLY<<< when the EF info is also + * used to set the modification time of the extracted file. + */ + if (G.extra_field && +#ifdef IZ_CHECK_TZ + G.tz_is_valid && +#endif + (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, + G.lrec.last_mod_dos_datetime, &z_utime, NULL) + & EB_UT_FL_MTIME)) + { + TTrace((stderr, "check_for_newer: using Unix extra field mtime\n")); + existing = G.statbuf.st_mtime; + archive = z_utime.mtime; + } else { + /* round up existing filetime to nearest 2 seconds for comparison, + * but saturate in case of arithmetic overflow + */ + existing = ((G.statbuf.st_mtime & 1) && + (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ? + G.statbuf.st_mtime + 1 : G.statbuf.st_mtime; + archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime); + } +#else /* !USE_EF_UT_TIME */ + /* round up existing filetime to nearest 2 seconds for comparison, + * but saturate in case of arithmetic overflow + */ + existing = ((G.statbuf.st_mtime & 1) && + (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ? + G.statbuf.st_mtime + 1 : G.statbuf.st_mtime; + archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime); +#endif /* ?USE_EF_UT_TIME */ + + TTrace((stderr, "check_for_newer: existing %lu, archive %lu, e-a %ld\n", + (ulg)existing, (ulg)archive, (long)(existing-archive))); + + return (existing >= archive); + +} /* end function check_for_newer() */ + +#endif /* !VMS && !OS2 && !CMS_MVS */ + + + + + +/************************/ +/* Function do_string() */ +/************************/ + +int do_string(__G__ length, option) /* return PK-type error code */ + __GDEF + unsigned int length; /* without prototype, ush converted to this */ + int option; +{ + unsigned comment_bytes_left; + unsigned int block_len; + int error=PK_OK; +#ifdef AMIGA + char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */ +#endif + + +/*--------------------------------------------------------------------------- + This function processes arbitrary-length (well, usually) strings. Four + major options are allowed: SKIP, wherein the string is skipped (pretty + logical, eh?); DISPLAY, wherein the string is printed to standard output + after undergoing any necessary or unnecessary character conversions; + DS_FN, wherein the string is put into the filename[] array after under- + going appropriate conversions (including case-conversion, if that is + indicated: see the global variable pInfo->lcflag); and EXTRA_FIELD, + wherein the `string' is assumed to be an extra field and is copied to + the (freshly malloced) buffer G.extra_field. The third option should + be OK since filename is dimensioned at 1025, but we check anyway. + + The string, by the way, is assumed to start at the current file-pointer + position; its length is given by 'length'. So start off by checking the + length of the string: if zero, we're already done. + ---------------------------------------------------------------------------*/ + + if (!length) + return PK_COOL; + + switch (option) { + +#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) + /* + * Special case: See if the comment begins with an autorun command line. + * Save that and display (or skip) the remainder. + */ + + case CHECK_AUTORUN: + case CHECK_AUTORUN_Q: + comment_bytes_left = length; + if (length >= 10) + { + block_len = readbuf(__G__ (char *)G.outbuf, 10); + if (block_len == 0) + return PK_EOF; + comment_bytes_left -= block_len; + G.outbuf[block_len] = '\0'; + if (!strcmp((char *)G.outbuf, "$AUTORUN$>")) { + char *eol; + length -= 10; + block_len = readbuf(__G__ G.autorun_command, + MIN(length, sizeof(G.autorun_command)-1)); + if (block_len == 0) + return PK_EOF; + comment_bytes_left -= block_len; + G.autorun_command[block_len] = '\0'; + A_TO_N(G.autorun_command); + eol = strchr(G.autorun_command, '\n'); + if (!eol) + eol = G.autorun_command + strlen(G.autorun_command) - 1; + length -= eol + 1 - G.autorun_command; + while (eol >= G.autorun_command && isspace(*eol)) + *eol-- = '\0'; +#if (defined(WIN32) && !defined(_WIN32_WCE)) + /* Win9x console always uses OEM character coding, and + WinNT console is set to OEM charset by default, too */ + INTERN_TO_OEM(G.autorun_command, G.autorun_command); +#endif /* (WIN32 && !_WIN32_WCE) */ + } + } + if (option == CHECK_AUTORUN_Q) /* don't display the remainder */ + length = 0; + /* seek to beginning of remaining part of comment -- rewind if */ + /* displaying entire comment, or skip to end if discarding it */ + seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + + (G.inptr - G.inbuf) + comment_bytes_left - length); + if (!length) + break; + /* FALL THROUGH... */ +#endif /* SFX && CHEAP_SFX_AUTORUN */ + + /* + * First normal case: print string on standard output. First set loop + * variables, then loop through the comment in chunks of OUTBUFSIZ bytes, + * converting formats and printing as we go. The second half of the + * loop conditional was added because the file might be truncated, in + * which case comment_bytes_left will remain at some non-zero value for + * all time. outbuf and slide are used as scratch buffers because they + * are available (we should be either before or in between any file pro- + * cessing). + */ + + case DISPLAY: + case DISPL_8: + comment_bytes_left = length; + block_len = OUTBUFSIZ; /* for the while statement, first time */ + while (comment_bytes_left > 0 && block_len > 0) { + register uch *p = G.outbuf; + register uch *q = G.outbuf; + + if ((block_len = readbuf(__G__ (char *)G.outbuf, + MIN((unsigned)OUTBUFSIZ, comment_bytes_left))) == 0) + return PK_EOF; + comment_bytes_left -= block_len; + + /* this is why we allocated an extra byte for outbuf: terminate + * with zero (ASCIIZ) */ + G.outbuf[block_len] = '\0'; + + /* remove all ASCII carriage returns from comment before printing + * (since used before A_TO_N(), check for CR instead of '\r') + */ + while (*p) { + while (*p == CR) + ++p; + *q++ = *p++; + } + /* could check whether (p - outbuf) == block_len here */ + *q = '\0'; + + if (option == DISPL_8) { + /* translate the text coded in the entry's host-dependent + "extended ASCII" charset into the compiler's (system's) + internal text code page */ + Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum, + G.pInfo->hostver, G.pInfo->HasUxAtt, + FALSE); +#ifdef WINDLL + /* translate to ANSI (RTL internal codepage may be OEM) */ + INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf); +#else /* !WINDLL */ +#if (defined(WIN32) && !defined(_WIN32_WCE)) + /* Win9x console always uses OEM character coding, and + WinNT console is set to OEM charset by default, too */ + INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf); +#endif /* (WIN32 && !_WIN32_WCE) */ +#endif /* ?WINDLL */ + } else { + A_TO_N(G.outbuf); /* translate string to native */ + } + +#ifdef WINDLL + /* ran out of local mem -- had to cheat */ + win_fprintf((zvoid *)&G, stdout, (extent)(q-G.outbuf), + (char *)G.outbuf); + win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n"); +#else /* !WINDLL */ +#ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */ + (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0); +#else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */ + p = G.outbuf - 1; + q = slide; + while (*++p) { + int pause = FALSE; + + if (*p == 0x1B) { /* ASCII escape char */ + *q++ = '^'; + *q++ = '['; + } else if (*p == 0x13) { /* ASCII ^S (pause) */ + pause = TRUE; + if (p[1] == LF) /* ASCII LF */ + *q++ = *++p; + else if (p[1] == CR && p[2] == LF) { /* ASCII CR LF */ + *q++ = *++p; + *q++ = *++p; + } + } else + *q++ = *p; + if ((unsigned)(q-slide) > WSIZE-3 || pause) { /* flush */ + (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0); + q = slide; + if (pause && G.extract_flag) /* don't pause for list/test */ + (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0); + } + } + (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0); +#endif /* ?NOANSIFILT */ +#endif /* ?WINDLL */ + } + /* add '\n' if not at start of line */ + (*G.message)((zvoid *)&G, slide, 0L, 0x40); + break; + + /* + * Second case: read string into filename[] array. The filename should + * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check, + * just to be sure. + */ + + case DS_FN: + case DS_FN_L: +#ifdef UNICODE_SUPPORT + /* get the whole filename as need it for Unicode checksum */ + if (G.fnfull_bufsize <= length) { + extent fnbufsiz = FILNAMSIZ; + + if (fnbufsiz <= length) + fnbufsiz = length + 1; + if (G.filename_full) + free(G.filename_full); + G.filename_full = malloc(fnbufsiz); + if (G.filename_full == NULL) + return PK_MEM; + G.fnfull_bufsize = fnbufsiz; + } + if (readbuf(__G__ G.filename_full, length) == 0) + return PK_EOF; + G.filename_full[length] = '\0'; /* terminate w/zero: ASCIIZ */ + + /* if needed, chop off end so standard filename is a valid length */ + if (length >= FILNAMSIZ) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(FilenameTooLongTrunc))); + error = PK_WARN; + length = FILNAMSIZ - 1; + } + /* no excess size */ + block_len = 0; + strncpy(G.filename, G.filename_full, length); + G.filename[length] = '\0'; /* terminate w/zero: ASCIIZ */ +#else /* !UNICODE_SUPPORT */ + if (length >= FILNAMSIZ) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(FilenameTooLongTrunc))); + error = PK_WARN; + /* remember excess length in block_len */ + block_len = length - (FILNAMSIZ - 1); + length = FILNAMSIZ - 1; + } else + /* no excess size */ + block_len = 0; + if (readbuf(__G__ G.filename, length) == 0) + return PK_EOF; + G.filename[length] = '\0'; /* terminate w/zero: ASCIIZ */ +#endif /* ?UNICODE_SUPPORT */ + + /* translate the Zip entry filename coded in host-dependent "extended + ASCII" into the compiler's (system's) internal text code page */ + Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum, G.pInfo->hostver, + G.pInfo->HasUxAtt, (option == DS_FN_L)); + + if (G.pInfo->lcflag) /* replace with lowercase filename */ + STRLOWER(G.filename, G.filename); + + if (G.pInfo->vollabel && length > 8 && G.filename[8] == '.') { + char *p = G.filename+8; + while (*p++) + p[-1] = *p; /* disk label, and 8th char is dot: remove dot */ + } + + if (!block_len) /* no overflow, we're done here */ + break; + + /* + * We truncated the filename, so print what's left and then fall + * through to the SKIP routine. + */ + Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename))); + length = block_len; /* SKIP the excess bytes... */ + /* FALL THROUGH... */ + + /* + * Third case: skip string, adjusting readbuf's internal variables + * as necessary (and possibly skipping to and reading a new block of + * data). + */ + + case SKIP: + /* cur_zipfile_bufstart already takes account of extra_bytes, so don't + * correct for it twice: */ + seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + + (G.inptr-G.inbuf) + length); + break; + + /* + * Fourth case: assume we're at the start of an "extra field"; malloc + * storage for it and read data into the allocated space. + */ + + case EXTRA_FIELD: + if (G.extra_field != (uch *)NULL) + free(G.extra_field); + if ((G.extra_field = (uch *)malloc(length)) == (uch *)NULL) { + Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong), + length)); + /* cur_zipfile_bufstart already takes account of extra_bytes, + * so don't correct for it twice: */ + seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + + (G.inptr-G.inbuf) + length); + } else { + if (readbuf(__G__ (char *)G.extra_field, length) == 0) + return PK_EOF; + /* Looks like here is where extra fields are read */ + getZip64Data(__G__ G.extra_field, length); +#ifdef UNICODE_SUPPORT + G.unipath_filename = NULL; + if (G.UzO.U_flag < 2) { + /* check if GPB11 (General Purpuse Bit 11) is set indicating + the standard path and comment are UTF-8 */ + if (G.pInfo->GPFIsUTF8) { + /* if GPB11 set then filename_full is untruncated UTF-8 */ + G.unipath_filename = G.filename_full; + } else { + /* Get the Unicode fields if exist */ + getUnicodeData(__G__ G.extra_field, length); + if (G.unipath_filename && strlen(G.unipath_filename) == 0) { + /* the standard filename field is UTF-8 */ + free(G.unipath_filename); + G.unipath_filename = G.filename_full; + } + } + if (G.unipath_filename) { +# ifdef UTF8_MAYBE_NATIVE + if (G.native_is_utf8 +# ifdef UNICODE_WCHAR + && (!G.unicode_escape_all) +# endif + ) { + strncpy(G.filename, G.unipath_filename, FILNAMSIZ - 1); + /* make sure filename is short enough */ + if (strlen(G.unipath_filename) >= FILNAMSIZ) { + G.filename[FILNAMSIZ - 1] = '\0'; + Info(slide, 0x401, ((char *)slide, + LoadFarString(UFilenameTooLongTrunc))); + error = PK_WARN; + } + } +# ifdef UNICODE_WCHAR + else +# endif +# endif /* UTF8_MAYBE_NATIVE */ +# ifdef UNICODE_WCHAR + { + char *fn; + + /* convert UTF-8 to local character set */ + fn = utf8_to_local_string(G.unipath_filename, + G.unicode_escape_all); + /* make sure filename is short enough */ + if (strlen(fn) >= FILNAMSIZ) { + fn[FILNAMSIZ - 1] = '\0'; + Info(slide, 0x401, ((char *)slide, + LoadFarString(UFilenameTooLongTrunc))); + error = PK_WARN; + } + /* replace filename with converted UTF-8 */ + strcpy(G.filename, fn); + free(fn); + } +# endif /* UNICODE_WCHAR */ + if (G.unipath_filename != G.filename_full) + free(G.unipath_filename); + G.unipath_filename = NULL; + } + } +#endif /* UNICODE_SUPPORT */ + } + break; + +#ifdef AMIGA + /* + * Fifth case, for the Amiga only: take the comment that would ordinarily + * be skipped over, and turn it into a 79 character string that will be + * attached to the file as a "filenote" after it is extracted. + */ + + case FILENOTE: + if ((block_len = readbuf(__G__ tmp_fnote, (unsigned) + MIN(length, 2 * AMIGA_FILENOTELEN - 1))) == 0) + return PK_EOF; + if ((length -= block_len) > 0) /* treat remainder as in case SKIP: */ + seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + + (G.inptr - G.inbuf) + length); + /* convert multi-line text into single line with no ctl-chars: */ + tmp_fnote[block_len] = '\0'; + while ((short int) --block_len >= 0) + if ((unsigned) tmp_fnote[block_len] < ' ') + if (tmp_fnote[block_len+1] == ' ') /* no excess */ + strcpy(tmp_fnote+block_len, tmp_fnote+block_len+1); + else + tmp_fnote[block_len] = ' '; + tmp_fnote[AMIGA_FILENOTELEN - 1] = '\0'; + if (G.filenotes[G.filenote_slot]) + free(G.filenotes[G.filenote_slot]); /* should not happen */ + G.filenotes[G.filenote_slot] = NULL; + if (tmp_fnote[0]) { + if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1))) + return PK_MEM; + strcpy(G.filenotes[G.filenote_slot], tmp_fnote); + } + break; +#endif /* AMIGA */ + + } /* end switch (option) */ + + return error; + +} /* end function do_string() */ + + + + + +/***********************/ +/* Function makeword() */ +/***********************/ + +ush makeword(b) + ZCONST uch *b; +{ + /* + * Convert Intel style 'short' integer to non-Intel non-16-bit + * host format. This routine also takes care of byte-ordering. + */ + return (ush)((b[1] << 8) | b[0]); +} + + + + + +/***********************/ +/* Function makelong() */ +/***********************/ + +ulg makelong(sig) + ZCONST uch *sig; +{ + /* + * Convert intel style 'long' variable to non-Intel non-16-bit + * host format. This routine also takes care of byte-ordering. + */ + return (((ulg)sig[3]) << 24) + + (((ulg)sig[2]) << 16) + + (ulg)((((unsigned)sig[1]) << 8) + + ((unsigned)sig[0])); +} + + + + + +/************************/ +/* Function makeint64() */ +/************************/ + +zusz_t makeint64(sig) + ZCONST uch *sig; +{ +#ifdef LARGE_FILE_SUPPORT + /* + * Convert intel style 'int64' variable to non-Intel non-16-bit + * host format. This routine also takes care of byte-ordering. + */ + return (((zusz_t)sig[7]) << 56) + + (((zusz_t)sig[6]) << 48) + + (((zusz_t)sig[4]) << 32) + + (zusz_t)((((ulg)sig[3]) << 24) + + (((ulg)sig[2]) << 16) + + (((unsigned)sig[1]) << 8) + + (sig[0])); + +#else /* !LARGE_FILE_SUPPORT */ + + if ((sig[7] | sig[6] | sig[5] | sig[4]) != 0) + return (zusz_t)0xffffffffL; + else + return (zusz_t)((((ulg)sig[3]) << 24) + + (((ulg)sig[2]) << 16) + + (((unsigned)sig[1]) << 8) + + (sig[0])); + +#endif /* ?LARGE_FILE_SUPPORT */ +} + + + + + +/*********************/ +/* Function fzofft() */ +/*********************/ + +/* Format a zoff_t value in a cylindrical buffer set. */ +char *fzofft(__G__ val, pre, post) + __GDEF + zoff_t val; + ZCONST char *pre; + ZCONST char *post; +{ + /* Storage cylinder. (now in globals.h) */ + /*static char fzofft_buf[FZOFFT_NUM][FZOFFT_LEN];*/ + /*static int fzofft_index = 0;*/ + + /* Temporary format string storage. */ + char fmt[16]; + + /* Assemble the format string. */ + fmt[0] = '%'; + fmt[1] = '\0'; /* Start after initial "%". */ + if (pre == FZOFFT_HEX_WID) /* Special hex width. */ + { + strcat(fmt, FZOFFT_HEX_WID_VALUE); + } + else if (pre == FZOFFT_HEX_DOT_WID) /* Special hex ".width". */ + { + strcat(fmt, "."); + strcat(fmt, FZOFFT_HEX_WID_VALUE); + } + else if (pre != NULL) /* Caller's prefix (width). */ + { + strcat(fmt, pre); + } + + strcat(fmt, FZOFFT_FMT); /* Long or long-long or whatever. */ + + if (post == NULL) + strcat(fmt, "d"); /* Default radix = decimal. */ + else + strcat(fmt, post); /* Caller's radix. */ + + /* Advance the cylinder. */ + G.fzofft_index = (G.fzofft_index + 1) % FZOFFT_NUM; + + /* Write into the current chamber. */ + sprintf(G.fzofft_buf[G.fzofft_index], fmt, val); + + /* Return a pointer to this chamber. */ + return G.fzofft_buf[G.fzofft_index]; +} + + + + +#if CRYPT + +#ifdef NEED_STR2ISO +/**********************/ +/* Function str2iso() */ +/**********************/ + +char *str2iso(dst, src) + char *dst; /* destination buffer */ + register ZCONST char *src; /* source string */ +{ +#ifdef INTERN_TO_ISO + INTERN_TO_ISO(src, dst); +#else + register uch c; + register char *dstp = dst; + + do { + c = (uch)foreign(*src++); + *dstp++ = (char)ASCII2ISO(c); + } while (c != '\0'); +#endif + + return dst; +} +#endif /* NEED_STR2ISO */ + + +#ifdef NEED_STR2OEM +/**********************/ +/* Function str2oem() */ +/**********************/ + +char *str2oem(dst, src) + char *dst; /* destination buffer */ + register ZCONST char *src; /* source string */ +{ +#ifdef INTERN_TO_OEM + INTERN_TO_OEM(src, dst); +#else + register uch c; + register char *dstp = dst; + + do { + c = (uch)foreign(*src++); + *dstp++ = (char)ASCII2OEM(c); + } while (c != '\0'); +#endif + + return dst; +} +#endif /* NEED_STR2OEM */ + +#endif /* CRYPT */ + + +#ifdef ZMEM /* memset/memcmp/memcpy for systems without either them or */ + /* bzero/bcmp/bcopy */ + /* (no known systems as of 960211) */ + +/*********************/ +/* Function memset() */ +/*********************/ + +zvoid *memset(buf, init, len) + register zvoid *buf; /* buffer location */ + register int init; /* initializer character */ + register unsigned int len; /* length of the buffer */ +{ + zvoid *start; + + start = buf; + while (len--) + *((char *)buf++) = (char)init; + return start; +} + + + +/*********************/ +/* Function memcmp() */ +/*********************/ + +int memcmp(b1, b2, len) + register ZCONST zvoid *b1; + register ZCONST zvoid *b2; + register unsigned int len; +{ + register int c; + + if (len > 0) do { + if ((c = (int)(*((ZCONST unsigned char *)b1)++) - + (int)(*((ZCONST unsigned char *)b2)++)) != 0) + return c; + } while (--len > 0) + return 0; +} + + + +/*********************/ +/* Function memcpy() */ +/*********************/ + +zvoid *memcpy(dst, src, len) + register zvoid *dst; + register ZCONST zvoid *src; + register unsigned int len; +{ + zvoid *start; + + start = dst; + while (len-- > 0) + *((char *)dst)++ = *((ZCONST char *)src)++; + return start; +} + +#endif /* ZMEM */ + + + + +#ifdef NO_STRNICMP + +/************************/ +/* Function zstrnicmp() */ +/************************/ + +int zstrnicmp(s1, s2, n) + register ZCONST char *s1, *s2; + register unsigned n; +{ + for (; n > 0; --n, ++s1, ++s2) { + + if (ToLower(*s1) != ToLower(*s2)) + /* test includes early termination of one string */ + return ((uch)ToLower(*s1) < (uch)ToLower(*s2))? -1 : 1; + + if (*s1 == '\0') /* both strings terminate early */ + return 0; + } + return 0; +} + +#endif /* NO_STRNICMP */ + + + + +#ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */ +# undef stat + +/********************/ +/* Function zstat() */ +/********************/ + +int zstat(p, s) + ZCONST char *p; + struct stat *s; +{ + return (stat((char *)p,s) >= 0? 0 : (-1)); +} + +#endif /* REGULUS */ + + + + +#ifdef _MBCS + +/* DBCS support for Info-ZIP's zip (mainly for japanese (-: ) + * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp) + * This code is public domain! Date: 1998/12/20 + */ + +/************************/ +/* Function plastchar() */ +/************************/ + +char *plastchar(ptr, len) + ZCONST char *ptr; + extent len; +{ + unsigned clen; + ZCONST char *oldptr = ptr; + while(*ptr != '\0' && len > 0){ + oldptr = ptr; + clen = CLEN(ptr); + ptr += clen; + len -= clen; + } + return (char *)oldptr; +} + + +#ifdef NEED_UZMBCLEN +/***********************/ +/* Function uzmbclen() */ +/***********************/ + +extent uzmbclen(ptr) + ZCONST unsigned char *ptr; +{ + int mbl; + + mbl = mblen((ZCONST char *)ptr, MB_CUR_MAX); + /* For use in code scanning through MBCS strings, we need a strictly + positive "MB char bytes count". For our scanning purpose, it is not + not relevant whether the MB character is valid or not. And, the NUL + char '\0' has a byte count of 1, but mblen() returns 0. So, we make + sure that the uzmbclen() return value is not less than 1. + */ + return (extent)(mbl > 0 ? mbl : 1); +} +#endif /* NEED_UZMBCLEN */ + + +#ifdef NEED_UZMBSCHR +/***********************/ +/* Function uzmbschr() */ +/***********************/ + +unsigned char *uzmbschr(str, c) + ZCONST unsigned char *str; + unsigned int c; +{ + while(*str != '\0'){ + if (*str == c) {return (unsigned char *)str;} + INCSTR(str); + } + return NULL; +} +#endif /* NEED_UZMBSCHR */ + + +#ifdef NEED_UZMBSRCHR +/************************/ +/* Function uzmbsrchr() */ +/************************/ + +unsigned char *uzmbsrchr(str, c) + ZCONST unsigned char *str; + unsigned int c; +{ + unsigned char *match = NULL; + while(*str != '\0'){ + if (*str == c) {match = (unsigned char *)str;} + INCSTR(str); + } + return match; +} +#endif /* NEED_UZMBSRCHR */ +#endif /* _MBCS */ + + + + + +#ifdef SMALL_MEM + +/*******************************/ +/* Function fLoadFarString() */ /* (and friends...) */ +/*******************************/ + +char *fLoadFarString(__GPRO__ const char Far *sz) +{ + (void)zfstrcpy(G.rgchBigBuffer, sz); + return G.rgchBigBuffer; +} + +char *fLoadFarStringSmall(__GPRO__ const char Far *sz) +{ + (void)zfstrcpy(G.rgchSmallBuffer, sz); + return G.rgchSmallBuffer; +} + +char *fLoadFarStringSmall2(__GPRO__ const char Far *sz) +{ + (void)zfstrcpy(G.rgchSmallBuffer2, sz); + return G.rgchSmallBuffer2; +} + + + + +#if (!defined(_MSC_VER) || (_MSC_VER < 600)) +/*************************/ +/* Function zfstrcpy() */ /* portable clone of _fstrcpy() */ +/*************************/ + +char Far * Far zfstrcpy(char Far *s1, const char Far *s2) +{ + char Far *p = s1; + + while ((*s1++ = *s2++) != '\0'); + return p; +} + +#if (!(defined(SFX) || defined(FUNZIP))) +/*************************/ +/* Function zfstrcmp() */ /* portable clone of _fstrcmp() */ +/*************************/ + +int Far zfstrcmp(const char Far *s1, const char Far *s2) +{ + int ret; + + while ((ret = (int)(uch)*s1 - (int)(uch)*s2) == 0 + && *s2 != '\0') { + ++s2; ++s1; + } + return ret; +} +#endif /* !(SFX || FUNZIP) */ +#endif /* !_MSC_VER || (_MSC_VER < 600) */ + +#endif /* SMALL_MEM */ diff --git a/flexos/Contents b/flexos/Contents new file mode 100644 index 0000000..e064731 --- /dev/null +++ b/flexos/Contents @@ -0,0 +1,8 @@ +Contents of the "flexos" subdirectory for UnZip 5.32 and later: + + Contents this file + README notes about limitations and assumptions of the FlexOS port + flexos.c OS-dependent UnZip routines for FlexOS + flxcfg.h OS-dependent configuration, included by unzpriv.h + hc.pro profile for MetaWare High C + makefile makefile for MetaWare High C, PAMAKE diff --git a/flexos/README b/flexos/README new file mode 100644 index 0000000..f1c03ab --- /dev/null +++ b/flexos/README @@ -0,0 +1,39 @@ +This should be considered an initial port - there will probably be some +bugs and non-functioning features. + +The only functionality that has had any real testing is "unzip filename", +anything else is basically untested. + +This has been cross-compiled from DOS using Metaware's High C compiler +and the DOS version of pamake (v3.0). It should compile with the FlexOS +hosted version of HighC, and the makefile could be converted to work +with the native FlexOS make. + +The following considerations apply: + +)Compiled against and linked with portlib. +)Used on FlexOS 286 v2.32 +)Volume labels are not supported - this is due to the way FlexOS decides + if a drive has case-sensitive filenames based upon the contents of the + volume label. +)No special handling for case-sensitive media (see above). +)Not using the PORTLIB wildarg routine (i.e., UnZip does its own globbing). +)Based upon the MSDOS port. +)Filenames are in FAT format. +)The current version of getch is a cheat (simply using getchar()). I + should interrogate stdin and if it's a FlexOS console use special code + to turn off echo and just read one char. +)Only the basic MSDOS FAT file attributes are saved/restored. There is + currently no support for the FlexOS extended file attributes. +)There is some code that should attempt to do the correct thing when a + pathspec with a logical name definition is used (e.g., "system:path/to/it"); + however it again has not been stress-tested. +)There is no special handling for floppy drives, there probably should + be. +)The dateformat is compiled in as DMY (shoot me I'm British), I'm not + sure if there is actually a way to get locale info. +)The assembler speedups haven't yet been ported to ASM86 (should simply + be a change of syntax) + + -- + D.Fawcus 17 July 1997 diff --git a/flexos/flexos.c b/flexos/flexos.c new file mode 100644 index 0000000..a2d1008 --- /dev/null +++ b/flexos/flexos.c @@ -0,0 +1,936 @@ +/* + Copyright (c) 1990-2007 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 +*/ +/*--------------------------------------------------------------------------- + + flexos.c + + FlexOS-specific routines for use with Info-ZIP's UnZip 5.2 and later. + + Based upon the MSDOS version of this file (msdos/msdos.c) + + Contains: do_wild() + mapattr() + mapname() + map2fat() + checkdir() + close_outfile() + dateformat() + version() + _wildarg() + + ---------------------------------------------------------------------------*/ + + + +#define UNZIP_INTERNAL +#include "unzip.h" + +#include + +/* The following should really be a static declaration, but the compiler + complains (crappy compiler can't cope with a static forward declaration). + */ +extern void map2fat OF((char *pathcomp, char *last_dot)); + +static int created_dir; /* used by mapname(), checkdir() */ +static int renamed_fullpath; /* ditto */ + +/*****************************/ +/* Strings used in flexos.c */ +/*****************************/ + +#ifndef SFX + static ZCONST char Far CantAllocateWildcard[] = + "warning: cannot allocate wildcard buffers\n"; +#endif +static ZCONST char Far WarnDirTraversSkip[] = + "warning: skipped \"../\" path component(s) in %s\n"; +static ZCONST char Far Creating[] = " creating: %s\n"; +static ZCONST char Far ConversionFailed[] = + "mapname: conversion of %s failed\n"; +static ZCONST char Far PathTooLong[] = "checkdir error: path too long: %s\n"; +static ZCONST char Far CantCreateDir[] = "checkdir error: cannot create %s\n\ + unable to process %s.\n"; +static ZCONST char Far DirIsntDirectory[] = + "checkdir error: %s exists but is not directory\n\ + unable to process %s.\n"; +static ZCONST char Far PathTooLongTrunc[] = + "checkdir warning: path too long; truncating\n %s\n\ + -> %s\n"; +#if (!defined(SFX) || defined(SFX_EXDIR)) + static ZCONST char Far CantCreateExtractDir[] = + "checkdir: cannot create extraction directory: %s\n"; +#endif + +#include + +#ifndef SFX + +/************************/ +/* Function do_wild() */ /* identical to OS/2 version */ +/************************/ + +char *do_wild(__G__ wildspec) + __GDEF + ZCONST char *wildspec; /* only used first time on a given dir */ +{ + static DIR *wild_dir = (DIR *)NULL; + static ZCONST char *wildname; + static char *dirname, matchname[FILNAMSIZ]; + static int notfirstcall=FALSE, have_dirname, dirnamelen; + char *fnamestart; + struct dirent *file; + + /* Even when we're just returning wildspec, we *always* do so in + * matchname[]--calling routine is allowed to append four characters + * to the returned string, and wildspec may be a pointer to argv[]. + */ + if (!notfirstcall) { /* first call: must initialize everything */ + notfirstcall = TRUE; + + if (!iswild(wildspec)) { + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + have_dirname = FALSE; + dir = NULL; + return matchname; + } + + /* break the wildspec into a directory part and a wildcard filename */ + if ((wildname = strrchr(wildspec, '/')) == (ZCONST char *)NULL && + (wildname = strrchr(wildspec, ':')) == (ZCONST char *)NULL) { + dirname = "."; + dirnamelen = 1; + have_dirname = FALSE; + wildname = wildspec; + } else { + ++wildname; /* point at character after '/' or ':' */ + dirnamelen = (int)(wildname - wildspec); + if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) { + Info(slide, 1, ((char *)slide, + LoadFarString(CantAllocateWildcard))); + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; /* but maybe filespec was not a wildcard */ + } +/* GRR: cannot strip trailing char for opendir since might be "d:/" or "d:" + * (would have to check for "./" at end--let opendir handle it instead) */ + strncpy(dirname, wildspec, dirnamelen); + dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ + have_dirname = TRUE; + } + Trace((stderr, "do_wild: dirname = [%s]\n", FnFilter1(dirname))); + + if ((wild_dir = opendir(dirname)) != (DIR *)NULL) { + if (have_dirname) { + strcpy(matchname, dirname); + fnamestart = matchname + dirnamelen; + } else + fnamestart = matchname; + while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + strcpy(fnamestart, file->d_name); + if (strrchr(fnamestart, '.') == (char *)NULL) + strcat(fnamestart, "."); + if (match(fnamestart, wildname, 1 WISEP) && /* 1=ignore case */ + /* skip "." and ".." directory entries */ + strcmp(fnamestart, ".") && strcmp(fnamestart, "..")) { + Trace((stderr, "do_wild: match() succeeds\n")); + /* remove trailing dot */ + fnamestart += strlen(fnamestart) - 1; + if (*fnamestart == '.') + *fnamestart = '\0'; + return matchname; + } + } + /* if we get to here directory is exhausted, so close it */ + closedir(wild_dir); + wild_dir = (DIR *)NULL; + } +#ifdef DEBUG + else { + Trace((stderr, "do_wild: opendir(%s) returns NULL\n", + FnFilter1(dirname))); + } +#endif /* DEBUG */ + + /* return the raw wildspec in case that works (e.g., directory not + * searchable, but filespec was not wild and file is readable) */ + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (wild_dir == (DIR *)NULL) { + notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + } + + /* If we've gotten this far, we've read and matched at least one entry + * successfully (in a previous call), so dirname has been copied into + * matchname already. + */ + if (have_dirname) { + /* strcpy(matchname, dirname); */ + fnamestart = matchname + dirnamelen; + } else + fnamestart = matchname; + while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + strcpy(fnamestart, file->d_name); + if (strrchr(fnamestart, '.') == (char *)NULL) + strcat(fnamestart, "."); + if (match(fnamestart, wildname, 1 WISEP)) { /* 1 == ignore case */ + Trace((stderr, "do_wild: match() succeeds\n")); + /* remove trailing dot */ + fnamestart += strlen(fnamestart) - 1; + if (*fnamestart == '.') + *fnamestart = '\0'; + return matchname; + } + } + + closedir(wild_dir); /* have read at least one entry; nothing left */ + wild_dir = (DIR *)NULL; + notfirstcall = FALSE; /* reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + +} /* end function do_wild() */ + +#endif /* !SFX */ + + + +/**********************/ +/* Function mapattr() */ +/**********************/ + +int mapattr(__G) + __GDEF +{ + /* set archive bit (file is not backed up): */ + G.pInfo->file_attr = (unsigned)(G.crec.external_file_attributes & 7) | 32; + return 0; +} + + + +/**********************/ +/* Function mapname() */ +/**********************/ + +int mapname(__G__ renamed) + __GDEF + int renamed; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - caution (truncated filename) + * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) + * MPN_ERR_SKIP - error -> skip entry + * MPN_ERR_TOOLONG - error -> path is too long + * MPN_NOMEM - error (memory allocation failed) -> skip entry + * [also MPN_VOL_LABEL, MPN_CREATED_DIR] + */ +{ + char pathcomp[FILNAMSIZ]; /* path-component buffer */ + char *pp, *cp=(char *)NULL; /* character pointers */ + char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ + char *last_dot=(char *)NULL; /* last dot not converted to underscore */ + int dotname = FALSE; /* path component begins with dot? */ + int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ + int error = MPN_OK; + register unsigned workch; /* hold the character being tested */ + + + if (G.pInfo->vollabel) + return MPN_VOL_LABEL; /* Cannot set disk volume labels in FlexOS */ + +/*--------------------------------------------------------------------------- + Initialize various pointers and counters and stuff. + ---------------------------------------------------------------------------*/ + + /* can create path as long as not just freshening, or if user told us */ + G.create_dirs = (!uO.fflag || renamed); + + created_dir = FALSE; /* not yet */ + renamed_fullpath = FALSE; + + if (renamed) { + cp = G.filename - 1; /* point to beginning of renamed name... */ + while (*++cp) + if (*cp == '\\') /* convert backslashes to forward */ + *cp = '/'; + cp = G.filename; + /* use temporary rootpath if user gave full pathname */ + if (G.filename[0] == '/') { + renamed_fullpath = TRUE; + pathcomp[0] = '/'; /* copy the '/' and terminate */ + pathcomp[1] = '\0'; + ++cp; + } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') { + renamed_fullpath = TRUE; + pp = pathcomp; + *pp++ = *cp++; /* copy the "d:" (+ '/', possibly) */ + *pp++ = *cp++; + if (*cp == '/') + *pp++ = *cp++; /* otherwise add "./"? */ + *pp = '\0'; + } + } + + /* pathcomp is ignored unless renamed_fullpath is TRUE: */ + if ((error = checkdir(__G__ pathcomp, INIT)) != 0) /* initialize path buf */ + return error; /* ...unless no mem or vol label on hard disk */ + + *pathcomp = '\0'; /* initialize translation buffer */ + pp = pathcomp; /* point to translation buffer */ + if (!renamed) { /* cp already set if renamed */ + if (uO.jflag) /* junking directories */ + cp = (char *)strrchr(G.filename, '/'); + if (cp == (char *)NULL) /* no '/' or not junking dirs */ + cp = G.filename; /* point to internal zipfile-member pathname */ + else + ++cp; /* point to start of last component of path */ + } + +/*--------------------------------------------------------------------------- + Begin main loop through characters in filename. + ---------------------------------------------------------------------------*/ + + while ((workch = (uch)*cp++) != 0) { + + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + map2fat(pathcomp, last_dot); /* 8.3 truncation (in place) */ + last_dot = (char *)NULL; + if (strcmp(pathcomp, ".") == 0) { + /* don't bother appending "./" to the path */ + *pathcomp = '\0'; + } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { + /* "../" dir traversal detected, skip over it */ + *pathcomp = '\0'; + killed_ddot = TRUE; /* set "show message" flag */ + } + /* when path component is not empty, append it now */ + if (*pathcomp != '\0' && + ((error = checkdir(__G__ pathcomp, APPEND_DIR)) + & MPN_MASK) > MPN_INF_TRUNC) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ + break; + + case '.': + if (pp == pathcomp) { /* nothing appended yet... */ + if (*cp == '.' && cp[1] == '/') { /* "../" */ + *pp++ = '.'; /* add first dot, unchanged... */ + ++cp; /* skip second dot, since it will */ + } else { /* be "added" at end of if-block */ + *pp++ = '_'; /* FAT doesn't allow null filename */ + dotname = TRUE; /* bodies, so map .exrc -> _.exrc */ + } /* (extra '_' now, "dot" below) */ + } else if (dotname) { /* found a second dot, but still */ + dotname = FALSE; /* have extra leading underscore: */ + *pp = '\0'; /* remove it by shifting chars */ + pp = pathcomp + 1; /* left one space (e.g., .p1.p2: */ + while (pp[1]) { /* __p1 -> _p1_p2 -> _p1.p2 when */ + *pp = pp[1]; /* finished) [opt.: since first */ + ++pp; /* two chars are same, can start */ + } /* shifting at second position] */ + } + last_dot = pp; /* point at last dot so far... */ + *pp++ = '_'; /* convert dot to underscore for now */ + break; + + /* drive names are not stored in zipfile, so no colons allowed; + * no brackets or most other punctuation either (all of which + * can appear in Unix-created archives; backslash is particularly + * bad unless all necessary directories exist) */ + case '[': /* these punctuation characters forbidden */ + case ']': /* only on plain FAT file systems */ + case '+': + case ',': + case '=': + case ':': /* special shell characters of command.com */ + case '\\': /* (device and directory limiters, wildcard */ + case '"': /* characters, stdin/stdout redirection and */ + case '<': /* pipe indicators and the quote sign) are */ + case '>': /* never allowed in filenames on (V)FAT */ + case '|': + case '*': + case '?': + *pp++ = '_'; + break; + + case ';': /* start of VMS version? */ + lastsemi = pp; + break; + + case ' ': /* change spaces to underscores */ + if (uO.sflag) /* only if requested */ + *pp++ = '_'; + else + *pp++ = (char)workch; + break; + + default: + /* allow ASCII 255 and European characters in filenames: */ + if (isprint(workch) || workch >= 127) + *pp++ = (char)workch; + + } /* end switch */ + } /* end while loop */ + + /* Show warning when stripping insecure "parent dir" path components */ + if (killed_ddot && QCOND2) { + Info(slide, 0, ((char *)slide, LoadFarString(WarnDirTraversSkip), + FnFilter1(G.filename))); + if (!(error & ~MPN_MASK)) + error = (error & MPN_MASK) | PK_WARN; + } + +/*--------------------------------------------------------------------------- + Report if directory was created (and no file to create: filename ended + in '/'), check name to be sure it exists, and combine path and name be- + fore exiting. + ---------------------------------------------------------------------------*/ + + if (G.filename[strlen(G.filename) - 1] == '/') { + checkdir(__G__ G.filename, GETPATH); + if (created_dir) { + if (QCOND2) { + Info(slide, 0, ((char *)slide, LoadFarString(Creating), + FnFilter1(G.filename))); + } + /* set dir time (note trailing '/') */ + return (error & ~MPN_MASK) | MPN_CREATED_DIR; + } + /* dir existed already; don't look for data to extract */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + *pp = '\0'; /* done with pathcomp: terminate it */ + + /* if not saving them, remove VMS version numbers (appended ";###") */ + if (!uO.V_flag && lastsemi) { + pp = lastsemi; /* semi-colon was omitted: expect all #'s */ + while (isdigit((uch)(*pp))) + ++pp; + if (*pp == '\0') /* only digits between ';' and end: nuke */ + *lastsemi = '\0'; + } + + map2fat(pathcomp, last_dot); /* 8.3 truncation (in place) */ + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed), + FnFilter1(G.filename))); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + + checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ + checkdir(__G__ G.filename, GETPATH); + + return error; + +} /* end function mapname() */ + + + + +/**********************/ +/* Function map2fat() */ +/**********************/ + +static void map2fat(pathcomp, last_dot) + char *pathcomp, *last_dot; +{ + char *pEnd = pathcomp + strlen(pathcomp); + +/*--------------------------------------------------------------------------- + Case 1: filename has no dot, so figure out if we should add one. Note + that the algorithm does not try to get too fancy: if there are no dots + already, the name either gets truncated at 8 characters or the last un- + derscore is converted to a dot (only if more characters are saved that + way). In no case is a dot inserted between existing characters. + + GRR: have problem if filename is volume label?? + + ---------------------------------------------------------------------------*/ + + /* pEnd = pathcomp + strlen(pathcomp); */ + if (last_dot == (char *)NULL) { /* no dots: check for underscores... */ + char *plu = strrchr(pathcomp, '_'); /* pointer to last underscore */ + + if (plu == (char *)NULL) { /* no dots, no underscores: truncate at */ + if (pEnd > pathcomp+8) /* 8 chars (could insert '.' and keep 11) */ + *(pEnd = pathcomp+8) = '\0'; + } else if (MIN(plu - pathcomp, 8) + MIN(pEnd - plu - 1, 3) > 8) { + last_dot = plu; /* be lazy: drop through to next if-block */ + } else if ((pEnd - pathcomp) > 8) /* more fits into just basename */ + pathcomp[8] = '\0'; /* than if convert last underscore to dot */ + /* else whole thing fits into 8 chars or less: no change */ + } + +/*--------------------------------------------------------------------------- + Case 2: filename has dot in it, so truncate first half at 8 chars (shift + extension if necessary) and second half at three. + ---------------------------------------------------------------------------*/ + + if (last_dot != (char *)NULL) { /* one dot (or two, in the case of */ + *last_dot = '.'; /* "..") is OK: put it back in */ + + if ((last_dot - pathcomp) > 8) { + char *p=last_dot, *q=pathcomp+8; + int i; + + for (i = 0; (i < 4) && *p; ++i) /* too many chars in basename: */ + *q++ = *p++; /* shift extension left and */ + *q = '\0'; /* truncate/terminate it */ + } else if ((pEnd - last_dot) > 4) + last_dot[4] = '\0'; /* too many chars in extension */ + /* else filename is fine as is: no change */ + } +} /* end function map2fat() */ + + + + +/***********************/ +/* Function checkdir() */ +/***********************/ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename + * MPN_INF_SKIP - path doesn't exist, not allowed to create + * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path + * exists and is not a directory, but is supposed to be + * MPN_ERR_TOOLONG - path is too long + * MPN_NOMEM - can't allocate memory for filename buffers + */ +{ + static int rootlen = 0; /* length of rootpath */ + static char *rootpath; /* user's "extract-to" directory */ + static char *buildpath; /* full path (so far) to extracted file */ + static char *end; /* pointer to end of buildpath ('\0') */ + +# define FN_MASK 7 +# define FUNCTION (flag & FN_MASK) + + +/*--------------------------------------------------------------------------- + APPEND_DIR: append the path component to the path being built and check + for its existence. If doesn't exist and we are creating directories, do + so for this one; else signal success or error as appropriate. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_DIR) { + int too_long = FALSE; + + Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') + ++end; + + /* GRR: could do better check, see if overrunning buffer as we go: + * check end-buildpath after each append, set warning variable if + * within 20 of FILNAMSIZ; then if var set, do careful check when + * appending. Clear variable when begin new path. */ + + if ((end-buildpath) > FILNAMSIZ-3) /* need '/', one-char name, '\0' */ + too_long = TRUE; /* check if extracting directory? */ + if (stat(buildpath, &G.statbuf)) /* path doesn't exist */ + { + if (!G.create_dirs) { /* told not to create (freshening) */ + free(buildpath); + return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong), + FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + if (mkdir(buildpath, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir), + FnFilter2(buildpath), FnFilter1(G.filename))); + free(buildpath); + /* path didn't exist, tried to create, failed */ + return MPN_ERR_SKIP; + } + created_dir = TRUE; + } else if (!S_ISDIR(G.statbuf.st_mode)) { + Info(slide, 1, ((char *)slide, LoadFarString(DirIsntDirectory), + FnFilter2(buildpath), FnFilter1(G.filename))); + free(buildpath); + /* path existed but wasn't dir */ + return MPN_ERR_SKIP; + } + if (too_long) { + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong), + FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + *end++ = '/'; + *end = '\0'; + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + return MPN_OK; + + } /* end if (FUNCTION == APPEND_DIR) */ + +/*--------------------------------------------------------------------------- + GETPATH: copy full path to the string pointed at by pathcomp, and free + buildpath. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == GETPATH) { + strcpy(pathcomp, buildpath); + Trace((stderr, "getting and freeing path [%s]\n", + FnFilter1(pathcomp))); + free(buildpath); + buildpath = end = (char *)NULL; + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + APPEND_NAME: assume the path component is the filename; append it and + return without checking for existence. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_NAME) { + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') { + ++end; + if ((end-buildpath) >= FILNAMSIZ) { + *--end = '\0'; + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLongTrunc), + FnFilter1(G.filename), FnFilter2(buildpath))); + return MPN_INF_TRUNC; /* filename truncated */ + } + } + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + /* could check for existence here, prompt for new name... */ + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + INIT: allocate and initialize buffer space for the file currently being + extracted. If file was renamed with an absolute path, don't prepend the + extract-to path. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == INIT) { + Trace((stderr, "initializing buildpath to ")); + /* allocate space for full filename, root path, and maybe "./" */ + if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+3)) == + (char *)NULL) + return MPN_NOMEM; + if (renamed_fullpath) { /* pathcomp = valid data */ + end = buildpath; + while ((*end = *pathcomp++) != '\0') + ++end; + } else if (rootlen > 0) { + strcpy(buildpath, rootpath); + end = buildpath + rootlen; + } else { + *buildpath = '\0'; + end = buildpath; + } + Trace((stderr, "[%s]\n", FnFilter1(buildpath))); + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + ROOT: if appropriate, store the path in rootpath and create it if neces- + sary; else assume it's a zipfile member and return. This path segment + gets used in extracting all members from every zipfile specified on the + command line. Note that under FlexOS, if a candidate extract-to + directory specification includes a drive letter (leading "x:"), it is + treated just as if it had a trailing '/'--that is, one directory level + will be created if the path doesn't exist, unless this is otherwise pro- + hibited (e.g., freshening). + ---------------------------------------------------------------------------*/ + +#if (!defined(SFX) || defined(SFX_EXDIR)) + if (FUNCTION == ROOT) { + Trace((stderr, "initializing root path to [%s]\n", + FnFilter1(pathcomp))); + if (pathcomp == (char *)NULL) { + rootlen = 0; + return MPN_OK; + } + if (rootlen > 0) /* rootpath was already set, nothing to do */ + return MPN_OK; + if ((rootlen = strlen(pathcomp)) > 0) { + int had_trailing_pathsep=FALSE, add_dot=FALSE; + char *tmproot; + + if ((tmproot = (char *)malloc(rootlen+3)) == (char *)NULL) { + rootlen = 0; + return MPN_NOMEM; + } + strcpy(tmproot, pathcomp); + if (tmproot[rootlen-1] == '/' || tmproot[rootlen-1] == '\\') { + tmproot[--rootlen] = '\0'; + had_trailing_pathsep = TRUE; + } + if (tmproot[rootlen-1] == ':') { + if (!had_trailing_pathsep) /* i.e., original wasn't "xxx:/" */ + add_dot = TRUE; /* relative path: add '.' before '/' */ + } else if (rootlen > 0) && /* need not check "xxx:." and "xxx:/" */ + (SSTAT(tmproot, &G.statbuf) || + !S_ISDIR(G.statbuf.st_mode)) + { + /* path does not exist */ + if (!G.create_dirs /* || iswild(tmproot) */ ) { + free(tmproot); + rootlen = 0; + /* treat as stored file */ + return MPN_INF_SKIP; + } +/* GRR: scan for wildcard characters? OS-dependent... + * if find any, return MPN_INF_SKIP: treat as stored file(s) */ + /* create directory (could add loop here scanning tmproot + * to create more than one level, but really necessary?) */ + if (mkdir(tmproot, 0777) == -1) { + Info(slide, 1, ((char *)slide, + LoadFarString(CantCreateExtractDir), + FnFilter1(tmproot))); + free(tmproot); + rootlen = 0; + /* path didn't exist, tried to create, and failed: */ + /* file exists, or 2+ subdir levels required */ + return MPN_ERR_SKIP; + } + } + if (add_dot) /* had just "x:", make "x:." */ + tmproot[rootlen++] = '.'; + tmproot[rootlen++] = '/'; + tmproot[rootlen] = '\0'; + if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { + free(tmproot); + rootlen = 0; + return MPN_NOMEM; + } + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath))); + } + return MPN_OK; + } +#endif /* !SFX || SFX_EXDIR */ + +/*--------------------------------------------------------------------------- + END: free rootpath, immediately prior to program exit. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == END) { + Trace((stderr, "freeing rootpath\n")); + if (rootlen > 0) { + free(rootpath); + rootlen = 0; + } + return MPN_OK; + } + + return MPN_INVALID; /* should never reach */ + +} /* end function checkdir() */ + + + + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) + __GDEF + /* + * FlexOS VERSION + * + * Set the output file date/time stamp according to information from the + * zipfile directory record for this member, then close the file and set + * its permissions (archive, hidden, read-only, system). Aside from closing + * the file, this routine is optional (but most compilers support it). + */ +{ + DISKFILE df; + LONG fnum; + + struct { /* date and time words */ + union { /* DOS file modification time word */ + ush ztime; + struct { + unsigned zt_se : 5; + unsigned zt_mi : 6; + unsigned zt_hr : 5; + } _tf; + } _t; + union { /* DOS file modification date word */ + ush zdate; + struct { + unsigned zd_dy : 5; + unsigned zd_mo : 4; + unsigned zd_yr : 7; + } _df; + } _d; + } zt; + +#ifdef USE_EF_UT_TIME + iztimes z_utime; + struct tm *t; +#endif /* ?USE_EF_UT_TIME */ + + fclose(G.outfile); + + if ((fnum = s_open(A_SET, G.filename)) < 0) { + Info(slide, 0x201, ((char *)slide, + "warning: cannot open %s to set the time\n", + FnFilter1(G.filename))); + return; + } + + if (s_get(T_FILE, fnum, &df, DSKFSIZE) < 0) { + s_close(0, fnum); + + Info(slide, 0x201, ((char *)slide, + "warning: cannot get info on %s\n", FnFilter1(G.filename))); + return; + } + + /* skip restoring time stamps on user's request */ + if (uO.D_flag <= 1) { + +/*--------------------------------------------------------------------------- + Copy and/or convert time and date variables, if necessary; then fill in + the file time/date. + ---------------------------------------------------------------------------*/ + +#ifdef USE_EF_UT_TIME + if (G.extra_field && +#ifdef IZ_CHECK_TZ + G.tz_is_valid && +#endif + (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, + G.lrec.last_mod_dos_datetime, &z_utime, NULL) & EB_UT_FL_MTIME)) + { + TTrace((stderr, "close_outfile: Unix e.f. modif. time = %ld\n", + z_utime.mtime)); + t = localtime(&(z_utime.mtime)); + } else + t = (struct tm *)NULL; + if (t != (struct tm *)NULL) { + if (t->tm_year < 80) { + df.df_modyear = 1980; + df.df_modmonth = 1; + df.df_modday = 1; + df.df_modhr = 0; + df.df_modmin = 0; + df.df_modsec = 0; + } else { + df.df_modyear = t->tm_year + 1900; + df.df_modmonth = t->tm_mon + 1; + df.df_modday = t->tm_mday; + df.df_modhr = t->tm_hour; + df.df_modmin = t->tm_min; + df.df_modsec = t->tm_sec; + } + } else +#endif /* ?USE_EF_UX_TIME */ + { + zt._t.ztime = (ush)(G.lrec.last_mod_dos_datetime) & 0xffff; + zt._d.zdate = (ush)(G.lrec.last_mod_dos_datetime >> 16); + + df.df_modyear = 1980 + zt._d._df.zd_yr; + df.df_modmonth = zt._d._df.zd_mo; + df.df_modday = zt._d._df.zd_dy; + df.df_modhr = zt._t._tf.zt_hr; + df.df_modmin = zt._t._tf.zt_mi; + df.df_modsec = zt._t._tf.zt_se << 1; + } + } + +/*--------------------------------------------------------------------------- + Fill in the file attributes. + ---------------------------------------------------------------------------*/ + + df.df_attr1 = (UBYTE)G.pInfo->file_attr; + +/*--------------------------------------------------------------------------- + Now we try to set the attributes & date/time. + ---------------------------------------------------------------------------*/ + + if (s_set(T_FILE, fnum, &df, DSKFSIZE) < 0) + Info(slide, 0x201, ((char *)slide, + "warning: cannot set info for %s\n", FnFilter1(G.filename))); + + s_close(0, fnum); +} /* end function close_outfile() */ + +#ifndef SFX + +/*************************/ +/* Function dateformat() */ +/*************************/ + +int dateformat() +{ + return DF_DMY; /* default for systems without locale info */ +} + +/************************/ +/* Function version() */ +/************************/ + +void version(__G) + __GDEF +{ + int len; + + len = sprintf((char *)slide, LoadFarString(CompiledWith), + "MetaWare High C", + "", + "FlexOS", + " (16-bit, big)", + +#ifdef __DATE__ + " on ", __DATE__ +#else + "", "" +#endif + ); + + (*G.message)((zvoid *)&G, slide, (ulg)len, 0); +} + +#endif /* !SFX */ + +/************************/ +/* Function _wildarg() */ +/************************/ + +/* This prevents the PORTLIB startup code from preforming argument globbing */ + +_wildarg() {} diff --git a/flexos/flxcfg.h b/flexos/flxcfg.h new file mode 100644 index 0000000..6bb910f --- /dev/null +++ b/flexos/flxcfg.h @@ -0,0 +1,30 @@ +/* + 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 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 +*/ +/*--------------------------------------------------------------------------- + FlexOS specific configuration section: + ---------------------------------------------------------------------------*/ + +#ifndef __flxcfg_h +#define __flxcfg_h + +#define __16BIT__ +#define MED_MEM +#define EXE_EXTENSION ".286" + +#ifndef nearmalloc +# define nearmalloc malloc +# define nearfree free +#endif + +#define CRTL_CP_IS_OEM + +#define near +#define far + +#endif /* !__flxcfg_h */ diff --git a/flexos/hc.pro b/flexos/hc.pro new file mode 100644 index 0000000..6b235db --- /dev/null +++ b/flexos/hc.pro @@ -0,0 +1,19 @@ +pragma Off(Floating_point); +pragma On(286); +pragma On(Literals_in_code); +pragma On(Warn); +pragma On(pointers_compatible); +pragma On(Callee_pops_when_possible); + +pragma On(Auto_reg_alloc); +pragma On(Const_in_Code); +pragma On(Read_only_strings); +pragma On(Optimize_for_space); + +pragma Off(Prototype_override_warnings); +pragma Off(Quiet); +pragma Off(Asm); +pragma Off(flexview); + +#define PORTLIB +#define FLEXOS 1 diff --git a/flexos/makefile b/flexos/makefile new file mode 100644 index 0000000..cc9d8fc --- /dev/null +++ b/flexos/makefile @@ -0,0 +1,199 @@ +#------------------------------------------------------------------------------ +# Makefile for UnZip 5.53 and later Derek Fawcus +# Version: MetaWare High C with PAMAKE 30 Dec 2005 + +# +########################################################################### +# +# Alter the first two macros to change the model +# + +MODEL = big +M = b + +# +########################################################################### +# +# These two sets of prefixes are changed when swapping between the master +# and my machine. +# + +FL_PREFIX = d:/flexos # Where FlexOS is rooted +#FL_PREFIX = c:/. + +# +########################################################################### +# +# The following should not have to be changed - they should be automatic +# given correct values for the above. +# + +HC_LIB = $(FL_PREFIX)/highc/$(MODEL)/hc$(M)e.l86 +PORT_LIB = $(FL_PREFIX)/usr/portlib/$(MODEL)/prtlbhc$(M).l86 +PORT_OBJ = $(FL_PREFIX)/usr/portlib/$(MODEL)/prtlbhc$(M).obj + +HC_INC = $(FL_PREFIX)/highc/inc +PORT_INC = $(FL_PREFIX)/usr/portlib/inc +FLEX_INC = $(FL_PREFIX)/usr/inc + ++IPATH = $(PORT_INC)/;$(FLEX_INC)/; +#+IPATH = $(PORT_INC)/;$(HC_INC)/;$(FLEX_INC)/; + +# +########################################################################### +# +# The programs to do the work. +# + +CC = hc +AS = rasm86 +LD = link86 + +#HCOPTS=-mm $(MODEL) -debug -pr flexos/hc.pro +HCOPTS=-mm $(MODEL) -pr flexos/hc.pro + +# +########################################################################### +# +# The file extensions to build from +# + +.SUFFIXES: +.SUFFIXES: .c .h .a86 + +# +########################################################################### +# + +# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. +CPU_TYP = 2 + +# Uncomment the following three macros to use the optimized CRC32 assembler +# routine in UnZip and UnZipSFX: +#ASMFLG = -DASM_CRC +#ASMOBJS = crc_i86.obj +#ASMOBJF = crc_i86_.obj + +ASCPUFLAG = __$(CPU_TYP)86 + +UNZIP_H = unzip.h unzpriv.h globals.h flexos/flxcfg.h + +default: unzip.286 +#default: unzip.286 funzip.286 unzipsfx.286 + +clean: + del *.ob? + del unzip.286 + del funzip.286 + del unzipsfx.* + del *.map + del *.lin + del *.sym + del *.dbg + +# +########################################################################### +# + +.asm.obj: + $(AS) $(ASFLAGS) -D$(ASUNMODEL) $*.asm + +.c.obj: + $(CC) $< $(HCOPTS) -ob $@ + +.c.obf: + $(CC) $< $(HCOPTS) -def FUNZIP -ob $@ + +.c.obs: + $(CC) $< $(HCOPTS) -def SFX -ob $@ + +# +########################################################################### +# + +crc_i86.obj: flexos/crc_i86.a86 + $(AS) $(ASFLAGS) -D$(ASUNMODEL) flexos/crc_i86.a86, $*.obj ; + +# +######################################################################### +# +# The objects to build from +# + +UNZIP_OBJS = unzip.obj crc32.obj crypt.obj envargs.obj \ + explode.obj extract.obj fileio.obj globals.obj inflate.obj \ + list.obj match.obj process.obj ttyio.obj unreduce.obj \ + unshrink.obj zipinfo.obj flexos.obj $(ASMOBJS) + +unzip.286: $(UNZIP_OBJS) + $(LD) $@[st[add[17e]]] = $-[input] +$(PORT_OBJ), +$+(${UNZIP_OBJS}), +$(PORT_LIB), +$(HC_LIB) +< + +UNZIPSFX_OBJS = unzip.obs crc32.obs crypt.obs extract.obs \ + fileio.obs globals.obs inflate.obs match.obs process.obs \ + ttyio.obs flexos.obs $(ASMOBJS) + +unzipsfx.286: $(UNZIPSFX_OBJS) + $(LD) $@[dbi,map[all],st[add[17e]]] = $-[input] +$(PORT_OBJ), +$+(${UNZIPSFX_OBJS}), +$(PORT_LIB), +$(HC_LIB) +< + +FUNZIP_OBJS = funzip.obj crc32.obf crypt.obf globals.obf inflate.obf \ + ttyio.obf $(ASMOBJF) + +funzip.286: $(FUNZIP_OBJS) + $(LD) $@[dbi,map[all],st[add[17e]]] = $-[input] +$(PORT_OBJ), +$+(${FUNZIP_OBJS}), +$(PORT_LIB), +$(HC_LIB) +< + +# +########################################################################### +# + +unreduce.obj: unreduce.c $(UNZIP_H) +unshrink.obj: unshrink.c $(UNZIP_H) +unzip.obj: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +zipinfo.obj: zipinfo.c $(UNZIP_H) +process.obj: process.c $(UNZIP_H) crc32.h +list.obj: list.c $(UNZIP_H) +match.obj: match.c $(UNZIP_H) +fileio.obj: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +envargs.obj: envargs.c $(UNZIP_H) +explode.obj: explode.c $(UNZIP_H) +extract.obj: extract.c $(UNZIP_H) crc32.h crypt.h +crc32.obj: crc32.c $(UNZIP_H) zip.h crc32.h + +flexos.obj: flexos/flexos.c $(UNZIP_H) +crc32.obj: crc32.c $(UNZIP_H) zip.h crc32.h +crypt.obj: crypt.c $(UNZIP_H) crc32.h crypt.h ttyio.h zip.h +globals.obj: globals.c $(UNZIP_H) +inflate.obj: inflate.c inflate.h $(UNZIP_H) +ttyio.obj: ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h + +funzip.obj: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h +crc32.obf: crc32.c $(UNZIP_H) zip.h crc32.h +crypt.obf: crypt.c $(UNZIP_H) crypt.h ttyio.h zip.h +globals.obf: globals.c $(UNZIP_H) +inflate.obf: inflate.c inflate.h $(UNZIP_H) crypt.h +ttyio.obf: ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h + +flexos.obs: flexos/flexos.c $(UNZIP_H) +crc32.obs: crc32.c $(UNZIP_H) zip.h crc32.h +extract.obs: extract.c $(UNZIP_H) crc32.h crypt.h +fileio.obs: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +globals.obs: globals.c $(UNZIP_H) +inflate.obs: inflate.c inflate.h $(UNZIP_H) crypt.h +match.obs: match.c $(UNZIP_H) +process.obs: process.c $(UNZIP_H) crc32.h +ttyio.obs: ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h +unzip.obs: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h diff --git a/funzip.c b/funzip.c new file mode 100644 index 0000000..1e55910 --- /dev/null +++ b/funzip.c @@ -0,0 +1,547 @@ +/* + Copyright (c) 1990-2009 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2009-Jan-02 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 +*/ +/* funzip.c -- by Mark Adler */ + +#define VERSION "3.95 of 20 January 2009" + + +/* Copyright history: + - Starting with UnZip 5.41 of 16-April-2000, this source file + is covered by the Info-Zip LICENSE cited above. + - Prior versions of this source file, found in UnZip source packages + up to UnZip 5.40, were put in the public domain. + The original copyright note by Mark Adler was: + "You can do whatever you like with this source file, + though I would prefer that if you modify it and + redistribute it that you include comments to that effect + with your name and the date. Thank you." + + History: + vers date who what + ---- --------- -------------- ------------------------------------ + 1.0 13 Aug 92 M. Adler really simple unzip filter. + 1.1 13 Aug 92 M. Adler cleaned up somewhat, give help if + stdin not redirected, warn if more + zip file entries after the first. + 1.2 15 Aug 92 M. Adler added check of lengths for stored + entries, added more help. + 1.3 16 Aug 92 M. Adler removed redundant #define's, added + decryption. + 1.4 27 Aug 92 G. Roelofs added exit(0). + 1.5 1 Sep 92 K. U. Rommel changed read/write modes for OS/2. + 1.6 6 Sep 92 G. Roelofs modified to use dummy crypt.c and + crypt.h instead of -DCRYPT. + 1.7 23 Sep 92 G. Roelofs changed to use DOS_OS2; included + crypt.c under MS-DOS. + 1.8 9 Oct 92 M. Adler improved inflation error msgs. + 1.9 17 Oct 92 G. Roelofs changed ULONG/UWORD/byte to ulg/ush/uch; + renamed inflate_entry() to inflate(); + adapted to use new, in-place zdecode. + 2.0 22 Oct 92 M. Adler allow filename argument, prompt for + passwords and don't echo, still allow + command-line password entry, but as an + option. + 2.1 23 Oct 92 J-l. Gailly fixed crypt/store bug, + G. Roelofs removed crypt.c under MS-DOS, fixed + decryption check to compare single byte. + 2.2 28 Oct 92 G. Roelofs removed declaration of key. + 2.3 14 Dec 92 M. Adler replaced fseek (fails on stdin for SCO + Unix V.3.2.4). added quietflg for + inflate.c. + 3.0 11 May 93 M. Adler added gzip support + 3.1 9 Jul 93 K. U. Rommel fixed OS/2 pipe bug (PIPE_ERROR) + 3.2 4 Sep 93 G. Roelofs moved crc_32_tab[] to tables.h; used FOPx + from unzip.h; nuked OUTB macro and outbuf; + replaced flush(); inlined FlushOutput(); + renamed decrypt to encrypted + 3.3 29 Sep 93 G. Roelofs replaced ReadByte() with NEXTBYTE macro; + revised (restored?) flush(); added FUNZIP + 3.4 21 Oct 93 G. Roelofs renamed quietflg to qflag; changed outcnt, + H. Gessau second updcrc() arg and flush() arg to ulg; + added inflate_free(); added "g =" to null + getc(in) to avoid compiler warnings + 3.5 31 Oct 93 H. Gessau changed DOS_OS2 to DOS_NT_OS2 + 3.6 6 Dec 93 H. Gessau added "near" to mask_bits[] + 3.7 9 Dec 93 G. Roelofs added extent typecasts to fwrite() checks + 3.8 28 Jan 94 GRR/JlG initialized g variable in main() for gcc + 3.81 22 Feb 94 M. Hanning-Lee corrected usage message + 3.82 27 Feb 94 G. Roelofs added some typecasts to avoid warnings + 3.83 22 Jul 94 G. Roelofs changed fprintf to macro for DLLs + - 2 Aug 94 - public release with UnZip 5.11 + - 28 Aug 94 - public release with UnZip 5.12 + 3.84 1 Oct 94 K. U. Rommel changes for Metaware High C + 3.85 29 Oct 94 G. Roelofs changed fprintf macro to Info + 3.86 7 May 95 K. Davis RISCOS patches; + P. Kienitz Amiga patches + 3.87 12 Aug 95 G. Roelofs inflate_free(), DESTROYGLOBALS fixes + 3.88 4 Sep 95 C. Spieler reordered macro to work around MSC 5.1 bug + 3.89 22 Nov 95 PK/CS ifdef'd out updcrc() for ASM_CRC + 3.9 17 Dec 95 G. Roelofs modified for USE_ZLIB (new fillinbuf()) + - 30 Apr 96 - public release with UnZip 5.2 + 3.91 17 Aug 96 G. Roelofs main() -> return int (Peter Seebach) + 3.92 13 Apr 97 G. Roelofs minor cosmetic fixes to messages + - 22 Apr 97 - public release with UnZip 5.3 + - 31 May 97 - public release with UnZip 5.31 + 3.93 20 Sep 97 G. Roelofs minor cosmetic fixes to messages + - 3 Nov 97 - public release with UnZip 5.32 + - 28 Nov 98 - public release with UnZip 5.4 + - 16 Apr 00 - public release with UnZip 5.41 + - 14 Jan 01 - public release with UnZip 5.42 + 3.94 20 Feb 01 C. Spieler added support for Deflate64(tm) + 23 Mar 02 C. Spieler changed mask_bits[] type to "unsigned" + */ + + +/* + + All funzip does is take a zipfile from stdin and decompress the + first entry to stdout. The entry has to be either deflated or + stored. If the entry is encrypted, then the decryption password + must be supplied on the command line as the first argument. + + funzip needs to be linked with inflate.o and crypt.o compiled from + the unzip source. If decryption is desired, the full version of + crypt.c (and crypt.h) from zcrypt28.zip or later must be used. + + */ + +#ifndef FUNZIP +# define FUNZIP +#endif +#define UNZIP_INTERNAL +#include "unzip.h" +#include "crc32.h" +#include "crypt.h" +#include "ttyio.h" + +#ifdef EBCDIC +# undef EBCDIC /* don't need ebcdic[] */ +#endif + +#ifndef USE_ZLIB /* zlib's function is called inflate(), too */ +# define UZinflate inflate +#endif + +/* PKZIP header definitions */ +#define ZIPMAG 0x4b50 /* two-byte zip lead-in */ +#define LOCREM 0x0403 /* remaining two bytes in zip signature */ +#define LOCSIG 0x04034b50L /* full signature */ +#define LOCFLG 4 /* offset of bit flag */ +#define CRPFLG 1 /* bit for encrypted entry */ +#define EXTFLG 8 /* bit for extended local header */ +#define LOCHOW 6 /* offset of compression method */ +#define LOCTIM 8 /* file mod time (for decryption) */ +#define LOCCRC 12 /* offset of crc */ +#define LOCSIZ 16 /* offset of compressed size */ +#define LOCLEN 20 /* offset of uncompressed length */ +#define LOCFIL 24 /* offset of file name field length */ +#define LOCEXT 26 /* offset of extra field length */ +#define LOCHDR 28 /* size of local header, including LOCREM */ +#define EXTHDR 16 /* size of extended local header, inc sig */ + +/* GZIP header definitions */ +#define GZPMAG 0x8b1f /* two-byte gzip lead-in */ +#define GZPHOW 0 /* offset of method number */ +#define GZPFLG 1 /* offset of gzip flags */ +#define GZPMUL 2 /* bit for multiple-part gzip file */ +#define GZPISX 4 /* bit for extra field present */ +#define GZPISF 8 /* bit for filename present */ +#define GZPISC 16 /* bit for comment present */ +#define GZPISE 32 /* bit for encryption */ +#define GZPTIM 2 /* offset of Unix file modification time */ +#define GZPEXF 6 /* offset of extra flags */ +#define GZPCOS 7 /* offset of operating system compressed on */ +#define GZPHDR 8 /* length of minimal gzip header */ + +#ifdef THEOS +/* Macros cause stack overflow in compiler */ +ush SH(uch* p) { return ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)); } +ulg LG(uch* p) { return ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)); } +#else /* !THEOS */ +/* Macros for getting two-byte and four-byte header values */ +#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)) +#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)) +#endif /* ?THEOS */ + +/* Function prototypes */ +static void err OF((int, char *)); +#if (defined(USE_DEFLATE64) && defined(__16BIT__)) +static int partflush OF((uch *rawbuf, unsigned w)); +#endif +int main OF((int, char **)); + +/* Globals */ +FILE *out; /* output file (*in moved to G struct) */ +ulg outsiz; /* total bytes written to out */ +int encrypted; /* flag to turn on decryption */ + +/* Masks for inflate.c */ +ZCONST unsigned near mask_bits[17] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + + +#ifdef USE_ZLIB + +int fillinbuf(__G) +__GDEF +/* Fill input buffer for pull-model inflate() in zlib. Return the number of + * bytes in inbuf. */ +{ +/* GRR: check return value from fread(): same as read()? check errno? */ + if ((G.incnt = fread((char *)G.inbuf, 1, INBUFSIZ, G.in)) <= 0) + return 0; + G.inptr = G.inbuf; + +#if CRYPT + if (encrypted) { + uch *p; + int n; + + for (n = G.incnt, p = G.inptr; n--; p++) + zdecode(*p); + } +#endif /* CRYPT */ + + return G.incnt; + +} + +#endif /* USE_ZLIB */ + + +static void err(n, m) +int n; +char *m; +/* Exit on error with a message and a code */ +{ + Info(slide, 1, ((char *)slide, "funzip error: %s\n", m)); + DESTROYGLOBALS(); + EXIT(n); +} + + +#if (defined(USE_DEFLATE64) && defined(__16BIT__)) + +static int partflush(rawbuf, w) +uch *rawbuf; /* start of buffer area to flush */ +extent w; /* number of bytes to flush */ +{ + G.crc32val = crc32(G.crc32val, rawbuf, (extent)w); + if (fwrite((char *)rawbuf,1,(extent)w,out) != (extent)w && !PIPE_ERROR) + err(9, "out of space on stdout"); + outsiz += w; + return 0; +} + + +int flush(w) /* used by inflate.c (FLUSH macro) */ +ulg w; /* number of bytes to flush */ +{ + uch *rawbuf; + int ret; + + /* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions + * cannot handle writes of 64k blocks at once. For these systems, the + * blocks to flush are split into pieces of 32k or less. + */ + rawbuf = slide; + while (w > 0x8000L) { + ret = partflush(rawbuf, 0x8000); + if (ret != PK_OK) + return ret; + w -= 0x8000L; + rawbuf += (unsigned)0x8000; + } + return partflush(rawbuf, (extent)w); +} /* end function flush() */ + +#else /* !(USE_DEFLATE64 && __16BIT__) */ + +int flush(w) /* used by inflate.c (FLUSH macro) */ +ulg w; /* number of bytes to flush */ +{ + G.crc32val = crc32(G.crc32val, slide, (extent)w); + if (fwrite((char *)slide,1,(extent)w,out) != (extent)w && !PIPE_ERROR) + err(9, "out of space on stdout"); + outsiz += w; + return 0; +} + +#endif /* ?(USE_DEFLATE64 && __16BIT__) */ + + +int main(argc, argv) +int argc; +char **argv; +/* Given a zipfile on stdin, decompress the first entry to stdout. */ +{ + ush n; + uch h[LOCHDR]; /* first local header (GZPHDR < LOCHDR) */ + int g = 0; /* true if gzip format */ + unsigned method = 0; /* initialized here to shut up gcc warning */ +#if CRYPT + char *s = " [-password]"; + char *p; /* password */ +#else /* !CRYPT */ + char *s = ""; +#endif /* ?CRYPT */ + CONSTRUCTGLOBALS(); + + /* skip executable name */ + argc--; + argv++; + +#if CRYPT + /* get the command line password, if any */ + p = (char *)NULL; + if (argc && **argv == '-') + { + argc--; + p = 1 + *argv++; + } +#endif /* CRYPT */ + +#ifdef MALLOC_WORK + /* The following expression is a cooked-down simplyfication of the + calculation for the work area size of UnZip (see unzip.c). For + fUnZip, the work area does not need to match the granularity + of the complex unshrink structures, because it only supports + inflation. But, like in UnZip, the zcalloc() wrapper function + is needed for the allocation, to support the 64kByte buffer on + 16-bit systems. + */ +# define UZ_SLIDE_CHUNK (sizeof(shrint)+sizeof(uch)+sizeof(uch)) +# define UZ_NUMOF_CHUNKS (unsigned)( (WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK ) + G.area.Slide = (uch *)zcalloc(UZ_NUMOF_CHUNKS, UZ_SLIDE_CHUNK); +# undef UZ_SLIDE_CHUNK +# undef UZ_NUMOF_CHUNKS +#endif + + /* if no file argument and stdin not redirected, give the user help */ + if (argc == 0 && isatty(0)) + { + Info(slide, 1, ((char *)slide, "fUnZip (filter UnZip), version %s\n", + VERSION)); + Info(slide, 1, ((char *)slide, "usage: ... | funzip%s | ...\n", s)); + Info(slide, 1, ((char *)slide, " ... | funzip%s > outfile\n", s)); + Info(slide, 1, ((char *)slide, " funzip%s infile.zip > outfile\n",s)); + Info(slide, 1, ((char *)slide, " funzip%s infile.gz > outfile\n", s)); + Info(slide, 1, ((char *)slide, "Extracts to stdout the gzip file or first\ + zip entry of stdin or the given file.\n")); + DESTROYGLOBALS(); + EXIT(3); + } + + /* prepare to be a binary filter */ + if (argc) + { + if ((G.in = fopen(*argv, FOPR)) == (FILE *)NULL) + err(2, "cannot find input file"); + } + else + { +#ifdef DOS_FLX_NLM_OS2_W32 +#if (defined(__HIGHC__) && !defined(FLEXOS)) + setmode(stdin, _BINARY); +#else + setmode(0, O_BINARY); /* some buggy C libraries require BOTH setmode() */ +#endif /* call AND the fdopen() in binary mode :-( */ +#endif /* DOS_FLX_NLM_OS2_W32 */ + +#ifdef RISCOS + G.in = stdin; +#else + if ((G.in = fdopen(0, FOPR)) == (FILE *)NULL) + err(2, "cannot find stdin"); +#endif + } + +#ifdef DOS_FLX_H68_NLM_OS2_W32 +#if (defined(__HIGHC__) && !defined(FLEXOS)) + setmode(stdout, _BINARY); +#else + setmode(1, O_BINARY); +#endif +#endif /* DOS_FLX_H68_NLM_OS2_W32 */ + +#ifdef RISCOS + out = stdout; +#else + if ((out = fdopen(1, FOPW)) == (FILE *)NULL) + err(2, "cannot write to stdout"); +#endif + + /* read local header, check validity, and skip name and extra fields */ + n = getc(G.in); n |= getc(G.in) << 8; + if (n == ZIPMAG) + { + if (fread((char *)h, 1, LOCHDR, G.in) != LOCHDR || SH(h) != LOCREM) + err(3, "invalid zipfile"); + switch (method = SH(h + LOCHOW)) { + case STORED: + case DEFLATED: +#ifdef USE_DEFLATE64 + case ENHDEFLATED: +#endif + break; + default: + err(3, "first entry not deflated or stored--cannot unpack"); + break; + } + for (n = SH(h + LOCFIL); n--; ) g = getc(G.in); + for (n = SH(h + LOCEXT); n--; ) g = getc(G.in); + g = 0; + encrypted = h[LOCFLG] & CRPFLG; + } + else if (n == GZPMAG) + { + if (fread((char *)h, 1, GZPHDR, G.in) != GZPHDR) + err(3, "invalid gzip file"); + if ((method = h[GZPHOW]) != DEFLATED && method != ENHDEFLATED) + err(3, "gzip file not deflated"); + if (h[GZPFLG] & GZPMUL) + err(3, "cannot handle multi-part gzip files"); + if (h[GZPFLG] & GZPISX) + { + n = getc(G.in); n |= getc(G.in) << 8; + while (n--) g = getc(G.in); + } + if (h[GZPFLG] & GZPISF) + while ((g = getc(G.in)) != 0 && g != EOF) ; + if (h[GZPFLG] & GZPISC) + while ((g = getc(G.in)) != 0 && g != EOF) ; + g = 1; + encrypted = h[GZPFLG] & GZPISE; + } + else + err(3, "input not a zip or gzip file"); + + /* if entry encrypted, decrypt and validate encryption header */ + if (encrypted) +#if CRYPT + { + ush i, e; + + if (p == (char *)NULL) { + if ((p = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL) + err(1, "out of memory"); + else if ((p = getp("Enter password: ", p, IZ_PWLEN+1)) == (char *)NULL) + err(1, "no tty to prompt for password"); + } + /* initialize crc_32_tab pointer for decryption */ + CRC_32_TAB = get_crc_table(); + /* prepare the decryption keys for extraction and check the password */ + init_keys(p); + for (i = 0; i < RAND_HEAD_LEN; i++) + e = NEXTBYTE; + if (e != (ush)(h[LOCFLG] & EXTFLG ? h[LOCTIM + 1] : h[LOCCRC + 3])) + err(3, "incorrect password for first entry"); + } +#else /* !CRYPT */ + err(3, "cannot decrypt entry (need to recompile with full crypt.c)"); +#endif /* ?CRYPT */ + + /* prepare output buffer and crc */ + G.outptr = slide; + G.outcnt = 0L; + outsiz = 0L; + G.crc32val = CRCVAL_INITIAL; + + /* decompress */ + if (g || h[LOCHOW]) + { /* deflated entry */ + int r; + +#ifdef USE_ZLIB + /* need to allocate and prepare input buffer */ + if ((G.inbuf = (uch *)malloc(INBUFSIZ)) == (uch *)NULL) + err(1, "out of memory"); +#endif /* USE_ZLIB */ + if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) { + if (r == 3) + err(1, "out of memory"); + else + err(4, "invalid compressed data--format violated"); + } + inflate_free(__G); + } + else + { /* stored entry */ + register ulg n; + + n = LG(h + LOCLEN); +#if CRYPT + if (n != LG(h + LOCSIZ) - (encrypted ? RAND_HEAD_LEN : 0)) { +#else + if (n != LG(h + LOCSIZ)) { +#endif + Info(slide, 1, ((char *)slide, "len %ld, siz %ld\n", n, LG(h + LOCSIZ))); + err(4, "invalid compressed data--length mismatch"); + } + while (n--) { + ush c = getc(G.in); +#if CRYPT + if (encrypted) + zdecode(c); +#endif + *G.outptr++ = (uch)c; +#if (defined(USE_DEFLATE64) && defined(__16BIT__)) + if (++G.outcnt == (WSIZE>>1)) /* do FlushOutput() */ +#else + if (++G.outcnt == WSIZE) /* do FlushOutput() */ +#endif + { + G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt); + if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt + && !PIPE_ERROR) + err(9, "out of space on stdout"); + outsiz += G.outcnt; + G.outptr = slide; + G.outcnt = 0L; + } + } + } + if (G.outcnt) /* flush one last time; no need to reset G.outptr/outcnt */ + { + G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt); + if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt + && !PIPE_ERROR) + err(9, "out of space on stdout"); + outsiz += G.outcnt; + } + fflush(out); + + /* if extended header, get it */ + if (g) + { + if (fread((char *)h + LOCCRC, 1, 8, G.in) != 8) + err(3, "gzip file ended prematurely"); + } + else + if ((h[LOCFLG] & EXTFLG) && + fread((char *)h + LOCCRC - 4, 1, EXTHDR, G.in) != EXTHDR) + err(3, "zipfile ended prematurely"); + + /* validate decompression */ + if (LG(h + LOCCRC) != G.crc32val) + err(4, "invalid compressed data--crc error"); + if (LG((g ? (h + LOCSIZ) : (h + LOCLEN))) != outsiz) + err(4, "invalid compressed data--length error"); + + /* check if there are more entries */ + if (!g && fread((char *)h, 1, 4, G.in) == 4 && LG(h) == LOCSIG) + Info(slide, 1, ((char *)slide, + "funzip warning: zipfile has more than one entry--rest ignored\n")); + + DESTROYGLOBALS(); + RETURN (0); +} diff --git a/funzip.txt b/funzip.txt new file mode 100644 index 0000000..0ce9120 --- /dev/null +++ b/funzip.txt @@ -0,0 +1,92 @@ +FUNZIP(1L) FUNZIP(1L) + +NAME + funzip - filter for extracting from a ZIP archive in a pipe + +SYNOPSIS + funzip [-password] [input[.zip|.gz]] + +ARGUMENTS + [-password] + Optional password to be used if ZIP archive is encrypted. + Decryption may not be supported at some sites. See DESCRIPTION + for more details. + + [input[.zip|.gz]] + Optional input archive file specification. See DESCRIPTION for + details. + +DESCRIPTION + funzip without a file argument acts as a filter; that is, it assumes + that a ZIP archive (or a gzip'd(1) file) is being piped into standard + input, and it extracts the first member from the archive to stdout. + When stdin comes from a tty device, funzip assumes that this cannot be + a stream of (binary) compressed data and shows a short help text, + instead. If there is a file argument, then input is read from the + specified file instead of from stdin. + + A password for encrypted zip files can be specified on the command line + (preceding the file name, if any) by prefixing the password with a + dash. Note that this constitutes a security risk on many systems; cur- + rently running processes are often visible via simple commands (e.g., + ps(1) under Unix), and command-line histories can be read. If the + first entry of the zip file is encrypted and no password is specified + on the command line, then the user is prompted for a password and the + password is not echoed on the console. + + Given the limitation on single-member extraction, funzip is most useful + in conjunction with a secondary archiver program such as tar(1). The + following section includes an example illustrating this usage in the + case of disk backups to tape. + +EXAMPLES + To use funzip to extract the first member file of the archive test.zip + and to pipe it into more(1): + + funzip test.zip | more + + To use funzip to test the first member file of test.zip (any errors + will be reported on standard error): + + funzip test.zip > /dev/null + + To use zip and funzip in place of compress(1) and zcat(1) (or gzip(1L) + and gzcat(1L)) for tape backups: + + tar cf - . | zip -7 | dd of=/dev/nrst0 obs=8k + dd if=/dev/nrst0 ibs=8k | funzip | tar xf - + + (where, for example, nrst0 is a SCSI tape drive). + +BUGS + When piping an encrypted file into more and allowing funzip to prompt + for password, the terminal may sometimes be reset to a non-echo mode. + This is apparently due to a race condition between the two programs; + funzip changes the terminal mode to non-echo before more reads its + state, and more then ``restores'' the terminal to this mode before + exiting. To recover, run funzip on the same file but redirect to + /dev/null rather than piping into more; after prompting again for the + password, funzip will reset the terminal properly. + + There is presently no way to extract any member but the first from a + ZIP archive. This would be useful in the case where a ZIP archive is + included within another archive. In the case where the first member is + a directory, funzip simply creates the directory and exits. + + The functionality of funzip should be incorporated into unzip itself + (future release). + +SEE ALSO + gzip(1L), unzip(1L), unzipsfx(1L), zip(1L), zipcloak(1L), zipinfo(1L), + zipnote(1L), zipsplit(1L) + +URL + The Info-ZIP home page is currently at + http://www.info-zip.org/pub/infozip/ + or + ftp://ftp.info-zip.org/pub/infozip/ . + +AUTHOR + Mark Adler (Info-ZIP) + +Info-ZIP 20 April 2009 (v3.95) FUNZIP(1L) diff --git a/gbloffs.c b/gbloffs.c new file mode 100644 index 0000000..1529f9c --- /dev/null +++ b/gbloffs.c @@ -0,0 +1,104 @@ +/* + 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 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 +*/ +/* Write out a fragment of assembly or C preprocessor source giving offsets + * in "Uz_Globs" and "struct huft". Used by Amiga and Human68k ports. + */ + +#define UNZIP_INTERNAL +#include "unzip.h" +#include "crypt.h" + +#ifndef REENTRANT + Uz_Globs G; +#endif + +static int asm_setflag(const char *flagname); +static int ccp_setflag(const char *flagname); + +static int asm_setflag(const char *flagname) +{ + static const char asm_flagdef[] = " IFND %s\n%-15s EQU 1\n ENDC\n"; + return printf(asm_flagdef, flagname, flagname); +} +static int ccp_setflag(const char *flagname) +{ + static const char ccp_flagdef[] = "#ifndef %s\n# define %s\n#endif\n"; + return printf(ccp_flagdef, flagname, flagname); +} + +int main(argc, argv) + int argc; + char **argv; +{ +#ifdef REENTRANT + Uz_Globs *pG = NULL; +#endif + struct huft *t = NULL; + static const char asm_offsdef[] = "%-15s EQU %lu\n"; + static const char ccp_offsdef[] = "#define %-15s %lu\n"; + + const char *out_format; + int (*set_flag)(const char *flagname); + int ccp_select = 0; + + if (argc > 1 && argv[1] != NULL && !strcmp(argv[1], "-ccp")) + ccp_select = 1; + + if (ccp_select) { + out_format = ccp_offsdef; + set_flag = ccp_setflag; + } else { + out_format = asm_offsdef; + set_flag = asm_setflag; + } + + printf(out_format, "h_e", (ulg)&t->e - (ulg)t); + printf(out_format, "h_b", (ulg)&t->b - (ulg)t); + printf(out_format, "h_v_n", (ulg)&t->v.n - (ulg)t); + printf(out_format, "h_v_t", (ulg)&t->v.t - (ulg)t); + printf(out_format, "SIZEOF_huft", (ulg)sizeof(struct huft)); + + printf(out_format, "bb", (ulg)&G.bb - (ulg)&G); + printf(out_format, "bk", (ulg)&G.bk - (ulg)&G); + printf(out_format, "wp", (ulg)&G.wp - (ulg)&G); +#ifdef FUNZIP + printf(out_format, "in", (ulg)&G.in - (ulg)&G); +#else + printf(out_format, "incnt", (ulg)&G.incnt - (ulg)&G); + printf(out_format, "inptr", (ulg)&G.inptr - (ulg)&G); + printf(out_format, "csize", (ulg)&G.csize - (ulg)&G); + printf(out_format, "mem_mode", (ulg)&G.mem_mode - (ulg)&G); +#endif + printf(out_format, "redirslide", (ulg)&redirSlide - (ulg)&G); + printf(out_format, "SIZEOF_slide", (ulg)sizeof(redirSlide)); +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + printf(out_format, "_wsize", (ulg)&G._wsize - (ulg)&G); +#endif /* DLL && !NO_SLIDE_REDIR */ + printf(out_format, "CRYPT", (ulg)CRYPT); +#ifdef FUNZIP + (*set_flag)("FUNZIP"); +#endif +#ifdef SFX + (*set_flag)("SFX"); +#endif +#ifdef REENTRANT + (*set_flag)("REENTRANT"); +#endif +#ifdef DLL + (*set_flag)("DLL"); +# ifdef NO_SLIDE_REDIR + (*set_flag)("NO_SLIDE_REDIR"); +# endif +#endif +#ifdef USE_DEFLATE64 + (*set_flag)("USE_DEFLATE64"); +#endif + + return 0; +} diff --git a/globals.c b/globals.c new file mode 100644 index 0000000..fa8cca5 --- /dev/null +++ b/globals.c @@ -0,0 +1,222 @@ +/* + Copyright (c) 1990-2007 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2003-May-08 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 +*/ +/*--------------------------------------------------------------------------- + + globals.c + + Routines to allocate and initialize globals, with or without threads. + + Contents: registerGlobalPointer() + deregisterGlobalPointer() + getGlobalPointer() + globalsCtor() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" + +#ifndef FUNZIP +/* initialization of sigs is completed at runtime so unzip(sfx) executable + * won't look like a zipfile + */ +char central_hdr_sig[4] = {0, 0, 0x01, 0x02}; +char local_hdr_sig[4] = {0, 0, 0x03, 0x04}; +char end_central_sig[4] = {0, 0, 0x05, 0x06}; +char end_central64_sig[4] = {0, 0, 0x06, 0x06}; +char end_centloc64_sig[4] = {0, 0, 0x06, 0x07}; +/* extern char extd_local_sig[4] = {0, 0, 0x07, 0x08}; NOT USED YET */ + +ZCONST char *fnames[2] = {"*", NULL}; /* default filenames vector */ +#endif + + +#ifndef REENTRANT + Uz_Globs G; +#else /* REENTRANT */ + +# ifndef USETHREADID + Uz_Globs *GG; +# else /* USETHREADID */ +# define THREADID_ENTRIES 0x40 + + int lastScan; + Uz_Globs *threadPtrTable[THREADID_ENTRIES]; + ulg threadIdTable [THREADID_ENTRIES] = { + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* Make sure there are */ + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* THREADID_ENTRIES 0s */ + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 + }; + + static ZCONST char Far TooManyThreads[] = + "error: more than %d simultaneous threads.\n\ + Some threads are probably not calling DESTROYTHREAD()\n"; + static ZCONST char Far EntryNotFound[] = + "error: couldn't find global pointer in table.\n\ + Maybe somebody accidentally called DESTROYTHREAD() twice.\n"; + static ZCONST char Far GlobalPointerMismatch[] = + "error: global pointer in table does not match pointer passed as\ + parameter\n"; + +static void registerGlobalPointer OF((__GPRO)); + + + +static void registerGlobalPointer(__G) + __GDEF +{ + int scan=0; + ulg tid = GetThreadId(); + + while (threadIdTable[scan] && scan < THREADID_ENTRIES) + scan++; + + if (scan == THREADID_ENTRIES) { + ZCONST char *tooMany = LoadFarString(TooManyThreads); + Info(slide, 0x421, ((char *)slide, tooMany, THREADID_ENTRIES)); + free(pG); + EXIT(PK_MEM); /* essentially memory error before we've started */ + } + + threadIdTable [scan] = tid; + threadPtrTable[scan] = pG; + lastScan = scan; +} + + + +void deregisterGlobalPointer(__G) + __GDEF +{ + int scan=0; + ulg tid = GetThreadId(); + + + while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES) + scan++; + +/*--------------------------------------------------------------------------- + There are two things we can do if we can't find the entry: ignore it or + scream. The most likely reason for it not to be here is the user calling + this routine twice. Since this could cause BIG problems if any globals + are accessed after the first call, we'd better scream. + ---------------------------------------------------------------------------*/ + + if (scan == THREADID_ENTRIES || threadPtrTable[scan] != pG) { + ZCONST char *noEntry; + if (scan == THREADID_ENTRIES) + noEntry = LoadFarString(EntryNotFound); + else + noEntry = LoadFarString(GlobalPointerMismatch); + Info(slide, 0x421, ((char *)slide, noEntry)); + EXIT(PK_WARN); /* programming error, but after we're all done */ + } + + threadIdTable [scan] = 0; + lastScan = scan; + free(threadPtrTable[scan]); +} + + + +Uz_Globs *getGlobalPointer() +{ + int scan=0; + ulg tid = GetThreadId(); + + while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES) + scan++; + +/*--------------------------------------------------------------------------- + There are two things we can do if we can't find the entry: ignore it or + scream. The most likely reason for it not to be here is the user calling + this routine twice. Since this could cause BIG problems if any globals + are accessed after the first call, we'd better scream. + ---------------------------------------------------------------------------*/ + + if (scan == THREADID_ENTRIES) { + ZCONST char *noEntry = LoadFarString(EntryNotFound); + fprintf(stderr, noEntry); /* can't use Info w/o a global pointer */ + EXIT(PK_ERR); /* programming error while still working */ + } + + return threadPtrTable[scan]; +} + +# endif /* ?USETHREADID */ +#endif /* ?REENTRANT */ + + + +Uz_Globs *globalsCtor() +{ +#ifdef REENTRANT + Uz_Globs *pG = (Uz_Globs *)malloc(sizeof(Uz_Globs)); + + if (!pG) + return (Uz_Globs *)NULL; +#endif /* REENTRANT */ + + /* for REENTRANT version, G is defined as (*pG) */ + + memzero(&G, sizeof(Uz_Globs)); + +#ifndef FUNZIP +#ifdef CMS_MVS + uO.aflag=1; + uO.C_flag=1; +#endif +#ifdef TANDEM + uO.aflag=1; /* default to '-a' auto create Text Files as type 101 */ +#endif +#ifdef VMS +# if (!defined(NO_TIMESTAMPS)) + uO.D_flag=1; /* default to '-D', no restoration of dir timestamps */ +# endif +#endif + + uO.lflag=(-1); + G.wildzipfn = ""; + G.pfnames = (char **)fnames; + G.pxnames = (char **)&fnames[1]; + G.pInfo = G.info; + G.sol = TRUE; /* at start of line */ + + G.message = UzpMessagePrnt; + G.input = UzpInput; /* not used by anyone at the moment... */ +#if defined(WINDLL) || defined(MACOS) + G.mpause = NULL; /* has scrollbars: no need for pausing */ +#else + G.mpause = UzpMorePause; +#endif + G.decr_passwd = UzpPassword; +#endif /* !FUNZIP */ + +#if (!defined(DOS_FLX_H68_NLM_OS2_W32) && !defined(AMIGA) && !defined(RISCOS)) +#if (!defined(MACOS) && !defined(ATARI) && !defined(VMS)) + G.echofd = -1; +#endif /* !(MACOS || ATARI || VMS) */ +#endif /* !(DOS_FLX_H68_NLM_OS2_W32 || AMIGA || RISCOS) */ + +#ifdef SYSTEM_SPECIFIC_CTOR + SYSTEM_SPECIFIC_CTOR(__G); +#endif + +#ifdef REENTRANT +#ifdef USETHREADID + registerGlobalPointer(__G); +#else + GG = &G; +#endif /* ?USETHREADID */ +#endif /* REENTRANT */ + + return &G; +} diff --git a/globals.h b/globals.h new file mode 100644 index 0000000..11b7215 --- /dev/null +++ b/globals.h @@ -0,0 +1,443 @@ +/* + Copyright (c) 1990-2009 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2009-Jan-02 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 +*/ +/*--------------------------------------------------------------------------- + + globals.h + + There is usually no need to include this file since unzip.h includes it. + + This header file is used by all of the UnZip source files. It contains + a struct definition that is used to "house" all of the global variables. + This is done to allow for multithreaded environments (OS/2, NT, Win95, + Unix) to call UnZip through an API without a semaphore. REENTRANT should + be defined for all platforms that require this. + + GLOBAL CONSTRUCTOR AND DESTRUCTOR (API WRITERS READ THIS!!!) + ------------------------------------------------------------ + + No, it's not C++, but it's as close as we can get with K&R. + + The main() of each process that uses these globals must include the + CONSTRUCTGLOBALS; statement. This will malloc enough memory for the + structure and initialize any variables that require it. This must + also be done by any API function that jumps into the middle of the + code. + + The DESTROYGLOBALS(); statement should be inserted before EVERY "EXIT(n)". + Naturally, it also needs to be put before any API returns as well. + In fact, it's much more important in API functions since the process + will NOT end, and therefore the memory WON'T automatically be freed + by the operating system. + + USING VARIABLES FROM THE STRUCTURE + ---------------------------------- + + All global variables must now be prefixed with `G.' which is either a + global struct (in which case it should be the only global variable) or + a macro for the value of a local pointer variable that is passed from + function to function. Yes, this is a pain. But it's the only way to + allow full reentrancy. + + ADDING VARIABLES TO THE STRUCTURE + --------------------------------- + + If you make the inclusion of any variables conditional, be sure to only + check macros that are GUARANTEED to be included in every module. + For instance, newzip and pwdarg are needed only if CRYPT is TRUE, + but this is defined after unzip.h has been read. If you are not careful, + some modules will expect your variable to be part of this struct while + others won't. This will cause BIG problems. (Inexplicable crashes at + strange times, car fires, etc.) When in doubt, always include it! + + Note also that UnZipSFX needs a few variables that UnZip doesn't. However, + it also includes some object files from UnZip. If we were to conditionally + include the extra variables that UnZipSFX needs, the object files from + UnZip would not mesh with the UnZipSFX object files. Result: we just + include the UnZipSFX variables every time. (It's only an extra 4 bytes + so who cares!) + + ADDING FUNCTIONS + ---------------- + + To support this new global struct, all functions must now conditionally + pass the globals pointer (pG) to each other. This is supported by 5 macros: + __GPRO, __GPRO__, __G, __G__ and __GDEF. A function that needs no other + parameters would look like this: + + int extract_or_test_files(__G) + __GDEF + { + ... stuff ... + } + + A function with other parameters would look like: + + int memextract(__G__ tgt, tgtsize, src, srcsize) + __GDEF + uch *tgt, *src; + ulg tgtsize, srcsize; + { + ... stuff ... + } + + In the Function Prototypes section of unzpriv.h, you should use __GPRO and + __GPRO__ instead: + + int uz_opts OF((__GPRO__ int *pargc, char ***pargv)); + int process_zipfiles OF((__GPRO)); + + Note that there is NO comma after __G__ or __GPRO__ and no semi-colon after + __GDEF. I wish there was another way but I don't think there is. + + + TESTING THE CODE + ----------------- + + Whether your platform requires reentrancy or not, you should always try + building with REENTRANT defined if any functions have been added. It is + pretty easy to forget a __G__ or a __GDEF and this mistake will only show + up if REENTRANT is defined. All platforms should run with REENTRANT + defined. Platforms that can't take advantage of it will just be paying + a performance penalty needlessly. + + SIGNAL MADNESS + -------------- + + This whole pointer passing scheme falls apart when it comes to SIGNALs. + I handle this situation 2 ways right now. If you define USETHREADID, + UnZip will include a 64-entry table. Each entry can hold a global + pointer and thread ID for one thread. This should allow up to 64 + threads to access UnZip simultaneously. Calling DESTROYGLOBALS() + will free the global struct and zero the table entry. If somebody + forgets to call DESTROYGLOBALS(), this table will eventually fill up + and UnZip will exit with an error message. A good way to test your + code to make sure you didn't forget a DESTROYGLOBALS() is to change + THREADID_ENTRIES to 3 or 4 in globals.c, making the table real small. + Then make a small test program that calls your API a dozen times. + + Those platforms that don't have threads still need to be able to compile + with REENTRANT defined to test and see if new code is correctly written + to work either way. For these platforms, I simply keep a global pointer + called GG that points to the Globals structure. Good enough for testing. + + I believe that NT has thread level storage. This could probably be used + to store a global pointer for the sake of the signal handler more cleanly + than my table approach. + + ---------------------------------------------------------------------------*/ + +#ifndef __globals_h +#define __globals_h + +#ifdef USE_ZLIB +# include "zlib.h" +# ifdef zlib_version /* This name is used internally in unzip */ +# undef zlib_version /* and must not be defined as a macro. */ +# endif +#endif + +#ifdef USE_BZIP2 +# include "bzlib.h" +#endif + + +/*************/ +/* Globals */ +/*************/ + +typedef struct Globals { +#ifdef DLL + zvoid *callerglobs; /* pointer to structure of pass-through global vars */ +#endif + + /* command options of general use */ + UzpOpts UzO; /* command options of general use */ + +#ifndef FUNZIP + /* command options specific to the high level command line interface */ +#ifdef MORE + int M_flag; /* -M: built-in "more" function */ +#endif + + /* internal flags and general globals */ +#ifdef MORE + int height; /* check for SIGWINCH, etc., eventually... */ + int lines; /* count of lines displayed on current screen */ +# if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) + int width; + int chars; /* count of screen characters in current line */ +# endif +#endif /* MORE */ +#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME)) + int tz_is_valid; /* indicates that timezone info can be used */ +#endif + int noargs; /* did true command line have *any* arguments? */ + unsigned filespecs; /* number of real file specifications to be matched */ + unsigned xfilespecs; /* number of excluded filespecs to be matched */ + int process_all_files; + int overwrite_mode; /* 0 - query, 1 - always, 2 - never */ + int create_dirs; /* used by main(), mapname(), checkdir() */ + int extract_flag; + int newzip; /* reset in extract.c; used in crypt.c */ + zoff_t real_ecrec_offset; + zoff_t expect_ecrec_offset; + zoff_t csize; /* used by decompr. (NEXTBYTE): must be signed */ + zoff_t used_csize; /* used by extract_or_test_member(), explode() */ + +#ifdef DLL + int fValidate; /* true if only validating an archive */ + int filenotfound; + int redirect_data; /* redirect data to memory buffer */ + int redirect_text; /* redirect text output to buffer */ +# ifndef NO_SLIDE_REDIR + int redirect_slide; /* redirect decompression area to mem buffer */ +# if (defined(USE_DEFLATE64) && defined(INT_16BIT)) + ulg _wsize; /* size of sliding window exceeds "unsigned" range */ +# else + unsigned _wsize; /* sliding window size can be hold in unsigned */ +# endif +# endif + ulg redirect_size; /* size of redirected output buffer */ + uch *redirect_buffer; /* pointer to head of allocated buffer */ + uch *redirect_pointer; /* pointer past end of written data */ +# ifndef NO_SLIDE_REDIR + uch *redirect_sldptr; /* head of decompression slide buffer */ +# endif +# ifdef OS2DLL + cbList(processExternally); /* call-back list */ +# endif +#endif /* DLL */ + + char **pfnames; + char **pxnames; + char sig[4]; + char answerbuf[10]; + min_info info[DIR_BLKSIZ]; + min_info *pInfo; +#endif /* !FUNZIP */ + union work area; /* see unzpriv.h for definition of work */ + +#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) + ZCONST ulg near *crc_32_tab; +#else + ZCONST ulg Far *crc_32_tab; +#endif + ulg crc32val; /* CRC shift reg. (was static in funzip) */ + +#ifdef FUNZIP + FILE *in; /* file descriptor of compressed stream */ +#endif + uch *inbuf; /* input buffer (any size is OK) */ + uch *inptr; /* pointer into input buffer */ + int incnt; + +#ifndef FUNZIP + ulg bitbuf; + int bits_left; /* unreduce and unshrink only */ + int zipeof; + char *argv0; /* used for NT and EXE_EXTENSION */ + char *wildzipfn; + char *zipfn; /* GRR: WINDLL: must nuke any malloc'd zipfn... */ +#ifdef USE_STRM_INPUT + FILE *zipfd; /* zipfile file descriptor */ +#else + int zipfd; /* zipfile file handle */ +#endif + zoff_t ziplen; + zoff_t cur_zipfile_bufstart; /* extract_or_test, readbuf, ReadByte */ + zoff_t extra_bytes; /* used in unzip.c, misc.c */ + uch *extra_field; /* Unix, VMS, Mac, OS/2, Acorn, ... */ + uch *hold; + + local_file_hdr lrec; /* used in unzip.c, extract.c */ + cdir_file_hdr crec; /* used in unzip.c, extract.c, misc.c */ + ecdir_rec ecrec; /* used in unzip.c, extract.c */ + z_stat statbuf; /* used by main, mapname, check_for_newer */ + + int mem_mode; + uch *outbufptr; /* extract.c static */ + ulg outsize; /* extract.c static */ + int reported_backslash; /* extract.c static */ + int disk_full; + int newfile; + + int didCRlast; /* fileio static */ + ulg numlines; /* fileio static: number of lines printed */ + int sol; /* fileio static: at start of line */ + int no_ecrec; /* process static */ +#ifdef SYMLINKS + int symlnk; + slinkentry *slink_head; /* pointer to head of symlinks list */ + slinkentry *slink_last; /* pointer to last entry in symlinks list */ +#endif +#ifdef NOVELL_BUG_FAILSAFE + int dne; /* true if stat() says file doesn't exist */ +#endif + + FILE *outfile; + uch *outbuf; + uch *realbuf; + +#ifndef VMS /* if SMALL_MEM, outbuf2 is initialized in */ + uch *outbuf2; /* process_zipfiles() (never changes); */ +#endif /* else malloc'd ONLY if unshrink and -a */ +#endif /* !FUNZIP */ + uch *outptr; + ulg outcnt; /* number of chars stored in outbuf */ +#ifndef FUNZIP + char filename[FILNAMSIZ]; /* also used by NT for temporary SFX path */ +#ifdef UNICODE_SUPPORT + char *filename_full; /* the full path so Unicode checks work */ + extent fnfull_bufsize; /* size of allocated filename buffer */ + int unicode_escape_all; + int unicode_mismatch; +#ifdef UTF8_MAYBE_NATIVE + int native_is_utf8; /* bool, TRUE => native charset == UTF-8 */ +#endif + + int unipath_version; /* version of Unicode field */ + ulg unipath_checksum; /* Unicode field checksum */ + char *unipath_filename; /* UTF-8 path */ +#endif /* UNICODE_SUPPORT */ + +#ifdef CMS_MVS + char *tempfn; /* temp file used; erase on close */ +#endif + + char *key; /* crypt static: decryption password or NULL */ + int nopwd; /* crypt static */ +#endif /* !FUNZIP */ + z_uint4 keys[3]; /* crypt static: keys defining pseudo-random sequence */ + +#if (!defined(DOS_FLX_H68_NLM_OS2_W32) && !defined(AMIGA) && !defined(RISCOS)) +#if (!defined(MACOS) && !defined(ATARI) && !defined(VMS)) + int echofd; /* ttyio static: file descriptor whose echo is off */ +#endif /* !(MACOS || ATARI || VMS) */ +#endif /* !(DOS_FLX_H68_NLM_OS2_W32 || AMIGA || RISCOS) */ + + unsigned hufts; /* track memory usage */ + +#ifdef USE_ZLIB + int inflInit; /* inflate static: zlib inflate() initialized */ + z_stream dstrm; /* inflate global: decompression stream */ +#else + struct huft *fixed_tl; /* inflate static */ + struct huft *fixed_td; /* inflate static */ + unsigned fixed_bl, fixed_bd; /* inflate static */ +#ifdef USE_DEFLATE64 + struct huft *fixed_tl64; /* inflate static */ + struct huft *fixed_td64; /* inflate static */ + unsigned fixed_bl64, fixed_bd64; /* inflate static */ + struct huft *fixed_tl32; /* inflate static */ + struct huft *fixed_td32; /* inflate static */ + unsigned fixed_bl32, fixed_bd32; /* inflate static */ + ZCONST ush *cplens; /* inflate static */ + ZCONST uch *cplext; /* inflate static */ + ZCONST uch *cpdext; /* inflate static */ +#endif + unsigned wp; /* inflate static: current position in slide */ + ulg bb; /* inflate static: bit buffer */ + unsigned bk; /* inflate static: bits count in bit buffer */ +#endif /* ?USE_ZLIB */ + +#ifndef FUNZIP + /* cylindric buffer space for formatting zoff_t values (fileio static) */ + char fzofft_buf[FZOFFT_NUM][FZOFFT_LEN]; + int fzofft_index; + +#ifdef SMALL_MEM + char rgchBigBuffer[512]; + char rgchSmallBuffer[96]; + char rgchSmallBuffer2[160]; /* boosted to 160 for local3[] in unzip.c */ +#endif + + MsgFn *message; + InputFn *input; + PauseFn *mpause; + PasswdFn *decr_passwd; + StatCBFn *statreportcb; +#ifdef WINDLL + LPUSERFUNCTIONS lpUserFunctions; +#endif + + int incnt_leftover; /* so improved NEXTBYTE does not waste input */ + uch *inptr_leftover; + +#ifdef VMS_TEXT_CONV + unsigned VMS_line_length; /* so native VMS variable-length text files */ + int VMS_line_state; /* are readable on other platforms */ + int VMS_line_pad; +#endif + +#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) + char autorun_command[FILNAMSIZ]; +#endif +#endif /* !FUNZIP */ + +#ifdef SYSTEM_SPECIFIC_GLOBALS + SYSTEM_SPECIFIC_GLOBALS +#endif + +} Uz_Globs; /* end of struct Globals */ + + +/***************************************************************************/ + + +#define CRC_32_TAB G.crc_32_tab + + +Uz_Globs *globalsCtor OF((void)); + +/* pseudo constant sigs; they are initialized at runtime so unzip executable + * won't look like a zipfile + */ +extern char local_hdr_sig[4]; +extern char central_hdr_sig[4]; +extern char end_central_sig[4]; +extern char end_central32_sig[4]; +extern char end_central64_sig[4]; +extern char end_centloc64_sig[4]; +/* extern char extd_local_sig[4]; NOT USED YET */ + +#ifdef REENTRANT +# define G (*(Uz_Globs *)pG) +# define __G pG +# define __G__ pG, +# define __GPRO Uz_Globs *pG +# define __GPRO__ Uz_Globs *pG, +# define __GDEF Uz_Globs *pG; +# ifdef USETHREADID + extern int lastScan; + void deregisterGlobalPointer OF((__GPRO)); + Uz_Globs *getGlobalPointer OF((void)); +# define GETGLOBALS() Uz_Globs *pG = getGlobalPointer() +# define DESTROYGLOBALS() do {free_G_buffers(pG); \ + deregisterGlobalPointer(pG);} while (0) +# else + extern Uz_Globs *GG; +# define GETGLOBALS() Uz_Globs *pG = GG +# define DESTROYGLOBALS() do {free_G_buffers(pG); free(pG);} while (0) +# endif /* ?USETHREADID */ +# define CONSTRUCTGLOBALS() Uz_Globs *pG = globalsCtor() +#else /* !REENTRANT */ + extern Uz_Globs G; +# define __G +# define __G__ +# define __GPRO void +# define __GPRO__ +# define __GDEF +# define GETGLOBALS() +# define CONSTRUCTGLOBALS() globalsCtor() +# define DESTROYGLOBALS() +#endif /* ?REENTRANT */ + +#define uO G.UzO + +#endif /* __globals_h */ diff --git a/human68k/Contents b/human68k/Contents new file mode 100644 index 0000000..9b39c02 --- /dev/null +++ b/human68k/Contents @@ -0,0 +1,7 @@ +Contents of the "human68k" sub-archive for UnZip 5.50 and later: + + Contents this file + Makefile (shorter) Makefile for GNU C on X680x0/Human68k + human68k.c Human68k-specific routines for UnZip + crc_68.s assembler version of crc32.c + flate.s assembler version of inflate_codes() (define ASM_INFLATECODES) diff --git a/human68k/Makefile b/human68k/Makefile new file mode 100644 index 0000000..624b604 --- /dev/null +++ b/human68k/Makefile @@ -0,0 +1,229 @@ +# Makefile for UnZip 5.53 and later: Human68k with gcc NIIMI Satoshi +# +# The original Makefile maybe works fine, but X680x0 is too slow +# to process it. So I split out needed part. +# +# Last revised: 25 Dec 06 +# +# 1999/09/23: Modified by Shimazaki Ryo. + +ifeq "$(TARGET)" "X68030" +COPT = -m68020-40 +AOPT = -m68020 +LDFLAGS = -L/usr/local/lib/lib060 +endif + +CC = gcc2 +CFLAGS = $(COPT) -Wall -O2 -I. -fomit-frame-pointer -fstrength-reduce \ + -DHAVE_TWONCALL_H -D__DOS_INLINE__ -DASM_CRC -DASM_INFLATECODES +#LDFLAGS = -Wl,-x +LIBS = -lhmem -lttyi -lsignal + +AS = g2as +ASFLAGS = $(AOPT) -1 -c4 -y + +# UnZipSFX flags +XC = -DSFX + +# fUnZip flags +FC = -DFUNZIP + +# object files +OBJS = unzip.o crc32.o crc_68.o crypt.o envargs.o explode.o extract.o \ + fileio.o globals.o inflate.o flate.o list.o match.o process.o \ + ttyio.o ubz2err.o unreduce.o unshrink.o zipinfo.o human68k.o +OBJX = unzipsfx.o crc32_.o crc_68.o crypt_.o extract_.o fileio_.o globals_.o \ + inflate_.o flate_.o match_.o process_.o ttyio_.o ubz2err_.o human68k_.o +OBJF = funzip.o crc32f.o crc_68.o cryptf.o globalsf.o inflatef.o flatef.o \ + ttyiof.o + +UNZIP_H = unzip.h unzpriv.h globals.h + +UNZIPS = unzip.x unzipsfx.x funzip.x +DOCS = unzip.txt unzipsfx.txt zipinfo.txt funzip.txt + +.c.o: + $(CC) $(CFLAGS) -I. -c $< -o $@ + +# for debugging +.c.s: + $(CC) $(CFLAGS) -c $< -o $@ + +all: unzips +unzips: $(UNZIPS) +docs: $(DOCS) +unzipsman: unzips docs +unzipsdocs: unzips docs + +clean: + rm -f $(OBJS) $(OBJF) $(OBJX) $(UNZIPS) + +unzip.x: $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +unzipsfx.x: $(OBJX) + $(CC) $(LDFLAGS) -o $@ $(OBJX) $(LIBS) + +funzip.x: $(OBJF) + $(CC) $(LDFLAGS) -o $@ $(OBJF) $(LIBS) + +crc32.o: crc32.c $(UNZIP_H) zip.h crc32.h +crypt.o: crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h +envargs.o: envargs.c $(UNZIP_H) +explode.o: explode.c $(UNZIP_H) +extract.o: extract.c $(UNZIP_H) crc32.h crypt.h +fileio.o: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +funzip.o: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.hh +globals.o: globals.c $(UNZIP_H) +inflate.o: inflate.c inflate.h $(UNZIP_H) +list.o: list.c $(UNZIP_H) +match.o: match.c $(UNZIP_H) +process.o: process.c $(UNZIP_H) crc32.h +ttyio.o: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ubz2err.o: ubz2err.c $(UNZIP_H) +unreduce.o: unreduce.c $(UNZIP_H) +unshrink.o: unshrink.c $(UNZIP_H) +unzip.o: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +zipinfo.o: zipinfo.c $(UNZIP_H) + + +# unzipsfx +crc32_.o: crc32.c $(UNZIP_H) zip.h crc32.h + $(CC) $(CFLAGS) $(XC) -c $< -o $@ + +crypt_.o: crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CC) $(CFLAGS) $(XC) -c $< -o $@ + +extract_.o: extract.c $(UNZIP_H) crc32.h crypt.h + $(CC) $(CFLAGS) $(XC) -c $< -o $@ + +fileio_.o: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h + $(CC) $(CFLAGS) $(XC) -c $< -o $@ + +globals_.o: globals.c $(UNZIP_H) + $(CC) $(CFLAGS) $(XC) -c $< -o $@ + +inflate_.o: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CC) $(CFLAGS) $(XC) -c $< -o $@ + +match_.o: match.c $(UNZIP_H) + $(CC) $(CFLAGS) $(XC) -c $< -o $@ + +process_.o: process.c $(UNZIP_H) crc32.h + $(CC) $(CFLAGS) $(XC) -c $< -o $@ + +ttyio_.o: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CC) $(CFLAGS) $(XC) -c $< -o $@ + +ubz2err_.o: ubz2err.c $(UNZIP_H) + $(CC) $(CFLAGS) $(XC) -c $< -o $@ + +unzipsfx.o: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h + $(CC) $(CFLAGS) $(XC) -c $< -o $@ + + +# funzip +crc32f.o: crc32.c $(UNZIP_H) zip.h crc32.h + $(CC) $(CFLAGS) $(FC) -c $< -o $@ + +cryptf.o: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CC) $(CFLAGS) $(FC) -c $< -o $@ + +globalsf.o: globals.c $(UNZIP_H) + $(CC) $(CFLAGS) $(FC) -c $< -o $@ + +inflatef.o: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CC) $(CFLAGS) $(FC) -c $< -o $@ + +ttyiof.o: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CC) $(CFLAGS) $(FC) -c $< -o $@ + + +human68k.o: human68k/human68k.c $(UNZIP_H) + $(CC) $(CFLAGS) -I. -c human68k/human68k.c -o $@ + +human68k_.o: human68k/human68k.c $(UNZIP_H) # unzipsfx + $(CC) $(CFLAGS) $(XC) -I. -c human68k/human68k.c -o $@ + +crc_68.o: human68k/crc_68.s + $(AS) $(ASFLAGS) $< -o $@ + +flate.o: human68k/flate.s human68k/g_offs.mac + $(AS) $(ASFLAGS) $< -o $@ + +flate_.o: human68k/flate.s human68k/g_offs_.mac # unzipsfx + $(AS) $(ASFLAGS) $< -o $@ -sSFX + +flatef.o: human68k/flate.s human68k/g_offsf.mac # funzip + $(AS) $(ASFLAGS) $< -o $@ -sFUNZIP + +human68k/g_offs.mac: human68k/gbloffs.x + human68k/mkgoff.x >! $@ + +human68k/g_offs_.mac: human68k/gbloffs_.x # unzipsfx + human68k/mkgoff_.x >! $@ + +human68k/g_offsf.mac: human68k/gbloffsf.x # funzip + human68k/mkgofff.x >! $@ + +human68k/gbloffs.x: gbloffs.c $(UNZIP_H) crypt.h + $(CC) $(CFLAGS) gbloffs.c -o $@ + +human68k/gbloffs_.x: gbloffs.c $(UNZIP_H) crypt.h # unzipsfx + $(CC) $(CFLAGS) gbloffs.c -o $@ $(XC) + +human68k/gbloffsf.x: gbloffs.c $(UNZIP_H) crypt.h # funzip + $(CC) $(CFLAGS) gbloffs.c -o $@ $(FC) + +# the test zipfile +TESTZIP = testmake.zip + +# test some basic features of the build +test: check + +check: unzips + @if test ! -f $(TESTZIP); then \ + echo "##### ERROR: can't find test file $(TESTZIP)"; exit 1; fi +# + @echo "##### testing extraction" + @./unzip -bo $(TESTZIP) testmake.zipinfo + @if test ! -f testmake.zipinfo ; then \ + echo "##### ERROR: file extraction from $(TESTZIP) failed"; \ + exit 1; fi +# + @echo '##### testing zipinfo (unzip -Z)' + @./unzip -Z $(TESTZIP) > testmake.unzip-Z + @if diff testmake.unzip-Z testmake.zipinfo; then echo "OK."; else \ + echo "##### WARNING: zipinfo output doesn't match stored version"; \ + echo '##### (If the only difference is the file times, compare your'; \ + echo '##### timezone with the Central European timezone, which is one'; \ + echo '##### hour east of Greenwich but effectively 2 hours east'; \ + echo '##### during summer Daylight Savings Time. The upper two'; \ + echo '##### lines should correspond to your local time when the'; \ + echo '##### files were created, on 19 November 1998 at 10:46pm CET.'; \ + echo '##### If the times are consistent, please ignore this warning.)'; \ + fi + @rm -f testmake.unzip-Z testmake.zipinfo +# + @echo '##### testing unzip -d exdir option' + @./unzip -bo $(TESTZIP) -d testun notes + @cat testun/notes +# + @echo '##### testing unzip -o and funzip (ignore funzip warning)' + @./unzip -boq $(TESTZIP) notes -d testun + @./funzip < $(TESTZIP) > testun/notes2 + @if diff testun/notes testun/notes2; then true; else \ + echo '##### ERROR: funzip output disagrees with unzip'; fi +# + @echo '##### testing unzipsfx (self-extractor)' + @cat unzipsfx.x $(TESTZIP) > testsfx.x + @chmod 0700 testsfx.x + @./testsfx -bo notes + @if diff notes testun/notes; then true; else \ + echo '##### ERROR: unzipsfx file disagrees with unzip'; fi + @rm -f testsfx.x notes testun/notes testun/notes2 + @rmdir testun +# + @echo '##### testing complete.' + +# EOF diff --git a/human68k/crc_68.s b/human68k/crc_68.s new file mode 100644 index 0000000..9ce78d8 --- /dev/null +++ b/human68k/crc_68.s @@ -0,0 +1,144 @@ +;=========================================================================== +; 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 +;=========================================================================== +; crc_68 created by Paul Kienitz, last modified 04 Jan 96. +; +; Return an updated 32 bit CRC value, given the old value and a block of data. +; The CRC table used to compute the value is gotten by calling get_crc_table(). +; This replaces the older updcrc() function used in Zip and fUnZip. The +; prototype of the function is: +; +; ulg crc32(ulg crcval, uch *text, extent textlen); +; +; On the Amiga, type extent is always unsigned long, not unsigned int, because +; int can be short or long at whim, but size_t is long. +; +; If using this source on a non-Amiga 680x0 system, note that we treat +; a0/a1/d0/d1 as scratch registers not preserved across function calls. +; We do not bother to support registerized arguments for crc32() -- the +; textlen parm is usually large enough so that savings outside the loop +; are pointless. +; +; Define NO_UNROLLED_LOOPS to use a simple short loop which might be more +; efficient on certain machines with dinky instruction caches ('020?), or for +; processing short strings. If loops are unrolled, the textlen parm must be +; less than 512K; if not unrolled, it must be less than 64K. +; +; 1999/09/23: for Human68k: Modified by Shimazaki Ryo. + + xdef _crc32 ; (ulg val, uch *buf, extent bufsize) + +DO_CRC0 MACRO + moveq #0,ltemp + move.b (textbuf)+,ltemp + eor.b crcval,ltemp + lsl.w #2,ltemp + move.l (crc_table,ltemp.w),ltemp + lsr.l #8,crcval + eor.l ltemp,crcval + ENDM + + +DO_CRC2 MACRO + move.b (textbuf)+,btemp + eor.b crcval,btemp + lsr.l #8,crcval + move.l (crc_table,btemp.w*4),ltemp + eor.l ltemp,crcval + ENDM + +crc_table reg a0 array of unsigned long +crcval reg d0 unsigned long initial value +textbuf reg a1 array of unsigned char +textbufsize reg d1 unsigned long (count of bytes in textbuf) +btemp reg d2 +ltemp reg d3 + + + xref _get_crc_table ; ulg *get_crc_table(void) + + + + quad +_crc32: + move.l 8(sp),d0 + bne.s valid +;;;;; moveq #0,d0 + rts +valid: movem.l btemp/ltemp,-(sp) + jsr _get_crc_table + movea.l d0,crc_table + move.l 12(sp),crcval + move.l 16(sp),textbuf + move.l 20(sp),textbufsize + not.l crcval + + ifdef NO_UNROLLED_LOOPS + + if CPU==68000 + bra.s decr +loop: DO_CRC0 +decr: dbra textbufsize,loop + bra.s done + + else +twenty: moveq #0,btemp + bra.s decr2 +loop2: DO_CRC2 +decr2: dbra textbufsize,loop2 + endif + + ELSE ; !NO_UNROLLED_LOOPS + + if CPU==68000 + moveq #7,btemp + and textbufsize,btemp + lsr.l #3,textbufsize + bra decr8 +loop8: DO_CRC0 + DO_CRC0 + DO_CRC0 + DO_CRC0 + DO_CRC0 + DO_CRC0 + DO_CRC0 + DO_CRC0 +decr8: dbra textbufsize,loop8 + bra.s decr1 +loop1: DO_CRC0 +decr1: dbra btemp,loop1 + bra done + + else +twenty: moveq #0,btemp + move.l textbufsize,-(sp) + lsr.l #3,textbufsize + bra decr82 + quad +loop82: DO_CRC2 + DO_CRC2 + DO_CRC2 + DO_CRC2 + DO_CRC2 + DO_CRC2 + DO_CRC2 + DO_CRC2 +decr82: dbra textbufsize,loop82 + moveq #7,textbufsize + and.l (sp)+,textbufsize + bra.s decr12 +loop12: DO_CRC2 +decr12: dbra textbufsize,loop12 + endif + + ENDC ; ?NO_UNROLLED_LOOPS + +done: movem.l (sp)+,btemp/ltemp + not.l crcval +;;;;; move.l crcval,d0 ; crcval already is d0 + rts diff --git a/human68k/flate.s b/human68k/flate.s new file mode 100644 index 0000000..f0aebf7 --- /dev/null +++ b/human68k/flate.s @@ -0,0 +1,499 @@ +;=========================================================================== +; 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 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 +;=========================================================================== +; flate.a created by Paul Kienitz, 20 June 94. Last modified 23 Mar 2002. +; +; 68000 assembly language version of inflate_codes(), for Amiga. Prototype: +; +; int inflate_codes(__GPRO__ struct huft *tl, struct huft *td, +; unsigned bl, unsigned bd); +; +; Where __GPRO__ expands to "Uz_Globs *G," if REENTRANT is defined, +; otherwise to nothing. In the latter case G is a global variable. +; +; Define the symbol FUNZIP if this is for fUnZip. It overrides REENTRANT. +; +; Define AZTEC to use the Aztec C macro version of getc() instead of the +; library getc() with FUNZIP. AZTEC is ignored if FUNZIP is not defined. +; +; Define NO_CHECK_EOF to not use the fancy paranoid version of NEEDBITS -- +; this is equivalent to removing the #define CHECK_EOF from inflate.c. +; +; Define INT16 if ints are short, otherwise it assumes ints are long. +; +; Define USE_DEFLATE64 if we're supporting Deflate64 decompression. +; +; Do NOT define WSIZE; it is always 32K or 64K depending on USE_DEFLATE64. +; +; 1999/09/23: for Human68k: Modified by Shimazaki Ryo. + +X: EQU $7ffe + + IFDEF INT16 +MOVINT MACRO _1,_2 + move.w _1,_2 + ENDM +INTSIZE equ 2 + ELSE ; !INT16 +MOVINT MACRO _1,_2 + move.l _1,_2 + ENDM +INTSIZE equ 4 + ENDC + + IFDEF REENTRANT + IFNDEF FUNZIP +REENT_G equ 1 + ENDC + ENDC + +; The following include file is generated from globals.h, and gives us equates +; that give the offsets in Uz_Globs of the fields we use, which are: +; ulg bb +; unsigned int bk, wp +; (either array of unsigned char, or pointer to unsigned char) redirslide +; For fUnZip: +; FILE *in +; For regular UnZip but not fUnZip: +; int incnt, mem_mode +; long csize +; uch *inptr +; It also defines a value SIZEOF_slide, which tells us whether the appropriate +; slide field in G (either area.Slide or redirect_pointer) is a pointer or an +; array instance. It is 4 in the former case and a large value in the latter. +; Lastly, this include will define CRYPT as 1 if appropriate. + + IFDEF FUNZIP + INCLUDE human68k/G_offs_.mac + ELSE + IFDEF SFX + INCLUDE human68k/G_offsf.mac" + ELSE + INCLUDE human68k/G_offs.mac + ENDC + ENDC + +; struct huft is defined as follows: +; +; struct huft { +; uch e; /* number of extra bits or operation */ +; uch b; /* number of bits in this code or subcode */ +; union { +; ush n; /* literal, length base, or distance base */ +; struct huft *t; /* pointer to next level of table */ +; } v; +; }; /* sizeof(struct huft) == 6 */ +; +; The G_offs include defines offsets h_e, h_b, h_v_n, and h_v_t in this +; struct, plus SIZEOF_huft. + +; G.bb is the global buffer that holds bits from the huffman code stream, which +; we cache in the register variable b. G.bk is the number of valid bits in it, +; which we cache in k. The macros NEEDBITS(n) and DUMPBITS(n) have side effects +; on b and k. + + IFDEF REENT_G +G_SIZE equ 4 +G_PUSH MACRO ; this macro passes "__G__" to functions + move.l G,-(sp) + ENDM + ELSE + xref _G ; Uz_Globs +G_SIZE equ 0 +G_PUSH MACRO + ds.b 0 ; does nothing; the assembler dislikes MACRO ENDM + ENDM + ENDC ; REENT_G + +;; xref _mask_bits ; const unsigned mask_bits[17]; + IFDEF FUNZIP + IF CRYPT + xref _encrypted ; int -- boolean flag + xref _update_keys ; int update_keys(__GPRO__ int) + xref _decrypt_byte ; int decrypt_byte(__GPRO) + ENDC ; CRYPT + ELSE ; !FUNZIP + xref _memflush ; int memflush(__GPRO__ uch *, ulg) + xref _readbyte ; int readbyte(__GPRO) + ENDC ; FUNZIP + + xref _flush ; if FUNZIP: int flush(__GPRO__ ulg) + ; else: int flush(__GPRO__ uch *, ulg, int) + +; Here are our register variables. + +b reg d2 ; unsigned long +k reg d3 ; unsigned short <= 32 +e reg d4 ; unsigned int, mostly used as unsigned char +w reg d5 ; unsigned long (was short before deflate64) +n reg d6 ; unsigned long (was short before deflate64) +d reg d7 ; unsigned int, used as unsigned short + +t reg a2 ; struct huft * +lmask reg a3 ; ulg * +G reg a6 ; Uz_Globs * + +; Couple other items we need: + +savregs reg d2-d7/a2/a3/a6 + IFDEF USE_DEFLATE64 +WSIZE equ $10000 ; 64K... be careful not to treat as short! + ELSE +WSIZE equ $08000 ; 32K... be careful not to treat as negative! + ENDC +EOF equ -1 +INVALID equ 99 + +; inflate_codes() returns one of the following status codes: +; 0 OK +; 1 internal inflate error or EOF on input stream +; the following return codes are passed through from FLUSH() errors +; 50 (PK_DISK) "overflow of output space" +; 80 (IZ_CTRLC) "canceled by user's request" + +RET_OK equ 0 +RET_ERR equ 1 + + IFDEF FUNZIP +; This does getc(in). LIBC version is based on #define getc(fp) in stdio.h + +GETC MACRO + xref _fgetc ; int fgetc(FILE *) + move.l in-X(G),-(sp) + jsr _fgetc + addq.l #4,sp + ENDM + ENDC ; FUNZIP + +; Input depends on the NEXTBYTE macro. This exists in three different forms. +; The first two are for fUnZip, with and without decryption. The last is for +; regular UnZip with or without decryption. The resulting byte is returned +; in d0 as a longword, and d1, a0, and a1 are clobbered. + +; FLUSH also has different forms for UnZip and fUnZip. Arg must be a longword. +; The same scratch registers are trashed. + + IFDEF FUNZIP + +NEXTBYTE MACRO + move.l d2,-(sp) + GETC + IF CRYPT + tst.w _encrypted+INTSIZE-2 ; test low word if long + beq.s @nbe + MOVINT d0,-(sp) ; save thru next call + G_PUSH + jsr _decrypt_byte + eor.w d0,G_SIZE+INTSIZE-2(sp) ; becomes arg to update_keys + jsr _update_keys + addq #INTSIZE+G_SIZE,sp +@nbe: + ENDC ; !CRYPT + IFEQ INTSIZE-2 + ext.l d0 ; assert -1 <= d0 <= 255 + ENDC + move.l (sp)+,d2 + ENDM + +FLUSH MACRO _1 + move.l d2,-(sp) + move.l _1,-(sp) + G_PUSH + jsr _flush + addq #4+G_SIZE,sp + move.l (sp)+,d2 + ENDM + + ELSE ; !FUNZIP + +NEXTBYTE MACRO + subq.w #1,incnt+INTSIZE-2-X(G) ; treat as short + bge.s @nbs + IFNE INTSIZE-2 + subq.w #1,incnt-X(G) + bge.s @nbs + ENDIF + move.l d2,-(sp) + G_PUSH + jsr _readbyte + IFNE G_SIZE + addq #G_SIZE,sp + ENDC + move.l (sp)+,d2 + IFEQ 2-INTSIZE + ext.l d0 ; assert -1 <= d0 <= 255 + ENDC + bra.s @nbe +@nbs: moveq #0,d0 + move.l inptr-X(G),a0 + move.b (a0)+,d0 + move.l a0,inptr-X(G) +@nbe: + ENDM + +FLUSH MACRO _1 + move.l d2,-(sp) + clr.l -(sp) ; unshrink flag: always false + move.l _1,-(sp) ; length + IF SIZEOF_slide>4 + pea redirslide-X(G) ; buffer to flush + ELSE + move.l redirslide-X(G),-(sp) + ENDC + G_PUSH + tst.w mem_mode+INTSIZE-2-X(G) ; test lower word if long + beq.s @fm + jsr _memflush ; ignores the unshrink flag + bra.s @fe +@fm: jsr _flush +@fe: lea 8+INTSIZE+G_SIZE(sp),sp + move.l (sp)+,d2 + ENDM + + ENDC ; ?FUNZIP + +; Here are the two bit-grabbing macros, defined in their NO_CHECK_EOF form: +; +; #define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<>=(n);k-=(n);} +; +; Without NO_CHECK_EOF, NEEDBITS reads like this: +; +; {while((int)k<(int)(n)){int c=NEXTBYTE; +; if(c==EOF){if((int)k>=0)break;return 1}; +; b|=((ulg)c)<4 + lea redirslide-X(G),a0 + ELSE + move.l redirslide-X(G),a0 + ENDC + move.l a0,a1 + add.l w,a0 ; w and d are valid longwords + add.l d,a1 +; Now at this point we could do tests to see if we should use an optimized +; large block copying method such as movem's, but since (a) such methods require +; the source and destination to be compatibly aligned -- and odd bytes at each +; end have to be handled separately, (b) it's only worth checking for if the +; block is pretty large, and (c) most strings are only a few bytes long, we're +; just not going to bother. Therefore we check above to make sure we move at +; most 32K in one sub-block, so a dbra loop can handle it. +dshort: move.l e,d0 + subq #1,d0 ; assert >= 0 +dspin: move.b (a1)+,(a0)+ + dbra d0,dspin + add.l e,w + add.l e,d + cmp.l #WSIZE,w + blo.s dnfl + FLUSH w + ext.l d0 ; does a test as it casts to long + bne return + moveq #0,w +dnfl: tst.l n ; need to do more sub-blocks? + bne docopy ; yes + moveq #0,e ; restore zeroness in upper bytes of e + bra main_loop ; break (newtop loop) + +nonleng: cmp.w #INVALID,e ; bottom of newtop loop -- misc. code + bne.s tailgo ; invalid code? + bra error_return ; then fail +tailgo: and.w #$001F,e + NEEDBITS e + move.w e,d0 + asl.w #2,d0 + and.l (lmask,d0.w),d1 + IFNE SIZEOF_huft-8 + mulu #SIZEOF_huft,d1 + ELSE + asl.l #3,d1 + ENDC + move.l h_v_t(t),t + add.l d1,t + bra newtop + +finish: MOVINT w,wp-X(G) ; done: restore cached globals + MOVINT k,bk-X(G) + move.l b,bb-X(G) + moveq #RET_OK,d0 ; return "no error" +return: movem.l (sp)+,savregs + unlk a5 + rts + +error_return: + moveq #RET_ERR,d0 ; return "error occured" + bra return diff --git a/human68k/human68k.c b/human68k/human68k.c new file mode 100644 index 0000000..8a8343a --- /dev/null +++ b/human68k/human68k.c @@ -0,0 +1,976 @@ +/* + Copyright (c) 1990-2007 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 +*/ +/*--------------------------------------------------------------------------- + + human68k.c + + Human68k-specific routines for use with Info-ZIP's UnZip 5.41 and later. + + Contains: do_wild() + mapattr() + mapname() + checkdir() + close_outfile() + stamp_file() (TIMESTAMP only) + version() + main() (for UnZipSFX) + + ---------------------------------------------------------------------------*/ + + +#include +#include +#include +#include +#ifdef HAVE_TWONCALL_H +#include +#endif +#define UNZIP_INTERNAL +#include "unzip.h" + +#if defined (SFX) && defined (MAIN) +#include +int MAIN(int argc, char *argv[]); +#endif + +static void map2fat(char *pathcomp, char *last_dot); +static char *trunc_name(char *name, int maxlen); + +static int created_dir; /* used in mapname(), checkdir() */ +static int renamed_fullpath; /* ditto */ + +static char multi_period, special_char; + +#ifndef SFX + +/**********************/ +/* Function do_wild() */ +/**********************/ + +char *do_wild(__G__ wildspec) + __GDEF + ZCONST char *wildspec; /* only used first time on a given dir */ +{ + static DIR *wild_dir = (DIR *)NULL; + static ZCONST char *wildname; + static char *dirname, matchname[FILNAMSIZ]; + static int notfirstcall=FALSE, have_dirname, dirnamelen; + struct dirent *file; + + /* Even when we're just returning wildspec, we *always* do so in + * matchname[]--calling routine is allowed to append four characters + * to the returned string, and wildspec may be a pointer to argv[]. + */ + if (!notfirstcall) { /* first call: must initialize everything */ + notfirstcall = TRUE; + + if (!iswild(wildspec)) { + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + have_dirname = FALSE; + wild_dir = (DIR *)NULL; + return matchname; + } + + /* break the wildspec into a directory part and a wildcard filename */ + if ((wildname = strrchr(wildspec, '/')) == NULL) { + dirname = "."; + dirnamelen = 1; + have_dirname = FALSE; + wildname = wildspec; + } else { + ++wildname; /* point at character after '/' */ + dirnamelen = wildname - wildspec; + if ((dirname = (char *)malloc(dirnamelen+1)) == NULL) { + Info(slide, 1, ((char *)slide, + "warning: cannot allocate wildcard buffers\n")); + strcpy(matchname, wildspec); + return matchname; /* but maybe filespec was not a wildcard */ + } + strncpy(dirname, wildspec, dirnamelen); + dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ + have_dirname = TRUE; + } + Trace((stderr, "do_wild: dirname = [%s]\n", FnFilter1(dirname))); + + if ((wild_dir = opendir(dirname)) != (DIR *)NULL) { + while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + if (file->d_name[0] == '.' && wildname[0] != '.') + continue; /* Unix: '*' and '?' do not match leading dot */ + if (match(file->d_name, wildname, 0 WISEP) && /* 0=case sens.*/ + /* skip "." and ".." directory entries */ + strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) { + Trace((stderr, "do_wild: match() succeeds\n")); + if (have_dirname) { + strcpy(matchname, dirname); + strcpy(matchname+dirnamelen, file->d_name); + } else + strcpy(matchname, file->d_name); + return matchname; + } + } + /* if we get to here directory is exhausted, so close it */ + closedir(wild_dir); + wild_dir = (DIR *)NULL; + } +#ifdef DEBUG + else { + Trace((stderr, "do_wild: Opendir(%s) returns NULL\n", + FnFilter1(dirname))); + } +#endif /* DEBUG */ + + /* return the raw wildspec in case that works (e.g., directory not + * searchable, but filespec was not wild and file is readable) */ + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (wild_dir == (DIR *)NULL) { + notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + } + + /* If we've gotten this far, we've read and matched at least one entry + * successfully (in a previous call), so dirname has been copied into + * matchname already. + */ + while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + if (file->d_name[0] == '.' && wildname[0] != '.') + continue; /* Unix: '*' and '?' do not match leading dot */ + if (match(file->d_name, wildname, 0 WISEP)) { /* 0 == case sens. */ + Trace((stderr, "do_wild: match() succeeds\n")); + if (have_dirname) { + /* strcpy(matchname, dirname); */ + strcpy(matchname+dirnamelen, file->d_name); + } else + strcpy(matchname, file->d_name); + return matchname; + } + } + + closedir(wild_dir); /* have read at least one entry; nothing left */ + wild_dir = (DIR *)NULL; + notfirstcall = FALSE; /* reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + +} /* end function do_wild() */ + +#endif /* !SFX */ + + + + +/**********************/ +/* Function mapattr() */ +/**********************/ + +int mapattr(__G) + __GDEF +{ + ulg tmp = G.crec.external_file_attributes; + + switch (G.pInfo->hostnum) { + case UNIX_: + if (tmp & 0xff) + break; + /* fall through */ + case VMS_: + case ACORN_: + case ATARI_: + case ATHEOS_: + case BEOS_: + case QDOS_: + G.pInfo->file_attr = _mode2dos(tmp >> 16); + return 0; + default: + break; + } + + /* set archive bit (file is not backed up) */ + if((tmp & 0x08) == 0) + tmp |= 0x20; + G.pInfo->file_attr = tmp & 0xff; + return 0; + +} /* end function mapattr() */ + + + + + +/**********************/ +/* Function mapname() */ +/**********************/ + +int mapname(__G__ renamed) + __GDEF + int renamed; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - caution (truncated filename) + * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) + * MPN_ERR_SKIP - error -> skip entry + * MPN_ERR_TOOLONG - error -> path is too long + * MPN_NOMEM - error (memory allocation failed) -> skip entry + * [also MPN_VOL_LABEL, MPN_CREATED_DIR] + */ +{ + char pathcomp[FILNAMSIZ]; /* path-component buffer */ + char *pp, *cp=(char *)NULL; /* character pointers */ + char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ + char *last_dot=(char *)NULL; /* last dot */ + int error = MPN_OK; + register unsigned workch; /* hold the character being tested */ + +#ifdef HAVE_TWONCALL_H + static char twentyone_flag; + + /* Get TwentyOne options */ + if (twentyone_flag == 0) { + twentyone_flag++; + if (GetTwentyOneID () == TWON_ID) { + int flags = GetTwentyOneOptions (); + + if (flags & (1 << TWON_PERIOD_BIT)) + multi_period = TRUE; + if (flags & (1 << TWON_SPECIAL_BIT)) + special_char = TRUE; + } + } +#endif + +/*--------------------------------------------------------------------------- + Initialize various pointers and counters and stuff. + ---------------------------------------------------------------------------*/ + + /* can create path as long as not just freshening, or if user told us */ + G.create_dirs = (!uO.fflag || renamed); + + created_dir = FALSE; /* not yet */ + renamed_fullpath = FALSE; + + if (renamed) { + cp = G.filename - 1; /* point to beginning of renamed name... */ + while (*++cp) + if (*cp == '\\') /* convert backslashes to forward */ + *cp = '/'; + cp = G.filename; + if ((G.filename[0] == '/') + || (isalpha(G.filename[0]) && G.filename[1] == ':')) { + /* user gave full pathname: don't prepend rootpath */ + renamed_fullpath = TRUE; + } + } + + if ((error = checkdir(__G__ (char *)NULL, INIT)) != 0) + return error; /* initialize path buffer, unless no memory */ + + *pathcomp = '\0'; /* initialize translation buffer */ + pp = pathcomp; /* point to translation buffer */ + if (uO.jflag) /* junking directories */ + cp = (char *)strrchr(G.filename, '/'); + if (cp == (char *)NULL) /* no '/' or not junking dirs */ + cp = G.filename; /* point to internal zipfile-member pathname */ + else + ++cp; /* point to start of last component of path */ + +/*--------------------------------------------------------------------------- + Begin main loop through characters in filename. + ---------------------------------------------------------------------------*/ + + while ((workch = (uch)*cp++) != 0) { + + if (_ismbblead((unsigned char)workch)) { + if (*cp) { + *pp++ = (char)workch; + *pp++ = (char)*cp++; + } + else + *pp++ = '_'; + continue; + } + + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + map2fat(pathcomp, last_dot); /* 18.3 trunc. (in place) */ + if (strcmp(pathcomp, ".") == 0) { + /* don't bother appending "./" to the path */ + *pathcomp = '\0'; + } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { + /* "../" dir traversal detected, skip over it */ + *pathcomp = '\0'; + killed_ddot = TRUE; /* set "show message" flag */ + } + /* when path component is not empty, append it now */ + if (*pathcomp != '\0' && + ((error = checkdir(__G__ pathcomp, APPEND_DIR)) + & MPN_MASK) > MPN_INF_TRUNC) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ + break; + + /* drive names are not stored in zipfile, so no colons allowed; + * no brackets or most other punctuation either (all of which + * can appear in Unix-created archives; backslash is particularly + * bad unless all necessary directories exist) */ + + case '[': /* these punctuation characters forbidden */ + case ']': /* only on plain FAT file systems */ + case '+': + case ',': + case '=': + case '<': + case '>': + case '|': + case '\"': + case '\'': + if (!special_char) + workch = '_'; + *pp++ = (char)workch; + break; + + case '-': + if (pp == pathcomp && !special_char) + workch = '_'; + *pp++ = (char)workch; + break; + + case ':': + case '\\': + case '*': + case '?': + *pp++ = '_'; + break; + + case ';': /* VMS version (or DEC-20 attrib?) */ + lastsemi = pp; + if (!special_char) + workch = '_'; + *pp++ = (char)workch; /* keep for now; remove VMS ";##" */ + break; /* later, if requested */ + + case ' ': /* change spaces to underscores */ +#if 0 /* do it always */ + if (uO.sflag) /* only if requested */ +#endif + workch = '_'; + *pp++ = (char)workch; + break; + + default: + /* allow European characters in filenames: */ + if (isprint(workch) || workch >= 128) + *pp++ = (char)workch; + + } /* end switch */ + } /* end while loop */ + + /* Show warning when stripping insecure "parent dir" path components */ + if (killed_ddot && QCOND2) { + Info(slide, 0, ((char *)slide, + "warning: skipped \"../\" path component(s) in %s\n", + FnFilter1(G.filename))); + if (!(error & ~MPN_MASK)) + error = (error & MPN_MASK) | PK_WARN; + } + +/*--------------------------------------------------------------------------- + Report if directory was created (and no file to create: filename ended + in '/'), check name to be sure it exists, and combine path and name be- + fore exiting. + ---------------------------------------------------------------------------*/ + + if (G.filename[strlen(G.filename) - 1] == '/') { + checkdir(__G__ G.filename, GETPATH); + if (created_dir) { + if (QCOND2) { + Info(slide, 0, ((char *)slide, " creating: %s\n", + FnFilter1(G.filename))); + } + /* set dir time (note trailing '/') */ + return (error & ~MPN_MASK) | MPN_CREATED_DIR; + } + /* dir existed already; don't look for data to extract */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + *pp = '\0'; /* done with pathcomp: terminate it */ + + /* if not saving them, remove VMS version numbers (appended ";###") */ + if (!uO.V_flag && lastsemi) { + pp = lastsemi + 1; + while (isdigit((uch)(*pp))) + ++pp; + if (*pp == '\0') /* only digits between ';' and end: nuke */ + *lastsemi = '\0'; + } + + map2fat(pathcomp, last_dot); /* 18.3 truncation (in place) */ + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", + FnFilter1(G.filename))); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + + checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ + checkdir(__G__ G.filename, GETPATH); + + if (G.pInfo->vollabel) { /* set the volume label now */ + int fd; + + if (QCOND2) + Info(slide, 0, ((char *)slide, " labelling: %s\n", + FnFilter1(G.filename))); + if ((fd = _dos_newfile(G.filename, G.pInfo->file_attr)) < 0) { + Info(slide, 1, ((char *)slide, + "mapname: error setting volume label\n")); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + _dos_close(fd); + /* success: skip the "extraction" quietly */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + return error; + +} /* end function mapname() */ + + + + +/**********************/ +/* Function map2fat() */ +/**********************/ + +static void map2fat(pathcomp, last_dot) + char *pathcomp, *last_dot; +{ + char *np; + + if (pathcomp == last_dot) { /* dotfile(e.g. ".foo") */ + pathcomp = last_dot; + last_dot = (char *)NULL; + } + + if (multi_period) { + if (strlen(pathcomp) <= 18) + return; + } + else { + char *p; + + for (p = pathcomp; *p; p++) + if (*p == (char)'.' && p != last_dot) + *p = '_'; + } + + if (last_dot) { + *last_dot++ = '\0'; + trunc_name(last_dot, 3); + } + np = trunc_name(pathcomp, 18); + if (last_dot) { + *--last_dot = '.'; + if (np) + strcpy(np, last_dot); + } + +} /* end function map2fat() */ + +static char *trunc_name(char *name, int maxlen) +{ + + if (strlen(name) <= maxlen) + return (char *)NULL; + + do { + if (_ismbblead((unsigned char)*name)) { + if (--maxlen == 0) + break; + name++; + } + name++; + maxlen--; + } while (maxlen > 0); + *name = '\0'; + + return name; +} + + + + +/***********************/ +/* Function checkdir() */ +/***********************/ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename + * MPN_INF_SKIP - path doesn't exist, not allowed to create + * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path + * exists and is not a directory, but is supposed to be + * MPN_ERR_TOOLONG - path is too long + * MPN_NOMEM - can't allocate memory for filename buffers + */ +{ + static int rootlen = 0; /* length of rootpath */ + static char *rootpath; /* user's "extract-to" directory */ + static char *buildpath; /* full path (so far) to extracted file */ + static char *end; /* pointer to end of buildpath ('\0') */ + +# define FN_MASK 7 +# define FUNCTION (flag & FN_MASK) + + +/*--------------------------------------------------------------------------- + APPEND_DIR: append the path component to the path being built and check + for its existence. If doesn't exist and we are creating directories, do + so for this one; else signal success or error as appropriate. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_DIR) { + int too_long = FALSE; + + Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') + ++end; + + /* GRR: could do better check, see if overrunning buffer as we go: + * check end-buildpath after each append, set warning variable if + * within 20 of FILNAMSIZ; then if var set, do careful check when + * appending. Clear variable when begin new path. */ + + if ((end-buildpath) > FILNAMSIZ-3) /* need '/', one-char name, '\0' */ + too_long = TRUE; /* check if extracting directory? */ + if (SSTAT(buildpath, &G.statbuf)) /* path doesn't exist */ + { + if (!G.create_dirs) { /* told not to create (freshening) */ + free(buildpath); + return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", + FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + if (mkdir(buildpath, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, + "checkdir error: cannot create %s\n\ + unable to process %s.\n", + FnFilter2(buildpath), FnFilter1(G.filename))); + free(buildpath); + /* path didn't exist, tried to create, failed */ + return MPN_ERR_SKIP; + } + created_dir = TRUE; + } else if (!S_ISDIR(G.statbuf.st_mode)) { + Info(slide, 1, ((char *)slide, + "checkdir error: %s exists but is not directory\n\ + unable to process %s.\n", + FnFilter2(buildpath), FnFilter1(G.filename))); + free(buildpath); + /* path existed but wasn't dir */ + return MPN_ERR_SKIP; + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + *end++ = '/'; + *end = '\0'; + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + return MPN_OK; + + } /* end if (FUNCTION == APPEND_DIR) */ + +/*--------------------------------------------------------------------------- + GETPATH: copy full path to the string pointed at by pathcomp, and free + buildpath. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == GETPATH) { + strcpy(pathcomp, buildpath); + Trace((stderr, "getting and freeing path [%s]\n", + FnFilter1(pathcomp))); + free(buildpath); + buildpath = end = (char *)NULL; + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + APPEND_NAME: assume the path component is the filename; append it and + return without checking for existence. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_NAME) { + + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') { + ++end; + if ((end-buildpath) >= FILNAMSIZ) { + *--end = '\0'; + Info(slide, 1, ((char *)slide, + "checkdir warning: path too long; truncating\n\ + %s\n -> %s\n", + FnFilter1(G.filename), FnFilter2(buildpath))); + return MPN_INF_TRUNC; /* filename truncated */ + } + } + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + /* could check for existence here, prompt for new name... */ + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + INIT: allocate and initialize buffer space for the file currently being + extracted. If file was renamed with an absolute path, don't prepend the + extract-to path. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == INIT) { + Trace((stderr, "initializing buildpath to ")); + /* allocate space for full filename, root path, and maybe "./" */ + if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+3)) == + (char *)NULL) + return MPN_NOMEM; + if ((rootlen > 0) && !renamed_fullpath) { + strcpy(buildpath, rootpath); + end = buildpath + rootlen; + } else { + *buildpath = '\0'; + end = buildpath; + } + Trace((stderr, "[%s]\n", FnFilter1(buildpath))); + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + ROOT: if appropriate, store the path in rootpath and create it if neces- + sary; else assume it's a zipfile member and return. This path segment + gets used in extracting all members from every zipfile specified on the + command line. + ---------------------------------------------------------------------------*/ + +#if (!defined(SFX) || defined(SFX_EXDIR)) + if (FUNCTION == ROOT) { + Trace((stderr, "initializing root path to [%s]\n", + FnFilter1(pathcomp))); + if (pathcomp == (char *)NULL) { + rootlen = 0; + return MPN_OK; + } + if (rootlen > 0) /* rootpath was already set, nothing to do */ + return MPN_OK; + if ((rootlen = strlen(pathcomp)) > 0) { + int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE; + char *tmproot; + + if ((tmproot = (char *)malloc(rootlen+3)) == (char *)NULL) { + rootlen = 0; + return MPN_NOMEM; + } + strcpy(tmproot, pathcomp); + if (isalpha((uch)tmproot[0]) && tmproot[1] == ':') + has_drive = TRUE; /* drive designator */ + if (tmproot[rootlen-1] == '/' || tmproot[rootlen-1] == '\\') { + tmproot[--rootlen] = '\0'; + had_trailing_pathsep = TRUE; + } + if (has_drive && (rootlen == 2)) { + if (!had_trailing_pathsep) /* i.e., original wasn't "x:/" */ + add_dot = TRUE; /* relative path: add '.' before '/' */ + } else if (rootlen > 0 && (SSTAT(tmproot, &G.statbuf) || + !S_ISDIR(G.statbuf.st_mode))) /* path does not exist */ + { + if (!G.create_dirs /* || iswild(tmproot) */ ) { + free(tmproot); + rootlen = 0; + /* skip (or treat as stored file) */ + return MPN_INF_SKIP; + } + /* create the directory (could add loop here scanning tmproot + * to create more than one level, but why really necessary?) */ + if (mkdir(tmproot, 0777) == -1) { + Info(slide, 1, ((char *)slide, + "checkdir: cannot create extraction directory: %s\n", + FnFilter1(tmproot))); + free(tmproot); + rootlen = 0; + /* path didn't exist, tried to create, and failed: */ + /* file exists, or 2+ subdir levels required */ + return MPN_ERR_SKIP; + } + } + if (add_dot) /* had just "x:", make "x:." */ + tmproot[rootlen++] = '.'; + tmproot[rootlen++] = '/'; + tmproot[rootlen] = '\0'; + if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { + free(tmproot); + rootlen = 0; + return MPN_NOMEM; + } + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath))); + } + return MPN_OK; + } +#endif /* !SFX || SFX_EXDIR */ + +/*--------------------------------------------------------------------------- + END: free rootpath, immediately prior to program exit. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == END) { + Trace((stderr, "freeing rootpath\n")); + if (rootlen > 0) { + free(rootpath); + rootlen = 0; + } + return MPN_OK; + } + + return MPN_INVALID; /* should never reach */ + +} /* end function checkdir() */ + + + + +#if (defined(USE_EF_UT_TIME) || defined(TIMESTAMP)) +/* The following DOS date/time structure is machine-dependent as it + * assumes "little-endian" byte order. For MSDOS-specific code, which + * is run on ix86 CPUs (or emulators), this assumption is valid; but + * care should be taken when using this code as template for other ports. + */ +typedef union { + ulg z_dostime; + struct { /* date and time words */ + ush ztime; /* DOS file modification time word */ + ush zdate; /* DOS file modification date word */ + } zft; + struct { /* DOS date/time components bitfield */ + unsigned zt_se : 5; + unsigned zt_mi : 6; + unsigned zt_hr : 5; + unsigned zd_dy : 5; + unsigned zd_mo : 4; + unsigned zd_yr : 7; + } z_dtf; +} dos_fdatetime; +#endif /* USE_EF_UT_TIME || TIMESTAMP */ + + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) + __GDEF +{ + /* skip restoring time stamps on user's request */ + if (uO.D_flag <= 1) { +#ifdef USE_EF_UT_TIME + dos_fdatetime dos_dt; + iztimes z_utime; + struct tm *t; +#endif /* USE_EF_UT_TIME */ + + +#ifdef USE_EF_UT_TIME + if (G.extra_field && +#ifdef IZ_CHECK_TZ + G.tz_is_valid && +#endif + (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, + G.lrec.last_mod_dos_datetime, &z_utime, NULL) + & EB_UT_FL_MTIME)) + { + TTrace((stderr, "close_outfile: Unix e.f. modif. time = %ld\n", + z_utime.mtime)); + /* round up (down if "up" overflows) to even seconds */ + if (z_utime.mtime & 1) + z_utime.mtime = (z_utime.mtime + 1 > z_utime.mtime) ? + z_utime.mtime + 1 : z_utime.mtime - 1; + TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7 or Macintosh */ + t = localtime(&(z_utime.mtime)); + } else + t = (struct tm *)NULL; + if (t != (struct tm *)NULL) { + if (t->tm_year < 80) { + dos_dt.z_dtf.zt_se = 0; + dos_dt.z_dtf.zt_mi = 0; + dos_dt.z_dtf.zt_hr = 0; + dos_dt.z_dtf.zd_dy = 1; + dos_dt.z_dtf.zd_mo = 1; + dos_dt.z_dtf.zd_yr = 0; + } else { + dos_dt.z_dtf.zt_se = t->tm_sec >> 1; + dos_dt.z_dtf.zt_mi = t->tm_min; + dos_dt.z_dtf.zt_hr = t->tm_hour; + dos_dt.z_dtf.zd_dy = t->tm_mday; + dos_dt.z_dtf.zd_mo = t->tm_mon + 1; + dos_dt.z_dtf.zd_yr = t->tm_year - 80; + } + } else { + dos_dt.z_dostime = G.lrec.last_mod_dos_datetime; + } + _dos_filedate(fileno(G.outfile), dos_dt.z_dostime); +#else /* !USE_EF_UT_TIME */ + _dos_filedate(fileno(G.outfile), G.lrec.last_mod_dos_datetime); +#endif /* ?USE_EF_UT_TIME */ + } + + fclose(G.outfile); + + _dos_chmod(G.filename, G.pInfo->file_attr); + +} /* end function close_outfile() */ + + + + + +#ifdef TIMESTAMP + +/*************************/ +/* Function stamp_file() */ +/*************************/ + +int stamp_file(fname, modtime) + ZCONST char *fname; + time_t modtime; +{ + dos_fdatetime dos_dt; + time_t t_even; + struct tm *t; + int fd; /* file handle */ + + /* round up (down if "up" overflows) to even seconds */ + t_even = ((modtime + 1 > modtime) ? modtime + 1 : modtime) & (~1); + TIMET_TO_NATIVE(t_even) /* NOP unless MSC 7.0 or Macintosh */ + t = localtime(&t_even); + if (t == (struct tm *)NULL) + return -1; /* time conversion error */ + if (t->tm_year < 80) { + dos_dt.z_dtf.zt_se = 0; + dos_dt.z_dtf.zt_mi = 0; + dos_dt.z_dtf.zt_hr = 0; + dos_dt.z_dtf.zd_dy = 1; + dos_dt.z_dtf.zd_mo = 1; + dos_dt.z_dtf.zd_yr = 0; + } else { + dos_dt.z_dtf.zt_se = t->tm_sec >> 1; + dos_dt.z_dtf.zt_mi = t->tm_min; + dos_dt.z_dtf.zt_hr = t->tm_hour; + dos_dt.z_dtf.zd_dy = t->tm_mday; + dos_dt.z_dtf.zd_mo = t->tm_mon + 1; + dos_dt.z_dtf.zd_yr = t->tm_year - 80; + } + if (((fd = open((char *)fname, 0)) == -1) || + (_dos_filedate(fd, dos_dt.z_dostime))) + { + if (fd != -1) + close(fd); + return -1; + } + close(fd); + return 0; + +} /* end function stamp_file() */ + +#endif /* TIMESTAMP */ + + + + +#ifndef SFX + +/************************/ +/* Function version() */ +/************************/ + +void version(__G) + __GDEF +{ + int len; +#if 0 + char buf[40]; +#endif + + len = sprintf((char *)slide, LoadFarString(CompiledWith), + +#ifdef __GNUC__ + "gcc ", __VERSION__, +#else +# if 0 + "cc ", (sprintf(buf, " version %d", _RELEASE), buf), +# else + "unknown compiler", "", +# endif +#endif + + "Human68k", +#ifdef __MC68020__ + " (X68030)", +#else + " (X680x0)", +#endif + +#ifdef __DATE__ + " on ", __DATE__ +#else + "", "" +#endif + ); + + (*G.message)((zvoid *)&G, slide, (ulg)len, 0); + +} /* end function version() */ + +#endif /* !SFX */ + + +#if defined (SFX) && defined (MAIN) +int main(int argc, char *argv[]) +{ + char argv0[92]; + + /* make true argv[0] (startup routine makes it inaccuracy) */ + argv[0] = strcat (strcpy (argv0, _procp->exe_path), _procp->exe_name); + + return MAIN(argc, argv); +} +#endif /* SFX && MAIN */ diff --git a/inflate.c b/inflate.c new file mode 100644 index 0000000..f2f6864 --- /dev/null +++ b/inflate.c @@ -0,0 +1,1775 @@ +/* + Copyright (c) 1990-2008 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2007-Mar-04 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 +*/ +/* inflate.c -- by Mark Adler + version c17e, 30 Mar 2007 */ + + +/* Copyright history: + - Starting with UnZip 5.41 of 16-April-2000, this source file + is covered by the Info-Zip LICENSE cited above. + - Prior versions of this source file, found in UnZip source packages + up to UnZip 5.40, were put in the public domain. + The original copyright note by Mark Adler was: + "You can do whatever you like with this source file, + though I would prefer that if you modify it and + redistribute it that you include comments to that effect + with your name and the date. Thank you." + + History: + vers date who what + ---- --------- -------------- ------------------------------------ + a ~~ Feb 92 M. Adler used full (large, one-step) lookup table + b1 21 Mar 92 M. Adler first version with partial lookup tables + b2 21 Mar 92 M. Adler fixed bug in fixed-code blocks + b3 22 Mar 92 M. Adler sped up match copies, cleaned up some + b4 25 Mar 92 M. Adler added prototypes; removed window[] (now + is the responsibility of unzip.h--also + changed name to slide[]), so needs diffs + for unzip.c and unzip.h (this allows + compiling in the small model on MSDOS); + fixed cast of q in huft_build(); + b5 26 Mar 92 M. Adler got rid of unintended macro recursion. + b6 27 Mar 92 M. Adler got rid of nextbyte() routine. fixed + bug in inflate_fixed(). + c1 30 Mar 92 M. Adler removed lbits, dbits environment variables. + changed BMAX to 16 for explode. Removed + OUTB usage, and replaced it with flush()-- + this was a 20% speed improvement! Added + an explode.c (to replace unimplod.c) that + uses the huft routines here. Removed + register union. + c2 4 Apr 92 M. Adler fixed bug for file sizes a multiple of 32k. + c3 10 Apr 92 M. Adler reduced memory of code tables made by + huft_build significantly (factor of two to + three). + c4 15 Apr 92 M. Adler added NOMEMCPY do kill use of memcpy(). + worked around a Turbo C optimization bug. + c5 21 Apr 92 M. Adler added the WSIZE #define to allow reducing + the 32K window size for specialized + applications. + c6 31 May 92 M. Adler added some typecasts to eliminate warnings + c7 27 Jun 92 G. Roelofs added some more typecasts (444: MSC bug). + c8 5 Oct 92 J-l. Gailly added ifdef'd code to deal with PKZIP bug. + c9 9 Oct 92 M. Adler removed a memory error message (~line 416). + c10 17 Oct 92 G. Roelofs changed ULONG/UWORD/byte to ulg/ush/uch, + removed old inflate, renamed inflate_entry + to inflate, added Mark's fix to a comment. + c10.5 14 Dec 92 M. Adler fix up error messages for incomplete trees. + c11 2 Jan 93 M. Adler fixed bug in detection of incomplete + tables, and removed assumption that EOB is + the longest code (bad assumption). + c12 3 Jan 93 M. Adler make tables for fixed blocks only once. + c13 5 Jan 93 M. Adler allow all zero length codes (pkzip 2.04c + outputs one zero length code for an empty + distance tree). + c14 12 Mar 93 M. Adler made inflate.c standalone with the + introduction of inflate.h. + c14b 16 Jul 93 G. Roelofs added (unsigned) typecast to w at 470. + c14c 19 Jul 93 J. Bush changed v[N_MAX], l[288], ll[28x+3x] arrays + to static for Amiga. + c14d 13 Aug 93 J-l. Gailly de-complicatified Mark's c[*p++]++ thing. + c14e 8 Oct 93 G. Roelofs changed memset() to memzero(). + c14f 22 Oct 93 G. Roelofs renamed quietflg to qflag; made Trace() + conditional; added inflate_free(). + c14g 28 Oct 93 G. Roelofs changed l/(lx+1) macro to pointer (Cray bug) + c14h 7 Dec 93 C. Ghisler huft_build() optimizations. + c14i 9 Jan 94 A. Verheijen set fixed_t{d,l} to NULL after freeing; + G. Roelofs check NEXTBYTE macro for EOF. + c14j 23 Jan 94 G. Roelofs removed Ghisler "optimizations"; ifdef'd + EOF check. + c14k 27 Feb 94 G. Roelofs added some typecasts to avoid warnings. + c14l 9 Apr 94 G. Roelofs fixed split comments on preprocessor lines + to avoid bug in Encore compiler. + c14m 7 Jul 94 P. Kienitz modified to allow assembler version of + inflate_codes() (define ASM_INFLATECODES) + c14n 22 Jul 94 G. Roelofs changed fprintf to macro for DLL versions + c14o 23 Aug 94 C. Spieler added a newline to a debug statement; + G. Roelofs added another typecast to avoid MSC warning + c14p 4 Oct 94 G. Roelofs added (voidp *) cast to free() argument + c14q 30 Oct 94 G. Roelofs changed fprintf macro to MESSAGE() + c14r 1 Nov 94 G. Roelofs fixed possible redefinition of CHECK_EOF + c14s 7 May 95 S. Maxwell OS/2 DLL globals stuff incorporated; + P. Kienitz "fixed" ASM_INFLATECODES macro/prototype + c14t 18 Aug 95 G. Roelofs added UZinflate() to use zlib functions; + changed voidp to zvoid; moved huft_build() + and huft_free() to end of file + c14u 1 Oct 95 G. Roelofs moved G into definition of MESSAGE macro + c14v 8 Nov 95 P. Kienitz changed ASM_INFLATECODES to use a regular + call with __G__ instead of a macro + c15 3 Aug 96 M. Adler fixed bomb-bug on random input data (Adobe) + c15b 24 Aug 96 M. Adler more fixes for random input data + c15c 28 Mar 97 G. Roelofs changed USE_ZLIB fatal exit code from + PK_MEM2 to PK_MEM3 + c16 20 Apr 97 J. Altman added memzero(v[]) in huft_build() + c16b 29 Mar 98 C. Spieler modified DLL code for slide redirection + c16c 04 Apr 99 C. Spieler fixed memory leaks when processing gets + stopped because of input data errors + c16d 05 Jul 99 C. Spieler take care of FLUSH() return values and + stop processing in case of errors + c17 31 Dec 00 C. Spieler added preliminary support for Deflate64 + c17a 04 Feb 01 C. Spieler complete integration of Deflate64 support + c17b 16 Feb 02 C. Spieler changed type of "extra bits" arrays and + corresponding huft_build() parameter e from + ush into uch, to save space + c17c 9 Mar 02 C. Spieler fixed NEEDBITS() "read beyond EOF" problem + with CHECK_EOF enabled + c17d 23 Jul 05 C. Spieler fixed memory leaks in inflate_dynamic() + when processing invalid compressed literal/ + distance table data + c17e 30 Mar 07 C. Spieler in inflate_dynamic(), initialize tl and td + to prevent freeing unallocated huft tables + when processing invalid compressed data and + hitting premature EOF, do not reuse td as + temp work ptr during tables decoding + */ + + +/* + Inflate deflated (PKZIP's method 8 compressed) data. The compression + method searches for as much of the current string of bytes (up to a + length of 258) in the previous 32K bytes. If it doesn't find any + matches (of at least length 3), it codes the next byte. Otherwise, it + codes the length of the matched string and its distance backwards from + the current position. There is a single Huffman code that codes both + single bytes (called "literals") and match lengths. A second Huffman + code codes the distance information, which follows a length code. Each + length or distance code actually represents a base value and a number + of "extra" (sometimes zero) bits to get to add to the base value. At + the end of each deflated block is a special end-of-block (EOB) literal/ + length code. The decoding process is basically: get a literal/length + code; if EOB then done; if a literal, emit the decoded byte; if a + length then get the distance and emit the referred-to bytes from the + sliding window of previously emitted data. + + There are (currently) three kinds of inflate blocks: stored, fixed, and + dynamic. The compressor outputs a chunk of data at a time and decides + which method to use on a chunk-by-chunk basis. A chunk might typically + be 32K to 64K, uncompressed. If the chunk is uncompressible, then the + "stored" method is used. In this case, the bytes are simply stored as + is, eight bits per byte, with none of the above coding. The bytes are + preceded by a count, since there is no longer an EOB code. + + If the data are compressible, then either the fixed or dynamic methods + are used. In the dynamic method, the compressed data are preceded by + an encoding of the literal/length and distance Huffman codes that are + to be used to decode this block. The representation is itself Huffman + coded, and so is preceded by a description of that code. These code + descriptions take up a little space, and so for small blocks, there is + a predefined set of codes, called the fixed codes. The fixed method is + used if the block ends up smaller that way (usually for quite small + chunks); otherwise the dynamic method is used. In the latter case, the + codes are customized to the probabilities in the current block and so + can code it much better than the pre-determined fixed codes can. + + The Huffman codes themselves are decoded using a multi-level table + lookup, in order to maximize the speed of decoding plus the speed of + building the decoding tables. See the comments below that precede the + lbits and dbits tuning parameters. + + GRR: return values(?) + 0 OK + 1 incomplete table + 2 bad input + 3 not enough memory + the following return codes are passed through from FLUSH() errors + 50 (PK_DISK) "overflow of output space" + 80 (IZ_CTRLC) "canceled by user's request" + */ + + +/* + Notes beyond the 1.93a appnote.txt: + + 1. Distance pointers never point before the beginning of the output + stream. + 2. Distance pointers can point back across blocks, up to 32k away. + 3. There is an implied maximum of 7 bits for the bit length table and + 15 bits for the actual data. + 4. If only one code exists, then it is encoded using one bit. (Zero + would be more efficient, but perhaps a little confusing.) If two + codes exist, they are coded using one bit each (0 and 1). + 5. There is no way of sending zero distance codes--a dummy must be + sent if there are none. (History: a pre 2.0 version of PKZIP would + store blocks with no distance codes, but this was discovered to be + too harsh a criterion.) Valid only for 1.93a. 2.04c does allow + zero distance codes, which is sent as one code of zero bits in + length. + 6. There are up to 286 literal/length codes. Code 256 represents the + end-of-block. Note however that the static length tree defines + 288 codes just to fill out the Huffman codes. Codes 286 and 287 + cannot be used though, since there is no length base or extra bits + defined for them. Similarily, there are up to 30 distance codes. + However, static trees define 32 codes (all 5 bits) to fill out the + Huffman codes, but the last two had better not show up in the data. + 7. Unzip can check dynamic Huffman blocks for complete code sets. + The exception is that a single code would not be complete (see #4). + 8. The five bits following the block type is really the number of + literal codes sent minus 257. + 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits + (1+6+6). Therefore, to output three times the length, you output + three codes (1+1+1), whereas to output four times the same length, + you only need two codes (1+3). Hmm. + 10. In the tree reconstruction algorithm, Code = Code + Increment + only if BitLength(i) is not zero. (Pretty obvious.) + 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) + 12. Note: length code 284 can represent 227-258, but length code 285 + really is 258. The last length deserves its own, short code + since it gets used a lot in very redundant files. The length + 258 is special since 258 - 3 (the min match length) is 255. + 13. The literal/length and distance code bit lengths are read as a + single stream of lengths. It is possible (and advantageous) for + a repeat code (16, 17, or 18) to go across the boundary between + the two sets of lengths. + 14. The Deflate64 (PKZIP method 9) variant of the compression algorithm + differs from "classic" deflate in the following 3 aspect: + a) The size of the sliding history window is expanded to 64 kByte. + b) The previously unused distance codes #30 and #31 code distances + from 32769 to 49152 and 49153 to 65536. Both codes take 14 bits + of extra data to determine the exact position in their 16 kByte + range. + c) The last lit/length code #285 gets a different meaning. Instead + of coding a fixed maximum match length of 258, it is used as a + "generic" match length code, capable of coding any length from + 3 (min match length + 0) to 65538 (min match length + 65535). + This means that the length code #285 takes 16 bits (!) of uncoded + extra data, added to a fixed min length of 3. + Changes a) and b) would have been transparent for valid deflated + data, but change c) requires to switch decoder configurations between + Deflate and Deflate64 modes. + */ + + +#define PKZIP_BUG_WORKAROUND /* PKZIP 1.93a problem--live with it */ + +/* + inflate.h must supply the uch slide[WSIZE] array, the zvoid typedef + (void if (void *) is accepted, else char) and the NEXTBYTE, + FLUSH() and memzero macros. If the window size is not 32K, it + should also define WSIZE. If INFMOD is defined, it can include + compiled functions to support the NEXTBYTE and/or FLUSH() macros. + There are defaults for NEXTBYTE and FLUSH() below for use as + examples of what those functions need to do. Normally, you would + also want FLUSH() to compute a crc on the data. inflate.h also + needs to provide these typedefs: + + typedef unsigned char uch; + typedef unsigned short ush; + typedef unsigned long ulg; + + This module uses the external functions malloc() and free() (and + probably memset() or bzero() in the memzero() macro). Their + prototypes are normally found in and . + */ + +#define __INFLATE_C /* identifies this source module */ + +/* #define DEBUG */ +#define INFMOD /* tell inflate.h to include code to be compiled */ +#include "inflate.h" + + +/* marker for "unused" huft code, and corresponding check macro */ +#define INVALID_CODE 99 +#define IS_INVALID_CODE(c) ((c) == INVALID_CODE) + +#ifndef WSIZE /* default is 32K resp. 64K */ +# ifdef USE_DEFLATE64 +# define WSIZE 65536L /* window size--must be a power of two, and */ +# else /* at least 64K for PKZip's deflate64 method */ +# define WSIZE 0x8000 /* window size--must be a power of two, and */ +# endif /* at least 32K for zip's deflate method */ +#endif + +/* some buffer counters must be capable of holding 64k for Deflate64 */ +#if (defined(USE_DEFLATE64) && defined(INT_16BIT)) +# define UINT_D64 ulg +#else +# define UINT_D64 unsigned +#endif + +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) +# define wsize G._wsize /* wsize is a variable */ +#else +# define wsize WSIZE /* wsize is a constant */ +#endif + + +#ifndef NEXTBYTE /* default is to simply get a byte from stdin */ +# define NEXTBYTE getchar() +#endif + +#ifndef MESSAGE /* only used twice, for fixed strings--NOT general-purpose */ +# define MESSAGE(str,len,flag) fprintf(stderr,(char *)(str)) +#endif + +#ifndef FLUSH /* default is to simply write the buffer to stdout */ +# define FLUSH(n) \ + (((extent)fwrite(redirSlide, 1, (extent)(n), stdout) == (extent)(n)) ? \ + 0 : PKDISK) +#endif +/* Warning: the fwrite above might not work on 16-bit compilers, since + 0x8000 might be interpreted as -32,768 by the library function. When + support for Deflate64 is enabled, the window size is 64K and the + simple fwrite statement is definitely broken for 16-bit compilers. */ + +#ifndef Trace +# ifdef DEBUG +# define Trace(x) fprintf x +# else +# define Trace(x) +# endif +#endif + + +/*---------------------------------------------------------------------------*/ +#ifdef USE_ZLIB + +/* Beginning with zlib version 1.2.0, a new inflate callback interface is + provided that allows tighter integration of the zlib inflate service + into unzip's extraction framework. + The advantages are: + - uses the windows buffer supplied by the unzip code; this saves one + copy process between zlib's internal decompression buffer and unzip's + post-decompression output buffer and improves performance. + - does not pull in unused checksum code (adler32). + The preprocessor flag NO_ZLIBCALLBCK can be set to force usage of the + old zlib 1.1.x interface, for testing purpose. + */ +#ifdef USE_ZLIB_INFLATCB +# undef USE_ZLIB_INFLATCB +#endif +#if (defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1200 && !defined(NO_ZLIBCALLBCK)) +# define USE_ZLIB_INFLATCB 1 +#else +# define USE_ZLIB_INFLATCB 0 +#endif + +/* Check for incompatible combinations of zlib and Deflate64 support. */ +#if defined(USE_DEFLATE64) +# if !USE_ZLIB_INFLATCB + #error Deflate64 is incompatible with traditional (pre-1.2.x) zlib interface! +# else + /* The Deflate64 callback function in the framework of zlib 1.2.x requires + the inclusion of the unsupported infback9 header file: + */ +# include "infback9.h" +# endif +#endif /* USE_DEFLATE64 */ + + +#if USE_ZLIB_INFLATCB + +static unsigned zlib_inCB OF((void FAR *pG, unsigned char FAR * FAR * pInbuf)); +static int zlib_outCB OF((void FAR *pG, unsigned char FAR *outbuf, + unsigned outcnt)); + +static unsigned zlib_inCB(pG, pInbuf) + void FAR *pG; + unsigned char FAR * FAR * pInbuf; +{ + *pInbuf = G.inbuf; + return fillinbuf(__G); +} + +static int zlib_outCB(pG, outbuf, outcnt) + void FAR *pG; + unsigned char FAR *outbuf; + unsigned outcnt; +{ +#ifdef FUNZIP + return flush(__G__ (ulg)(outcnt)); +#else + return ((G.mem_mode) ? memflush(__G__ outbuf, (ulg)(outcnt)) + : flush(__G__ outbuf, (ulg)(outcnt), 0)); +#endif +} +#endif /* USE_ZLIB_INFLATCB */ + + +/* + GRR: return values for both original inflate() and UZinflate() + 0 OK + 1 incomplete table(?) + 2 bad input + 3 not enough memory + */ + +/**************************/ +/* Function UZinflate() */ +/**************************/ + +int UZinflate(__G__ is_defl64) + __GDEF + int is_defl64; +/* decompress an inflated entry using the zlib routines */ +{ + int retval = 0; /* return code: 0 = "no error" */ + int err=Z_OK; +#if USE_ZLIB_INFLATCB + +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) + wsize = G.redirect_size, redirSlide = G.redirect_buffer; + else + wsize = WSIZE, redirSlide = slide; +#endif + + if (!G.inflInit) { + /* local buffer for efficiency */ + ZCONST char *zlib_RtVersion = zlibVersion(); + + /* only need to test this stuff once */ + if ((zlib_RtVersion[0] != ZLIB_VERSION[0]) || + (zlib_RtVersion[2] != ZLIB_VERSION[2])) { + Info(slide, 0x21, ((char *)slide, + "error: incompatible zlib version (expected %s, found %s)\n", + ZLIB_VERSION, zlib_RtVersion)); + return 3; + } else if (strcmp(zlib_RtVersion, ZLIB_VERSION) != 0) + Info(slide, 0x21, ((char *)slide, + "warning: different zlib version (expected %s, using %s)\n", + ZLIB_VERSION, zlib_RtVersion)); + + G.dstrm.zalloc = (alloc_func)Z_NULL; + G.dstrm.zfree = (free_func)Z_NULL; + + G.inflInit = 1; + } + +#ifdef USE_DEFLATE64 + if (is_defl64) + { + Trace((stderr, "initializing inflate9()\n")); + err = inflateBack9Init(&G.dstrm, redirSlide); + + if (err == Z_MEM_ERROR) + return 3; + else if (err != Z_OK) { + Trace((stderr, "oops! (inflateBack9Init() err = %d)\n", err)); + return 2; + } + + G.dstrm.next_in = G.inptr; + G.dstrm.avail_in = G.incnt; + + err = inflateBack9(&G.dstrm, zlib_inCB, &G, zlib_outCB, &G); + if (err != Z_STREAM_END) { + if (err == Z_DATA_ERROR || err == Z_STREAM_ERROR) { + Trace((stderr, "oops! (inflateBack9() err = %d)\n", err)); + retval = 2; + } else if (err == Z_MEM_ERROR) { + retval = 3; + } else if (err == Z_BUF_ERROR) { + Trace((stderr, "oops! (inflateBack9() err = %d)\n", err)); + if (G.dstrm.next_in == Z_NULL) { + /* input failure */ + Trace((stderr, " inflateBack9() input failure\n")); + retval = 2; + } else { + /* output write failure */ + retval = (G.disk_full != 0 ? PK_DISK : IZ_CTRLC); + } + } else { + Trace((stderr, "oops! (inflateBack9() err = %d)\n", err)); + retval = 2; + } + } + if (G.dstrm.next_in != NULL) { + G.inptr = (uch *)G.dstrm.next_in; + G.incnt = G.dstrm.avail_in; + } + + err = inflateBack9End(&G.dstrm); + if (err != Z_OK) { + Trace((stderr, "oops! (inflateBack9End() err = %d)\n", err)); + if (retval == 0) + retval = 2; + } + } + else +#endif /* USE_DEFLATE64 */ + { + /* For the callback interface, inflate initialization has to + be called before each decompression call. + */ + { + unsigned i; + int windowBits; + /* windowBits = log2(wsize) */ + for (i = (unsigned)wsize, windowBits = 0; + !(i & 1); i >>= 1, ++windowBits); + if ((unsigned)windowBits > (unsigned)15) + windowBits = 15; + else if (windowBits < 8) + windowBits = 8; + + Trace((stderr, "initializing inflate()\n")); + err = inflateBackInit(&G.dstrm, windowBits, redirSlide); + + if (err == Z_MEM_ERROR) + return 3; + else if (err != Z_OK) { + Trace((stderr, "oops! (inflateBackInit() err = %d)\n", err)); + return 2; + } + } + + G.dstrm.next_in = G.inptr; + G.dstrm.avail_in = G.incnt; + + err = inflateBack(&G.dstrm, zlib_inCB, &G, zlib_outCB, &G); + if (err != Z_STREAM_END) { + if (err == Z_DATA_ERROR || err == Z_STREAM_ERROR) { + Trace((stderr, "oops! (inflateBack() err = %d)\n", err)); + retval = 2; + } else if (err == Z_MEM_ERROR) { + retval = 3; + } else if (err == Z_BUF_ERROR) { + Trace((stderr, "oops! (inflateBack() err = %d)\n", err)); + if (G.dstrm.next_in == Z_NULL) { + /* input failure */ + Trace((stderr, " inflateBack() input failure\n")); + retval = 2; + } else { + /* output write failure */ + retval = (G.disk_full != 0 ? PK_DISK : IZ_CTRLC); + } + } else { + Trace((stderr, "oops! (inflateBack() err = %d)\n", err)); + retval = 2; + } + } + if (G.dstrm.next_in != NULL) { + G.inptr = (uch *)G.dstrm.next_in; + G.incnt = G.dstrm.avail_in; + } + + err = inflateBackEnd(&G.dstrm); + if (err != Z_OK) { + Trace((stderr, "oops! (inflateBackEnd() err = %d)\n", err)); + if (retval == 0) + retval = 2; + } + } + +#else /* !USE_ZLIB_INFLATCB */ + int repeated_buf_err; + +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) + wsize = G.redirect_size, redirSlide = G.redirect_buffer; + else + wsize = WSIZE, redirSlide = slide; +#endif + + G.dstrm.next_out = redirSlide; + G.dstrm.avail_out = wsize; + + G.dstrm.next_in = G.inptr; + G.dstrm.avail_in = G.incnt; + + if (!G.inflInit) { + unsigned i; + int windowBits; + /* local buffer for efficiency */ + ZCONST char *zlib_RtVersion = zlibVersion(); + + /* only need to test this stuff once */ + if (zlib_RtVersion[0] != ZLIB_VERSION[0]) { + Info(slide, 0x21, ((char *)slide, + "error: incompatible zlib version (expected %s, found %s)\n", + ZLIB_VERSION, zlib_RtVersion)); + return 3; + } else if (strcmp(zlib_RtVersion, ZLIB_VERSION) != 0) + Info(slide, 0x21, ((char *)slide, + "warning: different zlib version (expected %s, using %s)\n", + ZLIB_VERSION, zlib_RtVersion)); + + /* windowBits = log2(wsize) */ + for (i = (unsigned)wsize, windowBits = 0; + !(i & 1); i >>= 1, ++windowBits); + if ((unsigned)windowBits > (unsigned)15) + windowBits = 15; + else if (windowBits < 8) + windowBits = 8; + + G.dstrm.zalloc = (alloc_func)Z_NULL; + G.dstrm.zfree = (free_func)Z_NULL; + + Trace((stderr, "initializing inflate()\n")); + err = inflateInit2(&G.dstrm, -windowBits); + + if (err == Z_MEM_ERROR) + return 3; + else if (err != Z_OK) + Trace((stderr, "oops! (inflateInit2() err = %d)\n", err)); + G.inflInit = 1; + } + +#ifdef FUNZIP + while (err != Z_STREAM_END) { +#else /* !FUNZIP */ + while (G.csize > 0) { + Trace((stderr, "first loop: G.csize = %ld\n", G.csize)); +#endif /* ?FUNZIP */ + while (G.dstrm.avail_out > 0) { + err = inflate(&G.dstrm, Z_PARTIAL_FLUSH); + + if (err == Z_DATA_ERROR) { + retval = 2; goto uzinflate_cleanup_exit; + } else if (err == Z_MEM_ERROR) { + retval = 3; goto uzinflate_cleanup_exit; + } else if (err != Z_OK && err != Z_STREAM_END) + Trace((stderr, "oops! (inflate(first loop) err = %d)\n", err)); + +#ifdef FUNZIP + if (err == Z_STREAM_END) /* "END-of-entry-condition" ? */ +#else /* !FUNZIP */ + if (G.csize <= 0L) /* "END-of-entry-condition" ? */ +#endif /* ?FUNZIP */ + break; + + if (G.dstrm.avail_in == 0) { + if (fillinbuf(__G) == 0) { + /* no "END-condition" yet, but no more data */ + retval = 2; goto uzinflate_cleanup_exit; + } + + G.dstrm.next_in = G.inptr; + G.dstrm.avail_in = G.incnt; + } + Trace((stderr, " avail_in = %u\n", G.dstrm.avail_in)); + } + /* flush slide[] */ + if ((retval = FLUSH(wsize - G.dstrm.avail_out)) != 0) + goto uzinflate_cleanup_exit; + Trace((stderr, "inside loop: flushing %ld bytes (ptr diff = %ld)\n", + (long)(wsize - G.dstrm.avail_out), + (long)(G.dstrm.next_out-(Bytef *)redirSlide))); + G.dstrm.next_out = redirSlide; + G.dstrm.avail_out = wsize; + } + + /* no more input, so loop until we have all output */ + Trace((stderr, "beginning final loop: err = %d\n", err)); + repeated_buf_err = FALSE; + while (err != Z_STREAM_END) { + err = inflate(&G.dstrm, Z_PARTIAL_FLUSH); + if (err == Z_DATA_ERROR) { + retval = 2; goto uzinflate_cleanup_exit; + } else if (err == Z_MEM_ERROR) { + retval = 3; goto uzinflate_cleanup_exit; + } else if (err == Z_BUF_ERROR) { /* DEBUG */ +#ifdef FUNZIP + Trace((stderr, + "zlib inflate() did not detect stream end\n")); +#else + Trace((stderr, + "zlib inflate() did not detect stream end (%s, %s)\n", + G.zipfn, G.filename)); +#endif + if ((!repeated_buf_err) && (G.dstrm.avail_in == 0)) { + /* when detecting this problem for the first time, + try to provide one fake byte beyond "EOF"... */ + G.dstrm.next_in = ""; + G.dstrm.avail_in = 1; + repeated_buf_err = TRUE; + } else + break; + } else if (err != Z_OK && err != Z_STREAM_END) { + Trace((stderr, "oops! (inflate(final loop) err = %d)\n", err)); + DESTROYGLOBALS(); + EXIT(PK_MEM3); + } + /* final flush of slide[] */ + if ((retval = FLUSH(wsize - G.dstrm.avail_out)) != 0) + goto uzinflate_cleanup_exit; + Trace((stderr, "final loop: flushing %ld bytes (ptr diff = %ld)\n", + (long)(wsize - G.dstrm.avail_out), + (long)(G.dstrm.next_out-(Bytef *)redirSlide))); + G.dstrm.next_out = redirSlide; + G.dstrm.avail_out = wsize; + } + Trace((stderr, "total in = %lu, total out = %lu\n", G.dstrm.total_in, + G.dstrm.total_out)); + + G.inptr = (uch *)G.dstrm.next_in; + G.incnt = (G.inbuf + INBUFSIZ) - G.inptr; /* reset for other routines */ + +uzinflate_cleanup_exit: + err = inflateReset(&G.dstrm); + if (err != Z_OK) + Trace((stderr, "oops! (inflateReset() err = %d)\n", err)); + +#endif /* ?USE_ZLIB_INFLATCB */ + return retval; +} + + +/*---------------------------------------------------------------------------*/ +#else /* !USE_ZLIB */ + + +/* Function prototypes */ +#ifndef OF +# ifdef __STDC__ +# define OF(a) a +# else +# define OF(a) () +# endif +#endif /* !OF */ +int inflate_codes OF((__GPRO__ struct huft *tl, struct huft *td, + unsigned bl, unsigned bd)); +static int inflate_stored OF((__GPRO)); +static int inflate_fixed OF((__GPRO)); +static int inflate_dynamic OF((__GPRO)); +static int inflate_block OF((__GPRO__ int *e)); + + +/* The inflate algorithm uses a sliding 32K byte window on the uncompressed + stream to find repeated byte strings. This is implemented here as a + circular buffer. The index is updated simply by incrementing and then + and'ing with 0x7fff (32K-1). */ +/* It is left to other modules to supply the 32K area. It is assumed + to be usable as if it were declared "uch slide[32768];" or as just + "uch *slide;" and then malloc'ed in the latter case. The definition + must be in unzip.h, included above. */ + + +/* unsigned wp; moved to globals.h */ /* current position in slide */ + +/* Tables for deflate from PKZIP's appnote.txt. */ +/* - Order of the bit length code lengths */ +static ZCONST unsigned border[] = { + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + +/* - Copy lengths for literal codes 257..285 */ +#ifdef USE_DEFLATE64 +static ZCONST ush cplens64[] = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 3, 0, 0}; + /* For Deflate64, the code 285 is defined differently. */ +#else +# define cplens32 cplens +#endif +static ZCONST ush cplens32[] = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* note: see note #13 above about the 258 in this list. */ +/* - Extra bits for literal codes 257..285 */ +#ifdef USE_DEFLATE64 +static ZCONST uch cplext64[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 16, INVALID_CODE, INVALID_CODE}; +#else +# define cplext32 cplext +#endif +static ZCONST uch cplext32[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, INVALID_CODE, INVALID_CODE}; + +/* - Copy offsets for distance codes 0..29 (0..31 for Deflate64) */ +static ZCONST ush cpdist[] = { + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, +#if (defined(USE_DEFLATE64) || defined(PKZIP_BUG_WORKAROUND)) + 8193, 12289, 16385, 24577, 32769, 49153}; +#else + 8193, 12289, 16385, 24577}; +#endif + +/* - Extra bits for distance codes 0..29 (0..31 for Deflate64) */ +#ifdef USE_DEFLATE64 +static ZCONST uch cpdext64[] = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13, 14, 14}; +#else +# define cpdext32 cpdext +#endif +static ZCONST uch cpdext32[] = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, +#ifdef PKZIP_BUG_WORKAROUND + 12, 12, 13, 13, INVALID_CODE, INVALID_CODE}; +#else + 12, 12, 13, 13}; +#endif + +#ifdef PKZIP_BUG_WORKAROUND +# define MAXLITLENS 288 +#else +# define MAXLITLENS 286 +#endif +#if (defined(USE_DEFLATE64) || defined(PKZIP_BUG_WORKAROUND)) +# define MAXDISTS 32 +#else +# define MAXDISTS 30 +#endif + + +/* moved to consts.h (included in unzip.c), resp. funzip.c */ +#if 0 +/* And'ing with mask_bits[n] masks the lower n bits */ +ZCONST unsigned near mask_bits[17] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; +#endif /* 0 */ + + +/* Macros for inflate() bit peeking and grabbing. + The usage is: + + NEEDBITS(j) + x = b & mask_bits[j]; + DUMPBITS(j) + + where NEEDBITS makes sure that b has at least j bits in it, and + DUMPBITS removes the bits from b. The macros use the variable k + for the number of bits in b. Normally, b and k are register + variables for speed and are initialized at the beginning of a + routine that uses these macros from a global bit buffer and count. + + In order to not ask for more bits than there are in the compressed + stream, the Huffman tables are constructed to only ask for just + enough bits to make up the end-of-block code (value 256). Then no + bytes need to be "returned" to the buffer at the end of the last + block. See the huft_build() routine. + + Actually, the precautions mentioned above are not sufficient to + prevent fetches of bits beyound the end of the last block in every + case. When the last code fetched before the end-of-block code was + a very short distance code (shorter than "distance-prefetch-bits" - + "end-of-block code bits"), this last distance code fetch already + exausts the available data. To prevent failure of extraction in this + case, the "read beyond EOF" check delays the raise of the "invalid + data" error until an actual overflow of "used data" is detected. + This error condition is only fulfilled when the "number of available + bits" counter k is found to be negative in the NEEDBITS() macro. + + An alternate fix for that problem adjusts the size of the distance code + base table so that it does not exceed the length of the end-of-block code + plus the minimum length of a distance code. This alternate fix can be + enabled by defining the preprocessor symbol FIX_PAST_EOB_BY_TABLEADJUST. + */ + +/* These have been moved to globals.h */ +#if 0 +ulg bb; /* bit buffer */ +unsigned bk; /* bits in bit buffer */ +#endif + +#ifndef CHECK_EOF +# define CHECK_EOF /* default as of 5.13/5.2 */ +#endif + +#ifndef CHECK_EOF +# define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<=0)break;retval=1;goto cleanup_and_exit;}\ + b|=((ulg)c)<>=(n);k-=(n);} + + +/* + Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + are not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the requested + table size, in which case the length of the shortest code in bits is + used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. + */ + + +/* bits in base literal/length lookup table */ +static ZCONST unsigned lbits = 9; +/* bits in base distance lookup table */ +static ZCONST unsigned dbits = 6; + + +#ifndef ASM_INFLATECODES + +int inflate_codes(__G__ tl, td, bl, bd) + __GDEF +struct huft *tl, *td; /* literal/length and distance decoder tables */ +unsigned bl, bd; /* number of bits decoded by tl[] and td[] */ +/* inflate (decompress) the codes in a deflated (compressed) block. + Return an error code or zero if it all goes ok. */ +{ + register unsigned e; /* table entry flag/number of extra bits */ + unsigned d; /* index for copy */ + UINT_D64 n; /* length for copy (deflate64: might be 64k+2) */ + UINT_D64 w; /* current window position (deflate64: up to 64k) */ + struct huft *t; /* pointer to table entry */ + unsigned ml, md; /* masks for bl and bd bits */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + int retval = 0; /* error code returned: initialized to "no error" */ + + + /* make local copies of globals */ + b = G.bb; /* initialize bit buffer */ + k = G.bk; + w = G.wp; /* initialize window position */ + + + /* inflate the coded data */ + ml = mask_bits[bl]; /* precompute masks for speed */ + md = mask_bits[bd]; + while (1) /* do until end of block */ + { + NEEDBITS(bl) + t = tl + ((unsigned)b & ml); + while (1) { + DUMPBITS(t->b) + + if ((e = t->e) == 32) /* then it's a literal */ + { + redirSlide[w++] = (uch)t->v.n; + if (w == wsize) + { + if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit; + w = 0; + } + break; + } + + if (e < 31) /* then it's a length */ + { + /* get length of block to copy */ + NEEDBITS(e) + n = t->v.n + ((unsigned)b & mask_bits[e]); + DUMPBITS(e) + + /* decode distance of block to copy */ + NEEDBITS(bd) + t = td + ((unsigned)b & md); + while (1) { + DUMPBITS(t->b) + if ((e = t->e) < 32) + break; + if (IS_INVALID_CODE(e)) + return 1; + e &= 31; + NEEDBITS(e) + t = t->v.t + ((unsigned)b & mask_bits[e]); + } + NEEDBITS(e) + d = (unsigned)w - t->v.n - ((unsigned)b & mask_bits[e]); + DUMPBITS(e) + + /* do the copy */ + do { +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) { + /* &= w/ wsize unnecessary & wrong if redirect */ + if ((UINT_D64)d >= wsize) + return 1; /* invalid compressed data */ + e = (unsigned)(wsize - (d > (unsigned)w ? (UINT_D64)d : w)); + } + else +#endif + e = (unsigned)(wsize - + ((d &= (unsigned)(wsize-1)) > (unsigned)w ? + (UINT_D64)d : w)); + if ((UINT_D64)e > n) e = (unsigned)n; + n -= e; +#ifndef NOMEMCPY + if ((unsigned)w - d >= e) + /* (this test assumes unsigned comparison) */ + { + memcpy(redirSlide + (unsigned)w, redirSlide + d, e); + w += e; + d += e; + } + else /* do it slowly to avoid memcpy() overlap */ +#endif /* !NOMEMCPY */ + do { + redirSlide[w++] = redirSlide[d++]; + } while (--e); + if (w == wsize) + { + if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit; + w = 0; + } + } while (n); + break; + } + + if (e == 31) /* it's the EOB signal */ + { + /* sorry for this goto, but we have to exit two loops at once */ + goto cleanup_decode; + } + + if (IS_INVALID_CODE(e)) + return 1; + + e &= 31; + NEEDBITS(e) + t = t->v.t + ((unsigned)b & mask_bits[e]); + } + } +cleanup_decode: + + /* restore the globals from the locals */ + G.wp = (unsigned)w; /* restore global window pointer */ + G.bb = b; /* restore global bit buffer */ + G.bk = k; + + +cleanup_and_exit: + /* done */ + return retval; +} + +#endif /* ASM_INFLATECODES */ + + + +static int inflate_stored(__G) + __GDEF +/* "decompress" an inflated type 0 (stored) block. */ +{ + UINT_D64 w; /* current window position (deflate64: up to 64k!) */ + unsigned n; /* number of bytes in block */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + int retval = 0; /* error code returned: initialized to "no error" */ + + + /* make local copies of globals */ + Trace((stderr, "\nstored block")); + b = G.bb; /* initialize bit buffer */ + k = G.bk; + w = G.wp; /* initialize window position */ + + + /* go to byte boundary */ + n = k & 7; + DUMPBITS(n); + + + /* get the length and its complement */ + NEEDBITS(16) + n = ((unsigned)b & 0xffff); + DUMPBITS(16) + NEEDBITS(16) + if (n != (unsigned)((~b) & 0xffff)) + return 1; /* error in compressed data */ + DUMPBITS(16) + + + /* read and output the compressed data */ + while (n--) + { + NEEDBITS(8) + redirSlide[w++] = (uch)b; + if (w == wsize) + { + if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit; + w = 0; + } + DUMPBITS(8) + } + + + /* restore the globals from the locals */ + G.wp = (unsigned)w; /* restore global window pointer */ + G.bb = b; /* restore global bit buffer */ + G.bk = k; + +cleanup_and_exit: + return retval; +} + + +/* Globals for literal tables (built once) */ +/* Moved to globals.h */ +#if 0 +struct huft *fixed_tl = (struct huft *)NULL; +struct huft *fixed_td; +int fixed_bl, fixed_bd; +#endif + +static int inflate_fixed(__G) + __GDEF +/* decompress an inflated type 1 (fixed Huffman codes) block. We should + either replace this with a custom decoder, or at least precompute the + Huffman tables. */ +{ + /* if first time, set up tables for fixed blocks */ + Trace((stderr, "\nliteral block")); + if (G.fixed_tl == (struct huft *)NULL) + { + int i; /* temporary variable */ + unsigned l[288]; /* length list for huft_build */ + + /* literal table */ + for (i = 0; i < 144; i++) + l[i] = 8; + for (; i < 256; i++) + l[i] = 9; + for (; i < 280; i++) + l[i] = 7; + for (; i < 288; i++) /* make a complete, but wrong code set */ + l[i] = 8; + G.fixed_bl = 7; +#ifdef USE_DEFLATE64 + if ((i = huft_build(__G__ l, 288, 257, G.cplens, G.cplext, + &G.fixed_tl, &G.fixed_bl)) != 0) +#else + if ((i = huft_build(__G__ l, 288, 257, cplens, cplext, + &G.fixed_tl, &G.fixed_bl)) != 0) +#endif + { + G.fixed_tl = (struct huft *)NULL; + return i; + } + + /* distance table */ + for (i = 0; i < MAXDISTS; i++) /* make an incomplete code set */ + l[i] = 5; + G.fixed_bd = 5; +#ifdef USE_DEFLATE64 + if ((i = huft_build(__G__ l, MAXDISTS, 0, cpdist, G.cpdext, + &G.fixed_td, &G.fixed_bd)) > 1) +#else + if ((i = huft_build(__G__ l, MAXDISTS, 0, cpdist, cpdext, + &G.fixed_td, &G.fixed_bd)) > 1) +#endif + { + huft_free(G.fixed_tl); + G.fixed_td = G.fixed_tl = (struct huft *)NULL; + return i; + } + } + + /* decompress until an end-of-block code */ + return inflate_codes(__G__ G.fixed_tl, G.fixed_td, + G.fixed_bl, G.fixed_bd); +} + + + +static int inflate_dynamic(__G) + __GDEF +/* decompress an inflated type 2 (dynamic Huffman codes) block. */ +{ + unsigned i; /* temporary variables */ + unsigned j; + unsigned l; /* last length */ + unsigned m; /* mask for bit lengths table */ + unsigned n; /* number of lengths to get */ + struct huft *tl = (struct huft *)NULL; /* literal/length code table */ + struct huft *td = (struct huft *)NULL; /* distance code table */ + struct huft *th; /* temp huft table pointer used in tables decoding */ + unsigned bl; /* lookup bits for tl */ + unsigned bd; /* lookup bits for td */ + unsigned nb; /* number of bit length codes */ + unsigned nl; /* number of literal/length codes */ + unsigned nd; /* number of distance codes */ + unsigned ll[MAXLITLENS+MAXDISTS]; /* lit./length and distance code lengths */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + int retval = 0; /* error code returned: initialized to "no error" */ + + + /* make local bit buffer */ + Trace((stderr, "\ndynamic block")); + b = G.bb; + k = G.bk; + + + /* read in table lengths */ + NEEDBITS(5) + nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */ + DUMPBITS(5) + NEEDBITS(5) + nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */ + DUMPBITS(5) + NEEDBITS(4) + nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */ + DUMPBITS(4) + if (nl > MAXLITLENS || nd > MAXDISTS) + return 1; /* bad lengths */ + + + /* read in bit-length-code lengths */ + for (j = 0; j < nb; j++) + { + NEEDBITS(3) + ll[border[j]] = (unsigned)b & 7; + DUMPBITS(3) + } + for (; j < 19; j++) + ll[border[j]] = 0; + + + /* build decoding table for trees--single level, 7 bit lookup */ + bl = 7; + retval = huft_build(__G__ ll, 19, 19, NULL, NULL, &tl, &bl); + if (bl == 0) /* no bit lengths */ + retval = 1; + if (retval) + { + if (retval == 1) + huft_free(tl); + return retval; /* incomplete code set */ + } + + + /* read in literal and distance code lengths */ + n = nl + nd; + m = mask_bits[bl]; + i = l = 0; + while (i < n) + { + NEEDBITS(bl) + j = (th = tl + ((unsigned)b & m))->b; + DUMPBITS(j) + j = th->v.n; + if (j < 16) /* length of code in bits (0..15) */ + ll[i++] = l = j; /* save last length in l */ + else if (j == 16) /* repeat last length 3 to 6 times */ + { + NEEDBITS(2) + j = 3 + ((unsigned)b & 3); + DUMPBITS(2) + if ((unsigned)i + j > n) { + huft_free(tl); + return 1; + } + while (j--) + ll[i++] = l; + } + else if (j == 17) /* 3 to 10 zero length codes */ + { + NEEDBITS(3) + j = 3 + ((unsigned)b & 7); + DUMPBITS(3) + if ((unsigned)i + j > n) { + huft_free(tl); + return 1; + } + while (j--) + ll[i++] = 0; + l = 0; + } + else /* j == 18: 11 to 138 zero length codes */ + { + NEEDBITS(7) + j = 11 + ((unsigned)b & 0x7f); + DUMPBITS(7) + if ((unsigned)i + j > n) { + huft_free(tl); + return 1; + } + while (j--) + ll[i++] = 0; + l = 0; + } + } + + + /* free decoding table for trees */ + huft_free(tl); + + + /* restore the global bit buffer */ + G.bb = b; + G.bk = k; + + + /* build the decoding tables for literal/length and distance codes */ + bl = lbits; +#ifdef USE_DEFLATE64 + retval = huft_build(__G__ ll, nl, 257, G.cplens, G.cplext, &tl, &bl); +#else + retval = huft_build(__G__ ll, nl, 257, cplens, cplext, &tl, &bl); +#endif + if (bl == 0) /* no literals or lengths */ + retval = 1; + if (retval) + { + if (retval == 1) { + if (!uO.qflag) + MESSAGE((uch *)"(incomplete l-tree) ", 21L, 1); + huft_free(tl); + } + return retval; /* incomplete code set */ + } +#ifdef FIX_PAST_EOB_BY_TABLEADJUST + /* Adjust the requested distance base table size so that a distance code + fetch never tries to get bits behind an immediatly following end-of-block + code. */ + bd = (dbits <= bl+1 ? dbits : bl+1); +#else + bd = dbits; +#endif +#ifdef USE_DEFLATE64 + retval = huft_build(__G__ ll + nl, nd, 0, cpdist, G.cpdext, &td, &bd); +#else + retval = huft_build(__G__ ll + nl, nd, 0, cpdist, cpdext, &td, &bd); +#endif +#ifdef PKZIP_BUG_WORKAROUND + if (retval == 1) + retval = 0; +#endif + if (bd == 0 && nl > 257) /* lengths but no distances */ + retval = 1; + if (retval) + { + if (retval == 1) { + if (!uO.qflag) + MESSAGE((uch *)"(incomplete d-tree) ", 21L, 1); + huft_free(td); + } + huft_free(tl); + return retval; + } + + /* decompress until an end-of-block code */ + retval = inflate_codes(__G__ tl, td, bl, bd); + +cleanup_and_exit: + /* free the decoding tables, return */ + if (tl != (struct huft *)NULL) + huft_free(tl); + if (td != (struct huft *)NULL) + huft_free(td); + return retval; +} + + + +static int inflate_block(__G__ e) + __GDEF + int *e; /* last block flag */ +/* decompress an inflated block */ +{ + unsigned t; /* block type */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + int retval = 0; /* error code returned: initialized to "no error" */ + + + /* make local bit buffer */ + b = G.bb; + k = G.bk; + + + /* read in last block bit */ + NEEDBITS(1) + *e = (int)b & 1; + DUMPBITS(1) + + + /* read in block type */ + NEEDBITS(2) + t = (unsigned)b & 3; + DUMPBITS(2) + + + /* restore the global bit buffer */ + G.bb = b; + G.bk = k; + + + /* inflate that block type */ + if (t == 2) + return inflate_dynamic(__G); + if (t == 0) + return inflate_stored(__G); + if (t == 1) + return inflate_fixed(__G); + + + /* bad block type */ + retval = 2; + +cleanup_and_exit: + return retval; +} + + + +int inflate(__G__ is_defl64) + __GDEF + int is_defl64; +/* decompress an inflated entry */ +{ + int e; /* last block flag */ + int r; /* result code */ +#ifdef DEBUG + unsigned h = 0; /* maximum struct huft's malloc'ed */ +#endif + +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) + wsize = G.redirect_size, redirSlide = G.redirect_buffer; + else + wsize = WSIZE, redirSlide = slide; /* how they're #defined if !DLL */ +#endif + + /* initialize window, bit buffer */ + G.wp = 0; + G.bk = 0; + G.bb = 0; + +#ifdef USE_DEFLATE64 + if (is_defl64) { + G.cplens = cplens64; + G.cplext = cplext64; + G.cpdext = cpdext64; + G.fixed_tl = G.fixed_tl64; + G.fixed_bl = G.fixed_bl64; + G.fixed_td = G.fixed_td64; + G.fixed_bd = G.fixed_bd64; + } else { + G.cplens = cplens32; + G.cplext = cplext32; + G.cpdext = cpdext32; + G.fixed_tl = G.fixed_tl32; + G.fixed_bl = G.fixed_bl32; + G.fixed_td = G.fixed_td32; + G.fixed_bd = G.fixed_bd32; + } +#else /* !USE_DEFLATE64 */ + if (is_defl64) { + /* This should not happen unless UnZip is built from object files + * compiled with inconsistent option setting. Handle this by + * returning with "bad input" error code. + */ + Trace((stderr, "\nThis inflate() cannot handle Deflate64!\n")); + return 2; + } +#endif /* ?USE_DEFLATE64 */ + + /* decompress until the last block */ + do { +#ifdef DEBUG + G.hufts = 0; +#endif + if ((r = inflate_block(__G__ &e)) != 0) + return r; +#ifdef DEBUG + if (G.hufts > h) + h = G.hufts; +#endif + } while (!e); + + Trace((stderr, "\n%u bytes in Huffman tables (%u/entry)\n", + h * (unsigned)sizeof(struct huft), (unsigned)sizeof(struct huft))); + +#ifdef USE_DEFLATE64 + if (is_defl64) { + G.fixed_tl64 = G.fixed_tl; + G.fixed_bl64 = G.fixed_bl; + G.fixed_td64 = G.fixed_td; + G.fixed_bd64 = G.fixed_bd; + } else { + G.fixed_tl32 = G.fixed_tl; + G.fixed_bl32 = G.fixed_bl; + G.fixed_td32 = G.fixed_td; + G.fixed_bd32 = G.fixed_bd; + } +#endif + + /* flush out redirSlide and return (success, unless final FLUSH failed) */ + return (FLUSH(G.wp)); +} + + + +int inflate_free(__G) + __GDEF +{ + if (G.fixed_tl != (struct huft *)NULL) + { + huft_free(G.fixed_td); + huft_free(G.fixed_tl); + G.fixed_td = G.fixed_tl = (struct huft *)NULL; + } + return 0; +} + +#endif /* ?USE_ZLIB */ + + +/* + * GRR: moved huft_build() and huft_free() down here; used by explode() + * and fUnZip regardless of whether USE_ZLIB defined or not + */ + + +/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ +#define BMAX 16 /* maximum bit length of any code (16 for explode) */ +#define N_MAX 288 /* maximum number of codes in any set */ + + +int huft_build(__G__ b, n, s, d, e, t, m) + __GDEF + ZCONST unsigned *b; /* code lengths in bits (all assumed <= BMAX) */ + unsigned n; /* number of codes (assumed <= N_MAX) */ + unsigned s; /* number of simple-valued codes (0..s-1) */ + ZCONST ush *d; /* list of base values for non-simple codes */ + ZCONST uch *e; /* list of extra bits for non-simple codes */ + struct huft **t; /* result: starting table */ + unsigned *m; /* maximum lookup bits, returns actual */ +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return zero on success, one if + the given code set is incomplete (the tables are still built in this + case), two if the input is invalid (all zero length codes or an + oversubscribed set of lengths), and three if not enough memory. + The code with value 256 is special, and the tables are constructed + so that no bits beyond that code are fetched when that code is + decoded. */ +{ + unsigned a; /* counter for codes of length k */ + unsigned c[BMAX+1]; /* bit length count table */ + unsigned el; /* length of EOB code (value 256) */ + unsigned f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register unsigned i; /* counter, current code */ + register unsigned j; /* counter */ + register int k; /* number of bits in current code */ + int lx[BMAX+1]; /* memory for l[-1..BMAX-1] */ + int *l = lx+1; /* stack of bits per table */ + register unsigned *p; /* pointer into c[], b[], or v[] */ + register struct huft *q; /* points to current table */ + struct huft r; /* table entry for structure assignment */ + struct huft *u[BMAX]; /* table stack */ + unsigned v[N_MAX]; /* values in order of bit length */ + register int w; /* bits before this table == (l * h) */ + unsigned x[BMAX+1]; /* bit offsets, then code stack */ + unsigned *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + unsigned z; /* number of entries in current table */ + + + /* Generate counts for each bit length */ + el = n > 256 ? b[256] : BMAX; /* set length of EOB code, if any */ + memzero((char *)c, sizeof(c)); + p = (unsigned *)b; i = n; + do { + c[*p]++; p++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (struct huft *)NULL; + *m = 0; + return 0; + } + + + /* Find minimum and maximum length, bound *m by those */ + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if (*m < j) + *m = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if (*m > i) + *m = i; + + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return 2; /* bad input: more codes than bits */ + if ((y -= c[i]) < 0) + return 2; + c[i] += y; + + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + + /* Make a table of values in order of bit lengths */ + memzero((char *)v, sizeof(v)); + p = (unsigned *)b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + n = x[g]; /* set n to length of v */ + + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = l[-1] = 0; /* no bits decoded yet */ + u[0] = (struct huft *)NULL; /* just to keep compilers happy */ + q = (struct huft *)NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l[h]) + { + w += l[h++]; /* add bits already decoded */ + + /* compute minimum size table less than or equal to *m bits */ + z = (z = g - w) > *m ? *m : z; /* upper limit */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + if ((unsigned)w + j > el && (unsigned)w < el) + j = el - w; /* make EOB code end at table */ + z = 1 << j; /* table entries for j-bit table */ + l[h] = j; /* set table size in stack */ + + /* allocate and link in new table */ + if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) == + (struct huft *)NULL) + { + if (h) + huft_free(u[0]); + return 3; /* not enough memory */ + } +#ifdef DEBUG + G.hufts += z + 1; /* track memory usage */ +#endif + *t = q + 1; /* link to list for huft_free() */ + *(t = &(q->v.t)) = (struct huft *)NULL; + u[h] = ++q; /* table starts after link */ + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.b = (uch)l[h-1]; /* bits to dump before this table */ + r.e = (uch)(32 + j); /* bits in this table */ + r.v.t = q; /* pointer to this table */ + j = (i & ((1 << w) - 1)) >> (w - l[h-1]); + u[h-1][j] = r; /* connect to last table */ + } + } + + /* set up table entry in r */ + r.b = (uch)(k - w); + if (p >= v + n) + r.e = INVALID_CODE; /* out of values--invalid code */ + else if (*p < s) + { + r.e = (uch)(*p < 256 ? 32 : 31); /* 256 is end-of-block code */ + r.v.n = (ush)*p++; /* simple code is just the value */ + } + else + { + r.e = e[*p - s]; /* non-simple--look up in lists */ + r.v.n = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != x[h]) + w -= l[--h]; /* don't need to update q */ + } + } + + + /* return actual size of base table */ + *m = l[0]; + + + /* Return true (1) if we were given an incomplete table */ + return y != 0 && g != 1; +} + + + +int huft_free(t) +struct huft *t; /* table to free */ +/* Free the malloc'ed tables built by huft_build(), which makes a linked + list of the tables it made, with the links in a dummy first entry of + each table. */ +{ + register struct huft *p, *q; + + + /* Go through linked list, freeing from the malloced (t[-1]) address. */ + p = t; + while (p != (struct huft *)NULL) + { + q = (--p)->v.t; + free((zvoid *)p); + p = q; + } + return 0; +} diff --git a/inflate.h b/inflate.h new file mode 100644 index 0000000..9ce48af --- /dev/null +++ b/inflate.h @@ -0,0 +1,39 @@ +/* + 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 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 +*/ +/* inflate.h for UnZip -- by Mark Adler + version c14f, 23 November 1995 */ + + +/* Copyright history: + - Starting with UnZip 5.41 of 16-April-2000, this source file + is covered by the Info-Zip LICENSE cited above. + - Prior versions of this source file, found in UnZip source packages + up to UnZip 5.40, were put in the public domain. + The original copyright note by Mark Adler was: + "You can do whatever you like with this source file, + though I would prefer that if you modify it and + redistribute it that you include comments to that effect + with your name and the date. Thank you." + + History: + vers date who what + ---- --------- -------------- ------------------------------------ + c14 12 Mar 93 M. Adler made inflate.c standalone with the + introduction of inflate.h. + c14d 28 Aug 93 G. Roelofs replaced flush/FlushOutput with new version + c14e 29 Sep 93 G. Roelofs moved everything into unzip.h; added crypt.h + c14f 23 Nov 95 G. Roelofs added UNZIP_INTERNAL to accommodate newly + split unzip.h + */ + +#define UNZIP_INTERNAL +#include "unzip.h" /* provides slide[], typedefs and macros */ +#ifdef FUNZIP +# include "crypt.h" /* provides NEXTBYTE macro for crypt version of funzip */ +#endif diff --git a/list.c b/list.c new file mode 100644 index 0000000..15e0011 --- /dev/null +++ b/list.c @@ -0,0 +1,733 @@ +/* + Copyright (c) 1990-2009 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2009-Jan-02 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 +*/ +/*--------------------------------------------------------------------------- + + list.c + + This file contains the non-ZipInfo-specific listing routines for UnZip. + + Contains: list_files() + get_time_stamp() [optional feature] + ratio() + fnprint() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" +#ifdef WINDLL +# ifdef POCKET_UNZIP +# include "wince/intrface.h" +# else +# include "windll/windll.h" +# endif +#endif + + +#ifdef TIMESTAMP + static int fn_is_dir OF((__GPRO)); +#endif + +#ifndef WINDLL + static ZCONST char Far CompFactorStr[] = "%c%d%%"; + static ZCONST char Far CompFactor100[] = "100%%"; + +#ifdef OS2_EAS + static ZCONST char Far HeadersS[] = + " Length EAs ACLs Date Time Name"; + static ZCONST char Far HeadersS1[] = + "--------- --- ---- ---------- ----- ----"; +#else + static ZCONST char Far HeadersS[] = + " Length Date Time Name"; + static ZCONST char Far HeadersS1[] = + "--------- ---------- ----- ----"; +#endif + + static ZCONST char Far HeadersL[] = + " Length Method Size Cmpr Date Time CRC-32 Name"; + static ZCONST char Far HeadersL1[] = + "-------- ------ ------- ---- ---------- ----- -------- ----"; + static ZCONST char Far *Headers[][2] = + { {HeadersS, HeadersS1}, {HeadersL, HeadersL1} }; + + static ZCONST char Far CaseConversion[] = + "%s (\"^\" ==> case\n%s conversion)\n"; + static ZCONST char Far LongHdrStats[] = + "%s %-7s%s %4s %02u%c%02u%c%02u %02u:%02u %08lx %c"; + static ZCONST char Far LongFileTrailer[] = + "-------- ------- --- \ + -------\n%s %s %4s %lu file%s\n"; +#ifdef OS2_EAS + static ZCONST char Far ShortHdrStats[] = + "%s %6lu %6lu %02u%c%02u%c%02u %02u:%02u %c"; + static ZCONST char Far ShortFileTrailer[] = + "--------- ----- ----- \ + -------\n%s %6lu %6lu %lu file%s\n"; + static ZCONST char Far OS2ExtAttrTrailer[] = + "%lu file%s %lu bytes of OS/2 extended attributes attached.\n"; + static ZCONST char Far OS2ACLTrailer[] = + "%lu file%s %lu bytes of access control lists attached.\n"; +#else + static ZCONST char Far ShortHdrStats[] = + "%s %02u%c%02u%c%02u %02u:%02u %c"; + static ZCONST char Far ShortFileTrailer[] = + "--------- -------\n%s\ + %lu file%s\n"; +#endif /* ?OS2_EAS */ +#endif /* !WINDLL */ + + + + + +/*************************/ +/* Function list_files() */ +/*************************/ + +int list_files(__G) /* return PK-type error code */ + __GDEF +{ + int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL; +#ifndef WINDLL + char sgn, cfactorstr[10]; + int longhdr=(uO.vflag>1); +#endif + int date_format; + char dt_sepchar; + ulg members=0L; + zusz_t j; + unsigned methnum; +#ifdef USE_EF_UT_TIME + iztimes z_utime; + struct tm *t; +#endif + unsigned yr, mo, dy, hh, mm; + zusz_t csiz, tot_csize=0L, tot_ucsize=0L; +#ifdef OS2_EAS + ulg ea_size, tot_easize=0L, tot_eafiles=0L; + ulg acl_size, tot_aclsize=0L, tot_aclfiles=0L; +#endif + min_info info; + char methbuf[8]; + static ZCONST char dtype[]="NXFS"; /* see zi_short() */ + static ZCONST char Far method[NUM_METHODS+1][8] = + {"Stored", "Shrunk", "Reduce1", "Reduce2", "Reduce3", "Reduce4", + "Implode", "Token", "Defl:#", "Def64#", "ImplDCL", "BZip2", + "LZMA", "Terse", "IBMLZ77", "WavPack", "PPMd", "Unk:###"}; + + + +/*--------------------------------------------------------------------------- + Unlike extract_or_test_files(), this routine confines itself to the cen- + tral directory. Thus its structure is somewhat simpler, since we can do + just a single loop through the entire directory, listing files as we go. + + So to start off, print the heading line and then begin main loop through + the central directory. The results will look vaguely like the following: + + Length Method Size Ratio Date Time CRC-32 Name ("^" ==> case +-------- ------ ------- ----- ---- ---- ------ ---- conversion) + 44004 Implode 13041 71% 11-02-89 19:34 8b4207f7 Makefile.UNIX + 3438 Shrunk 2209 36% 09-15-90 14:07 a2394fd8 ^dos-file.ext + 16717 Defl:X 5252 69% 11-03-97 06:40 1ce0f189 WHERE +-------- ------- --- ------- + 64159 20502 68% 3 files + ---------------------------------------------------------------------------*/ + + G.pInfo = &info; + date_format = DATE_FORMAT; + dt_sepchar = DATE_SEPCHAR; + +#ifndef WINDLL + if (uO.qflag < 2) { + if (uO.L_flag) + Info(slide, 0, ((char *)slide, LoadFarString(CaseConversion), + LoadFarStringSmall(Headers[longhdr][0]), + LoadFarStringSmall2(Headers[longhdr][1]))); + else + Info(slide, 0, ((char *)slide, "%s\n%s\n", + LoadFarString(Headers[longhdr][0]), + LoadFarStringSmall(Headers[longhdr][1]))); + } +#endif /* !WINDLL */ + + for (j = 1L;;j++) { + + if (readbuf(__G__ G.sig, 4) == 0) + return PK_EOF; + if (memcmp(G.sig, central_hdr_sig, 4)) { /* is it a CentDir entry? */ + /* no new central directory entry + * -> is the number of processed entries compatible with the + * number of entries as stored in the end_central record? + */ + if (((j - 1) & + (ulg)(G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16)) + == (ulg)G.ecrec.total_entries_central_dir) + { + /* "j modulus 4T/64k" matches the reported 64/16-bit-unsigned + * number of directory entries -> probably, the regular + * end of the central directory has been reached + */ + break; + } else { + Info(slide, 0x401, + ((char *)slide, LoadFarString(CentSigMsg), j)); + Info(slide, 0x401, + ((char *)slide, LoadFarString(ReportMsg))); + return PK_BADERR; /* sig not found */ + } + } + /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag, ...: */ + if ((error = process_cdir_file_hdr(__G)) != PK_COOL) + return error; /* only PK_EOF defined */ + + /* + * We could DISPLAY the filename instead of storing (and possibly trun- + * cating, in the case of a very long name) and printing it, but that + * has the disadvantage of not allowing case conversion--and it's nice + * to be able to see in the listing precisely how you have to type each + * filename in order for unzip to consider it a match. Speaking of + * which, if member names were specified on the command line, check in + * with match() to see if the current file is one of them, and make a + * note of it if it is. + */ + + if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != + PK_COOL) /* ^--(uses pInfo->lcflag) */ + { + error_in_archive = error; + if (error > PK_WARN) /* fatal: can't continue */ + return error; + } + if (G.extra_field != (uch *)NULL) { + free(G.extra_field); + G.extra_field = (uch *)NULL; + } + if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) + != 0) + { + error_in_archive = error; + if (error > PK_WARN) /* fatal */ + return error; + } + if (!G.process_all_files) { /* check if specified on command line */ + unsigned i; + + if (G.filespecs == 0) + do_this_file = TRUE; + else { /* check if this entry matches an `include' argument */ + do_this_file = FALSE; + for (i = 0; i < G.filespecs; i++) + if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) { + do_this_file = TRUE; + break; /* found match, so stop looping */ + } + } + if (do_this_file) { /* check if this is an excluded file */ + for (i = 0; i < G.xfilespecs; i++) + if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) { + do_this_file = FALSE; /* ^-- ignore case in match */ + break; + } + } + } + /* + * If current file was specified on command line, or if no names were + * specified, do the listing for this file. Otherwise, get rid of the + * file comment and go back for the next file. + */ + + if (G.process_all_files || do_this_file) { + +#ifdef OS2DLL + /* this is used by UzpFileTree() to allow easy processing of lists + * of zip directory contents */ + if (G.processExternally) { + if ((G.processExternally)(G.filename, &G.crec)) + break; + ++members; + } else { +#endif +#ifdef OS2_EAS + { + uch *ef_ptr = G.extra_field; + int ef_size, ef_len = G.crec.extra_field_length; + ea_size = acl_size = 0; + + while (ef_len >= EB_HEADSIZE) { + ef_size = makeword(&ef_ptr[EB_LEN]); + switch (makeword(&ef_ptr[EB_ID])) { + case EF_OS2: + ea_size = makelong(&ef_ptr[EB_HEADSIZE]); + break; + case EF_ACL: + acl_size = makelong(&ef_ptr[EB_HEADSIZE]); + break; + } + ef_ptr += (ef_size + EB_HEADSIZE); + ef_len -= (ef_size + EB_HEADSIZE); + } + } +#endif +#ifdef USE_EF_UT_TIME + if (G.extra_field && +#ifdef IZ_CHECK_TZ + G.tz_is_valid && +#endif + (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1, + G.crec.last_mod_dos_datetime, &z_utime, NULL) + & EB_UT_FL_MTIME)) + { + TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7.0, Mac */ + t = localtime(&(z_utime.mtime)); + } else + t = (struct tm *)NULL; + if (t != (struct tm *)NULL) { + mo = (unsigned)(t->tm_mon + 1); + dy = (unsigned)(t->tm_mday); + yr = (unsigned)(t->tm_year + 1900); + hh = (unsigned)(t->tm_hour); + mm = (unsigned)(t->tm_min); + } else +#endif /* USE_EF_UT_TIME */ + { + yr = ((((unsigned)(G.crec.last_mod_dos_datetime >> 25) & 0x7f) + + 1980)); + mo = ((unsigned)(G.crec.last_mod_dos_datetime >> 21) & 0x0f); + dy = ((unsigned)(G.crec.last_mod_dos_datetime >> 16) & 0x1f); + hh = (((unsigned)G.crec.last_mod_dos_datetime >> 11) & 0x1f); + mm = (((unsigned)G.crec.last_mod_dos_datetime >> 5) & 0x3f); + } + /* permute date so it displays according to nat'l convention + * ('methnum' is not yet set, it is used as temporary buffer) */ + switch (date_format) { + case DF_YMD: + methnum = mo; + mo = yr; yr = dy; dy = methnum; + break; + case DF_DMY: + methnum = mo; + mo = dy; dy = methnum; + } + + csiz = G.crec.csize; + if (G.crec.general_purpose_bit_flag & 1) + csiz -= 12; /* if encrypted, don't count encryption header */ + if ((cfactor = ratio(G.crec.ucsize, csiz)) < 0) { +#ifndef WINDLL + sgn = '-'; +#endif + cfactor = (-cfactor + 5) / 10; + } else { +#ifndef WINDLL + sgn = ' '; +#endif + cfactor = (cfactor + 5) / 10; + } + + methnum = find_compr_idx(G.crec.compression_method); + zfstrcpy(methbuf, method[methnum]); + if (G.crec.compression_method == DEFLATED || + G.crec.compression_method == ENHDEFLATED) { + methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3]; + } else if (methnum >= NUM_METHODS) { + sprintf(&methbuf[4], "%03u", G.crec.compression_method); + } + +#if 0 /* GRR/Euro: add this? */ +#if defined(DOS_FLX_NLM_OS2_W32) || defined(THEOS) || defined(UNIX) + for (p = G.filename; *p; ++p) + if (!isprint(*p)) + *p = '?'; /* change non-printable chars to '?' */ +#endif /* DOS_FLX_NLM_OS2_W32 || THEOS || UNIX */ +#endif /* 0 */ + +#ifdef WINDLL + /* send data to application for formatting and printing */ + if (G.lpUserFunctions->SendApplicationMessage != NULL) + (*G.lpUserFunctions->SendApplicationMessage)(G.crec.ucsize, + csiz, (unsigned)cfactor, mo, dy, yr, hh, mm, + (char)(G.pInfo->lcflag ? '^' : ' '), + (LPCSTR)fnfilter(G.filename, slide, (WSIZE>>1)), + (LPCSTR)methbuf, G.crec.crc32, + (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' ')); + else if (G.lpUserFunctions->SendApplicationMessage_i32 != NULL) { + unsigned long ucsize_lo, csiz_lo; + unsigned long ucsize_hi=0L, csiz_hi=0L; + ucsize_lo = (unsigned long)(G.crec.ucsize); + csiz_lo = (unsigned long)(csiz); +#ifdef ZIP64_SUPPORT + ucsize_hi = (unsigned long)(G.crec.ucsize >> 32); + csiz_hi = (unsigned long)(csiz >> 32); +#endif /* ZIP64_SUPPORT */ + (*G.lpUserFunctions->SendApplicationMessage_i32)(ucsize_lo, + ucsize_hi, csiz_lo, csiz_hi, (unsigned)cfactor, + mo, dy, yr, hh, mm, + (char)(G.pInfo->lcflag ? '^' : ' '), + (LPCSTR)fnfilter(G.filename, slide, (WSIZE>>1)), + (LPCSTR)methbuf, G.crec.crc32, + (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' ')); + } +#else /* !WINDLL */ + if (cfactor == 100) + sprintf(cfactorstr, LoadFarString(CompFactor100)); + else + sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor); + if (longhdr) + Info(slide, 0, ((char *)slide, LoadFarString(LongHdrStats), + FmZofft(G.crec.ucsize, "8", "u"), methbuf, + FmZofft(csiz, "8", "u"), cfactorstr, + mo, dt_sepchar, dy, dt_sepchar, yr, hh, mm, + G.crec.crc32, (G.pInfo->lcflag? '^':' '))); + else +#ifdef OS2_EAS + Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats), + FmZofft(G.crec.ucsize, "9", "u"), ea_size, acl_size, + mo, dt_sepchar, dy, dt_sepchar, yr, hh, mm, + (G.pInfo->lcflag? '^':' '))); +#else + Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats), + FmZofft(G.crec.ucsize, "9", "u"), + mo, dt_sepchar, dy, dt_sepchar, yr, hh, mm, + (G.pInfo->lcflag? '^':' '))); +#endif + fnprint(__G); +#endif /* ?WINDLL */ + + if ((error = do_string(__G__ G.crec.file_comment_length, + QCOND? DISPL_8 : SKIP)) != 0) + { + error_in_archive = error; /* might be just warning */ + if (error > PK_WARN) /* fatal */ + return error; + } + tot_ucsize += G.crec.ucsize; + tot_csize += csiz; + ++members; +#ifdef OS2_EAS + if (ea_size) { + tot_easize += ea_size; + ++tot_eafiles; + } + if (acl_size) { + tot_aclsize += acl_size; + ++tot_aclfiles; + } +#endif +#ifdef OS2DLL + } /* end of "if (G.processExternally) {...} else {..." */ +#endif + } else { /* not listing this file */ + SKIP_(G.crec.file_comment_length) + } + } /* end for-loop (j: files in central directory) */ + +/*--------------------------------------------------------------------------- + Print footer line and totals (compressed size, uncompressed size, number + of members in zipfile). + ---------------------------------------------------------------------------*/ + + if (uO.qflag < 2 +#ifdef OS2DLL + && !G.processExternally +#endif + ) { + if ((cfactor = ratio(tot_ucsize, tot_csize)) < 0) { +#ifndef WINDLL + sgn = '-'; +#endif + cfactor = (-cfactor + 5) / 10; + } else { +#ifndef WINDLL + sgn = ' '; +#endif + cfactor = (cfactor + 5) / 10; + } +#ifdef WINDLL + /* pass the totals back to the calling application */ + G.lpUserFunctions->TotalSizeComp = tot_csize; + G.lpUserFunctions->TotalSize = tot_ucsize; + G.lpUserFunctions->CompFactor = (ulg)cfactor; + G.lpUserFunctions->NumMembers = members; + +#else /* !WINDLL */ + if (cfactor == 100) + sprintf(cfactorstr, LoadFarString(CompFactor100)); + else + sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor); + if (longhdr) { + Info(slide, 0, ((char *)slide, LoadFarString(LongFileTrailer), + FmZofft(tot_ucsize, "8", "u"), FmZofft(tot_csize, "8", "u"), + cfactorstr, members, members==1? "":"s")); +#ifdef OS2_EAS + if (tot_easize || tot_aclsize) + Info(slide, 0, ((char *)slide, "\n")); + if (tot_eafiles && tot_easize) + Info(slide, 0, ((char *)slide, LoadFarString(OS2ExtAttrTrailer), + tot_eafiles, tot_eafiles == 1? " has" : "s have a total of", + tot_easize)); + if (tot_aclfiles && tot_aclsize) + Info(slide, 0, ((char *)slide, LoadFarString(OS2ACLTrailer), + tot_aclfiles, + tot_aclfiles == 1 ? " has" : "s have a total of", + tot_aclsize)); +#endif /* OS2_EAS */ + } else +#ifdef OS2_EAS + Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer), + FmZofft(tot_ucsize, "9", "u"), tot_easize, tot_aclsize, + members, members == 1 ? "" : "s")); +#else + Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer), + FmZofft(tot_ucsize, "9", "u"), + members, members == 1 ? "" : "s")); +#endif /* OS2_EAS */ +#endif /* ?WINDLL */ + } + + /* Skip the following checks in case of a premature listing break. */ + if (error_in_archive <= PK_WARN) { + +/*--------------------------------------------------------------------------- + Double check that we're back at the end-of-central-directory record. + ---------------------------------------------------------------------------*/ + + if ( (memcmp(G.sig, + (G.ecrec.have_ecr64 ? + end_central64_sig : end_central_sig), + 4) != 0) + && (!G.ecrec.is_zip64_archive) + && (memcmp(G.sig, end_central_sig, 4) != 0) + ) { /* just to make sure again */ + Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); + error_in_archive = PK_WARN; /* didn't find sig */ + } + + /* Set specific return code when no files have been found. */ + if (members == 0L && error_in_archive <= PK_WARN) + error_in_archive = PK_FIND; + + } + + return error_in_archive; + +} /* end function list_files() */ + + + + + +#ifdef TIMESTAMP + +/************************/ +/* Function fn_is_dir() */ +/************************/ + +static int fn_is_dir(__G) /* returns TRUE if G.filename is directory */ + __GDEF +{ + extent fn_len = strlen(G.filename); + register char endc; + + return fn_len > 0 && + ((endc = lastchar(G.filename, fn_len)) == '/' || + (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/') && + endc == '\\')); +} + + + + + +/*****************************/ +/* Function get_time_stamp() */ +/*****************************/ + +int get_time_stamp(__G__ last_modtime, nmember) /* return PK-type error code */ + __GDEF + time_t *last_modtime; + ulg *nmember; +{ + int do_this_file=FALSE, error, error_in_archive=PK_COOL; + ulg j; +#ifdef USE_EF_UT_TIME + iztimes z_utime; +#endif + min_info info; + + +/*--------------------------------------------------------------------------- + Unlike extract_or_test_files() but like list_files(), this function works + on information in the central directory alone. Thus we have a single, + large loop through the entire directory, searching for the latest time + stamp. + ---------------------------------------------------------------------------*/ + + *last_modtime = 0L; /* assuming no zipfile data older than 1970 */ + *nmember = 0L; + G.pInfo = &info; + + for (j = 1L;; j++) { + + if (readbuf(__G__ G.sig, 4) == 0) + return PK_EOF; + if (memcmp(G.sig, central_hdr_sig, 4)) { /* is it a CentDir entry? */ + if (((unsigned)(j - 1) & (unsigned)0xFFFF) == + (unsigned)G.ecrec.total_entries_central_dir) { + /* "j modulus 64k" matches the reported 16-bit-unsigned + * number of directory entries -> probably, the regular + * end of the central directory has been reached + */ + break; + } else { + Info(slide, 0x401, + ((char *)slide, LoadFarString(CentSigMsg), j)); + Info(slide, 0x401, + ((char *)slide, LoadFarString(ReportMsg))); + return PK_BADERR; /* sig not found */ + } + } + /* process_cdir_file_hdr() sets pInfo->lcflag: */ + if ((error = process_cdir_file_hdr(__G)) != PK_COOL) + return error; /* only PK_EOF defined */ + if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != PK_OK) + { /* ^-- (uses pInfo->lcflag) */ + error_in_archive = error; + if (error > PK_WARN) /* fatal: can't continue */ + return error; + } + if (G.extra_field != (uch *)NULL) { + free(G.extra_field); + G.extra_field = (uch *)NULL; + } + if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) + != 0) + { + error_in_archive = error; + if (error > PK_WARN) /* fatal */ + return error; + } + if (!G.process_all_files) { /* check if specified on command line */ + unsigned i; + + if (G.filespecs == 0) + do_this_file = TRUE; + else { /* check if this entry matches an `include' argument */ + do_this_file = FALSE; + for (i = 0; i < G.filespecs; i++) + if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) { + do_this_file = TRUE; + break; /* found match, so stop looping */ + } + } + if (do_this_file) { /* check if this is an excluded file */ + for (i = 0; i < G.xfilespecs; i++) + if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) { + do_this_file = FALSE; /* ^-- ignore case in match */ + break; + } + } + } + + /* If current file was specified on command line, or if no names were + * specified, check the time for this file. Either way, get rid of the + * file comment and go back for the next file. + * Directory entries are always ignored, to stay compatible with both + * Zip and PKZIP. + */ + if ((G.process_all_files || do_this_file) && !fn_is_dir(__G)) { +#ifdef USE_EF_UT_TIME + if (G.extra_field && +#ifdef IZ_CHECK_TZ + G.tz_is_valid && +#endif + (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1, + G.crec.last_mod_dos_datetime, &z_utime, NULL) + & EB_UT_FL_MTIME)) + { + if (*last_modtime < z_utime.mtime) + *last_modtime = z_utime.mtime; + } else +#endif /* USE_EF_UT_TIME */ + { + time_t modtime = dos_to_unix_time(G.crec.last_mod_dos_datetime); + + if (*last_modtime < modtime) + *last_modtime = modtime; + } + ++*nmember; + } + SKIP_(G.crec.file_comment_length) + + } /* end for-loop (j: files in central directory) */ + +/*--------------------------------------------------------------------------- + Double check that we're back at the end-of-central-directory record. + ---------------------------------------------------------------------------*/ + + if (memcmp(G.sig, end_central_sig, 4)) { /* just to make sure again */ + Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); + error_in_archive = PK_WARN; + } + if (*nmember == 0L && error_in_archive <= PK_WARN) + error_in_archive = PK_FIND; + + return error_in_archive; + +} /* end function get_time_stamp() */ + +#endif /* TIMESTAMP */ + + + + + +/********************/ +/* Function ratio() */ /* also used by ZipInfo routines */ +/********************/ + +int ratio(uc, c) + zusz_t uc, c; +{ + zusz_t denom; + + if (uc == 0) + return 0; + if (uc > 2000000L) { /* risk signed overflow if multiply numerator */ + denom = uc / 1000L; + return ((uc >= c) ? + (int) ((uc-c + (denom>>1)) / denom) : + -((int) ((c-uc + (denom>>1)) / denom))); + } else { /* ^^^^^^^^ rounding */ + denom = uc; + return ((uc >= c) ? + (int) ((1000L*(uc-c) + (denom>>1)) / denom) : + -((int) ((1000L*(c-uc) + (denom>>1)) / denom))); + } /* ^^^^^^^^ rounding */ +} + + + + + +/************************/ +/* Function fnprint() */ /* also used by ZipInfo routines */ +/************************/ + +void fnprint(__G) /* print filename (after filtering) and newline */ + __GDEF +{ + char *name = fnfilter(G.filename, slide, (extent)(WSIZE>>1)); + + (*G.message)((zvoid *)&G, (uch *)name, (ulg)strlen(name), 0); + (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); + +} /* end function fnprint() */ diff --git a/macos/Contents b/macos/Contents new file mode 100644 index 0000000..d797cc7 --- /dev/null +++ b/macos/Contents @@ -0,0 +1,62 @@ +Contents of the "macos" sub-archive for UnZip 5.42 and later: + + Contents this file + README.TXT Dirk Haase's infos on updated Macintosh ports of Zip/UnZip + HISTORY.TXT Dirk Haase's MacOS specific ChangeLog + + UnZp.h config header used to build standalone app with GUI + UnZpLib.h config header used to build a static library + UnZpSFX.h config header used to build the SFX stub + UnZpSx.h config header for building a standalone app. with MW Sioux + UnZpPrj.xml Metrowerks CodeWarrior pro5 project file (xml export file) + + source/ subdirectory containing all sources: + a) UnZip specific code + macbin3.c macbinary III code, used for extraction of ZipIt archives + macbin3.h macbinary III header, macbinary docu + public prototyping + macos.c Mac-specific filesystem code + maccfg.h Mac-specific configuration and global declarations + macdir.c Macintosh Posix-style directory emulation ("dirent") + macdir.h header file for directory emulation + macscreen.c screen functions to be used in standalone UnZip application + macstat.c Macintosh stat() emulation + macstat.h header file for stat() emulation + macunzip.c Macintosh standalone version main function + sxunzip.c main function for use with static library (SIOUX) + unzip_rc.hqx UnZip resource file for standalone application (BinHex) + + b) general utilities shared between Zip and UnZip + charmap.h character mapping tables ISO 8859-1 <--> MacRoman + getenv.c simulation of unix compatible getenv() on MacOS + helpers.c some helper functions + helpers.h + macstuff.h wrapper to pull in some "MoreFiles" filemanager stuff + mactime.c replacement for broken Metrowerks RTL time functions + mactime.h + pathname.c functions for handling MacOS HFS path- /filenames + pathname.h + +The new UnZpPrj.hqx project file should be "un-BinHex'ed" into UnZpPrj, +which builds the following targets: + Unzip (68k) -> standalone unzip for 68k + Unzip (PPC) -> standalone unzip for PPC + Unzip Lib (68k) -> static library 68k + Unzip Lib (PPC) -> static library PPC + Unzip Sioux (68k) -> MW Sioux standoalone App, good for debugging + Unzip Sioux (PPC) -> MW Sioux standoalone App, good for debugging + + +Before you start a build on your Macintosh: + +Extract "*.hqx" and "source:*.hqx" first! +And PLEASE, read the MacOS specific documentation in README.TXT! + + +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..8c52be7 --- /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 wildcard ! + (see Footnotes: 1 wildcard, 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. wildcard: + The '*' is a wildcard and means 'all files' + Just in case you don't know wildcards: + '*' 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/UnZp.h b/macos/UnZp.h new file mode 100644 index 0000000..dc4a9e0 --- /dev/null +++ b/macos/UnZp.h @@ -0,0 +1,151 @@ +/* + 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 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 +*/ +/*--------------------------------------------------------------------------- + + UnZp.h + + This header-files is global to the project Unzip standalone. + + ---------------------------------------------------------------------------*/ + +/*****************************************************************************/ +/* Macros, typedefs */ +/*****************************************************************************/ + +#define MACUNZIP_STANDALONE +#define MACUNZIP + +/* These functions are defined as a macro instead of a function. +so we have to undefine them for replacing */ +#undef getc +#undef getchar +#undef putchar +#undef putc + +#ifndef TRUE +#define TRUE 1 +#endif /* TRUE */ +#ifndef FALSE +#define FALSE 0 +#endif /* FALSE */ + +/*****************************************************************************/ +/* Includes standard headers */ +/*****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + + +/* +#define MAC_DEBUG 1 + */ + + +#ifdef MAC_DEBUG +#define LOG_DEBUG 7 /* debug-level messages */ +int Print2Syslog(UInt8 priority, const char *format, ...); +#include + + +#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 /* !MAC_DEBUG */ +#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 /* ?MAC_DEBUG */ diff --git a/macos/UnZpLib.h b/macos/UnZpLib.h new file mode 100644 index 0000000..e2bc6fd --- /dev/null +++ b/macos/UnZpLib.h @@ -0,0 +1,161 @@ +/* + 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 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 +*/ +/*--------------------------------------------------------------------------- + + UnZpLib.h + + This header-files is global to the project UnZpLib. + + ---------------------------------------------------------------------------*/ + +/*****************************************************************************/ +/* Macros, typedefs */ +/*****************************************************************************/ + +#define MacStaticLib +#define MACUNZIP + +/* 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 TRUE +#define TRUE 1 +#endif /* TRUE */ +#ifndef FALSE +#define FALSE 0 +#endif /* FALSE */ + +/* +#define DEBUG_TIME + */ + + +#define USE_EF_UT_TIME + +/* since we have no TZ environment variable on Macs + this option must be disabled */ +#undef IZ_CHECK_TZ + + +/*****************************************************************************/ +/* Includes standard headers */ +/*****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* +#define MAC_DEBUG 1 + */ + + +#ifdef MAC_DEBUG +#define LOG_DEBUG 7 /* debug-level messages */ +int Print2Syslog(UInt8 priority, const char *format, ...); +#include + + +#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 /* !MAC_DEBUG */ +#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 /* ?MAC_DEBUG */ diff --git a/macos/UnZpPrj.xml b/macos/UnZpPrj.xml new file mode 100644 index 0000000..331e1d1 --- /dev/null +++ b/macos/UnZpPrj.xml @@ -0,0 +1 @@ + ]> Unzip Sioux (68k) UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::izshr:macos: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:CHeaders: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:PascalInterfaces: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:Sources: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS 68K Linker PreLinker PostLinker TargetnameUnzip Sioux (68k) OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeOBJ FileExtension CompilerMPW Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.p CompilerMW Pascal 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ 68K Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ 68K Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.ppu CompilerMW Pascal 68K Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.seg Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowserfalse DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeLarge MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym0 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileUnzip Sioux (68k) MWProject_68K_symfilename MWProject_68K_filecreator1230662000 MWProject_68K_filetype1095782476 MWProject_68K_size1024 MWProject_68K_flags22720 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize512 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs1 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnameUnZpSx.h MWFrontEnd_C_ansistrict1 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse1 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma0 MWWarning_C_warn_emptydecl0 MWWarning_C_warn_possunwant0 MWWarning_C_warn_unusedvar0 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma0 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWFTP_Post_hostName MWFTP_Post_username MWFTP_Post_password MWFTP_Post_remoteDir MWFTP_Post_uploadDir MWFTP_Post_ftp_port21 MWFTP_Post_SendBin1 MWFTP_Post_ShouldLog1 MWCommandLine_Java_clsName MWCommandLine_Java_args MWJava_Language_optimize0 MWJava_Language_warnDeprecated0 MWJava_Language_emitMap0 MWJava_Language_strictFileNames0 MWJava_Language_strictFileHierarchy0 MWJava_Language_emitHeadersNoNativeHeaders MWJava_Language_packageFilter MWJava_Language_genComments1 MWJava_Language_genHeaders0 MWJava_MacOS_typeJBindery MWJava_MacOS_grow0 MWJava_MacOS_profile0 MWJava_MacOS_verify0 MWJava_MacOS_useHttpProxy0 MWJava_MacOS_useFTPProxy0 MWJava_MacOS_useFirewallProxy0 MWJava_MacOS_outfileJBoundApp MWJava_MacOS_outcreator1061109567 MWJava_MacOS_maxMem1048576 MWJava_MacOS_minMem524288 MWJava_MacOS_red65535 MWJava_MacOS_green65535 MWJava_MacOS_blue65535 MWJava_MacOS_stdoutType1464421956 MWJava_MacOS_stdinType1853189228 MWJava_MacOS_httpProxyPort0 MWJava_MacOS_fTPProxyPort0 MWJava_MacOS_firewallProxyPort0 MWJava_MacOS_httpProxy MWJava_MacOS_fTPProxy MWJava_MacOS_firewallProxy MWJava_MacOS_merge0 MWJava_MacOS_write_old_rsrcs1 MWJava_MacOS_jbindrundebug0 MWJava_MacOS_stdoutfile MWJava_MacOS_stdinfile MWJava_Output_outputtypeJarFile MWJava_Output_outfileJavaClasses.jar MWJava_Output_ftype1514754080 MWJava_Output_fcreator1297570384 MWJava_Output_compress0 MWJava_Output_genManifest0 MWJava_Output_trunctypeFront MWJava_Output_deleteClasses0 MWJava_Output_consoleApp1 MWJava_Proj_projtypeApplet MWJava_Proj_runtimeArgs MWJava_Proj_mainClassName MWJava_Proj_HTMLAppCreator1297303877 MWJava_Proj_HTMLAppNameInternet Explorer MWJava_Proj_HTMLAppWin32NameIexplore.exe MWJava_Proj_compress0 MWJava_Proj_useVM1 MWJava_Proj_workingDir MWJava_Proj_vmarguments MWJava_Proj_vmName MWJavaDoc_Proj_Version1 MWJavaDoc_Proj_Depricated0 MWJavaDoc_Proj_Author1 MWJavaDoc_Proj_Index1 MWJavaDoc_Proj_Tree1 MWJavaDoc_Proj_SunResolveToSame1 MWJavaDoc_Proj_Shortnames1 MWJavaDoc_Proj_Folder0 MWJavaDoc_Proj_GenerateAPILinks0 MWJavaDoc_Proj_scopePublic MWJavaDoc_Proj_fcreator1297303877 MWJavaDoc_Proj_encodingName MWJavaDoc_Proj_decodingName MWJavaDoc_Proj_javaPackagePathhttp://java.sun.com/products/jdk/1.1/docs/api/ MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources ‰aˆ MWCodeGen_PPC_structalignmentMC68K MWCodeGen_PPC_tracebacktablesNone MWCodeGen_PPC_processorGeneric MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule0 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata0 MWCodeGen_PPC_vrsave0 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym1 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeFast MWLinker_PPC_initname MWLinker_PPC_mainname__start MWLinker_PPC_termname MWPEF_exportsNone MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads0 MWProject_PPC_typeApplication MWProject_PPC_outfilea.out MWProject_PPC_filecreator1061109567 MWProject_PPC_filetype1095782476 MWProject_PPC_size384 MWProject_PPC_minsize384 MWProject_PPC_stacksize64 MWProject_PPC_flags22720 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name inflate.h MacOS Text Name globals.h MacOS Text Name unzip.h MacOS Text Name unzip.c MacOS Text Name explode.c MacOS Text Name extract.c MacOS Text Name fileio.c MacOS Text Name list.c MacOS Text Name globals.c MacOS Text Name match.c MacOS Text Name zipinfo.c MacOS Text Name inflate.c MacOS Text Name process.c MacOS Text Name unshrink.c MacOS Text Name unreduce.c MacOS Text Name unzpriv.h MacOS Text Name macdir.c MacOS Text Name crc32.c MacOS Text Name crypt.c MacOS Text Name ttyio.c MacOS Text Name envargs.c MacOS Text Name helpers.c MacOS Text Name helpers.h MacOS Text Name macstuff.h MacOS Text Name pathname.c MacOS Text Name pathname.h MacOS Text Name maccfg.h MacOS Text Name sxunzip.c MacOS Text Name UnZpSx.h MacOS Text Name mactime.c MacOS Text Name macstat.c MacOS Text Name macstat.h MacOS Text Name unzip.rc MacOS Resource Name charmap.h MacOS Text Name FSp_fopen.c MacOS Text Name getenv.c MacOS Text Name macos.c MacOS Text Name macbin3.h MacOS Text Name macbin3.c MacOS Text Name MSL Runtime68K.Lib MacOS Library Name MacOS.lib MacOS Library Name MathLib68K (2i).Lib MacOS Library Name DirectoryCopy.h MacOS Text Name FileCopy.h MacOS Text Name FSpCompat.h MacOS Text Name FullPath.h MacOS Text Name IterateDirectory.h MacOS Text Name MoreDesktopMgr.h MacOS Text Name MoreFiles.h MacOS Text Name MoreFilesExtras.h MacOS Text Name Optimization.h MacOS Text Name OptimizationEnd.h MacOS Text Name Search.h MacOS Text First Segment Protected, Locked Name inflate.h MacOS Name globals.h MacOS Name unzip.h MacOS Name unzip.c MacOS Name explode.c MacOS Name extract.c MacOS Name fileio.c MacOS Name list.c MacOS Name globals.c MacOS Name match.c MacOS Name zipinfo.c MacOS Name inflate.c MacOS Name process.c MacOS Name unshrink.c MacOS Name unreduce.c MacOS Name unzpriv.h MacOS Name macdir.c MacOS Name crc32.c MacOS Name crypt.c MacOS Name ttyio.c MacOS Name envargs.c MacOS Name helpers.c MacOS Name helpers.h MacOS Name macstuff.h MacOS Name pathname.c MacOS Name pathname.h MacOS Name maccfg.h MacOS Name sxunzip.c MacOS Name UnZpSx.h MacOS Name macstat.c MacOS Name macstat.h MacOS Name charmap.h MacOS Name FSp_fopen.c MacOS Name getenv.c MacOS Name mactime.c MacOS Name unzip.rc MacOS Name macos.c MacOS Name macbin3.h MacOS Name macbin3.c MacOS Name MSL Runtime68K.Lib MacOS Name MacOS.lib MacOS Name MathLib68K (2i).Lib MacOS Name DirectoryCopy.h MacOS Name FileCopy.h MacOS Name FSpCompat.h MacOS Name FullPath.h MacOS Name IterateDirectory.h MacOS Name MoreDesktopMgr.h MacOS Name MoreFiles.h MacOS Name MoreFilesExtras.h MacOS Name Optimization.h MacOS Name OptimizationEnd.h MacOS Name Search.h MacOS Unzip Sioux (PPC) UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::izshr:macos: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:CHeaders: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:PascalInterfaces: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:Sources: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameUnzip Sioux (PPC) OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.p CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.ppu CompilerMW Pascal PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowsertrue DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileToolbox68k.out MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22688 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs1 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnameUnZpSx.h MWFrontEnd_C_ansistrict1 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse1 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma0 MWWarning_C_warn_emptydecl0 MWWarning_C_warn_possunwant0 MWWarning_C_warn_unusedvar0 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma0 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWFTP_Post_hostName MWFTP_Post_username MWFTP_Post_password MWFTP_Post_remoteDir MWFTP_Post_uploadDir MWFTP_Post_ftp_port21 MWFTP_Post_SendBin1 MWFTP_Post_ShouldLog1 MWCommandLine_Java_clsName MWCommandLine_Java_args MWJava_Language_optimize0 MWJava_Language_warnDeprecated0 MWJava_Language_emitMap0 MWJava_Language_strictFileNames0 MWJava_Language_strictFileHierarchy0 MWJava_Language_emitHeadersNoNativeHeaders MWJava_Language_packageFilter MWJava_Language_genComments1 MWJava_Language_genHeaders0 MWJava_MacOS_typeJBindery MWJava_MacOS_grow0 MWJava_MacOS_profile0 MWJava_MacOS_verify0 MWJava_MacOS_useHttpProxy0 MWJava_MacOS_useFTPProxy0 MWJava_MacOS_useFirewallProxy0 MWJava_MacOS_outfileJBoundApp MWJava_MacOS_outcreator1061109567 MWJava_MacOS_maxMem1048576 MWJava_MacOS_minMem524288 MWJava_MacOS_red65535 MWJava_MacOS_green65535 MWJava_MacOS_blue65535 MWJava_MacOS_stdoutType1464421956 MWJava_MacOS_stdinType1853189228 MWJava_MacOS_httpProxyPort0 MWJava_MacOS_fTPProxyPort0 MWJava_MacOS_firewallProxyPort0 MWJava_MacOS_httpProxy MWJava_MacOS_fTPProxy MWJava_MacOS_firewallProxy MWJava_MacOS_merge0 MWJava_MacOS_write_old_rsrcs1 MWJava_MacOS_jbindrundebug0 MWJava_MacOS_stdoutfile MWJava_MacOS_stdinfile MWJava_Output_outputtypeJarFile MWJava_Output_outfileJavaClasses.jar MWJava_Output_ftype1514754080 MWJava_Output_fcreator1297570384 MWJava_Output_compress0 MWJava_Output_genManifest0 MWJava_Output_trunctypeFront MWJava_Output_deleteClasses0 MWJava_Output_consoleApp1 MWJava_Proj_projtypeApplet MWJava_Proj_runtimeArgs MWJava_Proj_mainClassName MWJava_Proj_HTMLAppCreator1297303877 MWJava_Proj_HTMLAppNameInternet Explorer MWJava_Proj_HTMLAppWin32NameIexplore.exe MWJava_Proj_compress0 MWJava_Proj_useVM1 MWJava_Proj_workingDir MWJava_Proj_vmarguments MWJava_Proj_vmName MWJavaDoc_Proj_Version1 MWJavaDoc_Proj_Depricated0 MWJavaDoc_Proj_Author1 MWJavaDoc_Proj_Index1 MWJavaDoc_Proj_Tree1 MWJavaDoc_Proj_SunResolveToSame1 MWJavaDoc_Proj_Shortnames1 MWJavaDoc_Proj_Folder0 MWJavaDoc_Proj_GenerateAPILinks0 MWJavaDoc_Proj_scopePublic MWJavaDoc_Proj_fcreator1297303877 MWJavaDoc_Proj_encodingName MWJavaDoc_Proj_decodingName MWJavaDoc_Proj_javaPackagePathhttp://java.sun.com/products/jdk/1.1/docs/api/ MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources ‰aˆ MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesInline MWCodeGen_PPC_processorGeneric MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule0 MWCodeGen_PPC_peephole0 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata0 MWCodeGen_PPC_vrsave0 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym0 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs1 MWLinker_PPC_linkmodeFast MWLinker_PPC_initname MWLinker_PPC_mainname__start MWLinker_PPC_termname MWPEF_exportsNone MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads0 MWProject_PPC_typeApplication MWProject_PPC_outfileUnzip Sioux (PPC) MWProject_PPC_filecreator1230662000 MWProject_PPC_filetype1095782476 MWProject_PPC_size2048 MWProject_PPC_minsize1024 MWProject_PPC_stacksize512 MWProject_PPC_flags22720 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name MSL C.PPC.Lib MacOS Library Name MSL C++.PPC.Lib MacOS Library Name InterfaceLib MacOS Library Name MathLib MacOS Library Name MSL RuntimePPC.Lib MacOS Library Name MSL SIOUX.PPC.Lib MacOS Library Debug Name inflate.h MacOS Text Name globals.h MacOS Text Name unzip.h MacOS Text Name unzip.c MacOS Text Name envargs.c MacOS Text Name explode.c MacOS Text Name extract.c MacOS Text Name fileio.c MacOS Text Name list.c MacOS Text Name globals.c MacOS Text Name match.c MacOS Text Name zipinfo.c MacOS Text Name inflate.c MacOS Text Name process.c MacOS Text Name unshrink.c MacOS Text Name unreduce.c MacOS Text Name unzpriv.h MacOS Text Name macdir.c MacOS Text Name crc32.c MacOS Text Name crypt.c MacOS Text Name ttyio.c MacOS Text Name helpers.c MacOS Text Name helpers.h MacOS Text Name macstuff.h MacOS Text Name pathname.c MacOS Text Name pathname.h MacOS Text Name maccfg.h MacOS Text Name sxunzip.c MacOS Text Name UnZpSx.h MacOS Text Name mactime.c MacOS Text Name macstat.c MacOS Text Name macstat.h MacOS Text Name unzip.rc MacOS Resource Name charmap.h MacOS Text Name FSp_fopen.c MacOS Text Name getenv.c MacOS Text Name macos.c MacOS Text Name macbin3.h MacOS Text Name macbin3.c MacOS Text Name DirectoryCopy.h MacOS Text Name FileCopy.h MacOS Text Name FSpCompat.h MacOS Text Name FullPath.h MacOS Text Name IterateDirectory.h MacOS Text Name MoreDesktopMgr.h MacOS Text Name MoreFiles.h MacOS Text Name MoreFilesExtras.h MacOS Text Name Optimization.h MacOS Text Name OptimizationEnd.h MacOS Text Name Search.h MacOS Text Name inflate.h MacOS Name globals.h MacOS Name unzip.h MacOS Name unzip.c MacOS Name envargs.c MacOS Name explode.c MacOS Name extract.c MacOS Name fileio.c MacOS Name list.c MacOS Name globals.c MacOS Name match.c MacOS Name zipinfo.c MacOS Name inflate.c MacOS Name process.c MacOS Name unshrink.c MacOS Name unreduce.c MacOS Name unzpriv.h MacOS Name macdir.c MacOS Name crc32.c MacOS Name crypt.c MacOS Name ttyio.c MacOS Name helpers.c MacOS Name helpers.h MacOS Name macstuff.h MacOS Name pathname.c MacOS Name pathname.h MacOS Name maccfg.h MacOS Name sxunzip.c MacOS Name UnZpSx.h MacOS Name macstat.c MacOS Name macstat.h MacOS Name unzip.rc MacOS Name charmap.h MacOS Name FSp_fopen.c MacOS Name mactime.c MacOS Name getenv.c MacOS Name macos.c MacOS Name macbin3.h MacOS Name macbin3.c MacOS Name MSL SIOUX.PPC.Lib MacOS Name MSL C.PPC.Lib MacOS Name MSL C++.PPC.Lib MacOS Name InterfaceLib MacOS Name MathLib MacOS Name MSL RuntimePPC.Lib MacOS Name DirectoryCopy.h MacOS Name FileCopy.h MacOS Name FSpCompat.h MacOS Name FullPath.h MacOS Name IterateDirectory.h MacOS Name MoreDesktopMgr.h MacOS Name MoreFiles.h MacOS Name MoreFilesExtras.h MacOS Name Optimization.h MacOS Name OptimizationEnd.h MacOS Name Search.h MacOS Unzip Lib (PPC) UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::izshr:macos: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:CHeaders: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:PascalInterfaces: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:Sources: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameUnzip Lib (PPC) OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.p CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.ppu CompilerMW Pascal PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowsertrue DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileToolbox68k.out MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22688 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs0 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnameUnZpLib.h MWFrontEnd_C_ansistrict1 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings1 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse1 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg1 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic1 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual1 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined1 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWFTP_Post_hostName MWFTP_Post_username MWFTP_Post_password MWFTP_Post_remoteDir MWFTP_Post_uploadDir MWFTP_Post_ftp_port21 MWFTP_Post_SendBin1 MWFTP_Post_ShouldLog1 MWCommandLine_Java_clsName MWCommandLine_Java_args MWJava_Language_optimize0 MWJava_Language_warnDeprecated0 MWJava_Language_emitMap0 MWJava_Language_strictFileNames0 MWJava_Language_strictFileHierarchy0 MWJava_Language_emitHeadersNoNativeHeaders MWJava_Language_packageFilter MWJava_Language_genComments1 MWJava_Language_genHeaders0 MWJava_MacOS_typeJBindery MWJava_MacOS_grow0 MWJava_MacOS_profile0 MWJava_MacOS_verify0 MWJava_MacOS_useHttpProxy0 MWJava_MacOS_useFTPProxy0 MWJava_MacOS_useFirewallProxy0 MWJava_MacOS_outfileJBoundApp MWJava_MacOS_outcreator1061109567 MWJava_MacOS_maxMem1048576 MWJava_MacOS_minMem524288 MWJava_MacOS_red65535 MWJava_MacOS_green65535 MWJava_MacOS_blue65535 MWJava_MacOS_stdoutType1464421956 MWJava_MacOS_stdinType1853189228 MWJava_MacOS_httpProxyPort0 MWJava_MacOS_fTPProxyPort0 MWJava_MacOS_firewallProxyPort0 MWJava_MacOS_httpProxy MWJava_MacOS_fTPProxy MWJava_MacOS_firewallProxy MWJava_MacOS_merge0 MWJava_MacOS_write_old_rsrcs1 MWJava_MacOS_jbindrundebug0 MWJava_MacOS_stdoutfile MWJava_MacOS_stdinfile MWJava_Output_outputtypeJarFile MWJava_Output_outfileJavaClasses.jar MWJava_Output_ftype1514754080 MWJava_Output_fcreator1297570384 MWJava_Output_compress0 MWJava_Output_genManifest0 MWJava_Output_trunctypeFront MWJava_Output_deleteClasses0 MWJava_Output_consoleApp1 MWJava_Proj_projtypeApplet MWJava_Proj_runtimeArgs MWJava_Proj_mainClassName MWJava_Proj_HTMLAppCreator1297303877 MWJava_Proj_HTMLAppNameInternet Explorer MWJava_Proj_HTMLAppWin32NameIexplore.exe MWJava_Proj_compress0 MWJava_Proj_useVM1 MWJava_Proj_workingDir MWJava_Proj_vmarguments MWJava_Proj_vmName MWJavaDoc_Proj_Version1 MWJavaDoc_Proj_Depricated0 MWJavaDoc_Proj_Author1 MWJavaDoc_Proj_Index1 MWJavaDoc_Proj_Tree1 MWJavaDoc_Proj_SunResolveToSame1 MWJavaDoc_Proj_Shortnames1 MWJavaDoc_Proj_Folder0 MWJavaDoc_Proj_GenerateAPILinks0 MWJavaDoc_Proj_scopePublic MWJavaDoc_Proj_fcreator1297303877 MWJavaDoc_Proj_encodingName MWJavaDoc_Proj_decodingName MWJavaDoc_Proj_javaPackagePathhttp://java.sun.com/products/jdk/1.1/docs/api/ MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources ‰aˆ MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesInline MWCodeGen_PPC_processorP603e MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule1 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata0 MWCodeGen_PPC_vrsave0 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel4 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym0 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs1 MWLinker_PPC_linkmodeFast MWLinker_PPC_initname MWLinker_PPC_mainname__start MWLinker_PPC_termname MWPEF_exportsNone MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads0 MWProject_PPC_typeLibrary MWProject_PPC_outfileUnzip Lib (PPC) MWProject_PPC_filecreator1061109567 MWProject_PPC_filetype1061109567 MWProject_PPC_size0 MWProject_PPC_minsize0 MWProject_PPC_stacksize0 MWProject_PPC_flags0 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name inflate.h MacOS Text Name globals.h MacOS Text Name unzip.h MacOS Text Name unzip.c MacOS Text Name explode.c MacOS Text Name extract.c MacOS Text Name fileio.c MacOS Text Name list.c MacOS Text Name globals.c MacOS Text Name match.c MacOS Text Name zipinfo.c MacOS Text Name inflate.c MacOS Text Name process.c MacOS Text Name unshrink.c MacOS Text Name unreduce.c MacOS Text Name unzpriv.h MacOS Text Name macdir.c MacOS Text Name maccfg.h MacOS Text Name sxunzip.c MacOS Text Name UnZpLib.h MacOS Text Name macstat.c MacOS Text Name macstat.h MacOS Text Name macos.c MacOS Text Name crypt.c MacOS Text Name macbin3.h MacOS Text Name macbin3.c MacOS Text Name ttyio.c MacOS Text Name DirectoryCopy.h MacOS Text Name FileCopy.h MacOS Text Name FSpCompat.h MacOS Text Name FullPath.h MacOS Text Name IterateDirectory.h MacOS Text Name MoreDesktopMgr.h MacOS Text Name MoreFiles.h MacOS Text Name MoreFilesExtras.h MacOS Text Name Optimization.h MacOS Text Name OptimizationEnd.h MacOS Text Name Search.h MacOS Text Name inflate.h MacOS Name globals.h MacOS Name unzip.h MacOS Name unzip.c MacOS Name explode.c MacOS Name extract.c MacOS Name fileio.c MacOS Name list.c MacOS Name globals.c MacOS Name match.c MacOS Name zipinfo.c MacOS Name inflate.c MacOS Name process.c MacOS Name unshrink.c MacOS Name unreduce.c MacOS Name unzpriv.h MacOS Name macdir.c MacOS Name maccfg.h MacOS Name sxunzip.c MacOS Name UnZpLib.h MacOS Name macstat.c MacOS Name macstat.h MacOS Name macos.c MacOS Name crypt.c MacOS Name macbin3.h MacOS Name macbin3.c MacOS Name ttyio.c MacOS Name DirectoryCopy.h MacOS Name FileCopy.h MacOS Name FSpCompat.h MacOS Name FullPath.h MacOS Name IterateDirectory.h MacOS Name MoreDesktopMgr.h MacOS Name MoreFiles.h MacOS Name MoreFilesExtras.h MacOS Name Optimization.h MacOS Name OptimizationEnd.h MacOS Name Search.h MacOS Unzip Lib (68k) UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::izshr:macos: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:CHeaders: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:PascalInterfaces: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:Sources: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS 68K Linker PreLinker PostLinker TargetnameUnzip Lib (68k) OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeOBJ FileExtension CompilerMPW Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.p CompilerMW Pascal 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ 68K Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ 68K Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.ppu CompilerMW Pascal 68K Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.seg Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowsertrue DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeLarge MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames0 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel4 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym0 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle1 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeLibrary MWProject_68K_outfileUnzip Lib (68k) MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1061109567 MWProject_68K_size0 MWProject_68K_flags0 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a41 MWProject_68K_minsize0 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs1 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnameUnZpLib.h MWFrontEnd_C_ansistrict1 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings1 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse1 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg1 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic1 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual1 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWFTP_Post_hostName MWFTP_Post_username MWFTP_Post_password MWFTP_Post_remoteDir MWFTP_Post_uploadDir MWFTP_Post_ftp_port21 MWFTP_Post_SendBin1 MWFTP_Post_ShouldLog1 MWCommandLine_Java_clsName MWCommandLine_Java_args MWJava_Language_optimize0 MWJava_Language_warnDeprecated0 MWJava_Language_emitMap0 MWJava_Language_strictFileNames0 MWJava_Language_strictFileHierarchy0 MWJava_Language_emitHeadersNoNativeHeaders MWJava_Language_packageFilter MWJava_Language_genComments1 MWJava_Language_genHeaders0 MWJava_MacOS_typeJBindery MWJava_MacOS_grow0 MWJava_MacOS_profile0 MWJava_MacOS_verify0 MWJava_MacOS_useHttpProxy0 MWJava_MacOS_useFTPProxy0 MWJava_MacOS_useFirewallProxy0 MWJava_MacOS_outfileJBoundApp MWJava_MacOS_outcreator1061109567 MWJava_MacOS_maxMem1048576 MWJava_MacOS_minMem524288 MWJava_MacOS_red65535 MWJava_MacOS_green65535 MWJava_MacOS_blue65535 MWJava_MacOS_stdoutType1464421956 MWJava_MacOS_stdinType1853189228 MWJava_MacOS_httpProxyPort0 MWJava_MacOS_fTPProxyPort0 MWJava_MacOS_firewallProxyPort0 MWJava_MacOS_httpProxy MWJava_MacOS_fTPProxy MWJava_MacOS_firewallProxy MWJava_MacOS_merge0 MWJava_MacOS_write_old_rsrcs1 MWJava_MacOS_jbindrundebug0 MWJava_MacOS_stdoutfile MWJava_MacOS_stdinfile MWJava_Output_outputtypeJarFile MWJava_Output_outfileJavaClasses.jar MWJava_Output_ftype1514754080 MWJava_Output_fcreator1297570384 MWJava_Output_compress0 MWJava_Output_genManifest0 MWJava_Output_trunctypeFront MWJava_Output_deleteClasses0 MWJava_Output_consoleApp1 MWJava_Proj_projtypeApplet MWJava_Proj_runtimeArgs MWJava_Proj_mainClassName MWJava_Proj_HTMLAppCreator1297303877 MWJava_Proj_HTMLAppNameInternet Explorer MWJava_Proj_HTMLAppWin32NameIexplore.exe MWJava_Proj_compress0 MWJava_Proj_useVM1 MWJava_Proj_workingDir MWJava_Proj_vmarguments MWJava_Proj_vmName MWJavaDoc_Proj_Version1 MWJavaDoc_Proj_Depricated0 MWJavaDoc_Proj_Author1 MWJavaDoc_Proj_Index1 MWJavaDoc_Proj_Tree1 MWJavaDoc_Proj_SunResolveToSame1 MWJavaDoc_Proj_Shortnames1 MWJavaDoc_Proj_Folder0 MWJavaDoc_Proj_GenerateAPILinks0 MWJavaDoc_Proj_scopePublic MWJavaDoc_Proj_fcreator1297303877 MWJavaDoc_Proj_encodingName MWJavaDoc_Proj_decodingName MWJavaDoc_Proj_javaPackagePathhttp://java.sun.com/products/jdk/1.1/docs/api/ MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources ‰aˆ MWCodeGen_PPC_structalignmentMC68K MWCodeGen_PPC_tracebacktablesNone MWCodeGen_PPC_processorGeneric MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule0 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata0 MWCodeGen_PPC_vrsave0 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym1 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeFast MWLinker_PPC_initname MWLinker_PPC_mainname__start MWLinker_PPC_termname MWPEF_exportsNone MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads0 MWProject_PPC_typeApplication MWProject_PPC_outfilea.out MWProject_PPC_filecreator1061109567 MWProject_PPC_filetype1095782476 MWProject_PPC_size384 MWProject_PPC_minsize384 MWProject_PPC_stacksize64 MWProject_PPC_flags22720 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name inflate.h MacOS Text Name globals.h MacOS Text Name unzip.h MacOS Text Name unzip.c MacOS Text Name explode.c MacOS Text Name extract.c MacOS Text Name fileio.c MacOS Text Name list.c MacOS Text Name globals.c MacOS Text Name match.c MacOS Text Name zipinfo.c MacOS Text Name inflate.c MacOS Text Name process.c MacOS Text Name unshrink.c MacOS Text Name unreduce.c MacOS Text Name unzpriv.h MacOS Text Name macdir.c MacOS Text Name maccfg.h MacOS Text Name sxunzip.c MacOS Text Name UnZpLib.h MacOS Text Name macstat.c MacOS Text Name macstat.h MacOS Text Name macos.c MacOS Text Name macbin3.h MacOS Text Name macbin3.c MacOS Text Name crypt.c MacOS Text Name ttyio.c MacOS Text Name DirectoryCopy.h MacOS Text Name FileCopy.h MacOS Text Name FSpCompat.h MacOS Text Name FullPath.h MacOS Text Name IterateDirectory.h MacOS Text Name MoreDesktopMgr.h MacOS Text Name MoreFiles.h MacOS Text Name MoreFilesExtras.h MacOS Text Name Optimization.h MacOS Text Name OptimizationEnd.h MacOS Text Name Search.h MacOS Text First Segment Protected, Locked Name inflate.h MacOS Name globals.h MacOS Name unzip.h MacOS Name unzip.c MacOS Name explode.c MacOS Name extract.c MacOS Name fileio.c MacOS Name list.c MacOS Name globals.c MacOS Name match.c MacOS Name zipinfo.c MacOS Name inflate.c MacOS Name process.c MacOS Name unshrink.c MacOS Name unreduce.c MacOS Name unzpriv.h MacOS Name macdir.c MacOS Name maccfg.h MacOS Name sxunzip.c MacOS Name UnZpLib.h MacOS Name macstat.c MacOS Name macstat.h MacOS Name macos.c MacOS Name macbin3.h MacOS Name macbin3.c MacOS Name crypt.c MacOS Name ttyio.c MacOS Name DirectoryCopy.h MacOS Name FileCopy.h MacOS Name FSpCompat.h MacOS Name FullPath.h MacOS Name IterateDirectory.h MacOS Name MoreDesktopMgr.h MacOS Name MoreFiles.h MacOS Name MoreFilesExtras.h MacOS Name Optimization.h MacOS Name OptimizationEnd.h MacOS Name Search.h MacOS Unzip (PPC) UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::izshr:macos: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:CHeaders: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:PascalInterfaces: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:Sources: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS PPC Linker PreLinker PostLinker TargetnameUnzip (PPC) OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.p CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.ppu CompilerMW Pascal PPC Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.s CompilerPPCAsm Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeXCOF FileExtension CompilerXCOFF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import PPC Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowsertrue DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeSmart MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel0 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym1 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileToolbox68k.out MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22688 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs1 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnameUnZp.h MWFrontEnd_C_ansistrict1 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse1 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma0 MWWarning_C_warn_emptydecl0 MWWarning_C_warn_possunwant0 MWWarning_C_warn_unusedvar0 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma0 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWFTP_Post_hostName MWFTP_Post_username MWFTP_Post_password MWFTP_Post_remoteDir MWFTP_Post_uploadDir MWFTP_Post_ftp_port21 MWFTP_Post_SendBin1 MWFTP_Post_ShouldLog1 MWCommandLine_Java_clsName MWCommandLine_Java_args MWJava_Language_optimize0 MWJava_Language_warnDeprecated0 MWJava_Language_emitMap0 MWJava_Language_strictFileNames0 MWJava_Language_strictFileHierarchy0 MWJava_Language_emitHeadersNoNativeHeaders MWJava_Language_packageFilter MWJava_Language_genComments1 MWJava_Language_genHeaders0 MWJava_MacOS_typeJBindery MWJava_MacOS_grow0 MWJava_MacOS_profile0 MWJava_MacOS_verify0 MWJava_MacOS_useHttpProxy0 MWJava_MacOS_useFTPProxy0 MWJava_MacOS_useFirewallProxy0 MWJava_MacOS_outfileJBoundApp MWJava_MacOS_outcreator1061109567 MWJava_MacOS_maxMem1048576 MWJava_MacOS_minMem524288 MWJava_MacOS_red65535 MWJava_MacOS_green65535 MWJava_MacOS_blue65535 MWJava_MacOS_stdoutType1464421956 MWJava_MacOS_stdinType1853189228 MWJava_MacOS_httpProxyPort0 MWJava_MacOS_fTPProxyPort0 MWJava_MacOS_firewallProxyPort0 MWJava_MacOS_httpProxy MWJava_MacOS_fTPProxy MWJava_MacOS_firewallProxy MWJava_MacOS_merge0 MWJava_MacOS_write_old_rsrcs1 MWJava_MacOS_jbindrundebug0 MWJava_MacOS_stdoutfile MWJava_MacOS_stdinfile MWJava_Output_outputtypeJarFile MWJava_Output_outfileJavaClasses.jar MWJava_Output_ftype1514754080 MWJava_Output_fcreator1297570384 MWJava_Output_compress0 MWJava_Output_genManifest0 MWJava_Output_trunctypeFront MWJava_Output_deleteClasses0 MWJava_Output_consoleApp1 MWJava_Proj_projtypeApplet MWJava_Proj_runtimeArgs MWJava_Proj_mainClassName MWJava_Proj_HTMLAppCreator1297303877 MWJava_Proj_HTMLAppNameInternet Explorer MWJava_Proj_HTMLAppWin32NameIexplore.exe MWJava_Proj_compress0 MWJava_Proj_useVM1 MWJava_Proj_workingDir MWJava_Proj_vmarguments MWJava_Proj_vmName MWJavaDoc_Proj_Version1 MWJavaDoc_Proj_Depricated0 MWJavaDoc_Proj_Author1 MWJavaDoc_Proj_Index1 MWJavaDoc_Proj_Tree1 MWJavaDoc_Proj_SunResolveToSame1 MWJavaDoc_Proj_Shortnames1 MWJavaDoc_Proj_Folder0 MWJavaDoc_Proj_GenerateAPILinks0 MWJavaDoc_Proj_scopePublic MWJavaDoc_Proj_fcreator1297303877 MWJavaDoc_Proj_encodingName MWJavaDoc_Proj_decodingName MWJavaDoc_Proj_javaPackagePathhttp://java.sun.com/products/jdk/1.1/docs/api/ MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources ‰aˆ MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesInline MWCodeGen_PPC_processorGeneric MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule0 MWCodeGen_PPC_peephole0 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata0 MWCodeGen_PPC_vrsave0 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym0 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs1 MWLinker_PPC_linkmodeFast MWLinker_PPC_initname MWLinker_PPC_mainname__start MWLinker_PPC_termname MWPEF_exportsNone MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads0 MWProject_PPC_typeApplication MWProject_PPC_outfileUnzip (PPC) MWProject_PPC_filecreator1230662000 MWProject_PPC_filetype1095782476 MWProject_PPC_size2048 MWProject_PPC_minsize1024 MWProject_PPC_stacksize512 MWProject_PPC_flags22720 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name MSL C.PPC.Lib MacOS Library Name MSL C++.PPC.Lib MacOS Library Name InterfaceLib MacOS Library Name MathLib MacOS Library Name MSL RuntimePPC.Lib MacOS Library Name MSL SIOUX.PPC.Lib MacOS Library Debug Name inflate.h MacOS Text Name globals.h MacOS Text Name unzip.h MacOS Text Name unzip.c MacOS Text Name explode.c MacOS Text Name extract.c MacOS Text Name fileio.c MacOS Text Name list.c MacOS Text Name globals.c MacOS Text Name match.c MacOS Text Name zipinfo.c MacOS Text Name inflate.c MacOS Text Name process.c MacOS Text Name unshrink.c MacOS Text Name unreduce.c MacOS Text Name unzpriv.h MacOS Text Name macdir.c MacOS Text Name crc32.c MacOS Text Name crypt.c MacOS Text Name ttyio.c MacOS Text Name helpers.c MacOS Text Name helpers.h MacOS Text Name macstuff.h MacOS Text Name pathname.c MacOS Text Name pathname.h MacOS Text Name maccfg.h MacOS Text Name macscreen.c MacOS Text Name macunzip.c MacOS Text Name sxunzip.c MacOS Text Name envargs.c MacOS Text Name UnZp.h MacOS Text Name mactime.c MacOS Text Name macstat.c MacOS Text Name macstat.h MacOS Text Name unzip.rc MacOS Resource Name charmap.h MacOS Text Name FSp_fopen.c MacOS Text Name getenv.c MacOS Text Name macos.c MacOS Text Name macbin3.h MacOS Text Name macbin3.c MacOS Text Name console.stubs.c MacOS Text Name DirectoryCopy.h MacOS Text Name FileCopy.h MacOS Text Name FSpCompat.h MacOS Text Name FullPath.h MacOS Text Name IterateDirectory.h MacOS Text Name MoreDesktopMgr.h MacOS Text Name MoreFiles.h MacOS Text Name MoreFilesExtras.h MacOS Text Name Optimization.h MacOS Text Name OptimizationEnd.h MacOS Text Name Search.h MacOS Text Name inflate.h MacOS Name globals.h MacOS Name unzip.h MacOS Name unzip.c MacOS Name explode.c MacOS Name extract.c MacOS Name fileio.c MacOS Name list.c MacOS Name globals.c MacOS Name match.c MacOS Name zipinfo.c MacOS Name inflate.c MacOS Name process.c MacOS Name unshrink.c MacOS Name unreduce.c MacOS Name unzpriv.h MacOS Name macdir.c MacOS Name crc32.c MacOS Name crypt.c MacOS Name ttyio.c MacOS Name helpers.c MacOS Name helpers.h MacOS Name macstuff.h MacOS Name pathname.c MacOS Name pathname.h MacOS Name maccfg.h MacOS Name macscreen.c MacOS Name macunzip.c MacOS Name sxunzip.c MacOS Name envargs.c MacOS Name UnZp.h MacOS Name mactime.c MacOS Name macstat.c MacOS Name macstat.h MacOS Name charmap.h MacOS Name FSp_fopen.c MacOS Name getenv.c MacOS Name unzip.rc MacOS Name MSL C.PPC.Lib MacOS Name MSL C++.PPC.Lib MacOS Name InterfaceLib MacOS Name MathLib MacOS Name MSL RuntimePPC.Lib MacOS Name MSL SIOUX.PPC.Lib MacOS Name macos.c MacOS Name macbin3.h MacOS Name macbin3.c MacOS Name console.stubs.c MacOS Name DirectoryCopy.h MacOS Name FileCopy.h MacOS Name FSpCompat.h MacOS Name FullPath.h MacOS Name IterateDirectory.h MacOS Name MoreDesktopMgr.h MacOS Name MoreFiles.h MacOS Name MoreFilesExtras.h MacOS Name Optimization.h MacOS Name OptimizationEnd.h MacOS Name Search.h MacOS Unzip (68k) UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::izshr:macos: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:CHeaders: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:PascalInterfaces: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:Sources: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS 68K Linker PreLinker PostLinker TargetnameUnzip (68k) OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeOBJ FileExtension CompilerMPW Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.p CompilerMW Pascal 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ 68K Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ 68K Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.ppu CompilerMW Pascal 68K Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.seg Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowsertrue DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeLarge MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel4 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym0 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeApplication MWProject_68K_outfileUnzip (68k) MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1095782476 MWProject_68K_size384 MWProject_68K_flags22720 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize384 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen0 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs1 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnameUnZp.h MWFrontEnd_C_ansistrict1 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings0 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse1 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma0 MWWarning_C_warn_emptydecl0 MWWarning_C_warn_possunwant0 MWWarning_C_warn_unusedvar0 MWWarning_C_warn_unusedarg0 MWWarning_C_warn_extracomma0 MWWarning_C_pedantic0 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual0 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWFTP_Post_hostName MWFTP_Post_username MWFTP_Post_password MWFTP_Post_remoteDir MWFTP_Post_uploadDir MWFTP_Post_ftp_port21 MWFTP_Post_SendBin1 MWFTP_Post_ShouldLog1 MWCommandLine_Java_clsName MWCommandLine_Java_args MWJava_Language_optimize0 MWJava_Language_warnDeprecated0 MWJava_Language_emitMap0 MWJava_Language_strictFileNames0 MWJava_Language_strictFileHierarchy0 MWJava_Language_emitHeadersNoNativeHeaders MWJava_Language_packageFilter MWJava_Language_genComments1 MWJava_Language_genHeaders0 MWJava_MacOS_typeJBindery MWJava_MacOS_grow0 MWJava_MacOS_profile0 MWJava_MacOS_verify0 MWJava_MacOS_useHttpProxy0 MWJava_MacOS_useFTPProxy0 MWJava_MacOS_useFirewallProxy0 MWJava_MacOS_outfileJBoundApp MWJava_MacOS_outcreator1061109567 MWJava_MacOS_maxMem1048576 MWJava_MacOS_minMem524288 MWJava_MacOS_red65535 MWJava_MacOS_green65535 MWJava_MacOS_blue65535 MWJava_MacOS_stdoutType1464421956 MWJava_MacOS_stdinType1853189228 MWJava_MacOS_httpProxyPort0 MWJava_MacOS_fTPProxyPort0 MWJava_MacOS_firewallProxyPort0 MWJava_MacOS_httpProxy MWJava_MacOS_fTPProxy MWJava_MacOS_firewallProxy MWJava_MacOS_merge0 MWJava_MacOS_write_old_rsrcs1 MWJava_MacOS_jbindrundebug0 MWJava_MacOS_stdoutfile MWJava_MacOS_stdinfile MWJava_Output_outputtypeJarFile MWJava_Output_outfileJavaClasses.jar MWJava_Output_ftype1514754080 MWJava_Output_fcreator1297570384 MWJava_Output_compress0 MWJava_Output_genManifest0 MWJava_Output_trunctypeFront MWJava_Output_deleteClasses0 MWJava_Output_consoleApp1 MWJava_Proj_projtypeApplet MWJava_Proj_runtimeArgs MWJava_Proj_mainClassName MWJava_Proj_HTMLAppCreator1297303877 MWJava_Proj_HTMLAppNameInternet Explorer MWJava_Proj_HTMLAppWin32NameIexplore.exe MWJava_Proj_compress0 MWJava_Proj_useVM1 MWJava_Proj_workingDir MWJava_Proj_vmarguments MWJava_Proj_vmName MWJavaDoc_Proj_Version1 MWJavaDoc_Proj_Depricated0 MWJavaDoc_Proj_Author1 MWJavaDoc_Proj_Index1 MWJavaDoc_Proj_Tree1 MWJavaDoc_Proj_SunResolveToSame1 MWJavaDoc_Proj_Shortnames1 MWJavaDoc_Proj_Folder0 MWJavaDoc_Proj_GenerateAPILinks0 MWJavaDoc_Proj_scopePublic MWJavaDoc_Proj_fcreator1297303877 MWJavaDoc_Proj_encodingName MWJavaDoc_Proj_decodingName MWJavaDoc_Proj_javaPackagePathhttp://java.sun.com/products/jdk/1.1/docs/api/ MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources ‰aˆ MWCodeGen_PPC_structalignmentPPC MWCodeGen_PPC_tracebacktablesInline MWCodeGen_PPC_processorGeneric MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule0 MWCodeGen_PPC_peephole0 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata0 MWCodeGen_PPC_vrsave0 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym0 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs1 MWLinker_PPC_linkmodeFast MWLinker_PPC_initname MWLinker_PPC_mainname__start MWLinker_PPC_termname MWPEF_exportsNone MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads0 MWProject_PPC_typeApplication MWProject_PPC_outfileUnzip (PPC) MWProject_PPC_filecreator1230662000 MWProject_PPC_filetype1095782476 MWProject_PPC_size2048 MWProject_PPC_minsize1024 MWProject_PPC_stacksize512 MWProject_PPC_flags22720 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name inflate.h MacOS Text Name globals.h MacOS Text Name unzip.h MacOS Text Name unzip.c MacOS Text Name envargs.c MacOS Text Name explode.c MacOS Text Name extract.c MacOS Text Name fileio.c MacOS Text Name list.c MacOS Text Name globals.c MacOS Text Name match.c MacOS Text Name zipinfo.c MacOS Text Name inflate.c MacOS Text Name process.c MacOS Text Name unshrink.c MacOS Text Name unreduce.c MacOS Text Name unzpriv.h MacOS Text Name macdir.c MacOS Text Name crc32.c MacOS Text Name crypt.c MacOS Text Name ttyio.c MacOS Text Name helpers.c MacOS Text Name helpers.h MacOS Text Name macstuff.h MacOS Text Name pathname.c MacOS Text Name pathname.h MacOS Text Name maccfg.h MacOS Text Name macscreen.c MacOS Text Name macunzip.c MacOS Text Name sxunzip.c MacOS Text Name UnZp.h MacOS Text Name mactime.c MacOS Text Name macstat.c MacOS Text Name macstat.h MacOS Text Name unzip.rc MacOS Resource Name charmap.h MacOS Text Name FSp_fopen.c MacOS Text Name getenv.c MacOS Text Name macos.c MacOS Text Name macbin3.h MacOS Text Name macbin3.c MacOS Text Name console.stubs.c MacOS Text Name MSL Runtime68K.Lib MacOS Library Name MacOS.lib MacOS Library Name MathLib68K (2i).Lib MacOS Library Name DirectoryCopy.h MacOS Text Name FileCopy.h MacOS Text Name FSpCompat.h MacOS Text Name FullPath.h MacOS Text Name IterateDirectory.h MacOS Text Name MoreDesktopMgr.h MacOS Text Name MoreFiles.h MacOS Text Name MoreFilesExtras.h MacOS Text Name Optimization.h MacOS Text Name OptimizationEnd.h MacOS Text Name Search.h MacOS Text First Segment Preloaded, Protected, Locked Name inflate.h MacOS Name globals.h MacOS Name unzip.h MacOS Name unzip.c MacOS Name envargs.c MacOS Name explode.c MacOS Name extract.c MacOS Name fileio.c MacOS Name list.c MacOS Name globals.c MacOS Name match.c MacOS Name zipinfo.c MacOS Name inflate.c MacOS Name process.c MacOS Name unshrink.c MacOS Name unreduce.c MacOS Name unzpriv.h MacOS Name macdir.c MacOS Name crc32.c MacOS Name crypt.c MacOS Name ttyio.c MacOS Name helpers.c MacOS Name helpers.h MacOS Name macstuff.h MacOS Name pathname.c MacOS Name pathname.h MacOS Name maccfg.h MacOS Name macscreen.c MacOS Name macunzip.c MacOS Name sxunzip.c MacOS Name UnZp.h MacOS Name mactime.c MacOS Name macstat.c MacOS Name macstat.h MacOS Name charmap.h MacOS Name FSp_fopen.c MacOS Name getenv.c MacOS Name unzip.rc MacOS Name macos.c MacOS Name macbin3.h MacOS Name macbin3.c MacOS Name console.stubs.c MacOS Name MSL Runtime68K.Lib MacOS Name MacOS.lib MacOS Name MathLib68K (2i).Lib MacOS Name DirectoryCopy.h MacOS Name FileCopy.h MacOS Name FSpCompat.h MacOS Name FullPath.h MacOS Name IterateDirectory.h MacOS Name MoreDesktopMgr.h MacOS Name MoreFiles.h MacOS Name MoreFilesExtras.h MacOS Name Optimization.h MacOS Name OptimizationEnd.h MacOS Name Search.h MacOS Unzip Lib (CFM68k) UserSourceTrees CustomColor1 Red0 Green32767 Blue0 CustomColor2 Red0 Green32767 Blue0 CustomColor3 Red0 Green32767 Blue0 CustomColor4 Red0 Green32767 Blue0 AlwaysSearchUserPathsfalse InterpretDOSAndUnixPathsfalse UserSearchPaths SearchPath Path: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::izshr:macos: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:CHeaders: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:PascalInterfaces: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SearchPath Path:::MoreFiles:Sources: PathFormatMacOS PathRootProject Recursivetrue HostFlagsAll SystemSearchPaths SearchPath Path:MSL: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path:MacOS Support: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll SearchPath Path: PathFormatMacOS PathRootCodeWarrior Recursivetrue HostFlagsAll LinkerMacOS 68K Linker PreLinker PostLinker TargetnameUnzip Lib (CFM68k) OutputDirectory Path: PathFormatMacOS PathRootProject SaveEntriesUsingRelativePathsfalse FileMappings FileTypeAPPL FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeAppl FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeMMLB FileExtension CompilerLib Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMPLF FileExtension CompilerLib Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeMWCD FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeOBJ FileExtension CompilerMPW Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeRSRC FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeTEXT FileExtension.bh CompilerBalloon Help Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.c++ CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cc CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cp CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.cpp CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.exp Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.h CompilerMW C/C++ 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMaketrue FileTypeTEXT FileExtension.p CompilerMW Pascal 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pas CompilerMW Pascal 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch CompilerMW C/C++ 68K Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.pch++ CompilerMW C/C++ 68K Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.ppu CompilerMW Pascal 68K Precompiletrue Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.r CompilerRez Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypeTEXT FileExtension.seg Compiler Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypedocu FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypersrc FileExtension Compiler Precompilefalse Launchabletrue ResourceFiletrue IgnoredByMakefalse FileTypeshlb FileExtension CompilerPEF Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileTypestub FileExtension CompilerPEF Import 68K Precompilefalse Launchablefalse ResourceFilefalse IgnoredByMakefalse FileExtension.doc Compiler Precompilefalse Launchabletrue ResourceFilefalse IgnoredByMaketrue CacheModDatestrue ActivateBrowsertrue DumpBrowserInfofalse CacheSubprojectstrue UseThirdPartyDebuggerfalse DebuggerCommandLine Debugger Runtime 0002000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 LogSystemMessagestrue AutoTargetDLLsfalse StopAtWatchpointstrue PauseWhileRunningfalse PauseInterval5 PauseUIFlags0 AltExePath Path PathFormatGeneric PathRootAbsolute StopAtTempBPOnLaunchtrue CacheSymbolicstrue TempBPFunctionNamemain TempBPTypefalse MWCodeGen_68K_codesizeLarge MWCodeGen_68K_structalignmentMC68K MWCodeGen_68K_fp_modeSANE MWCodeGen_68K_code680200 MWCodeGen_68K_profiler0 MWCodeGen_68K_mpwc0 MWCodeGen_68K_fourbyteints1 MWCodeGen_68K_IEEEdoubles1 MWCodeGen_68K_fardata1 MWCodeGen_68K_farvtables1 MWCodeGen_68K_farstrings1 MWCodeGen_68K_pcrelstrings0 MWCodeGen_68K_macsbugNew MWCodeGen_68K_a6frames1 MWDisassembler_68K_showcode1 MWDisassembler_68K_mix0 MWDisassembler_68K_nohex0 MWDisassembler_68K_showdata1 MWDisassembler_68K_showexceptions1 MWDisassembler_68K_showsym0 MWDisassembler_68K_shownames1 GlobalOptimizer_68K_optimizationlevelLevel4 GlobalOptimizer_68K_optforSpeed MWLinker_68K_linksym0 MWLinker_68K_symfullpath1 MWLinker_68K_linksingle0 MWLinker_68K_fastlink1 MWLinker_68K_generateMap0 MWLinker_68K_nolinkwarnings0 MWLinker_68K_glueintosegone1 MWLinker_68K_dontdeadstripinitcode0 MWProject_68K_typeLibrary MWProject_68K_outfileUnzip Lib (CFM68k) MWProject_68K_symfilename MWProject_68K_filecreator1061109567 MWProject_68K_filetype1061109567 MWProject_68K_size0 MWProject_68K_flags0 MWProject_68K_rsrcheaderStandard MWProject_68K_rsrcname MWProject_68K_rsrctype1061109567 MWProject_68K_rsrcid0 MWProject_68K_rsrcmulti0 MWProject_68K_rsrcstore0 MWProject_68K_rsrcmerge0 MWProject_68K_rsrcflags0 MWProject_68K_a40 MWProject_68K_minsize0 MWProject_68K_rsrcsegtype0 MWProject_68K_cfm68kcodegen1 MWProject_68K_stacksize0 MWProject_68K_thedebugger0 MWProject_68K_rsrc_custom0 MWProject_68K_is_rseg_app0 MWProject_68K_is_pilot_lib0 MWProject_68K_pilot_main_entry MWFrontEnd_C_cplusplus0 MWFrontEnd_C_checkprotos1 MWFrontEnd_C_arm0 MWFrontEnd_C_trigraphs1 MWFrontEnd_C_onlystdkeywords0 MWFrontEnd_C_enumsalwaysint0 MWFrontEnd_C_mpwpointerstyle0 MWFrontEnd_C_prefixnameUnZpLib.h MWFrontEnd_C_ansistrict1 MWFrontEnd_C_mpwcnewline0 MWFrontEnd_C_wchar_type1 MWFrontEnd_C_enableexceptions0 MWFrontEnd_C_dontreusestrings1 MWFrontEnd_C_poolstrings0 MWFrontEnd_C_dontinline0 MWFrontEnd_C_useRTTI0 MWFrontEnd_C_multibyteaware0 MWFrontEnd_C_unsignedchars0 MWFrontEnd_C_autoinline0 MWFrontEnd_C_booltruefalse1 MWFrontEnd_C_direct_to_som0 MWFrontEnd_C_som_env_check0 MWFrontEnd_C_alwaysinline0 MWFrontEnd_C_inlinelevel0 MWFrontEnd_C_ecplusplus0 MWFrontEnd_C_objective_c0 MWFrontEnd_C_defer_codegen0 MWWarning_C_warn_illpragma1 MWWarning_C_warn_emptydecl1 MWWarning_C_warn_possunwant1 MWWarning_C_warn_unusedvar1 MWWarning_C_warn_unusedarg1 MWWarning_C_warn_extracomma1 MWWarning_C_pedantic1 MWWarning_C_warningerrors0 MWWarning_C_warn_hidevirtual1 MWWarning_C_warn_implicitconv0 MWWarning_C_warn_notinlined0 MWWarning_C_warn_structclass0 MWCFM68K_exportsNone MWCFM68K_olddefversion0 MWCFM68K_oldimpversion0 MWCFM68K_currentversion0 MWCFM68K_farthreshold256 PCFM68K_sharedata0 MWCFM68K_fragmentname MWCFM68K_initname MWCFM68K_mainname__start MWCFM68K_termname MWCFM68K_libfolder0 MWCFM68K_alignmentAlign_2 MWFTP_Post_hostName MWFTP_Post_username MWFTP_Post_password MWFTP_Post_remoteDir MWFTP_Post_uploadDir MWFTP_Post_ftp_port21 MWFTP_Post_SendBin1 MWFTP_Post_ShouldLog1 MWCommandLine_Java_clsName MWCommandLine_Java_args MWJava_Language_optimize0 MWJava_Language_warnDeprecated0 MWJava_Language_emitMap0 MWJava_Language_strictFileNames0 MWJava_Language_strictFileHierarchy0 MWJava_Language_emitHeadersNoNativeHeaders MWJava_Language_packageFilter MWJava_Language_genComments1 MWJava_Language_genHeaders0 MWJava_MacOS_typeJBindery MWJava_MacOS_grow0 MWJava_MacOS_profile0 MWJava_MacOS_verify0 MWJava_MacOS_useHttpProxy0 MWJava_MacOS_useFTPProxy0 MWJava_MacOS_useFirewallProxy0 MWJava_MacOS_outfileJBoundApp MWJava_MacOS_outcreator1061109567 MWJava_MacOS_maxMem1048576 MWJava_MacOS_minMem524288 MWJava_MacOS_red65535 MWJava_MacOS_green65535 MWJava_MacOS_blue65535 MWJava_MacOS_stdoutType1464421956 MWJava_MacOS_stdinType1853189228 MWJava_MacOS_httpProxyPort0 MWJava_MacOS_fTPProxyPort0 MWJava_MacOS_firewallProxyPort0 MWJava_MacOS_httpProxy MWJava_MacOS_fTPProxy MWJava_MacOS_firewallProxy MWJava_MacOS_merge0 MWJava_MacOS_write_old_rsrcs1 MWJava_MacOS_jbindrundebug0 MWJava_MacOS_stdoutfile MWJava_MacOS_stdinfile MWJava_Output_outputtypeJarFile MWJava_Output_outfileJavaClasses.jar MWJava_Output_ftype1514754080 MWJava_Output_fcreator1297570384 MWJava_Output_compress0 MWJava_Output_genManifest0 MWJava_Output_trunctypeFront MWJava_Output_deleteClasses0 MWJava_Output_consoleApp1 MWJava_Proj_projtypeApplet MWJava_Proj_runtimeArgs MWJava_Proj_mainClassName MWJava_Proj_HTMLAppCreator1297303877 MWJava_Proj_HTMLAppNameInternet Explorer MWJava_Proj_HTMLAppWin32NameIexplore.exe MWJava_Proj_compress0 MWJava_Proj_useVM1 MWJava_Proj_workingDir MWJava_Proj_vmarguments MWJava_Proj_vmName MWJavaDoc_Proj_Version1 MWJavaDoc_Proj_Depricated0 MWJavaDoc_Proj_Author1 MWJavaDoc_Proj_Index1 MWJavaDoc_Proj_Tree1 MWJavaDoc_Proj_SunResolveToSame1 MWJavaDoc_Proj_Shortnames1 MWJavaDoc_Proj_Folder0 MWJavaDoc_Proj_GenerateAPILinks0 MWJavaDoc_Proj_scopePublic MWJavaDoc_Proj_fcreator1297303877 MWJavaDoc_Proj_encodingName MWJavaDoc_Proj_decodingName MWJavaDoc_Proj_javaPackagePathhttp://java.sun.com/products/jdk/1.1/docs/api/ MWMerge_MacOS_projectTypeApplication MWMerge_MacOS_outputNameMerge Out MWMerge_MacOS_outputCreator1061109567 MWMerge_MacOS_outputType1095782476 MWMerge_MacOS_suppressWarning0 MWMerge_MacOS_copyFragments1 MWMerge_MacOS_copyResources1 MWMerge_MacOS_skipResources ‰aˆ MWCodeGen_PPC_structalignmentMC68K MWCodeGen_PPC_tracebacktablesNone MWCodeGen_PPC_processorGeneric MWCodeGen_PPC_readonlystrings0 MWCodeGen_PPC_tocdata1 MWCodeGen_PPC_profiler0 MWCodeGen_PPC_fpcontract1 MWCodeGen_PPC_schedule0 MWCodeGen_PPC_peephole1 MWCodeGen_PPC_processorspecific0 MWCodeGen_PPC_altivec0 MWCodeGen_PPC_vectortocdata0 MWCodeGen_PPC_vrsave0 MWDisassembler_PPC_showcode1 MWDisassembler_PPC_extended1 MWDisassembler_PPC_mix0 MWDisassembler_PPC_nohex0 MWDisassembler_PPC_showdata1 MWDisassembler_PPC_showexceptions1 MWDisassembler_PPC_showsym0 MWDisassembler_PPC_shownames1 GlobalOptimizer_PPC_optimizationlevelLevel0 GlobalOptimizer_PPC_optforSpeed MWLinker_PPC_linksym1 MWLinker_PPC_symfullpath1 MWLinker_PPC_linkmap0 MWLinker_PPC_nolinkwarnings0 MWLinker_PPC_dontdeadstripinitcode0 MWLinker_PPC_permitmultdefs0 MWLinker_PPC_linkmodeFast MWLinker_PPC_initname MWLinker_PPC_mainname__start MWLinker_PPC_termname MWPEF_exportsNone MWPEF_libfolder0 MWPEF_sortcodeNone MWPEF_expandbss0 MWPEF_sharedata0 MWPEF_olddefversion0 MWPEF_oldimpversion0 MWPEF_currentversion0 MWPEF_fragmentname MWPEF_collapsereloads0 MWProject_PPC_typeApplication MWProject_PPC_outfilea.out MWProject_PPC_filecreator1061109567 MWProject_PPC_filetype1095782476 MWProject_PPC_size384 MWProject_PPC_minsize384 MWProject_PPC_stacksize64 MWProject_PPC_flags22720 MWProject_PPC_symfilename MWProject_PPC_rsrcname MWProject_PPC_rsrcheaderNative MWProject_PPC_rsrctype1061109567 MWProject_PPC_rsrcid0 MWProject_PPC_rsrcflags0 MWProject_PPC_rsrcstore0 MWProject_PPC_rsrcmerge0 MWAssembler_PPC_auxheader0 MWAssembler_PPC_symmodeMac MWAssembler_PPC_dialectPPC MWAssembler_PPC_prefixfile MWAssembler_PPC_typecheck0 MWAssembler_PPC_warnings0 MWAssembler_PPC_casesensitive0 MWRez_Language_maxwidth80 MWRez_Language_scriptRoman MWRez_Language_alignmentAlign1 MWRez_Language_filtermodeFilterSkip MWRez_Language_suppresswarnings0 MWRez_Language_escapecontrolchars1 MWRez_Language_prefixname MWRez_Language_filteredtypes'CODE' 'DATA' 'PICT' Name inflate.h MacOS Text Name globals.h MacOS Text Name unzip.h MacOS Text Name unzip.c MacOS Text Name explode.c MacOS Text Name extract.c MacOS Text Name fileio.c MacOS Text Name list.c MacOS Text Name globals.c MacOS Text Name match.c MacOS Text Name zipinfo.c MacOS Text Name inflate.c MacOS Text Name process.c MacOS Text Name unshrink.c MacOS Text Name unreduce.c MacOS Text Name unzpriv.h MacOS Text Name macdir.c MacOS Text Name maccfg.h MacOS Text Name sxunzip.c MacOS Text Name UnZpLib.h MacOS Text Name macstat.c MacOS Text Name macstat.h MacOS Text Name macos.c MacOS Text Name macbin3.h MacOS Text Name macbin3.c MacOS Text Name crypt.c MacOS Text Name DirectoryCopy.h MacOS Text Name FileCopy.h MacOS Text Name FSpCompat.h MacOS Text Name FullPath.h MacOS Text Name IterateDirectory.h MacOS Text Name MoreDesktopMgr.h MacOS Text Name MoreFiles.h MacOS Text Name MoreFilesExtras.h MacOS Text Name Optimization.h MacOS Text Name OptimizationEnd.h MacOS Text Name Search.h MacOS Text First Segment Protected, Locked Name inflate.h MacOS Name globals.h MacOS Name unzip.h MacOS Name unzip.c MacOS Name explode.c MacOS Name extract.c MacOS Name fileio.c MacOS Name list.c MacOS Name globals.c MacOS Name match.c MacOS Name zipinfo.c MacOS Name inflate.c MacOS Name process.c MacOS Name unshrink.c MacOS Name unreduce.c MacOS Name unzpriv.h MacOS Name macdir.c MacOS Name maccfg.h MacOS Name sxunzip.c MacOS Name UnZpLib.h MacOS Name macstat.c MacOS Name macstat.h MacOS Name macos.c MacOS Name macbin3.h MacOS Name macbin3.c MacOS Name crypt.c MacOS Name DirectoryCopy.h MacOS Name FileCopy.h MacOS Name FSpCompat.h MacOS Name FullPath.h MacOS Name IterateDirectory.h MacOS Name MoreDesktopMgr.h MacOS Name MoreFiles.h MacOS Name MoreFilesExtras.h MacOS Name Optimization.h MacOS Name OptimizationEnd.h MacOS Name Search.h MacOS Unzip Sioux (68k) Unzip Sioux (PPC) Unzip Lib (PPC) Unzip Lib (68k) Unzip (PPC) Unzip (68k) Unzip Lib (CFM68k) Sources Unzip (PPC) Name UnZp.h MacOS Unzip Lib (PPC) Name UnZpLib.h MacOS Unzip Sioux (68k) Name UnZpSx.h MacOS Mac-Specific include Unzip Sioux (68k) Name maccfg.h MacOS Unzip Sioux (68k) Name macstat.h MacOS Unzip Sioux (68k) Name macbin3.h MacOS source Unzip Sioux (68k) Name macos.c MacOS Unzip Sioux (68k) Name macbin3.c MacOS Unzip Sioux (68k) Name macdir.c MacOS Unzip Sioux (68k) Name macstat.c MacOS Unzip (PPC) Name macunzip.c MacOS Unzip Sioux (68k) Name sxunzip.c MacOS Unzip (PPC) Name macscreen.c MacOS UnZip_H Unzip Sioux (68k) Name inflate.h MacOS Unzip Sioux (68k) Name globals.h MacOS Unzip Sioux (68k) Name unzpriv.h MacOS Unzip Sioux (68k) Name unzip.h MacOS shared code Unzip & Zip Unzip Sioux (68k) Name getenv.c MacOS Unzip Sioux (68k) Name ttyio.c MacOS Unzip Sioux (68k) Name crc32.c MacOS Unzip Sioux (68k) Name crypt.c MacOS Unzip Sioux (68k) Name helpers.c MacOS Unzip Sioux (68k) Name helpers.h MacOS Unzip Sioux (68k) Name mactime.c MacOS Unzip Sioux (68k) Name macstuff.h MacOS Unzip Sioux (68k) Name pathname.c MacOS Unzip Sioux (68k) Name pathname.h MacOS Unzip Sioux (68k) Name charmap.h MacOS ObjS1 Unzip Sioux (68k) Name unzip.c MacOS Unzip Sioux (68k) Name envargs.c MacOS Unzip Sioux (68k) Name explode.c MacOS ObjS2 Unzip Sioux (68k) Name extract.c MacOS Unzip Sioux (68k) Name fileio.c MacOS Unzip Sioux (68k) Name list.c MacOS Unzip Sioux (68k) Name globals.c MacOS Unzip Sioux (68k) Name match.c MacOS Unzip Sioux (68k) Name zipinfo.c MacOS Unzip Sioux (68k) Name inflate.c MacOS ObjS3 Unzip Sioux (68k) Name process.c MacOS Unzip Sioux (68k) Name unshrink.c MacOS Unzip Sioux (68k) Name unreduce.c MacOS Mac Libraries 68k Unzip Sioux (68k) Name MSL Runtime68K.Lib MacOS Unzip Sioux (68k) Name MacOS.lib MacOS Unzip Sioux (68k) Name MathLib68K (2i).Lib MacOS PPC Unzip Sioux (PPC) Name InterfaceLib MacOS Unzip Sioux (PPC) Name MathLib MacOS Unzip Sioux (PPC) Name MSL RuntimePPC.Lib MacOS Unzip (PPC) Name console.stubs.c MacOS ANSI Libraries 68k PPC Unzip Sioux (PPC) Name MSL C.PPC.Lib MacOS Unzip Sioux (PPC) Name MSL C++.PPC.Lib MacOS Unzip Sioux (PPC) Name MSL SIOUX.PPC.Lib MacOS Unzip Sioux (68k) Name FSp_fopen.c MacOS FAT Target Files Resources Unzip Sioux (68k) Name unzip.rc MacOS MoreFiles CHeaders Unzip Sioux (68k) Name DirectoryCopy.h MacOS Unzip Sioux (68k) Name FileCopy.h MacOS Unzip Sioux (68k) Name FSpCompat.h MacOS Unzip Sioux (68k) Name FullPath.h MacOS Unzip Sioux (68k) Name IterateDirectory.h MacOS Unzip Sioux (68k) Name MoreDesktopMgr.h MacOS Unzip Sioux (68k) Name MoreFiles.h MacOS Unzip Sioux (68k) Name MoreFilesExtras.h MacOS Unzip Sioux (68k) Name Optimization.h MacOS Unzip Sioux (68k) Name OptimizationEnd.h MacOS Unzip Sioux (68k) Name Search.h MacOS \ No newline at end of file diff --git a/macos/UnZpSFX.h b/macos/UnZpSFX.h new file mode 100644 index 0000000..1317815 --- /dev/null +++ b/macos/UnZpSFX.h @@ -0,0 +1,158 @@ +/* + 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 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 +*/ +/*--------------------------------------------------------------------------- + + UnZpSFX.h + + This header-files is global to the project UnzipSFX standalone. + + ---------------------------------------------------------------------------*/ + +/*****************************************************************************/ +/* Macros, typedefs */ +/*****************************************************************************/ + +#define MACUNZIP_STANDALONE +#define MACUNZIP + +/* These functions are defined as a macro instead of a function. +so we have to undefine them for replacing */ +#undef getc +#undef getchar +#undef putchar +#undef putc + +#ifndef TRUE +#define TRUE 1 +#endif /* TRUE */ +#ifndef FALSE +#define FALSE 0 +#endif /* FALSE */ + +#define SFX + +/*****************************************************************************/ +/* Includes standard headers */ +/*****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int ratio(unsigned long uc,unsigned long c); + void fnprint(void); + + +/* +#define MAC_DEBUG 1 + */ + + + +#include + + +#ifdef MAC_DEBUG +#define LOG_DEBUG 7 /* debug-level messages */ +int Print2Syslog(UInt8 priority, const char *format, ...); +#include + + +#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 /* !MAC_DEBUG */ +#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 /* ?MAC_DEBUG */ diff --git a/macos/UnZpSx.h b/macos/UnZpSx.h new file mode 100644 index 0000000..d3d4446 --- /dev/null +++ b/macos/UnZpSx.h @@ -0,0 +1,142 @@ +/* + 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 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 +*/ +/*--------------------------------------------------------------------------- + + UnZpSx.h + + This header-files is global to the project Unzip Sioux. + + ---------------------------------------------------------------------------*/ + +/*****************************************************************************/ +/* Macros, typedefs */ +/*****************************************************************************/ + +#define USE_SIOUX +#define MACUNZIP + +#ifndef TRUE +#define TRUE 1 +#endif /* TRUE */ +#ifndef FALSE +#define FALSE 0 +#endif /* FALSE */ + + +/*****************************************************************************/ +/* Includes standard headers */ +/*****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +#define MAC_DEBUG 1 + */ + + +#ifdef MAC_DEBUG +#define LOG_DEBUG 7 /* debug-level messages */ +int Print2Syslog(UInt8 priority, const char *format, ...); +#include + + +#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 /* !MAC_DEBUG */ +#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 /* ?MAC_DEBUG */ 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/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 +#include +#include +#include +#include +#include +#include + +#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 +#include +#include + +#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/macbin3.c b/macos/source/macbin3.c new file mode 100644 index 0000000..f7887dd --- /dev/null +++ b/macos/source/macbin3.c @@ -0,0 +1,763 @@ +/**************************************************************** + MacBinaryIII.c + + Copyright 1997 Christopher Evans (cevans@poppybank.com) + + Basic encoding and decoding of Macintosh files to the + MacBinary III spec. + + This file is part of the MacBinaryIII_src_C.sit package + see macbin3.h for more information + +****************************************************************/ + +/*****************************************************************************/ +/* Includes */ +/*****************************************************************************/ + +#include +#include +#include "macbin3.h" + +/*****************************************************************************/ +/* Macros, typedefs */ +/*****************************************************************************/ + +/* source (the macbinary file) will be deleted */ +#define DELETE_MACBINARY_SOURCE + +/* enable encoding +#define INCLUDE_ENCODE_MACBINARY */ + +/* enable decoding */ +#define INCLUDE_DECODE_MACBINARY + +/* include own CRC 32 Bit Calculation +#define INCLUDE_CRC32CALC */ + +/* produce some helpful printouts for tracing +#define TRACE_MACBINARY */ + + + +#define LONG_AT_OFFSET(data, offset) *((long *)((unsigned char *)&data[offset])) +#define WORD_AT_OFFSET(data, offset) *((Word *)((unsigned char *)&data[offset])) +#define BYTE_AT_OFFSET(data, offset) *((Byte *)((unsigned char *)&data[offset])) +#define PTR_AT_OFFSET(data, offset) ((Ptr)((unsigned char *)&data[offset])) + +typedef unsigned short Word; + +#define kOldVersionOffset 0 +#define kFileNameLengthOffset 1 +#define kFileNameOffset 2 +#define kFileTypeOffset 65 +#define kFileCreatorOffset 69 +#define kFinderFlagsHiOffset 73 +#define kVersionCheckZero 74 +#define kFileVPositionOffset 75 +#define kFileHPositionOffset 77 +#define kFileFolderIDOffset 79 +#define kProtectedFlagOffset 81 +#define kVersionOneCheckZero 82 +#define kDataForkLengthOffset 83 +#define kResourceForkLengthOffset 87 +#define kFileCreationDateOffset 91 +#define kFileModificationDateOffset 95 +#define kGetInfoCommentLengthOffset 99 +#define kFinderFlagsLowOffset 101 +#define kMacbinarySigOffset 102 +#define kFilenameScriptOffset 106 +#define kExtendedFinderFlagsOffset 107 +#define kTotalFileLengthOffset 116 +#define kSecondaryHeaderLengthOffset 120 +#define kCurrentVersionOffset 122 +#define kMinimumVersionOffset 123 +#define kCRCOffset 124 + +#define kResourceForkMaxLen (1024 * 1024 * 16) + + +/*****************************************************************************/ +/* Module level Vars */ +/*****************************************************************************/ + +#ifdef INCLUDE_CRC32CALC +static unsigned long crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; +#endif + + +/*****************************************************************************/ +/* Prototypes */ +/*****************************************************************************/ + +static Boolean HeaderIsMacBinary(char *header, + Word *version, + long maxDataLen); +static Boolean FSpExists(FSSpec *file); +#ifdef INCLUDE_CRC32CALC +static unsigned long crc32(unsigned long seed, unsigned char *p, size_t len); +#else +extern unsigned long crc32(unsigned long seed, unsigned char *p, size_t len); +#endif +static OSErr GetDesktopComment(FSSpec *file, char*comment, long *length); +static OSErr SetDesktopComment(FSSpec *file, char*comment, long length); +static Handle EncodeMacbinary(FSSpec *file); +static OSErr DecodeMacBinary(Handle data, FSSpec *destination); + +/*****************************************************************************/ +/* Functions */ +/*****************************************************************************/ + + +#ifdef INCLUDE_CRC32CALC +/* taken from the mcvert source code */ +static unsigned long crc32(unsigned long seed, unsigned char *p, size_t len) +{ + unsigned long hold; /* crc computed so far */ + size_t i; /* index into data */ + + hold = seed; /* start with seed */ + for (i = 0; i < len; i++, p++) + { + hold ^= (*p << 8); + hold = (hold << 8) ^ crc_table[(unsigned char) (hold >> 8)]; + } + + return (hold); +} /* crc32() */ +#endif + + + +static Boolean FSpExists(FSSpec *file) +{ + FInfo fndrInfo; + + return FSpGetFInfo(file, &fndrInfo) == noErr; +} + + +static Boolean HeaderIsMacBinary(char *header, + Word *version, + long maxDataLen) +{ + Boolean isIt = false; + unsigned long resourceForkLength, dataForkLength, df_rf_length; + short commentLength; + Byte mbVersion; + +#ifdef TRACE_MACBINARY +printf("\n\n Function HeaderIsMacBinary(): "); +#endif + + if(LONG_AT_OFFSET(header, kMacbinarySigOffset) == 'mBIN') + { + isIt = true; + mbVersion = 130; + } + else + if(BYTE_AT_OFFSET(header, kVersionCheckZero) == 0 && + BYTE_AT_OFFSET(header, kOldVersionOffset) == 0) + { + if(WORD_AT_OFFSET(header, kCRCOffset) == + crc32(0, (unsigned char*) &header, 124)) + { + isIt = true; + mbVersion = 129; + } + else + { + if(BYTE_AT_OFFSET(header, kVersionOneCheckZero) == 0) + { + isIt = true; + mbVersion = 128; + } + } + } + +#ifdef TRACE_MACBINARY +printf("\n mbVersion: %d",mbVersion); +#endif + + resourceForkLength = LONG_AT_OFFSET(header, kResourceForkLengthOffset); + dataForkLength = LONG_AT_OFFSET(header, kDataForkLengthOffset); + commentLength = WORD_AT_OFFSET(header, kGetInfoCommentLengthOffset); + df_rf_length = dataForkLength + resourceForkLength; + +#ifdef TRACE_MACBINARY +printf("\n resourceForkLength: %d",resourceForkLength); +printf("\n dataForkLength: %d",dataForkLength); +printf("\n commentLength: %d",commentLength); +printf("\n df_rf_length: %d",df_rf_length); +printf("\n 1. isIt: bool: %d", + isIt); +printf("\n BYTE_AT_OFFSET(header, kFileNameLengthOffset) >= 1 bool: %d", + BYTE_AT_OFFSET(header, kFileNameLengthOffset) >= 1); +printf("\n BYTE_AT_OFFSET(header, kFileNameLengthOffset) <= 31 bool: %d", + BYTE_AT_OFFSET(header, kFileNameLengthOffset) <= 31); +printf("\n dataForkLength >= 0 bool: %d", + dataForkLength >= 0); +printf("\n resourceForkLength >= 0 bool: %d", + resourceForkLength >= 0); +printf("\n resourceForkLength <= 0x%8x bool: %d", + kResourceForkMaxLen, resourceForkLength <= kResourceForkMaxLen); +printf("\n dataForkLength <= %8u bool: %d", + maxDataLen, dataForkLength <= maxDataLen); +printf("\n df_rf_length > 0 bool: %d", + df_rf_length > 0); +printf("\n df_rf_length <= %8u bool: %d", + maxDataLen, df_rf_length <= maxDataLen); +#endif + + if(isIt && + BYTE_AT_OFFSET(header, kFileNameLengthOffset) >= 1 && + BYTE_AT_OFFSET(header, kFileNameLengthOffset) <= 31 && + dataForkLength >= 0 && + resourceForkLength >= 0 && + resourceForkLength <= kResourceForkMaxLen && + df_rf_length > 0 && + df_rf_length <= maxDataLen) + { + isIt = true; + } + else + isIt = false; /* something is wrong with the header */ + +#ifdef TRACE_MACBINARY +printf("\n 2. isIt: bool: %d", + isIt); +#endif + + if(version) + *version = mbVersion; + return isIt; +} + + + +Boolean FSpIsMacBinary(FSSpec *file) +{ + char header[128]; + short dfRefNum = 0; + OSErr err; + long size; + Boolean isIt = false; + CInfoPBRec pb; + long maxDataLen; + + memset(&pb, 0, sizeof(CInfoPBRec)); + pb.hFileInfo.ioNamePtr = file->name; + pb.hFileInfo.ioVRefNum = file->vRefNum; + pb.hFileInfo.ioFDirIndex = 0; /* query a file */ + pb.hFileInfo.ioDirID = file->parID; + err = PBGetCatInfo(&pb,false); + maxDataLen = pb.hFileInfo.ioFlLgLen; + + memset(header, 0, 128); + + err = FSpOpenDF(file, fsRdPerm, &dfRefNum); + if(!err) + { + err = GetEOF(dfRefNum, &size); + if(size > 128) + { + size = 128; + err = FSRead(dfRefNum, &size, &header); + + if(err == noErr) + { + isIt = HeaderIsMacBinary(header, nil, maxDataLen); + } + } + FSClose(dfRefNum); + } + return isIt; +} + + + +#ifdef INCLUDE_ENCODE_MACBINARY + +static OSErr GetDesktopComment(FSSpec *file, char*comment, long *length) +{ + DTPBRec pb; + OSErr err; + + pb.ioCompletion = nil; + pb.ioNamePtr = NULL; + pb.ioVRefNum = file->vRefNum; + + err = PBDTGetPath(&pb); + + if(err == noErr) + { + pb.ioNamePtr = file->name; + pb.ioDTBuffer = comment; + pb.ioDirID = file->parID; + err = PBDTGetComment(&pb, false); + *length = pb.ioDTActCount; + } + return err; +} + + + + +OSErr EncodeMacbinaryFile(FSSpec *file) +{ + Handle data; + OSErr err = paramErr; + short dfRefNum; + + data = EncodeMacbinary(file); + + if(data) + { + if(file->name[0] > 27) + file->name[0] = 27; + + PtoCstr(file->name); + strcat((char*)file->name, ".bin"); + CtoPstr((char *)file->name); + + FSpDelete(file); + if(FSpCreate(file, 'dMB3', 'mBIN', smSystemScript) == noErr) + { + err = FSpOpenDF(file, fsWrPerm, &dfRefNum); + if(err == noErr) + { + long inOutCount = GetHandleSize(data); + + HLock(data); + err = FSWrite(dfRefNum,&inOutCount,*data); + HUnlock(data); + FSClose(dfRefNum); + } + } + DisposeHandle(data); + } + return err; +} + + + + + +static Handle EncodeMacbinary(FSSpec *file) +{ + Handle result = nil; + FInfo fndrInfo; + FXInfo fndrXInfo; + OSErr err; + CInfoPBRec pb; + short dfRefNum, rfRefNum; + long ioCount; + char buffer[128]; + char header[128]; + char comment[256]; + long resourceForkLength, dataForkLength, commentLength; + + memset(&header, 0, sizeof(header)); + err = FSpGetFInfo(file, &fndrInfo); + + memset(&pb, 0, sizeof(CInfoPBRec)); + pb.hFileInfo.ioNamePtr = file->name; + pb.hFileInfo.ioVRefNum = file->vRefNum; + pb.hFileInfo.ioFDirIndex = 0; //query a file + pb.hFileInfo.ioDirID = file->parID; + err = PBGetCatInfo(&pb,false); + + fndrXInfo = pb.hFileInfo.ioFlXFndrInfo; + + BYTE_AT_OFFSET(header, kFileNameLengthOffset) = file->name[0]; + BlockMoveData( &(file->name[1]), + PTR_AT_OFFSET(header, + kFileNameOffset), + file->name[0]); + LONG_AT_OFFSET(header, kFileTypeOffset) = fndrInfo.fdType; + LONG_AT_OFFSET(header, kFileCreatorOffset) = fndrInfo.fdCreator; + + BYTE_AT_OFFSET(header, kFinderFlagsHiOffset) = + (fndrInfo.fdFlags & 0xFF00) >> 8; + BYTE_AT_OFFSET(header, kFinderFlagsLowOffset) = + (fndrInfo.fdFlags & 0x00FF); + + WORD_AT_OFFSET(header, kFileVPositionOffset) = fndrInfo.fdLocation.v; + WORD_AT_OFFSET(header, kFileHPositionOffset) = fndrInfo.fdLocation.h; + WORD_AT_OFFSET(header, kFileFolderIDOffset) = fndrInfo.fdFldr; + + LONG_AT_OFFSET(header, kFileCreationDateOffset) = pb.hFileInfo.ioFlCrDat; + LONG_AT_OFFSET(header, kFileModificationDateOffset) = + pb.hFileInfo.ioFlMdDat; + + LONG_AT_OFFSET(header, kMacbinarySigOffset) = 'mBIN'; + BYTE_AT_OFFSET(header, kFilenameScriptOffset) = fndrXInfo.fdScript; + BYTE_AT_OFFSET(header, kExtendedFinderFlagsOffset) = fndrXInfo.fdXFlags; + + LONG_AT_OFFSET(header, kTotalFileLengthOffset) = 0; + WORD_AT_OFFSET(header, kSecondaryHeaderLengthOffset) = 0; + + WORD_AT_OFFSET(header, kCurrentVersionOffset) = 130; + WORD_AT_OFFSET(header, kMinimumVersionOffset) = 129; + + err = FSpOpenDF(file,fsRdPerm,&dfRefNum); + if(err == noErr) + { + err = GetEOF(dfRefNum,&dataForkLength); + LONG_AT_OFFSET(header, kDataForkLengthOffset) = dataForkLength; + } + else + { + dfRefNum = 0; + } + + err = FSpOpenRF(file,fsRdPerm,&rfRefNum); + if(err == noErr) + { + err = GetEOF(rfRefNum,&resourceForkLength); + LONG_AT_OFFSET(header, kResourceForkLengthOffset) = resourceForkLength; + } + else + { + rfRefNum = 0; + } + + memset(comment, 0, 256); + if(GetDesktopComment(file, comment, &commentLength) != noErr) + commentLength = 0; + + WORD_AT_OFFSET(header, kGetInfoCommentLengthOffset) = commentLength; + WORD_AT_OFFSET(header, kCRCOffset) = + crc32( 0, (unsigned char*) &header, 124); + + result = TempNewHandle(0, &err); + if(result) + { + err = PtrAndHand(&header,result,128); + + if(dfRefNum && dataForkLength) + { + err = noErr; + while(dataForkLength > 0 && err == noErr) + { + ioCount = 128; + err = FSRead(dfRefNum,&ioCount,&buffer); + + if(err == noErr || err == eofErr) + err = PtrAndHand(&buffer,result,128); + + dataForkLength -= ioCount; + } + } + + if(rfRefNum && resourceForkLength) + { + err = noErr; + while(resourceForkLength > 0 && err == noErr) + { + ioCount = 128; + err = FSRead(rfRefNum,&ioCount,&buffer); + + if(err == noErr || err == eofErr) + err = PtrAndHand(&buffer,result,128); + + resourceForkLength -= ioCount; + } + } + + if(commentLength) + { + PtrAndHand(&comment,result,commentLength); + } + } + + if(rfRefNum) + FSClose(rfRefNum); + + if(dfRefNum) + FSClose(dfRefNum); + + return result; +} + +#endif /* INCLUDE_ENCODE_MACBINARY */ + + + +#ifdef INCLUDE_DECODE_MACBINARY + +static OSErr SetDesktopComment(FSSpec *file, char*comment, long length) +{ + DTPBRec pb; + OSErr err; + + pb.ioCompletion = nil; + pb.ioNamePtr = NULL; + pb.ioVRefNum = file->vRefNum; + + err = PBDTGetPath(&pb); + + if(err == noErr) + { + pb.ioNamePtr = file->name; + pb.ioDTBuffer = comment; + pb.ioDirID = file->parID; + pb.ioDTReqCount = length; + err = PBDTSetComment(&pb, false); + } + return err; +} + + + + +OSErr DecodeMacBinaryFile(FSSpec *source) +{ + Handle data = nil; + OSErr err; + short dfRefNum = 0; + long size; + FSSpec McBin_source; + + memcpy(McBin_source.name,source->name,source->name[0]+1); + McBin_source.vRefNum = source->vRefNum; + McBin_source.parID = source->parID; + + err = FSpOpenDF(source, fsRdPerm, &dfRefNum); + if(!err) + { + err = GetEOF(dfRefNum, &size); + + data = TempNewHandle(size, &err); + + if(data) + { + HLock(data); + err = FSRead(dfRefNum,&size,*data); + HUnlock(data); + } + FSClose(dfRefNum); + } + + if(data && err == noErr) + { + err = DecodeMacBinary(data, source); + DisposeHandle(data); + } + +#ifdef DELETE_MACBINARY_SOURCE + if (err == noErr) + err = FSpDelete(&McBin_source); +#endif + + return err; +} + + + + + +static OSErr DecodeMacBinary(Handle data, FSSpec *destination) +{ + Handle result = nil; + FInfo fndrInfo; + OSErr err; + CInfoPBRec pb; + short dfRefNum, rfRefNum; + long ioCount; + char header[128]; + char comment[256]; + long resourceForkLength, dataForkLength, commentLength; + Boolean isMacBinaryFile = false; + short headerEnd = 128; + long rfOffset; + long maxDataLen; + + memset(&pb, 0, sizeof(CInfoPBRec)); + pb.hFileInfo.ioNamePtr = destination->name; + pb.hFileInfo.ioVRefNum = destination->vRefNum; + pb.hFileInfo.ioFDirIndex = 0; /* query a file */ + pb.hFileInfo.ioDirID = destination->parID; + err = PBGetCatInfo(&pb,false); + maxDataLen = pb.hFileInfo.ioFlLgLen; + + HLock(data); + memcpy(header, *data, 128); + + /* already checked with FSpIsMacBinary() */ + isMacBinaryFile = HeaderIsMacBinary(header, nil, maxDataLen);; + + if(!isMacBinaryFile) + return paramErr; + + if(WORD_AT_OFFSET(header, kSecondaryHeaderLengthOffset)) + { + headerEnd = WORD_AT_OFFSET(header, kSecondaryHeaderLengthOffset); + headerEnd = (headerEnd + 127) & ~127L; + } + + resourceForkLength = LONG_AT_OFFSET(header, kResourceForkLengthOffset); + dataForkLength = LONG_AT_OFFSET(header, kDataForkLengthOffset); + commentLength = WORD_AT_OFFSET(header, kGetInfoCommentLengthOffset); + + memcpy( destination->name, + PTR_AT_OFFSET(header, + kFileNameLengthOffset), + BYTE_AT_OFFSET(header, + kFileNameLengthOffset)); + + fndrInfo.fdType = LONG_AT_OFFSET(header, kFileTypeOffset); + fndrInfo.fdCreator = LONG_AT_OFFSET(header, kFileCreatorOffset); + + fndrInfo.fdFlags = BYTE_AT_OFFSET(header, kFinderFlagsHiOffset); + fndrInfo.fdFlags << 8; + fndrInfo.fdFlags |= BYTE_AT_OFFSET(header, kFinderFlagsLowOffset); + + fndrInfo.fdLocation.v = WORD_AT_OFFSET(header, kFileVPositionOffset); + fndrInfo.fdLocation.h = WORD_AT_OFFSET(header, kFileHPositionOffset); + fndrInfo.fdFldr = WORD_AT_OFFSET(header, kFileFolderIDOffset); +/* + index = 1; + checkFile = *destination; + while(FSpExists(&checkFile)) + { + checkFile = *destination; + + if(index < 10) + checkFile.name[++checkFile.name[0]] = '0' + index; + else + checkFile.name[++checkFile.name[0]] = ('a' - 10) + index; + index++; + } + *destination = checkFile; +*/ + err = FSpCreate(destination, + fndrInfo.fdCreator, + fndrInfo.fdType, + smSystemScript); + + dfRefNum = 0; + if(err == noErr) + { + err = FSpOpenDF(destination, fsRdWrPerm, &dfRefNum); + } + + if(err == noErr && dfRefNum) + { + ioCount = dataForkLength; + err = FSWrite(dfRefNum,&ioCount,*data + headerEnd); + FSClose(dfRefNum); + } + + rfRefNum = 0; + if(err == noErr) + { + err = FSpOpenRF(destination, fsRdWrPerm, &rfRefNum); + } + + rfOffset = headerEnd + dataForkLength; + rfOffset = (rfOffset + 127) & ~127L; + + if(err == noErr && rfRefNum) + { + ioCount = resourceForkLength; + err = FSWrite(rfRefNum,&ioCount,*data + rfOffset); + FSClose(rfRefNum); + } + + rfOffset += resourceForkLength; + rfOffset = (rfOffset + 127) & ~127L; + + if(err == noErr) + { + FSpSetFInfo(destination,&fndrInfo); + + memset(&pb, 0, sizeof(CInfoPBRec)); + pb.hFileInfo.ioNamePtr = destination->name; + pb.hFileInfo.ioVRefNum = destination->vRefNum; + pb.hFileInfo.ioFDirIndex = 0; /* query a file */ + pb.hFileInfo.ioDirID = destination->parID; + err = PBGetCatInfo(&pb,false); + + if(err == noErr) + { + pb.hFileInfo.ioDirID = destination->parID; + pb.hFileInfo.ioFlCrDat = + LONG_AT_OFFSET(header, kFileCreationDateOffset); + pb.hFileInfo.ioFlMdDat = + LONG_AT_OFFSET(header, kFileModificationDateOffset); + pb.hFileInfo.ioFlXFndrInfo.fdXFlags = + BYTE_AT_OFFSET(header, kExtendedFinderFlagsOffset); + pb.hFileInfo.ioFlXFndrInfo.fdScript = + BYTE_AT_OFFSET(header, kFilenameScriptOffset); + err = PBSetCatInfo(&pb, false); + } + + if(commentLength) + { + memcpy(comment,*data + rfOffset, commentLength); + SetDesktopComment(destination, comment, commentLength); + } + + } + HUnlock(data); + return err; +} + +#endif /* INCLUDE_DECODE_MACBINARY */ + + + diff --git a/macos/source/macbin3.h b/macos/source/macbin3.h new file mode 100644 index 0000000..fd694e6 --- /dev/null +++ b/macos/source/macbin3.h @@ -0,0 +1,153 @@ +#ifndef __MCBINIII_H__ +#define __MCBINIII_H__ + + +/**************************************************************** + MacBinaryIII.h + + Copyright 1997 Christopher Evans (cevans@poppybank.com) + + Basic encoding and decoding of Macintosh files to the + MacBinary III spec. +****************************************************************/ + + +/* +-------------------------------------------------------------------- +This source is copyrighted by Christopher Evans (cevans@poppybank.com) +(available at ftp://ftp.lazerware.com/MacBinaryIII_src_C.sit + homepage of Leonard Rosenthol leonardr@netcom.com) + + + +I made the following changes: + * renamed files MacBinaryIII.h / MacBinaryIII.c to + macbin3.c / macbin3.h + * removed pragmas: + #pragma once + #pragma options align=mac68k + * added 5 macros to make the migration into other projects easier: + DELETE_MACBINARY_SOURCE -> delete the macbinary file after + decoding + INCLUDE_ENCODE_MACBINARY -> include the encode-part of the source + INCLUDE_DECODE_MACBINARY -> include the decode-part of the source + INCLUDE_CRC32CALC -> include the CRC32 calculation + TRACE_MACBINARY -> produce some diagnostic printouts + * changed the source layout to fit into a 80 col window + * removed non-ASCII characters from the sources + * renamed the function CalculateCRC() to crc32() and changed + the order of the arguments. So the crc32() func of the InfoZip + package can be used instead. + * moved module specific macros and protos to the mcbiniii.c + * added comments and enhanced the documention of the MacBinary Spec + * changed definition crc_table[] from short to unsigned long. + * improved the HeaderIsMacBinary() function to be more restrictive + +The specification says: + "Offsets 83 and 87, Long Word, (the length of the forks) + should be in the range of 0-$007FFFFF " +However, I do not understand the reason of this range. The data fork +can be much larger than $007FFFFF ( 2 Gigabytes! ) and the size of the +resource fork can be until 16 MByte. ZipIt and Stuffit seems to be +ignore this limit. +I changed this limit (see kResourceForkMaxLen), and I removed the +maximum check of the data fork. + +Dirk Haase (d_haase@sitec.de); 05.Dec.1998 + +-------------------------------------------------------------------- + + + +MacBinary III + +MacBinary is a standard format for binary transfer of arbitrary Macintosh +documents via a telecommunication link. It is intended for use both between +Macintoshes and for use in uploading arbitrary Macintosh documents to remote +systems (where it is presumed that they will be stored as an exact image of +the data transmitted). It does this by combing both the resource and data +forks (as well as the "Finder Info") of a standard Macintosh file into a +single data fork only file that can be stored on non-Macintosh machines. + + +The format of the header for MacBinary III is as follows: + Offset Length Contents + 000 Byte old version number, must be kept at zero for + compatibility + 001 Byte Length of filename (must be in the range 1-31) + 002 1 to 63 Bytes filename (only "length" bytes are significant). + 065 Long Word file type (normally expressed as four characters) + 069 Long Word file creator (normally expressed as four + characters) + 073 Byte original Finder flags + Bit 7 - isAlias. + Bit 6 - isInvisible. + Bit 5 - hasBundle. + Bit 4 - nameLocked. + Bit 3 - isStationery. + Bit 2 - hasCustomIcon. + Bit 1 - reserved. + Bit 0 - hasBeenInited. + 074 Byte zero fill, must be zero for compatibility + 075 Word file's vertical position within its window. + 077 Word file's horizontal position within its window. + 079 Word file's window or folder ID. + 081 Byte "Protected" flag (in low order bit). + 082 Byte zero fill, must be zero for compatibility + 083 Long Word Data Fork length (bytes, zero if no Data Fork). + 087 Long Word Resource Fork length (bytes, zero if no R.F.). + 091 Long Word File's creation date + 095 Long Word File's "last modified" date. + 099 Word length of Get Info comment to be sent after the + resource fork (if implemented, see below). + 101 Byte Finder Flags, bits 0-7. (Bits 8-15 are already in + byte 73) + Bit 7 - hasNoInits + Bit 6 - isShared + Bit 5 - requiresSwitchLaunch + Bit 4 - ColorReserved + Bits 1-3 - color + Bit 0 - isOnDesk + *102 Long Word signature for indentification purposes ('mBIN') + *106 Byte script of file name (from the fdScript field of an + fxInfo record) + *107 Byte extended Finder flags (from the fdXFlags field of + an fxInfo record) + 108-115 Unused (must be zeroed by creators, must be + ignored by readers) + 116 Long Word Length of total files when packed files are + unpacked. As of the writing of this document, this + field has never been used. + 120 Word Length of a secondary header. If this is non-zero, + skip this many bytes (rounded up to the next + multiple of 128). This is for future expansion + only, when sending files with MacBinary, this word + should be zero. + *122 Byte Version number of MacBinary III that the uploading + program is written for (the version is 130 for + MacBinary III) + 123 Byte Minimum MacBinary version needed to read this file + (set this value at 129 for backwards compatibility + with MacBinary II) + 124 Word CRC of previous 124 bytes + +*These fields have changed for MacBinary III. + + All values are stored in normal 68000 order, with Most Significant Byte +appearing first then the file. Any bytes in the header not defined above +should be set to zero. + +*/ + + +/* +Public functions +*/ + +OSErr EncodeMacbinaryFile(FSSpec *file); +OSErr DecodeMacBinaryFile(FSSpec *source); +Boolean FSpIsMacBinary(FSSpec *file); + + +#endif + diff --git a/macos/source/maccfg.h b/macos/source/maccfg.h new file mode 100644 index 0000000..201dbf9 --- /dev/null +++ b/macos/source/maccfg.h @@ -0,0 +1,258 @@ +/* + 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 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 +*/ +/*--------------------------------------------------------------------------- + MACOS specific configuration and declarations: + ---------------------------------------------------------------------------*/ + +#ifndef __maccfg_h +#define __maccfg_h + + +/*****************************************************************************/ +/* Macros, missing RTL declarations, compatibility typedefs */ +/*****************************************************************************/ + + +#if defined(__MWERKS__) && defined(macintosh) +# include + + typedef unsigned long mode_t; +# define _STAT + +# if (defined(MacStaticLib) || defined(USE_SIOUX)) +# define MAIN UZ_EXP UzpMain /* was UzpUnzip */ +# else +# define MAIN _dummy_main +# endif +#endif + +#ifdef THINK_C +# ifndef __STDC__ /* if Think C hasn't defined __STDC__ ... */ +# define __STDC__ 1 /* make sure it's defined: it needs it */ +# else +# if !__STDC__ /* sometimes __STDC__ is defined as 0; */ +# undef __STDC__ /* it needs to be 1 or required header */ +# define __STDC__ 1 /* files are not properly included. */ +# endif /* !__STDC__ */ +# endif +# define IOCompletionUPP ProcPtr +# define CREATOR 'KAHL' +# define MAIN _dummy_main +#endif /* THINK_C */ + +#ifdef MPW +# include +# include +# include +# include +# include +# ifndef QUERY_TRNEWLN +# define QUERY_TRNEWLN +# endif +# ifdef fileno +# undef fileno +# endif +# ifdef MCH_MACINTOSH +# define CREATOR 'Manx' +# else +# define CREATOR 'MPS ' +# endif +#endif /* MPW */ + +#include /* O_BINARY for open() w/o CR/LF translation */ +#define fileno(x) ((x) == stdout ? 1 : ((x) == stderr ? 2 : (short)(x))) +#define open macopen +#define close macclose +#define fclose(x) macclose(fileno((x))) +#define read macread +#define write macwrite +#define lseek maclseek +#define creat(x,y) maccreat((x)) +#define stat UZmacstat +#define lstat UZmacstat +#define dup +#ifndef MCH_MACINTOSH +# define NO_STRNICMP +#endif + +#define DIR_END ':' +#ifndef DATE_FORMAT +# define DATE_FORMAT DF_MDY +#endif +#define lenEOL 1 +#define PutNativeEOL *q++ = native(CR); +#define NOANSIFILT /* MWRKS C creates broken code for the ANSI-ESC filter */ +#define MALLOC_WORK +#define INT_SPRINTF + +#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)) +# define USE_EF_UT_TIME +#endif + +#undef IZ_CHECK_TZ +#undef MORE +#undef DYNAMIC_CRC_TABLE + + +#ifndef MPW +# ifndef MacStaticLib +# ifndef USE_SIOUX +# define fgets macfgets +# define fflush(f) +# define fprintf macfprintf +# define fputs(s,f) macfprintf((f), "%s", (s)) +# define printf macprintf +# ifdef putc +# undef putc +# endif +# define putc(c,f) macfprintf((f), "%c", (c)) +# endif /* !USE_SIOUX */ +# else +# ifdef putc +# undef putc +# endif +# define putc(c,f) fprintf((f), "%c", (c)) +# endif + +# define isatty(f) (((f) >= 0) || ((f) <= 2)) +#endif + +#ifndef isascii +# define isascii(c) ((unsigned char)(c) <= 0x3F) +#endif + +#include "macstat.h" +#include "macdir.h" + +#ifdef CR +# undef CR +#endif + + +#ifdef foreign +# undef foreign +#endif +#define foreign(c) ((c) & 0x80 ? MacRoman_to_WinCP1252[(c) & 0x7f] : (c)) + +#ifdef native +# undef native +#endif +#define native(c) ((c) & 0x80 ? WinCP1252_to_MacRoman[(c) & 0x7f] : (c)) +#define NATIVE "MacRoman charset" + +#ifdef _ISO_INTERN +# undef _ISO_INTERN +#endif +#define _ISO_INTERN(str1) {register uch *p;\ + for (p=(uch *)(str1); *p; p++)\ + *p = (*p & 0x80) ? WinCP1252_to_MacRoman[*p & 0x7f] : *p;} + +#ifdef _OEM_INTERN +# undef _OEM_INTERN +#endif +#ifndef IZ_OEM2ISO_ARRAY +# define IZ_OEM2ISO_ARRAY +#endif +#define _OEM_INTERN(str1) {register uch *p;\ + for (p=(uch *)(str1); *p; p++)\ + *p = (*p & 0x80) ? WinCP1252_to_MacRoman[oem2iso[*p & 0x7f]] : *p;} + +#ifdef __FILEIO_C /* get the ISO8859-1 <--> MacROMAN conversion tables */ +# include "charmap.h" +#else + extern ZCONST uch WinCP1252_to_MacRoman[128]; + extern ZCONST uch MacRoman_to_WinCP1252[128]; +#endif + + +#define EB_M3_FL_NOCHANGE 0x02 /* filename will be not changed */ +/* other EB_M3 flags are defined in unzpriv.h */ +#define EB_MAC3_SIZE (EB_HEADSIZE + EB_MAC3_HLEN) + +/*****************************************************************************/ +/* Structure typedefs */ +/*****************************************************************************/ + +typedef struct _ZipExtraHdr { + ush header; /* 2 bytes */ + ush data; /* 2 bytes */ +} ZIP_EXTRA_HEADER; + + +/* the following structure is a combination of the old and the new + extra-field definition; so it's *not* the definition of the extra-field */ + +typedef struct _MacInfo { + unsigned char *filename; /* for ZipIt ef */ + ush header; /* tag for this extra block type */ + ush data; /* total data size for this block */ + ulg size; /* uncompressed finder attribute data size */ + + ush flags; /* info bits: + bit 0 if set, file is a data fork + bit 1 if set, filename will be not changed + bit 2 if set, Attribs is uncompressed + bit 3 if set, date and times are in 64 bit; + if zero, date and times are in 32 bit + bit 4 if set, "local time - UTC" offsets are + omitted + bits 5-15 reserved; not tested; */ + + ush CompType; + ulg CRCvalue; + + CInfoPBRec fpb; /* Macintosh FInfo / FXInfo structure */ + long Cr_UTCoffs; /* difference "local time - UTC" for Creat-time */ + long Md_UTCoffs; /* difference "local time - UTC" for Modif-time */ + long Bk_UTCoffs; /* difference "local time - UTC" for Bckup-time */ + + short TextEncodingBase; /* TextEncodingBase (Charset) */ + char *FullPath; /* Path of the current file */ + char *FinderComment; /* Finder Comment of current file */ +} MACINFO; + + +/*****************************************************************************/ +/* Global Vars */ +/*****************************************************************************/ + +#define SYSTEM_SPECIFIC_GLOBALS \ + short giCursor;\ + CursHandle rghCursor[4]; /* status cursors */ + +#define SYSTEM_SPECIFIC_CTOR MacGlobalsInit + + +/*****************************************************************************/ +/* Prototypes */ +/*****************************************************************************/ + +void screenOpen OF((char *)); /* macscreen.c */ +void screenControl OF((char *, int)); /* macscreen.c */ +void screenDump OF((char *, long)); /* macscreen.c */ +void screenUpdate OF((WindowPtr)); /* macscreen.c */ +void screenClose OF((void)); /* macscreen.c */ +int macgetch OF((void)); /* macscreen.c */ + +int macmkdir OF((char *)); /* macos.c */ +short macopen OF((char *, short)); /* macos.c */ +short maccreat OF((char *)); /* macos.c */ +short macread OF((short, char *, unsigned)); /* macos.c */ +long macwrite OF((short, char *, unsigned)); /* macos.c */ +short macclose OF((short)); /* macos.c */ +long maclseek OF((short, long, short)); /* macos.c */ +char *macfgets OF((char *, int, FILE *)); /* macos.c */ +int macfprintf OF((FILE *, char *, ...)); /* macos.c */ +int macprintf OF((char *, ...)); /* macos.c */ + +ulg makePPClong(ZCONST uch *sig); +ush makePPCword(ZCONST uch *b); +void UserStop(void); + +#endif /* !__maccfg_h */ diff --git a/macos/source/macdir.c b/macos/source/macdir.c new file mode 100644 index 0000000..5bd5754 --- /dev/null +++ b/macos/source/macdir.c @@ -0,0 +1,169 @@ +/* + 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 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 +*/ +/*--------------------------------------------------------------------------- + + macdir.c + + * This file provides dirent-style directory-reading procedures + * for V7 Unix systems that don't have such procedures. + * + * + ---------------------------------------------------------------------------*/ + + +/*****************************************************************************/ +/* Includes */ +/*****************************************************************************/ + + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "macdir.h" +#include "helpers.h" +#include "pathname.h" + + +/*****************************************************************************/ +/* Functions */ +/*****************************************************************************/ + +int closedir(DIR *dPtr) +{ + free(dPtr); + + return 0; +} + + +DIR *opendir(char *dirName) +{ + int fullPath; + unsigned pathLen; + char *s; + HParamBlockRec hPB; + CInfoPBRec cPB; + DIR *dPtr; + OSErr err; + FSSpec spec; + char CompletePath[NAME_MAX]; + + GetCompletePath(CompletePath, dirName, &spec, &err); + printerr("GetCompletePath", err, err, __LINE__, __FILE__, dirName); + + if (dirName == NULL || *dirName == '\0' || + (pathLen = strlen(dirName)) >= 256) { + errno = EINVAL; + return NULL; + } + + + /* Get information about volume. */ + memset(&hPB, '\0', sizeof(hPB)); + + if (((s = strchr(dirName, ':')) == NULL) || (*dirName == ':')) { + fullPath = false; + } else { + *(s + 1) = '\0'; + hPB.volumeParam.ioVolIndex = -1; + fullPath = true; + } + + hPB.volumeParam.ioNamePtr = spec.name; + + err = PBHGetVInfoSync(&hPB); + + if ((err != noErr) || (hPB.volumeParam.ioVFSID != 0)) { + errno = ENOENT; + return NULL; + } + + /* Get information about file. */ + + memset(&cPB, '\0', sizeof(cPB)); + + if (fullPath) + cPB.hFileInfo.ioVRefNum = hPB.volumeParam.ioVRefNum; + + cPB.hFileInfo.ioNamePtr = spec.name; + + err = PBGetCatInfoSync(&cPB); + + if (err != noErr) { + errno = (err == fnfErr) ? ENOENT : EIO; + return NULL; + } + + if (!(cPB.hFileInfo.ioFlAttrib & ioDirMask)) { + errno = ENOTDIR; + return NULL; + } + + /* Get space for, and fill in, DIR structure. */ + + if ((dPtr = (DIR *)malloc(sizeof(DIR))) == NULL) { + return NULL; + } + + dPtr->ioVRefNum = cPB.dirInfo.ioVRefNum; + dPtr->ioDrDirID = cPB.dirInfo.ioDrDirID; + dPtr->ioFDirIndex = 1; + dPtr->flags = 0; + + return dPtr; +} + + +struct dirent *readdir(DIR *dPtr) +{ + struct dirent *dirPtr; + CInfoPBRec cPB; + char name[256]; + OSErr err; + + if (dPtr->flags) { + return NULL; + } + + /* Get information about file. */ + + memset(&cPB, '\0', sizeof(cPB)); + + cPB.hFileInfo.ioNamePtr = (StringPtr)name; + cPB.hFileInfo.ioFDirIndex = dPtr->ioFDirIndex; + cPB.hFileInfo.ioVRefNum = dPtr->ioVRefNum; + cPB.hFileInfo.ioDirID = dPtr->ioDrDirID; + + err = PBGetCatInfoSync(&cPB); + + if (err != noErr) { + dPtr->flags = 0xff; + errno = (err == fnfErr) ? ENOENT : EIO; + return NULL; + } + + p2cstr((StringPtr)name); + + dirPtr = &dPtr->currEntry; + + dirPtr->d_fileno = dPtr->ioFDirIndex++; + dirPtr->d_namlen = strlen(name); + strcpy(dirPtr->d_name, name); + dirPtr->d_reclen = sizeof(struct dirent) - sizeof(dirPtr->d_name) + + dirPtr->d_namlen; + + return dirPtr; +} diff --git a/macos/source/macdir.h b/macos/source/macdir.h new file mode 100644 index 0000000..429889a --- /dev/null +++ b/macos/source/macdir.h @@ -0,0 +1,62 @@ +/* + 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 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 +*/ +/***************************************************************** + * + * dirent.h + * + *****************************************************************/ + +#ifndef __DIRENT_H +#define __DIRENT_H + +#include + +#ifndef EINVAL +#define EINVAL 9 +#endif + +#ifndef EIO +#define EIO 10 +#endif + +#ifndef ENOTDIR +#define ENOTDIR 20 +#endif + +#ifndef ENOENT +#define ENOENT 39 +#endif + +#ifndef NAME_MAX +#define NAME_MAX 1024 +#endif + +struct dirent { + unsigned long d_fileno; + short d_reclen; + short d_namlen; + char d_name[NAME_MAX + 1]; +}; + +typedef struct { + short ioFDirIndex; + short ioVRefNum; + long ioDrDirID; + short flags; + struct dirent currEntry; +} DIR; + +#define direct dirent + +DIR *opendir(char *); +struct dirent *readdir(DIR *); +void rewinddir(DIR *); +int closedir(DIR *); + +#endif /* !__DIRENT_H */ diff --git a/macos/source/macos.c b/macos/source/macos.c new file mode 100644 index 0000000..77f1939 --- /dev/null +++ b/macos/source/macos.c @@ -0,0 +1,1986 @@ +/* + Copyright (c) 1990-2007 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 +*/ +/*--------------------------------------------------------------------------- + + macos.c + + Macintosh-specific routines for use with Info-ZIP's UnZip 5.4 and later. + + Contains: + do_wild () + mapattr () + checkdir () + version () + macmkdir () + macopen () + maccreat () + macread () + macwrite () + macclose () + maclseek () + BuildMacFilename() + SetFinderInfo () + isMacOSexfield () + makePPClong () + makePPCword () + PrintMacExtraInfo () + GetExtraFieldData () + DecodeMac3ExtraField () + DecodeJLEEextraField () + PrintTextEncoding () + MacGlobalsInit () + + ---------------------------------------------------------------------------*/ + + +/*****************************************************************************/ +/* Includes */ +/*****************************************************************************/ + +#define UNZIP_INTERNAL +#include "unzip.h" + +#include +#include + +#include "pathname.h" +#include "helpers.h" +#include "macstuff.h" +#include "mactime.h" +#include "macbin3.h" + +/*****************************************************************************/ +/* Macros, typedefs */ +/*****************************************************************************/ + +/* disable ZipIt support +#define SwitchZIPITefSupportOff */ + +#define read_only file_attr /* for readability only */ +#define EB_MAX_OF_VARDATA 1300 /* max possible datasize of extra-field */ + +#ifdef WILD_STOP_AT_DIR +# define WESEP , (oU.W_flag ? ':' : '\0') +#else +# define WESEP +#endif + + +/*****************************************************************************/ +/* Global Vars */ +/*****************************************************************************/ + +/* 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 */ + +Boolean MacUnzip_Noisy; /* MacUnzip_Noisy is also used by console */ + +MACINFO newExtraField; /* contains all extra-field data */ +short MacZipMode; + + +/*****************************************************************************/ +/* Module level Vars */ +/*****************************************************************************/ + +static const char MacPathEnd = ':'; /* the Macintosh dir separator */ + +static int created_dir; /* used in mapname(), checkdir() */ +static int renamed_fullpath; /* ditto */ +static FSSpec CurrentFile; + +static Boolean OpenZipFile = true; +static Boolean UseUT_ExtraField = false; +static Boolean IgnoreEF_Macfilename = false; +static short fileSystemID; + +static uch *attrbuff = NULL; +static uch *malloced_attrbuff = NULL; + +const short HFS_fileSystem = 0; + +/*****************************************************************************/ +/* Prototypes */ +/*****************************************************************************/ + +extern char *GetUnZipInfoVersions(void); + +static OSErr SetFinderInfo(__GPRO__ int SetTime, FSSpec *spec, MACINFO *mi); +static Boolean GetExtraFieldData(short *MacZipMode, MACINFO *mi); +static uch *scanMacOSexfield(uch *ef_ptr, unsigned ef_len, + short *MacZipMode); +static Boolean isMacOSexfield(unsigned id, unsigned size, short *MacZipMode); +static void PrintMacExtraInfo(MACINFO *mi); +static OSErr SetFileTime(__GPRO); +static void DecodeMac3ExtraField(ZCONST uch *buff, MACINFO *mi); +static void DecodeJLEEextraField(ZCONST uch *buff, MACINFO *mi); +static void DecodeZPITextraField(ZCONST uch *buff, MACINFO *mi); +static char *PrintTextEncoding(short script); +static void BuildMacFilename(void); + +/*****************************************************************************/ +/* Constants (strings, etc.) */ +/*****************************************************************************/ + +static ZCONST char Far CannotCreateFile[] = "error: cannot create %s\n"; + +static ZCONST char Far OutOfMemEF[] = "Can't allocate memory to uncompress"\ + " file attributes.\n"; + +static ZCONST char Far ErrUncmpEF[] = "Error uncompressing file attributes.\n"; + +static ZCONST char Far No64Time[] = "Don't support 64 bit Timevalues; get "\ + " a newer version of MacZip \n"; + +static ZCONST char Far NoUniCode[] = "Don't support Unicoded Filenames; get"\ + " a newer version of MacZip\n"; + +static ZCONST char Far ZitIt_EF[] = "warning: found ZipIt extra field "\ + " -> file is probably not "\ + "usable!!\n"; + +static ZCONST char Far CantAllocateWildcard[] = + "warning: cannot allocate wildcard buffers\n"; + +static ZCONST char Far ErrNoTimeSet[] = "error (%d): cannot set the time for"\ + " %s\n"; + +static ZCONST char Far MacBinaryMsg[] = "\n ... decoding MacBinary "; + +static ZCONST char Far WarnDirTraversSkip[] = + "warning: skipped \"../\" path component(s) in %s\n"; + +static ZCONST char Far Creating[] = " creating: %s\n"; + +static ZCONST char Far ConversionFailed[] = + "mapname: conversion of %s failed\n"; + +static ZCONST char Far PathTooLong[] = "checkdir error: path too long: %s\n"; + +static ZCONST char Far CantCreateDir[] = "checkdir error: cannot create %s\n\ + unable to process %s.\n"; + +static ZCONST char Far DirIsntDirectory[] = + "checkdir error: %s exists but is not directory\n\ + unable to process %s.\n"; + +static ZCONST char Far PathTooLongTrunc[] = + "checkdir warning: path too long; truncating\n %s\n\ + -> %s\n"; + +static ZCONST char Far CantCreateExtractDir[] = + "checkdir: cannot create extraction directory: %s\n"; + +static ZCONST char Far FilenameToLong[] = + "Filename is to long; truncated: %s\n"; + +/*****************************************************************************/ +/* Functions */ +/*****************************************************************************/ + +#ifndef SFX + +/**********************/ +/* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ +/**********************/ + +char *do_wild(__G__ wildspec) + __GDEF + ZCONST char *wildspec; /* only used first time on a given dir */ +{ + static DIR *wild_dir = (DIR *)NULL; + static ZCONST char *wildname; + static char *dirname, matchname[FILNAMSIZ]; + static int notfirstcall=FALSE, have_dirname; + static unsigned long dirnamelen; + struct dirent *file; + + /* Even when we're just returning wildspec, we *always* do so in + * matchname[]--calling routine is allowed to append four characters + * to the returned string, and wildspec may be a pointer to argv[]. + */ + if (!notfirstcall) { /* first call: must initialize everything */ + notfirstcall = TRUE; + + /* Folder names must always end with a colon */ + if (uO.exdir[strlen(uO.exdir)-1] != ':') { + strcat(uO.exdir, ":"); + } + + MacUnzip_Noisy = !uO.qflag; + + if (MacUnzip_Noisy) printf("%s \n\n", GetUnZipInfoVersions()); + + /* break the wildspec into a directory part and a wildcard filename */ + if ((wildname = (ZCONST char *)strrchr(wildspec, ':')) == + (ZCONST char *)NULL) { + dirname = ":"; + dirnamelen = 1; + have_dirname = FALSE; + wildname = wildspec; + } else { + ++wildname; /* point at character after ':' */ + dirnamelen = wildname - wildspec; + if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) { + Info(slide, 0x201, ((char *)slide, + LoadFarString(CantAllocateWildcard))); + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; /* but maybe filespec was not a wildcard */ + } + strncpy(dirname, wildspec, dirnamelen); + dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ + have_dirname = TRUE; + } + + if ((wild_dir = opendir(dirname)) != (DIR *)NULL) { + while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { + if (match(file->d_name, wildname, 0 WESEP)) { /* 0=case sens.*/ + if (have_dirname) { + strcpy(matchname, dirname); + strcpy(matchname+dirnamelen, file->d_name); + } else + strcpy(matchname, file->d_name); + return matchname; + } + } + /* if we get to here directory is exhausted, so close it */ + closedir(wild_dir); + wild_dir = (DIR *)NULL; + } + + /* return the raw wildspec in case that works (e.g., directory not + * searchable, but filespec was not wild and file is readable) */ + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (wild_dir == (DIR *)NULL) { + notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + } + + /* If we've gotten this far, we've read and matched at least one entry + * successfully (in a previous call), so dirname has been copied into + * matchname already. + */ + while ((file = readdir(wild_dir)) != (struct dirent *)NULL) + if (match(file->d_name, wildname, 0 WESEP)) { /* 0 == case sens. */ + if (have_dirname) { + /* strcpy(matchname, dirname); */ + strcpy(matchname+dirnamelen, file->d_name); + } else + strcpy(matchname, file->d_name); + return matchname; + } + + closedir(wild_dir); /* have read at least one entry; nothing left */ + wild_dir = (DIR *)NULL; + notfirstcall = FALSE; /* reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + +} /* end function do_wild() */ + +#endif /* !SFX */ + + + + + +/***************************/ +/* Function open_outfile() */ +/***************************/ + +int open_outfile(__G) /* return 1 if fail */ + __GDEF +{ + short outfd, fDataFork = true; + +#ifdef DLL + if (G.redirect_data) + return (redirect_outfile(__G) == FALSE); +#endif + Trace((stderr, "open_outfile: trying to open (%s) for writing\n", + FnFilter1(G.filename))); + + if (!uO.aflag) { + /* unknown type documents */ + /* all files are considered to be of type 'TEXT' and creator 'hscd' */ + /* this is the default type for CDROM ISO-9660 without Apple extensions */ + newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType = 'TEXT'; + newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator = 'hscd'; + } else { + /* unknown text-files defaults to 'TEXT' */ + newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType = 'TEXT'; + /* Bare Bones BBEdit */ + newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator = 'R*ch'; + } + + BuildMacFilename(); + + if (MacZipMode <= TomBrownZipIt2_EF) + { + fDataFork = true; + } + else + { + fDataFork = (newExtraField.flags & EB_M3_FL_DATFRK) ? TRUE : FALSE; + } + + + if ((outfd = maccreat(G.filename)) != -1) { + outfd = macopen(G.filename, (fDataFork) ? 1 : 2); + } + + if (outfd == -1) { + G.outfile = (FILE *)NULL; + Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile), + FnFilter1(G.filename))); + return 1; + } + G.outfile = (FILE *)outfd; + Trace((stderr, "open_outfile: successfully opened (%s) for writing\n", + FnFilter1(G.filename))); + + return 0; + +} /* end function open_outfile() */ + + + + + +/**********************/ +/* Function mapattr() */ +/**********************/ + +int mapattr(__G) + __GDEF +{ + /* only care about read-only bit, so just look at MS-DOS side of attrs */ + G.pInfo->read_only = (unsigned)(G.crec.external_file_attributes & 1); + return 0; + +} /* end function mapattr() */ + + + + + +/************************/ +/* Function mapname() */ +/************************/ + +int mapname(__G__ renamed) + __GDEF + int renamed; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - caution (truncated filename) + * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) + * MPN_ERR_SKIP - error -> skip entry + * MPN_ERR_TOOLONG - error -> path is too long + * MPN_NOMEM - error (memory allocation failed) -> skip entry + * [also MPN_VOL_LABEL, MPN_CREATED_DIR] + */ +{ + char pathcomp[FILNAMSIZ]; /* path-component buffer */ + char *pp, *cp=(char *)NULL; /* character pointers */ + char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ + int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ + int error = MPN_OK; + register unsigned workch; /* hold the character being tested */ + + +/*--------------------------------------------------------------------------- + Initialize various pointers and counters and stuff. + ---------------------------------------------------------------------------*/ + + if (G.pInfo->vollabel) + return MPN_VOL_LABEL; /* can't set disk volume labels on Macintosh */ + + /* can create path as long as not just freshening, or if user told us */ + G.create_dirs = (!uO.fflag || renamed); + + created_dir = FALSE; /* not yet */ + + /* user gave full pathname: don't prepend rootpath */ + renamed_fullpath = (renamed && (*G.filename == '/')); + + if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM) + return MPN_NOMEM; /* initialize path buffer, unless no memory */ + + *pathcomp = '\0'; /* initialize translation buffer */ + pp = pathcomp; /* point to translation buffer */ + + if (uO.jflag) /* junking directories */ + cp = (char *)strrchr(G.filename, '/'); + if (cp == (char *)NULL) { /* no '/' or not junking dirs */ + cp = G.filename; /* point to internal zipfile-member pathname */ + if (renamed_fullpath) + ++cp; /* skip over leading '/' */ + } else + ++cp; /* point to start of last component of path */ + +/*--------------------------------------------------------------------------- + Begin main loop through characters in filename. + ---------------------------------------------------------------------------*/ + + while ((workch = (uch)*cp++) != 0) { + + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + if (strcmp(pathcomp, ".") == 0) { + /* don't bother appending "./" to the path */ + *pathcomp = '\0'; + } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { + /* "../" dir traversal detected, skip over it */ + *pathcomp = '\0'; + killed_ddot = TRUE; /* set "show message" flag */ + } + /* when path component is not empty, append it now */ + if (*pathcomp != '\0' && + ((error = checkdir(__G__ pathcomp, APPEND_DIR)) + & MPN_MASK) > MPN_INF_TRUNC) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ + break; + + case ':': + *pp++ = '/'; /* ':' is a pathseperator for HFS */ + break; + + case ';': /* VMS version (or DEC-20 attrib?) */ + lastsemi = pp; /* keep for now; remove VMS ";##" */ + *pp++ = (char)workch; /* later, if requested */ + break; + + default: + /* allow European characters in filenames: */ + if (isprint(workch) || (128 <= workch && workch <= 254)) + *pp++ = (char)workch; + } /* end switch */ + + } /* end while loop */ + + /* Show warning when stripping insecure "parent dir" path components */ + if (killed_ddot && QCOND2) { + Info(slide, 0, ((char *)slide, LoadFarString(WarnDirTraversSkip), + FnFilter1(G.filename))); + if (!(error & ~MPN_MASK)) + error = (error & MPN_MASK) | PK_WARN; + } + +/*--------------------------------------------------------------------------- + Report if directory was created (and no file to create: filename ended + in '/'), check name to be sure it exists, and combine path and name be- + fore exiting. + ---------------------------------------------------------------------------*/ + + if (G.filename[strlen(G.filename) - 1] == '/') { + checkdir(__G__ G.filename, GETPATH); + if (created_dir) { + if (QCOND2) { + Info(slide, 0, ((char *)slide, LoadFarString(Creating), + FnFilter1(G.filename))); + } + /* set dir time (note trailing '/') */ + return (error & ~MPN_MASK) | MPN_CREATED_DIR; + } + /* dir existed already; don't look for data to extract */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + *pp = '\0'; /* done with pathcomp: terminate it */ + + /* if not saving them, remove VMS version numbers (appended ";###") */ + if (!uO.V_flag && lastsemi) { + pp = lastsemi + 1; + while (isdigit((uch)(*pp))) + ++pp; + if (*pp == '\0') /* only digits between ';' and end: nuke */ + *lastsemi = '\0'; + } + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed), + FnFilter1(G.filename))); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + + checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ + checkdir(__G__ G.filename, GETPATH); + + return error; + +} /* end function mapname() */ + + + + + +/***********************/ +/* Function checkdir() */ +/***********************/ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename + * MPN_INF_SKIP - path doesn't exist, not allowed to create + * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path + * exists and is not a directory, but is supposed to be + * MPN_ERR_TOOLONG - path is too long + * MPN_NOMEM - can't allocate memory for filename buffers + */ +{ + static int rootlen = 0; /* length of rootpath */ + static char *rootpath; /* user's "extract-to" directory */ + static char *buildpath; /* full path (so far) to extracted file */ + static char *end; /* pointer to end of buildpath ('\0') */ + +# define FN_MASK 7 +# define FUNCTION (flag & FN_MASK) + + +/*--------------------------------------------------------------------------- + APPEND_DIR: append the path component to the path being built and check + for its existence. If doesn't exist and we are creating directories, do + so for this one; else signal success or error as appropriate. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_DIR) { + int too_long = FALSE; +#ifdef SHORT_NAMES + char *old_end = end; +#endif + + Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') + ++end; +#ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ + if ((end-old_end) > NAME_MAX) + *(end = old_end + NAME_MAX) = '\0'; +#endif + + /* GRR: could do better check, see if overrunning buffer as we go: + * check end-buildpath after each append, set warning variable if + * within 20 of FILNAMSIZ; then if var set, do careful check when + * appending. Clear variable when begin new path. */ + + if ((end-buildpath) > NAME_MAX-3) /* need ':', one-char name, '\0' */ + too_long = TRUE; /* check if extracting directory? */ + if (stat(buildpath, &G.statbuf)) { /* path doesn't exist */ + if (!G.create_dirs) { /* told not to create (freshening) */ + free(buildpath); + return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong), + FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + if (macmkdir(buildpath) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir), + FnFilter2(buildpath), FnFilter1(G.filename))); + free(buildpath); + /* path didn't exist, tried to create, failed */ + return MPN_ERR_SKIP; + } + created_dir = TRUE; + } else if (!S_ISDIR(G.statbuf.st_mode)) { + Info(slide, 1, ((char *)slide, LoadFarString(DirIsntDirectory), + FnFilter2(buildpath), FnFilter1(G.filename))); + free(buildpath); + /* path existed but wasn't dir */ + return MPN_ERR_SKIP; + } + if (too_long) { + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong), + FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + *end++ = ':'; + *end = '\0'; + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + return MPN_OK; + + } /* end if (FUNCTION == APPEND_DIR) */ + +/*--------------------------------------------------------------------------- + GETPATH: copy full path to the string pointed at by pathcomp, and free + buildpath. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == GETPATH) { + strcpy(pathcomp, buildpath); + Trace((stderr, "getting and freeing path [%s]\n", + FnFilter1(pathcomp))); + free(buildpath); + buildpath = end = (char *)NULL; + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + APPEND_NAME: assume the path component is the filename; append it and + return without checking for existence. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_NAME) { +#ifdef SHORT_NAMES + char *old_end = end; +#endif + + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') { + ++end; +#ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ + if ((end-old_end) > NAME_MAX) + *(end = old_end + NAME_MAX) = '\0'; +#endif + if ((end-buildpath) >= NAME_MAX) { + *--end = '\0'; + Info(slide, 0x201, ((char *)slide, + LoadFarString(PathTooLongTrunc), + FnFilter1(G.filename), FnFilter2(buildpath))); + return MPN_INF_TRUNC; /* filename truncated */ + } + } + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + /* could check for existence here, prompt for new name... */ + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + INIT: allocate and initialize buffer space for the file currently being + extracted. If file was renamed with an absolute path, don't prepend the + extract-to path. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == INIT) { + Trace((stderr, "initializing buildpath to ")); + if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+2)) + == (char *)NULL) + return MPN_NOMEM; + if ((rootlen > 0) && !renamed_fullpath) { + strcpy(buildpath, rootpath); + end = buildpath + rootlen; + } else { + end = buildpath; + if (!renamed_fullpath && !uO.jflag) { + *end++ = ':'; /* indicate relative path */ + } + *end = '\0'; + } + Trace((stderr, "[%s]\n", FnFilter1(buildpath))); + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + ROOT: if appropriate, store the path in rootpath and create it if + necessary; else assume it's a zipfile member and return. This path + segment gets used in extracting all members from every zipfile specified + on the command line. + ---------------------------------------------------------------------------*/ + +#if (!defined(SFX) || defined(SFX_EXDIR)) + if (FUNCTION == ROOT) { + Trace((stderr, "initializing root path to [%s]\n", + FnFilter1pathcomp))); + if (pathcomp == (char *)NULL) { + rootlen = 0; + return MPN_OK; + } + if (rootlen > 0) /* rootpath was already set, nothing to do */ + return MPN_OK; + if ((rootlen = strlen(pathcomp)) > 0) { + char *tmproot; + + if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) { + rootlen = 0; + return MPN_NOMEM; + } + strcpy(tmproot, pathcomp); + if (tmproot[rootlen-1] == ':') { + tmproot[--rootlen] = '\0'; /* strip trailing delimiter */ + } + if (rootlen > 0 && (stat(tmproot, &G.statbuf) || + !S_ISDIR(G.statbuf.st_mode))) + { /* path does not exist */ + if (!G.create_dirs /* || iswild(tmproot) */ ) { + free(tmproot); + rootlen = 0; + /* skip (or treat as stored file) */ + return MPN_INF_SKIP; + } + /* create the directory (could add loop here scanning tmproot + * to create more than one level, but why really necessary?) */ + if (macmkdir(tmproot) == -1) { + Info(slide, 1, ((char *)slide, + LoadFarString(CantCreateExtractDir), + FnFilter1(tmproot))); + free(tmproot); + rootlen = 0; + /* path didn't exist, tried to create, and failed: */ + /* file exists, or 2+ subdir levels required */ + return MPN_ERR_SKIP; + } + } + tmproot[rootlen++] = ':'; + tmproot[rootlen] = '\0'; + if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { + free(tmproot); + rootlen = 0; + return MPN_NOMEM; + } + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath))); + } + return MPN_OK; + } +#endif /* !SFX || SFX_EXDIR */ + +/*--------------------------------------------------------------------------- + END: free rootpath, immediately prior to program exit. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == END) { + Trace((stderr, "freeing rootpath\n")); + if (rootlen > 0) { + free(rootpath); + rootlen = 0; + } + return MPN_OK; + } + + return MPN_INVALID; /* should never reach */ + +} /* end function checkdir() */ + + + + + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) + __GDEF +{ + OSErr err; + + if (fileno(G.outfile) == 1) + return; /* don't attempt to close or set time on stdout */ + + err = (OSErr)fclose(G.outfile); + + /* finally set FinderInfo */ + if (MacZipMode >= JohnnyLee_EF) + { + /* skip restoring time stamps on user's request */ + err = SetFinderInfo(__G__ (uO.D_flag <= 1), + &CurrentFile, &newExtraField); + printerr("close_outfile SetFinderInfo ", err, err, + __LINE__, __FILE__, G.filename); + } + else /* unknown extra field, set at least file time/dates */ + { + /* skip restoring time stamps on user's request */ + if (uO.D_flag <= 1) + err = SetFileTime(__G); + } + +#ifndef SwitchZIPITefSupportOff + if ((MacZipMode == TomBrownZipIt1_EF) || + (MacZipMode == TomBrownZipIt2_EF)) + { + if(FSpIsMacBinary(&CurrentFile)) + { + Info(slide, 0, ((char *)slide, LoadFarString(MacBinaryMsg))); + err = DecodeMacBinaryFile(&CurrentFile); + printerr("close_outfile DecodeMacBinaryFile ", err, err, + __LINE__, __FILE__, G.filename); + } + } +#endif + + /* set read-only perms if needed */ + if ((err == noErr) && G.pInfo->read_only) + { + err = FSpSetFLock(&CurrentFile); + printerr("FSpSetFLock",err,err,__LINE__,__FILE__,G.filename); + } + + if (malloced_attrbuff != NULL) + { + attrbuff = malloced_attrbuff; + } + +} /* end function close_outfile() */ + + + + +/****************************/ +/* Function SetFileTime() */ +/****************************/ + +static OSErr SetFileTime(__G) + __GDEF +{ +#ifdef USE_EF_UT_TIME + iztimes z_utime; + unsigned eb_izux_flg; +#endif + OSErr err; + CInfoPBRec fpb; + + fpb.hFileInfo.ioNamePtr = CurrentFile.name; + fpb.hFileInfo.ioVRefNum = CurrentFile.vRefNum; + fpb.hFileInfo.ioDirID = CurrentFile.parID; + fpb.hFileInfo.ioFDirIndex = 0; + + err = PBGetCatInfoSync((CInfoPBPtr)&fpb); + printerr("PBGetCatInfoSync", err, err, __LINE__, __FILE__, G.filename); + + if ((MacZipMode == UnKnown_EF) || UseUT_ExtraField ) { + +#ifdef USE_EF_UT_TIME + eb_izux_flg = ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, + G.lrec.last_mod_dos_datetime, &z_utime, NULL); + + if (G.extra_field && (eb_izux_flg & EB_UT_FL_MTIME)) + { + fpb.hFileInfo.ioFlMdDat = UnixFtime2MacFtime(z_utime.mtime); + fpb.hFileInfo.ioFlCrDat = UnixFtime2MacFtime(z_utime.ctime); + } + +#ifdef DEBUG_TIME + { + struct tm *tp = gmtime(&z_utime.ctime); + printf( + "SetFileTime: Unix e.f. creat. time = %d/%2d/%2d %2d:%2d:%2d -> %lu UTC\n", + tp->tm_year, tp->tm_mon+1, tp->tm_mday, + tp->tm_hour, tp->tm_min, tp->tm_sec, z_utime.ctime); + tp = gmtime(&z_utime.mtime); + printf( + "SetFileTime: Unix e.f. modif. time = %d/%2d/%2d %2d:%2d:%2d -> %lu UTC\n", + tp->tm_year, tp->tm_mon+1, tp->tm_mday, + tp->tm_hour, tp->tm_min, tp->tm_sec, z_utime.mtime); + } +#endif /* DEBUG_TIME */ + + + else /* no Unix time field found - use dostime */ +#endif /* !USE_EF_UT_TIME */ + { + TTrace((stderr, "SetFileTime: using DOS-Datetime ! \n", + z_utime.mtime)); + fpb.hFileInfo.ioFlMdDat = dos_to_unix_time(G.lrec.last_mod_dos_datetime); + UNIX_TO_MACOS(fpb.hFileInfo.ioFlMdDat); + fpb.hFileInfo.ioFlCrDat = fpb.hFileInfo.ioFlMdDat; + } + + /* Restore ioDirID field in pb which was changed by PBGetCatInfoSync */ + fpb.hFileInfo.ioDirID = CurrentFile.parID; + + if (err == noErr) + { + err = PBSetCatInfoSync((CInfoPBPtr)&fpb); + printerr("PBSetCatInfoSync",err,err,__LINE__,__FILE__,G.filename); + } + if (err != noErr) + Info(slide, 0x201, ((char *)slide, LoadFarString(ErrNoTimeSet), + FnFilter1(G.filename))); + } + +return err; +} /* end function SetFileTime() */ + + + + +#ifndef SFX + +/************************/ +/* Function version() */ +/************************/ + +void version(__G) + __GDEF +{ +/* +ZCONST char Far CompiledWith[] = + "Compiled with %s%s for %s%s%s%s.\n\n"; */ + +char DateTime[50]; + +#ifdef __MWERKS__ +char CompVer[10]; +sprintf(CompVer, "%x", __MWERKS__); +#endif + + sprintf(DateTime,"%s %s",__DATE__, __TIME__); + + sprintf((char *)slide, LoadFarString(CompiledWith), + +#ifdef __MWERKS__ + + " Metrowerks CodeWarrior version ",CompVer, +#else + " ", " ", +#endif + +#ifdef __MC68K__ + " MC68K Processor", +#else + " PowerPC Processor", +#endif + +#ifdef __DATE__ + + "\n compile time: ", DateTime, "" +#else + "", "", "" +#endif + ); + + (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0); + +} /* end function version() */ + +#endif /* !SFX */ + + + + + +/***********************/ +/* Function macmkdir() */ +/***********************/ + +int macmkdir(char *path) +{ + OSErr err = -1; + OSErr err_rc; + char CompletePath[NAME_MAX], CompletePath2[NAME_MAX]; + Boolean isDirectory = false; + short CurrentFork; + unsigned pathlen; + long dirID; + + AssertStr(path, path) + + GetExtraFieldData(&MacZipMode, &newExtraField); + + if (MacZipMode >= JohnnyLee_EF) { + RfDfFilen2Real(CompletePath, G.filename, MacZipMode, + (newExtraField.flags & EB_M3_FL_NOCHANGE), &CurrentFork); + if (CurrentFork == ResourceFork) + /* don't build a 'XtraStuf.mac:' dir */ + return 0; + } + + if (!IgnoreEF_Macfilename) + { + pathlen = strlen(path); + strcpy(CompletePath, uO.exdir); + strcat(CompletePath, newExtraField.FullPath); + CompletePath[pathlen] = 0x00; + } + else + { + strcpy(CompletePath, path); + } + + GetCompletePath(CompletePath2, CompletePath, &CurrentFile, &err); + printerr("GetCompletePath", (err != -43) && (err != -120) && (err != 0), + err, __LINE__, __FILE__, CompletePath2); + + + err = FSpGetDirectoryID(&CurrentFile, &dirID, &isDirectory); + printerr("macmkdir FSpGetDirectoryID ", (err != -43) && (err != 0), + err, __LINE__, __FILE__, CompletePath2); + + if (err != -43) /* -43 = file/directory not found */ + return 0; + else { + HParamBlockRec hpbr; + + hpbr.fileParam.ioCompletion = NULL; + hpbr.fileParam.ioNamePtr = CurrentFile.name; + hpbr.fileParam.ioVRefNum = CurrentFile.vRefNum; + hpbr.fileParam.ioDirID = CurrentFile.parID; + err = PBDirCreateSync(&hpbr); + printerr("macmkdir PBDirCreateSync ", err, + err, __LINE__, __FILE__, CompletePath2); + + /* finally set FinderInfo */ + if (MacZipMode >= JohnnyLee_EF) + { + err_rc = SetFinderInfo(__G__ (uO.D_flag <= 0), + &CurrentFile, &newExtraField); + printerr("macmkdir SetFinderInfo ", err_rc, err_rc, + __LINE__, __FILE__, CompletePath2); + } + } + + return (int)err; +} /* macmkdir */ + + + + +/**********************/ +/* Function macopen() */ +/**********************/ + +short macopen(char *sz, short nFlags) +{ + OSErr err; + char chPerms = (!nFlags) ? fsRdPerm : fsRdWrPerm; + short nFRefNum; + + AssertStr(sz, sz) + + /* we only need the filespec of the zipfile; + filespec of the other files (to be extracted) will be + determined by open_outfile() */ + if (OpenZipFile) + { + char CompletePath[NAME_MAX]; + FSSpec zipfile; + GetCompletePath(CompletePath, sz, &zipfile, &err); + printerr("GetCompletePath", (err != -43) && (err != 0), + err, __LINE__, __FILE__, sz); + if (CheckMountedVolumes(CompletePath) > 1) + DoWarnUserDupVol(CompletePath); + err = HOpen(zipfile.vRefNum, zipfile.parID, zipfile.name, + chPerms, &nFRefNum); + printerr("Zipfile HOpen", err, err, __LINE__, __FILE__, sz); + OpenZipFile = false; + } + else /* open zipfile entries */ + { + if (nFlags > 1) + { + err = HOpenRF(CurrentFile.vRefNum, CurrentFile.parID, CurrentFile.name, + chPerms, &nFRefNum); + printerr("HOpenRF", (err != -43) && (err != 0) && (err != -54), + err, __LINE__, __FILE__, sz); + } + else + { + err = HOpen(CurrentFile.vRefNum, CurrentFile.parID, CurrentFile.name, + chPerms, &nFRefNum); + printerr("HOpen", (err != -43) && (err != 0), + err, __LINE__, __FILE__, sz); + } + } + + if ( err || (nFRefNum == 1) ) + { + printerr("macopen", err, err, __LINE__, __FILE__, + (char *) CurrentFile.name); + return -1; + } + else + { + if ( nFlags ) + SetEOF( nFRefNum, 0 ); + return nFRefNum; + } +} + + + + + +/***********************/ +/* Function maccreat() */ +/***********************/ + +short maccreat(char *sz) +{ + OSErr err; + char scriptTag = newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript; + static char Num = 0; + + sz = sz; + + /* Set fdScript in FXInfo + * The negative script constants (smSystemScript, smCurrentScript, + * and smAllScripts) don't make sense on disk. So only use scriptTag + * if scriptTag >= smRoman (smRoman is 0). + * fdScript is valid if high bit is set (see IM-6, page 9-38) + */ + scriptTag = (scriptTag >= smRoman) ? + ((char)scriptTag | (char)0x80) : (smRoman); + newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript = scriptTag; + + err = FSpCreate(&CurrentFile, + newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator, + newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType, + newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript); + + /* -37 = bad filename; make the filename shorter and try again */ + /* filename must not be longer than 32 chars */ + if (err == -37) + { + strcpy((char *)CurrentFile.name, + MakeFilenameShorter(P2CStr(CurrentFile.name))); + Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameToLong), + FnFilter1((char *)CurrentFile.name))); + C2PStr((char *)CurrentFile.name); + err = FSpCreate(&CurrentFile, + newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator, + newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType, + newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript); + } + + err = printerr("FSpCreate maccreat ", (err != -48) && (err != 0), + err, __LINE__, __FILE__, G.filename); + + if (err == noErr) + return noErr; + else + return -1; +} + + + + + +/**********************/ +/* Function macread() */ +/**********************/ + +short macread(short nFRefNum, char *pb, unsigned cb) +{ + long lcb = cb; + + (void)FSRead( nFRefNum, &lcb, pb ); + return (short)lcb; +} + + + + +/***********************/ +/* Function macwrite() */ +/***********************/ + +long macwrite(short nFRefNum, char *pb, unsigned cb) +{ + long lcb = cb; + OSErr err = 0; + FILE *stream; + + if ( (nFRefNum == 1) || (nFRefNum == 2) ) + { + stream = (nFRefNum == 1 ? stdout : stderr); + pb[cb] = '\0'; /* terminate C-string */ + /* assumes writable buffer (e.g., slide[]) */ + /* with room for one more char at end of buf */ + lcb = fprintf(stream, "%s", pb); + } + else + err = FSWrite( nFRefNum, &lcb, pb ); + + if (err != 0) + { + errno = ERANGE; + return -1; + } + + return (long)lcb; +} + + + + + +/***********************/ +/* Function macclose() */ +/***********************/ + +short macclose(short nFRefNum) +{ +OSErr err; + +err = FSClose( nFRefNum ); +printerr("macclose FSClose ",err,err, __LINE__,__FILE__,G.filename); + + +return err; +} + + + + + +/***********************/ +/* Function maclseek() */ +/***********************/ + +long maclseek(short nFRefNum, long lib, short nMode) +{ + ParamBlockRec pbr; + + if (nMode == SEEK_SET) + nMode = fsFromStart; + else if (nMode == SEEK_CUR) + nMode = fsFromMark; + else if (nMode == SEEK_END) + nMode = fsFromLEOF; + pbr.ioParam.ioRefNum = nFRefNum; + pbr.ioParam.ioPosMode = nMode; + pbr.ioParam.ioPosOffset = lib; + (void)PBSetFPosSync(&pbr); + return pbr.ioParam.ioPosOffset; +} + + + +static void BuildMacFilename(void) +{ +char CompletePath[NAME_MAX]; +char ArchiveDir[NAME_MAX]; +unsigned exdirlen = strlen(uO.exdir); +short CurrentFork; +OSErr err; + +GetExtraFieldData(&MacZipMode, &newExtraField); + +if (MacZipMode >= JohnnyLee_EF) + { + if (IgnoreEF_Macfilename) + { + strcpy(ArchiveDir, &G.filename[exdirlen+1]); + G.filename[exdirlen+1] = '\0'; + RfDfFilen2Real(ArchiveDir, ArchiveDir, MacZipMode, + (newExtraField.flags & EB_M3_FL_DATFRK), &CurrentFork); + strcat(G.filename, ArchiveDir); + } + else + { /* use the filename of mac extra-field */ + G.filename[exdirlen] = '\0'; /* cut resource-path */ + strcat(G.filename,newExtraField.FullPath); + } + } + +GetCompletePath(CompletePath, G.filename, &CurrentFile, &err); +printerr("GetCompletePath BuildMacFilename ", (err != -43) && (err != 0), + err, __LINE__, __FILE__, CompletePath); + +err = GetVolFileSystemID(C2PStr(CompletePath), CurrentFile.vRefNum, + &fileSystemID); +printerr("GetVolFileSystemID BuildMacFilename ", err, err, __LINE__, __FILE__, + CompletePath); + +if (MacZipMode == TomBrownZipIt1_EF) + { + memcpy(CurrentFile.name, newExtraField.filename, newExtraField.filename[0]+1); + CurrentFile.name[0] = CurrentFile.name[0] - 1; + } + +} + + + + +/* The following functions are dealing with the extra-field handling, only. */ + +/****************************/ +/* Function SetFinderInfo() */ +/****************************/ + +static OSErr SetFinderInfo(__GPRO__ int SetTime, FSSpec *spec, MACINFO *mi) +{ + OSErr err; + CInfoPBRec fpb; + + fpb.hFileInfo.ioNamePtr = (StringPtr) &(spec->name); + fpb.hFileInfo.ioVRefNum = spec->vRefNum; + fpb.hFileInfo.ioDirID = spec->parID; + fpb.hFileInfo.ioFDirIndex = 0; + + err = PBGetCatInfoSync(&fpb); + printerr("PBGetCatInfo SetFinderInfo ", err, err, + __LINE__, __FILE__, G.filename); + + if ((MacZipMode == JohnnyLee_EF) || (MacZipMode == NewZipMode_EF)) + { + /* skip restoring time stamps on user's request */ + if (SetTime && !UseUT_ExtraField) { + fpb.hFileInfo.ioFlCrDat = mi->fpb.hFileInfo.ioFlCrDat; + fpb.hFileInfo.ioFlMdDat = mi->fpb.hFileInfo.ioFlMdDat; + } + + fpb.hFileInfo.ioFlFndrInfo = mi->fpb.hFileInfo.ioFlFndrInfo; + } + + if (MacZipMode == NewZipMode_EF) + { + if (uO.E_flag) PrintMacExtraInfo(mi); + fpb.hFileInfo.ioFlXFndrInfo = mi->fpb.hFileInfo.ioFlXFndrInfo; + + fpb.hFileInfo.ioFVersNum = mi->fpb.hFileInfo.ioFVersNum; + fpb.hFileInfo.ioACUser = mi->fpb.hFileInfo.ioACUser; + + /* skip restoring time stamps on user's request */ + if (SetTime && !UseUT_ExtraField) { + fpb.hFileInfo.ioFlBkDat = mi->fpb.hFileInfo.ioFlBkDat; +#ifdef USE_EF_UT_TIME + if (!(mi->flags & EB_M3_FL_NOUTC)) + { +#ifdef DEBUG_TIME + { + printf("\nSetFinderInfo: Mac modif: %lu local -> UTOffset: "\ + "%d before AdjustForTZmoveMac\n", + fpb.hFileInfo.ioFlCrDat, mi->Cr_UTCoffs); + } +#endif /* DEBUG_TIME */ + fpb.hFileInfo.ioFlCrDat = + AdjustForTZmoveMac(fpb.hFileInfo.ioFlCrDat, mi->Cr_UTCoffs); + fpb.hFileInfo.ioFlMdDat = + AdjustForTZmoveMac(fpb.hFileInfo.ioFlMdDat, mi->Md_UTCoffs); + fpb.hFileInfo.ioFlBkDat = + AdjustForTZmoveMac(fpb.hFileInfo.ioFlBkDat, mi->Bk_UTCoffs); +#ifdef DEBUG_TIME + { + printf("SetFinderInfo: Mac modif: %lu local -> UTOffset: "\ + "%d after AdjustForTZmoveMac\n", + fpb.hFileInfo.ioFlCrDat, mi->Cr_UTCoffs); + } +#endif /* DEBUG_TIME */ + + } +#endif /* USE_EF_UT_TIME */ + } + + if ((mi->FinderComment) && + (fileSystemID == HFS_fileSystem)) { + C2PStr(mi->FinderComment); + err = FSpDTSetComment(spec, (unsigned char *) mi->FinderComment); + printerr("FSpDTSetComment:",err , err, + __LINE__, __FILE__, mi->FullPath); + } + } + + /* Restore ioDirID field in pb which was changed by PBGetCatInfo */ + fpb.hFileInfo.ioDirID = spec->parID; + err = PBSetCatInfoSync(&fpb); + + return err; +} /* SetFinderInfo() */ + + + + +/* +** Scan the extra fields in extra_field, and look for a MacOS EF; return a +** pointer to that EF, or NULL if it's not there. +*/ +static uch *scanMacOSexfield(uch *ef_ptr, unsigned ef_len, + short *MacZipMode) +{ + while (ef_ptr != NULL && ef_len >= EB_HEADSIZE) { + unsigned eb_id = makeword(EB_ID + ef_ptr); + unsigned eb_len = makeword(EB_LEN + ef_ptr); + + if (eb_len > (ef_len - EB_HEADSIZE)) { + Trace((stderr, + "scanMacOSexfield: block length %u > rest ef_size %u\n", eb_len, + ef_len - EB_HEADSIZE)); + break; + } + + if (isMacOSexfield(eb_id, eb_len, MacZipMode)) { + return ef_ptr; + } + + ef_ptr += (eb_len + EB_HEADSIZE); + ef_len -= (eb_len + EB_HEADSIZE); + } + + return NULL; +} + + + + +static Boolean isMacOSexfield(unsigned id, unsigned size, short *MacZipMode) +{ +size = size; + + switch (id) + { + case EF_ZIPIT: + { /* we do not (yet) support ZipIt's format completely */ + *MacZipMode = TomBrownZipIt1_EF; + IgnoreEF_Macfilename = true; + return true; + } + + case EF_ZIPIT2: + { /* we do not (yet) support ZipIt's format completely */ + *MacZipMode = TomBrownZipIt2_EF; + IgnoreEF_Macfilename = true; + return true; + } + + case EF_MAC3: + { /* the new maczip format */ + *MacZipMode = NewZipMode_EF; + IgnoreEF_Macfilename = false; + return true; + } + + case EF_JLMAC: + { /* Johnny Lee's old maczip format */ + *MacZipMode = JohnnyLee_EF; + IgnoreEF_Macfilename = true; + return true; + } + + default: + { /* any other format */ + *MacZipMode = UnKnown_EF; + IgnoreEF_Macfilename = true; + return false; + } + } + + return false; +} + + + + +/* +** Return a unsigned long from a four-byte sequence +** in big endian format +*/ + +ulg makePPClong(ZCONST uch *sig) +{ + return (((ulg)sig[0]) << 24) + + (((ulg)sig[1]) << 16) + + (((ulg)sig[2]) << 8) + + ((ulg)sig[3]); +} + + + + +/* +** Return a unsigned short from a two-byte sequence +** in big endian format +*/ + +ush makePPCword(ZCONST uch *b) +{ + return (ush)((b[0] << 8) | b[1]); +} + + + + +/* +** Print mac extra-field +** +*/ + +static void PrintMacExtraInfo(MACINFO *mi) +{ +#define MY_FNDRINFO fpb.hFileInfo.ioFlFndrInfo + DateTimeRec MacTime; + static ZCONST char space[] = " "; + static ZCONST char line[] = "------------------------------------"\ + "------------------------------"; + + printf("\n\n%s", line); + + printf("\nFullPath = [%s]", mi->FullPath); + printf("\nFinderComment = [%s]", mi->FinderComment); + printf("\nText Encoding Base (Filename) \"%s\" \n", + PrintTextEncoding(mi->fpb.hFileInfo.ioFlXFndrInfo.fdScript)); + + printf("\nExtraField Flags : %s 0x%x %4d", + sBit2Str(mi->flags), mi->flags, mi->flags); + + printf("\n%sExtra Field is %s", space, + (mi->flags & EB_M3_FL_UNCMPR ? + "Uncompressed" : "Compressed")); + printf("\n%sFile Dates are in %u Bit", space, + (mi->flags & EB_M3_FL_TIME64 ? 64 : 32)); + printf("\n%sFile UTC time adjustments are %ssupported", space, + (mi->flags & EB_M3_FL_NOUTC ? "not " : "")); + printf("\n%sFile Name is %schanged", space, + (mi->flags & EB_M3_FL_NOCHANGE ? "not " : "")); + printf("\n%sFile is a %s\n", space, + (mi->flags & EB_M3_FL_DATFRK ? + "Datafork" : "Resourcefork")); + + /* not all type / creator codes are printable */ + if (isprint((char)(mi->MY_FNDRINFO.fdType >> 24)) && + isprint((char)(mi->MY_FNDRINFO.fdType >> 16)) && + isprint((char)(mi->MY_FNDRINFO.fdType >> 8)) && + isprint((char)mi->MY_FNDRINFO.fdType)) + { + printf("\nFile Type = [%c%c%c%c] 0x%lx", + (char)(mi->MY_FNDRINFO.fdType >> 24), + (char)(mi->MY_FNDRINFO.fdType >> 16), + (char)(mi->MY_FNDRINFO.fdType >> 8), + (char)(mi->MY_FNDRINFO.fdType), + mi->MY_FNDRINFO.fdType); + } + else + { + printf("\nFile Type = 0x%lx", + mi->MY_FNDRINFO.fdType); + } + + if (isprint((char)(mi->MY_FNDRINFO.fdCreator >> 24)) && + isprint((char)(mi->MY_FNDRINFO.fdCreator >> 16)) && + isprint((char)(mi->MY_FNDRINFO.fdCreator >> 8)) && + isprint((char)mi->MY_FNDRINFO.fdCreator)) + { + printf("\nFile Creator = [%c%c%c%c] 0x%lx", + (char)(mi->MY_FNDRINFO.fdCreator >> 24), + (char)(mi->MY_FNDRINFO.fdCreator >> 16), + (char)(mi->MY_FNDRINFO.fdCreator >> 8), + (char)(mi->MY_FNDRINFO.fdCreator), + mi->MY_FNDRINFO.fdCreator); + } + else + { + printf("\nFile Creator = 0x%lx", + mi->MY_FNDRINFO.fdCreator); + } + + printf("\n\nDates (local time of archiving location):"); + SecondsToDate(mi->fpb.hFileInfo.ioFlCrDat, &MacTime); + printf("\n Created = %4d/%2d/%2d %2d:%2d:%2d ", + MacTime.year, MacTime.month, MacTime.day, + MacTime.hour, MacTime.minute, MacTime.second); + SecondsToDate(mi->fpb.hFileInfo.ioFlMdDat, &MacTime); + printf("\n Modified = %4d/%2d/%2d %2d:%2d:%2d ", + MacTime.year, MacTime.month, MacTime.day, + MacTime.hour, MacTime.minute, MacTime.second); + SecondsToDate(mi->fpb.hFileInfo.ioFlBkDat, &MacTime); + printf("\n Backup = %4d/%2d/%2d %2d:%2d:%2d ", + MacTime.year, MacTime.month, MacTime.day, + MacTime.hour, MacTime.minute, MacTime.second); + + if (!(mi->flags & EB_M3_FL_NOUTC)) { + printf("\nGMT Offset of Creation time = %4ld sec %2d h", + mi->Cr_UTCoffs, (int)mi->Cr_UTCoffs / (60 * 60)); + printf("\nGMT Offset of Modification time = %4ld sec %2d h", + mi->Md_UTCoffs, (int)mi->Md_UTCoffs / (60 * 60)); + printf("\nGMT Offset of Backup time = %4ld sec %2d h", + mi->Bk_UTCoffs, (int)mi->Bk_UTCoffs / (60 * 60)); + } + + printf("\n\nFinder Flags : %s 0x%x %4d", + sBit2Str(mi->MY_FNDRINFO.fdFlags), + mi->MY_FNDRINFO.fdFlags, + mi->MY_FNDRINFO.fdFlags); + + printf("\nFinder Icon Position = X: %4d", + mi->MY_FNDRINFO.fdLocation.h); + + printf("\n Y: %4d", + mi->MY_FNDRINFO.fdLocation.v); + + printf("\n\nText Encoding Base (System/MacZip) \"%s\"", + PrintTextEncoding(mi->TextEncodingBase)); + + printf("\n%s\n", line); +#undef MY_FNDRINFO +} + + + + +/* +** Decode mac extra-field and assign the data to the structure +** +*/ + +static Boolean GetExtraFieldData(short *MacZipMode, MACINFO *mi) +{ +uch *ptr; +int retval = PK_OK; + +ptr = scanMacOSexfield(G.extra_field, G.lrec.extra_field_length, MacZipMode); + +/* MacOS is no preemptive OS therefore do some (small) event-handling */ +UserStop(); + +if (uO.J_flag) + { + *MacZipMode = UnKnown_EF; + IgnoreEF_Macfilename = true; + return false; + } + +if (ptr != NULL) +{ /* Collect the data from the extra field buffer. */ + mi->header = makeword(ptr); ptr += 2; + mi->data = makeword(ptr); ptr += 2; + + switch (*MacZipMode) + { + case NewZipMode_EF: + { + mi->size = makelong(ptr); ptr += 4; + mi->flags = makeword(ptr); ptr += 2; + /* Type/Creator are always uncompressed */ + mi->fpb.hFileInfo.ioFlFndrInfo.fdType = makePPClong(ptr); + ptr += 4; + mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator = makePPClong(ptr); + ptr += 4; + + if (!(mi->flags & EB_M3_FL_UNCMPR)) + { + + retval = memextract(__G__ attrbuff, mi->size, ptr, + mi->data - EB_MAC3_HLEN); + + if (retval != PK_OK) /* error uncompressing attributes */ + { + Info(slide, 0x201, ((char *)slide, + LoadFarString(ErrUncmpEF))); + *MacZipMode = UnKnown_EF; + return false; /* EF-Block unusable, ignore it */ + } + + } + else + { /* file attributes are uncompressed */ + attrbuff = ptr; + } + + DecodeMac3ExtraField(attrbuff, mi); + + return true; + break; + } + + case JohnnyLee_EF: + { + if (strncmp((char *)ptr, "JLEE", 4) == 0) + { /* Johnny Lee's old MacZip e.f. was found */ + attrbuff = ptr + 4; + DecodeJLEEextraField(attrbuff, mi); + return true; + } + else + { /* second signature did not match, ignore EF block */ + *MacZipMode = UnKnown_EF; + return false; + } + break; + } + + + case TomBrownZipIt1_EF: + case TomBrownZipIt2_EF: + { + if (strncmp((char *)ptr, "ZPIT", 4) == 0) + { /* Johnny Lee's old MacZip e.f. was found */ + attrbuff = ptr + 4; + DecodeZPITextraField(attrbuff, mi); + return true; + } + else + { /* second signature did not match, ignore EF block */ + *MacZipMode = UnKnown_EF; + return false; + } + break; + } + + + default: + { /* just to make sure */ + *MacZipMode = UnKnown_EF; + IgnoreEF_Macfilename = true; + return false; + break; + } + } +} /* if (ptr != NULL) */ + +/* no Mac extra field was found */ +return false; +} + + + + +/* +** Assign the new Mac3 Extra-Field to the structure +** +*/ + +static void DecodeMac3ExtraField(ZCONST uch *buff, MACINFO *mi) +{ /* extra-field info of the new MacZip implementation */ + /* compresssed extra-field starts here (if compressed) */ + +Assert_it(buff, "", ""); + +mi->fpb.hFileInfo.ioFlFndrInfo.fdFlags = makeword(buff); buff += 2; +mi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.v = makeword(buff); buff += 2; +mi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.h = makeword(buff); buff += 2; +mi->fpb.hFileInfo.ioFlFndrInfo.fdFldr = makeword(buff); buff += 2; + +mi->fpb.hFileInfo.ioFlXFndrInfo.fdIconID = makeword(buff); buff += 2; +mi->fpb.hFileInfo.ioFlXFndrInfo.fdReserved[0] = makeword(buff); buff += 2; +mi->fpb.hFileInfo.ioFlXFndrInfo.fdReserved[1] = makeword(buff); buff += 2; +mi->fpb.hFileInfo.ioFlXFndrInfo.fdReserved[2] = makeword(buff); buff += 2; +mi->fpb.hFileInfo.ioFlXFndrInfo.fdScript = *buff; buff += 1; +mi->fpb.hFileInfo.ioFlXFndrInfo.fdXFlags = *buff; buff += 1; +mi->fpb.hFileInfo.ioFlXFndrInfo.fdComment = makeword(buff); buff += 2; +mi->fpb.hFileInfo.ioFlXFndrInfo.fdPutAway = makelong(buff); buff += 4; + +mi->fpb.hFileInfo.ioFVersNum = *buff; buff += 1; +mi->fpb.hFileInfo.ioACUser = *buff; buff += 1; + +/* +This implementation does not use the 64 bit time values, therefore +use the UT extra field instead +*/ +if (mi->flags & EB_M3_FL_TIME64) + { + Info(slide, 0x201, ((char *)slide, LoadFarString(No64Time))); + UseUT_ExtraField = true; + buff += 24; /* jump over the date values */ + } +else + { + UseUT_ExtraField = false; + mi->fpb.hFileInfo.ioFlCrDat = makelong(buff); buff += 4; + mi->fpb.hFileInfo.ioFlMdDat = makelong(buff); buff += 4; + mi->fpb.hFileInfo.ioFlBkDat = makelong(buff); buff += 4; + } + +if (!(mi->flags & EB_M3_FL_NOUTC)) + { + mi->Cr_UTCoffs = makelong(buff); buff += 4; + mi->Md_UTCoffs = makelong(buff); buff += 4; + mi->Bk_UTCoffs = makelong(buff); buff += 4; + } + +/* TextEncodingBase type & values */ +/* (values 0-32 correspond to the Script Codes defined in "Inside Macintosh", + Text pages 6-52 and 6-53) */ +mi->TextEncodingBase = makeword(buff); buff += 2; + +if (mi->TextEncodingBase >= kTextEncodingUnicodeV1_1) + { + Info(slide, 0x201, ((char *)slide, LoadFarString(NoUniCode))); + IgnoreEF_Macfilename = true; + } + +mi->FullPath = (char *)buff; buff += strlen(mi->FullPath) + 1; +mi->FinderComment = (char *)buff; buff += strlen(mi->FinderComment) + 1; + +if (uO.i_flag) IgnoreEF_Macfilename = true; + +} + + + + +/* +** Assign the new JLEE Extra-Field to the structure +** +*/ + +static void DecodeJLEEextraField(ZCONST uch *buff, MACINFO *mi) +{ /* extra-field info of Johnny Lee's old MacZip */ + +Assert_it(buff, "", ""); + +mi->fpb.hFileInfo.ioFlFndrInfo.fdType = makePPClong(buff); buff += 4; +mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator = makePPClong(buff); buff += 4; +mi->fpb.hFileInfo.ioFlFndrInfo.fdFlags = makePPCword(buff); buff += 2; +mi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.v = makePPCword(buff); buff += 2; +mi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.h = makePPCword(buff); buff += 2; +mi->fpb.hFileInfo.ioFlFndrInfo.fdFldr = makePPCword(buff); buff += 2; + +mi->fpb.hFileInfo.ioFlCrDat = makePPClong(buff); buff += 4; +mi->fpb.hFileInfo.ioFlMdDat = makePPClong(buff); buff += 4; +mi->flags = makePPClong(buff); buff += 4; + +newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript = smSystemScript; +} + + + + +/* +** Assign the new JLEE Extra-Field to the structure +** +*/ + +static void DecodeZPITextraField(ZCONST uch *buff, MACINFO *mi) +{ /* extra-field info of Johnny Lee's old MacZip */ +unsigned char filelen; + +Assert_it(buff, "", ""); + +#ifdef SwitchZIPITefSupportOff +MacZipMode = UnKnown_EF; +Info(slide, 0x221, ((char *)slide,LoadFarString(ZitIt_EF))); +return; +#endif + +if (MacZipMode == TomBrownZipIt1_EF) + { + filelen = *buff; + newExtraField.filename = buff; + buff += 1; + buff += filelen; + mi->fpb.hFileInfo.ioFlFndrInfo.fdType = makePPClong(buff); + buff += 4; + mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator = makePPClong(buff); + buff += 4; + } +else /* if (MacZipMode == TomBrownZipIt2_EF) */ + { + mi->fpb.hFileInfo.ioFlFndrInfo.fdType = makePPClong(buff); + buff += 4; + mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator = makePPClong(buff); + buff += 4; + } + +newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript = smSystemScript; +} + + + +/* +** Return char* to describe the text encoding +** +*/ + +static char *PrintTextEncoding(short script) +{ +char *info; +static char buffer[14]; +/* TextEncodingBase type & values */ +/* (values 0-32 correspond to the Script Codes defined in + Inside Macintosh: Text pages 6-52 and 6-53 */ + +switch (script) { /* Mac OS encodings*/ + case kTextEncodingMacRoman: info = "Roman"; break; + case kTextEncodingMacJapanese: info = "Japanese"; break; + case kTextEncodingMacChineseTrad: info = "ChineseTrad"; break; + case kTextEncodingMacKorean: info = "Korean"; break; + case kTextEncodingMacArabic: info = "Arabic"; break; + case kTextEncodingMacHebrew: info = "Hebrew"; break; + case kTextEncodingMacGreek: info = "Greek"; break; + case kTextEncodingMacCyrillic: info = "Cyrillic"; break; + case kTextEncodingMacDevanagari: info = "Devanagari"; break; + case kTextEncodingMacGurmukhi: info = "Gurmukhi"; break; + case kTextEncodingMacGujarati: info = "Gujarati"; break; + case kTextEncodingMacOriya: info = "Oriya"; break; + case kTextEncodingMacBengali: info = "Bengali"; break; + case kTextEncodingMacTamil: info = "Tamil"; break; + case kTextEncodingMacTelugu: info = "Telugu"; break; + case kTextEncodingMacKannada: info = "Kannada"; break; + case kTextEncodingMacMalayalam: info = "Malayalam"; break; + case kTextEncodingMacSinhalese: info = "Sinhalese"; break; + case kTextEncodingMacBurmese: info = "Burmese"; break; + case kTextEncodingMacKhmer: info = "Khmer"; break; + case kTextEncodingMacThai: info = "Thai"; break; + case kTextEncodingMacLaotian: info = "Laotian"; break; + case kTextEncodingMacGeorgian: info = "Georgian"; break; + case kTextEncodingMacArmenian: info = "Armenian"; break; + case kTextEncodingMacChineseSimp: info = "ChineseSimp"; break; + case kTextEncodingMacTibetan: info = "Tibetan"; break; + case kTextEncodingMacMongolian: info = "Mongolian"; break; + case kTextEncodingMacEthiopic: info = "Ethiopic"; break; + case kTextEncodingMacCentralEurRoman: info = "CentralEurRoman"; break; + case kTextEncodingMacVietnamese: info = "Vietnamese"; break; + case kTextEncodingMacExtArabic: info = "ExtArabic"; break; + + case kTextEncodingUnicodeV1_1: info = "Unicode V 1.1"; break; + case kTextEncodingUnicodeV2_0: info = "Unicode V 2.0"; break; + + default: { + sprintf(buffer,"Code: 0x%x",(short) script); + info = buffer; + break; + } + } + +return info; +} + + + +/* +** Init Globals +** +*/ + +void MacGlobalsInit(__GPRO) +{ +newExtraField.FullPath = NULL; +newExtraField.FinderComment = NULL; + +OpenZipFile = true; + +MacZipMode = UnKnown_EF; +IgnoreEF_Macfilename = true; + +if (malloced_attrbuff == NULL) + { + /* make room for extra-field */ + attrbuff = (uch *)malloc(EB_MAX_OF_VARDATA); + + if (attrbuff == NULL) + { /* No memory to uncompress attributes */ + Info(slide, 0x201, ((char *)slide, LoadFarString(OutOfMemEF))); + exit(PK_MEM); + } + else + { + malloced_attrbuff = attrbuff; + } + } +else + { + attrbuff = malloced_attrbuff; + } + +} diff --git a/macos/source/macscreen.c b/macos/source/macscreen.c new file mode 100644 index 0000000..f453bb5 --- /dev/null +++ b/macos/source/macscreen.c @@ -0,0 +1,462 @@ +/* + 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 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 +*/ +/*--------------------------------------------------------------------------- + + macscreen.c + This file is only linked into the standalone version (not SIOUX) of unzip. + Macintosh-GUI routines. + + ---------------------------------------------------------------------------*/ + + +/*****************************************************************************/ +/* Includes */ +/*****************************************************************************/ + +#include + +#include +#include +#include + + +/*****************************************************************************/ +/* Macros, typedefs */ +/*****************************************************************************/ + +#define bufferSize 4096 + +#define screenWindow 128 + +#define pauseOption 0x0001 +#define scrollOption 0x0002 + + +/*****************************************************************************/ +/* Module level Vars */ +/*****************************************************************************/ + +static Rect scrollRect, pauseRect; +static WindowPtr theWindow; +static RgnHandle scrollRgn; + +static short fontHeight, fontWidth, screenHeight, screenWidth; +static short currentPosition, maxPosition, pausePosition; + +static short *screenLength, startLine, endLine; +static char *screenImage, **screenLine; + +static int screenOptions; + + + +/*****************************************************************************/ +/* Prototypes */ +/*****************************************************************************/ + +void screenOpen(char *); +void screenControl(char *, int); +void screenClose(void); +void screenUpdate(WindowPtr); +void screenDisplay(char *); +void screenDump(char *, long); + +char *macfgets(char *, int, FILE *); +int macfprintf(FILE *, char *, ...); +int macprintf(char *, ...); +int macgetch(void); + + +/*****************************************************************************/ +/* Functions */ +/*****************************************************************************/ + +void screenOpen(char *Title) { + FontInfo fontInfo; + int n; + short fontFamID; + + theWindow = GetNewWindow(screenWindow, nil, (WindowPtr)(-1)); + + if ((Title != NULL) && (*Title != '\0')) { + c2pstr(Title); + SetWTitle(theWindow, (StringPtr)Title); + p2cstr((StringPtr)Title); + } + + ShowWindow(theWindow); + + SetPort(theWindow); + GetFNum( "\pMonaco", &fontFamID ); + TextFont(fontFamID); + TextSize(9); + + GetFontInfo(&fontInfo); + fontHeight = fontInfo.ascent + fontInfo.descent + fontInfo.leading; + fontWidth = fontInfo.widMax; + + scrollRgn = NewRgn(); + + screenWidth = (theWindow->portRect.right - theWindow->portRect.left - 10) / + fontWidth; + screenHeight = (theWindow->portRect.bottom - theWindow->portRect.top) / + fontHeight; + maxPosition = screenHeight * fontHeight; + pausePosition = maxPosition - (currentPosition = fontHeight); + + SetRect(&scrollRect, theWindow->portRect.left, + theWindow->portRect.top + fontInfo.descent, + theWindow->portRect.right, + theWindow->portRect.bottom); + SetRect(&pauseRect, theWindow->portRect.left, + pausePosition + fontInfo.descent, + theWindow->portRect.right, + theWindow->portRect.bottom); + + MoveTo(5, currentPosition); + + n = (sizeof(char *) + sizeof(short) + screenWidth) * screenHeight; + + screenLine = (char **)NewPtr(n); + + screenLength = (short *)&screenLine[screenHeight]; + screenImage = (char *)&screenLength[screenHeight]; + + for (n = 0; n < screenHeight; n++) { + screenLine[n] = &screenImage[n * screenWidth]; + screenLength[n] = 0; + } + + startLine = endLine = 0; + + screenOptions = 0; + + return; +} + + + + +void screenControl(char *options, int setting) { + int n = 0; + + while (*options) { + switch (*options) { + case 'p': + n |= pauseOption; + break; + case 's': + n |= scrollOption; + break; + default: + break; + } + options += 1; + } + + if (setting == 0) + screenOptions &= (n ^ (-1)); + else + screenOptions |= n; + + if ((pausePosition = maxPosition - currentPosition) == 0) + pausePosition = maxPosition - fontHeight; + + return; +} + + + + +void screenClose(void) { + DisposePtr((Ptr)screenLine); + + DisposeWindow(theWindow); + + return; +} + + + + +void screenUpdate(WindowPtr window) { + GrafPort *savePort; + int m, n; + + if (window == theWindow) { + BeginUpdate(window); + if (!EmptyRgn(window->visRgn)) { + GetPort(&savePort); + SetPort(window); + n = startLine; + for (m = 1; ; m++) { + MoveTo(5, m * fontHeight); + if (screenLength[n] != 0) + DrawText(screenLine[n], 0, screenLength[n]); + if (n == endLine) break; + if ((n += 1) == screenHeight) n = 0; + } + SetPort(savePort); + } + EndUpdate(window); + } + + return; +} + + + + +static void screenNewline(void) { + MoveTo(5, currentPosition += fontHeight); + if (currentPosition > maxPosition) { + if (screenOptions & scrollOption) { + ScrollRect(&scrollRect, 0, -fontHeight, scrollRgn); + MoveTo(5, currentPosition = maxPosition); + if ((startLine += 1) == screenHeight) startLine = 0; + } else { + ScrollRect(&scrollRect, 0, -maxPosition + fontHeight, scrollRgn); + MoveTo(5, currentPosition = fontHeight + fontHeight); + startLine = endLine; + } + } + pausePosition -= fontHeight; + + if ((endLine += 1) == screenHeight) endLine = 0; + screenLength[endLine] = 0; + + return; +} + + + + +static char waitChar(void) { + WindowPtr whichWindow; + EventRecord theEvent; + + for ( ; ; ) { + SystemTask(); + if (GetNextEvent(everyEvent, &theEvent)) { + switch (theEvent.what) { + case keyDown: + if ((theEvent.modifiers & cmdKey) && + ((theEvent.message & charCodeMask) == '.')) + ExitToShell(); + return(theEvent.message & charCodeMask); + case mouseDown: + if (FindWindow(theEvent.where, &whichWindow) == inSysWindow) + SystemClick(&theEvent, whichWindow); + break; + case updateEvt: + screenUpdate((WindowPtr)theEvent.message); + break; + } + } + } +} + + + + +static void screenPause(void) { + if (pausePosition == 0) { + if (screenOptions & pauseOption) { + DrawText("Press any key to continue ...", 0, 29); + memcpy(screenLine[endLine], "Press any key to continue ...", 29); + screenLength[endLine] = 29; + + (void)waitChar(); + + EraseRect(&pauseRect); + MoveTo(5, currentPosition); + screenLength[endLine] = 0; + } + + pausePosition = maxPosition - fontHeight; + } + + return; +} + + + + +void screenDisplay(char *s) { + GrafPort *savePort; + int m, n; + char *t; + + GetPort(&savePort); + SetPort(theWindow); + + while (*s) { + screenPause(); + + for (t = s; (*s) && (*s != '\n') && (*s != '\r'); s++) + ; /* empty body */ + + if ((n = s - t) > (m = screenWidth - screenLength[endLine])) n = m; + + if (n > 0) { + DrawText(t, 0, n); + memcpy(screenLine[endLine] + screenLength[endLine], t, n); + screenLength[endLine] += n; + } + + if ((*s == '\n') || (*s == '\r')) { + screenNewline(); + s += 1; + } + } + + SetPort(savePort); + + return; +} + + + + +void screenDump(char *s, long n) { + GrafPort *savePort; + int k, m; + char *t; + + GetPort(&savePort); + SetPort(theWindow); + + while (n) { + screenPause(); + + for (t = s; (n) && (*s != '\n') && (*s != '\r'); s++, n--) + ; /* empty body */ + + if ((k = s - t) > (m = screenWidth - screenLength[endLine])) k = m; + + if (k > 0) { + DrawText(t, 0, k); + memcpy(screenLine[endLine] + screenLength[endLine], t, k); + screenLength[endLine] += k; + } + + if ((*s == '\n') || (*s == '\r')) { + screenNewline(); + s += 1; + n -= 1; + } + } + + SetPort(savePort); + + return; +} + + + + +char *macfgets(char *s, int n, FILE *stream) { + GrafPort *savePort; + char c, *t = s; + + stream = stream; + + GetPort(&savePort); + SetPort(theWindow); + + for (n -= 1; (n > 0) && ((c = waitChar()) != '\r'); n -= 1) { + DrawChar(*t++ = c); + if (screenLength[endLine] < screenWidth) + screenLine[endLine][screenLength[endLine]++] = c; + } + + if (c == '\r') screenNewline(); + + *t = '\0'; + + SetPort(savePort); + + return(s); +} + + + + +int macfprintf(FILE *stream, char *format, ...) +{ + char buffer[bufferSize]; + va_list ap; + int rc; + + stream = stream; + + va_start(ap, format); + rc = vsprintf(buffer, format, ap); + va_end(ap); + + screenDisplay(buffer); + + return rc; +} + + + + +int macprintf(char *format, ...) +{ + char buffer[bufferSize]; + va_list ap; + int rc; + + va_start(ap, format); + rc = vsprintf(buffer, format, ap); + va_end(ap); + + screenDisplay(buffer); + + return rc; +} + + + +/***********************/ +/* Function macgetch() */ +/***********************/ + +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: + screenUpdate((WindowPtr)theEvent.message); + break; + } + } + } while (theEvent.what != keyDown); + + macprintf("*"); + + return (int)c; +} diff --git a/macos/source/macstat.c b/macos/source/macstat.c new file mode 100644 index 0000000..2c47157 --- /dev/null +++ b/macos/source/macstat.c @@ -0,0 +1,187 @@ +/* + 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 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 +*/ +/*--------------------------------------------------------------------------- + + macstat.c + + * This file provides a unix like file-stat routine + * for V7 Unix systems that don't have such procedures. + * + * + ---------------------------------------------------------------------------*/ + + +/*****************************************************************************/ +/* Includes */ +/*****************************************************************************/ + +#include +#include +#include + +#define UNZIP_INTERNAL +#include "unzip.h" + +#include "macstat.h" +#include "helpers.h" +#include "pathname.h" +#include "macstuff.h" +#include "mactime.h" + + +/*****************************************************************************/ +/* Global Vars */ +/*****************************************************************************/ + +extern int errno; +extern MACINFO newExtraField; /* contains all extra-field data */ +extern short MacZipMode; + + +/*****************************************************************************/ +/* Prototypes */ +/*****************************************************************************/ + + + +/*****************************************************************************/ +/* Functions */ +/*****************************************************************************/ + + +int UZmacstat(const char *path, struct stat *buf) +{ + Boolean isDirectory; + long dirID; + char fullpath[NAME_MAX], UnmangledPath[NAME_MAX]; + CInfoPBRec fpb; + HVolumeParam vpb; + FSSpec fileSpec; + OSErr err, err2; + short CurrentFork; + + AssertStr(path,path) + Assert_it(buf,"","") + + memset(buf, 0, sizeof(struct stat)); /* zero out all fields */ + + RfDfFilen2Real(UnmangledPath, path, MacZipMode, + (newExtraField.flags & EB_M3_FL_NOCHANGE), &CurrentFork); + GetCompletePath(fullpath, path, &fileSpec, &err); + err2 = PrintUserHFSerr((err != -43) && (err != 0) && (err != -120), + err, path); + printerr("GetCompletePath:", err2, err2, __LINE__, __FILE__, path); + + if (err != noErr) { + errno = err; + return -1; + } + + /* + * Fill the fpb & vpb struct up with info about file or directory. + */ + + FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); + vpb.ioVRefNum = fpb.hFileInfo.ioVRefNum = fileSpec.vRefNum; + vpb.ioNamePtr = fpb.hFileInfo.ioNamePtr = fileSpec.name; + if (isDirectory) { + fpb.hFileInfo.ioDirID = fileSpec.parID; + } else { + fpb.hFileInfo.ioDirID = dirID; + } + + fpb.hFileInfo.ioFDirIndex = 0; + err = PBGetCatInfo(&fpb, false); + if (err == noErr) { + vpb.ioVolIndex = 0; + err = PBHGetVInfoSync((HParmBlkPtr)&vpb); + if (err == noErr && buf != NULL) { + /* + * Files are always readable by everyone. + */ + buf->st_mode |= S_IRUSR | S_IRGRP | S_IROTH; + + /* + * Use the Volume Info & File Info to fill out stat buf. + */ + if (fpb.hFileInfo.ioFlAttrib & 0x10) { + buf->st_mode |= S_IFDIR; + buf->st_nlink = 2; + } else { + buf->st_nlink = 1; + if (fpb.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) { + buf->st_mode |= S_IFLNK; + } else { + buf->st_mode |= S_IFREG; + } + } + if ((fpb.hFileInfo.ioFlAttrib & 0x10) || + (fpb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')) { + /* + * Directories and applications are executable by everyone. + */ + + buf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; + } + if ((fpb.hFileInfo.ioFlAttrib & 0x01) == 0) { + /* + * If not locked, then everyone has write acces. + */ + + buf->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; + } + buf->st_ino = fpb.hFileInfo.ioDirID; + buf->st_dev = fpb.hFileInfo.ioVRefNum; + buf->st_uid = -1; + buf->st_gid = -1; + buf->st_rdev = 0; + + if (CurrentFork == ResourceFork) + buf->st_size = fpb.hFileInfo.ioFlRLgLen; + else + buf->st_size = 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". + */ + + buf->st_mtime = MacFtime2UnixFtime(fpb.hFileInfo.ioFlMdDat); + buf->st_ctime = MacFtime2UnixFtime(fpb.hFileInfo.ioFlCrDat); + buf->st_atime = buf->st_ctime; /* best guess */ + +#ifdef DEBUG_TIME + { + struct tm *tp = localtime(&buf->st_mtime); + printf( + "\nUZmacstat: local buf->st_mtime is %ld = %d/%2d/%2d %2d:%2d:%2d", + buf->st_mtime, tp->tm_year, tp->tm_mon+1, tp->tm_mday, + tp->tm_hour, tp->tm_min, tp->tm_sec); + tp = gmtime(&buf->st_mtime); + printf( + "\nUZmacstat: UTC buf->st_mtime is %ld = %d/%2d/%2d %2d:%2d:%2d\n", + buf->st_mtime, tp->tm_year, tp->tm_mon+1, tp->tm_mday, + tp->tm_hour, tp->tm_min, tp->tm_sec); + } +#endif /* DEBUG_TIME */ + } + } + + if (err != noErr) { + errno = err; + } + + return (err == noErr ? 0 : -1); +} diff --git a/macos/source/macstat.h b/macos/source/macstat.h new file mode 100644 index 0000000..85c0f2b --- /dev/null +++ b/macos/source/macstat.h @@ -0,0 +1,72 @@ +/* + 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 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 +*/ +/***************************************************************** + * + * stat.h + * + *****************************************************************/ + +#ifndef __macstat_h +#define __macstat_h + +#include +typedef long dev_t; +typedef long ino_t; +typedef long off_t; + +#define _STAT + +struct stat { + dev_t st_dev; + ino_t st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + dev_t st_rdev; + off_t st_size; + time_t st_atime, st_mtime, st_ctime; + long st_blksize; + long st_blocks; +}; + +#define S_IFMT 0xF000 +#define S_IFIFO 0x1000 +#define S_IFCHR 0x2000 +#define S_IFDIR 0x4000 +#define S_IFBLK 0x6000 +#define S_IFREG 0x8000 +#define S_IFLNK 0xA000 +#define S_IFSOCK 0xC000 +#define S_ISUID 0x800 +#define S_ISGID 0x400 +#define S_ISVTX 0x200 +#define S_IREAD 0x100 +#define S_IWRITE 0x80 +#define S_IEXEC 0x40 + +#define S_IRUSR 00400 +#define S_IWUSR 00200 +#define S_IXUSR 00100 +#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) /* = 00700 */ + +#define S_IRGRP 00040 +#define S_IWGRP 00020 +#define S_IXGRP 00010 +#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) /* = 00070 */ + +#define S_IROTH 00004 +#define S_IWOTH 00002 +#define S_IXOTH 00001 +#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) /* = 00007 */ + + +extern int UZmacstat(const char *path, struct stat *buf); + +#endif /* !__macstat_h */ 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 +#include +#include +#include +#include + +#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 +#include + +/*****************************************************************************/ +/* 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/macunzip.c b/macos/source/macunzip.c new file mode 100644 index 0000000..90eb20e --- /dev/null +++ b/macos/source/macunzip.c @@ -0,0 +1,848 @@ +/* + Copyright (c) 1990-2006 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 +*/ +/*--------------------------------------------------------------------------- + + macunzip.c + + Main-function for use with the standalone Unzip App. + + ---------------------------------------------------------------------------*/ + + + +/*****************************************************************************/ +/* Includes */ +/*****************************************************************************/ + +#define UNZIP_INTERNAL +#include "unzip.h" +#include "unzvers.h" +#include "pathname.h" +#include "helpers.h" + +#include + + +/*****************************************************************************/ +/* Macros, typedefs */ +/*****************************************************************************/ + +#define aboutAlert 128 + +#define selectDialog 129 +#define okItem 1 +#define cancelItem 2 +#define editItem 3 +#define staticItem 4 + +#define unzipMenuBar 128 + +#define appleMenu 128 +#define aboutItem 1 + +#define fileMenu 129 +#define extractItem 1 +#define infoItem 2 +#define listItem 3 +#define testItem 4 +#define commentItem 6 +#define freshenItem 8 +#define updateItem 9 +#define quitItem 11 + +#define editMenu 130 +#define cutItem 1 +#define copyItem 2 +#define pasteItem 3 + +#define modifierMenu 131 +#define excludeItem 1 +#define selectItem 2 +#define quietItem 9 +#define verboseItem 10 + +#define screenMenu 132 +#define pauseItem 1 +#define scrollItem 2 + +#define extractMenu 133 +#define screenItem 3 +#define junkItem 5 + +#define caseMenu 134 +#define insensitiveItem 1 +#define lowercaseItem 2 + +#define convertMenu 135 +#define autoItem 1 +#define binaryItem 2 +#define textItem 3 + +#define overwriteMenu 136 +#define alwaysItem 1 +#define neverItem 2 +#define promptItem 3 + +#define infoMenu 137 +#define prtCommentItem 2 +#define prtHeaderItem 3 +#define prtTotalsItem 4 + +#define formatMenu 138 +#define filenameItem 1 +#define longItem 2 +#define mediumItem 3 +#define shortItem 4 + +#define allFlags 0x000FFFFF + +#define quietFlag 0x00000001 +#define verboseFlag 0x00000002 + +#define pauseFlag 0x00080000 +#define scrollFlag 0x00040000 + +#define screenFlag 0x00000004 +#define junkFlag 0x00000008 + +#define insensitiveFlag 0x00000010 +#define lowercaseFlag 0x00000020 + +#define autoFlag 0x00000040 +#define textFlag 0x00000080 + +#define neverFlag 0x00000100 +#define overwriteFlag 0x00000200 + +#define prtCommentFlag 0x00000400 +#define prtHeaderFlag 0x00000800 +#define prtTotalsFlag 0x00001000 + +#define filenameFlag 0x00002000 +#define longFlag 0x00004000 +#define mediumFlag 0x00008000 +#define shortFlag 0x00010000 + +#define extractMask 0x000003FD +#define infoMask 0x0001FE02 +#define listMask 0x00000001 +#define testMask 0x00000001 +#define commentMask 0x00000000 +#define freshenMask 0x000003FD +#define updateMask 0x000003FD + + +/*****************************************************************************/ +/* Global Vars */ +/*****************************************************************************/ + +char UnzipVersion[32], ZipinfoVersion[32]; + +long modifiers, modifierMask; + +EventRecord myevent; +MenuHandle appleHandle, modifierHandle, screenHandle, extractHandle; +MenuHandle caseHandle, convertHandle, overwriteHandle, infoHandle; +MenuHandle formatHandle; +Handle menubar, itemHandle; +short itemType; +Rect itemRect; + +char command; +extern char fileList[256]; + +Boolean stop; + +SysEnvRec sysRec; + + +/*****************************************************************************/ +/* Prototypes */ +/*****************************************************************************/ + +static void domousedown(EventRecord *myevent); + + + +/*****************************************************************************/ +/* Functions */ +/*****************************************************************************/ + +static Boolean TrapAvailable(machineType, trapNumber, trapType) +short machineType; +short trapNumber; +TrapType trapType; +{ + if (machineType < 0) + return (false); + + if ((trapType == ToolTrap) && + (machineType > envMachUnknown) && + (machineType < envMacII)) { + if ((trapNumber &= 0x03FF) > 0x01FF) + trapNumber = _Unimplemented; + } + return (NGetTrapAddress(trapNumber, trapType) != +#ifdef __MWERKS__ + NGetTrapAddress(_Unimplemented, trapType)); +#else + GetTrapAddress(_Unimplemented)); +#endif +} + + + +/* +** excute menu-command +** +*/ + +static void domenu(menucommand) long menucommand; +{ + short themenu, theitem; + DialogPtr thedialog; + Str255 name; + long check; + + themenu = HiWord(menucommand); + theitem = LoWord(menucommand); + + switch (themenu) { + + case appleMenu: + if (theitem == aboutItem) { + ParamText((StringPtr)UnzipVersion, (StringPtr)ZipinfoVersion, nil, nil); + Alert(aboutAlert, nil); + } else { + GetMenuItemText(appleHandle, theitem, name); + theitem = OpenDeskAcc(name); + } + break; + + case fileMenu: + switch (theitem) { + case extractItem: + if (modifiers & screenFlag) + command = 'c'; + else + command = 'x'; + modifierMask = extractMask; + break; + case infoItem: + command = 'Z'; + modifierMask = infoMask; + break; + case listItem: + if (modifiers & verboseFlag) + command = 'v'; + else + command = 'l'; + modifierMask = listMask; + break; + case testItem: + command = 't'; + modifierMask = testMask; + break; + case commentItem: + command = 'z'; + modifierMask = commentMask; + break; + case freshenItem: + command = 'f'; + modifierMask = freshenMask; + break; + case updateItem: + command = 'u'; + modifierMask = updateMask; + break; + case quitItem: + stop = true; + break; + default: + break; + } + break; + + case editMenu: + break; + + case modifierMenu: + switch (theitem) { + case excludeItem: + check = -1; + break; + case selectItem: + thedialog = GetNewDialog(selectDialog, nil, (WindowPtr)(-1)); + SetPort(thedialog); + do + ModalDialog(nil, &theitem); + while ((theitem != okItem) && (theitem != cancelItem)); + if (theitem == okItem) { + GetDialogItem(thedialog, editItem, &itemType, &itemHandle, + &itemRect); + GetDialogItemText(itemHandle, (StringPtr)&fileList); + p2cstr((StringPtr)fileList); + } + DisposeDialog(thedialog); + check = -1; + break; + case quietItem: + check = (modifiers ^= quietFlag) & quietFlag; + break; + case verboseItem: + check = (modifiers ^= verboseFlag) & verboseFlag; + break; + default: + break; + } + if (check == 0) + CheckItem(modifierHandle, theitem, false); + else if (check > 0) + CheckItem(modifierHandle, theitem, true); + break; + + case screenMenu: + switch (theitem) { + case pauseItem: + check = (modifiers ^= pauseFlag) & pauseFlag; + screenControl("p", check); + break; + case scrollItem: + check = (modifiers ^= scrollFlag) & scrollFlag; + screenControl("s", check); + break; + default: + break; + } + if (check == 0) + CheckItem(screenHandle, theitem, false); + else if (check > 0) + CheckItem(screenHandle, theitem, true); + break; + + case extractMenu: + switch (theitem) { + case screenItem: + check = (modifiers ^= screenFlag) & screenFlag; + break; + case junkItem: + check = (modifiers ^= junkFlag) & junkFlag; + break; + default: + break; + } + if (check == 0) + CheckItem(extractHandle, theitem, false); + else if (check > 0) + CheckItem(extractHandle, theitem, true); + break; + + case caseMenu: + switch (theitem) { + case insensitiveItem: + check = (modifiers ^= insensitiveFlag) & insensitiveFlag; + break; + case lowercaseItem: + check = (modifiers ^= lowercaseFlag) & lowercaseFlag; + break; + default: + break; + } + if (check == 0) + CheckItem(caseHandle, theitem, false); + else if (check > 0) + CheckItem(caseHandle, theitem, true); + break; + + case convertMenu: + switch (theitem) { + case autoItem: + CheckItem(convertHandle, autoItem, true); + CheckItem(convertHandle, binaryItem, false); + CheckItem(convertHandle, textItem, false); + modifiers &= (allFlags ^ textFlag); + modifiers |= autoFlag; + break; + case binaryItem: + CheckItem(convertHandle, autoItem, false); + CheckItem(convertHandle, binaryItem, true); + CheckItem(convertHandle, textItem, false); + modifiers &= (allFlags ^ (autoFlag | textFlag)); + break; + case textItem: + CheckItem(convertHandle, autoItem, false); + CheckItem(convertHandle, binaryItem, false); + CheckItem(convertHandle, textItem, true); + modifiers &= (allFlags ^ autoFlag); + modifiers |= textFlag; + break; + default: + break; + } + break; + + case overwriteMenu: + switch (theitem) { + case alwaysItem: + CheckItem(overwriteHandle, alwaysItem, true); + CheckItem(overwriteHandle, neverItem, false); + CheckItem(overwriteHandle, promptItem, false); + modifiers &= (allFlags ^ neverFlag); + modifiers |= overwriteFlag; + break; + case neverItem: + CheckItem(overwriteHandle, alwaysItem, false); + CheckItem(overwriteHandle, neverItem, true); + CheckItem(overwriteHandle, promptItem, false); + modifiers &= (allFlags ^ overwriteFlag); + modifiers |= neverFlag; + break; + case promptItem: + CheckItem(overwriteHandle, alwaysItem, false); + CheckItem(overwriteHandle, neverItem, false); + CheckItem(overwriteHandle, promptItem, true); + modifiers &= (allFlags ^ (neverFlag | overwriteFlag)); + break; + default: + break; + } + break; + + case infoMenu: + switch (theitem) { + case prtCommentItem: + check = (modifiers ^= prtCommentFlag) & prtCommentFlag; + break; + case prtHeaderItem: + check = (modifiers ^= prtHeaderFlag) & prtHeaderFlag; + break; + case prtTotalsItem: + check = (modifiers ^= prtTotalsFlag) & prtTotalsFlag; + break; + default: + break; + } + if (check == 0) + CheckItem(infoHandle, theitem, false); + else if (check > 0) + CheckItem(infoHandle, theitem, true); + break; + + case formatMenu: + switch (theitem) { + case filenameItem: + CheckItem(formatHandle, filenameItem, true); + CheckItem(formatHandle, longItem, false); + CheckItem(formatHandle, mediumItem, false); + CheckItem(formatHandle, shortItem, false); + modifiers &= (allFlags ^ (longFlag | mediumFlag | shortFlag)); + modifiers |= filenameFlag; + break; + case longItem: + CheckItem(formatHandle, filenameItem, false); + CheckItem(formatHandle, longItem, true); + CheckItem(formatHandle, mediumItem, false); + CheckItem(formatHandle, shortItem, false); + modifiers &= (allFlags ^ (filenameFlag | mediumFlag | shortFlag)); + modifiers |= longFlag; + break; + case mediumItem: + CheckItem(formatHandle, filenameItem, false); + CheckItem(formatHandle, longItem, false); + CheckItem(formatHandle, mediumItem, true); + CheckItem(formatHandle, shortItem, false); + modifiers &= (allFlags ^ (filenameFlag | longFlag | shortFlag)); + modifiers |= mediumFlag; + break; + case shortItem: + CheckItem(formatHandle, filenameItem, false); + CheckItem(formatHandle, longItem, false); + CheckItem(formatHandle, mediumItem, false); + CheckItem(formatHandle, shortItem, true); + modifiers &= (allFlags ^ (filenameFlag | longFlag | mediumFlag)); + modifiers |= shortFlag; + break; + default: + break; + } + break; + + default: + break; + + } + + HiliteMenu(0); + return; +} + + + +/* +** work with shortcuts +** +*/ + +static void dokey(myevent) EventRecord *myevent; +{ + char code; + + code = (char)(myevent->message & charCodeMask); + + if (myevent->modifiers & cmdKey) { + if (myevent->what != autoKey) { + domenu(MenuKey(code)); + } + } + + return; +} + + + +/* +** work with mouse-events +** +*/ + +static void domousedown(EventRecord *myevent) +{ + WindowPtr whichwindow; + long code; + + code = FindWindow(myevent->where, &whichwindow); + + switch (code) { + + case inSysWindow: + SystemClick(myevent, whichwindow); + break; + + case inMenuBar: + domenu(MenuSelect(myevent->where)); + break; + + } + + return; +} + + + +/* +** Do a little event-handling and let the user stop +** th current action +*/ + +void UserStop(void) +{ + EventRecord theEvent; + + if ( WaitNextEvent( everyEvent, &theEvent, 0, nil )) { + + switch (theEvent.what) { + + case mouseDown: + domousedown( &theEvent ); + break; + + case autoKey: + case keyDown: + if ((theEvent.modifiers & cmdKey) && + ((theEvent.message & charCodeMask) == '.')) + { + printf("\n\n <- User Canceled -> \n"); + exit(1); /* setjmp() must be already called */ + } + return; + + } /* switch (theEvent.what) */ + } /* if ( WaitNextEvent(... */ +} + + + +/* +** The Standalone Unzip starts here +** +*/ + +int main(argc, argv) int argc; char *argv[]; +{ + Uz_Globs saveGlobals; + Boolean haveEvent, useWNE; + short markChar; + char *ArchivePath, *ExtractPath; + OSErr err; + + FlushEvents(everyEvent, 0); + InitGraf(&qd.thePort); + InitFonts(); + InitWindows(); + InitMenus(); + TEInit(); + InitDialogs(nil); + InitCursor(); + + CONSTRUCTGLOBALS(); + + sprintf(UnzipVersion, "%d.%d%d%s of %s", UZ_MAJORVER, UZ_MINORVER, + UZ_PATCHLEVEL, UZ_BETALEVEL, UZ_VERSION_DATE); + sprintf(ZipinfoVersion, "%d.%d%d%s of %s", ZI_MAJORVER, ZI_MINORVER, + UZ_PATCHLEVEL, UZ_BETALEVEL, UZ_VERSION_DATE); + + c2pstr(UnzipVersion); + c2pstr(ZipinfoVersion); + + SysEnvirons(1, &sysRec); + useWNE = TrapAvailable(sysRec.machineType, _WaitNextEvent, ToolTrap); + + SetMenuBar(menubar = GetNewMBar(unzipMenuBar)); + DisposeHandle(menubar); + InsertMenu(GetMenu(screenMenu), -1); + InsertMenu(GetMenu(extractMenu), -1); + InsertMenu(GetMenu(caseMenu), -1); + InsertMenu(GetMenu(convertMenu), -1); + InsertMenu(GetMenu(overwriteMenu), -1); + InsertMenu(GetMenu(infoMenu), -1); + InsertMenu(GetMenu(formatMenu), -1); + AppendResMenu(appleHandle = GetMenuHandle(appleMenu), 'DRVR'); + modifierHandle = GetMenuHandle(modifierMenu); + screenHandle = GetMenuHandle(screenMenu); + extractHandle = GetMenuHandle(extractMenu); + caseHandle = GetMenuHandle(caseMenu); + convertHandle = GetMenuHandle(convertMenu); + overwriteHandle = GetMenuHandle(overwriteMenu); + infoHandle = GetMenuHandle(infoMenu); + formatHandle = GetMenuHandle(formatMenu); + DrawMenuBar(); + + screenOpen("Unzip"); + + modifiers = 0; + + GetItemMark(modifierHandle, quietItem, &markChar); + if (markChar) modifiers ^= quietFlag; + GetItemMark(modifierHandle, verboseItem, &markChar); + if (markChar) modifiers ^= verboseFlag; + + GetItemMark(screenHandle, pauseItem, &markChar); + if (markChar) modifiers ^= pauseFlag; + screenControl("p", markChar); + GetItemMark(screenHandle, scrollItem, &markChar); + if (markChar) modifiers ^= scrollFlag; + screenControl("s", markChar); + + GetItemMark(extractHandle, screenItem, &markChar); + if (markChar) modifiers ^= screenFlag; + GetItemMark(extractHandle, junkItem, &markChar); + if (markChar) modifiers ^= junkFlag; + + GetItemMark(caseHandle, insensitiveItem, &markChar); + if (markChar) modifiers ^= insensitiveFlag; + GetItemMark(caseHandle, lowercaseItem, &markChar); + if (markChar) modifiers ^= lowercaseFlag; + + GetItemMark(convertHandle, autoItem, &markChar); + if (markChar) modifiers ^= autoFlag; + GetItemMark(convertHandle, textItem, &markChar); + if (markChar) modifiers ^= textFlag; + + if ((modifiers & (autoFlag | textFlag)) == (autoFlag | textFlag)) { + CheckItem(convertHandle, textItem, false); + modifiers &= (allFlags ^ textFlag); + } else if (modifiers & (autoFlag | textFlag)) + CheckItem(convertHandle, binaryItem, false); + else + CheckItem(convertHandle, binaryItem, true); + + GetItemMark(overwriteHandle, alwaysItem, &markChar); + if (markChar) modifiers ^= overwriteFlag; + GetItemMark(overwriteHandle, neverItem, &markChar); + if (markChar) modifiers ^= neverFlag; + + if ((modifiers & (neverFlag | overwriteFlag)) == (neverFlag | overwriteFlag)) { + CheckItem(overwriteHandle, alwaysItem, false); + CheckItem(overwriteHandle, neverItem, false); + CheckItem(overwriteHandle, promptItem, true); + modifiers &= (allFlags ^ (neverFlag | overwriteFlag)); + } else if (modifiers & (neverFlag | overwriteFlag)) + CheckItem(overwriteHandle, promptItem, false); + else + CheckItem(overwriteHandle, promptItem, true); + + GetItemMark(infoHandle, prtCommentItem, &markChar); + if (markChar) modifiers ^= prtCommentFlag; + GetItemMark(infoHandle, prtHeaderItem, &markChar); + if (markChar) modifiers ^= prtHeaderFlag; + GetItemMark(infoHandle, prtTotalsItem, &markChar); + if (markChar) modifiers ^= prtTotalsFlag; + + GetItemMark(formatHandle, filenameItem, &markChar); + if (markChar) modifiers ^= filenameFlag; + GetItemMark(formatHandle, longItem, &markChar); + if (markChar) modifiers ^= longFlag; + GetItemMark(formatHandle, mediumItem, &markChar); + if (markChar) modifiers ^= mediumFlag; + GetItemMark(formatHandle, shortItem, &markChar); + if (markChar) modifiers ^= shortFlag; + + if (modifiers & longFlag) { + CheckItem(formatHandle, filenameItem, false); + CheckItem(formatHandle, mediumItem, false); + CheckItem(formatHandle, shortItem, false); + modifiers &= (allFlags ^ (filenameFlag | mediumFlag | shortFlag)); + } else if (modifiers & mediumFlag) { + CheckItem(formatHandle, filenameItem, false); + CheckItem(formatHandle, shortItem, false); + modifiers &= (allFlags ^ (filenameFlag | shortFlag)); + } else if (modifiers & shortFlag) { + CheckItem(formatHandle, filenameItem, false); + modifiers &= (allFlags ^ filenameFlag); + } + + command = ' '; + + stop = false; + while (!stop) { + SetCursor(&qd.arrow); + + if (useWNE) { + haveEvent = WaitNextEvent(everyEvent, &myevent, LONG_MAX, NULL); + } else { + SystemTask(); + haveEvent = GetNextEvent(everyEvent, &myevent); + } + + if (haveEvent) { + switch (myevent.what) { + + case activateEvt: + break; + + case keyDown: + case autoKey: + dokey(&myevent); + break; + + case mouseDown: + domousedown(&myevent); + break; + + case updateEvt: + screenUpdate((WindowPtr)myevent.message); + break; + + case mouseUp: + case keyUp: + break; + + default: + break; + + } + } + + if (command != ' ') { + char *s, **v, modifierString[32]; + Point p; + int m, n; + SFTypeList myTypes = {'TEXT', 'ZIP '}; + StandardFileReply myReply; + + SetPt(&p, 40, 40); + + StandardGetFile(nil, 2, myTypes, &myReply); + + ArchivePath = StrCalloc(512); + ExtractPath = StrCalloc(512); + + GetFullPathFromSpec(ArchivePath, &myReply.sfFile, &err); + + strcpy(ExtractPath,ArchivePath); + FindNewExtractFolder(ExtractPath, false); + + if (myReply.sfGood && (CheckMountedVolumes(ArchivePath) == 1)) { + modifierMask &= modifiers; + + s = modifierString; + + *s++ = '-'; + if ((command != 'x') && (command != 'Z')) *s++ = command; + + if (modifierMask) { + if (modifierMask & (autoFlag | textFlag)) *s++ = 'a'; + if (modifierMask & textFlag) *s++ = 'a'; + if (modifierMask & insensitiveFlag) *s++ = 'C'; + if (modifierMask & junkFlag) *s++ = 'j'; + if (modifierMask & lowercaseFlag) *s++ = 'L'; + if (modifierMask & neverFlag) *s++ = 'n'; + if (modifierMask & overwriteFlag) *s++ = 'o'; + if (modifierMask & quietFlag) *s++ = 'q'; + if (modifierMask & verboseFlag) *s++ = 'v'; + + if (modifierMask & prtCommentFlag) *s++ = 'z'; + if (modifierMask & prtHeaderFlag) *s++ = 'h'; + if (modifierMask & prtTotalsFlag) *s++ = 't'; + if (modifierMask & filenameFlag) *s++ = '2'; + if (modifierMask & longFlag) *s++ = 'l'; + if (modifierMask & mediumFlag) *s++ = 'm'; + if (modifierMask & shortFlag) *s++ = 's'; + } + + if (*(s - 1) == '-') s -= 1; + + *s++ = 'd'; + *s = '\0'; + + v = (char **)malloc(sizeof(char *)); + *v = "unzip"; + argc = 1; + + envargs(&argc, &v, NULL, NULL); + + argv = (char **)malloc((argc + 3) * sizeof(char *)); + + argv[m = 0] = (command == 'Z') ? "zipinfo" : "unzip"; + if (*modifierString) argv[++m] = modifierString; + argv[++m] = ExtractPath; + argv[++m] = ArchivePath; + for (n = 1; n < argc; n++) argv[n + m] = v[n]; + argv[argc += m] = NULL; + + free(v); + + for (n = 0; argv[n] != NULL; n++) printf("%s ", argv[n]); + printf("...\n\n"); + + memcpy(&saveGlobals, &G, sizeof(Uz_Globs)); + + unzip(__G__ argc, argv); + + memcpy(&G, &saveGlobals, sizeof(Uz_Globs)); + + ArchivePath = StrFree(ArchivePath); + ExtractPath = StrFree(ExtractPath); + + printf("\nDone\n"); + } + + fileList[0] = '\0'; + command = ' '; + } + } + + screenClose(); + + DESTROYGLOBALS(); + + ExitToShell(); + +return 0; +} 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 +#include +#include +#include + +#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/sxunzip.c b/macos/source/sxunzip.c new file mode 100644 index 0000000..6684e35 --- /dev/null +++ b/macos/source/sxunzip.c @@ -0,0 +1,144 @@ +/* + 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 +*/ +/*****************************************************************************/ +/* Includes */ +/*****************************************************************************/ + +#include +#include "unzvers.h" +#include + + +#ifdef USE_SIOUX +# include +# include +# include +# include +#endif /* USE_SIOUX */ + + +/*****************************************************************************/ +/* Global Vars */ +/*****************************************************************************/ + +char fileList[256]; + + +/*****************************************************************************/ +/* Prototypes */ +/*****************************************************************************/ + +int UzpMain(int argc,char **argv); + +char *GetUnZipLocalVersion(void); +char *GetUnZipInfoVersions(void); +int macgetch(void); +void UserStop(void); + + + +/*****************************************************************************/ +/* Functions */ +/*****************************************************************************/ + +#ifndef MacStaticLib +#ifndef MACUNZIP_STANDALONE + +/* +Program execution starts here with Metrowerks SIOUX-Console */ +int main(int argc,char **argv) +{ + int return_code; + + SIOUXSettings.asktosaveonclose = FALSE; + SIOUXSettings.showstatusline = TRUE; + + SIOUXSettings.columns = 100; + SIOUXSettings.rows = 40; + + argc = ccommand(&argv); + + return_code = UzpMain(argc,argv); + + printf("\n\n Finish %d",return_code); + + return return_code; +} + + + +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; +} + + +/* SIOUX needs no extra event handling */ +void UserStop(void) +{ +} + +#endif /* #ifndef MACUNZIP_STANDALONE */ +#endif /* #ifndef MacStaticLib */ + + + + +char *GetUnZipLocalVersion(void) +{ +static char UnZipVersionLocal[50]; + +memset(UnZipVersionLocal,0,sizeof(UnZipVersionLocal)); + +sprintf(UnZipVersionLocal, "[%s %s]", __DATE__, __TIME__); + +return UnZipVersionLocal; +} + + + + +char *GetUnZipInfoVersions(void) +{ +static char UnzipVersion[200]; + +memset(UnzipVersion,0,sizeof(UnzipVersion)); + +sprintf(UnzipVersion, "Unzip Module\n%d.%d%d%s of %s", UZ_MAJORVER, + UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, UZ_VERSION_DATE); + +return UnzipVersion; +} diff --git a/macos/source/unzip_rc.hqx b/macos/source/unzip_rc.hqx new file mode 100644 index 0000000..bd7f141 --- /dev/null +++ b/macos/source/unzip_rc.hqx @@ -0,0 +1,92 @@ +(This file must be converted with BinHex 4.0) +:#d&bBfKTGQ8ZFfPd!&0*9%46593K!*!%%23!N!65[90*9#%!!J!!%24b6'&e!TN +!N!-@QCN0!!KeERTTF#jbBaEf1!6lrh3!6%TU!*!$J!#3"!8$bq6#IJ#3&!Y[!*! +%rj!%8P053e*6483K!,'+E[HbPeU-!!!FrJ#3"JVT!*!%KNX!N!MBC3`!&CjkAB5 +YAEECeXrEK!)``L9EH[`m0leZ$pK[bPfEGECTRT`1q"0'1'%ARKUq$XpGhcEqDm, +*FGHDf*-4Mh#bM``fZAf%Cq6jNGq%Gf56#5I()i``-Q+E8"lEK*(EC%,**Z`f18D +1NpYNXM*bE0+[E"AiqVj*hqGQK"ej6UDEE,*I-YTNX-P[XJ&H"ddL4#+%2,fHN!# +0m2Sq-Bc'B(8eT@q`L0,ClAYMACV4fd9IS-QiYVdUPCM9NNe'*%)E`Z(1aSKUUUE +CX+Ya6$A-aQ$#4`D("MX(KlUlYK$b$[N,Q#ZIAjp,h1E)jTaQ@[5jj'aMm)dJT3H +95'mLUJ-KVS(EL"+,kC%'fV+0QYUXUNGTJfNCUBMP#$8fIKp8iG'!#TU0!+%25MZ +4(ZiB9#-dSL9($G5K0+`B5V`$2"e&SU""'SBUGk3Kh)#Lf`pTb@G01S**TP(G3+m +l(a#Y#4A*@X,5cBPYY&02cKMDq)4&hf[C[IYli+FVF,kq194e6$iQfckiZ6QilGR +fl*Bl'c1"mi3!2a1kFbal,'[RR)YSk%ipij-!A1i$G)lF',JfIq(%m6RILH2c&`D +Z(ERKk2cGamE-PMZB!F`%U%"@-$ZKU[VQIrVBd%bVNTZR@l0[jN!MPmZq1GfDh%b +V0[c$ab5TB&fJ4fSKKk5il"[i!FHKD4b5[L(l1j9%4)dacR0N)pNMaGI`[V%1d+e +5['VR8&+0D0%C'Y9L+NdSFEA"E+43QdR&XP3MJDLPde'9UY1@S83XG@`2kUmQ$A! +rNqC)ZUX,m+mcr-I5ViJNXAB)C`k$Vj%QXNVUN@i3ZG$"!ZhKF*q!$[@'+GIFfJX +Y!Q+TCl#lKe(5%-heG[Brik%3rejBI&q5bHqN0MI[Q0@I5'e9lidN`!Jph,b0MXj +3hRYk`dh"X'jBQTi`D81NNEEXhV8Ek800G(m6(BTVeN46-!LkV)-HKTi*j(jebTT +5$*8UL6(@Vk*D!J)pGY5NLT@h&Ka53@%d08i003Nf65`E*@90k!C6JTkh(GKQfp6 +4e14d5a1%6HTB#V2f&'qHmRHDGZjBaEXM3N"C"8@6KS`I*bF!E3"-(0Zf2jI@V@i +Ie9-@EkJAN5CYG`6HjYA(Y6ir)[G!H9Gema+q5!B)UF68A55pJ26"#('43$9@$UZ +)$$Y'eR4TCM+Qc%"RMXI9"&"GMc8pKQT1U!Q+aNa'$)iNaa4,c61iP2aL5V2)Lc` +Cqb'AAJirP,[(0%XH5BcTj*!!SeI4QE,)+k#,m`$TK,5%&G05b8Z!G-C8aA!-r)* +9KI#5qe2e3Ae-LfS`3p9d6dGLU6%h&@!'bM1Q`Y`M'%0Z(SFLKJTT(%LbaN!fR46 +%@P%X([-8@FdkJdXi+k4@3B*9'+Rd-CAeXjG8Be3h!9[,FY016ZC6ETFGV`iV+91 +PR)553B$d@#c2`(1FR#UB@-V1QNi&6DJ*8l1d5FfD)CY1NpT126%*j3!#2$QEjNQ +G)`cGbA&)528!k%`C'P6CTM1NEP#0kj-U$([@"1f(NF"dV,H6q@)@bJDVfe1@(PF +X,B*TmhGS#F@BB5eJ'+B(4hNh19-`iARhYmHQP"PQYV*I"4BLrV#Kaj-JcZ[J9A+ +f)&kX5(q2ES"lXZNF#BB0Q#UG[X@k%fIX9a@FXYN)`aR$ZUA%h!`I)+F,rTEVUUi +hB3S8CeFV-X'D4CmqT4S4e",e`V1eMj`VZ"%*UX%QK+1@53F5-9iJIATLR+AlS$U +QTH+X"SCJGR#U"SBUk(%q!0JEbNNqkT0b)Cq8PRa!KAJG['ZPh%Fr*'rrmJKjpf` +[@AJ,XAEblNF+@8K,8Xl9JKLed32c)RbK4c"lKS6X-i55+[BqBfI)AL!$Y`+5k,j +ALkKYCq(056RE*YN[AZ5@00&$J5(mh`(rKCIjKmd++c8X*(%bJ1-V6[!+iRrQjim +,#apcA'Lj1&GN12#bb(I`l-,#!QJc(F&R4rLk`U4V,f&dem-A--5mC$,4k15N[X! +%-TGU5HBe[pm26-5cQ8Z3!#`JN!#lk)rBUff5m41r2jTNZ+Y(#-1C([TjMH0-MbF +DFHlA``%+&[2e-*r&I+203Md`[&3[D!(2HH%$mqiF*`q&HR420LKJ3ACaF-D1Lhm +Xl,LiPd@ZRrIP,K(bYS[(SDmXcI"mqUNJfJ!9$hNH6j&ImR@2RcIQmF9aS@8q!a" +LCiAr)+&Z[Y`-)qPj&l5G2*EiH3((MNdZ`rNYh-ZB#Nq!!!BSm!NmH!X&aFbL'K+ +%!VV1'`3kj`-6qH#5j2NVrV!JlrPcme2LHri+"Hee#6HrprNLI&aIrkV24rAYC20 +[r5(2Ip*I4"EFipCrZGkAcP)p21b2+mF'Lb9f@AQ&ch1@6p%brf&b22k6j$c+9eZ +p[Ilkl6UlEVlHVV&VlYE-eGYeYq[@Akqh!jr*[N#fhUkhiF%,I,J-`b#3!)1E"3p +TCh)KY6J@,8"`"6#-NB1cA5h%YReVr"KfRFbYD*6(ij1e'-038ZYjm25j(jL0(#i +$lU+F'()BNFhd5dA'#YXT0e%F'2''i"@,D!#m1J61$VC1865X&b)1K",1Qf'q9hV +kHArhr4Ib)mTjTAiGF,P91AK"$@GkCi4daM`SVq)-jq$1Z1[L!R"a-4pl1%GF2m+ +LJ`I&b1RJ`!#mN!!Ga2-cp!0qILH3!-IC6S$MqCd!`r-l!DlRl33BRYm*Z(TL*q$ +k%6X"efq"AmErRFqPHLML6+@!)k')BlplJZIVhA%YC[S[*aAlC[%X#bcaEbk0%d[ +mXX!+[b4`Mem8@-j21BYPrXfPL@L*cc4+,G8jbrcbc2U9IQ%-,16K2VmJi2*,1i9 +lr1*1iEkr`NlK(Vqi8hMXMmhmMr2cN!"IfKPmaIqI"rAjCApic2F%([*GK8GmCkl +l$rq,G8+Tc8XN!+YH'Ii9bHcA5c@m9@Piff45Ha8Q")S[U0'd*1*em+iP&2EG&2E +G&2EG&2EG&2EG&2EG6-I9%V(`d3a[+l`KmEB'B$*%r`%l#fm1AK[I0,cRiEhU[*! +!V[qq`JGiYE2`fZ*&$#HYYY"9fN`ED+XYfr)m[,Cm9jjM-IA63#JAZKU#Ef'KV,e +mJ@Z(F(HHCRAQE-ECTPH-cJb(QCr9h"8hCRX1L2QH!f+fjd!Fpac)a`(1dh0L2QM +#QS6(h"KcMRZ0jAeXH@TcF6&#HAa8+24"E((,Z1JR,Llf(N8F##@FQh6eKHN(rXT +iSERaPPV%miTZcV%)5Yp#jFASYDdI!Q@cEjDX`Amc)(#ZFf4`#(la[G291p`(q1@ +Z[S&pS2(APh[lm9rGVIDq3Ib2jH0ri+5DM[iZq+NPIC2rN!#6GQJ4%hN(Y%KX&m5 +MJ'-m#rLh)Ii4i"LrIl#MI4"d,acXlKq"$hPri$rYI)2iVm-G%Ab)9Ec!X,4Y3fY +mQ@&c$2XC`iicl"1'R8"-qTDM!IkQ('d`ShXm(rq[ahP2HjKdhF-#Sr,LF!2AHkT +$AKbr)I6fbB[DK-"Dj-@*2Z'T&E#6R&H6!#c'HHYlS0*HjEa9VmZ,"lSiEqeHm24 +ccU[p,RKkKI-fe)$H"jaA&38IdjbhCSqmq2T@iHmhS,G"q$X(HMrP[!TH(aaM[lq +i4X9EAUh)M8kY`+U$IIMM(m)U0c2X&,EA5S9Kmk3H-&jEC`M8PAmE`ml#TbRLeaK +f'Rjh%MrlA`HrLm"r!,S,1iHKdkb9&dFq+(ma@rSXY[aYbrf"9Ia1YIchbIQq0$# +98!hijQMU+51LrKm0!!YeERTTF(0QBbjbB`6lrh3!6%TU!*!$J!#3"!8$bq5qFJ# +3%4B!N!MrN!458e*$8P0&4#%!XBTZpl+A@GJ!!!Nf!*!'"48!N!6(q`#3##3`)d3 +1)LTG595#b[aFefGjh@l'cV8kJ@fHHiB5P2Af)&[1-QPjVLHVETBc4L,Qdf2KF'" +@M"[F-'SAciTchCMP9Ch8(HN1G%GDJY1)ER1JFEr[AU,qfNBdLf6$C,-cQfGjcr8 +beLR&fY@%"X)F'@jR5)ULa@TCBadcj-eF5l"D`p5c-E-J0'M@k9#&8JBUD!i#K$i +%&K$d((mhMl'BR1R9KBl!`T)ZTIh`G*-J5M5))DpihM$D3#%kj'`j-p0JDd6)3N, +6KGHK[bI@T,JJPkQQCU6U@%$,$1Pb-Q@bIBe,PT`'2r1Sb%Sj`p&)Cc[5,QIADKX +R2`$Hee85N!$8'&FX6J5G3%XGk5Tl,[b"KMV5CI-M'4k6%d-X)5ZFU9+DeaUc',a +A5DE*G9@J04VVjB`2QVS8-hPmUG$A85fq&XGf'Ji'JIH`m0@1qmMKX-BGhK,4q*' +2bKfYMPq5kmL%UTV$iBim0,8pc'c0d(D-!24-DhG,Ud@T3lHN24#D2ST#rd,HiPD +(Lcl[D"V*(92pQU1TE0mD&8D%FaVU@1m3XfGVE0MR$@Zk+@ZU`@TMXeMMNX9,"$h +2apTm,*+@cC62ki8Zh4$6X41!R-d(c!&*jda5ipBmPXSUQNUPcf#51@E01m+K8*4 +0-TeRB0-UaUB`DkBdh9+#Q4i#YV9TS#rE2pMS3a[&ieQ4@S#p(2L&[[RcbZhT4`J +S@Ja0(4*I5KF!$3FQ29XZpe[(a)VQALeVfJ[MH8&MjKB%lV1R6p5kZ-(9L[&@YpJ +Mr$ae%4@,k*kRGL"C@*(2%kC4%H8#b5mB-3CP)k0)3pJmFp*F"GAZ8GqUFb2&95D +-@5fLpjT-A$,j'%18iXr-bLDGDBGK3CD1$(Hk@Z+bk9UMaM8kZk$("E)QVBFZlMX +53#`jNQ&b@JXN6H'5AM#`dCS+b8[E0pfG@Pa1b,J4p#f$-58E(iN#c-"iPR2XGBQ +40j*MANcRL(&maPS-j+3GHD)K2b`1jZe8B@d'1q(1[*3@!CIJC+L-FfZI6H*kVfB +!ml@b5D8GBj(EIZGB&jDb"QFf#5@p!98UbKJ$he+km)J*GcV'J#4-P+L'E-VpXMP +%*ee%P3&0lFFiJ)!B6TqG9&d3KZdN1i3VD6adjZXbTUc2,UVZjQQYRq1BU8Qa%%i +#Dm&k+ZdmQN+R38eceY65NLR(4'a+[ka+qT!!Y3,bF6h)bYI3VL-Q(0k9cFU!0'5 +C9B3i@)JS`lU@cN"FR)0TG2%4mID*9,CU1Yb6NbiKEeM(e56[,EUG4)D&5q++T#H +-b-MA6%NC56L6,MVLVfZZI0T9)irLE9B65eR,)NXEi(T-D%Rc)UBeKLijiNB+5#q +@%*jD9YDP+[D!C'PUdSTl()r,fE3e!hQi(Ha6J`G2aaR0rpA'(6-H"XAN1*rFBJj +")$IB(Ze!2c[Bd389F[kkpT!!Z-rZEZlSaPiR0rP$3A&hEFTI@$XkrFhGiU)Dea* +DJh[MN!"pJ6&RNb1A'lR@@)'aTpKA(H90YV!kJ6&GVVq+RTcRrF,e9mQp0Sqm0DT +"[MkQ0p$e9r+b21B$62,%R1ckUp5$0Smp$Eci2$BD@,LY`@k#aMSk2jGc8C(Ep9I +YLqN#`H2@J,I+AV6F)@$ef*F'c&8UmRJG@bXBf%r!@iRP%ihCdJ&V`#kj4Pa#J"9 +MlM1!E3&@J+Q&I"@r"SEM24d6CiD24hkhZYe,Z'XGfMGEqjVUfLRb@KJrS()Gjk0 +9bqSarMi!*p!!!!: diff --git a/man/Contents b/man/Contents new file mode 100644 index 0000000..1036869 --- /dev/null +++ b/man/Contents @@ -0,0 +1,14 @@ +Contents of the "man" subdirectory for UnZip 5.41 and later: + + Contents this file + funzip.1 fUnZip manual page, nroff format + unzip.1 UnZip manual page, nroff format + unzipsfx.1 UnZipSFX manual page, nroff format + zipgrep.1 ZipGrep manual page, nroff format + zipinfo.1 ZipInfo manual page, nroff format + +This subdirectory contains the master source files for the UnZip user +documentation. Although these documents are Unix man-page sources, they +are of general interest and therefore stored separately. +Some non-Unix systems may supply a man-page reader where they could be +used; and they are the sources for the generic ASCII text document files. diff --git a/man/funzip.1 b/man/funzip.1 new file mode 100644 index 0000000..30206e4 --- /dev/null +++ b/man/funzip.1 @@ -0,0 +1,127 @@ +.\" Copyright (c) 1990-2009 Info-ZIP. All rights reserved. +.\" +.\" See the accompanying file LICENSE, version 2009-Jan-02 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 +.\" +.\" funzip.1 by Greg Roelofs and others. +.\" +.\" ========================================================================= +.\" define .EX/.EE (for multiline user-command examples; normal Courier font) +.de EX +.in +4n +.nf +.ft CW +.. +.de EE +.ft R +.fi +.in -4n +.. +.\" ========================================================================= +.TH FUNZIP 1L "20 April 2009 (v3.95)" "Info-ZIP" +.SH NAME +funzip \- filter for extracting from a ZIP archive in a pipe +.PD +.SH SYNOPSIS +\fBfunzip\fP [\fB\-password\fP] [\fIinput[.zip|.gz]\fP] +.\" ========================================================================= +.SH ARGUMENTS +.IP [\fI\-password\fP] +Optional password to be used if ZIP archive is encrypted. Decryption +may not be supported at some sites. See DESCRIPTION for more details. +.IP [\fIinput[.zip|.gz]\fP] +Optional input archive file specification. See DESCRIPTION for details. +.PD +.\" ========================================================================= +.SH DESCRIPTION +.I funzip +without a file argument acts as a filter; that is, it assumes that a +ZIP archive (or a \fIgzip\fP'd(1) file) is being piped into +standard input, and it extracts the first member from the archive to stdout. +When stdin comes from a tty device, +.I funzip +assumes that this cannot be a stream of (binary) compressed data and +shows a short help text, instead. +If there is a file argument, then input is read from the specified file +instead of from stdin. +.PP +A password for encrypted zip files can be specified +on the command line (preceding the file name, if any) by prefixing the +password with a dash. Note that this constitutes a security risk on many +systems; currently running processes are often visible via simple commands +(e.g., \fIps\fP(1) under Unix), and command-line histories can be read. +If the first entry of the zip file is encrypted and +no password is specified on the command line, then the user is prompted for +a password and the password is not echoed on the console. +.PP +Given the limitation on single-member extraction, \fIfunzip\fP is most +useful in conjunction with a secondary archiver program such as \fItar\fP(1). +The following section includes an example illustrating this usage in the +case of disk backups to tape. +.PD +.\" ========================================================================= +.SH EXAMPLES +To use \fIfunzip\fP to extract the first member file of the archive test.zip +and to pipe it into \fImore\fP(1): +.PP +.EX +funzip test.zip | more +.EE +.PP +To use \fIfunzip\fP to test the first member file of test.zip (any errors +will be reported on standard error): +.PP +.EX +funzip test.zip > /dev/null +.EE +.PP +To use \fIzip\fP and \fIfunzip\fP in place of \fIcompress\fP(1) and +\fIzcat\fP(1) (or \fIgzip\fP(1L) and \fIgzcat\fP(1L)) for tape backups: +.PP +.EX +tar cf \- . | zip \-7 | dd of=/dev/nrst0 obs=8k +dd if=/dev/nrst0 ibs=8k | funzip | tar xf \- +.EE +.PP +(where, for example, nrst0 is a SCSI tape drive). +.PD +.\" ========================================================================= +.SH BUGS +When piping an encrypted file into \fImore\fP and allowing \fIfunzip\fP +to prompt for password, the terminal may sometimes be reset to a non-echo +mode. This is apparently due to a race condition between the two programs; +\fIfunzip\fP changes the terminal mode to non-echo before \fImore\fP reads +its state, and \fImore\fP then ``restores'' the terminal to this mode before +exiting. To recover, run \fIfunzip\fP on the same file but redirect to +/dev/null rather than piping into more; after prompting again for the +password, \fIfunzip\fP will reset the terminal properly. +.PP +There is presently no way to extract any member but the first from a ZIP +archive. This would be useful in the case where a ZIP archive is included +within another archive. In the case where the first member is a directory, +\fIfunzip\fP simply creates the directory and exits. +.PP +The functionality of \fIfunzip\fP should be incorporated into \fIunzip\fP +itself (future release). +.PD +.\" ========================================================================= +.SH "SEE ALSO" +\fIgzip\fP(1L), \fIunzip\fP(1L), \fIunzipsfx\fP(1L), \fIzip\fP(1L), +\fIzipcloak\fP(1L), \fIzipinfo\fP(1L), \fIzipnote\fP(1L), \fIzipsplit\fP(1L) +.PD +.\" ========================================================================= +.SH URL +The Info-ZIP home page is currently at +.EX +\fChttp://www.info-zip.org/pub/infozip/\fR +.EE +or +.EX +\fCftp://ftp.info-zip.org/pub/infozip/\fR . +.EE +.PD +.\" ========================================================================= +.SH AUTHOR +Mark Adler (Info-ZIP) diff --git a/man/unzip.1 b/man/unzip.1 new file mode 100644 index 0000000..75a7060 --- /dev/null +++ b/man/unzip.1 @@ -0,0 +1,1040 @@ +.\" Copyright (c) 1990-2009 Info-ZIP. All rights reserved. +.\" +.\" See the accompanying file LICENSE, version 2009-Jan-02 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 +.\" +.\" unzip.1 by Greg Roelofs, Fulvio Marino, Jim van Zandt and others. +.\" +.\" ========================================================================= +.\" define .EX/.EE (for multiline user-command examples; normal Courier font) +.de EX +.in +4n +.nf +.ft CW +.. +.de EE +.ft R +.fi +.in -4n +.. +.\" ========================================================================= +.TH UNZIP 1L "20 April 2009 (v6.0)" "Info-ZIP" +.SH NAME +unzip \- list, test and extract compressed files in a ZIP archive +.PD +.SH SYNOPSIS +\fBunzip\fP [\fB\-Z\fP] [\fB\-cflptTuvz\fP[\fBabjnoqsCDKLMUVWX$/:^\fP]] +\fIfile\fP[\fI.zip\fP] [\fIfile(s)\fP\ .\|.\|.] +[\fB\-x\fP\ \fIxfile(s)\fP\ .\|.\|.] [\fB\-d\fP\ \fIexdir\fP] +.PD +.\" ========================================================================= +.SH DESCRIPTION +\fIunzip\fP will list, test, or extract files from a ZIP archive, commonly +found on MS-DOS systems. The default behavior (with no options) is to extract +into the current directory (and subdirectories below it) all files from the +specified ZIP archive. A companion program, \fIzip\fP(1L), creates ZIP +archives; both programs are compatible with archives created by PKWARE's +\fIPKZIP\fP and \fIPKUNZIP\fP for MS-DOS, but in many cases the program +options or default behaviors differ. +.PD +.\" ========================================================================= +.SH ARGUMENTS +.TP +.IR file [ .zip ] +Path of the ZIP archive(s). If the file specification is a wildcard, +each matching file is processed in an order determined by the operating +system (or file system). Only the filename can be a wildcard; the path +itself cannot. Wildcard expressions are similar to those supported in +commonly used Unix shells (\fIsh\fP, \fIksh\fP, \fIcsh\fP) and may contain: +.RS +.IP * +matches a sequence of 0 or more characters +.IP ? +matches exactly 1 character +.IP [.\|.\|.] +matches any single character found inside the brackets; ranges are specified +by a beginning character, a hyphen, and an ending character. If an exclamation +point or a caret (`!' or `^') follows the left bracket, then the range of +characters within the brackets is complemented (that is, anything \fIexcept\fP +the characters inside the brackets is considered a match). To specify a +verbatim left bracket, the three-character sequence ``[[]'' has to be used. +.RE +.IP +(Be sure to quote any character that might otherwise be interpreted or +modified by the operating system, particularly under Unix and VMS.) If no +matches are found, the specification is assumed to be a literal filename; +and if that also fails, the suffix \fC.zip\fR is appended. Note that +self-extracting ZIP files are supported, as with any other ZIP archive; +just specify the \fC.exe\fR suffix (if any) explicitly. +.IP [\fIfile(s)\fP] +An optional list of archive members to be processed, separated by spaces. +(VMS versions compiled with VMSCLI defined must delimit files with commas +instead. See \fB\-v\fP in \fBOPTIONS\fP below.) +Regular expressions (wildcards) may be used to match multiple members; see +above. Again, be sure to quote expressions that would otherwise be expanded +or modified by the operating system. +.IP [\fB\-x\fP\ \fIxfile(s)\fP] +An optional list of archive members to be excluded from processing. +Since wildcard characters normally match (`/') directory separators +(for exceptions see the option \fB\-W\fP), this option may be used +to exclude any files that are in subdirectories. For +example, ``\fCunzip foo *.[ch] -x */*\fR'' would extract all C source files +in the main directory, but none in any subdirectories. Without the \fB\-x\fP +option, all C source files in all directories within the zipfile would be +extracted. +.IP [\fB\-d\fP\ \fIexdir\fP] +An optional directory to which to extract files. By default, all files +and subdirectories are recreated in the current directory; the \fB\-d\fP +option allows extraction in an arbitrary directory (always assuming one +has permission to write to the directory). This option need not appear +at the end of the command line; it is also accepted before the zipfile +specification (with the normal options), immediately after the zipfile +specification, or between the \fIfile(s)\fP and the \fB\-x\fP option. +The option and directory may be concatenated without any white space +between them, but note that this may cause normal shell behavior to be +suppressed. In particular, ``\fC\-d\ ~\fR'' (tilde) is expanded by Unix +C shells into the name of the user's home directory, but ``\fC\-d~\fR'' +is treated as a literal subdirectory ``\fB~\fP'' of the current directory. +.\" ========================================================================= +.SH OPTIONS +Note that, in order to support obsolescent hardware, \fIunzip\fP's usage +screen is limited to 22 or 23 lines and should therefore be considered +only a reminder of the basic \fIunzip\fP syntax rather than an exhaustive +list of all possible flags. The exhaustive list follows: +.TP +.B \-Z +\fIzipinfo\fP(1L) mode. If the first option on the command line is \fB\-Z\fP, +the remaining options are taken to be \fIzipinfo\fP(1L) options. See the +appropriate manual page for a description of these options. +.TP +.B \-A +[OS/2, Unix DLL] print extended help for the DLL's programming interface (API). +.TP +.B \-c +extract files to stdout/screen (``CRT''). This option is similar to the +\fB\-p\fP option except that the name of each file is printed as it is +extracted, the \fB\-a\fP option is allowed, and ASCII-EBCDIC conversion +is automatically performed if appropriate. This option is not listed in +the \fIunzip\fP usage screen. +.TP +.B \-f +freshen existing files, i.e., extract only those files that +already exist on disk and that are newer than the disk copies. By +default \fIunzip\fP queries before overwriting, but the \fB\-o\fP option +may be used to suppress the queries. Note that under many operating systems, +the TZ (timezone) environment variable must be set correctly in order for +\fB\-f\fP and \fB\-u\fP to work properly (under Unix the variable is usually +set automatically). The reasons for this are somewhat subtle but +have to do with the differences between DOS-format file times (always local +time) and Unix-format times (always in GMT/UTC) and the necessity to compare +the two. A typical TZ value is ``PST8PDT'' (US Pacific time with automatic +adjustment for Daylight Savings Time or ``summer time''). +.TP +.B \-l +list archive files (short format). The names, uncompressed file sizes and +modification dates and times of the specified files are printed, along +with totals for all files specified. If UnZip was compiled with OS2_EAS +defined, the \fB\-l\fP option also lists columns for the sizes of stored +OS/2 extended attributes (EAs) and OS/2 access control lists (ACLs). In +addition, the zipfile comment and individual file comments (if any) are +displayed. If a file was archived from a single-case file system (for +example, the old MS-DOS FAT file system) and the \fB\-L\fP option was given, +the filename is converted to lowercase and is prefixed with a caret (^). +.TP +.B \-p +extract files to pipe (stdout). Nothing but the file data is sent to +stdout, and the files are always extracted in binary format, just as they +are stored (no conversions). +.TP +.B \-t +test archive files. This option extracts each specified file in memory +and compares the CRC (cyclic redundancy check, an enhanced checksum) of +the expanded file with the original file's stored CRC value. +.TP +.B \-T +[most OSes] set the timestamp on the archive(s) to that of the newest file +in each one. This corresponds to \fIzip\fP's \fB\-go\fP option except that +it can be used on wildcard zipfiles (e.g., ``\fCunzip \-T \e*.zip\fR'') and +is much faster. +.TP +.B \-u +update existing files and create new ones if needed. This option performs +the same function as the \fB\-f\fP option, extracting (with query) files +that are newer than those with the same name on disk, and in addition it +extracts those files that do not already exist on disk. See \fB\-f\fP +above for information on setting the timezone properly. +.TP +.B \-v +list archive files (verbose format) or show diagnostic version info. +This option has evolved and now behaves as both an option and a modifier. +As an option it has two purposes: when a zipfile is specified with no +other options, \fB\-v\fP lists archive files verbosely, adding to the +basic \fB\-l\fP info the compression method, compressed size, +compression ratio and 32-bit CRC. In contrast to most of the competing +utilities, \fIunzip\fP removes the 12 additional header bytes of +encrypted entries from the compressed size numbers. Therefore, +compressed size and compression ratio figures are independent of the entry's +encryption status and show the correct compression performance. (The complete +size of the encrypted compressed data stream for zipfile entries is reported +by the more verbose \fIzipinfo\fP(1L) reports, see the separate manual.) +When no zipfile is specified (that is, the complete command is simply +``\fCunzip \-v\fR''), a diagnostic screen is printed. In addition to +the normal header with release date and version, \fIunzip\fP lists the +home Info-ZIP ftp site and where to find a list of other ftp and non-ftp +sites; the target operating system for which it was compiled, as well +as (possibly) the hardware on which it was compiled, the compiler and +version used, and the compilation date; any special compilation options +that might affect the program's operation (see also \fBDECRYPTION\fP below); +and any options stored in environment variables that might do the same +(see \fBENVIRONMENT OPTIONS\fP below). As a modifier it works in +conjunction with other options (e.g., \fB\-t\fP) to produce more +verbose or debugging output; this is not yet fully implemented +but will be in future releases. +.TP +.B \-z +display only the archive comment. +.PD +.\" ========================================================================= +.SH MODIFIERS +.TP +.B \-a +convert text files. Ordinarily all files are extracted exactly as they +are stored (as ``binary'' files). The \fB\-a\fP option causes files identified +by \fIzip\fP as text files (those with the `t' label in \fIzipinfo\fP +listings, rather than `b') to be automatically extracted as such, converting +line endings, end-of-file characters and the character set itself as necessary. +(For example, Unix files use line feeds (LFs) for end-of-line (EOL) and +have no end-of-file (EOF) marker; Macintoshes use carriage returns (CRs) +for EOLs; and most PC operating systems use CR+LF for EOLs and control-Z for +EOF. In addition, IBM mainframes and the Michigan Terminal System use EBCDIC +rather than the more common ASCII character set, and NT supports Unicode.) +Note that \fIzip\fP's identification of text files is by no means perfect; some +``text'' files may actually be binary and vice versa. \fIunzip\fP therefore +prints ``\fC[text]\fR'' or ``\fC[binary]\fR'' as a visual check for each file +it extracts when using the \fB\-a\fP option. The \fB\-aa\fP option forces +all files to be extracted as text, regardless of the supposed file type. +On VMS, see also \fB\-S\fP. +.TP +.B \-b +[general] treat all files as binary (no text conversions). This is a shortcut +for \fB\-\-\-a\fP. +.TP +.B \-b +[Tandem] force the creation files with filecode type 180 ('C') when +extracting Zip entries marked as "text". (On Tandem, \fB\-a\fP is enabled +by default, see above). +.TP +.B \-b +[VMS] auto-convert binary files (see \fB\-a\fP above) to fixed-length, +512-byte record format. Doubling the option (\fB\-bb\fP) forces all files +to be extracted in this format. When extracting to standard output +(\fB\-c\fP or \fB\-p\fP option in effect), the default conversion of text +record delimiters is disabled for binary (\fB\-b\fP) resp. all (\fB\-bb\fP) +files. +.TP +.B \-B +[when compiled with UNIXBACKUP defined] save a backup copy of each +overwritten file. The backup file is gets the name of the target file with +a tilde and optionally a unique sequence number (up to 5 digits) appended. +The sequence number is applied whenever another file with the original name +plus tilde already exists. When used together with the "overwrite all" +option \fB\-o\fP, numbered backup files are never created. In this case, +all backup files are named as the original file with an appended tilde, +existing backup files are deleted without notice. +This feature works similarly to the default behavior of \fIemacs\fP(1) +in many locations. +.IP +Example: the old copy of ``\fCfoo\fR'' is renamed to ``\fCfoo~\fR''. +.IP +Warning: Users should be aware that the \fB-B\fP option does not prevent +loss of existing data under all circumstances. For example, when +\fIunzip\fP is run in overwrite-all mode, an existing ``\fCfoo~\fR'' file +is deleted before \fIunzip\fP attempts to rename ``\fCfoo\fR'' to +``\fCfoo~\fR''. When this rename attempt fails (because of a file locks, +insufficient privileges, or ...), the extraction of ``\fCfoo~\fR'' gets +cancelled, but the old backup file is already lost. A similar scenario +takes place when the sequence number range for numbered backup files gets +exhausted (99999, or 65535 for 16-bit systems). In this case, the backup +file with the maximum sequence number is deleted and replaced by the new +backup version without notice. +.TP +.B \-C +use case-insensitive matching for the selection of archive entries +from the command-line list of extract selection patterns. +\fIunzip\fP's philosophy is ``you get what you ask for'' (this is +also responsible for the \fB\-L\fP/\fB\-U\fP change; see the relevant +options below). Because some file systems are fully case-sensitive +(notably those under the Unix operating system) and because +both ZIP archives and \fIunzip\fP itself are portable across platforms, +\fIunzip\fP's default behavior is to match both wildcard and literal +filenames case-sensitively. That is, specifying ``\fCmakefile\fR'' +on the command line will \fIonly\fP match ``makefile'' in the archive, +not ``Makefile'' or ``MAKEFILE'' (and similarly for wildcard specifications). +Since this does not correspond to the behavior of many other +operating/file systems (for example, OS/2 HPFS, which preserves +mixed case but is not sensitive to it), the \fB\-C\fP option may be +used to force all filename matches to be case-insensitive. In the +example above, all three files would then match ``\fCmakefile\fR'' +(or ``\fCmake*\fR'', or similar). The \fB\-C\fP option affects +file specs in both the normal file list and the excluded-file list (xlist). +.IP +Please note that the \fB\-C\fP option does neither affect the search for +the zipfile(s) nor the matching of archive entries to existing files on +the extraction path. On a case-sensitive file system, \fIunzip\fP will +never try to overwrite a file ``FOO'' when extracting an entry ``foo''! +.TP +.B \-D +skip restoration of timestamps for extracted items. Normally, \fIunzip\fP +tries to restore all meta-information for extracted items that are supplied +in the Zip archive (and do not require privileges or impose a security risk). +By specifying \fB\-D\fP, \fIunzip\fP is told to suppress restoration of +timestamps for directories explicitly created from Zip archive entries. +This option only applies to ports that support setting timestamps for +directories (currently ATheOS, BeOS, MacOS, OS/2, Unix, VMS, Win32, for other +\fIunzip\fP ports, \fB\-D\fP has no effect). +The duplicated option \fB\-DD\fP forces suppression of timestamp restoration +for all extracted entries (files and directories). This option results in +setting the timestamps for all extracted entries to the current time. +.IP +On VMS, the default setting for this option is \fB\-D\fP for consistency +with the behaviour of BACKUP: file timestamps are restored, timestamps of +extracted directories are left at the current time. To enable restoration +of directory timestamps, the negated option \fB\--D\fP should be specified. +On VMS, the option \fB\-D\fP disables timestamp restoration for all extracted +Zip archive items. (Here, a single \fB\-D\fP on the command line combines +with the default \fB\-D\fP to do what an explicit \fB\-DD\fP does on other +systems.) +.TP +.B \-E +[MacOS only] display contents of MacOS extra field during restore operation. +.TP +.B \-F +[Acorn only] suppress removal of NFS filetype extension from stored filenames. +.TP +.B \-F +[non-Acorn systems supporting long filenames with embedded commas, +and only if compiled with ACORN_FTYPE_NFS defined] translate +filetype information from ACORN RISC OS extra field blocks into a +NFS filetype extension and append it to the names of the extracted files. +(When the stored filename appears to already have an appended NFS filetype +extension, it is replaced by the info from the extra field.) +.TP +.B \-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. +.TP +.B \-j +junk paths. The archive's directory structure is not recreated; all files +are deposited in the extraction directory (by default, the current one). +.TP +.B \-J +[BeOS only] junk file attributes. The file's BeOS file attributes are not +restored, just the file's data. +.TP +.B \-J +[MacOS only] ignore MacOS extra fields. All Macintosh specific info +is skipped. Data-fork and resource-fork are restored as separate files. +.TP +.B \-K +[AtheOS, BeOS, Unix only] retain SUID/SGID/Tacky file attributes. Without +this flag, these attribute bits are cleared for security reasons. +.TP +.B \-L +convert to lowercase any filename originating on an uppercase-only operating +system or file system. (This was \fIunzip\fP's default behavior in releases +prior to 5.11; the new default behavior is identical to the old behavior with +the \fB\-U\fP option, which is now obsolete and will be removed in a future +release.) Depending on the archiver, files archived under single-case +file systems (VMS, old MS-DOS FAT, etc.) may be stored as all-uppercase names; +this can be ugly or inconvenient when extracting to a case-preserving +file system such as OS/2 HPFS or a case-sensitive one such as under +Unix. By default \fIunzip\fP lists and extracts such filenames exactly as +they're stored (excepting truncation, conversion of unsupported characters, +etc.); this option causes the names of all files from certain systems to be +converted to lowercase. The \fB\-LL\fP option forces conversion of every +filename to lowercase, regardless of the originating file system. +.TP +.B \-M +pipe all output through an internal pager similar to the Unix \fImore\fP(1) +command. At the end of a screenful of output, \fIunzip\fP pauses with a +``\-\-More\-\-'' prompt; the next screenful may be viewed by pressing the +Enter (Return) key or the space bar. \fIunzip\fP can be terminated by +pressing the ``q'' key and, on some systems, the Enter/Return key. Unlike +Unix \fImore\fP(1), there is no forward-searching or editing capability. +Also, \fIunzip\fP doesn't notice if long lines wrap at the edge of the screen, +effectively resulting in the printing of two or more lines and the likelihood +that some text will scroll off the top of the screen before being viewed. +On some systems the number of available lines on the screen is not detected, +in which case \fIunzip\fP assumes the height is 24 lines. +.TP +.B \-n +never overwrite existing files. If a file already exists, skip the extraction +of that file without prompting. By default \fIunzip\fP queries before +extracting any file that already exists; the user may choose to overwrite +only the current file, overwrite all files, skip extraction of the current +file, skip extraction of all existing files, or rename the current file. +.TP +.B \-N +[Amiga] extract file comments as Amiga filenotes. File comments are created +with the \-c option of \fIzip\fP(1L), or with the \-N option of the Amiga port +of \fIzip\fP(1L), which stores filenotes as comments. +.TP +.B \-o +overwrite existing files without prompting. This is a dangerous option, so +use it with care. (It is often used with \fB\-f\fP, however, and is the only +way to overwrite directory EAs under OS/2.) +.IP \fB\-P\fP\ \fIpassword\fP +use \fIpassword\fP to decrypt encrypted zipfile entries (if any). \fBTHIS IS +INSECURE!\fP Many multi-user operating systems provide ways for any user to +see the current command line of any other user; even on stand-alone systems +there is always the threat of over-the-shoulder peeking. Storing the plaintext +password as part of a command line in an automated script is even worse. +Whenever possible, use the non-echoing, interactive prompt to enter passwords. +(And where security is truly important, use strong encryption such as Pretty +Good Privacy instead of the relatively weak encryption provided by standard +zipfile utilities.) +.TP +.B \-q +perform operations quietly (\fB\-qq\fP = even quieter). Ordinarily \fIunzip\fP +prints the names of the files it's extracting or testing, the extraction +methods, any file or zipfile comments that may be stored in the archive, +and possibly a summary when finished with each archive. The \fB\-q\fP[\fBq\fP] +options suppress the printing of some or all of these messages. +.TP +.B \-s +[OS/2, NT, MS-DOS] convert spaces in filenames to underscores. Since all PC +operating systems allow spaces in filenames, \fIunzip\fP by default extracts +filenames with spaces intact (e.g., ``\fCEA\ DATA.\ SF\fR''). This can be +awkward, however, since MS-DOS in particular does not gracefully support +spaces in filenames. Conversion of spaces to underscores can eliminate the +awkwardness in some cases. +.TP +.B \-S +[VMS] convert text files (\fB\-a\fP, \fB\-aa\fP) into Stream_LF record format, +instead of the text-file default, variable-length record format. +(Stream_LF is the default record format of VMS \fIunzip\fP. It is applied +unless conversion (\fB\-a\fP, \fB\-aa\fP and/or \fB\-b\fP, \fB\-bb\fP) is +requested or a VMS-specific entry is processed.) +.TP +.B \-U +[UNICODE_SUPPORT only] modify or disable UTF-8 handling. +When UNICODE_SUPPORT is available, the option \fB\-U\fP forces \fIunzip\fP +to escape all non-ASCII characters from UTF-8 coded filenames as ``#Uxxxx'' +(for UCS-2 characters, or ``#Lxxxxxx'' for unicode codepoints needing 3 +octets). This option is mainly provided for debugging purpose when the +fairly new UTF-8 support is suspected to mangle up extracted filenames. +.IP +The option \fB\-UU\fP allows to entirely disable the recognition of UTF-8 +encoded filenames. The handling of filename codings within \fIunzip\fP falls +back to the behaviour of previous versions. +.IP +[old, obsolete usage] leave filenames uppercase if +created under MS-DOS, VMS, etc. See \fB\-L\fP above. +.TP +.B \-V +retain (VMS) file version numbers. VMS files can be stored with a version +number, in the format \fCfile.ext;##\fR. By default the ``\fC;##\fR'' version +numbers are stripped, but this option allows them to be retained. (On +file systems that limit filenames to particularly short lengths, the version +numbers may be truncated or stripped regardless of this option.) +.TP +.B \-W +[only when WILD_STOP_AT_DIR compile-time option enabled] +modifies the pattern matching routine so that both `?' (single-char wildcard) +and `*' (multi-char wildcard) do not match the directory separator character +`/'. (The two-character sequence ``**'' acts as a multi-char wildcard that +includes the directory separator in its matched characters.) Examples: +.PP +.EX + "*.c" matches "foo.c" but not "mydir/foo.c" + "**.c" matches both "foo.c" and "mydir/foo.c" + "*/*.c" matches "bar/foo.c" but not "baz/bar/foo.c" + "??*/*" matches "ab/foo" and "abc/foo" + but not "a/foo" or "a/b/foo" +.EE +.IP +This modified behaviour is equivalent to the pattern matching style +used by the shells of some of UnZip's supported target OSs (one +example is Acorn RISC OS). This option may not be available on systems +where the Zip archive's internal directory separator character `/' is +allowed as regular character in native operating system filenames. +(Currently, UnZip uses the same pattern matching rules for both wildcard +zipfile specifications and zip entry selection patterns in most ports. +For systems allowing `/' as regular filename character, the -W option +would not work as expected on a wildcard zipfile specification.) +.TP +.B \-X +[VMS, Unix, OS/2, NT, Tandem] restore owner/protection info (UICs and ACL +entries) under VMS, or user and group info (UID/GID) under Unix, or access +control lists (ACLs) under certain network-enabled versions of OS/2 +(Warp Server with IBM LAN Server/Requester 3.0 to 5.0; Warp Connect with +IBM Peer 1.0), or security ACLs under Windows NT. In most cases this will +require special system privileges, and doubling the option (\fB\-XX\fP) +under NT instructs \fIunzip\fP to use privileges for extraction; but under +Unix, for example, a user who belongs to several groups can restore files +owned by any of those groups, as long as the user IDs match his or her own. +Note that ordinary file attributes are always restored--this option applies +only to optional, extra ownership info available on some operating systems. +[NT's access control lists do not appear to be especially compatible with +OS/2's, so no attempt is made at cross-platform portability of access +privileges. It is not clear under what conditions this would ever be +useful anyway.] +.TP +.B \-Y +[VMS] treat archived file name endings of ``.nnn'' (where ``nnn'' is a +decimal number) as if they were VMS version numbers (``;nnn''). +(The default is to treat them as file types.) Example: +.EX + "a.b.3" -> "a.b;3". +.EE +.TP +.B \-$ +.\" Amiga support possible eventually, but not yet +[MS-DOS, OS/2, NT] restore the volume label if the extraction medium is +removable (e.g., a diskette). Doubling the option (\fB\-$$\fP) allows fixed +media (hard disks) to be labelled as well. By default, volume labels are +ignored. +.IP \fB\-/\fP\ \fIextensions\fP +[Acorn only] overrides the extension list supplied by Unzip$Ext environment +variable. During extraction, filename extensions that match one of the items +in this extension list are swapped in front of the base name of the extracted +file. +.TP +.B \-: +[all but Acorn, VM/CMS, MVS, Tandem] allows to extract archive members into +locations outside of the current `` extraction root folder''. For security +reasons, \fIunzip\fP normally removes ``parent dir'' path components +(``../'') from the names of extracted file. This safety feature (new for +version 5.50) prevents \fIunzip\fP from accidentally writing files to +``sensitive'' areas outside the active extraction folder tree head. The +\fB\-:\fP option lets \fIunzip\fP switch back to its previous, more liberal +behaviour, to allow exact extraction of (older) archives that used ``../'' +components to create multiple directory trees at the level of the current +extraction folder. This option does not enable writing explicitly to the +root directory (``/''). To achieve this, it is necessary to set the +extraction target folder to root (e.g. \fB\-d / \fP). However, when the +\fB\-:\fP option is specified, it is still possible to implicitly write to +the root directory by specifying enough ``../'' path components within the +zip archive. +Use this option with extreme caution. +.TP +.B \-^ +[Unix only] allow control characters in names of extracted ZIP archive +entries. On Unix, a file name may contain any (8-bit) character code with +the two exception '/' (directory delimiter) and NUL (0x00, the C string +termination indicator), unless the specific file system has more +restrictive conventions. Generally, this allows to embed ASCII control +characters (or even sophisticated control sequences) in file names, at least +on 'native' Unix file systems. However, it may be highly suspicious to +make use of this Unix "feature". Embedded control characters in file names +might have nasty side effects when displayed on screen by some listing code +without sufficient filtering. And, for ordinary users, it may be difficult +to handle such file names (e.g. when trying to specify it for open, copy, +move, or delete operations). Therefore, \fIunzip\fP applies a filter by +default that removes potentially dangerous control characters from the +extracted file names. The \fB-^\fP option allows to override this filter +in the rare case that embedded filename control characters are to be +intentionally restored. +.TP +.B \-2 +[VMS] force unconditionally conversion of file names to ODS2-compatible +names. The default is to exploit the destination file system, preserving +case and extended file name characters on an ODS5 destination file system; +and applying the ODS2-compatibility file name filtering on an ODS2 destination +file system. +.PD +.\" ========================================================================= +.SH "ENVIRONMENT OPTIONS" +\fIunzip\fP's default behavior may be modified via options placed in +an environment variable. This can be done with any option, but it +is probably most useful with the \fB\-a\fP, \fB\-L\fP, \fB\-C\fP, \fB\-q\fP, +\fB\-o\fP, or \fB\-n\fP modifiers: make \fIunzip\fP auto-convert text +files by default, make it convert filenames from uppercase systems to +lowercase, make it match names case-insensitively, make it quieter, +or make it always overwrite or never overwrite files as it extracts +them. For example, to make \fIunzip\fP act as quietly as possible, only +reporting errors, one would use one of the following commands: +.TP + Unix Bourne shell: +UNZIP=\-qq; export UNZIP +.TP + Unix C shell: +setenv UNZIP \-qq +.TP + OS/2 or MS-DOS: +set UNZIP=\-qq +.TP + VMS (quotes for \fIlowercase\fP): +define UNZIP_OPTS "\-qq" +.PP +Environment options are, in effect, considered to be just like any other +command-line options, except that they are effectively the first options +on the command line. To override an environment option, one may use the +``minus operator'' to remove it. For instance, to override one of the +quiet-flags in the example above, use the command +.PP +.EX +unzip \-\-q[\fIother options\fP] zipfile +.EE +.PP +The first hyphen is the normal +switch character, and the second is a minus sign, acting on the q option. +Thus the effect here is to cancel one quantum of quietness. To cancel +both quiet flags, two (or more) minuses may be used: +.PP +.EX +unzip \-t\-\-q zipfile +unzip \-\-\-qt zipfile +.EE +.PP +(the two are equivalent). This may seem awkward +or confusing, but it is reasonably intuitive: just ignore the first +hyphen and go from there. It is also consistent with the behavior of +Unix \fInice\fP(1). +.PP +As suggested by the examples above, the default variable names are UNZIP_OPTS +for VMS (where the symbol used to install \fIunzip\fP as a foreign command +would otherwise be confused with the environment variable), and UNZIP +for all other operating systems. For compatibility with \fIzip\fP(1L), +UNZIPOPT is also accepted (don't ask). If both UNZIP and UNZIPOPT +are defined, however, UNZIP takes precedence. \fIunzip\fP's diagnostic +option (\fB\-v\fP with no zipfile name) can be used to check the values +of all four possible \fIunzip\fP and \fIzipinfo\fP environment variables. +.PP +The timezone variable (TZ) should be set according to the local timezone +in order for the \fB\-f\fP and \fB\-u\fP to operate correctly. See the +description of \fB\-f\fP above for details. This variable may also be +necessary to get timestamps of extracted files to be set correctly. +The WIN32 (Win9x/ME/NT4/2K/XP/2K3) port of \fIunzip\fP gets the timezone +configuration from the registry, assuming it is correctly set in the +Control Panel. The TZ variable is ignored for this port. +.PD +.\" ========================================================================= +.SH DECRYPTION +Encrypted archives are fully supported by Info-ZIP software, but due to +United States export restrictions, de-/encryption support might be disabled +in your compiled binary. However, since spring 2000, US export restrictions +have been liberated, and our source archives do now include full crypt code. +In case you need binary distributions with crypt support enabled, see the +file ``WHERE'' in any Info-ZIP source or binary distribution for locations +both inside and outside the US. +.PP +Some compiled versions of \fIunzip\fP may not support decryption. +To check a version for crypt support, either attempt to test or extract +an encrypted archive, or else check \fIunzip\fP's diagnostic +screen (see the \fB\-v\fP option above) for ``\fC[decryption]\fR'' as one +of the special compilation options. +.PP +As noted above, the \fB\-P\fP option may be used to supply a password on +the command line, but at a cost in security. The preferred decryption +method is simply to extract normally; if a zipfile member is encrypted, +\fIunzip\fP will prompt for the password without echoing what is typed. +\fIunzip\fP continues to use the same password as long as it appears to be +valid, by testing a 12-byte header on each file. The correct password will +always check out against the header, but there is a 1-in-256 chance that an +incorrect password will as well. (This is a security feature of the PKWARE +zipfile format; it helps prevent brute-force attacks that might otherwise +gain a large speed advantage by testing only the header.) In the case that +an incorrect password is given but it passes the header test anyway, either +an incorrect CRC will be generated for the extracted data or else \fIunzip\fP +will fail during the extraction because the ``decrypted'' bytes do not +constitute a valid compressed data stream. +.PP +If the first password fails the header check on some file, \fIunzip\fP will +prompt for another password, and so on until all files are extracted. If +a password is not known, entering a null password (that is, just a carriage +return or ``Enter'') is taken as a signal to skip all further prompting. +Only unencrypted files in the archive(s) will thereafter be extracted. (In +fact, that's not quite true; older versions of \fIzip\fP(1L) and +\fIzipcloak\fP(1L) allowed null passwords, so \fIunzip\fP checks each encrypted +file to see if the null password works. This may result in ``false positives'' +and extraction errors, as noted above.) +.PP +Archives encrypted with 8-bit passwords (for example, passwords with accented +European characters) may not be portable across systems and/or other +archivers. This problem stems from the use of multiple encoding methods for +such characters, including Latin-1 (ISO 8859-1) and OEM code page 850. +DOS \fIPKZIP\fP 2.04g uses the OEM code page; Windows \fIPKZIP\fP 2.50 +uses Latin-1 (and is therefore incompatible with DOS \fIPKZIP\fP); Info-ZIP +uses the OEM code page on DOS, OS/2 and Win3.x ports but ISO coding +(Latin-1 etc.) everywhere else; and Nico Mak's \fIWinZip\fP 6.x does not +allow 8-bit passwords at all. \fIUnZip\fP 5.3 (or newer) attempts to use +the default character set first (e.g., Latin-1), followed by the alternate +one (e.g., OEM code page) to test passwords. On EBCDIC systems, if both +of these fail, EBCDIC encoding will be tested as a last resort. (EBCDIC is +not tested on non-EBCDIC systems, because there are no known archivers +that encrypt using EBCDIC encoding.) ISO character encodings other than +Latin-1 are not supported. The new addition of (partially) Unicode (resp. +UTF-8) support in \fIUnZip\fP 6.0 has not yet been adapted to the encryption +password handling in \fIunzip\fP. On systems that use UTF-8 as native +character encoding, \fIunzip\fP simply tries decryption with the native +UTF-8 encoded password; the built-in attempts to check the password in +translated encoding have not yet been adapted for UTF-8 support and +will consequently fail. +.PD +.\" ========================================================================= +.SH EXAMPLES +To use \fIunzip\fP to extract all members of the archive \fIletters.zip\fP +into the current directory and subdirectories below it, creating any +subdirectories as necessary: +.PP +.EX +unzip letters +.EE +.PP +To extract all members of \fIletters.zip\fP into the current directory only: +.PP +.EX +unzip -j letters +.EE +.PP +To test \fIletters.zip\fP, printing only a summary message indicating +whether the archive is OK or not: +.PP +.EX +unzip -tq letters +.EE +.PP +To test \fIall\fP zipfiles in the current directory, printing only the +summaries: +.PP +.EX +unzip -tq \e*.zip +.EE +.PP +(The backslash before the asterisk is only required if the shell expands +wildcards, as in Unix; double quotes could have been used instead, as in +the source examples below.)\ \ To extract to standard output all members of +\fIletters.zip\fP whose names end in \fI.tex\fP, auto-converting to the +local end-of-line convention and piping the output into \fImore\fP(1): +.PP +.EX +unzip \-ca letters \e*.tex | more +.EE +.PP +To extract the binary file \fIpaper1.dvi\fP to standard output and pipe it +to a printing program: +.PP +.EX +unzip \-p articles paper1.dvi | dvips +.EE +.PP +To extract all FORTRAN and C source files--*.f, *.c, *.h, and Makefile--into +the /tmp directory: +.PP +.EX +unzip source.zip "*.[fch]" Makefile -d /tmp +.EE +.PP +(the double quotes are necessary only in Unix and only if globbing is turned +on). To extract all FORTRAN and C source files, regardless of case (e.g., +both *.c and *.C, and any makefile, Makefile, MAKEFILE or similar): +.PP +.EX +unzip \-C source.zip "*.[fch]" makefile -d /tmp +.EE +.PP +To extract any such files but convert any uppercase MS-DOS or VMS names to +lowercase and convert the line-endings of all of the files to the local +standard (without respect to any files that might be marked ``binary''): +.PP +.EX +unzip \-aaCL source.zip "*.[fch]" makefile -d /tmp +.EE +.PP +To extract only newer versions of the files already in the current +directory, without querying (NOTE: be careful of unzipping in one timezone a +zipfile created in another--ZIP archives other than those created by Zip 2.1 +or later contain no timezone information, and a ``newer'' file from an eastern +timezone may, in fact, be older): +.PP +.EX +unzip \-fo sources +.EE +.PP +To extract newer versions of the files already in the current directory and +to create any files not already there (same caveat as previous example): +.PP +.EX +unzip \-uo sources +.EE +.PP +To display a diagnostic screen showing which \fIunzip\fP and \fIzipinfo\fP +options are stored in environment variables, whether decryption support was +compiled in, the compiler with which \fIunzip\fP was compiled, etc.: +.PP +.EX +unzip \-v +.EE +.PP +In the last five examples, assume that UNZIP or UNZIP_OPTS is set to -q. +To do a singly quiet listing: +.PP +.EX +unzip \-l file.zip +.EE +.PP +To do a doubly quiet listing: +.PP +.EX +unzip \-ql file.zip +.EE +.PP +(Note that the ``\fC.zip\fR'' is generally not necessary.) To do a standard +listing: +.PP +.EX +unzip \-\-ql file.zip +.EE +or +.EX +unzip \-l\-q file.zip +.EE +or +.EX +unzip \-l\-\-q file.zip +.EE +\fR(Extra minuses in options don't hurt.) +.PD +.\" ========================================================================= +.SH TIPS +The current maintainer, being a lazy sort, finds it very useful to define +a pair of aliases: \fCtt\fR for ``\fCunzip \-tq\fR'' and \fCii\fR for +``\fCunzip \-Z\fR'' (or ``\fCzipinfo\fR''). One may then simply type +``\fCtt zipfile\fR'' to test an archive, something that is worth making a +habit of doing. With luck \fIunzip\fP will report ``\fCNo errors detected +in compressed data of zipfile.zip\fR,'' after which one may breathe a sigh +of relief. +.PP +The maintainer also finds it useful to set the UNZIP environment variable +to ``\fC\-aL\fR'' and is tempted to add ``\fC\-C\fR'' as well. His ZIPINFO +variable is set to ``\fC\-z\fR''. +.PD +.\" ========================================================================= +.SH DIAGNOSTICS +The exit status (or error level) approximates the exit codes defined by PKWARE +and takes on the following values, except under VMS: +.RS +.IP 0 +normal; no errors or warnings detected. +.IP 1 +one or more warning errors were encountered, but processing completed +successfully anyway. This includes zipfiles where one or more files +was skipped due to unsupported compression method or encryption with an +unknown password. +.IP 2 +a generic error in the zipfile format was detected. Processing may have +completed successfully anyway; some broken zipfiles created by other +archivers have simple work-arounds. +.IP 3 +a severe error in the zipfile format was detected. Processing probably +failed immediately. +.IP 4 +\fIunzip\fP was unable to allocate memory for one or more buffers during +program initialization. +.IP 5 +\fIunzip\fP was unable to allocate memory or unable to obtain a tty to read +the decryption password(s). +.IP 6 +\fIunzip\fP was unable to allocate memory during decompression to disk. +.IP 7 +\fIunzip\fP was unable to allocate memory during in-memory decompression. +.IP 8 +[currently not used] +.IP 9 +the specified zipfiles were not found. +.IP 10 +invalid options were specified on the command line. +.IP 11 +no matching files were found. +.IP 50 +the disk is (or was) full during extraction. +.IP 51 +the end of the ZIP archive was encountered prematurely. +.IP 80 +the user aborted \fIunzip\fP prematurely with control-C (or similar) +.IP 81 +testing or extraction of one or more files failed due to unsupported +compression methods or unsupported decryption. +.IP 82 +no files were found due to bad decryption password(s). (If even one file is +successfully processed, however, the exit status is 1.) +.RE +.PP +VMS interprets standard Unix (or PC) return values as other, scarier-looking +things, so \fIunzip\fP instead maps them into VMS-style status codes. The +current mapping is as follows: 1 (success) for normal exit, 0x7fff0001 +for warning errors, and (0x7fff000? + 16*normal_unzip_exit_status) for all +other errors, where the `?' is 2 (error) for \fIunzip\fP values 2, 9-11 and +80-82, and 4 (fatal error) for the remaining ones (3-8, 50, 51). In addition, +there is a compilation option to expand upon this behavior: defining +RETURN_CODES results in a human-readable explanation of what the error +status means. +.PD +.\" ========================================================================= +.SH BUGS +Multi-part archives are not yet supported, except in conjunction with +\fIzip\fP. (All parts must be concatenated together in order, and then +``\fCzip \-F\fR'' (for \fIzip 2.x\fP) or ``\fCzip \-FF\fR'' (for +\fIzip 3.x\fP) must be performed on the concatenated archive in order to +``fix'' it. Also, \fIzip 3.0\fP and later can combine multi-part (split) +archives into a combined single-file archive using ``\fCzip \-s\- inarchive +-O outarchive\fR''. See the \fIzip 3\fP manual page for more information.) +This will definitely be corrected in the next major release. +.PP +Archives read from standard input are not yet supported, except with +\fIfunzip\fP (and then only the first member of the archive can be extracted). +.PP +Archives encrypted with 8-bit passwords (e.g., passwords with accented +European characters) may not be portable across systems and/or other +archivers. See the discussion in \fBDECRYPTION\fP above. +.PP +\fIunzip\fP's \fB\-M\fP (``more'') option tries to take into account automatic +wrapping of long lines. However, the code may fail to detect the correct +wrapping locations. First, TAB characters (and similar control sequences) are +not taken into account, they are handled as ordinary printable characters. +Second, depending on the actual system / OS port, \fIunzip\fP may not detect +the true screen geometry but rather rely on "commonly used" default dimensions. +The correct handling of tabs would require the implementation of a query for +the actual tabulator setup on the output console. +.PP +Dates, times and permissions of stored directories are not restored except +under Unix. (On Windows NT and successors, timestamps are now restored.) +.PP +[MS-DOS] When extracting or testing files from an archive on a defective +floppy diskette, if the ``Fail'' option is chosen from DOS's ``Abort, Retry, +Fail?'' message, older versions of \fIunzip\fP may hang the system, requiring +a reboot. This problem appears to be fixed, but control-C (or control-Break) +can still be used to terminate \fIunzip\fP. +.PP +Under DEC Ultrix, \fIunzip\fP would sometimes fail on long zipfiles (bad CRC, +not always reproducible). This was apparently due either to a hardware bug +(cache memory) or an operating system bug (improper handling of page faults?). +Since Ultrix has been abandoned in favor of Digital Unix (OSF/1), this may not +be an issue anymore. +.PP +[Unix] Unix special files such as FIFO buffers (named pipes), block devices +and character devices are not restored even if they are somehow represented +in the zipfile, nor are hard-linked files relinked. Basically the only file +types restored by \fIunzip\fP are regular files, directories and symbolic +(soft) links. +.PP +[OS/2] Extended attributes for existing directories are only updated if the +\fB\-o\fP (``overwrite all'') option is given. This is a limitation of the +operating system; because directories only have a creation time associated +with them, \fIunzip\fP has no way to determine whether the stored attributes +are newer or older than those on disk. In practice this may mean a two-pass +approach is required: first unpack the archive normally (with or without +freshening/updating existing files), then overwrite just the directory entries +(e.g., ``\fCunzip -o foo */\fR''). +.PP +[VMS] When extracting to another directory, only the \fI[.foo]\fP syntax is +accepted for the \fB\-d\fP option; the simple Unix \fIfoo\fP syntax is +silently ignored (as is the less common VMS \fIfoo.dir\fP syntax). +.PP +[VMS] When the file being extracted already exists, \fIunzip\fP's query only +allows skipping, overwriting or renaming; there should additionally be a +choice for creating a new version of the file. In fact, the ``overwrite'' +choice does create a new version; the old version is not overwritten or +deleted. +.PD +.\" ========================================================================= +.SH "SEE ALSO" +\fIfunzip\fP(1L), \fIzip\fP(1L), \fIzipcloak\fP(1L), \fIzipgrep\fP(1L), +\fIzipinfo\fP(1L), \fIzipnote\fP(1L), \fIzipsplit\fP(1L) +.PD +.\" ========================================================================= +.SH URL +The Info-ZIP home page is currently at +.EX +\fChttp://www.info-zip.org/pub/infozip/\fR +.EE +or +.EX +\fCftp://ftp.info-zip.org/pub/infozip/\fR . +.EE +.PD +.\" ========================================================================= +.SH AUTHORS +The primary Info-ZIP authors (current semi-active members of the Zip-Bugs +workgroup) are: Ed Gordon (Zip, general maintenance, shared code, Zip64, +Win32, Unix, Unicode); Christian Spieler (UnZip maintenance coordination, +VMS, MS-DOS, Win32, shared code, general Zip and UnZip integration and +optimization); Onno van der Linden (Zip); Mike White (Win32, Windows GUI, +Windows DLLs); Kai Uwe Rommel (OS/2, Win32); Steven M. Schweda (VMS, Unix, +support of new features); Paul Kienitz (Amiga, Win32, Unicode); Chris +Herborth (BeOS, QNX, Atari); Jonathan Hudson (SMS/QDOS); Sergio Monesi +(Acorn RISC OS); Harald Denker (Atari, MVS); John Bush (Solaris, Amiga); +Hunter Goatley (VMS, Info-ZIP Site maintenance); Steve Salisbury (Win32); +Steve Miller (Windows CE GUI), Johnny Lee (MS-DOS, Win32, Zip64); and Dave +Smith (Tandem NSK). +.PP +The following people were former members of the Info-ZIP development group +and provided major contributions to key parts of the current code: +Greg ``Cave Newt'' Roelofs (UnZip, unshrink decompression); +Jean-loup Gailly (deflate compression); +Mark Adler (inflate decompression, fUnZip). +.PP +The author of the original unzip code upon which Info-ZIP's was based +is Samuel H. Smith; Carl Mascott did the first Unix port; and David P. +Kirschbaum organized and led Info-ZIP in its early days with Keith Petersen +hosting the original mailing list at WSMR-SimTel20. The full list of +contributors to UnZip has grown quite large; please refer to the CONTRIBS +file in the UnZip source distribution for a relatively complete version. +.PD +.\" ========================================================================= +.SH VERSIONS +.ta \w'vx.xxnn'u +\w'fall 1989'u+3n +.PD 0 +.IP "v1.2\t15 Mar 89" \w'\t\t'u +Samuel H. Smith +.IP "v2.0\t\ 9 Sep 89" +Samuel H. Smith +.IP "v2.x\tfall 1989" +many Usenet contributors +.IP "v3.0\t\ 1 May 90" +Info-ZIP (DPK, consolidator) +.IP "v3.1\t15 Aug 90" +Info-ZIP (DPK, consolidator) +.IP "v4.0\t\ 1 Dec 90" +Info-ZIP (GRR, maintainer) +.IP "v4.1\t12 May 91" +Info-ZIP +.IP "v4.2\t20 Mar 92" +Info-ZIP (Zip-Bugs subgroup, GRR) +.IP "v5.0\t21 Aug 92" +Info-ZIP (Zip-Bugs subgroup, GRR) +.IP "v5.01\t15 Jan 93" +Info-ZIP (Zip-Bugs subgroup, GRR) +.IP "v5.1\t\ 7 Feb 94" +Info-ZIP (Zip-Bugs subgroup, GRR) +.IP "v5.11\t\ 2 Aug 94" +Info-ZIP (Zip-Bugs subgroup, GRR) +.IP "v5.12\t28 Aug 94" +Info-ZIP (Zip-Bugs subgroup, GRR) +.IP "v5.2\t30 Apr 96" +Info-ZIP (Zip-Bugs subgroup, GRR) +.IP "v5.3\t22 Apr 97" +Info-ZIP (Zip-Bugs subgroup, GRR) +.IP "v5.31\t31 May 97" +Info-ZIP (Zip-Bugs subgroup, GRR) +.IP "v5.32\t\ 3 Nov 97" +Info-ZIP (Zip-Bugs subgroup, GRR) +.IP "v5.4\t28 Nov 98" +Info-ZIP (Zip-Bugs subgroup, SPC) +.IP "v5.41\t16 Apr 00" +Info-ZIP (Zip-Bugs subgroup, SPC) +.IP "v5.42\t14 Jan 01" +Info-ZIP (Zip-Bugs subgroup, SPC) +.IP "v5.5\t17 Feb 02" +Info-ZIP (Zip-Bugs subgroup, SPC) +.IP "v5.51\t22 May 04" +Info-ZIP (Zip-Bugs subgroup, SPC) +.IP "v5.52\t28 Feb 05" +Info-ZIP (Zip-Bugs subgroup, SPC) +.IP "v6.0\t20 Apr 09" +Info-ZIP (Zip-Bugs subgroup, SPC) +.PD diff --git a/man/unzipsfx.1 b/man/unzipsfx.1 new file mode 100644 index 0000000..d9a0e59 --- /dev/null +++ b/man/unzipsfx.1 @@ -0,0 +1,336 @@ +.\" Copyright (c) 1990-2009 Info-ZIP. All rights reserved. +.\" +.\" See the accompanying file LICENSE, version 2009-Jan-02 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 +.\" +.\" unzipsfx.1 by Greg Roelofs +.\" +.\" ========================================================================= +.\" define .EX/.EE (for multiline user-command examples; normal Courier font) +.de EX +.in +4n +.nf +.ft CW +.. +.de EE +.ft R +.fi +.in -4n +.. +.\" ========================================================================= +.TH UNZIPSFX 1L "20 April 2009 (v6.0)" "Info-ZIP" +.SH NAME +unzipsfx \- self-extracting stub for prepending to ZIP archives +.PD +.SH SYNOPSIS +\fB\fP [\fB\-cfptuz\fP[\fBajnoqsCLV$\fP]] +[\fIfile(s)\fP\ .\|.\|. [\fB\-x\fP\ \fIxfile(s)\fP\ .\|.\|.]] +.PD +.\" ========================================================================= +.SH DESCRIPTION +\fIunzipsfx\fP is a modified version of \fIunzip\fP(1L) designed to be +prepended to existing ZIP archives in order to form self-extracting archives. +Instead of taking its first non-flag argument to be the zipfile(s) to be +extracted, \fIunzipsfx\fP seeks itself under the name by which it was invoked +and tests or extracts the contents of the appended archive. Because the +executable stub adds bulk to the archive (the whole purpose of which is to +be as small as possible), a number of the less-vital capabilities in regular +\fIunzip\fP have been removed. Among these are the usage (or help) screen, +the listing and diagnostic functions (\fB\-l\fP and \fB\-v\fP), the ability +to decompress older compression formats (the ``reduce,'' ``shrink'' and +``implode'' methods). The ability to extract to a directory other than +the current one can be selected as a compile-time option, which is now enabled +by default since UnZipSFX version 5.5. Similarly, decryption is supported as +a compile-time option but should be avoided unless the attached archive +contains encrypted files. Starting with release 5.5, another compile-time +option adds a simple ``run command after extraction'' feature. This feature +is currently incompatible with the ``extract to different directory'' +feature and remains disabled by default. +.PP +\fBNote that +self-extracting archives made with\fP \fIunzipsfx\fP \fBare no more (or less) +portable across different operating systems than is +the\fP \fIunzip\fP \fBexecutable itself.\fP In general a self-extracting +archive made on +a particular Unix system, for example, will only self-extract under the same +flavor of Unix. Regular \fIunzip\fP may still be used to extract the +embedded archive as with any normal zipfile, although it will generate +a harmless warning about extra bytes at the beginning of the zipfile. +\fIDespite this\fP, however, the self-extracting archive is technically +\fInot\fP a valid ZIP archive, and PKUNZIP may be unable to test or extract +it. This limitation is due to the simplistic manner in which the archive +is created; the internal directory structure is not updated to reflect the +extra bytes prepended to the original zipfile. +.PD +.\" ========================================================================= +.SH ARGUMENTS +.IP [\fIfile(s)\fP] +An optional list of archive members to be processed. +Regular expressions (wildcards) similar to those in Unix \fIegrep\fP(1) +may be used to match multiple members. These wildcards may contain: +.RS +.IP * +matches a sequence of 0 or more characters +.IP ? +matches exactly 1 character +.IP [.\|.\|.] +matches any single character found inside the brackets; ranges are specified +by a beginning character, a hyphen, and an ending character. If an exclamation +point or a caret (`!' or `^') follows the left bracket, then the range of +characters within the brackets is complemented (that is, anything \fIexcept\fP +the characters inside the brackets is considered a match). +.RE +.IP +(Be sure to quote any character that might otherwise be interpreted or +modified by the operating system, particularly under Unix and VMS.) +.IP [\fB\-x\fP\ \fIxfile(s)\fP] +An optional list of archive members to be excluded from processing. +Since wildcard characters match directory separators (`/'), this option +may be used to exclude any files that are in subdirectories. For +example, ``\fCfoosfx *.[ch] -x */*\fR'' would extract all C source files +in the main directory, but none in any subdirectories. Without the \fB\-x\fP +option, all C source files in all directories within the zipfile would be +extracted. +.PP +If \fIunzipsfx\fP is compiled with SFX_EXDIR defined, the following option +is also enabled: +.IP [\fB\-d\fP\ \fIexdir\fP] +An optional directory to which to extract files. By default, all files +and subdirectories are recreated in the current directory; the \fB\-d\fP +option allows extraction in an arbitrary directory (always assuming one +has permission to write to the directory). The option and directory may +be concatenated without any white space between them, but note that this +may cause normal shell behavior to be suppressed. In particular, +``\fC\-d\ ~\fR'' (tilde) is expanded by Unix C shells into the name +of the user's home directory, but ``\fC\-d~\fR'' is treated as a +literal subdirectory ``\fB~\fP'' of the current directory. +.PD +.\" ========================================================================= +.SH OPTIONS +\fIunzipsfx\fP supports the following \fIunzip\fP(1L) options: \fB\-c\fP +and \fB\-p\fP (extract to standard output/screen), \fB\-f\fP and \fB\-u\fP +(freshen and update existing files upon extraction), \fB\-t\fP (test +archive) and \fB\-z\fP (print archive comment). All normal listing options +(\fB\-l\fP, \fB\-v\fP and \fB\-Z\fP) have been removed, but the testing +option (\fB\-t\fP) may be used as a ``poor man's'' listing. Alternatively, +those creating self-extracting archives may wish to include a short listing +in the zipfile comment. +.PP +See \fIunzip\fP(1L) for a more complete description of these options. +.PD +.\" ========================================================================= +.SH MODIFIERS +\fIunzipsfx\fP currently supports all \fIunzip\fP(1L) modifiers: \fB\-a\fP +(convert text files), \fB\-n\fP (never overwrite), \fB\-o\fP (overwrite +without prompting), \fB\-q\fP (operate quietly), \fB\-C\fP (match names +case-insensitively), \fB\-L\fP (convert uppercase-OS names to lowercase), +\fB\-j\fP (junk paths) and \fB\-V\fP (retain version numbers); plus the +following operating-system specific options: \fB\-X\fP (restore VMS +owner/protection info), \fB\-s\fP (convert spaces in filenames to underscores +[DOS, OS/2, NT]) and \fB\-$\fP (restore volume label [DOS, OS/2, NT, Amiga]). +.PP +(Support for regular ASCII text-conversion may be removed in future versions, +since it is simple enough for the archive's creator to ensure that text +files have the appropriate format for the local OS. EBCDIC conversion will +of course continue to be supported since the zipfile format implies ASCII +storage of text files.) +.PP +See \fIunzip\fP(1L) for a more complete description of these modifiers. +.PD +.\" ========================================================================= +.SH "ENVIRONMENT OPTIONS" +\fIunzipsfx\fP uses the same environment variables as \fIunzip\fP(1L) does, +although this is likely to be an issue only for the person creating and +testing the self-extracting archive. See \fIunzip\fP(1L) for details. +.PD +.\" ========================================================================= +.SH DECRYPTION +Decryption is supported exactly as in \fIunzip\fP(1L); that is, interactively +with a non-echoing prompt for the password(s). See \fIunzip\fP(1L) for +details. Once again, note that if the archive has no encrypted files there +is no reason to use a version of \fIunzipsfx\fP with decryption support; +that only adds to the size of the archive. +.PD +.\" ========================================================================= +.SH AUTORUN COMMAND +When \fIunzipsfx\fP was compiled with CHEAP_SFX_AUTORUN defined, a simple +``command autorun'' feature is supported. You may enter a command into the +Zip archive comment, using the following format: +.PP +.EX +$AUTORUN$>[command line string] +.EE +.PP +When \fIunzipsfx\fP recognizes the ``$AUTORUN$>'' token at the beginning +of the Zip archive comment, the remainder of the first line of the comment +(until the first newline character) is passed as a shell command to the +operating system using the C rtl ``system'' function. Before executing +the command, \fIunzipsfx\fP displays the command on the console and prompts +the user for confirmation. When the user has switched off prompting by +specifying the \fB-q\fP option, autorun commands are never executed. +.PP +In case the archive comment contains additional lines of text, the remainder +of the archive comment following the first line is displayed normally, unless +quiet operation was requested by supplying a \fB-q\fP option. +.PD +.\" ========================================================================= +.SH EXAMPLES +To create a self-extracting archive \fIletters\fP from a regular zipfile +\fIletters.zip\fP and change the new archive's permissions to be +world-executable under Unix: +.PP +.EX +cat unzipsfx letters.zip > letters +chmod 755 letters +zip -A letters +.EE +.PP +To create the same archive under MS-DOS, OS/2 or NT (note the use of the +\fB/b\fP [binary] option to the \fIcopy\fP command): +.PP +.EX +copy /b unzipsfx.exe+letters.zip letters.exe +zip -A letters.exe +.EE +.PP +Under VMS: +.PP +.EX +copy unzipsfx.exe,letters.zip letters.exe +letters == "$currentdisk:[currentdir]letters.exe" +zip -A letters.exe +.EE +.PP +(The VMS \fIappend\fP command may also be used. The second command installs +the new program as a ``foreign command'' capable of taking arguments. The +third line assumes that Zip is already installed as a foreign command.) +Under AmigaDOS: +.PP +.EX +MakeSFX letters letters.zip UnZipSFX +.EE +.PP +(MakeSFX is included with the UnZip source distribution and with Amiga +binary distributions. ``\fCzip -A\fR'' doesn't work on Amiga self-extracting +archives.) +To test (or list) the newly created self-extracting archive: +.PP +.EX +letters \-t +.EE +.PP +To test \fIletters\fP quietly, printing only a summary message indicating +whether the archive is OK or not: +.PP +.EX +letters \-tqq +.EE +.PP +To extract the complete contents into the current directory, recreating all +files and subdirectories as necessary: +.PP +.EX +letters +.EE +.PP +To extract all \fC*.txt\fR files (in Unix quote the `*'): +.PP +.EX +letters *.txt +.EE +.PP +To extract everything \fIexcept\fP the \fC*.txt\fR files: +.PP +.EX +letters -x *.txt +.EE +.PP +To extract only the README file to standard output (the screen): +.PP +.EX +letters -c README +.EE +.PP +To print only the zipfile comment: +.PP +.EX +letters \-z +.EE +.PD +.\" ========================================================================= +.SH LIMITATIONS +The principle and fundamental limitation of \fIunzipsfx\fP is that it is +not portable across architectures or operating systems, and therefore +neither are the resulting archives. For some architectures there is +limited portability, however (e.g., between some flavors of Intel-based Unix). +.PP +Another problem with the current implementation is that any archive +with ``junk'' prepended to the beginning technically is no longer a zipfile +(unless \fIzip\fP(1) is used to adjust the zipfile offsets appropriately, +as noted above). \fIunzip\fP(1) takes note of the prepended bytes +and ignores them since some file-transfer protocols, notably MacBinary, are +also known to prepend junk. But PKWARE's archiver suite may not be able to +deal with the modified archive unless its offsets have been adjusted. +.PP +\fIunzipsfx\fP has no knowledge of the user's PATH, so in general an archive +must either be in the current directory when it is invoked, or else a full +or relative path must be given. If a user attempts to extract the archive +from a directory in the PATH other than the current one, \fIunzipsfx\fP will +print a warning to the effect, ``can't find myself.'' This is always true +under Unix and may be true in some cases under MS-DOS, depending on the +compiler used (Microsoft C fully qualifies the program name, but other +compilers may not). Under OS/2 and NT there are operating-system calls +available that provide the full path name, so the archive may be invoked +from anywhere in the user's path. The situation is not known for AmigaDOS, +Atari TOS, MacOS, etc. +.PP +As noted above, a number of the normal \fIunzip\fP(1L) functions have +been removed in order to make \fIunzipsfx\fP smaller: usage and diagnostic +info, listing functions and extraction to other directories. Also, only +stored and deflated files are supported. The latter limitation is mainly +relevant to those who create SFX archives, however. +.PP +VMS users must know how to set up self-extracting archives as foreign +commands in order to use any of \fIunzipsfx\fP's options. This is not +necessary for simple extraction, but the command to do so then becomes, +e.g., ``\fCrun letters\fR'' (to continue the examples given above). +.PP +\fIunzipsfx\fP on the Amiga requires the use of a special program, MakeSFX, +in order to create working self-extracting archives; simple concatenation +does not work. (For technically oriented users, the attached archive is +defined as a ``debug hunk.'') There may be compatibility problems between +the ROM levels of older Amigas and newer ones. +.PP +All current bugs in \fIunzip\fP(1L) exist in \fIunzipsfx\fP as well. +.PD +.\" ========================================================================= +.SH DIAGNOSTICS +\fIunzipsfx\fP's exit status (error level) is identical to that of +\fIunzip\fP(1L); see the corresponding man page. +.PD +.\" ========================================================================= +.SH "SEE ALSO" +\fIfunzip\fP(1L), \fIunzip\fP(1L), \fIzip\fP(1L), \fIzipcloak\fP(1L), +\fIzipgrep\fP(1L), \fIzipinfo\fP(1L), \fIzipnote\fP(1L), \fIzipsplit\fP(1L) +.PD +.PD +.\" ========================================================================= +.SH URL +The Info-ZIP home page is currently at +.EX +\fChttp://www.info-zip.org/pub/infozip/\fR +.EE +or +.EX +\fCftp://ftp.info-zip.org/pub/infozip/\fR . +.EE +.PD +.\" ========================================================================= +.SH AUTHORS +Greg Roelofs was responsible for the basic modifications to UnZip necessary +to create UnZipSFX. See \fIunzip\fP(1L) for the current list of Zip-Bugs +authors, or the file CONTRIBS in the UnZip source distribution for the +full list of Info-ZIP contributors. +.PD diff --git a/man/zipgrep.1 b/man/zipgrep.1 new file mode 100644 index 0000000..dad83f8 --- /dev/null +++ b/man/zipgrep.1 @@ -0,0 +1,89 @@ +.\" Copyright (c) 1990-2009 Info-ZIP. All rights reserved. +.\" +.\" See the accompanying file LICENSE, version 2009-Jan-02 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 +.\" +.\" zipgrep.1 by Greg Roelofs. +.\" +.\" ========================================================================= +.TH ZIPGREP 1L "20 April 2009" "Info-ZIP" +.SH NAME +zipgrep \- search files in a ZIP archive for lines matching a pattern +.PD +.SH SYNOPSIS +\fBzipgrep\fP [\fBegrep_options\fP] \fIpattern\fP +\fIfile\fP[\fI.zip\fP] [\fIfile(s)\fP\ .\|.\|.] +[\fB\-x\fP\ \fIxfile(s)\fP\ .\|.\|.] +.PD +.\" ========================================================================= +.SH DESCRIPTION +\fIzipgrep\fP will search files within a ZIP archive for lines matching +the given string or pattern. \fIzipgrep\fP is a shell script and requires +\fIegrep\fP(1) and \fIunzip\fP(1L) to function. Its output is identical to +that of \fIegrep\fP(1). +.PD +.\" ========================================================================= +.SH ARGUMENTS +.TP +.IP \fIpattern\fP +The pattern to be located within a ZIP archive. Any string or regular +expression accepted by \fIegrep\fP(1) may be used. +.IR file [ .zip ] +Path of the ZIP archive. (Wildcard expressions for the ZIP archive name are +not supported.) If the literal filename is not found, the suffix \fC.zip\fR +is appended. Note that self-extracting ZIP files are supported, as with any +other ZIP archive; just specify the \fC.exe\fR suffix (if any) explicitly. +.IP [\fIfile(s)\fP] +An optional list of archive members to be processed, separated by spaces. +If no member files are specified, all members of the ZIP archive are searched. +Regular expressions (wildcards) may be used to match multiple members: +.RS +.IP * +matches a sequence of 0 or more characters +.IP ? +matches exactly 1 character +.IP [.\|.\|.] +matches any single character found inside the brackets; ranges are specified +by a beginning character, a hyphen, and an ending character. If an exclamation +point or a caret (`!' or `^') follows the left bracket, then the range of +characters within the brackets is complemented (that is, anything \fIexcept\fP +the characters inside the brackets is considered a match). +.RE +.IP +(Be sure to quote any character that might otherwise be interpreted or +modified by the operating system.) +.IP [\fB\-x\fP\ \fIxfile(s)\fP] +An optional list of archive members to be excluded from processing. +Since wildcard characters match directory separators (`/'), this option +may be used to exclude any files that are in subdirectories. For +example, ``\fCzipgrep grumpy foo *.[ch] -x */*\fR'' would search for the +string ``grumpy'' in all C source files in the main directory of the ``foo'' +archive, but none in any subdirectories. Without the \fB\-x\fP +option, all C source files in all directories within the zipfile would be +searched. +.\" ========================================================================= +.SH OPTIONS +All options prior to the ZIP archive filename are passed to \fIegrep\fP(1). +.PD +.\" ========================================================================= +.SH "SEE ALSO" +\fIegrep\fP(1), \fIunzip\fP(1L), \fIzip\fP(1L), \fIfunzip\fP(1L), +\fIzipcloak\fP(1L), \fIzipinfo\fP(1L), \fIzipnote\fP(1L), \fIzipsplit\fP(1L) +.PD +.\" ========================================================================= +.SH URL +The Info-ZIP home page is currently at +.EX +\fChttp://www.info-zip.org/pub/infozip/\fR +.EE +or +.EX +\fCftp://ftp.info-zip.org/pub/infozip/\fR . +.EE +.PD +.\" ========================================================================= +.SH AUTHORS +\fIzipgrep\fP was written by Jean-loup Gailly. +.PD diff --git a/man/zipinfo.1 b/man/zipinfo.1 new file mode 100644 index 0000000..428e4b9 --- /dev/null +++ b/man/zipinfo.1 @@ -0,0 +1,517 @@ +.\" Copyright (c) 1990-2009 Info-ZIP. All rights reserved. +.\" +.\" See the accompanying file LICENSE, version 2009-Jan-02 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 +.\" +.\" zipinfo.1 by Greg Roelofs and others. +.\" +.\" ========================================================================= +.\" define .X macro (for long-line ZipInfo output examples; small Courier): +.de X +.nf +.ft CW +.ie n .ti -5 +.el \{ .ti +2m +.ps -1 \} +\&\\$1 +.ie n .ti +5 +.el \{ .ti -2m +.ps +1 \} +.ft +.fi +.. +.\" define .EX/.EE (for multiline user-command examples; normal Courier font) +.de EX +.in +4n +.nf +.ft CW +.. +.de EE +.ft +.fi +.in -4n +.. +.\" ========================================================================= +.TH ZIPINFO 1L "20 April 2009 (v3.0)" "Info-ZIP" +.SH NAME +zipinfo \- list detailed information about a ZIP archive +.PD +.SH SYNOPSIS +\fBzipinfo\fP [\fB\-12smlvhMtTz\fP] \fIfile\fP[\fI.zip\fP] +[\fIfile(s)\fP\ .\|.\|.] [\fB\-x\fP\ \fIxfile(s)\fP\ .\|.\|.] +.PP +\fBunzip\fP \fB\-Z\fP [\fB\-12smlvhMtTz\fP] \fIfile\fP[\fI.zip\fP] +[\fIfile(s)\fP\ .\|.\|.] [\fB\-x\fP\ \fIxfile(s)\fP\ .\|.\|.] +.PD +.\" ========================================================================= +.SH DESCRIPTION +\fIzipinfo\fP lists technical information about files in a ZIP archive, most +commonly found on MS-DOS systems. Such information includes file access +permissions, encryption status, type of compression, version and operating +system or file system of compressing program, and the like. The default +behavior (with no options) is +to list single-line entries for each file in the archive, with header and +trailer lines providing summary information for the entire archive. The +format is a cross between Unix ``\fCls \-l\fR'' and ``\fCunzip \-v\fR'' +output. See +.B "DETAILED DESCRIPTION" +below. Note that \fIzipinfo\fP is the same program as \fIunzip\fP (under +Unix, a link to it); on some systems, however, \fIzipinfo\fP support may +have been omitted when \fIunzip\fP was compiled. +.PD +.\" ========================================================================= +.SH ARGUMENTS +.TP +.IR file [ .zip ] +Path of the ZIP archive(s). If the file specification is a wildcard, +each matching file is processed in an order determined by the operating +system (or file system). Only the filename can be a wildcard; the path +itself cannot. Wildcard expressions are similar to Unix \fIegrep\fP(1) +(regular) expressions and may contain: +.RS +.IP * +matches a sequence of 0 or more characters +.IP ? +matches exactly 1 character +.IP [.\|.\|.] +matches any single character found inside the brackets; ranges are specified +by a beginning character, a hyphen, and an ending character. If an exclamation +point or a caret (`!' or `^') follows the left bracket, then the range of +characters within the brackets is complemented (that is, anything \fIexcept\fP +the characters inside the brackets is considered a match). To specify a +verbatim left bracket, the three-character sequence ``[[]'' has to be used. +.RE +.IP +(Be sure to quote any character that might otherwise be interpreted or +modified by the operating system, particularly under Unix and VMS.) If no +matches are found, the specification is assumed to be a literal filename; +and if that also fails, the suffix \fC.zip\fR is appended. Note that +self-extracting ZIP files are supported, as with any other ZIP archive; +just specify the \fC.exe\fR suffix (if any) explicitly. +.IP [\fIfile(s)\fP] +An optional list of archive members to be processed, separated by spaces. +(VMS versions compiled with VMSCLI defined must delimit files with commas +instead.) +Regular expressions (wildcards) may be used to match multiple members; see +above. Again, be sure to quote expressions that would otherwise be expanded +or modified by the operating system. +.IP [\fB\-x\fP\ \fIxfile(s)\fP] +An optional list of archive members to be excluded from processing. +.\" ========================================================================= +.SH OPTIONS +.TP +.B \-1 +list filenames only, one per line. This option excludes all others; headers, +trailers and zipfile comments are never printed. It is intended for use in +Unix shell scripts. +.TP +.B \-2 +list filenames only, one per line, but allow headers (\fB\-h\fP), trailers +(\fB\-t\fP) and zipfile comments (\fB\-z\fP), as well. This option may be +useful in cases where the stored filenames are particularly long. +.TP +.B \-s +list zipfile info in short Unix ``\fCls \-l\fR'' format. This is the default +behavior; see below. +.TP +.B \-m +list zipfile info in medium Unix ``\fCls \-l\fR'' format. Identical to the +\fB\-s\fP output, except that the compression factor, expressed as a +percentage, is also listed. +.TP +.B \-l +list zipfile info in long Unix ``\fCls \-l\fR'' format. As with \fB\-m\fP +except that the compressed size (in bytes) is printed instead of the +compression ratio. +.TP +.B \-v +list zipfile information in verbose, multi-page format. +.TP +.B \-h +list header line. The archive name, actual size (in bytes) and total number +of files is printed. +.TP +.B \-M +pipe all output through an internal pager similar to the Unix \fImore\fP(1) +command. At the end of a screenful of output, \fIzipinfo\fP pauses with a +``\-\-More\-\-'' prompt; the next screenful may be viewed by pressing the +Enter (Return) key or the space bar. \fIzipinfo\fP can be terminated by +pressing the ``q'' key and, on some systems, the Enter/Return key. Unlike +Unix \fImore\fP(1), there is no forward-searching or editing capability. +Also, \fIzipinfo\fP doesn't notice if long lines wrap at the edge of the +screen, effectively resulting in the printing of two or more lines and the +likelihood that some text will scroll off the top of the screen before being +viewed. On some systems the number of available lines on the screen is not +detected, in which case \fIzipinfo\fP assumes the height is 24 lines. +.TP +.B \-t +list totals for files listed or for all files. The number of files listed, +their uncompressed and compressed total sizes , and their overall compression +factor is printed; or, if only the totals line is being printed, the values +for the entire archive are given. The compressed total size does not include +the 12 additional header bytes of each encrypted entry. Note that the total +compressed (data) size will never match the actual zipfile size, since the +latter includes all of the internal zipfile headers in addition to the +compressed data. +.TP +.B \-T +print the file dates and times in a sortable decimal format (yymmdd.hhmmss). +The default date format is a more standard, human-readable version with +abbreviated month names (see examples below). +.TP +.B \-U +[UNICODE_SUPPORT only] modify or disable UTF-8 handling. +When UNICODE_SUPPORT is available, the option \fB\-U\fP forces \fIunzip\fP +to escape all non-ASCII characters from UTF-8 coded filenames as ``#Uxxxx''. +This option is mainly provided for debugging purpose when the fairly new +UTF-8 support is suspected to mangle up extracted filenames. +.IP +The option \fB\-UU\fP allows to entirely disable the recognition of UTF-8 +encoded filenames. The handling of filename codings within \fIunzip\fP falls +back to the behaviour of previous versions. +.TP +.B \-z +include the archive comment (if any) in the listing. +.PD +.\" ========================================================================= +.SH "DETAILED DESCRIPTION" +.I zipinfo +has a number of modes, and its behavior can be rather difficult to fathom +if one isn't familiar with Unix \fIls\fP(1) (or even if one is). The default +behavior is to list files in the following format: +.PP +.X "-rw-rws--- 1.9 unx 2802 t- defX 11-Aug-91 13:48 perms.2660" +.PP +The last three fields are the modification date and time of +the file, and its name. The case of the filename is respected; thus +files that come from MS-DOS PKZIP are always capitalized. If the file +was zipped with a stored directory name, that is also displayed as part +of the filename. +.PP +The second and third fields indicate that the file was zipped under +Unix with version 1.9 of \fIzip\fP. Since it comes from Unix, the file +permissions at the beginning of the line are printed in Unix format. +The uncompressed file-size (2802 in this example) is the fourth field. +.PP +The fifth field consists of two characters, either of which may take +on several values. The first character may be either `t' or `b', indicating +that \fIzip\fP believes the file to be text or binary, respectively; +but if the file is encrypted, \fIzipinfo\fP +notes this fact by capitalizing the character (`T' or `B'). The second +character may also take on four values, depending on whether there is +an extended local header and/or an ``extra field'' associated with the +file (fully explained in PKWare's APPNOTE.TXT, but basically analogous to +pragmas in ANSI C--i.e., they provide a standard way to include non-standard +information in the archive). If neither exists, the character +will be a hyphen (`\-'); if there is an extended local header but no extra +field, `l'; if the reverse, `x'; and if both exist, `X'. Thus the +file in this example is (probably) a text file, is not encrypted, and +has neither an extra field nor an extended local header associated with it. +The example below, on the other hand, is an encrypted binary file with an +extra field: +.PP +.X "RWD,R,R 0.9 vms 168 Bx shrk 9-Aug-91 19:15 perms.0644" +.PP +Extra fields are used for various purposes (see discussion of the \fB\-v\fP +option below) including the storage of VMS file attributes, which is +presumably the case here. Note that the file attributes are listed in +VMS format. Some other possibilities for the host operating system (which +is actually a misnomer--host file system is more correct) include +OS/2 or NT with High Performance File System (HPFS), MS-DOS, OS/2 or NT +with File Allocation Table (FAT) file system, and Macintosh. These are +denoted as follows: +.PP +.X "-rw-a-- 1.0 hpf 5358 Tl i4:3 4-Dec-91 11:33 longfilename.hpfs" +.X "-r--ahs 1.1 fat 4096 b- i4:2 14-Jul-91 12:58 EA DATA. SF" +.X "--w------- 1.0 mac 17357 bx i8:2 4-May-92 04:02 unzip.macr" +.PP +File attributes in the first two cases are indicated in a Unix-like format, +where the seven subfields indicate whether the file: (1) is a directory, +(2) is readable (always true), (3) is writable, (4) is executable (guessed +on the basis of the extension--\fI.exe\fP, \fI.com\fP, \fI.bat\fP, \fI.cmd\fP +and \fI.btm\fP files are assumed to be so), (5) has its archive bit set, +(6) is hidden, and (7) is a system file. Interpretation of Macintosh file +attributes is unreliable because some Macintosh archivers don't store any +attributes in the archive. +.PP +Finally, the sixth field indicates +the compression method and possible sub-method used. There are six methods +known at present: storing (no compression), reducing, shrinking, imploding, +tokenizing (never publicly released), and deflating. In addition, there are +four levels of reducing (1 through 4); four types of imploding (4K or 8K +sliding dictionary, and 2 or 3 Shannon-Fano trees); and four levels of +deflating (superfast, fast, normal, maximum compression). \fIzipinfo\fP +represents these methods and their sub-methods as follows: \fIstor\fP; +\fIre:1\fP, \fIre:2\fP, etc.; \fIshrk\fP; \fIi4:2\fP, \fIi8:3\fP, etc.; +\fItokn\fP; and \fIdefS\fP, \fIdefF\fP, \fIdefN\fP, and \fIdefX\fP. +.PP +The medium and long listings are almost identical to the short format except +that they add information on the file's compression. The medium format lists +the file's compression factor as a percentage indicating the amount of space +that has been ``removed'': +.PP +.X "-rw-rws--- 1.5 unx 2802 t- 81% defX 11-Aug-91 13:48 perms.2660" +.PP +In this example, the file has been compressed by more than a factor of +five; the compressed data are only 19% of the original size. The long +format gives the compressed file's size in bytes, instead: +.PP +.X "-rw-rws--- 1.5 unx 2802 t- 538 defX 11-Aug-91 13:48 perms.2660" +.PP +In contrast to the \fIunzip\fP listings, the compressed size figures in +this listing format denote the complete size of compressed data, including +the 12 extra header bytes in case of encrypted entries. +.PP +Adding the \fB\-T\fP option changes the file date and time to decimal +format: +.PP +.X "-rw-rws--- 1.5 unx 2802 t- 538 defX 910811.134804 perms.2660" +.PP +Note that because of limitations in the MS-DOS format used to store file +times, the seconds field is always rounded to the nearest even second. +For Unix files this is expected to change in the next major releases of +\fIzip\fP(1L) and \fIunzip\fP. +.PP +In addition to individual file information, a default zipfile listing +also includes header and trailer lines: +.PP +.X "Archive: OS2.zip 5453 bytes 5 files" +.X ",,rw, 1.0 hpf 730 b- i4:3 26-Jun-92 23:40 Contents" +.X ",,rw, 1.0 hpf 3710 b- i4:3 26-Jun-92 23:33 makefile.os2" +.X ",,rw, 1.0 hpf 8753 b- i8:3 26-Jun-92 15:29 os2unzip.c" +.X ",,rw, 1.0 hpf 98 b- stor 21-Aug-91 15:34 unzip.def" +.X ",,rw, 1.0 hpf 95 b- stor 21-Aug-91 17:51 zipinfo.def" +.X "5 files, 13386 bytes uncompressed, 4951 bytes compressed: 63.0%" +.PP +The header line gives the name of the archive, its total size, and the +total number of files; the trailer gives the number of files listed, +their total uncompressed size, and their total compressed size (not +including any of \fIzip\fP's internal overhead). If, however, one or +more \fIfile(s)\fP are provided, the header and trailer lines are +not listed. This behavior is also similar to that of Unix's ``\fCls \-l\fR''; +it may be overridden by specifying the \fB\-h\fP and \fB\-t\fP options +explicitly. +In such a case the listing format must also be specified explicitly, +since \fB\-h\fP or \fB\-t\fP (or both) in the absence of other options implies +that ONLY the header or trailer line (or both) is listed. See the +\fBEXAMPLES\fP section below for a semi-intelligible translation of this +nonsense. +.PP +The verbose listing is mostly self-explanatory. It also lists file +comments and the zipfile comment, if any, and the type and number of bytes +in any stored extra fields. Currently known types of extra fields include +PKWARE's authentication (``AV'') info; OS/2 extended attributes; VMS +filesystem info, both PKWARE and Info-ZIP versions; Macintosh resource +forks; Acorn/Archimedes SparkFS info; and so on. (Note +that in the case of OS/2 extended attributes--perhaps the most common +use of zipfile extra fields--the size of the stored EAs as reported by +\fIzipinfo\fP may not match the number given by OS/2's \fIdir\fP command: +OS/2 always reports the number of bytes required in 16-bit format, whereas +\fIzipinfo\fP always reports the 32-bit storage.) +.PP +Again, the compressed size figures of the individual entries include the +12 extra header bytes for encrypted entries. In contrast, the archive total +compressed size and the average compression ratio shown in the summary +bottom line are calculated \fBwithout\fP the extra 12 header bytes of +encrypted entries. +.PD +.\" ========================================================================= +.SH "ENVIRONMENT OPTIONS" +Modifying \fIzipinfo\fP's default behavior via options placed in +an environment variable can be a bit complicated to explain, due to +\fIzipinfo\fP's attempts to handle various defaults in an intuitive, +yet Unix-like, manner. (Try not to laugh.) Nevertheless, there is some +underlying logic. In brief, +there are three ``priority levels'' of options: the default options; +environment options, which can override or add to the defaults; and +explicit options given by the user, which can override or add to +either of the above. +.PP +The default listing format, as noted above, corresponds roughly +to the "\fCzipinfo \-hst\fR" command (except when individual zipfile members +are specified). +A user who prefers the long-listing format (\fB\-l\fP) can make use of the +\fIzipinfo\fP's environment variable to change this default: +.TP +Unix Bourne shell: +\f(CW\&ZIPINFO=\-l; export ZIPINFO\fP +.TP +Unix C shell: +\f(CW\&setenv ZIPINFO \-l\fP +.TP +OS/2 or MS-DOS: +\f(CW\&set ZIPINFO=\-l\fP +.TP +VMS (quotes for \fIlowercase\fP): +\f(CW\&define ZIPINFO_OPTS "\-l"\fP +.EE +.PP +If, in addition, the user dislikes the trailer line, \fIzipinfo\fP's +concept of ``negative options'' may be used to override the default +inclusion of the line. This is accomplished by preceding the undesired +option with one or more minuses: e.g., ``\fC\-l\-t\fR'' or ``\fC\-\-tl\fR'', +in this example. The first hyphen is the regular switch character, but the +one before the `t' is a minus sign. The dual use of hyphens may seem a +little awkward, but it's reasonably intuitive nonetheless: simply ignore +the first hyphen and go from there. It is also consistent with the behavior +of the Unix command \fInice\fP(1). +.PP +As suggested above, the default variable names are ZIPINFO_OPTS for VMS +(where the symbol used to install \fIzipinfo\fP as a foreign command +would otherwise be confused with the environment variable), and ZIPINFO +for all other operating systems. For compatibility with \fIzip\fP(1L), +ZIPINFOOPT is also accepted (don't ask). If both ZIPINFO and ZIPINFOOPT +are defined, however, ZIPINFO takes precedence. \fIunzip\fP's diagnostic +option (\fB\-v\fP with no zipfile name) can be used to check the values +of all four possible \fIunzip\fP and \fIzipinfo\fP environment variables. +.PD +.\" ========================================================================= +.SH EXAMPLES +To get a basic, short-format listing of the complete contents of a ZIP +archive \fIstorage.zip\fP, with both header and totals lines, use only +the archive name as an argument to zipinfo: +.PP +.EX +zipinfo storage +.EE +.PP +To produce a basic, long-format listing (not verbose), including header and +totals lines, use \fB\-l\fP: +.PP +.EX +zipinfo \-l storage +.EE +.PP +To list the complete contents of the archive without header and totals +lines, either negate the \fB\-h\fP and \fB\-t\fP options or else specify the +contents explicitly: +.PP +.EX +zipinfo \-\-h\-t storage +zipinfo storage \e* +.EE +.PP +(where the backslash is required only if the shell would otherwise expand +the `*' wildcard, as in Unix when globbing is turned on--double quotes around +the asterisk would have worked as well). To turn off the totals line by +default, use the environment variable (C shell is assumed here): +.PP +.EX +setenv ZIPINFO \-\-t +zipinfo storage +.EE +.PP +To get the full, short-format listing of the first example again, given +that the environment variable is set as in the previous example, it is +necessary to specify the \fB\-s\fP option explicitly, since the \fB\-t\fP +option by itself implies that ONLY the footer line is to be printed: +.PP +.EX +setenv ZIPINFO \-\-t +zipinfo \-t storage \fR[only totals line]\fP +zipinfo \-st storage \fR[full listing]\fP +.EE +.PP +The \fB\-s\fP option, like \fB\-m\fP and \fB\-l\fP, includes headers and +footers by default, unless otherwise specified. Since the environment +variable specified no footers and that has a higher precedence than the +default behavior of \fB\-s\fP, an explicit \fB\-t\fP option was necessary +to produce the full listing. Nothing was indicated about the header, +however, so the \fB\-s\fP option was sufficient. Note that both the +\fB\-h\fP and \fB\-t\fP options, when used by themselves or with +each other, override any default listing of member files; only the header +and/or footer are printed. This behavior is useful when \fIzipinfo\fP is +used with a wildcard zipfile specification; the contents of all zipfiles +are then summarized with a single command. +.PP +To list information on a single file within the archive, in medium format, +specify the filename explicitly: +.PP +.EX +zipinfo \-m storage unshrink.c +.EE +.PP +The specification of any member file, as in this example, will override +the default header and totals lines; only the single line of information +about the requested file will be printed. This is intuitively what one +would expect when requesting information about a single file. For multiple +files, it is often useful to know the total compressed and uncompressed +size; in such cases \fB\-t\fP may be specified explicitly: +.PP +.EX +zipinfo \-mt storage "*.[ch]" Mak\e* +.EE +.PP +To get maximal information about the ZIP archive, use the verbose +option. It is usually wise to pipe the output into a filter such as +Unix \fImore\fP(1) if the operating system allows it: +.PP +.EX +zipinfo \-v storage | more +.EE +.PP +Finally, to see the most recently modified files in the archive, use +the \fB\-T\fP option in conjunction with an external sorting utility +such as Unix \fIsort\fP(1) (and \fIsed\fP(1) as well, in this example): +.PP +.EX +zipinfo \-T storage | sort -nr -k 7 | sed 15q +.EE +.PP +The \fB\-nr\fP option to \fIsort\fP(1) tells it to sort numerically +in reverse order rather than in textual order, and the \fB\-k\ 7\fP option +tells it to sort on the seventh field. This +assumes the default short-listing format; if \fB\-m\fP or \fB\-l\fP is +used, the proper \fIsort\fP(1) option would be \fB\-k\ 8\fP. +Older versions of \fIsort\fP(1) do not support the \fB\-k\fP option, +but you can use the traditional \fB\+\fP option instead, e.g., +\fB\+6\fP instead of \fB\-k\ 7\fP. The \fIsed\fP(1) +command filters out all but the first 15 lines of the listing. Future +releases of \fIzipinfo\fP may incorporate date/time and filename sorting +as built-in options. +.PD +.\" ========================================================================= +.SH TIPS +The author finds it convenient to define an alias \fIii\fP for \fIzipinfo\fP +on systems that allow aliases (or, on other systems, copy/rename the +executable, create a link or create a command file with the name \fIii\fP). +The \fIii\fP usage parallels the common \fIll\fP alias for long listings in +Unix, and the similarity between the outputs of the two commands was +intentional. +.PD +.\" ========================================================================= +.SH BUGS +As with \fIunzip\fP, \fIzipinfo\fP's \fB\-M\fP (``more'') option is overly +simplistic in its handling of screen output; as noted above, it fails to detect +the wrapping of long lines and may thereby cause lines at the top of the screen +to be scrolled off before being read. \fIzipinfo\fP should detect and treat +each occurrence of line-wrap as one additional line printed. This requires +knowledge of the screen's width as well as its height. In addition, +\fIzipinfo\fP should detect the true screen geometry on all systems. +.PP +\fIzipinfo\fP's listing-format behavior is unnecessarily complex and should +be simplified. (This is not to say that it will be.) +.PP +.\" ========================================================================= +.SH "SEE ALSO" +\fIls\fP(1), \fIfunzip\fP(1L), \fIunzip\fP(1L), \fIunzipsfx\fP(1L), +\fIzip\fP(1L), \fIzipcloak\fP(1L), \fIzipnote\fP(1L), \fIzipsplit\fP(1L) +.PD +.\" ========================================================================= +.SH URL +The Info-ZIP home page is currently at +.EX +\fChttp://www.info-zip.org/pub/infozip/\fR +.EE +or +.EX +\fCftp://ftp.info-zip.org/pub/infozip/\fR . +.EE +.PD +.\" ========================================================================= +.SH AUTHOR +Greg ``Cave Newt'' Roelofs. ZipInfo contains pattern-matching code +by Mark Adler and fixes/improvements by many others. Please refer to the +CONTRIBS file in the UnZip source distribution for a more complete list. diff --git a/match.c b/match.c new file mode 100644 index 0000000..f634409 --- /dev/null +++ b/match.c @@ -0,0 +1,442 @@ +/* + Copyright (c) 1990-2005 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 +*/ +/*--------------------------------------------------------------------------- + + match.c + + The match() routine recursively compares a string to a "pattern" (regular + expression), returning TRUE if a match is found or FALSE if not. This + version is specifically for use with unzip.c: as did the previous match() + routines from SEA and J. Kercheval, it leaves the case (upper, lower, or + mixed) of the string alone, but converts any uppercase characters in the + pattern to lowercase if indicated by the global var pInfo->lcflag (which + is to say, string is assumed to have been converted to lowercase already, + if such was necessary). + + GRR: reversed order of text, pattern in matche() (now same as match()); + added ignore_case/ic flags, Case() macro. + + PaulK: replaced matche() with recmatch() from Zip, modified to have an + ignore_case argument; replaced test frame with simpler one. + + --------------------------------------------------------------------------- + + Copyright on recmatch() from Zip's util.c (although recmatch() was almost + certainly written by Mark Adler...ask me how I can tell :-) ): + + Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly, + Kai Uwe Rommel and Igor Mandrichenko. + + Permission is granted to any individual or institution to use, copy, + or redistribute this software so long as all of the original files are + included unmodified, that it is not sold for profit, and that this copy- + right notice is retained. + + --------------------------------------------------------------------------- + + Match the pattern (wildcard) against the string (fixed): + + match(string, pattern, ignore_case, sepc); + + returns TRUE if string matches pattern, FALSE otherwise. In the pattern: + + `*' matches any sequence of characters (zero or more) + `?' matches any single character + [SET] matches any character in the specified set, + [!SET] or [^SET] matches any character not in the specified set. + + A set is composed of characters or ranges; a range looks like ``character + hyphen character'' (as in 0-9 or A-Z). [0-9a-zA-Z_] is the minimal set of + characters allowed in the [..] pattern construct. Other characters are + allowed (i.e., 8-bit characters) if your system will support them. + + To suppress the special syntactic significance of any of ``[]*?!^-\'', in- + side or outside a [..] construct, and match the character exactly, precede + it with a ``\'' (backslash). + + Note that "*.*" and "*." are treated specially under MS-DOS if DOSWILD is + defined. See the DOSWILD section below for an explanation. Note also + that with VMSWILD defined, '%' is used instead of '?', and sets (ranges) + are delimited by () instead of []. + + ---------------------------------------------------------------------------*/ + + +#define __MATCH_C /* identifies this source module */ + +/* define ToLower() in here (for Unix, define ToLower to be macro (using + * isupper()); otherwise just use tolower() */ +#define UNZIP_INTERNAL +#include "unzip.h" + +#ifndef THEOS /* the Theos port defines its own variant of match() */ + +#if 0 /* this is not useful until it matches Amiga names insensitively */ +#ifdef AMIGA /* some other platforms might also want to use this */ +# define ANSI_CHARSET /* MOVE INTO UNZIP.H EVENTUALLY */ +#endif +#endif /* 0 */ + +#ifdef ANSI_CHARSET +# ifdef ToLower +# undef ToLower +# endif + /* uppercase letters are values 41 thru 5A, C0 thru D6, and D8 thru DE */ +# define IsUpper(c) (c>=0xC0 ? c<=0xDE && c!=0xD7 : c>=0x41 && c<=0x5A) +# define ToLower(c) (IsUpper((uch) c) ? (unsigned) c | 0x20 : (unsigned) c) +#endif +#define Case(x) (ic? ToLower(x) : (x)) + +#ifdef VMSWILD +# define WILDCHAR '%' +# define BEG_RANGE '(' +# define END_RANGE ')' +#else +# define WILDCHAR '?' +# define BEG_RANGE '[' +# define END_RANGE ']' +#endif + +#if 0 /* GRR: add this to unzip.h someday... */ +#if !(defined(MSDOS) && defined(DOSWILD)) +#ifdef WILD_STOP_AT_DIR +#define match(s,p,ic,sc) (recmatch((ZCONST uch *)p,(ZCONST uch *)s,ic,sc) == 1) +#else +#define match(s,p,ic) (recmatch((ZCONST uch *)p,(ZCONST uch *)s,ic) == 1) +#endif +int recmatch OF((ZCONST uch *pattern, ZCONST uch *string, + int ignore_case __WDLPRO)); +#endif +#endif /* 0 */ +static int recmatch OF((ZCONST uch *pattern, ZCONST uch *string, + int ignore_case __WDLPRO)); +static char *isshexp OF((ZCONST char *p)); +static int namecmp OF((ZCONST char *s1, ZCONST char *s2)); + + +/* match() is a shell to recmatch() to return only Boolean values. */ + +int match(string, pattern, ignore_case __WDL) + ZCONST char *string, *pattern; + int ignore_case; + __WDLDEF +{ +#if (defined(MSDOS) && defined(DOSWILD)) + char *dospattern; + int j = strlen(pattern); + +/*--------------------------------------------------------------------------- + Optional MS-DOS preprocessing section: compare last three chars of the + wildcard to "*.*" and translate to "*" if found; else compare the last + two characters to "*." and, if found, scan the non-wild string for dots. + If in the latter case a dot is found, return failure; else translate the + "*." to "*". In either case, continue with the normal (Unix-like) match + procedure after translation. (If not enough memory, default to normal + match.) This causes "a*.*" and "a*." to behave as MS-DOS users expect. + ---------------------------------------------------------------------------*/ + + if ((dospattern = (char *)malloc(j+1)) != NULL) { + strcpy(dospattern, pattern); + if (!strcmp(dospattern+j-3, "*.*")) { + dospattern[j-2] = '\0'; /* nuke the ".*" */ + } else if (!strcmp(dospattern+j-2, "*.")) { + char *p = MBSCHR(string, '.'); + + if (p) { /* found a dot: match fails */ + free(dospattern); + return 0; + } + dospattern[j-1] = '\0'; /* nuke the end "." */ + } + j = recmatch((uch *)dospattern, (uch *)string, ignore_case __WDL); + free(dospattern); + return j == 1; + } else +#endif /* MSDOS && DOSWILD */ + return recmatch((uch *)pattern, (uch *)string, ignore_case __WDL) == 1; +} + + + +static int recmatch(p, s, ic __WDL) + ZCONST uch *p; /* sh pattern to match */ + ZCONST uch *s; /* string to which to match it */ + int ic; /* true for case insensitivity */ + __WDLDEF /* directory sepchar for WildStopAtDir mode, or 0 */ +/* Recursively compare the sh pattern p with the string s and return 1 if + * they match, and 0 or 2 if they don't or if there is a syntax error in the + * pattern. This routine recurses on itself no more deeply than the number + * of characters in the pattern. */ +{ + unsigned int c; /* pattern char or start of range in [-] loop */ + + /* Get first character, the pattern for new recmatch calls follows */ + c = *p; INCSTR(p); + + /* If that was the end of the pattern, match if string empty too */ + if (c == 0) + return *s == 0; + + /* '?' (or '%') matches any character (but not an empty string). */ + if (c == WILDCHAR) +#ifdef WILD_STOP_AT_DIR + /* If uO.W_flag is non-zero, it won't match '/' */ + return (*s && (!sepc || *s != (uch)sepc)) + ? recmatch(p, s + CLEN(s), ic, sepc) : 0; +#else + return *s ? recmatch(p, s + CLEN(s), ic) : 0; +#endif + + /* '*' matches any number of characters, including zero */ +#ifdef AMIGA + if (c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */ + c = '*', p++; +#endif /* AMIGA */ + if (c == '*') { +#ifdef WILD_STOP_AT_DIR + if (sepc) { + /* check for single "*" or double "**" */ +# ifdef AMIGA + if ((c = p[0]) == '#' && p[1] == '?') /* "#?" is Amiga-ese for "*" */ + c = '*', p++; + if (c != '*') { +# else /* !AMIGA */ + if (*p != '*') { +# endif /* ?AMIGA */ + /* single "*": this doesn't match the dirsep character */ + for (; *s && *s != (uch)sepc; INCSTR(s)) + if ((c = recmatch(p, s, ic, sepc)) != 0) + return (int)c; + /* end of pattern: matched if at end of string, else continue */ + if (*p == '\0') + return (*s == 0); + /* continue to match if at sepc in pattern, else give up */ + return (*p == (uch)sepc || (*p == '\\' && p[1] == (uch)sepc)) + ? recmatch(p, s, ic, sepc) : 2; + } + /* "**": this matches slashes */ + ++p; /* move p behind the second '*' */ + /* and continue with the non-W_flag code variant */ + } +#endif /* WILD_STOP_AT_DIR */ + if (*p == 0) + return 1; + if (isshexp((ZCONST char *)p) == NULL) { + /* Optimization for rest of pattern being a literal string: + * If there are no other shell expression chars in the rest + * of the pattern behind the multi-char wildcard, then just + * compare the literal string tail. + */ + ZCONST uch *srest; + + srest = s + (strlen((ZCONST char *)s) - strlen((ZCONST char *)p)); + if (srest - s < 0) + /* remaining literal string from pattern is longer than rest + * of test string, there can't be a match + */ + return 0; + else + /* compare the remaining literal pattern string with the last + * bytes of the test string to check for a match + */ +#ifdef _MBCS + { + ZCONST uch *q = s; + + /* MBCS-aware code must not scan backwards into a string from + * the end. + * So, we have to move forward by character from our well-known + * character position s in the test string until we have + * advanced to the srest position. + */ + while (q < srest) + INCSTR(q); + /* In case the byte *srest is a trailing byte of a multibyte + * character in the test string s, we have actually advanced + * past the position (srest). + * For this case, the match has failed! + */ + if (q != srest) + return 0; + return ((ic + ? namecmp((ZCONST char *)p, (ZCONST char *)q) + : strcmp((ZCONST char *)p, (ZCONST char *)q) + ) == 0); + } +#else /* !_MBCS */ + return ((ic + ? namecmp((ZCONST char *)p, (ZCONST char *)srest) + : strcmp((ZCONST char *)p, (ZCONST char *)srest) + ) == 0); +#endif /* ?_MBCS */ + } else { + /* pattern contains more wildcards, continue with recursion... */ + for (; *s; INCSTR(s)) + if ((c = recmatch(p, s, ic __WDL)) != 0) + return (int)c; + return 2; /* 2 means give up--match will return false */ + } + } + + /* Parse and process the list of characters and ranges in brackets */ + if (c == BEG_RANGE) { + int e; /* flag true if next char to be taken literally */ + ZCONST uch *q; /* pointer to end of [-] group */ + int r; /* flag true to match anything but the range */ + + if (*s == 0) /* need a character to match */ + return 0; + p += (r = (*p == '!' || *p == '^')); /* see if reverse */ + for (q = p, e = 0; *q; INCSTR(q)) /* find closing bracket */ + if (e) + e = 0; + else + if (*q == '\\') /* GRR: change to ^ for MS-DOS, OS/2? */ + e = 1; + else if (*q == END_RANGE) + break; + if (*q != END_RANGE) /* nothing matches if bad syntax */ + return 0; + for (c = 0, e = (*p == '-'); p < q; INCSTR(p)) { + /* go through the list */ + if (!e && *p == '\\') /* set escape flag if \ */ + e = 1; + else if (!e && *p == '-') /* set start of range if - */ + c = *(p-1); + else { + unsigned int cc = Case(*s); + + if (*(p+1) != '-') + for (c = c ? c : *p; c <= *p; c++) /* compare range */ + if ((unsigned)Case(c) == cc) /* typecast for MSC bug */ + return r ? 0 : recmatch(q + 1, s + 1, ic __WDL); + c = e = 0; /* clear range, escape flags */ + } + } + return r ? recmatch(q + CLEN(q), s + CLEN(s), ic __WDL) : 0; + /* bracket match failed */ + } + + /* if escape ('\\'), just compare next character */ + if (c == '\\' && (c = *p++) == 0) /* if \ at end, then syntax error */ + return 0; + + /* just a character--compare it */ +#ifdef QDOS + return QMatch(Case((uch)c), Case(*s)) ? + recmatch(p, s + CLEN(s), ic __WDL) : 0; +#else + return Case((uch)c) == Case(*s) ? + recmatch(p, s + CLEN(s), ic __WDL) : 0; +#endif + +} /* end function recmatch() */ + + + +static char *isshexp(p) +ZCONST char *p; +/* If p is a sh expression, a pointer to the first special character is + returned. Otherwise, NULL is returned. */ +{ + for (; *p; INCSTR(p)) + if (*p == '\\' && *(p+1)) + p++; + else if (*p == WILDCHAR || *p == '*' || *p == BEG_RANGE) + return (char *)p; + return NULL; +} /* end function isshexp() */ + + + +static int namecmp(s1, s2) + ZCONST char *s1, *s2; +{ + int d; + + for (;;) { + d = (int)ToLower((uch)*s1) + - (int)ToLower((uch)*s2); + + if (d || *s1 == 0 || *s2 == 0) + return d; + + s1++; + s2++; + } +} /* end function namecmp() */ + +#endif /* !THEOS */ + + + + +int iswild(p) /* originally only used for stat()-bug workaround in */ + ZCONST char *p; /* VAX C, Turbo/Borland C, Watcom C, Atari MiNT libs; */ +{ /* now used in process_zipfiles() as well */ + for (; *p; INCSTR(p)) + if (*p == '\\' && *(p+1)) + ++p; +#ifdef THEOS + else if (*p == '?' || *p == '*' || *p=='#'|| *p == '@') +#else /* !THEOS */ +#ifdef VMS + else if (*p == '%' || *p == '*') +#else /* !VMS */ +#ifdef AMIGA + else if (*p == '?' || *p == '*' || (*p=='#' && p[1]=='?') || *p == '[') +#else /* !AMIGA */ + else if (*p == '?' || *p == '*' || *p == '[') +#endif /* ?AMIGA */ +#endif /* ?VMS */ +#endif /* ?THEOS */ +#ifdef QDOS + return (int)p; +#else + return TRUE; +#endif + + return FALSE; + +} /* end function iswild() */ + + + + + +#ifdef TEST_MATCH + +#define put(s) {fputs(s,stdout); fflush(stdout);} +#ifdef main +# undef main +#endif + +int main(int argc, char **argv) +{ + char pat[256], str[256]; + + for (;;) { + put("Pattern (return to exit): "); + gets(pat); + if (!pat[0]) + break; + for (;;) { + put("String (return for new pattern): "); + gets(str); + if (!str[0]) + break; + printf("Case sensitive: %s insensitive: %s\n", + match(str, pat, 0) ? "YES" : "NO", + match(str, pat, 1) ? "YES" : "NO"); + } + } + EXIT(0); +} + +#endif /* TEST_MATCH */ diff --git a/msdos/Contents b/msdos/Contents new file mode 100644 index 0000000..e82fde0 --- /dev/null +++ b/msdos/Contents @@ -0,0 +1,35 @@ +Contents of the "msdos" subdirectory for UnZip 5.3 and later: + + Contents this file + README notes about quirks in MS-DOS executables and compilers + crc_i86.asm optimized 8086/80286 assembler version of generic crc32.c + doscfg.h OS-dependent configuration, included by unzpriv.h + msdos.c OS-dependent UnZip routines for MS-DOS + makefile.bc makefile for Borland C++ and Turbo C++ + makefile.msc makefile for Microsoft C and make or nmake + makefile.tc makefile for Turbo C and make + makefile.wat makefile for Watcom C + makefile.dj1 makefile for GNU C, djgpp v1.12m4 port + makefile.dj2 makefile for GNU C, djgpp v2.x port + makefile.emx makefile for GNU C, emx 0.9c port, gnu make + +Notes: + +(1) Two makefiles for djgpp/GNU make are provided, one for djgpp 1.12 and one + for djgpp v2.x. In addition, the Unix makefile (unix/Makefile) contains + a djgpp v2.x target using the go32-gcc cross compiler on Linux. Read the + appropriate makefile sections for details. + +(2) The makefile for emx+gcc has been used with GNU Make ports from DJGPP and + the GNUish MS-DOS project. Other make utilities may work, too. The + resulting executables require emx.exe or rsx.exe to run (akin to djgpp + 1.x's go32.exe). + +(3) The OS/2 makefile includes several (cross compilation ?) targets to + generate MS-DOS executables which can be used with MSC 6.0 or later + (`mscdos', 16-bit), Watcom C/C++ 9.0 or later (`watcom16dos', 16-bit; + `watcomdos' and `pmodew', 32-bit) and emx+gcc 0.9c or later (`gccdos', + 32-bit). These targets have only been tested in cross-compilation from + OS/2 to MS-DOS, but they may work on a plain MS-DOS system, when a proper + make utility is available. + diff --git a/msdos/README b/msdos/README new file mode 100644 index 0000000..277fd8d --- /dev/null +++ b/msdos/README @@ -0,0 +1,117 @@ +Notes about MS-DOS executables and compilers: + + - Borland start-up code is reported to switch the screen mode auto- + matically if it's not 80 columns (or possibly 40) and either 25, 43 + or 50 lines. In particular, extended modes such as 100x40 are not + retained. + + - Borland start-up code also uses interrupt 1Ah, causing incorrect + behavior (including lock-ups) on some Japanese MS-DOS machines such + as the Fujitsu FMR series, which lack this interrupt. + + - Some(?) Borland compilers are apparently incapable of putting static + data into far memory; this means all of UnZip's strings are in near + memory, and there is not enough room to enable ZipInfo in the small + memory model. The medium memory model is the default for now, but + it may be necessary in some cases to use the large model. + + - Older Borland compilers do not understand source files with Unix + line-endings (LF rather than CR/LF). Use "flip" or a similar utility + to convert the line endings before compiling. + + - The Borland 5.00 compiler is simply too buggy to use on WizUnZip, both + 16-bit and 32-bit versions, and we recommend avoiding it for now even + on the commmand-line version of UnZip. + + - Microsoft C 5.1 large-model code is more than an order of magnitude + slower than the identical code compiled with MSC 6 or 7 (a factor of + 15 in our tests, actually). This may be due to a lousy optimizer or + lousy libraries; regardless, since UnZip is hovering at the doorstep + of the large memory model, we recommend upgrading to a later version + of the compiler. + +For these reasons, Info-ZIP's distributed versions of the 16-bit MS-DOS +executables are compiled with MSC 6 or 7. + + - djgpp 2.x (currently 2.03) is no longer distributed with the go32 extender. + Instead, a 2K stub bound into the executable searches for a DPMI server; + if none is found, it loads the default DPMI server while executing UnZip. + Both djgpp 1.x and 2.x are capable of substituting a list of files in an + ASCII file (say, `foo') on the command line; for example, "unzip archive + @foo" will extract from `archive' all of the files listed in `foo'. Note, + however, that djgpp 2.x is considerably slower than 1.x at file extraction + (roughly twice as slow, in fact); see proginfo/perform.dos in the UnZip 5.3 + source distribution for details. + + - djgpp 2.0's long-filename support is somewhat flaky; users should upgrade + to version 2.01 instead. + + - The default wildcard ("globbing") behavior of djgpp 1.x/go32 is disabled + by default in UnZip, but this can be overridden if the GO32 environment + variable is set to "glob". This will cause UnZip to fail with various + odd errors about "filename not matched" and the like; to avoid this, set + the GO32 variable to "noglob" or unset it altogether. (The documented + method of avoiding this by quoting wildcards with single quotes was + buggy in djgpp 1.11 but is reported fixed in 1.12; not tested.) + + - djgpp 1.x's handling of timezones, necessary for the correct conversion of + MS-DOS file times to those used in the Unix-like C library, is completely + broken in djgpp 1.12 and probably earlier versions as well. It is fixed + (or very close to it) in the 1.12m4 patch release and reportedly in the + 2.x series, so be sure to use one of those when compiling. Otherwise + UnZip's -f and -u (freshen/update) functions will not work correctly. + It is reportedly necessary to set the TZDIR environment variable correctly + with 1.12m4; for example, add `set TZDIR=c:/djgpp/zoneinfo' or similar to + autoexec.bat. + + - djgpp 1.x/go32 executables, when run in a DOS box under OS/2 *and* extrac- + ting to an HPFS disk *and* overwriting existing files (intentionally, that + is), do not set the files' timestamps correctly. Instead, the timestamps + remain set to whatever the original files' stamps were. This is a pretty + obscure bug, but it does *not* occur in the 16-bit version so it seems + to be go32's fault somehow. + + - According to notes found in another package, there was a known conflict + between djgpp 1.x's go32 extender and QEMM's DPMI; this was apparently + fixed in QEMM 7.04/QDPMI 1.05, but if you still have an older version + (1.03 or 1.01), add "set GO32=nodpmi" to your autoexec.bat to avoid the + conflict.) + + - [For Zip only, the djgpp/go32 extender goes nuts with the copying and/or + deletion of some sort of a temporary file (swap file?) after compression + is finished; this can take 30 seconds or more and really hurts perfor- + mance. It doesn't affect UnZip, apparently.] + + - [Also apparently for Zip only, djgpp/go32 is reported to have problems + when EMM386 is set to NOEMS; it sometimes gives the error message, "CPU + must be in REAL mode (not V86 mode) to run this program without VCPI. + (If you are using an EMS emulator, make sure that EMS isn't disabled)" + Sometimes Zip works correctly, however, possibly due to other software + having been run previously.] + + - emx+gcc's DOS extender does not understand DPMI, and while there is an + alternative extender called RSX available (found in dpmigcc4.zip as of + August 1994), its setup is somewhat kludgy when the local memory manager + supports both DPMI and VCPI (or something else). It's also not yet as + widely known or available as djgpp. + + - The free PMODE/W extender, used in conjunction with executables compiled + with Watcom C 10.x and run in an OS/2 DOS box, appears to use up some + critical DPMI resource and will fail to run after a few dozen executions + ("PMODE/W: DPMI error" and/or SYS 3176). Some newer versions of PMODE/W, + in combination with "unzip -v" on certain zipfiles (e.g., APMTST.ZIP from + IBM/EWS), fail immediately (SYS 3176). And on some OS/2 systems, *any* + use of the PMODE/W executables causes the machine to lock up. + + - PMODE/W is also reported to lock up pure DOS systems if QEMM is running. + + - At least older versions of PMODE/W, used in conjunction with Microsoft's + EMM386, cause UnZip to start up extremely slowly. (This problem does not + occur with QEMM.) + +For these reasons Info-ZIP's distributed 32-bit MS-DOS executables will +be compiled with djgpp 2.03, mainly because of its nice long-filename +support when running in a Win32 DOS box. The cwsdpmi DPMI server will be +bundled if necessary. + +SPC 2000-04-16 diff --git a/msdos/crc_i86.asm b/msdos/crc_i86.asm new file mode 100644 index 0000000..3ad0349 --- /dev/null +++ b/msdos/crc_i86.asm @@ -0,0 +1,497 @@ +;=========================================================================== +; Copyright (c) 1990-2007 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 +;=========================================================================== +; Created by Christian Spieler, last modified 07 Jan 2007. +; + TITLE crc_i86.asm + NAME crc_i86 +; +; Optimized 8086 assembler version of the CRC32 calculation loop, intended +; for real mode Info-ZIP programs (Zip 2.1, UnZip 5.2, and later versions). +; Supported compilers are Microsoft C (DOS real mode) and Borland C(++) +; (Turbo C). Watcom C (16bit) should also work. +; This module was inspired by a similar module for the Amiga (Paul Kienitz). +; +; It replaces the `ulg crc32(ulg crc, ZCONST uch *buf, extent len)' function +; in crc32.c. +; +; In March/April 1997, the code has been revised to incorporate Rodney Brown's +; ideas for optimized access to the data buffer. For 8086 real mode code, +; the data buffer is now accessed by aligned word-wide read operations. +; This new optimization may be turned off by defining the macro switch +; NO_16_BIT_LOADS. +; +; In December 1998, the loop branch commands were changed from "loop dest" +; into "dec cx; jnz dest". On modern systems (486 and newer), the latter +; code is usually much faster (e.g. 1 clock cycle compared to 5 for "loop" +; on Pentium MMX). For the 286, the penalty of "dec cx; jnz" is one clock +; cycle (12 vs. 11 cycles); on an 8088 the cycle counts are 22 (dec cx; jnz) +; vs. 18 (loop). I decided to optimize for newer CPU models by default, because +; I expect that old 80286 or 8088 dinosaurier machines may be rarely used +; nowadays. In case you want optimum performance for these old CPU models +; you should define the OPTIMIZE_286_88 macro switch on the assembler's +; command line. +; Likewise, "jcxz" was replaced by "jz", because the latter is faster on +; 486 and newer CPUs (without any penalty on 80286 and older CPU models). +; +; In January 2007, the "hand-made" memory model setup section has been guarded +; against redefinition of @CodeSize and @DataSize symbols, to work around a +; problem with current Open Watcom (version 1.6) wasm assembler. +; +; The code in this module should work with all kinds of C memory models +; (except Borland's __HUGE__ model), as long as the following +; restrictions are not violated: +; +; - The implementation assumes that the char buffer is confined to a +; 64k segment. The pointer `s' to the buffer must be in a format that +; all bytes can be accessed by manipulating the offset part, only. +; This means: +; + no huge pointers +; + char buffer size < 64 kByte +; +; - Since the buffer size argument `n' is of type `size_t' (= unsigned short) +; for this routine, the char buffer size is limited to less than 64 kByte, +; anyway. So, the assumption above should be easily fulfilled. +; +;============================================================================== +; +; Do NOT assemble this source if external crc32 routine from zlib gets used, +; or only the precomputed CRC_32_Table is needed. +; +ifndef USE_ZLIB +ifndef CRC_TABLE_ONLY +; +; Setup of amount of assemble time informational messages: +; +ifdef DEBUG + VERBOSE_INFO EQU 1 +else + ifdef _AS_MSG_ + VERBOSE_INFO EQU 1 + else + VERBOSE_INFO EQU 0 + endif +endif +; +; Selection of memory model, and initialization of memory model +; related macros: +; +ifndef __SMALL__ + ifndef __COMPACT__ + ifndef __MEDIUM__ + ifndef __LARGE__ + ifndef __HUGE__ +; __SMALL__ EQU 1 + endif + endif + endif + endif +endif + +ifdef __HUGE__ +; .MODEL Huge + ifndef @CodeSize + @CodeSize EQU 1 + endif + ifndef @DataSize + @DataSize EQU 1 + endif + Save_DS EQU 1 + if VERBOSE_INFO + if1 + %out Assembling for C, Huge memory model + endif + endif +else + ifdef __LARGE__ +; .MODEL Large + ifndef @CodeSize + @CodeSize EQU 1 + endif + ifndef @DataSize + @DataSize EQU 1 + endif + if VERBOSE_INFO + if1 + %out Assembling for C, Large memory model + endif + endif + else + ifdef __COMPACT__ +; .MODEL Compact + ifndef @CodeSize + @CodeSize EQU 0 + endif + ifndef @DataSize + @DataSize EQU 1 + endif + if VERBOSE_INFO + if1 + %out Assembling for C, Compact memory model + endif + endif + else + ifdef __MEDIUM__ +; .MODEL Medium + ifndef @CodeSize + @CodeSize EQU 1 + endif + ifndef @DataSize + @DataSize EQU 0 + endif + if VERBOSE_INFO + if1 + %out Assembling for C, Medium memory model + endif + endif + else +; .MODEL Small + ifndef @CodeSize + @CodeSize EQU 0 + endif + ifndef @DataSize + @DataSize EQU 0 + endif + if VERBOSE_INFO + if1 + %out Assembling for C, Small memory model + endif + endif + endif + endif + endif +endif + +if @CodeSize + LCOD_OFS EQU 2 +else + LCOD_OFS EQU 0 +endif + +IF @DataSize + LDAT_OFS EQU 2 +else + LDAT_OFS EQU 0 +endif + +ifdef Save_DS +; (di,si,ds)+(size, return address) + SAVE_REGS EQU 6+(4+LCOD_OFS) +else +; (di,si)+(size, return address) + SAVE_REGS EQU 4+(4+LCOD_OFS) +endif + +; +; Selection of the supported CPU instruction set and initialization +; of CPU type related macros: +; +ifdef __686 + Use_286_code EQU 1 + Align_Size EQU 4 ; dword alignment on Pentium II/III/IV + Alig_PARA EQU 1 ; paragraph aligned code segment +else +ifdef __586 + Use_286_code EQU 1 + Align_Size EQU 4 ; dword alignment on Pentium + Alig_PARA EQU 1 ; paragraph aligned code segment +else +ifdef __486 + Use_286_code EQU 1 + Align_Size EQU 4 ; dword alignment on 32 bit processors + Alig_PARA EQU 1 ; paragraph aligned code segment +else +ifdef __386 + Use_286_code EQU 1 + Align_Size EQU 4 ; dword alignment on 32 bit processors + Alig_PARA EQU 1 ; paragraph aligned code segment +else +ifdef __286 + Use_286_code EQU 1 + Align_Size EQU 2 ; word alignment on 16 bit processors + Alig_PARA EQU 0 ; word aligned code segment +else +ifdef __186 + Use_186_code EQU 1 + Align_Size EQU 2 ; word alignment on 16 bit processors + Alig_PARA EQU 0 ; word aligned code segment +else + Align_Size EQU 2 ; word alignment on 16 bit processors + Alig_PARA EQU 0 ; word aligned code segment +endif ;?__186 +endif ;?__286 +endif ;?__386 +endif ;?__486 +endif ;?__586 +endif ;?__686 + +ifdef Use_286_code + .286 + Have_80x86 EQU 1 +else +ifdef Use_186_code + .186 + Have_80x86 EQU 1 +else + .8086 + Have_80x86 EQU 0 +endif ;?Use_186_code +endif ;?Use_286_code + +; +; Declare the segments used in this module: +; +if @CodeSize +if Alig_PARA +CRC32_TEXT SEGMENT PARA PUBLIC 'CODE' +else +CRC32_TEXT SEGMENT WORD PUBLIC 'CODE' +endif +CRC32_TEXT ENDS +else ;!@CodeSize +if Alig_PARA +_TEXT SEGMENT PARA PUBLIC 'CODE' +else +_TEXT SEGMENT WORD PUBLIC 'CODE' +endif +_TEXT ENDS +endif ;?@CodeSize +_DATA SEGMENT WORD PUBLIC 'DATA' +_DATA ENDS +_BSS SEGMENT WORD PUBLIC 'BSS' +_BSS ENDS +DGROUP GROUP _BSS, _DATA +if @DataSize + ASSUME DS: nothing, SS: DGROUP +else + ASSUME DS: DGROUP, SS: DGROUP +endif + +if @CodeSize +EXTRN _get_crc_table:FAR +else +EXTRN _get_crc_table:NEAR +endif + + +Do_CRC MACRO + mov bl,al + sub bh,bh +if Have_80x86 + shl bx,2 +else + shl bx,1 + shl bx,1 +endif + mov al,ah + mov ah,dl + mov dl,dh + sub dh,dh + xor ax,WORD PTR [bx][si] + xor dx,WORD PTR [bx+2][si] + ENDM +; +Do_1 MACRO +if @DataSize + xor al,BYTE PTR es:[di] +else + xor al,BYTE PTR [di] +endif + inc di + Do_CRC + ENDM +; +Do_2 MACRO +ifndef NO_16_BIT_LOADS +if @DataSize + xor ax,WORD PTR es:[di] +else + xor ax,WORD PTR [di] +endif + add di,2 + Do_CRC + Do_CRC +else + Do_1 + Do_1 +endif + ENDM +; +Do_4 MACRO + Do_2 + Do_2 + ENDM +; + +IF @CodeSize +CRC32_TEXT SEGMENT + ASSUME CS: CRC32_TEXT +else +_TEXT SEGMENT + ASSUME CS: _TEXT +endif +; Line 37 + +; +;ulg crc32(ulg crc, +; ZCONST uch *buf, +; extent len) +; + PUBLIC _crc32 +if @CodeSize +_crc32 PROC FAR +else +_crc32 PROC NEAR +endif +if Have_80x86 + enter WORD PTR 0,0 +else + push bp + mov bp,sp +endif + push di + push si +if @DataSize +; crc = 4+LCOD_OFS DWORD (unsigned long) +; buf = 8+LCOD_OFS DWORD PTR BYTE (uch *) +; len = 12+LCOD_OFS WORD (unsigned int) +else +; crc = 4+LCOD_OFS DWORD (unsigned long) +; buf = 8+LCOD_OFS WORD PTR BYTE (uch *) +; len = 10+LCOD_OFS WORD (unsigned int) +endif +; +if @DataSize + mov ax,WORD PTR [bp+8+LCOD_OFS] ; buf + or ax,WORD PTR [bp+10+LCOD_OFS] ; == NULL ? +else + cmp WORD PTR [bp+8+LCOD_OFS],0 ; buf == NULL ? +endif + jne crc_update + sub ax,ax ; crc = 0 + cwd +ifndef NO_UNROLLED_LOOPS + jmp fine +else + jmp SHORT fine +endif +; +crc_update: + call _get_crc_table +; When used with compilers that conform to the Microsoft/Borland standard +; C calling convention, model-dependent handling is not needed, because +; _get_crc_table returns NEAR pointer. +; But Watcom C is different and does not allow one to assume DS pointing to +; DGROUP. So, we load DS with DGROUP, to be safe. +;if @DataSize +; push ds +; mov ds,dx +; ASSUME DS: nothing +;endif + mov si,ax ;crc_table +if @DataSize + push ds + mov ax,SEG DGROUP + mov ds,ax + ASSUME DS: DGROUP +endif +; + mov ax,WORD PTR [bp+4+LCOD_OFS] ;crc + mov dx,WORD PTR [bp+6+LCOD_OFS] + not ax + not dx +if @DataSize + les di,DWORD PTR [bp+8+LCOD_OFS] ;buf + mov cx,WORD PTR [bp+12+LCOD_OFS] ;len +else + mov di,WORD PTR [bp+8+LCOD_OFS] ;buf + mov cx,WORD PTR [bp+10+LCOD_OFS] ;len +endif +; +ifndef NO_UNROLLED_LOOPS +ifndef NO_16_BIT_LOADS + test cx,cx + jnz start + jmp done +start: test di,1 + jz is_wordaligned + dec cx + Do_1 + mov WORD PTR [bp+10+LDAT_OFS+LCOD_OFS],cx +is_wordaligned: +endif ; !NO_16_BIT_LOADS +if Have_80x86 + shr cx,2 +else + shr cx,1 + shr cx,1 +endif + jz No_Fours +; + align Align_Size ; align destination of branch +Next_Four: + Do_4 +ifndef OPTIMIZE_286_88 + dec cx ; on 286, "loop Next_Four" needs 11 + jnz Next_Four ; clocks, one less than this code +else + loop Next_Four +endif +; +No_Fours: +if @DataSize + mov cx,WORD PTR [bp+12+LCOD_OFS] ;len +else + mov cx,WORD PTR [bp+10+LCOD_OFS] ;len +endif + and cx,00003H +endif ; !NO_UNROLLED_LOOPS + jz done +; + align Align_Size ; align destination of branch +Next_Byte: + Do_1 +ifndef OPTIMIZE_286_88 + dec cx ; on 286, "loop Next_Four" needs 11 + jnz Next_Byte ; clocks, one less than this code +else + loop Next_Four +endif +; +done: +if @DataSize + pop ds +; ASSUME DS: DGROUP + ASSUME DS: nothing +endif + not ax + not dx +; +fine: + pop si + pop di +if Have_80x86 + leave +else + mov sp,bp + pop bp +endif + ret + +_crc32 ENDP + +if @CodeSize +CRC32_TEXT ENDS +else +_TEXT ENDS +endif +; +endif ;!CRC_TABLE_ONLY +endif ;!USE_ZLIB +; +END diff --git a/msdos/doscfg.h b/msdos/doscfg.h new file mode 100644 index 0000000..1f2c6fe --- /dev/null +++ b/msdos/doscfg.h @@ -0,0 +1,342 @@ +/* + Copyright (c) 1990-2008 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 +*/ +/*--------------------------------------------------------------------------- + MS-DOS specific configuration section: + ---------------------------------------------------------------------------*/ + +#ifndef __doscfg_h +#define __doscfg_h + +#include /* for REGS macro (TC) or _dos_setftime (MSC) */ + +#ifdef __TURBOC__ /* includes Power C */ +# include /* for structure ftime */ +# ifndef __BORLANDC__ /* there appears to be a bug (?) in Borland's */ +# include /* MEM.H related to __STDC__ and far poin- */ +# endif /* ters. (dpk) [mem.h included for memcpy] */ +#endif + +#ifdef WINDLL +# if (defined(MSC) || defined(__WATCOMC__)) +# include +# else /* !(MSC || __WATCOMC__) ==> may be BORLANDC, or GNU environment */ +# include +# endif /* ?(MSC || __WATCOMC__) */ +#endif + +#ifdef __WATCOMC__ +# define DOS_STAT_BANDAID + +# ifdef __386__ +# ifndef WATCOMC_386 +# define WATCOMC_386 +# endif +# define __32BIT__ +# undef far +# define far +# undef near +# define near + +/* Get asm routines to link properly without using "__cdecl": */ +# ifndef USE_ZLIB +# pragma aux crc32 "_*" parm caller [] value [eax] modify [eax] +# pragma aux get_crc_table "_*" parm caller [] value [eax] \ + modify [eax ecx edx] +# endif /* !USE_ZLIB */ +# else /* !__386__ */ +# ifndef USE_ZLIB +# pragma aux crc32 "_*" parm caller [] value [ax dx] \ + modify [ax cx dx bx] +# pragma aux get_crc_table "_*" parm caller [] value [ax] \ + modify [ax cx dx bx] +# endif /* !USE_ZLIB */ +# endif /* ?__386__ */ +#endif /* __WATCOMC__ */ + +#ifdef __EMX__ +# ifndef __32BIT__ +# define __32BIT__ +# endif +# define far +# ifndef HAVE_MKTIME +# define HAVE_MKTIME +# endif +#endif + +#if defined(__GO32__) || defined(__DJGPP__) /* MS-DOS compiler, not OS/2 */ +# ifndef __32BIT__ +# define __32BIT__ +# endif +# ifndef __GO32__ +# define __GO32__ +# endif +# ifndef HAVE_MKTIME +# define HAVE_MKTIME +# endif +# include /* for structure ftime and ftime() */ +# if (defined(__DJGPP__) && (__DJGPP__ > 1)) +# include /* for prototypes for read/write etc. */ +# include /* for FA_LABEL */ +# if ((__DJGPP__ == 2) && (__DJGPP_MINOR__ == 0)) +# include /* for _USE_LFN, djgpp 2.0 only */ +# endif +# define USE_LFN _USE_LFN /* runtime test: support long filenames? */ +# else + int setmode(int, int); /* not in older djgpp's include files */ +# endif +#endif + +#ifndef __32BIT__ +# define __16BIT__ +#endif + +#if (defined(M_I86CM) || defined(M_I86LM)) || defined(WINDLL) +# define MED_MEM +#endif +#if (defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)) +# define MED_MEM +#endif +#ifdef __16BIT__ +# ifndef MED_MEM +# define SMALL_MEM +# endif +#endif + +#define EXE_EXTENSION ".exe" /* OS/2 has GetLoadPath() function instead */ + +#ifdef __16BIT__ +# if defined(MSC) || defined(__WATCOMC__) +# include +# define nearmalloc _nmalloc +# define nearfree _nfree +# endif +# if defined(__TURBOC__) && defined(DYNALLOC_CRCTAB) +# if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__) +# undef DYNALLOC_CRCTAB +# endif +# endif +# ifndef nearmalloc +# define nearmalloc malloc +# define nearfree free +# endif +# if defined(DEBUG) && defined(MSC) && (!defined(_MSC_VER) || _MSC_VER < 600) + /* for MSC 5.1, prevent macro expansion space overflow in DEBUG mode */ +# define NO_DEBUG_IN_MACROS +# endif +# ifdef USE_DEFLATE64 +# if (defined(M_I86TM) || defined(M_I86SM) || defined(M_I86MM)) +# error Deflate64(tm) requires compact or large memory model +# endif +# if (defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)) +# error Deflate64(tm) requires compact or large memory model +# endif + /* the 64k history buffer for Deflate64 must be allocated specially */ +# define MALLOC_WORK +# define MY_ZCALLOC +# endif +#endif + +/* 32-bit MSDOS supports the 32-bit optimized CRC-32 C code */ +#ifdef IZ_CRC_BE_OPTIMIZ +# undef IZ_CRC_BE_OPTIMIZ +#endif +#ifdef __32BIT__ +# if !defined(IZ_CRC_LE_OPTIMIZ) && !defined(NO_CRC_OPTIMIZ) +# define IZ_CRC_LE_OPTIMIZ +# endif +#else /* __16BIT__ does not support optimized C crc32 code */ +# ifdef IZ_CRC_LE_OPTIMIZ +# undef IZ_CRC_LE_OPTIMIZ +# endif +#endif + +/* another stat()/fopen() bug with some 16-bit compilers on Novell drives; + * very dangerous (silently overwrites executables in other directories) + */ +#define NOVELL_BUG_WORKAROUND + +/* enables additional test and message code that directs UnZip to fail safely + * in case the "workaround" enabled above does not work as intended + */ +#define NOVELL_BUG_FAILSAFE + +/* Some implementations of stat() tend to fail on "." in root directories + * or on remote (root) directories specified by an UNC network path. This + * patch of stat() is useful for at least the WATCOM compilers. The + * stat_bandaid() wrapper detects stat failures on root directories and + * fills in suitable values. + */ +#ifdef DOS_STAT_BANDAID +# ifdef SSTAT +# undef SSTAT +# endif +# ifdef WILD_STAT_BUG +# define SSTAT(path,pbuf) (iswild(path) || stat_bandaid(path,pbuf)) +# else +# define SSTAT stat_bandaid +# endif + int stat_bandaid(const char *path, struct stat *buf); +#endif + +/* the TIMESTAMP feature is now supported on MSDOS, enable it per default */ +#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) +# define TIMESTAMP +#endif + +/* check that TZ environment variable is defined before using UTC times */ +#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ)) +# define IZ_CHECK_TZ +#endif + +/* The optional "long filename" support available with some MSDOS compiler + * environments running under VFAT systems (Win95) is controlled with the + * help of the two preprocessor symbols USE_VFAT and USE_LFN: + * - USE_VFAT is a compile time switch that selects the long filename + * semantics in mapname() + * - USE_LFN is a macro equating to a boolean expression indicating + * whether long filenames are supported. If available, this + * macro should make use of a runtime function checking the + * LFN support. + * + * The code in msdos.c distinguishes three cases: + * 1.) USE_VFAT is not defined: + * No support of LFN is included; filenames are mapped to 8+3 plain FAT + * syntax unconditionally. + * This is achieved by ``#define MAYBE_PLAIN_FAT'' to include the plain + * FAT name mapping code and by ``#undef USE_LFN'' to disable bypassing + * of the FAT mapping at runtime. + * 2.) USE_VFAT is defined: + * Support for LFN is enabled. + * a) USE_LFN is undefined: + * There is no (runtime) check available to distinguish between OS + * environments that support VFAT extensions and those that do not. + * In this case, filenames are mapped to the more liberal VFAT LFN + * syntax unconditionally. The internal switch MAYBE_PLAIN_FAT remains + * undefined to exclude to "map to plain FAT" code parts. + * b) USE_LFN is defined (hopefully to a boolean runtime LFN check function): + * "#define MAYBE_PLAIN_FAT" is applied to include the plain FAT mapping + * code; the programs checks at runtime whether the OS supports LFN and + * uses the appropiate mapping syntax. + */ +/* Some environments, like DJGPP v2, can support long filenames on VFAT + * systems and DOS 8.3 filenames on FAT systems in the same executable. If + * such support is available, USE_LFN should be defined to an expression + * that will return non-zero when long filenames API should be used, zero + * otherwise. + */ +#ifndef USE_VFAT +# ifdef USE_LFN +# undef USE_LFN +# endif +# ifndef MAYBE_PLAIN_FAT +# define MAYBE_PLAIN_FAT +# endif +#else +# ifdef USE_LFN +# define MAYBE_PLAIN_FAT +# endif +#endif + +#ifdef ACORN_FTYPE_NFS +# undef ACORN_FTYPE_NFS /* no commas allowed in short filenames */ +#endif + +/* handlers for OEM <--> ANSI string conversions */ +#ifdef WINDLL +# if 1 + /* C RTL's file system support assumes OEM-coded strings */ +# ifdef CRTL_CP_IS_ISO +# undef CRTL_CP_IS_ISO +# endif +# ifndef CRTL_CP_IS_OEM +# define CRTL_CP_IS_OEM +# endif +# else + /* C RTL's file system support assumes ISO-coded strings */ +# ifndef CRTL_CP_IS_ISO +# define CRTL_CP_IS_ISO +# endif +# ifdef CRTL_CP_IS_OEM +# undef CRTL_CP_IS_OEM +# endif +# endif /* ?(code page of 16bit Windows compilers) */ + /* include Win API declarations only in sources where conversion is + * actually used (skip __EXTRACT_C, extract.c includes windll.h instead) + */ +# if defined(__ENVARGS_C) || defined(__UNZIP_C) || defined(ZCRYPT_INTERNAL) +# include +# endif + /* use conversion functions of Windows API */ +# ifdef CRTL_CP_IS_ISO +# define ISO_TO_INTERN(src, dst) {if ((src) != (dst)) strcpy((dst), (src));} +# define OEM_TO_INTERN(src, dst) OemToAnsi(src, dst) +# define INTERN_TO_ISO(src, dst) {if ((src) != (dst)) strcpy((dst), (src));} +# define INTERN_TO_OEM(src, dst) AnsiToOem(src, dst) +# endif +# ifdef CRTL_CP_IS_OEM +# define ISO_TO_INTERN(src, dst) AnsiToOem(src, dst) +# define OEM_TO_INTERN(src, dst) {if ((src) != (dst)) strcpy((dst), (src));} +# define INTERN_TO_ISO(src, dst) OemToAnsi(src, dst) +# define INTERN_TO_OEM(src, dst) {if ((src) != (dst)) strcpy((dst), (src));} +# endif +# define _OEM_INTERN(str1) OEM_TO_INTERN(str1, str1) +# define _ISO_INTERN(str1) ISO_TO_INTERN(str1, str1) + /* UzpPassword supplies ANSI-coded string regardless of C RTL's native CP */ +# define STR_TO_CP2(dst, src) (AnsiToOem(src, dst), dst) + /* dummy defines to disable these functions, they are not needed */ +# define STR_TO_ISO +# define STR_TO_OEM +#else + /* use home-brewed conversion functions; internal charset is OEM */ +# ifdef CRTL_CP_IS_ISO +# undef CRTL_CP_IS_ISO +# endif +# ifndef CRTL_CP_IS_OEM +# define CRTL_CP_IS_OEM +# endif +#endif +#ifndef NEED_ISO_OEM_INIT +# define NEED_ISO_OEM_INIT +#endif + +/* SCREENLINES macros for 16-bit and djgpp compilers */ +#ifdef __16BIT__ +# define SCREENLINES (int)(*((unsigned char far*)0x00400084L) + 1) +# define SCREENWIDTH (int)(*(unsigned short far*)0x0040004AL) +#endif + +#if defined(__GO32__) || defined(__DJGPP__) /* djgpp v1.x and v2.x */ +# include +# define SCREENLINES ScreenRows() +# define SCREENWIDTH ScreenCols() +#endif + +#ifdef __EMX__ +# define SCREENWIDTH 80 +# define SCREENSIZE(scrrows, scrcols) screensize(scrrows, scrcols) + int screensize(int *tt_rows, int *tt_cols); +#endif + +#ifdef WATCOMC_386 +# define SCREENWIDTH 80 +# define SCREENSIZE(scrrows, scrcols) screensize(scrrows, scrcols) + int screensize(int *tt_rows, int *tt_cols); +#endif + +#ifndef SCREENSIZE +# define SCREENSIZE(scrrows, scrcols) { \ + if ((scrrows) != NULL) *(scrrows) = SCREENLINES; \ + if ((scrcols) != NULL) *(scrcols) = SCREENWIDTH; } +#endif + +/* on the DOS console screen, line-wraps are always enabled */ +#define SCREENLWRAP 1 +#define TABSIZE 8 + +#endif /* !__doscfg_h */ diff --git a/msdos/makefile.bc b/msdos/makefile.bc new file mode 100644 index 0000000..bb24940 --- /dev/null +++ b/msdos/makefile.bc @@ -0,0 +1,232 @@ +# Makefile for UnZip(SFX) and fUnZip for Borland C++ 2.x-4.x and Turbo C++ 1.0 +# Version: 5.53 and later Alvin Koh, Jim Knoble, Christian Spieler, etc. +# +# Last revised: 29 Dec 05 +# +# To compile with Turbo C++ 1.0, set the macro CC_REV to 1 at the command line +# (make -fmsdos/makefile.bc -DCC_REV=1). + + +# GNU make doesn't like the return value from "rem" +#STRIP=rem +STRIP=echo Ignore this line. +# If you don't have UPX, LZEXE, or PKLITE, get one of them. Then define: +# (NOTE: upx needs a 386 or higher system to run the exe compressor) +#STRIP=upx --8086 --best +# or +#STRIP=lzexe +# or +#STRIP=pklite +# This makes a big difference in .exe size (and possibly load time). + + +# Optional nonstandard preprocessor flags (as -DCHECK_EOF or -DDOS_WILD) +# should be added to the environment via "set LOCAL_UNZIP=-DFOO" or added +# to the declaration of LOC here: +LOC = $(LOCAL_UNZIP) + +# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. +CPU_TYP = 0 + +# (De)Select inclusion of optimized assembler CRC32 routine: +USE_ASMCRC = 1 + +!if $(CC_REV) == 1 +# Turbo C++ 1.0 +CC = tcc +!else +# Borland C++ 2.0, 3.0, 3.1 ... +! if !$(CC_REV) +CC_REV = 3 +! endif +CC = bcc +!endif + +AS = tasm + +# "near data" model is sufficient for UnZip and ZipInfo, now that strings moved +# switched to medium model; UnZip code has grown beyond the 64k limit. +# since 5.42: switched to large model; medium model requires to much memory +# to compile zipinfo, reported for BC++ 4.51 and TC++ 1.0 +# (compilation worked with 624k DOS memory and TC++ 1.0, but that much free +# space requires an almost "empty" DOS system) +# for 5.5: large or compact model required for Deflate64 support +UNMODEL = l # large model for UnZip and ZipInfo +ASUNMODEL=__LARGE__ # keep in sync with UNMODEL definition !! + +FUMODEL = c # need compact model for fUnZip with Deflate64 support +ASFUMODEL=__COMPACT__ # keep in sync with FUMODEL definition !! + +SXMODEL = s # use small model for SFXUnZip (no Deflate64 support) +ASSXMODEL=__SMALL__ # keep in sync with SXMODEL definition !! + +!if $(USE_ASMCRC) +ASMFLG = -DASM_CRC +ASMOBJS = crc_i86.obj +ASMOBJF = crc_i86_.obj +ASMOBJX = crc_i86x.obj +!else +ASMFLG = +ASMOBJS = +ASMOBJF = +ASMOBJX = +!endif + + +# compiler flags + +ASCPUFLAG = __$(CPU_TYP)86 +!if $(CPU_TYP) != 0 +CC_CPUFLG = -$(CPU_TYP) +!endif +ASFLAGS = -ml -m2 -w0 -D$(ASCPUFLAG) $(LOC) +!if $(CC_REV) == 1 +# Bug: TC ++ 1.0 ignores "far" on "const" strings, so const is disabled! +CCOPTIM = -O -G -Z -a -d -DZCONST +LDFLAGS = -lxncd # for tcc +!else +CCOPTIM = -O2 +LDFLAGS = -lxncd -l-P # for bcc +!endif +CFLAGS = $(CCOPTIM) $(CC_CPUFLG) -ff- -k- -P-.C -I. $(ASMFLG) $(LOC) +UNFLAGS = -m$(UNMODEL) $(CFLAGS) +FUFLAGS = -m$(FUMODEL) $(CFLAGS) -K -d +SXFLAGS = -m$(SXMODEL) $(CFLAGS) + +# implicit rules + +.asm.obj: + $(AS) $(ASFLAGS) -D$(ASUNMODEL) $< + +.c.obj: + $(CC) -c $(UNFLAGS) {$< } + +# list macros + +OBJU1 = unzip.obj crc32.obj crypt.obj envargs.obj explode.obj +OBJU2 = extract.obj fileio.obj globals.obj inflate.obj list.obj match.obj +OBJU3 = process.obj ttyio.obj unreduce.obj unshrink.obj zipinfo.obj +OBJUS = msdos.obj $(ASMOBJS) +OBJU = $(OBJU1) $(OBJU2) $(OBJU3) $(OBJUS) +OBJF = funzip.obj crc32f.obj cryptf.obj globalsf.obj inflatef.obj \ + ttyiof.obj msdosf.obj $(ASMOBJF) +OBJX1 = unzipsfx.obj crc32x.obj cryptx.obj extractx.obj fileiox.obj +OBJX2 = globalsx.obj inflatex.obj matchx.obj processx.obj ttyiox.obj +OBJXS = msdosx.obj $(ASMOBJX) +OBJX = $(OBJX1) $(OBJX2) $(OBJXS) + +UNZIP_H = unzip.h unzpriv.h globals.h msdos/doscfg.h + +# explicit rules + +all: unzip.exe funzip.exe unzipsfx.exe + +unzip.exe: $(OBJU) + $(CC) -m$(UNMODEL) $(LDFLAGS) -eunzip.exe @&&| +$(OBJU) +| + $(STRIP) unzip.exe + +funzip.exe: $(OBJF) + $(CC) -m$(FUMODEL) $(LDFLAGS) -efunzip.exe @&&| +$(OBJF) +| + $(STRIP) funzip.exe + +unzipsfx.exe: $(OBJX) + $(CC) -m$(SXMODEL) $(LDFLAGS) -eunzipsfx.exe @&&| +$(OBJX) +| + $(STRIP) unzipsfx.exe + +clean: + rem Ignore any errors in the following... + -del *.obj + -del unzip.exe + -del funzip.exe + -del unzipsfx.exe + +# individual file dependencies + +crc32.obj: crc32.c $(UNZIP_H) zip.h crc32.h +crypt.obj: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +envargs.obj: envargs.c $(UNZIP_H) +explode.obj: explode.c $(UNZIP_H) +extract.obj: extract.c $(UNZIP_H) crc32.h crypt.h +fileio.obj: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +globals.obj: globals.c $(UNZIP_H) +inflate.obj: inflate.c inflate.h $(UNZIP_H) +list.obj: list.c $(UNZIP_H) +match.obj: match.c $(UNZIP_H) +process.obj: process.c $(UNZIP_H) crc32.h +ttyio.obj: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +unreduce.obj: unreduce.c $(UNZIP_H) +unshrink.obj: unshrink.c $(UNZIP_H) +unzip.obj: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +zipinfo.obj: zipinfo.c $(UNZIP_H) + +crc_i86.obj: msdos/crc_i86.asm + $(AS) $(ASFLAGS) -D$(ASUNMODEL) msdos\crc_i86.asm, $*.obj ; + +crc_i86_.obj: msdos/crc_i86.asm + $(AS) $(ASFLAGS) -D$(ASFUMODEL) msdos\crc_i86.asm, $*.obj ; + +crc_i86x.obj: msdos/crc_i86.asm + $(AS) $(ASFLAGS) -D$(ASSXMODEL) msdos\crc_i86.asm, $*.obj ; + +msdos.obj: msdos/msdos.c $(UNZIP_H) + $(CC) -c $(UNFLAGS) msdos/msdos.c + +funzip.obj: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h + $(CC) -c $(FUFLAGS) funzip.c + +crc32f.obj: crc32.c $(UNZIP_H) zip.h crc32.h + $(CC) -c $(FUFLAGS) -DFUNZIP -ocrc32f.obj crc32.c + +cryptf.obj: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CC) -c $(FUFLAGS) -DFUNZIP -ocryptf.obj crypt.c + +globalsf.obj: globals.c $(UNZIP_H) + $(CC) -c $(FUFLAGS) -DFUNZIP -oglobalsf.obj globals.c + +inflatef.obj: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CC) -c $(FUFLAGS) -DFUNZIP -oinflatef.obj inflate.c + +ttyiof.obj: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CC) -c $(FUFLAGS) -DFUNZIP -ottyiof.obj ttyio.c + +msdosf.obj: msdos/msdos.c $(UNZIP_H) + $(CC) -c $(FUFLAGS) -DFUNZIP -omsdosf.obj msdos/msdos.c + +unzipsfx.obj: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h + $(CC) -c $(SXFLAGS) -DSFX -ounzipsfx.obj unzip.c + +crc32x.obj: crc32.c $(UNZIP_H) zip.h crc32.h + $(CC) -c $(SXFLAGS) -DSFX -ocrc32x.obj crc32.c + +cryptx.obj: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CC) -c $(SXFLAGS) -DSFX -ocryptx.obj crypt.c + +extractx.obj: extract.c $(UNZIP_H) crc32.h crypt.h + $(CC) -c $(SXFLAGS) -DSFX -oextractx.obj extract.c + +fileiox.obj: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h + $(CC) -c $(SXFLAGS) -DSFX -ofileiox.obj fileio.c + +globalsx.obj: globals.c $(UNZIP_H) + $(CC) -c $(SXFLAGS) -DSFX -oglobalsx.obj globals.c + +inflatex.obj: inflate.c inflate.h $(UNZIP_H) + $(CC) -c $(SXFLAGS) -DSFX -oinflatex.obj inflate.c + +matchx.obj: match.c $(UNZIP_H) + $(CC) -c $(SXFLAGS) -DSFX -omatchx.obj match.c + +processx.obj: process.c $(UNZIP_H) crc32.h + $(CC) -c $(SXFLAGS) -DSFX -oprocessx.obj process.c + +ttyiox.obj: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CC) -c $(SXFLAGS) -DSFX -ottyiox.obj ttyio.c + +msdosx.obj: msdos/msdos.c $(UNZIP_H) + $(CC) -c $(SXFLAGS) -DSFX -omsdosx.obj msdos/msdos.c diff --git a/msdos/makefile.dj1 b/msdos/makefile.dj1 new file mode 100644 index 0000000..455b6ef --- /dev/null +++ b/msdos/makefile.dj1 @@ -0,0 +1,214 @@ +# Makefile for Info-ZIP's unzip, zipinfo, funzip and unzipsfx +# using djgpp v1.12m4. Tested with unzip550 by Christian Spieler +# +# This Makefile is specifically tailored for GNU Make and GNU C and +# may not work with a generic UNIX compatible Make utility. +# Features use: +# - pattern rules (%.o : %.c, etc.) +# - GNUMake conditionals and functions (ifeq, $(patsubst,,),...) +# +# To allow mixed use of real mode (16bit) vs. GO32 (32bit protected mode) +# GNUMake utility and GCC driver, precautions have been taken to +# limit command lines to the DOS 126 bytes limit. +# In case you have an environment that supports long command lines +# at all "interface" levels (e.g.: DJGPPv1 Gmake 3.71 and GO32 gcc.exe), +# you may define the Makefile macro LONGARGS to take advantage of the +# "long command lines" capability. +# I have archived the fastest compilation (with LONGARGS support!) by +# using both a real mode gnumake (private port) and the real mode +# gcc.exe driver. +# +# The Makefile allows the optional creation of standalone exectutables. +# This has the advantage that unzip.exe does not rely on any other file, +# but results in much larger executables. +# + +# Separators colon and are used in U**X, semi-colon and in DOS. +VPATH=. msdos + +ifdef NOASM +USE_ASMCRC= +else +USE_ASMCRC=1 +endif + +# UnZip flags +LOC=-DDOS $(ASMFLG) $(LOCAL_UNZIP) +CC=gcc +LD=$(CC) +CPPFLAGS=-I. $(LOC) +ASFLAGS=$(CPPFLAGS) +CFLAGS=-Wall -O2 -m486 $(CPPFLAGS) +FUN_FLAGS=$(CFLAGS) -DFUNZIP +SFX_FLAGS=$(CFLAGS) -DSFX +LDFLAGS=-s -v +LIBS=-lpc + +STRIP=strip + +# Define the STANDALONE macro to create executables which can be +# used without any external extender file. +# >>> NOTE: Either copy the go32 extender into your build directory, or +# >>> edit the STUBIFY macro and add the correct path to "go32.exe". +ifdef STANDALONE +STUBIFY=coff2exe -s go32.exe +else +STUBIFY=coff2exe +endif + +# general-purpose stuff +# If cp.exe is not found change to CP=copy /Y . +CP = cp -f +# If install.exe is not found change to INSTALL=$(CP) . +INSTALL=install +# The default value of RM is "rm -f" . If rm.exe is not found, uncomment +# the following: +RM=del +E = .exe +O = .o +M=msdos + +# defaults for crc32 stuff and system dependent headers +ifdef USE_ASMCRC +ASMFLG = -DASM_CRC +CRCA_O = crc_gcc$O +else +ASMFLG = +CRCA_O = +endif + +# object files +OBJS1 = unzip$O crc32$O $(CRCA_O) crypt$O envargs$O explode$O +OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O +OBJS3 = process$O ttyio$O ubz2err$O unreduce$O unshrink$O zipinfo$O +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O + +OBJX1 = unzipsfx$O crc32_$O $(CRCA_O) crypt_$O extract_$O fileio_$O +OBJX2 = globals_$O inflate_$O match_$O process_$O ttyio_$O ubz2err_$O $M_$O +OBJX = $(OBJX1) $(OBJX2) + +OBJF = funzip$O crc32-$O $(CRCA_O) crypt-$O globals-$O inflate-$O ttyio-$O + +OBJECTS_ALL = $(sort $(OBJS) $(OBJX) $(OBJF) crc_gcc$O) + +# Common header files included by all C sources: +UNZIP_H = unzip.h unzpriv.h globals.h msdos/doscfg.h + +# executable files +UNZIPS = unzip$E zipinfo$E funzip$E unzipsfx$E + +# pattern rules to compile the sources: +%$O : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +%-$O: %.c + $(CC) $(FUN_FLAGS) -c $< -o $@ + +%_$O: %.c + $(CC) $(SFX_FLAGS) -c $< -o $@ + +%sfx$O: %.c + $(CC) $(SFX_FLAGS) -c $< -o $@ + +all: unzips + +unzips: unzip$E zipinfo$E funzip$E unzipsfx$E + +unzip$E: $(OBJS) +ifdef LONGARGS + $(LD) $(LDFLAGS) $(OBJS) $(LIBS) -o unzip +else + echo $(OBJS1) > unzip.rsp + echo $(OBJS2) >> unzip.rsp + echo $(OBJS3) $M$O >> unzip.rsp + echo $(LIBS) >> unzip.rsp + $(LD) $(LDFLAGS) -o unzip @unzip.rsp + $(RM) unzip.rsp +endif + $(STRIP) unzip + $(STUBIFY) unzip + stubedit $@ globbing=no + $(RM) unzip + +zipinfo$E: unzip$E + coff2exe -g zipinfo + stubedit $@ runfile=unzip globbing=no + +funzip$E: $(OBJF) + $(LD) $(LDFLAGS) $(OBJF) -o funzip + $(STRIP) funzip + $(STUBIFY) funzip + $(RM) funzip + +unzipsfx$E: $(OBJX) +ifdef LONGARGS + $(LD) $(LDFLAGS) $(OBJX) $(LIBS) -o unzipsfx +else + echo $(OBJX1) > unzipsfx.rsp + echo $(OBJX2) >> unzipsfx.rsp + echo $(LIBS) >> unzipsfx.rsp + $(LD) $(LDFLAGS) -o unzipsfx @unzipsfx.rsp + $(RM) unzipsfx.rsp +endif + $(STRIP) unzipsfx + $(STUBIFY) unzipsfx + stubedit $@ globbing=no + $(RM) unzipsfx + +# explicit compilation instructions: +crc_gcc$O: crc_i386.S # 32bit, GNU AS + $(CC) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S + +# BIN_PATH may be defined in djgpp.env [make] or defined above. +install: + $(INSTALL) $(UNZIPS) $(BIN_PATH) + +uninstall: + cd $(BIN_PATH); $(RM) $(UNZIPS) + +clean: +ifeq ($(firstword $(RM)), del) + $(RM) *$O + $(RM) *.zip +else + $(RM) $(OBJECTS_ALL) *.zip +endif + +# Source dependencies: +crc_gcc$O: crc_i386.S +crc32$O: crc32.c $(UNZIP_H) zip.h crc32.h +crc32-$O: crc32.c $(UNZIP_H) zip.h crc32.h +crc32_$O: crc32.c $(UNZIP_H) zip.h crc32.h +crypt$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +crypt-$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +crypt_$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +envargs$O: envargs.c $(UNZIP_H) +explode$O: explode.c $(UNZIP_H) +extract$O: extract.c $(UNZIP_H) crc32.h crypt.h +extract_$O: extract.c $(UNZIP_H) crc32.h crypt.h +fileio$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +fileio_$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +funzip$O: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h +globals$O: globals.c $(UNZIP_H) +globals-$O: globals.c $(UNZIP_H) +globals_$O: globals.c $(UNZIP_H) +inflate$O: inflate.c inflate.h $(UNZIP_H) +inflate-$O: inflate.c inflate.h $(UNZIP_H) crypt.h +inflate_$O: inflate.c inflate.h $(UNZIP_H) +list$O: list.c $(UNZIP_H) +match$O: match.c $(UNZIP_H) +match_$O: match.c $(UNZIP_H) +msdos$O: msdos/msdos.c $(UNZIP_H) +msdos_$O: msdos/msdos.c $(UNZIP_H) +process$O: process.c $(UNZIP_H) crc32.h +process_$O: process.c $(UNZIP_H) crc32.h +ttyio$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ttyio-$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ttyio_$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ubz2err$O: ubz2err.c $(UNZIP_H) +ubz2err_$O: ubz2err.c $(UNZIP_H) +unreduce$O: unreduce.c $(UNZIP_H) +unshrink$O: unshrink.c $(UNZIP_H) +unzip$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +unzipsfx$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +zipinfo$O: zipinfo.c $(UNZIP_H) diff --git a/msdos/makefile.dj2 b/msdos/makefile.dj2 new file mode 100644 index 0000000..2377694 --- /dev/null +++ b/msdos/makefile.dj2 @@ -0,0 +1,259 @@ +# Makefile for Info-ZIP's UnZip, UnZipSFX and fUnZip using DJGPP v2.01 or +# higher, by Frank Donahoe. Last updated: 21 Jul 2008 + +# This Makefile is specifically tailored for GNU make and GNU C and +# may not work with a generic Unix-compatible make utility. The latest +# make version is 3.78.1. Thanks to Eli Zaretskii for generously responding +# to questions with advice on the changes needed to make install work under +# DJGPP version 2.0x. +# Features used: +# - pattern rules (%.o : %.c, etc.) +# - GNU-specific conditionals and functions (ifeq, $(patsubst,,),...) +# - simply expanded variables (VAR := text) +# +# The stand-alone executable requires DPMI services to run. If running +# in a DOS window under Windows 3.1 or later, the dpmi server is auto- +# matically present. Under DOS, if a DPMI server is not loaded, the +# program will look for "cwsdpmi.exe." If found, it will be loaded for +# the duration of the program. +# +# cwsdpmi is a "free" dpmi server written by Charles W. Sandmann +# (sandman@clio.rice.edu). It may be found, among other sites, on SimTel +# Net at the URL: +# +# ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2misc/csdpmi?[b,s].zip +# +# and on its mirrors worldwide. The latest version as of this writing is 5. +# Archives with the b postscript contain the binaries. An alternate server +# is found, l.c., in the archive pmode??[b,s].zip. The latest (20001022) is +# v1.3. + +# Separators colon and are used in Unix, semi-colon and in DOS. +VPATH=. msdos + +ifdef NOASM +USE_ASMCRC= +else +USE_ASMCRC=1 +endif + +.PHONY : clean install uninstall + +# UnZip flags +# LOCAL_UNZIP may be set in "AUTOEXEC.BAT" or defined in "djgpp.env" under +# [make] as in the example below. Or, if you habitually work in a DOS box +# under Windows9x, right click on the MS-DOS icon, select properties, then +# program, to find a slot called batch file, where you may specify the path +# to a file which will set the variables of choice every time the box is +# opened. +# See, for example, DOSWILD, in the file INSTALL. + +# [make] +# +BUTT=-mcpu=pentiumpro +# +LOC=-W -Wall +# +LOCAL_UNZIP=-DUSE_UNSHRINK + +# BUTT may be defined to specify the target system. With gcc v2.95, +# optimizing options like "-mcpu=pentiumpro -march=pentiumpro" are supported, +# but the traditional "-m386" and "-m486" options of previous gcc 2.x +# version will continue to work. +# So if you are in the habit of compiling from source, programs for your +# own use, it is well to consult gcc's manual for options suitable to +# your processer and to set BUTT accordingly. Consult INSTALL for +# LOCAL_UNZIP. + +LOC= +CC=gcc +LD=$(CC) +CPPFLAGS=-I. $(INC_BZ2LIB) -DDOS -DUSE_VFAT $(ASMFLG) $(LOCAL_UNZIP) $(LOC) +ASFLAGS=$(CPPFLAGS) +CFLAGS=-Wall -O2 $(BUTT) $(CPPFLAGS) + +# See INSTALL for discussion of SFX_EXDIR. +# EXDIR=-DSFX_EXDIR + +FUN_FLAGS=$(CFLAGS) -DFUNZIP + +# Include OFP for a modest decrease in size of unzipsfx.exe. +OFP=-fomit-frame-pointer + +SFX_FLAGS=-Wall -O2 $(CPPFLAGS) -DSFX $(EXDIR) $(OFP) +LDFLAGS=-s + +# general-purpose stuff +# If cp.exe is not found change to CP=copy /Y . +CP = cp -fp +# If install.exe is not found change to INSTALL=$(CP) . To prevent a +# conflict with any of the many different "install's" that might be found +# in the path, GNU install will be called as `ginstall'. This also bypasses +# a stub bug that cropped up with the install from fil316b.zip. +INSTALL=ginstall +# The default value of RM is "rm -f" . If rm.exe is not found, uncomment +# the following: +# RM=del +# Laszlo Molnar who wrote DJ Packer and Markus F. X. J. Oberhumer who wrote +# the compression library used by the DJ Packer have collaborated on the +# Ultimate Packer for eXecutables, which has recently been released. Look +# for upx???d.zip at http://upx.sourceforge.net/ +# As an alternative, look for "djp.exe", now two years old, in the archive +# mlp107[b,s].zip, found in the same location as csdpmi?[b,s].zip (see above). +# Do not add the option -s to djp.exe without making the required changes +# to the target zipinfo$E. Uncomment the three lines beginning with $(DJP) +# or $(DJPSX). + +#DJP = djp -q +#DJPSX = djp -q -s +DJP = upx -qq --best +DJPSX = $(DJP) +E = .exe +O = .o +M=msdos + +# defaults for crc32 stuff and system dependent headers +ifdef USE_ASMCRC +ASMFLG = -DASM_CRC +CRCA_O = crc_gcc$O +else +ASMFLG = +CRCA_O = +endif + +# optional inclusion of bzip2 decompression +IZ_BZIP2 = bzip2 +ifdef USEBZ2 +INC_BZ2LIB = -I$(IZ_BZIP2) +LOCAL_UNZIP:=-DUSE_BZIP2 $(LOCAL_UNZIP) +LD_BZ2LIB = -L$(IZ_BZIP2) -lbz2 +LIBBZIP2 = $(IZ_BZIP2)/libbz2.a +else +INC_BZ2LIB = +LD_BZ2LIB = +LIBBZIP2 = +endif + +# object files +OBJS1 = unzip$O crc32$O $(CRCA_O) crypt$O envargs$O explode$O +OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O +OBJS3 = process$O ttyio$O ubz2err$O unreduce$O unshrink$O zipinfo$O +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O + +OBJX = unzipsfx$O crc32_$O $(CRCA_O) crypt_$O extract_$O fileio_$O \ + globals_$O inflate_$O match_$O process_$O ttyio_$O ubz2err_$O $M_$O + +OBJF = funzip$O crc32-$O $(CRCA_O) crypt-$O globals-$O inflate-$O ttyio-$O + +OBJECTS_ALL = $(sort $(OBJS) $(OBJX) $(OBJF) crc_gcc$O) + +# Common header files included by all C sources: +UNZIP_H = unzip.h unzpriv.h globals.h msdos/doscfg.h + +# executable files +UNZIPS = unzip$E zipinfo$E funzip$E unzipsfx$E + +# pattern rules to compile the sources: +%$O : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +%-$O: %.c + $(CC) $(FUN_FLAGS) -c $< -o $@ + +%_$O: %.c + $(CC) $(SFX_FLAGS) -c $< -o $@ + +%sfx$O: %.c + $(CC) $(SFX_FLAGS) -c $< -o $@ + +all: unzips + +unzips: unzip$E zipinfo$E funzip$E unzipsfx$E + +unzip$E: $(OBJS) $(LIBBZIP2) + $(LD) $(LDFLAGS) $(OBJS) $(LD_BZ2LIB) -o $@ +# $(DJP) $@ + +zipinfo$E: unzip$E + stubify -g $@ + stubedit $@ runfile=unzip argv0=zipinfo + +funzip$E: $(OBJF) + $(LD) $(LDFLAGS) $(OBJF) -o $@ +# $(DJP) $@ + +unzipsfx$E: $(OBJX) + $(LD) $(LDFLAGS) $(OBJX) -o $@ +# $(DJPSX) $@ + +# create/update the library for the optional bzip2 support: +$(IZ_BZIP2)/libbz2.a: + $(MAKE) -C $(IZ_BZIP2) -f Makebz2.iz CC="$(CC)" RM="$(RM)" + +# explicit compilation instructions: + +crc_gcc$O: crc_i386.S # 32bit, GNU AS + $(CC) $(ASFLAGS) -x assembler-with-cpp -c -o $@ $< + +# BIN_PATH may be defined in djgpp.env [make] or defined below. If the +# installation is to the directory containing gcc.exe etc. place the +# following in djgpp.env: + +# [make] +# +BIN_PATH=%\DJDIR%\bin + +# Even if so placed, it can be over-ridden here by, say: +# BIN_PATH=c:\usr\bin + +install: + -@if not exist $(BIN_PATH)\nul mkdir $(BIN_PATH) + command.com /c for %f in ($(UNZIPS)) do $(INSTALL) %f $(BIN_PATH) > NUL + +uninstall: + command.com /c for %f in ($(UNZIPS)) do $(RM) $(BIN_PATH)\%f > NUL + +clean: + $(MAKE) -C $(IZ_BZIP2) -f Makebz2.iz CC="$(CC)" RM="$(RM)" clean +ifeq ($(firstword $(RM)), del) + $(RM) *$O + $(RM) *.~ + $(RM) *.exe +else + $(RM) $(OBJECTS_ALL) *.~ *.exe +endif + +# Source dependencies: +crc_gcc$O: crc_i386.S +crc32$O: crc32.c $(UNZIP_H) zip.h crc32.h +crc32-$O: crc32.c $(UNZIP_H) zip.h crc32.h +crc32_$O: crc32.c $(UNZIP_H) zip.h crc32.h +crypt$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +crypt-$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +crypt_$O: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +envargs$O: envargs.c $(UNZIP_H) +explode$O: explode.c $(UNZIP_H) +extract$O: extract.c $(UNZIP_H) crc32.h crypt.h +extract_$O: extract.c $(UNZIP_H) crc32.h crypt.h +fileio$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +fileio_$O: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +funzip$O: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h +globals$O: globals.c $(UNZIP_H) +globals-$O: globals.c $(UNZIP_H) +globals_$O: globals.c $(UNZIP_H) +inflate$O: inflate.c inflate.h $(UNZIP_H) +inflate-$O: inflate.c inflate.h $(UNZIP_H) crypt.h +inflate_$O: inflate.c inflate.h $(UNZIP_H) +list$O: list.c $(UNZIP_H) +match$O: match.c $(UNZIP_H) +match_$O: match.c $(UNZIP_H) +msdos$O: msdos/msdos.c $(UNZIP_H) +msdos_$O: msdos/msdos.c $(UNZIP_H) +process$O: process.c $(UNZIP_H) crc32.h +process_$O: process.c $(UNZIP_H) crc32.h +ttyio$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ttyio-$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ttyio_$O: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ubz2err$O: ubz2err.c $(UNZIP_H) +ubz2err_$O: ubz2err.c $(UNZIP_H) +unreduce$O: unreduce.c $(UNZIP_H) +unshrink$O: unshrink.c $(UNZIP_H) +unzip$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +unzipsfx$O: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +zipinfo$O: zipinfo.c $(UNZIP_H) diff --git a/msdos/makefile.emx b/msdos/makefile.emx new file mode 100644 index 0000000..429f59b --- /dev/null +++ b/msdos/makefile.emx @@ -0,0 +1,223 @@ +# Makefile for UnZip, fUnZip and UnZipSFX +# for emx 0.9c / gcc under MS-DOS. Derived from makefile.os2 +# By E-Yen Tan (with mods by Christian Spieler). +# Last updated 25 December 2006 (Christian Spieler). +# +# This makefile should work fine with GNU make and hopefully some others. +# Tested with GNU make 3.71 gnuish 16-bit and djgpp 32-bit versions. + +#ifdef NOASM +#AS_FLAGS = +#else +AS_FLAGS = -DASM_CRC +#endif + +CP=copy +RM=del + +CC=gcc -O -I. -m486 + +# Version 5.1 of the RSX extender provides long file name support under +# Windows 95. If you don't have Windows 95 or use a version of RSX prior +# to 5.1 (or simply don't want LFN support) remove -DUSE_VFAT from CFLAGS. +# Note that if you have a version of RSX prior to 5.1, you can still compile +# with USE_VFAT enabled and upgrade RSX.EXE at a later stage. +# +# If you enable USE_VFAT then long file names under plain DOS will simply be +# truncated to 8.3 format without mapping. See doscfg.h for details. +# +CFLAGS=-Wall -DMSDOS $(AS_FLAGS) $(LOCAL_UNZIP) -DUSE_VFAT +NFLAGS= +DLLFLAG= +AS=gcc +ASFLAGS=-Di386 +LDFLAGS=-o ./ +LDFLAGS2=-Zsmall-conv -s +OUT=-o +OBJ=.o + +#ifdef NOASM +#CRCA_O= +#else +CRCA_O=crc_gcc$(OBJ) +#endif +OBJUS=msdos$(OBJ) +OBJXS=msdos_$(OBJ) +OSDEP_H=msdos/doscfg.h + + +# default settings for target dependent macros: +DIRSEP = / +AS_DIRSEP = / + +OBJU1 = unzip$(OBJ) crc32$(OBJ) $(CRCA_O) crypt$(OBJ) envargs$(OBJ) +OBJU2 = explode$(OBJ) extract$(OBJ) fileio$(OBJ) globals$(OBJ) +OBJU3 = inflate$(OBJ) list$(OBJ) match$(OBJ) process$(OBJ) ttyio$(OBJ) +OBJU4 = ubz2err$(OBJ) unreduce$(OBJ) unshrink$(OBJ) zipinfo$(OBJ) +OBJU = $(OBJU1) $(OBJU2) $(OBJU3) $(OBJU4) $(OBJUS) +OBJX1 = unzipsf_$(OBJ) crc32_$(OBJ) $(CRCA_O) crypt_$(OBJ) +OBJX2 = extract_$(OBJ) fileio_$(OBJ) globals_$(OBJ) inflate_$(OBJ) +OBJX3 = match_$(OBJ) process_$(OBJ) ttyio_$(OBJ) ubz2err_$(OBJ) +OBJX = $(OBJX1) $(OBJX2) $(OBJX3) $(OBJXS) +OBJF = funzip$(OBJ) crc32f$(OBJ) $(CRCA_O) cryptf$(OBJ) inflatef$(OBJ) \ + globalsf$(OBJ) ttyiof$(OBJ) + +UNZIP_H = unzip.h unzpriv.h globals.h $(OSDEP_H) + +# rules + +.SUFFIXES: .c $(OBJ) + +.c$(OBJ): + $(CC) -c $(CFLAGS) $(DLLFLAG) $(OUT)$@ $< + +# targets + +all: unzip.exe funzip.exe unzipsfx.exe + +# This next bit is nasty, but is needed to overcome the MS-DOS command +# line limit as response files for emx's gcc seem to only work if each +# file is on a different line. DJGPP doesn't do this (if you are at all +# interested). + +unzip.exe: $(OBJU) + @ echo off +# -@ $(RM) unzip.rsp +# @ for %f in ($(OBJU1)) do echo %f >> unzip.rsp +# @ for %f in ($(OBJU2)) do echo %f >> unzip.rsp +# @ for %f in ($(OBJU3)) do echo %f >> unzip.rsp +# @ for %f in ($(OBJU4) $(OBJUS)) do echo %f >> unzip.rsp + @ echo unzip$(OBJ) > unzip.rsp + @ echo crc32$(OBJ) >> unzip.rsp + @ if not "$(CRCA_O)"=="" echo $(CRCA_O) >> unzip.rsp + @ echo crypt$(OBJ) >> unzip.rsp + @ echo envargs$(OBJ) >> unzip.rsp + @ echo explode$(OBJ) >> unzip.rsp + @ echo extract$(OBJ) >> unzip.rsp + @ echo fileio$(OBJ) >> unzip.rsp + @ echo globals$(OBJ) >> unzip.rsp + @ echo inflate$(OBJ) >> unzip.rsp + @ echo list$(OBJ) >> unzip.rsp + @ echo match$(OBJ) >> unzip.rsp + @ echo process$(OBJ) >> unzip.rsp + @ echo ttyio$(OBJ) >> unzip.rsp + @ echo ubz2err$(OBJ) >> unzip.rsp + @ echo unreduce$(OBJ) >> unzip.rsp + @ echo unshrink$(OBJ) >> unzip.rsp + @ echo zipinfo$(OBJ) >> unzip.rsp + @ echo msdos$(OBJ) >> unzip.rsp + $(CC) $(LDFLAGS)$@ $(DEF) @unzip.rsp $(LDFLAGS2) + @ $(RM) unzip.rsp + +funzip.exe: $(OBJF) + $(CC) $(LDFLAGS)$@ $(DEF) $(OBJF) $(LDFLAGS2) + +unzipsfx.exe: $(OBJX) + @ echo off +# -@ $(RM) unzipsfx.rsp +# @ for %f in ($(OBJX1)) do echo %f >> unzipsfx.rsp +# @ for %f in ($(OBJX2)) do echo %f >> unzipsfx.rsp +# @ for %f in ($(OBJX3)) do echo %f >> unzipsfx.rsp +# @ for %f in ($(OBJXS)) do echo %f >> unzipsfx.rsp + @ echo unzipsf_$(OBJ) > unzipsfx.rsp + @ echo crc32_$(OBJ) >> unzipsfx.rsp + @ if not "$(CRCA_O)"=="" echo $(CRCA_O) >> unzipsfx.rsp + @ echo crypt_$(OBJ) >> unzipsfx.rsp + @ echo extract_$(OBJ) >> unzipsfx.rsp + @ echo fileio_$(OBJ) >> unzipsfx.rsp + @ echo globals_$(OBJ) >> unzipsfx.rsp + @ echo inflate_$(OBJ) >> unzipsfx.rsp + @ echo match_$(OBJ) >> unzipsfx.rsp + @ echo process_$(OBJ) >> unzipsfx.rsp + @ echo ttyio_$(OBJ) >> unzipsfx.rsp + @ echo ubz2err_$(OBJ) >> unzipsfx.rsp + @ echo msdos_$(OBJ) >> unzipsfx.rsp + $(CC) $(LDFLAGS)$@ $(DEF) @unzipsfx.rsp $(LDFLAGS2) + @ $(RM) unzipsfx.rsp + +# dependencies + +apihelp$(OBJ): apihelp.c $(UNZIP_H) unzvers.h +crc32$(OBJ): crc32.c $(UNZIP_H) zip.h crc32.h +envargs$(OBJ): envargs.c $(UNZIP_H) +explode$(OBJ): explode.c $(UNZIP_H) +extract$(OBJ): extract.c $(UNZIP_H) crc32.h crypt.h +fileio$(OBJ): fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +globals$(OBJ): globals.c $(UNZIP_H) +inflate$(OBJ): inflate.c $(UNZIP_H) +list$(OBJ): list.c $(UNZIP_H) +match$(OBJ): match.c $(UNZIP_H) +process$(OBJ): process.c $(UNZIP_H) crc32.h +ttyio$(OBJ): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ubz2err$(OBJ): ubz2err.c $(UNZIP_H) +unreduce$(OBJ): unreduce.c $(UNZIP_H) +unshrink$(OBJ): unshrink.c $(UNZIP_H) +unzip$(OBJ): unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +api$(OBJ): api.c $(UNZIP_H) unzvers.h +zipinfo$(OBJ): zipinfo.c $(UNZIP_H) + +funzip$(OBJ): funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h # funzip only + $(CC) -c $(CFLAGS) $(OUT)$@ funzip.c + +msdos$(OBJ): msdos/msdos.c $(UNZIP_H) unzvers.h # DOS only + $(CC) -c $(CFLAGS) $(OUT)$@ msdos$(DIRSEP)msdos.c + +msdos_$(OBJ): msdos/msdos.c $(UNZIP_H) # DOS unzipsfx + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ msdos$(DIRSEP)msdos.c + +crc_gcc$(OBJ): crc_i386.S # 32bit, GNU AS + $(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S + +# NFLAGS are solely used as work-around for optimization bug in IBM C++ Set +crypt$(OBJ): crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CC) -c $(CFLAGS) $(DLLFLAG) $(NFLAGS) $(OUT)$@ crypt.c + +# funzip specific section +crc32f$(OBJ): crc32.c $(UNZIP_H) zip.h crc32.h + $(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ crc32.c + +cryptf$(OBJ): crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ crypt.c + +globalsf$(OBJ): globals.c $(UNZIP_H) + $(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ globals.c + +inflatef$(OBJ): inflate.c inflate.h $(UNZIP_H) crypt.h + $(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ inflate.c + +ttyiof$(OBJ): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ ttyio.c + +# unzipsfx specific section +crc32_$(OBJ): crc32.c $(UNZIP_H) zip.h crc32.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crc32.c + +crypt_$(OBJ): crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crypt.c + +extract_$(OBJ): extract.c $(UNZIP_H) crc32.h crypt.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ extract.c + +fileio_$(OBJ): fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ fileio.c + +globals_$(OBJ): globals.c $(UNZIP_H) + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ globals.c + +inflate_$(OBJ): inflate.c inflate.h $(UNZIP_H) crypt.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ inflate.c + +match_$(OBJ): match.c $(UNZIP_H) + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ match.c + +process_$(OBJ): process.c $(UNZIP_H) crc32.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ process.c + +ttyio_$(OBJ): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ ttyio.c + +ubz2err_$(OBJ): ubz2err.c $(UNZIP_H) + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ ubz2err.c + +unzipsf_$(OBJ): unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ unzip.c diff --git a/msdos/makefile.msc b/msdos/makefile.msc new file mode 100644 index 0000000..9fd68ee --- /dev/null +++ b/msdos/makefile.msc @@ -0,0 +1,252 @@ +#------------------------------------------------------------------------------ +# Makefile for UnZip 5.53 and later Greg Roelofs and others +# Version: Microsoft C (5.x and later) 29 Dec 05 +#------------------------------------------------------------------------------ + +# Users of MSC 6/7 and NMAKE can use the Unix Makefile (target msc_dos), +# if desired. This makefile works just fine, too, however. OS/2 users +# can cross-compile using os2/makefile.os2 (target mscdos). Note that +# there is possibly a bug in MSC 6 which screws up funzip (goes into +# infinite loop? --this has not been confirmed in over a year...). There +# is definitely a bug (internal compiler error) in MSC 6.00 while com- +# piling explode.c (fixed in 6.0a, 6.0ax, 6.0ax2, 7.*, 8.*). + + +# GNU make doesn't like the return value from "rem" +#STRIP=rem +STRIP=echo Ignore this line. +# If you don't have UPX, LZEXE, or PKLITE, get one of them. Then define: +# (NOTE: upx needs a 386 or higher system to run the exe compressor) +#STRIP=upx --8086 --best +# or +#STRIP=lzexe +# or +#STRIP=pklite +# and remove /e from LDFLAGS. +# This makes a big difference in .exe size (and possibly load time). + +# Optional nonstandard preprocessor flags (as -DCHECK_EOF or -DDOS_WILD) +# should be added to the environment via "set LOCAL_UNZIP=-DFOO" or added +# to the declaration of LOC here: +LOC = $(LOCAL_UNZIP) + +# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. +CPU_TYP = 0 + +#UNMODEL=M # medium model for UnZip +# with MSC 5.1, 6.0 and 8.x, small model exceeds 64k code segment; use medium +# deflate64 support requires large or compact model +UNMODEL=L # large model for UnZip with Deflate64 support +FUMODEL=C # compact model for fUnZip (Deflate64 support enabled) +SXMODEL=S # small model for UnZipSFX (without Deflate64 support) + +# name of Flag to select memory model for assembler compiles, supported +# values are __SMALL__ , __MEDIUM__ , __COMPACT__ , __LARGE__ : +# for MSC 5.1 and 8.x use: +ASUNMODEL=__LARGE__ # keep in sync with UNMODEL definition !! +ASFUMODEL=__COMPACT__ # keep in sync with FUMODEL definition !! +ASSXMODEL=__SMALL__ # keep in sync with SXMODEL definition !! + +# Uncomment the following three macros to use the optimized CRC32 assembler +# routine in UnZip and UnZipSFX: +ASMFLG = -DASM_CRC +ASMOBJS = crc_i86.obj +ASMOBJF = crc_i86_.obj +ASMOBJX = crc_i86x.obj + +ASCPUFLAG = __$(CPU_TYP)86 + +CC = cl +# add -G2(3,4) for 286 (386, 486) and/or -FPi87 for 80x87: +CC_GENFLAGS = -nologo -DMSC $(ASMFLG) $(LOC) -I. -G$(CPU_TYP) +CC_SPEEDOPT = -Oait -Gs # -Ox does not work for inflate.c +CC_SIZEOPT = -Oas -Gs +CFLAGS_UN = -A$(UNMODEL) $(CC_GENFLAGS) $(CC_SPEEDOPT) +CFLAGS_FU = -A$(FUMODEL) $(CC_GENFLAGS) $(CC_SPEEDOPT) -DFUNZIP +CFLAGS_SX = -A$(SXMODEL) $(CC_GENFLAGS) $(CC_SIZEOPT) -DSFX + +AS = masm +ASFLAGS = -ml -D$(ASCPUFLAG) $(LOC) + +LD = Link # mixed case to disable special handling by GNU Make +# remove /e if you have LZEXE or PKLITE: +LDFLAGS = /nologo/noi/e/st:0x0c00/farcall/packcode +# "/farcall/packcode" are only useful for `large code' memory models +# but should be a "no-op" for small code models. +LDFLAGS2 = ,$* +LDFLAGS2_UN = $(LDFLAGS2); +LDFLAGS2_FU = $(LDFLAGS2); +LDFLAGS2_SX = $(LDFLAGS2); + +OBJS1 = unzip.obj crc32.obj crypt.obj envargs.obj explode.obj +OBJS2 = extract.obj fileio.obj globals.obj inflate.obj list.obj match.obj +OBJS3 = process.obj ttyio.obj unreduce.obj unshrink.obj zipinfo.obj +OBJS4 = msdos.obj $(ASMOBJS) +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJS4) + +OBJX1 = unzipsfx.obj crc32x.obj cryptx.obj extractx.obj fileiox.obj +OBJX2 = globalsx.obj inflatex.obj matchx.obj processx.obj ttyiox.obj +OBJX3 = msdosx.obj $(ASMOBJX) +OBJX = $(OBJX1) $(OBJX2) $(OBJX3) + +OBJF = funzip.obj crc32_.obj crypt_.obj globals_.obj inflate_.obj ttyio_.obj \ + msdos_.obj $(ASMOBJF) + +UNZIP_H = unzip.h unzpriv.h globals.h msdos/doscfg.h + + +default: unzip.exe funzip.exe unzipsfx.exe + +#clean: +# As long as the brain damaged old ``Make'' utility from MSC 5.1 and earlier +# (NMAKE from MSC 6.0 + would work !) remains supported, a "clean" target +# cannot be inserted !! + +# pattern rules for implicit dependencies: +.asm.obj: + $(AS) $(ASFLAGS) -D$(ASUNMODEL) $<, $@; + +.c.obj: + $(CC) -c $(CFLAGS_UN) $*.c + +# individual dependencies and action rules: +crc_i86.obj: msdos/crc_i86.asm + $(AS) $(ASFLAGS) -D$(ASUNMODEL) msdos/crc_i86.asm, $@; + +crc_i86_.obj: msdos/crc_i86.asm + $(AS) $(ASFLAGS) -D$(ASFUMODEL) msdos/crc_i86.asm, $@; + +crc_i86x.obj: msdos/crc_i86.asm + $(AS) $(ASFLAGS) -D$(ASSXMODEL) msdos/crc_i86.asm, $@; + +crc32.obj: crc32.c $(UNZIP_H) zip.h crc32.h + +crc32_.obj: crc32.c $(UNZIP_H) zip.h crc32.h + $(CC) -c $(CFLAGS_FU) -Focrc32_.obj crc32.c + +crc32x.obj: crc32.c $(UNZIP_H) zip.h crc32.h + $(CC) -c $(CFLAGS_SX) -Focrc32x.obj crc32.c + +crypt.obj: crypt.c $(UNZIP_H) crypt.h crc32.h ttyio.h zip.h + +crypt_.obj: crypt.c $(UNZIP_H) crypt.h crc32.h ttyio.h zip.h + $(CC) -c $(CFLAGS_FU) -Focrypt_.obj crypt.c + +cryptx.obj: crypt.c $(UNZIP_H) crypt.h crc32.h ttyio.h zip.h + $(CC) -c $(CFLAGS_SX) -Focryptx.obj crypt.c + +envargs.obj: envargs.c $(UNZIP_H) + +explode.obj: explode.c $(UNZIP_H) + +extract.obj: extract.c $(UNZIP_H) crc32.h crypt.h + +extractx.obj: extract.c $(UNZIP_H) crc32.h crypt.h + $(CC) -c $(CFLAGS_SX) -Foextractx.obj extract.c + +fileio.obj: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h + +fileiox.obj: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h + $(CC) -c $(CFLAGS_SX) -Fofileiox.obj fileio.c + +funzip.obj: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h + $(CC) -c $(CFLAGS_FU) funzip.c + +globals.obj: globals.c $(UNZIP_H) + +globals_.obj: globals.c $(UNZIP_H) + $(CC) -c $(CFLAGS_FU) -Foglobals_.obj globals.c + +globalsx.obj: globals.c $(UNZIP_H) + $(CC) -c $(CFLAGS_SX) -Foglobalsx.obj globals.c + +inflate.obj: inflate.c inflate.h $(UNZIP_H) + +inflate_.obj: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CC) -c $(CFLAGS_FU) -Foinflate_.obj inflate.c + +inflatex.obj: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CC) -c $(CFLAGS_SX) -Foinflatex.obj inflate.c + +list.obj: list.c $(UNZIP_H) + +match.obj: match.c $(UNZIP_H) + +matchx.obj: match.c $(UNZIP_H) + $(CC) -c $(CFLAGS_SX) -Fomatchx.obj match.c + +msdos.obj: msdos/msdos.c $(UNZIP_H) + $(CC) -c $(CFLAGS_UN) msdos/msdos.c + +msdos_.obj: msdos/msdos.c $(UNZIP_H) + $(CC) -c $(CFLAGS_FU) -Fomsdos_.obj msdos/msdos.c + +msdosx.obj: msdos/msdos.c $(UNZIP_H) + $(CC) -c $(CFLAGS_SX) -Fomsdosx.obj msdos/msdos.c + +process.obj: process.c $(UNZIP_H) crc32.h + +processx.obj: process.c $(UNZIP_H) crc32.h + $(CC) -c $(CFLAGS_SX) -Foprocessx.obj process.c + +ttyio.obj: ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h + +ttyio_.obj: ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h + $(CC) -c $(CFLAGS_FU) -Fottyio_.obj ttyio.c + +ttyiox.obj: ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h + $(CC) -c $(CFLAGS_SX) -Fottyiox.obj ttyio.c + +unreduce.obj: unreduce.c $(UNZIP_H) + +unshrink.obj: unshrink.c $(UNZIP_H) + +unzip.obj: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h + +unzipsfx.obj: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h + $(CC) -c $(CFLAGS_SX) -Founzipsfx.obj unzip.c + +zipinfo.obj: zipinfo.c $(UNZIP_H) + + +# MS make: +# ------- +unzip.exe: $(OBJS) + echo $(OBJS1)+ > unzip.rsp + echo $(OBJS2)+ >> unzip.rsp + echo $(OBJS3)+ >> unzip.rsp + echo $(OBJS4) >> unzip.rsp + echo $(LDFLAGS2_UN) >> unzip.rsp + $(LD) $(LDFLAGS) @unzip.rsp + del unzip.rsp + $(STRIP) unzip.exe + +unzipsfx.exe: $(OBJX) + echo $(OBJX1)+ > unzipsfx.rsp + echo $(OBJX2)+ >> unzipsfx.rsp + echo $(OBJX3) >> unzipsfx.rsp + echo $(LDFLAGS2_UN) >> unzipsfx.rsp + $(LD) $(LDFLAGS) @unzipsfx.rsp + del unzipsfx.rsp + $(STRIP) unzipsfx.exe + +funzip.exe: $(OBJF) + echo $(OBJF) > funzip.rsp + echo $(LDFLAGS2_FU) >> funzip.rsp + $(LD) $(LDFLAGS) @funzip.rsp + del funzip.rsp + $(STRIP) funzip.exe + +# better makes which know how to deal with 128-char limit on command line: +# ----------------------------------------------------------------------- +#unzip.exe: $(OBJS) +# $(LD) $(LDFLAGS) $(OBJS) $(LDFLAGS2) +# $(STRIP) unzip.exe +# +#unzipsfx.exe: $(OBJX) +# $(LD) $(LDFLAGS) $(OBJX) $(LDFLAGS2) +# $(STRIP) unzipsfx.exe +# +#funzip.exe: $(OBJF) +# $(LD) $(LDFLAGS) $(OBJF) $(LDFLAGS2_FU) +# $(STRIP) funzip.exe diff --git a/msdos/makefile.tc b/msdos/makefile.tc new file mode 100644 index 0000000..a43bfd4 --- /dev/null +++ b/msdos/makefile.tc @@ -0,0 +1,225 @@ +#------------------------------------------------------------------------------ +# Makefile for UnZip 5.53 and later Jean-loup Gailly +# Version: Turbo C (edit and use makefile.bc for Turbo C++) 29 Dec 05 +#------------------------------------------------------------------------------ + +# GNU make doesn't like the return value from "rem" +#STRIP=rem +STRIP=echo Ignore this line. :-) +# If you don't have LZEXE or PKLITE, get one of them. Then define: +#STRIP=lzexe +# or +#STRIP=pklite +# This makes a big difference in .exe size (and possibly load time). + +# Optional nonstandard preprocessor flags (as -DCHECK_EOF or -DDOS_WILD) +# should be added to the environment via "set LOCAL_UNZIP=-DFOO" or added +# to the declaration of LOC here: +LOC = $(LOCAL_UNZIP) + +# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. +CPU_TYP = 0 + +# memory model for UnZip (conflicting reports on whether Turbo C can or +# cannot put strings into far memory; for now assume it can and use small +# model *with* ZipInfo enabled...if fails, either define NO_ZIPINFO or +# use large model) [GRR 940712: sigh, no go--inflate fails. Back to +# large model...] +#UNMODEL = s +UNMODEL = l +# funzip can use small-model (compact-model when including Deflate64 support) +FUMODEL = c + +# name of Flag to select memory model for assembler compiles, supported +# values are __SMALL__ , __MEDIUM__ , __COMPACT__ , __LARGE__ : +ASUNMODEL=__LARGE__ # keep in sync with UNMODEL definition !! +ASFUMODEL=__COMPACT__ # keep in sync with FUMODEL definition !! + +# Uncomment the following three macros to use the optimized CRC32 assembler +# routine in UnZip and UnZipSFX: +ASMFLG = -DASM_CRC +ASMOBJS = crc_i86.obj +ASMOBJF = crc_i86_.obj + +CC = tcc + +AS = tasm + +ASCPUFLAG = __$(CPU_TYP)86 +ASFLAGS = -ml -m2 -w0 -D$(ASCPUFLAG) $(LOC) +CFLAGS = -O -Z -I. -DFar= $(ASMFLG) $(LOC) +UCFLAGS = -m$(UNMODEL) $(CFLAGS) +ULDFLAGS = -m$(UNMODEL) +FCFLAGS = -m$(FUMODEL) $(CFLAGS) +FLDFLAGS = -m$(FUMODEL) + +LDFLAGS2 = + +OBJS = unzip.obj crc32.obj crypt.obj envargs.obj explode.obj \ + extract.obj fileio.obj globals.obj inflate.obj list.obj match.obj \ + process.obj ttyio.obj unreduce.obj unshrink.obj zipinfo.obj \ + msdos.obj $(ASMOBJS) + +OBJX = unzipsfx.obj crc32x.obj cryptx.obj extractx.obj \ + fileiox.obj globalsx.obj inflatex.obj matchx.obj processx.obj \ + ttyiox.obj \ + msdosx.obj $(ASMOBJS) + +OBJF = funzip.obj crc32_.obj crypt_.obj globals_.obj inflate_.obj ttyio_.obj \ + msdos_.obj $(ASMOBJF) + +UNZIP_H = unzip.h unzpriv.h globals.h msdos/doscfg.h + + +default: unzip.exe unzipsfx.exe funzip.exe + +clean: + rem Ignore any errors in the following... + del *.ob + del *.obu + del *.obj + del unzip.exe + del funzip.exe + del unzipsfx.exe + +.asm.obj: + $(AS) $(ASFLAGS) -D$(ASUNMODEL) $*.asm + +.c.obj: + $(CC) -c $(UCFLAGS) $*.c + +crc_i86.obj: msdos/crc_i86.asm + $(AS) $(ASFLAGS) -D$(ASUNMODEL) msdos\crc_i86.asm, $*.obj ; + +crc_i86_.obj: msdos/crc_i86.asm + $(AS) $(ASFLAGS) -D$(ASFUMODEL) msdos\crc_i86.asm, $*.obj ; + +crc32.obj: crc32.c $(UNZIP_H) zip.h crc32.h + +crc32_.obj: crc32.c $(UNZIP_H) zip.h crc32.h + $(CC) -c $(FCFLAGS) -DFUNZIP -ocrc32_.obj crc32.c + +crypt.obj: crypt.c $(UNZIP_H) crypt.h crc32.h ttyio.h zip.h + +crypt_.obj: crypt.c $(UNZIP_H) crypt.h crc32.h ttyio.h zip.h + $(CC) -c $(FCFLAGS) -DFUNZIP -ocrypt_.obj crypt.c + +envargs.obj: envargs.c $(UNZIP_H) + +explode.obj: explode.c $(UNZIP_H) + +extract.obj: extract.c $(UNZIP_H) crc32.h crypt.h + +extractx.obj: extract.c $(UNZIP_H) crc32.h crypt.h + $(CC) -c $(UCFLAGS) -DSFX -oextractx.obj extract.c + +fileio.obj: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h + +funzip.obj: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h + $(CC) -c $(FCFLAGS) funzip.c + +globals.obj: globals.c $(UNZIP_H) + +globals_.obj: globals.c $(UNZIP_H) + $(CC) -c $(FCFLAGS) -DFUNZIP -oglobals_.obj globals.c + +inflate.obj: inflate.c inflate.h $(UNZIP_H) + +inflate_.obj: inflate.c inflate.h $(UNZIP_H) crypt.h + $(CC) -c $(FCFLAGS) -DFUNZIP -oinflate_.obj inflate.c + +list.obj: list.c $(UNZIP_H) + +match.obj: match.c $(UNZIP_H) + +msdos.obj: msdos/msdos.c $(UNZIP_H) + $(CC) -c $(UCFLAGS) msdos/msdos.c + +msdos_.obj: msdos/msdos.c $(UNZIP_H) + $(CC) -c $(FCFLAGS) -DFUNZIP -omsdos_.obj msdos/msdos.c + +msdosx.obj: msdos/msdos.c $(UNZIP_H) + $(CC) -c $(UCFLAGS) -DSFX -omsdos_.obj msdos/msdos.c + +process.obj: process.c $(UNZIP_H) crc32.h + +processx.obj: process.c $(UNZIP_H) crc32.h + $(CC) -c $(UCFLAGS) -DSFX -oprocess_.obj process.c + +ttyio.obj: ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h + +ttyio_.obj: ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h + $(CC) -c $(FCFLAGS) -DFUNZIP -ottyio_.obj ttyio.c + +unreduce.obj: unreduce.c $(UNZIP_H) + +unshrink.obj: unshrink.c $(UNZIP_H) + +unzip.obj: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h + +unzipsfx.obj: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h + $(CC) -c $(UCFLAGS) -DSFX -ounzipsfx.obj unzip.c + +zipinfo.obj: zipinfo.c $(UNZIP_H) + + +# Turbo Make, which cannot deal with the MS-DOS 128-byte limit: +# ------------------------------------------------------------ +unzip.exe: $(OBJS) + rem Ignore any warnings in the following commands: + del *.ob + ren crc32_.obj *.ob + ren crc_i86_.obj *.ob + ren crypt_.obj *.ob + ren extract_.obj *.ob + ren funzip.obj *.ob + ren globals_.obj *.ob + ren inflate_.obj *.ob + ren msdos_.obj *.ob + ren process_.obj *.ob + ren ttyio_.obj *.ob + ren unzipsfx.obj *.ob + $(CC) $(ULDFLAGS) -eunzip.exe *.obj + ren *.ob *.obj + @$(STRIP) unzip.exe + +# GRR 970901 +unzipsfx.exe: $(OBJX) + rem Ignore any warnings in the following commands: + del *.ob + ren crc32_.obj *.ob + ren crc_i86_.obj *.ob + ren crypt_.obj *.ob + ren envargs.obj *.ob + ren explode.obj *.ob + ren extract.obj *.ob + ren funzip.obj *.ob + ren globals_.obj *.ob + ren inflate_.obj *.ob + ren list.obj *.ob + ren msdos.obj *.ob + ren process.obj *.ob + ren ttyio_.obj *.ob + ren unreduce.obj *.ob + ren unshrink.obj *.ob + ren unzip.obj *.ob + ren zipinfo.obj *.ob + $(CC) $(ULDFLAGS) -eunzipsfx.exe *.obj + ren *.ob *.obj + @$(STRIP) unzipsfx.exe + +# better makes that know how to deal with 128-char limit on command line: +# ---------------------------------------------------------------------- +#unzip.exe: $(OBJS) +# $(CC) $(ULDFLAGS) $(OBJS) $(LDFLAGS2) +# @$(STRIP) unzip.exe +# +#unzipsfx.exe: $(OBJX) +# $(CC) $(ULDFLAGS) $(OBJX) $(LDFLAGS2) +# @$(STRIP) unzipsfx.exe + +# both makes: +# ---------- +funzip.exe: $(OBJF) + $(CC) $(FLDFLAGS) $(OBJF) $(LDFLAGS2) + @$(STRIP) funzip.exe diff --git a/msdos/makefile.wat b/msdos/makefile.wat new file mode 100644 index 0000000..39fb83c --- /dev/null +++ b/msdos/makefile.wat @@ -0,0 +1,329 @@ +# WMAKE makefile for 16 bit MSDOS or 32 bit DOS extender (PMODE/W or DOS/4GW) +# using Watcom C/C++ v11.0+, by Paul Kienitz, last revised 16 Feb 2008. +# Makes UnZip.exe, fUnZip.exe, and UnZipSFX.exe. +# +# Invoke from UnZip source dir with "WMAKE -F MSDOS\MAKEFILE.WAT [targets]". +# To make the PMODE/W version use "WMAKE PM=1 ..." +# To make the DOS/4GW version use "WMAKE GW=1 ..." (overrides PM=1) +# Note: specifying PM or GW without NOASM requires that the win32 source +# directory be present, so it can access the 32 bit assembly source. +# PMODE/W is recommended over DOS/4GW for best performance. +# To build with debug info use "WMAKE DEBUG=1 ..." +# To build with no assembly modules use "WMAKE NOASM=1 ..." +# To omit unshrinking support use "WMAKE NO_LZW=1 ..." +# To support unreducing, get the real unreduce.c and go "WMAKE OFFEND_RMS=1 ..." +# To include support for bzip2 decompression (only for 32-bit), get the bzip2 +# source distribution into the bzip2/ subfolder and start compilation +# with "WMAKE PM=1 USEBZ2=1 ..." +# +# Other options to be fed to the compiler can be specified in an environment +# variable called LOCAL_UNZIP. + +variation = $(%LOCAL_UNZIP) + +# Stifle annoying "Delete this file?" questions when errors occur: +.ERASE + +.EXTENSIONS: +.EXTENSIONS: .exe .obj .obx .c .h .asm + +# We maintain multiple sets of object files in different directories so that +# we can compile msdos, dos/4gw, and win32 versions of UnZip without their +# object files interacting. The following var must be a directory name +# ending with a backslash. All object file names must include this macro +# at the beginning, for example "$(O)foo.obj". + +!ifdef GW +PM = 1 # both protected mode formats use the same object files +!endif + +!ifdef DEBUG +! ifdef PM +OBDIR = od32d +! else +OBDIR = od16d +! endif +!else +! ifdef PM +OBDIR = ob32d +! else +OBDIR = ob16d +! endif +!endif +O = $(OBDIR)\ # comment here so backslash won't continue the line + +!ifdef NO_LZW +cvars = $+$(cvars)$- -DLZW_CLEAN +avars = $+$(avars)$- -DLZW_CLEAN +# "$+$(foo)$-" means expand foo as it has been defined up to now; normally, +# this Make defers inner expansion until the outer macro is expanded. +!endif +!ifdef OFFEND_RMS +cvars = $+$(cvars)$- -DUSE_SMITH_CODE +avars = $+$(avars)$- -DUSE_SMITH_CODE +!endif + +IZ_BZIP2 = bzip2 +!ifdef USEBZ2 +!ifdef PM +cvars = $+$(cvars)$- -DUSE_BZIP2 -I$(IZ_BZIP2) +bz2errob = $(O)ubz2err.obj +bz2errox = $(O)ubz2err.obj +BZIPLIB = $(IZ_BZIP2)/$(OBDIR)/bz2.lib +BZ2LNKLIB = lib {$(BZIPLIB)} +!else +bz2errob = +bz2errox = +BZIPLIB = +BZ2LNKLIB = +!endif +!else +bz2errob = +bz2errox = +BZIPLIB = +BZ2LNKLIB = +!endif + +# The assembly hot-spot code in crc_i[3]86.asm is optional. This section +# controls its usage. + +!ifdef NOASM +crcaob = +crcaof = +crcaox = +!else # !NOASM +cvars = $+$(cvars)$- -DASM_CRC +! ifdef PM +crcaob = $(O)crc_i386.obj +crcaof = $(O)crc_i38f.obj +crcaox = $(O)crc_i386.obx +crc_s = win32\crc_i386.asm # requires that the win32 directory be present +! else +crcaob = $(O)crc_i86.obj +crcaof = $(O)crc_i8f.obj +crcaox = $(O)crc_i86.obx +crc_s = msdos\crc_i86.asm +! endif +!endif + +# Our object files: OBJ[A-C] is for UnZip, OBJX for UnZipSFX, OBJF for fUnZip: + +OBJA1 = $(O)unzip.obj $(O)crc32.obj $(crcaob) $(O)crypt.obj $(O)envargs.obj +OBJA = $(OBJA1) $(O)explode.obj $(O)extract.obj $(O)fileio.obj $(O)globals.obj +OBJB2 = $(O)inflate.obj $(O)list.obj $(O)match.obj $(O)process.obj +OBJB = $(OBJB2) $(O)ttyio.obj $(bz2errob) $(O)unreduce.obj +OBJC = $(O)unshrink.obj $(O)zipinfo.obj $(O)msdos.obj + +OBJX2 = $(O)unzip.obx $(O)crc32.obx $(crcaox) $(O)crypt.obx $(O)extract.obx +OBJX1 = $(OBJX2) $(O)fileio.obx $(O)globals.obx $(O)inflate.obx $(O)match.obx +OBJX = $(OBJX1) $(O)process.obx $(bz2errox) $(O)ttyio.obx $(O)msdos.obx + +OBJF1 = $(O)funzip.obj $(O)crc32f.obj $(crcaof) $(O)cryptf.obj $(O)globalsf.obj +OBJF = $(OBJF1) $(O)inflatef.obj $(O)ttyiof.obj $(O)msdosf.obj + +# Common header files included by all C sources: + +UNZIP_H = unzip.h unzpriv.h globals.h msdos\doscfg.h + +# Now we have to pick out the proper compiler and options for it. This gets +# pretty complicated with the PM, GW, DEBUG, and NOASM options... + +link = wlink +asm = wasm + +!ifdef PM +cc = wcc386 +# Use Pentium Pro timings, flat memory, static strings in code, max strictness: +cflags = -bt=DOS -mf -6r -zt -zq -wx +aflags = -bt=DOS -mf -3 -zq +cflagf = $(cflags) +aflagf = $(aflags) +cflagx = $(cflags) +aflagx = $(aflags) + +! ifdef GW +lflags = sys DOS4G +! else +# THIS REQUIRES THAT PMODEW.EXE BE FINDABLE IN THE COMMAND PATH. +# It does NOT require you to add a pmodew entry to wlink.lnk or wlsystem.lnk. +defaultlibs = libpath %WATCOM%\lib386 libpath %WATCOM%\lib386\dos +lflags = format os2 le op osname='PMODE/W' op stub=pmodew.exe $(defaultlibs) +! endif + +!else # plain 16-bit DOS: + +cc = wcc +# Use plain 8086 code, large memory, static strings in code, max strictness: +cflags = -bt=DOS -ml -0 -zt -zq -wx +aflags = -bt=DOS -ml -0 -zq +# for fUnZip, Deflate64 support requires the compact memory model: +cflagf = -bt=DOS -mc -0 -zt -zq -wx +aflagf = -bt=DOS -mc -0 -zq +# for UnZipSFX (without Deflate64 support), use the small memory model: +cflagx = -bt=DOS -ms -0 -zt -zq -wx +aflagx = -bt=DOS -ms -0 -zq +lflags = sys DOS +!endif # !PM + +cvars = $+$(cvars)$- -DMSDOS $(variation) +avars = $+$(avars)$- $(variation) + + +# Specify optimizations, or a nonoptimized debugging version: + +!ifdef DEBUG +cdebug = -od -d2 +cdebux = -od -d2 +ldebug = d w all op symf +!else +! ifdef PM +cdebug = -s -obhikl+rt -oe=100 -zp8 +# -oa helps slightly but might be dangerous. +! else +cdebug = -s -oehiklrt +! endif +cdebux = -s -obhiklrs +ldebug = op el +!endif + +# How to compile sources: +.c.obx: + $(cc) $(cdebux) $(cflagx) $(cvars) -DSFX $[@ -fo=$@ + +.c.obj: + $(cc) $(cdebug) $(cflags) $(cvars) $[@ -fo=$@ + +# Here we go! By default, make all targets, except no UnZipSFX for PMODE: +!ifdef PM +all: UnZip.exe fUnZip.exe +!else +all: UnZip.exe fUnZip.exe UnZipSFX.exe +!endif + +# Convenient shorthand options for single targets: +u: UnZip.exe .SYMBOLIC +f: fUnZip.exe .SYMBOLIC +x: UnZipSFX.exe .SYMBOLIC + +UnZip.exe: $(OBDIR) $(OBJA) $(OBJB) $(OBJC) $(BZIPLIB) + set WLK_VA=file {$(OBJA)} + set WLK_VB=file {$(OBJB)} + set WLK_VC=file {$(OBJC)} $(BZ2LNKLIB) + $(link) $(lflags) $(ldebug) name $@ @WLK_VA @WLK_VB @WLK_VC + set WLK_VA= + set WLK_VB= + set WLK_VC= +# We use WLK_VA/WLK_VB/WLK_VC to keep the size of each command below 256 chars. + +UnZipSFX.exe: $(OBDIR) $(OBJX) $(BZIPLIB) + set WLK_VX=file {$(OBJX)} + $(link) $(lflags) $(ldebug) name $@ @WLK_VX + set WLK_VX= + +fUnZip.exe: $(OBDIR) $(OBJF) + set WLK_VF=file {$(OBJF)} + $(link) $(lflags) $(ldebug) name $@ @WLK_VF + set WLK_VF= + + +# Source dependencies: + +# for UnZip ... + +$(O)crc32.obj: crc32.c $(UNZIP_H) zip.h crc32.h +$(O)crypt.obj: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +$(O)envargs.obj: envargs.c $(UNZIP_H) +$(O)explode.obj: explode.c $(UNZIP_H) +$(O)extract.obj: extract.c $(UNZIP_H) crc32.h crypt.h +$(O)fileio.obj: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +$(O)globals.obj: globals.c $(UNZIP_H) +$(O)inflate.obj: inflate.c inflate.h $(UNZIP_H) +$(O)list.obj: list.c $(UNZIP_H) +$(O)match.obj: match.c $(UNZIP_H) +$(O)process.obj: process.c $(UNZIP_H) crc32.h +$(O)ttyio.obj: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +$(O)ubz2err.obj: ubz2err.c $(UNZIP_H) +$(O)unreduce.obj: unreduce.c $(UNZIP_H) +$(O)unshrink.obj: unshrink.c $(UNZIP_H) +$(O)unzip.obj: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +$(O)zipinfo.obj: zipinfo.c $(UNZIP_H) + +# for UnZipSFX ... + +$(O)crc32.obx: crc32.c $(UNZIP_H) zip.h crc32.h +$(O)crypt.obx: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h +$(O)extract.obx: extract.c $(UNZIP_H) crc32.h crypt.h +$(O)fileio.obx: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +$(O)globals.obx: globals.c $(UNZIP_H) +$(O)inflate.obx: inflate.c inflate.h $(UNZIP_H) +$(O)match.obx: match.c $(UNZIP_H) +$(O)process.obx: process.c $(UNZIP_H) crc32.h +$(O)ttyio.obx: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +$(O)ubz2err.obx: ubz2err.c $(UNZIP_H) +$(O)unzip.obx: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h + +# Special case object files: + +$(O)msdos.obj: msdos\msdos.c $(UNZIP_H) + $(cc) $(cdebug) $(cflags) $(cvars) msdos\msdos.c -fo=$@ + +$(O)msdos.obx: msdos\msdos.c $(UNZIP_H) + $(cc) $(cdebux) $(cflagx) $(cvars) -DSFX msdos\msdos.c -fo=$@ + +!ifndef NOASM +$(crcaob): $(crc_s) + $(asm) $(aflags) $(avars) $(crc_s) -fo=$@ + +$(crcaof): $(crc_s) + $(asm) $(aflagf) $(avars) $(crc_s) -fo=$@ + +$(crcaox): $(crc_s) + $(asm) $(aflagx) $(avars) $(crc_s) -fo=$@ +!endif + +# Variant object files for fUnZip, using $(cflagf): + +$(O)funzip.obj: funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h + $(cc) $(cdebux) $(cflagf) $(cvars) funzip.c -fo=$@ + +$(O)crc32f.obj: crc32.c $(UNZIP_H) zip.h crc32.h + $(cc) $(cdebux) $(cflagf) $(cvars) -DFUNZIP crc32.c -fo=$@ + +$(O)cryptf.obj: crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(cc) $(cdebux) $(cflagf) $(cvars) -DFUNZIP crypt.c -fo=$@ + +$(O)globalsf.obj: globals.c $(UNZIP_H) + $(cc) $(cdebux) $(cflagf) $(cvars) -DFUNZIP globals.c -fo=$@ + +$(O)inflatef.obj: inflate.c inflate.h $(UNZIP_H) crypt.h + $(cc) $(cdebux) $(cflagf) $(cvars) -DFUNZIP inflate.c -fo=$@ + +$(O)ttyiof.obj: ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(cc) $(cdebux) $(cflagf) $(cvars) -DFUNZIP ttyio.c -fo=$@ + +$(O)msdosf.obj: msdos\msdos.c $(UNZIP_H) + $(cc) $(cdebux) $(cflagf) $(cvars) -DFUNZIP msdos\msdos.c -fo=$@ + +# The bzip2 (de)compression library for BZIP2 support: +$(IZ_BZIP2)/$(OBDIR)/bz2.lib : .ALWAYS .RECHECK + $(MAKE) -h -f $(IZ_BZIP2)/makbz2iz.wat CC=$(cc) AR=lib386 & + CFLSYS="$(cdebug) $(cflags)" & + BZROOTDIR=$(IZ_BZIP2) BZOBDIR=$(IZ_BZIP2)/$(OBDIR) + +# Creation of subdirectory for intermediate files +$(OBDIR): + -mkdir $@ + +# Unwanted file removal: + +clean_bz2_lib: .SYMBOLIC + $(MAKE) -h -f $(IZ_BZIP2)/makbz2iz.wat & + BZROOTDIR=$(IZ_BZIP2) BZOBDIR=$(IZ_BZIP2)\$(OBDIR) clean + +clean: clean_bz2_lib .SYMBOLIC + del $(O)*.ob? + +cleaner: clean .SYMBOLIC + del UnZip.exe + del fUnZip.exe + del UnZipSFX.exe diff --git a/msdos/msc51opt.dif b/msdos/msc51opt.dif new file mode 100644 index 0000000..c63fe4a --- /dev/null +++ b/msdos/msc51opt.dif @@ -0,0 +1,62 @@ +Date: Mon, 28 Aug 1995 23:53:23 CET +0100 +From: "Christian Spieler, Institut fuer Kernphysik, Schlossgartenstr. 9, + D-64289 Darmstadt" +Subject: More MSC 5.1 related patches for UnZip 5.20f2 + + +D) I want to suggest two small patches to allow the use of + full optimization (including loop optimization) when compiling UnZip + with MSC (5.1, and probably newer). There are only two small pieces + of code (containing to deeply nested loops) that break MSC 5.1's loop + optimization. I have guarded these loops with "#pragma loop_opt (off)" + to allow loop optimization for the rest of the code. Here are the patches: + +===================== cut here ======================== +diff -c ./inflate.c ./modif/inflate.c +*** ./inflate.c Thu Oct 05 14:57:38 1995 +--- ./modif/inflate.c Thu Oct 05 14:58:24 1995 +*************** +*** 1162,1173 **** +--- 1162,1179 ---- + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; ++ #if defined (MSC) ++ #pragma loop_opt (off) ++ #endif /* MS C compilers */ + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } ++ #if defined (MSC) ++ #pragma loop_opt () ++ #endif /* MS C compilers */ + } + if ((unsigned)w + j > el && (unsigned)w < el) + j = el - w; /* make EOB code end at table */ +diff -c ./zipinfo.c ./modif/zipinfo.c +*** ./zipinfo.c Thu Oct 05 14:51:58 1995 +--- ./modif/zipinfo.c Thu Oct 05 14:52:42 1995 +*************** +*** 1134,1145 **** +--- 1134,1151 ---- + workspace[10] = 'E'; + + p = attribs; ++ #if defined (MSC) && (!defined (_MSC_VER) || _MSC_VER < 600) ++ #pragma loop_opt (off) ++ #endif /* MS C, Version < 6.00 */ + for (k = j = 0; j < 3; ++j) { /* groups of permissions */ + for (i = 0; i < 4; ++i, ++k) /* perms within a group */ + if (workspace[k]) + *p++ = workspace[k]; + *p++ = ','; /* group separator */ + } ++ #if defined (MSC) && (!defined (_MSC_VER) || _MSC_VER < 600) ++ #pragma loop_opt () ++ #endif /* MS C, Version < 6.00 */ + *--p = ' '; /* overwrite last comma */ + if ((p - attribs) < 12) + sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10); diff --git a/msdos/msdos.c b/msdos/msdos.c new file mode 100644 index 0000000..dbd73f5 --- /dev/null +++ b/msdos/msdos.c @@ -0,0 +1,2431 @@ +/* + Copyright (c) 1990-2008 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 +*/ +/*--------------------------------------------------------------------------- + + msdos.c + + MSDOS-specific routines for use with Info-ZIP's UnZip 5.3 and later. + + Contains: Opendir() (from zip) + Readdir() (from zip) + do_wild() + mapattr() + mapname() + maskDOSdevice() + map2fat() + checkdir() + isfloppy() + z_dos_chmod() + volumelabel() (non-djgpp, non-emx) + close_outfile() + stamp_file() (TIMESTAMP only) + prepare_ISO_OEM_translat() + dateformat() + version() + zcalloc() (16-bit, only) + zcfree() (16-bit, only) + _dos_getcountryinfo() (djgpp 1.x, emx) + [_dos_getftime() (djgpp 1.x, emx) to be added] + _dos_setftime() (djgpp 1.x, emx) + _dos_setfileattr() (djgpp 1.x, emx) + _dos_getdrive() (djgpp 1.x, emx) + _dos_creat() (djgpp 1.x, emx) + _dos_close() (djgpp 1.x, emx) + volumelabel() (djgpp, emx) + _dos_getcountryinfo() (djgpp 2.x) + _is_executable() (djgpp 2.x) + __crt0_glob_function() (djgpp 2.x) + __crt0_load_environment_file() (djgpp 2.x) + dos_getcodepage() (all, ASM system call) + screensize() (emx, Watcom 32-bit) + int86x_realmode() (Watcom 32-bit) + stat_bandaid() (Watcom) + + ---------------------------------------------------------------------------*/ + + + +#define UNZIP_INTERNAL +#include "unzip.h" + +/* fUnZip does not need anything from here except the zcalloc() & zcfree() + * function pair (when Deflate64 support is enabled in 16-bit environment). + */ +#ifndef FUNZIP + +static void maskDOSdevice(__GPRO__ char *pathcomp, char *last_dot); +#ifdef MAYBE_PLAIN_FAT + static void map2fat OF((char *pathcomp, char *last_dot)); +#endif +static int isfloppy OF((int nDrive)); +static int z_dos_chmod OF((__GPRO__ ZCONST char *fname, int attributes)); +static int volumelabel OF((ZCONST char *newlabel)); +#if (!defined(SFX) && !defined(WINDLL)) + static int is_running_on_windows OF((void)); +#endif +static int getdoscodepage OF((void)); + +static int created_dir; /* used by mapname(), checkdir() */ +static int renamed_fullpath; /* ditto */ +static unsigned nLabelDrive; /* ditto, plus volumelabel() */ + + + +/*****************************/ +/* Strings used in msdos.c */ +/*****************************/ + +#ifndef SFX + static ZCONST char Far CantAllocateWildcard[] = + "warning: cannot allocate wildcard buffers\n"; +#endif +static ZCONST char Far WarnDirTraversSkip[] = + "warning: skipped \"../\" path component(s) in %s\n"; +static ZCONST char Far Creating[] = " creating: %s\n"; +static ZCONST char Far ConversionFailed[] = + "mapname: conversion of %s failed\n"; +static ZCONST char Far Labelling[] = "labelling %c: %-22s\n"; +static ZCONST char Far ErrSetVolLabel[] = + "mapname: error setting volume label\n"; +static ZCONST char Far PathTooLong[] = "checkdir error: path too long: %s\n"; +static ZCONST char Far CantCreateDir[] = "checkdir error: cannot create %s\n\ + unable to process %s.\n"; +static ZCONST char Far DirIsntDirectory[] = + "checkdir error: %s exists but is not directory\n\ + unable to process %s.\n"; +static ZCONST char Far PathTooLongTrunc[] = + "checkdir warning: path too long; truncating\n %s\n\ + -> %s\n"; +#if (!defined(SFX) || defined(SFX_EXDIR)) + static ZCONST char Far CantCreateExtractDir[] = + "checkdir: cannot create extraction directory: %s\n"; +#endif +static ZCONST char Far AttribsMayBeWrong[] = + "\nwarning: file attributes may not be correct\n"; +#if (!defined(SFX) && !defined(WINDLL)) + static ZCONST char Far WarnUsedOnWindows[] = + "\n%s warning: You are using the MSDOS version on Windows.\n" + "Please try the native Windows version before reporting any problems.\n"; +#endif + + + +/****************************/ +/* Macros used in msdos.c */ +/****************************/ + +#ifdef WATCOMC_386 +# define WREGS(v,r) (v.w.r) +# define int86x int386x + static int int86x_realmode(int inter_no, union REGS *in, + union REGS *out, struct SREGS *seg); +# define F_intdosx(ir,or,sr) int86x_realmode(0x21, ir, or, sr) +# define XXX__MK_FP_IS_BROKEN +#else +# if (defined(__DJGPP__) && (__DJGPP__ >= 2)) +# define WREGS(v,r) (v.w.r) +# else +# define WREGS(v,r) (v.x.r) +# endif +# define F_intdosx(ir,or,sr) intdosx(ir, or, sr) +#endif + +#if (defined(__GO32__) || defined(__EMX__)) +# include /* use readdir() */ +# define MKDIR(path,mode) mkdir(path,mode) +# define Opendir opendir +# define Readdir readdir +# define Closedir closedir +# define zdirent dirent +# define zDIR DIR +# ifdef __EMX__ +# include +# define GETDRIVE(d) d = _getdrive() +# define FA_LABEL A_LABEL +# else +# define GETDRIVE(d) _dos_getdrive(&d) +# endif +# if defined(_A_SUBDIR) /* MSC dos.h and compatibles */ +# define FSUBDIR _A_SUBDIR +# elif defined(FA_DIREC) /* Borland dos.h and compatible variants */ +# define FSUBDIR FA_DIREC +# elif defined(A_DIR) /* EMX dir.h (and dirent.h) */ +# define FSUBDIR A_DIR +# else /* fallback definition */ +# define FSUBDIR 0x10 +# endif +# if defined(_A_VOLID) /* MSC dos.h and compatibles */ +# define FVOLID _A_VOLID +# elif defined(FA_LABEL) /* Borland dos.h and compatible variants */ +# define FVOLID FA_LABEL +# elif defined(A_LABEL) /* EMX dir.h (and dirent.h) */ +# define FVOLID A_LABEL +# else +# define FVOLID 0x08 +# endif +#else /* !(__GO32__ || __EMX__) */ +# define MKDIR(path,mode) mkdir(path) +# ifdef __TURBOC__ +# define FATTR FA_HIDDEN+FA_SYSTEM+FA_DIREC +# define FVOLID FA_LABEL +# define FSUBDIR FA_DIREC +# define FFIRST(n,d,a) findfirst(n,(struct ffblk *)d,a) +# define FNEXT(d) findnext((struct ffblk *)d) +# define GETDRIVE(d) d=getdisk()+1 +# include +# else /* !__TURBOC__ */ +# define FATTR _A_HIDDEN+_A_SYSTEM+_A_SUBDIR +# define FVOLID _A_VOLID +# define FSUBDIR _A_SUBDIR +# define FFIRST(n,d,a) _dos_findfirst(n,a,(struct find_t *)d) +# define FNEXT(d) _dos_findnext((struct find_t *)d) +# define GETDRIVE(d) _dos_getdrive(&d) +# include +# endif /* ?__TURBOC__ */ + typedef struct zdirent { + char d_reserved[30]; + char d_name[13]; + int d_first; + } zDIR; + zDIR *Opendir OF((const char *)); + struct zdirent *Readdir OF((zDIR *)); +# define Closedir free + + + + +#ifndef SFX + +/**********************/ /* Borland C++ 3.x has its own opendir/readdir */ +/* Function Opendir() */ /* library routines, but earlier versions don't, */ +/**********************/ /* so use ours regardless */ + +zDIR *Opendir(name) + const char *name; /* name of directory to open */ +{ + zDIR *dirp; /* malloc'd return value */ + char *nbuf; /* malloc'd temporary string */ + extent len = strlen(name); /* path length to avoid strlens and strcats */ + + + if ((dirp = (zDIR *)malloc(sizeof(zDIR))) == (zDIR *)NULL) + return (zDIR *)NULL; + if ((nbuf = malloc(len + 6)) == (char *)NULL) { + free(dirp); + return (zDIR *)NULL; + } + strcpy(nbuf, name); + if (len > 0) { + if (nbuf[len-1] == ':') { + nbuf[len++] = '.'; + } else if (nbuf[len-1] == '/' || nbuf[len-1] == '\\') + --len; + } + strcpy(nbuf+len, "/*.*"); + Trace((stderr, "Opendir: nbuf = [%s]\n", FnFilter1(nbuf))); + + if (FFIRST(nbuf, dirp, FATTR)) { + free((zvoid *)nbuf); + return (zDIR *)NULL; + } + free((zvoid *)nbuf); + dirp->d_first = 1; + return dirp; +} + + + + + +/**********************/ +/* Function Readdir() */ +/**********************/ + +struct zdirent *Readdir(d) + zDIR *d; /* directory stream from which to read */ +{ + /* Return pointer to first or next directory entry, or NULL if end. */ + + if (d->d_first) + d->d_first = 0; + else + if (FNEXT(d)) + return (struct zdirent *)NULL; + return (struct zdirent *)d; +} + +#endif /* !SFX */ +#endif /* ?(__GO32__ || __EMX__) */ + + + + + +#ifndef SFX + +/************************/ +/* Function do_wild() */ /* identical to OS/2 version */ +/************************/ + +char *do_wild(__G__ wildspec) + __GDEF + ZCONST char *wildspec; /* only used first time on a given dir */ +{ + static zDIR *wild_dir = (zDIR *)NULL; + static ZCONST char *wildname; + static char *dirname, matchname[FILNAMSIZ]; + static int notfirstcall=FALSE, have_dirname, dirnamelen; + char *fnamestart; + struct zdirent *file; + + /* Even when we're just returning wildspec, we *always* do so in + * matchname[]--calling routine is allowed to append four characters + * to the returned string, and wildspec may be a pointer to argv[]. + */ + if (!notfirstcall) { /* first call: must initialize everything */ + notfirstcall = TRUE; + + if (!iswild(wildspec)) { + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + have_dirname = FALSE; + wild_dir = NULL; + return matchname; + } + + /* break the wildspec into a directory part and a wildcard filename */ + if ((wildname = strrchr(wildspec, '/')) == (ZCONST char *)NULL && + (wildname = strrchr(wildspec, ':')) == (ZCONST char *)NULL) { + dirname = "."; + dirnamelen = 1; + have_dirname = FALSE; + wildname = wildspec; + } else { + ++wildname; /* point at character after '/' or ':' */ + dirnamelen = (int)(wildname - wildspec); + if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) { + Info(slide, 1, ((char *)slide, + LoadFarString(CantAllocateWildcard))); + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; /* but maybe filespec was not a wildcard */ + } +/* GRR: can't strip trailing char for opendir since might be "d:/" or "d:" + * (would have to check for "./" at end--let opendir handle it instead) */ + strncpy(dirname, wildspec, dirnamelen); + dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ + have_dirname = TRUE; + } + Trace((stderr, "do_wild: dirname = [%s]\n", FnFilter1(dirname))); + + if ((wild_dir = Opendir(dirname)) != (zDIR *)NULL) { + if (have_dirname) { + strcpy(matchname, dirname); + fnamestart = matchname + dirnamelen; + } else + fnamestart = matchname; + while ((file = Readdir(wild_dir)) != (struct zdirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + strcpy(fnamestart, file->d_name); + if (strrchr(fnamestart, '.') == (char *)NULL) + strcat(fnamestart, "."); + /* 1 == ignore case (for case-insensitive DOS-FS) */ + if (match(fnamestart, wildname, 1 WISEP) && + /* skip "." and ".." directory entries */ + strcmp(fnamestart, ".") && strcmp(fnamestart, "..")) { + Trace((stderr, "do_wild: match() succeeds\n")); + /* remove trailing dot */ + fnamestart += strlen(fnamestart) - 1; + if (*fnamestart == '.') + *fnamestart = '\0'; + return matchname; + } + } + /* if we get to here directory is exhausted, so close it */ + Closedir(wild_dir); + wild_dir = (zDIR *)NULL; + } +#ifdef DEBUG + else { + Trace((stderr, "do_wild: Opendir(%s) returns NULL\n", + FnFilter1(dirname))); + } +#endif /* DEBUG */ + + /* return the raw wildspec in case that works (e.g., directory not + * searchable, but filespec was not wild and file is readable) */ + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (wild_dir == (zDIR *)NULL) { + notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + } + + /* If we've gotten this far, we've read and matched at least one entry + * successfully (in a previous call), so dirname has been copied into + * matchname already. + */ + if (have_dirname) { + /* strcpy(matchname, dirname); */ + fnamestart = matchname + dirnamelen; + } else + fnamestart = matchname; + while ((file = Readdir(wild_dir)) != (struct zdirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + strcpy(fnamestart, file->d_name); + if (strrchr(fnamestart, '.') == (char *)NULL) + strcat(fnamestart, "."); + if (match(fnamestart, wildname, 1 WISEP)) { /* 1 == ignore case */ + Trace((stderr, "do_wild: match() succeeds\n")); + /* remove trailing dot */ + fnamestart += strlen(fnamestart) - 1; + if (*fnamestart == '.') + *fnamestart = '\0'; + return matchname; + } + } + + Closedir(wild_dir); /* have read at least one entry; nothing left */ + wild_dir = (zDIR *)NULL; + notfirstcall = FALSE; /* reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + +} /* end function do_wild() */ + +#endif /* !SFX */ + + + + +/**********************/ +/* Function mapattr() */ +/**********************/ + +int mapattr(__G) + __GDEF +{ + /* set archive bit for file entries (file is not backed up): */ + G.pInfo->file_attr = ((unsigned)G.crec.external_file_attributes | + (G.crec.external_file_attributes & FSUBDIR ? 0 : 32)) & 0xff; + return 0; + +} /* end function mapattr() */ + + + + + +/************************/ +/* Function mapname() */ +/************************/ + +int mapname(__G__ renamed) + __GDEF + int renamed; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - caution (truncated filename) + * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) + * MPN_ERR_SKIP - error -> skip entry + * MPN_ERR_TOOLONG - error -> path is too long + * MPN_NOMEM - error (memory allocation failed) -> skip entry + * [also MPN_VOL_LABEL, MPN_CREATED_DIR] + */ +{ + char pathcomp[FILNAMSIZ]; /* path-component buffer */ + char *pp, *cp=(char *)NULL; /* character pointers */ + char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ +#ifdef MAYBE_PLAIN_FAT + char *last_dot=(char *)NULL; /* last dot not converted to underscore */ +# ifdef USE_LFN + int use_lfn = USE_LFN; /* file system supports long filenames? */ +# endif +#endif + int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ + int error = MPN_OK; + register unsigned workch; /* hold the character being tested */ + + +/*--------------------------------------------------------------------------- + Initialize various pointers and counters and stuff. + ---------------------------------------------------------------------------*/ + + /* can create path as long as not just freshening, or if user told us */ + G.create_dirs = (!uO.fflag || renamed); + + created_dir = FALSE; /* not yet */ + renamed_fullpath = FALSE; + + if (renamed) { + cp = G.filename - 1; /* point to beginning of renamed name... */ + while (*++cp) + if (*cp == '\\') /* convert backslashes to forward */ + *cp = '/'; + cp = G.filename; + /* use temporary rootpath if user gave full pathname */ + if (G.filename[0] == '/') { + renamed_fullpath = TRUE; + pathcomp[0] = '/'; /* copy the '/' and terminate */ + pathcomp[1] = '\0'; + ++cp; + } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') { + renamed_fullpath = TRUE; + pp = pathcomp; + *pp++ = *cp++; /* copy the "d:" (+ '/', possibly) */ + *pp++ = *cp++; + if (*cp == '/') + *pp++ = *cp++; /* otherwise add "./"? */ + *pp = '\0'; + } + } + + /* pathcomp is ignored unless renamed_fullpath is TRUE: */ + if ((error = checkdir(__G__ pathcomp, INIT)) != 0) /* initialize path buf */ + return error; /* ...unless no mem or vol label on hard disk */ + + *pathcomp = '\0'; /* initialize translation buffer */ + pp = pathcomp; /* point to translation buffer */ + if (!renamed) { /* cp already set if renamed */ + if (uO.jflag) /* junking directories */ + cp = (char *)strrchr(G.filename, '/'); + if (cp == (char *)NULL) /* no '/' or not junking dirs */ + cp = G.filename; /* point to internal zipfile-member pathname */ + else + ++cp; /* point to start of last component of path */ + } + +/*--------------------------------------------------------------------------- + Begin main loop through characters in filename. + ---------------------------------------------------------------------------*/ + + while ((workch = (uch)*cp++) != 0) { + + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; +#ifdef MAYBE_PLAIN_FAT + maskDOSdevice(__G__ pathcomp, last_dot); +#else + maskDOSdevice(__G__ pathcomp, NULL); +#endif +#ifdef MAYBE_PLAIN_FAT +# ifdef USE_LFN + if (!use_lfn) +# endif + { + map2fat(pathcomp, last_dot); /* 8.3 trunc. (in place) */ + last_dot = (char *)NULL; + } +#endif + if (strcmp(pathcomp, ".") == 0) { + /* don't bother appending "./" to the path */ + *pathcomp = '\0'; + } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { + /* "../" dir traversal detected, skip over it */ + *pathcomp = '\0'; + killed_ddot = TRUE; /* set "show message" flag */ + } + /* when path component is not empty, append it now */ + if (*pathcomp != '\0' && + ((error = checkdir(__G__ pathcomp, APPEND_DIR)) + & MPN_MASK) > MPN_INF_TRUNC) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ + break; + +#ifdef MAYBE_PLAIN_FAT + case '.': +# ifdef USE_LFN + if (use_lfn) { /* LFN filenames may contain many */ + *pp++ = '.'; /* dots, so simply copy it ... */ + } else +# endif + if (pp == pathcomp && *cp == '.' && cp[1] == '/') { + /* nothing appended yet.., and found "../" */ + *pp++ = '.'; /* add first dot, */ + *pp++ = '.'; /* second dot, and */ + ++cp; /* skip over to the '/' */ + } else { /* found dot within path component */ + last_dot = pp; /* point at last dot so far... */ + *pp++ = '_'; /* convert to underscore for now */ + } + break; +#endif /* MAYBE_PLAIN_FAT */ + + /* drive names are not stored in zipfile, so no colons allowed; + * no brackets or most other punctuation either (all of which + * can appear in Unix-created archives; backslash is particularly + * bad unless all necessary directories exist) */ +#ifdef MAYBE_PLAIN_FAT + case '[': /* these punctuation characters forbidden */ + case ']': /* only on plain FAT file systems */ + case '+': + case ',': + case '=': +# ifdef USE_LFN + if (use_lfn) + *pp++ = (char)workch; + else + *pp++ = '_'; + break; +# endif +#endif + case ':': /* special shell characters of command.com */ + case '\\': /* (device and directory limiters, wildcard */ + case '"': /* characters, stdin/stdout redirection and */ + case '<': /* pipe indicators and the quote sign) are */ + case '>': /* never allowed in filenames on (V)FAT */ + case '|': + case '*': + case '?': + *pp++ = '_'; + break; + + case ';': /* start of VMS version? */ + lastsemi = pp; +#ifdef MAYBE_PLAIN_FAT +# ifdef USE_LFN + if (use_lfn) + *pp++ = ';'; /* keep for now; remove VMS ";##" later */ +# endif +#else + *pp++ = ';'; /* keep for now; remove VMS ";##" later */ +#endif + break; + +#ifdef MAYBE_PLAIN_FAT + case ' ': /* change spaces to underscores */ +# ifdef USE_LFN + if (!use_lfn && uO.sflag) /* only if requested and NO lfn! */ +# else + if (uO.sflag) /* only if requested */ +# endif + *pp++ = '_'; + else + *pp++ = (char)workch; + break; +#endif /* MAYBE_PLAIN_FAT */ + + default: + /* allow ASCII 255 and European characters in filenames: */ + if (isprint(workch) || workch >= 127) + *pp++ = (char)workch; + + } /* end switch */ + } /* end while loop */ + + /* Show warning when stripping insecure "parent dir" path components */ + if (killed_ddot && QCOND2) { + Info(slide, 0, ((char *)slide, LoadFarString(WarnDirTraversSkip), + FnFilter1(G.filename))); + if (!(error & ~MPN_MASK)) + error = (error & MPN_MASK) | PK_WARN; + } + +/*--------------------------------------------------------------------------- + Report if directory was created (and no file to create: filename ended + in '/'), check name to be sure it exists, and combine path and name be- + fore exiting. + ---------------------------------------------------------------------------*/ + + if (G.filename[strlen(G.filename) - 1] == '/') { + checkdir(__G__ G.filename, GETPATH); + if (created_dir) { + if (QCOND2) { + Info(slide, 0, ((char *)slide, LoadFarString(Creating), + FnFilter1(G.filename))); + } + + /* set file attributes: */ + z_dos_chmod(__G__ G.filename, G.pInfo->file_attr); + + /* set dir time (note trailing '/') */ + return (error & ~MPN_MASK) | MPN_CREATED_DIR; + } else if (IS_OVERWRT_ALL) { + /* overwrite attributes of existing directory on user's request */ + + /* set file attributes: */ + z_dos_chmod(__G__ G.filename, G.pInfo->file_attr); + } + /* dir existed already; don't look for data to extract */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + *pp = '\0'; /* done with pathcomp: terminate it */ + + /* if not saving them, remove VMS version numbers (appended ";###") */ + if (!uO.V_flag && lastsemi) { +#ifndef MAYBE_PLAIN_FAT + pp = lastsemi + 1; +#else +# ifdef USE_LFN + if (use_lfn) + pp = lastsemi + 1; + else + pp = lastsemi; /* semi-colon was omitted: expect all #'s */ +# else + pp = lastsemi; /* semi-colon was omitted: expect all #'s */ +# endif +#endif + while (isdigit((uch)(*pp))) + ++pp; + if (*pp == '\0') /* only digits between ';' and end: nuke */ + *lastsemi = '\0'; + } + +#ifdef MAYBE_PLAIN_FAT + maskDOSdevice(__G__ pathcomp, last_dot); +#else + maskDOSdevice(__G__ pathcomp, NULL); +#endif + + if (G.pInfo->vollabel) { + if (strlen(pathcomp) > 11) + pathcomp[11] = '\0'; + } else { +#ifdef MAYBE_PLAIN_FAT +# ifdef USE_LFN + if (!use_lfn) + map2fat(pathcomp, last_dot); /* 8.3 truncation (in place) */ +# else + map2fat(pathcomp, last_dot); /* 8.3 truncation (in place) */ +# endif +#endif + } + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed), + FnFilter1(G.filename))); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + + checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ + checkdir(__G__ G.filename, GETPATH); + + if (G.pInfo->vollabel) { /* set the volume label now */ + if (QCOND2) + Info(slide, 0, ((char *)slide, LoadFarString(Labelling), + (nLabelDrive + 'a' - 1), + FnFilter1(G.filename))); + if (volumelabel(G.filename)) { + Info(slide, 1, ((char *)slide, LoadFarString(ErrSetVolLabel))); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + /* success: skip the "extraction" quietly */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + return error; + +} /* end function mapname() */ + + + + + +/****************************/ +/* Function maskDOSdevice() */ +/****************************/ + +static void maskDOSdevice(__G__ pathcomp, last_dot) + __GDEF + char *pathcomp, *last_dot; +{ +/*--------------------------------------------------------------------------- + Put an underscore in front of the file name if the file name is a + DOS/WINDOWS device name like CON.*, AUX.*, PRN.*, etc. Trying to + extract such a file would fail at best and wedge us at worst. + ---------------------------------------------------------------------------*/ +#if !defined(S_IFCHR) && defined(_S_IFCHR) +# define S_IFCHR _S_IFCHR +#endif +#if !defined(S_ISCHR) +# if defined(_S_ISCHR) +# define S_ISCHR(m) _S_ISCHR(m) +# elif defined(S_IFCHR) +# define S_ISCHR(m) ((m) & S_IFCHR) +# endif +#endif + +#ifdef DEBUG + if (stat(pathcomp, &G.statbuf) == 0) { + Trace((stderr, + "maskDOSdevice() stat(\"%s\", buf) st_mode result: %X, %o\n", + FnFilter1(pathcomp), G.statbuf.st_mode, G.statbuf.st_mode)); + } else { + Trace((stderr, "maskDOSdevice() stat(\"%s\", buf) failed\n", + FnFilter1(pathcomp))); + } +#endif + if (stat(pathcomp, &G.statbuf) == 0 && S_ISCHR(G.statbuf.st_mode)) { + extent i; + + /* pathcomp contains a name of a DOS character device (builtin or + * installed device driver). + * Prepend a '_' to allow creation of the item in the file system. + */ + for (i = strlen(pathcomp) + 1; i > 0; --i) + pathcomp[i] = pathcomp[i - 1]; + pathcomp[0] = '_'; + if (last_dot != (char *)NULL) + last_dot++; + } +} /* end function maskDOSdevice() */ + + + + + +#ifdef MAYBE_PLAIN_FAT + +/**********************/ +/* Function map2fat() */ +/**********************/ + +static void map2fat(pathcomp, last_dot) + char *pathcomp, *last_dot; +{ + char *pEnd = pathcomp + strlen(pathcomp); + +/*--------------------------------------------------------------------------- + Case 1: filename has no dot, so figure out if we should add one. Note + that the algorithm does not try to get too fancy: if there are no dots + already, the name either gets truncated at 8 characters or the last un- + derscore is converted to a dot (only if more characters are saved that + way). In no case is a dot inserted between existing characters. + + GRR: have problem if filename is volume label?? + + ---------------------------------------------------------------------------*/ + + if (last_dot == (char *)NULL) { /* no dots: check for underscores... */ + char *plu = strrchr(pathcomp, '_'); /* pointer to last underscore */ + + if ((plu != (char *)NULL) && /* found underscore: convert to dot? */ + (MIN(plu - pathcomp, 8) + MIN(pEnd - plu - 1, 3) > 8)) { + last_dot = plu; /* be lazy: drop through to next if-block */ + } else if ((pEnd - pathcomp) > 8) + /* no underscore; or converting underscore to dot would save less + chars than leaving everything in the basename */ + pathcomp[8] = '\0'; /* truncate at 8 chars */ + /* else whole thing fits into 8 chars or less: no change */ + } + +/*--------------------------------------------------------------------------- + Case 2: filename has dot in it, so truncate first half at 8 chars (shift + extension if necessary) and second half at three. + ---------------------------------------------------------------------------*/ + + if (last_dot != (char *)NULL) { /* one dot is OK: */ + *last_dot = '.'; /* put the last back in */ + + if ((last_dot - pathcomp) > 8) { + char *p, *q; + int i; + + p = last_dot; + q = last_dot = pathcomp + 8; + for (i = 0; (i < 4) && *p; ++i) /* too many chars in basename: */ + *q++ = *p++; /* shift extension left and */ + *q = '\0'; /* truncate/terminate it */ + } else if ((pEnd - last_dot) > 4) + last_dot[4] = '\0'; /* too many chars in extension */ + /* else filename is fine as is: no change */ + + if ((last_dot - pathcomp) > 0 && last_dot[-1] == ' ') + last_dot[-1] = '_'; /* NO blank in front of '.'! */ + } +} /* end function map2fat() */ + +#endif /* MAYBE_PLAIN_FAT */ + + + + + +/***********************/ +/* Function checkdir() */ +/***********************/ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename + * MPN_INF_SKIP - path doesn't exist, not allowed to create + * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path + * exists and is not a directory, but is supposed to be + * MPN_ERR_TOOLONG - path is too long + * MPN_NOMEM - can't allocate memory for filename buffers + */ +{ + static int rootlen = 0; /* length of rootpath */ + static char *rootpath; /* user's "extract-to" directory */ + static char *buildpath; /* full path (so far) to extracted file */ + static char *end; /* pointer to end of buildpath ('\0') */ +#ifdef MSC + int attrs; /* work around MSC stat() bug */ +#endif + +# define FN_MASK 7 +# define FUNCTION (flag & FN_MASK) + + + +/*--------------------------------------------------------------------------- + APPEND_DIR: append the path component to the path being built and check + for its existence. If doesn't exist and we are creating directories, do + so for this one; else signal success or error as appropriate. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_DIR) { + int too_long = FALSE; + + Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') + ++end; + + /* GRR: could do better check, see if overrunning buffer as we go: + * check end-buildpath after each append, set warning variable if + * within 20 of FILNAMSIZ; then if var set, do careful check when + * appending. Clear variable when begin new path. */ + + if ((end-buildpath) > FILNAMSIZ-3) /* need '/', one-char name, '\0' */ + too_long = TRUE; /* check if extracting directory? */ +#ifdef MSC /* MSC 6.00 bug: stat(non-existent-dir) == 0 [exists!] */ + if (_dos_getfileattr(buildpath, &attrs) || stat(buildpath, &G.statbuf)) +#else + if (SSTAT(buildpath, &G.statbuf)) /* path doesn't exist */ +#endif + { + if (!G.create_dirs) { /* told not to create (freshening) */ + free(buildpath); + /* path doesn't exist: nothing to do */ + return MPN_INF_SKIP; + } + if (too_long) { + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong), + FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + if (MKDIR(buildpath, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir), + FnFilter2(buildpath), FnFilter1(G.filename))); + free(buildpath); + /* path didn't exist, tried to create, failed */ + return MPN_ERR_SKIP; + } + created_dir = TRUE; + } else if (!S_ISDIR(G.statbuf.st_mode)) { + Info(slide, 1, ((char *)slide, LoadFarString(DirIsntDirectory), + FnFilter2(buildpath), FnFilter1(G.filename))); + free(buildpath); + /* path existed but wasn't dir */ + return MPN_ERR_SKIP; + } + if (too_long) { + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong), + FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + *end++ = '/'; + *end = '\0'; + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + return MPN_OK; + + } /* end if (FUNCTION == APPEND_DIR) */ + +/*--------------------------------------------------------------------------- + GETPATH: copy full path to the string pointed at by pathcomp, and free + buildpath. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == GETPATH) { + strcpy(pathcomp, buildpath); + Trace((stderr, "getting and freeing path [%s]\n", + FnFilter1(pathcomp))); + free(buildpath); + buildpath = end = (char *)NULL; + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + APPEND_NAME: assume the path component is the filename; append it and + return without checking for existence. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_NAME) { +#ifdef NOVELL_BUG_WORKAROUND + if (end == buildpath && !G.pInfo->vollabel) { + /* work-around for Novell's "overwriting executables" bug: + prepend "./" to name when no path component is specified */ + *end++ = '.'; + *end++ = '/'; + } +#endif /* NOVELL_BUG_WORKAROUND */ + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') { + ++end; + if ((end-buildpath) >= FILNAMSIZ) { + *--end = '\0'; + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLongTrunc), + FnFilter1(G.filename), FnFilter2(buildpath))); + return MPN_INF_TRUNC; /* filename truncated */ + } + } + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + /* could check for existence here, prompt for new name... */ + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + INIT: allocate and initialize buffer space for the file currently being + extracted. If file was renamed with an absolute path, don't prepend the + extract-to path. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == INIT) { + Trace((stderr, "initializing buildpath to ")); + /* allocate space for full filename, root path, and maybe "./" */ + if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+3)) == + (char *)NULL) + return MPN_NOMEM; + if (G.pInfo->vollabel) { +/* GRR: for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */ + if (renamed_fullpath && pathcomp[1] == ':') + *buildpath = (char)ToLower(*pathcomp); + else if (!renamed_fullpath && rootlen > 1 && rootpath[1] == ':') + *buildpath = (char)ToLower(*rootpath); + else { + GETDRIVE(nLabelDrive); /* assumed that a == 1, b == 2, etc. */ + *buildpath = (char)(nLabelDrive - 1 + 'a'); + } + nLabelDrive = *buildpath - 'a' + 1; /* save for mapname() */ + if (uO.volflag == 0 || *buildpath < 'a' || /* no label/bogus disk */ + (uO.volflag == 1 && !isfloppy(nLabelDrive))) /* -$: no fixed */ + { + free(buildpath); + return MPN_VOL_LABEL; /* skipping with message */ + } + *buildpath = '\0'; + end = buildpath; + } else if (renamed_fullpath) { /* pathcomp = valid data */ + end = buildpath; + while ((*end = *pathcomp++) != '\0') + ++end; + } else if (rootlen > 0) { + strcpy(buildpath, rootpath); + end = buildpath + rootlen; + } else { + *buildpath = '\0'; + end = buildpath; + } + Trace((stderr, "[%s]\n", FnFilter1(buildpath))); + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + ROOT: if appropriate, store the path in rootpath and create it if neces- + sary; else assume it's a zipfile member and return. This path segment + gets used in extracting all members from every zipfile specified on the + command line. Note that under OS/2 and MS-DOS, if a candidate extract-to + directory specification includes a drive letter (leading "x:"), it is + treated just as if it had a trailing '/'--that is, one directory level + will be created if the path doesn't exist, unless this is otherwise pro- + hibited (e.g., freshening). + ---------------------------------------------------------------------------*/ + +#if (!defined(SFX) || defined(SFX_EXDIR)) + if (FUNCTION == ROOT) { + Trace((stderr, "initializing root path to [%s]\n", + FnFilter1(pathcomp))); + if (pathcomp == (char *)NULL) { + rootlen = 0; + return MPN_OK; + } + if (rootlen > 0) /* rootpath was already set, nothing to do */ + return MPN_OK; + if ((rootlen = strlen(pathcomp)) > 0) { + int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE; + char *tmproot; + + if ((tmproot = (char *)malloc(rootlen+3)) == (char *)NULL) { + rootlen = 0; + return MPN_NOMEM; + } + strcpy(tmproot, pathcomp); + if (isalpha((uch)tmproot[0]) && tmproot[1] == ':') + has_drive = TRUE; /* drive designator */ + if (tmproot[rootlen-1] == '/' || tmproot[rootlen-1] == '\\') { + tmproot[--rootlen] = '\0'; + had_trailing_pathsep = TRUE; + } + if (has_drive && (rootlen == 2)) { + if (!had_trailing_pathsep) /* i.e., original wasn't "x:/" */ + add_dot = TRUE; /* relative path: add '.' before '/' */ + } else if (rootlen > 0) { /* need not check "x:." and "x:/" */ +#ifdef MSC + /* MSC 6.00 bug: stat(non-existent-dir) == 0 [exists!] */ + if (_dos_getfileattr(tmproot, &attrs) || + SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) +#else + if (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) +#endif + { + /* path does not exist */ + if (!G.create_dirs /* || iswild(tmproot) */ ) { + free(tmproot); + rootlen = 0; + /* treat as stored file */ + return MPN_INF_SKIP; + } +/* GRR: scan for wildcard characters? OS-dependent... if find any, return 2: + * treat as stored file(s) */ + /* create directory (could add loop here scanning tmproot + * to create more than one level, but really necessary?) */ + if (MKDIR(tmproot, 0777) == -1) { + Info(slide, 1, ((char *)slide, + LoadFarString(CantCreateExtractDir), + FnFilter1(tmproot))); + free(tmproot); + rootlen = 0; + /* path didn't exist, tried to create, failed: */ + /* file exists, or need 2+ subdir levels */ + return MPN_ERR_SKIP; + } + } + } + if (add_dot) /* had just "x:", make "x:." */ + tmproot[rootlen++] = '.'; + tmproot[rootlen++] = '/'; + tmproot[rootlen] = '\0'; + if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) { + free(tmproot); + rootlen = 0; + return MPN_NOMEM; + } + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath))); + } + return MPN_OK; + } +#endif /* !SFX || SFX_EXDIR */ + +/*--------------------------------------------------------------------------- + END: free rootpath, immediately prior to program exit. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == END) { + Trace((stderr, "freeing rootpath\n")); + if (rootlen > 0) { + free(rootpath); + rootlen = 0; + } + return MPN_OK; + } + + return MPN_INVALID; /* should never reach */ + +} /* end function checkdir() */ + + + + + + +/***********************/ +/* Function isfloppy() */ +/***********************/ + +static int isfloppy(nDrive) /* more precisely, is it removable? */ + int nDrive; +{ + union REGS regs; + + regs.h.ah = 0x44; + regs.h.al = 0x08; + regs.h.bl = (uch)nDrive; +#ifdef __EMX__ + _int86(0x21, ®s, ®s); + if (WREGS(regs,flags) & 1) +#else + intdos(®s, ®s); + if (WREGS(regs,cflag)) /* error: do default a/b check instead */ +#endif + { + Trace((stderr, + "error in DOS function 0x44 (AX = 0x%04x): guessing instead...\n", + (unsigned int)(WREGS(regs,ax)))); + return (nDrive == 1 || nDrive == 2)? TRUE : FALSE; + } else + return WREGS(regs,ax)? FALSE : TRUE; +} + + + + +/**************************/ +/* Function z_dos_chmod() */ +/**************************/ + +static int z_dos_chmod(__G__ fname, attributes) + __GDEF + ZCONST char *fname; + int attributes; +{ + char *name; + unsigned fnamelength; + int errv; + + /* set file attributes: + The DOS `chmod' system call requires to mask out the + directory and volume_label attribute bits. + And, a trailing '/' has to be removed from the directory name, + the DOS `chmod' system call does not accept it. */ + fnamelength = strlen(fname); + if (fnamelength > 1 && fname[fnamelength-1] == '/' && + fname[fnamelength-2] != ':' && + (name = (char *)malloc(fnamelength)) != (char *)NULL) { + strncpy(name, fname, fnamelength-1); + name[fnamelength-1] = '\0'; + } else { + name = (char *)fname; + fnamelength = 0; + } + +#if defined(__TURBOC__) || (defined(__DJGPP__) && (__DJGPP__ >= 2)) +# if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0452)) +# define Chmod _rtl_chmod +# else +# define Chmod _chmod +# endif + errv = (Chmod(name, 1, attributes & (~FSUBDIR & ~FVOLID)) != + (attributes & (~FSUBDIR & ~FVOLID))); +# undef Chmod +#else /* !(__TURBOC__ || (__DJGPP__ && __DJGPP__ >= 2)) */ + errv = (_dos_setfileattr(name, attributes & (~FSUBDIR & ~FVOLID)) != 0); +#endif /* ?(__TURBOC__ || (__DJGPP__ && __DJGPP__ >= 2)) */ + if (errv) + Info(slide, 1, ((char *)slide, LoadFarString(AttribsMayBeWrong))); + + if (fnamelength > 0) + free(name); + return errv; +} /* end function z_dos_chmod() */ + + + + +#if (!defined(__GO32__) && !defined(__EMX__)) + +typedef struct dosfcb { + uch flag; /* ff to indicate extended FCB */ + char res[5]; /* reserved */ + uch vattr; /* attribute */ + uch drive; /* drive (1=A, 2=B, ...) */ + uch vn[11]; /* file or volume name */ + char dmmy[5]; + uch nn[11]; /* holds new name if renaming (else reserved) */ + char dmmy2[9]; +} dos_fcb; + +/**************************/ +/* Function volumelabel() */ +/**************************/ + +static int volumelabel(newlabel) + ZCONST char *newlabel; +{ +#ifdef DEBUG + char *p; +#endif + int len = strlen(newlabel); + int fcbseg, dtaseg, fcboff, dtaoff, retv; + dos_fcb fcb, dta, far *pfcb=&fcb, far *pdta=&dta; + struct SREGS sregs; + union REGS regs; + + +/*--------------------------------------------------------------------------- + Label the diskette specified by nLabelDrive using FCB calls. (Old ver- + sions of MS-DOS and OS/2 DOS boxes can't use DOS function 3Ch to create + labels.) Must use far pointers for MSC FP_* macros to work; must pad + FCB filenames with spaces; and cannot include dot in 8th position. May + or may not need to zero out FCBs before using; do so just in case. + ---------------------------------------------------------------------------*/ + +#ifdef WATCOMC_386 + int truseg; + + memset(&sregs, 0, sizeof(sregs)); + memset(®s, 0, sizeof(regs)); + /* PMODE/W does not support extended versions of any dos FCB functions, */ + /* so we have to use brute force, allocating real mode memory for them. */ + regs.w.ax = 0x0100; + regs.w.bx = (2 * sizeof(dos_fcb) + 15) >> 4; /* size in paragraphs */ + int386(0x31, ®s, ®s); /* DPMI allocate DOS memory */ + if (regs.w.cflag) + return DF_MDY; /* no memory, return default */ + truseg = regs.w.dx; /* protected mode selector */ + dtaseg = regs.w.ax; /* real mode paragraph */ + fcboff = 0; + dtaoff = sizeof(dos_fcb); +#ifdef XXX__MK_FP_IS_BROKEN + /* XXX This code may not be trustworthy in general, though it is */ + /* valid with DOS/4GW and PMODE/w, which is all we support for now. */ + regs.w.ax = 6; + regs.w.bx = truseg; + int386(0x31, ®s, ®s); /* convert seg to linear address */ + pfcb = (dos_fcb far *) (((ulg) regs.w.cx << 16) | regs.w.dx); + /* pfcb = (dos_fcb far *) ((ulg) dtaseg << 4); */ + pdta = pfcb + 1; +#else + pfcb = MK_FP(truseg, fcboff); + pdta = MK_FP(truseg, dtaoff); +#endif + _fmemset((char far *)pfcb, 0, 2 * sizeof(dos_fcb)); + /* we pass the REAL MODE paragraph to the dos interrupts: */ + fcbseg = dtaseg; + +#else /* !WATCOMC_386 */ + + memset((char *)&dta, 0, sizeof(dos_fcb)); + memset((char *)&fcb, 0, sizeof(dos_fcb)); + fcbseg = FP_SEG(pfcb); + fcboff = FP_OFF(pfcb); + dtaseg = FP_SEG(pdta); + dtaoff = FP_OFF(pdta); +#endif /* ?WATCOMC_386 */ + +#ifdef DEBUG + for (p = (char *)&dta; (p - (char *)&dta) < sizeof(dos_fcb); ++p) + if (*p) + fprintf(stderr, "error: dta[%d] = %x\n", (p - (char *)&dta), *p); + for (p = (char *)&fcb; (p - (char *)&fcb) < sizeof(dos_fcb); ++p) + if (*p) + fprintf(stderr, "error: fcb[%d] = %x\n", (p - (char *)&fcb), *p); + printf("testing pointer macros:\n"); + segread(&sregs); + printf("cs = %x, ds = %x, es = %x, ss = %x\n", sregs.cs, sregs.ds, sregs.es, + sregs.ss); +#endif /* DEBUG */ + +#if 0 +#ifdef __TURBOC__ + bdosptr(0x1a, dta, DO_NOT_CARE); +#else + (intdosx method below) +#endif +#endif /* 0 */ + + /* set the disk transfer address for subsequent FCB calls */ + sregs.ds = dtaseg; + WREGS(regs,dx) = dtaoff; + Trace((stderr, "segment:offset of pdta = %x:%x\n", dtaseg, dtaoff)); + Trace((stderr, "&dta = %lx, pdta = %lx\n", (ulg)&dta, (ulg)pdta)); + regs.h.ah = 0x1a; + F_intdosx(®s, ®s, &sregs); + + /* fill in the FCB */ + sregs.ds = fcbseg; + WREGS(regs,dx) = fcboff; + pfcb->flag = 0xff; /* extended FCB */ + pfcb->vattr = 0x08; /* attribute: disk volume label */ + pfcb->drive = (uch)nLabelDrive; + +#ifdef DEBUG + Trace((stderr, "segment:offset of pfcb = %x:%x\n", + (unsigned int)(sregs.ds), + (unsigned int)(WREGS(regs,dx)))); + Trace((stderr, "&fcb = %lx, pfcb = %lx\n", (ulg)&fcb, (ulg)pfcb)); + Trace((stderr, "(2nd check: labelling drive %c:)\n", pfcb->drive-1+'A')); + if (pfcb->flag != fcb.flag) + fprintf(stderr, "error: pfcb->flag = %d, fcb.flag = %d\n", + pfcb->flag, fcb.flag); + if (pfcb->drive != fcb.drive) + fprintf(stderr, "error: pfcb->drive = %d, fcb.drive = %d\n", + pfcb->drive, fcb.drive); + if (pfcb->vattr != fcb.vattr) + fprintf(stderr, "error: pfcb->vattr = %d, fcb.vattr = %d\n", + pfcb->vattr, fcb.vattr); +#endif /* DEBUG */ + + /* check for existing label */ + Trace((stderr, "searching for existing label via FCBs\n")); + regs.h.ah = 0x11; /* FCB find first */ +#ifdef WATCOMC_386 + _fstrncpy((char far *)&pfcb->vn, "???????????", 11); +#else + strncpy((char *)fcb.vn, "???????????", 11); /* i.e., "*.*" */ +#endif /* ?WATCOMC_386 */ + Trace((stderr, "fcb.vn = %lx\n", (ulg)fcb.vn)); + Trace((stderr, "regs.h.ah = %x, regs.x.dx = %04x, sregs.ds = %04x\n", + (unsigned int)(regs.h.ah), (unsigned int)(WREGS(regs,dx)), + (unsigned int)(sregs.ds))); + Trace((stderr, "flag = %x, drive = %d, vattr = %x, vn = %s = %s.\n", + fcb.flag, fcb.drive, fcb.vattr, fcb.vn, pfcb->vn)); + F_intdosx(®s, ®s, &sregs); + +/*--------------------------------------------------------------------------- + If not previously labelled, write a new label. Otherwise just rename, + since MS-DOS 2.x has a bug that damages the FAT when the old label is + deleted. + ---------------------------------------------------------------------------*/ + + if (regs.h.al) { + Trace((stderr, "no label found\n\n")); + regs.h.ah = 0x16; /* FCB create file */ +#ifdef WATCOMC_386 + _fstrncpy((char far *)pfcb->vn, newlabel, len); + if (len < 11) + _fstrncpy((char far *)(pfcb->vn+len), " ", 11-len); +#else + strncpy((char *)fcb.vn, newlabel, len); + if (len < 11) /* fill with spaces */ + strncpy((char *)(fcb.vn+len), " ", 11-len); +#endif + Trace((stderr, "fcb.vn = %lx pfcb->vn = %lx\n", (ulg)fcb.vn, + (ulg)pfcb->vn)); + Trace((stderr, "flag = %x, drive = %d, vattr = %x\n", fcb.flag, + fcb.drive, fcb.vattr)); + Trace((stderr, "vn = %s = %s.\n", fcb.vn, pfcb->vn)); + F_intdosx(®s, ®s, &sregs); + regs.h.ah = 0x10; /* FCB close file */ + if (regs.h.al) { + Trace((stderr, "unable to write volume name (AL = %x)\n", + (unsigned int)(regs.h.al))); + F_intdosx(®s, ®s, &sregs); + retv = 1; + } else { + F_intdosx(®s, ®s, &sregs); + Trace((stderr, "new volume label [%s] written\n", newlabel)); + retv = 0; + } + } else { + Trace((stderr, "found old label [%s]\n\n", dta.vn)); /* not term. */ + regs.h.ah = 0x17; /* FCB rename */ +#ifdef WATCOMC_386 + _fstrncpy((char far *)pfcb->vn, (char far *)pdta->vn, 11); + _fstrncpy((char far *)pfcb->nn, newlabel, len); + if (len < 11) + _fstrncpy((char far *)(pfcb->nn+len), " ", 11-len); +#else + strncpy((char *)fcb.vn, (char *)dta.vn, 11); + strncpy((char *)fcb.nn, newlabel, len); + if (len < 11) /* fill with spaces */ + strncpy((char *)(fcb.nn+len), " ", 11-len); +#endif + Trace((stderr, "fcb.vn = %lx pfcb->vn = %lx\n", (ulg)fcb.vn, + (ulg)pfcb->vn)); + Trace((stderr, "fcb.nn = %lx pfcb->nn = %lx\n", (ulg)fcb.nn, + (ulg)pfcb->nn)); + Trace((stderr, "flag = %x, drive = %d, vattr = %x\n", fcb.flag, + fcb.drive, fcb.vattr)); + Trace((stderr, "vn = %s = %s.\n", fcb.vn, pfcb->vn)); + Trace((stderr, "nn = %s = %s.\n", fcb.nn, pfcb->nn)); + F_intdosx(®s, ®s, &sregs); + if (regs.h.al) { + Trace((stderr, "Unable to change volume name (AL = %x)\n", + (unsigned int)(regs.h.al))); + retv = 1; + } else { + Trace((stderr, "volume label changed to [%s]\n", newlabel)); + retv = 0; + } + } +#ifdef WATCOMC_386 + regs.w.ax = 0x0101; /* free dos memory */ + regs.w.dx = truseg; + int386(0x31, ®s, ®s); +#endif + return retv; + +} /* end function volumelabel() */ + +#endif /* !__GO32__ && !__EMX__ */ + + + + + +#if (defined(USE_EF_UT_TIME) || defined(TIMESTAMP)) +/* The following DOS date/time structure is machine-dependent as it + * assumes "little-endian" byte order. For MSDOS-specific code, which + * is run on ix86 CPUs (or emulators), this assumption is valid; but + * care should be taken when using this code as template for other ports. + */ +typedef union { + ulg z_dostime; +# ifdef __TURBOC__ + struct ftime ft; /* system file time record */ +# endif + struct { /* date and time words */ + ush ztime; /* DOS file modification time word */ + ush zdate; /* DOS file modification date word */ + } zft; + struct { /* DOS date/time components bitfield */ + unsigned zt_se : 5; + unsigned zt_mi : 6; + unsigned zt_hr : 5; + unsigned zd_dy : 5; + unsigned zd_mo : 4; + unsigned zd_yr : 7; + } z_dtf; +} dos_fdatetime; +#endif /* USE_EF_UT_TIME || TIMESTAMP */ + + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) + __GDEF + /* + * MS-DOS VERSION + * + * Set the output file date/time stamp according to information from the + * zipfile directory record for this member, then close the file and set + * its permissions (archive, hidden, read-only, system). Aside from closing + * the file, this routine is optional (but most compilers support it). + */ +{ + /* skip restoring time stamps on user's request */ + if (uO.D_flag <= 1) { +#ifdef USE_EF_UT_TIME + dos_fdatetime dos_dt; + iztimes z_utime; + struct tm *t; +#endif /* USE_EF_UT_TIME */ + + +/*--------------------------------------------------------------------------- + Copy and/or convert time and date variables, if necessary; then set + the file time/date. WEIRD BORLAND "BUG": if output is buffered, + and if run under at least some versions of DOS (e.g., 6.0), and if + files are smaller than DOS physical block size (i.e., 512 bytes) (?), + then files MAY NOT get timestamped correctly--apparently setftime() + occurs before any data are written to the file, and when file is + closed and buffers are flushed, timestamp is overwritten with + current time. Even with a 32K buffer, this does not seem to occur + with larger files. UnZip output is now unbuffered, but if it were + not, could still avoid problem by adding "fflush(outfile)" just + before setftime() call. Weird, huh? + ---------------------------------------------------------------------------*/ + +#ifdef USE_EF_UT_TIME + if (G.extra_field && +#ifdef IZ_CHECK_TZ + G.tz_is_valid && +#endif + (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, + G.lrec.last_mod_dos_datetime, &z_utime, NULL) + & EB_UT_FL_MTIME)) + { + TTrace((stderr, "close_outfile: Unix e.f. modif. time = %ld\n", + z_utime.mtime)); + /* round up (down if "up" overflows) to even seconds */ + if (z_utime.mtime & 1) + z_utime.mtime = (z_utime.mtime + 1 > z_utime.mtime) ? + z_utime.mtime + 1 : z_utime.mtime - 1; + TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7 or Macintosh */ + t = localtime(&(z_utime.mtime)); + } else + t = (struct tm *)NULL; + if (t != (struct tm *)NULL) { + if (t->tm_year < 80) { + dos_dt.z_dtf.zt_se = 0; + dos_dt.z_dtf.zt_mi = 0; + dos_dt.z_dtf.zt_hr = 0; + dos_dt.z_dtf.zd_dy = 1; + dos_dt.z_dtf.zd_mo = 1; + dos_dt.z_dtf.zd_yr = 0; + } else { + dos_dt.z_dtf.zt_se = t->tm_sec >> 1; + dos_dt.z_dtf.zt_mi = t->tm_min; + dos_dt.z_dtf.zt_hr = t->tm_hour; + dos_dt.z_dtf.zd_dy = t->tm_mday; + dos_dt.z_dtf.zd_mo = t->tm_mon + 1; + dos_dt.z_dtf.zd_yr = t->tm_year - 80; + } + } else { + dos_dt.z_dostime = G.lrec.last_mod_dos_datetime; + } +# ifdef __TURBOC__ + setftime(fileno(G.outfile), &dos_dt.ft); +# else + _dos_setftime(fileno(G.outfile), dos_dt.zft.zdate, dos_dt.zft.ztime); +# endif +#else /* !USE_EF_UT_TIME */ +# ifdef __TURBOC__ + setftime(fileno(G.outfile), + (struct ftime *)(&(G.lrec.last_mod_dos_datetime))); +# else + _dos_setftime(fileno(G.outfile), + (ush)(G.lrec.last_mod_dos_datetime >> 16), + (ush)(G.lrec.last_mod_dos_datetime)); +# endif +#endif /* ?USE_EF_UT_TIME */ + } + +/*--------------------------------------------------------------------------- + And finally we can close the file...at least everybody agrees on how to + do *this*. I think... Also change the mode according to the stored file + attributes, since we didn't do that when we opened the dude. + ---------------------------------------------------------------------------*/ + + fclose(G.outfile); + + z_dos_chmod(__G__ G.filename, G.pInfo->file_attr); + +} /* end function close_outfile() */ + + + + + +#ifdef TIMESTAMP + +/*************************/ +/* Function stamp_file() */ +/*************************/ + +int stamp_file(fname, modtime) + ZCONST char *fname; + time_t modtime; +{ + dos_fdatetime dos_dt; + time_t t_even; + struct tm *t; + int fd; /* file handle */ + + /* round up (down if "up" overflows) to even seconds */ + t_even = ((modtime + 1 > modtime) ? modtime + 1 : modtime) & (~1); + TIMET_TO_NATIVE(t_even) /* NOP unless MSC 7.0 or Macintosh */ + t = localtime(&t_even); + if (t == (struct tm *)NULL) + return -1; /* time conversion error */ + if (t->tm_year < 80) { + dos_dt.z_dtf.zt_se = 0; + dos_dt.z_dtf.zt_mi = 0; + dos_dt.z_dtf.zt_hr = 0; + dos_dt.z_dtf.zd_dy = 1; + dos_dt.z_dtf.zd_mo = 1; + dos_dt.z_dtf.zd_yr = 0; + } else { + dos_dt.z_dtf.zt_se = t->tm_sec >> 1; + dos_dt.z_dtf.zt_mi = t->tm_min; + dos_dt.z_dtf.zt_hr = t->tm_hour; + dos_dt.z_dtf.zd_dy = t->tm_mday; + dos_dt.z_dtf.zd_mo = t->tm_mon + 1; + dos_dt.z_dtf.zd_yr = t->tm_year - 80; + } + if (((fd = open((char *)fname, 0)) == -1) || +# ifdef __TURBOC__ + (setftime(fd, &dos_dt.ft))) +# else + (_dos_setftime(fd, dos_dt.zft.zdate, dos_dt.zft.ztime))) +# endif + { + if (fd != -1) + close(fd); + return -1; + } + close(fd); + return 0; + +} /* end function stamp_file() */ + +#endif /* TIMESTAMP */ + + + + +void prepare_ISO_OEM_translat(__G) + __GDEF +{ + switch (getdoscodepage()) { + case 437: + case 850: + case 858: +#ifdef IZ_ISO2OEM_ARRAY + iso2oem = iso2oem_850; +#endif +#ifdef IZ_OEM2ISO_ARRAY + oem2iso = oem2iso_850; +#endif + + case 932: /* Japanese */ + case 949: /* Korean */ + case 936: /* Chinese, simple */ + case 950: /* Chinese, traditional */ + case 874: /* Thai */ + case 1258: /* Vietnamese */ +#ifdef IZ_ISO2OEM_ARRAY + iso2oem = NULL; +#endif +#ifdef IZ_OEM2ISO_ARRAY + oem2iso = NULL; +#endif + + default: +#ifdef IZ_ISO2OEM_ARRAY + iso2oem = NULL; +#endif +#ifdef IZ_OEM2ISO_ARRAY + oem2iso = NULL; +#endif + } +} /* end function prepare_ISO_OEM_translat() */ + + + + +#ifndef SFX + +/*************************/ +/* Function dateformat() */ +/*************************/ + +int dateformat() +{ + +/*--------------------------------------------------------------------------- + For those operating systems that support it, this function returns a + value that tells how national convention says that numeric dates are + displayed. Return values are DF_YMD, DF_DMY and DF_MDY (the meanings + should be fairly obvious). + ---------------------------------------------------------------------------*/ + +#ifndef WINDLL + ush CountryInfo[18]; +#if (!defined(__GO32__) && !defined(__EMX__)) + ush far *_CountryInfo = CountryInfo; + struct SREGS sregs; + union REGS regs; +#ifdef WATCOMC_386 + ush seg, para; + + memset(&sregs, 0, sizeof(sregs)); + memset(®s, 0, sizeof(regs)); + /* PMODE/W does not support an extended version of dos function 38, */ + /* so we have to use brute force, allocating real mode memory for it. */ + regs.w.ax = 0x0100; + regs.w.bx = 3; /* 36 bytes rounds up to 48 */ + int386(0x31, ®s, ®s); /* DPMI allocate DOS memory */ + if (regs.w.cflag) + return DF_MDY; /* no memory, return default */ + seg = regs.w.dx; + para = regs.w.ax; + +#ifdef XXX__MK_FP_IS_BROKEN + /* XXX This code may not be trustworthy in general, though it is + * valid with DOS/4GW and PMODE/w, which is all we support for now. */ + /* _CountryInfo = (ush far *) (para << 4); */ /* works for some extenders */ + regs.w.ax = 6; + regs.w.bx = seg; + int386(0x31, ®s, ®s); /* convert seg to linear address */ + _CountryInfo = (ush far *) (((ulg) regs.w.cx << 16) | regs.w.dx); +#else + _CountryInfo = (ush far *) MK_FP(seg, 0); +#endif + + sregs.ds = para; /* real mode paragraph */ + regs.w.dx = 0; /* no offset from segment */ + regs.w.ax = 0x3800; + int86x_realmode(0x21, ®s, ®s, &sregs); + CountryInfo[0] = regs.w.cflag ? 0 : _CountryInfo[0]; + regs.w.ax = 0x0101; + regs.w.dx = seg; + int386(0x31, ®s, ®s); /* DPMI free DOS memory */ + +#else /* !WATCOMC_386 */ + + sregs.ds = FP_SEG(_CountryInfo); + regs.x.dx = FP_OFF(_CountryInfo); + regs.x.ax = 0x3800; + intdosx(®s, ®s, &sregs); +#endif /* ?WATCOMC_386 */ + +#else /* __GO32__ || __EMX__ */ + _dos_getcountryinfo(CountryInfo); +#endif /* ?(__GO32__ || __EMX__) */ + + switch(CountryInfo[0]) { + case 0: + return DF_MDY; + case 1: + return DF_DMY; + case 2: + return DF_YMD; + } +#endif /* !WINDLL */ + + return DF_MDY; /* default for systems without locale info */ + +} /* end function dateformat() */ + + + + +#ifndef WINDLL + +/**************************************/ +/* Function is_running_on_windows() */ +/**************************************/ + +static int is_running_on_windows(void) +{ + char *var = getenv("OS"); + + /* if the OS env.var says 'Windows_NT' then */ + /* we're likely running on a variant of WinNT */ + if ((var != NULL) && (strcmp("Windows_NT", var) == 0)) + return TRUE; + + /* if the windir env.var is non-null then */ + /* we're likely running on a variant of Win9x */ + /* DOS mode of Win9x doesn't define windir, only winbootdir */ + /* NT's command.com can't see lowercase env. vars */ + var = getenv("windir"); + if ((var != NULL) && (var[0] != '\0')) + return TRUE; + + return FALSE; +} + + +/**********************************/ +/* Function check_for_windows() */ +/**********************************/ + +void check_for_windows(ZCONST char *app) +{ +#ifdef SMALL_MEM + char msg_str[160]; /* enough space for two 79-char-lines */ + + (void)zfstrcpy(msg_buf, WarnUsedOnWindows) +#else +# define msg_str WarnUsedOnWindows +#endif + /* Print a warning for users running under Windows */ + /* to reduce bug reports due to running DOS version */ + /* under Windows, when Windows version usually works correctly */ + if (is_running_on_windows()) + printf(msg_str, app); +} /* end function check_for_windows() */ + + +/************************/ +/* Function version() */ +/************************/ + +void version(__G) + __GDEF +{ + int len; +#if defined(__DJGPP__) || defined(__WATCOMC__) || \ + (defined(_MSC_VER) && (_MSC_VER != 800)) + char buf[80]; +#endif + + len = sprintf((char *)slide, LoadFarString(CompiledWith), + +#if defined(__GNUC__) +# if defined(__DJGPP__) + (sprintf(buf, "djgpp v%d.%02d / gcc ", __DJGPP__, __DJGPP_MINOR__), buf), +# elif defined(__GO32__) /* __GO32__ is defined as "1" only (sigh) */ + "djgpp v1.x / gcc ", +# elif defined(__EMX__) /* ...so is __EMX__ (double sigh) */ + "emx+gcc ", +# else + "gcc ", +# endif + __VERSION__, +#elif defined(__WATCOMC__) +# if (__WATCOMC__ % 10 != 0) + "Watcom C/C++", (sprintf(buf, " %d.%02d", __WATCOMC__ / 100, + __WATCOMC__ % 100), buf), +# else + "Watcom C/C++", (sprintf(buf, " %d.%d", __WATCOMC__ / 100, + (__WATCOMC__ % 100) / 10), buf), +# endif +#elif defined(__TURBOC__) +# ifdef __BORLANDC__ + "Borland C++", +# if (__BORLANDC__ < 0x0200) + " 1.0", +# elif (__BORLANDC__ == 0x0200) /* James: __TURBOC__ = 0x0297 */ + " 2.0", +# elif (__BORLANDC__ == 0x0400) + " 3.0", +# elif (__BORLANDC__ == 0x0410) /* __BCPLUSPLUS__ = 0x0310 */ + " 3.1", +# elif (__BORLANDC__ == 0x0452) /* __BCPLUSPLUS__ = 0x0320 */ + " 4.0 or 4.02", +# elif (__BORLANDC__ == 0x0460) /* __BCPLUSPLUS__ = 0x0340 */ + " 4.5", +# elif (__BORLANDC__ == 0x0500) + " 5.0", +# else + " later than 5.0", +# endif +# else + "Turbo C", +# if (__TURBOC__ > 0x0401) /* Kevin: 3.0 -> 0x0401 */ + "++ later than 3.0", +# elif (__TURBOC__ >= 0x0400) + "++ 3.0", +# elif (__TURBOC__ >= 0x0297) /* see remark for Borland C++ 2.0 */ + "++ 2.0", +# elif (__TURBOC__ == 0x0296) /* [662] checked by SPC */ + "++ 1.01", +# elif (__TURBOC__ == 0x0295) /* [661] vfy'd by Kevin */ + "++ 1.0", +# elif (__TURBOC__ == 0x0201) /* Brian: 2.01 -> 0x0201 */ + " 2.01", +# elif ((__TURBOC__ >= 0x018d) && (__TURBOC__ <= 0x0200)) /* James: 0x0200 */ + " 2.0", +# elif (__TURBOC__ > 0x0100) + " 1.5", /* James: 0x0105? */ +# else + " 1.0", /* James: 0x0100 */ +# endif +# endif +#elif defined(MSC) +# if defined(_QC) && !defined(_MSC_VER) + "MS Quick C ", "2.0 or earlier", /* _QC is defined as 1 */ +# elif defined(_QC) && (_MSC_VER == 600) + "MS Quick C ", "2.5 (MSC 6.00)", +# else + "Microsoft C ", +# ifdef _MSC_VER +# if (_MSC_VER == 800) + "8.0/8.0c (Visual C++ 1.0/1.5)", +# else + (sprintf(buf, "%d.%02d", _MSC_VER/100, _MSC_VER%100), buf), +# endif +# else + "5.1 or earlier", +# endif +# endif +#else + "unknown compiler", "", +#endif /* ?compilers */ + + "\nMS-DOS", + +#if (defined(__GNUC__) || defined(WATCOMC_386)) + " (32-bit)", +#else +# if defined(M_I86HM) || defined(__HUGE__) + " (16-bit, huge)", +# elif defined(M_I86LM) || defined(__LARGE__) + " (16-bit, large)", +# elif defined(M_I86MM) || defined(__MEDIUM__) + " (16-bit, medium)", +# elif defined(M_I86CM) || defined(__COMPACT__) + " (16-bit, compact)", +# elif defined(M_I86SM) || defined(__SMALL__) + " (16-bit, small)", +# elif defined(M_I86TM) || defined(__TINY__) + " (16-bit, tiny)", +# else + " (16-bit)", +# endif +#endif + +#ifdef __DATE__ + " on ", __DATE__ +#else + "", "" +#endif + ); + + (*G.message)((zvoid *)&G, slide, (ulg)len, 0); + /* MSC can't handle huge macro expansion */ + + /* temporary debugging code for Borland compilers only */ +#if (defined(__TURBOC__) && defined(DEBUG)) + Info(slide, 0, ((char *)slide, "\tdebug(__TURBOC__ = 0x%04x = %d)\n", + __TURBOC__, __TURBOC__)); +#ifdef __BORLANDC__ + Info(slide, 0, ((char *)slide, "\tdebug(__BORLANDC__ = 0x%04x)\n", + __BORLANDC__)); +#else + Info(slide, 0, ((char *)slide, "\tdebug(__BORLANDC__ not defined)\n")); +#endif +#ifdef __TCPLUSPLUS__ + Info(slide, 0, ((char *)slide, "\tdebug(__TCPLUSPLUS__ = 0x%04x)\n", + __TCPLUSPLUS__)); +#else + Info(slide, 0, ((char *)slide, "\tdebug(__TCPLUSPLUS__ not defined)\n")); +#endif +#ifdef __BCPLUSPLUS__ + Info(slide, 0, ((char *)slide, "\tdebug(__BCPLUSPLUS__ = 0x%04x)\n\n", + __BCPLUSPLUS__)); +#else + Info(slide, 0, ((char *)slide, "\tdebug(__BCPLUSPLUS__ not defined)\n\n")); +#endif +#endif /* __TURBOC__ && DEBUG */ + +} /* end function version() */ + +#endif /* !WINDLL */ +#endif /* !SFX */ + +#endif /* !FUNZIP */ + + + + + +#ifdef MY_ZCALLOC /* Special zcalloc function for MEMORY16 (MSDOS/OS2) */ + +#if defined(__TURBOC__) && !defined(OS2) +#include +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 2 /* reduced from 10 to save space */ +/* 10*64K = 640K */ + +static int next_ptr = 0; + +typedef struct ptr_table_s { + zvoid far *org_ptr; + zvoid far *new_ptr; +} ptr_table; + +static ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +zvoid far *zcalloc(unsigned items, unsigned size) +{ + zvoid far *buf; + ulg bsize = (ulg)items*size; + + if (bsize < (65536L-16L)) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-NULL) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +zvoid zcfree(zvoid far *ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = next_ptr - 1; n >= 0; n--) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + Trace((stderr, "zcfree: ptr not found!\n")); +} +#endif /* __TURBOC__ */ + +#if defined(MSC) || defined(__WATCOMC__) +#if (!defined(_MSC_VER) || (_MSC_VER < 700)) +# define _halloc halloc +# define _hfree hfree +#endif + +zvoid far *zcalloc(unsigned items, unsigned size) +{ + return (zvoid far *)_halloc((long)items, size); +} + +zvoid zcfree(zvoid far *ptr) +{ + _hfree((void huge *)ptr); +} +#endif /* MSC || __WATCOMC__ */ + +#endif /* MY_ZCALLOC */ + + +#ifndef FUNZIP + +#if (defined(__GO32__) || defined(__EMX__)) + +#if (!defined(__DJGPP__) || (__DJGPP__ < 2) || \ + ((__DJGPP__ == 2) && (__DJGPP_MINOR__ < 2))) +int volatile _doserrno; +#endif /* not "djgpp v2.02 or newer" */ + +#if (!defined(__DJGPP__) || (__DJGPP__ < 2)) + +unsigned _dos_getcountryinfo(void *countrybuffer) +{ + asm("movl %0, %%edx": : "g" (countrybuffer)); + asm("movl $0x3800, %eax"); + asm("int $0x21": : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"); + _doserrno = 0; + asm("jnc 1f"); + asm("movl %%eax, %0": "=m" (_doserrno)); + asm("1:"); + return (unsigned)_doserrno; +} + +unsigned _dos_setftime(int fd, unsigned dosdate, unsigned dostime) +{ + asm("movl %0, %%ebx": : "g" (fd)); + asm("movl %0, %%ecx": : "g" (dostime)); + asm("movl %0, %%edx": : "g" (dosdate)); + asm("movl $0x5701, %eax"); + asm("int $0x21": : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"); + _doserrno = 0; + asm("jnc 1f"); + asm("movl %%eax, %0": "=m" (_doserrno)); + errno = EBADF; + asm("1:"); + return (unsigned)_doserrno; +} + +unsigned _dos_setfileattr(const char *name, unsigned attr) +{ +#if 0 /* stripping of trailing '/' is not needed for unzip-internal use */ + unsigned namlen = strlen(name); + char *i_name = alloca(namlen + 1); + + strcpy(i_name, name); + if (namlen > 1 && i_name[namlen-1] == '/' && i_name[namlen-2] != ':') + i_name[namlen-1] = '\0'; + asm("movl %0, %%edx": : "g" (i_name)); +#else + asm("movl %0, %%edx": : "g" (name)); +#endif + asm("movl %0, %%ecx": : "g" (attr)); + asm("movl $0x4301, %eax"); + asm("int $0x21": : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"); + _doserrno = 0; + asm("jnc 1f"); + asm("movl %%eax, %0": "=m" (_doserrno)); + switch (_doserrno) { + case 2: + case 3: + errno = ENOENT; + break; + case 5: + errno = EACCES; + break; + } + asm("1:"); + return (unsigned)_doserrno; +} + +void _dos_getdrive(unsigned *d) +{ + asm("movl $0x1900, %eax"); + asm("int $0x21": : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"); + asm("xorb %ah, %ah"); + asm("incb %al"); + asm("movl %%eax, %0": "=a" (*d)); +} + +unsigned _dos_creat(const char *path, unsigned attr, int *fd) +{ + asm("movl $0x3c00, %eax"); + asm("movl %0, %%edx": :"g" (path)); + asm("movl %0, %%ecx": :"g" (attr)); + asm("int $0x21": : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"); + asm("movl %%eax, %0": "=a" (*fd)); + _doserrno = 0; + asm("jnc 1f"); + _doserrno = *fd; + switch (_doserrno) { + case 3: + errno = ENOENT; + break; + case 4: + errno = EMFILE; + break; + case 5: + errno = EACCES; + break; + } + asm("1:"); + return (unsigned)_doserrno; +} + +unsigned _dos_close(int fd) +{ + asm("movl %0, %%ebx": : "g" (fd)); + asm("movl $0x3e00, %eax"); + asm("int $0x21": : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi"); + _doserrno = 0; + asm("jnc 1f"); + asm ("movl %%eax, %0": "=m" (_doserrno)); + if (_doserrno == 6) { + errno = EBADF; + } + asm("1:"); + return (unsigned)_doserrno; +} + +#endif /* !__DJGPP__ || (__DJGPP__ < 2) */ + + +static int volumelabel(ZCONST char *name) +{ + int fd; + + return _dos_creat(name, FA_LABEL, &fd) ? fd : _dos_close(fd); +} + + +#if (defined(__DJGPP__) && (__DJGPP__ >= 2)) + +#include /* These includes for the country info */ +#include +#include + +/* The above _dos_getcountryinfo function doesn't work with djgpp v2, presumably + * because ds is not set correctly (does it really work at all?). Note that + * this version only sets the date (ie. CountryInfo[0]). + */ +unsigned _dos_getcountryinfo(void *countrybuffer) +{ + __dpmi_regs regs; + + regs.x.ax = 0x3800; + regs.x.dx = __tb & 0x0f; + regs.x.ds = (__tb >> 4) & 0xffff; + _doserrno = __dpmi_int(0x21, ®s); + + *(ush*)countrybuffer = _farpeekw(_dos_ds, __tb & 0xfffff); + + return (unsigned)_doserrno; +} + + +/* Disable determination of "x" bit in st_mode field for [f]stat() calls. */ +int _is_executable (const char *path, int fhandle, const char *ext) +{ + return 0; +} + +#ifndef USE_DJGPP_GLOB +/* Prevent globbing of filenames. This gives the same functionality as + * "stubedit globbing=no" did with DJGPP v1. + */ +char **__crt0_glob_function(char *_arg) +{ + return NULL; +} +#endif /* !USE_DJGPP_GLOB */ + +#ifndef USE_DJGPP_ENV +/* Reduce the size of the executable and remove the functionality to read + * the program's environment from whatever $DJGPP points to. + */ +void __crt0_load_environment_file(char *_app_name) +{ +} +#endif /* !USE_DJGPP_ENV */ + +#endif /* __DJGPP__ >= 2 */ +#endif /* __GO32__ || __EMX__ */ + + + +static int getdoscodepage(void) +{ + union REGS regs; + + WREGS(regs,ax) = 0x6601; +#ifdef __EMX__ + _int86(0x21, ®s, ®s); + if (WREGS(regs,flags) & 1) +#else + intdos(®s, ®s); + if (WREGS(regs,cflag)) +#endif + { + Trace((stderr, + "error in DOS function 0x66 (AX = 0x%04x): default to 850...\n", + (unsigned int)(WREGS(regs,ax)))); + return 858; + } else + return WREGS(regs,bx); +} + + + +#ifdef __EMX__ +#ifdef MORE + +/*************************/ +/* Function screensize() */ +/*************************/ + +int screensize(int *tt_rows, int *tt_cols) +{ + int scr_dimen[2]; /* scr_dimen[0]: columns, src_dimen[1]: rows */ + + _scrsize(scr_dimen); + if (tt_rows != NULL) *tt_rows = scr_dimen[1]; + if (tt_cols != NULL) *tt_cols = scr_dimen[0]; + return 0; +} + +#endif /* MORE */ +#endif /* __EMX__ */ + + + +#ifdef WATCOMC_386 +#ifdef MORE +#include + +/*************************/ +/* Function screensize() */ +/*************************/ + +int screensize(int *tt_rows, int *tt_cols) +{ + struct videoconfig vc; + + _getvideoconfig(&vc); + if (tt_rows != NULL) *tt_rows = (int)(vc.numtextrows); + if (tt_cols != NULL) *tt_cols = (int)(vc.numtextcols); + return 0; +} + +#endif /* MORE */ + + +static struct RMINFO { + ulg edi, esi, ebp; + ulg reserved; + ulg ebx, edx, ecx, eax; + ush flags; + ush es,ds,fs,gs; + ush ip_ignored,cs_ignored; + ush sp,ss; +}; + +/* This function is used to call dos interrupts that may not be supported + * by some particular 32-bit DOS extender. It uses DPMI function 300h to + * simulate a real mode call of the interrupt. The caller is responsible + * for providing real mode addresses of any buffer areas used. The docs + * for PMODE/W imply that this should not be necessary for calling the DOS + * interrupts that it doesn't extend, but it crashes when this isn't used. */ + +static int int86x_realmode(int inter_no, union REGS *in, + union REGS *out, struct SREGS *seg) +{ + union REGS local; + struct SREGS localseg; + struct RMINFO rmi; + int r; + + rmi.eax = in->x.eax; + rmi.ebx = in->x.ebx; + rmi.ecx = in->x.ecx; + rmi.edx = in->x.edx; + rmi.edi = in->x.edi; + rmi.esi = in->x.esi; + rmi.ebp = rmi.reserved = 0L; + rmi.es = seg->es; + rmi.ds = seg->ds; + rmi.fs = seg->fs; + rmi.gs = seg->gs; + rmi.sp = rmi.ss = rmi.ip_ignored = rmi.cs_ignored = rmi.flags = 0; + memset(&local, 0, sizeof(local)); + memset(&localseg, 0, sizeof(localseg)); + local.w.ax = 0x0300; + local.h.bl = inter_no; + local.h.bh = 0; + local.w.cx = 0; + localseg.es = FP_SEG(&rmi); + local.x.edi = FP_OFF(&rmi); + r = int386x(0x31, &local, &local, &localseg); + out->x.eax = rmi.eax; + out->x.ebx = rmi.ebx; + out->x.ecx = rmi.ecx; + out->x.edx = rmi.edx; + out->x.edi = rmi.edi; + out->x.esi = rmi.esi; + out->x.cflag = rmi.flags & INTR_CF; + return r; +} + +#endif /* WATCOMC_386 */ + + + + +#ifdef DOS_STAT_BANDAID + +/* This papers over a bug in Watcom 10.6's standard library...sigh. + * Apparently it applies to both the DOS and Win32 stat()s. */ + +int stat_bandaid(const char *path, struct stat *buf) +{ + char newname[4]; + + if (!stat(path, buf)) + return 0; + else if (!strcmp(path, ".") || (path[0] && !strcmp(path + 1, ":."))) { + strcpy(newname, path); + newname[strlen(path) - 1] = '\\'; /* stat(".") fails for root! */ + return stat(newname, buf); + } else + return -1; +} + +#endif /* DOS_STAT_BANDAID */ + +#endif /* !FUNZIP */ diff --git a/netware/Contents b/netware/Contents new file mode 100644 index 0000000..d22a7d6 --- /dev/null +++ b/netware/Contents @@ -0,0 +1,15 @@ +Contents of the "netware" subdirectory for UnZip 5.53 and later: + + Contents this file + README notes about Novell NetWare port + makefile.wat makefile for compiling unzip.nlm using Watcom C 11.0 + nlmcfg.h OS-dependent configuration, included by unzpriv.h + netware.c OS-dependent UnZip routines for NetWare + unzip.build Korn-shell build script + unzip.link Watcom link directive file + +Notes: + +This port is courtesy of Vance Baarda (Novell NetWare Server Install). +It is designed to compile with the Watcom C compiler. See the README +for further info. diff --git a/netware/README b/netware/README new file mode 100644 index 0000000..0b47d25 --- /dev/null +++ b/netware/README @@ -0,0 +1,66 @@ +1) I used the Watcom version 11 compiler and the Novell NetWare SDK + from October 1998. You can get the latest NetWare SDK (free). Go to + http://developer.novell.com/ndk/netware.htm#C/C++ and look for "NLM and + NetWare Libraries for C (including CLIB and XPlat)" + +2) The unzip.nlm runs in the same address space as the NetWare OS. + In other words, if unzip.nlm crashes, the server will most likely crash. + Therefore, I recommend you do not load unzip.nlm on a server that your + company depends on for business until it's been thoroughly tested on a + test server. + +3) I've designed this unzip.nlm port to load on any version of NetWare + starting with NetWare 3.12. However, I've tested it only on NetWare 5.0. + If unzip.nlm does not load or run correctly, try the following in + this order: + + a) Load clibaux.nlm version 1.21a or later before loading + unzip.nlm. The clibaux.nlm is part of the NetWare SDK package + mentioned above. It's also part of the 3.x C library package + mentioned below. + + b) On NetWare 3.x, install the latest 3.x C library modules. + Go to http://support.novell.com/misc/patlst.htm#nw and look for + "NetWare 3.12/3.2 CLIB". + + c) On NetWare 4.10, install the latest 4.10 C library modules. + Go to http://support.novell.com/misc/patlst.htm#nw and look for + "Updated modular CLIB and DSAPI". + + d) On NetWare 4.11 and 4.2, install the latest support pack. + Go to http://support.novell.com/misc/patlst.htm#nw and look for + "NetWare 4 Support Pack". + +4) This unzip.nlm assumes that support for the long name space (also + known as the OS/2 name space) has already been added to the current + working volume. If it has not, and the zip archive contains files with + long names, then the fopen() for such files will just fail. The code + does not attempt to rename the file to fit in a DOS-style name. The same + problem would occur with long directory names. + +5) If unzip.nlm works correctly on NetWare 3.x (which it should, + but I've not tried it), it will create all files and directories with + all-uppercase names. The reason is that the NetWare 3.x C library does + not support creating mixed-case or lowercase file names, even in the long + (OS/2) name space. + +6) To change the current working volume and current working directory + in which unzip.nlm loads and runs, load unzip.nlm like this: + + load unzip (CLIB_OPT)/P: + + For example: + + load unzip archive.zip (CLIB_OPT)/Pvol1:\usr\home + + For more information on CLIB_OPT, go to http://developer.novell.com/search/ + and enter "CLIB_OPT" in the "Novell Developer Kit Search" box. + +7) To find out more about clibaux.nlm, go to + http://developer.novell.com/search/ and enter "clibaux" in the "Novell + Developer Kit Search" box. + + +Vance Baarda +NetWare Server Install +Novell, Inc. diff --git a/netware/makefile.wat b/netware/makefile.wat new file mode 100644 index 0000000..cce6910 --- /dev/null +++ b/netware/makefile.wat @@ -0,0 +1,143 @@ +#------------------------------------------------------------------------------ +# Makefile for UnZip 5.53 and later Mark Wright and others +# Version: Watcom C 31 Mar 07 +#------------------------------------------------------------------------------ + + +# WARNING: this is a hacked-up version of an ancient (1993) makefile. It will +# not work without modifications to the UnZip 5.3 sources. This makefile is +# (for now) included only for completeness and as a starting point for a real +# Novell Netware NLM port. (This makefile was intended for Netware 3.11.) + + +# Commands to execute before making any target +# Set environment variables for compiler +.BEFORE + @set inc386=\watcom\novh + @set wcg386=\watcom\binp\wcl386.exe + +# Macro definitions +NLMNAME = unzip +DESCRIPTION = unzip utility +VERSION = 5.5.3 +COPYRIGHT = Copyright 1990-2007 Info-ZIP (www.info-zip.org). +SCREENNAME = Info-ZIP's UnZip Utility +CLIBIMP = \watcom\novi\clib.imp +OBJFILE = $NLMNAME.obj +PRELUDE = \watcom\novi\prelude.obj + +# Compile switches +# d2 include full symbolic debugging information +# 5s generate 586 instructions, use stack-based argument-passing conventions +# zdp allows DS register to "peg" it to DGROUP +# zq "quiet" mode +# NLM produce Netware Loadable Module +# DEBUG include debug info + +CC = wcc386 +# COMPILE = wcc386 -zq -d2 -3s -zdp -w4 -DNLM +# COMPILE = wcc386 -zq -d2 -5s -zdp -w4 -DNLM $(LOCAL_UNZIP) +COMPILE = $(CC) -zq -olax -5s -zp1 -ei -ez -ri -w4 -DNLM -DN_PLAT_NLM -U_WIN32 $(LOCAL_UNZIP) +LINK = wlink +DESTDIR = target + +# All .obj files implicitly depend on .c files +.c.obj : + @echo Compiling $[*.c + @$COMPILE $[*.c + + +UNZIP_H = unzip.h unzpriv.h globals.h netware/nlmcfg.h + +crc32.obj: crc32.c $(UNZIP_H) zip.h crc32.h +crypt.obj: crypt.c $(UNZIP_H) crc32.h crypt.h ttyio.h zip.h +envargs.obj: envargs.c $(UNZIP_H) +explode.obj: explode.c $(UNZIP_H) +extract.obj: extract.c $(UNZIP_H) crc32.h crypt.h +fileio.obj: fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +globals.obj: globals.c $(UNZIP_H) +inflate.obj: inflate.c inflate.h $(UNZIP_H) +list.obj: list.c $(UNZIP_H) +match.obj: match.c $(UNZIP_H) +process.obj: process.c $(UNZIP_H) crc32.h +ttyio.obj: ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h +unreduce.obj: unreduce.c $(UNZIP_H) +unshrink.obj: unshrink.c $(UNZIP_H) +unzip.obj: unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +zipinfo.obj: zipinfo.c $(UNZIP_H) + +# individual dependencies and action rules: +#crc_i86.obj: msdos\crc_i86.asm +# $(AS) $(ASFLAGS) -D$(ASUNMODEL) msdos\crc_i86.asm, $@; + +netware.obj: netware/netware.c $(UNZIP_H) + $(CC) -c -A$(UNMODEL) $(CFLAGS) netware/netware.c + + +OBJ01 = unzip.obj +OBJ02 = crc32.obj +OBJ03 = crypt.obj +OBJ04 = envargs.obj +OBJ05 = explode.obj +OBJ06 = extract.obj +OBJ07 = fileio.obj +OBJ08 = globals.obj +OBJ09 = inflate.obj +OBJ10 = list.obj +OBJ11 = match.obj +OBJ12 = process.obj +OBJ13 = ttyio.obj +OBJ14 = unreduce.obj +OBJ15 = unshrink.obj +OBJ16 = zipinfo.obj +OBJ17 = netware.obj +#OBJ18 = $(ASMOBJS) +OBJS = $OBJFILE $OBJ01 $OBJ02 $OBJ03 $OBJ04 $OBJ05 $OBJ06 $OBJ07 $OBJ08 \ + $OBJ09 $OBJ10 $OBJ11 $OBJ12 $OBJ13 $OBJ14 $OBJ15 $OBJ16 $OBJ17 + + +# if .obj or .lnk files are modified, link new .nlm and maybe copy to DESTDIR +$NLMNAME.nlm : $OBJS + @echo Linking... + @$LINK @$NLMNAME +# @echo Copying $[*.nlm to $DESTDIR +# @copy $NLMNAME.nlm $DESTDIR + + +# if makefile is modified, create new linker option file +$NLMNAME.lnk : $NLMNAME.mak + @echo FORMAT NOVELL NLM '$DESCRIPTION' >$NLMNAME.lnk + @echo OPTION THREADNAME '$NLMNAME' >>$NLMNAME.lnk + @echo OPTION SCREENNAME '$SCREENNAME' >>$NLMNAME.lnk + @echo NAME $NLMNAME >>$NLMNAME.lnk + @echo OPTION VERSION=$VERSION >>$NLMNAME.lnk + @echo OPTION COPYRIGHT '$COPYRIGHT' >>$NLMNAME.lnk + @echo DEBUG NOVELL >>$NLMNAME.lnk + @echo DEBUG ALL >>$NLMNAME.lnk + @echo OPTION NODEFAULTLIBS >>$NLMNAME.lnk + @echo OPTION DOSSEG >>$NLMNAME.lnk + @echo OPTION STACK=40000 >>$NLMNAME.lnk + @echo OPTION CASEEXACT >>$NLMNAME.lnk + @echo OPTION PSEUDOPREEMPTION >>$NLMNAME.lnk + @echo OPTION MAP >>$NLMNAME.lnk + @echo FILE $PRELUDE >>$NLMNAME.lnk + @echo FILE $OBJFILE >>$NLMNAME.lnk + @echo FILE $OBJ01 >>$NLMNAME.lnk + @echo FILE $OBJ02 >>$NLMNAME.lnk + @echo FILE $OBJ03 >>$NLMNAME.lnk + @echo FILE $OBJ04 >>$NLMNAME.lnk + @echo FILE $OBJ05 >>$NLMNAME.lnk + @echo FILE $OBJ06 >>$NLMNAME.lnk + @echo FILE $OBJ07 >>$NLMNAME.lnk + @echo FILE $OBJ08 >>$NLMNAME.lnk + @echo FILE $OBJ09 >>$NLMNAME.lnk + @echo FILE $OBJ10 >>$NLMNAME.lnk + @echo FILE $OBJ11 >>$NLMNAME.lnk + @echo FILE $OBJ12 >>$NLMNAME.lnk + @echo FILE $OBJ13 >>$NLMNAME.lnk + @echo FILE $OBJ14 >>$NLMNAME.lnk + @echo FILE $OBJ15 >>$NLMNAME.lnk + @echo FILE $OBJ16 >>$NLMNAME.lnk + @echo FILE $OBJ17 >>$NLMNAME.lnk + @echo MODULE clib >>$NLMNAME.lnk + @echo IMPORT @$CLIBIMP >>$NLMNAME.lnk diff --git a/netware/netware.c b/netware/netware.c new file mode 100644 index 0000000..47061eb --- /dev/null +++ b/netware/netware.c @@ -0,0 +1,915 @@ +/* + Copyright (c) 1990-2007 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2007-Mar-04 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 +*/ +/*--------------------------------------------------------------------------- + + netware.c + + This file implements these functions for a NetWare Loadable Module (NLM): + + Contains: InitUnZipConsole() + do_wild() + mapattr() + mapname() + checkdir() + close_outfile() + stamp_file() + version() + screensize() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" +#include +#include +#include +#include +#include +#include + +#ifdef ACORN_FTYPE_NFS +/* Acorn bits for NFS filetyping */ +typedef struct { + uch ID[2]; + uch size[2]; + uch ID_2[4]; + uch loadaddr[4]; + uch execaddr[4]; + uch attr[4]; +} RO_extra_block; + +#endif /* ACORN_FTYPE_NFS */ + +static int created_dir; /* used in mapname(), checkdir() */ +static int renamed_fullpath; /* ditto */ + + +/*********************************/ +/* Function InitUnZipConsole() */ +/*********************************/ + +void InitUnZipConsole() +{ + unsigned int myHandle = GetNLMHandle(); + unsigned int *activeScreen = + ImportSymbol(myHandle, "activeScreen"); + unsigned int *systemConsoleScreen = + ImportSymbol(myHandle, "systemConsoleScreen"); + void (*pUseAccurateCaseForPaths)(int) = + ImportSymbol(myHandle, "UseAccurateCaseForPaths"); + + if (!activeScreen || !systemConsoleScreen || + *activeScreen == *systemConsoleScreen) + CreateScreen("Info-ZIP UnZip Utility", 0); + else + CreateScreen("System Console", DONT_AUTO_ACTIVATE); + + SetCurrentNameSpace(NW_NS_LONG); + if (pUseAccurateCaseForPaths) + pUseAccurateCaseForPaths(TRUE); + + UnimportSymbol(myHandle, "activeScreen"); + UnimportSymbol(myHandle, "systemConsoleScreen"); + UnimportSymbol(myHandle, "UseAccurateCaseForPaths"); +} + + +/**********************/ +/* Function do_wild() */ /* for porting: dir separator; match(ignore_case) */ +/**********************/ + +char *do_wild(__G__ wildspec) + __GDEF + ZCONST char *wildspec; /* only used first time on a given dir */ +{ + static DIR *wild_dir = (DIR *)NULL; + static ZCONST char *wildname; + static char *dirname, matchname[FILNAMSIZ]; + static int notfirstcall=FALSE, have_dirname, dirnamelen; + struct dirent *file; + + /* Even when we're just returning wildspec, we *always* do so in + * matchname[]--calling routine is allowed to append four characters + * to the returned string, and wildspec may be a pointer to argv[]. + */ + if (!notfirstcall) { /* first call: must initialize everything */ + notfirstcall = TRUE; + + if (!iswild(wildspec)) { + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + have_dirname = FALSE; + dir = NULL; + return matchname; + } + + /* break the wildspec into a directory part and a wildcard filename */ + if ((wildname = strrchr(wildspec, '/')) == (ZCONST char *)NULL) { + dirname = "."; + dirnamelen = 1; + have_dirname = FALSE; + wildname = wildspec; + } else { + ++wildname; /* point at character after '/' */ + dirnamelen = wildname - wildspec; + if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) { + Info(slide, 0x201, ((char *)slide, + "warning: cannot allocate wildcard buffers\n")); + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; /* but maybe filespec was not a wildcard */ + } + strncpy(dirname, wildspec, dirnamelen); + dirname[dirnamelen] = '\0'; /* terminate for strcpy below */ + have_dirname = TRUE; + } + + if ((wild_dir = opendir(dirname)) != (DIR *)NULL) { + while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + if (file->d_name[0] == '.' && wildname[0] != '.') + continue; /* Unix: '*' and '?' do not match leading dot */ + if (match(file->d_name, wildname, 0 WISEP) && /* 0=case sens.*/ + /* skip "." and ".." directory entries */ + strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) { + Trace((stderr, "do_wild: match() succeeds\n")); + if (have_dirname) { + strcpy(matchname, dirname); + strcpy(matchname+dirnamelen, file->d_name); + } else + strcpy(matchname, file->d_name); + return matchname; + } + } + /* if we get to here directory is exhausted, so close it */ + closedir(wild_dir); + wild_dir = (DIR *)NULL; + } + + /* return the raw wildspec in case that works (e.g., directory not + * searchable, but filespec was not wild and file is readable) */ + strncpy(matchname, wildspec, FILNAMSIZ); + matchname[FILNAMSIZ-1] = '\0'; + return matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (wild_dir == (DIR *)NULL) { + notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + } + + /* If we've gotten this far, we've read and matched at least one entry + * successfully (in a previous call), so dirname has been copied into + * matchname already. + */ + while ((file = readdir(wild_dir)) != (struct dirent *)NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + if (file->d_name[0] == '.' && wildname[0] != '.') + continue; /* Unix: '*' and '?' do not match leading dot */ + if (match(file->d_name, wildname, 0 WISEP)) { /* 0 == case sens. */ + Trace((stderr, "do_wild: match() succeeds\n")); + if (have_dirname) { + /* strcpy(matchname, dirname); */ + strcpy(matchname+dirnamelen, file->d_name); + } else + strcpy(matchname, file->d_name); + return matchname; + } + } + + closedir(wild_dir); /* have read at least one entry; nothing left */ + wild_dir = (DIR *)NULL; + notfirstcall = FALSE; /* reset for new wildspec */ + if (have_dirname) + free(dirname); + return (char *)NULL; + +} /* end function do_wild() */ + + +/**********************/ +/* Function mapattr() */ +/**********************/ + +int mapattr(__G) + __GDEF +{ + ulg tmp = G.crec.external_file_attributes; + + G.pInfo->file_attr = 0; + /* initialized to 0 for check in "default" branch below... */ + + switch (G.pInfo->hostnum) { + case AMIGA_: + tmp = (unsigned)(tmp>>17 & 7); /* Amiga RWE bits */ + G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp); + break; + case UNIX_: + case VMS_: + case ACORN_: + case ATARI_: + case ATHEOS_: + case BEOS_: + case QDOS_: + case TANDEM_: + G.pInfo->file_attr = (unsigned)(tmp >> 16); + if (G.pInfo->file_attr != 0 || !G.extra_field) { + return 0; + } else { + /* Some (non-Info-ZIP) implementations of Zip for Unix and + * VMS (and probably others ??) leave 0 in the upper 16-bit + * part of the external_file_attributes field. Instead, they + * store file permission attributes in some extra field. + * As a work-around, we search for the presence of one of + * these extra fields and fall back to the MSDOS compatible + * part of external_file_attributes if one of the known + * e.f. types has been detected. + * Later, we might implement extraction of the permission + * bits from the VMS extra field. But for now, the work-around + * should be sufficient to provide "readable" extracted files. + * (For ASI Unix e.f., an experimental remap from the e.f. + * mode value IS already provided!) + */ + ush ebID; + unsigned ebLen; + uch *ef = G.extra_field; + unsigned ef_len = G.crec.extra_field_length; + int r = FALSE; + + while (!r && ef_len >= EB_HEADSIZE) { + ebID = makeword(ef); + ebLen = (unsigned)makeword(ef+EB_LEN); + if (ebLen > (ef_len - EB_HEADSIZE)) + /* discoverd some e.f. inconsistency! */ + break; + switch (ebID) { + case EF_ASIUNIX: + if (ebLen >= (EB_ASI_MODE+2)) { + G.pInfo->file_attr = + (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE)); + /* force stop of loop: */ + ef_len = (ebLen + EB_HEADSIZE); + break; + } + /* else: fall through! */ + case EF_PKVMS: + /* "found nondecypherable e.f. with perm. attr" */ + r = TRUE; + default: + break; + } + ef_len -= (ebLen + EB_HEADSIZE); + ef += (ebLen + EB_HEADSIZE); + } + if (!r) + return 0; + } + /* fall through! */ + /* all remaining cases: expand MSDOS read-only bit into write perms */ + case FS_FAT_: + /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the + * Unix attributes in the upper 16 bits of the external attributes + * field, just like Info-ZIP's Zip for Unix. We try to use that + * value, after a check for consistency with the MSDOS attribute + * bits (see below). + */ + G.pInfo->file_attr = (unsigned)(tmp >> 16); + /* fall through! */ + case FS_HPFS_: + case FS_NTFS_: + case MAC_: + case TOPS20_: + default: + /* Ensure that DOS subdir bit is set when the entry's name ends + * in a '/'. Some third-party Zip programs fail to set the subdir + * bit for directory entries. + */ + if ((tmp & 0x10) == 0) { + extent fnlen = strlen(G.filename); + if (fnlen > 0 && G.filename[fnlen-1] == '/') + tmp |= 0x10; + } + /* read-only bit --> write perms; subdir bit --> dir exec bit */ + tmp = !(tmp & 1) << 1 | (tmp & 0x10) >> 4; + if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) + /* keep previous G.pInfo->file_attr setting, when its "owner" + * part appears to be consistent with DOS attribute flags! + */ + return 0; + G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp); + break; + } /* end switch (host-OS-created-by) */ + + /* for originating systems with no concept of "group," "other," "system": */ + umask( (int)(tmp=umask(0)) ); /* apply mask to expanded r/w(/x) perms */ + G.pInfo->file_attr &= ~tmp; + + return 0; + +} /* end function mapattr() */ + + + + +/**********************/ +/* Function mapname() */ +/**********************/ + +int mapname(__G__ renamed) + __GDEF + int renamed; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - caution (truncated filename) + * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) + * MPN_ERR_SKIP - error -> skip entry + * MPN_ERR_TOOLONG - error -> path is too long + * MPN_NOMEM - error (memory allocation failed) -> skip entry + * [also MPN_VOL_LABEL, MPN_CREATED_DIR] + */ +{ + char pathcomp[FILNAMSIZ]; /* path-component buffer */ + char *pp, *cp=(char *)NULL; /* character pointers */ + char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ +#ifdef ACORN_FTYPE_NFS + char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ + RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */ +#endif + int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ + int error = MPN_OK; + register unsigned workch; /* hold the character being tested */ + + +/*--------------------------------------------------------------------------- + Initialize various pointers and counters and stuff. + ---------------------------------------------------------------------------*/ + + if (G.pInfo->vollabel) + return MPN_VOL_LABEL; /* can't set disk volume labels in Netware */ + + /* can create path as long as not just freshening, or if user told us */ + G.create_dirs = (!uO.fflag || renamed); + + created_dir = FALSE; /* not yet */ + + /* user gave full pathname: don't prepend rootpath */ + renamed_fullpath = (renamed && (*G.filename == '/')); + + if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM) + return MPN_NOMEM; /* initialize path buffer, unless no memory */ + + *pathcomp = '\0'; /* initialize translation buffer */ + pp = pathcomp; /* point to translation buffer */ + if (uO.jflag) /* junking directories */ + cp = (char *)strrchr(G.filename, '/'); + if (cp == (char *)NULL) /* no '/' or not junking dirs */ + cp = G.filename; /* point to internal zipfile-member pathname */ + else + ++cp; /* point to start of last component of path */ + +/*--------------------------------------------------------------------------- + Begin main loop through characters in filename. + ---------------------------------------------------------------------------*/ + + while ((workch = (uch)*cp++) != 0) { + + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + if (strcmp(pathcomp, ".") == 0) { + /* don't bother appending "./" to the path */ + *pathcomp = '\0'; + } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { + /* "../" dir traversal detected, skip over it */ + *pathcomp = '\0'; + killed_ddot = TRUE; /* set "show message" flag */ + } + /* when path component is not empty, append it now */ + if (*pathcomp != '\0' && + ((error = checkdir(__G__ pathcomp, APPEND_DIR)) + & MPN_MASK) > MPN_INF_TRUNC) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ + break; + + case ';': /* VMS version (or DEC-20 attrib?) */ + lastsemi = pp; + *pp++ = ';'; /* keep for now; remove VMS ";##" */ + break; /* later, if requested */ + +#ifdef ACORN_FTYPE_NFS + case ',': /* NFS filetype extension */ + lastcomma = pp; + *pp++ = ','; /* keep for now; may need to remove */ + break; /* later, if requested */ +#endif + + default: + /* allow European characters in filenames: */ + if (isprint(workch) || (128 <= workch && workch <= 254)) + *pp++ = (char)workch; + } /* end switch */ + + } /* end while loop */ + + /* Show warning when stripping insecure "parent dir" path components */ + if (killed_ddot && QCOND2) { + Info(slide, 0, ((char *)slide, + "warning: skipped \"../\" path component(s) in %s\n", + FnFilter1(G.filename))); + if (!(error & ~MPN_MASK)) + error = (error & MPN_MASK) | PK_WARN; + } + +/*--------------------------------------------------------------------------- + Report if directory was created (and no file to create: filename ended + in '/'), check name to be sure it exists, and combine path and name be- + fore exiting. + ---------------------------------------------------------------------------*/ + + if (G.filename[strlen(G.filename) - 1] == '/') { + checkdir(__G__ G.filename, GETPATH); + if (created_dir) { + if (QCOND2) { + Info(slide, 0, ((char *)slide, " creating: %s\n", + FnFilter1(G.filename))); + } +#if !defined(NO_CHMOD) && !defined(NLM) + /* In NetWare, chmod does not work on directories */ + /* set approx. dir perms (make sure can still read/write in dir) */ + if (chmod(G.filename, (0xffff & G.pInfo->file_attr) | 0700)) + perror("chmod (directory attributes) error"); +#endif + /* set dir time (note trailing '/') */ + return (error & ~MPN_MASK) | MPN_CREATED_DIR; + } + /* dir existed already; don't look for data to extract */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + *pp = '\0'; /* done with pathcomp: terminate it */ + + /* if not saving them, remove VMS version numbers (appended ";###") */ + if (!uO.V_flag && lastsemi) { + pp = lastsemi + 1; + while (isdigit((uch)(*pp))) + ++pp; + if (*pp == '\0') /* only digits between ';' and end: nuke */ + *lastsemi = '\0'; + } + +#ifdef ACORN_FTYPE_NFS + /* translate Acorn filetype information if asked to do so */ + if (uO.acorn_nfs_ext && + (ef_spark = (RO_extra_block *) + getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) + != (RO_extra_block *)NULL) + { + /* file *must* have a RISC OS extra field */ + long ft = (long)makelong(ef_spark->loadaddr); + /*32-bit*/ + if (lastcomma) { + pp = lastcomma + 1; + while (isxdigit((uch)(*pp))) ++pp; + if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */ + } + if ((ft & 1<<31)==0) ft=0x000FFD00; + sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF); + } +#endif /* ACORN_FTYPE_NFS */ + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", + FnFilter1(G.filename))); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + + checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ + checkdir(__G__ G.filename, GETPATH); + + return error; + +} /* end function mapname() */ + + + + +/***********************/ +/* Function checkdir() */ +/***********************/ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename + * MPN_INF_SKIP - path doesn't exist, not allowed to create + * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path + * exists and is not a directory, but is supposed to be + * MPN_ERR_TOOLONG - path is too long + * MPN_NOMEM - can't allocate memory for filename buffers + */ +{ + static int rootlen = 0; /* length of rootpath */ + static char *rootpath; /* user's "extract-to" directory */ + static char *buildpath; /* full path (so far) to extracted file */ + static char *end; /* pointer to end of buildpath ('\0') */ + +# define FN_MASK 7 +# define FUNCTION (flag & FN_MASK) + + +/*--------------------------------------------------------------------------- + APPEND_DIR: append the path component to the path being built and check + for its existence. If doesn't exist and we are creating directories, do + so for this one; else signal success or error as appropriate. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_DIR) { + int too_long = FALSE; +#ifdef SHORT_NAMES + char *old_end = end; +#endif + + Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') + ++end; +#ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ + if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ + *(end = old_end + FILENAME_MAX) = '\0'; +#endif + + /* GRR: could do better check, see if overrunning buffer as we go: + * check end-buildpath after each append, set warning variable if + * within 20 of FILNAMSIZ; then if var set, do careful check when + * appending. Clear variable when begin new path. */ + + if ((end-buildpath) > FILNAMSIZ-3) /* need '/', one-char name, '\0' */ + too_long = TRUE; /* check if extracting directory? */ + if (stat(buildpath, &G.statbuf)) { /* path doesn't exist */ + if (!G.create_dirs) { /* told not to create (freshening) */ + free(buildpath); + /* path doesn't exist: nothing to do */ + return MPN_INF_SKIP; + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", + FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + if (mkdir(buildpath) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, + "checkdir error: cannot create %s\n\ + unable to process %s.\n", + FnFilter2(buildpath), FnFilter1(G.filename))); + free(buildpath); + /* path didn't exist, tried to create, failed */ + return MPN_ERR_SKIP; + } + created_dir = TRUE; + } else if (!S_ISDIR(G.statbuf.st_mode)) { + Info(slide, 1, ((char *)slide, + "checkdir error: %s exists but is not directory\n\ + unable to process %s.\n", + FnFilter2(buildpath), FnFilter1(G.filename))); + free(buildpath); + /* path existed but wasn't dir */ + return MPN_ERR_SKIP; + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", FnFilter1(buildpath))); + free(buildpath); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + *end++ = '/'; + *end = '\0'; + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + return MPN_OK; + + } /* end if (FUNCTION == APPEND_DIR) */ + +/*--------------------------------------------------------------------------- + GETPATH: copy full path to the string pointed at by pathcomp, and free + buildpath. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == GETPATH) { + strcpy(pathcomp, buildpath); + Trace((stderr, "getting and freeing path [%s]\n", + FnFilter1(pathcomp))); + free(buildpath); + buildpath = end = (char *)NULL; + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + APPEND_NAME: assume the path component is the filename; append it and + return without checking for existence. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_NAME) { +#ifdef SHORT_NAMES + char *old_end = end; +#endif + + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); + while ((*end = *pathcomp++) != '\0') { + ++end; +#ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ + if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ + *(end = old_end + FILENAME_MAX) = '\0'; +#endif + if ((end-buildpath) >= FILNAMSIZ) { + *--end = '\0'; + Info(slide, 0x201, ((char *)slide, + "checkdir warning: path too long; truncating\n\ + %s\n -> %s\n", + FnFilter1(G.filename), FnFilter2(buildpath))); + return MPN_INF_TRUNC; /* filename truncated */ + } + } + Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath))); + /* could check for existence here, prompt for new name... */ + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + INIT: allocate and initialize buffer space for the file currently being + extracted. If file was renamed with an absolute path, don't prepend the + extract-to path. + ---------------------------------------------------------------------------*/ + +/* GRR: for VMS and TOPS-20, add up to 13 to strlen */ + + if (FUNCTION == INIT) { + Trace((stderr, "initializing buildpath to ")); +#ifdef ACORN_FTYPE_NFS + if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+ + (uO.acorn_nfs_ext ? 5 : 1))) +#else + if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1)) +#endif + == (char *)NULL) + return MPN_NOMEM; + if ((rootlen > 0) && !renamed_fullpath) { + strcpy(buildpath, rootpath); + end = buildpath + rootlen; + } else { + *buildpath = '\0'; + end = buildpath; + } + Trace((stderr, "[%s]\n", FnFilter1(buildpath))); + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + ROOT: if appropriate, store the path in rootpath and create it if neces- + sary; else assume it's a zipfile member and return. This path segment + gets used in extracting all members from every zipfile specified on the + command line. + ---------------------------------------------------------------------------*/ + +#if (!defined(SFX) || defined(SFX_EXDIR)) + if (FUNCTION == ROOT) { + Trace((stderr, "initializing root path to [%s]\n", + FnFilter1(pathcomp))); + if (pathcomp == (char *)NULL) { + rootlen = 0; + return MPN_OK; + } + if ((rootlen = strlen(pathcomp)) > 0) { + if (pathcomp[rootlen-1] == '/') { + pathcomp[--rootlen] = '\0'; + } + if (rootlen > 0 && (stat(pathcomp, &G.statbuf) || + !S_ISDIR(G.statbuf.st_mode))) /* path does not exist */ + { + if (!G.create_dirs /* || iswild(pathcomp) */ ) { + rootlen = 0; + /* skip (or treat as stored file) */ + return MPN_INF_SKIP; + } + /* create the directory (could add loop here to scan pathcomp + * and create more than one level, but why really necessary?) */ + if (mkdir(pathcomp) == -1) { + Info(slide, 1, ((char *)slide, + "checkdir: cannot create extraction directory: %s\n", + FnFilter1(pathcomp))); + rootlen = 0; + /* path didn't exist, tried to create, and failed: */ + /* file exists, or 2+ subdirectory levels required */ + return MPN_ERR_SKIP; + } + } + if ((rootpath = (char *)malloc(rootlen+2)) == (char *)NULL) { + rootlen = 0; + return MPN_NOMEM; + } + strcpy(rootpath, pathcomp); + rootpath[rootlen++] = '/'; + rootpath[rootlen] = '\0'; + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath))); + } + return MPN_OK; + } +#endif /* !SFX || SFX_EXDIR */ + +/*--------------------------------------------------------------------------- + END: free rootpath, immediately prior to program exit. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == END) { + Trace((stderr, "freeing rootpath\n")); + if (rootlen > 0) { + free(rootpath); + rootlen = 0; + } + return MPN_OK; + } + + return MPN_INVALID; /* should never reach */ + +} /* end function checkdir() */ + + + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) /* GRR: change to return PK-style warning level */ + __GDEF +{ + fclose(G.outfile); + + /* skip restoring time stamps on user's request */ + if (uO.D_flag <= 1) { + WORD date = G.lrec.last_mod_dos_datetime >> 16; + WORD time = G.lrec.last_mod_dos_datetime & 0xffff; + static struct ModifyStructure changeBuffer; + + /* set the file's access and modification times */ + changeBuffer.MLastAccessedDate = date; + changeBuffer.MLastUpdatedDate = date; + changeBuffer.MLastUpdatedTime = time; + if (ChangeDirectoryEntry(G.filename, &changeBuffer, + MLastAccessedDateBit | MLastUpdatedDateBit | MLastUpdatedTimeBit, + 0)) + { + if (uO.qflag) + Info(slide, 0x201, ((char *)slide, + "warning: cannot set times for %s\n", + FnFilter1(G.filename))); + else + Info(slide, 0x201, ((char *)slide, + " (warning) cannot set times")); + } + } + +/*--------------------------------------------------------------------------- + Change the file permissions from default ones to those stored in the + zipfile. + ---------------------------------------------------------------------------*/ + + if (chmod(G.filename, 0xffff & G.pInfo->file_attr)) + perror("chmod (file attributes) error"); + +} /* end function close_outfile() */ + + +#ifdef TIMESTAMP + +/***************************/ +/* Function stamp_file() */ +/***************************/ + +int stamp_file(fname, modtime) + ZCONST char *fname; + time_t modtime; +{ + ztimbuf tp; + + tp.modtime = tp.actime = modtime; + return (utime(fname, &tp)); + +} /* end function stamp_file() */ + +#endif /* TIMESTAMP */ + + +/************************/ +/* Function version() */ +/************************/ + +void version(__G) + __GDEF +{ + int len; +#if defined(__IBMC__) || defined(__WATCOMC__) || defined(_MSC_VER) + char buf[80]; +#endif + + len = sprintf((char *)slide, LoadFarString(CompiledWith), + +#if defined(__GNUC__) +# ifdef __EMX__ /* __EMX__ is defined as "1" only (sigh) */ + "emx+gcc ", __VERSION__, +# else + "gcc/2 ", __VERSION__, +# endif +#elif defined(__WATCOMC__) + "Watcom C", (sprintf(buf, " (__WATCOMC__ = %d)", __WATCOMC__), buf), +#elif defined(__TURBOC__) +# ifdef __BORLANDC__ + "Borland C++", +# if (__BORLANDC__ < 0x0460) + " 1.0", +# elif (__BORLANDC__ == 0x0460) + " 1.5", /* from Kai Uwe: three less than DOS */ +# else + " 2.0", /* (__BORLANDC__ == 0x0500)? */ +# endif +# else + "Turbo C", /* these are probably irrelevant */ +# if (__TURBOC__ >= 661) + "++ 1.0 or later", +# elif (__TURBOC__ == 661) + " 3.0?", +# elif (__TURBOC__ == 397) + " 2.0", +# else + " 1.0 or 1.5?", +# endif +# endif +#elif defined(MSC) + "Microsoft C ", +# ifdef _MSC_VER + (sprintf(buf, "%d.%02d", _MSC_VER/100, _MSC_VER%100), buf), +# else + "5.1 or earlier", +# endif +#else + "unknown compiler", "", +#endif /* ?compilers */ + + "NetWare", + " (32-bit)", + +#ifdef __DATE__ + " on ", __DATE__ +#else + "", "" +#endif + ); + + (*G.message)((zvoid *)&G, slide, (ulg)len, 0); + /* MSC can't handle huge macro expansions */ + +} /* end function version() */ + + +#ifdef MORE + +/*************************/ +/* Function screensize() */ +/*************************/ + +int screensize(int *tt_rows, int *tt_cols) +{ + WORD height; + WORD width; + + if (GetSizeOfScreen(&height, &width) == 0) { + if (tt_rows != NULL) *tt_rows = height; + if (tt_cols != NULL) *tt_cols = width; + return 0; /* signal success */ + } else { + if (tt_rows != NULL) *tt_rows = 25; + if (tt_cols != NULL) *tt_cols = 80; + return 1; /* signal failure */ + } +} + +#endif /* MORE */ diff --git a/netware/nlm_EOL.pat b/netware/nlm_EOL.pat new file mode 100644 index 0000000..2ae7f95 --- /dev/null +++ b/netware/nlm_EOL.pat @@ -0,0 +1,82 @@ +diff -rc2 ./fileio.c e:fileio.c +*** ./fileio.c Sat Dec 4 19:58:26 1999 +--- e:fileio.c Sat Dec 4 20:54:10 1999 +*************** +*** 85,88 **** +--- 85,91 ---- + (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len)) + #else /* !WINDLL */ ++ #ifdef NLM ++ # define WriteError(buf,len,strm) nlm_WriteError(buf, (extent)(len), strm) ++ #else /* !NLM */ + # ifdef USE_FWRITE + # define WriteError(buf,len,strm) \ +*************** +*** 92,95 **** +--- 95,99 ---- + ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len)) + # endif ++ #endif /* ?NLM */ + #endif /* ?WINDLL */ + +diff -rc2 ./netware/nlmcfg.h e:netware/nlmcfg.h +*** ./netware/nlmcfg.h Sat Dec 4 20:39:20 1999 +--- e:netware/nlmcfg.h Sat Dec 4 21:20:36 1999 +*************** +*** 21,25 **** + # define lenEOL 2 + # define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);} +- # define USE_FWRITE /* write() fails to support textmode output */ + # if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) + # define TIMESTAMP +--- 21,24 ---- +*************** +*** 30,32 **** +--- 29,32 ---- + void InitUnZipConsole OF((void)); + int screenlines OF((void)); ++ int nlm_WriteError OF((uch *buf, extent len, FILE *strm)); + #endif /* NLM */ +diff -rc2 ./netware/netware.c e:netware/netware.c +*** ./netware/netware.c Sat Dec 4 21:11:52 1999 +--- e:netware/netware.c Sat Dec 4 21:28:38 1999 +*************** +*** 22,25 **** +--- 22,26 ---- + version() + screenlines() ++ nlm_WriteError() + + ---------------------------------------------------------------------------*/ +*************** +*** 821,822 **** +--- 822,850 ---- + + #endif /* MORE */ ++ ++ ++ /*******************************/ ++ /* Function nlm_WriteError() */ ++ /*******************************/ ++ ++ int nlm_WriteError(buf, len, strm) ++ uch *buf; ++ extent len; ++ FILE *strm; ++ { ++ /* The write() implementation in the Novell C RTL lacks support of ++ text-mode streams (fails to translate '\n' into "CR-LF" when ++ writing to text-mode channels like the console). ++ In contrast, fwrite() takes into account when an output stream ++ was opened in text-mode, but fails to handle output of large ++ buffers correctly. ++ So, we have to use Unix I/O style write() when emitting data ++ to "regular" files but switch over to stdio's fwrite() when ++ writing to the console streams. ++ */ ++ if ((strm == stdout)) || (file == stderr)) { ++ return ((extent)fwrite((char *)buf, 1, len, strm) != len); ++ } else { ++ return ((extent)write(fileno(strm), (char *)buf, len) != len); ++ } ++ } /* end function nlm_WriteError() */ diff --git a/netware/nlmcfg.h b/netware/nlmcfg.h new file mode 100644 index 0000000..c6271e4 --- /dev/null +++ b/netware/nlmcfg.h @@ -0,0 +1,33 @@ +/* + 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 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 +*/ +#ifdef NLM +# include +# include +# include +# include +# include +# include +# define DIRENT +# include +# ifndef DATE_FORMAT +# define DATE_FORMAT DF_MDY +# endif +# define lenEOL 2 +# define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);} +# define USE_FWRITE /* write() fails to support textmode output */ +# if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) +# define TIMESTAMP +# endif +# define MAIN main +# define DECLARE_TIMEZONE +# define SCREENWIDTH 80 +# define SCREENSIZE(scrrows, scrcols) screensize(scrrows, scrcols) + void InitUnZipConsole OF((void)); + int screensize OF((int *tt_rows, int *tt_cols)); +#endif /* NLM */ diff --git a/netware/unzip.build b/netware/unzip.build new file mode 100644 index 0000000..700767f --- /dev/null +++ b/netware/unzip.build @@ -0,0 +1,17 @@ +export WATCOM='\\prv-dev2\dev\tool\wcc\1100' +CC='\\prv-dev2\dev\tool\wcc\1100\binnt\wcc386' +LINK='\\prv-dev2\dev\tool\wcc\1100\binnt\wlink' + +CFLAGS="-olax -5s -zq -zp1 -ei -ez -ri -w4" +DEFS="-DNLM -DN_PLAT_NLM -U_WIN32" +INCS='-I. -Inetware -Ic:\novell\ndk\nwsdk\include\nlm -Ic:\novell\ndk\nwsdk\include\nlm\sys -Ic:\novell\ndk\nwsdk\include -Ic:\novell\ndk\nwsdk\include\nlm\nit' + +cd .. +for i in crc32.c crypt.c envargs.c explode.c extract.c fileio.c \ + globals.c inflate.c list.c match.c netware\\netware.c process.c \ + ttyio.c unreduce.c unshrink.c unzip.c zipinfo.c +do + $CC $CFLAGS $DEFS $INCS $i +done + +$LINK @netware/unzip.link diff --git a/netware/unzip.link b/netware/unzip.link new file mode 100644 index 0000000..045abaa --- /dev/null +++ b/netware/unzip.link @@ -0,0 +1,35 @@ +format novell NLM 'unzip utility' +name unzip +option caseexact +option copyright 'Copyright 1990-2005 Info-ZIP (www.info-zip.org).' +option map = unzip.map +option nodefaultlibs +option quiet +option screenname 'none' +option stack = 32k +option symfile = unzip.sym +option threadname 'unzip' +option version = 5.5.1 +module clib +import @c:/novell/ndk/nwsdk/imports/clib.imp +import @c:/novell/ndk/nwsdk/imports/nlmlib.imp +import @c:/novell/ndk/nwsdk/imports/threads.imp +import @c:/novell/ndk/nwsdk/imports/nit.imp +file crc32.obj +file crypt.obj +file envargs.obj +file explode.obj +file extract.obj +file fileio.obj +file globals.obj +file inflate.obj +file list.obj +file match.obj +file netware.obj +file process.obj +file ttyio.obj +file unreduce.obj +file unshrink.obj +file unzip.obj +file zipinfo.obj +file c:/novell/ndk/nwsdk/imports/nwpre.obj diff --git a/new-cmdparser/unz6-newcmdparser-diffs.txt b/new-cmdparser/unz6-newcmdparser-diffs.txt new file mode 100644 index 0000000..5a75e1c --- /dev/null +++ b/new-cmdparser/unz6-newcmdparser-diffs.txt @@ -0,0 +1,3476 @@ +diff -ru2 unz60e03/unzip.c u6e3_np/unzip.c +--- unz60e03/unzip.c Wed Mar 19 13:08:38 2008 ++++ u6e3_np/unzip.c Mon Mar 24 14:16:58 2008 +@@ -128,4 +128,6 @@ + "error: command line parameter #%d exceeds internal size limit\n"; + #endif /* !SFX */ ++static ZCONST char Far NoMemArgsList[] = ++ "error: no memory for arguments list"; + + #if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS)) +@@ -245,5 +247,5 @@ + static ZCONST char Far local3[] = "\ + -Y treat \".nnn\" as \";nnn\" version -2 force ODS2 names\n\ +- --D restore dir (-D: no) timestamps -M pipe through \"more\" pager\n\ ++ -D- restore dir (-D: no) timestamps -M pipe through \"more\" pager\n\ + (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)\ + \n\n"; +@@ -251,5 +253,5 @@ + static ZCONST char Far local3[] = "\n\ + -Y treat \".nnn\" as \";nnn\" version -2 force ODS2 names\n\ +- --D restore dir (-D: no) timestamps\n\ ++ -D- restore dir (-D: no) timestamps\n\ + (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)\ + \n\n"; +@@ -694,5 +696,5 @@ + char *p; + #endif +-#if (defined(DOS_FLX_H68_NLM_OS2_W32) || !defined(SFX)) ++#if ((defined(WIN32) && defined(__RSXNT__)) || !defined(SFX)) + int i; + #endif +@@ -1053,4 +1055,45 @@ + * 'forward slashes' for user's convenience (include zipfile name itself) + */ ++ { ++ /* pfnames */ ++ ++ char **names; ++ ++ for (names = G.pfnames; *names; names++) { ++#ifdef __human68k__ ++ extern char *_toslash(char *); ++ _toslash(*names); ++#else /* !__human68k__ */ ++ char *q = *names; ++ ++ while (*q != '\0') { ++ if (*q == '\\') ++ *q = '/'; ++ INCSTR(q); ++ } ++#endif /* ?__human68k__ */ ++ } ++ } ++ { ++ /* G.wildzipfn */ ++ ++#ifdef __human68k__ ++ extern char *_toslash(char *); ++ _toslash(*G.wildzipfn); ++#else /* !__human68k__ */ ++ char *q = G.wildzipfn; ++ ++ while (*q != '\0') { ++ if (*q == '\\') ++ *q = '/'; ++ INCSTR(q); ++ } ++#endif /* ?__human68k__ */ ++ } ++#endif /* DOS_FLX_H68_NLM_OS2_W32 */ ++ ++ ++#if 0 ++#ifdef DOS_FLX_H68_NLM_OS2_W32 + #ifdef SFX + for (G.pfnames = argv, i = argc; i > 0; --i) { +@@ -1074,11 +1117,18 @@ + } + #endif /* DOS_FLX_H68_NLM_OS2_W32 */ ++#endif /* 0 */ + ++/* + #ifndef SFX + G.wildzipfn = *argv++; + #endif ++*/ + + #if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */ + ++# if 0 ++ /* all this should be done in the options call now */ ++ ++ + G.filespecs = argc; + G.xfilespecs = 0; +@@ -1104,7 +1154,10 @@ + } else + G.process_all_files = TRUE; /* for speed */ ++# endif + + #else /* !SFX || SFX_EXDIR */ /* check for -x or -d */ + ++# if 0 ++ + G.filespecs = argc; + G.xfilespecs = 0; +@@ -1118,9 +1171,9 @@ + while (*++pp) { + Trace((stderr, "pp - argv = %d\n", pp-argv)); +-#ifdef CMS_MVS ++# ifdef CMS_MVS + if (!uO.exdir && STRNICMP(*pp, "-d", 2) == 0) { +-#else ++# else + if (!uO.exdir && strncmp(*pp, "-d", 2) == 0) { +-#endif ++# endif + int firstarg = (pp == argv); + +@@ -1177,4 +1230,5 @@ + } else + G.process_all_files = TRUE; /* for speed */ ++# endif + + if (uO.exdir != (char *)NULL && !G.extract_flag) /* -d ignored */ +@@ -1260,4 +1314,269 @@ + + ++/* ++ ------------------------------------------------------- ++ Command Line Options ++ ------------------------------------------------------- ++ ++ Valid command line options. ++ ++ The function get_option() uses this table to check if an ++ option is valid and if it takes a value (also called an ++ option parameter). To add an option to unzip just add it ++ to this table and add a case in the main switch to handle ++ it. If either shortopt or longopt not used set to "". ++ ++ The fields: ++ option_group - UZO for UnZip option, ZIO for ZipInfo option ++ shortopt - short option name (1 or 2 chars) ++ longopt - long option name ++ value_type - see zip.h for constants ++ negatable - option is negatable with trailing - ++ ID - unsigned long int returned for option ++ name - short description of option which is ++ returned on some errors and when options ++ are listed with -so option, can be NULL ++*/ ++ ++/* Most option IDs are set to the shortopt char. For ++ multichar short options set to arbitrary unused constant. */ ++#define o_so 0x101 ++ ++ ++/* The below is from the old main command line code with a few changes. ++ Note that UnZip and ZipInfo filter out their own options based on the ++ option_group value, so the same option letter can be used for both. */ ++ ++static struct option_struct far options[] = { ++ ++ /* UnZip options */ ++ ++ /* short longopt value_type negatable ++ ID name */ ++#ifdef RISCOS ++ {UZO, "/", "", o_REQUIRED_VALUE, o_NEGATABLE, ++ '/', "override Unzip$Exts"}, ++#endif ++ {UZO, "a", "", o_NO_VALUE, o_NEGATABLE, ++ 'a', "text conv (EOL char, ASCII->EBCDIC"}, ++#if (defined(DLL) && defined(API_DOC)) ++ {UZO, "A", "", o_NO_VALUE, o_NEGATABLE, ++ 'A', "extended help for API"}, ++#endif ++ {UZO, "b", "", o_NO_VALUE, o_NEGATABLE, ++ 'b', "binary, no ASCII conversions"}, ++#ifdef UNIXBACKUP ++ {UZO, "B", "", o_NO_VALUE, o_NEGATABLE, ++ 'B', "back up existing files"}, ++#endif ++#ifdef CMS_MVS ++ {UZO, "B", "", o_NO_VALUE, o_NEGATABLE, ++ 'b', "CMS/MVS binary"}, ++#endif ++ {UZO, "c", "", o_NO_VALUE, o_NEGATABLE, ++ 'c', "output to stdout"}, ++#ifdef CMS_MVS ++ /* for CMS_MVS map to lower case */ ++ {UZO, "C", "", o_NO_VALUE, o_NEGATABLE, ++ 'C', "CMS/MVS lower case"}, ++#endif ++#if (!defined(SFX) || defined(SFX_EXDIR)) ++ {UZO, "d", "", o_REQUIRED_VALUE, o_NEGATABLE, ++ 'd', "extraction root directory"}, ++#endif ++#if (!defined(NO_TIMESTAMPS)) ++ {UZO, "D", "", o_NO_VALUE, o_NEGATABLE, ++ 'D', "don't restore dir (-DD: any) timestamps"}, ++#endif ++ {UZO, "e", "", o_NO_VALUE, o_NEGATABLE, ++ 'e', "extract (not used?)"}, ++#ifdef MACOS ++ {UZO, "E", "", o_NO_VALUE, o_NEGATABLE, ++ 'E', "display Mac e.f. when restoring"}, ++#endif ++ {UZO, "f", "", o_NO_VALUE, o_NEGATABLE, ++ 'f', "freshen (extract only newer files)"}, ++#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS)) ++ {UZO, "F", "", o_NO_VALUE, o_NEGATABLE, ++ 'F', "Acorn filetype & NFS extension handling"}, ++#endif ++ {UZO, "h", "", o_NO_VALUE, o_NOT_NEGATABLE, ++ 'h', "help"}, ++#ifdef MACOS ++ {UZO, "i", "", o_NO_VALUE, o_NEGATABLE, ++ 'i', "ignore filenames stored in Mac ef"}, ++#endif ++ {UZO, "j", "", o_NO_VALUE, o_NEGATABLE, ++ 'j', "junk directories, extract names only"}, ++#if (defined(ATH_BEO) || defined(MACOS)) ++ {UZO, "J", "", o_NO_VALUE, o_NEGATABLE, ++ 'J', "Junk AtheOS, BeOS or MacOS file attrs"}, ++#endif ++#ifdef ATH_BEO_UNX ++ {UZO, "K", "", o_NO_VALUE, o_NEGATABLE, ++ 'K', "retain SUID/SGID/Tacky attrs"}, ++#endif ++#ifndef SFX ++ {UZO, "l", "", o_NO_VALUE, o_NEGATABLE, ++ 'l', "listing verbosity"}, ++#endif ++#ifndef CMS_MVS ++ {UZO, "L", "", o_NO_VALUE, o_NEGATABLE, ++ 'L', "convert (some) names to lower"}, ++#endif ++#ifdef MORE ++# ifdef CMS_MVS ++ {UZO, "m", "", o_NO_VALUE, o_NEGATABLE, ++ 'm', "pipe output through more"}, ++# endif ++ {UZO, "M", "", o_NO_VALUE, o_NEGATABLE, ++ 'M', "pipe output through more"}, ++#endif /* MORE */ ++ {UZO, "n", "", o_NO_VALUE, o_NEGATABLE, ++ 'n', "never overwrite files (no prompting)"}, ++#ifdef AMIGA ++ {UZO, "N", "", o_NO_VALUE, o_NEGATABLE, ++ 'N', "restore comments as filenotes"}, ++#endif ++ {UZO, "o", "", o_NO_VALUE, o_NEGATABLE, ++ 'o', "overwrite files without prompting"}, ++ {UZO, "p", "", o_NO_VALUE, o_NEGATABLE, ++ 'p', "pipe extraction to stdout, no messages"}, ++#if CRYPT ++ {UZO, "P", "", o_REQUIRED_VALUE, o_NEGATABLE, ++ 'P', "password"}, ++#endif ++ {UZO, "q", "", o_NO_VALUE, o_NEGATABLE, ++ 'q', "quiet"}, ++#ifdef QDOS ++ {UZO, "Q", "", o_NO_VALUE, o_NEGATABLE, ++ 'Q', "QDOS flags"}, ++#endif ++#ifdef TANDEM ++ {UZO, "r", "", o_NO_VALUE, o_NEGATABLE, ++ 'r', "remove file extensions"}, ++#endif ++#ifdef DOS_FLX_NLM_OS2_W32 ++ {UZO, "s", "", o_NO_VALUE, o_NEGATABLE, ++ 's', "spaces to underscores"}, ++#endif ++#ifdef VMS ++ {UZO, "S", "", o_NO_VALUE, o_NEGATABLE, ++ 'S', "VMS extract text as Stream LF"}, ++#endif ++ {UZO, "t", "", o_NO_VALUE, o_NEGATABLE, ++ 't', "test"}, ++#ifdef TIMESTAMP ++ {UZO, "T", "", o_NO_VALUE, o_NEGATABLE, ++ 'T', "timestamps"}, ++#endif ++ {UZO, "u", "", o_NO_VALUE, o_NEGATABLE, ++ 'u', "update (extract only new/newer files)"}, ++#ifdef UNICODE_SUPPORT ++ {UZO, "U", "", o_NO_VALUE, o_NEGATABLE, ++ 'U', "escape non-ASCII Unicode, disable Unicode"}, ++#else /* !UNICODE_SUPPORT */ ++# ifndef CMS_MVS ++ {UZO, "U", "", o_NO_VALUE, o_NEGATABLE, ++ 'U', "names to lower case"}, ++# endif /* !CMS_MVS */ ++#endif /* ?UNICODE_SUPPORT */ ++#ifndef SFX ++ {UZO, "v", "", o_NO_VALUE, o_NEGATABLE, ++ 'v', "verbose"}, ++#endif ++#ifndef CMS_MVS ++ {UZO, "V", "", o_NO_VALUE, o_NEGATABLE, ++ 'V', "don't strip VMS version numbers"}, ++#endif ++#ifdef WILD_STOP_AT_DIR ++ {UZO, "W", "", o_NO_VALUE, o_NEGATABLE, ++ 'W', "wildcard * doesn't span /"}, ++#endif ++ {UZO, "x", "", o_VALUE_LIST, o_NOT_NEGATABLE, ++ 'x', "exclude this list of files"}, ++#if (defined(RESTORE_UIDGID) || defined(RESTORE_ACL)) ++ {UZO, "X", "", o_NO_VALUE, o_NEGATABLE, ++ 'X', "restore owner/prot or UID/GID or ACLs"}, ++#endif ++#ifdef VMS ++ {UZO, "Y", "", o_NO_VALUE, o_NEGATABLE, ++ 'Y', "VMS treat .nnn as ;nnn version"}, ++#endif ++ {UZO, "z", "", o_NO_VALUE, o_NEGATABLE, ++ 'z', "display zipfile comment"}, ++#ifndef SFX ++ {UZO, "Z", "", o_NO_VALUE, o_NOT_NEGATABLE, ++ 'Z', "ZipInfo mode"}, ++#endif ++#ifdef VMS ++ {UZO, "2", "", o_NO_VALUE, o_NEGATABLE, ++ '2', "Force ODS2-compliant names."}, ++#endif ++#ifdef DOS_H68_OS2_W32 ++ {UZO, "$", "", o_NO_VALUE, o_NEGATABLE, ++ '$', "extract volume labels"}, ++#endif ++#if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM)) ++ {UZO, ":", "", o_NO_VALUE, o_NEGATABLE, ++ ':', "don't skip ../ path elements"}, ++#endif ++#ifdef UNIX ++ {UZO, "^", "", o_NO_VALUE, o_NEGATABLE, ++ '^', "allow control chars in filenames"}, ++#endif ++ ++#ifndef NO_ZIPINFO ++ /* ZipInfo options */ ++ ++ /* short longopt value_type negatable ++ ID name (help text) */ ++ {ZIO, "1", "", o_NO_VALUE, o_NEGATABLE, ++ '1', "shortest list"}, ++ {ZIO, "2", "", o_NO_VALUE, o_NEGATABLE, ++ '2', "names and headers"}, ++#ifndef CMS_MVS ++ {ZIO, "C", "", o_NO_VALUE, o_NEGATABLE, ++ 'C', "ignore case"}, ++#endif ++ {ZIO, "h", "", o_NO_VALUE, o_NEGATABLE, ++ 'h', "header line"}, ++ {ZIO, "l", "", o_NO_VALUE, o_NEGATABLE, ++ 'l', "longer listing"}, ++ {ZIO, "m", "", o_NO_VALUE, o_NEGATABLE, ++ 'm', "medium listing"}, ++#ifdef MORE ++ {ZIO, "M", "", o_NO_VALUE, o_NEGATABLE, ++ 'M', "output like more"}, ++#endif ++ {ZIO, "s", "", o_NO_VALUE, o_NEGATABLE, ++ 's', "shorter list"}, ++ {ZIO, "t", "", o_NO_VALUE, o_NEGATABLE, ++ 't', "totals line"}, ++ {ZIO, "T", "", o_NO_VALUE, o_NEGATABLE, ++ 'T', "decimal time format"}, ++#ifdef UNICODE_SUPPORT ++ {ZIO, "U", "", o_NO_VALUE, o_NEGATABLE, ++ 'U', "escape non-ASCII Unicode, disable Unicode"}, ++#endif ++ {ZIO, "v", "", o_NO_VALUE, o_NEGATABLE, ++ 'v', "turbo-verbose listing"}, ++#ifdef WILD_STOP_AT_DIR ++ {ZIO, "W", "", o_NO_VALUE, o_NEGATABLE, ++ 'W', "wild stop at /"}, ++#endif ++ {ZIO, "x", "", o_VALUE_LIST, o_NOT_NEGATABLE, ++ 'x', "exclude this list of files"}, ++ {ZIO, "z", "", o_NO_VALUE, o_NEGATABLE, ++ 'z', "print zipfile comment"}, ++ {ZIO, "Z", "", o_NO_VALUE, o_NEGATABLE, ++ 'Z', "ZipInfo mode"}, ++#endif /* !NO_ZIPINFO */ ++ ++ /* the end of the list */ ++ {0, NULL, NULL, o_NO_VALUE, o_NOT_NEGATABLE, ++ 0, NULL} /* end has option_ID = 0 */ ++ }; ++ + + +@@ -1271,502 +1590,649 @@ + char ***pargv; + { +- char **argv, *s; +- int argc, c, error=FALSE, negative=0; ++ char **args; ++ int argc, error=FALSE; + ++ /* used by get_option */ ++ unsigned long option; /* option ID returned by get_option */ ++ int argcnt = 0; /* current argcnt in args */ ++ int argnum = 0; /* arg number */ ++ int optchar = 0; /* option state */ ++ char *value = NULL; /* non-option arg, option value or NULL */ ++ int negative = 0; /* 1 = option negated */ ++ int fna = 0; /* current first non-opt arg */ ++ int optnum = 0; /* index in table */ + +- argc = *pargc; +- argv = *pargv; + +- while (++argv, (--argc > 0 && *argv != NULL && **argv == '-')) { +- s = *argv + 1; +- while ((c = *s++) != 0) { /* "!= 0": prevent Turbo C warning */ +-#ifdef CMS_MVS +- switch (tolower(c)) +-#else +- switch (c) +-#endif +- { +- case ('-'): +- ++negative; +- break; ++ /* since get_option() returns xfiles and files one at a time, store them ++ in linked lists until have them all */ ++ ++ int file_count = 0; ++ struct file_list *next_file; ++ ++ /* files to extract */ ++ int in_files_count = 0; ++ struct file_list *in_files = NULL; ++ struct file_list *next_in_files = NULL; ++ ++ /* files to exclude in -x list */ ++ int in_xfiles_count = 0; ++ struct file_list *in_xfiles = NULL; ++ struct file_list *next_in_xfiles = NULL; ++ ++ G.wildzipfn = NULL; ++ ++ /* make copy of args that can use with insert_arg() used by get_option() */ ++ args = copy_args(*pargv, 0); ++ ++ ++ /* Initialize lists */ ++ G.filespecs = 0; ++ G.xfilespecs = 0; ++ ++ ++ /* ++ ------------------------------------------- ++ Process command line using get_option ++ ------------------------------------------- ++ ++ Each call to get_option() returns either a command ++ line option and possible value or a non-option argument. ++ Arguments are permuted so that all options (-r, -b temp) ++ are returned before non-option arguments (zipfile). ++ Returns 0 when nothing left to read. ++ */ ++ ++ /* set argnum = 0 on first call to init get_option */ ++ argnum = 0; ++ ++ /* get_option returns the option ID and updates parameters: ++ args - usually same as argv if no argument file support ++ argcnt - current argc for args ++ value - char* to value (free() when done with it) or NULL if none ++ negated - option was negated with trailing - ++ */ ++ ++ while ((option = get_option(UZO, &args, &argcnt, &argnum, ++ &optchar, &value, &negative, ++ &fna, &optnum, 0))) ++ { ++ if(option == o_BAD_ERR) { ++ return(PK_PARAM); ++ } ++ ++ switch (option) ++ { + #ifdef RISCOS +- case ('/'): +- if (negative) { /* negative not allowed with -/ swap */ +- Info(slide, 0x401, ((char *)slide, +- "error: must give extensions list")); +- return(PK_PARAM); /* don't extract here by accident */ +- } +- exts2swap = s; /* override Unzip$Exts */ +- s += strlen(s); +- break; +-#endif +- case ('a'): +- if (negative) { +- uO.aflag = MAX(uO.aflag-negative,0); +- negative = 0; +- } else +- ++uO.aflag; +- break; ++ case ('/'): ++ if (negative) { /* negative not allowed with -/ swap */ ++ Info(slide, 0x401, ((char *)slide, ++ "error: must give extensions list")); ++ return(PK_PARAM); /* don't extract here by accident */ ++ } ++ exts2swap = value; /* override Unzip$Exts */ ++ break; ++#endif ++ case ('a'): ++ if (negative) { ++ uO.aflag = MAX(uO.aflag-negative,0); ++ negative = 0; ++ } else ++ ++uO.aflag; ++ break; + #if (defined(DLL) && defined(API_DOC)) +- case ('A'): /* extended help for API */ +- APIhelp(__G__ argc, argv); +- *pargc = -1; /* signal to exit successfully */ +- return 0; ++ case ('A'): /* extended help for API */ ++ APIhelp(__G__ argc, args); ++ *pargc = -1; /* signal to exit successfully */ ++ return 0; + #endif +- case ('b'): +- if (negative) { ++ case ('b'): ++ if (negative) { + #if (defined(TANDEM) || defined(VMS)) +- uO.bflag = MAX(uO.bflag-negative,0); ++ uO.bflag = MAX(uO.bflag-negative,0); + #endif +- negative = 0; /* do nothing: "-b" is default */ +- } else { ++ negative = 0; /* do nothing: "-b" is default */ ++ } else { + #ifdef VMS +- if (uO.aflag == 0) +- ++uO.bflag; ++ if (uO.aflag == 0) ++ ++uO.bflag; + #endif + #ifdef TANDEM +- ++uO.bflag; ++ ++uO.bflag; + #endif +- uO.aflag = 0; +- } +- break; ++ uO.aflag = 0; ++ } ++ break; + #ifdef UNIXBACKUP +- case ('B'): /* -B: back up existing files */ +- if (negative) +- uO.B_flag = FALSE, negative = 0; +- else +- uO.B_flag = TRUE; +- break; +-#endif +- case ('c'): +- if (negative) { +- uO.cflag = FALSE, negative = 0; ++ case ('B'): /* -B: back up existing files */ ++ if (negative) ++ uO.B_flag = FALSE, negative = 0; ++ else ++ uO.B_flag = TRUE; ++ break; ++#endif ++ case ('c'): ++ if (negative) { ++ uO.cflag = FALSE, negative = 0; + #ifdef NATIVE +- uO.aflag = 0; ++ uO.aflag = 0; + #endif +- } else { +- uO.cflag = TRUE; ++ } else { ++ uO.cflag = TRUE; + #ifdef NATIVE +- uO.aflag = 2; /* so you can read it on the screen */ ++ uO.aflag = 2; /* so you can read it on the screen */ + #endif + #ifdef DLL +- if (G.redirect_text) +- G.redirect_data = 2; ++ if (G.redirect_text) ++ G.redirect_data = 2; + #endif +- } +- break; ++ } ++ break; + #ifndef CMS_MVS +- case ('C'): /* -C: match filenames case-insensitively */ +- if (negative) +- uO.C_flag = FALSE, negative = 0; +- else +- uO.C_flag = TRUE; +- break; ++ case ('C'): /* -C: match filenames case-insensitively */ ++ if (negative) ++ uO.C_flag = FALSE, negative = 0; ++ else ++ uO.C_flag = TRUE; ++ break; + #endif /* !CMS_MVS */ + #if (!defined(SFX) || defined(SFX_EXDIR)) +- case ('d'): +- if (negative) { /* negative not allowed with -d exdir */ ++ case ('d'): ++ if (negative) { /* negative not allowed with -d exdir */ ++ Info(slide, 0x401, ((char *)slide, ++ LoadFarString(MustGiveExdir))); ++ return(PK_PARAM); /* don't extract here by accident */ ++ } ++ if (uO.exdir != (char *)NULL) { ++ Info(slide, 0x401, ((char *)slide, ++ LoadFarString(OnlyOneExdir))); ++ return(PK_PARAM); /* GRR: stupid restriction? */ ++ } else { ++ /* first check for "-dexdir", then for "-d exdir" */ ++ uO.exdir = value; ++ if (uO.exdir == NULL || *uO.exdir == '\0') { + Info(slide, 0x401, ((char *)slide, + LoadFarString(MustGiveExdir))); +- return(PK_PARAM); /* don't extract here by accident */ +- } +- if (uO.exdir != (char *)NULL) { +- Info(slide, 0x401, ((char *)slide, +- LoadFarString(OnlyOneExdir))); +- return(PK_PARAM); /* GRR: stupid restriction? */ +- } else { +- /* first check for "-dexdir", then for "-d exdir" */ +- uO.exdir = s; +- if (*uO.exdir == '\0') { +- if (argc > 1) { +- --argc; +- uO.exdir = *++argv; +- if (*uO.exdir == '-') { +- Info(slide, 0x401, ((char *)slide, +- LoadFarString(MustGiveExdir))); +- return(PK_PARAM); +- } +- /* else uO.exdir points at extraction dir */ +- } else { +- Info(slide, 0x401, ((char *)slide, +- LoadFarString(MustGiveExdir))); +- return(PK_PARAM); +- } +- } +- /* uO.exdir now points at extraction dir (-dexdir or +- * -d exdir); point s at end of exdir to avoid mis- +- * interpretation of exdir characters as more options +- */ +- if (*s != 0) +- while (*++s != 0) +- ; ++ return(PK_PARAM); + } +- break; ++ /* else uO.exdir points at extraction dir */ ++ } ++ break; + #endif /* !SFX || SFX_EXDIR */ + #if (!defined(NO_TIMESTAMPS)) +- case ('D'): /* -D: Skip restoring dir (or any) timestamp. */ +- if (negative) { +- uO.D_flag = MAX(uO.D_flag-negative,0); +- negative = 0; +- } else +- uO.D_flag++; +- break; ++ case ('D'): /* -D: Skip restoring dir (or any) timestamp. */ ++ if (negative) { ++ uO.D_flag = MAX(uO.D_flag-negative,0); ++ negative = 0; ++ } else ++ uO.D_flag++; ++ break; + #endif /* (!NO_TIMESTAMPS) */ +- case ('e'): /* just ignore -e, -x options (extract) */ +- break; ++ case ('e'): /* just ignore -e, -x options (extract) */ ++ break; + #ifdef MACOS +- case ('E'): /* -E [MacOS] display Mac e.f. when restoring */ +- if( negative ) { +- uO.E_flag = FALSE, negative = 0; +- } else { +- uO.E_flag = TRUE; +- } +- break; ++ case ('E'): /* -E [MacOS] display Mac e.f. when restoring */ ++ if( negative ) { ++ uO.E_flag = FALSE, negative = 0; ++ } else { ++ uO.E_flag = TRUE; ++ } ++ break; + #endif /* MACOS */ +- case ('f'): /* "freshen" (extract only newer files) */ +- if (negative) +- uO.fflag = uO.uflag = FALSE, negative = 0; +- else +- uO.fflag = uO.uflag = TRUE; +- break; ++ case ('f'): /* "freshen" (extract only newer files) */ ++ if (negative) ++ uO.fflag = uO.uflag = FALSE, negative = 0; ++ else ++ uO.fflag = uO.uflag = TRUE; ++ break; + #if (defined(RISCOS) || defined(ACORN_FTYPE_NFS)) +- case ('F'): /* Acorn filetype & NFS extension handling */ +- if (negative) +- uO.acorn_nfs_ext = FALSE, negative = 0; +- else +- uO.acorn_nfs_ext = TRUE; +- break; ++ case ('F'): /* Acorn filetype & NFS extension handling */ ++ if (negative) ++ uO.acorn_nfs_ext = FALSE, negative = 0; ++ else ++ uO.acorn_nfs_ext = TRUE; ++ break; + #endif /* RISCOS || ACORN_FTYPE_NFS */ +- case ('h'): /* just print help message and quit */ +- *pargc = -1; +- return USAGE(PK_OK); ++ case ('h'): /* just print help message and quit */ ++ *pargc = -1; ++ return USAGE(PK_OK); + #ifdef MACOS +- case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */ +- if( negative ) { +- uO.i_flag = FALSE, negative = 0; +- } else { +- uO.i_flag = TRUE; +- } +- break; ++ case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */ ++ if( negative ) { ++ uO.i_flag = FALSE, negative = 0; ++ } else { ++ uO.i_flag = TRUE; ++ } ++ break; + #endif /* MACOS */ +- case ('j'): /* junk pathnames/directory structure */ +- if (negative) +- uO.jflag = FALSE, negative = 0; +- else +- uO.jflag = TRUE; +- break; ++ case ('j'): /* junk pathnames/directory structure */ ++ if (negative) ++ uO.jflag = FALSE, negative = 0; ++ else ++ uO.jflag = TRUE; ++ break; + #if (defined(ATH_BEO) || defined(MACOS)) +- case ('J'): /* Junk AtheOS, BeOS or MacOS file attributes */ +- if( negative ) { +- uO.J_flag = FALSE, negative = 0; +- } else { +- uO.J_flag = TRUE; +- } +- break; ++ case ('J'): /* Junk AtheOS, BeOS or MacOS file attributes */ ++ if( negative ) { ++ uO.J_flag = FALSE, negative = 0; ++ } else { ++ uO.J_flag = TRUE; ++ } ++ break; + #endif /* ATH_BEO || MACOS */ + #ifdef ATH_BEO_UNX +- case ('K'): +- if (negative) { +- uO.K_flag = FALSE, negative = 0; +- } else { +- uO.K_flag = TRUE; +- } +- break; ++ case ('K'): ++ if (negative) { ++ uO.K_flag = FALSE, negative = 0; ++ } else { ++ uO.K_flag = TRUE; ++ } ++ break; + #endif /* ATH_BEO_UNX */ + #ifndef SFX +- case ('l'): +- if (negative) { +- uO.vflag = MAX(uO.vflag-negative,0); +- negative = 0; +- } else +- ++uO.vflag; +- break; ++ case ('l'): ++ if (negative) { ++ uO.vflag = MAX(uO.vflag-negative,0); ++ negative = 0; ++ } else ++ ++uO.vflag; ++ break; + #endif /* !SFX */ + #ifndef CMS_MVS +- case ('L'): /* convert (some) filenames to lowercase */ +- if (negative) { +- uO.L_flag = MAX(uO.L_flag-negative,0); +- negative = 0; +- } else +- ++uO.L_flag; +- break; ++ case ('L'): /* convert (some) filenames to lowercase */ ++ if (negative) { ++ uO.L_flag = MAX(uO.L_flag-negative,0); ++ negative = 0; ++ } else ++ ++uO.L_flag; ++ break; + #endif /* !CMS_MVS */ + #ifdef MORE + #ifdef CMS_MVS +- case ('m'): ++ case ('m'): + #endif +- case ('M'): /* send all screen output through "more" fn. */ ++ case ('M'): /* send all screen output through "more" fn. */ + /* GRR: eventually check for numerical argument => height */ +- if (negative) +- G.M_flag = FALSE, negative = 0; +- else +- G.M_flag = TRUE; +- break; ++ if (negative) ++ G.M_flag = FALSE, negative = 0; ++ else ++ G.M_flag = TRUE; ++ break; + #endif /* MORE */ +- case ('n'): /* don't overwrite any files */ +- if (negative) +- uO.overwrite_none = FALSE, negative = 0; +- else +- uO.overwrite_none = TRUE; +- break; ++ case ('n'): /* don't overwrite any files */ ++ if (negative) ++ uO.overwrite_none = FALSE, negative = 0; ++ else ++ uO.overwrite_none = TRUE; ++ break; + #ifdef AMIGA +- case ('N'): /* restore comments as filenotes */ +- if (negative) +- uO.N_flag = FALSE, negative = 0; +- else +- uO.N_flag = TRUE; +- break; ++ case ('N'): /* restore comments as filenotes */ ++ if (negative) ++ uO.N_flag = FALSE, negative = 0; ++ else ++ uO.N_flag = TRUE; ++ break; + #endif /* AMIGA */ +- case ('o'): /* OK to overwrite files without prompting */ +- if (negative) { +- uO.overwrite_all = MAX(uO.overwrite_all-negative,0); +- negative = 0; +- } else +- ++uO.overwrite_all; +- break; +- case ('p'): /* pipes: extract to stdout, no messages */ +- if (negative) { +- uO.cflag = FALSE; +- uO.qflag = MAX(uO.qflag-999,0); +- negative = 0; +- } else { +- uO.cflag = TRUE; +- uO.qflag += 999; +- } +- break; ++ case ('o'): /* OK to overwrite files without prompting */ ++ if (negative) { ++ uO.overwrite_all = MAX(uO.overwrite_all-negative,0); ++ negative = 0; ++ } else ++ ++uO.overwrite_all; ++ break; ++ case ('p'): /* pipes: extract to stdout, no messages */ ++ if (negative) { ++ uO.cflag = FALSE; ++ uO.qflag = MAX(uO.qflag-999,0); ++ negative = 0; ++ } else { ++ uO.cflag = TRUE; ++ uO.qflag += 999; ++ } ++ break; + #if CRYPT +- /* GRR: yes, this is highly insecure, but dozens of people +- * have pestered us for this, so here we go... */ +- case ('P'): +- if (negative) { /* negative not allowed with -P passwd */ +- Info(slide, 0x401, ((char *)slide, +- LoadFarString(MustGivePasswd))); +- return(PK_PARAM); /* don't extract here by accident */ +- } +- if (uO.pwdarg != (char *)NULL) { ++ /* GRR: yes, this is highly insecure, but dozens of people ++ * have pestered us for this, so here we go... */ ++ case ('P'): ++ if (negative) { /* negative not allowed with -P passwd */ ++ Info(slide, 0x401, ((char *)slide, ++ LoadFarString(MustGivePasswd))); ++ return(PK_PARAM); /* don't extract here by accident */ ++ } ++ if (uO.pwdarg != (char *)NULL) { + /* +- GRR: eventually support multiple passwords? ++ GRR: eventually support multiple passwords? ++ Info(slide, 0x401, ((char *)slide, ++ LoadFarString(OnlyOnePasswd))); ++ return(PK_PARAM); ++*/ ++ } else { ++ /* first check for "-Ppasswd", then for "-P passwd" */ ++ uO.pwdarg = value; ++ if (uO.pwdarg == NULL || *uO.pwdarg == '\0') { + Info(slide, 0x401, ((char *)slide, +- LoadFarString(OnlyOnePasswd))); ++ LoadFarString(MustGivePasswd))); + return(PK_PARAM); +- */ +- } else { +- /* first check for "-Ppasswd", then for "-P passwd" */ +- uO.pwdarg = s; +- if (*uO.pwdarg == '\0') { +- if (argc > 1) { +- --argc; +- uO.pwdarg = *++argv; +- if (*uO.pwdarg == '-') { +- Info(slide, 0x401, ((char *)slide, +- LoadFarString(MustGivePasswd))); +- return(PK_PARAM); +- } +- /* else pwdarg points at decryption password */ +- } else { +- Info(slide, 0x401, ((char *)slide, +- LoadFarString(MustGivePasswd))); +- return(PK_PARAM); +- } +- } +- /* pwdarg now points at decryption password (-Ppasswd or +- * -P passwd); point s at end of passwd to avoid mis- +- * interpretation of passwd characters as more options +- */ +- if (*s != 0) +- while (*++s != 0) +- ; ++ /* else pwdarg points at decryption password */ + } +- break; ++ } ++ break; + #endif /* CRYPT */ +- case ('q'): /* quiet: fewer comments/messages */ +- if (negative) { +- uO.qflag = MAX(uO.qflag-negative,0); +- negative = 0; +- } else +- ++uO.qflag; +- break; ++ case ('q'): /* quiet: fewer comments/messages */ ++ if (negative) { ++ uO.qflag = MAX(uO.qflag-negative,0); ++ negative = 0; ++ } else ++ ++uO.qflag; ++ break; + #ifdef QDOS +- case ('Q'): /* QDOS flags */ +- qlflag ^= strtol(s, &s, 10); +- break; /* we XOR this as we can config qlflags */ ++ case ('Q'): /* QDOS flags */ ++ qlflag ^= strtol(value, &value, 10); ++ break; /* we XOR this as we can config qlflags */ + #endif + #ifdef TANDEM +- case ('r'): /* remove file extensions */ +- if (negative) +- uO.rflag = FALSE, negative = 0; +- else +- uO.rflag = TRUE; +- break; ++ case ('r'): /* remove file extensions */ ++ if (negative) ++ uO.rflag = FALSE, negative = 0; ++ else ++ uO.rflag = TRUE; ++ break; + #endif /* TANDEM */ + #ifdef DOS_FLX_NLM_OS2_W32 +- case ('s'): /* spaces in filenames: allow by default */ +- if (negative) +- uO.sflag = FALSE, negative = 0; +- else +- uO.sflag = TRUE; +- break; ++ case ('s'): /* spaces in filenames: allow by default */ ++ if (negative) ++ uO.sflag = FALSE, negative = 0; ++ else ++ uO.sflag = TRUE; ++ break; + #endif /* DOS_FLX_NLM_OS2_W32 */ + #ifdef VMS +- /* VMS: extract "text" files in Stream_LF format (-a[a]) */ +- case ('S'): +- if (negative) +- uO.S_flag = FALSE, negative = 0; +- else +- uO.S_flag = TRUE; +- break; ++ /* VMS: extract "text" files in Stream_LF format (-a[a]) */ ++ case ('S'): ++ if (negative) ++ uO.S_flag = FALSE, negative = 0; ++ else ++ uO.S_flag = TRUE; ++ break; + #endif /* VMS */ +- case ('t'): +- if (negative) +- uO.tflag = FALSE, negative = 0; +- else +- uO.tflag = TRUE; +- break; ++ case ('t'): ++ if (negative) ++ uO.tflag = FALSE, negative = 0; ++ else ++ uO.tflag = TRUE; ++ break; + #ifdef TIMESTAMP +- case ('T'): +- if (negative) +- uO.T_flag = FALSE, negative = 0; +- else +- uO.T_flag = TRUE; +- break; +-#endif +- case ('u'): /* update (extract only new and newer files) */ +- if (negative) +- uO.uflag = FALSE, negative = 0; +- else +- uO.uflag = TRUE; +- break; ++ case ('T'): ++ if (negative) ++ uO.T_flag = FALSE, negative = 0; ++ else ++ uO.T_flag = TRUE; ++ break; ++#endif ++ case ('u'): /* update (extract only new and newer files) */ ++ if (negative) ++ uO.uflag = FALSE, negative = 0; ++ else ++ uO.uflag = TRUE; ++ break; + #ifdef UNICODE_SUPPORT +- case ('U'): /* escape UTF-8, or disable UTF-8 support */ +- if (negative) { +- uO.U_flag = MAX(uO.U_flag-negative,0); +- negative = 0; +- } else +- uO.U_flag++; +- break; ++ case ('U'): /* escape UTF-8, or disable UTF-8 support */ ++ if (negative) ++ uO.U_flag = MAX(uO.U_flag - 1, 0); ++ else ++ uO.U_flag++; ++ break; + #else /* !UNICODE_SUPPORT */ + #ifndef CMS_MVS +- case ('U'): /* obsolete; to be removed in version 6.0 */ +- if (negative) +- uO.L_flag = TRUE, negative = 0; +- else +- uO.L_flag = FALSE; +- break; ++ case ('U'): /* obsolete; to be removed in version 6.0 */ ++ if (negative) ++ uO.L_flag = TRUE, negative = 0; ++ else ++ uO.L_flag = FALSE; ++ break; + #endif /* !CMS_MVS */ + #endif /* ?UNICODE_SUPPORT */ + #ifndef SFX +- case ('v'): /* verbose */ +- if (negative) { +- uO.vflag = MAX(uO.vflag-negative,0); +- negative = 0; +- } else if (uO.vflag) +- ++uO.vflag; +- else +- uO.vflag = 2; +- break; ++ case ('v'): /* verbose */ ++ if (negative) { ++ uO.vflag = MAX(uO.vflag-negative,0); ++ negative = 0; ++ } else if (uO.vflag) ++ ++uO.vflag; ++ else ++ uO.vflag = 2; ++ break; + #endif /* !SFX */ + #ifndef CMS_MVS +- case ('V'): /* Version (retain VMS/DEC-20 file versions) */ +- if (negative) +- uO.V_flag = FALSE, negative = 0; +- else +- uO.V_flag = TRUE; +- break; ++ case ('V'): /* Version (retain VMS/DEC-20 file versions) */ ++ if (negative) ++ uO.V_flag = FALSE, negative = 0; ++ else ++ uO.V_flag = TRUE; ++ break; + #endif /* !CMS_MVS */ + #ifdef WILD_STOP_AT_DIR +- case ('W'): /* Wildcard interpretation (stop at '/'?) */ +- if (negative) +- uO.W_flag = FALSE, negative = 0; +- else +- uO.W_flag = TRUE; +- break; ++ case ('W'): /* Wildcard interpretation (stop at '/'?) */ ++ if (negative) ++ uO.W_flag = FALSE, negative = 0; ++ else ++ uO.W_flag = TRUE; ++ break; + #endif /* WILD_STOP_AT_DIR */ +- case ('x'): /* extract: default */ +-#ifdef SFX +- /* when 'x' is the only option in this argument, and the +- * next arg is not an option, assume this initiates an +- * exclusion list (-x xlist): terminate option-scanning +- * and leave uz_opts with argv still pointing to "-x"; +- * the xlist is processed later +- */ +- if (s - argv[0] == 2 && *s == '\0' && +- argc > 1 && argv[1][0] != '-') { +- /* break out of nested loops without "++argv;--argc" */ +- goto opts_done; ++ case ('x'): /* extract: default */ ++ /* add -x file to linked list */ ++ ++ if (in_xfiles_count == 0) { ++ /* first entry */ ++ if ((in_xfiles = (struct file_list *) ++ malloc(sizeof(struct file_list)) ++ ) == NULL) { ++ Info(slide, 0x401, ((char *)slide, ++ LoadFarString(NoMemArgsList))); ++ return PK_MEM; ++ } ++ in_xfiles->name = value; ++ in_xfiles->next = NULL; ++ next_in_xfiles = in_xfiles; ++ } else { ++ /* add next entry */ ++ if ((next_file = (struct file_list *) ++ malloc(sizeof(struct file_list)) ++ ) == NULL) { ++ Info(slide, 0x401, ((char *)slide, ++ LoadFarString(NoMemArgsList))); ++ return PK_MEM; + } ++ next_in_xfiles->next = next_file; ++ next_file->name = value; ++ next_file->next = NULL; ++ next_in_xfiles = next_file; ++ } ++ in_xfiles_count++; ++ ++#if 0 ++#ifdef SFX ++ /* now get -x list one entry at a time */ ++ ++ ++ ++ /* when 'x' is the only option in this argument, and the ++ * next arg is not an option, assume this initiates an ++ * exclusion list (-x xlist): terminate option-scanning ++ * and leave uz_opts with argv still pointing to "-x"; ++ * the xlist is processed later ++ */ ++ if (s - argv[0] == 2 && *s == '\0' && ++ argc > 1 && argv[1][0] != '-') { ++ /* break out of nested loops without "++argv;--argc" */ ++ goto opts_done; ++ } + #endif /* SFX */ +- break; ++#endif ++ break; + #if (defined(RESTORE_UIDGID) || defined(RESTORE_ACL)) +- case ('X'): /* restore owner/protection info (need privs?) */ +- if (negative) { +- uO.X_flag = MAX(uO.X_flag-negative,0); +- negative = 0; +- } else +- ++uO.X_flag; +- break; ++ case ('X'): /* restore owner/protection info (need privs?) */ ++ if (negative) { ++ uO.X_flag = MAX(uO.X_flag-negative,0); ++ negative = 0; ++ } else ++ ++uO.X_flag; ++ break; + #endif /* RESTORE_UIDGID || RESTORE_ACL */ + #ifdef VMS +- case ('Y'): /* Treat ".nnn" as ";nnn" version. */ +- if (negative) +- uO.Y_flag = FALSE, negative = 0; +- else +- uO.Y_flag = TRUE; +- break; ++ case ('Y'): /* Treat ".nnn" as ";nnn" version. */ ++ if (negative) ++ uO.Y_flag = FALSE, negative = 0; ++ else ++ uO.Y_flag = TRUE; ++ break; + #endif /* VMS */ +- case ('z'): /* display only the archive comment */ +- if (negative) { +- uO.zflag = MAX(uO.zflag-negative,0); +- negative = 0; +- } else +- ++uO.zflag; +- break; ++ case ('z'): /* display only the archive comment */ ++ if (negative) { ++ uO.zflag = MAX(uO.zflag-negative,0); ++ negative = 0; ++ } else ++ ++uO.zflag; ++ break; + #ifndef SFX +- case ('Z'): /* should have been first option (ZipInfo) */ +- Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst))); +- error = TRUE; +- break; ++ case ('Z'): /* should have been first option (ZipInfo) */ ++ Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst))); ++ error = TRUE; ++ break; + #endif /* !SFX */ + #ifdef VMS +- case ('2'): /* Force ODS2-compliant names. */ +- if (negative) +- uO.ods2_flag = FALSE, negative = 0; +- else +- uO.ods2_flag = TRUE; +- break; ++ case ('2'): /* Force ODS2-compliant names. */ ++ if (negative) ++ uO.ods2_flag = FALSE, negative = 0; ++ else ++ uO.ods2_flag = TRUE; ++ break; + #endif /* VMS */ + #ifdef DOS_H68_OS2_W32 +- case ('$'): +- if (negative) { +- uO.volflag = MAX(uO.volflag-negative,0); +- negative = 0; +- } else +- ++uO.volflag; +- break; ++ case ('$'): ++ if (negative) { ++ uO.volflag = MAX(uO.volflag-negative,0); ++ negative = 0; ++ } else ++ ++uO.volflag; ++ break; + #endif /* DOS_H68_OS2_W32 */ + #if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM)) +- case (':'): /* allow "parent dir" path components */ +- if (negative) { +- uO.ddotflag = MAX(uO.ddotflag-negative,0); +- negative = 0; +- } else +- ++uO.ddotflag; +- break; ++ case (':'): /* allow "parent dir" path components */ ++ if (negative) { ++ uO.ddotflag = MAX(uO.ddotflag-negative,0); ++ negative = 0; ++ } else ++ ++uO.ddotflag; ++ break; + #endif /* !RISCOS && !CMS_MVS && !TANDEM */ + #ifdef UNIX +- case ('^'): /* allow control chars in filenames */ +- if (negative) { +- uO.cflxflag = MAX(uO.cflxflag-negative,0); +- negative = 0; +- } else +- ++uO.cflxflag; +- break; ++ case ('^'): /* allow control chars in filenames */ ++ if (negative) { ++ uO.cflxflag = MAX(uO.cflxflag-negative,0); ++ negative = 0; ++ } else ++ ++uO.cflxflag; ++ break; + #endif /* UNIX */ +- default: +- error = TRUE; +- break; +- +- } /* end switch */ +- } /* end while (not end of argument string) */ +- } /* end while (not done with switches) */ ++ case o_NON_OPTION_ARG: ++ /* not an option */ ++ /* no more options as permuting */ ++ ++ ++ if (G.wildzipfn == NULL) { ++ /* first non-option argument is zip file */ ++ G.wildzipfn = value; ++ ++ } else { ++ /* add include file to list */ ++ if (in_files_count == 0) { ++ /* first entry */ ++ if ((next_file = (struct file_list *) ++ malloc(sizeof(struct file_list)) ++ ) == NULL) { ++ Info(slide, 0x401, ((char *)slide, ++ LoadFarString(NoMemArgsList))); ++ return PK_MEM; ++ } ++ next_file->name = value; ++ next_file->next = NULL; ++ in_files = next_file; ++ next_in_files = next_file; ++ } else { ++ /* add next entry */ ++ if ((next_file = (struct file_list *) ++ malloc(sizeof(struct file_list)) ++ ) == NULL) { ++ Info(slide, 0x401, ((char *)slide, ++ LoadFarString(NoMemArgsList))); ++ return PK_MEM; ++ } ++ next_in_files->next = next_file; ++ next_file->name = value; ++ next_file->next = NULL; ++ next_in_files = next_file; ++ } ++ in_files_count++; ++ } ++ break; ++ default: ++ error = TRUE; ++ break; ++ ++ } /* end switch */ ++ } /* get_option() */ ++ ++ ++ /* convert files and xfiles lists to arrays */ ++ ++ /* convert files list to array */ ++ if (in_files_count) { ++ if ((G.pfnames = (char **) malloc((in_files_count + 1) * sizeof(char *)) ++ ) == NULL) { ++ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArgsList))); ++ return PK_MEM; ++ } ++ file_count = 0; ++ for (next_file = in_files; next_file;) { ++ G.pfnames[file_count] = next_file->name; ++ in_files = next_file; ++ next_file = next_file->next; ++ free(in_files); ++ file_count++; ++ } ++ G.pfnames[file_count] = NULL; ++ G.filespecs = in_files_count; ++ } ++ ++ /* convert xfiles list to array */ ++ if (in_xfiles_count) { ++ if ((G.pxnames = (char **) malloc((in_xfiles_count + 1) * sizeof(char *)) ++ ) == NULL) { ++ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArgsList))); ++ return PK_MEM; ++ } ++ file_count = 0; ++ for (next_file = in_xfiles; next_file;) { ++ G.pxnames[file_count] = next_file->name; ++ in_xfiles = next_file; ++ next_file = next_file->next; ++ free(in_xfiles); ++ file_count++; ++ } ++ G.pxnames[file_count] = NULL; ++ G.xfilespecs = in_xfiles_count; ++ } ++ ++ if (in_files_count || in_xfiles_count) { ++ G.process_all_files = FALSE; ++ } else { ++ G.process_all_files = TRUE; /* for speed */ ++ } ++ ++ ++ /* it's possible the arg count could have been changed by get_option() */ ++ argc = arg_count(args); ++ ++ + + /*--------------------------------------------------------------------------- +@@ -1774,7 +2240,77 @@ + ---------------------------------------------------------------------------*/ + ++ if ((uO.cflag && (uO.tflag || uO.uflag)) || ++ (uO.tflag && uO.uflag) || (uO.fflag && uO.overwrite_none)) ++ { ++ Info(slide, 0x401, ((char *)slide, LoadFarString(InvalidOptionsMsg))); ++ error = TRUE; ++ } ++ if (uO.aflag > 2) ++ uO.aflag = 2; ++#ifdef VMS ++ if (uO.bflag > 2) ++ uO.bflag = 2; ++ /* Clear -s flag when converting text files. */ ++ if (uO.aflag <= 0) ++ uO.S_flag = 0; ++#endif /* VMS */ ++ if (uO.overwrite_all && uO.overwrite_none) { ++ Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg))); ++ uO.overwrite_all = FALSE; ++ } ++#ifdef MORE ++ if (G.M_flag && !isatty(1)) /* stdout redirected: "more" func. useless */ ++ G.M_flag = 0; ++#endif ++ ++#ifdef SFX ++ if (error) ++#else ++ if ((G.wildzipfn == NULL) || error) ++#endif ++ { ++ /* tell caller to exit */ ++ if (argc <= 2) ++ argc = -1; ++ ++ *pargc = argc; ++ *pargv = args; ++#ifndef SFX ++ if (uO.vflag >= 2 && argc == -1) { /* "unzip -v" */ ++ show_version_info(__G); ++ return PK_OK; ++ } ++ if (!G.noargs && !error) ++ error = TRUE; /* had options (not -h or -v) but no zipfile */ ++#endif /* !SFX */ ++ return USAGE(error); ++ } ++ + #ifdef SFX +-opts_done: /* yes, very ugly...but only used by UnZipSFX with -x xlist */ ++ /* print our banner unless we're being fairly quiet */ ++ if (uO.qflag < 2) ++ Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner), ++ UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, ++ LoadFarStringSmall(VersionDate))); ++#ifdef BETA ++ /* always print the beta warning: no unauthorized distribution!! */ ++ Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n", ++ "SFX")); ++#endif ++#endif /* SFX */ ++ ++ if (uO.cflag || uO.tflag || uO.vflag || uO.zflag ++#ifdef TIMESTAMP ++ || uO.T_flag + #endif ++ ) ++ G.extract_flag = FALSE; ++ else ++ G.extract_flag = TRUE; ++ ++#if 0 ++# ifdef SFX ++opts_done: /* yes, very ugly...but only used by UnZipSFX with -x xlist */ ++# endif + + if ((uO.cflag && (uO.tflag || uO.uflag)) || +@@ -1786,5 +2322,5 @@ + if (uO.aflag > 2) + uO.aflag = 2; +-#ifdef VMS ++# ifdef VMS + if (uO.bflag > 2) + uO.bflag = 2; +@@ -1792,23 +2328,23 @@ + if (uO.aflag <= 0) + uO.S_flag = 0; +-#endif /* VMS */ ++# endif /* VMS */ + if (uO.overwrite_all && uO.overwrite_none) { + Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg))); + uO.overwrite_all = FALSE; + } +-#ifdef MORE ++# ifdef MORE + if (G.M_flag && !isatty(1)) /* stdout redirected: "more" func. useless */ + G.M_flag = 0; +-#endif ++# endif + +-#ifdef SFX ++# ifdef SFX + if (error) +-#else ++# else + if ((argc-- == 0) || error) +-#endif ++# endif + { + *pargc = argc; +- *pargv = argv; +-#ifndef SFX ++ *pargv = args; ++# ifndef SFX + if (uO.vflag >= 2 && argc == -1) { /* "unzip -v" */ + show_version_info(__G); +@@ -1817,9 +2353,9 @@ + if (!G.noargs && !error) + error = TRUE; /* had options (not -h or -v) but no zipfile */ +-#endif /* !SFX */ ++# endif /* !SFX */ + return USAGE(error); + } + +-#ifdef SFX ++# ifdef SFX + /* print our banner unless we're being fairly quiet */ + if (uO.qflag < 2) +@@ -1827,22 +2363,23 @@ + UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, + LoadFarStringSmall(VersionDate))); +-#ifdef BETA ++# ifdef BETA + /* always print the beta warning: no unauthorized distribution!! */ + Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n", + "SFX")); +-#endif +-#endif /* SFX */ ++# endif ++# endif /* SFX */ + + if (uO.cflag || uO.tflag || uO.vflag || uO.zflag +-#ifdef TIMESTAMP ++# ifdef TIMESTAMP + || uO.T_flag +-#endif ++# endif + ) + G.extract_flag = FALSE; + else + G.extract_flag = TRUE; ++#endif + + *pargc = argc; +- *pargv = argv; ++ *pargv = args; + return PK_OK; + +@@ -2314,2 +2851,1366 @@ + #endif /* !SFX */ + #endif /* !WINDLL */ ++ ++ ++ ++ ++ ++ ++/*--------------------------------------------------------------- ++ * Long option support ++ * 8/23/2003 ++ * Updated 3/1/2008 to support UnZip ++ * ++ * Defines function get_option() to get and process the command ++ * line options and arguments from argv[]. The caller calls ++ * get_option() in a loop to get either one option and possible ++ * value or a non-option argument each loop. ++ * ++ * This version has been modified to work with UnZip and ZipInfo. ++ * the major changes are removing the error returns, instead ++ * passing back error codes for errors, and supporting separate ++ * groups of options for UnZip and ZipInfo and selecting the option ++ * group by an argument. ++ * ++ * This version does not include argument file support and can ++ * work directly on argv. The argument file code complicates things and ++ * it seemed best to leave it out for now. If argument file support ++ * (reading in command line arguments stored in a file and inserting into ++ * command line where @filename is found) is added later the arguments ++ * can change and a freeable copy of argv will be needed and can be ++ * created using copy_args in the left out code. ++ * ++ * Supports short and long options as defined in the array options[] ++ * in zip.c, multiple short options in an argument (like -jlv), long ++ * option abbreviation (like --te for --temp-file if --te unique), ++ * short and long option values (like -b filename or --temp-file filename ++ * or --temp-file=filename), optional and required values, option negation ++ * by trailing - (like -S- to not include hidden and system files in MSDOS), ++ * value lists (like -x a b c), argument permuting (returning all options ++ * and values before any non-option arguments), and argument files (where ++ * any non-option non-value argument in form @path gets substituted with ++ * the white space separated arguments in the text file at path). In this ++ * version argument file support has been removed to simplify development ++ * but may be added later. ++ * ++ * E. Gordon ++ */ ++ ++ ++/* message output - char casts are needed to handle constants */ ++#define oWARN(message) Info(slide, 0x401, ((char *)slide, (char *)message)) ++ ++ ++ ++/* Although the below provides some support for multibyte characters ++ the proper thing to do may be to use wide characters and support ++ Unicode. May get to it soon. Wide support would likely require ++ the ability to convert the command line to wide strings, which most ++ modern OS should support now. EG ++ */ ++ ++/* For now stay with multi-byte characters. May support wide characters ++ in Zip 3.1 and UnZip 6.1. ++ */ ++ ++/* multibyte character set support ++ Multibyte characters use typically two or more sequential bytes ++ to represent additional characters than can fit in a single byte ++ character set. The code used here is based on the ANSI mblen function. */ ++#define MB_CLEN(ptr) CLEN(ptr) ++#define MB_NEXTCHAR(ptr) PREINCSTR(ptr) ++ ++ ++/* constants */ ++ ++/* function get_args_from_arg_file() can return this in depth parameter */ ++#define ARG_FILE_ERR -1 ++ ++/* internal settings for optchar */ ++#define SKIP_VALUE_ARG -1 ++#define THIS_ARG_DONE -2 ++#define START_VALUE_LIST -3 ++#define IN_VALUE_LIST -4 ++#define NON_OPTION_ARG -5 ++#define STOP_VALUE_LIST -6 ++/* 7/25/04 EG */ ++#define READ_REST_ARGS_VERBATIM -7 ++ ++ ++/* global veriables */ ++ ++int enable_permute = 1; /* yes - return options first */ ++/* 7/25/04 EG */ ++int doubledash_ends_options = 1; /* when -- what follows are not options */ ++ ++/* buffer for error messages (this sizing is a guess but must hold 2 paths) */ ++#define OPTIONERR_BUF_SIZE (80+ 2*FILENAME_MAX) ++char optionerrbuf[OPTIONERR_BUF_SIZE + 1]; ++ ++/* error messages */ ++static ZCONST char Far op_not_neg_err[] = ++ "option %s not negatable"; ++static ZCONST char Far op_req_val_err[] = ++ "option %s requires a value"; ++static ZCONST char Far op_no_allow_val_err[] = ++ "option %s does not allow a value"; ++static ZCONST char Far sh_op_not_sup_err[] = ++ "short option '%c' not supported"; ++static ZCONST char Far oco_req_val_err[] = ++ "option %s requires one character value"; ++static ZCONST char Far oco_no_mbc_err[] = ++ "option %s does not support multibyte values"; ++static ZCONST char Far num_req_val_err[] = ++ "option %s requires number value"; ++static ZCONST char Far long_op_ambig_err[] = ++ "long option '%s' ambiguous"; ++static ZCONST char Far long_op_not_sup_err[] = ++ "long option '%s' not supported"; ++ ++static ZCONST char Far no_arg_files_err[] = "argument files not enabled\n"; ++ ++ ++/* below removed as only used for processing argument files */ ++ ++/* get_nextarg */ ++/* get_args_from_string */ ++/* get_args_from_arg_file */ ++ ++ ++/* copy error, option name, and option description if any to buf */ ++static int optionerr(options, buf, err, optind, islong) ++ struct option_struct *options; ++ char *buf; ++ ZCONST char Far *err; ++ int optind; ++ int islong; ++{ ++ char optname[50]; ++ ++ if (options[optind].name && options[optind].name[0] != '\0') { ++ sprintf(optname, "'%s' (%s)", ++ LoadFarStringSmall2(islong ? options[optind].longopt ++ : options[optind].shortopt), ++ LoadFarStringSmall(options[optind].name)); ++ } else { ++ sprintf(optname, "'%s'", ++ LoadFarStringSmall2(islong ? options[optind].longopt ++ : options[optind].shortopt)); ++ } ++ sprintf(buf, LoadFarStringSmall(err), optname); ++ return 0; ++} ++ ++ ++/* copy_args ++ * ++ * Copy arguments in args, allocating storage with malloc. ++ * Copies until a NULL argument is found or until max_args args ++ * including args[0] are copied. Set max_args to 0 to copy ++ * until NULL. Always terminates returned args[] with NULL arg. ++ * ++ * Any argument in the returned args can be freed with free(). Any ++ * freed argument should be replaced with either another string ++ * allocated with malloc or by NULL if last argument so that free_args ++ * will properly work. ++ */ ++char **copy_args(args, max_args) ++ char **args; ++ int max_args; ++{ ++ int j; ++ char **new_args; ++ ++ if (args == NULL) { ++ return NULL; ++ } ++ ++ /* count args */ ++ for (j = 0; args[j] && (max_args == 0 || j < max_args); j++) ; ++ ++ if ((new_args = (char **) malloc((j + 1) * sizeof(char *))) == NULL) { ++ oWARN("memory - ca"); ++ return NULL; ++ } ++ ++ for (j = 0; args[j] && (max_args == 0 || j < max_args); j++) { ++ if (args[j] == NULL) { ++ /* null argument is end of args */ ++ new_args[j] = NULL; ++ break; ++ } ++ if ((new_args[j] = malloc(strlen(args[j]) + 1)) == NULL) { ++ free_args(new_args); ++ oWARN("memory - ca"); ++ return NULL; ++ } ++ strcpy(new_args[j], args[j]); ++ } ++ new_args[j] = NULL; ++ ++ return new_args; ++} ++ ++ ++/* count args - count args in argv like array */ ++int arg_count(args) ++ char **args; ++{ ++ int i; ++ ++ if (args == NULL) { ++ return 0; ++ } ++ ++ for (i = 0; args[i]; i++) { ++ } ++ return i; ++} ++ ++ ++/* free args - free args created with one of these functions */ ++int free_args(args) ++ char **args; ++{ ++ int i; ++ ++ if (args == NULL) { ++ return 0; ++ } ++ ++ for (i = 0; args[i]; i++) { ++ free(args[i]); ++ } ++ free(args); ++ return i; ++} ++ ++ ++/* insert_arg ++ * ++ * Insert the argument arg into the array args before argument at_arg. ++ * If at_arg = -1 then append to end. ++ * Return the new count of arguments (argc). ++ * ++ * If free_args is true, this function frees the old args array ++ * (but not the component strings). DO NOT set free_args on original ++ * argv but only on args allocated with malloc. ++ */ ++ ++int insert_arg(pargs, arg, at_arg, free_args) ++ char ***pargs; ++ ZCONST char *arg; ++ int at_arg; ++ int free_args; ++{ ++ char *newarg = NULL; ++ char **args; ++ char **newargs = NULL; ++ int argnum; ++ int newargnum; ++ int argcnt; ++ int newargcnt; ++ ++ if (pargs == NULL) { ++ return 0; ++ } ++ args = *pargs; ++ ++ /* count args */ ++ if (args == NULL) { ++ argcnt = 0; ++ } else { ++ for (argcnt = 0; args[argcnt]; argcnt++) ; ++ } ++ if (arg == NULL) { ++ /* done */ ++ return argcnt; ++ } ++ if (at_arg == -1) { ++ at_arg = argcnt; ++ } ++ newargcnt = argcnt + 1; ++ ++ /* get storage for new args */ ++ if ((newargs = (char **) malloc((newargcnt + 1) * sizeof(char *))) == NULL) ++ { ++ oWARN("memory - ia"); ++ return 0; ++ } ++ ++ /* copy argument pointers from args to position at_arg, copy the new arg, ++ then copy the rest of the args */ ++ argnum = 0; ++ newargnum = 0; ++ if (args) { ++ for (; args[argnum] && argnum < at_arg; argnum++) { ++ newargs[newargnum++] = args[argnum]; ++ } ++ } ++ /* copy new arg */ ++ if ((newarg = (char *) malloc(strlen(arg) + 1)) == NULL) { ++ oWARN("memory - ia"); ++ return 0; ++ } ++ strcpy(newarg, arg); ++ ++ newargs[newargnum++] = newarg; ++ if (args) { ++ for ( ; args[argnum]; argnum++) { ++ newargs[newargnum++] = args[argnum]; ++ } ++ } ++ newargs[newargnum] = NULL; ++ ++ /* free old args array but not component strings - this assumes that ++ args was allocated with malloc as copy_args does. DO NOT DO THIS ++ on the original argv. ++ */ ++ if (free_args) ++ free(args); ++ ++ *pargs = newargs; ++ ++ return newargnum; ++} ++ ++/* ------------------------------------- */ ++ ++/* get_shortopt ++ * ++ * Get next short option from arg. The state is stored in argnum, optchar, and ++ * option_num so no static storage is used. Returns the option_ID. ++ * ++ * parameters: ++ * option_group - either UZO for UnZip options or ZIO for ZipInfo options ++ * args - argv array of arguments ++ * argnum - index of current arg in args ++ * optchar - pointer to index of next char to process. Can be 0 or ++ * const defined at top of this file like THIS_ARG_DONE ++ * negated - on return pointer to int set to 1 if option negated ++ * or 0 otherwise ++ * value - on return pointer to string set to value of option if any ++ * or NULL if none. If value is returned then the caller ++ * should free() it when not needed anymore. ++ * option_num - pointer to index in options[] of returned option or ++ * o_NO_OPTION_MATCH if none. Do not change as used by ++ * value lists. ++ * depth - recursion depth (0 at top level, 1 or more in arg files) ++ */ ++static unsigned long get_shortopt(option_group, args, argnum, optchar, negated, ++ value, option_num, depth) ++ int option_group; ++ ZCONST char **args; ++ int argnum; ++ int *optchar; ++ int *negated; ++ char **value; ++ int *option_num; ++ int depth; ++{ ++ ZCONST char *shortopt; ++ int clen; ++ ZCONST char *nextchar; ++ ZCONST char *s; ++ ZCONST char *start; ++ int op; ++ ZCONST char *arg; ++ int match = -1; ++ ++ ++ /* get arg */ ++ arg = args[argnum]; ++ /* current char in arg */ ++ nextchar = arg + (*optchar); ++ clen = MB_CLEN(nextchar); ++ /* next char in arg */ ++ (*optchar) += clen; ++ /* get first char of short option */ ++ shortopt = arg + (*optchar); ++ /* no value */ ++ *value = NULL; ++ ++ if (*shortopt == '\0') { ++ /* no more options in arg */ ++ *optchar = 0; ++ *option_num = o_NO_OPTION_MATCH; ++ return 0; ++ } ++ ++ /* look for match in options */ ++ clen = MB_CLEN(shortopt); ++ for (op = 0; options[op].option_ID; op++) { ++ /* Only look at options in this option group */ ++ if (options[op].option_group == option_group) { ++ s = options[op].shortopt; ++ if (s && s[0] == shortopt[0]) { ++ if (s[1] == '\0' && clen == 1) { ++ /* single char match */ ++ match = op; ++ } else { ++ /* 2 wide short opt. Could support more chars but should use long opts instead */ ++ if (s[1] == shortopt[1]) { ++ /* match 2 char short opt or 2 byte char */ ++ match = op; ++ if (clen == 1) (*optchar)++; ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++ if (match > -1) { ++ /* match */ ++ clen = MB_CLEN(shortopt); ++ nextchar = arg + (*optchar) + clen; ++ /* check for trailing dash negating option */ ++ if (*nextchar == '-') { ++ /* negated */ ++ if (options[match].negatable == o_NOT_NEGATABLE) { ++ if (options[match].value_type == o_NO_VALUE) { ++ optionerr(options, optionerrbuf, op_not_neg_err, match, 0); ++ if (depth > 0) { ++ /* unwind */ ++ oWARN(optionerrbuf); ++ return o_ARG_FILE_ERR; ++ } else { ++ oWARN(optionerrbuf); ++ return o_BAD_ERR; ++ } ++ } ++ } else { ++ *negated = 1; ++ /* set up to skip negating dash */ ++ (*optchar) += clen; ++ clen = 1; ++ } ++ } ++ ++ /* value */ ++ clen = MB_CLEN(arg + (*optchar)); ++ /* optional value, one char value, and number value must follow option */ ++ if (options[match].value_type == o_ONE_CHAR_VALUE) { ++ /* one char value */ ++ if (arg[(*optchar) + clen]) { ++ /* has value */ ++ if (MB_CLEN(arg + (*optchar) + clen) > 1) { ++ /* multibyte value not allowed for now */ ++ optionerr(options, optionerrbuf, oco_no_mbc_err, match, 0); ++ if (depth > 0) { ++ /* unwind */ ++ oWARN(optionerrbuf); ++ return o_ARG_FILE_ERR; ++ } else { ++ oWARN(optionerrbuf); ++ return o_BAD_ERR; ++ } ++ } ++ if ((*value = (char *) malloc(2)) == NULL) { ++ oWARN("memory - gso"); ++ return o_BAD_ERR; ++ } ++ (*value)[0] = *(arg + (*optchar) + clen); ++ (*value)[1] = '\0'; ++ *optchar += clen; ++ clen = 1; ++ } else { ++ /* one char values require a value */ ++ optionerr(options, optionerrbuf, oco_req_val_err, match, 0); ++ if (depth > 0) { ++ oWARN(optionerrbuf); ++ return o_ARG_FILE_ERR; ++ } else { ++ oWARN(optionerrbuf); ++ return o_BAD_ERR; ++ } ++ } ++ } else if (options[match].value_type == o_NUMBER_VALUE) { ++ /* read chars until end of number */ ++ start = arg + (*optchar) + clen; ++ if (*start == '+' || *start == '-') { ++ start++; ++ } ++ s = start; ++ for (; isdigit(*s); MB_NEXTCHAR(s)) ; ++ if (s == start) { ++ /* no digits */ ++ optionerr(options, optionerrbuf, num_req_val_err, match, 0); ++ if (depth > 0) { ++ oWARN(optionerrbuf); ++ return o_ARG_FILE_ERR; ++ } else { ++ oWARN(optionerrbuf); ++ return o_BAD_ERR; ++ } ++ } ++ start = arg + (*optchar) + clen; ++ if ((*value = (char *) malloc((int)(s - start) + 1)) == NULL) { ++ oWARN("memory - gso"); ++ return o_BAD_ERR; ++ } ++ *optchar += (int)(s - start); ++ strncpy(*value, start, (int)(s - start)); ++ (*value)[(int)(s - start)] = '\0'; ++ clen = MB_CLEN(s); ++ } else if (options[match].value_type == o_OPTIONAL_VALUE) { ++ /* optional value */ ++ /* This seemed inconsistent so now if no value attached to argument look ++ to the next argument if that argument is not an option for option ++ value - 11/12/04 EG */ ++ if (arg[(*optchar) + clen]) { ++ /* has value */ ++ /* add support for optional = - 2/6/05 EG */ ++ if (arg[(*optchar) + clen] == '=') { ++ /* skip = */ ++ clen++; ++ } ++ if (arg[(*optchar) + clen]) { ++ if ((*value = (char *)malloc(strlen(arg + (*optchar) + clen) + 1)) ++ == NULL) { ++ oWARN("memory - gso"); ++ return o_BAD_ERR; ++ } ++ strcpy(*value, arg + (*optchar) + clen); ++ } ++ *optchar = THIS_ARG_DONE; ++ } else if (args[argnum + 1] && args[argnum + 1][0] != '-') { ++ /* use next arg for value */ ++ if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) == NULL) { ++ oWARN("memory - gso"); ++ return o_BAD_ERR; ++ } ++ /* using next arg as value */ ++ strcpy(*value, args[argnum + 1]); ++ *optchar = SKIP_VALUE_ARG; ++ } ++ } else if (options[match].value_type == o_REQUIRED_VALUE || ++ options[match].value_type == o_VALUE_LIST) { ++ /* see if follows option */ ++ if (arg[(*optchar) + clen]) { ++ /* has value following option as -ovalue */ ++ /* add support for optional = - 6/5/05 EG */ ++ if (arg[(*optchar) + clen] == '=') { ++ /* skip = */ ++ clen++; ++ } ++ if ((*value = (char *)malloc(strlen(arg + (*optchar) + clen) + 1)) ++ == NULL) { ++ oWARN("memory - gso"); ++ return o_BAD_ERR; ++ } ++ strcpy(*value, arg + (*optchar) + clen); ++ *optchar = THIS_ARG_DONE; ++ } else { ++ /* use next arg for value */ ++ if (args[argnum + 1]) { ++ if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) ++ == NULL) { ++ oWARN("memory - gso"); ++ return o_BAD_ERR; ++ } ++ strcpy(*value, args[argnum + 1]); ++ if (options[match].value_type == o_VALUE_LIST) { ++ *optchar = START_VALUE_LIST; ++ } else { ++ *optchar = SKIP_VALUE_ARG; ++ } ++ } else { ++ /* no value found */ ++ optionerr(options, optionerrbuf, op_req_val_err, match, 0); ++ if (depth > 0) { ++ oWARN(optionerrbuf); ++ return o_ARG_FILE_ERR; ++ } else { ++ oWARN(optionerrbuf); ++ return o_BAD_ERR; ++ } ++ } ++ } ++ } ++ ++ *option_num = match; ++ return options[match].option_ID; ++ } ++ sprintf(optionerrbuf, LoadFarStringSmall(sh_op_not_sup_err), *shortopt); ++ if (depth > 0) { ++ /* unwind */ ++ oWARN(optionerrbuf); ++ return o_ARG_FILE_ERR; ++ } else { ++ oWARN(optionerrbuf); ++ return o_BAD_ERR; ++ } ++ return 0; ++} ++ ++ ++/* get_longopt ++ * ++ * Get the long option in args array at argnum. ++ * Parameters same as for get_shortopt. ++ */ ++ ++static unsigned long get_longopt(option_group, args, argnum, optchar, negated, ++ value, option_num, depth) ++ int option_group; ++ ZCONST char **args; ++ int argnum; ++ int *optchar; ++ int *negated; ++ char **value; ++ int *option_num; ++ int depth; ++{ ++ char *longopt; ++ char *lastchr; ++ char *valuestart; ++ int op; ++ char *arg; ++ int match = -1; ++ *value = NULL; ++ ++ if (args == NULL) { ++ *option_num = o_NO_OPTION_MATCH; ++ return 0; ++ } ++ if (args[argnum] == NULL) { ++ *option_num = o_NO_OPTION_MATCH; ++ return 0; ++ } ++ /* copy arg so can chop end if value */ ++ if ((arg = (char *)malloc(strlen(args[argnum]) + 1)) == NULL) { ++ oWARN("memory - glo"); ++ return o_BAD_ERR; ++ } ++ strcpy(arg, args[argnum]); ++ ++ /* get option */ ++ longopt = arg + 2; ++ /* no value */ ++ *value = NULL; ++ ++ /* find = */ ++ for (lastchr = longopt, valuestart = longopt; ++ *valuestart && *valuestart != '='; ++ lastchr = valuestart, MB_NEXTCHAR(valuestart)) ; ++ if (*valuestart) { ++ /* found =value */ ++ *valuestart = '\0'; ++ valuestart++; ++ } else { ++ valuestart = NULL; ++ } ++ ++ if (*lastchr == '-') { ++ /* option negated */ ++ *negated = 1; ++ *lastchr = '\0'; ++ } else { ++ *negated = 0; ++ } ++ ++ /* look for long option match */ ++ for (op = 0; options[op].option_ID; op++) { ++ /* Only look at options in the option group */ ++ if (options[op].option_group == option_group) { ++ if (options[op].longopt && ++ strcmp(LoadFarStringSmall(options[op].longopt), longopt) == 0) { ++ /* exact match */ ++ match = op; ++ break; ++ } ++ if (options[op].longopt && ++ strncmp(LoadFarStringSmall(options[op].longopt), ++ longopt, strlen(longopt)) == 0) { ++ if (match > -1) { ++ sprintf(optionerrbuf, LoadFarStringSmall(long_op_ambig_err), ++ longopt); ++ free(arg); ++ if (depth > 0) { ++ /* unwind */ ++ oWARN(optionerrbuf); ++ return o_ARG_FILE_ERR; ++ } else { ++ oWARN(optionerrbuf); ++ return o_BAD_ERR; ++ } ++ } ++ match = op; ++ } ++ } ++ } ++ ++ if (match == -1) { ++ sprintf(optionerrbuf, LoadFarStringSmall(long_op_not_sup_err), longopt); ++ free(arg); ++ if (depth > 0) { ++ oWARN(optionerrbuf); ++ return o_ARG_FILE_ERR; ++ } else { ++ oWARN(optionerrbuf); ++ return o_BAD_ERR; ++ } ++ } ++ ++ /* one long option an arg */ ++ *optchar = THIS_ARG_DONE; ++ ++ /* if negated then see if allowed */ ++ if (*negated && options[match].negatable == o_NOT_NEGATABLE) { ++ optionerr(options, optionerrbuf, op_not_neg_err, match, 1); ++ free(arg); ++ if (depth > 0) { ++ /* unwind */ ++ oWARN(optionerrbuf); ++ return o_ARG_FILE_ERR; ++ } else { ++ oWARN(optionerrbuf); ++ return o_BAD_ERR; ++ } ++ } ++ /* get value */ ++ if (options[match].value_type == o_OPTIONAL_VALUE) { ++ /* optional value in form option=value */ ++ if (valuestart) { ++ /* option=value */ ++ if ((*value = (char *)malloc(strlen(valuestart) + 1)) == NULL) { ++ free(arg); ++ oWARN("memory - glo"); ++ return o_BAD_ERR; ++ } ++ strcpy(*value, valuestart); ++ } ++ } else if (options[match].value_type == o_REQUIRED_VALUE || ++ options[match].value_type == o_NUMBER_VALUE || ++ options[match].value_type == o_ONE_CHAR_VALUE || ++ options[match].value_type == o_VALUE_LIST) { ++ /* handle long option one char and number value as required value */ ++ if (valuestart) { ++ /* option=value */ ++ if ((*value = (char *)malloc(strlen(valuestart) + 1)) == NULL) { ++ free(arg); ++ oWARN("memory - glo"); ++ return o_BAD_ERR; ++ } ++ strcpy(*value, valuestart); ++ } else { ++ /* use next arg */ ++ if (args[argnum + 1]) { ++ if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) == NULL) { ++ free(arg); ++ oWARN("memory - glo"); ++ return o_BAD_ERR; ++ } ++ /* using next arg as value */ ++ strcpy(*value, args[argnum + 1]); ++ if (options[match].value_type == o_VALUE_LIST) { ++ *optchar = START_VALUE_LIST; ++ } else { ++ *optchar = SKIP_VALUE_ARG; ++ } ++ } else { ++ /* no value found */ ++ optionerr(options, optionerrbuf, op_req_val_err, match, 1); ++ free(arg); ++ if (depth > 0) { ++ /* unwind */ ++ oWARN(optionerrbuf); ++ return o_ARG_FILE_ERR; ++ } else { ++ oWARN(optionerrbuf); ++ return o_BAD_ERR; ++ } ++ } ++ } ++ } else if (options[match].value_type == o_NO_VALUE) { ++ /* this option does not accept a value */ ++ if (valuestart) { ++ /* --option=value */ ++ optionerr(options, optionerrbuf, op_no_allow_val_err, match, 1); ++ free(arg); ++ if (depth > 0) { ++ oWARN(optionerrbuf); ++ return o_ARG_FILE_ERR; ++ } else { ++ oWARN(optionerrbuf); ++ return o_BAD_ERR; ++ } ++ } ++ } ++ free(arg); ++ ++ *option_num = match; ++ return options[match].option_ID; ++} ++ ++ ++ ++/* get_option ++ * ++ * Main interface for user. Use this function to get options, values and ++ * non-option arguments from a command line provided in argv form. ++ * ++ * To use get_option() first define valid options by setting ++ * the global variable options[] to an array of option_struct. Also ++ * either change defaults below or make variables global and set elsewhere. ++ * Zip uses below defaults. ++ * ++ * Call get_option() to get an option (like -b or --temp-file) and any ++ * value for that option (like filename for -b) or a non-option argument ++ * (like archive name) each call. If *value* is not NULL after calling ++ * get_option() it is a returned value and the caller should either store ++ * the char pointer or free() it before calling get_option() again to avoid ++ * leaking memory. If a non-option non-value argument is returned get_option() ++ * returns o_NON_OPTION_ARG and value is set to the entire argument. ++ * When there are no more arguments get_option() returns 0. ++ * ++ * The parameters argnum (after set to 0 on initial call), ++ * optchar, first_nonopt_arg, option_num, and depth (after initial ++ * call) are set and maintained by get_option() and should not be ++ * changed. The parameters argc, negated, and value are outputs and ++ * can be used by the calling program. get_option() returns either the ++ * option_ID for the current option, a special value defined in ++ * zip.h, or 0 when no more arguments. ++ * ++ * The value returned by get_option() is the ID value in the options ++ * table. This value can be duplicated in the table if different ++ * options are really the same option. The index into the options[] ++ * table is given by option_num, though the ID should be used as ++ * option numbers change when the table is changed. The ID must ++ * not be 0 for any option as this ends the table. If get_option() ++ * finds an option not in the table it calls oERR to post an ++ * error and exit. Errors also result if the option requires a ++ * value that is missing, a value is present but the option does ++ * not take one, and an option is negated but is not ++ * negatable. Non-option arguments return o_NON_OPTION_ARG ++ * with the entire argument in value. ++ * ++ * For Zip and UnZip, permuting is on and all options and their values ++ * are returned before any non-option arguments like archive name. ++ * ++ * The arguments "-" alone and "--" alone return as non-option arguments. ++ * Note that "-" should not be used as part of a short option ++ * entry in the table but can be used in the middle of long ++ * options such as in the long option "a-long-option". Now "--" alone ++ * stops option processing, returning any arguments following "--" as ++ * non-option arguments instead of options. ++ * ++ * Argument file support is removed from this version. It may be added later. ++ * ++ * After each call: ++ * argc is set to the current size of args[] but should not change ++ * with argument file support removed, ++ * argnum is the index of the current arg, ++ * value is either the value of the returned option or non-option ++ * argument or NULL if option with no value, ++ * negated is set if the option was negated by a trailing dash (-) ++ * option_num is set to either the index in options[] for the option or ++ * o_NO_OPTION_MATCH if no match. ++ * Negation is checked before the value is read if the option is negatable so ++ * that the - is not included in the value. If the option is not negatable ++ * but takes a value then the - will start the value. If permuting then ++ * argnum and first_nonopt_arg are unreliable and should not be used. ++ * ++ * Command line is read from left to right. As get_option() finds non-option ++ * arguments (arguments not starting with - and that are not values to options) ++ * it moves later options and values in front of the non-option arguments. ++ * This permuting is turned off by setting enable_permute to 0. Then ++ * get_option() will return options and non-option arguments in the order ++ * found. Currently permuting is only done after an argument is completely ++ * processed so that any value can be moved with options they go with. All ++ * state information is stored in the parameters argnum, optchar, ++ * first_nonopt_arg and option_num. You should not change these after the ++ * first call to get_option(). If you need to back up to a previous arg then ++ * set argnum to that arg (remembering that args may have been permuted) and ++ * set optchar = 0 and first_nonopt_arg to the first non-option argument if ++ * permuting. After all arguments are returned the next call to get_option() ++ * returns 0. The caller can then call free_args(args) if appropriate. ++ * ++ * get_option() accepts arguments in the following forms: ++ * short options ++ * of 1 and 2 characters, e.g. a, b, cc, d, and ba, after a single ++ * leading -, as in -abccdba. In this example if 'b' is followed by 'a' ++ * it matches short option 'ba' else it is interpreted as short option ++ * b followed by another option. The character - is not legal as a ++ * short option or as part of a 2 character short option. ++ * ++ * If a short option has a value it immediately follows the option or ++ * if that option is the end of the arg then the next arg is used as ++ * the value. So if short option e has a value, it can be given as ++ * -evalue ++ * or ++ * -e value ++ * and now ++ * -e=value ++ * but now that = is optional a leading = is stripped for the first. ++ * This change allows optional short option values to be defaulted as ++ * -e= ++ * Either optional or required values can be specified. Optional values ++ * now use both forms as ignoring the later got confusing. Any ++ * non-value short options can preceed a valued short option as in ++ * -abevalue ++ * Some value types (one_char and number) allow options after the value ++ * so if oc is an option that takes a character and n takes a number ++ * then ++ * -abocVccn42evalue ++ * returns value V for oc and value 42 for n. All values are strings ++ * so programs may have to convert the "42" to a number. See long ++ * options below for how value lists are handled. ++ * ++ * Any short option can be negated by following it with -. Any - is ++ * handled and skipped over before any value is read unless the option ++ * is not negatable but takes a value and then - starts the value. ++ * ++ * If the value for an optional value is just =, then treated as no ++ * value. ++ * ++ * long options ++ * of arbitrary length are assumed if an arg starts with -- but is not ++ * exactly --. Long options are given one per arg and can be abbreviated ++ * if the abbreviation uniquely matches one of the long options. ++ * Exact matches always match before partial matches. If ambiguous an ++ * error is generated. ++ * ++ * Values are specified either in the form ++ * --longoption=value ++ * or can be the following arg if the value is required as in ++ * --longoption value ++ * Optional values to long options must be in the first form. ++ * ++ * Value lists are specified by o_VALUE_LIST and consist of an option ++ * that takes a value followed by one or more value arguments. ++ * The two forms are ++ * --option=value ++ * or ++ * -ovalue ++ * for a single value or ++ * --option value1 value2 value3 ... --option2 ++ * or ++ * -o value1 value2 value3 ... ++ * for a list of values. The list ends at the next option, the ++ * end of the command line, or at a single "@" argument. ++ * Each value is treated as if it was preceeded by the option, so ++ * --option1 val1 val2 ++ * with option1 value_type set to o_VALUE_LIST is the same as ++ * --option1=val1 --option1=val2 ++ * ++ * Long options can be negated by following the option with - as in ++ * --longoption- ++ * Long options with values can also be negated if this makes sense for ++ * the caller as: ++ * --longoption-=value ++ * If = is not followed by anything it is treated as no value. ++ * ++ * @path ++ * Argument files support removed from this version. It may be added ++ * back later. ++ * ++ * non-option argument ++ * is any argument not given above. If enable_permute is 1 then ++ * these are returned after all options, otherwise all options and ++ * args are returned in order. Returns option ID o_NON_OPTION_ARG ++ * and sets value to the argument. ++ * ++ * ++ * Arguments to get_option: ++ * int option_group - either UZO for UnZip or ZIO for ZipInfo ++ * char ***pargs - pointer to arg array in the argv form ++ * int *argc - returns the current argc for args incl. args[0] ++ * int *argnum - the index of the current argument (caller ++ * should set = 0 on first call and not change ++ * after that) ++ * int *optchar - index of next short opt in arg or special ++ * int *first_nonopt_arg - used by get_option to permute args ++ * int *negated - option was negated (had trailing -) ++ * char *value - value of option if any (free when done with it) ++ * or NULL ++ * int *option_num - the index in options of the last option returned ++ * (can be o_NO_OPTION_MATCH) ++ * int recursion_depth - current depth of recursion ++ * (always set to 0 by caller) ++ * (always 0 with argument files support removed) ++ * ++ * Caller should only read the returned option ID and the value, negated, ++ * and option_num (if required) parameters after each call. ++ * ++ * Ed Gordon ++ * 8/24/2003 (last updated 3/1/2008 EG) ++ * ++ */ ++ ++unsigned long get_option(option_group, pargs, argc, argnum, optchar, value, ++ negated, first_nonopt_arg, option_num, recursion_depth) ++ int option_group; ++ char ***pargs; ++ int *argc; ++ int *argnum; ++ int *optchar; ++ char **value; ++ int *negated; ++ int *first_nonopt_arg; ++ int *option_num; ++ int recursion_depth; ++{ ++ char **args; ++ unsigned long option_ID; ++ ++ int argcnt; ++ int first_nonoption_arg; ++ char *arg = NULL; ++ int h; ++ int optc; ++ int argn; ++ int j; ++ int v; ++ int read_rest_args_verbatim = 0; /* 7/25/04 - ignore options and arg files for rest args */ ++ ++ /* caller should free value or assign it to another ++ variable before calling get_option again. */ ++ *value = NULL; ++ ++ /* if args is NULL then done */ ++ if (pargs == NULL) { ++ *argc = 0; ++ return 0; ++ } ++ args = *pargs; ++ if (args == NULL) { ++ *argc = 0; ++ return 0; ++ } ++ ++ /* count args */ ++ for (argcnt = 0; args[argcnt]; argcnt++) ; ++ ++ /* if no provided args then nothing to do */ ++ if (argcnt < 1 || (recursion_depth == 0 && argcnt < 2)) { ++ *argc = argcnt; ++ /* return 0 to note that no args are left */ ++ return 0; ++ } ++ ++ *negated = 0; ++ first_nonoption_arg = *first_nonopt_arg; ++ argn = *argnum; ++ optc = *optchar; ++ ++ if (optc == READ_REST_ARGS_VERBATIM) { ++ read_rest_args_verbatim = 1; ++ } ++ ++ if (argn == -1 || (recursion_depth == 0 && argn == 0)) { ++ /* first call */ ++ /* if depth = 0 then args[0] is argv[0] so skip */ ++ *option_num = o_NO_OPTION_MATCH; ++ optc = THIS_ARG_DONE; ++ first_nonoption_arg = -1; ++ } ++ ++ /* if option_num is set then restore last option_ID in case continuing ++ value list */ ++ option_ID = 0; ++ if (*option_num != o_NO_OPTION_MATCH) { ++ option_ID = options[*option_num].option_ID; ++ } ++ ++ /* get next option if any */ ++ for (;;) { ++ if (read_rest_args_verbatim) { ++ /* rest of args after "--" are non-option args if doubledash_ends_options ++ set */ ++ argn++; ++ if (argn > argcnt || args[argn] == NULL) { ++ /* done */ ++ option_ID = 0; ++ break; ++ } ++ arg = args[argn]; ++ if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) { ++ oWARN("memory - go"); ++ return o_BAD_ERR; ++ } ++ strcpy(*value, arg); ++ *option_num = o_NO_OPTION_MATCH; ++ option_ID = o_NON_OPTION_ARG; ++ break; ++ ++ /* permute non-option args after option args so options are returned ++ first */ ++ } else if (enable_permute) { ++ if (optc == SKIP_VALUE_ARG || optc == THIS_ARG_DONE || ++ optc == START_VALUE_LIST || optc == IN_VALUE_LIST || ++ optc == STOP_VALUE_LIST) { ++ /* moved to new arg */ ++ if (first_nonoption_arg > -1 && args[first_nonoption_arg]) { ++ /* do the permuting - move non-options after this option */ ++ /* if option and value separate args or starting list skip option */ ++ if (optc == SKIP_VALUE_ARG || optc == START_VALUE_LIST) { ++ v = 1; ++ } else { ++ v = 0; ++ } ++ for (h = first_nonoption_arg; h < argn; h++) { ++ arg = args[first_nonoption_arg]; ++ for (j = first_nonoption_arg; j < argn + v; j++) { ++ args[j] = args[j + 1]; ++ } ++ args[j] = arg; ++ } ++ first_nonoption_arg += 1 + v; ++ } ++ } ++ } else if (optc == NON_OPTION_ARG) { ++ /* if not permuting then already returned arg */ ++ optc = THIS_ARG_DONE; ++ } ++ ++ /* value lists */ ++ if (optc == STOP_VALUE_LIST) { ++ optc = THIS_ARG_DONE; ++ } ++ ++ if (optc == START_VALUE_LIST || optc == IN_VALUE_LIST) { ++ if (optc == START_VALUE_LIST) { ++ /* already returned first value */ ++ argn++; ++ optc = IN_VALUE_LIST; ++ } ++ argn++; ++ arg = args[argn]; ++ /* if end of args and still in list and there are non-option args then ++ terminate list */ ++ if (arg == NULL && (optc == START_VALUE_LIST || optc == IN_VALUE_LIST) ++ && first_nonoption_arg > -1) { ++ /* terminate value list with @ */ ++ /* this is only needed for argument files */ ++ /* but is also good for show command line so command lines with lists ++ can always be read back in */ ++ argcnt = insert_arg(&args, "@", first_nonoption_arg, 1); ++ argn++; ++ if (first_nonoption_arg > -1) { ++ first_nonoption_arg++; ++ } ++ } ++ ++ arg = args[argn]; ++ if (arg && arg[0] == '@' && arg[1] == '\0') { ++ /* inserted arguments terminator */ ++ optc = STOP_VALUE_LIST; ++ continue; ++ } else if (arg && arg[0] != '-') { /* not option */ ++ /* - and -- are not allowed in value lists unless escaped */ ++ /* another value in value list */ ++ if ((*value = (char *)malloc(strlen(args[argn]) + 1)) == NULL) { ++ oWARN("memory - go"); ++ return o_BAD_ERR; ++ } ++ strcpy(*value, args[argn]); ++ break; ++ ++ } else { ++ argn--; ++ optc = THIS_ARG_DONE; ++ } ++ } ++ ++ /* move to next arg */ ++ if (optc == SKIP_VALUE_ARG) { ++ argn += 2; ++ optc = 0; ++ } else if (optc == THIS_ARG_DONE) { ++ argn++; ++ optc = 0; ++ } ++ if (argn > argcnt) { ++ break; ++ } ++ if (args[argn] == NULL) { ++ /* done unless permuting and non-option args */ ++ if (first_nonoption_arg > -1 && args[first_nonoption_arg]) { ++ /* return non-option arguments at end */ ++ if (optc == NON_OPTION_ARG) { ++ first_nonoption_arg++; ++ } ++ /* after first pass args are permuted but skipped over non-option ++ args */ ++ /* swap so argn points to first non-option arg */ ++ j = argn; ++ argn = first_nonoption_arg; ++ first_nonoption_arg = j; ++ } ++ if (argn > argcnt || args[argn] == NULL) { ++ /* done */ ++ option_ID = 0; ++ break; ++ } ++ } ++ ++ /* after swap first_nonoption_arg points to end which is NULL */ ++ if (first_nonoption_arg > -1 && (args[first_nonoption_arg] == NULL)) { ++ /* only non-option args left */ ++ if (optc == NON_OPTION_ARG) { ++ argn++; ++ } ++ if (argn > argcnt || args[argn] == NULL) { ++ /* done */ ++ option_ID = 0; ++ break; ++ } ++ if ((*value = (char *)malloc(strlen(args[argn]) + 1)) == NULL) { ++ oWARN("memory - go"); ++ return o_BAD_ERR; ++ } ++ strcpy(*value, args[argn]); ++ optc = NON_OPTION_ARG; ++ option_ID = o_NON_OPTION_ARG; ++ break; ++ } ++ ++ arg = args[argn]; ++ ++ /* is it an option */ ++ if (arg[0] == '-') { ++ /* option */ ++ if (arg[1] == '\0') { ++ /* arg = - */ ++ /* treat like non-option arg */ ++ *option_num = o_NO_OPTION_MATCH; ++ if (enable_permute) { ++ /* permute args to move all non-option args to end */ ++ if (first_nonoption_arg < 0) { ++ first_nonoption_arg = argn; ++ } ++ argn++; ++ } else { ++ /* not permute args so return non-option args when found */ ++ if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) { ++ oWARN("memory - go"); ++ return o_BAD_ERR; ++ } ++ strcpy(*value, arg); ++ optc = NON_OPTION_ARG; ++ option_ID = o_NON_OPTION_ARG; ++ break; ++ } ++ ++ } else if (arg[1] == '-') { ++ /* long option */ ++ if (arg[2] == '\0') { ++ /* arg = -- */ ++ if (doubledash_ends_options) { ++ /* Now -- stops permuting and forces the rest of ++ the command line to be read verbatim - 7/25/04 EG */ ++ ++ /* never permute args after -- and return as non-option args */ ++ if (first_nonoption_arg < 1) { ++ /* -- is first non-option argument - 8/7/04 EG */ ++ argn--; ++ } else { ++ /* go back to start of non-option args - 8/7/04 EG */ ++ argn = first_nonoption_arg - 1; ++ } ++ ++ /* disable permuting and treat remaining arguments as not ++ options */ ++ read_rest_args_verbatim = 1; ++ optc = READ_REST_ARGS_VERBATIM; ++ ++ } else { ++ /* treat like non-option arg */ ++ *option_num = o_NO_OPTION_MATCH; ++ if (enable_permute) { ++ /* permute args to move all non-option args to end */ ++ if (first_nonoption_arg < 0) { ++ first_nonoption_arg = argn; ++ } ++ argn++; ++ } else { ++ /* not permute args so return non-option args when found */ ++ if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) { ++ oWARN("memory - go"); ++ return o_BAD_ERR; ++ } ++ strcpy(*value, arg); ++ optc = NON_OPTION_ARG; ++ option_ID = o_NON_OPTION_ARG; ++ break; ++ } ++ } ++ ++ } else { ++ option_ID = get_longopt(option_group, (ZCONST char **)args, argn, ++ &optc, negated, ++ value, option_num, recursion_depth); ++ if (option_ID == o_BAD_ERR) { ++ return o_BAD_ERR; ++ } else if (option_ID == o_ARG_FILE_ERR) { ++ /* unwind as only get this if recursion_depth > 0 */ ++ return option_ID; ++ } ++ break; ++ } ++ ++ } else { ++ /* short option */ ++ option_ID = get_shortopt(option_group, (ZCONST char **)args, argn, ++ &optc, negated, ++ value, option_num, recursion_depth); ++ ++ if (option_ID == o_BAD_ERR) { ++ return o_BAD_ERR; ++ } else if (option_ID == o_ARG_FILE_ERR) { ++ /* unwind as only get this if recursion_depth > 0 */ ++ return option_ID; ++ } ++ ++ if (optc == 0) { ++ /* if optc = 0 then ran out of short opts this arg */ ++ optc = THIS_ARG_DONE; ++ } else { ++ break; ++ } ++ } ++ ++#if 0 ++ /* argument file code left out ++ so for now let filenames start with @ ++ */ ++ ++ } else if (allow_arg_files && arg[0] == '@') { ++ /* arg file */ ++ oERR(PK_PARMS, no_arg_files_err); ++#endif ++ ++ } else { ++ /* non-option */ ++ if (enable_permute) { ++ /* permute args to move all non-option args to end */ ++ if (first_nonoption_arg < 0) { ++ first_nonoption_arg = argn; ++ } ++ argn++; ++ } else { ++ /* no permute args so return non-option args when found */ ++ if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) { ++ oWARN("memory - go"); ++ return o_BAD_ERR; ++ } ++ strcpy(*value, arg); ++ *option_num = o_NO_OPTION_MATCH; ++ optc = NON_OPTION_ARG; ++ option_ID = o_NON_OPTION_ARG; ++ break; ++ } ++ ++ } ++ } ++ ++ *pargs = args; ++ *argc = argcnt; ++ *first_nonopt_arg = first_nonoption_arg; ++ *argnum = argn; ++ *optchar = optc; ++ ++ return option_ID; ++} +diff -ru2 unz60e03/unzpriv.h u6e3_np/unzpriv.h +--- unz60e03/unzpriv.h Mon Mar 24 11:53:24 2008 ++++ u6e3_np/unzpriv.h Mon Mar 24 14:13:02 2008 +@@ -1271,4 +1271,89 @@ + #endif + ++ ++/*-------------------------------------------------------------------- ++ Long option support ++ 23 August 2003 ++ Updated for UnZip 1 March 2008 ++ See unzip.c ++ --------------------------------------------------------------------*/ ++ ++/* The below is for use in the caller-provided options table */ ++ ++/* option groups */ ++#define UZO 1 /* UnZip option */ ++#define ZIO 2 /* ZipInfo option */ ++ ++ ++/* value_type - value is always returned as a string. */ ++#define o_NO_VALUE 0 /* this option does not take a value */ ++#define o_REQUIRED_VALUE 1 /* this option requires a value */ ++#define o_OPTIONAL_VALUE 2 /* value is optional (see get_option() for details) */ ++#define o_VALUE_LIST 3 /* this option takes a list of values */ ++#define o_ONE_CHAR_VALUE 4 /* next char is value (does not end short opt string) */ ++#define o_NUMBER_VALUE 5 /* value is integer (does not end short opt string) */ ++ ++ ++/* negatable - a dash following the option (but before any value) sets negated. */ ++#define o_NOT_NEGATABLE 0 /* trailing '-' to negate either starts value or generates error */ ++#define o_NEGATABLE 1 /* trailing '-' sets negated to TRUE */ ++ ++ ++/* option_num can be this when option not in options table */ ++#define o_NO_OPTION_MATCH -1 ++ ++/* special values returned by get_option - do not use these as option IDs */ ++#define o_NON_OPTION_ARG ((unsigned long) 0xFFFF) /* returned for non-option ++ args */ ++#define o_ARG_FILE_ERR ((unsigned long) 0xFFFE) /* internal recursion ++ return (user never sees) */ ++#define o_BAD_ERR ((unsigned long) 0xFFFD) /* bad error */ ++ ++/* options array is set in unzip.c */ ++struct option_struct { ++ int option_group; /* either UZO for UnZip or ZIO for ZipInfo syntax */ ++ char Far *shortopt; /* pointer to short option string */ ++ char Far *longopt; /* pointer to long option string */ ++ int value_type; /* from above */ ++ int negatable; /* from above */ ++ unsigned long option_ID; /* value returned by get_option when this option ++ is found */ ++ char Far *name; /* optional string for option returned on some ++ errors */ ++}; ++ ++/* structure used to create -x and include file lists */ ++struct file_list { ++ char *name; ++ struct file_list *next; ++}; ++ ++ ++/* function prototypes */ ++ ++/* get the next option from args */ ++unsigned long get_option OF((int option_group, ++ char ***pargs, int *argc, int *argnum, ++ int *optchar, ++ char **value, int *negated, int *first_nonopt_arg, ++ int *option_num, int recursion_depth)); ++ ++/* copy args - copy an args array, allocating space as needed */ ++char **copy_args OF((char **args, int max_args)); ++ ++/* arg count - count args in argv like array */ ++int arg_count OF((char **args)); ++ ++/* free args - free args created with one of these functions */ ++int free_args OF((char **args)); ++ ++/* insert arg - copy an arg into args */ ++int insert_arg OF((char ***args, ZCONST char *arg, int insert_at, ++ int free_args)); ++ ++/*-------------------------------------------------------------------- ++ End of Long option support ++ --------------------------------------------------------------------*/ ++ + /***********************************/ + /* LARGE_FILE_SUPPORT */ +diff -ru2 unz60e03/vms/cmdline.c u6e3_np/vms/cmdline.c +--- unz60e03/vms/cmdline.c Tue Feb 12 01:37:42 2008 ++++ u6e3_np/vms/cmdline.c Mon Mar 24 14:13:10 2008 +@@ -34,4 +34,6 @@ + ** Modified by: + ** ++** 02-014 E. Gordon 10-Mar-2008 03:12 ++** Modified to work with get_options(). + ** 02-013 S. Schweda, C. Spieler 29-Dec-2007 03:34 + ** Extended /RESTORE qualifier to support timestamp restoration +@@ -172,10 +174,10 @@ + $DESCRIPTOR(cli_text_auto, "TEXT.AUTO"); /* -a */ + $DESCRIPTOR(cli_text_all, "TEXT.ALL"); /* -aa */ +-$DESCRIPTOR(cli_text_none, "TEXT.NONE"); /* ---a */ ++$DESCRIPTOR(cli_text_none, "TEXT.NONE"); /* -a- */ + $DESCRIPTOR(cli_text_stmlf, "TEXT.STMLF"); /* -S */ + $DESCRIPTOR(cli_binary, "BINARY"); /* -b[b] */ + $DESCRIPTOR(cli_binary_auto, "BINARY.AUTO"); /* -b */ + $DESCRIPTOR(cli_binary_all, "BINARY.ALL"); /* -bb */ +-$DESCRIPTOR(cli_binary_none, "BINARY.NONE"); /* ---b */ ++$DESCRIPTOR(cli_binary_none, "BINARY.NONE"); /* -b- */ + $DESCRIPTOR(cli_case_insensitive,"CASE_INSENSITIVE"); /* -C */ + $DESCRIPTOR(cli_screen, "SCREEN"); /* -c */ +@@ -202,5 +204,5 @@ + $DESCRIPTOR(cli_restore_own, "RESTORE.OWNER_PROT"); /* -X */ + $DESCRIPTOR(cli_restore_date, "RESTORE.DATE"); /* -DD */ +-$DESCRIPTOR(cli_restore_date_all, "RESTORE.DATE.ALL"); /* --D */ ++$DESCRIPTOR(cli_restore_date_all, "RESTORE.DATE.ALL"); /* -D- */ + $DESCRIPTOR(cli_restore_date_files, "RESTORE.DATE.FILES"); /* -D */ + $DESCRIPTOR(cli_dot_version, "DOT_VERSION"); /* -Y */ +@@ -299,4 +301,6 @@ + ** SS$_ABORT - Bad time value + ** ++** Modified to work with the get_option() command line parser. 10 March 2008 ++** + */ + register unsigned long status; +@@ -419,5 +423,4 @@ + if (status != CLI$_ABSENT) { + *ptr++ = '-'; +- *ptr++ = '-'; + *ptr++ = 'b'; + if ((status & 1) && +@@ -427,4 +430,5 @@ + *ptr++ = 'b'; + } ++ *ptr++ = '-'; + } + +@@ -436,5 +440,4 @@ + if (status != CLI$_ABSENT) { + *ptr++ = '-'; +- *ptr++ = '-'; + *ptr++ = 'a'; + if ((status & 1) && +@@ -446,4 +449,5 @@ + *ptr++ = 'S'; + } ++ *ptr++ = '-'; + } + +diff -ru2 unz60e03/zipinfo.c u6e3_np/zipinfo.c +--- unz60e03/zipinfo.c Mon Mar 24 14:23:54 2008 ++++ u6e3_np/zipinfo.c Mon Mar 24 14:25:24 2008 +@@ -171,4 +171,6 @@ + static ZCONST char Far ZipfileCommTruncMsg[] = + "\ncaution: zipfile comment truncated\n"; ++static ZCONST char Far NoMemArguments[] = ++ "envargs: cannot get memory for arguments"; + + static ZCONST char Far CentralDirEntry[] = +@@ -459,10 +461,48 @@ + __GDEF + { +- char **argv, *s; +- int argc, c, error=FALSE, negative=0; ++ int argc, error=FALSE; + int hflag_slmv=TRUE, hflag_2=FALSE; /* diff options => diff defaults */ + int tflag_slm=TRUE, tflag_2v=FALSE; + int explicit_h=FALSE, explicit_t=FALSE; + ++ char **args; ++ ++ ++ /* used by get_option */ ++ unsigned long option; /* option ID returned by get_option */ ++ int argcnt = 0; /* current argcnt in args */ ++ int argnum = 0; /* arg number */ ++ int optchar = 0; /* option state */ ++ char *value = NULL; /* non-option arg, option value or NULL */ ++ int negative = 0; /* 1 = option negated */ ++ int fna = 0; /* current first non-opt arg */ ++ int optnum = 0; /* index in table */ ++ ++ ++ /* since get_option() returns xfiles and files one at a time, store them in ++ linked lists until have them all */ ++ ++ int file_count; ++ struct file_list *next_file; ++ ++ /* files to extract */ ++ int in_files_count = 0; ++ struct file_list *in_files = NULL; ++ struct file_list *next_in_files = NULL; ++ ++ /* files to exclude in -x list */ ++ int in_xfiles_count = 0; ++ struct file_list *in_xfiles = NULL; ++ struct file_list *next_in_xfiles = NULL; ++ ++ G.wildzipfn = NULL; ++ ++ /* make copy of args that can use with insert_arg() used by get_option() */ ++ args = copy_args(*pargv, 0); ++ ++ ++ /* Initialize lists */ ++ G.filespecs = 0; ++ G.xfilespecs = 0; + + #ifdef MACOS +@@ -470,17 +510,41 @@ + #endif + G.extract_flag = FALSE; /* zipinfo does not extract to disk */ +- argc = *pargc; +- argv = *pargv; + +- while (--argc > 0 && (*++argv)[0] == '-') { +- s = argv[0] + 1; +- while ((c = *s++) != 0) { /* "!= 0": prevent Turbo C warning */ +- switch (c) { +- case '-': +- ++negative; +- break; ++ ++ /* ++ ------------------------------------------- ++ Process command line using get_option ++ ------------------------------------------- ++ ++ Each call to get_option() returns either a command ++ line option and possible value or a non-option argument. ++ Arguments are permuted so that all options (-r, -b temp) ++ are returned before non-option arguments (zipfile). ++ Returns 0 when nothing left to read. ++ */ ++ ++ /* set argnum = 0 on first call to init get_option */ ++ argnum = 0; ++ ++ /* get_option returns the option ID and updates parameters: ++ args - usually same as argv if no argument file support ++ argcnt - current argc for args ++ value - char* to value (free() when done with it) or NULL if no value ++ negated - option was negated with trailing - ++ */ ++ ++ while ((option = get_option(ZIO, &args, &argcnt, &argnum, ++ &optchar, &value, &negative, ++ &fna, &optnum, 0))) ++ { ++ if(option == o_BAD_ERR) { ++ return(PK_PARAM); ++ } ++ ++ switch (option) ++ { + case '1': /* shortest listing: JUST filenames */ + if (negative) +- uO.lflag = -2, negative = 0; ++ uO.lflag = -2; + else + uO.lflag = 1; +@@ -488,5 +552,5 @@ + case '2': /* just filenames, plus headers if specified */ + if (negative) +- uO.lflag = -2, negative = 0; ++ uO.lflag = -2; + else + uO.lflag = 2; +@@ -495,5 +559,5 @@ + case ('C'): /* -C: match filenames case-insensitively */ + if (negative) +- uO.C_flag = FALSE, negative = 0; ++ uO.C_flag = FALSE; + else + uO.C_flag = TRUE; +@@ -502,5 +566,5 @@ + case 'h': /* header line */ + if (negative) +- hflag_2 = hflag_slmv = FALSE, negative = 0; ++ hflag_2 = hflag_slmv = FALSE; + else { + hflag_2 = hflag_slmv = explicit_h = TRUE; +@@ -511,5 +575,5 @@ + case 'l': /* longer form of "ls -l" type listing */ + if (negative) +- uO.lflag = -2, negative = 0; ++ uO.lflag = -2; + else + uO.lflag = 5; +@@ -517,5 +581,5 @@ + case 'm': /* medium form of "ls -l" type listing */ + if (negative) +- uO.lflag = -2, negative = 0; ++ uO.lflag = -2; + else + uO.lflag = 4; +@@ -524,5 +588,5 @@ + case 'M': /* send output through built-in "more" */ + if (negative) +- G.M_flag = FALSE, negative = 0; ++ G.M_flag = FALSE; + else + G.M_flag = TRUE; +@@ -531,5 +595,5 @@ + case 's': /* default: shorter "ls -l" type listing */ + if (negative) +- uO.lflag = -2, negative = 0; ++ uO.lflag = -2; + else + uO.lflag = 3; +@@ -537,5 +601,5 @@ + case 't': /* totals line */ + if (negative) +- tflag_2v = tflag_slm = FALSE, negative = 0; ++ tflag_2v = tflag_slm = FALSE; + else { + tflag_2v = tflag_slm = explicit_t = TRUE; +@@ -546,5 +610,5 @@ + case ('T'): /* use (sortable) decimal time format */ + if (negative) +- uO.T_flag = FALSE, negative = 0; ++ uO.T_flag = FALSE; + else + uO.T_flag = TRUE; +@@ -552,8 +616,7 @@ + #ifdef UNICODE_SUPPORT + case ('U'): /* escape UTF-8, or disable UTF-8 support */ +- if (negative) { +- uO.U_flag = MAX(uO.U_flag-negative,0); +- negative = 0; +- } else ++ if (negative) ++ uO.U_flag = MAX(uO.U_flag - 1, 0); ++ else + uO.U_flag++; + break; +@@ -561,5 +624,5 @@ + case 'v': /* turbo-verbose listing */ + if (negative) +- uO.lflag = -2, negative = 0; ++ uO.lflag = -2; + else + uO.lflag = 10; +@@ -568,12 +631,36 @@ + case ('W'): /* Wildcard interpretation (stop at '/'?) */ + if (negative) +- uO.W_flag = FALSE, negative = 0; ++ uO.W_flag = FALSE; + else + uO.W_flag = TRUE; + break; + #endif /* WILD_STOP_AT_DIR */ ++ case ('x'): /* extract: default */ ++ /* add -x file to linked list */ ++ ++ if (in_xfiles_count == 0) { ++ /* first entry */ ++ if ((in_xfiles = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) { ++ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments))); ++ return PK_MEM; ++ } ++ in_xfiles->name = value; ++ in_xfiles->next = NULL; ++ next_in_xfiles = in_xfiles; ++ } else { ++ /* add next entry */ ++ if ((next_file = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) { ++ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments))); ++ return PK_MEM; ++ } ++ next_in_xfiles->next = next_file; ++ next_file->name = value; ++ next_file->next = NULL; ++ next_in_xfiles = next_file; ++ } ++ in_xfiles_count++; + case 'z': /* print zipfile comment */ + if (negative) +- uO.zflag = negative = 0; ++ uO.zflag = 0; + else + uO.zflag = 1; +@@ -581,13 +668,96 @@ + case 'Z': /* ZipInfo mode: ignore */ + break; ++ case o_NON_OPTION_ARG: ++ /* not an option */ ++ /* no more options as permuting */ ++ ++ ++ if (G.wildzipfn == NULL) { ++ /* first non-option argument is zip file */ ++ G.wildzipfn = value; ++ ++ } else { ++ /* add include file to list */ ++ if (in_files_count == 0) { ++ /* first entry */ ++ if ((next_file = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) { ++ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments))); ++ return PK_MEM; ++ } ++ next_file->name = value; ++ next_file->next = NULL; ++ in_files = next_file; ++ next_in_files = next_file; ++ } else { ++ /* add next entry */ ++ if ((next_file = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) { ++ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments))); ++ return PK_MEM; ++ } ++ next_in_files->next = next_file; ++ next_file->name = value; ++ next_file->next = NULL; ++ next_in_files = next_file; ++ } ++ in_files_count++; ++ } ++ break; + default: + error = TRUE; + break; +- } +- } ++ } /* switch */ ++ } /* get_option() */ ++ ++ /* convert files and xfiles lists to arrays */ ++ ++ /* convert files list to array */ ++ if (in_files_count) { ++ if ((G.pfnames = (char **) malloc((in_files_count + 1) * sizeof(char *))) == NULL) { ++ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments))); ++ return PK_MEM; ++ } ++ file_count = 0; ++ for (next_file = in_files; next_file;) { ++ G.pfnames[file_count] = next_file->name; ++ in_files = next_file; ++ next_file = next_file->next; ++ free(in_files); ++ file_count++; ++ } ++ G.pfnames[file_count] = NULL; ++ G.filespecs = in_files_count; ++ } ++ ++ /* convert xfiles list to array */ ++ if (in_xfiles_count) { ++ if ((G.pxnames = (char **) malloc((in_xfiles_count + 1) * sizeof(char *))) == NULL) { ++ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments))); ++ return PK_MEM; ++ } ++ file_count = 0; ++ for (next_file = in_xfiles; next_file;) { ++ G.pxnames[file_count] = next_file->name; ++ in_xfiles = next_file; ++ next_file = next_file->next; ++ free(in_xfiles); ++ file_count++; ++ } ++ G.pxnames[file_count] = NULL; ++ G.xfilespecs = in_xfiles_count; + } +- if ((argc-- == 0) || error) { ++ ++ if (in_files_count || in_xfiles_count) { ++ G.process_all_files = FALSE; ++ } else { ++ G.process_all_files = TRUE; /* for speed */ ++ } ++ ++ /* it's possible the arg count could have been changed by get_option() */ ++ argc = arg_count(args); ++ ++ if ((G.wildzipfn == NULL) || error) { ++ argc = -1; /* tell the caller to stop processing */ + *pargc = argc; +- *pargv = argv; ++ *pargv = args; + return USAGE(error); + } +@@ -628,5 +798,5 @@ + + *pargc = argc; +- *pargv = argv; ++ *pargv = args; + return 0; + diff --git a/os2/Contents b/os2/Contents new file mode 100644 index 0000000..b251cd9 --- /dev/null +++ b/os2/Contents @@ -0,0 +1,22 @@ +Contents of the "os2" subdirectory for UnZip 5.3 and later: + + Contents this file + makefile.os2 makefile for almost every compiler available under OS/2 + os2.c OS/2-specific support routines + os2data.h OS/2-specific data declarations + os2cfg.h OS/2-specific configuration, included in unzpriv.h + os2acl.c OS/2-specific routines for access-control-list support + os2acl.h OS/2-specific header file for access-control-list support + rexxapi.c interface to integrate UnZip DLL in REXX API + rexxapi.def OS/2 linker definition file for REXX API DLL + rexxhelp.c help function for UnZip's REXX API DLL + rexxtest.cmd REXX script for testing UnZip's REXX API DLL + stub.def OS/2 linker definition file (generic UnZip DLL API) + unzip.def OS/2 linker definition file + zip2exe.cmd REXX script for creating self-extracting archives + zipgrep.cmd really cool REXX script to search for strings in a zipfile + zgrepapi.cmd new version of zipgrep.cmd; takes advantage of REXX API DLL + +There is no support for the ancient Zortech and GCC/2 (Michael Johnson/Colin +Jensen) compilers. The free emx+gcc is supported, as are roughly half a dozen +commercial compilers. diff --git a/os2/makefile.os2 b/os2/makefile.os2 new file mode 100644 index 0000000..005f4f6 --- /dev/null +++ b/os2/makefile.os2 @@ -0,0 +1,662 @@ +# Makefile for UnZip, UnZipSFX and fUnZip 03 January 2007 +# +# supported compilers: +# - Microsoft C, version 6.00 or higher, for use under OS/2 1.x (16-bit) +# - Watcom C/C++, version 9.0+, for use under OS/2 1.x or 2.x+ (16/32-bit) +# - emx+gcc, version 0.9c or higher, for use under OS/2 2.x+ (32-bit) +# - IBM C Set++, for use under OS/2 2.x+ (32-bit) +# - Borland C++, for use under OS/2 2.x+ (32-bit) +# - Metaware High C/C++, for use under OS/2 2.x+ (32-bit) +# +# supported cross-compilers: +# - Microsoft C, version 6.0 or 7.0, for use under DOS (16-bit) +# - Watcom C/C++, version 9.0+, for use under DOS/Win95/NT (16/32-bit) +# - GNU gcc (emx), version 0.9c or higher, for use under DOS/Win95/NT (32-bit) +# +# supported assemblers: +# - Microsoft MASM 6.00 with Microsoft C +# - Watcom WASM with Watcom C/C++ +# - GNU as with GNU gcc + +# To use MASM 5.x instead of MASM 6.00: +# - set AS="masm -t -Ml" +# - set ASEOL=";" + +# To use, enter "{d,n}make -f os2/makefile.os2" (this makefile depends on its +# name being "makefile.os2", and it must be in the os2 subdirectory). + +# In case you want to use Watcom wmake instead, you have to switch wmake into +# the "MS nmake compatible" mode by specifying the "-ms" option. Additionally, +# it is required to override the MAKE macro definition for the recursive +# invokation of wmake. An example: +# wmake -ms -f os2/makefile.os2 MAKE="wmake -ms" watcom + +# Notes on Microsoft C 6.00 compilation for OS/2: +# +# The resulting programs can be used under OS/2 protected mode only, not +# under DOS. A larger stack has to be used for OS/2 because system calls +# use more stack than under DOS; 8k is recommended by Microsoft. + +# Notes on IBM C Set++, Watcom C/C++, Borland C++ or emx+gcc compilation: +# +# The resulting programs can be used under protected mode of OS/2 2.x or +# higher only, not under OS/2 1.x and not under DOS. +# +# The NFLAGS macro is used to work around an optimization bug in the IBM +# C++ Set compiler; this is fixed by CSD #4, so NFLAGS="" can be used for +# all targets below. + +# Notes on Watcom C/C++ compilation for DOS with the PMODE/W extender: +# +# You need to add the following section to your \watcom\binb\wlsystem.lnk +# file and also need to copy pmodew.exe to the same directory: +# +# system begin pmodew +# option osname='PMODE/W' +# libpath %WATCOM%\lib386 +# libpath %WATCOM%\lib386\dos +# op stub=pmodew.exe +# format os2 le +# end +# +# PMODE/W 1.16 or higher is required. See also msdos/README for important +# notes about PMODE/W bugs. + +default: + @echo "Enter `$(MAKE) -f os2/makefile.os2 target' from the main" + @echo "UnZip directory, where target is one of:" + @echo " msc mscdebug mscdos ibm ibmdyn ibmdebug ibmprof" + @echo " ibmdll ibmdyndll ibmdebugdll ibmprofdll" + @echo " metaware borland gcc gccdyn gccdebug gccdos gccwin32" + @echo " watcom watcom16 watcomdos watcom16dos pmodew watcomwin32" + +# MS C 6.00 for OS/2, 16-bit (should figure out way to split unzip/funzip +# compiles so former is always large model and latter always small model...) +msc: + $(MAKE) -f os2/makefile.os2 all \ + CC="cl -nologo -AL -Ocegit -Gs -I. $(FP)" \ + CFLAGS="-G2 -Zp1 -W3 -DOS2 -DMSC -DASM_CRC $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="ml -nologo -c -Zm -Cp" \ + ASFLAGS="-D__LARGE__ -D__286" \ + LDFLAGS="-F 2000 -Lp -Fe" \ + LDFLAGS2="-link /noe" \ + OUT="-Fo" \ + OBJ=".obj" \ + CRCA_O="crc_i86.obj" \ + OBJF2="os2f.obj" \ + DEF="os2\unzip.def" + +# MS C 6.00 for OS/2, debug version +mscdebug: + $(MAKE) -f os2/makefile.os2 all \ + CC="cl -nologo -AL -Zi -Od -I. $(FP)" \ + CFLAGS="-G2 -Zp1 -W3 -DOS2 -DMSC -DASM_CRC $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="ml -nologo -c -Zim -Cp" \ + ASFLAGS="-D__LARGE__ -D__286" \ + LDFLAGS="-F 2000 -Lp -Fe" \ + LDFLAGS2="-link /noe" \ + OUT="-Fo" \ + OBJ=".obj" \ + CRCA_O="crc_i86.obj" \ + OBJF2="os2f.obj" \ + DEF="os2\unzip.def" + +# cross-compilation for MS-DOS with MS C 6.00 (same comment as above...formerly; +# now unzip is large model again, because of DEFLATE_64 support) +mscdos: + $(MAKE) -f os2/makefile.os2 all \ + CC="cl -nologo -AL -Oaict -Gs -I. $(FP)" \ + CFLAGS="-Zp1 -W3 -DASM_CRC $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="ml -nologo -c -Zm -Cp" \ + ASFLAGS="-D__LARGE__" \ + LDFLAGS="-F 0C00 -Lr -Fe" \ + LDFLAGS2="-link /noe /exe" \ + OUT="-Fo" \ + OBJ=".obj" \ + CRCA_O="crc_i86" \ + OBJU2="msdos.obj" \ + OBJX2="msdos_.obj" \ + OBJF2="msdosf.obj" \ + OSDEP_H="msdos/doscfg.h" + +# IBM C Set, statically linked runtime +ibm: + $(MAKE) -f os2/makefile.os2 all \ + CC="icc -Q -O -Gs -I." \ + CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + LDFLAGS="-B/ST:0x50000 -Fe" \ + LDFLAGS2="" \ + OUT="-Fo" \ + OBJ=".obj" \ + DEF="os2\unzip.def" + +# IBM C Set, dynamically linked runtime +ibmdyn: + $(MAKE) -f os2/makefile.os2 all \ + CC="icc -Q -O -Gs -Gd -I." \ + CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + LDFLAGS="-B/ST:0x50000 -Fe" \ + LDFLAGS2="" \ + OUT="-Fo" \ + OBJ=".obj" \ + DEF="os2\unzip.def" + +# IBM C Set, debug version +ibmdebug: + $(MAKE) -f os2/makefile.os2 all \ + CC="icc -Q -Ti -I." \ + CFLAGS="-Sm -Sp1 -D__DEBUG_ALLOC__ -DOS2 $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + LDFLAGS="-B/ST:0x50000 -Fe" \ + LDFLAGS2="" \ + OUT="-Fo" \ + OBJ=".obj" \ + DEF="os2\unzip.def" + +# IBM C Set, profiling version for PROFIT +ibmprof: + $(MAKE) -f os2/makefile.os2 all \ + CC="icc -Q -O -Gs -Gh -Ti -I." \ + CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + LDFLAGS="-B/ST:0x50000 -Fe" \ + LDFLAGS2="cppopa3.obj" \ + OUT="-Fo" \ + OBJ=".obj" \ + DEF="os2\unzip.def" + +# IBM C Set, statically linked runtime +ibmdll: + $(MAKE) -f os2/makefile.os2 dll \ + CC="icc -Q -O -Gs -I." \ + CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC" \ + LDFLAGS="-Fe" \ + LDFLAGS2="" \ + OUT="-Fo" \ + OBJ=".obj" \ + DLLDEF="os2\rexxapi.def" \ + STUBDEF="os2\stub.def" \ + DEF="os2\unzip.def" \ + APILIB="REXX.lib" + +# IBM C Set, dynamically linked runtime +ibmdyndll: + $(MAKE) -f os2/makefile.os2 dll \ + CC="icc -Q -O -Gs -Gd -I." \ + CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC" \ + LDFLAGS="-Fe" \ + LDFLAGS2="" \ + OUT="-Fo" \ + OBJ=".obj" \ + DLLDEF="os2\rexxapi.def" \ + STUBDEF="os2\stub.def" \ + DEF="os2\unzip.def" \ + APILIB="REXX.lib" + +# IBM C Set, debug version +ibmdebugdll: + $(MAKE) -f os2/makefile.os2 dll \ + CC="icc -Q -Ti -I." \ + CFLAGS="-Sm -Sp1 -D__DEBUG_ALLOC__ -DOS2 $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC" \ + LDFLAGS="-Fe" \ + LDFLAGS2="" \ + OUT="-Fo" \ + OBJ=".obj" \ + DLLDEF="os2\rexxapi.def" \ + STUBDEF="os2\stub.def" \ + DEF="os2\unzip.def" \ + APILIB="REXX.lib" + +# IBM C Set, profiling version for PROFIT +ibmprofdll: + $(MAKE) -f os2/makefile.os2 dll \ + CC="icc -Q -O -Gs -Gh -Ti -I." \ + CFLAGS="-Gm -Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC" \ + LDFLAGS="-Fe" \ + LDFLAGS2="profit.obj" \ + OUT="-Fo" \ + OBJ=".obj" \ + DLLDEF="os2\rexxapi.def" \ + STUBDEF="os2\stub.def" \ + DEF="os2\unzip.def" \ + APILIB="REXX.lib" + +# Watcom C/386 9.0 or higher +watcom: + $(MAKE) -f os2/makefile.os2 all \ + CC="wcl386 -bt=os2v2 -zq -Ox -s -I." \ + CFLAGS="-Zp1 -DOS2 -DASM_CRC $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="wasm -bt=os2v2 -zq -3 -mf" \ + ASFLAGS="" \ + LDFLAGS="-k0x50000 -x -l=os2v2 -Fe=" \ + LDFLAGS2="" \ + OUT="-Fo" \ + OBJ=".obj" \ + CRCA_O="crc_i386.obj" \ + DEF="" \ + DIRSEP="\\" \ + AS_DIRSEP="\\" + +# Watcom C/286 9.0 or higher +watcom16: + $(MAKE) -f os2/makefile.os2 all \ + CC="wcl -bt=os2 -zq -ml -Ox -s -I." \ + CFLAGS="-Zp1 -DOS2 $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="wasm -bt=os2 -zq -2 -ml" \ + ASFLAGS="" \ + LDFLAGS="-k0x2000 -x -l=os2 -Fe=" \ + LDFLAGS2="" \ + OUT="-Fo" \ + OBJ=".obj" \ + CRCA_O="crc_i86.obj" \ + OBJF2="os2f.obj" \ + DIRSEP="\\" \ + AS_DIRSEP="\\" + +# Watcom C/386 9.0 or higher, crosscompilation for DOS, DOS4GW extender +watcomdos: + $(MAKE) -f os2/makefile.os2 all \ + CC="wcl386 -bt=dos4g -zq -Ox -s -I." \ + CFLAGS="-Zp1 -DMSDOS -DASM_CRC $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="wasm -bt=dos4g -zq -3 -mf" \ + ASFLAGS="" \ + LDFLAGS="-k0x50000 -x -l=dos4g -Fe=" \ + LDFLAGS2="" \ + OUT="-Fo" \ + OBJ=".obj" \ + CRCA_O="crc_i386.obj" \ + OBJU2="msdos.obj" \ + OBJX2="msdos_.obj" \ + OSDEP_H="msdos/doscfg.h" \ + DIRSEP="\\" \ + AS_DIRSEP="\\" + +# Watcom C/386 9.0 or higher, crosscompilation for DOS, PMODE/W extender +pmodew: + $(MAKE) -f os2/makefile.os2 all \ + CC="wcl386 -bt=dos4g -zq -Ox -s -I." \ + CFLAGS="-Zp1 -DMSDOS -DASM_CRC $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="wasm -bt=dos4g -zq -3 -mf" \ + ASFLAGS="" \ + LDFLAGS="-k0x50000 -x -l=pmodew -Fe=" \ + LDFLAGS2="" \ + OUT="-Fo" \ + OBJ=".obj" \ + CRCA_O="crc_i386.obj" \ + OBJU2="msdos.obj" \ + OBJX2="msdos_.obj" \ + OSDEP_H="msdos/doscfg.h" \ + DIRSEP="\\" \ + AS_DIRSEP="\\" + +# Watcom C/286 9.0 or higher, crosscompilation for DOS +watcom16dos: + $(MAKE) -f os2/makefile.os2 all \ + CC="wcl -bt=dos -zq -ml -Ox -s -I." \ + CFLAGS="-Zp1 -DMSDOS $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="wasm -bt=dos -0 -ml" \ + ASFLAGS="-D__LARGE__" \ + LDFLAGS="-k0xC00 -x -l=dos -Fe=" \ + LDFLAGS2="" \ + OUT="-Fo" \ + OBJ=".obj" \ + OBJU2="msdos.obj" \ + OBJX2="msdos_.obj" \ + OBJF2="msdosf.obj" \ + OSDEP_H="msdos/doscfg.h" \ + DIRSEP="\\" \ + AS_DIRSEP="\\" + +# Watcom C/386 9.0 or higher, crosscompilation for Win95/NT +watcomwin32: + $(MAKE) -f os2/makefile.os2 all \ + CC="wcl386 -bt=NT -zq -Ox -s -I." \ + CFLAGS="-Zp1 -DWIN32 -DASM_CRC $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="wasm -bt=NT -zq -3 -mf" \ + ASFLAGS="" \ + LDFLAGS="-k0x50000 -x -l=NT -Fe=" \ + LDFLAGS2="" \ + OUT="-Fo" \ + OBJ=".obj" \ + CRCA_O="crc_i386.obj" \ + OBJU2="win32.obj nt.obj" \ + OBJX2="win32_.obj nt_.obj" \ + OBJF2="win32f.obj" \ + DEF="" \ + DIRSEP="\\" \ + AS_DIRSEP="\\" + +# MetaWare High C/C++ 3.2 +metaware: + $(MAKE) -f os2/makefile.os2 all \ + CC="hc -O2 -I." \ + CFLAGS="-D__32BIT__ -DOS2 $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + LDFLAGS="-o " \ + LDFLAGS2="" \ + OUT="-o ./" \ + OBJ=".obj" \ + DEF="-Hdef=os2\unzip.def" + +# Borland C++ +borland: + $(MAKE) -f os2/makefile.os2 all \ + CC="bcc -O -I. -Ios2" \ + CFLAGS="-w- -D__cdecl -D__32BIT__ -DOS2 $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + LDFLAGS="-e" \ + LDFLAGS2="" \ + OUT="-o" \ + OBJ=".obj" \ + DEF="-sDos2\unzip.def" + +# emx, gcc, OMF format, statically linked C runtime +gcc: + $(MAKE) -f os2/makefile.os2 all \ + CC="gcc -Zomf -O -I." \ + CFLAGS="-Wall -DOS2 -DASM_CRC $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="gcc -Zomf" \ + ASFLAGS="-Di386" \ + LDFLAGS="-o ./" \ + LDFLAGS2="-Zsmall-conv -Zstack 320 -Zsys -s" \ + OUT="-o" \ + OBJ=".obj" \ + CRCA_O="crc_gcc.obj" \ + DEF="os2/unzip.def" + +# emx, gcc, OMF format, dynamically linked C runtime +gccdyn: + $(MAKE) -f os2/makefile.os2 all \ + CC="gcc -Zomf -O -I." \ + CFLAGS="-Wall -DOS2 -DASM_CRC $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="gcc -Zomf" \ + ASFLAGS="-Di386" \ + LDFLAGS="-o ./" \ + LDFLAGS2="-Zstack 320 -Zcrtdll -s" \ + OUT="-o" \ + OBJ=".obj" \ + CRCA_O="crc_gcc.obj" \ + DEF="os2/unzip.def" + +# emx, gcc, a.out format, with debug info for gdb +gccdebug: + $(MAKE) -f os2/makefile.os2 all \ + CC="gcc -g -I." \ + CFLAGS="-Wall -DOS2 -DASM_CRC $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="gcc -g" \ + ASFLAGS="-Di386" \ + LDFLAGS="-o ./" \ + LDFLAGS2="-Zsmall-conv" \ + OUT="-o" \ + OBJ=".o" \ + CRCA_O="crc_gcc.o" \ + +# emx, gcc, a.out format, cross-compilation for MS-DOS +gccdos: + $(MAKE) -f os2/makefile.os2 all \ + CC="gcc -O -I." \ + CFLAGS="-Wall -DMSDOS -DASM_CRC $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="gcc" \ + ASFLAGS="-Di386" \ + LDFLAGS="-o ./" \ + LDFLAGS2="-Zsmall-conv -s" \ + OUT="-o" \ + OBJ=".o" \ + CRCA_O="crc_gcc.o" \ + OBJU2="msdos.o" \ + OBJX2="msdos_.o" \ + OSDEP_H="msdos/doscfg.h" + +# emx, gcc, RSXNT, cross-compilation for Win32, statically linked C runtime +gccwin32: + $(MAKE) -f os2/makefile.os2 all \ + CC="gcc -Zwin32 -O2 -I." \ + CFLAGS="-Wall -DWIN32 -DASM_CRC $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="gcc" \ + ASFLAGS="-Di386" \ + LDFLAGS="-Zsys -o ./" \ + LDFLAGS2="-ladvapi32 -Zsmall-conv -s" \ + OUT="-o" \ + OBJ=".o" \ + CRCA_O="crc_gcc.o" \ + OBJU2="win32.o nt.o" \ + OBJX2="win32_.o nt_.o" \ + OBJF2="win32f.o" \ + OSDEP_H="win32/w32cfg.h" + +# variables + +# LOCAL_UNZIP = -DREENTRANT + +# default settings for target dependent macros: +DIRSEP = / +AS_DIRSEP = / + +OSDEP_H = os2/os2data.h os2/os2cfg.h +CRCA_O = + +OBJU = unzip$(OBJ) crc32$(OBJ) $(CRCA_O) crypt$(OBJ) envargs$(OBJ) \ + explode$(OBJ) extract$(OBJ) fileio$(OBJ) globals$(OBJ) \ + inflate$(OBJ) list$(OBJ) match$(OBJ) process$(OBJ) ttyio$(OBJ) \ + ubz2err$(OBJ) unreduce$(OBJ) unshrink$(OBJ) zipinfo$(OBJ) +OBJU2 = os2$(OBJ) os2acl$(OBJ) +OBJX = unzipsf_$(OBJ) crc32_$(OBJ) $(CRCA_O) crypt_$(OBJ) \ + extract_$(OBJ) fileio_$(OBJ) globals_$(OBJ) inflate_$(OBJ) \ + match_$(OBJ) process_$(OBJ) ttyio_$(OBJ) ubz2err_$(OBJ) +OBJX2 = os2_$(OBJ) os2acl_$(OBJ) +OBJDLL= api$(OBJ) apihelp$(OBJ) rexxhelp$(OBJ) rexxapi$(OBJ) +OBJF = funzip$(OBJ) crc32f$(OBJ) $(CRCA_O) cryptf$(OBJ) inflatef$(OBJ) \ + globalsf$(OBJ) ttyiof$(OBJ) +OBJF2 = + +UNZIP_H = unzip.h unzpriv.h globals.h $(OSDEP_H) + +# rules + +.SUFFIXES: .c .asm $(OBJ) + +.c$(OBJ): + $(CC) -c $(CFLAGS) $(DLLFLAG) $< + +.asm$(OBJ): + $(AS) $(ASFLAGS) $< $(ASEOL) + +# targets + +all: unzip.exe funzip.exe unzipsfx.exe +dll: unzip32.dll unzip.stb funzip.exe unzipsfx.exe + +unzip.exe: $(OBJU) $(OBJU2) + $(CC) $(LDFLAGS)$@ $(DEF) $(OBJU) $(OBJU2) $(LDFLAGS2) + +funzip.exe: $(OBJF) $(OBJF2) + $(CC) $(LDFLAGS)$@ $(DEF) $(OBJF) $(OBJF2) $(LDFLAGS2) + +unzipsfx.exe: $(OBJX) $(OBJX2) + $(CC) $(LDFLAGS)$@ $(DEF) $(OBJX) $(OBJX2) $(LDFLAGS2) + +unzip32.dll: $(DLLDEF) $(OBJU) $(OBJU2) $(OBJDLL) + $(CC) $(DLLFLAG) $(LDFLAGS)$@ $(DLLDEF) $(OBJU) $(OBJDLL) $(OBJU2) $(APILIB) $(LDFLAGS2) + +unzip.stb: unzipstb$(OBJ) $(STUBDEF) + $(CC) $(LDFLAGS)$@ $(STUBDEF) unzipstb$(OBJ) $(LDFLAGS2) + copy unzip.stb unzip.exe + +# dependencies + +apihelp$(OBJ): apihelp.c $(UNZIP_H) unzvers.h +crc32$(OBJ): crc32.c $(UNZIP_H) zip.h crc32.h +envargs$(OBJ): envargs.c $(UNZIP_H) +explode$(OBJ): explode.c $(UNZIP_H) +extract$(OBJ): extract.c $(UNZIP_H) crc32.h crypt.h +fileio$(OBJ): fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h +globals$(OBJ): globals.c $(UNZIP_H) +inflate$(OBJ): inflate.c $(UNZIP_H) +list$(OBJ): list.c $(UNZIP_H) +match$(OBJ): match.c $(UNZIP_H) +process$(OBJ): process.c $(UNZIP_H) crc32.h +ttyio$(OBJ): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h +ubz2err$(OBJ): ubz2err.c $(UNZIP_H) +unreduce$(OBJ): unreduce.c $(UNZIP_H) +unshrink$(OBJ): unshrink.c $(UNZIP_H) +unzip$(OBJ): unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h +api$(OBJ): api.c $(UNZIP_H) unzvers.h +zipinfo$(OBJ): zipinfo.c $(UNZIP_H) + +unzipstb$(OBJ): unzipstb.c # DLL version + $(CC) -c $(CFLAGS) unzipstb.c + +msdos$(OBJ): msdos/msdos.c $(UNZIP_H) unzvers.h # DOS only + $(CC) -c $(CFLAGS) msdos$(DIRSEP)msdos.c + +msdos_$(OBJ): msdos/msdos.c $(UNZIP_H) # DOS unzipsfx + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ msdos$(DIRSEP)msdos.c + +msdosf$(OBJ): msdos/msdos.c $(UNZIP_H) # DOS funzip + $(CC) -c $(CFLAGS) -DFUNZII $(OUT)$@ msdos$(DIRSEP)msdos.c + +win32$(OBJ): win32/win32.c $(UNZIP_H) win32/nt.h unzvers.h # Win32 only + $(CC) -c $(CFLAGS) win32$(DIRSEP)win32.c + +nt$(OBJ): win32/nt.c $(UNZIP_H) win32/nt.h # Win32 only + $(CC) -c $(CFLAGS) win32$(DIRSEP)nt.c + +win32_$(OBJ): win32/win32.c $(UNZIP_H) win32/nt.h # Win32 unzipsfx + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ win32$(DIRSEP)win32.c + +nt_$(OBJ): win32/nt.c $(UNZIP_H) win32/nt.h # Win32 unzipsfx + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ win32$(DIRSEP)nt.c + +win32f$(OBJ): win32/win32.c $(UNZIP_H) win32/nt.h # Win32 funzip + $(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ win32$(DIRSEP)win32.c + +os2$(OBJ): os2/os2.c $(UNZIP_H) unzvers.h # OS/2 only + $(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)os2.c + +os2_$(OBJ): os2/os2.c $(UNZIP_H) # OS/2 unzipsfx + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ os2$(DIRSEP)os2.c + +os2f$(OBJ): os2/os2.c $(UNZIP_H) # OS/2 funzip + $(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ os2$(DIRSEP)os2.c + +os2acl$(OBJ): os2/os2acl.c $(UNZIP_H) unzvers.h # OS/2 only + $(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)os2acl.c + +os2acl_$(OBJ): os2/os2acl.c $(UNZIP_H) unzvers.h # OS/2 unzipsfx + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ os2$(DIRSEP)os2acl.c + +rexxhelp$(OBJ): os2/rexxhelp.c # OS/2 DLL only + $(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)rexxhelp.c + +rexxapi$(OBJ): os2/rexxapi.c # OS/2 DLL only + $(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)rexxapi.c + +crc_i86$(OBJ): msdos/crc_i86.asm # 16bit only + $(AS) $(ASFLAGS) msdos$(AS_DIRSEP)crc_i86.asm $(ASEOL) + +crc_i386$(OBJ): win32/crc_i386.asm # 32bit, MASM + $(AS) $(ASFLAGS) win32$(AS_DIRSEP)crc_i386.asm $(ASEOL) + +crc_gcc$(OBJ): crc_i386.S # 32bit, GNU AS + $(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S + +# NFLAGS are solely used as work-around for optimization bug in IBM C++ Set +crypt$(OBJ): crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CC) -c $(CFLAGS) $(DLLFLAG) $(NFLAGS) crypt.c + +# funzip compilation section +funzip$(OBJ): funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h + $(CC) -c $(CFLAGS) funzip.c + +crc32f$(OBJ): crc32.c $(UNZIP_H) zip.h crc32.h + $(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ crc32.c + +cryptf$(OBJ): crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ crypt.c + +globalsf$(OBJ): globals.c $(UNZIP_H) + $(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ globals.c + +inflatef$(OBJ): inflate.c inflate.h $(UNZIP_H) crypt.h + $(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ inflate.c + +ttyiof$(OBJ): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ ttyio.c + +# unzipsfx compilation section +crc32_$(OBJ): crc32.c $(UNZIP_H) zip.h crc32.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crc32.c + +crypt_$(OBJ): crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crypt.c + +extract_$(OBJ): extract.c $(UNZIP_H) crypt.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ extract.c + +fileio_$(OBJ): fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ fileio.c + +globals_$(OBJ): globals.c $(UNZIP_H) + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ globals.c + +inflate_$(OBJ): inflate.c inflate.h $(UNZIP_H) crypt.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ inflate.c + +match_$(OBJ): match.c $(UNZIP_H) + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ match.c + +process_$(OBJ): process.c $(UNZIP_H) crc32.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ process.c + +ttyio_$(OBJ): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ ttyio.c + +ubz2err_$(OBJ): ubz2err.c $(UNZIP_H) + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ ubz2err.c + +unzipsf_$(OBJ): unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ unzip.c diff --git a/os2/os2.c b/os2/os2.c new file mode 100644 index 0000000..b962ca7 --- /dev/null +++ b/os2/os2.c @@ -0,0 +1,2412 @@ +/* + Copyright (c) 1990-2007 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, both of these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html +*/ +/*--------------------------------------------------------------------------- + + os2.c + + OS/2-specific routines for use with Info-ZIP's UnZip 5.1 and later. + + This file contains the OS/2 versions of the file name/attribute/time/etc + code. Most or all of the routines which make direct use of OS/2 system + calls (i.e., the non-lowercase routines) are Kai Uwe Rommel's. The read- + dir() suite was written by Michael Rendell and ported to OS/2 by Kai Uwe; + it is in the public domain. + + Contains: GetCountryInfo() + SetFileSize() + GetFileTime() + SetFileTime() (TIMESTAMP only) + stamp_file() (TIMESTAMP only) + Utime2DosDateTime() + SetPathAttrTimes() + SetEAs() + GetLoadPath() + opendir() + closedir() + readdir() + [ seekdir() ] not used + [ telldir() ] not used + free_dircontents() + getdirent() + IsFileSystemFAT() + do_wild() + mapattr() + mapname() + checkdir() + isfloppy() + IsFileNameValid() + map2fat() + SetLongNameEA() + close_outfile() + check_for_newer() + dateformat() + version() + zcalloc() (16-bit, only) + zcfree() (16-bit, only) + InitNLS() + IsUpperNLS() + ToLowerNLS() + StringLower() + screensize() + DebugMalloc() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" + +/* fUnZip does not need anything from here except the zcalloc() & zcfree() + * function pair (when Deflate64 support is enabled in 16-bit environment). + */ +#ifndef FUNZIP + +#include "os2acl.h" + +extern ZCONST char Far TruncEAs[]; + +/* local prototypes */ + +#ifdef TIMESTAMP + static int SetFileTime(ZCONST char *name, ulg stamp); +#endif +#if defined(USE_EF_UT_TIME) || defined(TIMESTAMP) + static ulg Utime2DosDateTime OF((time_t uxtime)); +#endif +static int getOS2filetimes OF((__GPRO__ + ulg *pM_dt, ulg *pA_dt, ulg *pC_dt)); +static void SetPathAttrTimes OF((__GPRO__ int flags, int dir)); +static int SetEAs OF((__GPRO__ const char *path, + void *ef_block)); +static int SetACL OF((__GPRO__ const char *path, + void *ef_block)); +static int EvalExtraFields OF((__GPRO__ const char *path, + void *extra_field, unsigned ef_len)); +static int isfloppy OF((int nDrive)); +static int IsFileNameValid OF((const char *name)); +static void map2fat OF((char *pathcomp, char **pEndFAT)); +static int SetLongNameEA OF((char *name, char *longname)); +static void InitNLS OF((void)); + + +#ifdef ACORN_FTYPE_NFS +/* Acorn bits for NFS filetyping */ +typedef struct { + uch ID[2]; + uch size[2]; + uch ID_2[4]; + uch loadaddr[4]; + uch execaddr[4]; + uch attr[4]; +} RO_extra_block; + +#endif /* ACORN_FTYPE_NFS */ + + +/*****************************/ +/* Strings used in os2.c */ +/*****************************/ + +#ifndef SFX + static ZCONST char Far CantAllocateWildcard[] = + "warning: cannot allocate wildcard buffers\n"; +#endif +static ZCONST char Far WarnDirTraversSkip[] = + "warning: skipped \"../\" path component(s) in %s\n"; +static ZCONST char Far Creating[] = " creating: %-22s "; +static ZCONST char Far ConversionFailed[] = + "mapname: conversion of %s failed\n"; +static ZCONST char Far Labelling[] = "labelling %c: %-22s\n"; +static ZCONST char Far ErrSetVolLabel[] = + "mapname: error setting volume label\n"; +static ZCONST char Far PathTooLong[] = "checkdir error: path too long: %s\n"; +static ZCONST char Far CantCreateDir[] = "checkdir error: cannot create %s\n\ + unable to process %s.\n"; +static ZCONST char Far DirIsntDirectory[] = + "checkdir error: %s exists but is not directory\n\ + unable to process %s.\n"; +static ZCONST char Far PathTooLongTrunc[] = + "checkdir warning: path too long; truncating\n %s\n\ + -> %s\n"; +#if (!defined(SFX) || defined(SFX_EXDIR)) + static ZCONST char Far CantCreateExtractDir[] = + "checkdir: cannot create extraction directory: %s\n"; +#endif + +#ifndef __GNUC__ + /* all supported non-gcc compilers provide MSC/DOS style mkdir() */ +# if (_MSC_VER >= 600) || defined(__IBMC__) +# include /* have special MSC/IBM C mkdir prototype */ +# else /* own prototype because dir.h conflicts? */ + int mkdir(const char *path); +# endif +# define MKDIR(path,mode) mkdir(path) +#else + /* EMX and hopefully all other gcc ports support POSIX style mkdir() */ +# define MKDIR(path,mode) mkdir(path,mode) +#endif + + +#ifdef __32BIT__ + +USHORT DosDevIOCtl32(PVOID pData, USHORT cbData, PVOID pParms, USHORT cbParms, + USHORT usFunction, USHORT usCategory, HFILE hDevice) +{ + ULONG ulParmLengthInOut = cbParms, ulDataLengthInOut = cbData; + return (USHORT) DosDevIOCtl(hDevice, usCategory, usFunction, + pParms, cbParms, &ulParmLengthInOut, + pData, cbData, &ulDataLengthInOut); +} + +# define DosDevIOCtl DosDevIOCtl32 +#else +# define DosDevIOCtl DosDevIOCtl2 +#endif + + +typedef struct +{ + ush nID; + ush nSize; + ulg lSize; +} +EFHEADER, *PEFHEADER; + + +#ifdef __32BIT__ + +#define DosFindFirst(p1, p2, p3, p4, p5, p6) \ + DosFindFirst(p1, p2, p3, p4, p5, p6, 1) + +#else + +typedef struct +{ + ULONG oNextEntryOffset; + BYTE fEA; + BYTE cbName; + USHORT cbValue; + CHAR szName[1]; +} +FEA2, *PFEA2; + +typedef struct +{ + ULONG cbList; + FEA2 list[1]; +} +FEA2LIST, *PFEA2LIST; + +#define DosQueryCurrentDisk DosQCurDisk +#define DosQueryFSAttach(p1, p2, p3, p4, p5) \ + DosQFSAttach(p1, p2, p3, p4, p5, 0) +#define DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7) \ + DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7, 0) +#define DosFindFirst(p1, p2, p3, p4, p5, p6) \ + DosFindFirst(p1, p2, p3, p4, p5, p6, 0) +#define DosMapCase DosCaseMap +#define DosSetPathInfo(p1, p2, p3, p4, p5) \ + DosSetPathInfo(p1, p2, p3, p4, p5, 0) +#define DosQueryPathInfo(p1, p2, p3, p4) \ + DosQPathInfo(p1, p2, p3, p4, 0) +#define DosQueryFileInfo DosQFileInfo +#define DosMapCase DosCaseMap +#define DosQueryCtryInfo DosGetCtryInfo + +#endif /* !__32BIT__ */ + + + + + +/* + * @(#) dir.h 1.4 87/11/06 Public Domain. + */ + +#define A_RONLY 0x01 +#define A_HIDDEN 0x02 +#define A_SYSTEM 0x04 +#define A_LABEL 0x08 +#define A_DIR 0x10 +#define A_ARCHIVE 0x20 + + +const int attributes = A_DIR | A_HIDDEN | A_SYSTEM; + + +extern DIR *opendir(__GPRO__ ZCONST char *); +extern struct direct *readdir(__GPRO__ DIR *); +extern void seekdir(DIR *, long); +extern long telldir(DIR *); +extern void closedir(DIR *); +#define rewinddir(dirp) seekdir(dirp, 0L) + +int IsFileSystemFAT(__GPRO__ ZCONST char *dir); +char *StringLower(char *szArg); + + + + +/* + * @(#)dir.c 1.4 87/11/06 Public Domain. + */ + + +#ifndef S_IFMT +# define S_IFMT 0xF000 +#endif + + +#ifndef SFX + static char *getdirent(__GPRO__ ZCONST char *); + static void free_dircontents(struct _dircontents *); +#endif /* !SFX */ + + + + +int GetCountryInfo(void) +{ + COUNTRYINFO ctryi; + COUNTRYCODE ctryc; +#ifdef __32BIT__ + ULONG cbInfo; +#else + USHORT cbInfo; +#endif + + ctryc.country = ctryc.codepage = 0; + + if ( DosQueryCtryInfo(sizeof(ctryi), &ctryc, &ctryi, &cbInfo) != NO_ERROR ) + return 0; + + return ctryi.fsDateFmt; +} + + +int SetFileSize(FILE *file, ulg filesize) +{ +#ifdef __32BIT__ + return DosSetFileSize(fileno(file), (size_t)filesize) ? -1 : 0; +#else + return 0; +#endif +} + + +long GetFileTime(ZCONST char *name) +{ +#ifdef __32BIT__ + FILESTATUS3 fs; +#else + FILESTATUS fs; +#endif + USHORT nDate, nTime; + + if ( DosQueryPathInfo((PSZ) name, 1, (PBYTE) &fs, sizeof(fs)) ) + return -1; + + nDate = * (USHORT *) &fs.fdateLastWrite; + nTime = * (USHORT *) &fs.ftimeLastWrite; + + return ((ULONG) nDate) << 16 | nTime; +} + + +#ifdef TIMESTAMP + +static int SetFileTime(ZCONST char *name, ulg stamp) /* swiped from Zip */ +{ + FILESTATUS fs; + USHORT fd, ft; + + if (DosQueryPathInfo((PSZ) name, FIL_STANDARD, (PBYTE) &fs, sizeof(fs))) + return -1; + + fd = (USHORT) (stamp >> 16); + ft = (USHORT) stamp; + fs.fdateLastWrite = fs.fdateCreation = * (FDATE *) &fd; + fs.ftimeLastWrite = fs.ftimeCreation = * (FTIME *) &ft; + + if (DosSetPathInfo((PSZ) name, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0)) + return -1; + + return 0; +} + + +int stamp_file(ZCONST char *fname, time_t modtime) +{ + return SetFileTime(fname, Utime2DosDateTime(modtime)); +} + +#endif /* TIMESTAMP */ + + +/* The following DOS date/time structures are machine-dependent as they + * assume "little-endian" byte order. For OS/2-specific code, which + * is run on x86 CPUs (or emulators?), this assumption is valid; but + * care should be taken when using this code as template for other ports. + */ +typedef union { + ULONG timevalue; /* combined value, useful for comparisons */ + struct { + FTIME ft; /* system file time record: + * USHORT twosecs : 5 + * USHORT minutes : 6; + * USHORT hours : 5; */ + FDATE fd; /* system file date record: + * USHORT day : 5 + * USHORT month : 4; + * USHORT year : 7; */ + } _fdt; +} F_DATE_TIME, *PF_DATE_TIME; + + +#if defined(USE_EF_UT_TIME) || defined(TIMESTAMP) + +static ulg Utime2DosDateTime(uxtime) + time_t uxtime; +{ + F_DATE_TIME dosfiletime; + struct tm *t; + + /* round up to even seconds */ + /* round up (down if "up" overflows) to even seconds */ + if (((ulg)uxtime) & 1) + uxtime = (uxtime + 1 > uxtime) ? uxtime + 1 : uxtime - 1; + + t = localtime(&(uxtime)); + if (t == (struct tm *)NULL) { + /* time conversion error; use current time instead, hoping + that localtime() does not reject it as well! */ + time_t now = time(NULL); + t = localtime(&now); + } + if (t->tm_year < 80) { + dosfiletime._fdt.ft.twosecs = 0; + dosfiletime._fdt.ft.minutes = 0; + dosfiletime._fdt.ft.hours = 0; + dosfiletime._fdt.fd.day = 1; + dosfiletime._fdt.fd.month = 1; + dosfiletime._fdt.fd.year = 0; + } else { + dosfiletime._fdt.ft.twosecs = t->tm_sec >> 1; + dosfiletime._fdt.ft.minutes = t->tm_min; + dosfiletime._fdt.ft.hours = t->tm_hour; + dosfiletime._fdt.fd.day = t->tm_mday; + dosfiletime._fdt.fd.month = t->tm_mon + 1; + dosfiletime._fdt.fd.year = t->tm_year - 80; + } + return dosfiletime.timevalue; + +} /* end function Utime2DosDateTime() */ + +#endif /* USE_EF_UT_TIME || TIMESTAMP */ + + +static int getOS2filetimes(__GPRO__ ulg *pM_dt, ulg *pA_dt, ulg *pC_dt) +{ +#ifdef USE_EF_UT_TIME + unsigned eb_izux_flg; + iztimes z_utime; +#endif + + /* Copy and/or convert time and date variables, if necessary; */ + /* return a flag indicating which time stamps are available. */ +#ifdef USE_EF_UT_TIME + if (G.extra_field && +#ifdef IZ_CHECK_TZ + G.tz_is_valid && +#endif + ((eb_izux_flg = ef_scan_for_izux(G.extra_field, + G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, + &z_utime, NULL)) & EB_UT_FL_MTIME)) + { + TTrace((stderr, "getOS2filetimes: UT e.f. modif. time = %lu\n", + z_utime.mtime)); + *pM_dt = Utime2DosDateTime(z_utime.mtime); + if (eb_izux_flg & EB_UT_FL_ATIME) { + TTrace((stderr, "getOS2filetimes: UT e.f. access time = %lu\n", + z_utime.atime)); + *pA_dt = Utime2DosDateTime(z_utime.atime); + } + if (eb_izux_flg & EB_UT_FL_CTIME) { + TTrace((stderr, "getOS2filetimes: UT e.f. creation time = %lu\n", + z_utime.ctime)); + *pC_dt = Utime2DosDateTime(z_utime.ctime); + } else { + /* no creation time value supplied, set it to modification time */ + *pC_dt = *pM_dt; + eb_izux_flg |= EB_UT_FL_CTIME; + } + return (int)eb_izux_flg; + } +#endif /* USE_EF_UT_TIME */ + *pC_dt = *pM_dt = G.lrec.last_mod_dos_datetime; + TTrace((stderr, "\ngetOS2filetimes: DOS dir modific./creation time = %lu\n", + *pM_dt)); + return (EB_UT_FL_MTIME | EB_UT_FL_CTIME); +} + + +static void SetPathAttrTimes(__GPRO__ int flags, int dir) +{ + HFILE hFile; +#ifdef __32BIT__ + ULONG nAction; +#else + USHORT nAction; +#endif + FILESTATUS fs; + USHORT nLength; + char szName[CCHMAXPATH]; + ulg Mod_dt, Acc_dt, Cre_dt; + int gotTimes; + + strcpy(szName, G.filename); + nLength = strlen(szName); + if (szName[nLength - 1] == '/') + szName[nLength - 1] = 0; + + if (dir) + { + if ( DosQueryPathInfo(szName, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)) ) + return; + } + else + { + /* for regular files, open them and operate on the file handle, to + work around certain network operating system bugs ... */ + + if ( DosOpen(szName, &hFile, &nAction, 0, 0, + OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW, + OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, 0) ) + return; + + if ( DosQueryFileInfo(hFile, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)) ) + return; + } + + if (uO.D_flag <= (dir ? 1 : 0)) { + /* set date/time stamps */ + gotTimes = getOS2filetimes(__G__ &Mod_dt, &Acc_dt, &Cre_dt); + if (gotTimes & EB_UT_FL_MTIME) { + fs.fdateLastWrite = ((F_DATE_TIME *)&Mod_dt)->_fdt.fd; + fs.ftimeLastWrite = ((F_DATE_TIME *)&Mod_dt)->_fdt.ft; + } + if (gotTimes & EB_UT_FL_ATIME) { + fs.fdateLastAccess = ((F_DATE_TIME *)&Acc_dt)->_fdt.fd; + fs.ftimeLastAccess = ((F_DATE_TIME *)&Acc_dt)->_fdt.ft; + } + if (gotTimes & EB_UT_FL_CTIME) { + fs.fdateCreation = ((F_DATE_TIME *)&Cre_dt)->_fdt.fd; + fs.ftimeCreation = ((F_DATE_TIME *)&Cre_dt)->_fdt.ft; + } + } + + if ( flags != -1 ) + fs.attrFile = flags; /* hidden, system, archive, read-only */ + + if (dir) + { + DosSetPathInfo(szName, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0); + } + else + { + DosSetFileInfo(hFile, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)); + DosClose(hFile); + } +} + + +typedef struct +{ + ULONG cbList; /* length of value + 22 */ +#ifdef __32BIT__ + ULONG oNext; +#endif + BYTE fEA; /* 0 */ + BYTE cbName; /* length of ".LONGNAME" = 9 */ + USHORT cbValue; /* length of value + 4 */ + BYTE szName[10]; /* ".LONGNAME" */ + USHORT eaType; /* 0xFFFD for length-preceded ASCII */ + USHORT eaSize; /* length of value */ + BYTE szValue[CCHMAXPATH]; +} +FEALST; + + +static int SetEAs(__GPRO__ const char *path, void *ef_block) +{ /* returns almost-PK errors */ + EFHEADER *pEAblock = (PEFHEADER) ef_block; +#ifdef __32BIT__ + EAOP2 eaop; + PFEA2LIST pFEA2list; +#else + EAOP eaop; + PFEALIST pFEAlist; + PFEA pFEA; + PFEA2LIST pFEA2list; + PFEA2 pFEA2; + ULONG nLength2; +#endif + USHORT nLength; + char szName[CCHMAXPATH]; + int error; + + if ( ef_block == NULL || pEAblock -> nID != EF_OS2 ) + return PK_OK; /* not an OS/2 extra field: assume OK */ + + if ( pEAblock->nSize < 4 || (pEAblock->lSize > 0L && pEAblock->nSize <= 10) ) + return IZ_EF_TRUNC; /* no compressed data! */ + + strcpy(szName, path); + nLength = strlen(szName); + if (szName[nLength - 1] == '/') + szName[nLength - 1] = 0; + + if ( (pFEA2list = (PFEA2LIST) malloc((size_t) pEAblock -> lSize)) == NULL ) + return PK_MEM4; + + if ( (error = memextract(__G__ (uch *)pFEA2list, pEAblock->lSize, + (uch *)(pEAblock+1), (ulg)(pEAblock->nSize - 4))) != PK_OK ) + { + free(pFEA2list); + return error; + } + +#ifdef __32BIT__ + eaop.fpGEA2List = NULL; + eaop.fpFEA2List = pFEA2list; +#else + pFEAlist = (PVOID) pFEA2list; + pFEA2 = pFEA2list -> list; + pFEA = pFEAlist -> list; + + do + { + nLength2 = pFEA2 -> oNextEntryOffset; + nLength = sizeof(FEA) + pFEA2 -> cbName + 1 + pFEA2 -> cbValue; + + memcpy(pFEA, (PCH) pFEA2 + sizeof(pFEA2 -> oNextEntryOffset), nLength); + + pFEA2 = (PFEA2) ((PCH) pFEA2 + nLength2); + pFEA = (PFEA) ((PCH) pFEA + nLength); + } + while ( nLength2 != 0 ); + + pFEAlist -> cbList = (PCH) pFEA - (PCH) pFEAlist; + + eaop.fpGEAList = NULL; + eaop.fpFEAList = pFEAlist; +#endif + + eaop.oError = 0; + DosSetPathInfo(szName, FIL_QUERYEASIZE, (PBYTE) &eaop, sizeof(eaop), 0); + + if (!uO.tflag && QCOND2) + Info(slide, 0, ((char *)slide, " (%ld bytes EAs)", pFEA2list -> cbList)); + + free(pFEA2list); + return PK_COOL; +} + + +static int SetACL(__GPRO__ const char *path, void *ef_block) +{ /* returns almost-PK errors */ + EFHEADER *pACLblock = (PEFHEADER) ef_block; + char *szACL; + int error; + + if ( ef_block == NULL || pACLblock -> nID != EF_ACL ) + return PK_OK; /* not an OS/2 extra field: assume OK */ + + if (pACLblock->nSize < 4 || (pACLblock->lSize > 0L && pACLblock->nSize <= 10)) + return IZ_EF_TRUNC; /* no compressed data! */ + + if ( (szACL = malloc((size_t) pACLblock -> lSize)) == NULL ) + return PK_MEM4; + + if ( (error = memextract(__G__ (uch *)szACL, pACLblock->lSize, + (uch *)(pACLblock+1), (ulg)(pACLblock->nSize - 4))) != PK_OK ) + { + free(szACL); + return error; + } + + if (acl_set(NULL, path, szACL) == 0) + if (!uO.tflag && QCOND2) + Info(slide, 0, ((char *)slide, " (%ld bytes ACL)", strlen(szACL))); + + free(szACL); + return PK_COOL; +} + + +#ifdef SFX + +char *GetLoadPath(__GPRO) +{ +#ifdef __32BIT__ /* generic for 32-bit API */ + PTIB pptib; + PPIB pppib; + char *szPath; + + DosGetInfoBlocks(&pptib, &pppib); + szPath = pppib -> pib_pchenv; +#else /* 16-bit, note: requires large data model */ + SEL selEnv; + USHORT offCmd; + char *szPath; + + DosGetEnv(&selEnv, &offCmd); + szPath = MAKEP(selEnv, 0); +#endif + + while (*szPath) /* find end of process environment */ + szPath = strchr(szPath, 0) + 1; + + return szPath + 1; /* .exe file name follows environment */ + +} /* end function GetLoadPath() */ + + + + + +#else /* !SFX */ + +DIR *opendir(__GPRO__ const char *name) +{ + struct stat statb; + DIR *dirp; + char c; + char *s; + struct _dircontents *dp; + char nbuf[MAXPATHLEN + 1]; + int len; + + strcpy(nbuf, name); + if ((len = strlen(nbuf)) == 0) + return NULL; + + if ( ((c = nbuf[len - 1]) == '\\' || c == '/') && (len > 1) ) + { + nbuf[len - 1] = 0; + --len; + + if ( nbuf[len - 1] == ':' ) + { + strcpy(nbuf+len, "\\."); + len += 2; + } + } + else + if ( nbuf[len - 1] == ':' ) + { + strcpy(nbuf+len, "."); + ++len; + } + + /* GRR: Borland and Watcom C return non-zero on wildcards... < 0 ? */ + if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR) + { + Trace((stderr, "opendir: stat(%s) returns negative or not directory\n", + FnFilter1(nbuf))); + return NULL; + } + + if ( (dirp = malloc(sizeof(DIR))) == NULL ) + return NULL; + + if ( nbuf[len - 1] == '.' && (len == 1 || nbuf[len - 2] != '.') ) + strcpy(nbuf+len-1, "*"); + else + if ( ((c = nbuf[len - 1]) == '\\' || c == '/') && (len == 1) ) + strcpy(nbuf+len, "*"); + else + strcpy(nbuf+len, "\\*"); + + /* len is no longer correct (but no longer needed) */ + Trace((stderr, "opendir: nbuf = [%s]\n", FnFilter1(nbuf))); + + dirp -> dd_loc = 0; + dirp -> dd_contents = dirp -> dd_cp = NULL; + + if ((s = getdirent(__G__ nbuf)) == NULL) + return dirp; + + do + { + if (((dp = malloc(sizeof(struct _dircontents))) == NULL) || + ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL) ) + { + if (dp) + free(dp); + free_dircontents(dirp -> dd_contents); + + return NULL; + } + + if (dirp -> dd_contents) + { + dirp -> dd_cp -> _d_next = dp; + dirp -> dd_cp = dirp -> dd_cp -> _d_next; + } + else + dirp -> dd_contents = dirp -> dd_cp = dp; + + strcpy(dp -> _d_entry, s); + dp -> _d_next = NULL; + + dp -> _d_size = G.os2.find.cbFile; + dp -> _d_mode = G.os2.find.attrFile; + dp -> _d_time = *(unsigned *) &(G.os2.find.ftimeLastWrite); + dp -> _d_date = *(unsigned *) &(G.os2.find.fdateLastWrite); + } + while ((s = getdirent(__G__ NULL)) != NULL); + + dirp -> dd_cp = dirp -> dd_contents; + + return dirp; +} + + +void closedir(DIR * dirp) +{ + free_dircontents(dirp -> dd_contents); + free(dirp); +} + + +struct direct *readdir(__GPRO__ DIR * dirp) +{ + /* moved to os2data.h so it can be global */ + /* static struct direct dp; */ + + if (dirp -> dd_cp == NULL) + return NULL; + + G.os2.dp.d_namlen = G.os2.dp.d_reclen = + strlen(strcpy(G.os2.dp.d_name, dirp -> dd_cp -> _d_entry)); + + G.os2.dp.d_ino = 0; + + G.os2.dp.d_size = dirp -> dd_cp -> _d_size; + G.os2.dp.d_mode = dirp -> dd_cp -> _d_mode; + G.os2.dp.d_time = dirp -> dd_cp -> _d_time; + G.os2.dp.d_date = dirp -> dd_cp -> _d_date; + + dirp -> dd_cp = dirp -> dd_cp -> _d_next; + dirp -> dd_loc++; + + return &G.os2.dp; +} + + + +#if 0 /* not used in unzip; retained for possibly future use */ + +void seekdir(DIR * dirp, long off) +{ + long i = off; + struct _dircontents *dp; + + if (off >= 0) + { + for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next); + + dirp -> dd_loc = off - (i + 1); + dirp -> dd_cp = dp; + } +} + + +long telldir(DIR * dirp) +{ + return dirp -> dd_loc; +} + +#endif /* 0 */ + + + +static void free_dircontents(struct _dircontents * dp) +{ + struct _dircontents *odp; + + while (dp) + { + if (dp -> _d_entry) + free(dp -> _d_entry); + + dp = (odp = dp) -> _d_next; + free(odp); + } +} + + +static char *getdirent(__GPRO__ ZCONST char *dir) +{ + int done; + /* moved to os2data.h so it can be global */ + /* static int lower; */ + + if (dir != NULL) + { /* get first entry */ + G.os2.hdir = HDIR_SYSTEM; + G.os2.count = 1; + done = DosFindFirst((PSZ) dir, &G.os2.hdir, attributes, + &G.os2.find, sizeof(G.os2.find), &G.os2.count); + G.os2.lower = IsFileSystemFAT(__G__ dir); + } + else /* get next entry */ + done = DosFindNext(G.os2.hdir, + &G.os2.find, sizeof(G.os2.find), &G.os2.count); + + if (done == 0) + { + if ( G.os2.lower ) + StringLower(G.os2.find.achName); + return G.os2.find.achName; + } + else + { + DosFindClose(G.os2.hdir); + return NULL; + } +} + + + +int IsFileSystemFAT(__GPRO__ ZCONST char *dir) /* FAT / HPFS detection */ +{ + /* moved to os2data.h so they can be global */ + /* static USHORT nLastDrive=(USHORT)(-1), nResult; */ + ULONG lMap; + BYTE bData[64]; + char bName[3]; +#ifdef __32BIT__ + ULONG nDrive, cbData; + PFSQBUFFER2 pData = (PFSQBUFFER2) bData; +#else + USHORT nDrive, cbData; + PFSQBUFFER pData = (PFSQBUFFER) bData; +#endif + + /* We separate FAT and HPFS+other file systems here. + at the moment I consider other systems to be similar to HPFS, + i.e. support long file names and case sensitive */ + + if ( isalpha((uch)dir[0]) && (dir[1] == ':') ) + nDrive = toupper(dir[0]) - '@'; + else + DosQueryCurrentDisk(&nDrive, &lMap); + + if ( nDrive == G.os2.nLastDrive ) + return G.os2.nResult; + + bName[0] = (char) (nDrive + '@'); + bName[1] = ':'; + bName[2] = 0; + + G.os2.nLastDrive = nDrive; + cbData = sizeof(bData); + + if ( !DosQueryFSAttach(bName, 0, FSAIL_QUERYNAME, (PVOID) pData, &cbData) ) + G.os2.nResult = !strcmp((char *) (pData -> szFSDName) + pData -> cbName, + "FAT"); + else + G.os2.nResult = FALSE; + + /* End of this ugly code */ + return G.os2.nResult; +} /* end function IsFileSystemFAT() */ + + + + + +/************************/ +/* Function do_wild() */ +/************************/ + +char *do_wild(__G__ wildspec) + __GDEF + ZCONST char *wildspec; /* only used first time on a given dir */ +{ + /* moved to os2data.h so they can be global */ +#if 0 + static DIR *wild_dir = NULL; + static ZCONST char *wildname; + static char *dirname, matchname[FILNAMSIZ]; + static int notfirstcall=FALSE, have_dirname, dirnamelen; +#endif + char *fnamestart; + struct direct *file; + + /* Even when we're just returning wildspec, we *always* do so in + * matchname[]--calling routine is allowed to append four characters + * to the returned string, and wildspec may be a pointer to argv[]. + */ + if (!G.os2.notfirstcall) { /* first call: must initialize everything */ + G.os2.notfirstcall = TRUE; + + if (!iswild(wildspec)) { + strncpy(G.os2.matchname, wildspec, FILNAMSIZ); + G.os2.matchname[FILNAMSIZ-1] = '\0'; + G.os2.have_dirname = FALSE; + G.os2.wild_dir = NULL; + return G.os2.matchname; + } + + /* break the wildspec into a directory part and a wildcard filename */ + if ((G.os2.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL && + (G.os2.wildname = (ZCONST char *)strrchr(wildspec, ':')) == NULL) { + G.os2.dirname = "."; + G.os2.dirnamelen = 1; + G.os2.have_dirname = FALSE; + G.os2.wildname = wildspec; + } else { + ++G.os2.wildname; /* point at character after '/' or ':' */ + G.os2.dirnamelen = G.os2.wildname - wildspec; + if ((G.os2.dirname = (char *)malloc(G.os2.dirnamelen+1)) == NULL) { + Info(slide, 1, ((char *)slide, + LoadFarString(CantAllocateWildcard))); + strncpy(G.os2.matchname, wildspec, FILNAMSIZ); + G.os2.matchname[FILNAMSIZ-1] = '\0'; + return G.os2.matchname; /* but maybe filespec was not a wildcard */ + } + strncpy(G.os2.dirname, wildspec, G.os2.dirnamelen); + G.os2.dirname[G.os2.dirnamelen] = '\0'; /* terminate for strcpy below */ + G.os2.have_dirname = TRUE; + } + Trace((stderr, "do_wild: dirname = [%s]\n", + FnFilter1(G.os2.dirname))); + + if ((G.os2.wild_dir = opendir(__G__ G.os2.dirname)) != NULL) { + if (G.os2.have_dirname) { + strcpy(G.os2.matchname, G.os2.dirname); + fnamestart = G.os2.matchname + G.os2.dirnamelen; + } else + fnamestart = G.os2.matchname; + while ((file = readdir(__G__ G.os2.wild_dir)) != NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + strcpy(fnamestart, file->d_name); + if (strrchr(fnamestart, '.') == (char *)NULL) + strcat(fnamestart, "."); + if (match(fnamestart, G.os2.wildname, 1 WISEP) && + /* 1 == ignore case */ + /* skip "." and ".." directory entries */ + strcmp(fnamestart, ".") && strcmp(fnamestart, "..")) { + Trace((stderr, "do_wild: match() succeeds\n")); + /* remove trailing dot */ + fnamestart += strlen(fnamestart) - 1; + if (*fnamestart == '.') + *fnamestart = '\0'; + return G.os2.matchname; + } + } + /* if we get to here directory is exhausted, so close it */ + closedir(G.os2.wild_dir); + G.os2.wild_dir = NULL; + } +#ifdef DEBUG + else { + Trace((stderr, "do_wild: opendir(%s) returns NULL\n", + FnFilter1(G.os2.dirname))); + } +#endif /* DEBUG */ + + /* return the raw wildspec in case that works (e.g., directory not + * searchable, but filespec was not wild and file is readable) */ + strncpy(G.os2.matchname, wildspec, FILNAMSIZ); + G.os2.matchname[FILNAMSIZ-1] = '\0'; + return G.os2.matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (G.os2.wild_dir == NULL) { + G.os2.notfirstcall = FALSE; /* nothing left to try--reset */ + if (G.os2.have_dirname) + free(G.os2.dirname); + return (char *)NULL; + } + + /* If we've gotten this far, we've read and matched at least one entry + * successfully (in a previous call), so dirname has been copied into + * matchname already. + */ + if (G.os2.have_dirname) { + /* strcpy(G.os2.matchname, G.os2.dirname); */ + fnamestart = G.os2.matchname + G.os2.dirnamelen; + } else + fnamestart = G.os2.matchname; + while ((file = readdir(__G__ G.os2.wild_dir)) != NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", + FnFilter1(file->d_name))); + strcpy(fnamestart, file->d_name); + if (strrchr(fnamestart, '.') == (char *)NULL) + strcat(fnamestart, "."); + if (match(fnamestart, G.os2.wildname, 1 WISEP)) { /* 1==ignore case */ + Trace((stderr, "do_wild: match() succeeds\n")); + /* remove trailing dot */ + fnamestart += strlen(fnamestart) - 1; + if (*fnamestart == '.') + *fnamestart = '\0'; + return G.os2.matchname; + } + } + + closedir(G.os2.wild_dir); /* have read at least one entry; nothing left */ + G.os2.wild_dir = NULL; + G.os2.notfirstcall = FALSE; /* reset for new wildspec */ + if (G.os2.have_dirname) + free(G.os2.dirname); + return (char *)NULL; + +} /* end function do_wild() */ + +#endif /* !SFX */ + + +/* scan extra fields for something we happen to know */ + +static int EvalExtraFields(__GPRO__ const char *path, + void *extra_field, unsigned ef_len) +{ + char *ef_ptr = extra_field; + PEFHEADER pEFblock; + int rc = PK_OK; + + while (ef_len >= sizeof(EFHEADER)) + { + pEFblock = (PEFHEADER) ef_ptr; + + if (pEFblock -> nSize > (ef_len - EB_HEADSIZE)) + return PK_ERR; /* claimed EFblock length exceeds EF size! */ + + switch (pEFblock -> nID) + { + case EF_OS2: + rc = SetEAs(__G__ path, ef_ptr); + break; + case EF_ACL: + rc = (uO.X_flag) ? SetACL(__G__ path, ef_ptr) : PK_OK; + break; +#if 0 + case EF_IZUNIX: + case EF_PKUNIX: + /* handled elsewhere */ + break; +#endif + default: + TTrace((stderr,"EvalExtraFields: unknown extra field block, ID=%d\n", + pEFblock -> nID)); + break; + } + + ef_ptr += (pEFblock -> nSize + EB_HEADSIZE); + ef_len -= (pEFblock -> nSize + EB_HEADSIZE); + + if (rc != PK_OK) + break; + } + + return rc; +} + + + +/************************/ +/* Function mapattr() */ +/************************/ + +int mapattr(__G) + __GDEF +{ + /* set archive bit (file is not backed up): */ + G.pInfo->file_attr = (unsigned)(G.crec.external_file_attributes | 32) & 0xff; + return 0; +} + + + + + +/************************/ +/* Function mapname() */ +/************************/ + +/* + * There are presently two possibilities in OS/2: the output filesystem is + * FAT, or it is HPFS. If the former, we need to map to FAT, obviously, but + * we *also* must map to HPFS and store that version of the name in extended + * attributes. Either way, we need to map to HPFS, so the main mapname + * routine does that. In the case that the output file system is FAT, an + * extra filename-mapping routine is called in checkdir(). While it should + * be possible to determine the filesystem immediately upon entry to mapname(), + * it is conceivable that the DOS APPEND utility could be added to OS/2 some- + * day, allowing a FAT directory to be APPENDed to an HPFS drive/path. There- + * fore we simply check the filesystem at each path component. + * + * Note that when alternative IFSes become available/popular, everything will + * become immensely more complicated. For example, a Minix filesystem would + * have limited filename lengths like FAT but no extended attributes in which + * to store the longer versions of the names. A BSD Unix filesystem would + * support paths of length 1024 bytes or more, but it is not clear that FAT + * EAs would allow such long .LONGNAME fields or that OS/2 would properly + * restore such fields when moving files from FAT to the new filesystem. + * + * GRR: some or all of the following chars should be checked in either + * mapname (HPFS) or map2fat (FAT), depending: ,=^+'"[]<>|\t& + */ +int mapname(__G__ renamed) + __GDEF + int renamed; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - caution (truncated filename) + * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) + * MPN_ERR_SKIP - error -> skip entry + * MPN_ERR_TOOLONG - error -> path is too long + * MPN_NOMEM - error (memory allocation failed) -> skip entry + * [also MPN_VOL_LABEL, MPN_CREATED_DIR] + */ +{ + char pathcomp[FILNAMSIZ]; /* path-component buffer */ + char *pp, *cp=(char *)NULL; /* character pointers */ + char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ +#ifdef ACORN_FTYPE_NFS + char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ + RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */ +#endif + int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ + int error = MPN_OK; + register unsigned workch; /* hold the character being tested */ + + +/*--------------------------------------------------------------------------- + Initialize various pointers and counters and stuff. + ---------------------------------------------------------------------------*/ + + /* can create path as long as not just freshening, or if user told us */ + G.create_dirs = (!uO.fflag || renamed); + + G.os2.created_dir = FALSE; /* not yet */ + G.os2.renamed_fullpath = FALSE; + G.os2.fnlen = strlen(G.filename); + +/* GRR: for VMS, convert to internal format now or later? or never? */ + if (renamed) { + cp = G.filename - 1; /* point to beginning of renamed name... */ + while (*++cp) + if (*cp == '\\') /* convert backslashes to forward */ + *cp = '/'; + cp = G.filename; + /* use temporary rootpath if user gave full pathname */ + if (G.filename[0] == '/') { + G.os2.renamed_fullpath = TRUE; + pathcomp[0] = '/'; /* copy the '/' and terminate */ + pathcomp[1] = '\0'; + ++cp; + } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') { + G.os2.renamed_fullpath = TRUE; + pp = pathcomp; + *pp++ = *cp++; /* copy the "d:" (+ '/', possibly) */ + *pp++ = *cp++; + if (*cp == '/') + *pp++ = *cp++; /* otherwise add "./"? */ + *pp = '\0'; + } + } + + /* pathcomp is ignored unless renamed_fullpath is TRUE: */ + if ((error = checkdir(__G__ pathcomp, INIT)) != 0) /* init path buffer */ + return error; /* ...unless no mem or vol label on hard disk */ + + *pathcomp = '\0'; /* initialize translation buffer */ + pp = pathcomp; /* point to translation buffer */ + if (!renamed) { /* cp already set if renamed */ + if (uO.jflag) /* junking directories */ +/* GRR: watch out for VMS version... */ + cp = (char *)strrchr(G.filename, '/'); + if (cp == (char *)NULL) /* no '/' or not junking dirs */ + cp = G.filename; /* point to internal zipfile-member pathname */ + else + ++cp; /* point to start of last component of path */ + } + +/*--------------------------------------------------------------------------- + Begin main loop through characters in filename. + ---------------------------------------------------------------------------*/ + + while ((workch = (uch)*cp++) != 0) { + + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + if (strcmp(pathcomp, ".") == 0) { + /* don't bother appending "./" to the path */ + *pathcomp = '\0'; + } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { + /* "../" dir traversal detected, skip over it */ + *pathcomp = '\0'; + killed_ddot = TRUE; /* set "show message" flag */ + } + /* when path component is not empty, append it now */ + if (*pathcomp != '\0' && + ((error = checkdir(__G__ pathcomp, APPEND_DIR)) + & MPN_MASK) > MPN_INF_TRUNC) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ + break; + + case ':': /* drive never stored, so no colon allowed */ + case '\\': /* "non-dos" FSs may allow '\\' as normal */ + *pp++ = '_'; /* character in filenames */ + break; /* -> map invalid chars to underscore */ + + case ';': /* start of VMS version? */ + lastsemi = pp; /* remove VMS version later... */ + *pp++ = ';'; /* but keep semicolon for now */ + break; + +#ifdef ACORN_FTYPE_NFS + case ',': /* NFS filetype extension */ + lastcomma = pp; + *pp++ = ','; /* keep for now; may need to remove */ + break; /* later, if requested */ +#endif + + case ' ': /* keep spaces unless specifically */ + if (uO.sflag) /* requested to change to underscore */ + *pp++ = '_'; + else + *pp++ = ' '; + break; + + default: + /* allow ASCII 255 and European characters in filenames: */ + if (isprint(workch) || workch >= 127) + *pp++ = (char)workch; + } /* end switch */ + + } /* end while loop */ + + /* Show warning when stripping insecure "parent dir" path components */ + if (killed_ddot && QCOND2) { + Info(slide, 0, ((char *)slide, LoadFarString(WarnDirTraversSkip), + FnFilter1(G.filename))); + if (!(error & ~MPN_MASK)) + error = (error & MPN_MASK) | PK_WARN; + } + +/*--------------------------------------------------------------------------- + Report if directory was created (and no file to create: filename ended + in '/'), check name to be sure it exists, and combine path and name be- + fore exiting. + ---------------------------------------------------------------------------*/ + + if (G.filename[G.os2.fnlen-1] == '/') { + checkdir(__G__ G.filename, GETPATH); + if (G.os2.created_dir) { + if (QCOND2) + Info(slide, 0, ((char *)slide, LoadFarString(Creating), + FnFilter1(G.filename))); + if (G.extra_field) { /* zipfile extra field has extended attribs */ + int err = EvalExtraFields(__G__ G.filename, G.extra_field, + G.lrec.extra_field_length); + + if (err == IZ_EF_TRUNC) { + if (uO.qflag) + Info(slide, 1, ((char *)slide, "%-22s ", + FnFilter1(G.filename))); + Info(slide, 1, ((char *)slide, LoadFarString(TruncEAs), + makeword(G.extra_field+2)-10, "\n")); + } else if (!uO.qflag) + (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); + } else if (!uO.qflag) + (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); + + /* set date/time stamps */ + SetPathAttrTimes(__G__ G.pInfo->file_attr & ~A_ARCHIVE, 1); + + /* dir time already set */ + return (error & ~MPN_MASK) | MPN_CREATED_DIR; + + } else if (G.extra_field && IS_OVERWRT_ALL) { + /* overwrite EAs of existing directory since user requested it */ + int err = EvalExtraFields(__G__ G.filename, G.extra_field, + G.lrec.extra_field_length); + + if (err == IZ_EF_TRUNC) { + Info(slide, 0x421, ((char *)slide, "%-22s ", + FnFilter1(G.filename))); + Info(slide, 0x401, ((char *)slide, LoadFarString(TruncEAs), + makeword(G.extra_field+2)-10, "\n")); + } + + /* set date/time stamps (dirs only have creation times) */ + SetPathAttrTimes(__G__ G.pInfo->file_attr & ~A_ARCHIVE, 1); + } + /* dir existed already; don't look for data to extract */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + *pp = '\0'; /* done with pathcomp: terminate it */ + + /* if not saving them, remove VMS version numbers (appended "###") */ + if (!uO.V_flag && lastsemi) { + pp = lastsemi + 1; /* semi-colon was kept: expect #s after */ + while (isdigit((uch)(*pp))) + ++pp; + if (*pp == '\0') /* only digits between ';' and end: nuke */ + *lastsemi = '\0'; + } + +#ifdef ACORN_FTYPE_NFS + /* translate Acorn filetype information if asked to do so */ + if (uO.acorn_nfs_ext && + (ef_spark = (RO_extra_block *) + getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) + != (RO_extra_block *)NULL) + { + /* file *must* have a RISC OS extra field */ + long ft = (long)makelong(ef_spark->loadaddr); + /*32-bit*/ + if (lastcomma) { + pp = lastcomma + 1; + while (isxdigit((uch)(*pp))) ++pp; + if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */ + } + if ((ft & 1<<31)==0) ft=0x000FFD00; + sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF); + } +#endif /* ACORN_FTYPE_NFS */ + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed), + FnFilter1(G.filename))); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + + checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ + checkdir(__G__ G.filename, GETPATH); + Trace((stderr, "mapname returns with filename = [%s] (error = %d)\n\n", + FnFilter1(G.filename), error)); + + if (G.pInfo->vollabel) { /* set the volume label now */ + VOLUMELABEL FSInfoBuf; +/* GRR: "VOLUMELABEL" defined for IBM C and emx, but haven't checked MSC... */ + + strcpy(FSInfoBuf.szVolLabel, G.filename); + FSInfoBuf.cch = (BYTE)strlen(FSInfoBuf.szVolLabel); + + if (!uO.qflag) + Info(slide, 0, ((char *)slide, LoadFarString(Labelling), + (char)(G.os2.nLabelDrive + 'a' - 1), FnFilter1(G.filename))); + if (DosSetFSInfo(G.os2.nLabelDrive, FSIL_VOLSER, (PBYTE)&FSInfoBuf, + sizeof(VOLUMELABEL))) + { + Info(slide, 1, ((char *)slide, LoadFarString(ErrSetVolLabel))); + return (error & ~MPN_MASK) | MPN_ERR_SKIP; + } + /* success: skip the "extraction" quietly */ + return (error & ~MPN_MASK) | MPN_INF_SKIP; + } + + return error; + +} /* end function mapname() */ + + + + + +/***********************/ +/* Function checkdir() */ +/***********************/ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: + * MPN_OK - no problem detected + * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename + * MPN_INF_SKIP - path doesn't exist, not allowed to create + * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path + * exists and is not a directory, but is supposed to be + * MPN_ERR_TOOLONG - path is too long + * MPN_NOMEM - can't allocate memory for filename buffers + */ +{ + /* moved to os2data.h so they can be global */ +#if 0 + static int rootlen = 0; /* length of rootpath */ + static char *rootpath; /* user's "extract-to" directory */ + static char *buildpathHPFS; /* full path (so far) to extracted file, */ + static char *buildpathFAT; /* both HPFS/EA (main) and FAT versions */ + static char *endHPFS; /* corresponding pointers to end of */ + static char *endFAT; /* buildpath ('\0') */ +#endif + +# define FN_MASK 7 +# define FUNCTION (flag & FN_MASK) + + + +/*--------------------------------------------------------------------------- + APPEND_DIR: append the path component to the path being built and check + for its existence. If doesn't exist and we are creating directories, do + so for this one; else signal success or error as appropriate. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_DIR) { + char *p = pathcomp; + int longdirEA, too_long=FALSE; + + Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); + while ((*G.os2.endHPFS = *p++) != '\0') /* copy to HPFS filename */ + ++G.os2.endHPFS; + if (IsFileNameValid(G.os2.buildpathHPFS)) { + longdirEA = FALSE; + p = pathcomp; + while ((*G.os2.endFAT = *p++) != '\0') /* copy to FAT filename, too */ + ++G.os2.endFAT; + } else { + longdirEA = TRUE; +/* GRR: check error return? */ + map2fat(pathcomp, &G.os2.endFAT); /* map, put in FAT fn, update endFAT */ + } + + /* GRR: could do better check, see if overrunning buffer as we go: + * check endHPFS-G.os2.buildpathHPFS after each append, set warning variable + * if within 20 of FILNAMSIZ; then if var set, do careful check when + * appending. Clear variable when begin new path. */ + + /* next check: need to append '/', at least one-char name, '\0' */ + if ((G.os2.endHPFS-G.os2.buildpathHPFS) > FILNAMSIZ-3) + too_long = TRUE; /* check if extracting dir? */ +#ifdef MSC /* MSC 6.00 bug: stat(non-existent-dir) == 0 [exists!] */ + if (GetFileTime(G.os2.buildpathFAT) == -1 || stat(G.os2.buildpathFAT, &G.statbuf)) +#else + if (stat(G.os2.buildpathFAT, &G.statbuf)) /* path doesn't exist */ +#endif + { + if (!G.create_dirs) { /* told not to create (freshening) */ + free(G.os2.buildpathHPFS); + free(G.os2.buildpathFAT); + /* path doesn't exist: nothing to do */ + return MPN_INF_SKIP; + } + if (too_long) { /* GRR: should allow FAT extraction w/o EAs */ + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong), + FnFilter1(G.os2.buildpathHPFS))); + free(G.os2.buildpathHPFS); + free(G.os2.buildpathFAT); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + if (MKDIR(G.os2.buildpathFAT, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir), + FnFilter2(G.os2.buildpathFAT), FnFilter1(G.filename))); + free(G.os2.buildpathHPFS); + free(G.os2.buildpathFAT); + /* path didn't exist, tried to create, failed */ + return MPN_ERR_SKIP; + } + G.os2.created_dir = TRUE; + /* only set EA if creating directory */ +/* GRR: need trailing '/' before function call? */ + if (longdirEA) { +#ifdef DEBUG + int e = +#endif + SetLongNameEA(G.os2.buildpathFAT, pathcomp); + Trace((stderr, "APPEND_DIR: SetLongNameEA() returns %d\n", e)); + } + } else if (!S_ISDIR(G.statbuf.st_mode)) { + Info(slide, 1, ((char *)slide, LoadFarString(DirIsntDirectory), + FnFilter2(G.os2.buildpathFAT), FnFilter1(G.filename))); + free(G.os2.buildpathHPFS); + free(G.os2.buildpathFAT); + /* path existed but wasn't dir */ + return MPN_ERR_SKIP; + } + if (too_long) { + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong), + FnFilter1(G.os2.buildpathHPFS))); + free(G.os2.buildpathHPFS); + free(G.os2.buildpathFAT); + /* no room for filenames: fatal */ + return MPN_ERR_TOOLONG; + } + *G.os2.endHPFS++ = '/'; + *G.os2.endFAT++ = '/'; + *G.os2.endHPFS = *G.os2.endFAT = '\0'; + Trace((stderr, "buildpathHPFS now = [%s]\n", + FnFilter1(G.os2.buildpathHPFS))); + Trace((stderr, "buildpathFAT now = [%s]\n", + FnFilter1(G.os2.buildpathFAT))); + return MPN_OK; + + } /* end if (FUNCTION == APPEND_DIR) */ + +/*--------------------------------------------------------------------------- + GETPATH: copy full FAT path to the string pointed at by pathcomp (want + filename to reflect name used on disk, not EAs; if full path is HPFS, + buildpathFAT and buildpathHPFS will be identical). Also free both paths. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == GETPATH) { + Trace((stderr, "getting and freeing FAT path [%s]\n", + FnFilter1(G.os2.buildpathFAT))); + Trace((stderr, "freeing HPFS path [%s]\n", + FnFilter1(G.os2.buildpathHPFS))); + strcpy(pathcomp, G.os2.buildpathFAT); + free(G.os2.buildpathFAT); + free(G.os2.buildpathHPFS); + G.os2.buildpathHPFS = G.os2.buildpathFAT = G.os2.endHPFS = G.os2.endFAT = (char *)NULL; + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + APPEND_NAME: assume the path component is the filename; append it and + return without checking for existence. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == APPEND_NAME) { + char *p = pathcomp; + int error = MPN_OK; + + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); + /* The buildpathHPFS buffer has been allocated large enough to + * hold the complete combined name, so there is no need to check + * for OS filename size limit overflow within the copy loop. + */ + while ((*G.os2.endHPFS = *p++) != '\0') { /* copy to HPFS filename */ + ++G.os2.endHPFS; + } + /* Now, check for OS filename size overflow. When detected, the + * mapped HPFS name is truncated and a warning message is shown. + */ + if ((G.os2.endHPFS-G.os2.buildpathHPFS) >= FILNAMSIZ) { + G.os2.buildpathHPFS[FILNAMSIZ-1] = '\0'; + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLongTrunc), + FnFilter1(G.filename), FnFilter2(G.os2.buildpathHPFS))); + error = MPN_INF_TRUNC; /* filename truncated */ + } + +/* GRR: how can longnameEA ever be set before this point??? we don't want + * to save the original name to EAs if user renamed it, do we? + * + * if (!G.os2.longnameEA && ((G.os2.longnameEA = !IsFileNameValid(name)) != 0)) + */ + /* The buildpathFAT buffer has the same allocated size as the + * buildpathHPFS buffer, so there is no need for an overflow check + * within the following copy loop, either. + */ + if (G.pInfo->vollabel || IsFileNameValid(G.os2.buildpathHPFS)) { + G.os2.longnameEA = FALSE; + /* copy to FAT filename, too */ + p = pathcomp; + while ((*G.os2.endFAT = *p++) != '\0') + ++G.os2.endFAT; + } else { + G.os2.longnameEA = TRUE; + if ((G.os2.lastpathcomp = (char *)malloc(strlen(pathcomp)+1)) == + (char *)NULL) + { + Info(slide, 1, ((char *)slide, + "checkdir warning: cannot save longname EA: out of memory\n")); + G.os2.longnameEA = FALSE; + /* can't set .LONGNAME extended attribute */ + error = MPN_INF_TRUNC; + } else /* used and freed in close_outfile() */ + strcpy(G.os2.lastpathcomp, pathcomp); + /* map, put in FAT fn, update endFAT */ + map2fat(pathcomp, &G.os2.endFAT); + } + + /* Check that the FAT path does not exceed the FILNAMSIZ limit, and + * truncate when neccessary. + * Note that truncation can only happen when the HPFS path (which is + * never shorter than the FAT path) has been already truncated. + * So, emission of the warning message and setting the error code + * has already happened. + */ + if ((G.os2.endFAT-G.os2.buildpathFAT) >= FILNAMSIZ) + G.os2.buildpathFAT[FILNAMSIZ-1] = '\0'; + Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n", + FnFilter1(G.os2.buildpathHPFS), FnFilter2(G.os2.buildpathFAT))); + + return error; /* could check for existence, prompt for new name... */ + + } /* end if (FUNCTION == APPEND_NAME) */ + +/*--------------------------------------------------------------------------- + INIT: allocate and initialize buffer space for the file currently being + extracted. If file was renamed with an absolute path, don't prepend the + extract-to path. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == INIT) { + Trace((stderr, "initializing buildpathHPFS and buildpathFAT to ")); +#ifdef ACORN_FTYPE_NFS + if ((G.os2.buildpathHPFS = (char *)malloc(G.os2.fnlen+G.os2.rootlen+ + (uO.acorn_nfs_ext ? 5 : 1))) +#else + if ((G.os2.buildpathHPFS = (char *)malloc(G.os2.fnlen+G.os2.rootlen+1)) +#endif + == (char *)NULL) + return MPN_NOMEM; +#ifdef ACORN_FTYPE_NFS + if ((G.os2.buildpathFAT = (char *)malloc(G.os2.fnlen+G.os2.rootlen+ + (uO.acorn_nfs_ext ? 5 : 1))) +#else + if ((G.os2.buildpathFAT = (char *)malloc(G.os2.fnlen+G.os2.rootlen+1)) +#endif + == (char *)NULL) { + free(G.os2.buildpathHPFS); + return MPN_NOMEM; + } + if (G.pInfo->vollabel) { /* use root or renamed path, but don't store */ +/* GRR: for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */ + if (G.os2.renamed_fullpath && pathcomp[1] == ':') + *G.os2.buildpathHPFS = (char)ToLower(*pathcomp); + else if (!G.os2.renamed_fullpath && G.os2.rootlen > 1 && G.os2.rootpath[1] == ':') + *G.os2.buildpathHPFS = (char)ToLower(*G.os2.rootpath); + else { + ULONG lMap; + DosQueryCurrentDisk(&G.os2.nLabelDrive, &lMap); + *G.os2.buildpathHPFS = (char)(G.os2.nLabelDrive - 1 + 'a'); + } + G.os2.nLabelDrive = *G.os2.buildpathHPFS - 'a' + 1; /* save for mapname() */ + if (uO.volflag == 0 || *G.os2.buildpathHPFS < 'a' || /* no labels/bogus? */ + (uO.volflag == 1 && !isfloppy(G.os2.nLabelDrive))) { /* -$: no fixed */ + free(G.os2.buildpathHPFS); + free(G.os2.buildpathFAT); + return MPN_VOL_LABEL; /* skipping with message */ + } + *G.os2.buildpathHPFS = '\0'; + } else if (G.os2.renamed_fullpath) /* pathcomp = valid data */ + strcpy(G.os2.buildpathHPFS, pathcomp); + else if (G.os2.rootlen > 0) + strcpy(G.os2.buildpathHPFS, G.os2.rootpath); + else + *G.os2.buildpathHPFS = '\0'; + G.os2.endHPFS = G.os2.buildpathHPFS; + G.os2.endFAT = G.os2.buildpathFAT; + while ((*G.os2.endFAT = *G.os2.endHPFS) != '\0') { + ++G.os2.endFAT; + ++G.os2.endHPFS; + } + Trace((stderr, "[%s]\n", FnFilter1(G.os2.buildpathHPFS))); + return MPN_OK; + } + +/*--------------------------------------------------------------------------- + ROOT: if appropriate, store the path in rootpath and create it if neces- + sary; else assume it's a zipfile member and return. This path segment + gets used in extracting all members from every zipfile specified on the + command line. Note that under OS/2 and MS-DOS, if a candidate extract-to + directory specification includes a drive letter (leading "x:"), it is + treated just as if it had a trailing '/'--that is, one directory level + will be created if the path doesn't exist, unless this is otherwise pro- + hibited (e.g., freshening). + ---------------------------------------------------------------------------*/ + +#if (!defined(SFX) || defined(SFX_EXDIR)) + if (FUNCTION == ROOT) { + Trace((stderr, "initializing root path to [%s]\n", + FnFilter1(pathcomp))); + if (pathcomp == (char *)NULL) { + G.os2.rootlen = 0; + return MPN_OK; + } + if (G.os2.rootlen > 0) /* rootpath was already set, nothing to do */ + return MPN_OK; + if ((G.os2.rootlen = strlen(pathcomp)) > 0) { + int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE; + char *tmproot; + + if ((tmproot = (char *)malloc(G.os2.rootlen+3)) == (char *)NULL) { + G.os2.rootlen = 0; + return MPN_NOMEM; + } + strcpy(tmproot, pathcomp); + if (isalpha((uch)tmproot[0]) && tmproot[1] == ':') + has_drive = TRUE; /* drive designator */ + if (tmproot[G.os2.rootlen-1] == '/') { + tmproot[--G.os2.rootlen] = '\0'; + had_trailing_pathsep = TRUE; + } + if (has_drive && (G.os2.rootlen == 2)) { + if (!had_trailing_pathsep) /* i.e., original wasn't "x:/" */ + add_dot = TRUE; /* relative path: add '.' before '/' */ + } else if (G.os2.rootlen > 0) { /* need not check "x:." and "x:/" */ +#ifdef MSC /* MSC 6.00 bug: stat(non-existent-dir) == 0 [exists!] */ + if (GetFileTime(tmproot) == -1 || + SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) +#else + if (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) +#endif + { /* path does not exist */ + if (!G.create_dirs /* || iswild(tmproot) */ + ) { + free(tmproot); + G.os2.rootlen = 0; + return MPN_INF_SKIP; /* treat as stored file */ + } + /* create directory (could add loop here scanning tmproot + * to create more than one level, but really necessary?) */ + if (MKDIR(tmproot, 0777) == -1) { + Info(slide, 1, ((char *)slide, + LoadFarString(CantCreateExtractDir), + FnFilter1(tmproot))); + free(tmproot); + G.os2.rootlen = 0; + /* path didn't exist, tried to create, failed: */ + /* file exists, or need 2+ directory levels */ + return MPN_ERR_SKIP; + } + } + } + if (add_dot) /* had just "x:", make "x:." */ + tmproot[G.os2.rootlen++] = '.'; + tmproot[G.os2.rootlen++] = '/'; + tmproot[G.os2.rootlen] = '\0'; + if ((G.os2.rootpath = realloc(tmproot, G.os2.rootlen+1)) == NULL) { + free(tmproot); + G.os2.rootlen = 0; + return MPN_NOMEM; + } + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.os2.rootpath))); + } + return MPN_OK; + } +#endif /* !SFX || SFX_EXDIR */ + +/*--------------------------------------------------------------------------- + END: free rootpath, immediately prior to program exit. + ---------------------------------------------------------------------------*/ + + if (FUNCTION == END) { + Trace((stderr, "freeing rootpath\n")); + if (G.os2.rootlen > 0) { + free(G.os2.rootpath); + G.os2.rootlen = 0; + } + return MPN_OK; + } + + return MPN_INVALID; /* should never reach */ + +} /* end function checkdir() */ + + + + + +/***********************/ +/* Function isfloppy() */ /* more precisely, is it removable? */ +/***********************/ + +static int isfloppy(nDrive) + int nDrive; /* 1 == A:, 2 == B:, etc. */ +{ + uch ParmList[1] = {0}; + uch DataArea[1] = {0}; + char Name[3]; + HFILE handle; +#ifdef __32BIT__ + ULONG rc; + ULONG action; +#else + USHORT rc; + USHORT action; +#endif + + + Name[0] = (char) (nDrive + 'A' - 1); + Name[1] = ':'; + Name[2] = 0; + + rc = DosOpen(Name, &handle, &action, 0L, FILE_NORMAL, FILE_OPEN, + OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR | + OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0L); + + if (rc == ERROR_NOT_READY) /* must be removable */ + return TRUE; + else if (rc) { /* other error: do default a/b heuristic instead */ + Trace((stderr, "error in DosOpen(DASD): guessing...\n", rc)); + return (nDrive == 1 || nDrive == 2)? TRUE : FALSE; + } + + rc = DosDevIOCtl(DataArea, sizeof(DataArea), ParmList, sizeof(ParmList), + DSK_BLOCKREMOVABLE, IOCTL_DISK, handle); + DosClose(handle); + + if (rc) { /* again, just check for a/b */ + Trace((stderr, "error in DosDevIOCtl category IOCTL_DISK, function " + "DSK_BLOCKREMOVABLE\n (rc = 0x%04x): guessing...\n", rc)); + return (nDrive == 1 || nDrive == 2)? TRUE : FALSE; + } else { + return DataArea[0] ? FALSE : TRUE; + } +} /* end function isfloppy() */ + + + + + +static int IsFileNameValid(const char *name) +{ + HFILE hf; +#ifdef __32BIT__ + ULONG uAction; +#else + USHORT uAction; +#endif + + switch( DosOpen((PSZ) name, &hf, &uAction, 0, 0, FILE_OPEN, + OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0) ) + { + case ERROR_INVALID_NAME: + case ERROR_FILENAME_EXCED_RANGE: + return FALSE; + case NO_ERROR: + DosClose(hf); + default: + return TRUE; + } +} + + + + + +/**********************/ +/* Function map2fat() */ +/**********************/ + +static void map2fat(pathcomp, pEndFAT) + char *pathcomp, **pEndFAT; +{ + char *ppc = pathcomp; /* variable pointer to pathcomp */ + char *pEnd = *pEndFAT; /* variable pointer to buildpathFAT */ + char *pBegin = *pEndFAT; /* constant pointer to start of this comp. */ + char *last_dot = (char *)NULL; /* last dot not converted to underscore */ + int dotname = FALSE; /* flag: path component begins with dot */ + /* ("." and ".." don't count) */ + register unsigned workch; /* hold the character being tested */ + + + /* Only need check those characters which are legal in HPFS but not + * in FAT: to get here, must already have passed through mapname. + * (GRR: oops, small bug--if char was quoted, no longer have any + * knowledge of that.) Also must truncate path component to ensure + * 8.3 compliance... + */ + while ((workch = (uch)*ppc++) != 0) { + switch (workch) { + case '[': /* add '"' '+' ',' '=' ?? */ + case ']': + *pEnd++ = '_'; /* convert brackets to underscores */ + break; + + case '.': + if (pEnd == *pEndFAT) { /* nothing appended yet... */ + if (*ppc == '\0') /* don't bother appending a */ + break; /* "./" component to the path */ + else if (*ppc == '.' && ppc[1] == '\0') { /* "../" */ + *pEnd++ = '.'; /* add first dot, unchanged... */ + ++ppc; /* skip second dot, since it will */ + } else { /* be "added" at end of if-block */ + *pEnd++ = '_'; /* FAT doesn't allow null filename */ + dotname = TRUE; /* bodies, so map .exrc -> _.exrc */ + } /* (extra '_' now, "dot" below) */ + } else if (dotname) { /* found a second dot, but still */ + dotname = FALSE; /* have extra leading underscore: */ + *pEnd = '\0'; /* remove it by shifting chars */ + pEnd = *pEndFAT + 1; /* left one space (e.g., .p1.p2: */ + while (pEnd[1]) { /* __p1 -> _p1_p2 -> _p1.p2 when */ + *pEnd = pEnd[1]; /* finished) [opt.: since first */ + ++pEnd; /* two chars are same, can start */ + } /* shifting at second position] */ + } + last_dot = pEnd; /* point at last dot so far... */ + *pEnd++ = '_'; /* convert dot to underscore for now */ + break; + + default: + *pEnd++ = (char)workch; + + } /* end switch */ + } /* end while loop */ + + *pEnd = '\0'; /* terminate buildpathFAT */ + + /* NOTE: keep in mind that pEnd points to the end of the path + * component, and *pEndFAT still points to the *beginning* of it... + * Also note that the algorithm does not try to get too fancy: + * if there are no dots already, the name either gets truncated + * at 8 characters or the last underscore is converted to a dot + * (only if more characters are saved that way). In no case is + * a dot inserted between existing characters. + */ + if (last_dot == (char *)NULL) { /* no dots: check for underscores... */ + char *plu = strrchr(pBegin, '_'); /* pointer to last underscore */ + + if (plu == (char *)NULL) { /* no dots, no underscores: truncate at 8 */ + *pEndFAT += 8; /* chars (could insert '.' and keep 11...) */ + if (*pEndFAT > pEnd) + *pEndFAT = pEnd; /* oops...didn't have 8 chars to truncate */ + else + **pEndFAT = '\0'; + } else if (MIN(plu - pBegin, 8) + MIN(pEnd - plu - 1, 3) > 8) { + last_dot = plu; /* be lazy: drop through to next if-block */ + } else if ((pEnd - *pEndFAT) > 8) { + *pEndFAT += 8; /* more fits into just basename than if */ + **pEndFAT = '\0'; /* convert last underscore to dot */ + } else + *pEndFAT = pEnd; /* whole thing fits into 8 chars or less */ + } + + if (last_dot != (char *)NULL) { /* one dot (or two, in the case of */ + *last_dot = '.'; /* "..") is OK: put it back in */ + + if ((last_dot - pBegin) > 8) { + char *p, *q; + int i; + + p = last_dot; + q = last_dot = pBegin + 8; + for (i = 0; (i < 4) && *p; ++i) /* too many chars in basename: */ + *q++ = *p++; /* shift ".ext" left and */ + *q = '\0'; /* truncate/terminate it */ + *pEndFAT = q; + } else if ((pEnd - last_dot) > 4) { /* too many chars in extension */ + *pEndFAT = last_dot + 4; + **pEndFAT = '\0'; + } else + *pEndFAT = pEnd; /* filename is fine; point at terminating zero */ + + if ((last_dot - pBegin) > 0 && last_dot[-1] == ' ') + last_dot[-1] = '_'; /* NO blank in front of '.'! */ + } +} /* end function map2fat() */ + + + + + +static int SetLongNameEA(char *name, char *longname) +{ + EAOP eaop; + FEALST fealst; + + eaop.fpFEAList = (PFEALIST) &fealst; + eaop.fpGEAList = NULL; + eaop.oError = 0; + + strcpy((char *) fealst.szName, ".LONGNAME"); + strcpy((char *) fealst.szValue, longname); + + fealst.cbList = sizeof(fealst) - CCHMAXPATH + strlen((char *) fealst.szValue); + fealst.cbName = (BYTE) strlen((char *) fealst.szName); + fealst.cbValue = sizeof(USHORT) * 2 + strlen((char *) fealst.szValue); + +#ifdef __32BIT__ + fealst.oNext = 0; +#endif + fealst.fEA = 0; + fealst.eaType = 0xFFFD; + fealst.eaSize = strlen((char *) fealst.szValue); + + return DosSetPathInfo(name, FIL_QUERYEASIZE, + (PBYTE) &eaop, sizeof(eaop), 0); +} + + + + + +/****************************/ +/* Function close_outfile() */ +/****************************/ + + /* GRR: need to return error level!! */ + +void close_outfile(__G) /* only for extracted files, not directories */ + __GDEF +{ + fclose(G.outfile); + + /* set extra fields, both stored-in-zipfile and .LONGNAME flavors */ + if (G.extra_field) { /* zipfile extra field may have extended attribs */ + int err = EvalExtraFields(__G__ G.filename, G.extra_field, + G.lrec.extra_field_length); + + if (err == IZ_EF_TRUNC) { + if (uO.qflag) + Info(slide, 1, ((char *)slide, "%-22s ", + FnFilter1(G.filename))); + Info(slide, 1, ((char *)slide, LoadFarString(TruncEAs), + makeword(G.extra_field+2)-10, uO.qflag? "\n" : "")); + } + } + + if (G.os2.longnameEA) { +#ifdef DEBUG + int e = +#endif + SetLongNameEA(G.filename, G.os2.lastpathcomp); + Trace((stderr, "close_outfile: SetLongNameEA() returns %d\n", e)); + free(G.os2.lastpathcomp); + } + + /* set date/time and permissions */ + SetPathAttrTimes(__G__ G.pInfo->file_attr, 0); + +} /* end function close_outfile() */ + + + + + +/******************************/ +/* Function check_for_newer() */ +/******************************/ + +int check_for_newer(__G__ filename) /* return 1 if existing file newer or equal; */ + __GDEF + char *filename; /* 0 if older; -1 if doesn't exist yet */ +{ + ulg existing, archive; +#ifdef USE_EF_UT_TIME + iztimes z_utime; +#endif + + if ((existing = (ulg)GetFileTime(filename)) == (ulg)-1) + return DOES_NOT_EXIST; + +#ifdef USE_EF_UT_TIME + if (G.extra_field && +#ifdef IZ_CHECK_TZ + G.tz_is_valid && +#endif + (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, + G.lrec.last_mod_dos_datetime, &z_utime, NULL) + & EB_UT_FL_MTIME)) + { + TTrace((stderr, "check_for_newer: using Unix extra field mtime\n")); + archive = Utime2DosDateTime(z_utime.mtime); + } else { + archive = G.lrec.last_mod_dos_datetime; + } +#else /* !USE_EF_UT_TIME */ + archive = G.lrec.last_mod_dos_datetime; +#endif /* ?USE_EF_UT_TIME */ + + return (existing >= archive); +} /* end function check_for_newer() */ + + + + + +#ifndef SFX + +/*************************/ +/* Function dateformat() */ +/*************************/ + +int dateformat() +{ +/*----------------------------------------------------------------------------- + For those operating systems which support it, this function returns a value + which tells how national convention says that numeric dates are displayed. + Return values are DF_YMD, DF_DMY and DF_MDY. + -----------------------------------------------------------------------------*/ + + switch (GetCountryInfo()) { + case 0: + return DF_MDY; + case 1: + return DF_DMY; + case 2: + return DF_YMD; + } + return DF_MDY; /* default if error */ + +} /* end function dateformat() */ + + + + + +/************************/ +/* Function version() */ +/************************/ + +void version(__G) + __GDEF +{ + int len; +#if defined(__IBMC__) || defined(__WATCOMC__) || defined(_MSC_VER) + char buf[80]; +#endif + + len = sprintf((char *)slide, LoadFarString(CompiledWith), + +#if defined(__GNUC__) +# ifdef __EMX__ /* __EMX__ is defined as "1" only (sigh) */ + "emx+gcc ", __VERSION__, +# else + "gcc ", __VERSION__, +# endif +#elif defined(__IBMC__) + "IBM ", +# if (__IBMC__ < 200) + (sprintf(buf, "C Set/2 %d.%02d", __IBMC__/100,__IBMC__%100), buf), +# elif (__IBMC__ < 300) + (sprintf(buf, "C Set++ %d.%02d", __IBMC__/100,__IBMC__%100), buf), +# else + (sprintf(buf, "Visual Age C++ %d.%02d", __IBMC__/100,__IBMC__%100), buf), +# endif +#elif defined(__WATCOMC__) + "Watcom C", (sprintf(buf, " (__WATCOMC__ = %d)", __WATCOMC__), buf), +#elif defined(__TURBOC__) +# ifdef __BORLANDC__ + "Borland C++", +# if (__BORLANDC__ < 0x0460) + " 1.0", +# elif (__BORLANDC__ == 0x0460) + " 1.5", /* from Kai Uwe: three less than DOS */ +# else + " 2.0", /* (__BORLANDC__ == 0x0500)? */ +# endif +# else + "Turbo C", /* these are probably irrelevant */ +# if (__TURBOC__ >= 661) + "++ 1.0 or later", +# elif (__TURBOC__ == 661) + " 3.0?", +# elif (__TURBOC__ == 397) + " 2.0", +# else + " 1.0 or 1.5?", +# endif +# endif +#elif defined(MSC) + "Microsoft C ", +# ifdef _MSC_VER + (sprintf(buf, "%d.%02d", _MSC_VER/100, _MSC_VER%100), buf), +# else + "5.1 or earlier", +# endif +#else + "unknown compiler", "", +#endif /* ?compilers */ + + "OS/2", + +/* GRR: does IBM C/2 identify itself as IBM rather than Microsoft? */ +#if (defined(MSC) || (defined(__WATCOMC__) && !defined(__386__))) +# if defined(M_I86HM) || defined(__HUGE__) + " (16-bit, huge)", +# elif defined(M_I86LM) || defined(__LARGE__) + " (16-bit, large)", +# elif defined(M_I86MM) || defined(__MEDIUM__) + " (16-bit, medium)", +# elif defined(M_I86CM) || defined(__COMPACT__) + " (16-bit, compact)", +# elif defined(M_I86SM) || defined(__SMALL__) + " (16-bit, small)", +# elif defined(M_I86TM) || defined(__TINY__) + " (16-bit, tiny)", +# else + " (16-bit)", +# endif +#else + " (32-bit)", +#endif + +#ifdef __DATE__ + " on ", __DATE__ +#else + "", "" +#endif + ); + + (*G.message)((zvoid *)&G, slide, (ulg)len, 0); + /* MSC can't handle huge macro expansions */ + + /* temporary debugging code for Borland compilers only */ + /* __TCPLUSPLUS__, __BCPLUSPLUS__ not defined for v1.5 */ +#if (defined(__TURBOC__) && defined(DEBUG)) + Info(slide, 0, ((char *)slide, "\t(__TURBOC__ = 0x%04x = %d)\n", __TURBOC__, + __TURBOC__)); +#ifdef __BORLANDC__ + Info(slide, 0, ((char *)slide, "\t(__BORLANDC__ = 0x%04x)\n",__BORLANDC__)); +#else + Info(slide, 0, ((char *)slide, "\tdebug(__BORLANDC__ not defined)\n")); +#endif +#endif /* __TURBOC__ && DEBUG */ + +} /* end function version() */ + +#endif /* !SFX */ + +#endif /* !FUNZIP */ + + + +#ifdef MY_ZCALLOC /* Special zcalloc function for MEMORY16 (MSDOS/OS2) */ + +#if defined(MSC) || defined(__WATCOMC__) +#if (!defined(_MSC_VER) || (_MSC_VER < 700)) +# define _halloc halloc +# define _hfree hfree +#endif + +zvoid far *zcalloc (unsigned items, unsigned size) +{ + return (zvoid far *)_halloc((long)items, size); +} + +zvoid zcfree (zvoid far *ptr) +{ + _hfree((void huge *)ptr); +} +#endif /* MSC || __WATCOMC__ */ + +#endif /* MY_ZCALLOC */ + + + +#ifndef FUNZIP + +/* This table can be static because it is pseudo-constant */ +static unsigned char cUpperCase[256], cLowerCase[256]; +static BOOL bInitialized=FALSE; + +/* Initialize the tables of upper- and lowercase characters, including + handling of country-dependent characters. */ + +static void InitNLS(void) +{ + unsigned nCnt, nU; + COUNTRYCODE cc; + + if (bInitialized == FALSE) { + bInitialized = TRUE; + + for ( nCnt = 0; nCnt < 256; nCnt++ ) + cUpperCase[nCnt] = cLowerCase[nCnt] = (unsigned char) nCnt; + + cc.country = cc.codepage = 0; + DosMapCase(sizeof(cUpperCase), &cc, (PCHAR) cUpperCase); + + for ( nCnt = 0; nCnt < 256; nCnt++ ) { + nU = cUpperCase[nCnt]; + if (nU != nCnt && cLowerCase[nU] == (unsigned char) nU) + cLowerCase[nU] = (unsigned char) nCnt; + } + + for ( nCnt = 'A'; nCnt <= 'Z'; nCnt++ ) + cLowerCase[nCnt] = (unsigned char) (nCnt - 'A' + 'a'); + } +} + + +int IsUpperNLS(int nChr) +{ + return (cUpperCase[nChr] == (unsigned char) nChr); +} + + +int ToLowerNLS(int nChr) +{ + return cLowerCase[nChr]; +} + + +char *StringLower(char *szArg) +{ + unsigned char *szPtr; + + for ( szPtr = (unsigned char *) szArg; *szPtr; szPtr++ ) + *szPtr = cLowerCase[*szPtr]; + return szArg; +} + + +#ifdef MORE +int screensize(int *tt_rows, int *tt_cols) +{ +#ifdef __EMX__ + int dst[2]; + _scrsize(dst); + if (tt_rows != NULL) *tt_rows = dst[1]; + if (tt_cols != NULL) *tt_cols = dst[0]; +#else + VIOMODEINFO vmi; + vmi.cb = sizeof(vmi); + VioGetMode(&vmi, 0); + if (tt_rows != NULL) *tt_rows = vmi.row; + if (tt_cols != NULL) *tt_cols = vmi.col; +#endif + return 0; +} +#endif /* MORE */ + + +#if defined(__IBMC__) && defined(__DEBUG_ALLOC__) +void DebugMalloc(void) +{ + _dump_allocated(0); /* print out debug malloc memory statistics */ +} +#endif + + +#if defined(REENTRANT) && defined(USETHREADID) +ulg GetThreadId(void) +{ + PTIB pptib; /* Address of a pointer to the + Thread Information Block */ + PPIB pppib; /* Address of a pointer to the + Process Information Block */ + + DosGetInfoBlocks(&pptib, &pppib); + return pptib->tib_ptib2->tib2_ultid; +} +#endif /* defined(REENTRANT) && defined(USETHREADID) */ + + +void os2GlobalsCtor(__GPRO) +{ + G.os2.nLastDrive = (USHORT)(-1); + +#ifdef OS2DLL + G.os2.rexx_mes = "0"; +#endif + + InitNLS(); +} + +#endif /* !FUNZIP */ diff --git a/os2/os2acl.c b/os2/os2acl.c new file mode 100644 index 0000000..4f88643 --- /dev/null +++ b/os2/os2acl.c @@ -0,0 +1,385 @@ +/* + 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 +*/ +/* os2acl.c - access to OS/2 (LAN Server) ACLs + * + * Author: Kai Uwe Rommel + * Created: Mon Aug 08 1994 + * + */ + +/* + * supported 32-bit compilers: + * - emx+gcc + * - IBM C Set++ 2.1 or newer + * - Watcom C/C++ 10.0 or newer + * + * supported 16-bit compilers: + * - MS C 6.00A + * - Watcom C/C++ 10.0 or newer + * + * supported OS/2 LAN environments: + * - IBM LAN Server/Requester 3.0, 4.0 and 5.0 (Warp Server) + * - IBM Peer 1.0 (Warp Connect) + */ + +#ifdef KUR + static char *rcsid = + "$Id: os2acl.c,v 1.3 1996/04/03 19:18:27 rommel Exp rommel $"; + static char *rcsrev = "$Revision: 1.3 $"; +#endif + +/* + * $Log: os2acl.c,v $ + * Revision 1.3 1996/04/03 19:18:27 rommel + * minor fixes + * + * Revision 1.2 1996/03/30 22:03:52 rommel + * avoid frequent dynamic allocation for every call + * streamlined code + * + * Revision 1.1 1996/03/30 09:35:00 rommel + * Initial revision + * + */ + +#include +#include +#include +#include +#include + +#define INCL_NOPM +#define INCL_DOS +#define INCL_DOSERRORS +#include + +#include "os2/os2acl.h" + +#define UNLEN 20 + +#if defined(__WATCOMC__) && defined(__386__) && !defined(__32BIT__) +#define __32BIT__ +#endif + +#ifdef __32BIT__ +typedef ULONG U_INT; +#ifdef __EMX__ +#define PSTR16 _far16ptr +#define PTR16(x) _emx_32to16(x) +#else /* other 32-bit */ +#define PSTR16 PCHAR16 +#define PTR16(x) ((PCHAR16)(x)) +#endif +#else /* 16-bit */ +typedef USHORT U_INT; +#define PSTR16 PSZ +#define PTR16(x) (x) +#endif + +typedef struct access_list +{ + char acl_ugname[UNLEN+1]; + char acl_pad; + USHORT acl_access; +} +ACCLIST; + +typedef struct access_info +{ + PSTR16 acc_resource_name; + USHORT acc_attr; + USHORT acc_count; +} +ACCINFO; + +static ACCINFO *ai; +static char *path, *data; + +#ifdef __32BIT__ + +#ifdef __EMX__ + +static USHORT (APIENTRY *_NetAccessGetInfo)(PSZ pszServer, PSZ pszResource, + USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail); +static USHORT (APIENTRY *_NetAccessSetInfo)(PSZ pszServer, PSZ pszResource, + USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum); +static USHORT (APIENTRY *_NetAccessAdd)(PSZ pszServer, + USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer); + +USHORT NetAccessGetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel, + PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail) +{ + return (USHORT) + (_THUNK_PROLOG (4+4+2+4+2+4); + _THUNK_FLAT (pszServer); + _THUNK_FLAT (pszResource); + _THUNK_SHORT (sLevel); + _THUNK_FLAT (pbBuffer); + _THUNK_SHORT (cbBuffer); + _THUNK_FLAT (pcbTotalAvail); + _THUNK_CALLI (_emx_32to16(_NetAccessGetInfo))); +} + +USHORT NetAccessSetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel, + PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum) +{ + return (USHORT) + (_THUNK_PROLOG (4+4+2+4+2+2); + _THUNK_FLAT (pszServer); + _THUNK_FLAT (pszResource); + _THUNK_SHORT (sLevel); + _THUNK_FLAT (pbBuffer); + _THUNK_SHORT (cbBuffer); + _THUNK_SHORT (sParmNum); + _THUNK_CALLI (_emx_32to16(_NetAccessSetInfo))); +} + +USHORT NetAccessAdd(PSZ pszServer, USHORT sLevel, + PVOID pbBuffer, USHORT cbBuffer) +{ + return (USHORT) + (_THUNK_PROLOG (4+2+4+2); + _THUNK_FLAT (pszServer); + _THUNK_SHORT (sLevel); + _THUNK_FLAT (pbBuffer); + _THUNK_SHORT (cbBuffer); + _THUNK_CALLI (_emx_32to16(_NetAccessAdd))); +} + +#else /* other 32-bit */ + +APIRET16 (* APIENTRY16 NetAccessGetInfo)(PCHAR16 pszServer, PCHAR16 pszResource, + USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, PVOID16 pcbTotalAvail); +APIRET16 (* APIENTRY16 NetAccessSetInfo)(PCHAR16 pszServer, PCHAR16 pszResource, + USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, USHORT sParmNum); +APIRET16 (* APIENTRY16 NetAccessAdd)(PCHAR16 pszServer, + USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer); + +#define _NetAccessGetInfo NetAccessGetInfo +#define _NetAccessSetInfo NetAccessSetInfo +#define _NetAccessAdd NetAccessAdd + +#if !defined(__IBMC__) || !defined(__TILED__) +#define _tmalloc malloc +#define _tfree free +#endif + +#endif +#else /* 16-bit */ + +USHORT (APIENTRY *NetAccessGetInfo)(PSZ pszServer, PSZ pszResource, + USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail); +USHORT (APIENTRY *NetAccessSetInfo)(PSZ pszServer, PSZ pszResource, + USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum); +USHORT (APIENTRY *NetAccessAdd)(PSZ pszServer, + USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer); + +#define _NetAccessGetInfo NetAccessGetInfo +#define _NetAccessSetInfo NetAccessSetInfo +#define _NetAccessAdd NetAccessAdd + +#define _tmalloc malloc +#define _tfree free + +#define DosQueryProcAddr(handle, ord, name, funcptr) \ + DosGetProcAddr(handle, name, funcptr) +#define DosQueryCurrentDir DosQCurDir +#define DosQueryCurrentDisk DosQCurDisk + +#endif + + +static BOOL acl_init(void) +{ + static BOOL initialized, netapi_avail; + HMODULE netapi; + char buf[256]; + + if (initialized) + return netapi_avail; + + initialized = TRUE; + + if (DosLoadModule(buf, sizeof(buf), "NETAPI", &netapi)) + return FALSE; + + if (DosQueryProcAddr(netapi, 0, "NETACCESSGETINFO", (PFN *) &_NetAccessGetInfo) || + DosQueryProcAddr(netapi, 0, "NETACCESSSETINFO", (PFN *) &_NetAccessSetInfo) || + DosQueryProcAddr(netapi, 0, "NETACCESSADD", (PFN *) &_NetAccessAdd)) + return FALSE; + +#if defined(__WATCOMC__) && defined(__386__) + NetAccessGetInfo = (PVOID) (ULONG) (PVOID16) NetAccessGetInfo; + NetAccessSetInfo = (PVOID) (ULONG) (PVOID16) NetAccessSetInfo; + NetAccessAdd = (PVOID) (ULONG) (PVOID16) NetAccessAdd; +#endif + + if ((path = _tmalloc(CCHMAXPATH)) == NULL) + return FALSE; + if ((data = _tmalloc(ACL_BUFFERSIZE)) == NULL) + return FALSE; + if ((ai = _tmalloc(sizeof(ACCINFO))) == NULL) + return -1; + + netapi_avail = TRUE; + + return netapi_avail; +} + +static void acl_mkpath(char *buffer, const char *source) +{ + char *ptr; + static char cwd[CCHMAXPATH]; + static U_INT cwdlen; + U_INT cdrive; + ULONG drivemap; + + if (isalpha((int)source[0]) && source[1] == ':') + buffer[0] = 0; /* fully qualified names */ + else + { + if (cwd[0] == 0) + { + DosQueryCurrentDisk(&cdrive, &drivemap); + cwd[0] = (char)(cdrive + '@'); + cwd[1] = ':'; + cwd[2] = '\\'; + cwdlen = sizeof(cwd) - 3; + DosQueryCurrentDir(0, cwd + 3, &cwdlen); + cwdlen = strlen(cwd); + } + + if (source[0] == '/' || source[0] == '\\') + { + if (source[1] == '/' || source[1] == '\\') + buffer[0] = 0; /* UNC names */ + else + { + strncpy(buffer, cwd, 2); + buffer[2] = 0; + } + } + else + { + strcpy(buffer, cwd); + if (cwd[cwdlen - 1] != '\\' && cwd[cwdlen - 1] != '/') + strcat(buffer, "/"); + } + } + + strcat(buffer, source); + + for (ptr = buffer; *ptr; ptr++) + if (*ptr == '/') + *ptr = '\\'; + + if (ptr[-1] == '\\') + ptr[-1] = 0; + + strupr(buffer); +} + +static int acl_bin2text(char *data, char *text) +{ + ACCINFO *ai; + ACCLIST *al; + U_INT cnt, offs; + + ai = (ACCINFO *) data; + al = (ACCLIST *) (data + sizeof(ACCINFO)); + + offs = sprintf(text, "ACL1:%X,%d\n", + ai -> acc_attr, ai -> acc_count); + + for (cnt = 0; cnt < ai -> acc_count; cnt++) + offs += sprintf(text + offs, "%s,%X\n", + al[cnt].acl_ugname, al[cnt].acl_access); + + return strlen(text); +} + +int acl_get(char *server, const char *resource, char *buffer) +{ + USHORT datalen; + PSZ srv = NULL; + int rc; + + if (!acl_init()) + return -1; + + if (server) + srv = server; + + acl_mkpath(path, resource); + datalen = 0; + + rc = NetAccessGetInfo(srv, path, 1, data, ACL_BUFFERSIZE, &datalen); + + if (rc == 0) + acl_bin2text(data, buffer); + + return rc; +} + +static int acl_text2bin(char *data, char *text, char *path) +{ + ACCINFO *ai; + ACCLIST *al; + char *ptr, *ptr2; + U_INT cnt; + + ai = (ACCINFO *) data; + ai -> acc_resource_name = PTR16(path); + + if (sscanf(text, "ACL1:%hX,%hd", + &ai -> acc_attr, &ai -> acc_count) != 2) + return ERROR_INVALID_PARAMETER; + + al = (ACCLIST *) (data + sizeof(ACCINFO)); + ptr = strchr(text, '\n') + 1; + + for (cnt = 0; cnt < ai -> acc_count; cnt++) + { + ptr2 = strchr(ptr, ','); + strncpy(al[cnt].acl_ugname, ptr, ptr2 - ptr); + al[cnt].acl_ugname[ptr2 - ptr] = 0; + sscanf(ptr2 + 1, "%hx", &al[cnt].acl_access); + ptr = strchr(ptr, '\n') + 1; + } + + return sizeof(ACCINFO) + ai -> acc_count * sizeof(ACCLIST); +} + +int acl_set(char *server, const char *resource, char *buffer) +{ + USHORT datalen; + PSZ srv = NULL; + + if (!acl_init()) + return -1; + + if (server) + srv = server; + + acl_mkpath(path, resource); + + ai -> acc_resource_name = PTR16(path); + ai -> acc_attr = 0; + ai -> acc_count = 0; + + NetAccessAdd(srv, 1, ai, sizeof(ACCINFO)); + /* Ignore any errors, most probably because ACL already exists. */ + /* In any such case, try updating the existing ACL. */ + + datalen = acl_text2bin(data, buffer, path); + + return NetAccessSetInfo(srv, path, 1, data, datalen, 0); +} + +/* end of os2acl.c */ diff --git a/os2/os2acl.h b/os2/os2acl.h new file mode 100644 index 0000000..03bb8a2 --- /dev/null +++ b/os2/os2acl.h @@ -0,0 +1,34 @@ +/* + 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 +*/ +/* os2acl.h + * + * Author: Kai Uwe Rommel + * Created: Fri Mar 29 1996 + */ + +/* $Id: os2acl.h,v 1.1 1996/03/30 09:35:00 rommel Exp rommel $ */ + +/* + * $Log: os2acl.h,v $ + * Revision 1.1 1996/03/30 09:35:00 rommel + * Initial revision + * + */ + +#ifndef _OS2ACL_H +#define _OS2ACL_H + +#define ACL_BUFFERSIZE 4096 + +int acl_get(char *server, const char *resource, char *buffer); +int acl_set(char *server, const char *resource, char *buffer); + +#endif /* _OS2ACL_H */ + +/* end of os2acl.h */ diff --git a/os2/os2cfg.h b/os2/os2cfg.h new file mode 100644 index 0000000..b21932d --- /dev/null +++ b/os2/os2cfg.h @@ -0,0 +1,166 @@ +/* + Copyright (c) 1990-2008 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 +*/ +/*--------------------------------------------------------------------------- + OS/2 specific configuration section: + ---------------------------------------------------------------------------*/ + +#ifndef __os2cfg_h +#define __os2cfg_h + +#ifdef MSDOS +# include /* for REGS macro (TC) or _dos_setftime (MSC) */ +# ifdef __TURBOC__ /* includes Power C */ +# include /* for structure ftime */ +# ifndef __BORLANDC__ /* there appears to be a bug (?) in Borland's */ +# include /* MEM.H related to __STDC__ and far poin- */ +# endif /* ters. (dpk) [mem.h included for memcpy] */ +# endif +#endif /* MSDOS */ + +#ifdef __IBMC__ +# define S_IFMT 0xF000 +# define timezone _timezone /* (underscore names work with */ +# define tzset _tzset /* all versions of C Set) */ +# define PIPE_ERROR (errno == EERRSET || errno == EOS2ERR) +#endif /* __IBMC__ */ + +#ifdef __WATCOMC__ +# ifdef __386__ +# ifndef WATCOMC_386 +# define WATCOMC_386 +# endif +# define __32BIT__ +# undef far +# define far +# undef near +# define near + +/* Get asm routines to link properly without using "__cdecl": */ +# ifndef USE_ZLIB +# pragma aux crc32 "_*" parm caller [] value [eax] modify [eax] +# pragma aux get_crc_table "_*" parm caller [] value [eax] \ + modify [eax ecx edx] +# endif /* !USE_ZLIB */ +# else /* !__386__ */ +# ifndef USE_ZLIB +# pragma aux crc32 "_*" parm caller [] value [ax dx] \ + modify [ax cx dx bx] +# pragma aux get_crc_table "_*" parm caller [] value [ax] \ + modify [ax cx dx bx] +# endif /* !USE_ZLIB */ +# endif /* ?__386__ */ +#endif /* __WATCOMC__ */ + +#ifdef __EMX__ +# ifndef __32BIT__ +# define __32BIT__ +# endif +# define far +#endif + +#ifndef __32BIT__ +# define __16BIT__ +#endif + +#ifdef MSDOS +# undef MSDOS +#endif + +#if defined(M_I86CM) || defined(M_I86LM) +# define MED_MEM +#endif +#if (defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)) +# define MED_MEM +#endif +#ifdef __16BIT__ +# ifndef MED_MEM +# define SMALL_MEM +# endif +#endif + +#ifdef __16BIT__ +# if defined(MSC) || defined(__WATCOMC__) +# include +# define nearmalloc _nmalloc +# define nearfree _nfree +# endif +# if defined(__TURBOC__) && defined(DYNALLOC_CRCTAB) +# if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__) +# undef DYNALLOC_CRCTAB +# endif +# endif +# ifndef nearmalloc +# define nearmalloc malloc +# define nearfree free +# endif +# ifdef USE_DEFLATE64 +# if (defined(M_I86TM) || defined(M_I86SM) || defined(M_I86MM)) +# error Deflate64(tm) requires compact or large memory model +# endif +# if (defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)) +# error Deflate64(tm) requires compact or large memory model +# endif + /* the 64k history buffer for Deflate64 must be allocated specially */ +# define MALLOC_WORK +# define MY_ZCALLOC +# endif +#endif + +/* TIMESTAMP is now supported on OS/2, so enable it by default */ +#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) +# define TIMESTAMP +#endif + +/* check that TZ environment variable is defined before using UTC times */ +#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ)) +# define IZ_CHECK_TZ +#endif + +#ifndef RESTORE_ACL +# define RESTORE_ACL +#endif + +#ifndef OS2_EAS +# define OS2_EAS /* for -l and -v listings (list.c) */ +#endif + +#ifdef isupper +# undef isupper +#endif +#ifdef tolower +# undef tolower +#endif +#define isupper(x) IsUpperNLS((unsigned char)(x)) +#define tolower(x) ToLowerNLS((unsigned char)(x)) +#ifndef NO_STRNICMP /* use UnZip's zstrnicmp(), because some compilers */ +# define NO_STRNICMP /* don't provide a NLS-aware strnicmp() function */ +#endif + +#define USETHREADID + +/* handlers for OEM <--> ANSI string conversions */ +#ifndef _OS2_ISO_ANSI + /* use home-brewed conversion functions; internal charset is OEM */ +# ifdef CRTL_CP_IS_ISO +# undef CRTL_CP_IS_ISO +# endif +# ifndef CRTL_CP_IS_OEM +# define CRTL_CP_IS_OEM +# endif +#endif + +/* screen size detection */ +#define SCREENWIDTH 80 +#define SCREENSIZE(scrrows, scrcols) screensize(scrrows, scrcols) +int screensize(int *tt_rows, int *tt_cols); + +/* on the OS/2 console screen, line-wraps are always enabled */ +#define SCREENLWRAP 1 + +#endif /* !__os2cfg_h */ diff --git a/os2/os2data.h b/os2/os2data.h new file mode 100644 index 0000000..0d36fbb --- /dev/null +++ b/os2/os2data.h @@ -0,0 +1,149 @@ +/* + 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 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 +*/ +/*--------------------------------------------------------------------------- + + os2data.h + + OS/2-specific structures and data to be included in the global data struc- + ture. + + ---------------------------------------------------------------------------*/ + + +#define MAXNAMLEN 256 +#define MAXPATHLEN 256 +#define MAXLEN 256 /* temporary buffer length */ +#define IBUF_LEN 4096 /* input buffer length */ + +#define INCL_NOPM +#define INCL_VIO +#define INCL_DOSNLS +#define INCL_DOSPROCESS +#define INCL_DOSDEVICES +#define INCL_DOSDEVIOCTL +#define INCL_DOSERRORS +#define INCL_DOSMISC + +#if (defined(OS2DLL) && !defined(DLL)) +# undef OS2DLL +#endif + +#ifdef OS2DLL +# define INCL_REXXSAA +# include +#endif + +#include + + +struct direct +{ + ino_t d_ino; /* a bit of a farce */ + int d_reclen; /* more farce */ + int d_namlen; /* length of d_name */ + char d_name[MAXNAMLEN + 1]; /* null terminated */ + /* nonstandard fields */ + long d_size; /* size in bytes */ + unsigned d_mode; /* MS-DOS or OS/2 file attributes */ + unsigned d_time; + unsigned d_date; +}; + +/* The fields d_size and d_mode are extensions by me (Kai Uwe Rommel). The + * find_first and find_next calls deliver these data without any extra cost. + * If these data are needed, the fields save a lot of extra calls to stat() + * (each stat() again performs a find_first call !). + */ + +struct _dircontents +{ + char *_d_entry; + long _d_size; + unsigned _d_mode, _d_time, _d_date; + struct _dircontents *_d_next; +}; + +typedef struct _dirdesc +{ + int dd_id; /* uniquely identify each open directory */ + long dd_loc; /* where we are in directory entry is this */ + struct _dircontents *dd_contents; /* pointer to contents of dir */ + struct _dircontents *dd_cp; /* pointer to current position */ +} +DIR; + + +struct os2Global { + +#ifndef SFX + HDIR hdir; +#ifdef __32BIT__ + ULONG count; + FILEFINDBUF3 find; +#else + USHORT count; + FILEFINDBUF find; +#endif +#endif /* !SFX */ + + int created_dir; /* used by mapname(), checkdir() */ + int renamed_fullpath; /* ditto */ + int fnlen; /* ditto */ +#ifdef __32BIT__ + ULONG nLabelDrive; /* ditto */ +#else + USHORT nLabelDrive; +#endif + int longnameEA; /* checkdir(), close_outfile() */ + char *lastpathcomp; /* ditto */ + + struct direct dp; + int lower; + USHORT nLastDrive, nResult; + + DIR *wild_dir; + ZCONST char *wildname; + char *dirname, matchname[FILNAMSIZ]; + int notfirstcall, have_dirname, dirnamelen; + + int rootlen; /* length of rootpath */ + char *rootpath; /* user's "extract-to" directory */ + char *buildpathHPFS; /* full path (so far) to extracted file, */ + char *buildpathFAT; /* both HPFS/EA (main) and FAT versions */ + char *endHPFS; /* corresponding pointers to end of */ + char *endFAT; /* buildpath ('\0') */ + +#ifdef OS2DLL + char buffer[IBUF_LEN]; + char output_var[MAXLEN]; + char getvar_buf[MAXLEN]; + int getvar_len; + + int output_idx; + int stem_len; + int putchar_idx; + int rexx_error; + char *rexx_mes; + + SHVBLOCK request; +#endif +}; + + +#define SYSTEM_SPECIFIC_GLOBALS struct os2Global os2; +#define SYSTEM_SPECIFIC_CTOR os2GlobalsCtor + +#ifdef OS2DLL +# ifdef API_DOC +# define SYSTEM_API_BRIEF REXXBrief +# define SYSTEM_API_DETAILS REXXDetails + extern char *REXXBrief; + extern APIDocStruct REXXDetails[]; +# endif +#endif diff --git a/os2/rexxapi.c b/os2/rexxapi.c new file mode 100644 index 0000000..2404090 --- /dev/null +++ b/os2/rexxapi.c @@ -0,0 +1,894 @@ +/* + Copyright (c) 1990-2004 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 +*/ +/********************************************************************** +* REXXAPI.C * +* * +* This program adds a ZIP engine directly to the REXX language. * +* The functions are: * +* UZDropFuncs -- Makes all functions in this package * +* unknown to REXX. * +* UZLoadFuncs -- Makes all functions in this package * +* known to REXX so REXX programs may * +* call them. * +* UZFileTree -- Searches for files matching a given * +* filespec, including files in * +* subdirectories. * +* UZUnZip -- Unzip command-line entry point. * +* This is functionally equivalent to * +* using Unzip as an external program. * +* UZUnZipToVar -- Unzip one file to a variable * +* UZUnZipToStem -- Unzip files to a variable array * +* UZVer -- Returns the Unzip version number * +* * +**********************************************************************/ +/* Include files */ + +#ifdef OS2DLL + +#define INCL_DOS +#define INCL_DOSMEMMGR +#include +#include +#include +#include + +#define UNZIP_INTERNAL +#include "../unzip.h" +#include "../unzvers.h" + + +/*********************************************************************/ +/* Various definitions used by various functions. */ +/*********************************************************************/ + +RexxFunctionHandler UZDropFuncs; +RexxFunctionHandler UZLoadFuncs; +RexxFunctionHandler UZFileTree; +RexxFunctionHandler UZUnZip; +RexxFunctionHandler UZUnZipToVar; +RexxFunctionHandler UZUnZipToStem; +RexxFunctionHandler UZVer; +RexxFunctionHandler UZAPIVer; + + +int SetOutputVar(__GPRO__ const char *name); +int SetOutputVarStem(__GPRO__ const char *name); +int SetOutputVarLength(__GPRO); +int WriteToVariable(__GPRO__ const char *name, char *buffer, int len); +int PrintToSubVariable(__GPRO__ int idx, const char *format,...); +int PrintToVariable(__GPRO__ const char *name, const char *format,...); +int _PrintToVariable(__GPRO__ const char *name, const char *format, va_list arg_ptr); +int TextSetNext(__GPRO__ char *format, int len, int all); + +#define EZRXSTRING(r,p) {(r).strptr=(PCH)p;(r).strlength=(ULONG)strlen((r).strptr);} + + +/*********************************************************************/ +/* RxFncTable */ +/* Array of names of the UNZIPAPI functions. */ +/* This list is used for registration and deregistration. */ +/*********************************************************************/ + +static PSZ RxFncTable[] = + { + "UZDropFuncs", + "UZLoadFuncs", + "UZFileSearch", + "UZFileTree", + "UZUnZip", + "UZUnZipToVar", + "UZUnZipToStem", + "UZVer", + }; + +/*********************************************************************/ +/* Numeric Error Return Strings */ +/*********************************************************************/ + +#define NO_UTIL_ERROR "0" /* No error whatsoever */ +#define ERROR_NOMEM "2" /* Insufficient memory */ + +/*********************************************************************/ +/* Numeric Return calls */ +/*********************************************************************/ + +#define INVALID_ROUTINE 40 /* Raise Rexx error */ +#define VALID_ROUTINE 0 /* Successful completion */ + +/*********************************************************************/ +/* Some useful macros */ +/*********************************************************************/ + +#define BUILDRXSTRING(t, s) { \ + strcpy((t)->strptr,(s));\ + (t)->strlength = strlen((s)); \ +} + + +/*********************************************************************/ +/**************** UNZIPAPI Supporting Functions ********************/ +/**************** UNZIPAPI Supporting Functions ********************/ +/**************** UNZIPAPI Supporting Functions ********************/ +/*********************************************************************/ + + +int RexxReturn(__GPRO__ int nodefault, RXSTRING *retstr) +{ + int ret = G.os2.rexx_error; + if (G.filenotfound) + G.os2.rexx_mes = "file not found"; + if (*G.os2.rexx_mes != '0') { + if (retstr->strlength > 255) { + DosFreeMem(retstr->strptr); + retstr->strptr = NULL; + } + } else if (nodefault) + goto noBuild; + BUILDRXSTRING(retstr, G.os2.rexx_mes); + noBuild: + DESTROYGLOBALS(); + return ret; +} + +/* Get a variable from REXX, return 0 if OK */ +int GetVariable(__GPRO__ const char *name) +{ + G.os2.request.shvnext = NULL; + EZRXSTRING(G.os2.request.shvname, name); + G.os2.request.shvnamelen = G.os2.request.shvname.strlength; + G.os2.request.shvvalue.strptr = G.os2.buffer; + G.os2.request.shvvalue.strlength = IBUF_LEN; + G.os2.request.shvvaluelen = IBUF_LEN; + G.os2.request.shvcode = RXSHV_SYFET; + G.os2.request.shvret = 0; + switch (RexxVariablePool(&G.os2.request)) { + case RXSHV_MEMFL: + G.os2.rexx_mes = ERROR_NOMEM; + break; + case RXSHV_BADN: + case RXSHV_NEWV: + G.os2.request.shvvaluelen = 0; + case RXSHV_OK: + *(G.os2.buffer+G.os2.request.shvvaluelen) = 0; + return G.os2.request.shvvaluelen; + } + return 0; +} + + +/* Get REXX compound variable */ +/* Stem must exist in G.os2.getvar_buf w/ length in G.os2.getvar_len */ +int GetVariableIndex(__GPRO__ int index) +{ + sprintf(G.os2.getvar_buf+G.os2.getvar_len,"%d",index); + return GetVariable(__G__ G.os2.getvar_buf); +} + + +/* Transfer REXX array to standard C string array */ +/* Returns number of elements */ +/* User is responsible for calling KillStringArray */ + +int CompoundToStringArray(__GPRO__ char ***pointer, const char *name) +{ + int count; + int total; + char **trav; + + G.os2.getvar_len = strlen(name); + memcpy(G.os2.getvar_buf,name,G.os2.getvar_len+1); + if (*(G.os2.getvar_buf+G.os2.getvar_len-1) != '.') + *(G.os2.getvar_buf+G.os2.getvar_len++) = '.', *(G.os2.getvar_buf+G.os2.getvar_len) = 0; + + if (GetVariableIndex(__G__ 0)) + return 0; + + total = atoi(G.os2.buffer); + *pointer = (char **)malloc((total+1)<<2); + trav = *pointer; + for (count = 1; count <= total; count++) { + GetVariableIndex(__G__ count); + trav[count-1] = (char *)malloc(strlen(G.os2.buffer)+1); + strcpy(trav[count-1],G.os2.buffer); + } + trav[count-1] = NULL; + return total; +} + + +/* Kill string array created by CompoundToStringArray */ + +void KillStringArray(char **pointer) +{ + char **trav=pointer; + while (*trav != NULL) { + free(*trav); + trav++; + } + free(pointer); +} + + +/************************************************************************* +* Function: UZDropFuncs * +* * +* Syntax: call UZDropFuncs * +* * +* Return: NO_UTIL_ERROR - Successful. * +*************************************************************************/ + +ULONG UZDropFuncs(CHAR *name, ULONG numargs, RXSTRING args[], + CHAR *queuename, RXSTRING *retstr) +{ + INT entries; /* Num of entries */ + INT j; /* Counter */ + + if (numargs != 0) /* no arguments for this */ + return INVALID_ROUTINE; /* raise an error */ + + retstr->strlength = 0; /* return a null string result*/ + + entries = sizeof(RxFncTable)/sizeof(PSZ); + + for (j = 0; j < entries; j++) + RexxDeregisterFunction(RxFncTable[j]); + + return VALID_ROUTINE; /* no error on call */ +} + + +/************************************************************************* +* Function: UZFileTree * +* * +* Syntax: call UZFileTree zipfile, stem[, include-filespec] * +* [, exclude-filespec][, options] * +* * +* Params: zipfile - Name of zip file to search. * +* stem - Name of stem var to store results in. * +* include - Filespec to search for (may include * and ?). * +* exclude - Filespec to exclude (may include * and ?). * +* options - Either of the following: * +* 'F' - Give file statistics. * +* Length Date Time Name * +* 'Z' - Give zip statistics, too. * +* Length Method Size Ratio Date Time CRC-32 Name* +* Default is to return only filenames * +* * +* Return: NO_UTIL_ERROR - Successful. * +* ERROR_NOMEM - Out of memory. * +*************************************************************************/ + +ULONG UZFileTree(CHAR *name, ULONG numargs, RXSTRING args[], + CHAR *queuename, RXSTRING *retstr) +{ + /* validate arguments */ + char *incname[2]; + char *excname[2]; + CONSTRUCTGLOBALS(); + + if (numargs < 2 || numargs > 5 || + !RXVALIDSTRING(args[0]) || + !RXVALIDSTRING(args[1]) || + args[0].strlength > 255) { + DESTROYGLOBALS(); + return INVALID_ROUTINE; /* Invalid call to routine */ + } + /* initialize data area */ + SetOutputVarStem(__G__ args[1].strptr); + G.wildzipfn = args[0].strptr; + G.process_all_files = TRUE; + + uO.lflag = 1; + uO.zipinfo_mode = TRUE; + uO.C_flag = 1; + G.extract_flag = FALSE; + uO.qflag = 2; + + if (numargs >= 3 && /* check third option */ + !RXNULLSTRING(args[2]) && + args[2].strlength > 0) { /* a zero length string isn't */ + if (!(G.filespecs = CompoundToStringArray(__G__ &G.pfnames,args[2].strptr))) { + G.pfnames = incname; + incname[0] = args[2].strptr; + incname[1] = NULL; + G.filespecs = 1; + } + G.process_all_files = FALSE; + } + + if (numargs >= 4 && /* check third option */ + !RXNULLSTRING(args[3]) && + args[3].strlength > 0) { /* a zero length string isn't */ + if (!(G.xfilespecs = CompoundToStringArray(__G__ &G.pxnames,args[3].strptr))) { + G.pxnames = excname; + excname[0] = args[3].strptr; + excname[1] = NULL; + G.xfilespecs = 1; + } + G.process_all_files = FALSE; + } + + if (numargs == 5 && /* check third option */ + !RXNULLSTRING(args[4]) && + args[4].strlength > 0) { /* a zero length string isn't */ + int first = *args[4].strptr & 0x5f; + + if (first == 'Z') + uO.vflag = 2, uO.lflag = 0, uO.zipinfo_mode = FALSE; + else if (first == 'F') + uO.vflag = 1, uO.lflag = 0, uO.zipinfo_mode = FALSE; + } + + process_zipfiles(__G); + SetOutputVarLength(__G); + if (G.filespecs > 0 && G.pfnames != incname) + KillStringArray(G.pfnames); + if (G.xfilespecs > 0 && G.pxnames != excname) + KillStringArray(G.pxnames); + return RexxReturn(__G__ 0,retstr); /* no error on call */ +} + + +/************************************************************************* +* Function: UZUnZipToVar * +* * +* Syntax: call UZUnZipToVar zipfile, filespec [, stem] * +* * +* Params: zipfile - Name of zip file to search. * +* filespec - File to extract * +* stem - If you specify a stem variable, the file will be * +* extracted to the variable, one line per index * +* In this case, 0 will be returned * +* * +* Return: Extracted file * +* ERROR_NOMEM - Out of memory. * +*************************************************************************/ + +ULONG UZUnZipToVar(CHAR *name, ULONG numargs, RXSTRING args[], + CHAR *queuename, RXSTRING *retstr) +{ + CONSTRUCTGLOBALS(); + UzpBuffer *ub = (UzpBuffer *)retstr; + /* validate arguments */ + if (numargs < 2 || numargs > 3 || + !RXVALIDSTRING(args[0]) || + !RXVALIDSTRING(args[1]) || + args[0].strlength == 0 || + args[1].strlength == 0) { + DESTROYGLOBALS(); + return INVALID_ROUTINE; /* Invalid call to routine */ + } + + uO.C_flag = 1; + G.redirect_data=1; + if (numargs == 3) { + if (!RXVALIDSTRING(args[2]) || + RXNULLSTRING(args[1]) || + args[2].strlength == 0) { + DESTROYGLOBALS(); + return INVALID_ROUTINE; /* Invalid call to routine */ + } + SetOutputVarStem(__G__ args[2].strptr); + G.redirect_text = 0; + G.redirect_data++; + } + unzipToMemory(__G__ args[0].strptr, args[1].strptr, + G.redirect_data==1 ? ub : NULL); + return RexxReturn(__G__ G.redirect_data==1,retstr); +} + + +/************************************************************************* +* Function: UZUnZipToStem * +* * +* Syntax: call UZUnZipToStem zipfile, stem[, include-filespec] * +* [, exclude-filespec][, mode] * +* * +* Params: zipfile - Name of zip file to search. * +* stem - Name of stem var to store files in. * +* include - Filespec to search for (may include * and ?). * +* exclude - Filespec to exclude (may include * and ?). * +* mode - Specifies 'F'lat or 'T'ree mode. Umm, this is * +* hard to explain so I'll give an example, too. * +* Assuming a file unzip.zip containing: * +* unzip.c * +* unshrink.c * +* extract.c * +* os2/makefile.os2 * +* os2/os2.c * +* os2/dll/dll.def * +* os2/dll/unzipapi.c * +* * +* -- In flat mode, each file is stored in * +* stem.fullname i.e. stem."os2/dll/unzipapi.c" * +* A list of files is created in stem. * +* * +* Flat mode returns: * +* stem.0 = 7 * +* stem.1 = unzip.c * +* stem.2 = unshrink.c * +* stem.3 = extract.c * +* stem.4 = os2/makefile.os2 * +* stem.5 = os2/os2.c * +* stem.6 = os2/dll/dll.def * +* stem.7 = os2/dll/unzipapi.c * +* * +* And the following contain the contents of the * +* various programs: * +* stem.unzip.c * +* stem.unshrink.c * +* stem.extract.c * +* stem.os2/makefile.os2 * +* stem.os2/os2.c * +* stem.os2/dll/dll.def * +* stem.os2/dll/unzipapi.c * +* * +* -- In tree mode, slashes are converted to periods* +* in the pathname thus the above file would have* +* been stored in stem.os2.dll.unzipapi.c * +* The index would then be stored in stem.OS2. * +* DLL.. * +* * +* NOTE: All path names are converted to uppercase * +* * +* Tree mode returns: * +* stem.0 = 4 * +* stem.1 = unzip.c * +* stem.2 = unshrink.c * +* stem.3 = extract.c * +* stem.4 = OS2/ * +* * +* stem.OS2.0 = 3 * +* stem.OS2.1 = makefile.os2 * +* stem.OS2.2 = os2.c * +* stem.OS2.3 = DLL/ * +* * +* stem.OS2.DLL.0 = 2 * +* stem.OS2.DLL.1 = def * +* stem.OS2.DLL.2 = unzipapi.c * +* * +* And the following contain the contents of the * +* various programs: * +* stem.unzip.c * +* stem.unshrink.c * +* stem.extract.c * +* stem.OS2.makefile.os2 * +* stem.OS2.os2.c * +* stem.OS2.DLL.dll.def * +* stem.OS2.DLL.unzipapi.c * +* * +* * +* Return: NO_UTIL_ERROR - Successful. * +* ERROR_NOMEM - Out of memory. * +*************************************************************************/ + +ULONG UZUnZipToStem(CHAR *name, ULONG numargs, RXSTRING args[], + CHAR *queuename, RXSTRING *retstr) +{ + char *incname[2]; + char *excname[2]; + CONSTRUCTGLOBALS(); + /* validate arguments */ + if (numargs < 2 || numargs > 5 || + !RXVALIDSTRING(args[0]) || + !RXVALIDSTRING(args[1]) || + args[0].strlength > 255) { + DESTROYGLOBALS(); + return INVALID_ROUTINE; /* Invalid call to routine */ + } + /* initialize data area */ + G.wildzipfn = args[0].strptr; + G.process_all_files = TRUE; + + uO.C_flag = 1; + G.extract_flag = TRUE; + SetOutputVarStem(__G__ args[1].strptr); + G.redirect_data = 3; + G.redirect_text = 0; + + if (numargs >= 3 && /* check third option */ + !RXNULLSTRING(args[2]) && + args[2].strlength > 0) { /* a zero length string isn't */ + if (!(G.filespecs = CompoundToStringArray(__G__ &G.pfnames,args[2].strptr))) { + G.pfnames = incname; + incname[0] = args[2].strptr; + incname[1] = NULL; + G.filespecs = 1; + } + G.process_all_files = FALSE; + } + + if (numargs >= 4 && /* check third option */ + !RXNULLSTRING(args[3]) && + args[3].strlength > 0) { /* a zero length string isn't */ + if (!(G.xfilespecs = CompoundToStringArray(__G__ &G.pxnames,args[3].strptr))) { + G.pxnames = excname; + excname[0] = args[3].strptr; + excname[1] = NULL; + G.xfilespecs = 1; + } + G.process_all_files = FALSE; + } + + if (numargs == 5 && /* check third option */ + !RXNULLSTRING(args[4]) && + (*args[4].strptr & 0x5f) == 'T') { + G.redirect_data++; + G.os2.request.shvnext = NULL; + EZRXSTRING(G.os2.request.shvname, args[4].strptr); + G.os2.request.shvnamelen = G.os2.request.shvname.strlength; + G.os2.request.shvcode = RXSHV_SYDRO; + G.os2.request.shvret = 0; + RexxVariablePool(&G.os2.request); + } + + + uO.qflag = 2; + + process_zipfiles(__G); + if (G.filespecs > 0 && G.pfnames != incname) + KillStringArray(G.pfnames); + if (G.xfilespecs > 0 && G.pxnames != excname) + KillStringArray(G.pxnames); + if (G.redirect_data == 3) + SetOutputVarLength(__G); + return RexxReturn(__G__ 0,retstr); /* no error on call */ +} + + +/************************************************************************* +* Function: UZLoadFuncs * +* * +* Syntax: call UZLoadFuncs [option] * +* * +* Params: none * +* * +* Return: null string * +*************************************************************************/ + +ULONG UZLoadFuncs(CHAR *name, ULONG numargs, RXSTRING args[], + CHAR *queuename, RXSTRING *retstr) +{ + INT entries; /* Num of entries */ + INT j; /* Counter */ + + retstr->strlength = 0; /* set return value */ + /* check arguments */ + if (numargs > 0) + return INVALID_ROUTINE; + + entries = sizeof(RxFncTable)/sizeof(PSZ); + + for (j = 0; j < entries; j++) { + RexxRegisterFunctionDll(RxFncTable[j], + "UNZIP32", RxFncTable[j]); + } + return VALID_ROUTINE; +} + + + +/************************************************************************* +* Function: UZVer * +* * +* Syntax: call UZVer * +* * +* Return: Version of Unzip * +*************************************************************************/ + +ULONG UZVer(CHAR *name, ULONG numargs, RXSTRING args[], + CHAR *queuename, RXSTRING *retstr) +{ + if (numargs > 1) /* validate arg count */ + return INVALID_ROUTINE; + + if (numargs == 0 || (*args[0].strptr & 0x5f) != 'L') + /* strcpy( retstr->strptr, UZ_VERNUM ); "5.13a BETA" */ + sprintf( retstr->strptr, "%d.%d%d%s", UZ_MAJORVER, UZ_MINORVER, + UZ_PATCHLEVEL, UZ_BETALEVEL ); + else + /* strcpy( retstr->strptr, UZ_VERSION ); UZ_VERNUM" of 26 Sep 94" */ + sprintf( retstr->strptr, "%d.%d%d%s of %s", UZ_MAJORVER, UZ_MINORVER, + UZ_PATCHLEVEL, UZ_BETALEVEL, UZ_VERSION_DATE ); + retstr->strlength = strlen(retstr->strptr); + return VALID_ROUTINE; +} + + +/************************************************************************* +* Function: UZUnZip * +* * +* Syntax: call UZUnZip * +* * +* Return: Unzip return code * +*************************************************************************/ + +ULONG UZUnZip(CHAR *name, ULONG numargs, RXSTRING args[], + CHAR *queuename, RXSTRING *retstr) +{ + char *argv[30]; + char *scan; + int argc=0; + int idx; + CONSTRUCTGLOBALS(); + + if (numargs < 1 || numargs > 2 || + args[0].strlength > 255) { + DESTROYGLOBALS(); + return INVALID_ROUTINE; /* Invalid call to routine */ + } + /* initialize data area */ + if (numargs == 2) + SetOutputVarStem(__G__ args[1].strptr); + + scan = args[0].strptr; + argv[argc++] = ""; /* D:\\SOURCECODE\\UNZIP51S\\UNZIP.COM"; */ + while (*scan == ' ') + scan++; + argv[argc++] = scan; + while ( (scan = strchr(scan,' ')) != NULL) { + *scan++ = 0; + while (*scan == ' ') + scan++; + argv[argc++] = scan; + } + if (*argv[argc-1] == 0) + argc--; + argv[argc] = 0; + + /* GRR: should resetMainFlags() be called in here somewhere? */ + + sprintf(retstr->strptr, "%d", unzip(__G__ argc, argv)); /* a.k.a. MAIN() */ + if (numargs == 2) + SetOutputVarLength(__G); + retstr->strlength = strlen(retstr->strptr); + return RexxReturn(__G__ 1,retstr); +} + +int varmessage(__GPRO__ ZCONST uch *buf, ulg size) +{ + if (size > 0) + memcpy(G.os2.buffer+G.os2.putchar_idx,buf,size); + G.os2.putchar_idx = TextSetNext(__G__ G.os2.buffer, size+G.os2.putchar_idx,0); + return 0; +} + +int varputchar(__GPRO__ int c) +{ + G.os2.buffer[G.os2.putchar_idx++] = c; + if (c == '\n') { + G.os2.buffer[G.os2.putchar_idx] = 0; + if (G.os2.output_var[0]) + G.os2.putchar_idx = TextSetNext(__G__ G.os2.buffer, G.os2.putchar_idx,0); + else { + G.os2.buffer[--G.os2.putchar_idx] = 0; + puts(G.os2.buffer); + G.os2.putchar_idx = 0; + } + } + return 1; +} + + + +int SetOutputVarStem(__GPRO__ const char *name) +{ + int len=strlen(name); + G.redirect_text=1; + G.os2.output_idx = 0; + strcpy(G.os2.output_var, name); + if (len) { + strupr(G.os2.output_var); /* uppercase the name */ + if (*(G.os2.output_var+len-1) != '.') { + *(G.os2.output_var+len) = '.'; + len++; + *(G.os2.output_var+len) = 0; + } + WriteToVariable(__G__ G.os2.output_var,"",0); + } + G.os2.stem_len = len; + return G.os2.stem_len; +} + +int SetOutputVar(__GPRO__ const char *name) +{ + int len=strlen(name); + G.redirect_text=1; + G.os2.output_idx = 0; + strcpy(G.os2.output_var, name); + strupr(G.os2.output_var); /* uppercase the name */ + if (*(name+len-1) == '.') + G.os2.stem_len = len; + else + G.os2.stem_len = 0; + return G.os2.stem_len; +} + +int SetOutputVarLength(__GPRO) +{ + if (G.os2.stem_len > 0) { + if (G.os2.putchar_idx) + TextSetNext(__G__ G.os2.buffer,G.os2.putchar_idx,1); + return PrintToSubVariable(__G__ 0,"%d",G.os2.output_idx); + } + return 0; +} + +int PrintToVariable(__GPRO__ const char *name, const char *format,...) +{ + va_list arg_ptr; + int ret; + + va_start(arg_ptr, format); + ret = _PrintToVariable(__G__ name, format, arg_ptr); + va_end(arg_ptr); + return ret; +} + +int WriteToVariable(__GPRO__ const char *name, char *buffer, int len) +{ + G.os2.request.shvnext = NULL; + EZRXSTRING(G.os2.request.shvname, name); + G.os2.request.shvnamelen = G.os2.request.shvname.strlength; + G.os2.request.shvvalue.strptr = buffer; + G.os2.request.shvvalue.strlength = len; + G.os2.request.shvvaluelen = len; + G.os2.request.shvcode = RXSHV_SET; + G.os2.request.shvret = 0; + switch (RexxVariablePool(&G.os2.request)) { + case RXSHV_BADN: + G.os2.rexx_error = INVALID_ROUTINE; + break; + case RXSHV_MEMFL: + G.os2.rexx_mes = ERROR_NOMEM; + break; + case RXSHV_OK: + return 0; + } + return INVALID_ROUTINE; /* error on non-zero */ +} + +int _PrintToVariable(__GPRO__ const char *name, const char *format, va_list arg_ptr) +{ + int ret = vsprintf(G.os2.buffer, format, arg_ptr); + WriteToVariable(__G__ name, G.os2.buffer, strlen(G.os2.buffer)); + return ret; +} + +int PrintToSubVariable(__GPRO__ int idx, const char *format, ...) +{ + va_list arg_ptr; + int ret; + + if (G.os2.stem_len == 0) + return INVALID_ROUTINE; /* error on non-zero */ + sprintf(G.os2.output_var+G.os2.stem_len,"%d",idx); + + va_start(arg_ptr, format); + ret = _PrintToVariable(__G__ G.os2.output_var, format, arg_ptr); + va_end(arg_ptr); + return ret; +} + + +int WriteToNextVariable(__GPRO__ char *buffer, int len) +{ + if (G.os2.stem_len > 0) { + G.os2.output_idx++; + sprintf(G.os2.output_var+G.os2.stem_len,"%d",G.os2.output_idx); + } + return WriteToVariable(__G__ G.os2.output_var, buffer, len); +} + + +int TextSetNext(__GPRO__ char *buffer, int len, int all) +{ + char *scan = buffer, *next, *base=buffer; + int remaining=len; + int ret; + + while ((next = strchr(scan,'\n')) != NULL && remaining > 0) { + if (next > scan && *(next-1) == 0xd) + *(next-1) = 0; + else + *next = 0; + if (WriteToNextVariable(__G__ scan,strlen(scan))) + return 0; + next++; + remaining -= (next-scan); + scan = next; + } + if (remaining > 0) + if (all) { + *(scan+remaining) = 0; + WriteToNextVariable(__G__ scan,remaining); + } else { + memcpy(buffer,scan,remaining); + return remaining; + } + + return 0; +} + +int finish_REXX_redirect(__GPRO) +{ + char *scan, *ptr; + int idx=0, first=1, offset; + + if (!G.redirect_size) + return 0; + switch(G.redirect_data) { + case 1: + break; + case 2: + TextSetNext(__G__ G.redirect_buffer, G.redirect_size, 1); + SetOutputVarLength(__G); + DosFreeMem(G.redirect_buffer); + G.redirect_buffer = NULL; + G.redirect_size = 0; + break; + case 3: + WriteToNextVariable(__G__ G.filename, strlen(G.filename)); + strcpy(G.os2.output_var+G.os2.stem_len, G.filename); + WriteToVariable(__G__ G.os2.output_var, G.redirect_buffer, G.redirect_size); + DosFreeMem(G.redirect_buffer); + G.redirect_buffer = NULL; + G.redirect_size = 0; + break; + case 4: + if ((scan = strrchr(G.filename,'/')) != NULL) { + idx = *scan; + *scan = 0; + strupr(G.filename); + *scan = idx; + } + scan = G.os2.output_var+G.os2.stem_len; + strcpy(scan,G.filename); + while ((scan = strchr(scan,'/')) != NULL) + *scan = '.'; + WriteToVariable(__G__ G.os2.output_var, G.redirect_buffer, G.redirect_size); + DosFreeMem(G.redirect_buffer); + G.redirect_buffer = NULL; + G.redirect_size = 0; + strcpy(G.os2.getvar_buf, G.os2.output_var); + do { + if ((scan = strrchr(G.filename,'/')) == NULL) + offset = 0; + else + offset = scan-G.filename+1; + if (first || !GetVariable(__G__ G.os2.output_var)) { + ptr = G.os2.getvar_buf+offset+G.os2.stem_len; + *ptr = '0'; + *(ptr+1) = 0; + if (!GetVariable(__G__ G.os2.getvar_buf)) + idx = 1; + else + idx = atoi(G.os2.buffer)+1; + PrintToVariable(__G__ G.os2.getvar_buf,"%d",idx); + sprintf(ptr,"%d",idx); + if (!first) { + PrintToVariable(__G__ G.os2.output_var,"%d",idx); + idx = strlen(G.filename); + *(G.filename+idx) = '/'; + *(G.filename+idx+1) = 0; + } + WriteToVariable(__G__ G.os2.getvar_buf,G.filename+offset,strlen(G.filename+offset)); + first=0; + } + if (offset) { + *(G.os2.output_var+G.os2.stem_len+offset-1) = 0; + *scan = 0; + } + } while (offset); + break; + } + return 0; +} + +#endif /* OS2DLL */ diff --git a/os2/rexxapi.def b/os2/rexxapi.def new file mode 100644 index 0000000..813964a --- /dev/null +++ b/os2/rexxapi.def @@ -0,0 +1,18 @@ +LIBRARY UNZIP32 INITINSTANCE LONGNAMES +PROTMODE +DESCRIPTION 'Info-ZIP UnZip API - Copyright Scott Maxwell 1994, Info-ZIP 1995-1997' +DATA MULTIPLE NONSHARED +EXPORTS + UzpVersion @1 + UzpUnzipToMemory @2 + UzpFileTree @3 + UzpMain @4 + UzpAltMain @5 + UzpVersion2 @6 + UZDROPFUNCS = UZDropFuncs @2000 + UZLOADFUNCS = UZLoadFuncs @2001 + UZFILETREE = UZFileTree @2002 + UZUNZIPTOVAR = UZUnZipToVar @2003 + UZUNZIPTOSTEM = UZUnZipToStem @2004 + UZVER = UZVer @2005 + UZUNZIP = UZUnZip @2007 diff --git a/os2/rexxhelp.c b/os2/rexxhelp.c new file mode 100644 index 0000000..19c2222 --- /dev/null +++ b/os2/rexxhelp.c @@ -0,0 +1,186 @@ +/* + 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 +*/ +/* rexxhelp.c */ + +#if defined(API_DOC) && defined(OS2DLL) + +#define UNZIP_INTERNAL +#include "../unzip.h" +#include "../unzvers.h" + +APIDocStruct REXXDetails[] = { + { "UZDROPFUNCS" , "UZDropFuncs" , + "call UZDropFuncs", + "Use this function to drop all the loaded UnZip functions.\n" +"\t\tOnce this function is processed by a REXX program, the\n" +"\t\tUnZip functions are not accessible in any OS/2 sessions.\n" }, + + { "UZLOADFUNCS" , "UZLoadFuncs" , + "call UZLoadFuncs", + "Use this function to make all of the UnZip functions\n" +" in this package available to all OS/2 sessions.\n\n" +" Example: call RxFuncAdd 'UZLoadFuncs', 'UNZIPAPI', 'UZLoadFuncs'\n" +" call UZLoadFuncs\n" }, + + { "UZFILETREE" , "UZFileTree" , + "rc = UZFileTree(zipfile, stem, [include], [exclude], [options])\n\n" +" zipfile - Name of ZIP file to search\n" +" stem - Name of the stem variable for results\n" +" Note: stem.0 contains the number of files found.\n" +" include - Optional stem variable specifying a list of files (including\n" +" wildcards) to include. stem.0 must indicate number of items.\n" +" exclude - Optional stem variable specifying a list of files (including\n" +" wildcards) to exclude. stem.0 must indicate number of items.\n" +" NOTE: If lists are not needed, filespec strings may be passed.\n" +" options - One of the following:\n" +" 'O' - Give file names only. This is the default.\n" +" 'F' - Give file statistics in the form:\n" +" Length Date Time Name\n" +" 'Z' - Also give ZIP statistics in the form:\n" +" Length Method Size Ratio Date Time CRC-32 Name", + "Finds all files in the specified ZIP with the specified\n" +" filespec and places their descriptions in a stem variable.\n\n" +" rc: Return codes\n" +" 0 Successful\n" +" 2 Error. Not enough memory.\n\n" +" Examples:\n" +" /* Return a list of all .NDX files in pcboard.qwk */\n" +" rc = UZFileTree('pcboard.qwk', 'stem.', '*.ndx')\n\n" +" /* Return a list of all files except *.NDX and *.DAT */\n" +" exc.0 = 2; exc.1 = '*.ndx'; exc.2 = '*.dat'\n" +" rc = UZFileTree('pcboard.qwk', 'stem.',,'exc.')\n" }, + + { "UZUNZIP" , "UZUnZip" , + "rc = UZUnZip('parameters', [stem])\n\n" +" parameters - The entire list of parameters you would use from\n" +" the command-line\n" +" stem - The name of an optional stem variable where any\n" +" output should be redirected.\n" +" NOTE: If a stem is not specified, all output will\n" +" go to the console.", + "Provide a direct entry point to the command line interface.\n\n" +" rc: UnZip return code\n\n" +" Examples: /* Test the archive 'unzip51s.zip' and return output in stem.*/\n" +" rc = UZUnZip('-t unzip51s.zip','stem.')\n" +" /* Extract the archive, display output on screen */\n" +" call UZUnZip 'doom.zip'\n" +" /* Extract all .NDX files from the archive */\n" +" call UZUnZip 'pcboard.qwk *.ndx','stem.'\n" }, + + { "UZUNZIPTOVAR" , "UZUnZipToVar" , + "rc = UZUnZipToVar('zipfile', 'filename', [stem])\n\n" +" zipfile - Name of ZIP file to search\n" +" filename - Name of file to extract from zipfile\n" +" stem - Optional stem variable to extract the file to.\n" +" If you specify a stem variable, the file will be extracted\n" +" to the variable, one line per index, stem.0 containing a\n" +" line count. In this case, 0 will be returned in rc.\n" +" If NO stem variable is specified, the entire file will be\n" +" extracted to rc.", + "Unzip one file to a variable.\n\n" +" rc: If no stem variable is specified, rc contains the contents of\n" +" the extracted file if successful or an error-code if not.\n" +" If a stem variable IS specified, rc contains 0 if successful.\n"}, + + /* GRR: "include" and "exclude" used to be identified as stem variables + * (Daniel H bug report) + */ + { "UZUNZIPTOSTEM", "UZUnZipToStem", + "rc = UZUnZipToStem(zipfile, stem, [include], [exclude], [mode])\n" +" zipfile - Name of ZIP file to search\n" +" stem - Stem variable used to store the extracted files\n" +" include - Optional string variable specifying a list of files (including\n" +" wildcards) to include. stem.0 must indicate number of items.\n" +" exclude - Optional string variable specifying a list of files (including\n" +" wildcards) to exclude. stem.0 must indicate number of items.\n" +" NOTE: If lists are not needed, filespec strings may be passed.\n" +" mode - Optional mode parameter specifies either 'F'lat (the default)\n" +" or 'T'ree mode.\n" +" -- In flat mode, each file is stored in stem.fullname i.e.\n" +" stem.os2/dll/unzipapi.c. A list of files is created in\n" +" stem.\n" +" -- In tree mode, slashes are converted to periods in the\n" +" pathname thus the above file would have been stored in\n" +" stem.OS2.DLL.unzipapi.c and an index stored for each\n" +" directory, i.e. stem.OS2.DLL. = \"unzipapi.c\",\n" +" stem.OS2. = \"DLL/\", stem. = \"OS2/\"", + "Unzip files to a stem variable.\n\n" +" Example: Assuming a file unzip.zip containing:\n" +" unzip.c, unshrink.c, extract.c,\n" +" os2/makefile.os2, os2/os2.c\n" +" os2/dll/dll.def, os2/dll/unzipapi.c\n\n" +" rc = UZUnZipToStem('unzip.zip', 'stem.')\n" +" Returns: stem.0 = 7\n" +" stem.1 = unzip.c\n" +" stem.2 = unshrink.c\n" +" stem.3 = extract.c\n" +" stem.4 = os2/makefile.os2\n" +" stem.5 = os2/os2.c\n" +" stem.6 = os2/dll/dll.def\n" +" stem.7 = os2/dll/unzipapi.c\n" +" And the following contain the contents of the\n" +" various files:\n" +" stem.unzip.c\n" +" stem.unshrink.c\n" +" stem.extract.c\n" +" stem.os2/makefile.os2\n" +" stem.os2/os2.c\n" +" stem.os2/dll/dll.def\n" +" stem.os2/dll/unzipapi.c\n\n" +" rc = UZUnZipToStem('unzip.zip', 'stem.',,,'TREE')\n" +" Returns: stem.0 = 4\n" +" stem.1 = unzip.c\n" +" stem.2 = unshrink.c\n" +" stem.3 = extract.c\n" +" stem.4 = OS2/\n" +" stem.OS2.0 = 3\n" +" stem.OS2.1 = makefile.os2\n" +" stem.OS2.2 = os2.c\n" +" stem.OS2.3 = DLL/\n" +" stem.OS2.DLL.0 = 2\n" +" stem.OS2.DLL.1 = def\n" +" stem.OS2.DLL.2 = unzipapi.c\n" +"\n" +" And the following contain the contents of the\n" +" various programs:\n" +" stem.unzip.c\n" +" stem.unshrink.c\n" +" stem.extract.c\n" +" stem.OS2.makefile.os2\n" +" stem.OS2.os2.c\n" +" stem.OS2.DLL.dll.def\n" +" stem.OS2.DLL.unzipapi.c\n" }, + + { "UZVER" , "UZVer" , + "rc = UZVer([option])\n\n" +" rc String containing UnZip version info in the form 'x.xx'\n" +" If option is 'L' then info is in the form 'x.xx of ", + "Returns the version number of UnZip\n" }, + + { "UZAPIVER" , "UZAPIVer" , + "rc = UZAPIVer([option])\n\n" +" rc String containing API version info in the form 'x.xx'\n" +" If option is 'L' then info is in the form 'x.xx of ", + "Returns the version number of the API\n" }, + { 0 } +}; + +char *REXXBrief = "\ +REXX functions:\n\ + UZDropFuncs -- Makes all functions in this package unknown to REXX\n\ + UZLoadFuncs -- Makes all functions in this package known to REXX\n\ + UZFileTree -- Searches for files matching a given filespec\n\ + UZUnZip -- UnZip command-line entry point\n\ + UZUnZipToVar -- Unzip one file to a variable\n\ + UZUnZipToStem -- Unzip files to a variable array\n\ + UZVer -- Returns the UnZip version number\n\ + UZAPIVer -- Returns the API version number\n"; + + +#endif /* API_DOC && OS2DLL */ diff --git a/os2/rexxtest.cmd b/os2/rexxtest.cmd new file mode 100644 index 0000000..5351ea9 --- /dev/null +++ b/os2/rexxtest.cmd @@ -0,0 +1,54 @@ +/* Test REXX UnZip API */ +call RxFuncAdd 'UZLoadFuncs', 'UNZIP32', 'UZLoadFuncs' +call UZLoadFuncs + +parse arg all + +say; say 'Demonstrating UZUnZip' UZUnZip(all,'TEST.') +do num=1 to test.0 + say num':'test.num +end + +/*** Demonstrate UZFileTree ***/ +fname = 'g:\cqc\channel1\12-30.qwk' +say; say 'Demonstrating UZFileTree by displaying all entries in', + fname +exc.0 = 2 +exc.1 = '*.dat' +exc.2 = '*.ndx' +call UZFileTree fname, 'files','','exc' +do num=1 to files.0 + say num':'files.num +end + +say; say 'Demonstrating UZUnZipToVar -' UZUnZipToVar(fname,'CONTROL.DAT') + + +test. = 0 +say; say 'Demonstrating UZUnZipToVar -' UZUnZipToVar(fname,'CONTROL.DAT','test.') +SAY "Test =" test.0 +do num=1 to test.0 + say num':'test.num +end + +test. = 0 +say; say 'Demonstrating UZUnZipToStem -' UZUnZipToStem('\SourceCode\cqc\cqcmain.zip','test',"*.rch",,'T') +call recout "test" + +say; say 'Demonstrating UZVer -' UZVer() + +call UZDropFuncs +exit + +recout: PROCEDURE EXPOSE test. +parse arg this +say this "Contains" value(this'.0') "entries" +do num=1 to value(this'.0') + tval = value(this'.'num) + say "Got" this'.'num':' tval + if Right(tval,1) = '/' then + call recout this'.'left(tval,length(tval)-1) + else + say "Contains:" value(this'.tval') +end +return diff --git a/os2/stub.def b/os2/stub.def new file mode 100644 index 0000000..f3852f1 --- /dev/null +++ b/os2/stub.def @@ -0,0 +1,6 @@ +DESCRIPTION 'The world-famous Info-ZIP unarchiving utilities' +STACKSIZE 0x50000 +IMPORTS + UNZIP32.UzpVersion + UNZIP32.UzpMain + UNZIP32.UzpVersion2 diff --git a/os2/unzip.def b/os2/unzip.def new file mode 100644 index 0000000..e57dd82 --- /dev/null +++ b/os2/unzip.def @@ -0,0 +1,4 @@ +NAME WINDOWCOMPAT NEWFILES +DESCRIPTION 'The world-famous Info-ZIP unarchiving utilities' +; SEGMENTS +; _MSGSEG32 CLASS 'CODE' diff --git a/os2/zgrepapi.cmd b/os2/zgrepapi.cmd new file mode 100644 index 0000000..3af0b19 --- /dev/null +++ b/os2/zgrepapi.cmd @@ -0,0 +1,98 @@ +/*--------------------------------------------------------------------------- + + zapigrep.cmd (ye olde REXX procedure for OS/2) + + Script to search members of a zipfile for a string and print the names of + any such members (and, optionally, the matching text). + + This is the zipgrep.cmd program completely rewritten to take advantage + of the REXX API. Among the improvements are: + egrep no longer needed. All work done by API and this script. + Added option switches. + + Be aware, however, that this script does not support regular expressions + as zipgrep does. + + ---------------------------------------------------------------------------*/ + +PARSE ARG args + +nocase = 0 +word = 0 +text = 0 + +DO WHILE Left(args,1) == '-' | Left(args,1) == '/' + PARSE VAR args option args + option = Translate(SubStr(option,2)) + DO WHILE option \= '' + oneopt = Left(option,1) + option = SubStr(option,2) + SELECT + WHEN oneopt == 'W' THEN + word = 1 + WHEN oneopt == 'I' THEN + nocase = 1 + WHEN oneopt == 'T' THEN + text = 1 + OTHERWISE NOP + END + END +END + +PARSE VAR args string zipfile members + +IF (string == '') THEN DO + SAY 'usage: zipgrep [-i][-t][-w] search_string zipfile [members...]' + SAY ' Displays the names of zipfile members containing a given string.' + SAY ' By default it displays filenames only of members containing an' + SAY ' exact match of the string. Options are:'"0a"x + SAY ' -i Ignore case' + SAY ' -t Display matching lines' + SAY ' -w Match words only' + EXIT 1 +END +string = Strip(string,'b','"') +IF nocase THEN string = Translate(string) + +CALL RxFuncAdd 'UZLoadFuncs', 'UNZIP32', 'UZLoadFuncs' +CALL UZLoadFuncs + +CALL UZUnZipToStem zipfile, 'file.', members + +DO i = 1 TO file.0 + ptr = file.i + file = file.ptr + IF nocase THEN file = Translate(file) + IF word THEN DO + wp = WordPos(string,file) + IF wp>0 THEN + scan = WordIndex(file,wp) + ELSE + scan = 0 + END + ELSE + scan = Pos(string,file) + IF scan \= 0 THEN DO + SAY file.i':' + IF text THEN DO + DO WHILE scan > 0 + from = LastPos('0a'x,file,scan)+1 + to = Pos('0a'x,file,scan) + IF to = 0 THEN to = Length(file.ptr) + oneline = Strip(SubStr(file.ptr,from,to-from),'T','0a'x) + SAY Strip(oneline,'T','0d'x) + IF word THEN DO + wp = WordPos(string,file,wp+1) + IF wp>0 THEN + scan = WordIndex(file,wp) + ELSE + scan = 0 + END + ELSE + scan = Pos(string,file,scan+1) + END + END + END +END + +EXIT 0 diff --git a/os2/zip2exe.cmd b/os2/zip2exe.cmd new file mode 100644 index 0000000..300deb2 --- /dev/null +++ b/os2/zip2exe.cmd @@ -0,0 +1,62 @@ +/**** REXX ******** ZIP2EXE.CMD ************** 01/04/96 *********\ +|** This exec will prepend the Info Zip unzipsfx.exe file to an **| +|** existing ZIP file to create a self extracting zip. **| +|** **| +|** The exec requires 1 argument, the name of the zip file to be **| +|** acted upon. **| +|** **| +|** Put this exec into the path that contains your Info Zip **| +|** executables. **| +|** **| +\*********************************************************************/ +rc = 0 +/** Start Argument processing ** End Initialization **/ +PARSE UPPER ARG zip_file +IF zip_file = "" +THEN + DO + SAY "You must specify the name of the file to be processed" + SAY "Please try again" + rc = 9 + SIGNAL FINI + END +IF POS(".ZIP",zip_file) = 0 +THEN + DO + sfx_file = zip_file||".EXE" + zip_file = zip_file||".ZIP" + END +ELSE + sfx_file = SUBSTR(zip_file,1,LASTPOS(".",zip_file))||"EXE" +zip_file = STREAM(zip_file,"C","QUERY EXISTS") +IF zip_file = "" +THEN + DO + SAY "The file "||ARG(1)||" Does not exist" + SAY "Processing terminated" + rc = 9 + SIGNAL FINI + END +/** Start unzipsfx location ** End Argument processing **/ +PARSE UPPER SOURCE . . command_file +unzipsfx = SUBSTR(command_file,1,LASTPOS("\",command_file))||, + "UNZIPSFX.EXE" +IF STREAM(unzipsfx,"C","QUERY EXISTS") = "" +THEN + DO + SAY "We are unable to locate the UNZIPSFX.EXE source" + SAY "Ensure that the ZIP2EXE command is in the directory", + "which contains UNZIPSFX.EXE" + rc = 9 + SIGNAL FINI + END +/** Execute the command ** End Argument processing **/ +ADDRESS CMD "@COPY /b "||unzipsfx||"+"||zip_file, + sfx_file||" > NUL" +IF rc = 0 +THEN + SAY sfx_file||" successfully created" +ELSE + SAY sfx_file||" creation failed" +FINI: + EXIT rc diff --git a/os2/zipgrep.cmd b/os2/zipgrep.cmd new file mode 100644 index 0000000..8de7e88 --- /dev/null +++ b/os2/zipgrep.cmd @@ -0,0 +1,56 @@ +/*--------------------------------------------------------------------------- + + zipgrep.cmd (ye olde REXX procedure for OS/2) + + Script to search members of a zipfile for a string or regular expression + and print the names of any such members (and, optionally, the matching + text). The search is case-insensitive by default. + + History: + original Bourne shell version by Jean-loup Gailly + modified by Greg Roelofs for Ultrix (no egrep -i) and zipinfo -1 + OS/2 REXX script by Greg Roelofs + + Last modified: 19 Jul 93 + + ---------------------------------------------------------------------------*/ + +PARSE ARG string zipfile members + +if (string == '') then do + say 'usage: zipgrep search_string zipfile [members...]' + say ' Displays the names of zipfile members containing a given string,' + say ' in addition to the matching text. This procedure requires unzip' + say ' and egrep in the current path, and it is quite slow....' + exit 1 +end + +/* doesn't seem to work... +newq = RXQUEUE("Create",zipgrep_pipe) +oldq = RXQUEUE("Set",newq) + */ + +/* flush the queue before starting */ +do QUEUED() + PULL junk +end + +/* GRR: can also add "2>&1" before pipe in following external command */ +'@unzip -Z1' zipfile members '| rxqueue' + +do while QUEUED() > 0 + PARSE PULL file + '@unzip -p' zipfile file '| egrep -is' string + if rc == 0 then do + SAY file':' + /* can comment out following line if just want filenames */ + '@unzip -p' zipfile file '| egrep -i' string + end +end + +/* +call RXQUEUE "Delete",newq +call RXQUEUE "Set",oldq + */ + +exit 0 diff --git a/packaging/unzip-6.0-attribs-overflow.patch b/packaging/unzip-6.0-attribs-overflow.patch new file mode 100644 index 0000000..3122325 --- /dev/null +++ b/packaging/unzip-6.0-attribs-overflow.patch @@ -0,0 +1,12 @@ +diff -up unzip60/zipinfo.c.attribs-overflow unzip60/zipinfo.c +--- unzip60/zipinfo.c.attribs-overflow 2009-11-30 09:55:39.000000000 +0100 ++++ unzip60/zipinfo.c 2009-11-30 09:56:42.844263244 +0100 +@@ -1881,7 +1881,7 @@ static int zi_short(__G) /* return PK- + #endif + int k, error, error_in_archive=PK_COOL; + unsigned hostnum, hostver, methid, methnum, xattr; +- char *p, workspace[12], attribs[16]; ++ char *p, workspace[12], attribs[17]; + char methbuf[5]; + static ZCONST char dtype[5]="NXFS"; /* normal, maximum, fast, superfast */ + static ZCONST char Far os[NUM_HOSTS+1][4] = { diff --git a/packaging/unzip-6.0-bzip2-configure.patch b/packaging/unzip-6.0-bzip2-configure.patch new file mode 100644 index 0000000..9cf006b --- /dev/null +++ b/packaging/unzip-6.0-bzip2-configure.patch @@ -0,0 +1,29 @@ +diff -up unzip60/unix/configure.bzip2-configure unzip60/unix/configure +--- unzip60/unix/configure.bzip2-configure 2009-04-16 21:25:12.000000000 +0200 ++++ unzip60/unix/configure 2009-11-18 11:22:14.598389194 +0100 +@@ -640,7 +640,24 @@ else + D_USE_BZ2="-DUSE_BZIP2" + L_BZ2="${BZLF} -lbz2" + else +- echo "-- bzip2 sources not found - no bzip2 support" ++ echo " Check if OS already has bzip2 library installed" ++ cat > conftest.c << _EOF_ ++#include "bzlib.h" ++int main() ++{ ++ bz_stream strm; ++ BZ2_bzCompressEnd(&strm); ++ return 0; ++} ++_EOF_ ++ $CC $CFLAGS -o conftest conftest.c -lbz2 > /dev/null 2>/dev/null ++ if test $? -eq 0; then ++ echo "-- OS supports bzip2 - linking in bzip2" ++ D_USE_BZ2="-DBZIP2_SUPPORT" ++ L_BZ2="${BZLF} -lbz2" ++ else ++ echo "-- Either bzlib.h or libbz2.a not found - no bzip2" ++ fi + fi + fi + diff --git a/packaging/unzip-6.0-close.patch b/packaging/unzip-6.0-close.patch new file mode 100644 index 0000000..9a238a9 --- /dev/null +++ b/packaging/unzip-6.0-close.patch @@ -0,0 +1,176 @@ +diff -up unzip60/extract.c.close unzip60/extract.c +--- unzip60/extract.c.close 2009-03-14 02:32:52.000000000 +0100 ++++ unzip60/extract.c 2009-11-19 08:17:23.481263496 +0100 +@@ -1924,24 +1924,21 @@ static int extract_or_test_member(__G) + + #ifdef VMS /* VMS: required even for stdout! (final flush) */ + if (!uO.tflag) /* don't close NULL file */ +- close_outfile(__G); ++ error = close_outfile(__G); + #else + #ifdef DLL + if (!uO.tflag && (!uO.cflag || G.redirect_data)) { + if (G.redirect_data) + FINISH_REDIRECT(); + else +- close_outfile(__G); ++ error = close_outfile(__G); + } + #else + if (!uO.tflag && !uO.cflag) /* don't close NULL file or stdout */ +- close_outfile(__G); ++ error = close_outfile(__G); + #endif + #endif /* VMS */ + +- /* GRR: CONVERT close_outfile() TO NON-VOID: CHECK FOR ERRORS! */ +- +- + if (G.disk_full) { /* set by flush() */ + if (G.disk_full > 1) { + #if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK)) +diff -up unzip60/unix/unix.c.close unzip60/unix/unix.c +--- unzip60/unix/unix.c.close 2009-01-24 00:31:26.000000000 +0100 ++++ unzip60/unix/unix.c 2009-11-19 08:33:25.568389171 +0100 +@@ -1096,10 +1096,41 @@ static int get_extattribs(__G__ pzt, z_u + #ifndef MTS + + /****************************/ ++/* Function CloseError() */ ++/***************************/ ++ ++int CloseError(__G) ++ __GDEF ++{ ++ int errval = PK_OK; ++ ++ if (fclose(G.outfile) < 0) { ++ switch (errno) { ++ case ENOSPC: ++ /* Do we need this on fileio.c? */ ++ Info(slide, 0x4a1, ((char *)slide, "%s: write error (disk full?). Continue? (y/n/^C) ", ++ FnFilter1(G.filename))); ++ fgets(G.answerbuf, 9, stdin); ++ if (*G.answerbuf == 'y') /* stop writing to this file */ ++ G.disk_full = 1; /* pass to next */ ++ else ++ G.disk_full = 2; /* no: exit program */ ++ ++ errval = PK_DISK; ++ break; ++ ++ default: ++ errval = PK_WARN; ++ } ++ } ++ return errval; ++} /* End of CloseError() */ ++ ++/****************************/ + /* Function close_outfile() */ + /****************************/ + +-void close_outfile(__G) /* GRR: change to return PK-style warning level */ ++int close_outfile(__G) + __GDEF + { + union { +@@ -1108,6 +1139,7 @@ void close_outfile(__G) /* GRR: chang + } zt; + ulg z_uidgid[2]; + int have_uidgid_flg; ++ int errval = PK_OK; + + have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid); + +@@ -1141,16 +1173,16 @@ void close_outfile(__G) /* GRR: chang + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed: mem alloc overflow\n", + FnFilter1(G.filename))); +- fclose(G.outfile); +- return; ++ errval = CloseError(G.outfile, G.filename); ++ return errval ? errval : PK_WARN; + } + + if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed: no mem\n", + FnFilter1(G.filename))); +- fclose(G.outfile); +- return; ++ errval = CloseError(G.outfile, G.filename); ++ return errval ? errval : PK_WARN; + } + slnk_entry->next = NULL; + slnk_entry->targetlen = ucsize; +@@ -1174,10 +1206,10 @@ void close_outfile(__G) /* GRR: chang + "warning: symbolic link (%s) failed\n", + FnFilter1(G.filename))); + free(slnk_entry); +- fclose(G.outfile); +- return; ++ errval = CloseError(G.outfile, G.filename); ++ return errval ? errval : PK_WARN; + } +- fclose(G.outfile); /* close "link" file for good... */ ++ errval = CloseError(G.outfile, G.filename); /* close "link" file for good... */ + slnk_entry->target[ucsize] = '\0'; + if (QCOND2) + Info(slide, 0, ((char *)slide, "-> %s ", +@@ -1188,7 +1220,7 @@ void close_outfile(__G) /* GRR: chang + else + G.slink_head = slnk_entry; + G.slink_last = slnk_entry; +- return; ++ return errval; + } + #endif /* SYMLINKS */ + +@@ -1201,7 +1233,7 @@ void close_outfile(__G) /* GRR: chang + #endif + + #if (defined(NO_FCHOWN)) +- fclose(G.outfile); ++ errval = CloseError(G.outfile, G.filename); + #endif + + /* if -X option was specified and we have UID/GID info, restore it */ +@@ -1227,7 +1259,7 @@ void close_outfile(__G) /* GRR: chang + } + + #if (!defined(NO_FCHOWN) && defined(NO_FCHMOD)) +- fclose(G.outfile); ++ errval = CloseError(G.outfile, G.filename); + #endif + + #if (!defined(NO_FCHOWN) && !defined(NO_FCHMOD)) +@@ -1239,7 +1271,7 @@ void close_outfile(__G) /* GRR: chang + if (fchmod(fileno(G.outfile), filtattr(__G__ G.pInfo->file_attr))) + perror("fchmod (file attributes) error"); + +- fclose(G.outfile); ++ errval = CloseError(G.outfile, G.filename); + #endif /* !NO_FCHOWN && !NO_FCHMOD */ + + /* skip restoring time stamps on user's request */ +@@ -1267,6 +1299,7 @@ void close_outfile(__G) /* GRR: chang + #endif + #endif /* NO_FCHOWN || NO_FCHMOD */ + ++ return errval; + } /* end function close_outfile() */ + + #endif /* !MTS */ +diff -up unzip60/unzpriv.h.close unzip60/unzpriv.h +--- unzip60/unzpriv.h.close 2009-04-20 01:59:26.000000000 +0200 ++++ unzip60/unzpriv.h 2009-11-19 08:19:08.610388618 +0100 +@@ -2604,7 +2604,7 @@ char *GetLoadPath OF((__GPRO)); + int SetFileSize OF((FILE *file, zusz_t filesize)); /* local */ + #endif + #ifndef MTS /* macro in MTS */ +- void close_outfile OF((__GPRO)); /* local */ ++ int close_outfile OF((__GPRO)); /* local */ + #endif + #ifdef SET_SYMLINK_ATTRIBS + int set_symlnk_attribs OF((__GPRO__ slinkentry *slnk_entry)); /* local */ diff --git a/packaging/unzip-6.0-exec-shield.patch b/packaging/unzip-6.0-exec-shield.patch new file mode 100644 index 0000000..74500aa --- /dev/null +++ b/packaging/unzip-6.0-exec-shield.patch @@ -0,0 +1,10 @@ +diff -up unzip60/crc_i386.S.exec-shield unzip60/crc_i386.S +--- unzip60/crc_i386.S.exec-shield 2007-01-07 06:02:58.000000000 +0100 ++++ unzip60/crc_i386.S 2009-11-18 11:16:39.630389312 +0100 +@@ -302,3 +302,6 @@ _crc32: /* ulg c + #endif /* i386 || _i386 || _I386 || __i386 */ + + #endif /* !USE_ZLIB && !CRC_TABLE_ONLY */ ++ ++.section .note.GNU-stack, "", @progbits ++.previous diff --git a/packaging/unzip-6.0-nostrip.patch b/packaging/unzip-6.0-nostrip.patch new file mode 100644 index 0000000..71c263f --- /dev/null +++ b/packaging/unzip-6.0-nostrip.patch @@ -0,0 +1,12 @@ +diff -up unzip60/unix/configure.nostrip unzip60/unix/configure +--- unzip60/unix/configure.nostrip 2009-11-30 10:18:09.000000000 +0100 ++++ unzip60/unix/configure 2009-11-30 10:21:08.354264213 +0100 +@@ -17,7 +17,7 @@ CFLAGSR=${CFLAGS} + IZ_BZIP2=${3} + CFLAGS="${CFLAGS} -I. -DUNIX" + LFLAGS1="" +-LFLAGS2="-s" ++LFLAGS2="" + LN="ln -s" + + CFLAGS_OPT='' diff --git a/packaging/unzip.changes b/packaging/unzip.changes new file mode 100644 index 0000000..8c6a943 --- /dev/null +++ b/packaging/unzip.changes @@ -0,0 +1,244 @@ +* Tue Feb 02 2010 Yi Yang - 6.0 +- Update to 6.0 + +* Wed Mar 19 2008 Ivana Varekova - 5.52-9 +- fix crash (double free) on malformed zip archive + CVE-2008-0888 (#431438) + +* Fri Feb 8 2008 Ivana Varekova - 5.52-8 +- fix output when out of space error appears + +* Wed Jan 23 2008 Ivana Varekova - 5.52-7 +- fix another long file support problem + +* Tue Jan 22 2008 Ivana Varekova - 5.52-6 +- add 4GB patch (#429674) + +* Tue Sep 4 2007 Ivana Varekova - 5.52-5 +- fix open call + +* Wed Feb 7 2007 Ivana Varekova - 5.52-4 +- incorporate the next peckage review comment + +* Tue Feb 6 2007 Ivana Varekova - 5.52-3 +- Resolves: 226516 + Incorporate the package review + +* Wed Jul 12 2006 Jesse Keating - 5.52-2.2.1 +- rebuild + +* Fri Feb 10 2006 Jesse Keating - 5.52-2.2 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 5.52-2.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Mon Feb 6 2006 Ivana Varekova 5.52-2 +- fix bug 180078 - unzip -l causing error +- fix CVE-2005-4667 - unzip long file name buffer overflow + +* Thu Dec 22 2005 Ivana Varekova 5.52-1 +- update to 5.52 + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Wed Aug 3 2005 Ivana Varekova 5.51-12 +- fix bug 164928 - TOCTOU issue in unzip + +* Mon May 9 2005 Ivana Varekova 5.51-11 +- fix bug 156959 – invalid file mode on created files + +* Mon Mar 7 2005 Ivana Varekova 5.51-10 +- rebuilt + +* Thu Feb 10 2005 Ivana Varekova 5.51-9 +- fix the other problem with unpacking zipfiles containing symlinks + (bug #134073) + +* Thu Feb 03 2005 Ivana Varekova 5.51-8 +- fix segfault with unpacking of zipfiles containing dangling symlinks + (bug #134073) + +* Thu Dec 02 2004 Lon Hohberger 5.51-6 +- Rebuild + +* Thu Dec 02 2004 Lon Hohberger 5.51-5 +- Fix segfault on extraction of symlinks + +* Mon Jun 21 2004 Lon Hohberger 5.51-4 +- Extend max file/archive size to 2^32-8193 (4294959103) bytes + +* Tue Jun 15 2004 Elliot Lee +- rebuilt + +* Tue Jun 08 2004 Lon Hohberger 5.51-2 +- Rebuild + +* Tue Jun 08 2004 Lon Hohberger 5.51-1.1 +- Update to 5.51; remove dotdot patch. + +* Fri Feb 13 2004 Elliot Lee +- rebuilt + +* Mon Nov 17 2003 Lon Hohberger 5.50-36 +- Rebuild for FC-next + +* Fri Aug 01 2003 Lon Hohberger 5.50-35 +- Rebuild for Severn + +* Fri Aug 01 2003 Lon Hohberger 5.50-34 +- Rebuild for Taroon + +* Fri Aug 01 2003 Lon Hohberger 5.50-33 +- Rebuild for 9 errata + +* Fri Aug 01 2003 Lon Hohberger 5.50-32 +- Rebuild for 8.0 errata + +* Fri Aug 01 2003 Lon Hohberger 5.50-31 +- Rebuild for 7.3 errata + +* Wed Jul 30 2003 Lon Hohberger 5.50-30 +- SECURITY Round 3: Fix up original patch (from 5.50-9) to fix +^V/ exploit, but still allow '-:', which the other patch (5.50-18) +does not allow. Never allow explicit writing to the root +directory; force users to change there and extract it manually. + +* Wed Jul 30 2003 Lon Hohberger 5.50-29 +- Rebuild for Severn + +* Wed Jul 30 2003 Lon Hohberger 5.50-28 +- Rebuild + +* Wed Jul 30 2003 Lon Hohberger 5.50-27 +- Rebuild for 9 + +* Wed Jul 30 2003 Lon Hohberger 5.50-26 +- Rebuild for 8.0 + +* Tue Jul 22 2003 Lon Hohberger 5.50-23 +- Rebuild for 7.3 + +* Mon Jul 21 2003 Lon Hohberger 5.50-22 +- Rebuild for Severn + +* Mon Jul 21 2003 Lon Hohberger 5.50-21 +- Rebuild + +* Mon Jul 21 2003 Lon Hohberger 5.50-20 +- Rebuild for 9 + +* Mon Jul 21 2003 Lon Hohberger 5.50-19 +- Rebuild for 8.0 + +* Mon Jul 21 2003 Lon Hohberger 5.50-18 +- SECURITY: Incorporate far cleaner patch from Ben Laurie + which also fixes ^V/ (quote-slash). +Patch checks post-decode as opposed to inline as previous +patch does. + +* Mon Jun 16 2003 Lon Hohberger 5.50-17 +- Rebuilt per request + +* Thu Jun 12 2003 Lon Hohberger 5.50-16 +- Rebuilt + +* Thu Jun 12 2003 Lon Hohberger 5.50-15 +- Rebuilt + +* Thu Jun 12 2003 Lon Hohberger 5.50-14 +- Rebuilt: Red Hat Linux 9 + +* Thu Jun 12 2003 Lon Hohberger 5.50-13 +- Rebuilt: Red Hat Enterprise Linux 2.1 + +* Thu Jun 12 2003 Lon Hohberger 5.50-12 +- Rebuilt Red Hat Linux 8.0 + +* Thu Jun 12 2003 Lon Hohberger 5.50-11 +- Rebuilt Red Hat Linux 7.3 + +* Wed Jun 11 2003 Lon Hohberger 5.50-10 +- Rebuilt + +* Wed Jun 11 2003 Lon Hohberger 5.50-9 +- SECURITY: Scour start of filename for ../ patterns which +include quote and/or control characters. + +* Wed Jun 04 2003 Elliot Lee +- rebuilt + +* Wed Jan 22 2003 Tim Powers +- rebuilt + +* Thu Dec 19 2002 Tim Powers +- bump and rebuild + +* Fri Jun 21 2002 Tim Powers +- automated rebuild + +* Thu May 23 2002 Tim Powers +- automated rebuild + +* Thu Apr 25 2002 Trond Eivind Glomsrød 5.50-3 +- Rebuild + +* Tue Apr 2 2002 Trond Eivind Glomsrød 5.50-2 +- Make it not strip + +* Wed Mar 13 2002 Trond Eivind Glomsrød 5.50-1 +- 5.50 + +* Thu Feb 21 2002 Trond Eivind Glomsrød 5.42-3 +- Rebuild + +* Wed Jan 09 2002 Tim Powers +- automated rebuild + +* Mon May 21 2001 Trond Eivind Glomsrød +- 5.42 +- Don't strip binaries explicitly +- build without assembly, it doesn't seem to increase performance +- make it respect RPM_OPT_FLAGS, define _GNU_SOURCE +- use %%{_tmppath} +- "License:" replaces "Copyright:" +- Update URL +- include zipgrep +- COPYING doesn't exist anymore, include LICENSE instead + +* Thu Jul 13 2000 Prospector +- automatic rebuild + +* Sun Jun 11 2000 BIll Nottingham +- rebuild in new env.; FHS fixes. + +* Tue Apr 18 2000 Bernhard Rosenkraenzer +- 4.51 (an acceptable license at last...) + +* Thu Feb 3 2000 Bill Nottingham +- handle compressed man pages + +* Fri Jul 30 1999 Bill Nottingham +- update to 5.40 + +* Sun Mar 21 1999 Cristian Gafton +- auto rebuild in the new build environment (release 5) + +* Thu Dec 17 1998 Michael Maher +- built for 6.0 + +* Tue Aug 11 1998 Jeff Johnson +- build root + +* Mon Apr 27 1998 Prospector System +- translations modified for de, fr, tr + +* Tue Oct 21 1997 Erik Troan +- builds on non i386 platforms + +* Mon Oct 20 1997 Otto Hammersmith +- updated the version + +* Thu Jul 10 1997 Erik Troan +- built against glibc diff --git a/packaging/unzip.spec b/packaging/unzip.spec new file mode 100644 index 0000000..a02ced0 --- /dev/null +++ b/packaging/unzip.spec @@ -0,0 +1,60 @@ +#specfile originally created for Fedora, modified for Moblin Linux +Summary: A utility for unpacking zip files +Name: unzip +Version: 6.0 +Release: 9 +License: BSD +Group: Applications/Archiving +Source: ftp://ftp.info-zip.org/pub/infozip/src/unzip60.tar.gz +# Not sent to upstream. +Patch1: unzip-6.0-bzip2-configure.patch +# Upstream plans to do this in zip (hopefully also in unzip). +Patch2: unzip-6.0-exec-shield.patch +# Upstream plans to do similar thing. +Patch3: unzip-6.0-close.patch +# Details in rhbz#532380. +# Reported to upstream: http://www.info-zip.org/board/board.pl?m-1259575993/ +Patch4: unzip-6.0-attribs-overflow.patch +# Not sent to upstream, as it's Fedora/RHEL specific. +# Modify the configure script not to request the strip of binaries. +Patch5: unzip-6.0-nostrip.patch +URL: http://www.info-zip.org/pub/infozip/UnZip.html +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + +%description +The unzip utility is used to list, test, or extract files from a zip +archive. Zip archives are commonly found on MS-DOS systems. The zip +utility, included in the zip package, creates zip archives. Zip and +unzip are both compatible with archives created by PKWARE(R)'s PKZIP +for MS-DOS, but the programs' options and default behaviors do differ +in some respects. + +Install the unzip package if you need to list, test or extract files from +a zip archive. + +%prep +%setup -q -n %{name}60 +%patch1 -p1 -b .bzip2-configure +%patch2 -p1 -b .exec-shield +%patch3 -p1 -b .close +%patch4 -p1 -b .attribs-overflow +%patch5 -p1 -b .nostrip +ln -s unix/Makefile Makefile + +%build +make CFLAGS="-D_LARGEFILE64_SOURCE" linux_noasm LF2="" %{?_smp_mflags} + +%install +rm -rf $RPM_BUILD_ROOT + +make prefix=$RPM_BUILD_ROOT%{_prefix} MANDIR=$RPM_BUILD_ROOT/%{_mandir}/man1 INSTALL="cp -p" install LF2="" + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%doc README BUGS LICENSE +%{_bindir}/* +%doc %{_mandir}/*/* + diff --git a/process.c b/process.c new file mode 100644 index 0000000..1e9a1e1 --- /dev/null +++ b/process.c @@ -0,0 +1,3088 @@ +/* + Copyright (c) 1990-2009 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2009-Jan-02 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 +*/ +/*--------------------------------------------------------------------------- + + process.c + + This file contains the top-level routines for processing multiple zipfiles. + + Contains: process_zipfiles() + free_G_buffers() + do_seekable() + file_size() + rec_find() + find_ecrec64() + find_ecrec() + process_zip_cmmnt() + process_cdir_file_hdr() + get_cdir_ent() + process_local_file_hdr() + getZip64Data() + ef_scan_for_izux() + getRISCOSexfield() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" +#ifdef WINDLL +# ifdef POCKET_UNZIP +# include "wince/intrface.h" +# else +# include "windll/windll.h" +# endif +#endif +#if defined(DYNALLOC_CRCTAB) || defined(UNICODE_SUPPORT) +# include "crc32.h" +#endif + +static int do_seekable OF((__GPRO__ int lastchance)); +#ifdef DO_SAFECHECK_2GB +# ifdef USE_STRM_INPUT +static zoff_t file_size OF((FILE *file)); +# else +static zoff_t file_size OF((int fh)); +# endif +#endif /* DO_SAFECHECK_2GB */ +static int rec_find OF((__GPRO__ zoff_t, char *, int)); +static int find_ecrec64 OF((__GPRO__ zoff_t searchlen)); +static int find_ecrec OF((__GPRO__ zoff_t searchlen)); +static int process_zip_cmmnt OF((__GPRO)); +static int get_cdir_ent OF((__GPRO)); +#ifdef IZ_HAVE_UXUIDGID +static int read_ux3_value OF((ZCONST uch *dbuf, unsigned uidgid_sz, + ulg *p_uidgid)); +#endif /* IZ_HAVE_UXUIDGID */ + + +static ZCONST char Far CannotAllocateBuffers[] = + "error: cannot allocate unzip buffers\n"; + +#ifdef SFX + static ZCONST char Far CannotFindMyself[] = + "unzipsfx: cannot find myself! [%s]\n"; +# ifdef CHEAP_SFX_AUTORUN + static ZCONST char Far AutorunPrompt[] = + "\nAuto-run command: %s\nExecute this command? [y/n] "; + static ZCONST char Far NotAutoRunning[] = + "Not executing auto-run command."; +# endif + +#else /* !SFX */ + /* process_zipfiles() strings */ +# if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME)) + static ZCONST char Far WarnInvalidTZ[] = + "Warning: TZ environment variable not found, cannot use UTC times!!\n"; +# endif +# if !(defined(UNIX) || defined(AMIGA)) + static ZCONST char Far CannotFindWildcardMatch[] = + "%s: cannot find any matches for wildcard specification \"%s\".\n"; +# endif /* !(UNIX || AMIGA) */ + static ZCONST char Far FilesProcessOK[] = + "%d archive%s successfully processed.\n"; + static ZCONST char Far ArchiveWarning[] = + "%d archive%s had warnings but no fatal errors.\n"; + static ZCONST char Far ArchiveFatalError[] = + "%d archive%s had fatal errors.\n"; + static ZCONST char Far FileHadNoZipfileDir[] = + "%d file%s had no zipfile directory.\n"; + static ZCONST char Far ZipfileWasDir[] = "1 \"zipfile\" was a directory.\n"; + static ZCONST char Far ManyZipfilesWereDir[] = + "%d \"zipfiles\" were directories.\n"; + static ZCONST char Far NoZipfileFound[] = "No zipfiles found.\n"; + + /* do_seekable() strings */ +# ifdef UNIX + static ZCONST char Far CannotFindZipfileDirMsg[] = + "%s: cannot find zipfile directory in one of %s or\n\ + %s%s.zip, and cannot find %s, period.\n"; + static ZCONST char Far CannotFindEitherZipfile[] = + "%s: cannot find or open %s, %s.zip or %s.\n"; +# else /* !UNIX */ + static ZCONST char Far CannotFindZipfileDirMsg[] = + "%s: cannot find zipfile directory in %s,\n\ + %sand cannot find %s, period.\n"; +# ifdef VMS + static ZCONST char Far CannotFindEitherZipfile[] = + "%s: cannot find %s (%s).\n"; +# else /* !VMS */ + static ZCONST char Far CannotFindEitherZipfile[] = + "%s: cannot find either %s or %s.\n"; +# endif /* ?VMS */ +# endif /* ?UNIX */ + extern ZCONST char Far Zipnfo[]; /* in unzip.c */ +#ifndef WINDLL + static ZCONST char Far Unzip[] = "unzip"; +#else + static ZCONST char Far Unzip[] = "UnZip DLL"; +#endif +#ifdef DO_SAFECHECK_2GB + static ZCONST char Far ZipfileTooBig[] = + "Trying to read large file (> 2 GiB) without large file support\n"; +#endif /* DO_SAFECHECK_2GB */ + static ZCONST char Far MaybeExe[] = + "note: %s may be a plain executable, not an archive\n"; + static ZCONST char Far CentDirNotInZipMsg[] = "\n\ + [%s]:\n\ + Zipfile is disk %lu of a multi-disk archive, and this is not the disk on\n\ + which the central zipfile directory begins (disk %lu).\n"; + static ZCONST char Far EndCentDirBogus[] = + "\nwarning [%s]: end-of-central-directory record claims this\n\ + is disk %lu but that the central directory starts on disk %lu; this is a\n\ + contradiction. Attempting to process anyway.\n"; +# ifdef NO_MULTIPART + static ZCONST char Far NoMultiDiskArcSupport[] = + "\nerror [%s]: zipfile is part of multi-disk archive\n\ + (sorry, not yet supported).\n"; + static ZCONST char Far MaybePakBug[] = "warning [%s]:\ + zipfile claims to be 2nd disk of a 2-part archive;\n\ + attempting to process anyway. If no further errors occur, this archive\n\ + was probably created by PAK v2.51 or earlier. This bug was reported to\n\ + NoGate in March 1991 and was supposed to have been fixed by mid-1991; as\n\ + of mid-1992 it still hadn't been. (If further errors do occur, archive\n\ + was probably created by PKZIP 2.04c or later; UnZip does not yet support\n\ + multi-part archives.)\n"; +# else + static ZCONST char Far MaybePakBug[] = "warning [%s]:\ + zipfile claims to be last disk of a multi-part archive;\n\ + attempting to process anyway, assuming all parts have been concatenated\n\ + together in order. Expect \"errors\" and warnings...true multi-part support\ +\n doesn't exist yet (coming soon).\n"; +# endif + static ZCONST char Far ExtraBytesAtStart[] = + "warning [%s]: %s extra byte%s at beginning or within zipfile\n\ + (attempting to process anyway)\n"; +#endif /* ?SFX */ + +#if ((!defined(WINDLL) && !defined(SFX)) || !defined(NO_ZIPINFO)) + static ZCONST char Far LogInitline[] = "Archive: %s\n"; +#endif + +static ZCONST char Far MissingBytes[] = + "error [%s]: missing %s bytes in zipfile\n\ + (attempting to process anyway)\n"; +static ZCONST char Far NullCentDirOffset[] = + "error [%s]: NULL central directory offset\n\ + (attempting to process anyway)\n"; +static ZCONST char Far ZipfileEmpty[] = "warning [%s]: zipfile is empty\n"; +static ZCONST char Far CentDirStartNotFound[] = + "error [%s]: start of central directory not found;\n\ + zipfile corrupt.\n%s"; +static ZCONST char Far Cent64EndSigSearchErr[] = + "fatal error: read failure while seeking for End-of-centdir-64 signature.\n\ + This zipfile is corrupt.\n"; +static ZCONST char Far Cent64EndSigSearchOff[] = + "error: End-of-centdir-64 signature not where expected (prepended bytes?)\n\ + (attempting to process anyway)\n"; +#ifndef SFX + static ZCONST char Far CentDirTooLong[] = + "error [%s]: reported length of central directory is\n\ + %s bytes too long (Atari STZip zipfile? J.H.Holm ZIPSPLIT 1.1\n\ + zipfile?). Compensating...\n"; + static ZCONST char Far CentDirEndSigNotFound[] = "\ + End-of-central-directory signature not found. Either this file is not\n\ + a zipfile, or it constitutes one disk of a multi-part archive. In the\n\ + latter case the central directory and zipfile comment will be found on\n\ + the last disk(s) of this archive.\n"; +#else /* SFX */ + static ZCONST char Far CentDirEndSigNotFound[] = + " End-of-central-directory signature not found.\n"; +#endif /* ?SFX */ +#ifdef TIMESTAMP + static ZCONST char Far ZipTimeStampFailed[] = + "warning: cannot set time for %s\n"; + static ZCONST char Far ZipTimeStampSuccess[] = + "Updated time stamp for %s.\n"; +#endif +static ZCONST char Far ZipfileCommTrunc1[] = + "\ncaution: zipfile comment truncated\n"; +#ifndef NO_ZIPINFO + static ZCONST char Far NoZipfileComment[] = + "There is no zipfile comment.\n"; + static ZCONST char Far ZipfileCommentDesc[] = + "The zipfile comment is %u bytes long and contains the following text:\n"; + static ZCONST char Far ZipfileCommBegin[] = + "======================== zipfile comment begins\ + ==========================\n"; + static ZCONST char Far ZipfileCommEnd[] = + "========================= zipfile comment ends\ + ===========================\n"; + static ZCONST char Far ZipfileCommTrunc2[] = + "\n The zipfile comment is truncated.\n"; +#endif /* !NO_ZIPINFO */ +#ifdef UNICODE_SUPPORT + static ZCONST char Far UnicodeVersionError[] = + "\nwarning: Unicode Path version > 1\n"; + static ZCONST char Far UnicodeMismatchError[] = + "\nwarning: Unicode Path checksum invalid\n"; +#endif + + + + +/*******************************/ +/* Function process_zipfiles() */ +/*******************************/ + +int process_zipfiles(__G) /* return PK-type error code */ + __GDEF +{ +#ifndef SFX + char *lastzipfn = (char *)NULL; + int NumWinFiles, NumLoseFiles, NumWarnFiles; + int NumMissDirs, NumMissFiles; +#endif + int error=0, error_in_archive=0; + + +/*--------------------------------------------------------------------------- + Start by allocating buffers and (re)constructing the various PK signature + strings. + ---------------------------------------------------------------------------*/ + + G.inbuf = (uch *)malloc(INBUFSIZ + 4); /* 4 extra for hold[] (below) */ + G.outbuf = (uch *)malloc(OUTBUFSIZ + 1); /* 1 extra for string term. */ + + if ((G.inbuf == (uch *)NULL) || (G.outbuf == (uch *)NULL)) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotAllocateBuffers))); + return(PK_MEM); + } + G.hold = G.inbuf + INBUFSIZ; /* to check for boundary-spanning sigs */ +#ifndef VMS /* VMS uses its own buffer scheme for textmode flush(). */ +#ifdef SMALL_MEM + G.outbuf2 = G.outbuf+RAWBUFSIZ; /* never changes */ +#endif +#endif /* !VMS */ + +#if 0 /* CRC_32_TAB has been NULLified by CONSTRUCTGLOBALS !!!! */ + /* allocate the CRC table later when we know we can read zipfile data */ + CRC_32_TAB = NULL; +#endif /* 0 */ + + /* finish up initialization of magic signature strings */ + local_hdr_sig[0] /* = extd_local_sig[0] */ = /* ASCII 'P', */ + central_hdr_sig[0] = end_central_sig[0] = /* not EBCDIC */ + end_centloc64_sig[0] = end_central64_sig[0] = 0x50; + + local_hdr_sig[1] /* = extd_local_sig[1] */ = /* ASCII 'K', */ + central_hdr_sig[1] = end_central_sig[1] = /* not EBCDIC */ + end_centloc64_sig[1] = end_central64_sig[1] = 0x4B; + +/*--------------------------------------------------------------------------- + Make sure timezone info is set correctly; localtime() returns GMT on some + OSes (e.g., Solaris 2.x) if this isn't done first. The ifdefs around + tzset() were initially copied from dos_to_unix_time() in fileio.c. They + may still be too strict; any listed OS that supplies tzset(), regardless + of whether the function does anything, should be removed from the ifdefs. + ---------------------------------------------------------------------------*/ + +#if (defined(WIN32) && defined(USE_EF_UT_TIME)) + /* For the Win32 environment, we may have to "prepare" the environment + prior to the tzset() call, to work around tzset() implementation bugs. + */ + iz_w32_prepareTZenv(); +#endif + +#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME)) +# ifndef VALID_TIMEZONE +# define VALID_TIMEZONE(tmp) \ + (((tmp = getenv("TZ")) != NULL) && (*tmp != '\0')) +# endif + { + char *p; + G.tz_is_valid = VALID_TIMEZONE(p); +# ifndef SFX + if (!G.tz_is_valid) { + Info(slide, 0x401, ((char *)slide, LoadFarString(WarnInvalidTZ))); + error_in_archive = error = PK_WARN; + } +# endif /* !SFX */ + } +#endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */ + +/* For systems that do not have tzset() but supply this function using another + name (_tzset() or something similar), an appropiate "#define tzset ..." + should be added to the system specifc configuration section. */ +#if (!defined(T20_VMS) && !defined(MACOS) && !defined(RISCOS) && !defined(QDOS)) +#if (!defined(BSD) && !defined(MTS) && !defined(CMS_MVS) && !defined(TANDEM)) + tzset(); +#endif +#endif + +/* Initialize UnZip's built-in pseudo hard-coded "ISO <--> OEM" translation, + depending on the detected codepage setup. */ +#ifdef NEED_ISO_OEM_INIT + prepare_ISO_OEM_translat(__G); +#endif + +/*--------------------------------------------------------------------------- + Initialize the internal flag holding the mode of processing "overwrite + existing file" cases. We do not use the calling interface flags directly + because the overwrite mode may be changed by user interaction while + processing archive files. Such a change should not affect the option + settings as passed through the DLL calling interface. + In case of conflicting options, the 'safer' flag uO.overwrite_none takes + precedence. + ---------------------------------------------------------------------------*/ + G.overwrite_mode = (uO.overwrite_none ? OVERWRT_NEVER : + (uO.overwrite_all ? OVERWRT_ALWAYS : OVERWRT_QUERY)); + +/*--------------------------------------------------------------------------- + Match (possible) wildcard zipfile specification with existing files and + attempt to process each. If no hits, try again after appending ".zip" + suffix. If still no luck, give up. + ---------------------------------------------------------------------------*/ + +#ifdef SFX + if ((error = do_seekable(__G__ 0)) == PK_NOZIP) { +#ifdef EXE_EXTENSION + int len=strlen(G.argv0); + + /* append .exe if appropriate; also .sfx? */ + if ( (G.zipfn = (char *)malloc(len+sizeof(EXE_EXTENSION))) != + (char *)NULL ) { + strcpy(G.zipfn, G.argv0); + strcpy(G.zipfn+len, EXE_EXTENSION); + error = do_seekable(__G__ 0); + free(G.zipfn); + G.zipfn = G.argv0; /* for "cannot find myself" message only */ + } +#endif /* EXE_EXTENSION */ +#ifdef WIN32 + G.zipfn = G.argv0; /* for "cannot find myself" message only */ +#endif + } + if (error) { + if (error == IZ_DIR) + error_in_archive = PK_NOZIP; + else + error_in_archive = error; + if (error == PK_NOZIP) + Info(slide, 1, ((char *)slide, LoadFarString(CannotFindMyself), + G.zipfn)); + } +#ifdef CHEAP_SFX_AUTORUN + if (G.autorun_command[0] && !uO.qflag) { /* NO autorun without prompt! */ + Info(slide, 0x81, ((char *)slide, LoadFarString(AutorunPrompt), + FnFilter1(G.autorun_command))); + if (fgets(G.answerbuf, 9, stdin) != (char *)NULL + && toupper(*G.answerbuf) == 'Y') + system(G.autorun_command); + else + Info(slide, 1, ((char *)slide, LoadFarString(NotAutoRunning))); + } +#endif /* CHEAP_SFX_AUTORUN */ + +#else /* !SFX */ + NumWinFiles = NumLoseFiles = NumWarnFiles = 0; + NumMissDirs = NumMissFiles = 0; + + while ((G.zipfn = do_wild(__G__ G.wildzipfn)) != (char *)NULL) { + Trace((stderr, "do_wild( %s ) returns %s\n", G.wildzipfn, G.zipfn)); + + lastzipfn = G.zipfn; + + /* print a blank line between the output of different zipfiles */ + if (!uO.qflag && error != PK_NOZIP && error != IZ_DIR +#ifdef TIMESTAMP + && (!uO.T_flag || uO.zipinfo_mode) +#endif + && (NumWinFiles+NumLoseFiles+NumWarnFiles+NumMissFiles) > 0) + (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); + + if ((error = do_seekable(__G__ 0)) == PK_WARN) + ++NumWarnFiles; + else if (error == IZ_DIR) + ++NumMissDirs; + else if (error == PK_NOZIP) + ++NumMissFiles; + else if (error != PK_OK) + ++NumLoseFiles; + else + ++NumWinFiles; + + Trace((stderr, "do_seekable(0) returns %d\n", error)); + if (error != IZ_DIR && error > error_in_archive) + error_in_archive = error; +#ifdef WINDLL + if (error == IZ_CTRLC) { + free_G_buffers(__G); + return error; + } +#endif + + } /* end while-loop (wildcard zipfiles) */ + + if ((NumWinFiles + NumWarnFiles + NumLoseFiles) == 0 && + (NumMissDirs + NumMissFiles) == 1 && lastzipfn != (char *)NULL) + { +#if (!defined(UNIX) && !defined(AMIGA)) /* filenames with wildcard characters */ + if (iswild(G.wildzipfn)) { + if (iswild(lastzipfn)) { + NumMissDirs = NumMissFiles = 0; + error_in_archive = PK_COOL; + if (uO.qflag < 3) + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotFindWildcardMatch), + LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), + G.wildzipfn)); + } + } else +#endif + { +#ifndef VMS + /* 2004-11-24 SMS. + * VMS has already tried a default file type of ".zip" in + * do_wild(), so adding ZSUFX here only causes confusion by + * corrupting some valid (though nonexistent) file names. + * Complaining below about "fred;4.zip" is unlikely to be + * helpful to the victim. + */ + /* 2005-08-14 Chr. Spieler + * Although we already "know" the failure result, we call + * do_seekable() again with the same zipfile name (and the + * lastchance flag set), just to trigger the error report... + */ +#if defined(UNIX) || defined(QDOS) + char *p = +#endif + strcpy(lastzipfn + strlen(lastzipfn), ZSUFX); +#endif /* !VMS */ + + G.zipfn = lastzipfn; + + NumMissDirs = NumMissFiles = 0; + error_in_archive = PK_COOL; + +#if defined(UNIX) || defined(QDOS) + /* only Unix has case-sensitive filesystems */ + /* Well FlexOS (sometimes) also has them, but support is per media */ + /* and a pig to code for, so treat as case insensitive for now */ + /* we do this under QDOS to check for .zip as well as _zip */ + if ((error = do_seekable(__G__ 0)) == PK_NOZIP || error == IZ_DIR) { + if (error == IZ_DIR) + ++NumMissDirs; + strcpy(p, ALT_ZSUFX); + error = do_seekable(__G__ 1); + } +#else + error = do_seekable(__G__ 1); +#endif + Trace((stderr, "do_seekable(1) returns %d\n", error)); + switch (error) { + case PK_WARN: + ++NumWarnFiles; + break; + case IZ_DIR: + ++NumMissDirs; + error = PK_NOZIP; + break; + case PK_NOZIP: + /* increment again => bug: + "1 file had no zipfile directory." */ + /* ++NumMissFiles */ ; + break; + default: + if (error) + ++NumLoseFiles; + else + ++NumWinFiles; + break; + } + + if (error > error_in_archive) + error_in_archive = error; +#ifdef WINDLL + if (error == IZ_CTRLC) { + free_G_buffers(__G); + return error; + } +#endif + } + } +#endif /* ?SFX */ + +/*--------------------------------------------------------------------------- + Print summary of all zipfiles, assuming zipfile spec was a wildcard (no + need for a summary if just one zipfile). + ---------------------------------------------------------------------------*/ + +#ifndef SFX + if (iswild(G.wildzipfn) && uO.qflag < 3 +#ifdef TIMESTAMP + && !(uO.T_flag && !uO.zipinfo_mode && uO.qflag > 1) +#endif + ) + { + if ((NumMissFiles + NumLoseFiles + NumWarnFiles > 0 || NumWinFiles != 1) +#ifdef TIMESTAMP + && !(uO.T_flag && !uO.zipinfo_mode && uO.qflag) +#endif + && !(uO.tflag && uO.qflag > 1)) + (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0x401); + if ((NumWinFiles > 1) || + (NumWinFiles == 1 && + NumMissDirs + NumMissFiles + NumLoseFiles + NumWarnFiles > 0)) + Info(slide, 0x401, ((char *)slide, LoadFarString(FilesProcessOK), + NumWinFiles, (NumWinFiles == 1)? " was" : "s were")); + if (NumWarnFiles > 0) + Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveWarning), + NumWarnFiles, (NumWarnFiles == 1)? "" : "s")); + if (NumLoseFiles > 0) + Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveFatalError), + NumLoseFiles, (NumLoseFiles == 1)? "" : "s")); + if (NumMissFiles > 0) + Info(slide, 0x401, ((char *)slide, + LoadFarString(FileHadNoZipfileDir), NumMissFiles, + (NumMissFiles == 1)? "" : "s")); + if (NumMissDirs == 1) + Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileWasDir))); + else if (NumMissDirs > 0) + Info(slide, 0x401, ((char *)slide, + LoadFarString(ManyZipfilesWereDir), NumMissDirs)); + if (NumWinFiles + NumLoseFiles + NumWarnFiles == 0) + Info(slide, 0x401, ((char *)slide, LoadFarString(NoZipfileFound))); + } +#endif /* !SFX */ + + /* free allocated memory */ + free_G_buffers(__G); + + return error_in_archive; + +} /* end function process_zipfiles() */ + + + + + +/*****************************/ +/* Function free_G_buffers() */ +/*****************************/ + +void free_G_buffers(__G) /* releases all memory allocated in global vars */ + __GDEF +{ +#ifndef SFX + unsigned i; +#endif + +#ifdef SYSTEM_SPECIFIC_DTOR + SYSTEM_SPECIFIC_DTOR(__G); +#endif + + inflate_free(__G); + checkdir(__G__ (char *)NULL, END); + +#ifdef DYNALLOC_CRCTAB + if (CRC_32_TAB) { + free_crc_table(); + CRC_32_TAB = NULL; + } +#endif + + if (G.key != (char *)NULL) { + free(G.key); + G.key = (char *)NULL; + } + + if (G.extra_field != (uch *)NULL) { + free(G.extra_field); + G.extra_field = (uch *)NULL; + } + +#if (!defined(VMS) && !defined(SMALL_MEM)) + /* VMS uses its own buffer scheme for textmode flush() */ + if (G.outbuf2) { + free(G.outbuf2); /* malloc'd ONLY if unshrink and -a */ + G.outbuf2 = (uch *)NULL; + } +#endif + + if (G.outbuf) + free(G.outbuf); + if (G.inbuf) + free(G.inbuf); + G.inbuf = G.outbuf = (uch *)NULL; + +#ifdef UNICODE_SUPPORT + if (G.filename_full) { + free(G.filename_full); + G.filename_full = (char *)NULL; + G.fnfull_bufsize = 0; + } +#endif /* UNICODE_SUPPORT */ + +#ifndef SFX + for (i = 0; i < DIR_BLKSIZ; i++) { + if (G.info[i].cfilname != (char Far *)NULL) { + zffree(G.info[i].cfilname); + G.info[i].cfilname = (char Far *)NULL; + } + } +#endif + +#ifdef MALLOC_WORK + if (G.area.Slide) { + free(G.area.Slide); + G.area.Slide = (uch *)NULL; + } +#endif + +} /* end function free_G_buffers() */ + + + + + +/**************************/ +/* Function do_seekable() */ +/**************************/ + +static int do_seekable(__G__ lastchance) /* return PK-type error code */ + __GDEF + int lastchance; +{ +#ifndef SFX + /* static int no_ecrec = FALSE; SKM: moved to globals.h */ + int maybe_exe=FALSE; + int too_weird_to_continue=FALSE; +#ifdef TIMESTAMP + time_t uxstamp; + ulg nmember = 0L; +#endif +#endif + int error=0, error_in_archive; + + +/*--------------------------------------------------------------------------- + Open the zipfile for reading in BINARY mode to prevent CR/LF translation, + which would corrupt the bit streams. + ---------------------------------------------------------------------------*/ + + if (SSTAT(G.zipfn, &G.statbuf) || +#ifdef THEOS + (error = S_ISLIB(G.statbuf.st_mode)) != 0 || +#endif + (error = S_ISDIR(G.statbuf.st_mode)) != 0) + { +#ifndef SFX + if (lastchance && (uO.qflag < 3)) { +#if defined(UNIX) || defined(QDOS) + if (G.no_ecrec) + Info(slide, 1, ((char *)slide, + LoadFarString(CannotFindZipfileDirMsg), + LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), + G.wildzipfn, uO.zipinfo_mode? " " : "", G.wildzipfn, + G.zipfn)); + else + Info(slide, 1, ((char *)slide, + LoadFarString(CannotFindEitherZipfile), + LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), + G.wildzipfn, G.wildzipfn, G.zipfn)); +#else /* !(UNIX || QDOS) */ + if (G.no_ecrec) + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotFindZipfileDirMsg), + LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), + G.wildzipfn, uO.zipinfo_mode? " " : "", G.zipfn)); + else +#ifdef VMS + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotFindEitherZipfile), + LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), + G.wildzipfn, + (*G.zipfn ? G.zipfn : vms_msg_text()))); +#else /* !VMS */ + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotFindEitherZipfile), + LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)), + G.wildzipfn, G.zipfn)); +#endif /* ?VMS */ +#endif /* ?(UNIX || QDOS) */ + } +#endif /* !SFX */ + return error? IZ_DIR : PK_NOZIP; + } + G.ziplen = G.statbuf.st_size; + +#ifndef SFX +#if defined(UNIX) || defined(DOS_OS2_W32) || defined(THEOS) + if (G.statbuf.st_mode & S_IEXEC) /* no extension on Unix exes: might */ + maybe_exe = TRUE; /* find unzip, not unzip.zip; etc. */ +#endif +#endif /* !SFX */ + +#ifdef VMS + if (check_format(__G)) /* check for variable-length format */ + return PK_ERR; +#endif + + if (open_input_file(__G)) /* this should never happen, given */ + return PK_NOZIP; /* the stat() test above, but... */ + +#ifdef DO_SAFECHECK_2GB + /* Need more care: Do not trust the size returned by stat() but + determine it by reading beyond the end of the file. */ + G.ziplen = file_size(G.zipfd); + + if (G.ziplen == EOF) { + Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileTooBig))); + /* + printf( +" We need a better error message for: 64-bit file, 32-bit program.\n"); + */ + CLOSE_INFILE(); + return IZ_ERRBF; + } +#endif /* DO_SAFECHECK_2GB */ + +/*--------------------------------------------------------------------------- + Find and process the end-of-central-directory header. UnZip need only + check last 65557 bytes of zipfile: comment may be up to 65535, end-of- + central-directory record is 18 bytes, and signature itself is 4 bytes; + add some to allow for appended garbage. Since ZipInfo is often used as + a debugging tool, search the whole zipfile if zipinfo_mode is true. + ---------------------------------------------------------------------------*/ + + G.cur_zipfile_bufstart = 0; + G.inptr = G.inbuf; + +#if ((!defined(WINDLL) && !defined(SFX)) || !defined(NO_ZIPINFO)) +# if (!defined(WINDLL) && !defined(SFX)) + if ( (!uO.zipinfo_mode && !uO.qflag +# ifdef TIMESTAMP + && !uO.T_flag +# endif + ) +# ifndef NO_ZIPINFO + || (uO.zipinfo_mode && uO.hflag) +# endif + ) +# else /* not (!WINDLL && !SFX) ==> !NO_ZIPINFO !! */ + if (uO.zipinfo_mode && uO.hflag) +# endif /* if..else..: (!WINDLL && !SFX) */ +# ifdef WIN32 /* Win32 console may require codepage conversion for G.zipfn */ + Info(slide, 0, ((char *)slide, LoadFarString(LogInitline), + FnFilter1(G.zipfn))); +# else + Info(slide, 0, ((char *)slide, LoadFarString(LogInitline), G.zipfn)); +# endif +#endif /* (!WINDLL && !SFX) || !NO_ZIPINFO */ + + if ( (error_in_archive = find_ecrec(__G__ +#ifndef NO_ZIPINFO + uO.zipinfo_mode ? G.ziplen : +#endif + MIN(G.ziplen, 66000L))) + > PK_WARN ) + { + CLOSE_INFILE(); + +#ifdef SFX + ++lastchance; /* avoid picky compiler warnings */ + return error_in_archive; +#else + if (maybe_exe) + Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeExe), + G.zipfn)); + if (lastchance) + return error_in_archive; + else { + G.no_ecrec = TRUE; /* assume we found wrong file: e.g., */ + return PK_NOZIP; /* unzip instead of unzip.zip */ + } +#endif /* ?SFX */ + } + + if ((uO.zflag > 0) && !uO.zipinfo_mode) { /* unzip: zflag = comment ONLY */ + CLOSE_INFILE(); + return error_in_archive; + } + +/*--------------------------------------------------------------------------- + Test the end-of-central-directory info for incompatibilities (multi-disk + archives) or inconsistencies (missing or extra bytes in zipfile). + ---------------------------------------------------------------------------*/ + +#ifdef NO_MULTIPART + error = !uO.zipinfo_mode && (G.ecrec.number_this_disk == 1) && + (G.ecrec.num_disk_start_cdir == 1); +#else + error = !uO.zipinfo_mode && (G.ecrec.number_this_disk != 0); +#endif + +#ifndef SFX + if (uO.zipinfo_mode && + G.ecrec.number_this_disk != G.ecrec.num_disk_start_cdir) + { + if (G.ecrec.number_this_disk > G.ecrec.num_disk_start_cdir) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(CentDirNotInZipMsg), G.zipfn, + (ulg)G.ecrec.number_this_disk, + (ulg)G.ecrec.num_disk_start_cdir)); + error_in_archive = PK_FIND; + too_weird_to_continue = TRUE; + } else { + Info(slide, 0x401, ((char *)slide, + LoadFarString(EndCentDirBogus), G.zipfn, + (ulg)G.ecrec.number_this_disk, + (ulg)G.ecrec.num_disk_start_cdir)); + error_in_archive = PK_WARN; + } +#ifdef NO_MULTIPART /* concatenation of multiple parts works in some cases */ + } else if (!uO.zipinfo_mode && !error && G.ecrec.number_this_disk != 0) { + Info(slide, 0x401, ((char *)slide, LoadFarString(NoMultiDiskArcSupport), + G.zipfn)); + error_in_archive = PK_FIND; + too_weird_to_continue = TRUE; +#endif + } + + if (!too_weird_to_continue) { /* (relatively) normal zipfile: go for it */ + if (error) { + Info(slide, 0x401, ((char *)slide, LoadFarString(MaybePakBug), + G.zipfn)); + error_in_archive = PK_WARN; + } +#endif /* !SFX */ + if ((G.extra_bytes = G.real_ecrec_offset-G.expect_ecrec_offset) < + (zoff_t)0) + { + Info(slide, 0x401, ((char *)slide, LoadFarString(MissingBytes), + G.zipfn, FmZofft((-G.extra_bytes), NULL, NULL))); + error_in_archive = PK_ERR; + } else if (G.extra_bytes > 0) { + if ((G.ecrec.offset_start_central_directory == 0) && + (G.ecrec.size_central_directory != 0)) /* zip 1.5 -go bug */ + { + Info(slide, 0x401, ((char *)slide, + LoadFarString(NullCentDirOffset), G.zipfn)); + G.ecrec.offset_start_central_directory = G.extra_bytes; + G.extra_bytes = 0; + error_in_archive = PK_ERR; + } +#ifndef SFX + else { + Info(slide, 0x401, ((char *)slide, + LoadFarString(ExtraBytesAtStart), G.zipfn, + FmZofft(G.extra_bytes, NULL, NULL), + (G.extra_bytes == 1)? "":"s")); + error_in_archive = PK_WARN; + } +#endif /* !SFX */ + } + + /*----------------------------------------------------------------------- + Check for empty zipfile and exit now if so. + -----------------------------------------------------------------------*/ + + if (G.expect_ecrec_offset==0L && G.ecrec.size_central_directory==0) { + if (uO.zipinfo_mode) + Info(slide, 0, ((char *)slide, "%sEmpty zipfile.\n", + uO.lflag>9? "\n " : "")); + else + Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileEmpty), + G.zipfn)); + CLOSE_INFILE(); + return (error_in_archive > PK_WARN)? error_in_archive : PK_WARN; + } + + /*----------------------------------------------------------------------- + Compensate for missing or extra bytes, and seek to where the start + of central directory should be. If header not found, uncompensate + and try again (necessary for at least some Atari archives created + with STZip, as well as archives created by J.H. Holm's ZIPSPLIT 1.1). + -----------------------------------------------------------------------*/ + + error = seek_zipf(__G__ G.ecrec.offset_start_central_directory); + if (error == PK_BADERR) { + CLOSE_INFILE(); + return PK_BADERR; + } +#ifdef OLD_SEEK_TEST + if (error != PK_OK || readbuf(__G__ G.sig, 4) == 0) { + CLOSE_INFILE(); + return PK_ERR; /* file may be locked, or possibly disk error(?) */ + } + if (memcmp(G.sig, central_hdr_sig, 4)) +#else + if ((error != PK_OK) || (readbuf(__G__ G.sig, 4) == 0) || + memcmp(G.sig, central_hdr_sig, 4)) +#endif + { +#ifndef SFX + zoff_t tmp = G.extra_bytes; +#endif + + G.extra_bytes = 0; + error = seek_zipf(__G__ G.ecrec.offset_start_central_directory); + if ((error != PK_OK) || (readbuf(__G__ G.sig, 4) == 0) || + memcmp(G.sig, central_hdr_sig, 4)) + { + if (error != PK_BADERR) + Info(slide, 0x401, ((char *)slide, + LoadFarString(CentDirStartNotFound), G.zipfn, + LoadFarStringSmall(ReportMsg))); + CLOSE_INFILE(); + return (error != PK_OK ? error : PK_BADERR); + } +#ifndef SFX + Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirTooLong), + G.zipfn, FmZofft((-tmp), NULL, NULL))); +#endif + error_in_archive = PK_ERR; + } + + /*----------------------------------------------------------------------- + Seek to the start of the central directory one last time, since we + have just read the first entry's signature bytes; then list, extract + or test member files as instructed, and close the zipfile. + -----------------------------------------------------------------------*/ + + error = seek_zipf(__G__ G.ecrec.offset_start_central_directory); + if (error != PK_OK) { + CLOSE_INFILE(); + return error; + } + + Trace((stderr, "about to extract/list files (error = %d)\n", + error_in_archive)); + +#ifdef DLL + /* G.fValidate is used only to look at an archive to see if + it appears to be a valid archive. There is no interest + in what the archive contains, nor in validating that the + entries in the archive are in good condition. This is + currently used only in the Windows DLLs for purposes of + checking archives within an archive to determine whether + or not to display the inner archives. + */ + if (!G.fValidate) +#endif + { +#ifndef NO_ZIPINFO + if (uO.zipinfo_mode) + error = zipinfo(__G); /* ZIPINFO 'EM */ + else +#endif +#ifndef SFX +#ifdef TIMESTAMP + if (uO.T_flag) + error = get_time_stamp(__G__ &uxstamp, &nmember); + else +#endif + if (uO.vflag && !uO.tflag && !uO.cflag) + error = list_files(__G); /* LIST 'EM */ + else +#endif /* !SFX */ + error = extract_or_test_files(__G); /* EXTRACT OR TEST 'EM */ + + Trace((stderr, "done with extract/list files (error = %d)\n", + error)); + } + + if (error > error_in_archive) /* don't overwrite stronger error */ + error_in_archive = error; /* with (for example) a warning */ +#ifndef SFX + } /* end if (!too_weird_to_continue) */ +#endif + + CLOSE_INFILE(); + +#ifdef TIMESTAMP + if (uO.T_flag && !uO.zipinfo_mode && (nmember > 0L)) { +# ifdef WIN32 + if (stamp_file(__G__ G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */ +# else + if (stamp_file(G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */ +# endif + if (uO.qflag < 3) + Info(slide, 0x201, ((char *)slide, + LoadFarString(ZipTimeStampFailed), G.zipfn)); + if (error_in_archive < PK_WARN) + error_in_archive = PK_WARN; + } else { + if (!uO.qflag) + Info(slide, 0, ((char *)slide, + LoadFarString(ZipTimeStampSuccess), G.zipfn)); + } + } +#endif + return error_in_archive; + +} /* end function do_seekable() */ + + + + +#ifdef DO_SAFECHECK_2GB +/************************/ +/* Function file_size() */ +/************************/ +/* File size determination which does not mislead for large files in a + small-file program. Probably should be somewhere else. + The file has to be opened previously +*/ +#ifdef USE_STRM_INPUT +static zoff_t file_size(file) + FILE *file; +{ + int sts; + size_t siz; +#else /* !USE_STRM_INPUT */ +static zoff_t file_size(fh) + int fh; +{ + int siz; +#endif /* ?USE_STRM_INPUT */ + zoff_t ofs; + char waste[4]; + +#ifdef USE_STRM_INPUT + /* Seek to actual EOF. */ + sts = zfseeko(file, 0, SEEK_END); + if (sts != 0) { + /* fseeko() failed. (Unlikely.) */ + ofs = EOF; + } else { + /* Get apparent offset at EOF. */ + ofs = zftello(file); + if (ofs < 0) { + /* Offset negative (overflow). File too big. */ + ofs = EOF; + } else { + /* Seek to apparent EOF offset. + Won't be at actual EOF if offset was truncated. + */ + sts = zfseeko(file, ofs, SEEK_SET); + if (sts != 0) { + /* fseeko() failed. (Unlikely.) */ + ofs = EOF; + } else { + /* Read a byte at apparent EOF. Should set EOF flag. */ + siz = fread(waste, 1, 1, file); + if (feof(file) == 0) { + /* Not at EOF, but should be. File too big. */ + ofs = EOF; + } + } + } + } +#else /* !USE_STRM_INPUT */ + /* Seek to actual EOF. */ + ofs = zlseek(fh, 0, SEEK_END); + if (ofs == (zoff_t) -1) { + /* zlseek() failed. (Unlikely.) */ + ofs = EOF; + } else if (ofs < 0) { + /* Offset negative (overflow). File too big. */ + ofs = EOF; + } else { + /* Seek to apparent EOF offset. + Won't be at actual EOF if offset was truncated. + */ + ofs = zlseek(fh, ofs, SEEK_SET); + if (ofs == (zoff_t) -1) { + /* zlseek() failed. (Unlikely.) */ + ofs = EOF; + } else { + /* Read a byte at apparent EOF. Should set EOF flag. */ + siz = read(fh, waste, 1); + if (siz != 0) { + /* Not at EOF, but should be. File too big. */ + ofs = EOF; + } + } + } +#endif /* ?USE_STRM_INPUT */ + return ofs; +} /* end function file_size() */ +#endif /* DO_SAFECHECK_2GB */ + + + + +/***********************/ +/* Function rec_find() */ +/***********************/ + +static int rec_find(__G__ searchlen, signature, rec_size) + /* return 0 when rec found, 1 when not found, 2 in case of read error */ + __GDEF + zoff_t searchlen; + char* signature; + int rec_size; +{ + int i, numblks, found=FALSE; + zoff_t tail_len; + +/*--------------------------------------------------------------------------- + Zipfile is longer than INBUFSIZ: may need to loop. Start with short + block at end of zipfile (if not TOO short). + ---------------------------------------------------------------------------*/ + + if ((tail_len = G.ziplen % INBUFSIZ) > rec_size) { +#ifdef USE_STRM_INPUT + zfseeko(G.zipfd, G.ziplen-tail_len, SEEK_SET); + G.cur_zipfile_bufstart = zftello(G.zipfd); +#else /* !USE_STRM_INPUT */ + G.cur_zipfile_bufstart = zlseek(G.zipfd, G.ziplen-tail_len, SEEK_SET); +#endif /* ?USE_STRM_INPUT */ + if ((G.incnt = read(G.zipfd, (char *)G.inbuf, + (unsigned int)tail_len)) != (int)tail_len) + return 2; /* it's expedient... */ + + /* 'P' must be at least (rec_size+4) bytes from end of zipfile */ + for (G.inptr = G.inbuf+(int)tail_len-(rec_size+4); + G.inptr >= G.inbuf; + --G.inptr) { + if ( (*G.inptr == (uch)0x50) && /* ASCII 'P' */ + !memcmp((char *)G.inptr, signature, 4) ) { + G.incnt -= (int)(G.inptr - G.inbuf); + found = TRUE; + break; + } + } + /* sig may span block boundary: */ + memcpy((char *)G.hold, (char *)G.inbuf, 3); + } else + G.cur_zipfile_bufstart = G.ziplen - tail_len; + +/*----------------------------------------------------------------------- + Loop through blocks of zipfile data, starting at the end and going + toward the beginning. In general, need not check whole zipfile for + signature, but may want to do so if testing. + -----------------------------------------------------------------------*/ + + numblks = (int)((searchlen - tail_len + (INBUFSIZ-1)) / INBUFSIZ); + /* ==amount= ==done== ==rounding== =blksiz= */ + + for (i = 1; !found && (i <= numblks); ++i) { + G.cur_zipfile_bufstart -= INBUFSIZ; +#ifdef USE_STRM_INPUT + zfseeko(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET); +#else /* !USE_STRM_INPUT */ + zlseek(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET); +#endif /* ?USE_STRM_INPUT */ + if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) + != INBUFSIZ) + return 2; /* read error is fatal failure */ + + for (G.inptr = G.inbuf+INBUFSIZ-1; G.inptr >= G.inbuf; --G.inptr) + if ( (*G.inptr == (uch)0x50) && /* ASCII 'P' */ + !memcmp((char *)G.inptr, signature, 4) ) { + G.incnt -= (int)(G.inptr - G.inbuf); + found = TRUE; + break; + } + /* sig may span block boundary: */ + memcpy((char *)G.hold, (char *)G.inbuf, 3); + } + return (found ? 0 : 1); +} /* end function rec_find() */ + + + + +#if 0 +/********************************/ +/* Function check_ecrec_zip64() */ +/********************************/ + +static int check_ecrec_zip64(__G) + __GDEF +{ + return G.ecrec.offset_start_central_directory == 0xFFFFFFFFL + || G.ecrec.size_central_directory == 0xFFFFFFFFL + || G.ecrec.total_entries_central_dir == 0xFFFF + || G.ecrec.num_entries_centrl_dir_ths_disk == 0xFFFF + || G.ecrec.num_disk_start_cdir == 0xFFFF + || G.ecrec.number_this_disk == 0xFFFF; +} /* end function check_ecrec_zip64() */ +#endif /* never */ + + + +/***************************/ +/* Function find_ecrec64() */ +/***************************/ + +static int find_ecrec64(__G__ searchlen) /* return PK-class error */ + __GDEF + zoff_t searchlen; +{ + ec_byte_rec64 byterec; /* buf for ecrec64 */ + ec_byte_loc64 byterecL; /* buf for ecrec64 locator */ + zoff_t ecloc64_start_offset; /* start offset of ecrec64 locator */ + zusz_t ecrec64_start_offset; /* start offset of ecrec64 */ + zuvl_t ecrec64_start_disk; /* start disk of ecrec64 */ + zuvl_t ecloc64_total_disks; /* total disks */ + zuvl_t ecrec64_disk_cdstart; /* disk number of central dir start */ + zucn_t ecrec64_this_entries; /* entries on disk with ecrec64 */ + zucn_t ecrec64_tot_entries; /* total number of entries */ + zusz_t ecrec64_cdirsize; /* length of central dir */ + zusz_t ecrec64_offs_cdstart; /* offset of central dir start */ + + /* First, find the ecrec64 locator. By definition, this must be before + ecrec with nothing in between. We back up the size of the ecrec64 + locator and check. */ + + ecloc64_start_offset = G.real_ecrec_offset - (ECLOC64_SIZE+4); + if (ecloc64_start_offset < 0) + /* Seeking would go past beginning, so probably empty archive */ + return PK_COOL; + +#ifdef USE_STRM_INPUT + zfseeko(G.zipfd, ecloc64_start_offset, SEEK_SET); + G.cur_zipfile_bufstart = zftello(G.zipfd); +#else /* !USE_STRM_INPUT */ + G.cur_zipfile_bufstart = zlseek(G.zipfd, ecloc64_start_offset, SEEK_SET); +#endif /* ?USE_STRM_INPUT */ + + if ((G.incnt = read(G.zipfd, (char *)byterecL, ECLOC64_SIZE+4)) + != (ECLOC64_SIZE+4)) { + if (uO.qflag || uO.zipinfo_mode) + Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); + Info(slide, 0x401, ((char *)slide, + LoadFarString(Cent64EndSigSearchErr))); + return PK_ERR; + } + + if (memcmp((char *)byterecL, end_centloc64_sig, 4) ) { + /* not found */ + return PK_COOL; + } + + /* Read the locator. */ + ecrec64_start_disk = (zuvl_t)makelong(&byterecL[NUM_DISK_START_EOCDR64]); + ecrec64_start_offset = (zusz_t)makeint64(&byterecL[OFFSET_START_EOCDR64]); + ecloc64_total_disks = (zuvl_t)makelong(&byterecL[NUM_THIS_DISK_LOC64]); + + /* Check for consistency */ +#ifdef TEST + fprintf(stdout,"\nnumber of disks (ECR) %u, (ECLOC64) %lu\n", + G.ecrec.number_this_disk, ecloc64_total_disks); fflush(stdout); +#endif + if ((G.ecrec.number_this_disk != 0xFFFF) && + (G.ecrec.number_this_disk != ecloc64_total_disks - 1)) { + /* Note: For some unknown reason, the developers at PKWARE decided to + store the "zip64 total disks" value as a counter starting from 1, + whereas all other "split/span volume" related fields use 0-based + volume numbers. Sigh... */ + /* When the total number of disks as found in the traditional ecrec + is not 0xFFFF, the disk numbers in ecrec and ecloc64 must match. + When this is not the case, the found ecrec64 locator cannot be valid. + -> This is not a Zip64 archive. + */ + Trace((stderr, + "\ninvalid ECLOC64, differing disk# (ECR %u, ECL64 %lu)\n", + G.ecrec.number_this_disk, ecloc64_total_disks - 1)); + return PK_COOL; + } + + /* If found locator, look for ecrec64 where the locator says it is. */ + + /* For now assume that ecrec64 is on the same disk as ecloc64 and ecrec, + which is usually the case and is how Zip writes it. To do this right, + however, we should allow the ecrec64 to be on another disk since + the AppNote allows it and the ecrec64 can be large, especially if + Version 2 is used (AppNote uses 8 bytes for the size of this record). */ + + /* FIX BELOW IF ADD SUPPORT FOR MULTIPLE DISKS */ + + if (ecrec64_start_offset > (zusz_t)ecloc64_start_offset) { + /* ecrec64 has to be before ecrec64 locator */ + if (uO.qflag || uO.zipinfo_mode) + Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); + Info(slide, 0x401, ((char *)slide, + LoadFarString(Cent64EndSigSearchErr))); + return PK_ERR; + } + +#ifdef USE_STRM_INPUT + zfseeko(G.zipfd, ecrec64_start_offset, SEEK_SET); + G.cur_zipfile_bufstart = zftello(G.zipfd); +#else /* !USE_STRM_INPUT */ + G.cur_zipfile_bufstart = zlseek(G.zipfd, ecrec64_start_offset, SEEK_SET); +#endif /* ?USE_STRM_INPUT */ + + if ((G.incnt = read(G.zipfd, (char *)byterec, ECREC64_SIZE+4)) + != (ECREC64_SIZE+4)) { + if (uO.qflag || uO.zipinfo_mode) + Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); + Info(slide, 0x401, ((char *)slide, + LoadFarString(Cent64EndSigSearchErr))); + return PK_ERR; + } + + if (memcmp((char *)byterec, end_central64_sig, 4) ) { + /* Zip64 EOCD Record not found */ + /* Since we already have seen the Zip64 EOCD Locator, it's + possible we got here because there are bytes prepended + to the archive, like the sfx prefix. */ + + /* Make a guess as to where the Zip64 EOCD Record might be */ + ecrec64_start_offset = ecloc64_start_offset - ECREC64_SIZE - 4; + +#ifdef USE_STRM_INPUT + zfseeko(G.zipfd, ecrec64_start_offset, SEEK_SET); + G.cur_zipfile_bufstart = zftello(G.zipfd); +#else /* !USE_STRM_INPUT */ + G.cur_zipfile_bufstart = zlseek(G.zipfd, ecrec64_start_offset, SEEK_SET); +#endif /* ?USE_STRM_INPUT */ + + if ((G.incnt = read(G.zipfd, (char *)byterec, ECREC64_SIZE+4)) + != (ECREC64_SIZE+4)) { + if (uO.qflag || uO.zipinfo_mode) + Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); + Info(slide, 0x401, ((char *)slide, + LoadFarString(Cent64EndSigSearchErr))); + return PK_ERR; + } + + if (memcmp((char *)byterec, end_central64_sig, 4) ) { + /* Zip64 EOCD Record not found */ + /* Probably something not so easy to handle so exit */ + if (uO.qflag || uO.zipinfo_mode) + Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); + Info(slide, 0x401, ((char *)slide, + LoadFarString(Cent64EndSigSearchErr))); + return PK_ERR; + } + + if (uO.qflag || uO.zipinfo_mode) + Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); + Info(slide, 0x401, ((char *)slide, + LoadFarString(Cent64EndSigSearchOff))); + } + + /* Check consistency of found ecrec64 with ecloc64 (and ecrec): */ + if ( (zuvl_t)makelong(&byterec[NUMBER_THIS_DSK_REC64]) + != ecrec64_start_disk ) + /* found ecrec64 does not match ecloc64 info -> no Zip64 archive */ + return PK_COOL; + /* Read all relevant ecrec64 fields and compare them to the corresponding + ecrec fields unless those are set to "all-ones". + */ + ecrec64_disk_cdstart = + (zuvl_t)makelong(&byterec[NUM_DISK_START_CEN_DIR64]); + if ( (G.ecrec.num_disk_start_cdir != 0xFFFF) && + (G.ecrec.num_disk_start_cdir != ecrec64_disk_cdstart) ) + return PK_COOL; + ecrec64_this_entries + = makeint64(&byterec[NUM_ENTRIES_CEN_DIR_THS_DISK64]); + if ( (G.ecrec.num_entries_centrl_dir_ths_disk != 0xFFFF) && + (G.ecrec.num_entries_centrl_dir_ths_disk != ecrec64_this_entries) ) + return PK_COOL; + ecrec64_tot_entries + = makeint64(&byterec[TOTAL_ENTRIES_CENTRAL_DIR64]); + if ( (G.ecrec.total_entries_central_dir != 0xFFFF) && + (G.ecrec.total_entries_central_dir != ecrec64_tot_entries) ) + return PK_COOL; + ecrec64_cdirsize + = makeint64(&byterec[SIZE_CENTRAL_DIRECTORY64]); + if ( (G.ecrec.size_central_directory != 0xFFFFFFFFL) && + (G.ecrec.size_central_directory != ecrec64_cdirsize) ) + return PK_COOL; + ecrec64_offs_cdstart + = makeint64(&byterec[OFFSET_START_CENTRAL_DIRECT64]); + if ( (G.ecrec.offset_start_central_directory != 0xFFFFFFFFL) && + (G.ecrec.offset_start_central_directory != ecrec64_offs_cdstart) ) + return PK_COOL; + + /* Now, we are (almost) sure that we have a Zip64 archive. */ + G.ecrec.have_ecr64 = 1; + + /* Update the "end-of-central-dir offset" for later checks. */ + G.real_ecrec_offset = ecrec64_start_offset; + + /* Update all ecdir_rec data that are flagged to be invalid + in Zip64 mode. Set the ecrec64-mandatory flag when such a + case is found. */ + if (G.ecrec.number_this_disk == 0xFFFF) { + G.ecrec.number_this_disk = ecrec64_start_disk; + if (ecrec64_start_disk != 0xFFFF) G.ecrec.is_zip64_archive = TRUE; + } + if (G.ecrec.num_disk_start_cdir == 0xFFFF) { + G.ecrec.num_disk_start_cdir = ecrec64_disk_cdstart; + if (ecrec64_disk_cdstart != 0xFFFF) G.ecrec.is_zip64_archive = TRUE; + } + if (G.ecrec.num_entries_centrl_dir_ths_disk == 0xFFFF) { + G.ecrec.num_entries_centrl_dir_ths_disk = ecrec64_this_entries; + if (ecrec64_this_entries != 0xFFFF) G.ecrec.is_zip64_archive = TRUE; + } + if (G.ecrec.total_entries_central_dir == 0xFFFF) { + G.ecrec.total_entries_central_dir = ecrec64_tot_entries; + if (ecrec64_tot_entries != 0xFFFF) G.ecrec.is_zip64_archive = TRUE; + } + if (G.ecrec.size_central_directory == 0xFFFFFFFFL) { + G.ecrec.size_central_directory = ecrec64_cdirsize; + if (ecrec64_cdirsize != 0xFFFFFFFF) G.ecrec.is_zip64_archive = TRUE; + } + if (G.ecrec.offset_start_central_directory == 0xFFFFFFFFL) { + G.ecrec.offset_start_central_directory = ecrec64_offs_cdstart; + if (ecrec64_offs_cdstart != 0xFFFFFFFF) G.ecrec.is_zip64_archive = TRUE; + } + + return PK_COOL; +} /* end function find_ecrec64() */ + + + +/*************************/ +/* Function find_ecrec() */ +/*************************/ + +static int find_ecrec(__G__ searchlen) /* return PK-class error */ + __GDEF + zoff_t searchlen; +{ + int found = FALSE; + int error_in_archive; + int result; + ec_byte_rec byterec; + +/*--------------------------------------------------------------------------- + Treat case of short zipfile separately. + ---------------------------------------------------------------------------*/ + + if (G.ziplen <= INBUFSIZ) { +#ifdef USE_STRM_INPUT + zfseeko(G.zipfd, 0L, SEEK_SET); +#else /* !USE_STRM_INPUT */ + zlseek(G.zipfd, 0L, SEEK_SET); +#endif /* ?USE_STRM_INPUT */ + if ((G.incnt = read(G.zipfd,(char *)G.inbuf,(unsigned int)G.ziplen)) + == (int)G.ziplen) + + /* 'P' must be at least (ECREC_SIZE+4) bytes from end of zipfile */ + for (G.inptr = G.inbuf+(int)G.ziplen-(ECREC_SIZE+4); + G.inptr >= G.inbuf; + --G.inptr) { + if ( (*G.inptr == (uch)0x50) && /* ASCII 'P' */ + !memcmp((char *)G.inptr, end_central_sig, 4)) { + G.incnt -= (int)(G.inptr - G.inbuf); + found = TRUE; + break; + } + } + +/*--------------------------------------------------------------------------- + Zipfile is longer than INBUFSIZ: + + MB - this next block of code moved to rec_find so that same code can be + used to look for zip64 ec record. No need to include code above since + a zip64 ec record will only be looked for if it is a BIG file. + ---------------------------------------------------------------------------*/ + + } else { + found = + (rec_find(__G__ searchlen, end_central_sig, ECREC_SIZE) == 0 + ? TRUE : FALSE); + } /* end if (ziplen > INBUFSIZ) */ + +/*--------------------------------------------------------------------------- + Searched through whole region where signature should be without finding + it. Print informational message and die a horrible death. + ---------------------------------------------------------------------------*/ + + if (!found) { + if (uO.qflag || uO.zipinfo_mode) + Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); + Info(slide, 0x401, ((char *)slide, + LoadFarString(CentDirEndSigNotFound))); + return PK_ERR; /* failed */ + } + +/*--------------------------------------------------------------------------- + Found the signature, so get the end-central data before returning. Do + any necessary machine-type conversions (byte ordering, structure padding + compensation) by reading data into character array and copying to struct. + ---------------------------------------------------------------------------*/ + + G.real_ecrec_offset = G.cur_zipfile_bufstart + (G.inptr-G.inbuf); +#ifdef TEST + printf("\n found end-of-central-dir signature at offset %s (%sh)\n", + FmZofft(G.real_ecrec_offset, NULL, NULL), + FmZofft(G.real_ecrec_offset, FZOFFT_HEX_DOT_WID, "X")); + printf(" from beginning of file; offset %d (%.4Xh) within block\n", + G.inptr-G.inbuf, G.inptr-G.inbuf); +#endif + + if (readbuf(__G__ (char *)byterec, ECREC_SIZE+4) == 0) + return PK_EOF; + + G.ecrec.number_this_disk = + makeword(&byterec[NUMBER_THIS_DISK]); + G.ecrec.num_disk_start_cdir = + makeword(&byterec[NUM_DISK_WITH_START_CEN_DIR]); + G.ecrec.num_entries_centrl_dir_ths_disk = + makeword(&byterec[NUM_ENTRIES_CEN_DIR_THS_DISK]); + G.ecrec.total_entries_central_dir = + makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]); + G.ecrec.size_central_directory = + makelong(&byterec[SIZE_CENTRAL_DIRECTORY]); + G.ecrec.offset_start_central_directory = + makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]); + G.ecrec.zipfile_comment_length = + makeword(&byterec[ZIPFILE_COMMENT_LENGTH]); + + /* Now, we have to read the archive comment, BEFORE the file pointer + is moved away backwards to seek for a Zip64 ECLOC64 structure. + */ + if ( (error_in_archive = process_zip_cmmnt(__G)) > PK_WARN ) + return error_in_archive; + + /* Next: Check for existence of Zip64 end-of-cent-dir locator + ECLOC64. This structure must reside on the same volume as the + classic ECREC, at exactly (ECLOC64_SIZE+4) bytes in front + of the ECREC. + The ECLOC64 structure directs to the longer ECREC64 structure + A ECREC64 will ALWAYS exist for a proper Zip64 archive, as + the "Version Needed To Extract" field is required to be set + to 4.5 or higher whenever any Zip64 features are used anywhere + in the archive, so just check for that to see if this is a + Zip64 archive. + */ + result = find_ecrec64(__G__ searchlen+76); + /* 76 bytes for zip64ec & zip64 locator */ + if (result != PK_COOL) { + if (error_in_archive < result) + error_in_archive = result; + return error_in_archive; + } + + G.expect_ecrec_offset = G.ecrec.offset_start_central_directory + + G.ecrec.size_central_directory; + +#ifndef NO_ZIPINFO + if (uO.zipinfo_mode) { + /* In ZipInfo mode, additional info about the data found in the + end-of-central-directory areas is printed out. + */ + zi_end_central(__G); + } +#endif + + return error_in_archive; + +} /* end function find_ecrec() */ + + + + + +/********************************/ +/* Function process_zip_cmmnt() */ +/********************************/ + +static int process_zip_cmmnt(__G) /* return PK-type error code */ + __GDEF +{ + int error = PK_COOL; + + +/*--------------------------------------------------------------------------- + Get the zipfile comment (up to 64KB long), if any, and print it out. + ---------------------------------------------------------------------------*/ + +#ifdef WINDLL + /* for comment button: */ + if ((!G.fValidate) && (G.lpUserFunctions != NULL)) + G.lpUserFunctions->cchComment = G.ecrec.zipfile_comment_length; +#endif /* WINDLL */ + +#ifndef NO_ZIPINFO + /* ZipInfo, verbose format */ + if (uO.zipinfo_mode && uO.lflag > 9) { + /*------------------------------------------------------------------- + Get the zipfile comment, if any, and print it out. + (Comment may be up to 64KB long. May the fleas of a thousand + camels infest the arm-pits of anyone who actually takes advantage + of this fact.) + -------------------------------------------------------------------*/ + + if (!G.ecrec.zipfile_comment_length) + Info(slide, 0, ((char *)slide, LoadFarString(NoZipfileComment))); + else { + Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommentDesc), + G.ecrec.zipfile_comment_length)); + Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommBegin))); + if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) + error = PK_WARN; + Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommEnd))); + if (error) + Info(slide, 0, ((char *)slide, + LoadFarString(ZipfileCommTrunc2))); + } /* endif (comment exists) */ + + /* ZipInfo, non-verbose mode: print zipfile comment only if requested */ + } else if (G.ecrec.zipfile_comment_length && + (uO.zflag > 0) && uO.zipinfo_mode) { + if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(ZipfileCommTrunc1))); + error = PK_WARN; + } + } else +#endif /* !NO_ZIPINFO */ + if ( G.ecrec.zipfile_comment_length && + (uO.zflag > 0 +#ifndef WINDLL + || (uO.zflag == 0 +# ifndef NO_ZIPINFO + && !uO.zipinfo_mode +# endif +# ifdef TIMESTAMP + && !uO.T_flag +# endif + && !uO.qflag) +#endif /* !WINDLL */ + ) ) + { + if (do_string(__G__ G.ecrec.zipfile_comment_length, +#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) +# ifndef NO_ZIPINFO + (oU.zipinfo_mode ? DISPLAY : CHECK_AUTORUN) +# else + CHECK_AUTORUN +# endif +#else + DISPLAY +#endif + )) + { + Info(slide, 0x401, ((char *)slide, + LoadFarString(ZipfileCommTrunc1))); + error = PK_WARN; + } + } +#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) + else if (G.ecrec.zipfile_comment_length) { + if (do_string(__G__ G.ecrec.zipfile_comment_length, CHECK_AUTORUN_Q)) + { + Info(slide, 0x401, ((char *)slide, + LoadFarString(ZipfileCommTrunc1))); + error = PK_WARN; + } + } +#endif + return error; + +} /* end function process_zip_cmmnt() */ + + + + + +/************************************/ +/* Function process_cdir_file_hdr() */ +/************************************/ + +int process_cdir_file_hdr(__G) /* return PK-type error code */ + __GDEF +{ + int error; + + +/*--------------------------------------------------------------------------- + Get central directory info, save host and method numbers, and set flag + for lowercase conversion of filename, depending on the OS from which the + file is coming. + ---------------------------------------------------------------------------*/ + + if ((error = get_cdir_ent(__G)) != 0) + return error; + + G.pInfo->hostver = G.crec.version_made_by[0]; + G.pInfo->hostnum = MIN(G.crec.version_made_by[1], NUM_HOSTS); +/* extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS); */ + + G.pInfo->lcflag = 0; + if (uO.L_flag == 1) /* name conversion for monocase systems */ + switch (G.pInfo->hostnum) { + case FS_FAT_: /* PKZIP and zip -k store in uppercase */ + case CPM_: /* like MS-DOS, right? */ + case VM_CMS_: /* all caps? */ + case MVS_: /* all caps? */ + case TANDEM_: + case TOPS20_: + case VMS_: /* our Zip uses lowercase, but ASi's doesn't */ + /* case Z_SYSTEM_: ? */ + /* case QDOS_: ? */ + G.pInfo->lcflag = 1; /* convert filename to lowercase */ + break; + + default: /* AMIGA_, FS_HPFS_, FS_NTFS_, MAC_, UNIX_, ATARI_, */ + break; /* FS_VFAT_, ATHEOS_, BEOS_ (Z_SYSTEM_), THEOS_: */ + /* no conversion */ + } + else if (uO.L_flag > 1) /* let -LL force lower case for all names */ + G.pInfo->lcflag = 1; + + /* do Amigas (AMIGA_) also have volume labels? */ + if (IS_VOLID(G.crec.external_file_attributes) && + (G.pInfo->hostnum == FS_FAT_ || G.pInfo->hostnum == FS_HPFS_ || + G.pInfo->hostnum == FS_NTFS_ || G.pInfo->hostnum == ATARI_)) + { + G.pInfo->vollabel = TRUE; + G.pInfo->lcflag = 0; /* preserve case of volume labels */ + } else + G.pInfo->vollabel = FALSE; + + /* this flag is needed to detect archives made by "PKZIP for Unix" when + deciding which kind of codepage conversion has to be applied to + strings (see do_string() function in fileio.c) */ + G.pInfo->HasUxAtt = (G.crec.external_file_attributes & 0xffff0000L) != 0L; + +#ifdef UNICODE_SUPPORT + /* remember the state of GPB11 (General Purpuse Bit 11) which indicates + that the standard path and comment are UTF-8. */ + G.pInfo->GPFIsUTF8 + = (G.crec.general_purpose_bit_flag & (1 << 11)) == (1 << 11); +#endif + + return PK_COOL; + +} /* end function process_cdir_file_hdr() */ + + + + + +/***************************/ +/* Function get_cdir_ent() */ +/***************************/ + +static int get_cdir_ent(__G) /* return PK-type error code */ + __GDEF +{ + cdir_byte_hdr byterec; + + +/*--------------------------------------------------------------------------- + Read the next central directory entry and do any necessary machine-type + conversions (byte ordering, structure padding compensation--do so by + copying the data from the array into which it was read (byterec) to the + usable struct (crec)). + ---------------------------------------------------------------------------*/ + + if (readbuf(__G__ (char *)byterec, CREC_SIZE) == 0) + return PK_EOF; + + G.crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0]; + G.crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1]; + G.crec.version_needed_to_extract[0] = + byterec[C_VERSION_NEEDED_TO_EXTRACT_0]; + G.crec.version_needed_to_extract[1] = + byterec[C_VERSION_NEEDED_TO_EXTRACT_1]; + + G.crec.general_purpose_bit_flag = + makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]); + G.crec.compression_method = + makeword(&byterec[C_COMPRESSION_METHOD]); + G.crec.last_mod_dos_datetime = + makelong(&byterec[C_LAST_MOD_DOS_DATETIME]); + G.crec.crc32 = + makelong(&byterec[C_CRC32]); + G.crec.csize = + makelong(&byterec[C_COMPRESSED_SIZE]); + G.crec.ucsize = + makelong(&byterec[C_UNCOMPRESSED_SIZE]); + G.crec.filename_length = + makeword(&byterec[C_FILENAME_LENGTH]); + G.crec.extra_field_length = + makeword(&byterec[C_EXTRA_FIELD_LENGTH]); + G.crec.file_comment_length = + makeword(&byterec[C_FILE_COMMENT_LENGTH]); + G.crec.disk_number_start = + makeword(&byterec[C_DISK_NUMBER_START]); + G.crec.internal_file_attributes = + makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]); + G.crec.external_file_attributes = + makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]); /* LONG, not word! */ + G.crec.relative_offset_local_header = + makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]); + + return PK_COOL; + +} /* end function get_cdir_ent() */ + + + + + +/*************************************/ +/* Function process_local_file_hdr() */ +/*************************************/ + +int process_local_file_hdr(__G) /* return PK-type error code */ + __GDEF +{ + local_byte_hdr byterec; + + +/*--------------------------------------------------------------------------- + Read the next local file header and do any necessary machine-type con- + versions (byte ordering, structure padding compensation--do so by copy- + ing the data from the array into which it was read (byterec) to the + usable struct (lrec)). + ---------------------------------------------------------------------------*/ + + if (readbuf(__G__ (char *)byterec, LREC_SIZE) == 0) + return PK_EOF; + + G.lrec.version_needed_to_extract[0] = + byterec[L_VERSION_NEEDED_TO_EXTRACT_0]; + G.lrec.version_needed_to_extract[1] = + byterec[L_VERSION_NEEDED_TO_EXTRACT_1]; + + G.lrec.general_purpose_bit_flag = + makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]); + G.lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]); + G.lrec.last_mod_dos_datetime = makelong(&byterec[L_LAST_MOD_DOS_DATETIME]); + G.lrec.crc32 = makelong(&byterec[L_CRC32]); + G.lrec.csize = makelong(&byterec[L_COMPRESSED_SIZE]); + G.lrec.ucsize = makelong(&byterec[L_UNCOMPRESSED_SIZE]); + G.lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]); + G.lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]); + + if ((G.lrec.general_purpose_bit_flag & 8) != 0) { + /* can't trust local header, use central directory: */ + G.lrec.crc32 = G.pInfo->crc; + G.lrec.csize = G.pInfo->compr_size; + G.lrec.ucsize = G.pInfo->uncompr_size; + } + + G.csize = G.lrec.csize; + + return PK_COOL; + +} /* end function process_local_file_hdr() */ + + +/*******************************/ +/* Function getZip64Data() */ +/*******************************/ + +int getZip64Data(__G__ ef_buf, ef_len) + __GDEF + ZCONST uch *ef_buf; /* buffer containing extra field */ + unsigned ef_len; /* total length of extra field */ +{ + unsigned eb_id; + unsigned eb_len; + +/*--------------------------------------------------------------------------- + This function scans the extra field for zip64 information, ie 8-byte + versions of compressed file size, uncompressed file size, relative offset + and a 4-byte version of disk start number. + Sets both local header and central header fields. Not terribly clever, + but it means that this procedure is only called in one place. + ---------------------------------------------------------------------------*/ + + if (ef_len == 0 || ef_buf == NULL) + return PK_COOL; + + Trace((stderr,"\ngetZip64Data: scanning extra field of length %u\n", + ef_len)); + + while (ef_len >= EB_HEADSIZE) { + eb_id = makeword(EB_ID + ef_buf); + eb_len = makeword(EB_LEN + ef_buf); + + if (eb_len > (ef_len - EB_HEADSIZE)) { + /* discovered some extra field inconsistency! */ + Trace((stderr, + "getZip64Data: block length %u > rest ef_size %u\n", eb_len, + ef_len - EB_HEADSIZE)); + break; + } + if (eb_id == EF_PKSZ64) { + + int offset = EB_HEADSIZE; + + if (G.crec.ucsize == 0xffffffff || G.lrec.ucsize == 0xffffffff){ + G.lrec.ucsize = G.crec.ucsize = makeint64(offset + ef_buf); + offset += sizeof(G.crec.ucsize); + } + if (G.crec.csize == 0xffffffff || G.lrec.csize == 0xffffffff){ + G.csize = G.lrec.csize = G.crec.csize = makeint64(offset + ef_buf); + offset += sizeof(G.crec.csize); + } + if (G.crec.relative_offset_local_header == 0xffffffff){ + G.crec.relative_offset_local_header = makeint64(offset + ef_buf); + offset += sizeof(G.crec.relative_offset_local_header); + } + if (G.crec.disk_number_start == 0xffff){ + G.crec.disk_number_start = (zuvl_t)makelong(offset + ef_buf); + offset += sizeof(G.crec.disk_number_start); + } + } + + /* Skip this extra field block */ + ef_buf += (eb_len + EB_HEADSIZE); + ef_len -= (eb_len + EB_HEADSIZE); + } + + return PK_COOL; +} /* end function getZip64Data() */ + + +#ifdef UNICODE_SUPPORT + +/*******************************/ +/* Function getUnicodeData() */ +/*******************************/ + +int getUnicodeData(__G__ ef_buf, ef_len) + __GDEF + ZCONST uch *ef_buf; /* buffer containing extra field */ + unsigned ef_len; /* total length of extra field */ +{ + unsigned eb_id; + unsigned eb_len; + +/*--------------------------------------------------------------------------- + This function scans the extra field for Unicode information, ie UTF-8 + path extra fields. + + On return, G.unipath_filename = + NULL, if no Unicode path extra field or error + "", if the standard path is UTF-8 (free when done) + null-terminated UTF-8 path (free when done) + Return PK_COOL if no error. + ---------------------------------------------------------------------------*/ + + G.unipath_filename = NULL; + + if (ef_len == 0 || ef_buf == NULL) + return PK_COOL; + + Trace((stderr,"\ngetUnicodeData: scanning extra field of length %u\n", + ef_len)); + + while (ef_len >= EB_HEADSIZE) { + eb_id = makeword(EB_ID + ef_buf); + eb_len = makeword(EB_LEN + ef_buf); + + if (eb_len > (ef_len - EB_HEADSIZE)) { + /* discovered some extra field inconsistency! */ + Trace((stderr, + "getUnicodeData: block length %u > rest ef_size %u\n", eb_len, + ef_len - EB_HEADSIZE)); + break; + } + if (eb_id == EF_UNIPATH) { + + int offset = EB_HEADSIZE; + ush ULen = eb_len - 5; + ulg chksum = CRCVAL_INITIAL; + + /* version */ + G.unipath_version = (uch) *(offset + ef_buf); + offset += 1; + if (G.unipath_version > 1) { + /* can do only version 1 */ + Info(slide, 0x401, ((char *)slide, + LoadFarString(UnicodeVersionError))); + return PK_ERR; + } + + /* filename CRC */ + G.unipath_checksum = makelong(offset + ef_buf); + offset += 4; + + /* + * Compute 32-bit crc + */ + + chksum = crc32(chksum, (uch *)(G.filename_full), + strlen(G.filename_full)); + + /* If the checksums's don't match then likely filename has been + * modified and the Unicode Path is no longer valid. + */ + if (chksum != G.unipath_checksum) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(UnicodeMismatchError))); + if (G.unicode_mismatch == 1) { + /* warn and continue */ + } else if (G.unicode_mismatch == 2) { + /* ignore and continue */ + } else if (G.unicode_mismatch == 0) { + } + return PK_ERR; + } + + /* UTF-8 Path */ + if ((G.unipath_filename = malloc(ULen + 1)) == NULL) { + return PK_ERR; + } + if (ULen == 0) { + /* standard path is UTF-8 so use that */ + G.unipath_filename[0] = '\0'; + } else { + /* UTF-8 path */ + strncpy(G.unipath_filename, + (ZCONST char *)(offset + ef_buf), ULen); + G.unipath_filename[ULen] = '\0'; + } + } + + /* Skip this extra field block */ + ef_buf += (eb_len + EB_HEADSIZE); + ef_len -= (eb_len + EB_HEADSIZE); + } + + return PK_COOL; +} /* end function getUnicodeData() */ + + + + +#ifdef UNICODE_WCHAR + /*--------------------------------------------- + * Unicode conversion functions + * + * Based on functions provided by Paul Kienitz + * + *--------------------------------------------- + */ + +/* + NOTES APPLICABLE TO ALL STRING FUNCTIONS: + + All of the x_to_y functions take parameters for an output buffer and + its available length, and return an int. The value returned is the + length of the string that the input produces, which may be larger than + the provided buffer length. If the returned value is less than the + buffer length, then the contents of the buffer will be null-terminated; + otherwise, it will not be terminated and may be invalid, possibly + stopping in the middle of a multibyte sequence. + + In all cases you may pass NULL as the buffer and/or 0 as the length, if + you just want to learn how much space the string is going to require. + + The functions will return -1 if the input is invalid UTF-8 or cannot be + encoded as UTF-8. +*/ + +static int utf8_char_bytes OF((ZCONST char *utf8)); +static ulg ucs4_char_from_utf8 OF((ZCONST char **utf8)); +static int utf8_to_ucs4_string OF((ZCONST char *utf8, ulg *ucs4buf, + int buflen)); + +/* utility functions for managing UTF-8 and UCS-4 strings */ + + +/* utf8_char_bytes + * + * Returns the number of bytes used by the first character in a UTF-8 + * string, or -1 if the UTF-8 is invalid or null. + */ +static int utf8_char_bytes(utf8) + ZCONST char *utf8; +{ + int t, r; + unsigned lead; + + if (!utf8) + return -1; /* no input */ + lead = (unsigned char) *utf8; + if (lead < 0x80) + r = 1; /* an ascii-7 character */ + else if (lead < 0xC0) + return -1; /* error: trailing byte without lead byte */ + else if (lead < 0xE0) + r = 2; /* an 11 bit character */ + else if (lead < 0xF0) + r = 3; /* a 16 bit character */ + else if (lead < 0xF8) + r = 4; /* a 21 bit character (the most currently used) */ + else if (lead < 0xFC) + r = 5; /* a 26 bit character (shouldn't happen) */ + else if (lead < 0xFE) + r = 6; /* a 31 bit character (shouldn't happen) */ + else + return -1; /* error: invalid lead byte */ + for (t = 1; t < r; t++) + if ((unsigned char) utf8[t] < 0x80 || (unsigned char) utf8[t] >= 0xC0) + return -1; /* error: not enough valid trailing bytes */ + return r; +} + + +/* ucs4_char_from_utf8 + * + * Given a reference to a pointer into a UTF-8 string, returns the next + * UCS-4 character and advances the pointer to the next character sequence. + * Returns ~0 (= -1 in twos-complement notation) and does not advance the + * pointer when input is ill-formed. + */ +static ulg ucs4_char_from_utf8(utf8) + ZCONST char **utf8; +{ + ulg ret; + int t, bytes; + + if (!utf8) + return ~0L; /* no input */ + bytes = utf8_char_bytes(*utf8); + if (bytes <= 0) + return ~0L; /* invalid input */ + if (bytes == 1) + ret = **utf8; /* ascii-7 */ + else + ret = **utf8 & (0x7F >> bytes); /* lead byte of a multibyte sequence */ + (*utf8)++; + for (t = 1; t < bytes; t++) /* consume trailing bytes */ + ret = (ret << 6) | (*((*utf8)++) & 0x3F); + return (zwchar) ret; +} + + +#if 0 /* currently unused */ +/* utf8_from_ucs4_char - Convert UCS char to UTF-8 + * + * Returns the number of bytes put into utf8buf to represent ch, from 1 to 6, + * or -1 if ch is too large to represent. utf8buf must have room for 6 bytes. + */ +static int utf8_from_ucs4_char(utf8buf, ch) + char *utf8buf; + ulg ch; +{ + int trailing = 0; + int leadmask = 0x80; + int leadbits = 0x3F; + int tch = ch; + int ret; + + if (ch > 0x7FFFFFFFL) + return -1; /* UTF-8 can represent 31 bits */ + if (ch < 0x7F) + { + *utf8buf++ = (char) ch; /* ascii-7 */ + return 1; + } + do { + trailing++; + leadmask = (leadmask >> 1) | 0x80; + leadbits >>= 1; + tch >>= 6; + } while (tch & ~leadbits); + ret = trailing + 1; + /* produce lead byte */ + *utf8buf++ = (char) (leadmask | (ch >> (6 * trailing))); + while (--trailing >= 0) + /* produce trailing bytes */ + *utf8buf++ = (char) (0x80 | ((ch >> (6 * trailing)) & 0x3F)); + return ret; +} +#endif /* unused */ + + +/*===================================================================*/ + +/* utf8_to_ucs4_string - convert UTF-8 string to UCS string + * + * Return UCS count. Now returns int so can return -1. + */ +static int utf8_to_ucs4_string(utf8, ucs4buf, buflen) + ZCONST char *utf8; + ulg *ucs4buf; + int buflen; +{ + int count = 0; + + for (;;) + { + ulg ch = ucs4_char_from_utf8(&utf8); + if (ch == ~0L) + return -1; + else + { + if (ucs4buf && count < buflen) + ucs4buf[count] = ch; + if (ch == 0) + return count; + count++; + } + } +} + + +#if 0 /* currently unused */ +/* ucs4_string_to_utf8 + * + * + */ +static int ucs4_string_to_utf8(ucs4, utf8buf, buflen) + ZCONST ulg *ucs4; + char *utf8buf; + int buflen; +{ + char mb[6]; + int count = 0; + + if (!ucs4) + return -1; + for (;;) + { + int mbl = utf8_from_ucs4_char(mb, *ucs4++); + int c; + if (mbl <= 0) + return -1; + /* We could optimize this a bit by passing utf8buf + count */ + /* directly to utf8_from_ucs4_char when buflen >= count + 6... */ + c = buflen - count; + if (mbl < c) + c = mbl; + if (utf8buf && count < buflen) + strncpy(utf8buf + count, mb, c); + if (mbl == 1 && !mb[0]) + return count; /* terminating nul */ + count += mbl; + } +} + + +/* utf8_chars + * + * Wrapper: counts the actual unicode characters in a UTF-8 string. + */ +static int utf8_chars(utf8) + ZCONST char *utf8; +{ + return utf8_to_ucs4_string(utf8, NULL, 0); +} +#endif /* unused */ + +/* --------------------------------------------------- */ +/* Unicode Support + * + * These functions common for all Unicode ports. + * + * These functions should allocate and return strings that can be + * freed with free(). + * + * 8/27/05 EG + * + * Use zwchar for wide char which is unsigned long + * in zip.h and 32 bits. This avoids problems with + * different sizes of wchar_t. + */ + +#if 0 /* currently unused */ +/* is_ascii_string + * Checks if a string is all ascii + */ +int is_ascii_string(mbstring) + ZCONST char *mbstring; +{ + char *p; + uch c; + + for (p = mbstring; c = (uch)*p; p++) { + if (c > 0x7F) { + return 0; + } + } + return 1; +} + +/* local to UTF-8 */ +char *local_to_utf8_string(local_string) + ZCONST char *local_string; +{ + return wide_to_utf8_string(local_to_wide_string(local_string)); +} +# endif /* unused */ + +/* wide_to_escape_string + provides a string that represents a wide char not in local char set + + An initial try at an algorithm. Suggestions welcome. + + According to the standard, Unicode character points are restricted to + the number range from 0 to 0x10FFFF, respective 21 bits. + For a hexadecimal notation, 2 octets are sufficient for the mostly + used characters from the "Basic Multilingual Plane", all other + Unicode characters can be represented by 3 octets (= 6 hex digits). + The Unicode standard suggests to write Unicode character points + as 4 resp. 6 hex digits, preprended by "U+". + (e.g.: U+10FFFF for the highest character point, or U+0030 for the ASCII + digit "0") + + However, for the purpose of escaping non-ASCII chars in an ASCII character + stream, the "U" is not a very good escape initializer. Therefore, we + use the following convention within our Info-ZIP code: + + If not an ASCII char probably need 2 bytes at least. So if + a 2-byte wide encode it as 4 hex digits with a leading #U. If + needs 3 bytes then prefix the string with #L. So + #U1234 + is a 2-byte wide character with bytes 0x12 and 0x34 while + #L123456 + is a 3-byte wide character with bytes 0x12, 0x34, 0x56. + On Windows, wide that need two wide characters need to be converted + to a single number. + */ + + /* set this to the max bytes an escape can be */ +#define MAX_ESCAPE_BYTES 8 + +char *wide_to_escape_string(wide_char) + zwchar wide_char; +{ + int i; + zwchar w = wide_char; + uch b[sizeof(zwchar)]; + char d[3]; + char e[11]; + int len; + char *r; + + /* fill byte array with zeros */ + memzero(b, sizeof(zwchar)); + /* get bytes in right to left order */ + for (len = 0; w; len++) { + b[len] = (char)(w % 0x100); + w /= 0x100; + } + strcpy(e, "#"); + /* either 2 bytes or 3 bytes */ + if (len <= 2) { + len = 2; + strcat(e, "U"); + } else { + strcat(e, "L"); + } + for (i = len - 1; i >= 0; i--) { + sprintf(d, "%02x", b[i]); + strcat(e, d); + } + if ((r = malloc(strlen(e) + 1)) == NULL) { + return NULL; + } + strcpy(r, e); + return r; +} + +#if 0 /* currently unused */ +/* returns the wide character represented by the escape string */ +zwchar escape_string_to_wide(escape_string) + ZCONST char *escape_string; +{ + int i; + zwchar w; + char c; + int len; + ZCONST char *e = escape_string; + + if (e == NULL) { + return 0; + } + if (e[0] != '#') { + /* no leading # */ + return 0; + } + len = strlen(e); + /* either #U1234 or #L123456 format */ + if (len != 6 && len != 8) { + return 0; + } + w = 0; + if (e[1] == 'L') { + if (len != 8) { + return 0; + } + /* 3 bytes */ + for (i = 2; i < 8; i++) { + c = e[i]; + if (c < '0' || c > '9') { + return 0; + } + w = w * 0x10 + (zwchar)(c - '0'); + } + } else if (e[1] == 'U') { + /* 2 bytes */ + for (i = 2; i < 6; i++) { + c = e[i]; + if (c < '0' || c > '9') { + return 0; + } + w = w * 0x10 + (zwchar)(c - '0'); + } + } + return w; +} +#endif /* unused */ + +#ifndef WIN32 /* WIN32 supplies a special variant of this function */ +/* convert wide character string to multi-byte character string */ +char *wide_to_local_string(wide_string, escape_all) + ZCONST zwchar *wide_string; + int escape_all; +{ + int i; + wchar_t wc; + int b; + int state_dependent; + int wsize = 0; + int max_bytes = MB_CUR_MAX; + char buf[9]; + char *buffer = NULL; + char *local_string = NULL; + + for (wsize = 0; wide_string[wsize]; wsize++) ; + + if (max_bytes < MAX_ESCAPE_BYTES) + max_bytes = MAX_ESCAPE_BYTES; + + if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) { + return NULL; + } + + /* convert it */ + buffer[0] = '\0'; + /* set initial state if state-dependent encoding */ + wc = (wchar_t)'a'; + b = wctomb(NULL, wc); + if (b == 0) + state_dependent = 0; + else + state_dependent = 1; + for (i = 0; i < wsize; i++) { + if (sizeof(wchar_t) < 4 && wide_string[i] > 0xFFFF) { + /* wchar_t probably 2 bytes */ + /* could do surrogates if state_dependent and wctomb can do */ + wc = zwchar_to_wchar_t_default_char; + } else { + wc = (wchar_t)wide_string[i]; + } + b = wctomb(buf, wc); + if (escape_all) { + if (b == 1 && (uch)buf[0] <= 0x7f) { + /* ASCII */ + strncat(buffer, buf, b); + } else { + /* use escape for wide character */ + char *escape_string = wide_to_escape_string(wide_string[i]); + strcat(buffer, escape_string); + free(escape_string); + } + } else if (b > 0) { + /* multi-byte char */ + strncat(buffer, buf, b); + } else { + /* no MB for this wide */ + /* use escape for wide character */ + char *escape_string = wide_to_escape_string(wide_string[i]); + strcat(buffer, escape_string); + free(escape_string); + } + } + if ((local_string = (char *)malloc(strlen(buffer) + 1)) != NULL) { + strcpy(local_string, buffer); + } + free(buffer); + + return local_string; +} +#endif /* !WIN32 */ + +#if 0 /* currently unused */ +/* convert local string to display character set string */ +char *local_to_display_string(local_string) + ZCONST char *local_string; +{ + char *display_string; + + /* For Windows, OEM string should never be bigger than ANSI string, says + CharToOem description. + For all other ports, just make a copy of local_string. + */ + if ((display_string = (char *)malloc(strlen(local_string) + 1)) == NULL) { + return NULL; + } + + strcpy(display_string, local_string); + +#ifdef EBCDIC + { + char *ebc; + + if ((ebc = malloc(strlen(display_string) + 1)) == NULL) { + return NULL; + } + strtoebc(ebc, display_string); + free(display_string); + display_string = ebc; + } +#endif + + return display_string; +} +#endif /* unused */ + +/* UTF-8 to local */ +char *utf8_to_local_string(utf8_string, escape_all) + ZCONST char *utf8_string; + int escape_all; +{ + zwchar *wide = utf8_to_wide_string(utf8_string); + char *loc = wide_to_local_string(wide, escape_all); + free(wide); + return loc; +} + +#if 0 /* currently unused */ +/* convert multi-byte character string to wide character string */ +zwchar *local_to_wide_string(local_string) + ZCONST char *local_string; +{ + int wsize; + wchar_t *wc_string; + zwchar *wide_string; + + /* for now try to convert as string - fails if a bad char in string */ + wsize = mbstowcs(NULL, local_string, strlen(local_string) + 1); + if (wsize == (size_t)-1) { + /* could not convert */ + return NULL; + } + + /* convert it */ + if ((wc_string = (wchar_t *)malloc((wsize + 1) * sizeof(wchar_t))) == NULL) { + return NULL; + } + wsize = mbstowcs(wc_string, local_string, strlen(local_string) + 1); + wc_string[wsize] = (wchar_t) 0; + + /* in case wchar_t is not zwchar */ + if ((wide_string = (zwchar *)malloc((wsize + 1) * sizeof(zwchar))) == NULL) { + return NULL; + } + for (wsize = 0; wide_string[wsize] = (zwchar)wc_string[wsize]; wsize++) ; + wide_string[wsize] = (zwchar) 0; + free(wc_string); + + return wide_string; +} + + +/* convert wide string to UTF-8 */ +char *wide_to_utf8_string(wide_string) + ZCONST zwchar *wide_string; +{ + int mbcount; + char *utf8_string; + + /* get size of utf8 string */ + mbcount = ucs4_string_to_utf8(wide_string, NULL, 0); + if (mbcount == -1) + return NULL; + if ((utf8_string = (char *) malloc(mbcount + 1)) == NULL) { + return NULL; + } + mbcount = ucs4_string_to_utf8(wide_string, utf8_string, mbcount + 1); + if (mbcount == -1) + return NULL; + + return utf8_string; +} +#endif /* unused */ + +/* convert UTF-8 string to wide string */ +zwchar *utf8_to_wide_string(utf8_string) + ZCONST char *utf8_string; +{ + int wcount; + zwchar *wide_string; + + wcount = utf8_to_ucs4_string(utf8_string, NULL, 0); + if (wcount == -1) + return NULL; + if ((wide_string = (zwchar *) malloc((wcount + 1) * sizeof(zwchar))) + == NULL) { + return NULL; + } + wcount = utf8_to_ucs4_string(utf8_string, wide_string, wcount + 1); + + return wide_string; +} + +#endif /* UNICODE_WCHAR */ +#endif /* UNICODE_SUPPORT */ + + + + + +#ifdef USE_EF_UT_TIME + +#ifdef IZ_HAVE_UXUIDGID +static int read_ux3_value(dbuf, uidgid_sz, p_uidgid) + ZCONST uch *dbuf; /* buffer a uid or gid value */ + unsigned uidgid_sz; /* size of uid/gid value */ + ulg *p_uidgid; /* return storage: uid or gid value */ +{ + zusz_t uidgid64; + + switch (uidgid_sz) { + case 2: + *p_uidgid = (ulg)makeword(dbuf); + break; + case 4: + *p_uidgid = (ulg)makelong(dbuf); + break; + case 8: + uidgid64 = makeint64(dbuf); +#ifndef LARGE_FILE_SUPPORT + if (uidgid64 == (zusz_t)0xffffffffL) + return FALSE; +#endif + *p_uidgid = (ulg)uidgid64; + if ((zusz_t)(*p_uidgid) != uidgid64) + return FALSE; + break; + } + return TRUE; +} +#endif /* IZ_HAVE_UXUIDGID */ + + +/*******************************/ +/* Function ef_scan_for_izux() */ +/*******************************/ + +unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos_mdatetime, + z_utim, z_uidgid) + ZCONST uch *ef_buf; /* buffer containing extra field */ + unsigned ef_len; /* total length of extra field */ + int ef_is_c; /* flag indicating "is central extra field" */ + ulg dos_mdatetime; /* last_mod_file_date_time in DOS format */ + iztimes *z_utim; /* return storage: atime, mtime, ctime */ + ulg *z_uidgid; /* return storage: uid and gid */ +{ + unsigned flags = 0; + unsigned eb_id; + unsigned eb_len; + int have_new_type_eb = 0; + long i_time; /* buffer for Unix style 32-bit integer time value */ +#ifdef TIME_T_TYPE_DOUBLE + int ut_in_archive_sgn = 0; +#else + int ut_zip_unzip_compatible = FALSE; +#endif + +/*--------------------------------------------------------------------------- + This function scans the extra field for EF_TIME, EF_IZUNIX2, EF_IZUNIX, or + EF_PKUNIX blocks containing Unix-style time_t (GMT) values for the entry's + access, creation, and modification time. + If a valid block is found, the time stamps are copied to the iztimes + structure (provided the z_utim pointer is not NULL). + If a IZUNIX2 block is found or the IZUNIX block contains UID/GID fields, + and the z_uidgid array pointer is valid (!= NULL), the owner info is + transfered as well. + The presence of an EF_TIME or EF_IZUNIX2 block results in ignoring all + data from probably present obsolete EF_IZUNIX blocks. + If multiple blocks of the same type are found, only the information from + the last block is used. + The return value is a combination of the EF_TIME Flags field with an + additional flag bit indicating the presence of valid UID/GID info, + or 0 in case of failure. + ---------------------------------------------------------------------------*/ + + if (ef_len == 0 || ef_buf == NULL || (z_utim == 0 && z_uidgid == NULL)) + return 0; + + TTrace((stderr,"\nef_scan_for_izux: scanning extra field of length %u\n", + ef_len)); + + while (ef_len >= EB_HEADSIZE) { + eb_id = makeword(EB_ID + ef_buf); + eb_len = makeword(EB_LEN + ef_buf); + + if (eb_len > (ef_len - EB_HEADSIZE)) { + /* discovered some extra field inconsistency! */ + TTrace((stderr, + "ef_scan_for_izux: block length %u > rest ef_size %u\n", eb_len, + ef_len - EB_HEADSIZE)); + break; + } + + switch (eb_id) { + case EF_TIME: + flags &= ~0x0ff; /* ignore previous IZUNIX or EF_TIME fields */ + have_new_type_eb = 1; + if ( eb_len >= EB_UT_MINLEN && z_utim != NULL) { + unsigned eb_idx = EB_UT_TIME1; + TTrace((stderr,"ef_scan_for_izux: found TIME extra field\n")); + flags |= (ef_buf[EB_HEADSIZE+EB_UT_FLAGS] & 0x0ff); + if ((flags & EB_UT_FL_MTIME)) { + if ((eb_idx+4) <= eb_len) { + i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf); + eb_idx += 4; + TTrace((stderr," UT e.f. modification time = %ld\n", + i_time)); + +#ifdef TIME_T_TYPE_DOUBLE + if ((ulg)(i_time) & (ulg)(0x80000000L)) { + if (dos_mdatetime == DOSTIME_MINIMUM) { + ut_in_archive_sgn = -1; + z_utim->mtime = + (time_t)((long)i_time | (~(long)0x7fffffffL)); + } else if (dos_mdatetime >= DOSTIME_2038_01_18) { + ut_in_archive_sgn = 1; + z_utim->mtime = + (time_t)((ulg)i_time & (ulg)0xffffffffL); + } else { + ut_in_archive_sgn = 0; + /* cannot determine sign of mtime; + without modtime: ignore complete UT field */ + flags &= ~0x0ff; /* no time_t times available */ + TTrace((stderr, + " UT modtime range error; ignore e.f.!\n")); + break; /* stop scanning this field */ + } + } else { + /* cannot determine, safe assumption is FALSE */ + ut_in_archive_sgn = 0; + z_utim->mtime = (time_t)i_time; + } +#else /* !TIME_T_TYPE_DOUBLE */ + if ((ulg)(i_time) & (ulg)(0x80000000L)) { + ut_zip_unzip_compatible = + ((time_t)0x80000000L < (time_t)0L) + ? (dos_mdatetime == DOSTIME_MINIMUM) + : (dos_mdatetime >= DOSTIME_2038_01_18); + if (!ut_zip_unzip_compatible) { + /* UnZip interprets mtime differently than Zip; + without modtime: ignore complete UT field */ + flags &= ~0x0ff; /* no time_t times available */ + TTrace((stderr, + " UT modtime range error; ignore e.f.!\n")); + break; /* stop scanning this field */ + } + } else { + /* cannot determine, safe assumption is FALSE */ + ut_zip_unzip_compatible = FALSE; + } + z_utim->mtime = (time_t)i_time; +#endif /* ?TIME_T_TYPE_DOUBLE */ + } else { + flags &= ~EB_UT_FL_MTIME; + TTrace((stderr," UT e.f. truncated; no modtime\n")); + } + } + if (ef_is_c) { + break; /* central version of TIME field ends here */ + } + + if (flags & EB_UT_FL_ATIME) { + if ((eb_idx+4) <= eb_len) { + i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf); + eb_idx += 4; + TTrace((stderr," UT e.f. access time = %ld\n", + i_time)); +#ifdef TIME_T_TYPE_DOUBLE + if ((ulg)(i_time) & (ulg)(0x80000000L)) { + if (ut_in_archive_sgn == -1) + z_utim->atime = + (time_t)((long)i_time | (~(long)0x7fffffffL)); + } else if (ut_in_archive_sgn == 1) { + z_utim->atime = + (time_t)((ulg)i_time & (ulg)0xffffffffL); + } else { + /* sign of 32-bit time is unknown -> ignore it */ + flags &= ~EB_UT_FL_ATIME; + TTrace((stderr, + " UT access time range error: skip time!\n")); + } + } else { + z_utim->atime = (time_t)i_time; + } +#else /* !TIME_T_TYPE_DOUBLE */ + if (((ulg)(i_time) & (ulg)(0x80000000L)) && + !ut_zip_unzip_compatible) { + flags &= ~EB_UT_FL_ATIME; + TTrace((stderr, + " UT access time range error: skip time!\n")); + } else { + z_utim->atime = (time_t)i_time; + } +#endif /* ?TIME_T_TYPE_DOUBLE */ + } else { + flags &= ~EB_UT_FL_ATIME; + } + } + if (flags & EB_UT_FL_CTIME) { + if ((eb_idx+4) <= eb_len) { + i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf); + TTrace((stderr," UT e.f. creation time = %ld\n", + i_time)); +#ifdef TIME_T_TYPE_DOUBLE + if ((ulg)(i_time) & (ulg)(0x80000000L)) { + if (ut_in_archive_sgn == -1) + z_utim->ctime = + (time_t)((long)i_time | (~(long)0x7fffffffL)); + } else if (ut_in_archive_sgn == 1) { + z_utim->ctime = + (time_t)((ulg)i_time & (ulg)0xffffffffL); + } else { + /* sign of 32-bit time is unknown -> ignore it */ + flags &= ~EB_UT_FL_CTIME; + TTrace((stderr, + " UT creation time range error: skip time!\n")); + } + } else { + z_utim->ctime = (time_t)i_time; + } +#else /* !TIME_T_TYPE_DOUBLE */ + if (((ulg)(i_time) & (ulg)(0x80000000L)) && + !ut_zip_unzip_compatible) { + flags &= ~EB_UT_FL_CTIME; + TTrace((stderr, + " UT creation time range error: skip time!\n")); + } else { + z_utim->ctime = (time_t)i_time; + } +#endif /* ?TIME_T_TYPE_DOUBLE */ + } else { + flags &= ~EB_UT_FL_CTIME; + } + } + } + break; + + case EF_IZUNIX2: + if (have_new_type_eb == 0) { + flags &= ~0x0ff; /* ignore any previous IZUNIX field */ + have_new_type_eb = 1; + } +#ifdef IZ_HAVE_UXUIDGID + if (have_new_type_eb > 1) + break; /* IZUNIX3 overrides IZUNIX2 e.f. block ! */ + if (eb_len == EB_UX2_MINLEN && z_uidgid != NULL) { + z_uidgid[0] = (ulg)makeword((EB_HEADSIZE+EB_UX2_UID) + ef_buf); + z_uidgid[1] = (ulg)makeword((EB_HEADSIZE+EB_UX2_GID) + ef_buf); + flags |= EB_UX2_VALID; /* signal success */ + } +#endif + break; + + case EF_IZUNIX3: + /* new 3rd generation Unix ef */ + have_new_type_eb = 2; + + /* + Version 1 byte version of this extra field, currently 1 + UIDSize 1 byte Size of UID field + UID Variable UID for this entry + GIDSize 1 byte Size of GID field + GID Variable GID for this entry + */ + +#ifdef IZ_HAVE_UXUIDGID + if (eb_len >= EB_UX3_MINLEN + && z_uidgid != NULL + && (*((EB_HEADSIZE + 0) + ef_buf) == 1) + /* only know about version 1 */ + { + uch uid_size; + uch gid_size; + + uid_size = *((EB_HEADSIZE + 1) + ef_buf); + gid_size = *((EB_HEADSIZE + uid_size + 2) + ef_buf); + + flags &= ~0x0ff; /* ignore any previous UNIX field */ + + if ( read_ux3_value((EB_HEADSIZE + 2) + ef_buf, + uid_size, z_uidgid[0]) + && + read_ux3_value((EB_HEADSIZE + uid_size + 3) + ef_buf, + gid_size, z_uidgid[1]) ) + { + flags |= EB_UX2_VALID; /* signal success */ + } + } +#endif /* IZ_HAVE_UXUIDGID */ + break; + + case EF_IZUNIX: + case EF_PKUNIX: /* PKUNIX e.f. layout is identical to IZUNIX */ + if (eb_len >= EB_UX_MINLEN) { + TTrace((stderr,"ef_scan_for_izux: found %s extra field\n", + (eb_id == EF_IZUNIX ? "IZUNIX" : "PKUNIX"))); + if (have_new_type_eb > 0) { + break; /* Ignore IZUNIX extra field block ! */ + } + if (z_utim != NULL) { + flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME); + i_time = (long)makelong((EB_HEADSIZE+EB_UX_MTIME)+ef_buf); + TTrace((stderr," Unix EF modtime = %ld\n", i_time)); +#ifdef TIME_T_TYPE_DOUBLE + if ((ulg)(i_time) & (ulg)(0x80000000L)) { + if (dos_mdatetime == DOSTIME_MINIMUM) { + ut_in_archive_sgn = -1; + z_utim->mtime = + (time_t)((long)i_time | (~(long)0x7fffffffL)); + } else if (dos_mdatetime >= DOSTIME_2038_01_18) { + ut_in_archive_sgn = 1; + z_utim->mtime = + (time_t)((ulg)i_time & (ulg)0xffffffffL); + } else { + ut_in_archive_sgn = 0; + /* cannot determine sign of mtime; + without modtime: ignore complete UT field */ + flags &= ~0x0ff; /* no time_t times available */ + TTrace((stderr, + " UX modtime range error: ignore e.f.!\n")); + } + } else { + /* cannot determine, safe assumption is FALSE */ + ut_in_archive_sgn = 0; + z_utim->mtime = (time_t)i_time; + } +#else /* !TIME_T_TYPE_DOUBLE */ + if ((ulg)(i_time) & (ulg)(0x80000000L)) { + ut_zip_unzip_compatible = + ((time_t)0x80000000L < (time_t)0L) + ? (dos_mdatetime == DOSTIME_MINIMUM) + : (dos_mdatetime >= DOSTIME_2038_01_18); + if (!ut_zip_unzip_compatible) { + /* UnZip interpretes mtime differently than Zip; + without modtime: ignore complete UT field */ + flags &= ~0x0ff; /* no time_t times available */ + TTrace((stderr, + " UX modtime range error: ignore e.f.!\n")); + } + } else { + /* cannot determine, safe assumption is FALSE */ + ut_zip_unzip_compatible = FALSE; + } + z_utim->mtime = (time_t)i_time; +#endif /* ?TIME_T_TYPE_DOUBLE */ + i_time = (long)makelong((EB_HEADSIZE+EB_UX_ATIME)+ef_buf); + TTrace((stderr," Unix EF actime = %ld\n", i_time)); +#ifdef TIME_T_TYPE_DOUBLE + if ((ulg)(i_time) & (ulg)(0x80000000L)) { + if (ut_in_archive_sgn == -1) + z_utim->atime = + (time_t)((long)i_time | (~(long)0x7fffffffL)); + } else if (ut_in_archive_sgn == 1) { + z_utim->atime = + (time_t)((ulg)i_time & (ulg)0xffffffffL); + } else if (flags & 0x0ff) { + /* sign of 32-bit time is unknown -> ignore it */ + flags &= ~EB_UT_FL_ATIME; + TTrace((stderr, + " UX access time range error: skip time!\n")); + } + } else { + z_utim->atime = (time_t)i_time; + } +#else /* !TIME_T_TYPE_DOUBLE */ + if (((ulg)(i_time) & (ulg)(0x80000000L)) && + !ut_zip_unzip_compatible && (flags & 0x0ff)) { + /* atime not in range of UnZip's time_t */ + flags &= ~EB_UT_FL_ATIME; + TTrace((stderr, + " UX access time range error: skip time!\n")); + } else { + z_utim->atime = (time_t)i_time; + } +#endif /* ?TIME_T_TYPE_DOUBLE */ + } +#ifdef IZ_HAVE_UXUIDGID + if (eb_len >= EB_UX_FULLSIZE && z_uidgid != NULL) { + z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX_UID) + ef_buf); + z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX_GID) + ef_buf); + flags |= EB_UX2_VALID; + } +#endif /* IZ_HAVE_UXUIDGID */ + } + break; + + default: + break; + } + + /* Skip this extra field block */ + ef_buf += (eb_len + EB_HEADSIZE); + ef_len -= (eb_len + EB_HEADSIZE); + } + + return flags; +} + +#endif /* USE_EF_UT_TIME */ + + +#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS)) + +#define SPARKID_2 0x30435241 /* = "ARC0" */ + +/*******************************/ +/* Function getRISCOSexfield() */ +/*******************************/ + +zvoid *getRISCOSexfield(ef_buf, ef_len) + ZCONST uch *ef_buf; /* buffer containing extra field */ + unsigned ef_len; /* total length of extra field */ +{ + unsigned eb_id; + unsigned eb_len; + +/*--------------------------------------------------------------------------- + This function scans the extra field for a Acorn SPARK filetype ef-block. + If a valid block is found, the function returns a pointer to the start + of the SPARK_EF block in the extra field buffer. Otherwise, a NULL + pointer is returned. + ---------------------------------------------------------------------------*/ + + if (ef_len == 0 || ef_buf == NULL) + return NULL; + + Trace((stderr,"\ngetRISCOSexfield: scanning extra field of length %u\n", + ef_len)); + + while (ef_len >= EB_HEADSIZE) { + eb_id = makeword(EB_ID + ef_buf); + eb_len = makeword(EB_LEN + ef_buf); + + if (eb_len > (ef_len - EB_HEADSIZE)) { + /* discovered some extra field inconsistency! */ + Trace((stderr, + "getRISCOSexfield: block length %u > rest ef_size %u\n", eb_len, + ef_len - EB_HEADSIZE)); + break; + } + + if (eb_id == EF_SPARK && (eb_len == 24 || eb_len == 20)) { + if (makelong(EB_HEADSIZE + ef_buf) == SPARKID_2) { + /* Return a pointer to the valid SPARK filetype ef block */ + return (zvoid *)ef_buf; + } + } + + /* Skip this extra field block */ + ef_buf += (eb_len + EB_HEADSIZE); + ef_len -= (eb_len + EB_HEADSIZE); + } + + return NULL; +} + +#endif /* (RISCOS || ACORN_FTYPE_NFS) */ diff --git a/proginfo/3rdparty.bug b/proginfo/3rdparty.bug new file mode 100644 index 0000000..32e7823 --- /dev/null +++ b/proginfo/3rdparty.bug @@ -0,0 +1,114 @@ +Known, current PKZIP bugs/limitations: +------------------------------------- + + - PKUNZIP 2.04g is reported to corrupt some files when compressing them with + the -ex option; when tested, the files fail the CRC check, and comparison + with the original file shows bogus data (6K in one case) embedded in the + middle. PKWARE apparently characterized this as a "known problem." + + - PKUNZIP 2.04g considers volume labels valid only if originated on a FAT + file system, but other OSes and file systems (e.g., Amiga and OS/2 HPFS) + support volume labels, too. + + - PKUNZIP 2.04g can restore volume labels created by Zip 2.x but not by + PKZIP 2.04g (OS/2 DOS box only??). + + - PKUNZIP 2.04g gives an error message for stored directory entries created + under other OSes (although it creates the directory anyway), and PKZIP -vt + does not report the directory attribute bit as being set, even if it is. + + - PKZIP 2.04g mangles unknown extra fields (especially OS/2 extended attri- + butes) when adding new files to an existing zipfile [example: Walnut Creek + Hobbes March 1995 CD-ROM, FILE_ID.DIZ additions]. + + - PKUNZIP 2.04g is unable to detect or deal with prepended junk in a zipfile, + reporting CRC errors in valid compressed data. + + - PKUNZIP 2.04g (registered version) incorrectly updates/freshens the AV extra + field in authenticated archives. The resultant extra block length and total + extra field length are inconsistent. + + - [Windows version 2.01] Win95 long filenames (VFAT) are stored OK, but the + file system is always listed as ordinary DOS FAT. + + - [Windows version 2.50] NT long filenames (NTFS) are stored OK, but the + file system is always listed as ordinary DOS FAT. + + - PKZIP 2.04 for DOS encrypts using the OEM code page for 8-bit passwords, + while PKZIP 2.50 for Windows uses Latin-1 (ISO 8859-1). This means an + archive encrypted with an 8-bit password with one of the two PKZIP versions + cannot be decrypted with the other version. + + - PKZIP for Windows GUI (v 2.60), PKZIP for Windows command line (v 2.50) and + PKZIP for Unix (v 2.51) save the host's native file timestamps, but + only in a local extra field. Thus, timestamp-related selections (update + or freshen, both in extraction or archiving operations) use the DOS-format + localtime records in the Zip archives for comparisons. This may result + in wrong decisions of the program when updating archives that were + previously created in a different local time zone. + + - PKZIP releases newer than PKZIP for DOS 2.04g (PKZIP for Windows, both + GUI v 2.60 and console v 2.50; PKZIP for Unix v 2.51; probably others too) + use different code pages for storing filenames in central (OEM Codepage) + and local (ANSI / ISO 8859-1 Codepage) headers. When a stored filename + contains extended-ASCII characters, the local and central filename fields + do not match. As a consequence, Info-ZIP's Zip program considers such + archives as being corrupt and does not allow to modify them. Beginning + with release 5.41, Info-ZIP's UnZip contains a workaround to list AND + extract such archives with the correct filenames. + Maybe PKWARE has implemented this "feature" to allow extraction of their + "made-by-PKZIP for Unix/Windows" archives using old (v5.2 and earlier) + versions of Info-ZIP's UnZip for Unix/WinNT ??? (UnZip versions before + v 5.3 assumed that all archive entries were encoded in the codepage of + the UnZip program's host system.) + + - PKUNZIP 2.04g is reported to have problems with archives created on and/or + copied from Iomega ZIP drives (irony, eh?). + +Known, current WinZip bugs/limitations: +-------------------------------------- + + - [16-bit version 6.1a] NT short filenames (FAT) are stored OK, but the + file system is always listed as NTFS. + + - WinZip doesn't allow 8-bit passwords, which means it cannot decrypt an + archive created with an 8-bit password (by PKZIP or Info-ZIP's Zip). + + - WinZip (at least Versions 6.3 PL1, 7.0 SR1) fails to remove old extra + fields when freshening existing archive entries. When updating archives + created by Info-ZIP's Zip that contain UT time stamp extra field blocks, + UnZip cannot display or restore the updated (DOS) time stamps of the + freshened archive members. + +Known, current other third-party Zip utils bugs/limitations: +------------------------------------------------------------ + + - Asi's PKZip clones for Macintosh (versions 2.3 and 2.10d) are thoroughly + broken. They create invalid Zip archives! + a) For the first entry, both compressed size and uncompressed length + are recorded as 0, despite the fact that compressed data of non-zero + length has been added. + b) Their program creates extra fields with an (undocumented) internal + structure that violates the requirements of PKWARE's Zip format + specification document "appnote.txt": Their extra field seems to + contain pure data; the 4-byte block header consisting of block ID + and data length is missing. + +Possibly current PKZIP bugs: +--------------------------- + + - PKZIP (2.04g?) can silently ignore read errors on network drives, storing + the correct CRC and compressed length but an incorrect and inconsistent + uncompressed length. + + - PKZIP (2.04g?), when deleting files from within a zipfile on a Novell + drive, sometimes only zeros out the data while failing to shrink the + zipfile. + +Other limitations: +----------------- + + - PKZIP 1.x and 2.x encryption has been cracked (known-plaintext approach; + see http://www.cryptography.com/ for details). + +[many other bugs in PKZIP 1.0, 1.1, 1.93a, 2.04c and 2.04e] diff --git a/proginfo/CONTRIBS b/proginfo/CONTRIBS new file mode 100644 index 0000000..e971da0 --- /dev/null +++ b/proginfo/CONTRIBS @@ -0,0 +1,262 @@ +This is a partial list of contributors to Info-ZIP's UnZip and the code upon +which it is based. Others have also contributed, and if you are among them, +please let us know (don't be shy!). Everyone who contributed via the Info- +ZIP digest *should* now be listed here, but oversights are entirely possible. + + Mark Adler decryption, inflate, explode, funzip code; misc. casts + Steve Alpert VMS rms.h bugfix + Jeffrey Altman inflate.c huft_build() bugfix + Glenn Andrews MS-DOS makefiles; prototyping bugfix; bogus main() fix + Andrei Arkhipov Solaris 2.x package files + Joel Aycock descrip.mms bugfix + Vance Baarda Novell Netware 4.x NLM port + Eric Baatz Borland version() info; Solaris zipgrep packaging fix + Bob Babcock DOS volume-label code (FCBs) + Charles Bailey VMS_SEVERITY fix; VMSWILD () extension + Audrey Beck "WHERE" file info for AOL OS/2 forum + Myles Bennet Initial start of Zip64 and Large-File handling + Mike Bernardi Unix makefile entry; CIX uploads + James Birdsall extract.c/makefile/NT stuff, etc.; awesome beta tester + Allan Bjorklund in misc.c + Denise Blakeley Unix makefile entry + Wim Bonner original OS/2 port; Unix makefile entry + Paul Borman BSD/386 (BSDI) fixes; Unix makefile entry + Carlton Brewster mapname bugfix + Marcus Brinkmann Unix configuration fix for GNU/Hurd + Rodney Brown stdin-/dev/null bugfix; VMS error levels; CRC optimiz. + Stan Brown "zipinfo -M"/isatty(1) bugfix + Jens von Buelow port to MPE/iX, a Unix variant running on HP 3000 + John Bush first full Amiga port; FileDate; Amiga fixes; etc. + Christian Carey Unix makefile bugfix for install target (create dirs) + Valter Cavecchia Unix makefile entry + Rudolf Cejka Unix UID/GID extraction bugfix + Peter Chang optional UNIXBACKUP option (-B) + Kevin Cheng windll MBCS fix (setlocale initialization) + Andrey Chernov BSD 4.4 utime fix + Brad Clarke Win32 XX_flag bugfix; Borland debug code removal + Mark Clayton LynxOS (unix/Makefile update) + John Cowan mods to original match.c; other stuff? + Frank da Cruz xxu.c, on which original mapname.c was based + Bill Davidsen -q(q); mapname stuff; envargs; Xenix stuff; opts; etc. + Karl Davis Acorn RISC OS port + Jim Delahanty NTSD fixes + Harald Denker major Atari update/fixes + Matt "Doc" D'Errico AIX stuff, Unix makefile entry + Kim DeVaughn Unix makefile entry + Arjan de Vet various things, but I don't remember exactly what... + Frank Donahoe djgpp v2.x makefile; documentation updates + Jean-Michel Dubois THEOS port + James Dugal ZMEM stuff; unshrink bugfix; file perms stuff; etc. + Jim Dumser -z stuff; umask, opendir/Borland, UID fixes; etc. + Peter Eckel DOS buffer-overrun fix + Mark Edwards mapname.c, misc.c fixes; Unix makefile entry + Paul Eggert man pages update for POSIX compatibility + Gershon Elber Unix makefile entry + Patrick Ellis VMS usage fix (`-' vs. `/' options) + Shane Erstad Borland makefile bugfix + Thomas Esken Acorn typo fix + Bruce Evans Unix makefile entry + Derek Fawcus FlexOS port + David Feinleib Windows NT port + David Fenyes Unix makefile entry + Scott Field Windows NT security-descriptor support; CRC opts + Greg Flint Unix makefile entry + Carl Forde VM/CMS port debugging (with Christian Spieler) + Craig Forbes "UnZipToMem with no ucsize in local header" bugfix + Joe Foster Unix makefile bugfix + Gordon Fox Unix makefile bugfix for apollo target + Jeffrey Foy OS/2 stuff(?); [CP/M] + Mike Freeman VMS gcc makefiles; VMS bugfixes; etc. + Kevin Fritz Borland bugfixes; MS-DOS makefile fixes; etc. + Aaron Gaalswyk OS/2 checkdir() fix + Jean-loup Gailly decryption code; ReadByte replacement; much nagging :-) + Forrest Gehrke Unix makefile entry + Tim Geibelhaus Unix makefile entry + Henry Gessau flush/Fwrite/outcnt fixes; new NT port + Christian Ghisler inflate tweaks + Filip Gieszczykiewicz Unix makefile entry + Paul Gilmartin work-around for systems with broken catman/makewhatis + Hunter Goatley VMSCLI interface; VMS help/RUNOFF; list maintainer + Ian E. Gorman VM/CMS & MVS support + Bill Gould MVS file-format fixes + Michael Graff Unix makefile entry + Juan Manuel Guerrero DOS/WIN32 filename mapping fixes, device name handling + Giuseppe Guerrini LynxOS variant of Unix port + Richard H. Gumpertz Unix makefile entry + Walter Haidinger Amiga SAS/C fixes + Steve Hanna Macintosh stuff + Mark Hanning-Lee docs corrections, Unix Makefile fixes, "check" target + Guy Harris ZipInfo man-page typo fix + Greg Hartwig finished VM/CMS port + Robert Heath Windows GUI port (WizUnZip) + Dave Heiland new usage screen + Ron Henderson -a bugfix + Chris Herborth new Atari port; Atari fixes + Greg Hill docs update + Lon Hohberger security fix; security advice in man-page + John Hollow "WHERE" file path corrections + Jason Hood DOS screen-width support + Phil Howard Unix makefile entry + Jonathan Hudson SMS/QDOS port + Joe Isuzu Unix makefile entry + Kimio Itoh ZipInfo DIR_END bugfix for MSVC 4.0 + Aubrey Jaffer pixel, v7 targets + "jelmer" directory traversal security fix + Graham Jenkins Sequent Dynix/ptx bugfix + Peter Jones Unix makefile entry + Larry Jones ZMEM stuff; unimplod fix; crc_i386.S improvements; etc. + Warren Jones MKS bugfix + Kjetil J{\o}rgenson Makefile, OSF/1, NetBSD fixes; djgpp v2 mods; USE_VFAT + Bruce Kahn DOS floppy detection?; Unix makefile entry + Bob Kemp NOTINT16 rewrite; Unix makefile entry + J. Kercheval filmatch.c, on which second match.c was based + Paul Kienitz continuing general Amiga porting; Aztec C support; ASM + Raymond L. King WINDLL VB example maintenance + Mike Kincer AIX "ps2" bugfix + David Kirschbaum mapname port; general-purpose meddling; Python jokes + Paul Klahr Regulus port + Jim Knoble Turbo C++ makefile fix + Alvin Koh Borland C++ bugfixes + D. Krumbholz Acorn filetime conversion bug + Karel Kubat Linux strncasecmp bugfix + Bo Kullmar -z code; umask, do_string, BSD time, echo fixes; etc. + Peter Kunath DLL bugfixes, MSVC __asm support + Russell Lang OS/2 DLL calling-convention bugfix + Michael Lawler Borland version() info; process.c string fix; DOS fixes + Rudolf Lechleitner inflate memory leak fix + Johnny Lee Macintosh port; Win3.1 port; far strings; fixes; etc. + Alexander Lehmann makefile.tc bugfix; MS-DOS mapname() bugfix + Marty Leisner Unix perms fix for non-Unix dirs; man pages fonts; etc. + Fred Lenk docs e-mail bugfix + Daniel Lewart AIX stuff; compiler warnings + Jim Lill SCO Unix SYSNDIR bugfix + John Limpert Unix makefile entry + Hogan Long Borland preprocessor bugfix + Mike Long Unix Makefile installation bugfix + Warner Losh in misc.c + Dave Lovelace Data General AOS/VS port + Stew Loving-Gibbard original Windows 16-bit DLL port (non-WizUnZip version) + Dale Lutz \-to-/ conversion argv/argc bugfix + Tony Luu NT timezone bugfix + Igor Mandrichenko vms.c; many improvements and VMS modifications + Javier Manero fileio.c bugfix; MS-DOS version() bugfix; Watcom fix + Paul Manno makefile.tc fixes + Claude Marinier Unix makefile recursive fix + Fulvio Marino revised UnZip and ZipInfo man pages; Makefile entry + Carl Mascott original Unix port + Rafal Maszkowski Convex unzip.h fixes; Unix makefile entry + Jim Mathies signal handler installing bugfix + Eberhard Mattes handler() bugfix; docs update + Adrian Maull .NET C# example projects for Zip and UnZip dll + Peter Mauzey Unix makefile entry + Scott Maxwell version.h; massive reentrancy fixes; OS/2 DLL port + Bob Maynard 16-bit OS/2 pathname bugfix + Randy McCaskile Unix makefile entry + John McDonald OS/2 zip2exe script + Gene McManus -o code + Joe Meadows file.c, on which VMSmunch.c (timestamps) was based + Jason Merrill Sequent patches + Tom Metro corrupted-zipfile handler bugfix + Ian Miller VMS makefile portability bugfix (non-standard "edit") + Steve Miller Windows CE GUI port; memory leak bugfix; etc. + Ricky Mobley Unix makefile entry + Navin Modi Unix makefile entry + Sergio Monesi Acorn RISC OS port + Paul Motsuk Borland _rtl_chmod() fix + Anthony Naggs MS-DOS error handling stuff + Jim Neeland unused-variables fix; Unix makefile entry + Harry Nyberg Macintosh INSTALL info + Mauricio Ponzo UNIXBACKUP fix + NIIMI Satoshi Human68k port + Mike O'Carroll early OS/2 stuff + Michael D. O'Connor DOS ifdef/elif mismatch fix; makefile.tc fixes + "Moby" Dick O'Connor Unix makefile entry + Thomas Opheys Watcom C stat() bugfix + Humberto Ortiz-Zuazaga Linux port; permissions bugfix; missing declarations + Keith Owens MVS support and extensions + Fernando Papa inflate memory leaks + Rafael Pappalardo Convex CRYPT bugfix; Convex Makefile entry, useful info + Trevor Paquette Unix makefile entry + Keith Petersen Pyramid fixes; former Info-ZIP list maintainer + George Petrov initial MVS, VM/CMS ports (!) + Alan Phillips Unix makefile entry + Art Pina C Set/2 crypt.c optimization bug + Piet W. Plomp Unix chmod()/chown() fix; msc_dos fixes; much testing + Norbert Pueschel Amiga timelib + Clint Pulley Unix makefile entry + Antonio Querubin, Jr. descrip.mms (VMS makefile) + Alistair Rae Encore preprocessor bugfix + Eric S. Raymond manpage tweaks for DocBook compatibility + Wally Reiher timezone bugfix + Stephen Ritcey vms/README installation correction + Phil Ritzenthaler ANSIfication bugfix + Simon Roberts Windows CE 2.1x/3.0 cmdline port + David Robinson MSC 6.0 stat() bugfix + Jochen Roderburg floating-point BSD4_4 fix, Borland _timezone fix; etc. + Greg Roelofs maintainer/principal author; ZipInfo; unshrink; etc. + Kai Uwe Rommel "real" OS/2 port; many new compilers; bugfixes; etc. + Paul Roub first self-extracting code + Shimazaki Ryo human68k port updates + Steve Salisbury Win32 fixes; dual-mode SFX instruct.; variable INBUFSIZ + Darren Salt Acorn filetype <-> "Acorn NFS filetype" translation + Georg Sassen Amiga DICE compiler support + Jon Saxton date formats, OS/2 fixes + Tom Schmidt Unix makefile entry; Xenix and SunOS 3 target bugfixes + Hugh Schmidt VMS stuff + Doug Schuessler Tandem/NSK port fixes + Steven M. Schweda VMS: adapt new 7+ features, I/O performance enhanced + Martin Schulz original Atari port, symlinks bugfix + Charles Scripter various bug reports and bugfixes + Chris Seaman Unix time stuff + Richard Seay MS-DOS Quick C makefile + Peter Seebach fUnZip int main() bugfix + Matthew Seitz keep inherited SGID attrib for created dirs on Unix + Gisbert Selke Unix makefile entry + Alex Sergejew fileio.c, stat(), Makefile fixes; Down Under jokes :-) + Jim Seymour Borland OS/2 fixes + Mark Shadley Unix -X, FGETCH, DESTROYGLOBALS & Unix makefile fixes + Miki Shapiro DLL: zipfilehandle leak (unhandled lseek errors) + Timur Shaporev inflate optimizations + Eric Siegerman bugfix for Unix' port attribute mapper + Paul Slootman partial fix >2G handling on 64bit file offset systems + Dave Smith Tandem/NSK port + Fred Smith Coherent 4.0 fixes + Nick Smith return code for user abort (control-C) + Samuel H. Smith original unzip code (Pascal and C) for MS-DOS + Tuomo Soini file-not-matched bugfix + Jim Spath zipinfo -T century bugfix + Christian Spieler VMS, DOS, WIN32, VM/CMS, portability & performance + Cliff Stanford fileio.c umask bug + Jack Stansbury DEC Alpha NT makefile fix + Dan Statkus OS/2, MS-DOS mapname() ASCII 255 bugfix + Jochen Stein Unix makefile entry + Jim Steiner Unix makefile entry + Richard Stephen Unix makefile entry + Wayne Stewart "WHERE" file MS-DOS correction + Mike Strock Win32 MSVC 5.0 "build file"; typo fixes + E-Yen Tan djgpp1/GNUmake 3.71 bug work-around; DOS makefile.emx + Brian Tillman "WHERE" file VMS fix; make_unz.com portability bugfix + Cosmin Truta Cygwin support; various C & ASM fixes + Onno van der Linden many fixes, esp. Intel Unix and 386 DOS + Jim Van Zandt one of original man pages + Geraldo Veiga Pyramid strrchr/rindex + Erik-Jan Vens Unix makefile entry + Antoine Verheijen new Mac port; Mac bugfixes; MTS/EBCDIC stuff; etc. + Santiago Vila -t stderr/stdout fix + Rich Wales former Info-ZIP moderator and zip guy; MKS stuff + Frank Wancho original TOPS-20 port + Douglas Wegscheid djgpp 2.x USE_LFN compatibility fix + Yohanan Weininger docs update + Paul Weiss unzipsfx bugfix + Paul Wells original Amiga port for SAS/C and Lattice C (?) + Mike White Windows GUI port version 3; 16- and 32-bit Windows DLLs + Rainer Wilcke HP/UX termios bugfix; man-page fixes + Charles Wilson Cygwin support + Greg Woods man-pages bugfixes + Mark Wright original Netware 3.11 NLM port + Randy Wright Unix makefile entry + Meiwei Wu open() return bugfix + Steve Youngs win32 timestamp conversion bugfix + Clay Zahrobsky .zip/wildcard bugfix + Eli Zaretskii improvements to DOS-mode VFAT support; djgpp 2.x fixes + Martin P.J. Zinser VMS .hlp file for unzipsfx; MAKESFX.COM command file diff --git a/proginfo/Contents b/proginfo/Contents new file mode 100644 index 0000000..9107362 --- /dev/null +++ b/proginfo/Contents @@ -0,0 +1,13 @@ +Contents of the "proginfo" subdirectory for UnZip 5.42 and later: + + Contents this file + CONTRIBS list of contributors to UnZip + ZipPorts Info-ZIP rules and guidelines on contributions to the cause + 3rdparty.bug known bugs in PK[UN]ZIP, WinZip, etc. + defer.in info about the NEXTBYTE macro and defer/undefer_input functions + extrafld.txt info about all known "extra field" types + fileinfo.cms info about the VM/CMS file system, including record formats + nt.sd info about support for Windows NT's Security Descriptors (ACLs) + perform.dos relative performance of Zip and UnZip with various DOS compilers + timezone.txt explanation of the TZ environment variable for timezones + ziplimit.txt limits of the Zip archive format and InfoZip's implementation diff --git a/proginfo/ZipPorts b/proginfo/ZipPorts new file mode 100644 index 0000000..2d946d3 --- /dev/null +++ b/proginfo/ZipPorts @@ -0,0 +1,285 @@ +__________________________________________________________________________ + + This is the Info-ZIP file ZipPorts, last updated on 17 February 1996. +__________________________________________________________________________ + + +This document defines a set of rules and guidelines for those who wish to +contribute patches to Zip and UnZip (or even entire ports to new operating +systems). The list below is something between a style sheet and a "Miss +Manners" etiquette guide. While Info-ZIP encourages contributions and +fixes from anyone who finds something worth changing, we are also aware +of the fact that no two programmers have the programming style and that +unrestrained changes by a few dozen contributors would result in hideously +ugly (and unmaintainable) Frankenstein code. So consider the following an +attempt by the maintainers to maintain sanity as well as useful code. + +(The first version of this document was called either "ZipRules" or the +"No Feelthy ..." file and was compiled by David Kirschbaum in consulta- +tion with Mark Adler, Cave McNewt and others. The current incarnation +expands upon the original with insights gained from a few more years of +happy hacking...) + + +Summary: + + (0) The Platinum Rule: DON'T BREAK EXISTING PORTS +(0.1) The Golden Rule: DO UNTO THE CODE AS OTHERS HAVE DONE BEFORE +(0.2) The Silver Rule: DO UNTO THE LATEST BETA CODE +(0.3) The Bronze Rule: NO FEELTHY PIGGYBACKS + + (1) NO FEELTHY TABS + (2) NO FEELTHY CARRIAGE RETURNS + (3) NO FEELTHY 8-BIT CHARS + (4) NO FEELTHY LEFT-JUSTIFIED DASHES + (5) NO FEELTHY FANCY_FILENAMES + (6) NO FEELTHY NON-ZIPFILES AND NO FEELTHY E-MAIL BETAS + (7) NO FEELTHY E-MAIL BINARIES + + +Explanations: + + (0) The Platinum Rule: DON'T BREAK EXISTING PORTS + + No doubt about it, this is the one which really pisses us off and + pretty much guarantees that your port or patch will be ignored and/ + or laughed at. Examples range from the *really* severe cases which + "port" by ripping out all of the existing multi-OS code, to more + subtle oopers like relying on a local capability which doesn't exist + on other OSes or in older compilers (e.g., the use of ANSI "#elif" + or "#pragma" or "##" constructs, C++ comments, GNU extensions, etc.). + As to the former, use #ifdefs for your new code (see rule 0.3). And + as to the latter, trust us--there are few things we'd like better + than to be able to use some of the elegant "new" features out there + (many of which have been around for a decade or more). But our code + still compiles on machines dating back even longer, at least in spirit + --e.g., the AT&T 3B1 family and Dynix/ptx. Until we say otherwise, + dinosaurs are supported. + + +(0.1) The Golden Rule: DO UNTO THE CODE AS OTHERS HAVE DONE BEFORE + + In other words, try to fit into the local style of programming--no + matter how painful it may be. This includes cosmetic aspects like + indenting the same amount (both in the main C code and in the in- + clude files), using braces and comments similarly, NO TABS (see rule + #1), etc.; but also more substantive things like (for UnZip) putting + character strings into static (far) variables and using the LoadFar- + String macros to avoid overflowing limited MS-DOS data segments, and + using the ugly Info() macro instead of the more usual *printf() + functions so that dynamic-link-library ports are simpler. NEVER put + single-OS code (e.g., OS/2) of more than two or three lines into the + main (generic) modules; those are shared by everybody, and nobody else + cares about it or wants to see it. + + Note that not only do Zip and UnZip differ in these respects, so do + individual parts of each program. While it would be nice to have + global consistency, cosmetic changes are not a high priority; for + now we'll settle for local consistency--i.e., don't make things any + worse than they already are. + + Exception (BIG exception): single-letter variable names. Despite + the prevailing practice in much of Zip and parts of UnZip, and de- + spite the fact that one-letter variables allow you to pack really + cool, compact and complicated expressions onto one line, they also + make the code very difficult to maintain and are therefore *strongly* + discouraged. Don't ask us who is responsible in the first place; + while this sort of brain damage is not uncommon among former BASIC + programmers, it is nevertheless a lifelong embarrassment, and we do + try to pity the poor sod (that is, when we're not chasing bugs and + cursing him). :-) + + +(0.2) The Silver Rule: DO UNTO THE LATEST BETA CODE + + Few things are as annoying as receiving a large patch which obviously + represents a lot of time and careful work but which is relative to + an old version of Info-ZIP code. As wonderful as Larry Wall's patch + program is at applying context diffs to modified code, we regularly + make near-global changes and/or reorganize big chunks of the sources + (particularly in UnZip), and "patch" can't work miracles--big changes + invariably break any patch which is relative to an old version of the + code. + + Bottom line: contact the Info-ZIP core team FIRST (via the zip-bugs + e-mail address) and get up to date with the latest code before begin- + ning a big new port. And try to *stay* up to date while working on + your port--at least, as much as possible. + + +(0.3) The Bronze Rule: NO FEELTHY PIGGYBACKS + + UnZip is currently ported to something like 12 operating systems + (a few more or less depending on how one counts), and each of these, + with the possible exception of VM/CMS, has a unique macro identifying + it: AMIGA, ATARI_ST, __human68k__, MACOS, MSDOS, MVS, OS2, TOPS20, + UNIX, VMS, WIN32. Zip is moving in the same direction. New ports + should NOT piggyback one of the existing ports unless they are sub- + stantially similar--for example, Minix and Coherent are basically Unix + and therefore are included in the UNIX macro, but DOS djgpp ports and + OS/2 emx ports (both of which use the Unix-originated GNU C compiler + and often have "unix" defined by default) are obviously *not* Unix. + [The existing MTS port is a special exception; basically only one per- + son knows what MTS really is, and he's not telling. Presumably it's + not very close to Unix, but it's not worth arguing about it now.] + Along the same lines, neither OS/2 nor Human68K is the same as (or + even close to) MS-DOS. MVS and VM/CMS, on the other hand, are quite + similar to each other and are therefore combined in most places. + + Bottom line: when adding a new port (e.g., QDOS), create a new macro + for it ("QDOS"), a new subdirectory ("qdos") and a new source file for + OS-specific code ("qdos/qdos.c"). Use #ifdefs to fit any OS-specific + changes into the existing code (e.g., unzpriv.h). If it's close enough + to an existing port that piggybacking is a temptation, define a new + "combination macro" (e.g., "CMS_MVS") and replace the old macros as + required. (This last applies to UnZip, at least; the old preference + in Zip was fewer macros and long #ifdef lines, so talk to Onno or Jean- + loup about that.) See also rule 0.1. + + (Note that, for UnZip, new ports need not attempt to deal with all + features. Among other things, the wildcard-zipfile code in do_wild() + may be replaced with a supplied dummy version, since opendir/readdir/ + closedir() or the equivalent can be difficult to implement.) + + + (1) NO FEELTHY TABS + + Some editors and e-mail systems either have no capability to use + and/or display tab characters (ASCII 9) correctly, or they use non- + standard or variable-width tab columns, or other horrors. Some edi- + tors auto-convert spaces to tabs, after which the blind use of "diff + -c" results in a huge and mostly useless patch. Yes, *we* know about + diff's "-b" option, but not everyone does. And yes, we also know this + makes the source files bigger, even after compression; so be it. If + we *really* cared that much about the size of the sources, we'd still + be writing Unix-only utilities. + + Bottom line: use spaces, not tabs. + + Exception: some of the makefiles (the Unix one in particular) require + tabs as part of the syntax. + + Related utility programs: + Unix, OS/2 and MS-DOS: expand, unexpand. + MS-DOS: Buerg's TABS; Toad Hall's TOADSOFT. + And some editors have the conversion built-in. + + + (2) NO FEELTHY CARRIAGE RETURNS + + All source, documentation and other text files shall have Unix style + line endings (LF only, a.k.a. ctrl-J), not the DOS/OS2/NT CR+LF or Mac + CR-only line endings. + + Reason: "real programmers" in any environment can convert back and + forth between Unix and DOS/Mac style. All PC compilers but a few old + Borland versions can use either Unix or MS-DOS end-of-lines. Buerg's + LIST (file-display utility) for MS-DOS can use Unix or MS-DOS EOLs. + Both Zip and UnZip can convert line-endings as appropriate. But Unix + utilities like diff and patch die a horrible death (or produce horrible + output) if the target files have CRs. + + Related utilities: flip for Unix, OS/2 and MS-DOS; Unix "tr". + + Exceptions: documentation in pre-compiled binary distributions should + be in the local (target) format. + + + (3) NO FEELTHY 8-BIT CHARS + + Do all your editing in a plain-text ASCII editor. No WordPerfect, MS + Word, WordStar document mode, or other word processor files, thenkyew. + No desktop publishing. *Especially* no EBCDIC. No TIFFs, no GIFs, no + embedded pictures or dancing ladies (too bad, Cave Newt). [Sigh... -CN] + + Reason: compatibility with different consoles. My old XT clone is + the most limited! + + Exceptions: some Macintosh makefiles apparently require some 8-bit + characters; the Human68k port uses 8-bit characters for Kanji or Kana + comments (I think); etc. + + Related utilities: vi, emacs, EDLIN, Turbo C editor, other programmers' + editors, various word processor -> text conversion utilities. + + + (4) NO FEELTHY LEFT-JUSTIFIED DASHES + + Always precede repeated dashes (------) with one or more leading non- + dash characters: spaces, tabs, pound signs (#), comments (/*), what- + ever. + + Reason: sooner or later your source file will be e-mailed through an + undigestifier utility, most of which treat leading dashes as end-of- + message separators. We'd rather not have your code broken up into a + dozen separate untitled messages, thank you. + + + (5) NO FEELTHY FANCY_FILENAMES + + Assume the worst: that someone on a brain-damaged DOS system has to + work with everything your magic fingers produced. Keep the filenames + unimaginative and within MS-DOS limits (i.e., ordinary A..Z, 1..9, + "-$_!"-type characters, in the 8.3 "filename.ext" format). Mac and + Unix users, giggle all you want, but no spaces or multiple dots. + + Reason: compatibility with different file systems. MS-DOS FAT is the + most limited, with the exception of CompuServe (6.3, argh). + + Exceptions: slightly longer names are occasionally acceptable within + OS-specific subdirectories, but don't do that unless there's a good + reason for it. + + + (6) NO FEELTHY NON-ZIPFILES AND NO FEELTHY E-MAIL BETAS + + Beta testers and developers are in general expected to have both + ftp capability and the ability to deal with zipfiles. Those without + should either find a friend who does or else learn about ftp-mailers. + + Reason: the core development team barely has time to work on the + code, much less prepare oddball formats and/or mail betas out (and + the situation is getting worse, sigh). + + Exceptions: anyone seriously proposing to do a new port will be + given special treatment, particularly with respect to UnZip; we + obviously realize that bootstrapping a completely new port can be + quite difficult and have no desire to make it even harder due to + lack of access to the latest code (rule 0.2). + + Public releases of UnZip, on the other hand, will be available in + two formats: .tar.Z (16-bit compress'd tar) and .zip (either "plain" + or self-extracting). Zip sources and executables will generally only + be distributed in .zip format, since Zip is pretty much useless without + UnZip. + + + (7) NO FEELTHY E-MAIL BINARIES + + Binary files (e.g., executables, test zipfiles, etc.) should NEVER + be mailed raw. Where possible, they should be uploaded via ftp in + BINARY mode; if that's impossible, Mark's "ship" ASCII-encoder should + be used; and if that's unavailable, uuencode or xxencode should be + used. Weirdo NeXTmail, mailtool and MIME formats are also Right Out. + + Files larger than 50KB may need to be broken into pieces for mailing + (be sure to label them in order!), unless "ship" is used (it can + auto-split, label and mail files if told to do so). If Down Under + is involved, files must be broken into under-20KB chunks. + + Reasons: to prevent sounds of gagging mailers from resounding through- + out the land. To be relatively efficient in the binary->ASCII conver- + sion. (Yeah, yeah, I know, there's better conversions out there. But + not as widely known, and they often break on BITNET gateways.) + + Related utilities: ship, uuencode, uudecode, uuxfer20, quux, others. + Just make sure they don't leave embedded or trailing spaces (that is, + they should use the "`" character in place of ASCII 32). Otherwise + mailers are prone to truncate or whatever. + + +Greg Roelofs (a.k.a. Cave Newt) +Info-ZIP UnZip maintainer + +David Kirschbaum +former Info-ZIP Coordinator diff --git a/proginfo/defer.in b/proginfo/defer.in new file mode 100644 index 0000000..a4e1d27 --- /dev/null +++ b/proginfo/defer.in @@ -0,0 +1,45 @@ +[Regarding an optimization to the bounds-checking code in the core + NEXTBYTE macro, which code is absolutely vital to the proper processing + of corrupt zipfiles (lack of checking can result in an infinite loop) + but which also slows processing.] + + +The key to the solution is a pair of small functions called +defer_leftover_input() and undefer_input(). The idea is, whenever +you are going to be processing input using NEXTBYTE, you call +defer_leftover_input(), and whenever you are going to process input by +any other means, such as readbuf(), ZLSEEK, or directly reading stuff +into G.inbuf, you call undefer_input(). What defer_leftover_input() +does is adjust G.incnt so that any data beyond the current end of file +is not visible. undefer_input() restores it to visibility. So when +you're calling NEXTBYTE (or NEEDBITS or READBITS), an end-of-data +condition only occurs at the same time as an end-of-buffer condition, +and can be handled inside readbyte() instead of needing a check in the +NEXTBYTE macro. Note: none of this applies to fUnZip. + +In order for this to work, certain conditions have to be met: + + 1) NEXTBYTE input must not be mixed with other forms of input involving + G.inptr and G.incnt. They must be separated by defer/undefer. + + I believe this condition is fully met by simply bracketing the central + part of extract_or_test_member with defer/undefer, around the part + where the actual decompression is done, and another defer/undefer pair + in decrypt() around the reading of the RAND_HEADER_LEN password bytes. + + When USE_ZLIB is defined, I think that calls of fillinbuf() must be + bracketed by defer/undefer. + + 2) G.csize must not be assumed to contain the number of bytes left to + process, when decompressing with NEXTBYTE. Instead, it contains + the number of bytes left after the current buffer is exausted. To + check the number of bytes remaining, use (G.csize + G.incnt). + + I believe the only places this change was needed were in explode.c, + mostly in the check at the end of each explode function that tests + whether the correct number of bytes has been read. G.incnt will + normally be zero at that time anyway. The other place is the line + that says "bd = G.csize > 200000L ? 8 : 7;" but that's just a rough + heuristic anyway. + +[Paul Kienitz] diff --git a/proginfo/extrafld.txt b/proginfo/extrafld.txt new file mode 100644 index 0000000..972950d --- /dev/null +++ b/proginfo/extrafld.txt @@ -0,0 +1,1608 @@ +The following are the known types of zipfile extra fields as of this +writing. Extra fields are documented in PKWARE's appnote.txt and are +intended to allow for backward- and forward-compatible extensions to +the zipfile format. Multiple extra-field types may be chained together, +provided that the total length of all extra-field data is less than 64KB. +(In fact, PKWARE requires that the total length of the entire file header, +including timestamp, file attributes, filename, comment, extra field, etc., +be no more than 64KB.) + +Each extra-field type (or subblock) must contain a four-byte header con- +sisting of a two-byte header ID and a two-byte length (little-endian) for +the remaining data in the subblock. If there are additional subblocks +within the extra field, the header for each one will appear immediately +following the data for the previous subblock (i.e., with no padding for +alignment). + +All integer fields in the descriptions below are in little-endian (Intel) +format unless otherwise specified. Note that "Short" means two bytes, +"Long" means four bytes, and "Long-Long" means eight bytes, regardless +of their native sizes. Unless specifically noted, all integer fields should +be interpreted as unsigned (non-negative) numbers. + +Christian Spieler, Ed Gordon, 20080717 + + ------------------------- + + Header ID's of 0 thru 31 are reserved for use by PKWARE. + The remaining ID's can be used by third party vendors for + proprietary usage. + + The current Header ID mappings defined by PKWARE are: + + 0x0001 Zip64 extended information extra field + 0x0007 AV Info + 0x0008 Reserved for extended language encoding data (PFS) + 0x0009 OS/2 extended attributes (also Info-ZIP) + 0x000a NTFS (Win9x/WinNT FileTimes) + 0x000c OpenVMS (also Info-ZIP) + 0x000d UNIX + 0x000e Reserved for file stream and fork descriptors + 0x000f Patch Descriptor + 0x0014 PKCS#7 Store for X.509 Certificates + 0x0015 X.509 Certificate ID and Signature for + individual file + 0x0016 X.509 Certificate ID for Central Directory + 0x0017 Strong Encryption Header + 0x0018 Record Management Controls + 0x0019 PKCS#7 Encryption Recipient Certificate List + 0x0065 IBM S/390 (Z390), AS/400 (I400) attributes + - uncompressed + 0x0066 Reserved for IBM S/390 (Z390), AS/400 (I400) + attributes - compressed + 0x4690 POSZIP 4690 (reserved) + + The Header ID mappings defined by Info-ZIP and third parties are: + + 0x07c8 Info-ZIP Macintosh (old, J. Lee) + 0x2605 ZipIt Macintosh (first version) + 0x2705 ZipIt Macintosh v 1.3.5 and newer (w/o full filename) + 0x2805 ZipIt Macintosh 1.3.5+ + 0x334d Info-ZIP Macintosh (new, D. Haase's 'Mac3' field) + 0x4154 Tandem NSK + 0x4341 Acorn/SparkFS (David Pilling) + 0x4453 Windows NT security descriptor (binary ACL) + 0x4704 VM/CMS + 0x470f MVS + 0x4854 Theos, old inofficial port + 0x4b46 FWKCS MD5 (see below) + 0x4c41 OS/2 access control list (text ACL) + 0x4d49 Info-ZIP OpenVMS (obsolete) + 0x4d63 Macintosh SmartZIP, by Macro Bambini + 0x4f4c Xceed original location extra field + 0x5356 AOS/VS (binary ACL) + 0x5455 extended timestamp + 0x554e Xceed unicode extra field + 0x5855 Info-ZIP UNIX (original; also OS/2, NT, etc.) + 0x6375 Info-ZIP UTF-8 comment field + 0x6542 BeOS (BeBox, PowerMac, etc.) + 0x6854 Theos + 0x7075 Info-ZIP UTF-8 name field + 0x7441 AtheOS (AtheOS/Syllable attributes) + 0x756e ASi UNIX + 0x7855 Info-ZIP UNIX (16-bit UID/GID info) + 0x7875 Info-ZIP UNIX 3rd generation (generic UID/GID, ...) + 0xa220 Microsoft Open Packaging Growth Hint + 0xfb4a SMS/QDOS + +The following are detailed descriptions of the known extra-field block types: + + -Zip64 Extended Information Extra Field (0x0001): + =============================================== + + The following is the layout of the zip64 extended + information "extra" block. If one of the size or + offset fields in the Local or Central directory + record is too small to hold the required data, + a zip64 extended information record is created. + The order of the fields in the zip64 extended + information record is fixed, but the fields will + only appear if the corresponding Local or Central + directory record field is set to 0xFFFF or 0xFFFFFFFF. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (ZIP64) 0x0001 2 bytes Tag for this "extra" block type + Size 2 bytes Size of this "extra" block + Original + Size 8 bytes Original uncompressed file size + Compressed + Size 8 bytes Size of compressed data + Relative Header + Offset 8 bytes Offset of local header record + Disk Start + Number 4 bytes Number of the disk on which + this file starts + + This entry in the Local header must include BOTH original + and compressed file size fields. If encrypting the + central directory and bit 13 of the general purpose bit + flag is set indicating masking, the value stored in the + Local Header for the original file size will be zero. + + + -OS/2 Extended Attributes Extra Field (0x0009): + ============================================= + + The following is the layout of the OS/2 extended attributes "extra" + block. (Last Revision 19960922) + + Note: all fields stored in Intel low-byte/high-byte order. + + Local-header version: + + Value Size Description + ----- ---- ----------- + (OS/2) 0x0009 Short tag for this extra block type + TSize Short total data size for this block + BSize Long uncompressed EA data size + CType Short compression type + EACRC Long CRC value for uncompressed EA data + (var.) variable compressed EA data + + Central-header version: + + Value Size Description + ----- ---- ----------- + (OS/2) 0x0009 Short tag for this extra block type + TSize Short total data size for this block (4) + BSize Long size of uncompressed local EA data + + The value of CType is interpreted according to the "compression + method" section above; i.e., 0 for stored, 8 for deflated, etc. + + The OS/2 extended attribute structure (FEA2LIST) is + compressed and then stored in its entirety within this + structure. There will only ever be one "block" of data in + the variable-length field. + + + -OS/2 Access Control List Extra Field: + ==================================== + + The following is the layout of the OS/2 ACL extra block. + (Last Revision 19960922) + + Local-header version: + + Value Size Description + ----- ---- ----------- + (ACL) 0x4c41 Short tag for this extra block type ("AL") + TSize Short total data size for this block + BSize Long uncompressed ACL data size + CType Short compression type + EACRC Long CRC value for uncompressed ACL data + (var.) variable compressed ACL data + + Central-header version: + + Value Size Description + ----- ---- ----------- + (ACL) 0x4c41 Short tag for this extra block type ("AL") + TSize Short total data size for this block (4) + BSize Long size of uncompressed local ACL data + + The value of CType is interpreted according to the "compression + method" section above; i.e., 0 for stored, 8 for deflated, etc. + + The uncompressed ACL data consist of a text header of the form + "ACL1:%hX,%hd\n", where the first field is the OS/2 ACCINFO acc_attr + member and the second is acc_count, followed by acc_count strings + of the form "%s,%hx\n", where the first field is acl_ugname (user + group name) and the second acl_access. This block type will be + extended for other operating systems as needed. + + + -Windows NT Security Descriptor Extra Field (0x4453): + =================================================== + + The following is the layout of the NT Security Descriptor (another + type of ACL) extra block. (Last Revision 19960922) + + Local-header version: + + Value Size Description + ----- ---- ----------- + (SD) 0x4453 Short tag for this extra block type ("SD") + TSize Short total data size for this block + BSize Long uncompressed SD data size + Version Byte version of uncompressed SD data format + CType Short compression type + EACRC Long CRC value for uncompressed SD data + (var.) variable compressed SD data + + Central-header version: + + Value Size Description + ----- ---- ----------- + (SD) 0x4453 Short tag for this extra block type ("SD") + TSize Short total data size for this block (4) + BSize Long size of uncompressed local SD data + + The value of CType is interpreted according to the "compression + method" section above; i.e., 0 for stored, 8 for deflated, etc. + Version specifies how the compressed data are to be interpreted + and allows for future expansion of this extra field type. Currently + only version 0 is defined. + + For version 0, the compressed data are to be interpreted as a single + valid Windows NT SECURITY_DESCRIPTOR data structure, in self-relative + format. + + + -PKWARE Win95/WinNT Extra Field (0x000a): + ======================================= + + The following description covers PKWARE's "NTFS" attributes + "extra" block, introduced with the release of PKZIP 2.50 for + Windows. (Last Revision 20001118) + + (Note: At this time the Mtime, Atime and Ctime values may + be used on any WIN32 system.) + [Info-ZIP note: In the current implementations, this field has + a fixed total data size of 32 bytes and is only stored as local + extra field.] + + Value Size Description + ----- ---- ----------- + (NTFS) 0x000a Short Tag for this "extra" block type + TSize Short Total Data Size for this block + Reserved Long for future use + Tag1 Short NTFS attribute tag value #1 + Size1 Short Size of attribute #1, in bytes + (var.) SubSize1 Attribute #1 data + . + . + . + TagN Short NTFS attribute tag value #N + SizeN Short Size of attribute #N, in bytes + (var.) SubSizeN Attribute #N data + + For NTFS, values for Tag1 through TagN are as follows: + (currently only one set of attributes is defined for NTFS) + + Tag Size Description + ----- ---- ----------- + 0x0001 2 bytes Tag for attribute #1 + Size1 2 bytes Size of attribute #1, in bytes (24) + Mtime 8 bytes 64-bit NTFS file last modification time + Atime 8 bytes 64-bit NTFS file last access time + Ctime 8 bytes 64-bit NTFS file creation time + + The total length for this block is 28 bytes, resulting in a + fixed size value of 32 for the TSize field of the NTFS block. + + The NTFS filetimes are 64-bit unsigned integers, stored in Intel + (least significant byte first) byte order. They determine the + number of 1.0E-07 seconds (1/10th microseconds!) past WinNT "epoch", + which is "01-Jan-1601 00:00:00 UTC". + + + -PKWARE OpenVMS Extra Field (0x000c): + =================================== + + The following is the layout of PKWARE's OpenVMS attributes + "extra" block. (Last Revision 12/17/91) + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (VMS) 0x000c Short Tag for this "extra" block type + TSize Short Total Data Size for this block + CRC Long 32-bit CRC for remainder of the block + Tag1 Short OpenVMS attribute tag value #1 + Size1 Short Size of attribute #1, in bytes + (var.) Size1 Attribute #1 data + . + . + . + TagN Short OpenVMS attribute tag value #N + SizeN Short Size of attribute #N, in bytes + (var.) SizeN Attribute #N data + + Rules: + + 1. There will be one or more of attributes present, which + will each be preceded by the above TagX & SizeX values. + These values are identical to the ATR$C_XXXX and + ATR$S_XXXX constants which are defined in ATR.H under + OpenVMS C. Neither of these values will ever be zero. + + 2. No word alignment or padding is performed. + + 3. A well-behaved PKZIP/OpenVMS program should never produce + more than one sub-block with the same TagX value. Also, + there will never be more than one "extra" block of type + 0x000c in a particular directory record. + + + -Info-ZIP VMS Extra Field: + ======================== + + The following is the layout of Info-ZIP's VMS attributes extra + block for VAX or Alpha AXP. The local-header and central-header + versions are identical. (Last Revision 19960922) + + Value Size Description + ----- ---- ----------- + (VMS2) 0x4d49 Short tag for this extra block type ("JM") + TSize Short total data size for this block + ID Long block ID + Flags Short info bytes + BSize Short uncompressed block size + Reserved Long (reserved) + (var.) variable compressed VMS file-attributes block + + The block ID is one of the following unterminated strings: + + "VFAB" struct FAB + "VALL" struct XABALL + "VFHC" struct XABFHC + "VDAT" struct XABDAT + "VRDT" struct XABRDT + "VPRO" struct XABPRO + "VKEY" struct XABKEY + "VMSV" version (e.g., "V6.1"; truncated at hyphen) + "VNAM" reserved + + The lower three bits of Flags indicate the compression method. The + currently defined methods are: + + 0 stored (not compressed) + 1 simple "RLE" + 2 deflated + + The "RLE" method simply replaces zero-valued bytes with zero-valued + bits and non-zero-valued bytes with a "1" bit followed by the byte + value. + + The variable-length compressed data contains only the data corre- + sponding to the indicated structure or string. Typically multiple + VMS2 extra fields are present (each with a unique block type). + + + -Info-ZIP Macintosh Extra Field: + ============================== + + The following is the layout of the (old) Info-ZIP resource-fork extra + block for Macintosh. The local-header and central-header versions + are identical. (Last Revision 19960922) + + Value Size Description + ----- ---- ----------- + (Mac) 0x07c8 Short tag for this extra block type + TSize Short total data size for this block + "JLEE" beLong extra-field signature + FInfo 16 bytes Macintosh FInfo structure + CrDat beLong HParamBlockRec fileParam.ioFlCrDat + MdDat beLong HParamBlockRec fileParam.ioFlMdDat + Flags beLong info bits + DirID beLong HParamBlockRec fileParam.ioDirID + VolName 28 bytes volume name (optional) + + All fields but the first two are in native Macintosh format + (big-endian Motorola order, not little-endian Intel). The least + significant bit of Flags is 1 if the file is a data fork, 0 other- + wise. In addition, if this extra field is present, the filename + has an extra 'd' or 'r' appended to indicate data fork or resource + fork. The 28-byte VolName field may be omitted. + + + -ZipIt Macintosh Extra Field (long): + ================================== + + The following is the layout of the ZipIt extra block for Macintosh. + The local-header and central-header versions are identical. + (Last Revision 19970130) + + Value Size Description + ----- ---- ----------- + (Mac2) 0x2605 Short tag for this extra block type + TSize Short total data size for this block + "ZPIT" beLong extra-field signature + FnLen Byte length of FileName + FileName variable full Macintosh filename + FileType Byte[4] four-byte Mac file type string + Creator Byte[4] four-byte Mac creator string + + + -ZipIt Macintosh Extra Field (short, for files): + ============================================== + + The following is the layout of a shortened variant of the + ZipIt extra block for Macintosh (without "full name" entry). + This variant is used by ZipIt 1.3.5 and newer for entries of + files (not directories) that do not have a MacBinary encoded + file. The local-header and central-header versions are identical. + (Last Revision 20030602) + + Value Size Description + ----- ---- ----------- + (Mac2b) 0x2705 Short tag for this extra block type + TSize Short total data size for this block (min. 12) + "ZPIT" beLong extra-field signature + FileType Byte[4] four-byte Mac file type string + Creator Byte[4] four-byte Mac creator string + fdFlags beShort attributes from FInfo.frFlags, + may be omitted + 0x0000 beShort reserved, may be omitted + + + -ZipIt Macintosh Extra Field (short, for directories): + ==================================================== + + The following is the layout of a shortened variant of the + ZipIt extra block for Macintosh used only for directory + entries. This variant is used by ZipIt 1.3.5 and newer to + save some optional Mac-specific information about directories. + The local-header and central-header versions are identical. + + Value Size Description + ----- ---- ----------- + (Mac2c) 0x2805 Short tag for this extra block type + TSize Short total data size for this block (12) + "ZPIT" beLong extra-field signature + frFlags beShort attributes from DInfo.frFlags, may + be omitted + View beShort ZipIt view flag, may be omitted + + + The View field specifies ZipIt-internal settings as follows: + + Bits of the Flags: + bit 0 if set, the folder is shown expanded (open) + when the archive contents are viewed in ZipIt. + bits 1-15 reserved, zero; + + + -Info-ZIP Macintosh Extra Field (new): + ==================================== + + The following is the layout of the (new) Info-ZIP extra + block for Macintosh, designed by Dirk Haase. + All values are in little-endian. + (Last Revision 19981005) + + Local-header version: + + Value Size Description + ----- ---- ----------- + (Mac3) 0x334d Short tag for this extra block type ("M3") + TSize Short total data size for this block + BSize Long uncompressed finder attribute data size + Flags Short info bits + fdType Byte[4] Type of the File (4-byte string) + fdCreator Byte[4] Creator of the File (4-byte string) + (CType) Short compression type + (CRC) Long CRC value for uncompressed MacOS data + Attribs variable finder attribute data (see below) + + + Central-header version: + + Value Size Description + ----- ---- ----------- + (Mac3) 0x334d Short tag for this extra block type ("M3") + TSize Short total data size for this block + BSize Long uncompressed finder attribute data size + Flags Short info bits + fdType Byte[4] Type of the File (4-byte string) + fdCreator Byte[4] Creator of the File (4-byte string) + + The third bit of Flags in both headers indicates whether + the LOCAL extra field is uncompressed (and therefore whether CType + and CRC are omitted): + + Bits of the Flags: + bit 0 if set, file is a data fork; otherwise unset + bit 1 if set, filename will be not changed + bit 2 if set, Attribs is uncompressed (no CType, CRC) + bit 3 if set, date and times are in 64 bit + if zero date and times are in 32 bit. + bit 4 if set, timezone offsets fields for the native + Mac times are omitted (UTC support deactivated) + bits 5-15 reserved; + + + Attributes: + + Attribs is a Mac-specific block of data in little-endian format with + the following structure (if compressed, uncompress it first): + + Value Size Description + ----- ---- ----------- + fdFlags Short Finder Flags + fdLocation.v Short Finder Icon Location + fdLocation.h Short Finder Icon Location + fdFldr Short Folder containing file + + FXInfo 16 bytes Macintosh FXInfo structure + FXInfo-Structure: + fdIconID Short + fdUnused[3] Short unused but reserved 6 bytes + fdScript Byte Script flag and number + fdXFlags Byte More flag bits + fdComment Short Comment ID + fdPutAway Long Home Dir ID + + FVersNum Byte file version number + may be not used by MacOS + ACUser Byte directory access rights + + FlCrDat ULong date and time of creation + FlMdDat ULong date and time of last modification + FlBkDat ULong date and time of last backup + These time numbers are original Mac FileTime values (local time!). + Currently, date-time width is 32-bit, but future version may + support be 64-bit times (see flags) + + CrGMTOffs Long(signed!) difference "local Creat. time - UTC" + MdGMTOffs Long(signed!) difference "local Modif. time - UTC" + BkGMTOffs Long(signed!) difference "local Backup time - UTC" + These "local time - UTC" differences (stored in seconds) may be + used to support timestamp adjustment after inter-timezone transfer. + These fields are optional; bit 4 of the flags word controls their + presence. + + Charset Short TextEncodingBase (Charset) + valid for the following two fields + + FullPath variable Path of the current file. + Zero terminated string (C-String) + Currently coded in the native Charset. + + Comment variable Finder Comment of the current file. + Zero terminated string (C-String) + Currently coded in the native Charset. + + + -SmartZIP Macintosh Extra Field: + ==================================== + + The following is the layout of the SmartZIP extra + block for Macintosh, designed by Marco Bambini. + + Local-header version: + + Value Size Description + ----- ---- ----------- + 0x4d63 Short tag for this extra block type ("cM") + TSize Short total data size for this block (64) + "dZip" beLong extra-field signature + fdType Byte[4] Type of the File (4-byte string) + fdCreator Byte[4] Creator of the File (4-byte string) + fdFlags beShort Finder Flags + fdLocation.v beShort Finder Icon Location + fdLocation.h beShort Finder Icon Location + fdFldr beShort Folder containing file + CrDat beLong HParamBlockRec fileParam.ioFlCrDat + MdDat beLong HParamBlockRec fileParam.ioFlMdDat + frScroll.v Byte vertical pos. of folder's scroll bar + fdScript Byte Script flag and number + frScroll.h Byte horizontal pos. of folder's scroll bar + fdXFlags Byte More flag bits + FileName Byte[32] full Macintosh filename (pascal string) + + All fields but the first two are in native Macintosh format + (big-endian Motorola order, not little-endian Intel). + The extra field size is fixed to 64 bytes. + The local-header and central-header versions are identical. + + + -Acorn SparkFS Extra Field: + ========================= + + The following is the layout of David Pilling's SparkFS extra block + for Acorn RISC OS. The local-header and central-header versions are + identical. (Last Revision 19960922) + + Value Size Description + ----- ---- ----------- + (Acorn) 0x4341 Short tag for this extra block type ("AC") + TSize Short total data size for this block (20) + "ARC0" Long extra-field signature + LoadAddr Long load address or file type + ExecAddr Long exec address + Attr Long file permissions + Zero Long reserved; always zero + + The following bits of Attr are associated with the given file + permissions: + + bit 0 user-writable ('W') + bit 1 user-readable ('R') + bit 2 reserved + bit 3 locked ('L') + bit 4 publicly writable ('w') + bit 5 publicly readable ('r') + bit 6 reserved + bit 7 reserved + + + -VM/CMS Extra Field: + ================== + + The following is the layout of the file-attributes extra block for + VM/CMS. The local-header and central-header versions are + identical. (Last Revision 19960922) + + Value Size Description + ----- ---- ----------- + (VM/CMS) 0x4704 Short tag for this extra block type + TSize Short total data size for this block + flData variable file attributes data + + flData is an uncompressed fldata_t struct. + + + -MVS Extra Field: + =============== + + The following is the layout of the file-attributes extra block for + MVS. The local-header and central-header versions are identical. + (Last Revision 19960922) + + Value Size Description + ----- ---- ----------- + (MVS) 0x470f Short tag for this extra block type + TSize Short total data size for this block + flData variable file attributes data + + flData is an uncompressed fldata_t struct. + + + -PKWARE Unix Extra Field (0x000d): + ================================ + + The following is the layout of PKWARE's Unix "extra" block. + It was introduced with the release of PKZIP for Unix 2.50. + Note: all fields are stored in Intel low-byte/high-byte order. + (Last Revision 19980901) + + This field has a minimum data size of 12 bytes and is only stored + as local extra field. + + Value Size Description + ----- ---- ----------- + (Unix0) 0x000d Short Tag for this "extra" block type + TSize Short Total Data Size for this block + AcTime Long time of last access (UTC/GMT) + ModTime Long time of last modification (UTC/GMT) + UID Short Unix user ID + GID Short Unix group ID + (var) variable Variable length data field + + The variable length data field will contain file type + specific data. Currently the only values allowed are + the original "linked to" file names for hard or symbolic + links, and the major and minor device node numbers for + character and block device nodes. Since device nodes + cannot be either symbolic or hard links, only one set of + variable length data is stored. Link files will have the + name of the original file stored. This name is NOT NULL + terminated. Its size can be determined by checking TSize - + 12. Device entries will have eight bytes stored as two 4 + byte entries (in little-endian format). The first entry + will be the major device number, and the second the minor + device number. + + [Info-ZIP note: The fixed part of this field has the same layout as + Info-ZIP's abandoned "Unix1 timestamps & owner ID info" extra field; + only the two tag bytes are different.] + + + -PATCH Descriptor Extra Field (0x000f): + ===================================== + + The following is the layout of the Patch Descriptor "extra" + block. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (Patch) 0x000f Short Tag for this "extra" block type + TSize Short Size of the total "extra" block + Version Short Version of the descriptor + Flags Long Actions and reactions (see below) + OldSize Long Size of the file about to be patched + OldCRC Long 32-bit CRC of the file about to be patched + NewSize Long Size of the resulting file + NewCRC Long 32-bit CRC of the resulting file + + + Actions and reactions + + Bits Description + ---- ---------------- + 0 Use for auto detection + 1 Treat as a self-patch + 2-3 RESERVED + 4-5 Action (see below) + 6-7 RESERVED + 8-9 Reaction (see below) to absent file + 10-11 Reaction (see below) to newer file + 12-13 Reaction (see below) to unknown file + 14-15 RESERVED + 16-31 RESERVED + + Actions + + Action Value + ------ ----- + none 0 + add 1 + delete 2 + patch 3 + + Reactions + + Reaction Value + -------- ----- + ask 0 + skip 1 + ignore 2 + fail 3 + + Patch support is provided by PKPatchMaker(tm) technology and is + covered under U.S. Patents and Patents Pending. The use or + implementation in a product of certain technological aspects set + forth in the current APPNOTE, including those with regard to + strong encryption, patching, or extended tape operations requires + a license from PKWARE. Please contact PKWARE with regard to + acquiring a license. + + + -PKCS#7 Store for X.509 Certificates (0x0014): + ============================================ + + This field contains information about each of the certificates + files may be signed with. When the Central Directory Encryption + feature is enabled for a ZIP file, this record will appear in + the Archive Extra Data Record, otherwise it will appear in the + first central directory record and will be ignored in any + other record. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (Store) 0x0014 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of the store data + SData TSize Data about the store + + SData + Value Size Description + ----- ---- ----------- + Version 2 bytes Version number, 0x0001 for now + StoreD (variable) Actual store data + + The StoreD member is suitable for passing as the pbData + member of a CRYPT_DATA_BLOB to the CertOpenStore() function + in Microsoft's CryptoAPI. The SSize member above will be + cbData + 6, where cbData is the cbData member of the same + CRYPT_DATA_BLOB. The encoding type to pass to + CertOpenStore() should be + PKCS_7_ANS_ENCODING | X509_ASN_ENCODING. + + + -X.509 Certificate ID and Signature for individual file (0x0015): + =============================================================== + + This field contains the information about which certificate in + the PKCS#7 store was used to sign a particular file. It also + contains the signature data. This field can appear multiple + times, but can only appear once per certificate. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (CID) 0x0015 2 bytes Tag for this "extra" block type + CSize 2 bytes Size of Method + Method (variable) + + Method + Value Size Description + ----- ---- ----------- + Version 2 bytes Version number, for now 0x0001 + AlgID 2 bytes Algorithm ID used for signing + IDSize 2 bytes Size of Certificate ID data + CertID (variable) Certificate ID data + SigSize 2 bytes Size of Signature data + Sig (variable) Signature data + + CertID + Value Size Description + ----- ---- ----------- + Size1 4 bytes Size of CertID, should be (IDSize - 4) + Size1 4 bytes A bug in version one causes this value + to appear twice. + IssSize 4 bytes Issuer data size + Issuer (variable) Issuer data + SerSize 4 bytes Serial Number size + Serial (variable) Serial Number data + + The Issuer and IssSize members are suitable for creating a + CRYPT_DATA_BLOB to be the Issuer member of a CERT_INFO + struct. The Serial and SerSize members would be the + SerialNumber member of the same CERT_INFO struct. This + struct would be used to find the certificate in the store + the file was signed with. Those structures are from the MS + CryptoAPI. + + Sig and SigSize are the actual signature data and size + generated by signing the file with the MS CryptoAPI using a + hash created with the given AlgID. + + + -X.509 Certificate ID and Signature for central directory (0x0016): + ================================================================= + + This field contains the information about which certificate in + the PKCS#7 store was used to sign the central directory structure. + When the Central Directory Encryption feature is enabled for a + ZIP file, this record will appear in the Archive Extra Data Record, + otherwise it will appear in the first central directory record, + along with the store. The data structure is the + same as the CID, except that SigSize will be 0, and there + will be no Sig member. + + This field is also kept after the last central directory + record, as the signature data (ID 0x05054b50, it looks like + a central directory record of a different type). This + second copy of the data is the Signature Data member of the + record, and will have a SigSize that is non-zero, and will + have Sig data. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (CDID) 0x0016 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of data that follows + TData TSize Data + + + -Strong Encryption Header (0x0017): + ================================= + + Value Size Description + ----- ---- ----------- + 0x0017 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of data that follows + Format 2 bytes Format definition for this record + AlgID 2 bytes Encryption algorithm identifier + Bitlen 2 bytes Bit length of encryption key + Flags 2 bytes Processing flags + CertData TSize-8 Certificate decryption extra field data + (refer to the explanation for CertData + in the section describing the + Certificate Processing Method under + the Strong Encryption Specification) + + + -Record Management Controls (0x0018): + =================================== + + Value Size Description + ----- ---- ----------- +(Rec-CTL) 0x0018 2 bytes Tag for this "extra" block type + CSize 2 bytes Size of total extra block data + Tag1 2 bytes Record control attribute 1 + Size1 2 bytes Size of attribute 1, in bytes + Data1 Size1 Attribute 1 data + . + . + . + TagN 2 bytes Record control attribute N + SizeN 2 bytes Size of attribute N, in bytes + DataN SizeN Attribute N data + + + -PKCS#7 Encryption Recipient Certificate List (0x0019): + ===================================================== + + This field contains information about each of the certificates + used in encryption processing and it can be used to identify who is + allowed to decrypt encrypted files. This field should only appear + in the archive extra data record. This field is not required and + serves only to aide archive modifications by preserving public + encryption key data. Individual security requirements may dictate + that this data be omitted to deter information exposure. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (CStore) 0x0019 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of the store data + TData TSize Data about the store + + TData: + + Value Size Description + ----- ---- ----------- + Version 2 bytes Format version number - must 0x0001 at this time + CStore (var) PKCS#7 data blob + + + -MVS Extra Field (PKWARE, 0x0065): + ================================ + + The following is the layout of the MVS "extra" block. + Note: Some fields are stored in Big Endian format. + All text is in EBCDIC format unless otherwise specified. + + Value Size Description + ----- ---- ----------- + (MVS) 0x0065 2 bytes Tag for this "extra" block type + TSize 2 bytes Size for the following data block + ID 4 bytes EBCDIC "Z390" 0xE9F3F9F0 or + "T4MV" for TargetFour + (var) TSize-4 Attribute data + + + -OS/400 Extra Field (0x0065): + =========================== + + The following is the layout of the OS/400 "extra" block. + Note: Some fields are stored in Big Endian format. + All text is in EBCDIC format unless otherwise specified. + + Value Size Description + ----- ---- ----------- + (OS400) 0x0065 2 bytes Tag for this "extra" block type + TSize 2 bytes Size for the following data block + ID 4 bytes EBCDIC "I400" 0xC9F4F0F0 or + "T4MV" for TargetFour + (var) TSize-4 Attribute data + + + -Info-ZIP Unicode Path Extra Field: + ================================= + + Stores the UTF-8 version of the entry path as stored in the + local header and central directory header. + (Last Revision 20070912) + + Value Size Description + ----- ---- ----------- + (UPath) 0x7075 Short tag for this extra block type ("up") + TSize Short total data size for this block + Version Byte version of this extra field, currently 1 + NameCRC32 Long CRC-32 checksum of standard name field + UnicodeName variable UTF-8 version of the entry file name + + Currently Version is set to the number 1. If there is a need + to change this field, the version will be incremented. Changes + may not be backward compatible so this extra field should not be + used if the version is not recognized. + + The NameCRC32 is the standard zip CRC32 checksum of the File Name + field in the header. This is used to verify that the header + File Name field has not changed since the Unicode Path extra field + was created. This can happen if a utility renames the entry but + does not update the UTF-8 path extra field. If the CRC check fails, + this UTF-8 Path Extra Field should be ignored and the File Name field + in the header should be used instead. + + The UnicodeName is the UTF-8 version of the contents of the File + Name field in the header, without any trailing NUL. The standard + name field in the Zip entry header remains filled with the entry + name coded in the local machine's extended ASCII system charset. + As UnicodeName is defined to be UTF-8, no UTF-8 byte order mark + (BOM) is used. The length of this field is determined by + subtracting the size of the previous fields from TSize. + If both the File Name and Comment fields are UTF-8, the new General + Purpose Bit Flag, bit 11 (Language encoding flag (EFS)), should be + used to indicate that both the header File Name and Comment fields + are UTF-8 and, in this case, the Unicode Path and Unicode Comment + extra fields are not needed and should not be created. Note that, + for backward compatibility, bit 11 should only be used if the native + character set of the paths and comments being zipped up are already + in UTF-8. The same method, either general purpose bit 11 or extra + fields, should be used in both the Local and Central Directory Header + for a file. + + Utilisation rules: + 1. This field shall never be created for names consisting solely of + 7-bit ASCII characters. + 2. On a system that already uses UTF-8 as system charset, this field + shall not repeat the string pattern already stored in the Zip + entry's standard name field. Instead, a field of exactly 9 bytes + (70 75 05 00 01 and 4 bytes CRC) should be created. + In this form with 5 data bytes, the field serves as indicator + for the UTF-8 encoding of the standard Zip header's name field. + 3. This field shall not be used whenever the calculated CRC-32 of + the entry's standard name field does not match the provided + CRC checksum value. A mismatch of the CRC check indicates that + the standard name field was changed by some non-"up"-aware + utility without synchronizing this UTF-8 name e.f. block. + + + -Info-ZIP Unicode Comment Extra Field: + ==================================== + + Stores the UTF-8 version of the entry comment as stored in the + central directory header. + (Last Revision 20070912) + + Value Size Description + ----- ---- ----------- + (UCom) 0x6375 Short tag for this extra block type ("uc") + TSize Short total data size for this block + Version 1 byte version of this extra field, currently 1 + ComCRC32 4 bytes Comment Field CRC32 Checksum + UnicodeCom Variable UTF-8 version of the entry comment + + Currently Version is set to the number 1. If there is a need + to change this field, the version will be incremented. Changes + may not be backward compatible so this extra field should not be + used if the version is not recognized. + + The ComCRC32 is the standard zip CRC32 checksum of the Comment + field in the central directory header. This is used to verify that + the comment field has not changed since the Unicode Comment extra + field was created. This can happen if a utility changes the Comment + field but does not update the UTF-8 Comment extra field. If the CRC + check fails, this Unicode Comment extra field should be ignored and + the Comment field in the header used. + + The UnicodeCom field is the UTF-8 version of the entry comment field + in the header. As UnicodeCom is defined to be UTF-8, no UTF-8 byte + order mark (BOM) is used. The length of this field is determined by + subtracting the size of the previous fields from TSize. If both the + File Name and Comment fields are UTF-8, the new General Purpose Bit + Flag, bit 11 (Language encoding flag (EFS)), can be used to indicate + both the header File Name and Comment fields are UTF-8 and, in this + case, the Unicode Path and Unicode Comment extra fields are not + needed and should not be created. Note that, for backward + compatibility, bit 11 should only be used if the native character set + of the paths and comments being zipped up are already in UTF-8. The + same method, either bit 11 or extra fields, should be used in both + the local and central directory headers. + + + -Extended Timestamp Extra Field: + ============================== + + The following is the layout of the extended-timestamp extra block. + (Last Revision 19970118) + + Local-header version: + + Value Size Description + ----- ---- ----------- + (time) 0x5455 Short tag for this extra block type ("UT") + TSize Short total data size for this block + Flags Byte info bits + (ModTime) Long time of last modification (UTC/GMT) + (AcTime) Long time of last access (UTC/GMT) + (CrTime) Long time of original creation (UTC/GMT) + + Central-header version: + + Value Size Description + ----- ---- ----------- + (time) 0x5455 Short tag for this extra block type ("UT") + TSize Short total data size for this block + Flags Byte info bits (refers to local header!) + (ModTime) Long time of last modification (UTC/GMT) + + The central-header extra field contains the modification time only, + or no timestamp at all. TSize is used to flag its presence or + absence. But note: + + If "Flags" indicates that Modtime is present in the local header + field, it MUST be present in the central header field, too! + This correspondence is required because the modification time + value may be used to support trans-timezone freshening and + updating operations with zip archives. + + The time values are in standard Unix signed-long format, indicating + the number of seconds since 1 January 1970 00:00:00. The times + are relative to Coordinated Universal Time (UTC), also sometimes + referred to as Greenwich Mean Time (GMT). To convert to local time, + the software must know the local timezone offset from UTC/GMT. + + The lower three bits of Flags in both headers indicate which time- + stamps are present in the LOCAL extra field: + + bit 0 if set, modification time is present + bit 1 if set, access time is present + bit 2 if set, creation time is present + bits 3-7 reserved for additional timestamps; not set + + Those times that are present will appear in the order indicated, but + any combination of times may be omitted. (Creation time may be + present without access time, for example.) TSize should equal + (1 + 4*(number of set bits in Flags)), as the block is currently + defined. Other timestamps may be added in the future. + + + -Info-ZIP Unix Extra Field (type 1): + ================================== + + The following is the layout of the old Info-ZIP extra block for + Unix. It has been replaced by the extended-timestamp extra block + (0x5455) and the Unix type 2 extra block (0x7855). + (Last Revision 19970118) + + Local-header version: + + Value Size Description + ----- ---- ----------- + (Unix1) 0x5855 Short tag for this extra block type ("UX") + TSize Short total data size for this block + AcTime Long time of last access (UTC/GMT) + ModTime Long time of last modification (UTC/GMT) + UID Short Unix user ID (optional) + GID Short Unix group ID (optional) + + Central-header version: + + Value Size Description + ----- ---- ----------- + (Unix1) 0x5855 Short tag for this extra block type ("UX") + TSize Short total data size for this block + AcTime Long time of last access (GMT/UTC) + ModTime Long time of last modification (GMT/UTC) + + The file access and modification times are in standard Unix signed- + long format, indicating the number of seconds since 1 January 1970 + 00:00:00. The times are relative to Coordinated Universal Time + (UTC), also sometimes referred to as Greenwich Mean Time (GMT). To + convert to local time, the software must know the local timezone + offset from UTC/GMT. The modification time may be used by non-Unix + systems to support inter-timezone freshening and updating of zip + archives. + + The local-header extra block may optionally contain UID and GID + info for the file. The local-header TSize value is the only + indication of this. Note that Unix UIDs and GIDs are usually + specific to a particular machine, and they generally require root + access to restore. + + This extra field type is obsolete, but it has been in use since + mid-1994. Therefore future archiving software should continue to + support it. Some guidelines: + + An archive member should either contain the old "Unix1" + extra field block or the new extra field types "time" and/or + "Unix2". + + If both the old "Unix1" block type and one or both of the new + block types "time" and "Unix2" are found, the "Unix1" block + should be considered invalid and ignored. + + Unarchiving software should recognize both old and new extra + field block types, but the info from new types overrides the + old "Unix1" field. + + Archiving software should recognize "Unix1" extra fields for + timestamp comparison but never create it for updated, freshened + or new archive members. When copying existing members to a new + archive, any "Unix1" extra field blocks should be converted to + the new "time" and/or "Unix2" types. + + + -Info-ZIP UNIX Extra Field (type 2): + ================================== + + The following is the layout of the new Info-ZIP extra block for + Unix. (Last Revision 19960922) + + Local-header version: + + Value Size Description + ----- ---- ----------- + (Unix2) 0x7855 Short tag for this extra block type ("Ux") + TSize Short total data size for this block (4) + UID Short Unix user ID + GID Short Unix group ID + + Central-header version: + + Value Size Description + ----- ---- ----------- + (Unix2) 0x7855 Short tag for this extra block type ("Ux") + TSize Short total data size for this block (0) + + The data size of the central-header version is zero; it is used + solely as a flag that UID/GID info is present in the local-header + extra field. If additional fields are ever added to the local + version, the central version may be extended to indicate this. + + Note that Unix UIDs and GIDs are usually specific to a particular + machine, and they generally require root access to restore. + + + -Info-ZIP New Unix Extra Field: + ==================================== + + Currently stores Unix UIDs/GIDs up to 32 bits. + (Last Revision 20080509) + + Value Size Description + ----- ---- ----------- + (UnixN) 0x7875 Short tag for this extra block type ("ux") + TSize Short total data size for this block + Version 1 byte version of this extra field, currently 1 + UIDSize 1 byte Size of UID field + UID Variable UID for this entry + GIDSize 1 byte Size of GID field + GID Variable GID for this entry + + Currently Version is set to the number 1. If there is a need + to change this field, the version will be incremented. Changes + may not be backward compatible so this extra field should not be + used if the version is not recognized. + + UIDSize is the size of the UID field in bytes. This size should + match the size of the UID field on the target OS. + + UID is the UID for this entry in standard little endian format. + + GIDSize is the size of the GID field in bytes. This size should + match the size of the GID field on the target OS. + + GID is the GID for this entry in standard little endian format. + + If both the old 16-bit Unix extra field (tag 0x7855, Info-ZIP Unix2) + and this extra field are present, the values in this extra field + supercede the values in that extra field. + + + -ASi UNIX Extra Field: + ==================== + + The following is the layout of the ASi extra block for Unix. The + local-header and central-header versions are identical. + (Last Revision 19960916) + + Value Size Description + ----- ---- ----------- + (Unix3) 0x756e Short tag for this extra block type ("nu") + TSize Short total data size for this block + CRC Long CRC-32 of the remaining data + Mode Short file permissions + SizDev Long symlink'd size OR major/minor dev num + UID Short user ID + GID Short group ID + (var.) variable symbolic link filename + + Mode is the standard Unix st_mode field from struct stat, containing + user/group/other permissions, setuid/setgid and symlink info, etc. + + If Mode indicates that this file is a symbolic link, SizDev is the + size of the file to which the link points. Otherwise, if the file + is a device, SizDev contains the standard Unix st_rdev field from + struct stat (includes the major and minor numbers of the device). + SizDev is undefined in other cases. + + If Mode indicates that the file is a symbolic link, the final field + will be the name of the file to which the link points. The file- + name length can be inferred from TSize. + + [Note that TSize may incorrectly refer to the data size not counting + the CRC; i.e., it may be four bytes too small.] + + + -BeOS Extra Field: + ================ + + The following is the layout of the file-attributes extra block for + BeOS. (Last Revision 19970531) + + Local-header version: + + Value Size Description + ----- ---- ----------- + (BeOS) 0x6542 Short tag for this extra block type ("Be") + TSize Short total data size for this block + BSize Long uncompressed file attribute data size + Flags Byte info bits + (CType) Short compression type + (CRC) Long CRC value for uncompressed file attribs + Attribs variable file attribute data + + Central-header version: + + Value Size Description + ----- ---- ----------- + (BeOS) 0x6542 Short tag for this extra block type ("Be") + TSize Short total data size for this block (5) + BSize Long size of uncompr. local EF block data + Flags Byte info bits + + The least significant bit of Flags in both headers indicates whether + the LOCAL extra field is uncompressed (and therefore whether CType + and CRC are omitted): + + bit 0 if set, Attribs is uncompressed (no CType, CRC) + bits 1-7 reserved; if set, assume error or unknown data + + Currently the only supported compression types are deflated (type 8) + and stored (type 0); the latter is not used by Info-ZIP's Zip but is + supported by UnZip. + + Attribs is a BeOS-specific block of data in big-endian format with + the following structure (if compressed, uncompress it first): + + Value Size Description + ----- ---- ----------- + Name variable attribute name (null-terminated string) + Type Long attribute type (32-bit unsigned integer) + Size Long Long data size for this sub-block (64 bits) + Data variable attribute data + + The attribute structure is repeated for every attribute. The Data + field may contain anything--text, flags, bitmaps, etc. + + + -AtheOS Extra Field: + ================== + + The following is the layout of the file-attributes extra block for + AtheOS. This field is a very close spin-off from the BeOS e.f. + The only differences are: + - a new extra field signature + - numeric field in the attributes data are stored in little-endian + format ("i386" was initial hardware for AtheOS) + (Last Revision 20040908) + + Local-header version: + + Value Size Description + ----- ---- ----------- + (AtheOS) 0x7441 Short tag for this extra block type ("At") + TSize Short total data size for this block + BSize Long uncompressed file attribute data size + Flags Byte info bits + (CType) Short compression type + (CRC) Long CRC value for uncompressed file attribs + Attribs variable file attribute data + + Central-header version: + + Value Size Description + ----- ---- ----------- + (AtheOS) 0x7441 Short tag for this extra block type ("At") + TSize Short total data size for this block (5) + BSize Long size of uncompr. local EF block data + Flags Byte info bits + + The least significant bit of Flags in both headers indicates whether + the LOCAL extra field is uncompressed (and therefore whether CType + and CRC are omitted): + + bit 0 if set, Attribs is uncompressed (no CType, CRC) + bits 1-7 reserved; if set, assume error or unknown data + + Currently the only supported compression types are deflated (type 8) + and stored (type 0); the latter is not used by Info-ZIP's Zip but is + supported by UnZip. + + Attribs is a AtheOS-specific block of data in little-endian format + with the following structure (if compressed, uncompress it first): + + Value Size Description + ----- ---- ----------- + Name variable attribute name (null-terminated string) + Type Long attribute type (32-bit unsigned integer) + Size Long Long data size for this sub-block (64 bits) + Data variable attribute data + + The attribute structure is repeated for every attribute. The Data + field may contain anything--text, flags, bitmaps, etc. + + + -SMS/QDOS Extra Field: + ==================== + + The following is the layout of the file-attributes extra block for + SMS/QDOS. The local-header and central-header versions are identical. + (Last Revision 19960929) + + Value Size Description + ----- ---- ----------- + (QDOS) 0xfb4a Short tag for this extra block type + TSize Short total data size for this block + LongID Long extra-field signature + (ExtraID) Long additional signature/flag bytes + QDirect 64 bytes qdirect structure + + LongID may be "QZHD" or "QDOS". In the latter case, ExtraID will + be present. Its first three bytes are "02\0"; the last byte is + currently undefined. + + QDirect contains the file's uncompressed directory info (qdirect + struct). Its elements are in native (big-endian) format: + + d_length beLong file length + d_access byte file access type + d_type byte file type + d_datalen beLong data length + d_reserved beLong unused + d_szname beShort size of filename + d_name 36 bytes filename + d_update beLong time of last update + d_refdate beLong file version number + d_backup beLong time of last backup (archive date) + + + -AOS/VS Extra Field: + ================== + + The following is the layout of the extra block for Data General + AOS/VS. The local-header and central-header versions are identical. + (Last Revision 19961125) + + Value Size Description + ----- ---- ----------- + (AOSVS) 0x5356 Short tag for this extra block type ("VS") + TSize Short total data size for this block + "FCI\0" Long extra-field signature + Version Byte version of AOS/VS extra block (10 = 1.0) + Fstat variable fstat packet + AclBuf variable raw ACL data ($MXACL bytes) + + Fstat contains the file's uncompressed fstat packet, which is one of + the following: + + normal fstat packet (P_FSTAT struct) + DIR/CPD fstat packet (P_FSTAT_DIR struct) + unit (device) fstat packet (P_FSTAT_UNIT struct) + IPC file fstat packet (P_FSTAT_IPC struct) + + AclBuf contains the raw ACL data; its length is $MXACL. + + + -Tandem NSK Extra Field: + ====================== + + The following is the layout of the file-attributes extra block for + Tandem NSK. The local-header and central-header versions are + identical. (Last Revision 19981221) + + Value Size Description + ----- ---- ----------- + (TA) 0x4154 Short tag for this extra block type ("TA") + TSize Short total data size for this block (20) + NSKattrs 20 Bytes NSK attributes + + + -THEOS Extra Field: + ================= + + The following is the layout of the file-attributes extra block for + Theos. The local-header and central-header versions are identical. + (Last Revision 19990206) + + Value Size Description + ----- ---- ----------- + (Theos) 0x6854 Short 'Th' signature + size Short size of extra block + flags Byte reserved for future use + filesize Long file size + fileorg Byte type of file (see below) + keylen Short key length for indexed and keyed files, + data segment size for 16 bits programs + reclen Short record length for indexed,keyed and direct, + text segment size for 16 bits programs + filegrow Byte growing factor for indexed,keyed and direct + protect Byte protections (see below) + reserved Short reserved for future use + + File types + ========== + + 0x80 library (keyed access list of files) + 0x40 directory + 0x10 stream file + 0x08 direct file + 0x04 keyed file + 0x02 indexed file + 0x0e reserved + 0x01 16 bits real mode program (obsolete) + 0x21 16 bits protected mode program + 0x41 32 bits protected mode program + + Protection codes + ================ + + User protection + --------------- + 0x01 non readable + 0x02 non writable + 0x04 non executable + 0x08 non erasable + + Other protection + ---------------- + 0x10 non readable + 0x20 non writable + 0x40 non executable Theos before 4.0 + 0x40 modified Theos 4.x + 0x80 not hidden + + + -THEOS old inofficial Extra Field: + ================================ + + The following is the layout of an inoffical former version of a + Theos file-attributes extra blocks. This layout was never published + and is no longer created. However, UnZip can optionally support it + when compiling with the option flag OLD_THEOS_EXTRA defined. + Both the local-header and central-header versions are identical. + (Last Revision 19990206) + + Value Size Description + ----- ---- ----------- + (THS0) 0x4854 Short 'TH' signature + size Short size of extra block + flags Short reserved for future use + filesize Long file size + reclen Short record length for indexed,keyed and direct, + text segment size for 16 bits programs + keylen Short key length for indexed and keyed files, + data segment size for 16 bits programs + filegrow Byte growing factor for indexed,keyed and direct + reserved 3 Bytes reserved for future use + + + -FWKCS MD5 Extra Field (0x4b46): + ============================== + + The FWKCS Contents_Signature System, used in automatically + identifying files independent of filename, optionally adds + and uses an extra field to support the rapid creation of + an enhanced contents_signature. + There is no local-header version; the following applies + only to the central header. (Last Revision 19961207) + + Central-header version: + + Value Size Description + ----- ---- ----------- + (MD5) 0x4b46 Short tag for this extra block type ("FK") + TSize Short total data size for this block (19) + "MD5" 3 bytes extra-field signature + MD5hash 16 bytes 128-bit MD5 hash of uncompressed data + (low byte first) + + When FWKCS revises a .ZIP file central directory to add + this extra field for a file, it also replaces the + central directory entry for that file's uncompressed + file length with a measured value. + + FWKCS provides an option to strip this extra field, if + present, from a .ZIP file central directory. In adding + this extra field, FWKCS preserves .ZIP file Authenticity + Verification; if stripping this extra field, FWKCS + preserves all versions of AV through PKZIP version 2.04g. + + FWKCS, and FWKCS Contents_Signature System, are + trademarks of Frederick W. Kantor. + + (1) R. Rivest, RFC1321.TXT, MIT Laboratory for Computer + Science and RSA Data Security, Inc., April 1992. + ll.76-77: "The MD5 algorithm is being placed in the + public domain for review and possible adoption as a + standard." + + + -Microsoft Open Packaging Growth Hint (0xa220): + ============================================= + + Value Size Description + ----- ---- ----------- + 0xa220 Short tag for this extra block type + TSize Short size of Sig + PadVal + Padding + Sig Short verification signature (A028) + PadVal Short Initial padding value + Padding variable filled with NULL characters diff --git a/proginfo/fileinfo.cms b/proginfo/fileinfo.cms new file mode 100644 index 0000000..9d21935 --- /dev/null +++ b/proginfo/fileinfo.cms @@ -0,0 +1,231 @@ +[Quoting from a C/370 manual, courtesy of Carl Forde.] + + C/370 supports three types of input and output: text streams, binary + streams, and record I/O. Text and binary streams are both ANSI + standards; record I/O is a C/370 extension. + +[...] + + Record I/O is a C/370 extension to the ANSI standard. For files + opened in record format, C/370 reads and writes one record at a + time. If you try to write more data to a record than the record + can hold, the data is truncated. For record I/O, C/370 only allows + the use of fread() and fwrite() to read and write to the files. Any + other functions (such as fprintf(), fscanf(), getc(), and putc()) + fail. For record-orientated files, records do not change size when + you update them. If the new data has fewer characters than the + original record, the new data fills the first n characters, where + n is the number of characters of the new data. The record will + remain the same size, and the old characters (those after) n are + left unchanged. A subsequent update begins at the next boundary. + For example, if you have the string "abcdefgh": + + abcdefgh + + and you overwrite it with the string "1234", the record will look + like this: + + 1234efgh + + C/370 record I/O is binary. That is, it does not interpret any of + the data in a record file and therefore does not recognize control + characters. + + + The record model consists of: + + * A record, which is the unit of data transmitted to and from a + program + * A block, which is the unit of data transmitted to and from a + device. Each block may contain one or more records. + + In the record model of I/O, records and blocks have the following + attributes: + + RECFM Specifies the format of the data or how the data is organized + on the physical device. + LRECL Specifies the length of logical records (as opposed to + physical ones). + + BLKSIZE Specifies the length of physical records (blocks on the + physical device). + + + Opening a File by Filename + + The filename that you specify on the call to fopen() or freopen() + must be in the following format: + + >> ----filename---- ----filetype-------------------- + | | | | + --.-- -- --filemode-- + | | + --.-- + where + + filename is a 1- to 8-character string of any of the characters, + A-Z, a-z, 0-9, and +, -, $, #, @, :, and _. You can separate it + from the filetype with one or more spaces, or with a period. + [Further note: filenames are fully case-sensitive, as in Unix.] + + filetype is a 1- to 8-character string of any of the characters, + A-Z, a-z, 0-9, and +, -, $, #, @, :, and _. You can separate it + from the filemode with one or more spaces, or with a period. The + separator between filetype and filemode must be the same as the + one between filename and filetype. + + filemode is a 1- to 2-character string. The first must be any of + the characters A-Z, a-z, or *. If you use the asis parameter on + the fopen() or freopen() call, the first character of the filemode + must be a capital letter or an asterisk. Otherwise, the function + call fails. The second character of filemode is optional; if you + specify it, it must be any of the digits 0-6. You cannot specify + the second character if you have specified * for the first one. + + If you do not use periods as separators, there is no limit to how + much whitespace you can have before and after the filename, the + filetype, and filemode. + + + Opening a File without a File Mode Specified + + If you omit the file mode or specify * for it, C/370 does one + of the following when you call fopen() or freopen(): + + * If you have specified a read mode, C/370 looks for the named file + on all the accessed readable disks, in order. If it does not find + the file, the fopen() or freopen() call fails. + * If you have specified any of the write modes, C/370 writes the file + on the first writable disk you have accessed. Specifying a write + mode on an fopen() or freopen() call that contains the filename of + an existing file destroys that file. If you do not have any + writable disks accessed, the call fails. + + + fopen() and freopen() parameters + + recfm + CMS supports only two RECFMs, V and F. [note that MVS supports + 27(!) different RECFMs.] If you do not specify the RECFM for a + file, C/370 determines whether is is in fixed or variable format. + + lrecl and blksize + For files in fixed format, CMS allows records to be read and + written in blocks. To have a fixed format CMS file treated as a + fixed blocked CMS file, you can open the file with recfm=fb and + specify the lrecl and blksize. If you do not specify a recfm on + the open, the blksize can be a multiple of the lrecl, and the + file is treated as if it were blocked. + + For files in variable format, the CMS LRECL is different from the + LRECL for the record model. In the record model, the LRECL is + equal to the data length plus 4 bytes (for the record descriptor + word), and the BLKSIZE is equal to the LRECL plus 4 bytes (for + the block descriptor word). In CMS, BDWs and RDWs do not exist, + but because CMS follows the record model, you must still account + for them. When you specify V, you must still allocate the record + descriptor word and block descriptor word. That is, if you want + a maximum of n bytes per record, you must specify a minimum LRECL + of n+4 and a minimum BLKSIZE of n+8. + + When you are appending to V files, you can enlarge the record size + dynamically, but only if you have not specified LRECL or BLKSIZE + on the fopen() or freopen() command that opened the file. + + type + If you specify this parameter, the only valid value for CMS disk + files is type =record. This opens a file for record I/O. + + asis + If you use this parameter, you can open files with mixed-case + filenames such as JaMeS dAtA or pErCy.FILE. If you specify this + parameter, the file mode that you specify must be a capital letter + (if it is not an asterisk); otherwise; the function call fails and + the value returned is NULL. + + + Reading from Record I/O Files + fread() is the only interface allowed for reading record I/O files. + Each time you call fread() for a record I/O file, fread() reads + one record from the system. If you call fread() with a request for + less than a complete record, the requested bytes are copied to your + buffer, and the file position is set to the start fo the next + record. If the request is for more bytes that are in the record, + one record is read and the position is set to the start of the next + record. C/370 does not strip any blank characters or interpret any + data. + + fread() returns the number of items read successfully, so if you + pass a size argument equal to 1 and a count argument equal to the + maximum expected length of the record, fread() returns the length, + in bytes, of the record read. If you pass a size argument equal + to the maximum expected length of the record, and a count argument + equal to 1, fread() returns either 0 or 1, indicating whether a + record of length size read. If a record is read successfully but + is less than size bytes long, fread() returns 0. + + + Writing to Record I/O Files + fwrite() is the only interface allowed for writing to a file + opened for record I/O. Only one record is written at a time. If + you attempt to write more new data than a full record can hold or + try to update a record with more data than it currently has, C/370 + truncates your output at the record boundary. When C/370 performs + a truncation, it sets errno and raises SIGIOERR, if SIGIOERR is not + set to SIG_IGN. + + When you are writing new records to a fixed-record I/O file, if you + try to write a short record, C/370 pads the record with nulls out + to LRECL. + + At the completion of an fwrite(), the file position is at the start + of the next record. For new data, the block is flushed out to the + system as soon as it is full. + + + fldata() Behavior + When you call the fldata() function for an open CMS minidisk file, + it returns a data structure that looks like this: + + struct __filedata { + unsigned int __recfmF : 1, /* fixed length records */ + __recfmV : 1, /* variable length records */ + __recfmU : 1, /* n/a */ + __recfmS : 1, /* n/a */ + __recfmBlk : 1, /* n/a */ + __recfmASA : 1, /* text mode and ASA */ + __recfmM : 1, /* n/a */ + __dsorgPO : 1, /* n/a */ + __dsorgPDSmem : 1, /* n/a */ + __dsorgPDSdir : 1, /* n/a */ + __dsorgPS : 1, /* sequential data set */ + __dsorgConcat : 1, /* n/a */ + __dsorgMem : 1, /* n/a */ + __dsorgHiper : 1, /* n/a */ + __dsorgTemp : 1, /* created with tmpfile() */ + __dsorgVSAM : 1, /* n/a */ + __reserve1 : 1, /* n/a */ + __openmode : 2, /* see below 1 */ + __modeflag : 4, /* see below 2 */ + __reserve2 : 9, /* n/a */ + + char __device; __DISK + unsigned long __blksize, /* see below 3 */ + __maxreclen; /* see below 4 */ + unsigned short __vsamtype; /* n/a */ + unsigned long __vsamkeylen; /* n/a */ + unsigned long __vsamRKP; /* n/a */ + char * __dsname; /* fname ftype fmode */ + unsigned int __reserve4; /* n/a */ + + /* note 1: values are: __TEXT, __BINARY, __RECORD + note 2: values are: __READ, __WRITE, __APPEND, __UPDATE + these values can be added together to determine + the return value; for example, a file opened with + a+ will have the value __READ + __APPEND. + note 3: total block size of the file, including ASA + characters as well as RDW information + note 4: maximum record length of the data only (includes + ASA characters but excludes RDW information). + */ + }; diff --git a/proginfo/nt.sd b/proginfo/nt.sd new file mode 100644 index 0000000..8ac31ba --- /dev/null +++ b/proginfo/nt.sd @@ -0,0 +1,111 @@ +Info-ZIP portable Zip/UnZip Windows NT security descriptor support +================================================================== +Scott Field (sfield@microsoft.com), 8 October 1996 + + +This version of Info-ZIP's Win32 code allows for processing of Windows +NT security descriptors if they were saved in the .zip file using the +appropriate Win32 Zip running under Windows NT. This also requires +that the file system that Zip/UnZip operates on supports persistent +Acl storage. When the operating system is not Windows NT and the +target file system does not support persistent Acl storage, no security +descriptor processing takes place. + +A Windows NT security descriptor consists of any combination of the +following components: + + an owner (Sid) + a primary group (Sid) + a discretionary ACL (Dacl) + a system ACL (Sacl) + qualifiers for the preceding items + +By default, Zip will save all aspects of the security descriptor except +for the Sacl. The Sacl contains information pertaining to auditing of +the file, and requires a security privilege be granted to the calling +user in addition to being enabled by the calling application. In order +to save the Sacl during Zip, the user must specify the -! switch on the +Zip commandline. The user must also be granted either the SeBackupPrivilege +"Backup files and directories" or the SeSystemSecurityPrivilege "Manage +auditing and security log". + +By default, UnZip will not restore any aspects of the security descriptor. +If the -X option is specified to UnZip, the Dacl is restored to the file. +The other items in the security descriptor on the new file will receive +default values. If the -XX option is specified to UnZip, as many aspects +of the security descriptor as possible will be restored. If the calling +user is granted the SeRestorePrivilege "Restore files and directories", +all aspects of the security descriptor will be restored. If the calling +user is only granted the SeSystemSecurityPrivilege "Manage auditing and +security log", only the Dacl and Sacl will be restored to the new file. + +Note that when operating on files that reside on remote volumes, the +privileges specified above must be granted to the calling user on that +remote machine. Currently, there is no way to directly test what privileges +are present on a remote machine, so Zip and UnZip make a remote privilege +determination based on an indirect method. + +UnZip considerations +-------------------- + +In order for file security to be processed correctly, any directory entries +that have a security descriptor will be processed at the end of the unzip +cycle. This allows for unzip to process files within the newly created +directory regardless of the security descriptor associated with the directory +entry. This also prevents security inheritance problems that can occur as +a result of creating a new directory and then creating files in that directory +that will inherit parent directory permissions; such inherited permissions may +prevent the security descriptor taken from the zip file from being applied +to the new file. + +If directories exist which match directory/extract paths in the .zip file, +file security is not updated on the target directory. It is assumed that if +the target directory already exists, then appropriate security has already +been applied to that directory. + +"unzip -t" will test the integrity of stored security descriptors when +present and the operating system is Windows NT. + +ZipInfo (unzip -Z) will display information on stored security descriptor +when "unzip -Zv" is specifed. + + +Potential uses +============== + +The obvious use for this new support is to better support backup and restore +operations in a Windows NT environment where NTFS file security is utilized. +This allows individuals and organizations to archive files in a portable +fashion and transport these files across the organization. + +Another potential use of this support is setup and installation. This +allows for distribution of Windows NT based applications that have preset +security on files and directories. For example, prior to creation of the +.zip file, the user can set file security via File Manager or Explorer on +the files to be contained in the .zip file. In many cases, it is appropriate +to only grant Everyone Read access to .exe and .dll files, while granting +Administrators Full control. Using this support in conjunction with the +unzipsfx.exe self-extractor stub can yield a useful and powerful way to +install software with preset security (note that -X or -XX should be +specified on the self-extractor commandline). + +When creating .zip files with security which are intended for transport +across systems, it is important to take into account the relevance of +access control entries and the associated Sid of each entry. For example, +if a .zip file is created on a Windows NT workstation, and file security +references local workstation user accounts (like an account named Fred), +this access entry will not be relevant if the .zip file is transported to +another machine. Where possible, take advantage of the built-in well-known +groups, like Administrators, Everyone, Network, Guests, etc. These groups +have the same meaning on any Windows NT machine. Note that the names of +these groups may differ depending on the language of the installed Windows +NT, but this isn't a problem since each name has well-known ID that, upon +restore, translates to the correct group name regardless of locale. + +When access control entries contain Sid entries that reference Domain +accounts, these entries will only be relevant on systems that recognize +the referenced domain. Generally speaking, the only side effects of +irrelevant access control entries is wasted space in the stored security +descriptor and loss of complete intended access control. Such irrelevant +access control entries will show up as "Account Unknown" when viewing file +security with File Manager or Explorer. diff --git a/proginfo/perform.dos b/proginfo/perform.dos new file mode 100644 index 0000000..98744ee --- /dev/null +++ b/proginfo/perform.dos @@ -0,0 +1,183 @@ +Date: Wed, 27 Mar 1996 01:31:50 CET +0100 +From: Christian Spieler (IKDA, THD, D-64289 Darmstadt) +Subject: More detailed comparison of MSDOS Info-ZIP programs' performance + +Hello all, + +In response to some additional questions and requests concerning +my previous message about DOS performance of 16/32-bit Info-ZIP programs, +I have produced a more detailed comparison: + +System: +Cx486DX-40, VL-bus, 8MB; IDE hard disk; +DOS 6.2, HIMEM, EMM386 NOEMS NOVCPI, SMARTDRV 3MB, write back. + +I have used the main directory of UnZip 5.20p as source, including the +objects and executable of an EMX compile for unzip.exe (to supply some +binary test files). + +Tested programs were (my current updated sources!) Zip 2.0w and UnZip 5.20p +- 16-bit MSC 5.1, compressed with LZEXE 0.91e +- 32-bit Watcom C 10.5, as supplied by Kai Uwe Rommel (PMODE 1.22) +- 32-bit EMX 0.9b +- 32-bit DJGPP v2 +- 32-bit DJGPP v1.12m4 + +The EMX and DJ1 (GO32) executables were bound with the full extender, to +create standalone executables. + +A) Tests of Zip + Command : "\zip.exe -q<#> tes.zip unz/*" (unz/*.* for Watcom!!) + where <#> was: 0, 1, 6, 9. + The test archive "tes.zip" was never deleted, this test + measured "time to update archive". + + The following table contains average execution seconds (averaged over + at least 3 runs, with the first run discarted to fill disk cache); + numbers in parenteses specify the standard deviation of the last + digits. + + cmpr level| 0 | 1 | 6 | 9 + =============================================================== + EMX win95 | 7.77 | 7.97 | 12.82 | 22.31 + --------------------------------------------------------------- + EMX | 7.15(40) | 8.00(6) | 12.52(25) | 20.93 + DJ2 | 13.50(32) | 14.20(7) | 19.05 | 28.48(9) + DJ1 | 13.56(30) | 14.48(3) | 18.70 | 27.43(13) + WAT | 6.94(22) | 8.93 | 15.73(34) | 30.25(6) + MSC | 5.99(82) | 9.40(4) | 13.59(9) | 20.77(4) + =============================================================== + + The "EMX win95" line was created for comparison, to check the performance + of emx 0.9 with the RSX extender in a DPMI environment. (This line was + produced by applying the "stubbed" EMX executable in a full screen DOS box.) + + +B) Tests of UnZip + Commands : \unzip.exe -qt tes.zip (testing performance) + \unzip.exe -qo tes.zip -dtm (extracting performance) + + The tes.zip archive created by maximum compression with the Zip test + was used as example archive. Contents (archive size was 347783 bytes): + 1028492 bytes uncompressed, 337235 bytes compressed, 67%, 85 files + + The extraction directory tm was not deleted between the individual runs, + thus this measurement checks the "overwrite all" time. + + | testing | extracting + =================================================================== + EMX | 1.98 | 6.43(8) + DJ2 | 2.09 | 11.85(39) + DJ1 | 2.09 | 7.46(9) + WAT | 2.42 | 7.10(27) + MSC | 4.94 | 9.57(31) + +Remarks: + +The executables compiled by me were generated with all "performance" +options enabled (ASM_CRC, and ASMV for Zip), and with full crypt support. +For DJ1 and DJ2, the GCC options were "-O2 -m486", for EMX "-O -m486". + +The Watcom UnZip was compiled with ASM_CRC code enabled as well, +but the Watcom Zip example was made without any optional assembler code! + + + +Discussion of the results: + +In overall performance, the EMX executables clearly win. +For UnZip, emx is by far the fastest program, and the Zip performance is +comparable to the 16-bit "reference". + +Whenever "real" work including I/O is requested, the DJGPP versions +lose badly because of poor I/O performance, this is the case especially +for the "newer" DJGPP v2 !!! +(I tried to tweak with the transfer buffer size, but without any success.) +An interesting result is that DJ v1 UnZip works remarkably better than +DJ v2 (in contrast to Zip, where both executables' performance is +approximately equal). + +The Watcom C programs show a clear performance deficit in the "computational +part" (Watcom C compiler produces code that is far from optimal), but +the extender (which is mostly responsible for the I/O throughput) seems +to be quite fast. + +The "natural" performance deficit of the 16-bit MSC code, which can be +clearly seen in the "testing task" comparison for UnZip, is (mostly, +for Zip more than) compensated by the better I/O throughput (due to the +"direct interface" between "C RTL" and "DOS services", without any mode +switching). + +But performance is only one aspect when choosing which compiler should +be used for official distribution: + +Sizes of the executables: + | Zip || UnZip + | standalone stub || standalone | stub +====================================================================== +EMX | 143,364 (1) | 94,212 || 159,748 (1) | 110,596 +DJ2 | 118,272 (2) | -- || 124,928 (2) | -- +DJ1 | 159,744 | 88,064 || 177,152 | 105,472 +WAT | 140,073 | -- || 116,231 | -- +MSC | 49,212 (3) | -- || 45,510 (3) | -- + +(1) does not run in "DPMI only" environment (Windows DOS box) +(2) requires externally supplied DPMI server +(3) compressed with LZexe 0.91 + +Caveats/Bugs/Problems of the different extenders: + +EMX: +- requires two different extenders to run in all DOS-compatible environments, + EMX for "raw/himem/vcpi" and RSX for "dpmi" (Windows). +- does not properly support time zones (no daylight savings time) + +DJv2: +- requires an external (freely available) DPMI extender when run on plain + DOS; this extender cannot (currently ??) be bound into the executable. + +DJv1: +- uses up large amount of "low" dos memory (below 1M) when spawning + another program, each instance of a DJv1 program requires its private + GO32 extender copy in low dos memory (may be problem for the zip + "-T" feature) + +Watcom/PMODE: +- extended memory is allocated statically (default: ALL available memory) + This means that a spawned program does not get any extended memory. + You can work around this problem by setting a hard limit on the amount + of extended memory available to the PMODE program, but this limit is + "hard" and restricts the allocatable memory for the program itself. + In detail: + The Watcom zip.exe as distributed did not allow the "zip -T" feature; + there was no extended memory left to spawn unzip. + I could work around this problem by applying PMSETUP to change the + amount of allocated extended memory to 2.0 MByte (I had 4MB free extended + memory on my test system). But, this limit cannot be enlarged at + runtime, when zip needs more memory to store "header info" while + zipping up a huge drive, and on a system with less free memory, this + method is not applicable, either. + +Summary: + +For Zip: +Use the 16-bit executable whenever possible (unless you need the +larger memory capabilities when zipping up a huge amount of files) + +As 32-bit executable, we may distribute Watcom C (after we have confirmed +that enabling ASMV and ASM_CRC give us some better computational +performance.) +The alternative for 32-bit remains DJGPP v1, which shows the least problems +(to my knowledge); v2 and EMX cannot be used because of their lack of +"universality". + +For UnZip: +Here, the Watcom C 32-bit executable is probably the best compromise, +but DJ v1 could be used as well. +And, after all, the 16-bit version does not lose badly when doing +"real" extraction! For the SFX stub, the 16-bit version remains first +choice because of its much smaller size! + +Best regards + +Christian Spieler diff --git a/proginfo/timezone.txt b/proginfo/timezone.txt new file mode 100644 index 0000000..7868093 --- /dev/null +++ b/proginfo/timezone.txt @@ -0,0 +1,85 @@ +Timezone strings: +----------------- +This is a description of valid timezone strings for ENV[ARC]:TZ: +"XPG3TZ - time zone information" +The form of the time zone information is based on the XPG3 specification of +the TZ environment variable. Spaces are allowed only in timezone +designations, where they are significant. The following description +closely follows the XPG3 specification, except for the paragraphs starting +**CLARIFICATION**. + +[[],[/