/********************************************************************
 ** 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
 **
 ** "OPEN" file support
 **
 ** TABS to 4
 ********************************************************************/

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

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

/** INTERNAL OPEN-DOS-MSG Passed around */
struct IFHOpenMsg {
	struct	IFHDosMsg	dm;
	struct	NFSOpenFileReturn openret;	/* net-send this back */
	void	*handlerport;				/* actual msg port of the file's handler */
};
#define IFH_OPENMSG_SIZE sizeof(struct IFHOpenMsg)



/********************************************************************/
	static void free_retret_open(struct PktMsgRecv *pmr)
/********************************************************************/
{
struct IFHOpenMsg	*ifhom = (void *)pmr->user.user2;
#ifdef DEBUG
	fpf(out, "nfs_open: Freeing memory\n");
#endif


	if(!ifhom->openret.remote_res1) {
	struct InternalFH *ifh = ifhom->dm.ifh;
		REMOVE_FROM_LIST(ifh, ifh_first);
		FreeRemember(&ifh->mem, TRUE);
		FreeMem(ifh, IFH_SIZE);
	}
	FreeMem(ifhom, IFH_OPENMSG_SIZE);
	FREE_PKTMSGRECV(pmr);
}



/********************************************************************/
	static void handle_open_dos(struct IFHOpenMsg *ifhom)
/********************************************************************/
{
struct InternalFH	*ifh = ifhom->dm.ifh;
struct PktMsgRecv	*pmr = ifhom->dm.pktmsg;

#ifdef DEBUG
	fpf(out, "nfs_open: result going home, FH=%lx\n", ifh);
#endif


/** SEE IF WE GOT EVERYTHING OK */
	ifhom->openret.remote_res2 = IFHMSG_RES2(&ifhom->dm);
	if((ifhom->openret.remote_res1 = IFHMSG_RES1(&ifhom->dm))) {
		ifhom->openret.remote_ifh = RES_INTERNALFH(ifh);

		ifhom->openret.remote_ifh_Port = (long)ifh->realfh.fh_Port;
															/* means INTERACTIVE */
		if(!ifh->realfh.fh_Type)
			ifh->realfh.fh_Type = ifhom->handlerport;		/* no need usually */
	}

	PUT_STDMSG(&pmr->pm.smsg, pmr->dmaport, TYPE_INTERNAL_SEND);
															/* net-reply */
}




/********************************************************************/
	void *srv_openfile(struct PktMsgRecv *pmr)
/********************************************************************
- Allocate mem (if this fails return pointer to "error" memory)
- try to find device
- send out dosmsg (or the packet back)
- next call will be handle_return_open when DOS returns
- the free_retret_open when the packet is sent back from the server
 ********************************************************************/
{
struct NFSOpenFile	*reqpkt = (void *)pmr->req_body;
struct IFHOpenMsg	*ifhom;					/* alloc for this message */
struct InternalFH	*ifh;					/* alloc to keep! */

unsigned char *fname = pmr->pm.send_body;	/* first byte should be length - BCPL */
struct MsgPort *handlerport;

	if(!(ifh = AllocMem(IFH_SIZE, MEMF_PUBLIC | MEMF_CLEAR))) return(&nfs_res_nomem);

	if(!(ifhom = AllocMem(IFH_OPENMSG_SIZE, MEMF_PUBLIC)))
								{ FreeMem(ifh, IFH_SIZE); return(&nfs_res_nomem); }

	ADD_HEAD(ifh, ifh_first);				/* list of open files */
	ifh->realfh.fh_End = -1;				/* according to AmiDos Tech Ref manual */
	ifh->realfh.fh_Pos = -1;
	ifh->machine = pmr->pm.dest;
	ifh->majic = ifhom->openret.remote_majic = GET_MAJIC;

	INIT_IFHDOSMSG(&ifhom->dm, dosport, handle_open_dos, ifh, pmr);
	ifhom->dm.dosmsg.sp.sp_Pkt.dp_Type = reqpkt->action;
	ifhom->dm.dosmsg.sp.sp_Pkt.dp_Arg1 = CTOB(&ifh->realfh);
	ifhom->dm.dosmsg.sp.sp_Pkt.dp_Arg3 = CTOB(fname);

	INTERNAL_PREP_PKTMSG_DMA(&pmr->pm,
							EMEM_RETURNMSG,
							SERV_RETURN,
							&ifhom->openret,
							reqpkt->sr.return_len);

	pmr->user.user1 = free_retret_open;
	pmr->user.user2 = (long)ifhom;

/** FIND THE HANDLER MSG-PORT */
	handlerport =
		FindHandlerPort(&fname[1],					/* file name (NULL terminated) */
			reqpkt->internallock, reqpkt->remote_majic,	/* input addition lock offset */
					&ifhom->dm.dosmsg.sp.sp_Pkt.dp_Arg2);
													/* output addition lock offset */
#ifdef DEBUG
	fpf(out, "nfs_open: Asking handler (name=%s, msgport=%lx)\n", &fname[1], handlerport);
#endif

/** DOS MSG TO THE HANDLER */
	if(handlerport)
		PutMsg(ifhom->handlerport = handlerport, ifhom);

/** ERROR */
	else {
		ifhom->openret.remote_res1 = 0;
		ifhom->openret.remote_res2 = ERROR_OBJECT_NOT_FOUND;
		PUT_STDMSG(&pmr->pm.smsg, pmr->dmaport, TYPE_INTERNAL_SEND);
	}
	return(NULL);
}
