/*static char *SCCSID = "@(#)wrtalb.c	6.3 92/02/10";*/
#define BSWAP0 BSWAP0

#include <os2def.h>

#include "storage.h"

#include "const.h"
#include "misc.h"
#include "buf.h"
#include "ea.h"
#include "fnode.h"
#include "chain.h"
#include "dir.h"
#include "volume.h"
#include "tables.h"
#include "pbmacros.h"
#include "frame.h"
#include "lw.h"
#include "fsdata.h"

#include "pr_alloc.h"
#include "pr_cache.h"
#include "pr_ea.h"
#include "pr_read.h"
#include "pr_write.h"

/*
 ***	WriteALB - Write to an ALBLK Allocation Tree
 *
 *	WriteALB writes a data stream to the sectors specified in
 *	an ALBLK allocation tree.  We start at offset 0, the caller
 *	must guarantee that the allocation tree is long enough.
 *
 *	ENTRY	cbToWrite (ecx) = size of data to write
 *		pbData	  (esi) = address of data to write
 *		palb	  (edi) = ALBLK address
 *
 *	RETURNS TRUE if OK
 *		FALSE if hard error
 *
 *	HISTORY
 *	    19-Sep-89 by JR (John Rogers, JohnRo@Microsoft)
 *		- Avoid warnings from Microsoft C 5.2 (on slash-slash comments).
 */

BOOL
WriteALB( USHORT cbToWrite,
	  PBYTE pbData,
	  PALBLK palb,
	  PFRAME pfrm)
{
    ULONG ulSeekPtr = 0;    /* byte offset into the data area */
    ULONG ulContig;	    /* number of contiguous sectors left in this extent */
    ULONG lsn;		    /* current sector number */
    PBUFNODE pbuf;	    /* buffer header of current sector */
    PBYTE pbDest;	    /* pointer to current sectcor */
    USHORT cb;		    /* temporary count of bytes to write (per iteration) */

    /* We're gonna do this the easy way - we'll get each sector into
     * the cache, and then write it.  This is slow because we call
     * RdBuf a lot and because when we're going to write a whole
     * cache block of data, we'll read the thing in when we do the first
     * RdBuf on it, when we should just do a write.  Well, large EAs
     * are rare, so sue me.  BUGBUG - upgrade this later when EAs become
     * more popular.
     */

    while (cbToWrite > 0) {

	lsn = CPS_Far(ulSeekPtr, palb, &ulContig, FALSE, pfrm); //#101488

    if (lsn == LSN_BOGUS)
	return(FALSE);

	while (cbToWrite > 0 && ulContig > 0) {

//test
//	    pbDest = GetInBuf(lsn,(USHORT)ulContig,BP_KEEP,&pbuf,pfrm);

#ifndef MINIFSD

       if ((pbDest = InitLzRd (lsn, &pbuf, pfrm)) == NULL)
         pbDest = GetInBuf(lsn, (USHORT)ulContig, BP_KEEP, &pbuf, pfrm);

#else
	    pbDest = GetInBuf(lsn,(USHORT)ulContig,BP_KEEP,&pbuf,pfrm);
#endif

	    if (pbDest == NULL)
		return(FALSE);

	    cb = MIN (cbToWrite, SECSIZE);
	    memcpy (pbDest, pbData, cb);

#ifndef MINIFSD
       if (pbuf->fFlag & BFL_LZREAD)
	      ClrLzRdBitFar((USHORT)(POINTER_SUBTRACT(pbDest, pbuf->pblkData)),
	                 cb, pbuf, pfrm);
#endif

	    SetDirt(pbDest, pbuf, pfrm->u.fWrtThru, pfrm);

	    cbToWrite -= cb;

	    if (cbToWrite > 0) {
		/* more to write */
		ulSeekPtr += SECSIZE;

		pbData += cb;

		if (--ulContig > 0) {
		    /* more to write in this extent */
		    lsn++;
		}
	    }
	}
    }

    /* Done with the write */
    return(TRUE);
}
