win95-initial-port-20010430
authorJeff Riegel <riegel@almaden.ibm.com>
Mon, 30 Apr 2001 08:03:55 +0000 (08:03 +0000)
committerDerrick Brashear <shadow@dementia.org>
Mon, 30 Apr 2001 08:03:55 +0000 (08:03 +0000)
Windows 95/98 port from IBM Almaden

documentation and build support

====================
This delta was composed from multiple commits as part of the CVS->Git migration.
The checkin message with each commit was inconsistent.
The following are the additional commit messages.
====================

Windows 95/98 port from IBM Almaden

changes to cache manager

====================

Windows 95/98 port from IBM Almaden

makefile changes

====================

Windows 95/98 port from IBM Almaden

osi changes to support 95/98

====================

Windows 95/98 port from IBM Almaden

installer for 95/98 client

====================

Windows 95/98 port from IBM Almaden

win95/98 panel app

====================

Windows 95/98 port from IBM Almaden

win95/98 panel app help

====================

Windows 95/98 port from IBM Almaden

makefile changes plus dns implementation

====================

Windows 95/98 port from IBM Almaden

makefile changes plus changes for compat with dos line conventions

====================

Windows 95/98 port from IBM Almaden

config for 95/98

====================

Windows 95/98 port from IBM Almaden

makefile changes plus support for 95/98 env

====================

Windows 95/98 port from IBM Almaden

ms compiler changes

====================

Windows 95/98 port from IBM Almaden

makefile changes

====================

Windows 95/98 port from IBM Almaden

lwp changes
to support 95/98 port

====================

Windows 95/98 port from IBM Almaden

rx changes to support 95/98 port

233 files changed:
src/Makefile.djgpp [new file with mode: 0644]
src/NTMake9x [new file with mode: 0644]
src/NTMakefile
src/README-WIN9X [new file with mode: 0644]
src/TechNotes-WIN9X [new file with mode: 0644]
src/WINNT/afsd/Makefile.djgpp [new file with mode: 0644]
src/WINNT/afsd/NTMakefile
src/WINNT/afsd/afsd.h
src/WINNT/afsd/afsd95.c [new file with mode: 0644]
src/WINNT/afsd/afsd_init.h
src/WINNT/afsd/afsd_init95.c [new file with mode: 0644]
src/WINNT/afsd/afsmsg95.c [new file with mode: 0644]
src/WINNT/afsd/afsmsg95.h [new file with mode: 0644]
src/WINNT/afsd/afsrpc95.h [new file with mode: 0644]
src/WINNT/afsd/cm.h
src/WINNT/afsd/cm_access.c
src/WINNT/afsd/cm_access.h
src/WINNT/afsd/cm_aclent.c
src/WINNT/afsd/cm_buf.c
src/WINNT/afsd/cm_buf.h
src/WINNT/afsd/cm_callback.c
src/WINNT/afsd/cm_callback.h
src/WINNT/afsd/cm_cell.c
src/WINNT/afsd/cm_config.c
src/WINNT/afsd/cm_config.h
src/WINNT/afsd/cm_conn.c
src/WINNT/afsd/cm_conn.h
src/WINNT/afsd/cm_daemon.c
src/WINNT/afsd/cm_dcache.c
src/WINNT/afsd/cm_dir.c
src/WINNT/afsd/cm_diskcache95.c [new file with mode: 0644]
src/WINNT/afsd/cm_diskcache95.h [new file with mode: 0644]
src/WINNT/afsd/cm_dnlc.c
src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/cm_ioctl.h
src/WINNT/afsd/cm_rpc.c
src/WINNT/afsd/cm_rpc.h
src/WINNT/afsd/cm_rpc95.h [new file with mode: 0644]
src/WINNT/afsd/cm_scache.c
src/WINNT/afsd/cm_scache.h
src/WINNT/afsd/cm_server.c
src/WINNT/afsd/cm_server.h
src/WINNT/afsd/cm_user.c
src/WINNT/afsd/cm_utils.c
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/afsd/cm_vnodeops.h
src/WINNT/afsd/cm_volume.c
src/WINNT/afsd/dosdefs95.h [new file with mode: 0644]
src/WINNT/afsd/dosutils95.c [new file with mode: 0644]
src/WINNT/afsd/fs_utils.h
src/WINNT/afsd/largeint95.c [new file with mode: 0644]
src/WINNT/afsd/largeint95.h [new file with mode: 0644]
src/WINNT/afsd/netbios95.c [new file with mode: 0644]
src/WINNT/afsd/netbios95.h [new file with mode: 0644]
src/WINNT/afsd/queue95.c [new file with mode: 0644]
src/WINNT/afsd/queue95.h [new file with mode: 0644]
src/WINNT/afsd/smb.c
src/WINNT/afsd/smb.h
src/WINNT/afsd/smb3.c
src/WINNT/afsd/smb3.h
src/WINNT/afsd/smb_iocons.h
src/WINNT/afsd/smb_ioctl.c
src/WINNT/afsd/smb_ioctl.h
src/WINNT/afsreg/NTMakefile
src/WINNT/client_config/NTMakefile
src/WINNT/client_config/lang/NTMakefile
src/WINNT/client_cpa/NTMakefile
src/WINNT/client_cpa/lang/NTMakefile
src/WINNT/client_creds/lang/NTMakefile
src/WINNT/client_exp/NTMakefile
src/WINNT/client_exp/lang/NTMakefile
src/WINNT/client_osi/Makefile.djgpp [new file with mode: 0644]
src/WINNT/client_osi/NTMakefile
src/WINNT/client_osi/osi.h
src/WINNT/client_osi/osifd.c
src/WINNT/client_osi/osifd.h
src/WINNT/client_osi/osilog.c
src/WINNT/client_osi/osilog.h
src/WINNT/client_osi/osiqueue.c
src/WINNT/client_osi/osisleep.h
src/WINNT/client_osi/osithrd95.c [new file with mode: 0644]
src/WINNT/client_osi/osithrd95.h [new file with mode: 0644]
src/WINNT/client_osi/osithrdnt.h [new file with mode: 0644]
src/WINNT/eventlog/NTMakefile
src/WINNT/eventlog/lang/NTMakefile
src/WINNT/install/Win9x/CellServDB [new file with mode: 0644]
src/WINNT/install/Win9x/NTMakeFile [new file with mode: 0644]
src/WINNT/install/Win9x/RUNONCE.PIF [new file with mode: 0755]
src/WINNT/install/Win9x/ReadMe.rtf [new file with mode: 0644]
src/WINNT/install/Win9x/install.bat [new file with mode: 0644]
src/WINNT/install/Win9x/license.txt [new file with mode: 0644]
src/WINNT/install/Win9x/templet.reg [new file with mode: 0644]
src/WINNT/pthread/NTMakefile
src/WINNT/talocale/NTMakefile
src/WINNT/win9xpanel/CAfs.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/CRegkey.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/CRegkey.h [new file with mode: 0644]
src/WINNT/win9xpanel/CellServDB [new file with mode: 0644]
src/WINNT/win9xpanel/Change.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/Change.h [new file with mode: 0644]
src/WINNT/win9xpanel/CommandSettings.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/CommandSettings.h [new file with mode: 0644]
src/WINNT/win9xpanel/Datalog.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/Datalog.h [new file with mode: 0644]
src/WINNT/win9xpanel/Encript.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/Force.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/Force.h [new file with mode: 0644]
src/WINNT/win9xpanel/Help/Advanced.mrb [new file with mode: 0755]
src/WINNT/win9xpanel/Help/PROGRESS.MRB [new file with mode: 0755]
src/WINNT/win9xpanel/Help/PROPER.MRB [new file with mode: 0755]
src/WINNT/win9xpanel/Help/afswin9x.cnt [new file with mode: 0644]
src/WINNT/win9xpanel/Help/afswin9x.hpj [new file with mode: 0644]
src/WINNT/win9xpanel/Help/afswin9x.rtf [new file with mode: 0644]
src/WINNT/win9xpanel/Help/icon.bmp [new file with mode: 0755]
src/WINNT/win9xpanel/MyFrame.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/MyFrame.h [new file with mode: 0644]
src/WINNT/win9xpanel/NTMakefile [new file with mode: 0644]
src/WINNT/win9xpanel/ProgBarDlg.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/ProgBarDlg.h [new file with mode: 0644]
src/WINNT/win9xpanel/Retry.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/Retry.h [new file with mode: 0644]
src/WINNT/win9xpanel/Settings.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/Settings.h [new file with mode: 0644]
src/WINNT/win9xpanel/StdAfx.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/StdAfx.h [new file with mode: 0644]
src/WINNT/win9xpanel/TermWarn.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/TermWarn.h [new file with mode: 0644]
src/WINNT/win9xpanel/Transbmp.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/Transbmp.h [new file with mode: 0644]
src/WINNT/win9xpanel/TrayIcon.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/TrayIcon.h [new file with mode: 0644]
src/WINNT/win9xpanel/Wait.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/Wait.h [new file with mode: 0644]
src/WINNT/win9xpanel/WinAfsLoad.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/WinAfsLoad.dep [new file with mode: 0644]
src/WINNT/win9xpanel/WinAfsLoad.h [new file with mode: 0644]
src/WINNT/win9xpanel/WinAfsLoad.rc [new file with mode: 0644]
src/WINNT/win9xpanel/WinAfsLoadDlg.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/WinAfsLoadDlg.h [new file with mode: 0644]
src/WINNT/win9xpanel/api95.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/api95.h [new file with mode: 0644]
src/WINNT/win9xpanel/cafs.h [new file with mode: 0644]
src/WINNT/win9xpanel/encript.h [new file with mode: 0644]
src/WINNT/win9xpanel/modver.cpp [new file with mode: 0644]
src/WINNT/win9xpanel/modver.h [new file with mode: 0644]
src/WINNT/win9xpanel/res/WinAfsLoad.ico [new file with mode: 0755]
src/WINNT/win9xpanel/res/world.bmp [new file with mode: 0755]
src/WINNT/win9xpanel/resource.h [new file with mode: 0644]
src/WINNT/win9xpanel/share.h [new file with mode: 0644]
src/audit/NTMakefile
src/auth/Makefile
src/auth/NTMakefile
src/auth/cellconfig.c
src/auth/ktc_nt.c
src/cmd/Makefile
src/cmd/NTMakefile
src/comerr/NTMakefile
src/comerr/compile_et.c
src/comerr/et_lex.lex_nt.c
src/config/Makefile.djgpp.common [new file with mode: 0644]
src/config/Makefile.i386_djgpp [new file with mode: 0644]
src/config/NTMakefile
src/config/NTMakefile.i386_nt40
src/config/NTMakefile.i386_win95 [new file with mode: 0644]
src/config/afs_sysnames.h
src/config/param.i386_djgpp.h [new file with mode: 0644]
src/config/param.i386_djgpp_usr.h [new file with mode: 0644]
src/config/param.i386_win95.h [new file with mode: 0644]
src/config/touch.c [new file with mode: 0644]
src/config/util_cr.c [new file with mode: 0644]
src/des/Makefile
src/des/NTMakefile
src/des/andrew-conf.h
src/des/new_rnd_key.c
src/des_stub/NTMakefile
src/fsint/Makefile
src/fsint/NTMakefile
src/kauth/NTMakefile
src/kauth/kautils.p.h
src/libacl/NTMakefile
src/libadmin/NTMakefile
src/libadmin/kas/afs_kasAdmin.h
src/libadmin/vos/afs_vosAdmin.h
src/libafsauthent/NTMakefile
src/libafsrpc/NTMakefile
src/lwp/Makefile
src/lwp/NTMake9x [new file with mode: 0644]
src/lwp/NTMakefile
src/lwp/iomgr.c
src/lwp/lwp.h
src/lwp/lwp_nt.c
src/lwp/preempt.c
src/lwp/process.s
src/lwp/timer.c
src/lwp/waitkey.c
src/mkdest.pl [new file with mode: 0644]
src/ntbuild.bat
src/pinstall/Makefile
src/procmgmt/Makefile
src/procmgmt/NTMakefile
src/ptserver/Makefile
src/ptserver/NTMakefile
src/rmbat.bat [new file with mode: 0644]
src/rmbat.rsp [new file with mode: 0644]
src/rx/Makefile
src/rx/NTMakefile
src/rx/rx.c
src/rx/rx_getaddr.c
src/rx/rx_lwp.c
src/rx/rx_misc.c
src/rx/rx_packet.c
src/rx/rx_packet.h
src/rx/rx_user.c
src/rx/rx_xmit_nt.c
src/rx/rx_xmit_nt.h
src/rx/xdr.h
src/rxgen/Makefile
src/rxgen/NTMakefile
src/rxkad/NTMakefile
src/rxstat/Makefile
src/rxstat/NTMakefile
src/symlink.bat [new file with mode: 0644]
src/sys/NTMakefile
src/sys/pioctl_nt.c
src/tbutc/NTMakefile
src/ubik/NTMakefile
src/usd/NTMakefile
src/util/Makefile
src/util/NTMakefile
src/util/afsutil.h
src/vlserver/Makefile
src/vlserver/NTMakefile
src/vlserver/vlserver.c

diff --git a/src/Makefile.djgpp b/src/Makefile.djgpp
new file mode 100644 (file)
index 0000000..362b1b2
--- /dev/null
@@ -0,0 +1,85 @@
+# Top-level Makefile for Win95/DJGPP AFS client
+# Assumes you are doing cross-compiling from Linux
+# Set LINUX_SYS to the proper sysname for your Linux system
+
+OBJ = $(SYS_NAME)/obj
+DEST = $(SYS_NAME)/dest
+#LINUX_SYS = i386_linux22
+
+all: afsd
+
+afsd: config pinstall libs
+       make -C $(OBJ)/WINNT/afsd -f Makefile.djgpp depends
+       make -C $(OBJ)/WINNT/afsd -f Makefile.djgpp install
+
+utils: pinstall rxgen comerr
+includes: afsdinc osiinc authinc 
+libs: fsint cmd lwp osi rx rxkad vldb rxstat acl
+
+clean:
+       -rm -f $(SYS_NAME)/dest/include/*
+       -rm -f $(SYS_NAME)/dest/include/afs/*
+       -rm -f $(SYS_NAME)/dest/lib/*
+       -rm -f $(SYS_NAME)/dest/lib/afs/*
+       -rm -f $(SYS_NAME)/dest/bin/*
+
+config:
+       -make -C $(OBJ)/config install
+
+# pinstall, rxgen, comerr, and util are built to run on Linux
+pinstall: config
+       -mkdir $(OBJ)/pinstall/afs
+       -cp $(OBJ)/config/param.$(LINUX_SYS).h $(OBJ)/pinstall/afs/param.h
+       make -C $(OBJ)/pinstall SYS_NAME=$(LINUX_SYS) install
+rxgen: config
+       -mkdir $(OBJ)/rxgen/afs
+       -cp $(OBJ)/config/param.$(LINUX_SYS).h $(OBJ)/rxgen/afs/param.h
+       make -C $(OBJ)/rxgen SYS_NAME=$(LINUX_SYS) install
+comerr: config util
+       -mkdir $(OBJ)/comerr/afs
+       -cp $(OBJ)/config/param.$(LINUX_SYS).h $(OBJ)/comerr/afs/param.h
+       make -C $(OBJ)/comerr SYS_NAME=$(LINUX_SYS) install
+util: config procmgmt
+       -mkdir $(OBJ)/util/afs
+       -cp $(OBJ)/util/param.$(LINUX_SYS).h $(OBJ)/util/afs/param.h
+       make -C $(OBJ)/util SYS_NAME=$(LINUX_SYS) install
+
+procmgmt:
+       make -C $(OBJ)/procmgmt includes
+lwp: util afsdinc osiinc lwpinc
+       make -C $(OBJ)/lwp install
+lwpinc:
+       make -C $(OBJ)/lwp includes
+rx: rxgen lwp
+       make -C $(OBJ)/rx install-djgpp
+des: desprogs
+       make -C $(OBJ)/des install
+desprogs:
+       make -C $(OBJ)/des SYS_NAME=$(LINUX_SYS) gprogs
+ubik: rx lwp
+       make -C $(OBJ)/ubik install
+fsint: rx rxgen
+       make -C $(OBJ)/fsint install
+rxkad: rx des
+       make -C $(OBJ)/rxkad install
+audit: fsint
+       make -C $(OBJ)/audit install
+authinc: comerr
+       make -C $(OBJ)/auth includes
+vldb: rxgen rx authinc audit ubik rxkad
+       make -C $(OBJ)/vlserver libinstall
+rxstat: rxgen rx
+       make -C $(OBJ)/rxstat install
+cmd: comerr
+       make -C $(OBJ)/cmd install
+afsdinc:
+       make -C $(OBJ)/WINNT/afsd -f Makefile.djgpp includes
+osiinc:
+       make -C $(OBJ)/WINNT/client_osi -f Makefile.djgpp includes
+osi: config
+       make -C $(OBJ)/WINNT/client_osi -f Makefile.djgpp depends
+       make -C $(OBJ)/WINNT/client_osi -f Makefile.djgpp install
+acl: config ptlib
+       make -C $(OBJ)/libacl install
+ptlib: config rxgen comerr
+       make -C $(OBJ)/ptserver libinstall
diff --git a/src/NTMake9x b/src/NTMake9x
new file mode 100644 (file)
index 0000000..0676d63
--- /dev/null
@@ -0,0 +1,320 @@
+# Copyright 2000, International Business Machines Corporation and others.
+# All Rights Reserved.
+# 
+# This software has been released under the terms of the IBM Public
+# License.  For details, see the LICENSE file in the top-level source
+# directory or online at http://www.openafs.org/dl/license10.html
+
+# Top level nmake NTMakefile driver for building AFS.
+#
+# This file simply imposes a reasonable total ordering on the set of
+# directories to build; this ordering is of course more strict than the
+# partial ordering established by the actual directory dependencies.
+#
+# When porting a new directory, simply add the directory into the
+# dependence chain at the earliest point possible, updating its successor
+# appropriately; if the new directory is the last in the chain, then
+# update the 'finale' dependency to be the new directory.
+
+
+CD = cd
+NTMAKE = nmake /nologo /f ntmakefile install9x
+NTMAKELANG = nmake /nologo /f ntmakefile en_install
+NTMAKE_HEADERS = nmake /nologo /f ntmakefile install_headers
+NTMAKE_LIBUTILS = nmake /nologo /f ntmakefile install_libutils
+MKDIR = mkdir
+OBJ = src
+
+# Standard install directory.
+!IFDEF AFSDEV_DESTDIR
+DESTDIR = $(AFSDEV_DESTDIR)
+!ELSE
+DESTDIR = $(AFSROOT)\DEST
+!ENDIF
+
+
+start:
+!      IF (!EXIST(src))
+!      ERROR Execute nmake from directory above src, e.g., afs\3.5.
+!      ENDIF
+!      IF (!EXIST($(DESTDIR)))
+    $(MKDIR) $(DESTDIR)
+!      ENDIF
+
+config:
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+procmgmt_headers: config
+     echo ***** $@
+       $(CD) $(OBJ)\procmgmt
+       $(NTMAKE_HEADERS)
+       $(CD) ..\..
+
+afsreg_headers: config
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\afsreg
+       $(NTMAKE_HEADERS)
+       $(CD) ..\..\..
+
+util: procmgmt_headers afsreg_headers
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+comerr: util
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+cmd: comerr
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+afsreg: cmd
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
+       $(NTMAKE)
+       $(CD) ..\..\..
+
+eventlog: afsreg
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
+       $(NTMAKE)
+       $(CD) ..\..\..
+
+lwp: eventlog
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+rxgen: lwp
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+des: rxgen
+     echo ***** $@
+!      IF (EXIST($(OBJ)\des\NTMakefile))
+               $(CD) $(OBJ)\des
+               $(NTMAKE)
+               $(CD) ..\..
+!      ELSE
+               $(CD) $(OBJ)\des_stub
+               $(NTMAKE)
+               $(CD) ..\..
+!      ENDIF
+
+rx: des
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+rxstat: rx
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+rxkad: rxstat
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+pthread: rxkad
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
+       $(NTMAKE)
+       $(CD) ..\..\..
+
+procmgmt: pthread
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+fsint: procmgmt
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+audit: fsint
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+osi_headers: audit
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\client_osi
+       $(NTMAKE_HEADERS)
+       $(CD) ..\..\..
+
+libacl_headers: osi_headers
+     echo ***** $@
+       $(CD) $(OBJ)\libacl
+       $(NTMAKE_HEADERS)
+       $(CD) ..\..
+
+cm_headers: libacl_headers
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\afsd
+       $(NTMAKE_HEADERS)
+       $(CD) ..\..\..
+
+sys: cm_headers
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+auth: sys
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+ubik: auth
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..     
+
+ptserver: ubik
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE_LIBUTILS)
+       $(CD) ..\..     
+
+libacl: ptserver
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+kauth: libacl
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+vlserver: kauth
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE_LIBUTILS)
+       $(CD) ..\..
+
+usd: vlserver
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+libafsrpc: usd
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+libafsauthent: libafsrpc
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+libadmin: libafsauthent
+     echo ***** $@
+       $(CD) $(OBJ)\$@
+       $(NTMAKE)
+       $(CD) ..\..
+
+client_talocale: libadmin
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\talocale
+       $(NTMAKE)
+       $(CD) ..\..\..
+
+client_osi: client_talocale
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
+       $(NTMAKE)
+       $(CD) ..\..\..
+
+afsd: client_osi
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
+       $(NTMAKE_LIBUTILS)
+       $(CD) ..\..\..
+
+client_cpa: afsd
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
+       $(NTMAKE)
+       $(CD) ..\..\..
+
+client_config: client_cpa
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
+       $(NTMAKE)
+       $(CD) ..\..\..
+
+client_exp: client_config
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
+       $(NTMAKE)
+       $(CD) ..\..\..
+
+
+#Leave last echo in - it helps the build reconize the last $(CD)
+win9xpanel :
+       echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
+       $(NTMAKE)
+       $(CD) ..\..\..
+       echo ***** End of Build 
+
+install: start client_exp win9xpanel
+
+install9x: install
+
+# InstallShield dependencies
+
+#Leave last echo in - it helps the build reconize the last $(CD)
+Win9x::
+       $(CD) $(OBJ)\WINNT\install\$@
+    nmake /nologo /f NTMakefile  install9x
+       $(CD) ..\..\..\..
+       echo **** End of Install Scripts
+
+media: Win9x
+
+# Clean target for obj tree
+# Fake the version copy so clean will go through the complete cycle with undefines
+clean: start
+       if not exist .\src\config\NTMakefile.version copy .\src\config\NTMakefile.version-NOCML .\src\config\NTMakefile.version
+    nmake /nologo /f ntmake9x "NTMAKE = nmake /nologo /f ntmakefile clean" "NTMAKE_HEADERS = nmake /nologo /f ntmakefile clean" "NTMAKE_LIBUTILS = nmake /nologo /f ntmakefile clean" install
+       $(CD) $(OBJ)\WINNT\install\Win9x
+       nmake /nologo /f NTMakefile clean
+       $(CD) ..\..\..\..
+       .\src\rmbat $(DESTDIR)\include\*.* $(DESTDIR)\include\afs\*.* $(DESTDIR)\include\WINNT\*.* $(DESTDIR)\include\rx\*.*
+       .\src\rmbat $(DESTDIR)\LIB\*.LIB $(DESTDIR)\LIB\*.DLL $(DESTDIR)\LIB\AFS\*.LIB
+       .\src\RMBAT $(DESTDIR)\root.client\usr\vice\etc\*.*
+       $(CD) $(OBJ)\config
+       nmake /nologo /f ntmakefile clean_version
+       $(CD) ..\..
+       echo **** End of Clean
+
+# Language-only build target
+lang:
+        nmake /nologo /f ntmakefile "NTMAKE = nmake /nologo /f ntmakefile lang" "NTMAKE_HEADERS = nmake /nologo /f ntmakefile lang" install
index 02af8af..b6ebfa5 100644 (file)
 
 CD = cd
 NTMAKE = nmake /nologo /f ntmakefile install
+NTMAKELANG = nmake /nologo /f ntmakefile en_US
 NTMAKE_HEADERS = nmake /nologo /f ntmakefile install_headers
 MKDIR = mkdir
+OBJ = obj
 
 # Standard install directory.
 !IFDEF AFSDEV_DESTDIR
@@ -39,362 +41,433 @@ start:
 !      ENDIF
 
 config:
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 procmgmt_headers: config
-       $(CD) src\procmgmt
+     echo ***** $@
+       $(CD) $(OBJ)\procmgmt
        $(NTMAKE_HEADERS)
        $(CD) ..\..
 
 afsreg_headers: config
-       $(CD) src\WINNT\afsreg
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\afsreg
        $(NTMAKE_HEADERS)
        $(CD) ..\..\..
 
 util: procmgmt_headers afsreg_headers
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 comerr: util
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 cmd: comerr
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 afsreg: cmd
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 eventlog: afsreg
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 lwp: eventlog
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 rxgen: lwp
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 des: rxgen
-!      IF (EXIST(src\des\NTMakefile))
-               $(CD) src\des
+     echo ***** $@
+!      IF (EXIST($(OBJ)\des\NTMakefile))
+               $(CD) $(OBJ)\des
                $(NTMAKE)
                $(CD) ..\..
 !      ELSE
-               $(CD) src\des_stub
+               $(CD) $(OBJ)\des_stub
                $(NTMAKE)
                $(CD) ..\..
 !      ENDIF
 
 rx: des
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 rxstat: rx
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 rxkad: rxstat
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 pthread: rxkad
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 procmgmt: pthread
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 fsint: procmgmt
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 audit: fsint
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 osi_headers: audit
-       $(CD) src\WINNT\client_osi
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\client_osi
        $(NTMAKE_HEADERS)
        $(CD) ..\..\..
 
 libacl_headers: osi_headers
-       $(CD) src\libacl
+     echo ***** $@
+       $(CD) $(OBJ)\libacl
        $(NTMAKE_HEADERS)
        $(CD) ..\..
 
 cm_headers: libacl_headers
-       $(CD) src\WINNT\afsd
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\afsd
        $(NTMAKE_HEADERS)
        $(CD) ..\..\..
 
 sys: cm_headers
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 auth: sys
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 ubik: auth
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..     
 
 ptserver: ubik
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..     
 
 libacl: ptserver
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 kauth: libacl
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 vlserver: kauth
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 usd: vlserver
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 bubasics: usd
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 budb:  bubasics
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 butm:  budb
-        $(CD) src\$@
+     echo ***** $@
+        $(CD) $(OBJ)\$@
         $(NTMAKE)
         $(CD) ..\..
 
 dir: butm
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 vol: dir
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 volser: vol
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 viced: volser
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 update: viced
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 bucoord: update
-        $(CD) src\$@
+     echo ***** $@
+        $(CD) $(OBJ)\$@
         $(NTMAKE)
         $(CD) ..\..
 
 butc:   bucoord
-        $(CD) src\$@
+     echo ***** $@
+        $(CD) $(OBJ)\$@
         $(NTMAKE)
         $(CD) ..\..
 
 bozo: butc
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 bosctlsvc: bozo
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 bu_utils: bosctlsvc
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 libafsrpc: bu_utils
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 libafsauthent: libafsrpc
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 tviced: libafsauthent
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
 
 tbutc:  tviced
-        $(CD) src\$@
+     echo ***** $@
+        $(CD) $(OBJ)\$@
         $(NTMAKE)
         $(CD) ..\..
 
 libadmin: tbutc
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..
        
 adminutil: libadmin
-       $(CD) src\libadmin\$@
+     echo ***** $@
+       $(CD) $(OBJ)\libadmin\$@
        $(NTMAKE)
        $(CD) ..\..\..
        
 vos: adminutil
-       $(CD) src\libadmin\$@
+     echo ***** $@
+       $(CD) $(OBJ)\libadmin\$@
        $(NTMAKE)
        $(CD) ..\..\..
        
 client: vos
-       $(CD) src\libadmin\$@
+     echo ***** $@
+       $(CD) $(OBJ)\libadmin\$@
        $(NTMAKE)
        $(CD) ..\..\..
        
 kas: client
-       $(CD) src\libadmin\$@
+     echo ***** $@
+       $(CD) $(OBJ)\libadmin\$@
        $(NTMAKE)
        $(CD) ..\..\..
        
 pts: kas
-       $(CD) src\libadmin\$@
+     echo ***** $@
+       $(CD) $(OBJ)\libadmin\$@
        $(NTMAKE)
        $(CD) ..\..\..
        
 bos: pts
-       $(CD) src\libadmin\$@
+     echo ***** $@
+       $(CD) $(OBJ)\libadmin\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 cfg: bos
-       $(CD) src\libadmin\$@
+     echo ***** $@
+       $(CD) $(OBJ)\libadmin\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 admintest: cfg
-       $(CD) src\libadmin\test
+     echo ***** $@
+       $(CD) $(OBJ)\libadmin\test
        $(NTMAKE)
        $(CD) ..\..\..
 
 talocale: admintest
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 license: talocale
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 afsadmsvr: license
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 afsusrmgr: afsadmsvr
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 afssvrmgr: afsusrmgr
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 afssvrcfg: afssvrmgr
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 afssvrcpa: afssvrcfg
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 afs_setup_utils: afssvrcpa
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 client_talocale: afs_setup_utils
-       $(CD) src\WINNT\talocale
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\talocale
        $(NTMAKE)
        $(CD) ..\..\..
 
 client_osi: client_talocale
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 afsd: client_osi
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 client_cpa: afsd
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 client_config: client_cpa
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 client_exp: client_config
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 client_creds: client_exp
-       $(CD) src\WINNT\$@
+     echo ***** $@
+       $(CD) $(OBJ)\WINNT\$@
        $(NTMAKE)
        $(CD) ..\..\..
 
 finale: client_creds
-       $(CD) src\$@
+     echo ***** $@
+       $(CD) $(OBJ)\$@
        $(NTMAKE)
        $(CD) ..\..     
 
@@ -403,7 +476,7 @@ install: start finale
 # InstallShield dependencies
 
 InstallShield5: install
-       $(CD) src\WINNT\install\$@
+       $(CD) $(OBJ)\WINNT\install\$@
        $(NTMAKE)
        $(CD) ..\..\..\..
 
@@ -411,10 +484,10 @@ media: InstallShield5
 
 
 
-# Clean target for src tree
+# Clean target for obj tree
 clean: start
         nmake /nologo /f ntmakefile "NTMAKE = nmake /nologo /f ntmakefile clean" "NTMAKE_HEADERS = nmake /nologo /f ntmakefile clean" install
-       $(CD) src\config
+       $(CD) $(OBJ)\config
        nmake /nologo /f ntmakefile clean_version
        $(CD) ..\..
 
diff --git a/src/README-WIN9X b/src/README-WIN9X
new file mode 100644 (file)
index 0000000..a19ba59
--- /dev/null
@@ -0,0 +1,165 @@
+Copyright 2000, International Business Machines Corporation and others.
+All Rights Reserved.
+
+This software has been released under the terms of the IBM Public
+License.  For details, see the LICENSE file in the top-level source
+directory or online at http://www.openafs.org/dl/license10.html
+
+Building Open AFS on Win 95
+---------------------------
+
+The Windows 95 Open AFS client consists of two main components: the client
+program afsd.exe, which is compiled with the DJGPP compiler and runs in a
+DOS virtual machine; and the utility programs, which are built on Windows
+NT or 9x using the Microsoft Visual C++ compiler V6.0.
+
+afsd.exe
+--------
+
+afsd.exe is built using the DJGPP cross-compiler, executed from Linux.
+It should also be possible to build it using the native DOS DJGPP compiler,
+but we did not try this.  You will need to install the following packages
+from DJGPP and the Coda project.
+
+ftp://ftp.coda.cs.cmu.edu/pub/tools/djgpp-2.01_0.93_glibc-1.i386.rpm
+ftp://ftp.coda.cs.cmu.edu/pub/tools/djgpp-win95ext-2.01_0.93_glibc-1.i386.rpm
+ftp://ftp.coda.cs.cmu.edu/pub/tools/gdb-djgpp-4.16-2.i386.rpm
+
+You will also need the MMAP.VXD and SOCK.VXD from the Coda project.  Source
+is available here:
+ftp://ftp.coda.cs.cmu.edu/pub/coda/src/win95-coda-5.2.0.zip
+
+Follow the Coda instructions to build these VXD's, which you can read here:
+http://www.coda.cs.cmu.edu/doc/html/coda-howto-6.html#ss6.4
+
+Once you have the necessary tools installed, set the following environment
+variables:
+SYS_NAME: set to i386_djgpp
+LINUX_SYS: set to the sysname of the Linux version you are using, e.g.,
+           i386_linux22
+
+The makefile expects to build into a platform directory with symlinks
+into the source directory.  The Perl script "mkdest.pl" in this dir. will
+set this up for you.  To use it, create a directory under the top-level
+dir. (the directory above src) called "i386_djgpp".  Then cd to that
+directory and type "../src/mkdest.pl <absolute path of your src dir.>"
+
+Then execute "make -f Makefile.djgpp" from the top-level directory.
+(You can create a symlink to src/Makefile.djgpp from this dir.)
+The afsd.exe will be built into i386_djgpp/dest/bin.
+
+Build notes:
+
+  The Makefile.djgpp actually builds Linux versions of the utilities
+  rxgen, install, compile_et, and util.a.  It uses the Linux version
+  of param.h which it copies to the afs subdirectory of the above
+  components.  You will need to set SYS_NAME to your Linux system name
+  manually if you want to build these utilities separately.
+
+Utilities and GUI programs
+--------------------------
+
+The rest of the support programs are built as Win32 executables from a
+Windows 9x or NT system.  You will need to set the following environment
+variables:
+
+set SYS_NAME=i386_win95
+set AFSDEV_BUILDTYPE=CHECKED (or FREE if you want to skip debugging info.)
+set AFSDEV_INCLUDE=<path of your Visual C include files>
+set AFSDEV_LIB=<path of your Visual C libs>
+set AFSDEV_BIN=.
+set AFSROOT=<PATH to base of development directory> 
+       e.g. AFSROOT\SRC is source directory of the build tree
+SET _WIN32_IE=0x400
+set OBJ=src or obj, see below
+set MSSDK=<path to sdk header files>, see below
+
+If you are building on a Unix directory exported to Windows through Samba
+or AFS, you can create a platform directory named "i386_win95" using the
+"mkdest.pl" script as described above (run from a Unix system).  This will
+only work on a file system that supports symbolic links.  If you are using
+a platform directory, set the OBJ environment var. to "obj" and create
+a symlink "obj" in the top-level dir. that points to "i386_win95/obj".
+Otherwise, set OBJ to "src" to build the objects with the sources.
+
+The environment variable AFSROOT points to the parent of the AFS src
+directory.  Executables will be built by default in AFSROOT\dest.
+
+Copy the file src\NTMake9x to the parent of the src directory.  You only
+need to do this once.  If you are building on a local drive, copy
+AFSROOT\src\symlink.bat to AFSROOT\.
+
+Follow the NT build instructions in file "README-NT" to perform the build.
+You will be using "NTMake9x" as the top-level makefile, instead of
+"NTMakefile".  Most of the instructions in "README-NT" apply to the Win9x
+build as well.
+
+Build Notes:
+
+1) If you are building the Windows 9x AFS Client Control Panel
+   (win9xpanel), it requires shlwapi.h.  This file can be found in the
+   header files associated with the Windows SDK (95/98 NT or W2000).
+
+2) You can build the Windows 9x client from a Windows NT or W2000 system.
+   This requires you to edit AFSROOT\config\NTMakefile.i386_win95.
+   Change line: DEL = $(AFSROOT)\src\rmbat
+                to:  DEL = -del  /q /f
+
+3) If you build the W2000 client, then switch to building the Windows 95
+   client (or vice versa), you should clean the previous build by either:
+       nmake -f ntmakefile clean 
+or     nmake -f ntmake9x clean
+
+4) When building the "comerr" component, the makefile now uses the
+   existing error_table_nt.c file (and touches it so it will be up to date
+   by default.)  If you make changes to the lex or yacc source files and want
+   to rebuild error_table_nt.c, you can simply delete it and rerun make,
+   which will cause the file to be built using lex and yacc.  Make sure
+   you have these utilities on your system.
+
+5) Required DLL's for redistribution
+
+   The AFS Control Panel for Win95/98 requires Microsoft DLL's that can
+   be installed using:
+      VC6RedistSetup_enu.exe
+   This is located at:
+      http://support.microsoft.com/support/kb/articles/Q259/4/03.ASP
+
+6) Installation
+
+   First, execute "nmake /f ntmake9x media" to copy all the client
+   executables and other files to DEST\WinInstall.
+
+   You can then install the client onto a target Windows 9x machine by
+   executing:
+     install.bat <source> <drive> <install dir.> <home cell> <cache size in 1K blocks>
+   For example,
+     install.bat DEST\WinInstall\ c: \afscli almaden.ibm.com 40000
+
+   If you do not wish to use the batch file, you can install the client
+   manually by performing the following steps.
+
+   1. On the target machine, copy all the files from DEST\WinInstall to the
+      install location (usually c:\afscli).
+   2. Add entries to the target's AUTOEXEC.BAT file as follows:
+       set AFSCONF=c:\afscli (replace with your install dir.)
+       path %path%;c:\afscli
+   3. Copy the template.reg file to afscli.reg.  Replace any references
+      to c: and afscli with your install location.  Double click on the
+      afscli.reg file to add the registry entries to the target system.
+   4. Create the following AFS configuration files in the install dir.:
+      - ThisCell:
+        containing the name of your home cell
+      - cache.info:
+        containing your cache configuration.  For example,
+        to configure a cache of 40,000 1KB blocks with a disk cache
+        location of c:\afscache, you would enter in this file:
+            /afs:c:\afscache;40000
+        (The cache location has no effect unless you have enabled
+        the experimental disk cache support.)
+      - CellServDB:
+        the cell server database.  You can get the latest version from AFS:
+        /afs/transarc.com/service/etc/CellServDB.export
+   5. Reboot the target machine.
+   6. You can now start the client by executing the program WinAfsLoad.exe
+      from the install directory.
diff --git a/src/TechNotes-WIN9X b/src/TechNotes-WIN9X
new file mode 100644 (file)
index 0000000..ced7f49
--- /dev/null
@@ -0,0 +1,154 @@
+Win9x AFS Client: Technical Notes
+---------------------------------
+
+This file gives a technical overview of the Win9x AFS client and describes
+the main differences from the NT client.
+
+
+Overview
+--------
+
+The Windows 9x client is based on the Windows NT/2000 client.  Like the
+NT client, it exports AFS through an SMB interface.  Programs access AFS
+files by mounting AFS submounts as SMB shares and using the built-in
+Windows SMB client to communicate with the AFS client.  The AFS client
+acts as an SMB server.  It runs entirely at user level.
+
+DOS box implementation and VXD's
+--------------------------------
+
+The main program of the Win9x client, afsd.exe, is implemented as a
+32-bit DOS program.  It is compiled using the DJGPP compiler and runs in
+a Windows 9x DOS virtual machine.  This approach was necessary to avoid
+a well-known deadlock problem in Windows 9x when the kernel calls up
+to a user-level Win32 daemon: the original requesting program grabs the
+Win16Mutex before entering the kernel.  The request is then passed up to
+the daemon, who attempts to service it using network or file I/O calls.
+These calls also attempt to obtain the Win16Mutex, which is still being
+held by the original requester, so there is a deadlock.
+
+To avoid this problem, the daemon runs in a DOS box.  I/O calls from
+a DOS program do not attempt to obtain the Win16Mutex, so the deadlock
+is avoided.  This approach was discovered by the Coda team at Carnegie
+Mellon University and used to implement a Win9x version of their client.
+The Win9x AFS client uses the same approach.  It also uses the Coda team's
+SOCK.VXD which was written to provide network functions to a DOS program.
+Sockets functions which call SOCK.VXD were added to the DJGPP library.
+
+For more information about the Coda team's approach to this problem, see
+their paper from Usenix 1999:
+http://www.cs.cmu.edu/afs/cs/project/coda/Web/docdir/freenix99.pdf
+
+Note that the AFS client also requires the Coda team's MMAP.VXD.  We are
+not actually calling this VXD, but afsd crashes if it is built without
+it (i.e., by building with dos-gcc -bw95 instead of -bmmap).  Solutions to
+this problem welcomed..
+
+Netbios functions
+-----------------
+
+The Windows AFS clients communicate with user applications using the
+SMB protocol, as described above.  SMB communication is done using the
+Netbios interface.  In Win32, there is a built-in function Netbios()
+which accomplishes this.  In a DOS program, however, this function is
+unavailable.  However, Netbios functionality is available in the BIOS
+by calling interrupt 0x5c.  The NCB (Netbios Control Block) and data
+buffer must be in conventional DOS memory, i.e., below 1 MB.  This memory
+can only be accessed in DJGPP by using the DOS memory access functions:
+dosmemget(), dosmemput(), _farpeekX() and _farpokeX().  The Win9x client
+uses a separately-allocated DOS memory buffer and copies data to and from
+DOS memory for network communication.
+
+Functions were also added to LWP's iomgr.c to check for the completion
+of Netbios requests.  The IOMGR now checks for NCB completion in addition
+to checking for timer expiration, signal delivery, and performing select()
+on file descriptors.
+
+See the new files: netbios95.c, dosutils95.c, and the various changes
+(marked by "#ifdef DJGPP") to smb.c in WINNT/afsd.  Also see lwp/iomgr.c.
+
+Thread functions
+----------------
+
+Unlike the NT client which uses Win32 thread and locking functions,
+the Win9x client uses the LWP package from the AFS source distribution.
+An interface layer was added to allow NT and Win9x to make the same calls.
+For example, thrd_Create() is now used to create a thread.  In NT, this
+is just a macro to the Win32 function CreateThread().  In Win9x, it is a
+function which calls the LWP function LWP_CreateProcess().  See the new
+files osithrd95.c, osithrd95.h, and osithrdnt.h in WINNT/client_osi.
+
+Configuration parameters
+------------------------
+
+In DJGPP, it is not feasible to access the system registry, which is
+where the NT client stores its configuration info.  For the Win9x client,
+the Unix approach is followed instead: the local cell is in a file called
+"ThisCell", cache configuration is in a file called "cache.info", and
+the cell database is stored in "CellServDB" instead of "afsdcell.ini".
+Many parameters are passed via the command line to afsd.exe and are
+processed just like the Unix clients.
+
+See the new files afsd_init95.c and afsd95.c in WINNT/afsd.
+
+Authentication
+--------------
+
+In the functions SetToken() and GetToken(), the NT client sends and
+receives the session key using a separate RPC which should use encryption,
+rather than including the session key in the pioctl packet.  The Win9x
+version avoids this RPC and puts the session key back into the pioctl.
+This should not be a security issue on Win9x since it is a single-user
+machine.  (The pioctl packet will not be visible externally.)  See files
+WINNT/afsd/cm_ioctl.c and auth/ktc_nt.c.
+
+Persistent (disk) caching
+-------------------------
+
+Disk caching support was added for the 9x client.  This has barely been
+tested and is still very experimental!  In addition, there are numerous
+performance issues.  It relies on the fact that LWP is a non-preemptive
+threads package, so no locking is done to protect shared data structures.
+In addition, it uses synchronous I/O to read and write disk files.  Since
+LWP is a user-level threads package, any calls to normal I/O system calls
+like read() or write() will block the entire process.  One better approach
+would be to add support for local disk file descriptors to the select()
+call used by IOMGR, and then to use IOMGR_Select to enqueue I/O requests
+to the disk.  Currently, the select() function supports only sockets.
+
+It should be fairly easy to adapt this code for the NT client.  See the
+implementation in WINNT/afsd/cm_diskcache95.c.  To enable this code,
+define DISKCACHE95 in WINNT/afsd/Makefile.djgpp.
+
+Utility programs
+----------------
+
+The utility programs, such as klog.exe and fs.exe, are Win32 programs and
+are built using the Microsoft compiler.  Changes to the code for these
+files are marked by "#ifdef AFS_WIN95_ENV".
+
+GUI interface
+-------------
+
+The Win9x client does not use the NT configuration GUI programs in
+client_creds and client_cpa (Control Panel Applet.)  It uses a separate
+GUI program called WinAfsLoad.exe in WINNT/win9xpanel.  This program can
+start afsd.exe and keep track of submounts and token expiration.
+
+The Explorer shell extension, which allows right clicking on a file
+in Windows Explorer to get an AFS submenu, is supported in Win9x.
+See WINNT/client_exp.
+
+Integrated logon
+----------------
+
+Integrated logon is not supported in the 9x client.
+
+Known issues
+------------
+
+1) The Microsoft linker LINK386.exe causes a deadlock when attempting to
+create an executable on an AFS filesystem.  Somehow, the linker appears
+to be preempting the entire machine so afsd.exe cannot run to service
+requests.  Solutions to this problem eagerly sought!  (This problem does
+not seem to occur with the Win9x Coda client.)
diff --git a/src/WINNT/afsd/Makefile.djgpp b/src/WINNT/afsd/Makefile.djgpp
new file mode 100644 (file)
index 0000000..6788573
--- /dev/null
@@ -0,0 +1,68 @@
+#
+# Makefile.djgpp
+# make information for this directory
+# requires gmake
+#
+
+SOURCES    = afsd95.c afsd_init95.c cm_access.c cm_aclent.c cm_buf.c \
+               cm_callback.c cm_cell.c cm_config.c cm_conn.c cm_daemon.c \
+               cm_dcache.c cm_dir.c cm_dnlc.c cm_ioctl.c cm_scache.c \
+               cm_server.c cm_user.c cm_utils.c cm_vnodeops.c cm_volume.c \
+               dosutils95.c largeint95.c netbios95.c smb.c smb_ioctl.c \
+               cm_diskcache95.c queue95.c afsmsg95.c smb3.c
+
+include ../../config/Makefile.djgpp.common
+
+# apply changes from common for this directory
+# 
+# no changes for this directory
+
+# what this directory builds
+#
+TARGETS = afsd.exe
+all : $(TARGETS)
+install : $(DESTBIN)/afsd.exe #$(DESTBIN)/klog.exe
+#CFLAGS += -I../vxd_lib
+#CFLAGS += -DAFS_VXD
+CFLAGS += -DDOS_PKT_WHOLE
+
+INCFILES = \
+        $(DESTINC)/netbios95.h \
+        $(DESTINC)/largeint95.h \
+        $(DESTINC)/dosdefs95.h \
+        $(DESTINC)/afs/afsmsg95.h
+
+# hard-wired dependency information
+#
+REQUIRED_LIBS = $(DESTLIB)/liblwp.a $(DESTLIB)/libosi.a \
+                $(DESTLIB)/afs/libcmd.a $(DESTLIB)/afs/libafsint.a \
+                $(DESTLIB)/afs/libvldb.a $(DESTLIB)/librxkad.a \
+                $(DESTLIB)/librx.a $(DESTLIB)/librxstat.a
+
+
+afsd.exe : $(ALL_OBJS) $(REQUIRED_LIBS)
+
+includes: $(INCFILES)
+
+EXECUTABLES = afsd afsd.exe
+
+$(DESTLIB)/liblwp.a :
+       $(MAKE) -C ../lwp install
+
+$(DESTLIB)/librx.a :
+       $(MAKE) -C ../rx install
+
+$(DESTLIB)/libosi.a :
+       $(MAKE) -C ../client_osi install
+
+$(DESTLIB)/libcmd.a :
+       $(MAKE) -C ../../cmd install
+
+$(DESTLIB)/libafsint.a :
+       $(MAKE) -C ../../fsint install
+
+$(DESTLIB)/librxkad.a :
+       $(MAKE) -C ../../rxkad install
+
+$(DESTLIB)/libvldb.a :
+       $(MAKE) -C ../../vlserver install
index 149b67f..96e05b9 100644 (file)
@@ -34,6 +34,7 @@ INCFILES =\
        $(INCFILEDIR)\smb3.h \
        $(INCFILEDIR)\smb_iocons.h \
        $(INCFILEDIR)\smb_ioctl.h \
+       $(INCFILEDIR)\afsmsg95.h \
        $(INCFILEDIR)\afsrpc.h
 
 IDLFILES =\
@@ -162,12 +163,26 @@ install: install_headers $(CONF_DLLFILE) \
        $(EXEDIR)\afsshare.exe \
        $(DESTDIR)\bin\kpasswd.exe
 
+install9X: install_headers $(CONF_DLLFILE) \
+       $(EXEDIR)\klog.exe \
+       $(EXEDIR)\tokens.exe \
+       $(EXEDIR)\unlog.exe $(EXEDIR)\afsd_service.exe \
+       $(EXEDIR)\fs.exe $(EXEDIR)\symlink.exe \
+       $(LOGON_DLLFILE) $(LOG95_DLLFILE) \
+       $(EXEDIR)\afsshare.exe \
+       $(DESTDIR)\bin\kpasswd.exe
+
+install_libutils: install_headers $(CONF_DLLFILE) \
+       $(EXEDIR)\klog.exe \
+       $(EXEDIR)\tokens.exe \
+       $(EXEDIR)\unlog.exe \
+       $(EXEDIR)\fs.exe $(EXEDIR)\symlink.exe \
+       $(EXEDIR)\afsshare.exe \
+       $(DESTDIR)\bin\kpasswd.exe
+
 ############################################################################
 # Local clean target; augments predefined clean target
 
-clean::
-       $(DEL) *.res
-
 ############################################################################
 # assorted exe's
 
@@ -305,3 +320,9 @@ afslogon.res: afslogon.rc AFS_component_version_number.h
 afslog95.res: afslog95.rc AFS_component_version_number.h
 
 libafsconf.res: libafsconf.rc AFS_component_version_number.h
+
+clean::
+       $(DEL) *.res
+       $(DEL) afsrpc.h
+       $(DEL) afsrpc_?.*
+       $(DEL) $(EXELIBS)
index 51b6dc2..0c6f59f 100644 (file)
 #ifndef __AFSD_H_ENV__
 #define __AFSD_H_ENV__ 1
 
+#include <afs/param.h>
+
+#ifndef DJGPP
 BOOL InitClass(HANDLE);
 BOOL InitInstance(HANDLE, int);
 
 LONG APIENTRY MainWndProc(HWND, unsigned int, unsigned int, long);
 BOOL APIENTRY About(HWND, unsigned int, unsigned int, long);
+#endif /* !DJGPP */
 
