summaryrefslogtreecommitdiff
path: root/os2
diff options
context:
space:
mode:
Diffstat (limited to 'os2')
-rw-r--r--os2/makefile.os2560
-rw-r--r--os2/match32.asm175
-rw-r--r--os2/os2.c481
-rw-r--r--os2/os2acl.c385
-rw-r--r--os2/os2acl.h34
-rw-r--r--os2/os2zip.c1213
-rw-r--r--os2/os2zip.h84
-rw-r--r--os2/osdep.h173
-rw-r--r--os2/zip.def3
-rw-r--r--os2/zipup.h16
10 files changed, 3124 insertions, 0 deletions
diff --git a/os2/makefile.os2 b/os2/makefile.os2
new file mode 100644
index 0000000..8e5e7cf
--- /dev/null
+++ b/os2/makefile.os2
@@ -0,0 +1,560 @@
+# Makefile for Zip, ZipCloak, ZipNote and ZipSplit
+
+# Supported Make utilities:
+# - Microsoft/IBM nmake
+# - dmake 3.8 or higher
+# - GNU make, at least version 3.68
+# - NOT watcom make
+# For Microsoft and Watcom C, better use NMAKE,
+# otherwise it doesn't matter.
+
+# Supported 16-bit C Compilers (created programs run under OS/2 1.x and 2.x):
+# - Microsoft C 6.00A
+# - Watcom C/C++ 16-bit
+
+# Supported 32-bit C Compilers (created programs run under OS/2 2.x only):
+# - GNU gcc (emx kit 0.9c or newer)
+# - IBM C Set/2 or C Set++ - does not yet work with ASM code
+# - Watcom C/C++ 32-bit - does not yet work with ASM code
+# - Borland C++ - no ASM code yet
+# - MetaWare High C/C++ - no ASM code yet
+
+# Supported Cross-Compilers for MS-DOS:
+# - Microsoft C 6.00A (16-bit)
+# - Watcom C/C++ (16- and 32-bit)
+# - GNU gcc (emx kit 0.9c or newer, 32-bit)
+
+# Supported Cross-Compilers for Win32 (WinNT/Win95):
+# - GNU gcc (emx kit 0.9c or newer, with RSXNT 1.4 or newer)
+
+# Supported Assemblers:
+# - Microsoft MASM 6.00 with Microsoft C, IBM C
+# - Watcom WASM with Watcom C/C++
+# - GNU as with GNU gcc
+
+# To use MASM 5.x instead of MASM 6.00:
+# - set AS="masm -T -Ml"
+# - set ASEOL=";"
+
+
+# To use, enter "make/nmake/dmake -f os2/makefile.os2"
+# (this makefile depends on its name being "os2/makefile.os2").
+
+# Add -DNO_ASM to CFLAGS and define OBJA to `nothing' if you do not have
+# masm or ml.
+# Add -DDYN_ALLOC to ASFLAGS if you have defined it in tailor.h or CFLAGS
+
+# Note: assembly language modules are really only supported for
+# Microsoft 16-bit and GNU gcc 32-bit compilation.
+
+# Notes on 16-bit (Microsoft C 6.00) compilation:
+
+# The resulting programs can be used under OS/2 protected mode only.
+# A larger stack has to be used for OS/2 because system calls
+# use more stack than under DOS, 8k is recommended by Microsoft.
+# Note that __STDC__ has to be defined explicitly with C 6.00 when -Ze
+# is given, because Microsoft disables __STDC__ when their extensions
+# are enabled. This is different from the C 5.10 behaviour.
+
+# Notes on 32-bit OS/2 compilation:
+
+# The resulting programs can be used under OS/2 protected
+# mode of OS/2 2.x only, not under 1.x and not under DOS.
+# It makes no difference if __STDC__ is defined or not.
+# Borland C++ works with DYN_ALLOC only.
+
+# Special Notes on IBM C/C++ compilation:
+
+# The older C compiler (C Set/2) breaks, while optimizing, on deflate.c
+# and trees.c (generates incorrect code). The newer C++ compiler (C Set++)
+# doesn't but instead breaks on crypt.c in the initial version and up to
+# CSD level 003. Starting with CSD level 004, it doesn't break any longer.
+
+# Notes on Watcom C/C++ compilation for DOS with the PMODE/W extender:
+#
+# You need to add the following section to your \watcom\binb\wlsystem.lnk
+# file and also need to copy pmodew.exe to the same directory:
+#
+# system begin pmodew
+# option osname='PMODE/W'
+# libpath %WATCOM%\lib386
+# libpath %WATCOM%\lib386\dos
+# op stub=pmodew.exe
+# format os2 le
+# end
+#
+# PMODE/W 1.16 or higher is required.
+
+
+default:
+ @echo "Enter $(MAKE) -f os2/makefile.os2 target"
+ @echo "where target is one of:"
+ @echo " msc mscdos ibm ibmdyn ibmdebug ibmprof metaware borland"
+ @echo " gcc gccdyn gcczlib gccdebug gccdos gccwin32 gccw32dyn"
+ @echo " watcom watcom16 watcomdos watcom16dos pmodew"
+
+# MS C 6.00 for OS/2, 16-bit
+msc:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="cl -nologo -AL -Ocegit -Gs $(FP)" \
+ CFLAGS="-W1 -Zep -J -G2 -D__STDC__ -DOS2 -DASM_CRC" \
+ AS="ml -nologo -c -Zm -Cp" \
+ ASFLAGS="-D__LARGE__ -D__286" \
+ LDFLAGS="-F 2000 -Lp -Fe" \
+ LDFLAGS2="-link /noe /pm:vio" \
+ OUT="-Fo" \
+ OBJ=".obj" \
+ CRC32="crc_i86" \
+ OBJA="match.obj" \
+ DEF="os2\zip.def"
+
+# MS C 6.00 for OS/2, 16-bit, debug
+mscdebug:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="cl -nologo -AL -Zi -Od $(FP)" \
+ CFLAGS="-W1 -Zep -J -G2 -D__STDC__ -DOS2 -DASM_CRC" \
+ AS="ml -nologo -c -Zim -Cp" \
+ ASFLAGS="-D__LARGE__ -D__286" \
+ LDFLAGS="-F 2000 -Lp -Fe" \
+ LDFLAGS2="-link /noe /pm:vio" \
+ OUT="-Fo" \
+ OBJ=".obj" \
+ CRC32="crc_i86" \
+ OBJA="match.obj" \
+ DEF="os2\zip.def"
+
+# crosscompilation for MS-DOS with MS C 6.00
+mscdos:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="cl -nologo -AL -Ocegit -Gs $(FP)" \
+ CFLAGS="-W1 -Zep -J -D__STDC__ -DDOS -DASM_CRC -DDYN_ALLOC" \
+ AS="ml -nologo -c -Zm -Cp" \
+ ASFLAGS="-D__LARGE__ -DDYN_ALLOC" \
+ LDFLAGS="-F 2000 -Lr -Fe" \
+ LDFLAGS2="-link /noe /exe" \
+ OUT="-Fo" \
+ OBJ=".obj" \
+ CRC32="crc_i86" \
+ OBJA="match.obj" \
+ OBJ2="msdos.obj" OBJU2="msdos_.obj" \
+ OSDEP_H="msdos/osdep.h" ZIPUP_H="msdos/zipup.h"
+
+
+# IBM C Set/2, statically linked runtime
+ibm:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="icc -Q -O -Gs" \
+ CFLAGS="-Sm -Sp1 -DOS2 -DNO_ASM" \
+ AS="ml -nologo -c -Zm -Cp" \
+ ASFLAGS="" \
+ LDFLAGS="-B/ST:0x50000 -Fe" \
+ LDFLAGS2="" \
+ OUT="-Fo" \
+ OBJ=".obj" \
+ OBJA="" \
+ DEF="os2/zip.def"
+
+# IBM C Set/2, dynamically linked runtime
+ibmdyn:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="icc -Q -O -Gd -Gs" \
+ CFLAGS="-Sm -Sp1 -DOS2 -DNO_ASM" \
+ AS="ml -nologo -c -Zm -Cp" \
+ ASFLAGS="" \
+ LDFLAGS="-B/ST:0x50000 -Fe" \
+ LDFLAGS2="" \
+ OUT="-Fo" \
+ OBJ=".obj" \
+ OBJA="" \
+ DEF="os2/zip.def"
+
+# IBM C Set/2, debug version
+ibmdebug:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="icc -Q -Ti" \
+ CFLAGS="-Sm -Sp1 -DOS2 -DNO_ASM -Tm" \
+ AS="ml -nologo -c -Zim -Cp" \
+ ASFLAGS="" \
+ LDFLAGS="-B/ST:0x50000 -Fe" \
+ LDFLAGS2="" \
+ OUT="-Fo" \
+ OBJ=".obj" \
+ OBJA="" \
+ DEF="os2/zip.def"
+
+# IBM C Set/2, profiling version for PROFIT
+ibmprof:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="icc -Q -O -Gs -Gh -Ti" \
+ CFLAGS="-Sm -Sp1 -DOS2 -DNO_ASM" \
+ AS="ml -nologo -c -Zm -Cp" \
+ ASFLAGS="" \
+ LDFLAGS="-B/ST:0x50000 -Fe" \
+ LDFLAGS2="profit.obj" \
+ OUT="-Fo" \
+ OBJ=".obj" \
+ OBJA="" \
+ DEF="os2/zip.def"
+
+# Watcom C/386 9.0 or higher
+watcom:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="wcl386 -bt=os2v2 -zq -Ox -s" \
+ CFLAGS="-Zp1 -DOS2 -DNO_ASM" \
+ AS="wasm -bt=os2v2 -3p" \
+ ASFLAGS="" \
+ LDFLAGS="-k0x50000 -x -l=os2v2 -Fe=" \
+ LDFLAGS2="" \
+ OUT="-Fo" \
+ OBJ=".obj" \
+ OBJA="" \
+ DIRSEP="\\" \
+ AS_DIRSEP="\\"
+
+# Watcom C/286 9.0 or higher
+watcom16:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="wcl -bt=os2 -zq -ml -Ox -s" \
+ CFLAGS="-Zp1 -DOS2 -DNO_ASM" \
+ AS="wasm -bt=os2 -2p -ml" \
+ ASFLAGS="" \
+ LDFLAGS="/\"option newfiles\" -k0x3000 -x -l=os2 -Fe=" \
+ LDFLAGS2="" \
+ OUT="-Fo" \
+ OBJ=".obj" \
+ OBJA="" \
+ DIRSEP="\\" \
+ AS_DIRSEP="\\"
+
+# Watcom C/386 9.0 or higher, crosscompilation for DOS, DOS4GW extender
+watcomdos:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="wcl386 -bt=dos4g -zq -Ox -s" \
+ CFLAGS="-Zp1 -DDOS -DMSDOS -DNO_ASM" \
+ AS="wasm -bt=dos4g -3p" \
+ ASFLAGS="" \
+ LDFLAGS="-k0x50000 -x -l=dos4g -Fe=" \
+ LDFLAGS2="" \
+ OUT="-Fo" \
+ OBJ=".obj" \
+ OBJA="" \
+ OBJ2="msdos.obj" \
+ OBJU2="msdos_.obj" \
+ OSDEP_H="msdos/osdep.h" \
+ ZIPUP_H="msdos/zipup.h" \
+ DIRSEP="\\" \
+ AS_DIRSEP="\\"
+
+# Watcom C/386 9.0 or higher, crosscompilation for DOS, PMODE/W extender
+pmodew:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="wcl386 -bt=dos4g -zq -Ox -s" \
+ CFLAGS="-Zp1 -DDOS -DMSDOS -DASM_CRC" \
+ AS="wasm -bt=dos4g -3p" \
+ ASFLAGS="" \
+ LDFLAGS="-k0x50000 -x -l=pmodew -Fe=" \
+ LDFLAGS2="" \
+ OUT="-Fo" \
+ OBJ=".obj" \
+ CRC32="crc_i386" \
+ OBJA="match32.obj" \
+ OBJ2="msdos.obj" \
+ OBJU2="msdos_.obj" \
+ OSDEP_H="msdos/osdep.h" \
+ ZIPUP_H="msdos/zipup.h" \
+ DIRSEP="\\" \
+ AS_DIRSEP="\\"
+
+# Watcom C/286 9.0 or higher, crosscompilation for DOS
+watcom16dos:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="wcl -bt=dos -zq -ml -Ox -s" \
+ CFLAGS="-Zp1 -DDOS -DMSDOS -DDYN_ALLOC -DNO_ASM" \
+ AS="wasm -bt=dos -2p -ml" \
+ ASFLAGS="-DDYN_ALLOC" \
+ LDFLAGS="-k0x2000 -x -l=dos -Fe=" \
+ LDFLAGS2="" \
+ OUT="-Fo" \
+ OBJ=".obj" \
+ OBJA="" \
+ OBJ2="msdos.obj" \
+ OBJU2="msdos_.obj" \
+ OSDEP_H="msdos/osdep.h" \
+ ZIPUP_H="msdos/zipup.h" \
+ DIRSEP="\\" \
+ AS_DIRSEP="\\"
+
+# MetaWare High C/C++ 3.2
+metaware:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="hc -O2" \
+ CFLAGS="-D__32BIT__ -DOS2 -DNO_ASM" \
+ AS="ml -nologo -c -Zm -Cp" \
+ ASFLAGS="" \
+ LDFLAGS="-o " \
+ LDFLAGS2="" \
+ OUT="-o ./" \
+ OBJ=".obj" \
+ DEF="-Hdef=os2/zip.def"
+
+# Borland C++
+borland:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="bcc -O" \
+ CFLAGS="-w- -DOS2 -DDYN_ALLOC -DNO_ASM" \
+ AS="ml -nologo -c -Zm -Cp" \
+ ASFLAGS="" \
+ LDFLAGS="-e" \
+ LDFLAGS2="" \
+ OUT="-o" \
+ OBJ=".obj" \
+ OBJA="" \
+ DEF="-sDos2/zip.def"
+
+# emx 0.9c, gcc, OMF format, statically linked C runtime and emx
+gcc:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="gcc -Zomf -O -Wimplicit" \
+ CFLAGS="-DOS2 -DASM_CRC" \
+ AS="gcc -Zomf" \
+ ASFLAGS="-Di386" \
+ LDFLAGS="-o ./" \
+ LDFLAGS2="-Zsys -Zstack 320 -s -Zsmall-conv" \
+ OUT="-o" \
+ OBJ=".obj" \
+ CRC32="crc_gcc" \
+ OBJA="matchgcc.obj" \
+ DEF="os2/zip.def"
+
+# emx 0.9c, gcc, OMF format, dynamically linked C runtime and emx
+gccdyn:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="gcc -Zomf -O -Wimplicit" \
+ CFLAGS="-DOS2 -DASM_CRC" \
+ AS="gcc -Zomf" \
+ ASFLAGS="-Di386" \
+ LDFLAGS="-o ./" \
+ LDFLAGS2="-Zcrtdll -Zstack 320 -s" \
+ OUT="-o" \
+ OBJ=".obj" \
+ CRC32="crc_gcc" \
+ OBJA="matchgcc.obj" \
+ DEF="os2/zip.def"
+
+# emx 0.9c, gcc, OMF format, statically linked zlib, C runtime, and emx
+gcczlib:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="gcc -Zomf -O -Wimplicit" \
+ CFLAGS="-DOS2 -DUSE_ZLIB" \
+ AS="gcc -Zomf" \
+ ASFLAGS="-Di386 -DUSE_ZLIB" \
+ LDFLAGS="-o ./" \
+ LDFLAGS2="-L. -lzlib -Zsys -Zstack 320 -s -Zsmall-conv" \
+ OUT="-o" \
+ OBJ=".obj" \
+ CRC32="crc32" \
+ OBJA="" \
+ DEF="os2/zip.def"
+
+# emx 0.9c, gcc, a.out format, with debug info for gdb
+gccdebug:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="gcc -g -Wimplicit" \
+ CFLAGS="-DOS2 -DASM_CRC" \
+ AS="gcc" \
+ ASFLAGS="-Di386" \
+ LDFLAGS="-o ./" \
+ LDFLAGS2="" \
+ OUT="-o" \
+ OBJ=".o" \
+ CRC32="crc_gcc" \
+ OBJA="matchgcc.o" \
+ DEF="os2/zip.def"
+
+# emx 0.9c, gcc, a.out format, for MS-DOS
+gccdos:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="gcc -O -Wimplicit" \
+ CFLAGS="-DDOS -DMSDOS -DASM_CRC" \
+ AS="gcc" \
+ ASFLAGS="-Di386" \
+ LDFLAGS="-o ./" \
+ LDFLAGS2="-s -Zsmall-conv" \
+ OUT="-o" \
+ OBJ=".o" \
+ CRC32="crc_gcc" \
+ OBJA="matchgcc.o" \
+ OBJ2="msdos.o" \
+ OBJU2="msdos_.o" \
+ OSDEP_H="msdos/osdep.h" \
+ ZIPUP_H="msdos/zipup.h"
+
+# emx 0.9c, gcc, RSXNT 1.4, cross-compilation for Win32
+gccwin32:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="gcc -Zwin32 -O -m486 -Wall" \
+ CFLAGS="-DWIN32 -DASM_CRC" \
+ AS="gcc -Zwin32" \
+ ASFLAGS="-Di386" \
+ LDFLAGS="-o ./" \
+ LDFLAGS2="-ladvapi32 -Zsys -Zsmall-conv -s" \
+ OUT="-o" \
+ OBJ=".o" \
+ CRC32="crc_gcc" \
+ OBJA="matchgcc.o" \
+ OBJ2="win32zip.o win32.o nt.o" \
+ OBJU2="win32_.o" \
+ OSDEP_H="win32/osdep.h" \
+ ZIPUP_H="win32/zipup.h" \
+ DEF="win32/zip.def"
+
+# emx 0.9c, gcc, RSXNT 1.4, cross-compilation for Win32, use emx C rtl DLL
+gccw32dyn:
+ $(MAKE) -f os2/makefile.os2 zips \
+ CC="gcc -Zwin32 -Zcrtdll=crtrsxnt -O -m486 -Wall" \
+ CFLAGS="-DWIN32 -DASM_CRC" \
+ AS="gcc -Zwin32" \
+ ASFLAGS="-Di386" \
+ LDFLAGS="-o ./" \
+ LDFLAGS2="-ladvapi32 -s" \
+ OUT="-o" \
+ OBJ=".o" \
+ CRC32="crc_gcc" \
+ OBJA="matchgcc.o" \
+ OBJ2="win32zip.o win32.o nt.o" \
+ OBJU2="win32_.o" \
+ OSDEP_H="win32/osdep.h" \
+ ZIPUP_H="win32/zipup.h" \
+ DEF="win32/zip.def"
+
+# VPATH = .;os2
+
+# variables
+
+#default settings for target dependent macros:
+DIRSEP = /
+AS_DIRSEP = /
+# LOCAL_OPTS =
+CCFLAGS = $(CFLAGS) $(LOCAL_OPTS)
+
+OSDEP_H = os2/osdep.h
+ZIPUP_H = os2/os2zip.h os2/zipup.h
+CRC32 = crc32
+
+
+OBJZ = zip$(OBJ) zipfile$(OBJ) zipup$(OBJ) fileio$(OBJ) util$(OBJ) \
+ $(CRC32)$(OBJ) crctab$(OBJ) globals$(OBJ) \
+ deflate$(OBJ) trees$(OBJ) crypt$(OBJ) ttyio$(OBJ)
+OBJ2 = os2zip$(OBJ) os2$(OBJ) os2acl$(OBJ)
+
+OBJU = zipfile_$(OBJ) fileio_$(OBJ) util_$(OBJ) globals$(OBJ)
+OBJU2 = os2zip_$(OBJ)
+
+OBJN = zipnote$(OBJ) $(OBJU) $(OBJU2)
+OBJS = zipsplit$(OBJ) $(OBJU) $(OBJU2)
+OBJC = zipcloak$(OBJ) crctab$(OBJ) crypt_$(OBJ) ttyio$(OBJ) $(OBJU) $(OBJU2)
+
+ZIP_H = zip.h ziperr.h tailor.h $(OSDEP_H)
+
+# rules
+
+.SUFFIXES: .c $(OBJ)
+
+.c$(OBJ):
+ $(CC) -c -I. $(CCFLAGS) $<
+
+.asm$(OBJ):
+ $(AS) $(ASFLAGS) $< $(ASEOL)
+
+# targets
+
+zips: zip.exe zipnote.exe zipsplit.exe zipcloak.exe
+
+zip$(OBJ): zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipfile$(OBJ): zipfile.c $(ZIP_H)
+zipup$(OBJ): zipup.c $(ZIP_H) revision.h crypt.h $(ZIPUP_H)
+fileio$(OBJ): fileio.c $(ZIP_H)
+util$(OBJ): util.c $(ZIP_H)
+globals$(OBJ): globals.c $(ZIP_H)
+deflate$(OBJ): deflate.c $(ZIP_H)
+trees$(OBJ): trees.c $(ZIP_H)
+crc32$(OBJ): crc32.c $(ZIP_H)
+crctab$(OBJ): crctab.c $(ZIP_H)
+crypt$(OBJ): crypt.c $(ZIP_H) crypt.h ttyio.h
+ttyio$(OBJ): ttyio.c $(ZIP_H) crypt.h ttyio.h
+
+os2zip$(OBJ): os2/os2zip.c $(ZIP_H) os2/os2zip.h os2/os2acl.h
+ $(CC) -c -I. $(CCFLAGS) os2$(DIRSEP)os2zip.c
+
+os2$(OBJ): os2/os2.c $(ZIP_H) os2/os2zip.h
+ $(CC) -c -I. $(CCFLAGS) os2$(DIRSEP)os2.c
+
+os2acl$(OBJ): os2/os2acl.c os2/os2acl.h
+ $(CC) -c -I. $(CCFLAGS) os2$(DIRSEP)os2acl.c
+
+msdos$(OBJ): msdos/msdos.c $(ZIP_H)
+ $(CC) -c -I. $(CCFLAGS) msdos$(DIRSEP)msdos.c
+
+win32zip$(OBJ): win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h
+ $(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)win32zip.c
+
+win32$(OBJ): win32/win32.c $(ZIP_H) win32/win32zip.h
+ $(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)win32.c
+
+nt$(OBJ): win32/nt.c win32/nt.h
+ $(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)nt.c
+
+crc_i86$(OBJ): msdos/crc_i86.asm # 16bit only
+ $(AS) $(ASFLAGS) msdos$(AS_DIRSEP)crc_i86.asm $(ASEOL)
+
+crc_i386$(OBJ): win32/crc_i386.asm # 32bit, MASM
+ $(AS) $(ASFLAGS) win32$(AS_DIRSEP)crc_i386.asm $(ASEOL)
+
+crc_gcc$(OBJ): crc_i386.S # 32bit, GNU AS
+ $(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S
+
+match$(OBJ): msdos/match.asm
+ $(AS) $(ASFLAGS) msdos$(AS_DIRSEP)match.asm $(ASEOL)
+
+match32$(OBJ): win32/match32.asm
+ $(AS) $(ASFLAGS) win32$(AS_DIRSEP)match32.asm
+
+matchgcc$(OBJ): match.S
+ $(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ match.S
+
+zipcloak$(OBJ): zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipnote$(OBJ): zipnote.c $(ZIP_H) revision.h
+zipsplit$(OBJ): zipsplit.c $(ZIP_H) revision.h
+
+zipfile_$(OBJ): zipfile.c $(ZIP_H)
+ $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ zipfile.c
+
+fileio_$(OBJ): fileio.c $(ZIP_H)
+ $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ fileio.c
+
+util_$(OBJ): util.c $(ZIP_H) os2/os2zip.h
+ $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ util.c
+
+crypt_$(OBJ): crypt.c $(ZIP_H) crypt.h ttyio.h
+ $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ crypt.c
+
+os2zip_$(OBJ): os2/os2zip.c $(ZIP_H) os2/os2zip.h
+ $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ os2$(DIRSEP)os2zip.c
+
+msdos_$(OBJ): msdos/msdos.c $(ZIP_H)
+ $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ msdos$(DIRSEP)msdos.c
+
+win32_$(OBJ): win32/win32.c $(ZIP_H) win32/win32zip.h
+ $(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ win32$(DIRSEP)win32.c
+
+zip.exe: $(OBJZ) $(OBJ2) $(OBJA)
+ $(CC) $(LDFLAGS)$@ $(DEF) $(OBJZ) $(OBJ2) $(OBJA) $(LDFLAGS2)
+
+zipcloak.exe: $(OBJC)
+ $(CC) $(LDFLAGS)$@ $(DEF) $(OBJC) $(LDFLAGS2)
+
+zipnote.exe: $(OBJN)
+ $(CC) $(LDFLAGS)$@ $(DEF) $(OBJN) $(LDFLAGS2)
+
+zipsplit.exe: $(OBJS)
+ $(CC) $(LDFLAGS)$@ $(DEF) $(OBJS) $(LDFLAGS2)
diff --git a/os2/match32.asm b/os2/match32.asm
new file mode 100644
index 0000000..ef9a541
--- /dev/null
+++ b/os2/match32.asm
@@ -0,0 +1,175 @@
+;===========================================================================
+; Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+;
+; See the accompanying file LICENSE, version 2004-May-22 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at: ftp://ftp.info-zip.org/pub/infozip/licen; Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+;===========================================================================
+;
+; match32.asm by Jean-loup Gailly.
+
+; match32.asm, optimized version of longest_match() in deflate.c
+; To be used only with 32 bit flat model. To simplify the code, the option
+; -DDYN_ALLOC is not supported.
+; This file is only optional. If you don't have an assembler, use the
+; C version (add -DNO_ASM to CFLAGS in makefile and remove match.o
+; from OBJI). If you have reduced WSIZE in zip.h, then make sure this is
+; assembled with an equivalent -DWSIZE=<whatever>.
+
+; Caution: this module works for IBM's C/C++ compiler versions 2 and 3
+; and for Watcom's 32-bit C/C++ compiler. Both pass the first (and only)
+; argument for longest_match in the EAX register, not on the stack, with
+; the default calling conventions (_System would use the stack).
+;
+;==============================================================================
+;
+; Do NOT assemble this source if external crc32 routine from zlib gets used.
+;
+ IFNDEF USE_ZLIB
+;
+ .386
+
+ name match
+
+BSS32 segment dword USE32 public 'BSS'
+ extrn window : byte
+ extrn prev : word
+ extrn prev_length : dword
+ extrn strstart : dword
+ extrn match_start : dword
+ extrn max_chain_length : dword
+ extrn good_match : dword
+ extrn nice_match : dword
+BSS32 ends
+
+CODE32 segment dword USE32 public 'CODE'
+ assume cs:CODE32, ds:FLAT, ss:FLAT
+
+ public match_init
+ public longest_match
+
+ ifndef WSIZE
+ WSIZE equ 32768 ; keep in sync with zip.h !
+ endif
+ MIN_MATCH equ 3
+ MAX_MATCH equ 258
+ MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
+ MAX_DIST equ (WSIZE-MIN_LOOKAHEAD)
+
+; initialize or check the variables used in match.asm.
+
+match_init proc near
+ ret
+match_init endp
+
+; -----------------------------------------------------------------------
+; Set match_start to the longest match starting at the given string and
+; return its length. Matches shorter or equal to prev_length are discarded,
+; in which case the result is equal to prev_length and match_start is
+; garbage.
+; IN assertions: cur_match is the head of the hash chain for the current
+; string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+
+; int longest_match(cur_match)
+
+longest_match proc near
+
+ ; return address ; esp+16
+ push ebp ; esp+12
+ push edi ; esp+8
+ push esi ; esp+4
+
+ lea ebx,window
+ add ebx,2
+ window_off equ dword ptr [esp]
+ push ebx ; esp
+
+; match equ esi
+; scan equ edi
+; chain_length equ ebp
+; best_len equ ebx
+; limit equ edx
+
+ mov esi,eax ; cur_match
+ mov edx,strstart
+ mov ebp,max_chain_length ; chain_length = max_chain_length
+ mov edi,edx
+ sub edx,MAX_DIST ; limit = strstart-MAX_DIST
+ cld ; string ops increment esi and edi
+ jae short limit_ok
+ sub edx,edx ; limit = NIL
+limit_ok:
+ add edi,window_off ; edi = offset(window + strstart + 2)
+ mov ebx,prev_length ; best_len = prev_length
+ mov cx,[edi-2] ; cx = scan[0..1]
+ mov ax,[ebx+edi-3] ; ax = scan[best_len-1..best_len]
+ cmp ebx,good_match ; do we have a good match already?
+ jb do_scan
+ shr ebp,2 ; chain_length >>= 2
+ jmp short do_scan
+
+ align 4 ; align destination of branch
+long_loop:
+; at this point, edi == scan+2, esi == cur_match
+ mov ax,[ebx+edi-3] ; ax = scan[best_len-1..best_len]
+ mov cx,[edi-2] ; cx = scan[0..1]
+short_loop:
+; at this point, edi == scan+2, esi == cur_match,
+; ax = scan[best_len-1..best_len] and cx = scan[0..1]
+ and esi,WSIZE-1 ; not needed if WSIZE=32768
+ dec ebp ; --chain_length
+ shl esi,1 ; cur_match as word index
+ mov si,prev[esi] ; cur_match = prev[cur_match]
+ ; top word of esi is still 0
+ jz the_end
+ cmp esi,edx ; cur_match <= limit ?
+ jbe short the_end
+do_scan:
+ cmp ax,word ptr window[ebx+esi-1] ; check match at best_len-1
+ jne short_loop
+ cmp cx,word ptr window[esi] ; check min_match_length match
+ jne short_loop
+
+ add esi,window_off ; esi = match
+ mov ecx,(MAX_MATCH-2)/2 ; scan for at most MAX_MATCH bytes
+ mov eax,edi ; eax = scan+2
+ repe cmpsw ; loop until mismatch
+ je maxmatch ; match of length MAX_MATCH?
+mismatch:
+ mov cl,[edi-2] ; mismatch on first or second byte?
+ xchg eax,edi ; edi = scan+2, eax = end of scan
+ sub cl,[esi-2] ; cl = 0 if first bytes equal
+ sub eax,edi ; eax = len
+ sub esi,window_off ; esi = match - (2 + offset(window))
+ sub esi,eax ; esi = cur_match (= match - len)
+ sub cl,1 ; set carry if cl == 0 (can't use DEC)
+ adc eax,0 ; eax = carry ? len+1 : len
+ cmp eax,ebx ; len > best_len ?
+ jle long_loop
+ mov match_start,esi ; match_start = cur_match
+ mov ebx,eax ; ebx = best_len = len
+ ifdef FULL_SEARCH
+ cmp eax,MAX_MATCH ; len >= MAX_MATCH ?
+ else
+ cmp eax,nice_match ; len >= nice_match ?
+ endif
+ jl long_loop
+the_end:
+ mov eax,ebx ; result = eax = best_len
+ pop ebx
+ pop esi
+ pop edi
+ pop ebp
+ ret
+maxmatch: ; come here if maximum match
+ cmpsb ; increment esi and edi
+ jmp mismatch ; force match_length = MAX_LENGTH
+
+longest_match endp
+
+CODE32 ends
+;
+ ENDIF ; !USE_ZLIB
+;
+ end
diff --git a/os2/os2.c b/os2/os2.c
new file mode 100644
index 0000000..355eea8
--- /dev/null
+++ b/os2/os2.c
@@ -0,0 +1,481 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include "zip.h"
+
+#ifndef UTIL /* the companion #endif is a bit of ways down ... */
+
+#include <time.h>
+#if defined(__IBMC__) || defined(MSC)
+#include <direct.h>
+#endif
+
+/* Extra malloc() space in names for cutpath() */
+#define PAD 0
+#define PATH_END '/'
+
+
+#include "os2zip.h"
+
+/* Library functions not in (most) header files */
+
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+/* Local functions */
+local char *readd OF((DIR *));
+
+
+local char *readd(d)
+DIR *d; /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+ no more entries or an error occurs. */
+{
+ struct dirent *e;
+
+ e = readdir(d);
+ return e == NULL ? (char *) NULL : e->d_name;
+}
+
+int wild(w)
+char *w; /* path/pattern to match */
+/* If not in exclude mode, expand the pattern based on the contents of the
+ file system. Return an error code in the ZE_ class. */
+{
+ DIR *d; /* stream for reading directory */
+ char *e; /* name found in directory */
+ int r; /* temporary variable */
+ char *n; /* constructed name from directory */
+ int f; /* true if there was a match */
+ char *a; /* alloc'ed space for name */
+ char *p; /* path */
+ char *q; /* name */
+ char v[5]; /* space for device current directory */
+
+ if (volume_label == 1) {
+ volume_label = 2;
+ label = getVolumeLabel((w != NULL && w[1] == ':') ? to_up(w[0]) : '\0',
+ &label_time, &label_mode, &label_utim);
+ if (label != NULL) {
+ newname(label, 0, 0);
+ }
+ if (w == NULL || (w[1] == ':' && w[2] == '\0')) return ZE_OK;
+ /* "zip -$ foo a:" can be used to force drive name */
+ }
+
+ if (w == NULL)
+ return ZE_OK;
+
+ /* special handling of stdin request */
+ if (strcmp(w, "-") == 0) /* if compressing stdin */
+ return newname(w, 0, 0);
+
+ /* Allocate and copy pattern */
+ if ((p = a = malloc(strlen(w) + 1)) == NULL)
+ return ZE_MEM;
+ strcpy(p, w);
+
+ /* catch special case: treat "*.*" as "*" for DOS-impaired people */
+ r = strlen(p);
+ if (strcmp(p + r - 3, "*.*") == 0)
+ p[r - 2] = '\0';
+
+ /* Normalize path delimiter as '/'. */
+ for (q = p; *q; q++) /* use / consistently */
+ if (*q == '\\')
+ *q = '/';
+
+ /* Only name can have special matching characters */
+ if ((q = isshexp(p)) != NULL &&
+ (strrchr(q, '/') != NULL || strrchr(q, ':') != NULL))
+ {
+ free((zvoid *)a);
+ return ZE_PARMS;
+ }
+
+ /* Separate path and name into p and q */
+ if ((q = strrchr(p, '/')) != NULL && (q == p || q[-1] != ':'))
+ {
+ *q++ = '\0'; /* path/name -> path, name */
+ if (*p == '\0') /* path is just / */
+ p = strcpy(v, "/.");
+ }
+ else if ((q = strrchr(p, ':')) != NULL)
+ { /* has device and no or root path */
+ *q++ = '\0';
+ p = strcat(strcpy(v, p), ":"); /* copy device as path */
+ if (*q == '/') /* -> device:/., name */
+ {
+ strcat(p, "/");
+ q++;
+ }
+ strcat(p, ".");
+ }
+ else if (recurse && (strcmp(p, ".") == 0 || strcmp(p, "..") == 0))
+ { /* current or parent directory */
+ /* I can't understand Mark's code so I am adding a hack here to get
+ * "zip -r foo ." to work. Allow the dubious "zip -r foo .." but
+ * reject "zip -rm foo ..".
+ */
+ if (dispose && strcmp(p, "..") == 0)
+ ziperr(ZE_PARMS, "cannot remove parent directory");
+ q = "*";
+ }
+ else /* no path or device */
+ {
+ q = p;
+ p = strcpy(v, ".");
+ }
+ if (recurse && *q == '\0') {
+ q = "*";
+ }
+ /* Search that level for matching names */
+ if ((d = opendir(p)) == NULL)
+ {
+ free((zvoid *)a);
+ return ZE_MISS;
+ }
+ if ((r = strlen(p)) > 1 &&
+ (strcmp(p + r - 2, ":.") == 0 || strcmp(p + r - 2, "/.") == 0))
+ *(p + r - 1) = '\0';
+ f = 0;
+ while ((e = readd(d)) != NULL) {
+ if (strcmp(e, ".") && strcmp(e, "..") && MATCH(q, e, 0))
+ {
+ f = 1;
+ if (strcmp(p, ".") == 0) { /* path is . */
+ r = procname(e, 0); /* name is name */
+ if (r) {
+ f = 0;
+ break;
+ }
+ } else
+ {
+ if ((n = malloc(strlen(p) + strlen(e) + 2)) == NULL)
+ {
+ free((zvoid *)a);
+ closedir(d);
+ return ZE_MEM;
+ }
+ n = strcpy(n, p);
+ if (n[r = strlen(n) - 1] != '/' && n[r] != ':')
+ strcat(n, "/");
+ r = procname(strcat(n, e), 0); /* name is path/name */
+ free((zvoid *)n);
+ if (r) {
+ f = 0;
+ break;
+ }
+ }
+ }
+ }
+ closedir(d);
+
+ /* Done */
+ free((zvoid *)a);
+ return f ? ZE_OK : ZE_MISS;
+}
+
+int procname(n, caseflag)
+char *n; /* name to process */
+int caseflag; /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude). Return
+ an error code in the ZE_ class. */
+{
+ char *a; /* path and name for recursion */
+ DIR *d; /* directory stream from opendir() */
+ char *e; /* pointer to name from readd() */
+ int m; /* matched flag */
+ char *p; /* path for recursion */
+ struct stat s; /* result of stat() */
+ struct zlist far *z; /* steps through zfiles list */
+
+ if (n == NULL) /* volume_label request in freshen|delete mode ?? */
+ return ZE_OK;
+
+ if (strcmp(n, "-") == 0) /* if compressing stdin */
+ return newname(n, 0, caseflag);
+ else if (LSSTAT(n, &s)
+#if defined(__TURBOC__) || defined(__WATCOMC__)
+ /* For these 2 compilers, stat() succeeds on wild card names! */
+ || isshexp(n)
+#endif
+ )
+ {
+ /* Not a file or directory--search for shell expression in zip file */
+ p = ex2in(n, 0, (int *)NULL); /* shouldn't affect matching chars */
+ m = 1;
+ for (z = zfiles; z != NULL; z = z->nxt) {
+ if (MATCH(p, z->iname, caseflag))
+ {
+ z->mark = pcount ? filter(z->zname, caseflag) : 1;
+ if (verbose)
+ fprintf(mesg, "zip diagnostic: %scluding %s\n",
+ z->mark ? "in" : "ex", z->name);
+ m = 0;
+ }
+ }
+ free((zvoid *)p);
+ return m ? ZE_MISS : ZE_OK;
+ }
+
+ /* Live name--use if file, recurse if directory */
+ for (p = n; *p; p++) /* use / consistently */
+ if (*p == '\\')
+ *p = '/';
+ if ((s.st_mode & S_IFDIR) == 0)
+ {
+ /* add or remove name of file */
+ if ((m = newname(n, 0, caseflag)) != ZE_OK)
+ return m;
+ } else {
+ /* Add trailing / to the directory name */
+ if ((p = malloc(strlen(n)+2)) == NULL)
+ return ZE_MEM;
+ if (strcmp(n, ".") == 0 || strcmp(n, "/.") == 0) {
+ *p = '\0'; /* avoid "./" prefix and do not create zip entry */
+ } else {
+ strcpy(p, n);
+ a = p + strlen(p);
+ if (a[-1] != '/')
+ strcpy(a, "/");
+ if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+ free((zvoid *)p);
+ return m;
+ }
+ }
+ /* recurse into directory */
+ if (recurse && (d = opendir(n)) != NULL)
+ {
+ while ((e = readd(d)) != NULL) {
+ if (strcmp(e, ".") && strcmp(e, ".."))
+ {
+ if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+ {
+ closedir(d);
+ free((zvoid *)p);
+ return ZE_MEM;
+ }
+ strcat(strcpy(a, p), e);
+ if ((m = procname(a, caseflag)) != ZE_OK) /* recurse on name */
+ {
+ if (m == ZE_MISS)
+ zipwarn("name not matched: ", a);
+ else
+ ziperr(m, a);
+ }
+ free((zvoid *)a);
+ }
+ }
+ closedir(d);
+ }
+ free((zvoid *)p);
+ } /* (s.st_mode & S_IFDIR) == 0) */
+ return ZE_OK;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x; /* external file name */
+int isdir; /* input: x is a directory */
+int *pdosflag; /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+ string or NULL if not enough memory. */
+{
+ char *n; /* internal file name (malloc'ed) */
+ char *t; /* shortened name */
+ int dosflag;
+
+ dosflag = dosify || IsFileSystemFAT(x) || (x == label);
+ if (!dosify && use_longname_ea && (t = GetLongPathEA(x)) != NULL)
+ {
+ x = t;
+ dosflag = 0;
+ }
+
+ /* Find starting point in name before doing malloc */
+ /* Strip drive specification */
+ t = *x && *(x + 1) == ':' ? x + 2 : x;
+ /* Strip "//host/share/" part of a UNC name */
+ if ((!strncmp(x,"//",2) || !strncmp(x,"\\\\",2)) &&
+ (x[2] != '\0' && x[2] != '/' && x[2] != '\\')) {
+ n = x + 2;
+ while (*n != '\0' && *n != '/' && *n != '\\')
+ n++; /* strip host name */
+ if (*n != '\0') {
+ n++;
+ while (*n != '\0' && *n != '/' && *n != '\\')
+ n++; /* strip `share' name */
+ }
+ if (*n != '\0')
+ t = n + 1;
+ }
+ /* Strip leading "/" to convert an absolute path into a relative path */
+ while (*t == '/' || *t == '\\')
+ t++;
+ /* Strip leading "./" as well as drive letter */
+ while (*t == '.' && (t[1] == '/' || t[1] == '\\'))
+ t += 2;
+
+ /* Make changes, if any, to the copied name (leave original intact) */
+ for (n = t; *n; n++)
+ if (*n == '\\')
+ *n = '/';
+
+ if (!pathput)
+ t = last(t, PATH_END);
+
+ /* Malloc space for internal name and copy it */
+ if ((n = malloc(strlen(t) + 1)) == NULL)
+ return NULL;
+ strcpy(n, t);
+
+ if (dosify)
+ msname(n);
+
+ /* Returned malloc'ed name */
+ if (pdosflag)
+ *pdosflag = dosflag;
+ return n;
+}
+
+
+char *in2ex(n)
+char *n; /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+ string or NULL if not enough memory. */
+{
+ char *x; /* external file name */
+
+ if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+ return NULL;
+ strcpy(x, n);
+
+ return x;
+}
+
+
+void stamp(f, d)
+char *f; /* name of file to change */
+ulg d; /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+ SetFileTime(f, d);
+}
+
+ulg filetime(f, a, n, t)
+char *f; /* name of file to get info on */
+ulg *a; /* return value: file attributes */
+long *n; /* return value: file size */
+iztimes *t; /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0. Else, return the file's last
+ modified date and time as an MSDOS date and time. The date and
+ time is returned in a long with the date most significant to allow
+ unsigned integer comparison of absolute times. Also, if a is not
+ a NULL pointer, store the file attributes there, with the high two
+ bytes being the Unix attributes, and the low byte being a mapping
+ of that to DOS attributes. If n is not NULL, store the file size
+ there. If t is not NULL, the file's access, modification and creation
+ times are stored there as UNIX time_t values.
+ If f is "-", use standard input as the file. If f is a device, return
+ a file size of -1 */
+{
+ struct stat s; /* results of stat() */
+ char *name;
+ ulg r;
+ unsigned int len = strlen(f);
+ int isstdin = !strcmp(f, "-");
+
+ if (f == label) {
+ if (a != NULL)
+ *a = label_mode;
+ if (n != NULL)
+ *n = -2L; /* convention for a label name */
+ if (t != NULL)
+ t->atime = t->mtime = t->ctime = label_utim;
+ return label_time;
+ }
+
+ if ((name = malloc(len + 1)) == NULL) {
+ ZIPERR(ZE_MEM, "filetime");
+ }
+ strcpy(name, f);
+ if (name[len - 1] == '/')
+ name[len - 1] = '\0';
+ /* not all systems allow stat'ing a file with / appended */
+
+ if (isstdin) {
+ /* it is common for some PC based compilers to
+ fail with fstat() on devices or pipes */
+ if (fstat(fileno(stdin), &s) != 0) {
+ s.st_mode = S_IFREG; s.st_size = -1L;
+ }
+ time(&s.st_ctime);
+ s.st_atime = s.st_mtime = s.st_ctime;
+ } else if (LSSTAT(name, &s) != 0) {
+ /* Accept about any file kind including directories
+ * (stored with trailing / with -r option)
+ */
+ free(name);
+ return 0;
+ }
+
+ if (a != NULL) {
+ *a = ((ulg)s.st_mode << 16) | (isstdin ? 0L : (ulg)GetFileMode(name));
+ }
+ if (n != NULL)
+ *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+#ifdef __WATCOMC__
+ /* of course, Watcom always has to make an exception */
+ if (s.st_atime == 312764400)
+ s.st_atime = s.st_mtime;
+ if (s.st_ctime == 312764400)
+ s.st_ctime = s.st_mtime;
+#endif
+ if (t != NULL) {
+ t->atime = s.st_atime;
+ t->mtime = s.st_mtime;
+ t->ctime = s.st_ctime;
+ }
+
+ r = GetFileTime(name);
+ free(name);
+
+ return r;
+}
+
+int deletedir(d)
+char *d; /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+ Return the result of rmdir(), delete(), or system().
+ */
+{
+ return rmdir(d);
+}
+
+
+#if defined MY_ZCALLOC /* Special zcalloc function for MEMORY16 (MSDOS/OS2) */
+
+#ifdef MSC /* Microsoft C */
+
+zvoid far *zcalloc (unsigned items, unsigned size)
+{
+ return (zvoid far *)halloc((long)items, size);
+}
+
+zvoid zcfree (zvoid far *ptr)
+{
+ hfree((void huge *)ptr);
+}
+
+#endif /* MSC */
+
+#endif /* MY_ZCALLOC */
+
+#endif /* !UTIL */
diff --git a/os2/os2acl.c b/os2/os2acl.c
new file mode 100644
index 0000000..7c5b1fd
--- /dev/null
+++ b/os2/os2acl.c
@@ -0,0 +1,385 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* os2acl.c - access to OS/2 (LAN Server) ACLs
+ *
+ * Author: Kai Uwe Rommel <rommel@ars.de>
+ * Created: Mon Aug 08 1994
+ *
+ */
+
+/*
+ * supported 32-bit compilers:
+ * - emx+gcc
+ * - IBM C Set++ 2.1 or newer
+ * - Watcom C/C++ 10.0 or newer
+ *
+ * supported 16-bit compilers:
+ * - MS C 6.00A
+ * - Watcom C/C++ 10.0 or newer
+ *
+ * supported OS/2 LAN environments:
+ * - IBM LAN Server/Requester 3.0, 4.0 and 5.0 (Warp Server)
+ * - IBM Peer 1.0 (Warp Connect)
+ */
+
+#ifdef KUR
+ static char *rcsid =
+ "$Id: os2acl.c,v 1.3 1996/04/03 19:18:27 rommel Exp rommel $";
+ static char *rcsrev = "$Revision: 1.3 $";
+#endif
+
+/*
+ * $Log: os2acl.c,v $
+ * Revision 1.3 1996/04/03 19:18:27 rommel
+ * minor fixes
+ *
+ * Revision 1.2 1996/03/30 22:03:52 rommel
+ * avoid frequent dynamic allocation for every call
+ * streamlined code
+ *
+ * Revision 1.1 1996/03/30 09:35:00 rommel
+ * Initial revision
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <malloc.h>
+
+#define INCL_NOPM
+#define INCL_DOS
+#define INCL_DOSERRORS
+#include <os2.h>
+
+#include "os2/os2acl.h"
+
+#define UNLEN 20
+
+#if defined(__WATCOMC__) && defined(__386__) && !defined(__32BIT__)
+#define __32BIT__
+#endif
+
+#ifdef __32BIT__
+typedef ULONG U_INT;
+#ifdef __EMX__
+#define PSTR16 _far16ptr
+#define PTR16(x) _emx_32to16(x)
+#else /* other 32-bit */
+#define PSTR16 PCHAR16
+#define PTR16(x) ((PCHAR16)(x))
+#endif
+#else /* 16-bit */
+typedef USHORT U_INT;
+#define PSTR16 PSZ
+#define PTR16(x) (x)
+#endif
+
+typedef struct access_list
+{
+ char acl_ugname[UNLEN+1];
+ char acl_pad;
+ USHORT acl_access;
+}
+ACCLIST;
+
+typedef struct access_info
+{
+ PSTR16 acc_resource_name;
+ USHORT acc_attr;
+ USHORT acc_count;
+}
+ACCINFO;
+
+static ACCINFO *ai;
+static char *path, *data;
+
+#ifdef __32BIT__
+
+#ifdef __EMX__
+
+static USHORT (APIENTRY *_NetAccessGetInfo)(PSZ pszServer, PSZ pszResource,
+ USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail);
+static USHORT (APIENTRY *_NetAccessSetInfo)(PSZ pszServer, PSZ pszResource,
+ USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum);
+static USHORT (APIENTRY *_NetAccessAdd)(PSZ pszServer,
+ USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer);
+
+USHORT NetAccessGetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel,
+ PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail)
+{
+ return (USHORT)
+ (_THUNK_PROLOG (4+4+2+4+2+4);
+ _THUNK_FLAT (pszServer);
+ _THUNK_FLAT (pszResource);
+ _THUNK_SHORT (sLevel);
+ _THUNK_FLAT (pbBuffer);
+ _THUNK_SHORT (cbBuffer);
+ _THUNK_FLAT (pcbTotalAvail);
+ _THUNK_CALLI (_emx_32to16(_NetAccessGetInfo)));
+}
+
+USHORT NetAccessSetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel,
+ PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum)
+{
+ return (USHORT)
+ (_THUNK_PROLOG (4+4+2+4+2+2);
+ _THUNK_FLAT (pszServer);
+ _THUNK_FLAT (pszResource);
+ _THUNK_SHORT (sLevel);
+ _THUNK_FLAT (pbBuffer);
+ _THUNK_SHORT (cbBuffer);
+ _THUNK_SHORT (sParmNum);
+ _THUNK_CALLI (_emx_32to16(_NetAccessSetInfo)));
+}
+
+USHORT NetAccessAdd(PSZ pszServer, USHORT sLevel,
+ PVOID pbBuffer, USHORT cbBuffer)
+{
+ return (USHORT)
+ (_THUNK_PROLOG (4+2+4+2);
+ _THUNK_FLAT (pszServer);
+ _THUNK_SHORT (sLevel);
+ _THUNK_FLAT (pbBuffer);
+ _THUNK_SHORT (cbBuffer);
+ _THUNK_CALLI (_emx_32to16(_NetAccessAdd)));
+}
+
+#else /* other 32-bit */
+
+APIRET16 (* APIENTRY16 NetAccessGetInfo)(PCHAR16 pszServer, PCHAR16 pszResource,
+ USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, PVOID16 pcbTotalAvail);
+APIRET16 (* APIENTRY16 NetAccessSetInfo)(PCHAR16 pszServer, PCHAR16 pszResource,
+ USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, USHORT sParmNum);
+APIRET16 (* APIENTRY16 NetAccessAdd)(PCHAR16 pszServer,
+ USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer);
+
+#define _NetAccessGetInfo NetAccessGetInfo
+#define _NetAccessSetInfo NetAccessSetInfo
+#define _NetAccessAdd NetAccessAdd
+
+#if !defined(__IBMC__) || !defined(__TILED__)
+#define _tmalloc malloc
+#define _tfree free
+#endif
+
+#endif
+#else /* 16-bit */
+
+USHORT (APIENTRY *NetAccessGetInfo)(PSZ pszServer, PSZ pszResource,
+ USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail);
+USHORT (APIENTRY *NetAccessSetInfo)(PSZ pszServer, PSZ pszResource,
+ USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum);
+USHORT (APIENTRY *NetAccessAdd)(PSZ pszServer,
+ USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer);
+
+#define _NetAccessGetInfo NetAccessGetInfo
+#define _NetAccessSetInfo NetAccessSetInfo
+#define _NetAccessAdd NetAccessAdd
+
+#define _tmalloc malloc
+#define _tfree free
+
+#define DosQueryProcAddr(handle, ord, name, funcptr) \
+ DosGetProcAddr(handle, name, funcptr)
+#define DosQueryCurrentDir DosQCurDir
+#define DosQueryCurrentDisk DosQCurDisk
+
+#endif
+
+
+static BOOL acl_init(void)
+{
+ static BOOL initialized, netapi_avail;
+ HMODULE netapi;
+ char buf[256];
+
+ if (initialized)
+ return netapi_avail;
+
+ initialized = TRUE;
+
+ if (DosLoadModule(buf, sizeof(buf), "NETAPI", &netapi))
+ return FALSE;
+
+ if (DosQueryProcAddr(netapi, 0, "NETACCESSGETINFO", (PFN *) &_NetAccessGetInfo) ||
+ DosQueryProcAddr(netapi, 0, "NETACCESSSETINFO", (PFN *) &_NetAccessSetInfo) ||
+ DosQueryProcAddr(netapi, 0, "NETACCESSADD", (PFN *) &_NetAccessAdd))
+ return FALSE;
+
+#if defined(__WATCOMC__) && defined(__386__)
+ NetAccessGetInfo = (PVOID) (ULONG) (PVOID16) NetAccessGetInfo;
+ NetAccessSetInfo = (PVOID) (ULONG) (PVOID16) NetAccessSetInfo;
+ NetAccessAdd = (PVOID) (ULONG) (PVOID16) NetAccessAdd;
+#endif
+
+ if ((path = _tmalloc(CCHMAXPATH)) == NULL)
+ return FALSE;
+ if ((data = _tmalloc(ACL_BUFFERSIZE)) == NULL)
+ return FALSE;
+ if ((ai = _tmalloc(sizeof(ACCINFO))) == NULL)
+ return -1;
+
+ netapi_avail = TRUE;
+
+ return netapi_avail;
+}
+
+static void acl_mkpath(char *buffer, const char *source)
+{
+ char *ptr;
+ static char cwd[CCHMAXPATH];
+ static U_INT cwdlen;
+ U_INT cdrive;
+ ULONG drivemap;
+
+ if (isalpha(source[0]) && source[1] == ':')
+ buffer[0] = 0; /* fully qualified names */
+ else
+ {
+ if (cwd[0] == 0)
+ {
+ DosQueryCurrentDisk(&cdrive, &drivemap);
+ cwd[0] = (char)(cdrive + '@');
+ cwd[1] = ':';
+ cwd[2] = '\\';
+ cwdlen = sizeof(cwd) - 3;
+ DosQueryCurrentDir(0, cwd + 3, &cwdlen);
+ cwdlen = strlen(cwd);
+ }
+
+ if (source[0] == '/' || source[0] == '\\')
+ {
+ if (source[1] == '/' || source[1] == '\\')
+ buffer[0] = 0; /* UNC names */
+ else
+ {
+ strncpy(buffer, cwd, 2);
+ buffer[2] = 0;
+ }
+ }
+ else
+ {
+ strcpy(buffer, cwd);
+ if (cwd[cwdlen - 1] != '\\' && cwd[cwdlen - 1] != '/')
+ strcat(buffer, "/");
+ }
+ }
+
+ strcat(buffer, source);
+
+ for (ptr = buffer; *ptr; ptr++)
+ if (*ptr == '/')
+ *ptr = '\\';
+
+ if (ptr[-1] == '\\')
+ ptr[-1] = 0;
+
+ strupr(buffer);
+}
+
+static int acl_bin2text(char *data, char *text)
+{
+ ACCINFO *ai;
+ ACCLIST *al;
+ U_INT cnt, offs;
+
+ ai = (ACCINFO *) data;
+ al = (ACCLIST *) (data + sizeof(ACCINFO));
+
+ offs = sprintf(text, "ACL1:%X,%d\n",
+ ai -> acc_attr, ai -> acc_count);
+
+ for (cnt = 0; cnt < ai -> acc_count; cnt++)
+ offs += sprintf(text + offs, "%s,%X\n",
+ al[cnt].acl_ugname, al[cnt].acl_access);
+
+ return strlen(text);
+}
+
+int acl_get(char *server, const char *resource, char *buffer)
+{
+ USHORT datalen;
+ PSZ srv = NULL;
+ int rc;
+
+ if (!acl_init())
+ return -1;
+
+ if (server)
+ srv = server;
+
+ acl_mkpath(path, resource);
+ datalen = 0;
+
+ rc = NetAccessGetInfo(srv, path, 1, data, ACL_BUFFERSIZE, &datalen);
+
+ if (rc == 0)
+ acl_bin2text(data, buffer);
+
+ return rc;
+}
+
+static int acl_text2bin(char *data, char *text, char *path)
+{
+ ACCINFO *ai;
+ ACCLIST *al;
+ char *ptr, *ptr2;
+ U_INT cnt;
+
+ ai = (ACCINFO *) data;
+ ai -> acc_resource_name = PTR16(path);
+
+ if (sscanf(text, "ACL1:%hX,%hd",
+ &ai -> acc_attr, &ai -> acc_count) != 2)
+ return ERROR_INVALID_PARAMETER;
+
+ al = (ACCLIST *) (data + sizeof(ACCINFO));
+ ptr = strchr(text, '\n') + 1;
+
+ for (cnt = 0; cnt < ai -> acc_count; cnt++)
+ {
+ ptr2 = strchr(ptr, ',');
+ strncpy(al[cnt].acl_ugname, ptr, ptr2 - ptr);
+ al[cnt].acl_ugname[ptr2 - ptr] = 0;
+ sscanf(ptr2 + 1, "%hx", &al[cnt].acl_access);
+ ptr = strchr(ptr, '\n') + 1;
+ }
+
+ return sizeof(ACCINFO) + ai -> acc_count * sizeof(ACCLIST);
+}
+
+int acl_set(char *server, const char *resource, char *buffer)
+{
+ USHORT datalen;
+ PSZ srv = NULL;
+
+ if (!acl_init())
+ return -1;
+
+ if (server)
+ srv = server;
+
+ acl_mkpath(path, resource);
+
+ ai -> acc_resource_name = PTR16(path);
+ ai -> acc_attr = 0;
+ ai -> acc_count = 0;
+
+ NetAccessAdd(srv, 1, ai, sizeof(ACCINFO));
+ /* Ignore any errors, most probably because ACL already exists. */
+ /* In any such case, try updating the existing ACL. */
+
+ datalen = acl_text2bin(data, buffer, path);
+
+ return NetAccessSetInfo(srv, path, 1, data, datalen, 0);
+}
+
+/* end of os2acl.c */
diff --git a/os2/os2acl.h b/os2/os2acl.h
new file mode 100644
index 0000000..dd34b2d
--- /dev/null
+++ b/os2/os2acl.h
@@ -0,0 +1,34 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, all these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* os2acl.h
+ *
+ * Author: Kai Uwe Rommel <rommel@ars.de>
+ * Created: Fri Mar 29 1996
+ */
+
+/* $Id: os2acl.h,v 1.1 1996/03/30 09:35:00 rommel Exp rommel $ */
+
+/*
+ * $Log: os2acl.h,v $
+ * Revision 1.1 1996/03/30 09:35:00 rommel
+ * Initial revision
+ *
+ */
+
+#ifndef _OS2ACL_H
+#define _OS2ACL_H
+
+#define ACL_BUFFERSIZE 4096
+
+int acl_get(char *server, const char *resource, char *buffer);
+int acl_set(char *server, const char *resource, char *buffer);
+
+#endif /* _OS2ACL_H */
+
+/* end of os2acl.h */
diff --git a/os2/os2zip.c b/os2/os2zip.c
new file mode 100644
index 0000000..83bc3bc
--- /dev/null
+++ b/os2/os2zip.c
@@ -0,0 +1,1213 @@
+/*
+ * @(#)dir.c 1.4 87/11/06 Public Domain.
+ *
+ * A public domain implementation of BSD directory routines for
+ * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
+ * August 1987
+ *
+ * Ported to OS/2 by Kai Uwe Rommel
+ * Addition of other OS/2 file system specific code
+ * Placed into the public domain
+ */
+
+/* does also contain EA access code for use in ZIP */
+
+
+#ifdef OS2
+
+
+#if defined(__EMX__) && !defined(__32BIT__)
+# define __32BIT__
+#endif
+
+#include "zip.h"
+
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#ifndef __BORLANDC__
+#include <malloc.h>
+#endif
+
+#define INCL_NOPM
+#define INCL_DOSNLS
+#define INCL_DOSERRORS
+#include <os2.h>
+
+#include "os2zip.h"
+#include "os2acl.h"
+
+
+#ifndef max
+#define max(a, b) ((a) < (b) ? (b) : (a))
+#endif
+
+
+#ifdef __32BIT__
+#define DosFindFirst(p1, p2, p3, p4, p5, p6) \
+ DosFindFirst(p1, p2, p3, p4, p5, p6, 1)
+#else
+#define DosQueryCurrentDisk DosQCurDisk
+#define DosQueryFSAttach(p1, p2, p3, p4, p5) \
+ DosQFSAttach(p1, p2, p3, p4, p5, 0)
+#define DosQueryFSInfo(d, l, b, s) \
+ DosQFSInfo(d, l, b, s)
+#define DosQueryPathInfo(p1, p2, p3, p4) \
+ DosQPathInfo(p1, p2, p3, p4, 0)
+#define DosSetPathInfo(p1, p2, p3, p4, p5) \
+ DosSetPathInfo(p1, p2, p3, p4, p5, 0)
+#define DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7) \
+ DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7, 0)
+#define DosFindFirst(p1, p2, p3, p4, p5, p6) \
+ DosFindFirst(p1, p2, p3, p4, p5, p6, 0)
+#define DosMapCase DosCaseMap
+#endif
+
+
+#ifndef UTIL
+
+extern int noisy;
+
+#ifndef S_IFMT
+#define S_IFMT 0xF000
+#endif
+
+static int attributes = _A_DIR | _A_HIDDEN | _A_SYSTEM;
+
+static char *getdirent(char *);
+static void free_dircontents(struct _dircontents *);
+
+#ifdef __32BIT__
+static HDIR hdir;
+static ULONG count;
+static FILEFINDBUF3 find;
+#else
+static HDIR hdir;
+static USHORT count;
+static FILEFINDBUF find;
+#endif
+
+DIR *opendir(const char *name)
+{
+ struct stat statb;
+ DIR *dirp;
+ char c;
+ char *s;
+ struct _dircontents *dp;
+ char nbuf[MAXPATHLEN + 1];
+ int len;
+
+ attributes = hidden_files ? (_A_DIR | _A_HIDDEN | _A_SYSTEM) : _A_DIR;
+
+ strcpy(nbuf, name);
+ if ((len = strlen(nbuf)) == 0)
+ return NULL;
+
+ if (((c = nbuf[len - 1]) == '\\' || c == '/') && (len > 1))
+ {
+ nbuf[len - 1] = 0;
+ --len;
+
+ if (nbuf[len - 1] == ':')
+ {
+ strcpy(nbuf+len, "\\.");
+ len += 2;
+ }
+ }
+ else
+ if (nbuf[len - 1] == ':')
+ {
+ strcpy(nbuf+len, ".");
+ ++len;
+ }
+
+#ifndef __BORLANDC__
+ /* when will we ever see a Borland compiler that can properly stat !!! */
+ if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
+ return NULL;
+#endif
+
+ if ((dirp = malloc(sizeof(DIR))) == NULL)
+ return NULL;
+
+ if (nbuf[len - 1] == '.' && (len == 1 || nbuf[len - 2] != '.'))
+ strcpy(nbuf+len-1, "*.*");
+ else
+ if (((c = nbuf[len - 1]) == '\\' || c == '/') && (len == 1))
+ strcpy(nbuf+len, "*");
+ else
+ strcpy(nbuf+len, "\\*");
+
+ /* len is no longer correct (but no longer needed) */
+
+ dirp -> dd_loc = 0;
+ dirp -> dd_contents = dirp -> dd_cp = NULL;
+
+ if ((s = getdirent(nbuf)) == NULL)
+ return dirp;
+
+ do
+ {
+ if (((dp = malloc(sizeof(struct _dircontents))) == NULL) ||
+ ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL) )
+ {
+ if (dp)
+ free(dp);
+ free_dircontents(dirp -> dd_contents);
+
+ return NULL;
+ }
+
+ if (dirp -> dd_contents)
+ {
+ dirp -> dd_cp -> _d_next = dp;
+ dirp -> dd_cp = dirp -> dd_cp -> _d_next;
+ }
+ else
+ dirp -> dd_contents = dirp -> dd_cp = dp;
+
+ strcpy(dp -> _d_entry, s);
+ dp -> _d_next = NULL;
+
+ dp -> _d_size = find.cbFile;
+ dp -> _d_mode = find.attrFile;
+ dp -> _d_time = *(unsigned *) &(find.ftimeLastWrite);
+ dp -> _d_date = *(unsigned *) &(find.fdateLastWrite);
+ }
+ while ((s = getdirent(NULL)) != NULL);
+
+ dirp -> dd_cp = dirp -> dd_contents;
+
+ return dirp;
+}
+
+void closedir(DIR * dirp)
+{
+ free_dircontents(dirp -> dd_contents);
+ free(dirp);
+}
+
+struct dirent *readdir(DIR * dirp)
+{
+ static struct dirent dp;
+
+ if (dirp -> dd_cp == NULL)
+ return NULL;
+
+ dp.d_namlen = dp.d_reclen =
+ strlen(strcpy(dp.d_name, dirp -> dd_cp -> _d_entry));
+
+ dp.d_ino = 0;
+
+ dp.d_size = dirp -> dd_cp -> _d_size;
+ dp.d_mode = dirp -> dd_cp -> _d_mode;
+ dp.d_time = dirp -> dd_cp -> _d_time;
+ dp.d_date = dirp -> dd_cp -> _d_date;
+
+ dirp -> dd_cp = dirp -> dd_cp -> _d_next;
+ dirp -> dd_loc++;
+
+ return &dp;
+}
+
+void seekdir(DIR * dirp, long off)
+{
+ long i = off;
+ struct _dircontents *dp;
+
+ if (off >= 0)
+ {
+ for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next);
+
+ dirp -> dd_loc = off - (i + 1);
+ dirp -> dd_cp = dp;
+ }
+}
+
+long telldir(DIR * dirp)
+{
+ return dirp -> dd_loc;
+}
+
+static void free_dircontents(struct _dircontents * dp)
+{
+ struct _dircontents *odp;
+
+ while (dp)
+ {
+ if (dp -> _d_entry)
+ free(dp -> _d_entry);
+
+ dp = (odp = dp) -> _d_next;
+ free(odp);
+ }
+}
+
+static char *getdirent(char *dir)
+{
+ int done;
+ static int lower;
+
+ if (dir != NULL)
+ { /* get first entry */
+ hdir = HDIR_SYSTEM;
+ count = 1;
+ done = DosFindFirst(dir, &hdir, attributes, &find, sizeof(find), &count);
+ lower = IsFileSystemFAT(dir);
+ }
+ else /* get next entry */
+ done = DosFindNext(hdir, &find, sizeof(find), &count);
+
+ if (done == 0)
+ {
+ if (lower)
+ StringLower(find.achName);
+ return find.achName;
+ }
+ else
+ {
+ DosFindClose(hdir);
+ return NULL;
+ }
+}
+
+/* FAT / HPFS detection */
+
+int IsFileSystemFAT(char *dir)
+{
+ static USHORT nLastDrive = -1, nResult;
+ ULONG lMap;
+ BYTE bData[64];
+ char bName[3];
+#ifdef __32BIT__
+ ULONG nDrive, cbData;
+ PFSQBUFFER2 pData = (PFSQBUFFER2) bData;
+#else
+ USHORT nDrive, cbData;
+ PFSQBUFFER pData = (PFSQBUFFER) bData;
+#endif
+
+ /* We separate FAT and HPFS+other file systems here.
+ at the moment I consider other systems to be similar to HPFS,
+ i.e. support long file names and being case sensitive */
+
+ if (isalpha(dir[0]) && (dir[1] == ':'))
+ nDrive = to_up(dir[0]) - '@';
+ else
+ DosQueryCurrentDisk(&nDrive, &lMap);
+
+ if (nDrive == nLastDrive)
+ return nResult;
+
+ bName[0] = (char) (nDrive + '@');
+ bName[1] = ':';
+ bName[2] = 0;
+
+ nLastDrive = nDrive;
+ cbData = sizeof(bData);
+
+ if (!DosQueryFSAttach(bName, 0, FSAIL_QUERYNAME, (PVOID) pData, &cbData))
+ nResult = !strcmp((char *) pData -> szFSDName + pData -> cbName, "FAT");
+ else
+ nResult = FALSE;
+
+ /* End of this ugly code */
+ return nResult;
+}
+
+/* access mode bits and time stamp */
+
+int GetFileMode(char *name)
+{
+#ifdef __32BIT__
+ FILESTATUS3 fs;
+ return DosQueryPathInfo(name, 1, &fs, sizeof(fs)) ? -1 : fs.attrFile;
+#else
+ USHORT mode;
+ return DosQFileMode(name, &mode, 0L) ? -1 : mode;
+#endif
+}
+
+ulg GetFileTime(char *name)
+{
+#ifdef __32BIT__
+ FILESTATUS3 fs;
+#else
+ FILESTATUS fs;
+#endif
+ USHORT nDate, nTime;
+ DATETIME dtCurrent;
+
+ if (strcmp(name, "-") == 0)
+ {
+ DosGetDateTime(&dtCurrent);
+ fs.fdateLastWrite.day = dtCurrent.day;
+ fs.fdateLastWrite.month = dtCurrent.month;
+ fs.fdateLastWrite.year = dtCurrent.year - 1980;
+ fs.ftimeLastWrite.hours = dtCurrent.hours;
+ fs.ftimeLastWrite.minutes = dtCurrent.minutes;
+ fs.ftimeLastWrite.twosecs = dtCurrent.seconds / 2;
+ }
+ else
+ if (DosQueryPathInfo(name, 1, (PBYTE) &fs, sizeof(fs)))
+ return -1;
+
+ nDate = * (USHORT *) &fs.fdateLastWrite;
+ nTime = * (USHORT *) &fs.ftimeLastWrite;
+
+ return ((ULONG) nDate) << 16 | nTime;
+}
+
+void SetFileTime(char *path, ulg stamp)
+{
+ FILESTATUS fs;
+ USHORT fd, ft;
+
+ if (DosQueryPathInfo(path, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)))
+ return;
+
+ fd = (USHORT) (stamp >> 16);
+ ft = (USHORT) stamp;
+ fs.fdateLastWrite = fs.fdateCreation = * (FDATE *) &fd;
+ fs.ftimeLastWrite = fs.ftimeCreation = * (FTIME *) &ft;
+
+ DosSetPathInfo(path, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0);
+}
+
+/* read volume label */
+
+char *getVolumeLabel(int drive, unsigned long *vtime, unsigned long *vmode,
+ time_t *utim)
+{
+ static FSINFO fi;
+
+ if (DosQueryFSInfo(drive ? drive - 'A' + 1 : 0,
+ FSIL_VOLSER, (PBYTE) &fi, sizeof(fi)))
+ return NULL;
+
+ time(utim);
+ *vtime = unix2dostime(utim);
+ *vmode = _A_VOLID | _A_ARCHIVE;
+
+ return (fi.vol.cch > 0) ? fi.vol.szVolLabel : NULL;
+}
+
+/* FAT / HPFS name conversion stuff */
+
+int IsFileNameValid(char *name)
+{
+ HFILE hf;
+#ifdef __32BIT__
+ ULONG uAction;
+#else
+ USHORT uAction;
+#endif
+
+ switch(DosOpen(name, &hf, &uAction, 0, 0, FILE_OPEN,
+ OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0))
+ {
+ case ERROR_INVALID_NAME:
+ case ERROR_FILENAME_EXCED_RANGE:
+ return FALSE;
+ case NO_ERROR:
+ DosClose(hf);
+ default:
+ return TRUE;
+ }
+}
+
+void ChangeNameForFAT(char *name)
+{
+ char *src, *dst, *next, *ptr, *dot, *start;
+ static char invalid[] = ":;,=+\"[]<>| \t";
+
+ if (isalpha(name[0]) && (name[1] == ':'))
+ start = name + 2;
+ else
+ start = name;
+
+ src = dst = start;
+ if ((*src == '/') || (*src == '\\'))
+ src++, dst++;
+
+ while (*src)
+ {
+ for (next = src; *next && (*next != '/') && (*next != '\\'); next++);
+
+ for (ptr = src, dot = NULL; ptr < next; ptr++)
+ if (*ptr == '.')
+ {
+ dot = ptr; /* remember last dot */
+ *ptr = '_';
+ }
+
+ if (dot == NULL)
+ for (ptr = src; ptr < next; ptr++)
+ if (*ptr == '_')
+ dot = ptr; /* remember last _ as if it were a dot */
+
+ if (dot && (dot > src) &&
+ ((next - dot <= 4) ||
+ ((next - src > 8) && (dot - src > 3))))
+ {
+ if (dot)
+ *dot = '.';
+
+ for (ptr = src; (ptr < dot) && ((ptr - src) < 8); ptr++)
+ *dst++ = *ptr;
+
+ for (ptr = dot; (ptr < next) && ((ptr - dot) < 4); ptr++)
+ *dst++ = *ptr;
+ }
+ else
+ {
+ if (dot && (next - src == 1))
+ *dot = '.'; /* special case: "." as a path component */
+
+ for (ptr = src; (ptr < next) && ((ptr - src) < 8); ptr++)
+ *dst++ = *ptr;
+ }
+
+ *dst++ = *next; /* either '/' or 0 */
+
+ if (*next)
+ {
+ src = next + 1;
+
+ if (*src == 0) /* handle trailing '/' on dirs ! */
+ *dst = 0;
+ }
+ else
+ break;
+ }
+
+ for (src = start; *src != 0; ++src)
+ if ((strchr(invalid, *src) != NULL) || (*src == ' '))
+ *src = '_';
+}
+
+/* .LONGNAME EA code */
+
+typedef struct
+{
+ ULONG cbList; /* length of value + 22 */
+#ifdef __32BIT__
+ ULONG oNext;
+#endif
+ BYTE fEA; /* 0 */
+ BYTE cbName; /* length of ".LONGNAME" = 9 */
+ USHORT cbValue; /* length of value + 4 */
+ BYTE szName[10]; /* ".LONGNAME" */
+ USHORT eaType; /* 0xFFFD for length-preceded ASCII */
+ USHORT eaSize; /* length of value */
+ BYTE szValue[CCHMAXPATH];
+}
+FEALST;
+
+typedef struct
+{
+ ULONG cbList;
+#ifdef __32BIT__
+ ULONG oNext;
+#endif
+ BYTE cbName;
+ BYTE szName[10]; /* ".LONGNAME" */
+}
+GEALST;
+
+char *GetLongNameEA(const char *name)
+{
+ EAOP eaop;
+ GEALST gealst;
+ static FEALST fealst;
+ char *ptr;
+
+ eaop.fpGEAList = (PGEALIST) &gealst;
+ eaop.fpFEAList = (PFEALIST) &fealst;
+ eaop.oError = 0;
+
+ strcpy((char *) gealst.szName, ".LONGNAME");
+ gealst.cbName = (BYTE) strlen((char *) gealst.szName);
+#ifdef __32BIT__
+ gealst.oNext = 0;
+#endif
+
+ gealst.cbList = sizeof(gealst);
+ fealst.cbList = sizeof(fealst);
+
+ if (DosQueryPathInfo(name, FIL_QUERYEASFROMLIST,
+ (PBYTE) &eaop, sizeof(eaop)))
+ return NULL;
+
+ if (fealst.cbValue > 4 && fealst.eaType == 0xFFFD)
+ {
+ fealst.szValue[fealst.eaSize] = 0;
+
+ for (ptr = fealst.szValue; *ptr; ptr++)
+ if (*ptr == '/' || *ptr == '\\')
+ *ptr = '!';
+
+ return (char *) fealst.szValue;
+ }
+
+ return NULL;
+}
+
+char *GetLongPathEA(const char *name)
+{
+ static char nbuf[CCHMAXPATH + 1];
+ char tempbuf[CCHMAXPATH + 1];
+ char *comp, *next, *ea, sep;
+ BOOL bFound = FALSE;
+
+ nbuf[0] = 0;
+ strncpy(tempbuf, name, CCHMAXPATH);
+ tempbuf[CCHMAXPATH] = '\0';
+ next = tempbuf;
+
+ while (*next)
+ {
+ comp = next;
+
+ while (*next != '\\' && *next != '/' && *next != 0)
+ next++;
+
+ sep = *next;
+ *next = 0;
+
+ ea = GetLongNameEA(tempbuf);
+ strcat(nbuf, ea ? ea : comp);
+ bFound = bFound || (ea != NULL);
+
+ if (sep)
+ {
+ strcat(nbuf, "\\");
+ *next++ = sep;
+ }
+ }
+
+ return (nbuf[0] != 0) && bFound ? nbuf : NULL;
+}
+
+/* general EA code */
+
+typedef struct
+{
+ USHORT nID;
+ USHORT nSize;
+ ULONG lSize;
+}
+EFHEADER, *PEFHEADER;
+
+#ifdef __32BIT__
+
+/* Perhaps due to bugs in the current OS/2 2.0 kernel, the success or
+ failure of the DosEnumAttribute() and DosQueryPathInfo() system calls
+ depends on the area where the return buffers are allocated. This
+ differs for the various compilers, for some alloca() works, for some
+ malloc() works, for some, both work. We'll have to live with that. */
+
+/* The use of malloc() is not very convenient, because it requires
+ backtracking (i.e. free()) at error returns. We do that for system
+ calls that may fail, but not for malloc() calls, because they are VERY
+ unlikely to fail. If ever, we just leave some memory allocated
+ over the usually short lifetime of a zip process ... */
+
+#ifdef __GNUC__
+#define alloc(x) alloca(x)
+#define unalloc(x)
+#else
+#define alloc(x) malloc(x)
+#define unalloc(x) free(x)
+#endif
+
+void GetEAs(char *path, char **bufptr, size_t *size,
+ char **cbufptr, size_t *csize)
+{
+ FILESTATUS4 fs;
+ PDENA2 pDENA, pFound;
+ EAOP2 eaop;
+ PGEA2 pGEA;
+ PGEA2LIST pGEAlist;
+ PFEA2LIST pFEAlist;
+ PEFHEADER pEAblock;
+ ULONG ulAttributes, ulMemoryBlock;
+ ULONG nLength;
+ ULONG nBlock;
+ char szName[CCHMAXPATH];
+
+ *size = *csize = 0;
+
+ strcpy(szName, path);
+ nLength = strlen(szName);
+ if (szName[nLength - 1] == '/')
+ szName[nLength - 1] = 0;
+
+ if (DosQueryPathInfo(szName, FIL_QUERYEASIZE, (PBYTE) &fs, sizeof(fs)))
+ return;
+ nBlock = max(fs.cbList, 65535);
+ if ((pDENA = alloc((size_t) nBlock)) == NULL)
+ return;
+
+ ulAttributes = -1;
+
+ if (DosEnumAttribute(ENUMEA_REFTYPE_PATH, szName, 1, pDENA, nBlock,
+ &ulAttributes, ENUMEA_LEVEL_NO_VALUE)
+ || ulAttributes == 0
+ || (pGEAlist = alloc((size_t) nBlock)) == NULL)
+ {
+ unalloc(pDENA);
+ return;
+ }
+
+ pGEA = pGEAlist -> list;
+ memset(pGEAlist, 0, nBlock);
+ pFound = pDENA;
+
+ while (ulAttributes--)
+ {
+ if (!(strcmp(pFound -> szName, ".LONGNAME") == 0 && use_longname_ea))
+ {
+ pGEA -> cbName = pFound -> cbName;
+ strcpy(pGEA -> szName, pFound -> szName);
+
+ nLength = sizeof(GEA2) + strlen(pGEA -> szName);
+ nLength = ((nLength - 1) / sizeof(ULONG) + 1) * sizeof(ULONG);
+
+ pGEA -> oNextEntryOffset = ulAttributes ? nLength : 0;
+ pGEA = (PGEA2) ((PCH) pGEA + nLength);
+ }
+
+ pFound = (PDENA2) ((PCH) pFound + pFound -> oNextEntryOffset);
+ }
+
+ if (pGEA == pGEAlist -> list) /* no attributes to save */
+ {
+ unalloc(pDENA);
+ unalloc(pGEAlist);
+ return;
+ }
+
+ pGEAlist -> cbList = (PCH) pGEA - (PCH) pGEAlist;
+
+ pFEAlist = (PVOID) pDENA; /* reuse buffer */
+ pFEAlist -> cbList = nBlock;
+
+ eaop.fpGEA2List = pGEAlist;
+ eaop.fpFEA2List = pFEAlist;
+ eaop.oError = 0;
+
+ if (DosQueryPathInfo(szName, FIL_QUERYEASFROMLIST,
+ (PBYTE) &eaop, sizeof(eaop)))
+ {
+ unalloc(pDENA);
+ unalloc(pGEAlist);
+ return;
+ }
+
+ /* The maximum compressed size is (in case of STORE type) the
+ uncompressed size plus the size of the compression type field
+ plus the size of the CRC field + 2*5 deflate overhead bytes
+ for uncompressable data.
+ (5 bytes per 32Kb block, max compressed size = 2 blocks) */
+
+ ulAttributes = pFEAlist -> cbList;
+ ulMemoryBlock = ulAttributes +
+ sizeof(USHORT) + sizeof(ULONG) + EB_DEFLAT_EXTRA;
+ pEAblock = (PEFHEADER) malloc(sizeof(EFHEADER) + ulMemoryBlock);
+
+ if (pEAblock == NULL)
+ {
+ unalloc(pDENA);
+ unalloc(pGEAlist);
+ return;
+ }
+
+ *bufptr = (char *) pEAblock;
+ *size = sizeof(EFHEADER);
+
+ pEAblock -> nID = EF_OS2EA;
+ pEAblock -> nSize = sizeof(pEAblock -> lSize);
+ pEAblock -> lSize = ulAttributes; /* uncompressed size */
+
+ nLength = memcompress((char *) (pEAblock + 1), ulMemoryBlock,
+ (char *) pFEAlist, ulAttributes);
+ *size += nLength;
+ pEAblock -> nSize += nLength;
+
+ if ((pEAblock = (PEFHEADER) malloc(sizeof(EFHEADER))) == NULL)
+ {
+ unalloc(pDENA);
+ unalloc(pGEAlist);
+ return;
+ }
+
+ *cbufptr = (char *) pEAblock;
+ *csize = sizeof(EFHEADER);
+
+ pEAblock -> nID = EF_OS2EA;
+ pEAblock -> nSize = sizeof(pEAblock -> lSize);
+ pEAblock -> lSize = ulAttributes;
+
+ if (noisy)
+ printf(" (%ld bytes EA's)", ulAttributes);
+
+ unalloc(pDENA);
+ unalloc(pGEAlist);
+}
+
+#else /* !__32BIT__ */
+
+typedef struct
+{
+ ULONG oNextEntryOffset;
+ BYTE fEA;
+ BYTE cbName;
+ USHORT cbValue;
+ CHAR szName[1];
+}
+FEA2, *PFEA2;
+
+typedef struct
+{
+ ULONG cbList;
+ FEA2 list[1];
+}
+FEA2LIST, *PFEA2LIST;
+
+void GetEAs(char *path, char **bufptr, size_t *size,
+ char **cbufptr, size_t *csize)
+{
+ FILESTATUS2 fs;
+ PDENA1 pDENA, pFound;
+ EAOP eaop;
+ PGEALIST pGEAlist;
+ PGEA pGEA;
+ PFEALIST pFEAlist;
+ PFEA pFEA;
+ PFEA2LIST pFEA2list;
+ PFEA2 pFEA2;
+ EFHEADER *pEAblock;
+ ULONG ulAttributes;
+ USHORT nLength, nMaxSize;
+ char szName[CCHMAXPATH];
+
+ *size = *csize = 0;
+
+ strcpy(szName, path);
+ nLength = strlen(szName);
+ if (szName[nLength - 1] == '/')
+ szName[nLength - 1] = 0;
+
+ if (DosQueryPathInfo(szName, FIL_QUERYEASIZE, (PBYTE) &fs, sizeof(fs))
+ || fs.cbList <= 2 * sizeof(ULONG))
+ return;
+
+ ulAttributes = -1;
+ nMaxSize = (USHORT) min(fs.cbList * 2, 65520L);
+
+ if ((pDENA = malloc((size_t) nMaxSize)) == NULL)
+ return;
+
+ if (DosEnumAttribute(ENUMEA_REFTYPE_PATH, szName, 1, pDENA, fs.cbList,
+ &ulAttributes, ENUMEA_LEVEL_NO_VALUE)
+ || ulAttributes == 0
+ || (pGEAlist = malloc(nMaxSize)) == NULL)
+ {
+ free(pDENA);
+ return;
+ }
+
+ pGEA = pGEAlist -> list;
+ pFound = pDENA;
+
+ while (ulAttributes--)
+ {
+ nLength = strlen(pFound -> szName);
+
+ if (!(strcmp(pFound -> szName, ".LONGNAME") == 0 && use_longname_ea))
+ {
+ pGEA -> cbName = pFound -> cbName;
+ strcpy(pGEA -> szName, pFound -> szName);
+
+ pGEA++;
+ pGEA = (PGEA) (((PCH) pGEA) + nLength);
+ }
+
+ pFound++;
+ pFound = (PDENA1) (((PCH) pFound) + nLength);
+ }
+
+ if (pGEA == pGEAlist -> list)
+ {
+ free(pDENA);
+ free(pGEAlist);
+ return;
+ }
+
+ pGEAlist -> cbList = (PCH) pGEA - (PCH) pGEAlist;
+
+ pFEAlist = (PFEALIST) pDENA; /* reuse buffer */
+ pFEAlist -> cbList = fs.cbList;
+ pFEA = pFEAlist -> list;
+
+ eaop.fpGEAList = pGEAlist;
+ eaop.fpFEAList = pFEAlist;
+ eaop.oError = 0;
+
+ if (DosQueryPathInfo(szName, FIL_QUERYEASFROMLIST,
+ (PBYTE) &eaop, sizeof(eaop)))
+ {
+ free(pDENA);
+ free(pGEAlist);
+ return;
+ }
+
+ /* now convert into new OS/2 2.0 32-bit format */
+
+ pFEA2list = (PFEA2LIST) pGEAlist; /* reuse buffer */
+ pFEA2 = pFEA2list -> list;
+
+ while ((PCH) pFEA - (PCH) pFEAlist < pFEAlist -> cbList)
+ {
+ nLength = sizeof(FEA) + pFEA -> cbName + 1 + pFEA -> cbValue;
+ memcpy((PCH) pFEA2 + sizeof(pFEA2 -> oNextEntryOffset), pFEA, nLength);
+ memset((PCH) pFEA2 + sizeof(pFEA2 -> oNextEntryOffset) + nLength, 0, 3);
+ pFEA = (PFEA) ((PCH) pFEA + nLength);
+
+ nLength = sizeof(FEA2) + pFEA2 -> cbName + 1 + pFEA2 -> cbValue;
+ nLength = ((nLength - 1) / sizeof(ULONG) + 1) * sizeof(ULONG);
+ /* rounded up to 4-byte boundary */
+ pFEA2 -> oNextEntryOffset =
+ ((PCH) pFEA - (PCH) pFEAlist < pFEAlist -> cbList) ? nLength : 0;
+ pFEA2 = (PFEA2) ((PCH) pFEA2 + nLength);
+ }
+
+ pFEA2list -> cbList = (PCH) pFEA2 - (PCH) pFEA2list;
+ ulAttributes = pFEA2list -> cbList;
+
+ pEAblock = (PEFHEADER) pDENA; /* reuse buffer */
+
+ *bufptr = (char *) pEAblock;
+ *size = sizeof(EFHEADER);
+
+ pEAblock -> nID = EF_OS2EA;
+ pEAblock -> nSize = sizeof(pEAblock -> lSize);
+ pEAblock -> lSize = ulAttributes; /* uncompressed size */
+
+ nLength = (USHORT) memcompress((char *) (pEAblock + 1),
+ nMaxSize - sizeof(EFHEADER), (char *) pFEA2list, ulAttributes);
+
+ *size += nLength;
+ pEAblock -> nSize += nLength;
+
+ pEAblock = (PEFHEADER) pGEAlist;
+
+ *cbufptr = (char *) pEAblock;
+ *csize = sizeof(EFHEADER);
+
+ pEAblock -> nID = EF_OS2EA;
+ pEAblock -> nSize = sizeof(pEAblock -> lSize);
+ pEAblock -> lSize = ulAttributes;
+
+ if (noisy)
+ printf(" (%ld bytes EA's)", ulAttributes);
+}
+
+#endif /* __32BIT__ */
+
+void GetACL(char *path, char **bufptr, size_t *size,
+ char **cbufptr, size_t *csize)
+{
+ static char *buffer;
+ char *cbuffer;
+ long bytes, cbytes;
+ PEFHEADER pACLblock;
+
+ if (buffer == NULL) /* avoid frequent allocation (for every file) */
+ if ((buffer = malloc(ACL_BUFFERSIZE)) == NULL)
+ return;
+
+ if (acl_get(NULL, path, buffer))
+ return; /* this will be the most likely case */
+
+ bytes = strlen(buffer);
+
+ /* The maximum compressed size is (in case of STORE type) the
+ uncompressed size plus the size of the compression type field
+ plus the size of the CRC field + 2*5 deflate overhead bytes
+ for uncompressable data.
+ (5 bytes per 32Kb block, max compressed size = 2 blocks) */
+
+ cbytes = bytes + sizeof(USHORT) + sizeof(ULONG) + EB_DEFLAT_EXTRA;
+ if ((*bufptr = realloc(*bufptr, *size + sizeof(EFHEADER) + cbytes)) == NULL)
+ return;
+
+ pACLblock = (PEFHEADER) (*bufptr + *size);
+
+ cbuffer = (char *) (pACLblock + 1);
+ cbytes = memcompress(cbuffer, cbytes, buffer, bytes);
+
+ *size += sizeof(EFHEADER) + cbytes;
+
+ pACLblock -> nID = EF_ACL;
+ pACLblock -> nSize = sizeof(pACLblock -> lSize) + cbytes;
+ pACLblock -> lSize = bytes; /* uncompressed size */
+
+ if ((*cbufptr = realloc(*cbufptr, *csize + sizeof(EFHEADER))) == NULL)
+ return;
+
+ pACLblock = (PEFHEADER) (*cbufptr + *csize);
+ *csize += sizeof(EFHEADER);
+
+ pACLblock -> nID = EF_ACL;
+ pACLblock -> nSize = sizeof(pACLblock -> lSize);
+ pACLblock -> lSize = bytes;
+
+ if (noisy)
+ printf(" (%ld bytes ACL)", bytes);
+}
+
+#ifdef USE_EF_UT_TIME
+
+int GetExtraTime(struct zlist far *z, iztimes *z_utim)
+{
+ int eb_c_size = EB_HEADSIZE + EB_UT_LEN(1);
+ int eb_l_size = eb_c_size;
+ char *eb_c_ptr;
+ char *eb_l_ptr;
+ unsigned long ultime;
+
+#ifdef IZ_CHECK_TZ
+ if (!zp_tz_is_valid) return ZE_OK; /* skip silently no correct tz info */
+#endif
+
+ eb_c_ptr = realloc(z->cextra, (z->cext + eb_c_size));
+ if (eb_c_ptr == NULL)
+ return ZE_MEM;
+ z->cextra = eb_c_ptr;
+ eb_c_ptr += z->cext;
+ z->cext += eb_c_size;
+
+ eb_c_ptr[0] = 'U';
+ eb_c_ptr[1] = 'T';
+ eb_c_ptr[2] = EB_UT_LEN(1); /* length of data part of e.f. */
+ eb_c_ptr[3] = 0;
+ eb_c_ptr[4] = EB_UT_FL_MTIME;
+ ultime = (unsigned long) z_utim->mtime;
+ eb_c_ptr[5] = (char)(ultime);
+ eb_c_ptr[6] = (char)(ultime >> 8);
+ eb_c_ptr[7] = (char)(ultime >> 16);
+ eb_c_ptr[8] = (char)(ultime >> 24);
+
+ if (z_utim->mtime != z_utim->atime || z_utim->mtime != z_utim->ctime)
+ {
+ eb_c_ptr[4] = EB_UT_FL_MTIME | EB_UT_FL_ATIME | EB_UT_FL_CTIME;
+ eb_l_size = EB_HEADSIZE + EB_UT_LEN(3); /* only on HPFS they can differ */
+ /* so only then it makes sense to store all three time stamps */
+ }
+
+ eb_l_ptr = realloc(z->extra, (z->ext + eb_l_size));
+ if (eb_l_ptr == NULL)
+ return ZE_MEM;
+ z->extra = eb_l_ptr;
+ eb_l_ptr += z->ext;
+ z->ext += eb_l_size;
+
+ memcpy(eb_l_ptr, eb_c_ptr, eb_c_size);
+
+ if (eb_l_size > eb_c_size)
+ {
+ eb_l_ptr[2] = EB_UT_LEN(3);
+ ultime = (unsigned long) z_utim->atime;
+ eb_l_ptr[9] = (char)(ultime);
+ eb_l_ptr[10] = (char)(ultime >> 8);
+ eb_l_ptr[11] = (char)(ultime >> 16);
+ eb_l_ptr[12] = (char)(ultime >> 24);
+ ultime = (unsigned long) z_utim->ctime;
+ eb_l_ptr[13] = (char)(ultime);
+ eb_l_ptr[14] = (char)(ultime >> 8);
+ eb_l_ptr[15] = (char)(ultime >> 16);
+ eb_l_ptr[16] = (char)(ultime >> 24);
+ }
+
+ return ZE_OK;
+}
+
+#endif /* USE_EF_UT_TIME */
+
+int set_extra_field(struct zlist far *z, iztimes *z_utim)
+{
+ /* store EA data in local header, and size only in central headers */
+ GetEAs(z->name, &z->extra, &z->ext, &z->cextra, &z->cext);
+
+ /* store ACL data in local header, and size only in central headers */
+ GetACL(z->name, &z->extra, &z->ext, &z->cextra, &z->cext);
+
+#ifdef USE_EF_UT_TIME
+ /* store extended time stamps in both headers */
+ return GetExtraTime(z, z_utim);
+#else /* !USE_EF_UT_TIME */
+ return ZE_OK;
+#endif /* ?USE_EF_UT_TIME */
+}
+
+#endif /* !UTIL */
+
+/* Initialize the table of uppercase characters including handling of
+ country dependent characters. */
+
+void init_upper()
+{
+ COUNTRYCODE cc;
+ unsigned nCnt, nU;
+
+ for (nCnt = 0; nCnt < sizeof(upper); nCnt++)
+ upper[nCnt] = lower[nCnt] = (unsigned char) nCnt;
+
+ cc.country = cc.codepage = 0;
+ DosMapCase(sizeof(upper), &cc, (PCHAR) upper);
+
+ for (nCnt = 0; nCnt < 256; nCnt++)
+ {
+ nU = upper[nCnt];
+ if (nU != nCnt && lower[nU] == (unsigned char) nU)
+ lower[nU] = (unsigned char) nCnt;
+ }
+
+ for (nCnt = 'A'; nCnt <= 'Z'; nCnt++)
+ lower[nCnt] = (unsigned char) (nCnt - 'A' + 'a');
+}
+
+char *StringLower(char *szArg)
+{
+ unsigned char *szPtr;
+ for (szPtr = (unsigned char *) szArg; *szPtr; szPtr++)
+ *szPtr = lower[*szPtr];
+ return szArg;
+}
+
+#if defined(__IBMC__) && defined(__DEBUG_ALLOC__)
+void DebugMalloc(void)
+{
+ _dump_allocated(0); /* print out debug malloc memory statistics */
+}
+#endif
+
+
+/******************************/
+/* Function version_local() */
+/******************************/
+
+void version_local()
+{
+ static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
+#if defined(__IBMC__) || defined(__WATCOMC__) || defined(_MSC_VER)
+ char buf[80];
+#endif
+
+ printf(CompiledWith,
+
+#ifdef __GNUC__
+# ifdef __EMX__ /* __EMX__ is defined as "1" only (sigh) */
+ "emx+gcc ", __VERSION__,
+# else
+ "gcc/2 ", __VERSION__,
+# endif
+#elif defined(__IBMC__)
+ "IBM ",
+# if (__IBMC__ < 200)
+ (sprintf(buf, "C Set/2 %d.%02d", __IBMC__/100,__IBMC__%100), buf),
+# elif (__IBMC__ < 300)
+ (sprintf(buf, "C Set++ %d.%02d", __IBMC__/100,__IBMC__%100), buf),
+# else
+ (sprintf(buf, "Visual Age C++ %d.%02d", __IBMC__/100,__IBMC__%100), buf),
+# endif
+#elif defined(__WATCOMC__)
+ "Watcom C", (sprintf(buf, " (__WATCOMC__ = %d)", __WATCOMC__), buf),
+#elif defined(__TURBOC__)
+# ifdef __BORLANDC__
+ "Borland C++",
+# if (__BORLANDC__ < 0x0460)
+ " 1.0",
+# elif (__BORLANDC__ == 0x0460)
+ " 1.5",
+# else
+ " 2.0",
+# endif
+# else
+ "Turbo C",
+# if (__TURBOC__ >= 661)
+ "++ 1.0 or later",
+# elif (__TURBOC__ == 661)
+ " 3.0?",
+# elif (__TURBOC__ == 397)
+ " 2.0",
+# else
+ " 1.0 or 1.5?",
+# endif
+# endif
+#elif defined(MSC)
+ "Microsoft C ",
+# ifdef _MSC_VER
+ (sprintf(buf, "%d.%02d", _MSC_VER/100, _MSC_VER%100), buf),
+# else
+ "5.1 or earlier",
+# endif
+#else
+ "unknown compiler", "",
+#endif /* __GNUC__ */
+
+ "OS/2",
+
+/* GRR: does IBM C/2 identify itself as IBM rather than Microsoft? */
+#if (defined(MSC) || (defined(__WATCOMC__) && !defined(__386__)))
+# if defined(M_I86HM) || defined(__HUGE__)
+ " (16-bit, huge)",
+# elif defined(M_I86LM) || defined(__LARGE__)
+ " (16-bit, large)",
+# elif defined(M_I86MM) || defined(__MEDIUM__)
+ " (16-bit, medium)",
+# elif defined(M_I86CM) || defined(__COMPACT__)
+ " (16-bit, compact)",
+# elif defined(M_I86SM) || defined(__SMALL__)
+ " (16-bit, small)",
+# elif defined(M_I86TM) || defined(__TINY__)
+ " (16-bit, tiny)",
+# else
+ " (16-bit)",
+# endif
+#else
+ " 2.x/3.x (32-bit)",
+#endif
+
+#ifdef __DATE__
+ " on ", __DATE__
+#else
+ "", ""
+#endif
+ );
+
+ /* temporary debugging code for Borland compilers only */
+#ifdef __TURBOC__
+ printf("\t(__TURBOC__ = 0x%04x = %d)\n", __TURBOC__, __TURBOC__);
+#ifdef __BORLANDC__
+ printf("\t(__BORLANDC__ = 0x%04x)\n",__BORLANDC__);
+#else
+ printf("\tdebug(__BORLANDC__ not defined)\n");
+#endif
+#ifdef __TCPLUSPLUS__
+ printf("\t(__TCPLUSPLUS__ = 0x%04x)\n", __TCPLUSPLUS__);
+#else
+ printf("\tdebug(__TCPLUSPLUS__ not defined)\n");
+#endif
+#ifdef __BCPLUSPLUS__
+ printf("\t(__BCPLUSPLUS__ = 0x%04x)\n\n", __BCPLUSPLUS__);
+#else
+ printf("\tdebug(__BCPLUSPLUS__ not defined)\n\n");
+#endif
+#endif /* __TURBOC__ */
+
+} /* end function version_local() */
+
+#endif /* OS2 */
diff --git a/os2/os2zip.h b/os2/os2zip.h
new file mode 100644
index 0000000..06d0a02
--- /dev/null
+++ b/os2/os2zip.h
@@ -0,0 +1,84 @@
+/*
+ * @(#) dir.h 1.4 87/11/06 Public Domain.
+ *
+ * A public domain implementation of BSD directory routines for
+ * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
+ * August 1987
+ *
+ * Ported to OS/2 by Kai Uwe Rommel
+ * Addition of other OS/2 file system specific code
+ * Placed into the public domain
+ */
+
+
+#define MAXNAMLEN 256
+#define MAXPATHLEN 256
+
+#define _A_RONLY 0x01
+#define _A_HIDDEN 0x02
+#define _A_SYSTEM 0x04
+#define _A_VOLID 0x08
+#define _A_DIR 0x10
+#define _A_ARCHIVE 0x20
+
+
+struct dirent
+{
+ ino_t d_ino; /* a bit of a farce */
+ int d_reclen; /* more farce */
+ int d_namlen; /* length of d_name */
+ char d_name[MAXNAMLEN + 1]; /* null terminated */
+ /* nonstandard fields */
+ long d_size; /* size in bytes */
+ unsigned d_mode; /* DOS or OS/2 file attributes */
+ unsigned d_time;
+ unsigned d_date;
+};
+
+/* The fields d_size and d_mode are extensions by me (Kai Uwe Rommel).
+ * The find_first and find_next calls deliver this data without any extra cost.
+ * If this data is needed, these fields save a lot of extra calls to stat()
+ * (each stat() again performs a find_first call !).
+ */
+
+struct _dircontents
+{
+ char *_d_entry;
+ long _d_size;
+ unsigned _d_mode, _d_time, _d_date;
+ struct _dircontents *_d_next;
+};
+
+typedef struct _dirdesc
+{
+ int dd_id; /* uniquely identify each open directory */
+ long dd_loc; /* where we are in directory entry is this */
+ struct _dircontents *dd_contents; /* pointer to contents of dir */
+ struct _dircontents *dd_cp; /* pointer to current position */
+}
+DIR;
+
+
+extern DIR *opendir(const char *);
+extern struct dirent *readdir(DIR *);
+extern void seekdir(DIR *, long);
+extern long telldir(DIR *);
+extern void closedir(DIR *);
+#define rewinddir(dirp) seekdir(dirp, 0L)
+
+int GetFileMode(char *name);
+ulg GetFileTime(char *name);
+void SetFileTime(char *path, ulg stamp);
+char *getVolumeLabel(int drive, unsigned long *time, unsigned long *mode,
+ time_t *utim);
+
+int IsFileNameValid(char *name);
+int IsFileSystemFAT(char *dir);
+void ChangeNameForFAT(char *name);
+
+char *GetLongNameEA(const char *name);
+char *GetLongPathEA(const char *name);
+void GetEAs(char *name, char **bufptr, size_t *size,
+ char **cbufptr, size_t *csize);
+
+char *StringLower(char *);
diff --git a/os2/osdep.h b/os2/osdep.h
new file mode 100644
index 0000000..ea2c3f9
--- /dev/null
+++ b/os2/osdep.h
@@ -0,0 +1,173 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#if defined(__OS2__) && !defined(OS2)
+# define OS2
+#endif
+
+/* Automatic setting of the common Microsoft C idenfifier MSC.
+ * NOTE: Watcom also defines M_I*86 !
+ */
+#if defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__))
+# ifndef MSC
+# define MSC /* This should work for older MSC, too! */
+# endif
+#endif
+
+#if defined(__WATCOMC__) && defined(__386__)
+# define WATCOMC_386
+#endif
+
+#if defined(__EMX__) || defined(WATCOMC_386) || defined(__BORLANDC__)
+# if (defined(OS2) && !defined(__32BIT__))
+# define __32BIT__
+# endif
+#endif
+
+#if defined(OS2) && !defined(__32BIT__)
+# define MEMORY16
+#endif
+
+#ifndef NO_ASM
+# define ASMV
+/* # define ASM_CRC */
+#endif
+
+/* enable creation of UTC time fields unless explicitely suppressed */
+#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))
+# define USE_EF_UT_TIME
+#endif
+
+/* check that TZ environment variable is defined before using UTC times */
+#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ))
+# define IZ_CHECK_TZ
+#endif
+
+#ifndef ZP_NEED_MEMCOMPR
+# define ZP_NEED_MEMCOMPR
+#endif
+
+#ifdef MEMORY16
+# ifdef __TURBOC__
+# include <alloc.h>
+# if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
+# if defined(DYNAMIC_CRC_TABLE) && defined(DYNALLOC_CRCTAB)
+ error: No dynamic CRC table allocation with Borland C far data models.
+# endif /* DYNAMIC_CRC_TABLE */
+# endif /* Turbo/Borland C far data memory models */
+# define nearmalloc malloc
+# define nearfree free
+# define DYN_ALLOC
+# else /* !__TURBOC__ */
+# include <malloc.h>
+# define nearmalloc _nmalloc
+# define nearfree _nfree
+# define farmalloc _fmalloc
+# define farfree _ffree
+# endif /* ?__TURBOC__ */
+# define MY_ZCALLOC 1
+#endif /* MEMORY16 */
+
+
+/* The symbol MSDOS is consistently used in the generic source files
+ * to identify code to support for MSDOS (and MSDOS related) stuff.
+ * e.g: FAT or (FAT like) file systems,
+ * '\\' as directory separator in paths,
+ * "\r\n" as record (line) terminator in text files, ...
+ *
+ * MSDOS is defined anyway with MS C 16-bit. So the block above works.
+ * For the 32-bit compilers, MSDOS must not be defined in the block above.
+ */
+#if (defined(OS2) && !defined(MSDOS))
+# define MSDOS
+/* inherit MS-DOS file system etc. stuff */
+#endif
+
+#define USE_CASE_MAP
+#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \
+ procname(n, 1))
+
+/* time stamp resolution of file system is 2 seconds */
+#define ROUNDED_TIME(time) ((time_t)(((unsigned long)(time) + 1) & (~1)))
+
+#define FOPR "rb"
+#define FOPM "r+b"
+#define FOPW "wb"
+
+#ifdef __32BIT__
+# define CBSZ 0x40000
+# define ZBSZ 0x40000
+#else
+# define CBSZ 0xE000
+# define ZBSZ 0x7F00 /* Some libraries do not allow a buffer size > 32K */
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+
+#ifdef ZCRYPT_INTERNAL
+# ifndef __GO32__
+# include <process.h> /* getpid() declaration for srand seed */
+# endif
+#endif
+
+/* for some (all ?) versions of IBM C Set/2 and IBM C Set++ */
+#ifndef S_IFMT
+# define S_IFMT 0xF000
+#endif /* !S_IFMT */
+
+#ifdef MSC
+# define NO_UNISTD_H
+#endif
+
+#ifdef __WATCOMC__
+# define NO_MKTEMP
+/* Get asm routines to link properly without using "__cdecl": */
+# ifdef __386__
+# ifdef ASMV
+# pragma aux window "*";
+# pragma aux prev "*";
+# pragma aux prev_length "*";
+# pragma aux strstart "*";
+# pragma aux match_start "*";
+# pragma aux max_chain_length "*";
+# pragma aux good_match "*";
+# pragma aux nice_match "*";
+# pragma aux match_init "*";
+# pragma aux longest_match "*";
+# endif
+# ifndef USE_ZLIB
+# pragma aux crc32 "_*" parm caller [] value [eax] modify [eax]
+# pragma aux get_crc_table "_*" parm caller [] value [eax] \
+ modify [eax ecx edx]
+# endif /* !USE_ZLIB */
+# else /* !__386__ */
+# if defined(ASMV) || defined(ASM_CRC)
+/*# error 16 bit assembly modules currently DO NOT WORK with Watcom C. */
+# endif
+# ifdef ASMV
+# pragma aux match_init "_*" parm caller [] loadds modify [ax bx]
+# pragma aux longest_match "_*" parm caller [] loadds value [ax] \
+ modify [ax bx cx dx es]
+# endif
+# ifndef USE_ZLIB
+# pragma aux crc32 "_*" parm caller [] value [ax dx] \
+ modify [ax bx cx dx es]
+# pragma aux get_crc_table "_*" parm caller [] value [ax] \
+ modify [ax bx cx dx]
+# endif /* !USE_ZLIB */
+# endif /* ?__386__ */
+#endif
+
+#ifdef __IBMC__
+# define NO_UNISTD_H
+# define NO_MKTEMP
+# define timezone _timezone /* (underscore names work with */
+# define tzset _tzset /* all versions of C Set) */
+#endif
diff --git a/os2/zip.def b/os2/zip.def
new file mode 100644
index 0000000..7404eee
--- /dev/null
+++ b/os2/zip.def
@@ -0,0 +1,3 @@
+NAME WINDOWCOMPAT NEWFILES
+DESCRIPTION 'The world-famous zip utilities from Info-ZIP'
+; STACKSIZE 0x50000
diff --git a/os2/zipup.h b/os2/zipup.h
new file mode 100644
index 0000000..592cff8
--- /dev/null
+++ b/os2/zipup.h
@@ -0,0 +1,16 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#define fhow (O_RDONLY|O_BINARY)
+#define fbad (-1)
+typedef int ftype;
+#define zopen(n,p) open(n,p)
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f) close(f)
+#define zerr(f) (k == (extent)(-1L))
+#define zstdin 0