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

/************************************************************************
*									*
*				Copyright 1984, 1985			*
*			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.				*
*									*
************************************************************************/

/*
 * Handle a remote chown call.  Pass the
 * path name to the remote machine.
 *
 * jht 841204-05,07 -- augment EFS with chown.
 * smj 850813	Remove (enable) refs to NET_SUPER_USER.
 */

#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 "../h/nami.h"

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

#ifdef	EFS_X_CHOWN
struct efs_chownCall {
	int		uidFile;	/* New	uid	*/
	int		gidFile;	/* New	gid	*/
	int		uidCaller;	/* Caller's uid	*/
	int		gidCaller;	/* Caller's gid	*/
	/* Null terminated fname follows this structure */
};

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

/*
 * Client-side Support for chown().
 */
efs_chown(fnamep, uidFile, gidFile)
	char	*fnamep;
	int	 uidFile;	/* New uid for the file */
	int	 gidFile;
{
	register connection_t	*	 conn;
	register struct efs_chownCall	*params;
	register struct efs_chownReturn *results;

	if ((conn = efs_uhostLookup()) == NULL) {
		u.u_error = EHOSTUNREACH;
		return;
	}
	params			= efs_makePacket(chown,EFS_PATHSIZE);
	params->uidFile		= uidFile;	/* For the file	*/
	params->gidFile		= gidFile;

	params->uidCaller	= u.u_uid;	/* Of the user	*/
	params->gidCaller	= u.u_gid;
	efs_getPathname(efs_data(params));	/* fname */

	efs_incClient(chowns);
	results = (struct efs_chownReturn *)efs_call(conn,EFS_CHOWN,params);
	if (results == NULL)
		return;
	u.u_error = results->error;
	rpc_freeResults(results);
}

/*
 * Server side.
 */
caddr_t
efs_remoteChown(clientConn, clientId, operation, params)
	connection_t	*	clientConn;
	u_long			clientId;
	u_short			operation;
	struct	efs_chownCall *	params;
{
	register struct efs_chownReturn *results;
	register struct inode		*ip;
	extern	 struct inode		*efs_owner();
	extern	 mbufchar();

	efs_incServer(chowns);
	/*
	 * BUG: Does this subvert the context
	 * set up by prpc?
	 */
	u.u_uid = u.u_ruid = params->uidCaller;
	u.u_gid = u.u_rgid = params->gidCaller;
	efs_checkNetsu();
	u.u_error = 0;
	results   = efs_makeReturnPacket(params,chown, 0);
	u.u_dirp  = efs_data(params);	/* fname */

	if (suser() && (ip = efs_owner(mbufchar, 0/*follow*/))) {
		u.u_error = chown1(ip, params->uidFile, params->gidFile);
		iput(ip);
	}
	results->error = u.u_error;
	rpc_freeParams(params);
	return((caddr_t)results);
}
#endif	EFS_X_CHOWN
/*
 * Identical with 'owner()',
 * except that it takes
 * the additional argument, 'func()'.
 *
 * Look up a pathname and test if
 * the resultant inode is owned by the
 * current user.
 * If not, try for super-user.
 * If permission is granted,
 * return inode pointer.
 */
 struct inode *
efs_owner(func, follow)
	int (*func)();
	int follow;
{
	register struct inode *ip;

	ip = namei(func, LOOKUP, follow);
	if (ip == NULL)
		return (NULL);
	if (u.u_uid == ip->i_uid)
		return (ip);
	if (suser())
		return (ip);
	iput(ip);
	return (NULL);
}
