static char rcsid[] = "$Header: efs_close.c,v 820.1 86/12/04 19:47:30 root Exp $";
static char sccsid[]="%W% %Y% %Q% %G%";

/************************************************************************
*									*
*				Copyright 1984				*
*			VALID LOGIC SYSTEMS INCORPORATED		*
*									*
*	This listing contains confidential proprietary information	*
*	which is not to be disclosed to unauthorized persons without	*
*	written consent of an officer of Valid Logic Systems 		*
*	Incorporated.							*
*									*
*	The copyright notice appearing above is included to provide	*
*	statutory protection in the event of unauthorized or 		*
*	unintentional public disclosure.				*
*									*
************************************************************************/

/*
 * Called on either last close of the
 * network special file (by the server) or
 * on the last close of a remote file.
 *
 * jam 840207-09-22
 */

#include "../h/param.h"
#include "../h/dir.h"
#include "../h/file.h"
#include "../h/user.h"

#include "../vnet/vnet.h"
#include "../conn/conn.h"
#include "../rpc/rpc.h"
#include "../efs/efs.h"

struct efs_closeCall {
	u_long		rfd;		/* Remote file descriptor */
};

struct efs_closeReturn {
	char		junk;
	char		interrupted;	/* Call was interrupted */
	char		eosys;		/* How to handle system call return */
	char		error;		/* Error number or 0 on success */
};

efs_close(dev, flag, fp)
   dev_t dev;
   struct file *fp;
{
	register struct efs_remoteFile *remote = fp->f_remote;
	register struct efs_closeCall *params;
	register struct efs_closeReturn *results;

	if (remote == NULL) {
		/*
		 * Close on special file, do nothing.
		 */
		return;
	}
	if (remote->state == EFS_FILE_CRASHED)
		u.u_error = ESERVERCRASHED;
	else {
		/*
		 * Make sure that the remote end has the
		 * correct environment for this transfer.
		 */
		efs_checkenv(remote);

		params = efs_makePacket(close, 0);
		params->rfd = remote->rfd;
		efs_incClient(closes);
		results = (struct efs_closeReturn *)
					efs_call(remote->conn,EFS_CLOSE,params);
		if (results) {
			u.u_error = results->error;
			if (results->interrupted) {
				u.u_eosys = results->eosys;
				rpc_freeResults(results);
				longjmp(&u.u_qsave);
			}
			rpc_freeResults(results);
		}
	}
	efs_freeRemoteFile(remote);
	fp->f_remote = NULL;
}

caddr_t
efs_remoteClose(clientConn, clientId, operation, params)
   connection_t *clientConn;
   u_long clientId;
   u_short operation;
   struct efs_closeCall *params;
{
	register struct efs_closeReturn *results;
	register efs_localFile_t *local;

	efs_incServer(closes);
	results = efs_makeReturnPacket(params,close, 0);
	if ((local = efs_rfdToLocal(params->rfd)) == NULL) {
		u.u_error = EBADF;
		results->interrupted = 0;
	} else {
		/*
		 * Grab the correct environment for this
		 * file descriptor.
		 */
		efs_takeenv(local);

		u.u_error = 0;
		EFS_SETJMP();
		closef(local->fp, 0, 0);
		EFS_UNSETJMP();
		efs_freeLocalFile(local);
	}
	results->error = u.u_error;
	rpc_freeParams(params);
	return((caddr_t)results);
}
