xref: /csrg-svn/sys/kern/kern_descrip.c (revision 39514)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)kern_descrip.c	7.7 (Berkeley) 11/12/89
18  */
19 
20 #include "param.h"
21 #include "systm.h"
22 #include "syscontext.h"
23 #include "kernel.h"
24 #include "vnode.h"
25 #include "proc.h"
26 #include "file.h"
27 #include "socket.h"
28 #include "socketvar.h"
29 #include "mount.h"
30 #include "stat.h"
31 
32 #include "ioctl.h"
33 
34 /*
35  * Descriptor management.
36  */
37 
38 /*
39  * System calls on descriptors.
40  */
41 getdtablesize()
42 {
43 
44 	u.u_r.r_val1 = NOFILE;
45 }
46 
47 dup()
48 {
49 	register struct a {
50 		int	i;
51 	} *uap = (struct a *) u.u_ap;
52 	struct file *fp;
53 	int j;
54 
55 	if (uap->i &~ 077) { uap->i &= 077; dup2(); return; }	/* XXX */
56 
57 	if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL)
58 		RETURN (EBADF);
59 	if (u.u_error = ufalloc(0, &j))
60 		return;
61 	u.u_r.r_val1 = j;
62 	dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
63 }
64 
65 dup2()
66 {
67 	register struct a {
68 		int	i, j;
69 	} *uap = (struct a *) u.u_ap;
70 	register struct file *fp;
71 	int error;
72 
73 	if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL)
74 		RETURN (EBADF);
75 	if (uap->j < 0 || uap->j >= NOFILE)
76 		RETURN (EBADF);
77 	u.u_r.r_val1 = uap->j;
78 	if (uap->i == uap->j)
79 		RETURN (0);
80 	if (u.u_ofile[uap->j]) {
81 		if (u.u_pofile[uap->j] & UF_MAPPED)
82 			munmapfd(uap->j);
83 		error = closef(u.u_ofile[uap->j]);
84 	}
85 	dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
86 	/*
87 	 * dup2() must succeed even though the close had an error.
88 	 */
89 	error = 0;		/* XXX */
90 	RETURN (error);
91 }
92 
93 dupit(fd, fp, flags)
94 	int fd;
95 	register struct file *fp;
96 	register int flags;
97 {
98 
99 	u.u_ofile[fd] = fp;
100 	u.u_pofile[fd] = flags;
101 	fp->f_count++;
102 	if (fd > u.u_lastfile)
103 		u.u_lastfile = fd;
104 }
105 
106 /*
107  * The file control system call.
108  */
109 fcntl()
110 {
111 	register struct file *fp;
112 	register struct a {
113 		int	fdes;
114 		int	cmd;
115 		int	arg;
116 	} *uap = (struct a *)u.u_ap;
117 	register char *pop;
118 	int i;
119 
120 	if ((unsigned)uap->fdes >= NOFILE ||
121 	    (fp = u.u_ofile[uap->fdes]) == NULL)
122 		RETURN (EBADF);
123 	pop = &u.u_pofile[uap->fdes];
124 	switch(uap->cmd) {
125 	case F_DUPFD:
126 		if (uap->arg < 0 || uap->arg >= NOFILE) {
127 			u.u_error = EINVAL;
128 			return;
129 		}
130 		if (u.u_error = ufalloc(uap->arg, &i))
131 			return;
132 		u.u_r.r_val1 = i;
133 		dupit(i, fp, *pop &~ UF_EXCLOSE);
134 		break;
135 
136 	case F_GETFD:
137 		u.u_r.r_val1 = *pop & 1;
138 		break;
139 
140 	case F_SETFD:
141 		*pop = (*pop &~ 1) | (uap->arg & 1);
142 		break;
143 
144 	case F_GETFL:
145 		u.u_r.r_val1 = fp->f_flag+FOPEN;
146 		break;
147 
148 	case F_SETFL:
149 		fp->f_flag &= FCNTLCANT;
150 		fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT;
151 		u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY);
152 		if (u.u_error)
153 			break;
154 		u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC);
155 		if (u.u_error)
156 			(void) fset(fp, FNDELAY, 0);
157 		break;
158 
159 	case F_GETOWN:
160 		u.u_error = fgetown(fp, &u.u_r.r_val1);
161 		break;
162 
163 	case F_SETOWN:
164 		u.u_error = fsetown(fp, uap->arg);
165 		break;
166 
167 	default:
168 		u.u_error = EINVAL;
169 	}
170 }
171 
172 fset(fp, bit, value)
173 	struct file *fp;
174 	int bit, value;
175 {
176 
177 	if (value)
178 		fp->f_flag |= bit;
179 	else
180 		fp->f_flag &= ~bit;
181 	return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC),
182 	    (caddr_t)&value));
183 }
184 
185 fgetown(fp, valuep)
186 	struct file *fp;
187 	int *valuep;
188 {
189 	int error;
190 
191 	switch (fp->f_type) {
192 
193 	case DTYPE_SOCKET:
194 		*valuep = ((struct socket *)fp->f_data)->so_pgid;
195 		return (0);
196 
197 	default:
198 		error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep);
199 		*valuep = -*valuep;
200 		return (error);
201 	}
202 }
203 
204 fsetown(fp, value)
205 	struct file *fp;
206 	int value;
207 {
208 
209 	if (fp->f_type == DTYPE_SOCKET) {
210 		((struct socket *)fp->f_data)->so_pgid = value;
211 		return (0);
212 	}
213 	if (value > 0) {
214 		struct proc *p = pfind(value);
215 		if (p == 0)
216 			return (ESRCH);
217 		value = p->p_pgrp->pg_id;
218 	} else
219 		value = -value;
220 	return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));
221 }
222 
223 fioctl(fp, cmd, value)
224 	struct file *fp;
225 	int cmd;
226 	caddr_t value;
227 {
228 
229 	return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
230 }
231 
232 close()
233 {
234 	struct a {
235 		int	fdes;
236 	} *uap = (struct a *)u.u_ap;
237 	register struct file *fp;
238 	register u_char *pf;
239 
240 	if ((unsigned)uap->fdes >= NOFILE ||
241 	    (fp = u.u_ofile[uap->fdes]) == NULL)
242 		RETURN (EBADF);
243 	pf = (u_char *)&u.u_pofile[uap->fdes];
244 	if (*pf & UF_MAPPED)
245 		munmapfd(uap->fdes);
246 	u.u_ofile[uap->fdes] = NULL;
247 	while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
248 		u.u_lastfile--;
249 	*pf = 0;
250 	RETURN (closef(fp));
251 }
252 
253 fstat()
254 {
255 	register struct file *fp;
256 	register struct a {
257 		int	fdes;
258 		struct	stat *sb;
259 	} *uap = (struct a *)u.u_ap;
260 	struct stat ub;
261 
262 	if ((unsigned)uap->fdes >= NOFILE ||
263 	    (fp = u.u_ofile[uap->fdes]) == NULL)
264 		RETURN (EBADF);
265 	switch (fp->f_type) {
266 
267 	case DTYPE_VNODE:
268 		u.u_error = vn_stat((struct vnode *)fp->f_data, &ub);
269 		break;
270 
271 	case DTYPE_SOCKET:
272 		u.u_error = soo_stat((struct socket *)fp->f_data, &ub);
273 		break;
274 
275 	default:
276 		panic("fstat");
277 		/*NOTREACHED*/
278 	}
279 	if (u.u_error == 0)
280 		u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb,
281 		    sizeof (ub));
282 }
283 
284 /*
285  * Allocate a user file descriptor.
286  */
287 ufalloc(want, result)
288 	register int want;
289 	int *result;
290 {
291 
292 	for (; want < NOFILE; want++)
293 		if (u.u_ofile[want] == NULL) {
294 			u.u_pofile[want] = 0;
295 			if (want > u.u_lastfile)
296 				u.u_lastfile = want;
297 			if (result)
298 				*result = want;
299 			return (0);
300 		}
301 	return (EMFILE);
302 }
303 
304 ufavail()
305 {
306 	register int i, avail = 0;
307 
308 	for (i = 0; i < NOFILE; i++)
309 		if (u.u_ofile[i] == NULL)
310 			avail++;
311 	return (avail);
312 }
313 
314 struct	file *lastf;
315 /*
316  * Allocate a user file descriptor
317  * and a file structure.
318  * Initialize the descriptor
319  * to point at the file structure.
320  */
321 falloc(resultfp, resultfd)
322 	struct file **resultfp;
323 	int *resultfd;
324 {
325 	register struct file *fp;
326 	int error, i;
327 
328 	if (error = ufalloc(0, &i))
329 		return (error);
330 	if (lastf == 0)
331 		lastf = file;
332 	for (fp = lastf; fp < fileNFILE; fp++)
333 		if (fp->f_count == 0)
334 			goto slot;
335 	for (fp = file; fp < lastf; fp++)
336 		if (fp->f_count == 0)
337 			goto slot;
338 	tablefull("file");
339 	return (ENFILE);
340 slot:
341 	u.u_ofile[i] = fp;
342 	fp->f_count = 1;
343 	fp->f_data = 0;
344 	fp->f_offset = 0;
345 	fp->f_cred = u.u_cred;
346 	crhold(fp->f_cred);
347 	lastf = fp + 1;
348 	if (resultfp)
349 		*resultfp = fp;
350 	if (resultfd)
351 		*resultfd = i;
352 	return (0);
353 }
354 
355 /*
356  * Internal form of close.
357  * Decrement reference count on file structure.
358  */
359 closef(fp)
360 	register struct file *fp;
361 {
362 	int error;
363 
364 	if (fp == NULL)
365 		return (0);
366 	if (fp->f_count > 1) {
367 		fp->f_count--;
368 		return (0);
369 	}
370 	if (fp->f_count < 1)
371 		panic("closef: count < 1");
372 	error = (*fp->f_ops->fo_close)(fp);
373 	crfree(fp->f_cred);
374 	fp->f_count = 0;
375 	return (error);
376 }
377 
378 /*
379  * Apply an advisory lock on a file descriptor.
380  */
381 flock()
382 {
383 	register struct a {
384 		int	fdes;
385 		int	how;
386 	} *uap = (struct a *)u.u_ap;
387 	register struct file *fp;
388 
389 	if ((unsigned)uap->fdes >= NOFILE ||
390 	    (fp = u.u_ofile[uap->fdes]) == NULL)
391 		RETURN (EBADF);
392 	if (fp->f_type != DTYPE_VNODE) {
393 		u.u_error = EOPNOTSUPP;
394 		return;
395 	}
396 	if (uap->how & LOCK_UN) {
397 		vn_unlock(fp, FSHLOCK|FEXLOCK);
398 		return;
399 	}
400 	if ((uap->how & (LOCK_SH | LOCK_EX)) == 0)
401 		return;					/* error? */
402 	if (uap->how & LOCK_EX)
403 		uap->how &= ~LOCK_SH;
404 	/* avoid work... */
405 	if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
406 	    (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
407 		return;
408 	u.u_error = vn_lock(fp, uap->how);
409 }
410 
411 /*
412  * File Descriptor pseudo-device driver (/dev/fd/).
413  *
414  * Fred Blonder - U of Maryland	11-Sep-1984
415  *
416  * Opening minor device N dup()s the file (if any) connected to file
417  * descriptor N belonging to the calling process.  Note that this driver
418  * consists of only the ``open()'' routine, because all subsequent
419  * references to this file will be direct to the other driver.
420  */
421 /* ARGSUSED */
422 fdopen(dev, mode, type)
423 	dev_t dev;
424 	int mode, type;
425 {
426 	struct file *fp, *wfp;
427 	int indx, dfd, rwmode;
428 
429 	/*
430 	 * Note the horrid kludge here: u.u_r.r_val1 contains the value
431 	 * of the new file descriptor, which was set before the call to
432 	 * vn_open() by copen() in vfs_syscalls.c
433 	 */
434 	indx = u.u_r.r_val1;		/* XXX from copen */
435 	if ((unsigned)indx >= NOFILE || (fp = u.u_ofile[indx]) == NULL)
436 		return (EBADF);
437 	dfd = minor(dev);
438 	if ((unsigned)dfd >= NOFILE || (wfp = u.u_ofile[dfd]) == NULL)
439 		return (EBADF);
440 	/*
441 	 * We must explicitly test for this case because ufalloc() may
442 	 * have allocated us the same file desriptor we are referring
443 	 * to, if the proccess referred to an invalid (closed) descriptor.
444 	 * Ordinarily this would be caught by the check for NULL above,
445 	 * but by the time we reach this routine u_pofile[minor(dev)]
446 	 * could already be set to point to our file struct.
447 	 */
448 	if (fp == wfp)
449 		return (EBADF);
450 	/*
451 	 * Fake a ``dup()'' sys call.
452 	 * Check that the mode the file is being opened
453 	 * for is consistent with the mode of the existing
454 	 * descriptor. This isn't as clean as it should be,
455 	 * but this entire driver is a real kludge anyway.
456 	 */
457 	rwmode = mode & (FREAD|FWRITE);
458 	if ((wfp->f_flag & rwmode) != rwmode)
459 		return (EACCES);
460 	/*
461 	 * Dup the file descriptor.
462 	 */
463 	dupit(indx, wfp, u.u_pofile[dfd]);
464 	/*
465 	 * Delete references to this pseudo-device by returning
466 	 * a special error (-1) that will cause all resources to
467 	 * be freed, then detected and cleared by copen.
468 	 */
469 	return (-1);
470 }
471