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