static char rcsid[] = "$Header: efs_fchown.c,v 820.1 86/12/04 19:47:34 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 chown on an open remote file.
 *
 * jht 841204-05,07 -- augment EFS with fchown.
 */

#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_CHOWN
struct efs_fchownCall {
	u_long	rfd;		/* Remote file descriptor */
	int	uidFile;	/* UID for file */
	int	gidFile;	/* GID for file */
};

struct efs_fchownReturn {
	int	error;		/* Error number or 0 on success */
};

/*
 * Client-side support for fchown().
 
 * Since the file is already 'open',
 * the uid/gid of the caller has
 * already been ajudicated.
 */
efs_fchown(fp)			/* Give file a new uid/gid */
	struct	file	*fp;
{
	register struct efs_remoteFile	 *	remote;
	register struct efs_fchownCall	 *	params;
	register struct efs_fchownReturn *	results;
	struct a {
		int	fd;
		int	uid;		/* UID for file*/
		int	gid;		/* GID for file*/
	} *uap = (struct a *)u.u_ap;

	if (fp == NULL)
		return;
	remote = fp->f_remote;
	if (remote->state == EFS_FILE_CRASHED)
		return(ESERVERCRASHED);
	params		= efs_makePacket(fchown, 0);
	params->rfd	= remote->rfd;
	params->uidFile	= uap->uid;
	params->gidFile	= uap->gid;
	efs_incClient(fchowns);
	results = (struct efs_fchownReturn *)efs_call(remote->conn,EFS_FCHOWN,params);
	if (results == NULL)
		return;
	u.u_error = results->error;
	rpc_freeResults(results);
}

/*
 * Server-side.
 */
caddr_t
efs_remoteFchown(clientConn, clientId, operation, params)
	connection_t	*	 clientConn;
	u_long			 clientId;
	u_short			 operation;
	struct	efs_fchownCall * params;
{
	register struct efs_fchownReturn * results;
	register efs_localFile_t	 * local;
	struct a {
		int	fd;
		int	uid;		/* UID for file*/
		int	gid;		/* GID for file*/
	} efs_fake_u_ap, *uap = (struct a *)&efs_fake_u_ap;

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

		if (fp == NULL) {
			results->error = EBADF;
			goto bad;
		}
		u.u_ap	 = (int *)uap;
		uap->fd  = -1;		/* (Unused -- known/bad state) */
		uap->uid = params->uidFile;
		uap->gid = params->gidFile;
		fchown1(fp);
		results->error	= u.u_error;
	}
bad:
	rpc_freeParams(params);
	return((caddr_t)results);
}
#endif	EFS_X_CHOWN