+#ifndef DJGPP
 #include <nb30.h>
+#else /* DJGPP */
+#include <sys/farptr.h>
+#include <go32.h>
+#include "dosdefs95.h"
+#include "largeint95.h"
+#endif /* !DJGPP */
+
 #include "afsdicon.h"
 
 #include "cm.h"
@@ -26,25 +38,31 @@ BOOL APIENTRY About(HWND, unsigned int, unsigned int, long);
 #include <crypt.h>
 #include <afs/prs_fs.h>
 
-#include "cm_access.h"
+#include <osi.h>
+#include "cm_user.h"
+#include "cm_callback.h"
+#ifdef DISKCACHE95
+#include "cm_diskcache95.h"
+#endif /* DISKCACHE95 */
+#include "cm_conn.h"
 #include "cm_aclent.h"
 #include "cm_cell.h"
 #include "cm_config.h"
 #include "cm_server.h"
-#include "cm_user.h"
-#include "cm_conn.h"
 #include "cm_volume.h"
-#include "cm_access.h"
 #include "cm_scache.h"
 #include "cm_dcache.h"
-#include "cm_buf.h"
-#include "cm_callback.h"
+#include "cm_access.h"
 #include "cm_vnodeops.h"
 #include "cm_dir.h"
 #include "cm_utils.h"
 #include "cm_daemon.h"
 #include "cm_ioctl.h"
 #include "cm_dnlc.h"
+#include "cm_buf.h"
+#ifdef DJGPP
+#include "afs/afsmsg95.h"
+#endif
 
 #include <afs/vldbint.h>
 #include <afs/afsint.h>
@@ -52,6 +70,8 @@ BOOL APIENTRY About(HWND, unsigned int, unsigned int, long);
 #define AFS_DAEMON_SERVICE_NAME "TransarcAFSDaemon"
 #define AFS_DAEMON_EVENT_NAME "AFS Client"
 
+void afs_exit();
+
 /* globals from the base afsd */
 
 extern int cm_logChunkSize;
diff --git a/src/WINNT/afsd/afsd95.c b/src/WINNT/afsd/afsd95.c
new file mode 100644 (file)
index 0000000..3aa6bc7
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#include <afs/param.h>
+#include <afs/stds.h>
+
+/*#include <windows.h>*/
+#include <string.h>
+/*#include <nb30.h>*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <osi.h>
+#include <signal.h>
+#include <afs/cmd.h>
+/*#include <winsock2.h>*/
+#include "afsd.h"
+#include "afsd_init.h"
+
+
+char main_statusText[100];
+osi_log_t *afsd_logp;
+
+extern int traceOnPanic;
+BOOL InitInstance(struct cmd_syndesc *as, char *arock);
+extern int afs_shutdown;
+int tried_shutdown=0;
+
+int afs_current_status = AFS_STATUS_INIT;
+
+/*
+ * Notifier function for use by osi_panic
+ */
+void afsd_notifier(char *msgp, char *filep, long line)
+{
+       char tbuffer[100];
+       if (filep)
+               sprintf(tbuffer, "Error at file %s, line %d", filep, line);
+       else
+               strcpy(tbuffer, "Error at unknown location");
+
+       if (!msgp)
+               msgp = "Assertion failure";
+
+       /*MessageBox(NULL, tbuffer, msgp, MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);*/
+
+       afsd_ForceTrace(TRUE);
+
+       if (traceOnPanic) {
+               /*asm("int 3");*/
+       }
+
+       afs_exit(AFS_EXITCODE_PANIC);
+}
+
+/* Init function called when window application starts.  Inits instance and
+ * application together, since in Win32 they're essentially the same.
+ *
+ * Function then goes into a loop handling user interface messages.  Most are
+ * used to handle redrawing the icon.
+ */
+int main(int argc, char *argv[])
+{
+    struct cmd_syndesc *ts;
+    
+    fprintf(stderr, "AFS Client for Windows 95.\n");
+    /*fprintf(stderr, "Use Ctrl-C to shut down client.\n\n\n");*/
+    ts = cmd_CreateSyntax((char *) 0, (int (*)()) InitInstance, (char *) 0, "start AFS");
+    cmd_AddParm(ts, "-lanadapt", CMD_SINGLE, CMD_OPTIONAL, "LAN adapter number");
+    cmd_AddParm(ts, "-threads", CMD_SINGLE, CMD_OPTIONAL, "Number of server threads");
+    cmd_AddParm(ts, "-rootvol", CMD_SINGLE, CMD_OPTIONAL, "name of AFS root volume");
+    cmd_AddParm(ts, "-stat", CMD_SINGLE, CMD_OPTIONAL, "number of stat entries");
+    cmd_AddParm(ts, "-memcache", CMD_FLAG, CMD_OPTIONAL, "use memory cache");
+    cmd_AddParm(ts, "-cachedir", CMD_SINGLE, CMD_OPTIONAL, "cache directory");
+    cmd_AddParm(ts, "-mountdir", CMD_SINGLE, CMD_OPTIONAL, "mount location");
+    cmd_AddParm(ts, "-daemons", CMD_SINGLE, CMD_OPTIONAL, "number of daemons to use");
+    cmd_AddParm(ts, "-nosettime", CMD_FLAG, CMD_OPTIONAL, "don't set the time");
+    cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, "display lots of information");
+    cmd_AddParm(ts, "-debug", CMD_FLAG, CMD_OPTIONAL, "display debug info");
+    cmd_AddParm(ts, "-chunksize", CMD_SINGLE, CMD_OPTIONAL, "log(2) of chunk size");
+    cmd_AddParm(ts, "-dcache", CMD_SINGLE, CMD_OPTIONAL, "number of dcache entries");
+    cmd_AddParm(ts, "-confdir", CMD_SINGLE, CMD_OPTIONAL, "configuration directory");
+    cmd_AddParm(ts, "-logfile", CMD_SINGLE, CMD_OPTIONAL, "Place to keep the CM log");
+    cmd_AddParm(ts, "-waitclose", CMD_FLAG, CMD_OPTIONAL, "make close calls synchronous");
+    cmd_AddParm(ts, "-shutdown", CMD_FLAG, CMD_OPTIONAL, "Shutdown all afs state");
+    cmd_AddParm(ts, "-sysname", CMD_SINGLE, CMD_OPTIONAL, "System name (@sys value)");
+    cmd_AddParm(ts, "-gateway", CMD_FLAG, CMD_OPTIONAL, "machine is a gateway");
+    cmd_AddParm(ts, "-tracebuf", CMD_SINGLE, CMD_OPTIONAL, "trace buffer size");
+    cmd_AddParm(ts, "-startup", CMD_FLAG, CMD_OPTIONAL, "start AFS client");
+    cmd_AddParm(ts, "-diskcache", CMD_SINGLE, CMD_OPTIONAL, "diskcache size");
+
+    return (cmd_Dispatch(argc, argv));
+}
+
+/* initialize the process.  Reads the init files to get the appropriate
+ * information. */
+void vxd_Shutdown(void);
+int afsd_shutdown(int);
+int shutdown_handler(int);
+
+BOOL InitInstance(struct cmd_syndesc *as, char *arock)
+{
+        long code;
+       char *reason;
+
+#ifdef DJGPP
+       osi_Init();
+#endif
+#ifndef DJGPP
+       osi_InitPanic(afsd_notifier);
+#endif
+
+        /*sleep(10);*/
+        
+       afsi_start();
+
+        code = afsMsg_Init();
+       if (code != 0)
+               osi_panic("socket failure", __FILE__, __LINE__);
+        
+        code = afsd_InitCM(&reason, as, arock);
+       if (code != 0)
+               osi_panic(reason, __FILE__, __LINE__);
+
+       code = afsd_InitDaemons(&reason);
+       if (code != 0)
+               osi_panic(reason, __FILE__, __LINE__);
+
+        code = afsd_InitSMB(&reason);
+       if (code != 0)
+               osi_panic(reason, __FILE__, __LINE__);
+
+        signal(SIGINT, shutdown_handler);
+
+        thrd_Yield();   /* give new threads a chance to run */
+        
+        /* send message to GUI caller indicating successful init */
+        afs_current_status = AFS_STATUS_RUNNING;
+        afsMsg_StatusChange(afs_current_status, 0, NULL);
+
+#ifdef DJGPP
+       /* Keep the process from just terminating */
+       while(afs_shutdown == 0)
+        {
+        /*IOMGR_Sleep(180);*/
+          IOMGR_Sleep(8);
+               /* workaround: WaitForKeystroke(nonzero num) calls 
+                  IOMGR_Select, though Win95 select works only on sockets */
+               /* so, we poll instead */
+               /*if (LWP_WaitForKeystroke(0))
+                  break;*/
+        }
+        afsd_shutdown(0);
+#endif
+        afs_exit(0);
+        
+       return (TRUE);
+}
+
+int shutdown_handler(int x)
+{
+  if (!tried_shutdown)
+  {
+    fprintf(stderr, "This program should not be shut down manually.  It should "
+           "be shut down by the\nWindows AFS Client Control Center.  Press Ctrl-C "
+            "again if you really want to do this.\n");
+    fflush(stderr);
+    tried_shutdown = 1;
+  }
+  else
+  {
+    fprintf(stderr, "Shutting down AFSD...\n");
+    fflush(stderr);
+    afs_shutdown = 1;
+  }
+}
+
+int afsd_shutdown(int x)
+{
+#ifdef AFS_VXD
+  vxd_Shutdown();
+#else
+  smb_Shutdown();
+#endif
+  
+  fprintf(stderr, "AFSD shutdown complete.\n");
+  /*exit(0);*/
+}
+
+void afs_exit(int exitCode)
+{
+  afs_current_status = AFS_STATUS_EXITING;
+  afsMsg_StatusChange(afs_current_status,
+                      exitCode, NULL);
+  afsMsg_Shutdown();
+  exit(exitCode);
+}
index 98ed195..803facc 100644 (file)
@@ -9,9 +9,14 @@
 
 void afsi_start();
 
+#ifndef DJGPP
 int afsd_InitCM(char **reasonP);
-int afsd_InitDaemons(char **reasonP);
 int afsd_InitSMB(char **reasonP, void *aMBfunc);
+#else /* DJGPP */
+int afsd_InitCM(char **reasonP, struct cmd_syndesc *as, char *arock);
+int afsd_InitSMB(char **reasonP);
+#endif /* !DJGPP */
+int afsd_InitDaemons(char **reasonP);
 
 void afsd_ForceTrace(BOOL flush);
 
