From 36508e0a174db820d5aa77552706e16d47f60313 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Tue, 11 Apr 2000 12:38:07 +0000 Subject: [PATCH] Added wxInstall a self extracting installation program using wxWindows. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_2_BRANCH@7117 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- utils/Install/builder/ToolbarVC.dsp | 175 ++ utils/Install/builder/ToolbarVC.dsw | 29 + utils/Install/builder/bitmaps/copy.bmp | Bin 0 -> 238 bytes utils/Install/builder/bitmaps/copy.xpm | 25 + utils/Install/builder/bitmaps/cut.bmp | Bin 0 -> 238 bytes utils/Install/builder/bitmaps/cut.xpm | 24 + utils/Install/builder/bitmaps/help.bmp | Bin 0 -> 238 bytes utils/Install/builder/bitmaps/help.xpm | 25 + utils/Install/builder/bitmaps/new.bmp | Bin 0 -> 238 bytes utils/Install/builder/bitmaps/new.xpm | 24 + utils/Install/builder/bitmaps/open.bmp | Bin 0 -> 238 bytes utils/Install/builder/bitmaps/open.xpm | 26 + utils/Install/builder/bitmaps/page.bmp | Bin 0 -> 714 bytes utils/Install/builder/bitmaps/paste.bmp | Bin 0 -> 238 bytes utils/Install/builder/bitmaps/preview.bmp | Bin 0 -> 238 bytes utils/Install/builder/bitmaps/preview.xpm | 26 + utils/Install/builder/bitmaps/print.bmp | Bin 0 -> 238 bytes utils/Install/builder/bitmaps/print.xpm | 26 + utils/Install/builder/bitmaps/save.bmp | Bin 0 -> 238 bytes utils/Install/builder/bitmaps/save.xpm | 25 + utils/Install/builder/makefile | 23 + utils/Install/builder/makefile.b32 | 10 + utils/Install/builder/makefile.bcc | 14 + utils/Install/builder/makefile.dos | 10 + utils/Install/builder/makefile.g95 | 10 + utils/Install/builder/makefile.sc | 37 + utils/Install/builder/makefile.sl | 14 + utils/Install/builder/makefile.twn | 35 + utils/Install/builder/makefile.unx | 23 + utils/Install/builder/makefile.vc | 11 + utils/Install/builder/makefile.wat | 11 + utils/Install/builder/mondrian.ico | Bin 0 -> 766 bytes utils/Install/builder/mondrian.xpm | 44 + utils/Install/builder/wxib.RES | Bin 0 -> 16692 bytes utils/Install/builder/wxib.cpp | 629 ++++++ utils/Install/builder/wxib.cpp.1 | 500 +++++ utils/Install/builder/wxib.def | 8 + utils/Install/builder/wxib.rc | 12 + utils/Install/incace/acestruc.h | 151 ++ utils/Install/incace/attribs.h | 33 + utils/Install/incace/declare.h | 38 + utils/Install/incace/globals.h | 90 + utils/Install/incace/os.h | 26 + utils/Install/incace/portable.h | 101 + utils/Install/incace/uac_comm.h | 14 + utils/Install/incace/uac_crc.h | 20 + utils/Install/incace/uac_crt.h | 12 + utils/Install/incace/uac_dcpr.h | 14 + utils/Install/incace/uac_sys.h | 18 + utils/Install/incace/unace.h | 66 + utils/Install/inczip/consts.h | 46 + utils/Install/inczip/crypt.h | 24 + utils/Install/inczip/ebcdic.h | 272 +++ utils/Install/inczip/globals.h | 395 ++++ utils/Install/inczip/inflate.h | 24 + utils/Install/inczip/nt.h | 28 + utils/Install/inczip/os2acl.h | 29 + utils/Install/inczip/os2cfg.h | 136 ++ utils/Install/inczip/os2data.h | 139 ++ utils/Install/inczip/rsxntwin.h | 155 ++ utils/Install/inczip/tables.h | 81 + utils/Install/inczip/ttyio.h | 186 ++ utils/Install/inczip/unzip.h | 548 +++++ utils/Install/inczip/unzpriv.h | 2384 ++++++++++++++++++++ utils/Install/inczip/version.h | 44 + utils/Install/inczip/w32cfg.h | 222 ++ utils/Install/inczip/zip.h | 15 + utils/Install/install.c | 1081 ++++++++++ utils/Install/install.h | 116 + utils/Install/instsup.cpp | 426 ++++ utils/Install/instsup.h | 25 + utils/Install/packace/globals.c | 134 ++ utils/Install/packace/makefile | 46 + utils/Install/packace/makefile.b32 | 41 + utils/Install/packace/makefile.g95 | 46 + utils/Install/packace/makefile.gcc | 46 + utils/Install/packace/uac_comm.c | 51 + utils/Install/packace/uac_crc.c | 36 + utils/Install/packace/uac_crt.c | 149 ++ utils/Install/packace/uac_dcpr.c | 553 +++++ utils/Install/packace/uac_sys.c | 105 + utils/Install/packace/unace.c | 584 +++++ utils/Install/packzip/api.c | 601 ++++++ utils/Install/packzip/apihelp.c | 147 ++ utils/Install/packzip/crc32.c | 56 + utils/Install/packzip/crc_i386.S | 230 ++ utils/Install/packzip/crc_i386.asm | 229 ++ utils/Install/packzip/crc_i386.c | 215 ++ utils/Install/packzip/crc_lcc.asm | 108 + utils/Install/packzip/crctab.c | 219 ++ utils/Install/packzip/crypt.c | 12 + utils/Install/packzip/envargs.c | 314 +++ utils/Install/packzip/explode.c | 871 ++++++++ utils/Install/packzip/extract.c | 1985 +++++++++++++++++ utils/Install/packzip/fileio.c | 2153 +++++++++++++++++++ utils/Install/packzip/funzip.c | 468 ++++ utils/Install/packzip/globals.c | 204 ++ utils/Install/packzip/inflate.c | 1305 +++++++++++ utils/Install/packzip/list.c | 649 ++++++ utils/Install/packzip/makefile | 146 ++ utils/Install/packzip/makefile.b32 | 118 + utils/Install/packzip/makefile.g95 | 158 ++ utils/Install/packzip/makefile.gcc | 146 ++ utils/Install/packzip/makefile.os2 | 670 ++++++ utils/Install/packzip/match.c | 294 +++ utils/Install/packzip/nt.c | 659 ++++++ utils/Install/packzip/os2.c | 2187 +++++++++++++++++++ utils/Install/packzip/os2acl.c | 381 ++++ utils/Install/packzip/process.c | 1383 ++++++++++++ utils/Install/packzip/rexxapi.c | 886 ++++++++ utils/Install/packzip/rexxapi.def | 18 + utils/Install/packzip/rexxhelp.c | 178 ++ utils/Install/packzip/stub.def | 6 + utils/Install/packzip/ttyio.c | 625 ++++++ utils/Install/packzip/unix.c | 1424 ++++++++++++ utils/Install/packzip/unreduce.c | 230 ++ utils/Install/packzip/unshrink.c | 301 +++ utils/Install/packzip/unzip.c | 1744 +++++++++++++++ utils/Install/packzip/unzip.def | 4 + utils/Install/packzip/unzipstb.c | 48 + utils/Install/packzip/win32.c | 2390 +++++++++++++++++++++ utils/Install/packzip/zipinfo.c | 1912 +++++++++++++++++ utils/Install/script/finished.ini | 9 + utils/Install/script/finished.wxr | 25 + utils/Install/script/install.bmp | Bin 0 -> 14418 bytes utils/Install/script/install.xpm | 292 +++ utils/Install/script/license.txt | 53 + utils/Install/script/nocheck.ini | 5 + utils/Install/script/page1.ini | 12 + utils/Install/script/page1.wxr | 27 + utils/Install/script/page2.ini | 11 + utils/Install/script/page2.wxr | 27 + utils/Install/script/page3.ini | 11 + utils/Install/script/page3.wxr | 29 + utils/Install/script/page4.ini | 11 + utils/Install/script/page4.wxr | 25 + utils/Install/script/readme.ini | 8 + utils/Install/script/readme.txt | 25 + utils/Install/script/wxinst.cfg | 62 + utils/Install/sfxace/globals.c | 137 ++ utils/Install/sfxace/install.PRJ | 50 + utils/Install/sfxace/install.def | 3 + utils/Install/sfxace/install.rc | 2 + utils/Install/sfxace/makefile | 47 + utils/Install/sfxace/makefile.b32 | 76 + utils/Install/sfxace/makefile.g95 | 53 + utils/Install/sfxace/makefile.gcc | 47 + utils/Install/sfxace/sfx.RES | Bin 0 -> 13744 bytes utils/Install/sfxace/sfx.rc | 2 + utils/Install/sfxace/uac_comm.c | 51 + utils/Install/sfxace/uac_crc.c | 36 + utils/Install/sfxace/uac_crt.c | 303 +++ utils/Install/sfxace/uac_dcpr.c | 554 +++++ utils/Install/sfxace/uac_sys.c | 96 + utils/Install/sfxace/unace.c | 555 +++++ utils/Install/sfxzip/api.c | 601 ++++++ utils/Install/sfxzip/apihelp.c | 147 ++ utils/Install/sfxzip/crc32.c | 56 + utils/Install/sfxzip/crc_i386.S | 230 ++ utils/Install/sfxzip/crc_i386.asm | 229 ++ utils/Install/sfxzip/crc_i386.c | 215 ++ utils/Install/sfxzip/crc_lcc.asm | 108 + utils/Install/sfxzip/crctab.c | 219 ++ utils/Install/sfxzip/crypt.c | 12 + utils/Install/sfxzip/envargs.c | 314 +++ utils/Install/sfxzip/explode.c | 871 ++++++++ utils/Install/sfxzip/extract.c | 1993 +++++++++++++++++ utils/Install/sfxzip/fileio.c | 2161 +++++++++++++++++++ utils/Install/sfxzip/funzip.c | 468 ++++ utils/Install/sfxzip/globals.c | 204 ++ utils/Install/sfxzip/inflate.c | 1305 +++++++++++ utils/Install/sfxzip/list.c | 644 ++++++ utils/Install/sfxzip/makefile | 142 ++ utils/Install/sfxzip/makefile.b32 | 135 ++ utils/Install/sfxzip/makefile.g95 | 164 ++ utils/Install/sfxzip/makefile.gcc | 142 ++ utils/Install/sfxzip/makefile.os2 | 670 ++++++ utils/Install/sfxzip/match.c | 294 +++ utils/Install/sfxzip/nt.c | 659 ++++++ utils/Install/sfxzip/os2.c | 2187 +++++++++++++++++++ utils/Install/sfxzip/os2acl.c | 381 ++++ utils/Install/sfxzip/process.c | 1400 ++++++++++++ utils/Install/sfxzip/rexxapi.c | 886 ++++++++ utils/Install/sfxzip/rexxhelp.c | 178 ++ utils/Install/sfxzip/sfx.RES | Bin 0 -> 13744 bytes utils/Install/sfxzip/sfx.rc | 2 + utils/Install/sfxzip/ttyio.c | 625 ++++++ utils/Install/sfxzip/unix.c | 1424 ++++++++++++ utils/Install/sfxzip/unreduce.c | 230 ++ utils/Install/sfxzip/unshrink.c | 301 +++ utils/Install/sfxzip/unzip.c | 1744 +++++++++++++++ utils/Install/sfxzip/unzipstb.c | 48 + utils/Install/sfxzip/win32.c | 2390 +++++++++++++++++++++ utils/Install/sfxzip/zipinfo.c | 1912 +++++++++++++++++ utils/Install/wxmain.cpp | 315 +++ 195 files changed, 64870 insertions(+) create mode 100644 utils/Install/builder/ToolbarVC.dsp create mode 100644 utils/Install/builder/ToolbarVC.dsw create mode 100644 utils/Install/builder/bitmaps/copy.bmp create mode 100644 utils/Install/builder/bitmaps/copy.xpm create mode 100644 utils/Install/builder/bitmaps/cut.bmp create mode 100644 utils/Install/builder/bitmaps/cut.xpm create mode 100644 utils/Install/builder/bitmaps/help.bmp create mode 100644 utils/Install/builder/bitmaps/help.xpm create mode 100644 utils/Install/builder/bitmaps/new.bmp create mode 100644 utils/Install/builder/bitmaps/new.xpm create mode 100644 utils/Install/builder/bitmaps/open.bmp create mode 100644 utils/Install/builder/bitmaps/open.xpm create mode 100644 utils/Install/builder/bitmaps/page.bmp create mode 100644 utils/Install/builder/bitmaps/paste.bmp create mode 100644 utils/Install/builder/bitmaps/preview.bmp create mode 100644 utils/Install/builder/bitmaps/preview.xpm create mode 100644 utils/Install/builder/bitmaps/print.bmp create mode 100644 utils/Install/builder/bitmaps/print.xpm create mode 100644 utils/Install/builder/bitmaps/save.bmp create mode 100644 utils/Install/builder/bitmaps/save.xpm create mode 100644 utils/Install/builder/makefile create mode 100644 utils/Install/builder/makefile.b32 create mode 100644 utils/Install/builder/makefile.bcc create mode 100644 utils/Install/builder/makefile.dos create mode 100644 utils/Install/builder/makefile.g95 create mode 100644 utils/Install/builder/makefile.sc create mode 100644 utils/Install/builder/makefile.sl create mode 100644 utils/Install/builder/makefile.twn create mode 100644 utils/Install/builder/makefile.unx create mode 100644 utils/Install/builder/makefile.vc create mode 100644 utils/Install/builder/makefile.wat create mode 100644 utils/Install/builder/mondrian.ico create mode 100644 utils/Install/builder/mondrian.xpm create mode 100644 utils/Install/builder/wxib.RES create mode 100644 utils/Install/builder/wxib.cpp create mode 100644 utils/Install/builder/wxib.cpp.1 create mode 100644 utils/Install/builder/wxib.def create mode 100644 utils/Install/builder/wxib.rc create mode 100644 utils/Install/incace/acestruc.h create mode 100644 utils/Install/incace/attribs.h create mode 100644 utils/Install/incace/declare.h create mode 100644 utils/Install/incace/globals.h create mode 100644 utils/Install/incace/os.h create mode 100644 utils/Install/incace/portable.h create mode 100644 utils/Install/incace/uac_comm.h create mode 100644 utils/Install/incace/uac_crc.h create mode 100644 utils/Install/incace/uac_crt.h create mode 100644 utils/Install/incace/uac_dcpr.h create mode 100644 utils/Install/incace/uac_sys.h create mode 100644 utils/Install/incace/unace.h create mode 100644 utils/Install/inczip/consts.h create mode 100644 utils/Install/inczip/crypt.h create mode 100644 utils/Install/inczip/ebcdic.h create mode 100644 utils/Install/inczip/globals.h create mode 100644 utils/Install/inczip/inflate.h create mode 100644 utils/Install/inczip/nt.h create mode 100644 utils/Install/inczip/os2acl.h create mode 100644 utils/Install/inczip/os2cfg.h create mode 100644 utils/Install/inczip/os2data.h create mode 100644 utils/Install/inczip/rsxntwin.h create mode 100644 utils/Install/inczip/tables.h create mode 100644 utils/Install/inczip/ttyio.h create mode 100644 utils/Install/inczip/unzip.h create mode 100644 utils/Install/inczip/unzpriv.h create mode 100644 utils/Install/inczip/version.h create mode 100644 utils/Install/inczip/w32cfg.h create mode 100644 utils/Install/inczip/zip.h create mode 100644 utils/Install/install.c create mode 100644 utils/Install/install.h create mode 100644 utils/Install/instsup.cpp create mode 100644 utils/Install/instsup.h create mode 100644 utils/Install/packace/globals.c create mode 100644 utils/Install/packace/makefile create mode 100644 utils/Install/packace/makefile.b32 create mode 100644 utils/Install/packace/makefile.g95 create mode 100644 utils/Install/packace/makefile.gcc create mode 100644 utils/Install/packace/uac_comm.c create mode 100644 utils/Install/packace/uac_crc.c create mode 100644 utils/Install/packace/uac_crt.c create mode 100644 utils/Install/packace/uac_dcpr.c create mode 100644 utils/Install/packace/uac_sys.c create mode 100644 utils/Install/packace/unace.c create mode 100644 utils/Install/packzip/api.c create mode 100644 utils/Install/packzip/apihelp.c create mode 100644 utils/Install/packzip/crc32.c create mode 100644 utils/Install/packzip/crc_i386.S create mode 100644 utils/Install/packzip/crc_i386.asm create mode 100644 utils/Install/packzip/crc_i386.c create mode 100644 utils/Install/packzip/crc_lcc.asm create mode 100644 utils/Install/packzip/crctab.c create mode 100644 utils/Install/packzip/crypt.c create mode 100644 utils/Install/packzip/envargs.c create mode 100644 utils/Install/packzip/explode.c create mode 100644 utils/Install/packzip/extract.c create mode 100644 utils/Install/packzip/fileio.c create mode 100644 utils/Install/packzip/funzip.c create mode 100644 utils/Install/packzip/globals.c create mode 100644 utils/Install/packzip/inflate.c create mode 100644 utils/Install/packzip/list.c create mode 100644 utils/Install/packzip/makefile create mode 100644 utils/Install/packzip/makefile.b32 create mode 100644 utils/Install/packzip/makefile.g95 create mode 100644 utils/Install/packzip/makefile.gcc create mode 100644 utils/Install/packzip/makefile.os2 create mode 100644 utils/Install/packzip/match.c create mode 100644 utils/Install/packzip/nt.c create mode 100644 utils/Install/packzip/os2.c create mode 100644 utils/Install/packzip/os2acl.c create mode 100644 utils/Install/packzip/process.c create mode 100644 utils/Install/packzip/rexxapi.c create mode 100644 utils/Install/packzip/rexxapi.def create mode 100644 utils/Install/packzip/rexxhelp.c create mode 100644 utils/Install/packzip/stub.def create mode 100644 utils/Install/packzip/ttyio.c create mode 100644 utils/Install/packzip/unix.c create mode 100644 utils/Install/packzip/unreduce.c create mode 100644 utils/Install/packzip/unshrink.c create mode 100644 utils/Install/packzip/unzip.c create mode 100644 utils/Install/packzip/unzip.def create mode 100644 utils/Install/packzip/unzipstb.c create mode 100644 utils/Install/packzip/win32.c create mode 100644 utils/Install/packzip/zipinfo.c create mode 100644 utils/Install/script/finished.ini create mode 100644 utils/Install/script/finished.wxr create mode 100644 utils/Install/script/install.bmp create mode 100644 utils/Install/script/install.xpm create mode 100644 utils/Install/script/license.txt create mode 100644 utils/Install/script/nocheck.ini create mode 100644 utils/Install/script/page1.ini create mode 100644 utils/Install/script/page1.wxr create mode 100644 utils/Install/script/page2.ini create mode 100644 utils/Install/script/page2.wxr create mode 100644 utils/Install/script/page3.ini create mode 100644 utils/Install/script/page3.wxr create mode 100644 utils/Install/script/page4.ini create mode 100644 utils/Install/script/page4.wxr create mode 100644 utils/Install/script/readme.ini create mode 100644 utils/Install/script/readme.txt create mode 100644 utils/Install/script/wxinst.cfg create mode 100644 utils/Install/sfxace/globals.c create mode 100644 utils/Install/sfxace/install.PRJ create mode 100644 utils/Install/sfxace/install.def create mode 100644 utils/Install/sfxace/install.rc create mode 100644 utils/Install/sfxace/makefile create mode 100644 utils/Install/sfxace/makefile.b32 create mode 100644 utils/Install/sfxace/makefile.g95 create mode 100644 utils/Install/sfxace/makefile.gcc create mode 100644 utils/Install/sfxace/sfx.RES create mode 100644 utils/Install/sfxace/sfx.rc create mode 100644 utils/Install/sfxace/uac_comm.c create mode 100644 utils/Install/sfxace/uac_crc.c create mode 100644 utils/Install/sfxace/uac_crt.c create mode 100644 utils/Install/sfxace/uac_dcpr.c create mode 100644 utils/Install/sfxace/uac_sys.c create mode 100644 utils/Install/sfxace/unace.c create mode 100644 utils/Install/sfxzip/api.c create mode 100644 utils/Install/sfxzip/apihelp.c create mode 100644 utils/Install/sfxzip/crc32.c create mode 100644 utils/Install/sfxzip/crc_i386.S create mode 100644 utils/Install/sfxzip/crc_i386.asm create mode 100644 utils/Install/sfxzip/crc_i386.c create mode 100644 utils/Install/sfxzip/crc_lcc.asm create mode 100644 utils/Install/sfxzip/crctab.c create mode 100644 utils/Install/sfxzip/crypt.c create mode 100644 utils/Install/sfxzip/envargs.c create mode 100644 utils/Install/sfxzip/explode.c create mode 100644 utils/Install/sfxzip/extract.c create mode 100644 utils/Install/sfxzip/fileio.c create mode 100644 utils/Install/sfxzip/funzip.c create mode 100644 utils/Install/sfxzip/globals.c create mode 100644 utils/Install/sfxzip/inflate.c create mode 100644 utils/Install/sfxzip/list.c create mode 100644 utils/Install/sfxzip/makefile create mode 100644 utils/Install/sfxzip/makefile.b32 create mode 100644 utils/Install/sfxzip/makefile.g95 create mode 100644 utils/Install/sfxzip/makefile.gcc create mode 100644 utils/Install/sfxzip/makefile.os2 create mode 100644 utils/Install/sfxzip/match.c create mode 100644 utils/Install/sfxzip/nt.c create mode 100644 utils/Install/sfxzip/os2.c create mode 100644 utils/Install/sfxzip/os2acl.c create mode 100644 utils/Install/sfxzip/process.c create mode 100644 utils/Install/sfxzip/rexxapi.c create mode 100644 utils/Install/sfxzip/rexxhelp.c create mode 100644 utils/Install/sfxzip/sfx.RES create mode 100644 utils/Install/sfxzip/sfx.rc create mode 100644 utils/Install/sfxzip/ttyio.c create mode 100644 utils/Install/sfxzip/unix.c create mode 100644 utils/Install/sfxzip/unreduce.c create mode 100644 utils/Install/sfxzip/unshrink.c create mode 100644 utils/Install/sfxzip/unzip.c create mode 100644 utils/Install/sfxzip/unzipstb.c create mode 100644 utils/Install/sfxzip/win32.c create mode 100644 utils/Install/sfxzip/zipinfo.c create mode 100644 utils/Install/wxmain.cpp diff --git a/utils/Install/builder/ToolbarVC.dsp b/utils/Install/builder/ToolbarVC.dsp new file mode 100644 index 0000000000..743b1d28d4 --- /dev/null +++ b/utils/Install/builder/ToolbarVC.dsp @@ -0,0 +1,175 @@ +# Microsoft Developer Studio Project File - Name="ToolbarVC" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=ToolbarVC - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ToolbarVC.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ToolbarVC.mak" CFG="ToolbarVC - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ToolbarVC - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "ToolbarVC - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE "ToolbarVC - Win32 Debug DLL" (based on "Win32 (x86) Application") +!MESSAGE "ToolbarVC - Win32 Release DLL" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ToolbarVC - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O1 /Ob2 /I "../../include" /I "../../contrib/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__WINDOWS__" /D "__WXMSW__" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "STRICT" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib winmm.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib rpcrt4.lib wsock32.lib winmm.lib wx.lib xpm.lib png.lib zlib.lib jpeg.lib tiff.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libci.lib" /nodefaultlib:"msvcrtd.lib" /out:"Release/toolbar.exe" /libpath:"../../lib" /libpath:"../../contrib/lib" + +!ELSEIF "$(CFG)" == "ToolbarVC - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /I "../../contrib/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__WINDOWS__" /D "__WXMSW__" /D DEBUG=1 /D "__WXDEBUG__" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "STRICT" /Yu"wx/wxprec.h" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib winmm.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib rpcrt4.lib wsock32.lib winmm.lib wxd.lib xpmd.lib pngd.lib zlibd.lib jpegd.lib tiffd.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd.lib" /nodefaultlib:"libcid.lib" /nodefaultlib:"msvcrt.lib" /out:"Debug/toolbar.exe" /pdbtype:sept /libpath:"../../lib" /libpath:"../../contrib/lib" + +!ELSEIF "$(CFG)" == "ToolbarVC - Win32 Debug DLL" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "DebugDLL" +# PROP BASE Intermediate_Dir "DebugDLL" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DebugDLL" +# PROP Intermediate_Dir "DebugDLL" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /I "../../contrib/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__WINDOWS__" /D "__WXMSW__" /D DEBUG=1 /D "__WXDEBUG__" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "STRICT" /D WXUSINGDLL=1 /Yu"wx/wxprec.h" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib winmm.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib rpcrt4.lib wsock32.lib winmm.lib wxdlld.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcd.lib" /nodefaultlib:"libcid.lib" /out:"DebugDLL/toolbar.exe" /pdbtype:sept /libpath:"../../lib" /libpath:"../../contrib/lib" + +!ELSEIF "$(CFG)" == "ToolbarVC - Win32 Release DLL" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ReleaseDLL" +# PROP BASE Intermediate_Dir "ReleaseDLL" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "ReleaseDLL" +# PROP Intermediate_Dir "ReleaseDLL" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O1 /Ob2 /I "../../include" /I "../../contrib/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__WINDOWS__" /D "__WXMSW__" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "STRICT" /D WXUSINGDLL=1 /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib winmm.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib rpcrt4.lib wsock32.lib winmm.lib wxdll.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libci.lib" /out:"ReleaseDLL/toolbar.exe" /libpath:"../../lib" /libpath:"../../contrib/lib" + +!ENDIF + +# Begin Target + +# Name "ToolbarVC - Win32 Release" +# Name "ToolbarVC - Win32 Debug" +# Name "ToolbarVC - Win32 Debug DLL" +# Name "ToolbarVC - Win32 Release DLL" +# Begin Source File + +SOURCE=.\toolbar.cpp + +!IF "$(CFG)" == "ToolbarVC - Win32 Release" + +!ELSEIF "$(CFG)" == "ToolbarVC - Win32 Debug" + +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ToolbarVC - Win32 Debug DLL" + +# SUBTRACT BASE CPP /YX /Yc /Yu +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "ToolbarVC - Win32 Release DLL" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\toolbar.rc +# ADD BASE RSC /l 0x809 +# ADD RSC /l 0x809 /i "../../include" /i "../../contrib/include" +# End Source File +# End Target +# End Project diff --git a/utils/Install/builder/ToolbarVC.dsw b/utils/Install/builder/ToolbarVC.dsw new file mode 100644 index 0000000000..37a469560f --- /dev/null +++ b/utils/Install/builder/ToolbarVC.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "ToolbarVC"=.\ToolbarVC.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/utils/Install/builder/bitmaps/copy.bmp b/utils/Install/builder/bitmaps/copy.bmp new file mode 100644 index 0000000000000000000000000000000000000000..4551a06bfa79e0a42c1ffb7cdbb90fd4f699dce2 GIT binary patch literal 238 zcmZvVK?*`K3`9pLxU9$U91{2|@hV+>tjiv)Cz3AyzP{vxy7<$~OeTT!c7JQf6T89- z%?kmn<${;(P#uFN<0A#FuUo(qgT{&F@ekspii W=d@ZzPG(Cb=QBs}_=7thzxV(viB<;y literal 0 HcmV?d00001 diff --git a/utils/Install/builder/bitmaps/copy.xpm b/utils/Install/builder/bitmaps/copy.xpm new file mode 100644 index 0000000000..47565c1cae --- /dev/null +++ b/utils/Install/builder/bitmaps/copy.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char *copy_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 4 1", +" c None", +". c Black", +"X c Gray100", +"o c #000080", +/* pixels */ +" ", +" ...... ", +" .XXXX.. ", +" .XXXX.X. ", +" .X..X.oooooo ", +" .XXXXXoXXXXoo ", +" .X....oXXXXoXo ", +" .XXXXXoX..Xoooo", +" .X....oXXXXXXXo", +" .XXXXXoX.....Xo", +" ......oXXXXXXXo", +" oX.....Xo", +" oXXXXXXXo", +" ooooooooo", +" " +}; diff --git a/utils/Install/builder/bitmaps/cut.bmp b/utils/Install/builder/bitmaps/cut.bmp new file mode 100644 index 0000000000000000000000000000000000000000..15554338a01bc4d8f0a501c32237e84200e64583 GIT binary patch literal 238 zcmZvU!3}^Q5Cqr6gr}Ba8OD(CvKJo2^+{<|WDB@(K8*2TclNjo+kV075Ef~cCTYMZ z2hQ$)mH}PlY>+FWlp?l4?H9GSBqTFi~p=nI%+}YJ={H-mN0|?29BK#fUL#erbtT(lh^R?4vYy(d-6AGn1|j$rr}v KbDqI%Xjd+{i$y;G literal 0 HcmV?d00001 diff --git a/utils/Install/builder/bitmaps/help.xpm b/utils/Install/builder/bitmaps/help.xpm new file mode 100644 index 0000000000..50fdb4157e --- /dev/null +++ b/utils/Install/builder/bitmaps/help.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char *help_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 4 1", +" c None", +". c Black", +"X c Blue", +"o c #000080", +/* pixels */ +" ", +" ...... ", +" .XXXXX.. ", +" .XX...oX.. ", +" .X.. .X.. ", +" .X.. .XX.. ", +" .. .XX.. ", +" .XX.. ", +" .X.. ", +" .X.. ", +" .o.. ", +" .. ", +" .XX.. ", +" .XX.. ", +" ... " +}; diff --git a/utils/Install/builder/bitmaps/new.bmp b/utils/Install/builder/bitmaps/new.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d66feb2384ad4c626a078c995c1a3e49af78ec3c GIT binary patch literal 238 zcmbu2yA6Oa5JQcGL>b0l4tjP;1(ew=nJ8j|<6WY3bU0`GK9aK^RUId`!4(ELX-1{H u>6c`QQqJ8_T9s0iQsQ8(Wab^@`3kuPA_p->w)Xt4Pkz>06 literal 0 HcmV?d00001 diff --git a/utils/Install/builder/bitmaps/new.xpm b/utils/Install/builder/bitmaps/new.xpm new file mode 100644 index 0000000000..754d2d20a2 --- /dev/null +++ b/utils/Install/builder/bitmaps/new.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *new_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 3 1", +" c None", +". c Black", +"X c Gray100", +/* pixels */ +" ", +" ........ ", +" .XXXXXX.. ", +" .XXXXXX.X. ", +" .XXXXXX.... ", +" .XXXXXXXXX. ", +" .XXXXXXXXX. ", +" .XXXXXXXXX. ", +" .XXXXXXXXX. ", +" .XXXXXXXXX. ", +" .XXXXXXXXX. ", +" .XXXXXXXXX. ", +" .XXXXXXXXX. ", +" ........... ", +" " +}; diff --git a/utils/Install/builder/bitmaps/open.bmp b/utils/Install/builder/bitmaps/open.bmp new file mode 100644 index 0000000000000000000000000000000000000000..bbf93fe03364e63f3e18a3507a0e85ab8ea2f87d GIT binary patch literal 238 zcmXv{u@M3>3=;=;U&0ua+_3>YyQsonW~6N3OvKTr2(k@|B{{YeKb~(CUb3rr5zpcQ zCn>O}mP9XDa6kd~GO1FGG0<95V`X5i$V8neN$dxz4&8XX3!AZr-;ApY^eS-9oTLj~ Y^Hcc9z2|$wrXTtLH=Rc2n(WoWFRhqJ00000 literal 0 HcmV?d00001 diff --git a/utils/Install/builder/bitmaps/open.xpm b/utils/Install/builder/bitmaps/open.xpm new file mode 100644 index 0000000000..54748e910d --- /dev/null +++ b/utils/Install/builder/bitmaps/open.xpm @@ -0,0 +1,26 @@ +/* XPM */ +static char *open_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 5 1", +" c None", +". c Black", +"X c Yellow", +"o c Gray100", +"O c #bfbf00", +/* pixels */ +" ", +" ... ", +" . . .", +" ..", +" ... ...", +" .XoX....... ", +" .oXoXoXoXo. ", +" .XoXoXoXoX. ", +" .oXoX..........", +" .XoX.OOOOOOOOO.", +" .oo.OOOOOOOOO. ", +" .X.OOOOOOOOO. ", +" ..OOOOOOOOO. ", +" ........... ", +" " +}; diff --git a/utils/Install/builder/bitmaps/page.bmp b/utils/Install/builder/bitmaps/page.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3dbd4b05b4c2d1a4f046141d450caf34c1a3d470 GIT binary patch literal 714 zcmaJk)fu{chJ-2TT-iZmtVS?uc5roS;-EuD8k*^vaH9hj_d6X ziQgC358^U$kRpEdIqzx8X~Jz0i&xCtBKWwA%eHOw^mwIrw+KG&;&N&1L*Q{1Xmx8p zxBo0O*pac2@{B`!>-fgLdSDP(C2}M>_DcBv60g*0UKyHhy!Oc8UYD-XBeIyOWTry_ zTA4Yuua#Ixm?vFMcI3@F*>XSp02Lyo AJ^%m! literal 0 HcmV?d00001 diff --git a/utils/Install/builder/bitmaps/paste.bmp b/utils/Install/builder/bitmaps/paste.bmp new file mode 100644 index 0000000000000000000000000000000000000000..564f514e0df7225f0a7adbe8457b41af537813bd GIT binary patch literal 238 zcmZvVF%Ci@5Jbns$83OZ*I;# co}I%%@f6>ra3+S=gC69}eM%GII+SAI4J;x>B>(^b literal 0 HcmV?d00001 diff --git a/utils/Install/builder/bitmaps/preview.bmp b/utils/Install/builder/bitmaps/preview.bmp new file mode 100644 index 0000000000000000000000000000000000000000..da1f4dbc4be6c2dd8fb9d7cb71cc48a4a7c139ca GIT binary patch literal 238 zcmZvVu?@p83pv2yNo4mlT?N_pr2ISnd1NHDM5O^cFcMc59&^> z)PfrwsOeYM05)2ipmU4fJIss+o(=cdQCu+!%TlZiKDH!a!aP2;C|UGpLD9M;zmsLJ XIp;lzIUm!ckI6HO{IjaYcZ_-fA4^nl literal 0 HcmV?d00001 diff --git a/utils/Install/builder/bitmaps/preview.xpm b/utils/Install/builder/bitmaps/preview.xpm new file mode 100644 index 0000000000..7e5e9cd06e --- /dev/null +++ b/utils/Install/builder/bitmaps/preview.xpm @@ -0,0 +1,26 @@ +/* XPM */ +static char *paste_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 5 1", +" c Black", +". c None", +"X c Gray100", +"o c #808080", +"O c Cyan", +/* pixels */ +" .......", +" XXXXXXX ......", +" XXXXXXX . .....", +" XXXXXXX ....", +" XXXXXXXXXX ....", +" XXXXXXX ....", +" XXXXXX o..o ...", +" XXXXX oOO.oo ..", +" XXXXX .O..o. ..", +" XXXXX ....o. ..", +" XXXXX o..Ooo ..", +" XXXXXX o..o o..", +" XXXXXXX o .", +" XXXXXXXXXX . ", +" .. " +}; diff --git a/utils/Install/builder/bitmaps/print.bmp b/utils/Install/builder/bitmaps/print.bmp new file mode 100644 index 0000000000000000000000000000000000000000..00319b55bb23c3c69cc051144d80e5275747c53e GIT binary patch literal 238 zcmZur!3_d23^Ni^o@EUFY`~vgA|YX<`*bfpod|VizM>j+f}Fx~Q7! zgtHKM7yg3|DAD^Sp<0YF#C}+nSj(MC$5#Ss27*aN<{l9dYV3`7rsq)3!X>4ws(){6V0MX5FKAjcylGXqN-n#XsS=YhW0WogZT{L^_i_GT%*k@+ph E1NJ~MtpET3 literal 0 HcmV?d00001 diff --git a/utils/Install/builder/bitmaps/save.xpm b/utils/Install/builder/bitmaps/save.xpm new file mode 100644 index 0000000000..01b18f9340 --- /dev/null +++ b/utils/Install/builder/bitmaps/save.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char *save_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 4 1", +" c None", +". c Black", +"X c #808000", +"o c #808080", +/* pixels */ +" ", +" .............. ", +" .X. . . ", +" .X. ... ", +" .X. .X. ", +" .X. .X. ", +" .X. .X. ", +" .X. .X. ", +" .XX........oX. ", +" .XXXXXXXXXXXX. ", +" .XX.........X. ", +" .XX...... .X. ", +" .XX...... .X. ", +" .XX...... .X. ", +" ............. " +}; diff --git a/utils/Install/builder/makefile b/utils/Install/builder/makefile new file mode 100644 index 0000000000..b718b54009 --- /dev/null +++ b/utils/Install/builder/makefile @@ -0,0 +1,23 @@ +# Purpose: makefile for toolbar example (Unix) +# Created: 2000-03-14 + +CC = gcc + +PROGRAM = wxib + +OBJECTS = $(PROGRAM).o + +# implementation + +.SUFFIXES: .o .cpp + +.cpp.o : + $(CC) -c `wx-config --cflags` -o $@ $< + +all: $(PROGRAM) + +$(PROGRAM): $(OBJECTS) + $(CC) -o $(PROGRAM) $(OBJECTS) `wx-config --libs` + +clean: + rm -f *.o $(PROGRAM) diff --git a/utils/Install/builder/makefile.b32 b/utils/Install/builder/makefile.b32 new file mode 100644 index 0000000000..2f78f08cc2 --- /dev/null +++ b/utils/Install/builder/makefile.b32 @@ -0,0 +1,10 @@ +# Purpose: makefile for toolbar example (BC++ 32bit) +# Created: 2000-03-14 + +WXDIR = $(WXWIN) + +TARGET=wxib +OBJECTS = $(TARGET).obj + +!include $(WXDIR)\src\makeprog.b32 + diff --git a/utils/Install/builder/makefile.bcc b/utils/Install/builder/makefile.bcc new file mode 100644 index 0000000000..a622b7c6aa --- /dev/null +++ b/utils/Install/builder/makefile.bcc @@ -0,0 +1,14 @@ +# Purpose: makefile for toolbar example (BC++ 16bit) +# Created: 2000-03-14 + +!if "$(WXWIN)" == "" +!error You must define the WXWIN variable in autoexec.bat, e.g. WXWIN=c:\wx +!endif + +WXDIR = $(WXWIN) + +TARGET=toolbar +OBJECTS=$(TARGET).obj + +!include $(WXDIR)\src\makeprog.bcc + diff --git a/utils/Install/builder/makefile.dos b/utils/Install/builder/makefile.dos new file mode 100644 index 0000000000..bb6f8d0c48 --- /dev/null +++ b/utils/Install/builder/makefile.dos @@ -0,0 +1,10 @@ +# Purpose: makefile for toolbar example (VC++ 1.5x) +# Created: 2000-03-14 + +WXDIR = $(WXWIN) + +TARGET=toolbar +OBJECTS=$(TARGET).obj + +!include $(WXDIR)\src\makeprog.msc + diff --git a/utils/Install/builder/makefile.g95 b/utils/Install/builder/makefile.g95 new file mode 100644 index 0000000000..25bcc5b88a --- /dev/null +++ b/utils/Install/builder/makefile.g95 @@ -0,0 +1,10 @@ +# Purpose: makefile for toolbar example (Cygwin/Mingw32) +# Created: #03.01.00 + +WXDIR = ../.. + +TARGET=toolbar +OBJECTS = $(TARGET).o + +include $(WXDIR)\src\makeprog.g95 + diff --git a/utils/Install/builder/makefile.sc b/utils/Install/builder/makefile.sc new file mode 100644 index 0000000000..6de8e6893c --- /dev/null +++ b/utils/Install/builder/makefile.sc @@ -0,0 +1,37 @@ +# Purpose: makefile for toolbar example (Symantec C++) +# Created: 2000-03-14 + +WXDIR = $(WXWIN) +WXLIB = $(WXDIR)\lib\wx.lib +INCDIR = $(WXDIR)\include +INCLUDE=$(INCDIR) +TARGET=toolbar + +include $(WXDIR)\src\makesc.env + +toolbar.exe: toolbar.obj $(DEFFILE) toolbar.res + *$(CC) $(LDFLAGS) -o$@ $** $(LIBS) + *$(RC) -k toolbar.res + +sc32.def: + echo EXETYPE NT > sc32.def + echo SUBSYSTEM WINDOWS >> sc32.def + +sc16.def: + echo NAME $(TARGET) > sc16.def + echo EXETYPE WINDOWS >> sc16.def + echo STUB 'WINSTUB.EXE' >> sc16.def + echo CODE PRELOAD MOVEABLE DISCARDABLE >> sc16.def + echo DATA PRELOAD MOVEABLE MULTIPLE >> sc16.def + echo HEAPSIZE 1024 >> sc16.def + echo STACKSIZE 8192 >> sc16.def + +clean: + -del *.obj + -del *.exe + -del *.res + -del *.map + -del *.rws + -del sc32.def + -del sc16.def + diff --git a/utils/Install/builder/makefile.sl b/utils/Install/builder/makefile.sl new file mode 100644 index 0000000000..216b087cf2 --- /dev/null +++ b/utils/Install/builder/makefile.sl @@ -0,0 +1,14 @@ +# Purpose: makefile for toolbar example (Salford C++) +# Created: 2000-03-14 + +PROGRAM = toolbar +OBJECTS = $(PROGRAM).obj + +include ..\..\src\makeprog.sl + +all: wx $(TARGET) + +wx: + cd $(WXDIR)\src\msw ^ mk32 -f makefile.sl all + cd $(WXDIR)\samples\toolbar + diff --git a/utils/Install/builder/makefile.twn b/utils/Install/builder/makefile.twn new file mode 100644 index 0000000000..fd89e57b4b --- /dev/null +++ b/utils/Install/builder/makefile.twn @@ -0,0 +1,35 @@ +# Purpose: makefile for toolbar example (TWIN) +# Created: 2000-03-14 + +WXDIR = ../.. + +# All common UNIX compiler flags and options are now in +# this central makefile. +include $(WXDIR)/src/maketwin.env + +OBJECTS = $(OBJDIR)/toolbar.$(OBJSUFF) $(OBJDIR)/toolbar.$(OBJSUFF) + +all: $(OBJDIR) toolbar$(GUISUFFIX)$(EXESUFF) + +wx: + +$(OBJDIR): + mkdir $(OBJDIR) + +toolbar$(GUISUFFIX)$(EXESUFF): $(OBJECTS) $(WXLIB) + $(CC) $(LDFLAGS) -o toolbar$(GUISUFFIX)$(EXESUFF) $(OBJECTS) $(LDLIBS) + +$(OBJDIR)/toolbar.$(OBJSUFF): toolbar.$(SRCSUFF) + $(CC) -c $(CPPFLAGS) -o $@ toolbar.$(SRCSUFF) + +toolbar.c: toolbar.rc + $(RESCOMP) $(RCINPUTSWITCH) toolbar.rc $(RCOUTPUTSWITCH) toolbar.c $(RESFLAGS) + +$(OBJDIR)/toolbar.$(OBJSUFF): toolbar.c + $(CC) -c $(CPPFLAGS) -o $@ toolbar.c + +#$(OBJDIR)/toolbar.o: toolbar.rc +# $(RESCOMP) $(RCINPUTSWITCH) toolbar.rc $(RCOUTPUTSWITCH) $(OBJDIR)/toolbar.o $(RESFLAGS) + +clean: + rm -f $(OBJECTS) toolbar$(GUISUFFIX).exe core *.rsc *.res diff --git a/utils/Install/builder/makefile.unx b/utils/Install/builder/makefile.unx new file mode 100644 index 0000000000..91d51a0bd1 --- /dev/null +++ b/utils/Install/builder/makefile.unx @@ -0,0 +1,23 @@ +# Purpose: makefile for toolbar example (Unix) +# Created: 2000-03-14 + +CC = gcc + +PROGRAM = toolbar + +OBJECTS = $(PROGRAM).o + +# implementation + +.SUFFIXES: .o .cpp + +.cpp.o : + $(CC) -c `wx-config --cflags` -o $@ $< + +all: $(PROGRAM) + +$(PROGRAM): $(OBJECTS) + $(CC) -o $(PROGRAM) $(OBJECTS) `wx-config --libs` + +clean: + rm -f *.o $(PROGRAM) diff --git a/utils/Install/builder/makefile.vc b/utils/Install/builder/makefile.vc new file mode 100644 index 0000000000..af02a4b4bd --- /dev/null +++ b/utils/Install/builder/makefile.vc @@ -0,0 +1,11 @@ +# Purpose: makefile for toolbar example (VC++ 32bit) +# Created: 2000-03-14 + +# Set WXDIR for your system +WXDIR = $(WXWIN) + +PROGRAM=toolbar +OBJECTS = $(PROGRAM).obj + +!include $(WXDIR)\src\makeprog.vc + diff --git a/utils/Install/builder/makefile.wat b/utils/Install/builder/makefile.wat new file mode 100644 index 0000000000..95c26443ed --- /dev/null +++ b/utils/Install/builder/makefile.wat @@ -0,0 +1,11 @@ +# Purpose: makefile for toolbar example (Watcom) +# Created: 2000-03-14 + +WXDIR = $(%WXWIN) + +PROGRAM = toolbar +OBJECTS = $(PROGRAM).obj + +!include $(WXDIR)\src\makeprog.wat + + diff --git a/utils/Install/builder/mondrian.ico b/utils/Install/builder/mondrian.ico new file mode 100644 index 0000000000000000000000000000000000000000..2310c5d275a87af295d5ea8dc79ea417a5e74c53 GIT binary patch literal 766 zcmZQzU<5)11px*Sc)`TLAO@s0fLH;D9e|jTfdxnc0Z~$G!B2rU?*`?N8*_DA@)yrljlh0!Ghuo(1(h)@Gj^W+R2{_*rmX9tYRU z@(RZKs>I6kv-0B@*NgJHdg%XaNnzj7f+EjJ#laK=iKItD`I>qCUN7%x@tsi|>pUPaE9^ zG-guw&ra-@1F*1J{2qa(X{)q9!tnknVp*%$)3jM?#{O2pXZ2$bw5)#0QhxCI;lK!C zDl&PL8$zTyA@ZfOBD;PE=Yi2PCCzfylaKt%fRU@#u3(L!k8^)DrgqEpnqAZFJlDK+ z^J4ARjT^O_Z@+)>CjaJd50EsLS6L*j;}>!QX*&1Z3C@ECbg9 z0l8(nC-NM)vHB(e!h%c!Oq(#dnpH^$=GO&7?=A)~F@k^!sV94ujIyKs>WO#4yY1D{ zE@ewWPDdqemDSODS@#fiG>!gt1J7XLVK2q1$a{4OCK4&Z(kC2FNrIg+Kwn;h=?9Z& z-Uem>E456x4!+YsE;<*#V$4Jhey(XcSnr!Ko0~s2=AEB3&EM8qWS(WL>%5C5)D@a$ zfjVjcN88f#@O3lrc6($O@YC>r9>&{KDW|J7+AOQ92kQ627S0t|N)>xz=U+t5Zi0%c zNuk&Wi0~PbsNfe zDw(qg))KU!qO{qoB+YIGC*yOIweB;I)wh$@JltUamDq3UQpJXd&6|+=1ga9 zt_jnuwe09B%(IMj+X>u_^Nf%`%K0p;hxUPa)SGBUMTM_L6= z0UrZC3fur(lZX^kIM1UXu<2J9#_Q++Y>6?%z~hbAQJB-w1g3};$i(4O_hCncb~!1W zdpD6LquOQ?%->1FcDYr)ezRSfztj21i9i48xjXYGpS}I|Tf`IH+MiDt)5ouy<{wX( zCTNS#n&w-?PnzbjO7m2wGXI@U`TFZ^$_(beld=!(3w^S0MDXxc1MI*yU>CYQQfv=m z0)={%CBXABO#VanqAz*iI`V6~5t+hI;I@t=64X+e zn@{Bwd|L?Y01fCG!r*fz3EziZT38_yYmIzx2H*(Oa!CzH|5oNp{ z^>8<$|Laa!+%{b?Q$U%64o^adYoWgo`U{e~5oT9N3JA>u6ShKA#`C61r?SL-_Om#T z4&aYZ87++0(PU0XqkP>1(2*O<2bGvrhVgd9XXAW&=bv^j^~_TlBh4|FS7d1itnz}+p9+z^WG|i|I0$0qjUA;9Bqc^uslS^G3Yq< z;vxDRX;%=+1eBXd?7KXty6&JrTUZjeqEH!Ngbv!uK%%ptOk`-1?k-$s(vG80D;y08 zAH9vqz_enIt+B;@E*+J#+ z$pA!WJzxiz!Yv{aL43gYnQ=7Z>7a$PCj}tRfHNczW(~3v$q&kxdiwAe+x6 zvc7MlJ`>-A$eVA3j>u;b-|_vEe@7$=!@keH!z$ru{IFV7F=toyBELFz#YOG|#@^2} z6Y0x3J0;aeU|$y7-z1Ko&eB)HVfw14ugDLTFN`ezW!XUbN*Gyrj=mg=r5%5Qy%*Yj8~^Sn9r09&o{q5TuzAb0CsKQ=pT{HthZJVS~ya~=}Wn76X?^`_Rpq7 zZ6bR%g)P_|(4S9Bolz9+Z83XRg^)3HUhyee_PpALhWyTg-$)G3D?Za>l)l)zjJ!>i zayGRFQdiTa(0SGuaxgwfV4jex|M!XkxyJ!M2J9kcV$79^0W}2c$ADmP4QvePX&(c6 z+Q)qNNQ2$VZ`&A9`{Iv_0sFLz0nJ$r`3#)CjbUB;HrJiZj;0=Lkk}6q!SEj+13raW z-EC8Ro3RTvWnp~mwh*5e4!Hj&&LsHdc9ilz z`t{17`xB8G>fhG}O^8SMx3PD_P6-Sft_m1zH8wD+5j&Rsj6+L@wmbZuKy!qSeHw8i z_y;s98GH8YS4!vQYhXJNFL%*Hz4wQq8OC24hw-C^v;vcdvS7qL+K$fMRJSYKj_e(?T~&niaS6Yo;{QEOqmJ*}0m;d#Se zuo_d;vyR{X9YpkKzXUvj^e}E`hunQ_2Wk)DJ2-yV=j6-X-{DqK<-fy~dwia;obPa> z9E3T@RY$q%@c;G0EAXGTK3A~6rh(kE-0eH@OpZJC`TnkC{qVlz6H=nzmwx}ECr9bnC@IXgv-AdO^#rDOfd)UAeZ)&U2^6od;o?!!uotdG-fx zAJ$=>m@&ui5!2JWPhGj^L#@u&-|*^)(5){kLWBH5_z-4!82RyYr4M`r=ym!h}@WJaNWBZvsnBAM%JsW5C^02R1fj;ijZd4y` z%&L#9UY*R*e(8%i<^Om55;TlmtA3v=1k^lEgGk=ge01qjNVMhTvE}NCJU=d5bH!L7`q2|Ts$sVQHtf!_GRuyhy$t7A4m@^bjRm5T!UFe zBRmZ~+{-#V=rgdt48fBC1g)2uPGcIjAey%Y(e2wh+-M$f8PmHB;IhqMMmc85Fb97`=mq~+xtDG+ZnptXhcfS&amE?2A%?zOAXurK+`Ii+C9N1h8bvK zoF50$F8Ke*4k1rimA#-B8_pQFml>PR;GRQT)41W%c*b3B>SP1heeSFPbZ93Th1MWo z3656s038Rd|RCz4ztUY-Xqybk=LZ{O@c)`12s9p5<1->0befWZjo5;%6$whAzOKW+ E09y(pIRF3v literal 0 HcmV?d00001 diff --git a/utils/Install/builder/wxib.cpp b/utils/Install/builder/wxib.cpp new file mode 100644 index 0000000000..810d307640 --- /dev/null +++ b/utils/Install/builder/wxib.cpp @@ -0,0 +1,629 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wxib.cpp +// Purpose: wxInstall Builder +// Author: Julian Smart +// Author: Brian Smith +// Modified by: +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// For compilers that support precompilation, includes "wx/wx.h". +#include + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include +#endif + +#include +#include +#include + +// define this to 1 to use wxToolBarSimple instead of the native one +#define USE_GENERIC_TBAR 0 + +#if USE_GENERIC_TBAR + #if !wxUSE_TOOLBAR_SIMPLE + #error wxToolBarSimple is not compiled in, set wxUSE_TOOLBAR_SIMPLE \ + to 1 in setup.h and recompile the library. + #else + #include + #endif +#endif // USE_GENERIC_TBAR + +// ---------------------------------------------------------------------------- +// resources +// ---------------------------------------------------------------------------- + +#if defined(__WXGTK__) || defined(__WXMOTIF__) + #include "mondrian.xpm" + #include "bitmaps/new.xpm" + #include "bitmaps/open.xpm" + #include "bitmaps/save.xpm" + #include "bitmaps/copy.xpm" + #include "bitmaps/cut.xpm" + #include "bitmaps/preview.xpm" // paste XPM + #include "bitmaps/print.xpm" + #include "bitmaps/help.xpm" +#endif // GTK or Motif + +char appName[] = "wxInstall Builder"; + +// ---------------------------------------------------------------------------- +// classes +// ---------------------------------------------------------------------------- + +// Define a new application +class MyApp : public wxApp +{ +public: + bool OnInit(); +}; + +// Define a new frame +class MyFrame: public wxFrame +{ +public: + MyFrame(wxFrame *parent, + wxWindowID id = -1, + const wxString& title = "wxInstall Builder", + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE); + + void RecreateToolbar(); + + void OnQuit(wxCommandEvent& event); + void OnAbout(wxCommandEvent& event); + + void OnNewScript(wxCommandEvent& event); + void OnOpenScript(wxCommandEvent& event); + void OnSaveScript(wxCommandEvent& event); + void OnNewProject(wxCommandEvent& event); + void OnOpenProject(wxCommandEvent& event); + void OnSaveProject(wxCommandEvent& event); + + void OnCut(wxCommandEvent& event); + void OnCopy(wxCommandEvent& event); + void OnPaste(wxCommandEvent& event); + + void OnListBoxDoubleClick(wxCommandEvent& event); + +#if USE_GENERIC_TBAR + virtual wxToolBar *OnCreateToolBar(long style, + wxWindowID id, + const wxString& name ); +#endif // USE_GENERIC_TBAR + +private: + bool m_smallToolbar, + m_horzToolbar; + size_t m_rows; // 1 or 2 only + + wxTextCtrl* m_textWindow; + wxListBox* m_listBox; + + DECLARE_EVENT_TABLE() +}; + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +const int ID_TOOLBAR = 500; + +enum +{ + ID_COMBO = 1000, + ID_LISTBOX, + wxID_NEW_SCRIPT, + wxID_SAVE_SCRIPT, + wxID_OPEN_SCRIPT, + wxID_NEW_PROJECT, + wxID_SAVE_PROJECT, + wxID_OPEN_PROJECT +}; + +// ---------------------------------------------------------------------------- +// event tables +// ---------------------------------------------------------------------------- + +// Notice that wxID_HELP will be processed for the 'About' menu and the toolbar +// help button. + +BEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_MENU(wxID_EXIT, MyFrame::OnQuit) + EVT_MENU(wxID_HELP, MyFrame::OnAbout) + + EVT_MENU(wxID_NEW_SCRIPT, MyFrame::OnNewScript) + EVT_MENU(wxID_OPEN_SCRIPT, MyFrame::OnOpenScript) + EVT_MENU(wxID_SAVE_SCRIPT, MyFrame::OnSaveScript) + EVT_MENU(wxID_NEW_PROJECT, MyFrame::OnNewProject) + EVT_MENU(wxID_OPEN_PROJECT, MyFrame::OnOpenProject) + EVT_MENU(wxID_SAVE_PROJECT, MyFrame::OnSaveProject) + + EVT_MENU(wxID_CUT, MyFrame::OnCut) + EVT_MENU(wxID_COPY, MyFrame::OnCopy) + EVT_MENU(wxID_PASTE, MyFrame::OnPaste) + + EVT_LISTBOX_DCLICK(ID_LISTBOX, MyFrame::OnListBoxDoubleClick) +END_EVENT_TABLE() + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// MyApp +// ---------------------------------------------------------------------------- + +IMPLEMENT_APP(MyApp) + +// The `main program' equivalent, creating the windows and returning the +// main frame +bool MyApp::OnInit() +{ + // Create the main frame window + MyFrame* frame = new MyFrame((wxFrame *) NULL, -1, + "wxInstall Builder", + wxPoint(100, 100), wxSize(450, 300)); + + frame->SetAutoLayout(TRUE); + + frame->Show(TRUE); + + frame->SetStatusText("Welcome to wxWindows Install Builder"); + + SetTopWindow(frame); + + return TRUE; +} + +void MyFrame::RecreateToolbar() +{ + // delete and recreate the toolbar + wxToolBarBase *toolBar = GetToolBar(); + delete toolBar; + + SetToolBar(NULL); + + long style = wxNO_BORDER | wxTB_FLAT | wxTB_DOCKABLE; + style |= m_horzToolbar ? wxTB_HORIZONTAL : wxTB_VERTICAL; + + toolBar = CreateToolBar(style, ID_TOOLBAR); + toolBar->SetMargins( 4, 4 ); + + // Set up toolbar + wxBitmap toolBarBitmaps[8]; + + toolBarBitmaps[0] = wxBITMAP(new); + toolBarBitmaps[1] = wxBITMAP(open); + toolBarBitmaps[2] = wxBITMAP(save); + toolBarBitmaps[3] = wxBITMAP(copy); + toolBarBitmaps[4] = wxBITMAP(cut); + toolBarBitmaps[5] = wxBITMAP(paste); + toolBarBitmaps[6] = wxBITMAP(print); + toolBarBitmaps[7] = wxBITMAP(help); + + if ( !m_smallToolbar ) + { + int w = 2*toolBarBitmaps[0].GetWidth(), + h = 2*toolBarBitmaps[0].GetHeight(); + for ( size_t n = 0; n < WXSIZEOF(toolBarBitmaps); n++ ) + { + toolBarBitmaps[n] = + wxImage(toolBarBitmaps[n]).Scale(w, h).ConvertToBitmap(); + } + + toolBar->SetToolBitmapSize(wxSize(w, h)); + } + +#ifdef __WXMSW__ + int width = 24; +#else + int width = 16; +#endif + + int currentX = 5; + + toolBar->AddTool(wxID_NEW_SCRIPT, toolBarBitmaps[0], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "New script"); + currentX += width + 5; + toolBar->AddTool(wxID_OPEN_SCRIPT, toolBarBitmaps[1], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Open script"); + + // neither the generic nor Motif native toolbars really support this + currentX += width + 5; + toolBar->AddTool(wxID_SAVE_SCRIPT, toolBarBitmaps[2], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Save script"); + currentX += width + 5; + toolBar->AddTool(wxID_COPY, toolBarBitmaps[3], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Copy"); + currentX += width + 5; + toolBar->AddTool(wxID_CUT, toolBarBitmaps[4], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Cut"); + currentX += width + 5; + toolBar->AddTool(wxID_PASTE, toolBarBitmaps[5], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Paste"); + currentX += width + 5; + toolBar->AddSeparator(); + toolBar->AddTool(wxID_HELP, toolBarBitmaps[7], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Help button"); + + // after adding the buttons to the toolbar, must call Realize() to reflect + // the changes + toolBar->Realize(); + + toolBar->SetRows(m_horzToolbar ? m_rows : 10 / m_rows); +} + +// ---------------------------------------------------------------------------- +// MyFrame +// ---------------------------------------------------------------------------- + +// Define my frame constructor +MyFrame::MyFrame(wxFrame* parent, + wxWindowID id, + const wxString& title, + const wxPoint& pos, + const wxSize& size, + long style) + : wxFrame(parent, id, title, pos, size, style) +{ + m_listBox = new wxListBox(this, ID_LISTBOX, wxPoint(0,0), wxSize(-1, -1)); + + m_listBox->Append("loadwxr"); + m_listBox->Append("closeold"); + m_listBox->Append("mleview"); + m_listBox->Append("setbutton"); + m_listBox->Append("getcheck"); + m_listBox->Append("message"); + m_listBox->Append("disable"); + m_listBox->Append("settext"); + m_listBox->Append("gettext"); + m_listBox->Append("grabfile"); + m_listBox->Append("remove"); + m_listBox->Append("system"); + m_listBox->Append("startinst"); + + wxLayoutConstraints *b1 = new wxLayoutConstraints; + b1->left.SameAs (this, wxLeft, 0); + b1->top.SameAs (this, wxTop, 0); + b1->width.PercentOf (this, wxWidth, 20); + b1->bottom.SameAs (this, wxBottom, 0); + m_listBox->SetConstraints(b1); + + m_textWindow = new wxTextCtrl(this, -1, "", wxPoint(0,0), wxSize(-1, -1), wxTE_MULTILINE); + + m_textWindow->AppendText("; Script generated by wxInstall Builder\n"); + + wxLayoutConstraints *b2 = new wxLayoutConstraints; + b2->top.SameAs (this, wxTop, 0); + b2->left.SameAs (m_listBox, wxRight, 0); + b2->width.PercentOf (this, wxWidth, 80); + b2->bottom.SameAs (this, wxBottom, 0); + m_textWindow->SetConstraints(b2); + + m_smallToolbar = TRUE; + m_horzToolbar = TRUE; + m_rows = 1; + + // Give it a status line + CreateStatusBar(); + + // Give it an icon + SetIcon(wxICON(mondrian)); + + wxMenu *fileMenu = new wxMenu; + fileMenu->Append(wxID_NEW_SCRIPT, "&New Script", "New wxInstall Script" ); + fileMenu->Append(wxID_OPEN_SCRIPT, "&Open Script", "Open wxInstall Script" ); + fileMenu->Append(wxID_SAVE_SCRIPT, "&Save Script", "Save wxInstall Script" ); + fileMenu->AppendSeparator(); + /*fileMenu->Append(wxID_NEW_PROJECT, "N&ew Project", "New wxInstall Project" ); + fileMenu->Append(wxID_OPEN_PROJECT, "O&pen Project", "Open wxInstall Project" ); + fileMenu->Append(wxID_SAVE_PROJECT, "S&ave Project", "Save wxInstall Project" ); + fileMenu->AppendSeparator();*/ + fileMenu->Append(wxID_EXIT, "E&xit", "Quit wxInstall Builder" ); + + wxMenu *helpMenu = new wxMenu; + helpMenu->Append(wxID_HELP, "&About", "About wxInstall Builder"); + + wxMenuBar* menuBar = new wxMenuBar( wxMB_DOCKABLE ); + + menuBar->Append(fileMenu, "&File"); + menuBar->Append(helpMenu, "&Help"); + + // Associate the menu bar with the frame + SetMenuBar(menuBar); + + // Create the toolbar + RecreateToolbar(); +} + +#if USE_GENERIC_TBAR + +wxToolBar* MyFrame::OnCreateToolBar(long style, + wxWindowID id, + const wxString& name) +{ + return (wxToolBar *)new wxToolBarSimple(this, id, + wxDefaultPosition, wxDefaultSize, + style, name); +} + +#endif // USE_GENERIC_TBAR + +void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) +{ + Close(TRUE); +} + +void MyFrame::OnCut(wxCommandEvent& WXUNUSED(event)) +{ + m_textWindow->Cut(); +} + +void MyFrame::OnCopy(wxCommandEvent& WXUNUSED(event)) +{ + m_textWindow->Copy(); +} + +void MyFrame::OnPaste(wxCommandEvent& WXUNUSED(event)) +{ + m_textWindow->Paste(); +} + +void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) +{ + (void)wxMessageBox("wxInstall Builder by Brian Smith", "About wxInstall Builder"); +} + +void MyFrame::OnNewScript(wxCommandEvent& event) +{ + m_textWindow->Clear(); + m_textWindow->AppendText("; Script generated by wxInstall Builder\n"); +} + +void MyFrame::OnOpenScript(wxCommandEvent& event) +{ + wxFileDialog dialog2(this, "Open Script", "", "", "*.ini", 0); + + if (dialog2.ShowModal() == wxID_OK) + m_textWindow->LoadFile(dialog2.GetPath()); +} + +void MyFrame::OnSaveScript(wxCommandEvent& event) +{ + wxFileDialog dialog2(this, "Save Script", "", "", "*.ini", 0); + + if (dialog2.ShowModal() == wxID_OK) + m_textWindow->SaveFile(dialog2.GetPath()); +} + +void MyFrame::OnNewProject(wxCommandEvent& event) +{ +} + +void MyFrame::OnOpenProject(wxCommandEvent& event) +{ +} + +void MyFrame::OnSaveProject(wxCommandEvent& event) +{ +} + +void MyFrame::OnListBoxDoubleClick( wxCommandEvent &event ) +{ + wxString str = event.GetString(); + if(strcmp(str, "closeold")==0) + { + m_textWindow->WriteText("closeold\n"); + } + else if(strcmp(str, "system")==0) + { + wxTextEntryDialog dialog2(this, + "Please enter the command to execute", + appName, + "", + wxOK | wxCANCEL); + + if (dialog2.ShowModal() == wxID_OK) + { + m_textWindow->WriteText("system,"); + m_textWindow->WriteText(dialog2.GetValue()); + m_textWindow->WriteText("\n"); + } + } + else if(strcmp(str, "grabfile")==0) + { + wxFileDialog dialog2(this, "Choose file to grab", "", "", "*", 0); + + if (dialog2.ShowModal() == wxID_OK) + { + m_textWindow->WriteText("grabfile,"); + m_textWindow->WriteText(dialog2.GetFilename()); + m_textWindow->WriteText("\n"); + } + } + else if(strcmp(str, "loadwxr")==0) + { + wxFileDialog dialog2(this, "Choose wxr filename", "", "", "*.wxr", 0); + + if (dialog2.ShowModal() == wxID_OK) + { + char tempbuf[1024] = "DialogEd "; + wxString tmp = dialog2.GetFilename(); + + m_textWindow->WriteText("loadwxr,"); + m_textWindow->WriteText(tmp); + m_textWindow->WriteText("\n"); + + strcat(tempbuf, tmp); + wxExecute(tempbuf); + } + } + else if(strcmp(str, "mleview")==0) + { + wxFileDialog dialog2(this, "Choose filename to view", "", "", "*.txt", 0); + + if (dialog2.ShowModal() == wxID_OK) + { + wxTextEntryDialog dialog3(this, + "Please enter name of the MLE widget", + appName, + "", + wxOK | wxCANCEL); + + if (dialog3.ShowModal() == wxID_OK) + { + m_textWindow->WriteText("mleview,"); + m_textWindow->WriteText(dialog3.GetValue()); + m_textWindow->WriteText(","); + m_textWindow->WriteText(dialog2.GetFilename()); + m_textWindow->WriteText("\n"); + } + } + } + else if(strcmp(str, "setbutton")==0) + { + wxFileDialog dialog2(this, "Choose script to attach to button", "", "", "*.ini", 0); + + if (dialog2.ShowModal() == wxID_OK) + { + wxTextEntryDialog dialog3(this, + "Please enter ID of the button", + appName, + "", + wxOK | wxCANCEL); + + if (dialog3.ShowModal() == wxID_OK) + { + m_textWindow->WriteText("setbutton,"); + m_textWindow->WriteText(dialog3.GetValue()); + m_textWindow->WriteText(","); + m_textWindow->WriteText(dialog2.GetFilename()); + m_textWindow->WriteText("\n"); + } + } + } + else if(strcmp(str, "startinst")==0) + { + wxFileDialog dialog2(this, "Choose script to run at installation completion", "", "", "*.ini", 0); + + if (dialog2.ShowModal() == wxID_OK) + { + wxTextEntryDialog dialog3(this, + "Please enter name of the gauge widget", + appName, + "", + wxOK | wxCANCEL); + + if (dialog3.ShowModal() == wxID_OK) + { + m_textWindow->WriteText("startinst,"); + m_textWindow->WriteText(dialog3.GetValue()); + m_textWindow->WriteText(","); + m_textWindow->WriteText(dialog2.GetFilename()); + m_textWindow->WriteText("\n"); + } + } + } + else if(strcmp(str, "remove")==0) + { + wxFileDialog dialog2(this, "Choose file to remove", "", "", "*", 0); + + if (dialog2.ShowModal() == wxID_OK) + { + m_textWindow->WriteText("remove,"); + m_textWindow->WriteText(dialog2.GetFilename()); + m_textWindow->WriteText("\n"); + } + } + else if(strcmp(str, "message")==0) + { + wxTextEntryDialog dialog2(this, + "Please enter the message to display to the user", + appName, + "", + wxOK | wxCANCEL); + + if (dialog2.ShowModal() == wxID_OK) + { + m_textWindow->WriteText("message,\""); + m_textWindow->WriteText(dialog2.GetValue()); + m_textWindow->WriteText("\"\n"); + } + } + else if(strcmp(str, "gettext")==0) + { + wxTextEntryDialog dialog2(this, + "Please enter text widget name to get from", + appName, + "", + wxOK | wxCANCEL); + + if (dialog2.ShowModal() == wxID_OK) + { + m_textWindow->WriteText("gettext,"); + m_textWindow->WriteText(dialog2.GetValue()); + m_textWindow->WriteText("\n"); + } + } + else if(strcmp(str, "settext")==0) + { + wxTextEntryDialog dialog2(this, + "Please enter text widget name to set from", + appName, + "", + wxOK | wxCANCEL); + + if (dialog2.ShowModal() == wxID_OK) + { + m_textWindow->WriteText("settext,"); + m_textWindow->WriteText(dialog2.GetValue()); + m_textWindow->WriteText("\n"); + } + } + else if(strcmp(str, "getcheck")==0) + { + wxFileDialog dialog2(this, "Choose script to run if not checked", "", "", "*.ini", 0); + + if (dialog2.ShowModal() == wxID_OK) + { + wxTextEntryDialog dialog3(this, + "Please enter name of the checkbox widget", + appName, + "", + wxOK | wxCANCEL); + + if (dialog3.ShowModal() == wxID_OK) + { + m_textWindow->WriteText("getcheck,"); + m_textWindow->WriteText(dialog3.GetValue()); + m_textWindow->WriteText(","); + m_textWindow->WriteText(dialog2.GetFilename()); + m_textWindow->WriteText("\n"); + } + } + } + else if(strcmp(str, "disable")==0) + { + wxTextEntryDialog dialog2(this, + "Please enter the widget name to disable", + appName, + "", + wxOK | wxCANCEL); + + if (dialog2.ShowModal() == wxID_OK) + { + m_textWindow->WriteText("disable,"); + m_textWindow->WriteText(dialog2.GetValue()); + m_textWindow->WriteText("\n"); + } + } + +} diff --git a/utils/Install/builder/wxib.cpp.1 b/utils/Install/builder/wxib.cpp.1 new file mode 100644 index 0000000000..9eb863643b --- /dev/null +++ b/utils/Install/builder/wxib.cpp.1 @@ -0,0 +1,500 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wxib.cpp +// Purpose: wxInstall Builder +// Author: Julian Smart +// Author: Brian Smith +// Modified by: +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// For compilers that support precompilation, includes "wx/wx.h". +#include + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include +#endif + +#include +#include +#include + +// define this to 1 to use wxToolBarSimple instead of the native one +#define USE_GENERIC_TBAR 0 + +#if USE_GENERIC_TBAR + #if !wxUSE_TOOLBAR_SIMPLE + #error wxToolBarSimple is not compiled in, set wxUSE_TOOLBAR_SIMPLE \ + to 1 in setup.h and recompile the library. + #else + #include + #endif +#endif // USE_GENERIC_TBAR + +// ---------------------------------------------------------------------------- +// resources +// ---------------------------------------------------------------------------- + +#if defined(__WXGTK__) || defined(__WXMOTIF__) + #include "mondrian.xpm" + #include "bitmaps/new.xpm" + #include "bitmaps/open.xpm" + #include "bitmaps/save.xpm" + #include "bitmaps/copy.xpm" + #include "bitmaps/cut.xpm" + #include "bitmaps/preview.xpm" // paste XPM + #include "bitmaps/print.xpm" + #include "bitmaps/help.xpm" +#endif // GTK or Motif + +// ---------------------------------------------------------------------------- +// classes +// ---------------------------------------------------------------------------- + +// Define a new application +class MyApp : public wxApp +{ +public: + bool OnInit(); +}; + +// Define a new frame +class MyFrame: public wxFrame +{ +public: + MyFrame(wxFrame *parent, + wxWindowID id = -1, + const wxString& title = "wxInstall Builder", + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_FRAME_STYLE); + + void RecreateToolbar(); + + void OnQuit(wxCommandEvent& event); + void OnAbout(wxCommandEvent& event); + + void OnToggleToolbarSize(wxCommandEvent& event); + void OnToggleToolbarOrient(wxCommandEvent& event); + void OnToggleToolbarRows(wxCommandEvent& event); + + void OnEnablePrint(wxCommandEvent& WXUNUSED(event)) { DoEnablePrint(); } + void OnDeletePrint(wxCommandEvent& WXUNUSED(event)) { DoDeletePrint(); } + void OnInsertPrint(wxCommandEvent& event); + void OnToggleHelp(wxCommandEvent& WXUNUSED(event)) { DoToggleHelp(); } + + void OnToolLeftClick(wxCommandEvent& event); + void OnListBoxDoubleClick(wxCommandEvent& event); + + void OnCombo(wxCommandEvent& event); + + void OnUpdateCopyAndCut(wxUpdateUIEvent& event); + +#if USE_GENERIC_TBAR + virtual wxToolBar *OnCreateToolBar(long style, + wxWindowID id, + const wxString& name ); +#endif // USE_GENERIC_TBAR + +private: + void DoEnablePrint(); + void DoDeletePrint(); + void DoToggleHelp(); + + bool m_smallToolbar, + m_horzToolbar; + size_t m_rows; // 1 or 2 only + + wxTextCtrl* m_textWindow; + wxListBox* m_listBox; + + DECLARE_EVENT_TABLE() +}; + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +const int ID_TOOLBAR = 500; + +enum +{ + IDM_TOOLBAR_TOGGLETOOLBARSIZE = 200, + IDM_TOOLBAR_TOGGLETOOLBARORIENT, + IDM_TOOLBAR_TOGGLETOOLBARROWS, + IDM_TOOLBAR_ENABLEPRINT, + IDM_TOOLBAR_DELETEPRINT, + IDM_TOOLBAR_INSERTPRINT, + IDM_TOOLBAR_TOGGLEHELP, + + ID_COMBO = 1000, + ID_LISTBOX +}; + +// ---------------------------------------------------------------------------- +// event tables +// ---------------------------------------------------------------------------- + +// Notice that wxID_HELP will be processed for the 'About' menu and the toolbar +// help button. + +BEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_MENU(wxID_EXIT, MyFrame::OnQuit) + EVT_MENU(wxID_HELP, MyFrame::OnAbout) + + EVT_MENU(IDM_TOOLBAR_TOGGLETOOLBARSIZE, MyFrame::OnToggleToolbarSize) + EVT_MENU(IDM_TOOLBAR_TOGGLETOOLBARORIENT, MyFrame::OnToggleToolbarOrient) + EVT_MENU(IDM_TOOLBAR_TOGGLETOOLBARROWS, MyFrame::OnToggleToolbarRows) + + EVT_MENU(IDM_TOOLBAR_ENABLEPRINT, MyFrame::OnEnablePrint) + EVT_MENU(IDM_TOOLBAR_DELETEPRINT, MyFrame::OnDeletePrint) + EVT_MENU(IDM_TOOLBAR_INSERTPRINT, MyFrame::OnInsertPrint) + EVT_MENU(IDM_TOOLBAR_TOGGLEHELP, MyFrame::OnToggleHelp) + + EVT_MENU(-1, MyFrame::OnToolLeftClick) + + EVT_LISTBOX_DCLICK(ID_LISTBOX, MyFrame::OnListBoxDoubleClick) + EVT_COMBOBOX(ID_COMBO, MyFrame::OnCombo) + + EVT_UPDATE_UI(wxID_COPY, MyFrame::OnUpdateCopyAndCut) + EVT_UPDATE_UI(wxID_CUT, MyFrame::OnUpdateCopyAndCut) +END_EVENT_TABLE() + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// MyApp +// ---------------------------------------------------------------------------- + +IMPLEMENT_APP(MyApp) + +// The `main program' equivalent, creating the windows and returning the +// main frame +bool MyApp::OnInit() +{ + // Create the main frame window + MyFrame* frame = new MyFrame((wxFrame *) NULL, -1, + "wxInstall Builder", + wxPoint(100, 100), wxSize(450, 300)); + + frame->SetAutoLayout(TRUE); + + frame->Show(TRUE); + + frame->SetStatusText("Welcome to wxWindows Install Builder"); + + SetTopWindow(frame); + + return TRUE; +} + +void MyFrame::RecreateToolbar() +{ + // delete and recreate the toolbar + wxToolBarBase *toolBar = GetToolBar(); + delete toolBar; + + SetToolBar(NULL); + + long style = wxNO_BORDER | wxTB_FLAT | wxTB_DOCKABLE; + style |= m_horzToolbar ? wxTB_HORIZONTAL : wxTB_VERTICAL; + + toolBar = CreateToolBar(style, ID_TOOLBAR); + toolBar->SetMargins( 4, 4 ); + + // Set up toolbar + wxBitmap toolBarBitmaps[8]; + + toolBarBitmaps[0] = wxBITMAP(new); + toolBarBitmaps[1] = wxBITMAP(open); + toolBarBitmaps[2] = wxBITMAP(save); + toolBarBitmaps[3] = wxBITMAP(copy); + toolBarBitmaps[4] = wxBITMAP(cut); + toolBarBitmaps[5] = wxBITMAP(paste); + toolBarBitmaps[6] = wxBITMAP(print); + toolBarBitmaps[7] = wxBITMAP(help); + + if ( !m_smallToolbar ) + { + int w = 2*toolBarBitmaps[0].GetWidth(), + h = 2*toolBarBitmaps[0].GetHeight(); + for ( size_t n = 0; n < WXSIZEOF(toolBarBitmaps); n++ ) + { + toolBarBitmaps[n] = + wxImage(toolBarBitmaps[n]).Scale(w, h).ConvertToBitmap(); + } + + toolBar->SetToolBitmapSize(wxSize(w, h)); + } + +#ifdef __WXMSW__ + int width = 24; +#else + int width = 16; +#endif + + int currentX = 5; + + toolBar->AddTool(wxID_NEW, toolBarBitmaps[0], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "New script"); + currentX += width + 5; + toolBar->AddTool(wxID_OPEN, toolBarBitmaps[1], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Open script"); + + // neither the generic nor Motif native toolbars really support this + currentX += width + 5; + toolBar->AddTool(wxID_SAVE, toolBarBitmaps[2], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Save script"); + currentX += width + 5; + toolBar->AddTool(wxID_COPY, toolBarBitmaps[3], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Copy"); + currentX += width + 5; + toolBar->AddTool(wxID_CUT, toolBarBitmaps[4], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Cut"); + currentX += width + 5; + toolBar->AddTool(wxID_PASTE, toolBarBitmaps[5], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Paste"); + currentX += width + 5; + toolBar->AddSeparator(); + toolBar->AddTool(wxID_HELP, toolBarBitmaps[7], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Help button"); + + // after adding the buttons to the toolbar, must call Realize() to reflect + // the changes + toolBar->Realize(); + + toolBar->SetRows(m_horzToolbar ? m_rows : 10 / m_rows); +} + +// ---------------------------------------------------------------------------- +// MyFrame +// ---------------------------------------------------------------------------- + +// Define my frame constructor +MyFrame::MyFrame(wxFrame* parent, + wxWindowID id, + const wxString& title, + const wxPoint& pos, + const wxSize& size, + long style) + : wxFrame(parent, id, title, pos, size, style) +{ + m_listBox = new wxListBox(this, ID_LISTBOX, wxPoint(0,0), wxSize(-1, -1)); + + m_listBox->Append("loadwxr"); + m_listBox->Append("closeold"); + m_listBox->Append("mleview"); + m_listBox->Append("setbutton"); + m_listBox->Append("getcheck"); + m_listBox->Append("message"); + m_listBox->Append("disable"); + m_listBox->Append("settext"); + m_listBox->Append("gettext"); + m_listBox->Append("grabfile"); + m_listBox->Append("remove"); + m_listBox->Append("system"); + m_listBox->Append("startinst"); + + wxLayoutConstraints *b1 = new wxLayoutConstraints; + b1->left.SameAs (this, wxLeft, 0); + b1->top.SameAs (this, wxTop, 0); + b1->width.PercentOf (this, wxWidth, 20); + b1->bottom.SameAs (this, wxBottom, 0); + m_listBox->SetConstraints(b1); + + m_textWindow = new wxTextCtrl(this, -1, "", wxPoint(0,0), wxSize(-1, -1), wxTE_MULTILINE); + + wxLayoutConstraints *b2 = new wxLayoutConstraints; + b2->top.SameAs (this, wxTop, 0); + b2->left.SameAs (m_listBox, wxRight, 0); + b2->width.PercentOf (this, wxWidth, 80); + b2->bottom.SameAs (this, wxBottom, 0); + m_textWindow->SetConstraints(b2); + + m_smallToolbar = TRUE; + m_horzToolbar = TRUE; + m_rows = 1; + + // Give it a status line + CreateStatusBar(); + + // Give it an icon + SetIcon(wxICON(mondrian)); + + wxMenu *fileMenu = new wxMenu; + fileMenu->Append(500, "&New Script", "New wxInstall Script" ); + fileMenu->Append(501, "&Save Script", "Save wxInstall Script" ); + fileMenu->Append(502, "&Open Script", "Open wxInstall Script" ); + fileMenu->AppendSeparator(); + fileMenu->Append(503, "N&ew Project", "New wxInstall Project" ); + fileMenu->Append(504, "S&ave Project", "Save wxInstall Project" ); + fileMenu->Append(505, "O&pen Project", "Open wxInstall Project" ); + fileMenu->AppendSeparator(); + fileMenu->Append(wxID_EXIT, "E&xit", "Quit wxInstall Builder" ); + + wxMenu *helpMenu = new wxMenu; + helpMenu->Append(wxID_HELP, "&About", "About wxInstall Builder"); + + wxMenuBar* menuBar = new wxMenuBar( wxMB_DOCKABLE ); + + menuBar->Append(fileMenu, "&File"); + menuBar->Append(helpMenu, "&Help"); + + // Associate the menu bar with the frame + SetMenuBar(menuBar); + + // Create the toolbar + RecreateToolbar(); +} + +#if USE_GENERIC_TBAR + +wxToolBar* MyFrame::OnCreateToolBar(long style, + wxWindowID id, + const wxString& name) +{ + return (wxToolBar *)new wxToolBarSimple(this, id, + wxDefaultPosition, wxDefaultSize, + style, name); +} + +#endif // USE_GENERIC_TBAR + +void MyFrame::OnToggleToolbarSize(wxCommandEvent& WXUNUSED(event)) +{ + m_smallToolbar = !m_smallToolbar; + + RecreateToolbar(); +} + +void MyFrame::OnToggleToolbarRows(wxCommandEvent& WXUNUSED(event)) +{ + // m_rows may be only 1 or 2 + m_rows = 3 - m_rows; + + GetToolBar()->SetRows(m_horzToolbar ? m_rows : 10 / m_rows); + + //RecreateToolbar(); -- this is unneeded +} + +void MyFrame::OnToggleToolbarOrient(wxCommandEvent& WXUNUSED(event)) +{ + m_horzToolbar = !m_horzToolbar; + + RecreateToolbar(); +} + +void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) +{ + Close(TRUE); +} + +void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) +{ + (void)wxMessageBox("wxInstall Builder by Brian Smith", "About wxInstall Builder"); +} + +void MyFrame::OnToolLeftClick(wxCommandEvent& event) +{ + /*wxString str; + str.Printf( _T("Clicked on tool %d\n"), event.GetId()); + m_textWindow->WriteText( str ); + + if (event.GetId() == wxID_HELP) + { + if ( event.GetExtraLong() != 0 ) + m_textWindow->WriteText( _T("Help button down now.\n") ); + else + m_textWindow->WriteText( _T("Help button up now.\n") ); + } + + if (event.GetId() == wxID_COPY) + { + DoEnablePrint(); + } + + if (event.GetId() == wxID_CUT) + { + DoToggleHelp(); + } + + if (event.GetId() == wxID_PRINT) + { + DoDeletePrint(); + } */ +} + +void MyFrame::OnCombo(wxCommandEvent& event) +{ + wxLogStatus(_T("Combobox string '%s' selected"), event.GetString().c_str()); +} + +void MyFrame::DoEnablePrint() +{ + wxToolBarBase *tb = GetToolBar(); + if (tb->GetToolEnabled(wxID_PRINT)) + tb->EnableTool( wxID_PRINT, FALSE ); + else + tb->EnableTool( wxID_PRINT, TRUE ); +} + +void MyFrame::DoDeletePrint() +{ + wxToolBarBase *tb = GetToolBar(); + + tb->DeleteTool( wxID_PRINT ); +} + +void MyFrame::DoToggleHelp() +{ + wxToolBarBase *tb = GetToolBar(); + tb->ToggleTool( wxID_HELP, !tb->GetToolState( wxID_HELP ) ); +} + +void MyFrame::OnUpdateCopyAndCut(wxUpdateUIEvent& event) +{ + /*event.Enable( m_textWindow->CanCopy() );*/ +} + +void MyFrame::OnInsertPrint(wxCommandEvent& WXUNUSED(event)) +{ + wxBitmap bmp = wxBITMAP(print); + + GetToolBar()->InsertTool(0, wxID_PRINT, bmp, wxNullBitmap, + FALSE, (wxObject *) NULL, + "Delete this tool", + "This button was inserted into the toolbar"); + + GetToolBar()->Realize(); +} + +void MyFrame::OnListBoxDoubleClick( wxCommandEvent &event ) +{ + wxString str = event.GetString(); + if(strcmp(str, "closeold")==0) + { + m_textWindow->AppendText("closeold\n"); + } + else if(strcmp(str, "system")==0) + { + wxTextEntryDialog dialog2(this, + "Please enter the command to execute", + "wxInstall Builder", + "", + wxOK | wxCANCEL); + + if (dialog2.ShowModal() == wxID_OK) + { + m_textWindow->AppendText("system,"); + m_textWindow->AppendText(dialog2.GetValue()); + m_textWindow->AppendText("\n"); + } + } + +} diff --git a/utils/Install/builder/wxib.def b/utils/Install/builder/wxib.def new file mode 100644 index 0000000000..897b9dacbb --- /dev/null +++ b/utils/Install/builder/wxib.def @@ -0,0 +1,8 @@ +NAME ToolTest +DESCRIPTION 'wxToolBar Sample' +EXETYPE WINDOWS +STUB 'WINSTUB.EXE' +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE MULTIPLE +HEAPSIZE 1024 +STACKSIZE 8192 diff --git a/utils/Install/builder/wxib.rc b/utils/Install/builder/wxib.rc new file mode 100644 index 0000000000..42bb7cb984 --- /dev/null +++ b/utils/Install/builder/wxib.rc @@ -0,0 +1,12 @@ +mondrian ICON "mondrian.ico" +#include "wx/msw/wx.rc" + +new BITMAP "bitmaps/new.bmp" +open BITMAP "bitmaps/open.bmp" +save BITMAP "bitmaps/save.bmp" +copy BITMAP "bitmaps/copy.bmp" +cut BITMAP "bitmaps/cut.bmp" +paste BITMAP "bitmaps/paste.bmp" +print BITMAP "bitmaps/print.bmp" +help BITMAP "bitmaps/help.bmp" + diff --git a/utils/Install/incace/acestruc.h b/utils/Install/incace/acestruc.h new file mode 100644 index 0000000000..1a6b488a20 --- /dev/null +++ b/utils/Install/incace/acestruc.h @@ -0,0 +1,151 @@ +#ifndef __acestruc_h +#define __acestruc_h + +#include "declare.h" +#include "portable.h" + +#define acesign_len 7 +#define bytes_before_acesign 7 +#define acever 10 + +struct tech +{ + UCHAR TYPE; + UCHAR QUAL; + USHORT PARM; +}; + +typedef struct tacehead +{ + USHORT HEAD_CRC; + USHORT HEAD_SIZE; + UCHAR HEAD_TYPE; + USHORT HEAD_FLAGS; + ULONG ADDSIZE; + UCHAR other[2048]; + +} thead; + +typedef struct tacemhead +{ + USHORT HEAD_CRC; + USHORT HEAD_SIZE; + UCHAR HEAD_TYPE; + USHORT HEAD_FLAGS; + + UCHAR ACESIGN[acesign_len]; + UCHAR VER_MOD; + UCHAR VER_CR; + UCHAR HOST_CR; + UCHAR VOL_NUM; + ULONG TIME_CR; + USHORT RES1; + USHORT RES2; + ULONG RES; + UCHAR AV_SIZE; + UCHAR AV[256]; + USHORT COMM_SIZE; + UCHAR COMM[2048]; + +} tmhead; + +#ifndef PATH_MAX + #define PATH_MAX 512 +#endif + +typedef struct tacefhead +{ + USHORT HEAD_CRC; + USHORT HEAD_SIZE; + UCHAR HEAD_TYPE; + USHORT HEAD_FLAGS; + + ULONG PSIZE; + ULONG SIZE; + ULONG FTIME; + ULONG ATTR; + ULONG CRC32; + struct tech TECH; + USHORT RESERVED; + USHORT FNAME_SIZE; + UCHAR FNAME[PATH_MAX]; + USHORT COMM_SIZE; + UCHAR COMM[2048]; + +} tfhead; + +#define mhead (*t_mhead) +#define fhead (*t_fhead) +#define rhead (*t_rhead) +#define tmpmhead (*t_tmpmhead) +#define tmpfhead (*t_tmpfhead) +#define tmprhead (*t_tmprhead) + +#define mhead_size h_mhead_size(mhead) +#define fhead_size h_fhead_size(fhead) +#define rhead_size ((INT)&rhead.REC_CRC-(INT)&head.HEAD_TYPE+sizeof(rhead.REC_CRC)) + +#define h_mhead_size(phead) ((INT)mhead.AV-(INT)&head.HEAD_TYPE+ \ + (phead).AV_SIZE+ \ + ((phead).HEAD_FLAGS&ACE_COMM? \ + sizeof((phead).COMM_SIZE)+H_MCOMM_SIZE(phead):0)) + + +#define h_fhead_size(phead) ((INT)fhead.FNAME-(INT)&head.HEAD_TYPE+ \ + (phead).FNAME_SIZE+ \ + ((phead).HEAD_FLAGS&ACE_COMM? \ + sizeof((phead).COMM_SIZE)+H_FCOMM_SIZE(phead):0)) + + +//main-comment-definitions +#define H_MCOMM_SIZE(head) (BUF2WORD((UCHAR*)&(head).AV+(head).AV_SIZE)) +#define MCOMM_SIZE H_MCOMM_SIZE(mhead) +#define H_MCOMM(head) ((UCHAR*)&(head).AV+(head).AV_SIZE+sizeof((head).COMM_SIZE)) +#define MCOMM H_MCOMM(mhead) + + +//file-comment-definitions +#define H_FCOMM_SIZE(head) (BUF2WORD((UCHAR*)&(head).FNAME+(head).FNAME_SIZE)) +#define FCOMM_SIZE H_FCOMM_SIZE(fhead) +#define H_FCOMM(head) ((UCHAR*)&(head).FNAME+(head).FNAME_SIZE+sizeof((head).COMM_SIZE)) +#define FCOMM H_FCOMM(fhead) + +// +#define calc_head_crc getcrc16(CRC_MASK, (CHAR*)&head.HEAD_TYPE, head.HEAD_SIZE) +#define GET_ADDSIZE ((head.HEAD_FLAGS & ACE_ADDSIZE) ? head.ADDSIZE : 0) + +//archive-header-flags +#define ACE_LIM256 1024 +#define ACE_MULT_VOL 2048 +#define ACE_AV 4096 +#define ACE_RECOV 8192 +#define ACE_LOCK 16384 +#define ACE_SOLID 32768 + +//file-header-flags +#define ACE_ADDSIZE 1 +#define ACE_PASSW 16384 +#define ACE_SP_BEF 4096 +#define ACE_SP_AFTER 8192 +#define ACE_COMM 2 + +//block types +#define MAIN_BLK 0 +#define FILE_BLK 1 +#define REC_BLK 2 + +//known compression types +#define TYPE_STORE 0 +#define TYPE_LZW1 1 + +//structure for archive handling +struct tadat +{ + INT sol, + vol, + vol_num; + ULONG time_cr; +}; + + +#endif /* __acestruc_h */ diff --git a/utils/Install/incace/attribs.h b/utils/Install/incace/attribs.h new file mode 100644 index 0000000000..dbc82ffb5b --- /dev/null +++ b/utils/Install/incace/attribs.h @@ -0,0 +1,33 @@ +#ifndef __attribs_h +#define __attribs_h + + +#ifndef _A_SUBDIR + #define _A_SUBDIR 0x10 // MS-DOS directory constant +#endif + +#ifndef S_IEXEC + #ifdef S_IEXECUTE + #define S_IEXEC S_IEXECUTE + #else + #define S_IEXEC 0 + #endif +#endif + +#ifndef S_IDELETE + #define S_IDELETE 0 +#endif + +#ifndef S_IRGRP + #define S_IRGRP 0 + #define S_IWGRP 0 +#endif + +#ifndef S_IROTH + #define S_IROTH 0 + #define S_IWOTH 0 +#endif + + +#endif /* __attribs_h */ + diff --git a/utils/Install/incace/declare.h b/utils/Install/incace/declare.h new file mode 100644 index 0000000000..4c14a28dcd --- /dev/null +++ b/utils/Install/incace/declare.h @@ -0,0 +1,38 @@ +/******************************************************/ +/* */ +/* declare.h: declaration-symbols (UCHAR, ULONG, ...) */ +/* */ +/******************************************************/ + +#ifndef __declare_h +#define __declare_h + +#if defined(__CYGWIN__) +#include +#endif + +#if !defined(OS2_H_INCLUDED) && !defined(__CYGWIN__) +#ifdef AMIGA + +#include + +#else /* AMIGA */ +typedef unsigned short USHORT; +typedef short SHORT ; +typedef unsigned short UWORD ; +typedef short WORD ; +typedef unsigned long ULONG ; +typedef long LONG ; +#endif /* !AMIGA */ + +typedef unsigned char UCHAR ; +typedef char CHAR ; +typedef unsigned UINT ; +typedef int INT ; +#else +typedef unsigned short UWORD ; +#endif + + +#endif /* __declare_h */ + diff --git a/utils/Install/incace/globals.h b/utils/Install/incace/globals.h new file mode 100644 index 0000000000..f6b03660ec --- /dev/null +++ b/utils/Install/incace/globals.h @@ -0,0 +1,90 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* Global variable definitions */ +/* */ +/* ------------------------------------------------------------------------ */ + +#ifndef __globals_h +#define __globals_h + +#include "acestruc.h" +#include "unace.h" + +//-------- Ace sign +extern const char *acesign; + +//-------- Version string for program +extern const char *version; + +//-------- header buffer and pointers +extern thead head; + +extern tmhead *t_mhead; +extern tfhead *t_fhead; + +//-------- buffers +extern ULONG *buf_rd ; +extern CHAR *buf ; +extern CHAR *buf_wr ; +extern UCHAR *readbuf; + +//-------- decompressor variables +extern +SHORT rpos , + dcpr_do , + dcpr_do_max , + blocksize , + dcpr_dic , + dcpr_oldnum , + bits_rd , + dcpr_frst_file; +extern +USHORT dcpr_code_mn[1 << maxwd_mn], + dcpr_code_lg[1 << maxwd_lg]; +extern +UCHAR dcpr_wd_mn[maxcode + 2], + dcpr_wd_lg[maxcode + 2], + wd_svwd[svwd_cnt]; +extern +ULONG dcpr_dpos , + cpr_dpos2 , + dcpr_dicsiz , + dcpr_dican , + dcpr_size , + dcpr_olddist[4], + code_rd ; +extern +CHAR *dcpr_text ; + +//-------- quicksort +extern USHORT sort_org[maxcode + 2]; +extern UCHAR sort_freq[(maxcode + 2) * 2]; + +//-------- file handling +extern CHAR aname[PATH_MAX]; +extern +INT archan, + wrhan; +#if !defined(__EMX__) && !defined(__OS2__) +extern FILE *farchan; +#endif + +extern LONG skipsize; + +//-------- structures for archive handling +extern struct tadat adat; + +//-------- flags +extern +INT f_err , + f_ovrall , + f_allvol_pr, + f_curpas , + f_criterr ; + +int pipeit(char *format, ...); +void error(char *format, ...); +int confirm(char *format, ...); + +#endif /* __globals_h */ + diff --git a/utils/Install/incace/os.h b/utils/Install/incace/os.h new file mode 100644 index 0000000000..a5f3d0de79 --- /dev/null +++ b/utils/Install/incace/os.h @@ -0,0 +1,26 @@ +#ifndef __os_h +#define __os_h + + +#if defined(AMIGA) + #define DIRSEP '/' + #define HI_LO_BYTE_ORDER +#endif + +#if defined(DOS) || defined(WINNT) || defined(WIN16) + #define DIRSEP '\\' + #define LO_HI_BYTE_ORDER +#endif + +#if defined(OS2) || defined(__EMX__) + #define DIRSEP '\\' + #define LO_HI_BYTE_ORDER +#endif + +#if defined(UNIX) + #define DIRSEP '/' + #define HI_LO_BYTE_ORDER +#endif + + +#endif /* __os_h */ diff --git a/utils/Install/incace/portable.h b/utils/Install/incace/portable.h new file mode 100644 index 0000000000..0488adf3d6 --- /dev/null +++ b/utils/Install/incace/portable.h @@ -0,0 +1,101 @@ +/****************************************************************/ +/* */ +/* A collection of routines used in making ACE portable for */ +/* different computers */ +/* */ +/****************************************************************/ + +#ifndef __portable_h +#define __portable_h + +#include "os.h" + +#ifdef HI_LO_BYTE_ORDER + +/* All kinds of inplace swap routines, to reverse from LOHI to HILO byte order */ + +#ifdef AMIGA + +#if __SASC && __VERSION__>=6 && __REVISION__>=58 + +#define WORDswap(n) (*(n) = __builtin_rol(*(n), 8, 1)) +#define LONGswap(n) ( WORDswap(&((WORD *)(n))[0]),\ + WORDswap(&((WORD *)(n))[1]),\ + *(n) = __builtin_rol(*(n), 16, 2) ) +#else /* __SASC */ + +#define EORSWAP + +#endif /* !__SASC */ + +#endif /* AMIGA */ + + +#ifdef EORSWAP + +/* With some compilers and processors these work faster then the + * regular swap below, for example on a Amiga 68040 using SAS C 6.58. + * But using builtin rotates works even faster, see above. + */ + +#define WORDswap(n) (((BYTE*)(n))[0] ^= ((BYTE*)(n))[1],\ + ((BYTE*)(n))[1] ^= ((BYTE*)(n))[0],\ + ((BYTE*)(n))[0] ^= ((BYTE*)(n))[1]) +#define LONGswap(n) (((BYTE*)(n))[0] ^= ((BYTE*)(n))[3],\ + ((BYTE*)(n))[3] ^= ((BYTE*)(n))[0],\ + ((BYTE*)(n))[0] ^= ((BYTE*)(n))[3],\ + ((BYTE*)(n))[1] ^= ((BYTE*)(n))[2],\ + ((BYTE*)(n))[2] ^= ((BYTE*)(n))[1],\ + ((BYTE*)(n))[1] ^= ((BYTE*)(n))[2]) +#endif /* EORSWAP */ + +#ifndef WORDswap + +/* If not yet defined use the standard swaps */ + +#define WORDswap(n) (*(n) = (*(n) << 8) | (*(n) >> 8)) +#define LONGswap(n) ( WORDswap(&((WORD *)(n))[0]),\ + WORDswap(&((WORD *)(n))[1]),\ + *(n) = (*(n) >> 16) | (*(n) << 16) ) +#endif /* WORDSWAP */ + +#endif /* HI_LO_BYTE_ORDER */ + + +/* GENERIC: Convert to LONG or WORD from BYTE-Pointer-to-LOHI-byte-order data, + * without worrying if the bytes are word alined in memory. + * p is a pointer to char. + */ + +#ifdef HI_LO_BYTE_ORDER + +#define BUFP2WORD(p) ((UWORD)*(p)++ | ((*(p)++)<<8)) +#define BUFP2LONG(p) ((ULONG)*(p)++ | ((*(p)++)<<8) | ((*(p)++)<<16) | ((*(p)++)<<24)) + +#define BUF2WORD(p) ((UWORD)*(p) | (*((p)+1)<<8)) +#define BUF2LONG(p) ((ULONG)*(p) | (*((p)+1)<<8) | (*((p)+2)<<16) | (*((p)+3)<<24)) + +#else /* HI_LO_BYTE_ORDER */ + +#define BUFP2WORD(p) *(UWORD*)((p+=2)-2) +#define BUFP2LONG(p) *(ULONG*)((p+=4)-4) + +#define BUF2WORD(p) (*(UWORD*)p) +#define BUF2LONG(p) (*(ULONG*)p) + +#endif /* !HI_LO_BYTE_ORDER */ + +/* Timestamp macros */ + +#define get_tx(m,d,h,n) (((ULONG)m<<21)+((ULONG)d<<16)+((ULONG)h<<11)+(n<<5)) +#define get_tstamp(y,m,d,h,n,s) ((((ULONG)(y-1980))<<25)+get_tx(m,d,h,n)+(s/2)) + +#define ts_year(ts) ((UINT)((ts >> 25) & 0x7f) + 1980) +#define ts_month(ts) ((UINT)(ts >> 21) & 0x0f) // 1..12 means Jan..Dec +#define ts_day(ts) ((UINT)(ts >> 16) & 0x1f) // 1..31 means 1st..31st +#define ts_hour(ts) ((UINT)(ts >> 11) & 0x1f) +#define ts_min(ts) ((UINT)(ts >> 5) & 0x3f) +#define ts_sec(ts) ((UINT)((ts & 0x1f) * 2)) + + +#endif /* __portable_h */ diff --git a/utils/Install/incace/uac_comm.h b/utils/Install/incace/uac_comm.h new file mode 100644 index 0000000000..04bfdcef56 --- /dev/null +++ b/utils/Install/incace/uac_comm.h @@ -0,0 +1,14 @@ +#ifndef __uac_comm_h +#define __uac_comm_h + + +#include "declare.h" + +extern INT comm_cpr_size; +extern CHAR *comm; + +void comment_out(CHAR *top); + + +#endif /* __uac_comm_h */ + diff --git a/utils/Install/incace/uac_crc.h b/utils/Install/incace/uac_crc.h new file mode 100644 index 0000000000..566a80845a --- /dev/null +++ b/utils/Install/incace/uac_crc.h @@ -0,0 +1,20 @@ +#ifndef __uac_crc_h +#define __uac_crc_h + + +#include "declare.h" + +#define CRC_MASK 0xFFFFFFFFL +#define CRCPOLY 0xEDB88320L + + +extern ULONG crctable[256]; +extern ULONG rd_crc; + + +ULONG getcrc(ULONG crc, UCHAR * addr, INT len); +void make_crctable(void); + + +#endif /* __uac_crc_h */ + diff --git a/utils/Install/incace/uac_crt.h b/utils/Install/incace/uac_crt.h new file mode 100644 index 0000000000..38614d1895 --- /dev/null +++ b/utils/Install/incace/uac_crt.h @@ -0,0 +1,12 @@ +#ifndef __uac_crt_h +#define __uac_crt_h + + +#include "acestruc.h" + +CHAR *ace_fname(CHAR * s, thead * head, INT nopath); +INT create_dest_file(CHAR * file, INT a); + + +#endif /* __uac_crt_h */ + diff --git a/utils/Install/incace/uac_dcpr.h b/utils/Install/incace/uac_dcpr.h new file mode 100644 index 0000000000..92795d056f --- /dev/null +++ b/utils/Install/incace/uac_dcpr.h @@ -0,0 +1,14 @@ +#ifndef __uac_dcpr_h +#define __uac_dcpr_h + +#include "declare.h" + +INT calc_dectabs(void); +void dcpr_comm(INT comm_size); +INT read_wd(UINT maxwd, USHORT * code, UCHAR * wd, INT max_el); +void dcpr_init(void); +INT dcpr_adds_blk(CHAR * buf, UINT len); +void dcpr_init_file(void); + +#endif /* __uac_dcpr_h */ + diff --git a/utils/Install/incace/uac_sys.h b/utils/Install/incace/uac_sys.h new file mode 100644 index 0000000000..ac283f1831 --- /dev/null +++ b/utils/Install/incace/uac_sys.h @@ -0,0 +1,18 @@ +#ifndef __uac_sys_h +#define __uac_sys_h + + +#include "declare.h" + +#define upcase(ch) ((in(ch,'a','z'))?(ch-32):(ch)) + +void memset16(USHORT * dest, SHORT val, INT len); +INT cancel(void); +INT wrask(CHAR * s); +#if !defined(__MINGW32__) +void beep(void); +#endif +void set_handler(void); + + +#endif diff --git a/utils/Install/incace/unace.h b/utils/Install/incace/unace.h new file mode 100644 index 0000000000..3e85277771 --- /dev/null +++ b/utils/Install/incace/unace.h @@ -0,0 +1,66 @@ +#ifndef __unace_h +#define __unace_h + + +#include "declare.h" + + +//--------- functions + +INT read_adds_blk(CHAR * buffer, INT len); + + +//--------- buffers: increase sizes when possible to speed up the program + +#define size_rdb 1024 +#define size_wrb 2048 +#define size_buf 1024 + +#define size_headrdb (sizeof(head)-20) // (some bytes less esp. for Amiga) + + +//--------- (de-)compressor constants + +#define maxdic 22 +#define maxwd_mn 11 +#define maxwd_lg 11 +#define maxwd_svwd 7 +#define maxlength 259 +#define maxdis2 255 +#define maxdis3 8191 +#define maxcode (255+4+maxdic) +#define svwd_cnt 15 +#define max_cd_mn (256+4+(maxdic+1)-1) +#define max_cd_lg (256-1) + +//--------- flags + +#define ERR_MEM 1 +#define ERR_FILES 2 +#define ERR_FOUND 3 +#define ERR_FULL 4 +#define ERR_OPEN 5 +#define ERR_READ 6 +#define ERR_WRITE 7 +#define ERR_CLINE 8 +#define ERR_CRC 9 +#define ERR_OTHER 10 +#define ERR_USER 255 + +//--------- system things + +#define flush fflush(stdout); + +#define in(v1,v2,v3) ((((long)v1)>=(v2)) && (((long)v1)<=(v3))) + +#define delay_len 500 + +//-------- file creation + +#define fileexists(name) (!access(name, 0)) + + +//-------- eof + +#endif /* __unace_h */ + diff --git a/utils/Install/inczip/consts.h b/utils/Install/inczip/consts.h new file mode 100644 index 0000000000..f418a6c8fe --- /dev/null +++ b/utils/Install/inczip/consts.h @@ -0,0 +1,46 @@ +/*--------------------------------------------------------------------------- + + 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 ush near mask_bits[] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + +ZCONST char Far VersionDate[] = VERSION_DATE; /* now defined in version.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 #%u).\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/utils/Install/inczip/crypt.h b/utils/Install/inczip/crypt.h new file mode 100644 index 0000000000..d462f2d7ba --- /dev/null +++ b/utils/Install/inczip/crypt.h @@ -0,0 +1,24 @@ +/* + crypt.h (dummy version) by Info-ZIP. Last revised: 15 Aug 98 + + This is a non-functional version of Info-ZIP's crypt.h encryption/ + decryption header file for Zip, ZipCloak, UnZip and fUnZip. This + file is not copyrighted and may be distributed without restriction. + See the "WHERE" file for sites from which to obtain the full crypt + sources (zcrypt28.zip or later). + */ + +#ifndef __crypt_h /* don't include more than once */ +#define __crypt_h + +#ifdef CRYPT +# undef CRYPT +#endif +#define CRYPT 0 /* dummy version */ + +#define zencode +#define zdecode + +#define zfwrite fwrite + +#endif /* !__crypt_h */ diff --git a/utils/Install/inczip/ebcdic.h b/utils/Install/inczip/ebcdic.h new file mode 100644 index 0000000000..db2e976b7f --- /dev/null +++ b/utils/Install/inczip/ebcdic.h @@ -0,0 +1,272 @@ +/*--------------------------------------------------------------------------- + + 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[] = { + 0x3F, 0x3F, 0x27, 0x9F, 0x22, 0x2E, 0xC5, 0xCE, /* 80 - 87 */ + 0x5E, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F, /* 88 - 8F */ + 0x3F, 0x27, 0x27, 0x22, 0x22, 0x07, 0x2D, 0x2D, /* 90 - 97 */ + 0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59, /* 98 - 9F */ + 0xFF, 0xAD, 0xBD, 0x9C, 0xCF, 0xBE, 0xDD, 0xF5, /* A0 - A7 */ + 0xF9, 0xB8, 0xA6, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE, /* A8 - AF */ + 0xF8, 0xF1, 0xFD, 0xFC, 0xEF, 0xE6, 0xF4, 0xFA, /* B0 - B7 */ + 0xF7, 0xFB, 0xA7, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8, /* B8 - BF */ + 0xB7, 0xB5, 0xB6, 0xC7, 0x8E, 0x8F, 0x92, 0x80, /* C0 - C7 */ + 0xD4, 0x90, 0xD2, 0xD3, 0xDE, 0xD6, 0xD7, 0xD8, /* C8 - CF */ + 0xD1, 0xA5, 0xE3, 0xE0, 0xE2, 0xE5, 0x99, 0x9E, /* D0 - D7 */ + 0x9D, 0xEB, 0xE9, 0xEA, 0x9A, 0xED, 0xE8, 0xE1, /* D8 - DF */ + 0x85, 0xA0, 0x83, 0xC6, 0x84, 0x86, 0x91, 0x87, /* E0 - E7 */ + 0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B, /* E8 - EF */ + 0xD0, 0xA4, 0x95, 0xA2, 0x93, 0xE4, 0x94, 0xF6, /* F0 - F7 */ + 0x9B, 0x97, 0xA3, 0x96, 0x81, 0xEC, 0xE7, 0x98 /* F8 - FF */ +}; +#endif /* IZ_ISO2OEM_ARRAY */ + +#ifdef IZ_OEM2ISO_ARRAY +ZCONST uch Far oem2iso[] = { + 0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7, /* 80 - 87 */ + 0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5, /* 88 - 8F */ + 0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9, /* 90 - 97 */ + 0xFF, 0xD6, 0xDC, 0xF8, 0xA3, 0xD8, 0xD7, 0x83, /* 98 - 9F */ + 0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA, /* A0 - A7 */ + 0xBF, 0xAE, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB, /* A8 - AF */ + 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xC1, 0xC2, 0xC0, /* B0 - B7 */ + 0xA9, 0xA6, 0xA6, 0x2B, 0x2B, 0xA2, 0xA5, 0x2B, /* B8 - BF */ + 0x2B, 0x2D, 0x2D, 0x2B, 0x2D, 0x2B, 0xE3, 0xC3, /* C0 - C7 */ + 0x2B, 0x2B, 0x2D, 0x2D, 0xA6, 0x2D, 0x2B, 0xA4, /* C8 - CF */ + 0xF0, 0xD0, 0xCA, 0xCB, 0xC8, 0x69, 0xCD, 0xCE, /* D0 - D7 */ + 0xCF, 0x2B, 0x2B, 0xA6, 0x5F, 0xA6, 0xCC, 0xAF, /* D8 - DF */ + 0xD3, 0xDF, 0xD4, 0xD2, 0xF5, 0xD5, 0xB5, 0xFE, /* E0 - E7 */ + 0xDE, 0xDA, 0xDB, 0xD9, 0xFD, 0xDD, 0xAF, 0xB4, /* E8 - EF */ + 0xAD, 0xB1, 0x3D, 0xBE, 0xB6, 0xA7, 0xF7, 0xB8, /* F0 - F7 */ + 0xB0, 0xA8, 0xB7, 0xB9, 0xB3, 0xB2, 0xA6, 0xA0 /* F8 - FF */ +}; +#endif /* IZ_OEM2ISO_ARRAY */ + +#endif /* __ebcdic_h */ diff --git a/utils/Install/inczip/globals.h b/utils/Install/inczip/globals.h new file mode 100644 index 0000000000..49439cffe7 --- /dev/null +++ b/utils/Install/inczip/globals.h @@ -0,0 +1,395 @@ +/*--------------------------------------------------------------------------- + + 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" +#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... */ +#endif /* (take line-wrapping into account?) */ +#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME)) + int tz_is_valid; /* indicates that timezone info can be used */ +#endif +#ifdef WINDLL + int prompt_always; /* prompt to overwrite if TRUE */ +#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 create_dirs; /* used by main(), mapname(), checkdir() */ + int extract_flag; + int newzip; /* reset in extract.c; used in crypt.c */ + LONGINT real_ecrec_offset; + LONGINT expect_ecrec_offset; + long csize; /* used by decompr. (NEXTBYTE): must be signed */ + long ucsize; /* used by unReduce(), explode() */ + long 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 */ + unsigned _wsize; +# endif + unsigned 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 */ + +#ifndef FUNZIP +# if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) + ZCONST ulg near *crc_32_tab; +# else + ZCONST ulg Far *crc_32_tab; +# endif +#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 + LONGINT ziplen; + LONGINT cur_zipfile_bufstart; /* extract_or_test, readbuf, ReadByte */ + LONGINT 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 */ + struct 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; +#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 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 */ + ulg keys[3]; /* crypt static: keys defining pseudo-random sequence */ + +#if (!defined(DOS_FLX_H68_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_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 */ + int fixed_bl, fixed_bd; /* inflate static */ + unsigned wp; /* inflate static: current position in slide */ + ulg bb; /* inflate static: bit buffer */ + unsigned bk; /* inflate static: bits in bit buffer */ +#endif /* ?USE_ZLIB */ + +#ifndef FUNZIP +#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 + int VMS_line_state; /* so native VMS variable-length text files are */ + int VMS_line_length; /* readable on other platforms */ + int VMS_line_pad; +#endif +#endif /* !FUNZIP */ + +#ifdef SYSTEM_SPECIFIC_GLOBALS + SYSTEM_SPECIFIC_GLOBALS +#endif + +} Uz_Globs; /* end of struct Globals */ + + +/***************************************************************************/ + + +#ifdef FUNZIP +# if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) + extern ZCONST ulg near crc_32_tab[256]; +# else + extern ZCONST ulg Far *crc_32_tab; +# endif +# define CRC_32_TAB crc_32_tab +#else +# define CRC_32_TAB G.crc_32_tab +#endif + + +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 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() {free_G_buffers(pG); deregisterGlobalPointer(pG);} +# else + extern Uz_Globs *GG; +# define GETGLOBALS() Uz_Globs *pG = GG; +# define DESTROYGLOBALS() {free_G_buffers(pG); free(pG);} +# 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/utils/Install/inczip/inflate.h b/utils/Install/inczip/inflate.h new file mode 100644 index 0000000000..f1d774b793 --- /dev/null +++ b/utils/Install/inczip/inflate.h @@ -0,0 +1,24 @@ +/* inflate.h for UnZip -- put in the public domain by Mark Adler + version c14f, 23 November 1995 */ + + +/* 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/utils/Install/inczip/nt.h b/utils/Install/inczip/nt.h new file mode 100644 index 0000000000..0109c2b678 --- /dev/null +++ b/utils/Install/inczip/nt.h @@ -0,0 +1,28 @@ +/* nt.h: central header for EF_NTSD "SD" extra field */ + +#ifndef _NT_H +#define _NT_H + +#define NTSD_BUFFERSIZE (1024) /* threshold to cause malloc() */ +#define OVERRIDE_BACKUP 1 /* we have SeBackupPrivilege on remote */ +#define OVERRIDE_RESTORE 2 /* we have SeRestorePrivilege on remote */ +#define OVERRIDE_SACL 4 /* we have SeSystemSecurityPrivilege on remote */ + +typedef struct { + BOOL bValid; /* are our contents valid? */ + BOOL bProcessDefer; /* process deferred entry yet? */ + BOOL bUsePrivileges; /* use privilege overrides? */ + DWORD dwFileSystemFlags; /* describes target file system */ + BOOL bRemote; /* is volume remote? */ + DWORD dwRemotePrivileges; /* relevant only on remote volumes */ + DWORD dwFileAttributes; + char RootPath[MAX_PATH+1]; /* path to network / filesystem */ +} VOLUMECAPS, *PVOLUMECAPS, *LPVOLUMECAPS; + +BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata); +BOOL GetVolumeCaps(char *rootpath, char *name, PVOLUMECAPS VolumeCaps); +BOOL ValidateSecurity(uch *securitydata); +BOOL ProcessDefer(PDWORD dwDirectoryCount, PDWORD dwBytesProcessed, + PDWORD dwDirectoryFail, PDWORD dwBytesFail); + +#endif /* _NT_H */ diff --git a/utils/Install/inczip/os2acl.h b/utils/Install/inczip/os2acl.h new file mode 100644 index 0000000000..1defd59bdb --- /dev/null +++ b/utils/Install/inczip/os2acl.h @@ -0,0 +1,29 @@ +/* os2acl.h + * + * Author: Kai Uwe Rommel + * Created: Fri Mar 29 1996 + */ + +/* $Id$ */ + +/* + * $Log$ + * Revision 1.1.2.1 2000/04/11 12:38:05 BS + * Added wxInstall a self extracting installation program using wxWindows. + * + * 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/utils/Install/inczip/os2cfg.h b/utils/Install/inczip/os2cfg.h new file mode 100644 index 0000000000..0a5bf491ce --- /dev/null +++ b/utils/Install/inczip/os2cfg.h @@ -0,0 +1,136 @@ +/*--------------------------------------------------------------------------- + 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__ */ + +# ifndef EPIPE +# define EPIPE -1 +# endif +# define PIPE_ERROR (errno == EPIPE) +#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 +#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 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)) +#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 + +#endif /* !__os2cfg_h */ diff --git a/utils/Install/inczip/os2data.h b/utils/Install/inczip/os2data.h new file mode 100644 index 0000000000..726baa99d3 --- /dev/null +++ b/utils/Install/inczip/os2data.h @@ -0,0 +1,139 @@ +/*--------------------------------------------------------------------------- + + 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_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 *dir; + char *dirname, *wildname, matchname[FILNAMSIZ]; + int firstcall, 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/utils/Install/inczip/rsxntwin.h b/utils/Install/inczip/rsxntwin.h new file mode 100644 index 0000000000..c6dd09a22f --- /dev/null +++ b/utils/Install/inczip/rsxntwin.h @@ -0,0 +1,155 @@ +/* rsxntwin.h + * + * fills some gaps in the rsxnt 1.3 win32 header files () that are + * required for compiling Info-ZIP sources for Win NT / Win 95 + */ + +#ifdef __RSXNT__ +#if !defined (_RSXNTWIN_H) +#define _RSXNTWIN_H + +#ifdef TFUNCT /* TFUNCT is undefined when MSSDK headers are used */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define PASCAL __stdcall + +#define ANYSIZE_ARRAY 1 + +#ifndef TIME_ZONE_ID_UNKNOWN +# define TIME_ZONE_ID_UNKNOWN 0 +#endif + +#define FILE_ATTRIBUTE_HIDDEN 0x00000002 +#define FILE_ATTRIBUTE_SYSTEM 0x00000004 + +#define FILE_SHARE_DELETE 0x00000004 + +#define FILE_PERSISTENT_ACLS 0x00000008 + +#define HFILE_ERROR ((HFILE)-1) + +#define FS_PERSISTENT_ACLS FILE_PERSISTENT_ACLS + + +BOOL WINAPI DosDateTimeToFileTime(WORD, WORD, LPFILETIME); + + +#ifndef SetVolumeLabel +#define SetVolumeLabel TFUNCT(SetVolumeLabel) +#endif +BOOL WINAPI SetVolumeLabel(LPCTSTR, LPCTSTR); + + +#ifndef GetDriveType +#define GetDriveType TFUNCT(GetDriveType) +#endif +DWORD GetDriveType(LPCTSTR); + +#define DRIVE_UNKNOWN 0 +#define DRIVE_REMOVABLE 2 +#define DRIVE_FIXED 3 +#define DRIVE_REMOTE 4 +#define DRIVE_CDROM 5 +#define DRIVE_RAMDISK 6 + +#ifndef SearchPath +#define SearchPath TFUNCT(SearchPath) +#endif +BOOL WINAPI SearchPath(LPCTSTR, LPCTSTR, LPCTSTR, UINT, LPTSTR, LPTSTR *); + +#define ERROR_SUCCESS 0 +#define ERROR_INSUFFICIENT_BUFFER 122 + +LONG WINAPI InterlockedExchange(LPLONG, LONG); + +#define ACCESS_SYSTEM_SECURITY 0x01000000L + +typedef PVOID PSECURITY_DESCRIPTOR; +typedef PVOID PSID; +typedef struct _ACL { + BYTE AclRevision; + BYTE Sbz1; + WORD AclSize; + WORD AceCount; + WORD Sbz2; +} ACL; +typedef ACL *PACL; + +typedef struct _LUID { + DWORD LowPart; + LONG HighPart; +} LUID, *PLUID; + +typedef struct _LUID_AND_ATTRIBUTES { + LUID Luid; + DWORD Attributes; + } LUID_AND_ATTRIBUTES, * PLUID_AND_ATTRIBUTES; + +typedef struct _TOKEN_PRIVILEGES { + DWORD PrivilegeCount; + LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; +} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES; + +#define TOKEN_QUERY 0x0008 +#define TOKEN_ADJUST_PRIVILEGES 0x0020 + +BOOL WINAPI OpenProcessToken(HANDLE, DWORD, PHANDLE); +BOOL WINAPI AdjustTokenPrivileges(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, + PTOKEN_PRIVILEGES, PDWORD); + +#ifndef LookupPrivilegeValue +#define LookupPrivilegeValue TFUNCT(LookupPrivilegeValue) +#endif +BOOL WINAPI LookupPrivilegeValue(LPCTSTR, LPCTSTR, PLUID); + +typedef DWORD SECURITY_INFORMATION, *PSECURITY_INFORMATION; +#define OWNER_SECURITY_INFORMATION 0x00000001L +#define GROUP_SECURITY_INFORMATION 0x00000002L +#define DACL_SECURITY_INFORMATION 0x00000004L +#define SACL_SECURITY_INFORMATION 0x00000008L + +typedef WORD SECURITY_DESCRIPTOR_CONTROL, *PSECURITY_DESCRIPTOR_CONTROL; +#define SE_DACL_PRESENT 0x0004 +#define SE_SACL_PRESENT 0x0010 + +#define SE_PRIVILEGE_ENABLED 0x00000002L + +#define SE_SECURITY_NAME TEXT("SeSecurityPrivilege") +#define SE_BACKUP_NAME TEXT("SeBackupPrivilege") +#define SE_RESTORE_NAME TEXT("SeRestorePrivilege") + +BOOL WINAPI GetKernelObjectSecurity(HANDLE, SECURITY_INFORMATION, + PSECURITY_DESCRIPTOR, DWORD, LPDWORD); +BOOL WINAPI SetKernelObjectSecurity(HANDLE, SECURITY_INFORMATION, + PSECURITY_DESCRIPTOR); +BOOL WINAPI IsValidSid(PSID); +BOOL WINAPI IsValidAcl(PACL); +BOOL WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR); +BOOL WINAPI IsValidSecurityDescriptor(PSECURITY_DESCRIPTOR); +DWORD WINAPI GetSecurityDescriptorLength(PSECURITY_DESCRIPTOR); +BOOL WINAPI GetSecurityDescriptorControl(PSECURITY_DESCRIPTOR, + PSECURITY_DESCRIPTOR_CONTROL, LPDWORD); +BOOL WINAPI SetSecurityDescriptorControl(PSECURITY_DESCRIPTOR, + SECURITY_DESCRIPTOR_CONTROL, SECURITY_DESCRIPTOR_CONTROL); +BOOL WINAPI GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR, + LPBOOL, PACL *, LPBOOL); +BOOL WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR, BOOL, PACL, BOOL); +BOOL WINAPI GetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR, + LPBOOL, PACL *, LPBOOL); +BOOL WINAPI SetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR, BOOL, PACL, BOOL); +BOOL WINAPI GetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR, PSID *, LPBOOL); +BOOL WINAPI SetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR, PSID, BOOL); +BOOL WINAPI GetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR, PSID *, LPBOOL); +BOOL WINAPI SetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR, PSID, BOOL); +VOID WINAPI InitializeCriticalSection(); + +#ifdef __cplusplus +} +#endif + +#endif /* TFUNCT */ +#endif /* !defined (_RSXNTWIN_H) */ +#endif /* __RSXNT__ */ diff --git a/utils/Install/inczip/tables.h b/utils/Install/inczip/tables.h new file mode 100644 index 0000000000..0f4ecc316a --- /dev/null +++ b/utils/Install/inczip/tables.h @@ -0,0 +1,81 @@ +/*--------------------------------------------------------------------------- + + tables.h + + This file contains only the 32-bit CRC table used in fUnZip; + it is in a separate file because it is rather big and ugly and + gets in the way during editing. + This file can be included in no more than ONE source file per + executable, of course. + + ---------------------------------------------------------------------------*/ + +#ifndef __tables_h /* prevent multiple inclusions */ +#define __tables_h + +#ifdef FUNZIP +#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) + +/* Table of CRC-32's of all single-byte values (made by makecrc.c) */ +ZCONST ulg near crc_32_tab[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 +}; + +#else /* USE_ZLIB && !USE_OWN_CRCTAB */ + +ZCONST uLongf *crc_32_tab = NULL; + +#endif /* ?(!USE_ZLIB || USE_OWN_CRCTAB) */ +#endif /* FUNZIP */ +#endif /* __tables_h */ diff --git a/utils/Install/inczip/ttyio.h b/utils/Install/inczip/ttyio.h new file mode 100644 index 0000000000..685e7ace66 --- /dev/null +++ b/utils/Install/inczip/ttyio.h @@ -0,0 +1,186 @@ +/* + ttyio.h + */ + +#ifndef __ttyio_h /* don't include more than once */ +#define __ttyio_h + +#ifndef __crypt_h +# include "crypt.h" /* ensure that encryption header file has been seen */ +#endif + +#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP))) +/* + * Non-echo keyboard/console input support is needed and enabled. + */ + +#ifndef __G /* UnZip only, for now (DLL stuff) */ +# define __G +# define __G__ +# define __GDEF +# define __GPRO void +# define __GPRO__ +#endif + +#ifndef ZCONST /* UnZip only (until have configure script like Zip) */ +# define ZCONST const +#endif + +#if (defined(MSDOS) || defined(OS2) || defined(WIN32)) +# ifndef DOS_OS2_W32 +# define DOS_OS2_W32 +# endif +#endif + +#if (defined(DOS_OS2_W32) || defined(__human68k__)) +# ifndef DOS_H68_OS2_W32 +# define DOS_H68_OS2_W32 +# endif +#endif + +#if (defined(DOS_OS2_W32) || defined(FLEXOS)) +# ifndef DOS_FLX_OS2_W32 +# define DOS_FLX_OS2_W32 +# endif +#endif + +#if (defined(DOS_H68_OS2_W32) || defined(FLEXOS)) +# ifndef DOS_FLX_H68_OS2_W32 +# define DOS_FLX_H68_OS2_W32 +# endif +#endif + +#if (defined(VM_CMS) || defined(MVS)) +# ifndef CMS_MVS +# define CMS_MVS +# endif +#endif + + +/* Function prototypes */ + +/* The following systems supply a `non-echo' character input function "getch()" + * (or an alias) and do not need the echoff() / echon() function pair. + */ +#ifdef AMIGA +# define echoff(f) +# define echon() +# define getch() Agetch() +# define HAVE_WORKING_GETCH +#endif /* AMIGA */ + +#ifdef ATARI +# define echoff(f) +# define echon() +# include +# define getch() (Cnecin() & 0x000000ff) +# define HAVE_WORKING_GETCH +#endif + +#ifdef MACOS +# define echoff(f) +# define echon() +# define getch() macgetch() +# define HAVE_WORKING_GETCH +#endif + +#ifdef QDOS +# define echoff(f) +# define echon() +# define HAVE_WORKING_GETCH +#endif + +#ifdef RISCOS +# define echoff(f) +# define echon() +# define getch() SWI_OS_ReadC() +# define HAVE_WORKING_GETCH +#endif + +#ifdef DOS_H68_OS2_W32 +# define echoff(f) +# define echon() +# ifdef WIN32 +# ifndef getch +# define getch() getch_win32() +# endif +# else /* !WIN32 */ +# ifdef __EMX__ +# ifndef getch +# define getch() _read_kbd(0, 1, 0) +# endif +# else /* !__EMX__ */ +# ifdef __GO32__ +# include +# define getch() getkey() +# else /* !__GO32__ */ +# include +# endif /* ?__GO32__ */ +# endif /* ?__EMX__ */ +# endif /* ?WIN32 */ +# define HAVE_WORKING_GETCH +#endif /* DOS_H68_OS2_W32 */ + +#ifdef FLEXOS +# define echoff(f) +# define echon() +# define getch() getchar() /* not correct, but may not be on a console */ +# define HAVE_WORKING_GETCH +#endif + +/* For VM/CMS and MVS, we do not (yet) have any support to switch terminal + * input echo on and off. The following "fake" definitions allow inclusion + * of crypt support and UnZip's "pause prompting" features, but without + * any echo suppression. + */ +#ifdef CMS_MVS +# define echoff(f) +# define echon() +#endif + +/* VMS has a single echo() function in ttyio.c to toggle terminal + * input echo on and off. + */ +#ifdef VMS +# define echoff(f) echo(0) +# define echon() echo(1) + int echo OF((int)); +#endif + +/* For all other systems, ttyio.c supplies the two functions Echoff() and + * Echon() for suppressing and (re)enabling console input echo. + */ +#ifndef echoff +# define echoff(f) Echoff(__G__ f) +# define echon() Echon(__G) + void Echoff OF((__GPRO__ int f)); + void Echon OF((__GPRO)); +#endif + +/* this stuff is used by MORE and also now by the ctrl-S code; fileio.c only */ +#if (defined(UNZIP) && !defined(FUNZIP)) +# ifdef HAVE_WORKING_GETCH +# define FGETCH(f) getch() +# endif +# ifndef FGETCH + /* default for all systems where no getch()-like function is available */ + int zgetch OF((__GPRO__ int f)); +# define FGETCH(f) zgetch(__G__ f) +# endif +#endif /* UNZIP && !FUNZIP */ + +#if (CRYPT && !defined(WINDLL)) + char *getp OF((__GPRO__ ZCONST char *m, char *p, int n)); +#endif + +#else /* !(CRYPT || (UNZIP && !FUNZIP)) */ + +/* + * No need for non-echo keyboard/console input; provide dummy definitions. + */ +#define echoff(f) +#define echon() + +#endif /* ?(CRYPT || (UNZIP && !FUNZIP)) */ + +#endif /* !__ttyio_h */ diff --git a/utils/Install/inczip/unzip.h b/utils/Install/inczip/unzip.h new file mode 100644 index 0000000000..5aa56a4160 --- /dev/null +++ b/utils/Install/inczip/unzip.h @@ -0,0 +1,548 @@ +/*--------------------------------------------------------------------------- + + unzip.h (new) + + This header file contains the public macros and typedefs required by + both the UnZip sources and by any application using the UnZip API. If + UNZIP_INTERNAL is defined, it includes unzpriv.h (containing includes, + prototypes and extern variables used by the actual UnZip sources). + + ---------------------------------------------------------------------------*/ + + +#ifndef __unzip_h /* prevent multiple inclusions */ +#define __unzip_h + +/*--------------------------------------------------------------------------- + Predefined, machine-specific macros. + ---------------------------------------------------------------------------*/ + +#ifdef __GO32__ /* MS-DOS extender: NOT Unix */ +# ifdef unix +# undef unix +# endif +# ifdef __unix +# undef __unix +# endif +# ifdef __unix__ +# undef __unix__ +# endif +#endif + +#if ((defined(__convex__) || defined(__convexc__)) && !defined(CONVEX)) +# define CONVEX +#endif + +#if (defined(unix) || defined(__unix) || defined(__unix__)) +# ifndef UNIX +# define UNIX +# endif +#endif /* unix || __unix || __unix__ */ +#if (defined(M_XENIX) || defined(COHERENT) || defined(__hpux)) +# ifndef UNIX +# define UNIX +# endif +#endif /* M_XENIX || COHERENT || __hpux */ +#if (defined(CONVEX) || defined(MINIX) || defined(_AIX) || defined(__QNX__)) +# ifndef UNIX +# define UNIX +# endif +#endif /* CONVEX || MINIX || _AIX || __QNX__ */ + +#if (defined(VM_CMS) || defined(MVS)) +# define CMS_MVS +#endif + +#if (defined(__OS2__) && !defined(OS2)) +# define OS2 +#endif + +#if (defined(__TANDEM) && !defined(TANDEM)) +# define TANDEM +#endif + +#if (defined(__VMS) && !defined(VMS)) +# define VMS +#endif + +#if ((defined(__WIN32__) || defined(_WIN32)) && !defined(WIN32)) +# define WIN32 +#endif +#if ((defined(__WINNT__) || defined(__WINNT)) && !defined(WIN32)) +# define WIN32 +#endif + +#ifdef __COMPILER_KCC__ +# include +# ifdef SYS_T20 +# define TOPS20 +# endif +#endif /* __COMPILER_KCC__ */ + +/* Borland C does not define __TURBOC__ if compiling for a 32-bit platform */ +#ifdef __BORLANDC__ +# ifndef __TURBOC__ +# define __TURBOC__ +# endif +# if (!defined(__MSDOS__) && !defined(OS2) && !defined(WIN32)) +# define __MSDOS__ +# endif +#endif + +/* define MSDOS for Turbo C (unless OS/2) and Power C as well as Microsoft C */ +#ifdef __POWERC +# define __TURBOC__ +# define MSDOS +#endif /* __POWERC */ + +#if (defined(__MSDOS__) && !defined(MSDOS)) /* just to make sure */ +# define MSDOS +#endif + +/* RSXNTDJ (at least up to v1.3) compiles for WIN32 (RSXNT) using a derivate + of the EMX environment, but defines MSDOS and __GO32__. ARG !!! */ +#if (defined(MSDOS) && defined(WIN32)) +# undef MSDOS /* WIN32 is >>>not<<< MSDOS */ +#endif +#if (defined(__GO32__) && defined(__EMX__) && defined(__RSXNT__)) +# undef __GO32__ +#endif + +#if (defined(linux) && !defined(LINUX)) +# define LINUX +#endif + +#ifdef __riscos +# define RISCOS +#endif + +#if (defined(THINK_C) || defined(MPW)) +# define MACOS +#endif +#if (defined(__MWERKS__) && defined(macintosh)) +# define MACOS +#endif + +/* use prototypes and ANSI libraries if __STDC__, or Microsoft or Borland C, or + * Silicon Graphics, or Convex?, or IBM C Set/2, or GNU gcc/emx, or Watcom C, + * or Macintosh, or Windows NT, or Sequent, or Atari or IBM RS/6000. + */ +#if (defined(__STDC__) || defined(MSDOS) || defined(WIN32) || defined(__EMX__)) +# ifndef PROTO +# define PROTO +# endif +# ifndef MODERN +# define MODERN +# endif +#endif +#if (defined(__IBMC__) || defined(__BORLANDC__) || defined(__WATCOMC__)) +# ifndef PROTO +# define PROTO +# endif +# ifndef MODERN +# define MODERN +# endif +#endif +#if (defined(MACOS) || defined(ATARI_ST) || defined(RISCOS)) +# ifndef PROTO +# define PROTO +# endif +# ifndef MODERN +# define MODERN +# endif +#endif +/* Sequent running Dynix/ptx: non-modern compiler */ +#if (defined(_AIX) || defined(sgi) || (defined(_SEQUENT_) && !defined(PTX))) +# ifndef PROTO +# define PROTO +# endif +# ifndef MODERN +# define MODERN +# endif +#endif +#if (defined(CMS_MVS) || defined(__BEOS__)) /* || defined(CONVEX) */ +# ifndef PROTO +# define PROTO +# endif +# ifndef MODERN +# define MODERN +# endif +#endif + +/* turn off prototypes if requested */ +#if (defined(NOPROTO) && defined(PROTO)) +# undef PROTO +#endif + +/* used to remove arguments in function prototypes for non-ANSI C */ +#ifdef PROTO +# define OF(a) a +#else +# define OF(a) () +#endif + +/* enable the "const" keyword only if MODERN and if not otherwise instructed */ +#ifdef MODERN +# if (!defined(ZCONST) && (defined(USE_CONST) || !defined(NO_CONST))) +# define ZCONST const +# endif +#endif + +#ifndef ZCONST +# define ZCONST +#endif + + +/*--------------------------------------------------------------------------- + Grab system-specific public include headers. + ---------------------------------------------------------------------------*/ + +#ifdef POCKET_UNZIP /* WinCE port */ +# include "wince/punzip.h" /* must appear before windows.h */ +#endif + +#ifdef WINDLL +# include +# include "windll/structs.h" +#endif + +/*--------------------------------------------------------------------------- + Grab system-dependent definition of EXPENTRY for prototypes below. + ---------------------------------------------------------------------------*/ + +#if 0 +#if (defined(OS2) && !defined(FUNZIP)) +# ifdef UNZIP_INTERNAL +# define INCL_NOPM +# define INCL_DOSNLS +# define INCL_DOSPROCESS +# define INCL_DOSDEVICES +# define INCL_DOSDEVIOCTL +# define INCL_DOSERRORS +# define INCL_DOSMISC +# ifdef OS2DLL +# define INCL_REXXSAA +# include +# endif +# endif /* UNZIP_INTERNAL */ +# include +# define UZ_EXP EXPENTRY +#endif /* OS2 && !FUNZIP */ +#endif /* 0 */ + +#if (defined(OS2) && !defined(FUNZIP)) +# if (defined(__IBMC__) || defined(__WATCOMC__)) +# define UZ_EXP _System /* compiler keyword */ +# else +# define UZ_EXP +# endif +#endif /* OS2 && !FUNZIP */ + +#if (defined(WINDLL) || defined(USE_UNZIP_LIB)) +# ifndef EXPENTRY +# define UZ_EXP WINAPI +# else +# define UZ_EXP EXPENTRY +# endif +#endif + +#ifndef UZ_EXP +# define UZ_EXP +#endif + + +/*--------------------------------------------------------------------------- + Public typedefs. + ---------------------------------------------------------------------------*/ + +#ifndef _IZ_TYPES_DEFINED +#ifdef MODERN + typedef void zvoid; +#else /* !MODERN */ +# ifndef AOS_VS /* mostly modern? */ +# ifndef VAXC /* not fully modern, but has knows 'void' */ +# define void int +# endif /* !VAXC */ +# endif /* !AOS_VS */ + typedef char zvoid; +#endif /* ?MODERN */ +typedef unsigned char uch; /* code assumes unsigned bytes; these type- */ +typedef unsigned short ush; /* defs replace byte/UWORD/ULONG (which are */ +typedef unsigned long ulg; /* predefined on some systems) & match zip */ +#define _IZ_TYPES_DEFINED +#endif /* !_IZ_TYPES_DEFINED */ + +/* InputFn is not yet used and is likely to change: */ +#ifdef PROTO + typedef int (UZ_EXP MsgFn) (zvoid *pG, uch *buf, ulg size, int flag); + typedef int (UZ_EXP InputFn) (zvoid *pG, uch *buf, int *size, int flag); + typedef void (UZ_EXP PauseFn) (zvoid *pG, ZCONST char *prompt, int flag); + typedef int (UZ_EXP PasswdFn) (zvoid *pG, int *rcnt, char *pwbuf, + int size, ZCONST char *zfn, + ZCONST char *efn); + typedef int (UZ_EXP StatCBFn) (zvoid *pG, int fnflag, ZCONST char *zfn, + ZCONST char *efn, ZCONST zvoid *details); + typedef void (UZ_EXP UsrIniFn) (void); +#else /* !PROTO */ + typedef int (UZ_EXP MsgFn) (); + typedef int (UZ_EXP InputFn) (); + typedef void (UZ_EXP PauseFn) (); + typedef int (UZ_EXP PasswdFn) (); + typedef int (UZ_EXP StatCBFn) (); + typedef void (UZ_EXP UsrIniFn) (); +#endif /* ?PROTO */ + +typedef struct _UzpBuffer { /* rxstr */ + ulg strlength; /* length of string */ + char *strptr; /* pointer to string */ +} UzpBuffer; + +typedef struct _UzpInit { + ulg structlen; /* length of the struct being passed */ + + /* GRR: can we assume that each of these is a 32-bit pointer? if not, + * does it matter? add "far" keyword to make sure? */ + MsgFn *msgfn; + InputFn *inputfn; + PauseFn *pausefn; + UsrIniFn *userfn; /* user init function to be called after */ + /* globals constructed and initialized */ + + /* pointer to program's environment area or something? */ + /* hooks for performance testing? */ + /* hooks for extra unzip -v output? (detect CPU or other hardware?) */ + /* anything else? let me (Greg) know... */ +} UzpInit; + +typedef struct _UzpCB { + ulg structlen; /* length of the struct being passed */ + /* GRR: can we assume that each of these is a 32-bit pointer? if not, + * does it matter? add "far" keyword to make sure? */ + MsgFn *msgfn; + InputFn *inputfn; + PauseFn *pausefn; + PasswdFn *passwdfn; + StatCBFn *statrepfn; +} UzpCB; + +/* the collection of general UnZip option flags and option arguments */ +typedef struct _UzpOpts { +#ifndef FUNZIP + char *exdir; /* pointer to extraction root directory (-d option) */ + char *pwdarg; /* pointer to command-line password (-P option) */ + int zipinfo_mode; /* behave like ZipInfo or like normal UnZip? */ + int aflag; /* -a: do ASCII-EBCDIC and/or end-of-line translation */ +#ifdef VMS + int bflag; /* -b: force fixed record format for binary files */ +#endif +#ifdef UNIXBACKUP + int B_flag; /* -B: back up existing files by renaming to *~ first */ +#endif + int cflag; /* -c: output to stdout */ + int C_flag; /* -C: match filenames case-insensitively */ +#ifdef MACOS + int E_flag; /* -E: [MacOS] show Mac extra field during restoring */ +#endif + int fflag; /* -f: "freshen" (extract only newer files) */ +#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS)) + int acorn_nfs_ext; /* -F: RISC OS types & NFS filetype extensions */ +#endif + int hflag; /* -h: header line (zipinfo) */ +#ifdef MACOS + int i_flag; /* -i: [MacOS] ignore filenames stored in Mac e.f. */ +#endif +#ifdef RISCOS + int scanimage; /* -I: scan image files */ +#endif + int jflag; /* -j: junk pathnames (unzip) */ +#if (defined(__BEOS__) || defined(MACOS)) + int J_flag; /* -J: ignore BeOS/MacOS extra field info (unzip) */ +#endif + int lflag; /* -12slmv: listing format (zipinfo) */ + int L_flag; /* -L: convert filenames from some OSes to lowercase */ + int overwrite_none; /* -n: never overwrite files (no prompting) */ +#ifdef AMIGA + int N_flag; /* -N: restore comments as AmigaDOS filenotes */ +#endif + int overwrite_all; /* -o: OK to overwrite files without prompting */ +#endif /* !FUNZIP */ + int qflag; /* -q: produce a lot less output */ +#ifndef FUNZIP +#if (defined(MSDOS) || defined(FLEXOS) || defined(OS2) || defined(WIN32)) + int sflag; /* -s: convert spaces in filenames to underscores */ +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WIN32)) + int volflag; /* -$: extract volume labels */ +#endif + int tflag; /* -t: test (unzip) or totals line (zipinfo) */ + int T_flag; /* -T: timestamps (unzip) or dec. time fmt (zipinfo) */ + int uflag; /* -u: "update" (extract only newer/brand-new files) */ + int vflag; /* -v: (verbosely) list directory */ + int V_flag; /* -V: don't strip VMS version numbers */ +#if (defined(TANDEM) || defined(UNIX) || defined(VMS) || defined(__BEOS__)) + int X_flag; /* -X: restore owner/protection or UID/GID or ACLs */ +#endif +#if (defined(OS2) || defined(WIN32)) + int X_flag; /* -X: restore owner/protection or UID/GID or ACLs */ +#endif + int zflag; /* -z: display the zipfile comment (only, for unzip) */ +#endif /* !FUNZIP */ +} UzpOpts; + +/* intended to be a private struct: */ +typedef struct _ver { + uch major; /* e.g., integer 5 */ + uch minor; /* e.g., 2 */ + uch patchlevel; /* e.g., 0 */ + uch not_used; +} _version_type; + +typedef struct _UzpVer { + ulg structlen; /* length of the struct being passed */ + ulg flag; /* bit 0: is_beta bit 1: uses_zlib */ + char *betalevel; /* e.g., "g BETA" or "" */ + char *date; /* e.g., "4 Sep 95" (beta) or "4 September 1995" */ + char *zlib_version; /* e.g., "0.95" or NULL */ + _version_type unzip; + _version_type zipinfo; + _version_type os2dll; + _version_type windll; +} UzpVer; + +/* for Visual BASIC access to Windows DLLs: */ +typedef struct _UzpVer2 { + ulg structlen; /* length of the struct being passed */ + ulg flag; /* bit 0: is_beta bit 1: uses_zlib */ + char betalevel[10]; /* e.g., "g BETA" or "" */ + char date[20]; /* e.g., "4 Sep 95" (beta) or "4 September 1995" */ + char zlib_version[10]; /* e.g., "0.95" or NULL */ + _version_type unzip; + _version_type zipinfo; + _version_type os2dll; + _version_type windll; +} UzpVer2; + +typedef struct central_directory_file_header { /* CENTRAL */ + uch version_made_by[2]; + uch version_needed_to_extract[2]; + ush general_purpose_bit_flag; + ush compression_method; + ulg last_mod_dos_datetime; + ulg crc32; + ulg csize; + ulg ucsize; + ush filename_length; + ush extra_field_length; + ush file_comment_length; + ush disk_number_start; + ush internal_file_attributes; + ulg external_file_attributes; + ulg relative_offset_local_header; +} cdir_file_hdr; + + +#define UZPINIT_LEN sizeof(UzpInit) +#define UZPVER_LEN sizeof(UzpVer) +#define cbList(func) int (* UZ_EXP func)(char *filename, cdir_file_hdr *crec) + + +/*--------------------------------------------------------------------------- + Return (and exit) values of the public UnZip API functions. + ---------------------------------------------------------------------------*/ + +/* external return codes */ +#define PK_OK 0 /* no error */ +#define PK_COOL 0 /* no error */ +#define PK_GNARLY 0 /* no error */ +#define PK_WARN 1 /* warning error */ +#define PK_ERR 2 /* error in zipfile */ +#define PK_BADERR 3 /* severe error in zipfile */ +#define PK_MEM 4 /* insufficient memory (during initialization) */ +#define PK_MEM2 5 /* insufficient memory (password failure) */ +#define PK_MEM3 6 /* insufficient memory (file decompression) */ +#define PK_MEM4 7 /* insufficient memory (memory decompression) */ +#define PK_MEM5 8 /* insufficient memory (not yet used) */ +#define PK_NOZIP 9 /* zipfile not found */ +#define PK_PARAM 10 /* bad or illegal parameters specified */ +#define PK_FIND 11 /* no files found */ +#define PK_DISK 50 /* disk full */ +#define PK_EOF 51 /* unexpected EOF */ + +#define IZ_CTRLC 80 /* user hit ^C to terminate */ +#define IZ_UNSUP 81 /* no files found: all unsup. compr/encrypt. */ +#define IZ_BADPWD 82 /* no files found: all had bad password */ + +/* internal and DLL-only return codes */ +#define IZ_DIR 76 /* potential zipfile is a directory */ +#define IZ_CREATED_DIR 77 /* directory created: set time and permissions */ +#define IZ_VOL_LABEL 78 /* volume label, but can't set on hard disk */ +#define IZ_EF_TRUNC 79 /* local extra field truncated (PKZIP'd) */ + +/* return codes of password fetches (negative = user abort; positive = error) */ +#define IZ_PW_ENTERED 0 /* got some password string; use/try it */ +#define IZ_PW_CANCEL -1 /* no password available (for this entry) */ +#define IZ_PW_CANCELALL -2 /* no password, skip any further pwd. request */ +#define IZ_PW_ERROR 5 /* = PK_MEM2 : failure (no mem, no tty, ...) */ + +/* flag values for status callback function */ +#define UZ_ST_START_EXTRACT 1 +#define UZ_ST_IN_PROGRESS 2 +#define UZ_ST_FINISH_MEMBER 3 + +/* return values of status callback function */ +#define UZ_ST_CONTINUE 0 +#define UZ_ST_BREAK 1 + + +/*--------------------------------------------------------------------------- + Prototypes for public UnZip API (DLL) functions. + ---------------------------------------------------------------------------*/ + +#define UzpMatch match + +int UZ_EXP UzpMain OF((int argc, char **argv)); +int UZ_EXP UzpAltMain OF((int argc, char **argv, UzpInit *init)); +UzpVer * UZ_EXP UzpVersion OF((void)); +void UZ_EXP UzpFreeMemBuffer OF((UzpBuffer *retstr)); +#ifndef WINDLL +int UZ_EXP UzpUnzipToMemory OF((char *zip, char *file, UzpOpts *optflgs, + UzpCB *UsrFunc, UzpBuffer *retstr)); +#endif +#ifndef WINDLL + int UZ_EXP UzpGrep OF((char *archive, char *file, + char *pattern, int cmd, int SkipBin, + UzpCB *UsrFunc)); +#endif +#ifdef OS2 +int UZ_EXP UzpFileTree OF((char *name, cbList(callBack), + char *cpInclude[], char *cpExclude[])); +#endif + +void UZ_EXP UzpVersion2 OF((UzpVer2 *version)); +int UZ_EXP UzpValidate OF((char *archive, int AllCodes)); + + +/* default I/O functions (can be swapped out via UzpAltMain() entry point): */ + +int UZ_EXP UzpMessagePrnt OF((zvoid *pG, uch *buf, ulg size, int flag)); +int UZ_EXP UzpMessageNull OF((zvoid *pG, uch *buf, ulg size, int flag)); +int UZ_EXP UzpInput OF((zvoid *pG, uch *buf, int *size, int flag)); +void UZ_EXP UzpMorePause OF((zvoid *pG, ZCONST char *prompt, int flag)); +int UZ_EXP UzpPassword OF((zvoid *pG, int *rcnt, char *pwbuf, + int size, ZCONST char *zfn, + ZCONST char *efn)); + + +/*--------------------------------------------------------------------------- + Remaining private stuff for UnZip compilation. + ---------------------------------------------------------------------------*/ + +#ifdef UNZIP_INTERNAL +# include "unzpriv.h" +#endif + +int pipeit(char *format, ...); +int pipeit2(char *format, int flag, ...); +int confirm(char *format, ...); + +#endif /* !__unzip_h */ diff --git a/utils/Install/inczip/unzpriv.h b/utils/Install/inczip/unzpriv.h new file mode 100644 index 0000000000..e4108c5281 --- /dev/null +++ b/utils/Install/inczip/unzpriv.h @@ -0,0 +1,2384 @@ +/*--------------------------------------------------------------------------- + + unzpriv.h + + This header file contains private (internal) macros, typedefs, prototypes + and global-variable declarations used by all of the UnZip source files. + In a prior life it was part of the main unzip.h header, but now it is only + included by that header if UNZIP_INTERNAL is defined. + + ---------------------------------------------------------------------------*/ + + + +#ifndef __unzpriv_h /* prevent multiple inclusions */ +#define __unzpriv_h + +/* First thing: Signal all following code that we compile UnZip utilities! */ +#ifndef UNZIP +# define UNZIP +#endif + +/* GRR 960204: MORE defined here in preparation for removal altogether */ +#ifndef MORE +# define MORE +#endif + +/* fUnZip should never need to be reentrant */ +#ifdef FUNZIP +# ifdef REENTRANT +# undef REENTRANT +# endif +# ifdef DLL +# undef DLL +# endif +#endif + +#if (defined(DLL) && !defined(REENTRANT)) +# define REENTRANT +#endif + +#if (!defined(DYNAMIC_CRC_TABLE) && !defined(FUNZIP)) +# define DYNAMIC_CRC_TABLE +#endif + +#if (defined(DYNAMIC_CRC_TABLE) && !defined(REENTRANT)) +# ifndef DYNALLOC_CRCTAB +# define DYNALLOC_CRCTAB +# endif +#endif + +/*--------------------------------------------------------------------------- + OS-dependent configuration for UnZip internals + ---------------------------------------------------------------------------*/ + +/* bad or (occasionally?) missing stddef.h: */ +#if (defined(M_XENIX) || defined(DNIX)) +# define NO_STDDEF_H +#endif + +#if (defined(M_XENIX) && !defined(M_UNIX)) /* SCO Xenix only, not SCO Unix */ +# define SCO_XENIX +# define NO_LIMITS_H /* no limits.h, but MODERN defined */ +# define NO_UID_GID /* no uid_t/gid_t */ +# define size_t int +#endif + +#ifdef realix /* Modcomp Real/IX, real-time SysV.3 variant */ +# define SYSV +# define NO_UID_GID /* no uid_t/gid_t */ +#endif + +#if (defined(_AIX) && !defined(_ALL_SOURCE)) +# define _ALL_SOURCE +#endif + +#if defined(apollo) /* defines __STDC__ */ +# define NO_STDLIB_H +#endif + +#ifdef DNIX +# define SYSV +# define SHORT_NAMES /* 14-char limitation on path components */ +/* # define FILENAME_MAX 14 */ +# define FILENAME_MAX NAME_MAX /* GRR: experiment */ +#endif + +#if (defined(SYSTEM_FIVE) || defined(__SYSTEM_FIVE)) +# ifndef SYSV +# define SYSV +# endif +#endif /* SYSTEM_FIVE || __SYSTEM_FIVE */ +#if (defined(M_SYSV) || defined(M_SYS5)) +# ifndef SYSV +# define SYSV +# endif +#endif /* M_SYSV || M_SYS5 */ +/* __SVR4 and __svr4__ catch Solaris on at least some combos of compiler+OS */ +#if (defined(__SVR4) || defined(__svr4__) || defined(sgi) || defined(__hpux)) +# ifndef SYSV +# define SYSV +# endif +#endif /* __SVR4 || __svr4__ || sgi || __hpux */ +#if (defined(LINUX) || defined(__QNX__)) +# ifndef SYSV +# define SYSV +# endif +#endif /* LINUX || __QNX__ */ + +#if (defined(ultrix) || defined(__ultrix) || defined(bsd4_2)) +# if (!defined(BSD) && !defined(SYSV)) +# define BSD +# endif +#endif /* ultrix || __ultrix || bsd4_2 */ +#if (defined(sun) || defined(pyr) || defined(CONVEX)) +# if (!defined(BSD) && !defined(SYSV)) +# define BSD +# endif +#endif /* sun || pyr || CONVEX */ + +#ifdef pyr /* Pyramid: has BSD and AT&T "universes" */ +# ifdef BSD +# define pyr_bsd +# define USE_STRINGS_H /* instead of more common string.h */ +# define ZMEM /* ZMEM now uses bcopy/bzero: not in AT&T universe */ +# endif /* (AT&T memcpy claimed to be very slow, though) */ +# define DECLARE_ERRNO +#endif /* pyr */ + +/* stat() bug for Borland, VAX C (also GNU?), and Atari ST MiNT on TOS + * filesystems: returns 0 for wildcards! (returns 0xffffffff on Minix + * filesystem or `U:' drive under Atari MiNT.) Watcom C was previously + * included on this list; it would be good to know what version the problem + * was fixed at, if it did exist. Watcom 10.6 has a separate stat() problem: + * it fails on "." when the current directory is a root. This is covered by + * giving it a separate definition of SSTAT in OS-specific header files. */ +#if (defined(__TURBOC__) || defined(VMS) || defined(__MINT__)) +# define WILD_STAT_BUG +#endif + +#ifdef WILD_STAT_BUG +# define SSTAT(path,pbuf) (iswild(path) || stat(path,pbuf)) +#else +# define SSTAT stat +#endif + +#ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */ +# define stat(p,s) zstat((p),(s)) +#endif + +#define STRNICMP zstrnicmp + +/*--------------------------------------------------------------------------- + OS-dependent includes + ---------------------------------------------------------------------------*/ + +#ifdef EFT +# define LONGINT off_t /* Amdahl UTS nonsense ("extended file types") */ +#else +# define LONGINT long +#endif + +#ifdef MODERN +# ifndef NO_STDDEF_H +# include +# endif +# ifndef NO_STDLIB_H +# include /* standard library prototypes, malloc(), etc. */ +# endif + typedef size_t extent; +#else /* !MODERN */ +# ifndef AOS_VS /* mostly modern? */ + LONGINT lseek(); +# ifdef VAXC /* not fully modern, but does have stdlib.h and void */ +# include +# else + char *malloc(); +# endif /* ?VAXC */ +# endif /* !AOS_VS */ + typedef unsigned int extent; +#endif /* ?MODERN */ + + +#ifndef MINIX /* Minix needs it after all the other includes (?) */ +# include +#endif +#include /* skip for VMS, to use tolower() function? */ +#include /* used in mapname() */ +#ifdef USE_STRINGS_H +# include /* strcpy, strcmp, memcpy, index/rindex, etc. */ +#else +# include /* strcpy, strcmp, memcpy, strchr/strrchr, etc. */ +#endif +#if (defined(MODERN) && !defined(NO_LIMITS_H)) +# include /* GRR: EXPERIMENTAL! (can be deleted) */ +#endif + +/* this include must be down here for SysV.4, for some reason... */ +#include /* used in unzip.c, fileio.c */ + + +/*--------------------------------------------------------------------------- + API (DLL) section: + ---------------------------------------------------------------------------*/ + +#ifdef DLL +# define MAIN UZ_EXP UzpMain /* was UzpUnzip */ +# ifdef OS2DLL +# undef Info +# define REDIRECTC(c) varputchar(__G__ c) +# define REDIRECTPRINT(buf,size) varmessage(__G__ buf, size) +# define FINISH_REDIRECT() finish_REXX_redirect(__G) +# else +# define REDIRECTC(c) +# define REDIRECTPRINT(buf,size) 0 +# define FINISH_REDIRECT() close_redirect(__G) +# endif +#endif + +/*--------------------------------------------------------------------------- + Acorn RISCOS section: + ---------------------------------------------------------------------------*/ + +#ifdef RISCOS +# include "acorn/riscos.h" +#endif + +/*--------------------------------------------------------------------------- + Amiga section: + ---------------------------------------------------------------------------*/ + +#ifdef AMIGA +# include "amiga/amiga.h" +#endif + +/*--------------------------------------------------------------------------- + AOS/VS section (somewhat similar to Unix, apparently): + ---------------------------------------------------------------------------*/ + +#ifdef AOS_VS +# ifdef FILEIO_C +# include "aosvs/aosvs.h" +# endif +#endif + +/*--------------------------------------------------------------------------- + Atari ST section: + ---------------------------------------------------------------------------*/ + +#ifdef ATARI +# include +# include +# include +# include +# define SYMLINKS +# define EXE_EXTENSION ".tos" +# ifndef DATE_FORMAT +# define DATE_FORMAT DF_DMY +# endif +# define DIR_END '/' +# define INT_SPRINTF +# define timezone _timezone +# define lenEOL 2 +# define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);} +# undef SHORT_NAMES +# if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) +# define TIMESTAMP +# endif +#endif + +/*--------------------------------------------------------------------------- + BeOS section: + ---------------------------------------------------------------------------*/ + +#ifdef __BEOS__ +# 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 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 SCREENLINES screenlines() +# define USE_EF_UT_TIME +# define SET_DIR_ATTRIB +# if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) +# define TIMESTAMP +# endif +# define RESTORE_UIDGID +# define NO_GMTIME /* maybe DR10 will have timezones... */ +# define INT_SPRINTF +# define SYMLINKS +# define MAIN main_stub /* now that we're using a wrapper... */ +#endif + +/*--------------------------------------------------------------------------- + Human68k/X68000 section: + ---------------------------------------------------------------------------*/ + +#ifdef __human68k__ /* DO NOT DEFINE DOS_OS2 HERE! If Human68k is so much */ +# include /* like MS-DOS and/or OS/2, create DOS_H68_OS2 macro. */ +# include +# include +# include +# include +# include +# ifndef DATE_FORMAT +# define DATE_FORMAT DF_YMD /* Japanese standard */ +# endif + /* GRR: these EOL macros are guesses */ +# define lenEOL 2 +# define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);} +# define EXE_EXTENSION ".exe" /* just a guess... */ +#endif + +/*--------------------------------------------------------------------------- + Mac section: + ---------------------------------------------------------------------------*/ + +#ifdef MACOS +# include "maccfg.h" +#endif /* MACOS */ + +/*--------------------------------------------------------------------------- + MS-DOS, OS/2, FLEXOS section: + ---------------------------------------------------------------------------*/ + +#ifdef WINDLL +# define MSWIN +# ifdef MORE +# undef MORE +# endif +# ifdef OS2_EAS +# undef OS2_EAS +# endif +#endif + +#if (defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__))) +# ifndef MSC +# define MSC /* This should work for older MSC, too! */ +# endif +#endif + +#if (defined(MSDOS) || defined(OS2) || defined(FLEXOS)) +# include /* off_t, time_t, dev_t, ... */ +# include +# include /* lseek(), open(), setftime(), dup(), creat() */ +# include /* localtime() */ +# include /* O_BINARY for open() w/o CR/LF translation */ + +# ifdef OS2 /* defined for all OS/2 compilers */ +# include "os2/os2cfg.h" +# else +# ifdef FLEXOS +# include "flexos/flxcfg.h" +# else +# include "msdos/doscfg.h" +# endif +# endif + +# if (defined(_MSC_VER) && (_MSC_VER == 700) && !defined(GRR)) + /* + * ARGH. MSC 7.0 libraries think times are based on 1899 Dec 31 00:00, not + * 1970 Jan 1 00:00. So we have to diddle time_t's appropriately: add or + * subtract 70 years' worth of seconds; i.e., number of days times 86400; + * i.e., (70*365 regular days + 17 leap days + 1 1899 day) * 86400 == + * (25550 + 17 + 1) * 86400 == 2209075200 seconds. We know time_t is an + * unsigned long (ulg) on the only system with this bug. + */ +# define TIMET_TO_NATIVE(x) (x) += (ulg)2209075200L; +# define NATIVE_TO_TIMET(x) (x) -= (ulg)2209075200L; +# endif +# if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0450)) +# define timezone _timezone +# endif +# if (defined(__GO32__) || defined(FLEXOS)) +# define DIR_END '/' +# else +# define DIR_END '\\' /* OS uses '\\' as directory separator */ +# define DIR_END2 '/' /* also check for '/' (RTL may convert) */ +# endif +# ifndef WIN32 +# ifdef DATE_FORMAT +# undef DATE_FORMAT +# endif +# define DATE_FORMAT dateformat() +# endif +# define lenEOL 2 +# define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);} +# define USE_EF_UT_TIME +#endif /* MSDOS || OS2 || FLEXOS */ + +/*--------------------------------------------------------------------------- + MTS section (piggybacks UNIX, I think): + ---------------------------------------------------------------------------*/ + +#ifdef MTS +# include /* off_t, time_t, dev_t, ... */ +# include +# include /* MTS uses this instead of fcntl.h */ +# include +# include +# include /* some important non-ANSI routines */ +# define mkdir(s,n) (-1) /* no "make directory" capability */ +# define EBCDIC /* set EBCDIC conversion on */ +# define NO_STRNICMP /* unzip's is as good the one in MTS */ +# define USE_FWRITE +# define close_outfile() fclose(G.outfile) /* can't set time on files */ +# define umask(n) /* don't have umask() on MTS */ +# define FOPWT "w" /* open file for writing in TEXT mode */ +# ifndef DATE_FORMAT +# define DATE_FORMAT DF_MDY +# endif +# define lenEOL 1 +# define PutNativeEOL *q++ = native(LF); +#endif /* MTS */ + + /*--------------------------------------------------------------------------- + QDOS section + ---------------------------------------------------------------------------*/ + +#ifdef QDOS +# define DIRENT +# include +# include +# include +# include +# include "qdos/izqdos.h" +# ifndef DATE_FORMAT +# define DATE_FORMAT DF_MDY +# endif +# define lenEOL 1 +# define PutNativeEOL *q++ = native(LF); +# define DIR_END '_' +# define RETURN QReturn +# undef PATH_MAX +# define PATH_MAX 36 +# if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) +# define TIMESTAMP +# endif +#endif + +/*--------------------------------------------------------------------------- + Tandem NSK section: + ---------------------------------------------------------------------------*/ + +#ifdef TANDEM +# include "tandem.h" +# include + /* use a single LF delimiter so that writes to 101 text files work */ +# define PutNativeEOL *q++ = native(LF); +# define lenEOL 1 +# ifndef DATE_FORMAT +# define DATE_FORMAT DF_DMY +# endif +# define USE_EF_UT_TIME +# define RESTORE_UIDGID +#endif + +/*--------------------------------------------------------------------------- + TOPS-20 section: + ---------------------------------------------------------------------------*/ + +#ifdef TOPS20 +# include /* off_t, time_t, dev_t, ... */ +# include +# include +# include +# include +# include +# include +# include /* get amazing monsym() macro */ + extern int open(), close(), read(); + extern int stat(), unlink(), jsys(), fcntl(); + extern long lseek(), dup(), creat(); +# define strchr index /* GRR: necessary? */ +# define strrchr rindex +# define REALLY_SHORT_SYMS +# define NO_MKDIR +# define DIR_BEG '<' +# define DIR_END '>' +# define DIR_EXT ".directory" +# ifndef DATE_FORMAT +# define DATE_FORMAT DF_MDY +# endif +# define EXE_EXTENSION ".exe" /* just a guess... */ +#endif /* TOPS20 */ + +/*--------------------------------------------------------------------------- + Unix section: + ---------------------------------------------------------------------------*/ + +#ifdef UNIX +# include /* off_t, time_t, dev_t, ... */ +# include + +# ifndef COHERENT +# include /* O_BINARY for open() w/o CR/LF translation */ +# else /* COHERENT */ +# ifdef _I386 +# include /* Coherent 4.0.x, Mark Williams C */ +# else +# include /* Coherent 3.10, Mark Williams C */ +# endif +# define SHORT_SYMS +# ifndef __COHERENT__ /* Coherent 4.2 has tzset() */ +# define tzset settz +# endif +# endif /* ?COHERENT */ + +# ifndef NO_PARAM_H +# ifdef NGROUPS_MAX +# undef NGROUPS_MAX /* SCO bug: defined again in */ +# endif +# ifdef BSD +# define TEMP_BSD /* may be defined again in */ +# undef BSD +# endif +# include /* conflict with , some systems? */ +# ifdef TEMP_BSD +# undef TEMP_BSD +# ifndef BSD +# define BSD +# endif +# endif +# endif /* !NO_PARAM_H */ + +# ifdef __osf__ +# define DIRENT +# ifdef BSD +# undef BSD +# endif +# endif /* __osf__ */ + +# ifdef BSD +# include +# include +# ifdef _AIX +# include +# endif +# else +# include + struct tm *gmtime(), *localtime(); +# endif + +# if (defined(BSD4_4) || (defined(SYSV) && defined(MODERN))) +# include /* this includes utime.h on SGIs */ +# if (defined(BSD4_4) || defined(linux)) +# include +# define GOT_UTIMBUF +# endif +# endif + +# if (defined(V7) || defined(pyr_bsd)) +# define strchr index +# define strrchr rindex +# endif +# ifdef V7 +# define O_RDONLY 0 +# define O_WRONLY 1 +# define O_RDWR 2 +# endif + +# ifdef MINIX +# include +# endif +# ifndef DATE_FORMAT +# define DATE_FORMAT DF_MDY /* GRR: customize with locale.h somehow? */ +# endif +# define lenEOL 1 +# ifdef EBCDIC +# define PutNativeEOL *q++ = '\n'; +# else +# define PutNativeEOL *q++ = native(LF); +# endif +# define SCREENLINES screenlines() +# define USE_EF_UT_TIME +# define SET_DIR_ATTRIB +# if (!defined(TIMESTAMP) && !defined(NOTIMESTAMP)) /* GRR 970513 */ +# define TIMESTAMP +# endif +# define RESTORE_UIDGID +#endif /* UNIX */ + +/*--------------------------------------------------------------------------- + VM/CMS and MVS section: + ---------------------------------------------------------------------------*/ + +#ifdef CMS_MVS +# include "vmmvs.h" +# define CLOSE_INFILE() close_infile(__G) +#endif + +/*--------------------------------------------------------------------------- + VMS section: + ---------------------------------------------------------------------------*/ + +#ifdef VMS +# include /* GRR: experimenting... */ +# include +# include /* the usual non-BSD time functions */ +# include /* same things as fcntl.h has */ +# include +# include +# define _MAX_PATH (NAM$C_MAXRSS+1) /* to define FILNAMSIZ below */ +# ifdef RETURN_CODES /* VMS interprets standard PK return codes incorrectly */ +# define RETURN(ret) return_VMS(__G__ (ret)) /* verbose version */ +# define EXIT(ret) return_VMS(__G__ (ret)) +# else +# define RETURN return_VMS /* quiet version */ +# define EXIT return_VMS +# endif +# ifdef VMSCLI +# define USAGE(ret) VMSCLI_usage(__G__ (ret)) +# endif +# define DIR_BEG '[' +# define DIR_END ']' +# define DIR_EXT ".dir" +# ifndef DATE_FORMAT +# define DATE_FORMAT DF_MDY +# endif +# define lenEOL 1 +# define PutNativeEOL *q++ = native(LF); +# define SCREENLINES screenlines() +# if (defined(__VMS_VERSION) && !defined(VMS_VERSION)) +# define VMS_VERSION __VMS_VERSION +# endif +# if (defined(__VMS_VER) && !defined(__CRTL_VER)) +# define __CRTL_VER __VMS_VER +# endif +# if ((!defined(__CRTL_VER)) || (__CRTL_VER < 70000000)) +# define NO_GMTIME /* gmtime() of earlier VMS C RTLs is broken */ +# else +# if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)) +# define USE_EF_UT_TIME +# endif +# endif +# if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) +# define TIMESTAMP +# endif +# define RESTORE_UIDGID +#endif /* VMS */ + +/*--------------------------------------------------------------------------- + Win32 (Windows 95/NT) section: + ---------------------------------------------------------------------------*/ + +#if (defined(WIN32) && !defined(POCKET_UNZIP)) +# include "w32cfg.h" +#endif + + + + + +/*************/ +/* Defines */ +/*************/ + +#define UNZIP_VERSION 20 /* compatible with PKUNZIP 2.0 */ +#define VMS_UNZIP_VERSION 42 /* if OS-needed-to-extract is VMS: can do */ + +#if (defined(MSDOS) || defined(OS2)) +# define DOS_OS2 +#endif + +#if (defined(OS2) || defined(WIN32)) +# define OS2_W32 +#endif + +#if (defined(DOS_OS2) || defined(WIN32)) +# define DOS_OS2_W32 +# define DOS_W32_OS2 /* historical: don't use */ +#endif + +#if (defined(DOS_OS2_W32) || defined(__human68k__)) +# define DOS_H68_OS2_W32 +#endif + +#if (defined(DOS_OS2) || defined(FLEXOS)) +# define DOS_FLX_OS2 +#endif + +#if (defined(DOS_OS2_W32) || defined(FLEXOS)) +# define DOS_FLX_OS2_W32 +#endif + +#if (defined(DOS_H68_OS2_W32) || defined(FLEXOS)) +# define DOS_FLX_H68_OS2_W32 +#endif + +#if (defined(TOPS20) || defined(VMS)) +# define T20_VMS +#endif + +#if (defined(MSDOS) || defined(T20_VMS)) +# define DOS_T20_VMS +#endif + +/* clean up with a few defaults */ +#ifndef DIR_END +# define DIR_END '/' /* last char before program name or filename */ +#endif +#ifndef DATE_FORMAT +# define DATE_FORMAT DF_MDY /* defaults to US convention */ +#endif +#ifndef CLOSE_INFILE +# define CLOSE_INFILE() close(G.zipfd) +#endif +#ifndef RETURN +# define RETURN return /* only used in main() */ +#endif +#ifndef EXIT +# define EXIT exit +#endif +#ifndef USAGE +# define USAGE(ret) usage(__G__ (ret)) /* used in unzip.c, zipinfo.c */ +#endif +#ifndef TIMET_TO_NATIVE /* everybody but MSC 7.0 and Macintosh */ +# define TIMET_TO_NATIVE(x) +# define NATIVE_TO_TIMET(x) +#endif + +#if (defined(DOS_FLX_OS2_W32) || defined(UNIX) || defined(RISCOS)) +# ifndef HAVE_UNLINK +# define HAVE_UNLINK +# endif +#endif +#if (defined(AOS_VS) || defined(ATARI) || defined(__BEOS__)) /* GRR: others? */ +# ifndef HAVE_UNLINK +# define HAVE_UNLINK +# endif +#endif + +/* OS-specific exceptions to the "ANSI <--> INT_SPRINTF" rule */ + +#if (!defined(PCHAR_SPRINTF) && !defined(INT_SPRINTF)) +# if (defined(SYSV) || defined(CONVEX) || defined(NeXT) || defined(BSD4_4)) +# define INT_SPRINTF /* sprintf() returns int: SysVish/Posix */ +# endif +# if (defined(DOS_FLX_OS2_W32) || defined(VMS) || defined(AMIGA)) +# define INT_SPRINTF /* sprintf() returns int: ANSI */ +# endif +# if (defined(ultrix) || defined(__ultrix)) /* Ultrix 4.3 and newer */ +# if (defined(POSIX) || defined(__POSIX)) +# define INT_SPRINTF /* sprintf() returns int: ANSI/Posix */ +# endif +# ifdef __GNUC__ +# define PCHAR_SPRINTF /* undetermined actual return value */ +# endif +# endif +# if (defined(__osf__) || defined(_AIX) || defined(CMS_MVS)) +# define INT_SPRINTF /* sprintf() returns int: ANSI/Posix */ +# endif +# if defined(sun) +# define PCHAR_SPRINTF /* sprintf() returns char *: SunOS cc *and* gcc */ +# endif +#endif + +/* defaults that we hope will take care of most machines in the future */ + +#if (!defined(PCHAR_SPRINTF) && !defined(INT_SPRINTF)) +# ifdef __STDC__ +# define INT_SPRINTF /* sprintf() returns int: ANSI */ +# endif +# ifndef INT_SPRINTF +# define PCHAR_SPRINTF /* sprintf() returns char *: BSDish */ +# endif +#endif + +#define MSG_STDERR(f) (f & 1) /* bit 0: 0 = stdout, 1 = stderr */ +#define MSG_INFO(f) ((f & 6) == 0) /* bits 1 and 2: 0 = info */ +#define MSG_WARN(f) ((f & 6) == 2) /* bits 1 and 2: 1 = warning */ +#define MSG_ERROR(f) ((f & 6) == 4) /* bits 1 and 2: 2 = error */ +#define MSG_FATAL(f) ((f & 6) == 6) /* bits 1 and 2: (3 = fatal error) */ +#define MSG_ZFN(f) (f & 0x0008) /* bit 3: 1 = print zipfile name */ +#define MSG_FN(f) (f & 0x0010) /* bit 4: 1 = print filename */ +#define MSG_LNEWLN(f) (f & 0x0020) /* bit 5: 1 = leading newline if !SOL */ +#define MSG_TNEWLN(f) (f & 0x0040) /* bit 6: 1 = trailing newline if !SOL */ +#define MSG_MNEWLN(f) (f & 0x0080) /* bit 7: 1 = trailing NL for prompts */ +/* the following are subject to change */ +#define MSG_NO_WGUI(f) (f & 0x0100) /* bit 8: 1 = skip if Windows GUI */ +#define MSG_NO_AGUI(f) (f & 0x0200) /* bit 9: 1 = skip if Acorn GUI */ +#define MSG_NO_DLL2(f) (f & 0x0400) /* bit 10: 1 = skip if OS/2 DLL */ +#define MSG_NO_NDLL(f) (f & 0x0800) /* bit 11: 1 = skip if WIN32 DLL */ +#define MSG_NO_WDLL(f) (f & 0x1000) /* bit 12: 1 = skip if Windows DLL */ + +#if (defined(MORE) && !defined(SCREENLINES)) +# ifdef DOS_FLX_OS2_W32 +# define SCREENLINES 25 /* can be (should be) a function instead */ +# else +# define SCREENLINES 24 /* VT-100s are assumed to be minimal hardware */ +# endif +#endif + +#define DIR_BLKSIZ 64 /* number of directory entries per block + * (should fit in 4096 bytes, usually) */ +#ifndef WSIZE +# define WSIZE 0x8000 /* window size--must be a power of two, and */ +#endif /* at least 32K for zip's deflate method */ + +#ifndef INBUFSIZ +# if (defined(MED_MEM) || defined(SMALL_MEM)) +# define INBUFSIZ 2048 /* works for MS-DOS small model */ +# else +# define INBUFSIZ 8192 /* larger buffers for real OSes */ +# endif +#endif + +#ifndef __16BIT__ +# define nearmalloc malloc +# define nearfree free +# if (!defined(__IBMC__) || !defined(OS2)) +# ifndef near +# define near +# endif +# ifndef far +# define far +# endif +# endif +#endif + +#if (defined(DYNALLOC_CRCTAB) && !defined(DYNAMIC_CRC_TABLE)) +# undef DYNALLOC_CRCTAB +#endif + +#if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT)) +# undef DYNALLOC_CRCTAB /* not safe with reentrant code */ +#endif + +#if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB)) +# ifdef DYNALLOC_CRCTAB +# undef DYNALLOC_CRCTAB +# endif +#endif + +#if (defined(USE_ZLIB) && defined(ASM_CRC)) +# undef ASM_CRC +#endif + +/* Logic for case of small memory, length of EOL > 1: if OUTBUFSIZ == 2048, + * OUTBUFSIZ>>1 == 1024 and OUTBUFSIZ>>7 == 16; therefore rawbuf is 1008 bytes + * and transbuf 1040 bytes. Have room for 32 extra EOL chars; 1008/32 == 31.5 + * chars/line, smaller than estimated 35-70 characters per line for C source + * and normal text. Hence difference is sufficient for most "average" files. + * (Argument scales for larger OUTBUFSIZ.) + */ +#ifdef SMALL_MEM /* i.e., 16-bit OSes: MS-DOS, OS/2 1.x, etc. */ +# define LoadFarString(x) fLoadFarString(__G__ (x)) +# define LoadFarStringSmall(x) fLoadFarStringSmall(__G__ (x)) +# define LoadFarStringSmall2(x) fLoadFarStringSmall2(__G__ (x)) +# if (defined(_MSC_VER) && (_MSC_VER >= 600)) +# define zfstrcpy(dest, src) _fstrcpy((dest), (src)) +# endif +# ifndef Far +# define Far far /* __far only works for MSC 6.00, not 6.0a or Borland */ +# endif +# define OUTBUFSIZ INBUFSIZ +# if (lenEOL == 1) +# define RAWBUFSIZ (OUTBUFSIZ>>1) +# else +# define RAWBUFSIZ ((OUTBUFSIZ>>1) - (OUTBUFSIZ>>7)) +# endif +# define TRANSBUFSIZ (OUTBUFSIZ-RAWBUFSIZ) + typedef short shrint; /* short/int or "shrink int" (unshrink) */ +#else +# define zfstrcpy(dest, src) strcpy((dest), (src)) +# ifdef QDOS +# define LoadFarString(x) Qstrfix(x) /* fix up _ for '.' */ +# define LoadFarStringSmall(x) Qstrfix(x) +# define LoadFarStringSmall2(x) Qstrfix(x) +# else +# define LoadFarString(x) x +# define LoadFarStringSmall(x) x +# define LoadFarStringSmall2(x) x +# endif +# ifdef MED_MEM +# define OUTBUFSIZ 0xFF80 /* can't malloc arrays of 0xFFE8 or more */ +# define TRANSBUFSIZ 0xFF80 + typedef short shrint; +# else +# define OUTBUFSIZ (lenEOL*WSIZE) /* more efficient text conversion */ +# define TRANSBUFSIZ (lenEOL*OUTBUFSIZ) +# ifdef AMIGA + typedef short shrint; +# else + typedef int shrint; /* for efficiency/speed, we hope... */ +# endif +# endif /* ?MED_MEM */ +# define RAWBUFSIZ OUTBUFSIZ +#endif /* ?SMALL_MEM */ + +#ifndef Far +# define Far +#endif + +#ifndef MAIN +# define MAIN main +#endif + +#ifdef SFX /* disable some unused features for SFX executables */ +# ifndef NO_ZIPINFO +# define NO_ZIPINFO +# endif +# ifdef TIMESTAMP +# undef TIMESTAMP +# endif +#endif + +/* user may have defined both by accident... NOTIMESTAMP takes precedence */ +#if (defined(TIMESTAMP) && defined(NOTIMESTAMP)) +# undef TIMESTAMP +#endif + +#if (!defined(COPYRIGHT_CLEAN) && !defined(USE_SMITH_CODE)) +# define COPYRIGHT_CLEAN +#endif + +#if (!defined(LZW_CLEAN) && !defined(USE_UNSHRINK)) +# define LZW_CLEAN +#endif + +#ifndef O_BINARY +# define O_BINARY 0 +#endif + +#ifndef PIPE_ERROR +# define PIPE_ERROR (errno == EPIPE) +#endif + +/* File operations--use "b" for binary if allowed or fixed length 512 on VMS */ +#ifdef VMS +# define FOPR "r","ctx=stm" +# define FOPM "r+","ctx=stm","rfm=fix","mrs=512" +# define FOPW "w","ctx=stm","rfm=fix","mrs=512" +#endif /* VMS */ + +#ifdef CMS_MVS +/* Binary files must be RECFM=F,LRECL=1 for ftell() to get correct pos */ +/* ...unless byteseek is used. Let's try that for a while. */ +# define FOPR "rb,byteseek" +# define FOPM "r+b,byteseek" +# define FOPW "wb,recfm=v,lrecl=32760" +# ifdef MVS +# define FOPWT "w,lrecl=133" +# else +# define FOPWT "w" +# endif +#endif /* CMS_MVS */ + +#ifdef TOPS20 /* TOPS-20 MODERN? You kidding? */ +# define FOPW "w8" +#endif /* TOPS20 */ + +/* Defaults when nothing special has been defined previously. */ +#ifdef MODERN +# ifndef FOPR +# define FOPR "rb" +# endif +# ifndef FOPM +# define FOPM "r+b" +# endif +# ifndef FOPW +# define FOPW "wb" +# endif +# ifndef FOPWT +# define FOPWT "wt" +# endif +#else /* !MODERN */ +# ifndef FOPR +# define FOPR "r" +# endif +# ifndef FOPM +# define FOPM "r+" +# endif +# ifndef FOPW +# define FOPW "w" +# endif +# ifndef FOPWT +# define FOPWT "w" +# endif +#endif /* ?MODERN */ + +/* + * If exists on most systems, should include that, since it may + * define some or all of the following: NAME_MAX, PATH_MAX, _POSIX_NAME_MAX, + * _POSIX_PATH_MAX. + */ +#ifdef DOS_FLX_OS2 +# include +#endif + +#ifndef PATH_MAX +# ifdef MAXPATHLEN +# define PATH_MAX MAXPATHLEN /* in on some systems */ +# else +# ifdef _MAX_PATH +# define PATH_MAX _MAX_PATH +# else +# if FILENAME_MAX > 255 +# define PATH_MAX FILENAME_MAX /* used like PATH_MAX on some systems */ +# else +# define PATH_MAX 1024 +# endif +# endif /* ?_MAX_PATH */ +# endif /* ?MAXPATHLEN */ +#endif /* !PATH_MAX */ + +#define FILNAMSIZ PATH_MAX + +#ifdef SHORT_SYMS /* Mark Williams C, ...? */ +# define extract_or_test_files xtr_or_tst_files +# define extract_or_test_member xtr_or_tst_member +#endif + +#ifdef REALLY_SHORT_SYMS /* TOPS-20 linker: first 6 chars */ +# define process_cdir_file_hdr XXpcdfh +# define process_local_file_hdr XXplfh +# define extract_or_test_files XXxotf /* necessary? */ +# define extract_or_test_member XXxotm /* necessary? */ +# define check_for_newer XXcfn +# define overwrite_all XXoa +# define process_all_files XXpaf +# define extra_field XXef +# define explode_lit8 XXel8 +# define explode_lit4 XXel4 +# define explode_nolit8 XXnl8 +# define explode_nolit4 XXnl4 +# define cpdist8 XXcpdist8 +# define inflate_codes XXic +# define inflate_stored XXis +# define inflate_fixed XXif +# define inflate_dynamic XXid +# define inflate_block XXib +# define maxcodemax XXmax +#endif + +#ifndef S_TIME_T_MAX /* max value of signed (>= 32-bit) time_t */ +# define S_TIME_T_MAX ((time_t)(ulg)0x7fffffffL) +#endif +#ifndef U_TIME_T_MAX /* max value of unsigned (>= 32-bit) time_t */ +# define U_TIME_T_MAX ((time_t)(ulg)0xffffffffL) +#endif +#ifdef DOSTIME_MINIMUM /* min DOSTIME value (1980-01-01) */ +# undef DOSTIME_MINIMUM +#endif +#define DOSTIME_MINIMUM ((ulg)0x00210000L) +#ifdef DOSTIME_2038_01_18 /* approximate DOSTIME equivalent of */ +# undef DOSTIME_2038_01_18 /* the signed-32-bit time_t limit */ +#endif +#define DOSTIME_2038_01_18 ((ulg)0x74320000L) + +#ifdef QDOS +# define ZSUFX "_zip" +# define ALT_ZSUFX ".zip" +#else +# ifdef RISCOS +# define ZSUFX "/zip" +# else +# define ZSUFX ".zip" +# endif +# define ALT_ZSUFX ".ZIP" /* Unix-only so far (only case-sensitive fs) */ +#endif + +#define CENTRAL_HDR_SIG "\001\002" /* the infamous "PK" signature bytes, */ +#define LOCAL_HDR_SIG "\003\004" /* sans "PK" (so unzip executable not */ +#define END_CENTRAL_SIG "\005\006" /* mistaken for zipfile itself) */ +#define EXTD_LOCAL_SIG "\007\010" /* [ASCII "\113" == EBCDIC "\080" ??] */ + +/* choice of activities for do_string() */ +#define SKIP 0 /* skip header block */ +#define DISPLAY 1 /* display archive comment (ASCII) */ +#define DISPL_8 5 /* display file comment (ext. ASCII) */ +#define DS_FN 2 /* read filename (ext. ASCII) */ +#define EXTRA_FIELD 3 /* copy extra field into buffer */ +#define DS_EF 3 +#ifdef AMIGA +# define FILENOTE 4 +#endif + +#define DOES_NOT_EXIST -1 /* return values for check_for_newer() */ +#define EXISTS_AND_OLDER 0 +#define EXISTS_AND_NEWER 1 + +#define ROOT 0 /* checkdir() extract-to path: called once */ +#define INIT 1 /* allocate buildpath: called once per member */ +#define APPEND_DIR 2 /* append a dir comp.: many times per member */ +#define APPEND_NAME 3 /* append actual filename: once per member */ +#define GETPATH 4 /* retrieve the complete path and free it */ +#define END 5 /* free root path prior to exiting program */ + +/* version_made_by codes (central dir): make sure these */ +/* are not defined on their respective systems!! */ +#define FS_FAT_ 0 /* filesystem used by MS-DOS, OS/2, Win32 */ +#define AMIGA_ 1 +#define VMS_ 2 +#define UNIX_ 3 +#define VM_CMS_ 4 +#define ATARI_ 5 /* what if it's a minix filesystem? [cjh] */ +#define FS_HPFS_ 6 /* filesystem used by OS/2 (and NT 3.x) */ +#define MAC_ 7 /* HFS filesystem used by MacOS */ +#define Z_SYSTEM_ 8 +#define CPM_ 9 +#define TOPS20_ 10 +#define FS_NTFS_ 11 /* filesystem used by Windows NT */ +#define QDOS_ 12 +#define ACORN_ 13 /* Archimedes Acorn RISC OS */ +#define FS_VFAT_ 14 /* filesystem used by Windows 95, NT */ +#define MVS_ 15 +#define BEOS_ 16 /* hybrid POSIX/database filesystem */ +#define TANDEM_ 17 /* Tandem/NSK */ +#define NUM_HOSTS 18 /* index of last system + 1 */ + +#define STORED 0 /* compression methods */ +#define SHRUNK 1 +#define REDUCED1 2 +#define REDUCED2 3 +#define REDUCED3 4 +#define REDUCED4 5 +#define IMPLODED 6 +#define TOKENIZED 7 +#define DEFLATED 8 +#define ENHDEFLATED 9 +#define DCLIMPLODED 10 +#define NUM_METHODS 11 /* index of last method + 1 */ +/* don't forget to update list_files(), extract.c and zipinfo.c appropriately + * if NUM_METHODS changes */ + +/* (the PK-class error codes are public and have been moved into unzip.h) */ + +#define DF_MDY 0 /* date format 10/26/91 (USA only) */ +#define DF_DMY 1 /* date format 26/10/91 (most of the world) */ +#define DF_YMD 2 /* date format 91/10/26 (a few countries) */ + +/*--------------------------------------------------------------------------- + Extra-field block ID values and offset info. + ---------------------------------------------------------------------------*/ +/* extra-field ID values, all little-endian: */ +#define EF_AV 0x0007 /* PKWARE's authenticity verification */ +#define EF_OS2 0x0009 /* OS/2 extended attributes */ +#define EF_PKW32 0x000a /* PKWARE's Win95/98/WinNT filetimes */ +#define EF_PKVMS 0x000c /* PKWARE's VMS */ +#define EF_PKUNIX 0x000d /* PKWARE's Unix */ +#define EF_IZVMS 0x4d49 /* Info-ZIP's VMS ("IM") */ +#define EF_IZUNIX 0x5855 /* Info-ZIP's old Unix[1] ("UX") */ +#define EF_IZUNIX2 0x7855 /* Info-ZIP's new Unix[2] ("Ux") */ +#define EF_TIME 0x5455 /* universal timestamp ("UT") */ +#define EF_MAC3 0x334d /* Info-ZIP's new Macintosh (= "M3") */ +#define EF_JLMAC 0x07c8 /* Johnny Lee's old Macintosh (= 1992) */ +#define EF_ZIPIT 0x2605 /* Thomas Brown's Macintosh (ZipIt) */ +#define EF_ZIPIT2 0x2705 /* T. Brown's Mac (ZipIt) v 1.3.8 and newer ? */ +#define EF_VMCMS 0x4704 /* Info-ZIP's VM/CMS ("\004G") */ +#define EF_MVS 0x470f /* Info-ZIP's MVS ("\017G") */ +#define EF_ACL 0x4c41 /* (OS/2) access control list ("AL") */ +#define EF_NTSD 0x4453 /* NT security descriptor ("SD") */ +#define EF_BEOS 0x6542 /* BeOS ("Be") */ +#define EF_QDOS 0xfb4a /* SMS/QDOS ("J\373") */ +#define EF_AOSVS 0x5356 /* AOS/VS ("VS") */ +#define EF_SPARK 0x4341 /* David Pilling's Acorn/SparkFS ("AC") */ +#define EF_MD5 0x4b46 /* Fred Kantor's MD5 ("FK") */ +#define EF_ASIUNIX 0x756e /* ASi's Unix ("nu") */ + +#define EB_HEADSIZE 4 /* length of extra field block header */ +#define EB_ID 0 /* offset of block ID in header */ +#define EB_LEN 2 /* offset of data length field in header */ +#define EB_UCSIZE_P 0 /* offset of ucsize field in compr. data */ +#define EB_CMPRHEADLEN 6 /* lenght of compression header */ + +#define EB_UX_MINLEN 8 /* minimal "UX" field contains atime, mtime */ +#define EB_UX_FULLSIZE 12 /* full "UX" field (atime, mtime, uid, gid) */ +#define EB_UX_ATIME 0 /* offset of atime in "UX" extra field data */ +#define EB_UX_MTIME 4 /* offset of mtime in "UX" extra field data */ +#define EB_UX_UID 8 /* byte offset of UID in "UX" field data */ +#define EB_UX_GID 10 /* byte offset of GID in "UX" field data */ + +#define EB_UX2_MINLEN 4 /* minimal "Ux" field contains UID/GID */ +#define EB_UX2_UID 0 /* byte offset of UID in "Ux" field data */ +#define EB_UX2_GID 2 /* byte offset of GID in "Ux" field data */ +#define EB_UX2_VALID (1 << 8) /* UID/GID present */ + +#define EB_UT_MINLEN 1 /* minimal UT field contains Flags byte */ +#define EB_UT_FLAGS 0 /* byte offset of Flags field */ +#define EB_UT_TIME1 1 /* byte offset of 1st time value */ +#define EB_UT_FL_MTIME (1 << 0) /* mtime present */ +#define EB_UT_FL_ATIME (1 << 1) /* atime present */ +#define EB_UT_FL_CTIME (1 << 2) /* ctime present */ + +#define EB_FLGS_OFFS 4 /* offset of flags area in generic compressed + extra field blocks (OS2, NT, and others) */ +#define EB_OS2_HLEN 4 /* size of OS2/ACL compressed data header */ +#define EB_BEOS_HLEN 5 /* length of BeOS e.f attribute header */ +#define EB_BE_FL_UNCMPR 0x01 /* "BeOS attributes uncompressed" bit flag */ +#define EB_MAC3_HLEN 14 /* length of Mac3 attribute block header */ +#define EB_M3_FL_DATFRK 0x01 /* "this entry is data fork" flag */ +#define EB_M3_FL_UNCMPR 0x04 /* "Mac3 attributes uncompressed" bit flag */ +#define EB_M3_FL_TIME64 0x08 /* "Mac3 time fields are 64 bit wide" flag */ +#define EB_M3_FL_NOUTC 0x10 /* "Mac3 timezone offset fields missing" flag */ + +#define EB_NTSD_C_LEN 4 /* length of central NT security data */ +#define EB_NTSD_L_LEN 5 /* length of minimal local NT security data */ +#define EB_NTSD_VERSION 4 /* offset of NTSD version byte */ +#define EB_NTSD_MAX_VER (0) /* maximum version # we know how to handle */ + +#define EB_ASI_CRC32 0 /* offset of ASI Unix field's crc32 checksum */ +#define EB_ASI_MODE 4 /* offset of ASI Unix permission mode field */ + +/*--------------------------------------------------------------------------- + True sizes of the various headers, as defined by PKWARE--so it is not + likely that these will ever change. But if they do, make sure both these + defines AND the typedefs below get updated accordingly. + ---------------------------------------------------------------------------*/ +#define LREC_SIZE 26 /* lengths of local file headers, central */ +#define CREC_SIZE 42 /* directory headers, and the end-of- */ +#define ECREC_SIZE 18 /* central-dir record, respectively */ + +#define MAX_BITS 13 /* used in unshrink() */ +#define HSIZE (1 << MAX_BITS) /* size of global work area */ + +#define LF 10 /* '\n' on ASCII machines; must be 10 due to EBCDIC */ +#define CR 13 /* '\r' on ASCII machines; must be 13 due to EBCDIC */ +#define CTRLZ 26 /* DOS & OS/2 EOF marker (used in fileio.c, vms.c) */ + +#ifdef EBCDIC +# define foreign(c) ascii[(uch)(c)] +# define native(c) ebcdic[(uch)(c)] +# define NATIVE "EBCDIC" +# define NOANSIFILT +#endif + +#if (defined(CRAY) && defined(ZMEM)) +# undef ZMEM +#endif + +#ifdef ZMEM +# undef ZMEM +# define memcmp(b1,b2,len) bcmp(b2,b1,len) +# define memcpy(dest,src,len) bcopy(src,dest,len) +# define memzero bzero +#else +# define memzero(dest,len) memset(dest,0,len) +#endif + +#ifdef VMS +# define ENV_UNZIP "UNZIP_OPTS" /* names of environment variables */ +# define ENV_ZIPINFO "ZIPINFO_OPTS" +#endif /* VMS */ +#ifdef RISCOS +# define ENV_UNZIP "Unzip$Options" +# define ENV_ZIPINFO "Zipinfo$Options" +# define ENV_UNZIPEXTS "Unzip$Exts" +#endif /* RISCOS */ +#ifndef ENV_UNZIP +# define ENV_UNZIP "UNZIP" /* the standard names */ +# define ENV_ZIPINFO "ZIPINFO" +#endif +#define ENV_UNZIP2 "UNZIPOPT" /* alternate names, for zip compat. */ +#define ENV_ZIPINFO2 "ZIPINFOOPT" + +#if (!defined(QQ) && !defined(NOQQ)) +# define QQ +#endif + +#ifdef QQ /* Newtware version: no file */ +# define QCOND (!uO.qflag) /* comments with -vq or -vqq */ +#else /* Bill Davidsen version: no way to */ +# define QCOND (longhdr) /* kill file comments when listing */ +#endif + +#ifdef OLD_QQ +# define QCOND2 (uO.qflag < 2) +#else +# define QCOND2 (!uO.qflag) +#endif + +#ifndef TRUE +# define TRUE 1 /* sort of obvious */ +#endif +#ifndef FALSE +# define FALSE 0 +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 +# define SEEK_CUR 1 +# define SEEK_END 2 +#endif + +#if (defined(UNIX) && defined(S_IFLNK) && !defined(MTS)) +# define SYMLINKS +# ifndef S_ISLNK +# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +# endif +#endif /* UNIX && S_IFLNK && !MTS */ + +#ifndef S_ISDIR +# ifdef CMS_MVS +# define S_ISDIR(m) (FALSE) +# else +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# endif +#endif + +#ifndef IS_VOLID +# define IS_VOLID(m) ((m) & 0x08) +#endif + + + + + +/**************/ +/* Typedefs */ +/**************/ + +#ifdef NO_UID_GID +# ifdef UID_USHORT + typedef unsigned short uid_t; /* TI SysV.3 */ + typedef unsigned short gid_t; +# else + typedef unsigned int uid_t; /* SCO Xenix */ + typedef unsigned int gid_t; +# endif +#endif + +#if (defined(WIN32) || defined(sgi) || defined(GOT_UTIMBUF) || defined(ATARI)) + typedef struct utimbuf ztimbuf; +#else + typedef struct ztimbuf { + time_t actime; /* new access time */ + time_t modtime; /* new modification time */ + } ztimbuf; +#endif + +typedef struct iztimes { + time_t atime; /* new access time */ + time_t mtime; /* new modification time */ + time_t ctime; /* used for creation time; NOT same as st_ctime */ +} iztimes; + +#ifdef SET_DIR_ATTRIB + typedef struct dirtime { /* temporary struct for holding directory info */ + struct dirtime *next; /* 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 */ + ush uidgid[2]; + } dirtime; +#endif /* SET_DIR_ATTRIB */ + +typedef struct min_info { + long offset; + ulg crc; /* crc (needed if extended header) */ + ulg compr_size; /* compressed size (needed if extended header) */ + ulg uncompr_size; /* uncompressed size (needed if extended header) */ + int hostnum; + unsigned file_attr; /* local flavor, as used by creat(), chmod()... */ + unsigned encrypted : 1; /* file encrypted: decrypt before uncompressing */ + unsigned ExtLocHdr : 1; /* use time instead of CRC for decrypt check */ + unsigned textfile : 1; /* file is text (according to zip) */ + unsigned textmode : 1; /* file is to be extracted as text */ + unsigned lcflag : 1; /* convert filename to lowercase */ + unsigned vollabel : 1; /* "file" is an MS-DOS volume (disk) label */ +} min_info; + +typedef struct VMStimbuf { + char *revdate; /* (both roughly correspond to Unix modtime/st_mtime) */ + char *credate; +} VMStimbuf; + +/*--------------------------------------------------------------------------- + Zipfile work area declarations. + ---------------------------------------------------------------------------*/ + +#ifdef MALLOC_WORK + union work { + struct { /* unshrink(): */ + shrint *Parent; /* (8193 * sizeof(shrint)) */ + uch *value; + uch *Stack; + } shrink; + uch *Slide; /* explode(), inflate(), unreduce() */ + }; +#else /* !MALLOC_WORK */ + union work { + struct { /* unshrink(): */ + shrint Parent[HSIZE]; /* (8192 * sizeof(shrint)) == 16KB minimum */ + uch value[HSIZE]; /* 8KB */ + uch Stack[HSIZE]; /* 8KB */ + } shrink; /* total = 32KB minimum; 80KB on Cray/Alpha */ + uch Slide[WSIZE]; /* explode(), inflate(), unreduce() */ + }; +#endif /* ?MALLOC_WORK */ + +#define slide G.area.Slide + +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) +# define redirSlide G.redirect_sldptr +#else +# define redirSlide G.area.Slide +#endif + +/*--------------------------------------------------------------------------- + Zipfile layout declarations. If these headers ever change, make sure the + xxREC_SIZE defines (above) change with them! + ---------------------------------------------------------------------------*/ + + typedef uch local_byte_hdr[ LREC_SIZE ]; +# define L_VERSION_NEEDED_TO_EXTRACT_0 0 +# define L_VERSION_NEEDED_TO_EXTRACT_1 1 +# define L_GENERAL_PURPOSE_BIT_FLAG 2 +# define L_COMPRESSION_METHOD 4 +# define L_LAST_MOD_DOS_DATETIME 6 +# define L_CRC32 10 +# define L_COMPRESSED_SIZE 14 +# define L_UNCOMPRESSED_SIZE 18 +# define L_FILENAME_LENGTH 22 +# define L_EXTRA_FIELD_LENGTH 24 + + typedef uch cdir_byte_hdr[ CREC_SIZE ]; +# define C_VERSION_MADE_BY_0 0 +# define C_VERSION_MADE_BY_1 1 +# define C_VERSION_NEEDED_TO_EXTRACT_0 2 +# define C_VERSION_NEEDED_TO_EXTRACT_1 3 +# define C_GENERAL_PURPOSE_BIT_FLAG 4 +# define C_COMPRESSION_METHOD 6 +# define C_LAST_MOD_DOS_DATETIME 8 +# define C_CRC32 12 +# define C_COMPRESSED_SIZE 16 +# define C_UNCOMPRESSED_SIZE 20 +# define C_FILENAME_LENGTH 24 +# define C_EXTRA_FIELD_LENGTH 26 +# define C_FILE_COMMENT_LENGTH 28 +# define C_DISK_NUMBER_START 30 +# define C_INTERNAL_FILE_ATTRIBUTES 32 +# define C_EXTERNAL_FILE_ATTRIBUTES 34 +# define C_RELATIVE_OFFSET_LOCAL_HEADER 38 + + typedef uch ec_byte_rec[ ECREC_SIZE+4 ]; +/* define SIGNATURE 0 space-holder only */ +# define NUMBER_THIS_DISK 4 +# define NUM_DISK_WITH_START_CENTRAL_DIR 6 +# define NUM_ENTRIES_CENTRL_DIR_THS_DISK 8 +# define TOTAL_ENTRIES_CENTRAL_DIR 10 +# define SIZE_CENTRAL_DIRECTORY 12 +# define OFFSET_START_CENTRAL_DIRECTORY 16 +# define ZIPFILE_COMMENT_LENGTH 20 + + + typedef struct local_file_header { /* LOCAL */ + uch version_needed_to_extract[2]; + ush general_purpose_bit_flag; + ush compression_method; + ulg last_mod_dos_datetime; + ulg crc32; + ulg csize; + ulg ucsize; + ush filename_length; + ush extra_field_length; + } local_file_hdr; + +#if 0 + typedef struct central_directory_file_header { /* CENTRAL */ + uch version_made_by[2]; + uch version_needed_to_extract[2]; + ush general_purpose_bit_flag; + ush compression_method; + ulg last_mod_dos_datetime; + ulg crc32; + ulg csize; + ulg ucsize; + ush filename_length; + ush extra_field_length; + ush file_comment_length; + ush disk_number_start; + ush internal_file_attributes; + ulg external_file_attributes; + ulg relative_offset_local_header; + } cdir_file_hdr; +#endif /* 0 */ + + typedef struct end_central_dir_record { /* END CENTRAL */ + ush number_this_disk; + ush num_disk_start_cdir; + ush num_entries_centrl_dir_ths_disk; + ush total_entries_central_dir; + ulg size_central_directory; + ulg offset_start_central_directory; + ush zipfile_comment_length; + } ecdir_rec; + + +/* Huffman code lookup table entry--this entry is four bytes for machines + that have 16-bit pointers (e.g. PC's in the small or medium model). + Valid extra bits are 0..13. e == 15 is EOB (end of block), e == 16 + means that v is a literal, 16 < e < 32 means that v is a pointer to + the next table, which codes e - 16 bits, and lastly e == 99 indicates + an unused code. If a code with e == 99 is looked up, this implies an + error in the data. */ + +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; +}; + + +typedef struct _APIDocStruct { + char *compare; + char *function; + char *syntax; + char *purpose; +} APIDocStruct; + + + + +/*************/ +/* Globals */ +/*************/ + +#if (defined(OS2) && !defined(FUNZIP)) +# include "os2/os2data.h" +#endif + +#include "globals.h" + + + +/*************************/ +/* Function Prototypes */ +/*************************/ + +/*--------------------------------------------------------------------------- + Functions in unzip.c (initialization routines): + ---------------------------------------------------------------------------*/ + +#ifndef WINDLL + int MAIN OF((int argc, char **argv)); + int unzip OF((__GPRO__ int argc, char **argv)); + int uz_opts OF((__GPRO__ int *pargc, char ***pargv)); + int usage OF((__GPRO__ int error)); +#endif /* !WINDLL */ + +/*--------------------------------------------------------------------------- + Functions in process.c (main driver routines): + ---------------------------------------------------------------------------*/ + +int process_zipfiles OF((__GPRO)); +void free_G_buffers OF((__GPRO)); +/* static int do_seekable OF((__GPRO__ int lastchance)); */ +/* static int find_ecrec OF((__GPRO__ long searchlen)); */ +int uz_end_central OF((__GPRO)); +int process_cdir_file_hdr OF((__GPRO)); +int get_cdir_ent OF((__GPRO)); +int process_local_file_hdr OF((__GPRO)); +unsigned ef_scan_for_izux OF((uch *ef_buf, unsigned ef_len, int ef_is_c, + ulg dos_mdatetime, + iztimes *z_utim, ush *z_uidgid)); + +#ifndef SFX + +/*--------------------------------------------------------------------------- + Functions in zipinfo.c (`zipinfo-style' listing routines): + ---------------------------------------------------------------------------*/ + +#ifndef NO_ZIPINFO +#ifndef WINDLL + int zi_opts OF((__GPRO__ int *pargc, char ***pargv)); +#endif +int zi_end_central OF((__GPRO)); +int zipinfo OF((__GPRO)); +/* static int zi_long OF((__GPRO__ ulg *pEndprev)); */ +/* static int zi_short OF((__GPRO)); */ +/* static char *zi_time OF((__GPRO__ ZCONST ulg *datetimez, + ZCONST time_t *modtimez, char *d_t_str));*/ +#endif /* !NO_ZIPINFO */ + +/*--------------------------------------------------------------------------- + Functions in list.c (generic zipfile-listing routines): + ---------------------------------------------------------------------------*/ + +int list_files OF((__GPRO)); +#ifdef TIMESTAMP + int get_time_stamp OF((__GPRO__ time_t *last_modtime, + unsigned *nmember)); +#endif +int ratio OF((ulg uc, ulg c)); +void fnprint OF((__GPRO)); + +#endif /* !SFX */ + +/*--------------------------------------------------------------------------- + Functions in fileio.c: + ---------------------------------------------------------------------------*/ + +int open_input_file OF((__GPRO)); +int open_outfile OF((__GPRO)); /* also vms.c */ +void undefer_input OF((__GPRO)); +void defer_leftover_input OF((__GPRO)); +unsigned readbuf OF((__GPRO__ char *buf, register unsigned len)); +int readbyte OF((__GPRO)); +int fillinbuf OF((__GPRO)); +#ifdef FUNZIP + int flush OF((__GPRO__ ulg size)); /* actually funzip.c */ +#else + int flush OF((__GPRO__ uch *buf, ulg size, int unshrink)); +#endif +/* static int disk_error OF((__GPRO)); */ +void handler OF((int signal)); +time_t dos_to_unix_time OF((ulg dos_datetime)); +int check_for_newer OF((__GPRO__ char *filename)); /* os2,vmcms,vms */ +int do_string OF((__GPRO__ unsigned int len, int option)); +ush makeword OF((ZCONST uch *b)); +ulg makelong OF((ZCONST uch *sig)); +#if (!defined(STR_TO_ISO) || defined(NEED_STR2ISO)) + char *str2iso OF((char *dst, ZCONST char *src)); +#endif +#if (!defined(STR_TO_OEM) || defined(NEED_STR2OEM)) + char *str2oem OF((char *dst, ZCONST char *src)); +#endif +int zstrnicmp OF((register ZCONST char *s1, + register ZCONST char *s2, + register unsigned n)); +#ifdef REGULUS + int zstat OF((char *p, struct stat *s)); +#endif +#ifdef ZMEM /* MUST be ifdef'd because of conflicts with the standard def. */ + zvoid *memset OF((register zvoid *, register int, register unsigned int)); + int memcmp OF((register ZCONST zvoid*, register ZCONST zvoid *, + register unsigned int)); + zvoid *memcpy OF((register zvoid *, register ZCONST zvoid *, + register unsigned int)); +#endif +#ifdef SMALL_MEM + char *fLoadFarString OF((__GPRO__ const char Far *sz)); + char *fLoadFarStringSmall OF((__GPRO__ const char Far *sz)); + char *fLoadFarStringSmall2 OF((__GPRO__ const char Far *sz)); + #ifndef zfstrcpy + char Far * Far zfstrcpy OF((char Far *s1, const char Far *s2)); + #endif +#endif + + +/*--------------------------------------------------------------------------- + Functions in extract.c: + ---------------------------------------------------------------------------*/ + +int extract_or_test_files OF((__GPRO)); +/* static int store_info OF((void)); */ +/* static int extract_or_test_member OF((__GPRO)); */ +/* static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len)); */ +/* static int test_OS2 OF((__GPRO__ uch *eb, unsigned eb_size)); */ +/* static int test_NT OF((__GPRO__ uch *eb, unsigned eb_size)); */ +int memextract OF((__GPRO__ uch *tgt, ulg tgtsize, + uch *src, ulg srcsize)); +int memflush OF((__GPRO__ uch *rawbuf, ulg size)); +char *fnfilter OF((ZCONST char *raw, uch *space)); + +/*--------------------------------------------------------------------------- + Decompression functions: + ---------------------------------------------------------------------------*/ + +#if (!defined(SFX) && !defined(FUNZIP)) +int explode OF((__GPRO)); /* explode.c */ +#endif +int huft_free OF((struct huft *t)); /* inflate.c */ +int huft_build OF((__GPRO__ ZCONST unsigned *b, unsigned n, + unsigned s, ZCONST ush *d, ZCONST ush *e, + struct huft **t, int *m)); +#ifdef USE_ZLIB + int UZinflate OF((__GPRO)); /* inflate.c */ +# define inflate_free(x) inflateEnd(&((Uz_Globs *)(&G))->dstrm) +#else + int inflate OF((__GPRO)); /* inflate.c */ + int inflate_free OF((__GPRO)); /* inflate.c */ +#endif /* ?USE_ZLIB */ +#if (!defined(SFX) && !defined(FUNZIP)) +void unreduce OF((__GPRO)); /* unreduce.c */ +/* static void LoadFollowers OF((__GPRO__ f_array *follower, uch *Slen)); + * unreduce.c */ +int unshrink OF((__GPRO)); /* unshrink.c */ +/* static void partial_clear OF((__GPRO)); * unshrink.c */ +#endif /* !SFX && !FUNZIP */ + +/*--------------------------------------------------------------------------- + Internal API functions (only included in DLL versions): + ---------------------------------------------------------------------------*/ + +#ifdef DLL + void setFileNotFound OF((__GPRO)); /* api.c */ + int unzipToMemory OF((__GPRO__ char *zip, char *file, + UzpBuffer *retstr)); /* api.c */ + int redirect_outfile OF((__GPRO)); /* api.c */ + int writeToMemory OF((__GPRO__ uch *rawbuf, ulg size)); + int close_redirect OF((__GPRO)); /* api.c */ + /* this obsolescent entry point kept for compatibility: */ + int UzpUnzip OF((int argc, char **argv));/* use UzpMain */ +#ifdef OS2DLL + int varmessage OF((__GPRO__ uch *buf, ulg size)); + int varputchar OF((__GPRO__ int c)); /* rexxapi.c */ + int finish_REXX_redirect OF((__GPRO)); /* rexxapi.c */ +#endif +#ifdef API_DOC + void APIhelp OF((__GPRO__ int argc, char **argv)); +#endif /* apihelp.c */ +#endif /* DLL */ + +/*--------------------------------------------------------------------------- + Acorn RISC OS-only functions: + ---------------------------------------------------------------------------*/ + +#ifdef RISCOS + int isRISCOSexfield OF((void *extra_field)); /* acorn.c */ + void setRISCOSexfield OF((char *path, void *extra_field)); /* acorn.c */ + void printRISCOSexfield OF((int isdir, void *extra_field)); /* acorn.c */ +#endif + +/*--------------------------------------------------------------------------- + Human68K-only functions: + ---------------------------------------------------------------------------*/ + +#ifdef __human68k__ + void InitTwentyOne OF((void)); +#endif + +/*--------------------------------------------------------------------------- + Macintosh-only functions: + ---------------------------------------------------------------------------*/ + +#ifdef MACOS + 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 *)); /* mac.c */ + short macopen OF((char *, short)); /* mac.c */ + short maccreat OF((char *)); /* mac.c */ + short macread OF((short, char *, unsigned)); /* mac.c */ + long macwrite OF((short, char *, unsigned)); /* mac.c */ + short macclose OF((short)); /* mac.c */ + long maclseek OF((short, long, short)); /* mac.c */ + char *macfgets OF((char *, int, FILE *)); /* mac.c */ + int macfprintf OF((FILE *, char *, ...)); /* mac.c */ + int macprintf OF((char *, ...)); /* mac.c */ +#endif + +/*--------------------------------------------------------------------------- + MSDOS-only functions: + ---------------------------------------------------------------------------*/ + +#if (defined(MSDOS) && (defined(__GO32__) || defined(__EMX__))) + unsigned _dos_getcountryinfo(void *); /* msdos.c */ +#if (!defined(__DJGPP__) || (__DJGPP__ < 2)) + unsigned _dos_setftime(int, unsigned short, unsigned short); /* msdos.c */ + unsigned _dos_setfileattr(char *, unsigned); /* msdos.c */ + unsigned _dos_creat(char *, unsigned, int *); /* msdos.c */ + void _dos_getdrive(unsigned *); /* msdos.c */ + unsigned _dos_close(int); /* msdos.c */ +#endif /* !__DJGPP__ || (__DJGPP__ < 2) */ +#endif + +/*--------------------------------------------------------------------------- + OS/2-only functions: + ---------------------------------------------------------------------------*/ + +#ifdef OS2 /* GetFileTime conflicts with something in Win32 header files */ +#if (defined(REENTRANT) && defined(USETHREADID)) + ulg GetThreadId OF((void)); +#endif + int GetCountryInfo OF((void)); /* os2.c */ + long GetFileTime OF((ZCONST char *name)); /* os2.c */ +/* static void SetPathAttrTimes OF((__GPRO__ int flags, int dir)); os2.c */ +/* static int SetEAs OF((__GPRO__ const char *path, + void *eablock)); os2.c */ +/* static int SetACL OF((__GPRO__ const char *path, + void *eablock)); os2.c */ +/* static int IsFileNameValid OF((const char *name)); os2.c */ +/* static void map2fat OF((char *pathcomp, char **pEndFAT)); os2.c */ +/* static int SetLongNameEA OF((char *name, char *longname)); os2.c */ +/* static void InitNLS OF((void)); os2.c */ + int IsUpperNLS OF((int nChr)); /* os2.c */ + int ToLowerNLS OF((int nChr)); /* os2.c */ + void DebugMalloc OF((void)); /* os2.c */ +#endif + +/*--------------------------------------------------------------------------- + QDOS-only functions: + ---------------------------------------------------------------------------*/ + +#ifdef QDOS + int QMatch (uch, uch); + void QFilename (__GPRO__ char *); + char *Qstrfix (char *); + int QReturn (int zip_error); +#endif + +/*--------------------------------------------------------------------------- + TOPS20-only functions: + ---------------------------------------------------------------------------*/ + +#ifdef TOPS20 + int upper OF((char *s)); /* tops20.c */ + int enquote OF((char *s)); /* tops20.c */ + int dequote OF((char *s)); /* tops20.c */ + int fnlegal OF(()); /* error if prototyped? */ /* tops20.c */ +#endif + +/*--------------------------------------------------------------------------- + VM/CMS- and MVS-only functions: + ---------------------------------------------------------------------------*/ + +#ifdef CMS_MVS + extent getVMMVSexfield OF((char *type, uch *ef_block, unsigned datalen)); + FILE *vmmvs_open_infile OF((__GPRO)); /* vmmvs.c */ + void close_infile OF((__GPRO)); /* vmmvs.c */ +#endif + +/*--------------------------------------------------------------------------- + VMS-only functions: + ---------------------------------------------------------------------------*/ + +#ifdef VMS + int check_format OF((__GPRO)); /* vms.c */ +/* int open_outfile OF((__GPRO)); * (see fileio.c) vms.c */ +/* int flush OF((__GPRO__ uch *rawbuf, unsigned size, + int final_flag)); * (see fileio.c) vms.c */ +#ifdef RETURN_CODES + void return_VMS OF((__GPRO__ int zip_error)); /* vms.c */ +#else + void return_VMS OF((int zip_error)); /* vms.c */ +#endif +#ifdef VMSCLI + ulg vms_unzip_cmdline OF((int *, char ***)); /* cmdline.c */ + int VMSCLI_usage OF((__GPRO__ int error)); /* cmdline.c */ +#endif +#endif + +/*--------------------------------------------------------------------------- + WIN32-only functions: + ---------------------------------------------------------------------------*/ + +#ifdef WIN32 + int IsWinNT OF((void)); /* win32.c */ +#ifdef NTSD_EAS + void process_defer_NT OF((__GPRO)); /* win32.c */ + int test_NTSD OF((__GPRO__ uch *eb, unsigned eb_size, + uch *eb_ucptr, ulg eb_ucsize)); /* win32.c */ +# define TEST_NTSD test_NTSD +#endif +#ifdef W32_STAT_BANDAID + int zstat_win32 OF((__W32STAT_GLOBALS__ + const char *path, struct stat *buf)); /* win32.c */ +#endif +#endif + +/*--------------------------------------------------------------------------- + Miscellaneous/shared functions: + ---------------------------------------------------------------------------*/ + +Uz_Globs *globalsCtor OF((void)); /* globals.c */ + +void envargs OF((__GPRO__ int *Pargc, char ***Pargv, + ZCONST char *envstr, ZCONST char *envstr2)); + /* envargs.c */ +void mksargs OF((int *argcp, char ***argvp)); /* envargs.c */ + +int match OF((ZCONST char *s, ZCONST char *p, + int ic)); /* match.c */ +int iswild OF((ZCONST char *p)); /* match.c */ + +#ifdef DYNALLOC_CRCTAB + void free_crc_table OF((void)); /* crctab.c */ +#endif +#ifndef USE_ZLIB + ZCONST ulg near *get_crc_table OF((void)); /* funzip.c, crctab.c */ + ulg crc32 OF((ulg crc, ZCONST uch *buf, extent len)); +#endif /* !USE_ZLIB */ /* assembler source or crc32.c */ + +int dateformat OF((void)); /* currently, only msdos.c */ +#ifndef WINDLL + void version OF((__GPRO)); /* local */ +#endif +int mapattr OF((__GPRO)); /* local */ +int mapname OF((__GPRO__ int renamed)); /* local */ +int checkdir OF((__GPRO__ char *pathcomp, int flag)); /* local */ +char *do_wild OF((__GPRO__ char *wildzipfn)); /* local */ +char *GetLoadPath OF((__GPRO)); /* local */ +#if (defined(MORE) && (defined(UNIX) || defined(VMS) || defined(__BEOS__))) + int screenlines OF((void)); /* local */ +#endif +#ifndef MTS /* macro in MTS */ + void close_outfile OF((__GPRO)); /* local */ +#endif +#ifdef SET_DIR_ATTRIB + int set_direc_attribs OF((__GPRO__ dirtime *d)); /* local */ +#endif +#ifdef TIMESTAMP +# ifdef WIN32 + int stamp_file OF((__GPRO__ + ZCONST char *fname, time_t modtime)); /* local */ +# else + int stamp_file OF((ZCONST char *fname, time_t modtime)); /* local */ +# endif +#endif +#ifdef SYSTEM_SPECIFIC_CTOR + void SYSTEM_SPECIFIC_CTOR OF((__GPRO)); /* local */ +#endif + + + + + +/************/ +/* Macros */ +/************/ + +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifdef DEBUG +# define Trace(x) fprintf x +#else +# define Trace(x) +#endif + +#ifdef DEBUG_TIME +# define TTrace(x) fprintf x +#else +# define TTrace(x) +#endif + +#ifdef NO_DEBUG_IN_MACROS +# define MTrace(x) +#else +# define MTrace(x) Trace(x) +#endif + +#if (defined(UNIX) || defined(T20_VMS)) /* generally old systems */ +# define ToLower(x) ((char)(isupper((int)x)? tolower((int)x) : x)) +#else +# define ToLower tolower /* assumed "smart"; used in match() */ +#endif + +#ifdef USE_STRM_INPUT + /* ``Replace'' the unbuffered UNIX style I/O function with similar + * standard C functions from . + */ +# define read(fd,buf,n) fread((buf),1,(n),(FILE *)(fd)) +# define lseek(fd,o,w) fseek((FILE *)(fd),(o),(w)) +# define close(fd) fclose((FILE *)(fd)) +#endif /* USE_STRM_INPUT */ + +/* The return value of the Info() "macro function" is never checked in + * UnZip. Otherwise, to get the same behaviour as for (*G.message)(), the + * Info() definition for "FUNZIP" would have to be corrected: + * #define Info(buf,flag,sprf_arg) \ + * (fprintf((flag)&1? stderr : stdout, \ + * (char *)(sprintf sprf_arg, (buf))) == EOF) + */ +#ifndef Info /* may already have been defined for redirection */ +# ifdef FUNZIP +# define Info(buf,flag,sprf_arg) \ + fprintf((flag)&1? stderr : stdout, (char *)(sprintf sprf_arg, (buf))) +# else +# ifdef INT_SPRINTF /* optimized version for "int sprintf()" flavour */ +# define Info(buf,flag,sprf_arg) \ + (*G.message)((zvoid *)&G, (uch *)(buf), (ulg)sprintf sprf_arg, (flag)) +# else /* generic version, does not use sprintf() return value */ +# define Info(buf,flag,sprf_arg) \ + (*G.message)((zvoid *)&G, (uch *)(buf), \ + (ulg)(sprintf sprf_arg, strlen((char *)(buf))), (flag)) +# endif +# endif +#endif /* !Info */ + +#undef Info +#define Info(buf,flag,sprf_arg) (0) + +/* The following macros wrappers around the fnfilter function are used many + * times to prepare archive entry names or name components for displaying + * listings and (warning/error) messages. They use sections in the upper half + * of 'slide' as buffer, since their output is normally fed through the + * Info() macro with 'slide' (the start of this area) as message buffer. + */ +#define FnFilter1(fname) fnfilter((fname), slide + (WSIZE>>1)) +#define FnFilter2(fname) fnfilter((fname), slide + ((WSIZE>>1) + (WSIZE>>2))) + +#ifndef FUNZIP /* used only in inflate.c */ +# define MESSAGE(str,len,flag) (*G.message)((zvoid *)&G,(str),(len),(flag)) +#endif + +#if 0 /* Optimization: use the (const) result of crc32(0L,NULL,0) */ +# define CRCVAL_INITIAL crc32(0L, NULL, 0) +#else +# define CRCVAL_INITIAL 0L +#endif + +#ifndef TEST_NTSD /* "NTSD valid?" checking function */ +# define TEST_NTSD NULL /* ... is not available */ +#endif + +/* + * 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 macro + * is used by uz_end_central (process.c), zi_end_central (zipinfo.c) and + * do_string (fileio.c). A slightly modified version is embedded within + * extract_or_test_files (extract.c). readbyte() and readbuf() (fileio.c) + * are compatible. NOTE THAT abs_offset is intended to be the "proper off- + * set" (i.e., if there were no extra bytes prepended); cur_zipfile_bufstart + * contains the corrected offset. + * + * Since ZLSEEK is never used during decompression, it is safe to use the + * slide[] buffer for the error message. + * + * The awkward "%cbs_offset" construct is provided for the obnoxious Solaris + * compiler, which wants to do macro substitution inside strings. + */ + +#ifndef ZLSEEK +# ifdef USE_STRM_INPUT +# define _ZLS_RELOAD(abs_offset) {\ + MTrace((stderr, "ZLSEEK: %cbs_offset = %ld, G.extra_bytes = %ld\n",\ + 'a', (abs_offset), G.extra_bytes));\ + fseek(G.zipfd,(LONGINT)bufstart,SEEK_SET);\ + G.cur_zipfile_bufstart = ftell(G.zipfd);\ + MTrace((stderr,\ + " request = %ld, (abs+extra) = %ld, inbuf_offset = %ld\n",\ + request, ((abs_offset)+G.extra_bytes), inbuf_offset));\ + MTrace((stderr, " bufstart = %ld, cur_zipfile_bufstart = %ld\n",\ + bufstart, G.cur_zipfile_bufstart));\ + if ((G.incnt = fread((char *)G.inbuf,1,INBUFSIZ,G.zipfd)) <= 0)\ + return(PK_EOF);\ + G.inptr = G.inbuf + (int)inbuf_offset;\ + G.incnt -= (int)inbuf_offset;\ + } +# else /* !USE_STRM_INPUT */ +# define _ZLS_RELOAD(abs_offset) {\ + MTrace((stderr, "ZLSEEK: %cbs_offset = %ld, G.extra_bytes = %ld\n",\ + 'a', (abs_offset), G.extra_bytes));\ + G.cur_zipfile_bufstart = lseek(G.zipfd,(LONGINT)bufstart,SEEK_SET);\ + MTrace((stderr,\ + " request = %ld, (abs+extra) = %ld, inbuf_offset = %ld\n",\ + request, ((abs_offset)+G.extra_bytes), inbuf_offset));\ + MTrace((stderr, " bufstart = %ld, cur_zipfile_bufstart = %ld\n",\ + bufstart, G.cur_zipfile_bufstart));\ + if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) <= 0)\ + return(PK_EOF);\ + G.inptr = G.inbuf + (int)inbuf_offset;\ + G.incnt -= (int)inbuf_offset;\ + } +# endif /* ?USE_STRM_INPUT */ + +# define ZLSEEK(abs_offset) {\ + LONGINT request = (abs_offset) + G.extra_bytes;\ + LONGINT inbuf_offset = request % INBUFSIZ;\ + LONGINT 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)\ + _ZLS_RELOAD(abs_offset)\ + else {\ + G.incnt += (G.inptr-G.inbuf) - (int)inbuf_offset;\ + G.inptr = G.inbuf + (int)inbuf_offset;\ + }\ + } +#endif /* !ZLSEEK */ + +#define SKIP_(length) if(length&&((error=do_string(__G__ length,SKIP))!=0))\ + {error_in_archive=error; if(error>1) return error;} + +/* + * Skip a variable-length field, and report any errors. Used in zipinfo.c + * and unzip.c in several functions. + * + * macro SKIP_(length) + * ush length; + * { + * if (length && ((error = do_string(length, SKIP)) != 0)) { + * error_in_archive = error; /-* might be warning *-/ + * if (error > 1) /-* fatal *-/ + * return (error); + * } + * } + * + */ + + +#ifdef FUNZIP +# define FLUSH(w) flush(__G__ (ulg)(w)) +# define NEXTBYTE getc(G.in) /* redefined in crypt.h if full version */ +#else +# define FLUSH(w) if (G.mem_mode) memflush(__G__ redirSlide,(ulg)(w)); \ + else flush(__G__ redirSlide,(ulg)(w),0) +# define NEXTBYTE (--G.incnt >= 0 ? (int)(*G.inptr++) : readbyte(__G)) +#endif + + +#define READBITS(nbits,zdest) {if(nbits>G.bits_left) {int temp; G.zipeof=1;\ + while (G.bits_left<=8*(int)(sizeof(G.bitbuf)-1) && (temp=NEXTBYTE)!=EOF) {\ + G.bitbuf|=(ulg)temp<>=nbits;\ + G.bits_left-=nbits;} + +/* + * macro READBITS(nbits,zdest) * only used by unreduce and unshrink * + * { + * if (nbits > G.bits_left) { * fill G.bitbuf, 8*sizeof(ulg) bits * + * int temp; + * + * G.zipeof = 1; + * while (G.bits_left <= 8*(int)(sizeof(G.bitbuf)-1) && + * (temp = NEXTBYTE) != EOF) { + * G.bitbuf |= (ulg)temp << G.bits_left; + * G.bits_left += 8; + * G.zipeof = 0; + * } + * } + * zdest = (shrint)((ush)G.bitbuf & mask_bits[nbits]); + * G.bitbuf >>= nbits; + * G.bits_left -= nbits; + * } + * + */ + + +/* GRR: should change name to STRLOWER and use StringLower if possible */ + +/* + * Copy the zero-terminated string in str1 into str2, converting any + * uppercase letters to lowercase as we go. str2 gets zero-terminated + * as well, of course. str1 and str2 may be the same character array. + */ +#ifdef __human68k__ +# define TOLOWER(str1, str2) \ + { \ + char *p=(str1), *q=(str2); \ + uch c; \ + while ((c = *p++) != '\0') { \ + if (iskanji(c)) { \ + if (*p == '\0') \ + break; \ + *q++ = c; \ + *q++ = *p++; \ + } else \ + *q++ = isupper(c) ? tolower(c) : c; \ + } \ + *q = '\0'; \ + } +#else +# define TOLOWER(str1, str2) \ + { \ + char *p, *q; \ + p = (str1) - 1; \ + q = (str2); \ + while (*++p) \ + *q++ = (char)(isupper((int)(*p))? tolower((int)(*p)) : *p); \ + *q = '\0'; \ + } +#endif +/* + * NOTES: This macro makes no assumptions about the characteristics of + * the tolower() function or macro (beyond its existence), nor does it + * make assumptions about the structure of the character set (i.e., it + * should work on EBCDIC machines, too). The fact that either or both + * of isupper() and tolower() may be macros has been taken into account; + * watch out for "side effects" (in the C sense) when modifying this + * macro. + */ + +#ifndef foreign +# define foreign(c) (c) +#endif + +#ifndef native +# define native(c) (c) +# define A_TO_N(str1) +#else +# ifndef NATIVE +# define NATIVE "native chars" +# endif +# define A_TO_N(str1) {register uch *p;\ + for (p=(uch *)(str1); *p; p++) *p=native(*p);} +#endif +/* + * Translate the zero-terminated string in str1 from ASCII to the native + * character set. The translation is performed in-place and uses the + * "native" macro to translate each character. + * + * NOTE: Using the "native" macro means that is it the only part of unzip + * which knows which translation table (if any) is actually in use to + * produce the native character set. This makes adding new character set + * translation tables easy, insofar as all that is needed is an appropriate + * "native" macro definition and the translation table itself. Currently, + * the only non-ASCII native character set implemented is EBCDIC, but this + * may not always be so. + */ + + +/* default setup for internal codepage: assume ISO 8859-1 compatibility!! */ +#if (!defined(NATIVE) && !defined(CRTL_CP_IS_ISO) && !defined(CRTL_CP_IS_OEM)) +# define CRTL_CP_IS_ISO +#endif + + +/* Translate "extended ASCII" chars (OEM coding for DOS and OS/2; else + * ISO-8859-1 [ISO Latin 1, Win Ansi,...]) into the internal "native" + * code page. As with A_TO_N(), conversion is done in place. + */ +#ifndef _ISO_INTERN +# ifdef CRTL_CP_IS_OEM +# ifndef IZ_ISO2OEM_ARRAY +# define IZ_ISO2OEM_ARRAY +# endif +# define _ISO_INTERN(str1) {register uch *p;\ + for (p=(uch *)(str1); *p; p++)\ + *p = native((*p & 0x80) ? iso2oem[*p & 0x7f] : *p);} +# else +# define _ISO_INTERN(str1) A_TO_N(str1) +# endif +#endif + +#ifndef _OEM_INTERN +# ifdef CRTL_CP_IS_OEM +# define _OEM_INTERN(str1) A_TO_N(str1) +# else +# ifndef IZ_OEM2ISO_ARRAY +# define IZ_OEM2ISO_ARRAY +# endif +# define _OEM_INTERN(str1) {register uch *p;\ + for (p=(uch *)(str1); *p; p++)\ + *p = native((*p & 0x80) ? oem2iso[*p & 0x7f] : *p);} +# endif +#endif + +#ifndef STR_TO_ISO +# ifdef CRTL_CP_IS_ISO +# define STR_TO_ISO strcpy +# else +# define STR_TO_ISO str2iso +# define NEED_STR2ISO +# endif +#endif + +#ifndef STR_TO_OEM +# ifdef CRTL_CP_IS_OEM +# define STR_TO_OEM strcpy +# else +# define STR_TO_OEM str2oem +# define NEED_STR2OEM +# endif +#endif + +#if (!defined(INTERN_TO_ISO) && !defined(ASCII2ISO)) +# ifdef CRTL_CP_IS_OEM + /* know: "ASCII" is "OEM" */ +# define ASCII2ISO(c) (((c) & 0x80) ? oem2iso[(c) & 0x7f] : (c)) +# if (defined(NEED_STR2ISO) && !defined(CRYP_USES_OEM2ISO)) +# define CRYP_USES_OEM2ISO +# endif +# else + /* assume: "ASCII" is "ISO-ANSI" */ +# define ASCII2ISO(c) (c) +# endif +#endif + +#if (!defined(INTERN_TO_OEM) && !defined(ASCII2OEM)) +# ifdef CRTL_CP_IS_OEM + /* know: "ASCII" is "OEM" */ +# define ASCII2OEM(c) (c) +# else + /* assume: "ASCII" is "ISO-ANSI" */ +# define ASCII2OEM(c) (((c) & 0x80) ? iso2oem[(c) & 0x7f] : (c)) +# if (defined(NEED_STR2OEM) && !defined(CRYP_USES_ISO2OEM)) +# define CRYP_USES_ISO2OEM +# endif +# endif +#endif + +/* codepage conversion setup for testp() in crypt.c */ +#ifdef CRTL_CP_IS_ISO +# ifndef STR_TO_CP2 +# define STR_TO_CP2 STR_TO_OEM +# endif +#else +# ifdef CRTL_CP_IS_OEM +# ifndef STR_TO_CP2 +# define STR_TO_CP2 STR_TO_ISO +# endif +# else /* native internal CP is neither ISO nor OEM */ +# ifndef STR_TO_CP1 +# define STR_TO_CP1 STR_TO_ISO +# endif +# ifndef STR_TO_CP2 +# define STR_TO_CP2 STR_TO_OEM +# endif +# endif +#endif + + +/* Convert filename (and file comment string) into "internal" charset. + * This macro assumes that Zip entry filenames are coded in OEM (IBM DOS) + * codepage when made on + * -> DOS (this includes 16-bit Windows 3.1) (FS_FAT_) + * -> OS/2 (FS_HPFS_) + * -> Win95/WinNT with Nico Mak's WinZip (FS_NTFS_ && hostver == "5.0") + * + * All other ports are assumed to code zip entry filenames in ISO 8859-1. + */ +#ifndef Ext_ASCII_TO_Native +# define Ext_ASCII_TO_Native(string, hostnum, hostver) \ + if ((hostnum) == FS_FAT_ || (hostnum) == FS_HPFS_ || \ + ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \ + _OEM_INTERN((string)); \ + } else { \ + _ISO_INTERN((string)); \ + } +#endif + + + +/**********************/ +/* Global constants */ +/**********************/ + + extern ZCONST ush near mask_bits[]; + extern ZCONST char *fnames[2]; + +#ifdef EBCDIC + extern ZCONST uch ebcdic[]; +#endif +#ifdef IZ_ISO2OEM_ARRAY + extern ZCONST uch Far iso2oem[]; +#endif +#ifdef IZ_OEM2ISO_ARRAY + extern ZCONST uch Far oem2iso[]; +#endif + + extern ZCONST char Far VersionDate[]; + extern ZCONST char Far CentSigMsg[]; + extern ZCONST char Far EndSigMsg[]; + extern ZCONST char Far SeekMsg[]; + extern ZCONST char Far FilenameNotMatched[]; + extern ZCONST char Far ExclFilenameNotMatched[]; + extern ZCONST char Far ReportMsg[]; + +#ifndef SFX + extern ZCONST char Far CompiledWith[]; +#endif /* !SFX */ + + + +/***********************************/ +/* Global (shared?) RTL variables */ +/***********************************/ + +#ifdef DECLARE_ERRNO + extern int errno; +#endif + + +#endif /* !__unzpriv_h */ diff --git a/utils/Install/inczip/version.h b/utils/Install/inczip/version.h new file mode 100644 index 0000000000..763cc13078 --- /dev/null +++ b/utils/Install/inczip/version.h @@ -0,0 +1,44 @@ +/* + version.h (for UnZip) by Info-ZIP. + + This header file is not copyrighted and may be distributed without + restriction. (That's a little geek humor, heh heh.) + */ + +#ifndef __version_h /* don't include more than once */ +#define __version_h + +#ifdef BETA +# undef BETA /* define BETA for internal beta releases */ +#endif + +#ifdef BETA +# define BETALEVEL "d BETA" +# define VERSION_DATE "27 November 98" /* internal beta version */ +#else +# define BETALEVEL "" +# define VERSION_DATE "28 November 1998" /* official release version */ +# define RELEASE +#endif + +#define UZ_MAJORVER 5 /* UnZip */ +#define UZ_MINORVER 4 + +#define ZI_MAJORVER 2 /* ZipInfo */ +#define ZI_MINORVER 3 + +#define PATCHLEVEL 0 + + +/* these are obsolete but remain for backward compatibility: */ +#define D2_MAJORVER UZ_MAJORVER /* DLL for OS/2 */ +#define D2_MINORVER UZ_MINORVER +#define D2_PATCHLEVEL PATCHLEVEL + +#define DW_MAJORVER UZ_MAJORVER /* DLL for MS Windows */ +#define DW_MINORVER UZ_MINORVER +#define DW_PATCHLEVEL PATCHLEVEL + +#define WIN_VERSION_DATE VERSION_DATE + +#endif /* !__version_h */ diff --git a/utils/Install/inczip/w32cfg.h b/utils/Install/inczip/w32cfg.h new file mode 100644 index 0000000000..18a8e3f85c --- /dev/null +++ b/utils/Install/inczip/w32cfg.h @@ -0,0 +1,222 @@ +/*--------------------------------------------------------------------------- + Win32 specific configuration section: + ---------------------------------------------------------------------------*/ + +#ifndef __w32cfg_h +#define __w32cfg_h + +#if (defined(__CYGWIN__) && !defined(__CYGWIN32__)) +# define __CYGWIN32__ /* new versions of CygWin may not define this */ +#endif + +#include /* off_t, time_t, dev_t, ... */ +#include +#include /* read(), open(), etc. */ +#include +#if (defined(__RSXNT__) || defined(__EMX__)) && !defined(tzset) +# define tzset _tzset +#endif +#ifdef __MINGW32__ + extern void _tzset(void); /* this is missing in */ +# ifndef tzset +# define tzset _tzset +# endif +#endif +#include +#if (!defined(__RSXNT__) && !defined(__CYGWIN32__)) +# include /* mkdir() */ +#endif +#include +#ifdef __CYGWIN32__ +# include + extern int setmode(int, int); /* this is missing in */ +#endif +#if (defined(MSC) || defined(__WATCOMC__) || defined(__MINGW32__)) +# include +#else +# include +#endif + +#if defined(FILEIO_C) +# ifndef __CYGWIN32__ +# include +# endif +# include +# ifdef __RSXNT__ +# include "win32/rsxntwin.h" +# endif +#endif +#if (defined(ENVARGS_C) || defined(EXTRACT_C) || defined(UNZIP_C) || \ + defined(ZCRYPT_INTERNAL)) +# include +# ifdef __RSXNT__ +# include "win32/rsxntwin.h" +# endif +#endif +#if (defined(__CYGWIN32__) || defined(__MINGW32__)) + /* the following definitions are missing in their */ +# ifndef AnsiToOem +# define AnsiToOem CharToOemA +# endif +# ifndef OemToAnsi +# define OemToAnsi OemToCharA +# endif +#endif + +#define DIR_END '\\' /* OS uses '\\' as directory separator */ +#define DIR_END2 '/' /* also check for '/' (RTL may convert) */ +#ifndef DATE_FORMAT +# define DATE_FORMAT DF_MDY +#endif +#define lenEOL 2 +#define PutNativeEOL {*q++ = native(CR); *q++ = native(LF);} + +#if (defined(__RSXNT__) && !defined(HAVE_MKTIME)) +# define HAVE_MKTIME /* use mktime() in time conversion routines */ +#endif +#if (defined(__CYGWIN32__) && defined(HAVE_MKTIME)) +# undef HAVE_MKTIME /* Cygnus' mktime() implementation is buggy */ +#endif +#if (!defined(NT_TZBUG_WORKAROUND) && !defined(NO_NT_TZBUG_WORKAROUND)) +# define NT_TZBUG_WORKAROUND +#endif +#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)) +# define USE_EF_UT_TIME +#endif +#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP)) +# define TIMESTAMP +#endif +#if (!defined(NO_NTSD_EAS) && !defined(NTSD_EAS)) +# define NTSD_EAS /* enable NTSD support unless explicitly suppressed */ +#endif + +/* handlers for OEM <--> ANSI string conversions */ +#ifdef __RSXNT__ + /* RSXNT uses OEM coded strings in functions supplied by C RTL */ +# ifdef CRTL_CP_IS_ISO +# undef CRTL_CP_IS_ISO +# endif +# ifndef CRTL_CP_IS_OEM +# define CRTL_CP_IS_OEM +# endif +#else + /* "real" native WIN32 compilers use ANSI coded strings in C RTL calls */ +# ifndef CRTL_CP_IS_ISO +# define CRTL_CP_IS_ISO +# endif +# ifdef CRTL_CP_IS_OEM +# undef CRTL_CP_IS_OEM +# endif +#endif + +#ifdef CRTL_CP_IS_ISO + /* C RTL's file system support assumes ANSI coded strings */ +# 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 /* CRTL_CP_IS_ISO */ +#ifdef CRTL_CP_IS_OEM + /* C RTL's file system support assumes OEM coded strings */ +# 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 /* CRTL_CP_IS_OEM */ +#define _OEM_INTERN(str1) OEM_TO_INTERN(str1, str1) +#define _ISO_INTERN(str1) ISO_TO_INTERN(str1, str1) +#ifndef WINDLL + /* Despite best intentions, for the command-line version UzpPassword() + * could return either character set, depending on whether running under + * Win95 (DOS-session) or WinNT (native WinNT command interpreter)! */ +# define STR_TO_CP2(dst, src) (AnsiToOem(src, dst), dst) +# define STR_TO_CP3(dst, src) (OemToAnsi(src, dst), dst) +#else + /* The WINDLL front end is known to supply ISO/ANSI-coded passwords! */ +# define STR_TO_CP2(dst, src) (AnsiToOem(src, dst), dst) +#endif +/* dummy defines to disable these functions, they are not needed */ +#define STR_TO_OEM +#define STR_TO_ISO + +/* Static variables that we have to add to Uz_Globs: */ +#define SYSTEM_SPECIFIC_GLOBALS \ + int created_dir, renamed_fullpath, fnlen;\ + unsigned nLabelDrive;\ + char lastRootPath[4];\ + int lastVolOldFAT, lastVolLocTim;\ + char *rootpath, *buildpathHPFS, *buildpathFAT, *endHPFS, *endFAT;\ + char *dirname, *wildname, matchname[FILNAMSIZ];\ + int rootlen, have_dirname, dirnamelen, notfirstcall;\ + zvoid *wild_dir; + +/* created_dir, renamed_fullpath, fnlen, and nLabelDrive are used by */ +/* both mapname() and checkdir(). */ +/* lastRootPath and lastVolOldFAT are used by IsVolumeOldFAT(). */ +/* rootlen, rootpath, buildpathHPFS, buildpathFAT, endHPFS, and endFAT */ +/* are used by checkdir(). */ +/* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */ +/* and notfirstcall are used by do_wild(). */ + +#if (defined(_MSC_VER) && !defined(MSC)) +# define MSC +#endif + +/* This replacement for C-RTL-supplied getch() (or similar) functionality + * avoids leaving unabsorbed LFs in the keyboard buffer under Windows95, + * and supports the +[0] feature. + */ +int getch_win32 OF((void)); + +/* This patch of stat() is useful for at least two compilers. It is */ +/* difficult to take a stat() of a root directory under Windows95, so */ +/* zstat_win32() detects that case and fills in suitable values. */ +#ifndef __RSXNT__ +# ifndef W32_STATROOT_FIX +# define W32_STATROOT_FIX +# endif +#endif /* !__RSXNT__ */ + +#if (defined(NT_TZBUG_WORKAROUND) || defined(W32_STATROOT_FIX)) +# define W32_STAT_BANDAID +# if (defined(NT_TZBUG_WORKAROUND) && defined(REENTRANT)) +# define __W32STAT_GLOBALS__ Uz_Globs *pG, +# define __W32STAT_G__ pG, +# else +# define __W32STAT_GLOBALS__ +# define __W32STAT_G__ +# endif +# undef SSTAT +# ifdef WILD_STAT_BUG +# define SSTAT(path, pbuf) (iswild(path) || zstat_win32(__W32STAT_G__ path, pbuf)) +# else +# define SSTAT(path, pbuf) zstat_win32(__W32STAT_G__ path, pbuf) +# endif +#endif + +#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 */ +# endif /* __386__ */ + +# ifndef EPIPE +# define EPIPE -1 +# endif +# define PIPE_ERROR (errno == EPIPE) +#endif /* __WATCOMC__ */ + +#endif /* !__w32cfg_h */ diff --git a/utils/Install/inczip/zip.h b/utils/Install/inczip/zip.h new file mode 100644 index 0000000000..5c079467f7 --- /dev/null +++ b/utils/Install/inczip/zip.h @@ -0,0 +1,15 @@ +/* This is a dummy zip.h to allow the source files shared with Zip (crypt.c, + crc32.c, crctab.c, ttyio.c) to compile for UnZip. */ + +#ifndef __zip_h /* don't include more than once */ +#define __zip_h + +#define UNZIP_INTERNAL +#include "unzip.h" + +#define local static + +#define ZE_MEM PK_MEM +#define ziperr(c, h) return + +#endif /* !__zip_h */ diff --git a/utils/Install/install.c b/utils/Install/install.c new file mode 100644 index 0000000000..1c29ce6a36 --- /dev/null +++ b/utils/Install/install.c @@ -0,0 +1,1081 @@ +/* + * install.c (c) 1998,1999 Brian Smith + * parts by Daniele Vistalli + */ + +#include +#include +#include +#include +#include +#include +#if defined(__OS2__) || defined(__EMX__) || defined(WINNT) || defined(WIN32) +#include +#endif +#include +#include "install.h" +#include "instsup.h" + +#if !defined(__EMX__) && !defined(__OS2__) && !defined(WIN32) && !defined(WINNT) +#define stricmp strcasecmp +#endif + +/* My Global variables ;) unusually many due to multiple dialogs */ +char tempPath[MAX_PATH]; +int installstate = NONE; +int installstage = 0; +int current_file=0, success=0; +unsigned long int acepos=0, aceoffset=0; +int pixels=0; +char confirmstring[1024]; +/* I know I am being excessive but... better safe than sorry ;) */ +char *configsys[8196]; +int configfilecount=-1; +int files = 0, files_deleted=0, packagesize=0, packagesselected[20]; +/* Global flags often set by the user */ +int driveselected, packagechosen, express = 1, driverstatus = -1, no_update = 0; +int licensechecked = 0, custom = 0, checkforupdate = 1, downloadsite = 0; +int usescitech = 1, usecurrent = 0, checking = 0, checkerror = 0, newerver = 0; +char sddfilename[256] = "", sddversion[256] = "", sdddate[256] = ""; +char sddurl[4][256] = { "", "", "", "" }; + +/* So these are accessible to REXX */ +int drivelist[26]; +FILE *self; + +/* These get loaded in loadheader */ +char *INSTALLER_APPLICATION; +char *INSTALLER_VERSION; +char *INSTALLER_TITLE; +char *INSTALLER_PATH; +char *INSTALLER_FOLDER; +char *INSTALLER_PROGRAM; +char *INSTALLER_SHADOW; +char *INSTALLER_OBJECT; +char *INSTALLER_SETS; +char *INSTALLER_SYSVAR; +char *INSTALLER_SYSLINE; +char *INSTALLER_PACKAGES[20]; +char *INSTALLER_CONFIRM_WPS; +char *INSTALLER_CONFIRM_CONFIGSYS; +char *INSTALLER_CONFIRM_OVERWRITE; +int INSTALLER_PACKAGE_COUNT; + +/* Will have to seperate this stuff to platform specifics... */ + +/* Config.Sys -- Note the drive letter gets replaced with the boot drive letter + It is just a place holder. (For the next 3 entries) */ +char csfile[] = "C:\\CONFIG.SYS"; +/* Backup Config.Sys filename */ +char bufile[] = "C:\\CONFIG.SDD"; +/* Installation Log Database -- Used for uninstallation and aborting */ +#if defined(__OS2__) || defined(__EMX__) || defined(WINNT) || defined(WIN32) +char instlog[] = "C:\\DBINST.LOG"; +#else +char instlog[] = "~/dbinst.log"; +#endif +char installdir[400]; + +char bootdrive[2] = "C"; +char winpath[400] = "C:\\OS2\\MDOS\\WINOS2"; +char winjpath[400] = "C:\\OS2\\MDOS\\WINJOS2"; +char wintpath[400] = "C:\\OS2\\MDOS\\WINTOS2"; +char winhpath[400] = "C:\\OS2\\MDOS\\WINHOS2"; +char browsedir[400] = "C:\\"; +char installdir2[400] = ""; +char empty_string[] = ""; +char currentcf[400] = ""; + +#ifdef ENABLE_LOGGING +FILE *logfile; +#endif + +/* Function prototypes */ +int installer_unpack(char *filename, int operation); +void resetglobals(void); + +typedef struct _replacements { + char *replacestring, *replacevar; +} Replacements; + +/* The variables in this array must be static buffers */ +Replacements InstRep[] = { + { "%INSTALLPATH%", installdir }, + { "%BOOTDRIVE%", bootdrive }, + { "%ANYSTRING%", empty_string }, + { "%WINPATH%", winpath }, + { "%WINJPATH%", winjpath }, + { "%WINTPATH%", wintpath }, + { "%WINHPATH%", winhpath }, + { "%USERPATH%", installdir2 }, + { "%VERSION%", "1.0" }, /* This may be depricated */ + { "%WEB_VER%", sddversion }, + { "%WEB_DATE%", sdddate }, + { "%WEB_LOCATION1%", sddurl[0] }, + { "%WEB_LOCATION2%", sddurl[1] }, + { "%WEB_LOCATION3%", sddurl[2] }, + { "%WEB_LOCATION4%", sddurl[3] }, + { "%PRI%", "SVGA" } +}; +int replacemax = 16; + +/* In str1, str2 gets replaced by str3 */ +char *replacestr(char *str1, char *str2, char *str3) +{ + char bigbuffer[4096]; + int z, x=0, len1 = strlen(str1), len2 = strlen(str2), len3 = strlen(str3); + + for(z=0;z 0 && strncmp(&str1[z], str2, len2)==0) + { + int i; + for(i=0;i (packagesize-(curpos-aceoffset))) + readit = (packagesize-(curpos-aceoffset)); + else + readit = count; + + return fread(buf, 1, readit, self); +} + +off_t acelseek(off_t offset, int whence) +{ + switch(whence) + { + case SEEK_SET: + fseek(self, aceoffset+offset, SEEK_SET); + break; + case SEEK_CUR: + fseek(self, offset, SEEK_CUR); + break; + } + acepos = ftell(self); + return acepos-aceoffset; +} + +int aceopen(const char *path, int flags) +{ + fseek(self, aceoffset, SEEK_SET); + return 1; +} + +int aceclose(int fd) +{ + fseek(self, aceoffset, SEEK_SET); + return 0; +} + +int acesize(void) +{ + return packagesize; +} + +int acetell(int fd) +{ + return ftell(self)-aceoffset; +} + +/* + * Read the generated log file and remove any files installed. + */ +void delete_files(void) +{ + char tmpbuf[8196], *fileptr; + FILE *tmplf; + int linenum=0, found=-1, z; + + files_deleted=1; + + if((tmplf=fopen(instlog, "rb"))==NULL) + return; + + while(!feof(tmplf)) + { + fgets(tmpbuf, 8196, tmplf); + linenum++; + if(tmpbuf[0]=='[' && (char *)strstr(tmpbuf, INSTALLER_APPLICATION) != NULL && !feof(tmplf)) + { + fgets(tmpbuf, 8196, tmplf); + linenum++; + if((char *)strstr(tmpbuf, "") != NULL && (char *)strstr(tmpbuf, INSTALLER_VERSION) != NULL) + found=linenum; + } + } + if(found != -1) + { + rewind(tmplf); + for (z=0;z") != NULL) + { + fileptr = (char *)strchr(tmpbuf, ',')+1; + /* Remove trailing CRLFs */ + if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n') + fileptr[strlen(fileptr)-1]=0; + if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n') + fileptr[strlen(fileptr)-1]=0; + remove(fileptr); + current_file--; +#if 0 + sendmessage(0, 1); +#endif + } + if((char *)strstr(tmpbuf, "") != NULL) + { + fclose(tmplf); + return; + } + } + } + fclose(tmplf); + return; +} + +/* + * Reads a config file into memory for editing with updatesys, updateset, etc. + */ +int readconfigfile(char *filename) +{ + char tmpbuf[8196]; + FILE *tmpcs; + + /* Reset this value when restarting */ + configfilecount = -1; + + if((tmpcs=fopen(filename, "rb"))==NULL) + { + strcpy(currentcf, empty_string); + return 1; + } + else + strcpy(currentcf, filename); + + while(!feof(tmpcs)) + { + configfilecount++; + fgets(tmpbuf, 8196, tmpcs); + configsys[configfilecount] = malloc(strlen(tmpbuf)+1); + strcpy(configsys[configfilecount], tmpbuf); + stripcrlf(configsys[configfilecount]); + } + + fclose(tmpcs); + return 0; +} + +/* + * Write the updated config file to disk and backup the original. + */ +int writeconfigfile(char *filename, char *backup) +{ + FILE *tmpcs; + int i; + + if(backup) + { + remove(backup); + rename(filename, backup); + } + else + remove(filename); + + if((tmpcs=fopen(filename, "wb"))==NULL) + return 1; + + for(i=0;i,%s,%s\r\n", currentcf, configsys[i]); +#endif + free(configsys[i]); + configsys[i] = malloc(strlen(setname)+strlen(nv)+6); + strcpy(configsys[i], "SET "); + strcat(configsys[i], setname); + strcat(configsys[i], "="); + strcat(configsys[i], nv); +#ifdef ENABLE_LOGGING + fprintf(logfile, ",%s,%s\r\n", currentcf, configsys[i]); +#endif + free(cmpbuf1);free(cmpbuf2);free(tmpptr); + } + return; + } + free(cmpbuf2); + } + free(tmpptr); + } + } + /* Couldn't find the line so we'll add it */ + configsys[configfilecount]=malloc(strlen(cmpbuf1)+strlen(nv)+6); + strcpy(configsys[configfilecount], "SET "); + strcat(configsys[configfilecount], setname); + strcat(configsys[configfilecount], "="); + strcat(configsys[configfilecount], nv); +#ifdef ENABLE_LOGGING + fprintf(logfile, ",%s,%s\r\n", currentcf, configsys[configfilecount]); +#endif + configfilecount++; + free(cmpbuf1); +} + +/* + * Adds an entry to a system variable (CONFIG.SYS) + */ +void updatesys(char *sysname, char *newvalue) +{ + char *cmpbuf1, *cmpbuf2, *tmpptr, *tmpptr2, *capbuf1, *capbuf2, *nv, *brian; + int i, z, t; + + nv=replaceem(newvalue); + + cmpbuf1=malloc(strlen(sysname)+2); + strcpy(cmpbuf1, sysname); + strcat(cmpbuf1, "="); + for(i=0;i,%s,%s\r\n", currentcf, configsys[i]); +#endif + brian = configsys[i]; + configsys[i] = malloc(strlen(configsys[i])+strlen(nv)+4); + strcpy(configsys[i], brian); + free(brian); + /* Remove any trailing CRLFs */ + if(configsys[i][strlen(configsys[i])-1]!=';') + strcat(configsys[i], ";"); + strcat(configsys[i], nv); + strcat(configsys[i], ";"); +#ifdef ENABLE_LOGGING + fprintf(logfile, ",%s,%s\r\n", currentcf, configsys[i]); +#endif + } + free(cmpbuf1);free(cmpbuf2);free(capbuf1);free(capbuf2); + return; + } + free(cmpbuf2); + } + } + /* Couldn't find the line so we'll add it */ + configsys[configfilecount]=malloc(strlen(cmpbuf1)+strlen(nv)+3); + strcpy(configsys[configfilecount], cmpbuf1); + strcat(configsys[configfilecount], nv); + strcat(configsys[configfilecount], ";"); +#ifdef ENABLE_LOGGING + fprintf(logfile, ",%s,%s", currentcf, configsys[configfilecount]); +#endif + configfilecount++; + free(cmpbuf1); + if(nv) + free(nv); +} + +/* + * Removes a line from a config file. + */ +void removeline(char *text) +{ + int z; + for(z=0;z,%s,%s\r\n", currentcf, configsys[z]); +#endif + free(configsys[z]); + for(t=z;t<(configfilecount-1);t++) + configsys[t] = configsys[t+1]; + configfilecount--; + } + } +} + + +/* + * The Window peocedure for the confirmation dialog. + */ +#if 0 +MRESULT EXPENTRY ConfirmDlgProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + SWP winpos; + + switch (msg) + { + case WM_INITDLG: + WinSetWindowText(hWnd, INSTALLER_TITLE); + WinEnableWindow(WinWindowFromID(mainhwnd, I_Cancel), FALSE); + WinSetDlgItemText(hWnd, I_Confirm, confirmstring); + WinQueryWindowPos(mainhwnd, &winpos); + WinSetWindowPos(hWnd, HWND_TOP, winpos.x+30, winpos.y+30, 0, 0, SWP_MOVE | SWP_ZORDER); + break; + case WM_COMMAND: + WinEnableWindow(WinWindowFromID(mainhwnd, I_Cancel), TRUE); + switch ( SHORT1FROMMP(mp1) ) + { + case I_Ja: + WinDismissDlg(hWnd, 0); + break; + case I_Alle: + WinDismissDlg(hWnd, 1); + break; + case I_Nein: + WinDismissDlg(hWnd, 2); + break; + case I_Halt: + success=2; + installstate=ABORTED; + WinDismissDlg(hWnd, 3); + break; + } + break; + default : + return(WinDefDlgProc(hWnd, msg, mp1, mp2)); + } + return(0L); +} +#endif +/* + * Display a confirmation dialog with the options: YES NO ALL CANCEL + * Returns: 0 for YES, 1 for ALL, 2 for NO and 3 for CANCEL + */ +int confirm(char *format, ...) { + va_list args; + + /* if no confirmation, return 1, meaning overwrite all */ + if (stricmp(INSTALLER_CONFIRM_OVERWRITE, "no") == 0) + return 1; + + va_start(args, format); + vsprintf(confirmstring, format, args); + va_end(args); + + /* Do something here in wxwindows */ + return 1; +} + +/* + * A function to grab a file from an embedded archive and extract it to the TEMP directory. + */ +void grabfile(char *filename) +{ + no_update = 1; + settempdir(); + remove(filename); + aceseek_entry(0); + resetglobals(); + installer_unpack(filename, 2); + no_update = 0; +} + +/* + * This thread runs along side the main thread allowing the user to cancel the process. + */ +void install_thread(void *param) +{ + char tmpinstallpath[1024]; + int k, j, installcount=0, installed=0; + + if(INSTALLER_PACKAGE_COUNT == 2) + packagesselected[1] = TRUE; + + installstate = INSTALLING; + +#ifdef ENABLE_LOGGING + if((logfile=fopen(instlog, "ab"))==NULL) + { + error("Log file \"%s\" open failed! Installation aborted!", instlog); + exit(1); + } + + fprintf(logfile, "[%s]\r\n,%s\r\n\r\n", INSTALLER_APPLICATION, INSTALLER_VERSION); +#endif + + /* Create nested subdirectories if necessary. */ + strcpy(tmpinstallpath, installdir); + for(k=3;k,%s\r\n", tmpinstallpath); +#else + ; +#endif + tmpinstallpath[k] = '\\'; + } + } + +#if defined(__EMX__) || defined(__CYGWIN__) || defined(UNIX) + if (!mkdir(installdir, 0)) +#else + if (!mkdir(installdir)) +#endif +#ifdef ENABLE_LOGGING + fprintf(logfile, ",%s\r\n", installdir); +#else + ; +#endif + + /*if(strlen(installdir) > 0 && installdir[0] > 'a'-1 && installdir[0] < 'z'+1) + installdir[0]=installdir[0] - ('a'-'A'); + if(strlen(installdir)>2 && installdir[1]==':' && installdir[2]=='\\') + DosSetDefaultDisk((int)(installdir[0]-'A'+1));*/ + + setdrivedir(installdir); + + /* Unpack files to destination directory */ + for(j=1;j0) + { + char *tmpptr = &temp[0]; + int len; + + strcpy(temp, INSTALLER_SYSLINE); + temp[4999] = 0; + len = strlen(temp); + + for(z=0;z,%s,%s\r\n", currentcf, tmpptr2); +#endif + configfilecount++; + } + } + if(tmpptr && *tmpptr) + { + char *tmpptr2; + + tmpptr2 = replaceem(tmpptr); + removeline(tmpptr2); + configsys[configfilecount] = tmpptr2; +#ifdef ENABLE_LOGGING + fprintf(logfile, ",%s,%s\r\n", currentcf, tmpptr2); +#endif + configfilecount++; + } + + } + /* Update SET variables */ + if(strlen(INSTALLER_SETS)>0) + { + strcpy(temp, INSTALLER_SETS); + argn=0; + arg1=&temp[0]; + arg2=arg3=NULL; + for(z=0;z0) + { + strcpy(temp, INSTALLER_SYSVAR); + argn=0; + arg1=&temp[0]; + arg2=NULL; + for(z=0;z +#include +#include +#include +#include +#include +#if defined(__OS2__) || defined(__EMX__) || defined(WIN32) || defined(WINNT) +#include +#endif +#include +#include "install.h" +#include "instsup.h" + +extern char *INSTALLER_TITLE; +extern char tempPath[], installdir[], csfile[], bufile[], bootdrive[], instlog[]; +extern int installstate, success; + +extern FILE *self; + +#ifdef __cplusplus +extern "C" { +#endif + +char *replaceem(char *orig); + +int sendmessage(int destination, int messid) +{ +#if 0 + /* Update percentage bar */ + if(messid == 1) + { + wxMutexGuiEnter(); + + updatepercent(); + + wxMutexGuiLeave(); + } + if(messid == 2) + { + extern wxCondition *InstCond; + + InstCond->Broadcast(); + } + +#endif + return 0; +} + +void DoGUI(void) +{ + updatepercent(); + wxYield(); +} +/* This should return the current color depth */ +unsigned long color_depth(void) +{ +#if 0 + HDC hdc = WinOpenWindowDC(HWND_DESKTOP); + LONG colors; + + DevQueryCaps(hdc, CAPS_COLORS, 1, &colors); + DevCloseDC(hdc); + return colors; +#endif + return 0; +} + +/* + * Call the reboot vector. + */ +void sysreboot(void) +{ +#if 0 +#define SYSFUNC 0xD5 +#define REBOOT 0xAB +#define REBOOTDEV "\\DEV\\DOS$" + + APIRET rc; + HFILE hREBOOT; + ULONG ulAction; + + rc = DosOpen(REBOOTDEV, + &hREBOOT, + &ulAction, + 0L, + FILE_NORMAL, + FILE_OPEN, + OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, + 0L); + if (rc == 0) + { + DosDevIOCtl(hREBOOT, + SYSFUNC, + REBOOT, + NULL, + 0L, + NULL, + NULL, + 0L, + NULL); + DosClose(hREBOOT); + } +#endif +} + +/* + * Display an informational dialog box to the user with the given text. + */ +int mesg(char *format, ...) { + va_list args; + char outbuf[4096]; + + va_start(args, format); + vsprintf(outbuf, format, args); + va_end(args); + + wxMessageBox(outbuf, INSTALLER_TITLE, + wxOK | wxICON_EXCLAMATION, NULL); + + return strlen(outbuf); +} + +int checktext(char *text, char *buffer, int buflen) +{ + int z, len = strlen(text); + + for(z=0;z<(buflen-len);z++) + { + if(memcmp(text, &buffer[z], len) == 0) + return z; + } + return -1; + +} + +/* + * Returns the offset withing the executable to the specified text. + */ +long findtext(char *text) +{ + char buffer[512]; + int offset; + unsigned long curpos = 0; + + fseek(self, 0, SEEK_SET); + fread(buffer, 1, 512, self); + if((offset = checktext(text, buffer, 512)) > -1) + return offset; + while(!feof(self)) + { + memcpy(buffer, &buffer[256], 256); + fread(&buffer[256], 1, 256, self); + curpos += 256; + if((offset = checktext(text, buffer, 512)) > -1) + return offset+curpos; + + } + return -1; +} + +/* We encode archive search text so we don't get confused + * by the string table - I was using LXLite to take care + * of this problem on OS/2 but in portable code this may + * not be an option. */ +char *decode(char *input) +{ + char *result; + int i = 0; + + result = (char *)malloc(strlen(input) / 2 + 1); + + while (input[0] && input[1]) + { + result[i] = ((input[0] - 0x41) << 4) | (input[1] - 0x41); + input += 2; + i++; + } + result[i] = '\0'; + + return result; +} + +/* + * Opens a Window which contains the text specfied by given filename. + */ +void viewfile(char *filename) +{ +#if 0 + HWND hwndFrame, /*hwndMLE,*/ hwndClient; + ULONG flStyle = FCF_MINMAX | FCF_SYSMENU | FCF_TITLEBAR | + FCF_SIZEBORDER | FCF_SHELLPOSITION | FCF_TASKLIST; + PPRESPARAMS ppp; + char deffont[] = "9.Warpsans"; + + WinRegisterClass(localhab, "VIEW", ViewWndProc, CS_SIZEREDRAW, 32); + + hwndFrame = WinCreateStdWindow(HWND_DESKTOP, + WS_VISIBLE | WS_MAXIMIZED, + &flStyle, + "VIEW", + filename, + 0L, + NULLHANDLE, + 0L, + &hwndClient); + + ppp = malloc((sizeof(ULONG) * 3) + strlen(deffont) + 1); + ppp->cb = (sizeof(ULONG) * 2) + strlen(deffont) + 1; + ppp->aparam[0].id = PP_FONTNAMESIZE; + ppp->aparam[0].cb = strlen(deffont)+1; + memcpy(&ppp->aparam[0].ab, deffont, strlen(deffont)+1); + + hwndMLE = WinCreateWindow(hwndFrame, + WC_MLE, + "", + WS_VISIBLE | MLS_VSCROLL | MLS_WORDWRAP | MLS_READONLY | MLS_BORDER, + 0,0,100,100, + hwndFrame, + HWND_TOP, + 999L, + NULL, + ppp); + + WinSetWindowPos(hwndFrame, HWND_TOP, 0,0,0,0,SWP_MAXIMIZE | SWP_ZORDER); + WinSetWindowPos(hwndMLE, HWND_TOP, 0,0,0,0,SWP_SHOW); + + if(!hwndMLE) + { + mesg("Error %lu while creating MLE window.", WinGetLastError(localhab)); + } + else + { + FILE *f; + char buffer[1024]; + ULONG bytes, point = -1; + + if((f = fopen(filename, "rb")) != NULL) + { + WinSendMsg(hwndMLE, MLM_SETIMPORTEXPORT, MPFROMP(buffer), MPFROMLONG(1024L)); + while(!feof(f)) + { + bytes = fread(buffer, 1, 1024, f); + WinSendMsg(hwndMLE, MLM_IMPORT, MPFROMP(&point), MPFROMLONG(bytes)); + } + fclose(f); + } + +} +#endif +} + +/* + * Removes any carriage returns or line feeds from the buffer. + */ +void stripcrlf(char *buffer) +{ + int z, len = strlen(buffer); + + for(z=0;z 3 && tempPath[len-1] == '\\') + tempPath[len-1] = 0; + strupr(tempPath); + setdrivedir(tempPath); +#else + setdrivedir("/tmp"); +#endif +} + +void getbootdrive(void) +{ + /* On windows I don't think you can boot from anything + except C: drive. So I am not going to do anything here. */ +} +/* + * Start an application using CMD.EXE. + */ +int cmdrun(char *progname) +{ +#if 0 + STARTDATA SData = {0}; + PSZ PgmTitle = "", + PgmName = "CMD.EXE"; + APIRET rc = NO_ERROR; + PID pid = 0; + ULONG ulSessID = 0; + CHAR achObjBuf[256] = {0}; + HQUEUE hqQueue; + REQUESTDATA rdRequest; + ULONG ulSzData; + BYTE bPriority; + PVOID pvData; + + SData.Length = sizeof(STARTDATA); + SData.Related = SSF_RELATED_CHILD; + SData.FgBg = SSF_FGBG_BACK; + SData.TraceOpt = SSF_TRACEOPT_NONE; + SData.PgmTitle = PgmTitle; + SData.PgmName = PgmName; + SData.PgmInputs = progname; + + SData.TermQ = "\\QUEUES\\CHILD.QUE"; + SData.Environment = 0; + SData.InheritOpt = SSF_INHERTOPT_SHELL; + SData.SessionType = SSF_TYPE_WINDOWABLEVIO; + SData.IconFile = 0; + SData.PgmHandle = 0; + + SData.PgmControl = SSF_CONTROL_INVISIBLE; + SData.Reserved = 0; + SData.ObjectBuffer = achObjBuf; + SData.ObjectBuffLen = (ULONG) sizeof(achObjBuf); + + if(!(rc = DosCreateQueue(&hqQueue, QUE_FIFO | QUE_CONVERT_ADDRESS,"\\QUEUES\\CHILD.QUE"))) + { + if(!(rc = DosStartSession(&SData, &ulSessID, &pid))) + if(!(rc=DosReadQueue(hqQueue, &rdRequest, &ulSzData, &pvData, 0, 0, &bPriority, 0))) + DosFreeMem(pvData); + DosCloseQueue(hqQueue); + } + + if (rc != NO_ERROR) { + mesg("Error %d while attempting to run %s!", rc, progname); + return 1; + } + return NO_ERROR; +#endif + return 0; +} + +void PM_backslash(char *s) +{ + unsigned int pos = strlen(s); + if (s[pos-1] != '\\') { + s[pos] = '\\'; + s[pos+1] = '\0'; + } +} +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/utils/Install/instsup.h b/utils/Install/instsup.h new file mode 100644 index 0000000000..912c0fe95a --- /dev/null +++ b/utils/Install/instsup.h @@ -0,0 +1,25 @@ +#ifdef __cplusplus +extern "C" { +#endif +unsigned long color_depth(void); +void sysreboot(void); +int mesg(char *format, ...); +int checktext(char *text, char *buffer, int buflen); +long findtext(char *text); +char *decode(char *input); +void viewfile(char *filename); +void stripcrlf(char *buffer); +unsigned long drivefree(int drive); +void error(char *format, ...); +void setdrivedir(char *drivedir); +void settempdir(void); +void getbootdrive(void); +int cmdrun(char *progname); +void PM_backslash(char *s); +int sendmessage(int destination, int messid); +void DoGUI(void); +#ifdef __cplusplus +} +#endif +int parse_ini(char *filename); +void updatepercent(void); \ No newline at end of file diff --git a/utils/Install/packace/globals.c b/utils/Install/packace/globals.c new file mode 100644 index 0000000000..b28c4f22c0 --- /dev/null +++ b/utils/Install/packace/globals.c @@ -0,0 +1,134 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* Global variable declarations */ +/* */ +/* ------------------------------------------------------------------------ */ + +#include "os.h" + +#include "acestruc.h" +#include "unace.h" + +#include +#include + +//-------- Ace sign +const char *acesign = "**ACE**"; + +//-------- Version string for program +const char *version="UNACE v1.1 public version\n"; + +#ifdef AMIGA +//-------- Version string for VERSION program +static char *_version="$VER: Unace Amiga 1.1 "__AMIGADATE__"\n\n"; +#endif + +//-------- header buffer and pointers +thead head; + +tmhead *t_mhead = (tmhead *) & head; +tfhead *t_fhead = (tfhead *) & head; + +//-------- buffers +ULONG *buf_rd =0; +CHAR *buf =0; +CHAR *buf_wr =0; +UCHAR *readbuf =0; + +//-------- decompressor variables +SHORT rpos =0, + dcpr_do =0, + dcpr_do_max =0, + blocksize =0, + dcpr_dic =0, + dcpr_oldnum =0, + bits_rd =0, + dcpr_frst_file =0; +USHORT dcpr_code_mn[1 << maxwd_mn], + dcpr_code_lg[1 << maxwd_lg]; +UCHAR dcpr_wd_mn[maxcode + 2], + dcpr_wd_lg[maxcode + 2], + wd_svwd[svwd_cnt]; +ULONG dcpr_dpos =0, + cpr_dpos2 =0, + dcpr_dicsiz =0, + dcpr_dican =0, + dcpr_size =0, + dcpr_olddist[4]={0,0,0,0}, + code_rd =0; + +CHAR *dcpr_text =0; + +//-------- quicksort +USHORT sort_org[maxcode + 2]; +UCHAR sort_freq[(maxcode + 2) * 2]; + +//-------- file handling +CHAR aname[PATH_MAX]; +INT archan, + wrhan; +#if !defined(__EMX__) && !defined(__OS2__) +FILE *farchan = NULL; +#endif +LONG skipsize=0; + +//-------- structures for archive handling +struct tadat adat; + +//-------- flags +INT f_err =0, + f_ovrall =0, + f_allvol_pr=0, + f_curpas =0, + f_criterr =0; + + +void resetglobals(void) +{ + t_mhead = (tmhead *) & head; + t_fhead = (tfhead *) & head; + + buf_rd =0; + buf =0; + buf_wr =0; + readbuf =0; + + rpos =0; + dcpr_do =0; + dcpr_do_max =0; + blocksize =0; + dcpr_dic =0; + dcpr_oldnum =0; + bits_rd =0; + dcpr_frst_file =0; + + memset(&dcpr_code_mn, 0, sizeof(dcpr_code_mn)); + memset(&dcpr_code_lg, 0, sizeof(dcpr_code_lg)); + memset(&dcpr_wd_mn, 0, sizeof(dcpr_wd_mn)); + memset(&dcpr_wd_lg, 0, sizeof(dcpr_wd_lg)); + memset(&wd_svwd, 0, sizeof(wd_svwd)); + dcpr_dpos =0; + cpr_dpos2 =0; + dcpr_dicsiz =0; + dcpr_dican =0; + dcpr_size =0; + + memset(&dcpr_olddist, 0, sizeof(dcpr_olddist)); + + code_rd =0; + dcpr_text =0; + + memset(&sort_org, 0, sizeof(sort_org)); + memset(&sort_freq, 0, sizeof(sort_freq)); + + archan=0; + wrhan=0; + skipsize=0; + + f_err =0; + f_ovrall =0; + f_allvol_pr=0; + f_curpas =0; + f_criterr =0; + +} diff --git a/utils/Install/packace/makefile b/utils/Install/packace/makefile new file mode 100644 index 0000000000..837e7878d0 --- /dev/null +++ b/utils/Install/packace/makefile @@ -0,0 +1,46 @@ +# Installer Makefile + +CC = gcc +RM = rm -f +RC = rc +MAKE = make + +DEFS = +LIBS = + +CFLAGS = -O -g -I../incace -Wall +LDFLAGS = + + +OBJECTS = globals.o packinst.o uac_comm.o uac_crc.o \ + uac_crt.o uac_dcpr.o uac_sys.o unace.o + +SOURCES = globals.c ../packinst/packinst.c uac_comm.c \ + uac_crc.c uac_crt.c uac_dcpr.c uac_sys.c unace.c + +all: packinst + +$(OBJECTS): + $(CC) $(CFLAGS) -c $< + +Include: ../incace/Makefile Makefile +# cd include +# $(MAKE) -f Makefile all + +packinst: $(OBJECTS) + $(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o packinst $(OBJECTS) + +clean: + $(RM) $(OBJECTS) packinst *~ + +globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h +packinst.o: ../packinst/packinst.c +uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h +uac_crc.o: uac_crc.c ../incace/uac_crc.h +uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h +uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \ + ../incace/uac_dcpr.h ../incace/uac_sys.h +uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h +unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \ + ../incace/uac_dcpr.h ../incace/uac_sys.h + diff --git a/utils/Install/packace/makefile.b32 b/utils/Install/packace/makefile.b32 new file mode 100644 index 0000000000..d2cece68fc --- /dev/null +++ b/utils/Install/packace/makefile.b32 @@ -0,0 +1,41 @@ +# Common settings for Borland 32-bit compilation (makefile.b32 files) + +LINK=ilink32 + +OPT = -O2 +LDFLAGS = -lxncd -l-P +CPPFLAGS = /I"..\incace" /DWIN32 +LINKFLAGS=/aa -L$(BCCDIR)\lib\psdk + +DUMMY=dummy + +SRCSUFF = cpp +OBJSUFF = obj + +TARGET = packinst +OBJECTS = globals.obj uac_comm.obj uac_crc.obj uac_crt.obj uac_dcpr.obj uac_sys.obj unace.obj packinst.obj + +all: $(TARGET).exe + +packinst.exe: $(OBJECTS) + bcc32 $(LDFLAGS) -epackinst.exe @&&| +$(OBJECTS) +| + +.$(SRCSUFF).obj: + bcc32 $(CPPFLAGS) -c {$< } + +packinst.obj: ..\packinst\packinst.c + bcc32 $(CPPFLAGS) -P- -c ..\packinst\packinst.c + +.c.obj: + bcc32 $(CPPFLAGS) -P- -c {$< } + +clean: + -erase *.obj + -erase *.exe + -erase *.res + -erase *.map + -erase *.rws + -erase *.tds + -erase *.il? diff --git a/utils/Install/packace/makefile.g95 b/utils/Install/packace/makefile.g95 new file mode 100644 index 0000000000..a89a5ddfee --- /dev/null +++ b/utils/Install/packace/makefile.g95 @@ -0,0 +1,46 @@ +# Installer Makefile + +CC = gcc +RM = rm -f +RC = rc +MAKE = make + +DEFS = +LIBS = + +CFLAGS = -mno-cygwin -O -g -I../incace -Wall -DWIN32 +LDFLAGS = -mno-cygwin + + +OBJECTS = globals.o packinst.o uac_comm.o uac_crc.o \ + uac_crt.o uac_dcpr.o uac_sys.o unace.o + +SOURCES = globals.c ../packinst/packinst.c uac_comm.c \ + uac_crc.c uac_crt.c uac_dcpr.c uac_sys.c unace.c + +all: packinst + +$(OBJECTS): + $(CC) $(CFLAGS) -c $< + +Include: ../incace/Makefile Makefile +# cd include +# $(MAKE) -f Makefile all + +packinst: $(OBJECTS) + $(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o packinst $(OBJECTS) + +clean: + $(RM) $(OBJECTS) packinst *~ + +globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h +packinst.o: ../packinst/packinst.c +uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h +uac_crc.o: uac_crc.c ../incace/uac_crc.h +uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h +uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \ + ../incace/uac_dcpr.h ../incace/uac_sys.h +uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h +unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \ + ../incace/uac_dcpr.h ../incace/uac_sys.h + diff --git a/utils/Install/packace/makefile.gcc b/utils/Install/packace/makefile.gcc new file mode 100644 index 0000000000..837e7878d0 --- /dev/null +++ b/utils/Install/packace/makefile.gcc @@ -0,0 +1,46 @@ +# Installer Makefile + +CC = gcc +RM = rm -f +RC = rc +MAKE = make + +DEFS = +LIBS = + +CFLAGS = -O -g -I../incace -Wall +LDFLAGS = + + +OBJECTS = globals.o packinst.o uac_comm.o uac_crc.o \ + uac_crt.o uac_dcpr.o uac_sys.o unace.o + +SOURCES = globals.c ../packinst/packinst.c uac_comm.c \ + uac_crc.c uac_crt.c uac_dcpr.c uac_sys.c unace.c + +all: packinst + +$(OBJECTS): + $(CC) $(CFLAGS) -c $< + +Include: ../incace/Makefile Makefile +# cd include +# $(MAKE) -f Makefile all + +packinst: $(OBJECTS) + $(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o packinst $(OBJECTS) + +clean: + $(RM) $(OBJECTS) packinst *~ + +globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h +packinst.o: ../packinst/packinst.c +uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h +uac_crc.o: uac_crc.c ../incace/uac_crc.h +uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h +uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \ + ../incace/uac_dcpr.h ../incace/uac_sys.h +uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h +unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \ + ../incace/uac_dcpr.h ../incace/uac_sys.h + diff --git a/utils/Install/packace/uac_comm.c b/utils/Install/packace/uac_comm.c new file mode 100644 index 0000000000..d050cf4e4c --- /dev/null +++ b/utils/Install/packace/uac_comm.c @@ -0,0 +1,51 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* Decompresses and outputs comment if present. */ +/* */ +/* ------------------------------------------------------------------------ */ + +#include // printf() + +#include "globals.h" +#include "uac_dcpr.h" +#include "uac_comm.h" + +INT comm_cpr_size=0; +CHAR *comm; + +void comment_out(CHAR *top) // outputs comment if present +{ + INT i; + + if (head.HEAD_FLAGS & ACE_COMM) + { // comment present? + if (head.HEAD_TYPE == MAIN_BLK) + { // get begin and size of comment data + comm = (CHAR *)MCOMM; + comm_cpr_size = MCOMM_SIZE; + } + else + { + comm = (CHAR *)FCOMM; + comm_cpr_size = FCOMM_SIZE; + } // limit comment size if too big + i = sizeof(head) - (INT)(comm - (CHAR*) &head); + if (comm_cpr_size > i) + comm_cpr_size = i; + dcpr_comm(i); // decompress comment + +#ifdef AMIGA + { + char *p=comm; + while (*p) + { + if (*p==0x0D) + *p=0x0A; // Replace ms-dos line termination + p++; + } + } +#endif + + pipeit("%s\n\n%s\n\n", top, comm); // output comment + } +} diff --git a/utils/Install/packace/uac_crc.c b/utils/Install/packace/uac_crc.c new file mode 100644 index 0000000000..3d9335ec72 --- /dev/null +++ b/utils/Install/packace/uac_crc.c @@ -0,0 +1,36 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* CRC-calculation routines. */ +/* */ +/* ------------------------------------------------------------------------ */ + +#include "uac_crc.h" + + +ULONG crctable[256]; +ULONG rd_crc=0; + + +void make_crctable(void) // initializes CRC table +{ + ULONG r, + i, + j; + + for (i = 0; i <= 255; i++) + { + for (r = i, j = 8; j; j--) + r = (r & 1) ? (r >> 1) ^ CRCPOLY : (r >> 1); + crctable[i] = r; + } +} + +// Updates crc from addr till addr+len-1 +// +ULONG getcrc(ULONG crc, UCHAR * addr, INT len) +{ + while (len--) + crc = crctable[(unsigned char) crc ^ (*addr++)] ^ (crc >> 8); + return (crc); +} + diff --git a/utils/Install/packace/uac_crt.c b/utils/Install/packace/uac_crt.c new file mode 100644 index 0000000000..9e20fcd162 --- /dev/null +++ b/utils/Install/packace/uac_crt.c @@ -0,0 +1,149 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* Creates/Replaces files or directories. */ +/* */ +/* ------------------------------------------------------------------------ */ + +#include "os.h" + +#include +#include // AMIGA: open() +#include // pipeit() remove() +#include // strncpy() +#include +#include // struct stat +#include + + +#if defined(DOS) || defined(WINNT) || defined(WIN16) + #include // access() +#endif +#if defined(__IBMC__) + #include +#endif + +#define DIRSEP '\\' + +#include "attribs.h" +#include "globals.h" +#include "uac_crt.h" +#include "uac_sys.h" + +/* gets file name from header + */ +CHAR *ace_fname(CHAR * s, thead * head, INT nopath) +{ + INT i; + char *cp; + + strncpy(s, (CHAR *)(*(tfhead *) head).FNAME, i = (*(tfhead *) head).FNAME_SIZE); + s[i] = 0; + + if (nopath) + { + cp=strrchr(s, '\\'); + if (cp) + memmove(s, cp+1, strlen(cp)); + } + + return s; +} + +void check_ext_dir(CHAR * f) // checks/creates path of file +{ + CHAR *cp, + d[PATH_MAX]; + INT i; + + d[0] = 0; + + for (;;) + { + if ((cp = (CHAR *) strchr(&f[strlen(d) + 1], DIRSEP))!=NULL) + { + i = cp - f; + strncpy(d, f, i); + d[i] = 0; + } + else + return; + + if (!fileexists(d)) +#if (defined(__OS2__) && !defined(__EMX__)) || (defined(WINNT) && !defined(__CYGWIN__)) + if (mkdir(d)) +#else + if (mkdir(d, 0)) +#endif + { + f_err = ERR_WRITE; + pipeit("\n Error while creating directory.\n"); + } + } +} + +INT ovr_delete(CHAR * n) // deletes directory or file +{ + if (remove(n) && rmdir(n)) + { + pipeit("\n Could not delete file or directory. Access denied.\n"); + return (1); + } + return (0); +} + +INT create_dest_file(CHAR * file, INT a) // creates file or directory +{ + INT han, + i = 0, + ex = fileexists(file); + struct stat st; + + check_ext_dir(file); + if (f_err) + return (-1); + if (a & _A_SUBDIR) + { // create dir or file? + if (ex) + stat(file, &st); +#if (defined(__OS2__) && !defined(__EMX__)) || (!defined(__CYGWIN__) && defined(WINNT)) + if ((!ex && mkdir(file)) || (ex && (st.st_mode & S_IFDIR))) +#else + if ((!ex && mkdir(file, 0)) || (ex && (st.st_mode & S_IFDIR))) +#endif + { + pipeit("\n Could not create directory.\n"); + return (-1); + } +#ifdef DOS + _dos_setfileattr(file, a); // set directory attributes +#endif + return (-1); + } + else + { + if (ex) + { // does the file already exist + if (!f_ovrall) + { + i = wrask("Overwrite existing file?"); // prompt for overwrite + f_ovrall = (i == 1); + if (i == 3) + f_err = ERR_USER; + } + if ((i && !f_ovrall) || ovr_delete(file)) + return (-1); // delete? + } +#if defined(__OS2_) || defined(__EMX__) || defined(WIN32) + if ((han = open(file, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, + S_IREAD | S_IWRITE | S_IEXEC | S_IDELETE | + S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH )) < 0) +#else + if ((han = open(file, O_WRONLY | O_TRUNC | O_CREAT, + S_IREAD | S_IWRITE | S_IEXEC | S_IDELETE | + S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH )) < 0) +#endif + pipeit("\n Could not create destination file.\n"); + return (han); + } +} + diff --git a/utils/Install/packace/uac_dcpr.c b/utils/Install/packace/uac_dcpr.c new file mode 100644 index 0000000000..9f1a29b9b3 --- /dev/null +++ b/utils/Install/packace/uac_dcpr.c @@ -0,0 +1,553 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* These are the decompression algorithms. */ +/* Don't change here anything (apart from memory allocation perhaps). */ +/* Any changes will very likely cause bugs! */ +/* */ +/* ------------------------------------------------------------------------ */ + +#include "os.h" + +#if defined(AMIGA) + #include // mem*() +#endif +#if defined(DOS) || defined(WIN16) || defined(WINNT) || defined(OS2) || defined(UNIX) +#if !defined(__CYGWIN__) + #include // mem*() +#endif +#endif + +#include // pipeit() +#include // malloc() +#include + +#include "globals.h" +#include "portable.h" +#include "uac_comm.h" +#include "uac_crc.h" +#include "uac_dcpr.h" +#include "uac_sys.h" +#ifdef CRYPT + #include "unace_ps.h" +#endif /* CRYPT */ + + +//------------------------------ QUICKSORT ---------------------------------// +#define xchg_def(v1,v2) {INT dummy;\ + dummy=v1; \ + v1=v2; \ + v2=dummy;} + +void sortrange(INT left, INT right) +{ + INT zl = left, + zr = right, + hyphen; + + hyphen = sort_freq[right]; + + //divides by hyphen the given range into 2 parts + do + { + while (sort_freq[zl] > hyphen) + zl++; + while (sort_freq[zr] < hyphen) + zr--; + //found a too small (left side) and + //a too big (right side) element-->exchange them + if (zl <= zr) + { + xchg_def(sort_freq[zl], sort_freq[zr]); + xchg_def(sort_org[zl], sort_org[zr]); + zl++; + zr--; + } + } + while (zl < zr); + + //sort partial ranges - when very small, sort directly + if (left < zr) + { + if (left < zr - 1) + sortrange(left, zr); + else if (sort_freq[left] < sort_freq[zr]) + { + xchg_def(sort_freq[left], sort_freq[zr]); + xchg_def(sort_org[left], sort_org[zr]); + } + } + + if (right > zl) + { + if (zl < right - 1) + sortrange(zl, right); + else if (sort_freq[zl] < sort_freq[right]) + { + xchg_def(sort_freq[zl], sort_freq[right]); + xchg_def(sort_org[zl], sort_org[right]); + } + } +} + +void quicksort(INT n) +{ + INT i; + + for (i = n + 1; i--;) + sort_org[i] = i; + sortrange(0, n); +} + +//------------------------------ read bits ---------------------------------// +void readdat(void) +{ + UINT i; + + i = (size_rdb - 2) << 2; + rpos -= size_rdb - 2; + buf_rd[0] = buf_rd[size_rdb - 2]; + buf_rd[1] = buf_rd[size_rdb - 1]; + read_adds_blk((CHAR *) & buf_rd[2], i); +#ifdef HI_LO_BYTE_ORDER + { + ULONG *p; + i>>=2; // count LONGs not BYTEs + p=&buf_rd[2]; + while (i--) + { + LONGswap(p); + p++; + } + } +#endif +} + +#define addbits(bits) \ +{ \ + rpos+=(bits_rd+=bits)>>5; \ + bits_rd&=31; \ + if (rpos==(size_rdb-2)) readdat(); \ + code_rd=(buf_rd[rpos] << bits_rd) \ + +((buf_rd[rpos+1] >> (32-bits_rd))&(!bits_rd-1)); \ + } + + +//---------------------- COMMENT DECOMPRESSION -----------------------------// + +#define comm_cpr_hf(a,b) (a+b) + +void dcpr_comm_init(void) +{ + INT i; + + i = comm_cpr_size > size_rdb * sizeof(LONG) ? size_rdb * sizeof(LONG) : comm_cpr_size; + if (!f_err) + memcpy(buf_rd, comm, i); +#ifdef HI_LO_BYTE_ORDER + { + ULONG *p; + i>>=2; // count LONGs not BYTEs + p=buf_rd; + while (i--) + { + LONGswap(p); + p++; + } + } +#endif + code_rd = buf_rd[0]; + rpos = bits_rd = 0; +} + +void dcpr_comm(INT comm_size) +{ + SHORT hash[comm_cpr_hf(255, 255) + 1]; + INT dpos = 0, + c, + pos = 0, + len, + hs; + + memset(&hash, 0, sizeof(hash)); + if (comm_cpr_size) + { + dcpr_comm_init(); + len = code_rd >> (32 - 15); + addbits(15); + if (len >= comm_size) + len = comm_size - 1; + if (read_wd(maxwd_mn, dcpr_code_mn, dcpr_wd_mn, max_cd_mn)) + do + { + if (dpos > 1) + { + pos = hash[hs = comm_cpr_hf(comm[dpos - 1], comm[dpos - 2])]; + hash[hs] = dpos; + } + addbits(dcpr_wd_mn[(c = dcpr_code_mn[code_rd >> (32 - maxwd_mn)])]); + if (rpos == size_rdb - 3) + rpos = 0; + if (c > 255) + { + c -= 256; + c += 2; + while (c--) + comm[dpos++] = comm[pos++]; + } + else + { + comm[dpos++] = c; + } + } + while (dpos < len); + comm[len] = 0; + } +} + +//------------------------- LZW1 DECOMPRESSION -----------------------------// +void wrchar(CHAR ch) +{ + dcpr_do++; + + dcpr_text[dcpr_dpos] = ch; + dcpr_dpos++; + dcpr_dpos &= dcpr_dican; +} + +void copystr(LONG d, INT l) +{ + INT mpos; + + dcpr_do += l; + + mpos = dcpr_dpos - d; + mpos &= dcpr_dican; + + if ((mpos >= dcpr_dicsiz - maxlength) || (dcpr_dpos >= dcpr_dicsiz - maxlength)) + { + while (l--) + { + dcpr_text[dcpr_dpos] = dcpr_text[mpos]; + dcpr_dpos++; + dcpr_dpos &= dcpr_dican; + mpos++; + mpos &= dcpr_dican; + } + } + else + { + while (l--) + dcpr_text[dcpr_dpos++] = dcpr_text[mpos++]; + dcpr_dpos &= dcpr_dican; + } +} + +void decompress(void) +{ + INT c, + lg, + i, + k; + ULONG dist; + + while (dcpr_do < dcpr_do_max) + { + if (!blocksize) + if (!calc_dectabs()) + return; + + addbits(dcpr_wd_mn[(c = dcpr_code_mn[code_rd >> (32 - maxwd_mn)])]); + blocksize--; + if (c > 255) + { + if (c > 259) + { + if ((c -= 260) > 1) + { + dist = (code_rd >> (33 - c)) + (1L << (c - 1)); + addbits(c - 1); + } + else + dist = c; + dcpr_olddist[(dcpr_oldnum = (dcpr_oldnum + 1) & 3)] = dist; + i = 2; + if (dist > maxdis2) + { + i++; + if (dist > maxdis3) + i++; + } + } + else + { + dist = dcpr_olddist[(dcpr_oldnum - (c &= 255)) & 3]; + for (k = c + 1; k--;) + dcpr_olddist[(dcpr_oldnum - k) & 3] = dcpr_olddist[(dcpr_oldnum - k + 1) & 3]; + dcpr_olddist[dcpr_oldnum] = dist; + i = 2; + if (c > 1) + i++; + } + addbits(dcpr_wd_lg[(lg = dcpr_code_lg[code_rd >> (32 - maxwd_lg)])]); + dist++; + lg += i; + copystr(dist, lg); + } + else + wrchar(c); + } +} + +//-------------------------- HUFFMAN ROUTINES ------------------------------// +INT makecode(UINT maxwd, UINT size1_t, UCHAR * wd, USHORT * code) +{ + UINT maxc, + size2_t, + l, + c, + i, + max_make_code; + + memcpy(&sort_freq, wd, (size1_t + 1) * sizeof(CHAR)); + if (size1_t) + quicksort(size1_t); + else + sort_org[0] = 0; + sort_freq[size1_t + 1] = size2_t = c = 0; + while (sort_freq[size2_t]) + size2_t++; + if (size2_t < 2) + { + i = sort_org[0]; + wd[i] = 1; + size2_t += (size2_t == 0); + } + size2_t--; + + max_make_code = 1 << maxwd; + for (i = size2_t + 1; i-- && c < max_make_code;) + { + maxc = 1 << (maxwd - sort_freq[i]); + l = sort_org[i]; + if (c + maxc > max_make_code) + { + dcpr_do = dcpr_do_max; + return (0); + } + memset16(&code[c], l, maxc); + c += maxc; + } + return (1); +} + +INT read_wd(UINT maxwd, USHORT * code, UCHAR * wd, INT max_el) +{ + UINT c, + i, + j, + num_el, + l, + uplim, + lolim; + + memset(wd, 0, max_el * sizeof(CHAR)); + memset(code, 0, (1 << maxwd) * sizeof(SHORT)); + + num_el = code_rd >> (32 - 9); + addbits(9); + if (num_el > max_el) + num_el = max_el; + + lolim = code_rd >> (32 - 4); + addbits(4); + uplim = code_rd >> (32 - 4); + addbits(4); + + for (i = -1; ++i <= uplim;) + { + wd_svwd[i] = code_rd >> (32 - 3); + addbits(3); + } + if (!makecode(maxwd_svwd, uplim, wd_svwd, code)) + return (0); + j = 0; + while (j <= num_el) + { + c = code[code_rd >> (32 - maxwd_svwd)]; + addbits(wd_svwd[c]); + if (c < uplim) + wd[j++] = c; + else + { + l = (code_rd >> 28) + 4; + addbits(4); + while (l-- && j <= num_el) + wd[j++] = 0; + } + } + if (uplim) + for (i = 0; ++i <= num_el;) + wd[i] = (wd[i] + wd[i - 1]) % uplim; + for (i = -1; ++i <= num_el;) + if (wd[i]) + wd[i] += lolim; + + return (makecode(maxwd, num_el, wd, code)); + +} + +INT calc_dectabs(void) +{ + if (!read_wd(maxwd_mn, dcpr_code_mn, dcpr_wd_mn, max_cd_mn) + || !read_wd(maxwd_lg, dcpr_code_lg, dcpr_wd_lg, max_cd_lg)) + return (0); + + blocksize = code_rd >> (32 - 15); + addbits(15); + + return (1); +} + +//---------------------------- BLOCK ROUTINES ------------------------------// +INT decompress_blk(CHAR * buf, UINT len) +{ + LONG old_pos = dcpr_dpos; + INT i; + + dcpr_do = 0; + if ((dcpr_do_max = len - maxlength) > dcpr_size) + dcpr_do_max = dcpr_size; + if ((LONG) dcpr_size > 0 && dcpr_do_max) + { + decompress(); + if (old_pos + dcpr_do > dcpr_dicsiz) + { + i = dcpr_dicsiz - old_pos; + memcpy(buf, &dcpr_text[old_pos], i); + memcpy(&buf[i], dcpr_text, dcpr_do - i); + } + else + memcpy(buf, &dcpr_text[old_pos], dcpr_do); + } + dcpr_size -= dcpr_do; + return (dcpr_do); +} + +INT unstore(CHAR * buf, UINT len) +{ + UINT rd = 0, + i, + pos = 0; + +#ifdef CRYPT + len = crypt_len(len - 8); /* because of decryption */ +#endif /* CRYPT */ + + while ((i = read_adds_blk((CHAR *) buf_rd, (INT) ((i = ((len > dcpr_size) ? dcpr_size : len)) > size_rdb ? size_rdb : i))) != 0) + { + rd += i; + len -= i; + memcpy(&buf[pos], buf_rd, i); + pos += i; + } + dcpr_size -= rd; + for (i = 0; i < rd; i++) + { + dcpr_text[dcpr_dpos] = buf[i]; + dcpr_dpos++; + dcpr_dpos &= dcpr_dican; + } + return (INT)rd; +} + +INT dcpr_adds_blk(CHAR * buf, UINT len) +{ + INT r; + + switch (fhead.TECH.TYPE) + { + case TYPE_STORE: + r = unstore(buf, len); + break; + case TYPE_LZW1: + r = decompress_blk(buf, len); + break; + default: + pipeit("\nFile compressed with unknown method. Decompression not possible.\n"); + f_err = ERR_OTHER; + r = 0; + } + rd_crc = getcrc(rd_crc, (UCHAR *)buf, r); + return r; +} + + +//----------------------------- INIT ROUTINES ------------------------------// +void dcpr_init(void) +{ + dcpr_frst_file = 1; + + dcpr_dic = 20; + while ((dcpr_text = malloc(dcpr_dicsiz = (LONG) 1 << dcpr_dic))==NULL) + dcpr_dic--; + dcpr_dican = dcpr_dicsiz - 1; +} + +void dcpr_init_file(void) +{ + UINT i; + +#ifdef CRYPT + + reset_cryptkey(); + +#else /* CRYPT */ + + if (head.HEAD_FLAGS & ACE_PASSW) + { + pipeit("\nFound passworded file. Decryption not supported.\n"); + f_err = ERR_OTHER; + return; + } + +#endif /* CRYPT */ + + rd_crc = CRC_MASK; + dcpr_size = fhead.SIZE; + if (fhead.TECH.TYPE == TYPE_LZW1) + { + if ((fhead.TECH.PARM & 15) + 10 > dcpr_dic) + { + pipeit("\nNot enough memory or dictionary of archive too large.\n"); + f_err = ERR_MEM; + return; + } + + i = size_rdb * sizeof(LONG); + read_adds_blk((CHAR *) buf_rd, i); +#ifdef HI_LO_BYTE_ORDER + { + ULONG *p; + i>>=2; // count LONGs not BYTEs + p=buf_rd; + while (i--) + { + LONGswap(p); + p++; + } + } +#endif + code_rd = buf_rd[0]; + bits_rd = rpos = 0; + + blocksize = 0; + } + if (!adat.sol || dcpr_frst_file) + dcpr_dpos = 0; + + dcpr_oldnum = 0; + memset(&dcpr_olddist, 0, sizeof(dcpr_olddist)); + + dcpr_frst_file = 0; +} + diff --git a/utils/Install/packace/uac_sys.c b/utils/Install/packace/uac_sys.c new file mode 100644 index 0000000000..2a261f3d57 --- /dev/null +++ b/utils/Install/packace/uac_sys.c @@ -0,0 +1,105 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* Some basic things. */ +/* */ +/* ------------------------------------------------------------------------ */ + +#include "os.h" + +#include // signal() +#include // fprintf() fflush() getch() putc() + +#if defined(DOS) || defined(WINNT) || defined(WIN16) +#if !defined(__CYGWIN__) + #include // getch() +#endif +#endif +#if defined(DOS) + #include // delay() sound() +#endif + +#include "globals.h" +#include "uac_sys.h" + + +void memset16(USHORT * dest, SHORT val, INT len) // fills short-array with +{ // value + while (len--) + *(dest++) = val; +} + +INT cancel(void) // checks whether to interrupt the program +{ +#ifdef DOS + while (kbhit()) + { + if (getch() == 27) + f_err = ERR_USER; + } +#endif + return (f_err); +} + +INT wrask(CHAR * s) // prompt-routine +{ + CHAR ch = 0; + + fprintf(stderr, "\n %s (Yes,Always,No,Cancel) ", s); + fflush(stderr); + do + { + /*ch = getch(); + ch = upcase(ch);*/ + } + while (ch != 'Y' && ch != 'A' && ch != 'N' && ch != 'C' && ch != 27); + fprintf(stderr, "%s", ch == 'Y' ? "Yes" : (ch == 'A' ? "Always" : (ch == 'N' ? "No" : "Cancel"))); + fflush(stderr); + return (ch == 'Y' ? 0 : (ch == 'A' ? 1 : (ch == 'N' ? 2 : 3))); +} + +void beep(void) // makes some noise +{ +#ifdef DOS + sound(800); + delay(250); + nosound(); +#endif +#ifdef AMIGA + putc(0x07, stderr); +#endif +} + +void my_signalhandler(INT sig_number) // sets f_err if ctrl+c or ctrl+brk +{ + f_err = ERR_USER; + pipeit("\nUser break\n"); +} + +#ifdef DOS // handles hardware errors +#ifdef __BORLANDC__ +INT harderrhandler(UINT deverr, UINT errc, UINT * devhdr) +#else +INT __far harderrhandler(UINT deverr, UINT errc, UINT * devhdr) +#endif +{ + f_criterr = 'A' + deverr & 0xff; + f_err = ERR_OTHER; + return (0x3); +} +#endif + +void set_handler(void) // initializes handlers +{ +#if defined(DOS) && !defined(__BORLANDC__) + signal(SIGBREAK, my_signalhandler); // set ctrl-break/-c handlers +#endif + signal(SIGINT, my_signalhandler); +#if defined(DOS) && !defined(__CONSOLE__) // set hardware error handler +#ifdef __BORLANDC__ + harderr(harderrhandler); +#else + _harderr(harderrhandler); +#endif +#endif +} + diff --git a/utils/Install/packace/unace.c b/utils/Install/packace/unace.c new file mode 100644 index 0000000000..e38a88d756 --- /dev/null +++ b/utils/Install/packace/unace.c @@ -0,0 +1,584 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* Main file of public UNACE. */ +/* */ +/* ------------------------------------------------------------------------ */ + + +//--------------- include general files ------------------------------------// +#include // tolower() +#include // open() +#include // printf() sprintf() remove() +#include // malloc() +#include // str*() +#include +#include // S_I* AMIGA: fstat() + +#define DIRSEP '\\' + +#if (!defined(__EMX__) && !defined(__OS2__) && !defined(WINNT) && !defined(WIN32)) || defined(__CYGWIN__) +#include +#endif + + +//--------------- include unace specific header files ----------------------// +#include "os.h" + +#include "globals.h" +#include "portable.h" +#include "uac_comm.h" +#include "uac_crc.h" +#include "uac_crt.h" +#include "uac_dcpr.h" +#include "uac_sys.h" + +#ifdef CRYPT + #include "unace_ps.h" +#endif /* CRYPT */ +int files=0; + +//--------------- BEGIN OF UNACE ROUTINES ----------------------------------// + +int pipeit(char *format, ...) { + /* Do nothing ... perhaps pipe this somewhere in the future */ + return 0; +} + +void init_unace(void) // initializes unace +{ + buf_rd =malloc(size_rdb * sizeof(ULONG)); // Allocate buffers: increase + buf =malloc(size_buf); // sizes when possible to speed + buf_wr =malloc(size_wrb); // up the program + readbuf=malloc(size_headrdb); + + if (buf_rd ==NULL || + buf ==NULL || + buf_wr ==NULL || + readbuf==NULL ) + f_err = ERR_MEM; + + make_crctable(); // initialize CRC table + dcpr_init(); // initialize decompression + + set_handler(); // ctrl+break etc. +} + +void done_unace(void) +{ + if (buf_rd ) free(buf_rd ); + if (buf ) free(buf ); + if (buf_wr ) free(buf_wr ); + if (readbuf ) free(readbuf ); + if (dcpr_text) free(dcpr_text); +} + +INT read_header(INT print_err) // reads any header from archive +{ + USHORT rd, + head_size, + crc_ok; + LONG crc; + UCHAR *tp=readbuf; + + lseek(archan, skipsize, SEEK_CUR); // skip ADDSIZE block + + if (read(archan, &head, 4)<4) + return (0); // read CRC and header size + +#ifdef HI_LO_BYTE_ORDER + WORDswap(&head.HEAD_CRC); + WORDswap(&head.HEAD_SIZE); +#endif + // read size_headrdb bytes into + head_size = head.HEAD_SIZE; // header structure + rd = (head_size > size_headrdb) ? size_headrdb : head_size; + if (read(archan, readbuf, rd) < rd) + return (0); + head_size -= rd; + crc = getcrc(CRC_MASK, readbuf, rd); + + while (head_size) // skip rest of header + { + rd = (head_size > size_buf) ? size_buf : head_size; + if (read(archan, buf, rd) < rd) + return (0); + head_size -= rd; + crc = getcrc(crc, (UCHAR *)buf, rd); + } + + head.HEAD_TYPE =*tp++; // generic buffer to head conversion + head.HEAD_FLAGS=BUFP2WORD(tp); + + if (head.HEAD_FLAGS & ACE_ADDSIZE) + skipsize = head.ADDSIZE = BUF2LONG(tp); // get ADDSIZE + else + skipsize = 0; + + // check header CRC + if (!(crc_ok = head.HEAD_CRC == (crc & 0xffff)) && print_err) + pipeit("\nError: archive is broken\n"); + else + switch (head.HEAD_TYPE) // specific buffer to head conversion + { + case MAIN_BLK: + memcpy(mhead.ACESIGN, tp, acesign_len); tp+=acesign_len; + mhead.VER_MOD=*tp++; + mhead.VER_CR =*tp++; + mhead.HOST_CR=*tp++; + mhead.VOL_NUM=*tp++; + mhead.TIME_CR=BUFP2LONG(tp); + mhead.RES1 =BUFP2WORD(tp); + mhead.RES2 =BUFP2WORD(tp); + mhead.RES =BUFP2LONG(tp); + mhead.AV_SIZE=*tp++; + memcpy(mhead.AV, tp, rd-(USHORT)(tp-readbuf)); + break; + case FILE_BLK: + fhead.PSIZE =BUFP2LONG(tp); + fhead.SIZE =BUFP2LONG(tp); + fhead.FTIME =BUFP2LONG(tp); + fhead.ATTR =BUFP2LONG(tp); + fhead.CRC32 =BUFP2LONG(tp); + fhead.TECH.TYPE =*tp++; + fhead.TECH.QUAL =*tp++; + fhead.TECH.PARM =BUFP2WORD(tp); + fhead.RESERVED =BUFP2WORD(tp); + fhead.FNAME_SIZE=BUFP2WORD(tp); + memcpy(fhead.FNAME, tp, rd-(USHORT)(tp-readbuf)); + break; + // default: (REC_BLK and future things): + // do nothing 'cause isn't needed for extraction + } + + return (crc_ok); +} +// maximum SFX module size +#define max_sfx_size 65536 // (needed by read_arc_head) + +INT read_arc_head(void) // searches for the archive header and reads it +{ + INT i, + flags, + buf_pos = 0; + LONG arc_head_pos, + old_fpos, + fpos = 0; + struct stat st; + + fstat(archan, &st); + + memset(buf, 0, size_buf); + +#if !defined(__EMX__) && !defined(__OS2__) + while (ftell(farchan) 0; + adat.vol = (flags & ACE_MULT_VOL) > 0; + adat.vol_num = mhead.VOL_NUM; + adat.time_cr = mhead.TIME_CR; + return (1); + } + } + } + // was no archive header, + // continue search + lseek(archan, fpos, SEEK_SET); + memcpy(buf, &buf[size_buf - 512], 512); + buf_pos = 512; // keep 512 old bytes + } + return (0); +} + +INT open_archive(INT print_err) // opens archive (or volume) +{ + CHAR av_str[80]; + + +#if defined(__OS2_) || defined(__EMX__) || defined(WIN32) + archan = open(aname, O_RDONLY | O_BINARY); // open file +#else + archan = open(aname, O_RDONLY); // open file +#endif +#if !defined(__EMX__) && !defined(__OS2__) + farchan = fdopen(archan, "rb"); +#endif + if (archan == -1) + { + pipeit("\nError opening file %s", aname); + return (0); + } + if (!read_arc_head()) // read archive header + { + if (print_err) + pipeit("\nInvalid archive file: %s\n", aname); +#if !defined(__EMX__) && !defined(__OS2__) + fclose(farchan); +#endif + close(archan); + return (0); + } + + pipeit("\nProcessing archive: %s\n\n", aname); + if (head.HEAD_FLAGS & ACE_AV) + { + pipeit("Authenticity Verification:"); // print the AV + sprintf(av_str, "\ncreated on %d.%d.%d by ", + ts_day(adat.time_cr), ts_month(adat.time_cr), ts_year(adat.time_cr)); + pipeit(av_str); + strncpy(av_str, (char *)mhead.AV, mhead.AV_SIZE); + av_str[mhead.AV_SIZE] = 0; + pipeit("%s\n\n", av_str); + } + comment_out("Main comment:"); // print main comment + return (1); +} + +void get_next_volname(void) // get file name of next volume +{ + CHAR *cp; + INT num; + + if ((cp = (CHAR *) strrchr(aname, '.')) == NULL || !*(cp + 1)) + num = -1; + else + { + cp++; + num = (*(cp + 1) - '0') * 10 + *(cp + 2) - '0'; + if (!in(num, 0, 99)) + num = -1; + if (in(*cp, '0', '9')) + num += (*cp - '0') * 100; + } + num++; + + if (num < 100) + *cp = 'C'; + else + *cp = num / 100 + '0'; + *(cp + 1) = (num / 10) % 10 + '0'; + *(cp + 2) = num % 10 + '0'; +} + +INT proc_vol(void) // opens volume +{ + INT i; + CHAR s[80]; + + if (!fileexists(aname) || !f_allvol_pr) + { + do + { + sprintf(s, "Ready to process %s?", aname); +#if !defined(__MINGW32__) + beep(); +#else + beep(500,500); +#endif + i = wrask(s); // ask whether ready or not + f_allvol_pr = (i == 1); // "Always" --> process all volumes + if (i >= 2) + { + f_err = ERR_FOUND; + return (0); + } + } + while (!fileexists(aname)); + } + + if (!open_archive(1)) // open volume + { + pipeit("\nError while opening archive. File not found or archive broken.\n"); + f_err = ERR_OPEN; + return (0); + } + + return (1); +} + +INT proc_next_vol(void) // opens next volume to process +{ +#if !defined(__EMX__) && !defined(__OS2__) + fclose(farchan); +#endif + close(archan); // close handle + get_next_volname(); // get file name of next volume + + if (!proc_vol()) // try to open volume, read archive header + return 0; + if (!read_header(1)) // read 2nd header + { + f_err=ERR_READ; + return 0; + } + return 1; +} + +INT read_adds_blk(CHAR * buffer, INT len) // reads part of ADD_SIZE block +{ + INT rd = 0, + l = len; + LONG i; + +#ifdef CRYPT + char *cbuffer=buffer; + + if (head.HEAD_TYPE == FILE_BLK && (head.HEAD_FLAGS & ACE_PASSW)) + len = crypt_len(len); +#endif /* CRYPT */ + while (!f_err && len && skipsize) + { + i = (skipsize > len) ? len : skipsize; + skipsize -= i; + + /* How do I check error condition when comping -mno-cygwin? */ +#if !defined(__MINGW32__) + errno = 0; +#endif + rd += read(archan, buffer, i); +#if !defined(__MINGW32__) + if (errno) + { + pipeit("\nRead error\n"); + f_err = ERR_READ; + } +#endif + + buffer += i; + len -= i; + + if (!skipsize) // if block is continued on next volume + if (head.HEAD_FLAGS & ACE_SP_AFTER && !proc_next_vol()) + break; + } +#ifdef CRYPT + if (head.HEAD_TYPE == FILE_BLK && (head.HEAD_FLAGS & ACE_PASSW)) + decrypt(cbuffer, rd); +#endif /* CRYPT */ + + return (rd > l ? l : rd); +} + +void crc_print(void) // checks CRC, prints message +{ + INT crc_not_ok = rd_crc != fhead.CRC32; /* check CRC of file */ + + if (!f_err) // print message + { + pipeit(crc_not_ok ? " CRC-check error" : " CRC OK"); + flush; + } +} + +void analyze_file(void) // analyzes one file (for solid archives) +{ + pipeit("\n Analyzing"); + flush; + while (!cancel() && (dcpr_adds_blk(buf_wr, size_wrb))) // decompress only + ; + crc_print(); +} + +void extract_file(void) // extracts one file +{ + INT rd; + + pipeit("\n Extracting"); + flush; // decompress block + while (!cancel() && (rd = dcpr_adds_blk(buf_wr, size_wrb))) + { + if (write(wrhan, buf_wr, rd) != rd) // write block + { + pipeit("\nWrite error\n"); + f_err = ERR_WRITE; + } + } + crc_print(); +} + +/* extracts or tests all files of the archive + */ +void extract_files(int nopath, int test) +{ + CHAR file[PATH_MAX]; + + while (!cancel() && read_header(1)) + { + if (head.HEAD_TYPE == FILE_BLK) + { + comment_out("File comment:"); // show file comment + ace_fname(file, &head, nopath); // get file name + pipeit("\n%s", file); + flush; + dcpr_init_file(); // initialize decompression of file + if (!f_err) + { + if (test || + (wrhan = create_dest_file(file, (INT) fhead.ATTR))<0) + { + if (test || adat.sol) + analyze_file(); // analyze file + } + else + { + extract_file(); // extract it +#ifdef DOS // set file time + _dos_setftime(wrhan, (USHORT) (fhead.FTIME >> 16), (USHORT) fhead.FTIME); +#endif + close(wrhan); +#ifdef DOS // set file attributes + _dos_setfileattr(file, (UINT) fhead.ATTR); +#endif +#ifdef AMIGA + { // set file date and time + struct DateTime dt; + char Date[9], Time[9]; + ULONG tstamp=fhead.FTIME; + + sprintf(Date, "%02d-%02d-%02d", ts_year(tstamp)-1900, ts_month(tstamp), ts_day(tstamp)); + sprintf(Time, "%02d:%02d:%02d", ts_hour(tstamp), ts_min(tstamp), ts_sec(tstamp)); + + dt.dat_Format = FORMAT_INT; + dt.dat_Flags = 0; + dt.dat_StrDate= Date; + dt.dat_StrTime= Time; + + if (StrToDate(&dt)) + SetFileDate(file, &dt.dat_Stamp); + } +#endif + if (f_err) + remove(file); + } + } + } + } +} + +unsigned percentage(ULONG p, ULONG d) +{ + return (unsigned)( d ? (d/2+p*100)/d : 100 ); +} + +void list_files(int verbose) +{ + ULONG size =0, + psize=0, + tpsize; + CHAR file[PATH_MAX]; + + pipeit("Date |Time |Packed |Size |Ratio|File\n"); + + while (!cancel() && read_header(1)) + { + if (head.HEAD_TYPE == FILE_BLK) + { + ULONG ti=fhead.FTIME; + ace_fname(file, &head, verbose ? 0 : 1); // get file name + + size += fhead.SIZE; + psize += + tpsize = fhead.PSIZE; + files++; + + while (head.HEAD_FLAGS & ACE_SP_AFTER) + { + skipsize=0; + if (!proc_next_vol()) + break; + psize += fhead.PSIZE; + tpsize+= fhead.PSIZE; + } + if (!f_err) + pipeit("%02u.%02u.%02u|%02u:%02u|%c%c%9lu|%9lu|%4u%%|%c%s\n", + ts_day (ti), ts_month(ti), ts_year(ti)%100, + ts_hour(ti), ts_min (ti), + fhead.HEAD_FLAGS & ACE_SP_BEF ? '<' : ' ', + fhead.HEAD_FLAGS & ACE_SP_AFTER ? '>' : ' ', + tpsize, fhead.SIZE, percentage(tpsize, fhead.SIZE), + fhead.HEAD_FLAGS & ACE_PASSW ? '*' : ' ', + file + ); + } + } + if (!f_err) + { + pipeit("\n %9lu|%9lu|%4u%%| %u file%s", + psize, + size, + percentage(psize, size), + files, + (char*)(files == 1 ? "" : "s") + ); + } +} + +void showhelp(void) +{ + pipeit("\n" + "Usage: UNACE \n" + "\n" + "Where is one of:\n" + "\n" + " e Extract files\n" + " l List archive\n" + " t Test archive integrity\n" + " v List archive (verbose)\n" + " x Extract files with full path" + ); +} + +int include_unpack(char *bleah) // processes the archive +{ + CHAR *s; + + strcpy(aname, bleah); + + init_unace(); // initialize unace + + if (!(s = (CHAR *) strrchr(aname, DIRSEP))) + s = aname; + if (!strrchr(s, '.')) + strcat(aname, ".ACE"); + + if (open_archive(1)) // open archive to process + { + if (adat.vol_num) + pipeit("\nFirst volume of archive required!\n"); + else + list_files (0 ); + +#if !defined(__EMX__) && !defined(__OS2__) + fclose(farchan); +#endif + close(archan); + if (f_err) + { + pipeit("\nError occurred\n"); + if (f_criterr) + pipeit("Critical error on drive %c\n", f_criterr); + } + } + else + f_err = ERR_CLINE; + + done_unace(); + return (f_err); +} + diff --git a/utils/Install/packzip/api.c b/utils/Install/packzip/api.c new file mode 100644 index 0000000000..5a4e73abf8 --- /dev/null +++ b/utils/Install/packzip/api.c @@ -0,0 +1,601 @@ +/*--------------------------------------------------------------------------- + + api.c + + This module supplies an UnZip engine for use directly from C/C++ + programs. The functions are: + + UzpVer *UzpVersion(void); + void 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 +#include + +#define UNZIP_INTERNAL +#include "unzip.h" +#include "version.h" +#ifdef WINDLL +# include "windll/windll.h" +#endif + +#ifdef DLL /* This source file supplies DLL-only interface code. */ + +jmp_buf dll_error_return; + +/*--------------------------------------------------------------------------- + Documented API entry points + ---------------------------------------------------------------------------*/ + + +UzpVer * UZ_EXP UzpVersion() /* should be pointer to const struct */ +{ + static UzpVer version; /* doesn't change between calls */ + + + version.structlen = UZPVER_LEN; + +#ifdef BETA + version.flag = 1; +#else + version.flag = 0; +#endif + version.betalevel = BETALEVEL; + version.date = VERSION_DATE; + +#ifdef ZLIB_VERSION + version.zlib_version = ZLIB_VERSION; + version.flag |= 2; +#else + version.zlib_version = NULL; +#endif + + /* someday each of these may have a separate patchlevel: */ + version.unzip.major = UZ_MAJORVER; + version.unzip.minor = UZ_MINORVER; + version.unzip.patchlevel = PATCHLEVEL; + + version.zipinfo.major = ZI_MAJORVER; + version.zipinfo.minor = ZI_MINORVER; + version.zipinfo.patchlevel = PATCHLEVEL; + + /* these are retained for backward compatibility only: */ + version.os2dll.major = UZ_MAJORVER; + version.os2dll.minor = UZ_MINORVER; + version.os2dll.patchlevel = PATCHLEVEL; + + version.windll.major = UZ_MAJORVER; + version.windll.minor = UZ_MINORVER; + version.windll.patchlevel = PATCHLEVEL; + + return &version; +} + +void UZ_EXP UzpVersion2(UzpVer2 *version) +{ + + version->structlen = UZPVER_LEN; + +#ifdef BETA + version->flag = 1; +#else + version->flag = 0; +#endif + strcpy(version->betalevel, BETALEVEL); + strcpy(version->date, VERSION_DATE); + +#ifdef ZLIB_VERSION + strcpy(version->zlib_version, ZLIB_VERSION); + 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 = PATCHLEVEL; + + version->zipinfo.major = ZI_MAJORVER; + version->zipinfo.minor = ZI_MINORVER; + version->zipinfo.patchlevel = PATCHLEVEL; + + /* these are retained for backward compatibility only: */ + version->os2dll.major = UZ_MAJORVER; + version->os2dll.minor = UZ_MINORVER; + version->os2dll.patchlevel = PATCHLEVEL; + + version->windll.major = UZ_MAJORVER; + version->windll.minor = UZ_MINORVER; + version->windll.patchlevel = PATCHLEVEL; +} + + + + + +#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->strptr != NULL) { + free(retstr->strptr); + retstr->strptr = NULL; + } +} + + + + +#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 */ + + + + +/*--------------------------------------------------------------------------- + Helper functions + ---------------------------------------------------------------------------*/ + + +void setFileNotFound(__G) + __GDEF +{ + G.filenotfound++; +} + + + +int unzipToMemory(__GPRO__ char *zip, char *file, UzpBuffer *retstr) +{ + int r; + char *incname[2]; + + 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 */ +} + + + +int redirect_outfile(__G) + __GDEF +{ + if (G.redirect_size != 0 || G.redirect_buffer != NULL) + return FALSE; + +#ifndef NO_SLIDE_REDIR + G.redirect_slide = !G.pInfo->textmode; +#endif + G.redirect_size = (G.pInfo->textmode ? + G.lrec.ucsize * lenEOL : G.lrec.ucsize); +#ifdef OS2 + DosAllocMem((void **)&G.redirect_buffer, G.redirect_size+1, + PAG_READ|PAG_WRITE|PAG_COMMIT); + G.redirect_pointer = G.redirect_buffer; +#else +#ifdef __16BIT__ + if ((ulg)((extent)G.redirect_size) != G.redirect_size) + return FALSE; +#endif + G.redirect_pointer = G.redirect_buffer = malloc(G.redirect_size+1); +#endif + if (!G.redirect_buffer) + return FALSE; + G.redirect_pointer[G.redirect_size] = '\0'; + return TRUE; +} + + + +int writeToMemory(__GPRO__ uch *rawbuf, ulg size) +{ + if (rawbuf != G.redirect_pointer) + memcpy(G.redirect_pointer,rawbuf,size); + G.redirect_pointer += size; + return 0; +} + + + + +int close_redirect(__G) + __GDEF +{ + if (G.pInfo->textmode) { + *G.redirect_pointer = '\0'; + G.redirect_size = 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 __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 wild card 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 */ +#ifdef WINDLL + Wiz_NoPrinting(TRUE); +#endif + + if (archive == NULL) { /* something is screwed up: no filename */ + DESTROYGLOBALS(); + return PK_NOZIP; + } + + G.wildzipfn = (char *)malloc(FILNAMSIZ + 1); + strcpy(G.wildzipfn, archive); +#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO)) + _ISO_INTERN(G.wildzipfn); +#endif + + G.process_all_files = TRUE; /* for speed */ + + retcode = setjmp(dll_error_return); + + if (retcode) { +#ifdef WINDLL + Wiz_NoPrinting(FALSE); +#endif + free(G.wildzipfn); + DESTROYGLOBALS(); + return PK_BADERR; + } + + 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 + */ + + 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 /* DLL */ diff --git a/utils/Install/packzip/apihelp.c b/utils/Install/packzip/apihelp.c new file mode 100644 index 0000000000..1a0d682cdd --- /dev/null +++ b/utils/Install/packzip/apihelp.c @@ -0,0 +1,147 @@ +/* apihelp.c */ + +#ifdef API_DOC + +#define UNZIP_INTERNAL +#include "unzip.h" +#include "version.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/utils/Install/packzip/crc32.c b/utils/Install/packzip/crc32.c new file mode 100644 index 0000000000..cd05536108 --- /dev/null +++ b/utils/Install/packzip/crc32.c @@ -0,0 +1,56 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* $Id$ */ + +#define __CRC32_C /* identifies this source module */ + +#include "zip.h" + +#ifndef USE_ZLIB +#ifndef ASM_CRC + +#ifndef ZCONST +# define ZCONST const +#endif + +#ifdef CRC32 +# undef CRC32 +#endif +#define CRC32(c, b) (crc_table[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) +#define DO1(buf) crc = CRC32(crc, *buf++) +#define DO2(buf) DO1(buf); DO1(buf) +#define DO4(buf) DO2(buf); DO2(buf) +#define DO8(buf) DO4(buf); DO4(buf) + +/* ========================================================================= */ +ulg crc32(crc, buf, len) + register ulg crc; /* crc shift register */ + register ZCONST uch *buf; /* pointer to bytes to pump through */ + extent len; /* number of bytes in buf[] */ +/* Run a set of bytes through the crc shift register. If buf is a NULL + pointer, then initialize the crc shift register contents instead. + Return the current crc in either case. */ +{ + register ZCONST ulg near *crc_table; + + if (buf == NULL) return 0L; + + crc_table = get_crc_table(); + + crc = crc ^ 0xffffffffL; +#ifndef NO_UNROLLED_LOOPS + while (len >= 8) { + DO8(buf); + len -= 8; + } +#endif + if (len) do { + DO1(buf); + } while (--len); + return crc ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ +} +#endif /* !ASM_CRC */ +#endif /* !USE_ZLIB */ diff --git a/utils/Install/packzip/crc_i386.S b/utils/Install/packzip/crc_i386.S new file mode 100644 index 0000000000..5d0867f0e1 --- /dev/null +++ b/utils/Install/packzip/crc_i386.S @@ -0,0 +1,230 @@ +/* + * crc_i386.S, optimized CRC calculation function for Zip and UnZip, not + * copyrighted by Paul Kienitz and Christian Spieler. Last revised 12 Oct 97. + * + * 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 ...) + * + * 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, ulg len). + * + * The loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS. + * This results in shorter code at the expense of reduced performance. + */ + +/* This file is NOT used in conjunction with zlib. */ +#ifndef USE_ZLIB + +/* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix + * external symbols with an underline character '_'. + */ +#if defined(NO_UNDERLINE) || defined(__ELF__) +# define _crc32 crc32 +# define _get_crc_table get_crc_table +#endif +/* Use 16-byte alignment if your assembler supports it. Warning: gas + * uses a log(x) parameter (.align 4 means 16-byte alignment). On SVR4 + * the parameter is a number of bytes. + */ +#ifndef ALIGNMENT +# define ALIGNMENT .align 4,0x90 +#endif + +#if defined(i386) || defined(_i386) || defined(_I386) || defined(__i386) + +/* This version is for 386 Unix, OS/2, MSDOS in 32 bit mode (gcc & gas). + * Warning: it uses the AT&T syntax: mov source,dest + * This file is only optional. If you want to use the C version, + * remove -DASM_CRC from CFLAGS in Makefile and set OBJA to an empty string. + */ + + .file "crc_i386.S" + +#if defined(NO_STD_STACKFRAME) && defined(USE_STD_STACKFRAME) +# undef USE_STACKFRAME +#else + /* The default is to use standard stack frame entry, because it + * results in smaller code! + */ +# ifndef USE_STD_STACKFRAME +# define USE_STD_STACKFRAME +# endif +#endif + +#ifdef USE_STD_STACKFRAME +# define _STD_ENTRY pushl %ebp ; movl %esp,%ebp +# define arg1 8(%ebp) +# define arg2 12(%ebp) +# define arg3 16(%ebp) +# define _STD_LEAVE popl %ebp +#else /* !USE_STD_STACKFRAME */ +# define _STD_ENTRY +# define arg1 24(%esp) +# define arg2 28(%esp) +# define arg3 32(%esp) +# define _STD_LEAVE +#endif /* ?USE_STD_STACKFRAME */ + +/* + * These two (three) macros make up the loop body of the CRC32 cruncher. + * registers modified: + * eax : crc value "c" + * esi : pointer to next data byte (or lword) "buf++" + * registers read: + * edi : pointer to base of crc_table array + * scratch registers: + * ebx : index into crc_table array + * (requires upper three bytes = 0 when __686 is undefined) + */ +#ifndef __686 /* optimize for 386, 486, Pentium */ +#define Do_CRC /* c = (c >> 8) ^ table[c & 0xFF] */\ + movb %al, %bl ;/* tmp = c & 0xFF */\ + shrl $8, %eax ;/* c = (c >> 8) */\ + xorl (%edi, %ebx, 4), %eax ;/* c ^= table[tmp] */ +#else /* __686 : optimize for Pentium Pro and compatible CPUs */ +#define Do_CRC /* c = (c >> 8) ^ table[c & 0xFF] */\ + movzbl %al, %ebx ;/* tmp = c & 0xFF */\ + shrl $8, %eax ;/* c = (c >> 8) */\ + xorl (%edi, %ebx, 4), %eax ;/* c ^=table[tmp] */ +#endif /* ?__686 */ + +#define Do_CRC_byte /* c = (c >> 8) ^ table[(c^*buf++)&0xFF] */\ + xorb (%esi), %al ;/* c ^= *buf */\ + incl %esi ;/* buf++ */\ + Do_CRC + +#ifndef NO_32_BIT_LOADS +#define Do_CRC_lword \ + xorl (%esi), %eax ;/* c ^= *(ulg *)buf */\ + addl $4, %esi ;/* ((ulg *)buf)++ */\ + Do_CRC \ + Do_CRC \ + Do_CRC \ + Do_CRC +#endif /* !NO_32_BIT_LOADS */ + + + .text + + .globl _crc32 + +_crc32: /* ulg crc32(ulg crc, uch *buf, extent len) */ + _STD_ENTRY + pushl %edi + pushl %esi + pushl %ebx + pushl %edx + pushl %ecx + + movl arg2, %esi /* 2nd arg: uch *buf */ + subl %eax, %eax /* > if (!buf) */ + testl %esi, %esi /* > return 0; */ + jz .L_fine /* > else { */ + call _get_crc_table + movl %eax, %edi + movl arg1, %eax /* 1st arg: ulg crc */ +#ifndef __686 + subl %ebx, %ebx /* ebx=0; bl usable as dword */ +#endif + movl arg3, %ecx /* 3rd arg: extent len */ + notl %eax /* > c = ~crc; */ + +#ifndef NO_UNROLLED_LOOPS +# ifndef NO_32_BIT_LOADS + testl %ecx, %ecx + jz .L_bail + /* Assert now have positive length */ +.L_align_loop: + testl $3, %esi /* Align buf on lword boundary */ + jz .L_aligned_now + Do_CRC_byte + decl %ecx + jnz .L_align_loop +.L_aligned_now: +# endif /* !NO_32_BIT_LOADS */ + movl %ecx, %edx /* save len in edx */ + andl $7, %edx /* edx = len % 8 */ + shrl $3, %ecx /* ecx = len / 8 */ + jz .L_No_Eights +/* align loop head at start of 486 internal cache line !! */ + ALIGNMENT +.L_Next_Eight: +# ifndef NO_32_BIT_LOADS + /* Do_CRC_lword */ + xorl (%esi), %eax ;/* c ^= *(ulg *)buf */ + addl $4, %esi ;/* ((ulg *)buf)++ */ + Do_CRC + Do_CRC + Do_CRC + Do_CRC + /* Do_CRC_lword */ + xorl (%esi), %eax ;/* c ^= *(ulg *)buf */ + addl $4, %esi ;/* ((ulg *)buf)++ */ + Do_CRC + Do_CRC + Do_CRC + Do_CRC +# else /* NO_32_BIT_LOADS */ + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte +# endif /* ?NO_32_BIT_LOADS */ + decl %ecx + jnz .L_Next_Eight + +.L_No_Eights: + movl %edx, %ecx +#endif /* NO_UNROLLED_LOOPS */ + +#ifndef NO_JECXZ_SUPPORT + jecxz .L_bail /* > if (len) */ +#else + testl %ecx, %ecx /* > if (len) */ + jz .L_bail +#endif +/* align loop head at start of 486 internal cache line !! */ + ALIGNMENT +.L_loupe: /* > do { */ + Do_CRC_byte /* c = CRC32(c, *buf++); */ + decl %ecx /* > } while (--len); */ + jnz .L_loupe + +.L_bail: /* > } */ + notl %eax /* > return ~c; */ +.L_fine: + popl %ecx + popl %edx + popl %ebx + popl %esi + popl %edi + _STD_LEAVE + ret + +#else + error: this asm version is for 386 only +#endif /* i386 || _i386 || _I386 || __i386 */ + +#endif /* !USE_ZLIB */ diff --git a/utils/Install/packzip/crc_i386.asm b/utils/Install/packzip/crc_i386.asm new file mode 100644 index 0000000000..ea29282286 --- /dev/null +++ b/utils/Install/packzip/crc_i386.asm @@ -0,0 +1,229 @@ +; crc_i386.asm, optimized CRC calculation function for Zip and UnZip, not +; copyrighted by Paul Kienitz and Christian Spieler. Last revised 25 Mar 98. +; +; Revised 06-Oct-96, Scott Field (sfield@microsoft.com) +; fixed to assemble with masm by not using .model directive which makes +; assumptions about segment alignment. Also, +; avoid using loop, and j[e]cxz where possible. Use mov + inc, rather +; than lodsb, and other misc. changes resulting in the following performance +; increases: +; +; unrolled loops NO_UNROLLED_LOOPS +; *8 >8 <8 *8 >8 <8 +; +; +54% +42% +35% +82% +52% +25% +; +; first item in each table is input buffer length, even multiple of 8 +; second item in each table is input buffer length, > 8 +; third item in each table is input buffer length, < 8 +; +; Revised 02-Apr-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au) +; Incorporated Rodney Brown's 32-bit-reads optimization as found in the +; UNIX AS source crc_i386.S. This new code can be disabled by defining +; the macro symbol NO_32_BIT_LOADS. +; +; Revised 12-Oct-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au) +; Incorporated Rodney Brown's additional tweaks for 32-bit-optimized CPUs +; (like the Pentium Pro, Pentium II, and probably some Pentium clones). +; This optimization is controlled by the macro symbol __686 and is disabled +; by default. (This default is based on the assumption that most users +; do not yet work on a Pentium Pro or Pentium II machine ...) +; +; FLAT memory model assumed. +; +; The loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS. +; This results in shorter code at the expense of reduced performance. +; +; Revised 25-Mar-98, Cosmin Truta (cosmint@cs.ubbcluj.ro) +; Working without .model directive caused tasm32 version 5.0 to produce +; bad object code. The optimized alignments can be optionally disabled +; by defining NO_ALIGN, thus allowing to use .model flat. There is no need +; to define this macro if using other version of tasm. +; +;============================================================================== +; +; Do NOT assemble this source if external crc32 routine from zlib gets used. +; + IFNDEF USE_ZLIB +; + .386p + name crc_i386 + + IFDEF NO_ALIGN + .model flat + ENDIF + +extrn _get_crc_table:near ; ZCONST ulg near *get_crc_table(void); + +; + IFNDEF NO_STD_STACKFRAME + ; Use a `standard' stack frame setup on routine entry and exit. + ; Actually, this option is set as default, because it results + ; in smaller code !! +STD_ENTRY MACRO + push ebp + mov ebp,esp + ENDM + + Arg1 EQU 08H[ebp] + Arg2 EQU 0CH[ebp] + Arg3 EQU 10H[ebp] + +STD_LEAVE MACRO + pop ebp + ENDM + + ELSE ; NO_STD_STACKFRAME + +STD_ENTRY MACRO + ENDM + + Arg1 EQU 18H[esp] + Arg2 EQU 1CH[esp] + Arg3 EQU 20H[esp] + +STD_LEAVE MACRO + ENDM + + ENDIF ; ?NO_STD_STACKFRAME + +; These two (three) macros make up the loop body of the CRC32 cruncher. +; registers modified: +; eax : crc value "c" +; esi : pointer to next data byte (or dword) "buf++" +; registers read: +; edi : pointer to base of crc_table array +; scratch registers: +; ebx : index into crc_table array +; (requires upper three bytes = 0 when __686 is undefined) + IFNDEF __686 ; optimize for 386, 486, Pentium +Do_CRC MACRO + mov bl,al ; tmp = c & 0xFF + shr eax,8 ; c = (c >> 8) + xor eax,[edi+ebx*4] ; ^ table[tmp] + ENDM + ELSE ; __686 : optimize for Pentium Pro, Pentium II and compatible CPUs +Do_CRC MACRO + movzx ebx,al ; tmp = c & 0xFF + shr eax,8 ; c = (c >> 8) + xor eax,[edi+ebx*4] ; ^ table[tmp] + ENDM + ENDIF ; ?__686 +Do_CRC_byte MACRO + xor al, byte ptr [esi] ; c ^= *buf + inc esi ; buf++ + Do_CRC ; c = (c >> 8) ^ table[c & 0xFF] + ENDM + IFNDEF NO_32_BIT_LOADS +Do_CRC_dword MACRO + xor eax, dword ptr [esi] ; c ^= *(ulg *)buf + add esi, 4 ; ((ulg *)buf)++ + Do_CRC + Do_CRC + Do_CRC + Do_CRC + ENDM + ENDIF ; !NO_32_BIT_LOADS + + IFNDEF NO_ALIGN +_TEXT segment use32 para public 'CODE' + ELSE +_TEXT segment use32 + ENDIF + assume CS: _TEXT + + public _crc32 +_crc32 proc near ; ulg crc32(ulg crc, ZCONST uch *buf, extent len) + STD_ENTRY + push edi + push esi + push ebx + push edx + push ecx + + mov esi,Arg2 ; 2nd arg: uch *buf + sub eax,eax ;> if (!buf) + test esi,esi ;> return 0; + jz fine ;> else { + + call _get_crc_table + mov edi,eax + mov eax,Arg1 ; 1st arg: ulg crc + IFNDEF __686 + sub ebx,ebx ; ebx=0; make bl usable as a dword + ENDIF + mov ecx,Arg3 ; 3rd arg: extent len + not eax ;> c = ~crc; + + IFNDEF NO_UNROLLED_LOOPS + IFNDEF NO_32_BIT_LOADS + test ecx,ecx + je bail +align_loop: + test esi,3 ; align buf pointer on next + jz SHORT aligned_now ; dword boundary + Do_CRC_byte + dec ecx + jnz align_loop +aligned_now: + ENDIF ; !NO_32_BIT_LOADS + mov edx,ecx ; save len in edx + and edx,000000007H ; edx = len % 8 + shr ecx,3 ; ecx = len / 8 + jz SHORT No_Eights + IFNDEF NO_ALIGN +; align loop head at start of 486 internal cache line !! + align 16 + ENDIF +Next_Eight: + IFNDEF NO_32_BIT_LOADS + Do_CRC_dword + Do_CRC_dword + ELSE ; NO_32_BIT_LOADS + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + ENDIF ; ?NO_32_BIT_LOADS + dec ecx + jnz Next_Eight +No_Eights: + mov ecx,edx + + ENDIF ; NO_UNROLLED_LOOPS + IFNDEF NO_JECXZ_SUPPORT + jecxz bail ;> if (len) + ELSE + test ecx,ecx ;> if (len) + jz SHORT bail + ENDIF + IFNDEF NO_ALIGN +; align loop head at start of 486 internal cache line !! + align 16 + ENDIF +loupe: ;> do { + Do_CRC_byte ; c = CRC32(c, *buf++); + dec ecx ;> } while (--len); + jnz loupe + +bail: ;> } + not eax ;> return ~c; +fine: + pop ecx + pop edx + pop ebx + pop esi + pop edi + STD_LEAVE + ret +_crc32 endp + +_TEXT ends +; + ENDIF ; !USE_ZLIB +; +end diff --git a/utils/Install/packzip/crc_i386.c b/utils/Install/packzip/crc_i386.c new file mode 100644 index 0000000000..72e2c6b9dc --- /dev/null +++ b/utils/Install/packzip/crc_i386.c @@ -0,0 +1,215 @@ +/* crc_i386.c -- Microsoft 32-bit C/C++ adaptation of crc_i386.asm + * Created by Rodney Brown from crc_i386.asm, modified by Chr. Spieler. + * Last revised: 22-Mai-1998 + * + * Original coded (in crc_i386.asm) and put into the public domain + * by Paul Kienitz and Christian Spieler. + * + * Revised 06-Oct-96, Scott Field (sfield@microsoft.com) + * fixed to assemble with masm by not using .model directive which makes + * assumptions about segment alignment. Also, + * avoid using loop, and j[e]cxz where possible. Use mov + inc, rather + * than lodsb, and other misc. changes resulting in the following performance + * increases: + * + * unrolled loops NO_UNROLLED_LOOPS + * *8 >8 <8 *8 >8 <8 + * + * +54% +42% +35% +82% +52% +25% + * + * first item in each table is input buffer length, even multiple of 8 + * second item in each table is input buffer length, > 8 + * third item in each table is input buffer length, < 8 + * + * Revised 02-Apr-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au) + * Incorporated Rodney Brown's 32-bit-reads optimization as found in the + * UNIX AS source crc_i386.S. This new code can be disabled by defining + * the macro symbol NO_32_BIT_LOADS. + * + * Revised 12-Oct-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au) + * Incorporated Rodney Brown's additional tweaks for 32-bit-optimized CPUs + * (like the Pentium Pro, Pentium II, and probably some Pentium clones). + * This optimization is controlled by the macro symbol __686 and is disabled + * by default. (This default is based on the assumption that most users + * do not yet work on a Pentium Pro or Pentium II machine ...) + * + * Revised 16-Nov-97, Chr. Spieler: Made code compatible with Borland C++ + * 32-bit, removed unneeded kludge for potentially unknown movzx mnemonic, + * confirmed correct working with MS VC++ (32-bit). + * + * Revised 22-Mai-98, Peter Kunath, Chr. Spieler : The 16-Nov-97 revision broke + * MSVC 5.0. Inside preprocessor macros, each instruction is enclosed in its + * own __asm {...} construct. For MSVC, a "#pragma warning" was added to + * shut up the "no return value" warning message. + * + * FLAT memory model assumed. + * + * The loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS. + * This results in shorter code at the expense of reduced performance. + * + */ + +#include "zip.h" + +#ifndef USE_ZLIB + +#ifndef ZCONST +# define ZCONST const +#endif + +/* Select wether the following inline-assember code is supported. */ +#if (defined(_MSC_VER) && _MSC_VER >= 700) +#if (defined(_M_IX86) && _M_IX86 >= 300) +# define MSC_INLINE_ASM_32BIT_SUPPORT + /* Disable warning for no return value, typical of asm functions */ +# pragma warning( disable : 4035 ) +#endif +#endif + +#if (defined(__BORLANDC__) && __BORLANDC__ >= 452) +# define MSC_INLINE_ASM_32BIT_SUPPORT +#endif + +#ifdef MSC_INLINE_ASM_32BIT_SUPPORT +/* This code is intended for Microsoft C/C++ (32-bit) compatible compilers. */ + +/* + * These two (three) macros make up the loop body of the CRC32 cruncher. + * registers modified: + * eax : crc value "c" + * esi : pointer to next data byte (or dword) "buf++" + * registers read: + * edi : pointer to base of crc_table array + * scratch registers: + * ebx : index into crc_table array + * (requires upper three bytes = 0 when __686 is undefined) + */ +#ifndef __686 +#define Do_CRC { \ + __asm { mov bl, al }; \ + __asm { shr eax, 8 }; \ + __asm { xor eax, [edi+ebx*4] }; } +#else /* __686 */ +#define Do_CRC { \ + __asm { movzx ebx, al }; \ + __asm { shr eax, 8 }; \ + __asm { xor eax, [edi+ebx*4] }; } +#endif /* ?__686 */ + +#define Do_CRC_byte { \ + __asm { xor al, byte ptr [esi] }; \ + __asm { inc esi }; \ + Do_CRC; } + +#ifndef NO_32_BIT_LOADS +#define Do_CRC_dword { \ + __asm { xor eax, dword ptr [esi] }; \ + __asm { add esi, 4 }; \ + Do_CRC; \ + Do_CRC; \ + Do_CRC; \ + Do_CRC; } +#endif /* !NO_32_BIT_LOADS */ + +/* ========================================================================= */ +ulg crc32(crc, buf, len) + ulg crc; /* crc shift register */ + ZCONST uch *buf; /* pointer to bytes to pump through */ + extent len; /* number of bytes in buf[] */ +/* Run a set of bytes through the crc shift register. If buf is a NULL + pointer, then initialize the crc shift register contents instead. + Return the current crc in either case. */ +{ + __asm { + push edx + push ecx + + mov esi,buf ;/* 2nd arg: uch *buf */ + sub eax,eax ;/*> if (!buf) */ + test esi,esi ;/*> return 0; */ + jz fine ;/*> else { */ + + call get_crc_table + mov edi,eax + mov eax,crc ;/* 1st arg: ulg crc */ +#ifndef __686 + sub ebx,ebx ;/* ebx=0; => bl usable as a dword */ +#endif + mov ecx,len ;/* 3rd arg: extent len */ + not eax ;/*> c = ~crc; */ + +#ifndef NO_UNROLLED_LOOPS +# ifndef NO_32_BIT_LOADS + test ecx,ecx + je bail +align_loop: + test esi,3 ;/* align buf pointer on next */ + jz aligned_now ;/* dword boundary */ + } + Do_CRC_byte ; + __asm { + dec ecx + jnz align_loop +aligned_now: +# endif /* !NO_32_BIT_LOADS */ + mov edx,ecx ;/* save len in edx */ + and edx,000000007H ;/* edx = len % 8 */ + shr ecx,3 ;/* ecx = len / 8 */ + jz No_Eights +; align loop head at start of 486 internal cache line !! + align 16 +Next_Eight: + } +# ifndef NO_32_BIT_LOADS + Do_CRC_dword ; + Do_CRC_dword ; +# else /* NO_32_BIT_LOADS */ + Do_CRC_byte ; + Do_CRC_byte ; + Do_CRC_byte ; + Do_CRC_byte ; + Do_CRC_byte ; + Do_CRC_byte ; + Do_CRC_byte ; + Do_CRC_byte ; +# endif /* ?NO_32_BIT_LOADS */ + __asm { + dec ecx + jnz Next_Eight +No_Eights: + mov ecx,edx + +#endif /* NO_UNROLLED_LOOPS */ +#ifndef NO_JECXZ_SUPPORT + jecxz bail ;/*> if (len) */ +#else + test ecx,ecx ;/*> if (len) */ + jz bail +#endif +; align loop head at start of 486 internal cache line !! + align 16 +loupe: ;/*> do { */ + } + Do_CRC_byte ;/* c = CRC32(c, *buf++); */ + __asm { + dec ecx ;/*> } while (--len); */ + jnz loupe + +bail: ;/*> } */ + not eax ;/*> return ~c; */ +fine: + pop ecx + pop edx + } +#ifdef NEED_RETURN + return _EAX; +#endif +} +#endif /* MSC_INLINE_ASM_32BIT_SUPPORT */ +#if (defined(_MSC_VER) && _MSC_VER >= 700) +#if (defined(_M_IX86) && _M_IX86 >= 300) + /* Reenable missing return value warning */ +# pragma warning( default : 4035 ) +#endif +#endif +#endif /* !USE_ZLIB */ diff --git a/utils/Install/packzip/crc_lcc.asm b/utils/Install/packzip/crc_lcc.asm new file mode 100644 index 0000000000..b3288a833e --- /dev/null +++ b/utils/Install/packzip/crc_lcc.asm @@ -0,0 +1,108 @@ +; crc_lcc.asm, optimized CRC calculation function for Zip and UnZip, not +; copyrighted by Paul Kienitz and Christian Spieler. Last revised 25 Mar 98. +; +; The code in this file has been copied verbatim from crc_i386.{asm|S}; +; only the assembler syntax and metacommands have been adapted to +; the habits of the free LCC-Win32 C compiler package. +; This version of the code uses the "optimized for i686" variant of +; crc_i386.{asm|S}. +; +; For more information (and a revision log), look into the original +; source files. +; + .text + .file "crc32.c" + .text + .type _crc32,function +_crc32: + pushl %ebp + movl %esp,%ebp + pushl %ecx + pushl %ebx + pushl %esi + pushl %edi + .line 34 + .line 37 + movl 12(%ebp),%esi + subl %eax,%eax + testl %esi,%esi + jz _$3 + .line 39 + call _get_crc_table + movl %eax,%edi + .line 41 + movl 8(%ebp),%eax + movl 16(%ebp),%ecx + notl %eax + testl %ecx,%ecx + jz _$4 +_$5: + testl $3,%esi + jz _$6 + xorb (%esi),%al + incl %esi + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + decl %ecx + jnz _$5 +_$6: + movl %ecx,%edx + andl $7,%edx + shrl $3,%ecx + jz _$8 +_$7: + xorl (%esi),%eax + addl $4,%esi + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + xorl (%esi),%eax + addl $4,%esi + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + decl %ecx + jnz _$7 +_$8: + movl %edx,%ecx + jecxz _$4 +_$9: + xorb (%esi),%al + incl %esi + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + decl %ecx + jnz _$9 +_$4: + xorl $0xffffffff,%eax +_$3: + .line 52 + popl %edi + popl %esi + popl %ebx + leave + ret +_$34: + .size _crc32,_$34-_crc32 + .globl _crc32 + .extern _get_crc_table diff --git a/utils/Install/packzip/crctab.c b/utils/Install/packzip/crctab.c new file mode 100644 index 0000000000..2f80aa2cfa --- /dev/null +++ b/utils/Install/packzip/crctab.c @@ -0,0 +1,219 @@ +/* crctab.c -- supply the CRC table needed for CRC-32 calculations. + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* $Id$ */ + +/* + Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all + the information needed to generate CRC's on data a byte at a time for all + combinations of CRC register values and incoming bytes. +*/ + +#define __CRCTAB_C /* identifies this source module */ + +#include "zip.h" + +#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) + +#ifndef ZCONST +# define ZCONST const +#endif + +#ifdef DYNAMIC_CRC_TABLE + +/* ========================================================================= + * Make the crc table. This function is needed only if you want to compute + * the table dynamically. + */ + +local void make_crc_table OF((void)); + +#if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT)) + error: Dynamic allocation of CRC table not safe with reentrant code. +#endif /* DYNALLOC_CRCTAB && REENTRANT */ + +#ifdef DYNALLOC_CRCTAB + local ulg near *crc_table = NULL; +# if 0 /* not used, since sizeof("near *") <= sizeof(int) */ + /* Use this section when access to a "local int" is faster than access to + a "local pointer" (e.g.: i86 16bit code with far pointers). */ + local int crc_table_empty = 1; +# define CRC_TABLE_IS_EMPTY (crc_table_empty != 0) +# define MARK_CRCTAB_FILLED crc_table_empty = 0 +# define MARK_CRCTAB_EMPTY crc_table_empty = 1 +# else + /* Use this section on systems where the size of pointers and ints is + equal (e.g.: all 32bit systems). */ +# define CRC_TABLE_IS_EMPTY (crc_table == NULL) +# define MARK_CRCTAB_FILLED crc_table = crctab_p +# define MARK_CRCTAB_EMPTY crc_table = NULL +# endif +#else /* !DYNALLOC_CRCTAB */ + local ulg near crc_table[256]; + local int crc_table_empty = 1; +# define CRC_TABLE_IS_EMPTY (crc_table_empty != 0) +# define MARK_CRCTAB_FILLED crc_table_empty = 0 +#endif /* ?DYNALLOC_CRCTAB */ + + +local void make_crc_table() +{ + ulg c; /* crc shift register */ + int n; /* counter for all possible eight bit values */ + int k; /* byte being shifted into crc apparatus */ +#ifdef DYNALLOC_CRCTAB + ulg near *crctab_p; /* temporary pointer to allocated crc_table area */ +#else /* !DYNALLOC_CRCTAB */ +# define crctab_p crc_table +#endif /* DYNALLOC_CRCTAB */ + +#ifdef COMPUTE_XOR_PATTERN + /* This piece of code has been left here to explain how the XOR pattern + * used in the creation of the crc_table values can be recomputed. + * For production versions of this function, it is more efficient to + * supply the resultant pattern at compile time. + */ + ulg xor; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static uch p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320L) */ + xor = 0L; + for (i = 0; i < sizeof(p)/sizeof(uch); i++) + xor |= 1L << (31 - p[i]); +#else +# define xor 0xedb88320L +#endif + +#ifdef DYNALLOC_CRCTAB + crctab_p = (ulg near *) nearmalloc (256*sizeof(ulg)); + if (crctab_p == NULL) { + ziperr(ZE_MEM, "crc_table allocation"); + } +#endif /* DYNALLOC_CRCTAB */ + + for (n = 0; n < 256; n++) { + c = (ulg)n; + for (k = 8; k; k--) + c = c & 1 ? xor ^ (c >> 1) : c >> 1; + crctab_p[n] = c; + } + MARK_CRCTAB_FILLED; +} + +#else /* !DYNAMIC_CRC_TABLE */ + +#ifdef DYNALLOC_CRCTAB + error: Inconsistent flags, DYNALLOC_CRCTAB without DYNAMIC_CRC_TABLE. +#endif + +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +local ZCONST ulg near crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; +#endif /* ?DYNAMIC_CRC_TABLE */ + +/* use "OF((void))" here to work around a Borland TC++ 1.0 problem */ +#ifdef USE_ZLIB +ZCONST uLongf *get_crc_table OF((void)) +#else +ZCONST ulg near *get_crc_table OF((void)) +#endif +{ +#ifdef DYNAMIC_CRC_TABLE + if (CRC_TABLE_IS_EMPTY) + make_crc_table(); +#endif +#ifdef USE_ZLIB + return (ZCONST uLongf *)crc_table; +#else + return (ZCONST ulg near *)crc_table; +#endif +} + +#ifdef DYNALLOC_CRCTAB +void free_crc_table() +{ + if (!CRC_TABLE_IS_EMPTY) + { + nearfree((ulg near *)crc_table); + MARK_CRCTAB_EMPTY; + } +} +#endif + +#endif /* !USE_ZLIB || USE_OWN_CRCTAB */ diff --git a/utils/Install/packzip/crypt.c b/utils/Install/packzip/crypt.c new file mode 100644 index 0000000000..0dbe227f81 --- /dev/null +++ b/utils/Install/packzip/crypt.c @@ -0,0 +1,12 @@ +/* + crypt.c (dummy version) by Info-ZIP. Last revised: 15 Aug 98 + + This is a non-functional version of Info-ZIP's crypt.c encryption/ + decryption code for Zip, ZipCloak, UnZip and fUnZip. This file is + not copyrighted and may be distributed freely. :-) See the "WHERE" + file for sites from which to obtain the full encryption/decryption + sources (zcrypt28.zip or later). + */ + +/* something "externally visible" to shut up compiler/linker warnings */ +int zcr_dummy; diff --git a/utils/Install/packzip/envargs.c b/utils/Install/packzip/envargs.c new file mode 100644 index 0000000000..76a41e8997 --- /dev/null +++ b/utils/Install/packzip/envargs.c @@ -0,0 +1,314 @@ +/*----------------------------------------------------------------* + | 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 +#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__ */ + +static int count_args OF((ZCONST char *)); +static void mem_err OF((__GPRO)); + +static ZCONST char Far NoMemArguments[] = + "envargs: cannot get memory for arguments"; + + +void envargs(__G__ Pargc, Pargv, envstr, envstr2) + __GDEF + int *Pargc; + char ***Pargv; + ZCONST char *envstr, *envstr2; +{ +#ifndef RISCOS + char *getenv(); +#endif + 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; + + bufptr = malloc(1 + strlen(envptr)); + if (bufptr == (char *)NULL) + mem_err(__G); +#if (defined(WIN32) || defined(WINDLL)) +# 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 environment uses OEM codepage */ + OEM_TO_INTERN(envptr, bufptr); +# endif +#else /* !(WIN32 || WINDLL) */ + strcpy(bufptr, envptr); +#endif /* ?(WIN32 || WINDLL) */ + + /* 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); + mem_err(__G); + } + 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 = *(++bufptr)) + if (ch == '\\' && bufptr[1] != '\0') + ++bufptr; /* skip char after backslash */ + if (ch != '\0') + *(bufptr++) = '\0'; /* overwrite trailing " */ + + /* remove escape characters */ + while ((argstart = strchr(argstart, '\\')) != (char *)NULL) { + strcpy(argstart, argstart + 1); + if (*argstart) + ++argstart; + } + } else { + *(argv++) = bufptr; + while ((ch = *bufptr) != '\0' && !ISspace(ch)) + ++bufptr; + if (ch != '\0') + *(bufptr++) = '\0'; + } +#else +#ifdef DOS_FLX_OS2_W32 + /* we do not support backslash-quoting of quotes in quoted + * strings under DOS_OS2_W32, because backslashes are directory + * separators and double quotes are illegal in filenames */ + if (*bufptr == '"') { + *(argv++) = ++bufptr; + while ((ch = *bufptr) != '\0' && ch != '\"') + ++bufptr; + if (ch != '\0') + *(bufptr++) = '\0'; + } else { + *(argv++) = bufptr; + while ((ch = *bufptr) != '\0' && !ISspace(ch)) + ++bufptr; + if (ch != '\0') + *(bufptr++) = '\0'; + } +#else + *(argv++) = bufptr; + while ((ch = *bufptr) != '\0' && !ISspace(ch)) + ++bufptr; + if (ch != '\0') + *(bufptr++) = '\0'; +#endif /* ?DOS_FLX_OS2_W32 */ +#endif /* ?(AMIGA || UNIX) */ + while ((ch = *bufptr) != '\0' && ISspace(ch)) + ++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 */ + *Pargv = argvect; + *Pargc = argc; +} + + + +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 = *(++s); ch != '\0' && ch != '\"'; ch = *(++s)) + if (ch == '\\' && s[1] != '\0') + ++s; + if (*s) + ++s; /* trailing quote */ + } else +#else +#ifdef DOS_FLX_OS2_W32 + if (*s == '\"') { + ++s; /* leading quote */ + while ((ch = *s) != '\0' && ch != '\"') + ++s; + if (*s) + ++s; /* trailing quote */ + } else +#endif /* DOS_FLX_OS2_W32 */ +#endif /* ?(AMIGA || UNIX) */ + while ((ch = *s) != '\0' && !ISspace(ch)) /* note else-clauses above */ + ++s; + while ((ch = *s) != '\0' && ISspace(ch)) + ++s; + } while (ch); + + return count; +} + + + +static void mem_err(__G) + __GDEF +{ + perror(LoadFarString(NoMemArguments)); + DESTROYGLOBALS() + EXIT(PK_MEM); +} + + + +#ifdef TEST + +main(argc, argv) + int argc; + char **argv; +{ + int i; + + pipeit("Orig argv: %p\n", argv); + dump_args(argc, argv); + envargs(__G__ &argc, &argv, "ENVTEST"); + pipeit(" New argv: %p\n", argv); + dump_args(argc, argv); +} + + + +dump_args(argc, argv) + int argc; + char *argv[]; +{ + int i; + + pipeit("\nDump %d args:\n", argc); + for (i = 0; i < argc; ++i) + pipeit("%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/utils/Install/packzip/explode.c b/utils/Install/packzip/explode.c new file mode 100644 index 0000000000..c1a8f80032 --- /dev/null +++ b/utils/Install/packzip/explode.c @@ -0,0 +1,871 @@ +/* explode.c -- put in the public domain by Mark Adler + version c15, 6 July 1996 */ + + +/* 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. + */ + + +/* + 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 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 wsize G._wsize +#else +# define wsize WSIZE +#endif + +/* routines here */ +static int get_tree OF((__GPRO__ unsigned *l, unsigned n)); +static int explode_lit8 OF((__GPRO__ struct huft *tb, struct huft *tl, + struct huft *td, int bb, int bl, int bd)); +static int explode_lit4 OF((__GPRO__ struct huft *tb, struct huft *tl, + struct huft *td, int bb, int bl, int bd)); +static int explode_nolit8 OF((__GPRO__ struct huft *tl, struct huft *td, + int bl, int bd)); +static int explode_nolit4 OF((__GPRO__ struct huft *tl, struct huft *td, + int bl, int bd)); +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. + */ + + +/* 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 ush 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);} + + + +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_lit8(__G__ tb, tl, td, bb, bl, bd) + __GDEF +struct huft *tb, *tl, *td; /* literal, length, and distance tables */ +int bb, bl, bd; /* number of bits decoded by those */ +/* Decompress the imploded data using coded literals and an 8K sliding + window. */ +{ + long 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 */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + unsigned u; /* true if unflushed */ + + + /* 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]; + s = G.ucsize; + while (s > 0) /* do until ucsize bytes uncompressed */ + { + NEEDBITS(1) + if (b & 1) /* then literal--decode it */ + { + DUMPBITS(1) + s--; + NEEDBITS((unsigned)bb) /* get coded literal */ + if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + redirSlide[w++] = (uch)t->v.n; + if (w == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + } + else /* else distance/length */ + { + DUMPBITS(1) + NEEDBITS(7) /* get distance low bits */ + d = (unsigned)b & 0x7f; + DUMPBITS(7) + NEEDBITS((unsigned)bd) /* get coded distance high bits */ + if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + d = w - d - t->v.n; /* construct offset */ + NEEDBITS((unsigned)bl) /* get coded length */ + if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + n = t->v.n; + if (e) /* get length extra bits */ + { + NEEDBITS(8) + n += (unsigned)b & 0xff; + DUMPBITS(8) + } + + /* do the copy */ + s -= n; + do { +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) { + /* &= w/ wsize not needed and wrong if redirect */ + if (d >= wsize) + return 1; + n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); + } else +#endif + n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > 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 == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + } while (n); + } + } + + /* flush out redirSlide */ + flush(__G__ redirSlide, (ulg)w, 0); + 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_lit4(__G__ tb, tl, td, bb, bl, bd) + __GDEF +struct huft *tb, *tl, *td; /* literal, length, and distance tables */ +int bb, bl, bd; /* number of bits decoded by those */ +/* Decompress the imploded data using coded literals and a 4K sliding + window. */ +{ + long 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 */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + unsigned u; /* true if unflushed */ + + + /* 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]; + s = G.ucsize; + while (s > 0) /* do until ucsize bytes uncompressed */ + { + NEEDBITS(1) + if (b & 1) /* then literal--decode it */ + { + DUMPBITS(1) + s--; + NEEDBITS((unsigned)bb) /* get coded literal */ + if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + redirSlide[w++] = (uch)t->v.n; + if (w == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + } + else /* else distance/length */ + { + DUMPBITS(1) + NEEDBITS(6) /* get distance low bits */ + d = (unsigned)b & 0x3f; + DUMPBITS(6) + NEEDBITS((unsigned)bd) /* get coded distance high bits */ + if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + d = w - d - t->v.n; /* construct offset */ + NEEDBITS((unsigned)bl) /* get coded length */ + if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + n = t->v.n; + if (e) /* get length extra bits */ + { + NEEDBITS(8) + n += (unsigned)b & 0xff; + DUMPBITS(8) + } + + /* do the copy */ + s -= n; + do { +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) { + /* &= w/ wsize not needed and wrong if redirect */ + if (d >= wsize) + return 1; + n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); + } else +#endif + n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > 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 == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + } while (n); + } + } + + /* flush out redirSlide */ + flush(__G__ redirSlide, (ulg)w, 0); + 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_nolit8(__G__ tl, td, bl, bd) + __GDEF +struct huft *tl, *td; /* length and distance decoder tables */ +int bl, bd; /* number of bits decoded by tl[] and td[] */ +/* Decompress the imploded data using uncoded literals and an 8K sliding + window. */ +{ + long 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 */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + unsigned u; /* true if unflushed */ + + + /* 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]; + s = G.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 == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + DUMPBITS(8) + } + else /* else distance/length */ + { + DUMPBITS(1) + NEEDBITS(7) /* get distance low bits */ + d = (unsigned)b & 0x7f; + DUMPBITS(7) + NEEDBITS((unsigned)bd) /* get coded distance high bits */ + if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + d = w - d - t->v.n; /* construct offset */ + NEEDBITS((unsigned)bl) /* get coded length */ + if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + n = t->v.n; + if (e) /* get length extra bits */ + { + NEEDBITS(8) + n += (unsigned)b & 0xff; + DUMPBITS(8) + } + + /* do the copy */ + s -= n; + do { +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) { + /* &= w/ wsize not needed and wrong if redirect */ + if (d >= wsize) + return 1; + n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); + } else +#endif + n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > 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 == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + } while (n); + } + } + + /* flush out redirSlide */ + flush(__G__ redirSlide, (ulg)w, 0); + 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_nolit4(__G__ tl, td, bl, bd) + __GDEF +struct huft *tl, *td; /* length and distance decoder tables */ +int bl, bd; /* number of bits decoded by tl[] and td[] */ +/* Decompress the imploded data using uncoded literals and a 4K sliding + window. */ +{ + long 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 */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + unsigned u; /* true if unflushed */ + + + /* 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]; + s = G.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 == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + DUMPBITS(8) + } + else /* else distance/length */ + { + DUMPBITS(1) + NEEDBITS(6) /* get distance low bits */ + d = (unsigned)b & 0x3f; + DUMPBITS(6) + NEEDBITS((unsigned)bd) /* get coded distance high bits */ + if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + d = w - d - t->v.n; /* construct offset */ + NEEDBITS((unsigned)bl) /* get coded length */ + if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + n = t->v.n; + if (e) /* get length extra bits */ + { + NEEDBITS(8) + n += (unsigned)b & 0xff; + DUMPBITS(8) + } + + /* do the copy */ + s -= n; + do { +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) { + /* &= w/ wsize not needed and wrong if redirect */ + if (d >= wsize) + return 1; + n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); + } else +#endif + n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > 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 == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + } while (n); + } + } + + /* flush out redirSlide */ + flush(__G__ redirSlide, (ulg)w, 0); + 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 */ + int bb; /* bits for tb */ + int bl; /* bits for tl */ + int bd; /* bits for td */ + unsigned l[256]; /* bit lengths for codes */ + +#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 + + /* 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; + + + /* With literal tree--minimum match length is 3 */ +#ifdef DEBUG + G.hufts = 0; /* initialize huft's malloc'ed */ +#endif + if (G.lrec.general_purpose_bit_flag & 4) + { + 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) + 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; + } + if ((r = get_tree(__G__ l, 64)) != 0) + return (int)r; + if (G.lrec.general_purpose_bit_flag & 2) /* true if 8K */ + { + if ((r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd)) != 0) + { + if (r == 1) + huft_free(td); + huft_free(tl); + huft_free(tb); + return (int)r; + } + r = explode_lit8(__G__ tb, tl, td, bb, bl, bd); + } + else /* else 4K */ + { + if ((r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd)) != 0) + { + if (r == 1) + huft_free(td); + huft_free(tl); + huft_free(tb); + return (int)r; + } + r = explode_lit4(__G__ tb, tl, td, bb, bl, bd); + } + huft_free(td); + huft_free(tl); + huft_free(tb); + } + else + + + /* No literal tree--minimum match length is 2 */ + { + 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) + return (int)r; + if (G.lrec.general_purpose_bit_flag & 2) /* true if 8K */ + { + if ((r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd)) != 0) + { + if (r == 1) + huft_free(td); + huft_free(tl); + return (int)r; + } + r = explode_nolit8(__G__ tl, td, bl, bd); + } + else /* else 4K */ + { + if ((r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd)) != 0) + { + if (r == 1) + huft_free(td); + huft_free(tl); + return (int)r; + } + r = explode_nolit4(__G__ tl, td, bl, bd); + } + 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 NEXTBYTE +#undef NEEDBITS +#undef DUMPBITS diff --git a/utils/Install/packzip/extract.c b/utils/Install/packzip/extract.c new file mode 100644 index 0000000000..5fd2577c31 --- /dev/null +++ b/utils/Install/packzip/extract.c @@ -0,0 +1,1985 @@ +/*--------------------------------------------------------------------------- + + 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() + extract_or_test_member() + TestExtraField() + test_compr_eb() + memextract() + memflush() + fnfilter() + + ---------------------------------------------------------------------------*/ + + +#define EXTRACT_C +#define UNZIP_INTERNAL +#include "unzip.h" +#include "crypt.h" +#ifdef WINDLL +# ifdef POCKET_UNZIP +# include "wince/intrface.h" +# else +# include "windll/windll.h" +# endif +#endif + +#define GRRDUMP(buf,len) { \ + int i, j; \ + \ + for (j = 0; j < (len)/16; ++j) { \ + pipeit(" "); \ + for (i = 0; i < 16; ++i) \ + pipeit("%02x ", (uch)(buf)[i+(j<<4)]); \ + pipeit("\n "); \ + for (i = 0; i < 16; ++i) { \ + char c = (char)(buf)[i+(j<<4)]; \ + \ + if (c == '\n') \ + pipeit("\\n "); \ + else if (c == '\r') \ + pipeit("\\r "); \ + else \ + pipeit(" %c ", c); \ + } \ + pipeit("\n"); \ + } \ + if ((len) % 16) { \ + pipeit(" "); \ + for (i = j<<4; i < (len); ++i) \ + pipeit("%02x ", (uch)(buf)[i]); \ + pipeit("\n "); \ + for (i = j<<4; i < (len); ++i) { \ + char c = (char)(buf)[i]; \ + \ + if (c == '\n') \ + pipeit("\\n "); \ + else if (c == '\r') \ + pipeit("\\r "); \ + else \ + pipeit(" %c ", c); \ + } \ + pipeit("\n"); \ + } \ +} + +static int store_info OF((__GPRO)); +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 +#ifdef SET_DIR_ATTRIB + static int 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 CmprEnDeflate[] = "enhanced deflate"; + static ZCONST char Far CmprDCLImplode[] = "DCL implode"; + static ZCONST char Far *ComprNames[NUM_METHODS] = { + CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce, + CmprImplode, CmprTokenize, CmprDeflate, CmprEnDeflate, CmprDCLImplode + }; +#endif /* !SFX */ +static ZCONST char Far FilNamMsg[] = + "%s: bad filename length (%s)\n"; +static ZCONST char Far ExtFieldMsg[] = + "%s: bad extra field length (%s)\n"; +static ZCONST char Far OffsetMsg[] = + "file #%u: bad zipfile offset (%s): %ld\n"; +static ZCONST char Far ExtractMsg[] = + "%8sing: %-22s %s%s"; +#ifndef SFX + static ZCONST char Far LengthMsg[] = + "%s %s: %ld bytes required to uncompress to %lu bytes;\n %s\ + supposed to require %lu 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 #%u: 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 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"; +#endif + +#ifndef WINDLL + static ZCONST char Far ReplaceQuery[] = + "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: "; + static ZCONST char Far AssumeNone[] = " NULL\n(assuming [N]one)\n"; + static ZCONST char Far NewNameQuery[] = "new name: "; + static ZCONST char Far InvalidResponse[] = "error: invalid response [%c]\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[] = + "%u 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 %u file%s tested.\n"; +static ZCONST char Far FilesSkipped[] = + "%u 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"; + +#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 +{ + uch *cd_inptr; + unsigned i, j, filnum=0, blknum=0; + int cd_incnt, renamed, query; + int error, error_in_archive=PK_COOL, *fn_matched=NULL, *xn_matched=NULL; +#ifdef WINDLL + int done_once = 0; +#else + extent len; +#endif + unsigned members_remaining, num_skipped=0, num_bad_pwd=0; + long cd_bufstart, bufstart, inbuf_offset, request; + LONGINT old_extra_bytes = 0L; +#ifdef SET_DIR_ATTRIB + unsigned num_dirs=0; + dirtime *dirlist=(dirtime *)NULL, **sorted_dirlist=(dirtime **)NULL; +#endif + + +/*--------------------------------------------------------------------------- + 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; + members_remaining = (unsigned)G.ecrec.total_entries_central_dir; + +#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. + ---------------------------------------------------------------------------*/ + + while (members_remaining) { + 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 (members_remaining && (j < DIR_BLKSIZ)) { + --members_remaining; + G.pInfo = &G.info[j]; + + if (readbuf(__G__ G.sig, 4) == 0) { + error_in_archive = PK_EOF; + members_remaining = 0; /* ...so no more left to do */ + break; + } + if (strncmp(G.sig, central_hdr_sig, 4)) { /* just to make sure */ + Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), + j + blknum*DIR_BLKSIZ + 1)); + Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); + error_in_archive = PK_BADERR; + members_remaining = 0; /* ...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 */ + members_remaining = 0; /* ...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")); + members_remaining = 0; + 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")); + members_remaining = 0; + 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))); + members_remaining = 0; + 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)) { + 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)) { + 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) */ + + + } /* 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. + -----------------------------------------------------------------------*/ + + for (i = 0; i < j; ++i) { + filnum++; /* filnum = 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(). */ + + /* ZLSEEK(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", + request, inbuf_offset)); + Trace((stderr, + "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", + bufstart, G.cur_zipfile_bufstart)); + if (request < 0) { + Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg), + G.zipfn, LoadFarString(ReportMsg))); + error_in_archive = PK_ERR; + if (filnum == 1 && G.extra_bytes != 0L) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(AttemptRecompensate))); + old_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", + request, inbuf_offset)); + Trace((stderr, + "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", + bufstart, G.cur_zipfile_bufstart)); + } else { + error_in_archive = PK_BADERR; + continue; /* this one hosed; try next */ + } + } + /* 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 if (bufstart != G.cur_zipfile_bufstart) { + Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n")); +#ifdef USE_STRM_INPUT + fseek((FILE *)G.zipfd,(LONGINT)bufstart,SEEK_SET); + G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd); +#else /* !USE_STRM_INPUT */ + G.cur_zipfile_bufstart = + lseek(G.zipfd,(LONGINT)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), + filnum, "lseek", 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), + filnum, "EOF", request)); + error_in_archive = PK_BADERR; + continue; /* but can still try next one */ + } + if (strncmp(G.sig, local_hdr_sig, 4)) { + Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), + filnum, LoadFarStringSmall(LocalHdrSig), request)); + /* + GRRDUMP(G.sig, 4) + GRRDUMP(local_hdr_sig, 4) + */ + error_in_archive = PK_ERR; + if ((filnum == 1 && G.extra_bytes != 0L) || + (G.extra_bytes == 0L && old_extra_bytes != 0L)) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(AttemptRecompensate))); + if (G.extra_bytes) { + old_extra_bytes = G.extra_bytes; + G.extra_bytes = 0L; + } else + G.extra_bytes = old_extra_bytes; /* third attempt */ + ZLSEEK(G.pInfo->offset) + if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */ + Info(slide, 0x401, ((char *)slide, + LoadFarString(OffsetMsg), filnum, "EOF", request)); + error_in_archive = PK_BADERR; + continue; /* but can still try next one */ + } + if (strncmp(G.sig, local_hdr_sig, 4)) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(OffsetMsg), filnum, + LoadFarStringSmall(LocalHdrSig), 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), + filnum)); + error_in_archive = error; /* only PK_EOF defined */ + continue; /* can still try next one */ + } + if ((error = do_string(__G__ G.lrec.filename_length, DS_FN)) != + 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 */ + } + } + +#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))); + ++num_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; + /* 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_ && !strchr(G.filename, '/')) { + char *p=G.filename-1; + + while (*++p) { + 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 = '/'; + } + } + } +#endif /* !SFX */ + + /* mapname can create dirs if not freshening or if renamed */ + if ((error = mapname(__G__ renamed)) > PK_WARN) { + if (error == IZ_CREATED_DIR) { +#ifdef SET_DIR_ATTRIB + dirtime *d_entry; + + d_entry = (dirtime *)malloc(sizeof(dirtime)); + if (d_entry == (dirtime *)NULL) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(DirlistEntryNoMem))); + } else { + unsigned eb_izux_flg; + + d_entry->next = dirlist; + dirlist = d_entry; + dirlist->fn = + (char *)malloc(strlen(G.filename) + 1); + if (dirlist->fn == (char *)NULL) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(DirlistEntryNoMem))); + dirlist = d_entry->next; + free(d_entry); + if (!error_in_archive) + error_in_archive = PK_WARN; + continue; + } + strcpy(dirlist->fn, G.filename); + dirlist->perms = G.pInfo->file_attr; +#ifdef USE_EF_UT_TIME + 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 ? &(dirlist->u.t3) : NULL), +#else + &(dirlist->u.t3), +#endif + dirlist->uidgid) + : 0; +#else /* !USE_EF_UT_TIME */ + eb_izux_flg = 0; +#endif /* ?USE_EF_UT_TIME */ + if (eb_izux_flg & EB_UT_FL_MTIME) { + TTrace((stderr, + "\nextract: Unix dir e.f. modtime = %ld\n", + dirlist->u.t3.mtime)); + } else { + dirlist->u.t3.mtime = dos_to_unix_time( + G.lrec.last_mod_dos_datetime); + } + if (eb_izux_flg & EB_UT_FL_ATIME) { + TTrace((stderr, + "\nextract: Unix dir e.f. actime = %ld\n", + dirlist->u.t3.atime)); + } else { + dirlist->u.t3.atime = + dirlist->u.t3.mtime; + } + dirlist->have_uidgid = + (uO.X_flag && (eb_izux_flg & EB_UX2_VALID)); + ++num_dirs; + } +#endif /* SET_DIR_ATTRIB */ + } else if (error == IZ_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 + /* if (!error_in_archive) + error_in_archive = PK_WARN; */ + } else if (error > PK_ERR && error_in_archive < PK_ERR) + error_in_archive = PK_ERR; + Trace((stderr, "mapname(%s) returns error = %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 + /* if freshening, don't skip if just renamed */ + if (uO.fflag && !renamed) + continue; /* freshen (no new files): skip */ + break; + case EXISTS_AND_OLDER: + if (uO.overwrite_none) { +#ifdef WINDLL + char szStr[FILNAMSIZ+40]; /* add. space for text */ + + if ((!G.prompt_always) || (done_once)) { + sprintf(szStr, + "Target file exists.\nSkipping %s\n", + FnFilter1(G.filename)); + win_fprintf((zvoid *)&G, stdout, + strlen(szStr), szStr); + } else { + query = TRUE; + break; + } +#endif /* WINDLL */ + continue; /* never overwrite: skip file */ + } +#ifdef UNIXBACKUP + if (!uO.overwrite_all && !uO.B_flag) +#else + if (!uO.overwrite_all) +#endif + query = TRUE; + break; + case EXISTS_AND_NEWER: /* (or equal) */ + if (uO.overwrite_none || (uO.uflag && !renamed)) { +#ifdef WINDLL + char szStr[FILNAMSIZ+40]; /* add. space for text */ + + if ((!G.prompt_always) || (done_once)) { + sprintf(szStr, + "Target file newer.\nSkipping %s\n", + FnFilter1(G.filename)); + win_fprintf((zvoid *)&G, stdout, + strlen(szStr), szStr); + } else { + query = TRUE; + break; + } +#endif /* WINDLL */ + continue; /* skip if update/freshen & orig name */ + } +#ifdef UNIXBACKUP + if (!uO.overwrite_all && !uO.B_flag) +#else + if (!uO.overwrite_all) +#endif + query = TRUE; + break; + } + if (query) { +#ifdef WINDLL + switch (G.lpUserFunctions->replace != NULL ? + (*G.lpUserFunctions->replace)(G.filename) : + IDM_REPLACE_NONE) { + case IDM_REPLACE_RENAME: + _ISO_INTERN(G.filename); + renamed = TRUE; + goto startover; + case IDM_REPLACE_YES: + break; + case IDM_REPLACE_ALL: + uO.overwrite_all = TRUE; + uO.overwrite_none = FALSE; /* just to make sure */ + break; + case IDM_REPLACE_NONE: + uO.overwrite_none = TRUE; + uO.overwrite_all = FALSE; /* make sure */ + done_once = TRUE; + /* FALL THROUGH, skip */ + case IDM_REPLACE_NO: + { + char szStr[FILNAMSIZ+40]; + + sprintf(szStr, + "Target file newer.\nSkipping %s\n", + FnFilter1(G.filename)); + win_fprintf((zvoid *)&G, stdout, + strlen(szStr), szStr); + } + continue; + } +#else /* !WINDLL */ +reprompt: + Info(slide, 0x81, ((char *)slide, + LoadFarString(ReplaceQuery), + FnFilter1(G.filename))); + if (fgets(G.answerbuf, 9, 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 'A': /* dangerous option: force caps */ + uO.overwrite_all = TRUE; + uO.overwrite_none = FALSE; /* just to make sure */ + break; + 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 */ + len = strlen(G.filename); + if (G.filename[len-1] == '\n') + G.filename[--len] = '\0'; + } while (len == 0); +#ifdef WIN32 /* WIN32 fgets( ... , stdin) returns OEM coded strings */ + _OEM_INTERN(G.filename); +#endif + renamed = TRUE; + goto startover; /* sorry for a goto */ + case 'y': + case 'Y': + break; + case 'N': + uO.overwrite_none = TRUE; + uO.overwrite_all = FALSE; /* make sure */ + /* FALL THROUGH, skip */ + case 'n': + continue; /* skip file */ + default: + Info(slide, 1, ((char *)slide, + LoadFarString(InvalidResponse), *G.answerbuf)); + goto reprompt; /* yet another goto? */ + } /* end switch (*answerbuf) */ +#endif /* ?WINDLL */ + } /* end if (query) */ + } /* end if (extracting to disk) */ + +#ifdef DLL + if ((G.statreportcb != NULL) && + (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn, + G.filename, NULL)) { + if (fn_matched) + free((zvoid *)fn_matched); + if (xn_matched) + free((zvoid *)xn_matched); + 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 + if (fn_matched) + free((zvoid *)fn_matched); + if (xn_matched) + free((zvoid *)xn_matched); + 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)) { + if (fn_matched) + free((zvoid *)fn_matched); + if (xn_matched) + free((zvoid *)xn_matched); + 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) */ + + + /* + * Jump back to where we were in the central directory, then go and do + * the next batch of files. + */ + +#ifdef USE_STRM_INPUT + fseek((FILE *)G.zipfd, (LONGINT)cd_bufstart, SEEK_SET); + G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd); +#else /* !USE_STRM_INPUT */ + G.cur_zipfile_bufstart = lseek(G.zipfd,(LONGINT)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 + pipeit("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart); + pipeit("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart, + cur_zipfile_bufstart); + pipeit("inptr-inbuf = %d\n", G.inptr-G.inbuf); + pipeit("incnt = %d\n\n", G.incnt); +#endif + + } /* end while-loop (blocks of files in central directory) */ + +/*--------------------------------------------------------------------------- + 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 = (dirtime **)malloc(num_dirs*sizeof(dirtime *)); + if (sorted_dirlist == (dirtime **)NULL) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(DirlistSortNoMem))); + while (dirlist != (dirtime *)NULL) { + dirtime *d = dirlist; + + dirlist = dirlist->next; + free(d); + } + } else { + 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(dirtime *), + dircomp); + } + + Trace((stderr, "setting directory times/perms/attributes\n")); + for (i = 0; i < num_dirs; ++i) { + dirtime *d = sorted_dirlist[i]; + + Trace((stderr, "dir = %s\n", d->fn)); + if ((error = set_direc_attribs(__G__ d)) != PK_OK) { + Info(slide, 0x201, ((char *)slide, + LoadFarString(DirlistSetAttrFailed), d->fn)); + if (!error_in_archive) + error_in_archive = error; + } + free(d->fn); + free(d); + } + free(sorted_dirlist); + } + } +#endif /* SET_DIR_ATTRIB */ + +#if (defined(WIN32) && defined(NTSD_EAS)) + process_defer_NT(__G); /* process any deferred items for this .zip file */ +#endif + +/*--------------------------------------------------------------------------- + Check for unmatched filespecs on command line and print warning if any + found. Free allocated memory. + ---------------------------------------------------------------------------*/ + + if (fn_matched) { + 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) { + 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); + } + +/*--------------------------------------------------------------------------- + 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 (readbuf(__G__ G.sig, 4) == 0) + error_in_archive = PK_EOF; + if (strncmp(G.sig, end_central_sig, 4)) { /* 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) { + unsigned 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 == 1)? "warning-" : "", G.zipfn)); + else if (num == 0) + Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested), + G.zipfn)); + else if (G.process_all_files && (num_skipped+num_bad_pwd == 0)) + Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData), + G.zipfn)); + else + Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles) + , G.zipfn, num, (num==1)? "":"s")); + if (num_skipped > 0) + Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped), + num_skipped, (num_skipped==1)? "":"s")); +#if CRYPT + if (num_bad_pwd > 0) + Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd) + , num_bad_pwd, (num_bad_pwd==1)? "":"s")); +#endif /* CRYPT */ + } else if ((uO.qflag == 0) && !error_in_archive && (num == 0)) + Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested), + G.zipfn)); + } + + /* 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 > 0) + 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 > 0) && error_in_archive <= PK_WARN) + error_in_archive = IZ_UNSUP; /* was PK_WARN; Jean-loup complained */ +#if CRYPT + else if ((num_bad_pwd > 0) && !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 SFX +# define UNKN_COMPR \ + (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED) +#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 +# define UNKN_COMPR (UNKN_RED || UNKN_SHR || \ + G.crec.compression_method==TOKENIZED || G.crec.compression_method>DEFLATED) +#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 && !uO.overwrite_all) { /* if -o, extract anyway */ + Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery), + FnFilter1(G.filename))); + fgets(G.answerbuf, 9, 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] > UNZIP_VERSION) { + 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, + UNZIP_VERSION / 10, UNZIP_VERSION % 10)); + return 0; + } + + if UNKN_COMPR { + if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) { +#ifndef SFX + if (G.crec.compression_method < NUM_METHODS) + Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName), + FnFilter1(G.filename), + LoadFarStringSmall(ComprNames[G.crec.compression_method]))); + 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 */ + + /* map whatever file attributes we have into the local format */ + mapattr(__G); /* GRR: worry about return value later */ + + G.pInfo->offset = (long)G.crec.relative_offset_local_header; + return 1; + +} /* end function store_info() */ + + + + + +/***************************************/ +/* 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; +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + ulg wsize; +#else +# define wsize WSIZE +#endif + + +/*--------------------------------------------------------------------------- + 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 came from Unix and is a symbolic link and we are extracting + * to disk, prepare to restore the link */ + if (S_ISLNK(G.pInfo->file_attr) && + (G.pInfo->hostnum == UNIX_ || G.pInfo->hostnum == ATARI_ || + G.pInfo->hostnum == BEOS_) && + !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0)) + G.symlnk = TRUE; + else + G.symlnk = FALSE; +#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_H68_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_H68_OS2_W32 */ +# define NEWLINE "\n" +#endif /* ?DOS_FLX_H68_OS2_W32 */ +#ifdef VMS + if (open_outfile(__G)) /* VMS: required even for stdout! */ + return PK_DISK; +#endif + } else if (open_outfile(__G)) + return PK_DISK; + } + +/*--------------------------------------------------------------------------- + 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.disk_full) { + *G.outptr++ = (uch)b; + if (++G.outcnt == wsize) { + flush(__G__ redirSlide, G.outcnt, 0); + G.outptr = redirSlide; + G.outcnt = 0L; + } + } + if (G.outcnt) /* flush final (partial) buffer */ + flush(__G__ redirSlide, G.outcnt, 0); + 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 ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall(ErrUnzipFile), + LoadFarString(NotEnoughMem), + LoadFarStringSmall2(Unshrink), + FnFilter1(G.filename))); + else + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall(ErrUnzipNoFile), + LoadFarString(NotEnoughMem), + 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 : "")); + } + unreduce(__G); + 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) && (r != 5)) { /* treat 5 specially */ + 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; + } + if (r == 5) { + int warning = ((ulg)G.used_csize <= G.lrec.csize); + + if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) + Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg), + "", warning? "warning" : "error", G.used_csize, + G.lrec.ucsize, warning? " " : "", G.lrec.csize, + " [", FnFilter1(G.filename), "]")); + else + Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg), + "\n", warning? "warning" : "error", G.used_csize, + G.lrec.ucsize, warning? " ":"", G.lrec.csize, + "", "", ".")); + error = warning? PK_WARN : PK_ERR; + } + break; +#endif /* !SFX */ + + case DEFLATED: + 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)) != 0) { + 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; + } + break; + + 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: + 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: + 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: + 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_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 ((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, *src; /* return PK-type error */ + ulg tgtsize, srcsize; /* level */ +{ + long 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 = 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 = G.csize; /* for CRC calculation */ + break; + case DEFLATED: + G.outcnt = 0L; + if ((r = UZinflate(__G)) != 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 + uch *rawbuf; + ulg size; +{ + if (size > G.outsize) + return 50; /* 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() */ + + + + + +/*************************/ +/* Function fnfilter() */ /* here instead of in list.c for SFX */ +/*************************/ + +char *fnfilter(raw, space) /* convert name to safely printable form */ + ZCONST char *raw; + uch *space; +{ +#ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */ + uch *r=(uch *)raw, *s=space; + + while (*r) { +#ifdef QDOS + if (qlflag & 2) { + if (*r == '/' || *r == '.') { + ++r; + *s++ = '_'; + continue; + } + } else +#endif + if (*r < 32) + *s++ = '^', *s++ = (uch)(64 + *r++); + else + *s++ = *r++; + } + *s = 0; + +#ifdef WINDLL + INTERN_TO_ISO((char *)space, (char *)space); /* translate to ANSI */ +#else +#ifdef WIN32 + /* 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 */ +#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 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((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); + /* return namecmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); */ +} + + + +#if 0 /* not used in Unix, but maybe for future OSes? */ + +/************************/ +/* Function namecmp() */ +/************************/ + +static int namecmp(s1, s2) /* [not] used by dircomp(); swiped from Zip */ + ZCONST char *s1, *s2; +{ + int d; + + for (;;) { + d = (int)(uch)case_map(*s1) + - (int)(uch)case_map(*s2); + + if (d || *s1 == 0 || *s2 == 0) + return d; + + s1++; + s2++; + } +} + +#endif /* 0 */ +#endif /* SET_DIR_ATTRIB */ diff --git a/utils/Install/packzip/fileio.c b/utils/Install/packzip/fileio.c new file mode 100644 index 0000000000..602bfaf058 --- /dev/null +++ b/utils/Install/packzip/fileio.c @@ -0,0 +1,2153 @@ +/*--------------------------------------------------------------------------- + + 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() (non-VMS, non-AOS/VS, non-CMS_MVS) + undefer_input() + defer_leftover_input() + readbuf() + readbyte() + fillinbuf() + flush() (non-VMS) + 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() + str2iso() (CRYPT && NEED_STR2ISO, only) + str2oem() (CRYPT && NEED_STR2OEM, only) + memset() (ZMEM only) + memcpy() (ZMEM only) + zstrnicmp() + zstat() (REGULUS only) + fLoadFarString() (SMALL_MEM only) + fLoadFarStringSmall() (SMALL_MEM only) + fLoadFarStringSmall2() (SMALL_MEM only) + zfstrcpy() (SMALL_MEM only) + + ---------------------------------------------------------------------------*/ + + +#define FILEIO_C +#define UNZIP_INTERNAL +#include "unzip.h" +#ifdef WINDLL +# include "windll/windll.h" +# include +#endif +#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 */ + +static int disk_error OF((__GPRO)); + + +/****************************/ +/* Strings used in fileio.c */ +/****************************/ + +#if (defined(UNIX) || defined(DOS_FLX_OS2_W32) || defined(__BEOS__)) + static ZCONST char Far CannotDeleteOldFile[] = + "error: cannot delete old %s\n"; +#ifdef UNIXBACKUP + static ZCONST char Far CannotRenameOldFile[] = + "error: cannot rename old %s\n"; + static ZCONST char Far BackupSuffix[] = "~"; +#endif +#endif /* UNIX || DOS_FLX_OS2_W32 || __BEOS__ */ + +static ZCONST char Far CannotOpenZipfile[] = + "error: cannot open zipfile [ %s ]\n"; +#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) + static ZCONST char Far CannotCreateFile[] = "error: cannot create %s\n"; +#endif +#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 ReadError[] = "error: zipfile read error\n"; +static ZCONST char Far FilenameTooLongTrunc[] = + "warning: filename too long--truncating.\n"; +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 + */ + +#if (defined(UNIX) || defined(TOPS20) || defined(AOS_VS) || defined(__BEOS__)) + G.zipfd = open(G.zipfn, O_RDONLY); +#else /* !(UNIX || TOPS20 || AOS_VS || __BEOS__) */ +#ifdef VMS + G.zipfd = open(G.zipfn, O_RDONLY, 0, "ctx=stm"); +#else /* !VMS */ +#ifdef MACOS + G.zipfd = open(G.zipfn, 0); +#else /* !MACOS */ +#ifdef RISCOS + G.zipfd = fopen(G.zipfn, "rb"); +#else /* !RISCOS */ +#ifdef CMS_MVS + G.zipfd = vmmvs_open_infile(__G); +#else /* !CMS_MVS */ + G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY); +#endif /* ?CMS_MVS */ +#endif /* ?RISCOS */ +#endif /* ?MACOS */ +#endif /* ?VMS */ +#endif /* ?(UNIX || TOPS20 || AOS_VS || __BEOS__) */ + +#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)); + return 1; + } + return 0; + +} /* end function open_input_file() */ + + + + +#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) + +/***************************/ +/* 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_OS2_W32) || defined(UNIX) || defined(__BEOS__)) +#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; + int blen, flen, tlen; + + blen = strlen(BackupSuffix); + flen = strlen(G.filename); + tlen = flen + blen + 1; + 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'; + } 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); + + /* GRR: should check if backup file exists, apply -n/-o to that */ + if (rename(G.filename, tname) < 0) { /* move file */ + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotRenameOldFile), FnFilter1(G.filename))); + free(tname); + return 1; + } + 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 */ + if (unlink(G.filename) != 0) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename))); + return 1; + } + Trace((stderr, "open_outfile: %s now deleted\n", + FnFilter1(G.filename))); + } +#endif /* DOS_FLX_OS2_W32 || UNIX || __BEOS__ */ +#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))); + 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)); + free(tfilnam); + return 1; + } + free(tfilnam); +#else /* !TOPS20 */ +#ifdef MTS + if (uO.aflag) + G.outfile = fopen(G.filename, FOPWT); + else + G.outfile = fopen(G.filename, FOPW); + if (G.outfile == (FILE *)NULL) { + Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), + FnFilter1(G.filename))); + return 1; + } +#else /* !MTS */ +#ifdef TANDEM + if (SSTAT(G.filename, &G.statbuf) == 0) { + Trace((stderr, "open_outfile: stat(%s) returns 0 (file exists)\n", + FnFilter1(G.filename))); + if (unlink(G.filename) != 0) { + Trace((stderr, "open_outfile: existing file %s is read-only\n", + FnFilter1(G.filename))); + chmod(G.filename, S_IRUSR | S_IWUSR); + Trace((stderr, "open_outfile: %s now writable\n", + FnFilter1(G.filename))); + if (unlink(G.filename) != 0) + return 1; + } + Trace((stderr, "open_outfile: %s now deleted\n", + FnFilter1(G.filename))); + } + if (G.pInfo->textmode) + G.outfile = fopen(G.filename, FOPWT); + else + G.outfile = fopen(G.filename, FOPW); + if (G.outfile == (FILE *)NULL) { + Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), + FnFilter1(G.filename))); + return 1; + } +#else /* !TANDEM */ +#ifdef DEBUG + Info(slide, 1, ((char *)slide, + "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G.filename))); + if ((G.outfile = fopen(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 = fopen(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 ((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))); +#endif /* !TANDEM */ +#endif /* !MTS */ +#endif /* !TOPS20 */ + +#ifdef USE_FWRITE +#ifdef DOS_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_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_OS2_W32 */ +#endif /* USE_FWRITE */ + return 0; + +} /* end function open_outfile() */ + +#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 ((long)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) { + G.incnt = 0; /* do not allow negative value to affect stuff */ + 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() */ + + + + + +#ifdef USE_ZLIB + +/************************/ +/* 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 */ + + + + + +#ifndef VMS /* for VMS use code in vms.c */ + +/********************/ +/* Function flush() */ /* returns PK error codes: */ +/********************/ /* if cflag => always 0; PK_DISK if write error */ + +int flush(__G__ rawbuf, size, unshrink) + __GDEF + uch *rawbuf; + ulg size; + int unshrink; +{ + register uch *p, *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) + writeToMemory(__G__ rawbuf, size); + 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 0; + } 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", OUTBUFSIZ)); +#endif + } + if (G.newfile) { +#ifdef VMS_TEXT_CONV + /* GRR: really want to check if -aa (or -aaa?) was given... */ + if (rawbuf[1]) { /* first line is more than 255 chars long */ + Trace((stderr, + "\nfirst line of VMS `text' too long; switching to normal extraction\n")); + G.VMS_line_state = -1; /* -1: don't treat as VMS text */ + } else + G.VMS_line_state = 0; /* 0: ready to read line length */ +#endif + G.didCRlast = FALSE; /* no previous buffers written */ + G.newfile = FALSE; + } + +#ifdef VMS_TEXT_CONV + if (G.pInfo->hostnum == VMS_ && G.extra_field && G.VMS_line_state >= 0) + { + /* GRR: really want to check for actual VMS extra field, and + * ideally for variable-length record format */ +/* + printf("\n>>>>>> GRR: file is VMS text and has an extra field\n"); + */ + + p = rawbuf; + q = transbuf; + while(p < rawbuf+(unsigned)size) { + switch (G.VMS_line_state) { + + /* 0: ready to read line length */ + case 0: + G.VMS_line_length = 0; + G.VMS_line_pad = 0; + if (p == rawbuf+(unsigned)size-1) { /* last char */ + G.VMS_line_length = (int)((uch)(*p++)); + G.VMS_line_state = 1; + } else { + G.VMS_line_length = makeword(p); + p += 2; + G.VMS_line_state = 2; + } + if (G.VMS_line_length & 1) /* odd */ + G.VMS_line_pad = 1; + break; + + /* 1: read one byte of length, need second */ + case 1: + G.VMS_line_length += ((int)((uch)(*p++)) << 8); + G.VMS_line_state = 2; + break; + + /* 2: ready to read VMS_line_length chars */ + case 2: + if (G.VMS_line_length < rawbuf+(unsigned)size-p) { + if (G.VMS_line_length >= + transbuf+(unsigned)transbufsiz-q) + { + int outroom = transbuf+(unsigned)transbufsiz-q; + +/* GRR: need to change this to *q++ = native(*p++); loop or something */ + memcpy(q, p, outroom); +#ifdef DLL + if (G.redirect_data) + writeToMemory(__G__ transbuf, + (unsigned)outroom); + else +#endif + if (!uO.cflag && WriteError(transbuf, + (unsigned)outroom, G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, + transbuf, (ulg)outroom, 0)) + return 0; + q = transbuf; + p += outroom; + G.VMS_line_length -= outroom; + /* fall through to normal case */ + } +/* GRR: need to change this to *q++ = native(*p++); loop or something */ + memcpy(q, p, G.VMS_line_length); + q += G.VMS_line_length; + p += G.VMS_line_length; + G.VMS_line_length = 0; /* necessary?? */ + G.VMS_line_state = 3; + + } else { /* remaining input is less than full line */ + int remaining = rawbuf+(unsigned)size-p; + + if (remaining < + transbuf+(unsigned)transbufsiz-q) + { + int outroom = transbuf+(unsigned)transbufsiz-q; + +/* GRR: need to change this to *q++ = native(*p++); loop or something */ + memcpy(q, p, outroom); +#ifdef DLL + if (G.redirect_data) + writeToMemory(__G__ transbuf, + (unsigned)(outroom)); + else +#endif + if (!uO.cflag && WriteError(transbuf, + (unsigned)outroom, G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, + transbuf, (ulg)outroom, 0)) + return 0; + q = transbuf; + p += outroom; + remaining -= outroom; + } +/* GRR: need to change this to *q++ = native(*p++); loop or something */ + memcpy(q, p, remaining); + q += remaining; + p += remaining; + G.VMS_line_length -= remaining; + /* no change in G.VMS_line_state */ + } + break; + + /* 3: ready to PutNativeEOL */ + case 3: + if (q > transbuf+(unsigned)transbufsiz-lenEOL) { +#ifdef DLL + if (G.redirect_data) + writeToMemory(__G__ transbuf, + (unsigned)(q-transbuf)); + else +#endif + if (!uO.cflag && + WriteError(transbuf, (unsigned)(q-transbuf), + G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, + transbuf, (ulg)(q-transbuf), 0)) + return 0; + q = transbuf; + } + PutNativeEOL + if (G.VMS_line_pad) + if (p < rawbuf+(unsigned)size) { + ++p; + G.VMS_line_state = 0; + } else + G.VMS_line_state = 4; + else + G.VMS_line_state = 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; p < rawbuf+(unsigned)size; ++p) { + if (*p == CR) { /* lone CR or CR/LF: EOL either way */ + PutNativeEOL + if (p == rawbuf+(unsigned)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+(unsigned)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, + (unsigned)(q-transbuf), G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, + transbuf, (ulg)(q-transbuf), 0)) + return 0; + 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) + writeToMemory(__G__ transbuf, (unsigned)(q-transbuf)); + else +#endif + if (!uO.cflag && WriteError(transbuf, (unsigned)(q-transbuf), + G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, + (ulg)(q-transbuf), 0)) + return 0; + } + } + + return 0; + +} /* end function flush() */ + + + + + +/*************************/ +/* 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, 9, 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-1; +#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 + /* room for --More-- and one line of overlap: */ + ((Uz_Globs *)pG)->height = SCREENLINES - 2; +#endif + + 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) + { + ++((Uz_Globs *)pG)->numlines; + if (((Uz_Globs *)pG)->numlines % + ((Uz_Globs *)pG)->height == 0L) /* GRR: fix */ + (*((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') { + ++((Uz_Globs *)pG)->numlines; + if (((Uz_Globs *)pG)->numlines % + ((Uz_Globs *)pG)->height == 0L) /* GRR: fix */ + { + if ((error = WriteError(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); + } + } + } /* end while */ + size = (ulg)(p - q); /* remaining text */ + } +#endif /* MORE */ + + if (size) { +#ifdef OS2DLL + if (!((Uz_Globs *)pG)->redirect_text) { +#endif + if ((error = WriteError(q, size, outfp)) != 0) + return error; + fflush(outfp); + if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag && + !isatty(1) && isatty(2)) + { + /* error output from testing redirected: also send to stderr */ + if ((error = WriteError(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 + ((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 */ + { +#if 0 + 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 (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 (ToLower(c) == 'q') { + DESTROYGLOBALS() + EXIT(PK_COOL); + } + + ((Uz_Globs *)pG)->sol = TRUE; + +#endif +} /* 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 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(AMIGA) || 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_UNKNOWN) + { + 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 && !uO.overwrite_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 && !uO.overwrite_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__ len, option) /* return PK-type error code */ + __GDEF + unsigned int len; /* without prototype, ush converted to this */ + int option; +{ + long comment_bytes_left, block_length; + int error=PK_OK; + ush extra_len; +#ifdef AMIGA + char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */ +#endif + + +/*--------------------------------------------------------------------------- + This function processes arbitrary-length (well, usually) strings. Four + options are allowed: SKIP, wherein the string is skipped (pretty logical, + eh?); DISPLAY, wherein the string is printed to standard output after un- + dergoing any necessary or unnecessary character conversions; DS_FN, + wherein the string is put into the filename[] array after undergoing ap- + propriate 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 len. So start off by checking length + of string: if zero, we're already done. + ---------------------------------------------------------------------------*/ + + if (!len) + return PK_COOL; + + switch (option) { + + /* + * First case: print string on standard output. First set loop vari- + * ables, 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 = len; + block_length = OUTBUFSIZ; /* for the while statement, first time */ + while (comment_bytes_left > 0 && block_length > 0) { + register uch *p = G.outbuf; + register uch *q = G.outbuf; + + if ((block_length = readbuf(__G__ (char *)G.outbuf, + (unsigned) MIN((long)OUTBUFSIZ, comment_bytes_left))) == 0) + return PK_EOF; + comment_bytes_left -= block_length; + + /* this is why we allocated an extra byte for outbuf: terminate + * with zero (ASCIIZ) */ + G.outbuf[(unsigned)block_length] = '\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_length 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.crec.version_made_by[0]); +#ifdef WINDLL + /* translate to ANSI (RTL internal codepage may be OEM) */ + INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf); +#else /* !WINDLL */ +#ifdef WIN32 + /* 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 */ +#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, len, (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: + extra_len = 0; + if (len >= FILNAMSIZ) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(FilenameTooLongTrunc))); + error = PK_WARN; + extra_len = (ush)(len - FILNAMSIZ + 1); + len = FILNAMSIZ - 1; + } + if (readbuf(__G__ G.filename, len) == 0) + return PK_EOF; + G.filename[len] = '\0'; /* terminate w/zero: ASCIIZ */ + + /* 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.crec.version_made_by[0]); + + if (G.pInfo->lcflag) /* replace with lowercase filename */ + TOLOWER(G.filename, G.filename); + + if (G.pInfo->vollabel && len > 8 && G.filename[8] == '.') { + char *p = G.filename+8; + while (*p++) + p[-1] = *p; /* disk label, and 8th char is dot: remove dot */ + } + + if (!extra_len) /* 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))); + len = extra_len; + /* 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: */ + ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes + + (G.inptr-G.inbuf) + len) + 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(len)) == (uch *)NULL) { + Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong), + len)); + /* cur_zipfile_bufstart already takes account of extra_bytes, + * so don't correct for it twice: */ + ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes + + (G.inptr-G.inbuf) + len) + } else + if (readbuf(__G__ (char *)G.extra_field, len) == 0) + return PK_EOF; + 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 ((extra_len = readbuf(__G__ tmp_fnote, (unsigned) + MIN(len, 2 * AMIGA_FILENOTELEN - 1))) == 0) + return PK_EOF; + if ((len -= extra_len) > 0) /* treat remainder as in case SKIP: */ + ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes + + (G.inptr - G.inbuf) + len) + /* convert multi-line text into single line with no ctl-chars: */ + tmp_fnote[extra_len] = '\0'; + while ((short int) --extra_len >= 0) + if ((unsigned) tmp_fnote[extra_len] < ' ') + if (tmp_fnote[extra_len+1] == ' ') /* no excess */ + strcpy(tmp_fnote+extra_len, tmp_fnote+extra_len+1); + else + tmp_fnote[extra_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)sig[1]) << 8) + + ((ulg)sig[0]); +} + + + +#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 */ + + + + + +/************************/ +/* 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 (ToLower(*s1) < ToLower(*s2))? -1 : 1; + + if (*s1 == '\0') /* both strings terminate early */ + return 0; + } + return 0; +} + + + + + +#ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */ +# undef stat + +/********************/ +/* Function zstat() */ +/********************/ + +int zstat(p, s) + char *p; + struct stat *s; +{ + return (stat(p,s) >= 0? 0 : (-1)); +} + +#endif /* REGULUS */ + + + + + +#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; +} +#endif /* !_MSC_VER || (_MSC_VER < 600) */ + +#endif /* SMALL_MEM */ diff --git a/utils/Install/packzip/funzip.c b/utils/Install/packzip/funzip.c new file mode 100644 index 0000000000..e83ae424d2 --- /dev/null +++ b/utils/Install/packzip/funzip.c @@ -0,0 +1,468 @@ +/* funzip.c -- put in the public domain by Mark Adler */ + +#define VERSION "3.93 of 21 November 1998" + + +/* 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 + */ + + +/* + + 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 zcrypt21.zip or later must be used. + + */ + +#define FUNZIP +#define UNZIP_INTERNAL +#include "unzip.h" +#include "crypt.h" +#include "ttyio.h" + +#ifdef EBCDIC +# undef EBCDIC /* don't need ebcdic[] */ +#endif +#include "tables.h" /* crc_32_tab[] */ + +#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 */ + +/* 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)) + +/* Function prototypes */ +void err OF((int, char *)); +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 ush near mask_bits[] = { + 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 */ + + +#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) +#ifdef USE_ZLIB +ZCONST uLongf *get_crc_table() +{ + return (ZCONST uLongf *)crc_32_tab; +} +#else /* !USE_ZLIB */ +ZCONST ulg near *get_crc_table() +{ + return crc_32_tab; +} +#endif /* ?USE_ZLIB */ +#endif /* !USE_ZLIB || USE_OWN_CRCTAB */ + + +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); +} + + +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; +} + + +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 */ +#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 + G.area.Slide = (uch *)calloc(8193, sizeof(short)+sizeof(char)+sizeof(char)); +#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_H68_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_H68_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_OS2_W32 +#if (defined(__HIGHC__) && !defined(FLEXOS)) + setmode(stdout, _BINARY); +#else + setmode(1, O_BINARY); +#endif +#endif /* DOS_FLX_H68_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"); + if (SH(h + LOCHOW) != STORED && SH(h + LOCHOW) != DEFLATED) + err(3, "first entry not deflated or stored--cannot unpack"); + 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 (h[GZPHOW] != DEFLATED) + 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"); + } +#if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB)) + /* initialize crc_32_tab pointer for decryption */ + CRC_32_TAB = (ZCONST ulg Far *)get_crc_table(); +#endif + 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)) != 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 (++G.outcnt == WSIZE) /* do FlushOutput() */ + { + 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/utils/Install/packzip/globals.c b/utils/Install/packzip/globals.c new file mode 100644 index 0000000000..d795090b98 --- /dev/null +++ b/utils/Install/packzip/globals.c @@ -0,0 +1,204 @@ +/*--------------------------------------------------------------------------- + + 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}; +/* 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 + + 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_OS2_W32) && !defined(AMIGA) && !defined(RISCOS)) +#if (!defined(MACOS) && !defined(ATARI) && !defined(VMS)) + G.echofd = -1; +#endif /* !(MACOS || ATARI || VMS) */ +#endif /* !(DOS_FLX_H68_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/utils/Install/packzip/inflate.c b/utils/Install/packzip/inflate.c new file mode 100644 index 0000000000..29877300d2 --- /dev/null +++ b/utils/Install/packzip/inflate.c @@ -0,0 +1,1305 @@ +/* inflate.c -- put in the public domain by Mark Adler + version c16b, 29 March 1998 */ + + +/* 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 + */ + + +/* + 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 + */ + + +/* + 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. + */ + + +#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 DEBUG */ +#define INFMOD /* tell inflate.h to include code to be compiled */ +#include "inflate.h" + + +#ifndef WSIZE /* default is 32K */ +# define WSIZE 0x8000 /* window size--must be a power of two, and at least */ +#endif /* 32K for zip's deflate method */ + +#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) pipeit((char *)(str)) +#endif + +#ifndef FLUSH /* default is to simply write the buffer to stdout */ +# define FLUSH(n) fwrite(redirSlide, 1, n, stdout) /* return value not used */ +#endif +/* Warning: the fwrite above might not work on 16-bit compilers, since + 0x8000 might be interpreted as -32,768 by the library function. */ + +#ifndef Trace +# ifdef DEBUG +# define Trace(x) fprintf x +# else +# define Trace(x) +# endif +#endif + + +/*---------------------------------------------------------------------------*/ +#ifdef USE_ZLIB + + +/* + 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) /* decompress an inflated entry using the zlib routines */ + __GDEF +{ + int err=Z_OK; + +#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; + + /* only need to test this stuff once */ + if (zlib_version[0] != ZLIB_VERSION[0]) { + Info(slide, 0x21, ((char *)slide, + "error: incompatible zlib version (expected %s, found %s)\n", + ZLIB_VERSION, zlib_version)); + return 3; + } else if (strcmp(zlib_version, ZLIB_VERSION) != 0) + Info(slide, 0x21, ((char *)slide, + "warning: different zlib version (expected %s, using %s)\n", + ZLIB_VERSION, zlib_version)); + + /* windowBits = log2(wsize) */ + for (i = ((unsigned)wsize * 2 - 1), 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) + return 2; + else if (err == Z_MEM_ERROR) + return 3; + 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) + return 2; /* no "END-condition" yet, but no more data */ + + G.dstrm.next_in = G.inptr; + G.dstrm.avail_in = G.incnt; + } + Trace((stderr, " avail_in = %d\n", G.dstrm.avail_in)); + } + FLUSH(wsize - G.dstrm.avail_out); /* flush slide[] */ + 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)); + while (err != Z_STREAM_END) { + err = inflate(&G.dstrm, Z_PARTIAL_FLUSH); + if (err == Z_DATA_ERROR) + return 2; + else if (err == Z_MEM_ERROR) + return 3; + else if (err == Z_BUF_ERROR) { /* DEBUG */ + Trace((stderr, "zlib inflate() did not detect stream end (%s, %s)\n" + , G.zipfn, G.filename)); + break; + } else if (err != Z_OK && err != Z_STREAM_END) { + Trace((stderr, "oops! (inflate(final loop) err = %d)\n", err)); + DESTROYGLOBALS() + EXIT(PK_MEM3); + } + FLUSH(wsize - G.dstrm.avail_out); /* final flush of slide[] */ + 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 = %ld, total out = %ld\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 */ + + err = inflateReset(&G.dstrm); + if (err != Z_OK) + Trace((stderr, "oops! (inflateReset() err = %d)\n", err)); + + return 0; +} + + +/*---------------------------------------------------------------------------*/ +#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, + int bl, int 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. */ +static ZCONST unsigned border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; +static ZCONST ush cplens[] = { /* Copy lengths for literal codes 257..285 */ + 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. */ +static ZCONST ush cplext[] = { /* Extra bits for literal codes 257..285 */ + 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, 99, 99}; /* 99==invalid */ +static ZCONST ush cpdist[] = { /* Copy offsets for distance codes 0..29 */ + 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, + 8193, 12289, 16385, 24577}; +static ZCONST ush cpdext[] = { /* Extra bits for distance codes */ + 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}; + + +/* 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 ush near mask_bits[] = { + 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 begining 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. + */ + +/* 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)<>=(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. + */ + + +static ZCONST int lbits = 9; /* bits in base literal/length lookup table */ +static ZCONST int dbits = 6; /* bits in base distance lookup table */ + + +#ifndef ASM_INFLATECODES + +int inflate_codes(__G__ tl, td, bl, bd) + __GDEF +struct huft *tl, *td; /* literal/length and distance decoder tables */ +int 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 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 */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* 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((unsigned)bl) + if ((e = (t = tl + ((unsigned)b & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + if (e == 16) /* then it's a literal */ + { + redirSlide[w++] = (uch)t->v.n; + if (w == wsize) + { + FLUSH(w); + w = 0; + } + } + else /* it's an EOB or a length */ + { + /* exit if end of block */ + if (e == 15) + break; + + /* 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((unsigned)bd) + if ((e = (t = td + ((unsigned)b & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + NEEDBITS(e) + d = 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 (d >= wsize) + return 1; /* invalid compressed data */ + n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); + } + else +#endif + n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e); +#ifndef NOMEMCPY + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(redirSlide + 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) + { + FLUSH(w); + w = 0; + } + } while (n); + } + } + + + /* restore the globals from the locals */ + G.wp = w; /* restore global window pointer */ + G.bb = b; /* restore global bit buffer */ + G.bk = k; + + + /* done */ + return 0; +} + +#endif /* ASM_INFLATECODES */ + + + +static int inflate_stored(__G) + __GDEF +/* "decompress" an inflated type 0 (stored) block. */ +{ + unsigned n; /* number of bytes in block */ + unsigned w; /* current window position */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* 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) + { + FLUSH(w); + w = 0; + } + DUMPBITS(8) + } + + + /* restore the globals from the locals */ + G.wp = w; /* restore global window pointer */ + G.bb = b; /* restore global bit buffer */ + G.bk = k; + return 0; +} + + +/* 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; + if ((i = huft_build(__G__ l, 288, 257, cplens, cplext, + &G.fixed_tl, &G.fixed_bl)) != 0) + { + G.fixed_tl = (struct huft *)NULL; + return i; + } + + /* distance table */ + for (i = 0; i < 30; i++) /* make an incomplete code set */ + l[i] = 5; + G.fixed_bd = 5; + if ((i = huft_build(__G__ l, 30, 0, cpdist, cpdext, + &G.fixed_td, &G.fixed_bd)) > 1) + { + huft_free(G.fixed_tl); + 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) != 0; +} + + + +static int inflate_dynamic(__G) + __GDEF +/* decompress an inflated type 2 (dynamic Huffman codes) block. */ +{ + int 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; /* literal/length code table */ + struct huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int 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 */ +#ifdef PKZIP_BUG_WORKAROUND + unsigned ll[288+32]; /* literal/length and distance code lengths */ +#else + unsigned ll[286+30]; /* literal/length and distance code lengths */ +#endif + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* 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) +#ifdef PKZIP_BUG_WORKAROUND + if (nl > 288 || nd > 32) +#else + if (nl > 286 || nd > 30) +#endif + 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; + i = huft_build(__G__ ll, 19, 19, NULL, NULL, &tl, &bl); + if (bl == 0) /* no bit lengths */ + i = 1; + if (i) + { + if (i == 1) + huft_free(tl); + return i; /* incomplete code set */ + } + + + /* read in literal and distance code lengths */ + n = nl + nd; + m = mask_bits[bl]; + i = l = 0; + while ((unsigned)i < n) + { + NEEDBITS((unsigned)bl) + j = (td = tl + ((unsigned)b & m))->b; + DUMPBITS(j) + j = td->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) + 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) + 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) + 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; + i = huft_build(__G__ ll, nl, 257, cplens, cplext, &tl, &bl); + if (bl == 0) /* no literals or lengths */ + i = 1; + if (i) + { + if (i == 1) { + if (!uO.qflag) + MESSAGE((uch *)"(incomplete l-tree) ", 21L, 1); + huft_free(tl); + } + return i; /* incomplete code set */ + } + bd = dbits; + i = huft_build(__G__ ll + nl, nd, 0, cpdist, cpdext, &td, &bd); + if (bd == 0 && nl > 257) /* lengths but no distances */ + { + if (!uO.qflag) + MESSAGE((uch *)"(incomplete d-tree) ", 21L, 1); + huft_free(tl); + return 1; + } + if (i == 1) { +#ifdef PKZIP_BUG_WORKAROUND + i = 0; +#else + if (!uO.qflag) + MESSAGE((uch *)"(incomplete d-tree) ", 21L, 1); + huft_free(td); +#endif + } + if (i) + { + huft_free(tl); + return i; + } + + + /* decompress until an end-of-block code */ + if (inflate_codes(__G__ tl, td, bl, bd)) + return 1; + + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + return 0; +} + + + +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 */ + + + /* 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 */ + return 2; +} + + + +int inflate(__G) + __GDEF +/* 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; + + + /* 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); + + + /* flush out redirSlide */ + FLUSH(G.wp); + + + /* return success */ + Trace((stderr, "\n%u bytes in Huffman tables (%d/entry)\n", + h * sizeof(struct huft), sizeof(struct huft))); + return 0; +} + + + +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 ush *e; /* list of extra bits for non-simple codes */ + struct huft **t; /* result: starting table */ + int *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 ((unsigned)*m < j) + *m = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((unsigned)*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) > (unsigned)*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)(16 + 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 = 99; /* out of values--invalid code */ + else if (*p < s) + { + r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ + r.v.n = (ush)*p++; /* simple code is just the value */ + } + else + { + r.e = (uch)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/utils/Install/packzip/list.c b/utils/Install/packzip/list.c new file mode 100644 index 0000000000..60fa4dc044 --- /dev/null +++ b/utils/Install/packzip/list.c @@ -0,0 +1,649 @@ +/*--------------------------------------------------------------------------- + + 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 Ratio 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[] = + "%8lu %-7s%8lu %4s %02u-%02u-%02u %02u:%02u %08lx %c"; + static ZCONST char Far LongFileTrailer[] = + "-------- ------- --- \ + -------\n%8lu %8lu %4s %u file%s\n"; +#ifdef OS2_EAS + static ZCONST char Far ShortHdrStats[] = + "%9lu %6lu %6lu %02u-%02u-%02u %02u:%02u %c"; + static ZCONST char Far ShortFileTrailer[] = " -------- ----- ----- \ + -------\n%9lu %6lu %6lu %u file%s\n"; + static ZCONST char Far OS2ExtAttrTrailer[] = + "%ld file%s %ld bytes of OS/2 extended attributes attached.\n"; + static ZCONST char Far OS2ACLTrailer[] = + "%ld file%s %ld bytes of access control lists attached.\n"; +#else + static ZCONST char Far ShortHdrStats[] = + "%9lu %02u-%02u-%02u %02u:%02u %c"; + static ZCONST char Far ShortFileTrailer[] = + " -------- -------\n%9lu %u 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; + unsigned j, methnum, members=0; +#ifdef USE_EF_UT_TIME + iztimes z_utime; + struct tm *t; +#endif + unsigned yr, mo, dy, hh, mm; + ulg 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:#", "EnhDefl", "ImplDCL", "Unk:###"}; + +extern int files; + + +/*--------------------------------------------------------------------------- + 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; + + files = 0; + +#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 = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) { + + if (readbuf(__G__ G.sig, 4) == 0) + return PK_EOF; + if (strncmp(G.sig, central_hdr_sig, 4)) { /* just to make sure */ + 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; + + do_this_file = FALSE; + for (i = 0; i < G.filespecs; i++) + if (match(G.filename, G.pfnames[i], uO.C_flag)) { + 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)) { + 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 % 100); + 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) + + 80) % (unsigned)100); + 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 = (unsigned)mo; + mo = yr; yr = dy; dy = (ush)methnum; + break; + case DF_DMY: + methnum = (unsigned)mo; + mo = dy; dy = (ush)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 = MIN(G.crec.compression_method, NUM_METHODS); + zfstrcpy(methbuf, method[methnum]); + if (methnum == DEFLATED) { + 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_OS2_W32) || defined(UNIX) + for (p = G.filename; *p; ++p) + if (!isprint(*p)) + *p = '?'; /* change non-printable chars to '?' */ +#endif /* DOS_FLX_OS2_W32 || UNIX */ +#endif /* 0 */ + +#ifdef WINDLL + /* send data to application for formatting and printing */ + (*G.lpUserFunctions->SendApplicationMessage)(G.crec.ucsize, csiz, + (ush)cfactor, mo, dy, yr, hh, mm, + (char)(G.pInfo->lcflag ? '^' : ' '), + (LPSTR)fnfilter(G.filename, slide), (LPSTR)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), + G.crec.ucsize, methbuf, csiz, cfactorstr, mo, dy, + yr, hh, mm, G.crec.crc32, (G.pInfo->lcflag? '^':' '))); + else +#ifdef OS2_EAS + Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats), + G.crec.ucsize, ea_size, acl_size, + mo, dy, yr, hh, mm, (G.pInfo->lcflag? '^':' '))); +#else + Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats), + G.crec.ucsize, + mo, dy, yr, hh, mm, (G.pInfo->lcflag? '^':' '))); +#endif + /* fnprint(__G);*/ + files++; +#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 = 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), + tot_ucsize, tot_csize, 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), + tot_ucsize, tot_easize, tot_aclsize, members, members == 1? + "" : "s")); +#else + Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer), + tot_ucsize, members, members == 1? "" : "s")); +#endif /* OS2_EAS */ +#endif /* ?WINDLL */ + } + +/*--------------------------------------------------------------------------- + Double check that we're back at the end-of-central-directory record. + ---------------------------------------------------------------------------*/ + + if (readbuf(__G__ G.sig, 4) == 0) /* disk error? */ + return PK_EOF; + if (strncmp(G.sig, end_central_sig, 4)) { /* just to make sure again */ + Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); + error_in_archive = PK_WARN; /* didn't find sig */ + } + if (members == 0 && 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 = G.filename[fn_len-1]) == '/' || + (G.pInfo->hostnum == FS_FAT_ && !strchr(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; + unsigned *nmember; +{ + int do_this_file=FALSE, error, error_in_archive=PK_COOL; + unsigned 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 = 0; + G.pInfo = &info; + + for (j = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) { + + if (readbuf(__G__ G.sig, 4) == 0) + return PK_EOF; + if (strncmp(G.sig, central_hdr_sig, 4)) { /* just to make sure */ + Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j)); + Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); + return PK_BADERR; + } + /* 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; + + do_this_file = FALSE; + for (i = 0; i < G.filespecs; i++) + if (match(G.filename, G.pfnames[i], uO.C_flag)) { + 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)) { + 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 (readbuf(__G__ G.sig, 4) == 0) + return PK_EOF; + if (strncmp(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 == 0 && 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) + ulg uc, c; +{ + ulg 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); + + (*G.message)((zvoid *)&G, (uch *)name, (ulg)strlen(name), 0); + (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); + +} /* end function fnprint() */ diff --git a/utils/Install/packzip/makefile b/utils/Install/packzip/makefile new file mode 100644 index 0000000000..e5b1b70ec4 --- /dev/null +++ b/utils/Install/packzip/makefile @@ -0,0 +1,146 @@ +#============================================================================== +# Makefile for UnZip, UnZipSFX and fUnZip: Unix and MS-DOS ("real" makes only) +# Version: 5.4 19 November 1998 +#============================================================================== + + +# INSTRUCTIONS (such as they are): +# +# "make sunos" -- makes UnZip in current directory on a generic SunOS 4.x Sun +# "make list" -- lists all supported systems (targets) +# "make help" -- provides pointers on what targets to try if problems occur +# "make wombat" -- chokes and dies if you haven't added the specifics for your +# Wombat 68000 (or whatever) to the systems list +# +# 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). +# +# Some versions of make do not define the macro "$(MAKE)"; this is rare, but +# if things don't work, try using "make" instead of "$(MAKE)" in your system's +# makerule. Or try adding the following line to your .login file: +# setenv MAKE "make" +# (That never works--makes that are too stupid to define MAKE are also too +# stupid to look in the environment--but try it anyway for kicks. :-) ) +# +# Memcpy and memset are provided for those systems that don't have them; they +# are in fileio.c and will be used if -DZMEM is included in CF. These days +# almost all systems have them. +# +# 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 = cc# try using "gcc" target rather than changing this (CC and LD +LD = $(CC)# must match, else "unresolved symbol: ___main" is possible) +AS = as +LOC = $(LOCAL_UNZIP) +AF = $(LOC) +CF = -O -I. -I.. -I../inczip $(LOC) +LF = -o packinst +LF2 = -s + +# general-purpose stuff +#CP = cp +CP = ln +LN = ln +RM = rm -f +CHMOD = chmod +BINPERMS = 755 +MANPERMS = 644 +STRIP = strip +E = +O = .o +M = unix +SHELL = /bin/sh + +# defaults for crc32 stuff and system dependent headers +CRC32 = crc32 + +# object files +OBJS1 = unzip$O $(CRC32)$O crctab$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 unreduce$O unshrink$O zipinfo$O +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O packinst$O +#OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O install$O wxmain$O instsup$O +UNZIP_H = ../inczip/unzip.h ../inczip/unzpriv.h ../inczip/globals.h + +# installation +# (probably can change next two to `install' and `install -d' if you have it) +INSTALL = cp +INSTALL_D = mkdir -p + +############################################### +# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES # +############################################### + +# this is for GNU make; comment out and notify zip-bugs if it causes errors +.SUFFIXES: .c .o .obj .pic.o + +# 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 + +.c.pic.o: + $(CC) -c $(CF) -o $@ $*.c + +all: sfx + + +# EDIT HERE FOR PARALLEL MAKES on Sequent (and others?)--screws up MS-DOS +# make utilities if default: change "unzip$E:" to "unzip$E:&" + +sfx$E: $(OBJS) # add `&' for parallel makes + $(LD) $(LF) $(OBJS) + +crc32$O: crc32.c $(UNZIP_H) ../inczip/zip.h +crctab$O: crctab.c $(UNZIP_H) ../inczip/zip.h +crypt$O: crypt.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h +envargs$O: envargs.c $(UNZIP_H) +explode$O: explode.c $(UNZIP_H) +extract$O: extract.c $(UNZIP_H) ../inczip/crypt.h +fileio$O: fileio.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/ebcdic.h +funzip$O: funzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/tables.h +globals$O: globals.c $(UNZIP_H) +inflate$O: inflate.c ../inczip/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) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h +unreduce$O: unreduce.c $(UNZIP_H) +unshrink$O: unshrink.c $(UNZIP_H) +unzip$O: unzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/version.h ../inczip/consts.h +zipinfo$O: zipinfo.c $(UNZIP_H) + +unix$O: unix.c $(UNZIP_H) ../inczip/version.h # Unix only + $(CC) -c $(CF) unix.c + +packinst$O: ../packinst/packinst.c + $(CC) -c $(CF) ../packinst/packinst.c + +#install$O: ../install.c +# $(CC) -c $(CF) ../install.c +# +#unix$O: ../wxmain.cpp +# $(CC) -c $(CF) ../wxmain.cpp +# +#unix$O: ../instsup.cpp +# $(CC) -c $(CF) ../instsup.cpp + + + diff --git a/utils/Install/packzip/makefile.b32 b/utils/Install/packzip/makefile.b32 new file mode 100644 index 0000000000..7734f0f7b3 --- /dev/null +++ b/utils/Install/packzip/makefile.b32 @@ -0,0 +1,118 @@ +# Makefile for UnZip(SFX) and fUnZip for Borland C++ for Windows 95/NT +# Version: 5.4 and later Alvin Koh, Jim Knoble, Christian Spieler, etc. +# Adapted from the MS-DOS makefile by E-Yen Tan +# +# Last revised: 24 Nov 98 +# +# + + +# 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 = 4 + +# (De)Select inclusion of optimized assembler CRC32 routine: +USE_ASMCRC = 0 + +# If you have bcc32i, you should define: +# CC = bcc32i +# This compiler generates a faster code. +CC = bcc32 +AS = tasm32 + +!if $(USE_ASMCRC) +ASMFLG = -DASM_CRC +ASMOBJS = crc_i386.obj +!else +ASMFLG = +ASMOBJS = +!endif + +!if $(UNCLEAN) +DIRT = -DUSE_SMITH_CODE -DUSE_UNSHRINK +!else +DIRT = +!endif + +# compiler flags + +ASCPUFLAG = __$(CPU_TYP)86 +!if $(CPU_TYP) != 0 +CC_CPUFLG = -$(CPU_TYP) +!endif +ASFLAGS = -ml -m2 -w0 -D$(ASCPUFLAG) $(LOC) +CFLAGS = -O2 -w- $(CC_CPUFLG) -ff- -k- -P-.C -I. -I.. -I..\inczip -DWIN32 $(ASMFLG) $(LOC) $(DIRT) +LDFLAGS = -lxncd -l-P # for bcc +UNFLAGS = $(CFLAGS) + +# implicit rules + +.asm.obj: + $(AS) $(ASFLAGS) $< + +.c.obj: + $(CC) -c $(UNFLAGS) {$< } + +# list macros + +OBJU1 = unzip.obj crc32.obj crctab.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 = win32.obj nt.obj $(ASMOBJS) packinst.obj +OBJU = $(OBJU1) $(OBJU2) $(OBJU3) $(OBJUS) + +UNZIP_H = ..\inczip\unzip.h ..\inczip\unzpriv.h ..\inczip\globals.h ..\inczip\w32cfg.h + +# explicit rules + +all: packinst.exe + +packinst.exe: $(OBJU) + $(CC) $(LDFLAGS) -epackinst.exe @&&| +$(OBJU) +| + +clean: + -erase *.obj + -erase *.exe + -erase *.res + -erase *.map + -erase *.rws + -erase *.tds + -erase *.il? + +# individual file dependencies + +crc32.obj: crc32.c $(UNZIP_H) ..\inczip\zip.h +crctab.obj: crctab.c $(UNZIP_H) ..\inczip\zip.h +crypt.obj: crypt.c $(UNZIP_H) ..\inczip\zip.h ..\inczip\crypt.h ..\inczip\ttyio.h +envargs.obj: envargs.c $(UNZIP_H) +explode.obj: explode.c $(UNZIP_H) +extract.obj: extract.c $(UNZIP_H) ..\inczip\crypt.h +fileio.obj: fileio.c $(UNZIP_H) ..\inczip\crypt.h ..\inczip\ttyio.h ..\inczip\ebcdic.h +globals.obj: globals.c $(UNZIP_H) +inflate.obj: inflate.c ..\inczip\inflate.h $(UNZIP_H) +list.obj: list.c $(UNZIP_H) +match.obj: match.c $(UNZIP_H) +process.obj: process.c $(UNZIP_H) +ttyio.obj: ttyio.c $(UNZIP_H) ..\inczip\zip.h ..\inczip\crypt.h ..\inczip\ttyio.h +unreduce.obj: unreduce.c $(UNZIP_H) +unshrink.obj: unshrink.c $(UNZIP_H) +unzip.obj: unzip.c $(UNZIP_H) ..\inczip\crypt.h ..\inczip\version.h ..\inczip\consts.h +zipinfo.obj: zipinfo.c $(UNZIP_H) + +crc_i386.obj: crc_i386.asm + $(AS) $(ASFLAGS) crc_i386.asm, $*.obj ; + +win32.obj: win32.c $(UNZIP_H) + $(CC) -c $(UNFLAGS) win32.c + +packinst.obj: ..\packinst\packinst.c $(UNZIP_H) + $(CC) -c $(UNFLAGS) ..\packinst\packinst.c + +nt.obj: nt.c $(UNZIP_H) + $(CC) -c $(UNFLAGS) nt.c diff --git a/utils/Install/packzip/makefile.g95 b/utils/Install/packzip/makefile.g95 new file mode 100644 index 0000000000..fdd6be493b --- /dev/null +++ b/utils/Install/packzip/makefile.g95 @@ -0,0 +1,158 @@ +# Makefile for UnZip, fUnZip and UnZipSFX for native Win32-Intel ports of gcc. +# Currently supported implementations: Cygnus/Win32 and MinGW32. +# +# First version: Cosmin Truta , Dec 1997. +# Last revision: Christian Spieler, 29-Apr-1998 +# +# To use, do "make -f win32/makefile.gcc". + + +### Optional section + +# Optional nonstandard preprocessor flags (as -DUSE_ZLIB or -DUSE_SMITH_CODE) +# should be added to the environment via "set LOCAL_UNZIP=-DFOO" or added +# to the declaration of LOCFLAGS here: +LOCFLAGS = $(LOCAL_UNZIP) + + +### Compiler-specific section + +# ------------ GNU C ------------ +CC = gcc + +#AS = as +AS = $(CC) + +#LD = ld +LD = $(CC) + +# Quiet +CC_QUIET_OPT = +AS_QUIET_OPT = $(CC_QUIET_OPT) +LD_QUIET_OPT = $(CC_QUIET_OPT) + +# Warnings +CC_WARN_OPT = -Wall +AS_WARN_OPT = $(CC_WARN_OPT) +LD_WARN_OPT = + +# Debug version +CC_DEBUG_OPT = -g +AS_DEBUG_OPT = $(CC_DEBUG_OPT) +LD_DEBUG_OPT = $(CC_DEBUG_OPT) + +# Release version +CC_RELEASE_OPT = +AS_RELEASE_OPT = +LD_RELEASE_OPT = -s + +# Smallest code +CC_SIZE_OPT = -O1 + +# Fastest code +CC_SPEED_OPT = -O2 + +# Output object file name +CC_OUT_OPT = -o + +# Other specific options +#CC_SPECIFIC_OPT = -c -DASM_CRC -DWIN32 -mno-cygwin +CC_SPECIFIC_OPT = -c -DWIN32 -mno-cygwin -I../inczip +AS_SPECIFIC_OPT = -c +LD_SPECIFIC_OPT = -mno-cygwin -o $@ + +# Libraries for the debug & release version +LD_RELEASE_LIBS = -luser32 -ladvapi32 +LD_DEBUG_LIBS = $(LD_RELEASE_LIBS) + + +### System-specific section + +# Suffixes +OBJ = .o +EXE = .exe + +.SUFFIXES: .c .S $(OBJ) $(EXE) + +# Commands +RM = rm -f + + +### General section + +CFLAGS = $(CC_SPECIFIC_OPT) $(CC_QUIET_OPT) $(CC_WARN_OPT) $(LOCFLAGS) \ + $(CC_OUT_OPT) $@ +ASFLAGS = $(AS_SPECIFIC_OPT) $(AS_QUIET_OPT) $(AS_WARN_OPT) $(LOCFLAGS) +LDFLAGS = $(LD_SPECIFIC_OPT) $(LD_QUIET_OPT) $(LD_WARN_OPT) + +# To build with debug info, use 'make DEBUG=1'. +ifdef DEBUG +CVER = $(CC_DEBUG_OPT) +ASVER = $(AS_DEBUG_OPT) +LDVER = $(LD_DEBUG_OPT) +GENFLAGS = +FFLAGS = -DFUNZIP +SFXFLAGS = -DSFX +LDLIBS = $(LD_DEBUG_LIBS) +else +CVER = $(CC_RELEASE_OPT) +ASVER = $(AS_RELEASE_OPT) +LDVER = $(LD_RELEASE_OPT) +GENFLAGS = $(CC_SPEED_OPT) +FFLAGS = $(CC_SPEED_OPT) -DFUNZIP +SFXFLAGS = $(CC_SIZE_OPT) -DSFX +LDLIBS = $(LD_RELEASE_LIBS) +endif + +# Object files +OBJA = crc_i386$(OBJ) packinst$(OBJ) +OBJS1 = unzip$(OBJ) crc32$(OBJ) crctab$(OBJ) crypt$(OBJ) envargs$(OBJ) +OBJS2 = explode$(OBJ) extract$(OBJ) fileio$(OBJ) globals$(OBJ) inflate$(OBJ) +OBJS3 = list$(OBJ) match$(OBJ) process$(OBJ) ttyio$(OBJ) unreduce$(OBJ) +OBJS4 = unshrink$(OBJ) zipinfo$(OBJ) win32$(OBJ) nt$(OBJ) +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJS4) $(OBJA) + +UNZIP_H = ../inczip/unzip.h ../inczip/unzpriv.h ../inczip/globals.h ../inczip/w32cfg.h + + +# Default target is all the executables +unzips: packinst$(EXE) + +packinst$(EXE): $(OBJS) + $(LD) $(LDFLAGS) $(LDVER) $(OBJS) $(LDLIBS) + +# How to compile sources +.c$(OBJ): + $(CC) $(CFLAGS) $(CVER) $(GENFLAGS) $< +.S$(OBJ): + $(AS) $(ASFLAGS) $(ASVER) $(GENFLAGS) $< + +# Dependencies +crc32$(OBJ): crc32.c $(UNZIP_H) ../inczip/zip.h +crctab$(OBJ): crctab.c $(UNZIP_H) ../inczip/zip.h +crypt$(OBJ): crypt.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h +envargs$(OBJ): envargs.c $(UNZIP_H) +explode$(OBJ): explode.c $(UNZIP_H) +extract$(OBJ): extract.c $(UNZIP_H) ../inczip/crypt.h +fileio$(OBJ): fileio.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/ebcdic.h +funzip$(OBJ): funzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/tables.h +globals$(OBJ): globals.c $(UNZIP_H) +inflate$(OBJ): inflate.c ../inczip/inflate.h $(UNZIP_H) +list$(OBJ): list.c $(UNZIP_H) +match$(OBJ): match.c $(UNZIP_H) +process$(OBJ): process.c $(UNZIP_H) +ttyio$(OBJ): ttyio.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h +unreduce$(OBJ): unreduce.c $(UNZIP_H) +unshrink$(OBJ): unshrink.c $(UNZIP_H) +unzip$(OBJ): unzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/version.h ../inczip/consts.h +zipinfo$(OBJ): zipinfo.c $(UNZIP_H) +crc_i386$(OBJ): crc_i386.S +win32$(OBJ): win32.c $(UNZIP_H) ../inczip/nt.h +nt$(OBJ): nt.c ../inczip/nt.h + +packinst$(OBJ): ../packinst/packinst.c + $(CC) $(CFLAGS) $(CVER) $(GENFLAGS) $< + +clean: + $(RM) *$(OBJ) + $(RM) *$(EXE) diff --git a/utils/Install/packzip/makefile.gcc b/utils/Install/packzip/makefile.gcc new file mode 100644 index 0000000000..e5b1b70ec4 --- /dev/null +++ b/utils/Install/packzip/makefile.gcc @@ -0,0 +1,146 @@ +#============================================================================== +# Makefile for UnZip, UnZipSFX and fUnZip: Unix and MS-DOS ("real" makes only) +# Version: 5.4 19 November 1998 +#============================================================================== + + +# INSTRUCTIONS (such as they are): +# +# "make sunos" -- makes UnZip in current directory on a generic SunOS 4.x Sun +# "make list" -- lists all supported systems (targets) +# "make help" -- provides pointers on what targets to try if problems occur +# "make wombat" -- chokes and dies if you haven't added the specifics for your +# Wombat 68000 (or whatever) to the systems list +# +# 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). +# +# Some versions of make do not define the macro "$(MAKE)"; this is rare, but +# if things don't work, try using "make" instead of "$(MAKE)" in your system's +# makerule. Or try adding the following line to your .login file: +# setenv MAKE "make" +# (That never works--makes that are too stupid to define MAKE are also too +# stupid to look in the environment--but try it anyway for kicks. :-) ) +# +# Memcpy and memset are provided for those systems that don't have them; they +# are in fileio.c and will be used if -DZMEM is included in CF. These days +# almost all systems have them. +# +# 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 = cc# try using "gcc" target rather than changing this (CC and LD +LD = $(CC)# must match, else "unresolved symbol: ___main" is possible) +AS = as +LOC = $(LOCAL_UNZIP) +AF = $(LOC) +CF = -O -I. -I.. -I../inczip $(LOC) +LF = -o packinst +LF2 = -s + +# general-purpose stuff +#CP = cp +CP = ln +LN = ln +RM = rm -f +CHMOD = chmod +BINPERMS = 755 +MANPERMS = 644 +STRIP = strip +E = +O = .o +M = unix +SHELL = /bin/sh + +# defaults for crc32 stuff and system dependent headers +CRC32 = crc32 + +# object files +OBJS1 = unzip$O $(CRC32)$O crctab$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 unreduce$O unshrink$O zipinfo$O +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O packinst$O +#OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O install$O wxmain$O instsup$O +UNZIP_H = ../inczip/unzip.h ../inczip/unzpriv.h ../inczip/globals.h + +# installation +# (probably can change next two to `install' and `install -d' if you have it) +INSTALL = cp +INSTALL_D = mkdir -p + +############################################### +# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES # +############################################### + +# this is for GNU make; comment out and notify zip-bugs if it causes errors +.SUFFIXES: .c .o .obj .pic.o + +# 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 + +.c.pic.o: + $(CC) -c $(CF) -o $@ $*.c + +all: sfx + + +# EDIT HERE FOR PARALLEL MAKES on Sequent (and others?)--screws up MS-DOS +# make utilities if default: change "unzip$E:" to "unzip$E:&" + +sfx$E: $(OBJS) # add `&' for parallel makes + $(LD) $(LF) $(OBJS) + +crc32$O: crc32.c $(UNZIP_H) ../inczip/zip.h +crctab$O: crctab.c $(UNZIP_H) ../inczip/zip.h +crypt$O: crypt.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h +envargs$O: envargs.c $(UNZIP_H) +explode$O: explode.c $(UNZIP_H) +extract$O: extract.c $(UNZIP_H) ../inczip/crypt.h +fileio$O: fileio.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/ebcdic.h +funzip$O: funzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/tables.h +globals$O: globals.c $(UNZIP_H) +inflate$O: inflate.c ../inczip/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) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h +unreduce$O: unreduce.c $(UNZIP_H) +unshrink$O: unshrink.c $(UNZIP_H) +unzip$O: unzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/version.h ../inczip/consts.h +zipinfo$O: zipinfo.c $(UNZIP_H) + +unix$O: unix.c $(UNZIP_H) ../inczip/version.h # Unix only + $(CC) -c $(CF) unix.c + +packinst$O: ../packinst/packinst.c + $(CC) -c $(CF) ../packinst/packinst.c + +#install$O: ../install.c +# $(CC) -c $(CF) ../install.c +# +#unix$O: ../wxmain.cpp +# $(CC) -c $(CF) ../wxmain.cpp +# +#unix$O: ../instsup.cpp +# $(CC) -c $(CF) ../instsup.cpp + + + diff --git a/utils/Install/packzip/makefile.os2 b/utils/Install/packzip/makefile.os2 new file mode 100644 index 0000000000..6778bd50ab --- /dev/null +++ b/utils/Install/packzip/makefile.os2 @@ -0,0 +1,670 @@ +# Makefile for UnZip, UnZipSFX and fUnZip 24 November 1998 +# +# 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). + +# 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" \ + CRC32="crc_i86" \ + CRC32F="crc_i86" \ + CRC32X="crc_i86" \ + 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" \ + CRC32="crc_i86" \ + CRC32F="crc_i86" \ + CRC32X="crc_i86" \ + DEF="os2\unzip.def" + +# cross-compilation for MS-DOS with MS C 6.00 (same comment as above...formerly; +# now unzip is medium model again, with [almost] all strings in far memory) +mscdos: + $(MAKE) -f os2/makefile.os2 all \ + CC="cl -nologo -AM -Oaict -Gs -I. $(FP)" \ + CFLAGS="-Zp1 -W3 -DASM_CRC $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="ml -nologo -c -Zm -Cp" \ + ASFLAGS="-D__MEDIUM__" \ + LDFLAGS="-F 0C00 -Lr -Fe" \ + LDFLAGS2="-link /noe /exe" \ + OUT="-Fo" \ + OBJ=".obj" \ + CRC32="crc_i86" \ + CRC32F="crc_i86" \ + CRC32X="crc_i86" \ + OBJU2="msdos.obj" \ + OBJX2="msdos_.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" \ + CRC32="crc_i386" \ + CRC32F="crc_i386" \ + CRC32X="crc_i386" \ + 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" \ + CRC32="crc_i86" \ + CRC32F="crc_i86" \ + CRC32X="crc_i86" \ + 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" \ + CRC32="crc_i386" \ + CRC32F="crc_i386" \ + CRC32X="crc_i386" \ + 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" \ + CRC32="crc_i386" \ + CRC32F="crc_i386" \ + CRC32X="crc_i386" \ + 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 -mm" \ + ASFLAGS="-D__MEDIUM__" \ + LDFLAGS="-k0xC00 -x -l=dos -Fe=" \ + LDFLAGS2="" \ + OUT="-Fo" \ + OBJ=".obj" \ + OBJU2="msdos.obj" \ + OBJX2="msdos_.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" \ + OBJU2="win32.obj nt.obj" \ + OBJX2="win32_.obj nt_.obj" \ + CRC32="crc_i386" \ + CRC32F="crc_i386" \ + CRC32X="crc_i386" \ + 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" \ + CRC32="crc_gcc" \ + CRC32F="crc_gcc" \ + CRC32X="crc_gcc" \ + 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" \ + CRC32="crc_gcc" \ + CRC32F="crc_gcc" \ + CRC32X="crc_gcc" \ + 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" \ + CRC32="crc_gcc" \ + CRC32F="crc_gcc" \ + CRC32X="crc_gcc" + +# 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" \ + CRC32="crc_gcc" \ + CRC32F="crc_gcc" \ + CRC32X="crc_gcc" \ + 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" \ + CRC32="crc_gcc" \ + CRC32F="crc_gcc" \ + CRC32X="crc_gcc" \ + 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 +CRC32 = crc32 +CRC32F = crc32f +CRC32X = crc32_ + +OBJU = unzip$(OBJ) $(CRC32)$(OBJ) crctab$(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) +OBJU2 = os2$(OBJ) os2acl$(OBJ) +OBJX = unzipsf_$(OBJ) $(CRC32X)$(OBJ) crctab_$(OBJ) crypt_$(OBJ) \ + extract_$(OBJ) fileio_$(OBJ) globals_$(OBJ) inflate_$(OBJ) \ + match_$(OBJ) process_$(OBJ) ttyio_$(OBJ) +OBJX2 = os2_$(OBJ) os2acl_$(OBJ) +OBJDLL= api$(OBJ) apihelp$(OBJ) rexxhelp$(OBJ) rexxapi$(OBJ) +OBJF = funzip$(OBJ) $(CRC32F)$(OBJ) 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) version.h +crc32$(OBJ): crc32.c $(UNZIP_H) zip.h +crctab$(OBJ): crctab.c $(UNZIP_H) zip.h +envargs$(OBJ): envargs.c $(UNZIP_H) +explode$(OBJ): explode.c $(UNZIP_H) +extract$(OBJ): extract.c $(UNZIP_H) crypt.h +fileio$(OBJ): fileio.c $(UNZIP_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) +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 version.h consts.h +api$(OBJ): api.c $(UNZIP_H) version.h +zipinfo$(OBJ): zipinfo.c $(UNZIP_H) + +funzip$(OBJ): funzip.c $(UNZIP_H) crypt.h ttyio.h tables.h # funzip only + $(CC) -c $(CFLAGS) funzip.c + +unzipstb$(OBJ): unzipstb.c # DLL version + $(CC) -c $(CFLAGS) unzipstb.c + +msdos$(OBJ): msdos/msdos.c $(UNZIP_H) version.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 + +win32$(OBJ): win32/win32.c $(UNZIP_H) win32/nt.h version.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) version.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 + +os2acl$(OBJ): os2/os2acl.c $(UNZIP_H) version.h # OS/2 only + $(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)os2acl.c + +os2acl_$(OBJ): os2/os2acl.c $(UNZIP_H) version.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 ttyio.h + $(CC) -c $(CFLAGS) $(DLLFLAG) $(NFLAGS) crypt.c + +cryptf$(OBJ): crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h # funzip only + $(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ crypt.c + +crc32f$(OBJ): crc32.c $(UNZIP_H) zip.h # funzip only + $(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ crc32.c + +globalsf$(OBJ): globals.c $(UNZIP_H) # funzip only + $(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ globals.c + +inflatef$(OBJ): inflate.c inflate.h $(UNZIP_H) crypt.h # funzip only + $(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ inflate.c + +ttyiof$(OBJ): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h # funzip only + $(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ ttyio.c + +crc32_$(OBJ): crc32.c $(UNZIP_H) zip.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crc32.c + +crctab_$(OBJ): crctab.c $(UNZIP_H) zip.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crctab.c + +crypt_$(OBJ): crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crypt.c + +extract_$(OBJ): extract.c $(UNZIP_H) crypt.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ extract.c + +fileio_$(OBJ): fileio.c $(UNZIP_H) crypt.h ttyio.h ebcdic.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ fileio.c + +globals_$(OBJ): globals.c $(UNZIP_H) # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ globals.c + +inflate_$(OBJ): inflate.c inflate.h $(UNZIP_H) crypt.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ inflate.c + +match_$(OBJ): match.c $(UNZIP_H) # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ match.c + +process_$(OBJ): process.c $(UNZIP_H) # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ process.c + +ttyio_$(OBJ): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ ttyio.c + +unzipsf_$(OBJ): unzip.c $(UNZIP_H) crypt.h version.h consts.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ unzip.c diff --git a/utils/Install/packzip/match.c b/utils/Install/packzip/match.c new file mode 100644 index 0000000000..77355d4400 --- /dev/null +++ b/utils/Install/packzip/match.c @@ -0,0 +1,294 @@ +/*--------------------------------------------------------------------------- + + 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); + + 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 ToLower() in here (for Unix, define ToLower to be macro (using + * isupper()); otherwise just use tolower() */ +#define UNZIP_INTERNAL +#include "unzip.h" + +#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)) +#define match(s,p,ic) (recmatch((ZCONST uch *)p,(ZCONST uch *)s,ic) == 1) +int recmatch OF((ZCONST uch *pattern, ZCONST uch *string, int ignore_case)); +#endif +#endif /* 0 */ +static int recmatch OF((ZCONST uch *pattern, ZCONST uch *string, + int ignore_case)); + + + +/* match() is a shell to recmatch() to return only Boolean values. */ + +int match(string, pattern, ignore_case) + ZCONST char *string, *pattern; + int ignore_case; +{ +#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 = strchr(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); + free(dospattern); + return j == 1; + } else +#endif /* MSDOS && DOSWILD */ + return recmatch((uch *)pattern, (uch *)string, ignore_case) == 1; +} + + + +static int recmatch(p, s, ic) + ZCONST uch *p; /* sh pattern to match */ + ZCONST uch *s; /* string to which to match it */ + int ic; /* true for case insensitivity */ +/* 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++; + + /* 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) + return *s ? recmatch(p, s + 1, ic) : 0; + + /* '*' matches any number of characters, including zero */ +#ifdef AMIGA + if (c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */ + c = '*', p++; +#endif /* AMIGA */ + if (c == '*') { + if (*p == 0) + return 1; + for (; *s; s++) + if ((c = recmatch(p, s, ic)) != 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; 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; p++) { /* go through the list */ + if (e == 0 && *p == '\\') /* set escape flag if \ */ + e = 1; + else if (e == 0 && *p == '-') /* set start of range if - */ + c = *(p-1); + else { + 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); + c = e = 0; /* clear range, escape flags */ + } + } + return r ? recmatch(q + 1, s + 1, ic) : 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, ic) : 0; +#else + return Case((uch)c) == Case(*s) ? recmatch(p, ++s, ic) : 0; +#endif + +} /* end function recmatch() */ + + + + + +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; ++p) + if (*p == '\\' && *(p+1)) + ++p; +#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 */ +#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);} + +void main() +{ + 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; + pipeit("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/utils/Install/packzip/nt.c b/utils/Install/packzip/nt.c new file mode 100644 index 0000000000..ab4cea3a9f --- /dev/null +++ b/utils/Install/packzip/nt.c @@ -0,0 +1,659 @@ +/* + + Copyright (c) 1996 Scott Field + + Module Name: + + nt.c + + Abstract: + + This module implements WinNT security descriptor operations for the + Win32 Info-ZIP project. Operation such as setting file security, + using/querying local and remote privileges, and queuing of operations + is performed here. The contents of this module are only relevant + when the code is running on Windows NT, and the target volume supports + persistent Acl storage. + + User privileges that allow accessing certain privileged aspects of the + security descriptor (such as the Sacl) are only used if the user specified + to do so. + + Author: + + Scott Field (sfield@microsoft.com) + + Last revised: 18 Jan 97 + + */ + +#define WIN32_LEAN_AND_MEAN +#define UNZIP_INTERNAL +#include "unzip.h" +#include +#ifdef __RSXNT__ +# include "rsxntwin.h" +#endif +#include "nt.h" + + +#ifdef NTSD_EAS /* This file is only needed for NTSD handling */ + +/* Borland C++ does not define FILE_SHARE_DELETE. Others also? */ +#ifndef FILE_SHARE_DELETE +# define FILE_SHARE_DELETE 0x00000004 +#endif + + +/* private prototypes */ + +static BOOL Initialize(VOID); +#if 0 /* currently unused */ +static BOOL Shutdown(VOID); +#endif +static BOOL DeferSet(char *resource, PVOLUMECAPS VolumeCaps, uch *buffer); +static VOID GetRemotePrivilegesSet(CHAR *FileName, PDWORD dwRemotePrivileges); +static VOID InitLocalPrivileges(VOID); + + +BOOL bInitialized = FALSE; /* module level stuff initialized? */ +HANDLE hInitMutex = NULL; /* prevent multiple initialization */ + +BOOL g_bRestorePrivilege = FALSE; /* for local set file security override */ +BOOL g_bSaclPrivilege = FALSE; /* for local set sacl operations, only when + restore privilege not present */ + +/* our single cached volume capabilities structure that describes the last + volume root we encountered. A single entry like this works well in the + zip/unzip scenario for a number of reasons: + 1. typically one extraction path during unzip. + 2. typically process one volume at a time during zip, and then move + on to the next. + 3. no cleanup code required and no memory leaks. + 4. simple code. + + This approach should be reworked to a linked list approach if we expect to + be called by many threads which are processing a variety of input/output + volumes, since lock contention and stale data may become a bottleneck. */ + +VOLUMECAPS g_VolumeCaps; +CRITICAL_SECTION VolumeCapsLock; + + +/* our deferred set structure linked list element, used for making a copy + of input data which is used at a later time to process the original input + at a time when it makes more sense. eg, applying security to newly created + directories, after all files have been placed in such directories. */ + +CRITICAL_SECTION SetDeferLock; + +typedef struct _DEFERRED_SET { + struct _DEFERRED_SET *Next; + uch *buffer; /* must point to DWORD aligned block */ + PVOLUMECAPS VolumeCaps; + char *resource; +} DEFERRED_SET, *PDEFERRED_SET, *LPDEFERRED_SET; + +PDEFERRED_SET pSetHead = NULL; +PDEFERRED_SET pSetTail; + +static BOOL Initialize(VOID) +{ + HANDLE hMutex; + HANDLE hOldMutex; + + if(bInitialized) return TRUE; + + hMutex = CreateMutex(NULL, TRUE, NULL); + if(hMutex == NULL) return FALSE; + + hOldMutex = (HANDLE)InterlockedExchange((LPLONG)&hInitMutex, (LONG)hMutex); + + if(hOldMutex != NULL) { + /* somebody setup the mutex already */ + InterlockedExchange((LPLONG)&hInitMutex, (LONG)hOldMutex); + + CloseHandle(hMutex); /* close new, un-needed mutex */ + + /* wait for initialization to complete and return status */ + WaitForSingleObject(hOldMutex, INFINITE); + ReleaseMutex(hOldMutex); + + return bInitialized; + } + + /* initialize module level resources */ + + InitializeCriticalSection( &SetDeferLock ); + + InitializeCriticalSection( &VolumeCapsLock ); + memset(&g_VolumeCaps, 0, sizeof(VOLUMECAPS)); + + InitLocalPrivileges(); + + bInitialized = TRUE; + + ReleaseMutex(hMutex); /* release correct mutex */ + + return TRUE; +} + +#if 0 /* currently not used ! */ +static BOOL Shutdown(VOID) +{ + /* really need to free critical sections, disable enabled privilges, etc, + but doing so brings up possibility of race conditions if those resources + are about to be used. The easiest way to handle this is let these + resources be freed when the process terminates... */ + + return TRUE; +} +#endif /* never */ + + +static BOOL DeferSet(char *resource, PVOLUMECAPS VolumeCaps, uch *buffer) +{ + PDEFERRED_SET psd; + DWORD cbDeferSet; + DWORD cbResource; + DWORD cbBuffer; + + if(!bInitialized) if(!Initialize()) return FALSE; + + cbResource = lstrlenA(resource) + 1; + cbBuffer = GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)buffer); + cbDeferSet = sizeof(DEFERRED_SET) + cbBuffer + sizeof(VOLUMECAPS) + + cbResource; + + psd = (PDEFERRED_SET)HeapAlloc(GetProcessHeap(), 0, cbDeferSet); + if(psd == NULL) return FALSE; + + psd->Next = NULL; + psd->buffer = (uch *)(psd+1); + psd->VolumeCaps = (PVOLUMECAPS)((char *)psd->buffer + cbBuffer); + psd->resource = (char *)((char *)psd->VolumeCaps + sizeof(VOLUMECAPS)); + + memcpy(psd->buffer, buffer, cbBuffer); + memcpy(psd->VolumeCaps, VolumeCaps, sizeof(VOLUMECAPS)); + psd->VolumeCaps->bProcessDefer = TRUE; + memcpy(psd->resource, resource, cbResource); + + /* take defer lock */ + EnterCriticalSection( &SetDeferLock ); + + /* add element at tail of list */ + + if(pSetHead == NULL) { + pSetHead = psd; + } else { + pSetTail->Next = psd; + } + + pSetTail = psd; + + /* release defer lock */ + LeaveCriticalSection( &SetDeferLock ); + + return TRUE; +} + +BOOL ProcessDefer(PDWORD dwDirectoryCount, PDWORD dwBytesProcessed, + PDWORD dwDirectoryFail, PDWORD dwBytesFail) +{ + PDEFERRED_SET This; + PDEFERRED_SET Next; + + *dwDirectoryCount = 0; + *dwBytesProcessed = 0; + + *dwDirectoryFail = 0; + *dwBytesFail = 0; + + if(!bInitialized) return TRUE; /* nothing to do */ + + EnterCriticalSection( &SetDeferLock ); + + This = pSetHead; + + while(This) { + + if(SecuritySet(This->resource, This->VolumeCaps, This->buffer)) { + (*dwDirectoryCount)++; + *dwBytesProcessed += + GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)This->buffer); + } else { + (*dwDirectoryFail)++; + *dwBytesFail += + GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)This->buffer); + } + + Next = This->Next; + HeapFree(GetProcessHeap(), 0, This); + This = Next; + } + + pSetHead = NULL; + + LeaveCriticalSection( &SetDeferLock ); + + return TRUE; +} + +BOOL ValidateSecurity(uch *securitydata) +{ + PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata; + PACL pAcl; + PSID pSid; + BOOL bAclPresent; + BOOL bDefaulted; + + if(!IsWinNT()) return TRUE; /* don't do anything if not on WinNT */ + + if(!IsValidSecurityDescriptor(sd)) return FALSE; + + /* verify Dacl integrity */ + + if(!GetSecurityDescriptorDacl(sd, &bAclPresent, &pAcl, &bDefaulted)) + return FALSE; + + if(bAclPresent) { + if(!IsValidAcl(pAcl)) return FALSE; + } + + /* verify Sacl integrity */ + + if(!GetSecurityDescriptorSacl(sd, &bAclPresent, &pAcl, &bDefaulted)) + return FALSE; + + if(bAclPresent) { + if(!IsValidAcl(pAcl)) return FALSE; + } + + /* verify owner integrity */ + + if(!GetSecurityDescriptorOwner(sd, &pSid, &bDefaulted)) + return FALSE; + + if(pSid != NULL) { + if(!IsValidSid(pSid)) return FALSE; + } + + /* verify group integrity */ + + if(!GetSecurityDescriptorGroup(sd, &pSid, &bDefaulted)) + return FALSE; + + if(pSid != NULL) { + if(!IsValidSid(pSid)) return FALSE; + } + + return TRUE; +} + +static VOID GetRemotePrivilegesSet(char *FileName, PDWORD dwRemotePrivileges) +{ + HANDLE hFile; + + *dwRemotePrivileges = 0; + + /* see if we have the SeRestorePrivilege */ + + hFile = CreateFileA( + FileName, + ACCESS_SYSTEM_SECURITY | WRITE_DAC | WRITE_OWNER | READ_CONTROL, + FILE_SHARE_READ | FILE_SHARE_DELETE, /* no sd updating allowed here */ + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL + ); + + if(hFile != INVALID_HANDLE_VALUE) { + /* no remote way to determine SeRestorePrivilege -- just try a + read/write to simulate it */ + SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION | + SACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION; + PSECURITY_DESCRIPTOR sd; + DWORD cbBuf = 0; + + GetKernelObjectSecurity(hFile, si, NULL, cbBuf, &cbBuf); + + if(ERROR_INSUFFICIENT_BUFFER == GetLastError()) { + if((sd = HeapAlloc(GetProcessHeap(), 0, cbBuf)) != NULL) { + if(GetKernelObjectSecurity(hFile, si, sd, cbBuf, &cbBuf)) { + if(SetKernelObjectSecurity(hFile, si, sd)) + *dwRemotePrivileges |= OVERRIDE_RESTORE; + } + HeapFree(GetProcessHeap(), 0, sd); + } + } + + CloseHandle(hFile); + } else { + + /* see if we have the SeSecurityPrivilege */ + /* note we don't need this if we have SeRestorePrivilege */ + + hFile = CreateFileA( + FileName, + ACCESS_SYSTEM_SECURITY, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* max */ + NULL, + OPEN_EXISTING, + 0, + NULL + ); + + if(hFile != INVALID_HANDLE_VALUE) { + CloseHandle(hFile); + *dwRemotePrivileges |= OVERRIDE_SACL; + } + } +} + + +BOOL GetVolumeCaps( + char *rootpath, /* filepath, or NULL */ + char *name, /* filename associated with rootpath */ + PVOLUMECAPS VolumeCaps /* result structure describing capabilities */ + ) +{ + char TempRootPath[MAX_PATH + 1]; + DWORD cchTempRootPath = 0; + BOOL bSuccess = TRUE; /* assume success until told otherwise */ + + if(!bInitialized) if(!Initialize()) return FALSE; + + /* process the input path to produce a consistent path suitable for + compare operations and also suitable for certain picky Win32 API + that don't like forward slashes */ + + if(rootpath != NULL && rootpath[0] != '\0') { + DWORD i; + + cchTempRootPath = lstrlen(rootpath); + if(cchTempRootPath > MAX_PATH) return FALSE; + + /* copy input, converting forward slashes to back slashes as we go */ + + for(i = 0 ; i <= cchTempRootPath ; i++) { + if(rootpath[i] == '/') TempRootPath[i] = '\\'; + else TempRootPath[i] = rootpath[i]; + } + + /* check for UNC and Null terminate or append trailing \ as + appropriate */ + + /* possible valid UNCs we are passed follow: + \\machine\foo\bar (path is \\machine\foo\) + \\machine\foo (path is \\machine\foo\) + \\machine\foo\ + \\.\c$\ (FIXFIX: Win32API doesn't like this - GetComputerName()) + LATERLATER: handling mounted DFS drives in the future will require + slightly different logic which isn't available today. + This is required because directories can point at + different servers which have differing capabilities. + */ + + if(TempRootPath[0] == '\\' && TempRootPath[1] == '\\') { + DWORD slash = 0; + + for(i = 2 ; i < cchTempRootPath ; i++) { + if(TempRootPath[i] == '\\') { + slash++; + + if(slash == 2) { + i++; + TempRootPath[i] = '\0'; + cchTempRootPath = i; + break; + } + } + } + + /* if there was only one slash found, just tack another onto the + end */ + + if(slash == 1 && TempRootPath[cchTempRootPath] != '\\') { + TempRootPath[cchTempRootPath] = TempRootPath[0]; /* '\' */ + TempRootPath[cchTempRootPath+1] = '\0'; + cchTempRootPath++; + } + + } else { + + if(TempRootPath[1] == ':') { + + /* drive letter specified, truncate to root */ + TempRootPath[2] = '\\'; + TempRootPath[3] = '\0'; + cchTempRootPath = 3; + } else { + + /* must be file on current drive */ + TempRootPath[0] = '\0'; + cchTempRootPath = 0; + } + + } + + } /* if path != NULL */ + + /* grab lock protecting cached entry */ + EnterCriticalSection( &VolumeCapsLock ); + + if(!g_VolumeCaps.bValid || + lstrcmpi(g_VolumeCaps.RootPath, TempRootPath) != 0) + { + + /* no match found, build up new entry */ + + DWORD dwFileSystemFlags; + DWORD dwRemotePrivileges = 0; + BOOL bRemote = FALSE; + + /* release lock during expensive operations */ + LeaveCriticalSection( &VolumeCapsLock ); + + bSuccess = GetVolumeInformation( + (TempRootPath[0] == '\0') ? NULL : TempRootPath, + NULL, 0, + NULL, NULL, + &dwFileSystemFlags, + NULL, 0); + + + /* only if target volume supports Acls, and we were told to use + privileges do we need to go out and test for the remote case */ + + if(bSuccess && (dwFileSystemFlags & FS_PERSISTENT_ACLS) && + VolumeCaps->bUsePrivileges) + { + if(GetDriveType( (TempRootPath[0] == '\0') ? NULL : TempRootPath ) + == DRIVE_REMOTE) + { + bRemote = TRUE; + + /* make a determination about our remote capabilities */ + + GetRemotePrivilegesSet(name, &dwRemotePrivileges); + } + } + + /* always take the lock again, since we release it below */ + EnterCriticalSection( &VolumeCapsLock ); + + /* replace the existing data if successful */ + if(bSuccess) { + + lstrcpynA(g_VolumeCaps.RootPath, TempRootPath, cchTempRootPath+1); + g_VolumeCaps.bProcessDefer = FALSE; + g_VolumeCaps.dwFileSystemFlags = dwFileSystemFlags; + g_VolumeCaps.bRemote = bRemote; + g_VolumeCaps.dwRemotePrivileges = dwRemotePrivileges; + g_VolumeCaps.bValid = TRUE; + } + } + + if(bSuccess) { + /* copy input elements */ + g_VolumeCaps.bUsePrivileges = VolumeCaps->bUsePrivileges; + g_VolumeCaps.dwFileAttributes = VolumeCaps->dwFileAttributes; + + /* give caller results */ + memcpy(VolumeCaps, &g_VolumeCaps, sizeof(VOLUMECAPS)); + } else { + g_VolumeCaps.bValid = FALSE; + } + + LeaveCriticalSection( &VolumeCapsLock ); /* release lock */ + + return bSuccess; +} + + +BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata) +{ + HANDLE hFile; + DWORD dwDesiredAccess = 0; + DWORD dwFlags = 0; + PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata; + SECURITY_DESCRIPTOR_CONTROL sdc; + SECURITY_INFORMATION RequestedInfo = 0; + DWORD dwRev; + BOOL bRestorePrivilege = FALSE; + BOOL bSaclPrivilege = FALSE; + BOOL bSuccess; + + if(!bInitialized) if(!Initialize()) return FALSE; + + /* defer directory processing */ + + if(VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if(!VolumeCaps->bProcessDefer) { + return DeferSet(resource, VolumeCaps, securitydata); + } else { + /* opening a directory requires FILE_FLAG_BACKUP_SEMANTICS */ + dwFlags |= FILE_FLAG_BACKUP_SEMANTICS; + } + } + + /* evaluate the input security desriptor and act accordingly */ + + if(!IsValidSecurityDescriptor(sd)) + return FALSE; + + if(!GetSecurityDescriptorControl(sd, &sdc, &dwRev)) + return FALSE; + + /* setup privilege usage based on if told we can use privileges, and if so, + what privileges we have */ + + if(VolumeCaps->bUsePrivileges) { + if(VolumeCaps->bRemote) { + /* use remotely determined privileges */ + if(VolumeCaps->dwRemotePrivileges & OVERRIDE_RESTORE) + bRestorePrivilege = TRUE; + + if(VolumeCaps->dwRemotePrivileges & OVERRIDE_SACL) + bSaclPrivilege = TRUE; + + } else { + /* use local privileges */ + bRestorePrivilege = g_bRestorePrivilege; + bSaclPrivilege = g_bSaclPrivilege; + } + } + + + /* if a Dacl is present write Dacl out */ + /* if we have SeRestorePrivilege, write owner and group info out */ + + if(sdc & SE_DACL_PRESENT) { + dwDesiredAccess |= WRITE_DAC; + RequestedInfo |= DACL_SECURITY_INFORMATION; + + if(bRestorePrivilege) { + dwDesiredAccess |= WRITE_OWNER; + RequestedInfo |= (OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION); + } + } + + /* if a Sacl is present and we have either SeRestorePrivilege or + SeSystemSecurityPrivilege try to write Sacl out */ + + if((sdc & SE_SACL_PRESENT) && (bRestorePrivilege || bSaclPrivilege)) { + dwDesiredAccess |= ACCESS_SYSTEM_SECURITY; + RequestedInfo |= SACL_SECURITY_INFORMATION; + } + + if(RequestedInfo == 0) /* nothing to do */ + return FALSE; + + if(bRestorePrivilege) + dwFlags |= FILE_FLAG_BACKUP_SEMANTICS; + + hFile = CreateFileA( + resource, + dwDesiredAccess, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,/* max sharing */ + NULL, + OPEN_EXISTING, + dwFlags, + NULL + ); + + if(hFile == INVALID_HANDLE_VALUE) + return FALSE; + + bSuccess = SetKernelObjectSecurity(hFile, RequestedInfo, sd); + + CloseHandle(hFile); + + return bSuccess; +} + +static VOID InitLocalPrivileges(VOID) +{ + HANDLE hToken; + TOKEN_PRIVILEGES tp; + + /* try to enable some interesting privileges that give us the ability + to get some security information that we normally cannot. + + note that enabling privileges is only relevant on the local machine; + when accessing files that are on a remote machine, any privileges + that are present on the remote machine get enabled by default. */ + + if(!OpenProcessToken(GetCurrentProcess(), + TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) + return; + + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if(LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid)) { + + /* try to enable SeRestorePrivilege; if this succeeds, we can write + all aspects of the security descriptor */ + + if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) && + GetLastError() == ERROR_SUCCESS) g_bRestorePrivilege = TRUE; + + } + + /* try to enable SeSystemSecurityPrivilege, if SeRestorePrivilege not + present; if this succeeds, we can write the Sacl */ + + if(!g_bRestorePrivilege && + LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid)) { + + if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) && + GetLastError() == ERROR_SUCCESS) g_bSaclPrivilege = TRUE; + } + + CloseHandle(hToken); +} +#endif /* NTSD_EAS */ diff --git a/utils/Install/packzip/os2.c b/utils/Install/packzip/os2.c new file mode 100644 index 0000000000..a9a962796c --- /dev/null +++ b/utils/Install/packzip/os2.c @@ -0,0 +1,2187 @@ +/*--------------------------------------------------------------------------- + + 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() + 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() + InitNLS() + IsUpperNLS() + ToLowerNLS() + StringLower() + DebugMalloc() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" +#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)); + + +/*****************************/ +/* Strings used in os2.c */ +/*****************************/ + +#ifndef SFX + static char Far CantAllocateWildcard[] = + "warning: cannot allocate wildcard buffers\n"; +#endif +static char Far Creating[] = " creating: %-22s "; +static char Far ConversionFailed[] = "mapname: conversion of %s failed\n"; +static char Far Labelling[] = "labelling %c: %-22s\n"; +static char Far ErrSetVolLabel[] = "mapname: error setting volume label\n"; +static char Far PathTooLong[] = "checkdir error: path too long: %s\n"; +static char Far CantCreateDir[] = "checkdir error: cannot create %s\n\ + unable to process %s.\n"; +static char Far DirIsntDirectory[] = + "checkdir error: %s exists but is not directory\n\ + unable to process %s.\n"; +static char Far PathTooLongTrunc[] = + "checkdir warning: path too long; truncating\n %s\n\ + -> %s\n"; +#if (!defined(SFX) || defined(SFX_EXDIR)) + static char Far CantCreateExtractDir[] = + "checkdir: cannot create extraction directory: %s\n"; +#endif + +#ifndef __EMX__ +# 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 +# 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; +} + + +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; + } + + /* 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", + 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", 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(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 + char *wildspec; /* only used first time on a given dir */ +{ + /* moved to os2data.h so they can be global */ +#if 0 + static DIR *dir = NULL; + static char *dirname, *wildname, matchname[FILNAMSIZ]; + static int firstcall=TRUE, 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.firstcall) { /* first call: must initialize everything */ + G.os2.firstcall = FALSE; + + if (!iswild(wildspec)) { + strcpy(G.os2.matchname, wildspec); + G.os2.have_dirname = FALSE; + G.os2.dir = NULL; + return G.os2.matchname; + } + + /* break the wildspec into a directory part and a wildcard filename */ + if ((G.os2.wildname = strrchr(wildspec, '/')) == NULL && + (G.os2.wildname = 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))); + strcpy(G.os2.matchname, wildspec); + 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", G.os2.dirname)); + + if ((G.os2.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.dir)) != NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", file->d_name)); + strcpy(fnamestart, file->d_name); + if (strrchr(fnamestart, '.') == (char *)NULL) + strcat(fnamestart, "."); + if (match(fnamestart, G.os2.wildname, 1) && /* 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.dir); + G.os2.dir = NULL; + } +#ifdef DEBUG + else { + Trace((stderr, "do_wild: opendir(%s) returns NULL\n", 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) */ + strcpy(G.os2.matchname, wildspec); + return G.os2.matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (G.os2.dir == NULL) { + G.os2.firstcall = TRUE; /* nothing left to try--reset for new wildspec */ + 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.dir)) != NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", file->d_name)); + strcpy(fnamestart, file->d_name); + if (strrchr(fnamestart, '.') == (char *)NULL) + strcat(fnamestart, "."); + if (match(fnamestart, G.os2.wildname, 1)) { /* 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.dir); /* have read at least one dir entry; nothing left */ + G.os2.dir = NULL; + G.os2.firstcall = TRUE; /* 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& + */ + /* return 0 if no error, 1 if caution (filename */ +int mapname(__G__ renamed) /* truncated), 2 if warning (skip file because */ + __GDEF /* dir doesn't exist), 3 if error (skip file), */ + int renamed; /* or 10 if out of memory (skip file) */ +{ /* [also IZ_VOL_LABEL, IZ_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 quote = FALSE; /* flag: next char is literal */ + int error = 0; + 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(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) { + + if (quote) { /* if character quoted, */ + *pp++ = (char)workch; /* include it literally */ + quote = FALSE; + } else + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave directory semi-colons alone */ + break; + + case ':': + *pp++ = '_'; /* drive names not stored in zipfile, */ + break; /* so no colons allowed */ + + case ';': /* start of VMS version? */ + lastsemi = pp; /* remove VMS version later... */ + *pp++ = ';'; /* but keep semicolon for now */ + break; + + case '\026': /* control-V quote for special chars */ + quote = TRUE; /* set flag for next character */ + break; + + 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 */ + + *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'; + } + +/*--------------------------------------------------------------------------- + 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 (!uO.qflag) + Info(slide, 0, ((char *)slide, LoadFarString(Creating), + 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 ", 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); + + return IZ_CREATED_DIR; /* dir time already set */ + + } else if (G.extra_field && uO.overwrite_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 ", 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); + } + return 2; /* dir existed already; don't look for data to extract */ + } + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed), + G.filename)); + return 3; + } + + 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", + 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), G.filename)); + if (DosSetFSInfo(G.os2.nLabelDrive, FSIL_VOLSER, (PBYTE)&FSInfoBuf, + sizeof(VOLUMELABEL))) + { + Info(slide, 1, ((char *)slide, LoadFarString(ErrSetVolLabel))); + return 3; + } + return 2; /* success: skip the "extraction" quietly */ + } + + return error; + +} /* end function mapname() */ + + + + + +/***********************/ +/* Function checkdir() */ +/***********************/ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: 1 - (on APPEND_NAME) truncated filename + * 2 - path doesn't exist, not allowed to create + * 3 - path doesn't exist, tried to create and failed; or + * path exists and is not a directory, but is supposed to be + * 4 - path is too long + * 10 - 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", 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); + return 2; /* path doesn't exist: nothing to do */ + } + if (too_long) { /* GRR: should allow FAT extraction w/o EAs */ + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong), + G.os2.buildpathHPFS)); + free(G.os2.buildpathHPFS); + free(G.os2.buildpathFAT); + return 4; /* no room for filenames: fatal */ + } + if (MKDIR(G.os2.buildpathFAT, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir), + G.os2.buildpathFAT, G.filename)); + free(G.os2.buildpathHPFS); + free(G.os2.buildpathFAT); + return 3; /* path didn't exist, tried to create, failed */ + } + 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), + G.os2.buildpathFAT, G.filename)); + free(G.os2.buildpathHPFS); + free(G.os2.buildpathFAT); + return 3; /* path existed but wasn't dir */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong), + G.os2.buildpathHPFS)); + free(G.os2.buildpathHPFS); + free(G.os2.buildpathFAT); + return 4; /* no room for filenames: fatal */ + } + *G.os2.endHPFS++ = '/'; + *G.os2.endFAT++ = '/'; + *G.os2.endHPFS = *G.os2.endFAT = '\0'; + Trace((stderr, "buildpathHPFS now = [%s]\n", G.os2.buildpathHPFS)); + Trace((stderr, "buildpathFAT now = [%s]\n", G.os2.buildpathFAT)); + return 0; + + } /* 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", G.os2.buildpathFAT)); + Trace((stderr, "freeing HPFS path [%s]\n", 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 0; + } + +/*--------------------------------------------------------------------------- + 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 = 0; + + Trace((stderr, "appending filename [%s]\n", pathcomp)); + while ((*G.os2.endHPFS = *p++) != '\0') { /* copy to HPFS filename */ + ++G.os2.endHPFS; + if ((G.os2.endHPFS-G.os2.buildpathHPFS) >= FILNAMSIZ) { + *--G.os2.endHPFS = '\0'; + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLongTrunc), + G.filename, G.os2.buildpathHPFS)); + error = 1; /* 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)) + */ + if (G.pInfo->vollabel || IsFileNameValid(G.os2.buildpathHPFS)) { + G.os2.longnameEA = FALSE; + p = pathcomp; + while ((*G.os2.endFAT = *p++) != '\0') /* copy to FAT filename, too */ + ++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; + error = 1; /* can't set .LONGNAME extended attribute */ + } else /* used and freed in close_outfile() */ + strcpy(G.os2.lastpathcomp, pathcomp); + map2fat(pathcomp, &G.os2.endFAT); /* map, put in FAT fn, update endFAT */ + } + Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n", + G.os2.buildpathHPFS, 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 ")); + if ((G.os2.buildpathHPFS = (char *)malloc(G.os2.fnlen+G.os2.rootlen+1)) == (char *)NULL) + return 10; + if ((G.os2.buildpathFAT = (char *)malloc(G.os2.fnlen+G.os2.rootlen+1)) == (char *)NULL) { + free(G.os2.buildpathHPFS); + return 10; + } + 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 IZ_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", G.os2.buildpathHPFS)); + return 0; + } + +/*--------------------------------------------------------------------------- + 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", pathcomp)); + if (pathcomp == (char *)NULL) { + G.os2.rootlen = 0; + return 0; + } + if ((G.os2.rootlen = strlen(pathcomp)) > 0) { + int had_trailing_pathsep=FALSE, has_drive=FALSE, xtra=2; + + if (isalpha(pathcomp[0]) && pathcomp[1] == ':') + has_drive = TRUE; /* drive designator */ + if (pathcomp[G.os2.rootlen-1] == '/') { + pathcomp[--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:/" */ + xtra = 3; /* room for '.' + '/' + 0 at end of "x:" */ + } 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(pathcomp) == -1 || + SSTAT(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) +#else + if (SSTAT(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) +#endif + { /* path does not exist */ + if (!G.create_dirs /* || iswild(pathcomp) */ + ) { + G.os2.rootlen = 0; + return 2; /* treat as stored file */ + } + /* create directory (could add loop here to scan pathcomp + * and create more than one level, but really necessary?) */ + if (MKDIR(pathcomp, 0777) == -1) { + Info(slide, 1, ((char *)slide, + LoadFarString(CantCreateExtractDir), pathcomp)); + G.os2.rootlen = 0; /* path didn't exist, tried to create, */ + return 3; /* failed: file exists, or need 2+ levels */ + } + } + } + if ((G.os2.rootpath = (char *)malloc(G.os2.rootlen+xtra)) == (char *)NULL) { + G.os2.rootlen = 0; + return 10; + } + strcpy(G.os2.rootpath, pathcomp); + if (xtra == 3) /* had just "x:", make "x:." */ + G.os2.rootpath[G.os2.rootlen++] = '.'; + G.os2.rootpath[G.os2.rootlen++] = '/'; + G.os2.rootpath[G.os2.rootlen] = '\0'; + Trace((stderr, "rootpath now = [%s]\n", G.os2.rootpath)); + } + return 0; + } +#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 0; + } + + return 99; /* 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 ", 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/2 ", __VERSION__, +# endif +#elif defined(__IBMC__) + "IBM ", +# if (__IBMC__ < 200) + (sprintf(buf, "C Set/2 %d.%02d", __IBMC__/100,__IBMC__%100), buf), +# elif (__IBMC__ < 300) + (sprintf(buf, "C Set++ %d.%02d", __IBMC__/100,__IBMC__%100), buf), +# else + (sprintf(buf, "Visual Age C++ %d.%02d", __IBMC__/100,__IBMC__%100), buf), +# endif +#elif defined(__WATCOMC__) + "Watcom C", (sprintf(buf, " (__WATCOMC__ = %d)", __WATCOMC__), buf), +#elif defined(__TURBOC__) +# ifdef __BORLANDC__ + "Borland C++", +# if (__BORLANDC__ < 0x0460) + " 1.0", +# elif (__BORLANDC__ == 0x0460) + " 1.5", /* 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 + " 2.x/3.x (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 */ + + + +/* 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; +} + + +#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); + G.os2.firstcall = TRUE; + +#ifdef OS2DLL + G.os2.rexx_mes = "0"; +#endif + + InitNLS(); +} diff --git a/utils/Install/packzip/os2acl.c b/utils/Install/packzip/os2acl.c new file mode 100644 index 0000000000..c58f6e0419 --- /dev/null +++ b/utils/Install/packzip/os2acl.c @@ -0,0 +1,381 @@ +/* os2acl.c - access to OS/2 (LAN Server) ACLs + * + * Author: Kai Uwe Rommel + * Created: Mon Aug 08 1994 + * + * This code is in the public domain. + */ + +/* + * 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$"; + static char *rcsrev = "$Revision$"; +#endif + +/* + * $Log$ + * Revision 1.1.2.1 2000/04/11 12:38:06 BS + * Added wxInstall a self extracting installation program using wxWindows. + * + * 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(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/utils/Install/packzip/process.c b/utils/Install/packzip/process.c new file mode 100644 index 0000000000..3fa023c904 --- /dev/null +++ b/utils/Install/packzip/process.c @@ -0,0 +1,1383 @@ +/*--------------------------------------------------------------------------- + + process.c + + This file contains the top-level routines for processing multiple zipfiles. + + Contains: process_zipfiles() + free_G_buffers() + do_seekable() + find_ecrec() + uz_end_central() + process_cdir_file_hdr() + get_cdir_ent() + process_local_file_hdr() + ef_scan_for_izux() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" +#ifdef WINDLL +# ifdef POCKET_UNZIP +# include "wince/intrface.h" +# else +# include "windll/windll.h" +# endif +#endif + +static int do_seekable OF((__GPRO__ int lastchance)); +static int find_ecrec OF((__GPRO__ long searchlen)); + +int files = 0; + +static ZCONST char Far CannotAllocateBuffers[] = + "error: cannot allocate unzip buffers\n"; + +#ifdef SFX + static ZCONST char Far CannotFindMyself[] = + "unzipsfx: cannot find myself! [%s]\n"; + +#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 + 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 %s, %s.zip or %s.\n"; /* ", so there" removed 970918 */ +# else /* !UNIX */ +# ifndef AMIGA + static ZCONST char Far CannotFindWildcardMatch[] = + "%s: cannot find any matches for wildcard specification \"%s\".\n"; +# endif /* !AMIGA */ + static ZCONST char Far CannotFindZipfileDirMsg[] = + "%s: cannot find zipfile directory in %s,\n\ + %sand cannot find %s, period.\n"; + static ZCONST char Far CannotFindEitherZipfile[] = + "%s: cannot find either %s or %s.\n"; /* ", so there" removed 970918 */ +# 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 + 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 %u of a multi-disk archive, and this is not the disk on\n\ + which the central zipfile directory begins (disk %u).\n"; + static ZCONST char Far EndCentDirBogus[] = + "\nwarning [%s]: end-of-central-directory record claims this\n\ + is disk %u but that the central directory starts on disk %u; 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]: %ld extra byte%s at beginning or within zipfile\n\ + (attempting to process anyway)\n"; +#endif /* ?SFX */ + +static ZCONST char Far MissingBytes[] = + "error [%s]: missing %ld 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"; +#ifndef SFX + static ZCONST char Far CentDirTooLong[] = + "error [%s]: reported length of central directory is\n\ + %ld 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 */ +static ZCONST char Far ZipfileCommTrunc1[] = + "\ncaution: zipfile comment truncated\n"; + + + + +/*******************************/ +/* 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 only later when we know we have a zipfile */ + CRC_32_TAB = NULL; +#endif /* 0 */ + + /* finish up initialization of magic signature strings */ + local_hdr_sig[0] /* = extd_local_sig[0] */ = 0x50; /* ASCII 'P', */ + central_hdr_sig[0] = end_central_sig[0] = 0x50; /* not EBCDIC */ + + local_hdr_sig[1] /* = extd_local_sig[1] */ = 0x4B; /* ASCII 'K', */ + central_hdr_sig[1] = end_central_sig[1] = 0x4B; /* not EBCDIC */ + +/*--------------------------------------------------------------------------- + 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 were + initially copied from dos_to_unix_time() in fileio.c. probably, they are + still too strict; any listed OS that supplies tzset(), regardless of + whether the function does anything, should be removed from the ifdefs. + ---------------------------------------------------------------------------*/ + +#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 + +/*--------------------------------------------------------------------------- + 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)); + } + +#else /* !SFX */ + NumWinFiles = NumLoseFiles = NumWarnFiles = 0; + files = 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) + ++NumLoseFiles; + else + ++NumWinFiles; + + if(!uO.vflag) + files = NumWinFiles; + + if (error != IZ_DIR && error > error_in_archive) + error_in_archive = error; + Trace((stderr, "do_seekable(0) returns %d\n", 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) + { + NumMissDirs = NumMissFiles = 0; + if (error_in_archive == PK_NOZIP) + error_in_archive = PK_COOL; + +#if (!defined(UNIX) && !defined(AMIGA)) /* filenames with wildcard characters */ + if (iswild(G.wildzipfn)) + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotFindWildcardMatch), uO.zipinfo_mode? + LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip), + G.wildzipfn)); + else +#endif + { + char *p = lastzipfn + strlen(lastzipfn); + + G.zipfn = lastzipfn; + strcpy(p, ZSUFX); + +#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 + if (error == PK_WARN) /* GRR: make this a switch/case stmt ... */ + ++NumWarnFiles; + else if (error == IZ_DIR) + ++NumMissDirs; + else if (error == PK_NOZIP) + /* increment again => bug: "1 file had no zipfile directory." */ + /* ++NumMissFiles */ ; + else if (error) + ++NumLoseFiles; + else + ++NumWinFiles; + + if (error > error_in_archive) + error_in_archive = error; + Trace((stderr, "do_seekable(1) returns %d\n", 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.qflag && !uO.zipinfo_mode) +#endif + ) + { + if ((NumMissFiles + NumLoseFiles + NumWarnFiles > 0 || NumWinFiles != 1) +#ifdef TIMESTAMP + && !(uO.T_flag && !uO.zipinfo_mode) +#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 +{ + 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 (!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 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; + unsigned nmember = 0; +#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) || + (error = S_ISDIR(G.statbuf.st_mode)) != 0) + { +#ifndef SFX + if (lastchance) { +#if defined(UNIX) || defined(QDOS) + if (G.no_ecrec) + Info(slide, 1, ((char *)slide, + LoadFarString(CannotFindZipfileDirMsg), uO.zipinfo_mode? + LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip), + G.wildzipfn, uO.zipinfo_mode? " " : "", G.wildzipfn, + G.zipfn)); + else + Info(slide, 1, ((char *)slide, + LoadFarString(CannotFindEitherZipfile), uO.zipinfo_mode? + LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip), + G.wildzipfn, G.wildzipfn, G.zipfn)); +#else /* !UNIX */ + if (G.no_ecrec) + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotFindZipfileDirMsg), uO.zipinfo_mode? + LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip), + G.wildzipfn, uO.zipinfo_mode? " " : "", G.zipfn)); + else + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotFindEitherZipfile), uO.zipinfo_mode? + LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip), + G.wildzipfn, G.zipfn)); +#endif /* ?UNIX */ + } +#endif /* !SFX */ + return error? IZ_DIR : PK_NOZIP; + } + G.ziplen = G.statbuf.st_size; + +#ifndef SFX +#if defined(UNIX) || defined(DOS_OS2_W32) + 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... */ + +/*--------------------------------------------------------------------------- + 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. + ---------------------------------------------------------------------------*/ + + /* 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)) + /* 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)) > 2) + return error; /* out of memory, or file in way */ + } +#endif /* !SFX || SFX_EXDIR */ + + G.cur_zipfile_bufstart = 0; + G.inptr = G.inbuf; + +#if (!defined(WINDLL) && !defined(SFX)) +#ifdef TIMESTAMP + if (!uO.zipinfo_mode && !uO.qflag && !uO.T_flag) +#else + if (!uO.zipinfo_mode && !uO.qflag) +#endif +#ifdef WIN32 /* Win32 console may require codepage conversion for G.zipfn */ + Info(slide, 0, ((char *)slide, "Archive: %s\n", FnFilter1(G.zipfn))); +#else + Info(slide, 0, ((char *)slide, "Archive: %s\n", G.zipfn)); +#endif +#endif /* !WINDLL && !SFX */ + + if (( +#ifndef NO_ZIPINFO + uO.zipinfo_mode && + ((error_in_archive = find_ecrec(__G__ G.ziplen)) != 0 || + (error_in_archive = zi_end_central(__G)) > PK_WARN)) + || (!uO.zipinfo_mode && +#endif + ((error_in_archive = find_ecrec(__G__ MIN(G.ziplen,66000L))) != 0 || + (error_in_archive = uz_end_central(__G)) > 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, + G.ecrec.number_this_disk, 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, + G.ecrec.number_this_disk, 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) < + (LONGINT)0) + { + Info(slide, 0x401, ((char *)slide, LoadFarString(MissingBytes), + G.zipfn, (long)(-G.extra_bytes))); + 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, + (long)G.extra_bytes, (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). + -----------------------------------------------------------------------*/ + + ZLSEEK( G.ecrec.offset_start_central_directory ) +#ifdef OLD_SEEK_TEST + if (readbuf(G.sig, 4) == 0) { + CLOSE_INFILE(); + return PK_ERR; /* file may be locked, or possibly disk error(?) */ + } + if (strncmp(G.sig, central_hdr_sig, 4)) +#else + if ((readbuf(__G__ G.sig, 4) == 0) || + strncmp(G.sig, central_hdr_sig, 4)) +#endif + { +#ifndef SFX + long tmp = G.extra_bytes; +#endif + + G.extra_bytes = 0; + ZLSEEK( G.ecrec.offset_start_central_directory ) + if ((readbuf(__G__ G.sig, 4) == 0) || + strncmp(G.sig, central_hdr_sig, 4)) + { + Info(slide, 0x401, ((char *)slide, + LoadFarString(CentDirStartNotFound), G.zipfn, + LoadFarStringSmall(ReportMsg))); + CLOSE_INFILE(); + return PK_BADERR; + } +#ifndef SFX + Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirTooLong), + G.zipfn, -tmp)); +#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. + -----------------------------------------------------------------------*/ + + Trace((stderr, "about to extract/list files (error = %d)\n", + error_in_archive)); + + ZLSEEK( G.ecrec.offset_start_central_directory ) + +#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 > 0)) { +# ifdef WIN32 + if (stamp_file(__G__ G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */ +# else + if (stamp_file(G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */ +# endif + Info(slide, 0x201, ((char *)slide, + "warning: cannot set time for %s\n", G.zipfn)); + if (error_in_archive < PK_WARN) + error_in_archive = PK_WARN; + } + } +#endif + return error_in_archive; + +} /* end function do_seekable() */ + + + + + +/*************************/ +/* Function find_ecrec() */ +/*************************/ + +static int find_ecrec(__G__ searchlen) /* return PK-class error */ + __GDEF + long searchlen; +{ + int i, numblks, found=FALSE; + LONGINT tail_len; + ec_byte_rec byterec; + + +/*--------------------------------------------------------------------------- + Treat case of short zipfile separately. + ---------------------------------------------------------------------------*/ + + if (G.ziplen <= INBUFSIZ) { + lseek(G.zipfd, 0L, SEEK_SET); + if ((G.incnt = read(G.zipfd,(char *)G.inbuf,(unsigned int)G.ziplen)) + == (int)G.ziplen) + + /* 'P' must be at least 22 bytes from end of zipfile */ + for (G.inptr = G.inbuf+(int)G.ziplen-22; G.inptr >= G.inbuf; + --G.inptr) + if ((native(*G.inptr) == 'P') && + !strncmp((char *)G.inptr, end_central_sig, 4)) { + G.incnt -= (int)(G.inptr - G.inbuf); + found = TRUE; + break; + } + +/*--------------------------------------------------------------------------- + Zipfile is longer than INBUFSIZ: may need to loop. Start with short + block at end of zipfile (if not TOO short). + ---------------------------------------------------------------------------*/ + + } else { + if ((tail_len = G.ziplen % INBUFSIZ) > ECREC_SIZE) { +#ifdef USE_STRM_INPUT + fseek((FILE *)G.zipfd, G.ziplen-tail_len, SEEK_SET); + G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd); +#else /* !USE_STRM_INPUT */ + G.cur_zipfile_bufstart = lseek(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) + goto fail; /* it's expedient... */ + + /* 'P' must be at least 22 bytes from end of zipfile */ + for (G.inptr = G.inbuf+(int)tail_len-22; G.inptr >= G.inbuf; + --G.inptr) + if ((native(*G.inptr) == 'P') && + !strncmp((char *)G.inptr, end_central_sig, 4)) { + G.incnt -= (int)(G.inptr - G.inbuf); + found = TRUE; + break; + } + /* sig may span block boundary: */ + strncpy((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; + lseek(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET); + if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) + != INBUFSIZ) + break; /* fall through and fail */ + + for (G.inptr = G.inbuf+INBUFSIZ-1; G.inptr >= G.inbuf; + --G.inptr) + if ((native(*G.inptr) == 'P') && + !strncmp((char *)G.inptr, end_central_sig, 4)) { + G.incnt -= (int)(G.inptr - G.inbuf); + found = TRUE; + break; + } + /* sig may span block boundary: */ + strncpy((char *)G.hold, (char *)G.inbuf, 3); + } + } /* end if (ziplen > INBUFSIZ) */ + +/*--------------------------------------------------------------------------- + Searched through whole region where signature should be without finding + it. Print informational message and die a horrible death. + ---------------------------------------------------------------------------*/ + +fail: + 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 + pipeit("\n found end-of-central-dir signature at offset %ld (%.8lXh)\n", + G.real_ecrec_offset, G.real_ecrec_offset); + pipeit(" 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_CENTRAL_DIR]); + G.ecrec.num_entries_centrl_dir_ths_disk = + makeword(&byterec[NUM_ENTRIES_CENTRL_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]); + + G.expect_ecrec_offset = G.ecrec.offset_start_central_directory + + G.ecrec.size_central_directory; + return PK_COOL; + +} /* end function find_ecrec() */ + + + + + +/*****************************/ +/* Function uz_end_central() */ +/*****************************/ + +int uz_end_central(__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. + Then position the file pointer to the beginning of the central directory + and fill buffer. + ---------------------------------------------------------------------------*/ + +#ifdef WINDLL + /* for comment button: */ + if ((!G.fValidate) && (G.lpUserFunctions != NULL)) + G.lpUserFunctions->cchComment = G.ecrec.zipfile_comment_length; + if (G.ecrec.zipfile_comment_length && (uO.zflag > 0)) +#else /* !WINDLL */ + if (G.ecrec.zipfile_comment_length && (uO.zflag > 0 || + (uO.zflag == 0 && +#ifdef TIMESTAMP + !uO.T_flag && +#endif + !uO.qflag))) +#endif /* ?WINDLL */ + { + if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(ZipfileCommTrunc1))); + error = PK_WARN; + } + } + return error; + +} /* end function uz_end_central() */ + + + + + +/************************************/ +/* 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->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) /* user specified case-conversion */ + 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_, BEOS_ (Z_SYSTEM_): no conversion */ + } + + /* 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; + + return PK_COOL; + +} /* end function process_cdir_file_hdr() */ + + + + + +/***************************/ +/* Function get_cdir_ent() */ +/***************************/ + +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]); + + G.csize = (long) G.lrec.csize; + G.ucsize = (long) G.lrec.ucsize; + + if ((G.lrec.general_purpose_bit_flag & 8) != 0) { + /* can't trust local header, use central directory: */ + G.lrec.crc32 = G.pInfo->crc; + G.csize = (long)(G.lrec.csize = G.pInfo->compr_size); + G.ucsize = (long)(G.lrec.ucsize = G.pInfo->uncompr_size); + } + + return PK_COOL; + +} /* end function process_local_file_hdr() */ + + +#ifdef USE_EF_UT_TIME + +/*******************************/ +/* Function ef_scan_for_izux() */ +/*******************************/ + +unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos_mdatetime, + z_utim, z_uidgid) + 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 */ + ush *z_uidgid; /* return storage: uid and gid */ +{ + unsigned flags = 0; + unsigned eb_id; + unsigned eb_len; + int have_new_type_eb = FALSE; + int ut_zip_unzip_compatible = FALSE; + +/*--------------------------------------------------------------------------- + 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 = TRUE; + 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) { + z_utim->mtime = makelong((EB_HEADSIZE+eb_idx) + ef_buf); + eb_idx += 4; + TTrace((stderr," UT e.f. modification time = %ld\n", + z_utim->mtime)); + + if ((ulg)(z_utim->mtime) & (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, + " 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; + } + } 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) { + z_utim->atime = makelong((EB_HEADSIZE+eb_idx) + ef_buf); + eb_idx += 4; + TTrace((stderr," UT e.f. access time = %ld\n", + z_utim->atime)); + if (((ulg)(z_utim->atime) & (ulg)(0x80000000L)) && + !ut_zip_unzip_compatible) { + flags &= ~EB_UT_FL_ATIME; + TTrace((stderr, + " UT access time range error: skip time!\n")); + } + } else { + flags &= ~EB_UT_FL_ATIME; + } + } + if (flags & EB_UT_FL_CTIME) { + if ((eb_idx+4) <= eb_len) { + z_utim->ctime = makelong((EB_HEADSIZE+eb_idx) + ef_buf); + TTrace((stderr," UT e.f. creation time = %ld\n", + z_utim->ctime)); + if (((ulg)(z_utim->ctime) & (ulg)(0x80000000L)) && + !ut_zip_unzip_compatible) { + flags &= ~EB_UT_FL_CTIME; + TTrace((stderr, + " UT creation time range error: skip time!\n")); + } + } else { + flags &= ~EB_UT_FL_CTIME; + } + } + } + break; + + case EF_IZUNIX2: + if (!have_new_type_eb) { + flags &= ~0x0ff; /* ignore any previous IZUNIX field */ + have_new_type_eb = TRUE; + } + if (eb_len >= EB_UX2_MINLEN && z_uidgid != NULL) { + z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX2_UID) + ef_buf); + z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX2_GID) + ef_buf); + flags |= EB_UX2_VALID; /* signal success */ + } + 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) { + break; /* Ignore IZUNIX extra field block ! */ + } + if (z_utim != NULL) { + z_utim->atime = makelong((EB_HEADSIZE+EB_UX_ATIME)+ef_buf); + z_utim->mtime = makelong((EB_HEADSIZE+EB_UX_MTIME)+ef_buf); + TTrace((stderr," Unix EF actime = %ld\n", z_utim->atime)); + TTrace((stderr," Unix EF modtime = %ld\n", z_utim->mtime)); + flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME); + if ((ulg)(z_utim->mtime) & (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; + } + if ((ulg)(z_utim->atime) & (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")); + } + } + 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; + } + } + 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 */ diff --git a/utils/Install/packzip/rexxapi.c b/utils/Install/packzip/rexxapi.c new file mode 100644 index 0000000000..43b4ddde3e --- /dev/null +++ b/utils/Install/packzip/rexxapi.c @@ -0,0 +1,886 @@ +/********************************************************************** +* 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 "../version.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, + PATCHLEVEL, 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, + PATCHLEVEL, BETALEVEL, 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__ 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)); + sprintf(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/utils/Install/packzip/rexxapi.def b/utils/Install/packzip/rexxapi.def new file mode 100644 index 0000000000..813964abe8 --- /dev/null +++ b/utils/Install/packzip/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/utils/Install/packzip/rexxhelp.c b/utils/Install/packzip/rexxhelp.c new file mode 100644 index 0000000000..20a72597a8 --- /dev/null +++ b/utils/Install/packzip/rexxhelp.c @@ -0,0 +1,178 @@ +/* rexxhelp.c */ + +#if defined(API_DOC) && defined(OS2DLL) + +#define UNZIP_INTERNAL +#include "../unzip.h" +#include "../version.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/utils/Install/packzip/stub.def b/utils/Install/packzip/stub.def new file mode 100644 index 0000000000..f3852f109e --- /dev/null +++ b/utils/Install/packzip/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/utils/Install/packzip/ttyio.c b/utils/Install/packzip/ttyio.c new file mode 100644 index 0000000000..c755d1c5a3 --- /dev/null +++ b/utils/Install/packzip/ttyio.c @@ -0,0 +1,625 @@ +/*--------------------------------------------------------------------------- + + ttyio.c + + This file contains routines for doing console input/output, including code + for non-echoing input. It is used by the encryption/decryption code but + does not contain any restricted code itself. This file is shared between + Info-ZIP's Zip and UnZip. + + Contains: echo() (VMS only) + Echon() (Unix only) + Echoff() (Unix only) + screenlines() (Unix only) + zgetch() (Unix and non-Unix versions) + getp() ("PC," Unix/Atari/Be, VMS/VMCMS/MVS) + + ---------------------------------------------------------------------------*/ + +#define __TTYIO_C /* identifies this source module */ + +#include "zip.h" +#include "crypt.h" + +#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP))) +/* Non-echo console/keyboard input is needed for (en/de)cryption's password + * entry, and for UnZip(SFX)'s MORE and Pause features. + * (The corresponding #endif is found at the end of this module.) + */ + +#include "ttyio.h" + +#ifndef PUTC +# define PUTC putc +#endif + +#ifdef ZIP +# ifdef GLOBAL /* used in Amiga system headers, maybe others too */ +# undef GLOBAL +# endif +# define GLOBAL(g) g +#else +# define GLOBAL(g) G.g +#endif + +#ifdef __BEOS__ /* why yes, we do */ +# define HAVE_TERMIOS_H +#endif + +#ifdef _POSIX_VERSION +# ifndef USE_POSIX_TERMIOS +# define USE_POSIX_TERMIOS /* use POSIX style termio (termios) */ +# endif +# ifndef HAVE_TERMIOS_H +# define HAVE_TERMIOS_H /* POSIX termios.h */ +# endif +#endif /* _POSIX_VERSION */ + +#ifdef UNZIP /* Zip handles this with the unix/configure script */ +# ifndef _POSIX_VERSION +# if (defined(SYSV) || defined(CRAY)) && !defined(__MINT__) +# ifndef USE_SYSV_TERMIO +# define USE_SYSV_TERMIO +# endif +# ifdef COHERENT +# ifndef HAVE_TERMIO_H +# define HAVE_TERMIO_H +# endif +# ifdef HAVE_SYS_TERMIO_H +# undef HAVE_SYS_TERMIO_H +# endif +# else /* !COHERENT */ +# ifdef HAVE_TERMIO_H +# undef HAVE_TERMIO_H +# endif +# ifndef HAVE_SYS_TERMIO_H +# define HAVE_SYS_TERMIO_H +# endif +# endif /* ?COHERENT */ +# endif /* (SYSV || CRAY) && !__MINT__ */ +# endif /* !_POSIX_VERSION */ +# if !(defined(BSD4_4) || defined(SYSV) || defined(__convexc__)) +# ifndef NO_FCNTL_H +# define NO_FCNTL_H +# endif +# endif /* !(BSD4_4 || SYSV || __convexc__) */ +#endif /* UNZIP */ + +#ifdef HAVE_TERMIOS_H +# ifndef USE_POSIX_TERMIOS +# define USE_POSIX_TERMIOS +# endif +#endif + +#if (defined(HAVE_TERMIO_H) || defined(HAVE_SYS_TERMIO_H)) +# ifndef USE_SYSV_TERMIO +# define USE_SYSV_TERMIO +# endif +#endif + +#if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE)) +# include +# define GOT_IOCTL_H + /* int ioctl OF((int, int, zvoid *)); GRR: may need for some systems */ +#endif + +#ifndef HAVE_WORKING_GETCH + /* include system support for switching of console echo */ +# ifdef VMS +# include +# include +# include +# include +# include +# else /* !VMS */ +# ifdef HAVE_TERMIOS_H +# include +# define sgttyb termios +# define sg_flags c_lflag +# define GTTY(f, s) tcgetattr(f, (zvoid *) s) +# define STTY(f, s) tcsetattr(f, TCSAFLUSH, (zvoid *) s) +# else /* !HAVE_TERMIOS_H */ +# ifdef USE_SYSV_TERMIO /* Amdahl, Cray, all SysV? */ +# ifdef HAVE_TERMIO_H +# include +# endif +# ifdef HAVE_SYS_TERMIO_H +# include +# endif +# ifdef NEED_PTEM +# include +# include +# endif +# define sgttyb termio +# define sg_flags c_lflag +# define GTTY(f,s) ioctl(f,TCGETA,(zvoid *)s) +# define STTY(f,s) ioctl(f,TCSETAW,(zvoid *)s) +# else /* !USE_SYSV_TERMIO */ +# ifndef CMS_MVS +# if (!defined(MINIX) && !defined(GOT_IOCTL_H)) +# include +# endif +# include +# define GTTY gtty +# define STTY stty +# ifdef UNZIP + /* + * XXX : Are these declarations needed at all ???? + */ + /* + * GRR: let's find out... Hmmm, appears not... + int gtty OF((int, struct sgttyb *)); + int stty OF((int, struct sgttyb *)); + */ +# endif +# endif /* !CMS_MVS */ +# endif /* ?USE_SYSV_TERMIO */ +# endif /* ?HAVE_TERMIOS_H */ +# ifndef NO_FCNTL_H +# ifndef UNZIP +# include +# endif +# else + char *ttyname OF((int)); +# endif +# endif /* ?VMS */ +#endif /* !HAVE_WORKING_GETCH */ + + + +#ifndef HAVE_WORKING_GETCH +#ifdef VMS + +/* + * Turn keyboard echoing on or off (VMS). Loosely based on VMSmunch.c + * and hence on Joe Meadows' file.c code. + */ +int echo(opt) + int opt; +{ + /* + * For VMS v5.x: + * IO$_SENSEMODE/SETMODE info: Programming, Vol. 7A, System Programming, + * I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6 + * sys$assign(), sys$qio() info: Programming, Vol. 4B, System Services, + * System Services Reference Manual, pp. sys-23, sys-379 + * fixed-length descriptor info: Programming, Vol. 3, System Services, + * Intro to System Routines, sec. 2.9.2 + * Greg Roelofs, 15 Aug 91 + */ + + /* SKM: make global? */ + static struct dsc$descriptor_s DevDesc = + {11, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$COMMAND"}; + /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */ + static short DevChan, iosb[4]; + static long status; + static unsigned long oldmode[2], newmode[2]; /* each = 8 bytes */ + + + /* assign a channel to standard input */ + status = sys$assign(&DevDesc, &DevChan, 0, 0); + if (!(status & 1)) + return status; + + /* use sys$qio and the IO$_SENSEMODE function to determine the current + * tty status (for password reading, could use IO$_READVBLK function + * instead, but echo on/off will be more general) + */ + status = sys$qiow(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0, + oldmode, 8, 0, 0, 0, 0); + if (!(status & 1)) + return status; + status = iosb[0]; + if (!(status & 1)) + return status; + + /* copy old mode into new-mode buffer, then modify to be either NOECHO or + * ECHO (depending on function argument opt) + */ + newmode[0] = oldmode[0]; + newmode[1] = oldmode[1]; + if (opt == 0) /* off */ + newmode[1] |= TT$M_NOECHO; /* set NOECHO bit */ + else + newmode[1] &= ~((unsigned long) TT$M_NOECHO); /* clear NOECHO bit */ + + /* use the IO$_SETMODE function to change the tty status */ + status = sys$qiow(0, DevChan, IO$_SETMODE, &iosb, 0, 0, + newmode, 8, 0, 0, 0, 0); + if (!(status & 1)) + return status; + status = iosb[0]; + if (!(status & 1)) + return status; + + /* deassign the sys$input channel by way of clean-up */ + status = sys$dassgn(DevChan); + if (!(status & 1)) + return status; + + return SS$_NORMAL; /* we be happy */ + +} /* end function echo() */ + + +#else /* !VMS: basically Unix */ + + +/* For VM/CMS and MVS, non-echo terminal input is not (yet?) supported. */ +#ifndef CMS_MVS + +#ifdef ZIP /* moved to globals.h for UnZip */ + static int echofd=(-1); /* file descriptor whose echo is off */ +#endif + +/* + * Turn echo off for file descriptor f. Assumes that f is a tty device. + */ +void Echoff(__G__ f) + __GDEF + int f; /* file descriptor for which to turn echo off */ +{ + struct sgttyb sg; /* tty device structure */ + + GLOBAL(echofd) = f; + GTTY(f, &sg); /* get settings */ + sg.sg_flags &= ~ECHO; /* turn echo off */ + STTY(f, &sg); +} + +/* + * Turn echo back on for file descriptor echofd. + */ +void Echon(__G) + __GDEF +{ + struct sgttyb sg; /* tty device structure */ + + if (GLOBAL(echofd) != -1) { + GTTY(GLOBAL(echofd), &sg); /* get settings */ + sg.sg_flags |= ECHO; /* turn echo on */ + STTY(GLOBAL(echofd), &sg); + GLOBAL(echofd) = -1; + } +} + +#endif /* !CMS_MVS */ +#endif /* ?VMS */ + + +#if (defined(UNZIP) && !defined(FUNZIP)) + +#if (defined(UNIX) || defined(__BEOS__)) +#ifdef MORE + +/* + * Get the number of lines on the output terminal. SCO Unix apparently + * defines TIOCGWINSZ but doesn't support it (!M_UNIX). + * + * GRR: will need to know width of terminal someday, too, to account for + * line-wrapping. + */ + +#if (defined(TIOCGWINSZ) && !defined(M_UNIX)) + +int screenlines() +{ + struct winsize wsz; +#ifdef DEBUG_WINSZ + static int firsttime = TRUE; +#endif + + /* see termio(4) under, e.g., SunOS */ + if (ioctl(1, TIOCGWINSZ, &wsz) == 0) { +#ifdef DEBUG_WINSZ + if (firsttime) { + firsttime = FALSE; + fprintf(stderr, "ttyio.c screenlines(): ws_row = %d\n", + wsz.ws_row); + } +#endif + /* number of columns = ws_col */ + return (wsz.ws_row > 0)? wsz.ws_row : 24; /* number of rows */ + + } else { /* this happens when piping to more(1), for example */ +#ifdef DEBUG_WINSZ + if (firsttime) { + firsttime = FALSE; + fprintf(stderr, + "ttyio.c screenlines(): ioctl(TIOCGWINSZ) failed\n")); + } +#endif + return 24; /* VT-100 assumed to be minimal hardware */ + } +} + +#else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */ + +int screenlines() +{ + char *envptr, *getenv(); + int n; + + /* GRR: this is overly simplistic, but don't have access to stty/gtty + * system anymore + */ + envptr = getenv("LINES"); + if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) + return 24; /* VT-100 assumed to be minimal hardware */ + else + return n; +} + +#endif /* ?(TIOCGWINSZ && !M_UNIX) */ +#endif /* MORE */ + + +/* + * Get a character from the given file descriptor without echo or newline. + */ +int zgetch(__G__ f) + __GDEF + int f; /* file descriptor from which to read */ +{ +#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS)) + char oldmin, oldtim; +#endif + char c; + struct sgttyb sg; /* tty device structure */ + + GTTY(f, &sg); /* get settings */ +#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS)) + oldmin = sg.c_cc[VMIN]; /* save old values */ + oldtim = sg.c_cc[VTIME]; + sg.c_cc[VMIN] = 1; /* need only one char to return read() */ + sg.c_cc[VTIME] = 0; /* no timeout */ + sg.sg_flags &= ~ICANON; /* canonical mode off */ +#else + sg.sg_flags |= CBREAK; /* cbreak mode on */ +#endif + sg.sg_flags &= ~ECHO; /* turn echo off, too */ + STTY(f, &sg); /* set cbreak mode */ + GLOBAL(echofd) = f; /* in case ^C hit (not perfect: still CBREAK) */ + + read(f, &c, 1); /* read our character */ + +#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS)) + sg.c_cc[VMIN] = oldmin; /* restore old values */ + sg.c_cc[VTIME] = oldtim; + sg.sg_flags |= ICANON; /* canonical mode on */ +#else + sg.sg_flags &= ~CBREAK; /* cbreak mode off */ +#endif + sg.sg_flags |= ECHO; /* turn echo on */ + STTY(f, &sg); /* restore canonical mode */ + GLOBAL(echofd) = -1; + + return (int)c; +} + + +#else /* !UNIX && !__BEOS__ */ + + +int zgetch(__G__ f) + __GDEF + int f; /* file descriptor from which to read (must be open already) */ +{ + char c, c2; + +/*--------------------------------------------------------------------------- + Get a character from the given file descriptor without echo; can't fake + CBREAK mode (i.e., newline required), but can get rid of all chars up to + and including newline. + ---------------------------------------------------------------------------*/ + + echoff(f); + read(f, &c, 1); + if (c != '\n') + do { + read(f, &c2, 1); /* throw away all other chars up thru newline */ + } while (c2 != '\n'); + echon(); + return (int)c; +} + +#endif /* ?(UNIX || __BEOS__) */ + +#endif /* UNZIP && !FUNZIP */ +#endif /* !HAVE_WORKING_GETCH */ + + +#if CRYPT /* getp() is only used with full encryption */ + +/* + * Simple compile-time check for source compatibility between + * zcrypt and ttyio: + */ +#if (!defined(CR_MAJORVER) || (CR_MAJORVER < 2) || (CR_MINORVER < 7)) + error: This Info-ZIP tool requires zcrypt 2.7 or later. +#endif + +/* + * Get a password of length n-1 or less into *p using the prompt *m. + * The entered password is not echoed. + */ + +#ifdef HAVE_WORKING_GETCH +/* + * For the AMIGA, getch() is defined as Agetch(), which is in + * amiga/filedate.c; SAS/C 6.x provides a getch(), but since Agetch() + * uses the infrastructure that is already in place in filedate.c, it is + * smaller. With this function, echoff() and echon() are not needed. + * + * For the MAC, a non-echo macgetch() function is defined in the MacOS + * specific sources which uses the event handling mechanism of the + * desktop window manager to get a character from the keyboard. + * + * For the other systems in this section, a non-echo getch() function + * is either contained the C runtime library (conio package), or getch() + * is defined as an alias for a similar system specific RTL function. + */ + +#ifndef WINDLL /* WINDLL does not support a console interface */ +#ifndef QDOS /* QDOS supplies a variant of this function */ + +/* This is the getp() function for all systems (with TTY type user interface) + * that supply a working `non-echo' getch() function for "raw" console input. + */ +char *getp(__G__ m, p, n) + __GDEF + ZCONST char *m; /* prompt for password */ + char *p; /* return value: line input */ + int n; /* bytes available in p[] */ +{ + char c; /* one-byte buffer for read() to use */ + int i; /* number of characters input */ + char *w; /* warning on retry */ + + /* get password */ + w = ""; + do { + fputs(w, stderr); /* warning if back again */ + fputs(m, stderr); /* display prompt and flush */ + fflush(stderr); + i = 0; + do { /* read line, keeping first n characters */ + if ((c = (char)getch()) == '\r') + c = '\n'; /* until user hits CR */ + if (c == 8 || c == 127) { + if (i > 0) i--; /* the `backspace' and `del' keys works */ + } + else if (i < n) + p[i++] = c; /* truncate past n */ + } while (c != '\n'); + PUTC('\n', stderr); fflush(stderr); + w = "(line too long--try again)\n"; + } while (p[i-1] != '\n'); + p[i-1] = 0; /* terminate at newline */ + + return p; /* return pointer to password */ + +} /* end function getp() */ + +#endif /* !QDOS */ +#endif /* !WINDLL */ + + +#else /* !HAVE_WORKING_GETCH */ + + +#if (defined(UNIX) || defined(__MINT__) || defined(__BEOS__)) + +#ifndef _PATH_TTY +# ifdef __MINT__ +# define _PATH_TTY ttyname(2) +# else +# define _PATH_TTY "/dev/tty" +# endif +#endif + +char *getp(__G__ m, p, n) + __GDEF + ZCONST char *m; /* prompt for password */ + char *p; /* return value: line input */ + int n; /* bytes available in p[] */ +{ + char c; /* one-byte buffer for read() to use */ + int i; /* number of characters input */ + char *w; /* warning on retry */ + int f; /* file descriptor for tty device */ + +#ifdef PASSWD_FROM_STDIN + /* Read from stdin. This is unsafe if the password is stored on disk. */ + f = 0; +#else + /* turn off echo on tty */ + + if ((f = open(_PATH_TTY, 0)) == -1) + return NULL; +#endif + /* get password */ + w = ""; + do { + fputs(w, stderr); /* warning if back again */ + fputs(m, stderr); /* prompt */ + fflush(stderr); + i = 0; + echoff(f); + do { /* read line, keeping n */ + read(f, &c, 1); + if (i < n) + p[i++] = c; + } while (c != '\n'); + echon(); + PUTC('\n', stderr); fflush(stderr); + w = "(line too long--try again)\n"; + } while (p[i-1] != '\n'); + p[i-1] = 0; /* terminate at newline */ + +#ifndef PASSWD_FROM_STDIN + close(f); +#endif + + return p; /* return pointer to password */ + +} /* end function getp() */ + +#endif /* UNIX || __MINT__ || __BEOS__ */ + + + +#if (defined(VMS) || defined(CMS_MVS)) + +char *getp(__G__ m, p, n) + __GDEF + ZCONST char *m; /* prompt for password */ + char *p; /* return value: line input */ + int n; /* bytes available in p[] */ +{ + char c; /* one-byte buffer for read() to use */ + int i; /* number of characters input */ + char *w; /* warning on retry */ + FILE *f; /* file structure for SYS$COMMAND device */ + +#ifdef PASSWD_FROM_STDIN + f = stdin; +#else + if ((f = fopen(ctermid(NULL), "r")) == NULL) + return NULL; +#endif + + /* get password */ + fflush(stdout); + w = ""; + do { + if (*w) /* bug: VMS apparently adds \n to NULL fputs */ + fputs(w, stderr); /* warning if back again */ + fputs(m, stderr); /* prompt */ + fflush(stderr); + i = 0; + echoff(f); + do { /* read line, keeping n */ + if ((c = (char)getc(f)) == '\r') + c = '\n'; + if (i < n) + p[i++] = c; + } while (c != '\n'); + echon(); + PUTC('\n', stderr); fflush(stderr); + w = "(line too long--try again)\n"; + } while (p[i-1] != '\n'); + p[i-1] = 0; /* terminate at newline */ +#ifndef PASSWD_FROM_STDIN + fclose(f); +#endif + + return p; /* return pointer to password */ + +} /* end function getp() */ + +#endif /* VMS || CMS_MVS */ +#endif /* ?HAVE_WORKING_GETCH */ +#endif /* CRYPT */ +#endif /* CRYPT || (UNZIP && !FUNZIP) */ diff --git a/utils/Install/packzip/unix.c b/utils/Install/packzip/unix.c new file mode 100644 index 0000000000..c9eaaabafc --- /dev/null +++ b/utils/Install/packzip/unix.c @@ -0,0 +1,1424 @@ +/*--------------------------------------------------------------------------- + + unix.c + + Unix-specific routines for use with Info-ZIP's UnZip 5.3 and later. + + Contains: readdir() + do_wild() <-- generic enough to put in fileio.c? + mapattr() + mapname() + checkdir() + mkdir() + close_outfile() + set_direc_attribs() + stamp_file() + version() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" + +#ifdef SCO_XENIX +# define SYSNDIR +#else /* SCO Unix, AIX, DNIX, TI SysV, Coherent 4.x, ... */ +# if defined(__convexc__) || defined(SYSV) || defined(CRAY) || defined(BSD4_4) +# define DIRENT +# endif +#endif +#if defined(_AIX) +# define DIRENT +#endif +#ifdef COHERENT +# if defined(_I386) || (defined(__COHERENT__) && (__COHERENT__ >= 0x420)) +# define DIRENT +# endif +#endif + +/* GRR: may need to uncomment this: */ +#if 0 +#if defined(_POSIX_VERSION) +# define DIRENT +#endif +#endif + +#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 */ + +#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; + +static int isRISCOSexfield OF((uch *extra_field)); +#endif /* ACORN_FTYPE_NFS */ + +static int created_dir; /* used in mapname(), checkdir() */ +static int renamed_fullpath; /* ditto */ + + +#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 + char *wildspec; /* only used first time on a given dir */ +{ + static DIR *dir = (DIR *)NULL; + static char *dirname, *wildname, matchname[FILNAMSIZ]; + static int firstcall=TRUE, 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 (firstcall) { /* first call: must initialize everything */ + firstcall = FALSE; + + if (!iswild(wildspec)) { + strcpy(matchname, wildspec); + have_dirname = FALSE; + dir = NULL; + return matchname; + } + + /* break the wildspec into a directory part and a wildcard filename */ + if ((wildname = strrchr(wildspec, '/')) == (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")); + 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; + } + + if ((dir = opendir(dirname)) != (DIR *)NULL) { + while ((file = readdir(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 */ + if (match(file->d_name, wildname, 0) && /* 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(dir); + 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) */ + strcpy(matchname, wildspec); + return matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (dir == (DIR *)NULL) { + firstcall = TRUE; /* 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(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 */ + if (match(file->d_name, wildname, 0)) { /* 0 == don't ignore case */ + 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(dir); /* have read at least one dir entry; nothing left */ + dir = (DIR *)NULL; + firstcall = TRUE; /* 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; + + 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 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: + /* 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() */ +/************************/ + /* return 0 if no error, 1 if caution (filename */ +int mapname(__G__ renamed) /* truncated), 2 if warning (skip file because */ + __GDEF /* dir doesn't exist), 3 if error (skip file), */ + int renamed; /* or 10 if out of memory (skip file) */ +{ /* [also IZ_VOL_LABEL, IZ_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 */ +#endif + int quote = FALSE; /* flags */ + int error = 0; + register unsigned workch; /* hold the character being tested */ + + +/*--------------------------------------------------------------------------- + Initialize various pointers and counters and stuff. + ---------------------------------------------------------------------------*/ + + if (G.pInfo->vollabel) + return IZ_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) == 10) + return 10; /* 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 (quote) { /* if character quoted, */ + *pp++ = (char)workch; /* include it literally */ + quote = FALSE; + } else + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave directory 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 + + case '\026': /* control-V quote for special chars */ + quote = TRUE; /* set flag for next character */ + break; + +#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 */ + + *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 && isRISCOSexfield(G.extra_field)) { + /* file *must* have a RISC OS extra field */ + int ft = (int)makelong(((RO_extra_block *)G.extra_field)->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", ft>>8 & 0xFFF); + } +#endif /* ACORN_FTYPE_NFS */ + +/*--------------------------------------------------------------------------- + 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", + G.filename)); + } +#ifndef NO_CHMOD + /* 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 + return IZ_CREATED_DIR; /* set dir time (note trailing '/') */ + } + return 2; /* dir existed already; don't look for data to extract */ + } + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", + G.filename)); + return 3; + } + + 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: 1 - (on APPEND_NAME) truncated filename + * 2 - path doesn't exist, not allowed to create + * 3 - path doesn't exist, tried to create and failed; or + * path exists and is not a directory, but is supposed to be + * 4 - path is too long + * 10 - 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", 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); + return 2; /* path doesn't exist: nothing to do */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", buildpath)); + free(buildpath); + return 4; /* no room for filenames: fatal */ + } + if (mkdir(buildpath, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, + "checkdir error: cannot create %s\n\ + unable to process %s.\n", buildpath, G.filename)); + free(buildpath); + return 3; /* path didn't exist, tried to create, failed */ + } + 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", buildpath, G.filename)); + free(buildpath); + return 3; /* path existed but wasn't dir */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", buildpath)); + free(buildpath); + return 4; /* no room for filenames: fatal */ + } + *end++ = '/'; + *end = '\0'; + Trace((stderr, "buildpath now = [%s]\n", buildpath)); + return 0; + + } /* 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", pathcomp)); + free(buildpath); + buildpath = end = (char *)NULL; + return 0; + } + +/*--------------------------------------------------------------------------- + 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", 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", G.filename, buildpath)); + return 1; /* filename truncated */ + } + } + Trace((stderr, "buildpath now = [%s]\n", buildpath)); + return 0; /* could check for existence here, prompt for new 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. + ---------------------------------------------------------------------------*/ + +/* 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 10; + if ((rootlen > 0) && !renamed_fullpath) { + strcpy(buildpath, rootpath); + end = buildpath + rootlen; + } else { + *buildpath = '\0'; + end = buildpath; + } + Trace((stderr, "[%s]\n", buildpath)); + return 0; + } + +/*--------------------------------------------------------------------------- + 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", pathcomp)); + if (pathcomp == (char *)NULL) { + rootlen = 0; + return 0; + } + 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; + return 2; /* skip (or treat as stored file) */ + } + /* create the directory (could add loop here to scan pathcomp + * and 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", + pathcomp)); + rootlen = 0; /* path didn't exist, tried to create, and */ + return 3; /* failed: file exists, or 2+ levels required */ + } + } + if ((rootpath = (char *)malloc(rootlen+2)) == (char *)NULL) { + rootlen = 0; + return 10; + } + strcpy(rootpath, pathcomp); + rootpath[rootlen++] = '/'; + rootpath[rootlen] = '\0'; + Trace((stderr, "rootpath now = [%s]\n", rootpath)); + } + return 0; + } +#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 0; + } + + return 99; /* should never reach */ + +} /* end function checkdir() */ + + + + + +#ifdef NO_MKDIR + +/********************/ +/* Function mkdir() */ +/********************/ + +int mkdir(path, mode) + char *path; + int mode; /* ignored */ +/* + * returns: 0 - successful + * -1 - failed (errno not set, however) + */ +{ + char command[FILNAMSIZ+40]; /* buffer for system() call */ + + /* GRR 930416: added single quotes around path to avoid bug with + * creating directories with ampersands in name; not yet tested */ + sprintf(command, "IFS=\" \t\n\" /bin/mkdir '%s' 2>/dev/null", path); + if (system(command)) + return -1; + return 0; +} + +#endif /* NO_MKDIR */ + + + + + +#if 0 +#ifdef MORE + +/**************************/ +/* Function screenlines() */ +/**************************/ + +int screenlines() +{ + char *envptr, *getenv(); + int n; + + /* GRR: this is overly simplistic; should use winsize struct and + * appropriate TIOCGWINSZ ioctl(), assuming exists on enough systems + */ + envptr = getenv("LINES"); + if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) + return 24; /* VT-100 assumed to be minimal hardware */ + else + return n; +} + +#endif /* MORE */ +#endif /* 0 */ + + + + + +#ifndef MTS + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) /* GRR: change to return PK-style warning level */ + __GDEF +{ + iztimes zt; + ush z_uidgid[2]; + unsigned eb_izux_flg; + +/*--------------------------------------------------------------------------- + If symbolic links are supported, allocate a storage area, put the uncom- + pressed "data" in it, and create the link. 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) { + unsigned ucsize = (unsigned)G.lrec.ucsize; + char *linktarget = (char *)malloc((unsigned)G.lrec.ucsize+1); + + fclose(G.outfile); /* close "data" file... */ + G.outfile = fopen(G.filename, FOPR); /* ...and reopen for reading */ + if (!linktarget || fread(linktarget, 1, ucsize, G.outfile) != + (int)ucsize) + { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed\n", G.filename)); + if (linktarget) + free(linktarget); + fclose(G.outfile); + return; + } + fclose(G.outfile); /* close "data" file for good... */ + unlink(G.filename); /* ...and delete it */ + linktarget[ucsize] = '\0'; + if (QCOND2) + Info(slide, 0, ((char *)slide, "-> %s ", linktarget)); + if (symlink(linktarget, G.filename)) /* create the real link */ + perror("symlink error"); + free(linktarget); + return; /* can't set time on symlinks */ + } +#endif /* SYMLINKS */ + + fclose(G.outfile); +#ifdef QLZIP + if (G.extra_field) { + static void qlfix OF((__GPRO__ uch *ef_ptr, unsigned ef_len)); + + qlfix(__G__ G.extra_field, G.lrec.extra_field_length); + } +#endif + +/*--------------------------------------------------------------------------- + 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. + ---------------------------------------------------------------------------*/ + + 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 ? &zt : NULL), +#else + &zt, +#endif + z_uidgid) : 0); + if (eb_izux_flg & EB_UT_FL_MTIME) { + TTrace((stderr, "\nclose_outfile: Unix e.f. modif. time = %ld\n", + zt.mtime)); + } else { + zt.mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); + } + if (eb_izux_flg & EB_UT_FL_ATIME) { + TTrace((stderr, "close_outfile: Unix e.f. access time = %ld\n", + zt.atime)); + } else { + zt.atime = zt.mtime; + TTrace((stderr, "\nclose_outfile: modification/access times = %ld\n", + zt.mtime)); + } + + /* if -X option was specified and we have UID/GID info, restore it */ + if (uO.X_flag && eb_izux_flg & EB_UX2_VALID) { + 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 %d and/or GID %d for %s\n", + z_uidgid[0], z_uidgid[1], G.filename)); + else + Info(slide, 0x201, ((char *)slide, + " (warning) cannot set UID %d and/or GID %d", + z_uidgid[0], z_uidgid[1])); + } + } + + /* set the file's access and modification times */ + if (utime(G.filename, (ztimbuf *)&zt)) { +#ifdef AOS_VS + if (uO.qflag) + Info(slide, 0x201, ((char *)slide, "... cannot set time for %s\n", + G.filename)); + else + Info(slide, 0x201, ((char *)slide, "... cannot set time")); +#else + if (uO.qflag) + Info(slide, 0x201, ((char *)slide, + "warning: cannot set times for %s\n", G.filename)); + else + Info(slide, 0x201, ((char *)slide, + " (warning) cannot set times")); +#endif /* ?AOS_VS */ + } + +/*--------------------------------------------------------------------------- + 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() */ + +#endif /* !MTS */ + + + + +#ifdef SET_DIR_ATTRIB +/* messages of code for setting directory attributes */ +static char Far DirlistUidGidFailed[] = + "warning: cannot set UID %d and/or GID %d for %s\n"; +static char Far DirlistUtimeFailed[] = + "warning: cannot set modification, access times for %s\n"; +# ifndef NO_CHMOD + static char Far DirlistChmodFailed[] = + "warning: cannot set permissions for %s\n"; +# endif + + +int set_direc_attribs(__G__ d) + __GDEF + dirtime *d; +{ + int errval = PK_OK; + + if (d->have_uidgid && + chown(d->fn, (uid_t)d->uidgid[0], (gid_t)d->uidgid[1])) + { + Info(slide, 0x201, ((char *)slide, + LoadFarString(DirlistUidGidFailed), + d->uidgid[0], d->uidgid[1], d->fn)); + if (!errval) + errval = PK_WARN; + } + if (utime(d->fn, &d->u.t2)) { + Info(slide, 0x201, ((char *)slide, + LoadFarString(DirlistUtimeFailed), d->fn)); + if (!errval) + errval = PK_WARN; + } +#ifndef NO_CHMOD + if (chmod(d->fn, 0xffff & d->perms)) { + Info(slide, 0x201, ((char *)slide, + LoadFarString(DirlistChmodFailed), d->fn)); + /* perror("chmod (file attributes) error"); */ + if (!errval) + errval = PK_WARN; + } +#endif /* !NO_CHMOD */ + return errval; +} /* end function set_directory_attributes() */ + +#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 +{ +#if defined(CRAY) || defined(NX_CURRENT_COMPILER_RELEASE) || defined(NetBSD) + char buf1[40]; +#if defined(CRAY) || defined(NX_CURRENT_COMPILER_RELEASE) + char buf2[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(buf1, "NeXT DevKit %d.%02d ", NX_CURRENT_COMPILER_RELEASE/100, + NX_CURRENT_COMPILER_RELEASE%100), buf1), + (strlen(__VERSION__) > 8)? "(gcc)" : + (sprintf(buf2, "(gcc %s)", __VERSION__), buf2), +# else + "gcc ", __VERSION__, +# endif +#else +# if defined(CRAY) && defined(_RELEASE) + "cc ", (sprintf(buf1, "version %d", _RELEASE), buf1), +# else +# ifdef __VERSION__ + "cc ", __VERSION__, +# else + "cc", "", +# endif +# endif +#endif + + "Unix", + +#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(buf2, " (Cray UNICOS release %d)", _UNICOS), buf2), +# 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(buf1, " (NetBSD 0.8%c)", (char)(NetBSD0_8 - 1 + 'A')), buf1), +# else +# ifdef NetBSD0_9 + (sprintf(buf1, " (NetBSD 0.9%c)", (char)(NetBSD0_9 - 1 + 'A')), buf1), +# else +# ifdef NetBSD1_0 + (sprintf(buf1, " (NetBSD 1.0%c)", (char)(NetBSD1_0 - 1 + 'A')), buf1), +# 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 +#ifdef __QNX__ + " (QNX 4)", +#else +#ifdef __QNXNTO__ + " (QNX Neutrino)", +#else +#ifdef Lynx + " (LynxOS)", +#else + "", +#endif /* Lynx */ +#endif /* QNX Neutrino */ +#endif /* QNX 4 */ +#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 */ + + + + +#ifdef QLZIP + +struct qdirect { + long d_length __attribute__ ((packed)); /* file length */ + unsigned char d_access __attribute__ ((packed)); /* file access type */ + unsigned char d_type __attribute__ ((packed)); /* file type */ + long d_datalen __attribute__ ((packed)); /* data length */ + long d_reserved __attribute__ ((packed));/* Unused */ + short d_szname __attribute__ ((packed)); /* size of name */ + char d_name[36] __attribute__ ((packed));/* name area */ + long d_update __attribute__ ((packed)); /* last update */ + long d_refdate __attribute__ ((packed)); + long d_backup __attribute__ ((packed)); /* EOD */ +}; + +#define LONGID "QDOS02" +#define EXTRALEN (sizeof(struct qdirect) + 8) +#define JBLONGID "QZHD" +#define JBEXTRALEN (sizeof(jbextra) - 4 * sizeof(char)) + +typedef struct { + char eb_header[4] __attribute__ ((packed)); /* place_holder */ + char longid[8] __attribute__ ((packed)); + struct qdirect header __attribute__ ((packed)); +} qdosextra; + +typedef struct { + char eb_header[4]; /* place_holder */ + char longid[4]; + struct qdirect header; +} jbextra; + + + +/* The following two functions SH() and LG() convert big-endian short + * and long numbers into native byte order. They are some kind of + * counterpart to the generic UnZip's makeword() and makelong() functions. + */ +static ush SH(ush val) +{ + uch swapbuf[2]; + + swapbuf[1] = (uch)(val & 0xff); + swapbuf[0] = (uch)(val >> 8); + return (*(ush *)swapbuf); +} + + + +static ulg LG(ulg val) +{ + /* convert the big-endian unsigned long number `val' to the machine + * dependant representation + */ + ush swapbuf[2]; + + swapbuf[1] = SH((ush)(val & 0xffff)); + swapbuf[0] = SH((ush)(val >> 16)); + return (*(ulg *)swapbuf); +} + + + +static void qlfix(__G__ ef_ptr, ef_len) + __GDEF + uch *ef_ptr; + unsigned ef_len; +{ + while (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)) { + /* discovered some extra field inconsistency! */ + Trace((stderr, + "qlfix: block length %u > rest ef_size %u\n", eb_len, + ef_len - EB_HEADSIZE)); + break; + } + + switch (eb_id) { + case EF_QDOS: + { + struct _ntc_ + { + long id; + long dlen; + } ntc; + long dlen = 0; + + qdosextra *extra = (qdosextra *)ef_ptr; + jbextra *jbp = (jbextra *)ef_ptr; + + if (!strncmp(extra->longid, LONGID, strlen(LONGID))) + { + if (eb_len != EXTRALEN) + if (uO.qflag) + Info(slide, 0x201, ((char *)slide, + "warning: invalid length in Qdos field for %s\n", + G.filename)); + else + Info(slide, 0x201, ((char *)slide, + "warning: invalid length in Qdos field")); + + if (extra->header.d_type) + { + dlen = extra->header.d_datalen; + } + } + + if (!strncmp(jbp->longid, JBLONGID, strlen(JBLONGID))) + { + if (eb_len != JBEXTRALEN) + if (uO.qflag) + Info(slide, 0x201, ((char *)slide, + "warning: invalid length in QZ field for %s\n", + G.filename)); + else + Info(slide, 0x201, ((char *)slide, + "warning: invalid length in QZ field")); + if(jbp->header.d_type) + { + dlen = jbp->header.d_datalen; + } + } + + if ((long)LG(dlen) > 0) + { + G.outfile = fopen(G.filename,"r+"); + fseek(G.outfile, -8, SEEK_END); + fread(&ntc, 8, 1, G.outfile); + if(ntc.id != *(long *)"XTcc") + { + ntc.id = *(long *)"XTcc"; + ntc.dlen = dlen; + fwrite (&ntc, 8, 1, G.outfile); + } + Info(slide, 0x201, ((char *)slide, "QData = %d", LG(dlen))); + fclose(G.outfile); + } + return; /* finished, cancel further extra field scanning */ + } + + default: + Trace((stderr,"qlfix: unknown extra field block, ID=%d\n", + eb_id)); + } + + /* Skip this extra field block */ + ef_ptr += (eb_len + EB_HEADSIZE); + ef_len -= (eb_len + EB_HEADSIZE); + } +} +#endif /* QLZIP */ + + + + +#ifdef ACORN_FTYPE_NFS + +/* Acorn bits for NFS filetyping */ + +static int isRISCOSexfield(uch *extra_field) +{ + if (extra_field != NULL) { + RO_extra_block *block = (RO_extra_block *)extra_field; + return ( + makeword(block->ID) == EF_SPARK && + (makeword(block->size) == 24 || makeword(block->size) == 20) && + makelong(block->ID_2) == 0x30435241 /* ARC0 */); + } + return FALSE; +} +#endif /* ACORN_FTYPE_NFS */ diff --git a/utils/Install/packzip/unreduce.c b/utils/Install/packzip/unreduce.c new file mode 100644 index 0000000000..4cfb3fec6f --- /dev/null +++ b/utils/Install/packzip/unreduce.c @@ -0,0 +1,230 @@ +/*--------------------------------------------------------------------------- + + unreduce.c + + The Reducing algorithm is actually a combination of two distinct algorithms. + The first algorithm compresses repeated byte sequences, and the second al- + gorithm takes the compressed stream from the first algorithm and applies a + probabilistic compression method. + + * 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. + + See the accompanying file "COPYING" in UnZip source and binary distributions + for further information. This code is NOT used unless USE_SMITH_CODE is + explicitly defined (==> COPYRIGHT_CLEAN is not defined). + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" /* defines COPYRIGHT_CLEAN by default */ + + +#ifndef COPYRIGHT_CLEAN + +/**************************************/ +/* UnReduce Defines, Typedefs, etc. */ +/**************************************/ + +#define DLE 144 + +typedef uch f_array[64]; /* for followers[256][64] */ + + + +/******************************/ +/* UnReduce Local Functions */ +/******************************/ + +static void LoadFollowers OF((__GPRO__ f_array *followers, uch *Slen)); + + + +/*******************************/ +/* UnReduce Global Constants */ +/*******************************/ + +static ZCONST shrint L_table[] = +{0, 0x7f, 0x3f, 0x1f, 0x0f}; + +static ZCONST shrint D_shift[] = +{0, 0x07, 0x06, 0x05, 0x04}; +static ZCONST shrint D_mask[] = +{0, 0x01, 0x03, 0x07, 0x0f}; + +static ZCONST shrint B_table[] = +{8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8}; + + + + + +/*************************/ +/* Function unreduce() */ +/*************************/ + +void unreduce(__G) /* expand probabilistically reduced data */ + __GDEF +{ + register int lchar = 0; + shrint nchar; + shrint ExState = 0; + shrint V = 0; + shrint Len = 0; + long s = G.ucsize; /* number of bytes left to decompress */ + unsigned w = 0; /* position in output window slide[] */ + unsigned u = 1; /* true if slide[] unflushed */ + uch Slen[256]; + + f_array *followers = (f_array *)(slide + 0x4000); + int factor = G.lrec.compression_method - 1; + + LoadFollowers(__G__ followers, Slen); + + while (s > 0 /* && (!zipeof) */) { + if (Slen[lchar] == 0) + READBITS(8, nchar) /* ; */ + else { + READBITS(1, nchar) /* ; */ + if (nchar != 0) + READBITS(8, nchar) /* ; */ + else { + shrint follower; + int bitsneeded = B_table[Slen[lchar]]; + + READBITS(bitsneeded, follower) /* ; */ + nchar = followers[lchar][follower]; + } + } + /* expand the resulting byte */ + switch (ExState) { + + case 0: + if (nchar != DLE) { + s--; + slide[w++] = (uch)nchar; + if (w == 0x4000) { + flush(__G__ slide, (ulg)w, 0); + w = u = 0; + } + } + else + ExState = 1; + break; + + case 1: + if (nchar != 0) { + V = nchar; + Len = V & L_table[factor]; + if (Len == L_table[factor]) + ExState = 2; + else + ExState = 3; + } else { + s--; + slide[w++] = DLE; + if (w == 0x4000) + { + flush(__G__ slide, (ulg)w, 0); + w = u = 0; + } + ExState = 0; + } + break; + + case 2:{ + Len += nchar; + ExState = 3; + } + break; + + case 3:{ + register unsigned e; + register unsigned n = Len + 3; + register unsigned d = w - ((((V >> D_shift[factor]) & + D_mask[factor]) << 8) + nchar + 1); + + s -= n; + do { + n -= (e = (e = 0x4000 - ((d &= 0x3fff) > w ? d : w)) > n ? + n : e); + if (u && w <= d) + { + memzero(slide + w, e); + w += e; + d += e; + } + else + if (w - d < e) /* (assume unsigned comparison) */ + do { /* slow to avoid memcpy() overlap */ + slide[w++] = slide[d++]; + } while (--e); + else + { + memcpy(slide + w, slide + d, e); + w += e; + d += e; + } + if (w == 0x4000) + { + flush(__G__ slide, (ulg)w, 0); + w = u = 0; + } + } while (n); + + ExState = 0; + } + break; + } + + /* store character for next iteration */ + lchar = nchar; + } + + /* flush out slide */ + flush(__G__ slide, (ulg)w, 0); +} + + + + + +/******************************/ +/* Function LoadFollowers() */ +/******************************/ + +static void LoadFollowers(__G__ followers, Slen) + __GDEF + f_array *followers; + uch *Slen; +{ + register int x; + register int i; + + for (x = 255; x >= 0; x--) { + READBITS(6, Slen[x]) /* ; */ + for (i = 0; (uch)i < Slen[x]; i++) + READBITS(8, followers[x][i]) /* ; */ + } +} + +#endif /* !COPYRIGHT_CLEAN */ diff --git a/utils/Install/packzip/unshrink.c b/utils/Install/packzip/unshrink.c new file mode 100644 index 0000000000..287b4baf54 --- /dev/null +++ b/utils/Install/packzip/unshrink.c @@ -0,0 +1,301 @@ +/*--------------------------------------------------------------------------- + + unshrink.c version 1.21 23 Nov 95 + + + NOTE: This code may or may not infringe on the so-called "Welch + patent" owned by Unisys. (From reading the patent, it appears + that a pure LZW decompressor is *not* covered, but this claim has + not been tested in court, and Unisys is reported to believe other- + wise.) It is therefore the responsibility of the user to acquire + whatever license(s) may be required for legal use of this code. + + THE INFO-ZIP GROUP DISCLAIMS ALL LIABILITY FOR USE OF THIS CODE + IN VIOLATION OF APPLICABLE PATENT LAW. + + + Shrinking is basically a dynamic LZW algorithm with allowed code sizes of + up to 13 bits; in addition, there is provision for partial clearing of + leaf nodes. PKWARE uses the special code 256 (decimal) to indicate a + change in code size or a partial clear of the code tree: 256,1 for the + former and 256,2 for the latter. [Note that partial clearing can "orphan" + nodes: the parent-to-be can be cleared before its new child is added, + but the child is added anyway (as an orphan, as though the parent still + existed). When the tree fills up to the point where the parent node is + reused, the orphan is effectively "adopted." Versions prior to 1.05 were + affected more due to greater use of pointers (to children and siblings + as well as parents).] + + This replacement version of unshrink.c was written from scratch. It is + based only on the algorithms described in Mark Nelson's _The Data Compres- + sion Book_ and in Terry Welch's original paper in the June 1984 issue of + IEEE _Computer_; no existing source code, including any in Nelson's book, + was used. + + Memory requirements have been reduced in this version and are now no more + than the original Sam Smith code. This is still larger than any of the + other algorithms: at a minimum, 8K+8K+16K (stack+values+parents) assuming + 16-bit short ints, and this does not even include the output buffer (the + other algorithms leave the uncompressed data in the work area, typically + called slide[]). For machines with a 64KB data space this is a problem, + particularly when text conversion is required and line endings have more + than one character. UnZip's solution is to use two roughly equal halves + of outbuf for the ASCII conversion in such a case; the "unshrink" argument + to flush() signals that this is the case. + + For large-memory machines, a second outbuf is allocated for translations, + but only if unshrinking and only if translations are required. + + | binary mode | text mode + --------------------------------------------------- + big mem | big outbuf | big outbuf + big outbuf2 <- malloc'd here + small mem | small outbuf | half + half small outbuf + + Copyright 1994, 1995 Greg Roelofs. See the accompanying file "COPYING" + in UnZip 5.20 (or later) source or binary distributions. + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" /* defines LZW_CLEAN by default */ + + +#ifndef LZW_CLEAN + +static void partial_clear OF((__GPRO)); + +#ifdef DEBUG +# define OUTDBG(c) \ + if ((c)<32 || (c)>=127) pipeit("\\x%02x",(c)); else { } +#else +# define OUTDBG(c) +#endif + +/* HSIZE is defined as 2^13 (8192) in unzip.h */ +#define BOGUSCODE 256 +#define FLAG_BITS parent /* upper bits of parent[] used as flag bits */ +#define CODE_MASK (HSIZE - 1) /* 0x1fff (lower bits are parent's index) */ +#define FREE_CODE HSIZE /* 0x2000 (code is unused or was cleared) */ +#define HAS_CHILD (HSIZE << 1) /* 0x4000 (code has a child--do not clear) */ + +#define parent G.area.shrink.Parent +#define Value G.area.shrink.value /* "value" conflicts with Pyramid ioctl.h */ +#define stack G.area.shrink.Stack + + +/***********************/ +/* Function unshrink() */ +/***********************/ + +int unshrink(__G) + __GDEF +{ + int offset = (HSIZE - 1); + uch *stacktop = stack + offset; + register uch *newstr; + int codesize=9, len, KwKwK, error; + shrint code, oldcode, freecode, curcode; + shrint lastfreecode; + unsigned int outbufsiz; +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + /* Normally realbuf and outbuf will be the same. However, if the data + * are redirected to a large memory buffer, realbuf will point to the + * new location while outbuf will remain pointing to the malloc'd + * memory buffer. */ + uch *realbuf = G.outbuf; +#else +# define realbuf G.outbuf +#endif + + +/*--------------------------------------------------------------------------- + Initialize various variables. + ---------------------------------------------------------------------------*/ + + lastfreecode = BOGUSCODE; + +#ifndef VMS /* VMS uses its own buffer scheme for textmode flush(). */ +#ifndef SMALL_MEM + /* non-memory-limited machines: allocate second (large) buffer for + * textmode conversion in flush(), but only if needed */ + if (G.pInfo->textmode && !G.outbuf2 && + (G.outbuf2 = (uch *)malloc(TRANSBUFSIZ)) == (uch *)NULL) + return PK_MEM3; +#endif +#endif /* !VMS */ + + for (code = 0; code < BOGUSCODE; ++code) { + Value[code] = (uch)code; + parent[code] = BOGUSCODE; + } + for (code = BOGUSCODE+1; code < HSIZE; ++code) + parent[code] = FREE_CODE; + +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) { /* use normal outbuf unless we're a DLL routine */ + realbuf = G.redirect_buffer; + outbufsiz = G.redirect_size; + } else +#endif +#ifdef DLL + if (G.pInfo->textmode && !G.redirect_data) +#else + if (G.pInfo->textmode) +#endif + outbufsiz = RAWBUFSIZ; + else + outbufsiz = OUTBUFSIZ; + G.outptr = realbuf; + G.outcnt = 0L; + +/*--------------------------------------------------------------------------- + Get and output first code, then loop over remaining ones. + ---------------------------------------------------------------------------*/ + + READBITS(codesize, oldcode) + if (!G.zipeof) { + *G.outptr++ = (uch)oldcode; + OUTDBG((uch)oldcode) + ++G.outcnt; + } + + do { + READBITS(codesize, code) + if (G.zipeof) + break; + if (code == BOGUSCODE) { /* possible to have consecutive escapes? */ + READBITS(codesize, code) + if (code == 1) { + ++codesize; + Trace((stderr, " (codesize now %d bits)\n", codesize)); + } else if (code == 2) { + Trace((stderr, " (partial clear code)\n")); + partial_clear(__G); /* clear leafs (nodes with no children) */ + Trace((stderr, " (done with partial clear)\n")); + lastfreecode = BOGUSCODE; /* reset start of free-node search */ + } + continue; + } + + /*----------------------------------------------------------------------- + Translate code: traverse tree from leaf back to root. + -----------------------------------------------------------------------*/ + + newstr = stacktop; + curcode = code; + + if (parent[curcode] == FREE_CODE) { + /* or (FLAG_BITS[curcode] & FREE_CODE)? */ + KwKwK = TRUE; + Trace((stderr, " (found a KwKwK code %d; oldcode = %d)\n", code, + oldcode)); + --newstr; /* last character will be same as first character */ + curcode = oldcode; + } else + KwKwK = FALSE; + + do { + *newstr-- = Value[curcode]; + curcode = (shrint)(parent[curcode] & CODE_MASK); + } while (curcode != BOGUSCODE); + + len = (int)(stacktop - newstr++); + if (KwKwK) + *stacktop = *newstr; + + /*----------------------------------------------------------------------- + Write expanded string in reverse order to output buffer. + -----------------------------------------------------------------------*/ + + Trace((stderr, "code %4d; oldcode %4d; char %3d (%c); string [", code, + oldcode, (int)(*newstr), (*newstr<32 || *newstr>=127)? ' ':*newstr)); + + { + register uch *p; + + for (p = newstr; p < newstr+len; ++p) { + *G.outptr++ = *p; + OUTDBG(*p) + if (++G.outcnt == outbufsiz) { + Trace((stderr, "doing flush(), outcnt = %lu\n", G.outcnt)); + if ((error = flush(__G__ realbuf, G.outcnt, TRUE)) != 0) + pipeit("unshrink: flush() error (%d)\n", + error); + Trace((stderr, "done with flush()\n")); + G.outptr = realbuf; + G.outcnt = 0L; + } + } + } + + /*----------------------------------------------------------------------- + Add new leaf (first character of newstr) to tree as child of oldcode. + -----------------------------------------------------------------------*/ + + /* search for freecode */ + freecode = (shrint)(lastfreecode + 1); + /* add if-test before loop for speed? */ + while (parent[freecode] != FREE_CODE) + ++freecode; + lastfreecode = freecode; + Trace((stderr, "]; newcode %d\n", freecode)); + + Value[freecode] = *newstr; + parent[freecode] = oldcode; + oldcode = code; + + } while (!G.zipeof); + +/*--------------------------------------------------------------------------- + Flush any remaining data and return to sender... + ---------------------------------------------------------------------------*/ + + if (G.outcnt > 0L) { + Trace((stderr, "doing final flush(), outcnt = %lu\n", G.outcnt)); + if ((error = flush(__G__ realbuf, G.outcnt, TRUE)) != 0) + pipeit("unshrink: flush() error (%d)\n", error); + Trace((stderr, "done with flush()\n")); + } + + return PK_OK; + +} /* end function unshrink() */ + + + + + +/****************************/ +/* Function partial_clear() */ /* no longer recursive... */ +/****************************/ + +static void partial_clear(__G) + __GDEF +{ + register shrint code; + + /* clear all nodes which have no children (i.e., leaf nodes only) */ + + /* first loop: mark each parent as such */ + for (code = BOGUSCODE+1; code < HSIZE; ++code) { + register shrint cparent = (shrint)(parent[code] & CODE_MASK); + + if (cparent > BOGUSCODE && cparent != FREE_CODE) + FLAG_BITS[cparent] |= HAS_CHILD; /* set parent's child-bit */ + } + + /* second loop: clear all nodes *not* marked as parents; reset flag bits */ + for (code = BOGUSCODE+1; code < HSIZE; ++code) { + if (FLAG_BITS[code] & HAS_CHILD) /* just clear child-bit */ + FLAG_BITS[code] &= ~HAS_CHILD; + else { /* leaf: lose it */ + Trace((stderr, "%d\n", code)); + parent[code] = FREE_CODE; + } + } + + return; +} + +#endif /* !LZW_CLEAN */ diff --git a/utils/Install/packzip/unzip.c b/utils/Install/packzip/unzip.c new file mode 100644 index 0000000000..feada08bfc --- /dev/null +++ b/utils/Install/packzip/unzip.c @@ -0,0 +1,1744 @@ +/*--------------------------------------------------------------------------- + + unzip.c + + UnZip - a zipfile extraction utility. See below for make instructions, or + read the comments in Makefile and the various Contents files for more de- + tailed explanations. To report a bug, send a *complete* description to + Zip-Bugs@lists.wku.edu; include machine type, operating system and ver- + sion, compiler and version, and reasonably detailed error messages or prob- + lem report. To join Info-ZIP, see the instructions in README. + + UnZip 5.x is a greatly expanded and partially rewritten successor to 4.x, + which in turn was almost a complete rewrite of version 3.x. For a detailed + revision history, see UnzpHist.zip at quest.jpl.nasa.gov. For a list of + the many (near infinite) contributors, see "CONTRIBS" in the UnZip source + distribution. + + --------------------------------------------------------------------------- + + [from original zipinfo.c] + + This program reads great gobs of totally nifty information, including the + central directory stuff, from ZIP archives ("zipfiles" for short). It + started as just a testbed for fooling with zipfiles, but at this point it + is actually a useful utility. It also became the basis for the rewrite of + UnZip (3.16 -> 4.0), using the central directory for processing rather than + the individual (local) file headers. + + As of ZipInfo v2.0 and UnZip v5.1, the two programs are combined into one. + If the executable is named "unzip" (or "unzip.exe", depending), it behaves + like UnZip by default; if it is named "zipinfo" or "ii", it behaves like + ZipInfo. The ZipInfo behavior may also be triggered by use of unzip's -Z + option; for example, "unzip -Z [zipinfo_options] archive.zip". + + Another dandy product from your buddies at Newtware! + + Author: Greg Roelofs, newt@pobox.com, http://pobox.com/~newt/ + 23 August 1990 -> April 1997 + + --------------------------------------------------------------------------- + + Version: unzip5??.{tar.Z | tar.gz | zip} for Unix, VMS, OS/2, MS-DOS, Amiga, + Atari, Windows 3.x/95/NT/CE, Macintosh, Human68K, Acorn RISC OS, + BeOS, SMS/QDOS, VM/CMS, MVS, AOS/VS and TOPS-20. Decryption + requires sources in zcrypt28.zip. See the accompanying "WHERE" + file in the main source distribution for ftp, uucp, BBS and mail- + server sites, or see http://www.cdrom.com/pub/infozip/UnZip.html . + + Copyrights: see accompanying file "COPYING" in UnZip source distribution. + (This software is free but NOT IN THE PUBLIC DOMAIN. There + are some restrictions on commercial use.) + + ---------------------------------------------------------------------------*/ + + + +#define UNZIP_C +#define UNZIP_INTERNAL +#include "unzip.h" /* includes, typedefs, macros, prototypes, etc. */ +#include "crypt.h" +#include "version.h" + +#ifndef WINDLL /* The WINDLL port uses windll/windll.c instead... */ + +/*******************/ +/* Local Functions */ +/*******************/ + +#ifndef SFX +static void show_version_info OF((__GPRO)); +#endif + + +/*************/ +/* Constants */ +/*************/ + +#include "consts.h" /* all constant global variables are in here */ + /* (non-constant globals were moved to globals.c) */ + +/* constant local variables: */ + +#ifndef SFX + static ZCONST char Far EnvUnZip[] = ENV_UNZIP; + static ZCONST char Far EnvUnZip2[] = ENV_UNZIP2; + static ZCONST char Far EnvZipInfo[] = ENV_ZIPINFO; + static ZCONST char Far EnvZipInfo2[] = ENV_ZIPINFO2; +#ifdef RISCOS + static ZCONST char Far EnvUnZipExts[] = ENV_UNZIPEXTS; +#endif /* RISCOS */ +#endif + +#if (!defined(SFX) || defined(SFX_EXDIR)) + static ZCONST char Far NotExtracting[] = + "caution: not extracting; -d ignored\n"; + static ZCONST char Far MustGiveExdir[] = + "error: must specify directory to which to extract with -d option\n"; + static ZCONST char Far OnlyOneExdir[] = + "error: -d option used more than once (only one exdir allowed)\n"; +#endif + +#if CRYPT + static ZCONST char Far MustGivePasswd[] = + "error: must give decryption password with -P option\n"; +#endif + +#ifndef SFX + static ZCONST char Far Zfirst[] = + "error: -Z must be first option for ZipInfo mode (check UNZIP variable?)\n"; +#endif +static ZCONST char Far InvalidOptionsMsg[] = "error:\ + -fn or any combination of -c, -l, -p, -t, -u and -v options invalid\n"; +static ZCONST char Far IgnoreOOptionMsg[] = + "caution: both -n and -o specified; ignoring -o\n"; + +/* usage() strings */ +#ifndef SFX +#ifdef VMS + static ZCONST char Far Example3[] = "vms.c"; + static ZCONST char Far Example2[] = " unzip\ + \"-V\" foo \"Bar\" => must quote uppercase options and filenames in VMS\n"; +#else /* !VMS */ + static ZCONST char Far Example3[] = "ReadMe"; +#ifdef RISCOS + static ZCONST char Far Example2[] = +" unzip foo -d RAM:$ => extract all files from foo into RAMDisc\n"; +#else /* !RISCOS */ +#if (defined(OS2) || (defined(DOS_FLX_OS2_W32) && defined(MORE))) + static ZCONST char Far Example2[] = + ""; /* no room: too many local3[] items */ +#else /* !OS2 */ +#ifdef MACOS + static ZCONST char Far Example2[] = ""; /* not needed */ +#else /* !MACOS */ + static ZCONST char Far Example2[] = " \ + unzip -p foo | more => send contents of foo.zip via pipe into program more\n"; +#endif /* ?MACOS */ +#endif /* ?OS2 */ +#endif /* ?RISCOS */ +#endif /* ?VMS */ + +/* local1[]: command options */ +#if (defined(DLL) && defined(API_DOC)) + static ZCONST char Far local1[] = + " -A print extended help for API functions"; +#else /* !(DLL && API_DOC) */ + static ZCONST char Far local1[] = ""; +#endif /* ?(DLL && API_DOC) */ + +/* local2[] and local3[]: modifier options */ +#ifdef DOS_FLX_OS2_W32 +#ifdef FLEXOS + static ZCONST char Far local2[] = ""; +#else + static ZCONST char Far local2[] = + " -$ label removables (-$$ => fixed disks)"; +#endif +#ifdef OS2 +#ifdef MORE + static ZCONST char Far local3[] = "\ + -X restore ACLs if supported -s spaces in filenames => '_'\n\ + -M pipe through \"more\" pager\n"; +#else + static ZCONST char Far local3[] = " \ + -X restore ACLs if supported -s spaces in filenames => '_'\n\n"; +#endif /* ?MORE */ +#else /* !OS2 */ +#ifdef WIN32 +#ifdef MORE + static ZCONST char Far local3[] = "\ + -X restore ACLs (-XX => use privileges) -s spaces in filenames => '_'\n\ + -M pipe through \"more\" pager\n"; +#else + static ZCONST char Far local3[] = " \ + -X restore ACLs (-XX => use privileges) -s spaces in filenames => '_'\n\n"; +#endif /* ?MORE */ +#else /* !WIN32 */ +#ifdef MORE + static ZCONST char Far local3[] = " -\ +M pipe through \"more\" pager -s spaces in filenames => '_'\n\n"; +#else + static ZCONST char Far local3[] = "\ + -s spaces in filenames => '_'\n"; +#endif +#endif /* ?WIN32 */ +#endif /* ?OS2 || ?WIN32 */ +#else /* !DOS_FLX_OS2_W32 */ +#ifdef VMS + static ZCONST char Far local2[] = "\"-X\" restore owner/protection info"; +#ifdef MORE + static ZCONST char Far local3[] = " \ + \"-M\" pipe through \"more\" pager\n"; +#else + static ZCONST char Far local3[] = "\n"; +#endif +#else /* !VMS */ +#if (defined(__BEOS__) || defined(TANDEM) || defined(UNIX)) + static ZCONST char Far local2[] = " -X restore UID/GID info"; +#ifdef MORE + static ZCONST char Far local3[] = "\ + -M pipe through \"more\" pager\n"; +#else + static ZCONST char Far local3[] = "\n"; +#endif +#else /* !(__BEOS__ || TANDEM || UNIX) */ +#ifdef AMIGA + static ZCONST char Far local2[] = " -N restore comments as filenotes"; +#ifdef MORE + static ZCONST char Far local3[] = "\ + -M pipe through \"more\" pager\n"; +#else + static ZCONST char Far local3[] = "\n"; +#endif +#else /* !AMIGA */ +#ifdef MACOS + static ZCONST char Far local2[] = " -E show Mac info during extraction"; + static ZCONST char Far local3[] = " \ + -i ignore filenames in mac extra info -J junk (ignore) Mac extra info\n\n"; +#else /* !MACOS */ +#ifdef MORE + static ZCONST char Far local2[] = " -M pipe through \"more\" pager"; + static ZCONST char Far local3[] = "\n"; +#else + static ZCONST char Far local2[] = ""; /* Atari, Mac, CMS/MVS etc. */ + static ZCONST char Far local3[] = ""; +#endif +#endif /* ?MACOS */ +#endif /* ?AMIGA */ +#endif /* ?(__BEOS__ || TANDEM || UNIX) */ +#endif /* ?VMS */ +#endif /* ?DOS_FLX_OS2_W32 */ +#endif /* !SFX */ + +#ifndef NO_ZIPINFO +#ifdef VMS + static ZCONST char Far ZipInfoExample[] = "* or % (e.g., \"*font-%.zip\")"; +#else + static ZCONST char Far ZipInfoExample[] = "*, ?, [] (e.g., \"[a-j]*.zip\")"; +#endif + +static ZCONST char Far ZipInfoUsageLine1[] = "\ +ZipInfo %d.%d%d%s of %s, by Greg Roelofs and the Info-ZIP group.\n\ +\n\ +List name, date/time, attribute, size, compression method, etc., about files\n\ +in list (excluding those in xlist) contained in the specified .zip archive(s).\ +\n\"file[.zip]\" may be a wildcard name containing %s.\n\n\ + usage: zipinfo [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n\ + or: unzip %s-Z%s [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n"; + +static ZCONST char Far ZipInfoUsageLine2[] = "\nmain\ + listing-format options: -s short Unix \"ls -l\" format (def.)\n\ + -1 filenames ONLY, one per line -m medium Unix \"ls -l\" format\n\ + -2 just filenames but allow -h/-t/-z -l long Unix \"ls -l\" format\n\ + -v verbose, multi-page format\n"; + +static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\ + -h print header line -t print totals for listed files or for all\n\ + -z print zipfile comment %c-T%c print file times in sortable decimal format\ +\n %c-C%c be case-insensitive %s\ + -x exclude filenames that follow from listing\n"; +#ifdef MORE +#ifdef VMS + static ZCONST char Far ZipInfoUsageLine4[] = + " \"-M\" page output through built-in \"more\"\n"; +#else + static ZCONST char Far ZipInfoUsageLine4[] = + " -M page output through built-in \"more\"\n"; +#endif +#else /* !MORE */ + static ZCONST char Far ZipInfoUsageLine4[] = ""; +#endif /* ?MORE */ +#endif /* !NO_ZIPINFO */ + +#ifdef BETA +# ifdef VMSCLI + /* BetaVersion[] is also used in vms/cmdline.c: do not make it static */ + ZCONST char Far BetaVersion[] = "%s\ + THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n"; +# else + static ZCONST char Far BetaVersion[] = "%s\ + THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n"; +# endif +#endif + +#ifdef SFX +# ifdef VMSCLI + /* UnzipSFXBanner[] is also used in vms/cmdline.c: do not make it static */ + ZCONST char Far UnzipSFXBanner[] = +# else + static ZCONST char Far UnzipSFXBanner[] = +# endif + "UnZipSFX %d.%d%d%s of %s, by Info-ZIP (Zip-Bugs@lists.wku.edu).\n"; +# ifdef SFX_EXDIR + static ZCONST char Far UnzipSFXOpts[] = + "Valid options are -tfupcz and -d ; modifiers are -abjnoqCL%sV%s.\n"; +# else + static ZCONST char Far UnzipSFXOpts[] = + "Valid options are -tfupcz; modifiers are -abjnoqCL%sV%s.\n"; +# endif +#else /* !SFX */ + static ZCONST char Far CompileOptions[] = + "UnZip special compilation options:\n"; + static ZCONST char Far CompileOptFormat[] = "\t%s\n"; + static ZCONST char Far EnvOptions[] = + "\nUnZip and ZipInfo environment options:\n"; + static ZCONST char Far EnvOptFormat[] = "%16s: %s\n"; + static ZCONST char Far None[] = "[none]"; +# ifdef ACORN_FTYPE_NFS + static ZCONST char Far AcornFtypeNFS[] = "ACORN_FTYPE_NFS"; +# endif +# ifdef ASM_CRC + static ZCONST char Far AsmCRC[] = "ASM_CRC"; +# endif +# ifdef ASM_INFLATECODES + static ZCONST char Far AsmInflateCodes[] = "ASM_INFLATECODES"; +# endif +# ifdef CHECK_VERSIONS + static ZCONST char Far Check_Versions[] = "CHECK_VERSIONS"; +# endif +# ifdef COPYRIGHT_CLEAN + static ZCONST char Far Copyright_Clean[] = + "COPYRIGHT_CLEAN (PKZIP 0.9x unreducing method not supported)"; +# endif +# ifdef DEBUG + static ZCONST char Far UDebug[] = "DEBUG"; +# endif +# ifdef DEBUG_TIME + static ZCONST char Far DebugTime[] = "DEBUG_TIME"; +# endif +# ifdef DLL + static ZCONST char Far Dll[] = "DLL"; +# endif +# ifdef DOSWILD + static ZCONST char Far DosWild[] = "DOSWILD"; +# endif +# ifdef LZW_CLEAN + static ZCONST char Far LZW_Clean[] = + "LZW_CLEAN (PKZIP/Zip 1.x unshrinking method not supported)"; +# endif +# ifndef MORE + static ZCONST char Far No_More[] = "NO_MORE"; +# endif +# ifdef NO_ZIPINFO + static ZCONST char Far No_ZipInfo[] = "NO_ZIPINFO"; +# endif +# ifdef NTSD_EAS + static ZCONST char Far NTSDExtAttrib[] = "NTSD_EAS"; +# endif +# ifdef OS2_EAS + static ZCONST char Far OS2ExtAttrib[] = "OS2_EAS"; +# endif +# ifdef QLZIP + static ZCONST char Far SMSExFldOnUnix[] = "QLZIP"; +# endif +# ifdef REENTRANT + static ZCONST char Far Reentrant[] = "REENTRANT"; +# endif +# ifdef REGARGS + static ZCONST char Far RegArgs[] = "REGARGS"; +# endif +# ifdef RETURN_CODES + static ZCONST char Far Return_Codes[] = "RETURN_CODES"; +# endif +# ifdef SET_DIR_ATTRIB + static ZCONST char Far SetDirAttrib[] = "SET_DIR_ATTRIB"; +# endif +# ifdef TIMESTAMP + static ZCONST char Far TimeStamp[] = "TIMESTAMP"; +# endif +# ifdef UNIXBACKUP + static ZCONST char Far UnixBackup[] = "UNIXBACKUP"; +# endif +# ifdef USE_EF_UT_TIME + static ZCONST char Far Use_EF_UT_time[] = "USE_EF_UT_TIME"; +# endif +# ifndef LZW_CLEAN + static ZCONST char Far Use_Unshrink[] = + "USE_UNSHRINK (PKZIP/Zip 1.x unshrinking method supported)"; +# endif +# ifndef COPYRIGHT_CLEAN + static ZCONST char Far Use_Smith_Code[] = + "USE_SMITH_CODE (PKZIP 0.9x unreducing method supported)"; +# endif +# ifdef USE_VFAT + static ZCONST char Far Use_VFAT_support[] = "USE_VFAT"; +# endif +# ifdef USE_ZLIB + static ZCONST char Far UseZlib[] = + "USE_ZLIB (compiled with version %s; using version %s)"; +# endif +# ifdef VMS_TEXT_CONV + static ZCONST char Far VmsTextConv[] = "VMS_TEXT_CONV"; +# endif +# ifdef VMSCLI + static ZCONST char Far VmsCLI[] = "VMSCLI"; +# endif +# ifdef VMSWILD + static ZCONST char Far VmsWild[] = "VMSWILD"; +# endif +# if CRYPT +# ifdef PASSWD_FROM_STDIN + static ZCONST char Far PasswdStdin[] = "PASSWD_FROM_STDIN"; +# endif + static ZCONST char Far Decryption[] = + "\t[decryption, version %d.%d%s of %s]\n"; + static ZCONST char Far CryptDate[] = CR_VERSION_DATE; +# endif +# ifndef __RSXNT__ +# ifdef __EMX__ + static ZCONST char Far EnvEMX[] = "EMX"; + static ZCONST char Far EnvEMXOPT[] = "EMXOPT"; +# endif +# if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2))) + static ZCONST char Far EnvGO32[] = "GO32"; + static ZCONST char Far EnvGO32TMP[] = "GO32TMP"; +# endif +# endif /* !__RSXNT__ */ + +#ifdef VMS +/* UnzipUsageLine1[] is also used in vms/cmdline.c: do not make it static */ + ZCONST char Far UnzipUsageLine1[] = "\ +UnZip %d.%d%d%s of %s, by Info-ZIP. For more details see: unzip -v.\n\n"; +#ifdef COPYRIGHT_CLEAN + static ZCONST char Far UnzipUsageLine1v[] = "\ +UnZip %d.%d%d%s of %s, by Info-ZIP. Maintained by C. Spieler. Send\n\ +bug reports to the authors at Zip-Bugs@lists.wku.edu; see README for details.\ +\n\n"; +#else + static ZCONST char Far UnzipUsageLine1v[] = "\ +UnZip %d.%d%d%s of %s, by Info-ZIP. UnReduce (c) 1989 by S. H. Smith.\n\ +Send bug reports to authors at Zip-Bugs@lists.wku.edu; see README for details.\ +\n\n"; +#endif /* ?COPYRIGHT_CLEAN */ +#else /* !VMS */ +#ifdef COPYRIGHT_CLEAN + static ZCONST char Far UnzipUsageLine1[] = "\ +UnZip %d.%d%d%s of %s, by Info-ZIP. Maintained by C. Spieler. Send\n\ +bug reports to the authors at Zip-Bugs@lists.wku.edu; see README for details.\ +\n\n"; +#else + static ZCONST char Far UnzipUsageLine1[] = "\ +UnZip %d.%d%d%s of %s, by Info-ZIP. UnReduce (c) 1989 by S. H. Smith.\n\ +Send bug reports to authors at Zip-Bugs@lists.wku.edu; see README for details.\ +\n\n"; +#endif /* ?COPYRIGHT_CLEAN */ +#define UnzipUsageLine1v UnzipUsageLine1 +#endif /* ?VMS */ + +static ZCONST char Far UnzipUsageLine2v[] = "\ +Latest sources and executables are at ftp://ftp.cdrom.com/pub/infozip/ , as of\ +\nabove date; see http://www.cdrom.com/pub/infozip/UnZip.html for other sites.\ +\n\n"; + +#ifdef MACOS +static ZCONST char Far UnzipUsageLine2[] = "\ +Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-d exdir]\n \ + Default action is to extract files in list, to exdir;\n\ + file[.zip] may be a wildcard. %s\n"; +#else /* !MACOS */ +#ifdef VM_CMS +static ZCONST char Far UnzipUsageLine2[] = "\ +Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d fm]\n \ + Default action is to extract files in list, except those in xlist, to disk fm;\n\ + file[.zip] may be a wildcard. %s\n"; +#else /* !VM_CMS */ +static ZCONST char Far UnzipUsageLine2[] = "\ +Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]\n \ + Default action is to extract files in list, except those in xlist, to exdir;\n\ + file[.zip] may be a wildcard. %s\n"; +#endif /* ?VM_CMS */ +#endif /* ?MACOS */ + +#ifdef NO_ZIPINFO +# define ZIPINFO_MODE_OPTION "" + static ZCONST char Far ZipInfoMode[] = + "(ZipInfo mode is disabled in this version.)"; +#else +# define ZIPINFO_MODE_OPTION "[-Z] " +# ifdef VMS + static ZCONST char Far ZipInfoMode[] = + "\"-Z\" => ZipInfo mode (`unzip \"-Z\"' for usage)."; +# else + static ZCONST char Far ZipInfoMode[] = + "-Z => ZipInfo mode (\"unzip -Z\" for usage)."; +# endif +#endif /* ?NO_ZIPINFO */ + +#ifdef VMS + static ZCONST char Far VMSusageLine2b[] = "\ +=> define foreign command symbol in LOGIN.COM: $ unzip :== $dev:[dir]unzip.exe\ +\n"; +#endif + +#ifdef MACOS +static ZCONST char Far UnzipUsageLine3[] = "\n\ + -d extract files into exdir -l list files (short format)\n\ + -f freshen existing files, create none -t test compressed archive data\n\ + -u update files, create if necessary -z display archive comment\n\ +%s\n"; +#else /* !MACOS */ +#ifdef VM_CMS +static ZCONST char Far UnzipUsageLine3[] = "\n\ + -p extract files to pipe, no messages -l list files (short format)\n\ + -f freshen existing files, create none -t test compressed archive data\n\ + -u update files, create if necessary -z display archive comment\n\ + -x exclude files that follow (in xlist) -d extract files onto disk fm\n\ +%s\n"; +#else /* !VM_CMS */ +static ZCONST char Far UnzipUsageLine3[] = "\n\ + -p extract files to pipe, no messages -l list files (short format)\n\ + -f freshen existing files, create none -t test compressed archive data\n\ + -u update files, create if necessary -z display archive comment\n\ + -x exclude files that follow (in xlist) -d extract files into exdir\n\ +%s\n"; +#endif /* ?VM_CMS */ +#endif /* ?MACOS */ + +static ZCONST char Far UnzipUsageLine4[] = "\ +modifiers: -q quiet mode (-qq => quieter)\n\ + -n never overwrite existing files -a auto-convert any text files\n\ + -o overwrite files WITHOUT prompting -aa treat ALL files as text\n \ + -j junk paths (do not make directories) -v be verbose/print version info\n\ + %c-C%c match filenames case-insensitively %c-L%c make (some) names \ +lowercase\n %-42s %c-V%c retain VMS version numbers\n%s"; + +static ZCONST char Far UnzipUsageLine5[] = "\ +Examples (see unzip.doc for more info):\n\ + unzip data1 -x joe => extract all files except joe from zipfile data1.zip\n\ +%s\ + unzip -fo foo %-6s => quietly replace existing %s if archive file newer\n"; +#endif /* ?SFX */ + + + + + +/*****************************/ +/* main() / UzpMain() stub */ +/*****************************/ + +int include_unpack(char *aname) /* return PK-type error code (except under VMS) */ +{ + int r, argc = 3; + char *argv[4]; + + argv[0] = "install.exe"; + argv[1] = "-v"; + argv[2] = aname; + argv[3] = NULL; + + CONSTRUCTGLOBALS(); + r = unzip(__G__ argc, argv); + DESTROYGLOBALS() + RETURN(r); +} + +void resetglobals(void) { } + +int pipeit(char *format, ...) +{ + return 0; +} + +int confirm(char *format, ...) +{ + return 1; +} + + + +/*******************************/ +/* Primary UnZip entry point */ +/*******************************/ + +int unzip(__G__ argc, argv) + __GDEF + int argc; + char *argv[]; +{ +#ifndef NO_ZIPINFO + char *p; +#endif +#ifdef DOS_FLX_H68_OS2_W32 + int i; +#endif + int retcode, error=FALSE; + +#if (defined(__IBMC__) && defined(__DEBUG_ALLOC__)) + extern void DebugMalloc(void); + + atexit(DebugMalloc); +#endif + +#ifdef MALLOC_WORK + G.area.Slide =(uch *)calloc(8193, sizeof(shrint)+sizeof(uch)+sizeof(uch)); + G.area.shrink.Parent = (shrint *)G.area.Slide; + G.area.shrink.value = G.area.Slide + (sizeof(shrint)*(HSIZE+1)); + G.area.shrink.Stack = G.area.Slide + + (sizeof(shrint) + sizeof(uch))*(HSIZE+1); +#endif + +/*--------------------------------------------------------------------------- + Macintosh initialization code. + ---------------------------------------------------------------------------*/ + +#ifdef MACOS + { + int a; + + for (a = 0; a < 4; ++a) + G.rghCursor[a] = GetCursor(a+128); + G.giCursor = 0; + } +#endif + +/*--------------------------------------------------------------------------- + Human68K initialization code. + ---------------------------------------------------------------------------*/ + +#ifdef __human68k__ + InitTwentyOne(); +#endif + +/*--------------------------------------------------------------------------- + Acorn RISC OS initialization code. + ---------------------------------------------------------------------------*/ + +#ifdef RISCOS + set_prefix(); +#endif + +/*--------------------------------------------------------------------------- + Set signal handler for restoring echo, warn of zipfile corruption, etc. + ---------------------------------------------------------------------------*/ + +#ifdef SIGINT + signal(SIGINT, handler); +#endif +#ifdef SIGTERM /* some systems really have no SIGTERM */ + signal(SIGTERM, handler); +#endif +#ifdef SIGBUS + signal(SIGBUS, handler); +#endif +#ifdef SIGSEGV + signal(SIGSEGV, handler); +#endif + +#if (defined(WIN32) && defined(__RSXNT__)) + for (i = 0 ; i < argc; i++) { + _ISO_INTERN(argv[i]); + } +#endif + +/*--------------------------------------------------------------------------- + First figure out if we're running in UnZip mode or ZipInfo mode, and put + the appropriate environment-variable options into the queue. Then rip + through any command-line options lurking about... + ---------------------------------------------------------------------------*/ + +#ifdef SFX + G.argv0 = argv[0]; +#if (defined(OS2) || defined(WIN32)) + G.zipfn = GetLoadPath(__G);/* non-MSC NT puts path into G.filename[] */ +#else + G.zipfn = G.argv0; +#endif + +#ifdef VMSCLI + { + ulg status = vms_unzip_cmdline(&argc, &argv); + if (!(status & 1)) + return status; + } +#endif /* VMSCLI */ + + uO.zipinfo_mode = FALSE; + error = uz_opts(__G__ &argc, &argv); /* UnZipSFX call only */ + +#else /* !SFX */ + +#ifdef RISCOS + /* get the extensions to swap from environment */ + getRISCOSexts(ENV_UNZIPEXTS); +#endif + +#ifdef MSDOS + /* extract MKS extended argument list from environment (before envargs!) */ + mksargs(&argc, &argv); +#endif + +#ifdef VMSCLI + { + ulg status = vms_unzip_cmdline(&argc, &argv); + if (!(status & 1)) + return status; + } +#endif /* VMSCLI */ + + G.noargs = (argc == 1); /* no options, no zipfile, no anything */ + +#ifndef NO_ZIPINFO + for (p = argv[0] + strlen(argv[0]); p >= argv[0]; --p) { + if (*p == DIR_END +#ifdef DIR_END2 + || *p == DIR_END2 +#endif + ) + break; + } + ++p; + + if (STRNICMP(p, LoadFarStringSmall(Zipnfo), 7) == 0 || + STRNICMP(p, "ii", 2) == 0 || + (argc > 1 && strncmp(argv[1], "-Z", 2) == 0)) + { + uO.zipinfo_mode = TRUE; + envargs(__G__ &argc, &argv, LoadFarStringSmall(EnvZipInfo), + LoadFarStringSmall2(EnvZipInfo2)); + error = zi_opts(__G__ &argc, &argv); + } else +#endif /* NO_ZIPINFO */ + { + uO.zipinfo_mode = FALSE; + envargs(__G__ &argc, &argv, LoadFarStringSmall(EnvUnZip), + LoadFarStringSmall2(EnvUnZip2)); + error = uz_opts(__G__ &argc, &argv); + } + +#endif /* ?SFX */ + + if ((argc < 0) || error) + return error; + +/*--------------------------------------------------------------------------- + Now get the zipfile name from the command line and then process any re- + maining options and file specifications. + ---------------------------------------------------------------------------*/ + +#ifdef DOS_FLX_H68_OS2_W32 + /* convert MSDOS-style directory separators to Unix-style ones for + * user's convenience (include zipfile name itself) + */ +#ifdef SFX + for (G.pfnames = argv, i = argc; i > 0; --i) { +#else + /* argc does not include the zipfile specification */ + for (G.pfnames = argv, i = argc+1; i > 0; --i) { +#endif + char *q; + + for (q = *G.pfnames; *q; ++q) + if (*q == '\\') + *q = '/'; + ++G.pfnames; + } +#endif /* DOS_FLX_H68_OS2_W32 */ + +#ifndef SFX + G.wildzipfn = *argv++; +#endif + +#if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */ + + G.filespecs = argc; + G.xfilespecs = 0; + + if (argc > 0) { + char **pp = argv-1; + + G.pfnames = argv; + while (*++pp) + if (strcmp(*pp, "-x") == 0) { + if (pp > argv) { + *pp = 0; /* terminate G.pfnames */ + G.filespecs = pp - G.pfnames; + } else { + G.pfnames = (char **)fnames; /* defaults */ + G.filespecs = 0; + } + G.pxnames = pp + 1; /* excluded-names ptr: _after_ -x */ + G.xfilespecs = argc - G.filespecs - 1; + break; /* skip rest of args */ + } + G.process_all_files = FALSE; + } else + G.process_all_files = TRUE; /* for speed */ + +#else /* !SFX || SFX_EXDIR */ /* check for -x or -d */ + + G.filespecs = argc; + G.xfilespecs = 0; + + if (argc > 0) { + int in_files=FALSE, in_xfiles=FALSE; + char **pp = argv-1; + + G.process_all_files = FALSE; + G.pfnames = argv; + while (*++pp) { + Trace((stderr, "pp - argv = %d\n", pp-argv)); +#ifdef CMS_MVS + if (!uO.exdir && STRNICMP(*pp, "-d", 2) == 0) { +#else + if (!uO.exdir && strncmp(*pp, "-d", 2) == 0) { +#endif + int firstarg = (pp == argv); + + uO.exdir = (*pp) + 2; + if (in_files) { /* ... zipfile ... -d exdir ... */ + *pp = (char *)NULL; /* terminate G.pfnames */ + G.filespecs = pp - G.pfnames; + in_files = FALSE; + } else if (in_xfiles) { + *pp = (char *)NULL; /* terminate G.pxnames */ + G.xfilespecs = pp - G.pxnames; + /* "... -x xlist -d exdir": nothing left */ + } + /* first check for "-dexdir", then for "-d exdir" */ + if (*uO.exdir == '\0') { + if (*++pp) + uO.exdir = *pp; + else { + Info(slide, 0x401, ((char *)slide, + LoadFarString(MustGiveExdir))); + return(PK_PARAM); /* don't extract here by accident */ + } + } + if (firstarg) { /* ... zipfile -d exdir ... */ + if (pp[1]) { + G.pfnames = pp + 1; /* argv+2 */ + G.filespecs = argc - (G.pfnames-argv); /* for now... */ + } else { + G.process_all_files = TRUE; + G.pfnames = (char **)fnames; /* GRR: necessary? */ + G.filespecs = 0; /* GRR: necessary? */ + break; + } + } + } else if (!in_xfiles) { + if (strcmp(*pp, "-x") == 0) { + in_xfiles = TRUE; + if (pp == G.pfnames) { + G.pfnames = (char **)fnames; /* defaults */ + G.filespecs = 0; + } else if (in_files) { + *pp = 0; /* terminate G.pfnames */ + G.filespecs = pp - G.pfnames; /* adjust count */ + in_files = FALSE; + } + G.pxnames = pp + 1; /* excluded-names ptr starts after -x */ + G.xfilespecs = argc - (G.pxnames-argv); /* anything left */ + } else + in_files = TRUE; + } + } + } else + G.process_all_files = TRUE; /* for speed */ + + if (uO.exdir != (char *)NULL && !G.extract_flag) /* -d ignored */ + Info(slide, 0x401, ((char *)slide, LoadFarString(NotExtracting))); +#endif /* ?(SFX && !SFX_EXDIR) */ + +/*--------------------------------------------------------------------------- + Okey dokey, we have everything we need to get started. Let's roll. + ---------------------------------------------------------------------------*/ + + retcode = process_zipfiles(__G); + return(retcode); + +} /* end main()/unzip() */ + + + + + +/**********************/ +/* Function uz_opts() */ +/**********************/ + +int uz_opts(__G__ pargc, pargv) + __GDEF + int *pargc; + char ***pargv; +{ + char **argv, *s; + int argc, c, error=FALSE, negative=0; + + + 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; + 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; +#endif + case ('b'): + if (negative) { +#ifdef VMS + uO.bflag = MAX(uO.bflag-negative,0); +#endif + negative = 0; /* do nothing: "-b" is default */ + } else { +#ifdef VMS + if (uO.aflag == 0) + ++uO.bflag; +#endif + 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; +#ifdef NATIVE + uO.aflag = 0; +#endif + } else { + uO.cflag = TRUE; +#ifdef NATIVE + uO.aflag = 2; /* so you can read it on the screen */ +#endif +#ifdef DLL + if (G.redirect_text) + G.redirect_data = 2; +#endif + } + 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; +#endif /* !CMS_MVS */ +#if (!defined(SFX) || defined(SFX_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 = 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) + ; + } + break; +#endif /* !SFX || SFX_EXDIR */ + 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; +#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; +#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; +#endif /* RISCOS || ACORN_FTYPE_NFS */ + 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; +#endif /* MACOS */ + case ('j'): /* junk pathnames/directory structure */ + if (negative) + uO.jflag = FALSE, negative = 0; + else + uO.jflag = TRUE; + break; +#if (defined(__BEOS__) || defined(MACOS)) + case ('J'): /* Junk BeOS or MacOS file attributes */ + if( negative ) { + uO.J_flag = FALSE, negative = 0; + } else { + uO.J_flag = TRUE; + } + break; +#endif /* __BEOS__ || MACOS */ +#ifndef SFX + 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 = FALSE, negative = 0; + else + uO.L_flag = TRUE; + break; +#endif /* !CMS_MVS */ +#ifdef MORE +#ifdef CMS_MVS + case ('m'): +#endif + 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; +#endif /* MORE */ + 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; +#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; +#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: 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 = 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) + ; + } + break; +#endif /* CRYPT */ + 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 */ +#endif +#ifdef DOS_FLX_OS2_W32 + case ('s'): /* spaces in filenames: allow by default */ + if (negative) + uO.sflag = FALSE, negative = 0; + else + uO.sflag = TRUE; + break; +#endif /* DOS_FLX_OS2_W32 */ + 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; +#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; +#endif /* !CMS_MVS */ +#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; +#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; +#endif /* !CMS_MVS */ + 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; + } +#endif /* SFX */ + break; +#if (defined(RESTORE_UIDGID) || defined(OS2_W32)) + 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 || OS2_W32 */ + 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; +#endif /* !SFX */ +#ifdef DOS_OS2_W32 + case ('$'): + if (negative) { + uO.volflag = MAX(uO.volflag-negative,0); + negative = 0; + } else + ++uO.volflag; + break; +#endif /* DOS_OS2_W32 */ + default: + error = TRUE; + break; + + } /* end switch */ + } /* end while (not end of argument string) */ + } /* end while (not done with switches) */ + +/*--------------------------------------------------------------------------- + Check for nonsensical combinations of options. + ---------------------------------------------------------------------------*/ + +#ifdef SFX +opts_done: /* yes, very ugly...but only used by UnZipSFX with -x xlist */ +#endif + + if ((uO.cflag && uO.tflag) || (uO.cflag && 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; +#endif + 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 ((argc-- == 0) || error) +#endif + { + *pargc = argc; + *pargv = argv; +#ifndef SFX + if (uO.vflag >= 2 && argc == -1) { /* "unzip -v" */ + show_version_info(__G); + return PK_OK; + } + if (!G.noargs && !error) + error = PK_PARAM; /* had options (not -h or -v) but no zipfile */ +#endif /* !SFX */ + return USAGE(error); + } + +#ifdef SFX + /* 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, PATCHLEVEL, 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; + + *pargc = argc; + *pargv = argv; + return PK_OK; + +} /* end function uz_opts() */ + + + + +/********************/ +/* Function usage() */ +/********************/ + +#ifdef SFX +# ifdef VMS +# define LOCAL "X. Quote uppercase options" +# endif +# ifdef UNIX +# define LOCAL "X" +# endif +# ifdef DOS_OS2_W32 +# define LOCAL "s$" +# endif +# ifdef FLEXOS +# define LOCAL "s" +# endif +# ifdef AMIGA +# define LOCAL "N" +# endif + /* Default for all other systems: */ +# ifndef LOCAL +# define LOCAL "" +# endif + +# ifdef MORE +# define SFXOPT1 "M" +# else +# define SFXOPT1 "" +# endif + +int usage(__G__ error) /* return PK-type error code */ + __GDEF + int error; +{ + Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner), + UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL, + LoadFarStringSmall(VersionDate))); + Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXOpts), + SFXOPT1, LOCAL)); +#ifdef BETA + Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n", + "SFX")); +#endif + + if (error) + return PK_PARAM; + else + return PK_COOL; /* just wanted usage screen: no error */ + +} /* end function usage() */ + + + + + +#else /* !SFX */ +# ifdef VMS +# define QUOT '\"' +# define QUOTS "\"" +# else +# define QUOT ' ' +# define QUOTS "" +# endif + +int usage(__G__ error) /* return PK-type error code */ + __GDEF + int error; +{ + int flag = (error? 1 : 0); + + +/*--------------------------------------------------------------------------- + Print either ZipInfo usage or UnZip usage, depending on incantation. + (Strings must be no longer than 512 bytes for Turbo C, apparently.) + ---------------------------------------------------------------------------*/ + + if (uO.zipinfo_mode) { + +#ifndef NO_ZIPINFO + + Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine1), + ZI_MAJORVER, ZI_MINORVER, PATCHLEVEL, BETALEVEL, + LoadFarStringSmall(VersionDate), + LoadFarStringSmall2(ZipInfoExample), QUOTS,QUOTS)); + Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine2))); + Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine3), + QUOT,QUOT, QUOT,QUOT, LoadFarStringSmall(ZipInfoUsageLine4))); +#ifdef VMS + Info(slide, flag, ((char *)slide, "\nRemember that non-lowercase\ + filespecs must be quoted in VMS (e.g., \"Makefile\").\n")); +#endif + +#endif /* !NO_ZIPINFO */ + + } else { /* UnZip mode */ + + Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine1), + UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL, + LoadFarStringSmall(VersionDate))); +#ifdef BETA + Info(slide, flag, ((char *)slide, LoadFarString(BetaVersion), "", "")); +#endif + + Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine2), + ZIPINFO_MODE_OPTION, LoadFarStringSmall(ZipInfoMode))); +#ifdef VMS + if (!error) /* maybe no command-line tail found; show extra help */ + Info(slide, flag, ((char *)slide, LoadFarString(VMSusageLine2b))); +#endif + + Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine3), + LoadFarStringSmall(local1))); + + Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine4), + QUOT,QUOT, QUOT,QUOT, LoadFarStringSmall(local2), QUOT,QUOT, + LoadFarStringSmall2(local3))); + + /* This is extra work for SMALL_MEM, but it will work since + * LoadFarStringSmall2 uses the same buffer. Remember, this + * is a hack. */ + Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine5), + LoadFarStringSmall(Example2), LoadFarStringSmall2(Example3), + LoadFarStringSmall2(Example3))); + + } /* end if (uO.zipinfo_mode) */ + + if (error) + return PK_PARAM; + else + return PK_COOL; /* just wanted usage screen: no error */ + +} /* end function usage() */ + +#endif /* ?SFX */ + + + + +#ifndef SFX + +/********************************/ +/* Function show_version_info() */ +/********************************/ + +static void show_version_info(__G) + __GDEF +{ + if (uO.qflag > 3) /* "unzip -vqqqq" */ + Info(slide, 0, ((char *)slide, "%d\n", + (UZ_MAJORVER*100 + UZ_MINORVER*10 + PATCHLEVEL))); + else { + char *envptr, *getenv(); + int numopts = 0; + + Info(slide, 0, ((char *)slide, LoadFarString(UnzipUsageLine1v), + UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL, + LoadFarStringSmall(VersionDate))); + Info(slide, 0, ((char *)slide, + LoadFarString(UnzipUsageLine2v))); + version(__G); + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptions))); +#ifdef ACORN_FTYPE_NFS + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(AcornFtypeNFS))); + ++numopts; +#endif +#ifdef ASM_CRC + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(AsmCRC))); + ++numopts; +#endif +#ifdef ASM_INFLATECODES + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(AsmInflateCodes))); + ++numopts; +#endif +#ifdef CHECK_VERSIONS + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Check_Versions))); + ++numopts; +#endif +#ifdef COPYRIGHT_CLEAN + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Copyright_Clean))); + ++numopts; +#endif +#ifdef DEBUG + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(UDebug))); + ++numopts; +#endif +#ifdef DEBUG_TIME + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(DebugTime))); + ++numopts; +#endif +#ifdef DLL + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Dll))); + ++numopts; +#endif +#ifdef DOSWILD + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(DosWild))); + ++numopts; +#endif +#ifdef LZW_CLEAN + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(LZW_Clean))); + ++numopts; +#endif +#ifndef MORE + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(No_More))); + ++numopts; +#endif +#ifdef NO_ZIPINFO + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(No_ZipInfo))); + ++numopts; +#endif +#ifdef NTSD_EAS + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(NTSDExtAttrib))); + ++numopts; +#endif +#ifdef OS2_EAS + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(OS2ExtAttrib))); + ++numopts; +#endif +#ifdef QLZIP + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(SMSExFldOnUnix))); + ++numopts; +#endif +#ifdef REENTRANT + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Reentrant))); + ++numopts; +#endif +#ifdef REGARGS + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(RegArgs))); + ++numopts; +#endif +#ifdef RETURN_CODES + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Return_Codes))); + ++numopts; +#endif +#ifdef SET_DIR_ATTRIB + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(SetDirAttrib))); + ++numopts; +#endif +#ifdef TIMESTAMP + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(TimeStamp))); + ++numopts; +#endif +#ifdef UNIXBACKUP + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(UnixBackup))); + ++numopts; +#endif +#ifdef USE_EF_UT_TIME + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Use_EF_UT_time))); + ++numopts; +#endif +#ifndef COPYRIGHT_CLEAN + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Use_Smith_Code))); + ++numopts; +#endif +#ifndef LZW_CLEAN + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Use_Unshrink))); + ++numopts; +#endif +#ifdef USE_VFAT + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Use_VFAT_support))); + ++numopts; +#endif +#ifdef USE_ZLIB + sprintf((char *)(slide+256), LoadFarStringSmall(UseZlib), + ZLIB_VERSION, zlib_version); + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + (char *)(slide+256))); + ++numopts; +#endif +#ifdef VMS_TEXT_CONV + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(VmsTextConv))); + ++numopts; +#endif +#ifdef VMSCLI + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(VmsCLI))); + ++numopts; +#endif +#ifdef VMSWILD + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(VmsWild))); + ++numopts; +#endif +#if CRYPT +# ifdef PASSWD_FROM_STDIN + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(PasswdStdin))); +# endif + Info(slide, 0, ((char *)slide, LoadFarString(Decryption), + CR_MAJORVER, CR_MINORVER, CR_BETA_VER, + LoadFarStringSmall(CryptDate))); + ++numopts; +#endif /* CRYPT */ + if (numopts == 0) + Info(slide, 0, ((char *)slide, + LoadFarString(CompileOptFormat), + LoadFarStringSmall(None))); + + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptions))); + envptr = getenv(LoadFarStringSmall(EnvUnZip)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvUnZip), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); + envptr = getenv(LoadFarStringSmall(EnvUnZip2)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvUnZip2), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); + envptr = getenv(LoadFarStringSmall(EnvZipInfo)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvZipInfo), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); + envptr = getenv(LoadFarStringSmall(EnvZipInfo2)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvZipInfo2), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); +#ifndef __RSXNT__ +#ifdef __EMX__ + envptr = getenv(LoadFarStringSmall(EnvEMX)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvEMX), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); + envptr = getenv(LoadFarStringSmall(EnvEMXOPT)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvEMXOPT), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); +#endif /* __EMX__ */ +#if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2))) + envptr = getenv(LoadFarStringSmall(EnvGO32)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvGO32), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); + envptr = getenv(LoadFarStringSmall(EnvGO32TMP)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvGO32TMP), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); +#endif /* __GO32__ && !(__DJGPP__ >= 2) */ +#endif /* !__RSXNT__ */ +#ifdef RISCOS + envptr = getenv(LoadFarStringSmall(EnvUnZipExts)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvUnZipExts), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); +#endif /* RISCOS */ + } +} /* end function show_version() */ + +#endif /* !SFX */ +#endif /* !WINDLL */ diff --git a/utils/Install/packzip/unzip.def b/utils/Install/packzip/unzip.def new file mode 100644 index 0000000000..e57dd829c7 --- /dev/null +++ b/utils/Install/packzip/unzip.def @@ -0,0 +1,4 @@ +NAME WINDOWCOMPAT NEWFILES +DESCRIPTION 'The world-famous Info-ZIP unarchiving utilities' +; SEGMENTS +; _MSGSEG32 CLASS 'CODE' diff --git a/utils/Install/packzip/unzipstb.c b/utils/Install/packzip/unzipstb.c new file mode 100644 index 0000000000..6ca238a89f --- /dev/null +++ b/utils/Install/packzip/unzipstb.c @@ -0,0 +1,48 @@ +/*--------------------------------------------------------------------------- + + unzipstb.c + + Simple stub function for UnZip DLL (or shared library, whatever); does + exactly the same thing as normal UnZip, except for additional printf()s + of various version numbers, solely as a demonstration of what can/should + be checked when using the DLL. (If major version numbers ever differ, + assume program is incompatible with DLL--especially if DLL version is + older. This is not likely to be a problem with *this* simple program, + but most user programs will be much more complex.) + + ---------------------------------------------------------------------------*/ + +#include +#include "unzip.h" +#include "version.h" + +int main(int argc, char *argv[]) +{ + static UzpVer *pVersion; /* no pervert jokes, please... */ + + pVersion = UzpVersion(); + + printf("UnZip stub: checking version numbers (DLL is dated %s)\n", + pVersion->date); + printf(" UnZip versions: expecting %d.%d%d, using %d.%d%d%s\n", + UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, pVersion->unzip.major, + pVersion->unzip.minor, pVersion->unzip.patchlevel, pVersion->betalevel); + printf(" ZipInfo versions: expecting %d.%d%d, using %d.%d%d\n", + ZI_MAJORVER, ZI_MINORVER, PATCHLEVEL, pVersion->zipinfo.major, + pVersion->zipinfo.minor, pVersion->zipinfo.patchlevel); + +/* + D2_M*VER and os2dll.* are obsolete, though retained for compatibility: + + printf(" OS2 DLL versions: expecting %d.%d%d, using %d.%d%d\n", + D2_MAJORVER, D2_MINORVER, PATCHLEVEL, pVersion->os2dll.major, + pVersion->os2dll.minor, pVersion->os2dll.patchlevel); + */ + + if (pVersion->flag & 2) + printf(" using zlib version %s\n", pVersion->zlib_version); + printf("\n"); + + /* call the actual UnZip routine (string-arguments version) */ + return UzpMain(argc, argv); +} diff --git a/utils/Install/packzip/win32.c b/utils/Install/packzip/win32.c new file mode 100644 index 0000000000..f50ee5f9dd --- /dev/null +++ b/utils/Install/packzip/win32.c @@ -0,0 +1,2390 @@ +/*--------------------------------------------------------------------------- + + win32.c + + 32-bit Windows-specific (NT/95) routines for use with Info-ZIP's UnZip 5.3 + and later. + + Contains: GetLoadPath() + Opendir() + Readdir() + Closedir() + process_defer_NT() process any deferred items + SetSD() set security descriptor on file + EvalExtraFields() evaluate and process and extra field NOW + IsWinNT() indicate type of WIN32 platform + test_NTSD() test integrity of NT security data + utime2FileTime() + FStampIsLocTime() + FileTime2utime() + VFatFileTime2utime() + UTCtime2Localtime() + NTtzbugWorkaround() + getNTfiletime() + close_outfile() + stamp_file() + isfloppy() + NTQueryVolInfo() + IsVolumeOldFAT() + do_wild() + mapattr() + mapname() + map2fat() + checkdir() + version() + zstat_win32() + getch_win32() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" +#include /* must be AFTER unzip.h to avoid struct G problems */ +#ifdef __RSXNT__ +# include "rsxntwin.h" +#endif +#include "nt.h" + +#ifndef FUNZIP /* most of this file is not used with fUnZip */ + +#if (defined(__GO32__) || defined(__EMX__) || defined(__CYGWIN32__)) +# define MKDIR(path,mode) mkdir(path,mode) +#else +# define MKDIR(path,mode) mkdir(path) +#endif + +#ifdef HAVE_WORKING_DIRENT_H +# undef HAVE_WORKING_DIRENT_H +#endif +/* The emxrtl dirent support of (__GO32__ || __EMX__) converts to lowercase! */ +#if defined(__CYGWIN32__) +# define HAVE_WORKING_DIRENT_H +#endif + +#ifndef SFX +# ifdef HAVE_WORKING_DIRENT_H +# include /* use readdir() */ +# define zdirent dirent +# define zDIR DIR +# define Opendir opendir +# define Readdir readdir +# define Closedir closedir +# else /* !HAVE_WORKING_DIRENT_H */ + typedef struct zdirent { + char reserved [21]; + char ff_attrib; + short ff_ftime; + short ff_fdate; + long size; + char d_name[MAX_PATH]; + int d_first; + HANDLE d_hFindFile; + } zDIR; + + static zDIR *Opendir (const char *n); + static struct zdirent *Readdir (zDIR *d); + static void Closedir (zDIR *d); +# endif /* ?HAVE_WORKING_DIRENT_H */ +#endif /* !SFX */ + + +/* Function prototypes */ +#ifdef NTSD_EAS + static int SetSD(__GPRO__ char *path, PVOLUMECAPS VolumeCaps, + uch *eb_ptr, unsigned eb_len); + static int EvalExtraFields(__GPRO__ char *path, uch *ef_ptr, + unsigned ef_len); +#endif + +#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND) || \ + defined(TIMESTAMP)) + static void utime2FileTime(time_t ut, FILETIME *pft); + static int FStampIsLocTime(__GPRO__ const char *path); +#endif /* USE_EF_UT_TIME || NT_TZBUG_WORKAROUND || TIMESTAMP */ +#ifdef NT_TZBUG_WORKAROUND + static int FileTime2utime(const FILETIME *pft, time_t *ut); +#ifdef W32_STAT_BANDAID + static int VFatFileTime2utime(const FILETIME *pft, time_t *ut); +#endif + static time_t UTCtime2Localtime(time_t utctime); + static void NTtzbugWorkaround(time_t ut, FILETIME *pft); +#endif /* NT_TZBUG_WORKAROUND */ + +static int getNTfiletime (__GPRO__ FILETIME *pModFT, FILETIME *pAccFT, + FILETIME *pCreFT); +static int isfloppy (int nDrive); +static int NTQueryVolInfo (__GPRO__ const char *name); +static int IsVolumeOldFAT (__GPRO__ const char *name); +static void map2fat (char *pathcomp, char **pEndFAT); + + +#ifdef __MINGW32__ + int _CRT_glob = 0; /* suppress command line globbing by C RTL */ +#endif + +/* static int created_dir; */ /* used by mapname(), checkdir() */ +/* static int renamed_fullpath; */ /* ditto */ +/* static int fnlen; */ /* ditto */ +/* static unsigned nLabelDrive; */ /* ditto */ + +extern char Far TruncNTSD[]; /* in extract.c */ + + + +#ifdef SFX + +/**************************/ +/* Function GetLoadPath() */ +/**************************/ + +char *GetLoadPath(__GPRO) +{ +#ifdef MSC + extern char *_pgmptr; + return _pgmptr; + +#else /* use generic API call */ + + GetModuleFileName(NULL, G.filename, FILNAMSIZ-1); + _ISO_INTERN(G.filename); /* translate to codepage of C rtl's stdio */ + return G.filename; +#endif + +} /* end function GetLoadPath() */ + + + + + +#else /* !SFX */ + +#ifndef HAVE_WORKING_DIRENT_H + +/**********************/ /* Borrowed from ZIP 2.0 sources */ +/* Function Opendir() */ /* Difference: no special handling for */ +/**********************/ /* hidden or system files. */ + +static zDIR *Opendir(n) + const char *n; /* directory to open */ +{ + zDIR *d; /* malloc'd return value */ + char *p; /* malloc'd temporary string */ + WIN32_FIND_DATA fd; + extent len = strlen(n); + + /* Start searching for files in directory n */ + + if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL || + (p = malloc(strlen(n) + 5)) == NULL) + { + if (d != (zDIR *)NULL) + free((void *)d); + return (zDIR *)NULL; + } + INTERN_TO_ISO(n, p); + if (len > 0) { + if (p[len-1] == ':') + p[len++] = '.'; /* x: => x:. */ + else if (p[len-1] == '/' || p[len-1] == '\\') + --len; /* foo/ => foo */ + } + strcpy(p+len, "/*"); + + if (INVALID_HANDLE_VALUE == (d->d_hFindFile = FindFirstFile(p, &fd))) { + free((zvoid *)d); + free((zvoid *)p); + return NULL; + } + strcpy(d->d_name, fd.cFileName); + + free((zvoid *)p); + d->d_first = 1; + return d; + +} /* end of function Opendir() */ + + + + +/**********************/ /* Borrowed from ZIP 2.0 sources */ +/* Function Readdir() */ /* Difference: no special handling for */ +/**********************/ /* hidden or system files. */ + +static 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 + { + WIN32_FIND_DATA fd; + + if ( !FindNextFile(d->d_hFindFile, &fd) ) + return NULL; + + ISO_TO_INTERN(fd.cFileName, d->d_name); + } + return (struct zdirent *)d; + +} /* end of function Readdir() */ + + + + +/***********************/ +/* Function Closedir() */ /* Borrowed from ZIP 2.0 sources */ +/***********************/ + +static void Closedir(d) + zDIR *d; /* directory stream to close */ +{ + FindClose(d->d_hFindFile); + free(d); +} + +#endif /* !HAVE_WORKING_DIRENT_H */ +#endif /* ?SFX */ + + + + +#ifdef NTSD_EAS + +/*********************************/ +/* Function process_defer_NT() */ +/*********************************/ + +void process_defer_NT(__G) + __GDEF +{ + /* process deferred items */ + + DWORD dir, bytes; + DWORD dirfail, bytesfail; + + ProcessDefer(&dir, &bytes, &dirfail, &bytesfail); + + if (!uO.tflag && (uO.qflag < 2)) { + if (dir) + Info(slide, 0, ((char *)slide, + " updated: %lu directory entries with %lu bytes security", + (ulg)dir, (ulg)bytes)); + if (dirfail) + Info(slide, 0, ((char *)slide, + " failed: %lu directory entries with %lu bytes security", + (ulg)dirfail, (ulg)bytesfail)); + } +} + + + +/**********************/ +/* Function SetSD() */ /* return almost-PK errors */ +/**********************/ + +static int SetSD(__G__ path, VolumeCaps, eb_ptr, eb_len) + __GDEF + char *path; + PVOLUMECAPS VolumeCaps; + uch *eb_ptr; + unsigned eb_len; +{ + ulg ntsd_ucSize; + uch *security_data; + int error; + + if (eb_ptr == NULL || eb_len < EB_NTSD_L_LEN) + return PK_OK; /* not a valid NTSD extra field: assume OK */ + + /* check if we know how to handle this version */ + if (*(eb_ptr + (EB_HEADSIZE+EB_NTSD_VERSION)) > (uch)EB_NTSD_MAX_VER) + return PK_OK; + + ntsd_ucSize = makelong(eb_ptr + (EB_HEADSIZE+EB_UCSIZE_P)); + if (ntsd_ucSize > 0L && eb_len <= (EB_NTSD_L_LEN + EB_CMPRHEADLEN)) + return IZ_EF_TRUNC; /* no compressed data! */ + + /* allocate storage for uncompressed data */ + security_data = (uch *)malloc((extent)ntsd_ucSize); + if (security_data == (uch *)NULL) + return PK_MEM4; + + error = memextract(__G__ security_data, ntsd_ucSize, + (eb_ptr + (EB_HEADSIZE+EB_NTSD_L_LEN)), (ulg)(eb_len - EB_NTSD_L_LEN)); + + if (error == PK_OK) { + if (SecuritySet(path, VolumeCaps, security_data)) { + error = PK_COOL; + if (!uO.tflag && (uO.qflag < 2) && + (!(VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))) + Info(slide, 0, ((char *)slide, " (%ld bytes security)", + ntsd_ucSize)); + } + } + + free(security_data); + return error; +} + + + + +/********************************/ /* scan extra fields for something */ +/* Function EvalExtraFields() */ /* we happen to know */ +/********************************/ + +static int EvalExtraFields(__G__ path, ef_ptr, ef_len) + __GDEF + char *path; + uch *ef_ptr; + unsigned ef_len; +{ + int rc = PK_OK; + + if (!uO.X_flag) + return PK_OK; /* user said don't process ACLs; for now, no other + extra block types are handled here */ + + while (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)) { + /* discovered some extra field inconsistency! */ + Trace((stderr, + "EvalExtraFields: block length %u > rest ef_size %u\n", eb_len, + ef_len - EB_HEADSIZE)); + break; + } + + switch (eb_id) + { + /* process security descriptor extra data if: + Caller is WinNT AND + Target local/remote drive supports acls AND + Target file is not a directory (else we defer processing + until later) + */ + case EF_NTSD: + if (IsWinNT()) { + VOLUMECAPS VolumeCaps; + + /* provide useful input */ + VolumeCaps.dwFileAttributes = G.pInfo->file_attr; + VolumeCaps.bUsePrivileges = (uO.X_flag > 1); + + /* check target volume capabilities - just fall through + * and try if fail */ + if (GetVolumeCaps(G.rootpath, path, &VolumeCaps) && + !(VolumeCaps.dwFileSystemFlags & FS_PERSISTENT_ACLS)) + { + rc = PK_OK; + break; + } + rc = SetSD(__G__ path, &VolumeCaps, ef_ptr, eb_len); + } else + rc = PK_OK; + break; + +#if 0 + /* perhaps later we can add support for unzipping OS/2 EAs to NT */ + case EF_OS2: + rc = SetEAs(__G__ path, ef_ptr); + break; + + case EF_PKUNIX: + case EF_IZUNIX: + case EF_IZUNIX2: + case EF_TIME: + break; /* handled elsewhere */ +#else /* ! 0 */ +#ifdef DEBUG + case EF_AV: + case EF_OS2: + case EF_PKVMS: + case EF_PKW32: + case EF_PKUNIX: + case EF_IZVMS: + case EF_IZUNIX: + case EF_IZUNIX2: + case EF_TIME: + case EF_MAC3: + case EF_JLMAC: + case EF_ZIPIT: + case EF_VMCMS: + case EF_MVS: + case EF_ACL: + case EF_BEOS: + case EF_QDOS: + case EF_AOSVS: + case EF_SPARK: + case EF_MD5: + case EF_ASIUNIX: + break; /* shut up for other known e.f. blocks */ +#endif /* DEBUG */ +#endif /* ? 0 */ + + default: + Trace((stderr, + "EvalExtraFields: unknown extra field block, ID=%u\n", + eb_id)); + break; + } + + ef_ptr += (eb_len + EB_HEADSIZE); + ef_len -= (eb_len + EB_HEADSIZE); + + if (rc != PK_OK) + break; + } + + return rc; +} + + + + +#ifndef SFX + +/**************************/ +/* Function test_NTSD() */ /* returns PK_WARN when NTSD data is invalid */ +/**************************/ + +#ifdef __BORLANDC__ +/* Turn off warning about not using all parameters for this function only */ +#pragma argsused +#endif +int test_NTSD(__G__ eb, eb_size, eb_ucptr, eb_ucsize) + __GDEF + uch *eb; + unsigned eb_size; + uch *eb_ucptr; + ulg eb_ucsize; +{ + int r = PK_OK; + + if (!ValidateSecurity(eb_ucptr)) + r = PK_WARN; + return r; + +} /* end function test_NTSD() */ + +#endif /* !SFX */ +#endif /* NTSD_EAS */ + + + + +/**********************/ +/* Function IsWinNT() */ +/**********************/ + +int IsWinNT(void) /* returns TRUE if real NT, FALSE if Win95 or Win32s */ +{ + static DWORD g_PlatformId = 0xFFFFFFFF; /* saved platform indicator */ + + if (g_PlatformId == 0xFFFFFFFF) { + /* note: GetVersionEx() doesn't exist on WinNT 3.1 */ + if (GetVersion() < 0x80000000) + g_PlatformId = TRUE; + else + g_PlatformId = FALSE; + } + return (int)g_PlatformId; +} + + +/* DEBUG_TIME insertion: */ +#ifdef DEBUG_TIME +static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft); + +static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft) +{ + SYSTEMTIME w32tm; + int rval; + + rval = FileTimeToSystemTime(pft, &w32tm); + if (!rval) { + fprintf(hdo, "%s\n %08lX,%08lX (%s) -> Conversion failed !!!\n", + TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime), + (isloc ? "local" : "UTC")); + } else { + fprintf(hdo, "%s\n %08lx,%08lx -> %04u-%02u-%02u, %02u:%02u:%02u %s\n", + TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime), + w32tm.wYear, w32tm.wMonth, w32tm.wDay, w32tm.wHour, + w32tm.wMinute, w32tm.wSecond, (isloc ? "local" : "UTC")); + } + return rval; +} +#define FTTrace(x) show_NTFileTime x +#else +#define FTTrace(x) +#endif /* DEBUG_TIME */ +/* end of TIME_DEBUG insertion */ + +#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND) || \ + defined(TIMESTAMP)) + +#if ((defined(__GNUC__) || defined(ULONG_LONG_MAX)) && !defined(HAVE_INT64)) + typedef long long LLONG64; + typedef unsigned long long ULLNG64; +# define HAVE_INT64 +#endif +#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1100) && !defined(HAVE_INT64)) + typedef __int64 LLONG64; + typedef unsigned __int64 ULLNG64; +# define HAVE_INT64 +#endif +#if (defined(_MSC_VER) && (_MSC_VER >= 1100) && !defined(HAVE_INT64)) + typedef __int64 LLONG64; + typedef unsigned __int64 ULLNG64; +# define HAVE_INT64 +#endif + +/*****************************/ +/* Function utime2FileTime() */ /* convert Unix time_t format into the */ +/*****************************/ /* form used by SetFileTime() in NT/95 */ + +#define UNIX_TIME_ZERO_HI 0x019DB1DEUL +#define UNIX_TIME_ZERO_LO 0xD53E8000UL +#define NT_QUANTA_PER_UNIX 10000000L + +static void utime2FileTime(time_t ut, FILETIME *pft) +{ +#ifdef HAVE_INT64 + ULLNG64 NTtime; + + /* NT_QUANTA_PER_UNIX is small enough so that "ut * NT_QUANTA_PER_UNIX" + * cannot overflow in 64-bit signed calculation, regardless wether "ut" + * is signed or unsigned. */ + NTtime = ((LLONG64)ut * NT_QUANTA_PER_UNIX) + + ((ULLNG64)UNIX_TIME_ZERO_LO + ((ULLNG64)UNIX_TIME_ZERO_HI << 32)); + pft->dwLowDateTime = (DWORD)NTtime; + pft->dwHighDateTime = (DWORD)(NTtime >> 32); + +#else /* !HAVE_INT64 (64-bit integer arithmetics may not be supported) */ + unsigned int b1, b2, carry = 0; + unsigned long r0, r1, r2, r3; + long r4; /* signed, to catch environments with signed time_t */ + + b1 = ut & 0xFFFF; + b2 = (ut >> 16) & 0xFFFF; /* if ut is over 32 bits, too bad */ + r1 = b1 * (NT_QUANTA_PER_UNIX & 0xFFFF); + r2 = b1 * (NT_QUANTA_PER_UNIX >> 16); + r3 = b2 * (NT_QUANTA_PER_UNIX & 0xFFFF); + r4 = b2 * (NT_QUANTA_PER_UNIX >> 16); + r0 = (r1 + (r2 << 16)) & 0xFFFFFFFFL; + if (r0 < r1) + carry++; + r1 = r0; + r0 = (r0 + (r3 << 16)) & 0xFFFFFFFFL; + if (r0 < r1) + carry++; + pft->dwLowDateTime = r0 + UNIX_TIME_ZERO_LO; + if (pft->dwLowDateTime < r0) + carry++; + pft->dwHighDateTime = r4 + (r2 >> 16) + (r3 >> 16) + + UNIX_TIME_ZERO_HI + carry; +#endif /* ?HAVE_INT64 */ + +} /* end function utime2FileTime() */ + + + +/******************************/ +/* Function FStampIsLocTime() */ +/******************************/ + +static int FStampIsLocTime(__GPRO__ const char *path) +{ + return (NTQueryVolInfo(__G__ path) ? G.lastVolLocTim : FALSE); +} + +#endif /* USE_EF_UT_TIME || NT_TZBUG_WORKAROUND || TIMESTAMP */ + + + +#ifndef NT_TZBUG_WORKAROUND +# define UTIME_BOUNDCHECK_1(utimval) \ + if (fs_uses_loctime) { \ + utime_dosmin = dos_to_unix_time(DOSTIME_MINIMUM); \ + if ((ulg)utimval < (ulg)utime_dosmin) \ + utimval = utime_dosmin; \ + } +# define UTIME_BOUNDCHECK_N(utimval) \ + if (fs_uses_loctime && ((ulg)utimval < (ulg)utime_dosmin)) \ + utimval = utime_dosmin; +# define NT_TZBUG_PRECOMPENSATE(ut, pft) + +#else /* NT_TZBUG_WORKAROUND */ +# define UNIX_TIME_UMAX_HI 0x0236485EUL +# define UNIX_TIME_UMAX_LO 0xD4A5E980UL +# define UNIX_TIME_SMIN_HI 0x0151669EUL +# define UNIX_TIME_SMIN_LO 0xD53E8000UL +# define UNIX_TIME_SMAX_HI 0x01E9FD1EUL +# define UNIX_TIME_SMAX_LO 0xD4A5E980UL +# define UTIME_1980_JAN_01_00_00 315532800L +# define UTIME_BOUNDCHECK_1(utimval) +# define UTIME_BOUNDCHECK_N(utimval) +# define NT_TZBUG_PRECOMPENSATE(ut, pft) \ + if (fs_uses_loctime) NTtzbugWorkaround(ut, pft); + + /* nonzero if `y' is a leap year, else zero */ +# define leap(y) (((y)%4 == 0 && (y)%100 != 0) || (y)%400 == 0) + /* number of leap years from 1970 to `y' (not including `y' itself) */ +# define nleap(y) (((y)-1969)/4 - ((y)-1901)/100 + ((y)-1601)/400) + +extern ZCONST ush ydays[]; /* defined in fileio.c */ + +/*****************************/ +/* Function FileTime2utime() */ +/*****************************/ + +static int FileTime2utime(const FILETIME *pft, time_t *ut) +{ +#ifdef HAVE_INT64 + ULLNG64 NTtime; + + NTtime = ((ULLNG64)pft->dwLowDateTime + + ((ULLNG64)pft->dwHighDateTime << 32)); + + /* underflow and overflow handling */ +#ifdef CHECK_UTIME_SIGNED_UNSIGNED + if ((time_t)0x80000000L < (time_t)0L) + { + if (NTtime < ((ULLNG64)UNIX_TIME_SMIN_LO + + ((ULLNG64)UNIX_TIME_SMIN_HI << 32))) { + *ut = (time_t)LONG_MIN; + return FALSE; + } + if (NTtime > ((ULLNG64)UNIX_TIME_SMAX_LO + + ((ULLNG64)UNIX_TIME_SMAX_HI << 32))) { + *ut = (time_t)LONG_MAX; + return FALSE; + } + } + else +#endif /* CHECK_UTIME_SIGNED_UNSIGNED */ + { + if (NTtime < ((ULLNG64)UNIX_TIME_ZERO_LO + + ((ULLNG64)UNIX_TIME_ZERO_HI << 32))) { + *ut = (time_t)0; + return FALSE; + } + if (NTtime > ((ULLNG64)UNIX_TIME_UMAX_LO + + ((ULLNG64)UNIX_TIME_UMAX_HI << 32))) { + *ut = (time_t)ULONG_MAX; + return FALSE; + } + } + + NTtime -= ((ULLNG64)UNIX_TIME_ZERO_LO + + ((ULLNG64)UNIX_TIME_ZERO_HI << 32)); + *ut = (time_t)(NTtime / (unsigned long)NT_QUANTA_PER_UNIX); + return TRUE; +#else /* !HAVE_INT64 (64-bit integer arithmetics may not be supported) */ + time_t days; + SYSTEMTIME w32tm; + + /* underflow and overflow handling */ +#ifdef CHECK_UTIME_SIGNED_UNSIGNED + if ((time_t)0x80000000L < (time_t)0L) + { + if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) || + ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) && + (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) { + *ut = (time_t)LONG_MIN; + return FALSE; + if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) || + ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) && + (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) { + *ut = (time_t)LONG_MAX; + return FALSE; + } + } + else +#endif /* CHECK_UTIME_SIGNED_UNSIGNED */ + { + if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) || + ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) && + (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) { + *ut = (time_t)0; + return FALSE; + } + if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) || + ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) && + (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) { + *ut = (time_t)ULONG_MAX; + return FALSE; + } + } + + FileTimeToSystemTime(pft, &w32tm); + + /* set `days' to the number of days into the year */ + days = w32tm.wDay - 1 + ydays[w32tm.wMonth-1] + + (w32tm.wMonth > 2 && leap (w32tm.wYear)); + + /* now set `days' to the number of days since 1 Jan 1970 */ + days += 365 * (time_t)(w32tm.wYear - 1970) + + (time_t)(nleap(w32tm.wYear)); + + *ut = (time_t)(86400L * days + 3600L * (time_t)w32tm.wHour + + (time_t)(60 * w32tm.wMinute + w32tm.wSecond)); + return TRUE; +#endif /* ?HAVE_INT64 */ +} /* end function FileTime2utime() */ + + + +#ifdef W32_STAT_BANDAID +/*********************************/ +/* Function VFatFileTime2utime() */ +/*********************************/ + +static int VFatFileTime2utime(const FILETIME *pft, time_t *ut) +{ + FILETIME lft; +#ifndef HAVE_MKTIME + WORD wDOSDate, wDOSTime; +#else + SYSTEMTIME w32tm; + struct tm ltm; +#endif + + FileTimeToLocalFileTime(pft, &lft); + FTTrace((stdout, "VFatFT2utime, feed for mktime()", 1, &lft)); +#ifndef HAVE_MKTIME + /* This version of the FILETIME-to-UNIXTIME conversion function + * uses DOS-DATE-TIME format as intermediate stage. For modification + * and access times, this is no problem. But, the extra fine resolution + * of the VFAT-stored creation time gets lost. + */ + FileTimeToDosDateTime(&lft, &wDOSDate, &wDOSTime); + TTrace((stdout,"DosDateTime is %04u-%02u-%02u %02u:%02u:%02u\n", + (unsigned)((wDOSDate>>9)&0x7f)+1980,(unsigned)((wDOSDate>>5)&0x0f), + (unsigned)(wDOSDate&0x1f),(unsigned)((wDOSTime>>11)&0x1f), + (unsigned)((wDOSTime>>5)&0x3f),(unsigned)((wDOSTime<<1)&0x3e))); + *ut = dos_to_unix_time(((ulg)wDOSDate << 16) | (ulg)wDOSTime); + + /* a cheap error check: dos_to_unix_time() only returns an odd time + * when clipping at maximum time_t value. DOS_DATE_TIME values have + * a resolution of 2 seconds and are therefore even numbers. + */ + return (((*ut)&1) == (time_t)0); +#else /* HAVE_MKTIME */ + FileTimeToSystemTime(&lft, &w32tm); + /* underflow and overflow handling */ + /* TODO: The range checks are not accurate, the actual limits may + * be off by one daylight-saving-time shift (typically 1 hour), + * depending on the current state of "is_dst". + */ +#ifdef CHECK_UTIME_SIGNED_UNSIGNED + if ((time_t)0x80000000L < (time_t)0L) + { + if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) || + ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) && + (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) { + *ut = (time_t)LONG_MIN; + return FALSE; + if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) || + ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) && + (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) { + *ut = (time_t)LONG_MAX; + return FALSE; + } + } + else +#endif /* CHECK_UTIME_SIGNED_UNSIGNED */ + { + if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) || + ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) && + (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) { + *ut = (time_t)0; + return FALSE; + } + if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) || + ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) && + (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) { + *ut = (time_t)ULONG_MAX; + return FALSE; + } + } + ltm.tm_year = w32tm.wYear - 1900; + ltm.tm_mon = w32tm.wMonth - 1; + ltm.tm_mday = w32tm.wDay; + ltm.tm_hour = w32tm.wHour; + ltm.tm_min = w32tm.wMinute; + ltm.tm_sec = w32tm.wSecond; + ltm.tm_isdst = -1; /* let mktime determine if DST is in effect */ + *ut = mktime(<m); + + /* a cheap error check: mktime returns "(time_t)-1L" on conversion errors. + * Normally, we would have to apply a consistency check because "-1" + * could also be a valid time. But, it is quite unlikely to read back odd + * time numbers from file systems that store time stamps in DOS format. + * (The only known exception is creation time on VFAT partitions.) + */ + return (*ut != (time_t)-1L); +#endif /* ?HAVE_MKTIME */ + +} /* end function VFatFileTime2utime() */ +#endif /* W32_STAT_BANDAID */ + + + +/********************************/ +/* Function UTCtime2Localtime() */ /* borrowed from Zip's mkgmtime() */ +/********************************/ + +static time_t UTCtime2Localtime(time_t utctime) +{ + time_t utc = utctime; + struct tm *tm; + unsigned years, months, days, hours, minutes, seconds; + + +#ifdef __BORLANDC__ /* Borland C++ 5.x crashes when trying to reference tm */ + if (utc < UTIME_1980_JAN_01_00_00) + utc = UTIME_1980_JAN_01_00_00; +#endif + tm = localtime(&utc); + if (tm == (struct tm *)NULL) + /* localtime() did not accept given utc time value; as an emergency + exit, the unconverted utctime value is returned */ + return utctime; + + years = tm->tm_year + 1900; /* year - 1900 -> year */ + months = tm->tm_mon; /* 0..11 */ + days = tm->tm_mday - 1; /* 1..31 -> 0..30 */ + hours = tm->tm_hour; /* 0..23 */ + minutes = tm->tm_min; /* 0..59 */ + seconds = tm->tm_sec; /* 0..61 in ANSI C */ + + /* set `days' to the number of days into the year */ + days += ydays[months] + (months > 1 && leap(years)); + + /* now set `days' to the number of days since 1 Jan 1970 */ + days += 365 * (years - 1970) + nleap(years); + + return (time_t)(86400L * (ulg)days + 3600L * (ulg)hours + + (ulg)(60 * minutes + seconds)); + +} /* end function UTCtime2Localtime() */ + + + +/********************************/ +/* Function NTtzbugWorkaround() */ +/********************************/ + +static void NTtzbugWorkaround(time_t ut, FILETIME *pft) +{ + FILETIME C_RTL_locft, NTAPI_locft; + time_t ux_loctime = UTCtime2Localtime(ut); + + /* This routine is only used when the target file system stores time- + * stamps as local time in MSDOS format. Thus we make sure that the + * resulting timestamp is within the range of MSDOS date-time values. */ + if (ux_loctime < UTIME_1980_JAN_01_00_00) + ux_loctime = UTIME_1980_JAN_01_00_00; + + utime2FileTime(ux_loctime, &C_RTL_locft); + if (!FileTimeToLocalFileTime(pft, &NTAPI_locft)) + return; + else { + long time_shift_l, time_shift_h; + int carry = 0; + + time_shift_l = C_RTL_locft.dwLowDateTime - NTAPI_locft.dwLowDateTime; + if (C_RTL_locft.dwLowDateTime < NTAPI_locft.dwLowDateTime) + carry--; + time_shift_h = C_RTL_locft.dwHighDateTime - NTAPI_locft.dwHighDateTime; + pft->dwLowDateTime += time_shift_l; + if (pft->dwLowDateTime < (ulg)time_shift_l) + carry++; + pft->dwHighDateTime += time_shift_h + carry; + TTrace((stdout, "FileTime shift: %08lx:%08lx\n", + time_shift_h+carry,time_shift_l)); + } +} /* end function NTtzbugWorkaround() */ + +#endif /* ?NT_TZBUG_WORKAROUND */ + + + +/****************************/ /* Get the file time in a format that */ +/* Function getNTfiletime() */ /* can be used by SetFileTime() in NT */ +/****************************/ + +static int getNTfiletime(__G__ pModFT, pAccFT, pCreFT) + __GDEF + FILETIME *pModFT; + FILETIME *pAccFT; + FILETIME *pCreFT; +{ +#ifdef NT_TZBUG_WORKAROUND + time_t ux_modtime; +#else /* !NT_TZBUG_WORKAROUND */ + FILETIME locft; /* 64-bit value made up of two 32-bit [low & high] */ + WORD wDOSDate; /* for converting from DOS date to Windows NT */ + WORD wDOSTime; +#endif /* ?NT_TZBUG_WORKAROUND */ +#ifdef USE_EF_UT_TIME + unsigned eb_izux_flg; + iztimes z_utime; /* struct for Unix-style actime & modtime, + creatime */ +#endif +#if (defined(USE_EF_UT_TIME) && !defined(NT_TZBUG_WORKAROUND)) + time_t utime_dosmin; +# endif +#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND)) + int fs_uses_loctime = FStampIsLocTime(__G__ G.filename); +#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, "getNTfiletime: Unix e.f. modif. time = %lu\n", + z_utime.mtime)); + UTIME_BOUNDCHECK_1(z_utime.mtime) + utime2FileTime(z_utime.mtime, pModFT); + NT_TZBUG_PRECOMPENSATE(z_utime.mtime, pModFT) + if (eb_izux_flg & EB_UT_FL_ATIME) { + UTIME_BOUNDCHECK_N(z_utime.atime) + utime2FileTime(z_utime.atime, pAccFT); + NT_TZBUG_PRECOMPENSATE(z_utime.atime, pAccFT) + } + if (eb_izux_flg & EB_UT_FL_CTIME) { + UTIME_BOUNDCHECK_N(z_utime.ctime) + utime2FileTime(z_utime.ctime, pCreFT); + NT_TZBUG_PRECOMPENSATE(z_utime.ctime, pCreFT) + } + return (int)eb_izux_flg; + } +#endif /* USE_EF_UT_TIME */ +#ifdef NT_TZBUG_WORKAROUND + ux_modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); + utime2FileTime(ux_modtime, pModFT); + NT_TZBUG_PRECOMPENSATE(ux_modtime, pModFT) +#else /* !NT_TZBUG_WORKAROUND */ + + wDOSTime = (WORD)(G.lrec.last_mod_dos_datetime); + wDOSDate = (WORD)(G.lrec.last_mod_dos_datetime >> 16); + + /* The DosDateTimeToFileTime() function converts a DOS date/time + * into a 64-bit Windows NT file time */ + if (!DosDateTimeToFileTime(wDOSDate, wDOSTime, &locft)) + { + Info(slide, 0, ((char *)slide, "DosDateTime failed: %d\n", + (int)GetLastError())); + return 0; + } + if (!LocalFileTimeToFileTime(&locft, pModFT)) + { + Info(slide, 0, ((char *)slide, "LocalFileTime failed: %d\n", + (int)GetLastError())); + *pModFT = locft; + } +#endif /* ?NT_TZBUG_WORKAROUND */ + *pAccFT = *pModFT; + return (EB_UT_FL_MTIME | EB_UT_FL_ATIME); + +} /* end function getNTfiletime() */ + + + + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) + __GDEF +{ + FILETIME Modft; /* File time type defined in NT, `last modified' time */ + FILETIME Accft; /* NT file time type, `last access' time */ + FILETIME Creft; /* NT file time type, `file creation' time */ + HANDLE hFile; /* File handle defined in NT */ + int gotTime; +#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ + char *ansi_name = (char *)alloca(strlen(G.filename) + 1); + + INTERN_TO_ISO(G.filename, ansi_name); +# define Ansi_Fname ansi_name +#else +# define Ansi_Fname G.filename +#endif + + /* Close the file and then re-open it using the Win32 + * CreateFile call, so that the file can be created + * with GENERIC_WRITE access, otherwise the SetFileTime + * call will fail. */ + fclose(G.outfile); + + /* don't set the time stamp and attributes on standard output */ + if (uO.cflag) + return; + + gotTime = getNTfiletime(__G__ &Modft, &Accft, &Creft); + + /* open a handle to the file before processing extra fields; + we do this in case new security on file prevents us from updating + time stamps */ + hFile = CreateFile(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + /* sfield@microsoft.com: set attributes before time in case we decide to + support other filetime members later. This also allows us to apply + attributes before the security is changed, which may prevent this + from succeeding otherwise. Also, since most files don't have + any interesting attributes, only change them if something other than + FILE_ATTRIBUTE_ARCHIVE appears in the attributes. This works well + as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the + file anyway, when it's created new. */ + if((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) { + if (!SetFileAttributes(Ansi_Fname, G.pInfo->file_attr & 0x7F)) + Info(slide, 1, ((char *)slide, + "\nwarning (%d): could not set file attributes\n", + (int)GetLastError())); + } + +#ifdef NTSD_EAS + /* 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(TruncNTSD), + makeword(G.extra_field+2)-10, uO.qflag? "\n":"")); + } + } +#endif /* NTSD_EAS */ + + if ( hFile == INVALID_HANDLE_VALUE ) + Info(slide, 1, ((char *)slide, + "\nCreateFile error %d when trying set file time\n", + (int)GetLastError())); + else { + if (gotTime) { + FILETIME *pModft = (gotTime & EB_UT_FL_MTIME) ? &Modft : NULL; + FILETIME *pAccft = (gotTime & EB_UT_FL_ATIME) ? &Accft : NULL; + FILETIME *pCreft = (gotTime & EB_UT_FL_CTIME) ? &Creft : NULL; + + if (!SetFileTime(hFile, pCreft, pAccft, pModft)) + Info(slide, 0, ((char *)slide, "\nSetFileTime failed: %d\n", + (int)GetLastError())); + } + CloseHandle(hFile); + } + + return; + +#undef Ansi_Fname + +} /* end function close_outfile() */ + + + + +#ifdef TIMESTAMP + +/*************************/ +/* Function stamp_file() */ +/*************************/ + +int stamp_file(__GPRO__ ZCONST char *fname, time_t modtime) +{ + FILETIME Modft; /* File time type defined in NT, `last modified' time */ + HANDLE hFile; /* File handle defined in NT */ + int errstat = 0; /* return status: 0 == "OK", -1 == "Failure" */ +#ifndef NT_TZBUG_WORKAROUND + time_t utime_dosmin; /* internal variable for UTIME_BOUNDCHECK_1 */ +#endif + int fs_uses_loctime = FStampIsLocTime(__G__ fname); +#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ + char *ansi_name = (char *)alloca(strlen(fname) + 1); + + INTERN_TO_ISO(fname, ansi_name); +# define Ansi_Fname ansi_name +#else +# define Ansi_Fname fname +#endif + + /* open a handle to the file to prepare setting the mod-time stamp */ + hFile = CreateFile(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if ( hFile == INVALID_HANDLE_VALUE ) { + errstat = -1; + } else { + /* convert time_t modtime into WIN32 native 64bit format */ + UTIME_BOUNDCHECK_1(modtime) + utime2FileTime(modtime, &Modft); + NT_TZBUG_PRECOMPENSATE(modtime, &Modft) + /* set Access and Modification times of the file to modtime */ + if (!SetFileTime(hFile, NULL, &Modft, &Modft)) { + errstat = -1; + } + CloseHandle(hFile); + } + + return errstat; + +#undef Ansi_Fname +} /* end function stamp_file() */ + +#endif /* TIMESTAMP */ + + + + +/***********************/ +/* Function isfloppy() */ /* more precisely, is it removable? */ +/***********************/ + +static int isfloppy(int nDrive) /* 1 == A:, 2 == B:, etc. */ +{ + char rootPathName[4]; + + rootPathName[0] = (char)('A' + nDrive - 1); /* build the root path */ + rootPathName[1] = ':'; /* name, e.g. "A:/" */ + rootPathName[2] = '/'; + rootPathName[3] = '\0'; + + return (GetDriveType(rootPathName) == DRIVE_REMOVABLE); + +} /* end function isfloppy() */ + + + + +/*****************************/ +/* Function NTQueryVolInfo() */ +/*****************************/ + +/* + * Note: 8.3 limits on filenames apply only to old-style FAT filesystems. + * More recent versions of Windows (Windows NT 3.5 / Windows 4.0) + * can support long filenames (LFN) on FAT filesystems. Check the + * filesystem maximum component length field to detect LFN support. + */ + +static int NTQueryVolInfo(__GPRO__ const char *name) +{ + /* static char lastRootPath[4] = ""; */ + /* static int lastVolOldFAT; */ + /* static int lastVolLocTim; */ + char *tmp0; + char tmp1[MAX_PATH], tmp2[MAX_PATH]; + unsigned volSerNo, maxCompLen, fileSysFlags; +#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ + char *ansi_name = (char *)alloca(strlen(name) + 1); + + INTERN_TO_ISO(name, ansi_name); + name = ansi_name; +#endif + + if ((!strncmp(name, "//", 2) || !strncmp(name,"\\\\", 2)) && + (name[2] != '\0' && name[2] != '/' && name[2] != '\\')) { + /* GetFullPathname() and GetVolumeInformation() do not work + * on UNC names. For now, we return "error". + * **FIXME**: check if UNC name is mapped to a drive letter + * and use mapped drive for volume info query. + */ + return FALSE; + } + if (isalpha((uch)name[0]) && (name[1] == ':')) + tmp0 = (char *)name; + else + { + if (!GetFullPathName(name, MAX_PATH, tmp1, &tmp0)) + return FALSE; + tmp0 = &tmp1[0]; + } + if (strncmp(G.lastRootPath, tmp0, 2) != 0) { + /* For speed, we skip repeated queries for the same device */ + strncpy(G.lastRootPath, tmp0, 2); /* Build the root path name, */ + G.lastRootPath[2] = '/'; /* e.g. "A:/" */ + G.lastRootPath[3] = '\0'; + + if (!GetVolumeInformation((LPCTSTR)G.lastRootPath, + (LPTSTR)tmp1, (DWORD)MAX_PATH, + (LPDWORD)&volSerNo, (LPDWORD)&maxCompLen, + (LPDWORD)&fileSysFlags, (LPTSTR)tmp2, (DWORD)MAX_PATH)) { + G.lastRootPath[0] = '\0'; + return FALSE; + } + + /* LFNs are available if the component length is > 12 */ + G.lastVolOldFAT = (maxCompLen <= 12); +/* G.lastVolOldFAT = !strncmp(strupr(tmp2), "FAT", 3); old version */ + + /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in + * local time! + */ + G.lastVolLocTim = !strncmp(strupr(tmp2), "VFAT", 4) || + !strncmp(tmp2, "HPFS", 4) || + !strncmp(tmp2, "FAT", 3); + } + + return TRUE; + +} /* end function NTQueryVolInfo() */ + + + + +/*****************************/ +/* Function IsVolumeOldFAT() */ +/*****************************/ + +static int IsVolumeOldFAT(__GPRO__ const char *name) +{ + return (NTQueryVolInfo(__G__ name) ? G.lastVolOldFAT : FALSE); +} + + + + +#ifndef SFX + +/************************/ +/* Function do_wild() */ /* identical to OS/2 version */ +/************************/ + +char *do_wild(__G__ wildspec) + __GDEF + char *wildspec; /* only used first time on a given dir */ +{ + /* static zDIR *wild_dir = NULL; */ + /* static char *dirname, *wildname, matchname[FILNAMSIZ]; */ + /* static int firstcall=TRUE, 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 (!G.notfirstcall) { /* first call: must initialize everything */ + G.notfirstcall = TRUE; + + if (!iswild(wildspec)) { + strcpy(G.matchname, wildspec); + 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 = strrchr(wildspec, '/')) == NULL && + (G.wildname = strrchr(wildspec, ':')) == NULL) { + G.dirname = "."; + G.dirnamelen = 1; + G.have_dirname = FALSE; + 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")); + strcpy(G.matchname, wildspec); + 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; + } + Trace((stderr, "do_wild: dirname = [%s]\n", G.dirname)); + + if ((G.wild_dir = (zvoid *)Opendir(G.dirname)) != NULL) { + if (G.have_dirname) { + strcpy(G.matchname, G.dirname); + fnamestart = G.matchname + G.dirnamelen; + } else + fnamestart = G.matchname; + while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) { + Trace((stderr, "do_wild: Readdir returns %s\n", file->d_name)); + strcpy(fnamestart, file->d_name); + if (strrchr(fnamestart, '.') == (char *)NULL) + strcat(fnamestart, "."); + if (match(fnamestart, G.wildname, 1) && /* 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.matchname; + } + } + /* if we get to here directory is exhausted, so close it */ + Closedir((zDIR *)G.wild_dir); + G.wild_dir = NULL; + } + Trace((stderr, "do_wild: Opendir(%s) returns NULL\n", G.dirname)); + + /* return the raw wildspec in case that works (e.g., directory not + * searchable, but filespec was not wild and file is readable) */ + strcpy(G.matchname, wildspec); + return G.matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (G.wild_dir == NULL) { + G.notfirstcall = FALSE; /* 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. + */ + if (G.have_dirname) { + /* strcpy(G.matchname, G.dirname); */ + fnamestart = G.matchname + G.dirnamelen; + } else + fnamestart = G.matchname; + while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", file->d_name)); + strcpy(fnamestart, file->d_name); + if (strrchr(fnamestart, '.') == (char *)NULL) + strcat(fnamestart, "."); + if (match(fnamestart, G.wildname, 1)) { /* 1 == ignore case */ + Trace((stderr, "do_wild: match() succeeds\n")); + /* remove trailing dot */ + fnamestart += strlen(fnamestart) - 1; + if (*fnamestart == '.') + *fnamestart = '\0'; + return G.matchname; + } + } + + Closedir((zDIR *)G.wild_dir); /* at least one entry read; nothing left */ + G.wild_dir = NULL; + G.notfirstcall = FALSE; /* reset for new wildspec */ + if (G.have_dirname) + free(G.dirname); + return (char *)NULL; + +} /* end function do_wild() */ + +#endif /* !SFX */ + + + +/**********************/ +/* Function mapattr() */ +/**********************/ + +/* Identical to MS-DOS, OS/2 versions. However, NT has a lot of extra + * permission stuff, so this function should probably be extended in the + * future. */ + +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 & FILE_ATTRIBUTE_DIRECTORY ? + 0 : FILE_ATTRIBUTE_ARCHIVE)) & 0xff; + return 0; + +} /* end function mapattr() */ + + + + +/************************/ +/* Function mapname() */ +/************************/ + /* return 0 if no error, 1 if caution (filename */ +int mapname(__G__ renamed) /* truncated), 2 if warning (skip file because */ + __GDEF /* dir doesn't exist), 3 if error (skip file), */ + int renamed; /* or 10 if out of memory (skip file) */ +{ /* [also IZ_VOL_LABEL, IZ_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 error; + 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.created_dir = FALSE; /* not yet */ + G.renamed_fullpath = FALSE; + G.fnlen = strlen(G.filename); + + 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.renamed_fullpath = TRUE; + pathcomp[0] = '/'; /* copy the '/' and terminate */ + pathcomp[1] = '\0'; + ++cp; + } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') { + G.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 */ + cp = (char *)strrchr(G.filename, '/'); + if (cp == 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)) > 1) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = NULL; /* leave directory semi-colons alone */ + break; + + case ':': /* drive names not stored in zipfile, */ + case '<': /* so no colons allowed */ + case '>': /* no redirection symbols allowed either */ + case '|': /* no pipe signs allowed */ + case '"': /* no double quotes allowed */ + case '?': /* no wildcards allowed */ + case '*': + *pp++ = '_'; /* these rules apply equally to FAT and NTFS */ + break; + case ';': /* start of VMS version? */ + lastsemi = pp; /* remove VMS version later... */ + *pp++ = ';'; /* but keep semicolon for now */ + break; + + case ' ': /* keep spaces unless specifically */ + /* NT cannot create filenames with spaces on FAT volumes */ + if (uO.sflag || IsVolumeOldFAT(__G__ G.filename)) + *pp++ = '_'; + else + *pp++ = ' '; + break; + + default: + /* allow European characters in filenames: */ + if (isprint(workch) || workch >= 127) + *pp++ = (char)workch; + } /* end switch */ + } /* end while loop */ + + *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'; + } + +/*--------------------------------------------------------------------------- + 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.fnlen-1] == '/') { + checkdir(__G__ G.filename, GETPATH); + if (G.created_dir) { +#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ + char *ansi_name = (char *)alloca(strlen(G.filename) + 1); + + INTERN_TO_ISO(G.filename, ansi_name); +# define Ansi_Fname ansi_name +#else +# define Ansi_Fname G.filename +#endif + if (QCOND2) { + Info(slide, 0, ((char *)slide, " creating: %-22s\n", + FnFilter1(G.filename))); + } + + /* set file attributes: + The default for newly created directories is "DIR attribute + flags set", so there is no need to change attributes unless + one of the DOS style attribute flags is set. The readonly + attribute need not be masked, since it does not prevent + modifications in the new directory. */ + if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) { + if (!SetFileAttributes(Ansi_Fname, G.pInfo->file_attr & 0x7F)) + Info(slide, 1, ((char *)slide, + "\nwarning (%d): could not set file attributes for %s\n", + (int)GetLastError(), G.filename)); + } + +#ifdef NTSD_EAS + /* set extra fields, both stored-in-zipfile and .LONGNAME flavors */ + if (G.extra_field) { /* zipfile e.f. 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(TruncNTSD), + makeword(G.extra_field+2)-10, uO.qflag? "\n":"")); + } + } +#endif /* NTSD_EAS */ + return IZ_CREATED_DIR; /* set dir time (note trailing '/') */ + } + return 2; /* dir existed already; don't look for data to extract */ + } + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", + FnFilter1(G.filename))); + return 3; + } + + 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 */ + char drive[4]; +#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ + char *ansi_name = (char *)alloca(strlen(G.filename) + 1); + INTERN_TO_ISO(G.filename, ansi_name); +# define Ansi_Fname ansi_name +#else +# define Ansi_Fname G.filename +#endif + + /* Build a drive string, e.g. "b:" */ + drive[0] = (char)('a' + G.nLabelDrive - 1); + strcpy(drive + 1, ":\\"); + if (QCOND2) + Info(slide, 0, ((char *)slide, "labelling %s %-22s\n", drive, + FnFilter1(G.filename))); + if (!SetVolumeLabel(drive, Ansi_Fname)) { + Info(slide, 1, ((char *)slide, + "mapname: error setting volume label\n")); + return 3; + } + return 2; /* success: skip the "extraction" quietly */ +#undef Ansi_Fname + } + + return error; + +} /* end function mapname() */ + + + + +/**********************/ +/* Function map2fat() */ /* Not quite identical to OS/2 version */ +/**********************/ + +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 = 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 NTFS but not + * in FAT: to get here, must already have passed through mapname. + * Also must truncate path component to ensure 8.3 compliance. + */ + while ((workch = (uch)*ppc++) != 0) { + switch (workch) { + case '[': + case ']': + case '+': + case ',': + case ';': + 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 == NULL) { /* no dots: check for underscores... */ + char *plu = strrchr(pBegin, '_'); /* pointer to last underscore */ + + if (plu == NULL) { /* no dots, no underscores: truncate at 8 chars */ + *pEndFAT += 8; /* (or 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-blk */ + } 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 != 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 trun- */ + *q = '\0'; /* cate/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() */ + + + + +/***********************/ /* Borrowed from os2.c for UnZip 5.1. */ +/* Function checkdir() */ /* Difference: no EA stuff */ +/***********************/ /* HPFS stuff works on NTFS too */ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: 1 - (on APPEND_NAME) truncated filename + * 2 - path doesn't exist, not allowed to create + * 3 - path doesn't exist, tried to create and failed; or + * path exists and is not a directory, but is supposed to be + * 4 - path is too long + * 10 - can't allocate memory for filename buffers + */ +{ + /* 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') */ + +# 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 too_long=FALSE; + + Trace((stderr, "appending dir segment [%s]\n", pathcomp)); + while ((*G.endHPFS = *p++) != '\0') /* copy to HPFS filename */ + ++G.endHPFS; + if (!IsVolumeOldFAT(__G__ G.buildpathHPFS)) { + p = pathcomp; + while ((*G.endFAT = *p++) != '\0') /* copy to FAT filename, too */ + ++G.endFAT; + } else + map2fat(pathcomp, &G.endFAT); /* map into FAT fn, update endFAT */ + + /* GRR: could do better check, see if overrunning buffer as we go: + * check endHPFS-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.endHPFS-G.buildpathHPFS) > FILNAMSIZ-3) + too_long = TRUE; /* check if extracting dir? */ +#ifdef FIX_STAT_BUG + /* Borland C++ 5.0 does not handle a call to stat() well if the + * directory does not exist (it tends to crash in strange places.) + * This is apparently a problem only when compiling for GUI rather + * than console. The code below attempts to work around this problem. + */ + if (access(G.buildpathFAT, 0) != 0) { + if (!G.create_dirs) { /* told not to create (freshening) */ + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 2; /* path doesn't exist: nothing to do */ + } + if (too_long) { /* GRR: should allow FAT extraction w/o EAs */ + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", + FnFilter1(G.buildpathHPFS))); + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 4; /* no room for filenames: fatal */ + } + if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, + "checkdir error: cannot create %s\n\ + unable to process %s.\n", + FnFilter2(G.buildpathFAT), FnFilter1(G.filename))); + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 3; /* path didn't exist, tried to create, failed */ + } + G.created_dir = TRUE; + } +#endif /* FIX_STAT_BUG */ + if (SSTAT(G.buildpathFAT, &G.statbuf)) /* path doesn't exist */ + { + if (!G.create_dirs) { /* told not to create (freshening) */ + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 2; /* path doesn't exist: nothing to do */ + } + if (too_long) { /* GRR: should allow FAT extraction w/o EAs */ + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", + FnFilter1(G.buildpathHPFS))); + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 4; /* no room for filenames: fatal */ + } + if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, + "checkdir error: cannot create %s\n\ + unable to process %s.\n", + FnFilter2(G.buildpathFAT), FnFilter1(G.filename))); + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 3; /* path didn't exist, tried to create, failed */ + } + 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.buildpathFAT), FnFilter1(G.filename))); + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 3; /* path existed but wasn't dir */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", + FnFilter1(G.buildpathHPFS))); + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 4; /* no room for filenames: fatal */ + } + *G.endHPFS++ = '/'; + *G.endFAT++ = '/'; + *G.endHPFS = *G.endFAT = '\0'; + Trace((stderr, "buildpathHPFS now = [%s]\nbuildpathFAT now = [%s]\n", + FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT))); + return 0; + + } /* 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.buildpathFAT))); + Trace((stderr, "freeing HPFS path [%s]\n", + FnFilter1(G.buildpathHPFS))); + strcpy(pathcomp, G.buildpathFAT); + free(G.buildpathFAT); + free(G.buildpathHPFS); + G.buildpathHPFS = G.buildpathFAT = G.endHPFS = G.endFAT = NULL; + return 0; + } + +/*--------------------------------------------------------------------------- + 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 = 0; + + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); + while ((*G.endHPFS = *p++) != '\0') { /* copy to HPFS filename */ + ++G.endHPFS; + if ((G.endHPFS-G.buildpathHPFS) >= FILNAMSIZ) { + *--G.endHPFS = '\0'; + Info(slide, 1, ((char *)slide, + "checkdir warning: path too long; truncating\n \ + %s\n -> %s\n", + FnFilter1(G.filename), FnFilter2(G.buildpathHPFS))); + error = 1; /* filename truncated */ + } + } + + if ( G.pInfo->vollabel || !IsVolumeOldFAT(__G__ G.buildpathHPFS)) { + p = pathcomp; + while ((*G.endFAT = *p++) != '\0') /* copy to FAT filename, too */ + ++G.endFAT; + } else + map2fat(pathcomp, &G.endFAT); /* map into FAT fn, update endFAT */ + Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n", + FnFilter1(G.buildpathHPFS), FnFilter2(G.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 ")); + if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+1)) == NULL) + return 10; + if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+1)) == NULL) { + free(G.buildpathHPFS); + return 10; + } + 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.renamed_fullpath && pathcomp[1] == ':') + *G.buildpathHPFS = (char)ToLower(*pathcomp); + else if (!G.renamed_fullpath && G.rootlen > 1 && + G.rootpath[1] == ':') + *G.buildpathHPFS = (char)ToLower(*G.rootpath); + else { + char tmpN[MAX_PATH], *tmpP; + if (GetFullPathName(".", MAX_PATH, tmpN, &tmpP) > MAX_PATH) + { /* by definition of MAX_PATH we should never get here */ + Info(slide, 1, ((char *)slide, + "checkdir warning: current dir path too long\n")); + return 1; /* can't get drive letter */ + } + G.nLabelDrive = *tmpN - 'a' + 1; + *G.buildpathHPFS = (char)(G.nLabelDrive - 1 + 'a'); + } + G.nLabelDrive = *G.buildpathHPFS - 'a' + 1; /* save for mapname() */ + if (uO.volflag == 0 || *G.buildpathHPFS < 'a' /* no labels/bogus? */ + || (uO.volflag == 1 && !isfloppy(G.nLabelDrive))) { /* !fixed */ + free(G.buildpathHPFS); + free(G.buildpathFAT); + return IZ_VOL_LABEL; /* skipping with message */ + } + *G.buildpathHPFS = '\0'; + } else if (G.renamed_fullpath) /* pathcomp = valid data */ + strcpy(G.buildpathHPFS, pathcomp); + else if (G.rootlen > 0) + strcpy(G.buildpathHPFS, G.rootpath); + else + *G.buildpathHPFS = '\0'; + G.endHPFS = G.buildpathHPFS; + G.endFAT = G.buildpathFAT; + while ((*G.endFAT = *G.endHPFS) != '\0') { + ++G.endFAT; + ++G.endHPFS; + } + Trace((stderr, "[%s]\n", FnFilter1(G.buildpathHPFS))); + return 0; + } + +/*--------------------------------------------------------------------------- + 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 == NULL) { + G.rootlen = 0; + return 0; + } + if ((G.rootlen = strlen(pathcomp)) > 0) { + int had_trailing_pathsep=FALSE, has_drive=FALSE, xtra=2; + + if (isalpha((uch)pathcomp[0]) && pathcomp[1] == ':') + has_drive = TRUE; /* drive designator */ + if (pathcomp[G.rootlen-1] == '/' || pathcomp[G.rootlen-1] == '\\') { + pathcomp[--G.rootlen] = '\0'; + had_trailing_pathsep = TRUE; + } + if (has_drive && (G.rootlen == 2)) { + if (!had_trailing_pathsep) /* i.e., original wasn't "x:/" */ + xtra = 3; /* room for '.' + '/' + 0 at end of "x:" */ + } else if (G.rootlen > 0) { /* need not check "x:." and "x:/" */ + if (SSTAT(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) + { + /* path does not exist */ + if (!G.create_dirs /* || iswild(pathcomp) */ ) { + G.rootlen = 0; + return 2; /* treat as stored file */ + } + /* create directory (could add loop here to scan pathcomp + * and create more than one level, but 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, */ + return 3; /* failed: file exists, or need 2+ levels */ + } + } + } + if ((G.rootpath = (char *)malloc(G.rootlen+xtra)) == NULL) { + G.rootlen = 0; + return 10; + } + strcpy(G.rootpath, pathcomp); + if (xtra == 3) /* had just "x:", make "x:." */ + G.rootpath[G.rootlen++] = '.'; + G.rootpath[G.rootlen++] = '/'; + G.rootpath[G.rootlen] = '\0'; + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath))); + } + return 0; + } +#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 0; + } + + return 99; /* should never reach */ + +} /* end function checkdir() */ + + + + + +#ifndef SFX +#ifndef WINDLL + +/************************/ +/* Function version() */ +/************************/ + +void version(__G) + __GDEF +{ + int len; +#if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DJGPP__)) + char buf[80]; +#if (defined(_MSC_VER) && (_MSC_VER > 900)) + char buf2[80]; +#endif +#endif + + len = sprintf((char *)slide, CompiledWith, + +#if defined(_MSC_VER) /* MSC == VC++, but what about SDK compiler? */ + (sprintf(buf, "Microsoft C %d.%02d ", _MSC_VER/100, _MSC_VER%100), buf), +# if (_MSC_VER == 800) + "(Visual C++ v1.1)", +# elif (_MSC_VER == 850) + "(Windows NT v3.5 SDK)", +# elif (_MSC_VER == 900) + "(Visual C++ v2.x)", +# elif (_MSC_VER > 900) + (sprintf(buf2, "(Visual C++ %d.%d)", _MSC_VER/100 - 6, _MSC_VER%100/10), + buf2), +# else + "(bad version)", +# endif +#elif defined(__WATCOMC__) +# if (__WATCOMC__ % 10 > 0) + (sprintf(buf, "Watcom C/C++ %d.%02d", __WATCOMC__ / 100, + __WATCOMC__ % 100), buf), "", +# else + (sprintf(buf, "Watcom C/C++ %d.%d", __WATCOMC__ / 100, + (__WATCOMC__ % 100) / 10), buf), "", +# endif +#elif defined(__BORLANDC__) + "Borland C++", +# if (__BORLANDC__ < 0x0200) + " 1.0", +# elif (__BORLANDC__ == 0x0200) + " 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) /* __BCPLUSPLUS__ = 0x0340 */ + " 5.0", +# elif (__BORLANDC__ == 0x0520) /* __BCPLUSPLUS__ = 0x0520 */ + " 5.2 (C++ Builder)", /* GRR: assume this will stay sync'd? */ +# else + " later than 5.2", +# endif +#elif defined(__LCC__) + "LCC-Win32", "", +#elif defined(__GNUC__) +# if defined(__RSXNT__) +# if (defined(__DJGPP__) && !defined(__EMX__)) + (sprintf(buf, "rsxnt(djgpp v%d.%02d) / gcc ", + __DJGPP__, __DJGPP_MINOR__), buf), +# elif defined(__DJGPP__) + (sprintf(buf, "rsxnt(emx+djgpp v%d.%02d) / gcc ", + __DJGPP__, __DJGPP_MINOR__), buf), +# elif (defined(__GO32__) && !defined(__EMX__)) + "rsxnt(djgpp v1.x) / gcc ", +# elif defined(__GO32__) + "rsxnt(emx + djgpp v1.x) / gcc ", +# elif defined(__EMX__) + "rsxnt(emx)+gcc ", +# else + "rsxnt(unknown) / gcc ", +# endif +# elif defined(__CYGWIN32__) + "cygnus win32 / gcc ", +# elif defined(__MINGW32__) + "mingw32 / gcc ", +# else + "gcc ", +# endif + __VERSION__, +#else /* !_MSC_VER, !__WATCOMC__, !__BORLANDC__, !__LCC__, !__GNUC__ */ + "unknown compiler (SDK?)", "", +#endif /* ?compilers */ + + "Windows 95 / Windows NT", "\n(32-bit)", + +#ifdef __DATE__ + " on ", __DATE__ +#else + "", "" +#endif + ); + + (*G.message)((zvoid *)&G, slide, (ulg)len, 0); + + return; + +} /* end function version() */ + +#endif /* !WINDLL */ +#endif /* !SFX */ + + + +#ifdef W32_STAT_BANDAID + +/* All currently known variants of WIN32 operating systems (Windows 95/98, + * WinNT 3.x, 4.0, 5.0) have a nasty bug in the OS kernel concerning + * conversions between UTC and local time: In the time conversion functions + * of the Win32 API, the timezone offset (including seasonal daylight saving + * shift) between UTC and local time evaluation is erratically based on the + * current system time. The correct evaluation must determine the offset + * value as it {was/is/will be} for the actual time to be converted. + * + * Some versions of MS C runtime lib's stat() returns utc time-stamps so + * that localtime(timestamp) corresponds to the (potentially false) local + * time shown by the OS' system programs (Explorer, command shell dir, etc.) + * The RSXNT port follows the same strategy, but fails to recognize the + * access-time attribute. + * + * For the NTFS file system (and other filesystems that store time-stamps + * as UTC values), this results in st_mtime (, st_{c|a}time) fields which + * are not stable but vary according to the seasonal change of "daylight + * saving time in effect / not in effect". + * + * Other C runtime libs (CygWin, or the CRT DLLs supplied with Win95/NT + * return the unix-time equivalent of the UTC FILETIME values as got back + * from the Win32 API call. This time, return values from NTFS are correct + * whereas utimes from files on (V)FAT volumes vary according to the DST + * switches. + * + * To achieve timestamp consistency of UTC (UT extra field) values in + * Zip archives, the Info-ZIP programs require work-around code for + * proper time handling in stat() (and other time handling routines). + */ +/* stat() functions under Windows95 tend to fail for root directories. * + * Watcom and Borland, at least, are affected by this bug. Watcom made * + * a partial fix for 11.0 but still missed some cases. This substitute * + * detects the case and fills in reasonable values. Otherwise we get * + * effects like failure to extract to a root dir because it's not found. */ + +int zstat_win32(__W32STAT_GLOBALS__ const char *path, struct stat *buf) +{ + if (!stat(path, buf)) + { +#ifdef NT_TZBUG_WORKAROUND + /* stat was successful, now redo the time-stamp fetches */ + int fs_uses_loctime = FStampIsLocTime(__G__ path); + HANDLE h; + FILETIME Modft, Accft, Creft; +#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ + char *ansi_path = (char *)alloca(strlen(path) + 1); + + INTERN_TO_ISO(path, ansi_path); +# define Ansi_Path ansi_path +#else +# define Ansi_Path path +#endif + + TTrace((stdout, "stat(%s) finds modtime %08lx\n", path, buf->st_mtime)); + h = CreateFile(Ansi_Path, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h != INVALID_HANDLE_VALUE) { + BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft); + CloseHandle(h); + + if (ftOK) { + FTTrace((stdout, "GetFileTime returned Modft", 0, &Modft)); + FTTrace((stdout, "GetFileTime returned Creft", 0, &Creft)); + if (!fs_uses_loctime) { + /* On a filesystem that stores UTC timestamps, we refill + * the time fields of the struct stat buffer by directly + * using the UTC values as returned by the Win32 + * GetFileTime() API call. + */ + FileTime2utime(&Modft, &(buf->st_mtime)); + if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0) + FileTime2utime(&Accft, &(buf->st_atime)); + else + buf->st_atime = buf->st_mtime; + if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0) + FileTime2utime(&Creft, &(buf->st_ctime)); + else + buf->st_ctime = buf->st_mtime; + TTrace((stdout,"NTFS, recalculated modtime %08lx\n", + buf->st_mtime)); + } else { + /* On VFAT and FAT-like filesystems, the FILETIME values + * are converted back to the stable local time before + * converting them to UTC unix time-stamps. + */ + VFatFileTime2utime(&Modft, &(buf->st_mtime)); + if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0) + VFatFileTime2utime(&Accft, &(buf->st_atime)); + else + buf->st_atime = buf->st_mtime; + if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0) + VFatFileTime2utime(&Creft, &(buf->st_ctime)); + else + buf->st_ctime = buf->st_mtime; + TTrace((stdout, "VFAT, recalculated modtime %08lx\n", + buf->st_mtime)); + } + } + } +# undef Ansi_Path +#endif /* NT_TZBUG_WORKAROUND */ + return 0; + } +#ifdef W32_STATROOT_FIX + else + { + DWORD flags; +#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ + char *ansi_path = (char *)alloca(strlen(path) + 1); + + INTERN_TO_ISO(path, ansi_path); +# define Ansi_Path ansi_path +#else +# define Ansi_Path path +#endif + + flags = GetFileAttributes(Ansi_Path); + if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) { + Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n", + path)); + memset(buf, 0, sizeof(struct stat)); + buf->st_atime = buf->st_ctime = buf->st_mtime = + dos_to_unix_time(DOSTIME_MINIMUM); /* 1-1-80 */ + buf->st_mode = S_IFDIR | S_IREAD | + ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE); + return 0; + } /* assumes: stat() won't fail on non-dirs without good reason */ +# undef Ansi_Path + } +#endif /* W32_STATROOT_FIX */ + return -1; +} + +#endif /* W32_STAT_BANDAID */ + +#endif /* !FUNZIP */ + + + +#ifndef WINDLL +/* This replacement getch() function was originally created for Watcom C + * and then additionally used with CYGWIN. Since UnZip 5.4, all other Win32 + * ports apply this replacement rather that their supplied getch() (or + * alike) function. There are problems with unabsorbed LF characters left + * over in the keyboard buffer under Win95 (and 98) when ENTER was pressed. + * (Under Win95, ENTER returns two(!!) characters: CR-LF.) This problem + * does not appear when run on a WinNT console prompt! + */ + +/* Watcom 10.6's getch() does not handle Alt+. */ +/* Note that if PASSWD_FROM_STDIN is defined, the file containing */ +/* the password must have a carriage return after the word, not a */ +/* Unix-style newline (linefeed only). This discards linefeeds. */ + +int getch_win32(void) +{ + HANDLE stin; + DWORD rc; + unsigned char buf[2]; + int ret = -1; + DWORD odemode = ~(DWORD)0; + +# ifdef PASSWD_FROM_STDIN + stin = GetStdHandle(STD_INPUT_HANDLE); +# else + stin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (stin == INVALID_HANDLE_VALUE) + return -1; +# endif + if (GetConsoleMode(stin, &odemode)) + SetConsoleMode(stin, ENABLE_PROCESSED_INPUT); /* raw except ^C noticed */ + if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1) + ret = buf[0]; + /* when the user hits return we get CR LF. We discard the LF, not the CR, + * because when we call this for the first time after a previous input + * such as the one for "replace foo? [y]es, ..." the LF may still be in + * the input stream before whatever the user types at our prompt. */ + if (ret == '\n') + if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1) + ret = buf[0]; + if (odemode != ~(DWORD)0) + SetConsoleMode(stin, odemode); +# ifndef PASSWD_FROM_STDIN + CloseHandle(stin); +# endif + return ret; +} +#endif /* !WINDLL */ diff --git a/utils/Install/packzip/zipinfo.c b/utils/Install/packzip/zipinfo.c new file mode 100644 index 0000000000..c244c1e92f --- /dev/null +++ b/utils/Install/packzip/zipinfo.c @@ -0,0 +1,1912 @@ +/*--------------------------------------------------------------------------- + + zipinfo.c Greg Roelofs et al. + + This file contains all of the ZipInfo-specific listing routines for UnZip. + + Contains: zi_opts() + zi_end_central() + zipinfo() + zi_long() + zi_short() + zi_time() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" + + +#ifndef NO_ZIPINFO /* strings use up too much space in small-memory systems */ + +/* Define OS-specific attributes for use on ALL platforms--the S_xxxx + * versions of these are defined differently (or not defined) by different + * compilers and operating systems. */ + +#define UNX_IFMT 0170000 /* Unix file type mask */ +#define UNX_IFDIR 0040000 /* Unix directory */ +#define UNX_IFREG 0100000 /* Unix regular file */ +#define UNX_IFSOCK 0140000 /* Unix socket (BSD, not SysV or Amiga) */ +#define UNX_IFLNK 0120000 /* Unix symbolic link (not SysV, Amiga) */ +#define UNX_IFBLK 0060000 /* Unix block special (not Amiga) */ +#define UNX_IFCHR 0020000 /* Unix character special (not Amiga) */ +#define UNX_IFIFO 0010000 /* Unix fifo (BCC, not MSC or Amiga) */ +#define UNX_ISUID 04000 /* Unix set user id on execution */ +#define UNX_ISGID 02000 /* Unix set group id on execution */ +#define UNX_ISVTX 01000 /* Unix directory permissions control */ +#define UNX_ENFMT UNX_ISGID /* Unix record locking enforcement flag */ +#define UNX_IRWXU 00700 /* Unix read, write, execute: owner */ +#define UNX_IRUSR 00400 /* Unix read permission: owner */ +#define UNX_IWUSR 00200 /* Unix write permission: owner */ +#define UNX_IXUSR 00100 /* Unix execute permission: owner */ +#define UNX_IRWXG 00070 /* Unix read, write, execute: group */ +#define UNX_IRGRP 00040 /* Unix read permission: group */ +#define UNX_IWGRP 00020 /* Unix write permission: group */ +#define UNX_IXGRP 00010 /* Unix execute permission: group */ +#define UNX_IRWXO 00007 /* Unix read, write, execute: other */ +#define UNX_IROTH 00004 /* Unix read permission: other */ +#define UNX_IWOTH 00002 /* Unix write permission: other */ +#define UNX_IXOTH 00001 /* Unix execute permission: other */ + +#define VMS_IRUSR UNX_IRUSR /* VMS read/owner */ +#define VMS_IWUSR UNX_IWUSR /* VMS write/owner */ +#define VMS_IXUSR UNX_IXUSR /* VMS execute/owner */ +#define VMS_IRGRP UNX_IRGRP /* VMS read/group */ +#define VMS_IWGRP UNX_IWGRP /* VMS write/group */ +#define VMS_IXGRP UNX_IXGRP /* VMS execute/group */ +#define VMS_IROTH UNX_IROTH /* VMS read/other */ +#define VMS_IWOTH UNX_IWOTH /* VMS write/other */ +#define VMS_IXOTH UNX_IXOTH /* VMS execute/other */ + +#define AMI_IFMT 06000 /* Amiga file type mask */ +#define AMI_IFDIR 04000 /* Amiga directory */ +#define AMI_IFREG 02000 /* Amiga regular file */ +#define AMI_IHIDDEN 00200 /* to be supported in AmigaDOS 3.x */ +#define AMI_ISCRIPT 00100 /* executable script (text command file) */ +#define AMI_IPURE 00040 /* allow loading into resident memory */ +#define AMI_IARCHIVE 00020 /* not modified since bit was last set */ +#define AMI_IREAD 00010 /* can be opened for reading */ +#define AMI_IWRITE 00004 /* can be opened for writing */ +#define AMI_IEXECUTE 00002 /* executable image, a loadable runfile */ +#define AMI_IDELETE 00001 /* can be deleted */ + +#define LFLAG 3 /* short "ls -l" type listing */ + +static int zi_long OF((__GPRO__ ulg *pEndprev)); +static int zi_short OF((__GPRO)); +static void zi_showMacTypeCreator + OF((__GPRO__ uch *ebfield)); +static char *zi_time OF((__GPRO__ ZCONST ulg *datetimez, + ZCONST time_t *modtimez, char *d_t_str)); + + +/**********************************************/ +/* Strings used in zipinfo.c (ZipInfo half) */ +/**********************************************/ + +static char nullStr[] = ""; + +static ZCONST char Far LongHeader[] = "Archive: %s %ld bytes %d file%s\n"; +static ZCONST char Far ShortHeader[] = "Archive: %s %ld %d\n"; +static ZCONST char Far EndCentDirRec[] = "\nEnd-of-central-directory record:\n"; +static ZCONST char Far LineSeparators[] = "-------------------------------\n\n"; +static ZCONST char Far ActOffsetCentDir[] = "\ + Actual offset of end-of-central-dir record: %9ld (%.8lXh)\n\ + Expected offset of end-of-central-dir record: %9ld (%.8lXh)\n\ + (based on the length of the central directory and its expected offset)\n\n"; +static ZCONST char Far SinglePartArchive1[] = "\ + This zipfile constitutes the sole disk of a single-part archive; its\n\ + central directory contains %u %s. The central directory is %lu\n\ + (%.8lXh) bytes long, and its (expected) offset in bytes from the\n"; +static ZCONST char Far SinglePartArchive2[] = "\ + beginning of the zipfile is %lu (%.8lXh).\n\n"; +static ZCONST char Far MultiPartArchive1[] = "\ + This zipfile constitutes disk %u of a multi-part archive. The central\n\ + directory starts on disk %u; %u of its entries %s contained within\n"; +static ZCONST char Far MultiPartArchive2[] = "\ + this zipfile, out of a total of %u %s. The entire central\n\ + directory is %lu (%.8lXh) bytes long, and its offset in bytes from\n"; +static ZCONST char Far MultiPartArchive3[] = "\ + the beginning of the zipfile in which it begins is %lu (%.8lXh).\n\n"; +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\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"; +static ZCONST char Far ZipfileCommTruncMsg[] = + "\ncaution: zipfile comment truncated\n"; + +static ZCONST char Far CentralDirEntry[] = + "\nCentral directory entry #%d:\n---------------------------\n\n"; +static ZCONST char Far ZipfileStats[] = + "%d file%s, %lu bytes uncompressed, %lu bytes compressed: %s%d.%d%%\n"; + +/* zi_long() strings */ +static ZCONST char Far OS_FAT[] = "MS-DOS, OS/2 or NT FAT"; +static ZCONST char Far OS_Amiga[] = "Amiga"; +static ZCONST char Far OS_VMS[] = "VMS"; +static ZCONST char Far OS_Unix[] = "Unix"; +static ZCONST char Far OS_VMCMS[] = "VM/CMS"; +static ZCONST char Far OS_AtariST[] = "Atari ST"; +static ZCONST char Far OS_HPFS[] = "OS/2 or NT HPFS"; +static ZCONST char Far OS_Macintosh[] = "Macintosh HFS"; +static ZCONST char Far OS_ZSystem[] = "Z-System"; +static ZCONST char Far OS_CPM[] = "CP/M"; +static ZCONST char Far OS_TOPS20[] = "TOPS-20"; +static ZCONST char Far OS_NTFS[] = "NTFS"; +static ZCONST char Far OS_QDOS[] = "SMS/QDOS"; +static ZCONST char Far OS_Acorn[] = "Acorn RISC OS"; +static ZCONST char Far OS_MVS[] = "MVS"; +static ZCONST char Far OS_VFAT[] = "Win32 VFAT"; +static ZCONST char Far OS_BeOS[] = "BeOS"; +static ZCONST char Far OS_Tandem[] = "Tandem NSK"; + +static ZCONST char Far MthdNone[] = "none (stored)"; +static ZCONST char Far MthdShrunk[] = "shrunk"; +static ZCONST char Far MthdRedF1[] = "reduced (factor 1)"; +static ZCONST char Far MthdRedF2[] = "reduced (factor 2)"; +static ZCONST char Far MthdRedF3[] = "reduced (factor 3)"; +static ZCONST char Far MthdRedF4[] = "reduced (factor 4)"; +static ZCONST char Far MthdImplode[] = "imploded"; +static ZCONST char Far MthdToken[] = "tokenized"; +static ZCONST char Far MthdDeflate[] = "deflated"; +static ZCONST char Far MthdEnDeflate[] = "deflated (enhanced)"; +static ZCONST char Far MthdDCLImplode[] = "imploded (PK DCL)"; + +static ZCONST char Far DeflNorm[] = "normal"; +static ZCONST char Far DeflMax[] = "maximum"; +static ZCONST char Far DeflFast[] = "fast"; +static ZCONST char Far DeflSFast[] = "superfast"; + +static ZCONST char Far ExtraBytesPreceding[] = + " There are an extra %ld bytes preceding this file.\n\n"; + +static ZCONST char Far UnknownNo[] = "unknown (%d)"; + +static ZCONST char Far LocalHeaderOffset[] = + "\n offset of local header from start of archive: %lu (%.8lXh) bytes\n"; +static ZCONST char Far HostOS[] = + " file system or operating system of origin: %s\n"; +static ZCONST char Far EncodeSWVer[] = + " version of encoding software: %d.%d\n"; +static ZCONST char Far MinOSCompReq[] = + " minimum file system compatibility required: %s\n"; +static ZCONST char Far MinSWVerReq[] = + " minimum software version required to extract: %d.%d\n"; +static ZCONST char Far CompressMethod[] = + " compression method: %s\n"; +static ZCONST char Far SlideWindowSizeImplode[] = + " size of sliding dictionary (implosion): %cK\n"; +static ZCONST char Far ShannonFanoTrees[] = + " number of Shannon-Fano trees (implosion): %c\n"; +static ZCONST char Far CompressSubtype[] = + " compression sub-type (deflation): %s\n"; +static ZCONST char Far FileSecurity[] = + " file security status: %sencrypted\n"; +static ZCONST char Far ExtendedLocalHdr[] = + " extended local header: %s\n"; +static ZCONST char Far FileModDate[] = + " file last modified on (DOS date/time): %s\n"; +#ifdef USE_EF_UT_TIME + static ZCONST char Far UT_FileModDate[] = + " file last modified on (UT extra field modtime): %s %s\n"; + static ZCONST char Far LocalTime[] = "local"; +#ifndef NO_GMTIME + static ZCONST char Far GMTime[] = "UTC"; +#endif +#endif /* USE_EF_UT_TIME */ +static ZCONST char Far CRC32Value[] = + " 32-bit CRC value (hex): %.8lx\n"; +static ZCONST char Far CompressedFileSize[] = + " compressed size: %lu bytes\n"; +static ZCONST char Far UncompressedFileSize[] = + " uncompressed size: %lu bytes\n"; +static ZCONST char Far FilenameLength[] = + " length of filename: %u characters\n"; +static ZCONST char Far ExtraFieldLength[] = + " length of extra field: %u bytes\n"; +static ZCONST char Far FileCommentLength[] = + " length of file comment: %u characters\n"; +static ZCONST char Far FileDiskNum[] = + " disk number on which file begins: disk %u\n"; +static ZCONST char Far ApparentFileType[] = + " apparent file type: %s\n"; +static ZCONST char Far VMSFileAttributes[] = + " VMS file attributes (%06o octal): %s\n"; +static ZCONST char Far AmigaFileAttributes[] = + " Amiga file attributes (%06o octal): %s\n"; +static ZCONST char Far UnixFileAttributes[] = + " Unix file attributes (%06o octal): %s\n"; +static ZCONST char Far NonMSDOSFileAttributes[] = + " non-MSDOS external file attributes: %06lX hex\n"; +static ZCONST char Far MSDOSFileAttributes[] = + " MS-DOS file attributes (%02X hex): none\n"; +static ZCONST char Far MSDOSFileAttributesRO[] = + " MS-DOS file attributes (%02X hex): read-only\n"; +static ZCONST char Far MSDOSFileAttributesAlpha[] = + " MS-DOS file attributes (%02X hex): %s%s%s%s%s%s\n"; + + +static ZCONST char Far ExtraFieldTrunc[] = "\n\ + error: EF data block (type 0x%04x) size %u exceeds remaining extra field\n\ + space %u; block length has been truncated.\n"; +static ZCONST char Far ExtraFields[] = "\n\ + The central-directory extra field contains:"; +static ZCONST char Far ExtraFieldType[] = "\n\ + - A subfield with ID 0x%04x (%s) and %u data bytes"; +static ZCONST char Far efAV[] = "PKWARE AV"; +static ZCONST char Far efOS2[] = "OS/2"; +static ZCONST char Far efPKVMS[] = "PKWARE VMS"; +static ZCONST char Far efPKWin32[] = "PKWARE Win32"; +static ZCONST char Far efPKUnix[] = "PKWARE Unix"; +static ZCONST char Far efIZVMS[] = "Info-ZIP VMS"; +static ZCONST char Far efIZUnix[] = "old Info-ZIP Unix/OS2/NT"; +static ZCONST char Far efIZUnix2[] = "Unix UID/GID"; +static ZCONST char Far efTime[] = "universal time"; +static ZCONST char Far efJLMac[] = "old Info-ZIP Macintosh"; +static ZCONST char Far efMac3[] = "new Info-ZIP Macintosh"; +static ZCONST char Far efZipIt[] = "ZipIt Macintosh"; +static ZCONST char Far efZipIt2[] = "ZipIt Macintosh (short)"; +static ZCONST char Far efVMCMS[] = "VM/CMS"; +static ZCONST char Far efMVS[] = "MVS"; +static ZCONST char Far efACL[] = "OS/2 ACL"; +static ZCONST char Far efNTSD[] = "Security Descriptor"; +static ZCONST char Far efBeOS[] = "BeOS"; +static ZCONST char Far efQDOS[] = "SMS/QDOS"; +static ZCONST char Far efAOSVS[] = "AOS/VS"; +static ZCONST char Far efSpark[] = "Acorn SparkFS"; +static ZCONST char Far efMD5[] = "Fred Kantor MD5"; +static ZCONST char Far efASiUnix[] = "ASi Unix"; +static ZCONST char Far efUnknown[] = "unknown"; + +static ZCONST char Far OS2EAs[] = ".\n\ + The local extra field has %lu bytes of OS/2 extended attributes.\n\ + (May not match OS/2 \"dir\" amount due to storage method)"; +static ZCONST char Far izVMSdata[] = ". The extra\n\ + field is %s and has %lu bytes of VMS %s information%s"; +static ZCONST char Far izVMSstored[] = "stored"; +static ZCONST char Far izVMSrleenc[] = "run-length encoded"; +static ZCONST char Far izVMSdeflat[] = "deflated"; +static ZCONST char Far izVMScunknw[] = "compressed(?)"; +static ZCONST char Far *izVMScomp[4] = + {izVMSstored, izVMSrleenc, izVMSdeflat, izVMScunknw}; +static ZCONST char Far ACLdata[] = ".\n\ + The local extra field has %lu bytes of access control list information"; +static ZCONST char Far NTSDData[] = ".\n\ + The local extra field has %lu bytes of NT security descriptor data"; +static ZCONST char Far UTdata[] = ".\n\ + The local extra field has UTC/GMT %s time%s"; +static ZCONST char Far UTmodification[] = "modification"; +static ZCONST char Far UTaccess[] = "access"; +static ZCONST char Far UTcreation[] = "creation"; +static ZCONST char Far ZipItFname[] = ".\n\ + The Mac long filename is %s.\n"; +static ZCONST char Far Mac3data[] = ".\n\ + The local extra field has %lu bytes of %scompressed Macintosh\n\ + finder attributes"; + /* MacOSdata[] is used by EF_MAC3, EF_ZIPIT, EF_ZIPIT2 and EF_JLEE e. f. */ +static ZCONST char Far MacOSdata[] = ".\n\ + The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'"; +static ZCONST char Far MacOSdata1[] = ".\n\ + The associated file has type code `0x%lx' and creator code `0x%lx'"; +static ZCONST char Far MacOSJLEEflags[] = "\n File is marked as %s"; +static ZCONST char Far MacOS_RF[] = "Resource-fork"; +static ZCONST char Far MacOS_DF[] = "Data-fork"; +static ZCONST char Far MacOSMAC3flags[] = ".\n\ + File is marked as %s, File Dates are in %d Bit"; +static ZCONST char Far BeOSdata[] = ".\n\ + The local extra field has %lu bytes of %scompressed BeOS file attributes"; + /* The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'" */ +static ZCONST char Far QDOSdata[] = ".\n\ + The QDOS extra field subtype is `%c%c%c%c'"; +static ZCONST char Far AOSVSdata[] = ".\n\ + The AOS/VS extra field revision is %d.%d"; +static ZCONST char Far MD5data[] = ".\n\ + The 128-bit MD5 signature is %s"; +#ifdef CMS_MVS + static ZCONST char Far VmMvsExtraField[] = ".\n\ + The stored file open mode (FLDATA TYPE) is \"%s\""; + static ZCONST char Far VmMvsInvalid[] = "[invalid]"; +#endif /* CMS_MVS */ + +static ZCONST char Far First20[] = ". The first\n 20 are: "; +static ZCONST char Far ColonIndent[] = ":\n "; +static ZCONST char Far efFormat[] = " %02x"; + +static ZCONST char Far lExtraFieldType[] = "\n\ + There %s a local extra field with ID 0x%04x (%s) and\n\ + %u data bytes (%s).\n"; +static ZCONST char Far efIZuid[] = + "GMT modification/access times and Unix UID/GID"; +static ZCONST char Far efIZnouid[] = "GMT modification/access times only"; + + +static ZCONST char Far NoFileComment[] = "\n There is no file comment.\n"; +static ZCONST char Far FileCommBegin[] = "\n\ +------------------------- file comment begins ----------------------------\n"; +static ZCONST char Far FileCommEnd[] = "\ +-------------------------- file comment ends -----------------------------\n"; + +/* zi_time() strings */ +static ZCONST char Far BogusFmt[] = "%03d"; +static ZCONST char Far DMYHMTime[] = "%2u-%s-%02u %02u:%02u"; +static ZCONST char Far YMDHMSTime[] = "%u %s %u %02u:%02u:%02u"; +static ZCONST char Far DecimalTime[] = "%04u%02u%02u.%02u%02u%02u"; +static ZCONST char Far YMDHMSTimeError[] = "???? ??? ?? ??:??:??"; + + + + + +#ifndef WINDLL + +/************************/ +/* Function zi_opts() */ +/************************/ + +int zi_opts(__G__ pargc, pargv) + int *pargc; + char ***pargv; + __GDEF +{ + char **argv, *s; + int argc, c, error=FALSE, negative=0; + 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; + + +#ifdef MACOS + uO.lflag = LFLAG; /* reset default on each call */ +#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; + case '1': /* shortest listing: JUST filenames */ + if (negative) + uO.lflag = -2, negative = 0; + else + uO.lflag = 1; + break; + case '2': /* just filenames, plus headers if specified */ + if (negative) + uO.lflag = -2, negative = 0; + else + uO.lflag = 2; + 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; +#endif /* !CMS_MVS */ + case 'h': /* header line */ + if (negative) + hflag_2 = hflag_slmv = FALSE, negative = 0; + else { + hflag_2 = hflag_slmv = explicit_h = TRUE; + if (uO.lflag == -1) + uO.lflag = 0; + } + break; + case 'l': /* longer form of "ls -l" type listing */ + if (negative) + uO.lflag = -2, negative = 0; + else + uO.lflag = 5; + break; + case 'm': /* medium form of "ls -l" type listing */ + if (negative) + uO.lflag = -2, negative = 0; + else + uO.lflag = 4; + break; +#ifdef MORE + case 'M': /* send output through built-in "more" */ + if (negative) + G.M_flag = FALSE, negative = 0; + else + G.M_flag = TRUE; + break; +#endif + case 's': /* default: shorter "ls -l" type listing */ + if (negative) + uO.lflag = -2, negative = 0; + else + uO.lflag = 3; + break; + case 't': /* totals line */ + if (negative) + tflag_2v = tflag_slm = FALSE, negative = 0; + else { + tflag_2v = tflag_slm = explicit_t = TRUE; + if (uO.lflag == -1) + uO.lflag = 0; + } + break; + case ('T'): /* use (sortable) decimal time format */ + if (negative) + uO.T_flag = FALSE, negative = 0; + else + uO.T_flag = TRUE; + break; + case 'v': /* turbo-verbose listing */ + if (negative) + uO.lflag = -2, negative = 0; + else + uO.lflag = 10; + break; + case 'z': /* print zipfile comment */ + if (negative) + uO.zflag = negative = 0; + else + uO.zflag = 1; + break; + case 'Z': /* ZipInfo mode: ignore */ + break; + default: + error = TRUE; + break; + } + } + } + if ((argc-- == 0) || error) { + *pargc = argc; + *pargv = argv; + return USAGE(error); + } + +#ifdef MORE + if (G.M_flag && !isatty(1)) /* stdout redirected: "more" func useless */ + G.M_flag = 0; +#endif + + /* if no listing options given (or all negated), or if only -h/-t given + * with individual files specified, use default listing format */ + if ((uO.lflag < 0) || ((argc > 0) && (uO.lflag == 0))) + uO.lflag = LFLAG; + + /* set header and totals flags to default or specified values */ + switch (uO.lflag) { + case 0: /* 0: can only occur if either -t or -h explicitly given; */ + case 2: /* therefore set both flags equal to normally false value */ + uO.hflag = hflag_2; + uO.tflag = tflag_2v; + break; + case 1: /* only filenames, *always* */ + uO.hflag = FALSE; + uO.tflag = FALSE; + uO.zflag = FALSE; + break; + case 3: + case 4: + case 5: + uO.hflag = ((argc > 0) && !explicit_h)? FALSE : hflag_slmv; + uO.tflag = ((argc > 0) && !explicit_t)? FALSE : tflag_slm; + break; + case 10: + uO.hflag = hflag_slmv; + uO.tflag = tflag_2v; + break; + } + + *pargc = argc; + *pargv = argv; + return 0; + +} /* end function zi_opts() */ + +#endif /* !WINDLL */ + + + + + +/*******************************/ +/* Function zi_end_central() */ +/*******************************/ + +int zi_end_central(__G) /* return PK-type error code */ + __GDEF +{ + int error = PK_COOL; + + +/*--------------------------------------------------------------------------- + Print out various interesting things about the zipfile. + ---------------------------------------------------------------------------*/ + + /* header fits on one line, for anything up to 10GB and 10000 files: */ + if (uO.hflag) + Info(slide, 0, ((char *)slide, ((int)strlen(G.zipfn) < 39)? + LoadFarString(LongHeader) : LoadFarString(ShortHeader), G.zipfn, + (long)G.ziplen, G.ecrec.total_entries_central_dir, + (G.ecrec.total_entries_central_dir==1)? + nullStr : "s")); + + /* verbose format */ + if (uO.lflag > 9) { + Info(slide, 0, ((char *)slide, LoadFarString(EndCentDirRec))); + Info(slide, 0, ((char *)slide, LoadFarString(LineSeparators))); + + Info(slide, 0, ((char *)slide, LoadFarString(ActOffsetCentDir), + (long)G.real_ecrec_offset, (long)G.real_ecrec_offset, + (long)G.expect_ecrec_offset, (long)G.expect_ecrec_offset)); + + if (G.ecrec.number_this_disk == 0) { + Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive1), + G.ecrec.total_entries_central_dir, + (G.ecrec.total_entries_central_dir == 1)? "entry" : "entries", + G.ecrec.size_central_directory, + G.ecrec.size_central_directory)); + Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive2), + G.ecrec.offset_start_central_directory, + G.ecrec.offset_start_central_directory)); + } else { + Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive1), + G.ecrec.number_this_disk + 1, + G.ecrec.num_disk_start_cdir + 1, + G.ecrec.num_entries_centrl_dir_ths_disk, + (G.ecrec.num_entries_centrl_dir_ths_disk == 1)? "is" : "are")); + Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive2), + G.ecrec.total_entries_central_dir, + (G.ecrec.total_entries_central_dir == 1) ? "entry" : "entries", + G.ecrec.size_central_directory, + G.ecrec.size_central_directory)); + Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive3), + G.ecrec.offset_start_central_directory, + G.ecrec.offset_start_central_directory)); + } + + /*----------------------------------------------------------------------- + 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) */ + + /* non-verbose mode: print zipfile comment only if requested */ + } else if (uO.zflag && G.ecrec.zipfile_comment_length) { + if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(ZipfileCommTruncMsg))); + error = PK_WARN; + } + } /* endif (verbose) */ + + return error; + +} /* end function zi_end_central() */ + + + + + +/************************/ +/* Function zipinfo() */ +/************************/ + +int zipinfo(__G) /* return PK-type error code */ + __GDEF +{ + int do_this_file=FALSE, error, error_in_archive=PK_COOL; + int *fn_matched=NULL, *xn_matched=NULL; + unsigned j, members=0; + ulg tot_csize=0L, tot_ucsize=0L; + ulg endprev; /* buffers end of previous entry for zi_long()'s check + * of extra bytes */ + + +/*--------------------------------------------------------------------------- + Malloc space for check on unmatched filespecs (no big deal if one or both + are NULL). + ---------------------------------------------------------------------------*/ + + if (G.filespecs > 0 && + (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != NULL) + for (j = 0; j < G.filespecs; ++j) + fn_matched[j] = FALSE; + + if (G.xfilespecs > 0 && + (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != NULL) + for (j = 0; j < G.xfilespecs; ++j) + xn_matched[j] = FALSE; + +/*--------------------------------------------------------------------------- + Set file pointer to start of central directory, then loop through cen- + tral directory entries. Check that directory-entry signature bytes are + actually there (just a precaution), then process the entry. We know + the entire central directory is on this disk: we wouldn't have any of + this information unless the end-of-central-directory record was on this + disk, and we wouldn't 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 maybe someday we'll add + multi-disk support. + ---------------------------------------------------------------------------*/ + + uO.L_flag = FALSE; /* zipinfo mode: never convert name to lowercase */ + G.pInfo = G.info; /* (re-)initialize, (just to make sure) */ + G.pInfo->textmode = 0; /* so one can read on screen (is this ever used?) */ + + /* reset endprev for new zipfile; account for multi-part archives (?) */ + endprev = (G.crec.relative_offset_local_header == 4L)? 4L : 0L; + + + for (j = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) { + if (readbuf(__G__ G.sig, 4) == 0) + return PK_EOF; + if (strncmp(G.sig, central_hdr_sig, 4)) { /* just to make sure */ + Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j)); + 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 */ + + if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != + PK_COOL) + { + error_in_archive = error; /* might be warning */ + if (error > PK_WARN) /* fatal */ + return error; + } + + if (!G.process_all_files) { /* check if specified on command line */ + unsigned i; + + do_this_file = FALSE; + for (i = 0; i < G.filespecs; i++) + if (match(G.filename, G.pfnames[i], uO.C_flag)) { + do_this_file = TRUE; + 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)) { + do_this_file = FALSE; /* ^-- ignore case in match */ + if (xn_matched) + xn_matched[i] = TRUE; + 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) { + + switch (uO.lflag) { + case 1: + case 2: + fnprint(__G); + SKIP_(G.crec.extra_field_length) + SKIP_(G.crec.file_comment_length) + break; + + case 3: + case 4: + case 5: + if ((error = zi_short(__G)) != PK_COOL) { + error_in_archive = error; /* might be warning */ + if (error > PK_WARN) /* fatal */ + return error; + } + break; + + case 10: + Info(slide, 0, ((char *)slide, + LoadFarString(CentralDirEntry), j)); + if ((error = zi_long(__G__ &endprev)) != PK_COOL) { + error_in_archive = error; /* might be warning */ + if (error > PK_WARN) /* fatal */ + return error; + } + break; + + default: + SKIP_(G.crec.extra_field_length) + SKIP_(G.crec.file_comment_length) + break; + + } /* end switch (lflag) */ + + tot_csize += G.crec.csize; + tot_ucsize += G.crec.ucsize; + if (G.crec.general_purpose_bit_flag & 1) + tot_csize -= 12; /* don't count encryption header */ + ++members; + +#ifdef DLL + if ((G.statreportcb != NULL) && + (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn, + G.filename, NULL)) { + if (fn_matched) + free((zvoid *)fn_matched); + if (xn_matched) + free((zvoid *)xn_matched); + return IZ_CTRLC; /* cancel operation by user request */ + } +#endif +#ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ + UserStop(); +#endif + + } else { /* not listing this file */ + SKIP_(G.crec.extra_field_length) + SKIP_(G.crec.file_comment_length) + + } /* end if (list member?) */ + + } /* end for-loop (j: member files) */ + +/*--------------------------------------------------------------------------- + Check that we actually found requested files; if so, print totals. + ---------------------------------------------------------------------------*/ + + if (uO.tflag) { + char *sgn = ""; + int cfactor = ratio(tot_ucsize, tot_csize); + + if (cfactor < 0) { + sgn = "-"; + cfactor = -cfactor; + } + Info(slide, 0, ((char *)slide, LoadFarString(ZipfileStats), + members, (members==1)? nullStr:"s", tot_ucsize, + tot_csize, sgn, cfactor/10, cfactor%10)); + } + +/*--------------------------------------------------------------------------- + Check for unmatched filespecs on command line and print warning if any + found. + ---------------------------------------------------------------------------*/ + + if (fn_matched) { + for (j = 0; j < G.filespecs; ++j) + if (!fn_matched[j]) + Info(slide, 0x401, ((char *)slide, + LoadFarString(FilenameNotMatched), G.pfnames[j])); + free((zvoid *)fn_matched); + } + if (xn_matched) { + for (j = 0; j < G.xfilespecs; ++j) + if (!xn_matched[j]) + Info(slide, 0x401, ((char *)slide, + LoadFarString(ExclFilenameNotMatched), G.pxnames[j])); + free((zvoid *)xn_matched); + } + +/*--------------------------------------------------------------------------- + Double check that we're back at the end-of-central-directory record. + ---------------------------------------------------------------------------*/ + + if (readbuf(__G__ G.sig, 4) == 0) /* disk error? */ + return PK_EOF; + if (strncmp(G.sig, end_central_sig, 4)) { /* just to make sure again */ + Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); + error_in_archive = PK_WARN; /* didn't find sig */ + } + if (members == 0 && error_in_archive <= PK_WARN) + error_in_archive = PK_FIND; + + if (uO.lflag >= 10) + (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); + + return error_in_archive; + +} /* end function zipinfo() */ + + + + + +/************************/ +/* Function zi_long() */ +/************************/ + +static int zi_long(__G__ pEndprev) /* return PK-type error code */ + __GDEF + ulg *pEndprev; /* for zi_long() check of extra bytes */ +{ +#ifdef USE_EF_UT_TIME + iztimes z_utime; +#endif + int error, error_in_archive=PK_COOL; + ush hostnum, hostver, extnum, extver, methnum, xattr; + char workspace[12], attribs[22]; + ZCONST char *varmsg_str; + char unkn[16]; + static ZCONST char Far *os[NUM_HOSTS] = { + OS_FAT, OS_Amiga, OS_VMS, OS_Unix, OS_VMCMS, OS_AtariST, OS_HPFS, + OS_Macintosh, OS_ZSystem, OS_CPM, OS_TOPS20, OS_NTFS, OS_QDOS, + OS_Acorn, OS_VFAT, OS_MVS, OS_BeOS, OS_Tandem + }; + static ZCONST char Far *method[NUM_METHODS] = { + MthdNone, MthdShrunk, MthdRedF1, MthdRedF2, MthdRedF3, MthdRedF4, + MthdImplode, MthdToken, MthdDeflate, MthdEnDeflate, MthdDCLImplode + }; + static ZCONST char Far *dtypelng[4] = { + DeflNorm, DeflMax, DeflFast, DeflSFast + }; + + +/*--------------------------------------------------------------------------- + Check whether there's any extra space inside the zipfile. If *pEndprev is + zero, it's probably a signal that OS/2 extra fields are involved (with + unknown compressed size). We won't worry about prepended junk here... + ---------------------------------------------------------------------------*/ + + if (G.crec.relative_offset_local_header != *pEndprev && *pEndprev > 0L) { + /* GRR DEBUG + Info(slide, 0, ((char *)slide, + " [crec.relative_offset_local_header = %lu, endprev = %lu]\n", + G.crec.relative_offset_local_header, *pEndprev)); + */ + Info(slide, 0, ((char *)slide, LoadFarString(ExtraBytesPreceding), + (long)G.crec.relative_offset_local_header - (long)(*pEndprev))); + } + + /* calculate endprev for next time around (problem: extra fields may + * differ in length between local and central-directory records) */ + *pEndprev = G.crec.relative_offset_local_header + 4L + LREC_SIZE + + G.crec.filename_length + G.crec.extra_field_length + + G.crec.file_comment_length + G.crec.csize; + +/*--------------------------------------------------------------------------- + Read the extra field, if any. It may be used to get UNIX style modtime. + ---------------------------------------------------------------------------*/ + + if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0) + { + if (G.extra_field != NULL) { + free(G.extra_field); + G.extra_field = NULL; + } + error_in_archive = error; + /* The premature return in case of a "fatal" error (PK_EOF) is + * delayed until we analyze the extra field contents. + * This allows us to display all the other info that has been + * successfully read in. + */ + } + +/*--------------------------------------------------------------------------- + Print out various interesting things about the compressed file. + ---------------------------------------------------------------------------*/ + + hostnum = (ush)(G.pInfo->hostnum); + hostver = G.crec.version_made_by[0]; + extnum = (ush)MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS); + extver = G.crec.version_needed_to_extract[0]; + methnum = (ush)MIN(G.crec.compression_method, NUM_METHODS); + + (*G.message)((zvoid *)&G, (uch *)" ", 2L, 0); fnprint(__G); + + Info(slide, 0, ((char *)slide, LoadFarString(LocalHeaderOffset), + G.crec.relative_offset_local_header, + G.crec.relative_offset_local_header)); + + if (hostnum >= NUM_HOSTS) { + sprintf(unkn, LoadFarString(UnknownNo), + (int)G.crec.version_made_by[1]); + varmsg_str = unkn; + } else { + varmsg_str = LoadFarStringSmall(os[hostnum]); + } + Info(slide, 0, ((char *)slide, LoadFarString(HostOS), varmsg_str)); + Info(slide, 0, ((char *)slide, LoadFarString(EncodeSWVer), hostver/10, + hostver%10)); + + if (extnum >= NUM_HOSTS) { + sprintf(unkn, LoadFarString(UnknownNo), + (int)G.crec.version_needed_to_extract[1]); + varmsg_str = unkn; + } else { + varmsg_str = LoadFarStringSmall(os[extnum]); + } + Info(slide, 0, ((char *)slide, LoadFarString(MinOSCompReq), varmsg_str)); + Info(slide, 0, ((char *)slide, LoadFarString(MinSWVerReq), extver/10, + extver%10)); + + if (methnum >= NUM_METHODS) { + sprintf(unkn, LoadFarString(UnknownNo), G.crec.compression_method); + varmsg_str = unkn; + } else { + varmsg_str = LoadFarStringSmall(method[methnum]); + } + Info(slide, 0, ((char *)slide, LoadFarString(CompressMethod), varmsg_str)); + if (methnum == IMPLODED) { + Info(slide, 0, ((char *)slide, LoadFarString(SlideWindowSizeImplode), + (G.crec.general_purpose_bit_flag & 2)? '8' : '4')); + Info(slide, 0, ((char *)slide, LoadFarString(ShannonFanoTrees), + (G.crec.general_purpose_bit_flag & 4)? '3' : '2')); + } else if (methnum == DEFLATED) { + ush dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3); + + Info(slide, 0, ((char *)slide, LoadFarString(CompressSubtype), + LoadFarStringSmall(dtypelng[dnum]))); + } + + Info(slide, 0, ((char *)slide, LoadFarString(FileSecurity), + (G.crec.general_purpose_bit_flag & 1) ? nullStr : "not ")); + Info(slide, 0, ((char *)slide, LoadFarString(ExtendedLocalHdr), + (G.crec.general_purpose_bit_flag & 8) ? "yes" : "no")); + /* print upper 3 bits for amusement? */ + + /* For printing of date & time, a "char d_t_buf[21]" is required. + * To save stack space, we reuse the "char attribs[22]" buffer which + * is not used yet. + */ +# define d_t_buf attribs + + zi_time(__G__ &G.crec.last_mod_dos_datetime, NULL, d_t_buf); + Info(slide, 0, ((char *)slide, LoadFarString(FileModDate), d_t_buf)); +#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 or Macintosh */ + d_t_buf[0] = (char)0; /* signal "show local time" */ + zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf); + Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate), + d_t_buf, LoadFarStringSmall(LocalTime))); +#ifndef NO_GMTIME + d_t_buf[0] = (char)1; /* signal "show UTC (GMT) time" */ + zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf); + Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate), + d_t_buf, LoadFarStringSmall(GMTime))); +#endif /* !NO_GMTIME */ + } +#endif /* USE_EF_UT_TIME */ + + Info(slide, 0, ((char *)slide, LoadFarString(CRC32Value), G.crec.crc32)); + Info(slide, 0, ((char *)slide, LoadFarString(CompressedFileSize), + G.crec.csize)); + Info(slide, 0, ((char *)slide, LoadFarString(UncompressedFileSize), + G.crec.ucsize)); + Info(slide, 0, ((char *)slide, LoadFarString(FilenameLength), + G.crec.filename_length)); + Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldLength), + G.crec.extra_field_length)); + Info(slide, 0, ((char *)slide, LoadFarString(FileCommentLength), + G.crec.file_comment_length)); + Info(slide, 0, ((char *)slide, LoadFarString(FileDiskNum), + G.crec.disk_number_start + 1)); + Info(slide, 0, ((char *)slide, LoadFarString(ApparentFileType), + (G.crec.internal_file_attributes & 1)? "text" + : (G.crec.internal_file_attributes & 2)? "ebcdic" + : "binary")); /* changed to accept EBCDIC */ +#ifdef ATARI + printf(" external file attributes (hex): %.8lx\n", + G.crec.external_file_attributes); +#endif + xattr = (ush)((G.crec.external_file_attributes >> 16) & 0xFFFF); + if (hostnum == VMS_) { + char *p=attribs, *q=attribs+1; + int i, j, k; + + for (k = 0; k < 12; ++k) + workspace[k] = 0; + if (xattr & VMS_IRUSR) + workspace[0] = 'R'; + if (xattr & VMS_IWUSR) { + workspace[1] = 'W'; + workspace[3] = 'D'; + } + if (xattr & VMS_IXUSR) + workspace[2] = 'E'; + if (xattr & VMS_IRGRP) + workspace[4] = 'R'; + if (xattr & VMS_IWGRP) { + workspace[5] = 'W'; + workspace[7] = 'D'; + } + if (xattr & VMS_IXGRP) + workspace[6] = 'E'; + if (xattr & VMS_IROTH) + workspace[8] = 'R'; + if (xattr & VMS_IWOTH) { + workspace[9] = 'W'; + workspace[11] = 'D'; + } + if (xattr & VMS_IXOTH) + workspace[10] = 'E'; + + *p++ = '('; + for (k = j = 0; j < 3; ++j) { /* loop over groups of permissions */ + for (i = 0; i < 4; ++i, ++k) /* loop over perms within a group */ + if (workspace[k]) + *p++ = workspace[k]; + *p++ = ','; /* group separator */ + if (j == 0) + while ((*p++ = *q++) != ',') + ; /* system, owner perms are same */ + } + *p-- = 0; + *p = ')'; /* overwrite last comma */ + Info(slide, 0, ((char *)slide, LoadFarString(VMSFileAttributes), xattr, + attribs)); + + } else if (hostnum == AMIGA_) { + switch (xattr & AMI_IFMT) { + case AMI_IFDIR: attribs[0] = 'd'; break; + case AMI_IFREG: attribs[0] = '-'; break; + default: attribs[0] = '?'; break; + } + attribs[1] = (xattr & AMI_IHIDDEN)? 'h' : '-'; + attribs[2] = (xattr & AMI_ISCRIPT)? 's' : '-'; + attribs[3] = (xattr & AMI_IPURE)? 'p' : '-'; + attribs[4] = (xattr & AMI_IARCHIVE)? 'a' : '-'; + attribs[5] = (xattr & AMI_IREAD)? 'r' : '-'; + attribs[6] = (xattr & AMI_IWRITE)? 'w' : '-'; + attribs[7] = (xattr & AMI_IEXECUTE)? 'e' : '-'; + attribs[8] = (xattr & AMI_IDELETE)? 'd' : '-'; + attribs[9] = 0; /* better dlm the string */ + Info(slide, 0, ((char *)slide, LoadFarString(AmigaFileAttributes), + xattr, attribs)); + + } else if ((hostnum != FS_FAT_) && (hostnum != FS_HPFS_) && + (hostnum != FS_NTFS_) && (hostnum != FS_VFAT_) && + (hostnum != ACORN_) && + (hostnum != VM_CMS_) && (hostnum != MVS_)) + { /* assume Unix-like */ + switch ((unsigned)(xattr & UNX_IFMT)) { + case (unsigned)UNX_IFDIR: attribs[0] = 'd'; break; + case (unsigned)UNX_IFREG: attribs[0] = '-'; break; + case (unsigned)UNX_IFLNK: attribs[0] = 'l'; break; + case (unsigned)UNX_IFBLK: attribs[0] = 'b'; break; + case (unsigned)UNX_IFCHR: attribs[0] = 'c'; break; + case (unsigned)UNX_IFIFO: attribs[0] = 'p'; break; + case (unsigned)UNX_IFSOCK: attribs[0] = 's'; break; + default: attribs[0] = '?'; break; + } + attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-'; + attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-'; + attribs[7] = (xattr & UNX_IROTH)? 'r' : '-'; + + attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-'; + attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-'; + attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-'; + + if (xattr & UNX_IXUSR) + attribs[3] = (xattr & UNX_ISUID)? 's' : 'x'; + else + attribs[3] = (xattr & UNX_ISUID)? 'S' : '-'; /* S = undefined */ + if (xattr & UNX_IXGRP) + attribs[6] = (xattr & UNX_ISGID)? 's' : 'x'; /* == UNX_ENFMT */ + else + attribs[6] = (xattr & UNX_ISGID)? 'l' : '-'; + if (xattr & UNX_IXOTH) + attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x'; /* "sticky bit" */ + else + attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-'; /* T = undefined */ + attribs[10] = 0; + + Info(slide, 0, ((char *)slide, LoadFarString(UnixFileAttributes), xattr, + attribs)); + + } else { + Info(slide, 0, ((char *)slide, LoadFarString(NonMSDOSFileAttributes), + G.crec.external_file_attributes >> 8)); + + } /* endif (hostnum: external attributes format) */ + + if ((xattr=(ush)(G.crec.external_file_attributes & 0xFF)) == 0) + Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributes), + xattr)); + else if (xattr == 1) + Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesRO), + xattr)); + else + Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesAlpha), + xattr, (xattr&1)? "rdo " : nullStr, + (xattr&2)? "hid " : nullStr, + (xattr&4)? "sys " : nullStr, + (xattr&8)? "lab " : nullStr, + (xattr&16)? "dir " : nullStr, + (xattr&32)? "arc" : nullStr)); + +/*--------------------------------------------------------------------------- + Analyze the extra field, if any, and print the file comment, if any (the + filename has already been printed, above). That finishes up this file + entry... + ---------------------------------------------------------------------------*/ + + if (G.crec.extra_field_length > 0) { + uch *ef_ptr = G.extra_field; + ush ef_len = G.crec.extra_field_length; + ush eb_id, eb_datalen; + ZCONST char Far *ef_fieldname; + + if (error_in_archive > PK_WARN) /* fatal: can't continue */ + /* delayed "fatal error" return from extra field reading */ + return error; + if (G.extra_field == (uch *)NULL) + return PK_ERR; /* not consistent with crec length */ + + Info(slide, 0, ((char *)slide, LoadFarString(ExtraFields))); + + while (ef_len >= EB_HEADSIZE) { + eb_id = makeword(&ef_ptr[EB_ID]); + eb_datalen = makeword(&ef_ptr[EB_LEN]); + ef_ptr += EB_HEADSIZE; + ef_len -= EB_HEADSIZE; + + if (eb_datalen > (ush)ef_len) { + Info(slide, 0x421, ((char *)slide, + LoadFarString(ExtraFieldTrunc), eb_id, eb_datalen, ef_len)); + eb_datalen = ef_len; + } + + switch (eb_id) { + case EF_AV: + ef_fieldname = efAV; + break; + case EF_OS2: + ef_fieldname = efOS2; + break; + case EF_ACL: + ef_fieldname = efACL; + break; + case EF_NTSD: + ef_fieldname = efNTSD; + break; + case EF_PKVMS: + ef_fieldname = efPKVMS; + break; + case EF_IZVMS: + ef_fieldname = efIZVMS; + break; + case EF_PKW32: + ef_fieldname = efPKWin32; + break; + case EF_PKUNIX: + ef_fieldname = efPKUnix; + break; + case EF_IZUNIX: + ef_fieldname = efIZUnix; + if (G.crec.version_made_by[1] == UNIX_ && *pEndprev > 0L) + *pEndprev += 4L; /* also have UID/GID in local copy */ + break; + case EF_IZUNIX2: + ef_fieldname = efIZUnix2; + if (*pEndprev > 0L) + *pEndprev += 4L; /* 4 byte UID/GID in local copy */ + break; + case EF_TIME: + ef_fieldname = efTime; + break; + case EF_MAC3: + ef_fieldname = efMac3; + break; + case EF_JLMAC: + ef_fieldname = efJLMac; + break; + case EF_ZIPIT: + ef_fieldname = efZipIt; + break; + case EF_ZIPIT2: + ef_fieldname = efZipIt2; + break; + case EF_VMCMS: + ef_fieldname = efVMCMS; + break; + case EF_MVS: + ef_fieldname = efMVS; + break; + case EF_BEOS: + ef_fieldname = efBeOS; + break; + case EF_QDOS: + ef_fieldname = efQDOS; + break; + case EF_AOSVS: + ef_fieldname = efAOSVS; + break; + case EF_SPARK: /* from RISC OS */ + ef_fieldname = efSpark; + break; + case EF_MD5: + ef_fieldname = efMD5; + break; + case EF_ASIUNIX: + ef_fieldname = efASiUnix; + break; + default: + ef_fieldname = efUnknown; + break; + } + Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldType), + eb_id, LoadFarStringSmall(ef_fieldname), eb_datalen)); + + /* additional, field-specific information: */ + switch (eb_id) { + case EF_OS2: + case EF_ACL: + if (eb_datalen >= EB_OS2_HLEN) { + if (eb_id == EF_OS2) + ef_fieldname = OS2EAs; + else + ef_fieldname = ACLdata; + Info(slide, 0, ((char *)slide, + LoadFarString(ef_fieldname), makelong(ef_ptr))); + *pEndprev = 0L; /* no clue about csize of local */ + } + break; + case EF_NTSD: + if (eb_datalen >= EB_NTSD_C_LEN) { + Info(slide, 0, ((char *)slide, LoadFarString(NTSDData), + makelong(ef_ptr))); + *pEndprev = 0L; /* no clue about csize of local */ + } + break; + case EF_IZVMS: + if (eb_datalen >= 8) { + char *p, q[8]; + int compr = makeword(ef_ptr+4) & 7; + + *q = '\0'; + if (compr > 3) + compr = 3; + if (strncmp((char *)ef_ptr, "VFAB", 4) == 0) + p = "FAB"; + else if (strncmp((char *)ef_ptr, "VALL", 4) == 0) + p = "XABALL"; + else if (strncmp((char *)ef_ptr, "VFHC", 4) == 0) + p = "XABFHC"; + else if (strncmp((char *)ef_ptr, "VDAT", 4) == 0) + p = "XABDAT"; + else if (strncmp((char *)ef_ptr, "VRDT", 4) == 0) + p = "XABRDT"; + else if (strncmp((char *)ef_ptr, "VPRO", 4) == 0) + p = "XABPRO"; + else if (strncmp((char *)ef_ptr, "VKEY", 4) == 0) + p = "XABKEY"; + else if (strncmp((char *)ef_ptr, "VMSV", 4) == 0) { + p = "version"; + if (eb_datalen >= 16) { + q[0] = ' '; + q[1] = '('; + strncpy(q+2, (char *)ef_ptr+12, 4); + q[6] = ')'; + q[7] = '\0'; + } + } else + p = "version"; + Info(slide, 0, ((char *)slide, LoadFarString(izVMSdata), + LoadFarStringSmall(izVMScomp[compr]), + makeword(ef_ptr+6), p, q)); + } + break; + case EF_TIME: + if (eb_datalen >= 1) { + char types[80]; + int num = 0, len; + + *types = '\0'; + if (*ef_ptr & 1) { + strcpy(types, LoadFarString(UTmodification)); + ++num; + } + if (*ef_ptr & 2) { + len = strlen(types); + if (num) + types[len++] = '/'; + strcpy(types+len, LoadFarString(UTaccess)); + ++num; + if (*pEndprev > 0L) + *pEndprev += 4L; + } + if (*ef_ptr & 4) { + len = strlen(types); + if (num) + types[len++] = '/'; + strcpy(types+len, LoadFarString(UTcreation)); + ++num; + if (*pEndprev > 0L) + *pEndprev += 4L; + } + if (num > 0) + Info(slide, 0, ((char *)slide, + LoadFarString(UTdata), types, + num == 1? nullStr : "s")); + } + break; + case EF_MAC3: + if (eb_datalen >= EB_MAC3_HLEN) { + ulg eb_uc = makelong(ef_ptr); + unsigned mac3_flgs = makeword(ef_ptr+EB_FLGS_OFFS); + unsigned eb_is_uc = mac3_flgs & EB_M3_FL_UNCMPR; + + Info(slide, 0, ((char *)slide, LoadFarString(Mac3data), + eb_uc, eb_is_uc ? "un" : nullStr)); + if (eb_is_uc) { + if (*pEndprev > 0L) + *pEndprev += makelong(ef_ptr); + } else { + *pEndprev = 0L; /* no clue about csize of local */ + } + + Info(slide, 0, ((char *)slide, + LoadFarString(MacOSMAC3flags), + LoadFarStringSmall(mac3_flgs & EB_M3_FL_DATFRK ? + MacOS_DF : MacOS_RF), + (mac3_flgs & EB_M3_FL_TIME64 ? 64 : 32))); + zi_showMacTypeCreator(__G__ &ef_ptr[6]); + } + break; + case EF_ZIPIT2: + if (eb_datalen >= 5 && + strncmp((char *)ef_ptr, "ZPIT", 4) == 0) { + + if (eb_datalen >= 12) { + zi_showMacTypeCreator(__G__ &ef_ptr[4]); + } + } + + case EF_ZIPIT: + if (eb_datalen >= 5 && + strncmp((char *)ef_ptr, "ZPIT", 4) == 0) { + unsigned fnlen = ef_ptr[4]; + + if (eb_datalen >= fnlen + (5 + 8)) { + uch nullchar = ef_ptr[fnlen+5]; + + ef_ptr[fnlen+5] = '\0'; /* terminate filename */ + Info(slide, 0, ((char *)slide, + LoadFarString(ZipItFname), (char *)ef_ptr+5)); + ef_ptr[fnlen+5] = nullchar; + zi_showMacTypeCreator(__G__ &ef_ptr[fnlen+5]); + } + } + break; + case EF_JLMAC: + if (eb_datalen >= 40 && + strncmp((char *)ef_ptr, "JLEE", 4) == 0) + { + zi_showMacTypeCreator(__G__ &ef_ptr[4]); + + Info(slide, 0, ((char *)slide, + LoadFarString(MacOSJLEEflags), + LoadFarStringSmall(ef_ptr[31] & 1 ? + MacOS_DF : MacOS_RF))); + } + break; +#ifdef CMS_MVS + case EF_VMCMS: + case EF_MVS: + { + char type[100]; + + Info(slide, 0, ((char *)slide, + LoadFarString(VmMvsExtraField), + (getVMMVSexfield(type, ef_ptr-EB_HEADSIZE, + (unsigned)eb_datalen) > 0)? + type : LoadFarStringSmall(VmMvsInvalid))); + } + break; +#endif /* CMS_MVS */ + case EF_BEOS: + if (eb_datalen >= EB_BEOS_HLEN) { + ulg eb_uc = makelong(ef_ptr); + unsigned eb_is_uc = + *(ef_ptr+EB_FLGS_OFFS) & EB_BE_FL_UNCMPR; + + Info(slide, 0, ((char *)slide, LoadFarString(BeOSdata), + eb_uc, eb_is_uc ? "un" : nullStr)); + if (eb_is_uc) { + if (*pEndprev > 0L) + *pEndprev += makelong(ef_ptr); + } else { + *pEndprev = 0L; /* no clue about csize of local */ + } + } + break; + case EF_QDOS: + if (eb_datalen >= 4) { + Info(slide, 0, ((char *)slide, LoadFarString(QDOSdata), + ef_ptr[0], ef_ptr[1], ef_ptr[2], ef_ptr[3])); + } + break; + case EF_AOSVS: + if (eb_datalen >= 5) { + Info(slide, 0, ((char *)slide, LoadFarString(AOSVSdata), + ((int)(uch)ef_ptr[4])/10, ((int)(uch)ef_ptr[4])%10)); + } + break; + case EF_MD5: + if (eb_datalen >= 19) { + char md5[33]; + int i; + + for (i = 0; i < 16; ++i) + sprintf(&md5[i<<1], "%02x", ef_ptr[15-i]); + md5[32] = '\0'; + Info(slide, 0, ((char *)slide, LoadFarString(MD5data), + md5)); + break; + } /* else: fall through !! */ + default: + if (eb_datalen > 0) { + ush i, n; + + if (eb_datalen <= 24) { + Info(slide, 0, ((char *)slide, + LoadFarString(ColonIndent))); + n = eb_datalen; + } else { + Info(slide, 0, ((char *)slide, + LoadFarString(First20))); + n = 20; + } + for (i = 0; i < n; ++i) + Info(slide, 0, ((char *)slide, + LoadFarString(efFormat), ef_ptr[i])); + } + break; + } + (*G.message)((zvoid *)&G, (uch *)".", 1L, 0); + + ef_ptr += eb_datalen; + ef_len -= eb_datalen; + } + (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); + } + + /* high bit == Unix/OS2/NT GMT times (mtime, atime); next bit == UID/GID */ + if ((xattr = (ush)((G.crec.external_file_attributes & 0xC000) >> 12)) & 8) + { + if (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_) + { + Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType), + "is", EF_IZUNIX, LoadFarStringSmall(efIZUnix), + (unsigned)(xattr&12), (xattr&4)? efIZuid : efIZnouid)); + if (*pEndprev > 0L) + *pEndprev += (ulg)(xattr&12); + } + else if (hostnum == FS_FAT_ && !(xattr&4)) + Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType), + "may be", EF_IZUNIX, LoadFarStringSmall(efIZUnix), 8, + efIZnouid)); + } + + if (!G.crec.file_comment_length) + Info(slide, 0, ((char *)slide, LoadFarString(NoFileComment))); + else { + Info(slide, 0, ((char *)slide, LoadFarString(FileCommBegin))); + if ((error = do_string(__G__ G.crec.file_comment_length, DISPL_8)) != + PK_COOL) + { + error_in_archive = error; /* might be warning */ + if (error > PK_WARN) /* fatal */ + return error; + } + Info(slide, 0, ((char *)slide, LoadFarString(FileCommEnd))); + } + + return error_in_archive; + +} /* end function zi_long() */ + + + + + +/*************************/ +/* Function zi_short() */ +/*************************/ + +static int zi_short(__G) /* return PK-type error code */ + __GDEF +{ +#ifdef USE_EF_UT_TIME + iztimes z_utime; + time_t *z_modtim; +#endif + int k, error, error_in_archive=PK_COOL; + ush methnum, hostnum, hostver, xattr; + char *p, workspace[12], attribs[16]; + char methbuf[5]; + static ZCONST char dtype[5]="NXFS"; /* normal, maximum, fast, superfast */ + static ZCONST char Far os[NUM_HOSTS+1][4] = { + "fat", "ami", "vms", "unx", "cms", "atr", "hpf", "mac", "zzz", + "cpm", "t20", "ntf", "qds", "aco", "vft", "mvs", "be ", "nsk", + "???" + }; + static ZCONST char Far method[NUM_METHODS+1][5] = { + "stor", "shrk", "re:1", "re:2", "re:3", "re:4", "i#:#", "tokn", + "def#", "edef", "dcli", "u###" + }; + + +/*--------------------------------------------------------------------------- + Print out various interesting things about the compressed file. + ---------------------------------------------------------------------------*/ + + methnum = (ush)MIN(G.crec.compression_method, NUM_METHODS); + hostnum = (ush)(G.pInfo->hostnum); + hostver = G.crec.version_made_by[0]; +/* + extnum = MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS); + extver = G.crec.version_needed_to_extract[0]; + */ + + zfstrcpy(methbuf, method[methnum]); + if (methnum == IMPLODED) { + methbuf[1] = (char)((G.crec.general_purpose_bit_flag & 2)? '8' : '4'); + methbuf[3] = (char)((G.crec.general_purpose_bit_flag & 4)? '3' : '2'); + } else if (methnum == DEFLATED) { + ush dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3); + methbuf[3] = dtype[dnum]; + } else if (methnum >= NUM_METHODS) { /* unknown */ + sprintf(&methbuf[1], "%03u", G.crec.compression_method); + } + + for (k = 0; k < 15; ++k) + attribs[k] = ' '; + attribs[15] = 0; + + xattr = (ush)((G.crec.external_file_attributes >> 16) & 0xFFFF); + switch (hostnum) { + case VMS_: + { int i, j; + + for (k = 0; k < 12; ++k) + workspace[k] = 0; + if (xattr & VMS_IRUSR) + workspace[0] = 'R'; + if (xattr & VMS_IWUSR) { + workspace[1] = 'W'; + workspace[3] = 'D'; + } + if (xattr & VMS_IXUSR) + workspace[2] = 'E'; + if (xattr & VMS_IRGRP) + workspace[4] = 'R'; + if (xattr & VMS_IWGRP) { + workspace[5] = 'W'; + workspace[7] = 'D'; + } + if (xattr & VMS_IXGRP) + workspace[6] = 'E'; + if (xattr & VMS_IROTH) + workspace[8] = 'R'; + if (xattr & VMS_IWOTH) { + workspace[9] = 'W'; + workspace[11] = 'D'; + } + if (xattr & VMS_IXOTH) + workspace[10] = 'E'; + + p = attribs; + 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 */ + } + *--p = ' '; /* overwrite last comma */ + if ((p - attribs) < 12) + sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10); + } + break; + + case FS_FAT_: + case FS_HPFS_: + case FS_NTFS_: + case VM_CMS_: + case FS_VFAT_: + case MVS_: + case ACORN_: + xattr = (ush)(G.crec.external_file_attributes & 0xFF); + sprintf(attribs, ".r.-... %d.%d", hostver/10, hostver%10); + attribs[2] = (xattr & 0x01)? '-' : 'w'; + attribs[5] = (xattr & 0x02)? 'h' : '-'; + attribs[6] = (xattr & 0x04)? 's' : '-'; + attribs[4] = (xattr & 0x20)? 'a' : '-'; + if (xattr & 0x10) { + attribs[0] = 'd'; + attribs[3] = 'x'; + } else + attribs[0] = '-'; + if (IS_VOLID(xattr)) + attribs[0] = 'V'; + else if ((p = strrchr(G.filename, '.')) != (char *)NULL) { + ++p; + if (STRNICMP(p, "com", 3) == 0 || STRNICMP(p, "exe", 3) == 0 || + STRNICMP(p, "btm", 3) == 0 || STRNICMP(p, "cmd", 3) == 0 || + STRNICMP(p, "bat", 3) == 0) + attribs[3] = 'x'; + } + break; + + case AMIGA_: + switch (xattr & AMI_IFMT) { + case AMI_IFDIR: attribs[0] = 'd'; break; + case AMI_IFREG: attribs[0] = '-'; break; + default: attribs[0] = '?'; break; + } + attribs[1] = (xattr & AMI_IHIDDEN)? 'h' : '-'; + attribs[2] = (xattr & AMI_ISCRIPT)? 's' : '-'; + attribs[3] = (xattr & AMI_IPURE)? 'p' : '-'; + attribs[4] = (xattr & AMI_IARCHIVE)? 'a' : '-'; + attribs[5] = (xattr & AMI_IREAD)? 'r' : '-'; + attribs[6] = (xattr & AMI_IWRITE)? 'w' : '-'; + attribs[7] = (xattr & AMI_IEXECUTE)? 'e' : '-'; + attribs[8] = (xattr & AMI_IDELETE)? 'd' : '-'; + sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10); + break; + + default: /* assume Unix-like */ + switch ((unsigned)(xattr & UNX_IFMT)) { + case (unsigned)UNX_IFDIR: attribs[0] = 'd'; break; + case (unsigned)UNX_IFREG: attribs[0] = '-'; break; + case (unsigned)UNX_IFLNK: attribs[0] = 'l'; break; + case (unsigned)UNX_IFBLK: attribs[0] = 'b'; break; + case (unsigned)UNX_IFCHR: attribs[0] = 'c'; break; + case (unsigned)UNX_IFIFO: attribs[0] = 'p'; break; + case (unsigned)UNX_IFSOCK: attribs[0] = 's'; break; + default: attribs[0] = '?'; break; + } + attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-'; + attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-'; + attribs[7] = (xattr & UNX_IROTH)? 'r' : '-'; + attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-'; + attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-'; + attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-'; + + if (xattr & UNX_IXUSR) + attribs[3] = (xattr & UNX_ISUID)? 's' : 'x'; + else + attribs[3] = (xattr & UNX_ISUID)? 'S' : '-'; /* S==undefined */ + if (xattr & UNX_IXGRP) + attribs[6] = (xattr & UNX_ISGID)? 's' : 'x'; /* == UNX_ENFMT */ + else + /* attribs[6] = (xattr & UNX_ISGID)? 'l' : '-'; real 4.3BSD */ + attribs[6] = (xattr & UNX_ISGID)? 'S' : '-'; /* SunOS 4.1.x */ + if (xattr & UNX_IXOTH) + attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x'; /* "sticky bit" */ + else + attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-'; /* T==undefined */ + + sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10); + break; + + } /* end switch (hostnum: external attributes format) */ + + Info(slide, 0, ((char *)slide, "%s %s %8lu ", attribs, + LoadFarStringSmall(os[hostnum]), G.crec.ucsize)); + Info(slide, 0, ((char *)slide, "%c", + (G.crec.general_purpose_bit_flag & 1)? + ((G.crec.internal_file_attributes & 1)? 'T' : 'B') : /* encrypted */ + ((G.crec.internal_file_attributes & 1)? 't' : 'b'))); /* plaintext */ + k = (G.crec.extra_field_length || + /* a local-only "UX" (old Unix/OS2/NT GMT times "IZUNIX") e.f.? */ + ((G.crec.external_file_attributes & 0x8000) && + (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_))); + Info(slide, 0, ((char *)slide, "%c", k? + ((G.crec.general_purpose_bit_flag & 8)? 'X' : 'x') : /* extra field */ + ((G.crec.general_purpose_bit_flag & 8)? 'l' : '-'))); /* no extra field */ + /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ extended local header or not */ + + if (uO.lflag == 4) { + ulg csiz = G.crec.csize; + + if (G.crec.general_purpose_bit_flag & 1) + csiz -= 12; /* if encrypted, don't count encryption header */ + Info(slide, 0, ((char *)slide, "%3d%%", + (ratio(G.crec.ucsize,csiz)+5)/10)); + } else if (uO.lflag == 5) + Info(slide, 0, ((char *)slide, " %8lu", G.crec.csize)); + + /* Read the extra field, if any. The extra field info may be used + * in the file modification time section, below. + */ + if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0) + { + if (G.extra_field != NULL) { + free(G.extra_field); + G.extra_field = NULL; + } + error_in_archive = error; + /* We do not return prematurely in case of a "fatal" error (PK_EOF). + * This does not hurt here, because we do not need to read from the + * zipfile again before the end of this function. + */ + } + + /* For printing of date & time, a "char d_t_buf[16]" is required. + * To save stack space, we reuse the "char attribs[16]" buffer whose + * content is no longer needed. + */ +# define d_t_buf attribs +#ifdef USE_EF_UT_TIME + z_modtim = 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) + ? &z_utime.mtime : NULL; + TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7.0 or Macintosh */ + d_t_buf[0] = (char)0; /* signal "show local time" */ +#else +# define z_modtim NULL +#endif + Info(slide, 0, ((char *)slide, " %s %s ", methbuf, + zi_time(__G__ &G.crec.last_mod_dos_datetime, z_modtim, d_t_buf))); + fnprint(__G); + +/*--------------------------------------------------------------------------- + Skip the file comment, if any (the filename has already been printed, + above). That finishes up this file entry... + ---------------------------------------------------------------------------*/ + + SKIP_(G.crec.file_comment_length) + + return error_in_archive; + +} /* end function zi_short() */ + + + + + +/**************************************/ +/* Function zi_showMacTypeCreator() */ +/**************************************/ + +static void zi_showMacTypeCreator(__G__ ebfield) + __GDEF + uch *ebfield; +{ + /* not every Type / Creator character is printable */ + if (isprint(ebfield[0]) && isprint(ebfield[1]) && + isprint(ebfield[2]) && isprint(ebfield[3]) && + isprint(ebfield[4]) && isprint(ebfield[5]) && + isprint(ebfield[6]) && isprint(ebfield[7])) { + Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata), + ebfield[0], ebfield[1], ebfield[2], ebfield[3], + ebfield[4], ebfield[5], ebfield[6], ebfield[7])); + } else { + Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata1), + (((ulg)ebfield[0]) << 24) + + (((ulg)ebfield[1]) << 16) + + (((ulg)ebfield[2]) << 8) + + ((ulg)ebfield[3]), + (((ulg)ebfield[4]) << 24) + + (((ulg)ebfield[5]) << 16) + + (((ulg)ebfield[6]) << 8) + + ((ulg)ebfield[7]))); + } +} /* end function zi_showMacTypeCreator() */ + + + + + +/************************/ +/* Function zi_time() */ +/************************/ + +static char *zi_time(__G__ datetimez, modtimez, d_t_str) + __GDEF + ZCONST ulg *datetimez; + ZCONST time_t *modtimez; + char *d_t_str; +{ + unsigned yr, mo, dy, hh, mm, ss; + char monthbuf[4]; + ZCONST char *monthstr; + static ZCONST char Far month[12][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; +#ifdef USE_EF_UT_TIME + struct tm *t; +#endif + + + +/*--------------------------------------------------------------------------- + Convert the file-modification date and time info to a string of the form + "1991 Feb 23 17:15:00", "23-Feb-91 17:15" or "19910223.171500", depending + on values of lflag and T_flag. If using Unix-time extra fields, convert + to local time or not, depending on value of first character in d_t_str[]. + ---------------------------------------------------------------------------*/ + +#ifdef USE_EF_UT_TIME + if (modtimez != NULL) { +#ifndef NO_GMTIME + /* check for our secret message from above... */ + t = (d_t_str[0] == (char)1)? gmtime(modtimez) : localtime(modtimez); +#else + t = localtime(modtimez); +#endif + if (uO.lflag > 9 && t == (struct tm *)NULL) + /* time conversion error in verbose listing format, + * return string with '?' instead of data + */ + return (strcpy(d_t_str, LoadFarString(YMDHMSTimeError))); + } 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); + + hh = (unsigned)(t->tm_hour); + mm = (unsigned)(t->tm_min); + ss = (unsigned)(t->tm_sec); + } else +#endif /* USE_EF_UT_TIME */ + { + yr = ((unsigned)(*datetimez >> 25) & 0x7f) + 80; + mo = ((unsigned)(*datetimez >> 21) & 0x0f); + dy = ((unsigned)(*datetimez >> 16) & 0x1f); + + hh = (((unsigned)*datetimez >> 11) & 0x1f); + mm = (((unsigned)*datetimez >> 5) & 0x3f); + ss = (((unsigned)*datetimez << 1) & 0x3e); + } + + if (mo == 0 || mo > 12) { + sprintf(monthbuf, LoadFarString(BogusFmt), mo); + monthstr = monthbuf; + } else + monthstr = LoadFarStringSmall(month[mo-1]); + + if (uO.lflag > 9) /* verbose listing format */ + sprintf(d_t_str, LoadFarString(YMDHMSTime), yr+1900, monthstr, dy, hh, + mm, ss); + else if (uO.T_flag) + sprintf(d_t_str, LoadFarString(DecimalTime), yr+1900, mo, dy, hh, mm, + ss); + else /* was: if ((uO.lflag >= 3) && (uO.lflag <= 5)) */ + sprintf(d_t_str, LoadFarString(DMYHMTime), dy, monthstr, yr%100, hh, + mm); + + return d_t_str; + +} /* end function zi_time() */ + +#endif /* !NO_ZIPINFO */ diff --git a/utils/Install/script/finished.ini b/utils/Install/script/finished.ini new file mode 100644 index 0000000000..3c52d33bcc --- /dev/null +++ b/utils/Install/script/finished.ini @@ -0,0 +1,9 @@ +# Sample ini file for the last page +# +closeold +grabfile,install.bmp +loadwxr,finished.wxr +setbutton,101,exit +setbutton,103,exit +disable,button3 +remove,install.bmp \ No newline at end of file diff --git a/utils/Install/script/finished.wxr b/utils/Install/script/finished.wxr new file mode 100644 index 0000000000..5d4e4b5dcd --- /dev/null +++ b/utils/Install/script/finished.wxr @@ -0,0 +1,25 @@ +static char *dialog1 = "dialog(name = 'dialog1',\ + style = 'wxRAISED_BORDER | wxCAPTION | wxTHICK_FRAME | wxSYSTEM_MENU',\ + title = 'Installing wxInstall 0.1',\ + id = 100,\ + x = 10, y = 10, width = 264, height = 179,\ + background_colour = 'D4D0C8',\ + use_dialog_units = 1,\ + use_system_defaults = 0,\ + font = [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg'],\ + control = [101, wxButton, 'Exit Installer', '0', 'button2', 5, 160, 60, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [102, wxButton, '<< Back', 'wxNO_BORDER', 'button3', 165, 160, 44, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [103, wxButton, 'Finish', '0', 'button4', 209, 160, 44, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [104, wxStaticBitmap, '', 'wxNO_BORDER', 'static5', 9, 8, 60, 144, 'bitmap9',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [105, wxStaticText, 'wxInstall Installation finished.', '0', 'statictext10', 81, 12, 164, 10, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [6006, wxStaticText, 'Thanks for trying wxInstall. Press finish to exit.', '0', 'statictext6', 80, 42, 168, 6, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']])."; + +static char *bitmap9 = "bitmap(name = 'bitmap9',\ + bitmap = ['install.bmp', wxBITMAP_TYPE_BMP, 'ANY'])."; + diff --git a/utils/Install/script/install.bmp b/utils/Install/script/install.bmp new file mode 100644 index 0000000000000000000000000000000000000000..b394773c37223ee9764a9162ebf0de10367fa667 GIT binary patch literal 14418 zcmeI0O^)L>5QRCmR@u>ZW7cMC23bbdbe4gw)@pz(+JJq4M%ot`AlZABE94S6L?5h? zSH&MuBB`IO$%ZZ2%He*abI_9qTMD9mo!32eJd% zf$TtbAUlv9$PP?6P#h-)gxy6`E`^F_zf;Q~sGQ`c4CT|`unM3yJ!II!h}=u5W_lpkGkrwP1Hb@ z4aydSXtF)lKu}fBTCM>jfQ}|yd*IGTLVBH4gT37H_pWZ1@eAa2q6SboJj&RjNEL|f zgidrFX|J(j2Gf7d;YJZ5Gz4T&AX?xFL_;AWM4d(miXni;7I;xi}>falNV+NlI0kZ^RgqZn|Mwpok8ALPlAd47g4&)Ha zOhX;wm?_9ZI%XVl2;Dl#YtzPxt8eGnP8@ViEiI+4~3y_`*ZER&&MAFm4K61L~+EyJ0lV3Q5p9A_Sg=e0FnvjVj9u(0z@a4^$RiTeo zsV#%pDl?o8KH{KphLM&VUq~xOVyn2D-hk}d7S9}{-?k@wW1w_wK-%Y;9*AsNiOr79 zY3Ox@E^36-6`i@{-Fe9TLjxJ16K@VUrI7iX1|k>Uh_ei)3pblnl6fW+4F=$kTZxYp zX~@vPTJ9=3YJ@OuMkvZ4tgS})zY>hs5HV1SF_cL~-RP(JM;Z)KaJXEA;p8joHUIk% zQ}P>qxgG3jgs6}UwF)oy?~>1ih^RC|3dKtHT9KLxnEo_6aIZN0Crc3IBpn+dh#>mk$f2p!HrOtkUUdp#;P` zcB|s@F;hESrCcInGyl>2cjMUN9(K`WSRL)-kb@kC1B^cw_dH==p%?c%$4Lf$; z%dc;~j$W)u2G<87zx49a8KoH11<1ooKOb#fia{~Y^5OC_$cKfJ3_=4k%!h@N40Ik| z38k3p<#v|4(`Mis><*u%g4$Yckk6|;ZB(eEnj?k;4GdY0TcWzY-Mo1K83-K% z0AG;K?eYqQLc4WyhZ&V(C?7&@fQC$&(m_6~a(zQ>IV3GY!6ld*^3f`~QG^v%;%%IVkw zMDC{Z8K_{-G|7aBcAUV}-02)6188T4W|R^PjnF3ZiAF3m#@L;L-TMG%r4gn>x-*8- zOgFGQ(@IIE8`zz3Zb{!<^*tk)Af<#(ckS-XGBVC=U4I0T-=g<}$}%w|@mmr_B!PJCGg74rB-ZzXSgP_-C-$ literal 0 HcmV?d00001 diff --git a/utils/Install/script/install.xpm b/utils/Install/script/install.xpm new file mode 100644 index 0000000000..cd2938912f --- /dev/null +++ b/utils/Install/script/install.xpm @@ -0,0 +1,292 @@ +/* XPM */ +static char * inst[] = { +/* width height ncolors chars_per_pixel */ +"100 275 10 1", +/* colors */ +" c #AE3E4A", +"! c #C2C2C2", +"# c #828282", +"$ c #FEFEFE", +"% c #020202", +"& c #020282", +"' c #0202FE", +"( c #FE0202", +") c #02FE02", +"* c #028202", +/* pixels */ +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" $$$$ ", +" $$$$$!!!!$$ ", +" $$$$!!!!!!!!!!!$$ ", +" $$$$$!!!!!!!!!!!!!!!!!$$ ", +" $$ $$$$$!!!!!!!!!!!!!!!!!!!!!!!!$$ ", +" $$!!$$% $$$$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$$ ", +" $$!!!!!!$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$$ ", +" $$!!!!!!!!!!$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$$ ", +" $!!!!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$$ ", +" $$!!!!!!!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$$ ", +" $!$!!!!!!!!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$% ", +" $!!$$!!!!!!!!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#% ", +" $!!!!$$!!!!!!!!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!###% ", +" $!!!!!!$$!!!!!!!!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!!!!!!!!!!!!#####% ", +" $!!!!!!!!$$!!!!!!!!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!!!!!!!!#######% ", +" $!!!!!!!!!!$$!!!!!!!!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!!!!#########% ", +" $!!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!!$!!!!!!!!!!!!!!!!!###########% ", +" $!!!!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!$$!!!!!!!!!!!!!#############% ", +" $!!!##!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!$$!!!!!!!!!###############% ", +" $!!!#'##!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!$$!!!!!#################% ", +" $!!!#&&'##!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!$$!###################% ", +" $!!!#''&&'##!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!%###################% ", +" $!!!#'&''&&'##!!!!!!!!!!!$$!!!!!!!!!!!!!!#%###################% ", +" $!!!#''&&'''&'##!!!!!!!!!!!$$!!!!!!!!!!###%###################% ", +" $!!!#&&'''&''&&&##!!!!!!!!!!!$$!!!!!!#####%###################% ", +" $!!!#''&&''&&'''&'##!!!!!!!!!!!$$!!#######%###################% ", +" $!!!#&&''&&'''&&''&&##!!!!!!!!!!!#########%###################% ", +" $!!!#&'&&''&&'''&&''&'##!!!!!!!!!#########%###################% ", +" $!!!#&&''&&''&&&''&'''&&##!!!!!!!#########%###################% ", +" $!!!#''&&&'&##''&'''&&''&'##!!!!!#########%###################% ", +" $!!!#&&&'&&'####''&&''&&''&&##!!!#########%###################% ", +" $!!!#&'&&''&######''&'''&&''&$!!!#########%###################% ", +" $!!!#&&''&&'#!######''&&''&''$!!!#########%##################% ", +" $!!!#&'&&&'&#!!!#####&''&'''&$!!!#########%#################%% ", +" $!!!#&&&'&&'#!!%!!####&&''&&'$!!!#########%################%#% ", +" $!!!#&'&&''&#!!!%%!!##''&&''&$!!!#########%###############%##% ", +" $!!!#&&&'&&&#!&&!!!%!#&&''&&'$!!!#########%##############%###% ", +" $!!!#&&&&&'&#!&&&&!!!#''&&''&$!!!#########%#############%####% ", +" $!!!#&&&'&&&#!!!&&&&!#&&'&&&'$!!!#########%############%#####% ", +" $!!!#&'&&&&&##!!!!&&!#'&&&''&$!!!#########%###########%######% ", +" $!!!#&&&'&&&'&##!!!!!#&&''&&'$!!!#########%##########%#######% ", +" $!!!#&&&&&'&&&&&##!!!#''&&''&$!!!#########%#########%########% ", +" $!!!$$&&'&&&'&&&'&##!#&&'&&&'$!!!#########%########%#########% ", +" $!!!!!$$&&&&&&'&&&&&##'&&&''&$!!!#########%#######%##########% ", +" $!!!!!!!$$&&&&&&'&&&'&&&''&&'$!!!#########%######%###########% ", +" $!!!!!!!!!$$&&&&&&'&&&&&&&'&&$!!!#########%#####%############% ", +" $#!!!!!!!!!!$$&&'&&&'&&&'&&&'$!!!#########%####%###########%% ", +" %%#!!!!!!!!!!!$$&&&&&&'&&&&&&$!!!#########%###%##########%% ", +" %##!!!!!!!!!!!$$&&'&&&'&&&'$!!!#########%##%#########%% ", +" %%##!!!!!!!!!!!$$&&&&&&'&&$!!!#########%#%########%% ", +" %%##!!!!!!!!!!!$$&&'&&&'$!!!#########%%#######%% ", +" $$!!%%##!!!!!!!!!!!$$&&&&&$!!!#########%######%% ", +" $$!!!!!!%%##!!!!!!!!!!!$$&&'$!!!#########%####%%$ ", +" $$!!!!!!!!!!%%##!!!!!!!!!!!$$&$!!!#########%##%%#%%$$ ", +" $$!!!!!!!!!!!!$#%%##!!!!!!!!!!!&$!!!#########%%%#####%!$$ ", +" $$!!!!!!!!!!!!!$####%%##!!!!!!))!!!!!!#########%########%!!$$ ", +" $$!!!!!!!!!!!!!!$#######%%##!!!!**!!!!!!#########%#########%!!!$$ ", +" $!$$!!!!!!!!!!!!$!!!!!####%%##!!!!!!!!!!#########%#########%!!!!!$$ ", +" $!!!$$!!!!!!!!!!$!!!!!!!!###%%##!!!!!!!!#########%#########%!!!!!!!$$ ", +" $!!!!!$$!!!!!!!!$!!!!!!!!!!###%%##!!!!!!#########%#########%!!!!!!!!!$$ ", +" $!!!!!!!$$!!!!!!$!!!!!!!!!!!!###%%##!!!!########%%#########%!!!!!!!!!!!$% ", +" $!!!!!!!!!$$!!!!!$!!!!!!!!!!!!!###%%##!!######%%##########%!!!!!!!!!!###% ", +" $!!!!!!!!!!!$$!!!%$!!!!!!!!!!!!!####%%######%%############%!!!!!!!!#####% ", +" $!!!))!!!!!!!!$!!!%$!!!!!!!!!!!!!!####%%##%%#############%!!!!!!!#######% ", +" $!!!))!!!!!!!!$!!!!%$$!!!!!!!!!!!!!#####%%##############%!!!!!!!!#######% ", +" $!!!**!!!!!!!!!$$!!!%%$$!!!!!!!!!!!!##################%%!!!!!!!#########% ", +" $!!!!!!!!!!!!!!!!$$!!!%%$$$!!!!!!!!!!###############%%!!!!!!!###########% ", +" $!!!!!!!!!!!!!!!!!!$$!!!%%%$$$$$!!!!!!###########%%%!!!!!!!#############% ", +" $!!!!!!!!!!!!!!!!!!!!$$!!!!%%%%%$$$$$$######%%%%%!!!!!!!!###########%%##% ", +" $!!!!!!!!!!!!!!!!!!!!!!$$!!!!!!!%%%%%%%%%%%%!!!!!!!!!!!###########%%%%##% ", +" $!!!!!!!!!!!!!!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!!!!!!!!!!#############%%#%##% ", +" $#!!!!!!!!!!!!!!!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!!!!!!###############%%#%##% ", +" %%##!!!!!!!!!!!!!!!!!!!!!!!!!$$!!!!!!!!!!!!!!!!!!#################%%%%##% ", +" %%##!!!!!!!!!!!!!!!!!!!!!!!!!$$!!!!!!!!!!!!!!###################%#%%##% ", +" %%##!!!!!!!!!!!!!!!##!!!!!!!!$$!!!!!!!!!!#####################%%%%##% ", +" %%##!!!!!!!!!!!!!$$##!!!!!!!!$$!!!!!!!######################%%####% ", +" %%##!!!!!!!!!!!!!$$##!!!!!!!!$$!!!#############################%% ", +" %%##!!!!!!!!!!!!!$$##!!!!!!!!$#############################%% ", +" %%#!!!!!!!!!!!!!!$$##!!!!!!!###########################%% ", +" %##!!!!!!!!!!!!!!$$##!!!!!#########################%% ", +" %%##!!!!!!!!!!!!!!$$!!!!!#######################%% ", +" %%##!!!!!!!!!!!!!!!!!!!#####################%% ", +" %%##!!!!!!!!!!!!!!!!!###################%% ", +" %%##!!!!!!!!!!!!!!!#################%% ", +" %%##!!!!!!!!!!!!!###############%% ", +" %%##!!!!!!!!!!!#############%% ", +" %%##!!!!!!!!!###########%% ", +" %%##!!!!!!!#########%% ", +" %%##!!!!!#######%% ", +" %%##!!!#####%% ", +" %%##!####% ", +" %%###%% ", +" %%% ", +" ", +" ", +" ", +" ", +" ", +" $$ ", +" $$$$$$ $$ ", +" $$!!(($$$$ $$$$$$ ", +" $$!!!!!!(($$$$ $$!!(($$$$ ", +" $$!!!!!!!!!!(($$$$ $$!!!!!!(($$$$ ", +" $$!!!!!!!!!$$!!!(($$$ $!!!!!!!!!!(($$$$ ", +" $$!!###!!!!!$##$!!!!(($$$ $$!!!!!!!!$$!!!(($$$$ ", +" $!!#######!!!!$$!!!!!!!!!#% $$!!##!!!!!$##$!!!!(($$$$ ", +" %##!!######$$!!!!!!!!!!!##% $!!######!!!!$$!!!!!!!!!!#% ", +" %%##!!%#$$$$$$!!!!!!!!#%% %##!!######!!!!!!!!!!!!!##% ", +" %%##$$%!!($$$$!!!!##% %%##!###%%##!!!!!!!!!##%% ", +" $$!!!!!!(($$$$##%% %%#!!%%##!#!!!!!!##%% ", +" $$!!!!!!!!!!(($$$$ %##!!%%##!!!!##%% ", +" $$!!!!!!!!!$$!!!(($$$$ %%##%%!!!!##%% ", +" $$!!###!!!!!$##$!!!!(($$$ %%##!!%##% ", +" $!!#######!!!!$$!!!!!!!!!!% %%##%% ", +" %##!!#######!!!!!!!!!!!!!#% $$ %% ", +" %%##!!###%%##!!!!!!!!!##% $$$$$$ ", +" %%##!!%##!!#!!!!!!##%% $$!!(($$$$ ", +" %%##!!%##%!!!!##%% $$!!!!!!(($$$ ", +" %%##%%!!!!##%% $$!!!!!!!!!!(($$$ ", +" %%##!!%##% $$!!!!!!!!!$$!!!($$$$ ", +" %%##%% $$!!###!!!!!$##$!!!(($$$$ ", +" %% $!!#######!!!!$$!!!!!!!!!#% ", +" %##!!#######!!!!!!!!!!!!##% ", +" %%##!!###%%##!!!!!!!!##%% ", +" %%##!!%##!!#!!!!!##%% ", +" %%##!!%##%!!!!#%% ", +" %%##%%!!!!##% ", +" %%##!!%##% ", +" %%##%% ", +" %% ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" " +}; diff --git a/utils/Install/script/license.txt b/utils/Install/script/license.txt new file mode 100644 index 0000000000..429d994410 --- /dev/null +++ b/utils/Install/script/license.txt @@ -0,0 +1,53 @@ + wxWindows Library Licence, Version 3 + ==================================== + + Copyright (C) 1998 Julian Smart, Robert Roebling [, ...] + + Everyone is permitted to copy and distribute verbatim copies + of this licence document, but changing it is not allowed. + + WXWINDOWS LIBRARY LICENCE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public Licence + along with this software, usually in a file named COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA. + + EXCEPTION NOTICE + + 1. As a special exception, the copyright holders of this library give + permission for additional uses of the text contained in this release of + the library as licenced under the wxWindows Library Licence, applying + either version 3 of the Licence, or (at your option) any later version of + the Licence as published by the copyright holders of version 3 of the + Licence document. + + 2. The exception is that you may use, copy, link, modify and distribute + under the user's own terms, binary object code versions of works based + on the Library. + + 3. If you copy code from files distributed under the terms of the GNU + General Public Licence or the GNU Library General Public Licence into a + copy of this library, as this licence permits, the exception does not + apply to the code that you add in this way. To avoid misleading anyone as + to the status of such modified files, you must delete this exception + notice from such code and/or adjust the licensing conditions notice + accordingly. + + 4. If you write modifications of your own for this library, it is your + choice whether to permit this exception to apply to your modifications. + If you do not wish that, you must delete the exception notice from such + code and/or adjust the licensing conditions notice accordingly. + + diff --git a/utils/Install/script/nocheck.ini b/utils/Install/script/nocheck.ini new file mode 100644 index 0000000000..7223ff2551 --- /dev/null +++ b/utils/Install/script/nocheck.ini @@ -0,0 +1,5 @@ +# ini file that gets called when the license isn't checked. +# +message,"Please accept the license or exit." +setbutton,101,exit +setbutton,103,page2.ini diff --git a/utils/Install/script/page1.ini b/utils/Install/script/page1.ini new file mode 100644 index 0000000000..af901086e1 --- /dev/null +++ b/utils/Install/script/page1.ini @@ -0,0 +1,12 @@ +# Sample ini file for page one +# +closeold +grabfile,install.bmp +loadwxr,page1.wxr +setbutton,101,exit +setbutton,103,page2.ini +disable,button3 +grabfile,license.txt +mleview,textctrl11,license.txt +remove,license.txt +remove,install.bmp \ No newline at end of file diff --git a/utils/Install/script/page1.wxr b/utils/Install/script/page1.wxr new file mode 100644 index 0000000000..5d0fb778eb --- /dev/null +++ b/utils/Install/script/page1.wxr @@ -0,0 +1,27 @@ +static char *dialog1 = "dialog(name = 'dialog1',\ + style = 'wxRAISED_BORDER | wxCAPTION | wxTHICK_FRAME | wxSYSTEM_MENU',\ + title = 'Installing wxInstall 0.1',\ + id = 100,\ + x = 10, y = 10, width = 264, height = 179,\ + background_colour = 'D4D0C8',\ + use_dialog_units = 1,\ + use_system_defaults = 0,\ + font = [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg'],\ + control = [101, wxButton, 'Exit Installer', '0', 'button2', 5, 160, 60, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [102, wxButton, '<< Back', 'wxNO_BORDER', 'button3', 165, 160, 44, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [103, wxButton, 'Next >>', '0', 'button4', 209, 160, 44, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [104, wxStaticBitmap, '', 'wxNO_BORDER', 'static5', 9, 8, 60, 144, 'bitmap9',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [105, wxStaticText, 'Welcome to wxInstall 0.1', '0', 'statictext10', 81, 12, 164, 10, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [106, wxTextCtrl, '', 'wxTE_READONLY | wxTE_MULTILINE', 'textctrl11', 80, 32, 168, 99, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [6001, wxCheckBox, 'I accept the terms of this license.', '0', 'checkbox1', 84, 140, 157, 10, 0,\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']])."; + +static char *bitmap9 = "bitmap(name = 'bitmap9',\ + bitmap = ['install.bmp', wxBITMAP_TYPE_BMP, 'ANY'])."; + diff --git a/utils/Install/script/page2.ini b/utils/Install/script/page2.ini new file mode 100644 index 0000000000..63012d61e2 --- /dev/null +++ b/utils/Install/script/page2.ini @@ -0,0 +1,11 @@ +# Sample ini file for page two +# +getcheck,checkbox1,nocheck.ini +closeold +grabfile,install.bmp +loadwxr,page2.wxr +settext,textctrl1 +setbutton,101,exit +setbutton,102,page1.ini +setbutton,103,page3.ini +remove,install.bmp \ No newline at end of file diff --git a/utils/Install/script/page2.wxr b/utils/Install/script/page2.wxr new file mode 100644 index 0000000000..6d3003e0a8 --- /dev/null +++ b/utils/Install/script/page2.wxr @@ -0,0 +1,27 @@ +static char *dialog1 = "dialog(name = 'dialog1',\ + style = 'wxRAISED_BORDER | wxCAPTION | wxTHICK_FRAME | wxSYSTEM_MENU',\ + title = 'Installing wxInstall 0.1',\ + id = 100,\ + x = 10, y = 10, width = 264, height = 179,\ + background_colour = 'D4D0C8',\ + use_dialog_units = 1,\ + use_system_defaults = 0,\ + font = [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg'],\ + control = [101, wxButton, 'Exit Installer', '0', 'button2', 5, 160, 60, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [102, wxButton, '<< Back', 'wxNO_BORDER', 'button3', 165, 160, 44, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [103, wxButton, 'Next >>', '0', 'button4', 209, 160, 44, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [104, wxStaticBitmap, '', 'wxNO_BORDER', 'static5', 9, 8, 60, 144, 'bitmap9',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [105, wxStaticText, 'Choose installation directory', '0', 'statictext10', 81, 12, 164, 10, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [106, wxTextCtrl, '', 'wxTE_READONLY | wxTE_MULTILINE', 'textctrl11', 80, 48, 168, 99, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [6002, wxTextCtrl, '', '0', 'textctrl1', 80, 28, 168, 13, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']])."; + +static char *bitmap9 = "bitmap(name = 'bitmap9',\ + bitmap = ['install.bmp', wxBITMAP_TYPE_BMP, 'ANY'])."; + diff --git a/utils/Install/script/page3.ini b/utils/Install/script/page3.ini new file mode 100644 index 0000000000..24ba2fe411 --- /dev/null +++ b/utils/Install/script/page3.ini @@ -0,0 +1,11 @@ +# Sample ini file for page three +# +gettext,textctrl1 +closeold +grabfile,install.bmp +loadwxr,page3.wxr +setbutton,101,exit +setbutton,102,page2.ini +setbutton,103,page4.ini +setbutton,6004,readme.ini +remove,install.bmp \ No newline at end of file diff --git a/utils/Install/script/page3.wxr b/utils/Install/script/page3.wxr new file mode 100644 index 0000000000..aeb885fecc --- /dev/null +++ b/utils/Install/script/page3.wxr @@ -0,0 +1,29 @@ +static char *dialog1 = "dialog(name = 'dialog1',\ + style = 'wxRAISED_BORDER | wxCAPTION | wxTHICK_FRAME | wxSYSTEM_MENU',\ + title = 'Installing wxInstall 0.1',\ + id = 100,\ + x = 10, y = 10, width = 264, height = 179,\ + background_colour = 'D4D0C8',\ + use_dialog_units = 1,\ + use_system_defaults = 0,\ + font = [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg'],\ + control = [101, wxButton, 'Exit Installer', '0', 'button2', 5, 160, 60, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [102, wxButton, '<< Back', 'wxNO_BORDER', 'button3', 165, 160, 44, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [103, wxButton, 'Start', '0', 'button4', 209, 160, 44, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [104, wxStaticBitmap, '', 'wxNO_BORDER', 'static5', 9, 8, 60, 144, 'bitmap9',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [105, wxStaticText, 'Ready to begin installation.', '0', 'statictext10', 81, 12, 164, 10, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [6002, wxStaticText, 'Thanks for trying wxInstall. Feel free to contact me at', '0', 'statictext2', 80, 27, 172, 10, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0]],\ + control = [6003, wxStaticText, 'dbsoft@technologist.com with comments questions or bug reports.', '0', 'statictext3', 80, 36, 181, 6, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [6004, wxButton, 'View Readme', '0', 'button5', 84, 81, 162, 15, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']])."; + +static char *bitmap9 = "bitmap(name = 'bitmap9',\ + bitmap = ['install.bmp', wxBITMAP_TYPE_BMP, 'ANY'])."; + diff --git a/utils/Install/script/page4.ini b/utils/Install/script/page4.ini new file mode 100644 index 0000000000..61417dc75b --- /dev/null +++ b/utils/Install/script/page4.ini @@ -0,0 +1,11 @@ +# Sample ini file for page four +# +remove,readme.txt +closeold +grabfile,install.bmp +loadwxr,page4.wxr +setbutton,101,exit +disable,button3 +disable,button4 +remove,install.bmp +startinst,gauge5,finished.ini \ No newline at end of file diff --git a/utils/Install/script/page4.wxr b/utils/Install/script/page4.wxr new file mode 100644 index 0000000000..c7b59f3d7f --- /dev/null +++ b/utils/Install/script/page4.wxr @@ -0,0 +1,25 @@ +static char *dialog1 = "dialog(name = 'dialog1',\ + style = 'wxRAISED_BORDER | wxCAPTION | wxTHICK_FRAME | wxSYSTEM_MENU',\ + title = 'Installing wxInstall 0.1',\ + id = 100,\ + x = 10, y = 10, width = 264, height = 179,\ + background_colour = 'D4D0C8',\ + use_dialog_units = 1,\ + use_system_defaults = 0,\ + font = [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg'],\ + control = [101, wxButton, 'Exit Installer', '0', 'button2', 5, 160, 60, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [102, wxButton, '<< Back', 'wxNO_BORDER', 'button3', 165, 160, 44, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [103, wxButton, 'Next >>', '0', 'button4', 209, 160, 44, 14, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [104, wxStaticBitmap, '', 'wxNO_BORDER', 'static5', 9, 8, 60, 144, 'bitmap9',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [105, wxStaticText, 'Please wait while installing wxInstall...', '0', 'statictext10', 81, 12, 164, 10, '',\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']],\ + control = [6005, wxGauge, '', 'wxGA_HORIZONTAL', 'gauge5', 85, 58, 157, 15, 0, 100,\ + [8, 'wxSWISS', 'wxNORMAL', 'wxNORMAL', 0, 'MS Shell Dlg']])."; + +static char *bitmap9 = "bitmap(name = 'bitmap9',\ + bitmap = ['install.bmp', wxBITMAP_TYPE_BMP, 'ANY'])."; + diff --git a/utils/Install/script/readme.ini b/utils/Install/script/readme.ini new file mode 100644 index 0000000000..9dfde93ed7 --- /dev/null +++ b/utils/Install/script/readme.ini @@ -0,0 +1,8 @@ +# Sample ini file for the readme +# +grabfile,readme.txt +system,"notepad readme.txt" +setbutton,101,exit +setbutton,102,page2.ini +setbutton,103,page4.ini +setbutton,6004,readme.ini diff --git a/utils/Install/script/readme.txt b/utils/Install/script/readme.txt new file mode 100644 index 0000000000..6e836c83c5 --- /dev/null +++ b/utils/Install/script/readme.txt @@ -0,0 +1,25 @@ +Ok, this is the first release of wxInstall, my wxWindows port of my +OS/2 installation program. Everything is under the wxWindows license +except for the Infozip code. + +Current Status: + +Archive support: ACE and ZIP. + +Tested platforms: Windows 2000, FreeBSD 4.0 (GTK) + +Todo: + +I need to write a directory browser, since the wxDirCtrl won't work. +I need to add Project support to the wxInstall builder. +Add platform specific code for modifying the startup environment. +--- There is some code for OS/2 (currently unsupported) and Windows --- + +Bugs: + +XPM's crash the installer on Windows. +ZIP archives crash on Windows. + +Thanks! + +You can reach me at dbsoft@technologist.com \ No newline at end of file diff --git a/utils/Install/script/wxinst.cfg b/utils/Install/script/wxinst.cfg new file mode 100644 index 0000000000..d00d98c8b0 --- /dev/null +++ b/utils/Install/script/wxinst.cfg @@ -0,0 +1,62 @@ +# Name of the application being installed +# +INSTALLER_APPLICATION=wxInstall +# +# Version of the application being installed +# +INSTALLER_VERSION=0.1 +# +# What the installer says in the title bar +# +INSTALLER_TITLE=wxInstall Installer +# +# Default install path +# +INSTALLER_PATH=c:\wxInstall +# +# Bitmap Width to avoid sizing problems +# +INSTALLER_BITMAP_WIDTH=100 +# +# Bitmap Height to avoid sizing problems +# +INSTALLER_BITMAP_HEIGHT=275 +# +# Make WPS Program: Title ,Program name, Icon, Destination, ID, setup +# +INSTALLER_PROGRAM=wxInstall Builder,%USERPATH%\wxib.exe,,,, +# +# Make WPS Folder: Folder title, Icon, Destination, ID, setup +# +INSTALLER_FOLDER=wxInstall,,,, +# +# Make WPS Folder: Shadow title, Reference, Destination +# +INSTALLER_SHADOW= +# +# Make a generic object: Title, Class, Destination, ID, setup +# +INSTALLER_OBJECT= +# +# Add SETs to the CONFIG.SYS: Variable, Value, flag +# flag = 1 if the installer should overwrite existing SETs +# flag = 2 if the installer should only create it if it is nonexistant +# +INSTALLER_SETS= +# +# Add System Variables (LIBPATH, PATH, ETC): SysVariable, Value +# +INSTALLER_SYSVAR=LIBPATH,%INSTALLPATH% +# +# Adds a line to the Config.Sys replacing an expandables. +# +INSTALLER_SYSLINE= +# +# Number of packages included in this self extractor. +# +INSTALLER_PACKAGE_COUNT=2 +# +# List of packages. +# +INSTALLER_PACKAGE=misc.ace,Misc. Files +INSTALLER_PACKAGE=wxinst.ace,wxInstall version 0.1 diff --git a/utils/Install/sfxace/globals.c b/utils/Install/sfxace/globals.c new file mode 100644 index 0000000000..fdba0e5509 --- /dev/null +++ b/utils/Install/sfxace/globals.c @@ -0,0 +1,137 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* Global variable declarations */ +/* */ +/* ------------------------------------------------------------------------ */ + +#include "os.h" + +#if defined(__CYGWIN__) +#include +#endif +#include "acestruc.h" +#include "unace.h" +#include +#include + +//-------- Ace sign +const char *acesign = "**ACE**"; + +//-------- Version string for program +const char *version="UNACE v1.1 public version\n"; + +#ifdef AMIGA +//-------- Version string for VERSION program +static char *_version="$VER: Unace Amiga 1.1 "__AMIGADATE__"\n\n"; +#endif + +//-------- header buffer and pointers +thead head; + +tmhead *t_mhead = (tmhead *) & head; +tfhead *t_fhead = (tfhead *) & head; + +//-------- buffers +ULONG *buf_rd =0; +CHAR *buf =0; +CHAR *buf_wr =0; +UCHAR *readbuf =0; + +//-------- decompressor variables +SHORT rpos =0, + dcpr_do =0, + dcpr_do_max =0, + blocksize =0, + dcpr_dic =0, + dcpr_oldnum =0, + bits_rd =0, + dcpr_frst_file =0; +USHORT dcpr_code_mn[1 << maxwd_mn], + dcpr_code_lg[1 << maxwd_lg]; +UCHAR dcpr_wd_mn[maxcode + 2], + dcpr_wd_lg[maxcode + 2], + wd_svwd[svwd_cnt]; +ULONG dcpr_dpos =0, + cpr_dpos2 =0, + dcpr_dicsiz =0, + dcpr_dican =0, + dcpr_size =0, + dcpr_olddist[4]={0,0,0,0}, + code_rd =0; + +CHAR *dcpr_text =0; + +//-------- quicksort +USHORT sort_org[maxcode + 2]; +UCHAR sort_freq[(maxcode + 2) * 2]; + +//-------- file handling +CHAR aname[PATH_MAX]; +INT archan, + wrhan; +#if !defined(__EMX__) && !defined(__OS2__) +FILE *farchan = NULL; +#endif + +LONG skipsize=0; + +//-------- structures for archive handling +struct tadat adat; + +//-------- flags +INT f_err =0, + f_ovrall =0, + f_allvol_pr=0, + f_curpas =0, + f_criterr =0; + + +void resetglobals(void) +{ + t_mhead = (tmhead *) & head; + t_fhead = (tfhead *) & head; + + buf_rd =0; + buf =0; + buf_wr =0; + readbuf =0; + + rpos =0; + dcpr_do =0; + dcpr_do_max =0; + blocksize =0; + dcpr_dic =0; + dcpr_oldnum =0; + bits_rd =0; + dcpr_frst_file =0; + + memset(&dcpr_code_mn, 0, sizeof(dcpr_code_mn)); + memset(&dcpr_code_lg, 0, sizeof(dcpr_code_lg)); + memset(&dcpr_wd_mn, 0, sizeof(dcpr_wd_mn)); + memset(&dcpr_wd_lg, 0, sizeof(dcpr_wd_lg)); + memset(&wd_svwd, 0, sizeof(wd_svwd)); + dcpr_dpos =0; + cpr_dpos2 =0; + dcpr_dicsiz =0; + dcpr_dican =0; + dcpr_size =0; + + memset(&dcpr_olddist, 0, sizeof(dcpr_olddist)); + + code_rd =0; + dcpr_text =0; + + memset(&sort_org, 0, sizeof(sort_org)); + memset(&sort_freq, 0, sizeof(sort_freq)); + + archan=0; + wrhan=0; + skipsize=0; + + f_err =0; + f_ovrall =0; + f_allvol_pr=0; + f_curpas =0; + f_criterr =0; + +} diff --git a/utils/Install/sfxace/install.PRJ b/utils/Install/sfxace/install.PRJ new file mode 100644 index 0000000000..73d30d6ad9 --- /dev/null +++ b/utils/Install/sfxace/install.PRJ @@ -0,0 +1,50 @@ +[Project ID] +Signature=UE Proj: v.1 +[Files] +0=C:\Program Files\wx2\samples\Install\install.c +1=C:\Program Files\wx2\samples\Install\install.h +2=C:\Program Files\wx2\samples\Install\instsup.c +3=C:\Program Files\wx2\samples\Install\makefile +4=C:\Program Files\wx2\samples\Install\wxmain.cpp +[Open Files] +Open File0=C:\Program Files\wx2\samples\Install\makefile +Open File Pos0=2487 +Open File Line0=1545 +Open File Window Pos0=0,1,0,0,-4,-23,22,22,646,423 +Open File1=C:\Program Files\wx2\samples\Install\wxmain.cpp +Open File Pos1=2953 +Open File Line1=0 +Open File Window Pos1=0,1,0,0,-4,-23,110,110,734,511 +Open File2=C:\Program Files\wx2\samples\Install\install.c +Open File Pos2=9875 +Open File Line2=9111 +Open File Window Pos2=0,1,0,0,-4,-23,176,176,800,577 +Open File3=C:\insttmp\winbitchx.cfg +Open File Pos3=229 +Open File Line3=0 +Open File Window Pos3=0,1,0,0,-4,-23,0,0,612,364 +Open File4=C:\Program Files\wx2\samples\Install\instsup.cpp +Open File Pos4=2 +Open File Line4=0 +Open File Window Pos4=0,1,0,0,-4,-23,154,154,788,507 +Open File5=C:\Program Files\wx2\samples\controls\controls.cpp +Open File Pos5=34608 +Open File Line5=34168 +Open File Window Pos5=2,3,0,0,-4,-23,88,88,722,437 +Open File6= +Open File Pos6=203 +Open File Line6=0 +Open File Window Pos6=0,1,0,0,-4,-23,154,154,788,502 +Open File7=C:\Program Files\wx2\src\makeg95.env +Open File Pos7=357 +Open File Line7=0 +Open File Window Pos7=0,1,0,0,-4,-23,0,0,634,348 +Open File8=c:\error.log +Open File Pos8=0 +Open File Line8=0 +Active File Index=5 +Open File Window Pos8=2,3,0,0,-4,-23,22,22,656,370 +Open File9= +Active File Display Mode=3 +[File View] +Current Select=Open Files\ diff --git a/utils/Install/sfxace/install.def b/utils/Install/sfxace/install.def new file mode 100644 index 0000000000..40e70d64c5 --- /dev/null +++ b/utils/Install/sfxace/install.def @@ -0,0 +1,3 @@ +NAME INSTALL WINDOWAPI +DESCRIPTION "Self extracting Installer (C)'99-00 Brian Smith" +STACKSIZE 51200 diff --git a/utils/Install/sfxace/install.rc b/utils/Install/sfxace/install.rc new file mode 100644 index 0000000000..82bdf07561 --- /dev/null +++ b/utils/Install/sfxace/install.rc @@ -0,0 +1,2 @@ +#include "wx/msw/wx.rc" + diff --git a/utils/Install/sfxace/makefile b/utils/Install/sfxace/makefile new file mode 100644 index 0000000000..429b74e760 --- /dev/null +++ b/utils/Install/sfxace/makefile @@ -0,0 +1,47 @@ +# Installer Makefile + +CC = gcc +RM = rm -f +RC = windres + + +DEFS = +LIBS = -lwx_gtk -lpng -ljpeg -lstdc++ -lgcc -lc_r -lgtk -lgdk -lgmodule -lglib -lXext -lX11 -lm -lgthread + +CFLAGS = -g -I.. -I../incace -I/usr/local//include -I/usr/X11R6/include -I/usr/local/lib/glib/include -DSTRICT -D__WXGTK__ -DGTK_NO_CHECK_CASTS -D_REENTRANT -D_IODBC_ -Wall +LDFLAGS = -L/usr/local/lib -L/usr/X11R6/lib -L/usr + +OBJECTS = globals.o install.o uac_comm.o uac_crc.o instsup.o \ + uac_crt.o uac_dcpr.o uac_sys.o unace.o wxmain.o + +SOURCES = globals.c ../install.c uac_comm.c uac_crc.c ../instsup.cpp \ + uac_crt.c uac_dcpr.c uac_sys.c unace.c ../wxmain.cpp + +all: sfx + +$(OBJECTS): + $(CC) $(CFLAGS) -c $< + +packinst: packinst/Makefile Makefile + @cd packinst + $(MAKE) -f Makefile all + +sfx: $(OBJECTS) + $(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o sfx $(OBJECTS) $(LIBS) + +clean: + $(RM) $(OBJECTS) install sfx *~ + +globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h +install.o: ../install.c ../install.h ../instsup.h +instsup.o: ../instsup.cpp +uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h +uac_crc.o: uac_crc.c ../incace/uac_crc.h +uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h +uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \ + ../incace/uac_dcpr.h ../incace/uac_sys.h +uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h +unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \ + ../incace/uac_dcpr.h ../incace/uac_sys.h +wxmain.o: ../wxmain.cpp + diff --git a/utils/Install/sfxace/makefile.b32 b/utils/Install/sfxace/makefile.b32 new file mode 100644 index 0000000000..f324d3be90 --- /dev/null +++ b/utils/Install/sfxace/makefile.b32 @@ -0,0 +1,76 @@ +# +# File: makefile.b32 +# Author: Julian Smart +# Created: 1999 +# Updated: +# Copyright: +# +# Makefile : Builds sample for 32-bit BC++ + +WXDIR = $(WXWIN) + +EXTRACPPFLAGS = /I"..\incace" /I".." +TARGET=sfx +OBJECTS = wxmain.obj instsup.obj install.obj globals.obj uac_comm.obj uac_crc.obj uac_crt.obj uac_dcpr.obj uac_sys.obj unace.obj + +WXDIR = $(WXWIN) +!include $(WXDIR)\src\makeb32.env + +LIBS=$(WXLIB) $(EXTRALIBS) cw32mt import32 ole2w32 winpng zlib jpeg xpm tiff odbc32 + +# Note: you may need to remove some libraries for earlier versions of BC++, as below +#LIBS=$(WXLIB) $(EXTRALIBS) cw32mt import32 ole2w32 winpng zlib xpm tiff + +!if "$(FINAL)" == "0" +#LINKFLAGS=/v /c /Tpe $(LNKCFG) $(EXTRALINKFLAGS) +LINKFLAGS=/v /c /aa -L$(WXLIBDIR);$(WXLIBDIR2);$(BCCDIR)\lib;$(BCCDIR)\lib\psdk $(EXTRALINKFLAGS) +OPT = -Od +DEBUG_FLAGS= -v +!else +#LINKFLAGS=/Tpe +$(LNKCFG) $(EXTRALINKFLAGS) +LINKFLAGS=/aa -L$(WXLIBDIR);$(WXLIBDIR2);$(BCCDIR)\lib;$(BCCDIR)\lib\psdk $(EXTRALINKFLAGS) +OPT = -O2 +DEBUG_FLAGS = +!endif + +CPPFLAGS=$(DEBUG_FLAGS) $(EXTRACPPFLAGS) $(OPT) @$(CFG) + +all: $(TARGET).exe $(EXTRATARGETS) + +$(TARGET).exe: $(OBJECTS) $(TARGET).res + $(LINK) $(LINKFLAGS) @&&! +c0w32.obj $(OBJECTS) +$(TARGET) +nul +$(LIBS) + +$(TARGET).res +! + +.$(SRCSUFF).obj: + bcc32 $(CPPFLAGS) -c {$< } + +install.obj: ..\install.c + bcc32 $(CPPFLAGS) -P- -c ..\install.c + +wxmain.obj: ..\wxmain.cpp + bcc32 $(CPPFLAGS) -P- -c ..\wxmain.cpp + +instsup.obj: ..\instsup.cpp + bcc32 $(CPPFLAGS) -P- -c ..\instsup.cpp + +.c.obj: + bcc32 $(CPPFLAGS) -P- -c {$< } + +$(TARGET).res : $(TARGET).rc $(WXDIR)\include\wx\msw\wx.rc + brc32 -r /i$(BCCDIR)\include /i$(WXDIR)\include /i$(WXDIR)\contrib\include $(TARGET) + +clean: + -erase *.obj + -erase *.exe + -erase *.res + -erase *.map + -erase *.rws + -erase *.tds + -erase *.il? + diff --git a/utils/Install/sfxace/makefile.g95 b/utils/Install/sfxace/makefile.g95 new file mode 100644 index 0000000000..2853f46219 --- /dev/null +++ b/utils/Install/sfxace/makefile.g95 @@ -0,0 +1,53 @@ +# Installer Makefile + +CC = gcc +RM = rm -f +RC = windres + + +DEFS = +LIBS = ../../../lib/libwx.a -lpng -ljpeg -lzlib -lxpm -lstdc++ -lgcc -lwinspool -lwinmm -lshell32 -lcomctl32 -lctl3d32 -lodbc32 -ladvapi32 -lole32 -loleaut32 -luuid -lodbc32 -lwsock32 + +#CFLAGS = -I./include -mno-cygwin -D_X86_=1 -DWIN32 -D_WIN32 -DWINVER=0x0400 -D__WIN95__ -D__GNUWIN32__ -D__WIN32__ -I../../include -I../../src/png -I../../src/jpeg -I../../src/zlib -I../../include/wx/msw/gnuwin32 -DSTRICT -D__WXMSW__ -D__WINDOWS__ -D__WXDEBUG__ -Wall -fno-pcc-struct-return -O2 -fno-rtti -fno-exceptions +#LDFLAGS = -mno-cygwin -Wl,--subsystem,windows -mwindows -L../../lib +CFLAGS = -g -I../incace -I.. -D_X86_=1 -DWIN32 -D_WIN32 -DWINVER=0x0400 -D__WIN95__ -D__GNUWIN32__ -D__WIN32__ -I../../../include -I../../../src/png -I../../../src/jpeg -I../../../src/zlib -I../../../include/wx/msw/gnuwin32 -DSTRICT -D__WXMSW__ -D__WINDOWS__ -D__WXDEBUG__ -Wall -fno-pcc-struct-return -O2 -fno-rtti -fno-exceptions +LDFLAGS = -Wl,--subsystem,windows -mwindows -L../../../lib + +OBJECTS = globals.o install.o uac_comm.o uac_crc.o instsup.o \ + uac_crt.o uac_dcpr.o uac_sys.o unace.o wxmain.o instres.o + +SOURCES = globals.c ../install.c uac_comm.c uac_crc.c ../instsup.cpp \ + uac_crt.c uac_dcpr.c uac_sys.c unace.c ../wxmain.cpp + +#all: sfx.exe packinst +all: sfx.exe + +$(OBJECTS): + $(CC) $(CFLAGS) -c $< + +packinst: packinst/Makefile Makefile + @cd packinst + $(MAKE) -f Makefile all + +sfx.exe: $(OBJECTS) + $(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o sfx.exe $(OBJECTS) $(LIBS) + +clean: + $(RM) $(OBJECTS) install.exe install.res sfx.exe + +instres.o: install.rc + $(RC) install.rc instres.o --include-dir ../../../include + +globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h +install.o: ../install.c ../install.h ../instsup.h +instsup.o: ../instsup.cpp +uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h +uac_crc.o: uac_crc.c ../incace/uac_crc.h +uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h +uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \ + ../incace/uac_dcpr.h ../incace/uac_sys.h +uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h +unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \ + ../incace/uac_dcpr.h ../incace/uac_sys.h +wxmain.o: ../wxmain.cpp + diff --git a/utils/Install/sfxace/makefile.gcc b/utils/Install/sfxace/makefile.gcc new file mode 100644 index 0000000000..429b74e760 --- /dev/null +++ b/utils/Install/sfxace/makefile.gcc @@ -0,0 +1,47 @@ +# Installer Makefile + +CC = gcc +RM = rm -f +RC = windres + + +DEFS = +LIBS = -lwx_gtk -lpng -ljpeg -lstdc++ -lgcc -lc_r -lgtk -lgdk -lgmodule -lglib -lXext -lX11 -lm -lgthread + +CFLAGS = -g -I.. -I../incace -I/usr/local//include -I/usr/X11R6/include -I/usr/local/lib/glib/include -DSTRICT -D__WXGTK__ -DGTK_NO_CHECK_CASTS -D_REENTRANT -D_IODBC_ -Wall +LDFLAGS = -L/usr/local/lib -L/usr/X11R6/lib -L/usr + +OBJECTS = globals.o install.o uac_comm.o uac_crc.o instsup.o \ + uac_crt.o uac_dcpr.o uac_sys.o unace.o wxmain.o + +SOURCES = globals.c ../install.c uac_comm.c uac_crc.c ../instsup.cpp \ + uac_crt.c uac_dcpr.c uac_sys.c unace.c ../wxmain.cpp + +all: sfx + +$(OBJECTS): + $(CC) $(CFLAGS) -c $< + +packinst: packinst/Makefile Makefile + @cd packinst + $(MAKE) -f Makefile all + +sfx: $(OBJECTS) + $(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o sfx $(OBJECTS) $(LIBS) + +clean: + $(RM) $(OBJECTS) install sfx *~ + +globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h +install.o: ../install.c ../install.h ../instsup.h +instsup.o: ../instsup.cpp +uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h +uac_crc.o: uac_crc.c ../incace/uac_crc.h +uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h +uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \ + ../incace/uac_dcpr.h ../incace/uac_sys.h +uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h +unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \ + ../incace/uac_dcpr.h ../incace/uac_sys.h +wxmain.o: ../wxmain.cpp + diff --git a/utils/Install/sfxace/sfx.RES b/utils/Install/sfxace/sfx.RES new file mode 100644 index 0000000000000000000000000000000000000000..09bcebd7887a75a6a5d6fa5fb08771241e46bbfb GIT binary patch literal 13744 zcmeHNO^jT{5w16H?6>}rXN@9^1z|=U5XVJ9(JBUJY%gA0F}AVS;pgH-kRKEWhM#B_ zZ2VqGBqL=d!_iWN$=}5%q~u`9Nc%)0#fO#5DdGg9L<*eZL5{>YjHmN`)!j31o@Zxm zyvBmiyEU(?yQ;dos;jzQ&xnXr0LEBAb)eh^Yzkn^DtS~Mll}6L9FSe|1fE-Eo9xDO z3iwvk_R4gRcVc`^(Ibg0y6RnWtGprKci04;_XE7_?U1rhW*}{^>=`0;Q0BSBipk2H zlAp`Z@b@y-^t3!9Ps(9=PJRqRuA>Ivquh+NlSMAYtvPOgSHBw1_jmi zLbrytlz{&9lrevS*erZJe3)-xQj-8<*6aS+j{UM99<~>shhXWgx|{6G2lr0_+O0s( z)G{q&KPxJW_9-Y+);=XEt-O8g)L^4jWc@5Rgh*vf=v(vhBgie z0yEV_!nd)z-bceH00sgQYyy-3s{trEwOtc>0@TpH2?6jRlK|2fE?2cCX~X?GAn0B} z0HPL%VM5x;o+ZQlXrD&n?TBu>b+#g-Z4~BgR8+34jn>MV8)%~mjJFf;Ius9oDO5!M zQ^O%)vM!bQXMj5w0Ju2YU;UDbUnamh+%H4xrMh{IW4)Rm8d2w4v{daGQ(2 zG3Mj9V)L)n7FcH+``Vv^g|-4~w$Mh1221$T!-#d$h<3YV2jC&ZKVL@Ms+hCYDrL*s zYDME-)Wo?0PpM!}Z2yPI{6?6lk_45hq)?f!6}H||D{Q-~R+!pWE9`u&R=BrV3+^f= zK@rBAzZX33SzgMZtR+fTZv*vqIdc}lTf!zxl*Zk15_ift86R9sU>tA<;8wsoz^X)~kRo`_0>P%gxn;DC_QRK$L-ZrwXd6X2 z8;xO!Oso3uTjO8AkAhYy2~K>PNX)D@PQr!DY1Aq;OXn}P$_tmFVoVQyYT~~iF)?rp519B}!go!4xEvpAmls}bm(IV~qRepN)s$oCSQwLI zBZEh*>O&j80l(1gkz#ug5*XBjEK@ukpQ+<-VyjUmWoO4?eYA}p#o082_p+Vh%V-;o zvjVw!CMGh zhY|^^smv{;atyI80<-}Jcok{z36n&hAwX8KYppNFp(9qg)He#IH0blZEw2jv0Y{b|;80*S6(neAjc{!2bzmpPnQVB2L zDPi{*pb01gH#oO=1Mq2A;tNfUDt=)jo^~+gLtMMb1?uAiQ3Y zkT6z}>EgKjs4ynSf}+H&*CZ}(9e`uNkN)x(GFK}|y;79f@iD25A(x1nNH=n&T}8Yq z4+7fwdep_c5#wKH+`{BU*^C2Z4mLar8?J`^BG@lXt^~MUkOWB0LlZS4Q^H+Sxm{l7 zefANYNBi-|TSi+(+h~2xM#Ey=3fRca<;!}Qn_Ncw5%0!%d*^Svm%DRVE1%%?qXOmO zr4A6N8nfropbzl?N1O)F@RHado+KK}`H3nZku*)gf)K(ef)iUG_(T;z%#{f7FIyTp zJl9{!;bs7jN&|SK0ld-h;vxD3an}&Z7-o`4!w-2vZQVwLa#$2^MUfJ~30-L^0g?8i z5|JP#-dQ})N2^hfw8P<$5V76UV-jJ_ndT(OEo)XA3wPz^w~Zb&$Xoc7wo94OGrz4cpM} z>zk7}-b29x-8*93?4a{+BmiKrE}#uab&FJyA25Gr9?g6@Y~t)m0SQJXEK#_jNy9uo zN^Ne>9G{s@40+gjyqCzvz72XOz6+T*zY#hlk08I}_fP&iB1l9TjD5_cE0rQXZ&Qy7 za(-nU=H~bnmE0?sd9Th&T_$un_5-Bh*-S|qjV&4U?3ri~KkM-`@@u7w>X!Z;Sx5X# zRJZaR{!T+I?&uTj1*><;g#hb`+Xc|Xbe2H$n*A5qi#h<@`0zB2gfD^>Uk{RMC8 zg1m!%!SU^GQV6$SN*rY+xqi7%=xL!UsfngA@ z3&>9?$t7iAw?XyfDT9wqb>OEAtN7-E0<<4h+qkK*8C|SvH%2551ceocgFt0^oCNG% z3eVGn+{vqN1{b>hc$}Zs**0Xpy4?PH#$|B5dHqnG5aSETmBHa}63ysayZamt6>;`b zYRdw9y58Q|l&DW+&!(sep9A>wX}L3sqP;I>&#DMAN`T&Z#apuMc{K?}WAc8*J3VIU zOMRD-KdZu=PZc3`@LlSg9PnClK<;rAp96M~Gco7NRQEI0l;odfexL9``xl zHR2$*@>@0s)Uo*Ca=;$$azHb$DW5^mw>hliZvjVmXNIWqxJhi1*h>*X@RiR2@58FD z^eKLuu>(G3%jn#%nDeJq%5*c&C^v2Q@W+os@hal-AluNWW2g2xB7J4*EDL#1-m2=tUD_pu-(|e=tk~X@+*!k9@*jWc?9f89eX(PM$q?h zbTaqs^L!U%Xs_4~*WMhE|w=X&%NOHKb*@Jd6b=?&6(?H;8a?>M?F2za#j1 ziZjRKq#-SN^z6~P{T&j|BM;h_K)-|(aOaFT+f0k9y6^K3SusbHWL$GJL+qdIRjyv_?-mYZ-;J)My zDZ%eczkkt`D+?m{mxTrUz$dDD$F|(QY}E0R0@eoKUGS{)t;I^WQ5=Z&;}BpJwAA_p zsXiO7UHP)>+^%`&0r=+NN^izGdlR>pbyz1>%=vr3^0e-suHDn2SJ&&`@M_4=Z7eIm zg8bd_3|4s%_0el(47>&4ZTbP~zKo+nu;n^z3M1Kq^-bsNznVHuo3edwy0Me>Db!!W z|8dlJqJw?Yq}ho!^0WTZ6q{`wk9yRvztXQ`!vY~aNKU`qr&-&l(LLwq01DDiPlG`V ze%{CVxO#T})cGWoLm%qvdkzZw~l-?dAR8%eP0y z_cMDiyEn6YwvpM(gR$Z|?C}NtM(yF|toF#-)yW(lm!7~W|Nj%0U}5Z9jr-IPKhiYM>!(jg1lvv;+pdww)8pmS%DI}jw3OcMS-iX-d=1WFjTBDT8NE~I4d|Y_9?&~< PPVc(HPCYqSqxb&-^+!7H literal 0 HcmV?d00001 diff --git a/utils/Install/sfxace/sfx.rc b/utils/Install/sfxace/sfx.rc new file mode 100644 index 0000000000..82bdf07561 --- /dev/null +++ b/utils/Install/sfxace/sfx.rc @@ -0,0 +1,2 @@ +#include "wx/msw/wx.rc" + diff --git a/utils/Install/sfxace/uac_comm.c b/utils/Install/sfxace/uac_comm.c new file mode 100644 index 0000000000..bcea08f4c8 --- /dev/null +++ b/utils/Install/sfxace/uac_comm.c @@ -0,0 +1,51 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* Decompresses and outputs comment if present. */ +/* */ +/* ------------------------------------------------------------------------ */ + +#include // printf() + +#include "globals.h" +#include "uac_dcpr.h" +#include "uac_comm.h" + +INT comm_cpr_size=0; +CHAR *comm; + +void comment_out(CHAR *top) // outputs comment if present +{ + INT i; + + if (head.HEAD_FLAGS & ACE_COMM) + { // comment present? + if (head.HEAD_TYPE == MAIN_BLK) + { // get begin and size of comment data + comm = (CHAR*)MCOMM; + comm_cpr_size = MCOMM_SIZE; + } + else + { + comm = (CHAR*)FCOMM; + comm_cpr_size = FCOMM_SIZE; + } // limit comment size if too big + i = sizeof(head) - (INT)(comm - (CHAR*) &head); + if (comm_cpr_size > i) + comm_cpr_size = i; + dcpr_comm(i); // decompress comment + +#ifdef AMIGA + { + char *p=comm; + while (*p) + { + if (*p==0x0D) + *p=0x0A; // Replace ms-dos line termination + p++; + } + } +#endif + + pipeit("%s\n\n%s\n\n", top, comm); // output comment + } +} diff --git a/utils/Install/sfxace/uac_crc.c b/utils/Install/sfxace/uac_crc.c new file mode 100644 index 0000000000..3d9335ec72 --- /dev/null +++ b/utils/Install/sfxace/uac_crc.c @@ -0,0 +1,36 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* CRC-calculation routines. */ +/* */ +/* ------------------------------------------------------------------------ */ + +#include "uac_crc.h" + + +ULONG crctable[256]; +ULONG rd_crc=0; + + +void make_crctable(void) // initializes CRC table +{ + ULONG r, + i, + j; + + for (i = 0; i <= 255; i++) + { + for (r = i, j = 8; j; j--) + r = (r & 1) ? (r >> 1) ^ CRCPOLY : (r >> 1); + crctable[i] = r; + } +} + +// Updates crc from addr till addr+len-1 +// +ULONG getcrc(ULONG crc, UCHAR * addr, INT len) +{ + while (len--) + crc = crctable[(unsigned char) crc ^ (*addr++)] ^ (crc >> 8); + return (crc); +} + diff --git a/utils/Install/sfxace/uac_crt.c b/utils/Install/sfxace/uac_crt.c new file mode 100644 index 0000000000..6a6acdb792 --- /dev/null +++ b/utils/Install/sfxace/uac_crt.c @@ -0,0 +1,303 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* Creates/Replaces files or directories. */ +/* */ +/* ------------------------------------------------------------------------ */ + +#include "os.h" + +#ifdef __EMX__ +#include +#include +#include +#endif +#include +#include // printf() remove() +#include // strncpy() +#include +#include // struct stat +#include +#include "install.h" + +#if defined(DOS) || defined(WINNT) || defined(WIN16) + #include // access() +#endif +#if defined(__CYGWIN__) +#include +#endif + +#include "attribs.h" +#include "globals.h" +#include "uac_crt.h" +#include "uac_sys.h" + +#ifdef ENABLE_LOGGING +extern FILE *logfile; +#endif +extern char installdir[400]; + +/* Undocumented functions */ +#if defined(__OS2__) || defined(__EMX__) +APIRET APIENTRY DosReplaceModule(PSZ pszOldModule,PSZ pszNewModule,PSZ pszBackupModule); +#endif + + +/* gets file name from header + */ +CHAR *ace_fname(CHAR * s, thead * head, INT nopath) +{ + INT i; + char *cp; + + strncpy(s, (CHAR*)(*(tfhead *) head).FNAME, i = (*(tfhead *) head).FNAME_SIZE); + s[i] = 0; + + if (nopath) + { + cp=strrchr(s, '\\'); + if (cp) + memmove(s, cp+1, strlen(cp)); + } +#ifdef __UNIX__ + else + { // by current OS seperator + cp=s; + while ((cp=strchr(cp, '\\'))!=NULL) + *cp++='/'; + } +#endif + + return s; +} + +void check_ext_dir(CHAR * f) // checks/creates path of file +{ + char d[1024]; + char buffer[1024]; + int z, flag = 0, len = strlen(f); + + strcpy(buffer, f); + for(z=len;z>-1;z--) + { + if(buffer[z] == '\\') + { + buffer[z+1] = 0; + flag = 1; + z = -1; + } + } + if(!flag) + return; + for(z=0;z 1 && d[1] == ':') + fprintf(logfile, ",%s\r\n", d); + else + { + if(installdir[strlen(installdir)-1] == '\\') + fprintf(logfile, ",%s%s\r\n", installdir, d); + else + fprintf(logfile, ",%s\\%s\r\n", installdir, d); + } + } +#endif + } + } + } + } + + } +} + +INT ovr_delete(CHAR * n) // deletes directory or file +{ + if (remove(n) && rmdir(n)) + { +#if defined(__OS2__) || defined(__EMX__) + DosReplaceModule(n, NULL, NULL); +#endif + if (remove(n) && rmdir(n)) + { + error("Could not delete file or directory: \"%s\" Access denied.", n); + return (1); + } + } + return (0); +} + +INT create_dest_file(CHAR * file, INT a) // creates file or directory +{ + INT han, + i = 0, + ex = fileexists(file); + struct stat st; + extern int no_update; + + check_ext_dir(file); + if (f_err) + return (-1); + if (a & _A_SUBDIR) + { // create dir or file? + if (ex) + { + stat(file, &st); + } + +#if (defined(__OS2__) && !defined(__EMX__)) || (!defined(__CYGWIN__) && defined(WINNT)) + if ((!ex && mkdir(file)) || (ex && (st.st_mode & S_IFDIR))) +#else + if ((!ex && mkdir(file, 0)) || (ex && (st.st_mode & S_IFDIR))) +#endif + { + error("Could not create directory %s."); + return (-1); + } + else + { /* I wonder why it never gets here... :/ BS */ +#ifdef ENABLE_LOGGIN + if(logfile) + fprintf(logfile, ",%s\\%s\r\n", installdir, file); +#endif + } + +#ifdef DOS + _dos_setfileattr(file, a); // set directory attributes +#endif + return (-1); + } + else + { + if (ex) + { // does the file already exist +#if defined(__OS2_) || defined(__EMX__) + static int sddall = 0; + FILESTATUS3 fileinfo; + + f_ovrall = 1; + + DosQueryPathInfo(file, FIL_STANDARD, &fileinfo, sizeof(FILESTATUS3)); + if(!sddall) + { + FDATE fdate; + FTIME ftime; + struct tm tc, tc2; + time_t tt, tt2; + + *((USHORT*)&fdate) = (USHORT)(fhead.FTIME >> 16); + *((USHORT*)&ftime) = (USHORT)fhead.FTIME; + + tc.tm_year = fileinfo.fdateLastWrite.year + 80; + tc.tm_mon = fileinfo.fdateLastWrite.month - 1; + tc.tm_mday = fileinfo.fdateLastWrite.day; + tc.tm_hour = fileinfo.ftimeLastWrite.hours; + tc.tm_min = fileinfo.ftimeLastWrite.minutes; + tc.tm_sec = fileinfo.ftimeLastWrite.twosecs * 2; + + tc2.tm_year = fdate.year + 80; + tc2.tm_mon = fdate.month - 1; + tc2.tm_mday = fdate.day; + tc2.tm_hour = ftime.hours; + tc2.tm_min = ftime.minutes; + tc2.tm_sec = ftime.twosecs * 2; + + if((tt = mktime(&tc)) == -1 || (tt2 = mktime(&tc2)) == -1 || tt > tt2) + { + + if(file[1] == ':') + i = confirm("File \"%s\" has a newer modification time. Overwrite?", file); // prompt for overwrite + else + { + if(installdir[strlen(installdir)-1] == '\\') + i = confirm("File \"%s%s\" has a newer modification time. Overwrite?", installdir, file); // prompt for overwrite + else + i = confirm("File \"%s\\%s\" has a newer modification time. Overwrite?", installdir, file); // prompt for overwrite + } + if(i == 1) + { + sddall = 1; + i = 0; + } + if (i == 3) + f_err = ERR_USER; + if(i) + return -1; + } + } + fileinfo.attrFile = FILE_NORMAL; + DosSetPathInfo(file, FIL_STANDARD, (PVOID)&fileinfo, sizeof(FILESTATUS3), 0); +#endif + if (!f_ovrall) + { + if(installdir[strlen(installdir)-1] == '\\') + i = confirm("Overwrite file \"%s%s\"?", installdir, file); // prompt for overwrite + else + i = confirm("Overwrite file \"%s\\%s\"?", installdir, file); // prompt for overwrite + f_ovrall = (i == 1); + if (i == 3) + f_err = ERR_USER; + } + if ((i && !f_ovrall) || ovr_delete(file)) + return (-1); // delete? + } +#if defined(__OS2_) || defined(__EMX__) || defined(WIN32) + if ((han = open(file, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, + S_IREAD | S_IWRITE | S_IEXEC | S_IDELETE | + S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH )) < 0) +#else + if ((han = open(file, O_WRONLY | O_TRUNC | O_CREAT, + S_IREAD | S_IWRITE | S_IEXEC | S_IDELETE | + S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH )) < 0) +#endif + error("Could not create destination file \"%s\".", file); + else + { +#ifdef ENABLE_LOGGING + if(logfile) + { + if(!no_update) + { + if(strlen(file) > 1 && file[1] == ':') + fprintf(logfile, ",%s\r\n", file); + else + { + if(installdir[strlen(installdir)-1] == '\\') + fprintf(logfile, ",%s%s\r\n", installdir, file); + else + fprintf(logfile, ",%s\\%s\r\n", installdir, file); + } + } + } +#endif + } + + return (han); + } +} + diff --git a/utils/Install/sfxace/uac_dcpr.c b/utils/Install/sfxace/uac_dcpr.c new file mode 100644 index 0000000000..d6703428ca --- /dev/null +++ b/utils/Install/sfxace/uac_dcpr.c @@ -0,0 +1,554 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* These are the decompression algorithms. */ +/* Don't change here anything (apart from memory allocation perhaps). */ +/* Any changes will very likely cause bugs! */ +/* */ +/* ------------------------------------------------------------------------ */ + +#include "os.h" + +#if defined(AMIGA) + #include // mem*() +#endif +#if defined(DOS) || defined(WIN16) || defined(WINNT) || defined(OS2) || defined(UNIX) +#if !defined(__CYGWIN__) + #include // mem*() +#endif +#endif + +#include // printf() +#include // malloc() +#include + + +#include "globals.h" +#include "portable.h" +#include "uac_comm.h" +#include "uac_crc.h" +#include "uac_dcpr.h" +#include "uac_sys.h" +#ifdef CRYPT + #include "unace_ps.h" +#endif /* CRYPT */ + + +//------------------------------ QUICKSORT ---------------------------------// +#define xchg_def(v1,v2) {INT dummy;\ + dummy=v1; \ + v1=v2; \ + v2=dummy;} + +void sortrange(INT left, INT right) +{ + INT zl = left, + zr = right, + hyphen; + + hyphen = sort_freq[right]; + + //divides by hyphen the given range into 2 parts + do + { + while (sort_freq[zl] > hyphen) + zl++; + while (sort_freq[zr] < hyphen) + zr--; + //found a too small (left side) and + //a too big (right side) element-->exchange them + if (zl <= zr) + { + xchg_def(sort_freq[zl], sort_freq[zr]); + xchg_def(sort_org[zl], sort_org[zr]); + zl++; + zr--; + } + } + while (zl < zr); + + //sort partial ranges - when very small, sort directly + if (left < zr) + { + if (left < zr - 1) + sortrange(left, zr); + else if (sort_freq[left] < sort_freq[zr]) + { + xchg_def(sort_freq[left], sort_freq[zr]); + xchg_def(sort_org[left], sort_org[zr]); + } + } + + if (right > zl) + { + if (zl < right - 1) + sortrange(zl, right); + else if (sort_freq[zl] < sort_freq[right]) + { + xchg_def(sort_freq[zl], sort_freq[right]); + xchg_def(sort_org[zl], sort_org[right]); + } + } +} + +void quicksort(INT n) +{ + INT i; + + for (i = n + 1; i--;) + sort_org[i] = i; + sortrange(0, n); +} + +//------------------------------ read bits ---------------------------------// +void readdat(void) +{ + UINT i; + + i = (size_rdb - 2) << 2; + rpos -= size_rdb - 2; + buf_rd[0] = buf_rd[size_rdb - 2]; + buf_rd[1] = buf_rd[size_rdb - 1]; + read_adds_blk((CHAR *) & buf_rd[2], i); +#ifdef HI_LO_BYTE_ORDER + { + ULONG *p; + i>>=2; // count LONGs not BYTEs + p=&buf_rd[2]; + while (i--) + { + LONGswap(p); + p++; + } + } +#endif +} + +#define addbits(bits) \ +{ \ + rpos+=(bits_rd+=bits)>>5; \ + bits_rd&=31; \ + if (rpos==(size_rdb-2)) readdat(); \ + code_rd=(buf_rd[rpos] << bits_rd) \ + +((buf_rd[rpos+1] >> (32-bits_rd))&(!bits_rd-1)); \ + } + + +//---------------------- COMMENT DECOMPRESSION -----------------------------// + +#define comm_cpr_hf(a,b) (a+b) + +void dcpr_comm_init(void) +{ + INT i; + + i = comm_cpr_size > size_rdb * sizeof(LONG) ? size_rdb * sizeof(LONG) : comm_cpr_size; + if (!f_err) + memcpy(buf_rd, comm, i); +#ifdef HI_LO_BYTE_ORDER + { + ULONG *p; + i>>=2; // count LONGs not BYTEs + p=buf_rd; + while (i--) + { + LONGswap(p); + p++; + } + } +#endif + code_rd = buf_rd[0]; + rpos = bits_rd = 0; +} + +void dcpr_comm(INT comm_size) +{ + SHORT hash[comm_cpr_hf(255, 255) + 1]; + INT dpos = 0, + c, + pos = 0, + len, + hs; + + memset(&hash, 0, sizeof(hash)); + if (comm_cpr_size) + { + dcpr_comm_init(); + len = code_rd >> (32 - 15); + addbits(15); + if (len >= comm_size) + len = comm_size - 1; + if (read_wd(maxwd_mn, dcpr_code_mn, dcpr_wd_mn, max_cd_mn)) + do + { + if (dpos > 1) + { + pos = hash[hs = comm_cpr_hf(comm[dpos - 1], comm[dpos - 2])]; + hash[hs] = dpos; + } + addbits(dcpr_wd_mn[(c = dcpr_code_mn[code_rd >> (32 - maxwd_mn)])]); + if (rpos == size_rdb - 3) + rpos = 0; + if (c > 255) + { + c -= 256; + c += 2; + while (c--) + comm[dpos++] = comm[pos++]; + } + else + { + comm[dpos++] = c; + } + } + while (dpos < len); + comm[len] = 0; + } +} + +//------------------------- LZW1 DECOMPRESSION -----------------------------// +void wrchar(CHAR ch) +{ + dcpr_do++; + + dcpr_text[dcpr_dpos] = ch; + dcpr_dpos++; + dcpr_dpos &= dcpr_dican; +} + +void copystr(LONG d, INT l) +{ + INT mpos; + + dcpr_do += l; + + mpos = dcpr_dpos - d; + mpos &= dcpr_dican; + + if ((mpos >= dcpr_dicsiz - maxlength) || (dcpr_dpos >= dcpr_dicsiz - maxlength)) + { + while (l--) + { + dcpr_text[dcpr_dpos] = dcpr_text[mpos]; + dcpr_dpos++; + dcpr_dpos &= dcpr_dican; + mpos++; + mpos &= dcpr_dican; + } + } + else + { + while (l--) + dcpr_text[dcpr_dpos++] = dcpr_text[mpos++]; + dcpr_dpos &= dcpr_dican; + } +} + +void decompress(void) +{ + INT c, + lg, + i, + k; + ULONG dist; + + while (dcpr_do < dcpr_do_max) + { + if (!blocksize) + if (!calc_dectabs()) + return; + + addbits(dcpr_wd_mn[(c = dcpr_code_mn[code_rd >> (32 - maxwd_mn)])]); + blocksize--; + if (c > 255) + { + if (c > 259) + { + if ((c -= 260) > 1) + { + dist = (code_rd >> (33 - c)) + (1L << (c - 1)); + addbits(c - 1); + } + else + dist = c; + dcpr_olddist[(dcpr_oldnum = (dcpr_oldnum + 1) & 3)] = dist; + i = 2; + if (dist > maxdis2) + { + i++; + if (dist > maxdis3) + i++; + } + } + else + { + dist = dcpr_olddist[(dcpr_oldnum - (c &= 255)) & 3]; + for (k = c + 1; k--;) + dcpr_olddist[(dcpr_oldnum - k) & 3] = dcpr_olddist[(dcpr_oldnum - k + 1) & 3]; + dcpr_olddist[dcpr_oldnum] = dist; + i = 2; + if (c > 1) + i++; + } + addbits(dcpr_wd_lg[(lg = dcpr_code_lg[code_rd >> (32 - maxwd_lg)])]); + dist++; + lg += i; + copystr(dist, lg); + } + else + wrchar(c); + } +} + +//-------------------------- HUFFMAN ROUTINES ------------------------------// +INT makecode(UINT maxwd, UINT size1_t, UCHAR * wd, USHORT * code) +{ + UINT maxc, + size2_t, + l, + c, + i, + max_make_code; + + memcpy(&sort_freq, wd, (size1_t + 1) * sizeof(CHAR)); + if (size1_t) + quicksort(size1_t); + else + sort_org[0] = 0; + sort_freq[size1_t + 1] = size2_t = c = 0; + while (sort_freq[size2_t]) + size2_t++; + if (size2_t < 2) + { + i = sort_org[0]; + wd[i] = 1; + size2_t += (size2_t == 0); + } + size2_t--; + + max_make_code = 1 << maxwd; + for (i = size2_t + 1; i-- && c < max_make_code;) + { + maxc = 1 << (maxwd - sort_freq[i]); + l = sort_org[i]; + if (c + maxc > max_make_code) + { + dcpr_do = dcpr_do_max; + return (0); + } + memset16(&code[c], l, maxc); + c += maxc; + } + return (1); +} + +INT read_wd(UINT maxwd, USHORT * code, UCHAR * wd, INT max_el) +{ + UINT c, + i, + j, + num_el, + l, + uplim, + lolim; + + memset(wd, 0, max_el * sizeof(CHAR)); + memset(code, 0, (1 << maxwd) * sizeof(SHORT)); + + num_el = code_rd >> (32 - 9); + addbits(9); + if (num_el > max_el) + num_el = max_el; + + lolim = code_rd >> (32 - 4); + addbits(4); + uplim = code_rd >> (32 - 4); + addbits(4); + + for (i = -1; ++i <= uplim;) + { + wd_svwd[i] = code_rd >> (32 - 3); + addbits(3); + } + if (!makecode(maxwd_svwd, uplim, wd_svwd, code)) + return (0); + j = 0; + while (j <= num_el) + { + c = code[code_rd >> (32 - maxwd_svwd)]; + addbits(wd_svwd[c]); + if (c < uplim) + wd[j++] = c; + else + { + l = (code_rd >> 28) + 4; + addbits(4); + while (l-- && j <= num_el) + wd[j++] = 0; + } + } + if (uplim) + for (i = 0; ++i <= num_el;) + wd[i] = (wd[i] + wd[i - 1]) % uplim; + for (i = -1; ++i <= num_el;) + if (wd[i]) + wd[i] += lolim; + + return (makecode(maxwd, num_el, wd, code)); + +} + +INT calc_dectabs(void) +{ + if (!read_wd(maxwd_mn, dcpr_code_mn, dcpr_wd_mn, max_cd_mn) + || !read_wd(maxwd_lg, dcpr_code_lg, dcpr_wd_lg, max_cd_lg)) + return (0); + + blocksize = code_rd >> (32 - 15); + addbits(15); + + return (1); +} + +//---------------------------- BLOCK ROUTINES ------------------------------// +INT decompress_blk(CHAR * buf, UINT len) +{ + LONG old_pos = dcpr_dpos; + INT i; + + dcpr_do = 0; + if ((dcpr_do_max = len - maxlength) > dcpr_size) + dcpr_do_max = dcpr_size; + if ((LONG) dcpr_size > 0 && dcpr_do_max) + { + decompress(); + if (old_pos + dcpr_do > dcpr_dicsiz) + { + i = dcpr_dicsiz - old_pos; + memcpy(buf, &dcpr_text[old_pos], i); + memcpy(&buf[i], dcpr_text, dcpr_do - i); + } + else + memcpy(buf, &dcpr_text[old_pos], dcpr_do); + } + dcpr_size -= dcpr_do; + return (dcpr_do); +} + +INT unstore(CHAR * buf, UINT len) +{ + UINT rd = 0, + i, + pos = 0; + +#ifdef CRYPT + len = crypt_len(len - 8); /* because of decryption */ +#endif /* CRYPT */ + + while ((i = read_adds_blk((CHAR *) buf_rd, (INT) ((i = ((len > dcpr_size) ? dcpr_size : len)) > size_rdb ? size_rdb : i))) != 0) + { + rd += i; + len -= i; + memcpy(&buf[pos], buf_rd, i); + pos += i; + } + dcpr_size -= rd; + for (i = 0; i < rd; i++) + { + dcpr_text[dcpr_dpos] = buf[i]; + dcpr_dpos++; + dcpr_dpos &= dcpr_dican; + } + return (INT)rd; +} + +INT dcpr_adds_blk(CHAR * buf, UINT len) +{ + INT r; + + switch (fhead.TECH.TYPE) + { + case TYPE_STORE: + r = unstore(buf, len); + break; + case TYPE_LZW1: + r = decompress_blk(buf, len); + break; + default: + error("\nFile compressed with unknown method. Decompression not possible.\n"); + f_err = ERR_OTHER; + r = 0; + } + rd_crc = getcrc(rd_crc, (UCHAR*)buf, r); + return r; +} + + +//----------------------------- INIT ROUTINES ------------------------------// +void dcpr_init(void) +{ + dcpr_frst_file = 1; + + dcpr_dic = 20; + while ((dcpr_text = malloc(dcpr_dicsiz = (LONG) 1 << dcpr_dic))==NULL) + dcpr_dic--; + dcpr_dican = dcpr_dicsiz - 1; +} + +void dcpr_init_file(void) +{ + UINT i; + +#ifdef CRYPT + + reset_cryptkey(); + +#else /* CRYPT */ + + if (head.HEAD_FLAGS & ACE_PASSW) + { + error("\nFound passworded file. Decryption not supported.\n"); + f_err = ERR_OTHER; + return; + } + +#endif /* CRYPT */ + + rd_crc = CRC_MASK; + dcpr_size = fhead.SIZE; + if (fhead.TECH.TYPE == TYPE_LZW1) + { + if ((fhead.TECH.PARM & 15) + 10 > dcpr_dic) + { + error("\nNot enough memory or dictionary of archive too large.\n"); + f_err = ERR_MEM; + return; + } + + i = size_rdb * sizeof(LONG); + read_adds_blk((CHAR *) buf_rd, i); +#ifdef HI_LO_BYTE_ORDER + { + ULONG *p; + i>>=2; // count LONGs not BYTEs + p=buf_rd; + while (i--) + { + LONGswap(p); + p++; + } + } +#endif + code_rd = buf_rd[0]; + bits_rd = rpos = 0; + + blocksize = 0; + } + if (!adat.sol || dcpr_frst_file) + dcpr_dpos = 0; + + dcpr_oldnum = 0; + memset(&dcpr_olddist, 0, sizeof(dcpr_olddist)); + + dcpr_frst_file = 0; +} + diff --git a/utils/Install/sfxace/uac_sys.c b/utils/Install/sfxace/uac_sys.c new file mode 100644 index 0000000000..d31e961ea1 --- /dev/null +++ b/utils/Install/sfxace/uac_sys.c @@ -0,0 +1,96 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* Some basic things. */ +/* */ +/* ------------------------------------------------------------------------ */ + +#include "os.h" + +#include // signal() +#include // fprintf() fflush() getch() putc() + +#include "globals.h" +#include "uac_sys.h" + + +void memset16(USHORT * dest, SHORT val, INT len) // fills short-array with +{ // value + while (len--) + *(dest++) = val; +} + +INT cancel(void) // checks whether to interrupt the program +{ +#ifdef DOS + while (kbhit()) + { + if (getch() == 27) + f_err = ERR_USER; + } +#endif + return (f_err); +} + +/*INT wrask(CHAR * s) // prompt-routine +{ + INT ch; + + fprintf(stderr, "\n %s (Yes,Always,No,Cancel) ", s); + fflush(stderr); + do + { + ch = getch(); + ch = upcase(ch); + } + while (ch != 'Y' && ch != 'A' && ch != 'N' && ch != 'C' && ch != 27); + fprintf(stderr, "%s", ch == 'Y' ? "Yes" : (ch == 'A' ? "Always" : (ch == 'N' ? "No" : "Cancel"))); + fflush(stderr); + return (ch == 'Y' ? 0 : (ch == 'A' ? 1 : (ch == 'N' ? 2 : 3))); +} */ + +void beep(void) // makes some noise +{ +#ifdef DOS + sound(800); + delay(250); + nosound(); +#endif +#ifdef AMIGA + putc(0x07, stderr); +#endif +} + +void my_signalhandler(INT sig_number) // sets f_err if ctrl+c or ctrl+brk +{ + f_err = ERR_USER; + error("\nUser break\n"); +} + +#ifdef DOS // handles hardware errors +#ifdef __BORLANDC__ +INT harderrhandler(UINT deverr, UINT errc, UINT * devhdr) +#else +INT __far harderrhandler(UINT deverr, UINT errc, UINT * devhdr) +#endif +{ + f_criterr = 'A' + deverr & 0xff; + f_err = ERR_OTHER; + return (0x3); +} +#endif + +void set_handler(void) // initializes handlers +{ +#if defined(DOS) && !defined(__BORLANDC__) + signal(SIGBREAK, my_signalhandler); // set ctrl-break/-c handlers +#endif + signal(SIGINT, my_signalhandler); +#if defined(DOS) && !defined(__CONSOLE__) // set hardware error handler +#ifdef __BORLANDC__ + harderr(harderrhandler); +#else + _harderr(harderrhandler); +#endif +#endif +} + diff --git a/utils/Install/sfxace/unace.c b/utils/Install/sfxace/unace.c new file mode 100644 index 0000000000..f08bdf58ac --- /dev/null +++ b/utils/Install/sfxace/unace.c @@ -0,0 +1,555 @@ +/* ------------------------------------------------------------------------ */ +/* */ +/* Main file of public UNACE. */ +/* */ +/* ------------------------------------------------------------------------ */ + + +#define INCL_WIN /* Window Manager Functions */ +#define INCL_DOS +#define INCL_BASE + + +//--------------- include general files ------------------------------------// +#include // tolower() +#include // open() +#include // printf() sprintf() remove() +#include // malloc() +#include // str*() +#include +#include // S_I* AMIGA: fstat() +#if (!defined(__EMX__) && !defined(__OS2__) && !defined(WINNT) && !defined(WIN32)) || defined(__CYGWIN__) +#include +#endif + +#if !defined(__EMX__) && !defined(__OS2__) && !defined(WIN32) && !defined(WINNT) +#define stricmp strcasecmp +#endif + +#include "install.h" +#include "instsup.h" +extern int installstate; + +off_t acelseek(off_t offset, int whence); +int aceread(void *buf, size_t count); +int aceopen(const char *path, int flags); +int aceclose(int fd); +int acesize(void); +int acetell(int fd); +char *replacestr(char *str1, char *str2, char *str3); + +//--------------- include unace specific header files ----------------------// +#include "os.h" + +#include "globals.h" +#include "portable.h" +#include "uac_comm.h" +#include "uac_crc.h" +#include "uac_crt.h" +#include "uac_dcpr.h" +#include "uac_sys.h" + +#ifdef CRYPT + #include "unace_ps.h" +#endif /* CRYPT */ + + + + +//--------------- BEGIN OF UNACE ROUTINES ----------------------------------// + +int pipeit(char *format, ...) +{ + /* Do nothing ... perhaps pipe this somewhere in the future */ + return 0; +} + +void init_unace(void) // initializes unace +{ + buf_rd =malloc(size_rdb * sizeof(ULONG)); // Allocate buffers: increase + buf =malloc(size_buf); // sizes when possible to speed + buf_wr =malloc(size_wrb); // up the program + readbuf=malloc(size_headrdb); + + if (buf_rd ==NULL || + buf ==NULL || + buf_wr ==NULL || + readbuf==NULL ) + f_err = ERR_MEM; + + make_crctable(); // initialize CRC table + dcpr_init(); // initialize decompression + + set_handler(); // ctrl+break etc. +} + +void done_unace(void) +{ + if (buf_rd ) free(buf_rd ); + if (buf ) free(buf ); + if (buf_wr ) free(buf_wr ); + if (readbuf ) free(readbuf ); + if (dcpr_text) free(dcpr_text); +} + +INT read_header(INT print_err) // reads any header from archive +{ + USHORT rd, + head_size, + crc_ok; + LONG crc; + UCHAR *tp=readbuf; + + acelseek(skipsize, SEEK_CUR); // skip ADDSIZE block + + if (aceread(&head, 4)<4) + return (0); // read CRC and header size + +#ifdef HI_LO_BYTE_ORDER + WORDswap(&head.HEAD_CRC); + WORDswap(&head.HEAD_SIZE); +#endif + // read size_headrdb bytes into + head_size = head.HEAD_SIZE; // header structure + rd = (head_size > size_headrdb) ? size_headrdb : head_size; + if (aceread(readbuf, rd) < rd) + return (0); + head_size -= rd; + crc = getcrc(CRC_MASK, readbuf, rd); + + while (head_size) // skip rest of header + { + rd = (head_size > size_buf) ? size_buf : head_size; + if (aceread(buf, rd) < rd) + return (0); + head_size -= rd; + crc = getcrc(crc, (UCHAR*)buf, rd); + } + + head.HEAD_TYPE =*tp++; // generic buffer to head conversion + head.HEAD_FLAGS=BUFP2WORD(tp); + + if (head.HEAD_FLAGS & ACE_ADDSIZE) + skipsize = head.ADDSIZE = BUF2LONG(tp); // get ADDSIZE + else + skipsize = 0; + + // check header CRC + if (!(crc_ok = head.HEAD_CRC == (crc & 0xffff)) && print_err) + pipeit("\nError: archive is broken\n"); + else + switch (head.HEAD_TYPE) // specific buffer to head conversion + { + case MAIN_BLK: + memcpy(mhead.ACESIGN, tp, acesign_len); tp+=acesign_len; + mhead.VER_MOD=*tp++; + mhead.VER_CR =*tp++; + mhead.HOST_CR=*tp++; + mhead.VOL_NUM=*tp++; + mhead.TIME_CR=BUFP2LONG(tp); + mhead.RES1 =BUFP2WORD(tp); + mhead.RES2 =BUFP2WORD(tp); + mhead.RES =BUFP2LONG(tp); + mhead.AV_SIZE=*tp++; + memcpy(mhead.AV, tp, rd-(USHORT)(tp-readbuf)); + break; + case FILE_BLK: + fhead.PSIZE =BUFP2LONG(tp); + fhead.SIZE =BUFP2LONG(tp); + fhead.FTIME =BUFP2LONG(tp); + fhead.ATTR =BUFP2LONG(tp); + fhead.CRC32 =BUFP2LONG(tp); + fhead.TECH.TYPE =*tp++; + fhead.TECH.QUAL =*tp++; + fhead.TECH.PARM =BUFP2WORD(tp); + fhead.RESERVED =BUFP2WORD(tp); + fhead.FNAME_SIZE=BUFP2WORD(tp); + memcpy(fhead.FNAME, tp, rd-(USHORT)(tp-readbuf)); + break; + // default: (REC_BLK and future things): + // do nothing 'cause isn't needed for extraction + } + + return (crc_ok); +} +// maximum SFX module size +#define max_sfx_size 65536 // (needed by read_arc_head) + +INT read_arc_head(void) // searches for the archive header and reads it +{ + INT i, + flags, + buf_pos = 0; + LONG arc_head_pos, + old_fpos, + fpos = 0; + struct stat st; + + fstat(archan, &st); + + memset(buf, 0, size_buf); + + while (acetell(archan) 0; + adat.vol = (flags & ACE_MULT_VOL) > 0; + adat.vol_num = mhead.VOL_NUM; + adat.time_cr = mhead.TIME_CR; + return (1); + } + } + } + // was no archive header, + // continue search + acelseek(fpos, SEEK_SET); + memcpy(buf, &buf[size_buf - 512], 512); + buf_pos = 512; // keep 512 old bytes + } + return (0); +} + +INT open_archive(INT print_err) // opens archive (or volume) +{ + CHAR av_str[80]; + +#if defined(__OS2_) || defined(__EMX__) || defined(WIN32) + archan = aceopen(aname, O_RDONLY | O_BINARY); // open file +#else + archan = aceopen(aname, O_RDONLY); // open file +#endif +#if !defined(__EMX__) && !defined(__OS2__) + farchan = fdopen(archan, "rb"); +#endif + + if (archan == -1) + { + error("\nError opening file %s", aname); + return (0); + } + if (!read_arc_head()) // read archive header + { + error("Invalid embedded archive file."); +#if !defined(__EMX__) && !defined(__OS2__) + fclose(farchan); +#endif + aceclose(archan); + return (0); + } + + pipeit("\nProcessing archive: %s\n\n", aname); + if (head.HEAD_FLAGS & ACE_AV) + { + pipeit("Authenticity Verification:"); // print the AV + sprintf(av_str, "\ncreated on %d.%d.%d by ", + ts_day(adat.time_cr), ts_month(adat.time_cr), ts_year(adat.time_cr)); + pipeit(av_str); + strncpy(av_str, (CHAR*)mhead.AV, mhead.AV_SIZE); + av_str[mhead.AV_SIZE] = 0; + pipeit("%s\n\n", av_str); + } + comment_out("Main comment:"); // print main comment + return (1); +} + +void get_next_volname(void) // get file name of next volume +{ + CHAR *cp; + INT num; + + if ((cp = (CHAR *) strrchr(aname, '.')) == NULL || !*(cp + 1)) + num = -1; + else + { + cp++; + num = (*(cp + 1) - '0') * 10 + *(cp + 2) - '0'; + if (!in(num, 0, 99)) + num = -1; + if (in(*cp, '0', '9')) + num += (*cp - '0') * 100; + } + num++; + + if (num < 100) + *cp = 'C'; + else + *cp = num / 100 + '0'; + *(cp + 1) = (num / 10) % 10 + '0'; + *(cp + 2) = num % 10 + '0'; +} + +INT proc_vol(void) // opens volume +{ + INT i; + CHAR s[80]; + + if (!fileexists(aname) || !f_allvol_pr) + { + do + { + sprintf(s, "Ready to process %s?", aname); +#if defined(__MINGW32__) + beep(500,500); +#else + beep(); +#endif + i = confirm(s); // ask whether ready or not + f_allvol_pr = (i == 1); // "Always" --> process all volumes + if (i >= 2) + { + f_err = ERR_FOUND; + return (0); + } + } + while (!fileexists(aname)); + } + + if (!open_archive(1)) // open volume + { + pipeit("\nError while opening archive. File not found or archive broken.\n"); + f_err = ERR_OPEN; + return (0); + } + + return (1); +} + +INT proc_next_vol(void) // opens next volume to process +{ +#if !defined(__EMX__) && !defined(__OS2__) + fclose(farchan); +#endif + aceclose(archan); // close handle + get_next_volname(); // get file name of next volume + + if (!proc_vol()) // try to open volume, read archive header + return 0; + if (!read_header(1)) // read 2nd header + { + f_err=ERR_READ; + return 0; + } + return 1; +} + +INT read_adds_blk(CHAR * buffer, INT len) // reads part of ADD_SIZE block +{ + INT rd = 0, + l = len; + LONG i; + +#ifdef CRYPT + char *cbuffer=buffer; + + if (head.HEAD_TYPE == FILE_BLK && (head.HEAD_FLAGS & ACE_PASSW)) + len = crypt_len(len); +#endif /* CRYPT */ + while (!f_err && len && skipsize) + { + i = (skipsize > len) ? len : skipsize; + skipsize -= i; + + /* How do I test failure when compiling -mno-cygwin? */ +#if !defined(__MINGW32__) + errno = 0; +#endif + rd += aceread(buffer, i); +#if !defined(__MINGW32__) + if (errno) + { + error("\nRead error\n"); + f_err = ERR_READ; + } +#endif + + buffer += i; + len -= i; + + if (!skipsize) // if block is continued on next volume + if (head.HEAD_FLAGS & ACE_SP_AFTER && !proc_next_vol()) + break; + } +#ifdef CRYPT + if (head.HEAD_TYPE == FILE_BLK && (head.HEAD_FLAGS & ACE_PASSW)) + decrypt(cbuffer, rd); +#endif /* CRYPT */ + + return (rd > l ? l : rd); +} + +void crc_print(void) // checks CRC, prints message +{ + INT crc_not_ok = rd_crc != fhead.CRC32; /* check CRC of file */ + + if(crc_not_ok && installstate != ABORTED) + error("CRC error reading archive!"); +} + +void analyze_file(void) // analyzes one file (for solid archives) +{ + pipeit("\n Analyzing"); + flush; + while (!cancel() && (dcpr_adds_blk(buf_wr, size_wrb))) // decompress only + ; + crc_print(); +} + +void extract_file(void) // extracts one file +{ + INT rd; + + pipeit("\n Extracting"); + flush; // decompress block + while (!cancel() && (rd = dcpr_adds_blk(buf_wr, size_wrb))) + { + if (write(wrhan, buf_wr, rd) != rd) // write block + { + error("\nWrite error\n"); + f_err = ERR_WRITE; + } + } + crc_print(); +} + + +/* extracts or tests all files of the archive + */ +void extract_files(int nopath, int test, char *getfilename) +{ + CHAR file[PATH_MAX]; + char *tmpfile; + extern unsigned current_file; + extern char installdir2[]; + + while (!cancel() && read_header(1)) + { + if (head.HEAD_TYPE == FILE_BLK) + { + if(installstate == ABORTED) + return; + current_file++; + if(installstate == INSTALLING) + DoGUI(); + + comment_out("File comment:"); // show file comment + ace_fname(file, &head, nopath); // get file name + + /* We allow expansion of "userdir" to the selected directory by the user */ + tmpfile = replacestr(file, "USERDIR", installdir2); + strcpy(file, tmpfile); + free(tmpfile); + + if(!getfilename || (getfilename && stricmp(getfilename, file) == 0)) + { + pipeit("\n%s", file); + flush; + dcpr_init_file(); // initialize decompression of file + if (!f_err) + { + if (test || + (wrhan = create_dest_file(file, (INT) fhead.ATTR))<0) + { + if (test || adat.sol) + analyze_file(); // analyze file + } + else + { + extract_file(); // extract it +#ifdef DOS // set file time + _dos_setftime(wrhan, (USHORT) (fhead.FTIME >> 16), (USHORT) fhead.FTIME); +#endif + close(wrhan); +#if defined(__OS2__) || defined(__EMX__) + { + FILESTATUS3 fileinfo; + + DosQueryPathInfo(file, FIL_STANDARD, &fileinfo, sizeof(FILESTATUS3)); + *((USHORT*)&fileinfo.fdateCreation) = (USHORT)(fhead.FTIME >> 16); + *((USHORT*)&fileinfo.ftimeCreation) = (USHORT)fhead.FTIME; + *((USHORT*)&fileinfo.fdateLastAccess) = (USHORT)(fhead.FTIME >> 16); + *((USHORT*)&fileinfo.ftimeLastAccess) = (USHORT)fhead.FTIME; + *((USHORT*)&fileinfo.fdateLastWrite) = (USHORT)(fhead.FTIME >> 16); + *((USHORT*)&fileinfo.ftimeLastWrite) = (USHORT)fhead.FTIME; + DosSetPathInfo(file, FIL_STANDARD, (PVOID)&fileinfo, sizeof(FILESTATUS3), 0); + } +#endif +#ifdef DOS // set file attributes + _dos_setfileattr(file, (UINT) fhead.ATTR); +#endif +#ifdef AMIGA + { // set file date and time + struct DateTime dt; + char Date[9], Time[9]; + ULONG tstamp=fhead.FTIME; + + sprintf(Date, "%02d-%02d-%02d", ts_year(tstamp)-1900, ts_month(tstamp), ts_day(tstamp)); + sprintf(Time, "%02d:%02d:%02d", ts_hour(tstamp), ts_min(tstamp), ts_sec(tstamp)); + + dt.dat_Format = FORMAT_INT; + dt.dat_Flags = 0; + dt.dat_StrDate= Date; + dt.dat_StrTime= Time; + + if (StrToDate(&dt)) + SetFileDate(file, &dt.dat_Stamp); + } +#endif + if (f_err) + remove(file); + } + } + } + } + } +} + +unsigned percentage(ULONG p, ULONG d) +{ + return (unsigned)( d ? (d/2+p*100)/d : 100 ); +} + +int installer_unpack(CHAR * filename, int operation) // processes the archive +{ + init_unace(); // initialize unace + strcpy(aname, "installer"); // get archive name + + if(filename) + f_ovrall=1; + + if (open_archive(1)) // open archive to process + { + if (adat.vol_num) + pipeit("\nFirst volume of archive required!\n"); + else + { + if(operation == 2) + extract_files(0, 0, filename); + } +#if !defined(__EMX__) && !defined(__OS2__) + fclose(farchan); +#endif + aceclose(archan); + if (f_err) + { + pipeit("\nError occurred\n"); + if (f_criterr) + pipeit("Critical error on drive %c\n", f_criterr); + } + } + + done_unace(); + return 0; +} diff --git a/utils/Install/sfxzip/api.c b/utils/Install/sfxzip/api.c new file mode 100644 index 0000000000..5a4e73abf8 --- /dev/null +++ b/utils/Install/sfxzip/api.c @@ -0,0 +1,601 @@ +/*--------------------------------------------------------------------------- + + api.c + + This module supplies an UnZip engine for use directly from C/C++ + programs. The functions are: + + UzpVer *UzpVersion(void); + void 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 +#include + +#define UNZIP_INTERNAL +#include "unzip.h" +#include "version.h" +#ifdef WINDLL +# include "windll/windll.h" +#endif + +#ifdef DLL /* This source file supplies DLL-only interface code. */ + +jmp_buf dll_error_return; + +/*--------------------------------------------------------------------------- + Documented API entry points + ---------------------------------------------------------------------------*/ + + +UzpVer * UZ_EXP UzpVersion() /* should be pointer to const struct */ +{ + static UzpVer version; /* doesn't change between calls */ + + + version.structlen = UZPVER_LEN; + +#ifdef BETA + version.flag = 1; +#else + version.flag = 0; +#endif + version.betalevel = BETALEVEL; + version.date = VERSION_DATE; + +#ifdef ZLIB_VERSION + version.zlib_version = ZLIB_VERSION; + version.flag |= 2; +#else + version.zlib_version = NULL; +#endif + + /* someday each of these may have a separate patchlevel: */ + version.unzip.major = UZ_MAJORVER; + version.unzip.minor = UZ_MINORVER; + version.unzip.patchlevel = PATCHLEVEL; + + version.zipinfo.major = ZI_MAJORVER; + version.zipinfo.minor = ZI_MINORVER; + version.zipinfo.patchlevel = PATCHLEVEL; + + /* these are retained for backward compatibility only: */ + version.os2dll.major = UZ_MAJORVER; + version.os2dll.minor = UZ_MINORVER; + version.os2dll.patchlevel = PATCHLEVEL; + + version.windll.major = UZ_MAJORVER; + version.windll.minor = UZ_MINORVER; + version.windll.patchlevel = PATCHLEVEL; + + return &version; +} + +void UZ_EXP UzpVersion2(UzpVer2 *version) +{ + + version->structlen = UZPVER_LEN; + +#ifdef BETA + version->flag = 1; +#else + version->flag = 0; +#endif + strcpy(version->betalevel, BETALEVEL); + strcpy(version->date, VERSION_DATE); + +#ifdef ZLIB_VERSION + strcpy(version->zlib_version, ZLIB_VERSION); + 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 = PATCHLEVEL; + + version->zipinfo.major = ZI_MAJORVER; + version->zipinfo.minor = ZI_MINORVER; + version->zipinfo.patchlevel = PATCHLEVEL; + + /* these are retained for backward compatibility only: */ + version->os2dll.major = UZ_MAJORVER; + version->os2dll.minor = UZ_MINORVER; + version->os2dll.patchlevel = PATCHLEVEL; + + version->windll.major = UZ_MAJORVER; + version->windll.minor = UZ_MINORVER; + version->windll.patchlevel = PATCHLEVEL; +} + + + + + +#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->strptr != NULL) { + free(retstr->strptr); + retstr->strptr = NULL; + } +} + + + + +#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 */ + + + + +/*--------------------------------------------------------------------------- + Helper functions + ---------------------------------------------------------------------------*/ + + +void setFileNotFound(__G) + __GDEF +{ + G.filenotfound++; +} + + + +int unzipToMemory(__GPRO__ char *zip, char *file, UzpBuffer *retstr) +{ + int r; + char *incname[2]; + + 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 */ +} + + + +int redirect_outfile(__G) + __GDEF +{ + if (G.redirect_size != 0 || G.redirect_buffer != NULL) + return FALSE; + +#ifndef NO_SLIDE_REDIR + G.redirect_slide = !G.pInfo->textmode; +#endif + G.redirect_size = (G.pInfo->textmode ? + G.lrec.ucsize * lenEOL : G.lrec.ucsize); +#ifdef OS2 + DosAllocMem((void **)&G.redirect_buffer, G.redirect_size+1, + PAG_READ|PAG_WRITE|PAG_COMMIT); + G.redirect_pointer = G.redirect_buffer; +#else +#ifdef __16BIT__ + if ((ulg)((extent)G.redirect_size) != G.redirect_size) + return FALSE; +#endif + G.redirect_pointer = G.redirect_buffer = malloc(G.redirect_size+1); +#endif + if (!G.redirect_buffer) + return FALSE; + G.redirect_pointer[G.redirect_size] = '\0'; + return TRUE; +} + + + +int writeToMemory(__GPRO__ uch *rawbuf, ulg size) +{ + if (rawbuf != G.redirect_pointer) + memcpy(G.redirect_pointer,rawbuf,size); + G.redirect_pointer += size; + return 0; +} + + + + +int close_redirect(__G) + __GDEF +{ + if (G.pInfo->textmode) { + *G.redirect_pointer = '\0'; + G.redirect_size = 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 __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 wild card 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 */ +#ifdef WINDLL + Wiz_NoPrinting(TRUE); +#endif + + if (archive == NULL) { /* something is screwed up: no filename */ + DESTROYGLOBALS(); + return PK_NOZIP; + } + + G.wildzipfn = (char *)malloc(FILNAMSIZ + 1); + strcpy(G.wildzipfn, archive); +#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO)) + _ISO_INTERN(G.wildzipfn); +#endif + + G.process_all_files = TRUE; /* for speed */ + + retcode = setjmp(dll_error_return); + + if (retcode) { +#ifdef WINDLL + Wiz_NoPrinting(FALSE); +#endif + free(G.wildzipfn); + DESTROYGLOBALS(); + return PK_BADERR; + } + + 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 + */ + + 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 /* DLL */ diff --git a/utils/Install/sfxzip/apihelp.c b/utils/Install/sfxzip/apihelp.c new file mode 100644 index 0000000000..1a0d682cdd --- /dev/null +++ b/utils/Install/sfxzip/apihelp.c @@ -0,0 +1,147 @@ +/* apihelp.c */ + +#ifdef API_DOC + +#define UNZIP_INTERNAL +#include "unzip.h" +#include "version.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/utils/Install/sfxzip/crc32.c b/utils/Install/sfxzip/crc32.c new file mode 100644 index 0000000000..cd05536108 --- /dev/null +++ b/utils/Install/sfxzip/crc32.c @@ -0,0 +1,56 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* $Id$ */ + +#define __CRC32_C /* identifies this source module */ + +#include "zip.h" + +#ifndef USE_ZLIB +#ifndef ASM_CRC + +#ifndef ZCONST +# define ZCONST const +#endif + +#ifdef CRC32 +# undef CRC32 +#endif +#define CRC32(c, b) (crc_table[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) +#define DO1(buf) crc = CRC32(crc, *buf++) +#define DO2(buf) DO1(buf); DO1(buf) +#define DO4(buf) DO2(buf); DO2(buf) +#define DO8(buf) DO4(buf); DO4(buf) + +/* ========================================================================= */ +ulg crc32(crc, buf, len) + register ulg crc; /* crc shift register */ + register ZCONST uch *buf; /* pointer to bytes to pump through */ + extent len; /* number of bytes in buf[] */ +/* Run a set of bytes through the crc shift register. If buf is a NULL + pointer, then initialize the crc shift register contents instead. + Return the current crc in either case. */ +{ + register ZCONST ulg near *crc_table; + + if (buf == NULL) return 0L; + + crc_table = get_crc_table(); + + crc = crc ^ 0xffffffffL; +#ifndef NO_UNROLLED_LOOPS + while (len >= 8) { + DO8(buf); + len -= 8; + } +#endif + if (len) do { + DO1(buf); + } while (--len); + return crc ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ +} +#endif /* !ASM_CRC */ +#endif /* !USE_ZLIB */ diff --git a/utils/Install/sfxzip/crc_i386.S b/utils/Install/sfxzip/crc_i386.S new file mode 100644 index 0000000000..5d0867f0e1 --- /dev/null +++ b/utils/Install/sfxzip/crc_i386.S @@ -0,0 +1,230 @@ +/* + * crc_i386.S, optimized CRC calculation function for Zip and UnZip, not + * copyrighted by Paul Kienitz and Christian Spieler. Last revised 12 Oct 97. + * + * 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 ...) + * + * 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, ulg len). + * + * The loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS. + * This results in shorter code at the expense of reduced performance. + */ + +/* This file is NOT used in conjunction with zlib. */ +#ifndef USE_ZLIB + +/* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix + * external symbols with an underline character '_'. + */ +#if defined(NO_UNDERLINE) || defined(__ELF__) +# define _crc32 crc32 +# define _get_crc_table get_crc_table +#endif +/* Use 16-byte alignment if your assembler supports it. Warning: gas + * uses a log(x) parameter (.align 4 means 16-byte alignment). On SVR4 + * the parameter is a number of bytes. + */ +#ifndef ALIGNMENT +# define ALIGNMENT .align 4,0x90 +#endif + +#if defined(i386) || defined(_i386) || defined(_I386) || defined(__i386) + +/* This version is for 386 Unix, OS/2, MSDOS in 32 bit mode (gcc & gas). + * Warning: it uses the AT&T syntax: mov source,dest + * This file is only optional. If you want to use the C version, + * remove -DASM_CRC from CFLAGS in Makefile and set OBJA to an empty string. + */ + + .file "crc_i386.S" + +#if defined(NO_STD_STACKFRAME) && defined(USE_STD_STACKFRAME) +# undef USE_STACKFRAME +#else + /* The default is to use standard stack frame entry, because it + * results in smaller code! + */ +# ifndef USE_STD_STACKFRAME +# define USE_STD_STACKFRAME +# endif +#endif + +#ifdef USE_STD_STACKFRAME +# define _STD_ENTRY pushl %ebp ; movl %esp,%ebp +# define arg1 8(%ebp) +# define arg2 12(%ebp) +# define arg3 16(%ebp) +# define _STD_LEAVE popl %ebp +#else /* !USE_STD_STACKFRAME */ +# define _STD_ENTRY +# define arg1 24(%esp) +# define arg2 28(%esp) +# define arg3 32(%esp) +# define _STD_LEAVE +#endif /* ?USE_STD_STACKFRAME */ + +/* + * These two (three) macros make up the loop body of the CRC32 cruncher. + * registers modified: + * eax : crc value "c" + * esi : pointer to next data byte (or lword) "buf++" + * registers read: + * edi : pointer to base of crc_table array + * scratch registers: + * ebx : index into crc_table array + * (requires upper three bytes = 0 when __686 is undefined) + */ +#ifndef __686 /* optimize for 386, 486, Pentium */ +#define Do_CRC /* c = (c >> 8) ^ table[c & 0xFF] */\ + movb %al, %bl ;/* tmp = c & 0xFF */\ + shrl $8, %eax ;/* c = (c >> 8) */\ + xorl (%edi, %ebx, 4), %eax ;/* c ^= table[tmp] */ +#else /* __686 : optimize for Pentium Pro and compatible CPUs */ +#define Do_CRC /* c = (c >> 8) ^ table[c & 0xFF] */\ + movzbl %al, %ebx ;/* tmp = c & 0xFF */\ + shrl $8, %eax ;/* c = (c >> 8) */\ + xorl (%edi, %ebx, 4), %eax ;/* c ^=table[tmp] */ +#endif /* ?__686 */ + +#define Do_CRC_byte /* c = (c >> 8) ^ table[(c^*buf++)&0xFF] */\ + xorb (%esi), %al ;/* c ^= *buf */\ + incl %esi ;/* buf++ */\ + Do_CRC + +#ifndef NO_32_BIT_LOADS +#define Do_CRC_lword \ + xorl (%esi), %eax ;/* c ^= *(ulg *)buf */\ + addl $4, %esi ;/* ((ulg *)buf)++ */\ + Do_CRC \ + Do_CRC \ + Do_CRC \ + Do_CRC +#endif /* !NO_32_BIT_LOADS */ + + + .text + + .globl _crc32 + +_crc32: /* ulg crc32(ulg crc, uch *buf, extent len) */ + _STD_ENTRY + pushl %edi + pushl %esi + pushl %ebx + pushl %edx + pushl %ecx + + movl arg2, %esi /* 2nd arg: uch *buf */ + subl %eax, %eax /* > if (!buf) */ + testl %esi, %esi /* > return 0; */ + jz .L_fine /* > else { */ + call _get_crc_table + movl %eax, %edi + movl arg1, %eax /* 1st arg: ulg crc */ +#ifndef __686 + subl %ebx, %ebx /* ebx=0; bl usable as dword */ +#endif + movl arg3, %ecx /* 3rd arg: extent len */ + notl %eax /* > c = ~crc; */ + +#ifndef NO_UNROLLED_LOOPS +# ifndef NO_32_BIT_LOADS + testl %ecx, %ecx + jz .L_bail + /* Assert now have positive length */ +.L_align_loop: + testl $3, %esi /* Align buf on lword boundary */ + jz .L_aligned_now + Do_CRC_byte + decl %ecx + jnz .L_align_loop +.L_aligned_now: +# endif /* !NO_32_BIT_LOADS */ + movl %ecx, %edx /* save len in edx */ + andl $7, %edx /* edx = len % 8 */ + shrl $3, %ecx /* ecx = len / 8 */ + jz .L_No_Eights +/* align loop head at start of 486 internal cache line !! */ + ALIGNMENT +.L_Next_Eight: +# ifndef NO_32_BIT_LOADS + /* Do_CRC_lword */ + xorl (%esi), %eax ;/* c ^= *(ulg *)buf */ + addl $4, %esi ;/* ((ulg *)buf)++ */ + Do_CRC + Do_CRC + Do_CRC + Do_CRC + /* Do_CRC_lword */ + xorl (%esi), %eax ;/* c ^= *(ulg *)buf */ + addl $4, %esi ;/* ((ulg *)buf)++ */ + Do_CRC + Do_CRC + Do_CRC + Do_CRC +# else /* NO_32_BIT_LOADS */ + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte +# endif /* ?NO_32_BIT_LOADS */ + decl %ecx + jnz .L_Next_Eight + +.L_No_Eights: + movl %edx, %ecx +#endif /* NO_UNROLLED_LOOPS */ + +#ifndef NO_JECXZ_SUPPORT + jecxz .L_bail /* > if (len) */ +#else + testl %ecx, %ecx /* > if (len) */ + jz .L_bail +#endif +/* align loop head at start of 486 internal cache line !! */ + ALIGNMENT +.L_loupe: /* > do { */ + Do_CRC_byte /* c = CRC32(c, *buf++); */ + decl %ecx /* > } while (--len); */ + jnz .L_loupe + +.L_bail: /* > } */ + notl %eax /* > return ~c; */ +.L_fine: + popl %ecx + popl %edx + popl %ebx + popl %esi + popl %edi + _STD_LEAVE + ret + +#else + error: this asm version is for 386 only +#endif /* i386 || _i386 || _I386 || __i386 */ + +#endif /* !USE_ZLIB */ diff --git a/utils/Install/sfxzip/crc_i386.asm b/utils/Install/sfxzip/crc_i386.asm new file mode 100644 index 0000000000..ea29282286 --- /dev/null +++ b/utils/Install/sfxzip/crc_i386.asm @@ -0,0 +1,229 @@ +; crc_i386.asm, optimized CRC calculation function for Zip and UnZip, not +; copyrighted by Paul Kienitz and Christian Spieler. Last revised 25 Mar 98. +; +; Revised 06-Oct-96, Scott Field (sfield@microsoft.com) +; fixed to assemble with masm by not using .model directive which makes +; assumptions about segment alignment. Also, +; avoid using loop, and j[e]cxz where possible. Use mov + inc, rather +; than lodsb, and other misc. changes resulting in the following performance +; increases: +; +; unrolled loops NO_UNROLLED_LOOPS +; *8 >8 <8 *8 >8 <8 +; +; +54% +42% +35% +82% +52% +25% +; +; first item in each table is input buffer length, even multiple of 8 +; second item in each table is input buffer length, > 8 +; third item in each table is input buffer length, < 8 +; +; Revised 02-Apr-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au) +; Incorporated Rodney Brown's 32-bit-reads optimization as found in the +; UNIX AS source crc_i386.S. This new code can be disabled by defining +; the macro symbol NO_32_BIT_LOADS. +; +; Revised 12-Oct-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au) +; Incorporated Rodney Brown's additional tweaks for 32-bit-optimized CPUs +; (like the Pentium Pro, Pentium II, and probably some Pentium clones). +; This optimization is controlled by the macro symbol __686 and is disabled +; by default. (This default is based on the assumption that most users +; do not yet work on a Pentium Pro or Pentium II machine ...) +; +; FLAT memory model assumed. +; +; The loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS. +; This results in shorter code at the expense of reduced performance. +; +; Revised 25-Mar-98, Cosmin Truta (cosmint@cs.ubbcluj.ro) +; Working without .model directive caused tasm32 version 5.0 to produce +; bad object code. The optimized alignments can be optionally disabled +; by defining NO_ALIGN, thus allowing to use .model flat. There is no need +; to define this macro if using other version of tasm. +; +;============================================================================== +; +; Do NOT assemble this source if external crc32 routine from zlib gets used. +; + IFNDEF USE_ZLIB +; + .386p + name crc_i386 + + IFDEF NO_ALIGN + .model flat + ENDIF + +extrn _get_crc_table:near ; ZCONST ulg near *get_crc_table(void); + +; + IFNDEF NO_STD_STACKFRAME + ; Use a `standard' stack frame setup on routine entry and exit. + ; Actually, this option is set as default, because it results + ; in smaller code !! +STD_ENTRY MACRO + push ebp + mov ebp,esp + ENDM + + Arg1 EQU 08H[ebp] + Arg2 EQU 0CH[ebp] + Arg3 EQU 10H[ebp] + +STD_LEAVE MACRO + pop ebp + ENDM + + ELSE ; NO_STD_STACKFRAME + +STD_ENTRY MACRO + ENDM + + Arg1 EQU 18H[esp] + Arg2 EQU 1CH[esp] + Arg3 EQU 20H[esp] + +STD_LEAVE MACRO + ENDM + + ENDIF ; ?NO_STD_STACKFRAME + +; These two (three) macros make up the loop body of the CRC32 cruncher. +; registers modified: +; eax : crc value "c" +; esi : pointer to next data byte (or dword) "buf++" +; registers read: +; edi : pointer to base of crc_table array +; scratch registers: +; ebx : index into crc_table array +; (requires upper three bytes = 0 when __686 is undefined) + IFNDEF __686 ; optimize for 386, 486, Pentium +Do_CRC MACRO + mov bl,al ; tmp = c & 0xFF + shr eax,8 ; c = (c >> 8) + xor eax,[edi+ebx*4] ; ^ table[tmp] + ENDM + ELSE ; __686 : optimize for Pentium Pro, Pentium II and compatible CPUs +Do_CRC MACRO + movzx ebx,al ; tmp = c & 0xFF + shr eax,8 ; c = (c >> 8) + xor eax,[edi+ebx*4] ; ^ table[tmp] + ENDM + ENDIF ; ?__686 +Do_CRC_byte MACRO + xor al, byte ptr [esi] ; c ^= *buf + inc esi ; buf++ + Do_CRC ; c = (c >> 8) ^ table[c & 0xFF] + ENDM + IFNDEF NO_32_BIT_LOADS +Do_CRC_dword MACRO + xor eax, dword ptr [esi] ; c ^= *(ulg *)buf + add esi, 4 ; ((ulg *)buf)++ + Do_CRC + Do_CRC + Do_CRC + Do_CRC + ENDM + ENDIF ; !NO_32_BIT_LOADS + + IFNDEF NO_ALIGN +_TEXT segment use32 para public 'CODE' + ELSE +_TEXT segment use32 + ENDIF + assume CS: _TEXT + + public _crc32 +_crc32 proc near ; ulg crc32(ulg crc, ZCONST uch *buf, extent len) + STD_ENTRY + push edi + push esi + push ebx + push edx + push ecx + + mov esi,Arg2 ; 2nd arg: uch *buf + sub eax,eax ;> if (!buf) + test esi,esi ;> return 0; + jz fine ;> else { + + call _get_crc_table + mov edi,eax + mov eax,Arg1 ; 1st arg: ulg crc + IFNDEF __686 + sub ebx,ebx ; ebx=0; make bl usable as a dword + ENDIF + mov ecx,Arg3 ; 3rd arg: extent len + not eax ;> c = ~crc; + + IFNDEF NO_UNROLLED_LOOPS + IFNDEF NO_32_BIT_LOADS + test ecx,ecx + je bail +align_loop: + test esi,3 ; align buf pointer on next + jz SHORT aligned_now ; dword boundary + Do_CRC_byte + dec ecx + jnz align_loop +aligned_now: + ENDIF ; !NO_32_BIT_LOADS + mov edx,ecx ; save len in edx + and edx,000000007H ; edx = len % 8 + shr ecx,3 ; ecx = len / 8 + jz SHORT No_Eights + IFNDEF NO_ALIGN +; align loop head at start of 486 internal cache line !! + align 16 + ENDIF +Next_Eight: + IFNDEF NO_32_BIT_LOADS + Do_CRC_dword + Do_CRC_dword + ELSE ; NO_32_BIT_LOADS + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + Do_CRC_byte + ENDIF ; ?NO_32_BIT_LOADS + dec ecx + jnz Next_Eight +No_Eights: + mov ecx,edx + + ENDIF ; NO_UNROLLED_LOOPS + IFNDEF NO_JECXZ_SUPPORT + jecxz bail ;> if (len) + ELSE + test ecx,ecx ;> if (len) + jz SHORT bail + ENDIF + IFNDEF NO_ALIGN +; align loop head at start of 486 internal cache line !! + align 16 + ENDIF +loupe: ;> do { + Do_CRC_byte ; c = CRC32(c, *buf++); + dec ecx ;> } while (--len); + jnz loupe + +bail: ;> } + not eax ;> return ~c; +fine: + pop ecx + pop edx + pop ebx + pop esi + pop edi + STD_LEAVE + ret +_crc32 endp + +_TEXT ends +; + ENDIF ; !USE_ZLIB +; +end diff --git a/utils/Install/sfxzip/crc_i386.c b/utils/Install/sfxzip/crc_i386.c new file mode 100644 index 0000000000..72e2c6b9dc --- /dev/null +++ b/utils/Install/sfxzip/crc_i386.c @@ -0,0 +1,215 @@ +/* crc_i386.c -- Microsoft 32-bit C/C++ adaptation of crc_i386.asm + * Created by Rodney Brown from crc_i386.asm, modified by Chr. Spieler. + * Last revised: 22-Mai-1998 + * + * Original coded (in crc_i386.asm) and put into the public domain + * by Paul Kienitz and Christian Spieler. + * + * Revised 06-Oct-96, Scott Field (sfield@microsoft.com) + * fixed to assemble with masm by not using .model directive which makes + * assumptions about segment alignment. Also, + * avoid using loop, and j[e]cxz where possible. Use mov + inc, rather + * than lodsb, and other misc. changes resulting in the following performance + * increases: + * + * unrolled loops NO_UNROLLED_LOOPS + * *8 >8 <8 *8 >8 <8 + * + * +54% +42% +35% +82% +52% +25% + * + * first item in each table is input buffer length, even multiple of 8 + * second item in each table is input buffer length, > 8 + * third item in each table is input buffer length, < 8 + * + * Revised 02-Apr-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au) + * Incorporated Rodney Brown's 32-bit-reads optimization as found in the + * UNIX AS source crc_i386.S. This new code can be disabled by defining + * the macro symbol NO_32_BIT_LOADS. + * + * Revised 12-Oct-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au) + * Incorporated Rodney Brown's additional tweaks for 32-bit-optimized CPUs + * (like the Pentium Pro, Pentium II, and probably some Pentium clones). + * This optimization is controlled by the macro symbol __686 and is disabled + * by default. (This default is based on the assumption that most users + * do not yet work on a Pentium Pro or Pentium II machine ...) + * + * Revised 16-Nov-97, Chr. Spieler: Made code compatible with Borland C++ + * 32-bit, removed unneeded kludge for potentially unknown movzx mnemonic, + * confirmed correct working with MS VC++ (32-bit). + * + * Revised 22-Mai-98, Peter Kunath, Chr. Spieler : The 16-Nov-97 revision broke + * MSVC 5.0. Inside preprocessor macros, each instruction is enclosed in its + * own __asm {...} construct. For MSVC, a "#pragma warning" was added to + * shut up the "no return value" warning message. + * + * FLAT memory model assumed. + * + * The loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS. + * This results in shorter code at the expense of reduced performance. + * + */ + +#include "zip.h" + +#ifndef USE_ZLIB + +#ifndef ZCONST +# define ZCONST const +#endif + +/* Select wether the following inline-assember code is supported. */ +#if (defined(_MSC_VER) && _MSC_VER >= 700) +#if (defined(_M_IX86) && _M_IX86 >= 300) +# define MSC_INLINE_ASM_32BIT_SUPPORT + /* Disable warning for no return value, typical of asm functions */ +# pragma warning( disable : 4035 ) +#endif +#endif + +#if (defined(__BORLANDC__) && __BORLANDC__ >= 452) +# define MSC_INLINE_ASM_32BIT_SUPPORT +#endif + +#ifdef MSC_INLINE_ASM_32BIT_SUPPORT +/* This code is intended for Microsoft C/C++ (32-bit) compatible compilers. */ + +/* + * These two (three) macros make up the loop body of the CRC32 cruncher. + * registers modified: + * eax : crc value "c" + * esi : pointer to next data byte (or dword) "buf++" + * registers read: + * edi : pointer to base of crc_table array + * scratch registers: + * ebx : index into crc_table array + * (requires upper three bytes = 0 when __686 is undefined) + */ +#ifndef __686 +#define Do_CRC { \ + __asm { mov bl, al }; \ + __asm { shr eax, 8 }; \ + __asm { xor eax, [edi+ebx*4] }; } +#else /* __686 */ +#define Do_CRC { \ + __asm { movzx ebx, al }; \ + __asm { shr eax, 8 }; \ + __asm { xor eax, [edi+ebx*4] }; } +#endif /* ?__686 */ + +#define Do_CRC_byte { \ + __asm { xor al, byte ptr [esi] }; \ + __asm { inc esi }; \ + Do_CRC; } + +#ifndef NO_32_BIT_LOADS +#define Do_CRC_dword { \ + __asm { xor eax, dword ptr [esi] }; \ + __asm { add esi, 4 }; \ + Do_CRC; \ + Do_CRC; \ + Do_CRC; \ + Do_CRC; } +#endif /* !NO_32_BIT_LOADS */ + +/* ========================================================================= */ +ulg crc32(crc, buf, len) + ulg crc; /* crc shift register */ + ZCONST uch *buf; /* pointer to bytes to pump through */ + extent len; /* number of bytes in buf[] */ +/* Run a set of bytes through the crc shift register. If buf is a NULL + pointer, then initialize the crc shift register contents instead. + Return the current crc in either case. */ +{ + __asm { + push edx + push ecx + + mov esi,buf ;/* 2nd arg: uch *buf */ + sub eax,eax ;/*> if (!buf) */ + test esi,esi ;/*> return 0; */ + jz fine ;/*> else { */ + + call get_crc_table + mov edi,eax + mov eax,crc ;/* 1st arg: ulg crc */ +#ifndef __686 + sub ebx,ebx ;/* ebx=0; => bl usable as a dword */ +#endif + mov ecx,len ;/* 3rd arg: extent len */ + not eax ;/*> c = ~crc; */ + +#ifndef NO_UNROLLED_LOOPS +# ifndef NO_32_BIT_LOADS + test ecx,ecx + je bail +align_loop: + test esi,3 ;/* align buf pointer on next */ + jz aligned_now ;/* dword boundary */ + } + Do_CRC_byte ; + __asm { + dec ecx + jnz align_loop +aligned_now: +# endif /* !NO_32_BIT_LOADS */ + mov edx,ecx ;/* save len in edx */ + and edx,000000007H ;/* edx = len % 8 */ + shr ecx,3 ;/* ecx = len / 8 */ + jz No_Eights +; align loop head at start of 486 internal cache line !! + align 16 +Next_Eight: + } +# ifndef NO_32_BIT_LOADS + Do_CRC_dword ; + Do_CRC_dword ; +# else /* NO_32_BIT_LOADS */ + Do_CRC_byte ; + Do_CRC_byte ; + Do_CRC_byte ; + Do_CRC_byte ; + Do_CRC_byte ; + Do_CRC_byte ; + Do_CRC_byte ; + Do_CRC_byte ; +# endif /* ?NO_32_BIT_LOADS */ + __asm { + dec ecx + jnz Next_Eight +No_Eights: + mov ecx,edx + +#endif /* NO_UNROLLED_LOOPS */ +#ifndef NO_JECXZ_SUPPORT + jecxz bail ;/*> if (len) */ +#else + test ecx,ecx ;/*> if (len) */ + jz bail +#endif +; align loop head at start of 486 internal cache line !! + align 16 +loupe: ;/*> do { */ + } + Do_CRC_byte ;/* c = CRC32(c, *buf++); */ + __asm { + dec ecx ;/*> } while (--len); */ + jnz loupe + +bail: ;/*> } */ + not eax ;/*> return ~c; */ +fine: + pop ecx + pop edx + } +#ifdef NEED_RETURN + return _EAX; +#endif +} +#endif /* MSC_INLINE_ASM_32BIT_SUPPORT */ +#if (defined(_MSC_VER) && _MSC_VER >= 700) +#if (defined(_M_IX86) && _M_IX86 >= 300) + /* Reenable missing return value warning */ +# pragma warning( default : 4035 ) +#endif +#endif +#endif /* !USE_ZLIB */ diff --git a/utils/Install/sfxzip/crc_lcc.asm b/utils/Install/sfxzip/crc_lcc.asm new file mode 100644 index 0000000000..b3288a833e --- /dev/null +++ b/utils/Install/sfxzip/crc_lcc.asm @@ -0,0 +1,108 @@ +; crc_lcc.asm, optimized CRC calculation function for Zip and UnZip, not +; copyrighted by Paul Kienitz and Christian Spieler. Last revised 25 Mar 98. +; +; The code in this file has been copied verbatim from crc_i386.{asm|S}; +; only the assembler syntax and metacommands have been adapted to +; the habits of the free LCC-Win32 C compiler package. +; This version of the code uses the "optimized for i686" variant of +; crc_i386.{asm|S}. +; +; For more information (and a revision log), look into the original +; source files. +; + .text + .file "crc32.c" + .text + .type _crc32,function +_crc32: + pushl %ebp + movl %esp,%ebp + pushl %ecx + pushl %ebx + pushl %esi + pushl %edi + .line 34 + .line 37 + movl 12(%ebp),%esi + subl %eax,%eax + testl %esi,%esi + jz _$3 + .line 39 + call _get_crc_table + movl %eax,%edi + .line 41 + movl 8(%ebp),%eax + movl 16(%ebp),%ecx + notl %eax + testl %ecx,%ecx + jz _$4 +_$5: + testl $3,%esi + jz _$6 + xorb (%esi),%al + incl %esi + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + decl %ecx + jnz _$5 +_$6: + movl %ecx,%edx + andl $7,%edx + shrl $3,%ecx + jz _$8 +_$7: + xorl (%esi),%eax + addl $4,%esi + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + xorl (%esi),%eax + addl $4,%esi + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + decl %ecx + jnz _$7 +_$8: + movl %edx,%ecx + jecxz _$4 +_$9: + xorb (%esi),%al + incl %esi + movzbl %al,%ebx + shrl $8,%eax + xorl (%edi,%ebx,4),%eax + decl %ecx + jnz _$9 +_$4: + xorl $0xffffffff,%eax +_$3: + .line 52 + popl %edi + popl %esi + popl %ebx + leave + ret +_$34: + .size _crc32,_$34-_crc32 + .globl _crc32 + .extern _get_crc_table diff --git a/utils/Install/sfxzip/crctab.c b/utils/Install/sfxzip/crctab.c new file mode 100644 index 0000000000..2f80aa2cfa --- /dev/null +++ b/utils/Install/sfxzip/crctab.c @@ -0,0 +1,219 @@ +/* crctab.c -- supply the CRC table needed for CRC-32 calculations. + * Copyright (C) 1995 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* $Id$ */ + +/* + Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all + the information needed to generate CRC's on data a byte at a time for all + combinations of CRC register values and incoming bytes. +*/ + +#define __CRCTAB_C /* identifies this source module */ + +#include "zip.h" + +#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) + +#ifndef ZCONST +# define ZCONST const +#endif + +#ifdef DYNAMIC_CRC_TABLE + +/* ========================================================================= + * Make the crc table. This function is needed only if you want to compute + * the table dynamically. + */ + +local void make_crc_table OF((void)); + +#if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT)) + error: Dynamic allocation of CRC table not safe with reentrant code. +#endif /* DYNALLOC_CRCTAB && REENTRANT */ + +#ifdef DYNALLOC_CRCTAB + local ulg near *crc_table = NULL; +# if 0 /* not used, since sizeof("near *") <= sizeof(int) */ + /* Use this section when access to a "local int" is faster than access to + a "local pointer" (e.g.: i86 16bit code with far pointers). */ + local int crc_table_empty = 1; +# define CRC_TABLE_IS_EMPTY (crc_table_empty != 0) +# define MARK_CRCTAB_FILLED crc_table_empty = 0 +# define MARK_CRCTAB_EMPTY crc_table_empty = 1 +# else + /* Use this section on systems where the size of pointers and ints is + equal (e.g.: all 32bit systems). */ +# define CRC_TABLE_IS_EMPTY (crc_table == NULL) +# define MARK_CRCTAB_FILLED crc_table = crctab_p +# define MARK_CRCTAB_EMPTY crc_table = NULL +# endif +#else /* !DYNALLOC_CRCTAB */ + local ulg near crc_table[256]; + local int crc_table_empty = 1; +# define CRC_TABLE_IS_EMPTY (crc_table_empty != 0) +# define MARK_CRCTAB_FILLED crc_table_empty = 0 +#endif /* ?DYNALLOC_CRCTAB */ + + +local void make_crc_table() +{ + ulg c; /* crc shift register */ + int n; /* counter for all possible eight bit values */ + int k; /* byte being shifted into crc apparatus */ +#ifdef DYNALLOC_CRCTAB + ulg near *crctab_p; /* temporary pointer to allocated crc_table area */ +#else /* !DYNALLOC_CRCTAB */ +# define crctab_p crc_table +#endif /* DYNALLOC_CRCTAB */ + +#ifdef COMPUTE_XOR_PATTERN + /* This piece of code has been left here to explain how the XOR pattern + * used in the creation of the crc_table values can be recomputed. + * For production versions of this function, it is more efficient to + * supply the resultant pattern at compile time. + */ + ulg xor; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static uch p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320L) */ + xor = 0L; + for (i = 0; i < sizeof(p)/sizeof(uch); i++) + xor |= 1L << (31 - p[i]); +#else +# define xor 0xedb88320L +#endif + +#ifdef DYNALLOC_CRCTAB + crctab_p = (ulg near *) nearmalloc (256*sizeof(ulg)); + if (crctab_p == NULL) { + ziperr(ZE_MEM, "crc_table allocation"); + } +#endif /* DYNALLOC_CRCTAB */ + + for (n = 0; n < 256; n++) { + c = (ulg)n; + for (k = 8; k; k--) + c = c & 1 ? xor ^ (c >> 1) : c >> 1; + crctab_p[n] = c; + } + MARK_CRCTAB_FILLED; +} + +#else /* !DYNAMIC_CRC_TABLE */ + +#ifdef DYNALLOC_CRCTAB + error: Inconsistent flags, DYNALLOC_CRCTAB without DYNAMIC_CRC_TABLE. +#endif + +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +local ZCONST ulg near crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; +#endif /* ?DYNAMIC_CRC_TABLE */ + +/* use "OF((void))" here to work around a Borland TC++ 1.0 problem */ +#ifdef USE_ZLIB +ZCONST uLongf *get_crc_table OF((void)) +#else +ZCONST ulg near *get_crc_table OF((void)) +#endif +{ +#ifdef DYNAMIC_CRC_TABLE + if (CRC_TABLE_IS_EMPTY) + make_crc_table(); +#endif +#ifdef USE_ZLIB + return (ZCONST uLongf *)crc_table; +#else + return (ZCONST ulg near *)crc_table; +#endif +} + +#ifdef DYNALLOC_CRCTAB +void free_crc_table() +{ + if (!CRC_TABLE_IS_EMPTY) + { + nearfree((ulg near *)crc_table); + MARK_CRCTAB_EMPTY; + } +} +#endif + +#endif /* !USE_ZLIB || USE_OWN_CRCTAB */ diff --git a/utils/Install/sfxzip/crypt.c b/utils/Install/sfxzip/crypt.c new file mode 100644 index 0000000000..0dbe227f81 --- /dev/null +++ b/utils/Install/sfxzip/crypt.c @@ -0,0 +1,12 @@ +/* + crypt.c (dummy version) by Info-ZIP. Last revised: 15 Aug 98 + + This is a non-functional version of Info-ZIP's crypt.c encryption/ + decryption code for Zip, ZipCloak, UnZip and fUnZip. This file is + not copyrighted and may be distributed freely. :-) See the "WHERE" + file for sites from which to obtain the full encryption/decryption + sources (zcrypt28.zip or later). + */ + +/* something "externally visible" to shut up compiler/linker warnings */ +int zcr_dummy; diff --git a/utils/Install/sfxzip/envargs.c b/utils/Install/sfxzip/envargs.c new file mode 100644 index 0000000000..76a41e8997 --- /dev/null +++ b/utils/Install/sfxzip/envargs.c @@ -0,0 +1,314 @@ +/*----------------------------------------------------------------* + | 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 +#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__ */ + +static int count_args OF((ZCONST char *)); +static void mem_err OF((__GPRO)); + +static ZCONST char Far NoMemArguments[] = + "envargs: cannot get memory for arguments"; + + +void envargs(__G__ Pargc, Pargv, envstr, envstr2) + __GDEF + int *Pargc; + char ***Pargv; + ZCONST char *envstr, *envstr2; +{ +#ifndef RISCOS + char *getenv(); +#endif + 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; + + bufptr = malloc(1 + strlen(envptr)); + if (bufptr == (char *)NULL) + mem_err(__G); +#if (defined(WIN32) || defined(WINDLL)) +# 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 environment uses OEM codepage */ + OEM_TO_INTERN(envptr, bufptr); +# endif +#else /* !(WIN32 || WINDLL) */ + strcpy(bufptr, envptr); +#endif /* ?(WIN32 || WINDLL) */ + + /* 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); + mem_err(__G); + } + 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 = *(++bufptr)) + if (ch == '\\' && bufptr[1] != '\0') + ++bufptr; /* skip char after backslash */ + if (ch != '\0') + *(bufptr++) = '\0'; /* overwrite trailing " */ + + /* remove escape characters */ + while ((argstart = strchr(argstart, '\\')) != (char *)NULL) { + strcpy(argstart, argstart + 1); + if (*argstart) + ++argstart; + } + } else { + *(argv++) = bufptr; + while ((ch = *bufptr) != '\0' && !ISspace(ch)) + ++bufptr; + if (ch != '\0') + *(bufptr++) = '\0'; + } +#else +#ifdef DOS_FLX_OS2_W32 + /* we do not support backslash-quoting of quotes in quoted + * strings under DOS_OS2_W32, because backslashes are directory + * separators and double quotes are illegal in filenames */ + if (*bufptr == '"') { + *(argv++) = ++bufptr; + while ((ch = *bufptr) != '\0' && ch != '\"') + ++bufptr; + if (ch != '\0') + *(bufptr++) = '\0'; + } else { + *(argv++) = bufptr; + while ((ch = *bufptr) != '\0' && !ISspace(ch)) + ++bufptr; + if (ch != '\0') + *(bufptr++) = '\0'; + } +#else + *(argv++) = bufptr; + while ((ch = *bufptr) != '\0' && !ISspace(ch)) + ++bufptr; + if (ch != '\0') + *(bufptr++) = '\0'; +#endif /* ?DOS_FLX_OS2_W32 */ +#endif /* ?(AMIGA || UNIX) */ + while ((ch = *bufptr) != '\0' && ISspace(ch)) + ++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 */ + *Pargv = argvect; + *Pargc = argc; +} + + + +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 = *(++s); ch != '\0' && ch != '\"'; ch = *(++s)) + if (ch == '\\' && s[1] != '\0') + ++s; + if (*s) + ++s; /* trailing quote */ + } else +#else +#ifdef DOS_FLX_OS2_W32 + if (*s == '\"') { + ++s; /* leading quote */ + while ((ch = *s) != '\0' && ch != '\"') + ++s; + if (*s) + ++s; /* trailing quote */ + } else +#endif /* DOS_FLX_OS2_W32 */ +#endif /* ?(AMIGA || UNIX) */ + while ((ch = *s) != '\0' && !ISspace(ch)) /* note else-clauses above */ + ++s; + while ((ch = *s) != '\0' && ISspace(ch)) + ++s; + } while (ch); + + return count; +} + + + +static void mem_err(__G) + __GDEF +{ + perror(LoadFarString(NoMemArguments)); + DESTROYGLOBALS() + EXIT(PK_MEM); +} + + + +#ifdef TEST + +main(argc, argv) + int argc; + char **argv; +{ + int i; + + pipeit("Orig argv: %p\n", argv); + dump_args(argc, argv); + envargs(__G__ &argc, &argv, "ENVTEST"); + pipeit(" New argv: %p\n", argv); + dump_args(argc, argv); +} + + + +dump_args(argc, argv) + int argc; + char *argv[]; +{ + int i; + + pipeit("\nDump %d args:\n", argc); + for (i = 0; i < argc; ++i) + pipeit("%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/utils/Install/sfxzip/explode.c b/utils/Install/sfxzip/explode.c new file mode 100644 index 0000000000..c1a8f80032 --- /dev/null +++ b/utils/Install/sfxzip/explode.c @@ -0,0 +1,871 @@ +/* explode.c -- put in the public domain by Mark Adler + version c15, 6 July 1996 */ + + +/* 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. + */ + + +/* + 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 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 wsize G._wsize +#else +# define wsize WSIZE +#endif + +/* routines here */ +static int get_tree OF((__GPRO__ unsigned *l, unsigned n)); +static int explode_lit8 OF((__GPRO__ struct huft *tb, struct huft *tl, + struct huft *td, int bb, int bl, int bd)); +static int explode_lit4 OF((__GPRO__ struct huft *tb, struct huft *tl, + struct huft *td, int bb, int bl, int bd)); +static int explode_nolit8 OF((__GPRO__ struct huft *tl, struct huft *td, + int bl, int bd)); +static int explode_nolit4 OF((__GPRO__ struct huft *tl, struct huft *td, + int bl, int bd)); +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. + */ + + +/* 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 ush 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);} + + + +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_lit8(__G__ tb, tl, td, bb, bl, bd) + __GDEF +struct huft *tb, *tl, *td; /* literal, length, and distance tables */ +int bb, bl, bd; /* number of bits decoded by those */ +/* Decompress the imploded data using coded literals and an 8K sliding + window. */ +{ + long 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 */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + unsigned u; /* true if unflushed */ + + + /* 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]; + s = G.ucsize; + while (s > 0) /* do until ucsize bytes uncompressed */ + { + NEEDBITS(1) + if (b & 1) /* then literal--decode it */ + { + DUMPBITS(1) + s--; + NEEDBITS((unsigned)bb) /* get coded literal */ + if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + redirSlide[w++] = (uch)t->v.n; + if (w == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + } + else /* else distance/length */ + { + DUMPBITS(1) + NEEDBITS(7) /* get distance low bits */ + d = (unsigned)b & 0x7f; + DUMPBITS(7) + NEEDBITS((unsigned)bd) /* get coded distance high bits */ + if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + d = w - d - t->v.n; /* construct offset */ + NEEDBITS((unsigned)bl) /* get coded length */ + if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + n = t->v.n; + if (e) /* get length extra bits */ + { + NEEDBITS(8) + n += (unsigned)b & 0xff; + DUMPBITS(8) + } + + /* do the copy */ + s -= n; + do { +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) { + /* &= w/ wsize not needed and wrong if redirect */ + if (d >= wsize) + return 1; + n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); + } else +#endif + n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > 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 == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + } while (n); + } + } + + /* flush out redirSlide */ + flush(__G__ redirSlide, (ulg)w, 0); + 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_lit4(__G__ tb, tl, td, bb, bl, bd) + __GDEF +struct huft *tb, *tl, *td; /* literal, length, and distance tables */ +int bb, bl, bd; /* number of bits decoded by those */ +/* Decompress the imploded data using coded literals and a 4K sliding + window. */ +{ + long 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 */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + unsigned u; /* true if unflushed */ + + + /* 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]; + s = G.ucsize; + while (s > 0) /* do until ucsize bytes uncompressed */ + { + NEEDBITS(1) + if (b & 1) /* then literal--decode it */ + { + DUMPBITS(1) + s--; + NEEDBITS((unsigned)bb) /* get coded literal */ + if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + redirSlide[w++] = (uch)t->v.n; + if (w == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + } + else /* else distance/length */ + { + DUMPBITS(1) + NEEDBITS(6) /* get distance low bits */ + d = (unsigned)b & 0x3f; + DUMPBITS(6) + NEEDBITS((unsigned)bd) /* get coded distance high bits */ + if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + d = w - d - t->v.n; /* construct offset */ + NEEDBITS((unsigned)bl) /* get coded length */ + if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + n = t->v.n; + if (e) /* get length extra bits */ + { + NEEDBITS(8) + n += (unsigned)b & 0xff; + DUMPBITS(8) + } + + /* do the copy */ + s -= n; + do { +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) { + /* &= w/ wsize not needed and wrong if redirect */ + if (d >= wsize) + return 1; + n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); + } else +#endif + n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > 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 == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + } while (n); + } + } + + /* flush out redirSlide */ + flush(__G__ redirSlide, (ulg)w, 0); + 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_nolit8(__G__ tl, td, bl, bd) + __GDEF +struct huft *tl, *td; /* length and distance decoder tables */ +int bl, bd; /* number of bits decoded by tl[] and td[] */ +/* Decompress the imploded data using uncoded literals and an 8K sliding + window. */ +{ + long 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 */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + unsigned u; /* true if unflushed */ + + + /* 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]; + s = G.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 == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + DUMPBITS(8) + } + else /* else distance/length */ + { + DUMPBITS(1) + NEEDBITS(7) /* get distance low bits */ + d = (unsigned)b & 0x7f; + DUMPBITS(7) + NEEDBITS((unsigned)bd) /* get coded distance high bits */ + if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + d = w - d - t->v.n; /* construct offset */ + NEEDBITS((unsigned)bl) /* get coded length */ + if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + n = t->v.n; + if (e) /* get length extra bits */ + { + NEEDBITS(8) + n += (unsigned)b & 0xff; + DUMPBITS(8) + } + + /* do the copy */ + s -= n; + do { +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) { + /* &= w/ wsize not needed and wrong if redirect */ + if (d >= wsize) + return 1; + n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); + } else +#endif + n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > 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 == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + } while (n); + } + } + + /* flush out redirSlide */ + flush(__G__ redirSlide, (ulg)w, 0); + 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_nolit4(__G__ tl, td, bl, bd) + __GDEF +struct huft *tl, *td; /* length and distance decoder tables */ +int bl, bd; /* number of bits decoded by tl[] and td[] */ +/* Decompress the imploded data using uncoded literals and a 4K sliding + window. */ +{ + long 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 */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + unsigned u; /* true if unflushed */ + + + /* 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]; + s = G.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 == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + DUMPBITS(8) + } + else /* else distance/length */ + { + DUMPBITS(1) + NEEDBITS(6) /* get distance low bits */ + d = (unsigned)b & 0x3f; + DUMPBITS(6) + NEEDBITS((unsigned)bd) /* get coded distance high bits */ + if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + d = w - d - t->v.n; /* construct offset */ + NEEDBITS((unsigned)bl) /* get coded length */ + if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + n = t->v.n; + if (e) /* get length extra bits */ + { + NEEDBITS(8) + n += (unsigned)b & 0xff; + DUMPBITS(8) + } + + /* do the copy */ + s -= n; + do { +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) { + /* &= w/ wsize not needed and wrong if redirect */ + if (d >= wsize) + return 1; + n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); + } else +#endif + n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > 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 == wsize) + { + flush(__G__ redirSlide, (ulg)w, 0); + w = u = 0; + } + } while (n); + } + } + + /* flush out redirSlide */ + flush(__G__ redirSlide, (ulg)w, 0); + 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 */ + int bb; /* bits for tb */ + int bl; /* bits for tl */ + int bd; /* bits for td */ + unsigned l[256]; /* bit lengths for codes */ + +#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 + + /* 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; + + + /* With literal tree--minimum match length is 3 */ +#ifdef DEBUG + G.hufts = 0; /* initialize huft's malloc'ed */ +#endif + if (G.lrec.general_purpose_bit_flag & 4) + { + 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) + 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; + } + if ((r = get_tree(__G__ l, 64)) != 0) + return (int)r; + if (G.lrec.general_purpose_bit_flag & 2) /* true if 8K */ + { + if ((r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd)) != 0) + { + if (r == 1) + huft_free(td); + huft_free(tl); + huft_free(tb); + return (int)r; + } + r = explode_lit8(__G__ tb, tl, td, bb, bl, bd); + } + else /* else 4K */ + { + if ((r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd)) != 0) + { + if (r == 1) + huft_free(td); + huft_free(tl); + huft_free(tb); + return (int)r; + } + r = explode_lit4(__G__ tb, tl, td, bb, bl, bd); + } + huft_free(td); + huft_free(tl); + huft_free(tb); + } + else + + + /* No literal tree--minimum match length is 2 */ + { + 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) + return (int)r; + if (G.lrec.general_purpose_bit_flag & 2) /* true if 8K */ + { + if ((r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd)) != 0) + { + if (r == 1) + huft_free(td); + huft_free(tl); + return (int)r; + } + r = explode_nolit8(__G__ tl, td, bl, bd); + } + else /* else 4K */ + { + if ((r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd)) != 0) + { + if (r == 1) + huft_free(td); + huft_free(tl); + return (int)r; + } + r = explode_nolit4(__G__ tl, td, bl, bd); + } + 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 NEXTBYTE +#undef NEEDBITS +#undef DUMPBITS diff --git a/utils/Install/sfxzip/extract.c b/utils/Install/sfxzip/extract.c new file mode 100644 index 0000000000..bd142dcae5 --- /dev/null +++ b/utils/Install/sfxzip/extract.c @@ -0,0 +1,1993 @@ +/*--------------------------------------------------------------------------- + + 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() + extract_or_test_member() + TestExtraField() + test_compr_eb() + memextract() + memflush() + fnfilter() + + ---------------------------------------------------------------------------*/ + + +#define EXTRACT_C +#define UNZIP_INTERNAL +#include "unzip.h" +#include "crypt.h" +#ifdef WINDLL +# ifdef POCKET_UNZIP +# include "wince/intrface.h" +# else +# include "windll/windll.h" +# endif +#endif + +off_t acelseek(off_t offset, int whence); +int aceread(void *buf, size_t count); +int aceopen(const char *path, int flags); +int aceclose(int fd); +int acesize(void); +int acetell(int fd); +char *replacestr(char *str1, char *str2, char *str3); + +#define GRRDUMP(buf,len) { \ + int i, j; \ + \ + for (j = 0; j < (len)/16; ++j) { \ + pipeit(" "); \ + for (i = 0; i < 16; ++i) \ + pipeit("%02x ", (uch)(buf)[i+(j<<4)]); \ + pipeit("\n "); \ + for (i = 0; i < 16; ++i) { \ + char c = (char)(buf)[i+(j<<4)]; \ + \ + if (c == '\n') \ + pipeit("\\n "); \ + else if (c == '\r') \ + pipeit("\\r "); \ + else \ + pipeit(" %c ", c); \ + } \ + pipeit("\n"); \ + } \ + if ((len) % 16) { \ + pipeit(" "); \ + for (i = j<<4; i < (len); ++i) \ + pipeit("%02x ", (uch)(buf)[i]); \ + pipeit("\n "); \ + for (i = j<<4; i < (len); ++i) { \ + char c = (char)(buf)[i]; \ + \ + if (c == '\n') \ + pipeit("\\n "); \ + else if (c == '\r') \ + pipeit("\\r "); \ + else \ + pipeit(" %c ", c); \ + } \ + pipeit("\n"); \ + } \ +} + +static int store_info OF((__GPRO)); +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 +#ifdef SET_DIR_ATTRIB + static int 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 CmprEnDeflate[] = "enhanced deflate"; + static ZCONST char Far CmprDCLImplode[] = "DCL implode"; + static ZCONST char Far *ComprNames[NUM_METHODS] = { + CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce, + CmprImplode, CmprTokenize, CmprDeflate, CmprEnDeflate, CmprDCLImplode + }; +#endif /* !SFX */ +static ZCONST char Far FilNamMsg[] = + "%s: bad filename length (%s)\n"; +static ZCONST char Far ExtFieldMsg[] = + "%s: bad extra field length (%s)\n"; +static ZCONST char Far OffsetMsg[] = + "file #%u: bad zipfile offset (%s): %ld\n"; +static ZCONST char Far ExtractMsg[] = + "%8sing: %-22s %s%s"; +#ifndef SFX + static ZCONST char Far LengthMsg[] = + "%s %s: %ld bytes required to uncompress to %lu bytes;\n %s\ + supposed to require %lu 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 #%u: 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 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"; +#endif + +#ifndef WINDLL + static ZCONST char Far ReplaceQuery[] = + "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: "; + static ZCONST char Far AssumeNone[] = " NULL\n(assuming [N]one)\n"; + static ZCONST char Far NewNameQuery[] = "new name: "; + static ZCONST char Far InvalidResponse[] = "error: invalid response [%c]\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[] = + "%u 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 %u file%s tested.\n"; +static ZCONST char Far FilesSkipped[] = + "%u 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"; + +#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 +{ + uch *cd_inptr; + unsigned i, j, filnum=0, blknum=0; + int cd_incnt, renamed, query; + int error, error_in_archive=PK_COOL, *fn_matched=NULL, *xn_matched=NULL; +#ifdef WINDLL + int done_once = 0; +#else + extent len; +#endif + unsigned members_remaining, num_skipped=0, num_bad_pwd=0; + long cd_bufstart, bufstart, inbuf_offset, request; + LONGINT old_extra_bytes = 0L; +#ifdef SET_DIR_ATTRIB + unsigned num_dirs=0; + dirtime *dirlist=(dirtime *)NULL, **sorted_dirlist=(dirtime **)NULL; +#endif + + +/*--------------------------------------------------------------------------- + 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; + members_remaining = (unsigned)G.ecrec.total_entries_central_dir; + +#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. + ---------------------------------------------------------------------------*/ + + while (members_remaining) { + 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 (members_remaining && (j < DIR_BLKSIZ)) { + --members_remaining; + G.pInfo = &G.info[j]; + + if (readbuf(__G__ G.sig, 4) == 0) { + error_in_archive = PK_EOF; + members_remaining = 0; /* ...so no more left to do */ + break; + } + if (strncmp(G.sig, central_hdr_sig, 4)) { /* just to make sure */ + Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), + j + blknum*DIR_BLKSIZ + 1)); + Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); + error_in_archive = PK_BADERR; + members_remaining = 0; /* ...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 */ + members_remaining = 0; /* ...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")); + members_remaining = 0; + 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")); + members_remaining = 0; + 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))); + members_remaining = 0; + 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)) { + 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)) { + 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) */ + + + } /* 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. + -----------------------------------------------------------------------*/ + + for (i = 0; i < j; ++i) { + filnum++; /* filnum = 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(). */ + + /* ZLSEEK(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", + request, inbuf_offset)); + Trace((stderr, + "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", + bufstart, G.cur_zipfile_bufstart)); + if (request < 0) { + Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg), + G.zipfn, LoadFarString(ReportMsg))); + error_in_archive = PK_ERR; + if (filnum == 1 && G.extra_bytes != 0L) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(AttemptRecompensate))); + old_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", + request, inbuf_offset)); + Trace((stderr, + "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", + bufstart, G.cur_zipfile_bufstart)); + } else { + error_in_archive = PK_BADERR; + continue; /* this one hosed; try next */ + } + } + /* 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 if (bufstart != G.cur_zipfile_bufstart) { + Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n")); +#ifdef USE_STRM_INPUT + fseek((FILE *)G.zipfd,(LONGINT)bufstart,SEEK_SET); + G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd); +#else /* !USE_STRM_INPUT */ + G.cur_zipfile_bufstart = + acelseek((LONGINT)bufstart,SEEK_SET); +#endif /* ?USE_STRM_INPUT */ + if ((G.incnt = aceread((char *)G.inbuf,INBUFSIZ)) <= 0) + { + Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), + filnum, "lseek", 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), + filnum, "EOF", request)); + error_in_archive = PK_BADERR; + continue; /* but can still try next one */ + } + if (strncmp(G.sig, local_hdr_sig, 4)) { + Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), + filnum, LoadFarStringSmall(LocalHdrSig), request)); + /* + GRRDUMP(G.sig, 4) + GRRDUMP(local_hdr_sig, 4) + */ + error_in_archive = PK_ERR; + if ((filnum == 1 && G.extra_bytes != 0L) || + (G.extra_bytes == 0L && old_extra_bytes != 0L)) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(AttemptRecompensate))); + if (G.extra_bytes) { + old_extra_bytes = G.extra_bytes; + G.extra_bytes = 0L; + } else + G.extra_bytes = old_extra_bytes; /* third attempt */ + ZLSEEK(G.pInfo->offset) + if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */ + Info(slide, 0x401, ((char *)slide, + LoadFarString(OffsetMsg), filnum, "EOF", request)); + error_in_archive = PK_BADERR; + continue; /* but can still try next one */ + } + if (strncmp(G.sig, local_hdr_sig, 4)) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(OffsetMsg), filnum, + LoadFarStringSmall(LocalHdrSig), 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), + filnum)); + error_in_archive = error; /* only PK_EOF defined */ + continue; /* can still try next one */ + } + if ((error = do_string(__G__ G.lrec.filename_length, DS_FN)) != + 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 */ + } + } + +#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))); + ++num_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; + /* 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_ && !strchr(G.filename, '/')) { + char *p=G.filename-1; + + while (*++p) { + 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 = '/'; + } + } + } +#endif /* !SFX */ + + /* mapname can create dirs if not freshening or if renamed */ + if ((error = mapname(__G__ renamed)) > PK_WARN) { + if (error == IZ_CREATED_DIR) { +#ifdef SET_DIR_ATTRIB + dirtime *d_entry; + + d_entry = (dirtime *)malloc(sizeof(dirtime)); + if (d_entry == (dirtime *)NULL) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(DirlistEntryNoMem))); + } else { + unsigned eb_izux_flg; + + d_entry->next = dirlist; + dirlist = d_entry; + dirlist->fn = + (char *)malloc(strlen(G.filename) + 1); + if (dirlist->fn == (char *)NULL) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(DirlistEntryNoMem))); + dirlist = d_entry->next; + free(d_entry); + if (!error_in_archive) + error_in_archive = PK_WARN; + continue; + } + strcpy(dirlist->fn, G.filename); + dirlist->perms = G.pInfo->file_attr; +#ifdef USE_EF_UT_TIME + 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 ? &(dirlist->u.t3) : NULL), +#else + &(dirlist->u.t3), +#endif + dirlist->uidgid) + : 0; +#else /* !USE_EF_UT_TIME */ + eb_izux_flg = 0; +#endif /* ?USE_EF_UT_TIME */ + if (eb_izux_flg & EB_UT_FL_MTIME) { + TTrace((stderr, + "\nextract: Unix dir e.f. modtime = %ld\n", + dirlist->u.t3.mtime)); + } else { + dirlist->u.t3.mtime = dos_to_unix_time( + G.lrec.last_mod_dos_datetime); + } + if (eb_izux_flg & EB_UT_FL_ATIME) { + TTrace((stderr, + "\nextract: Unix dir e.f. actime = %ld\n", + dirlist->u.t3.atime)); + } else { + dirlist->u.t3.atime = + dirlist->u.t3.mtime; + } + dirlist->have_uidgid = + (uO.X_flag && (eb_izux_flg & EB_UX2_VALID)); + ++num_dirs; + } +#endif /* SET_DIR_ATTRIB */ + } else if (error == IZ_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 + /* if (!error_in_archive) + error_in_archive = PK_WARN; */ + } else if (error > PK_ERR && error_in_archive < PK_ERR) + error_in_archive = PK_ERR; + Trace((stderr, "mapname(%s) returns error = %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 + /* if freshening, don't skip if just renamed */ + if (uO.fflag && !renamed) + continue; /* freshen (no new files): skip */ + break; + case EXISTS_AND_OLDER: + if (uO.overwrite_none) { +#ifdef WINDLL + char szStr[FILNAMSIZ+40]; /* add. space for text */ + + if ((!G.prompt_always) || (done_once)) { + sprintf(szStr, + "Target file exists.\nSkipping %s\n", + FnFilter1(G.filename)); + win_fprintf((zvoid *)&G, stdout, + strlen(szStr), szStr); + } else { + query = TRUE; + break; + } +#endif /* WINDLL */ + continue; /* never overwrite: skip file */ + } +#ifdef UNIXBACKUP + if (!uO.overwrite_all && !uO.B_flag) +#else + if (!uO.overwrite_all) +#endif + query = TRUE; + break; + case EXISTS_AND_NEWER: /* (or equal) */ + if (uO.overwrite_none || (uO.uflag && !renamed)) { +#ifdef WINDLL + char szStr[FILNAMSIZ+40]; /* add. space for text */ + + if ((!G.prompt_always) || (done_once)) { + sprintf(szStr, + "Target file newer.\nSkipping %s\n", + FnFilter1(G.filename)); + win_fprintf((zvoid *)&G, stdout, + strlen(szStr), szStr); + } else { + query = TRUE; + break; + } +#endif /* WINDLL */ + continue; /* skip if update/freshen & orig name */ + } +#ifdef UNIXBACKUP + if (!uO.overwrite_all && !uO.B_flag) +#else + if (!uO.overwrite_all) +#endif + query = TRUE; + break; + } + if (query) { +#ifdef WINDLL + switch (G.lpUserFunctions->replace != NULL ? + (*G.lpUserFunctions->replace)(G.filename) : + IDM_REPLACE_NONE) { + case IDM_REPLACE_RENAME: + _ISO_INTERN(G.filename); + renamed = TRUE; + goto startover; + case IDM_REPLACE_YES: + break; + case IDM_REPLACE_ALL: + uO.overwrite_all = TRUE; + uO.overwrite_none = FALSE; /* just to make sure */ + break; + case IDM_REPLACE_NONE: + uO.overwrite_none = TRUE; + uO.overwrite_all = FALSE; /* make sure */ + done_once = TRUE; + /* FALL THROUGH, skip */ + case IDM_REPLACE_NO: + { + char szStr[FILNAMSIZ+40]; + + sprintf(szStr, + "Target file newer.\nSkipping %s\n", + FnFilter1(G.filename)); + win_fprintf((zvoid *)&G, stdout, + strlen(szStr), szStr); + } + continue; + } +#else /* !WINDLL */ +reprompt: + Info(slide, 0x81, ((char *)slide, + LoadFarString(ReplaceQuery), + FnFilter1(G.filename))); + if (fgets(G.answerbuf, 9, 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 'A': /* dangerous option: force caps */ + uO.overwrite_all = TRUE; + uO.overwrite_none = FALSE; /* just to make sure */ + break; + 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 */ + len = strlen(G.filename); + if (G.filename[len-1] == '\n') + G.filename[--len] = '\0'; + } while (len == 0); +#ifdef WIN32 /* WIN32 fgets( ... , stdin) returns OEM coded strings */ + _OEM_INTERN(G.filename); +#endif + renamed = TRUE; + goto startover; /* sorry for a goto */ + case 'y': + case 'Y': + break; + case 'N': + uO.overwrite_none = TRUE; + uO.overwrite_all = FALSE; /* make sure */ + /* FALL THROUGH, skip */ + case 'n': + continue; /* skip file */ + default: + Info(slide, 1, ((char *)slide, + LoadFarString(InvalidResponse), *G.answerbuf)); + goto reprompt; /* yet another goto? */ + } /* end switch (*answerbuf) */ +#endif /* ?WINDLL */ + } /* end if (query) */ + } /* end if (extracting to disk) */ + +#ifdef DLL + if ((G.statreportcb != NULL) && + (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn, + G.filename, NULL)) { + if (fn_matched) + free((zvoid *)fn_matched); + if (xn_matched) + free((zvoid *)xn_matched); + 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 + if (fn_matched) + free((zvoid *)fn_matched); + if (xn_matched) + free((zvoid *)xn_matched); + 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)) { + if (fn_matched) + free((zvoid *)fn_matched); + if (xn_matched) + free((zvoid *)xn_matched); + 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) */ + + + /* + * Jump back to where we were in the central directory, then go and do + * the next batch of files. + */ + +#ifdef USE_STRM_INPUT + fseek((FILE *)G.zipfd, (LONGINT)cd_bufstart, SEEK_SET); + G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd); +#else /* !USE_STRM_INPUT */ + G.cur_zipfile_bufstart = acelseek((LONGINT)cd_bufstart,SEEK_SET); +#endif /* ?USE_STRM_INPUT */ + aceread((char *)G.inbuf, INBUFSIZ); /* been here before... */ + G.inptr = cd_inptr; + G.incnt = cd_incnt; + ++blknum; + +#ifdef TEST + pipeit("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart); + pipeit("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart, + cur_zipfile_bufstart); + pipeit("inptr-inbuf = %d\n", G.inptr-G.inbuf); + pipeit("incnt = %d\n\n", G.incnt); +#endif + + } /* end while-loop (blocks of files in central directory) */ + +/*--------------------------------------------------------------------------- + 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 = (dirtime **)malloc(num_dirs*sizeof(dirtime *)); + if (sorted_dirlist == (dirtime **)NULL) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(DirlistSortNoMem))); + while (dirlist != (dirtime *)NULL) { + dirtime *d = dirlist; + + dirlist = dirlist->next; + free(d); + } + } else { + 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(dirtime *), + dircomp); + } + + Trace((stderr, "setting directory times/perms/attributes\n")); + for (i = 0; i < num_dirs; ++i) { + dirtime *d = sorted_dirlist[i]; + + Trace((stderr, "dir = %s\n", d->fn)); + if ((error = set_direc_attribs(__G__ d)) != PK_OK) { + Info(slide, 0x201, ((char *)slide, + LoadFarString(DirlistSetAttrFailed), d->fn)); + if (!error_in_archive) + error_in_archive = error; + } + free(d->fn); + free(d); + } + free(sorted_dirlist); + } + } +#endif /* SET_DIR_ATTRIB */ + +#if (defined(WIN32) && defined(NTSD_EAS)) + process_defer_NT(__G); /* process any deferred items for this .zip file */ +#endif + +/*--------------------------------------------------------------------------- + Check for unmatched filespecs on command line and print warning if any + found. Free allocated memory. + ---------------------------------------------------------------------------*/ + + if (fn_matched) { + 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) { + 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); + } + +/*--------------------------------------------------------------------------- + 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 (readbuf(__G__ G.sig, 4) == 0) + error_in_archive = PK_EOF; + if (strncmp(G.sig, end_central_sig, 4)) { /* 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) { + unsigned 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 == 1)? "warning-" : "", G.zipfn)); + else if (num == 0) + Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested), + G.zipfn)); + else if (G.process_all_files && (num_skipped+num_bad_pwd == 0)) + Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData), + G.zipfn)); + else + Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles) + , G.zipfn, num, (num==1)? "":"s")); + if (num_skipped > 0) + Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped), + num_skipped, (num_skipped==1)? "":"s")); +#if CRYPT + if (num_bad_pwd > 0) + Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd) + , num_bad_pwd, (num_bad_pwd==1)? "":"s")); +#endif /* CRYPT */ + } else if ((uO.qflag == 0) && !error_in_archive && (num == 0)) + Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested), + G.zipfn)); + } + + /* 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 > 0) + 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 > 0) && error_in_archive <= PK_WARN) + error_in_archive = IZ_UNSUP; /* was PK_WARN; Jean-loup complained */ +#if CRYPT + else if ((num_bad_pwd > 0) && !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 SFX +# define UNKN_COMPR \ + (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED) +#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 +# define UNKN_COMPR (UNKN_RED || UNKN_SHR || \ + G.crec.compression_method==TOKENIZED || G.crec.compression_method>DEFLATED) +#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 && !uO.overwrite_all) { /* if -o, extract anyway */ + Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery), + FnFilter1(G.filename))); + fgets(G.answerbuf, 9, 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] > UNZIP_VERSION) { + 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, + UNZIP_VERSION / 10, UNZIP_VERSION % 10)); + return 0; + } + + if UNKN_COMPR { + if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) { +#ifndef SFX + if (G.crec.compression_method < NUM_METHODS) + Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName), + FnFilter1(G.filename), + LoadFarStringSmall(ComprNames[G.crec.compression_method]))); + 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 */ + + /* map whatever file attributes we have into the local format */ + mapattr(__G); /* GRR: worry about return value later */ + + G.pInfo->offset = (long)G.crec.relative_offset_local_header; + return 1; + +} /* end function store_info() */ + + + + + +/***************************************/ +/* 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; +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + ulg wsize; +#else +# define wsize WSIZE +#endif + + +/*--------------------------------------------------------------------------- + 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 came from Unix and is a symbolic link and we are extracting + * to disk, prepare to restore the link */ + if (S_ISLNK(G.pInfo->file_attr) && + (G.pInfo->hostnum == UNIX_ || G.pInfo->hostnum == ATARI_ || + G.pInfo->hostnum == BEOS_) && + !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0)) + G.symlnk = TRUE; + else + G.symlnk = FALSE; +#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_H68_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_H68_OS2_W32 */ +# define NEWLINE "\n" +#endif /* ?DOS_FLX_H68_OS2_W32 */ +#ifdef VMS + if (open_outfile(__G)) /* VMS: required even for stdout! */ + return PK_DISK; +#endif + } else if (open_outfile(__G)) + return PK_DISK; + } + +/*--------------------------------------------------------------------------- + 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.disk_full) { + *G.outptr++ = (uch)b; + if (++G.outcnt == wsize) { + flush(__G__ redirSlide, G.outcnt, 0); + G.outptr = redirSlide; + G.outcnt = 0L; + } + } + if (G.outcnt) /* flush final (partial) buffer */ + flush(__G__ redirSlide, G.outcnt, 0); + 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 ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall(ErrUnzipFile), + LoadFarString(NotEnoughMem), + LoadFarStringSmall2(Unshrink), + FnFilter1(G.filename))); + else + Info(slide, 0x401, ((char *)slide, + LoadFarStringSmall(ErrUnzipNoFile), + LoadFarString(NotEnoughMem), + 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 : "")); + } + unreduce(__G); + 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) && (r != 5)) { /* treat 5 specially */ + 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; + } + if (r == 5) { + int warning = ((ulg)G.used_csize <= G.lrec.csize); + + if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) + Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg), + "", warning? "warning" : "error", G.used_csize, + G.lrec.ucsize, warning? " " : "", G.lrec.csize, + " [", FnFilter1(G.filename), "]")); + else + Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg), + "\n", warning? "warning" : "error", G.used_csize, + G.lrec.ucsize, warning? " ":"", G.lrec.csize, + "", "", ".")); + error = warning? PK_WARN : PK_ERR; + } + break; +#endif /* !SFX */ + + case DEFLATED: + 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)) != 0) { + 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; + } + break; + + 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: + 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: + 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: + 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_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 ((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, *src; /* return PK-type error */ + ulg tgtsize, srcsize; /* level */ +{ + long 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 = 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 = G.csize; /* for CRC calculation */ + break; + case DEFLATED: + G.outcnt = 0L; + if ((r = UZinflate(__G)) != 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 + uch *rawbuf; + ulg size; +{ + if (size > G.outsize) + return 50; /* 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() */ + + + + + +/*************************/ +/* Function fnfilter() */ /* here instead of in list.c for SFX */ +/*************************/ + +char *fnfilter(raw, space) /* convert name to safely printable form */ + ZCONST char *raw; + uch *space; +{ +#ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */ + uch *r=(uch *)raw, *s=space; + + while (*r) { +#ifdef QDOS + if (qlflag & 2) { + if (*r == '/' || *r == '.') { + ++r; + *s++ = '_'; + continue; + } + } else +#endif + if (*r < 32) + *s++ = '^', *s++ = (uch)(64 + *r++); + else + *s++ = *r++; + } + *s = 0; + +#ifdef WINDLL + INTERN_TO_ISO((char *)space, (char *)space); /* translate to ANSI */ +#else +#ifdef WIN32 + /* 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 */ +#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 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((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); + /* return namecmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); */ +} + + + +#if 0 /* not used in Unix, but maybe for future OSes? */ + +/************************/ +/* Function namecmp() */ +/************************/ + +static int namecmp(s1, s2) /* [not] used by dircomp(); swiped from Zip */ + ZCONST char *s1, *s2; +{ + int d; + + for (;;) { + d = (int)(uch)case_map(*s1) + - (int)(uch)case_map(*s2); + + if (d || *s1 == 0 || *s2 == 0) + return d; + + s1++; + s2++; + } +} + +#endif /* 0 */ +#endif /* SET_DIR_ATTRIB */ diff --git a/utils/Install/sfxzip/fileio.c b/utils/Install/sfxzip/fileio.c new file mode 100644 index 0000000000..9ee4ed3a92 --- /dev/null +++ b/utils/Install/sfxzip/fileio.c @@ -0,0 +1,2161 @@ +/*--------------------------------------------------------------------------- + + 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() (non-VMS, non-AOS/VS, non-CMS_MVS) + undefer_input() + defer_leftover_input() + readbuf() + readbyte() + fillinbuf() + flush() (non-VMS) + 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() + str2iso() (CRYPT && NEED_STR2ISO, only) + str2oem() (CRYPT && NEED_STR2OEM, only) + memset() (ZMEM only) + memcpy() (ZMEM only) + zstrnicmp() + zstat() (REGULUS only) + fLoadFarString() (SMALL_MEM only) + fLoadFarStringSmall() (SMALL_MEM only) + fLoadFarStringSmall2() (SMALL_MEM only) + zfstrcpy() (SMALL_MEM only) + + ---------------------------------------------------------------------------*/ + + +#define FILEIO_C +#define UNZIP_INTERNAL +#include "unzip.h" +#ifdef WINDLL +# include "windll/windll.h" +# include +#endif +#include "crypt.h" +#include "ttyio.h" + +off_t acelseek(off_t offset, int whence); +int aceread(void *buf, size_t count); +int aceopen(const char *path, int flags); +int aceclose(int fd); +int acesize(void); +int acetell(int fd); +char *replacestr(char *str1, char *str2, char *str3); + +/* 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 */ + +static int disk_error OF((__GPRO)); + + +/****************************/ +/* Strings used in fileio.c */ +/****************************/ + +#if (defined(UNIX) || defined(DOS_FLX_OS2_W32) || defined(__BEOS__)) + static ZCONST char Far CannotDeleteOldFile[] = + "error: cannot delete old %s\n"; +#ifdef UNIXBACKUP + static ZCONST char Far CannotRenameOldFile[] = + "error: cannot rename old %s\n"; + static ZCONST char Far BackupSuffix[] = "~"; +#endif +#endif /* UNIX || DOS_FLX_OS2_W32 || __BEOS__ */ + +static ZCONST char Far CannotOpenZipfile[] = + "error: cannot open zipfile [ %s ]\n"; +#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) + static ZCONST char Far CannotCreateFile[] = "error: cannot create %s\n"; +#endif +#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 ReadError[] = "error: zipfile read error\n"; +static ZCONST char Far FilenameTooLongTrunc[] = + "warning: filename too long--truncating.\n"; +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 + */ + +#if (defined(UNIX) || defined(TOPS20) || defined(AOS_VS) || defined(__BEOS__)) + G.zipfd = aceopen(G.zipfn, O_RDONLY); +#else /* !(UNIX || TOPS20 || AOS_VS || __BEOS__) */ +#ifdef VMS + G.zipfd = open(G.zipfn, O_RDONLY, 0, "ctx=stm"); +#else /* !VMS */ +#ifdef MACOS + G.zipfd = aceopen(G.zipfn, 0); +#else /* !MACOS */ +#ifdef RISCOS + G.zipfd = fopen(G.zipfn, "rb"); +#else /* !RISCOS */ +#ifdef CMS_MVS + G.zipfd = vmmvs_open_infile(__G); +#else /* !CMS_MVS */ + G.zipfd = aceopen(G.zipfn, O_RDONLY | O_BINARY); +#endif /* ?CMS_MVS */ +#endif /* ?RISCOS */ +#endif /* ?MACOS */ +#endif /* ?VMS */ +#endif /* ?(UNIX || TOPS20 || AOS_VS || __BEOS__) */ + +#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)); + return 1; + } + return 0; + +} /* end function open_input_file() */ + + + + +#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) + +/***************************/ +/* 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_OS2_W32) || defined(UNIX) || defined(__BEOS__)) +#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; + int blen, flen, tlen; + + blen = strlen(BackupSuffix); + flen = strlen(G.filename); + tlen = flen + blen + 1; + 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'; + } 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); + + /* GRR: should check if backup file exists, apply -n/-o to that */ + if (rename(G.filename, tname) < 0) { /* move file */ + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotRenameOldFile), FnFilter1(G.filename))); + free(tname); + return 1; + } + 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 */ + if (unlink(G.filename) != 0) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename))); + return 1; + } + Trace((stderr, "open_outfile: %s now deleted\n", + FnFilter1(G.filename))); + } +#endif /* DOS_FLX_OS2_W32 || UNIX || __BEOS__ */ +#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))); + 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)); + free(tfilnam); + return 1; + } + free(tfilnam); +#else /* !TOPS20 */ +#ifdef MTS + if (uO.aflag) + G.outfile = fopen(G.filename, FOPWT); + else + G.outfile = fopen(G.filename, FOPW); + if (G.outfile == (FILE *)NULL) { + Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), + FnFilter1(G.filename))); + return 1; + } +#else /* !MTS */ +#ifdef TANDEM + if (SSTAT(G.filename, &G.statbuf) == 0) { + Trace((stderr, "open_outfile: stat(%s) returns 0 (file exists)\n", + FnFilter1(G.filename))); + if (unlink(G.filename) != 0) { + Trace((stderr, "open_outfile: existing file %s is read-only\n", + FnFilter1(G.filename))); + chmod(G.filename, S_IRUSR | S_IWUSR); + Trace((stderr, "open_outfile: %s now writable\n", + FnFilter1(G.filename))); + if (unlink(G.filename) != 0) + return 1; + } + Trace((stderr, "open_outfile: %s now deleted\n", + FnFilter1(G.filename))); + } + if (G.pInfo->textmode) + G.outfile = fopen(G.filename, FOPWT); + else + G.outfile = fopen(G.filename, FOPW); + if (G.outfile == (FILE *)NULL) { + Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), + FnFilter1(G.filename))); + return 1; + } +#else /* !TANDEM */ +#ifdef DEBUG + Info(slide, 1, ((char *)slide, + "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G.filename))); + if ((G.outfile = fopen(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 = fopen(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 ((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))); +#endif /* !TANDEM */ +#endif /* !MTS */ +#endif /* !TOPS20 */ + +#ifdef USE_FWRITE +#ifdef DOS_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_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_OS2_W32 */ +#endif /* USE_FWRITE */ + return 0; + +} /* end function open_outfile() */ + +#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 ((long)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 = aceread((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 = aceread((char *)G.inbuf, INBUFSIZ)) == 0) { + G.incnt = 0; /* do not allow negative value to affect stuff */ + 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() */ + + + + + +#ifdef USE_ZLIB + +/************************/ +/* Function fillinbuf() */ +/************************/ + +int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */ + __GDEF +{ + if (G.mem_mode || + (G.incnt = aceread((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 */ + + + + + +#ifndef VMS /* for VMS use code in vms.c */ + +/********************/ +/* Function flush() */ /* returns PK error codes: */ +/********************/ /* if cflag => always 0; PK_DISK if write error */ + +int flush(__G__ rawbuf, size, unshrink) + __GDEF + uch *rawbuf; + ulg size; + int unshrink; +{ + register uch *p, *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) + writeToMemory(__G__ rawbuf, size); + 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 0; + } 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", OUTBUFSIZ)); +#endif + } + if (G.newfile) { +#ifdef VMS_TEXT_CONV + /* GRR: really want to check if -aa (or -aaa?) was given... */ + if (rawbuf[1]) { /* first line is more than 255 chars long */ + Trace((stderr, + "\nfirst line of VMS `text' too long; switching to normal extraction\n")); + G.VMS_line_state = -1; /* -1: don't treat as VMS text */ + } else + G.VMS_line_state = 0; /* 0: ready to read line length */ +#endif + G.didCRlast = FALSE; /* no previous buffers written */ + G.newfile = FALSE; + } + +#ifdef VMS_TEXT_CONV + if (G.pInfo->hostnum == VMS_ && G.extra_field && G.VMS_line_state >= 0) + { + /* GRR: really want to check for actual VMS extra field, and + * ideally for variable-length record format */ +/* + printf("\n>>>>>> GRR: file is VMS text and has an extra field\n"); + */ + + p = rawbuf; + q = transbuf; + while(p < rawbuf+(unsigned)size) { + switch (G.VMS_line_state) { + + /* 0: ready to read line length */ + case 0: + G.VMS_line_length = 0; + G.VMS_line_pad = 0; + if (p == rawbuf+(unsigned)size-1) { /* last char */ + G.VMS_line_length = (int)((uch)(*p++)); + G.VMS_line_state = 1; + } else { + G.VMS_line_length = makeword(p); + p += 2; + G.VMS_line_state = 2; + } + if (G.VMS_line_length & 1) /* odd */ + G.VMS_line_pad = 1; + break; + + /* 1: read one byte of length, need second */ + case 1: + G.VMS_line_length += ((int)((uch)(*p++)) << 8); + G.VMS_line_state = 2; + break; + + /* 2: ready to read VMS_line_length chars */ + case 2: + if (G.VMS_line_length < rawbuf+(unsigned)size-p) { + if (G.VMS_line_length >= + transbuf+(unsigned)transbufsiz-q) + { + int outroom = transbuf+(unsigned)transbufsiz-q; + +/* GRR: need to change this to *q++ = native(*p++); loop or something */ + memcpy(q, p, outroom); +#ifdef DLL + if (G.redirect_data) + writeToMemory(__G__ transbuf, + (unsigned)outroom); + else +#endif + if (!uO.cflag && WriteError(transbuf, + (unsigned)outroom, G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, + transbuf, (ulg)outroom, 0)) + return 0; + q = transbuf; + p += outroom; + G.VMS_line_length -= outroom; + /* fall through to normal case */ + } +/* GRR: need to change this to *q++ = native(*p++); loop or something */ + memcpy(q, p, G.VMS_line_length); + q += G.VMS_line_length; + p += G.VMS_line_length; + G.VMS_line_length = 0; /* necessary?? */ + G.VMS_line_state = 3; + + } else { /* remaining input is less than full line */ + int remaining = rawbuf+(unsigned)size-p; + + if (remaining < + transbuf+(unsigned)transbufsiz-q) + { + int outroom = transbuf+(unsigned)transbufsiz-q; + +/* GRR: need to change this to *q++ = native(*p++); loop or something */ + memcpy(q, p, outroom); +#ifdef DLL + if (G.redirect_data) + writeToMemory(__G__ transbuf, + (unsigned)(outroom)); + else +#endif + if (!uO.cflag && WriteError(transbuf, + (unsigned)outroom, G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, + transbuf, (ulg)outroom, 0)) + return 0; + q = transbuf; + p += outroom; + remaining -= outroom; + } +/* GRR: need to change this to *q++ = native(*p++); loop or something */ + memcpy(q, p, remaining); + q += remaining; + p += remaining; + G.VMS_line_length -= remaining; + /* no change in G.VMS_line_state */ + } + break; + + /* 3: ready to PutNativeEOL */ + case 3: + if (q > transbuf+(unsigned)transbufsiz-lenEOL) { +#ifdef DLL + if (G.redirect_data) + writeToMemory(__G__ transbuf, + (unsigned)(q-transbuf)); + else +#endif + if (!uO.cflag && + WriteError(transbuf, (unsigned)(q-transbuf), + G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, + transbuf, (ulg)(q-transbuf), 0)) + return 0; + q = transbuf; + } + PutNativeEOL + if (G.VMS_line_pad) + if (p < rawbuf+(unsigned)size) { + ++p; + G.VMS_line_state = 0; + } else + G.VMS_line_state = 4; + else + G.VMS_line_state = 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; p < rawbuf+(unsigned)size; ++p) { + if (*p == CR) { /* lone CR or CR/LF: EOL either way */ + PutNativeEOL + if (p == rawbuf+(unsigned)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+(unsigned)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, + (unsigned)(q-transbuf), G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, + transbuf, (ulg)(q-transbuf), 0)) + return 0; + 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) + writeToMemory(__G__ transbuf, (unsigned)(q-transbuf)); + else +#endif + if (!uO.cflag && WriteError(transbuf, (unsigned)(q-transbuf), + G.outfile)) + return disk_error(__G); + else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, + (ulg)(q-transbuf), 0)) + return 0; + } + } + + return 0; + +} /* end function flush() */ + + + + + +/*************************/ +/* 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, 9, 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-1; +#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 + /* room for --More-- and one line of overlap: */ + ((Uz_Globs *)pG)->height = SCREENLINES - 2; +#endif + + 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) + { + ++((Uz_Globs *)pG)->numlines; + if (((Uz_Globs *)pG)->numlines % + ((Uz_Globs *)pG)->height == 0L) /* GRR: fix */ + (*((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') { + ++((Uz_Globs *)pG)->numlines; + if (((Uz_Globs *)pG)->numlines % + ((Uz_Globs *)pG)->height == 0L) /* GRR: fix */ + { + if ((error = WriteError(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); + } + } + } /* end while */ + size = (ulg)(p - q); /* remaining text */ + } +#endif /* MORE */ + + if (size) { +#ifdef OS2DLL + if (!((Uz_Globs *)pG)->redirect_text) { +#endif + if ((error = WriteError(q, size, outfp)) != 0) + return error; + fflush(outfp); + if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag && + !isatty(1) && isatty(2)) + { + /* error output from testing redirected: also send to stderr */ + if ((error = WriteError(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 + ((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 */ + { +#if 0 + 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 (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 (ToLower(c) == 'q') { + DESTROYGLOBALS() + EXIT(PK_COOL); + } + + ((Uz_Globs *)pG)->sol = TRUE; + +#endif +} /* 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 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(AMIGA) || 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_UNKNOWN) + { + 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 && !uO.overwrite_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 && !uO.overwrite_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__ len, option) /* return PK-type error code */ + __GDEF + unsigned int len; /* without prototype, ush converted to this */ + int option; +{ + long comment_bytes_left, block_length; + int error=PK_OK; + ush extra_len; +#ifdef AMIGA + char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */ +#endif + + +/*--------------------------------------------------------------------------- + This function processes arbitrary-length (well, usually) strings. Four + options are allowed: SKIP, wherein the string is skipped (pretty logical, + eh?); DISPLAY, wherein the string is printed to standard output after un- + dergoing any necessary or unnecessary character conversions; DS_FN, + wherein the string is put into the filename[] array after undergoing ap- + propriate 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 len. So start off by checking length + of string: if zero, we're already done. + ---------------------------------------------------------------------------*/ + + if (!len) + return PK_COOL; + + switch (option) { + + /* + * First case: print string on standard output. First set loop vari- + * ables, 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 = len; + block_length = OUTBUFSIZ; /* for the while statement, first time */ + while (comment_bytes_left > 0 && block_length > 0) { + register uch *p = G.outbuf; + register uch *q = G.outbuf; + + if ((block_length = readbuf(__G__ (char *)G.outbuf, + (unsigned) MIN((long)OUTBUFSIZ, comment_bytes_left))) == 0) + return PK_EOF; + comment_bytes_left -= block_length; + + /* this is why we allocated an extra byte for outbuf: terminate + * with zero (ASCIIZ) */ + G.outbuf[(unsigned)block_length] = '\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_length 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.crec.version_made_by[0]); +#ifdef WINDLL + /* translate to ANSI (RTL internal codepage may be OEM) */ + INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf); +#else /* !WINDLL */ +#ifdef WIN32 + /* 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 */ +#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, len, (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: + extra_len = 0; + if (len >= FILNAMSIZ) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(FilenameTooLongTrunc))); + error = PK_WARN; + extra_len = (ush)(len - FILNAMSIZ + 1); + len = FILNAMSIZ - 1; + } + if (readbuf(__G__ G.filename, len) == 0) + return PK_EOF; + G.filename[len] = '\0'; /* terminate w/zero: ASCIIZ */ + + /* 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.crec.version_made_by[0]); + + if (G.pInfo->lcflag) /* replace with lowercase filename */ + TOLOWER(G.filename, G.filename); + + if (G.pInfo->vollabel && len > 8 && G.filename[8] == '.') { + char *p = G.filename+8; + while (*p++) + p[-1] = *p; /* disk label, and 8th char is dot: remove dot */ + } + + if (!extra_len) /* 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))); + len = extra_len; + /* 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: */ + ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes + + (G.inptr-G.inbuf) + len) + 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(len)) == (uch *)NULL) { + Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong), + len)); + /* cur_zipfile_bufstart already takes account of extra_bytes, + * so don't correct for it twice: */ + ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes + + (G.inptr-G.inbuf) + len) + } else + if (readbuf(__G__ (char *)G.extra_field, len) == 0) + return PK_EOF; + 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 ((extra_len = readbuf(__G__ tmp_fnote, (unsigned) + MIN(len, 2 * AMIGA_FILENOTELEN - 1))) == 0) + return PK_EOF; + if ((len -= extra_len) > 0) /* treat remainder as in case SKIP: */ + ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes + + (G.inptr - G.inbuf) + len) + /* convert multi-line text into single line with no ctl-chars: */ + tmp_fnote[extra_len] = '\0'; + while ((short int) --extra_len >= 0) + if ((unsigned) tmp_fnote[extra_len] < ' ') + if (tmp_fnote[extra_len+1] == ' ') /* no excess */ + strcpy(tmp_fnote+extra_len, tmp_fnote+extra_len+1); + else + tmp_fnote[extra_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)sig[1]) << 8) + + ((ulg)sig[0]); +} + + + +#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 */ + + + + + +/************************/ +/* 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 (ToLower(*s1) < ToLower(*s2))? -1 : 1; + + if (*s1 == '\0') /* both strings terminate early */ + return 0; + } + return 0; +} + + + + + +#ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */ +# undef stat + +/********************/ +/* Function zstat() */ +/********************/ + +int zstat(p, s) + char *p; + struct stat *s; +{ + return (stat(p,s) >= 0? 0 : (-1)); +} + +#endif /* REGULUS */ + + + + + +#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; +} +#endif /* !_MSC_VER || (_MSC_VER < 600) */ + +#endif /* SMALL_MEM */ diff --git a/utils/Install/sfxzip/funzip.c b/utils/Install/sfxzip/funzip.c new file mode 100644 index 0000000000..e83ae424d2 --- /dev/null +++ b/utils/Install/sfxzip/funzip.c @@ -0,0 +1,468 @@ +/* funzip.c -- put in the public domain by Mark Adler */ + +#define VERSION "3.93 of 21 November 1998" + + +/* 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 + */ + + +/* + + 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 zcrypt21.zip or later must be used. + + */ + +#define FUNZIP +#define UNZIP_INTERNAL +#include "unzip.h" +#include "crypt.h" +#include "ttyio.h" + +#ifdef EBCDIC +# undef EBCDIC /* don't need ebcdic[] */ +#endif +#include "tables.h" /* crc_32_tab[] */ + +#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 */ + +/* 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)) + +/* Function prototypes */ +void err OF((int, char *)); +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 ush near mask_bits[] = { + 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 */ + + +#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) +#ifdef USE_ZLIB +ZCONST uLongf *get_crc_table() +{ + return (ZCONST uLongf *)crc_32_tab; +} +#else /* !USE_ZLIB */ +ZCONST ulg near *get_crc_table() +{ + return crc_32_tab; +} +#endif /* ?USE_ZLIB */ +#endif /* !USE_ZLIB || USE_OWN_CRCTAB */ + + +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); +} + + +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; +} + + +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 */ +#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 + G.area.Slide = (uch *)calloc(8193, sizeof(short)+sizeof(char)+sizeof(char)); +#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_H68_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_H68_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_OS2_W32 +#if (defined(__HIGHC__) && !defined(FLEXOS)) + setmode(stdout, _BINARY); +#else + setmode(1, O_BINARY); +#endif +#endif /* DOS_FLX_H68_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"); + if (SH(h + LOCHOW) != STORED && SH(h + LOCHOW) != DEFLATED) + err(3, "first entry not deflated or stored--cannot unpack"); + 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 (h[GZPHOW] != DEFLATED) + 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"); + } +#if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB)) + /* initialize crc_32_tab pointer for decryption */ + CRC_32_TAB = (ZCONST ulg Far *)get_crc_table(); +#endif + 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)) != 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 (++G.outcnt == WSIZE) /* do FlushOutput() */ + { + 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/utils/Install/sfxzip/globals.c b/utils/Install/sfxzip/globals.c new file mode 100644 index 0000000000..d795090b98 --- /dev/null +++ b/utils/Install/sfxzip/globals.c @@ -0,0 +1,204 @@ +/*--------------------------------------------------------------------------- + + 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}; +/* 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 + + 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_OS2_W32) && !defined(AMIGA) && !defined(RISCOS)) +#if (!defined(MACOS) && !defined(ATARI) && !defined(VMS)) + G.echofd = -1; +#endif /* !(MACOS || ATARI || VMS) */ +#endif /* !(DOS_FLX_H68_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/utils/Install/sfxzip/inflate.c b/utils/Install/sfxzip/inflate.c new file mode 100644 index 0000000000..29877300d2 --- /dev/null +++ b/utils/Install/sfxzip/inflate.c @@ -0,0 +1,1305 @@ +/* inflate.c -- put in the public domain by Mark Adler + version c16b, 29 March 1998 */ + + +/* 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 + */ + + +/* + 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 + */ + + +/* + 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. + */ + + +#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 DEBUG */ +#define INFMOD /* tell inflate.h to include code to be compiled */ +#include "inflate.h" + + +#ifndef WSIZE /* default is 32K */ +# define WSIZE 0x8000 /* window size--must be a power of two, and at least */ +#endif /* 32K for zip's deflate method */ + +#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) pipeit((char *)(str)) +#endif + +#ifndef FLUSH /* default is to simply write the buffer to stdout */ +# define FLUSH(n) fwrite(redirSlide, 1, n, stdout) /* return value not used */ +#endif +/* Warning: the fwrite above might not work on 16-bit compilers, since + 0x8000 might be interpreted as -32,768 by the library function. */ + +#ifndef Trace +# ifdef DEBUG +# define Trace(x) fprintf x +# else +# define Trace(x) +# endif +#endif + + +/*---------------------------------------------------------------------------*/ +#ifdef USE_ZLIB + + +/* + 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) /* decompress an inflated entry using the zlib routines */ + __GDEF +{ + int err=Z_OK; + +#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; + + /* only need to test this stuff once */ + if (zlib_version[0] != ZLIB_VERSION[0]) { + Info(slide, 0x21, ((char *)slide, + "error: incompatible zlib version (expected %s, found %s)\n", + ZLIB_VERSION, zlib_version)); + return 3; + } else if (strcmp(zlib_version, ZLIB_VERSION) != 0) + Info(slide, 0x21, ((char *)slide, + "warning: different zlib version (expected %s, using %s)\n", + ZLIB_VERSION, zlib_version)); + + /* windowBits = log2(wsize) */ + for (i = ((unsigned)wsize * 2 - 1), 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) + return 2; + else if (err == Z_MEM_ERROR) + return 3; + 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) + return 2; /* no "END-condition" yet, but no more data */ + + G.dstrm.next_in = G.inptr; + G.dstrm.avail_in = G.incnt; + } + Trace((stderr, " avail_in = %d\n", G.dstrm.avail_in)); + } + FLUSH(wsize - G.dstrm.avail_out); /* flush slide[] */ + 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)); + while (err != Z_STREAM_END) { + err = inflate(&G.dstrm, Z_PARTIAL_FLUSH); + if (err == Z_DATA_ERROR) + return 2; + else if (err == Z_MEM_ERROR) + return 3; + else if (err == Z_BUF_ERROR) { /* DEBUG */ + Trace((stderr, "zlib inflate() did not detect stream end (%s, %s)\n" + , G.zipfn, G.filename)); + break; + } else if (err != Z_OK && err != Z_STREAM_END) { + Trace((stderr, "oops! (inflate(final loop) err = %d)\n", err)); + DESTROYGLOBALS() + EXIT(PK_MEM3); + } + FLUSH(wsize - G.dstrm.avail_out); /* final flush of slide[] */ + 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 = %ld, total out = %ld\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 */ + + err = inflateReset(&G.dstrm); + if (err != Z_OK) + Trace((stderr, "oops! (inflateReset() err = %d)\n", err)); + + return 0; +} + + +/*---------------------------------------------------------------------------*/ +#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, + int bl, int 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. */ +static ZCONST unsigned border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; +static ZCONST ush cplens[] = { /* Copy lengths for literal codes 257..285 */ + 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. */ +static ZCONST ush cplext[] = { /* Extra bits for literal codes 257..285 */ + 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, 99, 99}; /* 99==invalid */ +static ZCONST ush cpdist[] = { /* Copy offsets for distance codes 0..29 */ + 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, + 8193, 12289, 16385, 24577}; +static ZCONST ush cpdext[] = { /* Extra bits for distance codes */ + 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}; + + +/* 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 ush near mask_bits[] = { + 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 begining 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. + */ + +/* 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)<>=(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. + */ + + +static ZCONST int lbits = 9; /* bits in base literal/length lookup table */ +static ZCONST int dbits = 6; /* bits in base distance lookup table */ + + +#ifndef ASM_INFLATECODES + +int inflate_codes(__G__ tl, td, bl, bd) + __GDEF +struct huft *tl, *td; /* literal/length and distance decoder tables */ +int 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 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 */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* 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((unsigned)bl) + if ((e = (t = tl + ((unsigned)b & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + if (e == 16) /* then it's a literal */ + { + redirSlide[w++] = (uch)t->v.n; + if (w == wsize) + { + FLUSH(w); + w = 0; + } + } + else /* it's an EOB or a length */ + { + /* exit if end of block */ + if (e == 15) + break; + + /* 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((unsigned)bd) + if ((e = (t = td + ((unsigned)b & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + NEEDBITS(e) + d = 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 (d >= wsize) + return 1; /* invalid compressed data */ + n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e); + } + else +#endif + n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e); +#ifndef NOMEMCPY + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(redirSlide + 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) + { + FLUSH(w); + w = 0; + } + } while (n); + } + } + + + /* restore the globals from the locals */ + G.wp = w; /* restore global window pointer */ + G.bb = b; /* restore global bit buffer */ + G.bk = k; + + + /* done */ + return 0; +} + +#endif /* ASM_INFLATECODES */ + + + +static int inflate_stored(__G) + __GDEF +/* "decompress" an inflated type 0 (stored) block. */ +{ + unsigned n; /* number of bytes in block */ + unsigned w; /* current window position */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* 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) + { + FLUSH(w); + w = 0; + } + DUMPBITS(8) + } + + + /* restore the globals from the locals */ + G.wp = w; /* restore global window pointer */ + G.bb = b; /* restore global bit buffer */ + G.bk = k; + return 0; +} + + +/* 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; + if ((i = huft_build(__G__ l, 288, 257, cplens, cplext, + &G.fixed_tl, &G.fixed_bl)) != 0) + { + G.fixed_tl = (struct huft *)NULL; + return i; + } + + /* distance table */ + for (i = 0; i < 30; i++) /* make an incomplete code set */ + l[i] = 5; + G.fixed_bd = 5; + if ((i = huft_build(__G__ l, 30, 0, cpdist, cpdext, + &G.fixed_td, &G.fixed_bd)) > 1) + { + huft_free(G.fixed_tl); + 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) != 0; +} + + + +static int inflate_dynamic(__G) + __GDEF +/* decompress an inflated type 2 (dynamic Huffman codes) block. */ +{ + int 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; /* literal/length code table */ + struct huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int 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 */ +#ifdef PKZIP_BUG_WORKAROUND + unsigned ll[288+32]; /* literal/length and distance code lengths */ +#else + unsigned ll[286+30]; /* literal/length and distance code lengths */ +#endif + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* 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) +#ifdef PKZIP_BUG_WORKAROUND + if (nl > 288 || nd > 32) +#else + if (nl > 286 || nd > 30) +#endif + 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; + i = huft_build(__G__ ll, 19, 19, NULL, NULL, &tl, &bl); + if (bl == 0) /* no bit lengths */ + i = 1; + if (i) + { + if (i == 1) + huft_free(tl); + return i; /* incomplete code set */ + } + + + /* read in literal and distance code lengths */ + n = nl + nd; + m = mask_bits[bl]; + i = l = 0; + while ((unsigned)i < n) + { + NEEDBITS((unsigned)bl) + j = (td = tl + ((unsigned)b & m))->b; + DUMPBITS(j) + j = td->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) + 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) + 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) + 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; + i = huft_build(__G__ ll, nl, 257, cplens, cplext, &tl, &bl); + if (bl == 0) /* no literals or lengths */ + i = 1; + if (i) + { + if (i == 1) { + if (!uO.qflag) + MESSAGE((uch *)"(incomplete l-tree) ", 21L, 1); + huft_free(tl); + } + return i; /* incomplete code set */ + } + bd = dbits; + i = huft_build(__G__ ll + nl, nd, 0, cpdist, cpdext, &td, &bd); + if (bd == 0 && nl > 257) /* lengths but no distances */ + { + if (!uO.qflag) + MESSAGE((uch *)"(incomplete d-tree) ", 21L, 1); + huft_free(tl); + return 1; + } + if (i == 1) { +#ifdef PKZIP_BUG_WORKAROUND + i = 0; +#else + if (!uO.qflag) + MESSAGE((uch *)"(incomplete d-tree) ", 21L, 1); + huft_free(td); +#endif + } + if (i) + { + huft_free(tl); + return i; + } + + + /* decompress until an end-of-block code */ + if (inflate_codes(__G__ tl, td, bl, bd)) + return 1; + + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + return 0; +} + + + +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 */ + + + /* 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 */ + return 2; +} + + + +int inflate(__G) + __GDEF +/* 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; + + + /* 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); + + + /* flush out redirSlide */ + FLUSH(G.wp); + + + /* return success */ + Trace((stderr, "\n%u bytes in Huffman tables (%d/entry)\n", + h * sizeof(struct huft), sizeof(struct huft))); + return 0; +} + + + +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 ush *e; /* list of extra bits for non-simple codes */ + struct huft **t; /* result: starting table */ + int *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 ((unsigned)*m < j) + *m = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((unsigned)*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) > (unsigned)*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)(16 + 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 = 99; /* out of values--invalid code */ + else if (*p < s) + { + r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ + r.v.n = (ush)*p++; /* simple code is just the value */ + } + else + { + r.e = (uch)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/utils/Install/sfxzip/list.c b/utils/Install/sfxzip/list.c new file mode 100644 index 0000000000..e5ea1ef6fe --- /dev/null +++ b/utils/Install/sfxzip/list.c @@ -0,0 +1,644 @@ +/*--------------------------------------------------------------------------- + + 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 Ratio 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[] = + "%8lu %-7s%8lu %4s %02u-%02u-%02u %02u:%02u %08lx %c"; + static ZCONST char Far LongFileTrailer[] = + "-------- ------- --- \ + -------\n%8lu %8lu %4s %u file%s\n"; +#ifdef OS2_EAS + static ZCONST char Far ShortHdrStats[] = + "%9lu %6lu %6lu %02u-%02u-%02u %02u:%02u %c"; + static ZCONST char Far ShortFileTrailer[] = " -------- ----- ----- \ + -------\n%9lu %6lu %6lu %u file%s\n"; + static ZCONST char Far OS2ExtAttrTrailer[] = + "%ld file%s %ld bytes of OS/2 extended attributes attached.\n"; + static ZCONST char Far OS2ACLTrailer[] = + "%ld file%s %ld bytes of access control lists attached.\n"; +#else + static ZCONST char Far ShortHdrStats[] = + "%9lu %02u-%02u-%02u %02u:%02u %c"; + static ZCONST char Far ShortFileTrailer[] = + " -------- -------\n%9lu %u 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; + unsigned j, methnum, members=0; +#ifdef USE_EF_UT_TIME + iztimes z_utime; + struct tm *t; +#endif + unsigned yr, mo, dy, hh, mm; + ulg 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:#", "EnhDefl", "ImplDCL", "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; + +#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 = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) { + + if (readbuf(__G__ G.sig, 4) == 0) + return PK_EOF; + if (strncmp(G.sig, central_hdr_sig, 4)) { /* just to make sure */ + 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; + + do_this_file = FALSE; + for (i = 0; i < G.filespecs; i++) + if (match(G.filename, G.pfnames[i], uO.C_flag)) { + 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)) { + 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 % 100); + 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) + + 80) % (unsigned)100); + 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 = (unsigned)mo; + mo = yr; yr = dy; dy = (ush)methnum; + break; + case DF_DMY: + methnum = (unsigned)mo; + mo = dy; dy = (ush)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 = MIN(G.crec.compression_method, NUM_METHODS); + zfstrcpy(methbuf, method[methnum]); + if (methnum == DEFLATED) { + 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_OS2_W32) || defined(UNIX) + for (p = G.filename; *p; ++p) + if (!isprint(*p)) + *p = '?'; /* change non-printable chars to '?' */ +#endif /* DOS_FLX_OS2_W32 || UNIX */ +#endif /* 0 */ + +#ifdef WINDLL + /* send data to application for formatting and printing */ + (*G.lpUserFunctions->SendApplicationMessage)(G.crec.ucsize, csiz, + (ush)cfactor, mo, dy, yr, hh, mm, + (char)(G.pInfo->lcflag ? '^' : ' '), + (LPSTR)fnfilter(G.filename, slide), (LPSTR)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), + G.crec.ucsize, methbuf, csiz, cfactorstr, mo, dy, + yr, hh, mm, G.crec.crc32, (G.pInfo->lcflag? '^':' '))); + else +#ifdef OS2_EAS + Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats), + G.crec.ucsize, ea_size, acl_size, + mo, dy, yr, hh, mm, (G.pInfo->lcflag? '^':' '))); +#else + Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats), + G.crec.ucsize, + mo, dy, 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 = 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), + tot_ucsize, tot_csize, 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), + tot_ucsize, tot_easize, tot_aclsize, members, members == 1? + "" : "s")); +#else + Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer), + tot_ucsize, members, members == 1? "" : "s")); +#endif /* OS2_EAS */ +#endif /* ?WINDLL */ + } + +/*--------------------------------------------------------------------------- + Double check that we're back at the end-of-central-directory record. + ---------------------------------------------------------------------------*/ + + if (readbuf(__G__ G.sig, 4) == 0) /* disk error? */ + return PK_EOF; + if (strncmp(G.sig, end_central_sig, 4)) { /* just to make sure again */ + Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); + error_in_archive = PK_WARN; /* didn't find sig */ + } + if (members == 0 && 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 = G.filename[fn_len-1]) == '/' || + (G.pInfo->hostnum == FS_FAT_ && !strchr(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; + unsigned *nmember; +{ + int do_this_file=FALSE, error, error_in_archive=PK_COOL; + unsigned 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 = 0; + G.pInfo = &info; + + for (j = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) { + + if (readbuf(__G__ G.sig, 4) == 0) + return PK_EOF; + if (strncmp(G.sig, central_hdr_sig, 4)) { /* just to make sure */ + Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j)); + Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); + return PK_BADERR; + } + /* 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; + + do_this_file = FALSE; + for (i = 0; i < G.filespecs; i++) + if (match(G.filename, G.pfnames[i], uO.C_flag)) { + 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)) { + 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 (readbuf(__G__ G.sig, 4) == 0) + return PK_EOF; + if (strncmp(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 == 0 && 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) + ulg uc, c; +{ + ulg 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); + + (*G.message)((zvoid *)&G, (uch *)name, (ulg)strlen(name), 0); + (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); + +} /* end function fnprint() */ diff --git a/utils/Install/sfxzip/makefile b/utils/Install/sfxzip/makefile new file mode 100644 index 0000000000..92be40b56a --- /dev/null +++ b/utils/Install/sfxzip/makefile @@ -0,0 +1,142 @@ +#============================================================================== +# Makefile for UnZip, UnZipSFX and fUnZip: Unix and MS-DOS ("real" makes only) +# Version: 5.4 19 November 1998 +#============================================================================== + + +# INSTRUCTIONS (such as they are): +# +# "make sunos" -- makes UnZip in current directory on a generic SunOS 4.x Sun +# "make list" -- lists all supported systems (targets) +# "make help" -- provides pointers on what targets to try if problems occur +# "make wombat" -- chokes and dies if you haven't added the specifics for your +# Wombat 68000 (or whatever) to the systems list +# +# 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). +# +# Some versions of make do not define the macro "$(MAKE)"; this is rare, but +# if things don't work, try using "make" instead of "$(MAKE)" in your system's +# makerule. Or try adding the following line to your .login file: +# setenv MAKE "make" +# (That never works--makes that are too stupid to define MAKE are also too +# stupid to look in the environment--but try it anyway for kicks. :-) ) +# +# Memcpy and memset are provided for those systems that don't have them; they +# are in fileio.c and will be used if -DZMEM is included in CF. These days +# almost all systems have them. +# +# 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 = cc# try using "gcc" target rather than changing this (CC and LD +LD = $(CC)# must match, else "unresolved symbol: ___main" is possible) +AS = as +LOC = $(LOCAL_UNZIP) +AF = $(LOC) +CF = -O -g -I. -I.. -I../inczip $(LOC) -I/usr/local//include -I/usr/X11R6/include -I/usr/local/lib/glib/include -DSTRICT -D__WXGTK__ -DGTK_NO_CHECK_CASTS -D_REENTRANT -D_IODBC_ -Wall +LF = -o sfx -L/usr/local/lib -L/usr/X11R6/lib -L/usr -lwx_gtk -lpng -ljpeg -lstdc++ -lgcc -lc_r -lgtk -lgdk -lgmodule -lglib -lXext -lX11 -lm -lgthread +LF2 = -s + +# general-purpose stuff +#CP = cp +CP = ln +LN = ln +RM = rm -f +CHMOD = chmod +BINPERMS = 755 +MANPERMS = 644 +STRIP = strip +E = +O = .o +M = unix +SHELL = /bin/sh + +# defaults for crc32 stuff and system dependent headers +CRC32 = crc32 + +# object files +OBJS1 = unzip$O $(CRC32)$O crctab$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 unreduce$O unshrink$O zipinfo$O +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O install$O wxmain$O instsup$O +UNZIP_H = ../inczip/unzip.h ../inczip/unzpriv.h ../inczip/globals.h + +# installation +# (probably can change next two to `install' and `install -d' if you have it) +INSTALL = cp +INSTALL_D = mkdir -p + +############################################### +# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES # +############################################### + +# this is for GNU make; comment out and notify zip-bugs if it causes errors +.SUFFIXES: .c .o .obj .pic.o + +# 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 + +.c.pic.o: + $(CC) -c $(CF) -o $@ $*.c + +all: sfx + + +# EDIT HERE FOR PARALLEL MAKES on Sequent (and others?)--screws up MS-DOS +# make utilities if default: change "unzip$E:" to "unzip$E:&" + +sfx$E: $(OBJS) # add `&' for parallel makes + $(LD) $(LF) $(OBJS) + +crc32$O: crc32.c $(UNZIP_H) ../inczip/zip.h +crctab$O: crctab.c $(UNZIP_H) ../inczip/zip.h +crypt$O: crypt.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h +envargs$O: envargs.c $(UNZIP_H) +explode$O: explode.c $(UNZIP_H) +extract$O: extract.c $(UNZIP_H) ../inczip/crypt.h +fileio$O: fileio.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/ebcdic.h +funzip$O: funzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/tables.h +globals$O: globals.c $(UNZIP_H) +inflate$O: inflate.c ../inczip/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) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h +unreduce$O: unreduce.c $(UNZIP_H) +unshrink$O: unshrink.c $(UNZIP_H) +unzip$O: unzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/version.h ../inczip/consts.h +zipinfo$O: zipinfo.c $(UNZIP_H) + +unix$O: unix.c $(UNZIP_H) ../inczip/version.h # Unix only + $(CC) -c $(CF) unix.c + +install$O: ../install.c + $(CC) -c $(CF) ../install.c + +wxmain$O: ../wxmain.cpp + $(CC) -c $(CF) ../wxmain.cpp + +instsup$O: ../instsup.cpp + $(CC) -c $(CF) ../instsup.cpp + + + diff --git a/utils/Install/sfxzip/makefile.b32 b/utils/Install/sfxzip/makefile.b32 new file mode 100644 index 0000000000..ce4e11187e --- /dev/null +++ b/utils/Install/sfxzip/makefile.b32 @@ -0,0 +1,135 @@ +# Makefile for UnZip(SFX) and fUnZip for Borland C++ for Windows 95/NT +# Version: 5.4 and later Alvin Koh, Jim Knoble, Christian Spieler, etc. +# Adapted from the MS-DOS makefile by E-Yen Tan +# +# Last revised: 24 Nov 98 +# +# + + +# 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 = 4 + +# (De)Select inclusion of optimized assembler CRC32 routine: +USE_ASMCRC = 0 + +# If you have bcc32i, you should define: +# CC = bcc32i +# This compiler generates a faster code. +CC = bcc32 +AS = tasm32 + +!if $(USE_ASMCRC) +ASMFLG = -DASM_CRC +ASMOBJS = crc_i386.obj +!else +ASMFLG = +ASMOBJS = +!endif + +!if $(UNCLEAN) +DIRT = -DUSE_SMITH_CODE -DUSE_UNSHRINK +!else +DIRT = +!endif + +# compiler flags + +ASCPUFLAG = __$(CPU_TYP)86 +!if $(CPU_TYP) != 0 +CC_CPUFLG = -$(CPU_TYP) +!endif +ASFLAGS = -ml -m2 -w0 -D$(ASCPUFLAG) $(LOC) +CFLAGS = -Od -w- $(CC_CPUFLG) -ff- -k- -P-.C -I. -I.. -I../inczip -I../../../include $(ASMFLG) $(LOC) $(DIRT) -v -D__WXMSW__ -DWXDEBUG=1 -D__WXDEBUG__ -DUSE_DEFINE -DWIN32 -D__WIN95__ -D__WINDOWS__ -I$(WXDIR)\include +LDFLAGS = -L$(WXWIN)\lib -aa -c # for bcc +LINK = ilink32 +LIBS = wx32 cw32mt import32 ole2w32 winpng zlib jpeg xpm tiff + +UNFLAGS = $(CFLAGS) + +# implicit rules + +.asm.obj: + $(AS) $(ASFLAGS) $< + +.c.obj: + $(CC) -c $(UNFLAGS) {$< } + +# list macros + +OBJU1 = unzip.obj crc32.obj crctab.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 = win32.obj nt.obj install.obj wxmain.obj instsup.obj $(ASMOBJS) +OBJU = $(OBJU1) $(OBJU2) $(OBJU3) $(OBJUS) + +UNZIP_H = ../inczip/unzip.h ../inczip/unzpriv.h ../inczip/globals.h ../inczip/w32cfg.h + +# explicit rules + +all: sfx.exe + +sfx.exe: $(OBJU) sfx.res + $(LINK) $(LDFLAGS) @&&! +c0w32.obj $(OBJU) +sfx.exe +nul +$(LIBS) + +sfx.res +! + +clean: + -erase *.obj + -erase *.exe + -erase *.res + -erase *.map + -erase *.rws + -erase *.tds + -erase *.il? + +# individual file dependencies + +crc32.obj: crc32.c $(UNZIP_H) ../inczip/zip.h +crctab.obj: crctab.c $(UNZIP_H) ../inczip/zip.h +crypt.obj: crypt.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h +envargs.obj: envargs.c $(UNZIP_H) +explode.obj: explode.c $(UNZIP_H) +extract.obj: extract.c $(UNZIP_H) ../inczip/crypt.h +fileio.obj: fileio.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/ebcdic.h +globals.obj: globals.c $(UNZIP_H) +inflate.obj: inflate.c ../inczip/inflate.h $(UNZIP_H) +list.obj: list.c $(UNZIP_H) +match.obj: match.c $(UNZIP_H) +process.obj: process.c $(UNZIP_H) +ttyio.obj: ttyio.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h +unreduce.obj: unreduce.c $(UNZIP_H) +unshrink.obj: unshrink.c $(UNZIP_H) +unzip.obj: unzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/version.h ../inczip/consts.h +zipinfo.obj: zipinfo.c $(UNZIP_H) + +#crc_i386.obj: win32/crc_i386.asm +# $(AS) $(ASFLAGS) win32\crc_i386.asm, $*.obj ; + +win32.obj: win32.c $(UNZIP_H) + $(CC) -c $(UNFLAGS) win32.c + +nt.obj: nt.c $(UNZIP_H) + $(CC) -c $(UNFLAGS) nt.c + +install.obj: ../install.c $(UNZIP_H) + $(CC) -c $(UNFLAGS) ../install.c + +wxmain.obj: ../wxmain.cpp $(UNZIP_H) + $(CC) -P- -c $(UNFLAGS) ../wxmain.cpp + +instsup.obj: ../instsup.cpp $(UNZIP_H) + $(CC) -P- -c $(UNFLAGS) ../instsup.cpp + +sfx.res : sfx.rc $(WXWIN)\include\wx\msw\wx.rc + brc32 -r /i$(BCCDIR)\include /i$(WXWIN)\include /i$(WXWIN)\contrib\include sfx diff --git a/utils/Install/sfxzip/makefile.g95 b/utils/Install/sfxzip/makefile.g95 new file mode 100644 index 0000000000..3049513be8 --- /dev/null +++ b/utils/Install/sfxzip/makefile.g95 @@ -0,0 +1,164 @@ +# Makefile for UnZip, fUnZip and UnZipSFX for native Win32-Intel ports of gcc. +# Currently supported implementations: Cygnus/Win32 and MinGW32. +# +# First version: Cosmin Truta , Dec 1997. +# Last revision: Christian Spieler, 29-Apr-1998 +# +# To use, do "make -f win32/makefile.gcc". + + +### Optional section + +# Optional nonstandard preprocessor flags (as -DUSE_ZLIB or -DUSE_SMITH_CODE) +# should be added to the environment via "set LOCAL_UNZIP=-DFOO" or added +# to the declaration of LOCFLAGS here: +LOCFLAGS = $(LOCAL_UNZIP) + + +### Compiler-specific section + +# ------------ GNU C ------------ +CC = gcc + +#AS = as +AS = $(CC) + +#LD = ld +LD = $(CC) + +# Quiet +CC_QUIET_OPT = +AS_QUIET_OPT = $(CC_QUIET_OPT) +LD_QUIET_OPT = $(CC_QUIET_OPT) + +# Warnings +CC_WARN_OPT = -Wall +AS_WARN_OPT = $(CC_WARN_OPT) +LD_WARN_OPT = + +# Debug version +CC_DEBUG_OPT = -g +AS_DEBUG_OPT = $(CC_DEBUG_OPT) +LD_DEBUG_OPT = $(CC_DEBUG_OPT) + +# Release version +CC_RELEASE_OPT = +AS_RELEASE_OPT = +#LD_RELEASE_OPT = -s + +# Smallest code +CC_SIZE_OPT = -O1 + +# Fastest code +CC_SPEED_OPT = -O2 + +# Output object file name +CC_OUT_OPT = -o + +# Other specific options +#CC_SPECIFIC_OPT = -c -DASM_CRC -DWIN32 -mno-cygwin +CC_SPECIFIC_OPT = -c -DWIN32 -I../inczip -g -I.. -D_X86_=1 -DWIN32 -D_WIN32 -DWINVER=0x0400 -D__WIN95__ -D__GNUWIN32__ -D__WIN32__ -I../../../include -I../../../src/png -I../../../src/jpeg -I../../../src/zlib -I../../../include/wx/msw/gnuwin32 -DSTRICT -D__WXMSW__ -D__WINDOWS__ -D__WXDEBUG__ -Wall -fno-pcc-struct-return -O2 -fno-rtti -fno-exceptions +AS_SPECIFIC_OPT = -c +LD_SPECIFIC_OPT = -Wl,--subsystem,windows -mwindows -L../../../lib -o $@ + +# Libraries for the debug & release version +LD_RELEASE_LIBS = ../../../lib/libwx.a -lpng -ljpeg -lzlib -lxpm -lstdc++ -lgcc -lwinspool -lwinmm -lshell32 -lcomctl32 -lctl3d32 -lodbc32 -ladvapi32 -lole32 -loleaut32 -luuid -lodbc32 -lwsock32 +LD_DEBUG_LIBS = $(LD_RELEASE_LIBS) + + +### System-specific section + +# Suffixes +OBJ = .o +EXE = .exe + +.SUFFIXES: .c .S $(OBJ) $(EXE) + +# Commands +RM = rm -f + + +### General section + +CFLAGS = $(CC_SPECIFIC_OPT) $(CC_QUIET_OPT) $(CC_WARN_OPT) $(LOCFLAGS) \ + $(CC_OUT_OPT) $@ +ASFLAGS = $(AS_SPECIFIC_OPT) $(AS_QUIET_OPT) $(AS_WARN_OPT) $(LOCFLAGS) +LDFLAGS = $(LD_SPECIFIC_OPT) $(LD_QUIET_OPT) $(LD_WARN_OPT) + +# To build with debug info, use 'make DEBUG=1'. +ifdef DEBUG +CVER = $(CC_DEBUG_OPT) +ASVER = $(AS_DEBUG_OPT) +LDVER = $(LD_DEBUG_OPT) +GENFLAGS = +FFLAGS = -DFUNZIP +SFXFLAGS = -DSFX +LDLIBS = $(LD_DEBUG_LIBS) +else +CVER = $(CC_RELEASE_OPT) +ASVER = $(AS_RELEASE_OPT) +LDVER = $(LD_RELEASE_OPT) +GENFLAGS = $(CC_SPEED_OPT) +FFLAGS = $(CC_SPEED_OPT) -DFUNZIP +SFXFLAGS = $(CC_SIZE_OPT) -DSFX +LDLIBS = $(LD_RELEASE_LIBS) +endif + +# Object files +OBJA = crc_i386$(OBJ) install$(OBJ) wxmain$(OBJ) instsup$(OBJ) +OBJS1 = unzip$(OBJ) crc32$(OBJ) crctab$(OBJ) crypt$(OBJ) envargs$(OBJ) +OBJS2 = explode$(OBJ) extract$(OBJ) fileio$(OBJ) globals$(OBJ) inflate$(OBJ) +OBJS3 = list$(OBJ) match$(OBJ) process$(OBJ) ttyio$(OBJ) unreduce$(OBJ) +OBJS4 = unshrink$(OBJ) zipinfo$(OBJ) win32$(OBJ) nt$(OBJ) +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJS4) $(OBJA) + +UNZIP_H = ../inczip/unzip.h ../inczip/unzpriv.h ../inczip/globals.h ../inczip/w32cfg.h + + +# Default target is all the executables +unzips: sfx$(EXE) + +sfx$(EXE): $(OBJS) + $(LD) $(LDFLAGS) $(LDVER) $(OBJS) $(LDLIBS) + +# How to compile sources +.c$(OBJ): + $(CC) $(CFLAGS) $(CVER) $(GENFLAGS) $< +.S$(OBJ): + $(AS) $(ASFLAGS) $(ASVER) $(GENFLAGS) $< + +# Dependencies +crc32$(OBJ): crc32.c $(UNZIP_H) ../inczip/zip.h +crctab$(OBJ): crctab.c $(UNZIP_H) ../inczip/zip.h +crypt$(OBJ): crypt.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h +envargs$(OBJ): envargs.c $(UNZIP_H) +explode$(OBJ): explode.c $(UNZIP_H) +extract$(OBJ): extract.c $(UNZIP_H) ../inczip/crypt.h +fileio$(OBJ): fileio.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/ebcdic.h +funzip$(OBJ): funzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/tables.h +globals$(OBJ): globals.c $(UNZIP_H) +inflate$(OBJ): inflate.c ../inczip/inflate.h $(UNZIP_H) +list$(OBJ): list.c $(UNZIP_H) +match$(OBJ): match.c $(UNZIP_H) +process$(OBJ): process.c $(UNZIP_H) +ttyio$(OBJ): ttyio.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h +unreduce$(OBJ): unreduce.c $(UNZIP_H) +unshrink$(OBJ): unshrink.c $(UNZIP_H) +unzip$(OBJ): unzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/version.h ../inczip/consts.h +zipinfo$(OBJ): zipinfo.c $(UNZIP_H) +crc_i386$(OBJ): crc_i386.S +win32$(OBJ): win32.c $(UNZIP_H) ../inczip/nt.h +nt$(OBJ): nt.c ../inczip/nt.h + +install$(OBJ): ../install.c + $(CC) $(CFLAGS) $(CVER) $(GENFLAGS) $< + +wxmain$(OBJ): ../wxmain.cpp + $(CC) $(CFLAGS) $(CVER) $(GENFLAGS) $< + +instsup$(OBJ): ../instsup.cpp + $(CC) $(CFLAGS) $(CVER) $(GENFLAGS) $< + +clean: + $(RM) *$(OBJ) + $(RM) *$(EXE) diff --git a/utils/Install/sfxzip/makefile.gcc b/utils/Install/sfxzip/makefile.gcc new file mode 100644 index 0000000000..92be40b56a --- /dev/null +++ b/utils/Install/sfxzip/makefile.gcc @@ -0,0 +1,142 @@ +#============================================================================== +# Makefile for UnZip, UnZipSFX and fUnZip: Unix and MS-DOS ("real" makes only) +# Version: 5.4 19 November 1998 +#============================================================================== + + +# INSTRUCTIONS (such as they are): +# +# "make sunos" -- makes UnZip in current directory on a generic SunOS 4.x Sun +# "make list" -- lists all supported systems (targets) +# "make help" -- provides pointers on what targets to try if problems occur +# "make wombat" -- chokes and dies if you haven't added the specifics for your +# Wombat 68000 (or whatever) to the systems list +# +# 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). +# +# Some versions of make do not define the macro "$(MAKE)"; this is rare, but +# if things don't work, try using "make" instead of "$(MAKE)" in your system's +# makerule. Or try adding the following line to your .login file: +# setenv MAKE "make" +# (That never works--makes that are too stupid to define MAKE are also too +# stupid to look in the environment--but try it anyway for kicks. :-) ) +# +# Memcpy and memset are provided for those systems that don't have them; they +# are in fileio.c and will be used if -DZMEM is included in CF. These days +# almost all systems have them. +# +# 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 = cc# try using "gcc" target rather than changing this (CC and LD +LD = $(CC)# must match, else "unresolved symbol: ___main" is possible) +AS = as +LOC = $(LOCAL_UNZIP) +AF = $(LOC) +CF = -O -g -I. -I.. -I../inczip $(LOC) -I/usr/local//include -I/usr/X11R6/include -I/usr/local/lib/glib/include -DSTRICT -D__WXGTK__ -DGTK_NO_CHECK_CASTS -D_REENTRANT -D_IODBC_ -Wall +LF = -o sfx -L/usr/local/lib -L/usr/X11R6/lib -L/usr -lwx_gtk -lpng -ljpeg -lstdc++ -lgcc -lc_r -lgtk -lgdk -lgmodule -lglib -lXext -lX11 -lm -lgthread +LF2 = -s + +# general-purpose stuff +#CP = cp +CP = ln +LN = ln +RM = rm -f +CHMOD = chmod +BINPERMS = 755 +MANPERMS = 644 +STRIP = strip +E = +O = .o +M = unix +SHELL = /bin/sh + +# defaults for crc32 stuff and system dependent headers +CRC32 = crc32 + +# object files +OBJS1 = unzip$O $(CRC32)$O crctab$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 unreduce$O unshrink$O zipinfo$O +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O install$O wxmain$O instsup$O +UNZIP_H = ../inczip/unzip.h ../inczip/unzpriv.h ../inczip/globals.h + +# installation +# (probably can change next two to `install' and `install -d' if you have it) +INSTALL = cp +INSTALL_D = mkdir -p + +############################################### +# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES # +############################################### + +# this is for GNU make; comment out and notify zip-bugs if it causes errors +.SUFFIXES: .c .o .obj .pic.o + +# 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 + +.c.pic.o: + $(CC) -c $(CF) -o $@ $*.c + +all: sfx + + +# EDIT HERE FOR PARALLEL MAKES on Sequent (and others?)--screws up MS-DOS +# make utilities if default: change "unzip$E:" to "unzip$E:&" + +sfx$E: $(OBJS) # add `&' for parallel makes + $(LD) $(LF) $(OBJS) + +crc32$O: crc32.c $(UNZIP_H) ../inczip/zip.h +crctab$O: crctab.c $(UNZIP_H) ../inczip/zip.h +crypt$O: crypt.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h +envargs$O: envargs.c $(UNZIP_H) +explode$O: explode.c $(UNZIP_H) +extract$O: extract.c $(UNZIP_H) ../inczip/crypt.h +fileio$O: fileio.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/ebcdic.h +funzip$O: funzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/tables.h +globals$O: globals.c $(UNZIP_H) +inflate$O: inflate.c ../inczip/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) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h +unreduce$O: unreduce.c $(UNZIP_H) +unshrink$O: unshrink.c $(UNZIP_H) +unzip$O: unzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/version.h ../inczip/consts.h +zipinfo$O: zipinfo.c $(UNZIP_H) + +unix$O: unix.c $(UNZIP_H) ../inczip/version.h # Unix only + $(CC) -c $(CF) unix.c + +install$O: ../install.c + $(CC) -c $(CF) ../install.c + +wxmain$O: ../wxmain.cpp + $(CC) -c $(CF) ../wxmain.cpp + +instsup$O: ../instsup.cpp + $(CC) -c $(CF) ../instsup.cpp + + + diff --git a/utils/Install/sfxzip/makefile.os2 b/utils/Install/sfxzip/makefile.os2 new file mode 100644 index 0000000000..6778bd50ab --- /dev/null +++ b/utils/Install/sfxzip/makefile.os2 @@ -0,0 +1,670 @@ +# Makefile for UnZip, UnZipSFX and fUnZip 24 November 1998 +# +# 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). + +# 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" \ + CRC32="crc_i86" \ + CRC32F="crc_i86" \ + CRC32X="crc_i86" \ + 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" \ + CRC32="crc_i86" \ + CRC32F="crc_i86" \ + CRC32X="crc_i86" \ + DEF="os2\unzip.def" + +# cross-compilation for MS-DOS with MS C 6.00 (same comment as above...formerly; +# now unzip is medium model again, with [almost] all strings in far memory) +mscdos: + $(MAKE) -f os2/makefile.os2 all \ + CC="cl -nologo -AM -Oaict -Gs -I. $(FP)" \ + CFLAGS="-Zp1 -W3 -DASM_CRC $(LOCAL_UNZIP)" \ + NFLAGS="" \ + DLLFLAG="" \ + AS="ml -nologo -c -Zm -Cp" \ + ASFLAGS="-D__MEDIUM__" \ + LDFLAGS="-F 0C00 -Lr -Fe" \ + LDFLAGS2="-link /noe /exe" \ + OUT="-Fo" \ + OBJ=".obj" \ + CRC32="crc_i86" \ + CRC32F="crc_i86" \ + CRC32X="crc_i86" \ + OBJU2="msdos.obj" \ + OBJX2="msdos_.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" \ + CRC32="crc_i386" \ + CRC32F="crc_i386" \ + CRC32X="crc_i386" \ + 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" \ + CRC32="crc_i86" \ + CRC32F="crc_i86" \ + CRC32X="crc_i86" \ + 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" \ + CRC32="crc_i386" \ + CRC32F="crc_i386" \ + CRC32X="crc_i386" \ + 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" \ + CRC32="crc_i386" \ + CRC32F="crc_i386" \ + CRC32X="crc_i386" \ + 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 -mm" \ + ASFLAGS="-D__MEDIUM__" \ + LDFLAGS="-k0xC00 -x -l=dos -Fe=" \ + LDFLAGS2="" \ + OUT="-Fo" \ + OBJ=".obj" \ + OBJU2="msdos.obj" \ + OBJX2="msdos_.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" \ + OBJU2="win32.obj nt.obj" \ + OBJX2="win32_.obj nt_.obj" \ + CRC32="crc_i386" \ + CRC32F="crc_i386" \ + CRC32X="crc_i386" \ + 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" \ + CRC32="crc_gcc" \ + CRC32F="crc_gcc" \ + CRC32X="crc_gcc" \ + 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" \ + CRC32="crc_gcc" \ + CRC32F="crc_gcc" \ + CRC32X="crc_gcc" \ + 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" \ + CRC32="crc_gcc" \ + CRC32F="crc_gcc" \ + CRC32X="crc_gcc" + +# 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" \ + CRC32="crc_gcc" \ + CRC32F="crc_gcc" \ + CRC32X="crc_gcc" \ + 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" \ + CRC32="crc_gcc" \ + CRC32F="crc_gcc" \ + CRC32X="crc_gcc" \ + 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 +CRC32 = crc32 +CRC32F = crc32f +CRC32X = crc32_ + +OBJU = unzip$(OBJ) $(CRC32)$(OBJ) crctab$(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) +OBJU2 = os2$(OBJ) os2acl$(OBJ) +OBJX = unzipsf_$(OBJ) $(CRC32X)$(OBJ) crctab_$(OBJ) crypt_$(OBJ) \ + extract_$(OBJ) fileio_$(OBJ) globals_$(OBJ) inflate_$(OBJ) \ + match_$(OBJ) process_$(OBJ) ttyio_$(OBJ) +OBJX2 = os2_$(OBJ) os2acl_$(OBJ) +OBJDLL= api$(OBJ) apihelp$(OBJ) rexxhelp$(OBJ) rexxapi$(OBJ) +OBJF = funzip$(OBJ) $(CRC32F)$(OBJ) 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) version.h +crc32$(OBJ): crc32.c $(UNZIP_H) zip.h +crctab$(OBJ): crctab.c $(UNZIP_H) zip.h +envargs$(OBJ): envargs.c $(UNZIP_H) +explode$(OBJ): explode.c $(UNZIP_H) +extract$(OBJ): extract.c $(UNZIP_H) crypt.h +fileio$(OBJ): fileio.c $(UNZIP_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) +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 version.h consts.h +api$(OBJ): api.c $(UNZIP_H) version.h +zipinfo$(OBJ): zipinfo.c $(UNZIP_H) + +funzip$(OBJ): funzip.c $(UNZIP_H) crypt.h ttyio.h tables.h # funzip only + $(CC) -c $(CFLAGS) funzip.c + +unzipstb$(OBJ): unzipstb.c # DLL version + $(CC) -c $(CFLAGS) unzipstb.c + +msdos$(OBJ): msdos/msdos.c $(UNZIP_H) version.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 + +win32$(OBJ): win32/win32.c $(UNZIP_H) win32/nt.h version.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) version.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 + +os2acl$(OBJ): os2/os2acl.c $(UNZIP_H) version.h # OS/2 only + $(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)os2acl.c + +os2acl_$(OBJ): os2/os2acl.c $(UNZIP_H) version.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 ttyio.h + $(CC) -c $(CFLAGS) $(DLLFLAG) $(NFLAGS) crypt.c + +cryptf$(OBJ): crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h # funzip only + $(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ crypt.c + +crc32f$(OBJ): crc32.c $(UNZIP_H) zip.h # funzip only + $(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ crc32.c + +globalsf$(OBJ): globals.c $(UNZIP_H) # funzip only + $(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ globals.c + +inflatef$(OBJ): inflate.c inflate.h $(UNZIP_H) crypt.h # funzip only + $(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ inflate.c + +ttyiof$(OBJ): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h # funzip only + $(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ ttyio.c + +crc32_$(OBJ): crc32.c $(UNZIP_H) zip.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crc32.c + +crctab_$(OBJ): crctab.c $(UNZIP_H) zip.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crctab.c + +crypt_$(OBJ): crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crypt.c + +extract_$(OBJ): extract.c $(UNZIP_H) crypt.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ extract.c + +fileio_$(OBJ): fileio.c $(UNZIP_H) crypt.h ttyio.h ebcdic.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ fileio.c + +globals_$(OBJ): globals.c $(UNZIP_H) # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ globals.c + +inflate_$(OBJ): inflate.c inflate.h $(UNZIP_H) crypt.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ inflate.c + +match_$(OBJ): match.c $(UNZIP_H) # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ match.c + +process_$(OBJ): process.c $(UNZIP_H) # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ process.c + +ttyio_$(OBJ): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ ttyio.c + +unzipsf_$(OBJ): unzip.c $(UNZIP_H) crypt.h version.h consts.h # unzipsfx only + $(CC) -c $(CFLAGS) -DSFX $(OUT)$@ unzip.c diff --git a/utils/Install/sfxzip/match.c b/utils/Install/sfxzip/match.c new file mode 100644 index 0000000000..77355d4400 --- /dev/null +++ b/utils/Install/sfxzip/match.c @@ -0,0 +1,294 @@ +/*--------------------------------------------------------------------------- + + 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); + + 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 ToLower() in here (for Unix, define ToLower to be macro (using + * isupper()); otherwise just use tolower() */ +#define UNZIP_INTERNAL +#include "unzip.h" + +#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)) +#define match(s,p,ic) (recmatch((ZCONST uch *)p,(ZCONST uch *)s,ic) == 1) +int recmatch OF((ZCONST uch *pattern, ZCONST uch *string, int ignore_case)); +#endif +#endif /* 0 */ +static int recmatch OF((ZCONST uch *pattern, ZCONST uch *string, + int ignore_case)); + + + +/* match() is a shell to recmatch() to return only Boolean values. */ + +int match(string, pattern, ignore_case) + ZCONST char *string, *pattern; + int ignore_case; +{ +#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 = strchr(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); + free(dospattern); + return j == 1; + } else +#endif /* MSDOS && DOSWILD */ + return recmatch((uch *)pattern, (uch *)string, ignore_case) == 1; +} + + + +static int recmatch(p, s, ic) + ZCONST uch *p; /* sh pattern to match */ + ZCONST uch *s; /* string to which to match it */ + int ic; /* true for case insensitivity */ +/* 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++; + + /* 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) + return *s ? recmatch(p, s + 1, ic) : 0; + + /* '*' matches any number of characters, including zero */ +#ifdef AMIGA + if (c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */ + c = '*', p++; +#endif /* AMIGA */ + if (c == '*') { + if (*p == 0) + return 1; + for (; *s; s++) + if ((c = recmatch(p, s, ic)) != 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; 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; p++) { /* go through the list */ + if (e == 0 && *p == '\\') /* set escape flag if \ */ + e = 1; + else if (e == 0 && *p == '-') /* set start of range if - */ + c = *(p-1); + else { + 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); + c = e = 0; /* clear range, escape flags */ + } + } + return r ? recmatch(q + 1, s + 1, ic) : 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, ic) : 0; +#else + return Case((uch)c) == Case(*s) ? recmatch(p, ++s, ic) : 0; +#endif + +} /* end function recmatch() */ + + + + + +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; ++p) + if (*p == '\\' && *(p+1)) + ++p; +#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 */ +#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);} + +void main() +{ + 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; + pipeit("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/utils/Install/sfxzip/nt.c b/utils/Install/sfxzip/nt.c new file mode 100644 index 0000000000..ab4cea3a9f --- /dev/null +++ b/utils/Install/sfxzip/nt.c @@ -0,0 +1,659 @@ +/* + + Copyright (c) 1996 Scott Field + + Module Name: + + nt.c + + Abstract: + + This module implements WinNT security descriptor operations for the + Win32 Info-ZIP project. Operation such as setting file security, + using/querying local and remote privileges, and queuing of operations + is performed here. The contents of this module are only relevant + when the code is running on Windows NT, and the target volume supports + persistent Acl storage. + + User privileges that allow accessing certain privileged aspects of the + security descriptor (such as the Sacl) are only used if the user specified + to do so. + + Author: + + Scott Field (sfield@microsoft.com) + + Last revised: 18 Jan 97 + + */ + +#define WIN32_LEAN_AND_MEAN +#define UNZIP_INTERNAL +#include "unzip.h" +#include +#ifdef __RSXNT__ +# include "rsxntwin.h" +#endif +#include "nt.h" + + +#ifdef NTSD_EAS /* This file is only needed for NTSD handling */ + +/* Borland C++ does not define FILE_SHARE_DELETE. Others also? */ +#ifndef FILE_SHARE_DELETE +# define FILE_SHARE_DELETE 0x00000004 +#endif + + +/* private prototypes */ + +static BOOL Initialize(VOID); +#if 0 /* currently unused */ +static BOOL Shutdown(VOID); +#endif +static BOOL DeferSet(char *resource, PVOLUMECAPS VolumeCaps, uch *buffer); +static VOID GetRemotePrivilegesSet(CHAR *FileName, PDWORD dwRemotePrivileges); +static VOID InitLocalPrivileges(VOID); + + +BOOL bInitialized = FALSE; /* module level stuff initialized? */ +HANDLE hInitMutex = NULL; /* prevent multiple initialization */ + +BOOL g_bRestorePrivilege = FALSE; /* for local set file security override */ +BOOL g_bSaclPrivilege = FALSE; /* for local set sacl operations, only when + restore privilege not present */ + +/* our single cached volume capabilities structure that describes the last + volume root we encountered. A single entry like this works well in the + zip/unzip scenario for a number of reasons: + 1. typically one extraction path during unzip. + 2. typically process one volume at a time during zip, and then move + on to the next. + 3. no cleanup code required and no memory leaks. + 4. simple code. + + This approach should be reworked to a linked list approach if we expect to + be called by many threads which are processing a variety of input/output + volumes, since lock contention and stale data may become a bottleneck. */ + +VOLUMECAPS g_VolumeCaps; +CRITICAL_SECTION VolumeCapsLock; + + +/* our deferred set structure linked list element, used for making a copy + of input data which is used at a later time to process the original input + at a time when it makes more sense. eg, applying security to newly created + directories, after all files have been placed in such directories. */ + +CRITICAL_SECTION SetDeferLock; + +typedef struct _DEFERRED_SET { + struct _DEFERRED_SET *Next; + uch *buffer; /* must point to DWORD aligned block */ + PVOLUMECAPS VolumeCaps; + char *resource; +} DEFERRED_SET, *PDEFERRED_SET, *LPDEFERRED_SET; + +PDEFERRED_SET pSetHead = NULL; +PDEFERRED_SET pSetTail; + +static BOOL Initialize(VOID) +{ + HANDLE hMutex; + HANDLE hOldMutex; + + if(bInitialized) return TRUE; + + hMutex = CreateMutex(NULL, TRUE, NULL); + if(hMutex == NULL) return FALSE; + + hOldMutex = (HANDLE)InterlockedExchange((LPLONG)&hInitMutex, (LONG)hMutex); + + if(hOldMutex != NULL) { + /* somebody setup the mutex already */ + InterlockedExchange((LPLONG)&hInitMutex, (LONG)hOldMutex); + + CloseHandle(hMutex); /* close new, un-needed mutex */ + + /* wait for initialization to complete and return status */ + WaitForSingleObject(hOldMutex, INFINITE); + ReleaseMutex(hOldMutex); + + return bInitialized; + } + + /* initialize module level resources */ + + InitializeCriticalSection( &SetDeferLock ); + + InitializeCriticalSection( &VolumeCapsLock ); + memset(&g_VolumeCaps, 0, sizeof(VOLUMECAPS)); + + InitLocalPrivileges(); + + bInitialized = TRUE; + + ReleaseMutex(hMutex); /* release correct mutex */ + + return TRUE; +} + +#if 0 /* currently not used ! */ +static BOOL Shutdown(VOID) +{ + /* really need to free critical sections, disable enabled privilges, etc, + but doing so brings up possibility of race conditions if those resources + are about to be used. The easiest way to handle this is let these + resources be freed when the process terminates... */ + + return TRUE; +} +#endif /* never */ + + +static BOOL DeferSet(char *resource, PVOLUMECAPS VolumeCaps, uch *buffer) +{ + PDEFERRED_SET psd; + DWORD cbDeferSet; + DWORD cbResource; + DWORD cbBuffer; + + if(!bInitialized) if(!Initialize()) return FALSE; + + cbResource = lstrlenA(resource) + 1; + cbBuffer = GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)buffer); + cbDeferSet = sizeof(DEFERRED_SET) + cbBuffer + sizeof(VOLUMECAPS) + + cbResource; + + psd = (PDEFERRED_SET)HeapAlloc(GetProcessHeap(), 0, cbDeferSet); + if(psd == NULL) return FALSE; + + psd->Next = NULL; + psd->buffer = (uch *)(psd+1); + psd->VolumeCaps = (PVOLUMECAPS)((char *)psd->buffer + cbBuffer); + psd->resource = (char *)((char *)psd->VolumeCaps + sizeof(VOLUMECAPS)); + + memcpy(psd->buffer, buffer, cbBuffer); + memcpy(psd->VolumeCaps, VolumeCaps, sizeof(VOLUMECAPS)); + psd->VolumeCaps->bProcessDefer = TRUE; + memcpy(psd->resource, resource, cbResource); + + /* take defer lock */ + EnterCriticalSection( &SetDeferLock ); + + /* add element at tail of list */ + + if(pSetHead == NULL) { + pSetHead = psd; + } else { + pSetTail->Next = psd; + } + + pSetTail = psd; + + /* release defer lock */ + LeaveCriticalSection( &SetDeferLock ); + + return TRUE; +} + +BOOL ProcessDefer(PDWORD dwDirectoryCount, PDWORD dwBytesProcessed, + PDWORD dwDirectoryFail, PDWORD dwBytesFail) +{ + PDEFERRED_SET This; + PDEFERRED_SET Next; + + *dwDirectoryCount = 0; + *dwBytesProcessed = 0; + + *dwDirectoryFail = 0; + *dwBytesFail = 0; + + if(!bInitialized) return TRUE; /* nothing to do */ + + EnterCriticalSection( &SetDeferLock ); + + This = pSetHead; + + while(This) { + + if(SecuritySet(This->resource, This->VolumeCaps, This->buffer)) { + (*dwDirectoryCount)++; + *dwBytesProcessed += + GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)This->buffer); + } else { + (*dwDirectoryFail)++; + *dwBytesFail += + GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)This->buffer); + } + + Next = This->Next; + HeapFree(GetProcessHeap(), 0, This); + This = Next; + } + + pSetHead = NULL; + + LeaveCriticalSection( &SetDeferLock ); + + return TRUE; +} + +BOOL ValidateSecurity(uch *securitydata) +{ + PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata; + PACL pAcl; + PSID pSid; + BOOL bAclPresent; + BOOL bDefaulted; + + if(!IsWinNT()) return TRUE; /* don't do anything if not on WinNT */ + + if(!IsValidSecurityDescriptor(sd)) return FALSE; + + /* verify Dacl integrity */ + + if(!GetSecurityDescriptorDacl(sd, &bAclPresent, &pAcl, &bDefaulted)) + return FALSE; + + if(bAclPresent) { + if(!IsValidAcl(pAcl)) return FALSE; + } + + /* verify Sacl integrity */ + + if(!GetSecurityDescriptorSacl(sd, &bAclPresent, &pAcl, &bDefaulted)) + return FALSE; + + if(bAclPresent) { + if(!IsValidAcl(pAcl)) return FALSE; + } + + /* verify owner integrity */ + + if(!GetSecurityDescriptorOwner(sd, &pSid, &bDefaulted)) + return FALSE; + + if(pSid != NULL) { + if(!IsValidSid(pSid)) return FALSE; + } + + /* verify group integrity */ + + if(!GetSecurityDescriptorGroup(sd, &pSid, &bDefaulted)) + return FALSE; + + if(pSid != NULL) { + if(!IsValidSid(pSid)) return FALSE; + } + + return TRUE; +} + +static VOID GetRemotePrivilegesSet(char *FileName, PDWORD dwRemotePrivileges) +{ + HANDLE hFile; + + *dwRemotePrivileges = 0; + + /* see if we have the SeRestorePrivilege */ + + hFile = CreateFileA( + FileName, + ACCESS_SYSTEM_SECURITY | WRITE_DAC | WRITE_OWNER | READ_CONTROL, + FILE_SHARE_READ | FILE_SHARE_DELETE, /* no sd updating allowed here */ + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL + ); + + if(hFile != INVALID_HANDLE_VALUE) { + /* no remote way to determine SeRestorePrivilege -- just try a + read/write to simulate it */ + SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION | + SACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION; + PSECURITY_DESCRIPTOR sd; + DWORD cbBuf = 0; + + GetKernelObjectSecurity(hFile, si, NULL, cbBuf, &cbBuf); + + if(ERROR_INSUFFICIENT_BUFFER == GetLastError()) { + if((sd = HeapAlloc(GetProcessHeap(), 0, cbBuf)) != NULL) { + if(GetKernelObjectSecurity(hFile, si, sd, cbBuf, &cbBuf)) { + if(SetKernelObjectSecurity(hFile, si, sd)) + *dwRemotePrivileges |= OVERRIDE_RESTORE; + } + HeapFree(GetProcessHeap(), 0, sd); + } + } + + CloseHandle(hFile); + } else { + + /* see if we have the SeSecurityPrivilege */ + /* note we don't need this if we have SeRestorePrivilege */ + + hFile = CreateFileA( + FileName, + ACCESS_SYSTEM_SECURITY, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* max */ + NULL, + OPEN_EXISTING, + 0, + NULL + ); + + if(hFile != INVALID_HANDLE_VALUE) { + CloseHandle(hFile); + *dwRemotePrivileges |= OVERRIDE_SACL; + } + } +} + + +BOOL GetVolumeCaps( + char *rootpath, /* filepath, or NULL */ + char *name, /* filename associated with rootpath */ + PVOLUMECAPS VolumeCaps /* result structure describing capabilities */ + ) +{ + char TempRootPath[MAX_PATH + 1]; + DWORD cchTempRootPath = 0; + BOOL bSuccess = TRUE; /* assume success until told otherwise */ + + if(!bInitialized) if(!Initialize()) return FALSE; + + /* process the input path to produce a consistent path suitable for + compare operations and also suitable for certain picky Win32 API + that don't like forward slashes */ + + if(rootpath != NULL && rootpath[0] != '\0') { + DWORD i; + + cchTempRootPath = lstrlen(rootpath); + if(cchTempRootPath > MAX_PATH) return FALSE; + + /* copy input, converting forward slashes to back slashes as we go */ + + for(i = 0 ; i <= cchTempRootPath ; i++) { + if(rootpath[i] == '/') TempRootPath[i] = '\\'; + else TempRootPath[i] = rootpath[i]; + } + + /* check for UNC and Null terminate or append trailing \ as + appropriate */ + + /* possible valid UNCs we are passed follow: + \\machine\foo\bar (path is \\machine\foo\) + \\machine\foo (path is \\machine\foo\) + \\machine\foo\ + \\.\c$\ (FIXFIX: Win32API doesn't like this - GetComputerName()) + LATERLATER: handling mounted DFS drives in the future will require + slightly different logic which isn't available today. + This is required because directories can point at + different servers which have differing capabilities. + */ + + if(TempRootPath[0] == '\\' && TempRootPath[1] == '\\') { + DWORD slash = 0; + + for(i = 2 ; i < cchTempRootPath ; i++) { + if(TempRootPath[i] == '\\') { + slash++; + + if(slash == 2) { + i++; + TempRootPath[i] = '\0'; + cchTempRootPath = i; + break; + } + } + } + + /* if there was only one slash found, just tack another onto the + end */ + + if(slash == 1 && TempRootPath[cchTempRootPath] != '\\') { + TempRootPath[cchTempRootPath] = TempRootPath[0]; /* '\' */ + TempRootPath[cchTempRootPath+1] = '\0'; + cchTempRootPath++; + } + + } else { + + if(TempRootPath[1] == ':') { + + /* drive letter specified, truncate to root */ + TempRootPath[2] = '\\'; + TempRootPath[3] = '\0'; + cchTempRootPath = 3; + } else { + + /* must be file on current drive */ + TempRootPath[0] = '\0'; + cchTempRootPath = 0; + } + + } + + } /* if path != NULL */ + + /* grab lock protecting cached entry */ + EnterCriticalSection( &VolumeCapsLock ); + + if(!g_VolumeCaps.bValid || + lstrcmpi(g_VolumeCaps.RootPath, TempRootPath) != 0) + { + + /* no match found, build up new entry */ + + DWORD dwFileSystemFlags; + DWORD dwRemotePrivileges = 0; + BOOL bRemote = FALSE; + + /* release lock during expensive operations */ + LeaveCriticalSection( &VolumeCapsLock ); + + bSuccess = GetVolumeInformation( + (TempRootPath[0] == '\0') ? NULL : TempRootPath, + NULL, 0, + NULL, NULL, + &dwFileSystemFlags, + NULL, 0); + + + /* only if target volume supports Acls, and we were told to use + privileges do we need to go out and test for the remote case */ + + if(bSuccess && (dwFileSystemFlags & FS_PERSISTENT_ACLS) && + VolumeCaps->bUsePrivileges) + { + if(GetDriveType( (TempRootPath[0] == '\0') ? NULL : TempRootPath ) + == DRIVE_REMOTE) + { + bRemote = TRUE; + + /* make a determination about our remote capabilities */ + + GetRemotePrivilegesSet(name, &dwRemotePrivileges); + } + } + + /* always take the lock again, since we release it below */ + EnterCriticalSection( &VolumeCapsLock ); + + /* replace the existing data if successful */ + if(bSuccess) { + + lstrcpynA(g_VolumeCaps.RootPath, TempRootPath, cchTempRootPath+1); + g_VolumeCaps.bProcessDefer = FALSE; + g_VolumeCaps.dwFileSystemFlags = dwFileSystemFlags; + g_VolumeCaps.bRemote = bRemote; + g_VolumeCaps.dwRemotePrivileges = dwRemotePrivileges; + g_VolumeCaps.bValid = TRUE; + } + } + + if(bSuccess) { + /* copy input elements */ + g_VolumeCaps.bUsePrivileges = VolumeCaps->bUsePrivileges; + g_VolumeCaps.dwFileAttributes = VolumeCaps->dwFileAttributes; + + /* give caller results */ + memcpy(VolumeCaps, &g_VolumeCaps, sizeof(VOLUMECAPS)); + } else { + g_VolumeCaps.bValid = FALSE; + } + + LeaveCriticalSection( &VolumeCapsLock ); /* release lock */ + + return bSuccess; +} + + +BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata) +{ + HANDLE hFile; + DWORD dwDesiredAccess = 0; + DWORD dwFlags = 0; + PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata; + SECURITY_DESCRIPTOR_CONTROL sdc; + SECURITY_INFORMATION RequestedInfo = 0; + DWORD dwRev; + BOOL bRestorePrivilege = FALSE; + BOOL bSaclPrivilege = FALSE; + BOOL bSuccess; + + if(!bInitialized) if(!Initialize()) return FALSE; + + /* defer directory processing */ + + if(VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if(!VolumeCaps->bProcessDefer) { + return DeferSet(resource, VolumeCaps, securitydata); + } else { + /* opening a directory requires FILE_FLAG_BACKUP_SEMANTICS */ + dwFlags |= FILE_FLAG_BACKUP_SEMANTICS; + } + } + + /* evaluate the input security desriptor and act accordingly */ + + if(!IsValidSecurityDescriptor(sd)) + return FALSE; + + if(!GetSecurityDescriptorControl(sd, &sdc, &dwRev)) + return FALSE; + + /* setup privilege usage based on if told we can use privileges, and if so, + what privileges we have */ + + if(VolumeCaps->bUsePrivileges) { + if(VolumeCaps->bRemote) { + /* use remotely determined privileges */ + if(VolumeCaps->dwRemotePrivileges & OVERRIDE_RESTORE) + bRestorePrivilege = TRUE; + + if(VolumeCaps->dwRemotePrivileges & OVERRIDE_SACL) + bSaclPrivilege = TRUE; + + } else { + /* use local privileges */ + bRestorePrivilege = g_bRestorePrivilege; + bSaclPrivilege = g_bSaclPrivilege; + } + } + + + /* if a Dacl is present write Dacl out */ + /* if we have SeRestorePrivilege, write owner and group info out */ + + if(sdc & SE_DACL_PRESENT) { + dwDesiredAccess |= WRITE_DAC; + RequestedInfo |= DACL_SECURITY_INFORMATION; + + if(bRestorePrivilege) { + dwDesiredAccess |= WRITE_OWNER; + RequestedInfo |= (OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION); + } + } + + /* if a Sacl is present and we have either SeRestorePrivilege or + SeSystemSecurityPrivilege try to write Sacl out */ + + if((sdc & SE_SACL_PRESENT) && (bRestorePrivilege || bSaclPrivilege)) { + dwDesiredAccess |= ACCESS_SYSTEM_SECURITY; + RequestedInfo |= SACL_SECURITY_INFORMATION; + } + + if(RequestedInfo == 0) /* nothing to do */ + return FALSE; + + if(bRestorePrivilege) + dwFlags |= FILE_FLAG_BACKUP_SEMANTICS; + + hFile = CreateFileA( + resource, + dwDesiredAccess, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,/* max sharing */ + NULL, + OPEN_EXISTING, + dwFlags, + NULL + ); + + if(hFile == INVALID_HANDLE_VALUE) + return FALSE; + + bSuccess = SetKernelObjectSecurity(hFile, RequestedInfo, sd); + + CloseHandle(hFile); + + return bSuccess; +} + +static VOID InitLocalPrivileges(VOID) +{ + HANDLE hToken; + TOKEN_PRIVILEGES tp; + + /* try to enable some interesting privileges that give us the ability + to get some security information that we normally cannot. + + note that enabling privileges is only relevant on the local machine; + when accessing files that are on a remote machine, any privileges + that are present on the remote machine get enabled by default. */ + + if(!OpenProcessToken(GetCurrentProcess(), + TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) + return; + + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if(LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid)) { + + /* try to enable SeRestorePrivilege; if this succeeds, we can write + all aspects of the security descriptor */ + + if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) && + GetLastError() == ERROR_SUCCESS) g_bRestorePrivilege = TRUE; + + } + + /* try to enable SeSystemSecurityPrivilege, if SeRestorePrivilege not + present; if this succeeds, we can write the Sacl */ + + if(!g_bRestorePrivilege && + LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid)) { + + if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) && + GetLastError() == ERROR_SUCCESS) g_bSaclPrivilege = TRUE; + } + + CloseHandle(hToken); +} +#endif /* NTSD_EAS */ diff --git a/utils/Install/sfxzip/os2.c b/utils/Install/sfxzip/os2.c new file mode 100644 index 0000000000..a9a962796c --- /dev/null +++ b/utils/Install/sfxzip/os2.c @@ -0,0 +1,2187 @@ +/*--------------------------------------------------------------------------- + + 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() + 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() + InitNLS() + IsUpperNLS() + ToLowerNLS() + StringLower() + DebugMalloc() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" +#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)); + + +/*****************************/ +/* Strings used in os2.c */ +/*****************************/ + +#ifndef SFX + static char Far CantAllocateWildcard[] = + "warning: cannot allocate wildcard buffers\n"; +#endif +static char Far Creating[] = " creating: %-22s "; +static char Far ConversionFailed[] = "mapname: conversion of %s failed\n"; +static char Far Labelling[] = "labelling %c: %-22s\n"; +static char Far ErrSetVolLabel[] = "mapname: error setting volume label\n"; +static char Far PathTooLong[] = "checkdir error: path too long: %s\n"; +static char Far CantCreateDir[] = "checkdir error: cannot create %s\n\ + unable to process %s.\n"; +static char Far DirIsntDirectory[] = + "checkdir error: %s exists but is not directory\n\ + unable to process %s.\n"; +static char Far PathTooLongTrunc[] = + "checkdir warning: path too long; truncating\n %s\n\ + -> %s\n"; +#if (!defined(SFX) || defined(SFX_EXDIR)) + static char Far CantCreateExtractDir[] = + "checkdir: cannot create extraction directory: %s\n"; +#endif + +#ifndef __EMX__ +# 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 +# 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; +} + + +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; + } + + /* 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", + 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", 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(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 + char *wildspec; /* only used first time on a given dir */ +{ + /* moved to os2data.h so they can be global */ +#if 0 + static DIR *dir = NULL; + static char *dirname, *wildname, matchname[FILNAMSIZ]; + static int firstcall=TRUE, 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.firstcall) { /* first call: must initialize everything */ + G.os2.firstcall = FALSE; + + if (!iswild(wildspec)) { + strcpy(G.os2.matchname, wildspec); + G.os2.have_dirname = FALSE; + G.os2.dir = NULL; + return G.os2.matchname; + } + + /* break the wildspec into a directory part and a wildcard filename */ + if ((G.os2.wildname = strrchr(wildspec, '/')) == NULL && + (G.os2.wildname = 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))); + strcpy(G.os2.matchname, wildspec); + 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", G.os2.dirname)); + + if ((G.os2.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.dir)) != NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", file->d_name)); + strcpy(fnamestart, file->d_name); + if (strrchr(fnamestart, '.') == (char *)NULL) + strcat(fnamestart, "."); + if (match(fnamestart, G.os2.wildname, 1) && /* 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.dir); + G.os2.dir = NULL; + } +#ifdef DEBUG + else { + Trace((stderr, "do_wild: opendir(%s) returns NULL\n", 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) */ + strcpy(G.os2.matchname, wildspec); + return G.os2.matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (G.os2.dir == NULL) { + G.os2.firstcall = TRUE; /* nothing left to try--reset for new wildspec */ + 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.dir)) != NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", file->d_name)); + strcpy(fnamestart, file->d_name); + if (strrchr(fnamestart, '.') == (char *)NULL) + strcat(fnamestart, "."); + if (match(fnamestart, G.os2.wildname, 1)) { /* 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.dir); /* have read at least one dir entry; nothing left */ + G.os2.dir = NULL; + G.os2.firstcall = TRUE; /* 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& + */ + /* return 0 if no error, 1 if caution (filename */ +int mapname(__G__ renamed) /* truncated), 2 if warning (skip file because */ + __GDEF /* dir doesn't exist), 3 if error (skip file), */ + int renamed; /* or 10 if out of memory (skip file) */ +{ /* [also IZ_VOL_LABEL, IZ_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 quote = FALSE; /* flag: next char is literal */ + int error = 0; + 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(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) { + + if (quote) { /* if character quoted, */ + *pp++ = (char)workch; /* include it literally */ + quote = FALSE; + } else + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave directory semi-colons alone */ + break; + + case ':': + *pp++ = '_'; /* drive names not stored in zipfile, */ + break; /* so no colons allowed */ + + case ';': /* start of VMS version? */ + lastsemi = pp; /* remove VMS version later... */ + *pp++ = ';'; /* but keep semicolon for now */ + break; + + case '\026': /* control-V quote for special chars */ + quote = TRUE; /* set flag for next character */ + break; + + 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 */ + + *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'; + } + +/*--------------------------------------------------------------------------- + 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 (!uO.qflag) + Info(slide, 0, ((char *)slide, LoadFarString(Creating), + 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 ", 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); + + return IZ_CREATED_DIR; /* dir time already set */ + + } else if (G.extra_field && uO.overwrite_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 ", 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); + } + return 2; /* dir existed already; don't look for data to extract */ + } + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed), + G.filename)); + return 3; + } + + 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", + 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), G.filename)); + if (DosSetFSInfo(G.os2.nLabelDrive, FSIL_VOLSER, (PBYTE)&FSInfoBuf, + sizeof(VOLUMELABEL))) + { + Info(slide, 1, ((char *)slide, LoadFarString(ErrSetVolLabel))); + return 3; + } + return 2; /* success: skip the "extraction" quietly */ + } + + return error; + +} /* end function mapname() */ + + + + + +/***********************/ +/* Function checkdir() */ +/***********************/ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: 1 - (on APPEND_NAME) truncated filename + * 2 - path doesn't exist, not allowed to create + * 3 - path doesn't exist, tried to create and failed; or + * path exists and is not a directory, but is supposed to be + * 4 - path is too long + * 10 - 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", 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); + return 2; /* path doesn't exist: nothing to do */ + } + if (too_long) { /* GRR: should allow FAT extraction w/o EAs */ + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong), + G.os2.buildpathHPFS)); + free(G.os2.buildpathHPFS); + free(G.os2.buildpathFAT); + return 4; /* no room for filenames: fatal */ + } + if (MKDIR(G.os2.buildpathFAT, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir), + G.os2.buildpathFAT, G.filename)); + free(G.os2.buildpathHPFS); + free(G.os2.buildpathFAT); + return 3; /* path didn't exist, tried to create, failed */ + } + 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), + G.os2.buildpathFAT, G.filename)); + free(G.os2.buildpathHPFS); + free(G.os2.buildpathFAT); + return 3; /* path existed but wasn't dir */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong), + G.os2.buildpathHPFS)); + free(G.os2.buildpathHPFS); + free(G.os2.buildpathFAT); + return 4; /* no room for filenames: fatal */ + } + *G.os2.endHPFS++ = '/'; + *G.os2.endFAT++ = '/'; + *G.os2.endHPFS = *G.os2.endFAT = '\0'; + Trace((stderr, "buildpathHPFS now = [%s]\n", G.os2.buildpathHPFS)); + Trace((stderr, "buildpathFAT now = [%s]\n", G.os2.buildpathFAT)); + return 0; + + } /* 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", G.os2.buildpathFAT)); + Trace((stderr, "freeing HPFS path [%s]\n", 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 0; + } + +/*--------------------------------------------------------------------------- + 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 = 0; + + Trace((stderr, "appending filename [%s]\n", pathcomp)); + while ((*G.os2.endHPFS = *p++) != '\0') { /* copy to HPFS filename */ + ++G.os2.endHPFS; + if ((G.os2.endHPFS-G.os2.buildpathHPFS) >= FILNAMSIZ) { + *--G.os2.endHPFS = '\0'; + Info(slide, 1, ((char *)slide, LoadFarString(PathTooLongTrunc), + G.filename, G.os2.buildpathHPFS)); + error = 1; /* 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)) + */ + if (G.pInfo->vollabel || IsFileNameValid(G.os2.buildpathHPFS)) { + G.os2.longnameEA = FALSE; + p = pathcomp; + while ((*G.os2.endFAT = *p++) != '\0') /* copy to FAT filename, too */ + ++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; + error = 1; /* can't set .LONGNAME extended attribute */ + } else /* used and freed in close_outfile() */ + strcpy(G.os2.lastpathcomp, pathcomp); + map2fat(pathcomp, &G.os2.endFAT); /* map, put in FAT fn, update endFAT */ + } + Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n", + G.os2.buildpathHPFS, 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 ")); + if ((G.os2.buildpathHPFS = (char *)malloc(G.os2.fnlen+G.os2.rootlen+1)) == (char *)NULL) + return 10; + if ((G.os2.buildpathFAT = (char *)malloc(G.os2.fnlen+G.os2.rootlen+1)) == (char *)NULL) { + free(G.os2.buildpathHPFS); + return 10; + } + 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 IZ_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", G.os2.buildpathHPFS)); + return 0; + } + +/*--------------------------------------------------------------------------- + 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", pathcomp)); + if (pathcomp == (char *)NULL) { + G.os2.rootlen = 0; + return 0; + } + if ((G.os2.rootlen = strlen(pathcomp)) > 0) { + int had_trailing_pathsep=FALSE, has_drive=FALSE, xtra=2; + + if (isalpha(pathcomp[0]) && pathcomp[1] == ':') + has_drive = TRUE; /* drive designator */ + if (pathcomp[G.os2.rootlen-1] == '/') { + pathcomp[--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:/" */ + xtra = 3; /* room for '.' + '/' + 0 at end of "x:" */ + } 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(pathcomp) == -1 || + SSTAT(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) +#else + if (SSTAT(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) +#endif + { /* path does not exist */ + if (!G.create_dirs /* || iswild(pathcomp) */ + ) { + G.os2.rootlen = 0; + return 2; /* treat as stored file */ + } + /* create directory (could add loop here to scan pathcomp + * and create more than one level, but really necessary?) */ + if (MKDIR(pathcomp, 0777) == -1) { + Info(slide, 1, ((char *)slide, + LoadFarString(CantCreateExtractDir), pathcomp)); + G.os2.rootlen = 0; /* path didn't exist, tried to create, */ + return 3; /* failed: file exists, or need 2+ levels */ + } + } + } + if ((G.os2.rootpath = (char *)malloc(G.os2.rootlen+xtra)) == (char *)NULL) { + G.os2.rootlen = 0; + return 10; + } + strcpy(G.os2.rootpath, pathcomp); + if (xtra == 3) /* had just "x:", make "x:." */ + G.os2.rootpath[G.os2.rootlen++] = '.'; + G.os2.rootpath[G.os2.rootlen++] = '/'; + G.os2.rootpath[G.os2.rootlen] = '\0'; + Trace((stderr, "rootpath now = [%s]\n", G.os2.rootpath)); + } + return 0; + } +#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 0; + } + + return 99; /* 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 ", 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/2 ", __VERSION__, +# endif +#elif defined(__IBMC__) + "IBM ", +# if (__IBMC__ < 200) + (sprintf(buf, "C Set/2 %d.%02d", __IBMC__/100,__IBMC__%100), buf), +# elif (__IBMC__ < 300) + (sprintf(buf, "C Set++ %d.%02d", __IBMC__/100,__IBMC__%100), buf), +# else + (sprintf(buf, "Visual Age C++ %d.%02d", __IBMC__/100,__IBMC__%100), buf), +# endif +#elif defined(__WATCOMC__) + "Watcom C", (sprintf(buf, " (__WATCOMC__ = %d)", __WATCOMC__), buf), +#elif defined(__TURBOC__) +# ifdef __BORLANDC__ + "Borland C++", +# if (__BORLANDC__ < 0x0460) + " 1.0", +# elif (__BORLANDC__ == 0x0460) + " 1.5", /* 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 + " 2.x/3.x (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 */ + + + +/* 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; +} + + +#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); + G.os2.firstcall = TRUE; + +#ifdef OS2DLL + G.os2.rexx_mes = "0"; +#endif + + InitNLS(); +} diff --git a/utils/Install/sfxzip/os2acl.c b/utils/Install/sfxzip/os2acl.c new file mode 100644 index 0000000000..c58f6e0419 --- /dev/null +++ b/utils/Install/sfxzip/os2acl.c @@ -0,0 +1,381 @@ +/* os2acl.c - access to OS/2 (LAN Server) ACLs + * + * Author: Kai Uwe Rommel + * Created: Mon Aug 08 1994 + * + * This code is in the public domain. + */ + +/* + * 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$"; + static char *rcsrev = "$Revision$"; +#endif + +/* + * $Log$ + * Revision 1.1.2.1 2000/04/11 12:38:06 BS + * Added wxInstall a self extracting installation program using wxWindows. + * + * 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(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/utils/Install/sfxzip/process.c b/utils/Install/sfxzip/process.c new file mode 100644 index 0000000000..73be25466a --- /dev/null +++ b/utils/Install/sfxzip/process.c @@ -0,0 +1,1400 @@ +/*--------------------------------------------------------------------------- + + process.c + + This file contains the top-level routines for processing multiple zipfiles. + + Contains: process_zipfiles() + free_G_buffers() + do_seekable() + find_ecrec() + uz_end_central() + process_cdir_file_hdr() + get_cdir_ent() + process_local_file_hdr() + ef_scan_for_izux() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" +#ifdef WINDLL +# ifdef POCKET_UNZIP +# include "wince/intrface.h" +# else +# include "windll/windll.h" +# endif +#endif + +#include "install.h" +#include "instsup.h" +extern int installstate; + +off_t acelseek(off_t offset, int whence); +int aceread(void *buf, size_t count); +int aceopen(const char *path, int flags); +int aceclose(int fd); +int acesize(void); +int acetell(int fd); +char *replacestr(char *str1, char *str2, char *str3); + +static int do_seekable OF((__GPRO__ int lastchance)); +static int find_ecrec OF((__GPRO__ long searchlen)); + +static ZCONST char Far CannotAllocateBuffers[] = + "error: cannot allocate unzip buffers\n"; + +#ifdef SFX + static ZCONST char Far CannotFindMyself[] = + "unzipsfx: cannot find myself! [%s]\n"; + +#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 + 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 %s, %s.zip or %s.\n"; /* ", so there" removed 970918 */ +# else /* !UNIX */ +# ifndef AMIGA + static ZCONST char Far CannotFindWildcardMatch[] = + "%s: cannot find any matches for wildcard specification \"%s\".\n"; +# endif /* !AMIGA */ + static ZCONST char Far CannotFindZipfileDirMsg[] = + "%s: cannot find zipfile directory in %s,\n\ + %sand cannot find %s, period.\n"; + static ZCONST char Far CannotFindEitherZipfile[] = + "%s: cannot find either %s or %s.\n"; /* ", so there" removed 970918 */ +# 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 + 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 %u of a multi-disk archive, and this is not the disk on\n\ + which the central zipfile directory begins (disk %u).\n"; + static ZCONST char Far EndCentDirBogus[] = + "\nwarning [%s]: end-of-central-directory record claims this\n\ + is disk %u but that the central directory starts on disk %u; 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]: %ld extra byte%s at beginning or within zipfile\n\ + (attempting to process anyway)\n"; +#endif /* ?SFX */ + +static ZCONST char Far MissingBytes[] = + "error [%s]: missing %ld 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"; +#ifndef SFX + static ZCONST char Far CentDirTooLong[] = + "error [%s]: reported length of central directory is\n\ + %ld 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 */ +static ZCONST char Far ZipfileCommTrunc1[] = + "\ncaution: zipfile comment truncated\n"; + + + + +/*******************************/ +/* 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; + extern unsigned current_file; + extern char installdir2[]; + + +/*--------------------------------------------------------------------------- + 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 only later when we know we have a zipfile */ + CRC_32_TAB = NULL; +#endif /* 0 */ + + /* finish up initialization of magic signature strings */ + local_hdr_sig[0] /* = extd_local_sig[0] */ = 0x50; /* ASCII 'P', */ + central_hdr_sig[0] = end_central_sig[0] = 0x50; /* not EBCDIC */ + + local_hdr_sig[1] /* = extd_local_sig[1] */ = 0x4B; /* ASCII 'K', */ + central_hdr_sig[1] = end_central_sig[1] = 0x4B; /* not EBCDIC */ + +/*--------------------------------------------------------------------------- + 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 were + initially copied from dos_to_unix_time() in fileio.c. probably, they are + still too strict; any listed OS that supplies tzset(), regardless of + whether the function does anything, should be removed from the ifdefs. + ---------------------------------------------------------------------------*/ + +#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 + +/*--------------------------------------------------------------------------- + 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)); + } + +#else /* !SFX */ + NumWinFiles = NumLoseFiles = NumWarnFiles = 0; + current_file = 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) + ++NumLoseFiles; + else + ++NumWinFiles; + + current_file = NumWinFiles; + + if(installstate == INSTALLING) + DoGUI(); + + if (error != IZ_DIR && error > error_in_archive) + error_in_archive = error; + Trace((stderr, "do_seekable(0) returns %d\n", 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) + { + NumMissDirs = NumMissFiles = 0; + if (error_in_archive == PK_NOZIP) + error_in_archive = PK_COOL; + +#if (!defined(UNIX) && !defined(AMIGA)) /* filenames with wildcard characters */ + if (iswild(G.wildzipfn)) + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotFindWildcardMatch), uO.zipinfo_mode? + LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip), + G.wildzipfn)); + else +#endif + { + char *p = lastzipfn + strlen(lastzipfn); + + G.zipfn = lastzipfn; + strcpy(p, ZSUFX); + +#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 + if (error == PK_WARN) /* GRR: make this a switch/case stmt ... */ + ++NumWarnFiles; + else if (error == IZ_DIR) + ++NumMissDirs; + else if (error == PK_NOZIP) + /* increment again => bug: "1 file had no zipfile directory." */ + /* ++NumMissFiles */ ; + else if (error) + ++NumLoseFiles; + else + ++NumWinFiles; + + if (error > error_in_archive) + error_in_archive = error; + Trace((stderr, "do_seekable(1) returns %d\n", 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.qflag && !uO.zipinfo_mode) +#endif + ) + { + if ((NumMissFiles + NumLoseFiles + NumWarnFiles > 0 || NumWinFiles != 1) +#ifdef TIMESTAMP + && !(uO.T_flag && !uO.zipinfo_mode) +#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 +{ + 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 (!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 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; + unsigned nmember = 0; +#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 0 + if (SSTAT(G.zipfn, &G.statbuf) || + (error = S_ISDIR(G.statbuf.st_mode)) != 0) + { +#ifndef SFX + if (lastchance) { +#if defined(UNIX) || defined(QDOS) + if (G.no_ecrec) + Info(slide, 1, ((char *)slide, + LoadFarString(CannotFindZipfileDirMsg), uO.zipinfo_mode? + LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip), + G.wildzipfn, uO.zipinfo_mode? " " : "", G.wildzipfn, + G.zipfn)); + else + Info(slide, 1, ((char *)slide, + LoadFarString(CannotFindEitherZipfile), uO.zipinfo_mode? + LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip), + G.wildzipfn, G.wildzipfn, G.zipfn)); +#else /* !UNIX */ + if (G.no_ecrec) + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotFindZipfileDirMsg), uO.zipinfo_mode? + LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip), + G.wildzipfn, uO.zipinfo_mode? " " : "", G.zipfn)); + else + Info(slide, 0x401, ((char *)slide, + LoadFarString(CannotFindEitherZipfile), uO.zipinfo_mode? + LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip), + G.wildzipfn, G.zipfn)); +#endif /* ?UNIX */ + } +#endif /* !SFX */ + return error? IZ_DIR : PK_NOZIP; + } + G.ziplen = G.statbuf.st_size; +#endif + G.ziplen = acesize(); + +#ifndef SFX +#if defined(UNIX) || defined(DOS_OS2_W32) + 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... */ + +/*--------------------------------------------------------------------------- + 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. + ---------------------------------------------------------------------------*/ + + /* 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)) + /* 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)) > 2) + return error; /* out of memory, or file in way */ + } +#endif /* !SFX || SFX_EXDIR */ + + G.cur_zipfile_bufstart = 0; + G.inptr = G.inbuf; + +#if (!defined(WINDLL) && !defined(SFX)) +#ifdef TIMESTAMP + if (!uO.zipinfo_mode && !uO.qflag && !uO.T_flag) +#else + if (!uO.zipinfo_mode && !uO.qflag) +#endif +#ifdef WIN32 /* Win32 console may require codepage conversion for G.zipfn */ + Info(slide, 0, ((char *)slide, "Archive: %s\n", FnFilter1(G.zipfn))); +#else + Info(slide, 0, ((char *)slide, "Archive: %s\n", G.zipfn)); +#endif +#endif /* !WINDLL && !SFX */ + + if (( +#ifndef NO_ZIPINFO + uO.zipinfo_mode && + ((error_in_archive = find_ecrec(__G__ G.ziplen)) != 0 || + (error_in_archive = zi_end_central(__G)) > PK_WARN)) + || (!uO.zipinfo_mode && +#endif + ((error_in_archive = find_ecrec(__G__ MIN(G.ziplen,66000L))) != 0 || + (error_in_archive = uz_end_central(__G)) > 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, + G.ecrec.number_this_disk, 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, + G.ecrec.number_this_disk, 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) < + (LONGINT)0) + { + Info(slide, 0x401, ((char *)slide, LoadFarString(MissingBytes), + G.zipfn, (long)(-G.extra_bytes))); + 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, + (long)G.extra_bytes, (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). + -----------------------------------------------------------------------*/ + + ZLSEEK( G.ecrec.offset_start_central_directory ) +#ifdef OLD_SEEK_TEST + if (readbuf(G.sig, 4) == 0) { + CLOSE_INFILE(); + return PK_ERR; /* file may be locked, or possibly disk error(?) */ + } + if (strncmp(G.sig, central_hdr_sig, 4)) +#else + if ((readbuf(__G__ G.sig, 4) == 0) || + strncmp(G.sig, central_hdr_sig, 4)) +#endif + { +#ifndef SFX + long tmp = G.extra_bytes; +#endif + + G.extra_bytes = 0; + ZLSEEK( G.ecrec.offset_start_central_directory ) + if ((readbuf(__G__ G.sig, 4) == 0) || + strncmp(G.sig, central_hdr_sig, 4)) + { + Info(slide, 0x401, ((char *)slide, + LoadFarString(CentDirStartNotFound), G.zipfn, + LoadFarStringSmall(ReportMsg))); + CLOSE_INFILE(); + return PK_BADERR; + } +#ifndef SFX + Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirTooLong), + G.zipfn, -tmp)); +#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. + -----------------------------------------------------------------------*/ + + Trace((stderr, "about to extract/list files (error = %d)\n", + error_in_archive)); + + ZLSEEK( G.ecrec.offset_start_central_directory ) + +#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 > 0)) { +# ifdef WIN32 + if (stamp_file(__G__ G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */ +# else + if (stamp_file(G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */ +# endif + Info(slide, 0x201, ((char *)slide, + "warning: cannot set time for %s\n", G.zipfn)); + if (error_in_archive < PK_WARN) + error_in_archive = PK_WARN; + } + } +#endif + return error_in_archive; + +} /* end function do_seekable() */ + + + + + +/*************************/ +/* Function find_ecrec() */ +/*************************/ + +static int find_ecrec(__G__ searchlen) /* return PK-class error */ + __GDEF + long searchlen; +{ + int i, numblks, found=FALSE; + LONGINT tail_len; + ec_byte_rec byterec; + + +/*--------------------------------------------------------------------------- + Treat case of short zipfile separately. + ---------------------------------------------------------------------------*/ + + if (G.ziplen <= INBUFSIZ) { + acelseek(0L, SEEK_SET); + if ((G.incnt = aceread((char *)G.inbuf,(unsigned int)G.ziplen)) + == (int)G.ziplen) + + /* 'P' must be at least 22 bytes from end of zipfile */ + for (G.inptr = G.inbuf+(int)G.ziplen-22; G.inptr >= G.inbuf; + --G.inptr) + if ((native(*G.inptr) == 'P') && + !strncmp((char *)G.inptr, end_central_sig, 4)) { + G.incnt -= (int)(G.inptr - G.inbuf); + found = TRUE; + break; + } + +/*--------------------------------------------------------------------------- + Zipfile is longer than INBUFSIZ: may need to loop. Start with short + block at end of zipfile (if not TOO short). + ---------------------------------------------------------------------------*/ + + } else { + if ((tail_len = G.ziplen % INBUFSIZ) > ECREC_SIZE) { +#ifdef USE_STRM_INPUT + fseek((FILE *)G.zipfd, G.ziplen-tail_len, SEEK_SET); + G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd); +#else /* !USE_STRM_INPUT */ + G.cur_zipfile_bufstart = acelseek(G.ziplen-tail_len, + SEEK_SET); +#endif /* ?USE_STRM_INPUT */ + if ((G.incnt = aceread((char *)G.inbuf, + (unsigned int)tail_len)) != (int)tail_len) + goto fail; /* it's expedient... */ + + /* 'P' must be at least 22 bytes from end of zipfile */ + for (G.inptr = G.inbuf+(int)tail_len-22; G.inptr >= G.inbuf; + --G.inptr) + if ((native(*G.inptr) == 'P') && + !strncmp((char *)G.inptr, end_central_sig, 4)) { + G.incnt -= (int)(G.inptr - G.inbuf); + found = TRUE; + break; + } + /* sig may span block boundary: */ + strncpy((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; + acelseek(G.cur_zipfile_bufstart, SEEK_SET); + if ((G.incnt = aceread((char *)G.inbuf,INBUFSIZ)) + != INBUFSIZ) + break; /* fall through and fail */ + + for (G.inptr = G.inbuf+INBUFSIZ-1; G.inptr >= G.inbuf; + --G.inptr) + if ((native(*G.inptr) == 'P') && + !strncmp((char *)G.inptr, end_central_sig, 4)) { + G.incnt -= (int)(G.inptr - G.inbuf); + found = TRUE; + break; + } + /* sig may span block boundary: */ + strncpy((char *)G.hold, (char *)G.inbuf, 3); + } + } /* end if (ziplen > INBUFSIZ) */ + +/*--------------------------------------------------------------------------- + Searched through whole region where signature should be without finding + it. Print informational message and die a horrible death. + ---------------------------------------------------------------------------*/ + +fail: + 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 + pipeit("\n found end-of-central-dir signature at offset %ld (%.8lXh)\n", + G.real_ecrec_offset, G.real_ecrec_offset); + pipeit(" 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_CENTRAL_DIR]); + G.ecrec.num_entries_centrl_dir_ths_disk = + makeword(&byterec[NUM_ENTRIES_CENTRL_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]); + + G.expect_ecrec_offset = G.ecrec.offset_start_central_directory + + G.ecrec.size_central_directory; + return PK_COOL; + +} /* end function find_ecrec() */ + + + + + +/*****************************/ +/* Function uz_end_central() */ +/*****************************/ + +int uz_end_central(__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. + Then position the file pointer to the beginning of the central directory + and fill buffer. + ---------------------------------------------------------------------------*/ + +#ifdef WINDLL + /* for comment button: */ + if ((!G.fValidate) && (G.lpUserFunctions != NULL)) + G.lpUserFunctions->cchComment = G.ecrec.zipfile_comment_length; + if (G.ecrec.zipfile_comment_length && (uO.zflag > 0)) +#else /* !WINDLL */ + if (G.ecrec.zipfile_comment_length && (uO.zflag > 0 || + (uO.zflag == 0 && +#ifdef TIMESTAMP + !uO.T_flag && +#endif + !uO.qflag))) +#endif /* ?WINDLL */ + { + if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(ZipfileCommTrunc1))); + error = PK_WARN; + } + } + return error; + +} /* end function uz_end_central() */ + + + + + +/************************************/ +/* 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->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) /* user specified case-conversion */ + 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_, BEOS_ (Z_SYSTEM_): no conversion */ + } + + /* 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; + + return PK_COOL; + +} /* end function process_cdir_file_hdr() */ + + + + + +/***************************/ +/* Function get_cdir_ent() */ +/***************************/ + +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]); + + G.csize = (long) G.lrec.csize; + G.ucsize = (long) G.lrec.ucsize; + + if ((G.lrec.general_purpose_bit_flag & 8) != 0) { + /* can't trust local header, use central directory: */ + G.lrec.crc32 = G.pInfo->crc; + G.csize = (long)(G.lrec.csize = G.pInfo->compr_size); + G.ucsize = (long)(G.lrec.ucsize = G.pInfo->uncompr_size); + } + + return PK_COOL; + +} /* end function process_local_file_hdr() */ + + +#ifdef USE_EF_UT_TIME + +/*******************************/ +/* Function ef_scan_for_izux() */ +/*******************************/ + +unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos_mdatetime, + z_utim, z_uidgid) + 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 */ + ush *z_uidgid; /* return storage: uid and gid */ +{ + unsigned flags = 0; + unsigned eb_id; + unsigned eb_len; + int have_new_type_eb = FALSE; + int ut_zip_unzip_compatible = FALSE; + +/*--------------------------------------------------------------------------- + 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 = TRUE; + 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) { + z_utim->mtime = makelong((EB_HEADSIZE+eb_idx) + ef_buf); + eb_idx += 4; + TTrace((stderr," UT e.f. modification time = %ld\n", + z_utim->mtime)); + + if ((ulg)(z_utim->mtime) & (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, + " 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; + } + } 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) { + z_utim->atime = makelong((EB_HEADSIZE+eb_idx) + ef_buf); + eb_idx += 4; + TTrace((stderr," UT e.f. access time = %ld\n", + z_utim->atime)); + if (((ulg)(z_utim->atime) & (ulg)(0x80000000L)) && + !ut_zip_unzip_compatible) { + flags &= ~EB_UT_FL_ATIME; + TTrace((stderr, + " UT access time range error: skip time!\n")); + } + } else { + flags &= ~EB_UT_FL_ATIME; + } + } + if (flags & EB_UT_FL_CTIME) { + if ((eb_idx+4) <= eb_len) { + z_utim->ctime = makelong((EB_HEADSIZE+eb_idx) + ef_buf); + TTrace((stderr," UT e.f. creation time = %ld\n", + z_utim->ctime)); + if (((ulg)(z_utim->ctime) & (ulg)(0x80000000L)) && + !ut_zip_unzip_compatible) { + flags &= ~EB_UT_FL_CTIME; + TTrace((stderr, + " UT creation time range error: skip time!\n")); + } + } else { + flags &= ~EB_UT_FL_CTIME; + } + } + } + break; + + case EF_IZUNIX2: + if (!have_new_type_eb) { + flags &= ~0x0ff; /* ignore any previous IZUNIX field */ + have_new_type_eb = TRUE; + } + if (eb_len >= EB_UX2_MINLEN && z_uidgid != NULL) { + z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX2_UID) + ef_buf); + z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX2_GID) + ef_buf); + flags |= EB_UX2_VALID; /* signal success */ + } + 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) { + break; /* Ignore IZUNIX extra field block ! */ + } + if (z_utim != NULL) { + z_utim->atime = makelong((EB_HEADSIZE+EB_UX_ATIME)+ef_buf); + z_utim->mtime = makelong((EB_HEADSIZE+EB_UX_MTIME)+ef_buf); + TTrace((stderr," Unix EF actime = %ld\n", z_utim->atime)); + TTrace((stderr," Unix EF modtime = %ld\n", z_utim->mtime)); + flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME); + if ((ulg)(z_utim->mtime) & (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; + } + if ((ulg)(z_utim->atime) & (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")); + } + } + 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; + } + } + 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 */ diff --git a/utils/Install/sfxzip/rexxapi.c b/utils/Install/sfxzip/rexxapi.c new file mode 100644 index 0000000000..43b4ddde3e --- /dev/null +++ b/utils/Install/sfxzip/rexxapi.c @@ -0,0 +1,886 @@ +/********************************************************************** +* 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 "../version.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, + PATCHLEVEL, 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, + PATCHLEVEL, BETALEVEL, 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__ 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)); + sprintf(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/utils/Install/sfxzip/rexxhelp.c b/utils/Install/sfxzip/rexxhelp.c new file mode 100644 index 0000000000..20a72597a8 --- /dev/null +++ b/utils/Install/sfxzip/rexxhelp.c @@ -0,0 +1,178 @@ +/* rexxhelp.c */ + +#if defined(API_DOC) && defined(OS2DLL) + +#define UNZIP_INTERNAL +#include "../unzip.h" +#include "../version.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/utils/Install/sfxzip/sfx.RES b/utils/Install/sfxzip/sfx.RES new file mode 100644 index 0000000000000000000000000000000000000000..09bcebd7887a75a6a5d6fa5fb08771241e46bbfb GIT binary patch literal 13744 zcmeHNO^jT{5w16H?6>}rXN@9^1z|=U5XVJ9(JBUJY%gA0F}AVS;pgH-kRKEWhM#B_ zZ2VqGBqL=d!_iWN$=}5%q~u`9Nc%)0#fO#5DdGg9L<*eZL5{>YjHmN`)!j31o@Zxm zyvBmiyEU(?yQ;dos;jzQ&xnXr0LEBAb)eh^Yzkn^DtS~Mll}6L9FSe|1fE-Eo9xDO z3iwvk_R4gRcVc`^(Ibg0y6RnWtGprKci04;_XE7_?U1rhW*}{^>=`0;Q0BSBipk2H zlAp`Z@b@y-^t3!9Ps(9=PJRqRuA>Ivquh+NlSMAYtvPOgSHBw1_jmi zLbrytlz{&9lrevS*erZJe3)-xQj-8<*6aS+j{UM99<~>shhXWgx|{6G2lr0_+O0s( z)G{q&KPxJW_9-Y+);=XEt-O8g)L^4jWc@5Rgh*vf=v(vhBgie z0yEV_!nd)z-bceH00sgQYyy-3s{trEwOtc>0@TpH2?6jRlK|2fE?2cCX~X?GAn0B} z0HPL%VM5x;o+ZQlXrD&n?TBu>b+#g-Z4~BgR8+34jn>MV8)%~mjJFf;Ius9oDO5!M zQ^O%)vM!bQXMj5w0Ju2YU;UDbUnamh+%H4xrMh{IW4)Rm8d2w4v{daGQ(2 zG3Mj9V)L)n7FcH+``Vv^g|-4~w$Mh1221$T!-#d$h<3YV2jC&ZKVL@Ms+hCYDrL*s zYDME-)Wo?0PpM!}Z2yPI{6?6lk_45hq)?f!6}H||D{Q-~R+!pWE9`u&R=BrV3+^f= zK@rBAzZX33SzgMZtR+fTZv*vqIdc}lTf!zxl*Zk15_ift86R9sU>tA<;8wsoz^X)~kRo`_0>P%gxn;DC_QRK$L-ZrwXd6X2 z8;xO!Oso3uTjO8AkAhYy2~K>PNX)D@PQr!DY1Aq;OXn}P$_tmFVoVQyYT~~iF)?rp519B}!go!4xEvpAmls}bm(IV~qRepN)s$oCSQwLI zBZEh*>O&j80l(1gkz#ug5*XBjEK@ukpQ+<-VyjUmWoO4?eYA}p#o082_p+Vh%V-;o zvjVw!CMGh zhY|^^smv{;atyI80<-}Jcok{z36n&hAwX8KYppNFp(9qg)He#IH0blZEw2jv0Y{b|;80*S6(neAjc{!2bzmpPnQVB2L zDPi{*pb01gH#oO=1Mq2A;tNfUDt=)jo^~+gLtMMb1?uAiQ3Y zkT6z}>EgKjs4ynSf}+H&*CZ}(9e`uNkN)x(GFK}|y;79f@iD25A(x1nNH=n&T}8Yq z4+7fwdep_c5#wKH+`{BU*^C2Z4mLar8?J`^BG@lXt^~MUkOWB0LlZS4Q^H+Sxm{l7 zefANYNBi-|TSi+(+h~2xM#Ey=3fRca<;!}Qn_Ncw5%0!%d*^Svm%DRVE1%%?qXOmO zr4A6N8nfropbzl?N1O)F@RHado+KK}`H3nZku*)gf)K(ef)iUG_(T;z%#{f7FIyTp zJl9{!;bs7jN&|SK0ld-h;vxD3an}&Z7-o`4!w-2vZQVwLa#$2^MUfJ~30-L^0g?8i z5|JP#-dQ})N2^hfw8P<$5V76UV-jJ_ndT(OEo)XA3wPz^w~Zb&$Xoc7wo94OGrz4cpM} z>zk7}-b29x-8*93?4a{+BmiKrE}#uab&FJyA25Gr9?g6@Y~t)m0SQJXEK#_jNy9uo zN^Ne>9G{s@40+gjyqCzvz72XOz6+T*zY#hlk08I}_fP&iB1l9TjD5_cE0rQXZ&Qy7 za(-nU=H~bnmE0?sd9Th&T_$un_5-Bh*-S|qjV&4U?3ri~KkM-`@@u7w>X!Z;Sx5X# zRJZaR{!T+I?&uTj1*><;g#hb`+Xc|Xbe2H$n*A5qi#h<@`0zB2gfD^>Uk{RMC8 zg1m!%!SU^GQV6$SN*rY+xqi7%=xL!UsfngA@ z3&>9?$t7iAw?XyfDT9wqb>OEAtN7-E0<<4h+qkK*8C|SvH%2551ceocgFt0^oCNG% z3eVGn+{vqN1{b>hc$}Zs**0Xpy4?PH#$|B5dHqnG5aSETmBHa}63ysayZamt6>;`b zYRdw9y58Q|l&DW+&!(sep9A>wX}L3sqP;I>&#DMAN`T&Z#apuMc{K?}WAc8*J3VIU zOMRD-KdZu=PZc3`@LlSg9PnClK<;rAp96M~Gco7NRQEI0l;odfexL9``xl zHR2$*@>@0s)Uo*Ca=;$$azHb$DW5^mw>hliZvjVmXNIWqxJhi1*h>*X@RiR2@58FD z^eKLuu>(G3%jn#%nDeJq%5*c&C^v2Q@W+os@hal-AluNWW2g2xB7J4*EDL#1-m2=tUD_pu-(|e=tk~X@+*!k9@*jWc?9f89eX(PM$q?h zbTaqs^L!U%Xs_4~*WMhE|w=X&%NOHKb*@Jd6b=?&6(?H;8a?>M?F2za#j1 ziZjRKq#-SN^z6~P{T&j|BM;h_K)-|(aOaFT+f0k9y6^K3SusbHWL$GJL+qdIRjyv_?-mYZ-;J)My zDZ%eczkkt`D+?m{mxTrUz$dDD$F|(QY}E0R0@eoKUGS{)t;I^WQ5=Z&;}BpJwAA_p zsXiO7UHP)>+^%`&0r=+NN^izGdlR>pbyz1>%=vr3^0e-suHDn2SJ&&`@M_4=Z7eIm zg8bd_3|4s%_0el(47>&4ZTbP~zKo+nu;n^z3M1Kq^-bsNznVHuo3edwy0Me>Db!!W z|8dlJqJw?Yq}ho!^0WTZ6q{`wk9yRvztXQ`!vY~aNKU`qr&-&l(LLwq01DDiPlG`V ze%{CVxO#T})cGWoLm%qvdkzZw~l-?dAR8%eP0y z_cMDiyEn6YwvpM(gR$Z|?C}NtM(yF|toF#-)yW(lm!7~W|Nj%0U}5Z9jr-IPKhiYM>!(jg1lvv;+pdww)8pmS%DI}jw3OcMS-iX-d=1WFjTBDT8NE~I4d|Y_9?&~< PPVc(HPCYqSqxb&-^+!7H literal 0 HcmV?d00001 diff --git a/utils/Install/sfxzip/sfx.rc b/utils/Install/sfxzip/sfx.rc new file mode 100644 index 0000000000..82bdf07561 --- /dev/null +++ b/utils/Install/sfxzip/sfx.rc @@ -0,0 +1,2 @@ +#include "wx/msw/wx.rc" + diff --git a/utils/Install/sfxzip/ttyio.c b/utils/Install/sfxzip/ttyio.c new file mode 100644 index 0000000000..c755d1c5a3 --- /dev/null +++ b/utils/Install/sfxzip/ttyio.c @@ -0,0 +1,625 @@ +/*--------------------------------------------------------------------------- + + ttyio.c + + This file contains routines for doing console input/output, including code + for non-echoing input. It is used by the encryption/decryption code but + does not contain any restricted code itself. This file is shared between + Info-ZIP's Zip and UnZip. + + Contains: echo() (VMS only) + Echon() (Unix only) + Echoff() (Unix only) + screenlines() (Unix only) + zgetch() (Unix and non-Unix versions) + getp() ("PC," Unix/Atari/Be, VMS/VMCMS/MVS) + + ---------------------------------------------------------------------------*/ + +#define __TTYIO_C /* identifies this source module */ + +#include "zip.h" +#include "crypt.h" + +#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP))) +/* Non-echo console/keyboard input is needed for (en/de)cryption's password + * entry, and for UnZip(SFX)'s MORE and Pause features. + * (The corresponding #endif is found at the end of this module.) + */ + +#include "ttyio.h" + +#ifndef PUTC +# define PUTC putc +#endif + +#ifdef ZIP +# ifdef GLOBAL /* used in Amiga system headers, maybe others too */ +# undef GLOBAL +# endif +# define GLOBAL(g) g +#else +# define GLOBAL(g) G.g +#endif + +#ifdef __BEOS__ /* why yes, we do */ +# define HAVE_TERMIOS_H +#endif + +#ifdef _POSIX_VERSION +# ifndef USE_POSIX_TERMIOS +# define USE_POSIX_TERMIOS /* use POSIX style termio (termios) */ +# endif +# ifndef HAVE_TERMIOS_H +# define HAVE_TERMIOS_H /* POSIX termios.h */ +# endif +#endif /* _POSIX_VERSION */ + +#ifdef UNZIP /* Zip handles this with the unix/configure script */ +# ifndef _POSIX_VERSION +# if (defined(SYSV) || defined(CRAY)) && !defined(__MINT__) +# ifndef USE_SYSV_TERMIO +# define USE_SYSV_TERMIO +# endif +# ifdef COHERENT +# ifndef HAVE_TERMIO_H +# define HAVE_TERMIO_H +# endif +# ifdef HAVE_SYS_TERMIO_H +# undef HAVE_SYS_TERMIO_H +# endif +# else /* !COHERENT */ +# ifdef HAVE_TERMIO_H +# undef HAVE_TERMIO_H +# endif +# ifndef HAVE_SYS_TERMIO_H +# define HAVE_SYS_TERMIO_H +# endif +# endif /* ?COHERENT */ +# endif /* (SYSV || CRAY) && !__MINT__ */ +# endif /* !_POSIX_VERSION */ +# if !(defined(BSD4_4) || defined(SYSV) || defined(__convexc__)) +# ifndef NO_FCNTL_H +# define NO_FCNTL_H +# endif +# endif /* !(BSD4_4 || SYSV || __convexc__) */ +#endif /* UNZIP */ + +#ifdef HAVE_TERMIOS_H +# ifndef USE_POSIX_TERMIOS +# define USE_POSIX_TERMIOS +# endif +#endif + +#if (defined(HAVE_TERMIO_H) || defined(HAVE_SYS_TERMIO_H)) +# ifndef USE_SYSV_TERMIO +# define USE_SYSV_TERMIO +# endif +#endif + +#if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE)) +# include +# define GOT_IOCTL_H + /* int ioctl OF((int, int, zvoid *)); GRR: may need for some systems */ +#endif + +#ifndef HAVE_WORKING_GETCH + /* include system support for switching of console echo */ +# ifdef VMS +# include +# include +# include +# include +# include +# else /* !VMS */ +# ifdef HAVE_TERMIOS_H +# include +# define sgttyb termios +# define sg_flags c_lflag +# define GTTY(f, s) tcgetattr(f, (zvoid *) s) +# define STTY(f, s) tcsetattr(f, TCSAFLUSH, (zvoid *) s) +# else /* !HAVE_TERMIOS_H */ +# ifdef USE_SYSV_TERMIO /* Amdahl, Cray, all SysV? */ +# ifdef HAVE_TERMIO_H +# include +# endif +# ifdef HAVE_SYS_TERMIO_H +# include +# endif +# ifdef NEED_PTEM +# include +# include +# endif +# define sgttyb termio +# define sg_flags c_lflag +# define GTTY(f,s) ioctl(f,TCGETA,(zvoid *)s) +# define STTY(f,s) ioctl(f,TCSETAW,(zvoid *)s) +# else /* !USE_SYSV_TERMIO */ +# ifndef CMS_MVS +# if (!defined(MINIX) && !defined(GOT_IOCTL_H)) +# include +# endif +# include +# define GTTY gtty +# define STTY stty +# ifdef UNZIP + /* + * XXX : Are these declarations needed at all ???? + */ + /* + * GRR: let's find out... Hmmm, appears not... + int gtty OF((int, struct sgttyb *)); + int stty OF((int, struct sgttyb *)); + */ +# endif +# endif /* !CMS_MVS */ +# endif /* ?USE_SYSV_TERMIO */ +# endif /* ?HAVE_TERMIOS_H */ +# ifndef NO_FCNTL_H +# ifndef UNZIP +# include +# endif +# else + char *ttyname OF((int)); +# endif +# endif /* ?VMS */ +#endif /* !HAVE_WORKING_GETCH */ + + + +#ifndef HAVE_WORKING_GETCH +#ifdef VMS + +/* + * Turn keyboard echoing on or off (VMS). Loosely based on VMSmunch.c + * and hence on Joe Meadows' file.c code. + */ +int echo(opt) + int opt; +{ + /* + * For VMS v5.x: + * IO$_SENSEMODE/SETMODE info: Programming, Vol. 7A, System Programming, + * I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6 + * sys$assign(), sys$qio() info: Programming, Vol. 4B, System Services, + * System Services Reference Manual, pp. sys-23, sys-379 + * fixed-length descriptor info: Programming, Vol. 3, System Services, + * Intro to System Routines, sec. 2.9.2 + * Greg Roelofs, 15 Aug 91 + */ + + /* SKM: make global? */ + static struct dsc$descriptor_s DevDesc = + {11, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$COMMAND"}; + /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */ + static short DevChan, iosb[4]; + static long status; + static unsigned long oldmode[2], newmode[2]; /* each = 8 bytes */ + + + /* assign a channel to standard input */ + status = sys$assign(&DevDesc, &DevChan, 0, 0); + if (!(status & 1)) + return status; + + /* use sys$qio and the IO$_SENSEMODE function to determine the current + * tty status (for password reading, could use IO$_READVBLK function + * instead, but echo on/off will be more general) + */ + status = sys$qiow(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0, + oldmode, 8, 0, 0, 0, 0); + if (!(status & 1)) + return status; + status = iosb[0]; + if (!(status & 1)) + return status; + + /* copy old mode into new-mode buffer, then modify to be either NOECHO or + * ECHO (depending on function argument opt) + */ + newmode[0] = oldmode[0]; + newmode[1] = oldmode[1]; + if (opt == 0) /* off */ + newmode[1] |= TT$M_NOECHO; /* set NOECHO bit */ + else + newmode[1] &= ~((unsigned long) TT$M_NOECHO); /* clear NOECHO bit */ + + /* use the IO$_SETMODE function to change the tty status */ + status = sys$qiow(0, DevChan, IO$_SETMODE, &iosb, 0, 0, + newmode, 8, 0, 0, 0, 0); + if (!(status & 1)) + return status; + status = iosb[0]; + if (!(status & 1)) + return status; + + /* deassign the sys$input channel by way of clean-up */ + status = sys$dassgn(DevChan); + if (!(status & 1)) + return status; + + return SS$_NORMAL; /* we be happy */ + +} /* end function echo() */ + + +#else /* !VMS: basically Unix */ + + +/* For VM/CMS and MVS, non-echo terminal input is not (yet?) supported. */ +#ifndef CMS_MVS + +#ifdef ZIP /* moved to globals.h for UnZip */ + static int echofd=(-1); /* file descriptor whose echo is off */ +#endif + +/* + * Turn echo off for file descriptor f. Assumes that f is a tty device. + */ +void Echoff(__G__ f) + __GDEF + int f; /* file descriptor for which to turn echo off */ +{ + struct sgttyb sg; /* tty device structure */ + + GLOBAL(echofd) = f; + GTTY(f, &sg); /* get settings */ + sg.sg_flags &= ~ECHO; /* turn echo off */ + STTY(f, &sg); +} + +/* + * Turn echo back on for file descriptor echofd. + */ +void Echon(__G) + __GDEF +{ + struct sgttyb sg; /* tty device structure */ + + if (GLOBAL(echofd) != -1) { + GTTY(GLOBAL(echofd), &sg); /* get settings */ + sg.sg_flags |= ECHO; /* turn echo on */ + STTY(GLOBAL(echofd), &sg); + GLOBAL(echofd) = -1; + } +} + +#endif /* !CMS_MVS */ +#endif /* ?VMS */ + + +#if (defined(UNZIP) && !defined(FUNZIP)) + +#if (defined(UNIX) || defined(__BEOS__)) +#ifdef MORE + +/* + * Get the number of lines on the output terminal. SCO Unix apparently + * defines TIOCGWINSZ but doesn't support it (!M_UNIX). + * + * GRR: will need to know width of terminal someday, too, to account for + * line-wrapping. + */ + +#if (defined(TIOCGWINSZ) && !defined(M_UNIX)) + +int screenlines() +{ + struct winsize wsz; +#ifdef DEBUG_WINSZ + static int firsttime = TRUE; +#endif + + /* see termio(4) under, e.g., SunOS */ + if (ioctl(1, TIOCGWINSZ, &wsz) == 0) { +#ifdef DEBUG_WINSZ + if (firsttime) { + firsttime = FALSE; + fprintf(stderr, "ttyio.c screenlines(): ws_row = %d\n", + wsz.ws_row); + } +#endif + /* number of columns = ws_col */ + return (wsz.ws_row > 0)? wsz.ws_row : 24; /* number of rows */ + + } else { /* this happens when piping to more(1), for example */ +#ifdef DEBUG_WINSZ + if (firsttime) { + firsttime = FALSE; + fprintf(stderr, + "ttyio.c screenlines(): ioctl(TIOCGWINSZ) failed\n")); + } +#endif + return 24; /* VT-100 assumed to be minimal hardware */ + } +} + +#else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */ + +int screenlines() +{ + char *envptr, *getenv(); + int n; + + /* GRR: this is overly simplistic, but don't have access to stty/gtty + * system anymore + */ + envptr = getenv("LINES"); + if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) + return 24; /* VT-100 assumed to be minimal hardware */ + else + return n; +} + +#endif /* ?(TIOCGWINSZ && !M_UNIX) */ +#endif /* MORE */ + + +/* + * Get a character from the given file descriptor without echo or newline. + */ +int zgetch(__G__ f) + __GDEF + int f; /* file descriptor from which to read */ +{ +#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS)) + char oldmin, oldtim; +#endif + char c; + struct sgttyb sg; /* tty device structure */ + + GTTY(f, &sg); /* get settings */ +#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS)) + oldmin = sg.c_cc[VMIN]; /* save old values */ + oldtim = sg.c_cc[VTIME]; + sg.c_cc[VMIN] = 1; /* need only one char to return read() */ + sg.c_cc[VTIME] = 0; /* no timeout */ + sg.sg_flags &= ~ICANON; /* canonical mode off */ +#else + sg.sg_flags |= CBREAK; /* cbreak mode on */ +#endif + sg.sg_flags &= ~ECHO; /* turn echo off, too */ + STTY(f, &sg); /* set cbreak mode */ + GLOBAL(echofd) = f; /* in case ^C hit (not perfect: still CBREAK) */ + + read(f, &c, 1); /* read our character */ + +#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS)) + sg.c_cc[VMIN] = oldmin; /* restore old values */ + sg.c_cc[VTIME] = oldtim; + sg.sg_flags |= ICANON; /* canonical mode on */ +#else + sg.sg_flags &= ~CBREAK; /* cbreak mode off */ +#endif + sg.sg_flags |= ECHO; /* turn echo on */ + STTY(f, &sg); /* restore canonical mode */ + GLOBAL(echofd) = -1; + + return (int)c; +} + + +#else /* !UNIX && !__BEOS__ */ + + +int zgetch(__G__ f) + __GDEF + int f; /* file descriptor from which to read (must be open already) */ +{ + char c, c2; + +/*--------------------------------------------------------------------------- + Get a character from the given file descriptor without echo; can't fake + CBREAK mode (i.e., newline required), but can get rid of all chars up to + and including newline. + ---------------------------------------------------------------------------*/ + + echoff(f); + read(f, &c, 1); + if (c != '\n') + do { + read(f, &c2, 1); /* throw away all other chars up thru newline */ + } while (c2 != '\n'); + echon(); + return (int)c; +} + +#endif /* ?(UNIX || __BEOS__) */ + +#endif /* UNZIP && !FUNZIP */ +#endif /* !HAVE_WORKING_GETCH */ + + +#if CRYPT /* getp() is only used with full encryption */ + +/* + * Simple compile-time check for source compatibility between + * zcrypt and ttyio: + */ +#if (!defined(CR_MAJORVER) || (CR_MAJORVER < 2) || (CR_MINORVER < 7)) + error: This Info-ZIP tool requires zcrypt 2.7 or later. +#endif + +/* + * Get a password of length n-1 or less into *p using the prompt *m. + * The entered password is not echoed. + */ + +#ifdef HAVE_WORKING_GETCH +/* + * For the AMIGA, getch() is defined as Agetch(), which is in + * amiga/filedate.c; SAS/C 6.x provides a getch(), but since Agetch() + * uses the infrastructure that is already in place in filedate.c, it is + * smaller. With this function, echoff() and echon() are not needed. + * + * For the MAC, a non-echo macgetch() function is defined in the MacOS + * specific sources which uses the event handling mechanism of the + * desktop window manager to get a character from the keyboard. + * + * For the other systems in this section, a non-echo getch() function + * is either contained the C runtime library (conio package), or getch() + * is defined as an alias for a similar system specific RTL function. + */ + +#ifndef WINDLL /* WINDLL does not support a console interface */ +#ifndef QDOS /* QDOS supplies a variant of this function */ + +/* This is the getp() function for all systems (with TTY type user interface) + * that supply a working `non-echo' getch() function for "raw" console input. + */ +char *getp(__G__ m, p, n) + __GDEF + ZCONST char *m; /* prompt for password */ + char *p; /* return value: line input */ + int n; /* bytes available in p[] */ +{ + char c; /* one-byte buffer for read() to use */ + int i; /* number of characters input */ + char *w; /* warning on retry */ + + /* get password */ + w = ""; + do { + fputs(w, stderr); /* warning if back again */ + fputs(m, stderr); /* display prompt and flush */ + fflush(stderr); + i = 0; + do { /* read line, keeping first n characters */ + if ((c = (char)getch()) == '\r') + c = '\n'; /* until user hits CR */ + if (c == 8 || c == 127) { + if (i > 0) i--; /* the `backspace' and `del' keys works */ + } + else if (i < n) + p[i++] = c; /* truncate past n */ + } while (c != '\n'); + PUTC('\n', stderr); fflush(stderr); + w = "(line too long--try again)\n"; + } while (p[i-1] != '\n'); + p[i-1] = 0; /* terminate at newline */ + + return p; /* return pointer to password */ + +} /* end function getp() */ + +#endif /* !QDOS */ +#endif /* !WINDLL */ + + +#else /* !HAVE_WORKING_GETCH */ + + +#if (defined(UNIX) || defined(__MINT__) || defined(__BEOS__)) + +#ifndef _PATH_TTY +# ifdef __MINT__ +# define _PATH_TTY ttyname(2) +# else +# define _PATH_TTY "/dev/tty" +# endif +#endif + +char *getp(__G__ m, p, n) + __GDEF + ZCONST char *m; /* prompt for password */ + char *p; /* return value: line input */ + int n; /* bytes available in p[] */ +{ + char c; /* one-byte buffer for read() to use */ + int i; /* number of characters input */ + char *w; /* warning on retry */ + int f; /* file descriptor for tty device */ + +#ifdef PASSWD_FROM_STDIN + /* Read from stdin. This is unsafe if the password is stored on disk. */ + f = 0; +#else + /* turn off echo on tty */ + + if ((f = open(_PATH_TTY, 0)) == -1) + return NULL; +#endif + /* get password */ + w = ""; + do { + fputs(w, stderr); /* warning if back again */ + fputs(m, stderr); /* prompt */ + fflush(stderr); + i = 0; + echoff(f); + do { /* read line, keeping n */ + read(f, &c, 1); + if (i < n) + p[i++] = c; + } while (c != '\n'); + echon(); + PUTC('\n', stderr); fflush(stderr); + w = "(line too long--try again)\n"; + } while (p[i-1] != '\n'); + p[i-1] = 0; /* terminate at newline */ + +#ifndef PASSWD_FROM_STDIN + close(f); +#endif + + return p; /* return pointer to password */ + +} /* end function getp() */ + +#endif /* UNIX || __MINT__ || __BEOS__ */ + + + +#if (defined(VMS) || defined(CMS_MVS)) + +char *getp(__G__ m, p, n) + __GDEF + ZCONST char *m; /* prompt for password */ + char *p; /* return value: line input */ + int n; /* bytes available in p[] */ +{ + char c; /* one-byte buffer for read() to use */ + int i; /* number of characters input */ + char *w; /* warning on retry */ + FILE *f; /* file structure for SYS$COMMAND device */ + +#ifdef PASSWD_FROM_STDIN + f = stdin; +#else + if ((f = fopen(ctermid(NULL), "r")) == NULL) + return NULL; +#endif + + /* get password */ + fflush(stdout); + w = ""; + do { + if (*w) /* bug: VMS apparently adds \n to NULL fputs */ + fputs(w, stderr); /* warning if back again */ + fputs(m, stderr); /* prompt */ + fflush(stderr); + i = 0; + echoff(f); + do { /* read line, keeping n */ + if ((c = (char)getc(f)) == '\r') + c = '\n'; + if (i < n) + p[i++] = c; + } while (c != '\n'); + echon(); + PUTC('\n', stderr); fflush(stderr); + w = "(line too long--try again)\n"; + } while (p[i-1] != '\n'); + p[i-1] = 0; /* terminate at newline */ +#ifndef PASSWD_FROM_STDIN + fclose(f); +#endif + + return p; /* return pointer to password */ + +} /* end function getp() */ + +#endif /* VMS || CMS_MVS */ +#endif /* ?HAVE_WORKING_GETCH */ +#endif /* CRYPT */ +#endif /* CRYPT || (UNZIP && !FUNZIP) */ diff --git a/utils/Install/sfxzip/unix.c b/utils/Install/sfxzip/unix.c new file mode 100644 index 0000000000..c9eaaabafc --- /dev/null +++ b/utils/Install/sfxzip/unix.c @@ -0,0 +1,1424 @@ +/*--------------------------------------------------------------------------- + + unix.c + + Unix-specific routines for use with Info-ZIP's UnZip 5.3 and later. + + Contains: readdir() + do_wild() <-- generic enough to put in fileio.c? + mapattr() + mapname() + checkdir() + mkdir() + close_outfile() + set_direc_attribs() + stamp_file() + version() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" + +#ifdef SCO_XENIX +# define SYSNDIR +#else /* SCO Unix, AIX, DNIX, TI SysV, Coherent 4.x, ... */ +# if defined(__convexc__) || defined(SYSV) || defined(CRAY) || defined(BSD4_4) +# define DIRENT +# endif +#endif +#if defined(_AIX) +# define DIRENT +#endif +#ifdef COHERENT +# if defined(_I386) || (defined(__COHERENT__) && (__COHERENT__ >= 0x420)) +# define DIRENT +# endif +#endif + +/* GRR: may need to uncomment this: */ +#if 0 +#if defined(_POSIX_VERSION) +# define DIRENT +#endif +#endif + +#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 */ + +#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; + +static int isRISCOSexfield OF((uch *extra_field)); +#endif /* ACORN_FTYPE_NFS */ + +static int created_dir; /* used in mapname(), checkdir() */ +static int renamed_fullpath; /* ditto */ + + +#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 + char *wildspec; /* only used first time on a given dir */ +{ + static DIR *dir = (DIR *)NULL; + static char *dirname, *wildname, matchname[FILNAMSIZ]; + static int firstcall=TRUE, 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 (firstcall) { /* first call: must initialize everything */ + firstcall = FALSE; + + if (!iswild(wildspec)) { + strcpy(matchname, wildspec); + have_dirname = FALSE; + dir = NULL; + return matchname; + } + + /* break the wildspec into a directory part and a wildcard filename */ + if ((wildname = strrchr(wildspec, '/')) == (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")); + 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; + } + + if ((dir = opendir(dirname)) != (DIR *)NULL) { + while ((file = readdir(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 */ + if (match(file->d_name, wildname, 0) && /* 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(dir); + 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) */ + strcpy(matchname, wildspec); + return matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (dir == (DIR *)NULL) { + firstcall = TRUE; /* 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(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 */ + if (match(file->d_name, wildname, 0)) { /* 0 == don't ignore case */ + 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(dir); /* have read at least one dir entry; nothing left */ + dir = (DIR *)NULL; + firstcall = TRUE; /* 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; + + 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 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: + /* 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() */ +/************************/ + /* return 0 if no error, 1 if caution (filename */ +int mapname(__G__ renamed) /* truncated), 2 if warning (skip file because */ + __GDEF /* dir doesn't exist), 3 if error (skip file), */ + int renamed; /* or 10 if out of memory (skip file) */ +{ /* [also IZ_VOL_LABEL, IZ_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 */ +#endif + int quote = FALSE; /* flags */ + int error = 0; + register unsigned workch; /* hold the character being tested */ + + +/*--------------------------------------------------------------------------- + Initialize various pointers and counters and stuff. + ---------------------------------------------------------------------------*/ + + if (G.pInfo->vollabel) + return IZ_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) == 10) + return 10; /* 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 (quote) { /* if character quoted, */ + *pp++ = (char)workch; /* include it literally */ + quote = FALSE; + } else + switch (workch) { + case '/': /* can assume -j flag not given */ + *pp = '\0'; + if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = (char *)NULL; /* leave directory 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 + + case '\026': /* control-V quote for special chars */ + quote = TRUE; /* set flag for next character */ + break; + +#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 */ + + *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 && isRISCOSexfield(G.extra_field)) { + /* file *must* have a RISC OS extra field */ + int ft = (int)makelong(((RO_extra_block *)G.extra_field)->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", ft>>8 & 0xFFF); + } +#endif /* ACORN_FTYPE_NFS */ + +/*--------------------------------------------------------------------------- + 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", + G.filename)); + } +#ifndef NO_CHMOD + /* 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 + return IZ_CREATED_DIR; /* set dir time (note trailing '/') */ + } + return 2; /* dir existed already; don't look for data to extract */ + } + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", + G.filename)); + return 3; + } + + 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: 1 - (on APPEND_NAME) truncated filename + * 2 - path doesn't exist, not allowed to create + * 3 - path doesn't exist, tried to create and failed; or + * path exists and is not a directory, but is supposed to be + * 4 - path is too long + * 10 - 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", 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); + return 2; /* path doesn't exist: nothing to do */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", buildpath)); + free(buildpath); + return 4; /* no room for filenames: fatal */ + } + if (mkdir(buildpath, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, + "checkdir error: cannot create %s\n\ + unable to process %s.\n", buildpath, G.filename)); + free(buildpath); + return 3; /* path didn't exist, tried to create, failed */ + } + 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", buildpath, G.filename)); + free(buildpath); + return 3; /* path existed but wasn't dir */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", buildpath)); + free(buildpath); + return 4; /* no room for filenames: fatal */ + } + *end++ = '/'; + *end = '\0'; + Trace((stderr, "buildpath now = [%s]\n", buildpath)); + return 0; + + } /* 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", pathcomp)); + free(buildpath); + buildpath = end = (char *)NULL; + return 0; + } + +/*--------------------------------------------------------------------------- + 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", 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", G.filename, buildpath)); + return 1; /* filename truncated */ + } + } + Trace((stderr, "buildpath now = [%s]\n", buildpath)); + return 0; /* could check for existence here, prompt for new 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. + ---------------------------------------------------------------------------*/ + +/* 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 10; + if ((rootlen > 0) && !renamed_fullpath) { + strcpy(buildpath, rootpath); + end = buildpath + rootlen; + } else { + *buildpath = '\0'; + end = buildpath; + } + Trace((stderr, "[%s]\n", buildpath)); + return 0; + } + +/*--------------------------------------------------------------------------- + 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", pathcomp)); + if (pathcomp == (char *)NULL) { + rootlen = 0; + return 0; + } + 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; + return 2; /* skip (or treat as stored file) */ + } + /* create the directory (could add loop here to scan pathcomp + * and 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", + pathcomp)); + rootlen = 0; /* path didn't exist, tried to create, and */ + return 3; /* failed: file exists, or 2+ levels required */ + } + } + if ((rootpath = (char *)malloc(rootlen+2)) == (char *)NULL) { + rootlen = 0; + return 10; + } + strcpy(rootpath, pathcomp); + rootpath[rootlen++] = '/'; + rootpath[rootlen] = '\0'; + Trace((stderr, "rootpath now = [%s]\n", rootpath)); + } + return 0; + } +#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 0; + } + + return 99; /* should never reach */ + +} /* end function checkdir() */ + + + + + +#ifdef NO_MKDIR + +/********************/ +/* Function mkdir() */ +/********************/ + +int mkdir(path, mode) + char *path; + int mode; /* ignored */ +/* + * returns: 0 - successful + * -1 - failed (errno not set, however) + */ +{ + char command[FILNAMSIZ+40]; /* buffer for system() call */ + + /* GRR 930416: added single quotes around path to avoid bug with + * creating directories with ampersands in name; not yet tested */ + sprintf(command, "IFS=\" \t\n\" /bin/mkdir '%s' 2>/dev/null", path); + if (system(command)) + return -1; + return 0; +} + +#endif /* NO_MKDIR */ + + + + + +#if 0 +#ifdef MORE + +/**************************/ +/* Function screenlines() */ +/**************************/ + +int screenlines() +{ + char *envptr, *getenv(); + int n; + + /* GRR: this is overly simplistic; should use winsize struct and + * appropriate TIOCGWINSZ ioctl(), assuming exists on enough systems + */ + envptr = getenv("LINES"); + if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) + return 24; /* VT-100 assumed to be minimal hardware */ + else + return n; +} + +#endif /* MORE */ +#endif /* 0 */ + + + + + +#ifndef MTS + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) /* GRR: change to return PK-style warning level */ + __GDEF +{ + iztimes zt; + ush z_uidgid[2]; + unsigned eb_izux_flg; + +/*--------------------------------------------------------------------------- + If symbolic links are supported, allocate a storage area, put the uncom- + pressed "data" in it, and create the link. 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) { + unsigned ucsize = (unsigned)G.lrec.ucsize; + char *linktarget = (char *)malloc((unsigned)G.lrec.ucsize+1); + + fclose(G.outfile); /* close "data" file... */ + G.outfile = fopen(G.filename, FOPR); /* ...and reopen for reading */ + if (!linktarget || fread(linktarget, 1, ucsize, G.outfile) != + (int)ucsize) + { + Info(slide, 0x201, ((char *)slide, + "warning: symbolic link (%s) failed\n", G.filename)); + if (linktarget) + free(linktarget); + fclose(G.outfile); + return; + } + fclose(G.outfile); /* close "data" file for good... */ + unlink(G.filename); /* ...and delete it */ + linktarget[ucsize] = '\0'; + if (QCOND2) + Info(slide, 0, ((char *)slide, "-> %s ", linktarget)); + if (symlink(linktarget, G.filename)) /* create the real link */ + perror("symlink error"); + free(linktarget); + return; /* can't set time on symlinks */ + } +#endif /* SYMLINKS */ + + fclose(G.outfile); +#ifdef QLZIP + if (G.extra_field) { + static void qlfix OF((__GPRO__ uch *ef_ptr, unsigned ef_len)); + + qlfix(__G__ G.extra_field, G.lrec.extra_field_length); + } +#endif + +/*--------------------------------------------------------------------------- + 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. + ---------------------------------------------------------------------------*/ + + 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 ? &zt : NULL), +#else + &zt, +#endif + z_uidgid) : 0); + if (eb_izux_flg & EB_UT_FL_MTIME) { + TTrace((stderr, "\nclose_outfile: Unix e.f. modif. time = %ld\n", + zt.mtime)); + } else { + zt.mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); + } + if (eb_izux_flg & EB_UT_FL_ATIME) { + TTrace((stderr, "close_outfile: Unix e.f. access time = %ld\n", + zt.atime)); + } else { + zt.atime = zt.mtime; + TTrace((stderr, "\nclose_outfile: modification/access times = %ld\n", + zt.mtime)); + } + + /* if -X option was specified and we have UID/GID info, restore it */ + if (uO.X_flag && eb_izux_flg & EB_UX2_VALID) { + 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 %d and/or GID %d for %s\n", + z_uidgid[0], z_uidgid[1], G.filename)); + else + Info(slide, 0x201, ((char *)slide, + " (warning) cannot set UID %d and/or GID %d", + z_uidgid[0], z_uidgid[1])); + } + } + + /* set the file's access and modification times */ + if (utime(G.filename, (ztimbuf *)&zt)) { +#ifdef AOS_VS + if (uO.qflag) + Info(slide, 0x201, ((char *)slide, "... cannot set time for %s\n", + G.filename)); + else + Info(slide, 0x201, ((char *)slide, "... cannot set time")); +#else + if (uO.qflag) + Info(slide, 0x201, ((char *)slide, + "warning: cannot set times for %s\n", G.filename)); + else + Info(slide, 0x201, ((char *)slide, + " (warning) cannot set times")); +#endif /* ?AOS_VS */ + } + +/*--------------------------------------------------------------------------- + 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() */ + +#endif /* !MTS */ + + + + +#ifdef SET_DIR_ATTRIB +/* messages of code for setting directory attributes */ +static char Far DirlistUidGidFailed[] = + "warning: cannot set UID %d and/or GID %d for %s\n"; +static char Far DirlistUtimeFailed[] = + "warning: cannot set modification, access times for %s\n"; +# ifndef NO_CHMOD + static char Far DirlistChmodFailed[] = + "warning: cannot set permissions for %s\n"; +# endif + + +int set_direc_attribs(__G__ d) + __GDEF + dirtime *d; +{ + int errval = PK_OK; + + if (d->have_uidgid && + chown(d->fn, (uid_t)d->uidgid[0], (gid_t)d->uidgid[1])) + { + Info(slide, 0x201, ((char *)slide, + LoadFarString(DirlistUidGidFailed), + d->uidgid[0], d->uidgid[1], d->fn)); + if (!errval) + errval = PK_WARN; + } + if (utime(d->fn, &d->u.t2)) { + Info(slide, 0x201, ((char *)slide, + LoadFarString(DirlistUtimeFailed), d->fn)); + if (!errval) + errval = PK_WARN; + } +#ifndef NO_CHMOD + if (chmod(d->fn, 0xffff & d->perms)) { + Info(slide, 0x201, ((char *)slide, + LoadFarString(DirlistChmodFailed), d->fn)); + /* perror("chmod (file attributes) error"); */ + if (!errval) + errval = PK_WARN; + } +#endif /* !NO_CHMOD */ + return errval; +} /* end function set_directory_attributes() */ + +#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 +{ +#if defined(CRAY) || defined(NX_CURRENT_COMPILER_RELEASE) || defined(NetBSD) + char buf1[40]; +#if defined(CRAY) || defined(NX_CURRENT_COMPILER_RELEASE) + char buf2[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(buf1, "NeXT DevKit %d.%02d ", NX_CURRENT_COMPILER_RELEASE/100, + NX_CURRENT_COMPILER_RELEASE%100), buf1), + (strlen(__VERSION__) > 8)? "(gcc)" : + (sprintf(buf2, "(gcc %s)", __VERSION__), buf2), +# else + "gcc ", __VERSION__, +# endif +#else +# if defined(CRAY) && defined(_RELEASE) + "cc ", (sprintf(buf1, "version %d", _RELEASE), buf1), +# else +# ifdef __VERSION__ + "cc ", __VERSION__, +# else + "cc", "", +# endif +# endif +#endif + + "Unix", + +#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(buf2, " (Cray UNICOS release %d)", _UNICOS), buf2), +# 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(buf1, " (NetBSD 0.8%c)", (char)(NetBSD0_8 - 1 + 'A')), buf1), +# else +# ifdef NetBSD0_9 + (sprintf(buf1, " (NetBSD 0.9%c)", (char)(NetBSD0_9 - 1 + 'A')), buf1), +# else +# ifdef NetBSD1_0 + (sprintf(buf1, " (NetBSD 1.0%c)", (char)(NetBSD1_0 - 1 + 'A')), buf1), +# 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 +#ifdef __QNX__ + " (QNX 4)", +#else +#ifdef __QNXNTO__ + " (QNX Neutrino)", +#else +#ifdef Lynx + " (LynxOS)", +#else + "", +#endif /* Lynx */ +#endif /* QNX Neutrino */ +#endif /* QNX 4 */ +#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 */ + + + + +#ifdef QLZIP + +struct qdirect { + long d_length __attribute__ ((packed)); /* file length */ + unsigned char d_access __attribute__ ((packed)); /* file access type */ + unsigned char d_type __attribute__ ((packed)); /* file type */ + long d_datalen __attribute__ ((packed)); /* data length */ + long d_reserved __attribute__ ((packed));/* Unused */ + short d_szname __attribute__ ((packed)); /* size of name */ + char d_name[36] __attribute__ ((packed));/* name area */ + long d_update __attribute__ ((packed)); /* last update */ + long d_refdate __attribute__ ((packed)); + long d_backup __attribute__ ((packed)); /* EOD */ +}; + +#define LONGID "QDOS02" +#define EXTRALEN (sizeof(struct qdirect) + 8) +#define JBLONGID "QZHD" +#define JBEXTRALEN (sizeof(jbextra) - 4 * sizeof(char)) + +typedef struct { + char eb_header[4] __attribute__ ((packed)); /* place_holder */ + char longid[8] __attribute__ ((packed)); + struct qdirect header __attribute__ ((packed)); +} qdosextra; + +typedef struct { + char eb_header[4]; /* place_holder */ + char longid[4]; + struct qdirect header; +} jbextra; + + + +/* The following two functions SH() and LG() convert big-endian short + * and long numbers into native byte order. They are some kind of + * counterpart to the generic UnZip's makeword() and makelong() functions. + */ +static ush SH(ush val) +{ + uch swapbuf[2]; + + swapbuf[1] = (uch)(val & 0xff); + swapbuf[0] = (uch)(val >> 8); + return (*(ush *)swapbuf); +} + + + +static ulg LG(ulg val) +{ + /* convert the big-endian unsigned long number `val' to the machine + * dependant representation + */ + ush swapbuf[2]; + + swapbuf[1] = SH((ush)(val & 0xffff)); + swapbuf[0] = SH((ush)(val >> 16)); + return (*(ulg *)swapbuf); +} + + + +static void qlfix(__G__ ef_ptr, ef_len) + __GDEF + uch *ef_ptr; + unsigned ef_len; +{ + while (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)) { + /* discovered some extra field inconsistency! */ + Trace((stderr, + "qlfix: block length %u > rest ef_size %u\n", eb_len, + ef_len - EB_HEADSIZE)); + break; + } + + switch (eb_id) { + case EF_QDOS: + { + struct _ntc_ + { + long id; + long dlen; + } ntc; + long dlen = 0; + + qdosextra *extra = (qdosextra *)ef_ptr; + jbextra *jbp = (jbextra *)ef_ptr; + + if (!strncmp(extra->longid, LONGID, strlen(LONGID))) + { + if (eb_len != EXTRALEN) + if (uO.qflag) + Info(slide, 0x201, ((char *)slide, + "warning: invalid length in Qdos field for %s\n", + G.filename)); + else + Info(slide, 0x201, ((char *)slide, + "warning: invalid length in Qdos field")); + + if (extra->header.d_type) + { + dlen = extra->header.d_datalen; + } + } + + if (!strncmp(jbp->longid, JBLONGID, strlen(JBLONGID))) + { + if (eb_len != JBEXTRALEN) + if (uO.qflag) + Info(slide, 0x201, ((char *)slide, + "warning: invalid length in QZ field for %s\n", + G.filename)); + else + Info(slide, 0x201, ((char *)slide, + "warning: invalid length in QZ field")); + if(jbp->header.d_type) + { + dlen = jbp->header.d_datalen; + } + } + + if ((long)LG(dlen) > 0) + { + G.outfile = fopen(G.filename,"r+"); + fseek(G.outfile, -8, SEEK_END); + fread(&ntc, 8, 1, G.outfile); + if(ntc.id != *(long *)"XTcc") + { + ntc.id = *(long *)"XTcc"; + ntc.dlen = dlen; + fwrite (&ntc, 8, 1, G.outfile); + } + Info(slide, 0x201, ((char *)slide, "QData = %d", LG(dlen))); + fclose(G.outfile); + } + return; /* finished, cancel further extra field scanning */ + } + + default: + Trace((stderr,"qlfix: unknown extra field block, ID=%d\n", + eb_id)); + } + + /* Skip this extra field block */ + ef_ptr += (eb_len + EB_HEADSIZE); + ef_len -= (eb_len + EB_HEADSIZE); + } +} +#endif /* QLZIP */ + + + + +#ifdef ACORN_FTYPE_NFS + +/* Acorn bits for NFS filetyping */ + +static int isRISCOSexfield(uch *extra_field) +{ + if (extra_field != NULL) { + RO_extra_block *block = (RO_extra_block *)extra_field; + return ( + makeword(block->ID) == EF_SPARK && + (makeword(block->size) == 24 || makeword(block->size) == 20) && + makelong(block->ID_2) == 0x30435241 /* ARC0 */); + } + return FALSE; +} +#endif /* ACORN_FTYPE_NFS */ diff --git a/utils/Install/sfxzip/unreduce.c b/utils/Install/sfxzip/unreduce.c new file mode 100644 index 0000000000..4cfb3fec6f --- /dev/null +++ b/utils/Install/sfxzip/unreduce.c @@ -0,0 +1,230 @@ +/*--------------------------------------------------------------------------- + + unreduce.c + + The Reducing algorithm is actually a combination of two distinct algorithms. + The first algorithm compresses repeated byte sequences, and the second al- + gorithm takes the compressed stream from the first algorithm and applies a + probabilistic compression method. + + * 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. + + See the accompanying file "COPYING" in UnZip source and binary distributions + for further information. This code is NOT used unless USE_SMITH_CODE is + explicitly defined (==> COPYRIGHT_CLEAN is not defined). + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" /* defines COPYRIGHT_CLEAN by default */ + + +#ifndef COPYRIGHT_CLEAN + +/**************************************/ +/* UnReduce Defines, Typedefs, etc. */ +/**************************************/ + +#define DLE 144 + +typedef uch f_array[64]; /* for followers[256][64] */ + + + +/******************************/ +/* UnReduce Local Functions */ +/******************************/ + +static void LoadFollowers OF((__GPRO__ f_array *followers, uch *Slen)); + + + +/*******************************/ +/* UnReduce Global Constants */ +/*******************************/ + +static ZCONST shrint L_table[] = +{0, 0x7f, 0x3f, 0x1f, 0x0f}; + +static ZCONST shrint D_shift[] = +{0, 0x07, 0x06, 0x05, 0x04}; +static ZCONST shrint D_mask[] = +{0, 0x01, 0x03, 0x07, 0x0f}; + +static ZCONST shrint B_table[] = +{8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8}; + + + + + +/*************************/ +/* Function unreduce() */ +/*************************/ + +void unreduce(__G) /* expand probabilistically reduced data */ + __GDEF +{ + register int lchar = 0; + shrint nchar; + shrint ExState = 0; + shrint V = 0; + shrint Len = 0; + long s = G.ucsize; /* number of bytes left to decompress */ + unsigned w = 0; /* position in output window slide[] */ + unsigned u = 1; /* true if slide[] unflushed */ + uch Slen[256]; + + f_array *followers = (f_array *)(slide + 0x4000); + int factor = G.lrec.compression_method - 1; + + LoadFollowers(__G__ followers, Slen); + + while (s > 0 /* && (!zipeof) */) { + if (Slen[lchar] == 0) + READBITS(8, nchar) /* ; */ + else { + READBITS(1, nchar) /* ; */ + if (nchar != 0) + READBITS(8, nchar) /* ; */ + else { + shrint follower; + int bitsneeded = B_table[Slen[lchar]]; + + READBITS(bitsneeded, follower) /* ; */ + nchar = followers[lchar][follower]; + } + } + /* expand the resulting byte */ + switch (ExState) { + + case 0: + if (nchar != DLE) { + s--; + slide[w++] = (uch)nchar; + if (w == 0x4000) { + flush(__G__ slide, (ulg)w, 0); + w = u = 0; + } + } + else + ExState = 1; + break; + + case 1: + if (nchar != 0) { + V = nchar; + Len = V & L_table[factor]; + if (Len == L_table[factor]) + ExState = 2; + else + ExState = 3; + } else { + s--; + slide[w++] = DLE; + if (w == 0x4000) + { + flush(__G__ slide, (ulg)w, 0); + w = u = 0; + } + ExState = 0; + } + break; + + case 2:{ + Len += nchar; + ExState = 3; + } + break; + + case 3:{ + register unsigned e; + register unsigned n = Len + 3; + register unsigned d = w - ((((V >> D_shift[factor]) & + D_mask[factor]) << 8) + nchar + 1); + + s -= n; + do { + n -= (e = (e = 0x4000 - ((d &= 0x3fff) > w ? d : w)) > n ? + n : e); + if (u && w <= d) + { + memzero(slide + w, e); + w += e; + d += e; + } + else + if (w - d < e) /* (assume unsigned comparison) */ + do { /* slow to avoid memcpy() overlap */ + slide[w++] = slide[d++]; + } while (--e); + else + { + memcpy(slide + w, slide + d, e); + w += e; + d += e; + } + if (w == 0x4000) + { + flush(__G__ slide, (ulg)w, 0); + w = u = 0; + } + } while (n); + + ExState = 0; + } + break; + } + + /* store character for next iteration */ + lchar = nchar; + } + + /* flush out slide */ + flush(__G__ slide, (ulg)w, 0); +} + + + + + +/******************************/ +/* Function LoadFollowers() */ +/******************************/ + +static void LoadFollowers(__G__ followers, Slen) + __GDEF + f_array *followers; + uch *Slen; +{ + register int x; + register int i; + + for (x = 255; x >= 0; x--) { + READBITS(6, Slen[x]) /* ; */ + for (i = 0; (uch)i < Slen[x]; i++) + READBITS(8, followers[x][i]) /* ; */ + } +} + +#endif /* !COPYRIGHT_CLEAN */ diff --git a/utils/Install/sfxzip/unshrink.c b/utils/Install/sfxzip/unshrink.c new file mode 100644 index 0000000000..287b4baf54 --- /dev/null +++ b/utils/Install/sfxzip/unshrink.c @@ -0,0 +1,301 @@ +/*--------------------------------------------------------------------------- + + unshrink.c version 1.21 23 Nov 95 + + + NOTE: This code may or may not infringe on the so-called "Welch + patent" owned by Unisys. (From reading the patent, it appears + that a pure LZW decompressor is *not* covered, but this claim has + not been tested in court, and Unisys is reported to believe other- + wise.) It is therefore the responsibility of the user to acquire + whatever license(s) may be required for legal use of this code. + + THE INFO-ZIP GROUP DISCLAIMS ALL LIABILITY FOR USE OF THIS CODE + IN VIOLATION OF APPLICABLE PATENT LAW. + + + Shrinking is basically a dynamic LZW algorithm with allowed code sizes of + up to 13 bits; in addition, there is provision for partial clearing of + leaf nodes. PKWARE uses the special code 256 (decimal) to indicate a + change in code size or a partial clear of the code tree: 256,1 for the + former and 256,2 for the latter. [Note that partial clearing can "orphan" + nodes: the parent-to-be can be cleared before its new child is added, + but the child is added anyway (as an orphan, as though the parent still + existed). When the tree fills up to the point where the parent node is + reused, the orphan is effectively "adopted." Versions prior to 1.05 were + affected more due to greater use of pointers (to children and siblings + as well as parents).] + + This replacement version of unshrink.c was written from scratch. It is + based only on the algorithms described in Mark Nelson's _The Data Compres- + sion Book_ and in Terry Welch's original paper in the June 1984 issue of + IEEE _Computer_; no existing source code, including any in Nelson's book, + was used. + + Memory requirements have been reduced in this version and are now no more + than the original Sam Smith code. This is still larger than any of the + other algorithms: at a minimum, 8K+8K+16K (stack+values+parents) assuming + 16-bit short ints, and this does not even include the output buffer (the + other algorithms leave the uncompressed data in the work area, typically + called slide[]). For machines with a 64KB data space this is a problem, + particularly when text conversion is required and line endings have more + than one character. UnZip's solution is to use two roughly equal halves + of outbuf for the ASCII conversion in such a case; the "unshrink" argument + to flush() signals that this is the case. + + For large-memory machines, a second outbuf is allocated for translations, + but only if unshrinking and only if translations are required. + + | binary mode | text mode + --------------------------------------------------- + big mem | big outbuf | big outbuf + big outbuf2 <- malloc'd here + small mem | small outbuf | half + half small outbuf + + Copyright 1994, 1995 Greg Roelofs. See the accompanying file "COPYING" + in UnZip 5.20 (or later) source or binary distributions. + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" /* defines LZW_CLEAN by default */ + + +#ifndef LZW_CLEAN + +static void partial_clear OF((__GPRO)); + +#ifdef DEBUG +# define OUTDBG(c) \ + if ((c)<32 || (c)>=127) pipeit("\\x%02x",(c)); else { } +#else +# define OUTDBG(c) +#endif + +/* HSIZE is defined as 2^13 (8192) in unzip.h */ +#define BOGUSCODE 256 +#define FLAG_BITS parent /* upper bits of parent[] used as flag bits */ +#define CODE_MASK (HSIZE - 1) /* 0x1fff (lower bits are parent's index) */ +#define FREE_CODE HSIZE /* 0x2000 (code is unused or was cleared) */ +#define HAS_CHILD (HSIZE << 1) /* 0x4000 (code has a child--do not clear) */ + +#define parent G.area.shrink.Parent +#define Value G.area.shrink.value /* "value" conflicts with Pyramid ioctl.h */ +#define stack G.area.shrink.Stack + + +/***********************/ +/* Function unshrink() */ +/***********************/ + +int unshrink(__G) + __GDEF +{ + int offset = (HSIZE - 1); + uch *stacktop = stack + offset; + register uch *newstr; + int codesize=9, len, KwKwK, error; + shrint code, oldcode, freecode, curcode; + shrint lastfreecode; + unsigned int outbufsiz; +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + /* Normally realbuf and outbuf will be the same. However, if the data + * are redirected to a large memory buffer, realbuf will point to the + * new location while outbuf will remain pointing to the malloc'd + * memory buffer. */ + uch *realbuf = G.outbuf; +#else +# define realbuf G.outbuf +#endif + + +/*--------------------------------------------------------------------------- + Initialize various variables. + ---------------------------------------------------------------------------*/ + + lastfreecode = BOGUSCODE; + +#ifndef VMS /* VMS uses its own buffer scheme for textmode flush(). */ +#ifndef SMALL_MEM + /* non-memory-limited machines: allocate second (large) buffer for + * textmode conversion in flush(), but only if needed */ + if (G.pInfo->textmode && !G.outbuf2 && + (G.outbuf2 = (uch *)malloc(TRANSBUFSIZ)) == (uch *)NULL) + return PK_MEM3; +#endif +#endif /* !VMS */ + + for (code = 0; code < BOGUSCODE; ++code) { + Value[code] = (uch)code; + parent[code] = BOGUSCODE; + } + for (code = BOGUSCODE+1; code < HSIZE; ++code) + parent[code] = FREE_CODE; + +#if (defined(DLL) && !defined(NO_SLIDE_REDIR)) + if (G.redirect_slide) { /* use normal outbuf unless we're a DLL routine */ + realbuf = G.redirect_buffer; + outbufsiz = G.redirect_size; + } else +#endif +#ifdef DLL + if (G.pInfo->textmode && !G.redirect_data) +#else + if (G.pInfo->textmode) +#endif + outbufsiz = RAWBUFSIZ; + else + outbufsiz = OUTBUFSIZ; + G.outptr = realbuf; + G.outcnt = 0L; + +/*--------------------------------------------------------------------------- + Get and output first code, then loop over remaining ones. + ---------------------------------------------------------------------------*/ + + READBITS(codesize, oldcode) + if (!G.zipeof) { + *G.outptr++ = (uch)oldcode; + OUTDBG((uch)oldcode) + ++G.outcnt; + } + + do { + READBITS(codesize, code) + if (G.zipeof) + break; + if (code == BOGUSCODE) { /* possible to have consecutive escapes? */ + READBITS(codesize, code) + if (code == 1) { + ++codesize; + Trace((stderr, " (codesize now %d bits)\n", codesize)); + } else if (code == 2) { + Trace((stderr, " (partial clear code)\n")); + partial_clear(__G); /* clear leafs (nodes with no children) */ + Trace((stderr, " (done with partial clear)\n")); + lastfreecode = BOGUSCODE; /* reset start of free-node search */ + } + continue; + } + + /*----------------------------------------------------------------------- + Translate code: traverse tree from leaf back to root. + -----------------------------------------------------------------------*/ + + newstr = stacktop; + curcode = code; + + if (parent[curcode] == FREE_CODE) { + /* or (FLAG_BITS[curcode] & FREE_CODE)? */ + KwKwK = TRUE; + Trace((stderr, " (found a KwKwK code %d; oldcode = %d)\n", code, + oldcode)); + --newstr; /* last character will be same as first character */ + curcode = oldcode; + } else + KwKwK = FALSE; + + do { + *newstr-- = Value[curcode]; + curcode = (shrint)(parent[curcode] & CODE_MASK); + } while (curcode != BOGUSCODE); + + len = (int)(stacktop - newstr++); + if (KwKwK) + *stacktop = *newstr; + + /*----------------------------------------------------------------------- + Write expanded string in reverse order to output buffer. + -----------------------------------------------------------------------*/ + + Trace((stderr, "code %4d; oldcode %4d; char %3d (%c); string [", code, + oldcode, (int)(*newstr), (*newstr<32 || *newstr>=127)? ' ':*newstr)); + + { + register uch *p; + + for (p = newstr; p < newstr+len; ++p) { + *G.outptr++ = *p; + OUTDBG(*p) + if (++G.outcnt == outbufsiz) { + Trace((stderr, "doing flush(), outcnt = %lu\n", G.outcnt)); + if ((error = flush(__G__ realbuf, G.outcnt, TRUE)) != 0) + pipeit("unshrink: flush() error (%d)\n", + error); + Trace((stderr, "done with flush()\n")); + G.outptr = realbuf; + G.outcnt = 0L; + } + } + } + + /*----------------------------------------------------------------------- + Add new leaf (first character of newstr) to tree as child of oldcode. + -----------------------------------------------------------------------*/ + + /* search for freecode */ + freecode = (shrint)(lastfreecode + 1); + /* add if-test before loop for speed? */ + while (parent[freecode] != FREE_CODE) + ++freecode; + lastfreecode = freecode; + Trace((stderr, "]; newcode %d\n", freecode)); + + Value[freecode] = *newstr; + parent[freecode] = oldcode; + oldcode = code; + + } while (!G.zipeof); + +/*--------------------------------------------------------------------------- + Flush any remaining data and return to sender... + ---------------------------------------------------------------------------*/ + + if (G.outcnt > 0L) { + Trace((stderr, "doing final flush(), outcnt = %lu\n", G.outcnt)); + if ((error = flush(__G__ realbuf, G.outcnt, TRUE)) != 0) + pipeit("unshrink: flush() error (%d)\n", error); + Trace((stderr, "done with flush()\n")); + } + + return PK_OK; + +} /* end function unshrink() */ + + + + + +/****************************/ +/* Function partial_clear() */ /* no longer recursive... */ +/****************************/ + +static void partial_clear(__G) + __GDEF +{ + register shrint code; + + /* clear all nodes which have no children (i.e., leaf nodes only) */ + + /* first loop: mark each parent as such */ + for (code = BOGUSCODE+1; code < HSIZE; ++code) { + register shrint cparent = (shrint)(parent[code] & CODE_MASK); + + if (cparent > BOGUSCODE && cparent != FREE_CODE) + FLAG_BITS[cparent] |= HAS_CHILD; /* set parent's child-bit */ + } + + /* second loop: clear all nodes *not* marked as parents; reset flag bits */ + for (code = BOGUSCODE+1; code < HSIZE; ++code) { + if (FLAG_BITS[code] & HAS_CHILD) /* just clear child-bit */ + FLAG_BITS[code] &= ~HAS_CHILD; + else { /* leaf: lose it */ + Trace((stderr, "%d\n", code)); + parent[code] = FREE_CODE; + } + } + + return; +} + +#endif /* !LZW_CLEAN */ diff --git a/utils/Install/sfxzip/unzip.c b/utils/Install/sfxzip/unzip.c new file mode 100644 index 0000000000..09968d4190 --- /dev/null +++ b/utils/Install/sfxzip/unzip.c @@ -0,0 +1,1744 @@ +/*--------------------------------------------------------------------------- + + unzip.c + + UnZip - a zipfile extraction utility. See below for make instructions, or + read the comments in Makefile and the various Contents files for more de- + tailed explanations. To report a bug, send a *complete* description to + Zip-Bugs@lists.wku.edu; include machine type, operating system and ver- + sion, compiler and version, and reasonably detailed error messages or prob- + lem report. To join Info-ZIP, see the instructions in README. + + UnZip 5.x is a greatly expanded and partially rewritten successor to 4.x, + which in turn was almost a complete rewrite of version 3.x. For a detailed + revision history, see UnzpHist.zip at quest.jpl.nasa.gov. For a list of + the many (near infinite) contributors, see "CONTRIBS" in the UnZip source + distribution. + + --------------------------------------------------------------------------- + + [from original zipinfo.c] + + This program reads great gobs of totally nifty information, including the + central directory stuff, from ZIP archives ("zipfiles" for short). It + started as just a testbed for fooling with zipfiles, but at this point it + is actually a useful utility. It also became the basis for the rewrite of + UnZip (3.16 -> 4.0), using the central directory for processing rather than + the individual (local) file headers. + + As of ZipInfo v2.0 and UnZip v5.1, the two programs are combined into one. + If the executable is named "unzip" (or "unzip.exe", depending), it behaves + like UnZip by default; if it is named "zipinfo" or "ii", it behaves like + ZipInfo. The ZipInfo behavior may also be triggered by use of unzip's -Z + option; for example, "unzip -Z [zipinfo_options] archive.zip". + + Another dandy product from your buddies at Newtware! + + Author: Greg Roelofs, newt@pobox.com, http://pobox.com/~newt/ + 23 August 1990 -> April 1997 + + --------------------------------------------------------------------------- + + Version: unzip5??.{tar.Z | tar.gz | zip} for Unix, VMS, OS/2, MS-DOS, Amiga, + Atari, Windows 3.x/95/NT/CE, Macintosh, Human68K, Acorn RISC OS, + BeOS, SMS/QDOS, VM/CMS, MVS, AOS/VS and TOPS-20. Decryption + requires sources in zcrypt28.zip. See the accompanying "WHERE" + file in the main source distribution for ftp, uucp, BBS and mail- + server sites, or see http://www.cdrom.com/pub/infozip/UnZip.html . + + Copyrights: see accompanying file "COPYING" in UnZip source distribution. + (This software is free but NOT IN THE PUBLIC DOMAIN. There + are some restrictions on commercial use.) + + ---------------------------------------------------------------------------*/ + + + +#define UNZIP_C +#define UNZIP_INTERNAL +#include "unzip.h" /* includes, typedefs, macros, prototypes, etc. */ +#include "crypt.h" +#include "version.h" + +#ifndef WINDLL /* The WINDLL port uses windll/windll.c instead... */ + +/*******************/ +/* Local Functions */ +/*******************/ + +#ifndef SFX +static void show_version_info OF((__GPRO)); +#endif + + +/*************/ +/* Constants */ +/*************/ + +#include "consts.h" /* all constant global variables are in here */ + /* (non-constant globals were moved to globals.c) */ + +/* constant local variables: */ + +#ifndef SFX + static ZCONST char Far EnvUnZip[] = ENV_UNZIP; + static ZCONST char Far EnvUnZip2[] = ENV_UNZIP2; + static ZCONST char Far EnvZipInfo[] = ENV_ZIPINFO; + static ZCONST char Far EnvZipInfo2[] = ENV_ZIPINFO2; +#ifdef RISCOS + static ZCONST char Far EnvUnZipExts[] = ENV_UNZIPEXTS; +#endif /* RISCOS */ +#endif + +#if (!defined(SFX) || defined(SFX_EXDIR)) + static ZCONST char Far NotExtracting[] = + "caution: not extracting; -d ignored\n"; + static ZCONST char Far MustGiveExdir[] = + "error: must specify directory to which to extract with -d option\n"; + static ZCONST char Far OnlyOneExdir[] = + "error: -d option used more than once (only one exdir allowed)\n"; +#endif + +#if CRYPT + static ZCONST char Far MustGivePasswd[] = + "error: must give decryption password with -P option\n"; +#endif + +#ifndef SFX + static ZCONST char Far Zfirst[] = + "error: -Z must be first option for ZipInfo mode (check UNZIP variable?)\n"; +#endif +static ZCONST char Far InvalidOptionsMsg[] = "error:\ + -fn or any combination of -c, -l, -p, -t, -u and -v options invalid\n"; +static ZCONST char Far IgnoreOOptionMsg[] = + "caution: both -n and -o specified; ignoring -o\n"; + +/* usage() strings */ +#ifndef SFX +#ifdef VMS + static ZCONST char Far Example3[] = "vms.c"; + static ZCONST char Far Example2[] = " unzip\ + \"-V\" foo \"Bar\" => must quote uppercase options and filenames in VMS\n"; +#else /* !VMS */ + static ZCONST char Far Example3[] = "ReadMe"; +#ifdef RISCOS + static ZCONST char Far Example2[] = +" unzip foo -d RAM:$ => extract all files from foo into RAMDisc\n"; +#else /* !RISCOS */ +#if (defined(OS2) || (defined(DOS_FLX_OS2_W32) && defined(MORE))) + static ZCONST char Far Example2[] = + ""; /* no room: too many local3[] items */ +#else /* !OS2 */ +#ifdef MACOS + static ZCONST char Far Example2[] = ""; /* not needed */ +#else /* !MACOS */ + static ZCONST char Far Example2[] = " \ + unzip -p foo | more => send contents of foo.zip via pipe into program more\n"; +#endif /* ?MACOS */ +#endif /* ?OS2 */ +#endif /* ?RISCOS */ +#endif /* ?VMS */ + +/* local1[]: command options */ +#if (defined(DLL) && defined(API_DOC)) + static ZCONST char Far local1[] = + " -A print extended help for API functions"; +#else /* !(DLL && API_DOC) */ + static ZCONST char Far local1[] = ""; +#endif /* ?(DLL && API_DOC) */ + +/* local2[] and local3[]: modifier options */ +#ifdef DOS_FLX_OS2_W32 +#ifdef FLEXOS + static ZCONST char Far local2[] = ""; +#else + static ZCONST char Far local2[] = + " -$ label removables (-$$ => fixed disks)"; +#endif +#ifdef OS2 +#ifdef MORE + static ZCONST char Far local3[] = "\ + -X restore ACLs if supported -s spaces in filenames => '_'\n\ + -M pipe through \"more\" pager\n"; +#else + static ZCONST char Far local3[] = " \ + -X restore ACLs if supported -s spaces in filenames => '_'\n\n"; +#endif /* ?MORE */ +#else /* !OS2 */ +#ifdef WIN32 +#ifdef MORE + static ZCONST char Far local3[] = "\ + -X restore ACLs (-XX => use privileges) -s spaces in filenames => '_'\n\ + -M pipe through \"more\" pager\n"; +#else + static ZCONST char Far local3[] = " \ + -X restore ACLs (-XX => use privileges) -s spaces in filenames => '_'\n\n"; +#endif /* ?MORE */ +#else /* !WIN32 */ +#ifdef MORE + static ZCONST char Far local3[] = " -\ +M pipe through \"more\" pager -s spaces in filenames => '_'\n\n"; +#else + static ZCONST char Far local3[] = "\ + -s spaces in filenames => '_'\n"; +#endif +#endif /* ?WIN32 */ +#endif /* ?OS2 || ?WIN32 */ +#else /* !DOS_FLX_OS2_W32 */ +#ifdef VMS + static ZCONST char Far local2[] = "\"-X\" restore owner/protection info"; +#ifdef MORE + static ZCONST char Far local3[] = " \ + \"-M\" pipe through \"more\" pager\n"; +#else + static ZCONST char Far local3[] = "\n"; +#endif +#else /* !VMS */ +#if (defined(__BEOS__) || defined(TANDEM) || defined(UNIX)) + static ZCONST char Far local2[] = " -X restore UID/GID info"; +#ifdef MORE + static ZCONST char Far local3[] = "\ + -M pipe through \"more\" pager\n"; +#else + static ZCONST char Far local3[] = "\n"; +#endif +#else /* !(__BEOS__ || TANDEM || UNIX) */ +#ifdef AMIGA + static ZCONST char Far local2[] = " -N restore comments as filenotes"; +#ifdef MORE + static ZCONST char Far local3[] = "\ + -M pipe through \"more\" pager\n"; +#else + static ZCONST char Far local3[] = "\n"; +#endif +#else /* !AMIGA */ +#ifdef MACOS + static ZCONST char Far local2[] = " -E show Mac info during extraction"; + static ZCONST char Far local3[] = " \ + -i ignore filenames in mac extra info -J junk (ignore) Mac extra info\n\n"; +#else /* !MACOS */ +#ifdef MORE + static ZCONST char Far local2[] = " -M pipe through \"more\" pager"; + static ZCONST char Far local3[] = "\n"; +#else + static ZCONST char Far local2[] = ""; /* Atari, Mac, CMS/MVS etc. */ + static ZCONST char Far local3[] = ""; +#endif +#endif /* ?MACOS */ +#endif /* ?AMIGA */ +#endif /* ?(__BEOS__ || TANDEM || UNIX) */ +#endif /* ?VMS */ +#endif /* ?DOS_FLX_OS2_W32 */ +#endif /* !SFX */ + +#ifndef NO_ZIPINFO +#ifdef VMS + static ZCONST char Far ZipInfoExample[] = "* or % (e.g., \"*font-%.zip\")"; +#else + static ZCONST char Far ZipInfoExample[] = "*, ?, [] (e.g., \"[a-j]*.zip\")"; +#endif + +static ZCONST char Far ZipInfoUsageLine1[] = "\ +ZipInfo %d.%d%d%s of %s, by Greg Roelofs and the Info-ZIP group.\n\ +\n\ +List name, date/time, attribute, size, compression method, etc., about files\n\ +in list (excluding those in xlist) contained in the specified .zip archive(s).\ +\n\"file[.zip]\" may be a wildcard name containing %s.\n\n\ + usage: zipinfo [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n\ + or: unzip %s-Z%s [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n"; + +static ZCONST char Far ZipInfoUsageLine2[] = "\nmain\ + listing-format options: -s short Unix \"ls -l\" format (def.)\n\ + -1 filenames ONLY, one per line -m medium Unix \"ls -l\" format\n\ + -2 just filenames but allow -h/-t/-z -l long Unix \"ls -l\" format\n\ + -v verbose, multi-page format\n"; + +static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\ + -h print header line -t print totals for listed files or for all\n\ + -z print zipfile comment %c-T%c print file times in sortable decimal format\ +\n %c-C%c be case-insensitive %s\ + -x exclude filenames that follow from listing\n"; +#ifdef MORE +#ifdef VMS + static ZCONST char Far ZipInfoUsageLine4[] = + " \"-M\" page output through built-in \"more\"\n"; +#else + static ZCONST char Far ZipInfoUsageLine4[] = + " -M page output through built-in \"more\"\n"; +#endif +#else /* !MORE */ + static ZCONST char Far ZipInfoUsageLine4[] = ""; +#endif /* ?MORE */ +#endif /* !NO_ZIPINFO */ + +#ifdef BETA +# ifdef VMSCLI + /* BetaVersion[] is also used in vms/cmdline.c: do not make it static */ + ZCONST char Far BetaVersion[] = "%s\ + THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n"; +# else + static ZCONST char Far BetaVersion[] = "%s\ + THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n"; +# endif +#endif + +#ifdef SFX +# ifdef VMSCLI + /* UnzipSFXBanner[] is also used in vms/cmdline.c: do not make it static */ + ZCONST char Far UnzipSFXBanner[] = +# else + static ZCONST char Far UnzipSFXBanner[] = +# endif + "UnZipSFX %d.%d%d%s of %s, by Info-ZIP (Zip-Bugs@lists.wku.edu).\n"; +# ifdef SFX_EXDIR + static ZCONST char Far UnzipSFXOpts[] = + "Valid options are -tfupcz and -d ; modifiers are -abjnoqCL%sV%s.\n"; +# else + static ZCONST char Far UnzipSFXOpts[] = + "Valid options are -tfupcz; modifiers are -abjnoqCL%sV%s.\n"; +# endif +#else /* !SFX */ + static ZCONST char Far CompileOptions[] = + "UnZip special compilation options:\n"; + static ZCONST char Far CompileOptFormat[] = "\t%s\n"; + static ZCONST char Far EnvOptions[] = + "\nUnZip and ZipInfo environment options:\n"; + static ZCONST char Far EnvOptFormat[] = "%16s: %s\n"; + static ZCONST char Far None[] = "[none]"; +# ifdef ACORN_FTYPE_NFS + static ZCONST char Far AcornFtypeNFS[] = "ACORN_FTYPE_NFS"; +# endif +# ifdef ASM_CRC + static ZCONST char Far AsmCRC[] = "ASM_CRC"; +# endif +# ifdef ASM_INFLATECODES + static ZCONST char Far AsmInflateCodes[] = "ASM_INFLATECODES"; +# endif +# ifdef CHECK_VERSIONS + static ZCONST char Far Check_Versions[] = "CHECK_VERSIONS"; +# endif +# ifdef COPYRIGHT_CLEAN + static ZCONST char Far Copyright_Clean[] = + "COPYRIGHT_CLEAN (PKZIP 0.9x unreducing method not supported)"; +# endif +# ifdef DEBUG + static ZCONST char Far UDebug[] = "DEBUG"; +# endif +# ifdef DEBUG_TIME + static ZCONST char Far DebugTime[] = "DEBUG_TIME"; +# endif +# ifdef DLL + static ZCONST char Far Dll[] = "DLL"; +# endif +# ifdef DOSWILD + static ZCONST char Far DosWild[] = "DOSWILD"; +# endif +# ifdef LZW_CLEAN + static ZCONST char Far LZW_Clean[] = + "LZW_CLEAN (PKZIP/Zip 1.x unshrinking method not supported)"; +# endif +# ifndef MORE + static ZCONST char Far No_More[] = "NO_MORE"; +# endif +# ifdef NO_ZIPINFO + static ZCONST char Far No_ZipInfo[] = "NO_ZIPINFO"; +# endif +# ifdef NTSD_EAS + static ZCONST char Far NTSDExtAttrib[] = "NTSD_EAS"; +# endif +# ifdef OS2_EAS + static ZCONST char Far OS2ExtAttrib[] = "OS2_EAS"; +# endif +# ifdef QLZIP + static ZCONST char Far SMSExFldOnUnix[] = "QLZIP"; +# endif +# ifdef REENTRANT + static ZCONST char Far Reentrant[] = "REENTRANT"; +# endif +# ifdef REGARGS + static ZCONST char Far RegArgs[] = "REGARGS"; +# endif +# ifdef RETURN_CODES + static ZCONST char Far Return_Codes[] = "RETURN_CODES"; +# endif +# ifdef SET_DIR_ATTRIB + static ZCONST char Far SetDirAttrib[] = "SET_DIR_ATTRIB"; +# endif +# ifdef TIMESTAMP + static ZCONST char Far TimeStamp[] = "TIMESTAMP"; +# endif +# ifdef UNIXBACKUP + static ZCONST char Far UnixBackup[] = "UNIXBACKUP"; +# endif +# ifdef USE_EF_UT_TIME + static ZCONST char Far Use_EF_UT_time[] = "USE_EF_UT_TIME"; +# endif +# ifndef LZW_CLEAN + static ZCONST char Far Use_Unshrink[] = + "USE_UNSHRINK (PKZIP/Zip 1.x unshrinking method supported)"; +# endif +# ifndef COPYRIGHT_CLEAN + static ZCONST char Far Use_Smith_Code[] = + "USE_SMITH_CODE (PKZIP 0.9x unreducing method supported)"; +# endif +# ifdef USE_VFAT + static ZCONST char Far Use_VFAT_support[] = "USE_VFAT"; +# endif +# ifdef USE_ZLIB + static ZCONST char Far UseZlib[] = + "USE_ZLIB (compiled with version %s; using version %s)"; +# endif +# ifdef VMS_TEXT_CONV + static ZCONST char Far VmsTextConv[] = "VMS_TEXT_CONV"; +# endif +# ifdef VMSCLI + static ZCONST char Far VmsCLI[] = "VMSCLI"; +# endif +# ifdef VMSWILD + static ZCONST char Far VmsWild[] = "VMSWILD"; +# endif +# if CRYPT +# ifdef PASSWD_FROM_STDIN + static ZCONST char Far PasswdStdin[] = "PASSWD_FROM_STDIN"; +# endif + static ZCONST char Far Decryption[] = + "\t[decryption, version %d.%d%s of %s]\n"; + static ZCONST char Far CryptDate[] = CR_VERSION_DATE; +# endif +# ifndef __RSXNT__ +# ifdef __EMX__ + static ZCONST char Far EnvEMX[] = "EMX"; + static ZCONST char Far EnvEMXOPT[] = "EMXOPT"; +# endif +# if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2))) + static ZCONST char Far EnvGO32[] = "GO32"; + static ZCONST char Far EnvGO32TMP[] = "GO32TMP"; +# endif +# endif /* !__RSXNT__ */ + +#ifdef VMS +/* UnzipUsageLine1[] is also used in vms/cmdline.c: do not make it static */ + ZCONST char Far UnzipUsageLine1[] = "\ +UnZip %d.%d%d%s of %s, by Info-ZIP. For more details see: unzip -v.\n\n"; +#ifdef COPYRIGHT_CLEAN + static ZCONST char Far UnzipUsageLine1v[] = "\ +UnZip %d.%d%d%s of %s, by Info-ZIP. Maintained by C. Spieler. Send\n\ +bug reports to the authors at Zip-Bugs@lists.wku.edu; see README for details.\ +\n\n"; +#else + static ZCONST char Far UnzipUsageLine1v[] = "\ +UnZip %d.%d%d%s of %s, by Info-ZIP. UnReduce (c) 1989 by S. H. Smith.\n\ +Send bug reports to authors at Zip-Bugs@lists.wku.edu; see README for details.\ +\n\n"; +#endif /* ?COPYRIGHT_CLEAN */ +#else /* !VMS */ +#ifdef COPYRIGHT_CLEAN + static ZCONST char Far UnzipUsageLine1[] = "\ +UnZip %d.%d%d%s of %s, by Info-ZIP. Maintained by C. Spieler. Send\n\ +bug reports to the authors at Zip-Bugs@lists.wku.edu; see README for details.\ +\n\n"; +#else + static ZCONST char Far UnzipUsageLine1[] = "\ +UnZip %d.%d%d%s of %s, by Info-ZIP. UnReduce (c) 1989 by S. H. Smith.\n\ +Send bug reports to authors at Zip-Bugs@lists.wku.edu; see README for details.\ +\n\n"; +#endif /* ?COPYRIGHT_CLEAN */ +#define UnzipUsageLine1v UnzipUsageLine1 +#endif /* ?VMS */ + +static ZCONST char Far UnzipUsageLine2v[] = "\ +Latest sources and executables are at ftp://ftp.cdrom.com/pub/infozip/ , as of\ +\nabove date; see http://www.cdrom.com/pub/infozip/UnZip.html for other sites.\ +\n\n"; + +#ifdef MACOS +static ZCONST char Far UnzipUsageLine2[] = "\ +Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-d exdir]\n \ + Default action is to extract files in list, to exdir;\n\ + file[.zip] may be a wildcard. %s\n"; +#else /* !MACOS */ +#ifdef VM_CMS +static ZCONST char Far UnzipUsageLine2[] = "\ +Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d fm]\n \ + Default action is to extract files in list, except those in xlist, to disk fm;\n\ + file[.zip] may be a wildcard. %s\n"; +#else /* !VM_CMS */ +static ZCONST char Far UnzipUsageLine2[] = "\ +Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]\n \ + Default action is to extract files in list, except those in xlist, to exdir;\n\ + file[.zip] may be a wildcard. %s\n"; +#endif /* ?VM_CMS */ +#endif /* ?MACOS */ + +#ifdef NO_ZIPINFO +# define ZIPINFO_MODE_OPTION "" + static ZCONST char Far ZipInfoMode[] = + "(ZipInfo mode is disabled in this version.)"; +#else +# define ZIPINFO_MODE_OPTION "[-Z] " +# ifdef VMS + static ZCONST char Far ZipInfoMode[] = + "\"-Z\" => ZipInfo mode (`unzip \"-Z\"' for usage)."; +# else + static ZCONST char Far ZipInfoMode[] = + "-Z => ZipInfo mode (\"unzip -Z\" for usage)."; +# endif +#endif /* ?NO_ZIPINFO */ + +#ifdef VMS + static ZCONST char Far VMSusageLine2b[] = "\ +=> define foreign command symbol in LOGIN.COM: $ unzip :== $dev:[dir]unzip.exe\ +\n"; +#endif + +#ifdef MACOS +static ZCONST char Far UnzipUsageLine3[] = "\n\ + -d extract files into exdir -l list files (short format)\n\ + -f freshen existing files, create none -t test compressed archive data\n\ + -u update files, create if necessary -z display archive comment\n\ +%s\n"; +#else /* !MACOS */ +#ifdef VM_CMS +static ZCONST char Far UnzipUsageLine3[] = "\n\ + -p extract files to pipe, no messages -l list files (short format)\n\ + -f freshen existing files, create none -t test compressed archive data\n\ + -u update files, create if necessary -z display archive comment\n\ + -x exclude files that follow (in xlist) -d extract files onto disk fm\n\ +%s\n"; +#else /* !VM_CMS */ +static ZCONST char Far UnzipUsageLine3[] = "\n\ + -p extract files to pipe, no messages -l list files (short format)\n\ + -f freshen existing files, create none -t test compressed archive data\n\ + -u update files, create if necessary -z display archive comment\n\ + -x exclude files that follow (in xlist) -d extract files into exdir\n\ +%s\n"; +#endif /* ?VM_CMS */ +#endif /* ?MACOS */ + +static ZCONST char Far UnzipUsageLine4[] = "\ +modifiers: -q quiet mode (-qq => quieter)\n\ + -n never overwrite existing files -a auto-convert any text files\n\ + -o overwrite files WITHOUT prompting -aa treat ALL files as text\n \ + -j junk paths (do not make directories) -v be verbose/print version info\n\ + %c-C%c match filenames case-insensitively %c-L%c make (some) names \ +lowercase\n %-42s %c-V%c retain VMS version numbers\n%s"; + +static ZCONST char Far UnzipUsageLine5[] = "\ +Examples (see unzip.doc for more info):\n\ + unzip data1 -x joe => extract all files except joe from zipfile data1.zip\n\ +%s\ + unzip -fo foo %-6s => quietly replace existing %s if archive file newer\n"; +#endif /* ?SFX */ + + + + + +/*****************************/ +/* main() / UzpMain() stub */ +/*****************************/ + +int installer_unpack(char *aname, int depricated) /* return PK-type error code (except under VMS) */ +{ + int r, argc = 3; + char tempfile[256]; + char *argv[4]; + + argv[0] = "install.exe"; + argv[1] = "install.exe"; + argv[2] = tempfile; + argv[3] = NULL; + + if(aname) + strcpy(tempfile, aname); + else + argc = 2; + + CONSTRUCTGLOBALS(); + r = unzip(__G__ argc, argv); + DESTROYGLOBALS() + RETURN(r); +} + +void resetglobals(void) { } + +int pipeit(char *format, ...) +{ + return 0; +} + + +/*******************************/ +/* Primary UnZip entry point */ +/*******************************/ + +int unzip(__G__ argc, argv) + __GDEF + int argc; + char *argv[]; +{ +#ifndef NO_ZIPINFO + char *p; +#endif +#ifdef DOS_FLX_H68_OS2_W32 + int i; +#endif + int retcode, error=FALSE; + +#if (defined(__IBMC__) && defined(__DEBUG_ALLOC__)) + extern void DebugMalloc(void); + + atexit(DebugMalloc); +#endif + +#ifdef MALLOC_WORK + G.area.Slide =(uch *)calloc(8193, sizeof(shrint)+sizeof(uch)+sizeof(uch)); + G.area.shrink.Parent = (shrint *)G.area.Slide; + G.area.shrink.value = G.area.Slide + (sizeof(shrint)*(HSIZE+1)); + G.area.shrink.Stack = G.area.Slide + + (sizeof(shrint) + sizeof(uch))*(HSIZE+1); +#endif + +/*--------------------------------------------------------------------------- + Macintosh initialization code. + ---------------------------------------------------------------------------*/ + +#ifdef MACOS + { + int a; + + for (a = 0; a < 4; ++a) + G.rghCursor[a] = GetCursor(a+128); + G.giCursor = 0; + } +#endif + +/*--------------------------------------------------------------------------- + Human68K initialization code. + ---------------------------------------------------------------------------*/ + +#ifdef __human68k__ + InitTwentyOne(); +#endif + +/*--------------------------------------------------------------------------- + Acorn RISC OS initialization code. + ---------------------------------------------------------------------------*/ + +#ifdef RISCOS + set_prefix(); +#endif + +/*--------------------------------------------------------------------------- + Set signal handler for restoring echo, warn of zipfile corruption, etc. + ---------------------------------------------------------------------------*/ + +#ifdef SIGINT + signal(SIGINT, handler); +#endif +#ifdef SIGTERM /* some systems really have no SIGTERM */ + signal(SIGTERM, handler); +#endif +#ifdef SIGBUS + signal(SIGBUS, handler); +#endif +#ifdef SIGSEGV + signal(SIGSEGV, handler); +#endif + +#if (defined(WIN32) && defined(__RSXNT__)) + for (i = 0 ; i < argc; i++) { + _ISO_INTERN(argv[i]); + } +#endif + +/*--------------------------------------------------------------------------- + First figure out if we're running in UnZip mode or ZipInfo mode, and put + the appropriate environment-variable options into the queue. Then rip + through any command-line options lurking about... + ---------------------------------------------------------------------------*/ + +#ifdef SFX + G.argv0 = argv[0]; +#if (defined(OS2) || defined(WIN32)) + G.zipfn = GetLoadPath(__G);/* non-MSC NT puts path into G.filename[] */ +#else + G.zipfn = G.argv0; +#endif + +#ifdef VMSCLI + { + ulg status = vms_unzip_cmdline(&argc, &argv); + if (!(status & 1)) + return status; + } +#endif /* VMSCLI */ + + uO.zipinfo_mode = FALSE; + error = uz_opts(__G__ &argc, &argv); /* UnZipSFX call only */ + +#else /* !SFX */ + +#ifdef RISCOS + /* get the extensions to swap from environment */ + getRISCOSexts(ENV_UNZIPEXTS); +#endif + +#ifdef MSDOS + /* extract MKS extended argument list from environment (before envargs!) */ + mksargs(&argc, &argv); +#endif + +#ifdef VMSCLI + { + ulg status = vms_unzip_cmdline(&argc, &argv); + if (!(status & 1)) + return status; + } +#endif /* VMSCLI */ + + G.noargs = (argc == 1); /* no options, no zipfile, no anything */ + +#ifndef NO_ZIPINFO + for (p = argv[0] + strlen(argv[0]); p >= argv[0]; --p) { + if (*p == DIR_END +#ifdef DIR_END2 + || *p == DIR_END2 +#endif + ) + break; + } + ++p; + + if (STRNICMP(p, LoadFarStringSmall(Zipnfo), 7) == 0 || + STRNICMP(p, "ii", 2) == 0 || + (argc > 1 && strncmp(argv[1], "-Z", 2) == 0)) + { + uO.zipinfo_mode = TRUE; + envargs(__G__ &argc, &argv, LoadFarStringSmall(EnvZipInfo), + LoadFarStringSmall2(EnvZipInfo2)); + error = zi_opts(__G__ &argc, &argv); + } else +#endif /* NO_ZIPINFO */ + { + uO.zipinfo_mode = FALSE; + envargs(__G__ &argc, &argv, LoadFarStringSmall(EnvUnZip), + LoadFarStringSmall2(EnvUnZip2)); + error = uz_opts(__G__ &argc, &argv); + } + +#endif /* ?SFX */ + + if ((argc < 0) || error) + return error; + +/*--------------------------------------------------------------------------- + Now get the zipfile name from the command line and then process any re- + maining options and file specifications. + ---------------------------------------------------------------------------*/ + +#ifdef DOS_FLX_H68_OS2_W32 + /* convert MSDOS-style directory separators to Unix-style ones for + * user's convenience (include zipfile name itself) + */ +#ifdef SFX + for (G.pfnames = argv, i = argc; i > 0; --i) { +#else + /* argc does not include the zipfile specification */ + for (G.pfnames = argv, i = argc+1; i > 0; --i) { +#endif + char *q; + + for (q = *G.pfnames; *q; ++q) + if (*q == '\\') + *q = '/'; + ++G.pfnames; + } +#endif /* DOS_FLX_H68_OS2_W32 */ + +#ifndef SFX + G.wildzipfn = *argv++; +#endif + +#if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */ + + G.filespecs = argc; + G.xfilespecs = 0; + + if (argc > 0) { + char **pp = argv-1; + + G.pfnames = argv; + while (*++pp) + if (strcmp(*pp, "-x") == 0) { + if (pp > argv) { + *pp = 0; /* terminate G.pfnames */ + G.filespecs = pp - G.pfnames; + } else { + G.pfnames = (char **)fnames; /* defaults */ + G.filespecs = 0; + } + G.pxnames = pp + 1; /* excluded-names ptr: _after_ -x */ + G.xfilespecs = argc - G.filespecs - 1; + break; /* skip rest of args */ + } + G.process_all_files = FALSE; + } else + G.process_all_files = TRUE; /* for speed */ + +#else /* !SFX || SFX_EXDIR */ /* check for -x or -d */ + + G.filespecs = argc; + G.xfilespecs = 0; + + if (argc > 0) { + int in_files=FALSE, in_xfiles=FALSE; + char **pp = argv-1; + + G.process_all_files = FALSE; + G.pfnames = argv; + while (*++pp) { + Trace((stderr, "pp - argv = %d\n", pp-argv)); +#ifdef CMS_MVS + if (!uO.exdir && STRNICMP(*pp, "-d", 2) == 0) { +#else + if (!uO.exdir && strncmp(*pp, "-d", 2) == 0) { +#endif + int firstarg = (pp == argv); + + uO.exdir = (*pp) + 2; + if (in_files) { /* ... zipfile ... -d exdir ... */ + *pp = (char *)NULL; /* terminate G.pfnames */ + G.filespecs = pp - G.pfnames; + in_files = FALSE; + } else if (in_xfiles) { + *pp = (char *)NULL; /* terminate G.pxnames */ + G.xfilespecs = pp - G.pxnames; + /* "... -x xlist -d exdir": nothing left */ + } + /* first check for "-dexdir", then for "-d exdir" */ + if (*uO.exdir == '\0') { + if (*++pp) + uO.exdir = *pp; + else { + Info(slide, 0x401, ((char *)slide, + LoadFarString(MustGiveExdir))); + return(PK_PARAM); /* don't extract here by accident */ + } + } + if (firstarg) { /* ... zipfile -d exdir ... */ + if (pp[1]) { + G.pfnames = pp + 1; /* argv+2 */ + G.filespecs = argc - (G.pfnames-argv); /* for now... */ + } else { + G.process_all_files = TRUE; + G.pfnames = (char **)fnames; /* GRR: necessary? */ + G.filespecs = 0; /* GRR: necessary? */ + break; + } + } + } else if (!in_xfiles) { + if (strcmp(*pp, "-x") == 0) { + in_xfiles = TRUE; + if (pp == G.pfnames) { + G.pfnames = (char **)fnames; /* defaults */ + G.filespecs = 0; + } else if (in_files) { + *pp = 0; /* terminate G.pfnames */ + G.filespecs = pp - G.pfnames; /* adjust count */ + in_files = FALSE; + } + G.pxnames = pp + 1; /* excluded-names ptr starts after -x */ + G.xfilespecs = argc - (G.pxnames-argv); /* anything left */ + } else + in_files = TRUE; + } + } + } else + G.process_all_files = TRUE; /* for speed */ + + if (uO.exdir != (char *)NULL && !G.extract_flag) /* -d ignored */ + Info(slide, 0x401, ((char *)slide, LoadFarString(NotExtracting))); +#endif /* ?(SFX && !SFX_EXDIR) */ + +/*--------------------------------------------------------------------------- + Okey dokey, we have everything we need to get started. Let's roll. + ---------------------------------------------------------------------------*/ + + retcode = process_zipfiles(__G); + return(retcode); + +} /* end main()/unzip() */ + + + + + +/**********************/ +/* Function uz_opts() */ +/**********************/ + +int uz_opts(__G__ pargc, pargv) + __GDEF + int *pargc; + char ***pargv; +{ + char **argv, *s; + int argc, c, error=FALSE, negative=0; + + + 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; + 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; +#endif + case ('b'): + if (negative) { +#ifdef VMS + uO.bflag = MAX(uO.bflag-negative,0); +#endif + negative = 0; /* do nothing: "-b" is default */ + } else { +#ifdef VMS + if (uO.aflag == 0) + ++uO.bflag; +#endif + 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; +#ifdef NATIVE + uO.aflag = 0; +#endif + } else { + uO.cflag = TRUE; +#ifdef NATIVE + uO.aflag = 2; /* so you can read it on the screen */ +#endif +#ifdef DLL + if (G.redirect_text) + G.redirect_data = 2; +#endif + } + 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; +#endif /* !CMS_MVS */ +#if (!defined(SFX) || defined(SFX_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 = 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) + ; + } + break; +#endif /* !SFX || SFX_EXDIR */ + 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; +#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; +#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; +#endif /* RISCOS || ACORN_FTYPE_NFS */ + 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; +#endif /* MACOS */ + case ('j'): /* junk pathnames/directory structure */ + if (negative) + uO.jflag = FALSE, negative = 0; + else + uO.jflag = TRUE; + break; +#if (defined(__BEOS__) || defined(MACOS)) + case ('J'): /* Junk BeOS or MacOS file attributes */ + if( negative ) { + uO.J_flag = FALSE, negative = 0; + } else { + uO.J_flag = TRUE; + } + break; +#endif /* __BEOS__ || MACOS */ +#ifndef SFX + 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 = FALSE, negative = 0; + else + uO.L_flag = TRUE; + break; +#endif /* !CMS_MVS */ +#ifdef MORE +#ifdef CMS_MVS + case ('m'): +#endif + 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; +#endif /* MORE */ + 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; +#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; +#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: 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 = 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) + ; + } + break; +#endif /* CRYPT */ + 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 */ +#endif +#ifdef DOS_FLX_OS2_W32 + case ('s'): /* spaces in filenames: allow by default */ + if (negative) + uO.sflag = FALSE, negative = 0; + else + uO.sflag = TRUE; + break; +#endif /* DOS_FLX_OS2_W32 */ + 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; +#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; +#endif /* !CMS_MVS */ +#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; +#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; +#endif /* !CMS_MVS */ + 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; + } +#endif /* SFX */ + break; +#if (defined(RESTORE_UIDGID) || defined(OS2_W32)) + 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 || OS2_W32 */ + 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; +#endif /* !SFX */ +#ifdef DOS_OS2_W32 + case ('$'): + if (negative) { + uO.volflag = MAX(uO.volflag-negative,0); + negative = 0; + } else + ++uO.volflag; + break; +#endif /* DOS_OS2_W32 */ + default: + error = TRUE; + break; + + } /* end switch */ + } /* end while (not end of argument string) */ + } /* end while (not done with switches) */ + +/*--------------------------------------------------------------------------- + Check for nonsensical combinations of options. + ---------------------------------------------------------------------------*/ + +#ifdef SFX +opts_done: /* yes, very ugly...but only used by UnZipSFX with -x xlist */ +#endif + + if ((uO.cflag && uO.tflag) || (uO.cflag && 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; +#endif + 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 ((argc-- == 0) || error) +#endif + { + *pargc = argc; + *pargv = argv; +#ifndef SFX + if (uO.vflag >= 2 && argc == -1) { /* "unzip -v" */ + show_version_info(__G); + return PK_OK; + } + if (!G.noargs && !error) + error = PK_PARAM; /* had options (not -h or -v) but no zipfile */ +#endif /* !SFX */ + return USAGE(error); + } + +#ifdef SFX + /* 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, PATCHLEVEL, 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; + + *pargc = argc; + *pargv = argv; + return PK_OK; + +} /* end function uz_opts() */ + + + + +/********************/ +/* Function usage() */ +/********************/ + +#ifdef SFX +# ifdef VMS +# define LOCAL "X. Quote uppercase options" +# endif +# ifdef UNIX +# define LOCAL "X" +# endif +# ifdef DOS_OS2_W32 +# define LOCAL "s$" +# endif +# ifdef FLEXOS +# define LOCAL "s" +# endif +# ifdef AMIGA +# define LOCAL "N" +# endif + /* Default for all other systems: */ +# ifndef LOCAL +# define LOCAL "" +# endif + +# ifdef MORE +# define SFXOPT1 "M" +# else +# define SFXOPT1 "" +# endif + +int usage(__G__ error) /* return PK-type error code */ + __GDEF + int error; +{ + Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner), + UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL, + LoadFarStringSmall(VersionDate))); + Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXOpts), + SFXOPT1, LOCAL)); +#ifdef BETA + Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n", + "SFX")); +#endif + + if (error) + return PK_PARAM; + else + return PK_COOL; /* just wanted usage screen: no error */ + +} /* end function usage() */ + + + + + +#else /* !SFX */ +# ifdef VMS +# define QUOT '\"' +# define QUOTS "\"" +# else +# define QUOT ' ' +# define QUOTS "" +# endif + +int usage(__G__ error) /* return PK-type error code */ + __GDEF + int error; +{ + int flag = (error? 1 : 0); + + +/*--------------------------------------------------------------------------- + Print either ZipInfo usage or UnZip usage, depending on incantation. + (Strings must be no longer than 512 bytes for Turbo C, apparently.) + ---------------------------------------------------------------------------*/ + + if (uO.zipinfo_mode) { + +#ifndef NO_ZIPINFO + + Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine1), + ZI_MAJORVER, ZI_MINORVER, PATCHLEVEL, BETALEVEL, + LoadFarStringSmall(VersionDate), + LoadFarStringSmall2(ZipInfoExample), QUOTS,QUOTS)); + Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine2))); + Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine3), + QUOT,QUOT, QUOT,QUOT, LoadFarStringSmall(ZipInfoUsageLine4))); +#ifdef VMS + Info(slide, flag, ((char *)slide, "\nRemember that non-lowercase\ + filespecs must be quoted in VMS (e.g., \"Makefile\").\n")); +#endif + +#endif /* !NO_ZIPINFO */ + + } else { /* UnZip mode */ + + Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine1), + UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL, + LoadFarStringSmall(VersionDate))); +#ifdef BETA + Info(slide, flag, ((char *)slide, LoadFarString(BetaVersion), "", "")); +#endif + + Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine2), + ZIPINFO_MODE_OPTION, LoadFarStringSmall(ZipInfoMode))); +#ifdef VMS + if (!error) /* maybe no command-line tail found; show extra help */ + Info(slide, flag, ((char *)slide, LoadFarString(VMSusageLine2b))); +#endif + + Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine3), + LoadFarStringSmall(local1))); + + Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine4), + QUOT,QUOT, QUOT,QUOT, LoadFarStringSmall(local2), QUOT,QUOT, + LoadFarStringSmall2(local3))); + + /* This is extra work for SMALL_MEM, but it will work since + * LoadFarStringSmall2 uses the same buffer. Remember, this + * is a hack. */ + Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine5), + LoadFarStringSmall(Example2), LoadFarStringSmall2(Example3), + LoadFarStringSmall2(Example3))); + + } /* end if (uO.zipinfo_mode) */ + + if (error) + return PK_PARAM; + else + return PK_COOL; /* just wanted usage screen: no error */ + +} /* end function usage() */ + +#endif /* ?SFX */ + + + + +#ifndef SFX + +/********************************/ +/* Function show_version_info() */ +/********************************/ + +static void show_version_info(__G) + __GDEF +{ + if (uO.qflag > 3) /* "unzip -vqqqq" */ + Info(slide, 0, ((char *)slide, "%d\n", + (UZ_MAJORVER*100 + UZ_MINORVER*10 + PATCHLEVEL))); + else { + char *envptr, *getenv(); + int numopts = 0; + + Info(slide, 0, ((char *)slide, LoadFarString(UnzipUsageLine1v), + UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL, + LoadFarStringSmall(VersionDate))); + Info(slide, 0, ((char *)slide, + LoadFarString(UnzipUsageLine2v))); + version(__G); + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptions))); +#ifdef ACORN_FTYPE_NFS + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(AcornFtypeNFS))); + ++numopts; +#endif +#ifdef ASM_CRC + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(AsmCRC))); + ++numopts; +#endif +#ifdef ASM_INFLATECODES + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(AsmInflateCodes))); + ++numopts; +#endif +#ifdef CHECK_VERSIONS + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Check_Versions))); + ++numopts; +#endif +#ifdef COPYRIGHT_CLEAN + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Copyright_Clean))); + ++numopts; +#endif +#ifdef DEBUG + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(UDebug))); + ++numopts; +#endif +#ifdef DEBUG_TIME + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(DebugTime))); + ++numopts; +#endif +#ifdef DLL + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Dll))); + ++numopts; +#endif +#ifdef DOSWILD + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(DosWild))); + ++numopts; +#endif +#ifdef LZW_CLEAN + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(LZW_Clean))); + ++numopts; +#endif +#ifndef MORE + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(No_More))); + ++numopts; +#endif +#ifdef NO_ZIPINFO + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(No_ZipInfo))); + ++numopts; +#endif +#ifdef NTSD_EAS + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(NTSDExtAttrib))); + ++numopts; +#endif +#ifdef OS2_EAS + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(OS2ExtAttrib))); + ++numopts; +#endif +#ifdef QLZIP + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(SMSExFldOnUnix))); + ++numopts; +#endif +#ifdef REENTRANT + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Reentrant))); + ++numopts; +#endif +#ifdef REGARGS + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(RegArgs))); + ++numopts; +#endif +#ifdef RETURN_CODES + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Return_Codes))); + ++numopts; +#endif +#ifdef SET_DIR_ATTRIB + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(SetDirAttrib))); + ++numopts; +#endif +#ifdef TIMESTAMP + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(TimeStamp))); + ++numopts; +#endif +#ifdef UNIXBACKUP + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(UnixBackup))); + ++numopts; +#endif +#ifdef USE_EF_UT_TIME + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Use_EF_UT_time))); + ++numopts; +#endif +#ifndef COPYRIGHT_CLEAN + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Use_Smith_Code))); + ++numopts; +#endif +#ifndef LZW_CLEAN + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Use_Unshrink))); + ++numopts; +#endif +#ifdef USE_VFAT + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(Use_VFAT_support))); + ++numopts; +#endif +#ifdef USE_ZLIB + sprintf((char *)(slide+256), LoadFarStringSmall(UseZlib), + ZLIB_VERSION, zlib_version); + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + (char *)(slide+256))); + ++numopts; +#endif +#ifdef VMS_TEXT_CONV + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(VmsTextConv))); + ++numopts; +#endif +#ifdef VMSCLI + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(VmsCLI))); + ++numopts; +#endif +#ifdef VMSWILD + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(VmsWild))); + ++numopts; +#endif +#if CRYPT +# ifdef PASSWD_FROM_STDIN + Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat), + LoadFarStringSmall(PasswdStdin))); +# endif + Info(slide, 0, ((char *)slide, LoadFarString(Decryption), + CR_MAJORVER, CR_MINORVER, CR_BETA_VER, + LoadFarStringSmall(CryptDate))); + ++numopts; +#endif /* CRYPT */ + if (numopts == 0) + Info(slide, 0, ((char *)slide, + LoadFarString(CompileOptFormat), + LoadFarStringSmall(None))); + + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptions))); + envptr = getenv(LoadFarStringSmall(EnvUnZip)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvUnZip), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); + envptr = getenv(LoadFarStringSmall(EnvUnZip2)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvUnZip2), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); + envptr = getenv(LoadFarStringSmall(EnvZipInfo)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvZipInfo), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); + envptr = getenv(LoadFarStringSmall(EnvZipInfo2)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvZipInfo2), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); +#ifndef __RSXNT__ +#ifdef __EMX__ + envptr = getenv(LoadFarStringSmall(EnvEMX)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvEMX), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); + envptr = getenv(LoadFarStringSmall(EnvEMXOPT)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvEMXOPT), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); +#endif /* __EMX__ */ +#if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2))) + envptr = getenv(LoadFarStringSmall(EnvGO32)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvGO32), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); + envptr = getenv(LoadFarStringSmall(EnvGO32TMP)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvGO32TMP), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); +#endif /* __GO32__ && !(__DJGPP__ >= 2) */ +#endif /* !__RSXNT__ */ +#ifdef RISCOS + envptr = getenv(LoadFarStringSmall(EnvUnZipExts)); + Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat), + LoadFarStringSmall(EnvUnZipExts), + (envptr == (char *)NULL || *envptr == 0)? + LoadFarStringSmall2(None) : envptr)); +#endif /* RISCOS */ + } +} /* end function show_version() */ + +#endif /* !SFX */ +#endif /* !WINDLL */ diff --git a/utils/Install/sfxzip/unzipstb.c b/utils/Install/sfxzip/unzipstb.c new file mode 100644 index 0000000000..6ca238a89f --- /dev/null +++ b/utils/Install/sfxzip/unzipstb.c @@ -0,0 +1,48 @@ +/*--------------------------------------------------------------------------- + + unzipstb.c + + Simple stub function for UnZip DLL (or shared library, whatever); does + exactly the same thing as normal UnZip, except for additional printf()s + of various version numbers, solely as a demonstration of what can/should + be checked when using the DLL. (If major version numbers ever differ, + assume program is incompatible with DLL--especially if DLL version is + older. This is not likely to be a problem with *this* simple program, + but most user programs will be much more complex.) + + ---------------------------------------------------------------------------*/ + +#include +#include "unzip.h" +#include "version.h" + +int main(int argc, char *argv[]) +{ + static UzpVer *pVersion; /* no pervert jokes, please... */ + + pVersion = UzpVersion(); + + printf("UnZip stub: checking version numbers (DLL is dated %s)\n", + pVersion->date); + printf(" UnZip versions: expecting %d.%d%d, using %d.%d%d%s\n", + UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, pVersion->unzip.major, + pVersion->unzip.minor, pVersion->unzip.patchlevel, pVersion->betalevel); + printf(" ZipInfo versions: expecting %d.%d%d, using %d.%d%d\n", + ZI_MAJORVER, ZI_MINORVER, PATCHLEVEL, pVersion->zipinfo.major, + pVersion->zipinfo.minor, pVersion->zipinfo.patchlevel); + +/* + D2_M*VER and os2dll.* are obsolete, though retained for compatibility: + + printf(" OS2 DLL versions: expecting %d.%d%d, using %d.%d%d\n", + D2_MAJORVER, D2_MINORVER, PATCHLEVEL, pVersion->os2dll.major, + pVersion->os2dll.minor, pVersion->os2dll.patchlevel); + */ + + if (pVersion->flag & 2) + printf(" using zlib version %s\n", pVersion->zlib_version); + printf("\n"); + + /* call the actual UnZip routine (string-arguments version) */ + return UzpMain(argc, argv); +} diff --git a/utils/Install/sfxzip/win32.c b/utils/Install/sfxzip/win32.c new file mode 100644 index 0000000000..f50ee5f9dd --- /dev/null +++ b/utils/Install/sfxzip/win32.c @@ -0,0 +1,2390 @@ +/*--------------------------------------------------------------------------- + + win32.c + + 32-bit Windows-specific (NT/95) routines for use with Info-ZIP's UnZip 5.3 + and later. + + Contains: GetLoadPath() + Opendir() + Readdir() + Closedir() + process_defer_NT() process any deferred items + SetSD() set security descriptor on file + EvalExtraFields() evaluate and process and extra field NOW + IsWinNT() indicate type of WIN32 platform + test_NTSD() test integrity of NT security data + utime2FileTime() + FStampIsLocTime() + FileTime2utime() + VFatFileTime2utime() + UTCtime2Localtime() + NTtzbugWorkaround() + getNTfiletime() + close_outfile() + stamp_file() + isfloppy() + NTQueryVolInfo() + IsVolumeOldFAT() + do_wild() + mapattr() + mapname() + map2fat() + checkdir() + version() + zstat_win32() + getch_win32() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" +#include /* must be AFTER unzip.h to avoid struct G problems */ +#ifdef __RSXNT__ +# include "rsxntwin.h" +#endif +#include "nt.h" + +#ifndef FUNZIP /* most of this file is not used with fUnZip */ + +#if (defined(__GO32__) || defined(__EMX__) || defined(__CYGWIN32__)) +# define MKDIR(path,mode) mkdir(path,mode) +#else +# define MKDIR(path,mode) mkdir(path) +#endif + +#ifdef HAVE_WORKING_DIRENT_H +# undef HAVE_WORKING_DIRENT_H +#endif +/* The emxrtl dirent support of (__GO32__ || __EMX__) converts to lowercase! */ +#if defined(__CYGWIN32__) +# define HAVE_WORKING_DIRENT_H +#endif + +#ifndef SFX +# ifdef HAVE_WORKING_DIRENT_H +# include /* use readdir() */ +# define zdirent dirent +# define zDIR DIR +# define Opendir opendir +# define Readdir readdir +# define Closedir closedir +# else /* !HAVE_WORKING_DIRENT_H */ + typedef struct zdirent { + char reserved [21]; + char ff_attrib; + short ff_ftime; + short ff_fdate; + long size; + char d_name[MAX_PATH]; + int d_first; + HANDLE d_hFindFile; + } zDIR; + + static zDIR *Opendir (const char *n); + static struct zdirent *Readdir (zDIR *d); + static void Closedir (zDIR *d); +# endif /* ?HAVE_WORKING_DIRENT_H */ +#endif /* !SFX */ + + +/* Function prototypes */ +#ifdef NTSD_EAS + static int SetSD(__GPRO__ char *path, PVOLUMECAPS VolumeCaps, + uch *eb_ptr, unsigned eb_len); + static int EvalExtraFields(__GPRO__ char *path, uch *ef_ptr, + unsigned ef_len); +#endif + +#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND) || \ + defined(TIMESTAMP)) + static void utime2FileTime(time_t ut, FILETIME *pft); + static int FStampIsLocTime(__GPRO__ const char *path); +#endif /* USE_EF_UT_TIME || NT_TZBUG_WORKAROUND || TIMESTAMP */ +#ifdef NT_TZBUG_WORKAROUND + static int FileTime2utime(const FILETIME *pft, time_t *ut); +#ifdef W32_STAT_BANDAID + static int VFatFileTime2utime(const FILETIME *pft, time_t *ut); +#endif + static time_t UTCtime2Localtime(time_t utctime); + static void NTtzbugWorkaround(time_t ut, FILETIME *pft); +#endif /* NT_TZBUG_WORKAROUND */ + +static int getNTfiletime (__GPRO__ FILETIME *pModFT, FILETIME *pAccFT, + FILETIME *pCreFT); +static int isfloppy (int nDrive); +static int NTQueryVolInfo (__GPRO__ const char *name); +static int IsVolumeOldFAT (__GPRO__ const char *name); +static void map2fat (char *pathcomp, char **pEndFAT); + + +#ifdef __MINGW32__ + int _CRT_glob = 0; /* suppress command line globbing by C RTL */ +#endif + +/* static int created_dir; */ /* used by mapname(), checkdir() */ +/* static int renamed_fullpath; */ /* ditto */ +/* static int fnlen; */ /* ditto */ +/* static unsigned nLabelDrive; */ /* ditto */ + +extern char Far TruncNTSD[]; /* in extract.c */ + + + +#ifdef SFX + +/**************************/ +/* Function GetLoadPath() */ +/**************************/ + +char *GetLoadPath(__GPRO) +{ +#ifdef MSC + extern char *_pgmptr; + return _pgmptr; + +#else /* use generic API call */ + + GetModuleFileName(NULL, G.filename, FILNAMSIZ-1); + _ISO_INTERN(G.filename); /* translate to codepage of C rtl's stdio */ + return G.filename; +#endif + +} /* end function GetLoadPath() */ + + + + + +#else /* !SFX */ + +#ifndef HAVE_WORKING_DIRENT_H + +/**********************/ /* Borrowed from ZIP 2.0 sources */ +/* Function Opendir() */ /* Difference: no special handling for */ +/**********************/ /* hidden or system files. */ + +static zDIR *Opendir(n) + const char *n; /* directory to open */ +{ + zDIR *d; /* malloc'd return value */ + char *p; /* malloc'd temporary string */ + WIN32_FIND_DATA fd; + extent len = strlen(n); + + /* Start searching for files in directory n */ + + if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL || + (p = malloc(strlen(n) + 5)) == NULL) + { + if (d != (zDIR *)NULL) + free((void *)d); + return (zDIR *)NULL; + } + INTERN_TO_ISO(n, p); + if (len > 0) { + if (p[len-1] == ':') + p[len++] = '.'; /* x: => x:. */ + else if (p[len-1] == '/' || p[len-1] == '\\') + --len; /* foo/ => foo */ + } + strcpy(p+len, "/*"); + + if (INVALID_HANDLE_VALUE == (d->d_hFindFile = FindFirstFile(p, &fd))) { + free((zvoid *)d); + free((zvoid *)p); + return NULL; + } + strcpy(d->d_name, fd.cFileName); + + free((zvoid *)p); + d->d_first = 1; + return d; + +} /* end of function Opendir() */ + + + + +/**********************/ /* Borrowed from ZIP 2.0 sources */ +/* Function Readdir() */ /* Difference: no special handling for */ +/**********************/ /* hidden or system files. */ + +static 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 + { + WIN32_FIND_DATA fd; + + if ( !FindNextFile(d->d_hFindFile, &fd) ) + return NULL; + + ISO_TO_INTERN(fd.cFileName, d->d_name); + } + return (struct zdirent *)d; + +} /* end of function Readdir() */ + + + + +/***********************/ +/* Function Closedir() */ /* Borrowed from ZIP 2.0 sources */ +/***********************/ + +static void Closedir(d) + zDIR *d; /* directory stream to close */ +{ + FindClose(d->d_hFindFile); + free(d); +} + +#endif /* !HAVE_WORKING_DIRENT_H */ +#endif /* ?SFX */ + + + + +#ifdef NTSD_EAS + +/*********************************/ +/* Function process_defer_NT() */ +/*********************************/ + +void process_defer_NT(__G) + __GDEF +{ + /* process deferred items */ + + DWORD dir, bytes; + DWORD dirfail, bytesfail; + + ProcessDefer(&dir, &bytes, &dirfail, &bytesfail); + + if (!uO.tflag && (uO.qflag < 2)) { + if (dir) + Info(slide, 0, ((char *)slide, + " updated: %lu directory entries with %lu bytes security", + (ulg)dir, (ulg)bytes)); + if (dirfail) + Info(slide, 0, ((char *)slide, + " failed: %lu directory entries with %lu bytes security", + (ulg)dirfail, (ulg)bytesfail)); + } +} + + + +/**********************/ +/* Function SetSD() */ /* return almost-PK errors */ +/**********************/ + +static int SetSD(__G__ path, VolumeCaps, eb_ptr, eb_len) + __GDEF + char *path; + PVOLUMECAPS VolumeCaps; + uch *eb_ptr; + unsigned eb_len; +{ + ulg ntsd_ucSize; + uch *security_data; + int error; + + if (eb_ptr == NULL || eb_len < EB_NTSD_L_LEN) + return PK_OK; /* not a valid NTSD extra field: assume OK */ + + /* check if we know how to handle this version */ + if (*(eb_ptr + (EB_HEADSIZE+EB_NTSD_VERSION)) > (uch)EB_NTSD_MAX_VER) + return PK_OK; + + ntsd_ucSize = makelong(eb_ptr + (EB_HEADSIZE+EB_UCSIZE_P)); + if (ntsd_ucSize > 0L && eb_len <= (EB_NTSD_L_LEN + EB_CMPRHEADLEN)) + return IZ_EF_TRUNC; /* no compressed data! */ + + /* allocate storage for uncompressed data */ + security_data = (uch *)malloc((extent)ntsd_ucSize); + if (security_data == (uch *)NULL) + return PK_MEM4; + + error = memextract(__G__ security_data, ntsd_ucSize, + (eb_ptr + (EB_HEADSIZE+EB_NTSD_L_LEN)), (ulg)(eb_len - EB_NTSD_L_LEN)); + + if (error == PK_OK) { + if (SecuritySet(path, VolumeCaps, security_data)) { + error = PK_COOL; + if (!uO.tflag && (uO.qflag < 2) && + (!(VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))) + Info(slide, 0, ((char *)slide, " (%ld bytes security)", + ntsd_ucSize)); + } + } + + free(security_data); + return error; +} + + + + +/********************************/ /* scan extra fields for something */ +/* Function EvalExtraFields() */ /* we happen to know */ +/********************************/ + +static int EvalExtraFields(__G__ path, ef_ptr, ef_len) + __GDEF + char *path; + uch *ef_ptr; + unsigned ef_len; +{ + int rc = PK_OK; + + if (!uO.X_flag) + return PK_OK; /* user said don't process ACLs; for now, no other + extra block types are handled here */ + + while (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)) { + /* discovered some extra field inconsistency! */ + Trace((stderr, + "EvalExtraFields: block length %u > rest ef_size %u\n", eb_len, + ef_len - EB_HEADSIZE)); + break; + } + + switch (eb_id) + { + /* process security descriptor extra data if: + Caller is WinNT AND + Target local/remote drive supports acls AND + Target file is not a directory (else we defer processing + until later) + */ + case EF_NTSD: + if (IsWinNT()) { + VOLUMECAPS VolumeCaps; + + /* provide useful input */ + VolumeCaps.dwFileAttributes = G.pInfo->file_attr; + VolumeCaps.bUsePrivileges = (uO.X_flag > 1); + + /* check target volume capabilities - just fall through + * and try if fail */ + if (GetVolumeCaps(G.rootpath, path, &VolumeCaps) && + !(VolumeCaps.dwFileSystemFlags & FS_PERSISTENT_ACLS)) + { + rc = PK_OK; + break; + } + rc = SetSD(__G__ path, &VolumeCaps, ef_ptr, eb_len); + } else + rc = PK_OK; + break; + +#if 0 + /* perhaps later we can add support for unzipping OS/2 EAs to NT */ + case EF_OS2: + rc = SetEAs(__G__ path, ef_ptr); + break; + + case EF_PKUNIX: + case EF_IZUNIX: + case EF_IZUNIX2: + case EF_TIME: + break; /* handled elsewhere */ +#else /* ! 0 */ +#ifdef DEBUG + case EF_AV: + case EF_OS2: + case EF_PKVMS: + case EF_PKW32: + case EF_PKUNIX: + case EF_IZVMS: + case EF_IZUNIX: + case EF_IZUNIX2: + case EF_TIME: + case EF_MAC3: + case EF_JLMAC: + case EF_ZIPIT: + case EF_VMCMS: + case EF_MVS: + case EF_ACL: + case EF_BEOS: + case EF_QDOS: + case EF_AOSVS: + case EF_SPARK: + case EF_MD5: + case EF_ASIUNIX: + break; /* shut up for other known e.f. blocks */ +#endif /* DEBUG */ +#endif /* ? 0 */ + + default: + Trace((stderr, + "EvalExtraFields: unknown extra field block, ID=%u\n", + eb_id)); + break; + } + + ef_ptr += (eb_len + EB_HEADSIZE); + ef_len -= (eb_len + EB_HEADSIZE); + + if (rc != PK_OK) + break; + } + + return rc; +} + + + + +#ifndef SFX + +/**************************/ +/* Function test_NTSD() */ /* returns PK_WARN when NTSD data is invalid */ +/**************************/ + +#ifdef __BORLANDC__ +/* Turn off warning about not using all parameters for this function only */ +#pragma argsused +#endif +int test_NTSD(__G__ eb, eb_size, eb_ucptr, eb_ucsize) + __GDEF + uch *eb; + unsigned eb_size; + uch *eb_ucptr; + ulg eb_ucsize; +{ + int r = PK_OK; + + if (!ValidateSecurity(eb_ucptr)) + r = PK_WARN; + return r; + +} /* end function test_NTSD() */ + +#endif /* !SFX */ +#endif /* NTSD_EAS */ + + + + +/**********************/ +/* Function IsWinNT() */ +/**********************/ + +int IsWinNT(void) /* returns TRUE if real NT, FALSE if Win95 or Win32s */ +{ + static DWORD g_PlatformId = 0xFFFFFFFF; /* saved platform indicator */ + + if (g_PlatformId == 0xFFFFFFFF) { + /* note: GetVersionEx() doesn't exist on WinNT 3.1 */ + if (GetVersion() < 0x80000000) + g_PlatformId = TRUE; + else + g_PlatformId = FALSE; + } + return (int)g_PlatformId; +} + + +/* DEBUG_TIME insertion: */ +#ifdef DEBUG_TIME +static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft); + +static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft) +{ + SYSTEMTIME w32tm; + int rval; + + rval = FileTimeToSystemTime(pft, &w32tm); + if (!rval) { + fprintf(hdo, "%s\n %08lX,%08lX (%s) -> Conversion failed !!!\n", + TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime), + (isloc ? "local" : "UTC")); + } else { + fprintf(hdo, "%s\n %08lx,%08lx -> %04u-%02u-%02u, %02u:%02u:%02u %s\n", + TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime), + w32tm.wYear, w32tm.wMonth, w32tm.wDay, w32tm.wHour, + w32tm.wMinute, w32tm.wSecond, (isloc ? "local" : "UTC")); + } + return rval; +} +#define FTTrace(x) show_NTFileTime x +#else +#define FTTrace(x) +#endif /* DEBUG_TIME */ +/* end of TIME_DEBUG insertion */ + +#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND) || \ + defined(TIMESTAMP)) + +#if ((defined(__GNUC__) || defined(ULONG_LONG_MAX)) && !defined(HAVE_INT64)) + typedef long long LLONG64; + typedef unsigned long long ULLNG64; +# define HAVE_INT64 +#endif +#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1100) && !defined(HAVE_INT64)) + typedef __int64 LLONG64; + typedef unsigned __int64 ULLNG64; +# define HAVE_INT64 +#endif +#if (defined(_MSC_VER) && (_MSC_VER >= 1100) && !defined(HAVE_INT64)) + typedef __int64 LLONG64; + typedef unsigned __int64 ULLNG64; +# define HAVE_INT64 +#endif + +/*****************************/ +/* Function utime2FileTime() */ /* convert Unix time_t format into the */ +/*****************************/ /* form used by SetFileTime() in NT/95 */ + +#define UNIX_TIME_ZERO_HI 0x019DB1DEUL +#define UNIX_TIME_ZERO_LO 0xD53E8000UL +#define NT_QUANTA_PER_UNIX 10000000L + +static void utime2FileTime(time_t ut, FILETIME *pft) +{ +#ifdef HAVE_INT64 + ULLNG64 NTtime; + + /* NT_QUANTA_PER_UNIX is small enough so that "ut * NT_QUANTA_PER_UNIX" + * cannot overflow in 64-bit signed calculation, regardless wether "ut" + * is signed or unsigned. */ + NTtime = ((LLONG64)ut * NT_QUANTA_PER_UNIX) + + ((ULLNG64)UNIX_TIME_ZERO_LO + ((ULLNG64)UNIX_TIME_ZERO_HI << 32)); + pft->dwLowDateTime = (DWORD)NTtime; + pft->dwHighDateTime = (DWORD)(NTtime >> 32); + +#else /* !HAVE_INT64 (64-bit integer arithmetics may not be supported) */ + unsigned int b1, b2, carry = 0; + unsigned long r0, r1, r2, r3; + long r4; /* signed, to catch environments with signed time_t */ + + b1 = ut & 0xFFFF; + b2 = (ut >> 16) & 0xFFFF; /* if ut is over 32 bits, too bad */ + r1 = b1 * (NT_QUANTA_PER_UNIX & 0xFFFF); + r2 = b1 * (NT_QUANTA_PER_UNIX >> 16); + r3 = b2 * (NT_QUANTA_PER_UNIX & 0xFFFF); + r4 = b2 * (NT_QUANTA_PER_UNIX >> 16); + r0 = (r1 + (r2 << 16)) & 0xFFFFFFFFL; + if (r0 < r1) + carry++; + r1 = r0; + r0 = (r0 + (r3 << 16)) & 0xFFFFFFFFL; + if (r0 < r1) + carry++; + pft->dwLowDateTime = r0 + UNIX_TIME_ZERO_LO; + if (pft->dwLowDateTime < r0) + carry++; + pft->dwHighDateTime = r4 + (r2 >> 16) + (r3 >> 16) + + UNIX_TIME_ZERO_HI + carry; +#endif /* ?HAVE_INT64 */ + +} /* end function utime2FileTime() */ + + + +/******************************/ +/* Function FStampIsLocTime() */ +/******************************/ + +static int FStampIsLocTime(__GPRO__ const char *path) +{ + return (NTQueryVolInfo(__G__ path) ? G.lastVolLocTim : FALSE); +} + +#endif /* USE_EF_UT_TIME || NT_TZBUG_WORKAROUND || TIMESTAMP */ + + + +#ifndef NT_TZBUG_WORKAROUND +# define UTIME_BOUNDCHECK_1(utimval) \ + if (fs_uses_loctime) { \ + utime_dosmin = dos_to_unix_time(DOSTIME_MINIMUM); \ + if ((ulg)utimval < (ulg)utime_dosmin) \ + utimval = utime_dosmin; \ + } +# define UTIME_BOUNDCHECK_N(utimval) \ + if (fs_uses_loctime && ((ulg)utimval < (ulg)utime_dosmin)) \ + utimval = utime_dosmin; +# define NT_TZBUG_PRECOMPENSATE(ut, pft) + +#else /* NT_TZBUG_WORKAROUND */ +# define UNIX_TIME_UMAX_HI 0x0236485EUL +# define UNIX_TIME_UMAX_LO 0xD4A5E980UL +# define UNIX_TIME_SMIN_HI 0x0151669EUL +# define UNIX_TIME_SMIN_LO 0xD53E8000UL +# define UNIX_TIME_SMAX_HI 0x01E9FD1EUL +# define UNIX_TIME_SMAX_LO 0xD4A5E980UL +# define UTIME_1980_JAN_01_00_00 315532800L +# define UTIME_BOUNDCHECK_1(utimval) +# define UTIME_BOUNDCHECK_N(utimval) +# define NT_TZBUG_PRECOMPENSATE(ut, pft) \ + if (fs_uses_loctime) NTtzbugWorkaround(ut, pft); + + /* nonzero if `y' is a leap year, else zero */ +# define leap(y) (((y)%4 == 0 && (y)%100 != 0) || (y)%400 == 0) + /* number of leap years from 1970 to `y' (not including `y' itself) */ +# define nleap(y) (((y)-1969)/4 - ((y)-1901)/100 + ((y)-1601)/400) + +extern ZCONST ush ydays[]; /* defined in fileio.c */ + +/*****************************/ +/* Function FileTime2utime() */ +/*****************************/ + +static int FileTime2utime(const FILETIME *pft, time_t *ut) +{ +#ifdef HAVE_INT64 + ULLNG64 NTtime; + + NTtime = ((ULLNG64)pft->dwLowDateTime + + ((ULLNG64)pft->dwHighDateTime << 32)); + + /* underflow and overflow handling */ +#ifdef CHECK_UTIME_SIGNED_UNSIGNED + if ((time_t)0x80000000L < (time_t)0L) + { + if (NTtime < ((ULLNG64)UNIX_TIME_SMIN_LO + + ((ULLNG64)UNIX_TIME_SMIN_HI << 32))) { + *ut = (time_t)LONG_MIN; + return FALSE; + } + if (NTtime > ((ULLNG64)UNIX_TIME_SMAX_LO + + ((ULLNG64)UNIX_TIME_SMAX_HI << 32))) { + *ut = (time_t)LONG_MAX; + return FALSE; + } + } + else +#endif /* CHECK_UTIME_SIGNED_UNSIGNED */ + { + if (NTtime < ((ULLNG64)UNIX_TIME_ZERO_LO + + ((ULLNG64)UNIX_TIME_ZERO_HI << 32))) { + *ut = (time_t)0; + return FALSE; + } + if (NTtime > ((ULLNG64)UNIX_TIME_UMAX_LO + + ((ULLNG64)UNIX_TIME_UMAX_HI << 32))) { + *ut = (time_t)ULONG_MAX; + return FALSE; + } + } + + NTtime -= ((ULLNG64)UNIX_TIME_ZERO_LO + + ((ULLNG64)UNIX_TIME_ZERO_HI << 32)); + *ut = (time_t)(NTtime / (unsigned long)NT_QUANTA_PER_UNIX); + return TRUE; +#else /* !HAVE_INT64 (64-bit integer arithmetics may not be supported) */ + time_t days; + SYSTEMTIME w32tm; + + /* underflow and overflow handling */ +#ifdef CHECK_UTIME_SIGNED_UNSIGNED + if ((time_t)0x80000000L < (time_t)0L) + { + if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) || + ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) && + (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) { + *ut = (time_t)LONG_MIN; + return FALSE; + if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) || + ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) && + (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) { + *ut = (time_t)LONG_MAX; + return FALSE; + } + } + else +#endif /* CHECK_UTIME_SIGNED_UNSIGNED */ + { + if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) || + ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) && + (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) { + *ut = (time_t)0; + return FALSE; + } + if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) || + ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) && + (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) { + *ut = (time_t)ULONG_MAX; + return FALSE; + } + } + + FileTimeToSystemTime(pft, &w32tm); + + /* set `days' to the number of days into the year */ + days = w32tm.wDay - 1 + ydays[w32tm.wMonth-1] + + (w32tm.wMonth > 2 && leap (w32tm.wYear)); + + /* now set `days' to the number of days since 1 Jan 1970 */ + days += 365 * (time_t)(w32tm.wYear - 1970) + + (time_t)(nleap(w32tm.wYear)); + + *ut = (time_t)(86400L * days + 3600L * (time_t)w32tm.wHour + + (time_t)(60 * w32tm.wMinute + w32tm.wSecond)); + return TRUE; +#endif /* ?HAVE_INT64 */ +} /* end function FileTime2utime() */ + + + +#ifdef W32_STAT_BANDAID +/*********************************/ +/* Function VFatFileTime2utime() */ +/*********************************/ + +static int VFatFileTime2utime(const FILETIME *pft, time_t *ut) +{ + FILETIME lft; +#ifndef HAVE_MKTIME + WORD wDOSDate, wDOSTime; +#else + SYSTEMTIME w32tm; + struct tm ltm; +#endif + + FileTimeToLocalFileTime(pft, &lft); + FTTrace((stdout, "VFatFT2utime, feed for mktime()", 1, &lft)); +#ifndef HAVE_MKTIME + /* This version of the FILETIME-to-UNIXTIME conversion function + * uses DOS-DATE-TIME format as intermediate stage. For modification + * and access times, this is no problem. But, the extra fine resolution + * of the VFAT-stored creation time gets lost. + */ + FileTimeToDosDateTime(&lft, &wDOSDate, &wDOSTime); + TTrace((stdout,"DosDateTime is %04u-%02u-%02u %02u:%02u:%02u\n", + (unsigned)((wDOSDate>>9)&0x7f)+1980,(unsigned)((wDOSDate>>5)&0x0f), + (unsigned)(wDOSDate&0x1f),(unsigned)((wDOSTime>>11)&0x1f), + (unsigned)((wDOSTime>>5)&0x3f),(unsigned)((wDOSTime<<1)&0x3e))); + *ut = dos_to_unix_time(((ulg)wDOSDate << 16) | (ulg)wDOSTime); + + /* a cheap error check: dos_to_unix_time() only returns an odd time + * when clipping at maximum time_t value. DOS_DATE_TIME values have + * a resolution of 2 seconds and are therefore even numbers. + */ + return (((*ut)&1) == (time_t)0); +#else /* HAVE_MKTIME */ + FileTimeToSystemTime(&lft, &w32tm); + /* underflow and overflow handling */ + /* TODO: The range checks are not accurate, the actual limits may + * be off by one daylight-saving-time shift (typically 1 hour), + * depending on the current state of "is_dst". + */ +#ifdef CHECK_UTIME_SIGNED_UNSIGNED + if ((time_t)0x80000000L < (time_t)0L) + { + if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) || + ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) && + (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) { + *ut = (time_t)LONG_MIN; + return FALSE; + if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) || + ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) && + (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) { + *ut = (time_t)LONG_MAX; + return FALSE; + } + } + else +#endif /* CHECK_UTIME_SIGNED_UNSIGNED */ + { + if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) || + ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) && + (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) { + *ut = (time_t)0; + return FALSE; + } + if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) || + ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) && + (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) { + *ut = (time_t)ULONG_MAX; + return FALSE; + } + } + ltm.tm_year = w32tm.wYear - 1900; + ltm.tm_mon = w32tm.wMonth - 1; + ltm.tm_mday = w32tm.wDay; + ltm.tm_hour = w32tm.wHour; + ltm.tm_min = w32tm.wMinute; + ltm.tm_sec = w32tm.wSecond; + ltm.tm_isdst = -1; /* let mktime determine if DST is in effect */ + *ut = mktime(<m); + + /* a cheap error check: mktime returns "(time_t)-1L" on conversion errors. + * Normally, we would have to apply a consistency check because "-1" + * could also be a valid time. But, it is quite unlikely to read back odd + * time numbers from file systems that store time stamps in DOS format. + * (The only known exception is creation time on VFAT partitions.) + */ + return (*ut != (time_t)-1L); +#endif /* ?HAVE_MKTIME */ + +} /* end function VFatFileTime2utime() */ +#endif /* W32_STAT_BANDAID */ + + + +/********************************/ +/* Function UTCtime2Localtime() */ /* borrowed from Zip's mkgmtime() */ +/********************************/ + +static time_t UTCtime2Localtime(time_t utctime) +{ + time_t utc = utctime; + struct tm *tm; + unsigned years, months, days, hours, minutes, seconds; + + +#ifdef __BORLANDC__ /* Borland C++ 5.x crashes when trying to reference tm */ + if (utc < UTIME_1980_JAN_01_00_00) + utc = UTIME_1980_JAN_01_00_00; +#endif + tm = localtime(&utc); + if (tm == (struct tm *)NULL) + /* localtime() did not accept given utc time value; as an emergency + exit, the unconverted utctime value is returned */ + return utctime; + + years = tm->tm_year + 1900; /* year - 1900 -> year */ + months = tm->tm_mon; /* 0..11 */ + days = tm->tm_mday - 1; /* 1..31 -> 0..30 */ + hours = tm->tm_hour; /* 0..23 */ + minutes = tm->tm_min; /* 0..59 */ + seconds = tm->tm_sec; /* 0..61 in ANSI C */ + + /* set `days' to the number of days into the year */ + days += ydays[months] + (months > 1 && leap(years)); + + /* now set `days' to the number of days since 1 Jan 1970 */ + days += 365 * (years - 1970) + nleap(years); + + return (time_t)(86400L * (ulg)days + 3600L * (ulg)hours + + (ulg)(60 * minutes + seconds)); + +} /* end function UTCtime2Localtime() */ + + + +/********************************/ +/* Function NTtzbugWorkaround() */ +/********************************/ + +static void NTtzbugWorkaround(time_t ut, FILETIME *pft) +{ + FILETIME C_RTL_locft, NTAPI_locft; + time_t ux_loctime = UTCtime2Localtime(ut); + + /* This routine is only used when the target file system stores time- + * stamps as local time in MSDOS format. Thus we make sure that the + * resulting timestamp is within the range of MSDOS date-time values. */ + if (ux_loctime < UTIME_1980_JAN_01_00_00) + ux_loctime = UTIME_1980_JAN_01_00_00; + + utime2FileTime(ux_loctime, &C_RTL_locft); + if (!FileTimeToLocalFileTime(pft, &NTAPI_locft)) + return; + else { + long time_shift_l, time_shift_h; + int carry = 0; + + time_shift_l = C_RTL_locft.dwLowDateTime - NTAPI_locft.dwLowDateTime; + if (C_RTL_locft.dwLowDateTime < NTAPI_locft.dwLowDateTime) + carry--; + time_shift_h = C_RTL_locft.dwHighDateTime - NTAPI_locft.dwHighDateTime; + pft->dwLowDateTime += time_shift_l; + if (pft->dwLowDateTime < (ulg)time_shift_l) + carry++; + pft->dwHighDateTime += time_shift_h + carry; + TTrace((stdout, "FileTime shift: %08lx:%08lx\n", + time_shift_h+carry,time_shift_l)); + } +} /* end function NTtzbugWorkaround() */ + +#endif /* ?NT_TZBUG_WORKAROUND */ + + + +/****************************/ /* Get the file time in a format that */ +/* Function getNTfiletime() */ /* can be used by SetFileTime() in NT */ +/****************************/ + +static int getNTfiletime(__G__ pModFT, pAccFT, pCreFT) + __GDEF + FILETIME *pModFT; + FILETIME *pAccFT; + FILETIME *pCreFT; +{ +#ifdef NT_TZBUG_WORKAROUND + time_t ux_modtime; +#else /* !NT_TZBUG_WORKAROUND */ + FILETIME locft; /* 64-bit value made up of two 32-bit [low & high] */ + WORD wDOSDate; /* for converting from DOS date to Windows NT */ + WORD wDOSTime; +#endif /* ?NT_TZBUG_WORKAROUND */ +#ifdef USE_EF_UT_TIME + unsigned eb_izux_flg; + iztimes z_utime; /* struct for Unix-style actime & modtime, + creatime */ +#endif +#if (defined(USE_EF_UT_TIME) && !defined(NT_TZBUG_WORKAROUND)) + time_t utime_dosmin; +# endif +#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND)) + int fs_uses_loctime = FStampIsLocTime(__G__ G.filename); +#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, "getNTfiletime: Unix e.f. modif. time = %lu\n", + z_utime.mtime)); + UTIME_BOUNDCHECK_1(z_utime.mtime) + utime2FileTime(z_utime.mtime, pModFT); + NT_TZBUG_PRECOMPENSATE(z_utime.mtime, pModFT) + if (eb_izux_flg & EB_UT_FL_ATIME) { + UTIME_BOUNDCHECK_N(z_utime.atime) + utime2FileTime(z_utime.atime, pAccFT); + NT_TZBUG_PRECOMPENSATE(z_utime.atime, pAccFT) + } + if (eb_izux_flg & EB_UT_FL_CTIME) { + UTIME_BOUNDCHECK_N(z_utime.ctime) + utime2FileTime(z_utime.ctime, pCreFT); + NT_TZBUG_PRECOMPENSATE(z_utime.ctime, pCreFT) + } + return (int)eb_izux_flg; + } +#endif /* USE_EF_UT_TIME */ +#ifdef NT_TZBUG_WORKAROUND + ux_modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime); + utime2FileTime(ux_modtime, pModFT); + NT_TZBUG_PRECOMPENSATE(ux_modtime, pModFT) +#else /* !NT_TZBUG_WORKAROUND */ + + wDOSTime = (WORD)(G.lrec.last_mod_dos_datetime); + wDOSDate = (WORD)(G.lrec.last_mod_dos_datetime >> 16); + + /* The DosDateTimeToFileTime() function converts a DOS date/time + * into a 64-bit Windows NT file time */ + if (!DosDateTimeToFileTime(wDOSDate, wDOSTime, &locft)) + { + Info(slide, 0, ((char *)slide, "DosDateTime failed: %d\n", + (int)GetLastError())); + return 0; + } + if (!LocalFileTimeToFileTime(&locft, pModFT)) + { + Info(slide, 0, ((char *)slide, "LocalFileTime failed: %d\n", + (int)GetLastError())); + *pModFT = locft; + } +#endif /* ?NT_TZBUG_WORKAROUND */ + *pAccFT = *pModFT; + return (EB_UT_FL_MTIME | EB_UT_FL_ATIME); + +} /* end function getNTfiletime() */ + + + + +/****************************/ +/* Function close_outfile() */ +/****************************/ + +void close_outfile(__G) + __GDEF +{ + FILETIME Modft; /* File time type defined in NT, `last modified' time */ + FILETIME Accft; /* NT file time type, `last access' time */ + FILETIME Creft; /* NT file time type, `file creation' time */ + HANDLE hFile; /* File handle defined in NT */ + int gotTime; +#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ + char *ansi_name = (char *)alloca(strlen(G.filename) + 1); + + INTERN_TO_ISO(G.filename, ansi_name); +# define Ansi_Fname ansi_name +#else +# define Ansi_Fname G.filename +#endif + + /* Close the file and then re-open it using the Win32 + * CreateFile call, so that the file can be created + * with GENERIC_WRITE access, otherwise the SetFileTime + * call will fail. */ + fclose(G.outfile); + + /* don't set the time stamp and attributes on standard output */ + if (uO.cflag) + return; + + gotTime = getNTfiletime(__G__ &Modft, &Accft, &Creft); + + /* open a handle to the file before processing extra fields; + we do this in case new security on file prevents us from updating + time stamps */ + hFile = CreateFile(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + /* sfield@microsoft.com: set attributes before time in case we decide to + support other filetime members later. This also allows us to apply + attributes before the security is changed, which may prevent this + from succeeding otherwise. Also, since most files don't have + any interesting attributes, only change them if something other than + FILE_ATTRIBUTE_ARCHIVE appears in the attributes. This works well + as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the + file anyway, when it's created new. */ + if((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) { + if (!SetFileAttributes(Ansi_Fname, G.pInfo->file_attr & 0x7F)) + Info(slide, 1, ((char *)slide, + "\nwarning (%d): could not set file attributes\n", + (int)GetLastError())); + } + +#ifdef NTSD_EAS + /* 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(TruncNTSD), + makeword(G.extra_field+2)-10, uO.qflag? "\n":"")); + } + } +#endif /* NTSD_EAS */ + + if ( hFile == INVALID_HANDLE_VALUE ) + Info(slide, 1, ((char *)slide, + "\nCreateFile error %d when trying set file time\n", + (int)GetLastError())); + else { + if (gotTime) { + FILETIME *pModft = (gotTime & EB_UT_FL_MTIME) ? &Modft : NULL; + FILETIME *pAccft = (gotTime & EB_UT_FL_ATIME) ? &Accft : NULL; + FILETIME *pCreft = (gotTime & EB_UT_FL_CTIME) ? &Creft : NULL; + + if (!SetFileTime(hFile, pCreft, pAccft, pModft)) + Info(slide, 0, ((char *)slide, "\nSetFileTime failed: %d\n", + (int)GetLastError())); + } + CloseHandle(hFile); + } + + return; + +#undef Ansi_Fname + +} /* end function close_outfile() */ + + + + +#ifdef TIMESTAMP + +/*************************/ +/* Function stamp_file() */ +/*************************/ + +int stamp_file(__GPRO__ ZCONST char *fname, time_t modtime) +{ + FILETIME Modft; /* File time type defined in NT, `last modified' time */ + HANDLE hFile; /* File handle defined in NT */ + int errstat = 0; /* return status: 0 == "OK", -1 == "Failure" */ +#ifndef NT_TZBUG_WORKAROUND + time_t utime_dosmin; /* internal variable for UTIME_BOUNDCHECK_1 */ +#endif + int fs_uses_loctime = FStampIsLocTime(__G__ fname); +#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ + char *ansi_name = (char *)alloca(strlen(fname) + 1); + + INTERN_TO_ISO(fname, ansi_name); +# define Ansi_Fname ansi_name +#else +# define Ansi_Fname fname +#endif + + /* open a handle to the file to prepare setting the mod-time stamp */ + hFile = CreateFile(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if ( hFile == INVALID_HANDLE_VALUE ) { + errstat = -1; + } else { + /* convert time_t modtime into WIN32 native 64bit format */ + UTIME_BOUNDCHECK_1(modtime) + utime2FileTime(modtime, &Modft); + NT_TZBUG_PRECOMPENSATE(modtime, &Modft) + /* set Access and Modification times of the file to modtime */ + if (!SetFileTime(hFile, NULL, &Modft, &Modft)) { + errstat = -1; + } + CloseHandle(hFile); + } + + return errstat; + +#undef Ansi_Fname +} /* end function stamp_file() */ + +#endif /* TIMESTAMP */ + + + + +/***********************/ +/* Function isfloppy() */ /* more precisely, is it removable? */ +/***********************/ + +static int isfloppy(int nDrive) /* 1 == A:, 2 == B:, etc. */ +{ + char rootPathName[4]; + + rootPathName[0] = (char)('A' + nDrive - 1); /* build the root path */ + rootPathName[1] = ':'; /* name, e.g. "A:/" */ + rootPathName[2] = '/'; + rootPathName[3] = '\0'; + + return (GetDriveType(rootPathName) == DRIVE_REMOVABLE); + +} /* end function isfloppy() */ + + + + +/*****************************/ +/* Function NTQueryVolInfo() */ +/*****************************/ + +/* + * Note: 8.3 limits on filenames apply only to old-style FAT filesystems. + * More recent versions of Windows (Windows NT 3.5 / Windows 4.0) + * can support long filenames (LFN) on FAT filesystems. Check the + * filesystem maximum component length field to detect LFN support. + */ + +static int NTQueryVolInfo(__GPRO__ const char *name) +{ + /* static char lastRootPath[4] = ""; */ + /* static int lastVolOldFAT; */ + /* static int lastVolLocTim; */ + char *tmp0; + char tmp1[MAX_PATH], tmp2[MAX_PATH]; + unsigned volSerNo, maxCompLen, fileSysFlags; +#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ + char *ansi_name = (char *)alloca(strlen(name) + 1); + + INTERN_TO_ISO(name, ansi_name); + name = ansi_name; +#endif + + if ((!strncmp(name, "//", 2) || !strncmp(name,"\\\\", 2)) && + (name[2] != '\0' && name[2] != '/' && name[2] != '\\')) { + /* GetFullPathname() and GetVolumeInformation() do not work + * on UNC names. For now, we return "error". + * **FIXME**: check if UNC name is mapped to a drive letter + * and use mapped drive for volume info query. + */ + return FALSE; + } + if (isalpha((uch)name[0]) && (name[1] == ':')) + tmp0 = (char *)name; + else + { + if (!GetFullPathName(name, MAX_PATH, tmp1, &tmp0)) + return FALSE; + tmp0 = &tmp1[0]; + } + if (strncmp(G.lastRootPath, tmp0, 2) != 0) { + /* For speed, we skip repeated queries for the same device */ + strncpy(G.lastRootPath, tmp0, 2); /* Build the root path name, */ + G.lastRootPath[2] = '/'; /* e.g. "A:/" */ + G.lastRootPath[3] = '\0'; + + if (!GetVolumeInformation((LPCTSTR)G.lastRootPath, + (LPTSTR)tmp1, (DWORD)MAX_PATH, + (LPDWORD)&volSerNo, (LPDWORD)&maxCompLen, + (LPDWORD)&fileSysFlags, (LPTSTR)tmp2, (DWORD)MAX_PATH)) { + G.lastRootPath[0] = '\0'; + return FALSE; + } + + /* LFNs are available if the component length is > 12 */ + G.lastVolOldFAT = (maxCompLen <= 12); +/* G.lastVolOldFAT = !strncmp(strupr(tmp2), "FAT", 3); old version */ + + /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in + * local time! + */ + G.lastVolLocTim = !strncmp(strupr(tmp2), "VFAT", 4) || + !strncmp(tmp2, "HPFS", 4) || + !strncmp(tmp2, "FAT", 3); + } + + return TRUE; + +} /* end function NTQueryVolInfo() */ + + + + +/*****************************/ +/* Function IsVolumeOldFAT() */ +/*****************************/ + +static int IsVolumeOldFAT(__GPRO__ const char *name) +{ + return (NTQueryVolInfo(__G__ name) ? G.lastVolOldFAT : FALSE); +} + + + + +#ifndef SFX + +/************************/ +/* Function do_wild() */ /* identical to OS/2 version */ +/************************/ + +char *do_wild(__G__ wildspec) + __GDEF + char *wildspec; /* only used first time on a given dir */ +{ + /* static zDIR *wild_dir = NULL; */ + /* static char *dirname, *wildname, matchname[FILNAMSIZ]; */ + /* static int firstcall=TRUE, 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 (!G.notfirstcall) { /* first call: must initialize everything */ + G.notfirstcall = TRUE; + + if (!iswild(wildspec)) { + strcpy(G.matchname, wildspec); + 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 = strrchr(wildspec, '/')) == NULL && + (G.wildname = strrchr(wildspec, ':')) == NULL) { + G.dirname = "."; + G.dirnamelen = 1; + G.have_dirname = FALSE; + 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")); + strcpy(G.matchname, wildspec); + 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; + } + Trace((stderr, "do_wild: dirname = [%s]\n", G.dirname)); + + if ((G.wild_dir = (zvoid *)Opendir(G.dirname)) != NULL) { + if (G.have_dirname) { + strcpy(G.matchname, G.dirname); + fnamestart = G.matchname + G.dirnamelen; + } else + fnamestart = G.matchname; + while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) { + Trace((stderr, "do_wild: Readdir returns %s\n", file->d_name)); + strcpy(fnamestart, file->d_name); + if (strrchr(fnamestart, '.') == (char *)NULL) + strcat(fnamestart, "."); + if (match(fnamestart, G.wildname, 1) && /* 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.matchname; + } + } + /* if we get to here directory is exhausted, so close it */ + Closedir((zDIR *)G.wild_dir); + G.wild_dir = NULL; + } + Trace((stderr, "do_wild: Opendir(%s) returns NULL\n", G.dirname)); + + /* return the raw wildspec in case that works (e.g., directory not + * searchable, but filespec was not wild and file is readable) */ + strcpy(G.matchname, wildspec); + return G.matchname; + } + + /* last time through, might have failed opendir but returned raw wildspec */ + if (G.wild_dir == NULL) { + G.notfirstcall = FALSE; /* 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. + */ + if (G.have_dirname) { + /* strcpy(G.matchname, G.dirname); */ + fnamestart = G.matchname + G.dirnamelen; + } else + fnamestart = G.matchname; + while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) { + Trace((stderr, "do_wild: readdir returns %s\n", file->d_name)); + strcpy(fnamestart, file->d_name); + if (strrchr(fnamestart, '.') == (char *)NULL) + strcat(fnamestart, "."); + if (match(fnamestart, G.wildname, 1)) { /* 1 == ignore case */ + Trace((stderr, "do_wild: match() succeeds\n")); + /* remove trailing dot */ + fnamestart += strlen(fnamestart) - 1; + if (*fnamestart == '.') + *fnamestart = '\0'; + return G.matchname; + } + } + + Closedir((zDIR *)G.wild_dir); /* at least one entry read; nothing left */ + G.wild_dir = NULL; + G.notfirstcall = FALSE; /* reset for new wildspec */ + if (G.have_dirname) + free(G.dirname); + return (char *)NULL; + +} /* end function do_wild() */ + +#endif /* !SFX */ + + + +/**********************/ +/* Function mapattr() */ +/**********************/ + +/* Identical to MS-DOS, OS/2 versions. However, NT has a lot of extra + * permission stuff, so this function should probably be extended in the + * future. */ + +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 & FILE_ATTRIBUTE_DIRECTORY ? + 0 : FILE_ATTRIBUTE_ARCHIVE)) & 0xff; + return 0; + +} /* end function mapattr() */ + + + + +/************************/ +/* Function mapname() */ +/************************/ + /* return 0 if no error, 1 if caution (filename */ +int mapname(__G__ renamed) /* truncated), 2 if warning (skip file because */ + __GDEF /* dir doesn't exist), 3 if error (skip file), */ + int renamed; /* or 10 if out of memory (skip file) */ +{ /* [also IZ_VOL_LABEL, IZ_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 error; + 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.created_dir = FALSE; /* not yet */ + G.renamed_fullpath = FALSE; + G.fnlen = strlen(G.filename); + + 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.renamed_fullpath = TRUE; + pathcomp[0] = '/'; /* copy the '/' and terminate */ + pathcomp[1] = '\0'; + ++cp; + } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') { + G.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 */ + cp = (char *)strrchr(G.filename, '/'); + if (cp == 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)) > 1) + return error; + pp = pathcomp; /* reset conversion buffer for next piece */ + lastsemi = NULL; /* leave directory semi-colons alone */ + break; + + case ':': /* drive names not stored in zipfile, */ + case '<': /* so no colons allowed */ + case '>': /* no redirection symbols allowed either */ + case '|': /* no pipe signs allowed */ + case '"': /* no double quotes allowed */ + case '?': /* no wildcards allowed */ + case '*': + *pp++ = '_'; /* these rules apply equally to FAT and NTFS */ + break; + case ';': /* start of VMS version? */ + lastsemi = pp; /* remove VMS version later... */ + *pp++ = ';'; /* but keep semicolon for now */ + break; + + case ' ': /* keep spaces unless specifically */ + /* NT cannot create filenames with spaces on FAT volumes */ + if (uO.sflag || IsVolumeOldFAT(__G__ G.filename)) + *pp++ = '_'; + else + *pp++ = ' '; + break; + + default: + /* allow European characters in filenames: */ + if (isprint(workch) || workch >= 127) + *pp++ = (char)workch; + } /* end switch */ + } /* end while loop */ + + *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'; + } + +/*--------------------------------------------------------------------------- + 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.fnlen-1] == '/') { + checkdir(__G__ G.filename, GETPATH); + if (G.created_dir) { +#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ + char *ansi_name = (char *)alloca(strlen(G.filename) + 1); + + INTERN_TO_ISO(G.filename, ansi_name); +# define Ansi_Fname ansi_name +#else +# define Ansi_Fname G.filename +#endif + if (QCOND2) { + Info(slide, 0, ((char *)slide, " creating: %-22s\n", + FnFilter1(G.filename))); + } + + /* set file attributes: + The default for newly created directories is "DIR attribute + flags set", so there is no need to change attributes unless + one of the DOS style attribute flags is set. The readonly + attribute need not be masked, since it does not prevent + modifications in the new directory. */ + if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) { + if (!SetFileAttributes(Ansi_Fname, G.pInfo->file_attr & 0x7F)) + Info(slide, 1, ((char *)slide, + "\nwarning (%d): could not set file attributes for %s\n", + (int)GetLastError(), G.filename)); + } + +#ifdef NTSD_EAS + /* set extra fields, both stored-in-zipfile and .LONGNAME flavors */ + if (G.extra_field) { /* zipfile e.f. 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(TruncNTSD), + makeword(G.extra_field+2)-10, uO.qflag? "\n":"")); + } + } +#endif /* NTSD_EAS */ + return IZ_CREATED_DIR; /* set dir time (note trailing '/') */ + } + return 2; /* dir existed already; don't look for data to extract */ + } + + if (*pathcomp == '\0') { + Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", + FnFilter1(G.filename))); + return 3; + } + + 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 */ + char drive[4]; +#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ + char *ansi_name = (char *)alloca(strlen(G.filename) + 1); + INTERN_TO_ISO(G.filename, ansi_name); +# define Ansi_Fname ansi_name +#else +# define Ansi_Fname G.filename +#endif + + /* Build a drive string, e.g. "b:" */ + drive[0] = (char)('a' + G.nLabelDrive - 1); + strcpy(drive + 1, ":\\"); + if (QCOND2) + Info(slide, 0, ((char *)slide, "labelling %s %-22s\n", drive, + FnFilter1(G.filename))); + if (!SetVolumeLabel(drive, Ansi_Fname)) { + Info(slide, 1, ((char *)slide, + "mapname: error setting volume label\n")); + return 3; + } + return 2; /* success: skip the "extraction" quietly */ +#undef Ansi_Fname + } + + return error; + +} /* end function mapname() */ + + + + +/**********************/ +/* Function map2fat() */ /* Not quite identical to OS/2 version */ +/**********************/ + +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 = 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 NTFS but not + * in FAT: to get here, must already have passed through mapname. + * Also must truncate path component to ensure 8.3 compliance. + */ + while ((workch = (uch)*ppc++) != 0) { + switch (workch) { + case '[': + case ']': + case '+': + case ',': + case ';': + 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 == NULL) { /* no dots: check for underscores... */ + char *plu = strrchr(pBegin, '_'); /* pointer to last underscore */ + + if (plu == NULL) { /* no dots, no underscores: truncate at 8 chars */ + *pEndFAT += 8; /* (or 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-blk */ + } 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 != 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 trun- */ + *q = '\0'; /* cate/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() */ + + + + +/***********************/ /* Borrowed from os2.c for UnZip 5.1. */ +/* Function checkdir() */ /* Difference: no EA stuff */ +/***********************/ /* HPFS stuff works on NTFS too */ + +int checkdir(__G__ pathcomp, flag) + __GDEF + char *pathcomp; + int flag; +/* + * returns: 1 - (on APPEND_NAME) truncated filename + * 2 - path doesn't exist, not allowed to create + * 3 - path doesn't exist, tried to create and failed; or + * path exists and is not a directory, but is supposed to be + * 4 - path is too long + * 10 - can't allocate memory for filename buffers + */ +{ + /* 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') */ + +# 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 too_long=FALSE; + + Trace((stderr, "appending dir segment [%s]\n", pathcomp)); + while ((*G.endHPFS = *p++) != '\0') /* copy to HPFS filename */ + ++G.endHPFS; + if (!IsVolumeOldFAT(__G__ G.buildpathHPFS)) { + p = pathcomp; + while ((*G.endFAT = *p++) != '\0') /* copy to FAT filename, too */ + ++G.endFAT; + } else + map2fat(pathcomp, &G.endFAT); /* map into FAT fn, update endFAT */ + + /* GRR: could do better check, see if overrunning buffer as we go: + * check endHPFS-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.endHPFS-G.buildpathHPFS) > FILNAMSIZ-3) + too_long = TRUE; /* check if extracting dir? */ +#ifdef FIX_STAT_BUG + /* Borland C++ 5.0 does not handle a call to stat() well if the + * directory does not exist (it tends to crash in strange places.) + * This is apparently a problem only when compiling for GUI rather + * than console. The code below attempts to work around this problem. + */ + if (access(G.buildpathFAT, 0) != 0) { + if (!G.create_dirs) { /* told not to create (freshening) */ + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 2; /* path doesn't exist: nothing to do */ + } + if (too_long) { /* GRR: should allow FAT extraction w/o EAs */ + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", + FnFilter1(G.buildpathHPFS))); + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 4; /* no room for filenames: fatal */ + } + if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, + "checkdir error: cannot create %s\n\ + unable to process %s.\n", + FnFilter2(G.buildpathFAT), FnFilter1(G.filename))); + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 3; /* path didn't exist, tried to create, failed */ + } + G.created_dir = TRUE; + } +#endif /* FIX_STAT_BUG */ + if (SSTAT(G.buildpathFAT, &G.statbuf)) /* path doesn't exist */ + { + if (!G.create_dirs) { /* told not to create (freshening) */ + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 2; /* path doesn't exist: nothing to do */ + } + if (too_long) { /* GRR: should allow FAT extraction w/o EAs */ + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", + FnFilter1(G.buildpathHPFS))); + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 4; /* no room for filenames: fatal */ + } + if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */ + Info(slide, 1, ((char *)slide, + "checkdir error: cannot create %s\n\ + unable to process %s.\n", + FnFilter2(G.buildpathFAT), FnFilter1(G.filename))); + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 3; /* path didn't exist, tried to create, failed */ + } + 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.buildpathFAT), FnFilter1(G.filename))); + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 3; /* path existed but wasn't dir */ + } + if (too_long) { + Info(slide, 1, ((char *)slide, + "checkdir error: path too long: %s\n", + FnFilter1(G.buildpathHPFS))); + free(G.buildpathHPFS); + free(G.buildpathFAT); + return 4; /* no room for filenames: fatal */ + } + *G.endHPFS++ = '/'; + *G.endFAT++ = '/'; + *G.endHPFS = *G.endFAT = '\0'; + Trace((stderr, "buildpathHPFS now = [%s]\nbuildpathFAT now = [%s]\n", + FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT))); + return 0; + + } /* 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.buildpathFAT))); + Trace((stderr, "freeing HPFS path [%s]\n", + FnFilter1(G.buildpathHPFS))); + strcpy(pathcomp, G.buildpathFAT); + free(G.buildpathFAT); + free(G.buildpathHPFS); + G.buildpathHPFS = G.buildpathFAT = G.endHPFS = G.endFAT = NULL; + return 0; + } + +/*--------------------------------------------------------------------------- + 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 = 0; + + Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); + while ((*G.endHPFS = *p++) != '\0') { /* copy to HPFS filename */ + ++G.endHPFS; + if ((G.endHPFS-G.buildpathHPFS) >= FILNAMSIZ) { + *--G.endHPFS = '\0'; + Info(slide, 1, ((char *)slide, + "checkdir warning: path too long; truncating\n \ + %s\n -> %s\n", + FnFilter1(G.filename), FnFilter2(G.buildpathHPFS))); + error = 1; /* filename truncated */ + } + } + + if ( G.pInfo->vollabel || !IsVolumeOldFAT(__G__ G.buildpathHPFS)) { + p = pathcomp; + while ((*G.endFAT = *p++) != '\0') /* copy to FAT filename, too */ + ++G.endFAT; + } else + map2fat(pathcomp, &G.endFAT); /* map into FAT fn, update endFAT */ + Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n", + FnFilter1(G.buildpathHPFS), FnFilter2(G.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 ")); + if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+1)) == NULL) + return 10; + if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+1)) == NULL) { + free(G.buildpathHPFS); + return 10; + } + 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.renamed_fullpath && pathcomp[1] == ':') + *G.buildpathHPFS = (char)ToLower(*pathcomp); + else if (!G.renamed_fullpath && G.rootlen > 1 && + G.rootpath[1] == ':') + *G.buildpathHPFS = (char)ToLower(*G.rootpath); + else { + char tmpN[MAX_PATH], *tmpP; + if (GetFullPathName(".", MAX_PATH, tmpN, &tmpP) > MAX_PATH) + { /* by definition of MAX_PATH we should never get here */ + Info(slide, 1, ((char *)slide, + "checkdir warning: current dir path too long\n")); + return 1; /* can't get drive letter */ + } + G.nLabelDrive = *tmpN - 'a' + 1; + *G.buildpathHPFS = (char)(G.nLabelDrive - 1 + 'a'); + } + G.nLabelDrive = *G.buildpathHPFS - 'a' + 1; /* save for mapname() */ + if (uO.volflag == 0 || *G.buildpathHPFS < 'a' /* no labels/bogus? */ + || (uO.volflag == 1 && !isfloppy(G.nLabelDrive))) { /* !fixed */ + free(G.buildpathHPFS); + free(G.buildpathFAT); + return IZ_VOL_LABEL; /* skipping with message */ + } + *G.buildpathHPFS = '\0'; + } else if (G.renamed_fullpath) /* pathcomp = valid data */ + strcpy(G.buildpathHPFS, pathcomp); + else if (G.rootlen > 0) + strcpy(G.buildpathHPFS, G.rootpath); + else + *G.buildpathHPFS = '\0'; + G.endHPFS = G.buildpathHPFS; + G.endFAT = G.buildpathFAT; + while ((*G.endFAT = *G.endHPFS) != '\0') { + ++G.endFAT; + ++G.endHPFS; + } + Trace((stderr, "[%s]\n", FnFilter1(G.buildpathHPFS))); + return 0; + } + +/*--------------------------------------------------------------------------- + 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 == NULL) { + G.rootlen = 0; + return 0; + } + if ((G.rootlen = strlen(pathcomp)) > 0) { + int had_trailing_pathsep=FALSE, has_drive=FALSE, xtra=2; + + if (isalpha((uch)pathcomp[0]) && pathcomp[1] == ':') + has_drive = TRUE; /* drive designator */ + if (pathcomp[G.rootlen-1] == '/' || pathcomp[G.rootlen-1] == '\\') { + pathcomp[--G.rootlen] = '\0'; + had_trailing_pathsep = TRUE; + } + if (has_drive && (G.rootlen == 2)) { + if (!had_trailing_pathsep) /* i.e., original wasn't "x:/" */ + xtra = 3; /* room for '.' + '/' + 0 at end of "x:" */ + } else if (G.rootlen > 0) { /* need not check "x:." and "x:/" */ + if (SSTAT(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) + { + /* path does not exist */ + if (!G.create_dirs /* || iswild(pathcomp) */ ) { + G.rootlen = 0; + return 2; /* treat as stored file */ + } + /* create directory (could add loop here to scan pathcomp + * and create more than one level, but 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, */ + return 3; /* failed: file exists, or need 2+ levels */ + } + } + } + if ((G.rootpath = (char *)malloc(G.rootlen+xtra)) == NULL) { + G.rootlen = 0; + return 10; + } + strcpy(G.rootpath, pathcomp); + if (xtra == 3) /* had just "x:", make "x:." */ + G.rootpath[G.rootlen++] = '.'; + G.rootpath[G.rootlen++] = '/'; + G.rootpath[G.rootlen] = '\0'; + Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath))); + } + return 0; + } +#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 0; + } + + return 99; /* should never reach */ + +} /* end function checkdir() */ + + + + + +#ifndef SFX +#ifndef WINDLL + +/************************/ +/* Function version() */ +/************************/ + +void version(__G) + __GDEF +{ + int len; +#if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DJGPP__)) + char buf[80]; +#if (defined(_MSC_VER) && (_MSC_VER > 900)) + char buf2[80]; +#endif +#endif + + len = sprintf((char *)slide, CompiledWith, + +#if defined(_MSC_VER) /* MSC == VC++, but what about SDK compiler? */ + (sprintf(buf, "Microsoft C %d.%02d ", _MSC_VER/100, _MSC_VER%100), buf), +# if (_MSC_VER == 800) + "(Visual C++ v1.1)", +# elif (_MSC_VER == 850) + "(Windows NT v3.5 SDK)", +# elif (_MSC_VER == 900) + "(Visual C++ v2.x)", +# elif (_MSC_VER > 900) + (sprintf(buf2, "(Visual C++ %d.%d)", _MSC_VER/100 - 6, _MSC_VER%100/10), + buf2), +# else + "(bad version)", +# endif +#elif defined(__WATCOMC__) +# if (__WATCOMC__ % 10 > 0) + (sprintf(buf, "Watcom C/C++ %d.%02d", __WATCOMC__ / 100, + __WATCOMC__ % 100), buf), "", +# else + (sprintf(buf, "Watcom C/C++ %d.%d", __WATCOMC__ / 100, + (__WATCOMC__ % 100) / 10), buf), "", +# endif +#elif defined(__BORLANDC__) + "Borland C++", +# if (__BORLANDC__ < 0x0200) + " 1.0", +# elif (__BORLANDC__ == 0x0200) + " 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) /* __BCPLUSPLUS__ = 0x0340 */ + " 5.0", +# elif (__BORLANDC__ == 0x0520) /* __BCPLUSPLUS__ = 0x0520 */ + " 5.2 (C++ Builder)", /* GRR: assume this will stay sync'd? */ +# else + " later than 5.2", +# endif +#elif defined(__LCC__) + "LCC-Win32", "", +#elif defined(__GNUC__) +# if defined(__RSXNT__) +# if (defined(__DJGPP__) && !defined(__EMX__)) + (sprintf(buf, "rsxnt(djgpp v%d.%02d) / gcc ", + __DJGPP__, __DJGPP_MINOR__), buf), +# elif defined(__DJGPP__) + (sprintf(buf, "rsxnt(emx+djgpp v%d.%02d) / gcc ", + __DJGPP__, __DJGPP_MINOR__), buf), +# elif (defined(__GO32__) && !defined(__EMX__)) + "rsxnt(djgpp v1.x) / gcc ", +# elif defined(__GO32__) + "rsxnt(emx + djgpp v1.x) / gcc ", +# elif defined(__EMX__) + "rsxnt(emx)+gcc ", +# else + "rsxnt(unknown) / gcc ", +# endif +# elif defined(__CYGWIN32__) + "cygnus win32 / gcc ", +# elif defined(__MINGW32__) + "mingw32 / gcc ", +# else + "gcc ", +# endif + __VERSION__, +#else /* !_MSC_VER, !__WATCOMC__, !__BORLANDC__, !__LCC__, !__GNUC__ */ + "unknown compiler (SDK?)", "", +#endif /* ?compilers */ + + "Windows 95 / Windows NT", "\n(32-bit)", + +#ifdef __DATE__ + " on ", __DATE__ +#else + "", "" +#endif + ); + + (*G.message)((zvoid *)&G, slide, (ulg)len, 0); + + return; + +} /* end function version() */ + +#endif /* !WINDLL */ +#endif /* !SFX */ + + + +#ifdef W32_STAT_BANDAID + +/* All currently known variants of WIN32 operating systems (Windows 95/98, + * WinNT 3.x, 4.0, 5.0) have a nasty bug in the OS kernel concerning + * conversions between UTC and local time: In the time conversion functions + * of the Win32 API, the timezone offset (including seasonal daylight saving + * shift) between UTC and local time evaluation is erratically based on the + * current system time. The correct evaluation must determine the offset + * value as it {was/is/will be} for the actual time to be converted. + * + * Some versions of MS C runtime lib's stat() returns utc time-stamps so + * that localtime(timestamp) corresponds to the (potentially false) local + * time shown by the OS' system programs (Explorer, command shell dir, etc.) + * The RSXNT port follows the same strategy, but fails to recognize the + * access-time attribute. + * + * For the NTFS file system (and other filesystems that store time-stamps + * as UTC values), this results in st_mtime (, st_{c|a}time) fields which + * are not stable but vary according to the seasonal change of "daylight + * saving time in effect / not in effect". + * + * Other C runtime libs (CygWin, or the CRT DLLs supplied with Win95/NT + * return the unix-time equivalent of the UTC FILETIME values as got back + * from the Win32 API call. This time, return values from NTFS are correct + * whereas utimes from files on (V)FAT volumes vary according to the DST + * switches. + * + * To achieve timestamp consistency of UTC (UT extra field) values in + * Zip archives, the Info-ZIP programs require work-around code for + * proper time handling in stat() (and other time handling routines). + */ +/* stat() functions under Windows95 tend to fail for root directories. * + * Watcom and Borland, at least, are affected by this bug. Watcom made * + * a partial fix for 11.0 but still missed some cases. This substitute * + * detects the case and fills in reasonable values. Otherwise we get * + * effects like failure to extract to a root dir because it's not found. */ + +int zstat_win32(__W32STAT_GLOBALS__ const char *path, struct stat *buf) +{ + if (!stat(path, buf)) + { +#ifdef NT_TZBUG_WORKAROUND + /* stat was successful, now redo the time-stamp fetches */ + int fs_uses_loctime = FStampIsLocTime(__G__ path); + HANDLE h; + FILETIME Modft, Accft, Creft; +#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ + char *ansi_path = (char *)alloca(strlen(path) + 1); + + INTERN_TO_ISO(path, ansi_path); +# define Ansi_Path ansi_path +#else +# define Ansi_Path path +#endif + + TTrace((stdout, "stat(%s) finds modtime %08lx\n", path, buf->st_mtime)); + h = CreateFile(Ansi_Path, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h != INVALID_HANDLE_VALUE) { + BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft); + CloseHandle(h); + + if (ftOK) { + FTTrace((stdout, "GetFileTime returned Modft", 0, &Modft)); + FTTrace((stdout, "GetFileTime returned Creft", 0, &Creft)); + if (!fs_uses_loctime) { + /* On a filesystem that stores UTC timestamps, we refill + * the time fields of the struct stat buffer by directly + * using the UTC values as returned by the Win32 + * GetFileTime() API call. + */ + FileTime2utime(&Modft, &(buf->st_mtime)); + if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0) + FileTime2utime(&Accft, &(buf->st_atime)); + else + buf->st_atime = buf->st_mtime; + if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0) + FileTime2utime(&Creft, &(buf->st_ctime)); + else + buf->st_ctime = buf->st_mtime; + TTrace((stdout,"NTFS, recalculated modtime %08lx\n", + buf->st_mtime)); + } else { + /* On VFAT and FAT-like filesystems, the FILETIME values + * are converted back to the stable local time before + * converting them to UTC unix time-stamps. + */ + VFatFileTime2utime(&Modft, &(buf->st_mtime)); + if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0) + VFatFileTime2utime(&Accft, &(buf->st_atime)); + else + buf->st_atime = buf->st_mtime; + if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0) + VFatFileTime2utime(&Creft, &(buf->st_ctime)); + else + buf->st_ctime = buf->st_mtime; + TTrace((stdout, "VFAT, recalculated modtime %08lx\n", + buf->st_mtime)); + } + } + } +# undef Ansi_Path +#endif /* NT_TZBUG_WORKAROUND */ + return 0; + } +#ifdef W32_STATROOT_FIX + else + { + DWORD flags; +#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ + char *ansi_path = (char *)alloca(strlen(path) + 1); + + INTERN_TO_ISO(path, ansi_path); +# define Ansi_Path ansi_path +#else +# define Ansi_Path path +#endif + + flags = GetFileAttributes(Ansi_Path); + if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) { + Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n", + path)); + memset(buf, 0, sizeof(struct stat)); + buf->st_atime = buf->st_ctime = buf->st_mtime = + dos_to_unix_time(DOSTIME_MINIMUM); /* 1-1-80 */ + buf->st_mode = S_IFDIR | S_IREAD | + ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE); + return 0; + } /* assumes: stat() won't fail on non-dirs without good reason */ +# undef Ansi_Path + } +#endif /* W32_STATROOT_FIX */ + return -1; +} + +#endif /* W32_STAT_BANDAID */ + +#endif /* !FUNZIP */ + + + +#ifndef WINDLL +/* This replacement getch() function was originally created for Watcom C + * and then additionally used with CYGWIN. Since UnZip 5.4, all other Win32 + * ports apply this replacement rather that their supplied getch() (or + * alike) function. There are problems with unabsorbed LF characters left + * over in the keyboard buffer under Win95 (and 98) when ENTER was pressed. + * (Under Win95, ENTER returns two(!!) characters: CR-LF.) This problem + * does not appear when run on a WinNT console prompt! + */ + +/* Watcom 10.6's getch() does not handle Alt+. */ +/* Note that if PASSWD_FROM_STDIN is defined, the file containing */ +/* the password must have a carriage return after the word, not a */ +/* Unix-style newline (linefeed only). This discards linefeeds. */ + +int getch_win32(void) +{ + HANDLE stin; + DWORD rc; + unsigned char buf[2]; + int ret = -1; + DWORD odemode = ~(DWORD)0; + +# ifdef PASSWD_FROM_STDIN + stin = GetStdHandle(STD_INPUT_HANDLE); +# else + stin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (stin == INVALID_HANDLE_VALUE) + return -1; +# endif + if (GetConsoleMode(stin, &odemode)) + SetConsoleMode(stin, ENABLE_PROCESSED_INPUT); /* raw except ^C noticed */ + if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1) + ret = buf[0]; + /* when the user hits return we get CR LF. We discard the LF, not the CR, + * because when we call this for the first time after a previous input + * such as the one for "replace foo? [y]es, ..." the LF may still be in + * the input stream before whatever the user types at our prompt. */ + if (ret == '\n') + if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1) + ret = buf[0]; + if (odemode != ~(DWORD)0) + SetConsoleMode(stin, odemode); +# ifndef PASSWD_FROM_STDIN + CloseHandle(stin); +# endif + return ret; +} +#endif /* !WINDLL */ diff --git a/utils/Install/sfxzip/zipinfo.c b/utils/Install/sfxzip/zipinfo.c new file mode 100644 index 0000000000..c244c1e92f --- /dev/null +++ b/utils/Install/sfxzip/zipinfo.c @@ -0,0 +1,1912 @@ +/*--------------------------------------------------------------------------- + + zipinfo.c Greg Roelofs et al. + + This file contains all of the ZipInfo-specific listing routines for UnZip. + + Contains: zi_opts() + zi_end_central() + zipinfo() + zi_long() + zi_short() + zi_time() + + ---------------------------------------------------------------------------*/ + + +#define UNZIP_INTERNAL +#include "unzip.h" + + +#ifndef NO_ZIPINFO /* strings use up too much space in small-memory systems */ + +/* Define OS-specific attributes for use on ALL platforms--the S_xxxx + * versions of these are defined differently (or not defined) by different + * compilers and operating systems. */ + +#define UNX_IFMT 0170000 /* Unix file type mask */ +#define UNX_IFDIR 0040000 /* Unix directory */ +#define UNX_IFREG 0100000 /* Unix regular file */ +#define UNX_IFSOCK 0140000 /* Unix socket (BSD, not SysV or Amiga) */ +#define UNX_IFLNK 0120000 /* Unix symbolic link (not SysV, Amiga) */ +#define UNX_IFBLK 0060000 /* Unix block special (not Amiga) */ +#define UNX_IFCHR 0020000 /* Unix character special (not Amiga) */ +#define UNX_IFIFO 0010000 /* Unix fifo (BCC, not MSC or Amiga) */ +#define UNX_ISUID 04000 /* Unix set user id on execution */ +#define UNX_ISGID 02000 /* Unix set group id on execution */ +#define UNX_ISVTX 01000 /* Unix directory permissions control */ +#define UNX_ENFMT UNX_ISGID /* Unix record locking enforcement flag */ +#define UNX_IRWXU 00700 /* Unix read, write, execute: owner */ +#define UNX_IRUSR 00400 /* Unix read permission: owner */ +#define UNX_IWUSR 00200 /* Unix write permission: owner */ +#define UNX_IXUSR 00100 /* Unix execute permission: owner */ +#define UNX_IRWXG 00070 /* Unix read, write, execute: group */ +#define UNX_IRGRP 00040 /* Unix read permission: group */ +#define UNX_IWGRP 00020 /* Unix write permission: group */ +#define UNX_IXGRP 00010 /* Unix execute permission: group */ +#define UNX_IRWXO 00007 /* Unix read, write, execute: other */ +#define UNX_IROTH 00004 /* Unix read permission: other */ +#define UNX_IWOTH 00002 /* Unix write permission: other */ +#define UNX_IXOTH 00001 /* Unix execute permission: other */ + +#define VMS_IRUSR UNX_IRUSR /* VMS read/owner */ +#define VMS_IWUSR UNX_IWUSR /* VMS write/owner */ +#define VMS_IXUSR UNX_IXUSR /* VMS execute/owner */ +#define VMS_IRGRP UNX_IRGRP /* VMS read/group */ +#define VMS_IWGRP UNX_IWGRP /* VMS write/group */ +#define VMS_IXGRP UNX_IXGRP /* VMS execute/group */ +#define VMS_IROTH UNX_IROTH /* VMS read/other */ +#define VMS_IWOTH UNX_IWOTH /* VMS write/other */ +#define VMS_IXOTH UNX_IXOTH /* VMS execute/other */ + +#define AMI_IFMT 06000 /* Amiga file type mask */ +#define AMI_IFDIR 04000 /* Amiga directory */ +#define AMI_IFREG 02000 /* Amiga regular file */ +#define AMI_IHIDDEN 00200 /* to be supported in AmigaDOS 3.x */ +#define AMI_ISCRIPT 00100 /* executable script (text command file) */ +#define AMI_IPURE 00040 /* allow loading into resident memory */ +#define AMI_IARCHIVE 00020 /* not modified since bit was last set */ +#define AMI_IREAD 00010 /* can be opened for reading */ +#define AMI_IWRITE 00004 /* can be opened for writing */ +#define AMI_IEXECUTE 00002 /* executable image, a loadable runfile */ +#define AMI_IDELETE 00001 /* can be deleted */ + +#define LFLAG 3 /* short "ls -l" type listing */ + +static int zi_long OF((__GPRO__ ulg *pEndprev)); +static int zi_short OF((__GPRO)); +static void zi_showMacTypeCreator + OF((__GPRO__ uch *ebfield)); +static char *zi_time OF((__GPRO__ ZCONST ulg *datetimez, + ZCONST time_t *modtimez, char *d_t_str)); + + +/**********************************************/ +/* Strings used in zipinfo.c (ZipInfo half) */ +/**********************************************/ + +static char nullStr[] = ""; + +static ZCONST char Far LongHeader[] = "Archive: %s %ld bytes %d file%s\n"; +static ZCONST char Far ShortHeader[] = "Archive: %s %ld %d\n"; +static ZCONST char Far EndCentDirRec[] = "\nEnd-of-central-directory record:\n"; +static ZCONST char Far LineSeparators[] = "-------------------------------\n\n"; +static ZCONST char Far ActOffsetCentDir[] = "\ + Actual offset of end-of-central-dir record: %9ld (%.8lXh)\n\ + Expected offset of end-of-central-dir record: %9ld (%.8lXh)\n\ + (based on the length of the central directory and its expected offset)\n\n"; +static ZCONST char Far SinglePartArchive1[] = "\ + This zipfile constitutes the sole disk of a single-part archive; its\n\ + central directory contains %u %s. The central directory is %lu\n\ + (%.8lXh) bytes long, and its (expected) offset in bytes from the\n"; +static ZCONST char Far SinglePartArchive2[] = "\ + beginning of the zipfile is %lu (%.8lXh).\n\n"; +static ZCONST char Far MultiPartArchive1[] = "\ + This zipfile constitutes disk %u of a multi-part archive. The central\n\ + directory starts on disk %u; %u of its entries %s contained within\n"; +static ZCONST char Far MultiPartArchive2[] = "\ + this zipfile, out of a total of %u %s. The entire central\n\ + directory is %lu (%.8lXh) bytes long, and its offset in bytes from\n"; +static ZCONST char Far MultiPartArchive3[] = "\ + the beginning of the zipfile in which it begins is %lu (%.8lXh).\n\n"; +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\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"; +static ZCONST char Far ZipfileCommTruncMsg[] = + "\ncaution: zipfile comment truncated\n"; + +static ZCONST char Far CentralDirEntry[] = + "\nCentral directory entry #%d:\n---------------------------\n\n"; +static ZCONST char Far ZipfileStats[] = + "%d file%s, %lu bytes uncompressed, %lu bytes compressed: %s%d.%d%%\n"; + +/* zi_long() strings */ +static ZCONST char Far OS_FAT[] = "MS-DOS, OS/2 or NT FAT"; +static ZCONST char Far OS_Amiga[] = "Amiga"; +static ZCONST char Far OS_VMS[] = "VMS"; +static ZCONST char Far OS_Unix[] = "Unix"; +static ZCONST char Far OS_VMCMS[] = "VM/CMS"; +static ZCONST char Far OS_AtariST[] = "Atari ST"; +static ZCONST char Far OS_HPFS[] = "OS/2 or NT HPFS"; +static ZCONST char Far OS_Macintosh[] = "Macintosh HFS"; +static ZCONST char Far OS_ZSystem[] = "Z-System"; +static ZCONST char Far OS_CPM[] = "CP/M"; +static ZCONST char Far OS_TOPS20[] = "TOPS-20"; +static ZCONST char Far OS_NTFS[] = "NTFS"; +static ZCONST char Far OS_QDOS[] = "SMS/QDOS"; +static ZCONST char Far OS_Acorn[] = "Acorn RISC OS"; +static ZCONST char Far OS_MVS[] = "MVS"; +static ZCONST char Far OS_VFAT[] = "Win32 VFAT"; +static ZCONST char Far OS_BeOS[] = "BeOS"; +static ZCONST char Far OS_Tandem[] = "Tandem NSK"; + +static ZCONST char Far MthdNone[] = "none (stored)"; +static ZCONST char Far MthdShrunk[] = "shrunk"; +static ZCONST char Far MthdRedF1[] = "reduced (factor 1)"; +static ZCONST char Far MthdRedF2[] = "reduced (factor 2)"; +static ZCONST char Far MthdRedF3[] = "reduced (factor 3)"; +static ZCONST char Far MthdRedF4[] = "reduced (factor 4)"; +static ZCONST char Far MthdImplode[] = "imploded"; +static ZCONST char Far MthdToken[] = "tokenized"; +static ZCONST char Far MthdDeflate[] = "deflated"; +static ZCONST char Far MthdEnDeflate[] = "deflated (enhanced)"; +static ZCONST char Far MthdDCLImplode[] = "imploded (PK DCL)"; + +static ZCONST char Far DeflNorm[] = "normal"; +static ZCONST char Far DeflMax[] = "maximum"; +static ZCONST char Far DeflFast[] = "fast"; +static ZCONST char Far DeflSFast[] = "superfast"; + +static ZCONST char Far ExtraBytesPreceding[] = + " There are an extra %ld bytes preceding this file.\n\n"; + +static ZCONST char Far UnknownNo[] = "unknown (%d)"; + +static ZCONST char Far LocalHeaderOffset[] = + "\n offset of local header from start of archive: %lu (%.8lXh) bytes\n"; +static ZCONST char Far HostOS[] = + " file system or operating system of origin: %s\n"; +static ZCONST char Far EncodeSWVer[] = + " version of encoding software: %d.%d\n"; +static ZCONST char Far MinOSCompReq[] = + " minimum file system compatibility required: %s\n"; +static ZCONST char Far MinSWVerReq[] = + " minimum software version required to extract: %d.%d\n"; +static ZCONST char Far CompressMethod[] = + " compression method: %s\n"; +static ZCONST char Far SlideWindowSizeImplode[] = + " size of sliding dictionary (implosion): %cK\n"; +static ZCONST char Far ShannonFanoTrees[] = + " number of Shannon-Fano trees (implosion): %c\n"; +static ZCONST char Far CompressSubtype[] = + " compression sub-type (deflation): %s\n"; +static ZCONST char Far FileSecurity[] = + " file security status: %sencrypted\n"; +static ZCONST char Far ExtendedLocalHdr[] = + " extended local header: %s\n"; +static ZCONST char Far FileModDate[] = + " file last modified on (DOS date/time): %s\n"; +#ifdef USE_EF_UT_TIME + static ZCONST char Far UT_FileModDate[] = + " file last modified on (UT extra field modtime): %s %s\n"; + static ZCONST char Far LocalTime[] = "local"; +#ifndef NO_GMTIME + static ZCONST char Far GMTime[] = "UTC"; +#endif +#endif /* USE_EF_UT_TIME */ +static ZCONST char Far CRC32Value[] = + " 32-bit CRC value (hex): %.8lx\n"; +static ZCONST char Far CompressedFileSize[] = + " compressed size: %lu bytes\n"; +static ZCONST char Far UncompressedFileSize[] = + " uncompressed size: %lu bytes\n"; +static ZCONST char Far FilenameLength[] = + " length of filename: %u characters\n"; +static ZCONST char Far ExtraFieldLength[] = + " length of extra field: %u bytes\n"; +static ZCONST char Far FileCommentLength[] = + " length of file comment: %u characters\n"; +static ZCONST char Far FileDiskNum[] = + " disk number on which file begins: disk %u\n"; +static ZCONST char Far ApparentFileType[] = + " apparent file type: %s\n"; +static ZCONST char Far VMSFileAttributes[] = + " VMS file attributes (%06o octal): %s\n"; +static ZCONST char Far AmigaFileAttributes[] = + " Amiga file attributes (%06o octal): %s\n"; +static ZCONST char Far UnixFileAttributes[] = + " Unix file attributes (%06o octal): %s\n"; +static ZCONST char Far NonMSDOSFileAttributes[] = + " non-MSDOS external file attributes: %06lX hex\n"; +static ZCONST char Far MSDOSFileAttributes[] = + " MS-DOS file attributes (%02X hex): none\n"; +static ZCONST char Far MSDOSFileAttributesRO[] = + " MS-DOS file attributes (%02X hex): read-only\n"; +static ZCONST char Far MSDOSFileAttributesAlpha[] = + " MS-DOS file attributes (%02X hex): %s%s%s%s%s%s\n"; + + +static ZCONST char Far ExtraFieldTrunc[] = "\n\ + error: EF data block (type 0x%04x) size %u exceeds remaining extra field\n\ + space %u; block length has been truncated.\n"; +static ZCONST char Far ExtraFields[] = "\n\ + The central-directory extra field contains:"; +static ZCONST char Far ExtraFieldType[] = "\n\ + - A subfield with ID 0x%04x (%s) and %u data bytes"; +static ZCONST char Far efAV[] = "PKWARE AV"; +static ZCONST char Far efOS2[] = "OS/2"; +static ZCONST char Far efPKVMS[] = "PKWARE VMS"; +static ZCONST char Far efPKWin32[] = "PKWARE Win32"; +static ZCONST char Far efPKUnix[] = "PKWARE Unix"; +static ZCONST char Far efIZVMS[] = "Info-ZIP VMS"; +static ZCONST char Far efIZUnix[] = "old Info-ZIP Unix/OS2/NT"; +static ZCONST char Far efIZUnix2[] = "Unix UID/GID"; +static ZCONST char Far efTime[] = "universal time"; +static ZCONST char Far efJLMac[] = "old Info-ZIP Macintosh"; +static ZCONST char Far efMac3[] = "new Info-ZIP Macintosh"; +static ZCONST char Far efZipIt[] = "ZipIt Macintosh"; +static ZCONST char Far efZipIt2[] = "ZipIt Macintosh (short)"; +static ZCONST char Far efVMCMS[] = "VM/CMS"; +static ZCONST char Far efMVS[] = "MVS"; +static ZCONST char Far efACL[] = "OS/2 ACL"; +static ZCONST char Far efNTSD[] = "Security Descriptor"; +static ZCONST char Far efBeOS[] = "BeOS"; +static ZCONST char Far efQDOS[] = "SMS/QDOS"; +static ZCONST char Far efAOSVS[] = "AOS/VS"; +static ZCONST char Far efSpark[] = "Acorn SparkFS"; +static ZCONST char Far efMD5[] = "Fred Kantor MD5"; +static ZCONST char Far efASiUnix[] = "ASi Unix"; +static ZCONST char Far efUnknown[] = "unknown"; + +static ZCONST char Far OS2EAs[] = ".\n\ + The local extra field has %lu bytes of OS/2 extended attributes.\n\ + (May not match OS/2 \"dir\" amount due to storage method)"; +static ZCONST char Far izVMSdata[] = ". The extra\n\ + field is %s and has %lu bytes of VMS %s information%s"; +static ZCONST char Far izVMSstored[] = "stored"; +static ZCONST char Far izVMSrleenc[] = "run-length encoded"; +static ZCONST char Far izVMSdeflat[] = "deflated"; +static ZCONST char Far izVMScunknw[] = "compressed(?)"; +static ZCONST char Far *izVMScomp[4] = + {izVMSstored, izVMSrleenc, izVMSdeflat, izVMScunknw}; +static ZCONST char Far ACLdata[] = ".\n\ + The local extra field has %lu bytes of access control list information"; +static ZCONST char Far NTSDData[] = ".\n\ + The local extra field has %lu bytes of NT security descriptor data"; +static ZCONST char Far UTdata[] = ".\n\ + The local extra field has UTC/GMT %s time%s"; +static ZCONST char Far UTmodification[] = "modification"; +static ZCONST char Far UTaccess[] = "access"; +static ZCONST char Far UTcreation[] = "creation"; +static ZCONST char Far ZipItFname[] = ".\n\ + The Mac long filename is %s.\n"; +static ZCONST char Far Mac3data[] = ".\n\ + The local extra field has %lu bytes of %scompressed Macintosh\n\ + finder attributes"; + /* MacOSdata[] is used by EF_MAC3, EF_ZIPIT, EF_ZIPIT2 and EF_JLEE e. f. */ +static ZCONST char Far MacOSdata[] = ".\n\ + The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'"; +static ZCONST char Far MacOSdata1[] = ".\n\ + The associated file has type code `0x%lx' and creator code `0x%lx'"; +static ZCONST char Far MacOSJLEEflags[] = "\n File is marked as %s"; +static ZCONST char Far MacOS_RF[] = "Resource-fork"; +static ZCONST char Far MacOS_DF[] = "Data-fork"; +static ZCONST char Far MacOSMAC3flags[] = ".\n\ + File is marked as %s, File Dates are in %d Bit"; +static ZCONST char Far BeOSdata[] = ".\n\ + The local extra field has %lu bytes of %scompressed BeOS file attributes"; + /* The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'" */ +static ZCONST char Far QDOSdata[] = ".\n\ + The QDOS extra field subtype is `%c%c%c%c'"; +static ZCONST char Far AOSVSdata[] = ".\n\ + The AOS/VS extra field revision is %d.%d"; +static ZCONST char Far MD5data[] = ".\n\ + The 128-bit MD5 signature is %s"; +#ifdef CMS_MVS + static ZCONST char Far VmMvsExtraField[] = ".\n\ + The stored file open mode (FLDATA TYPE) is \"%s\""; + static ZCONST char Far VmMvsInvalid[] = "[invalid]"; +#endif /* CMS_MVS */ + +static ZCONST char Far First20[] = ". The first\n 20 are: "; +static ZCONST char Far ColonIndent[] = ":\n "; +static ZCONST char Far efFormat[] = " %02x"; + +static ZCONST char Far lExtraFieldType[] = "\n\ + There %s a local extra field with ID 0x%04x (%s) and\n\ + %u data bytes (%s).\n"; +static ZCONST char Far efIZuid[] = + "GMT modification/access times and Unix UID/GID"; +static ZCONST char Far efIZnouid[] = "GMT modification/access times only"; + + +static ZCONST char Far NoFileComment[] = "\n There is no file comment.\n"; +static ZCONST char Far FileCommBegin[] = "\n\ +------------------------- file comment begins ----------------------------\n"; +static ZCONST char Far FileCommEnd[] = "\ +-------------------------- file comment ends -----------------------------\n"; + +/* zi_time() strings */ +static ZCONST char Far BogusFmt[] = "%03d"; +static ZCONST char Far DMYHMTime[] = "%2u-%s-%02u %02u:%02u"; +static ZCONST char Far YMDHMSTime[] = "%u %s %u %02u:%02u:%02u"; +static ZCONST char Far DecimalTime[] = "%04u%02u%02u.%02u%02u%02u"; +static ZCONST char Far YMDHMSTimeError[] = "???? ??? ?? ??:??:??"; + + + + + +#ifndef WINDLL + +/************************/ +/* Function zi_opts() */ +/************************/ + +int zi_opts(__G__ pargc, pargv) + int *pargc; + char ***pargv; + __GDEF +{ + char **argv, *s; + int argc, c, error=FALSE, negative=0; + 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; + + +#ifdef MACOS + uO.lflag = LFLAG; /* reset default on each call */ +#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; + case '1': /* shortest listing: JUST filenames */ + if (negative) + uO.lflag = -2, negative = 0; + else + uO.lflag = 1; + break; + case '2': /* just filenames, plus headers if specified */ + if (negative) + uO.lflag = -2, negative = 0; + else + uO.lflag = 2; + 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; +#endif /* !CMS_MVS */ + case 'h': /* header line */ + if (negative) + hflag_2 = hflag_slmv = FALSE, negative = 0; + else { + hflag_2 = hflag_slmv = explicit_h = TRUE; + if (uO.lflag == -1) + uO.lflag = 0; + } + break; + case 'l': /* longer form of "ls -l" type listing */ + if (negative) + uO.lflag = -2, negative = 0; + else + uO.lflag = 5; + break; + case 'm': /* medium form of "ls -l" type listing */ + if (negative) + uO.lflag = -2, negative = 0; + else + uO.lflag = 4; + break; +#ifdef MORE + case 'M': /* send output through built-in "more" */ + if (negative) + G.M_flag = FALSE, negative = 0; + else + G.M_flag = TRUE; + break; +#endif + case 's': /* default: shorter "ls -l" type listing */ + if (negative) + uO.lflag = -2, negative = 0; + else + uO.lflag = 3; + break; + case 't': /* totals line */ + if (negative) + tflag_2v = tflag_slm = FALSE, negative = 0; + else { + tflag_2v = tflag_slm = explicit_t = TRUE; + if (uO.lflag == -1) + uO.lflag = 0; + } + break; + case ('T'): /* use (sortable) decimal time format */ + if (negative) + uO.T_flag = FALSE, negative = 0; + else + uO.T_flag = TRUE; + break; + case 'v': /* turbo-verbose listing */ + if (negative) + uO.lflag = -2, negative = 0; + else + uO.lflag = 10; + break; + case 'z': /* print zipfile comment */ + if (negative) + uO.zflag = negative = 0; + else + uO.zflag = 1; + break; + case 'Z': /* ZipInfo mode: ignore */ + break; + default: + error = TRUE; + break; + } + } + } + if ((argc-- == 0) || error) { + *pargc = argc; + *pargv = argv; + return USAGE(error); + } + +#ifdef MORE + if (G.M_flag && !isatty(1)) /* stdout redirected: "more" func useless */ + G.M_flag = 0; +#endif + + /* if no listing options given (or all negated), or if only -h/-t given + * with individual files specified, use default listing format */ + if ((uO.lflag < 0) || ((argc > 0) && (uO.lflag == 0))) + uO.lflag = LFLAG; + + /* set header and totals flags to default or specified values */ + switch (uO.lflag) { + case 0: /* 0: can only occur if either -t or -h explicitly given; */ + case 2: /* therefore set both flags equal to normally false value */ + uO.hflag = hflag_2; + uO.tflag = tflag_2v; + break; + case 1: /* only filenames, *always* */ + uO.hflag = FALSE; + uO.tflag = FALSE; + uO.zflag = FALSE; + break; + case 3: + case 4: + case 5: + uO.hflag = ((argc > 0) && !explicit_h)? FALSE : hflag_slmv; + uO.tflag = ((argc > 0) && !explicit_t)? FALSE : tflag_slm; + break; + case 10: + uO.hflag = hflag_slmv; + uO.tflag = tflag_2v; + break; + } + + *pargc = argc; + *pargv = argv; + return 0; + +} /* end function zi_opts() */ + +#endif /* !WINDLL */ + + + + + +/*******************************/ +/* Function zi_end_central() */ +/*******************************/ + +int zi_end_central(__G) /* return PK-type error code */ + __GDEF +{ + int error = PK_COOL; + + +/*--------------------------------------------------------------------------- + Print out various interesting things about the zipfile. + ---------------------------------------------------------------------------*/ + + /* header fits on one line, for anything up to 10GB and 10000 files: */ + if (uO.hflag) + Info(slide, 0, ((char *)slide, ((int)strlen(G.zipfn) < 39)? + LoadFarString(LongHeader) : LoadFarString(ShortHeader), G.zipfn, + (long)G.ziplen, G.ecrec.total_entries_central_dir, + (G.ecrec.total_entries_central_dir==1)? + nullStr : "s")); + + /* verbose format */ + if (uO.lflag > 9) { + Info(slide, 0, ((char *)slide, LoadFarString(EndCentDirRec))); + Info(slide, 0, ((char *)slide, LoadFarString(LineSeparators))); + + Info(slide, 0, ((char *)slide, LoadFarString(ActOffsetCentDir), + (long)G.real_ecrec_offset, (long)G.real_ecrec_offset, + (long)G.expect_ecrec_offset, (long)G.expect_ecrec_offset)); + + if (G.ecrec.number_this_disk == 0) { + Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive1), + G.ecrec.total_entries_central_dir, + (G.ecrec.total_entries_central_dir == 1)? "entry" : "entries", + G.ecrec.size_central_directory, + G.ecrec.size_central_directory)); + Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive2), + G.ecrec.offset_start_central_directory, + G.ecrec.offset_start_central_directory)); + } else { + Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive1), + G.ecrec.number_this_disk + 1, + G.ecrec.num_disk_start_cdir + 1, + G.ecrec.num_entries_centrl_dir_ths_disk, + (G.ecrec.num_entries_centrl_dir_ths_disk == 1)? "is" : "are")); + Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive2), + G.ecrec.total_entries_central_dir, + (G.ecrec.total_entries_central_dir == 1) ? "entry" : "entries", + G.ecrec.size_central_directory, + G.ecrec.size_central_directory)); + Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive3), + G.ecrec.offset_start_central_directory, + G.ecrec.offset_start_central_directory)); + } + + /*----------------------------------------------------------------------- + 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) */ + + /* non-verbose mode: print zipfile comment only if requested */ + } else if (uO.zflag && G.ecrec.zipfile_comment_length) { + if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) { + Info(slide, 0x401, ((char *)slide, + LoadFarString(ZipfileCommTruncMsg))); + error = PK_WARN; + } + } /* endif (verbose) */ + + return error; + +} /* end function zi_end_central() */ + + + + + +/************************/ +/* Function zipinfo() */ +/************************/ + +int zipinfo(__G) /* return PK-type error code */ + __GDEF +{ + int do_this_file=FALSE, error, error_in_archive=PK_COOL; + int *fn_matched=NULL, *xn_matched=NULL; + unsigned j, members=0; + ulg tot_csize=0L, tot_ucsize=0L; + ulg endprev; /* buffers end of previous entry for zi_long()'s check + * of extra bytes */ + + +/*--------------------------------------------------------------------------- + Malloc space for check on unmatched filespecs (no big deal if one or both + are NULL). + ---------------------------------------------------------------------------*/ + + if (G.filespecs > 0 && + (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != NULL) + for (j = 0; j < G.filespecs; ++j) + fn_matched[j] = FALSE; + + if (G.xfilespecs > 0 && + (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != NULL) + for (j = 0; j < G.xfilespecs; ++j) + xn_matched[j] = FALSE; + +/*--------------------------------------------------------------------------- + Set file pointer to start of central directory, then loop through cen- + tral directory entries. Check that directory-entry signature bytes are + actually there (just a precaution), then process the entry. We know + the entire central directory is on this disk: we wouldn't have any of + this information unless the end-of-central-directory record was on this + disk, and we wouldn't 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 maybe someday we'll add + multi-disk support. + ---------------------------------------------------------------------------*/ + + uO.L_flag = FALSE; /* zipinfo mode: never convert name to lowercase */ + G.pInfo = G.info; /* (re-)initialize, (just to make sure) */ + G.pInfo->textmode = 0; /* so one can read on screen (is this ever used?) */ + + /* reset endprev for new zipfile; account for multi-part archives (?) */ + endprev = (G.crec.relative_offset_local_header == 4L)? 4L : 0L; + + + for (j = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) { + if (readbuf(__G__ G.sig, 4) == 0) + return PK_EOF; + if (strncmp(G.sig, central_hdr_sig, 4)) { /* just to make sure */ + Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j)); + 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 */ + + if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != + PK_COOL) + { + error_in_archive = error; /* might be warning */ + if (error > PK_WARN) /* fatal */ + return error; + } + + if (!G.process_all_files) { /* check if specified on command line */ + unsigned i; + + do_this_file = FALSE; + for (i = 0; i < G.filespecs; i++) + if (match(G.filename, G.pfnames[i], uO.C_flag)) { + do_this_file = TRUE; + 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)) { + do_this_file = FALSE; /* ^-- ignore case in match */ + if (xn_matched) + xn_matched[i] = TRUE; + 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) { + + switch (uO.lflag) { + case 1: + case 2: + fnprint(__G); + SKIP_(G.crec.extra_field_length) + SKIP_(G.crec.file_comment_length) + break; + + case 3: + case 4: + case 5: + if ((error = zi_short(__G)) != PK_COOL) { + error_in_archive = error; /* might be warning */ + if (error > PK_WARN) /* fatal */ + return error; + } + break; + + case 10: + Info(slide, 0, ((char *)slide, + LoadFarString(CentralDirEntry), j)); + if ((error = zi_long(__G__ &endprev)) != PK_COOL) { + error_in_archive = error; /* might be warning */ + if (error > PK_WARN) /* fatal */ + return error; + } + break; + + default: + SKIP_(G.crec.extra_field_length) + SKIP_(G.crec.file_comment_length) + break; + + } /* end switch (lflag) */ + + tot_csize += G.crec.csize; + tot_ucsize += G.crec.ucsize; + if (G.crec.general_purpose_bit_flag & 1) + tot_csize -= 12; /* don't count encryption header */ + ++members; + +#ifdef DLL + if ((G.statreportcb != NULL) && + (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn, + G.filename, NULL)) { + if (fn_matched) + free((zvoid *)fn_matched); + if (xn_matched) + free((zvoid *)xn_matched); + return IZ_CTRLC; /* cancel operation by user request */ + } +#endif +#ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ + UserStop(); +#endif + + } else { /* not listing this file */ + SKIP_(G.crec.extra_field_length) + SKIP_(G.crec.file_comment_length) + + } /* end if (list member?) */ + + } /* end for-loop (j: member files) */ + +/*--------------------------------------------------------------------------- + Check that we actually found requested files; if so, print totals. + ---------------------------------------------------------------------------*/ + + if (uO.tflag) { + char *sgn = ""; + int cfactor = ratio(tot_ucsize, tot_csize); + + if (cfactor < 0) { + sgn = "-"; + cfactor = -cfactor; + } + Info(slide, 0, ((char *)slide, LoadFarString(ZipfileStats), + members, (members==1)? nullStr:"s", tot_ucsize, + tot_csize, sgn, cfactor/10, cfactor%10)); + } + +/*--------------------------------------------------------------------------- + Check for unmatched filespecs on command line and print warning if any + found. + ---------------------------------------------------------------------------*/ + + if (fn_matched) { + for (j = 0; j < G.filespecs; ++j) + if (!fn_matched[j]) + Info(slide, 0x401, ((char *)slide, + LoadFarString(FilenameNotMatched), G.pfnames[j])); + free((zvoid *)fn_matched); + } + if (xn_matched) { + for (j = 0; j < G.xfilespecs; ++j) + if (!xn_matched[j]) + Info(slide, 0x401, ((char *)slide, + LoadFarString(ExclFilenameNotMatched), G.pxnames[j])); + free((zvoid *)xn_matched); + } + +/*--------------------------------------------------------------------------- + Double check that we're back at the end-of-central-directory record. + ---------------------------------------------------------------------------*/ + + if (readbuf(__G__ G.sig, 4) == 0) /* disk error? */ + return PK_EOF; + if (strncmp(G.sig, end_central_sig, 4)) { /* just to make sure again */ + Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); + error_in_archive = PK_WARN; /* didn't find sig */ + } + if (members == 0 && error_in_archive <= PK_WARN) + error_in_archive = PK_FIND; + + if (uO.lflag >= 10) + (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); + + return error_in_archive; + +} /* end function zipinfo() */ + + + + + +/************************/ +/* Function zi_long() */ +/************************/ + +static int zi_long(__G__ pEndprev) /* return PK-type error code */ + __GDEF + ulg *pEndprev; /* for zi_long() check of extra bytes */ +{ +#ifdef USE_EF_UT_TIME + iztimes z_utime; +#endif + int error, error_in_archive=PK_COOL; + ush hostnum, hostver, extnum, extver, methnum, xattr; + char workspace[12], attribs[22]; + ZCONST char *varmsg_str; + char unkn[16]; + static ZCONST char Far *os[NUM_HOSTS] = { + OS_FAT, OS_Amiga, OS_VMS, OS_Unix, OS_VMCMS, OS_AtariST, OS_HPFS, + OS_Macintosh, OS_ZSystem, OS_CPM, OS_TOPS20, OS_NTFS, OS_QDOS, + OS_Acorn, OS_VFAT, OS_MVS, OS_BeOS, OS_Tandem + }; + static ZCONST char Far *method[NUM_METHODS] = { + MthdNone, MthdShrunk, MthdRedF1, MthdRedF2, MthdRedF3, MthdRedF4, + MthdImplode, MthdToken, MthdDeflate, MthdEnDeflate, MthdDCLImplode + }; + static ZCONST char Far *dtypelng[4] = { + DeflNorm, DeflMax, DeflFast, DeflSFast + }; + + +/*--------------------------------------------------------------------------- + Check whether there's any extra space inside the zipfile. If *pEndprev is + zero, it's probably a signal that OS/2 extra fields are involved (with + unknown compressed size). We won't worry about prepended junk here... + ---------------------------------------------------------------------------*/ + + if (G.crec.relative_offset_local_header != *pEndprev && *pEndprev > 0L) { + /* GRR DEBUG + Info(slide, 0, ((char *)slide, + " [crec.relative_offset_local_header = %lu, endprev = %lu]\n", + G.crec.relative_offset_local_header, *pEndprev)); + */ + Info(slide, 0, ((char *)slide, LoadFarString(ExtraBytesPreceding), + (long)G.crec.relative_offset_local_header - (long)(*pEndprev))); + } + + /* calculate endprev for next time around (problem: extra fields may + * differ in length between local and central-directory records) */ + *pEndprev = G.crec.relative_offset_local_header + 4L + LREC_SIZE + + G.crec.filename_length + G.crec.extra_field_length + + G.crec.file_comment_length + G.crec.csize; + +/*--------------------------------------------------------------------------- + Read the extra field, if any. It may be used to get UNIX style modtime. + ---------------------------------------------------------------------------*/ + + if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0) + { + if (G.extra_field != NULL) { + free(G.extra_field); + G.extra_field = NULL; + } + error_in_archive = error; + /* The premature return in case of a "fatal" error (PK_EOF) is + * delayed until we analyze the extra field contents. + * This allows us to display all the other info that has been + * successfully read in. + */ + } + +/*--------------------------------------------------------------------------- + Print out various interesting things about the compressed file. + ---------------------------------------------------------------------------*/ + + hostnum = (ush)(G.pInfo->hostnum); + hostver = G.crec.version_made_by[0]; + extnum = (ush)MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS); + extver = G.crec.version_needed_to_extract[0]; + methnum = (ush)MIN(G.crec.compression_method, NUM_METHODS); + + (*G.message)((zvoid *)&G, (uch *)" ", 2L, 0); fnprint(__G); + + Info(slide, 0, ((char *)slide, LoadFarString(LocalHeaderOffset), + G.crec.relative_offset_local_header, + G.crec.relative_offset_local_header)); + + if (hostnum >= NUM_HOSTS) { + sprintf(unkn, LoadFarString(UnknownNo), + (int)G.crec.version_made_by[1]); + varmsg_str = unkn; + } else { + varmsg_str = LoadFarStringSmall(os[hostnum]); + } + Info(slide, 0, ((char *)slide, LoadFarString(HostOS), varmsg_str)); + Info(slide, 0, ((char *)slide, LoadFarString(EncodeSWVer), hostver/10, + hostver%10)); + + if (extnum >= NUM_HOSTS) { + sprintf(unkn, LoadFarString(UnknownNo), + (int)G.crec.version_needed_to_extract[1]); + varmsg_str = unkn; + } else { + varmsg_str = LoadFarStringSmall(os[extnum]); + } + Info(slide, 0, ((char *)slide, LoadFarString(MinOSCompReq), varmsg_str)); + Info(slide, 0, ((char *)slide, LoadFarString(MinSWVerReq), extver/10, + extver%10)); + + if (methnum >= NUM_METHODS) { + sprintf(unkn, LoadFarString(UnknownNo), G.crec.compression_method); + varmsg_str = unkn; + } else { + varmsg_str = LoadFarStringSmall(method[methnum]); + } + Info(slide, 0, ((char *)slide, LoadFarString(CompressMethod), varmsg_str)); + if (methnum == IMPLODED) { + Info(slide, 0, ((char *)slide, LoadFarString(SlideWindowSizeImplode), + (G.crec.general_purpose_bit_flag & 2)? '8' : '4')); + Info(slide, 0, ((char *)slide, LoadFarString(ShannonFanoTrees), + (G.crec.general_purpose_bit_flag & 4)? '3' : '2')); + } else if (methnum == DEFLATED) { + ush dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3); + + Info(slide, 0, ((char *)slide, LoadFarString(CompressSubtype), + LoadFarStringSmall(dtypelng[dnum]))); + } + + Info(slide, 0, ((char *)slide, LoadFarString(FileSecurity), + (G.crec.general_purpose_bit_flag & 1) ? nullStr : "not ")); + Info(slide, 0, ((char *)slide, LoadFarString(ExtendedLocalHdr), + (G.crec.general_purpose_bit_flag & 8) ? "yes" : "no")); + /* print upper 3 bits for amusement? */ + + /* For printing of date & time, a "char d_t_buf[21]" is required. + * To save stack space, we reuse the "char attribs[22]" buffer which + * is not used yet. + */ +# define d_t_buf attribs + + zi_time(__G__ &G.crec.last_mod_dos_datetime, NULL, d_t_buf); + Info(slide, 0, ((char *)slide, LoadFarString(FileModDate), d_t_buf)); +#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 or Macintosh */ + d_t_buf[0] = (char)0; /* signal "show local time" */ + zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf); + Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate), + d_t_buf, LoadFarStringSmall(LocalTime))); +#ifndef NO_GMTIME + d_t_buf[0] = (char)1; /* signal "show UTC (GMT) time" */ + zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf); + Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate), + d_t_buf, LoadFarStringSmall(GMTime))); +#endif /* !NO_GMTIME */ + } +#endif /* USE_EF_UT_TIME */ + + Info(slide, 0, ((char *)slide, LoadFarString(CRC32Value), G.crec.crc32)); + Info(slide, 0, ((char *)slide, LoadFarString(CompressedFileSize), + G.crec.csize)); + Info(slide, 0, ((char *)slide, LoadFarString(UncompressedFileSize), + G.crec.ucsize)); + Info(slide, 0, ((char *)slide, LoadFarString(FilenameLength), + G.crec.filename_length)); + Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldLength), + G.crec.extra_field_length)); + Info(slide, 0, ((char *)slide, LoadFarString(FileCommentLength), + G.crec.file_comment_length)); + Info(slide, 0, ((char *)slide, LoadFarString(FileDiskNum), + G.crec.disk_number_start + 1)); + Info(slide, 0, ((char *)slide, LoadFarString(ApparentFileType), + (G.crec.internal_file_attributes & 1)? "text" + : (G.crec.internal_file_attributes & 2)? "ebcdic" + : "binary")); /* changed to accept EBCDIC */ +#ifdef ATARI + printf(" external file attributes (hex): %.8lx\n", + G.crec.external_file_attributes); +#endif + xattr = (ush)((G.crec.external_file_attributes >> 16) & 0xFFFF); + if (hostnum == VMS_) { + char *p=attribs, *q=attribs+1; + int i, j, k; + + for (k = 0; k < 12; ++k) + workspace[k] = 0; + if (xattr & VMS_IRUSR) + workspace[0] = 'R'; + if (xattr & VMS_IWUSR) { + workspace[1] = 'W'; + workspace[3] = 'D'; + } + if (xattr & VMS_IXUSR) + workspace[2] = 'E'; + if (xattr & VMS_IRGRP) + workspace[4] = 'R'; + if (xattr & VMS_IWGRP) { + workspace[5] = 'W'; + workspace[7] = 'D'; + } + if (xattr & VMS_IXGRP) + workspace[6] = 'E'; + if (xattr & VMS_IROTH) + workspace[8] = 'R'; + if (xattr & VMS_IWOTH) { + workspace[9] = 'W'; + workspace[11] = 'D'; + } + if (xattr & VMS_IXOTH) + workspace[10] = 'E'; + + *p++ = '('; + for (k = j = 0; j < 3; ++j) { /* loop over groups of permissions */ + for (i = 0; i < 4; ++i, ++k) /* loop over perms within a group */ + if (workspace[k]) + *p++ = workspace[k]; + *p++ = ','; /* group separator */ + if (j == 0) + while ((*p++ = *q++) != ',') + ; /* system, owner perms are same */ + } + *p-- = 0; + *p = ')'; /* overwrite last comma */ + Info(slide, 0, ((char *)slide, LoadFarString(VMSFileAttributes), xattr, + attribs)); + + } else if (hostnum == AMIGA_) { + switch (xattr & AMI_IFMT) { + case AMI_IFDIR: attribs[0] = 'd'; break; + case AMI_IFREG: attribs[0] = '-'; break; + default: attribs[0] = '?'; break; + } + attribs[1] = (xattr & AMI_IHIDDEN)? 'h' : '-'; + attribs[2] = (xattr & AMI_ISCRIPT)? 's' : '-'; + attribs[3] = (xattr & AMI_IPURE)? 'p' : '-'; + attribs[4] = (xattr & AMI_IARCHIVE)? 'a' : '-'; + attribs[5] = (xattr & AMI_IREAD)? 'r' : '-'; + attribs[6] = (xattr & AMI_IWRITE)? 'w' : '-'; + attribs[7] = (xattr & AMI_IEXECUTE)? 'e' : '-'; + attribs[8] = (xattr & AMI_IDELETE)? 'd' : '-'; + attribs[9] = 0; /* better dlm the string */ + Info(slide, 0, ((char *)slide, LoadFarString(AmigaFileAttributes), + xattr, attribs)); + + } else if ((hostnum != FS_FAT_) && (hostnum != FS_HPFS_) && + (hostnum != FS_NTFS_) && (hostnum != FS_VFAT_) && + (hostnum != ACORN_) && + (hostnum != VM_CMS_) && (hostnum != MVS_)) + { /* assume Unix-like */ + switch ((unsigned)(xattr & UNX_IFMT)) { + case (unsigned)UNX_IFDIR: attribs[0] = 'd'; break; + case (unsigned)UNX_IFREG: attribs[0] = '-'; break; + case (unsigned)UNX_IFLNK: attribs[0] = 'l'; break; + case (unsigned)UNX_IFBLK: attribs[0] = 'b'; break; + case (unsigned)UNX_IFCHR: attribs[0] = 'c'; break; + case (unsigned)UNX_IFIFO: attribs[0] = 'p'; break; + case (unsigned)UNX_IFSOCK: attribs[0] = 's'; break; + default: attribs[0] = '?'; break; + } + attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-'; + attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-'; + attribs[7] = (xattr & UNX_IROTH)? 'r' : '-'; + + attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-'; + attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-'; + attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-'; + + if (xattr & UNX_IXUSR) + attribs[3] = (xattr & UNX_ISUID)? 's' : 'x'; + else + attribs[3] = (xattr & UNX_ISUID)? 'S' : '-'; /* S = undefined */ + if (xattr & UNX_IXGRP) + attribs[6] = (xattr & UNX_ISGID)? 's' : 'x'; /* == UNX_ENFMT */ + else + attribs[6] = (xattr & UNX_ISGID)? 'l' : '-'; + if (xattr & UNX_IXOTH) + attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x'; /* "sticky bit" */ + else + attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-'; /* T = undefined */ + attribs[10] = 0; + + Info(slide, 0, ((char *)slide, LoadFarString(UnixFileAttributes), xattr, + attribs)); + + } else { + Info(slide, 0, ((char *)slide, LoadFarString(NonMSDOSFileAttributes), + G.crec.external_file_attributes >> 8)); + + } /* endif (hostnum: external attributes format) */ + + if ((xattr=(ush)(G.crec.external_file_attributes & 0xFF)) == 0) + Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributes), + xattr)); + else if (xattr == 1) + Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesRO), + xattr)); + else + Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesAlpha), + xattr, (xattr&1)? "rdo " : nullStr, + (xattr&2)? "hid " : nullStr, + (xattr&4)? "sys " : nullStr, + (xattr&8)? "lab " : nullStr, + (xattr&16)? "dir " : nullStr, + (xattr&32)? "arc" : nullStr)); + +/*--------------------------------------------------------------------------- + Analyze the extra field, if any, and print the file comment, if any (the + filename has already been printed, above). That finishes up this file + entry... + ---------------------------------------------------------------------------*/ + + if (G.crec.extra_field_length > 0) { + uch *ef_ptr = G.extra_field; + ush ef_len = G.crec.extra_field_length; + ush eb_id, eb_datalen; + ZCONST char Far *ef_fieldname; + + if (error_in_archive > PK_WARN) /* fatal: can't continue */ + /* delayed "fatal error" return from extra field reading */ + return error; + if (G.extra_field == (uch *)NULL) + return PK_ERR; /* not consistent with crec length */ + + Info(slide, 0, ((char *)slide, LoadFarString(ExtraFields))); + + while (ef_len >= EB_HEADSIZE) { + eb_id = makeword(&ef_ptr[EB_ID]); + eb_datalen = makeword(&ef_ptr[EB_LEN]); + ef_ptr += EB_HEADSIZE; + ef_len -= EB_HEADSIZE; + + if (eb_datalen > (ush)ef_len) { + Info(slide, 0x421, ((char *)slide, + LoadFarString(ExtraFieldTrunc), eb_id, eb_datalen, ef_len)); + eb_datalen = ef_len; + } + + switch (eb_id) { + case EF_AV: + ef_fieldname = efAV; + break; + case EF_OS2: + ef_fieldname = efOS2; + break; + case EF_ACL: + ef_fieldname = efACL; + break; + case EF_NTSD: + ef_fieldname = efNTSD; + break; + case EF_PKVMS: + ef_fieldname = efPKVMS; + break; + case EF_IZVMS: + ef_fieldname = efIZVMS; + break; + case EF_PKW32: + ef_fieldname = efPKWin32; + break; + case EF_PKUNIX: + ef_fieldname = efPKUnix; + break; + case EF_IZUNIX: + ef_fieldname = efIZUnix; + if (G.crec.version_made_by[1] == UNIX_ && *pEndprev > 0L) + *pEndprev += 4L; /* also have UID/GID in local copy */ + break; + case EF_IZUNIX2: + ef_fieldname = efIZUnix2; + if (*pEndprev > 0L) + *pEndprev += 4L; /* 4 byte UID/GID in local copy */ + break; + case EF_TIME: + ef_fieldname = efTime; + break; + case EF_MAC3: + ef_fieldname = efMac3; + break; + case EF_JLMAC: + ef_fieldname = efJLMac; + break; + case EF_ZIPIT: + ef_fieldname = efZipIt; + break; + case EF_ZIPIT2: + ef_fieldname = efZipIt2; + break; + case EF_VMCMS: + ef_fieldname = efVMCMS; + break; + case EF_MVS: + ef_fieldname = efMVS; + break; + case EF_BEOS: + ef_fieldname = efBeOS; + break; + case EF_QDOS: + ef_fieldname = efQDOS; + break; + case EF_AOSVS: + ef_fieldname = efAOSVS; + break; + case EF_SPARK: /* from RISC OS */ + ef_fieldname = efSpark; + break; + case EF_MD5: + ef_fieldname = efMD5; + break; + case EF_ASIUNIX: + ef_fieldname = efASiUnix; + break; + default: + ef_fieldname = efUnknown; + break; + } + Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldType), + eb_id, LoadFarStringSmall(ef_fieldname), eb_datalen)); + + /* additional, field-specific information: */ + switch (eb_id) { + case EF_OS2: + case EF_ACL: + if (eb_datalen >= EB_OS2_HLEN) { + if (eb_id == EF_OS2) + ef_fieldname = OS2EAs; + else + ef_fieldname = ACLdata; + Info(slide, 0, ((char *)slide, + LoadFarString(ef_fieldname), makelong(ef_ptr))); + *pEndprev = 0L; /* no clue about csize of local */ + } + break; + case EF_NTSD: + if (eb_datalen >= EB_NTSD_C_LEN) { + Info(slide, 0, ((char *)slide, LoadFarString(NTSDData), + makelong(ef_ptr))); + *pEndprev = 0L; /* no clue about csize of local */ + } + break; + case EF_IZVMS: + if (eb_datalen >= 8) { + char *p, q[8]; + int compr = makeword(ef_ptr+4) & 7; + + *q = '\0'; + if (compr > 3) + compr = 3; + if (strncmp((char *)ef_ptr, "VFAB", 4) == 0) + p = "FAB"; + else if (strncmp((char *)ef_ptr, "VALL", 4) == 0) + p = "XABALL"; + else if (strncmp((char *)ef_ptr, "VFHC", 4) == 0) + p = "XABFHC"; + else if (strncmp((char *)ef_ptr, "VDAT", 4) == 0) + p = "XABDAT"; + else if (strncmp((char *)ef_ptr, "VRDT", 4) == 0) + p = "XABRDT"; + else if (strncmp((char *)ef_ptr, "VPRO", 4) == 0) + p = "XABPRO"; + else if (strncmp((char *)ef_ptr, "VKEY", 4) == 0) + p = "XABKEY"; + else if (strncmp((char *)ef_ptr, "VMSV", 4) == 0) { + p = "version"; + if (eb_datalen >= 16) { + q[0] = ' '; + q[1] = '('; + strncpy(q+2, (char *)ef_ptr+12, 4); + q[6] = ')'; + q[7] = '\0'; + } + } else + p = "version"; + Info(slide, 0, ((char *)slide, LoadFarString(izVMSdata), + LoadFarStringSmall(izVMScomp[compr]), + makeword(ef_ptr+6), p, q)); + } + break; + case EF_TIME: + if (eb_datalen >= 1) { + char types[80]; + int num = 0, len; + + *types = '\0'; + if (*ef_ptr & 1) { + strcpy(types, LoadFarString(UTmodification)); + ++num; + } + if (*ef_ptr & 2) { + len = strlen(types); + if (num) + types[len++] = '/'; + strcpy(types+len, LoadFarString(UTaccess)); + ++num; + if (*pEndprev > 0L) + *pEndprev += 4L; + } + if (*ef_ptr & 4) { + len = strlen(types); + if (num) + types[len++] = '/'; + strcpy(types+len, LoadFarString(UTcreation)); + ++num; + if (*pEndprev > 0L) + *pEndprev += 4L; + } + if (num > 0) + Info(slide, 0, ((char *)slide, + LoadFarString(UTdata), types, + num == 1? nullStr : "s")); + } + break; + case EF_MAC3: + if (eb_datalen >= EB_MAC3_HLEN) { + ulg eb_uc = makelong(ef_ptr); + unsigned mac3_flgs = makeword(ef_ptr+EB_FLGS_OFFS); + unsigned eb_is_uc = mac3_flgs & EB_M3_FL_UNCMPR; + + Info(slide, 0, ((char *)slide, LoadFarString(Mac3data), + eb_uc, eb_is_uc ? "un" : nullStr)); + if (eb_is_uc) { + if (*pEndprev > 0L) + *pEndprev += makelong(ef_ptr); + } else { + *pEndprev = 0L; /* no clue about csize of local */ + } + + Info(slide, 0, ((char *)slide, + LoadFarString(MacOSMAC3flags), + LoadFarStringSmall(mac3_flgs & EB_M3_FL_DATFRK ? + MacOS_DF : MacOS_RF), + (mac3_flgs & EB_M3_FL_TIME64 ? 64 : 32))); + zi_showMacTypeCreator(__G__ &ef_ptr[6]); + } + break; + case EF_ZIPIT2: + if (eb_datalen >= 5 && + strncmp((char *)ef_ptr, "ZPIT", 4) == 0) { + + if (eb_datalen >= 12) { + zi_showMacTypeCreator(__G__ &ef_ptr[4]); + } + } + + case EF_ZIPIT: + if (eb_datalen >= 5 && + strncmp((char *)ef_ptr, "ZPIT", 4) == 0) { + unsigned fnlen = ef_ptr[4]; + + if (eb_datalen >= fnlen + (5 + 8)) { + uch nullchar = ef_ptr[fnlen+5]; + + ef_ptr[fnlen+5] = '\0'; /* terminate filename */ + Info(slide, 0, ((char *)slide, + LoadFarString(ZipItFname), (char *)ef_ptr+5)); + ef_ptr[fnlen+5] = nullchar; + zi_showMacTypeCreator(__G__ &ef_ptr[fnlen+5]); + } + } + break; + case EF_JLMAC: + if (eb_datalen >= 40 && + strncmp((char *)ef_ptr, "JLEE", 4) == 0) + { + zi_showMacTypeCreator(__G__ &ef_ptr[4]); + + Info(slide, 0, ((char *)slide, + LoadFarString(MacOSJLEEflags), + LoadFarStringSmall(ef_ptr[31] & 1 ? + MacOS_DF : MacOS_RF))); + } + break; +#ifdef CMS_MVS + case EF_VMCMS: + case EF_MVS: + { + char type[100]; + + Info(slide, 0, ((char *)slide, + LoadFarString(VmMvsExtraField), + (getVMMVSexfield(type, ef_ptr-EB_HEADSIZE, + (unsigned)eb_datalen) > 0)? + type : LoadFarStringSmall(VmMvsInvalid))); + } + break; +#endif /* CMS_MVS */ + case EF_BEOS: + if (eb_datalen >= EB_BEOS_HLEN) { + ulg eb_uc = makelong(ef_ptr); + unsigned eb_is_uc = + *(ef_ptr+EB_FLGS_OFFS) & EB_BE_FL_UNCMPR; + + Info(slide, 0, ((char *)slide, LoadFarString(BeOSdata), + eb_uc, eb_is_uc ? "un" : nullStr)); + if (eb_is_uc) { + if (*pEndprev > 0L) + *pEndprev += makelong(ef_ptr); + } else { + *pEndprev = 0L; /* no clue about csize of local */ + } + } + break; + case EF_QDOS: + if (eb_datalen >= 4) { + Info(slide, 0, ((char *)slide, LoadFarString(QDOSdata), + ef_ptr[0], ef_ptr[1], ef_ptr[2], ef_ptr[3])); + } + break; + case EF_AOSVS: + if (eb_datalen >= 5) { + Info(slide, 0, ((char *)slide, LoadFarString(AOSVSdata), + ((int)(uch)ef_ptr[4])/10, ((int)(uch)ef_ptr[4])%10)); + } + break; + case EF_MD5: + if (eb_datalen >= 19) { + char md5[33]; + int i; + + for (i = 0; i < 16; ++i) + sprintf(&md5[i<<1], "%02x", ef_ptr[15-i]); + md5[32] = '\0'; + Info(slide, 0, ((char *)slide, LoadFarString(MD5data), + md5)); + break; + } /* else: fall through !! */ + default: + if (eb_datalen > 0) { + ush i, n; + + if (eb_datalen <= 24) { + Info(slide, 0, ((char *)slide, + LoadFarString(ColonIndent))); + n = eb_datalen; + } else { + Info(slide, 0, ((char *)slide, + LoadFarString(First20))); + n = 20; + } + for (i = 0; i < n; ++i) + Info(slide, 0, ((char *)slide, + LoadFarString(efFormat), ef_ptr[i])); + } + break; + } + (*G.message)((zvoid *)&G, (uch *)".", 1L, 0); + + ef_ptr += eb_datalen; + ef_len -= eb_datalen; + } + (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0); + } + + /* high bit == Unix/OS2/NT GMT times (mtime, atime); next bit == UID/GID */ + if ((xattr = (ush)((G.crec.external_file_attributes & 0xC000) >> 12)) & 8) + { + if (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_) + { + Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType), + "is", EF_IZUNIX, LoadFarStringSmall(efIZUnix), + (unsigned)(xattr&12), (xattr&4)? efIZuid : efIZnouid)); + if (*pEndprev > 0L) + *pEndprev += (ulg)(xattr&12); + } + else if (hostnum == FS_FAT_ && !(xattr&4)) + Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType), + "may be", EF_IZUNIX, LoadFarStringSmall(efIZUnix), 8, + efIZnouid)); + } + + if (!G.crec.file_comment_length) + Info(slide, 0, ((char *)slide, LoadFarString(NoFileComment))); + else { + Info(slide, 0, ((char *)slide, LoadFarString(FileCommBegin))); + if ((error = do_string(__G__ G.crec.file_comment_length, DISPL_8)) != + PK_COOL) + { + error_in_archive = error; /* might be warning */ + if (error > PK_WARN) /* fatal */ + return error; + } + Info(slide, 0, ((char *)slide, LoadFarString(FileCommEnd))); + } + + return error_in_archive; + +} /* end function zi_long() */ + + + + + +/*************************/ +/* Function zi_short() */ +/*************************/ + +static int zi_short(__G) /* return PK-type error code */ + __GDEF +{ +#ifdef USE_EF_UT_TIME + iztimes z_utime; + time_t *z_modtim; +#endif + int k, error, error_in_archive=PK_COOL; + ush methnum, hostnum, hostver, xattr; + char *p, workspace[12], attribs[16]; + char methbuf[5]; + static ZCONST char dtype[5]="NXFS"; /* normal, maximum, fast, superfast */ + static ZCONST char Far os[NUM_HOSTS+1][4] = { + "fat", "ami", "vms", "unx", "cms", "atr", "hpf", "mac", "zzz", + "cpm", "t20", "ntf", "qds", "aco", "vft", "mvs", "be ", "nsk", + "???" + }; + static ZCONST char Far method[NUM_METHODS+1][5] = { + "stor", "shrk", "re:1", "re:2", "re:3", "re:4", "i#:#", "tokn", + "def#", "edef", "dcli", "u###" + }; + + +/*--------------------------------------------------------------------------- + Print out various interesting things about the compressed file. + ---------------------------------------------------------------------------*/ + + methnum = (ush)MIN(G.crec.compression_method, NUM_METHODS); + hostnum = (ush)(G.pInfo->hostnum); + hostver = G.crec.version_made_by[0]; +/* + extnum = MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS); + extver = G.crec.version_needed_to_extract[0]; + */ + + zfstrcpy(methbuf, method[methnum]); + if (methnum == IMPLODED) { + methbuf[1] = (char)((G.crec.general_purpose_bit_flag & 2)? '8' : '4'); + methbuf[3] = (char)((G.crec.general_purpose_bit_flag & 4)? '3' : '2'); + } else if (methnum == DEFLATED) { + ush dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3); + methbuf[3] = dtype[dnum]; + } else if (methnum >= NUM_METHODS) { /* unknown */ + sprintf(&methbuf[1], "%03u", G.crec.compression_method); + } + + for (k = 0; k < 15; ++k) + attribs[k] = ' '; + attribs[15] = 0; + + xattr = (ush)((G.crec.external_file_attributes >> 16) & 0xFFFF); + switch (hostnum) { + case VMS_: + { int i, j; + + for (k = 0; k < 12; ++k) + workspace[k] = 0; + if (xattr & VMS_IRUSR) + workspace[0] = 'R'; + if (xattr & VMS_IWUSR) { + workspace[1] = 'W'; + workspace[3] = 'D'; + } + if (xattr & VMS_IXUSR) + workspace[2] = 'E'; + if (xattr & VMS_IRGRP) + workspace[4] = 'R'; + if (xattr & VMS_IWGRP) { + workspace[5] = 'W'; + workspace[7] = 'D'; + } + if (xattr & VMS_IXGRP) + workspace[6] = 'E'; + if (xattr & VMS_IROTH) + workspace[8] = 'R'; + if (xattr & VMS_IWOTH) { + workspace[9] = 'W'; + workspace[11] = 'D'; + } + if (xattr & VMS_IXOTH) + workspace[10] = 'E'; + + p = attribs; + 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 */ + } + *--p = ' '; /* overwrite last comma */ + if ((p - attribs) < 12) + sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10); + } + break; + + case FS_FAT_: + case FS_HPFS_: + case FS_NTFS_: + case VM_CMS_: + case FS_VFAT_: + case MVS_: + case ACORN_: + xattr = (ush)(G.crec.external_file_attributes & 0xFF); + sprintf(attribs, ".r.-... %d.%d", hostver/10, hostver%10); + attribs[2] = (xattr & 0x01)? '-' : 'w'; + attribs[5] = (xattr & 0x02)? 'h' : '-'; + attribs[6] = (xattr & 0x04)? 's' : '-'; + attribs[4] = (xattr & 0x20)? 'a' : '-'; + if (xattr & 0x10) { + attribs[0] = 'd'; + attribs[3] = 'x'; + } else + attribs[0] = '-'; + if (IS_VOLID(xattr)) + attribs[0] = 'V'; + else if ((p = strrchr(G.filename, '.')) != (char *)NULL) { + ++p; + if (STRNICMP(p, "com", 3) == 0 || STRNICMP(p, "exe", 3) == 0 || + STRNICMP(p, "btm", 3) == 0 || STRNICMP(p, "cmd", 3) == 0 || + STRNICMP(p, "bat", 3) == 0) + attribs[3] = 'x'; + } + break; + + case AMIGA_: + switch (xattr & AMI_IFMT) { + case AMI_IFDIR: attribs[0] = 'd'; break; + case AMI_IFREG: attribs[0] = '-'; break; + default: attribs[0] = '?'; break; + } + attribs[1] = (xattr & AMI_IHIDDEN)? 'h' : '-'; + attribs[2] = (xattr & AMI_ISCRIPT)? 's' : '-'; + attribs[3] = (xattr & AMI_IPURE)? 'p' : '-'; + attribs[4] = (xattr & AMI_IARCHIVE)? 'a' : '-'; + attribs[5] = (xattr & AMI_IREAD)? 'r' : '-'; + attribs[6] = (xattr & AMI_IWRITE)? 'w' : '-'; + attribs[7] = (xattr & AMI_IEXECUTE)? 'e' : '-'; + attribs[8] = (xattr & AMI_IDELETE)? 'd' : '-'; + sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10); + break; + + default: /* assume Unix-like */ + switch ((unsigned)(xattr & UNX_IFMT)) { + case (unsigned)UNX_IFDIR: attribs[0] = 'd'; break; + case (unsigned)UNX_IFREG: attribs[0] = '-'; break; + case (unsigned)UNX_IFLNK: attribs[0] = 'l'; break; + case (unsigned)UNX_IFBLK: attribs[0] = 'b'; break; + case (unsigned)UNX_IFCHR: attribs[0] = 'c'; break; + case (unsigned)UNX_IFIFO: attribs[0] = 'p'; break; + case (unsigned)UNX_IFSOCK: attribs[0] = 's'; break; + default: attribs[0] = '?'; break; + } + attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-'; + attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-'; + attribs[7] = (xattr & UNX_IROTH)? 'r' : '-'; + attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-'; + attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-'; + attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-'; + + if (xattr & UNX_IXUSR) + attribs[3] = (xattr & UNX_ISUID)? 's' : 'x'; + else + attribs[3] = (xattr & UNX_ISUID)? 'S' : '-'; /* S==undefined */ + if (xattr & UNX_IXGRP) + attribs[6] = (xattr & UNX_ISGID)? 's' : 'x'; /* == UNX_ENFMT */ + else + /* attribs[6] = (xattr & UNX_ISGID)? 'l' : '-'; real 4.3BSD */ + attribs[6] = (xattr & UNX_ISGID)? 'S' : '-'; /* SunOS 4.1.x */ + if (xattr & UNX_IXOTH) + attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x'; /* "sticky bit" */ + else + attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-'; /* T==undefined */ + + sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10); + break; + + } /* end switch (hostnum: external attributes format) */ + + Info(slide, 0, ((char *)slide, "%s %s %8lu ", attribs, + LoadFarStringSmall(os[hostnum]), G.crec.ucsize)); + Info(slide, 0, ((char *)slide, "%c", + (G.crec.general_purpose_bit_flag & 1)? + ((G.crec.internal_file_attributes & 1)? 'T' : 'B') : /* encrypted */ + ((G.crec.internal_file_attributes & 1)? 't' : 'b'))); /* plaintext */ + k = (G.crec.extra_field_length || + /* a local-only "UX" (old Unix/OS2/NT GMT times "IZUNIX") e.f.? */ + ((G.crec.external_file_attributes & 0x8000) && + (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_))); + Info(slide, 0, ((char *)slide, "%c", k? + ((G.crec.general_purpose_bit_flag & 8)? 'X' : 'x') : /* extra field */ + ((G.crec.general_purpose_bit_flag & 8)? 'l' : '-'))); /* no extra field */ + /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ extended local header or not */ + + if (uO.lflag == 4) { + ulg csiz = G.crec.csize; + + if (G.crec.general_purpose_bit_flag & 1) + csiz -= 12; /* if encrypted, don't count encryption header */ + Info(slide, 0, ((char *)slide, "%3d%%", + (ratio(G.crec.ucsize,csiz)+5)/10)); + } else if (uO.lflag == 5) + Info(slide, 0, ((char *)slide, " %8lu", G.crec.csize)); + + /* Read the extra field, if any. The extra field info may be used + * in the file modification time section, below. + */ + if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0) + { + if (G.extra_field != NULL) { + free(G.extra_field); + G.extra_field = NULL; + } + error_in_archive = error; + /* We do not return prematurely in case of a "fatal" error (PK_EOF). + * This does not hurt here, because we do not need to read from the + * zipfile again before the end of this function. + */ + } + + /* For printing of date & time, a "char d_t_buf[16]" is required. + * To save stack space, we reuse the "char attribs[16]" buffer whose + * content is no longer needed. + */ +# define d_t_buf attribs +#ifdef USE_EF_UT_TIME + z_modtim = 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) + ? &z_utime.mtime : NULL; + TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7.0 or Macintosh */ + d_t_buf[0] = (char)0; /* signal "show local time" */ +#else +# define z_modtim NULL +#endif + Info(slide, 0, ((char *)slide, " %s %s ", methbuf, + zi_time(__G__ &G.crec.last_mod_dos_datetime, z_modtim, d_t_buf))); + fnprint(__G); + +/*--------------------------------------------------------------------------- + Skip the file comment, if any (the filename has already been printed, + above). That finishes up this file entry... + ---------------------------------------------------------------------------*/ + + SKIP_(G.crec.file_comment_length) + + return error_in_archive; + +} /* end function zi_short() */ + + + + + +/**************************************/ +/* Function zi_showMacTypeCreator() */ +/**************************************/ + +static void zi_showMacTypeCreator(__G__ ebfield) + __GDEF + uch *ebfield; +{ + /* not every Type / Creator character is printable */ + if (isprint(ebfield[0]) && isprint(ebfield[1]) && + isprint(ebfield[2]) && isprint(ebfield[3]) && + isprint(ebfield[4]) && isprint(ebfield[5]) && + isprint(ebfield[6]) && isprint(ebfield[7])) { + Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata), + ebfield[0], ebfield[1], ebfield[2], ebfield[3], + ebfield[4], ebfield[5], ebfield[6], ebfield[7])); + } else { + Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata1), + (((ulg)ebfield[0]) << 24) + + (((ulg)ebfield[1]) << 16) + + (((ulg)ebfield[2]) << 8) + + ((ulg)ebfield[3]), + (((ulg)ebfield[4]) << 24) + + (((ulg)ebfield[5]) << 16) + + (((ulg)ebfield[6]) << 8) + + ((ulg)ebfield[7]))); + } +} /* end function zi_showMacTypeCreator() */ + + + + + +/************************/ +/* Function zi_time() */ +/************************/ + +static char *zi_time(__G__ datetimez, modtimez, d_t_str) + __GDEF + ZCONST ulg *datetimez; + ZCONST time_t *modtimez; + char *d_t_str; +{ + unsigned yr, mo, dy, hh, mm, ss; + char monthbuf[4]; + ZCONST char *monthstr; + static ZCONST char Far month[12][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; +#ifdef USE_EF_UT_TIME + struct tm *t; +#endif + + + +/*--------------------------------------------------------------------------- + Convert the file-modification date and time info to a string of the form + "1991 Feb 23 17:15:00", "23-Feb-91 17:15" or "19910223.171500", depending + on values of lflag and T_flag. If using Unix-time extra fields, convert + to local time or not, depending on value of first character in d_t_str[]. + ---------------------------------------------------------------------------*/ + +#ifdef USE_EF_UT_TIME + if (modtimez != NULL) { +#ifndef NO_GMTIME + /* check for our secret message from above... */ + t = (d_t_str[0] == (char)1)? gmtime(modtimez) : localtime(modtimez); +#else + t = localtime(modtimez); +#endif + if (uO.lflag > 9 && t == (struct tm *)NULL) + /* time conversion error in verbose listing format, + * return string with '?' instead of data + */ + return (strcpy(d_t_str, LoadFarString(YMDHMSTimeError))); + } 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); + + hh = (unsigned)(t->tm_hour); + mm = (unsigned)(t->tm_min); + ss = (unsigned)(t->tm_sec); + } else +#endif /* USE_EF_UT_TIME */ + { + yr = ((unsigned)(*datetimez >> 25) & 0x7f) + 80; + mo = ((unsigned)(*datetimez >> 21) & 0x0f); + dy = ((unsigned)(*datetimez >> 16) & 0x1f); + + hh = (((unsigned)*datetimez >> 11) & 0x1f); + mm = (((unsigned)*datetimez >> 5) & 0x3f); + ss = (((unsigned)*datetimez << 1) & 0x3e); + } + + if (mo == 0 || mo > 12) { + sprintf(monthbuf, LoadFarString(BogusFmt), mo); + monthstr = monthbuf; + } else + monthstr = LoadFarStringSmall(month[mo-1]); + + if (uO.lflag > 9) /* verbose listing format */ + sprintf(d_t_str, LoadFarString(YMDHMSTime), yr+1900, monthstr, dy, hh, + mm, ss); + else if (uO.T_flag) + sprintf(d_t_str, LoadFarString(DecimalTime), yr+1900, mo, dy, hh, mm, + ss); + else /* was: if ((uO.lflag >= 3) && (uO.lflag <= 5)) */ + sprintf(d_t_str, LoadFarString(DMYHMTime), dy, monthstr, yr%100, hh, + mm); + + return d_t_str; + +} /* end function zi_time() */ + +#endif /* !NO_ZIPINFO */ diff --git a/utils/Install/wxmain.cpp b/utils/Install/wxmain.cpp new file mode 100644 index 0000000000..4d6b8d4be1 --- /dev/null +++ b/utils/Install/wxmain.cpp @@ -0,0 +1,315 @@ +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#include "wx/wx.h" +#endif + +#include "wx/resource.h" +#include "install.h" +#include "instsup.h" + +#include + +#if !defined(__EMX__) && !defined(__OS2__) && !defined(WIN32) && !defined(WINNT) +#define stricmp strcasecmp +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +extern char installdir[]; + +#ifdef __cplusplus +} +#endif + +typedef struct _wxCommands { + int id; + char file[50]; +} wxCommands; + +#define COMMANDMAX 20 + +wxCommands wxcommands[COMMANDMAX]; +char finishedscript[256] = ""; +char percentname[256] = ""; + +class MyApp: public wxApp +{ +public: + MyApp(); + + virtual bool OnInit(); + + virtual ~MyApp(); +}; + +class MyDialog : public wxDialog +{ +public: + void handle_button(wxCommandEvent& event); +}; + +class MyThread : public wxThread +{ +public: + virtual void *Entry(); +}; + +void *MyThread::Entry() +{ + install_thread(NULL); + return NULL; +} + +MyDialog *dialog = NULL; + +IMPLEMENT_APP(MyApp) + +MyApp::MyApp() +{ +} + +wxCondition *InstCond = NULL; + +void updatepercent(void) +{ + wxGauge *tmp = (wxGauge *)wxFindWindowByName(percentname, dialog); + + if(tmp) + { + unsigned long sliderpos; + int pixels = 100; + extern int current_file, files; + + sliderpos = (unsigned long)(((float)(current_file)/(float)files)*pixels); + tmp->SetValue(sliderpos); + } +} + +int parse_ini(char *filename) +{ + FILE *f; + int b; + + for(b=0;bLoadFromResource(NULL, "dialog1"); + dialog->Show(TRUE); + + /*MyApp::SetTopWindow(dialog);*/ + } + else if(stricmp(entry, "closeold") == 0) + { + if(dialog) + dialog->Destroy(); + dialog = NULL; + } + else if(stricmp(entry, "getcheck") == 0) + { + wxCheckBox *tmp = (wxCheckBox *)wxFindWindowByName(entrydata, dialog); + + if(tmp) + { + if(!tmp->GetValue()) + { + parse_ini(entrydata2); + bytesread = 0; + } + } + } + else if(stricmp(entry, "gettext") == 0) + { + wxTextCtrl *tmp = (wxTextCtrl *)wxFindWindowByName(entrydata, dialog); + wxString bleah; + + if(tmp) + { + if((bleah = tmp->GetValue())) + strcpy(installdir, bleah); + } + } + else if(stricmp(entry, "settext") == 0) + { + wxTextCtrl *tmp = (wxTextCtrl *)wxFindWindowByName(entrydata, dialog); + + if(tmp) + tmp->SetValue(installdir); + } + else if(stricmp(entry, "message") == 0) + mesg(entrydata); + else if(stricmp(entry, "disable") == 0) + { + wxButton *tmp = (wxButton *)wxFindWindowByName(entrydata, dialog); + if(tmp) + tmp->Disable(); + } + else if(stricmp(entry, "grabfile") == 0) + grabfile(entrydata); + else if(stricmp(entry, "remove") == 0) + remove(entrydata); + else if(stricmp(entry, "system") == 0) + wxExecute(entrydata); + else if(stricmp(entry, "startinst") == 0) + { + strcpy(percentname, entrydata); + strcpy(finishedscript, entrydata2); + + /* I couldn't get it working with threads, even when + using conditions it blocked the message loop making + it unreadable, so I am going with wxYield for the + moment. */ +#if 0 + MyThread *thread = new MyThread(); + + if ( thread->Create() != wxTHREAD_NO_ERROR ) + { + error("Can't create thread!"); + } + strcpy(finishedscript, entrydata); + + InstCond = new wxCondition(); + + thread->Run(); + + wxMutex *test = new wxMutex(); + + InstCond->Wait(*test); +#endif + install_thread(NULL); + parse_ini(finishedscript); + } + else if(stricmp(entry, "mleview") == 0) + { + FILE *f; + unsigned long bytes; + char buffer[1025]; + wxTextCtrl *tmp = (wxTextCtrl *)wxFindWindowByName(entrydata, dialog); + + if(tmp) + { + grabfile(entrydata2); + + if((f = fopen(entrydata2, "rb"))!= NULL) + { + while(!feof(f)) + { + memset(buffer, 0, 1025); + bytes = fread(buffer, 1, 1024, f); + *tmp << buffer; + } + fclose(f); + } + remove(entrydata2); + tmp->ShowPosition(0); + } + + } + else if(stricmp(entry, "setbutton") == 0) + { + for(b=0;bConnect( atol(entrydata), -1, wxEVT_COMMAND_BUTTON_CLICKED, + (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) + &MyDialog::handle_button); + + } + } + fclose(f); + remove(filename); + return TRUE; + } + remove(filename); + return FALSE; +} + +void MyDialog::handle_button(wxCommandEvent& event ) +{ + int b; + + for(b=0;b