/********************************************************************
 ** NETWORK FILE SYSTEM SERVICE
 **
 ** (c) Spak, Darrell Tam, c9107253@ee.newcastle.edu.au (1994)
 ** phone (Australia) 049-829-710
 **                    49-829-710
 ** (c) SST Jan-Feb-Mar 1994
 **
 ** "EXAMINE" (locate_object) file support
 **
 ** CURRENTLY SLOW BECAUSE THE SENDER HAS TO SEND BACK THE OLD FIB
 ** AmigaDOS style FOR EXAMINENEXT
 ** Possible solutions:
 ** 1) Send only the old filename and disk key back
 ** 2) Keep track locally and assume that a given lock will only
 **    be examined by one thread at a time (?? legal??)
 **
 ** TABS to 4
 ********************************************************************/

#include "/snd/everything.h"
#include <st/st_proto.h>

#include "nfsinternal.h"
#include "nfsglobs_protos.h"
#include "misc_protos.h"


/** the following 2 structures must be compatible for the beginning */
#define EXAMINEMSG_SIZE (sizeof(struct ExamineDosMsg))
struct ExamineDosMsg {
	struct DosMsg		dm;
	struct NFSStdReturn examineret;
	struct PktMsgRecv	*pmr;
	struct FileInfoBlock *fib;		/* should point to fib_real */
	long   allocsize;

	/** long word aligned */
	struct FileInfoBlock fib_real;

};


#define EXNEXTMSG_SIZE (sizeof(struct ExNextDosMsg))
struct ExNextDosMsg {
	struct DosMsg		dm;
	struct NFSStdReturn examineret;
	struct PktMsgRecv	*pmr;
	struct FileInfoBlock *fib;
	long   allocsize;
};







/********************************************************************/
	static void free_retret_examine(struct PktMsgRecv *pmr)
/********************************************************************/
{
struct ExNextDosMsg *exdm = (void *)pmr->user.user2;

#ifdef DEBUG
	fpf(out, "nfs_examine: Freeing memory\n");
#endif
	FreeMem(exdm, exdm->allocsize);
	FREE_PKTMSGRECV(pmr);
}


/********************************************************************/
	static void handle_examine_net(struct PktMsgRecv *pmr)
/********************************************************************/
{
struct	ExNextDosMsg *exdm = (void *)pmr->user.user2;
struct	NFSExamine *req = (void *)pmr->req_body;

#ifdef DEBUG
	fpf(out, "nfs_examine: Return\n");
#endif
	pmr->user.user1 = free_retret_examine;			/* up above */
	INTERNAL_PREP_PKTMSG_DMA(&pmr->pm, EMEM_RETURNMSG, SERV_RETURN,
					&exdm->examineret, req->sr.return_len);
	PUT_STDMSG(&pmr->pm.smsg, pmr->dmaport, TYPE_INTERNAL_SEND);
}



/********************************************************************/
	static void handle_examine_dos(struct ExamineDosMsg *exdm)
/********************************************************************/
{
struct PktMsgRecv *pmr = exdm->pmr;
struct NFSExamine *req = (void *)pmr->req_body;

#ifdef DEBUG
	fpf(out, "nfs_examine: result going home\n");
#endif

	pmr->user.user2 = (long)exdm;					/* yep */

/** SEE IF WE SHOULD SEND BACK THE FIB */
	exdm->examineret.remote_res2 = exdm->dm.sp.sp_Pkt.dp_Res2;
	if(!(exdm->examineret.remote_res1 = exdm->dm.sp.sp_Pkt.dp_Res1)) {
		handle_examine_net(pmr);
		return;
	}

/** SEND BACK THE FILEINFOBLOCK */
	pmr->user.user1 = handle_examine_net;			/* up above */
	INTERNAL_PREP_PKTMSG_DMA(&pmr->pm, EMEM_RETURNMSG, SERV_RESULT,
					exdm->fib, req->sr.result_len);
	PUT_STDMSG(&pmr->pm.smsg, pmr->dmaport, TYPE_INTERNAL_SEND);
}







/********************************************************************/
	void *srv_examinelock(struct PktMsgRecv *pmr)
/********************************************************************/
{
struct	NFSExamine		*req = (void *)pmr->req_body;
struct	InternalLock	*orig_il =
		GET_INTERNALLOCK(req->remote_il, req->remote_majic);
struct	ExamineDosMsg	*exdm;

	if(!orig_il) return(&nfs_res_notfound);
	ACT_ALLOCMSG_THINGY(exdm, EXAMINEMSG_SIZE);			/* get dosmsgpkt+return memory */

	exdm->pmr = pmr;
	exdm->fib = &exdm->fib_real;
	exdm->allocsize = EXAMINEMSG_SIZE;

	INIT_DOS_MSG(&exdm->dm, dosport, handle_examine_dos);
	exdm->dm.sp.sp_Pkt.dp_Type = ACTION_EXAMINE_OBJECT;
	exdm->dm.sp.sp_Pkt.dp_Arg1 = CTOB(orig_il->reallock);
	exdm->dm.sp.sp_Pkt.dp_Arg2 = CTOB(exdm->fib);
	PutMsg(orig_il->reallock->fl_Task, exdm);
	return(NULL);
}




/********************************************************************/
	void *srv_examinenext(struct PktMsgRecv *pmr)
/********************************************************************/
{
struct	NFSExamine		*req = (void *)pmr->req_body;
struct	InternalLock	*orig_il =
		GET_INTERNALLOCK(req->remote_il, req->remote_majic);
struct	ExNextDosMsg	*exdm;

	if(!orig_il || pmr->pm.send_len < sizeof(struct FileInfoBlock))
		return(&nfs_res_notfound);

	ACT_ALLOCMSG_THINGY(exdm, EXNEXTMSG_SIZE);		/* get dosmsgpkt+return memory */

	exdm->pmr = pmr;
	exdm->fib = pmr->pm.send_body;					/* write all over this */
	exdm->allocsize = EXNEXTMSG_SIZE;

	INIT_DOS_MSG(&exdm->dm, dosport, handle_examine_dos);
	exdm->dm.sp.sp_Pkt.dp_Type = ACTION_EXAMINE_NEXT;
	exdm->dm.sp.sp_Pkt.dp_Arg1 = CTOB(orig_il->reallock);
	exdm->dm.sp.sp_Pkt.dp_Arg2 = CTOB(exdm->fib);
	PutMsg(orig_il->reallock->fl_Task, exdm);
	return(NULL);
}


