static char rcsid[] = "$Header: dfs_fio.c,v 820.1 86/12/04 19:44:08 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.				*
*									*
************************************************************************/

/*
 * DFS routines for ufs_fio.c
 *
 *	Bakul Shah
 *
 * bvs 840501 -- original version
 * jht 841115,16,26-29 -- complete conversion to use prpc.
 * jht 850213 -- add dfsPktHdr_t containing version/functionality info to pkts.
 * jht 850301 -- conversion to use new errno.h error-code mnemonics.
 * jht 850401 -- fill out the gathering of statistics.
 */

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

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

#include "../h/inode.h"
#include "../h/socket.h"
#include "../h/kernel.h"
#include "../net/if.h"
#include "../h/mbuf.h"


typedef struct dfsc_access {	/* Pkt from client --> server */
#ifdef	DFS_PACKETHDR
	dfsPktHdr_t	dfsPktHdr;	/* Info about DFS versions, etc	*/
#endif	DFS_PACKETHDR
	caddr_t 	ip;		/* Remote file descriptor  */
	long		mode;		/* Offset into remote file */
	int		uid;		/* UID of caller */
	int		gid;		/* GID of caller */
	int		groups[NGROUPS];/* Groups we have permission for */
} dfsc_access_t;

typedef struct dfsr_access {	/* Pkt from client <-- server */
#ifdef	DFS_PACKETHDR
	dfsPktHdr_t	dfsPktHdr;	/* Info about DFS versions, etc	*/
#endif	DFS_PACKETHDR
	int		error;		/* Error number or 0 on success  */
	int		value;		/* Number of bytes actually read */
} dfsr_access_t;

/*
 * Remote access.
 * Sockets can not be created on a remote machine.
 * Pack mode, uid, cmask, offset, count, parent dir ip, groups
 * in a call packet and make a remote call.
 * The result contans the inode ptr and contents of inode.
 */
dfsClient_access(ip, mode)
	register struct inode *  ip;
{
	register dfsc_access_t * call;
	register dfsr_access_t * result;
	register int		 value;
	
	dfs_incClient(access);
	if (!dfsClient_validContext(ip, "access"))
		return 1;
	call = DFSC_PACKET(access);
	if (!call)
		return 1;
	call->mode = mode;
	call->ip = ip->i_rmt_ip;
	call->uid = u.u_uid;
	call->gid = u.u_gid;
	groupstombuf(call->groups, u.u_groups);
	result       = DFS_CALL(ip->i_host,access,call);
	if (!result)
		return 1;
	if (u.u_error = result->error)
		return 1;
	value = result->value;
	DFS_FREE_RESULTS(result);
	return value;
}

/*
 * Remote access.
 */
dfsr_access_t *
dfsServer_access(clientConn, clientId, operation, call)
	connection_t	*	clientConn;	/* Host we are serving	*/
	u_long			clientId;	/* Specific client@host	*/
	u_short			operation;	/* Redundant: what to do*/
	register dfsc_access_t * call;		/* Call pkt -- params	*/
{
	register dfsr_access_t * result;
	register dfs_remote_t * rp;

	dfs_incServer(access);
	if (!dfsServer_validContext(operation, call, "access")) {
		DFS_FREE_PARAMS(call);
		return NULL;
	}
	result = DFSR_PACKET(access);
	if (!result) {
		DFS_FREE_PARAMS(call);
		return NULL;		/* Say "no result pkt" */
	}
	rp = dfs_rmt_find(DFS_NODE(clientConn), call->ip);
	if (!rp || !(rp->flags & DFS_RMT_LOCKED)) {
		u.u_error = !rp ? DFS_EBADRMTDESC : DFS_ERMTNOTLOCKED;
		goto ret;
	}
	rp->locktime = UPTIME();
	u.u_uid = DFS_UID(call->uid, clientConn);
	u.u_gid = DFS_GID(call->gid, clientConn);
	mbuftogroups(u.u_groups, call->groups);
	result->value = access(rp->ip, call->mode);
ret:
	result->error = u.u_error;
	DFS_FREE_PARAMS(call);
	DFS_RETURN(result);
}

typedef struct dfsc_openi {	/* Pkt from client --> server */
#ifdef	DFS_PACKETHDR
	dfsPktHdr_t	dfsPktHdr;	/* Info about DFS versions, etc	*/
#endif	DFS_PACKETHDR
	caddr_t 	ip;		/* Ptr to inode			*/
	long		mode;		/* Mode  arg of openi (flags)	*/
	long		fmode;		/* Fmode arg of openi		*/	
} dfsc_openi_t;

typedef struct dfsr_openi {	/* Pkt from client <-- server */
#ifdef	DFS_PACKETHDR
	dfsPktHdr_t	dfsPktHdr;	/* Info about DFS versions, etc	*/
#endif	DFS_PACKETHDR
	int		error;		/* Error number or 0 on success */
} dfsr_openi_t;

/*
 * 
 */
dfsClient_openi(ip, mode, fmode)
	register struct inode * ip;
{
	register dfsc_openi_t * call;
	register dfsr_openi_t * result;

	
	dfs_incClient(openi);
	if (!dfsClient_validContext(ip, "openi"))
		return u.u_error;
	call = DFSC_PACKET(openi);
	if (!call)
		return u.u_error;
	call->mode	= mode;
	call->fmode	= fmode;
	call->ip	= ip->i_rmt_ip;
	result = DFS_CALL(ip->i_host,openi,call);
	if (!result)
		return u.u_error;
	u.u_error = result->error;
	DFS_FREE_RESULTS(result);
	return u.u_error;
}

dfsr_openi_t *
dfsServer_openi(clientConn, clientId, operation, call)
	connection_t	*	clientConn;	/* Host we are serving	*/
	u_long			clientId;	/* Specific client@host	*/
	u_short			operation;	/* Redundant: what to do*/
	register dfsc_openi_t * call;		/* Call pkt -- params	*/
{
	register dfsr_openi_t * result;
	register dfs_remote_t * rp;
	register struct inode * ip;

	dfs_incServer(openi);
	if (!dfsServer_validContext(operation, call, "openi")) {
		DFS_FREE_PARAMS(call);
		return NULL;
	}
	result = DFSR_PACKET(openi);
	if (!result) {
		DFS_FREE_PARAMS(call);
		return NULL;		/* Say "no result pkt" */
	}
	rp = dfs_rmt_find(DFS_NODE(clientConn), call->ip);
	if (!rp) {
		u.u_error = DFS_EBADRMTDESC;
		goto ret;
	}
	rp->locktime = UPTIME();
	if (!(ip = rp->ip)) {
		u.u_error = DFS_EINVAL;
		goto ret;
	}

	u.u_error = openi(ip, call->mode, call->fmode);
ret:
	result->error = u.u_error;
	DFS_FREE_PARAMS(call);
	DFS_RETURN(result);
}