diff --git a/src/WINNT/afsd/afsd_init95.c b/src/WINNT/afsd/afsd_init95.c
new file mode 100644 (file)
index 0000000..777b4c9
--- /dev/null
@@ -0,0 +1,746 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#include <afs/param.h>
+#include <afs/stds.h>
+#include <afs/afs_args.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <stdarg.h>
+
+#include <osi.h>
+#include "afsd.h"
+#include <rx/rx.h>
+#include <rx/rx_null.h>
+#include <afs/cmd.h>
+#include <netdb.h>
+#include "cm_rpc.h"
+
+#define AFSDIR_CLIENT_ETC_DIRPATH "c:/"
+#define AFSLOGFILE "afs.log"
+#define CACHEINFOFILE "cache.info"
+
+extern int RXAFSCB_ExecuteRequest();
+extern int RXSTATS_ExecuteRequest();
+
+osi_log_t *afsd_logp;
+
+char cm_rootVolumeName[64];
+DWORD cm_rootVolumeNameLen;
+cm_volume_t *cm_rootVolumep = NULL;
+cm_cell_t *cm_rootCellp = NULL;
+cm_fid_t cm_rootFid;
+cm_scache_t *cm_rootSCachep;
+char cm_mountRoot[1024];
+DWORD cm_mountRootLen;
+int cm_logChunkSize;
+int cm_chunkSize;
+int afs_diskCacheChunks;
+char cm_cachePath[128];
+int cm_diskCacheEnabled = 0;
+
+int smb_UseV3;
+
+int LANadapter;
+int lanAdaptSet = 0;
+int rootVolSet = 0;
+int cacheSetTime = TRUE;
+int afsd_verbose = 0;
+int chunkSize;
+
+int numBkgD;
+int numSvThreads;
+
+int traceOnPanic = 0;
+
+int logReady = 0;
+
+char cm_HostName[200];
+long cm_HostAddr;
+
+/*char cm_CachePath[200];*/
+/*DWORD cm_CachePathLen;*/
+char cm_CacheInfoPath[1024];
+int cacheBlocks;
+int sawCacheSize=0, sawDiskCacheSize=0, sawMountRoot=0;
+int sawCacheBaseDir=0;
+char cm_AFSLogFile[200];
+int afsd_CloseSynch = 0;
+int afs_shutdown = 0;
+char cm_confDir[200];
+
+BOOL isGateway = FALSE;
+BOOL reportSessionStartups = FALSE;
+
+int afsd_debug;
+cm_initparams_v1 cm_initParams;
+
+/*
+ * AFSD Initialization Log
+ *
+ * This is distinct from the regular debug logging facility.
+ * Log items go directly to a file, not to an array in memory, so that even
+ * if AFSD crashes, the log can be inspected.
+ */
+
+FILE *afsi_file;
+
+void
+afsi_start()
+{
+       char wd[100];
+       char t[100], u[100];
+       int zilch;
+       int code;
+        time_t now;
+        char *p;
+
+       afsi_file = NULL;
+       /*code = GetWindowsDirectory(wd, sizeof(wd));
+          if (code == 0) return;*/
+        strcpy (wd, "C:");
+       strcat(wd, "\\afsd_init.log");
+       /*GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, t, sizeof(t));*/
+        time (&now);
+        strcpy(t, asctime(localtime(&now)));
+        /*afsi_file = CreateFile(wd, GENERIC_WRITE, FILE_SHARE_READ, NULL,
+          CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);*/
+        /*afsi_file = open(wd, O_RDWR | O_CREAT | O_RSHARE);*/
+        afsi_file = fopen(wd, "wt");
+        setbuf(afsi_file, NULL);
+        
+       /*GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, u, sizeof(u));*/
+        time (&now);
+        strcpy(u, asctime(localtime(&now)));
+        p = strchr(u, '\n'); if (p) *p = 0;
+        p = strchr(u, '\r'); if (p) *p = 0;
+       strcat(t, ": Create log file\n");
+       strcat(u, ": Created log file\n");
+       /*WriteFile(afsi_file, t, strlen(t), &zilch, NULL);
+          WriteFile(afsi_file, u, strlen(u), &zilch, NULL);*/
+        /*write(afsi_file, t, strlen(t));
+          write(afsi_file, u, strlen(u));*/
+        fputs(t, afsi_file);
+        fputs(u, afsi_file);
+}
+
+void
+afsi_log(char *pattern, ...)
+{
+       char s[100], t[100], u[100];
+       int zilch;
+        time_t now;
+       va_list ap;
+#ifndef DEBUG
+        return;
+#endif
+       va_start(ap, pattern);
+
+       vsprintf(s, pattern, ap);
+       /*GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, t, sizeof(t));*/
+        time(&now);
+        strcpy(t, asctime(localtime(&now)));
+       sprintf(u, "%s: %s\n", t, s);
+       if (afsi_file != NULL)
+          /* fputs(u, stderr); */
+          fputs(u, afsi_file);
+          /*write(afsi_file, u, strlen(u));*/
+        /*WriteFile(afsi_file, u, strlen(u), &zilch, NULL);*/
+}
+
+/*
+ * Standard AFSD trace
+ */
+
+void afsd_ForceTrace(BOOL flush)
+{
+       FILE *handle;
+       int len;
+       char buf[100];
+
+       if (!logReady) return;
+
+       /*len = GetTempPath(99, buf);*/
+       /*strcpy(&buf[len], "/afsd.log");*/
+       strcpy(buf, "c:/afsd.log");
+       /*handle = CreateFile(buf, GENERIC_WRITE, FILE_SHARE_READ,
+          NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);*/
+        /*handle = open(buf, O_RDWR | O_CREAT | O_RSHARE);*/
+        handle = fopen(buf, "wt");
+       if (handle == NULL) {
+               logReady = 0;
+               osi_panic("Cannot create log file", __FILE__, __LINE__);
+       }
+       osi_LogPrint(afsd_logp, handle);
+       if (flush)
+          fflush(handle);
+        /*FlushFileBuffers(handle);*/
+       /*CloseHandle(handle);*/
+        fclose(handle);
+}
+
+/*------------------------------------------------------------------------------
+  * ParseCacheInfoFile
+  *
+  * Description:
+  *    Open the file containing the description of the workstation's AFS cache
+  *    and pull out its contents.  The format of this file is as follows:
+  *
+  *        cm_mountRoot:cacheBaseDir:cacheBlocks
+  *
+  * Arguments:
+  *    None.
+  *
+  * Returns:
+  *    0 if everything went well,
+  *    1 otherwise.
+  *
+  * Environment:
+  *    Nothing interesting.
+  *
+  *  Side Effects:
+  *    Sets globals.
+  *---------------------------------------------------------------------------*/
+
+int ParseCacheInfoFile()
+{
+    static char rn[]="ParseCacheInfoFile";     /*This routine's name*/
+    FILE *cachefd;                             /*Descriptor for cache info file*/
+    int        parseResult;                            /*Result of our fscanf()*/
+    int32 tCacheBlocks;
+    char tCacheBaseDir[1024], *tbd, tCacheMountDir[1024], *tmd;
+    /*char cacheBaseDir[1024];  /* cache in mem, this is ignored */
+
+    if (afsd_debug)
+       printf("%s: Opening cache info file '%s'...\n",
+           rn, cm_CacheInfoPath);
+
+    cachefd = fopen(cm_CacheInfoPath, "r");
+    if (!cachefd) {
+       printf("%s: Can't read cache info file '%s'\n",
+              rn, cm_CacheInfoPath);
+        return(1);
+    }
+
+    /*
+     * Parse the contents of the cache info file.  All chars up to the first
+     * colon are the AFS mount directory, all chars to the next colon are the
+     * full path name of the workstation cache directory and all remaining chars
+     * represent the number of blocks in the cache.
+     */
+    tCacheMountDir[0] = tCacheBaseDir[0] = '\0';
+    parseResult = fscanf(cachefd,
+                         "%1024[^;];%1024[^;];%d",
+                         tCacheMountDir, tCacheBaseDir, &tCacheBlocks);
+
+    /*
+     * Regardless of how the parse went, we close the cache info file.
+     */
+    fclose(cachefd);
+
+    if (parseResult == EOF || parseResult < 3) {
+       printf("%s: Format error in cache info file!\n",
+              rn);
+       if (parseResult == EOF)
+           printf("\tEOF encountered before any field parsed.\n");
+       else
+           printf("\t%d out of 3 fields successfully parsed.\n",
+                  parseResult);
+
+       printf("\tcm_mountRoot: '%s'\n\tcm_cachePath: '%s'\n\tcacheBlocks: %d\n",
+              cm_mountRoot, cm_cachePath, cacheBlocks);
+       return(1);
+    }
+
+    for (tmd = tCacheMountDir; *tmd == '\n' || *tmd == ' ' || *tmd == '\t'; tmd++) ;
+    for (tbd = tCacheBaseDir; *tbd == '\n' || *tbd == ' ' || *tbd == '\t'; tbd++) ;
+    /* now copy in the fields not explicitly overridden by cmd args */
+    if (!sawMountRoot) 
+    {
+       strcpy(cm_mountRoot, tmd);
+        cm_mountRootLen = strlen(tmd);
+    }
+    if (!sawCacheBaseDir)
+      strcpy(cm_cachePath, tbd);
+    if  (!sawCacheSize)
+       cacheBlocks = tCacheBlocks;
+
+    if (afsd_debug) {
+       printf("%s: Cache info file successfully parsed:\n",
+              rn);
+       printf("\tcm_mountRoot: '%s'\n\tcm_cachePath: '%s'\n\tcacheBlocks: %d\n",
+              tmd, tbd, tCacheBlocks);
+    }
+    /*printf("cm_cachePath: %s\n", cm_cachePath);*/
+
+    /*PartSizeOverflow(tbd, cacheBlocks);*/
+
+    return(0);
+}
+
+/*
+ * AFSD Initialization
+ */
+
+int afsd_InitCM(char **reasonP, struct cmd_syndesc *as, char *arock)
+{
+       osi_uid_t debugID;
+       long cacheBlocks;
+       long cacheSize;
+       long logChunkSize;
+       long stats;
+       long traceBufSize;
+       long ltt, ltto;
+       char rootCellName[256];
+       struct rx_service *serverp;
+       static struct rx_securityClass *nullServerSecurityClassp;
+       struct hostent *thp;
+       char *msgBuf;
+       char buf[200];
+       DWORD dummyLen;
+       long code;
+        struct cmd_syndesc *ts;
+        char *afsconf_path;
+        long diskCacheSize;
+       /*WSADATA WSAjunk;
+
+          WSAStartup(0x0101, &WSAjunk);*/
+
+#ifndef DJGPP
+       /* setup osidebug server at RPC slot 1000 */
+       osi_LongToUID(1000, &debugID);
+       code = osi_InitDebug(&debugID);
+       afsi_log("osi_InitDebug code %d", code);
+//     osi_LockTypeSetDefault("stat"); /* comment this out for speed *
+       if (code != 0) {
+               *reasonP = "unknown error";
+               return -1;
+       }
+#endif 
+
+       /* who are we ? */
+       gethostname(cm_HostName, sizeof(cm_HostName));
+#ifdef DJGPP
+       /* For some reason, we may be getting space-padded hostnames.
+          If so, we take out the padding so that we can append -AFS later. */
+       {
+         char *space = strchr(cm_HostName,' ');
+         if (space) *space = '\0';
+       }
+#endif
+       afsi_log("gethostname %s", cm_HostName);
+       thp = gethostbyname(cm_HostName);
+       memcpy(&cm_HostAddr, thp->h_addr_list[0], 4);
+
+       /* seed random number generator */
+       srand(ntohl(cm_HostAddr));
+
+       /* Get configuration parameters from command line */
+
+        /* call atoi on the appropriate parsed results */
+
+        if (!as->parms[20].items) {
+          /* -startup */
+          fprintf(stderr, "Please do not run this program directly.  Use the AFS Client Windows loader\nto start AFS.\n");
+          exit(1);
+        }
+
+        if (as->parms[0].items) {
+          /* -lanadapt */
+          LANadapter = atoi(as->parms[0].items->data);
+          lanAdaptSet = 1;
+          afsi_log("LAN adapter number %d", LANadapter);
+        }
+        else
+        {
+          LANadapter = 0;
+          afsi_log("Default LAN adapter number 0");
+        }
+        
+        if (as->parms[1].items) {
+          /* -threads */
+          numSvThreads = atoi(as->parms[1].items->data);
+          afsi_log("%d server threads", numSvThreads);
+        }
+        else
+        {
+          numSvThreads = CM_CONFIGDEFAULT_SVTHREADS;
+          afsi_log("Defaulting to %d server threads", numSvThreads);
+        }
+        
+        if (as->parms[2].items) {
+          /* -rootvol */
+          strcpy(cm_rootVolumeName, as->parms[2].items->data);
+          rootVolSet = 1;
+          afsi_log("Root volume %s", cm_rootVolumeName);
+        }
+        else
+        {
+          strcpy(cm_rootVolumeName, "root.afs");
+          afsi_log("Default root volume name root.afs");
+        }
+        
+        if (as->parms[3].items) {
+          /* -stat */
+          stats = atoi(as->parms[3].items->data);
+          afsi_log("Status cache size %d", stats);
+        }
+        else
+        {
+          stats = CM_CONFIGDEFAULT_STATS;
+          afsi_log("Default status cache size %d", stats);
+        }
+        
+        if (as->parms[4].items) {
+          /* -memcache */
+          /* no-op */
+        }
+        
+        if (as->parms[5].items) {
+          /* -cachedir */
+          /* no-op; cache is in memory, not mapped file */
+          strcpy(cm_cachePath, as->parms[5].items->data);
+          sawCacheBaseDir = 1;
+        }
+        
+        if (as->parms[6].items) {
+          /* -mountdir */
+          strcpy(cm_mountRoot, as->parms[6].items->data);
+          cm_mountRootLen = strlen(cm_mountRoot);
+          sawMountRoot = 1;
+          afsi_log("Mount root %s", cm_mountRoot);
+        }
+        else
+        {
+          strcpy(cm_mountRoot, "/afs");
+          cm_mountRootLen = 4;
+          /* Don't log */
+        }
+        
+        if (as->parms[7].items) {
+          /* -daemons */
+          numBkgD = atoi(as->parms[7].items->data);
+          afsi_log("%d background daemons", numBkgD);
+        }
+        else
+        {
+          numBkgD = CM_CONFIGDEFAULT_DAEMONS;
+          afsi_log("Defaulting to %d background daemons", numBkgD);
+        }
+        
+        if (as->parms[8].items) {
+          /* -nosettime */
+          cacheSetTime = FALSE;
+        }
+        
+        if (as->parms[9].items) {
+          /* -verbose */
+          afsd_verbose = 1;
+        }
+        
+        if (as->parms[10].items) {
+          /* -debug */
+          afsd_debug = 1;
+          afsd_verbose = 1;
+        }
+        
+        if (as->parms[11].items) {
+          /* -chunksize */
+          chunkSize = atoi(as->parms[11].items->data);
+          if (chunkSize < 12 || chunkSize > 30) {
+            afsi_log("Invalid chunk size %d, using default",
+                     logChunkSize);
+           logChunkSize = CM_CONFIGDEFAULT_CHUNKSIZE;
+          }
+        } else {
+          logChunkSize = CM_CONFIGDEFAULT_CHUNKSIZE;
+          afsi_log("Default chunk size %d", logChunkSize);
+        }
+        cm_logChunkSize = logChunkSize;
+        cm_chunkSize = 1 << logChunkSize;
+        
+        if (as->parms[12].items) {
+          /* -dcache */
+          cacheSize = atoi(as->parms[12].items->data);
+          afsi_log("Cache size %d", cacheSize);
+          sawCacheSize = 1;
+        }
+        else
+        {
+          cacheSize = CM_CONFIGDEFAULT_CACHESIZE;
+          afsi_log("Default cache size %d", cacheSize);
+        }
+        
+        afsconf_path = getenv("AFSCONF");
+        if (!afsconf_path)
+          strcpy(cm_confDir, AFSDIR_CLIENT_ETC_DIRPATH);
+        else
+          strcpy(cm_confDir, afsconf_path);
+        if (as->parms[13].items) {
+          /* -confdir */
+          strcpy(cm_confDir, as->parms[13].items->data);
+        }
+
+        sprintf(cm_CacheInfoPath,  "%s/%s", cm_confDir, CACHEINFOFILE);
+
+        sprintf(cm_AFSLogFile,  "%s/%s", cm_confDir, AFSLOGFILE);
+        if (as->parms[14].items) {
+          /* -logfile */
+          strcpy(cm_AFSLogFile, as->parms[14].items->data);
+        }
+
+        if (as->parms[15].items) {
+          /* -waitclose */
+          afsd_CloseSynch = 1;
+        }
+
+        if (as->parms[16].items) {
+          /* -shutdown */
+          afs_shutdown = 1;
+          /* 
+           * Cold shutdown is the default
+           */
+          printf("afsd: Shutting down all afs processes and afs state\n");
+          /*call_syscall(AFSOP_SHUTDOWN, 1);*/
+          exit(0);
+        }
+
+        if (as->parms[17].items) {
+          /* -sysname */
+          strcpy(cm_sysName, as->parms[17].items->data);
+        }
+        else
+          strcpy(cm_sysName, "i386_win95");
+        
+        if (as->parms[18].items) {
+          /* -gateway */
+          isGateway = 1;
+          afsi_log("Set for %s service",
+                   isGateway ? "gateway" : "stand-alone");
+        }
+        else
+          isGateway = 0;
+
+        if (as->parms[19].items) {
+          /* -tracebuf */
+          traceBufSize = atoi(as->parms[19].items->data);
+          afsi_log("Trace Buffer size %d", traceBufSize);
+        }
+        else
+        {
+          traceBufSize = CM_CONFIGDEFAULT_TRACEBUFSIZE;
+          afsi_log("Default trace buffer size %d", traceBufSize);
+       }
+        
+        if (as->parms[21].items) {
+          /* -diskcache */
+          diskCacheSize = atoi(as->parms[21].items->data);
+          cm_diskCacheEnabled = 1;
+          afsi_log("Disk cache size %d K", diskCacheSize);
+          /*printf("Disk cache size %d K", diskCacheSize);*/
+          sawDiskCacheSize = 1;
+        }
+        else
+        {
+          diskCacheSize = 50000; /*CM_CONFIGDEFAULT_DISKCACHESIZE;*/
+          afsi_log("Default disk cache size %d", diskCacheSize);
+        }
+
+        if (ParseCacheInfoFile()) {
+          exit(1);
+        }
+
+       /* setup early variables */
+       /* These both used to be configurable. */
+       smb_UseV3 = 1;
+        buf_bufferSize = CM_CONFIGDEFAULT_BLOCKSIZE;
+
+       /* turn from 1024 byte units into memory blocks */
+        cacheBlocks = (cacheSize * 1024) / buf_bufferSize;
+        afs_diskCacheChunks = (diskCacheSize * 1024) / buf_bufferSize;
+        /*printf("afs_diskCacheChunks=%d\n", afs_diskCacheChunks);*/
+
+        /*
+         * Save client configuration for GetCacheConfig requests
+         */
+        cm_initParams.nChunkFiles = 0;
+        cm_initParams.nStatCaches = stats;
+        cm_initParams.nDataCaches = 0;
+        cm_initParams.nVolumeCaches = 0;
+        cm_initParams.firstChunkSize = cm_chunkSize;
+        cm_initParams.otherChunkSize = cm_chunkSize;
+        cm_initParams.cacheSize = cacheSize;
+        cm_initParams.setTime = 0;
+        cm_initParams.memCache = 0;
+        
+       /* setup and enable debug log */
+       afsd_logp = osi_LogCreate("afsd", traceBufSize);
+       afsi_log("osi_LogCreate log addr %x", afsd_logp);
+        osi_LogEnable(afsd_logp);
+       logReady = 1;
+
+#if 0
+       /* get network related info */
+       cm_noIPAddr = CM_MAXINTERFACE_ADDR;
+       code = syscfg_GetIFInfo(&cm_noIPAddr,
+                               cm_IPAddr, cm_SubnetMask,
+                               cm_NetMtu, cm_NetFlags);
+
+       if ( (cm_noIPAddr <= 0) || (code <= 0 ) )
+           afsi_log("syscfg_GetIFInfo error code %d", code);
+       else
+           afsi_log("First Network address %x SubnetMask %x",
+                    cm_IPAddr[0], cm_SubnetMask[0]);
+#endif
+
+       /* initialize RX, and tell it to listen to port 7001, which is used for
+         * callback RPC messages.
+         */
+       code = rx_Init(htons(7001));
+       afsi_log("rx_Init code %x", code);
+       if (code != 0) {
+               *reasonP = "afsd: failed to init rx client on port 7001";
+               return -1;
+       }
+
+       /* Initialize the RPC server for session keys */
+       /*RpcInit();*/
+
+       /* create an unauthenticated service #1 for callbacks */
+       nullServerSecurityClassp = rxnull_NewServerSecurityObject();
+        serverp = rx_NewService(0, 1, "AFS", &nullServerSecurityClassp, 1,
+               RXAFSCB_ExecuteRequest);
+       afsi_log("rx_NewService addr %x", serverp);
+       if (serverp == NULL) {
+               *reasonP = "unknown error";
+               return -1;
+       }
+
+        nullServerSecurityClassp = rxnull_NewServerSecurityObject();
+        serverp = rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats",
+                &nullServerSecurityClassp, 1, RXSTATS_ExecuteRequest);
+        afsi_log("rx_NewService addr %x", serverp);
+        if (serverp == NULL) {
+                *reasonP = "unknown error";
+                return -1;
+        }
+        
+        /* start server threads, *not* donating this one to the pool */
+        rx_StartServer(0);
+       afsi_log("rx_StartServer");
+
+       /* init user daemon, and other packages */
+       cm_InitUser();
+
+       cm_InitACLCache(2*stats);
+
+       cm_InitConn();
+
+        cm_InitCell();
+        
+        cm_InitServer();
+        
+        cm_InitVolume();
+        
+        cm_InitIoctl();
+        
+        smb_InitIoctl();
+        
+        cm_InitCallback();
+        
+        cm_InitSCache(stats);
+        
+        code = cm_InitDCache(0, cacheBlocks);
+
+       afsi_log("cm_InitDCache code %x", code);
+       if (code != 0) {
+               *reasonP = "error initializing cache";
+               return -1;
+       }
+
+       code = cm_GetRootCellName(rootCellName);
+       afsi_log("cm_GetRootCellName code %d rcn %s", code,
+                (code ? "<none>" : rootCellName));
+       if (code != 0) {
+               *reasonP = "can't find root cell name in ThisCell";
+               return -1;
+       }
+
+       cm_rootCellp = cm_GetCell(rootCellName, CM_FLAG_CREATE);
+       afsi_log("cm_GetCell addr %x", cm_rootCellp);
+       if (cm_rootCellp == NULL) {
+               *reasonP = "can't find root cell in CellServDB";
+               return -1;
+       }
+
+       return 0;
+}
+
+int afsd_InitDaemons(char **reasonP)
+{
+       long code;
+       cm_req_t req;
+
+       cm_InitReq(&req);
+
+       /* this should really be in an init daemon from here on down */
+
+       code = cm_GetVolumeByName(cm_rootCellp, cm_rootVolumeName, cm_rootUserp,                &req, CM_FLAG_CREATE, &cm_rootVolumep);
+       afsi_log("cm_GetVolumeByName code %x root vol %x", code,
+                (code ? 0xffffffff : cm_rootVolumep));
+       if (code != 0) {
+               *reasonP = "can't find root volume in root cell";
+               return -1;
+        }
+
+        /* compute the root fid */
+       cm_rootFid.cell = cm_rootCellp->cellID;
+        cm_rootFid.volume = cm_GetROVolumeID(cm_rootVolumep);
+        cm_rootFid.vnode = 1;
+        cm_rootFid.unique = 1;
+        
+        code = cm_GetSCache(&cm_rootFid, &cm_rootSCachep, cm_rootUserp, &req);
+       afsi_log("cm_GetSCache code %x scache %x", code,
+                (code ? 0xffffffff : cm_rootSCachep));
+       if (code != 0) {
+               *reasonP = "unknown error";
+               return -1;
+       }
+
+       cm_InitDaemon(numBkgD);
+       afsi_log("cm_InitDaemon");
+
+       return 0;
+}
+
+int afsd_InitSMB(char **reasonP)
+{
+       char hostName[200];
+       char *ctemp;
+
+       /* Do this last so that we don't handle requests before init is done.
+         * Here we initialize the SMB listener.
+         */
+       strcpy(hostName, cm_HostName);
+        ctemp = strchr(hostName, '.'); /* turn ntdfs.* into ntdfs */
+        if (ctemp) *ctemp = 0;
+        hostName[11] = 0;      /* ensure that even after adding the -A, we
+                                * leave one byte free for the netbios server
+                                * type.
+                                 */
+        strcat(hostName, "-AFS");
+        strupr(hostName);
+       smb_Init(afsd_logp, hostName, smb_UseV3, LANadapter, numSvThreads);
+       afsi_log("smb_Init");
+
+       return 0;
+}
diff --git a/src/WINNT/afsd/afsmsg95.c b/src/WINNT/afsd/afsmsg95.c
new file mode 100644 (file)
index 0000000..5abec8c
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+/* This file contains functions used by the Windows 95 (DJGPP) AFS client
+   to communicate with the startup executable. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "afs/afsmsg95.h"
+
+int sock;
+struct sockaddr_in addr;
+extern int errno;
+
+int afsMsg_Init()
+{
+  int rc;
+  struct sockaddr_in myaddr;
+  
+  sock = socket(AF_INET, SOCK_DGRAM, 0);
+  if (sock < 0)
+    return -1;
+
+  addr.sin_addr.s_addr = htonl(0x7f000001);  /* 127.0.0.1 */
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons(AFS_MSG_PORT);
+
+  myaddr.sin_addr.s_addr = INADDR_ANY;
+  myaddr.sin_family = AF_INET;
+  myaddr.sin_port = 0;
+
+  rc = bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr));
+#ifdef DEBUG
+  fprintf(stderr, "afsMsg_Init: bind sock %d rc=%d\n", sock, rc);
+#endif
+  
+  return 0;
+}
+
+int afsMsg_StatusChange(int status, int exitCode, char *string)
+{
+  afsMsg_statChange_t *msgP;
+  int rc;
+  int slen = 0;
+  char msgBuf[AFS_MAX_MSG_LEN];
+  int now;
+
+  msgP = (afsMsg_statChange_t *) msgBuf;
+  
+  msgP->hdr.msgtype = AFS_MSG_STATUS_CHANGE;
+  
+  msgP->newStatus = status;
+  msgP->exitCode = exitCode;
+
+  if (string)
+  {
+    slen = strlen(string);  /* one extra for NULL */
+    if (slen > AFS_MAX_MSG_LEN - sizeof(afsMsg_statChange_t))
+      slen = AFS_MAX_MSG_LEN - sizeof(afsMsg_statChange_t);
+    strncpy(&msgP->message, string, slen);
+  }
+
+  msgP->hdr.length = sizeof(afsMsg_statChange_t) + slen;
+
+  rc = sendto(sock, msgP, msgP->hdr.length, 0, (struct sockaddr *) &addr,
+              sizeof(addr));
+  /*rc = send(sock, &msg, msg.hdr.length, 0);*/
+  time(&now);
+#ifdef DEBUG
+  fprintf(stderr, "%s: sent status change %d to sock %d length %d size=%d errno=%d\n",
+         asctime(localtime(&now)), status,
+         sock, msgP->hdr.length, rc, (rc < 0 ? errno:0));
+#endif
+  fflush(stdout);
+
+  return rc;
+}
+
+int afsMsg_Print(char *str, int level)
+{
+  afsMsg_print_t *msgP;
+  int rc;
+  char msgBuf[AFS_MAX_MSG_LEN];
+  int slen;
+
+  slen = strlen(str);  /* one extra for NULL */
+  if (slen > AFS_MAX_MSG_LEN - sizeof(afsMsg_statChange_t))
+    slen = AFS_MAX_MSG_LEN - sizeof(afsMsg_statChange_t);
+  strncpy(&msgP->message, str, slen);
+
+  msgP->hdr.msgtype = AFS_MSG_PRINT;
+  msgP->hdr.length = sizeof(afsMsg_hdr_t) + slen;
+  msgP->debugLevel = level;
+  strcpy(&msgP->message, str);
+  
+  rc = sendto(sock, msgP, msgP->hdr.length, 0, (struct sockaddr *) &addr,
+              sizeof(addr));
+  return rc;
+}
+
+int afsMsg_Shutdown()
+{
+  int rc;
+  rc = close(sock);
+  if (rc < 0) fprintf(stderr, "error closing socket, rc=%d\n", rc);
+#ifdef DEBUG
+  else fprintf(stderr, "socket closed\n");
+#endif
+  fflush(stderr);
+}
diff --git a/src/WINNT/afsd/afsmsg95.h b/src/WINNT/afsd/afsmsg95.h
new file mode 100644 (file)
index 0000000..57f1493
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _AFSMSG_H
+#define _AFSMSG_H
+
+#define AFS_MSG_PORT 2020
+
+#define AFS_MAX_MSG_LEN 512
+
+typedef struct _afsMsg_hdr {
+  int msgtype;
+  int length;
+} afsMsg_hdr_t;
+
+#define AFS_MSG_STATUS_CHANGE 1
+#define AFS_MSG_PRINT 2
+
+typedef struct _afsMsg_statChange {
+  afsMsg_hdr_t hdr;
+  int oldStatus;
+  int newStatus;
+  int exitCode;
+  char message;
+} afsMsg_statChange_t;
+
+#define AFS_STATUS_NOSTATUS -1
+#define AFS_STATUS_INIT    1
+#define AFS_STATUS_RUNNING 2
+#define AFS_STATUS_EXITING 3
+
+#define AFS_EXITCODE_NORMAL 0
+#define AFS_EXITCODE_PANIC  2
+#define AFS_EXITCODE_NETWORK_FAILURE 3
+#define AFS_EXITCODE_GENERAL_FAILURE 100
+
+typedef struct _afsMsg_print {
+  afsMsg_hdr_t hdr;
+  int debugLevel;
+  char message;
+} afsMsg_print_t;
+
+#endif
diff --git a/src/WINNT/afsd/afsrpc95.h b/src/WINNT/afsd/afsrpc95.h
new file mode 100644 (file)
index 0000000..a763f57
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef AFSRPC_H
+#define AFSRPC_H
+
+/* Copied from declaration of GUID in RPCDCE.H */
+typedef struct afs_uuid {
+        unsigned long Data1;
+        unsigned short Data2;
+        unsigned short Data3;
+        unsigned char Data4[8];
+} afs_uuid_t;
+
+long AFSRPC_SetToken(
+        afs_uuid_t      uuid,
+        unsigned char   sessionKey[8]
+);
+
+long AFSRPC_GetToken(
+        afs_uuid_t      uuid,
+        unsigned char   sessionKey[8]
+);
+
+#endif
index 8d2043b..fbf6af6 100644 (file)
 #define __CM_H_ENV__ 1
 
 #include <rx/rx.h>
+#ifdef DJGPP      /* we need these for vldbentry decl., etc. */
+#include <afs/vldbint.h>
+#include <afs/afsint.h>
+#endif /* DJGPP */
 
 /* from .xg file */
 long VL_GetEntryByID(struct rx_connection *, long, long, struct vldbentry *);
@@ -41,36 +45,36 @@ extern RXAFS_FetchStatus (struct rx_connection *,
        struct AFSCallBack *CallBack, 
        struct AFSVolSync *Sync);
 
