xref: /386bsd/usr/src/kernel/kern/descrip.c (revision dc8b130e)
1 /*
2  * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * $Id: descrip.c,v 1.1 94/10/20 00:02:49 bill Exp Locker: bill $
34  *
35  * File instance and file descriptor management and system calls.
36  */
37 
38 #include "sys/param.h"
39 #include "sys/stat.h"
40 #include "sys/ioctl.h"
41 #include "sys/fcntl.h"
42 #include "sys/syslog.h"
43 #include "sys/errno.h"
44 #include "filedesc.h"
45 #include "kernel.h"	/* time */
46 #include "malloc.h"
47 #include "modconfig.h"
48 #include "proc.h"
49 /*#include "socketvar.h"*/
50 #include "resourcevar.h"
51 #include "uio.h"
52 #ifdef KTRACE
53 #include "sys/ktrace.h"
54 #endif
55 
56 
57 #include "vnode.h"
58 
59 #include "prototypes.h"
60 
61 /*
62  * Descriptor management.
63  */
64 struct file *filehead;	/* head of list of open files */
65 int nfiles;		/* actual number of open files */
66 static int fdopen(dev_t dev, int mode, int type, struct proc *p);
67 /*int fdalloc(struct proc *p, int want, int *result);*/
68 static int selscan(struct proc *p, fd_set *ibits, fd_set *obits, int nfd, int *retval);
69 
70 
71 
72 
73 
74 /*
75  * Descriptor system calls, both BSD and POSIX.
76  */
77 
78 /* BSD file descriptor "table" size (number of descriptors */
79 int
getdtablesize(p,uap,retval)80 getdtablesize(p, uap, retval)
81 	struct proc *p;
82 	void *uap;
83 	int *retval;
84 {
85 
86 	*retval = p->p_rlimit[RLIMIT_OFILE].rlim_cur;
87 	return (0);
88 }
89 
90 
91 
92 /* POSIX Duplicate a file descriptor.  */
93 int
dup(p,uap,retval)94 dup(p, uap, retval)
95 	struct proc *p;
96 	struct args {
97 		int	i;
98 	} *uap;
99 	int *retval;
100 {
101 	register struct filedesc *fdp = p->p_fd;
102 	struct file *fp;
103 	int fd, error;
104 
105 	if ((unsigned)uap->i >= fdp->fd_nfiles ||
106 	    (fp = fdp->fd_ofiles[uap->i]) == NULL)
107 		return (EBADF);
108 
109 	if (error = fdalloc(p, 0, &fd))
110 		return (error);
111 
112 	fdp->fd_ofiles[fd] = fp;
113 	fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE;
114 	fp->f_count++;
115 	if (fd > fdp->fd_lastfile)
116 		fdp->fd_lastfile = fd;
117 	*retval = fd;
118 	return (0);
119 }
120 
121 
122 
123 
124 /* POSIX Duplicate a file descriptor to a particular value.  */
125 int
dup2(p,uap,retval)126 dup2(p, uap, retval)
127 	struct proc *p;
128 	struct args {
129 		u_int	from;
130 		u_int	to;
131 	} *uap;
132 	int *retval;
133 {
134 	register struct filedesc *fdp = p->p_fd;
135 	register struct file *fp;
136 	register u_int old = uap->from, new = uap->to;
137 	int i, error;
138 
139 	if (old >= fdp->fd_nfiles ||
140 	    (fp = fdp->fd_ofiles[old]) == NULL ||
141 	    new >= p->p_rlimit[RLIMIT_OFILE].rlim_cur)
142 		return (EBADF);
143 
144 	*retval = new;
145 	if (old == new)
146 		return (0);
147 
148 	if (new >= fdp->fd_nfiles) {
149 		if (error = fdalloc(p, new, &i))
150 			return (error);
151 #ifdef DIAGNOSTIC
152 		if (new != i)
153 			panic("dup2: fdalloc");
154 #endif
155 	} else if (fdp->fd_ofiles[new]) {
156 		if (fdp->fd_ofileflags[new] & UF_MAPPED)
157 			(void) munmapfd(p, new);
158 		/* dup2() must succeed even if the close has an error.*/
159 		(void) closef(fdp->fd_ofiles[new], p);
160 	}
161 
162 	fdp->fd_ofiles[new] = fp;
163 	fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
164 	fp->f_count++;
165 	if (new > fdp->fd_lastfile)
166 		fdp->fd_lastfile = new;
167 	return (0);
168 }
169 
170 
171 
172 
173 /* POSIX file control system call.  */
174 int
fcntl(p,uap,retval)175 fcntl(p, uap, retval)
176 	struct proc *p;
177 	struct args {
178 		int	fd;
179 		int	cmd;
180 		int	arg;
181 	} *uap;
182 	int *retval;
183 {
184 	struct filedesc *fdp = p->p_fd;
185 	struct file *fp;
186 	char *pop;
187 	struct vnode *vp;
188 	int cmd, i, tmp, error, flg = F_POSIX;
189 	struct flock fl;
190 
191 	if ((unsigned)uap->fd >= fdp->fd_nfiles ||
192 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
193 		return (EBADF);
194 
195 	pop = &fdp->fd_ofileflags[uap->fd];
196 	switch(uap->cmd) {
197 	case F_DUPFD:
198 		if ((unsigned)uap->arg >= p->p_rlimit[RLIMIT_OFILE].rlim_cur)
199 			return (EINVAL);
200 		if (error = fdalloc(p, uap->arg, &i))
201 			return (error);
202 		fdp->fd_ofiles[i] = fp;
203 		fdp->fd_ofileflags[i] = *pop &~ UF_EXCLOSE;
204 		fp->f_count++;
205 		if (i > fdp->fd_lastfile)
206 			fdp->fd_lastfile = i;
207 		*retval = i;
208 		return (0);
209 
210 	case F_GETFD:
211 		*retval = *pop & UF_EXCLOSE;
212 		return (0);
213 
214 	case F_SETFD:
215 		*pop = (*pop &~ UF_EXCLOSE) | (uap->arg & 1);
216 		return (0);
217 
218 	case F_GETFL:
219 		*retval = OFLAGS(fp->f_flag);
220 		return (0);
221 
222 	case F_SETFL:
223 		fp->f_flag &= ~FCNTLFLAGS;
224 		fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS;
225 		tmp = fp->f_flag & FNONBLOCK;
226 		error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
227 		if (error)
228 			return (error);
229 		tmp = fp->f_flag & FASYNC;
230 		error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
231 		if (!error)
232 			return (0);
233 		fp->f_flag &= ~FNONBLOCK;
234 		tmp = 0;
235 		(void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
236 		return (error);
237 
238 	case F_GETOWN:
239 		if (fp->f_type == DTYPE_SOCKET)
240 			cmd = SIOCGPGRP;
241 		else
242 			cmd = TIOCGPGRP;
243 		error = (*fp->f_ops->fo_ioctl) (fp, cmd, (caddr_t)retval, p);
244 		if (fp->f_type != DTYPE_SOCKET)
245 			*retval = -*retval;
246 		return (error);
247 
248 	case F_SETOWN:
249 		if (fp->f_type == DTYPE_SOCKET)
250 			cmd = SIOCSPGRP;
251 		else {
252 			cmd = TIOCSPGRP;
253 			if (uap->arg <= 0) {
254 				uap->arg = -uap->arg;
255 			} else {
256 				struct proc *p1 = pfind(uap->arg);
257 				if (p1 == 0)
258 					return (ESRCH);
259 				uap->arg = p1->p_pgrp->pg_id;
260 			}
261 		}
262 		return((*fp->f_ops->fo_ioctl)(fp, cmd, (caddr_t)&uap->arg, p));
263 
264 	case F_SETLKW:
265 		flg |= F_WAIT;
266 		/* Fall into F_SETLK */
267 
268 	case F_SETLK:
269 		if (fp->f_type != DTYPE_VNODE)
270 			return (EBADF);
271 		vp = (struct vnode *)fp->f_data;
272 
273 		/* fetch the lock structure */
274 		error = copyin(p, (caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
275 		if (error)
276 			return (error);
277 
278 		if (fl.l_whence == SEEK_CUR)
279 			fl.l_start += fp->f_offset;
280 
281 		switch (fl.l_type) {
282 
283 		case F_RDLCK:
284 			if ((fp->f_flag & FREAD) == 0)
285 				return (EBADF);
286 			p->p_flag |= SADVLCK;
287 			return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
288 
289 		case F_WRLCK:
290 			if ((fp->f_flag & FWRITE) == 0)
291 				return (EBADF);
292 			p->p_flag |= SADVLCK;
293 			return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
294 
295 		case F_UNLCK:
296 			return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
297 				F_POSIX));
298 
299 		default:
300 			return (EINVAL);
301 		}
302 
303 	case F_GETLK:
304 		if (fp->f_type != DTYPE_VNODE)
305 			return (EBADF);
306 		vp = (struct vnode *)fp->f_data;
307 
308 		/* fetch the lock structure */
309 		error = copyin(p, (caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
310 		if (error)
311 			return (error);
312 		if (fl.l_whence == SEEK_CUR)
313 			fl.l_start += fp->f_offset;
314 		if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX))
315 			return (error);
316 		return (copyout(p, (caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl)));
317 
318 	default:
319 		return (EINVAL);
320 	}
321 	/* NOTREACHED */
322 }
323 
324 
325 
326 
327 /* POSIX close a file descriptor. */
328 int
close(p,uap,retval)329 close(p, uap, retval)
330 	struct proc *p;
331 	struct args {
332 		int	fd;
333 	} *uap;
334 	int *retval;
335 {
336 	struct filedesc *fdp = p->p_fd;
337 	struct file *fp;
338 	int fd = uap->fd;
339 	u_char *pf;
340 
341 	if ((unsigned)fd >= fdp->fd_nfiles ||
342 	    (fp = fdp->fd_ofiles[fd]) == NULL)
343 		return (EBADF);
344 
345 	pf = (u_char *)&fdp->fd_ofileflags[fd];
346 	if (*pf & UF_MAPPED)
347 		(void) munmapfd(p, fd);
348 
349 	fdp->fd_ofiles[fd] = NULL;
350 	while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
351 		fdp->fd_lastfile--;
352 	if (fd < fdp->fd_freefile)
353 		fdp->fd_freefile = fd;
354 	*pf = 0;
355 	return (closef(fp, p));
356 }
357 
358 
359 
360 /* POSIX: Return status information about a file descriptor. */
361 int
fstat(p,uap,retval)362 fstat(p, uap, retval)
363 	struct proc *p;
364 	struct args {
365 		int	fd;
366 		struct	stat *sb;
367 	} *uap;
368 	int *retval;
369 {
370 	struct filedesc *fdp = p->p_fd;
371 	struct file *fp;
372 	struct stat ub;
373 	int error;
374 
375 	if ((unsigned)uap->fd >= fdp->fd_nfiles ||
376 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
377 		return (EBADF);
378 
379 #ifdef foo
380 	switch (fp->f_type) {
381 
382 	case DTYPE_VNODE:
383 		error = vn_stat((struct vnode *)fp->f_data, &ub, p);
384 		break;
385 
386 	case DTYPE_SOCKET:
387 		error = soo_stat((struct socket *)fp->f_data, &ub);
388 		break;
389 
390 	default:
391 		panic("fstat");
392 		/*NOTREACHED*/
393 	}
394 #endif
395 	error = (*fp->f_ops->fo_stat)(fp, &ub, p);
396 
397 	if (error == 0)
398 		error = copyout(p, (caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub));
399 	return (error);
400 }
401 
402 
403 
404 /* POSIX Read function system call handler.  */
405 int
read(p,uap,retval)406 read(p, uap, retval)
407 	struct proc *p;
408 	register struct args {
409 		int	fdes;
410 		char	*cbuf;
411 		unsigned count;
412 	} *uap;
413 	int *retval;
414 {
415 	register struct file *fp;
416 	register struct filedesc *fdp = p->p_fd;
417 	struct uio auio;
418 	struct iovec aiov;
419 	long cnt, error = 0;
420 #ifdef KTRACE
421 	struct iovec ktriov;
422 #endif
423 
424 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
425 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
426 	    (fp->f_flag & FREAD) == 0)
427 		return (EBADF);
428 
429 	aiov.iov_base = (caddr_t)uap->cbuf;
430 	aiov.iov_len = uap->count;
431 	auio.uio_iov = &aiov;
432 	auio.uio_iovcnt = 1;
433 	auio.uio_resid = uap->count;
434 	auio.uio_rw = UIO_READ;
435 	auio.uio_segflg = UIO_USERSPACE;
436 	auio.uio_procp = p;
437 
438 #ifdef KTRACE
439 	/*
440 	 * if tracing, save a copy of iovec
441 	 */
442 	if (KTRPOINT(p, KTR_GENIO))
443 		ktriov = aiov;
444 #endif
445 
446 	cnt = uap->count;
447 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
448 		if (auio.uio_resid != cnt && (error == ERESTART ||
449 		    error == EINTR || error == EWOULDBLOCK))
450 			error = 0;
451 	cnt -= auio.uio_resid;
452 
453 #ifdef KTRACE
454 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
455 		ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error);
456 #endif
457 
458 	*retval = cnt;
459 	return (error);
460 }
461 
462 
463 
464 /* BSD scatter readv() system call handler. */
465 int
readv(p,uap,retval)466 readv(p, uap, retval)
467 	struct proc *p;
468 	register struct args {
469 		int	fdes;
470 		struct	iovec *iovp;
471 		unsigned iovcnt;
472 	} *uap;
473 	int *retval;
474 {
475 	struct file *fp;
476 	struct filedesc *fdp = p->p_fd;
477 	struct uio auio;
478 	struct iovec *iov;
479 	struct iovec *saveiov;
480 	struct iovec aiov[UIO_SMALLIOV];
481 	long i, cnt, error = 0;
482 	unsigned iovlen;
483 #ifdef KTRACE
484 	struct iovec *ktriov = NULL;
485 #endif
486 
487 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
488 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
489 	    (fp->f_flag & FREAD) == 0)
490 		return (EBADF);
491 
492 	/* note: can't use iovlen until iovcnt is validated */
493 	iovlen = uap->iovcnt * sizeof (struct iovec);
494 
495 	if (uap->iovcnt > UIO_SMALLIOV) {
496 		if (uap->iovcnt > UIO_MAXIOV)
497 			return (EINVAL);
498 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
499 		saveiov = iov;
500 	} else
501 		iov = aiov;
502 
503 	auio.uio_iov = iov;
504 	auio.uio_iovcnt = uap->iovcnt;
505 	auio.uio_rw = UIO_READ;
506 	auio.uio_segflg = UIO_USERSPACE;
507 	auio.uio_procp = p;
508 
509 	if (error = copyin(p, (caddr_t)uap->iovp, (caddr_t)iov, iovlen))
510 		goto done;
511 
512 	auio.uio_resid = 0;
513 	for (i = 0; i < uap->iovcnt; i++) {
514 		if (iov->iov_len < 0) {
515 			error = EINVAL;
516 			goto done;
517 		}
518 		auio.uio_resid += iov->iov_len;
519 		if (auio.uio_resid < 0) {
520 			error = EINVAL;
521 			goto done;
522 		}
523 		iov++;
524 	}
525 
526 #ifdef KTRACE
527 	/*
528 	 * if tracing, save a copy of iovec
529 	 */
530 	if (KTRPOINT(p, KTR_GENIO))  {
531 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
532 		(void) memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
533 	}
534 #endif
535 
536 	cnt = auio.uio_resid;
537 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
538 		if (auio.uio_resid != cnt && (error == ERESTART ||
539 		    error == EINTR || error == EWOULDBLOCK))
540 			error = 0;
541 	cnt -= auio.uio_resid;
542 
543 #ifdef KTRACE
544 	if (ktriov != NULL) {
545 		if (error == 0)
546 			ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov,
547 			    cnt, error);
548 		FREE(ktriov, M_TEMP);
549 	}
550 #endif
551 
552 	*retval = cnt;
553 done:
554 	if (uap->iovcnt > UIO_SMALLIOV)
555 		FREE(saveiov, M_IOV);
556 
557 	return (error);
558 }
559 
560 
561 
562 /* POSIX write() function system call handler */
563 int
write(p,uap,retval)564 write(p, uap, retval)
565 	struct proc *p;
566 	struct args {
567 		int	fdes;
568 		char	*cbuf;
569 		unsigned count;
570 	} *uap;
571 	int *retval;
572 {
573 	register struct file *fp;
574 	register struct filedesc *fdp = p->p_fd;
575 	struct uio auio;
576 	struct iovec aiov;
577 	long cnt, error = 0;
578 #ifdef KTRACE
579 	struct iovec ktriov;
580 #endif
581 
582 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
583 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
584 	    (fp->f_flag & FWRITE) == 0)
585 		return (EBADF);
586 
587 	aiov.iov_base = (caddr_t)uap->cbuf;
588 	aiov.iov_len = uap->count;
589 	auio.uio_iov = &aiov;
590 	auio.uio_iovcnt = 1;
591 	auio.uio_resid = uap->count;
592 	auio.uio_rw = UIO_WRITE;
593 	auio.uio_segflg = UIO_USERSPACE;
594 	auio.uio_procp = p;
595 
596 #ifdef KTRACE
597 	/*
598 	 * if tracing, save a copy of iovec
599 	 */
600 	if (KTRPOINT(p, KTR_GENIO))
601 		ktriov = aiov;
602 #endif
603 
604 	cnt = uap->count;
605 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
606 		if (auio.uio_resid != cnt && (error == ERESTART ||
607 		    error == EINTR || error == EWOULDBLOCK))
608 			error = 0;
609 		if (error == EPIPE)
610 			psignal(p, SIGPIPE);
611 	}
612 	cnt -= auio.uio_resid;
613 
614 #ifdef KTRACE
615 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
616 		ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
617 		    &ktriov, cnt, error);
618 #endif
619 
620 	*retval = cnt;
621 	return (error);
622 }
623 
624 
625 
626 /* BSD gather write writev() function system call handler */
627 int
writev(p,uap,retval)628 writev(p, uap, retval)
629 	struct proc *p;
630 	register struct args {
631 		int	fdes;
632 		struct	iovec *iovp;
633 		unsigned iovcnt;
634 	} *uap;
635 	int *retval;
636 {
637 	register struct file *fp;
638 	register struct filedesc *fdp = p->p_fd;
639 	struct uio auio;
640 	register struct iovec *iov;
641 	struct iovec *saveiov;
642 	struct iovec aiov[UIO_SMALLIOV];
643 	long i, cnt, error = 0;
644 	unsigned iovlen;
645 #ifdef KTRACE
646 	struct iovec *ktriov = NULL;
647 #endif
648 
649 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
650 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
651 	    (fp->f_flag & FWRITE) == 0)
652 		return (EBADF);
653 
654 	/* note: can't use iovlen until iovcnt is validated */
655 	iovlen = uap->iovcnt * sizeof (struct iovec);
656 	if (uap->iovcnt > UIO_SMALLIOV) {
657 		if (uap->iovcnt > UIO_MAXIOV)
658 			return (EINVAL);
659 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
660 		saveiov = iov;
661 	} else
662 		iov = aiov;
663 
664 	auio.uio_iov = iov;
665 	auio.uio_iovcnt = uap->iovcnt;
666 	auio.uio_rw = UIO_WRITE;
667 	auio.uio_segflg = UIO_USERSPACE;
668 	auio.uio_procp = p;
669 
670 	if (error = copyin(p, (caddr_t)uap->iovp, (caddr_t)iov, iovlen))
671 		goto done;
672 
673 	auio.uio_resid = 0;
674 	for (i = 0; i < uap->iovcnt; i++) {
675 		if (iov->iov_len < 0) {
676 			error = EINVAL;
677 			goto done;
678 		}
679 		auio.uio_resid += iov->iov_len;
680 		if (auio.uio_resid < 0) {
681 			error = EINVAL;
682 			goto done;
683 		}
684 		iov++;
685 	}
686 
687 #ifdef KTRACE
688 	/*
689 	 * if tracing, save a copy of iovec
690 	 */
691 	if (KTRPOINT(p, KTR_GENIO))  {
692 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
693 		(void) memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
694 	}
695 #endif
696 
697 	cnt = auio.uio_resid;
698 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
699 		if (auio.uio_resid != cnt && (error == ERESTART ||
700 		    error == EINTR || error == EWOULDBLOCK))
701 			error = 0;
702 		if (error == EPIPE)
703 			psignal(p, SIGPIPE);
704 	}
705 	cnt -= auio.uio_resid;
706 
707 #ifdef KTRACE
708 	if (ktriov != NULL) {
709 		if (error == 0)
710 			ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
711 				ktriov, cnt, error);
712 		FREE(ktriov, M_TEMP);
713 	}
714 #endif
715 
716 	*retval = cnt;
717 done:
718 	if (uap->iovcnt > UIO_SMALLIOV)
719 		FREE(saveiov, M_IOV);
720 
721 	return (error);
722 }
723 
724 
725 
726 
727 /* POSIX ioctl() function system call handler */
728 int
ioctl(p,uap,retval)729 ioctl(p, uap, retval)
730 	struct proc *p;
731 	register struct args {
732 		int	fdes;
733 		int	cmd;
734 		caddr_t	cmarg;
735 	} *uap;
736 	int *retval;
737 {
738 	struct file *fp;
739 	struct filedesc *fdp = p->p_fd;
740 	int com, cmd, error;
741 	u_int size;
742 	caddr_t memp = 0;
743 #define STK_PARAMS	128
744 	char stkbuf[STK_PARAMS];
745 	caddr_t data = stkbuf;
746 	int tmp;
747 
748 	if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
749 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
750 		return (EBADF);
751 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
752 		return (EBADF);
753 
754 	com = uap->cmd;
755 	if (com == FIOCLEX) {
756 		fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE;
757 		return (0);
758 	}
759 	if (com == FIONCLEX) {
760 		fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE;
761 		return (0);
762 	}
763 
764 	/*
765 	 * Interpret high order word to find
766 	 * amount of data to be copied to/from the
767 	 * user's address space.
768 	 */
769 	size = IOCPARM_LEN(com);
770 	if (size > IOCPARM_MAX)
771 		return (ENOTTY);
772 	if (size > sizeof (stkbuf)) {
773 		memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
774 		data = memp;
775 	}
776 	if (com&IOC_IN) {
777 		if (size) {
778 			error = copyin(p, uap->cmarg, data, (u_int)size);
779 			if (error) {
780 				if (memp)
781 					free(memp, M_IOCTLOPS);
782 				return (error);
783 			}
784 		} else
785 			*(caddr_t *)data = uap->cmarg;
786 	} else if ((com&IOC_OUT) && size)
787 		/*
788 		 * Zero the buffer so the user always
789 		 * gets back something deterministic.
790 		 */
791 		(void) memset(data, 0, size);
792 	else if (com&IOC_VOID)
793 		*(caddr_t *)data = uap->cmarg;
794 
795 	switch (com) {
796 
797 	case FIONBIO:
798 		if (tmp = *(int *)data)
799 			fp->f_flag |= FNONBLOCK;
800 		else
801 			fp->f_flag &= ~FNONBLOCK;
802 		error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
803 		break;
804 
805 	case FIOASYNC:
806 		if (tmp = *(int *)data)
807 			fp->f_flag |= FASYNC;
808 		else
809 			fp->f_flag &= ~FASYNC;
810 		error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
811 		break;
812 
813 	case FIOSETOWN:
814 		tmp = *(int *)data;
815 		if (fp->f_type == DTYPE_SOCKET)
816 			cmd = SIOCSPGRP;
817 		else {
818 			cmd = TIOCSPGRP;
819 			if (tmp <= 0) {
820 				tmp = -tmp;
821 			} else {
822 				struct proc *p1 = pfind(tmp);
823 				if (p1 == 0) {
824 					error = ESRCH;
825 					break;
826 				}
827 				tmp = p1->p_pgrp->pg_id;
828 			}
829 		}
830 		error = (*fp->f_ops->fo_ioctl) (fp, cmd, (caddr_t)&tmp, p);
831 		break;
832 
833 	case FIOGETOWN:
834 		if (fp->f_type == DTYPE_SOCKET)
835 			cmd = SIOCGPGRP;
836 		else
837 			cmd = TIOCGPGRP;
838 		error = (*fp->f_ops->fo_ioctl)(fp, cmd, data, p);
839 		if (fp->f_type != DTYPE_SOCKET)
840 			*(int *)data = -*(int *)data;
841 		break;
842 
843 	default:
844 		error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
845 		if (error == 0 && (com&IOC_OUT) && size)
846 			error = copyout(p, data, uap->cmarg, (u_int)size);
847 		break;
848 	}
849 
850 	if (memp)
851 		free(memp, M_IOCTLOPS);
852 	return (error);
853 }
854 
855 int	selwait, nselcoll;
856 
857 
858 
859 /* BSD select() function system call handler.  */
860 int
select(p,uap,retval)861 select(p, uap, retval)
862 	register struct proc *p;
863 	register struct args {
864 		int	nd;
865 		fd_set	*in, *ou, *ex;
866 		struct	timeval *tv;
867 	} *uap;
868 	int *retval;
869 {
870 	fd_set ibits[3], obits[3];
871 	struct timeval atv;
872 	int ncoll, ni, error = 0, timo;
873 
874 	(void) memset((caddr_t)ibits, 0, sizeof(ibits));
875 	(void) memset((caddr_t)obits, 0, sizeof(obits));
876 	if (uap->nd > p->p_fd->fd_nfiles)
877 		uap->nd = p->p_fd->fd_nfiles;
878 	ni = howmany(uap->nd, NFDBITS);
879 
880 #define	getbits(name, x) \
881 	if (uap->name) { \
882 		error = copyin(p, (caddr_t)uap->name, (caddr_t)&ibits[x], \
883 		    (unsigned)(ni * sizeof(fd_mask))); \
884 		if (error) \
885 			goto done; \
886 	}
887 	getbits(in, 0);
888 	getbits(ou, 1);
889 	getbits(ex, 2);
890 #undef	getbits
891 
892 	if (uap->tv) {
893 		error = copyin(p, (caddr_t)uap->tv, (caddr_t)&atv,
894 			sizeof (atv));
895 		if (error)
896 			goto done;
897 		if (itimerfix(&atv)) {
898 			error = EINVAL;
899 			goto done;
900 		}
901 		splclock(); timevaladd(&atv, &time); splnone();
902 		timo = hzto(&atv);
903 	} else
904 		timo = 0;
905 
906 retry:
907 	ncoll = nselcoll;
908 	p->p_flag |= SSEL;
909 	error = selscan(p, ibits, obits, uap->nd, retval);
910 	if (error || *retval)
911 		goto done;
912 
913 	splhigh();
914 	/* this should be timercmp(&time, &atv, >=) */
915 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
916 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
917 		p->p_flag &= ~SSEL;
918 		/* error = EWOULDBLOCK; */
919 		splnone();
920 		goto done;
921 	}
922 	if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
923 		splnone();
924 		goto retry;
925 	}
926 	p->p_flag &= ~SSEL;
927 	error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
928 	splnone();
929 
930 	if (error == 0)
931 		goto retry;
932 done:
933 
934 	/* select is not restarted after signals... */
935 	if (error == ERESTART)
936 		error = EINTR;
937 	if (error == EWOULDBLOCK)
938 		error = 0;
939 
940 #define	putbits(name, x) \
941 	if (uap->name) { \
942 		int error2 = copyout(p, (caddr_t)&obits[x], (caddr_t)uap->name, \
943 		    (unsigned)(ni * sizeof(fd_mask))); \
944 		if (error2) \
945 			error = error2; \
946 	}
947 	if (error == 0) {
948 		putbits(in, 0);
949 		putbits(ou, 1);
950 		putbits(ex, 2);
951 	}
952 #undef putbits
953 
954 	return (error);
955 }
956 
957 static int
selscan(struct proc * p,fd_set * ibits,fd_set * obits,int nfd,int * retval)958 selscan(struct proc *p, fd_set *ibits, fd_set *obits, int nfd, int *retval)
959 {
960 	struct filedesc *fdp = p->p_fd;
961 	int which, i, j;
962 	fd_mask bits;
963 	int flag;
964 	struct file *fp;
965 	int error = 0, n = 0;
966 
967 	for (which = 0; which < 3; which++) {
968 		switch (which) {
969 
970 		case 0:
971 			flag = FREAD; break;
972 
973 		case 1:
974 			flag = FWRITE; break;
975 
976 		case 2:
977 			flag = 0; break;
978 		}
979 		for (i = 0; i < nfd; i += NFDBITS) {
980 			bits = ibits[which].fds_bits[i/NFDBITS];
981 			while ((j = ffs(bits)) && i + --j < nfd) {
982 				bits &= ~(1 << j);
983 				fp = fdp->fd_ofiles[i + j];
984 				if (fp == NULL) {
985 					error = EBADF;
986 					break;
987 				}
988 				if ((*fp->f_ops->fo_select)(fp, flag, p)) {
989 					FD_SET(i + j, &obits[which]);
990 					n++;
991 				}
992 			}
993 		}
994 	}
995 	*retval = n;
996 	return (error);
997 }
998 
999 /*ARGSUSED*/
1000 int
seltrue(dev_t dev,int which,struct proc * p)1001 seltrue(dev_t dev, int which, struct proc *p)
1002 {
1003 
1004 	return (1);
1005 }
1006 
1007 
1008 void
selwakeup(pid_t pid,int coll)1009 selwakeup(pid_t pid, int coll)
1010 {
1011 	register struct proc *p;
1012 
1013 	if (coll) {
1014 		nselcoll++;
1015 		wakeup((caddr_t)&selwait);
1016 	}
1017 
1018 	if (pid && (p = pfind(pid))) {
1019 		int s = splhigh();
1020 
1021 		if (p->p_wchan == (caddr_t)&selwait) {
1022 			if (p->p_stat == SSLEEP)
1023 				setrun(p);
1024 			else
1025 				unsleep(p);
1026 		} else if (p->p_flag & SSEL)
1027 			p->p_flag &= ~SSEL;
1028 		splx(s);
1029 	}
1030 }
1031 
1032 /*
1033  * Allocate a file descriptor for the process.
1034  */
1035 int
fdalloc(struct proc * p,int want,int * result)1036 fdalloc(struct proc *p, int want, int *result)
1037 {
1038 	register struct filedesc *fdp = p->p_fd;
1039 	int i;
1040 	int lim, last, nfiles;
1041 	struct file **newofile;
1042 	char *newofileflags;
1043 
1044 	/*
1045 	 * Search for a free descriptor starting at the higher
1046 	 * of want or fd_freefile.  If that fails, consider
1047 	 * expanding the ofile array.
1048 	 */
1049 	lim = p->p_rlimit[RLIMIT_OFILE].rlim_cur;
1050 	for (;;) {
1051 		last = min(fdp->fd_nfiles, lim);
1052 		if ((i = want) < fdp->fd_freefile)
1053 			i = fdp->fd_freefile;
1054 		for (; i < last; i++) {
1055 			if (fdp->fd_ofiles[i] == NULL) {
1056 				fdp->fd_ofileflags[i] = 0;
1057 				if (i > fdp->fd_lastfile)
1058 					fdp->fd_lastfile = i;
1059 				if (want <= fdp->fd_freefile)
1060 					fdp->fd_freefile = i;
1061 				*result = i;
1062 				return (0);
1063 			}
1064 		}
1065 
1066 		/* no space in current array.  expand it? */
1067 		if (fdp->fd_nfiles >= lim)
1068 			return (EMFILE);
1069 		if (fdp->fd_nfiles < NDEXTENT)
1070 			nfiles = NDEXTENT;
1071 		else
1072 			nfiles = (2 * fdp->fd_nfiles) % lim;
1073 
1074 		MALLOC(newofile, struct file **, nfiles * OFILESIZE,
1075 		    M_FILEDESC, M_WAITOK);
1076 		newofileflags = (char *) &newofile[nfiles];
1077 
1078 		/*
1079 		 * Copy the existing ofile and ofileflags arrays
1080 		 * and zero the new portion of each array.
1081 		 */
1082 		(void) memcpy(newofile, fdp->fd_ofiles,
1083 			(i = sizeof(struct file *) * fdp->fd_nfiles));
1084 		(void) memset((char *)newofile + i, 0,
1085 			nfiles * sizeof(struct file *) - i);
1086 		(void) memcpy(newofileflags, fdp->fd_ofileflags,
1087 			(i = sizeof(char) * fdp->fd_nfiles));
1088 		(void) memset(newofileflags + i, 0, nfiles * sizeof(char) - i);
1089 
1090 		if (fdp->fd_nfiles > NDFILE)
1091 			FREE(fdp->fd_ofiles, M_FILEDESC);
1092 
1093 		fdp->fd_ofiles = newofile;
1094 		fdp->fd_ofileflags = newofileflags;
1095 		fdp->fd_nfiles = nfiles;
1096 	}
1097 }
1098 
1099 /*
1100  * Check to see whether n user file descriptors
1101  * are available to the process p.
1102  */
1103 int
fdavail(struct proc * p,int n)1104 fdavail(struct proc *p, int n)
1105 {
1106 	struct filedesc *fdp = p->p_fd;
1107 	struct file **fpp;
1108 	int i;
1109 
1110 	if ((i = p->p_rlimit[RLIMIT_OFILE].rlim_cur - fdp->fd_nfiles) > 0 &&
1111 	    (n -= i) <= 0)
1112 		return (1);
1113 
1114 	fpp = &fdp->fd_ofiles[fdp->fd_freefile];
1115 	for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++)
1116 		if (*fpp == NULL && --n <= 0)
1117 			return (1);
1118 	return (0);
1119 }
1120 
1121 /*
1122  * Create a new open file structure and allocate
1123  * a file descriptor for the process that refers to it.
1124  */
1125 int
falloc(struct proc * p,struct file ** resultfp,int * resultfd)1126 falloc(struct proc *p, struct file **resultfp, int *resultfd)
1127 {
1128 	struct file *fp, *fq, **fpp;
1129 	int error, i;
1130 
1131 	if (error = fdalloc(p, 0, &i))
1132 		return (error);
1133 	if (nfiles >= maxfiles) {
1134 		tablefull("file");
1135 		return (ENFILE);
1136 	}
1137 
1138 	/*
1139 	 * Allocate a new file descriptor.
1140 	 * If the process has file descriptor zero open, add to the list
1141 	 * of open files at that point, otherwise put it at the front of
1142 	 * the list of open files.
1143 	 */
1144 	nfiles++;
1145 	MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
1146 	if (fq = p->p_fd->fd_ofiles[0])
1147 		fpp = &fq->f_filef;
1148 	else
1149 		fpp = &filehead;
1150 	p->p_fd->fd_ofiles[i] = fp;
1151 	if (fq = *fpp)
1152 		fq->f_fileb = &fp->f_filef;
1153 	fp->f_filef = fq;
1154 	fp->f_fileb = fpp;
1155 	*fpp = fp;
1156 
1157 	fp->f_count = 1;
1158 	fp->f_msgcount = 0;
1159 	fp->f_offset = 0;
1160 	fp->f_cred = p->p_ucred;
1161 	crhold(fp->f_cred);
1162 
1163 	if (resultfp)
1164 		*resultfp = fp;
1165 	if (resultfd)
1166 		*resultfd = i;
1167 	return (0);
1168 }
1169 
1170 /*
1171  * Free a file instance, recovering resources.
1172  */
1173 void
ffree(struct file * fp)1174 ffree(struct file *fp)
1175 {
1176 	struct file *fq;
1177 
1178 	/* remove from global file list */
1179 	if (fq = fp->f_filef)
1180 		fq->f_fileb = fp->f_fileb;
1181 	*fp->f_fileb = fq;
1182 
1183 #ifdef DIAGNOSTIC
1184 	fp->f_filef = NULL;
1185 	fp->f_fileb = NULL;
1186 	fp->f_count = 0;
1187 #endif
1188 
1189 	crfree(fp->f_cred);
1190 	nfiles--;
1191 	FREE(fp, M_FILE);
1192 }
1193 
1194 /*
1195  * Copy a filedesc structure.
1196  */
1197 struct filedesc *
fdcopy(struct proc * p)1198 fdcopy(struct proc *p)
1199 {
1200 	struct filedesc *newfdp, *fdp = p->p_fd;
1201 	struct file **fpp;
1202 	int i;
1203 
1204 	MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),
1205 	    M_FILEDESC, M_WAITOK);
1206 	(void) memcpy(newfdp, fdp, sizeof(struct filedesc));
1207 	newfdp->fd_refcnt = 1;
1208 
1209 	VREF(newfdp->fd_cdir);
1210 	if (newfdp->fd_rdir)
1211 		VREF(newfdp->fd_rdir);
1212 
1213 	/*
1214 	 * If the number of open files fits in the internal arrays
1215 	 * of the open file structure, use them, otherwise allocate
1216 	 * additional memory for the number of descriptors currently
1217 	 * in use.
1218 	 */
1219 	if (newfdp->fd_lastfile < NDFILE) {
1220 		newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
1221 		newfdp->fd_ofileflags =
1222 		    ((struct filedesc0 *) newfdp)->fd_dfileflags;
1223 		i = NDFILE;
1224 	} else {
1225 		/*
1226 		 * Compute the smallest multiple of NDEXTENT needed
1227 		 * for the file descriptors currently in use,
1228 		 * allowing the table to shrink.
1229 		 */
1230 		i = newfdp->fd_nfiles;
1231 		while (i > 2 * NDEXTENT && i >= newfdp->fd_lastfile * 2)
1232 			i /= 2;
1233 		MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE,
1234 		    M_FILEDESC, M_WAITOK);
1235 		newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
1236 	}
1237 
1238 	newfdp->fd_nfiles = i;
1239 	(void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles, i * sizeof(struct file **));
1240 	(void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags, i * sizeof(char));
1241 	fpp = newfdp->fd_ofiles;
1242 	for (i = newfdp->fd_lastfile; i-- >= 0; fpp++)
1243 		if (*fpp != NULL)
1244 			(*fpp)->f_count++;
1245 
1246 	return (newfdp);
1247 }
1248 
1249 /*
1250  * Release a filedesc structure.
1251  */
1252 void
fdfree(struct proc * p)1253 fdfree(struct proc *p)
1254 {
1255 	register struct filedesc *fdp = p->p_fd;
1256 	struct file **fpp;
1257 	char *fdfp;
1258 	register int i;
1259 
1260 	if (--fdp->fd_refcnt > 0)
1261 		return;
1262 
1263 	fpp = fdp->fd_ofiles;
1264 	fdfp = fdp->fd_ofileflags;
1265 	for (i = 0; i <= fdp->fd_lastfile; i++, fpp++, fdfp++)
1266 		if (*fpp != NULL) {
1267 			if (*fdfp & UF_MAPPED)
1268 				(void) munmapfd(p, i);
1269 			(void) closef(*fpp, p);
1270 		}
1271 
1272 	if (fdp->fd_nfiles > NDFILE)
1273 		FREE(fdp->fd_ofiles, M_FILEDESC);
1274 
1275 	vrele(fdp->fd_cdir);
1276 	if (fdp->fd_rdir)
1277 		vrele(fdp->fd_rdir);
1278 
1279 	FREE(fdp, M_FILEDESC);
1280 }
1281 
1282 /* Close any files on execve()? */
1283 void
fdcloseexec(struct proc * p)1284 fdcloseexec(struct proc *p)
1285 {
1286 	struct filedesc *fdp = p->p_fd;
1287 	struct file **fpp;
1288 	char *fdfp;
1289 	register int i;
1290 
1291 	fpp = fdp->fd_ofiles;
1292 	fdfp = fdp->fd_ofileflags;
1293 	for (i = 0; i <= fdp->fd_lastfile; i++, fpp++, fdfp++)
1294 		if (*fpp != NULL && (*fdfp & UF_EXCLOSE)) {
1295 			if (*fdfp & UF_MAPPED)
1296 				(void) munmapfd(p, i);
1297 			(void) closef(*fpp, p);
1298 			*fpp = NULL;
1299 			*fdfp = 0;
1300 			if (i < fdp->fd_freefile)
1301 				fdp->fd_freefile = i;
1302 		}
1303 
1304 	while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
1305 		fdp->fd_lastfile--;
1306 }
1307 
1308 /*
1309  * Private file close function.
1310  * Decrement reference count on file structure.
1311  */
1312 int
closef(struct file * fp,struct proc * p)1313 closef(struct file *fp, struct proc *p)
1314 {
1315 	struct vnode *vp;
1316 	struct flock lf;
1317 	int error;
1318 
1319 	if (fp == NULL)
1320 		return (0);
1321 	/*
1322 	 * POSIX record locking dictates that any close releases ALL
1323 	 * locks owned by this process.  This is handled by setting
1324 	 * a flag in the unlock to free ONLY locks obeying POSIX
1325 	 * semantics, and not to free BSD-style file locks.
1326 	 */
1327 	if ((p->p_flag & SADVLCK) && fp->f_type == DTYPE_VNODE) {
1328 		lf.l_whence = SEEK_SET;
1329 		lf.l_start = 0;
1330 		lf.l_len = 0;
1331 		lf.l_type = F_UNLCK;
1332 		vp = (struct vnode *)fp->f_data;
1333 		(void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
1334 	}
1335 	if (--fp->f_count > 0)
1336 		return (0);
1337 
1338 #ifdef	DIAGNOSTIC
1339 	if (fp->f_count < 0)
1340 		panic("closef: count < 0");
1341 #endif
1342 	if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
1343 		lf.l_whence = SEEK_SET;
1344 		lf.l_start = 0;
1345 		lf.l_len = 0;
1346 		lf.l_type = F_UNLCK;
1347 		vp = (struct vnode *)fp->f_data;
1348 		(void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
1349 	}
1350 
1351 	error = (*fp->f_ops->fo_close)(fp, p);
1352 	ffree(fp);
1353 	return (error);
1354 }
1355 
1356 /*
1357  * Apply an advisory lock on a file descriptor.
1358  *
1359  * Just attempt to get a record lock of the requested type on
1360  * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
1361  */
1362 
1363 /* ARGSUSED */
1364 int
flock(p,uap,retval)1365 flock(p, uap, retval)
1366 	struct proc *p;
1367 	struct args {
1368 		int	fd;
1369 		int	how;
1370 	} *uap;
1371 	int *retval;
1372 {
1373 	register struct filedesc *fdp = p->p_fd;
1374 	register struct file *fp;
1375 	struct vnode *vp;
1376 	struct flock lf;
1377 	int error;
1378 
1379 	if ((unsigned)uap->fd >= fdp->fd_nfiles ||
1380 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
1381 		return (EBADF);
1382 	if (fp->f_type != DTYPE_VNODE)
1383 		return (EOPNOTSUPP);
1384 
1385 	vp = (struct vnode *)fp->f_data;
1386 	lf.l_whence = SEEK_SET;
1387 	lf.l_start = 0;
1388 	lf.l_len = 0;
1389 
1390 	if (uap->how & LOCK_UN) {
1391 		lf.l_type = F_UNLCK;
1392 		fp->f_flag &= ~FHASLOCK;
1393 		return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
1394 	}
1395 
1396 	if (uap->how & LOCK_EX)
1397 		lf.l_type = F_WRLCK;
1398 	else if (uap->how & LOCK_SH)
1399 		lf.l_type = F_RDLCK;
1400 	else
1401 		return (EBADF);
1402 
1403 	fp->f_flag |= FHASLOCK;
1404 	if (uap->how & LOCK_NB)
1405 		return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
1406 
1407 	return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
1408 }
1409 
1410 /*
1411  * File Descriptor pseudo-device driver (/dev/fd/).
1412  *
1413  * Opening minor device N dup()s the file (if any) connected to file
1414  * descriptor N belonging to the calling process.  Note that this driver
1415  * consists of only the ``open()'' routine, because all subsequent
1416  * references to this file will be directed to the other file.
1417  */
1418 /* ARGSUSED */
1419 static int
fdopen(dev_t dev,int mode,int type,struct proc * p)1420 fdopen(dev_t dev, int mode, int type, struct proc *p)
1421 {
1422 
1423 	/*
1424 	 * XXX Kludge: set curproc->p_dupfd to contain the value of the
1425 	 * the file descriptor being sought for duplication. The error
1426 	 * return ensures that the vnode for this device will be released
1427 	 * by vn_open. Open will detect this special error and take the
1428 	 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
1429 	 * will simply report the error.
1430 	 */
1431 	p->p_dupfd = minor(dev);		/* XXX */
1432 	return (ENODEV);
1433 }
1434 
1435 static struct devif fd_devif =
1436 {
1437 	{0}, -1, -2, 0, 0, 0, 0, 0, 0,
1438 	fdopen, 0, 0, 0, 0, 0, 0,
1439 	0, 0, 0, 0,
1440 	0,  0,
1441 };
1442 
DRIVER_MODCONFIG()1443 DRIVER_MODCONFIG() {
1444 	char *cfg_string = "fdesc 53.";
1445 
1446 	if (devif_config(&cfg_string, &fd_devif) == 0)
1447 		return;
1448 }
1449 
1450 /*
1451  * Duplicate the specified descriptor to a free descriptor.
1452  */
1453 int
dupfdopen(struct filedesc * fdp,int indx,int dfd,int mode)1454 dupfdopen(struct filedesc *fdp, int indx, int dfd, int mode)
1455 {
1456 	register struct file *wfp;
1457 	struct file *fp;
1458 
1459 	/*
1460 	 * If the to-be-dup'd fd number is greater than the allowed number
1461 	 * of file descriptors, or the fd to be dup'd has already been
1462 	 * closed, reject.  Note, check for new == old is necessary as
1463 	 * falloc could allocate an already closed to-be-dup'd descriptor
1464 	 * as the new descriptor.
1465 	 */
1466 	fp = fdp->fd_ofiles[indx];
1467 	if ((u_int)dfd >= fdp->fd_nfiles ||
1468 	    (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp)
1469 		return (EBADF);
1470 
1471 	/*
1472 	 * Check that the mode the file is being opened for is a subset
1473 	 * of the mode of the existing descriptor.
1474 	 */
1475 	if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
1476 		return (EACCES);
1477 	fdp->fd_ofiles[indx] = wfp;
1478 	fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1479 	wfp->f_count++;
1480 	if (indx > fdp->fd_lastfile)
1481 		fdp->fd_lastfile = indx;
1482 	return (0);
1483 }
1484