xref: /386bsd/usr/src/kernel/kern/descrip.c (revision a2142627)
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 $
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
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
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
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
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 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 			*retval = ((struct socket *)fp->f_data)->so_pgid;
241 			return (0);
242 		}
243 		error = (*fp->f_ops->fo_ioctl)
244 			(fp, (int)TIOCGPGRP, (caddr_t)retval, p);
245 		*retval = -*retval;
246 		return (error);
247 
248 	case F_SETOWN:
249 		if (fp->f_type == DTYPE_SOCKET) {
250 			((struct socket *)fp->f_data)->so_pgid = uap->arg;
251 			return (0);
252 		}
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 		return ((*fp->f_ops->fo_ioctl)
262 			(fp, (int)TIOCSPGRP, (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
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
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 	switch (fp->f_type) {
380 
381 	case DTYPE_VNODE:
382 		error = vn_stat((struct vnode *)fp->f_data, &ub, p);
383 		break;
384 
385 	case DTYPE_SOCKET:
386 		error = soo_stat((struct socket *)fp->f_data, &ub);
387 		break;
388 
389 	default:
390 		panic("fstat");
391 		/*NOTREACHED*/
392 	}
393 
394 	if (error == 0)
395 		error = copyout(p, (caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub));
396 	return (error);
397 }
398 
399 
400 
401 /* POSIX Read function system call handler.  */
402 int
403 read(p, uap, retval)
404 	struct proc *p;
405 	register struct args {
406 		int	fdes;
407 		char	*cbuf;
408 		unsigned count;
409 	} *uap;
410 	int *retval;
411 {
412 	register struct file *fp;
413 	register struct filedesc *fdp = p->p_fd;
414 	struct uio auio;
415 	struct iovec aiov;
416 	long cnt, error = 0;
417 #ifdef KTRACE
418 	struct iovec ktriov;
419 #endif
420 
421 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
422 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
423 	    (fp->f_flag & FREAD) == 0)
424 		return (EBADF);
425 
426 	aiov.iov_base = (caddr_t)uap->cbuf;
427 	aiov.iov_len = uap->count;
428 	auio.uio_iov = &aiov;
429 	auio.uio_iovcnt = 1;
430 	auio.uio_resid = uap->count;
431 	auio.uio_rw = UIO_READ;
432 	auio.uio_segflg = UIO_USERSPACE;
433 	auio.uio_procp = p;
434 
435 #ifdef KTRACE
436 	/*
437 	 * if tracing, save a copy of iovec
438 	 */
439 	if (KTRPOINT(p, KTR_GENIO))
440 		ktriov = aiov;
441 #endif
442 
443 	cnt = uap->count;
444 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
445 		if (auio.uio_resid != cnt && (error == ERESTART ||
446 		    error == EINTR || error == EWOULDBLOCK))
447 			error = 0;
448 	cnt -= auio.uio_resid;
449 
450 #ifdef KTRACE
451 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
452 		ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error);
453 #endif
454 
455 	*retval = cnt;
456 	return (error);
457 }
458 
459 
460 
461 /* BSD scatter readv() system call handler. */
462 int
463 readv(p, uap, retval)
464 	struct proc *p;
465 	register struct args {
466 		int	fdes;
467 		struct	iovec *iovp;
468 		unsigned iovcnt;
469 	} *uap;
470 	int *retval;
471 {
472 	struct file *fp;
473 	struct filedesc *fdp = p->p_fd;
474 	struct uio auio;
475 	struct iovec *iov;
476 	struct iovec *saveiov;
477 	struct iovec aiov[UIO_SMALLIOV];
478 	long i, cnt, error = 0;
479 	unsigned iovlen;
480 #ifdef KTRACE
481 	struct iovec *ktriov = NULL;
482 #endif
483 
484 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
485 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
486 	    (fp->f_flag & FREAD) == 0)
487 		return (EBADF);
488 
489 	/* note: can't use iovlen until iovcnt is validated */
490 	iovlen = uap->iovcnt * sizeof (struct iovec);
491 
492 	if (uap->iovcnt > UIO_SMALLIOV) {
493 		if (uap->iovcnt > UIO_MAXIOV)
494 			return (EINVAL);
495 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
496 		saveiov = iov;
497 	} else
498 		iov = aiov;
499 
500 	auio.uio_iov = iov;
501 	auio.uio_iovcnt = uap->iovcnt;
502 	auio.uio_rw = UIO_READ;
503 	auio.uio_segflg = UIO_USERSPACE;
504 	auio.uio_procp = p;
505 
506 	if (error = copyin(p, (caddr_t)uap->iovp, (caddr_t)iov, iovlen))
507 		goto done;
508 
509 	auio.uio_resid = 0;
510 	for (i = 0; i < uap->iovcnt; i++) {
511 		if (iov->iov_len < 0) {
512 			error = EINVAL;
513 			goto done;
514 		}
515 		auio.uio_resid += iov->iov_len;
516 		if (auio.uio_resid < 0) {
517 			error = EINVAL;
518 			goto done;
519 		}
520 		iov++;
521 	}
522 
523 #ifdef KTRACE
524 	/*
525 	 * if tracing, save a copy of iovec
526 	 */
527 	if (KTRPOINT(p, KTR_GENIO))  {
528 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
529 		(void) memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
530 	}
531 #endif
532 
533 	cnt = auio.uio_resid;
534 	if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
535 		if (auio.uio_resid != cnt && (error == ERESTART ||
536 		    error == EINTR || error == EWOULDBLOCK))
537 			error = 0;
538 	cnt -= auio.uio_resid;
539 
540 #ifdef KTRACE
541 	if (ktriov != NULL) {
542 		if (error == 0)
543 			ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov,
544 			    cnt, error);
545 		FREE(ktriov, M_TEMP);
546 	}
547 #endif
548 
549 	*retval = cnt;
550 done:
551 	if (uap->iovcnt > UIO_SMALLIOV)
552 		FREE(saveiov, M_IOV);
553 
554 	return (error);
555 }
556 
557 
558 
559 /* POSIX write() function system call handler */
560 int
561 write(p, uap, retval)
562 	struct proc *p;
563 	struct args {
564 		int	fdes;
565 		char	*cbuf;
566 		unsigned count;
567 	} *uap;
568 	int *retval;
569 {
570 	register struct file *fp;
571 	register struct filedesc *fdp = p->p_fd;
572 	struct uio auio;
573 	struct iovec aiov;
574 	long cnt, error = 0;
575 #ifdef KTRACE
576 	struct iovec ktriov;
577 #endif
578 
579 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
580 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
581 	    (fp->f_flag & FWRITE) == 0)
582 		return (EBADF);
583 
584 	aiov.iov_base = (caddr_t)uap->cbuf;
585 	aiov.iov_len = uap->count;
586 	auio.uio_iov = &aiov;
587 	auio.uio_iovcnt = 1;
588 	auio.uio_resid = uap->count;
589 	auio.uio_rw = UIO_WRITE;
590 	auio.uio_segflg = UIO_USERSPACE;
591 	auio.uio_procp = p;
592 
593 #ifdef KTRACE
594 	/*
595 	 * if tracing, save a copy of iovec
596 	 */
597 	if (KTRPOINT(p, KTR_GENIO))
598 		ktriov = aiov;
599 #endif
600 
601 	cnt = uap->count;
602 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
603 		if (auio.uio_resid != cnt && (error == ERESTART ||
604 		    error == EINTR || error == EWOULDBLOCK))
605 			error = 0;
606 		if (error == EPIPE)
607 			psignal(p, SIGPIPE);
608 	}
609 	cnt -= auio.uio_resid;
610 
611 #ifdef KTRACE
612 	if (KTRPOINT(p, KTR_GENIO) && error == 0)
613 		ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
614 		    &ktriov, cnt, error);
615 #endif
616 
617 	*retval = cnt;
618 	return (error);
619 }
620 
621 
622 
623 /* BSD gather write writev() function system call handler */
624 int
625 writev(p, uap, retval)
626 	struct proc *p;
627 	register struct args {
628 		int	fdes;
629 		struct	iovec *iovp;
630 		unsigned iovcnt;
631 	} *uap;
632 	int *retval;
633 {
634 	register struct file *fp;
635 	register struct filedesc *fdp = p->p_fd;
636 	struct uio auio;
637 	register struct iovec *iov;
638 	struct iovec *saveiov;
639 	struct iovec aiov[UIO_SMALLIOV];
640 	long i, cnt, error = 0;
641 	unsigned iovlen;
642 #ifdef KTRACE
643 	struct iovec *ktriov = NULL;
644 #endif
645 
646 	if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
647 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
648 	    (fp->f_flag & FWRITE) == 0)
649 		return (EBADF);
650 
651 	/* note: can't use iovlen until iovcnt is validated */
652 	iovlen = uap->iovcnt * sizeof (struct iovec);
653 	if (uap->iovcnt > UIO_SMALLIOV) {
654 		if (uap->iovcnt > UIO_MAXIOV)
655 			return (EINVAL);
656 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
657 		saveiov = iov;
658 	} else
659 		iov = aiov;
660 
661 	auio.uio_iov = iov;
662 	auio.uio_iovcnt = uap->iovcnt;
663 	auio.uio_rw = UIO_WRITE;
664 	auio.uio_segflg = UIO_USERSPACE;
665 	auio.uio_procp = p;
666 
667 	if (error = copyin(p, (caddr_t)uap->iovp, (caddr_t)iov, iovlen))
668 		goto done;
669 
670 	auio.uio_resid = 0;
671 	for (i = 0; i < uap->iovcnt; i++) {
672 		if (iov->iov_len < 0) {
673 			error = EINVAL;
674 			goto done;
675 		}
676 		auio.uio_resid += iov->iov_len;
677 		if (auio.uio_resid < 0) {
678 			error = EINVAL;
679 			goto done;
680 		}
681 		iov++;
682 	}
683 
684 #ifdef KTRACE
685 	/*
686 	 * if tracing, save a copy of iovec
687 	 */
688 	if (KTRPOINT(p, KTR_GENIO))  {
689 		MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
690 		(void) memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
691 	}
692 #endif
693 
694 	cnt = auio.uio_resid;
695 	if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
696 		if (auio.uio_resid != cnt && (error == ERESTART ||
697 		    error == EINTR || error == EWOULDBLOCK))
698 			error = 0;
699 		if (error == EPIPE)
700 			psignal(p, SIGPIPE);
701 	}
702 	cnt -= auio.uio_resid;
703 
704 #ifdef KTRACE
705 	if (ktriov != NULL) {
706 		if (error == 0)
707 			ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
708 				ktriov, cnt, error);
709 		FREE(ktriov, M_TEMP);
710 	}
711 #endif
712 
713 	*retval = cnt;
714 done:
715 	if (uap->iovcnt > UIO_SMALLIOV)
716 		FREE(saveiov, M_IOV);
717 
718 	return (error);
719 }
720 
721 
722 
723 
724 /* POSIX ioctl() function system call handler */
725 int
726 ioctl(p, uap, retval)
727 	struct proc *p;
728 	register struct args {
729 		int	fdes;
730 		int	cmd;
731 		caddr_t	cmarg;
732 	} *uap;
733 	int *retval;
734 {
735 	struct file *fp;
736 	struct filedesc *fdp = p->p_fd;
737 	int com, error;
738 	u_int size;
739 	caddr_t memp = 0;
740 #define STK_PARAMS	128
741 	char stkbuf[STK_PARAMS];
742 	caddr_t data = stkbuf;
743 	int tmp;
744 
745 	if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
746 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
747 		return (EBADF);
748 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
749 		return (EBADF);
750 
751 	com = uap->cmd;
752 	if (com == FIOCLEX) {
753 		fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE;
754 		return (0);
755 	}
756 	if (com == FIONCLEX) {
757 		fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE;
758 		return (0);
759 	}
760 
761 	/*
762 	 * Interpret high order word to find
763 	 * amount of data to be copied to/from the
764 	 * user's address space.
765 	 */
766 	size = IOCPARM_LEN(com);
767 	if (size > IOCPARM_MAX)
768 		return (ENOTTY);
769 	if (size > sizeof (stkbuf)) {
770 		memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
771 		data = memp;
772 	}
773 	if (com&IOC_IN) {
774 		if (size) {
775 			error = copyin(p, uap->cmarg, data, (u_int)size);
776 			if (error) {
777 				if (memp)
778 					free(memp, M_IOCTLOPS);
779 				return (error);
780 			}
781 		} else
782 			*(caddr_t *)data = uap->cmarg;
783 	} else if ((com&IOC_OUT) && size)
784 		/*
785 		 * Zero the buffer so the user always
786 		 * gets back something deterministic.
787 		 */
788 		(void) memset(data, 0, size);
789 	else if (com&IOC_VOID)
790 		*(caddr_t *)data = uap->cmarg;
791 
792 	switch (com) {
793 
794 	case FIONBIO:
795 		if (tmp = *(int *)data)
796 			fp->f_flag |= FNONBLOCK;
797 		else
798 			fp->f_flag &= ~FNONBLOCK;
799 		error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
800 		break;
801 
802 	case FIOASYNC:
803 		if (tmp = *(int *)data)
804 			fp->f_flag |= FASYNC;
805 		else
806 			fp->f_flag &= ~FASYNC;
807 		error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
808 		break;
809 
810 	case FIOSETOWN:
811 		tmp = *(int *)data;
812 		if (fp->f_type == DTYPE_SOCKET) {
813 			((struct socket *)fp->f_data)->so_pgid = tmp;
814 			error = 0;
815 			break;
816 		}
817 		if (tmp <= 0) {
818 			tmp = -tmp;
819 		} else {
820 			struct proc *p1 = pfind(tmp);
821 			if (p1 == 0) {
822 				error = ESRCH;
823 				break;
824 			}
825 			tmp = p1->p_pgrp->pg_id;
826 		}
827 		error = (*fp->f_ops->fo_ioctl)
828 			(fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
829 		break;
830 
831 	case FIOGETOWN:
832 		if (fp->f_type == DTYPE_SOCKET) {
833 			error = 0;
834 			*(int *)data = ((struct socket *)fp->f_data)->so_pgid;
835 			break;
836 		}
837 		error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
838 		*(int *)data = -*(int *)data;
839 		break;
840 
841 	default:
842 		error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
843 		if (error == 0 && (com&IOC_OUT) && size)
844 			error = copyout(p, data, uap->cmarg, (u_int)size);
845 		break;
846 	}
847 
848 	if (memp)
849 		free(memp, M_IOCTLOPS);
850 	return (error);
851 }
852 
853 int	selwait, nselcoll;
854 
855 
856 
857 /* BSD select() function system call handler.  */
858 int
859 select(p, uap, retval)
860 	register struct proc *p;
861 	register struct args {
862 		int	nd;
863 		fd_set	*in, *ou, *ex;
864 		struct	timeval *tv;
865 	} *uap;
866 	int *retval;
867 {
868 	fd_set ibits[3], obits[3];
869 	struct timeval atv;
870 	int ncoll, ni, error = 0, timo;
871 
872 	(void) memset((caddr_t)ibits, 0, sizeof(ibits));
873 	(void) memset((caddr_t)obits, 0, sizeof(obits));
874 	if (uap->nd > p->p_fd->fd_nfiles)
875 		uap->nd = p->p_fd->fd_nfiles;
876 	ni = howmany(uap->nd, NFDBITS);
877 
878 #define	getbits(name, x) \
879 	if (uap->name) { \
880 		error = copyin(p, (caddr_t)uap->name, (caddr_t)&ibits[x], \
881 		    (unsigned)(ni * sizeof(fd_mask))); \
882 		if (error) \
883 			goto done; \
884 	}
885 	getbits(in, 0);
886 	getbits(ou, 1);
887 	getbits(ex, 2);
888 #undef	getbits
889 
890 	if (uap->tv) {
891 		error = copyin(p, (caddr_t)uap->tv, (caddr_t)&atv,
892 			sizeof (atv));
893 		if (error)
894 			goto done;
895 		if (itimerfix(&atv)) {
896 			error = EINVAL;
897 			goto done;
898 		}
899 		splclock(); timevaladd(&atv, &time); splnone();
900 		timo = hzto(&atv);
901 	} else
902 		timo = 0;
903 
904 retry:
905 	ncoll = nselcoll;
906 	p->p_flag |= SSEL;
907 	error = selscan(p, ibits, obits, uap->nd, retval);
908 	if (error || *retval)
909 		goto done;
910 
911 	splhigh();
912 	/* this should be timercmp(&time, &atv, >=) */
913 	if (uap->tv && (time.tv_sec > atv.tv_sec ||
914 	    time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
915 		p->p_flag &= ~SSEL;
916 		/* error = EWOULDBLOCK; */
917 		splnone();
918 		goto done;
919 	}
920 	if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
921 		splnone();
922 		goto retry;
923 	}
924 	p->p_flag &= ~SSEL;
925 	error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
926 	splnone();
927 
928 	if (error == 0)
929 		goto retry;
930 done:
931 
932 	/* select is not restarted after signals... */
933 	if (error == ERESTART)
934 		error = EINTR;
935 	if (error == EWOULDBLOCK)
936 		error = 0;
937 
938 #define	putbits(name, x) \
939 	if (uap->name) { \
940 		int error2 = copyout(p, (caddr_t)&obits[x], (caddr_t)uap->name, \
941 		    (unsigned)(ni * sizeof(fd_mask))); \
942 		if (error2) \
943 			error = error2; \
944 	}
945 	if (error == 0) {
946 		putbits(in, 0);
947 		putbits(ou, 1);
948 		putbits(ex, 2);
949 	}
950 #undef putbits
951 
952 	return (error);
953 }
954 
955 static int
956 selscan(struct proc *p, fd_set *ibits, fd_set *obits, int nfd, int *retval)
957 {
958 	struct filedesc *fdp = p->p_fd;
959 	int which, i, j;
960 	fd_mask bits;
961 	int flag;
962 	struct file *fp;
963 	int error = 0, n = 0;
964 
965 	for (which = 0; which < 3; which++) {
966 		switch (which) {
967 
968 		case 0:
969 			flag = FREAD; break;
970 
971 		case 1:
972 			flag = FWRITE; break;
973 
974 		case 2:
975 			flag = 0; break;
976 		}
977 		for (i = 0; i < nfd; i += NFDBITS) {
978 			bits = ibits[which].fds_bits[i/NFDBITS];
979 			while ((j = ffs(bits)) && i + --j < nfd) {
980 				bits &= ~(1 << j);
981 				fp = fdp->fd_ofiles[i + j];
982 				if (fp == NULL) {
983 					error = EBADF;
984 					break;
985 				}
986 				if ((*fp->f_ops->fo_select)(fp, flag, p)) {
987 					FD_SET(i + j, &obits[which]);
988 					n++;
989 				}
990 			}
991 		}
992 	}
993 	*retval = n;
994 	return (error);
995 }
996 
997 /*ARGSUSED*/
998 int
999 seltrue(dev_t dev, int which, struct proc *p)
1000 {
1001 
1002 	return (1);
1003 }
1004 
1005 
1006 void
1007 selwakeup(pid_t pid, int coll)
1008 {
1009 	register struct proc *p;
1010 
1011 	if (coll) {
1012 		nselcoll++;
1013 		wakeup((caddr_t)&selwait);
1014 	}
1015 
1016 	if (pid && (p = pfind(pid))) {
1017 		int s = splhigh();
1018 
1019 		if (p->p_wchan == (caddr_t)&selwait) {
1020 			if (p->p_stat == SSLEEP)
1021 				setrun(p);
1022 			else
1023 				unsleep(p);
1024 		} else if (p->p_flag & SSEL)
1025 			p->p_flag &= ~SSEL;
1026 		splx(s);
1027 	}
1028 }
1029 
1030 /*
1031  * Allocate a file descriptor for the process.
1032  */
1033 int
1034 fdalloc(struct proc *p, int want, int *result)
1035 {
1036 	register struct filedesc *fdp = p->p_fd;
1037 	int i;
1038 	int lim, last, nfiles;
1039 	struct file **newofile;
1040 	char *newofileflags;
1041 
1042 	/*
1043 	 * Search for a free descriptor starting at the higher
1044 	 * of want or fd_freefile.  If that fails, consider
1045 	 * expanding the ofile array.
1046 	 */
1047 	lim = p->p_rlimit[RLIMIT_OFILE].rlim_cur;
1048 	for (;;) {
1049 		last = min(fdp->fd_nfiles, lim);
1050 		if ((i = want) < fdp->fd_freefile)
1051 			i = fdp->fd_freefile;
1052 		for (; i < last; i++) {
1053 			if (fdp->fd_ofiles[i] == NULL) {
1054 				fdp->fd_ofileflags[i] = 0;
1055 				if (i > fdp->fd_lastfile)
1056 					fdp->fd_lastfile = i;
1057 				if (want <= fdp->fd_freefile)
1058 					fdp->fd_freefile = i;
1059 				*result = i;
1060 				return (0);
1061 			}
1062 		}
1063 
1064 		/* no space in current array.  expand it? */
1065 		if (fdp->fd_nfiles >= lim)
1066 			return (EMFILE);
1067 		if (fdp->fd_nfiles < NDEXTENT)
1068 			nfiles = NDEXTENT;
1069 		else
1070 			nfiles = (2 * fdp->fd_nfiles) % lim;
1071 
1072 		MALLOC(newofile, struct file **, nfiles * OFILESIZE,
1073 		    M_FILEDESC, M_WAITOK);
1074 		newofileflags = (char *) &newofile[nfiles];
1075 
1076 		/*
1077 		 * Copy the existing ofile and ofileflags arrays
1078 		 * and zero the new portion of each array.
1079 		 */
1080 		(void) memcpy(newofile, fdp->fd_ofiles,
1081 			(i = sizeof(struct file *) * fdp->fd_nfiles));
1082 		(void) memset((char *)newofile + i, 0,
1083 			nfiles * sizeof(struct file *) - i);
1084 		(void) memcpy(newofileflags, fdp->fd_ofileflags,
1085 			(i = sizeof(char) * fdp->fd_nfiles));
1086 		(void) memset(newofileflags + i, 0, nfiles * sizeof(char) - i);
1087 
1088 		if (fdp->fd_nfiles > NDFILE)
1089 			FREE(fdp->fd_ofiles, M_FILEDESC);
1090 
1091 		fdp->fd_ofiles = newofile;
1092 		fdp->fd_ofileflags = newofileflags;
1093 		fdp->fd_nfiles = nfiles;
1094 	}
1095 }
1096 
1097 /*
1098  * Check to see whether n user file descriptors
1099  * are available to the process p.
1100  */
1101 int
1102 fdavail(struct proc *p, int n)
1103 {
1104 	struct filedesc *fdp = p->p_fd;
1105 	struct file **fpp;
1106 	int i;
1107 
1108 	if ((i = p->p_rlimit[RLIMIT_OFILE].rlim_cur - fdp->fd_nfiles) > 0 &&
1109 	    (n -= i) <= 0)
1110 		return (1);
1111 
1112 	fpp = &fdp->fd_ofiles[fdp->fd_freefile];
1113 	for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++)
1114 		if (*fpp == NULL && --n <= 0)
1115 			return (1);
1116 	return (0);
1117 }
1118 
1119 /*
1120  * Create a new open file structure and allocate
1121  * a file descriptor for the process that refers to it.
1122  */
1123 int
1124 falloc(struct proc *p, struct file **resultfp, int *resultfd)
1125 {
1126 	struct file *fp, *fq, **fpp;
1127 	int error, i;
1128 
1129 	if (error = fdalloc(p, 0, &i))
1130 		return (error);
1131 	if (nfiles >= maxfiles) {
1132 		tablefull("file");
1133 		return (ENFILE);
1134 	}
1135 
1136 	/*
1137 	 * Allocate a new file descriptor.
1138 	 * If the process has file descriptor zero open, add to the list
1139 	 * of open files at that point, otherwise put it at the front of
1140 	 * the list of open files.
1141 	 */
1142 	nfiles++;
1143 	MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
1144 	if (fq = p->p_fd->fd_ofiles[0])
1145 		fpp = &fq->f_filef;
1146 	else
1147 		fpp = &filehead;
1148 	p->p_fd->fd_ofiles[i] = fp;
1149 	if (fq = *fpp)
1150 		fq->f_fileb = &fp->f_filef;
1151 	fp->f_filef = fq;
1152 	fp->f_fileb = fpp;
1153 	*fpp = fp;
1154 
1155 	fp->f_count = 1;
1156 	fp->f_msgcount = 0;
1157 	fp->f_offset = 0;
1158 	fp->f_cred = p->p_ucred;
1159 	crhold(fp->f_cred);
1160 
1161 	if (resultfp)
1162 		*resultfp = fp;
1163 	if (resultfd)
1164 		*resultfd = i;
1165 	return (0);
1166 }
1167 
1168 /*
1169  * Free a file instance, recovering resources.
1170  */
1171 void
1172 ffree(struct file *fp)
1173 {
1174 	struct file *fq;
1175 
1176 	/* remove from global file list */
1177 	if (fq = fp->f_filef)
1178 		fq->f_fileb = fp->f_fileb;
1179 	*fp->f_fileb = fq;
1180 
1181 #ifdef DIAGNOSTIC
1182 	fp->f_filef = NULL;
1183 	fp->f_fileb = NULL;
1184 	fp->f_count = 0;
1185 #endif
1186 
1187 	crfree(fp->f_cred);
1188 	nfiles--;
1189 	FREE(fp, M_FILE);
1190 }
1191 
1192 /*
1193  * Copy a filedesc structure.
1194  */
1195 struct filedesc *
1196 fdcopy(struct proc *p)
1197 {
1198 	struct filedesc *newfdp, *fdp = p->p_fd;
1199 	struct file **fpp;
1200 	int i;
1201 
1202 	MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),
1203 	    M_FILEDESC, M_WAITOK);
1204 	(void) memcpy(newfdp, fdp, sizeof(struct filedesc));
1205 	newfdp->fd_refcnt = 1;
1206 
1207 	VREF(newfdp->fd_cdir);
1208 	if (newfdp->fd_rdir)
1209 		VREF(newfdp->fd_rdir);
1210 
1211 	/*
1212 	 * If the number of open files fits in the internal arrays
1213 	 * of the open file structure, use them, otherwise allocate
1214 	 * additional memory for the number of descriptors currently
1215 	 * in use.
1216 	 */
1217 	if (newfdp->fd_lastfile < NDFILE) {
1218 		newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
1219 		newfdp->fd_ofileflags =
1220 		    ((struct filedesc0 *) newfdp)->fd_dfileflags;
1221 		i = NDFILE;
1222 	} else {
1223 		/*
1224 		 * Compute the smallest multiple of NDEXTENT needed
1225 		 * for the file descriptors currently in use,
1226 		 * allowing the table to shrink.
1227 		 */
1228 		i = newfdp->fd_nfiles;
1229 		while (i > 2 * NDEXTENT && i >= newfdp->fd_lastfile * 2)
1230 			i /= 2;
1231 		MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE,
1232 		    M_FILEDESC, M_WAITOK);
1233 		newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
1234 	}
1235 
1236 	newfdp->fd_nfiles = i;
1237 	(void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles, i * sizeof(struct file **));
1238 	(void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags, i * sizeof(char));
1239 	fpp = newfdp->fd_ofiles;
1240 	for (i = newfdp->fd_lastfile; i-- >= 0; fpp++)
1241 		if (*fpp != NULL)
1242 			(*fpp)->f_count++;
1243 
1244 	return (newfdp);
1245 }
1246 
1247 /*
1248  * Release a filedesc structure.
1249  */
1250 void
1251 fdfree(struct proc *p)
1252 {
1253 	register struct filedesc *fdp = p->p_fd;
1254 	struct file **fpp;
1255 	char *fdfp;
1256 	register int i;
1257 
1258 	if (--fdp->fd_refcnt > 0)
1259 		return;
1260 
1261 	fpp = fdp->fd_ofiles;
1262 	fdfp = fdp->fd_ofileflags;
1263 	for (i = 0; i <= fdp->fd_lastfile; i++, fpp++, fdfp++)
1264 		if (*fpp != NULL) {
1265 			if (*fdfp & UF_MAPPED)
1266 				(void) munmapfd(p, i);
1267 			(void) closef(*fpp, p);
1268 		}
1269 
1270 	if (fdp->fd_nfiles > NDFILE)
1271 		FREE(fdp->fd_ofiles, M_FILEDESC);
1272 
1273 	vrele(fdp->fd_cdir);
1274 	if (fdp->fd_rdir)
1275 		vrele(fdp->fd_rdir);
1276 
1277 	FREE(fdp, M_FILEDESC);
1278 }
1279 
1280 /* Close any files on execve()? */
1281 void
1282 fdcloseexec(struct proc *p)
1283 {
1284 	struct filedesc *fdp = p->p_fd;
1285 	struct file **fpp;
1286 	char *fdfp;
1287 	register int i;
1288 
1289 	fpp = fdp->fd_ofiles;
1290 	fdfp = fdp->fd_ofileflags;
1291 	for (i = 0; i <= fdp->fd_lastfile; i++, fpp++, fdfp++)
1292 		if (*fpp != NULL && (*fdfp & UF_EXCLOSE)) {
1293 			if (*fdfp & UF_MAPPED)
1294 				(void) munmapfd(p, i);
1295 			(void) closef(*fpp, p);
1296 			*fpp = NULL;
1297 			*fdfp = 0;
1298 			if (i < fdp->fd_freefile)
1299 				fdp->fd_freefile = i;
1300 		}
1301 
1302 	while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
1303 		fdp->fd_lastfile--;
1304 }
1305 
1306 /*
1307  * Private file close function.
1308  * Decrement reference count on file structure.
1309  */
1310 int
1311 closef(struct file *fp, struct proc *p)
1312 {
1313 	struct vnode *vp;
1314 	struct flock lf;
1315 	int error;
1316 
1317 	if (fp == NULL)
1318 		return (0);
1319 	/*
1320 	 * POSIX record locking dictates that any close releases ALL
1321 	 * locks owned by this process.  This is handled by setting
1322 	 * a flag in the unlock to free ONLY locks obeying POSIX
1323 	 * semantics, and not to free BSD-style file locks.
1324 	 */
1325 	if ((p->p_flag & SADVLCK) && fp->f_type == DTYPE_VNODE) {
1326 		lf.l_whence = SEEK_SET;
1327 		lf.l_start = 0;
1328 		lf.l_len = 0;
1329 		lf.l_type = F_UNLCK;
1330 		vp = (struct vnode *)fp->f_data;
1331 		(void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
1332 	}
1333 	if (--fp->f_count > 0)
1334 		return (0);
1335 
1336 #ifdef	DIAGNOSTIC
1337 	if (fp->f_count < 0)
1338 		panic("closef: count < 0");
1339 #endif
1340 	if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
1341 		lf.l_whence = SEEK_SET;
1342 		lf.l_start = 0;
1343 		lf.l_len = 0;
1344 		lf.l_type = F_UNLCK;
1345 		vp = (struct vnode *)fp->f_data;
1346 		(void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
1347 	}
1348 
1349 	error = (*fp->f_ops->fo_close)(fp, p);
1350 	ffree(fp);
1351 	return (error);
1352 }
1353 
1354 /*
1355  * Apply an advisory lock on a file descriptor.
1356  *
1357  * Just attempt to get a record lock of the requested type on
1358  * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
1359  */
1360 
1361 /* ARGSUSED */
1362 int
1363 flock(p, uap, retval)
1364 	struct proc *p;
1365 	struct args {
1366 		int	fd;
1367 		int	how;
1368 	} *uap;
1369 	int *retval;
1370 {
1371 	register struct filedesc *fdp = p->p_fd;
1372 	register struct file *fp;
1373 	struct vnode *vp;
1374 	struct flock lf;
1375 	int error;
1376 
1377 	if ((unsigned)uap->fd >= fdp->fd_nfiles ||
1378 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
1379 		return (EBADF);
1380 	if (fp->f_type != DTYPE_VNODE)
1381 		return (EOPNOTSUPP);
1382 
1383 	vp = (struct vnode *)fp->f_data;
1384 	lf.l_whence = SEEK_SET;
1385 	lf.l_start = 0;
1386 	lf.l_len = 0;
1387 
1388 	if (uap->how & LOCK_UN) {
1389 		lf.l_type = F_UNLCK;
1390 		fp->f_flag &= ~FHASLOCK;
1391 		return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
1392 	}
1393 
1394 	if (uap->how & LOCK_EX)
1395 		lf.l_type = F_WRLCK;
1396 	else if (uap->how & LOCK_SH)
1397 		lf.l_type = F_RDLCK;
1398 	else
1399 		return (EBADF);
1400 
1401 	fp->f_flag |= FHASLOCK;
1402 	if (uap->how & LOCK_NB)
1403 		return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
1404 
1405 	return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
1406 }
1407 
1408 /*
1409  * File Descriptor pseudo-device driver (/dev/fd/).
1410  *
1411  * Opening minor device N dup()s the file (if any) connected to file
1412  * descriptor N belonging to the calling process.  Note that this driver
1413  * consists of only the ``open()'' routine, because all subsequent
1414  * references to this file will be directed to the other file.
1415  */
1416 /* ARGSUSED */
1417 static int
1418 fdopen(dev_t dev, int mode, int type, struct proc *p)
1419 {
1420 
1421 	/*
1422 	 * XXX Kludge: set curproc->p_dupfd to contain the value of the
1423 	 * the file descriptor being sought for duplication. The error
1424 	 * return ensures that the vnode for this device will be released
1425 	 * by vn_open. Open will detect this special error and take the
1426 	 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
1427 	 * will simply report the error.
1428 	 */
1429 	p->p_dupfd = minor(dev);		/* XXX */
1430 	return (ENODEV);
1431 }
1432 
1433 static struct devif fd_devif =
1434 {
1435 	{0}, -1, -2, 0, 0, 0, 0, 0, 0,
1436 	fdopen, 0, 0, 0, 0, 0, 0,
1437 	0, 0, 0, 0,
1438 	0,  0,
1439 };
1440 
1441 DRIVER_MODCONFIG() {
1442 	char *cfg_string = "fdesc 53.";
1443 
1444 	if (devif_config(&cfg_string, &fd_devif) == 0)
1445 		return;
1446 }
1447 
1448 /*
1449  * Duplicate the specified descriptor to a free descriptor.
1450  */
1451 int
1452 dupfdopen(struct filedesc *fdp, int indx, int dfd, int mode)
1453 {
1454 	register struct file *wfp;
1455 	struct file *fp;
1456 
1457 	/*
1458 	 * If the to-be-dup'd fd number is greater than the allowed number
1459 	 * of file descriptors, or the fd to be dup'd has already been
1460 	 * closed, reject.  Note, check for new == old is necessary as
1461 	 * falloc could allocate an already closed to-be-dup'd descriptor
1462 	 * as the new descriptor.
1463 	 */
1464 	fp = fdp->fd_ofiles[indx];
1465 	if ((u_int)dfd >= fdp->fd_nfiles ||
1466 	    (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp)
1467 		return (EBADF);
1468 
1469 	/*
1470 	 * Check that the mode the file is being opened for is a subset
1471 	 * of the mode of the existing descriptor.
1472 	 */
1473 	if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
1474 		return (EACCES);
1475 	fdp->fd_ofiles[indx] = wfp;
1476 	fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1477 	wfp->f_count++;
1478 	if (indx > fdp->fd_lastfile)
1479 		fdp->fd_lastfile = indx;
1480 	return (0);
1481 }
1482