/*static char *SCCSID = "@(#)appaux.c	6.2 92/01/31";*/
#define BSWAP0 BSWAP0

#define INCL_DOSERRORS
#include <os2def.h>
#include <bse.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 "pbmacros.h"
#include "lw.h"
#include "frame.h"
#include "fsdata.h"

#include "pr_debug.h"
#include "pr_ea.h"
#include "pr_heap.h"
#include "pr_misc.h"

/*
 ***	AppendAux - Append Auxilliary Info
 *
 *	AppendAux appends data to an auxillary info structure.
 *
 *	FOR NOW, THE STRUCTURE MUST BE EMPTY.
 *
 *	ENTRY	paxi   (eax) = address of AUXINFO structure in the fnode
 *		pfnd   (ebx) = fnode address
 *		cb     (edx) = length
 *		pbData (esi) = data address
 *		lsn    (edi) = sector # within fnode cache block
 *
 *	RETURNS NO_ERROR if OK
 *		error code if not OK
 *
 *	NOTES	Although this function is called AppendAux,
 *		it is only halfway implemented to append and therefore
 *		will fail terribly if used to append info to the end
 *		of an Aux Info list.  It should be cleaned up and renamed
 *		FillAux().
 *
 *	BUGBUG - SetEA assumes this can only return
 *		 NO_ERROR or ERROR_READ_FAULT, fix SetEA if we ever
 *		 finish this routine
 *
 *	HISTORY
 *	    19-Sep-89 by JR (John Rogers, JohnRo@Microsoft)
 *		- Avoid warnings from Microsoft C 5.2 (on slash-slash comments).
 */

#if FALSE
typedef AAWORK struct {		 /* stack frame for working values */
 PAUXINFO paxi;			 /* address of AUXINFO structure */
 USHORT	  cbWrite;		 /* # of bytes to write */
 LSN	  lsnNear;		 /* sector # near fnode */
 PBYTE	  pbData;		 /* data address */
} AAWORK;
#endif

USHORT
AppendAux(PAUXINFO paxi,
	  PFNODE pfnd,
	  USHORT cb,
	  PBYTE pbData,
	  LSN lsn,
	  PFRAME pfrm)
{
    PALBLK palb;

#ifdef DEBUG
    if ((USHORT)paxi->sp.cbRun != 0)
	/* seek wasn't zero! */
	dprintf (__FILE__": seek wasn't zero!");

    if (paxi->usFNL != 0)
	dprintf (__FILE__": usFNL wasn't zero!");
#endif

    /* See if there's enough space in the FNODE to hold this info
     * in the fnode.  If not, there's no use storing just some in
     * the fnode, so we'll move it all to disk
     *
     * BUGBUG - this won't work unless the paxi is empty
     *	we could end up with half of the auxinfo in the fnode and half
     *	in a b-tree.
     */
    if((sizeof(FNODE) -
	    (pfnd->usACLBase + pfnd->aiACL.usFNL + pfnd->aiEA.usFNL)) >= cb) {
	/* Good news - it all fits in the fnode.  Stuff 'em in */

	if ((PBYTE) &paxi == (PBYTE) &pfnd->aiACL) {

#ifdef ACL_API

	    /* Growing the perm. list.  The EA list is in the way, so
	     * move it down.
	     */

	    /* aaux10: */

#ifdef DEBUG
	    dprintf ("AppendAux: move the EA list\n");
#endif

	    if (pfnd->aiEA.usFNL != 0) {
		/* EA to move */

		/* NOTE: The 386 ASM code for this only works if the
		 *	 existing perm.  list is empty.  The following
		 *	 code should work in any case.
		 */

		{
		    USHORT i;
		    PBYTE  pSrc, pDst;

		    i = pfnd->aiEA.usFNL;

		    pSrc = (PBYTE)pfnd + pfnd->usACLBase + pfnd->aiACL.usFNL;
		    pDst = (PBYTE)pfnd + pfnd->usACLBase +
						      pfnd->aiACL.usFNL + cb;

		    BYTE_COPY_DN( pSrc + i, pDst + i, i );

		}
		/* This is how it should look!!
		 *
		 * memmove ((PBYTE)(pfnd +  pfnd->usACLBase +
		 *				    pfnd->aiACL.usFNL + cb),
		 *	   (PBYTE)(pfnd + pfnd->usACLBase +
		 *				    pfnd->aiACL.usFNL),
		 *	   pfnd->aiEA.usFNL);
		 */
	    }

	    memcpy( ((PBYTE)pfnd + pfnd->usACLBase), pbData, cb);
#endif /* no ACL_API */

	} else {

	    /* Growing the EA list, which follows the perm. list.  Just
	     * move it in.
	     */

	    /* NOTE:  The 386 ASM code for this only works if the
	     *	      existing EA list is empty.  The following
	     *	      code shosuld work in any case.
	     *
	     * memcpy( (pfnd + pfnd->usACLBase +
	     *		pfnd->aiACL.usFNL + pfnd->aiEA.usFNL),
	     *		pbData, cb);
	     *
	     * BUGBUG - since this has more far pointer data references
	     * and we have already said that this has to be rewritten
	     * to work with non-empty paxi's, I am going to
	     * put in code here that also won't work with a non empty paxi.
	     */
#ifdef DEBUG
	    if( pfnd->aiEA.usFNL != 0 )
		INTERR(__FILE__": EA list is not empty" );
#endif
	    memcpy( ((PBYTE)pfnd + pfnd->usACLBase + pfnd->aiACL.usFNL), pbData, cb);

	}

	paxi->usFNL += cb;

	return NO_ERROR;
    }

    /* We've got to take some disk space. */

    /* We don't have an ALBLK structure because it wastes too much
     * space, so we'll build noe for the occasion.
     */

#ifdef DEBUG
    if ((USHORT)paxi->sp.cbRun != 0)
	INTERR (__FILE__": already have disk allocation");
#endif

    CHECKSWAP(&swapBSWAP0);
    palb = BuildAlBlk(&(paxi->sp),FALSE,pfrm);

    CHECKSWAP(&swapBSWAP0);
    if ((EAA (palb, lsn, cb,pfrm)) == FALSE) {

	/*
	 * Could be hard error or disk full, assume the more common one
	 */
	RetHeap( palb );
	/*  Note:  11/16/88 asm adds RetHeap(paxi), which can't be right */
	return( GetHardErr( ERROR_DISK_FULL ) );
    }
    else {
	CHECKSWAP(&swapBSWAP0);
	paxi->bDat = LOBYTE (BuildEAAT (&(paxi->sp), palb));

	paxi->sp.cbRun += cb;

	CHECKSWAP(&swapBSWAP0);
	if ( !WriteALB (cb, pbData, palb, pfrm) ) {

	    RetHeap( palb );
	    return( ERROR_READ_FAULT );
	}

	RetHeap (palb);

	return NO_ERROR;
    }
}
