xref: /csrg-svn/sys/kern/vfs_vnops.c (revision 17099)
1*17099Sbloom /*	vfs_vnops.c	6.3	84/08/29	*/
218Sbill 
39764Ssam #include "../machine/reg.h"
49764Ssam 
5*17099Sbloom #include "param.h"
6*17099Sbloom #include "systm.h"
7*17099Sbloom #include "dir.h"
8*17099Sbloom #include "user.h"
9*17099Sbloom #include "fs.h"
10*17099Sbloom #include "file.h"
11*17099Sbloom #include "conf.h"
12*17099Sbloom #include "inode.h"
13*17099Sbloom #include "acct.h"
14*17099Sbloom #include "mount.h"
15*17099Sbloom #include "socket.h"
16*17099Sbloom #include "socketvar.h"
17*17099Sbloom #include "proc.h"
1818Sbill 
1918Sbill /*
2018Sbill  * Check mode permission on inode pointer.
2118Sbill  * Mode is READ, WRITE or EXEC.
2218Sbill  * In the case of WRITE, the
2318Sbill  * read-only status of the file
2418Sbill  * system is checked.
2518Sbill  * Also in WRITE, prototype text
2618Sbill  * segments cannot be written.
2718Sbill  * The mode is shifted to select
2818Sbill  * the owner/group/other fields.
2918Sbill  * The super user is granted all
3018Sbill  * permissions.
3118Sbill  */
3218Sbill access(ip, mode)
334817Swnj 	register struct inode *ip;
344817Swnj 	int mode;
3518Sbill {
3618Sbill 	register m;
377867Sroot 	register int *gp;
3818Sbill 
3918Sbill 	m = mode;
404817Swnj 	if (m == IWRITE) {
4111162Ssam 		/*
4211162Ssam 		 * Disallow write attempts on read-only
4311162Ssam 		 * file systems; unless the file is a block
4411162Ssam 		 * or character device resident on the
4511162Ssam 		 * file system.
4611162Ssam 		 */
476569Smckusic 		if (ip->i_fs->fs_ronly != 0) {
488956Sroot 			if ((ip->i_mode & IFMT) != IFCHR &&
498956Sroot 			    (ip->i_mode & IFMT) != IFBLK) {
508956Sroot 				u.u_error = EROFS;
518956Sroot 				return (1);
528956Sroot 			}
5318Sbill 		}
5411162Ssam 		/*
5511162Ssam 		 * If there's shared text associated with
5611162Ssam 		 * the inode, try to free it up once.  If
5711162Ssam 		 * we fail, we can't allow writing.
5811162Ssam 		 */
5911162Ssam 		if (ip->i_flag&ITEXT)
6018Sbill 			xrele(ip);
614817Swnj 		if (ip->i_flag & ITEXT) {
6218Sbill 			u.u_error = ETXTBSY;
634817Swnj 			return (1);
6418Sbill 		}
6518Sbill 	}
6611162Ssam 	/*
6711162Ssam 	 * If you're the super-user,
6811162Ssam 	 * you always get access.
6911162Ssam 	 */
704817Swnj 	if (u.u_uid == 0)
714817Swnj 		return (0);
7211162Ssam 	/*
7311162Ssam 	 * Access check is based on only
7411162Ssam 	 * one of owner, group, public.
7511162Ssam 	 * If not owner, then check group.
7611162Ssam 	 * If not a member of the group, then
7711162Ssam 	 * check public access.
7811162Ssam 	 */
794817Swnj 	if (u.u_uid != ip->i_uid) {
8018Sbill 		m >>= 3;
8111162Ssam 		if (u.u_gid == ip->i_gid)
8211162Ssam 			goto found;
8311812Ssam 		gp = u.u_groups;
8411812Ssam 		for (; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++)
8510044Ssam 			if (ip->i_gid == *gp)
867867Sroot 				goto found;
877867Sroot 		m >>= 3;
887867Sroot found:
897867Sroot 		;
9018Sbill 	}
914817Swnj 	if ((ip->i_mode&m) != 0)
924817Swnj 		return (0);
9318Sbill 	u.u_error = EACCES;
944817Swnj 	return (1);
9518Sbill }
9618Sbill 
9718Sbill /*
9818Sbill  * Look up a pathname and test if
9918Sbill  * the resultant inode is owned by the
10018Sbill  * current user.
10118Sbill  * If not, try for super-user.
10218Sbill  * If permission is granted,
10318Sbill  * return inode pointer.
10418Sbill  */
10518Sbill struct inode *
10616693Smckusick owner(fname, follow)
10716693Smckusick 	caddr_t fname;
1085990Swnj 	int follow;
10918Sbill {
11018Sbill 	register struct inode *ip;
11116693Smckusick 	register struct nameidata *ndp = &u.u_nd;
11218Sbill 
11316693Smckusick 	ndp->ni_nameiop = LOOKUP | follow;
11416693Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
11516693Smckusick 	ndp->ni_dirp = fname;
11616693Smckusick 	ip = namei(ndp);
1174817Swnj 	if (ip == NULL)
1184817Swnj 		return (NULL);
1194817Swnj 	if (u.u_uid == ip->i_uid)
1204817Swnj 		return (ip);
1214817Swnj 	if (suser())
1224817Swnj 		return (ip);
12318Sbill 	iput(ip);
1244817Swnj 	return (NULL);
12518Sbill }
12618Sbill 
12718Sbill /*
12818Sbill  * Test if the current user is the
12918Sbill  * super user.
13018Sbill  */
13118Sbill suser()
13218Sbill {
13318Sbill 
1344817Swnj 	if (u.u_uid == 0) {
13518Sbill 		u.u_acflag |= ASU;
1364817Swnj 		return (1);
13718Sbill 	}
13818Sbill 	u.u_error = EPERM;
1394817Swnj 	return (0);
14018Sbill }
141