xref: /csrg-svn/sys/kern/vfs_vnops.c (revision 2932)
1*2932Swnj /*	vfs_vnops.c	4.7	03/06/81	*/
218Sbill 
318Sbill #include "../h/param.h"
418Sbill #include "../h/systm.h"
518Sbill #include "../h/dir.h"
618Sbill #include "../h/user.h"
718Sbill #include "../h/filsys.h"
818Sbill #include "../h/file.h"
918Sbill #include "../h/conf.h"
1018Sbill #include "../h/inode.h"
1118Sbill #include "../h/reg.h"
1218Sbill #include "../h/acct.h"
132302Skre #include "../h/mount.h"
1418Sbill 
1518Sbill /*
1618Sbill  * Convert a user supplied
1718Sbill  * file descriptor into a pointer
1818Sbill  * to a file structure.
1918Sbill  * Only task is to check range
2018Sbill  * of the descriptor.
2118Sbill  */
2218Sbill struct file *
2318Sbill getf(f)
2418Sbill register int f;
2518Sbill {
2618Sbill 	register struct file *fp;
2718Sbill 
282329Swnj 	if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
292329Swnj 		u.u_error = EBADF;
302329Swnj 		return (NULL);
3118Sbill 	}
322329Swnj 	return (fp);
3318Sbill }
3418Sbill 
3518Sbill /*
3618Sbill  * Internal form of close.
3718Sbill  * Decrement reference count on
3818Sbill  * file structure.
3918Sbill  * Also make sure the pipe protocol
4018Sbill  * does not constipate.
4118Sbill  *
4218Sbill  * Decrement reference count on the inode following
4318Sbill  * removal to the referencing file structure.
4418Sbill  * Call device handler on last close.
4518Sbill  */
4618Sbill closef(fp)
4718Sbill register struct file *fp;
4818Sbill {
4918Sbill 	register struct inode *ip;
502302Skre 	register struct mount *mp;
5118Sbill 	int flag, mode;
5218Sbill 	dev_t dev;
5318Sbill 	register int (*cfunc)();
5418Sbill 
5518Sbill 	if(fp == NULL)
5618Sbill 		return;
5718Sbill 	if (fp->f_count > 1) {
5818Sbill 		fp->f_count--;
5918Sbill 		return;
6018Sbill 	}
6118Sbill 	ip = fp->f_inode;
6218Sbill 	flag = fp->f_flag;
6318Sbill 	dev = (dev_t)ip->i_un.i_rdev;
642302Skre 	mode = ip->i_mode & IFMT;
6518Sbill 
6618Sbill 	plock(ip);
6718Sbill 	fp->f_count = 0;
6818Sbill 	if(flag & FPIPE) {
6918Sbill 		ip->i_mode &= ~(IREAD|IWRITE);
7018Sbill 		wakeup((caddr_t)ip+1);
7118Sbill 		wakeup((caddr_t)ip+2);
7218Sbill 	}
7318Sbill 	iput(ip);
7418Sbill 
752302Skre 	switch(mode) {
7618Sbill 
7718Sbill 	case IFCHR:
7818Sbill 	case IFMPC:
7918Sbill 		cfunc = cdevsw[major(dev)].d_close;
8018Sbill 		break;
8118Sbill 
8218Sbill 	case IFBLK:
832302Skre 		/*
842302Skre 		 * We don't want to really close the device if it is mounted
852302Skre 		 */
862302Skre 		for (mp = mount; mp < &mount[NMOUNT]; mp++)
872302Skre 			if (mp->m_bufp != NULL && mp->m_dev == dev)
882302Skre 				return;
8918Sbill 	case IFMPB:
9018Sbill 		cfunc = bdevsw[major(dev)].d_close;
9118Sbill 		break;
9218Sbill 	default:
9318Sbill 		return;
9418Sbill 	}
9518Sbill 
962302Skre 	if ((flag & FMP) == 0) {
972738Swnj 		for(fp=file; fp < fileNFILE; fp++)
982302Skre 			if (fp->f_count && (ip=fp->f_inode)->i_un.i_rdev==dev &&
992302Skre 			    (ip->i_mode&IFMT) == mode)
1002302Skre 				return;
1012302Skre 		if (mode == IFBLK) {
1022302Skre 			/*
1032302Skre 			 * on last close of a block device (that isn't mounted)
1042302Skre 			 * we must invalidate any in core blocks
1052302Skre 			 */
1062302Skre 			bflush(dev);
1072302Skre 			binval(dev);
1082302Skre 		}
1092302Skre 	}
1102274Swnj 	(*cfunc)(dev, flag, fp);
11118Sbill }
11218Sbill 
11318Sbill /*
11418Sbill  * openi called to allow handler
11518Sbill  * of special files to initialize and
11618Sbill  * validate before actual IO.
11718Sbill  */
11818Sbill openi(ip, rw)
11918Sbill register struct inode *ip;
12018Sbill {
12118Sbill 	dev_t dev;
12218Sbill 	register unsigned int maj;
12318Sbill 
12418Sbill 	dev = (dev_t)ip->i_un.i_rdev;
12518Sbill 	maj = major(dev);
12618Sbill 	switch(ip->i_mode&IFMT) {
12718Sbill 
12818Sbill 	case IFCHR:
12918Sbill 	case IFMPC:
13018Sbill 		if(maj >= nchrdev)
13118Sbill 			goto bad;
13218Sbill 		(*cdevsw[maj].d_open)(dev, rw);
13318Sbill 		break;
13418Sbill 
13518Sbill 	case IFBLK:
13618Sbill 	case IFMPB:
13718Sbill 		if(maj >= nblkdev)
13818Sbill 			goto bad;
13918Sbill 		(*bdevsw[maj].d_open)(dev, rw);
14018Sbill 	}
14118Sbill 	return;
14218Sbill 
14318Sbill bad:
14418Sbill 	u.u_error = ENXIO;
14518Sbill }
14618Sbill 
14718Sbill /*
14818Sbill  * Check mode permission on inode pointer.
14918Sbill  * Mode is READ, WRITE or EXEC.
15018Sbill  * In the case of WRITE, the
15118Sbill  * read-only status of the file
15218Sbill  * system is checked.
15318Sbill  * Also in WRITE, prototype text
15418Sbill  * segments cannot be written.
15518Sbill  * The mode is shifted to select
15618Sbill  * the owner/group/other fields.
15718Sbill  * The super user is granted all
15818Sbill  * permissions.
15918Sbill  */
16018Sbill access(ip, mode)
16118Sbill register struct inode *ip;
16218Sbill {
16318Sbill 	register m;
16418Sbill 
16518Sbill 	m = mode;
16618Sbill 	if(m == IWRITE) {
16718Sbill 		if(getfs(ip->i_dev)->s_ronly != 0) {
16818Sbill 			u.u_error = EROFS;
16918Sbill 			return(1);
17018Sbill 		}
17118Sbill 		if (ip->i_flag&ITEXT)		/* try to free text */
17218Sbill 			xrele(ip);
17318Sbill 		if(ip->i_flag & ITEXT) {
17418Sbill 			u.u_error = ETXTBSY;
17518Sbill 			return(1);
17618Sbill 		}
17718Sbill 	}
17818Sbill 	if(u.u_uid == 0)
17918Sbill 		return(0);
18018Sbill 	if(u.u_uid != ip->i_uid) {
18118Sbill 		m >>= 3;
18218Sbill 		if(u.u_gid != ip->i_gid)
18318Sbill 			m >>= 3;
18418Sbill 	}
18518Sbill 	if((ip->i_mode&m) != 0)
18618Sbill 		return(0);
18718Sbill 
18818Sbill 	u.u_error = EACCES;
18918Sbill 	return(1);
19018Sbill }
19118Sbill 
19218Sbill /*
19318Sbill  * Look up a pathname and test if
19418Sbill  * the resultant inode is owned by the
19518Sbill  * current user.
19618Sbill  * If not, try for super-user.
19718Sbill  * If permission is granted,
19818Sbill  * return inode pointer.
19918Sbill  */
20018Sbill struct inode *
20118Sbill owner()
20218Sbill {
20318Sbill 	register struct inode *ip;
20418Sbill 
20518Sbill 	ip = namei(uchar, 0);
20618Sbill 	if(ip == NULL)
20718Sbill 		return(NULL);
20818Sbill 	if(u.u_uid == ip->i_uid)
20918Sbill 		return(ip);
21018Sbill 	if(suser())
21118Sbill 		return(ip);
21218Sbill 	iput(ip);
21318Sbill 	return(NULL);
21418Sbill }
21518Sbill 
21618Sbill /*
21718Sbill  * Test if the current user is the
21818Sbill  * super user.
21918Sbill  */
22018Sbill suser()
22118Sbill {
22218Sbill 
22318Sbill 	if(u.u_uid == 0) {
22418Sbill 		u.u_acflag |= ASU;
22518Sbill 		return(1);
22618Sbill 	}
22718Sbill 	u.u_error = EPERM;
22818Sbill 	return(0);
22918Sbill }
23018Sbill 
23118Sbill /*
23218Sbill  * Allocate a user file descriptor.
23318Sbill  */
23418Sbill ufalloc()
23518Sbill {
23618Sbill 	register i;
23718Sbill 
23818Sbill 	for(i=0; i<NOFILE; i++)
23918Sbill 		if(u.u_ofile[i] == NULL) {
24018Sbill 			u.u_r.r_val1 = i;
24118Sbill 			u.u_pofile[i] = 0;
24218Sbill 			return(i);
24318Sbill 		}
24418Sbill 	u.u_error = EMFILE;
24518Sbill 	return(-1);
24618Sbill }
24718Sbill 
2482768Swnj struct	file *lastf;
24918Sbill /*
25018Sbill  * Allocate a user file descriptor
25118Sbill  * and a file structure.
25218Sbill  * Initialize the descriptor
25318Sbill  * to point at the file structure.
25418Sbill  */
25518Sbill struct file *
25618Sbill falloc()
25718Sbill {
25818Sbill 	register struct file *fp;
25918Sbill 	register i;
26018Sbill 
26118Sbill 	i = ufalloc();
2622768Swnj 	if (i < 0)
26318Sbill 		return(NULL);
2642768Swnj 	if (lastf == 0)
2652768Swnj 		lastf = file;
2662768Swnj 	for (fp = lastf; fp < fileNFILE; fp++)
2672768Swnj 		if (fp->f_count == 0)
268387Sbill 			goto slot;
2692768Swnj 	for (fp = file; fp < lastf; fp++)
2702768Swnj 		if (fp->f_count == 0)
271387Sbill 			goto slot;
272*2932Swnj 	tablefull("file");
27318Sbill 	u.u_error = ENFILE;
2742768Swnj 	return (NULL);
275387Sbill slot:
276387Sbill 	u.u_ofile[i] = fp;
277387Sbill 	fp->f_count++;
278387Sbill 	fp->f_un.f_offset = 0;
279387Sbill 	lastf = fp + 1;
2802768Swnj 	return (fp);
28118Sbill }
282