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

/*
 * Perform a chmod on an open remote file.
 *
 * jht 841204-05,07 -- augment EFS with fchmod.
 */

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

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

#ifdef	EFS_X_CHMOD
struct efs_fchmodCall {		/* Params/call pkt		*/
	u_long	rfd;		/* Remote file descriptor	*/
	int	fmode;		/* File mode a la' chmod(2)	*/
};

struct efs_fchmodReturn {	/* Results/return pkt		*/
	int	error;		/* Error number or 0 on success */
};

/*
 * Client-side support for fchmod().
 
 * Since the file is already 'open',
 * the uid/gid of the caller has
 * already been ajudicated.
 */
efs_fchmod(fp)
	struct	file	*fp;
{
	register struct efs_remoteFile	 *	remote = fp->f_remote;
	register struct efs_fchmodCall	 *	params;
	register struct efs_fchmodReturn *	results;
	struct a {
		int	fd;
		int	fmode;		/* File mode a la' chmod(2) */
	} *uap = (struct a *)u.u_ap;

	if (remote->state == EFS_FILE_CRASHED)
		return(ESERVERCRASHED);
	params		= efs_makePacket(fchmod, 0);
	params->rfd	= remote->rfd;
	params->fmode	= uap->fmode;
	efs_incClient(fchmods);
	results = (struct efs_fchmodReturn *)efs_call(remote->conn,EFS_FCHMOD,params);
	if (results == NULL)
		return;
	u.u_error = results->error;
	rpc_freeResults(results);
}

/*
 * Server-side.
 */
caddr_t
efs_remoteFchmod(clientConn, clientId, operation, params)
	connection_t	*	 clientConn;
	u_long			 clientId;
	u_short			 operation;
	struct	efs_fchmodCall * params;
{
	register struct efs_fchmodReturn * results;
	register struct inode		 * ip;
	register efs_localFile_t	 * local;
	struct a {
		int	fd;
		int	fmode;		/* File mode a la' chmod(2) */
	} efs_fake_u_ap, *uap = (struct a *)&efs_fake_u_ap;

	efs_incServer(fchmods);
	results = efs_makeReturnPacket(params,fchmod, 0);
	if (results == NULL)
		goto bad;
	if ((local = efs_rfdToLocal(params->rfd)) == NULL)
		results->error = EBADF;
	else {
		register struct file * fp = local->fp;

		results->error = 0;
		if (fp == NULL) {
			results->error = EBADF;
			goto bad;
		}
		u.u_ap	 = (int *)uap;
		uap->fd    = -1;	/* (Unused -- known/bad state) */
		uap->fmode = params->fmode;
		fchmod1(fp);
		results->error = u.u_error;
	}
bad:
	rpc_freeParams(params);
	return((caddr_t)results);
}
#endif	EFS_X_CHMOD
