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