4.3BSD release version
[unix-history] / usr / src / sys / kern / vfs_vnops.c
/*
* Copyright (c) 1982, 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
* @(#)vfs_vnops.c 7.1 (Berkeley) %G%
*/
#include "../machine/reg.h"
#include "param.h"
#include "systm.h"
#include "dir.h"
#include "user.h"
#include "fs.h"
#include "file.h"
#include "conf.h"
#include "inode.h"
#include "acct.h"
#include "mount.h"
#include "socket.h"
#include "socketvar.h"
#include "proc.h"
/*
* Check mode permission on inode pointer.
* Mode is READ, WRITE or EXEC.
* In the case of WRITE, the
* read-only status of the file
* system is checked.
* Also in WRITE, prototype text
* segments cannot be written.
* The mode is shifted to select
* the owner/group/other fields.
* The super user is granted all
* permissions.
*/
access(ip, mode)
register struct inode *ip;
int mode;
{
register m;
register gid_t *gp;
m = mode;
if (m == IWRITE) {
/*
* Disallow write attempts on read-only
* file systems; unless the file is a block
* or character device resident on the
* file system.
*/
if (ip->i_fs->fs_ronly != 0) {
if ((ip->i_mode & IFMT) != IFCHR &&
(ip->i_mode & IFMT) != IFBLK) {
u.u_error = EROFS;
return (1);
}
}
/*
* If there's shared text associated with
* the inode, try to free it up once. If
* we fail, we can't allow writing.
*/
if (ip->i_flag&ITEXT)
xrele(ip);
if (ip->i_flag & ITEXT) {
u.u_error = ETXTBSY;
return (1);
}
}
/*
* If you're the super-user,
* you always get access.
*/
if (u.u_uid == 0)
return (0);
/*
* Access check is based on only
* one of owner, group, public.
* If not owner, then check group.
* If not a member of the group, then
* check public access.
*/
if (u.u_uid != ip->i_uid) {
m >>= 3;
if (u.u_gid == ip->i_gid)
goto found;
gp = u.u_groups;
for (; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++)
if (ip->i_gid == *gp)
goto found;
m >>= 3;
found:
;
}
if ((ip->i_mode&m) != 0)
return (0);
u.u_error = EACCES;
return (1);
}
/*
* 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 *
owner(fname, follow)
caddr_t fname;
int follow;
{
register struct inode *ip;
register struct nameidata *ndp = &u.u_nd;
ndp->ni_nameiop = LOOKUP | follow;
ndp->ni_segflg = UIO_USERSPACE;
ndp->ni_dirp = fname;
ip = namei(ndp);
if (ip == NULL)
return (NULL);
if (u.u_uid == ip->i_uid)
return (ip);
if (suser())
return (ip);
iput(ip);
return (NULL);
}
/*
* Test if the current user is the
* super user.
*/
suser()
{
if (u.u_uid == 0) {
u.u_acflag |= ASU;
return (1);
}
u.u_error = EPERM;
return (0);
}