/*static char *SCCSID = "@(#)openda.c	6.3 92/01/31";*/
#define INCL_DOSERRORS
#include <os2def.h>
#include <bse.h>
#include "api.h"
#include "filemode.h"
#include "const.h"
#include "misc.h"
#include "chain.h"
#include "buf.h"
#include "dir.h"
#include "storage.h"
#include "volume.h"
#include "tables.h"
#include "lw.h"
#include "frame.h"
#include "fsdata.h"
#include "heap.h"
#include "pbmacros.h"
#include "rahead.h"
#include "pr_FCN.h"
#include "pr_HEAP.h"
#include "pr_debug.h"
#include "pr_MISC.h"

/*
 ***	OpenDirect - Open a File (DIRECT ACCESS)
 *
 *	ENTRY	usMode = MODE
 *		  1... .... .... ....	DASD open (ALWAYS ON)
 *		  .1.. .... .... ....	Write through (OPEN_WRITE_THROUGH)
 *		  ..1. .... .... ....	No hard error handling (OPEN_AUTO_FAIL)
 *		  .... .... 1... ....	No auto inheritance (ignore)
 *		  .... .... .111 ....	sharing mode (OPEN_SHARING_MODE)
 *		  .... .... .... .111	access mode (OPEN_ACCESS, OPEN_FOR_xxx)
 *
 *		pcp = address of cracked path name
 *		pulSize = address of file size returned to caller
 *		phf = address of handle returned to caller
 *
 *	EXIT	Returns 0 if OK
 *		  *pulSize = file size
 *		  *ppfht = handle
 *
 *		Returns non-zero error code if error
 */

USHORT far
OpenDirect (USHORT	 usMode,    /* mode from filemode.h */
	    PCRACKEDPATH pcp,	    /* cracked path */
	    PULONG	 pulSize,   /* file size returned here */
	    PFHT far *	 ppfht,	    /* file handle returned here */
	    PFRAME	 pfrm)
{
    POFT poft;
    PFHT pfht;
    ULONG cSectors;		/* sectors on volume */

#ifdef DEBUG
    if (usMode & OPEN_DIRECT == 0)
	INTERR (__FILE__": OPEN_DIRECT flag not set");
#endif

    /*
     * We will create a dummy OFT, which maps to the entire partition.
     *
     * We intentionally clobber some fields in the OFT to prevent unintentional
     * access to non-existant items.
     */

    /* alloc space for the OFT (we don't put in a name) */
    if ((poft = (POFT)GHS(sizeof(OFT),pfrm)) == NULL)
	return ERROR_NOT_ENOUGH_MEMORY;

    /* allocate a handle */
    if ((pfht = (PFHT)GHS(sizeof(FHT),pfrm)) == NULL) {
	RetHeap (poft);
	return (ERROR_NOT_ENOUGH_MEMORY);
    }

    /* zero out OFT */
    memset (poft, 0, sizeof (OFT));


    /* set up volume information */
    poft->pVolume = FindAnyVol(pcp->hVPB);
    if (poft->pVolume == NULL) {
#ifdef DEBUG
	dprintf ("OpenDirect: FindAnyVol returned NULL\n");
#endif

	/*
	 *  The volume has not been mounted
	 *  properly;  lose the OFT and
	 *  return an error.
	 */
	RetHeap( pfht );
	RetHeap( poft );
	return( ERROR_INVALID_HANDLE );

    }

    {	POFT	    poftScratch;

	/* insert it into the OFT list */
	poft->dcpOFTList.pFwd = poftScratch = oftHead.pFwd;
	oftHead.pFwd = poft;
	poft->dcpOFTList.pBak = (POFT) &oftHead;
	poftScratch->dcpOFTList.pBak = poft;
	cOFT++;
    }

    /* remember it's Direct Access */
    poft->bSFlag = OFS_DASD;

    /* set FHT count to 1 */
    poft->cusClientFHTs = 1;

    /* cchName is already 0 */
    cSectors = poft->pVolume->cSectsOnVol;

    if (cSectors < CSEC_BIG_DISK) {

       cSectors *= SECSIZE;	/* < 2 gig volume do normal byte I/O */

    } else {

       poft->bSFlag |= OFS_ONLYSECIO; /* large volume, do sector based I/O */
    }

    /* set extent length */
    poft->fst.a.aall[0].csecRun = cSectors;

    /* set up alblk (non-zero fields) */
    poft->fst.alb.cUsed = 1;
    poft->fst.alb.cFree = LEAFPERFNODE - 1;
    poft->fst.alb.oFree = sizeof (ALBLK) + sizeof (ALLEAF);

    /* set true, alloc, & last valid data file size */
    *pulSize =
    poft->ulFActualLen =
    poft->ulFAllocLen =
    poft->fst.ulVLen = cSectors;

/* ope300: + about 60 lines */
    /* Set up the DMask fields */
//    pfrm->flDMask = (poft->flDMask = flDirtMask) | (pfrm->usHardErr & 0xFF);
    pfrm->flDMask = poft->flDMask = flDirtMask;

    pfrm->pvol = poft->pVolume;

    if( (flDirtMask <<= 1) == 0 )
	flDirtMask = DMASK_INIT;

    /* clear flush flag */
    pfht->bFlush = 0;

    pfht->poft = poft;
    pfht->offSeek = 0;
    pfht->usMode = usMode;
	 pfht->usMode2	= 0;
#ifdef RAHEAD
    pfht->bRAFlags = 0;  /* Initialize read-ahead fields */
	 pfht->bRAReads = RA_LOW;
	 pfht->bRABigReads = RA_LOW;
#endif
    *ppfht = pfht;

    return NO_ERROR;
}