-StartRXAFS_StoreData (struct rx_call *,
+int StartRXAFS_StoreData (struct rx_call *,
        struct AFSFid *Fid, 
        struct AFSStoreStatus *InStatus, 
        afs_int32 Pos, 
        afs_int32 Length, 
        afs_int32 FileLength);
 
-EndRXAFS_StoreData(struct rx_call *,
+int EndRXAFS_StoreData(struct rx_call *,
        struct AFSFetchStatus *OutStatus, 
        struct AFSVolSync *Sync);
 
-RXAFS_StoreACL (struct rx_connection *,
+int RXAFS_StoreACL (struct rx_connection *,
        struct AFSFid *Fid, 
        struct AFSOpaque *AccessList,  
        struct AFSFetchStatus *OutStatus, 
        struct AFSVolSync *Sync);
 
-RXAFS_StoreStatus(struct rx_connection *,
+int RXAFS_StoreStatus(struct rx_connection *,
        struct AFSFid *Fid, 
        struct AFSStoreStatus *InStatus, 
        struct AFSFetchStatus *OutStatus, 
        struct AFSVolSync *Sync);
 
-RXAFS_RemoveFile (struct rx_connection *,
+int RXAFS_RemoveFile (struct rx_connection *,
        struct AFSFid *DirFid, 
        char *namep,
        struct AFSFetchStatus *OutStatus, 
        struct AFSVolSync *Sync);
 
-RXAFS_CreateFile (struct rx_connection *,
+int RXAFS_CreateFile (struct rx_connection *,
        struct AFSFid *DirFid, 
        char *Name,
        struct AFSStoreStatus *InStatus, 
@@ -80,7 +84,7 @@ RXAFS_CreateFile (struct rx_connection *,
        struct AFSCallBack *CallBack, 
        struct AFSVolSync *Sync);
 
-RXAFS_Rename (struct rx_connection *,
+int RXAFS_Rename (struct rx_connection *,
        struct AFSFid *OldDirFid, 
        char *OldName,
        struct AFSFid *NewDirFid, 
@@ -89,7 +93,7 @@ RXAFS_Rename (struct rx_connection *,
        struct AFSFetchStatus *OutNewDirStatus, 
        struct AFSVolSync *Sync);
 
-RXAFS_Symlink (struct rx_connection *,
+int RXAFS_Symlink (struct rx_connection *,
        struct AFSFid *DirFid, 
        char *name,
        char *LinkContents,
@@ -99,7 +103,7 @@ RXAFS_Symlink (struct rx_connection *,
        struct AFSFetchStatus *OutDirStatus, 
        struct AFSVolSync *Sync);
 
-RXAFS_Link (struct rx_connection *,
+int RXAFS_Link (struct rx_connection *,
        struct AFSFid *DirFid, 
        char *Name,
        struct AFSFid *ExistingFid, 
@@ -107,7 +111,7 @@ RXAFS_Link (struct rx_connection *,
        struct AFSFetchStatus *OutDirStatus, 
        struct AFSVolSync *Sync);
 
-RXAFS_MakeDir (struct rx_connection *,
+int RXAFS_MakeDir (struct rx_connection *,
        struct AFSFid *DirFid, 
        char *name,
        struct AFSStoreStatus *InStatus, 
@@ -117,69 +121,69 @@ RXAFS_MakeDir (struct rx_connection *,
        struct AFSCallBack *CallBack, 
        struct AFSVolSync *Sync);
 
-RXAFS_RemoveDir (struct rx_connection *,
+int RXAFS_RemoveDir (struct rx_connection *,
        struct AFSFid *DirFid, 
        char *Name,
        struct AFSFetchStatus *OutDirStatus, 
        struct AFSVolSync *Sync);
 
-RXAFS_GetStatistics (struct rx_connection *,
+int RXAFS_GetStatistics (struct rx_connection *,
        struct ViceStatistics *Statistics);
 
-RXAFS_GiveUpCallBacks (struct rx_connection *,
+int RXAFS_GiveUpCallBacks (struct rx_connection *,
        struct AFSCBFids *Fids_Array,
        struct AFSCBs *CallBacks_Array);
 
-RXAFS_GetVolumeInfo (struct rx_connection *,
+int RXAFS_GetVolumeInfo (struct rx_connection *,
        char *VolumeName,
        struct VolumeInfo *Volumeinfo);
 
-RXAFS_GetVolumeStatus (struct rx_connection *,
+int RXAFS_GetVolumeStatus (struct rx_connection *,
        afs_int32 Volumeid, 
        struct AFSFetchVolumeStatus *Volumestatus, 
        char **name,
         char **offlineMsg,
         char **motd);
 
-RXAFS_SetVolumeStatus (struct rx_connection *,
+int RXAFS_SetVolumeStatus (struct rx_connection *,
        afs_int32 Volumeid, 
        struct AFSStoreVolumeStatus *Volumestatus,
        char *name,
        char *olm,
        char *motd);
 
-RXAFS_GetRootVolume (struct rx_connection *,
+int RXAFS_GetRootVolume (struct rx_connection *,
        char **VolumeName);
 
-RXAFS_CheckToken (struct rx_connection *,
+int RXAFS_CheckToken (struct rx_connection *,
        afs_int32 ViceId,
        struct AFSOpaque *token);
 
-RXAFS_GetTime (struct rx_connection *,
+int RXAFS_GetTime (struct rx_connection *,
        afs_uint32 *Seconds, 
        afs_uint32 *USeconds);
 
-RXAFS_BulkStatus (struct rx_connection *,
+int RXAFS_BulkStatus (struct rx_connection *,
        struct AFSCBFids *FidsArray,
        struct AFSBulkStats *StatArray,
        struct AFSCBs *CBArray,
        struct AFSVolSync *Sync);
 
-RXAFS_SetLock (struct rx_connection *,
+int RXAFS_SetLock (struct rx_connection *,
        struct AFSFid *Fid, 
        int Type, 
        struct AFSVolSync *Sync);
 
-RXAFS_ExtendLock (struct rx_connection *,
+int RXAFS_ExtendLock (struct rx_connection *,
        struct AFSFid *Fid, 
        struct AFSVolSync *Sync);
 
-RXAFS_ReleaseLock (struct rx_connection *,
+int RXAFS_ReleaseLock (struct rx_connection *,
        struct AFSFid *Fid, 
        struct AFSVolSync *Sync);
 
 /* This interface is to supported the AFS/DFS Protocol Translator */
-RXAFS_Lookup (struct rx_connection *,
+int RXAFS_Lookup (struct rx_connection *,
        struct AFSFid *DirFid,
        char *Name,
        struct AFSFid *OutFid,
@@ -240,5 +244,6 @@ RXAFS_Lookup (struct rx_connection *,
 #define CM_ERROR_NOIPC                 (CM_ERROR_BASE+36)
 #define CM_ERROR_BADNTFILENAME         (CM_ERROR_BASE+37)
 #define CM_ERROR_BUFFERTOOSMALL                (CM_ERROR_BASE+38)
+#define CM_ERROR_RENAME_IDENTICAL      (CM_ERROR_BASE+39)
 
 #endif /*  __CM_H_ENV__ */
index 5d69e70..9b6e1e3 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
 #include <winsock2.h>
+#endif
 #include <malloc.h>
 #include <string.h>
 #include <stdlib.h>
+#ifndef DJGPP
 #include <nb30.h>
+#endif
 #include <osi.h>
 
 #include "afsd.h"
index f7d1c7f..7e5933e 100644 (file)
@@ -10,6 +10,8 @@
 #ifndef _CM_ACCESS_H_ENV__
 #define _CM_ACCESS_H_ENV__ 1
 
+#include "cm_user.h"
+
 extern int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *up,
        long rights, long *outRights);
 
index 54096b6..c043375 100644 (file)
@@ -10,7 +10,9 @@
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
+#endif
 #include <stdlib.h>
 #include <string.h>
 #include <malloc.h>
index 22ad75d..b4790d9 100644 (file)
@@ -12,7 +12,9 @@
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
+#endif
 #include <osi.h>
 #include <malloc.h>
 #include <stdio.h>
@@ -74,11 +76,13 @@ long buf_nOrigBuffers;
 long buf_bufferSize = CM_BUF_SIZE;
 long buf_hashSize = CM_BUF_HASHSIZE;
 
+#ifndef DJGPP
 static
 HANDLE CacheHandle;
 
 static
 SYSTEM_INFO sysInfo;
+#endif /* !DJGPP */
 
 /* buffer reservation variables */
 long buf_reservedBufs;
@@ -94,6 +98,14 @@ cm_buf_t **buf_hashTablepp;
 /* another hash table */
 cm_buf_t **buf_fileHashTablepp;
 
+#ifdef DISKCACHE95
+/* for experimental disk caching support in Win95 client */
+cm_buf_t *buf_diskFreeListp;
+cm_buf_t *buf_diskFreeListEndp;
+cm_buf_t *buf_diskAllp;
+extern int cm_diskCacheEnabled;
+#endif /* DISKCACHE95 */
+
 /* hold a reference to an already held buffer */
 void buf_Hold(cm_buf_t *bp)
 {
@@ -116,8 +128,12 @@ void buf_IncrSyncer(long parm)
         lock_ReleaseWrite(&buf_globalLock);
         nAtOnce = buf_nbuffers / 10;
        while (1) {
-               i = SleepEx(5000, 1);
+#ifndef DJGPP
+                i = SleepEx(5000, 1);
                 if (i != 0) continue;
+#else
+               thrd_Sleep(5000);
+#endif /* DJGPP */
                 
                 /* now go through our percentage of the buffers */
                 for(i=0; i<nAtOnce; i++) {
@@ -147,6 +163,7 @@ void buf_IncrSyncer(long parm)
         }              /* whole daemon's while loop */
 }
 
+#ifndef DJGPP
 /* Create a security attribute structure suitable for use when the cache file
  * is created.  What we mainly want is that only the administrator should be
  * able to do anything with the file.  We create an ACL with only one entry,
@@ -192,7 +209,9 @@ PSECURITY_ATTRIBUTES CreateCacheFileSA()
 
        return psa;
 }
+#endif /* !DJGPP */
 
+#ifndef DJGPP
 /* Free a security attribute structure created by CreateCacheFileSA() */
 VOID FreeCacheFileSA(PSECURITY_ATTRIBUTES psa)
 {
@@ -204,6 +223,7 @@ VOID FreeCacheFileSA(PSECURITY_ATTRIBUTES psa)
        GlobalFree(psa->lpSecurityDescriptor);
        GlobalFree(psa);
 }
+#endif /* !DJGPP */
        
 /* initialize the buffer package; called with no locks
  * held during the initialization phase.
@@ -213,16 +233,20 @@ long buf_Init(cm_buf_ops_t *opsp)
        static osi_once_t once;
         cm_buf_t *bp;
         long sectorSize;
-        HANDLE phandle;
+        thread_t phandle;
+#ifndef DJGPP
+       HANDLE hf, hm;
+       PSECURITY_ATTRIBUTES psa;
+#endif /* !DJGPP */
        long i;
         unsigned long pid;
-       HANDLE hf, hm;
        char *data;
-       PSECURITY_ATTRIBUTES psa;
        long cs;
 
+#ifndef DJGPP
        /* Get system info; all we really want is the allocation granularity */ 
        GetSystemInfo(&sysInfo);
+#endif /* !DJGPP */
 
        /* Have to be able to reserve a whole chunk */
        if (((buf_nbuffers - 3) * buf_bufferSize) < cm_chunkSize)
@@ -235,6 +259,7 @@ long buf_Init(cm_buf_ops_t *opsp)
                /* initialize global locks */
                lock_InitializeRWLock(&buf_globalLock, "Global buffer lock");
 
+#ifndef DJGPP
                /*
                 * Cache file mapping constrained by
                 * system allocation granularity;
@@ -248,6 +273,7 @@ long buf_Init(cm_buf_ops_t *opsp)
                        afsi_log("Cache size rounded up to %d buffers",
                                 buf_nbuffers);
                }
+#endif /* !DJGPP */
 
                /* remember this for those who want to reset it */
                buf_nOrigBuffers = buf_nbuffers;
@@ -268,6 +294,7 @@ long buf_Init(cm_buf_ops_t *opsp)
                /* min value for which this works */
                sectorSize = 1;
 
+#ifndef DJGPP
                /* Reserve buffer space by mapping cache file */
                psa = CreateCacheFileSA();
                hf = CreateFile(cm_CachePath,
@@ -305,6 +332,10 @@ long buf_Init(cm_buf_ops_t *opsp)
                        return CM_ERROR_INVAL;
                }
                CloseHandle(hm);
+#else
+                /* djgpp doesn't support memory mapped files */
+                data = malloc(buf_nbuffers * buf_bufferSize);
+#endif /* !DJGPP */
 
                 /* create buffer headers and put in free list */
                bp = malloc(buf_nbuffers * sizeof(cm_buf_t));
@@ -345,10 +376,14 @@ long buf_Init(cm_buf_ops_t *opsp)
                osi_EndOnce(&once);
                 
                 /* and create the incr-syncer */
-                phandle = CreateThread((SECURITY_ATTRIBUTES *) 0, 0,
-                       (LPTHREAD_START_ROUTINE) buf_IncrSyncer, 0, 0, &pid);
+                phandle = thrd_Create(0, 0,
+                                      (ThreadFunc) buf_IncrSyncer, 0, 0, &pid,
+                                      "buf_IncrSyncer");
+
                osi_assertx(phandle != NULL, "buf: can't create incremental sync proc");
+#ifndef DJGPP
                CloseHandle(phandle);
+#endif /* !DJGPP */
         }
 
        return 0;
@@ -362,6 +397,7 @@ long buf_AddBuffers(long nbuffers)
        cm_buf_t *bp;
         int i;
        char *data;
+#ifndef DJGPP
        HANDLE hm;
        long cs;
 
@@ -399,6 +435,9 @@ long buf_AddBuffers(long nbuffers)
                return CM_ERROR_INVAL;
        }
        CloseHandle(hm);
+#else
+        data = malloc(buf_nbuffers * buf_bufferSize);
+#endif /* DJGPP */
 
        /* Create buffer headers and put in free list */
         bp = malloc(nbuffers * sizeof(*bp));
@@ -554,6 +593,12 @@ void buf_LockedCleanAsync(cm_buf_t *bp, cm_req_t *reqp)
                 
                 lock_ObtainMutex(&bp->mx);
                 if (code) break;
+
+#ifdef DISKCACHE95
+                /* Disk cache support */
+                /* write buffer to disk cache (synchronous for now) */
+                diskcache_Update(bp->dcp, bp->datap, buf_bufferSize, bp->dataVersion);
+#endif /* DISKCACHE95 */
        };
 
         /* do logging after call to GetLastError, or else */
@@ -857,6 +902,9 @@ long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bufpp)
         osi_hyper_t pageOffset;
         unsigned long tcount;
         int created;
+#ifdef DISKCACHE95
+        cm_diskcache_t *dcp;
+#endif /* DISKCACHE95 */
 
        created = 0;
         pageOffset.HighPart = offsetp->HighPart;
@@ -869,6 +917,11 @@ long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bufpp)
                        /* lock it and break out */
                        lock_ObtainMutex(&bp->mx);
                         break;
+
+#ifdef DISKCACHE95
+                        /* touch disk chunk to update LRU info */
+                        diskcache_Touch(bp->dcp);
+#endif /* DISKCACHE95 */
                 }
                 
                 /* otherwise, we have to create a page */
@@ -895,15 +948,25 @@ long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bufpp)
                osi_assert(!(bp->flags & (CM_BUF_READING | CM_BUF_WRITING)));
 
                /* setup offset, event */
+#ifndef DJGPP  /* doesn't seem to be used */
                bp->over.Offset = bp->offset.LowPart;
                bp->over.OffsetHigh = bp->offset.HighPart;
+#endif /* !DJGPP */
 
                /* start the I/O; may drop lock */
                 bp->flags |= CM_BUF_READING;
                        code = (*cm_buf_opsp->Readp)(bp, buf_bufferSize, &tcount, NULL);
+
+#ifdef DISKCACHE95
+                code = diskcache_Get(&bp->fid, &bp->offset, bp->datap, buf_bufferSize, &bp->dataVersion, &tcount, &dcp);
+                bp->dcp = dcp;    /* pointer to disk cache struct. */
+#endif /* DISKCACHE95 */
+
                if (code != 0) {
                        /* failure or queued */
+#ifndef DJGPP   /* cm_bufRead always returns 0 */
                         if (code != ERROR_IO_PENDING) {
+#endif
                                bp->error = code;
                                 bp->flags |= CM_BUF_ERROR;
                                 bp->flags &= ~CM_BUF_READING;
@@ -914,7 +977,9 @@ long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bufpp)
                                lock_ReleaseMutex(&bp->mx);
                                 buf_Release(bp);
                                 return code;
+#ifndef DJGPP
                         }
+#endif
                 } else {
                        /* otherwise, I/O completed instantly and we're done, except
                          * for padding the xfr out with 0s and checking for EOF
index b19950b..f37094f 100644 (file)
@@ -13,6 +13,9 @@
 #define _BUF_H__ENV_ 1
 
 #include <osi.h>
+#ifdef DISKCACHE95
+#include "cm_diskcache.h"
+#endif /* DISKCACHE95 */
 
 /* default # of buffers if not changed */
 #define CM_BUF_BUFFERS 100
@@ -78,11 +81,16 @@ typedef struct cm_buf {
         char *datap;           /* data in this buffer */
        unsigned long error;    /* last error code, if CM_BUF_ERROR is set */
         struct cm_user *userp; /* user who wrote to the buffer last */
+#ifndef DJGPP
         OVERLAPPED over;       /* overlapped structure for I/O */
+#endif
         
         /* fields added for the CM; locked by scp->mx */
         long dataVersion;      /* data version of this page */
         long cmFlags;          /* flags for cm */
+#ifdef DISKCACHE95
+        cm_diskcache_t *dcp;    /* diskcache structure */
+#endif /* DISKCACHE95 */
 } cm_buf_t;
 
 /* values for cmFlags */
@@ -143,7 +151,9 @@ extern cm_buf_t *buf_LockedFind(struct cm_scache *, osi_hyper_t *);
 
 extern cm_buf_t *buf_Find(struct cm_scache *, osi_hyper_t *);
 
+#ifndef DJGPP
 extern HANDLE buf_GetFileHandle(long);
+#endif /* !DJGPP */
 
 extern void buf_LockedCleanAsync(cm_buf_t *, cm_req_t *);
 
index c1a0a9d..2801464 100644 (file)
 #include <afs/afs_args.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
 #include <winsock2.h>
+#else
+#include <sys/socket.h>
+#endif /* !DJGPP */
 #include <malloc.h>
 #include <string.h>
 #include <stdlib.h>
index eb88d8a..d556c9e 100644 (file)
@@ -11,7 +11,6 @@
 #define _CM_CALLBACK_H_ENV__ 1
 
 #include <osi.h>
-#include "cm_scache.h"
 
 typedef struct cm_callbackRequest {
        long callbackCount;             /* callback count at start of the request */
@@ -19,6 +18,8 @@ typedef struct cm_callbackRequest {
         struct cm_server *serverp;     /* server we really got the callback from */
 } cm_callbackRequest_t;
 
+#include "cm_scache.h"
+
 typedef struct cm_racingRevokes {
         osi_queue_t q;                 /* queue for forward/backward searches */
         cm_fid_t fid;                  /* fid revoked */
index fc2f663..b8317eb 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
 #include <nb30.h>
 #include <winsock2.h>
+#endif /* !DJGPP */
 #include <stdlib.h>
 #include <stdio.h>
 #include <malloc.h>
index 4d0274d..2e1261b 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
 #include <winsock2.h>
+#else
+#include <sys/socket.h>
+#include <netdb.h>
+#endif /* !DJGPP */
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 char AFSConfigKeyName[] =
        "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
 
+#define AFS_THISCELL "ThisCell"
+#define AFS_CELLSERVDB_UNIX "CellServDB"
+#define AFS_CELLSERVDB_NT "afsdcell.ini"
+#define AFSDIR_CLIENT_ETC_DIRPATH "c:/afs"
+#if defined(DJGPP) || defined(AFS_WIN95_ENV)
+#define AFS_CELLSERVDB AFS_CELLSERVDB_UNIX
+#ifdef DJGPP
+extern char cm_confDir[];
+extern int errno;
+#endif /* DJGPP */
+#else
+#define AFS_CELLSERVDB AFS_CELLSERVDB_NT
+#endif /* DJGPP || WIN95 */
+
+
 static long cm_ParsePair(char *lineBufferp, char *leftp, char *rightp)
 {
        char *tp;
@@ -93,20 +113,48 @@ long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
         int foundCell;
         long code;
        int tracking = 1, partial = 0;
+        long ip_addr;
+#if defined(DJGPP) || defined(AFS_WIN95_ENV)
+        int c1, c2, c3, c4;
+        char aname[256];
+#endif
+        char *afsconf_path;
 
        foundCell = 0;
 
+#if !defined(DJGPP)
        code = GetWindowsDirectory(wdir, sizeof(wdir));
         if (code == 0 || code > sizeof(wdir)) return -1;
-        
+
        /* add trailing backslash, if required */
         tlen = strlen(wdir);
         if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
-
-        strcat(wdir, "afsdcell.ini");
+#else
+        strcpy(wdir, cm_confDir);
+        strcat(wdir,"/");
+#endif /* !DJGPP */
         
+        strcat(wdir, AFS_CELLSERVDB);
+
         tfilep = fopen(wdir, "r");
-        if (!tfilep) return -2;
+
+        if (!tfilep) {
+          /* If we are using DJGPP client, cellservdb will be in afsconf dir. */
+          /* If we are in Win95 here, we are linking with klog etc. and are
+             using DJGPP client even though DJGPP is not defined.  So we still
+             need to check AFSCONF for location. */
+            afsconf_path = getenv("AFSCONF");
+            if (!afsconf_path)
+               strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
+            else
+               strcpy(wdir, afsconf_path);
+            strcat(wdir, "/");
+            strcat(wdir, AFS_CELLSERVDB_UNIX);
+            /*fprintf(stderr, "opening cellservdb file %s\n", wdir);*/
+            tfilep = fopen(wdir, "r");
+            if (!tfilep) return -2;
+        }
+
        bestp = fopen(wdir, "r");
         
        /* have we seen the cell line for the guy we're looking for? */
@@ -181,6 +229,7 @@ long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
                         else inRightCell = 0;
                 }
                 else {
+#if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
                        valuep = strchr(lineBuffer, '#');
                        if (valuep == NULL) {
                                fclose(tfilep);
@@ -188,8 +237,11 @@ long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
                                return -4;
                        }
                         valuep++;      /* skip the "#" */
+
                         valuep += strspn(valuep, "     "); /* skip SP & TAB */
+#endif /* !DJGPP */
                        if (inRightCell) {
+#if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
                                /* add the server to the VLDB list */
                                 thp = gethostbyname(valuep);
                                 if (thp) {
@@ -201,11 +253,30 @@ long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
                                                (*procp)(rockp, &vlSockAddr, valuep);
                                        foundCell = 1;
                                }
+#else
+                                /* For DJGPP, we will read IP address instead
+                                   of name/comment field */
+                                code = sscanf(lineBuffer, "%d.%d.%d.%d #%s",
+                                              &c1, &c2, &c3, &c4, aname);
+                                tp = (char *) &ip_addr;
+                                *tp++ = c1;
+                                *tp++ = c2;
+                                *tp++ = c3;
+                                *tp++ = c4;
+                                memcpy(&vlSockAddr.sin_addr.s_addr, &ip_addr,
+                                               sizeof(long));
+                                vlSockAddr.sin_family = AF_INET;
+                                /* sin_port supplied by connection code */
+                                if (procp)
+                                  (*procp)(rockp, &vlSockAddr, valuep);
+                                foundCell = 1;
+#endif /* !DJGPP */
                         }
                 }      /* a vldb line */
         }              /* while loop processing all lines */
 }
 
+#if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
 /* look up the root cell's name in the Registry */
 long cm_GetRootCellName(char *cellNamep)
 {
@@ -226,6 +297,43 @@ long cm_GetRootCellName(char *cellNamep)
 
        return 0;
 }
+#else
+/* look up the root cell's name in the THISCELL file */
+long cm_GetRootCellName(char *cellNamep)
+{
+        FILE *thisCell;
+        char thisCellPath[256];
+        char *afsconf_path;
+        char *newline;
+
+#ifdef DJGPP
+        strcpy(thisCellPath, cm_confDir);
+#else
+        /* Win 95 */
+        afsconf_path = getenv("AFSCONF");
+        if (!afsconf_path)
+          strcpy(thisCellPath, AFSDIR_CLIENT_ETC_DIRPATH);
+        else
+          strcpy(thisCellPath, afsconf_path);
+#endif
+        strcat(thisCellPath,"/");
+
+        strcat(thisCellPath, AFS_THISCELL);
+        thisCell = fopen(thisCellPath, "r");
+        if (thisCell == NULL)
+          return -1;
+
+        fgets(cellNamep, 256, thisCell);
+        fclose(thisCell);
+
+        newline = strrchr(cellNamep,'\n');
+        if (newline) *newline = '\0';
+        newline = strrchr(cellNamep,'\r');
+        if (newline) *newline = '\0';
+
+        return 0;
+}
+#endif /* !DJGPP */
 
 cm_configFile_t *cm_CommonOpen(char *namep, char *rwp)
 {
@@ -233,13 +341,27 @@ cm_configFile_t *cm_CommonOpen(char *namep, char *rwp)
         long code;
         long tlen;
         FILE *tfilep;
+        char *afsconf_path;
 
+#if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
        code = GetWindowsDirectory(wdir, sizeof(wdir));
         if (code == 0 || code > sizeof(wdir)) return NULL;
         
        /* add trailing backslash, if required */
         tlen = strlen(wdir);
         if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
+#else
+#ifdef DJGPP
+        strcpy(wdir,cm_confDir);
+#else
+        afsconf_path = getenv("AFSCONF");
+        if (!afsconf_path)
+          strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
+        else
+          strcpy(wdir, afsconf_path);
+#endif /* !DJGPP */
+        strcat(wdir,"/");
+#endif /* DJGPP || WIN95 */
 
         strcat(wdir, namep);
         
@@ -248,6 +370,7 @@ cm_configFile_t *cm_CommonOpen(char *namep, char *rwp)
        return ((cm_configFile_t *) tfilep);        
 }
 
+#ifndef DJGPP
 long cm_WriteConfigString(char *labelp, char *valuep)
 {
        DWORD code, dummyDisp;
@@ -267,7 +390,9 @@ long cm_WriteConfigString(char *labelp, char *valuep)
 
         return 0;
 }
+#endif /* !DJGPP */
 
+#ifndef DJGPP
 long cm_WriteConfigInt(char *labelp, long value)
 {
        DWORD code, dummyDisp;
@@ -287,6 +412,7 @@ long cm_WriteConfigInt(char *labelp, long value)
 
        return 0;
 }
+#endif /* !DJGPP */
 
 cm_configFile_t *cm_OpenCellFile(void)
 {
@@ -305,7 +431,7 @@ long cm_AppendPrunedCellList(cm_configFile_t *ofp, char *cellNamep)
         int inRightCell;
         int foundCell;
 
-        tfilep = cm_CommonOpen("afsdcell.ini", "r");
+        tfilep = cm_CommonOpen(AFS_CELLSERVDB, "r");
         if (!tfilep) return -1;
 
        foundCell = 0;
@@ -383,15 +509,30 @@ extern long cm_CloseCellFile(cm_configFile_t *filep)
         long code;
         long closeCode;
         int tlen;
+        char *afsconf_path;
 
        closeCode = fclose((FILE *)filep);
 
+#if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
        code = GetWindowsDirectory(wdir, sizeof(wdir));
-        if (code == 0 || code > sizeof(wdir)) return -1;
+        if (code == 0 || code > sizeof(wdir)) return NULL;
         
        /* add trailing backslash, if required */
         tlen = strlen(wdir);
         if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
+#else
+#ifdef DJGPP
+        strcpy(wdir,cm_confDir);
+#else
+        afsconf_path = getenv("AFSCONF");
+        if (!afsconf_path)
+          strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
+        else
+          strcpy(wdir, afsconf_path);
+#endif /* !DJGPP */
+        strcat(wdir,"/");
+#endif /* DJGPP || WIN95 */
+
         strcpy(sdir, wdir);
 
        if (closeCode != 0) {
@@ -401,7 +542,7 @@ extern long cm_CloseCellFile(cm_configFile_t *filep)
                 return closeCode;
         }
 
-        strcat(wdir, "afsdcell.ini");
+        strcat(wdir, AFS_CELLSERVDB);
         strcat(sdir, "afsdcel2.ini");  /* new file */
         
         unlink(wdir);                  /* delete old file */
index 2963ff2..19ab236 100644 (file)
@@ -21,6 +21,9 @@
 #ifndef __CM_CONFIG_INTERFACES_ONLY__
 
 #include <stdio.h>
+#ifdef DJGPP
+#include <netinet/in.h>
+#endif /* DJGPP */
 
 extern char AFSConfigKeyName[];
 
index c78bc66..0f74060 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
+#endif /* !DJGPP */
 #include <string.h>
 #include <malloc.h>
 #include <osi.h>
 #include <rx/rx.h>
+#ifndef DJGPP
 #include <rxkad.h>
+#else
+#include <rx/rxkad.h>
+#endif
 
 #include "afsd.h"
 
@@ -45,7 +51,12 @@ void cm_InitConn(void)
 void cm_InitReq(cm_req_t *reqp)
 {
        memset((char *)reqp, 0, sizeof(cm_req_t));
+#ifndef DJGPP
        reqp->startTime = GetCurrentTime();
+#else
+        gettimeofday(&reqp->startTime, NULL);
+#endif
 }
 
 long cm_GetServerList(struct cm_fid *fidp, struct cm_user *userp,
@@ -130,7 +141,7 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
                        if (tsrp->status == busy)
                                tsrp->status = not_busy;
                }
-               Sleep(5000);
+               thrd_Sleep(5000);
                retry = 1;
        }
 
@@ -154,7 +165,7 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
                int same;
 
                /* Back off to allow move to complete */
-               Sleep(2000);
+               thrd_Sleep(2000);
 
                /* Update the volume location and see if it changed */
                cm_GetServerList(fidp, userp, reqp, &serversp);
@@ -181,6 +192,7 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
                 * this is to prevent the SMB session from timing out
                 * In addition, we log an event to the event log 
                 */
+#ifndef DJGPP
                HANDLE h;
                 char *ptbuf[1];
                 char s[100];
@@ -190,6 +202,7 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
                 ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1009, NULL,
                         1, 0, ptbuf, NULL);
                 DeregisterEventSource(h);
+#endif /* !DJGPP */
          
                retry = 0;
                osi_Log0(afsd_logp, "cm_Analyze: hardDeadTime exceeded");
@@ -236,10 +249,19 @@ long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp,
         long firstError = 0;
        int someBusy = 0, someOffline = 0;
        long timeUsed, timeLeft, hardTimeLeft;
+#ifdef DJGPP
+        struct timeval now;
+#endif /* DJGPP */        
 
         *connpp = NULL;
 
+#ifndef DJGPP
        timeUsed = (GetCurrentTime() - reqp->startTime) / 1000;
+#else
+        gettimeofday(&now, NULL);
+        timeUsed = sub_time(now, reqp->startTime) / 1000;
+#endif
+        
        /* leave 5 seconds margin of safety */
        timeLeft = RDRtimeout - timeUsed - 5;
        hardTimeLeft = timeLeft;
index e03bfe6..4c9a42f 100644 (file)
@@ -79,6 +79,8 @@ typedef struct cm_req {
                                   VBUSY above.  This is negative so that old
                                   cache managers treat it as "server is down"*/
 
+#include "cm_server.h"
+
 extern void cm_InitConn(void);
 
 extern void cm_InitReq(cm_req_t *reqp);
index 45177d7..33b3dc5 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
 #include <winsock2.h>
+#else
+#include <netdb.h>
+#endif /* !DJGPP */
 #include <stdlib.h>
 #include <malloc.h>
 #include <string.h>
@@ -113,7 +117,12 @@ void cm_Daemon(long parm)
         */
        gethostname(thostName, sizeof(thostName));
        thp = gethostbyname(thostName);
-       memcpy(&code, thp->h_addr_list[0], 4);
+        if (thp == NULL)    /* In djgpp, gethostname returns the netbios
+                               name of the machine.  gethostbyname will fail
+                               looking this up if it differs from DNS name. */
+          code = 0;
+        else
+          memcpy(&code, thp->h_addr_list[0], 4);
        srand(ntohl(code));
 
        now = osi_Time();
@@ -125,7 +134,7 @@ void cm_Daemon(long parm)
        lastTokenCacheCheck = now - cm_daemonTokenCheckInterval/2 + (rand() % cm_daemonTokenCheckInterval);
        
         while (1) {
-               Sleep(30 * 1000);               /* sleep 30 seconds */
+               thrd_Sleep(30 * 1000);          /* sleep 30 seconds */
                 
                /* find out what time it is */
                now = osi_Time();
@@ -168,7 +177,7 @@ void cm_InitDaemon(int nDaemons)
 {
        static osi_once_t once;
         long pid;
-        HANDLE phandle;
+        thread_t phandle;
         int i;
         
         if (osi_Once(&once)) {
@@ -176,16 +185,17 @@ void cm_InitDaemon(int nDaemons)
                osi_EndOnce(&once);
                 
                 /* creating pinging daemon */
-               phandle = CreateThread((SECURITY_ATTRIBUTES *) 0, 0,
-                       (LPTHREAD_START_ROUTINE) cm_Daemon, 0, 0, &pid);
+               phandle = thrd_Create((SecurityAttrib) 0, 0,
+                       (ThreadFunc) cm_Daemon, 0, 0, &pid, "cm_Daemon");
                osi_assert(phandle != NULL);
 
-               CloseHandle(phandle);
+               thrd_CloseHandle(phandle);
                for(i=0; i < nDaemons; i++) {
-                       phandle = CreateThread((SECURITY_ATTRIBUTES *) 0, 0,
-                               (LPTHREAD_START_ROUTINE) cm_BkgDaemon, 0, 0, &pid);
+                       phandle = thrd_Create((SecurityAttrib) 0, 0,
+                               (ThreadFunc) cm_BkgDaemon, 0, 0, &pid,
+                                              "cm_BkgDaemon");
                        osi_assert(phandle != NULL);
-                       CloseHandle(phandle);
+                       thrd_CloseHandle(phandle);
                }
         }
 }
index f5a6496..69a08cd 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
 #include <winsock2.h>
+#include <nb30.h>
+#endif /* !DJGPP */
 #include <malloc.h>
 #include <string.h>
 #include <stdlib.h>
-#include <nb30.h>
 #include <osi.h>
 
 #include "afsd.h"
@@ -1113,6 +1115,11 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *up,
         
         lock_ReleaseMutex(&scp->mx);
 
+#ifdef DISKCACHE95
+        DPRINTF("cm_GetBuffer: fetching data scpDV=%d bufDV=%d scp=%x bp=%x dcp=%x\n",
+                scp->dataVersion, bufp->dataVersion, scp, bufp, bufp->dcp);
+#endif /* DISKCACHE95 */
+
        /* now make the call */
         do {
                code = cm_Conn(&scp->fid, up, reqp, &connp);
@@ -1237,6 +1244,12 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *up,
                    qdp = (osi_queueData_t *) osi_QNext(&qdp->q)) {
                        tbufp = osi_GetQData(qdp);
                         tbufp->dataVersion = afsStatus.DataVersion;
+
+#ifdef DISKCACHE95
+                        /* write buffer out to disk cache */
+                        diskcache_Update(tbufp->dcp, tbufp->datap, buf_bufferSize,
+                                         tbufp->dataVersion);
+#endif /* DISKCACHE95 */
                 }
         }
 
index 01d71e5..c32de29 100644 (file)
@@ -10,7 +10,9 @@
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
+#endif /* !DJGPP */
 #include <string.h>
 #include <malloc.h>
 #include <osi.h>
diff --git a/src/WINNT/afsd/cm_diskcache95.c b/src/WINNT/afsd/cm_diskcache95.c
new file mode 100644 (file)
index 0000000..a1263bb
--- /dev/null
@@ -0,0 +1,760 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+/* This code is experimental persistent disk cache support for the
+   Windows 95/DJGPP AFS client.  It uses synchronous I/O and assumes
+   non-preemptible threads (which is the case in DJGPP), so it has
+   no locking. */
+
+   
+#ifdef DISKCACHE95
+
+#include <afs/param.h>
+#include <afs/stds.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+
+#include "afsd.h"
+
+cm_diskcache_t **diskHashTable;    /* pointers to hash chains */
+Queue diskLRUList;
+Queue openFileList;
+cm_diskcache_t *diskCBBuf;
+
+extern int afs_diskCacheChunks;
+/*extern int cm_diskCacheChunkSize;*/
+extern long buf_bufferSize;
+long cm_diskCacheChunkSize;
+extern char cm_cachePath[];
+extern int cm_cachePathLen;
+extern int cm_diskCacheEnabled;
+
+int cacheInfo_fd;
+int accessOrd = 0;            /* monotonically increasing access ordinal */
+int updates = 0;
+int afs_dhashsize = 2048;
+int openCacheFiles = 0;
+
+char cacheInfoPath[128];
+char cacheFileName[128];
+
+extern int errno;
+
+#define MAX_OPEN_FILES 22
+
+/* internal functions */
+void diskcache_WriteCacheInfo(cm_diskcache_t *dcp);
+int diskcache_New();
+cm_diskcache_t *diskcache_Find(cm_fid_t *fid, int chunk);
+cm_diskcache_t *diskcache_Alloc(cm_fid_t *fid, int chunk, int dataVersion);
+int diskcache_Read(cm_diskcache_t *dcp, char *buf, int size);
+int diskcache_Write(cm_diskcache_t *dcp, char *buf, int size);
+
+#define complain printf
+
+#define OFFSET_TO_CHUNK(a) (LargeIntegerDivideByLong((a), cm_diskCacheChunkSize))
+#define GEN_CACHE_DIR_NAME(name, path, i) \
+           sprintf(name, "%s\\D%07d", cm_cachePath, (i) / CACHE_FILES_PER_DIR)
+#define GEN_CACHE_FILE_NAME(name, path, i) \
+           sprintf(name, "%s\\D%07d\\C%07d", path, (i) / CACHE_FILES_PER_DIR, \
+                   (i) % CACHE_FILES_PER_DIR)
+
+/* Initialize the disk cache */
+int diskcache_Init()
+{
+  int i;
+  int rc;
+  int fd;
+  int invalid;
+  int index;
+  char *chunkBuf;
+  char tmpBuf[512];
+  struct stat cacheInfoStat, chunkStat;
+  cm_cacheInfoHdr_t hdr;
+  cm_diskcache_t *dcp;
+  int validCount = 0;
+
+  if (!cm_diskCacheEnabled)
+    return 0;
+  
+  cm_diskCacheChunkSize = buf_bufferSize;
+  if (cm_diskCacheChunkSize % buf_bufferSize != 0)
+  {
+    complain("Error: disk cache chunk size %d not a multiple of buffer size %d\n",
+             cm_diskCacheChunkSize, buf_bufferSize);
+    return CM_ERROR_INVAL;
+  }
+  
+  /* alloc mem for chunk file control blocks */
+  diskCBBuf = (cm_diskcache_t *) malloc(afs_diskCacheChunks * sizeof(cm_diskcache_t));
+  if (diskCBBuf == NULL)
+    return CM_ERROR_SPACE;
+  memset(diskCBBuf, 0, afs_diskCacheChunks * sizeof(cm_diskcache_t));
+
+  /* alloc mem for hash table pointers */
+  diskHashTable = (cm_diskcache_t **) malloc(afs_dhashsize * sizeof(cm_diskcache_t *));
+  if (diskHashTable == NULL)
+    return CM_ERROR_SPACE;
+  memset(diskHashTable, 0, afs_dhashsize*sizeof(cm_diskcache_t *));
+
+  QInit(&diskLRUList);
+  QInit(&openFileList);
+  
+  /*sprintf(cacheInfoPath, "%s\\%s", cm_cachePath, CACHE_INFO_FILE);*/
+  memset(cacheInfoPath, 0, 128);
+  DPRINTF("cm_cachePath=%s\n", cm_cachePath);
+  strncpy(cacheInfoPath, cm_cachePath, 50);
+  strcat(cacheInfoPath, "\\");
+  strcat(cacheInfoPath, CACHE_INFO_FILE);
+  DPRINTF("cacheInfoPath=%s\n", cacheInfoPath);
+  
+  cacheInfo_fd = open(cacheInfoPath, O_RDWR | O_BINARY);
+  
+  if (cacheInfo_fd < 0)
+  {
+    /* file not present */
+    return diskcache_New();   /* initialize new empty disk cache */
+  }
+
+  /* get stat of cache info file */
+  rc = fstat(cacheInfo_fd, &cacheInfoStat);
+
+  /* Check for valid header in cache info file */
+  rc = read(cacheInfo_fd, &hdr, sizeof(cm_cacheInfoHdr_t));
+  if (rc < sizeof(cm_cacheInfoHdr_t) ||
+      hdr.magic != CACHE_INFO_MAGIC)
+  /*hdrp = (cm_cacheInfoHdr_t *) tmpBuf;*/
+  {
+    close(cacheInfo_fd);
+    return diskcache_New();
+  }
+        
+  if (hdr.chunks != afs_diskCacheChunks ||
+      hdr.chunkSize != cm_diskCacheChunkSize)
+  {
+    /* print error message saying params don't match */
+    return CM_ERROR_INVAL;
+  }
+  
+  chunkBuf = (char *) malloc(cm_diskCacheChunkSize);
+  if (chunkBuf == NULL)
+    return CM_ERROR_SPACE;
+
+  /* read metadata from cache info file into control blocks */
+  /* reconstruct hash chains based on fid, chunk */
+  for (i = 0; i < afs_diskCacheChunks; i++)
+  {  /* for all cache chunks */
+    if (i % 500 == 0)
+    {
+      printf("%d...", i);
+      fflush(stdout);
+    }
+    dcp = &diskCBBuf[i];
+    dcp->refCount = 0;
+    rc = read(cacheInfo_fd, &dcp->f, sizeof(struct fcache));
+    if (rc < sizeof(struct fcache))
+    {
+      /* print error message about reading cache info file */
+      /* this isn't the right error code for a read error */
+      return CM_ERROR_INVAL;
+    }
+
+    if (dcp->f.index != i)
+      return CM_ERROR_INVAL;   /* index should match position in cache info file */
+
+    /* Try to open cache file.  This chunk will be invalidated if we can't
+       find the file, the file is newer than the cache info file, the file
+       size doesn't match the cache info file, or the file's header is
+       invalid. */
+    GEN_CACHE_FILE_NAME(cacheFileName, cm_cachePath, i);
+#if 1
+    /*fd = open(cacheFileName, O_RDWR | O_BINARY);
+    if (fd < 0) invalid = 1;
+    else
+    {
+    rc = fstat(fd, &chunkStat);*/
+    rc = stat(cacheFileName, &chunkStat);
+
+      if (rc < 0) invalid = 1;
+      /*else if (cacheInfoStat.st_mtime < chunkStat.st_mtime + 120) invalid = 1;*/
+      else if (cacheInfoStat.st_mtime < chunkStat.st_mtime) invalid = 1;
+      /*else if (cacheInfoStat.st_mtime < dcp->f.modTime + 120) invalid = 1;*/
+      else if (cacheInfoStat.st_mtime < dcp->f.modTime) invalid = 1;
+      else if (cm_diskCacheChunkSize != chunkStat.st_size ||
+               dcp->f.chunkBytes != chunkStat.st_size) invalid = 1;
+      /*else
+        {*/
+        /*rc = read(fd, chunkBuf, cm_diskCacheChunkSize);
+          if (rc < 0) invalid = 1;*/
+
+        /*else
+        {
+          cacheFileHdrP = (cm_cacheFileHdr_t *) chunkBuf;
+          if (cacheFileHdrP->magic != CACHE_FILE_MAGIC ||
+              cacheFileHdrP->index != i)
+          {
+            invalid = 1;
+          }
+        }*/
+      /*}*/
+      /*}*/
+#else
+    invalid = 0;
+#endif
+      
+    if (invalid == 0)
+    {
+      /* Cache file seems to be valid */
+    
+      validCount++;
+      DPRINTF("Found fid/chunk=%08x-%08x-%08x-%08x/%04d in slot=%d dcp=%x\n",
+             dcp->f.fid.cell, dcp->f.fid.volume, dcp->f.fid.vnode,
+             dcp->f.fid.unique, dcp->f.chunk, i, dcp);
+      /* Put control block in hash table */
+      index = DCHash(&dcp->f.fid, dcp->f.chunk);
+      /*osi_QAdd(&diskHashTable[index], &dcp->f.hashq);*/
+
+      /* add to head of hash list.  (we should probably look at
+         ord here instead.  use queues?) */
+      dcp->hash_next = diskHashTable[index];
+      dcp->hash_prev = NULL;
+      if (diskHashTable[index]) diskHashTable[index]->hash_prev = dcp;
+      diskHashTable[index] = dcp;
+
+      /* Add to LRU queue in access time order (lowest at tail) */
+      QAddOrd(&diskLRUList, &dcp->lruq, dcp->f.accessOrd);
+
+      close(fd);
+    }
+    else
+    {
+      /* Cache file is invalid */
+      
+      /* Create the cache file with correct size */
+      memset(chunkBuf, 0, cm_diskCacheChunkSize);
+      /*cacheFileHdrP->magic = CACHE_FILE_MAGIC;
+        cacheFileHdrP->index = i;*/
+      
+      if (fd != 0) close(fd);
+      /* Note that if the directory this file is supposed to be in doesn't
+         exist, the creat call will fail and we will return an error. */
+      /*fd = creat(cacheFileName, S_IRUSR|S_IWUSR);*/
+      fd = open(cacheFileName, O_RDWR | O_BINARY | O_CREAT | O_TRUNC,
+                S_IRUSR | S_IWUSR);
+      if (fd < 0) return CM_ERROR_INVAL;   /* couldn't create file */
+      rc = write(fd, chunkBuf, cm_diskCacheChunkSize);
+      if (rc < 0)   /* ran out of space? */
+        return CM_ERROR_INVAL;
+      close(fd);
+      
+      /* We consider an invalid chunk as empty, so we put it at tail of LRU */
+      memset(dcp, 0, sizeof(cm_diskcache_t));
+      dcp->f.accessOrd = 0;
+      dcp->f.states = DISK_CACHE_EMPTY;
+      dcp->f.index = i;
+      dcp->f.chunkBytes = cm_diskCacheChunkSize;
+      /*osi_QAdd(diskLRUList, &dcp->lruq);*/
+      QAddOrd(&diskLRUList, &dcp->lruq, dcp->f.accessOrd);     /* head is LRU */
+
+      /* write out cache info modifications */
+      lseek(cacheInfo_fd, -sizeof(struct fcache), SEEK_CUR);
+      write(cacheInfo_fd, &dcp->f, sizeof(struct fcache));
+    }
+  }  /* for all cache chunks */
+
+  free(chunkBuf);
+  /*close(cacheInfo_fd);*/
+  fprintf(stderr, "\nFound %d of %d valid %d-byte blocks\n", validCount,
+          afs_diskCacheChunks, cm_diskCacheChunkSize);
+
+  return 0;
+}
+
+/* create empty disk cache files */
+/* assumes tables have already been malloc'd by diskcache_Init */
+int diskcache_New()
+{
+  int i;
+  int rc;
+  int fd;
+  int invalid;
+  int index;
+  /*char cacheInfoPath[256];
+    char cacheFileName[256];*/
+  char dirName[256];
+  char *chunkBuf;
+  struct stat cacheInfoStat, chunkStat;
+  cm_cacheInfoHdr_t hdr;
+  cm_diskcache_t *dcp;
+  
+  sprintf(cacheInfoPath, "%s\\%s", cm_cachePath, CACHE_INFO_FILE);
+  /*cacheInfo_fd = creat(cacheInfoPath, S_IRUSR | S_IWUSR);*/
+  cacheInfo_fd = open(cacheInfoPath, O_RDWR | O_BINARY | O_CREAT | O_TRUNC,
+                      S_IRUSR | S_IWUSR);
+  if (cacheInfo_fd < 0)
+  {
+    complain("diskcache_New: Error creating cache info file in cache directory %s\n",
+             cm_cachePath);
+    return CM_ERROR_INVAL;
+  }
+
+  /* write valid header */
+  hdr.magic = CACHE_INFO_MAGIC;
+  hdr.chunks = afs_diskCacheChunks;
+  hdr.chunkSize = cm_diskCacheChunkSize;
+  rc = write(cacheInfo_fd, (char *) &hdr, sizeof(cm_cacheInfoHdr_t));
+  if (rc < 0)
+    return CM_ERROR_INVAL;
+  
+  chunkBuf = (char *) malloc(cm_diskCacheChunkSize);
+  if (chunkBuf == NULL)
+    return CM_ERROR_SPACE;
+  memset(chunkBuf, 0, cm_diskCacheChunkSize);
+
+  for (i = 0; i < afs_diskCacheChunks; i++)
+  {  /* for all cache chunks */
+    if (i % 500 == 0)
+    {
+      printf("%d...", i);
+      fflush(stdout);
+    }
+
+    dcp = &diskCBBuf[i];
+
+    dcp->refCount = 0;
+    /* $$$: init mutex mx */
+    memset(dcp, 0, sizeof(cm_diskcache_t));
+    dcp->f.accessOrd = 0;
+    dcp->f.index = i;
+    dcp->f.states = DISK_CACHE_EMPTY;
+    dcp->f.chunkBytes = cm_diskCacheChunkSize;
+    QAddT(&diskLRUList, &dcp->lruq, dcp->f.accessOrd);     /* head is LRU */
+    rc = write(cacheInfo_fd, &dcp->f, sizeof(struct fcache));
+
+    if (i % CACHE_FILES_PER_DIR == 0)
+    {
+      GEN_CACHE_DIR_NAME(dirName, cm_cachePath, i);
+      rc = mkdir(dirName, S_IRUSR | S_IWUSR);
+      if (rc < 0 && errno != EEXIST)
+      {
+        complain("diskcache_New: Couldn't create cache directory %s\n", dirName);
+        return CM_ERROR_INVAL;
+      }
+    }
+    
+    GEN_CACHE_FILE_NAME(cacheFileName, cm_cachePath, i);
+    /*fd = creat(cacheFileName, S_IRUSR | S_IWUSR);*/
+    fd = open(cacheFileName, O_RDWR | O_BINARY | O_CREAT | O_TRUNC,
+              S_IRUSR | S_IWUSR);
+    if (fd < 0)
+    {
+      if (errno == ENOSPC)
+        complain("diskcache_New: Not enough space in cache path to create file %s\n",
+                 cacheFileName);
+      else
+        complain("diskcache_New: Couldn't create cache file %s\n", cacheFileName);
+      return CM_ERROR_INVAL;
+    }
+
+    /*fileHdr.magic = CACHE_FILE_MAGIC;
+    fileHdr.index = i;
+    rc = write(fd, &fileHdr, sizeof(cm_cacheFileHdr_t));  /* maybe we should write
+                                                             a full block? */
+    /*if (rc == 0)
+      {*/
+      rc = write(fd, chunkBuf, cm_diskCacheChunkSize);
+      /*}*/
+
+    if (rc < 0)
+    {
+      if (errno == ENOSPC)
+        complain("diskcache_New: Not enough space in cache path to write to file %s\n",
+                 cacheFileName);
+      else
+        complain("diskcache_New: Couldn't write to cache file %s\n",
+                 cacheFileName);
+      return CM_ERROR_INVAL;
+    }
+
+    close(fd);
+  }  /* for all cache chunks */
+
+  free(chunkBuf);
+    
+  /*close(cacheInfo_fd);*/
+
+  return 0;
+}
+
+/* Get chunk from the cache or allocate a new chunk */
+int diskcache_Get(cm_fid_t *fid, osi_hyper_t *offset, char *buf, int size, int *dataVersion, int *dataCount, cm_diskcache_t **dcpRet)
+{
+  cm_diskcache_t *dcp;
+  int rc;
+  int chunk;
+
+  
+  if (!cm_diskCacheEnabled)
+  {
+    *dcpRet = NULL;
+    return 0;
+  }
+
+  chunk = OFFSET_TO_CHUNK(*offset);  /* chunk number */
+
+  DPRINTF("diskcache_Get: fid/chunk=%08x-%08x-%08x-%08x/%04d\n",
+           fid->cell, fid->volume, fid->vnode, fid->unique, chunk);
+  
+  dcp = diskcache_Find(fid, chunk);
+  if (dcp != NULL)
+  {
+    rc = diskcache_Read(dcp, buf, size);
+    *dataVersion = dcp->f.dataVersion;   /* update caller's data version */
+    if (rc < 0)
+      return -1;
+    else
+      *dataCount = rc;
+  }
+  else
+  {
+    dcp = diskcache_Alloc(fid, chunk, *dataVersion);
+    if (dcp == NULL)
+      return -1;
+  }
+
+  if (++updates >= CACHE_INFO_UPDATES_PER_WRITE)
+  {
+    updates = 0;
+    diskcache_WriteCacheInfo(dcp);  /* update cache info for this slot */
+  }
+
+  *dcpRet = dcp;
+  /*printf("diskcache_Get: returning dcp=%x\n", dcp);*/
+  return 0;
+}
+
+
+/* Look for a file chunk in the cache */
+cm_diskcache_t *diskcache_Find(cm_fid_t *fid, int chunk)
+{
+  int index;
+  cm_diskcache_t *dcp;
+  cm_diskcache_t *prev;
+
+  index = DCHash(fid, chunk);
+  dcp = diskHashTable[index];
+  prev = NULL;
+
+  while (dcp != NULL)
+  {
+    if (cm_FidCmp(&dcp->f.fid, fid) == 0 && chunk == dcp->f.chunk)
+    {
+      dcp->f.accessOrd = accessOrd++;
+      /* Move it to the beginning of the list */
+      if (diskHashTable[index] != dcp)
+      {
+        assert(dcp->hash_prev->hash_next == dcp);
+        dcp->hash_prev->hash_next = dcp->hash_next;
+        if (dcp->hash_next)
+        {
+          assert(dcp->hash_next->hash_prev == dcp);
+          dcp->hash_next->hash_prev = dcp->hash_prev;
+        }
+        dcp->hash_next = diskHashTable[index];
+        dcp->hash_prev = NULL;
+        if (diskHashTable[index]) diskHashTable[index]->hash_prev = dcp;
+        diskHashTable[index] = dcp;
+      }
+      break;
+    }
+    prev = dcp;
+    dcp = dcp->hash_next;
+  }
+      
+  if (dcp)
+    DPRINTF("diskcache_Find: fid/chunk=%08x-%08x-%08x-%08x/%04d slot=%d hash=%d dcp=%x\n",
+           fid->cell, fid->volume, fid->vnode, fid->unique, chunk, dcp->f.index, index, dcp);
+  else
+    DPRINTF("diskcache_Find: fid/chunk=%08x/%04d not found\n",
+           fid->unique, chunk);
+    
+  return dcp;
+}
+    
+int diskcache_Read(cm_diskcache_t *dcp, char *buf, int size)
+{
+  char cacheFileName[256];
+  int fd;
+  int rc;
+  int opened = 0;
+
+  GEN_CACHE_FILE_NAME(cacheFileName, cm_cachePath, dcp->f.index);
+
+  DPRINTF("diskcache_Read: filename=%s dcp=%x\n", cacheFileName,
+         dcp);
+  
+  /* For reads, we will use the fd if already open, but we won't leave
+     the file open.  Note that if we use async I/O, we will need to
+     do locking to prevent someone from closing the file while I/O
+     is going on.  But for now, all I/O is synchronous, and threads
+     are non-preemptible. */
+  
+  if (dcp->openfd == 0)
+  {
+    fd = open(cacheFileName, O_RDWR | O_BINARY);
+    if (fd < 0)
+    {
+      complain("diskcache_Read: Couldn't open cache file %s\n", cacheFileName);
+      return -1;
+    }
+    opened = 1;
+  }
+  else
+    fd = dcp->openfd;
+
+  if (fd < 0)
+  {
+    complain("diskcache_Read: Couldn't open cache file %s\n", cacheFileName);
+    return -1;
+  }
+
+  rc = read(fd, buf, size);
+  if (rc < 0)
+  {
+    complain("diskcache_Read: Couldn't read cache file %s\n", cacheFileName);
+    close(fd); return -1;
+  }
+    
+  if (opened)
+    close(fd);   /* close it if we opened it */
+  return rc;  /* bytes read */
+}
+
+/* Write out buffer to disk */
+int diskcache_Update(cm_diskcache_t *dcp, char *buf, int size, int dataVersion)
+{
+  if (!cm_diskCacheEnabled)
+    return 0;
+
+  DPRINTF("diskcache_Update dcp=%x, dataVersion=%d\n", dcp, dataVersion);
+  diskcache_Write(dcp, buf, size);
+  /*diskcache_SetMRU(dcp);*/
+  dcp->f.dataVersion = dataVersion;
+  /*dcp->f.accessOrd = accessOrd++;*/
+  /*QMoveToTail(&diskLRUList, &dcp->lruq, dcp->f.accessOrd);*/
+
+  if (++updates >= CACHE_INFO_UPDATES_PER_WRITE)
+  {
+    updates = 0;
+    diskcache_WriteCacheInfo(dcp);  /* update cache info */
+  }
+  return 0;
+}
+
+/* Allocate a new chunk file control block for this fid/chunk */
+cm_diskcache_t *diskcache_Alloc(cm_fid_t *fid, int chunk, int dataVersion)
+{
+  cm_diskcache_t *dcp;
+  QLink* q;
+  int index;
+  int stole=0, stolen_chunk, stolen_fid_unique;
+  
+  /* Remove LRU elt. (head) from free list */
+  q = QServe(&diskLRUList);
+  if (q == NULL)
+    dcp = NULL;
+  else
+    dcp = (cm_diskcache_t *) MEM_TO_OBJ(cm_diskcache_t, lruq, q);
+  if (dcp == NULL)
+  {
+    DPRINTF("diskcache_Alloc: fid/chunk=%08x/%04d allocation failed\n",
+           fid->unique, chunk);
+    return NULL;
+  }
+
+  /* Use this element for this fid/chunk */
+  if (dcp->f.states == DISK_CACHE_USED)
+  {
+    /* Remove from old hash chain */
+    if (dcp->hash_prev)
+    {
+      assert(dcp->hash_prev->hash_next == dcp);
+      dcp->hash_prev->hash_next = dcp->hash_next;
+    }
+    else
+    {
+      index = DCHash(&dcp->f.fid, dcp->f.chunk);
+      diskHashTable[index] = dcp->hash_next;
+    }
+    if (dcp->hash_next)
+    {
+      assert(dcp->hash_next->hash_prev == dcp);
+      dcp->hash_next->hash_prev = dcp->hash_prev;
+    }
+    
+    stole = 1;
+    stolen_chunk = dcp->f.chunk;
+    stolen_fid_unique = dcp->f.fid.unique;
+  }
+  
+  memcpy(&dcp->f.fid, fid, sizeof(cm_fid_t));
+  dcp->f.chunk = chunk;
+  dcp->f.dataVersion = dataVersion;
+  dcp->f.accessOrd = accessOrd++;
+  dcp->f.states = DISK_CACHE_USED;
+  
+  /* allocate at head of new hash chain */
+  index = DCHash(fid, chunk);
+  /*osi_QAddH(&diskHashTable[index], &dcp->hashq);*/
+  dcp->hash_next = diskHashTable[index];
+  dcp->hash_prev = NULL;
+  if (diskHashTable[index]) diskHashTable[index]->hash_prev = dcp;
+  diskHashTable[index] = dcp;
+
+  /* put at tail of queue */
+  QAddT(&diskLRUList, &dcp->lruq, dcp->f.accessOrd);
+  
+  if (stole)
+    DPRINTF("diskcache_Alloc: fid/chunk=%08x/%04d (recyc fid/chunk=%08x/%04d) "
+           "slot=%d hash=%d dcp=%x\n",
+           fid->unique, chunk, stolen_fid_unique, stolen_chunk,
+           dcp->f.index, index, dcp);
+  else
+    DPRINTF("diskcache_Alloc: fid/chunk=%08x/%04d slot=%d hash=%d dcp=%x\n",
+           fid->unique, chunk, dcp->f.index, index, dcp);
+  return dcp;
+}
+
+/* Write this chunk to its disk file */
+int diskcache_Write(cm_diskcache_t *dcp, /*int bufferNum,*/ char *buf, int size)
+{
+   char cacheFileName[256];
+   int fd;
+   int rc;
+   int opened = 0;
+   QLink *q;
+   
+   /*return 0;*/
+   
+   DPRINTF("diskcache_Write\n");
+   
+   /* write bytes of buf into chunk file */
+   GEN_CACHE_FILE_NAME(cacheFileName, cm_cachePath, dcp->f.index);
+   if (dcp->openfd == 0)
+   {
+     dcp->openfd = open(cacheFileName, O_RDWR | O_BINARY);
+     if (dcp->openfd < 0)
+     {
+       dcp->openfd = 0;
+       complain("diskcache_Write: Couldn't open cache file %s\n", cacheFileName);
+       return -1;
+     }
+     opened = 1;
+   }
+
+   /*lseek(dcp->openfd, bufferNum * buf_bufferSize, SEEK_SET);*/
+   /* only write size bytes */
+   rc = write(dcp->openfd, buf, size);
+   if (rc < 0)
+   {
+      complain("diskcache_Write: Couldn't write cache file %s\n", cacheFileName);
+      close(dcp->openfd); dcp->openfd = 0; return rc;
+   }
+
+   if (opened)
+   {
+     /* add to open file list */
+     QAddT(&openFileList, &dcp->openq, 0);
+     openCacheFiles++;
+   }
+   else
+     QMoveToTail(&openFileList, &dcp->openq, 0);
+
+   if (openCacheFiles >= MAX_OPEN_FILES)
+   {
+     /* close longest-open file */
+     q = QServe(&openFileList);
+     dcp = (cm_diskcache_t *) MEM_TO_OBJ(cm_diskcache_t, openq, q);
+     assert(dcp != NULL);
+     if (dcp->openfd > 0)
+       close(dcp->openfd);
+     dcp->openfd = 0;
+     openCacheFiles--;
+   }
+     
+   return 0;
+}
+
+/* we accessed this chunk (hit on buffer read), so move to MRU */
+void diskcache_Touch(cm_diskcache_t *dcp)
+{
+  if (!cm_diskCacheEnabled || !dcp) return;
+  dcp->f.accessOrd = accessOrd++;
+  QMoveToTail(&diskLRUList, &dcp->lruq, dcp->f.accessOrd);  /* tail is MRU */
+}
+
+/* invalidate this disk cache entry */
+int diskcache_Invalidate(cm_diskcache_t *dcp)
+{
+  /* We consider an invalid chunk as empty, so we put it at tail of LRU */
+  QRemove(&diskLRUList, &dcp->lruq);
+
+  dcp->f.accessOrd = 0;
+  dcp->f.states = DISK_CACHE_EMPTY;
+  dcp->f.chunk = 0;
+  memset(&dcp->f.fid, sizeof(cm_fid_t));
+  /*osi_QAdd(diskLRUList, &dcp->lruq);*/
+  QAddH(&diskLRUList, &dcp->lruq, dcp->f.accessOrd);     /* head is LRU */
+}
+
+void diskcache_WriteCacheInfo(cm_diskcache_t *dcp)
+{
+  /*char cacheInfoPath[256];
+    int cacheInfo_fd;*/
+  int rc;
+  
+  /*return;   /* skip this for perf. testing */
+  /*sprintf(cacheInfoPath, "%s\\%s", cm_cachePath, CACHE_INFO_FILE);
+    cacheInfo_fd = open(cacheInfoPath, O_RDWR);*/
+
+  DPRINTF("diskcache_WriteCacheInfo\n");
+
+  lseek(cacheInfo_fd, dcp->f.index * sizeof(struct fcache) +
+        sizeof(cm_cacheInfoHdr_t), SEEK_SET);
+
+  rc = write(cacheInfo_fd, &dcp->f, sizeof(struct fcache));
+  if (rc < 0)
+    complain("diskcache_WriteCacheInfo: Couldn't write cache info file, error=%d\n", errno);
+  /*fsync(cacheInfo_fd);*/
+
+  /*close(cacheInfo_fd);*/
+}
+
+void diskcache_Shutdown()
+{
+  cm_diskcache_t *dcp;
+  QLink *q;
+
+  /* close cache info file */
+  close (cacheInfo_fd);
+  
+  /* close all open cache files */
+  q = QServe(&openFileList);
+  while (q)
+  {
+    dcp = (cm_diskcache_t *) MEM_TO_OBJ(cm_diskcache_t, openq, q);
+    if (dcp->openfd)
+      close(dcp->openfd);
+    q = QServe(&openFileList);
+  }
+}
+
+#endif /* DISKCACHE95 */
diff --git a/src/WINNT/afsd/cm_diskcache95.h b/src/WINNT/afsd/cm_diskcache95.h
new file mode 100644 (file)
index 0000000..f8721e0
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#ifndef CM_DISKCACHE_H
+#define CM_DISKCACHE_H
+
+#include "queue95.h"
+
+#define        DCHash(v, c)    ((((v)->vnode + (v)->volume + (c))) & (afs_dhashsize-1))
+
+#define CACHE_INFO_FILE "cacheInfo"
+
+#define CACHE_INFO_MAGIC 0x34564321
+#define CACHE_FILE_MAGIC 0x78931230
+#define CACHE_FILES_PER_DIR 1000
+#define CACHE_INFO_UPDATES_PER_WRITE 1
+
+#define DPRINTF if (0) printf
+
+/* kept on disk and in dcache entries */
+struct fcache {
+    cm_fid_t fid;      /* Fid for this file */
+    int32 modTime;             /* last time this entry was modified */
+  /*afs_hyper_t versionNo;     /* Associated data version number */
+  int dataVersion;
+    int chunk;         /* Relative chunk number */
+    int chunkBytes;            /* Num bytes in this chunk */
+    char states;               /* Has this chunk been modified? */
+    int accessOrd;      /* change to 64 bit later */
+#define DISK_CACHE_EMPTY 0
+#define DISK_CACHE_USED 1
+  int index;                /* absolute chunk number */
+  int checksum;
+  /*char pad[464];   /* pad up to 512 bytes */
+};
+
+/* in-memory chunk file control block */
+typedef struct cm_diskcache {
+  struct fcache f;
+
+  /*osi_queue_t lruq;
+    osi_queue_t hashq;*/
+  QLink lruq;
+  QLink openq;
+  int openfd;      /* open file descriptor */
+  struct cm_diskcache *hash_next;
+  struct cm_diskcache *hash_prev;
+  int refCount;
+  osi_mutex_t mx;
+} cm_diskcache_t;
+
+typedef struct cm_cacheInfoHdr {
+  int magic;
+  int chunks;     /* total chunks in cache */
+  int chunkSize;
+  char pad[500];  /* pad up to 512 bytes */
+} cm_cacheInfoHdr_t;
+
+typedef struct cm_cacheFileHdr {
+  int magic;
+  int index;
+} cm_cacheFileHdr_t;
+
+/* external functions */
+
+/* Initialize the disk cache */
+int diskcache_Init();
+/* Get chunk from the cache or allocate a new chunk */
+int diskcache_Get(cm_fid_t *fid, osi_hyper_t *offset, char *buf, int size, int *dataVersion, int *dataCount, cm_diskcache_t **dcpRet);
+/* Write out buffer to disk */
+int diskcache_Update(cm_diskcache_t *dcp, char *buf, int size, int dataVersion);
+/* we accessed this chunk, so move to MRU */
+void diskcache_Touch(cm_diskcache_t *dcp);
+
+#endif /* CM_DISKCACHE_H */
index 76052d6..ec53fbb 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
 #include <winsock2.h>
+#endif /* !DJGPP */
 #include <string.h>
 #include <stdlib.h>
 #include <osi.h>
@@ -41,6 +43,7 @@ static struct nc nameCache[NCSIZE];
 struct nc*     nameHash[NHSIZE];
 
 
+#ifndef DJGPP
 #define dnlcNotify(x,debug){                    \
                         HANDLE  hh;             \
                         char *ptbuf[1];         \
@@ -52,6 +55,9 @@ struct nc*    nameHash[NHSIZE];
                             DeregisterEventSource(hh);                 \
                        }                                               \
                      }  
+#else
+#define dnlcNotify(x,debug)
+#endif /* !DJGPP */
 
 
 static struct nc * 
index db9346d..2de6df1 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
+#else
+#include <sys/socket.h>
+#endif /* !DJGPP */
 #include <errno.h>
 #include <stdlib.h>
 #include <malloc.h>
 
 #include "smb.h"
 
+#ifndef DJGPP
 #include <rxkad.h>
-
 #include "afsrpc.h"
+#else
+#include <rx/rxkad.h>
+#include "afsrpc95.h"
+#endif
+
 #include "cm_rpc.h"
 
 /* Copied from afs_tokens.h */
 #define PIOCTL_LOGON   0x1
+#define MAX_PATH 260
 
 osi_mutex_t cm_Afsdsbmt_Lock;
 
@@ -99,10 +109,17 @@ void cm_ResetACLCache(cm_user_t *userp)
  */
 void TranslateExtendedChars(char *str)
 {
+  char *p;
+  
         if (!str || !*str)
                 return;
 
+#ifndef DJGPP
         CharToOem(str, str);
+#else
+        p = str;
+        while (*p) *p++ &= 0x7f;  /* turn off high bit; probably not right */
+#endif
 }
         
 /* parse the passed-in file name and do a namei on it.  If we fail,
@@ -1367,10 +1384,12 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
                uname = tp;
                tp += strlen(tp) + 1;
 
+#ifndef DJGPP   /* for win95, session key is back in pioctl */
                /* uuid */
                memcpy(&uuid, tp, sizeof(uuid));
                if (!cm_FindTokenEvent(uuid, sessionKey))
                        return CM_ERROR_INVAL;
+#endif /* !DJGPP */
        } else
                cellp = cm_rootCellp;
 
@@ -1382,6 +1401,7 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
                free(ucellp->ticketp);  /* Discard old token if any */
        ucellp->ticketp = malloc(ticketLen);
        memcpy(ucellp->ticketp, ticket, ticketLen);
+#ifndef DJGPP
        /*
         * Get the session key from the RPC, rather than from the pioctl.
         */
@@ -1389,6 +1409,10 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
        memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
         */
        memcpy(ucellp->sessionKey.data, sessionKey, sizeof(sessionKey));
+#else
+        /* for win95, we are getting the session key from the pioctl */
+        memcpy(&ucellp->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
+#endif /* !DJGPP */
        ucellp->kvno = ct.AuthHandle;
        ucellp->expirationTime = ct.EndTimestamp;
        ucellp->gen++;
@@ -1455,6 +1479,7 @@ long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
        /* clear token */
        ct.AuthHandle = ucellp->kvno;
+#ifndef DJGPP
        /*
         * Don't give out a real session key here
         */
@@ -1462,6 +1487,9 @@ long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
        memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
         */
        memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
+#else
+       memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
+#endif /* !DJGPP */
        ct.ViceId = 37;                 /* XXX */
        ct.BeginTimestamp = 0;          /* XXX */
        ct.EndTimestamp = ucellp->expirationTime;
@@ -1496,7 +1524,9 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
        cm_ucell_t *ucellp;
        struct ClearToken ct;
        char *tp;
+#ifndef DJGPP
        afs_uuid_t uuid;
+#endif /* !DJGPP */
 
        cm_SkipIoctlPath(ioctlp);
 
@@ -1509,8 +1539,10 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
        if (!cellp) return CM_ERROR_NOSUCHCELL;
        tp += strlen(tp) + 1;
 
+#ifndef DJGPP
        /* uuid */
        memcpy(&uuid, tp, sizeof(uuid));
+#endif /* !DJGPP */
 
        lock_ObtainMutex(&userp->mx);
 
@@ -1535,6 +1567,7 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
        /* clear token */
        ct.AuthHandle = ucellp->kvno;
+#ifndef DJGPP
        /*
         * Don't give out a real session key here
         */
@@ -1542,6 +1575,9 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
        memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
         */
        memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
+#else
+        memcpy(ct.HandShakeKey, &ucellp->sessionKey, sizeof(ct.HandShakeKey));
+#endif /* !DJGPP */
        ct.ViceId = 37;                 /* XXX */
        ct.BeginTimestamp = 0;          /* XXX */
        ct.EndTimestamp = ucellp->expirationTime;
@@ -1565,7 +1601,9 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
 
        lock_ReleaseMutex(&userp->mx);
 
+#ifndef DJGPP
        cm_RegisterNewTokenEvent(uuid, ucellp->sessionKey.data);
+#endif /* !DJGPP */
 
        return 0;
 }
@@ -1806,3 +1844,14 @@ long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp)
 
        return 0;
 }
+
+#ifdef DJGPP
+extern int afsd_shutdown(int);
+extern int afs_shutdown;
+
+long cm_IoctlShutdown(smb_ioctl_t *ioctlp, cm_user_t *userp)
+{
+  afs_shutdown = 1;   /* flag to shut down */
+  return 0;
+}
+#endif /* DJGPP */
index 0346d29..ee5b338 100644 (file)
@@ -123,6 +123,9 @@ extern long cm_IoctlGetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp);
 
 extern long cm_IoctlSetRxkcrypt(smb_ioctl_t *ioctlp, cm_user_t *userp);
 
+extern long cm_IoctlShutdown(smb_ioctl_t *ioctlp, cm_user_t *userp);
+
+
 #endif /* __CM_IOCTL_INTERFACES_ONLY__ */
 
 #endif /*  __CM_IOCTL_H_ENV__ */
index ca297f6..33f4c8e 100644 (file)
 #include <malloc.h>
 
 #include <osi.h>
+#ifndef DJGPP
 #include "afsrpc.h"
+#else
+#include "afsrpc95.h"
+#endif
 
 #include "afsd.h"
 #include "afsd_init.h"
index 3245cc6..beba2e3 100644 (file)
 #ifndef        __CM_RPC_H__
 #define __CM_RPC_H__
 
+#ifndef DJGPP
 #include "afsrpc.h"
+#else
+#include "afsrpc95.h"
+#endif
 
 void cm_RegisterNewTokenEvent(afs_uuid_t uuid, char sessionKey[8]);
 BOOL cm_FindTokenEvent(afs_uuid_t uuid, char sessionKey[8]);
diff --git a/src/WINNT/afsd/cm_rpc95.h b/src/WINNT/afsd/cm_rpc95.h
new file mode 100644 (file)
index 0000000..0b5a63b
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#ifndef        __CM_RPC_H__
+#define __CM_RPC_H__
+
+/* Copied from declaration of GUID in RPCDCE.H */
+typedef struct afs_uuid {
+     unsigned long Data1;
+     unsigned short Data2;
+     unsigned short Data3;
+     unsigned char Data4[8];
+} afs_uuid_t;
+
+long AFSRPC_SetToken(
+     afs_uuid_t     uuid,
+     unsigned char  sessionKey[8]
+);
+
+long AFSRPC_GetToken(
+     afs_uuid_t     uuid,
+     unsigned char  sessionKey[8]
+);
+
+#endif /* __CM_RPC_H__ */
index 16bd46c..759a31f 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
 #include <winsock2.h>
+#include <nb30.h>
+#endif /* !DJGPP */
 #include <malloc.h>
 #include <string.h>
 #include <stdlib.h>
-#include <nb30.h>
 #include <osi.h>
 
 #include "afsd.h"
@@ -828,3 +830,27 @@ void cm_ReleaseSCache(cm_scache_t *scp)
        osi_assert(scp->refCount-- > 0);
        lock_ReleaseWrite(&cm_scacheLock);
 }
+
+/* just look for the scp entry to get filetype */
+/* doesn't need to be perfectly accurate, so locking doesn't matter too much */
+int cm_FindFileType(cm_fid_t *fidp)
+{
+        long hash;
+        cm_scache_t *scp;
+        
+        hash = CM_SCACHE_HASH(fidp);
+        
+        osi_assert(fidp->cell != 0);
+
+        lock_ObtainWrite(&cm_scacheLock);
+        for(scp=cm_hashTablep[hash]; scp; scp=scp->nextp) {
+                if (cm_FidCmp(fidp, &scp->fid) == 0) {
+                  /*scp->refCount++;*/
+                  /*cm_AdjustLRU(scp);*/
+                  lock_ReleaseWrite(&cm_scacheLock);
+                  return scp->fileType;
+                }
+        }
+        lock_ReleaseWrite(&cm_scacheLock);
+        return NULL;
+}
index 4d74dbd..aec2f97 100644 (file)
 #ifndef __CM_SCACHE_H_ENV__
 #define __CM_SCACHE_H_ENV__ 1
 
+#ifdef DJGPP
+#include "largeint95.h"
+#endif /* DJGPP */
+
 typedef struct cm_fid {
        unsigned long cell;
         unsigned long volume;
@@ -210,6 +214,9 @@ typedef struct cm_scache {
                                    (fidp)->unique))    \
                                        % cm_hashTableSize)
 
+#include "cm_conn.h"
+#include "cm_buf.h"
+
 extern cm_scache_t cm_fakeSCache;
 
 extern void cm_InitSCache(long);
index ffb2b7a..16672eb 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
 #include <winsock2.h>
+#include <nb30.h>
+#else
+#include <sys/socket.h>
+#endif /* !DJGPP */
 #include <stdlib.h>
 #include <malloc.h>
 #include <string.h>
 
 #include <osi.h>
 #include <rx/rx.h>
-#include <nb30.h>
 #include "afsd.h"
 
 osi_rwlock_t cm_serverLock;
index 7fce862..c0b357f 100644 (file)
 #ifndef __CM_SERVER_H_ENV__
 #define __CM_SERVER_H_ENV__ 1
 
+#ifndef DJGPP
 #include <winsock2.h>
+#else /* DJGPP */
+#include <netinet/in.h>
+#endif /* !DJGPP */
 #include <osi.h>
 
 /* pointed to by volumes and cells without holds; cm_serverLock is obtained
index 9a20e18..51803c3 100644 (file)
@@ -10,7 +10,9 @@
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
+#endif /* !DJGPP */
 #include <malloc.h>
 #include <string.h>
 
index 2fd367f..e18654a 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
+#include <winsock2.h>
+#endif /* !DJGPP */
 #include <string.h>
 #include <malloc.h>
-#include <winsock2.h>
 
 #include <osi.h>
 #include <rx/rx.h>
index e122436..440d34d 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
-#include <stddef.h>
 #include <winsock2.h>
+#endif /* !DJGPP */
+#include <stddef.h>
 #include <malloc.h>
 #include <string.h>
 #include <stdlib.h>
@@ -2178,6 +2180,10 @@ long cm_Rename(cm_scache_t *oldDscp, char *oldNamep, cm_scache_t *newDscp,
         * which makes the code a little verbose.
          */
        if (oldDscp == newDscp) {
+                /* check for identical names */
+                if (strcmp(oldNamep, newNamep) == 0)
+                        return CM_ERROR_RENAME_IDENTICAL;
+
                oneDir = 1;
                lock_ObtainMutex(&oldDscp->mx);
                cm_dnlcRemove(oldDscp, oldNamep);
index f71b30b..d4667b1 100644 (file)
@@ -38,6 +38,8 @@ typedef struct cm_lookupSearch {
         int hasTilde;
 } cm_lookupSearch_t;
 
+#include "cm_dir.h"
+
 typedef int (*cm_DirFuncp_t)(struct cm_scache *, struct cm_dirEntry *, void *,
        osi_hyper_t *entryOffsetp);
 
index 9487466..994e526 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
-#include <string.h>
-#include <malloc.h>
 #include <winsock2.h>
 #include <nb30.h>
+#else
+#include <sys/socket.h>
+#endif /* !DJGPP */
+#include <string.h>
+#include <malloc.h>
 #include <osi.h>
 #include <rx/rx.h>
 
diff --git a/src/WINNT/afsd/dosdefs95.h b/src/WINNT/afsd/dosdefs95.h
new file mode 100644 (file)
index 0000000..5c14377
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef DOSDEFS_H
+#define DOSDEFS_H
+
+/* dos_ptr is the phys. addr. accepted by farpeek/farpoke functions, i.e.,
+   dos_ptr = segment * 16 + offset */
+#define dos_ptr unsigned long
+
+/* get/set structure member of a struct in DOS memory */
+#define get_dos_member_b(T, ptr, memb) _farpeekb(_dos_ds, (ptr) + (dos_ptr)&(((T*)0)->memb))
+#define get_dos_member_w(T, ptr, memb) _farpeekw(_dos_ds, (ptr) + (dos_ptr)&(((T*)0)->memb))
+#define get_dos_member_l(T, ptr, memb) _farpeekl(_dos_ds, (ptr) + (dos_ptr)&(((T*)0)->memb))
+
+#define set_dos_member_b(T, ptr, memb, val) \
+                  _farpokeb(_dos_ds, (ptr) + (dos_ptr)&(((T*)0)->memb), val)
+#define set_dos_member_w(T, ptr, memb, val) \
+                  _farpokew(_dos_ds, (ptr) + (dos_ptr)&(((T*)0)->memb), val)
+#define set_dos_member_l(T, ptr, memb, val) \
+                  _farpokel(_dos_ds, (ptr) + (dos_ptr)&(((T*)0)->memb), val)
+
+typedef struct _filetime
+{
+  unsigned int dwLowDateTime;
+  unsigned int dwHighDateTime;
+} FILETIME;
+
+#define FILE_ACTION_ADDED               0x00000001   
+#define FILE_ACTION_REMOVED             0x00000002   
+#define FILE_ACTION_MODIFIED            0x00000003   
+#define FILE_ACTION_RENAMED_OLD_NAME    0x00000004   
+#define FILE_ACTION_RENAMED_NEW_NAME    0x00000005   
+
+#define FILE_NOTIFY_CHANGE_FILE_NAME    0x00000001   
+#define FILE_NOTIFY_CHANGE_DIR_NAME     0x00000002   
+#define FILE_NOTIFY_CHANGE_ATTRIBUTES   0x00000004   
+#define FILE_NOTIFY_CHANGE_SIZE         0x00000008   
+#define FILE_NOTIFY_CHANGE_LAST_WRITE   0x00000010   
+#define FILE_NOTIFY_CHANGE_LAST_ACCESS  0x00000020   
+#define FILE_NOTIFY_CHANGE_CREATION     0x00000040   
+#define FILE_NOTIFY_CHANGE_SECURITY     0x00000100   
+
+#define ULONG unsigned long
+#define USHORT unsigned short
+#define WCHAR wchar_t
+
+#define GetTickCount gettime_ms
+#define GetCurrentTime gettime_ms
+
+#define lstrcpy strcpy
+#define strcmpi stricmp
+#define lstrlen strlen
+#define _stricmp stricmp
+#define _strlwr strlwr
+#define _strupr strupr
+
+#endif
diff --git a/src/WINNT/afsd/dosutils95.c b/src/WINNT/afsd/dosutils95.c
new file mode 100644 (file)
index 0000000..2984916
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+/* functions for DJGPP to write to DOS memory or duplicate Win32 functions. */
+
+#include <stdio.h>
+#include <sys/farptr.h>
+#include <go32.h>
+#include <sys/time.h>
+#include "dosdefs95.h"
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+dos_memset(dos_ptr offset, int val, int size)
+{
+  int i;
+  
+  for (i = 0; i < size; i++)
+  {
+    _farpokeb(_dos_ds, offset++, val);
+  }
+}
+    
+char *dos_strcpy_get(char *str, unsigned int offset)
+{
+  register char a;
+  
+  while ((a = _farpeekb(_dos_ds, offset++)) != 0)
+    *str++ = a;
+  *str = 0;
+
+  return str;
+}
+
+char *dos_strncpy_get(char *str, unsigned int offset, int len)
+{
+  register char a;
+  register int n=0;
+  
+  while ((a = _farpeekb(_dos_ds, offset++)) != 0 && n++ < len)
+    *str++ = a;
+  *str = 0;
+
+  return str;
+}
+
+dos_ptr dos_strcpy_put(dos_ptr offset, char *str)
+{
+  char a;
+  
+  while ((a = *str++) != 0)
+    _farpokeb(_dos_ds, offset++, a);
+  _farpokeb(_dos_ds, offset, 0);
+
+  return offset;
+}
+
+dos_ptr dos_strncpy_put(dos_ptr offset, char *str, int len)
+{
+  register char a;
+  register int n=0;
+  
+  while ((a = *str++) != 0 && n++ < len)
+    _farpokeb(_dos_ds, offset++, a);
+  _farpokeb(_dos_ds, offset, 0);
+
+  return offset;
+}
+
+dos_ptr dos_strrchr(dos_ptr offset, char c)
+{
+  dos_ptr temp = 0;
+  char a;
+  
+  while ((a = _farpeekb(_dos_ds, offset++)) != 0)
+  {
+    if (a == c) temp = offset-1;
+  }
+
+  return temp;
+}
+
+int dos_strcmp(unsigned char *str, dos_ptr offset)
+{
+  register unsigned char a, b;
+  
+  while (((a = *str++) == (b = _farpeekb(_dos_ds, offset++))) && a && b);
+  return a-b;
+}
+
+int dos_strncmp(unsigned char *str, dos_ptr offset, int len)
+{
+  register unsigned char a, b;
+  register int i=0;
+  
+  while (i++ < len && ((a = *str++) == (b = _farpeekb(_dos_ds, offset++))) && a && b);
+  return a-b;
+}
+
+int dos_strlen(dos_ptr offset)
+{
+  int len=0;
+  
+  while (_farpeekb(_dos_ds, offset++))
+    len++;
+
+  return len;
+}
+
+
+int sub_time(struct timeval a, struct timeval b)
+{
+  int n = a.tv_sec - b.tv_sec;
+  n *= 1000000;
+  n += a.tv_usec - b.tv_usec;
+  return n / 1000;
+}
+
+int tm_to_ms(struct timeval t)
+{
+  int n = t.tv_sec * 1000;
+  n += t.tv_usec / 1000;
+  return n;
+}
+
+int gettime_ms()
+{
+  struct timeval t;
+  int n = t.tv_sec * 1000;
+
+  gettimeofday(&t, NULL);
+  n += t.tv_usec / 1000;
+  return n;
+}
+  
+int gettime_us()
+{
+  struct timeval t;
+  int n;
+
+  gettimeofday(&t, NULL);
+  n = t.tv_sec * 1000000;
+  n += t.tv_usec;
+  return n;
+}
+
+int GetPrivateProfileString(char *sect, char *key, char *def,
+                            char *buf, int len, char *file)
+{
+  char s[256];
+  char skey[128];
+  int nchars=0;
+  int amt;
+  int offset;
+  char sectstr[256];
+  char *p;
+  FILE *f = fopen(file, "r");
+  if (!f) return 0;
+
+  sprintf(sectstr, "[%s]", sect);
+  while (1)
+  {
+    fgets(s, 256, f);
+    if (feof(f)) break;
+
+    /* look for section names */
+    if (s[0] != '[')
+      continue;
+    
+    /* if sect is NULL, copy all section names */
+    if (!sect)
+    {
+      amt = MIN(strlen(s)+1, len-1);
+      strncpy(buf, s, amt-1);
+      buf[amt] = 0;
+      len -= amt;
+      buf += amt;
+      nchars += amt;
+      continue;
+    }
+
+    /* continue if non-matching section name */
+    if (sect && strnicmp(s+1, sect, strlen(sect)) != 0)
+      continue;
+
+    /* else we have the correct section */
+
+    while (len > 0)
+    {
+      fgets(s, 256, f);
+      if (feof(f)) break;
+      
+      /* get the key part */
+      strcpy(skey, s);
+      p = strrchr(skey, '=');
+      if (!p) { fclose(f); return 0; }
+      *p = 0;
+      
+      /* continue if key doesn't match */
+      if (key && stricmp(skey, key) != 0)
+        continue;
+
+      /* if NULL key, copy key names */
+      if (!key)
+      {
+        amt = MIN(strlen(skey)+1, len-2);
+        strncpy(buf, skey, amt);
+        buf[amt] = 0;
+        buf[amt+1] = 0;   /* final trailing NULL */
+        len -= amt;
+        buf += amt;
+        nchars += amt;
+        continue;
+      }
+        
+      /* discard key= and newline */
+      offset = strlen(key) + 1;
+      amt = MIN(strlen(s+offset)-1, len-1);
+      strncpy(buf, s+offset, amt);
+      buf[amt] = 0;
+      len -= amt;
+      buf += amt;
+      nchars += amt;
+    }
+  }
+  
+  if (nchars == 0)
+  {
+    if (def)
+    {
+      strcpy(buf, def);
+      nchars = strlen(def);
+    }
+  }
+
+  fclose(f);
+  return nchars;
+}
+
+int WritePrivateProfileString(char *sect, char *key, char *str, char *file)
+{
+  char tmpfile[256], s[256], sectstr[256];
+  int found = 0;
+  char *p;
+  FILE *fr = fopen(file, "r");
+  FILE *fw = fopen(tmpfile, "w");
+
+  strcpy(tmpfile, file);
+  p = strrchr(tmpfile, '.');
+  *p = 0;
+  strcat(tmpfile, ".tmp");   /* change extension to .tmp */
+  
+  sprintf(sectstr, "[%s]", sect);
+  while (1)
+  {
+    fgets(s, 256, fr);
+    if (feof(fr)) break;
+
+    fputs(s, fw);
+    
+    /* look for section names */
+    if (found || s[0] != '[')
+    {
+      continue;
+    }
+  
+    if (stricmp(s, sectstr) == 0)
+    {
+      /* found section, print new item */
+      found = 1;
+      strcpy(s, key);
+      strcat(s, "=");
+      strcat(s, str);
+      strcat(s, "\n");
+      fputs(s, fw);
+    }
+  }
+  fclose(fw);
+  fclose(fr);
+
+  /* delete old file */
+  remove(file);
+  
+  /* rename .tmp */
+  rename(tmpfile, file);
+  
+  return found;
+}
index 2bdcabc..6e09e1d 100644 (file)
@@ -18,7 +18,9 @@
 #include <afs/prs_fs.h>
 #include <afs/pioctl_nt.h>
 
+#ifndef _MFC_VER
 #include <winsock2.h>
+#endif
 
 /* Fake error code since NT errno.h doesn't define it */
 #include <afs/errmap_nt.h>
diff --git a/src/WINNT/afsd/largeint95.c b/src/WINNT/afsd/largeint95.c
new file mode 100644 (file)
index 0000000..19c2c4e
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+/* Large integer support for DJGPP */
+
+#include <stdlib.h>
+#include "largeint95.h"
+
+LARGE_INTEGER LargeIntegerAdd(LARGE_INTEGER a, LARGE_INTEGER b)
+{
+  LARGE_INTEGER c;
+  long long *c1 = (long long *) &c;
+  long long *a1 = (long long *) &a;
+  long long *b1 = (long long *) &b;
+  *c1 = *a1 + *b1;
+  return c;
+}
+  
+LARGE_INTEGER LargeIntegerSubtract(LARGE_INTEGER a, LARGE_INTEGER b)
+{
+  LARGE_INTEGER c;
+  long long *c1 = (long long *) &c;
+  long long *a1 = (long long *) &a;
+  long long *b1 = (long long *) &b;
+  *c1 = *a1 - *b1;
+  return c;
+}
+  
+LARGE_INTEGER ConvertLongToLargeInteger(unsigned long a)
+{
+  LARGE_INTEGER n;
+
+  n.LowPart = a;
+  n.HighPart = 0;
+  return n;
+}
+
+LARGE_INTEGER LargeIntegerMultiplyLongByLong(unsigned long a, unsigned long b)
+{
+  LARGE_INTEGER c;
+  long long *c1 = (long long *) &c;
+
+  *c1 = (long long) a * (long long) b;
+  return c;
+}
+  
+LARGE_INTEGER LargeIntegerMultiplyByLong(LARGE_INTEGER a, unsigned long b)
+{
+  LARGE_INTEGER c;
+  long long *c1 = (long long *) &c;
+  long long *a1 = (long long *) &a;
+
+  *c1 = *a1 * (long long) b;
+  return c;
+}
+  
+unsigned long LargeIntegerDivideByLong(LARGE_INTEGER a, unsigned long b)
+{
+  lldiv_t q;
+  long long *a1 = (long long *) &a;
+
+  q = lldiv(*a1, (long long) b);
+  return (unsigned long) q.quot;
+}
+
+#if 0
+LARGE_INTEGER LargeIntegerAdd(LARGE_INTEGER a, LARGE_INTEGER b)
+{
+  LARGE_INTEGER c;
+
+  c.LowPart = a.LowPart + b.LowPart;
+  c.HighPart = a.HighPart + b.HighPart;
+
+  /* not sure how to do a real carry */
+  if (c.LowPart < a.LowPart)
+    c.HighPart++;
+
+  return c;
+}
+
+LARGE_INTEGER LargeIntegerSubtract(LARGE_INTEGER a, LARGE_INTEGER b)
+{
+  LARGE_INTEGER c;
+
+  c.LowPart = a.LowPart - b.LowPart;
+  c.HighPart = a.HighPart - b.HighPart;
+
+  /* borrow */
+  if (c.LowPart > a.LowPart)
+    c.HighPart--;
+
+  return c;
+}
+
+__inline__ unsigned long mult32(unsigned long a, unsigned long b,
+                                unsigned long *ov)
+{
+  unsigned long p, o;
+  
+  /* multiply low part and save the overflow bits */
+  __asm__ __volatile__ ("movl %2, %%eax\n
+                         mull %3, %%eax\n
+                         movl %%eax, %0\n
+                         movl %%edx, %1"
+                        : "=g" (p), "=g" (o)
+                        : "g" (a), "g" (b)
+                        : "ax", "dx", "memory"
+                        );
+  *ov = o;
+  return p;
+}
+
+__inline__ unsigned long div32(unsigned long a, unsigned long b,
+                               unsigned long *rem)
+{
+  unsigned long q, r;
+  
+  /* multiply low part and save the overflow bits */
+  __asm__ __volatile__ ("movl %2, %%eax\n
+                         divl %3, %%eax\n
+                         movl %%eax, %0\n
+                         movl %%edx, %1"
+                        : "=g" (q), "=g" (r)
+                        : "g" (a), "g" (b)
+                        : "ax", "dx", "memory"
+                        );
+  *rem = r;
+  return q;
+}
+
+LARGE_INTEGER LargeIntegerMultiplyLongByLong(unsigned long a, unsigned long b)
+{
+  LARGE_INTEGER prod;
+
+  prod.LowPart = mult32(a, b, &prod.HighPart);
+  return prod;
+}
+  
+LARGE_INTEGER LargeIntegerMultiplyByLong(LARGE_INTEGER a, unsigned long b)
+{
+  LARGE_INTEGER prod;
+  unsigned long x, prodl, prodh, ovl, ovh;
+  
+  /* multiply low part and save the overflow bits */
+  prod.LowPart = mult32(a.LowPart, b, &ovl);
+  
+  /* multiply high part */
+  prod.HighPart = mult32(a.HighPart, b, &ovh);
+  
+  /* add overflow from low part */
+  prod.HighPart += ovl;
+
+  return prod;
+}
+  
+unsigned long LargeIntegerDivideByLong(LARGE_INTEGER a, unsigned long b, unsigned long *rem)
+{
+  unsigned long n, r, q; 
+  LARGE_INTEGER t;
+  
+  if (b == 0) { return 0; }
+  if (b == 1) { *rem = 0; return a.LowPart; }
+
+  n = div32(a.LowPart, b, &r);
+  if (a.HighPart == 0)
+  {
+    *rem = r;
+    return n;
+  }
+  else
+  {
+    q = div32(0xffffffff-b+1, b, &r);
+    q++;
+    n += q * a.HighPart;
+    n += LargeIntegerDivideByLong(LargeIntegerMultiplyLongByLong(r, a.HighPart), b, rem);
+    return n;
+  }
+}
+#endif
+  
+#if 0
+int LargeIntegerGreaterThan(LARGE_INTEGER a, LARGE_INTEGER b)
+{
+  if (a.HighPart > b.HighPart) return 1;
+  else if (a.HighPart == b.HighPart && a.LowPart > b.LowPart) return 1;
+  else return 0;
+}
+
+int LargeIntegerGreaterThanOrEqualTo(LARGE_INTEGER a, LARGE_INTEGER b)
+{
+  if (a.HighPart > b.HighPart) return 1;
+  else if (a.HighPart == b.HighPart && a.LowPart >= b.LowPart) return 1;
+  else return 0;
+}
+  
+int LargeIntegerEqualTo(LARGE_INTEGER a, LARGE_INTEGER b)
+{
+  if (a.HighPart == b.HighPart && a.LowPart == b.LowPart) return 1;
+  else return 0;
+}
+
+int LargeIntegerGreaterOrEqualToZero(LARGE_INTEGER a)
+{
+  return ((a.HighPart & 0x8fffffff) ? 0 : 1);
+}
+
+int LargeIntegerLessThanZero(LARGE_INTEGER a)
+{
+  return ((a.HighPart & 0x8fffffff) ? 1 : 0);
+}
+#endif
diff --git a/src/WINNT/afsd/largeint95.h b/src/WINNT/afsd/largeint95.h
new file mode 100644 (file)
index 0000000..f55b411
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef LARGEINT_H
+#define LARGEINT_H
+
+typedef struct {
+  unsigned long LowPart;
+  unsigned long HighPart;
+} LARGE_INTEGER;
+
+LARGE_INTEGER LargeIntegerAdd(LARGE_INTEGER a, LARGE_INTEGER b);
+LARGE_INTEGER LargeIntegerSubtract(LARGE_INTEGER a, LARGE_INTEGER b);
+/*int LargeIntegerGreaterThan(LARGE_INTEGER a, LARGE_INTEGER b);
+int LargeIntegerGreaterThanOrEqualTo(LARGE_INTEGER a, LARGE_INTEGER b);
+int LargeIntegerEqualTo(LARGE_INTEGER a, LARGE_INTEGER b);
+int LargeIntegerGreaterOrEqualToZero(LARGE_INTEGER a);
+int LargeIntegerLessThanZero(LARGE_INTEGER a);*/
+LARGE_INTEGER ConvertLongToLargeInteger(unsigned long a);
+LARGE_INTEGER LargeIntegerMultiplyByLong(LARGE_INTEGER a, unsigned long b);
+unsigned long LargeIntegerDivideByLong(LARGE_INTEGER a, unsigned long b);
+
+#define LargeIntegerGreaterThan(a, b) \
+ ((a).HighPart > (b).HighPart || \
+  ((a).HighPart == (b).HighPart && (a).LowPart > (b).LowPart))
+
+#define LargeIntegerGreaterThanOrEqualTo(a, b) \
+ ((a).HighPart > (b).HighPart || \
+  ((a).HighPart == (b).HighPart && (a).LowPart >= (b).LowPart))
+  
+#define LargeIntegerLessThan(a, b) \
+ ((a).HighPart < (b).HighPart || \
+  ((a).HighPart == (b).HighPart && (a).LowPart < (b).LowPart))
+
+#define LargeIntegerLessThanOrEqualTo(a, b) \
+ ((a).HighPart < (b).HighPart || \
+  ((a).HighPart == (b).HighPart && (a).LowPart <= (b).LowPart))
+
+#define LargeIntegerEqualTo(a, b) \
+  ((a).HighPart == (b).HighPart && (a).LowPart == (b).LowPart)
+  
+#define LargeIntegerGreaterOrEqualToZero(a) ((a).HighPart >= 0)
+  
+#define LargeIntegerLessThanZero(a) ((a).HighPart < 0)
+
+#define LargeIntegerNotEqualToZero(a) ((a).HighPart || (a).LowPart)
+
+#endif
diff --git a/src/WINNT/afsd/netbios95.c b/src/WINNT/afsd/netbios95.c
new file mode 100644 (file)
index 0000000..bc86a3c
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+/* Netbios function for DJGPP: calls interrupt 5Ch for Netbios function.
+   NCB and buffer space must be in DOS memory (below 1MB). */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dpmi.h>
+#include <go32.h>
+#include "dosdefs95.h"
+#include "netbios95.h"
+
+extern int handler_seg, handler_off;
+
+int Netbios(NCB *Ncb, dos_ptr dos_ncb)
+{
+  __dpmi_regs regs;
+  int asynch = 1;
+  dos_ptr oldncb_buffer;
+
+#if 1
+  if (Ncb->ncb_command == NCBRESET ||
+      Ncb->ncb_command == NCBCANCEL ||
+      Ncb->ncb_command == NCBUNLINK ||
+      Ncb->ncb_command == NCBADDNAME ||
+      Ncb->ncb_command == NCBENUM ||
+      Ncb->ncb_command == NCBDELNAME) /* temp */
+    asynch = 0;
+#else
+  if (1)
+    asynch = 0;
+#endif
+  else
+    /* set to asynchronous */
+    Ncb->ncb_command |= ASYNCH;
+
+  /* adjust ncb_buffer pointer to be a segment:zero-offset pointer
+     for __dpmi_int */
+  oldncb_buffer = Ncb->ncb_buffer;
+  Ncb->ncb_buffer = Ncb->ncb_buffer << 12;
+
+  /*if (asynch)
+    Ncb->ncb_post = (handler_seg << 16) | handler_off;*/
+
+  /* copy to DOS space */
+  dosmemput(Ncb, sizeof(NCB), dos_ncb);
+
+  /* set address of NCB in registers */
+  memset(&regs, 0, sizeof(regs));
+  regs.d.ebx = 0;
+  regs.x.ds = regs.x.es = dos_ncb/16;
+
+  __dpmi_int(0x5c,&regs);
+  /*dosmemget(__tb, sizeof(NCB), Ncb);*/
+  
+  if (asynch)
+    IOMGR_NCBSelect(Ncb, dos_ncb, NULL);
+
+  /* undo the change to ncb_buffer */
+  Ncb->ncb_buffer = oldncb_buffer;
+
+  return regs.x.ax;
+}
+
diff --git a/src/WINNT/afsd/netbios95.h b/src/WINNT/afsd/netbios95.h
new file mode 100644 (file)
index 0000000..c70c855
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#ifndef NETBIOS_H
+#define NETBIOS_H
+
+#define BYTE char
+#define WORD short
+
+#define NCBNAMSZ        16    /* absolute length of a net name           */
+#define MAX_LANA       254    /* lana's in range 0 to MAX_LANA inclusive */
+
+#define MAX_COMPUTERNAME_LENGTH 15
+
+
+#define UCHAR unsigned char
+#define PUCHAR unsigned char *
+#define WORD short
+
+#include "osithrd95.h"
+
+typedef struct _NCB {
+    UCHAR ncb_command;
+    UCHAR ncb_retcode;
+    UCHAR ncb_lsn;
+    UCHAR ncb_num;
+    unsigned int ncb_buffer;
+    WORD ncb_length;
+    UCHAR ncb_callname[NCBNAMSZ];
+    UCHAR ncb_name[NCBNAMSZ];
+    UCHAR ncb_rto;
+    UCHAR ncb_sto;
+    int (*ncb_post)();
+    UCHAR ncb_lana_num;
+    UCHAR ncb_cmd_cplt;
+    UCHAR ncb_reserve[10];
+    UCHAR ncb_reserve2[4];
+    EVENT_HANDLE ncb_event;
+} NCB, *PNCB;
+
+
+#define NCBCALL 0x10
+#define NCBLISTEN 0x11
+#define NCBHANGUP 0x12
+#define NCBSEND 0x14
+#define NCBRECV 0x15
+#define NCBRECVANY 0x16
+#define NCBCHAINSEND 0x17
+#define NCBDGSEND 0x20
+#define NCBDGRECV 0x21
+#define NCBDGSENDBC 0x22
+#define NCBDGRECVBC 0x23
+#define NCBADDNAME 0x30
+#define NCBDELNAME 0x31
+#define NCBRESET 0x32
+#define NCBASTAT 0x33
+#define NCBSSTAT 0x34
+#define NCBCANCEL 0x35
+#define NCBADDGRNAME 0x36
+#define NCBENUM 0x37
+#define NCBUNLINK 0x70
+#define NCBSENDNA 0x71
+#define NCBCHAINSENDNA 0x72
+#define NCBLANSTALERT 0x73
+#define NCBACTION 0x77
+#define NCBFINDNAME 0x78
+#define NCBTRACE 0x79
+#define ASYNCH 0x80
+
+
+#define NRC_GOODRET 0x00
+#define NRC_BUFLEN 0x01
+#define NRC_ILLCMD 0x03
+#define NRC_CMDTMO 0x05
+#define NRC_INCOMP 0x06
+#define NRC_BADDR 0x07
+#define NRC_SNUMOUT 0x08
+#define NRC_NORES 0x09
+#define NRC_SCLOSED 0x0a
+#define NRC_CMDCAN 0x0b
+#define NRC_DUPNAME 0x0d
+#define NRC_NAMTFUL 0x0e
+#define NRC_ACTSES 0x0f
+#define NRC_LOCTFUL 0x11
+#define NRC_REMTFUL 0x12
+#define NRC_ILLNN 0x13
+#define NRC_NOCALL 0x14
+#define NRC_NOWILD 0x15
+#define NRC_INUSE 0x16
+#define NRC_NAMERR 0x17
+#define NRC_SABORT 0x18
+#define NRC_NAMCONF 0x19
+#define NRC_IFBUSY 0x21
+#define NRC_TOOMANY 0x22
+#define NRC_BRIDGE 0x23
+#define NRC_CANOCCR 0x24
+#define NRC_CANCEL 0x26
+#define NRC_DUPENV 0x30
+#define NRC_ENVNOTDEF 0x34
+#define NRC_OSRESNOTAV 0x35
+#define NRC_MAXAPPS 0x36
+#define NRC_NOSAPS 0x37
+#define NRC_NORESOURCES 0x38
+#define NRC_INVADDRESS 0x39
+#define NRC_INVDDID 0x3B
+#define NRC_LOCKFAIL 0x3C
+#define NRC_OPENERR 0x3f
+#define NRC_SYSTEM 0x40
+#define NRC_PENDING 0xff
+
+#endif  /* NETBIOS_H */
diff --git a/src/WINNT/afsd/queue95.c b/src/WINNT/afsd/queue95.c
new file mode 100644 (file)
index 0000000..06f6454
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+/* queue.c
+ *
+ * Generic queue for use with Windows 95/DJGPP disk cache
+ *
+ ************************************************************************/
+
+#ifdef DISKCACHE95
+
+#define NULL 0
+#include "queue95.h"
+#include <stdio.h>
+
+void QInit(Queue *queue)
+{
+  queue->head = NULL;
+  queue->tail = NULL;
+  queue->currpos = NULL;
+}
+
+void QAddT(Queue *queue, QLink* node, int ord)
+{
+  /*QLink* node = new QLink;*/
+
+  /*node->item = x;*/
+  node->ord = ord;
+  node->next = NULL;
+  node->prev = NULL;
+  if (!queue->tail)
+    queue->head = queue->tail = node;
+  else {
+    queue->tail->next = node;
+    queue->tail = node;
+    node->prev = queue->tail;
+  }
+  queue->size++;
+}
+
+void QAddH(Queue *queue, QLink *node, int ord)
+{
+  node->ord = ord;
+  node->next = NULL;
+  node->prev = NULL;
+  if (!queue->head)
+    queue->head = queue->tail = node;
+  else {
+    node->next = queue->head;
+    queue->head->prev = node;
+    queue->head = node;
+  }
+  queue->size++;
+}
+           
+void QAddOrd(Queue *queue, QLink *node, int ord)
+{
+  /*QLink<T>* node = new QLink<T>;*/
+  QLink* p, *prev;
+
+  node->ord = ord;
+  node->next = NULL;
+  node->prev = NULL;
+  if (!queue->tail)
+    queue->head = queue->tail = node;
+  else {
+    p = queue->head;
+    while (p && ord >= p->ord) {    /* add towards tail end if equals found */
+      prev = p;
+      p = p->next;
+    }
+    if (p == queue->head) {
+      QAddH(queue, node, ord);
+    }
+    else if (p == NULL) {
+      QAddT(queue, node, ord);
+    }
+    else {
+      node->next = p;
+      node->prev = prev;
+      prev->next = node;
+    }
+  }
+  queue->size++;
+}
+
+QLink* QServe(Queue *queue)
+{
+  QLink *n = queue->head;
+
+  if (!queue->head) return NULL;
+  if (queue->head == queue->tail)
+    queue->head = queue->tail = NULL;
+  else
+    queue->head = n->next;
+  queue->size--;
+  return n;
+}
+
+void QMoveToTail(Queue *queue, QLink *n, int ord)
+{
+  QRemove(queue, n);
+  QAddT(queue, n, ord);
+}
+
+void QRemove(Queue *queue, QLink *n)
+{
+  /*QLink* n2 = NULL;*/
+
+  if (!queue->head) return;
+  /*while(n && n != x) {
+    n2 = n;
+    n = n->next;
+    }*/
+  if (n == queue->currpos) {
+    if (n == queue->head) queue->currpos = n->next;
+    if (n == queue->tail) queue->currpos = n->prev;
+    if (n->prev) queue->currpos = n->prev;
+  }
+
+  if (n->prev)
+  {
+    /*assert(n->prev->next == n);*/
+    n->prev->next = n->next;
+  }
+  else
+    queue->head = n->next;
+
+  if (n->next)
+  {
+    /*assert(n->next->prev == n);*/
+    n->next->prev = n->prev;
+  }
+  else
+    queue->tail = n->prev;
+  
+  queue->size--;
+}
+
+QLink *QCurrent(Queue *queue)
+{
+  /*if (currpos) return currpos->item;
+    else return NULL;*/
+  return queue->currpos;
+}
+
+void QIterate(Queue *queue)
+{
+  QLink* node;
+
+  node = queue->head;
+  while (node) {
+    printf("node=%x, ord=%f\n", node, node->ord);
+    node = node->next;
+  }
+  fflush(stdout);
+}
+
+#endif /* DISKCACHE95 */
diff --git a/src/WINNT/afsd/queue95.h b/src/WINNT/afsd/queue95.h
new file mode 100644 (file)
index 0000000..8bbb8f4
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+/* queue.h
+ *
+ * Class declaration for generic queue for use with Windows 95/DJGPP client
+ * disk cache
+ *
+ ***************************************************************************/
+
+#ifndef _QUEUE_H
+#define _QUEUE_H
+
+/* offset of member m in struct T */
+#define OFFSETOF(T, m) ((USHORT) &(((T *) NULL)->m))
+
+/* get pointer to parent struct T containing member m at address p */
+#define MEM_TO_OBJ(T, m, p) ((char *)(p) - OFFSETOF(T, m))
+
+typedef struct _QLink {
+  struct _QLink *next;
+  struct _QLink *prev;
+  int ord;
+} QLink;
+
+typedef struct _Queue {
+  QLink *head;
+  QLink *tail;
+  int size;
+  QLink *currpos;
+} Queue;
+
+/* add item to tail of queue */
+void QAddT(Queue *queue, QLink* node, int ord);
+
+/* add item to head of queue */
+void QAddH(Queue *queue, QLink *node, int ord);
+
+/* add item based on order value */
+void QAddOrd(Queue *queue, QLink *node, int ord);
+
+/* remove and return head of queue */
+QLink* QServe(Queue *queue);
+
+/* move item to tail of queue */
+void QMoveToTail(Queue *queue, QLink *x, int ord);
+
+/* remove item from queue */
+void QRemove(Queue *queue, QLink* x);
+
+/* return current position */
+QLink *QCurrent(Queue *queue);
+
+/* print out list of queued items */
+void QIterate(Queue *queue);
+
+#endif
index 6249535..171f936 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
+#else
+#include <sys/timeb.h>
+#include <tzfile.h>
+#endif /* !DJGPP */
 #include <stddef.h>
 #include <stdlib.h>
 #include <malloc.h>
@@ -35,6 +40,9 @@ char *loggedOutName = NULL;
 smb_user_t *loggedOutUserp = NULL;
 unsigned long loggedOutTime;
 int loggedOut = 0;
+#ifdef DJGPP
+int smbShutdownFlag = 0;
+#endif /* DJGPP */
 
 int smb_LogoffTokenTransfer;
 unsigned long smb_LogoffTransferTimeout;
@@ -55,6 +63,7 @@ osi_rwlock_t smb_globalLock;
 osi_rwlock_t smb_rctLock;
 
 unsigned char smb_LANadapter;
+unsigned char smb_sharename[NCBNAMSZ+1] = {0};
 
 /* for debugging */
 long smb_maxObsConcurrentCalls=0;
@@ -70,20 +79,26 @@ int smb_NumServerThreads;
 int numNCBs, numSessions;
 
 #define NCBmax 100
-HANDLE NCBavails[NCBmax], NCBevents[NCBmax];
-HANDLE **NCBreturns;
+EVENT_HANDLE NCBavails[NCBmax], NCBevents[NCBmax];
+EVENT_HANDLE **NCBreturns;
 DWORD NCBsessions[NCBmax];
 NCB *NCBs[NCBmax];
 struct smb_packet *bufs[NCBmax];
 
 #define Sessionmax 100
-HANDLE SessionEvents[Sessionmax];
+EVENT_HANDLE SessionEvents[Sessionmax];
 unsigned short LSNs[Sessionmax];
 BOOL dead_sessions[Sessionmax];
 
 /* for raw I/O */
 osi_mutex_t smb_RawBufLock;
+#ifdef DJGPP
+#define SMB_RAW_BUFS 4
+dos_ptr smb_RawBufs;
+int smb_RawBufSel[SMB_RAW_BUFS];
+#else
 char *smb_RawBufs;
+#endif /* DJGPP */
 
 #define RAWTIMEOUT INFINITE
 
@@ -92,7 +107,11 @@ typedef struct raw_write_cont {
        long code;
        osi_hyper_t offset;
        long count;
+#ifndef DJGPP
        char *buf;
+#else
+        dos_ptr buf;
+#endif /* DJGPP */
        int writeMode;
        long alreadyWritten;
 } raw_write_cont_t;
@@ -105,8 +124,10 @@ smb_dirSearch_t *smb_lastDirSearchp;
 /* global state about V3 protocols */
 int smb_useV3;         /* try to negotiate V3 */
 
+#ifndef DJGPP
 /* MessageBox or something like it */
 int (WINAPI *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
+#endif /* DJGPP */
 
 /* GMT time info:
  * Time in Unix format of midnight, 1/1/1970 local time.
@@ -126,6 +147,18 @@ smb_waitingLock_t *smb_allWaitingLocks;
 /* forward decl */
 void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
        NCB *ncbp, raw_write_cont_t *rwcp);
+void smb_NetbiosInit();
+extern char cm_HostName[];
+#ifdef DJGPP
+extern char cm_confDir[];
+#endif
+
+#ifdef DJGPP
+#define LPTSTR char *
+#define GetComputerName(str, sizep) \
+       strcpy((str), cm_HostName); \
+       *(sizep) = strlen(cm_HostName)
+#endif /* DJGPP */
 
 /*
  * Demo expiration
@@ -176,6 +209,7 @@ static int ExtractBits(WORD bits, short start, short len)
         return (int)num;
 }
 
+#ifndef DJGPP
 void ShowUnixTime(char *FuncName, long unixTime)
 {
         FILETIME ft;
@@ -201,7 +235,9 @@ void ShowUnixTime(char *FuncName, long unixTime)
                 osi_Log1(afsd_logp, "%s", osi_LogSaveString(afsd_logp, msg));
         }
 }
+#endif /* DJGPP */
 
+#ifndef DJGPP
 /* Determine if we are observing daylight savings time */
 void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
 {
@@ -244,6 +280,19 @@ void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
        */
        *pDST = localDST.wHour != local.wHour;
 }
+#else
+/* Determine if we are observing daylight savings time */
+void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
+{
+  struct timeb t;
+
+  ftime(&t);
+  *pDST = t.dstflag;
+  *pDstBias = -60;    /* where can this be different? */
+  *pBias = t.timezone;
+}
+#endif /* DJGPP */
 
 void CompensateForSmbClientLastWriteTimeBugs(long *pLastWriteTime)
 {
@@ -303,6 +352,8 @@ smb_CalculateNowTZ()
 
        smb_NowTZ = seconds;
 }
+
+#ifndef DJGPP
 void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, long unixTime)
 {
        struct tm *ltp;
@@ -342,7 +393,29 @@ void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, long unixTime)
 
        SystemTimeToFileTime(&stm, largeTimep);
 }
+#else /* DJGPP */
+void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, long unixTime)
+{
+  /* unixTime: seconds since 1/1/1970 00:00:00 GMT */
+  /* FILETIME: 100ns intervals since 1/1/1601 00:00:00 ??? */
+  LARGE_INTEGER *ft = (LARGE_INTEGER *) largeTimep;
+  LARGE_INTEGER ut;
+  int leap_years = 89;   /* leap years betw 1/1/1601 and 1/1/1970 */
+
+  /* set ft to number of 100ns intervals betw 1/1/1601 and 1/1/1970 GMT */
+  *ft = ConvertLongToLargeInteger(((EPOCH_YEAR-1601) * 365 + leap_years)
+                                   * 24 * 60);
+  *ft = LargeIntegerMultiplyByLong(*ft, 60);
+  *ft = LargeIntegerMultiplyByLong(*ft, 10000000);
+
+  /* add unix time */
+  ut = ConvertLongToLargeInteger(unixTime);
+  ut = LargeIntegerMultiplyByLong(ut, 10000000);
+  *ft = LargeIntegerAdd(*ft, ut);
+}
+#endif /* !DJGPP */
 
+#ifndef DJGPP
 void smb_UnixTimeFromLargeSearchTime(long *unixTimep, FILETIME *largeTimep)
 {
        SYSTEMTIME stm;
@@ -365,6 +438,28 @@ void smb_UnixTimeFromLargeSearchTime(long *unixTimep, FILETIME *largeTimep)
        *unixTimep = mktime(&lt);
        _timezone = save_timezone;
 }
+#else /* DJGPP */
+void smb_UnixTimeFromLargeSearchTime(long *unixTimep, FILETIME *largeTimep)
+{
+  /* unixTime: seconds since 1/1/1970 00:00:00 GMT */
+  /* FILETIME: 100ns intervals since 1/1/1601 00:00:00 GMT? */
+  LARGE_INTEGER *ft = (LARGE_INTEGER *) largeTimep;
+  LARGE_INTEGER a;
+  int leap_years = 89;
+
+  /* set to number of 100ns intervals betw 1/1/1601 and 1/1/1970 */
+  a = ConvertLongToLargeInteger(((EPOCH_YEAR-1601) * 365 + leap_years) * 24 * 60
+);
+  a = LargeIntegerMultiplyByLong(a, 60);
+  a = LargeIntegerMultiplyByLong(a, 10000000);
+
+  /* subtract it from ft */
+  a = LargeIntegerSubtract(*ft, a);
+
+  /* divide down to seconds */
+  *unixTimep = LargeIntegerDivideByLong(a, 10000000);
+}
+#endif /* !DJGPP */
 
 void smb_SearchTimeFromUnixTime(long *dosTimep, long unixTime)
 {
@@ -373,7 +468,7 @@ void smb_SearchTimeFromUnixTime(long *dosTimep, long unixTime)
         int dosTime;
         struct tm localJunk;
 
-       ltp = localtime(&unixTime);
+       ltp = localtime((time_t*) &unixTime);
 
        /* if we fail, make up something */
         if (!ltp) {
@@ -418,7 +513,12 @@ void smb_DosUTimeFromUnixTime(long *dosUTimep, long unixTime)
 
 void smb_UnixTimeFromDosUTime(long *unixTimep, long dosTime)
 {
+#ifndef DJGPP
        *unixTimep = dosTime + smb_localZero;
+#else /* DJGPP */
+        /* dosTime seems to be already adjusted for GMT */
+       *unixTimep = dosTime;
+#endif /* !DJGPP */
 }
 
 smb_vc_t *smb_FindVC(unsigned short lsn, int flags)
@@ -665,7 +765,7 @@ retry:
                 lock_InitializeMutex(&fidp->mx, "fid_t mutex");
                 fidp->fid = fid;
                fidp->curr_chunk = fidp->prev_chunk = -2;
-               fidp->raw_write_event = CreateEvent(NULL, FALSE, TRUE, NULL);
+               fidp->raw_write_event = thrd_CreateEvent(NULL, FALSE, TRUE, NULL);
                 if (newFid) {
                        vcp->fidCounter = fid+1;
                         if (vcp->fidCounter == 0) vcp->fidCounter = 1;
@@ -689,7 +789,7 @@ void smb_ReleaseFID(smb_fid_t *fidp)
                if (!(fidp->flags & SMB_FID_IOCTL))
                        scp = fidp->scp;
                osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
-               CloseHandle(fidp->raw_write_event);
+               thrd_CloseHandle(fidp->raw_write_event);
 
                /* and see if there is ioctl stuff to free */
                 ioctlp = fidp->ioctlp;
@@ -743,6 +843,69 @@ char VNLCUserName[] = "%LCUSERNAME%";
 char VNComputerName[] = "%COMPUTERNAME%";
 char VNLCComputerName[] = "%LCCOMPUTERNAME%";
 
+/* List available shares */
+int smb_ListShares()
+{
+        char sbmtpath[256];
+        char pathName[256];
+        char shareBuf[4096];
+        int num_shares=0;
+        char *this_share;
+        int len;
+        char *p;
+        int print_afs = 0;
+        int code;
+
+        /*strcpy(shareNameList[num_shares], "all");
+          strcpy(pathNameList[num_shares++], "/afs");*/
+        fprintf(stderr, "The following shares are available:\n");
+        fprintf(stderr, "Share Name (AFS Path)\n");
+        fprintf(stderr, "---------------------\n");
+        fprintf(stderr, "\\\\%s\\%-16s (/afs)\n", smb_localNamep, "ALL");
+
+#ifndef DJGPP
+       code = GetWindowsDirectory(sbmtpath, sizeof(sbmtpath));
+        if (code == 0 || code > sizeof(sbmtpath)) return -1;
+#else
+        strcpy(sbmtpath, cm_confDir);
+#endif /* !DJGPP */
+        strcat(sbmtpath, "/afsdsbmt.ini");
+        len = GetPrivateProfileString("AFS Submounts", NULL, NULL,
+                                      shareBuf, sizeof(shareBuf),
+                                      sbmtpath);
+        if (len == 0) {
+          return num_shares;
+        }
+
+        this_share = shareBuf;
+        do
+        {
+          print_afs = 0;
+          /*strcpy(shareNameList[num_shares], this_share);*/
+          len = GetPrivateProfileString("AFS Submounts", this_share,
+                                        NULL,
+                                        pathName, 256,
+                                        sbmtpath);
+          if (!len) return num_shares;
+          p = pathName;
+          if (strncmp(p, "/afs", 4) != 0)
+            print_afs = 1;
+          while (*p) {
+            if (*p == '\\') *p = '/';    /* change to / */
+            p++;
+          }
+
+          fprintf(stderr, "\\\\%s\\%-16s (%s%s)\n",
+                  smb_localNamep, this_share, (print_afs ? "/afs" : "\0"),
+                  pathName);
+          num_shares++;
+          while (*this_share != NULL) this_share++;  /* find next NULL */
+          this_share++;   /* skip past the NULL */
+        } while (*this_share != NULL);  /* stop at final NULL */
+
+        return num_shares;
+}
+
 /* find a shareName in the table of submounts */
 int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
        char **pathNamep)
@@ -753,6 +916,8 @@ int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
        smb_user_t *uidp;
        char temp[1024];
        DWORD sizeTemp;
+        char sbmtpath[256];
+        char *p, *q;
 
        if (strcmp(shareName, "IPC$") == 0) {
                *pathNamep = NULL;
@@ -764,45 +929,62 @@ int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
                return 1;
        }
 
+#ifndef DJGPP
+        strcpy(sbmtpath, "afsdsbmt.ini");
+#else /* DJGPP */
+        strcpy(sbmtpath, cm_confDir);
+        strcat(sbmtpath, "/afsdsbmt.ini");
+#endif /* !DJGPP */
        len = GetPrivateProfileString("AFS Submounts", shareName, "",
-                                     pathName, sizeof(pathName), "afsdsbmt.ini");
+                                     pathName, sizeof(pathName), sbmtpath);
        if (len == 0 || len == sizeof(pathName) - 1) {
                *pathNamep = NULL;
                return 0;
        }
+        
+        /* We can accept either unix or PC style AFS pathnames.  Convert
+           Unix-style to PC style here for internal use. */
+        p = pathName;
+        if (strncmp(p, "/afs", 4) == 0)
+          p += 4;  /* skip /afs */
+        q = p;
+        while (*q) {
+          if (*q == '/') *q = '\\';    /* change to \ */
+          q++;
+        }
 
        while (1)
        {
-               if (var = smb_stristr(pathName, VNUserName)) {
+               if (var = smb_stristr(p, VNUserName)) {
                        uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
-                       smb_subst(pathName, var, sizeof(VNUserName),
+                       smb_subst(p, var, sizeof(VNUserName),
                                  uidp->name);
                        smb_ReleaseUID(uidp);
                }
-               else if (var = smb_stristr(pathName, VNLCUserName)) {
+               else if (var = smb_stristr(p, VNLCUserName)) {
                        uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
                        strcpy(temp, uidp->name);
                        _strlwr(temp);
-                       smb_subst(pathName, var, sizeof(VNLCUserName), temp);
+                       smb_subst(p, var, sizeof(VNLCUserName), temp);
                        smb_ReleaseUID(uidp);
                }
-               else if (var = smb_stristr(pathName, VNComputerName)) {
+               else if (var = smb_stristr(p, VNComputerName)) {
                        sizeTemp = sizeof(temp);
                        GetComputerName((LPTSTR)temp, &sizeTemp);
-                       smb_subst(pathName, var, sizeof(VNComputerName),
+                       smb_subst(p, var, sizeof(VNComputerName),
                                  temp);
                }
-               else if (var = smb_stristr(pathName, VNLCComputerName)) {
+               else if (var = smb_stristr(p, VNLCComputerName)) {
                        sizeTemp = sizeof(temp);
                        GetComputerName((LPTSTR)temp, &sizeTemp);
                        _strlwr(temp);
-                       smb_subst(pathName, var, sizeof(VNLCComputerName),
+                       smb_subst(p, var, sizeof(VNLCComputerName),
                                  temp);
                }
                else break;
        }
 
-       *pathNamep = strdup(pathName);
+       *pathNamep = strdup(p);
        return 1;
 }
 
@@ -980,12 +1162,20 @@ smb_dirSearch_t *smb_NewDirSearch(int isV3)
 static smb_packet_t *GetPacket(void)
 {
        smb_packet_t *tbp;
+#ifdef DJGPP
+        unsigned int npar, seg, tb_sel;
+#endif
+
        lock_ObtainWrite(&smb_globalLock);
        tbp = smb_packetFreeListp;
         if (tbp) smb_packetFreeListp = tbp->nextp;
        lock_ReleaseWrite(&smb_globalLock);
         if (!tbp) {
+#ifndef DJGPP
                tbp = GlobalAlloc(GMEM_FIXED, 65540);
+#else /* DJGPP */
+                tbp = malloc(sizeof(smb_packet_t));
+#endif /* !DJGPP */
                 tbp->magic = SMB_PACKETMAGIC;
                tbp->ncbp = NULL;
                tbp->vcp = NULL;
@@ -997,8 +1187,27 @@ static smb_packet_t *GetPacket(void)
                tbp->oddByte = 0;
                tbp->ncb_length = 0;
                tbp->flags = 0;
-       }
         
+#ifdef DJGPP
+                npar = SMB_PACKETSIZE >> 4;  /* number of paragraphs */
+                {
+                  signed int retval =
+                    __dpmi_allocate_dos_memory(npar, &tb_sel); /* DOS segment */
+                  if (retval == -1) {
+                    afsi_log("Cannot allocate %d paragraphs of DOS memory",
+                             npar);
+                    osi_panic("",__FILE__,__LINE__);
+                  }
+                  else {
+                    afsi_log("Allocated %d paragraphs of DOS mem at 0x%X",
+                             npar, retval);
+                    seg = retval;
+                  }
+                }
+                tbp->dos_pkt = (seg * 16) + 0;  /* DOS physical address */
+                tbp->dos_pkt_sel = tb_sel;
+#endif /* DJGPP */
+       }
         osi_assert(tbp->magic == SMB_PACKETMAGIC);
 
         return tbp;
@@ -1009,26 +1218,56 @@ smb_packet_t *smb_CopyPacket(smb_packet_t *pkt)
        smb_packet_t *tbp;
        tbp = GetPacket();
        memcpy(tbp, pkt, sizeof(smb_packet_t));
-       tbp->wctp = tbp->data + (pkt->wctp - pkt->data);
+       tbp->wctp = tbp->data + ((unsigned int)pkt->wctp -
+                                 (unsigned int)pkt->data);
        return tbp;
 }
 
 static NCB *GetNCB(void)
 {
        smb_ncb_t *tbp;
+        NCB *ncbp;
+#ifdef DJGPP
+        unsigned int npar, seg, tb_sel;
+#endif /* DJGPP */
+
        lock_ObtainWrite(&smb_globalLock);
        tbp = smb_ncbFreeListp;
         if (tbp) smb_ncbFreeListp = tbp->nextp;
        lock_ReleaseWrite(&smb_globalLock);
         if (!tbp) {
+#ifndef DJGPP
                tbp = GlobalAlloc(GMEM_FIXED, sizeof(*tbp));
+#else /* DJGPP */
+                tbp = malloc(sizeof(*tbp));
+                npar = (sizeof(NCB)+15) >> 4;  /* number of paragraphs */
+                {
+                  signed int retval =
+                    __dpmi_allocate_dos_memory(npar, &tb_sel); /* DOS segment */
+                  if (retval == -1) {
+                    afsi_log("Cannot allocate %d paragraphs of DOS mem in GetNCB",
+                             npar);
+                    osi_panic("",__FILE__,__LINE__);
+                  } else {
+                    afsi_log("Allocated %d paragraphs of DOS mem at 0x%X in GetNCB",
+                             npar, retval);
+                    seg = retval;
+                  }
+                }
+                tbp->dos_ncb = (seg * 16) + 0;  /* DOS physical address */
+                tbp->dos_ncb_sel = tb_sel;
+#endif /* !DJGPP */
                 tbp->magic = SMB_NCBMAGIC;
        }
         
         osi_assert(tbp->magic == SMB_NCBMAGIC);
 
        memset(&tbp->ncb, 0, sizeof(NCB));
-        return &tbp->ncb;
+        ncbp = &tbp->ncb;
+#ifdef DJGPP
+        dos_memset(tbp->dos_ncb, 0, sizeof(NCB));
+#endif /* DJGPP */
+        return ncbp;
 }
 
 void smb_FreePacket(smb_packet_t *tbp)
@@ -1107,6 +1346,7 @@ unsigned int smb_GetSMBParm(smb_packet_t *smbp, int parm)
        parmCount = *smbp->wctp;
 
        if (parm >= parmCount) {
+#ifndef DJGPP
                HANDLE h;
                char *ptbuf[1];
                char s[100];
@@ -1117,6 +1357,13 @@ unsigned int smb_GetSMBParm(smb_packet_t *smbp, int parm)
                ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1006, NULL,
                            1, smbp->ncb_length, ptbuf, smbp);
                DeregisterEventSource(h);
+#else /* DJGPP */
+                char s[100];
+
+                sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
+                        parm, parmCount, smbp->ncb_length);
+                osi_Log0(afsd_logp, s);
+#endif /* !DJGPP */
                osi_panic(s, __FILE__, __LINE__);
        }
        parmDatap = smbp->wctp + (2*parm) + 1;
@@ -1133,6 +1380,7 @@ unsigned int smb_GetSMBOffsetParm(smb_packet_t *smbp, int parm, int offset)
        parmCount = *smbp->wctp;
 
        if (parm * 2 + offset >= parmCount * 2) {
+#ifndef DJGPP
                HANDLE h;
                char *ptbuf[1];
                char s[100];
@@ -1143,6 +1391,15 @@ unsigned int smb_GetSMBOffsetParm(smb_packet_t *smbp, int parm, int offset)
                ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1006, NULL,
                            1, smbp->ncb_length, ptbuf, smbp);
                DeregisterEventSource(h);
+#else /* DJGPP */
+                char s[100];
+                
+                sprintf(s, "Bad SMB param %d offset %d out of %d, "
+                        "ncb len %d",
+                        parm, offset, parmCount, smbp->ncb_length);
+                osi_Log0(afsd_logp, s);
+#endif /* !DJGPP */
+
                osi_panic(s, __FILE__, __LINE__);
        }
        parmDatap = smbp->wctp + (2*parm) + 1 + offset;
@@ -1296,27 +1553,43 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
         long code;
         unsigned char *tp;
        int localNCB = 0;
+#ifdef DJGPP
+        dos_ptr dos_ncb;
+#endif /* DJGPP */
         
         ncbp = inp->ncbp;
        if (ncbp == NULL) {
                ncbp = GetNCB();
                localNCB = 1;
        }
+#ifdef DJGPP
+        dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+#endif /* DJGPP */
        memset((char *)ncbp, 0, sizeof(NCB));
 
         extra = 2 * (*inp->wctp);      /* space used by parms, in bytes */
        tp = inp->wctp + 1+ extra;      /* points to count of data bytes */
         extra += tp[0] + (tp[1]<<8);
-        extra += (inp->wctp - inp->data);      /* distance to last wct field */
+        extra += ((unsigned int)inp->wctp - (unsigned int)inp->data);  /* distance to last wct field */
         extra += 3;                    /* wct and length fields */
         
         ncbp->ncb_length = extra;      /* bytes to send */
         ncbp->ncb_lsn = (unsigned char) vcp->lsn;      /* vc to use */
        ncbp->ncb_lana_num = smb_LANadapter;
         ncbp->ncb_command = NCBSEND;   /* op means send data */
+#ifndef DJGPP
         ncbp->ncb_buffer = (char *) inp;/* packet */
-        
         code = Netbios(ncbp);
+#else /* DJGPP */
+        ncbp->ncb_buffer = inp->dos_pkt;/* packet */
+        ((smb_ncb_t*)ncbp)->orig_pkt = inp;
+
+        /* copy header information from virtual to DOS address space */
+        dosmemput((char*)inp, SMB_PACKETSIZE, inp->dos_pkt);
+        code = Netbios(ncbp, dos_ncb);
+#endif /* !DJGPP */
+        
        if (code != 0)
                osi_Log1(afsd_logp, "SendPacket failure code %d", code);
 
@@ -1566,6 +1839,10 @@ void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
                class = 1;
                error = 18;     /* no files in search */
        }
+        else if (code == CM_ERROR_RENAME_IDENTICAL) {
+                class = 1;
+                error = 183;     /* Samba uses this */
+        }
         else {
                class = 2;
                 error = 1;
@@ -1609,8 +1886,14 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
        smb_fid_t *fidp;
        long code;
        cm_user_t *userp = NULL;
-       char *rawBuf;
-       NCB *ncbp;
+        NCB *ncbp;
+        int rc;
+#ifndef DJGPP
+        char *rawBuf = NULL;
+#else
+        dos_ptr rawBuf = NULL;
+        dos_ptr dos_ncb;
+#endif /* DJGPP */
 
        rawBuf = NULL;
        finalCount = 0;
@@ -1628,31 +1911,65 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
        if (!fidp)
                goto send1;
 
-       if (fidp->flags & SMB_FID_IOCTL)
-               return smb_IoctlReadRaw(fidp, vcp, inp, outp);
-
-       userp = smb_GetUser(vcp, inp);
-
        lock_ObtainMutex(&smb_RawBufLock);
        if (smb_RawBufs) {
                /* Get a raw buf, from head of list */
                rawBuf = smb_RawBufs;
+#ifndef DJGPP
                smb_RawBufs = *(char **)smb_RawBufs;
+#else /* DJGPP */
+                smb_RawBufs = _farpeekl(_dos_ds, smb_RawBufs);
+#endif /* !DJGPP */
        }
        lock_ReleaseMutex(&smb_RawBufLock);
        if (!rawBuf)
-               goto send;
+               goto send1a;
+
+        if (fidp->flags & SMB_FID_IOCTL)
+        {
+#ifndef DJGPP
+          rc = smb_IoctlReadRaw(fidp, vcp, inp, outp);
+#else
+          rc = smb_IoctlReadRaw(fidp, vcp, inp, outp, rawBuf);
+#endif
+          if (rawBuf) {
+            /* Give back raw buffer */
+            lock_ObtainMutex(&smb_RawBufLock);
+#ifndef DJGPP
+            *((char **) rawBuf) = smb_RawBufs;
+#else /* DJGPP */
+            _farpokel(_dos_ds, rawBuf, smb_RawBufs);
+#endif /* !DJGPP */
+            
+            smb_RawBufs = rawBuf;
+            lock_ReleaseMutex(&smb_RawBufLock);
+          }
+          return rc;
+        }
+        
+        userp = smb_GetUser(vcp, inp);
 
+#ifndef DJGPP
        code = smb_ReadData(fidp, &offset, count, rawBuf, userp, &finalCount);
+#else /* DJGPP */
+        /* have to give ReadData flag so it will treat buffer as DOS mem. */
+        code = smb_ReadData(fidp, &offset, count, (unsigned char *)rawBuf,
+                            userp, &finalCount, TRUE /* rawFlag */);
+#endif /* !DJGPP */
+
        if (code != 0)
                goto send;
 
 send:
+        cm_ReleaseUser(userp);
+send1a:
        smb_ReleaseFID(fidp);
 
-       cm_ReleaseUser(userp);
 send1:
        ncbp = outp->ncbp;
+#ifdef DJGPP
+        dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+#endif /* DJGPP */
        memset((char *)ncbp, 0, sizeof(NCB));
 
        ncbp->ncb_length = (unsigned short) finalCount;
@@ -1661,14 +1978,23 @@ send1:
        ncbp->ncb_command = NCBSEND;
        ncbp->ncb_buffer = rawBuf;
 
+#ifndef DJGPP
        code = Netbios(ncbp);
+#else /* DJGPP */
+       code = Netbios(ncbp, dos_ncb);
+#endif /* !DJGPP */
        if (code != 0)
                osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
 
        if (rawBuf) {
                /* Give back raw buffer */
                lock_ObtainMutex(&smb_RawBufLock);
+#ifndef DJGPP
                *((char **) rawBuf) = smb_RawBufs;
+#else /* DJGPP */
+                _farpokel(_dos_ds, rawBuf, smb_RawBufs);
+#endif /* !DJGPP */
+
                smb_RawBufs = rawBuf;
                lock_ReleaseMutex(&smb_RawBufLock);
        }
@@ -1694,7 +2020,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        int NTProtoIndex;
         int protoIndex;                        /* index we're using */
         int namex;
-        long dbytes;
+        int dbytes;
        int entryLength;
         int tcounter;
        char protocol_array[10][1024]; /* protocol signature of the client */
@@ -1860,7 +2186,7 @@ void smb_Daemon(void *parmp)
 
        while(1) {
                count++;
-               Sleep(10000);
+               thrd_Sleep(10000);
                if ((count % 360) == 0)         /* every hour */
                        smb_CalculateNowTZ();
                /* XXX GC dir search entries */
@@ -1881,7 +2207,7 @@ void smb_WaitingLocksDaemon()
                nwL = smb_allWaitingLocks;
                if (nwL == NULL) {
                        osi_SleepW((long)&smb_allWaitingLocks, &smb_globalLock);
-                       Sleep(1000);
+                       thrd_Sleep(1000);
                        continue;
                }
                else first = 1;
@@ -1931,7 +2257,7 @@ endWait:
                        FreeNCB(ncbp);
                        free(wL);
                } while (nwL);
-               Sleep(1000);
+               thrd_Sleep(1000);
        }
 }
 
@@ -2124,9 +2450,9 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
 
        /* pull pathname and stat block out of request */
        tp = smb_GetSMBData(inp, NULL);
-        pathp = smb_ParseASCIIBlock(tp, &tp);
+        pathp = smb_ParseASCIIBlock(tp, (char **) &tp);
         osi_assert(pathp != NULL);
-        statBlockp = smb_ParseVblBlock(tp, &tp, &statLen);
+        statBlockp = smb_ParseVblBlock(tp, (char **) &tp, &statLen);
         osi_assert(statBlockp != NULL);
        if (statLen == 0) {
                statBlockp = initStatBlock;
@@ -2251,7 +2577,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         int maxCount;
         smb_dirListPatch_t *dirListPatchesp;
         smb_dirListPatch_t *curPatchp;
-        long dataLength;
+        int dataLength;
         cm_buf_t *bufferp;
         long temp;
         osi_hyper_t dirLength;
@@ -2283,6 +2609,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         int caseFold;
        char *tidPathp;
         cm_req_t req;
+        cm_fid_t fid;
+        int fileType;
 
        cm_InitReq(&req);
 
@@ -2582,6 +2910,24 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                        /* this is one of the entries to use: it is not deleted
                         * and it matches the star pattern we're looking for.
                          */
+
+                        /* Eliminate entries that don't match requested
+                           attributes */
+                        if (!(dsp->attribute & 0x10))  /* no directories */
+                        {
+                           /* We have already done the cm_TryBulkStat above */
+                           fid.cell = scp->fid.cell;
+                           fid.volume = scp->fid.volume;
+                           fid.vnode = ntohl(dep->fid.vnode);
+                           fid.unique = ntohl(dep->fid.unique);
+                           fileType = cm_FindFileType(&fid);
+                           osi_Log2(afsd_logp, "smb_ReceiveCoreSearchDir: file %s "
+                                    "has filetype %d", dep->name,
+                                    fileType);
+                           if (fileType == CM_SCACHETYPE_DIRECTORY)
+                              goto nextEntry;
+                        }
+
                        *op++ = resByte;
                         memcpy(op, mask, 11); op += 11;
                         *op++ = (char) dsp->cookie;    /* they say it must be non-zero */
@@ -3114,7 +3460,7 @@ typedef struct smb_unlinkRock {
        int any;
 } smb_unlinkRock_t;
 
-long smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
+int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
 {
        long code;
         smb_unlinkRock_t *rockp;
@@ -3234,7 +3580,7 @@ typedef struct smb_renameRock {
         char *newNamep;                /* ptr to the new file's name */
 } smb_renameRock_t;
 
-long smb_RenameProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
+int smb_RenameProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
 {
        long code;
         smb_renameRock_t *rockp;
@@ -3409,7 +3755,7 @@ typedef struct smb_rmdirRock {
        int any;
 } smb_rmdirRock_t;
 
-long smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
+int smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
 {
        long code;
         smb_rmdirRock_t *rockp;
@@ -3545,7 +3891,7 @@ struct smb_FullNameRock {
        char *fullName;
 };
 
-long smb_FullNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
+int smb_FullNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
        osi_hyper_t *offp)
 {
        char shortName[13];
@@ -3616,7 +3962,7 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        /* Don't jump the gun on an async raw write */
        while (fidp->raw_writers) {
                lock_ReleaseMutex(&fidp->mx);
-               WaitForSingleObject(fidp->raw_write_event, RAWTIMEOUT);
+               thrd_WaitForSingleObject_Event(fidp->raw_write_event, RAWTIMEOUT);
                lock_ObtainMutex(&fidp->mx);
        }
 
@@ -3677,8 +4023,13 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 /*
  * smb_ReadData -- common code for Read, Read And X, and Raw Read
  */
+#ifndef DJGPP
 long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
        cm_user_t *userp, long *readp)
+#else /* DJGPP */
+long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
+       cm_user_t *userp, long *readp, int dosflag)
+#endif /* !DJGPP */
 {
        osi_hyper_t offset;
        long code;
@@ -3796,6 +4147,11 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
                 if (nbytes > count) nbytes = count;    /* don't go past EOF */
                
                 /* now copy the data */
+#ifdef DJGPP
+                if (dosflag)
+                  dosmemput(bufferp->datap + bufIndex, nbytes, (dos_ptr)op);
+                else
+#endif /* DJGPP */
                 memcpy(op, bufferp->datap + bufIndex, nbytes);
                 
                /* adjust counters, pointers, etc. */
@@ -3820,8 +4176,13 @@ done:
 /*
  * smb_WriteData -- common code for Write and Raw Write
  */
+#ifndef DJGPP
 long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
        cm_user_t *userp, long *writtenp)
+#else /* DJGPP */
+long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
+       cm_user_t *userp, long *writtenp, int dosflag)
+#endif /* !DJGPP */
 {
        osi_hyper_t offset;
         long code;
@@ -3996,6 +4357,11 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
                 if (nbytes > count) nbytes = count;    /* don't go past end of request */
                
                 /* now copy the data */
+#ifdef DJGPP
+                if (dosflag)
+                  dosmemget((dos_ptr)op, nbytes, bufferp->datap + bufIndex);
+                else
+#endif /* DJGPP */
                 memcpy(bufferp->datap + bufIndex, op, nbytes);
                 buf_SetDirty(bufferp);
 
@@ -4051,7 +4417,7 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         cm_user_t *userp;
         cm_attr_t truncAttr;   /* attribute struct used for truncating file */
         char *op;
-        long inDataBlockCount;
+        int inDataBlockCount;
 
         fd = smb_GetSMBParm(inp, 0);
         count = smb_GetSMBParm(inp, 1);
@@ -4108,7 +4474,11 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                fidp->scp->clientModTime = time(NULL);
        }
 
+#ifndef DJGPP
        code = smb_WriteData(fidp, &offset, count, op, userp, &written);
+#else /* DJGPP */
+       code = smb_WriteData(fidp, &offset, count, op, userp, &written, FALSE);
+#endif /* !DJGPP */
        if (code == 0 && written < count)
                code = CM_ERROR_PARTIALWRITE;
 
@@ -4131,8 +4501,12 @@ void smb_CompleteWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
        unsigned short fd;
        smb_fid_t *fidp;
        cm_user_t *userp;
+#ifndef DJGPP
        char *rawBuf;
-       int written = 0;
+#else /* DJGPP */
+        dos_ptr rawBuf;
+#endif /* !DJGPP */
+       long written = 0;
        long code;
 
        fd = smb_GetSMBParm(inp, 0);
@@ -4143,10 +4517,16 @@ void smb_CompleteWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
 
        userp = smb_GetUser(vcp, inp);
 
+#ifndef DJGPP
        rawBuf = rwcp->buf;
-
        code = smb_WriteData(fidp, &rwcp->offset, rwcp->count, rawBuf, userp,
                             &written);
+#else /* DJGPP */
+       rawBuf = (dos_ptr) rwcp->buf;
+       code = smb_WriteData(fidp, &rwcp->offset, rwcp->count,
+                             (unsigned char *) rawBuf, userp,
+                            &written, TRUE);
+#endif /* !DJGPP */
 
        if (rwcp->writeMode & 0x1) {    /* synchronous */
                smb_t *op;
@@ -4163,13 +4543,17 @@ void smb_CompleteWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                lock_ObtainMutex(&fidp->mx);
                fidp->raw_writers--;
                if (fidp->raw_writers == 0)
-                       SetEvent(fidp->raw_write_event);
+                       thrd_SetEvent(fidp->raw_write_event);
                lock_ReleaseMutex(&fidp->mx);
        }
 
        /* Give back raw buffer */
        lock_ObtainMutex(&smb_RawBufLock);
+#ifndef DJGPP
        *((char **)rawBuf) = smb_RawBufs;
+#else /* DJGPP */
+        _farpokel(_dos_ds, rawBuf, smb_RawBufs);
+#endif /* !DJGPP */
        smb_RawBufs = rawBuf;
        lock_ReleaseMutex(&smb_RawBufLock);
 
@@ -4193,7 +4577,11 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         cm_user_t *userp;
         char *op;
        unsigned short writeMode;
+#ifndef DJGPP
        char *rawBuf;
+#else /* DJGPP */
+        dos_ptr rawBuf;
+#endif /* !DJGPP */
 
         fd = smb_GetSMBParm(inp, 0);
        totalCount = smb_GetSMBParm(inp, 1);
@@ -4232,7 +4620,11 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                fidp->scp->clientModTime = time(NULL);
        }
 
+#ifndef DJGPP
        code = smb_WriteData(fidp, &offset, count, op, userp, &written);
+#else /* DJGPP */
+       code = smb_WriteData(fidp, &offset, count, op, userp, &written, FALSE);
+#endif /* !DJGPP */
        if (code == 0 && written < count)
                code = CM_ERROR_PARTIALWRITE;
 
@@ -4243,7 +4635,11 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                if (smb_RawBufs) {
                        /* Get a raw buf, from head of list */
                        rawBuf = smb_RawBufs;
+#ifndef DJGPP
                        smb_RawBufs = *(char **)smb_RawBufs;
+#else /* DJGPP */
+                        smb_RawBufs = _farpeekl(_dos_ds, smb_RawBufs);
+#endif /* !DJGPP */
                }
                else
                        code = CM_ERROR_USESTD;
@@ -4254,7 +4650,7 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        if (code == 0 && (writeMode & 1) == 0) {
                lock_ObtainMutex(&fidp->mx);
                fidp->raw_writers++;
-               ResetEvent(fidp->raw_write_event);
+               thrd_ResetEvent(fidp->raw_write_event);
                lock_ReleaseMutex(&fidp->mx);
        }
 
@@ -4338,7 +4734,11 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         *op++ = (unsigned char) (count & 0xff);
         *op++ = (unsigned char) ((count >> 8) & 0xff);
                 
+#ifndef DJGPP
        code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount);
+#else /* DJGPP */
+        code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount, FALSE);
+#endif /* !DJGPP */
 
        /* fix some things up */
        smb_SetSMBParm(outp, 0, finalCount);
@@ -4689,6 +5089,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
        /* Sanity check */
        if (ncbp->ncb_length < offsetof(struct smb, vdata)) {
                /* log it and discard it */
+#ifndef DJGPP
                HANDLE h;
                char *ptbuf[1];
                char s[100];
@@ -4698,11 +5099,16 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1007, NULL,
                        1, ncbp->ncb_length, ptbuf, inp);
                DeregisterEventSource(h);
+#else /* DJGPP */
+                osi_Log1(smb_logp, "SMB message too short, len %d",
+                         ncbp->ncb_length);
+#endif /* !DJGPP */
+
                return;
        }
 
        /* We are an ongoing op */
-       InterlockedIncrement(&ongoingOps);
+       thrd_Increment(&ongoingOps);
 
         /* set up response packet for receiving output */
        if (!(outp->flags & SMB_PACKETFLAG_SUSPENDED))
@@ -4761,6 +5167,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                                code = (*(dp->procp)) (vcp, inp, outp);
 
                        if (oldGen != sessionGen) {
+#ifndef DJGPP
                                HANDLE h;
                                char *ptbuf[1];
                                char s[100];
@@ -4772,21 +5179,28 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                                ReportEvent(h, EVENTLOG_WARNING_TYPE, 0,
                                1005, NULL, 1, ncbp->ncb_length, ptbuf, smbp);
                                DeregisterEventSource(h);
+#else /* DJGPP */
+                              osi_Log1(afsd_logp, "Pkt straddled session startup, "
+                                       "ncb length %d", ncbp->ncb_length);
+#endif /* !DJGPP */
                        }
                 }
                 else {
                        /* bad opcode, fail the request, after displaying it */
+#ifndef DJGPP
                        if (showErrors) {
                                sprintf(tbuffer, "Received bad SMB req 0x%x", inp->inCom);
                                code = (*smb_MBfunc)(NULL, tbuffer, "Cancel: don't show again",
                                        MB_OKCANCEL);
                                if (code == IDCANCEL) showErrors = 0;
                        }
+#endif /* DJGPP */
                         code = CM_ERROR_BADOP;
                 }
 
                /* catastrophic failure:  log as much as possible */
                if (code == CM_ERROR_BADSMB) {
+#ifndef DJGPP
                        HANDLE h;
                        char *ptbuf[1];
                        char s[100];
@@ -4802,12 +5216,16 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                        ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1002, NULL,
                                    1, ncbp->ncb_length, ptbuf, smbp);
                        DeregisterEventSource(h);
+#else /* DJGPP */
+                        osi_Log1(afsd_logp, "Invalid SMB message, length %d",
+                                 ncbp->ncb_length);
+#endif /* !DJGPP */
 
                        code = CM_ERROR_INVAL;
                }
 
                if (outp->flags & SMB_PACKETFLAG_NOSEND) {
-                       InterlockedDecrement(&ongoingOps);
+                       thrd_Decrement(&ongoingOps);
                        return;
                }
 
@@ -4885,7 +5303,7 @@ resume:
                /* tp now points to the new output record; go back and patch the
                  * second parameter (off2) to point to the new record.
                  */
-               temp = tp - ((char *) outp->data);
+               temp = (unsigned int)tp - ((unsigned int) outp->data);
                 outWctp[3] = (unsigned char) (temp & 0xff);
                 outWctp[4] = (unsigned char) ((temp >> 8) & 0xff);
                 outWctp[2] = 0;        /* padding */
@@ -4911,7 +5329,7 @@ resume:
         /* now send the output packet, and return */
         if (!noSend)
                smb_SendPacket(vcp, outp);
-       InterlockedDecrement(&ongoingOps);
+       thrd_Decrement(&ongoingOps);
 
        if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
                active_vcp = vcp;
@@ -4923,6 +5341,7 @@ resume:
         return;
 }
 
+#ifndef DJGPP
 /* Wait for Netbios() calls to return, and make the results available to server
  * threads.  Note that server threads can't wait on the NCBevents array
  * themselves, because NCB events are manual-reset, and the servers would race
@@ -4933,16 +5352,17 @@ void smb_ClientWaiter(void *parmp)
        DWORD code, idx;
 
        while (1) {
-               code = WaitForMultipleObjects(numNCBs, NCBevents,
+               code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBevents,
                                              FALSE, INFINITE);
                if (code == WAIT_OBJECT_0)
                        continue;
                idx = code - WAIT_OBJECT_0;
 
-               ResetEvent(NCBevents[idx]);
-               SetEvent(NCBreturns[0][idx]);
+               thrd_ResetEvent(NCBevents[idx]);
+               thrd_SetEvent(NCBreturns[0][idx]);
        }
 }
+#endif /* !DJGPP */
 
 /*
  * Try to have one NCBRECV request waiting for every live session.  Not more
@@ -4952,19 +5372,22 @@ void smb_ServerWaiter(void *parmp)
 {
        DWORD code, idx_session, idx_NCB;
        NCB *ncbp;
+#ifdef DJGPP
+        dos_ptr dos_ncb;
+#endif /* DJGPP */
 
        while (1) {
                /* Get a session */
-               code = WaitForMultipleObjects(numSessions, SessionEvents,
-                                             FALSE, INFINITE);
+               code = thrd_WaitForMultipleObjects_Event(numSessions, SessionEvents,
+                                                   FALSE, INFINITE);
                if (code == WAIT_OBJECT_0)
                        continue;
                idx_session = code - WAIT_OBJECT_0;
 
                /* Get an NCB */
 NCBretry:
-               code = WaitForMultipleObjects(numNCBs, NCBavails,
-                                             FALSE, INFINITE);
+               code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBavails,
+                                                   FALSE, INFINITE);
                if (code == WAIT_OBJECT_0)
                        goto NCBretry;
                idx_NCB = code - WAIT_OBJECT_0;
@@ -4974,13 +5397,24 @@ NCBretry:
 
                /* Fire it up */
                ncbp = NCBs[idx_NCB];
+#ifdef DJGPP
+                dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+#endif /* DJGPP */
                ncbp->ncb_lsn = (unsigned char) LSNs[idx_session];
                ncbp->ncb_command = NCBRECV | ASYNCH;
                ncbp->ncb_lana_num = smb_LANadapter;
+#ifndef DJGPP
                ncbp->ncb_buffer = (unsigned char *) bufs[idx_NCB];
-               ncbp->ncb_length = SMB_PACKETSIZE;
                ncbp->ncb_event = NCBevents[idx_NCB];
+               ncbp->ncb_length = SMB_PACKETSIZE;
                Netbios(ncbp);
+#else /* DJGPP */
+               ncbp->ncb_buffer = bufs[idx_NCB]->dos_pkt;
+                ((smb_ncb_t*)ncbp)->orig_pkt = bufs[idx_NCB];
+               ncbp->ncb_event = NCBreturns[0][idx_NCB];
+               ncbp->ncb_length = SMB_PACKETSIZE;
+               Netbios(ncbp, dos_ncb);
+#endif /* !DJGPP */
        }
 }
 
@@ -5005,6 +5439,9 @@ void smb_Server(VOID *parmp)
        UCHAR rc;
        smb_vc_t *vcp;
        smb_t *smbp;
+#ifdef DJGPP
+        dos_ptr dos_ncb;
+#endif /* DJGPP */
 
        outncbp = GetNCB();
        outbufp = GetPacket();
@@ -5019,18 +5456,21 @@ void smb_Server(VOID *parmp)
                                (*smb_MBfunc)(NULL, "AFS demo expiration",
                                           "afsd dispatcher",
                                           MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);
-                               ExitThread(1);
+                               trhd_Exit(1);
                        }
                }
 #endif /* !NOEXPIRE */
 
-               code = WaitForMultipleObjects(numNCBs, NCBreturns[myIdx],
-                                             FALSE, INFINITE);
+               code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBreturns[myIdx],
+                                                   FALSE, INFINITE);
                if (code == WAIT_OBJECT_0)
                        continue;
                idx_NCB = code - WAIT_OBJECT_0;
 
                ncbp = NCBs[idx_NCB];
+#ifdef DJGPP
+                dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+#endif /* DJGPP */
                idx_session = NCBsessions[idx_NCB];
                rc = ncbp->ncb_retcode;
 
@@ -5079,7 +5519,8 @@ void smb_Server(VOID *parmp)
                        case NRC_INCOMP:
                                /* Treat as transient error */
                                {
-                                       HANDLE h;
+#ifndef DJGPP
+                                       EVENT_HANDLE h;
                                        char *ptbuf[1];
                                        char s[100];
 
@@ -5096,6 +5537,15 @@ void smb_Server(VOID *parmp)
                                                    ncbp->ncb_length, ptbuf,
                                                    bufp);
                                        DeregisterEventSource(h);
+#else /* DJGPP */
+                                       osi_Log1(smb_logp,
+                                               "dispatch smb recv failed, message incomplete, ncb_length %d",
+                                               ncbp->ncb_length);
+                                        osi_Log1(smb_logp,
+                                                 "SMB message incomplete, "
+                                                 "length %d", ncbp->ncb_length);
+#endif /* !DJGPP */
+
                                        /*
                                         * We used to discard the packet.
                                         * Instead, try handling it normally.
@@ -5111,8 +5561,8 @@ void smb_Server(VOID *parmp)
                                if (vcp->errorCount++ > 3)
                                        dead_sessions[idx_session] = TRUE;
                                else {
-                                       Sleep(1000);
-                                       SetEvent(SessionEvents[idx_session]);
+                                       thrd_Sleep(1000);
+                                       thrd_SetEvent(SessionEvents[idx_session]);
                                }
                                continue;
                }
@@ -5126,28 +5576,41 @@ void smb_Server(VOID *parmp)
                vcp = smb_FindVC(ncbp->ncb_lsn, 0);
                vcp->errorCount = 0;
                bufp = (struct smb_packet *) ncbp->ncb_buffer;
+#ifdef DJGPP
+               bufp = ((smb_ncb_t *) ncbp)->orig_pkt;
+                /* copy whole packet to virtual memory */
+                /*fprintf(stderr, "smb_Server: copying dos packet at 0x%x, "
+                        "bufp=0x%x\n",
+                        bufp->dos_pkt / 16, bufp);*/
+                fflush(stderr);
+                dosmemget(bufp->dos_pkt, ncbp->ncb_length, bufp->data);
+#endif /* DJGPP */
                smbp = (smb_t *)bufp->data;
                outbufp->flags = 0;
 
                if (smbp->com == 0x1d) {
                        /* Special handling for Write Raw */
                        raw_write_cont_t rwc;
-                       HANDLE rwevent;
+                       EVENT_HANDLE rwevent;
                        smb_DispatchPacket(vcp, bufp, outbufp, ncbp, &rwc);
                        if (rwc.code == 0) {
-                               rwevent = CreateEvent(NULL, FALSE, FALSE, NULL);
+                               rwevent = thrd_CreateEvent(NULL, FALSE, FALSE, NULL);
                                ncbp->ncb_command = NCBRECV | ASYNCH;
                                ncbp->ncb_lsn = (unsigned char) vcp->lsn;
                                ncbp->ncb_lana_num = smb_LANadapter;
                                ncbp->ncb_buffer = rwc.buf;
                                ncbp->ncb_length = 65535;
                                ncbp->ncb_event = rwevent;
+#ifndef DJGPP
                                Netbios(ncbp);
-                               rcode = WaitForSingleObject(rwevent,
-                                                           RAWTIMEOUT);
-                               CloseHandle(rwevent);
+#else
+                               Netbios(ncbp, dos_ncb);
+#endif /* !DJGPP */
+                               rcode = thrd_WaitForSingleObject_Event(rwevent,
+                                                                 RAWTIMEOUT);
+                               thrd_CloseHandle(rwevent);
                        }
-                       SetEvent(SessionEvents[idx_session]);
+                       thrd_SetEvent(SessionEvents[idx_session]);
                        if (rwc.code == 0)
                                smb_CompleteWriteRaw(vcp, bufp, outbufp, ncbp,
                                                     &rwc);
@@ -5157,16 +5620,16 @@ void smb_Server(VOID *parmp)
                         * (defect 11626)
                          */
                        smb_DispatchPacket(vcp, bufp, outbufp, ncbp, NULL);
-                       SetEvent(SessionEvents[idx_session]);
+                       thrd_SetEvent(SessionEvents[idx_session]);
                 } else {
-                       SetEvent(SessionEvents[idx_session]);
+                       thrd_SetEvent(SessionEvents[idx_session]);
                        smb_DispatchPacket(vcp, bufp, outbufp, ncbp, NULL);
                }
 
                smb_concurrentCalls--;
 
 doneWithNCB:
-               SetEvent(NCBavails[idx_NCB]);
+               thrd_SetEvent(NCBavails[idx_NCB]);
        }
 }
 
@@ -5179,13 +5642,15 @@ doneWithNCB:
 void InitNCBslot(int idx)
 {
        struct smb_packet *bufp;
-       HANDLE retHandle;
+       EVENT_HANDLE retHandle;
        int i;
 
        NCBs[idx] = GetNCB();
-       NCBavails[idx] = CreateEvent(NULL, FALSE, TRUE, NULL);
-       NCBevents[idx] = CreateEvent(NULL, TRUE, FALSE, NULL);
-       retHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
+       NCBavails[idx] = thrd_CreateEvent(NULL, FALSE, TRUE, NULL);
+#ifndef DJGPP
+       NCBevents[idx] = thrd_CreateEvent(NULL, TRUE, FALSE, NULL);
+#endif /* !DJGPP */
+       retHandle = thrd_CreateEvent(NULL, FALSE, FALSE, NULL);
        for (i=0; i<smb_NumServerThreads; i++)
                NCBreturns[i][idx] = retHandle;
        bufp = GetPacket();
@@ -5205,10 +5670,23 @@ void smb_Listener(void *parmp)
        char rname[NCBNAMSZ+1];
        char cname[MAX_COMPUTERNAME_LENGTH+1];
        int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
+#ifdef DJGPP
+        dos_ptr dos_ncb;
+        time_t now;
+#endif /* DJGPP */
 
        ncbp = GetNCB();
+#ifdef DJGPP
+        dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+#endif /* DJGPP */
 
        while (1) {
+#ifdef DJGPP
+             /* terminate if shutdown flag is set */
+             if (smbShutdownFlag == 1)
+               thrd_Exit(1);
+#endif /* DJGPP */
+
 #ifndef NOEXPIRE
                /* check for demo expiration */
                {
@@ -5236,7 +5714,25 @@ void smb_Listener(void *parmp)
         
                ncbp->ncb_lana_num = smb_LANadapter;
 
+#ifndef DJGPP
                code = Netbios(ncbp);
+#else /* DJGPP */
+               code = Netbios(ncbp, dos_ncb);
+
+                if (code != 0)
+                {
+                  fprintf(stderr, "NCBLISTEN lana=%d (smb_LANadapter=%d) "
+                          "failed with code %d\n",
+                          ncbp->ncb_lana_num, smb_LANadapter, code);
+                  osi_Log3(0, "NCBLISTEN lana=%d (smb_LANadapter=%d) "
+                           "failed with code %d",
+                           ncbp->ncb_lana_num, smb_LANadapter, code);
+                  fprintf(stderr, "\nClient exiting due to network failure "
+                          "(possibly due to power-saving mode)\n");
+                  fprintf(stderr, "Please restart client.\n");
+                  afs_exit(AFS_EXITCODE_NETWORK_FAILURE);
+                }
+#endif /* !DJGPP */
                osi_assert(code == 0);
 
                /* check for remote conns */
@@ -5262,6 +5758,7 @@ void smb_Listener(void *parmp)
 
                /* Log session startup */
                if (reportSessionStartups) {
+#ifndef DJGPP
                        HANDLE h;
                        char *ptbuf[1];
                        char s[100];
@@ -5273,6 +5770,17 @@ void smb_Listener(void *parmp)
                        ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1004, NULL,
                                    1, 0, ptbuf, NULL);
                        DeregisterEventSource(h);
+#else /* DJGPP */
+                        afsi_log("NCBLISTEN completed, call from %s",rname);
+                        osi_Log1(afsd_logp, "SMB session startup, %d ongoing o
+ps",
+                                 ongoingOps);
+                         time(&now);
+                         fprintf(stderr, "%s: New session starting from host %s
+\n",
+                                 asctime(localtime(&now)), rname);
+                         fflush(stderr);
+#endif /* !DJGPP */
                }
 
                 /* now ncbp->ncb_lsn is the connection ID */
@@ -5292,44 +5800,178 @@ void smb_Listener(void *parmp)
                        /* Add new NCB for new session */
                        InitNCBslot(numNCBs);
                        numNCBs++;
-                       SetEvent(NCBavails[0]);
-                       SetEvent(NCBevents[0]);
+                       thrd_SetEvent(NCBavails[0]);
+                       thrd_SetEvent(NCBevents[0]);
                        for (j = 0; j < smb_NumServerThreads; j++)
-                               SetEvent(NCBreturns[j][0]);
+                               thrd_SetEvent(NCBreturns[j][0]);
                        /* Also add new session event */
-                       SessionEvents[i] = CreateEvent(NULL, FALSE, TRUE, NULL);
+                       SessionEvents[i] = thrd_CreateEvent(NULL, FALSE, TRUE, NULL);
                        numSessions++;
-                       SetEvent(SessionEvents[0]);
+                       thrd_SetEvent(SessionEvents[0]);
                } else {
-                       SetEvent(SessionEvents[i]);
+                       thrd_SetEvent(SessionEvents[i]);
                }
 
         }      /* dispatch while loop */
 }
 
+/* initialize Netbios */
+void smb_NetbiosInit()
+{
+        NCB *ncbp;
+#ifdef DJGPP
+        dos_ptr dos_ncb;
+#endif /* DJGPP */
+        int i, lana, code;
+        char s[100];
+        int delname_tried=0;
+        int len;
+
+       /* setup the NCB system */
+       ncbp = GetNCB();
+#ifdef DJGPP
+        dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+#endif /* DJGPP */
+
+#ifndef DJGPP
+       /* reset the adaptor: in Win32, this is required for every process, and
+         * acts as an init call, not as a real hardware reset.
+         */
+        ncbp->ncb_command = NCBRESET;
+        ncbp->ncb_callname[0] = 100;
+        ncbp->ncb_callname[2] = 100;
+       ncbp->ncb_lana_num = smb_LANadapter;
+        code = Netbios(ncbp);
+        if (code == 0) code = ncbp->ncb_retcode;
+       if (code != 0) {
+               sprintf(s, "Netbios NCBRESET error code %d", code);
+               afsi_log(s);
+               osi_panic(s, __FILE__, __LINE__);
+       }
+#endif /* !DJGPP */
+
+  try_addname:
+       /* and declare our name so we can receive connections */
+       memset(ncbp, 0, sizeof(*ncbp));
+       ncbp->ncb_lana_num = smb_LANadapter;
+        ncbp->ncb_command = NCBADDNAME;
+       strcpy(ncbp->ncb_name, smb_localNamep);
+        len = strlen(smb_localNamep);
+        for(i=len; i<NCBNAMSZ; i++) ncbp->ncb_name[i] = ' ';
+        /* Keep the name so we can unregister it later */
+        memcpy(smb_sharename,ncbp->ncb_name,NCBNAMSZ);
+        lana = smb_LANadapter;
+
+        do {        /* try multiple LANA numbers until we find one that works */
+          ncbp->ncb_lana_num = lana;
+#ifndef DJGPP
+          code = Netbios(ncbp);
+#else /* DJGPP */
+          code = Netbios(ncbp, dos_ncb);
+#endif /* !DJGPP */
+          
+          afsi_log("Netbios NCBADDNAME code=%d retcode=%d complete=%d",code,
+                   ncbp->ncb_retcode,ncbp->ncb_cmd_cplt);
+          {
+            char name[200];
+            int i;
+            for (i=0;i<NCBNAMSZ;++i)
+              name[i] = ncbp->ncb_name[i];
+            name[i] = '\0';
+            afsi_log("Netbios NCBADDNAME added new name >%s<",name);
+          }
+
+          if (code == 0)
+          {
+            code = ncbp->ncb_retcode;
+            smb_LANadapter = lana;     /* correct LANA number */
+            break;
+          }
+          else
+          {
+            sprintf(s, "Netbios NCBADDNAME lana %d error code %d", lana, code);
+            afsi_log(s);
+            if (code != NRC_BRIDGE)    /* invalid LANA num */
+              break;
+            else
+              lana = (lana + 1) % 8;
+          }
+        } while (lana != smb_LANadapter);  /* quit when we loop back to orig. */
+        
+        if (code == NRC_DUPNAME)
+        {
+          /* Name already exists; try to delete it */
+          memset(ncbp, 0, sizeof(*ncbp));
+          ncbp->ncb_command = NCBDELNAME;
+          memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
+          ncbp->ncb_lana_num = smb_LANadapter;
+#ifndef DJGPP
+          code = Netbios(ncbp);
+#else
+          code = Netbios(ncbp, dos_ncb);
+#endif /* DJGPP */
+          if (code == 0) code = ncbp->ncb_retcode;
+          if (code != 0) {
+            fprintf(stderr, "Netbios NCBDELNAME error code %d", code);
+          }
+          fflush(stderr);
+          if (code == 0 && !delname_tried)
+          {
+            delname_tried = 1;
+            goto try_addname;
+          }
+        }
+
+        if (code != 0)
+          osi_panic(s, __FILE__, __LINE__);
+        
+        fprintf(stderr, "Using LAN Adapter %d\n", smb_LANadapter, code);
+        afsi_log("Netbios NCBADDNAME lana=%d name number=%d", smb_LANadapter,
+                 ncbp->ncb_num);
+
+       /* we're done with the NCB now */
+        FreeNCB(ncbp);
+}
+
 void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
-       int nThreads, void *aMBfunc)
+       int nThreads
+#ifndef DJGPP
+        , void *aMBfunc
+#endif
+  )
+
 {
-       HANDLE phandle;
-        long lpid;
+       thread_t phandle;
+        int lpid;
         int i;
         long code;
         int len;
         NCB *ncbp;
        struct tm myTime;
        char s[100];
+#ifdef DJGPP
+        int npar, seg, sel;
+        dos_ptr rawBuf;
+#endif /* DJGPP */
 
+#ifndef DJGPP
        smb_MBfunc = aMBfunc;
+#endif /* DJGPP */
 
 #ifndef NOEXPIRE
        /* check for demo expiration */
        {
                unsigned long tod = time((void *) 0);
                if (tod > EXPIREDATE) {
+#ifndef DJGPP
                        (*smb_MBfunc)(NULL, "AFS demo expiration",
                                   "afsd",
                                   MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);
                        exit(1);
+#else /* DJGPP */
+                        fprintf(stderr, "AFS demo expiration\n");
+                        afs_exit(0);
+#endif /* !DJGPP */
                }
        }
 #endif /* !NOEXPIRE */
@@ -5366,6 +6008,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
        lock_InitializeMutex(&smb_RawBufLock, "smb raw buffer lock");
 
        /* 4 Raw I/O buffers */
+#ifndef DJGPP
        smb_RawBufs = GlobalAlloc(GMEM_FIXED, 65536);
        *((char **)smb_RawBufs) = NULL;
        for (i=0; i<3; i++) {
@@ -5373,57 +6016,57 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
                *((char **)rawBuf) = smb_RawBufs;
                smb_RawBufs = rawBuf;
        }
+#else /* DJGPP */
+        npar = 65536 >> 4;  /* number of paragraphs */
+        seg = __dpmi_allocate_dos_memory(npar, &smb_RawBufSel[0]);
+        if (seg == -1) {
+          afsi_log("Cannot allocate %d paragraphs of DOS memory",
+                   npar);
+          osi_panic("",__FILE__,__LINE__);
+        }
+        else {
+          afsi_log("Allocated %d paragraphs of DOS mem at 0x%X",
+                   npar, seg);
+        }
+        smb_RawBufs = (seg * 16) + 0;  /* DOS physical address */
+        
+        _farpokel(_dos_ds, smb_RawBufs, NULL);
+        for (i=0; i<SMB_RAW_BUFS-1; i++) {
+          npar = 65536 >> 4;  /* number of paragraphs */
+          seg = __dpmi_allocate_dos_memory(npar, &smb_RawBufSel[i+1]);
+          if (seg == -1) {
+            afsi_log("Cannot allocate %d paragraphs of DOS memory",
+                     npar);
+            osi_panic("",__FILE__,__LINE__);
+          }
+          else {
+            afsi_log("Allocated %d paragraphs of DOS mem at 0x%X",
+                     npar, seg);
+          }
+          rawBuf = (seg * 16) + 0;  /* DOS physical address */
+          /*_farpokel(_dos_ds, smb_RawBufs, smb_RawBufs);*/
+          _farpokel(_dos_ds, rawBuf, smb_RawBufs);
+          smb_RawBufs = rawBuf;
+        }
+#endif /* !DJGPP */
 
        /* global free lists */
        smb_ncbFreeListp = NULL;
         smb_packetFreeListp = NULL;
 
-       /* setup the NCB system */
-       ncbp = GetNCB();
-
-       /* reset the adaptor: in Win32, this is required for every process, and
-         * acts as an init call, not as a real hardware reset.
-         */
-        ncbp->ncb_command = NCBRESET;
-        ncbp->ncb_callname[0] = 100;
-        ncbp->ncb_callname[2] = 100;
-       ncbp->ncb_lana_num = smb_LANadapter;
-        code = Netbios(ncbp);
-        if (code == 0) code = ncbp->ncb_retcode;
-       if (code != 0) {
-               sprintf(s, "Netbios NCBRESET error code %d", code);
-               afsi_log(s);
-               osi_panic(s, __FILE__, __LINE__);
-       }
-
-       /* and declare our name so we can receive connections */
-       memset(ncbp, 0, sizeof(*ncbp));
-       ncbp->ncb_lana_num = smb_LANadapter;
-        ncbp->ncb_command = NCBADDNAME;
-       strncpy(ncbp->ncb_name, snamep, len);
-        for(i=len; i<NCBNAMSZ; i++) ncbp->ncb_name[i] = ' ';
-        code = Netbios(ncbp);
-       if (code == 0) {
-               code = ncbp->ncb_retcode;
-       }
-       if (code != 0) {
-               afsi_log("Netbios NCBADDNAME error code %d", code);
-       }
-        
-       /* we're done with the NCB now */
-        FreeNCB(ncbp);
+        smb_NetbiosInit();
 
        /* Initialize listener and server structures */
        memset(dead_sessions, 0, sizeof(dead_sessions));
-       SessionEvents[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
+       SessionEvents[0] = thrd_CreateEvent(NULL, FALSE, FALSE, NULL);
        numSessions = 1;
        smb_NumServerThreads = nThreads;
-       NCBavails[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
-       NCBevents[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
-       NCBreturns = malloc(nThreads * sizeof(HANDLE *));
+       NCBavails[0] = thrd_CreateEvent(NULL, FALSE, FALSE, NULL);
+       NCBevents[0] = thrd_CreateEvent(NULL, FALSE, FALSE, NULL);
+       NCBreturns = malloc(nThreads * sizeof(EVENT_HANDLE *));
        for (i = 0; i < nThreads; i++) {
-               NCBreturns[i] = malloc(NCBmax * sizeof(HANDLE));
-               NCBreturns[i][0] = CreateEvent(NULL, FALSE, FALSE, NULL);
+               NCBreturns[i] = malloc(NCBmax * sizeof(EVENT_HANDLE));
+               NCBreturns[i][0] = thrd_CreateEvent(NULL, FALSE, FALSE, NULL);
        }
        for (i = 1; i <= nThreads; i++)
                InitNCBslot(i);
@@ -5516,39 +6159,94 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
 
        /* Start listeners, waiters, servers, and daemons */
 
-        phandle = CreateThread(NULL, 65536, (LPTHREAD_START_ROUTINE) smb_Listener,
-               NULL, 0, &lpid);
+        phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_Listener,
+               NULL, 0, &lpid, "smb_Listener");
        osi_assert(phandle != NULL);
-       CloseHandle(phandle);
+       thrd_CloseHandle(phandle);
 
-        phandle = CreateThread(NULL, 65536, (LPTHREAD_START_ROUTINE) smb_ClientWaiter,
-               NULL, 0, &lpid);
+#ifndef DJGPP
+        phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ClientWaiter,
+               NULL, 0, &lpid, "smb_ClientWaiter");
        osi_assert(phandle != NULL);
-       CloseHandle(phandle);
+       thrd_CloseHandle(phandle);
+#endif /* !DJGPP */
 
-        phandle = CreateThread(NULL, 65536, (LPTHREAD_START_ROUTINE) smb_ServerWaiter,
-               NULL, 0, &lpid);
+        phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ServerWaiter,
+               NULL, 0, &lpid, "smb_ServerWaiter");
        osi_assert(phandle != NULL);
-       CloseHandle(phandle);
+       thrd_CloseHandle(phandle);
 
        for (i=0; i<nThreads; i++) {
-               phandle = CreateThread(NULL, 65536,
-                                       (LPTHREAD_START_ROUTINE) smb_Server,
-                                       (void *) i, 0, &lpid);
+               phandle = thrd_Create(NULL, 65536,
+                                       (ThreadFunc) smb_Server,
+                                       (void *) i, 0, &lpid, "smb_Server");
                osi_assert(phandle != NULL);
-               CloseHandle(phandle);
+               thrd_CloseHandle(phandle);
        }
 
-        phandle = CreateThread(NULL, 65536, (LPTHREAD_START_ROUTINE) smb_Daemon,
-               NULL, 0, &lpid);
+        phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_Daemon,
+               NULL, 0, &lpid, "smb_Daemon");
        osi_assert(phandle != NULL);
