xref: /csrg-svn/sys/kern/vfs_vnops.c (revision 387)
1*387Sbill /*	vfs_vnops.c	3.3	07/19/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++)
9618Sbill 		if (fp->f_count && fp->f_inode==ip)
9718Sbill 			return;
9818Sbill 
9918Sbill call:
10018Sbill 	(*cfunc)(dev, flag, cp);
10118Sbill }
10218Sbill 
10318Sbill /*
10418Sbill  * openi called to allow handler
10518Sbill  * of special files to initialize and
10618Sbill  * validate before actual IO.
10718Sbill  */
10818Sbill openi(ip, rw)
10918Sbill register struct inode *ip;
11018Sbill {
11118Sbill 	dev_t dev;
11218Sbill 	register unsigned int maj;
11318Sbill 
11418Sbill 	dev = (dev_t)ip->i_un.i_rdev;
11518Sbill 	maj = major(dev);
11618Sbill 	switch(ip->i_mode&IFMT) {
11718Sbill 
11818Sbill 	case IFCHR:
11918Sbill 	case IFMPC:
12018Sbill 		if(maj >= nchrdev)
12118Sbill 			goto bad;
12218Sbill 		(*cdevsw[maj].d_open)(dev, rw);
12318Sbill 		break;
12418Sbill 
12518Sbill 	case IFBLK:
12618Sbill 	case IFMPB:
12718Sbill 		if(maj >= nblkdev)
12818Sbill 			goto bad;
12918Sbill 		(*bdevsw[maj].d_open)(dev, rw);
13018Sbill 	}
13118Sbill 	return;
13218Sbill 
13318Sbill bad:
13418Sbill 	u.u_error = ENXIO;
13518Sbill }
13618Sbill 
13718Sbill /*
13818Sbill  * Check mode permission on inode pointer.
13918Sbill  * Mode is READ, WRITE or EXEC.
14018Sbill  * In the case of WRITE, the
14118Sbill  * read-only status of the file
14218Sbill  * system is checked.
14318Sbill  * Also in WRITE, prototype text
14418Sbill  * segments cannot be written.
14518Sbill  * The mode is shifted to select
14618Sbill  * the owner/group/other fields.
14718Sbill  * The super user is granted all
14818Sbill  * permissions.
14918Sbill  */
15018Sbill access(ip, mode)
15118Sbill register struct inode *ip;
15218Sbill {
15318Sbill 	register m;
15418Sbill 
15518Sbill 	m = mode;
15618Sbill 	if(m == IWRITE) {
15718Sbill 		if(getfs(ip->i_dev)->s_ronly != 0) {
15818Sbill 			u.u_error = EROFS;
15918Sbill 			return(1);
16018Sbill 		}
16118Sbill 		if (ip->i_flag&ITEXT)		/* try to free text */
16218Sbill 			xrele(ip);
16318Sbill 		if(ip->i_flag & ITEXT) {
16418Sbill 			u.u_error = ETXTBSY;
16518Sbill 			return(1);
16618Sbill 		}
16718Sbill 	}
16818Sbill 	if(u.u_uid == 0)
16918Sbill 		return(0);
17018Sbill 	if(u.u_uid != ip->i_uid) {
17118Sbill 		m >>= 3;
17218Sbill 		if(u.u_gid != ip->i_gid)
17318Sbill 			m >>= 3;
17418Sbill 	}
17518Sbill 	if((ip->i_mode&m) != 0)
17618Sbill 		return(0);
17718Sbill 
17818Sbill 	u.u_error = EACCES;
17918Sbill 	return(1);
18018Sbill }
18118Sbill 
18218Sbill /*
18318Sbill  * Look up a pathname and test if
18418Sbill  * the resultant inode is owned by the
18518Sbill  * current user.
18618Sbill  * If not, try for super-user.
18718Sbill  * If permission is granted,
18818Sbill  * return inode pointer.
18918Sbill  */
19018Sbill struct inode *
19118Sbill owner()
19218Sbill {
19318Sbill 	register struct inode *ip;
19418Sbill 
19518Sbill 	ip = namei(uchar, 0);
19618Sbill 	if(ip == NULL)
19718Sbill 		return(NULL);
19818Sbill 	if(u.u_uid == ip->i_uid)
19918Sbill 		return(ip);
20018Sbill 	if(suser())
20118Sbill 		return(ip);
20218Sbill 	iput(ip);
20318Sbill 	return(NULL);
20418Sbill }
20518Sbill 
20618Sbill /*
20718Sbill  * Test if the current user is the
20818Sbill  * super user.
20918Sbill  */
21018Sbill suser()
21118Sbill {
21218Sbill 
21318Sbill 	if(u.u_uid == 0) {
21418Sbill 		u.u_acflag |= ASU;
21518Sbill 		return(1);
21618Sbill 	}
21718Sbill 	u.u_error = EPERM;
21818Sbill 	return(0);
21918Sbill }
22018Sbill 
22118Sbill /*
22218Sbill  * Allocate a user file descriptor.
22318Sbill  */
22418Sbill ufalloc()
22518Sbill {
22618Sbill 	register i;
22718Sbill 
22818Sbill 	for(i=0; i<NOFILE; i++)
22918Sbill 		if(u.u_ofile[i] == NULL) {
23018Sbill 			u.u_r.r_val1 = i;
23118Sbill 			u.u_pofile[i] = 0;
23218Sbill 			return(i);
23318Sbill 		}
23418Sbill 	u.u_error = EMFILE;
23518Sbill 	return(-1);
23618Sbill }
23718Sbill 
238*387Sbill struct	file *lastf = &file[0];
23918Sbill /*
24018Sbill  * Allocate a user file descriptor
24118Sbill  * and a file structure.
24218Sbill  * Initialize the descriptor
24318Sbill  * to point at the file structure.
24418Sbill  *
24518Sbill  * no file -- if there are no available
24618Sbill  * 	file structures.
24718Sbill  */
24818Sbill struct file *
24918Sbill falloc()
25018Sbill {
25118Sbill 	register struct file *fp;
25218Sbill 	register i;
25318Sbill 
25418Sbill 	i = ufalloc();
25518Sbill 	if(i < 0)
25618Sbill 		return(NULL);
257*387Sbill 	for(fp = lastf; fp < &file[NFILE]; fp++)
258*387Sbill 		if(fp->f_count == 0)
259*387Sbill 			goto slot;
260*387Sbill 	for(fp = &file[0]; fp < lastf; fp++)
261*387Sbill 		if(fp->f_count == 0)
262*387Sbill 			goto slot;
26318Sbill 	printf("no file\n");
26418Sbill 	u.u_error = ENFILE;
26518Sbill 	return(NULL);
266*387Sbill slot:
267*387Sbill 	u.u_ofile[i] = fp;
268*387Sbill 	fp->f_count++;
269*387Sbill 	fp->f_un.f_offset = 0;
270*387Sbill 	lastf = fp + 1;
271*387Sbill 	return(fp);
27218Sbill }
273