/*static char *SCCSID = "@(#)cols.c	6.2 92/01/31";*/
/***	cols.c - compute oft last sector
 */

#define INCL_DOSERRORS
#include <os2.h>
#include "chain.h"
#include "const.h"
#include "misc.h"
#include "buf.h"
#include "dir.h"
#include "storage.h"
#include "volume.h"
#include "tables.h"
#include "pbmsg.h"
#include "frame.h"

#include "pr_ALLOC.h"
#include "pr_CACHE.h"
#include "pr_MISC.h"

/*
 ***	COLS - Compute OFT Last Sector
 *
 *	The OFT has the last allocated physical sector # in it
 *	to facilitate extension of the file.  This is the first
 *	time that we've needed it, so we have to set it.  It will
 *	be accurate from here on out; if we grow the file we'll update
 *	it.
 *
 *	COLS should only be called on files which have at least one
 *	sector allocated to them.
 *
 *	ENTRY	poft = OFT pointer
 *
 *	EXIT	Returns new lsnLast value in OFT structure
 *		lastRunPtr in OFT structure is updated
 *		Yields CPU
 *		Returns LSN_BOGUS if error.
 *
 *	HISTORY
 *	    12-Sep-89 by JR (John Rogers, JohnRo@Microsoft)
 *		- Converted HPFS from OS/2 1.2 to run with OS/2 2.0 (commented
 *		  first field in struct ALBLK: must be first for FIELDOFFSET
 *		  macro usage in COLS()).
 */

LSN
COLS (OFT far *poft, PFRAME pfrm)
{
    ALBLK far * palb = & (poft->fst.alb);

    /*	Optimize for code size.  Perform node walking first and
     *	fall into leaf walking
     */

    while ((palb->bFlag & ABF_NODE) != 0) {
	if (palb->cUsed == 0)
	    INTERR (PBMSG_COLS_NODE_EMPTY);

	/*  Sleazy code!  Set up the LSN part of the SECPTR, let
	 *  RDBUF fill in the pbufHint part.  Also, to save stack/code
	 *  have RDBUF point palb at the beginning of the sector.  Since
	 *  we are reading in an ALSEC, we must advance palb appropriately
	 */

	if ((palb = RdBuf(poft->LastRun.scpLastRun.lsn =
			  PALNFROMPALB(palb)[palb->cUsed-1].lsnPhys,
			  BP_KEEP,
			  &(poft->LastRun.scpLastRun.pbufHint),
			  pfrm )) == NULL)

	  return LSN_BOGUS;

//#114986
#ifndef MINIFSD
   if (poft->LastRun.scpLastRun.pbufHint->fFlag & BFL_LZREAD) {
     if (LazyRead (poft->LastRun.scpLastRun.pbufHint, pfrm))
	    return LSN_BOGUS;
   }
#endif

	/* LastRun.scpLastRun.lsn does not contain the volume info -
	 * so add it
	 */
	poft->LastRun.scpLastRun.lsn &= SECMASK; /* clear volume bits */

	poft->LastRun.scpLastRun.lsn |=
		      (poft->LastRun.scpLastRun.pbufHint->lsnSec & ~(SECMASK));

	/*  palb really points to an ALSEC.  Advance it to point to alb field.
	 *  Note: This depends on alb.bFlag being first field in ALBLK.
	 */
	OFFSETOF (palb) += FIELDOFFSET (ALSEC, alb.bFlag);
	}

    if (palb->cUsed == 0)
	INTERR (PBMSG_COLS_LEAF_EMPTY);

    /*	palb points to lowest-level leaf block.
     *
     *	To save stack, reuse palb by treating it as an ALLEAF
     */

#define pall	MAKETYPE(palb,PALLEAF)

    pall = &(PALLFROMPALB(palb)[palb->cUsed-1]);

    if ((poft->fst.alb.bFlag & ABF_NODE) == 0)
   	poft->LastRun.pallLastRun = pall;

    return poft->lsnLast = pall->lsnPhys + pall->csecRun - 1;
#undef pall
}