-       CloseHandle(phandle);
+       thrd_CloseHandle(phandle);
 
-       phandle = CreateThread(NULL, 65536,
-               (LPTHREAD_START_ROUTINE) smb_WaitingLocksDaemon,
-               NULL, 0, &lpid);
+       phandle = thrd_Create(NULL, 65536,
+               (ThreadFunc) smb_WaitingLocksDaemon,
+               NULL, 0, &lpid, "smb_WaitingLocksDaemon");
        osi_assert(phandle != NULL);
-       CloseHandle(phandle);
+       thrd_CloseHandle(phandle);
+
+#ifdef DJGPP
+        smb_ListShares();
+#endif
 
        return;
 }
+
+#ifdef DJGPP
+void smb_Shutdown(void)
+{
+        NCB *ncbp;
+        dos_ptr dos_ncb;
+        long code;
+        int i;
+        
+        /*fprintf(stderr, "Entering smb_Shutdown\n");*/
+        
+        /* setup the NCB system */
+        ncbp = GetNCB();
+        dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+
+        /* Block new sessions by setting shutdown flag */
+        /*smbShutdownFlag = 1;*/
+
+        /* Hang up all sessions */
+        for (i = 1; i < numSessions; i++)
+        {
+          if (dead_sessions[i])
+            continue;
+          
+          /*fprintf(stderr, "NCBHANGUP session %d LSN %d\n", i, LSNs[i]);*/
+          ncbp->ncb_command = NCBHANGUP;
+          ncbp->ncb_lana_num = smb_LANadapter;
+          ncbp->ncb_lsn = LSNs[i];
+          code = Netbios(ncbp, dos_ncb);
+          /*fprintf(stderr, "returned from NCBHANGUP session %d LSN %d\n", i, LS
+            Ns[i]);*/
+          if (code == 0) code = ncbp->ncb_retcode;
+          if (code != 0) {
+            fprintf(stderr, "Session %d Netbios NCBHANGUP error code %d", i, code);
+          }
+        }
+
+        /* Delete Netbios name */
+        ncbp->ncb_command = NCBDELNAME;
+        memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
+        ncbp->ncb_lana_num = smb_LANadapter;
+        code = Netbios(ncbp, dos_ncb);
+        if (code == 0) code = ncbp->ncb_retcode;
+        if (code != 0) {
+          fprintf(stderr, "Netbios NCBDELNAME error code %d", code);
+        }
+        fflush(stderr);
+}
+#endif /* DJGPP */
index 201bafd..0bba634 100644 (file)
 #ifndef __SMB_H_ENV__
 #define __SMB_H_ENV__ 1
 
