xref: /csrg-svn/sys/kern/vfs_vnops.c (revision 18)
1*18Sbill /*	vfs_vnops.c	3.1	10/14/12	*/
2*18Sbill 
3*18Sbill #include "../h/param.h"
4*18Sbill #include "../h/systm.h"
5*18Sbill #include "../h/dir.h"
6*18Sbill #include "../h/user.h"
7*18Sbill #include "../h/filsys.h"
8*18Sbill #include "../h/file.h"
9*18Sbill #include "../h/conf.h"
10*18Sbill #include "../h/inode.h"
11*18Sbill #include "../h/reg.h"
12*18Sbill #include "../h/acct.h"
13*18Sbill 
14*18Sbill /*
15*18Sbill  * Convert a user supplied
16*18Sbill  * file descriptor into a pointer
17*18Sbill  * to a file structure.
18*18Sbill  * Only task is to check range
19*18Sbill  * of the descriptor.
20*18Sbill  */
21*18Sbill struct file *
22*18Sbill getf(f)
23*18Sbill register int f;
24*18Sbill {
25*18Sbill 	register struct file *fp;
26*18Sbill 
27*18Sbill 	if(0 <= f && f < NOFILE) {
28*18Sbill 		fp = u.u_ofile[f];
29*18Sbill 		if(fp != NULL)
30*18Sbill 			return(fp);
31*18Sbill 	}
32*18Sbill 	u.u_error = EBADF;
33*18Sbill 	return(NULL);
34*18Sbill }
35*18Sbill 
36*18Sbill /*
37*18Sbill  * Internal form of close.
38*18Sbill  * Decrement reference count on
39*18Sbill  * file structure.
40*18Sbill  * Also make sure the pipe protocol
41*18Sbill  * does not constipate.
42*18Sbill  *
43*18Sbill  * Decrement reference count on the inode following
44*18Sbill  * removal to the referencing file structure.
45*18Sbill  * Call device handler on last close.
46*18Sbill  */
47*18Sbill closef(fp)
48*18Sbill register struct file *fp;
49*18Sbill {
50*18Sbill 	register struct inode *ip;
51*18Sbill 	int flag, mode;
52*18Sbill 	dev_t dev;
53*18Sbill 	register int (*cfunc)();
54*18Sbill 	struct chan *cp;
55*18Sbill 
56*18Sbill 	if(fp == NULL)
57*18Sbill 		return;
58*18Sbill 	if (fp->f_count > 1) {
59*18Sbill 		fp->f_count--;
60*18Sbill 		return;
61*18Sbill 	}
62*18Sbill 	ip = fp->f_inode;
63*18Sbill 	flag = fp->f_flag;
64*18Sbill 	cp = fp->f_un.f_chan;
65*18Sbill 	dev = (dev_t)ip->i_un.i_rdev;
66*18Sbill 	mode = ip->i_mode;
67*18Sbill 
68*18Sbill 	plock(ip);
69*18Sbill 	fp->f_count = 0;
70*18Sbill 	if(flag & FPIPE) {
71*18Sbill 		ip->i_mode &= ~(IREAD|IWRITE);
72*18Sbill 		wakeup((caddr_t)ip+1);
73*18Sbill 		wakeup((caddr_t)ip+2);
74*18Sbill 	}
75*18Sbill 	iput(ip);
76*18Sbill 
77*18Sbill 	switch(mode&IFMT) {
78*18Sbill 
79*18Sbill 	case IFCHR:
80*18Sbill 	case IFMPC:
81*18Sbill 		cfunc = cdevsw[major(dev)].d_close;
82*18Sbill 		break;
83*18Sbill 
84*18Sbill 	case IFBLK:
85*18Sbill 	case IFMPB:
86*18Sbill 		cfunc = bdevsw[major(dev)].d_close;
87*18Sbill 		break;
88*18Sbill 	default:
89*18Sbill 		return;
90*18Sbill 	}
91*18Sbill 
92*18Sbill 	if (flag & FMP)
93*18Sbill 		goto call;
94*18Sbill 
95*18Sbill 	for(fp=file; fp < &file[NFILE]; fp++)
96*18Sbill 		if (fp->f_count && fp->f_inode==ip)
97*18Sbill 			return;
98*18Sbill 
99*18Sbill call:
100*18Sbill 	(*cfunc)(dev, flag, cp);
101*18Sbill }
102*18Sbill 
103*18Sbill /*
104*18Sbill  * openi called to allow handler
105*18Sbill  * of special files to initialize and
106*18Sbill  * validate before actual IO.
107*18Sbill  */
108*18Sbill openi(ip, rw)
109*18Sbill register struct inode *ip;
110*18Sbill {
111*18Sbill 	dev_t dev;
112*18Sbill 	register unsigned int maj;
113*18Sbill 
114*18Sbill 	dev = (dev_t)ip->i_un.i_rdev;
115*18Sbill 	maj = major(dev);
116*18Sbill 	switch(ip->i_mode&IFMT) {
117*18Sbill 
118*18Sbill 	case IFCHR:
119*18Sbill 	case IFMPC:
120*18Sbill 		if(maj >= nchrdev)
121*18Sbill 			goto bad;
122*18Sbill 		(*cdevsw[maj].d_open)(dev, rw);
123*18Sbill 		break;
124*18Sbill 
125*18Sbill 	case IFBLK:
126*18Sbill 	case IFMPB:
127*18Sbill 		if(maj >= nblkdev)
128*18Sbill 			goto bad;
129*18Sbill 		(*bdevsw[maj].d_open)(dev, rw);
130*18Sbill 	}
131*18Sbill 	return;
132*18Sbill 
133*18Sbill bad:
134*18Sbill 	u.u_error = ENXIO;
135*18Sbill }
136*18Sbill 
137*18Sbill /*
138*18Sbill  * Check mode permission on inode pointer.
139*18Sbill  * Mode is READ, WRITE or EXEC.
140*18Sbill  * In the case of WRITE, the
141*18Sbill  * read-only status of the file
142*18Sbill  * system is checked.
143*18Sbill  * Also in WRITE, prototype text
144*18Sbill  * segments cannot be written.
145*18Sbill  * The mode is shifted to select
146*18Sbill  * the owner/group/other fields.
147*18Sbill  * The super user is granted all
148*18Sbill  * permissions.
149*18Sbill  */
150*18Sbill access(ip, mode)
151*18Sbill register struct inode *ip;
152*18Sbill {
153*18Sbill 	register m;
154*18Sbill 
155*18Sbill 	m = mode;
156*18Sbill 	if(m == IWRITE) {
157*18Sbill 		if(getfs(ip->i_dev)->s_ronly != 0) {
158*18Sbill 			u.u_error = EROFS;
159*18Sbill 			return(1);
160*18Sbill 		}
161*18Sbill 		if (ip->i_flag&ITEXT)		/* try to free text */
162*18Sbill 			xrele(ip);
163*18Sbill 		if(ip->i_flag & ITEXT) {
164*18Sbill 			u.u_error = ETXTBSY;
165*18Sbill 			return(1);
166*18Sbill 		}
167*18Sbill 	}
168*18Sbill 	if(u.u_uid == 0)
169*18Sbill 		return(0);
170*18Sbill 	if(u.u_uid != ip->i_uid) {
171*18Sbill 		m >>= 3;
172*18Sbill 		if(u.u_gid != ip->i_gid)
173*18Sbill 			m >>= 3;
174*18Sbill 	}
175*18Sbill 	if((ip->i_mode&m) != 0)
176*18Sbill 		return(0);
177*18Sbill 
178*18Sbill 	u.u_error = EACCES;
179*18Sbill 	return(1);
180*18Sbill }
181*18Sbill 
182*18Sbill /*
183*18Sbill  * Look up a pathname and test if
184*18Sbill  * the resultant inode is owned by the
185*18Sbill  * current user.
186*18Sbill  * If not, try for super-user.
187*18Sbill  * If permission is granted,
188*18Sbill  * return inode pointer.
189*18Sbill  */
190*18Sbill struct inode *
191*18Sbill owner()
192*18Sbill {
193*18Sbill 	register struct inode *ip;
194*18Sbill 
195*18Sbill 	ip = namei(uchar, 0);
196*18Sbill 	if(ip == NULL)
197*18Sbill 		return(NULL);
198*18Sbill 	if(u.u_uid == ip->i_uid)
199*18Sbill 		return(ip);
200*18Sbill 	if(suser())
201*18Sbill 		return(ip);
202*18Sbill 	iput(ip);
203*18Sbill 	return(NULL);
204*18Sbill }
205*18Sbill 
206*18Sbill /*
207*18Sbill  * Test if the current user is the
208*18Sbill  * super user.
209*18Sbill  */
210*18Sbill suser()
211*18Sbill {
212*18Sbill 
213*18Sbill 	if(u.u_uid == 0) {
214*18Sbill 		u.u_acflag |= ASU;
215*18Sbill 		return(1);
216*18Sbill 	}
217*18Sbill 	u.u_error = EPERM;
218*18Sbill 	return(0);
219*18Sbill }
220*18Sbill 
221*18Sbill /*
222*18Sbill  * Allocate a user file descriptor.
223*18Sbill  */
224*18Sbill ufalloc()
225*18Sbill {
226*18Sbill 	register i;
227*18Sbill 
228*18Sbill 	for(i=0; i<NOFILE; i++)
229*18Sbill 		if(u.u_ofile[i] == NULL) {
230*18Sbill 			u.u_r.r_val1 = i;
231*18Sbill 			u.u_pofile[i] = 0;
232*18Sbill 			return(i);
233*18Sbill 		}
234*18Sbill 	u.u_error = EMFILE;
235*18Sbill 	return(-1);
236*18Sbill }
237*18Sbill 
238*18Sbill /*
239*18Sbill  * Allocate a user file descriptor
240*18Sbill  * and a file structure.
241*18Sbill  * Initialize the descriptor
242*18Sbill  * to point at the file structure.
243*18Sbill  *
244*18Sbill  * no file -- if there are no available
245*18Sbill  * 	file structures.
246*18Sbill  */
247*18Sbill struct file *
248*18Sbill falloc()
249*18Sbill {
250*18Sbill 	register struct file *fp;
251*18Sbill 	register i;
252*18Sbill 
253*18Sbill 	i = ufalloc();
254*18Sbill 	if(i < 0)
255*18Sbill 		return(NULL);
256*18Sbill 	for(fp = &file[0]; fp < &file[NFILE]; fp++)
257*18Sbill 		if(fp->f_count == 0) {
258*18Sbill 			u.u_ofile[i] = fp;
259*18Sbill 			fp->f_count++;
260*18Sbill 			fp->f_un.f_offset = 0;
261*18Sbill 			return(fp);
262*18Sbill 		}
263*18Sbill 	printf("no file\n");
264*18Sbill 	u.u_error = ENFILE;
265*18Sbill 	return(NULL);
266*18Sbill }
267