/*static char *SCCSID = "@(#)closoft.c	6.2 92/01/31";*/
#ifndef	 _BTXT
#define	 _BTXT _BTXT
#define	 _THISFILE "CLOSOFT.C"
#include _THISFILE.C
#undef	 _BTXT
#endif

#ifndef HDRS
#define HDRS

#include <os2def.h>
#include "heap.h"
#include "const.h"
#include "misc.h"
#include "buf.h"
#include "storage.h"
#include "ea.h"
#include "fnode.h"
#include "chain.h"
#include "dir.h"
#include "volume.h"
#include "tables.h"
#include "lw.h"
#include "frame.h"
#include "fsdata.h"
#include "assert.h"
#include "pbmacros.h"

#endif

#include "pr_dir.h"
#include "pr_ea.h"
#include "pr_fssub.h"
#include "pr_heap.h"
#include "pr_misc.h"

#ifdef DEBUG
#include "pr_debug.h"
#endif

/*
 ***	ShutOFT - Close Out Use of an OFT
 *
 *	Pathname based calls sometimes "mostly open" a file.  They
 *	don't do a full open in that they don't create a file handle
 *	table, they don't go through the sharing rules, and they
 *	don't modify the access times.  What they *do* is to create
 *	or access the OFT.  When they're done, we have to release their
 *	hold on the OFT and perhaps collapse the OFT.
 *
 *	Note that in the ASM code, ClosOFT jumps to GetHardErr if
 *	a hard error indication is passed in.  In the C version,
 *	the caller is responsible for invoking GetHardErr after
 *	the return from ClosOFT in these situations.
 *
 *	ENTRY	poft = oft address (held)
 *
 *	This function is not in the ASM pinball.  It was added because
 *	ClosOFT had an extra UnHoldDir() call in it that was screwing
 *	up FindFirst/Next as called through CFR.
 *
 * History:
 *	20-Dec-1988 23:09:30 by Jon Parati [jonpa]
 *	     ShutOFT formed by renaming ClosOFT and removing UnHoldDir line
 */

void
ShutOFT(POFT poft, PFRAME pfrm)
{
    /* coft0: */

#ifdef DEBUG
    /*
     * This check is really only for ClosOFT & ClosOFT_, but it should
     * still apply here.  (UnLockDir uses pfrm->sbd!)
     */
     if ((poft->bSFlag & OFS_DASD) == 0)
	/* psbdDir is only valid if not Direct Access (DASD) */
	if (pfrm->psbd != poft->psbdDir)
	    INTERR (__FILE__": sbdirs don't match");

    /* coft2: */
#endif

    UnHoldOFT (poft);

    if (--poft->cusClientFHTs == 0) {
	/*
	 * release the OFT entry
	 *
	 * We need to have no one holding it and no one waiting on it.
	 *
	 * If necessary, the OFT info was updated to the DIR and FNODE entries.
	 */

	/* unuse the SBDIR  (DASD OFTs don't have psbdDir) */
	if (poft->psbdDir != NULL)
	    poft->psbdDir->cOpens--;

	/* Wait until no one else is using OFT */
	if (poft->cusHolds != 0 || poft->cWaits != 0)
	    SoloOFT (poft,pfrm);

	/*
	 * Since this oft is going away, we need to decrement its count in
	 * the band table.
	 */
	if (poft->pbtLastAlloc != NULL) {

	    #ifdef DEBUG
		if (poft->pbtLastAlloc->cFilesInBand == 0) {
		    dprintf (__FILE__ "(%d): cFilesInBand going negative\n",
			     __LINE__);
		    Int3 ();
		}
	    #endif /* DEBUG */

	    poft->pbtLastAlloc->cFilesInBand--;
	}

	/* delete this OFT entry from the OFT list */
	{
	    POFT poftFwd;
	    POFT poftBak;

	    poftFwd = poft->dcpOFTList.pFwd;
	    poftBak = poft->dcpOFTList.pBak;
	    poftFwd->dcpOFTList.pBak = poftBak;
	    poftBak->dcpOFTList.pFwd = poftFwd;

	    /*
	     * Even though the ASM code doesn't have this, we need it
	     * because we don't hash OFTs.
	     */
	    cOFT--;

	    RetHeap (poft);
	}
    }	/* client count == 0 */
    return;
}
