xref: /original-bsd/sys/kern/kern_descrip.c (revision 54e6d6c7)
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.4 (Berkeley) 05/09/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 
72 	if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL)
73 		RETURN (EBADF);
74 	if (uap->j < 0 || uap->j >= NOFILE) {
75 		u.u_error = EBADF;
76 		return;
77 	}
78 	u.u_r.r_val1 = uap->j;
79 	if (uap->i == uap->j)
80 		return;
81 	if (u.u_ofile[uap->j]) {
82 		if (u.u_pofile[uap->j] & UF_MAPPED)
83 			munmapfd(uap->j);
84 		closef(u.u_ofile[uap->j]);
85 		if (u.u_error)
86 			return;
87 	}
88 	dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE);
89 }
90 
91 dupit(fd, fp, flags)
92 	int fd;
93 	register struct file *fp;
94 	register int flags;
95 {
96 
97 	u.u_ofile[fd] = fp;
98 	u.u_pofile[fd] = flags;
99 	fp->f_count++;
100 	if (fd > u.u_lastfile)
101 		u.u_lastfile = fd;
102 }
103 
104 /*
105  * The file control system call.
106  */
107 fcntl()
108 {
109 	register struct file *fp;
110 	register struct a {
111 		int	fdes;
112 		int	cmd;
113 		int	arg;
114 	} *uap = (struct a *)u.u_ap;
115 	register char *pop;
116 	int i;
117 
118 	if ((unsigned)uap->fdes >= NOFILE ||
119 	    (fp = u.u_ofile[uap->fdes]) == NULL)
120 		RETURN (EBADF);
121 	pop = &u.u_pofile[uap->fdes];
122 	switch(uap->cmd) {
123 	case F_DUPFD:
124 		if (uap->arg < 0 || uap->arg >= NOFILE) {
125 			u.u_error = EINVAL;
126 			return;
127 		}
128 		if (u.u_error = ufalloc(uap->arg, &i))
129 			return;
130 		u.u_r.r_val1 = i;
131 		dupit(i, fp, *pop &~ UF_EXCLOSE);
132 		break;
133 
134 	case F_GETFD:
135 		u.u_r.r_val1 = *pop & 1;
136 		break;
137 
138 	case F_SETFD:
139 		*pop = (*pop &~ 1) | (uap->arg & 1);
140 		break;
141 
142 	case F_GETFL:
143 		u.u_r.r_val1 = fp->f_flag+FOPEN;
144 		break;
145 
146 	case F_SETFL:
147 		fp->f_flag &= FCNTLCANT;
148 		fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT;
149 		u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY);
150 		if (u.u_error)
151 			break;
152 		u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC);
153 		if (u.u_error)
154 			(void) fset(fp, FNDELAY, 0);
155 		break;
156 
157 	case F_GETOWN:
158 		u.u_error = fgetown(fp, &u.u_r.r_val1);
159 		break;
160 
161 	case F_SETOWN:
162 		u.u_error = fsetown(fp, uap->arg);
163 		break;
164 
165 	default:
166 		u.u_error = EINVAL;
167 	}
168 }
169 
170 fset(fp, bit, value)
171 	struct file *fp;
172 	int bit, value;
173 {
174 
175 	if (value)
176 		fp->f_flag |= bit;
177 	else
178 		fp->f_flag &= ~bit;
179 	return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC),
180 	    (caddr_t)&value));
181 }
182 
183 fgetown(fp, valuep)
184 	struct file *fp;
185 	int *valuep;
186 {
187 	int error;
188 
189 	switch (fp->f_type) {
190 
191 	case DTYPE_SOCKET:
192 		*valuep = ((struct socket *)fp->f_data)->so_pgid;
193 		return (0);
194 
195 	default:
196 		error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep);
197 		*valuep = -*valuep;
198 		return (error);
199 	}
200 }
201 
202 fsetown(fp, value)
203 	struct file *fp;
204 	int value;
205 {
206 
207 	if (fp->f_type == DTYPE_SOCKET) {
208 		((struct socket *)fp->f_data)->so_pgid = value;
209 		return (0);
210 	}
211 	if (value > 0) {
212 		struct proc *p = pfind(value);
213 		if (p == 0)
214 			return (ESRCH);
215 		value = p->p_pgrp->pg_id;
216 	} else
217 		value = -value;
218 	return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));
219 }
220 
221 fioctl(fp, cmd, value)
222 	struct file *fp;
223 	int cmd;
224 	caddr_t value;
225 {
226 
227 	return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
228 }
229 
230 close()
231 {
232 	struct a {
233 		int	fdes;
234 	} *uap = (struct a *)u.u_ap;
235 	register struct file *fp;
236 	register u_char *pf;
237 
238 	if ((unsigned)uap->fdes >= NOFILE ||
239 	    (fp = u.u_ofile[uap->fdes]) == NULL)
240 		RETURN (EBADF);
241 	pf = (u_char *)&u.u_pofile[uap->fdes];
242 	if (*pf & UF_MAPPED)
243 		munmapfd(uap->fdes);
244 	u.u_ofile[uap->fdes] = NULL;
245 	while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
246 		u.u_lastfile--;
247 	*pf = 0;
248 	closef(fp);
249 	/* WHAT IF u.u_error ? */
250 }
251 
252 fstat()
253 {
254 	register struct file *fp;
255 	register struct a {
256 		int	fdes;
257 		struct	stat *sb;
258 	} *uap = (struct a *)u.u_ap;
259 	struct stat ub;
260 
261 	if ((unsigned)uap->fdes >= NOFILE ||
262 	    (fp = u.u_ofile[uap->fdes]) == NULL)
263 		RETURN (EBADF);
264 	switch (fp->f_type) {
265 
266 	case DTYPE_VNODE:
267 		u.u_error = vn_stat((struct vnode *)fp->f_data, &ub);
268 		break;
269 
270 	case DTYPE_SOCKET:
271 		u.u_error = soo_stat((struct socket *)fp->f_data, &ub);
272 		break;
273 
274 	default:
275 		panic("fstat");
276 		/*NOTREACHED*/
277 	}
278 	if (u.u_error == 0)
279 		u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb,
280 		    sizeof (ub));
281 }
282 
283 /*
284  * Allocate a user file descriptor.
285  */
286 ufalloc(want, result)
287 	register int want;
288 	int *result;
289 {
290 
291 	for (; want < NOFILE; want++)
292 		if (u.u_ofile[want] == NULL) {
293 			u.u_pofile[want] = 0;
294 			if (want > u.u_lastfile)
295 				u.u_lastfile = want;
296 			if (result)
297 				*result = want;
298 			return (0);
299 		}
300 	return (EMFILE);
301 }
302 
303 ufavail()
304 {
305 	register int i, avail = 0;
306 
307 	for (i = 0; i < NOFILE; i++)
308 		if (u.u_ofile[i] == NULL)
309 			avail++;
310 	return (avail);
311 }
312 
313 struct	file *lastf;
314 /*
315  * Allocate a user file descriptor
316  * and a file structure.
317  * Initialize the descriptor
318  * to point at the file structure.
319  */
320 falloc(resultfp, resultfd)
321 	struct file **resultfp;
322 	int *resultfd;
323 {
324 	register struct file *fp;
325 	int error, i;
326 
327 	if (error = ufalloc(0, &i))
328 		return (error);
329 	if (lastf == 0)
330 		lastf = file;
331 	for (fp = lastf; fp < fileNFILE; fp++)
332 		if (fp->f_count == 0)
333 			goto slot;
334 	for (fp = file; fp < lastf; fp++)
335 		if (fp->f_count == 0)
336 			goto slot;
337 	tablefull("file");
338 	return (ENFILE);
339 slot:
340 	u.u_ofile[i] = fp;
341 	fp->f_count = 1;
342 	fp->f_data = 0;
343 	fp->f_offset = 0;
344 	fp->f_cred = u.u_cred;
345 	crhold(fp->f_cred);
346 	lastf = fp + 1;
347 	if (resultfp)
348 		*resultfp = fp;
349 	if (resultfd)
350 		*resultfd = i;
351 	return (0);
352 }
353 
354 /*
355  * Internal form of close.
356  * Decrement reference count on file structure.
357  */
358 closef(fp)
359 	register struct file *fp;
360 {
361 
362 	if (fp == NULL)
363 		return;
364 	if (fp->f_count > 1) {
365 		fp->f_count--;
366 		return;
367 	}
368 	if (fp->f_count < 1)
369 		panic("closef: count < 1");
370 	(*fp->f_ops->fo_close)(fp);
371 	crfree(fp->f_cred);
372 	fp->f_count = 0;
373 }
374 
375 /*
376  * Apply an advisory lock on a file descriptor.
377  */
378 flock()
379 {
380 	register struct a {
381 		int	fdes;
382 		int	how;
383 	} *uap = (struct a *)u.u_ap;
384 	register struct file *fp;
385 
386 	if ((unsigned)uap->fdes >= NOFILE ||
387 	    (fp = u.u_ofile[uap->fdes]) == NULL)
388 		RETURN (EBADF);
389 	if (fp->f_type != DTYPE_VNODE) {
390 		u.u_error = EOPNOTSUPP;
391 		return;
392 	}
393 	if (uap->how & LOCK_UN) {
394 		vn_unlock(fp, FSHLOCK|FEXLOCK);
395 		return;
396 	}
397 	if ((uap->how & (LOCK_SH | LOCK_EX)) == 0)
398 		return;					/* error? */
399 	if (uap->how & LOCK_EX)
400 		uap->how &= ~LOCK_SH;
401 	/* avoid work... */
402 	if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
403 	    (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
404 		return;
405 	u.u_error = vn_lock(fp, uap->how);
406 }
407 
408 /*
409  * File Descriptor pseudo-device driver (/dev/fd/).
410  *
411  * Fred Blonder - U of Maryland	11-Sep-1984
412  *
413  * Opening minor device N dup()s the file (if any) connected to file
414  * descriptor N belonging to the calling process.  Note that this driver
415  * consists of only the ``open()'' routine, because all subsequent
416  * references to this file will be direct to the other driver.
417  */
418 /* ARGSUSED */
419 fdopen(dev, mode, type)
420 	dev_t dev;
421 	int mode, type;
422 {
423 	struct file *fp, *wfp;
424 	int indx, dfd, rwmode;
425 
426 	/*
427 	 * Note the horrid kludge here: u.u_r.r_val1 contains the value
428 	 * of the new file descriptor, which was set before the call to
429 	 * vn_open() by copen() in vfs_syscalls.c
430 	 */
431 	indx = u.u_r.r_val1;		/* XXX */
432 	if ((unsigned)indx >= NOFILE || (fp = u.u_ofile[indx]) == NULL)
433 		return (EBADF);
434 	dfd = minor(dev);
435 	if ((unsigned)dfd >= NOFILE || (wfp = u.u_ofile[dfd]) == NULL)
436 		return (EBADF);
437 	/*
438 	 * We must explicitly test for this case because ufalloc() may
439 	 * have allocated us the same file desriptor we are referring
440 	 * to, if the proccess referred to an invalid (closed) descriptor.
441 	 * Ordinarily this would be caught by the check for NULL above,
442 	 * but by the time we reach this routine u_pofile[minor(dev)]
443 	 * could already be set to point to our file struct.
444 	 */
445 	if (fp == wfp)
446 		return (EBADF);
447 	/*
448 	 * Fake a ``dup()'' sys call.
449 	 * Check that the mode the file is being opened
450 	 * for is consistent with the mode of the existing
451 	 * descriptor. This isn't as clean as it should be,
452 	 * but this entire driver is a real kludge anyway.
453 	 */
454 	rwmode = mode & (FREAD|FWRITE);
455 	if ((fp->f_flag & rwmode) != rwmode)
456 		return (EACCES);
457 	/*
458 	 * Delete references to this pseudo-device.
459 	 * Note that fp->f_count is guaranteed == 1, and
460 	 * that fp references the vnode for this driver.
461 	 */
462 	if (fp->f_count != 1 || fp->f_type != DTYPE_VNODE)
463 		panic("fdopen");
464 	vrele((struct vnode *)fp->f_data);
465 	fp->f_count = 0;
466 	/*
467 	 * Dup the file descriptor.
468 	 */
469 	dupit(indx, wfp, u.u_pofile[dfd]);
470 	return (0);
471 }
472