xref: /csrg-svn/sys/kern/vfs_vnops.c (revision 869)
1*869Sbill /*	vfs_vnops.c	3.4	09/14/80	*/
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"
1318Sbill 
1418Sbill /*
1518Sbill  * Convert a user supplied
1618Sbill  * file descriptor into a pointer
1718Sbill  * to a file structure.
1818Sbill  * Only task is to check range
1918Sbill  * of the descriptor.
2018Sbill  */
2118Sbill struct file *
2218Sbill getf(f)
2318Sbill register int f;
2418Sbill {
2518Sbill 	register struct file *fp;
2618Sbill 
2718Sbill 	if(0 <= f && f < NOFILE) {
2818Sbill 		fp = u.u_ofile[f];
2918Sbill 		if(fp != NULL)
3018Sbill 			return(fp);
3118Sbill 	}
3218Sbill 	u.u_error = EBADF;
3318Sbill 	return(NULL);
3418Sbill }
3518Sbill 
3618Sbill /*
3718Sbill  * Internal form of close.
3818Sbill  * Decrement reference count on
3918Sbill  * file structure.
4018Sbill  * Also make sure the pipe protocol
4118Sbill  * does not constipate.
4218Sbill  *
4318Sbill  * Decrement reference count on the inode following
4418Sbill  * removal to the referencing file structure.
4518Sbill  * Call device handler on last close.
4618Sbill  */
4718Sbill closef(fp)
4818Sbill register struct file *fp;
4918Sbill {
5018Sbill 	register struct inode *ip;
5118Sbill 	int flag, mode;
5218Sbill 	dev_t dev;
5318Sbill 	register int (*cfunc)();
5418Sbill 	struct chan *cp;
5518Sbill 
5618Sbill 	if(fp == NULL)
5718Sbill 		return;
5818Sbill 	if (fp->f_count > 1) {
5918Sbill 		fp->f_count--;
6018Sbill 		return;
6118Sbill 	}
6218Sbill 	ip = fp->f_inode;
6318Sbill 	flag = fp->f_flag;
6418Sbill 	cp = fp->f_un.f_chan;
6518Sbill 	dev = (dev_t)ip->i_un.i_rdev;
6618Sbill 	mode = ip->i_mode;
6718Sbill 
6818Sbill 	plock(ip);
6918Sbill 	fp->f_count = 0;
7018Sbill 	if(flag & FPIPE) {
7118Sbill 		ip->i_mode &= ~(IREAD|IWRITE);
7218Sbill 		wakeup((caddr_t)ip+1);
7318Sbill 		wakeup((caddr_t)ip+2);
7418Sbill 	}
7518Sbill 	iput(ip);
7618Sbill 
7718Sbill 	switch(mode&IFMT) {
7818Sbill 
7918Sbill 	case IFCHR:
8018Sbill 	case IFMPC:
8118Sbill 		cfunc = cdevsw[major(dev)].d_close;
8218Sbill 		break;
8318Sbill 
8418Sbill 	case IFBLK:
8518Sbill 	case IFMPB:
8618Sbill 		cfunc = bdevsw[major(dev)].d_close;
8718Sbill 		break;
8818Sbill 	default:
8918Sbill 		return;
9018Sbill 	}
9118Sbill 
9218Sbill 	if (flag & FMP)
9318Sbill 		goto call;
9418Sbill 
9518Sbill 	for(fp=file; fp < &file[NFILE]; fp++)
96*869Sbill 		if (fp->f_count && (ip=fp->f_inode)->i_un.i_rdev==dev &&
97*869Sbill 		    (ip->i_mode&IFMT) == (mode&IFMT))
9818Sbill 			return;
9918Sbill 
10018Sbill call:
10118Sbill 	(*cfunc)(dev, flag, cp);
10218Sbill }
10318Sbill 
10418Sbill /*
10518Sbill  * openi called to allow handler
10618Sbill  * of special files to initialize and
10718Sbill  * validate before actual IO.
10818Sbill  */
10918Sbill openi(ip, rw)
11018Sbill register struct inode *ip;
11118Sbill {
11218Sbill 	dev_t dev;
11318Sbill 	register unsigned int maj;
11418Sbill 
11518Sbill 	dev = (dev_t)ip->i_un.i_rdev;
11618Sbill 	maj = major(dev);
11718Sbill 	switch(ip->i_mode&IFMT) {
11818Sbill 
11918Sbill 	case IFCHR:
12018Sbill 	case IFMPC:
12118Sbill 		if(maj >= nchrdev)
12218Sbill 			goto bad;
12318Sbill 		(*cdevsw[maj].d_open)(dev, rw);
12418Sbill 		break;
12518Sbill 
12618Sbill 	case IFBLK:
12718Sbill 	case IFMPB:
12818Sbill 		if(maj >= nblkdev)
12918Sbill 			goto bad;
13018Sbill 		(*bdevsw[maj].d_open)(dev, rw);
13118Sbill 	}
13218Sbill 	return;
13318Sbill 
13418Sbill bad:
13518Sbill 	u.u_error = ENXIO;
13618Sbill }
13718Sbill 
13818Sbill /*
13918Sbill  * Check mode permission on inode pointer.
14018Sbill  * Mode is READ, WRITE or EXEC.
14118Sbill  * In the case of WRITE, the
14218Sbill  * read-only status of the file
14318Sbill  * system is checked.
14418Sbill  * Also in WRITE, prototype text
14518Sbill  * segments cannot be written.
14618Sbill  * The mode is shifted to select
14718Sbill  * the owner/group/other fields.
14818Sbill  * The super user is granted all
14918Sbill  * permissions.
15018Sbill  */
15118Sbill access(ip, mode)
15218Sbill register struct inode *ip;
15318Sbill {
15418Sbill 	register m;
15518Sbill 
15618Sbill 	m = mode;
15718Sbill 	if(m == IWRITE) {
15818Sbill 		if(getfs(ip->i_dev)->s_ronly != 0) {
15918Sbill 			u.u_error = EROFS;
16018Sbill 			return(1);
16118Sbill 		}
16218Sbill 		if (ip->i_flag&ITEXT)		/* try to free text */
16318Sbill 			xrele(ip);
16418Sbill 		if(ip->i_flag & ITEXT) {
16518Sbill 			u.u_error = ETXTBSY;
16618Sbill 			return(1);
16718Sbill 		}
16818Sbill 	}
16918Sbill 	if(u.u_uid == 0)
17018Sbill 		return(0);
17118Sbill 	if(u.u_uid != ip->i_uid) {
17218Sbill 		m >>= 3;
17318Sbill 		if(u.u_gid != ip->i_gid)
17418Sbill 			m >>= 3;
17518Sbill 	}
17618Sbill 	if((ip->i_mode&m) != 0)
17718Sbill 		return(0);
17818Sbill 
17918Sbill 	u.u_error = EACCES;
18018Sbill 	return(1);
18118Sbill }
18218Sbill 
18318Sbill /*
18418Sbill  * Look up a pathname and test if
18518Sbill  * the resultant inode is owned by the
18618Sbill  * current user.
18718Sbill  * If not, try for super-user.
18818Sbill  * If permission is granted,
18918Sbill  * return inode pointer.
19018Sbill  */
19118Sbill struct inode *
19218Sbill owner()
19318Sbill {
19418Sbill 	register struct inode *ip;
19518Sbill 
19618Sbill 	ip = namei(uchar, 0);
19718Sbill 	if(ip == NULL)
19818Sbill 		return(NULL);
19918Sbill 	if(u.u_uid == ip->i_uid)
20018Sbill 		return(ip);
20118Sbill 	if(suser())
20218Sbill 		return(ip);
20318Sbill 	iput(ip);
20418Sbill 	return(NULL);
20518Sbill }
20618Sbill 
20718Sbill /*
20818Sbill  * Test if the current user is the
20918Sbill  * super user.
21018Sbill  */
21118Sbill suser()
21218Sbill {
21318Sbill 
21418Sbill 	if(u.u_uid == 0) {
21518Sbill 		u.u_acflag |= ASU;
21618Sbill 		return(1);
21718Sbill 	}
21818Sbill 	u.u_error = EPERM;
21918Sbill 	return(0);
22018Sbill }
22118Sbill 
22218Sbill /*
22318Sbill  * Allocate a user file descriptor.
22418Sbill  */
22518Sbill ufalloc()
22618Sbill {
22718Sbill 	register i;
22818Sbill 
22918Sbill 	for(i=0; i<NOFILE; i++)
23018Sbill 		if(u.u_ofile[i] == NULL) {
23118Sbill 			u.u_r.r_val1 = i;
23218Sbill 			u.u_pofile[i] = 0;
23318Sbill 			return(i);
23418Sbill 		}
23518Sbill 	u.u_error = EMFILE;
23618Sbill 	return(-1);
23718Sbill }
23818Sbill 
239387Sbill struct	file *lastf = &file[0];
24018Sbill /*
24118Sbill  * Allocate a user file descriptor
24218Sbill  * and a file structure.
24318Sbill  * Initialize the descriptor
24418Sbill  * to point at the file structure.
24518Sbill  *
24618Sbill  * no file -- if there are no available
24718Sbill  * 	file structures.
24818Sbill  */
24918Sbill struct file *
25018Sbill falloc()
25118Sbill {
25218Sbill 	register struct file *fp;
25318Sbill 	register i;
25418Sbill 
25518Sbill 	i = ufalloc();
25618Sbill 	if(i < 0)
25718Sbill 		return(NULL);
258387Sbill 	for(fp = lastf; fp < &file[NFILE]; fp++)
259387Sbill 		if(fp->f_count == 0)
260387Sbill 			goto slot;
261387Sbill 	for(fp = &file[0]; fp < lastf; fp++)
262387Sbill 		if(fp->f_count == 0)
263387Sbill 			goto slot;
26418Sbill 	printf("no file\n");
26518Sbill 	u.u_error = ENFILE;
26618Sbill 	return(NULL);
267387Sbill slot:
268387Sbill 	u.u_ofile[i] = fp;
269387Sbill 	fp->f_count++;
270387Sbill 	fp->f_un.f_offset = 0;
271387Sbill 	lastf = fp + 1;
272387Sbill 	return(fp);
27318Sbill }
274