+#ifdef DJGPP
+#include "netbios95.h"
+#endif /* DJGPP */
+
 /* basic core protocol SMB structure */
 typedef struct smb {
        unsigned char id[4];
@@ -74,6 +78,10 @@ typedef struct smb_packet {
        unsigned char oddByte;
        unsigned short ncb_length;
        unsigned char flags;
+#ifdef DJGPP
+        dos_ptr dos_pkt;
+        unsigned int dos_pkt_sel;
+#endif /* DJGPP */
 } smb_packet_t;
 
 /* smb_packet flags */
@@ -87,6 +95,11 @@ typedef struct myncb {
        NCB ncb;                        /* ncb to use */
         struct myncb *nextp;           /* when on free list */
         long magic;
+#ifdef DJGPP
+        dos_ptr dos_ncb;
+        smb_packet_t *orig_pkt;
+        unsigned int dos_ncb_sel;
+#endif /* DJGPP */
 } smb_ncb_t;
 
 /* structures representing environments from kernel / SMB network.
@@ -209,7 +222,7 @@ typedef struct smb_fid {
        int curr_chunk;                 /* chunk being read */
        int prev_chunk;                 /* previous chunk read */
        int raw_writers;                /* pending async raw writes */
-       HANDLE raw_write_event;         /* signal this when raw_writers zero */
+       EVENT_HANDLE raw_write_event;   /* signal this when raw_writers zero */
 } smb_fid_t;
 
 #define SMB_FID_OPENREAD               1       /* open for reading */
@@ -279,11 +292,16 @@ typedef struct smb_dispatch {
                                                 * the response was already
                                                 * sent.
                                                  */
+#define SMB_MAX_PATH                    256     /* max path length */
 
 /* prototypes */
 
 extern void smb_Init(osi_log_t *logp, char *smbNamep, int useV3, int LANadapt,
-       int nThreads, void *aMBfunc);
+       int nThreads
+#ifndef DJGPP
+        , void *aMBfunc
+#endif
+  );
 
 extern void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, long unixTime);
 
@@ -402,8 +420,13 @@ extern unsigned char *smb_ParseVblBlock(unsigned char *inp, char **chainpp, int
 
 extern int smb_SUser(cm_user_t *userp);
 
+#ifndef DJGPP
 extern long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count,
        char *op, cm_user_t *userp, long *readp);
+#else /* DJGPP */
+extern long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count,
+       char *op, cm_user_t *userp, long *readp, int dosflag);
+#endif /* !DJGPP */
 
 extern BOOL smb_IsLegalFilename(char *filename);